summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-bar.mkiv227
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi537
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua697
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv512
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua1205
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv459
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv205
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv383
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-col.lua587
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-col.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-eff.lua134
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-eff.mkiv60
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua195
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv128
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-lay.lua307
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-lay.mkiv105
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-mkr.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-mkr.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-neg.lua104
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/attr-neg.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-exp.lua3706
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv292
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-ini.lua122
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv120
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua171
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv589
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv86
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/back-u3d.mkiv158
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bibl-bib.lua768
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv981
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bibl-tra.lua301
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv1511
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bibl-tst.lua21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/blob-ini.lua194
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/blob-ini.mkiv62
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.lua42
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv43
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.lua14
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.lua209
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.mkiv69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.lua119
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.mkiv76
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.lua80
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.lua101
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.mkiv70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.lua132
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.mkiv82
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.lua133
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.mkiv71
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua607
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv301
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-par.lua232
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-par.mkvi167
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua908
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv1004
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/bxml-apa.mkiv615
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-act.mkiv74
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-ctx.mkiv179
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-def.mkiv147
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-ini.lua45
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv354
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-sym.mkiv190
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/catc-xml.mkiv124
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv90
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-cjk.lua1293
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-def.lua227055
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-enc.lua193
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-enc.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-ent.lua2259
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-fio.lua94
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-ini.lua1357
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-map.lua1072
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-tex.lua822
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-utf.lua657
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-utf.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/chem-ini.lua62
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/chem-ini.mkiv53
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/chem-str.lua888
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv759
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua190
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-bas.mkiv19
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-com.lua38
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-com.mkiv19
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua1934
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv56
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua222
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-int.mkiv26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-prs.lua72
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua165
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-stp.lua69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua77
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-ver.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-ext.mkiv100
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-grp.mkiv168
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-icc.lua120
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv254
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-dem.mkiv275
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-ema.mkiv500
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-ral.mkiv239
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-rgb.mkiv337
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-x11.mkiv478
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-imp-xwi.mkiv146
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua1050
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv1268
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-run.lua74
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/colo-run.mkiv255
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-cs.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-de.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-en.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-fil.mkiv126
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-fr.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-gb.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-it.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv326
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv141
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-nl.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-nop.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-pe.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-ro.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-run.lua252
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-yes.mkiv99
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-base.lmx88
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-characters.lmx110
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-debug.lmx112
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-error.lmx59
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-fonttest.lmx47
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-help.lmx129
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-performance.tex66
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-timing.lmx52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context-todo.tex57
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context.css261
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context.lus71
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context.mkiv577
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-con.lua1357
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv859
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-ctx.ctx23
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua367
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-ctx.mkiv29
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-dat.lua315
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv101
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv170
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-env.lua274
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv847
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-ini.mkiv221
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-sys.lua90
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-sys.mkiv459
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-two.lua179
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv122
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-uti.lua438
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/core-uti.mkiv36
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-aux.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-bin.lua27
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-con.lua138
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-crl.lua61
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-ctx.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-env.lua307
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-exp.lua552
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-fil.lua113
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-gen.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-ini.lua360
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-inp.lua25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-lst.lua81
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-lua.lua134
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-met.lua141
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-out.lua18
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-pre.lua142
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-res.lua1885
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-sch.lua210
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-tex.lua193
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-tmf.lua73
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-tmp.lua448
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-tre.lua233
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-use.lua101
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-vir.lua85
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-zip.lua264
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/enco-ini.mkiv546
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/export-example.css864
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/export-example.rng377
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/export-example.tex118
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-ini.lua52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-ini.mkvi239
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-job.lua1225
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi331
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-lib.lua90
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-lib.mkvi20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-mod.lua242
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi293
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-res.lua172
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-res.mkvi153
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-syn.lua72
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/file-syn.mkvi66
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-afk.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-afm.lua1197
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-age.lua4115
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-agl.lua692
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-aux.lua241
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-aux.mkvi26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-cff.lua1698
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-chk.lua462
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-chk.mkiv29
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-cid.lua177
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-col.lua348
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi138
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-con.lua1454
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua2498
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-def.lua454
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua2200
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi237
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-enc.lua153
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-enh.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ext.lua1039
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua340
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi356
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi454
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua255
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-gds.lua917
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi91
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua349
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ini.lua32
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi2608
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-inj.lua1196
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ldr.lua70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi112
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-log.lua88
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-lua.lua46
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-map.lua517
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi511
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-mis.lua51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-mps.lua450
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-nod.lua550
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-odk.lua904
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-odv.lua2380
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-off.lua229
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-osd.lua2414
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ota.lua442
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otb.lua707
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otc.lua747
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otd.lua253
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otf.lua3057
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-oth.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-oti.lua158
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otj.lua1532
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otl.lua839
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otn.lua3960
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-oto.lua452
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otp.lua909
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-otr.lua2335
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ots.lua3765
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ott.lua1130
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-oup.lua2157
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-pat.lua92
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv772
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-run.mkiv403
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sel.lua770
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sel.mkvi429
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi164
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sol.lua956
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sol.mkvi129
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi412
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi250
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-syn.lua2090
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua201
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-tmp.lua118
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv290
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-trt.lua116
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua480
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-uni.mkiv27
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-unk.mkiv150
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi56
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-vf.lua206
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua97
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua34
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-epd.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-fig.mkiv391
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-fil.lua93
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua2119
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv797
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-raw.lua57
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-raw.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua185
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-rul.mkiv89
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua94
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv1238
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-u3d.lua51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-wnd.lua47
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/hand-ini.mkiv82
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv395
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv625
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv34
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-imp-stp.mkiv123
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-ini.lua268
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/java-ini.mkiv159
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-boolean.lua69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-dir.lua593
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-file.lua698
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-function.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-gzip.lua54
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-io.lua358
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-lpeg.lua1173
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-lua.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-math.lua38
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-md5.lua107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-number.lua207
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-os.lua558
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-package.lua362
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-pdfview.lua180
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua271
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-set.lua87
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-string.lua213
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-table.lua1265
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua1272
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-url.lua366
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-xml.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-def.lua466
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv713
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua231
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-frd.mkiv143
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-frq-de.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-frq-en.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-frq-nl.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-frq.mkiv235
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua1700
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv274
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua476
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv831
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-lab.lua171
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv385
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv697
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua336
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-rep.mkiv75
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv76
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua2804
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-url.lua167
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-url.mkiv172
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua413
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-wrd.mkiv70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/layo-ini.lua54
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/layo-ini.mkiv31
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua1271
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua735
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-enc.lua157
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua418
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua839
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua1423
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua842
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua295
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua1271
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua472
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-mov.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua183
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml176
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml49
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml202
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua386
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua40
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua304
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua617
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua487
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua682
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua279
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-bwc.lua32
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua386
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua214
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua184
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-cod.mkiv79
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-env.lua184
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-exe.lua73
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua134
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua157
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua28
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv283
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-iop.lua24
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv91
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-lua.lua45
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-mac.lua439
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-run.lua236
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-sta.lua211
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua187
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua192
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv126
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua1010
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua171
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-css.mkiv39
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.lua142
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.mkiv58
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-dir.lua117
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-ent.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua58
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-ini.lua143
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv517
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua1586
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-mis.lua103
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-sor.lua162
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-sor.mkiv97
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-tab.lua1790
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua2368
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lxml-xml.lua445
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/m-newcolumnsets.mkiv38
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/m-oldbibtex.mkiv16
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv77
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-acc.mkvi181
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-act.lua661
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv1287
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv462
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-def.mkiv158
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-del.mkiv121
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-dim.lua246
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-dir.lua172
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-dis.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ext.lua197
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua614
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv716
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-for.mkiv33
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-frc.lua57
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv618
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ini.lua712
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv2424
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-inl.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-int.mkiv141
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-map.lua805
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-mis.mkiv60
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-noa.lua1763
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv141
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-rad.mkvi290
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ren.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-scr.mkiv59
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi1293
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-tag.lua555
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-ttv.lua801
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua1107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-fig.mkiv69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua266
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-fnt.mkiv36
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-fun.lua57
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-fun.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-grd.mkiv116
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-clp.mkiv164
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv216
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-fen.mkiv173
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-grid.mkiv63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-mis.mkiv54
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-nav.mkiv65
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-outlines.mkiv176
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-pre.mkiv68
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-tab.mkiv73
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv337
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua137
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv1567
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-pag.mkiv121
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua583
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-pdf.mkiv94
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-pdh.lua610
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv773
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua208
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-tex.mkiv153
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/meta-xml.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/metatex.lus9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/metatex.tex165
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua375
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.mkiv83
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua153
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua392
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua722
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv184
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua1497
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv154
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua617
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-arrange.tex123
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-combine.tex116
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-common.tex43
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-copy.tex151
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-ideas.tex52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex138
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-markdown.tex92
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-precache.tex161
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-select.tex110
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-setups.tex78
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-sql.tex64
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-timing.tex48
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-trim.tex72
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex76
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-aux.lua168
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv1271
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-chk.lua93
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-chk.mkiv103
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-def.lua17725
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-def.mkiv46
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-dim.mkvi170
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua136
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua464
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv859
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-low.lua425
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-mes.lua1777
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-mps.lua162
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua1287
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv81
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv713
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-acc.lua178
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-aux.lua563
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-bck.lua194
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-dir.lua309
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ext.lua30
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-fin.lua641
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv79
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua514
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ini.lua356
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv61
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua3174
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-met.lua652
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-mig.lua165
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-mig.mkiv61
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-nut.lua759
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-pag.lua30
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-pag.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua474
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-pro.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ref.lua941
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-res.lua690
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-rul.lua536
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv423
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-ser.lua342
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-shp.lua241
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-snp.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-tex.lua40
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-tra.lua687
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua420
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-tst.lua136
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-typ.lua129
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/norm-ctx.mkiv87
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv92
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi262
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv1098
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv949
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv163
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-fen.mkiv97
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv749
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-mis.mkvi112
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv853
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua262
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv162
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-pos.mkiv164
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua231
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv3066
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-app.mkiv219
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv701
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi311
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-brk.mkiv562
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-col.mkiv179
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-com.mkiv178
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-cst.lua1454
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv778
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-fac.mkiv87
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-flt.lua383
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv317
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-flw.mkiv143
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-grd.mkiv106
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv1369
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv106
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv270
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-inj.lua125
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi217
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-ins.lua119
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-ins.mkiv186
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv1632
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-lin.lua521
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi576
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mak.mkvi269
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mbk.mkvi250
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mix.lua1090
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv959
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mrk.mkiv206
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv1824
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-not.mkiv71
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv624
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-otr.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi296
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-par.mkiv73
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-plg.mkiv215
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-pst.lua105
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-pst.mkiv104
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv310
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi405
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv2729
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv866
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv131
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-str.lua296
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv153
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi1000
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-var.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/phys-dim.lua969
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/phys-dim.mkiv810
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/prop-ini.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua876
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua1210
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-fnd.lua298
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.lua544
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi1523
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.lua479
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.mkvi1135
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-author.mkvi303
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi280
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-commands.mkvi15
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.lua124
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.mkvi507
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-definitions.mkvi123
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-list.mkvi96
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-page.mkvi51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-replacements.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-imp-test.bib294
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua3342
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv1855
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-jrn.lua189
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-old.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-oth.lua154
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-reg.lua227
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-sor.lua377
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-tra.lua504
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-tra.mkiv87
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-usr.lua128
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-usr.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/publ-xml.mkiv114
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-1.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-10.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-11.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-13.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-14.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-15.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-16.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-2.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-3.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-4.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-5.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-6.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-7.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-8.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-8859-9.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1250.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1251.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1252.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1253.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1254.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1255.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1256.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1257.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-cp1258.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-demo.lua22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-ini.lua436
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-ini.mkiv33
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/regi-pdfdoc.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi410
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-but.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi1036
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-fld.lua191
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi1038
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.lua157
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.mkvi167
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-ini.lua43
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi210
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-pag.lua56
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi308
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-ref.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi102
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-wid.lua345
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi721
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua1008
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua157
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua978
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv95
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/scrp-tha.lua57
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua796
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/sort-ini.mkiv19
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua926
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua149
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv1238
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua313
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv95
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-def.mkiv90
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv154
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv303
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-hor.lua44
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv1207
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv159
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv183
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv243
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua943
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-prf.mkvi117
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua2028
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv2373
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-files.pdfbin0 -> 9125 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-lua.pdfbin0 -> 267932 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-mkiv.lua6386
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-mkiv.tex328
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-bkm.lua516
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-bkm.mkiv188
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua162
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv100
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-con.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi1049
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv250
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-des.mkvi250
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua1135
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv32
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-enu.mkvi376
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi2310
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ind.mkiv131
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ini.lua405
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ini.mkvi89
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-itm.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi1790
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lab.mkiv198
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lev.lua75
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lev.mkvi96
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi369
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua1340
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi1603
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua731
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-mar.mkiv155
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-mat.lua53
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv1045
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-not.lua450
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi1933
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-num.lua718
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv826
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua401
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv492
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua2795
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi2296
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua1354
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv1043
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv789
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-rsc.lua185
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv148
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv1208
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-syn.lua318
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv666
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua516
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv523
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-xml.mkiv146
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-box.lua420
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv2945
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv317
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-ran.lua107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-ran.mkiv39
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/supp-vis.mkiv1873
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-cc.mkiv88
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-cow.mkiv130
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-eur.mkiv52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-jmn.mkiv196
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv77
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv263
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-imp-nav.mkiv129
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-ini.lua62
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv318
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv59
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua514
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv7462
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-con.lua68
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-con.mkiv137
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-fnt.mkiv52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv1159
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua180
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-mes.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/syst-pln.mkiv120
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv53
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv780
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-mis.mkiv289
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv2118
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-nte.mkiv110
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-pln.mkiv132
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv2273
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.lua52
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv2484
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv537
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-xnt.mkvi135
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua1273
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi810
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/task-ini.lua253
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/task-ini.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua281
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-map.lua70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-map.mkiv63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua447
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-tra.lua292
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-tra.mkiv31
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-ctx.lua70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-ctx.mkiv59
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua352
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-deb.mkiv43
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-exp.lua229
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-fil.lua181
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua209
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua115
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-jus.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-lmx.lua732
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-log.lua1031
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-par.lua144
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-pro.lua210
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-set.lua380
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-tex.lua118
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-tex.mkiv42
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-tim.lua138
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua1107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv240
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/trac-xml.lua183
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-def.mkiv48
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-fbk.mkiv70
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-ini.lua117
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi642
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-lua.mkiv86
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-one.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-otf.mkiv27
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv124
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-siz.mkiv169
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/type-tmf.mkiv14
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua385
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-bld.mkiv68
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua500
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-brk.mkiv99
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua487
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv292
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua251
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv82
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua110
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-cln.mkiv33
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv778
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua458
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua181
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dig.mkiv58
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua207
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv195
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua384
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv140
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua829
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua990
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua1025
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua309
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv112
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-ini.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-ini.mkiv49
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-inj.lua98
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-inj.mkiv80
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua590
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-itc.mkvi63
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-itm.mkiv273
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua638
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-krn.mkiv166
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-lan.lua74
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-lan.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-lig.mkiv31
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua471
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-lin.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-man.lua113
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua999
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv438
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua198
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-pag.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv29
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua129
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-prc.mkvi99
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua145
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-rep.mkiv51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv268
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua257
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-spa.mkiv81
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua311
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-sus.mkiv51
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua390
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-tal.mkiv177
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-txt.mkvi244
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua76
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/unic-ini.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/unic-ini.mkiv36
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-deb.lua132
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-dim.lua452
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-env.lua262
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-fil.lua167
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua76
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua158
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gm.lua69
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gs.lua212
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-lib.lua297
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-lua.lua160
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua228
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-pck.lua146
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-prs.lua725
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-ran.lua107
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sac.lua202
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sbx.lua415
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sci.lua288
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-seq.lua352
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-soc.lua97
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua284
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua289
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-swiglib.lua546
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-loggers.lua277
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-sessions.lua349
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-tickets.lua772
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-tracers.lua71
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua410
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql.lua457
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sta.lua352
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sto.lua174
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-str.lua1136
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-tab.lua837
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-tpl.lua213
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-you.lua256
921 files changed, 631905 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-bar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-bar.mkiv
new file mode 100644
index 00000000000..b5df21a0797
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-bar.mkiv
@@ -0,0 +1,227 @@
+%D \module
+%D [ file=anch-bar,
+%D version=2003.03.16,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Margin Bars and alike,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Margin Bars}
+
+\unprotect
+
+%D We will implement a sidebar mechanism using the
+%D functionality from \type {core-pos}.
+%D
+%D \starttyping
+%D \definesidebar[whow][rulecolor=green,distance=0pt]
+%D
+%D \input tufte \par
+%D \startsidebar
+%D \input tufte \par
+%D \input tufte \par
+%D \startsidebar[whow]
+%D \input tufte \par
+%D \input tufte \par
+%D \input tufte
+%D \stopsidebar \par
+%D \input tufte \par
+%D \input tufte
+%D \stopsidebar \par
+%D \input tufte \par
+%D \input tufte \par
+%D \startsidebar
+%D \input tufte \par
+%D \input tufte \par
+%D \input tufte \par
+%D \input tufte \par
+%D \input tufte
+%D \stopsidebar \par
+%D \input tufte \par
+%D \input tufte \par
+%D \startsidebar
+%D \input tufte
+%D \input tufte
+%D \input tufte
+%D \input tufte
+%D \input tufte
+%D \stopsidebar
+%D \stoptyping
+
+\installcorenamespace{sidebar}
+
+\installcommandhandler \??sidebar {sidebar} \??sidebar
+
+\newcount\c_anch_sidebars_n
+\newcount\c_anch_sidebars_current % local
+\newdimen\d_anch_sidebars_distance
+\newcount\c_anch_sidebars_level
+
+% \setupMPvariables
+% [mpos:sidebar]
+% [linecolor=red,
+% linewidth=2pt,
+% distance=5pt]
+
+\setupsidebar
+ [\c!rulethickness=\dimexpr\bodyfontsize/6\relax, % 2pt default
+ \c!rulecolor=\s!black,
+ \c!alternative=0,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!distance=.5\bodyfontsize,
+ \c!level=,
+ \c!leftmargindistance=\zeropoint]
+
+\let\setupsidebars\setupsidebar
+
+\unexpanded\def\startsidebar
+ {\dodoubleempty\anch_sidebars_start}
+
+\def\anch_sidebars_start[#1][#2]%
+ {\bgroup
+ \dontleavehmode
+ \advance\c_anch_sidebars_level\plusone
+ \global\advance\c_anch_sidebars_n\plusone
+ \c_anch_sidebars_current\c_anch_sidebars_n\relax % relax needed
+ \doifelseassignment{#1}
+ {\edef\currentsidebar{\the\c_anch_sidebars_level}%
+ \checksidebarparent
+ \setupcurrentsidebar[#1]}
+ {\def\currentsidebar{#1}%
+ \setupcurrentsidebar[#2]}%
+ \scratchdistance\sidebarparameter\c!distance\relax
+ \edef\m_level{\sidebarparameter\c!level}%
+ \ifx\m_level\empty
+ \ifnum\c_anch_sidebars_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \fi
+ \else
+ \ifnum\m_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \d_anch_sidebars_distance\dimexpr\scratchdimen+\numexpr\m_level-\plusone\relax\dimexpr\scratchdistance\relax\relax
+ \fi
+ \fi
+ \startpositionoverlay{\v!text-1}%
+ \normalexpanded{\setMPpositiongraphicrange % maybe expand in definition
+ {b:sidebar:\the\c_anch_sidebars_n}%
+ {e:sidebar:\the\c_anch_sidebars_n}%
+ {mpos:sidebar}%
+ {self=sidebar:\the\c_anch_sidebars_n,
+ linewidth=\sidebarparameter\c!rulethickness,
+ linecolor=\sidebarparameter\c!rulecolor,
+ alternative=\sidebarparameter\c!alternative,
+ topoffset=\the\dimexpr\sidebarparameter\c!topoffset,
+ bottomoffset=\the\dimexpr\sidebarparameter\c!bottomoffset,
+ distance=\the\d_anch_sidebars_distance}%
+ }%
+ \stoppositionoverlay
+ \bpos{sidebar:\the\c_anch_sidebars_current}%
+ \ignorespaces}
+
+\unexpanded\def\stopsidebar
+ {\removelastspace
+ \epos{sidebar:\the\c_anch_sidebars_current}
+ \carryoverpar\egroup}
+
+%D Let's keep this nice and simple (okay, we could pass the 6 variables in
+%D one lua call).
+
+\startMPpositionmethod{mpos:sidebar}
+ \startMPpositiongraphic{mpos:sidebar}{linecolor,linewidth,distance,alternative}%
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ anch_sidebars_draw (
+ \MPp\MPbself,\MPp\MPeself,\MPy\MPbself,\MPy\MPeself,\MPh\MPbself,\MPd\MPeself,
+ \MPx{\textanchor},\MPy{\textanchor},\MPw{\textanchor},\MPh{\textanchor},
+ \MPvar{alternative},\MPvar{distance},\MPvar{linewidth},\MPvar{linecolor},
+ \MPvar{topoffset}, \MPvar{bottomoffset}
+ ) ;
+ \stopMPpositiongraphic
+ \MPpositiongraphic{mpos:sidebar}{}%
+\stopMPpositionmethod
+
+%D We now reimplement the \MKII\ margin rules handler in a more
+%D modern way.
+%D
+%D \setupmarginrules
+%D [rulecolor=darkred,
+%D rulethickness=2pt]
+%D
+%D \setupmarginrules % sidebar
+%D [2]
+%D [rulecolor=darkblue]
+%D
+%D \startmarginrule[1]
+%D \input ward
+%D \startmarginrule[2]
+%D \input ward
+%D \startmarginrule[3]
+%D \input ward
+%D \startmarginrule[level=6,rulecolor=darkgreen]
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D
+%D Compared to the old mechanism we now can pass settings too.
+
+\definesidebar
+ [\v!margin]
+ [\c!leftmargindistance=\dimexpr\leftmargindistance+\sidebarparameter\c!rulethickness/2\relax]
+
+\dorecurse{5}{\definesidebar[\v!margin:#1][\v!margin]} % let's be nice and predefine 5 levels
+
+\unexpanded\def\setupmarginrule
+ {\dodoubleargument\anch_marginrules_setup}
+
+\def\anch_marginrules_setup[#1][#2]%
+ {\ifsecondargument
+ \setupsidebar[\v!margin:#1][#2]%
+ \else
+ \setupsidebar[\v!margin][#1]%
+ \fi}
+
+\let\setupmarginrules\setupmarginrule
+
+\unexpanded\def\startmarginrule
+ {\dosingleempty\anch_marginrules_start}
+
+\def\anch_marginrules_start[#1]% pretty inefficient checking
+ {\edef\m_anch_marginrules_kind{#1}%
+ \ifx\m_anch_marginrules_kind\empty
+ \anch_sidebars_start[\v!margin][]%
+ \else
+ \doifelseassignment\m_anch_marginrules_kind
+ {\anch_sidebars_start[\v!margin][#1]}%
+ {\anch_marginrules_check{#1}%
+ \anch_sidebars_start[\v!margin:#1][\c!level=#1]}%
+ \fi}
+
+\def\anch_marginrules_check#1%
+ {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}}
+
+\let\stopmarginrule\stopsidebar
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi b/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi
new file mode 100644
index 00000000000..ee392f11474
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi
@@ -0,0 +1,537 @@
+%D \module
+%D [ file=anch-bck, % moved from anch-pgr (1999.08.01)
+%D version=2011.12.19,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Backgrounds}
+
+%D This module is quite okay but at some point I might add methods
+%D that use attributes although not too much is to be expected,
+%D apart from better anchoring. In fact better anchoring can be
+%D done independent of that.
+
+\unprotect
+
+% This might be overloaded later on:
+
+% \defineoverlay[\v!text-2][\positionoverlay{\v!text-2}]
+% \defineoverlay[\v!text-1][\positionoverlay{\v!text-1}]
+% \defineoverlay[\v!text+1][\positionoverlay{\v!text+1}]
+% \defineoverlay[\v!text+2][\positionoverlay{\v!text+2}]
+
+% Paragraph positions:
+
+\newcount\c_anch_backgrounds_text_n
+
+\def\v_anch_backgrounds_text_current {tbg:0}
+\def\v_anch_backgrounds_anchor_current_b{b:\v_anch_backgrounds_text_current}
+\def\v_anch_backgrounds_anchor_current_e{e:\v_anch_backgrounds_text_current}
+
+\def\anch_backgrounds_text_initialize_next
+ {\global\advance\c_anch_backgrounds_text_n\plusone
+ \edef\v_anch_backgrounds_text_current{tbg:\number\c_anch_backgrounds_text_n}}
+
+% The first position can be used in the middle of a paragraph in which case we're
+% too late with initializing par positions. Therefore we check if positions are
+% used at all.
+%
+% tricky: we need to catch newly set! otherwise an old run can have positions
+
+\unexpanded\def\anch_backgrounds_text_initialize
+ {\doifelsepositionsused\enableparpositions\donothing
+ \global\let\anch_backgrounds_text_initialize\relax}
+
+\appendtoks
+ \anch_backgrounds_text_initialize
+\to \everystarttext
+
+%D Some MP
+
+\newcount\MPparcounter
+
+\def\MPself {\MPvar{self}}
+\def\MPbself {b:\MPvar{self}}
+\def\MPeself {e:\MPvar{self}}
+\def\MPparanchor{p:\number\MPparcounter}
+
+% \carryoverpar is needed for left/right floats
+
+% \definetextbackground[more][state=start,backgroundcolor=red] % location=paragraph
+% \definetextbackground[test][state=start,backgroundcolor=green]
+%
+% \page \placefigure[left]{}{}
+%
+% \starttextbackground[test]
+% \readfile{ward}{}{}
+% \starttextbackground[more]
+% \readfile{ward}{}{}
+% \stoptextbackground
+% \readfile{ward}{}{}
+% \stoptextbackground
+%
+% \page \placefigure[right]{}{}
+%
+% \starttextbackground[test]
+% \readfile{ward}{}{}
+% \starttextbackground[more]
+% \readfile{ward}{}{}
+% \stoptextbackground
+% \readfile{ward}{}{}
+% \stoptextbackground
+
+\newcount\c_anch_backgrounds_text_level
+
+\installcorenamespace{textbackground}
+\installcorenamespace{textbackgroundlevel}
+
+\installcommandhandler \??textbackground {textbackground} \??textbackground
+
+\appendtoks
+ \setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}%
+ \setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}%
+ \setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}%
+% \doif{\textbackgroundparameter\c!state}\v!start\checkpositionoverlays
+\to \everydefinetextbackground
+
+% \appendtoks
+% \doif{\textbackgroundparameter\c!state}\v!start\checkpositionoverlays
+% \to \everysetuptextbackground
+
+\unexpanded\def\starttextbackground
+ {\begingroup
+ \advance\c_anch_backgrounds_text_level\plusone
+ \dodoubleempty\anch_backgrounds_text_start}
+
+\def\anch_backgrounds_text_start[#tag][#settings]%
+ {%\checkpositionoverlays
+ \def\currenttextbackground{#tag}%
+ \anch_backgrounds_text_initialize_next
+ \ifsecondargument
+ \setupcurrenttextbackground[#settings]%
+ \fi
+ \doifelse{\textbackgroundparameter\c!state}\v!start
+ \anch_backgrounds_text_preset_yes
+ \anch_backgrounds_text_preset_nop
+ \anch_backgrounds_text_start_indeed}
+
+% todo \backgroundvariable\c!variant
+
+\let\anch_backgrounds_text_start_indeed\relax
+\let\anch_backgrounds_text_stop_indeed \relax
+
+\setvalue{\??textbackgroundlevel\v!text}%
+ {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt}
+
+\setvalue{\??textbackgroundlevel\v!paragraph}%
+ {\ifnum\c_anch_backgrounds_text_level>\plusone
+ \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt
+ \else
+ \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par
+ \fi}
+
+\setvalue{\??textbackgroundlevel\v!none}%
+ {\anch_backgrounds_text_preset_nop}
+
+\def\anch_backgrounds_text_preset_nop
+ {\let\anch_backgrounds_text_start_indeed\relax
+ \let\anch_backgrounds_text_stop_indeed \relax}
+
+\def\anch_backgrounds_text_preset_yes
+ {\anch_backgrounds_text_preset_nop
+ \csname\??textbackgroundlevel\textbackgroundparameter\c!location\endcsname
+ \edef\p_anch_backgrounds_text_frame {\textbackgroundparameter\c!frame}%
+ \edef\p_anch_backgrounds_text_corner {\textbackgroundparameter\c!corner}%
+ \edef\p_anch_backgrounds_text_background{\textbackgroundparameter\c!background}%
+ \ifx\p_anch_backgrounds_text_frame\v!on
+ \ifx\p_anch_backgrounds_text_corner\v!round
+ \let\p_anch_backgrounds_text_frame\!!plustwo
+ \else
+ \let\p_anch_backgrounds_text_frame\!!plusone
+ \fi
+ \else
+ \let\p_anch_backgrounds_text_frame\!!zerocount
+ \fi
+ \ifx\p_anch_backgrounds_text_background\v!color
+ \let\p_anch_backgrounds_text_background\!!plusone
+ \else
+ \let\p_anch_backgrounds_text_background\!!zerocount
+ \fi
+ \startpositionoverlay{\textbackgroundoverlay{\textbackgroundparameter\c!level}}%
+ \anch_backgrounds_text_meta_graphic % gets expanded directly
+ \stoppositionoverlay}
+
+\def\anch_backgrounds_text_meta_graphic
+ {\normalexpanded
+ {\setMPpositiongraphicrange % needs to be optimized
+ {\v_anch_backgrounds_anchor_current_b}%
+ {\v_anch_backgrounds_anchor_current_e}%
+ {\textbackgroundparameter\c!method}%
+ {self=\v_anch_backgrounds_text_current,
+ mp=\textbackgroundparameter\c!mp,
+ gridtype=\textbackgroundparameter\c!alternative,
+ filltype=\p_anch_backgrounds_text_background,
+ linetype=\p_anch_backgrounds_text_frame,
+ dashtype=\textbackgroundparameter\c!dash,
+ gridcolor=\textbackgroundparameter\c!framecolor,
+ linecolor=\textbackgroundparameter\c!framecolor,
+ lineoffset=\textbackgroundparameter\c!frameoffset,
+ fillcolor=\textbackgroundparameter\c!backgroundcolor,
+ filloffset=\textbackgroundparameter\c!backgroundoffset,
+ gridwidth=\textbackgroundparameter\c!rulethickness,
+ gridshift=\textbackgroundparameter\c!voffset,
+ linewidth=\textbackgroundparameter\c!rulethickness,
+ lineradius=\textbackgroundparameter\c!radius}}}
+
+\unexpanded\def\stoptextbackground
+ {\anch_backgrounds_text_stop_indeed
+ \carryoverpar\endgroup} % why doesn't this work ?
+
+\unexpanded\def\starttextbackgroundmanual
+ {\begingroup
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \bpos\v_anch_backgrounds_text_current}
+
+\unexpanded\def\stoptextbackgroundmanual
+ {\epos\v_anch_backgrounds_text_current
+ \carryoverpar\endgroup}
+
+\def\anch_backgrounds_text_start_txt
+ {\ifvmode \dontleavehmode \fi
+ \begingroup
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \bpos\v_anch_backgrounds_text_current}
+
+\def\anch_backgrounds_text_stop_txt
+ {\epos\v_anch_backgrounds_text_current
+ \carryoverpar\endgroup}
+
+\newskip\textbackgroundskip
+
+\def\anch_backgrounds_text_start_par
+ {\endgraf % new
+ \textbackgroundparameter\c!before
+ \begingroup
+ \begingroup
+ \resetallattributes % \attribute\linenumberattribute \attributeunsetvalue
+ \noindent
+ \ifgridsnapping
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}%
+ \ifdim\textbackgroundskip>\zeropoint
+ \struttedbox{\hbox{\raise\textbackgroundskip\hbox{\bpos\v_anch_backgrounds_text_current}}}%
+ \else
+ \bpos\v_anch_backgrounds_text_current
+ \fi
+ \else
+ \bpos\v_anch_backgrounds_text_current
+ \fi
+ \endgraf % we need a vertical nobreak - 29/06/2004
+ \endgroup
+ \nobreak
+ \vskip-\lineheight
+ \nobreak
+ \ifgridsnapping \else
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}%
+ \ifdim\textbackgroundskip>\zeropoint
+ \kern\textbackgroundskip\nobreak
+ \fi
+ \fi
+ \dosetleftskipadaption{\textbackgroundparameter\c!leftoffset}%
+ \advance\leftskip\leftskipadaption
+ \dosetleftskipadaption{\textbackgroundparameter\c!rightoffset}%
+ \advance\rightskip\leftskipadaption
+ % new
+ \dosetraggedcommand{\textbackgroundparameter\c!align}%
+ \raggedcommand
+ %
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \nowhitespace
+ \seteffectivehsize
+ \doinhibitblank % \blank[\v!disable]% new
+ \par}
+
+\def\anch_backgrounds_text_stop_par
+ {\par
+ \removelastskip % new
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}%
+ \ifdim\lastskip>\zeropoint
+ \advance\textbackgroundskip-\lastskip
+ \fi
+ \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint
+ \kern\textbackgroundskip\nobreak
+ \fi \fi
+ \nobreak
+ \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent
+ \nobreak
+ \endgroup
+ \begingroup
+ \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM
+ \resetallattributes % \attribute\linenumberattribute \attributeunsetvalue
+ \nobreak \noindent \strut \hfill \kern\zeropoint
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}%
+ \ifgridsnapping % experimental, pascal (todo: topoffset in same way)
+ \ifdim\textbackgroundskip>\zeropoint
+ \struttedbox\plusone{\hbox{\lower\textbackgroundskip\hbox{\epos\v_anch_backgrounds_text_current}}}%
+ \else
+ \epos\v_anch_backgrounds_text_current
+ \fi
+ \else
+ \epos\v_anch_backgrounds_text_current
+ \fi
+ \endgraf
+ \carryoverpar\endgroup
+ \endgraf % new
+ \textbackgroundparameter\c!after}
+
+\unexpanded\def\checkpositionoverlays % overloads \relax in anch-pgr
+ {\ifproductionrun
+ \enabletextarearegistration
+ \enablehiddenbackground
+ \global\let\checkpositionoverlays\relax
+ \fi}
+
+\setuptextbackground
+ [\c!mp=mpos:region:draw,
+ \c!method=mpos:region, % mpos:regionshape
+ \c!state=\v!start,
+ \c!location=\v!text,
+ \c!leftoffset=\!!zeropoint, % 1em,
+ \c!rightoffset=\textbackgroundparameter\c!leftoffset,
+ \c!topoffset=\!!zeropoint, % \v!medium,
+ \c!bottomoffset=\textbackgroundparameter\c!topoffset,
+ \c!level=-1,
+ \c!alternative=0,
+ \c!align=,
+ \c!dash=0, % to be internationalized
+ \c!background=\v!color,
+ \c!backgroundcolor=lightgray,
+ \c!backgroundoffset=\!!zeropoint,
+ \c!corner=\v!rectangular,
+ \c!radius=.5\bodyfontsize,
+ \c!voffset=\!!zeropoint,
+ \c!frame=\v!on,
+ \c!framecolor=blue,
+ \c!frameoffset=\!!zeropoint,
+ \c!rulethickness=\linewidth]
+
+%D The \METAPOST\ connection:
+
+% gridtype = 1 => baseline
+% gridtype = 2 => betweenline
+
+\setupMPvariables
+ [mpos:region]
+ [mp=mpos:region:unset,
+ gridtype=0,
+ linetype=1,
+ filltype=1,
+ dashtype=0, % 1 = dashed, 2 = dashed with background
+ gridcolor=red,
+ linecolor=blue,
+ fillcolor=lightgray,
+ filloffset=\!!zeropoint,
+ linewidth=\linewidth,
+ gridwidth=\linewidth,
+ gridshift=\!!zeropoint,
+ lineradius=.5\bodyfontsize,
+ lineoffset=\!!zeropoint,
+ dashtype=1]
+
+\startuseMPgraphic{mpos:region:setup}
+ if unknown context_abck : input mp-abck.mpiv ; fi ;
+ boxgridtype := \MPvar{gridtype} ;
+ boxlinetype := \MPvar{linetype} ;
+ boxfilltype := \MPvar{filltype} ;
+ boxdashtype := \MPvar{dashtype} ;
+ boxfilloffset := \MPvar{filloffset} ;
+ boxlinewidth := \MPvar{linewidth} ;
+ boxgridwidth := \MPvar{gridwidth} ;
+ boxgridshift := \MPvar{gridshift} ;
+ boxlineradius := \MPvar{lineradius} ;
+ boxlineoffset := \MPvar{lineoffset} ;
+ %
+ def boxgridoptions = withcolor \MPvar{gridcolor} enddef ;
+ def boxlineoptions = withcolor \MPvar{linecolor} enddef ;
+ def boxfilloptions = withcolor \MPvar{fillcolor} enddef ;
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:extra}
+ % user stuff
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:anchor}
+ setbounds currentpicture to multibox ;
+\stopuseMPgraphic
+
+% \startMPpositionmethod{mpos:region}
+% \startMPpositiongraphic{mpos:region}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+% \includeMPgraphic{mpos:region:setup} ;
+% \includeMPgraphic{mpos:region:extra} ;
+% \MPgetmultipars{\MPvar{self}}{\MPanchorid} ;
+% \includeMPgraphic{\MPvar{mp}} ;
+% \includeMPgraphic{mpos:region:anchor} ;
+% \stopMPpositiongraphic
+% \MPpositiongraphic{mpos:region}{}%
+% \stopMPpositionmethod
+
+\startMPpositiongraphic{mpos:region}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+ \includeMPgraphic{mpos:region:setup} ;
+ \includeMPgraphic{mpos:region:extra} ;
+ \MPgetmultipars{\MPvar{self}}{\MPanchorid} ;
+ \includeMPgraphic{\MPvar{mp}} ;
+ \includeMPgraphic{mpos:region:anchor} ;
+\stopMPpositiongraphic
+
+\startMPpositiongraphic{mpos:regionshape}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+ \includeMPgraphic{mpos:region:setup} ;
+ \includeMPgraphic{mpos:region:extra} ;
+ \MPgetmultishapes{\MPvar{self}}{\MPanchorid} ;
+ \includeMPgraphic{\MPvar{mp}} ;
+ \includeMPgraphic{mpos:region:anchor} ;
+\stopMPpositiongraphic
+
+\startMPpositionmethod{mpos:region}
+ \MPpositiongraphic{mpos:region}{}%
+\stopMPpositionmethod
+
+\startuseMPgraphic{mpos:region:draw}
+ draw_multi_pars
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:show}
+ show_multi_pars
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:kind}
+ show_multi_kind
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:sideline}
+ draw_multi_side
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:sideline:dashed}
+ draw_multi_side_path dashed evenly ;
+\stopuseMPgraphic
+
+%D As an example we define a grid background:
+
+\definetextbackground
+ [\v!grid]
+ [\c!state=\v!stop,
+ \c!location=\v!paragraph,
+ \c!frame=\v!off,
+ \c!framecolor=red,
+ \c!background=,
+ \c!alternative=1]
+
+\ifx\basegrid\undefined \else \letvalue\v!grid=\basegrid \fi
+
+%D Some examples (that might become modules anch-imp-whatever):
+
+\setupMPvariables
+ [mpos:encircle]
+ [fillcolor=lightgray,
+ filloffset=\!!zeropoint,
+ linecolor=blue,
+ lineoffset=5pt,
+ linewidth=1pt]
+
+\startMPpositiongraphic{mpos:encircle}{linecolor,fillcolor,linewidth,lineoffset}
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ \MPgetposboxes{\MPvar{self}}{\MPanchorid}
+ if nofposboxes = 1 :
+ posboxes[1] := posboxes[1] enlarged \MPvar{lineoffset} cornered \MPvar{lineoffset} ;
+ fill posboxes[1] withcolor \MPvar{fillcolor} ;
+ draw posboxes[1] withpen pencircle scaled \MPvar{linewidth} withcolor \MPvar{linecolor} ;
+ fi ;
+\stopMPpositiongraphic
+
+\setupMPvariables
+ [mpos:connect]
+ [linecolor=red,
+ lineoffset=.25ex,
+ linewidth=1pt]
+
+\startMPpositiongraphic{mpos:connect}{linecolor,lineoffset,linewidth}
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ boxlinewidth := \MPvar{linewidth} ;
+ boxlineoffset := \MPvar{lineoffset} ;
+ def boxlineoptions = withcolor \MPvar{linecolor} enddef ;
+ \MPgetposboxes{\MPvar{from},\MPvar{to}}{\MPanchorid}
+ connect_positions ;
+\stopMPpositiongraphic
+
+\protect \endinput
+
+\definetextbackground[underline] [location=text,alternative=1,background=,frame=off]
+\definetextbackground[overstrike] [location=text,alternative=2,background=,frame=off]
+\definetextbackground[exlines] [location=text,alternative=3,background=,frame=off]
+\definetextbackground[strikethrough][location=text,alternative=4,background=,frame=off]
+
+\definestartstop [underline]
+ [before={\starttextbackground[underline]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [overstrike]
+ [before={\starttextbackground[overstrike]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [exlines]
+ [before={\starttextbackground[exlines]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [strikethrough]
+ [before={\starttextbackground[strikethrough]},
+ after=\stoptextbackground]
+
+\definetextbackground
+ [sideline]
+ [mp=mpos:region:sideline,
+ location=paragraph,
+ framecolor=red,
+ frameoffset=5mm]
+
+\definestartstop [sideline]
+ [before={\starttextbackground[sideline]},
+ after=\stoptextbackground]
+
+\starttext
+
+ \startunderline \input tufte \stopunderline \blank
+ \startoverstrike \input tufte \stopoverstrike \blank
+ \startexlines \input tufte \stopexlines \blank
+ \startstrikethrough \input tufte \stopstrikethrough \blank
+ \startsideline \input tufte \stopsideline \blank
+
+ \page
+
+ \startpositionoverlay{text-1}
+ \setMPpositiongraphic{connect-1-b}{mpos:connect}{from=connect-1-b,to=connect-1-e}
+ \setMPpositiongraphic{connect-1-e}{mpos:connect}{from=connect-1-b,to=connect-1-e}
+ \stoppositionoverlay
+
+ \startpositionoverlay{text-1}
+ \setMPpositiongraphic{encircle-1}{mpos:encircle}{self=encircle-1}
+ \stoppositionoverlay
+
+ test \hpos{connect-1-b}{START}
+ \dorecurse{10}{\input ward}
+ \hpos{encircle-1}{\strut HERE}
+ \dorecurse{10}{\input ward}
+ \hpos{connect-1-e}{STOP} test
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua
new file mode 100644
index 00000000000..b5c2ae6280a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua
@@ -0,0 +1,697 @@
+if not modules then modules = { } end modules ['anch-pgr'] = {
+ version = 1.001,
+ comment = "companion to anch-pgr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: we need to clean up lists (of previous pages)
+
+local format = string.format
+local abs = math.abs
+local concat, sort = table.concat, table.sort
+local splitter = lpeg.splitat(":")
+local lpegmatch = lpeg.match
+
+local jobpositions = job.positions
+local formatters = string.formatters
+
+local commands = commands
+local context = context
+
+local implement = interfaces.implement
+
+local report_graphics = logs.reporter("graphics")
+
+local f_b_tag = formatters["b:%s"]
+local f_e_tag = formatters["e:%s"]
+local f_p_tag = formatters["p:%s"]
+
+local f_tag_two = formatters["%s:%s"]
+
+local f_point = formatters["%p"]
+local f_pair = formatters["(%p,%p)"]
+local f_path = formatters["%--t--cycle"]
+
+local function regionarea(r)
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ return {
+ f_pair(rx, rh - ry),
+ f_pair(rw, rh - ry),
+ f_pair(rw, rd - ry),
+ f_pair(rx, rd - ry),
+ }
+end
+
+-- we can use a 'local t, n' and reuse the table
+
+local eps = 2
+
+local function add(t,x,y,last,direction)
+ local n = #t
+ if n == 0 then
+ t[n+1] = { x, y }
+ else
+ local tn = t[n]
+ local lx = tn[1]
+ local ly = tn[2]
+ if x == lx and y == ly then
+ -- quick skip
+ elseif n == 1 then
+ -- if abs(lx-x) <= eps or abs(ly-y) <= eps then
+ if abs(lx-x) > eps or abs(ly-y) > eps then
+ t[n+1] = { x, y }
+ end
+ else
+ local tm = t[n-1]
+ local px = tm[1]
+ local py = tm[2]
+ if (direction == "down" and y > ly) or (direction == "up" and y < ly) then
+ -- move back from too much hang
+ elseif abs(lx-px) <= eps and abs(lx-x) <= eps then
+ if abs(ly-y) > eps then
+ tn[2] = y
+ end
+ elseif abs(ly-py) <= eps and abs(ly-y) <= eps then
+ if abs(lx-x) > eps then
+ tn[1] = x
+ end
+ elseif not last then
+ t[n+1] = { x, y }
+ end
+ end
+ end
+end
+
+-- local function add(t,x,y,last)
+-- t[#t+1] = { x, y }
+-- end
+
+local function finish(t)
+ local n = #t
+ if n > 1 then
+ local first = t[1]
+ local last = t[n]
+ if abs(first[1]-last[1]) <= eps and abs(first[2]-last[2]) <= eps then
+ t[n] = nil
+ end
+ end
+end
+
+local function clip(t,ytop,ybot)
+ local first, last = 1, #t
+ for i=first,last do
+ local y = t[i][2]
+ if ytop < y then
+ first = i
+ end
+ if ybot > y then
+ last = i
+ break
+ end
+ end
+ local lp = { }
+ lp[#lp+1] = { t[first][1], ytop }
+ for i=first+1,last-1 do
+ lp[#lp+1] = { t[i][1], t[i][2] }
+ end
+ lp[#lp+1] = { t[last][1], ybot }
+ return lp
+end
+
+-- todo: mark regions and free paragraphs in collected
+
+local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
+ -- we assume that we only hang per page and not cross pages
+ -- which makes sense as hanging is only uses in special cases
+ --
+ -- we can remove data as soon as a page is done so we could
+ -- remember per page and discard areas after each shipout
+ local leftshape, rightshape
+ leftshape = { { rx, rh } } -- spikes get removed so we can start at the edge
+ rightshape = { { rw, rh } } -- even if we hang next
+ local paragraphs = r.paragraphs
+ local extending = false
+ if paragraphs then
+ for i=1,#paragraphs do
+ local p = paragraphs[i]
+ local ha = p.ha
+ if obeyhang and ha and ha ~= 0 then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local hi = p.hi
+ local hang = ha * (ph + pd)
+ local py_ph = py + ph
+ -- ha < 0 hi < 0 : right top
+ -- ha < 0 hi > 0 : left top
+ if ha < 0 then
+ if hi < 0 then -- right
+ add(rightshape,rw, py_ph,"up")
+ add(rightshape,rw + hi,py_ph,"up")
+ add(rightshape,rw + hi,py_ph + hang,"up")
+ add(rightshape,rw, py_ph + hang,"up")
+ else
+ -- left
+ add(leftshape,rx,py_ph,"down")
+ add(leftshape,rx + hi,py_ph,"down")
+ add(leftshape,rx + hi,py_ph + hang,"down")
+ add(leftshape,rx,py_ph + hang,"down")
+ end
+ else
+ -- maybe some day
+ end
+ extending = true -- false
+ else -- we need to clip to the next par
+ local ps = p.ps
+ if ps then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local step = ph + pd
+ local size = #ps * step
+ local py_ph = py + ph
+ add(leftshape,rx,py_ph,"up")
+ add(rightshape,rw,py_ph,"down")
+ for i=1,#ps do
+ local p = ps[i]
+ local l = p[1]
+ local w = p[2]
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
+ py_ph = py_ph - step
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
+ end
+ extending = true
+ elseif extending then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local py_ph = py + ph
+ local py_pd = py - pd
+ add(leftshape,leftshape[#leftshape][1],py_ph,"up")
+ add(rightshape,rightshape[#rightshape][1],py_ph,"down")
+ add(leftshape,rx,py_ph,"up") -- shouldn't this be py_pd
+ add(rightshape,rw,py_ph,"down") -- shouldn't this be py_pd
+ extending = false
+ end
+ end
+ end
+ end
+ -- we can have a simple variant when no paragraphs
+ if extending then
+ -- not ok
+ leftshape[#leftshape][2] = rd
+ rightshape[#rightshape][2] = rw
+ else
+ add(leftshape,rx,rd,"up")
+ add(rightshape,rw,rd,"down")
+ end
+ return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
+end
+
+-- local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
+-- local leftshape = { { rx, rh }, { rx, rd } }
+-- local rightshape = { { rw, rh }, { rw, rd } }
+-- return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
+-- end
+
+local function singlepart(b,e,r,left,right,obeyhang)
+ local bx, by = b.x, b.y
+ local ex, ey = e.x, e.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local bh = by + b.h
+ local bd = by - b.d
+ local eh = ey + e.h
+ local ed = ey - e.d
+ if ex == rx then
+ -- We probably have a strut at the next line so we force a width
+ -- although of course it is better to move up. But as we have whitespace
+ -- (at least visually) injected then it's best to stress the issue.
+ ex = rw
+ end
+ local area
+ if by == ey then
+ area = {
+ f_pair(bx,bh-ry),
+ f_pair(ex,eh-ry),
+ f_pair(ex,ed-ry),
+ f_pair(bx,bd-ry),
+ }
+ else
+ area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh,obeyhang)
+ add(area,bx,bh-ry)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ add(area,ex,eh-ry)
+ add(area,ex,ed-ry)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ add(area,bx,bd-ry)
+ add(area,bx,bh-ry,true) -- finish last straight line (but no add as we cycle)
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = f_pair(a[1],a[2])
+ end
+ end
+ return {
+ location = "single",
+ region = r,
+ area = area,
+ }
+end
+
+local function firstpart(b,r,left,right,obeyhang)
+ local bx, by = b.x, b.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local bh = by + b.h
+ local bd = by - b.d
+ local area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd,obeyhang)
+ add(area,bx,bh-ry)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ add(area,bx,bd-ry)
+ add(area,bx,bh-ry,true) -- finish last straight line (but no add as we cycle)
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = f_pair(a[1],a[2])
+ end
+ return {
+ location = "first",
+ region = r,
+ area = area,
+ }
+end
+
+local function middlepart(r,left,right,obeyhang)
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd,obeyhang)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = f_pair(a[1],a[2])
+ end
+ return {
+ location = "middle",
+ region = r,
+ area = area,
+ }
+end
+
+local function lastpart(e,r,left,right,obeyhang)
+ local ex, ey = e.x, e.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local area = { }
+ -- two cases: till end and halfway e line
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh,obeyhang)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ add(area,ex,eh-ry)
+ add(area,ex,ed-ry)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = f_pair(a[1],a[2])
+ end
+ return {
+ location = "last",
+ region = r,
+ area = area,
+ }
+end
+
+graphics = graphics or { }
+local backgrounds = { }
+
+graphics.backgrounds = backgrounds
+
+local function calculatemultipar(tag,obeyhang)
+ local collected = jobpositions.collected
+ local b = collected[f_b_tag(tag)]
+ local e = collected[f_e_tag(tag)]
+ if not b or not e then
+ report_graphics("invalid tag %a",tag)
+ return { }
+ end
+ local br = b.r
+ local er = e.r
+ if not br or not er then
+ report_graphics("invalid region for %a",tag)
+ return { }
+ end
+ local btag, bindex = lpegmatch(splitter,br)
+ local etag, eindex = lpegmatch(splitter,er)
+ if not bindex or not eindex or btag ~= etag then
+ report_graphics("invalid indices for %a",tag)
+ return { }
+ end
+ local bindex = tonumber(bindex)
+ local eindex = tonumber(eindex)
+ -- Here we compensate for columns (in tables): a table can have a set of column
+ -- entries and these are shared. We compensate left/right based on the columns
+ -- x and w but need to take the region into acount where the specification was
+ -- flushed and not the begin pos's region, because otherwise we get the wrong
+ -- compensation for assymetrical doublesided layouts.
+ local left = 0
+ local right = 0
+ local rc = b.c
+ if rc then
+ rc = collected[rc]
+ if rc then
+ local tb = collected[rc.r]
+ if tb then
+ left = -(tb.x - rc.x)
+ right = (tb.w - rc.w - left) -- tb.x - rc.x
+ end
+ end
+ end
+ -- Obeying intermediate changes of left/rightskip makes no sense as it will
+ -- look bad, so we only look at the begin situation.
+ local bn = b.n
+ if bn then
+ local bp = collected[f_p_tag(bn)]
+ if bp then
+ left = left + bp.ls
+ right = right + bp.rs
+ end
+ end
+ --
+ if bindex == eindex then
+ return {
+ list = { [b.p] = { singlepart(b,e,collected[br],left,right,obeyhang) } },
+ bpos = b,
+ epos = e,
+ }
+ else
+ local list = {
+ [b.p] = { firstpart(b,collected[br],left,right,obeyhang) },
+ }
+ for i=bindex+1,eindex-1 do
+ br = f_tag_two(btag,i)
+ local r = collected[br]
+ if not r then
+ report_graphics("invalid middle for %a",br)
+ else
+ local p = r.p
+ local pp = list[p]
+ if pp then
+ pp[#pp+1] = middlepart(r,left,right,obeyhang)
+ else
+ list[p] = { middlepart(r,left,right,obeyhang) }
+ end
+ end
+ end
+ local p = e.p
+ local pp = list[p]
+ if pp then
+ pp[#pp+1] = lastpart(e,collected[er],left,right,obeyhang)
+ else
+ list[p] = { lastpart(e,collected[er],left,right,obeyhang) }
+ end
+ return {
+ list = list,
+ bpos = b,
+ epos = e,
+ }
+ end
+end
+
+-- local pending = { } -- needs gc
+--
+-- local function register(data,n,anchor)
+-- local pa = pending[anchor]
+-- if not pa then
+-- pa = { }
+-- pending[anchor] = pa
+-- end
+-- for page, pagedata in next, data do
+-- local pap = pa[page]
+-- if pap then
+-- pap[#pap+1] = n
+-- else
+-- pa[page] = { n }
+-- end
+-- end
+-- end
+--
+-- function backgrounds.registered(anchor,page)
+-- local pa = pending[anchor]
+-- if pa then
+-- concat(pa,",")
+-- else
+-- return ""
+-- end
+-- end
+
+local pbg = { } -- will move to pending
+
+function backgrounds.calculatemultipar(n)
+ if not pbg[n] then
+ pbg[n] = calculatemultipar("pbg",n) or { }
+ end
+end
+
+local multilocs = {
+ single = 1, -- maybe 0
+ first = 1,
+ middle = 2,
+ last = 3,
+}
+
+-- if unknown context_abck : input mp-abck.mpiv ; fi ;
+
+local f_template_a = [[
+path multiregs[], multipars[], multibox ;
+string multikind[] ;
+numeric multilocs[], nofmultipars ;
+nofmultipars := %s ;
+multibox := unitsquare xyscaled (%p,%p) ;
+numeric par_strut_height, par_strut_depth, par_line_height ;
+par_strut_height := %p ;
+par_strut_depth := %p ;
+par_line_height := %p ;
+]]
+
+local f_template_b = [[
+multilocs[%s] := %s ;
+multikind[%s] := "%s" ;
+multipars[%s] := (%--t--cycle) shifted - (%p,%p) ;
+]]
+
+local f_template_c = [[
+multiregs[%s] := (%--t--cycle) shifted - %s ;
+]]
+
+local f_template_d = [[
+setbounds currentpicture to multibox ;
+]]
+
+f_template_a = formatters[f_template_a]
+f_template_b = formatters[f_template_b]
+f_template_c = formatters[f_template_c]
+f_template_d = formatters[f_template_d]
+
+local function fetchmultipar(n,anchor,page,obeyhang)
+ local data = pbg[n]
+ if not data then
+ data = calculatemultipar(n,obeyhang)
+ pbg[n] = data -- can be replaced by register
+ -- register(data.list,n,anchor)
+ end
+ if data then
+ local list = data.list
+ if list then
+ local pagedata = list[page]
+ if pagedata then
+ local nofmultipars = #pagedata
+ -- report_graphics("fetching %a at page %s using anchor %a containing %s multipars",n,page,anchor,nofmultipars)
+ local a = jobpositions.collected[anchor]
+ if not a then
+ report_graphics("missing anchor %a",anchor)
+ else
+ local trace = false
+ local x, y, w, h, d = a.x, a.y, a.w, a.h, a.d
+ local bpos = data.bpos
+ local bh, bd = bpos.h, bpos.d
+ local result = { f_template_a(nofmultipars,w,h+d,bh,bd,bh+bd) }
+ for i=1,nofmultipars do
+ local region = pagedata[i]
+ result[#result+1] = f_template_b(
+ i, multilocs[region.location],
+ i, region.location,
+ i, region.area, x, y-region.region.y)
+ if trace then
+ result[#result+1] = f_template_c(i, regionarea(region.region), offset)
+ end
+ end
+ data[page] = nil
+ result[#result+1] = f_template_d()
+ result = concat(result,"\n")
+ return result
+ end
+ end
+ end
+ end
+ return f_template_a(0,"origin",0,0,0)
+end
+
+backgrounds.fetchmultipar = fetchmultipar
+
+backgrounds.point = f_point
+backgrounds.pair = f_pair
+backgrounds.path = f_path
+
+-- n anchor page
+
+implement {
+ name = "fetchmultipar",
+ actions = { fetchmultipar, context },
+ arguments = { "string", "string", "integer" }
+}
+
+implement {
+ name = "fetchmultishape",
+ actions = { fetchmultipar, context },
+ arguments = { "string", "string", "integer", true }
+}
+
+local f_template_a = [[
+path posboxes[], posregions[] ;
+numeric pospages[] ;
+numeric nofposboxes ;
+nofposboxes := %s ;
+%t ;
+]]
+
+local f_template_b = [[
+pospages[%s] := %s ;
+posboxes[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
+posregions[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
+]]
+
+f_template_a = formatters[f_template_a]
+f_template_b = formatters[f_template_b]
+
+implement {
+ name = "fetchposboxes",
+ arguments = { "string", "string", "integer" },
+ actions = function(tags,anchor,page) -- no caching (yet) / todo: anchor, page
+ local collected = jobpositions.collected
+ if type(tags) == "string" then
+ tags = utilities.parsers.settings_to_array(tags)
+ end
+ local list, nofboxes = { }, 0
+ for i=1,#tags do
+ local tag= tags[i]
+ local c = collected[tag]
+ if c then
+ local r = c.r
+ if r then
+ r = collected[r]
+ if r then
+ local rx, ry, rw, rh, rd = r.x, r.y, r.w, r.h, r.d
+ local cx = c.x - rx
+ local cy = c.y - ry
+ local cw = cx + c.w
+ local ch = cy + c.h
+ local cd = cy - c.d
+ nofboxes = nofboxes + 1
+ list[nofboxes] = f_template_b(
+ nofboxes,c.p,
+ nofboxes,cx,ch,cw,ch,cw,cd,cx,cd,
+ nofboxes,0,rh,rw,rh,rw,rd,0,rd
+ )
+ end
+ end
+ else
+ print("\n missing",tag)
+ end
+ end
+ context(f_template_a(nofboxes,list))
+ end
+}
+
+local doifelse = commands.doifelse
+
+implement {
+ name = "doifelserangeonpage",
+ arguments = { "string", "string", "integer" },
+ actions = function(first,last,page)
+ local collected = jobpositions.collected
+ local f = collected[first]
+ if not f or f.p == true then
+ doifelse(false)
+ return
+ end
+ local l = collected[last]
+ if not l or l.p == true then
+ doifelse(false)
+ return
+ end
+ doifelse(page >= f.p and page <= l.p)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv
new file mode 100644
index 00000000000..a7ad26dff7f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv
@@ -0,0 +1,512 @@
+%D \module
+%D [ file=anch-pgr, % split off core-pos
+%D version=1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Positioning Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Grapics}
+
+%D Before we come to graphics support, we have to make sure of
+%D the reference point on the page. The next macros do so and
+%D are hooked into the page building routine.
+
+\registerctxluafile{anch-pgr}{1.001}
+
+\unprotect
+
+%D A few more low level macros take care of defining and recalling
+%D actions. Actions are saved globally! The lists can become quite
+%D long because there can be lots of parameters passed on so we
+%D clean up the list afterwards.
+
+\newtoks\everypositionaction
+\newtoks\everyinsertpositionaction
+\newtoks\everycleanpositionaction
+
+\installcorenamespace{positionaction}
+\installcorenamespace{positioncleanup}
+
+\unexpanded\def\anch_positions_set_action#1%
+ {\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces
+
+\unexpanded\def\doifpositionaction#1%
+ {\ifcsname\??positionaction#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifelsepositionaction#1%
+ {\ifcsname\??positionaction#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifpositionactionelse\doifelsepositionaction
+
+\unexpanded\def\dopositionaction#1%
+ {\edef\currentpositionaction{#1}%
+ \ifcsname\??positionaction\currentpositionaction\endcsname
+ \anch_positions_action_indeed
+ \fi}
+
+\def\anch_positions_action_indeed
+ {\doifelseposition\currentpositionaction
+ \anch_positions_action_indeed_yes
+ \anch_positions_action_indeed_nop}
+
+\def\anch_positions_action_indeed_nop
+ {\anch_positions_trace_action_nop}
+
+\def\anch_positions_action_indeed_yes % we need a way to figure out if we have actions
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\anch_positions_trace_action_yes
+ \the\everyinsertpositionaction
+ \the\everypositionaction
+ \csname\??positionaction\currentpositionaction\endcsname
+ \anch_positions_cleanup_action}%
+ \smashedbox\scratchbox % smashing is really needed else we get problems with too big overlays
+ \endgroup}
+
+\unexpanded\def\anch_positions_trace_action_nop_indeed
+ {\anch_positions_trace\clap\darkred{<\currentpositionaction>}}
+
+\unexpanded\def\anch_positions_trace_action_yes_indeed
+ {\anch_positions_trace\clap\darkgreen{<\currentpositionaction>}}
+
+\let\anch_positions_trace_action_nop\relax
+\let\anch_positions_trace_action_yes\relax
+
+\appendtoks
+ \let\anch_positions_trace_action_nop\anch_positions_trace_action_nop_indeed
+ \let\anch_positions_trace_action_yes\anch_positions_trace_action_yes_indeed
+\to \t_anch_positions_tracers
+
+%D Here the complication has to do with collecting actions
+%D for later execution. This collection is especially handy
+%D when we want to move actions to a specific layer. Such
+%D series of actions are stored in a macro that is cleaned up
+%D after each invocation.
+
+\def\anch_positions_cleanup_action % not in trialtypesetting
+ {\ifcsname\??positioncleanup\currentpositionaction\endcsname
+ \the\everycleanpositionaction
+ % \iflocalpositioning
+ % % erase
+ % \expandafter\let\csname\??positioncleanup\currentpositionaction\endcsname\empty
+ % \else
+ % globalize expansion cleans up
+ \setxvalue{\??positioncleanup\currentpositionaction}{\csname\??positioncleanup\currentpositionaction\endcsname}%
+ % \fi
+ \fi}
+
+\def\handlepositionaction#1\with#2\on#3% ugly
+ {\begingroup
+ \edef\currentpositionanchor
+ {\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
+ \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
+ \let#1\relax
+ \ifcsname\??positioncleanup\currentpositionanchor\endcsname
+ \setxvalue{\??positioncleanup\currentpositionanchor}%
+ {\csname\??positioncleanup\currentpositionanchor\endcsname#1#2}%
+ \else
+ \setxvalue{\??positioncleanup\currentpositionanchor}%
+ {#1#2}%
+ \fi
+ \endgroup}
+
+%D The first version of this module implemented head and tail
+%D anchors. Currently we stick to just one anchor and derive
+%D the head and tail anchors from this one. We set these
+%D anchors before and after each page.
+
+\newdimen\c_anch_page_width
+\newdimen\c_anch_page_height
+
+\unexpanded\def\anch_positions_register_page#1% this one is flushed first ! ... can't we avoid this one
+ {\ifpositioning\ifcase\realpageno\or
+ \ifdim\c_anch_page_height=\paperheight
+ \ifdim\c_anch_page_width=\paperwidth
+ % no change
+ \else
+ \c_anch_page_width \paperwidth
+ \c_anch_page_height\paperheight
+ \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hbox{\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
+ \fi
+ \fi\fi}
+
+\unexpanded\def\anch_positions_place_anchors
+ {\ifpositioning
+ \anch_positions_place_anchors_yes
+ \else
+ \anch_positions_place_anchors_nop
+ \fi}
+
+\def\anch_positions_place_anchors_yes % todo : depth pagebox
+ {\begingroup
+ \setbox\scratchbox\emptyhbox
+ \ht\scratchbox\textheight
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\makeupwidth
+ \anch_mark_text_box\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\def\anch_positions_place_anchors_nop
+ {\vskip\textheight}
+
+%D \macros
+%D {positionoverlay,startpositionoverlay}
+%D
+%D As long as we're dealing with graphics it makes much sense
+%D to use the available overlay mechanism. For this purpose, we
+%D define some dedicated overlay extensions.
+%D
+%D \startbuffer[sample]
+%D \defineoverlay [sample] [\positionoverlay{sample}]
+%D
+%D \startpositionoverlay{sample}
+%D \setMPpositiongraphic{A-1}{connectcenter}{from=A-1,to=A-2}
+%D \stoppositionoverlay
+%D \stopbuffer
+%D
+%D \typebuffer[sample]
+%D
+%D \startbuffer[graphic]
+%D \startMPpositiongraphic{connectcenter}
+%D path pa, pb ; pair ca, cb ;
+%D initialize_box(\MPpos{\MPvar{from}}) ; pa := pxy ; ca := cxy ;
+%D initialize_box(\MPpos{\MPvar{to}}) ; pb := pxy ; cb := cxy ;
+%D draw pa withcolor red ;
+%D draw pb withcolor red ;
+%D draw ca -- cb withcolor blue ;
+%D anchor_box(\MPanchor{\MPvar{from}}) ;
+%D \stopMPpositiongraphic
+%D \stopbuffer
+%D
+%D We can best demonstrate this in an example, say:
+%D
+%D \startbuffer[text]
+%D \framed
+%D [backgroundachtergrond=sample,align=middle,width=7cm]
+%D {We want to connect \hpos {A-1} {this} word with its
+%D grammatical cousin \hpos {A-2} {that}.}
+%D \stopbuffer
+%D
+%D \typebuffer[text]
+%D
+%D \startlinecorrection
+%D %\getbuffer[graphic,sample,text]
+%D \stoplinecorrection
+%D
+%D The graphic is defined in the following way, using some
+%D macros defined in an auxiliary \METAPOST\ module that is
+%D preloaded.
+%D
+%D \typebuffer[graphic]
+
+\def\MPanchoridentifier{mpa} % {mp-anchor}
+
+%D The rest of the definitions concerning such overlays may
+%D look complicated,
+
+\let\currentpositionoverlay\empty
+
+%D Position actions are automatically executed when a position
+%D is set.
+
+% \newcount\localpositionnumber % incremented elsewhere
+% \newif\iflocalpositioning
+%
+% \def\textbackgroundoverlay#1{\iflocalpositioning\v!local\else\v!text\fi#1}
+% \def\MPanchornumber {\the\iflocalpositioning\localpositionnumber\else\realpageno\fi}
+
+\def\textbackgroundoverlay#1{\v!text#1}
+\def\MPanchornumber {\the\realpageno}
+
+\unexpanded\def\positionoverlay % the test prevents too many redundant positions
+ {\ifpositioning % in (not used) text* position layers
+ \expandafter\anch_positions_overlay_indeed
+ \else % also \iftrialtypesetting test here?
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\anch_positions_overlay_indeed#1%
+ {\begingroup
+ \edef\currentpositionoverlay{#1}%
+ \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
+ \anch_positions_overlay_compose
+ \fi
+ \endgroup}
+
+\def\MPoverlayanchor#1{\MPpos\MPanchorid}
+
+\def\anch_positions_overlay_compose
+ {\vpack to \d_overlay_height
+ {%\writestatus{!!!}{\currentpositionoverlay/\MPanchoridentifier/\MPanchornumber}%
+ \edef\MPanchorid{\currentpositionoverlay::\MPanchoridentifier:\MPanchornumber}% realpageno
+ % \edef\MPanchor##1{\MPpos\MPanchorid}%
+ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
+ \the\everyinsertpositionaction
+ \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
+ \setbox\scratchbox\hbox to \d_overlay_width
+ {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+ \ht\scratchbox\d_overlay_height
+ \dp\scratchbox\zeropoint
+ \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox
+ \box\scratchbox
+ \vfill}}
+
+\unexpanded\def\positionregionoverlay % shares regions
+ {\ifpositioning
+ \expandafter\anch_positions_region_overlay_indeed
+ \else % also \iftrialtypesetting test here?
+ \expandafter\gobbletwoarguments
+ \fi}
+
+\let\currentpositionregion\empty
+
+\def\anch_positions_region_overlay_indeed#1#2%
+ {\begingroup
+ \edef\currentpositionregion {#1}%
+ \edef\currentpositionoverlay{#2}%
+ \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
+ \anch_positions_region_overlay_compose
+ \fi
+ \endgroup}
+
+\def\anch_positions_region_overlay_compose
+ {\vpack to \d_overlay_height
+ {\let\MPanchorid\currentpositionregion
+ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
+ \the\everyinsertpositionaction
+ \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
+ \setbox\scratchbox\hbox to \d_overlay_width
+ {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+ \ht\scratchbox\d_overlay_height
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \vfill}}
+
+% \let\anch_positions_overlay_nop\gobbleoneargument
+
+\unexpanded\def\startpositionoverlay
+ {\iftrialtypesetting
+ \expandafter\anch_positions_overlay_start_nop
+ \else
+ \expandafter\anch_positions_overlay_start_yes
+ \fi}
+
+\let\stoppositionoverlay\relax
+
+\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
+ {}
+
+\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi
+
+\let\currentpositionoverlay\empty
+
+\def\anch_positions_overlay_start_yes#1%
+ {\checkpositionoverlays
+ \edef\currentpositionoverlay{#1}}
+
+\unexpanded\def\stoppositionoverlay
+ {\let\currentpositionoverlay\empty}
+
+% needs checking if still needed
+%
+% \def\resetpositionoverlay#1%
+% {\anch_positions_set_action{#1::\MPanchoridentifier::}{}}
+%
+% \def\handlepositionboxes#1#2#3%
+% {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}
+%
+% \def\doinsertpositionboxes#1#2#3% pos tag setups
+% {\ifnum\MPp{#1}=\realpageno\relax % can be sped up
+% \executeifdefined{\MPoverlayposprefix#1}\gobblethreearguments{#1}{#2}{#3}% not used
+% \fi}
+%
+% \appendtoks
+% \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
+% \to \everyinsertpositionaction
+%
+% \def\docleanpositionboxes#1#2#3% pos tag setups
+% {\ifnum\MPp{#1}<\realpageno \else
+% \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert
+% \fi}
+%
+% \appendtoks
+% \let\dohandlepositionboxes\docleanpositionboxes
+% \to \everycleanpositionaction
+
+%D A position graphic is a normal (non||reused) \METAPOST\
+%D graphic, used immediately, with zero dimensions, so that a
+%D sequence of them does not harm.
+
+\installcorenamespace{positiongraphic}
+\installcorenamespace{positionmethod}
+%installcorenamespace{graphicvariable}
+
+\newbox\b_anch_positions_graphic
+
+\def\startMPpositiongraphic % id setups
+ {\dodoublegroupempty\anch_positions_meta_graphic_start}
+
+\def\anch_positions_meta_graphic_start#1#2#3\stopMPpositiongraphic % tag list mpcode
+ {\setgvalue{\??positiongraphic#1}{\anch_positions_meta_graphic_use{#1}{#2}{#3}}}
+
+\let\stopMPpositiongraphic\relax
+
+\def\anch_positions_meta_graphic_prepare
+ {\ifcsname\??graphicvariable\currentmpvariableclass:self\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:self}\currentposition
+ \fi
+ \ifcsname\??graphicvariable\currentmpvariableclass:from\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:from}\currentposition
+ \fi}
+
+\def\anch_positions_meta_graphic_use#1#2#3%
+ {\begingroup
+ \meta_prepare_variables{#2}%
+ \anch_positions_meta_graphic_prepare
+ \startMPcode#3\stopMPcode
+ \endgroup}
+
+\unexpanded\def\MPpositiongraphic
+ {\dodoublegroupempty\anch_positions_meta_graphic_direct}
+
+\def\anch_positions_meta_graphic_direct#1% tag setups
+ {\ifcsname\??positionmethod#1\endcsname % method
+ \expandafter\anch_positions_meta_graphic_direct_indeed_method
+ \else\ifcsname\??positiongraphic#1\endcsname
+ \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_normal
+ \else
+ \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_unknown
+ \fi\fi{#1}}
+
+\let\anch_positions_meta_graphic_direct_indeed_unknown\gobbletwoarguments
+
+\def\anch_positions_meta_graphic_direct_indeed_method
+ {\anch_positions_meta_graphic_direct_indeed\??positionmethod}
+
+\def\anch_positions_meta_graphic_direct_indeed_normal
+ {\anch_positions_meta_graphic_direct_indeed\??positiongraphic}
+
+\def\anch_positions_meta_graphic_direct_indeed#1#2#3% what tag setups
+ {\begingroup
+ \setupMPvariables[#2][#3]%
+ \edef\currentmpvariableclass{#2}%
+ \anch_positions_meta_graphic_prepare
+ \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
+ \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
+ \setbox\b_anch_positions_graphic\hbox
+ {\ignorespaces\csname#1#2\endcsname\removelastspace}%
+ \smashbox\b_anch_positions_graphic
+ \box\b_anch_positions_graphic
+ \endgroup}
+
+\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
+ {\begingroup
+ \setupMPvariables[#2][#1,#3]%
+ \edef\currentmpvariableclass{#2}%
+ \anch_positions_meta_graphic_prepare
+ \csname\??positiongraphic#2\endcsname
+ \endgroup}%
+
+\def\startMPpositionmethod#1#2\stopMPpositionmethod
+ {\setgvalue{\??positionmethod#1}{#2}} % todo: var list here
+
+\let\stopMPpositionmethod\relax
+
+%D Simple one position graphics.
+
+\unexpanded\def\setMPpositiongraphic
+ {\dotriplegroupempty\anch_positions_meta_graphic_set}
+
+\def\anch_positions_meta_graphic_set#1#2#3% pos tag vars
+ {\ifx\currentpositionoverlay\empty
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}%
+ \else % silly can be one
+ \anch_positions_meta_graphic_handle{#1}{#2}{#3}%
+ \fi}
+
+\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes
+ {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}}
+
+\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups
+ {\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
+ \def\currentposition{#1}\MPpositiongraphic{#2}{#3}%
+ \fi}
+
+\let\anch_positions_meta_graphic_handle_indeed\relax
+
+\appendtoks
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert
+\to \everyinsertpositionaction
+
+\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups
+ {\ifnum\MPp{#1}<\realpageno \else
+ \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}%
+ \fi}
+
+\appendtoks
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup
+\to \everycleanpositionaction
+
+%D Graphics that span two positions (beware, does not cross pages).
+
+\unexpanded\def\setMPpositiongraphicrange
+ {\doquadruplegroupempty\anch_positions_meta_graphic_set_range}
+
+\def\anch_positions_meta_graphic_set_range#1#2#3#4% bpos epos tag vars
+ {\ifx\currentpositionoverlay\empty
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}%
+ \else
+ \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}%
+ \fi}
+
+\def\anch_positions_meta_graphic_handle_range#1#2#3#4%
+ {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}}
+
+\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups
+ {\clf_doifelserangeonpage{#1}{#2}\realpageno
+ {\def\currentposition{#1}%
+ \MPpositiongraphic{#3}{#4}}%
+ {}}
+
+\appendtoks
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range
+\to \everyinsertpositionaction
+
+\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups
+ {\ifnum\MPp{#2}<\realpageno \else
+ \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}%
+ \fi}
+
+\appendtoks
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range
+\to \everycleanpositionaction
+
+\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments
+
+% Helpers:
+
+\def\MPgetposboxes #1#2{\clf_fetchposboxes {#1}{#2}\realpageno}
+\def\MPgetmultipars #1#2{\clf_fetchmultipar {#1}{#2}\realpageno}
+\def\MPgetmultishapes#1#2{\clf_fetchmultishape{#1}{#2}\realpageno}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua
new file mode 100644
index 00000000000..c01e9017976
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua
@@ -0,0 +1,1205 @@
+if not modules then modules = { } end modules ['anch-pos'] = {
+ version = 1.001,
+ comment = "companion to anch-pos.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>We save positional information in the main utility table. Not only
+can we store much more information in <l n='lua'/> but it's also
+more efficient.</p>
+--ldx]]--
+
+-- plus (extra) is obsolete but we will keep it for a while
+
+-- context(new_latelua_node(f_enhance(tag)))
+-- =>
+-- context.lateluafunction(function() f_enhance(tag) end)
+
+-- maybe replace texsp by our own converter (stay at the lua end)
+-- eventually mp will have large numbers so we can use sp there too
+
+local tostring, next, rawget, setmetatable = tostring, next, rawget, setmetatable
+local sort = table.sort
+local format, gmatch, match = string.format, string.gmatch, string.match
+local rawget = rawget
+local lpegmatch = lpeg.match
+local insert, remove = table.insert, table.remove
+local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+
+local scanners = tokens.scanners
+local scanstring = scanners.string
+local scaninteger = scanners.integer
+local scandimen = scanners.dimen
+
+local compilescanner = tokens.compile
+local scanners = interfaces.scanners
+
+local commands = commands
+local context = context
+
+local tex = tex
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+local texget = tex.get
+local texsp = tex.sp
+----- texsp = string.todimen -- because we cache this is much faster but no rounding
+
+local pdf = pdf -- h and v are variables
+
+local setmetatableindex = table.setmetatableindex
+
+local nuts = nodes.nuts
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getbox = nuts.getbox
+local getskip = nuts.getskip
+
+local find_tail = nuts.tail
+
+local new_latelua = nuts.pool.latelua
+local new_latelua_node = nodes.pool.latelua
+
+local variables = interfaces.variables
+local v_text = variables.text
+local v_column = variables.column
+
+local pt = number.dimenfactors.pt
+local pts = number.pts
+local formatters = string.formatters
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local jobpositions = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.positions = jobpositions
+
+_plib_ = jobpositions -- might go
+
+local default = { -- not r and paragraphs etc
+ __index = {
+ x = 0, -- x position baseline
+ y = 0, -- y position baseline
+ w = 0, -- width
+ h = 0, -- height
+ d = 0, -- depth
+ p = 0, -- page
+ n = 0, -- paragraph
+ ls = 0, -- leftskip
+ rs = 0, -- rightskip
+ hi = 0, -- hangindent
+ ha = 0, -- hangafter
+ hs = 0, -- hsize
+ pi = 0, -- parindent
+ ps = false, -- parshape
+ }
+}
+
+local f_b_tag = formatters["b:%s"]
+local f_e_tag = formatters["e:%s"]
+local f_p_tag = formatters["p:%s"]
+local f_w_tag = formatters["w:%s"]
+
+local f_b_column = formatters["_plib_.b_col(%q)"]
+local f_e_column = formatters["_plib_.e_col()"]
+
+local f_enhance = formatters["_plib_.enhance(%q)"]
+local f_region = formatters["region:%s"]
+
+local f_b_region = formatters["_plib_.b_region(%q)"]
+local f_e_region = formatters["_plib_.e_region(%s)"]
+
+local f_tag_three = formatters["%s:%s:%s"]
+local f_tag_two = formatters["%s:%s"]
+
+local function sorter(a,b)
+ return a.y > b.y
+end
+
+local nofusedregions = 0
+local nofmissingregions = 0
+local nofregular = 0
+
+jobpositions.used = false
+
+-- todo: register subsets and count them indepently
+
+local function initializer()
+ tobesaved = jobpositions.tobesaved
+ collected = jobpositions.collected
+ -- add sparse regions
+ local pages = structures.pages.collected
+ if pages then
+ local last = nil
+ for p=1,#pages do
+ local region = "page:" .. p
+ local data = collected[region]
+ if data then
+ last = data
+ last.p = nil -- no need for a page
+ elseif last then
+ collected[region] = last
+ end
+ end
+ end
+ -- enhance regions with paragraphs
+ for tag, data in next, collected do
+ local region = data.r
+ if region then
+ local r = collected[region]
+ if r then
+ local paragraphs = r.paragraphs
+ if not paragraphs then
+ r.paragraphs = { data }
+ else
+ paragraphs[#paragraphs+1] = data
+ end
+ nofusedregions = nofusedregions + 1
+ else
+ nofmissingregions = nofmissingregions + 1
+ end
+ else
+ nofregular = nofregular + 1
+ end
+ setmetatable(data,default)
+ end
+ -- add metatable
+ -- for tag, data in next, collected do
+ -- setmetatable(data,default)
+ -- end
+ -- sort this data
+ for tag, data in next, collected do
+ local region = data.r
+ if region then
+ local r = collected[region]
+ if r then
+ local paragraphs = r.paragraphs
+ if paragraphs and #paragraphs > 1 then
+ sort(paragraphs,sorter)
+ end
+ end
+ end
+ -- so, we can be sparse and don't need 'or 0' code
+ end
+ jobpositions.used = next(collected)
+end
+
+job.register('job.positions.collected', tobesaved, initializer)
+
+local regions = { }
+local nofregions = 0
+local region = nil
+
+local columns = { }
+local nofcolumns = 0
+local column = nil
+
+local nofpages = nil
+
+-- beware ... we're not sparse here as lua will reserve slots for the nilled
+
+local 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 function setdim(name,w,h,d,extra) -- will be used when we move to sp allover
+ local x, y = getpos()
+ if x == 0 then x = nil end
+ if y == 0 then y = nil end
+ if w == 0 then w = nil end
+ if h == 0 then h = nil end
+ if d == 0 then d = nil end
+ if extra == "" then extra = nil end
+ -- todo: sparse
+ tobesaved[name] = {
+ p = texgetcount("realpageno"),
+ x = x,
+ y = y,
+ w = w,
+ h = h,
+ d = d,
+ e = extra,
+ r = region,
+ c = column,
+ }
+end
+
+local function setall(name,p,x,y,w,h,d,extra)
+ if x == 0 then x = nil end
+ if y == 0 then y = nil end
+ if w == 0 then w = nil end
+ if h == 0 then h = nil end
+ if d == 0 then d = nil end
+ if extra == "" then extra = nil end
+ -- todo: sparse
+ tobesaved[name] = {
+ p = p,
+ x = x,
+ y = y,
+ w = w,
+ h = h,
+ d = d,
+ e = extra,
+ r = region,
+ c = column,
+ }
+end
+
+local function enhance(data)
+ if not data then
+ return nil
+ end
+ if data.r == true then -- or ""
+ data.r = region
+ end
+ if data.x == true then
+ if data.y == true then
+ data.x, data.y = getpos()
+ else
+ data.x = gethpos()
+ end
+ elseif data.y == true then
+ data.y = getvpos()
+ end
+ if data.p == true then
+ data.p = texgetcount("realpageno")
+ end
+ if data.c == true then
+ data.c = column
+ end
+ if data.w == 0 then
+ data.w = nil
+ end
+ if data.h == 0 then
+ data.h = nil
+ end
+ if data.d == 0 then
+ data.d = nil
+ end
+ return data
+end
+
+-- 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
+-- if data[key] and not next(next(data)) then
+-- data = data[key]
+-- end
+ container = tobesaved[name]
+ if not container then
+ tobesaved[name] = {
+ [index] = data
+ }
+ else
+ container[index] = data
+ end
+ else
+ tobesaved[name] = data
+ end
+end
+
+local function get(id,index)
+ if index then
+ local container = collected[id]
+ return container and container[index]
+ else
+ return collected[id]
+ end
+end
+
+jobpositions.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
+
+scanners.dosaveposition = compilescanner {
+ actions = setall, -- name p x y
+ arguments = { "string", "integer", "dimen", "dimen" }
+}
+
+scanners.dosavepositionwhd = compilescanner { -- somehow fails
+ actions = setall, -- name p x y w h d
+ arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" }
+}
+
+scanners.dosavepositionplus = compilescanner {
+ actions = setall, -- name p x y w h d extra
+ arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen", "string" }
+}
+
+-- will become private table (could also become attribute driven but too nasty
+-- as attributes can bleed e.g. in margin stuff)
+
+-- not much gain in keeping stack (inc/dec instead of insert/remove)
+
+function jobpositions.b_col(tag)
+ tobesaved[tag] = {
+ r = true,
+ x = gethpos(),
+ w = 0,
+ }
+ insert(columns,tag)
+ column = tag
+end
+
+function jobpositions.e_col(tag)
+ local t = tobesaved[column]
+ if not t then
+ -- something's wrong
+ else
+ t.w = gethpos() - t.x
+ t.r = region
+ end
+ remove(columns)
+ column = columns[#columns]
+end
+
+scanners.bposcolumn = function() -- tag
+ local tag = scanstring()
+ insert(columns,tag)
+ column = tag
+end
+
+scanners.bposcolumnregistered = function() -- tag
+ local tag = scanstring()
+ insert(columns,tag)
+ column = tag
+ context(new_latelua_node(f_b_column(tag)))
+end
+
+scanners.eposcolumn = function()
+ remove(columns)
+ column = columns[#columns]
+end
+
+scanners.eposcolumnregistered = function()
+ context(new_latelua_node(f_e_column()))
+ remove(columns)
+ column = columns[#columns]
+end
+
+-- regions
+
+function jobpositions.b_region(tag)
+ local last = tobesaved[tag]
+ last.x, last.y = getpos()
+ last.p = texgetcount("realpageno")
+ insert(regions,tag)
+ region = tag
+end
+
+function jobpositions.e_region(correct)
+ local last = tobesaved[region]
+ local v = getvpos()
+ if correct then
+ last.h = last.y - v
+ end
+ last.y = v
+ remove(regions)
+ region = regions[#regions]
+end
+
+local function setregionbox(n,tag)
+ if not tag or tag == "" then
+ nofregions = nofregions + 1
+ tag = f_region(nofregions)
+ end
+ local box = getbox(n)
+ local w = getfield(box,"width")
+ local h = getfield(box,"height")
+ local d = getfield(box,"depth")
+ tobesaved[tag] = {
+ p = true,
+ x = true,
+ y = getvpos(), -- true,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ }
+ return tag, box
+end
+
+local function markregionbox(n,tag,correct)
+ local tag, box = setregionbox(n,tag)
+ local push = new_latelua(f_b_region(tag))
+ local pop = new_latelua(f_e_region(tostring(correct))) -- todo: check if tostring is needed with formatter
+ -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end
+ local head = getlist(box)
+ if head then
+ local tail = find_tail(head)
+ setlink(push,head)
+ setlink(tail,pop)
+ else -- we can have a simple push/pop
+ setlink(push,pop)
+ end
+ setlist(box,push)
+end
+
+jobpositions.markregionbox = markregionbox
+jobpositions.setregionbox = setregionbox
+
+function jobpositions.enhance(name)
+ enhance(tobesaved[name])
+end
+
+-- scanners.pos = function(name,t) -- name t
+-- local name = scanstring()
+-- tobesaved[name] = scanstring()
+-- context(new_latelua_node(f_enhance(name)))
+-- end
+
+local nofparagraphs = 0
+
+scanners.parpos = function() -- todo: relate to localpar (so this is an intermediate variant)
+ nofparagraphs = nofparagraphs + 1
+ texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
+ local strutbox = getbox("strutbox")
+ local t = {
+ p = true,
+ c = true,
+ r = true,
+ x = true,
+ y = true,
+ h = getfield(strutbox,"height"),
+ d = getfield(strutbox,"depth"),
+ hs = texget("hsize"),
+ }
+ local leftskip = getfield(getskip("leftskip"),"width")
+ local rightskip = getfield(getskip("rightskip"),"width")
+ local hangindent = texget("hangindent")
+ local hangafter = texget("hangafter")
+ local parindent = texget("parindent")
+ local parshape = texget("parshape")
+ if leftskip ~= 0 then
+ t.ls = leftskip
+ end
+ if rightskip ~= 0 then
+ t.rs = rightskip
+ end
+ if hangindent ~= 0 then
+ t.hi = hangindent
+ end
+ if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero
+ t.ha = hangafter
+ end
+ if parindent ~= 0 then
+ t.pi = parindent
+ end
+ if parshape and #parshape > 0 then
+ t.ps = parshape
+ end
+ local tag = f_p_tag(nofparagraphs)
+ tobesaved[tag] = t
+ context(new_latelua_node(f_enhance(tag)))
+end
+
+scanners.dosetposition = function() -- name
+ local name = scanstring()
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua_node(f_enhance(name)))
+end
+
+scanners.dosetpositionwhd = function() -- name w h d extra
+ local name = scanstring()
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = scandimen(),
+ h = scandimen(),
+ d = scandimen(),
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua_node(f_enhance(name)))
+end
+
+scanners.dosetpositionbox = function() -- name box
+ local name = scanstring()
+ local box = getbox(scaninteger())
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = getfield(box,"width"),
+ h = getfield(box,"height"),
+ d = getfield(box,"depth"),
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua_node(f_enhance(name)))
+end
+
+scanners.dosetpositionplus = function() -- name w h d extra
+ local name = scanstring()
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = scandimen(),
+ h = scandimen(),
+ d = scandimen(),
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ e = scanstring(),
+ }
+ context(new_latelua_node(f_enhance(name)))
+end
+
+scanners.dosetpositionstrut = function() -- name
+ local name = scanstring()
+ local strutbox = getbox("strutbox")
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ h = getfield(strutbox,"height"),
+ d = getfield(strutbox,"depth"),
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua_node(f_enhance(name)))
+end
+
+function jobpositions.getreserved(tag,n)
+ if tag == v_column then
+ local fulltag = f_tag_three(tag,texgetcount("realpageno"),n or 1)
+ local data = collected[fulltag]
+ if data then
+ return data, fulltag
+ end
+ tag = v_text
+ end
+ if tag == v_text then
+ local fulltag = f_tag_two(tag,texgetcount("realpageno"))
+ return collected[fulltag] or false, fulltag
+ end
+ return collected[tag] or false, tag
+end
+
+function jobpositions.copy(target,source)
+ collected[target] = collected[source]
+end
+
+function jobpositions.replace(id,p,x,y,w,h,d)
+ collected[id] = { p = p, x = x, y = y, w = w, h = h, d = d } -- c g
+end
+
+function jobpositions.page(id)
+ local jpi = collected[id]
+ return jpi and jpi.p
+end
+
+function jobpositions.region(id)
+ local jpi = collected[id]
+ if jpi then
+ local r = jpi.r
+ if r then
+ return r
+ end
+ local p = jpi.p
+ if p then
+ return "page:" .. p
+ end
+ end
+ return false
+end
+
+function jobpositions.column(id)
+ local jpi = collected[id]
+ return jpi and jpi.c or false
+end
+
+function jobpositions.paragraph(id)
+ local jpi = collected[id]
+ return jpi and jpi.n
+end
+
+jobpositions.p = jobpositions.page
+jobpositions.r = jobpositions.region
+jobpositions.c = jobpositions.column
+jobpositions.n = jobpositions.paragraph
+
+function jobpositions.x(id)
+ local jpi = collected[id]
+ return jpi and jpi.x
+end
+
+function jobpositions.y(id)
+ local jpi = collected[id]
+ return jpi and jpi.y
+end
+
+function jobpositions.width(id)
+ local jpi = collected[id]
+ return jpi and jpi.w
+end
+
+function jobpositions.height(id)
+ local jpi = collected[id]
+ return jpi and jpi.h
+end
+
+function jobpositions.depth(id)
+ local jpi = collected[id]
+ return jpi and jpi.d
+end
+
+function jobpositions.leftskip(id)
+ local jpi = collected[id]
+ return jpi and jpi.ls
+end
+
+function jobpositions.rightskip(id)
+ local jpi = collected[id]
+ return jpi and jpi.rs
+end
+
+function jobpositions.hsize(id)
+ local jpi = collected[id]
+ return jpi and jpi.hs
+end
+
+function jobpositions.parindent(id)
+ local jpi = collected[id]
+ return jpi and jpi.pi
+end
+
+function jobpositions.hangindent(id)
+ local jpi = collected[id]
+ return jpi and jpi.hi
+end
+
+function jobpositions.hangafter(id)
+ local jpi = collected[id]
+ return jpi and jpi.ha or 1
+end
+
+function jobpositions.xy(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.x, jpi.y
+ else
+ return 0, 0
+ end
+end
+
+function jobpositions.lowerleft(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.x, jpi.y - jpi.d
+ else
+ return 0, 0
+ end
+end
+
+function jobpositions.lowerright(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.x + jpi.w, jpi.y - jpi.d
+ else
+ return 0, 0
+ end
+end
+
+function jobpositions.upperright(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.x + jpi.w, jpi.y + jpi.h
+ else
+ return 0, 0
+ end
+end
+
+function jobpositions.upperleft(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.x, jpi.y + jpi.h
+ else
+ return 0, 0
+ end
+end
+
+function jobpositions.position(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.p, jpi.x, jpi.y, jpi.w, jpi.h, jpi.d
+ else
+ return 0, 0, 0, 0, 0, 0
+ end
+end
+
+function jobpositions.extra(id,n,default) -- assume numbers
+ local jpi = collected[id]
+ if jpi then
+ local e = jpi.e
+ if e then
+ local split = jpi.split
+ if not split then
+ split = lpegmatch(splitter,jpi.e)
+ jpi.split = split
+ end
+ return texsp(split[n]) or default -- watch the texsp here
+ end
+ end
+ return default
+end
+
+local function overlapping(one,two,overlappingmargin) -- hm, strings so this is wrong .. texsp
+ one = collected[one]
+ two = collected[two]
+ if one and two and one.p == two.p then
+ if not overlappingmargin then
+ overlappingmargin = 2
+ end
+ local x_one = one.x
+ local x_two = two.x
+ local w_two = two.w
+ local llx_one = x_one - overlappingmargin
+ local urx_two = x_two + w_two + overlappingmargin
+ if llx_one > urx_two then
+ return false
+ end
+ local w_one = one.w
+ local urx_one = x_one + w_one + overlappingmargin
+ local llx_two = x_two - overlappingmargin
+ if urx_one < llx_two then
+ return false
+ end
+ local y_one = one.y
+ local y_two = two.y
+ local d_one = one.d
+ local h_two = two.h
+ local lly_one = y_one - d_one - overlappingmargin
+ local ury_two = y_two + h_two + overlappingmargin
+ if lly_one > ury_two then
+ return false
+ end
+ local h_one = one.h
+ local d_two = two.d
+ local ury_one = y_one + h_one + overlappingmargin
+ local lly_two = y_two - d_two - overlappingmargin
+ if ury_one < lly_two then
+ return false
+ end
+ return true
+ end
+end
+
+local function onsamepage(list,page)
+ for id in gmatch(list,"(, )") do
+ local jpi = collected[id]
+ if jpi then
+ local p = jpi.p
+ if not p then
+ return false
+ elseif not page then
+ page = p
+ elseif page ~= p then
+ return false
+ end
+ end
+ end
+ return page
+end
+
+jobpositions.overlapping = overlapping
+jobpositions.onsamepage = onsamepage
+
+-- interface
+
+scanners.replacepospxywhd = function() -- name page x y w h d
+ collected[scanstring()] = {
+ p = scaninteger(),
+ x = scandimen(),
+ y = scandimen(),
+ w = scandimen(),
+ h = scandimen(),
+ d = scandimen(),
+ }
+end
+
+scanners.copyposition = function() -- target source
+ collected[scanstring()] = collected[scanstring()]
+end
+
+scanners.MPp = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local p = jpi.p
+ if p and p ~= true then
+ context(p)
+ return
+ end
+ end
+ context('0')
+end
+
+scanners.MPx = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local x = jpi.x
+ if x and x ~= true and x ~= 0 then
+ context("%.5Fpt",x*pt)
+ return
+ end
+ end
+ context('0pt')
+end
+
+scanners.MPy = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local y = jpi.y
+ if y and y ~= true and y ~= 0 then
+ context("%.5Fpt",y*pt)
+ return
+ end
+ end
+ context('0pt')
+end
+
+scanners.MPw = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local w = jpi.w
+ if w and w ~= 0 then
+ context("%.5Fpt",w*pt)
+ return
+ end
+ end
+ context('0pt')
+end
+
+scanners.MPh = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local h = jpi.h
+ if h and h ~= 0 then
+ context("%.5Fpt",h*pt)
+ return
+ end
+ end
+ context('0pt')
+end
+
+scanners.MPd = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local d = jpi.d
+ if d and d ~= 0 then
+ context("%.5Fpt",d*pt)
+ return
+ end
+ end
+ context('0pt')
+end
+
+scanners.MPxy = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x*pt,
+ jpi.y*pt
+ )
+ else
+ context('(0,0)')
+ end
+end
+
+scanners.MPll = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x *pt,
+ (jpi.y-jpi.d)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
+end
+
+scanners.MPlr = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y - jpi.d)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
+end
+
+scanners.MPur = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y + jpi.h)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
+end
+
+scanners.MPul = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x *pt,
+ (jpi.y + jpi.h)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
+end
+
+local function MPpos(id)
+ local jpi = collected[id]
+ if jpi then
+ local p = jpi.p
+ if p then
+ context("%s,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt",
+ p,
+ jpi.x*pt,
+ jpi.y*pt,
+ jpi.w*pt,
+ jpi.h*pt,
+ jpi.d*pt
+ )
+ return
+ end
+ end
+ context('0,0,0,0,0,0') -- for mp only
+end
+
+scanners.MPpos = function() -- name
+ MPpos(scanstring())
+end
+
+scanners.MPn = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local n = jpi.n
+ if n then
+ context(n)
+ return
+ end
+ end
+ context(0)
+end
+
+scanners.MPc = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local c = jpi.c
+ if c and c ~= true then
+ context(c)
+ return
+ end
+ end
+ context('0') -- okay ?
+end
+
+scanners.MPr = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ local r = jpi.r
+ if r and r ~= true then
+ context(r)
+ end
+ local p = jpi.p
+ if p then
+ context("page:" .. p)
+ end
+ end
+end
+
+local function MPpardata(n)
+ local t = collected[n]
+ if not t then
+ local tag = f_p_tag(n)
+ t = collected[tag]
+ end
+ if t then
+ context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%s,%.5Fpt",
+ t.hs*pt,
+ t.ls*pt,
+ t.rs*pt,
+ t.hi*pt,
+ t.ha,
+ t.pi*pt
+ )
+ else
+ context("0,0,0,0,0,0") -- for mp only
+ end
+end
+
+scanners.MPpardata = function() -- name
+ MPpardata(scanstring())
+end
+
+scanners.MPposset = function() -- name (special helper, used in backgrounds)
+ local name = scanstring()
+ local b = f_b_tag(name)
+ local e = f_e_tag(name)
+ local w = f_w_tag(name)
+ local p = f_p_tag(jobpositions.n(b))
+ MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p)
+end
+
+scanners.MPls = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context("%.5Fpt",jpi.ls*pt)
+ else
+ context("0pt")
+ end
+end
+
+scanners.MPrs = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context("%.5Fpt",jpi.rs*pt)
+ else
+ context("0pt")
+ end
+end
+
+local splitter = lpeg.tsplitat(",")
+
+scanners.MPplus = function() -- name n default
+ local jpi = collected[scanstring()]
+ local n = scaninteger()
+ local default = scanstring()
+ if jpi then
+ local e = jpi.e
+ if e then
+ local split = jpi.split
+ if not split then
+ split = lpegmatch(splitter,jpi.e)
+ jpi.split = split
+ end
+ context(split[n] or default)
+ return
+ end
+ end
+ context(default)
+end
+
+scanners.MPrest = function() -- name default
+ local jpi = collected[scanstring()]
+ local default = scanstring()
+ context(jpi and jpi.e or default)
+end
+
+scanners.MPxywhd = function() -- name
+ local jpi = collected[scanstring()]
+ if jpi then
+ context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt",
+ jpi.x*pt,
+ jpi.y*pt,
+ jpi.w*pt,
+ jpi.h*pt,
+ jpi.d*pt
+ )
+ else
+ context("0,0,0,0,0") -- for mp only
+ end
+end
+
+local doif = commands.doif
+local doifelse = commands.doifelse
+
+scanners.doifelseposition = function() -- name
+ doifelse(collected[scanstring()])
+end
+
+scanners.doifposition = function() -- name
+ doif(collected[scanstring()])
+end
+
+scanners.doifelsepositiononpage = function() -- name page -- probably always realpageno
+ local c = collected[scanstring()]
+ local p = scaninteger()
+ doifelse(c and c.p == p)
+end
+
+scanners.doifelseoverlapping = function() -- one two
+ doifelse(overlapping(scanstring(),scanstring()))
+end
+
+scanners.doifelsepositionsonsamepage = function() -- list
+ doifelse(onsamepage(scanstring()))
+end
+
+scanners.doifelsepositionsonthispage = function() -- list
+ doifelse(onsamepage(scanstring(),tostring(texgetcount("realpageno"))))
+end
+
+scanners.doifelsepositionsused = function()
+ doifelse(next(collected))
+end
+
+scanners.markregionbox = function() -- box
+ markregionbox(scaninteger())
+end
+
+scanners.setregionbox = function() -- box
+ setregionbox(scaninteger())
+end
+
+scanners.markregionboxtagged = function() -- box tag
+ markregionbox(scaninteger(),scanstring())
+end
+
+scanners.setregionboxtagged = function() -- box tag
+ setregionbox(scaninteger(),scanstring())
+end
+
+scanners.markregionboxcorrected = function() -- box tag
+ markregionbox(scaninteger(),scanstring(),true)
+end
+
+-- statistics (at least for the moment, when testing)
+
+statistics.register("positions", function()
+ local total = nofregular + nofusedregions + nofmissingregions
+ if total > 0 then
+ return format("%s collected, %s regulars, %s regions, %s unresolved regions",
+ total, nofregular, nofusedregions, nofmissingregions)
+ else
+ return nil
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv
new file mode 100644
index 00000000000..5d9c2fd3478
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv
@@ -0,0 +1,459 @@
+%D \module
+%D [ file=anch-pos, % was core-pos
+%D version=1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Positioning Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Positioning}
+
+%D In \MKIV\ there was already a different housekeeping model for positions quite
+%D early, but starting in 2012 more dramatic changes started to happen, especially
+%D in relation to background graphics. It will probably take some time to settle.
+
+\registerctxluafile{anch-pos}{1.001}
+
+\unprotect
+
+%D The first application of positional information was embedded graphics. Since we
+%D are interacting with text, it made sense to take the current line height and
+%D depth into account too. This is why we have position macros for simple positions
+%D and one boxes.
+%D
+%D \starttyping
+%D \dosetposition {identifier}
+%D \dosetpositionwhd {identifier} {width} {height} {depth}
+%D \dosetpositionplus {identifier} {width} {height} {depth} {list}
+%D \stoptyping
+
+\def\dosaveposition #1#2#3#4{\clf_dosaveposition {#1}#2 #3 #4\relax}
+\def\dosavepositionwhd #1#2#3#4#5#6#7{\clf_dosavepositionwhd {#1}#2 #3 #4 #5 #6 #7\relax}
+\def\dosavepositionplus#1#2#3#4#5#6#7#8{\clf_dosavepositionplus{#1}#2 #3 #4 #5 #6 #7{#8}}
+
+\def\dosetposition #1{\clf_dosetposition {#1}} % {} expands
+\def\dosetpositionwhd #1#2#3#4{\clf_dosetpositionwhd {#1}#2 #3 #4\relax}
+\def\dosetpositionplus#1#2#3#4#5{\clf_dosetpositionplus {#1}#2 #3 #4{#5}}
+\def\dosetpositionbox #1#2{\clf_dosetpositionbox {#1}#2\relax}
+\def\dosetpositionstrut #1{\clf_dosetpositionstrut{#1}}
+
+\newbox\b_anch_position
+\newif \ifpositioning % sort of public
+
+%D Sometimes we want to trick the position handler a bit:
+
+\def\replacepospxywhd#1#2#3#4#5#6#7% when used we can better make a helper
+ {\clf_replacepospxywhd{#1}#2 #3 #4 #5 #6 #7\relax}
+
+%D \macros
+%D {MPp, MPx, MPy, MPw, MPh, MPd, MPxy, MPll, MPlr, MPur, MPul, MPpos, MPanchor}
+%D
+%D Access to the positional information is provided by macros with short names
+%S that are clearly meant for \METAPOST\ but nowadays also used for other purposes.
+
+\def\MPp #1{\clf_MPp {#1}}
+\def\MPr #1{\clf_MPr {#1}}
+\def\MPc #1{\clf_MPc {#1}}
+\def\MPn #1{\clf_MPn {#1}}
+\def\MPx #1{\clf_MPx {#1}}
+\def\MPy #1{\clf_MPy {#1}}
+\def\MPw #1{\clf_MPw {#1}}
+\def\MPh #1{\clf_MPh {#1}}
+\def\MPd #1{\clf_MPd {#1}}
+\def\MPxy #1{\clf_MPxy {#1}}
+\def\MPll #1{\clf_MPll {#1}}
+\def\MPlr #1{\clf_MPlr {#1}}
+\def\MPur #1{\clf_MPur {#1}}
+\def\MPul #1{\clf_MPul {#1}}
+\def\MPpos #1{\clf_MPpos {#1}}
+\def\MPls #1{\clf_MPls {#1}}
+\def\MPrs #1{\clf_MPrs {#1}}
+\def\MPpardata#1{\clf_MPpardata{#1}}
+\def\MPxywhd #1{\clf_MPxywhd {#1}}
+\def\MPposset #1{\clf_MPposset {#1}}
+
+\let\MPpage \MPp
+\let\MPregion \MPr
+\let\MPcolumn \MPc
+\let\MPparagraph\MPn
+
+\let\MPanchor \MPpos % overloaded locally when needed
+\let\MPleftskip \MPls % compatible feature
+\let\MPrightkip \MPrs % compatible feature
+
+%D \macros
+%D {MPplus, MPrest, MPv, MPvv}
+%D
+%D Since we will probably keep on extending, we provide a general extension
+%D macro. The plus alternative takes an extra argument, denoting what additional
+%D parameter to pick up. So, the third extra is fetched with,
+%D
+%D \starttyping
+%D \MPplus{identifier}{3}{default}
+%D \stoptyping
+%D
+%D All extras (comma separated) are fetched with:
+%D
+%D \starttyping
+%D \MPrest{identifier}
+%D \stoptyping
+%D
+%D The extra parameters are not treated.
+
+\def\MPplus#1#2#3{\clf_MPplus{#1}#2{#3}} \let\MPv \MPplus
+\def\MPrest #1#2{\clf_MPrest{#1}{#2}} \let\MPvv\MPrest
+
+%D There are two low level positioning macros. Both store the position as well
+%D as execute an action associated with that position.
+
+\let\dopositionaction\gobbleoneargument % implemented later
+
+\def\anch_positions_initialize
+ {\ifpositioning \else
+ \global\positioningtrue
+ \fi}
+
+\unexpanded\def\setpositiononly
+ {\iftrialtypesetting
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\anch_positions_set_only_indeed
+ \fi}
+
+\def\anch_positions_set_only_indeed#1%
+ {\anch_positions_initialize
+ \edef\currentposition{#1}%
+ \dosetposition\currentposition}
+
+\unexpanded\def\setposition
+ {\iftrialtypesetting
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\anch_positions_set_indeed
+ \fi}
+
+\def\anch_positions_set_indeed#1%
+ {\anch_positions_initialize
+ \edef\currentposition{#1}%
+ \dosetposition\currentposition
+ \anch_positions_trace_left
+ \dopositionaction\currentposition}
+
+\unexpanded\def\setpositiondata
+ {\iftrialtypesetting
+ \expandafter\gobblefourarguments
+ \else
+ \expandafter\anch_positions_set_data_indeed
+ \fi}
+
+\def\anch_positions_set_data_indeed#1#2#3#4%
+ {\anch_positions_initialize
+ \hbox
+ {\edef\currentposition{#1}%
+ \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr
+ \anch_positions_trace_left
+ \dopositionaction\currentposition
+ \hss}}
+
+\unexpanded\def\setpositionbox
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_box_nop
+ \else
+ \expandafter\anch_positions_set_box_yes
+ \fi}
+
+\def\anch_positions_set_box_nop#1%
+ {\dowithnextboxcs\flushnextbox}
+
+\def\anch_positions_set_box_yes#1%
+ {\dowithnextbox{\anch_positions_set_box_finish{#1}}}
+
+\def\anch_positions_set_box_finish#1%
+ {\anch_positions_initialize
+ \hbox to \wd\nextbox
+ {\edef\currentposition{#1}%
+ \dosetpositionbox\currentposition\nextbox
+ \anch_positions_trace_left
+ \setbox\b_anch_position\box\nextbox
+ \dopositionaction\currentposition
+ \box\b_anch_position
+ \hss}}
+
+\unexpanded\def\setpositionstrut
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_strut_nop
+ \else
+ \expandafter\anch_positions_set_strut_yes
+ \fi}
+
+\def\anch_positions_set_strut_nop#1%
+ {\strut}
+
+\def\anch_positions_set_strut_yes#1%
+ {\anch_positions_initialize
+ \hbox to \zeropoint
+ {\edef\currentposition{#1}%
+ \dosetpositionstrut\currentposition
+ \anch_positions_trace_left
+ \dopositionaction\currentposition
+ \strut
+ \hss}}
+
+\unexpanded\def\setpositiondataplus
+ {\iftrialtypesetting
+ \expandafter\gobblefivearguments
+ \else
+ \expandafter\anch_positions_set_plus_indeed
+ \fi}
+
+\def\anch_positions_set_plus_indeed#1#2#3#4#5%
+ {\anch_positions_initialize
+ \hbox % just package
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr
+ \anch_positions_trace_right
+ \dopositionaction\currentposition
+ \hss}}
+
+\unexpanded\def\setpositionplus
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_plus_nop
+ \else
+ \expandafter\anch_positions_set_plus_yes
+ \fi}
+
+\def\anch_positions_set_plus_nop#1#2%
+ {\dowithnextboxcs\flushnextbox}
+
+\def\anch_positions_set_plus_yes#1#2%
+ {\dowithnextbox{\anch_positions_set_plus_yes_finish{#1}{#2}}}
+
+\def\anch_positions_set_plus_yes_finish#1#2%
+ {\anch_positions_initialize
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition{\wd\nextbox}{\ht\nextbox}{\dp\nextbox}{#2}%
+ \anch_positions_trace_right
+ \setbox\b_anch_position\flushnextbox
+ \dopositionaction\currentposition
+ \box\b_anch_position
+ \hss}}
+
+\let\currentposition\s!unknown
+
+%D A few special ones .. will be cleaned up
+
+\def\pageanchor {page:\the\realpageno} % for the moment only one pagesize
+\def\textanchor {text:\the\realpageno}
+\def\regionanchor{region:0}
+
+\newcount\c_anch_column % will be delegated to lua
+\newcount\c_anch_text % will be delegated to lua
+
+% beware we need to pass \somethingexpanded or { }
+
+\unexpanded\def\anch_mark_column_box#1%
+ {\global\advance\c_anch_column\plusone
+ \clf_markregionboxtagged#1{columnarea:\the\c_anch_column}} % extra height
+
+\unexpanded\def\anch_mark_region_box
+ {\iftrialtypesetting
+ \singleexpandafter\gobbleoneargument
+ \else\ifpositioning
+ \doubleexpandafter\anch_mark_region_box_indeed
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+\unexpanded\def\anch_mark_region_box_indeed#1%
+ {\clf_markregionbox#1\relax}
+
+\unexpanded\def\anch_mark_flow_box#1% will be extended / renamed
+ {\hbox\bgroup
+ \global\advance\c_anch_text\plusone
+ \clf_markregionboxtagged#1{textarea:\the\c_anch_text}%
+ \box#1%
+ \egroup}
+
+\unexpanded\def\anch_mark_tagged_box#1#2%
+ {\clf_markregionboxtagged#1{#2}}
+
+\unexpanded\def\anch_mark_flow_only#1% will be extended / renamed
+ {\global\advance\c_anch_text\plusone
+ \clf_markregionboxcorrected#1{textarea:\the\c_anch_text}}
+
+\unexpanded\def\anch_make_page_box#1% maybe like text
+ {\clf_setregionboxtagged#1{page:\the\realpageno}}
+
+\unexpanded\def\anch_mark_text_box#1%
+ {\clf_markregionboxtagged#1{text:\the\realpageno}} % needs an hbox
+
+%D We can copy a position with:
+%D
+%D \starttyping
+%D \copyposition {to} {from}
+%D \stoptyping
+%D
+%D Again, this is a global operation.
+
+\unexpanded\def\copyposition#1#2%
+ {\clf_copyposition{#1}{#2}}
+
+%D The fact that handling positions is a two pass operation, is one of the
+%D reasons why we need to be able to test for existence, using:
+%D
+%D \starttyping
+%D \doifpositionelse {identifier} {found action} {not found action}
+%D \stoptyping
+
+\unexpanded\def\doifposition #1{\clf_doifposition {#1}}
+\unexpanded\def\doifelseposition #1{\clf_doifelseposition {#1}}
+\unexpanded\def\doifelsepositiononpage#1#2{\clf_doifelsepositiononpage{#1}#2\relax}
+
+\let\doifpositionelse \doifelseposition
+\let\doifpositiononpageelse\doifelsepositiononpage
+
+%D \macros
+%D {xypos}
+%D
+%D We have several macros available to save positions. Later we will see
+%D applications.
+%D
+%D \starttabulate[|l|l||]
+%D \NC \type {\xypos} \NC \NC simple position with no dimensions \NC \NR
+%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR
+%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR
+%D \NC \type {\bpos} \NC b: \NC begin point in a line \NC \NR
+%D \NC \type {\epos} \NC e: \NC end point in a line \NC \NR
+%D \stoptabulate
+%D
+%D Each macro takes an identifier as argument, and the \type {\hpos} and
+%D \type {\vpos} also expect box content.
+
+\let\xypos\setpositiononly
+
+\unexpanded\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
+\unexpanded\def\vpos#1{\setpositionbox{#1}\vbox}
+\unexpanded\def\bpos#1{\dontleavehmode \setpositionstrut{b:#1}\ignorespaces}
+\unexpanded\def\epos#1{\removeunwantedspaces\setpositionstrut{e:#1}}
+
+%D When we want to calculate more complex backgrounds, we need to know what the
+%D current indentation scheme is. At the cost of many positions and memory, we
+%D can keep track of them. This mechanism is activated automatically based on
+%D information collected in the previous pass.
+
+\newtoks \t_anch_positions_tracers
+\newcount\c_anch_positions_paragraph
+
+\unexpanded\def\tracepositions
+ {\the\t_anch_positions_tracers}
+
+\unexpanded\def\enableparpositions % global
+ {\global\let\registerparoptions\doregisterparoptions
+ \global\positioningtrue}
+
+\let\disableparpositions\relax
+
+\let\registerparoptions\relax
+
+\unexpanded\def\doregisterparoptions
+ {\iftrialtypesetting \else
+ \ifinpagebody \else \ifmmode \else \ifinformula \else
+ \anch_positions_register_par_options
+ \fi \fi \fi
+ \fi}
+
+\def\anch_positions_register_par_options_normal
+ {\dontleavehmode\clf_parpos}
+
+\def\anch_positions_register_par_options_traced
+ {\anch_positions_register_par_options_normal
+ \smashedhbox to \zeropoint
+ {\hss
+ \startcolor[blue]%
+ \llap{\infofont\number\c_anch_positions_paragraph}%
+ \vrule
+ \s!width 4\onepoint
+ \s!height2\onepoint
+ \s!depth 2\onepoint
+ \stopcolor
+ \hss}}
+
+\let\anch_positions_register_par_options\anch_positions_register_par_options_normal
+
+\appendtoks
+ \let\anch_positions_register_par_options\anch_positions_register_par_options_traced
+\to \t_anch_positions_tracers
+
+\unexpanded\def\anch_positions_trace#1#2#3%
+ {\smashedhbox
+ {#1{\infofont#2#3}%
+ \kern-\onepoint
+ \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}}
+
+\unexpanded\def\anch_positions_trace_left_indeed
+ {\anch_positions_trace\llap\darkmagenta{\currentposition>}}
+
+\unexpanded\def\anch_positions_trace_right_indeed
+ {\anch_positions_trace\rlap\darkcyan{<\currentposition}}
+
+\let\anch_positions_trace_left \relax
+\let\anch_positions_trace_right\relax
+
+\appendtoks
+ \let\anch_positions_trace_left \anch_positions_trace_left_indeed
+ \let\anch_positions_trace_right \anch_positions_trace_right_indeed
+\to \t_anch_positions_tracers
+
+% \appendtoks \registerparoptions \to \everypar
+
+%D \macros
+%D {doifoverlappingelse}
+%D
+%D A first application of positional information, is to determine if two
+%D boxes do overlap:
+%D
+%D \starttyping
+%D \doifoverlappingelse{point a}{point b}
+%D {action when overlapping}
+%D {action when not overlapping}
+%D \stoptyping
+
+\unexpanded\def\doifelseoverlapping#1#2{\clf_doifelseoverlapping{#1}{#2}}
+
+\let\doifoverlappingelse\doifelseoverlapping
+
+%D \macros
+%D {doifpositionsonsamepageelse,
+%D doifpositionsonthispageelse}
+%D
+%D Instead of letting the user handle fuzzy expansion, we provide a simple test on
+%D positions being on the same page.
+%D
+%D \starttyping
+%D \doifpositionsonsamepageelse{point a}{point b}
+%D {action when on same page}
+%D {action when not on same page}
+%D \doifpositionsonthispageelse{point a}{point b}
+%D {action when on this page}
+%D {action when not on this page}
+%D \stoptyping
+
+\unexpanded\def\doifelsepositionsonsamepage#1{\clf_doifelsepositionsonsamepage{#1}}
+\unexpanded\def\doifelsepositionsonthispage#1{\clf_doifelsepositionsonthispage{#1}}
+
+\let\doifpositionsonsamepageelse\doifelsepositionsonsamepage
+\let\doifpositionsonthispageelse\doifelsepositionsonthispage
+
+%D Moved here:
+
+\unexpanded\def\doifelsepositionsused{\clf_doifelsepositionsused}
+
+\let\doifpositionsusedelse\doifelsepositionsused
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv
new file mode 100644
index 00000000000..d0d3a58d1f3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv
@@ -0,0 +1,205 @@
+%D \module
+%D [ file=anch-snc,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Synchronization,
+%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.
+
+% this can be optimized (will do when used again)
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Synchronization}
+
+\unprotect
+
+\ifx\s!num \undefined \def\s!num {num} \fi
+\ifx\s!set \undefined \def\s!set {set} \fi
+\ifx\s!reset \undefined \def\s!reset {reset} \fi
+\ifx\s!preset \undefined \def\s!preset {preset} \fi
+\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi
+
+\unexpanded\def\definesyncpositions[#1]%
+ {\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}}%
+ \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
+
+\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}%
+ \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
+
+\protect
+
+\continueifinputfile{anch-snc.mkiv}
+
+\starttext
+
+\setupbodyfont[dejavu]
+
+\definesyncpositions[1]
+
+\startuseMPgraphic{sync}
+ if unknown context_abck : input mp-abck.mpiv ; fi ;
+ StartPage ;
+ \getsyncpositions{1} ;
+ SyncThreshold := 2LineHeight ;
+ 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 ;
+\stopuseMPgraphic
+
+\defineoverlay[tempoverlay][\useMPgraphic{sync}]
+
+\setupbackgrounds[page][background=tempoverlay]
+
+\dorecurse {10} {
+
+ \startchapter[title={Test #1}]
+ \syncposition[1][1] \dorecurse{10}{\input ward \endgraf}
+ \syncposition[1][2] \dorecurse {4}{\input ward \endgraf}
+ \syncposition[1][3] \dorecurse {7}{\input ward \endgraf}
+ \syncposition[1][4] \dorecurse {3}{\input ward \endgraf}
+ \stopchapter
+}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv
new file mode 100644
index 00000000000..7e0116cbff6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv
@@ -0,0 +1,383 @@
+%D \module
+%D [ file=anch-pgr, % moved from anch-pgr (1999.08.01)
+%D version=2011.12.19, % 1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Table Extensions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Table Extensions}
+
+%D This is just a playground and functionality might change or even
+%D dissappear in favour of better solutions.
+
+\unprotect
+
+\newcount\c_anch_tabs
+
+\unexpanded\def\tabl_tabulate_hook_b
+ {\iftrialtypesetting\else
+ \ifpositioning
+ \ifcase\c_tabl_tabulate_noflines % \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines
+ \tabl_tabulate_hook_b_first
+ \else
+ \tabl_tabulate_hook_b_next
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hook_e
+ {\iftrialtypesetting\else
+ \ifpositioning
+ \ifcase\c_tabl_tabulate_noflines % \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines
+ \tabl_tabulate_hook_e_first
+ \else
+ \tabl_tabulate_hook_e_next
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hook_b_first
+ {\clf_bposcolumnregistered{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}}
+
+\unexpanded\def\tabl_tabulate_hook_b_next
+ {\clf_bposcolumn{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}}
+
+\unexpanded\def\tabl_tabulate_hook_e_first
+ {\clf_eposcolumnregistered}
+
+\unexpanded\def\tabl_tabulate_hook_e_next
+ {\clf_eposcolumn}
+
+% \appendtoks \registerparoptions \to \everypar
+
+\appendtoks
+ \global\advance\c_anch_tabs\plusone
+\to \everytabulate
+
+%D Beware, the following code is somewhat weird and experimental and might be
+%D dropped or become a loadable module.
+
+%D \macros
+%D {GFC, GTC, GSC}
+%D
+%D The next macros extend tables and tabulation with backgrounds and position
+%D related features. Areas are specified with symbolic names, and symbolic
+%D references to the graphics involved. Each table has its own namespace.
+
+\newconditional\tablehaspositions
+\newcount \noftabpositions
+\newtoks \posXCtoks
+
+\def\anch_tabulate_bpos{\bpos}
+\def\anch_tabulate_epos{\epos}
+
+\installcorenamespace{positiontables}
+
+\def\tbPOSprefix
+ {\??positiontables\number\noftabpositions:}
+
+\def\tablepos
+ {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}}
+
+\let\tabulatepos\tablepos
+
+\unexpanded\def\tbXC {\dosingleempty\anch_tables_XC }
+\unexpanded\def\tbGSC{\dosingleempty\anch_tables_GSC}
+\unexpanded\def\tbGFC{\dosingleempty\anch_tables_GFC}
+\unexpanded\def\tbGTC{\dosingleempty\anch_tables_GTC}
+
+\def\anch_table_check_state
+ {\iftrialtypesetting
+ \global\settrue\tablehaspositions
+ \firstargumentfalse
+ \fi}
+
+\def\anch_tables_XC [#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_XC [#1]\else\expandafter\fi\NC}
+\def\anch_tables_GSC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GFC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GTC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi}
+
+\def\anch_tables_indeed_XC[#1]%
+ {{\let\NC\relax\processcommalist[#1]\anch_tables_step_XC}}
+
+\def\anch_tables_step_XC#1%
+ {\anch_tables_step_indeed_XC[#1]}
+
+\def\anch_tables_step_indeed_XC[#1#2]%
+ {\if#1>\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1+\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1<\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1-\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1=\anch_tables_indeed_GSC [#2:#2]\else
+ \anch_tables_indeed_GSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
+
+\def\anch_tables_indeed_GSC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GSC}
+
+\def\anch_tables_step_GSC#1%
+ {\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}
+
+\def\anch_tables_process_GSC[#1:#2]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}%
+ \doglobal\appendtoks\@EA\anch_tabulate_epos\@EA{\tbPOSprefix#1}\to\posXCtoks}
+
+\def\anch_tables_indeed_GFC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC}
+
+\def\anch_tables_delayed_GFC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GFC}
+
+\def\anch_tables_step_GFC#1%
+ {\anch_tables_process_GFC[#1:#1]}
+
+\def\anch_tables_process_GFC[#1:#2:#3]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}}
+
+\def\anch_tables_indeed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC}
+
+\def\anch_tables_delayed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks}
+
+\def\anch_tables_process_GTC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GTC}
+
+\def\anch_tables_step_GTC#1%
+ {\anch_tables_step_indeed_GTC[#1:#1]}
+
+\def\anch_tables_step_indeed_GTC[#1:#2]%
+ {\anch_tabulate_epos{\tbPOSprefix#1}}
+
+%D The amount of code to support tables and tabulation is rather
+%D minimalistic.
+
+\let\tabulatepos\tablepos
+
+\def\tabulatenormalpos
+ {\iftrialtypesetting
+ % nothing
+ \else\ifconditional\tablehaspositions
+ \hss\tabulatepos\hss
+ \else
+ % nothing
+ \fi\fi}
+
+\def\tabulateequalpos
+ {\iftrialtypesetting
+ \tabulateEQ
+ \else\ifconditional\tablehaspositions
+ \tabulateEQpos
+ \else
+ \tabulateEQ
+ \fi\fi}
+
+\def\tabulateEQpos
+ {\setbox\scratchbox\hbox{\tabulateEQ}%
+ \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}% hpack
+ \kern-\wd\scratchbox
+ \box\scratchbox}
+
+\appendtoks
+ \global\advance\noftabpositions\plusone
+ \global\setfalse\tablehaspositions
+\to \everytabulate
+
+% We need to handle paragraphs as well.
+
+\let\anch_tabulate_flush_epos\relax
+
+\def\anch_tabulate_bpos_indeed
+ {\bpos}
+
+\def\anch_tabulate_epos_indeed#1%
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ \epos{#1}%
+ \glet\anch_tabulate_flush_epos\relax
+ \else
+ \gdef\anch_tabulate_flush_epos{\epos{#1}}%
+ \fi}
+
+\def\flushtabulatesplitbox
+ {\box\b_tabl_tabulate
+ \iftrialtypesetting\else\ifconditional\tablehaspositions\anch_tabulate_flush_epos\fi\fi}
+
+\appendtoks
+ \let\anch_tabulate_bpos\anch_tabulate_bpos_indeed % ?
+ \let\anch_tabulate_epos\anch_tabulate_epos_indeed % ?
+ \glet\anch_tabulate_flush_epos\relax
+\to \everytabulate
+
+%D In order to prevent potential clashes with abbreviations, postpone the mapping.
+
+\appendtoks
+ \let\GSC\tbGSC
+ \let\GFC\tbGFC
+ \let\GTC\tbGTC
+ \let\XC \tbXC
+\to \everytabulate
+
+%D \macros
+%D {definepositionframed}
+%D
+%D The next example show how to provide backgrounds to table cells. First we define
+%D some framed backgrounds.
+%D
+%D \startbuffer
+%D \definepositionframed[x][background=color,backgroundcolor=red]
+%D \definepositionframed[y][background=color,backgroundcolor=green]
+%D \definepositionframed[z][background=color,backgroundcolor=blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D % \getbuffer
+%D
+%D \startbuffer
+%D \starttabulate[|c|c|c|]
+%D \GFC[f:x] this is a small \NC table \NC in which we \NC \FR
+%D \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+%D \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D The table itself defines three areas (a, b and~c) using these frames.
+%D
+%D \typebuffer
+%D % \getbuffer
+%D
+%D Tables (based on \TABLE) are supported by:
+
+\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&} % |
+\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \|
+\def\normalTABLEquote {\unskip\!ttRightGlue&\omit\tablepos&} % "
+
+\appendtoks
+ \global\advance\noftabpositions\plusone
+ \global\setfalse\tablehaspositions
+\to \everytable
+
+%D Since we don't want nameclashes:
+
+\appendtoks
+ \let\GSC\tbGSC
+ \let\GFC\tbGFC
+ \let\GTC\tbGTC
+ \let\XC \tbXC
+\to \everytable
+
+%D In the previous example, we could have provided an overlay to the framed definition.
+%D A more direct approach is demonstrated below:
+%D
+%D \startbuffer
+%D \def\cw#1{\color[white]{#1}}
+%D
+%D \startMPpositiongraphic{tableshade}
+%D initialize_area(\MPpos{\MPvar{from}},\MPpos{\MPvar{to}}) ;
+%D color c ; c := \MPvar{color} ;
+%D linear_shade(pxy,0,.4c,.9c) ;
+%D anchor_area(\MPanchor{\MPvar{from}}) ;
+%D \stopMPpositiongraphic
+%D
+%D \setMPpositiongraphic{b:x}{tableshade}{from=b:x,to=e:x,color=red}
+%D \setMPpositiongraphic{b:y}{tableshade}{from=b:y,to=e:y,color=green}
+%D \setMPpositiongraphic{b:z}{tableshade}{from=b:z,to=e:z,color=blue}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The definition of the table looks about the same as the previous one:
+%D
+%D \startbuffer
+%D \starttable[|c|c|c|]
+%D \GFC[b:z] \cw{this is a small} \NC \cw{table} \NC in which we \NC \FR
+%D \NC \cw{will demonstrate} \GFC[c:y] \cw{that this} \GTC[c] \cw{positioning} \NC \MR
+%D \GSC[a:x] \cw{mechanism also} \GTC[b] \cw{works quite well} \NC in tables \NC \LR
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+% \definepositionframed[w][background=color,backgroundcolor=yellow]
+% \definepositionframed[x][background=color,backgroundcolor=red]
+% \definepositionframed[y][background=color,backgroundcolor=green]
+% \definepositionframed[z][background=color,backgroundcolor=blue]
+%
+% \starttabulate[|c|c|c|]
+% \NC this is a small \NC table \NC in which we \NC \FR
+% \NC will demonstrate \NC that this \NC positioning \NC \MR
+% \NC mechanism also \NC works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \GFC[f:x] this is a small \GTC table \NC in which we \NC \FR
+% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \GFC[f:x,d:w] this is a small \GTC[d] table \NC in which we \NC \FR
+% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \XC[+f:x] this is a small \XC table \NC in which we \NC \FR
+% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
+% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \XC[+f:x,+d:w] this is a small \XC[-d] table \NC in which we \NC \FR
+% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
+% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+
+% evt [b:x]
+%
+% \definepositionframed[x][background=color,fillcolor=red]
+% \definepositionframed[y][background=color,fillcolor=green]
+% \definepositionframed[z][background=color,fillcolor=blue]
+
+\unexpanded\def\remappositionframed#1#2% from to
+ {\copyposition{b:#1}{b:#2}%
+ \copyposition{e:#1}{e:#2}%
+ \anch_positions_set_action{b:#2}{\dopositionaction{b:#1}}}
+
+\unexpanded\def\definepositionframed
+ {\dodoubleargument\anch_framed_define}
+
+\def\anch_framed_define[#1][#2]%
+ {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}}
+
+\unexpanded\def\anch_framed_handle
+ {\bgroup
+ \anch_framed_indeed}
+
+\unexpanded\def\positionframed
+ {\bgroup
+ \dodoubleempty\anch_framed_indeed}
+
+\def\anch_framed_indeed[#1][#2]%
+ {\setbox\scratchbox\hpack
+ {\scratchwidth \dimexpr\MPx{e:#1}-\MPx{b:#1}\relax
+ \scratchdepth \dimexpr\MPy{b:#1}-\MPy{e:#1}+\MPd{e:#1}\relax
+ \scratchheight\dimexpr\scratchdepth+\MPh{b:#1}\relax
+ \lower\scratchdepth\hpack
+ {\framed[\c!width=\scratchwidth,\c!height=\scratchheight,\c!offset=\v!overlay,#2]{}}}%
+ \smashedbox\scratchbox
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua
new file mode 100644
index 00000000000..6b11333a7b9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua
@@ -0,0 +1,587 @@
+if not modules then modules = { } end modules ['attr-col'] = {
+ version = 1.001,
+ comment = "companion to attr-col.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module is being reconstructed and code will move to other places
+-- we can also do the nsnone via a metatable and then also se index 0
+
+-- list could as well refer to the tables (instead of numbers that
+-- index into another table) .. depends on what we need
+
+local type = type
+local format = string.format
+local concat = table.concat
+local min, max, floor = math.min, math.max, math.floor
+
+local attributes = attributes
+local nodes = nodes
+local utilities = utilities
+local logs = logs
+local backends = backends
+local storage = storage
+local context = context
+local tex = tex
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local report_attributes = logs.reporter("attributes","colors")
+local report_colors = logs.reporter("colors","support")
+local report_transparencies = logs.reporter("transparencies","support")
+
+-- todo: document this but first reimplement this as it reflects the early
+-- days of luatex / mkiv and we have better ways now
+
+-- nb: attributes: color etc is much slower than normal (marks + literals) but ...
+-- nb. too many "0 g"s
+
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local registrations = backends.registrations
+local unsetvalue = attributes.unsetvalue
+
+local registerstorage = storage.register
+local formatters = string.formatters
+
+local interfaces = interfaces
+local implement = interfaces.implement
+
+-- We can distinguish between rules and glyphs but it's not worth the trouble. A
+-- first implementation did that and while it saves a bit for glyphs and rules, it
+-- costs more resourses for transparencies. So why bother.
+
+--
+-- colors
+--
+
+-- we can also collapse the two attributes: n, n+1, n+2 and then
+-- at the tex end add 0, 1, 2, but this is not faster and less
+-- flexible (since sometimes we freeze color attribute values at
+-- the lua end of the game)
+--
+-- we also need to store the colorvalues because we need then in mp
+--
+-- This is a compromis between speed and simplicity. We used to store the
+-- values and data in one array, which made in neccessary to store the
+-- converters that need node constructor into strings and evaluate them
+-- at runtime (after reading from storage). Think of:
+--
+-- colors.strings = colors.strings or { }
+--
+-- if environment.initex then
+-- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")"
+-- end
+--
+-- registerstorage("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated
+--
+-- We assume that only processcolors are defined in the format.
+
+attributes.colors = attributes.colors or { }
+local colors = attributes.colors
+
+local a_color = attributes.private('color')
+local a_selector = attributes.private('colormodel')
+
+colors.data = allocate()
+colors.values = colors.values or { }
+colors.registered = colors.registered or { }
+colors.weightgray = true
+colors.attribute = a_color
+colors.selector = a_selector
+colors.default = 1
+colors.main = nil
+colors.triggering = true
+colors.supported = true
+colors.model = "all"
+
+local data = colors.data
+local values = colors.values
+local registered = colors.registered
+
+local numbers = attributes.numbers
+local list = attributes.list
+
+registerstorage("attributes/colors/values", values, "attributes.colors.values")
+registerstorage("attributes/colors/registered", registered, "attributes.colors.registered")
+
+local f_colors = {
+ rgb = formatters["r:%s:%s:%s"],
+ cmyk = formatters["c:%s:%s:%s:%s"],
+ gray = formatters["s:%s"],
+ spot = formatters["p:%s:%s:%s:%s"],
+}
+
+local models = {
+ [interfaces.variables.none] = unsetvalue,
+ black = unsetvalue,
+ bw = unsetvalue,
+ all = 1,
+ gray = 2,
+ rgb = 3,
+ cmyk = 4,
+}
+
+local function rgbtocmyk(r,g,b) -- we could reduce
+ if not r then
+ return 0, 0, 0
+ else
+ return 1-r, 1-g, 1-b, 0
+ end
+end
+
+local function cmyktorgb(c,m,y,k)
+ if not c then
+ return 0, 0, 0, 1
+ else
+ return 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+ end
+end
+
+local function rgbtogray(r,g,b)
+ if not r then
+ return 0
+ elseif colors.weightgray then
+ return .30*r + .59*g + .11*b
+ else
+ return r/3 + g/3 + b/3
+ end
+end
+
+local function cmyktogray(c,m,y,k)
+ return rgbtogray(cmyktorgb(c,m,y,k))
+end
+
+-- not critical so not needed:
+--
+-- local function cmyktogray(c,m,y,k)
+-- local r, g, b = 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+-- if colors.weightgray then
+-- return .30*r + .59*g + .11*b
+-- else
+-- return r/3 + g/3 + b/3
+-- end
+-- end
+
+-- http://en.wikipedia.org/wiki/HSI_color_space
+-- http://nl.wikipedia.org/wiki/HSV_(kleurruimte)
+
+local function hsvtorgb(h,s,v)
+ -- h = h % 360
+ local hd = h/60
+ local hf = floor(hd)
+ local hi = hf % 6
+ -- local f = hd - hi
+ local f = hd - hf
+ local p = v * (1 - s)
+ local q = v * (1 - f * s)
+ local t = v * (1 - (1 - f) * s)
+ if hi == 0 then
+ return v, t, p
+ elseif hi == 1 then
+ return q, v, p
+ elseif hi == 2 then
+ return p, v, t
+ elseif hi == 3 then
+ return p, q, v
+ elseif hi == 4 then
+ return t, p, v
+ elseif hi == 5 then
+ return v, p, q
+ else
+ print("error in hsv -> rgb",hi,h,s,v)
+ end
+end
+
+local function rgbtohsv(r,g,b)
+ local offset, maximum, other_1, other_2
+ if r >= g and r >= b then
+ offset, maximum, other_1, other_2 = 0, r, g, b
+ elseif g >= r and g >= b then
+ offset, maximum, other_1, other_2 = 2, g, b, r
+ else
+ offset, maximum, other_1, other_2 = 4, b, r, g
+ end
+ if maximum == 0 then
+ return 0, 0, 0
+ end
+ local minimum = other_1 < other_2 and other_1 or other_2
+ if maximum == minimum then
+ return 0, 0, maximum
+ end
+ local delta = maximum - minimum
+ return (offset + (other_1-other_2)/delta)*60, delta/maximum, maximum
+end
+
+local function graytorgb(s) -- unweighted
+ return 1-s, 1-s, 1-s
+end
+
+local function hsvtogray(h,s,v)
+ return rgb_to_gray(hsv_to_rgb(h,s,v))
+end
+
+local function graytohsv(s)
+ return 0, 0, s
+end
+
+colors.rgbtocmyk = rgbtocmyk
+colors.rgbtogray = rgbtogray
+colors.cmyktorgb = cmyktorgb
+colors.cmyktogray = cmyktogray
+colors.rgbtohsv = rgbtohsv
+colors.hsvtorgb = hsvtorgb
+colors.hsvtogray = hsvtogray
+colors.graytohsv = graytohsv
+
+-- we can share some *data by using s, rgb and cmyk hashes, but
+-- normally the amount of colors is not that large; storing the
+-- components costs a bit of extra runtime, but we expect to gain
+-- some back because we have them at hand; the number indicates the
+-- default color space
+
+function colors.gray(s)
+ return { 2, s, s, s, s, 0, 0, 0, 1-s }
+end
+
+function colors.rgb(r,g,b)
+ local s = rgbtogray(r,g,b)
+ local c, m, y, k = rgbtocmyk(r,g,b)
+ return { 3, s, r, g, b, c, m, y, k }
+end
+
+function colors.cmyk(c,m,y,k)
+ local s = cmyktogray(c,m,y,k)
+ local r, g, b = cmyktorgb(c,m,y,k)
+ return { 4, s, r, g, b, c, m, y, k }
+end
+
+--~ function colors.spot(parent,f,d,p)
+--~ return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
+--~ end
+
+local p_split = lpeg.tsplitat(",")
+local lpegmatch = lpeg.match
+
+function colors.spot(parent,f,d,p)
+ -- inspect(parent) inspect(f) inspect(d) inspect(p)
+ if type(p) == "number" then
+ local n = list[numbers.color][parent] -- hard coded ref to color number
+ if n then
+ 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 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 }
+ end
+ end
+ else
+ -- todo, multitone (maybe p should be a table)
+ local ps = lpegmatch(p_split,p)
+ local ds = lpegmatch(p_split,d)
+ local c, m, y, k = 0, 0, 0, 0
+ local done = false
+ for i=1,#ps do
+ local p = tonumber(ps[i])
+ local d = ds[i]
+ if p and d then
+ local n = list[numbers.color][d] -- hard coded ref to color number
+ if n then
+ local v = values[n]
+ if v then
+ c = c + p*v[6]
+ m = m + p*v[7]
+ y = y + p*v[8]
+ k = k + p*v[8]
+ done = true
+ end
+ end
+ end
+ end
+ if done then
+ local r, g, b = cmyktorgb(c,m,y,k)
+ local s = cmyktogray(c,m,y,k)
+ local f = tonumber(f)
+ return { 5, s, r, g, b, c, m, y, k, parent, f, d, p }
+ end
+ end
+ return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
+end
+
+local function graycolor(...) graycolor = nodeinjections.graycolor return graycolor(...) end
+local function rgbcolor (...) rgbcolor = nodeinjections.rgbcolor return rgbcolor (...) end
+local function cmykcolor(...) cmykcolor = nodeinjections.cmykcolor return cmykcolor(...) end
+local function spotcolor(...) spotcolor = nodeinjections.spotcolor return spotcolor(...) end
+
+local function extender(colors,key)
+ if colors.supported and key == "none" then
+ local d = graycolor(0)
+ colors.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if colors.supported then
+ local v = values[n]
+ local d
+ if not v then
+ local gray = graycolor(0)
+ d = { gray, gray, gray, gray }
+ report_attributes("unable to revive color %a",n)
+ else
+ local model = colors.forcedmodel(v[1])
+ if model == 2 then
+ 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])
+ 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])
+ d = { cmyk, gray, rgb, cmyk }
+ elseif model == 5 then
+ local spot = spotcolor(v[10],v[11],v[12],v[13])
+ -- d = { spot, gray, rgb, cmyk }
+ d = { spot, spot, spot, spot }
+ end
+ end
+ data[n] = d
+ return d
+ end
+end
+
+setmetatableindex(colors, extender)
+setmetatableindex(colors.data, reviver)
+
+function colors.filter(n)
+ return concat(data[n],":",5)
+end
+
+function colors.setmodel(name,weightgray)
+ colors.model = name
+ colors.default = models[name] or 1
+ colors.weightgray = weightgray ~= false
+ return colors.default
+end
+
+function colors.register(name, colorspace, ...) -- passing 9 vars is faster (but not called that often)
+ local stamp = f_colors[colorspace](...)
+ local color = registered[stamp]
+ if not color then
+ color = #values + 1
+ values[color] = colors[colorspace](...)
+ registered[stamp] = color
+ -- colors.reviver(color)
+ end
+ if name then
+ list[a_color][name] = color -- not grouped, so only global colors
+ end
+ return registered[stamp]
+end
+
+function colors.value(id)
+ return values[id]
+end
+
+attributes.colors.handler = nodes.installattributehandler {
+ name = "color",
+ namespace = colors,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.selective,
+ resolver = function() return colors.main end,
+}
+
+function colors.enable(value)
+ if value == false or not colors.supported then
+ tasks.disableaction("shipouts","attributes.colors.handler")
+ else
+ tasks.enableaction("shipouts","attributes.colors.handler")
+ end
+end
+
+function colors.forcesupport(value) -- can move to attr-div
+ colors.supported = value
+ report_colors("color is %ssupported",value and "" or "not ")
+ colors.enable(value)
+end
+
+-- transparencies
+
+local a_transparency = attributes.private('transparency')
+
+attributes.transparencies = attributes.transparencies or { }
+local transparencies = attributes.transparencies
+transparencies.registered = transparencies.registered or { }
+transparencies.data = allocate()
+transparencies.values = transparencies.values or { }
+transparencies.triggering = true
+transparencies.attribute = a_transparency
+transparencies.supported = true
+
+local registered = transparencies.registered -- we could use a 2 dimensional table instead
+local data = transparencies.data
+local values = transparencies.values
+local f_transparency = formatters["%s:%s"]
+
+registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered")
+registerstorage("attributes/transparencies/values", values, "attributes.transparencies.values")
+
+local function inject_transparency(...)
+ inject_transparency = nodeinjections.transparency
+ return inject_transparency(...)
+end
+
+local function register_transparency(...)
+ register_transparency = registrations.transparency
+ return register_transparency(...)
+end
+
+function transparencies.register(name,a,t,force) -- name is irrelevant here (can even be nil)
+ -- Force needed here for metapost converter. We could always force
+ -- but then we'd end up with transparencies resources even if we
+ -- would not use transparencies (but define them only). This is
+ -- somewhat messy.
+ local stamp = f_transparency(a,t)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = { a, t }
+ registered[stamp] = n
+ if force then
+ register_transparency(n,a,t)
+ end
+ elseif force and not data[n] then
+ register_transparency(n,a,t)
+ end
+ if name then
+ list[a_transparency][name] = n -- not grouped, so only global transparencies
+ end
+ return registered[stamp]
+end
+
+local function extender(transparencies,key)
+ if colors.supported and key == "none" then
+ local d = inject_transparency(0)
+ transparencies.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if transparencies.supported then
+ local v = values[n]
+ local d
+ if not v then
+ d = inject_transparency(0)
+ else
+ d = inject_transparency(n)
+ register_transparency(n,v[1],v[2])
+ end
+ data[n] = d
+ return d
+ else
+ return ""
+ end
+end
+
+setmetatableindex(transparencies, extender)
+setmetatableindex(transparencies.data, reviver) -- register if used
+
+-- check if there is an identity
+
+function transparencies.value(id)
+ return values[id]
+end
+
+attributes.transparencies.handler = nodes.installattributehandler {
+ name = "transparency",
+ namespace = transparencies,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function transparencies.enable(value) -- nil is enable
+ if value == false or not transparencies.supported then
+ tasks.disableaction("shipouts","attributes.transparencies.handler")
+ else
+ tasks.enableaction("shipouts","attributes.transparencies.handler")
+ end
+end
+
+function transparencies.forcesupport(value) -- can move to attr-div
+ transparencies.supported = value
+ report_transparencies("transparency is %ssupported",value and "" or "not ")
+ transparencies.enable(value)
+end
+
+--- colorintents: overprint / knockout
+
+attributes.colorintents = attributes.colorintents or { }
+local colorintents = attributes.colorintents
+colorintents.data = allocate() -- colorintents.data or { }
+colorintents.attribute = attributes.private('colorintent')
+
+colorintents.registered = allocate {
+ overprint = 1,
+ knockout = 2,
+}
+
+local data, registered = colorintents.data, colorintents.registered
+
+local function extender(colorintents,key)
+ if key == "none" then
+ local d = data[2]
+ colorintents.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if n == 1 then
+ local d = nodeinjections.overprint() -- called once
+ data[1] = d
+ return d
+ elseif n == 2 then
+ local d = nodeinjections.knockout() -- called once
+ data[2] = d
+ return d
+ end
+end
+
+setmetatableindex(colorintents, extender)
+setmetatableindex(colorintents.data, reviver)
+
+function colorintents.register(stamp)
+ return registered[stamp] or registered.overprint
+end
+
+colorintents.handler = nodes.installattributehandler {
+ name = "colorintent",
+ namespace = colorintents,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function colorintents.enable()
+ tasks.enableaction("shipouts","attributes.colorintents.handler")
+end
+
+-- interface
+
+implement { name = "enablecolor", onlyonce = true, actions = colors.enable }
+implement { name = "enabletransparency", onlyonce = true, actions = transparencies.enable }
+implement { name = "enablecolorintents", onlyonce = true, actions = colorintents.enable }
+
+--------- { name = "registercolor", actions = { colors .register, context }, arguments = "string" }
+--------- { name = "registertransparency", actions = { transparencies.register, context }, arguments = "string" }
+implement { name = "registercolorintent", actions = { colorintents .register, context }, arguments = "string" }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-col.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-col.mkiv
new file mode 100644
index 00000000000..6231755e914
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-col.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=attr-col,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Color,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Color}
+
+\registerctxluafile{attr-col}{1.001}
+
+\unprotect
+
+% We implement this elsewhere but some coce might end up here.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-eff.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-eff.lua
new file mode 100644
index 00000000000..ff41e12de70
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-eff.lua
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['attr-eff'] = {
+ version = 1.001,
+ comment = "companion to attr-eff.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities
+local tex = tex
+
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local texsetattribute = tex.setattribute
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local interfaces = interfaces
+local implement = interfaces.implement
+
+local variables = interfaces.variables
+local v_normal = variables.normal
+
+attributes.effects = attributes.effects or { }
+local effects = attributes.effects
+
+local a_effect = attributes.private('effect')
+
+effects.data = allocate()
+effects.values = effects.values or { }
+effects.registered = effects.registered or { }
+effects.attribute = a_effect
+
+local data = effects.data
+local registered = effects.registered
+local values = effects.values
+
+local f_stamp = formatters["%s:%s:%s"]
+
+storage.register("attributes/effects/registered", registered, "attributes.effects.registered")
+storage.register("attributes/effects/values", values, "attributes.effects.values")
+
+-- valid effects: normal inner outer both hidden (stretch,rulethickness,effect)
+
+local function effect(...) effect = nodeinjections.effect return effect(...) end
+
+local function extender(effects,key)
+ if key == "none" then
+ local d = effect(0,0,0)
+ effects.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local e = values[n] -- we could nil values[n] now but hardly needed
+ local d = effect(e[1],e[2],e[3])
+ data[n] = d
+ return d
+end
+
+setmetatableindex(effects, extender)
+setmetatableindex(effects.data, reviver)
+
+effects.handler = nodes.installattributehandler {
+ name = "effect",
+ namespace = effects,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+local function register(specification)
+ local alternative, stretch, rulethickness
+ if specification then
+ alternative = specification.alternative or v_normal
+ stretch = specification.stretch or 0
+ rulethickness = specification.rulethickness or 0
+ else
+ alternative = v_normal
+ stretch = 0
+ rulethickness = 0
+ end
+ local stamp = f_stamp(alternative,stretch,rulethickness)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = { alternative, stretch, rulethickness }
+ registered[stamp] = n
+ end
+ return n
+end
+
+local enabled = false
+
+local function enable()
+ if not enabled then
+ tasks.enableaction("shipouts","attributes.effects.handler")
+ enabled = true
+ end
+end
+
+effects.register = register
+effects.enable = enable
+
+-- interface
+
+implement {
+ name = "seteffect",
+ actions = function(specification)
+ if not enabled then
+ enable()
+ end
+ texsetattribute(a_effect,register(specification))
+ end,
+ arguments = {
+ {
+ { "alternative", "string" },
+ { "stretch", "integer" },
+ { "rulethickness", "dimen" }
+ }
+ }
+}
+
+implement {
+ name = "reseteffect",
+ actions = function()
+ if enabled then
+ texsetattribute(a_effect,register())
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-eff.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-eff.mkiv
new file mode 100644
index 00000000000..859814ebc23
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-eff.mkiv
@@ -0,0 +1,60 @@
+%D \module
+%D [ file=attr-eff,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Effects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Effects}
+
+\registerctxluafile{attr-eff}{1.001}
+
+\unprotect
+
+\installcorenamespace{effect}
+
+\installcommandhandler \??effect {effect} \??effect
+
+\setupeffect
+ [\c!method=\v!none,
+ \c!stretch=\zerocount,
+ \c!rulethickness=\zeropoint,
+ \c!alternative=\v!normal]
+
+\appendtoks
+ \edef\p_method{\effectparameter\c!method}%
+ \ifx\p_method\v!command
+ \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}%
+ \setuxvalue{\e!stop \currenteffect}{\stopeffect}%
+ \fi
+\to \everydefineeffect
+
+\unexpanded\def\starteffect[#1]%
+ {\clf_seteffect
+ alternative {\namedeffectparameter{#1}\c!alternative}
+ stretch \numexpr\namedeffectparameter{#1}\c!stretch\relax
+ rulethickness \dimexpr\namedeffectparameter{#1}\c!rulethickness\relax
+ \relax}
+
+\unexpanded\def\stopeffect % can be special
+ {\clf_reseteffect} % v!normal 0 0
+
+\unexpanded\def\effect[#1]%
+ {\groupedcommand{\starteffect[#1]}{\stopeffect}}
+
+% yes or no grouped
+
+\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt]
+\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt]
+\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt]
+\defineeffect [\v!normal] [\c!alternative=\v!normal]
+\defineeffect [\v!hidden] [\c!alternative=\v!hidden]
+\defineeffect [\v!stretch] [\c!alternative=\v!stretch,\c!stretch=1]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua
new file mode 100644
index 00000000000..df7404d11b0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua
@@ -0,0 +1,195 @@
+if not modules then modules = { } end modules ['attr-ini'] = {
+ version = 1.001,
+ comment = "companion to attr-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+
+--[[ldx--
+<p>We start with a registration system for atributes so that we can use the
+symbolic names later on.</p>
+--ldx]]--
+
+local nodes = nodes
+local context = context
+local storage = storage
+local commands = commands
+
+local implement = interfaces.implement
+
+attributes = attributes or { }
+local attributes = attributes
+
+local sharedstorage = storage.shared
+
+local texgetcount = tex.getcount
+local texsetattribute = tex.setattribute
+
+attributes.names = attributes.names or { }
+attributes.numbers = attributes.numbers or { }
+attributes.list = attributes.list or { }
+attributes.states = attributes.states or { }
+attributes.handlers = attributes.handlers or { }
+attributes.unsetvalue = -0x7FFFFFFF
+
+local names = attributes.names
+local numbers = attributes.numbers
+local list = attributes.list
+
+storage.register("attributes/names", names, "attributes.names")
+storage.register("attributes/numbers", numbers, "attributes.numbers")
+storage.register("attributes/list", list, "attributes.list")
+
+-- function attributes.define(name,number) -- at the tex end
+-- if not numbers[name] then
+-- numbers[name] = number
+-- names[number] = name
+-- list[number] = { }
+-- end
+-- end
+
+--[[ldx--
+<p>We reserve this one as we really want it to be always set (faster).</p>
+--ldx]]--
+
+names[0], numbers["fontdynamic"] = "fontdynamic", 0
+
+--[[ldx--
+<p>private attributes are used by the system and public ones are for users. We use dedicated
+ranges of numbers for them. Of course a the <l n='context'/> end a private attribute can be
+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_public = sharedstorage.attributes_last_public or 1024 -- less private
+
+function attributes.private(name) -- at the lua end (hidden from user)
+ local number = numbers[name]
+ if not number then
+ local last = sharedstorage.attributes_last_private
+ if last < 1023 then
+ last = last + 1
+ sharedstorage.attributes_last_private = last
+ else
+ report_attribute("no more room for private attributes")
+ os.exit()
+ end
+ number = last
+ numbers[name], names[number], list[number] = number, name, { }
+ end
+ return number
+end
+
+function attributes.public(name) -- at the lua end (hidden from user)
+ local number = numbers[name]
+ if not number then
+ local last = sharedstorage.attributes_last_public
+ if last < 65535 then
+ last = last + 1
+ sharedstorage.attributes_last_public = last
+ else
+ report_attribute("no more room for public attributes")
+ os.exit()
+ end
+ number = last
+ numbers[name], names[number], list[number] = number, name, { }
+ end
+ return number
+end
+
+attributes.system = attributes.private
+
+function attributes.define(name,category)
+ return (attributes[category or "public"] or attributes["public"])(name)
+end
+
+-- tracers
+
+local report_attribute = logs.reporter("attributes")
+
+local function showlist(what,list)
+ if list then
+ local a = list.next
+ local i = 0
+ while a do
+ local number, value = a.number, a.value
+ i = i + 1
+ report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number])
+ a = a.next
+ end
+ end
+end
+
+function attributes.showcurrent()
+ showlist("current",node.current_attr())
+end
+
+function attributes.ofnode(n)
+ showlist(n,n.attr)
+end
+
+-- rather special
+
+local store = { }
+
+function attributes.save(name)
+ name = name or ""
+ local n = node.current_attr()
+ n = n and n.next
+ local t = { }
+ while n do
+ t[n.number] = n.value
+ n = n.next
+ end
+ store[name] = {
+ attr = t,
+ font = font.current(),
+ }
+end
+
+function attributes.restore(name)
+ name = name or ""
+ local t = store[name]
+ if t then
+ local attr = t.attr
+ local font = t.font
+ if attr then
+ for k, v in next, attr do
+ texsetattribute(k,v)
+ end
+ end
+ if font then
+ -- tex.font = font
+ context.getvalue(fonts.hashes.csnames[font]) -- we don't have a direct way yet (will discuss it with taco)
+ end
+ end
+ -- store[name] = nil
+end
+
+implement {
+ name = "defineattribute",
+ arguments = { "string", "string" },
+ actions = { attributes.define, context }
+}
+
+-- interface
+
+implement {
+ name = "showattributes",
+ actions = attributes.showcurrent
+}
+
+implement {
+ name = "savecurrentattributes",
+ arguments = "string",
+ actions = attributes.save
+}
+
+implement {
+ name = "restorecurrentattributes",
+ arguments = "string",
+ actions = attributes.restore
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv
new file mode 100644
index 00000000000..3f0b7fb27e7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv
@@ -0,0 +1,128 @@
+%D \module
+%D [ file=attr-ini,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Initialization}
+
+%D Although it's still somewhat experimental, here we introduce code
+%D related to attributes. Housekeeping will move completely to \LUA\
+%D and \type {\newattribute} will go away.
+
+\unprotect
+
+\registerctxluafile{attr-ini}{1.001}
+
+\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd)
+\installcorenamespace{attributeid} % the internal number
+\installcorenamespace{attributestack} % the attribute specific stack
+
+\unexpanded\def\pushattribute#1%
+ {\global\advance\csname\??attributestack\string#1\endcsname\plusone
+ \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}}
+
+\unexpanded\def\popattribute#1%
+ {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax
+ \global\advance\csname\??attributestack\string#1\endcsname\minusone}
+
+\unexpanded\def\installattributestack#1%
+ {\ifcsname\??attributestack\string#1\endcsname \else
+ \expandafter\newcount\csname\??attributestack\string#1\endcsname
+ \fi}
+
+\newtoks \attributesresetlist
+
+\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
+
+\unexpanded\def\defineattribute {\dodoubleempty\attr_basics_define}
+\unexpanded\def\definesystemattribute{\dodoubleempty\attr_basics_define_system}
+
+\def\attr_basics_define {\attr_basics_define_indeed\s!public}
+\def\attr_basics_define_system{\attr_basics_define_indeed\s!private}
+
+\def\attr_basics_define_indeed#1[#2][#3]%
+ {\ifcsname\??attributecount#2\endcsname\else
+ \scratchcounter\clf_defineattribute{#2}{#1}\relax
+ %\writestatus\m!system{defining #1 attribute #2 with number \number\scratchcounter}%
+ \expandafter\attributedef\csname\??attributecount#2\endcsname\scratchcounter
+ \expandafter\newconstant \csname\??attributeid#2\endcsname
+ \csname\??attributeid#2\endcsname\scratchcounter
+ % some attributes are always global
+ \doifnotinset\s!global{#3}{\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\attributesresetlist}%
+ % here public means 'visible' so it's not to be confused with 'public' at the lua end
+ \doifinset \s!public{#3}{\expandafter\let\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}%
+ \fi}
+
+\unexpanded\def\newattribute#1%
+ {\attr_basics_define_indeed\s!public[\csstring#1][]%
+ \expandafter\let\expandafter#1\csname\??attributeid\csstring#1\endcsname}
+
+% expandable so we can \edef them for speed
+
+\def\dosetattribute#1#2{\csname\??attributecount#1\endcsname#2\relax}
+\def\doresetattribute#1{\csname\??attributecount#1\endcsname\attributeunsetvalue}
+\def\dogetattribute #1{\number\csname\??attributecount#1\endcsname}
+\def\dogetattributeid#1{\number\csname\??attributeid#1\endcsname}
+
+\let\dompattribute\gobbletwoarguments
+
+\unexpanded\def\resetallattributes{\the\attributesresetlist}
+
+%D Rather special.
+
+\unexpanded\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}}
+\unexpanded\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}}
+
+%D For the moment we put this here (later it will move to where it's used):
+
+\definesystemattribute [state]
+\definesystemattribute [color] [public] % global
+\definesystemattribute [colormodel] [public,global]
+\definesystemattribute [skip]
+\definesystemattribute [penalty]
+\definesystemattribute [transparency] [public]
+\definesystemattribute [background] [public]
+\definesystemattribute [alignbackground] [public]
+\definesystemattribute [colorintent] [public]
+\definesystemattribute [negative] [public]
+\definesystemattribute [effect] [public]
+\definesystemattribute [viewerlayer] [public]
+\definesystemattribute [layoutcomponent] [public]
+\definesystemattribute [reference] [public]
+\definesystemattribute [destination] [public]
+\definesystemattribute [internal] [public]
+\definesystemattribute [ruled] [public]
+\definesystemattribute [shifted] [public]
+\definesystemattribute [checkedbreak] [public]
+\definesystemattribute [vboxtohboxseparator] [public]
+
+\unexpanded\def\showattributes{\clf_showattributes}
+
+\protect \endinput
+
+% for the luatex list:
+%
+% \attributedef\zeroattribute=0
+% \attributedef\someatriubute=999
+%
+% \directlua {
+% local createtoken = newtoken.create
+% function attributenumber(name)
+% local n = createtoken(name).mode - createtoken("zeroattribute").mode
+% return n >= 0 and n or false
+% end
+% }
+%
+% \directlua{print(attributenumber("noneattribute"))}
+% \directlua{print(attributenumber("someattribute"))}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-lay.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-lay.lua
new file mode 100644
index 00000000000..0d43979c813
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-lay.lua
@@ -0,0 +1,307 @@
+if not modules then modules = { } end modules ['attr-lay'] = {
+ version = 1.001,
+ comment = "companion to attr-lay.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- layers (ugly code, due to no grouping and such); currently we use exclusive layers
+-- but when we need it stacked layers might show up too; the next function based
+-- approach can be replaced by static (metatable driven) resolvers
+
+-- maybe use backends.registrations here too
+
+local type = type
+local insert, remove = table.insert, table.remove
+
+local attributes = attributes
+local nodes = nodes
+local utilities = utilities
+local logs = logs
+local backends = backends
+
+local context = context
+local interfaces = interfaces
+local tex = tex
+
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local report_viewerlayers = logs.reporter("viewerlayers")
+
+-- todo: document this but first reimplement this as it reflects the early
+-- days of luatex / mkiv and we have better ways now
+
+-- nb: attributes: color etc is much slower than normal (marks + literals) but ...
+-- nb. too many "0 g"s
+-- nb: more local tables
+
+attributes.viewerlayers = attributes.viewerlayers or { }
+local viewerlayers = attributes.viewerlayers
+
+local variables = interfaces.variables
+local v_local = variables["local"]
+local v_global = variables["global"]
+local v_start = variables["start"]
+local v_yes = variables["yes"]
+
+local a_viewerlayer = attributes.private("viewerlayer")
+
+viewerlayers = viewerlayers or { }
+viewerlayers.data = allocate()
+viewerlayers.registered = viewerlayers.registered or { }
+viewerlayers.values = viewerlayers.values or { }
+viewerlayers.scopes = viewerlayers.scopes or { }
+viewerlayers.listwise = allocate()
+viewerlayers.attribute = a_viewerlayer
+viewerlayers.supported = true
+viewerlayers.hasorder = true
+
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+
+local texsetattribute = tex.setattribute
+local texgetattribute = tex.getattribute
+local texsettokenlist = tex.settoks
+local unsetvalue = attributes.unsetvalue
+
+local nodepool = nodes.pool
+
+local data = viewerlayers.data
+local values = viewerlayers.values
+local listwise = viewerlayers.listwise
+local registered = viewerlayers.registered
+local scopes = viewerlayers.scopes
+
+local f_stamp = formatters["%s"]
+
+storage.register("attributes/viewerlayers/registered", registered, "attributes.viewerlayers.registered")
+storage.register("attributes/viewerlayers/values", values, "attributes.viewerlayers.values")
+storage.register("attributes/viewerlayers/scopes", scopes, "attributes.viewerlayers.scopes")
+
+local layerstacker = utilities.stacker.new("layers") -- experiment
+
+layerstacker.mode = "stack"
+layerstacker.unset = attributes.unsetvalue
+
+viewerlayers.resolve_reset = layerstacker.resolve_reset
+viewerlayers.resolve_begin = layerstacker.resolve_begin
+viewerlayers.resolve_step = layerstacker.resolve_step
+viewerlayers.resolve_end = layerstacker.resolve_end
+
+-- stacked
+
+local function startlayer(...) startlayer = nodeinjections.startlayer return startlayer(...) end
+local function stoplayer (...) stoplayer = nodeinjections.stoplayer return stoplayer (...) end
+
+local function extender(viewerlayers,key)
+ if viewerlayers.supported and key == "none" then
+ local d = stoplayer()
+ viewerlayers.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if viewerlayers.supported then
+ local v = values[n]
+ if v then
+ local d = startlayer(v)
+ data[n] = d
+ return d
+ else
+ report_viewerlayers("error: unknown reference %a",tostring(n))
+ end
+ end
+end
+
+setmetatableindex(viewerlayers,extender)
+setmetatableindex(viewerlayers.data,reviver)
+
+-- !!!! TEST CODE !!!!
+
+layerstacker.start = function(...) local f = nodeinjections.startstackedlayer layerstacker.start = f return f(...) end
+layerstacker.stop = function(...) local f = nodeinjections.stopstackedlayer layerstacker.stop = f return f(...) end
+layerstacker.change = function(...) local f = nodeinjections.changestackedlayer layerstacker.change = f return f(...) end
+
+local function initializer(...)
+ return states.initialize(...)
+end
+
+attributes.viewerlayers.handler = nodes.installattributehandler {
+ name = "viewerlayer",
+ namespace = viewerlayers,
+ initializer = initializer,
+ finalizer = states.finalize,
+ processor = states.stacker,
+ -- processor = states.stacked,
+}
+
+local stack, enabled, global = { }, false, false
+
+function viewerlayers.enable(value)
+ if value == false or not viewerlayers.supported then
+ if enabled then
+ tasks.disableaction("shipouts","attributes.viewerlayers.handler")
+ end
+ enabled = false
+ else
+ if not enabled then
+ tasks.enableaction("shipouts","attributes.viewerlayers.handler")
+ end
+ enabled = true
+ end
+end
+
+function viewerlayers.forcesupport(value)
+ viewerlayers.supported = value
+ report_viewerlayers("viewerlayers are %ssupported",value and "" or "not ")
+ viewerlayers.enable(value)
+end
+
+local function register(name,lw) -- if not inimode redefine data[n] in first call
+ if not enabled then
+ viewerlayers.enable(true)
+ end
+ local stamp = f_stamp(name)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = name
+ registered[stamp] = n
+ listwise[n] = lw or false -- lw forces a used
+ end
+ return registered[stamp] -- == n
+end
+
+viewerlayers.register = register
+
+function viewerlayers.setfeatures(hasorder)
+ viewerlayers.hasorder = hasorder
+end
+
+local usestacker = true -- new, experimental
+
+function viewerlayers.start(name)
+ local a
+ if usestacker then
+ a = layerstacker.push(register(name) or unsetvalue)
+ else
+ insert(stack,texgetattribute(a_viewerlayer))
+ a = register(name) or unsetvalue
+ end
+ if global or scopes[name] == v_global then
+ scopes[a] = v_global -- messy but we don't know the attributes yet
+ texsetattribute("global",a_viewerlayer,a)
+ else
+ texsetattribute(a_viewerlayer,a)
+ end
+ texsettokenlist("currentviewerlayertoks",name)
+end
+
+function viewerlayers.stop()
+ local a
+ if usestacker then
+ a = layerstacker.pop()
+ else
+ a = remove(stack)
+ end
+ if not a then
+ -- error
+ elseif a >= 0 then
+ if global or scopes[a] == v_global then
+ texsetattribute("global",a_viewerlayer,a)
+ else
+ texsetattribute(a_viewerlayer,a)
+ end
+ texsettokenlist("currentviewerlayertoks",values[a] or "")
+ else
+ if global or scopes[a] == v_global then
+ texsetattribute("global",a_viewerlayer,unsetvalue)
+ else
+ texsetattribute(a_viewerlayer,unsetvalue)
+ end
+ texsettokenlist("currentviewerlayertoks","")
+ end
+end
+
+function viewerlayers.define(settings)
+ local tag = settings.tag
+ if not tag or tag == "" then
+ -- error
+ elseif not scopes[tag] then -- prevent duplicates
+ local title = settings.title
+ if not title or title == "" then
+ settings.title = tag
+ end
+ scopes[tag] = settings.scope or v_local
+ codeinjections.defineviewerlayer(settings)
+ end
+end
+
+function viewerlayers.definedlayoutcomponent(tag)
+ viewerlayers.define {
+ tag = tag,
+ title = utilities.strings.nice(tag),
+ visible = v_start,
+ editable = v_yes,
+ printable = v_yes,
+ }
+ return register(tag,true) -- true forces a use
+end
+
+function viewerlayers.cleanup()
+ layerstacker.clean()
+ -- todo
+end
+
+implement {
+ name = "cleanuplayers",
+ actions = viewerlayers.cleanup
+}
+
+implement {
+ name = "defineviewerlayer",
+ actions = viewerlayers.define,
+ arguments = {
+ {
+ { "tag" },
+ { "title" },
+ { "visible" },
+ { "editable" },
+ { "export" },
+ { "printable" },
+ { "scope" },
+ },
+ true
+ }
+}
+
+implement {
+ name = "definedlayoutcomponent",
+ actions = { viewerlayers.definedlayoutcomponent, context },
+ arguments = "string"
+}
+
+implement {
+ name = "startviewerlayer",
+ actions = viewerlayers.start,
+ arguments = "string",
+}
+
+implement {
+ name = "stopviewerlayer",
+ actions = viewerlayers.stop
+}
+
+implement {
+ name = "registeredviewerlayer",
+ actions = { register, context },
+ arguments = { "string", true } -- true forces a use
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-lay.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-lay.mkiv
new file mode 100644
index 00000000000..14ef4a6d40f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-lay.mkiv
@@ -0,0 +1,105 @@
+%D \module
+%D [ file=attr-lay,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Viewerlayers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Viewerlayers}
+
+%D Currently there is a limitation in mixed inline usage. This has to do with the fact
+%D that we have a stacked model but cannot determine where to revert to (as we can
+%D have AABBCCAA ranges). Maybe I'll solve that one day. It only affects nested inline
+%D layers and these make not much sense anyway. We'd have to store the complete nesting
+%D stack in the attribute in order to be able to cross pages and that demands a new
+%D mechanism.
+
+\unprotect
+
+\registerctxluafile{attr-lay}{1.001}
+
+% needs to work over stopitemize grouping etc
+
+\installcorenamespace{viewerlayer}
+
+\installcommandhandler \??viewerlayer {viewerlayer} \??viewerlayer
+
+\setupviewerlayer
+ [\c!state=\v!start,
+ \c!title=,
+ \c!export=\v!yes, % exportable is ugly
+ \c!printable=\v!yes,
+ \c!scope=\v!local, % maybe global but needs checking with layout
+ \c!method=\v!none]
+
+\appendtoks
+ \clf_defineviewerlayer
+ tag {\currentviewerlayer}%
+ title {\viewerlayerparameter\c!title}%
+ visible {\viewerlayerparameter\c!state}%
+ editable {\v!yes}%
+ export {\viewerlayerparameter\c!export}%
+ printable {\viewerlayerparameter\c!printable}%
+ scope {\viewerlayerparameter\c!scope}%
+ \relax
+ \doif{\viewerlayerparameter\c!method}\v!command
+ {\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}%
+ \setuxvalue{\e!stop #1}{\stopviewerlayer}}%
+\to \everydefineviewerlayer
+
+\unexpanded\def\startviewerlayer[#1]{\clf_startviewerlayer{#1}}% not grouped
+\unexpanded\def\stopviewerlayer {\clf_stopviewerlayer} % not grouped
+\unexpanded\def\viewerlayer [#1]{\groupedcommand
+ {\clf_startviewerlayer{#1}}% grouped
+ {\clf_stopviewerlayer}} % grouped
+
+% some day we will keep this at the lua end as the info is only needed there
+
+\newtoks\currentviewerlayertoks % soon we can set macros at the lua end
+
+\def\currentviewerlayer{\the\currentviewerlayertoks}
+
+\appendtoks
+ \let\currentviewerlayer\empty
+\to \everybeforepagebody
+
+% layout components are implemented rather directly (speed)
+
+\installcorenamespace{layoutcomponentattribute}
+
+\def\attr_layoutcomponent_initialize#1%
+ {\edef\layoutcomponentboxattribute{\clf_definedlayoutcomponent{#1}}%
+ \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}%
+ \expandafter\glet\csname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute}
+
+\def\attr_layoutcomponent_set#1% make this faster
+ {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??layoutcomponentattribute#1\endcsname
+ \ifx\layoutcomponentboxattribute\relax
+ \attr_layoutcomponent_initialize{#1}% get rid of { }
+ \fi}
+
+\def\attr_layoutcomponent_reset
+ {\let\layoutcomponentboxattribute\empty}
+
+\let\setlayoutcomponentattribute \gobbleoneargument
+\let\resetlayoutcomponentattribute\relax
+\let\layoutcomponentboxattribute \empty
+
+\unexpanded\def\showlayoutcomponents
+ {\let\setlayoutcomponentattribute \attr_layoutcomponent_set
+ \let\resetlayoutcomponentattribute\attr_layoutcomponent_reset}
+
+\unexpanded\def\attr_layoutcomponent_cleanup
+ {\clf_cleanuplayers}
+
+\appendtoks
+ \attr_layoutcomponent_cleanup
+\to \everyshipout
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.lua
new file mode 100644
index 00000000000..976598fa013
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['attr-mkr'] = {
+ version = 1.001,
+ comment = "companion to attr-mkr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local markers = nodes.markers or { }
+nodes.markers = markers
+
+local cache = { }
+local numbers = attributes.numbers
+local a_unknown = attributes.private("marker:unknown")
+
+table.setmetatableindex(cache,function(t,k)
+ local k = "marker:" .. k
+ local v = numbers[k] or a_unknown
+ t[k] = v
+ return v
+end)
+
+function markers.get(n,name)
+ local a = cache[name]
+ return a and n[a] or nil
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.mkiv
new file mode 100644
index 00000000000..c8818ebae7e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-mkr.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=attr-mkr,
+%D version=2013.01.09,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Markers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Markers}
+
+\unprotect
+
+\registerctxluafile{attr-mkr}{1.001}
+
+\unexpanded\def\definemarker [#1]{\defineattribute[\s!marker:#1]}
+\unexpanded\def\setmarker [#1]#2[#3]{\dosetattribute{\s!marker:#1}{#3}}
+\unexpanded\def\resetmarker [#1]{\dogetattribute{\s!marker:#1}}
+ \def\boxmarker #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-neg.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-neg.lua
new file mode 100644
index 00000000000..1347c3d1ad8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-neg.lua
@@ -0,0 +1,104 @@
+if not modules then modules = { } end modules ['attr-neg'] = {
+ version = 1.001,
+ comment = "companion to attr-neg.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module is being reconstructed and code will move to other places
+-- we can also do the nsnone via a metatable and then also se index 0
+
+local format = string.format
+
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
+
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local texsetattribute = tex.setattribute
+local variables = interfaces.variables
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+--- negative / positive
+
+attributes.negatives = attributes.negatives or { }
+local negatives = attributes.negatives
+
+local a_negative = attributes.private("negative")
+
+local v_none = interfaces.variables.none
+
+negatives.data = allocate()
+negatives.attribute = a_negative
+
+negatives.registered = allocate {
+ [variables.positive] = 1,
+ [variables.negative] = 2,
+}
+
+local data = negatives.data
+local registered = negatives.registered
+
+local function extender(negatives,key)
+ if key == "none" then -- v_none then
+ local d = data[1]
+ negatives.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if n == 1 then
+ local d = nodeinjections.positive() -- called once
+ data[1] = d
+ return d
+ elseif n == 2 then
+ local d = nodeinjections.negative() -- called once
+ data[2] = d
+ return d
+ end
+end
+
+setmetatableindex(negatives, extender)
+setmetatableindex(negatives.data, reviver)
+
+negatives.handler = nodes.installattributehandler {
+ name = "negative",
+ namespace = negatives,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+local function register(stamp)
+ return registered[stamp] or registered.positive
+end
+
+local function enable()
+ tasks.enableaction("shipouts","attributes.negatives.handler")
+end
+
+negatives.register = register
+negatives.enable = enable
+
+-- interface
+
+local enabled = false
+
+function negatives.set(stamp)
+ if not enabled then
+ enable()
+ enabled = true
+ end
+ texsetattribute(a_negative,register(stamp))
+end
+
+interfaces.implement {
+ name = "setnegative",
+ actions = negatives.set,
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-neg.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-neg.mkiv
new file mode 100644
index 00000000000..ff1f52a96b4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/attr-neg.mkiv
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=attr-neg,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Negation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Negation}
+
+\registerctxluafile{attr-neg}{1.001}
+
+\unprotect
+
+% positive and negative are preregistered
+
+\unexpanded\def\startnegative{\attr_trigger_negative\v!negative}
+\unexpanded\def\stopnegative {\attr_trigger_negative\v!positive}
+
+\unexpanded\def\startpositive{\attr_trigger_negative\v!positive}
+\unexpanded\def\stoppositive {\attr_trigger_negative\v!negative}
+
+\def\attr_trigger_negative#1{\clf_setnegative{#1}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua b/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua
new file mode 100644
index 00000000000..681996d4802
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua
@@ -0,0 +1,3706 @@
+if not modules then modules = { } end modules ['back-exp'] = {
+ 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"
+}
+
+-- Todo: share properties more with tagged pdf (or thge reverse)
+
+-- Because we run into the 200 local limit we quite some do .. end wrappers .. not always
+-- that nice but it has to be.
+
+-- Experiments demonstrated that mapping to <div> and classes is messy because we have to
+-- package attributes (some 30) into one set of (space seperatated but prefixed classes)
+-- which only makes things worse .. so if you want something else, use xslt to get there.
+
+-- language -> only mainlanguage, local languages should happen through start/stoplanguage
+-- tocs/registers -> maybe add a stripper (i.e. just don't flush entries in final tree)
+-- footnotes -> css 3
+-- bodyfont -> in styles.css
+
+-- Because we need to look ahead we now always build a tree (this was optional in
+-- the beginning). The extra overhead in the frontend is neglectable.
+--
+-- We can optimize the code ... currently the overhead is some 10% for xml + html so
+-- there is no hurry.
+
+-- todo: move critital formatters out of functions
+-- todo: delay loading (apart from basic tag stuff)
+
+-- problem : too many local variables
+
+-- check setting __i__
+
+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 concat, insert, remove, merge = table.concat, table.insert, table.remove, table.merge
+local sortedhash = table.sortedhash
+local formatters = string.formatters
+local todimen = number.todimen
+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 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)
+
+show_comment = false -- figure out why break comment
+
+-- maybe we will also support these:
+--
+-- local css_hyphens = false directives.register("export.css.hyphens", function(v) css_hyphens = v end)
+-- local css_textalign = false directives.register("export.css.textalign", function(v) css_textalign = v end)
+-- local css_bodyfontsize = false directives.register("export.css.bodyfontsize", function(v) css_bodyfontsize = v end)
+-- local css_textwidth = false directives.register("export.css.textwidth", function(v) css_textwidth = v end)
+
+local report_export = logs.reporter("backend","export")
+
+local nodes = nodes
+local attributes = attributes
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+local v_no = variables.no
+local v_hidden = variables.hidden
+
+local implement = interfaces.implement
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local setmetatableindex = table.setmetatableindex
+local tasks = nodes.tasks
+local fontchar = fonts.hashes.characters
+local fontquads = fonts.hashes.quads
+local languagenames = languages.numbers
+
+local nodecodes = nodes.nodecodes
+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 insert_code = nodecodes.insert
+
+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 getlist = nuts.getlist
+local getid = nuts.getid
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local isglyph = nuts.isglyph
+
+local traverse_id = nuts.traverse_id
+local traverse_nodes = nuts.traverse
+
+local references = structures.references
+local structurestags = structures.tags
+local taglist = structurestags.taglist
+local specifications = structurestags.specifications
+local properties = structurestags.properties
+local locatedtag = structurestags.locatedtag
+
+structurestags.usewithcare = { }
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local characterdata = characters.data
+local overloads = fonts.mappings.overloads
+
+-- todo: more locals (and optimize)
+
+local exportversion = "0.34"
+local mathmlns = "http://www.w3.org/1998/Math/MathML"
+local contextns = "http://www.contextgarden.net/context/export" -- whatever suits
+local cssnamespaceurl = "@namespace context url('%namespace%') ;"
+local cssnamespace = "context|"
+----- cssnamespacenop = "/* no namespace */"
+
+local usecssnamespace = false
+
+local nofcurrentcontent = 0 -- so we don't free (less garbage collection)
+local currentcontent = { }
+local currentnesting = nil
+local currentattribute = nil
+local last = nil
+local currentparagraph = nil
+
+local noftextblocks = 0
+
+local hyphencode = 0xAD
+local hyphen = utfchar(0xAD) -- todo: also emdash etc
+local tagsplitter = structurestags.patterns.splitter
+----- colonsplitter = lpeg.splitat(":")
+----- dashsplitter = lpeg.splitat("-")
+local threshold = 65536
+local indexing = false
+local keephyphens = false
+local exportproperties = false
+
+local finetuning = { }
+
+local treestack = { }
+local nesting = { }
+local currentdepth = 0
+
+local wrapups = { }
+
+local tree = { data = { }, fulltag == "root" } -- root
+local treeroot = tree
+local treehash = { }
+local extras = { }
+local checks = { }
+local finalizers = { }
+local nofbreaks = 0
+local used = { }
+local exporting = false
+local restart = false
+local specialspaces = { [0x20] = " " } -- for conversion
+local somespace = { [0x20] = true, [" "] = true } -- for testing
+local entities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;" }
+local attribentities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;", ['"'] = "quot;" }
+
+local p_entity = lpeg.replacer(entities) -- was: entityremapper = utf.remapper(entities)
+local p_attribute = lpeg.replacer(attribentities)
+local p_stripper = lpeg.patterns.stripper
+local p_escaped = lpeg.patterns.xml.escaped
+
+local f_tagid = formatters["%s-%04i"]
+
+-- local alignmapping = {
+-- flushright = "right",
+-- middle = "center",
+-- flushleft = "left",
+-- }
+
+local defaultnature = "mixed" -- "inline"
+
+setmetatableindex(used, function(t,k)
+ if k then
+ local v = { }
+ t[k] = v
+ return v
+ end
+end)
+
+local f_entity = formatters["&#x%X;"]
+local f_attribute = formatters[" %s=%q"]
+local f_property = formatters[" %s%s=%q"]
+
+setmetatableindex(specialspaces, function(t,k)
+ local v = utfchar(k)
+ t[k] = v
+ entities[v] = f_entity(k)
+ somespace[k] = true
+ somespace[v] = true
+ return v
+end)
+
+
+local namespaced = {
+ -- filled on
+}
+
+local namespaces = {
+ msubsup = "m",
+ msub = "m",
+ msup = "m",
+ mn = "m",
+ mi = "m",
+ ms = "m",
+ mo = "m",
+ mtext = "m",
+ mrow = "m",
+ mfrac = "m",
+ mroot = "m",
+ msqrt = "m",
+ munderover = "m",
+ munder = "m",
+ mover = "m",
+ merror = "m",
+ math = "m",
+ mrow = "m",
+ mtable = "m",
+ mtr = "m",
+ mtd = "m",
+ mfenced = "m",
+ maction = "m",
+ mspace = "m",
+ -- only when testing
+ mstacker = "m",
+ mstackertop = "m",
+ mstackermid = "m",
+ mstackerbot = "m",
+}
+
+setmetatableindex(namespaced, function(t,k)
+ if k then
+ local namespace = namespaces[k]
+ local v = namespace and namespace .. ":" .. k or k
+ t[k] = v
+ return v
+ end
+end)
+
+local function attribute(key,value)
+ if value and value ~= "" then
+ return f_attribute(key,lpegmatch(p_attribute,value))
+ else
+ return ""
+ end
+end
+
+local function setattribute(di,key,value,escaped)
+ if value and value ~= "" then
+ local a = di.attributes
+ if escaped then
+ value = lpegmatch(p_escaped,value)
+ end
+ if not a then
+ di.attributes = { [key] = value }
+ else
+ a[key] = value
+ end
+ end
+end
+
+local listdata = { } -- this has to be done otherwise: each element can just point back to ...
+
+function wrapups.hashlistdata()
+ local c = structures.lists.collected
+ for i=1,#c do
+ local ci = c[i]
+ local tag = ci.references.tag
+ if tag then
+ local m = ci.metadata
+ local t = m.kind .. ">" .. tag -- todo: use internal (see strc-lst.lua where it's set)
+ listdata[t] = ci
+ end
+ end
+end
+
+function structurestags.setattributehash(attr,key,value) -- public hash
+ local specification = taglist[attr]
+ if specification then
+ specification[key] = value
+ else
+ -- some kind of error
+ end
+end
+
+local usedstyles = { }
+
+local namespacetemplate = [[
+/* %what% for file %filename% */
+
+%cssnamespaceurl%
+]]
+
+do
+
+ -- experiment: styles and images
+ --
+ -- officially we should convert to bp but we round anyway
+
+ -- /* padding : ; */
+ -- /* text-justify : inter-word ; */
+ -- /* text-align : justify ; */
+
+local documenttemplate = [[
+document, %namespace%div.document {
+ font-size : %size% !important ;
+ max-width : %width% !important ;
+ text-width : %align% !important ;
+ hyphens : %hyphens% !important ;
+}
+]]
+
+local styletemplate = [[
+%element%[detail="%detail%"], %namespace%div.%element%.%detail% {
+ display : inline ;
+ font-style : %style% ;
+ font-variant : %variant% ;
+ font-weight : %weight% ;
+ font-family : %family% ;
+ color : %color% ;
+}]]
+
+ local numbertoallign = {
+ [0] = "justify", ["0"] = "justify", [variables.normal ] = "justify",
+ [1] = "right", ["1"] = "right", [variables.flushright] = "right",
+ [2] = "center", ["2"] = "center", [variables.middle ] = "center",
+ [3] = "left", ["3"] = "left", [variables.flushleft ] = "left",
+ }
+
+ function wrapups.allusedstyles(basename)
+ local result = { replacetemplate(namespacetemplate, {
+ what = "styles",
+ filename = basename,
+ namespace = contextns,
+ -- cssnamespaceurl = usecssnamespace and cssnamespaceurl or cssnamespacenop,
+ cssnamespaceurl = cssnamespaceurl,
+ }) }
+ --
+ local bodyfont = finetuning.bodyfont
+ local width = finetuning.width
+ local hyphen = finetuning.hyphen
+ local align = finetuning.align
+ --
+ if type(bodyfont) == "number" then
+ bodyfont = todimen(bodyfont)
+ else
+ bodyfont = "12pt"
+ end
+ if type(width) == "number" then
+ width = todimen(width) or "50em"
+ else
+ width = "50em"
+ end
+ if hyphen == v_yes then
+ hyphen = "manual"
+ else
+ hyphen = "inherited"
+ end
+ if align then
+ align = numbertoallign[align]
+ end
+ if not align then
+ align = hyphen and "justify" or "inherited"
+ end
+ --
+ result[#result+1] = replacetemplate(documenttemplate,{
+ size = bodyfont,
+ width = width,
+ align = align,
+ hyphens = hyphen
+ })
+ --
+ local colorspecification = xml.css.colorspecification
+ local fontspecification = xml.css.fontspecification
+ for element, details in sortedhash(usedstyles) do
+ for detail, data in sortedhash(details) do
+ local s = fontspecification(data.style)
+ local c = colorspecification(data.color)
+ detail = gsub(detail,"[^A-Za-z0-9]+","-")
+ result[#result+1] = replacetemplate(styletemplate,{
+ namespace = usecssnamespace and cssnamespace or "",
+ element = element,
+ detail = detail,
+ style = s.style or "inherit",
+ variant = s.variant or "inherit",
+ weight = s.weight or "inherit",
+ family = s.family or "inherit",
+ color = c or "inherit",
+ })
+ end
+ end
+ return concat(result,"\n\n")
+ end
+
+end
+
+local usedimages = { }
+
+do
+
+local imagetemplate = [[
+%element%[id="%id%"], %namespace%div.%element%[id="%id%"] {
+ display : block ;
+ background-image : url('%url%') ;
+ background-size : 100%% auto ;
+ background-repeat : no-repeat ;
+ width : %width% ;
+ height : %height% ;
+}]]
+
+ local f_svgname = formatters["%s.svg"]
+ local f_svgpage = formatters["%s-page-%s.svg"]
+ local collected = { }
+
+ local function usedname(name,page)
+ if file.suffix(name) == "pdf" then
+ -- temp hack .. we will have a remapper
+ if page and page > 1 then
+ name = f_svgpage(file.nameonly(name),page)
+ else
+ name = f_svgname(file.nameonly(name))
+ end
+ end
+ local scheme = url.hasscheme(name)
+ if not scheme or scheme == "file" then
+ -- or can we just use the name ?
+ return file.join("../images",file.basename(url.filename(name)))
+ else
+ return name
+ end
+ end
+
+ function wrapups.allusedimages(basename)
+ local result = { replacetemplate(namespacetemplate, {
+ what = "images",
+ filename = basename,
+ namespace = contextns,
+ -- cssnamespaceurl = usecssnamespace and cssnamespaceurl or "",
+ cssnamespaceurl = cssnamespaceurl,
+ }) }
+ for element, details in sortedhash(usedimages) do
+ for detail, data in sortedhash(details) do
+ local name = data.name
+ local page = tonumber(data.page) or 1
+ local spec = {
+ element = element,
+ id = data.id,
+ name = name,
+ page = page,
+ url = usedname(name,page),
+ width = data.width,
+ height = data.height,
+ used = data.used,
+ namespace = usecssnamespace and cssnamespace or "",
+ }
+ result[#result+1] = replacetemplate(imagetemplate,spec)
+ collected[detail] = spec
+ end
+ end
+ return concat(result,"\n\n")
+ end
+
+ function wrapups.uniqueusedimages() -- todo: combine these two
+ return collected
+ end
+
+end
+
+--
+
+properties.vspace = { export = "break", nature = "display" }
+----------------- = { export = "pagebreak", nature = "display" }
+
+local function makebreaklist(list)
+ nofbreaks = nofbreaks + 1
+ local t = { }
+ local l = list and list.taglist
+ if l then
+ for i=1,#list do
+ t[i] = l[i]
+ end
+ end
+ t[#t+1] = "break>" .. nofbreaks -- maybe no number or 0
+ return { taglist = t }
+end
+
+local breakattributes = {
+ type = "collapse"
+}
+
+local function makebreaknode(attributes) -- maybe no fulltag
+ nofbreaks = nofbreaks + 1
+ return {
+ tg = "break",
+ fulltag = "break>" .. nofbreaks,
+ n = nofbreaks,
+ element = "break",
+ nature = "display",
+ attributes = attributes or nil,
+ -- data = { }, -- not needed
+ -- attribute = 0, -- not needed
+ -- parnumber = 0,
+ }
+end
+
+local function ignorebreaks(di,element,n,fulltag)
+ local data = di.data
+ for i=1,#data do
+ local d = data[i]
+ if d.content == " " then
+ d.content = ""
+ end
+ end
+end
+
+local function ignorespaces(di,element,n,fulltag)
+ local data = di.data
+ for i=1,#data do
+ local d = data[i]
+ local c = d.content
+ if type(c) == "string" then
+ d.content = lpegmatch(p_stripper,c)
+ end
+ end
+end
+
+do
+
+ local fields = { "title", "subtitle", "author", "keywords" }
+
+ local function checkdocument(root)
+ local data = root.data
+ if data then
+ for i=1,#data do
+ local di = data[i]
+ local tg = di.tg
+ if tg == "noexport" then
+ local s = specifications[di.fulltag]
+ local u = s and s.userdata
+ if u then
+ local comment = u.comment
+ if comment then
+ di.element = "comment"
+ di.data = { { content = comment } }
+ u.comment = nil
+ else
+ data[i] = false
+ end
+ else
+ data[i] = false
+ end
+ elseif di.content then
+ -- okay
+ elseif tg == "ignore" then
+ di.element = ""
+ checkdocument(di)
+ else
+ checkdocument(di) -- new, else no noexport handling
+ end
+ end
+ end
+ end
+
+ function extras.document(di,element,n,fulltag)
+ setattribute(di,"language",languagenames[texgetcount("mainlanguagenumber")])
+ if not less_state then
+ setattribute(di,"file",tex.jobname)
+ setattribute(di,"date",os.date())
+ setattribute(di,"context",environment.version)
+ setattribute(di,"version",exportversion)
+ setattribute(di,"xmlns:m",mathmlns)
+ local identity = interactions.general.getidentity()
+ for i=1,#fields do
+ local key = fields[i]
+ local value = identity[key]
+ if value and value ~= "" then
+ setattribute(di,key,value)
+ end
+ end
+ end
+ checkdocument(di)
+ end
+
+end
+
+do
+
+ local symbols = { }
+
+ function structurestags.settagdelimitedsymbol(symbol)
+ symbols[locatedtag("delimitedsymbol")] = {
+ symbol = symbol,
+ }
+ end
+
+ function extras.delimitedsymbol(di,element,n,fulltag)
+ local hash = symbols[fulltag]
+ if hash then
+ setattribute(di,"symbol",hash.symbol or nil)
+ end
+ end
+
+end
+
+do
+
+ local symbols = { }
+
+ function structurestags.settagsubsentencesymbol(symbol)
+ symbols[locatedtag("subsentencesymbol")] = {
+ symbol = symbol,
+ }
+ end
+
+ function extras.subsentencesymbol(di,element,n,fulltag)
+ local hash = symbols[fulltag]
+ if hash then
+ setattribute(di,"symbol",hash.symbol or nil)
+ end
+ end
+
+end
+
+do
+
+ local itemgroups = { }
+
+ function structurestags.setitemgroup(packed,level,symbol)
+ itemgroups[locatedtag("itemgroup")] = {
+ packed = packed,
+ symbol = symbol,
+ level = level,
+ }
+ end
+
+ function structurestags.setitem(kind)
+ itemgroups[locatedtag("item")] = {
+ kind = kind,
+ }
+ end
+
+ function extras.itemgroup(di,element,n,fulltag)
+ local hash = itemgroups[fulltag]
+ if hash then
+ setattribute(di,"packed",hash.packed and "yes" or nil)
+ setattribute(di,"symbol",hash.symbol)
+ setattribute(di,"level",hash.level)
+ end
+ end
+
+ function extras.item(di,element,n,fulltag)
+ local hash = itemgroups[fulltag]
+ if hash then
+ local kind = hash.kind
+ if kind and kind ~= "" then
+ setattribute(di,"kind",kind)
+ end
+ end
+ end
+
+end
+
+do
+
+ local synonyms = { }
+ local sortings = { }
+
+ function structurestags.setsynonym(tag)
+ synonyms[locatedtag("synonym")] = tag
+ end
+
+ function extras.synonym(di,element,n,fulltag)
+ local tag = synonyms[fulltag]
+ if tag then
+ setattribute(di,"tag",tag)
+ end
+ end
+
+ function structurestags.setsorting(tag)
+ sortings[locatedtag("sorting")] = tag
+ end
+
+ function extras.sorting(di,element,n,fulltag)
+ local tag = sortings[fulltag]
+ if tag then
+ setattribute(di,"tag",tag)
+ end
+ end
+
+end
+
+do
+
+ local highlight = { }
+ usedstyles.highlight = highlight
+
+ local strippedtag = structurestags.strip -- we assume global styles
+
+ function structurestags.sethighlight(style,color)
+ highlight[strippedtag(locatedtag("highlight"))] = {
+ style = style, -- xml.css.fontspecification(style),
+ color = color, -- xml.css.colorspec(color),
+ }
+ end
+
+end
+
+do
+
+ local descriptions = { }
+ local symbols = { }
+ local linked = { }
+
+ -- we could move the notation itself to the first reference (can be an option)
+
+ function structurestags.setnotation(tag,n) -- needs checking (is tag needed)
+ -- we can also use the internals hash or list
+ local nd = structures.notes.get(tag,n)
+ if nd then
+ local references = nd.references
+ descriptions[references and references.internal] = locatedtag("description")
+ end
+ end
+
+ function structurestags.setnotationsymbol(tag,n) -- needs checking (is tag needed)
+ local nd = structures.notes.get(tag,n) -- todo: use listdata instead
+ if nd then
+ local references = nd.references
+ symbols[references and references.internal] = locatedtag("descriptionsymbol")
+ end
+ end
+
+ function finalizers.descriptions(tree)
+ local n = 0
+ for id, tag in next, descriptions do
+ local sym = symbols[id]
+ if sym then
+ n = n + 1
+ linked[tag] = n
+ linked[sym] = n
+ end
+ end
+ end
+
+ function extras.description(di,element,n,fulltag)
+ local id = linked[fulltag]
+ if id then
+ setattribute(di,"insert",id)
+ end
+ end
+
+ function extras.descriptionsymbol(di,element,n,fulltag)
+ local id = linked[fulltag]
+ if id then
+ setattribute(di,"insert",id)
+ end
+ end
+
+end
+
+-- -- todo: ignore breaks
+--
+-- function extras.verbatimline(di,element,n,fulltag)
+-- inspect(di)
+-- end
+
+do
+
+ local f_id = formatters["%s-%s"]
+ local image = { }
+ usedimages.image = image
+
+ structurestags.usewithcare.images = image
+
+ function structurestags.setfigure(name,used,page,width,height,label)
+ local fulltag = locatedtag("image")
+ local spec = specifications[fulltag]
+ local page = tonumber(page)
+ image[fulltag] = {
+ id = f_id(spec.tagname,spec.tagindex),
+ name = name,
+ used = used,
+ page = page and page > 1 and page or nil,
+ width = todimen(width, "cm","%0.3F%s"),
+ height = todimen(height,"cm","%0.3F%s"),
+ label = label,
+ }
+ end
+
+ function extras.image(di,element,n,fulltag)
+ local data = image[fulltag]
+ if data then
+ setattribute(di,"name",data.name)
+ setattribute(di,"page",data.page)
+ setattribute(di,"id",data.id)
+ setattribute(di,"width",data.width)
+ setattribute(di,"height",data.height)
+ setattribute(di,"label",data.height)
+ end
+ end
+
+end
+
+do
+
+ local combinations = { }
+
+ function structurestags.setcombination(nx,ny)
+ combinations[locatedtag("combination")] = {
+ nx = nx,
+ ny = ny,
+ }
+ end
+
+ function extras.combination(di,element,n,fulltag)
+ local data = combinations[fulltag]
+ if data then
+ setattribute(di,"nx",data.nx)
+ setattribute(di,"ny",data.ny)
+ end
+ end
+
+end
+
+-- quite some code deals with exporting references --
+
+-- links:
+--
+-- url :
+-- file :
+-- internal : automatic location
+-- location : named reference
+
+-- references:
+--
+-- implicit : automatic reference
+-- explicit : named reference
+
+local evaluators = { }
+local specials = { }
+local explicits = { }
+
+evaluators.inner = function(di,var)
+ local inner = var.inner
+ if inner then
+ setattribute(di,"location",inner,true)
+ end
+end
+
+evaluators.outer = function(di,var)
+ local file, url = references.checkedfileorurl(var.outer,var.outer)
+ if url then
+ setattribute(di,"url",url,true)
+ elseif file then
+ setattribute(di,"file",file,true)
+ end
+end
+
+evaluators["outer with inner"] = function(di,var)
+ local file = references.checkedfile(var.f)
+ if file then
+ setattribute(di,"file",file,true)
+ end
+ local inner = var.inner
+ if inner then
+ setattribute(di,"inner",inner,true)
+ end
+end
+
+evaluators.special = function(di,var)
+ local handler = specials[var.special]
+ if handler then
+ handler(di,var)
+ end
+end
+
+local referencehash = { }
+
+do
+
+ evaluators["special outer with operation"] = evaluators.special
+ evaluators["special operation"] = evaluators.special
+ evaluators["special operation with arguments"] = evaluators.special
+
+ function specials.url(di,var)
+ local url = references.checkedurl(var.operation)
+ if url and url ~= "" then
+ setattribute(di,"url",url,true)
+ end
+ end
+
+ function specials.file(di,var)
+ local file = references.checkedfile(var.operation)
+ if file and file ~= "" then
+ setattribute(di,"file",file,true)
+ end
+ end
+
+ function specials.fileorurl(di,var)
+ local file, url = references.checkedfileorurl(var.operation,var.operation)
+ if url and url ~= "" then
+ setattribute(di,"url",url,true)
+ elseif file and file ~= "" then
+ setattribute(di,"file",file,true)
+ end
+ end
+
+ function specials.internal(di,var)
+ local internal = references.checkedurl(var.operation)
+ if internal then
+ setattribute(di,"location",internal)
+ end
+ end
+
+ local function adddestination(di,references) -- todo: specials -> exporters and then concat
+ if references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local prefix = references.prefix
+ if prefix and prefix ~= "" then
+ setattribute(di,"prefix",prefix,true)
+ end
+ setattribute(di,"destination",reference,true)
+ for i=1,#references do
+ local r = references[i]
+ local e = evaluators[r.kind]
+ if e then
+ e(di,r)
+ end
+ end
+ end
+ end
+ end
+
+ function extras.addimplicit(di,references)
+ if references then
+ local internal = references.internal
+ if internal then
+ setattribute(di,"implicit",internal)
+ end
+ end
+ end
+
+ function extras.addinternal(di,references)
+ if references then
+ local internal = references.internal
+ if internal then
+ setattribute(di,"internal",internal)
+ end
+ end
+ end
+
+ local p_firstpart = lpeg.Cs((1-lpeg.P(","))^0)
+
+ local function addreference(di,references)
+ if references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local prefix = references.prefix
+ if prefix and prefix ~= "" then
+ setattribute(di,"prefix",prefix)
+ end
+ setattribute(di,"reference",reference,true)
+ setattribute(di,"explicit",lpegmatch(p_firstpart,reference),true)
+ end
+ local internal = references.internal
+ if internal and internal ~= "" then
+ setattribute(di,"implicit",internal)
+ end
+ end
+ end
+
+ local function link(di,element,n,fulltag)
+ -- for instance in lists a link has nested elements and no own text
+ local reference = referencehash[fulltag]
+ if reference then
+ adddestination(di,structures.references.get(reference))
+ return true
+ else
+ local data = di.data
+ if data then
+ for i=1,#data do
+ local di = data[i]
+ if di then
+ local fulltag = di.fulltag
+ if fulltag and link(di,element,n,fulltag) then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+
+ extras.adddestination = adddestination
+ extras.addreference = addreference
+
+ extras.link = link
+
+end
+
+-- no settings, as these are obscure ones
+
+do
+
+ local automathrows = true directives.register("export.math.autorows", function(v) automathrows = v end)
+ local automathapply = true directives.register("export.math.autoapply", function(v) automathapply = v end)
+ local automathnumber = true directives.register("export.math.autonumber", function(v) automathnumber = v end)
+ local automathstrip = true directives.register("export.math.autostrip", function(v) automathstrip = v end)
+
+ local functions = mathematics.categories.functions
+
+ local function collapse(di,i,data,ndata,detail,element)
+ local collapsing = di.data
+ if data then
+ di.element = element
+ di.detail = nil
+ i = i + 1
+ while i <= ndata do
+ local dn = data[i]
+ if dn.detail == detail then
+ collapsing[#collapsing+1] = dn.data[1]
+ dn.skip = "ignore"
+ i = i + 1
+ else
+ break
+ end
+ end
+ end
+ return i
+ end
+
+ local function collapse_mn(di,i,data,ndata)
+ -- this is tricky ... we need to make sure that we wrap in mrows if we want
+ -- to bypass this one
+ local collapsing = di.data
+ if data then
+ i = i + 1
+ while i <= ndata do
+ local dn = data[i]
+ local tg = dn.tg
+ if tg == "mn" then
+ collapsing[#collapsing+1] = dn.data[1]
+ dn.skip = "ignore"
+ i = i + 1
+ elseif tg == "mo" then
+ local d = dn.data[1]
+ if d == "." then
+ collapsing[#collapsing+1] = d
+ dn.skip = "ignore"
+ i = i + 1
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ return i
+ end
+
+ -- maybe delay __i__ till we need it
+
+ local apply_function = {
+ {
+ element = "mo",
+ -- comment = "apply function",
+ -- data = { utfchar(0x2061) },
+ data = { "&#x2061;" },
+ nature = "mixed",
+ }
+ }
+
+ local functioncontent = { }
+
+ setmetatableindex(functioncontent,function(t,k)
+ local v = { { content = k } }
+ t[k] = v
+ return v
+ end)
+
+ local dummy_nucleus = {
+ element = "mtext",
+ data = { content = "" },
+ nature = "inline",
+ comment = "dummy nucleus",
+ fulltag = "mtext>0"
+ }
+
+ local function accentchar(d)
+ for i=1,3 do
+ d = d.data
+ if not d then
+ return
+ end
+ d = d[1]
+ if not d then
+ return
+ end
+ local tg = d.tg
+ if tg == "mover" then
+ local s = specifications[d.fulltag]
+ local t = s.top
+ if t then
+ d = d.data[1]
+ local d1 = d.data[1]
+ d1.content = utfchar(t)
+ d.data = { d1 }
+ return d
+ end
+ elseif tg == "munder" then
+ local s = specifications[d.fulltag]
+ local b = s.bottom
+ if b then
+ d = d.data[1]
+ local d1 = d.data[1]
+ d1.content = utfchar(b)
+ d.data = { d1 }
+ return d
+ end
+ end
+ end
+ end
+
+ local no_mrow = {
+ mrow = true,
+ mfenced = true,
+ mfrac = true,
+ mroot = true,
+ msqrt = true,
+ mi = true,
+ mo = true,
+ mn = true,
+ }
+
+ local function checkmath(root) -- we can provide utf.toentities as an option
+ local data = root.data
+ if data then
+ local ndata = #data
+ local roottg = root.tg
+ if roottg == "msubsup" then
+ local nucleus, superscript, subscript
+ for i=1,ndata do
+ local di = data[i]
+ if not di then
+ -- weird
+ elseif di.content then
+ -- text
+ elseif not nucleus then
+ nucleus = i
+ elseif not superscript then
+ superscript = i
+ elseif not subscript then
+ subscript = i
+ else
+ -- error
+ end
+ end
+ if superscript and subscript then
+ local sup, sub = data[superscript], data[subscript]
+ data[superscript], data[subscript] = sub, sup
+ -- sub.__o__, sup.__o__ = subscript, superscript
+ sub.__i__, sup.__i__ = superscript, subscript
+ end
+-- elseif roottg == "msup" or roottg == "msub" then
+-- -- m$^2$
+-- if ndata == 1 then
+-- local d = data[1]
+-- data[2] = d
+-- d.__i__ = 2
+-- data[1] = dummy_nucleus
+-- end
+ elseif roottg == "mfenced" then
+ local s = specifications[root.fulltag]
+ local l, m, r = s.left, s.middle, s.right
+ if l then
+ l = utfchar(l)
+ end
+ if m then
+ local t = { }
+ for i=1,#m do
+ t[i] = utfchar(m[i])
+ end
+ m = concat(t)
+ end
+ if r then
+ r = utfchar(r)
+ end
+ root.attributes = {
+ open = l,
+ separators = m,
+ close = r,
+ }
+ end
+ if ndata == 0 then
+ return
+ elseif ndata == 1 then
+ local d = data[1]
+ if not d then
+ return
+ elseif d.content then
+ return
+ elseif #root.data == 1 then
+ local tg = d.tg
+ if automathrows and roottg == "mrow" then
+ -- maybe just always ! check spec first
+ if no_mrow[tg] then
+ root.skip = "comment"
+ end
+ elseif roottg == "mo" then
+ if tg == "mo" then
+ root.skip = "comment"
+ end
+ end
+ end
+ end
+ local i = 1
+ while i <= ndata do -- -- -- TOO MUCH NESTED CHECKING -- -- --
+ local di = data[i]
+ if di and not di.content then
+ local tg = di.tg
+ if tg == "math" then
+ -- di.element = "mrow" -- when properties
+ di.skip = "comment"
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mover" then
+ local s = specifications[di.fulltag]
+ if s.accent then
+ local t = s.top
+ local d = di.data
+ -- todo: accent = "false" (for scripts like limits)
+ di.attributes = {
+ accent = "true",
+ }
+ -- todo: p.topfixed
+ if t then
+ -- mover
+ d[1].data[1].content = utfchar(t)
+ di.data = { d[2], d[1] }
+ end
+ else
+ -- can't happen
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "munder" then
+ local s = specifications[di.fulltag]
+ if s.accent then
+ local b = s.bottom
+ local d = di.data
+ -- todo: accent = "false" (for scripts like limits)
+ di.attributes = {
+ accent = "true",
+ }
+ -- todo: p.bottomfixed
+ if b then
+ -- munder
+ d[2].data[1].content = utfchar(b)
+ end
+ else
+ -- can't happen
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "munderover" then
+ local s = specifications[di.fulltag]
+ if s.accent then
+ local t = s.top
+ local b = s.bottom
+ local d = di.data
+ -- todo: accent = "false" (for scripts like limits)
+ -- todo: accentunder = "false" (for scripts like limits)
+ di.attributes = {
+ accent = "true",
+ accentunder = "true",
+ }
+ -- todo: p.topfixed
+ -- todo: p.bottomfixed
+ if t and b then
+ -- munderover
+ d[1].data[1].content = utfchar(t)
+ d[3].data[1].content = utfchar(b)
+ di.data = { d[2], d[3], d[1] }
+ else
+ -- can't happen
+ end
+ else
+ -- can't happen
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mstacker" then
+ local d = di.data
+ local d1 = d[1]
+ local d2 = d[2]
+ local d3 = d[3]
+ local t1 = d1 and d1.tg
+ local t2 = d2 and d2.tg
+ local t3 = d3 and d3.tg
+ local m = nil -- d1.data[1]
+ local t = nil
+ local b = nil
+ -- only accent when top / bot have stretch
+ -- normally we flush [base under over] which is better for tagged pdf
+ if t1 == "mstackermid" then
+ m = accentchar(d1) -- or m
+ if t2 == "mstackertop" then
+ if t3 == "mstackerbot" then
+ t = accentchar(d2)
+ b = accentchar(d3)
+ di.element = "munderover"
+ di.data = { m or d1.data[1], b or d3.data[1], t or d2.data[1] }
+ else
+ t = accentchar(d2)
+ di.element = "mover"
+ di.data = { m or d1.data[1], t or d2.data[1] }
+ end
+ elseif t2 == "mstackerbot" then
+ if t3 == "mstackertop" then
+ b = accentchar(d2)
+ t = accentchar(d3)
+ di.element = "munderover"
+ di.data = { m or d1.data[1], t or d3.data[1], m, b or d2.data[1] }
+ else
+ b = accentchar(d2)
+ di.element = "munder"
+ di.data = { m or d1.data[1], b or d2.data[1] }
+ end
+ else
+ -- can't happen
+ end
+ else
+ -- can't happen
+ end
+ if t or b then
+ di.attributes = {
+ accent = t and "true" or nil,
+ accentunder = b and "true" or nil,
+ }
+ di.detail = nil
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mroot" then
+ local data = di.data
+ local size = #data
+ if size == 1 then
+ -- else firefox complains ... code in math-tag (for pdf tagging)
+ di.element = "msqrt"
+ elseif size == 2 then
+ data[1], data[2] = data[2], data[1]
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "break" then
+ di.skip = "comment"
+ i = i + 1
+ elseif tg == "mtext" then
+ -- this is only needed for unboxed mtexts ... all kind of special
+ -- tex border cases and optimizations ... trial and error
+ local data = di.data
+ if #data > 1 then
+ for i=1,#data do
+ local di = data[i]
+ local content = di.content
+ if content then
+ data[i] = {
+ element = "mtext",
+ nature = "inline",
+ data = { di },
+ n = 0,
+ }
+ elseif di.tg == "math" then
+ local di = di.data[1]
+ data[i] = di
+ checkmath(di)
+ end
+ end
+ di.element = "mrow"
+ -- di.tg = "mrow"
+ -- di.nature = "inline"
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mrow" and detail then -- hm, falls through
+ di.detail = nil
+ checkmath(di)
+ di = {
+ element = "maction",
+ nature = "display",
+ attributes = { actiontype = detail },
+ data = { di },
+ n = 0,
+ }
+ data[i] = di
+ i = i + 1
+ else
+ local category = di.mathcategory
+ if category then
+ -- no checkmath(di) here
+ if category == 1 then -- mo
+ i = collapse(di,i,data,ndata,detail,"mo")
+ elseif category == 2 then -- mi
+ i = collapse(di,i,data,ndata,detail,"mi")
+ elseif category == 3 then -- mn
+ i = collapse(di,i,data,ndata,detail,"mn")
+ elseif category == 4 then -- ms
+ i = collapse(di,i,data,ndata,detail,"ms")
+ elseif category >= 1000 then
+ local apply = category >= 2000
+ if apply then
+ category = category - 1000
+ end
+ if tg == "mi" then -- function
+ if roottg == "mrow" then
+ root.skip = "comment"
+ root.element = "function"
+ end
+ i = collapse(di,i,data,ndata,detail,"mi")
+ local tag = functions[category]
+ if tag then
+ di.data = functioncontent[tag]
+ end
+ if apply then
+ di.after = apply_function
+ elseif automathapply then -- make function
+ local following
+ if i <= ndata then
+ -- normally not the case
+ following = data[i]
+ else
+ local parent = di.__p__ -- == root
+ if parent.tg == "mrow" then
+ parent = parent.__p__
+ end
+ local index = parent.__i__
+ following = parent.data[index+1]
+ end
+ if following then
+ local tg = following.tg
+ if tg == "mrow" or tg == "mfenced" then -- we need to figure out the right condition
+ di.after = apply_function
+ end
+ end
+ end
+ else -- some problem
+ checkmath(di)
+ i = i + 1
+ end
+ else
+ checkmath(di)
+ i = i + 1
+ end
+ elseif automathnumber and tg == "mn" then
+ checkmath(di)
+ i = collapse_mn(di,i,data,ndata)
+ else
+ checkmath(di)
+ i = i + 1
+ end
+ end
+ else -- can be string or boolean
+ if parenttg ~= "mtext" and di == " " then
+ data[i] = false
+ end
+ i = i + 1
+ end
+ end
+ end
+ end
+
+ local function stripmath(di)
+ if not di then
+ --
+ elseif di.content then
+ return di
+ else
+ local tg = di.tg
+ if tg == "mtext" or tg == "ms" then
+ return di
+ else
+ local data = di.data
+ local ndata = #data
+ local n = 0
+ for i=1,ndata do
+ local d = data[i]
+ if d and not d.content then
+ d = stripmath(d)
+ end
+ if d then
+ local content = d.content
+ if not content then
+ n = n + 1
+ d.__i__ = n
+ data[n] = d
+ elseif content == " " or content == "" then
+ if di.tg == "mspace" then
+ -- we append or prepend a space to a preceding or following mtext
+ local parent = di.__p__
+ local index = di.__i__ -- == i
+ local data = parent.data
+ if index > 1 then
+ local d = data[index-1]
+ if d.tg == "mtext" then
+ local dd = d.data
+ local dn = dd[#dd]
+ local dc = dn.content
+ if dc then
+ dn.content = dc .. content
+ end
+ end
+ elseif index < ndata then
+ local d = data[index+1]
+ if d.tg == "mtext" then
+ local dd = d.data
+ local dn = dd[1]
+ local dc = dn.content
+ if dc then
+ dn.content = content .. dc
+ end
+ end
+ end
+ end
+ else
+ n = n + 1
+ data[n] = d
+ end
+ end
+ end
+ for i=ndata,n+1,-1 do
+ data[i] = nil
+ end
+ if #data > 0 then
+ return di
+ end
+-- end
+ end
+ -- could be integrated but is messy then
+-- while roottg == "mrow" and #data == 1 do
+-- data = data[1]
+-- for k, v in next, data do
+-- root[k] = v
+-- end
+-- roottg = data.tg
+-- end
+ end
+ end
+
+ function checks.math(di)
+ local specification = specifications[di.fulltag]
+ local mode = specification and specification.mode == "display" and "block" or "inline"
+ di.attributes = {
+ ["display"] = mode,
+ ["xmlns:m"] = mathmlns,
+ }
+ -- can be option if needed:
+ if mode == "inline" then
+ -- di.nature = "mixed" -- else spacing problem (maybe inline)
+ di.nature = "inline" -- we need to catch x$X$x and x $X$ x
+ else
+ di.nature = "display"
+ end
+ if automathstrip then
+ stripmath(di)
+ end
+ checkmath(di)
+ end
+
+ local a, z, A, Z = 0x61, 0x7A, 0x41, 0x5A
+
+ function extras.mi(di,element,n,fulltag) -- check with content
+ local str = di.data[1].content
+ if str and sub(str,1,1) ~= "&" then -- hack but good enough (maybe gsub op eerste)
+ for v in utfvalues(str) do
+ if (v >= a and v <= z) or (v >= A and v <= Z) then
+ local a = di.attributes
+ if a then
+ a.mathvariant = "normal"
+ else
+ di.attributes = { mathvariant = "normal" }
+ end
+ end
+ end
+ end
+ end
+
+ function extras.msub(di,element,n,fulltag)
+ -- m$^2$
+ local data = di.data
+ if #data == 1 then
+ local d = data[1]
+ data[2] = d
+ d.__i__ = 2
+ data[1] = dummy_nucleus
+ end
+ end
+
+ extras.msup = extras.msub
+
+end
+
+do
+
+ local registered = structures.sections.registered
+
+ local function resolve(di,element,n,fulltag)
+ local data = listdata[fulltag]
+ if data then
+ extras.addreference(di,data.references)
+ return true
+ else
+ local data = di.data
+ if data then
+ for i=1,#data do
+ local di = data[i]
+ if di then
+ local ft = di.fulltag
+ if ft and resolve(di,element,n,ft) then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function extras.section(di,element,n,fulltag)
+ local r = registered[specifications[fulltag].detail]
+ if r then
+ setattribute(di,"level",r.level)
+ end
+ resolve(di,element,n,fulltag)
+ end
+
+ extras.float = resolve
+
+ -- todo: internal is already hashed
+
+ function structurestags.setlist(n)
+ local data = structures.lists.getresult(n)
+ if data then
+ referencehash[locatedtag("listitem")] = data
+ end
+ end
+
+ function extras.listitem(di,element,n,fulltag)
+ local data = referencehash[fulltag]
+ if data then
+ extras.addinternal(di,data.references)
+ return true
+ end
+ end
+
+end
+
+do
+
+ -- todo: internal is already hashed
+
+ function structurestags.setregister(tag,n) -- check if tag is needed
+ local data = structures.registers.get(tag,n)
+ if data then
+ referencehash[locatedtag("registerlocation")] = data
+ end
+ end
+
+ function extras.registerlocation(di,element,n,fulltag)
+ local data = referencehash[fulltag]
+ if type(data) == "table" then
+ extras.addinternal(di,data.references)
+ return true
+ else
+ -- needs checking, probably bookmarks
+ end
+ end
+
+ extras.registerpages = ignorebreaks
+ extras.registerseparator = ignorespaces
+
+end
+
+do
+
+ local tabledata = { }
+
+ local function hascontent(data)
+ for i=1,#data do
+ local di = data[i]
+ if not di then
+ --
+ elseif di.content then
+ return true
+ else
+ local d = di.data
+ if d and #d > 0 and hascontent(d) then
+ return true
+ end
+ end
+ end
+ end
+
+ function structurestags.settablecell(rows,columns,align)
+ if align > 0 or rows > 1 or columns > 1 then
+ tabledata[locatedtag("tablecell")] = {
+ rows = rows,
+ columns = columns,
+ align = align,
+ }
+ end
+ end
+
+ function extras.tablecell(di,element,n,fulltag)
+ local hash = tabledata[fulltag]
+ if hash then
+ local columns = hash.columns
+ if columns and columns > 1 then
+ setattribute(di,"columns",columns)
+ end
+ local rows = hash.rows
+ if rows and rows > 1 then
+ setattribute(di,"rows",rows)
+ end
+ local align = hash.align
+ if not align or align == 0 then
+ -- normal
+ elseif align == 1 then -- use numbertoalign here
+ setattribute(di,"align","flushright")
+ elseif align == 2 then
+ setattribute(di,"align","middle")
+ elseif align == 3 then
+ setattribute(di,"align","flushleft")
+ end
+ end
+ end
+
+ local tabulatedata = { }
+
+ function structurestags.settabulatecell(align)
+ if align > 0 then
+ tabulatedata[locatedtag("tabulatecell")] = {
+ align = align,
+ }
+ end
+ end
+
+ function extras.tabulate(di,element,n,fulltag)
+ local data = di.data
+ for i=1,#data do
+ local di = data[i]
+ if di.tg == "tabulaterow" and not hascontent(di.data) then
+ di.element = "" -- or simply remove
+ end
+ end
+ end
+
+ function extras.tabulatecell(di,element,n,fulltag)
+ local hash = tabulatedata[fulltag]
+ if hash then
+ local align = hash.align
+ if not align or align == 0 then
+ -- normal
+ elseif align == 1 then
+ setattribute(di,"align","flushleft")
+ elseif align == 2 then
+ setattribute(di,"align","flushright")
+ elseif align == 3 then
+ setattribute(di,"align","middle")
+ end
+ end
+ end
+
+end
+
+-- flusher
+
+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_empty_inline = formatters["<%s/>"]
+ local f_empty_mixed = formatters["%w<%s/>\n"]
+ local f_empty_display = formatters["\n%w<%s/>\n"]
+ local f_empty_inline_attr = formatters["<%s%s/>"]
+ local f_empty_mixed_attr = formatters["%w<%s%s/>"]
+ local f_empty_display_attr = formatters["\n%w<%s%s/>\n"]
+
+ local f_begin_inline = formatters["<%s>"]
+ local f_begin_mixed = formatters["%w<%s>"]
+ local f_begin_display = formatters["\n%w<%s>\n"]
+ local f_begin_inline_attr = formatters["<%s%s>"]
+ local f_begin_mixed_attr = formatters["%w<%s%s>"]
+ local f_begin_display_attr = formatters["\n%w<%s%s>\n"]
+
+ local f_end_inline = formatters["</%s>"]
+ local f_end_mixed = formatters["</%s>\n"]
+ local f_end_display = formatters["%w</%s>\n"]
+
+ local f_begin_inline_comment = formatters["<!-- %s --><%s>"]
+ local f_begin_mixed_comment = formatters["%w<!-- %s --><%s>"]
+ local f_begin_display_comment = formatters["\n%w<!-- %s -->\n%w<%s>\n"]
+ local f_begin_inline_attr_comment = formatters["<!-- %s --><%s%s>"]
+ local f_begin_mixed_attr_comment = formatters["%w<!-- %s --><%s%s>"]
+ local f_begin_display_attr_comment = formatters["\n%w<!-- %s -->\n%w<%s%s>\n"]
+
+ local f_comment_begin_inline = formatters["<!-- begin %s -->"]
+ local f_comment_begin_mixed = formatters["%w<!-- begin %s -->"]
+ local f_comment_begin_display = formatters["\n%w<!-- begin %s -->\n"]
+
+ local f_comment_end_inline = formatters["<!-- end %s -->"]
+ local f_comment_end_mixed = formatters["<!-- end %s -->\n"]
+ local f_comment_end_display = formatters["%w<!-- end %s -->\n"]
+
+ local f_metadata_begin = formatters["\n%w<metadata>\n"]
+ local f_metadata = formatters["%w<metavariable name=%q>%s</metavariable>\n"]
+ local f_metadata_end = formatters["%w</metadata>\n"]
+
+ --- we could share the r tables ... but it's fast enough anyway
+
+ local function attributes(a)
+ local r = { } -- can be shared
+ local n = 0
+ for k, v in next, a do
+ n = n + 1
+ r[n] = f_attribute(k,v) -- lpegmatch(p_escaped,v)
+ end
+ return concat(r,"",1,n)
+ end
+
+ local depth = 0
+ local inline = 0
+
+ local function bpar(result)
+ result[#result+1] = "\n<p>"
+ end
+ local function epar(result)
+ result[#result+1] = "</p>\n"
+ end
+
+ local function emptytag(result,embedded,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
+ result[#result+1] = f_empty_display_attr(depth,namespaced[element],attributes(a))
+ elseif nature == "mixed" then
+ result[#result+1] = f_empty_mixed_attr(depth,namespaced[element],attributes(a))
+ else
+ result[#result+1] = f_empty_inline_attr(namespaced[element],attributes(a))
+ end
+ else
+ if nature == "display" then
+ result[#result+1] = f_empty_display(depth,namespaced[element])
+ elseif nature == "mixed" then
+ result[#result+1] = f_empty_mixed(depth,namespaced[element])
+ else
+ result[#result+1] = f_empty_inline(namespaced[element])
+ end
+ end
+ end
+
+ local function begintag(result,embedded,element,nature,di,skip)
+ local index = di.n
+ local fulltag = di.fulltag
+ local specification = specifications[fulltag] or { } -- we can have a dummy
+ local comment = di.comment
+ local detail = specification.detail
+ if skip == "comment" then
+ if show_comment then
+ if nature == "inline" or inline > 0 then
+ result[#result+1] = f_comment_begin_inline(namespaced[element])
+ inline = inline + 1
+ elseif nature == "mixed" then
+ result[#result+1] = f_comment_begin_mixed(depth,namespaced[element])
+ depth = depth + 1
+ inline = 1
+ else
+ result[#result+1] = f_comment_begin_display(depth,namespaced[element])
+ depth = depth + 1
+ end
+ end
+ elseif skip then
+ -- 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
+ detail = gsub(detail,"[^A-Za-z0-9]+","-")
+ specification.detail = detail -- we use it later in for the div
+ n = n + 1
+ r[n] = f_detail(detail)
+ end
+ local parents = specification.parents
+ if parents then
+ parents = gsub(parents,"[^A-Za-z0-9 ]+","-")
+ specification.parents = parents -- we use it later in for the div
+ n = n + 1
+ r[n] = f_chain(parents)
+ end
+ if indexing and index then
+ n = n + 1
+ r[n] = f_index(index)
+ end
+ local extra = extras[element]
+ if extra then
+ extra(di,element,index,fulltag)
+ end
+ if exportproperties then
+ local p = specification.userdata
+ if not p then
+ -- skip
+ elseif exportproperties == v_yes then
+ for k, v in next, p do
+ n = n + 1
+ r[n] = f_attribute(k,v)
+ end
+ else
+ for k, v in next, p do
+ n = n + 1
+ r[n] = f_property(exportproperties,k,v)
+ end
+ end
+ end
+ local a = di.attributes
+ if a then
+ for k, v in next, a do
+ n = n + 1
+ r[n] = f_attribute(k,v)
+ end
+ end
+ if n == 0 then
+ if nature == "inline" or inline > 0 then
+ if show_comment and comment then
+ result[#result+1] = f_begin_inline_comment(comment,namespaced[element])
+ else
+ result[#result+1] = f_begin_inline(namespaced[element])
+ end
+ inline = inline + 1
+ elseif nature == "mixed" then
+ if show_comment and comment then
+ result[#result+1] = f_begin_mixed_comment(depth,comment,namespaced[element])
+ else
+ result[#result+1] = f_begin_mixed(depth,namespaced[element])
+ end
+ depth = depth + 1
+ inline = 1
+ else
+ if show_comment and comment then
+ result[#result+1] = f_begin_display_comment(depth,comment,depth,namespaced[element])
+ else
+ result[#result+1] = f_begin_display(depth,namespaced[element])
+ end
+ depth = depth + 1
+ end
+ else
+ r = concat(r,"",1,n)
+ if nature == "inline" or inline > 0 then
+ if show_comment and comment then
+ result[#result+1] = f_begin_inline_attr_comment(comment,namespaced[element],r)
+ else
+ result[#result+1] = f_begin_inline_attr(namespaced[element],r)
+ end
+ inline = inline + 1
+ elseif nature == "mixed" then
+ if show_comment and comment then
+ result[#result+1] = f_begin_mixed_attr_comment(depth,comment,namespaced[element],r)
+ else
+ result[#result+1] = f_begin_mixed_attr(depth,namespaced[element],r)
+ end
+ depth = depth + 1
+ inline = 1
+ else
+ if show_comment and comment then
+ result[#result+1] = f_begin_display_attr_comment(depth,comment,depth,namespaced[element],r)
+ else
+ result[#result+1] = f_begin_display_attr(depth,namespaced[element],r)
+ end
+ depth = depth + 1
+ end
+ end
+ end
+ used[element][detail or ""] = { nature, specification.parents } -- for template css
+ -- also in last else ?
+ local metadata = specification.metadata
+ if metadata then
+ result[#result+1] = f_metadata_begin(depth)
+ for k, v in table.sortedpairs(metadata) do
+ result[#result+1] = f_metadata(depth+1,k,lpegmatch(p_entity,v))
+ end
+ result[#result+1] = f_metadata_end(depth)
+ end
+ end
+
+ local function endtag(result,embedded,element,nature,di,skip)
+ if skip == "comment" then
+ if show_comment then
+ if nature == "display" and (inline == 0 or inline == 1) then
+ depth = depth - 1
+ result[#result+1] = f_comment_end_display(depth,namespaced[element])
+ inline = 0
+ elseif nature == "mixed" and (inline == 0 or inline == 1) then
+ depth = depth - 1
+ result[#result+1] = f_comment_end_mixed(namespaced[element])
+ inline = 0
+ else
+ inline = inline - 1
+ result[#result+1] = f_comment_end_inline(namespaced[element])
+ end
+ end
+ elseif skip then
+ -- ignore
+ else
+ if nature == "display" and (inline == 0 or inline == 1) then
+ depth = depth - 1
+ result[#result+1] = f_end_display(depth,namespaced[element])
+ inline = 0
+ elseif nature == "mixed" and (inline == 0 or inline == 1) then
+ depth = depth - 1
+ result[#result+1] = f_end_mixed(namespaced[element])
+ inline = 0
+ else
+ 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 nofdata = #data
+ for i=1,nofdata do
+ local di = data[i]
+ if not di then -- hm, di can be string
+ -- whatever
+ else
+ local content = di.content
+ -- also optimize for content == "" : trace that first
+ if content then
+ -- already has breaks
+ local content = lpegmatch(p_entity,content)
+ if i == nofdata and sub(content,-1) == "\n" then -- move check
+ -- can be an end of line in par but can also be the last line
+ if trace_spacing then
+ result[#result+1] = f_spacing(di.parnumber or 0,sub(content,1,-2))
+ else
+ result[#result+1] = sub(content,1,-2)
+ end
+ result[#result+1] = " "
+ else
+ if trace_spacing then
+ result[#result+1] = f_spacing(di.parnumber or 0,content)
+ else
+ result[#result+1] = content
+ end
+ end
+ elseif not di.collapsed then -- ignore collapsed data (is appended, reconstructed par)
+ local element = di.element
+ if not element then
+ -- skip
+ elseif element == "break" then -- or element == "pagebreak"
+ emptytag(result,embedded,element,nature,di)
+ elseif element == "" or di.skip == "ignore" then
+ -- skip
+ else
+ if di.before then
+ flushtree(result,embedded,di.before,nature)
+ end
+ local natu = di.nature
+ local skip = di.skip
+ if di.breaknode then
+ emptytag(result,embedded,"break","display",di)
+ end
+ begintag(result,embedded,element,natu,di,skip)
+ flushtree(result,embedded,di.data,natu)
+ endtag(result,embedded,element,natu,di,skip)
+ if di.after then
+ flushtree(result,embedded,di.after,nature)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local function breaktree(tree,parent,parentelement) -- also removes double breaks
+ local data = tree.data
+ if data then
+ local nofdata = #data
+ local prevelement
+ local prevnature
+ local prevparnumber
+ local newdata = { }
+ local nofnewdata = 0
+ for i=1,nofdata do
+ local di = data[i]
+ if not di then
+ -- skip
+ elseif di.content then
+ local parnumber = di.parnumber
+ if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevelement = nil
+ prevnature = "inline"
+ prevparnumber = parnumber
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ elseif not di.collapsed then
+ local element = di.element
+ if element == "break" then -- or element == "pagebreak"
+ if prevelement == "break" then
+ di.element = ""
+ end
+ prevelement = element
+ prevnature = "display"
+ elseif element == "" or di.skip == "ignore" then
+ -- skip
+ else
+ local nature = di.nature
+ local parnumber = di.parnumber
+ if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevnature = nature
+ prevparnumber = parnumber
+ prevelement = element
+ breaktree(di,tree,element)
+ end
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ else
+ local nature = di.nature
+ local parnumber = di.parnumber
+ if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevnature = nature
+ prevparnumber = parnumber
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ end
+ end
+ tree.data = newdata
+ end
+ end
+
+ -- also tabulaterow reconstruction .. maybe better as a checker
+ -- i.e cell attribute
+
+ local function collapsetree()
+ for tag, trees in next, treehash do
+ local d = trees[1].data
+ if d then
+ local nd = #d
+ if nd > 0 then
+ for i=2,#trees do
+ local currenttree = trees[i]
+ local currentdata = currenttree.data
+ local currentpar = currenttree.parnumber
+ local previouspar = trees[i-1].parnumber
+ currenttree.collapsed = true
+ -- is the next ok?
+ if previouspar == 0 or not (di and di.content) then
+ previouspar = nil -- no need anyway so no further testing needed
+ end
+ for j=1,#currentdata do
+ local cd = currentdata[j]
+ if not cd or cd == "" then
+ -- skip
+ elseif cd.content then
+ if not currentpar then
+ -- add space ?
+ elseif not previouspar then
+ -- add space ?
+ elseif currentpar ~= previouspar then
+ nd = nd + 1
+ if trace_spacing then
+ d[nd] = makebreaknode { type = "d", p = previouspar, n = currentpar }
+ else
+ d[nd] = makebreaknode()
+ end
+ end
+ previouspar = currentpar
+ nd = nd + 1
+ d[nd] = cd
+ else
+ nd = nd + 1
+ d[nd] = cd
+ end
+ currentdata[j] = false
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local function finalizetree(tree)
+ for _, finalizer in next, finalizers do
+ finalizer(tree)
+ end
+ end
+
+ local function indextree(tree)
+ local data = tree.data
+ if data then
+ local n, new = 0, { }
+ for i=1,#data do
+ local d = data[i]
+ if not d then
+ -- skip
+ elseif d.content then
+ n = n + 1
+ new[n] = d
+ elseif not d.collapsed then
+ n = n + 1
+ d.__i__ = n
+ d.__p__ = tree
+ indextree(d)
+ new[n] = d
+ end
+ end
+ tree.data = new
+ end
+ end
+
+ local function checktree(tree)
+ local data = tree.data
+ if data then
+ for i=1,#data do
+ local d = data[i]
+ if type(d) == "table" then
+ local check = checks[d.tg]
+ if check then
+ check(d)
+ end
+ checktree(d)
+ end
+ end
+ end
+ end
+
+ wrapups.flushtree = flushtree
+ wrapups.breaktree = breaktree
+ wrapups.collapsetree = collapsetree
+ wrapups.finalizetree = finalizetree
+ wrapups.indextree = indextree
+ wrapups.checktree = checktree
+
+end
+
+-- collector code
+
+local function push(fulltag,depth)
+ local tg, n, detail
+ local specification = specifications[fulltag]
+ if specification then
+ tg = specification.tagname
+ n = specification.tagindex
+ detail = specification.detail
+ else
+ -- a break (more efficient if we don't store those in specifications)
+ tg, n = lpegmatch(tagsplitter,fulltag)
+ n = tonumber(n) -- to tonumber in tagsplitter
+ end
+ local p = properties[tg]
+ local element = p and p.export or tg
+ local nature = p and p.nature or "inline" -- defaultnature
+ local treedata = tree.data
+ local t = { -- maybe we can use the tag table
+ tg = tg,
+ fulltag = fulltag,
+ detail = detail,
+ n = n, -- already a number
+ element = element,
+ nature = nature,
+ data = { },
+ attribute = currentattribute,
+ parnumber = currentparagraph,
+ }
+ treedata[#treedata+1] = t
+ currentdepth = currentdepth + 1
+ nesting[currentdepth] = fulltag
+ treestack[currentdepth] = tree
+ if trace_export then
+ if detail and detail ~= "" then
+ report_export("%w<%s trigger=%q n=%q paragraph=%q index=%q detail=%q>",currentdepth-1,tg,n,currentattribute or 0,currentparagraph or 0,#treedata,detail)
+ else
+ report_export("%w<%s trigger=%q n=%q paragraph=%q index=%q>",currentdepth-1,tg,n,currentattribute or 0,currentparagraph or 0,#treedata)
+ end
+ end
+ tree = t
+ if tg == "break" then
+ -- no need for this
+ else
+ local h = treehash[fulltag]
+ if h then
+ h[#h+1] = t
+ else
+ treehash[fulltag] = { t }
+ end
+ end
+end
+
+local function pop()
+ if currentdepth > 0 then
+ local top = nesting[currentdepth]
+ tree = treestack[currentdepth]
+ currentdepth = currentdepth - 1
+ if trace_export then
+ if top then
+ report_export("%w</%s>",currentdepth,top)
+ else
+ report_export("</%s>",top)
+ end
+ end
+ else
+ report_export("%w<!-- too many pops -->",currentdepth)
+ end
+end
+
+local function continueexport()
+ if nofcurrentcontent > 0 then
+ if trace_export then
+ report_export("%w<!-- injecting pagebreak space -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " " -- pagebreak
+ end
+end
+
+local function pushentry(current)
+ if not current then
+ -- bad news
+ return
+ end
+ current = current.taglist
+ if not current then
+ -- even worse news
+ return
+ end
+ if restart then
+ continueexport()
+ restart = false
+ end
+ local newdepth = #current
+ local olddepth = currentdepth
+ if trace_export then
+ report_export("%w<!-- moving from depth %s to %s (%s) -->",currentdepth,olddepth,newdepth,current[newdepth])
+ end
+ if olddepth <= 0 then
+ for i=1,newdepth do
+ push(current[i],i)
+ end
+ else
+ local difference
+ if olddepth < newdepth then
+ for i=1,olddepth do
+ if current[i] ~= nesting[i] then
+ difference = i
+ break
+ end
+ end
+ else
+ for i=1,newdepth do
+ if current[i] ~= nesting[i] then
+ difference = i
+ break
+ end
+ end
+ end
+ if difference then
+ for i=olddepth,difference,-1 do
+ pop()
+ end
+ for i=difference,newdepth do
+ push(current[i],i)
+ end
+ elseif newdepth > olddepth then
+ for i=olddepth+1,newdepth do
+ push(current[i],i)
+ end
+ elseif newdepth < olddepth then
+ for i=olddepth,newdepth,-1 do
+ pop()
+ end
+ elseif trace_export then
+ report_export("%w<!-- staying at depth %s (%s) -->",currentdepth,newdepth,nesting[newdepth] or "?")
+ end
+ end
+ return olddepth, newdepth
+end
+
+local function pushcontent(oldparagraph,newparagraph)
+ if nofcurrentcontent > 0 then
+ if oldparagraph then
+ if currentcontent[nofcurrentcontent] == "\n" then
+ if trace_export then
+ report_export("%w<!-- removing newline -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent - 1
+ end
+ end
+ local content = concat(currentcontent,"",1,nofcurrentcontent)
+ if content == "" then
+ -- omit; when oldparagraph we could push, remove spaces, pop
+ elseif somespace[content] and oldparagraph then
+ -- omit; when oldparagraph we could push, remove spaces, pop
+ else
+ local olddepth, newdepth
+ local list = taglist[currentattribute]
+ if list then
+ olddepth, newdepth = pushentry(list)
+ end
+ if tree then
+ local td = tree.data
+ 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%s",currentdepth,(gsub(content,"\n","\\n")))
+ report_export("%w<!-- stop content -->",currentdepth)
+ end
+ if olddepth then
+ for i=newdepth-1,olddepth,-1 do
+ pop()
+ end
+ end
+ end
+ end
+ nofcurrentcontent = 0
+ end
+ if oldparagraph then
+ pushentry(makebreaklist(currentnesting))
+ if trace_export then
+ report_export("%w<!-- break added between paragraph %a and %a -->",currentdepth,oldparagraph,newparagraph)
+ end
+ end
+end
+
+local function finishexport()
+ if trace_export then
+ report_export("%w<!-- start finalizing -->",currentdepth)
+ end
+ if nofcurrentcontent > 0 then
+ if somespace[currentcontent[nofcurrentcontent]] then
+ if trace_export then
+ report_export("%w<!-- removing space -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent - 1
+ end
+ pushcontent()
+ end
+ for i=currentdepth,1,-1 do
+ pop()
+ end
+ currentcontent = { } -- we're nice and do a cleanup
+ if trace_export then
+ report_export("%w<!-- stop finalizing -->",currentdepth)
+ end
+end
+
+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)
+ else
+ -- we could add tonunicodes for ligatures (todo)
+ local components = getfield(n,"components")
+ 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)
+ else
+ if last ~= at then
+ local tl = taglist[at]
+ pushcontent()
+ currentnesting = tl
+ currentparagraph = getattr(n,a_taggedpar) or pap
+ currentattribute = at
+ last = at
+ pushentry(currentnesting)
+ if trace_export then
+ report_export("%w<!-- processing glyph %C tagged %a -->",currentdepth,c,at)
+ end
+ -- We need to intercept this here; maybe I will also move this
+ -- to a regular setter at the tex end.
+ local r = getattr(n,a_reference)
+ if r then
+ local t = tl.taglist
+ referencehash[t[#t]] = r -- fulltag
+ end
+ --
+ elseif last then
+ -- we can consider tagging the pars (lines) in the parbuilder but then we loose some
+ -- information unless we inject a special node (but even then we can run into nesting
+ -- issues)
+ 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 glyph %C tagged %a) -->",currentdepth,c,last)
+ end
+ else
+ if trace_export then
+ report_export("%w<!-- processing glyph %C tagged %a) -->",currentdepth,c,at)
+ end
+ end
+ local s = getattr(n,a_exportstatus)
+ if s then
+ c = s
+ end
+ if c == 0 then
+ if trace_export then
+ report_export("%w<!-- skipping last glyph -->",currentdepth)
+ end
+ elseif c == 0x20 then
+ local a = getattr(n,a_characters)
+ nofcurrentcontent = nofcurrentcontent + 1
+ if a then
+ if trace_export then
+ report_export("%w<!-- turning last space into special space %U -->",currentdepth,a)
+ end
+ currentcontent[nofcurrentcontent] = specialspaces[a] -- special space
+ else
+ currentcontent[nofcurrentcontent] = " "
+ end
+ else
+ local fc = fontchar[getfont(n)]
+ if fc then
+ fc = fc and fc[c]
+ if fc then
+ local u = fc.unicode
+ if not u then
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
+ elseif type(u) == "table" then
+ for i=1,#u do
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(u[i])
+ end
+ else
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(u)
+ end
+ elseif c > 0 then
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
+ else
+ -- we can have -1 as side effect of an explicit hyphen (unless we expand)
+ end
+ elseif c > 0 then
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
+ else
+ -- we can have -1 as side effect of an explicit hyphen (unless we expand)
+ 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
+ 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)
+ 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
+ else
+ local subtype = getsubtype(n)
+ if subtype == userskip_code then
+ if getfield(n,"width") > threshold then
+ if last and not somespace[currentcontent[nofcurrentcontent]] then
+ local a = getattr(n,a_tagged) or pat
+ if a == last then
+ if trace_export then
+ report_export("%w<!-- injecting spacing 5a -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ elseif a then
+ -- e.g LOGO<space>LOGO
+ if trace_export then
+ report_export("%w<!-- processing glue > threshold tagged %s becomes %s -->",currentdepth,last,a)
+ end
+ pushcontent()
+ if trace_export then
+ report_export("%w<!-- injecting spacing 5b -->",currentdepth)
+ end
+ last = a
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ end
+ elseif subtype == spaceskip_code or subtype == xspaceskip_code then
+ if not somespace[currentcontent[nofcurrentcontent]] then
+ local a = getattr(n,a_tagged) or pat
+ if a == last then
+ if trace_export then
+ report_export("%w<!-- injecting spacing 7 (stay in element) -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ else
+ if trace_export then
+ report_export("%w<!-- injecting spacing 7 (end of element) -->",currentdepth)
+ end
+ last = a
+ pushcontent()
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ elseif subtype == rightskip_code then
+ -- a line
+ if nofcurrentcontent > 0 then
+ local r = currentcontent[nofcurrentcontent]
+ if r == hyphen then
+ if not keephyphens then
+ nofcurrentcontent = nofcurrentcontent - 1
+ end
+ elseif not somespace[r] then
+ local a = getattr(n,a_tagged) or pat
+ if a == last then
+ if trace_export then
+ report_export("%w<!-- injecting spacing 1 (end of line, stay in element) -->",currentdepth)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ else
+ if trace_export then
+ report_export("%w<!-- injecting spacing 1 (end of line, end of element) -->",currentdepth)
+ end
+ last = a
+ pushcontent()
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ end
+ elseif subtype == parfillskip_code then
+ -- deal with paragaph endings (crossings) elsewhere and we quit here
+ -- as we don't want the rightskip space addition
+ return
+ end
+ end
+ elseif id == 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
+ local at = getattr(n,a_tagged) or pat
+ collectresults(list,n,at)
+ end
+ end
+ elseif id == kern_code then
+ local kern = getfield(n,"kern")
+ if kern > 0 then
+ local limit = threshold
+ if p and getid(p) == glyph_code then
+ limit = fontquads[getfont(p)] / 4
+ 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 9 (kern %p) -->",currentdepth,kern)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ end
+ end
+ 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)
+ end
+ -- continueexport()
+ restart = true
+
+-- local function f(head,depth,pat)
+-- for n in node.traverse(head) do
+-- local a = n[a_tagged] or pat
+-- local t = taglist[a]
+-- print(depth,n,a,t and table.concat(t," "))
+-- if n.id == hlist_code or n.id == vlist_code and n.list then
+-- f(n.list,depth+1,a)
+-- end
+-- end
+-- end
+-- f(head,1)
+
+ collectresults(tonut(head))
+ if trace_export then
+ report_export("%w<!-- stop flushing page -->",currentdepth)
+ 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
+ setattr(n,a_textblock,0)
+ end
+ end
+ return false
+end
+
+do
+
+local xmlpreamble = [[
+<?xml version="1.0" encoding="UTF-8" standalone="%standalone%" ?>
+
+<!--
+
+ input filename : %filename%
+ processing date : %date%
+ context version : %contextversion%
+ exporter version : %exportversion%
+
+-->
+
+]]
+
+ local flushtree = wrapups.flushtree
+
+ local function wholepreamble(standalone)
+ return replacetemplate(xmlpreamble, {
+ standalone = standalone and "yes" or "no",
+ filename = tex.jobname,
+ date = os.date(),
+ contextversion = environment.version,
+ exportversion = exportversion,
+ })
+ end
+
+
+local csspreamble = [[
+<?xml-stylesheet type="text/css" href="%filename%" ?>
+]]
+
+local cssheadlink = [[
+<link type="text/css" rel="stylesheet" href="%filename%" />
+]]
+
+ local function allusedstylesheets(cssfiles,files,path)
+ local done = { }
+ local result = { }
+ local extras = { }
+ for i=1,#cssfiles do
+ local cssfile = cssfiles[i]
+ if type(cssfile) ~= "string" then
+ -- error
+ elseif cssfile == "export-example.css" then
+ -- ignore
+ elseif not done[cssfile] then
+ cssfile = file.join(path,cssfile)
+ report_export("adding css reference '%s'",cssfile)
+ files[#files+1] = cssfile
+ result[#result+1] = replacetemplate(csspreamble, { filename = cssfile })
+ extras[#extras+1] = replacetemplate(cssheadlink, { filename = cssfile })
+ done[cssfile] = true
+ end
+ end
+ return concat(result), concat(extras)
+ end
+
+local elementtemplate = [[
+/* element="%element%" detail="%detail%" chain="%chain%" */
+
+%element%, %namespace%div.%element% {
+ display: %display% ;
+}]]
+
+local detailtemplate = [[
+/* element="%element%" detail="%detail%" chain="%chain%" */
+
+%element%[detail=%detail%], %namespace%div.%element%.%detail% {
+ display: %display% ;
+}]]
+
+-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd" >
+
+local htmltemplate = [[
+%preamble%
+
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:math="http://www.w3.org/1998/Math/MathML">
+
+ <head>
+
+ <meta charset="utf-8"/>
+
+ <title>%title%</title>
+
+%style%
+
+ </head>
+ <body>
+ <div xmlns="http://www.pragma-ade.com/context/export">
+
+<div class="warning">Rendering can be suboptimal because there is no default/fallback css loaded.</div>
+
+%body%
+
+ </div>
+ </body>
+</html>
+]]
+
+ local displaymapping = {
+ inline = "inline",
+ display = "block",
+ mixed = "inline",
+ }
+
+ local function allusedelements(basename)
+ local result = { replacetemplate(namespacetemplate, {
+ what = "template",
+ filename = basename,
+ namespace = contextns,
+ -- cssnamespaceurl = usecssnamespace and cssnamespaceurl or "",
+ cssnamespaceurl = cssnamespaceurl,
+ }) }
+ for element, details in sortedhash(used) do
+ if namespaces[element] then
+ -- skip math
+ else
+ for detail, what in sortedhash(details) do
+ local nature = what[1] or "display"
+ local chain = what[2]
+ local display = displaymapping[nature] or "block"
+ if detail == "" then
+ result[#result+1] = replacetemplate(elementtemplate, {
+ element = element,
+ display = display,
+ chain = chain,
+ namespace = usecssnamespace and namespace or "",
+ })
+ else
+ result[#result+1] = replacetemplate(detailtemplate, {
+ element = element,
+ display = display,
+ detail = detail,
+ chain = chain,
+ namespace = usecssnamespace and cssnamespace or "",
+ })
+ end
+ end
+ end
+ end
+ return concat(result,"\n\n")
+ end
+
+ local function allcontent(tree,embed)
+ local result = { }
+ local embedded = embed and { }
+ flushtree(result,embedded,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
+ end
+
+ -- local xhtmlpreamble = [[
+ -- <!DOCTYPE html PUBLIC
+ -- "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
+ -- "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd"
+ -- >
+ -- ]]
+
+ local function cleanxhtmltree(xmltree)
+ if xmltree then
+ local implicits = { }
+ local explicits = { }
+ local overloads = { }
+ for e in xml.collected(xmltree,"*") do
+ local at = e.at
+ if at then
+ local explicit = at.explicit
+ local implicit = at.implicit
+ if explicit then
+ if not explicits[explicit] then
+ explicits[explicit] = true
+ at.id = explicit
+ if implicit then
+ overloads[implicit] = explicit
+ end
+ end
+ else
+ if implicit and not implicits[implicit] then
+ implicits[implicit] = true
+ at.id = "aut:" .. implicit
+ end
+ end
+ end
+ end
+ for e in xml.collected(xmltree,"*") do
+ local at = e.at
+ if at then
+ local internal = at.internal
+ local location = at.location
+ if internal then
+ if location then
+ local explicit = overloads[location]
+ if explicit then
+ at.href = "#" .. explicit
+ else
+ at.href = "#aut:" .. internal
+ end
+ else
+ at.href = "#aut:" .. internal
+ end
+ else
+ if location then
+ at.href = "#" .. location
+ else
+ local url = at.url
+ if url then
+ at.href = url
+ else
+ local file = at.file
+ if file then
+ at.href = file
+ end
+ end
+ end
+ end
+ end
+ end
+ return xmltree
+ else
+ return xml.convert('<?xml version="1.0"?>\n<error>invalid xhtml tree</error>')
+ end
+ end
+
+ -- maybe the reverse: be explicit about what is permitted
+
+ local private = {
+ destination = true,
+ prefix = true,
+ reference = true,
+ --
+ id = true,
+ href = true,
+ --
+ implicit = true,
+ explicit = true,
+ --
+ url = true,
+ file = true,
+ internal = true,
+ location = true,
+ --
+ name = true, -- image name
+ used = true, -- image name
+ page = true, -- image name
+ width = true,
+ height = true,
+ --
+ }
+
+ local addclicks = true
+ local f_onclick = formatters[ [[location.href='%s']] ]
+ local f_onclick = formatters[ [[location.href='%s']] ]
+
+ local p_cleanid = lpeg.replacer { [":"] = "-" }
+ local p_cleanhref = lpeg.Cs(lpeg.P("#") * p_cleanid)
+
+ local p_splitter = lpeg.Ct ( (
+ lpeg.Carg(1) * lpeg.C((1-lpeg.P(" "))^1) / function(d,s) if not d[s] then d[s] = true return s end end
+ * lpeg.P(" ")^0 )^1 )
+
+
+ local classes = table.setmetatableindex(function(t,k)
+ local v = concat(lpegmatch(p_splitter,k,1,{})," ")
+ t[k] = v
+ return v
+ end)
+
+ local function makeclass(tg,at)
+ local detail = at.detail
+ local chain = at.chain
+ local result
+ at.detail = nil
+ at.chain = nil
+ if detail and detail ~= "" then
+ if chain and chain ~= "" then
+ if chain ~= detail then
+ result = { classes[tg .. " " .. chain .. " " .. detail] } -- we need to remove duplicates
+ elseif tg ~= detail then
+ result = { tg, detail }
+ else
+ result = { tg }
+ end
+ elseif tg ~= detail then
+ result = { tg, detail }
+ else
+ result = { tg }
+ end
+ elseif chain and chain ~= "" then
+ if tg ~= chain then
+ result = { tg, chain }
+ else
+ result = { tg }
+ end
+ else
+ result = { tg }
+ end
+ for k, v in next, at do
+ if not private[k] then
+ result[#result+1] = k .. "-" .. v
+ end
+ end
+ return concat(result, " ")
+ end
+
+ local function remap(specification,source,target)
+ local comment = nil -- share comments
+ for c in xml.collected(source,"*") do
+ if not c.special then
+ local tg = c.tg
+ local ns = c.ns
+ if ns == "m" then
+ if false then -- yes or no
+ c.ns = ""
+ c.at["xmlns:m"] = nil
+ end
+ -- elseif tg == "a" then
+ -- c.ns = ""
+ else
+ -- if tg == "tabulatecell" or tg == "tablecell" then
+ local dt = c.dt
+ local nt = #dt
+ if nt == 0 or (nt == 1 and dt[1] == "") then
+ if comment then
+ c.dt = comment
+ else
+ xml.setcomment(c,"empty")
+ comment = c.dt
+ end
+ end
+ -- end
+ local at = c.at
+ local class = nil
+ if tg == "document" then
+ at.href = nil
+ at.detail = nil
+ at.chain = nil
+ elseif tg == "metavariable" then
+ at.detail = "metaname-" .. at.name
+ class = makeclass(tg,at)
+ else
+ class = makeclass(tg,at)
+ end
+ local id = at.id
+ local href = at.href
+ if id then
+ id = lpegmatch(p_cleanid, id) or id
+ if href then
+ href = lpegmatch(p_cleanhref,href) or href
+ c.at = {
+ class = class,
+ id = id,
+ href = href,
+ onclick = addclicks and f_onclick(href) or nil,
+ }
+ else
+ c.at = {
+ class = class,
+ id = id,
+ }
+ end
+ else
+ if href then
+ href = lpegmatch(p_cleanhref,href) or href
+ c.at = {
+ class = class,
+ href = href,
+ onclick = addclicks and f_onclick(href) or nil,
+ }
+ else
+ c.at = {
+ class = class,
+ }
+ end
+ end
+ c.tg = "div"
+ end
+ end
+ end
+ end
+
+ -- local cssfile = nil directives.register("backend.export.css", function(v) cssfile = v end)
+
+ local addsuffix = file.addsuffix
+ local joinfile = file.join
+
+ local embedfile = false directives.register("export.embed",function(v) embedfile = v end)
+ local embedmath = false
+
+ local function stopexport(v)
+
+ starttiming(treehash)
+ --
+ finishexport()
+ --
+ report_export("")
+ report_export("exporting xml, xhtml and html files")
+ report_export("")
+ --
+ wrapups.collapsetree(tree)
+ wrapups.indextree(tree)
+ wrapups.checktree(tree)
+ wrapups.breaktree(tree)
+ wrapups.finalizetree(tree)
+ --
+ wrapups.hashlistdata()
+ --
+ if type(v) ~= "string" or v == v_yes or v == "" then
+ v = tex.jobname
+ end
+
+ -- we use a dedicated subpath:
+ --
+ -- ./jobname-export
+ -- ./jobname-export/images
+ -- ./jobname-export/styles
+ -- ./jobname-export/styles
+ -- ./jobname-export/jobname-export.xml
+ -- ./jobname-export/jobname-export.xhtml
+ -- ./jobname-export/jobname-export.html
+ -- ./jobname-export/jobname-specification.lua
+ -- ./jobname-export/styles/jobname-defaults.css
+ -- ./jobname-export/styles/jobname-styles.css
+ -- ./jobname-export/styles/jobname-images.css
+ -- ./jobname-export/styles/jobname-templates.css
+
+ local basename = file.basename(v)
+ local corename = file.removesuffix(basename)
+ local basepath = basename .. "-export"
+ local imagepath = joinfile(basepath,"images")
+ local stylepath = joinfile(basepath,"styles")
+
+ local function validpath(what,pathname)
+ if lfs.isdir(pathname) then
+ report_export("using exiting %s path %a",what,pathname)
+ return pathname
+ end
+ lfs.mkdir(pathname)
+ if lfs.isdir(pathname) then
+ report_export("using cretated %s path %a",what,basepath)
+ return pathname
+ else
+ report_export("unable to create %s path %a",what,basepath)
+ return false
+ end
+ end
+
+ if not (validpath("export",basepath) and validpath("images",imagepath) and validpath("styles",stylepath)) then
+ return
+ end
+
+ -- we're now on the dedicated export subpath so we can't clash names
+
+ local xmlfilebase = addsuffix(basename .. "-raw","xml" )
+ local xhtmlfilebase = addsuffix(basename .. "-tag","xhtml")
+ local htmlfilebase = addsuffix(basename .. "-div","xhtml")
+ local specificationfilebase = addsuffix(basename .. "-pub","lua" )
+
+ local xmlfilename = joinfile(basepath, xmlfilebase )
+ local xhtmlfilename = joinfile(basepath, xhtmlfilebase )
+ local htmlfilename = joinfile(basepath, htmlfilebase )
+ local specificationfilename = joinfile(basepath, specificationfilebase)
+ --
+ local defaultfilebase = addsuffix(basename .. "-defaults", "css")
+ local imagefilebase = addsuffix(basename .. "-images", "css")
+ local stylefilebase = addsuffix(basename .. "-styles", "css")
+ local templatefilebase = addsuffix(basename .. "-templates","css")
+ --
+ local defaultfilename = joinfile(stylepath,defaultfilebase )
+ local imagefilename = joinfile(stylepath,imagefilebase )
+ local stylefilename = joinfile(stylepath,stylefilebase )
+ local templatefilename = joinfile(stylepath,templatefilebase)
+
+ local cssfile = finetuning.cssfile
+
+ -- we keep track of all used files
+
+ local files = {
+ }
+
+ -- we always load the defaults and optionally extra css files; we also copy the example
+ -- css file so that we always have the latest version
+
+ local cssfiles = {
+ defaultfilebase,
+ imagefilebase,
+ stylefilebase,
+ }
+
+ local examplefilename = resolvers.find_file("export-example.css")
+ if examplefilename then
+ local data = io.loaddata(examplefilename)
+ if not data or data == "" then
+ data = "/* missing css file */"
+ elseif not usecssnamespace then
+ data = gsub(data,cssnamespace,"")
+ end
+ io.savedata(defaultfilename,data)
+ end
+
+ if cssfile then
+ local list = table.unique(settings_to_array(cssfile))
+ for i=1,#list do
+ local source = addsuffix(list[i],"css")
+ local target = joinfile(stylepath,file.basename(source))
+ cssfiles[#cssfiles+1] = source
+ if not lfs.isfile(source) then
+ source = joinfile("../",source)
+ end
+ if lfs.isfile(source) then
+ report_export("copying %s",source)
+ file.copy(source,target)
+ end
+ end
+ end
+
+ 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
+ -- only for testing
+ attach {
+ data = concat{ wholepreamble(true), result },
+ name = file.basename(xmlfilename),
+ registered = "export",
+ title = "raw xml export",
+ method = v_hidden,
+ mimetype = "application/mathml+xml",
+ }
+ end
+ -- if embedmath and attach then
+ -- local refs = { }
+ -- for k, v in sortedhash(embedded) do
+ -- attach {
+ -- data = v,
+ -- file = file.basename(k),
+ -- name = file.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),
+ x_styles, -- adds to files
+ result,
+ }
+
+ cssfiles = table.unique(cssfiles)
+
+ -- we're now ready for saving the result in the xml file
+
+ report_export("saving xml data in %a",xmlfilename)
+ io.savedata(xmlfilename,result)
+
+ report_export("saving css image definitions in %a",imagefilename)
+ io.savedata(imagefilename,wrapups.allusedimages(basename))
+
+ report_export("saving css style definitions in %a",stylefilename)
+ io.savedata(stylefilename,wrapups.allusedstyles(basename))
+
+ report_export("saving css template in %a",templatefilename)
+ io.savedata(templatefilename,allusedelements(basename))
+
+ -- additionally we save an xhtml file; for that we load the file as xml tree
+
+ report_export("saving xhtml variant in %a",xhtmlfilename)
+
+ local xmltree = cleanxhtmltree(xml.convert(result))
+
+ xml.save(xmltree,xhtmlfilename)
+
+ -- now we save a specification file that can b eused for generating an epub file
+
+ -- looking at identity is somewhat redundant as we also inherit from interaction
+ -- at the tex end
+
+ local identity = interactions.general.getidentity()
+
+ local specification = {
+ name = file.removesuffix(v),
+ identifier = os.uuid(),
+ images = wrapups.uniqueusedimages(),
+ imagefile = joinfile("styles",imagefilebase),
+ imagepath = "images",
+ stylepath = "styles",
+ xmlfiles = { xmlfilebase },
+ xhtmlfiles = { xhtmlfilebase },
+ htmlfiles = { htmlfilebase },
+ styles = cssfiles,
+ htmlroot = htmlfilebase,
+ language = languagenames[texgetcount("mainlanguagenumber")],
+ title = validstring(finetuning.title) or validstring(identity.title),
+ subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle),
+ author = validstring(finetuning.author) or validstring(identity.author),
+ firstpage = validstring(finetuning.firstpage),
+ lastpage = validstring(finetuning.lastpage),
+ }
+
+ report_export("saving specification in %a",specificationfilename,specificationfilename)
+
+ io.savedata(specificationfilename,table.serialize(specification,true))
+
+ -- the html export for epub is different in the sense that it uses div's instead of
+ -- specific tags
+
+ report_export("saving div based alternative in %a",htmlfilename)
+
+ remap(specification,xmltree)
+
+ local title = specification.title
+
+ if not title or title == "" then
+ title = "no title" -- believe it or not, but a <title/> can prevent viewing in browsers
+ end
+
+ local variables = {
+ style = h_styles,
+ body = xml.tostring(xml.first(xmltree,"/div")),
+ preamble = wholepreamble(false),
+ title = title,
+ }
+
+ io.savedata(htmlfilename,replacetemplate(htmltemplate,variables,"xml"))
+
+ -- finally we report how an epub file can be made (using the specification)
+
+ report_export("")
+ report_export('create epub with: mtxrun --script epub --make "%s" [--purge --rename --svgmath]',file.nameonly(basename))
+ report_export("")
+
+ stoptiming(treehash)
+ end
+
+ local appendaction = nodes.tasks.appendaction
+ local enableaction = nodes.tasks.enableaction
+
+ function structurestags.setupexport(t)
+ merge(finetuning,t)
+ keephyphens = finetuning.hyphen == v_yes
+ exportproperties = finetuning.properties
+ if exportproperties == v_no then
+ exportproperties = false
+ end
+ end
+
+ local function startexport(v)
+ if v and not exporting then
+ report_export("enabling export to xml")
+ -- not yet known in task-ini
+ appendaction("shipouts","normalizers", "nodes.handlers.export")
+ -- enableaction("shipouts","nodes.handlers.export")
+ enableaction("shipouts","nodes.handlers.accessibility")
+ enableaction("math", "noads.handlers.tags")
+ -- appendaction("finalizers","lists","builders.paragraphs.tag")
+ -- enableaction("finalizers","builders.paragraphs.tag")
+ luatex.registerstopactions(structurestags.finishexport)
+ exporting = v
+ end
+ end
+
+ function structurestags.finishexport()
+ if exporting then
+ stopexport(exporting)
+ exporting = false
+ end
+ end
+
+ directives.register("backend.export",startexport) -- maybe .name
+
+ statistics.register("xml exporting time", function()
+ if exporting then
+ return string.format("%s seconds, version %s", statistics.elapsedtime(treehash),exportversion)
+ end
+ end)
+
+end
+
+-- These are called at the tex end:
+
+implement {
+ name = "setupexport",
+ actions = structurestags.setupexport,
+ arguments = {
+ {
+ { "align" },
+ { "bodyfont", "dimen" },
+ { "width", "dimen" },
+ { "properties" },
+ { "hyphen" },
+ { "title" },
+ { "subtitle" },
+ { "author" },
+ { "firstpage" },
+ { "lastpage" },
+ { "svgstyle" },
+ { "cssfile" },
+ }
+ }
+}
+
+implement {
+ name = "finishexport",
+ actions = structurestags.finishexport,
+}
+
+implement {
+ name = "settagitemgroup",
+ actions = structurestags.setitemgroup,
+ arguments = { "boolean", "integer", "string" }
+}
+
+implement {
+ name = "settagitem",
+ actions = structurestags.setitem,
+ arguments = "string"
+}
+
+implement {
+ name = "settagdelimitedsymbol",
+ actions = structurestags.settagdelimitedsymbol,
+ arguments = "string"
+}
+
+implement {
+ name = "settagsubsentencesymbol",
+ actions = structurestags.settagsubsentencesymbol,
+ arguments = "string"
+}
+
+implement {
+ name = "settagsynonym",
+ actions = structurestags.setsynonym,
+ arguments = "string"
+}
+
+implement {
+ name = "settagsorting",
+ actions = structurestags.setsorting,
+ arguments = "string"
+}
+
+implement {
+ name = "settagnotation",
+ actions = structurestags.setnotation,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "settagnotationsymbol",
+ actions = structurestags.setnotationsymbol,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "settaghighlight",
+ actions = structurestags.sethighlight,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "settagfigure",
+ actions = structurestags.setfigure,
+ arguments = { "string", "string", "string", "dimen", "dimen", "string" }
+}
+
+implement {
+ name = "settagcombination",
+ actions = structurestags.setcombination,
+ arguments = { "integer", "integer" }
+}
+
+implement {
+ name = "settagtablecell",
+ actions = structurestags.settablecell,
+ arguments = { "integer", "integer", "integer" }
+}
+
+implement {
+ name = "settagtabulatecell",
+ actions = structurestags.settabulatecell,
+ arguments = "integer"
+}
+
+implement {
+ name = "settagregister",
+ actions = structurestags.setregister,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "settaglist",
+ actions = structurestags.setlist,
+ arguments = "integer"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv
new file mode 100644
index 00000000000..48f4d3c4871
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv
@@ -0,0 +1,292 @@
+%D \module
+%D [ file=back-exp,
+%D version=2010.08.22,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=XML export,
+%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 Backend Macros / XML export}
+
+\registerctxluafile{back-exp.lua}{1.001}
+
+%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 general we assume that when the \XML\ is converted to \HTML\ some stylesheet
+%D is applied anyway.
+
+\unprotect
+
+% we can replace this by a more generic attributeset mechanism where we bind
+% to any element (needed anyway, see userdata thingies)
+
+\definesystemattribute[taggedpar][public]
+
+\unexpanded\def\setelementexporttag
+ {\dotripleargument\back_export_set_element_tag}
+
+\def\back_export_set_element_tag
+ {\ifthirdargument
+ \expandafter \back_export_set_element_tag_a
+ \else\ifsecondargument
+ \doubleexpandafter\back_export_set_element_tag_b
+ \fi\fi}
+
+\def\back_export_set_element_tag_a[#1][#2][#3]{\clf_settagproperty{#1}{#2}{#3}}
+\def\back_export_set_element_tag_b[#1][#2][#3]{\clf_settagproperty{#1}{export}{#2}}
+
+% todo: no need for calls when trialtypesetting
+
+\def\taggedctxcommand
+ {\iftrialtypesetting
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\ctxcommand
+ \fi}
+
+\newcount\tagparcounter
+
+\let\dotagsetparcounter\relax
+\let\doresetparcounter \relax
+
+\appendtoks
+ \doresetparcounter
+\to \everyflushatnextpar
+
+% \appendtoks
+% \dotagsetparcounter
+% \to \everypar
+
+\prependtoks
+ \dotagsetparcounter
+\to \everypar
+
+% \appendtoks
+% \dotagsetparcounter
+% \to \neverypar
+
+\prependtoks
+ \dotagsetparcounter
+\to \neverypar
+
+\appendtoks
+ \dotagsetparcounter
+\to \everytabulatepar % tricky, maybe this should be neverypar
+
+\appendtoks
+ \unexpanded\def\dotagTABLEcell
+ {\iftrialtypesetting\else
+ \clf_settagtablecell
+ \numexpr\tablecellrows\relax
+ \numexpr\tablecellcolumns\relax
+ \numexpr\raggedstatus\relax
+ \fi}%
+ % brrr, we need to tag empty cells (unless we start numbering)
+ \unexpanded\def\dotagTABLEsignal
+ {\signalcharacter}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagtabulatecell
+ {\iftrialtypesetting\else\clf_settagtabulatecell\c_tabl_tabulate_align\fi}%
+ \unexpanded\def\dotagtabulatesignal
+ {\dontleavehmode\signalcharacter\ignorespaces}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsynonym
+ {\iftrialtypesetting\else\clf_settagsynonym{\currentsynonymtag}\fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsorting
+ {\iftrialtypesetting\else\clf_settagsorting{\currentsortingtag}\fi}%
+\to \everyenableelements
+
+\appendtoks % frozen and assumed global per highlight class
+ \unexpanded\def\dotaghighlight
+ {\iftrialtypesetting\else
+ \clf_settaghighlight{\highlightparameter\c!style}\attribute\colorattribute\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks % we can have differently scaled images
+ \unexpanded\def\dotagfigure
+ {\iftrialtypesetting\else
+ \clf_settagfigure
+ {\figurefileoriginal}%
+ {\figurefullname}%
+ {\figurefilepage}%
+ \dimexpr\figurewidth\relax
+ \dimexpr\figureheight\relax
+ {\figurelabel}%
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagcombination
+ {\iftrialtypesetting\else
+ \clf_settagcombination
+ \numexpr\combinationparameter\c!nx\relax
+ \numexpr\combinationparameter\c!ny\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetparcounter
+ {\global\advance\tagparcounter\plusone\attribute\taggedparattribute\tagparcounter}%
+ \unexpanded\def\doresetparcounter
+ {\attribute\taggedparattribute\attributeunsetvalue}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetitemgroup
+ {\iftrialtypesetting\else
+ \clf_settagitemgroup
+ \ifconditional\c_strc_itemgroups_pack true\else false\fi\space
+ \numexpr\currentitemlevel\relax
+ {\currentitemgroupsymbol}%
+ \fi}%
+ \unexpanded\def\dotagsetitem#1%
+ {\iftrialtypesetting\else
+ \clf_settagitem{#1}%
+ \fi}%
+\to \everyenableelements
+
+% \appendtoks
+% \unexpanded\def\dotagsetdescription
+% {\iftrialtypesetting\else
+% \clf_settagdescription{\currentdescription}\currentdescriptionnumberentry\relax
+% \fi}%
+% \to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetnotation
+ {\iftrialtypesetting\else
+ \clf_settagnotation{\currentnote}\currentnotenumber\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetnotesymbol
+ {\iftrialtypesetting\else
+ \clf_settagnotationsymbol{\currentnote}\currentnotenumber\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagregisterlocation
+ {\iftrialtypesetting\else
+ \clf_settagregister{\currentregister}\currentregisternumber\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotaglistlocation
+ {\iftrialtypesetting\else
+ \clf_settaglist\currentlistindex\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetdelimitedsymbol#1%
+ {\iftrialtypesetting\else
+ \clf_settagdelimitedsymbol{#1}\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagsetsubsentencesymbol#1%
+ {\iftrialtypesetting\else
+ \clf_settagsubsentencesymbol{#1}\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \let\specialfixedspace \explicitfixedspace
+ \let\specialobeyedspace \explicitobeyedspace
+ \let\specialstretchedspace\explicitstretchedspace
+ \let\specialcontrolspace \explicitcontrolspace
+\to \everyenableelements
+
+% The action: \setupbackend[export=yes] % or filename
+
+% maybe xhtml css settings will move to setupexport
+
+% maybe some day a definer
+
+\installcorenamespace{export}
+
+\installparameterhandler \??export {export}
+\installsetuphandler \??export {export}
+
+\setupexport
+ [\c!align=\number\raggedstatus,
+ \c!bodyfont=\bodyfontsize,
+ \c!width=\textwidth,
+ \c!title={\directinteractionparameter\c!title},
+ \c!subtitle={\directinteractionparameter\c!subtitle},
+ \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=]
+
+\def\dosynchronizeexport
+ {\let\currentexport\empty
+ \clf_setupexport
+ align {\exportparameter\c!align}%
+ bodyfont \dimexpr\exportparameter\c!bodyfont\relax
+ width \dimexpr\exportparameter\c!width\relax
+ properties {\exportparameter\c!properties}%
+ hyphen {\exportparameter\c!hyphen}%
+ title {\exportparameter\c!title}%
+ subtitle {\exportparameter\c!subtitle}%
+ author {\exportparameter\c!author}%
+ firstpage {\exportparameter\c!firstpage}%
+ lastpage {\exportparameter\c!lastpage}%
+ svgstyle {\exportparameter\c!svgstyle}%
+ cssfile {\exportparameter\c!cssfile}%
+ \relax}
+
+\appendtoks
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport
+\to \everystarttext
+
+% better (before pdf gets closed, so we can embed), but it needs testing:
+
+\appendtoks
+ \clf_finishexport
+\to \everystoptext
+
+\appendtoks
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport % in case it is done inside \starttext
+\to \everysetupdocument
+
+% \appendtoks
+% \doifsomething{\backendparameter\c!xhtml}
+% {\enabledirectives[backend.export.xhtml=\backendparameter\c!xhtml]}%
+% \doifsomething{\backendparameter\c!css}
+% {\enabledirectives[backend.export.css={\backendparameter\c!css}]}%
+% \doifsomething{\backendparameter\c!alternative}
+% {\enabledirectives[backend.export.alternative={\backendparameter\c!alternative}]}%
+% \to \everysetupbackend
+
+\appendtoks
+ \doifelsenothing{\backendparameter\c!export}
+ {\resetsystemmode\v!export}
+ {\setuptagging[\c!state=\v!start]%
+ \enabledirectives[backend.export=\backendparameter\c!export]%
+ \setsystemmode\v!export}%
+\to \everysetupbackend
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua
new file mode 100644
index 00000000000..e8af4d9d9c2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua
@@ -0,0 +1,122 @@
+if not modules then modules = { } end modules ['back-ini'] = {
+ version = 1.001,
+ comment = "companion to back-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ 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
+
+backends = backends or { }
+local backends = backends
+
+local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end)
+
+local report_backend = logs.reporter("backend","initializing")
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local function nothing() return nil end
+
+backends.nothing = nothing
+
+local nodeinjections = { }
+local codeinjections = { }
+local registrations = { }
+local tables = allocate()
+
+local function donothing(t,k)
+ t[k] = nothing
+ return nothing
+end
+
+setmetatableindex(nodeinjections, donothing)
+setmetatableindex(codeinjections, donothing)
+setmetatableindex(registrations, donothing)
+
+local defaults = {
+ nodeinjections = nodeinjections,
+ codeinjections = codeinjections,
+ registrations = registrations,
+ tables = tables,
+}
+
+backends.defaults = defaults
+
+backends.nodeinjections = { } setmetatableindex(backends.nodeinjections, nodeinjections)
+backends.codeinjections = { } setmetatableindex(backends.codeinjections, codeinjections)
+backends.registrations = { } setmetatableindex(backends.registrations, registrations)
+backends.tables = { } setmetatableindex(backends.tables, tables)
+
+backends.current = "unknown"
+
+function backends.install(what)
+ if type(what) == "string" then
+ local backend = backends[what]
+ if backend then
+ if trace_backend then
+ if backend.comment then
+ report_backend("initializing backend %a, %a",what,backend.comment)
+ else
+ report_backend("initializing backend %a",what)
+ end
+ end
+ backends.current = what
+ for category, default in next, defaults do
+ local target, plugin = backends[category], backend[category]
+ setmetatableindex(plugin, default)
+ setmetatableindex(target, plugin)
+ end
+ elseif trace_backend then
+ report_backend("no backend named %a",what)
+ end
+ end
+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")
+ else
+ return nil
+ end
+end)
+
+local comment = { "comment", "" }
+
+tables.vfspecials = allocate {
+ red = comment,
+ green = comment,
+ blue = comment,
+ black = comment,
+ startslant = comment,
+ 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 {
+ name = "setrealspaces",
+ arguments = "string",
+ actions = function(v)
+ nodes.tasks.setaction("shipouts","nodes.handlers.accessibility",v == interfaces.variables.yes)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv
new file mode 100644
index 00000000000..9859f026a1f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv
@@ -0,0 +1,120 @@
+%D \module
+%D [ file=back-ini,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Most will go away here as it is replaced by \LUA\ calls to
+%D backend functions.
+
+\writestatus{loading}{ConTeXt Backend Macros / Initialization}
+
+\registerctxluafile{back-ini}{1.001}
+
+%D We currently have a curious mix between tex and lua backend
+%D handling but eventually most will move to lua.
+
+\unprotect
+
+\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi
+\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
+%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
+%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
+%D Not everything here makes sense and the content of this file will
+%D definitely change (or even go away).
+
+\let \dostartrotation \gobbleoneargument
+\let \dostoprotation \donothing
+\let \dostartscaling \gobbletwoarguments
+\let \dostopscaling \donothing
+\let \dostartmirroring \donothing
+\let \dostopmirroring \donothing
+\let \dotransformnextbox\gobblesixarguments % and pass last box
+
+%D \macros
+%D {back_ovalbox}
+%D
+%D When we look at the implementation, this is a complicated
+%D one. There are seven 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).
+
+\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
+%D \starttyping
+%D \dostartclipping {pathname} {width} {height}
+%D \dostopclipping
+%D \stoptyping
+
+\let \dostartclipping \gobblethreearguments
+\let \dostopclipping \donothing
+
+%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 modules we wil set \type {\jobsuffix} to \type {pdf}.
+
+%D Backend configuration:
+
+\installcorenamespace{backend}
+
+\installsetuponlycommandhandler \??backend {backend}
+
+\let\jobsuffix\empty
+
+\unexpanded\def\back_job_set_suffix#1% % checking could happen in mode
+ {\ifx\jobsuffix\empty\else\resetsystemmode\jobsuffix\fi
+ \edef\jobsuffix{#1}%
+ \ifx\jobsuffix\empty\else\setsystemmode \jobsuffix\fi}
+
+\back_job_set_suffix{pdf} % default
+
+% \setupbackend[space=yes] % replace spacing in (pdf) file
+
+\appendtoks
+ \clf_setrealspaces{\backendparameter\c!space}%
+\to \everysetupbackend
+
+%D For older styles:
+
+\let\setupoutput\gobbleoneoptional
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua
new file mode 100644
index 00000000000..0821abb2895
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua
@@ -0,0 +1,171 @@
+if not modules then modules = { } end modules ['back-pdf'] = {
+ version = 1.001,
+ comment = "companion to back-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we could do \pdfmatrix sx <> sy <> etc
+
+local tonumber = tonumber
+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 scanstring = scanners.string
+local scannumber = scanners.number
+local scaninteger = scanners.integer
+local scankeyword = scanners.keyword
+
+local scanners = interfaces.scanners
+local implement = interfaces.implement
+
+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
+
+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 {
+ name = "setpdfcompression",
+ arguments = { "integer", "integer" },
+ actions = function(c,o)
+ pdf.setcompresslevel(c)
+ pdf.setobjcompresslevel(o)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv
new file mode 100644
index 00000000000..ab9e4160cb9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv
@@ -0,0 +1,589 @@
+%D \module
+%D [ file=back-pdf,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=\PDF,
+%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 Backend Macros / PDF}
+
+%registerctxluafile{lpdf-aux}{1.001} % common helpers
+\registerctxluafile{lpdf-ini}{1.001}
+\registerctxluafile{lpdf-nod}{1.001}
+\registerctxluafile{lpdf-col}{1.000}
+\registerctxluafile{lpdf-xmp}{1.001}
+\registerctxluafile{lpdf-ano}{1.001}
+\registerctxluafile{lpdf-res}{1.001}
+\registerctxluafile{lpdf-mis}{1.001}
+\registerctxluafile{lpdf-ren}{1.001}
+\registerctxluafile{lpdf-grp}{1.001}
+\registerctxluafile{lpdf-wid}{1.001}
+\registerctxluafile{lpdf-fld}{1.001}
+\registerctxluafile{lpdf-mov}{1.001}
+\registerctxluafile{lpdf-u3d}{1.001}
+\registerctxluafile{lpdf-swf}{1.001}
+\registerctxluafile{lpdf-tag}{1.001}
+\registerctxluafile{lpdf-fmt}{1.001}
+\registerctxluafile{lpdf-epd}{1.001}
+\registerctxluafile{lpdf-epa}{1.001}
+
+\registerctxluafile{back-pdf}{1.001} % some code will move to lpdf-*
+
+\unprotect
+
+%D We will minimize the number of calls to \PDF\ specific primitives
+%D and delegate all management and injection of code to the backend.
+%D
+%D Here we initialize some internal quantities. We also protect them.
+
+\outputmode \plusone \let\modeoutput \undefined \newcount\outputmode \outputmode \plusone
+
+%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 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.
+
+\let\pdfcolorstack \relax
+\let\pdfcolorstackinit \relax
+\let\pdfannot \relax
+\let\pdfstartlink \relax
+\let\pdfendlink \relax
+\let\pdfoutline \relax
+\let\pdfdest \relax
+\let\pdfthread \relax
+\let\pdfstartthread \relax
+\let\pdfendthread \relax
+\let\pdffontattr \relax
+\let\pdfglyphtounicode \relax
+
+%D Here we do intercept (silently) what gets passed. One should use the
+%D \CONTEXT\ interfaces instead.
+
+\let\pdfcatalog \relax \newtoks \pdfcatalog
+\let\pdfinfo \relax \newtoks \pdfinfo
+\let\pdfnames \relax \newtoks \pdfnames
+\let\pdftrailer \relax \newtoks \pdftrailer
+\let\pdfpageresources \relax \newtoks \pdfpageresources
+\let\pdfpageattr \relax \newtoks \pdfpageattr
+\let\pdfpagesattr \relax \newtoks \pdfpagesattr
+\let\pdfxformattr \relax \newtoks \pdfxformattr
+\let\pdfxformresources \relax \newtoks \pdfxformresources
+
+%D We use the \LUA\ interface (which then permits more control over
+%D possible pdf/x extensions).
+
+\let\pdfcompresslevel \relax \newcount\pdfcompresslevel
+\let\pdfobjcompresslevel\relax \newcount\pdfobjcompresslevel
+
+%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}
+
+%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}}
+
+%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.
+
+\let\pdfcreationdate \relax \newtoks \pdfcreationdate
+\let\pdfdecimaldigits \relax \newcount\pdfdecimaldigits
+\let\pdfdestmargin \relax \newcount\pdfdestmargin
+\let\pdffontname \relax \newcount\pdffontname
+\let\pdffontobjnum \relax \newcount\pdffontobjnum
+\let\pdffontsize \relax \newcount\pdffontsize
+\let\pdfgamma \relax \newcount\pdfgamma
+\let\pdfgentounicode \relax \newcount\pdfgentounicode
+\let\pdfhorigin \relax \newcount\pdfhorigin
+\let\pdfignoreunknownimages \relax \newcount\pdfignoreunknownimages
+\let\pdfimageaddfilename \relax \newcount\pdfimageaddfilename
+\let\pdfimageapplygamma \relax \newcount\pdfimageapplygamma
+\let\pdfimagegamma \relax \newcount\pdfimagegamma
+\let\pdfimagehicolor \relax \newcount\pdfimagehicolor
+\let\pdfimageresolution \relax \newcount\pdfimageresolution
+\let\pdfincludechars \relax \newtoks \pdffontsize
+\let\pdfinclusioncopyfonts \relax \newcount\pdfinclusioncopyfonts
+\let\pdfinclusionerrorlevel \relax \newcount\pdfinclusionerrorlevel
+\let\pdfinfoomitdate \relax \newcount\pdfinfoomitdate
+\let\pdflastannot \relax \newcount\pdflastannot
+\let\pdflastlink \relax \newcount\pdflastlink
+\let\pdflinkmargin \relax \newcount\pdflinkmargin
+\let\pdfminorversion \relax \newcount\pdfminorversion
+\let\pdfpagebox \relax \newcount\pdfpagebox
+\let\pdfpageref \relax \newcount\pdfpageref
+\let\pdfpkfixeddpi \relax \newcount\pdfpkfixeddpi
+\let\pdfpkmode \relax \newtoks \pdfpkmode
+\let\pdfpkresolution \relax \newcount\pdfpkresolution
+\let\pdfretval \relax \newcount\pdfretval
+\let\pdfsuppressoptionalinfo \relax \newcount\pdfsuppressoptionalinfo
+\let\pdfsuppressptexinfo \relax \newcount\pdfsuppressptexinfo
+\let\pdftexrevision \relax \newcount\pdftexrevision
+\let\pdftexversion \relax \newcount\pdftexversion
+\let\pdfthreadmargin \relax \newcount\pdfthreadmargin
+\let\pdftrailerid \relax \newtoks \pdftrailerid
+\let\pdfuniqueresname \relax \newcount\pdfuniqueresname
+\let\pdfvorigin \relax \newcount\pdfvorigin
+\let\pdfxformmargin \relax \newcount\pdfxformmargin
+\let\pdfxformname \relax \newcount\pdfxformname
+
+%D These are still accepted but are normally not needed.
+
+\let\pdflastxform \lastsavedboxresourceindex
+\let\pdflastximage \lastsavedimageresourceindex
+\let\pdflastximagepages \lastsavedimageresourcepages
+\let\pdflastxpos \lastxpos
+\let\pdflastypos \lastypos
+\let\pdfrefxform \useboxresource
+\let\pdfrefximage \useimageresource
+\let\pdfsavepos \savepos
+\let\pdfxform \saveboxresource
+\let\pdfximage \saveimageresource
+
+%D For the moment we keep these as they are but they will become \LUA\
+%D calls eventually, after which we will nil the three \type {\pdf}
+%D interface primitives.
+
+\normalprotected\def\pdfliteral {\pdfextension literal }
+\normalprotected\def\pdfobj {\pdfextension obj }
+ \def\pdflastobj {\numexpr\pdffeedback lastobj\relax}
+\normalprotected\def\pdfrefobj {\pdfextension refobj }
+\normalprotected\def\pdfrestore {\pdfextension restore\relax}
+\normalprotected\def\pdfsave {\pdfextension save\relax}
+\normalprotected\def\pdfsetmatrix{\pdfextension setmatrix }
+
+%D This one can be consulted by users although the suffix is also
+%D a system mode.
+
+\back_job_set_suffix{pdf}
+
+%D PDF/X (maybe combine the two lua calls)
+
+\setupbackend
+ [xmpfile=]
+
+\appendtoks
+ \doifsomething{\backendparameter{xmpfile}}
+ {\clf_setxmpfile{\backendparameter{xmpfile}}}%
+\to \everysetupbackend
+
+% \doifsomething{\backendparameter\c!format} .. at the lua end
+
+\appendtoks
+ \clf_setformat
+ format {\backendparameter\c!format}%
+ level {\backendparameter\c!level}%
+ option {\backendparameter\c!option}%
+ profile {\backendparameter\c!profile}%
+ intent {\backendparameter\c!intent}%
+ file {\backendparameter\c!file}%
+ \relax
+\to \everysetupbackend
+
+%D For the moment we keep these.
+
+%newtoks \pdfbackendeveryximage
+\newtoks \pdfbackendeveryxform
+
+%D These are the only official methods to add stuff to the resources.
+
+\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog {#1}{#2}}
+\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo {#1}{#2}}
+\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames {#1}{#2}}
+
+\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes {#1}{#2}}
+\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes {#1}{#2}}
+\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources {#1}{#2}}
+
+\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate {#1}{#2}}
+\unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}}
+\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern {#1}{#2}}
+\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade {#1}{#2}}
+
+ \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources}
+ \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
+ {\PointsToBigPoints{#2}\width
+ \PointsToBigPoints{#3}\height
+ \meta_grab_clip_path{#1}\width\height{%
+ 0 0 m %
+ \width\space 0 l %
+ \width\space \height\space l %
+ 0 \height\space l%
+ }%
+ \pdfliteral{q 0 w \MPclippath\space W n}}
+
+\unexpanded\def\dostopclipping
+ {\pdfliteral{Q}}
+
+%D Temporary hack, will be removed or improved or default.
+
+% attr {/Group << /S /Transparency /I false /K true >>}
+
+%def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}}
+\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
+
+% \let\lastpredefinedsymbol\empty % some day we can do more at the lua end
+%
+% \unexpanded\def\predefinesymbol[#1]%
+% {\begingroup
+% \xdef\lastpredefinedsymbol{#1}%
+% \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting
+% \dogetobjectreference{SYM}{#1}\m_back_object_reference
+% \clf_registerbackendsymbol{#1}\m_back_object_reference\relax
+% \endgroup}
+
+% Still here:
+
+%D \macros
+%D {back_ovalbox}
+%D
+%D Drawing frames with round corners is inherited from the
+%D main module.
+%D
+%D For drawing ovals we use quite raw \PDF\ code. The next
+%D implementation does not differ that much from the one
+%D implemented in the \POSTSCRIPT\ driver. This code is
+%D somewhat obsolete as we now have metapost embedded.
+
+% \def\back_oval_calculate#1#2#3%
+% {\PointsToBigPoints{\dimexpr#2+#3\relax}#1}
+
+\unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8%
+ {\forcecolorhack
+ \bgroup
+% \scratchdimen#4%
+% \divide\scratchdimen\plustwo
+% \back_oval_calculate\xmin \zeropoint\scratchdimen
+% \back_oval_calculate\xmax {#1}{-\scratchdimen}%
+% \back_oval_calculate\ymax {#2}{-\scratchdimen}%
+% \back_oval_calculate\ymin {-#3}\scratchdimen
+% \advance\scratchdimen by #5%
+% \back_oval_calculate\xxmin \zeropoint\scratchdimen
+% \back_oval_calculate\xxmax {#1}{-\scratchdimen}%
+% \back_oval_calculate\yymax {#2}{-\scratchdimen}%
+% \back_oval_calculate\yymin {-#3}\scratchdimen
+% \back_oval_calculate\stroke{#4}\zeropoint
+% \back_oval_calculate\radius{#5}\zeropoint
+ %
+ \PointsToBigPoints{#4} \stroke
+ \PointsToBigPoints{#5} \radius
+ \scratchdimen\dimexpr#4/\plustwo\relax
+ \PointsToBigPoints \scratchdimen \xmin
+ \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xmax
+ \PointsToBigPoints{\dimexpr #2-\scratchdimen}\ymax
+ \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\ymin
+ \advance\scratchdimen by #5\relax
+ \PointsToBigPoints \scratchdimen \xxmin
+ \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xxmax
+ \PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax
+ \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin
+ %
+ \edef\dostroke{\number#6}%
+ \edef\dofill{\number#7}%
+ \edef\mode{\number#8}%
+ % no \ifcase, else \relax in pdfcode
+ \setbox\scratchbox\naturalhpack
+ {\ifnum\dostroke\dofill>\zerocount
+ \pdfliteral
+ {q
+ \stroke\space w
+ \ifcase\mode\space
+ \xxmin\space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 1
+ \xxmin\space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 2
+ \xxmin\space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 3
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ h
+ \or % 4
+ \xmin \space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xmin \space \ymax \space l
+ \xmin \space \ymin\space l
+ h
+ \or % 5
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xmin \space \ymax \space l
+ \xmin \space \ymin \space l
+ h
+ \or % 6
+ \xmin \space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \ymin \space l
+ h
+ \or
+ \xxmin\space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ h
+ \or % 9 top open
+ \xmin \space \ymax \space m
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \or % 10 right open
+ \xmax \space \ymax \space m
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ \xmax\space \ymin \space l
+ \or % 11 bottom open
+ \xmax \space \ymin \space m
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax \space \ymax\space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ \or % 12 left open
+ \xmin \space \ymax \space m
+ \xxmax\space \ymax \space l
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space l
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \ymin \space l
+ \or % 13
+ \xmin \space \ymax \space m
+ \xxmax\space \ymax \space l
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax\space \ymin \space l
+ \or % 14
+ \xmax \space \ymax \space m
+ \xmax \space \yymin\space l
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \ymin \space l
+ \or % 15
+ \xmax \space \ymin \space m
+ \xxmin\space \ymin \space l
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \ymax \space l
+ \or % 16
+ \xmin \space \ymin \space m
+ \xmin \space \yymax\space l
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \xmax \space \ymax \space l
+ \or % 17
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \or % 18
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \or % 19
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 20
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 21
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 22
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \or % 23
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 24
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 25
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 26
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 27
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 28
+ \fi
+ \ifnum\mode>\pluseight\space
+ S
+ \else
+ \ifnum\dostroke=\plusone S \fi
+ \ifnum\dofill =\plusone f \fi
+ \fi
+ Q}%
+ \fi}%
+ \wd\scratchbox#1%
+ \ht\scratchbox#2%
+ \dp\scratchbox#3%
+ \box\scratchbox
+ \egroup}
+
+\unexpanded\def\pdfbackendactualtext#1#2% not interfaced
+ {\clf_startactualtext{#2}%
+ #1%
+ \clf_stopactualtext}
+
+\let\pdfactualtext\pdfbackendactualtext
+
+% \starttext
+% text \pdfbackendactualtext{Meier}{Müller} text
+% \stoptext
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv
new file mode 100644
index 00000000000..09745e0f93f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv
@@ -0,0 +1,86 @@
+%D \module
+%D [ file=back-swf,
+%D version=2009.12.31,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=Shockwave Experiment,
+%D author=Hans Hagen \& Luigi Scarso,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is only a placeholder that demonstrates the usage of swf resources.
+%D There is no need to include this file into the format. The module was
+%D tested by Luigi and Willi and based on their suggestions the functionality
+%D was improved.
+%D
+%D \starttyping
+%D \enabletrackers[graphics.locating]
+%D \enabletrackers[backend.swf]
+%D
+%D \startluaparameterset [swf:relative:resources]
+%D relativepaths = {
+%D "assets"
+%D }
+%D \stopluaparameterset
+%D
+%D \startluaparameterset[swf:relative:display]
+%D toolbar = true,
+%D preview = "images/posterframes/*.jpg", -- relative to assets
+%D open = "click",
+%D close = "focus",
+%D \stopluaparameterset
+%D
+%D \startTEXpage
+%D \externalfigure
+%D [whatever.swf]
+%D [resources=swf:relative:resources,
+%D display=swf:relative:display]
+%D \stopTEXpage
+%D \stoptyping
+
+\endinput
+
+\starttext
+
+\startluaparameterset [swf:myset:display:1]
+ toolbar = true,
+ preview = "assets/images/posterframes/SPT_14-16_Ra_01_PN_LE01_02_DoLikeMeLater_posterframe.jpg",
+ -- preview = "t:/sources/cow.pdf",
+ -- preview = "t:/sources/hacker.jpg",
+ open = "click", -- click page focus
+ close = "focus", -- click page focus
+\stopluaparameterset
+
+\startluaparameterset [swf:myset:resources:1]
+ paths = {
+ "assets"
+ },
+ files = {
+ -- "somename_1"
+ -- "somename_1"
+ }
+\stopluaparameterset
+
+\startluaparameterset [swf:dolikemelater:resources]
+ paths = {
+ "assets"
+ },
+\stopluaparameterset
+
+% preview=swf:myset:display:1
+% controls=swf:myset:controls:1
+% resources=swf:myset:resources:1
+
+\placefigure
+ {flash demo}
+ {\startcombination[2*2]
+ {\externalfigure[trasf1.swf][width=0.45\textwidth,height=0.25\textheight]} {one}
+ {\externalfigure[trasf2.swf][width=0.45\textwidth,height=0.25\textheight]} {two}
+ {\externalfigure[trasf3.swf][width=0.45\textwidth,height=0.25\textheight]} {three}
+ {\externalfigure[trasf4.swf][width=0.45\textwidth,height=0.25\textheight]} {four}
+ \stopcombination}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-u3d.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-u3d.mkiv
new file mode 100644
index 00000000000..297dd554579
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/back-u3d.mkiv
@@ -0,0 +1,158 @@
+%D \module
+%D [ file=back-u3d,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=U3D Experiment,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is only a placeholder that demonstrates the usage of u3d resources. The
+%D user interface is rather messy an might be improved. The files and setup is
+%D derived from an example by Michael Vidiassov.
+
+\endinput
+
+\starttext
+
+\startluaparameterset [u3d:myset:controls:1]
+ view = {
+ name = 'default',
+ bg = {1,1,1},
+ mag = 100,
+ coo = {0,0,0},
+ c2c = {0,0,1},
+ rot = {40,0,60},
+ roo = 6,
+ lights = 'CAD'
+ },
+ js = 'cloudq.js'
+\stopluaparameterset
+
+\startluaparameterset [u3d:myset:controls:2]
+ views = {
+ {
+ name = 'AnglePositioning',
+ bg = {1,1,1},
+ azimuth = 45,
+ altitude = 45,
+ roo = 50,
+ aac = 2.5,
+ lights = 'Artwork'
+ },
+ {
+ name = 'RotationPositioning',
+ bg = {1,1,1},
+ rot = {0,45,45},
+ roo = 50,
+ aac = 2.5,
+ lights = 'Artwork'
+ },
+ {
+ name = 'VectorPositioning',
+ bg = {1,0,0},
+ c2c = {1,1,math.sqrt(2)},
+ roo = 50,
+ aac = 2.5,
+ lights = 'CAD'
+ },
+ {
+ name = 'PositionPositioning',
+ bg = {1,0,0},
+ pos = {1+25,1+25,1+50/math.sqrt(2)},
+ aac = 2.5,
+ lights = 'CAD'
+ },
+ {
+ name = 'ortho',
+ bg = {1,1,1},
+ mag = 300,
+ lights = 'CAD',
+ crossection = {}
+ }
+ },
+ view = {
+ name = 'default',
+ bg = {1,1,1},
+ c2c = {-1,-1,0},
+ roo = 50,
+ aac = 2.5,
+ roll = 45,
+ lights = 'CAD',
+ crossection = {
+ normal = {-1,-1,-1},
+ transparent = true
+ },
+ nodes = {
+ {
+ name = 'xlabel',
+ visible = false
+ },
+ {
+ name = 'ylabel',
+ opacity = 0.5
+ },
+ {
+ name = 'zlabel',
+ rendermode = 'Wireframe'
+ }
+ }
+ }
+\stopluaparameterset
+
+\useexternalfigure
+ [cloudq]
+ [cloudq.u3d]
+ [width=0.7\textwidth,
+ height=.7\textwidth,
+ display=u3d:myset:display:1,
+ controls=u3d:myset:controls:1]
+
+\useexternalfigure
+ [axes]
+ [axes.u3d]
+ [width=0.7\textwidth,
+ height=.7\textwidth,
+ controls=u3d:myset:controls:1]
+
+\startluaparameterset[u3d:myset:display:2]
+ toolbar = true,
+ preview = 'cloudq.png'
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:3]
+ toolbar = true,
+ tree = false,
+ preview = 'axes.png'
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:4]
+ toolbar = true,
+ tree = false,
+ view = {
+ name = 'view',
+ bg = {0.1,0.1,0.1},
+ c2c = {-1,-1,0},
+ roo = 50,
+ aac = 2.5,
+ roll = 45,
+ lights = 'Red'
+ }
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:5]
+ toolbar = true,
+ tree = false,
+ view = 'ortho'
+\stopluaparameterset
+
+\placefigure[here]{none}{\externalfigure[cloudq][display=u3d:myset:display:2]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:3]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:4]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.lua b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.lua
new file mode 100644
index 00000000000..baeb3d2f9af
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.lua
@@ -0,0 +1,768 @@
+if not modules then modules = { } end modules ['bibl-bib'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>This is a prelude to integrated bibliography support. This file just loads
+bibtex files and converts them to xml so that the we access the content
+in a convenient way. Actually handling the data takes place elsewhere.</p>
+--ldx]]--
+
+local lower, format, gsub, concat = string.lower, string.format, string.gsub, table.concat
+local next = next
+local utfchar = utf.char
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local textoutf = characters and characters.tex.toutf
+local variables = interfaces and interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+local finalizers = xml.finalizers.tex
+local xmlfilter, xmltext, getid = xml.filter, xml.text, lxml.getid
+local formatters = string.formatters
+
+local P, R, S, C, Cc, Cs, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct
+
+local trace_bibxml = false trackers.register("publications.bibxml", function(v) trace_bibtex = v end)
+
+local report_xml = logs.reporter("publications","xml")
+
+bibtex = bibtex or { }
+local bibtex = bibtex
+
+bibtex.statistics = bibtex.statistics or { }
+local bibtexstats = bibtex.statistics
+
+bibtexstats.nofbytes = 0
+bibtexstats.nofdefinitions = 0
+bibtexstats.nofshortcuts = 0
+
+local defaultshortcuts = {
+ jan = "1",
+ feb = "2",
+ mar = "3",
+ apr = "4",
+ may = "5",
+ jun = "6",
+ jul = "7",
+ aug = "8",
+ sep = "9",
+ oct = "10",
+ nov = "11",
+ dec = "12",
+}
+
+local shortcuts = { }
+local data = { }
+local entries
+
+-- Currently we expand shortcuts and for large ones (like the acknowledgements
+-- in tugboat.bib this is not that efficient. However, eventually strings get
+-- hashed again.
+
+local function do_shortcut(tag,key,value)
+ bibtexstats.nofshortcuts = bibtexstats.nofshortcuts + 1
+ if lower(tag) == "@string" then
+ shortcuts[key] = value
+ end
+end
+
+local function do_definition(tag,key,tab) -- maybe check entries here (saves memory)
+ if not entries or entries[key] then
+ bibtexstats.nofdefinitions = bibtexstats.nofdefinitions + 1
+ local t = { }
+ for i=1,#tab,2 do
+ t[tab[i]] = tab[i+1]
+ end
+ local p = data[tag]
+ if not p then
+ data[tag] = { [key] = t }
+ else
+ p[key] = t
+ end
+ end
+end
+
+local function resolve(s)
+ return shortcuts[s] or defaultshortcuts[s] or s -- can be number
+end
+
+local percent = P("%")
+local start = P("@")
+local comma = P(",")
+local hash = P("#")
+local escape = P("\\")
+local single = P("'")
+local double = P('"')
+local left = P('{')
+local right = P('}')
+local both = left + right
+local lineending = S("\n\r")
+local space = S(" \t\n\r\f")
+local spacing = space^0
+local equal = P("=")
+local collapsed = (space^1)/ " "
+
+----- function add(a,b) if b then return a..b else return a end end
+
+local keyword = C((R("az","AZ","09") + S("@_:-"))^1) -- C((1-space)^1)
+local s_quoted = ((escape*single) + collapsed + (1-single))^0
+local d_quoted = ((escape*double) + collapsed + (1-double))^0
+local balanced = lpegpatterns.balanced
+
+local s_value = (single/"") * s_quoted * (single/"")
+local d_value = (double/"") * d_quoted * (double/"")
+local b_value = (left /"") * balanced * (right /"")
+local r_value = keyword/resolve
+
+local somevalue = s_value + d_value + b_value + r_value
+local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0))
+
+local assignment = spacing * keyword * spacing * equal * spacing * value * spacing
+local shortcut = keyword * spacing * left * spacing * (assignment * comma^0)^0 * spacing * right
+local definition = keyword * spacing * left * spacing * keyword * comma * Ct((assignment * comma^0)^0) * spacing * right
+local comment = keyword * spacing * left * (1-right)^0 * spacing * right
+local forget = percent^1 * (1-lineending)^0
+
+-- todo \%
+
+local grammar = (space + forget + shortcut/do_shortcut + definition/do_definition + comment + 1)^0
+
+function bibtex.convert(session,content)
+ statistics.starttiming(bibtex)
+ data, shortcuts, entries = session.data, session.shortcuts, session.entries
+ bibtexstats.nofbytes = bibtexstats.nofbytes + #content
+ session.nofbytes = session.nofbytes + #content
+ lpegmatch(grammar,content or "")
+ statistics.stoptiming(bibtex)
+end
+
+function bibtex.load(session,filename)
+ statistics.starttiming(bibtex)
+ local filename = resolvers.findfile(filename,"bib")
+ if filename ~= "" then
+ local data = io.loaddata(filename) or ""
+ if data == "" then
+ report_xml("empty file %a, no conversion to xml",filename)
+ elseif trace_bibxml then
+ report_xml("converting file %a to xml",filename)
+ end
+ bibtex.convert(session,data)
+ end
+ statistics.stoptiming(bibtex)
+end
+
+function bibtex.new()
+ return {
+ data = { },
+ shortcuts = { },
+ xml = xml.convert("<?xml version='1.0' standalone='yes'?>\n<bibtex></bibtex>"),
+ nofbytes = 0,
+ entries = nil,
+ loaded = false,
+ }
+end
+
+local p_escaped = lpegpatterns.xml.escaped
+
+local ihatethis = {
+ f = "\\f",
+ n = "\\n",
+ r = "\\r",
+ s = "\\s",
+ t = "\\t",
+ v = "\\v",
+ z = "\\z",
+}
+
+local command = P("\\")/"" * Cc("\\bibtexcommand{") * (R("az","AZ")^1) * Cc("}")
+local any = P(1)
+local done = P(-1)
+local one_l = P("{") / ""
+local one_r = P("}") / ""
+local two_l = P("{{") / ""
+local two_r = P("}}") / ""
+
+local filter = Cs(
+ two_l * (command + any - two_r - done)^0 * two_r * done +
+ one_l * (command + any - one_r - done)^0 * one_r * done +
+ (command + any )^0
+)
+
+function bibtex.toxml(session,options)
+ if session.loaded then
+ return
+ else
+ session.loaded = true
+ end
+ -- we can always speed this up if needed
+ -- format slows down things a bit but who cares
+ statistics.starttiming(bibtex)
+ local result, r = { }, 0
+ local options = settings_to_hash(options)
+ local convert = options.convert -- todo: interface
+ local strip = options.strip -- todo: interface
+ local entries = session.entries
+ r = r + 1 ; result[r] = "<?xml version='1.0' standalone='yes'?>"
+ r = r + 1 ; result[r] = "<bibtex>"
+ for id, categories in next, session.data do
+ id = lower(gsub(id,"^@",""))
+ for name, entry in next, categories do
+ if not entries or entries[name] then
+ r = r + 1 ; result[r] = formatters["<entry tag='%s' category='%s'>"](lower(name),id)
+ for key, value in next, entry do
+ value = gsub(value,"\\(.)",ihatethis) -- this really needs checking
+ value = lpegmatch(p_escaped,value)
+ if value ~= "" then
+ if convert then
+ value = textoutf(value,true)
+ end
+ if strip then
+ -- as there is no proper namespace in bibtex we need this
+ -- kind of hackery ... bibtex databases are quite unportable
+ value = lpegmatch(filter,value) or value
+ end
+ r = r + 1 ; result[r] = formatters[" <field name='%s'>%s</field>"](key,value)
+ end
+ end
+ r = r + 1 ; result[r] = "</entry>"
+ end
+ end
+ end
+ r = r + 1 ; result[r] = "</bibtex>"
+ result = concat(result,"\n")
+ -- alternatively we could use lxml.convert
+ session.xml = xml.convert(result, {
+ resolve_entities = true,
+ resolve_predefined_entities = true, -- in case we have escaped entities
+ -- unify_predefined_entities = true, -- &#038; -> &amp;
+ utfize_entities = true,
+ } )
+ session.data = nil
+ session.shortcuts = nil
+ statistics.stoptiming(bibtex)
+end
+
+statistics.register("bibtex load time", function()
+ local nofbytes = bibtexstats.nofbytes
+ if nofbytes > 0 then
+ return format("%s seconds, %s bytes, %s definitions, %s shortcuts",
+ statistics.elapsedtime(bibtex),nofbytes,bibtexstats.nofdefinitions,bibtexstats.nofshortcuts)
+ else
+ return nil
+ end
+end)
+
+--~ str = [[
+--~ @COMMENT { CRAP }
+--~ @STRING{ hans = "h a n s" }
+--~ @STRING{ taco = "t a c o" }
+--~ @SOMETHING{ key1, abc = "t a c o" , def = "h a n s" }
+--~ @SOMETHING{ key2, abc = hans # taco }
+--~ @SOMETHING{ key3, abc = "hans" # taco }
+--~ @SOMETHING{ key4, abc = hans # "taco" }
+--~ @SOMETHING{ key5, abc = hans # taco # "hans" # "taco"}
+--~ @SOMETHING{ key6, abc = {oeps {oeps} oeps} }
+--~ ]]
+
+--~ local session = bibtex.new()
+--~ bibtex.convert(session,str)
+--~ bibtex.toxml(session)
+--~ print(session.nofbytes,statistics.elapsedtime(bibtex))
+
+--~ local session = bibtex.new()
+--~ bibtex.load(session,"IEEEabrv.bib")
+--~ bibtex.load(session,"IEEEfull.bib")
+--~ bibtex.load(session,"IEEEexample.bib")
+--~ bibtex.toxml(session)
+--~ print(session.nofbytes,statistics.elapsedtime(bibtex))
+
+--~ local session = bibtex.new()
+--~ bibtex.load(session,"gut.bib")
+--~ bibtex.load(session,"komoedie.bib")
+--~ bibtex.load(session,"texbook1.bib")
+--~ bibtex.load(session,"texbook2.bib")
+--~ bibtex.load(session,"texbook3.bib")
+--~ bibtex.load(session,"texgraph.bib")
+--~ bibtex.load(session,"texjourn.bib")
+--~ bibtex.load(session,"texnique.bib")
+--~ bibtex.load(session,"tugboat.bib")
+--~ bibtex.toxml(session)
+--~ print(session.nofbytes,statistics.elapsedtime(bibtex))
+
+--~ print(table.serialize(session.data))
+--~ print(table.serialize(session.shortcuts))
+--~ print(xml.serialize(session.xml))
+
+if not characters then dofile(resolvers.findfile("char-def.lua")) end
+
+local chardata = characters.data
+local concat = table.concat
+
+local lpeg = lpeg
+
+local P, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.Ct, lpeg.match, lpeg.patterns
+
+local space, comma = P(" "), P(",")
+
+local andsplitter = lpeg.tsplitat(space^1 * "and" * space^1)
+local commasplitter = lpeg.tsplitat(space^0 * comma * space^0)
+local spacesplitter = lpeg.tsplitat(space^1)
+local firstcharacter = lpegpatterns.utf8byte
+
+local function is_upper(str)
+ local first = lpegmatch(firstcharacter,str)
+ local okay = chardata[first]
+ return okay and okay.category == "lu"
+end
+
+local function splitauthors(str)
+ local authors = lpegmatch(andsplitter,str)
+ for i=1,#authors do
+ local firstnames, vons, surnames, initials, juniors, words
+ local author = authors[i]
+ local split = lpegmatch(commasplitter,author)
+ local n = #split
+ if n == 1 then
+ --~ First von Last
+ words = lpegmatch(spacesplitter,author)
+ firstnames, vons, surnames = { }, { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ elseif n == 2 then
+ --~ von Last, First
+ words = lpegmatch(spacesplitter,split[2])
+ surnames = lpegmatch(spacesplitter,split[1])
+ firstnames, vons = { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ vons[#vons+1], i = words[i], i + 1
+ end
+ else
+ --~ von Last, Jr ,First
+ firstnames = lpegmatch(spacesplitter,split[1])
+ juniors = lpegmatch(spacesplitter,split[2])
+ surnames = lpegmatch(spacesplitter,split[3])
+ if n > 3 then
+ -- error
+ end
+ end
+ if #surnames == 0 then
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ end
+ if firstnames then
+ initials = { }
+ for i=1,#firstnames do
+ initials[i] = utfchar(lpegmatch(firstcharacter,firstnames[i]))
+ end
+ end
+ authors[i] = {
+ original = author,
+ firstnames = firstnames,
+ vons = vons,
+ surnames = surnames,
+ initials = initials,
+ juniors = juniors,
+ }
+ end
+ authors.original = str
+ return authors
+end
+
+local function the_initials(initials,symbol)
+ local t, symbol = { }, symbol or "."
+ for i=1,#initials do
+ t[i] = initials[i] .. symbol
+ end
+ return t
+end
+
+-- authors
+
+bibtex.authors = bibtex.authors or { }
+
+local authors = bibtex.authors
+
+local defaultsettings = {
+ firstnamesep = " ",
+ vonsep = " ",
+ surnamesep = " ",
+ juniorsep = " ",
+ surnamejuniorsep = ", ",
+ juniorjuniorsep = ", ",
+ surnamefirstnamesep = ", ",
+ surnameinitialsep = ", ",
+ namesep = ", ",
+ lastnamesep = " and ",
+ finalnamesep = " and ",
+}
+
+function authors.normal(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = concat(firstnames," ")
+ result[#result+1] = settings.firstnamesep or defaultsettings.firstnamesep
+ end
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = concat(juniors," ")
+ result[#result+1] = settings.surnamesep or defaultsettings.surnamesep
+ end
+ return concat(result)
+end
+
+function authors.normalshort(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = concat(firstnames," ")
+ result[#result+1] = settings.firstnamesep or defaultsettings.firstnamesep
+ end
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = concat(juniors," ")
+ result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep
+ end
+ return concat(result)
+end
+
+function authors.inverted(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = settings.juniorjuniorsep or defaultsettings.juniorjuniorsep
+ result[#result+1] = concat(juniors," ")
+ end
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = settings.surnamefirstnamesep or defaultsettings.surnamefirstnamesep
+ result[#result+1] = concat(firstnames," ")
+ end
+ return concat(result)
+end
+
+function authors.invertedshort(author,settings)
+ local vons, surnames, initials, juniors = author.vons, author.surnames, author.initials, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = settings.juniorjuniorsep or defaultsettings.juniorjuniorsep
+ result[#result+1] = concat(juniors," ")
+ end
+ if initials and #initials > 0 then
+ result[#result+1] = settings.surnameinitialsep or defaultsettings.surnameinitialsep
+ result[#result+1] = concat(the_initials(initials)," ")
+ end
+ return concat(result)
+end
+
+local lastconcatsize = 1
+
+local function bibtexconcat(t,settings)
+ local namesep = settings.namesep or defaultsettings.namesep or ", "
+ local lastnamesep = settings.lastnamesep or defaultsettings.lastnamesep or namesep
+ local finalnamesep = settings.finalnamesep or defaultsettings.finalnamesep or lastnamesep
+ local lastconcatsize = #t
+ if lastconcatsize > 2 then
+ local s = { }
+ for i=1,lastconcatsize-2 do
+ s[i] = t[i] .. namesep
+ end
+ s[lastconcatsize-1], s[lastconcatsize] = t[lastconcatsize-1] .. finalnamesep, t[lastconcatsize]
+ return concat(s)
+ elseif lastconcatsize > 1 then
+ return concat(t,lastnamesep)
+ elseif lastconcatsize > 0 then
+ return t[1]
+ else
+ return ""
+ end
+end
+
+function authors.concat(author,combiner,what,settings)
+ if type(combiner) == "string" then
+ combiner = authors[combiner or "normal"] or authors.normal
+ end
+ local split = splitauthors(author)
+ local setting = settings[what]
+ local etallimit, etaldisplay, etaltext = 1000, 1000, ""
+ if setting then
+ etallimit = settings.etallimit or 1000
+ etaldisplay = settings.etaldisplay or etallimit
+ etalltext = settings.etaltext or ""
+ end
+ local max = #split
+ if max > etallimit and etaldisplay < max then
+ max = etaldisplay
+ end
+ for i=1,max do
+ split[i] = combiner(split[i],settings)
+ end
+ local result = bibtexconcat(split,settings)
+ if max < #split then
+ return result
+ else
+ return result .. etaltext
+ end
+end
+
+function authors.short(author,year)
+ local result = { }
+ if author then
+ local authors = splitauthors(author)
+ for a=1,#authors do
+ local aa = authors[a]
+ local initials = aa.initials
+ for i=1,#initials do
+ result[#result+1] = initials[i]
+ end
+ local surnames = aa.surnames
+ for s=1,#surnames do
+ result[#result+1] = utfchar(lpegmatch(firstcharacter,surnames[s]))
+ end
+ end
+ end
+ if year then
+ result[#result+1] = year
+ end
+ return concat(result)
+end
+
+-- We can consider creating a hashtable key -> entry but I wonder if
+-- pays off.
+
+local function collectauthoryears(id,list)
+ list = settings_to_hash(list)
+ id = getid(id)
+ local found = { }
+ for e in xml.collected(id,"/bibtex/entry") do
+ if list[e.at.tag] then
+ local year = xmlfilter(e,"xml:///field[@name='year']/text()")
+ local author = xmlfilter(e,"xml:///field[@name='author']/text()")
+ if author and year then
+ local a = found[author]
+ if not a then
+ a = { }
+ found[author] = a
+ end
+ local y = a[year]
+ if not y then
+ y = { }
+ a[year] = y
+ end
+ y[#y+1] = e
+ end
+ end
+ end
+ -- found = { author = { year_1 = { e1, e2, e3 } } }
+ local done = { }
+ for author, years in next, found do
+ local yrs = { }
+ for year, entries in next, years do
+ if subyears then
+ -- -- add letters to all entries of an author and if so shouldn't
+ -- -- we tag all years of an author as soon as we do this?
+ -- if #entries > 1 then
+ -- for i=1,#years do
+ -- local entry = years[i]
+ -- -- years[i] = year .. string.char(i + string.byte("0") - 1)
+ -- end
+ -- end
+ else
+ yrs[#yrs+1] = year
+ end
+ end
+ done[author] = yrs
+ end
+ return done
+end
+
+local method, settings = "normal", { }
+
+function authors.setsettings(s)
+ settings = s or settings
+end
+
+if commands then
+
+ local sessions = { }
+
+ function commands.definebibtexsession(name)
+ sessions[name] = bibtex.new()
+ end
+
+ function commands.preparebibtexsession(name,xmlname,options)
+ bibtex.toxml(sessions[name],options)
+ lxml.register(xmlname,sessions[name].xml)
+ end
+
+ function commands.registerbibtexfile(name,filename)
+ bibtex.load(sessions[name],filename)
+ end
+
+ function commands.registerbibtexentry(name,entry)
+ local session = sessions[name]
+ local entries = session.entries
+ if not entries then
+ session.entries = { [entry] = true } -- here we can keep more info
+ else
+ entries[entry] = true
+ end
+ end
+
+ -- commands.bibtexconcat = bibtexconcat
+
+ -- finalizers can be rather dumb as we have just text and no embedded xml
+
+ function finalizers.bibtexconcat(collected,method,what)
+ if collected then
+ local author = collected[1].dt[1] or ""
+ if author ~= "" then
+ context(authors.concat(author,method,what,settings))
+ end
+ end
+ end
+
+ function finalizers.bibtexshort(collected)
+ if collected then
+ local c = collected[1]
+ local year = xmlfilter(c,"xml://field[@name='year']/text()")
+ local author = xmlfilter(c,"xml://field[@name='author']/text()")
+ context(authors.short(author,year))
+ end
+ end
+
+ -- experiment:
+
+ --~ -- alternative approach: keep data at the tex end
+
+ --~ local function xbibtexconcat(t,sep,finalsep,lastsep)
+ --~ local n = #t
+ --~ if n > 0 then
+ --~ context(t[1])
+ --~ if n > 1 then
+ --~ if n > 2 then
+ --~ for i=2,n-1 do
+ --~ context.bibtexpublicationsparameter("sep")
+ --~ context(t[i])
+ --~ end
+ --~ context.bibtexpublicationsparameter("finalsep")
+ --~ else
+ --~ context.bibtexpublicationsparameter("lastsep")
+ --~ end
+ --~ context(t[n])
+ --~ end
+ --~ end
+ --~ end
+
+ -- todo : sort
+
+ -- todo: choose between bibtex or commands namespace
+
+ function bibtex.authorref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ context(authors.concat(author,method,what,settings))
+ end
+ end
+
+ function bibtex.authoryearref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ context("%s (%s)",authors.concat(author,method,what,settings),concat(years,", "))
+ end
+ end
+
+ function bibtex.authoryearsref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ context("(%s, %s)",authors.concat(author,method,what,settings),concat(years,", "))
+ end
+ end
+
+ function bibtex.singularorplural(singular,plural)
+ if lastconcatsize and lastconcatsize > 1 then
+ context(plural)
+ else
+ context(singular)
+ end
+ end
+
+end
+
+
+--~ local function test(sample)
+--~ local authors = splitauthors(sample)
+--~ print(table.serialize(authors))
+--~ for i=1,#authors do
+--~ local author = authors[i]
+--~ print(normalauthor (author,settings))
+--~ print(normalshortauthor (author,settings))
+--~ print(invertedauthor (author,settings))
+--~ print(invertedshortauthor(author,settings))
+--~ end
+--~ print(concatauthors(sample,settings,normalauthor))
+--~ print(concatauthors(sample,settings,normalshortauthor))
+--~ print(concatauthors(sample,settings,invertedauthor))
+--~ print(concatauthors(sample,settings,invertedshortauthor))
+--~ end
+
+--~ local sample_a = "Hagen, Hans and Hoekwater, Taco Whoever T. Ex. and Henkel Hut, Hartmut Harald von der"
+--~ local sample_b = "Hans Hagen and Taco Whoever T. Ex. Hoekwater and Hartmut Harald von der Henkel Hut"
+
+--~ test(sample_a)
+--~ test(sample_b)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv
new file mode 100644
index 00000000000..80d04099bd2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv
@@ -0,0 +1,981 @@
+%D \module
+%D [ file=bibl-bib,
+%D version=2007.08.17,
+%D title=\CONTEXT\ Bibliography Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen \& Taco Hoekwater,
+%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 Bibliography Support / Experimental BibTeX}
+
+\registerctxluafile{bibl-bib}{1.001}
+
+\unprotect
+
+% todo: et al limiters
+% todo: split: citationvariant and publicationvariant
+
+%D This interface is under development. As I don't use \BIBTEX\ myself I need
+%D some motivation to spend time on it, and an occasional question on the
+%D list can be a reason. A few examples. As \BIBTEX\ databases can be poluted
+%D by local commands, we need to catch:
+%D
+%D \startbuffer
+%D \defbibtexcommand\MF {MF}
+%D \defbibtexcommand\MP {MP}
+%D \defbibtexcommand\TUB {TUGboat}
+%D \defbibtexcommand\Mc {Mac}
+%D \defbibtexcommand\sltt{\tt}
+%D \defbibtexcommand\<#1>{\type{#1}}
+%D \defbibtexcommand\acro#1{#1}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Let's define a session and load a few databases. We convert to \UTF\ and
+%D strip commands.
+%D
+%D \startbuffer
+%D \definebibtexsession [somebibtex]
+%D \registerbibtexfile [somebibtex] [tugboat.bib]
+%D \registerbibtexfile [somebibtex] [komoedie.bib]
+%D \preparebibtexsession [somebibtex] [convert,strip]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This loads an mapping (work in progress):
+%D
+%D \startbuffer
+%D \def\currentbibtexformat{apa} \input bxml-\currentbibtexformat.mkiv
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D There are several ways to handle the \XML. It helps if you're a bit
+%D familiar with \XML\ processing in \MKIV.
+%D
+%D Here we regular setups. Three elements are mapped but only one
+%D is actually used and applied to root element \type {/bibtex}.
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex
+%D \xmlregistereddocumentsetups{#1}{}
+%D \xmlsetsetup{#1}{bibtex|entry|field}{bibtex:*}
+%D \xmlmain{#1}
+%D \stopxmlsetups
+%D
+%D \startxmlsetups bibtex:bibtex
+%D \xmlfilter{#1}{
+%D /entry[@category='article']
+%D /field[@name='author' and (find(text(),'Hagen') or find(text(),'Hoekwater'))]
+%D /../command(bibtex:format)
+%D }
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D A simpler setup is given next. Here we just apply a setup to the root
+%D element directly:
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex:list
+%D \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)}
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex:list]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D A slightly more complex expression:
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex:filter
+%D \xmlfilter{#1}{
+%D /bibtex
+%D /entry[@category='article']
+%D /field[@name='author' and (find(text(),'Hagen') or find(text(),'Hoekwater'))]
+%D /../command(bibtex:format)
+%D }
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex:filter]
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\newtoks \everydefinebibtexsession
+\newtoks \everypreparebibtexsession
+\newtoks \everysetupbibtexsession
+\setfalse \tracebibtexformat
+
+\unexpanded\def\definebibtexsession{\dosingleargument\dodefinebibtexsession}
+\def\preparebibtexsession {\dodoubleempty \dopreparebibtexsession}
+\unexpanded\def\setupbibtexsession {\dodoubleargument\dosetupbibtexsession}
+
+\def\dodefinebibtexsession [#1]{\edef\currentbibtexsession{#1}%
+ \ctxcommand{definebibtexsession("#1")}%
+ \the\everydefinebibtexsession}
+
+\def\dopreparebibtexsession[#1][#2]{\edef\currentbibtexsession{#1}%
+ \ctxcommand{preparebibtexsession("#1","bibtex:#1","#2")}%
+ \the\everypreparebibtexsession}
+
+\def\dosetupbibtexsession [#1][#2]{\edef\currentbibtexsession{#1}%
+ \getparameters[\??pb#1][#2]%
+ \the\everysetupbibtexsession}
+
+\def\registerbibtexfile {\dodoubleargument\doregisterbibtexfile}
+\def\registerbibtexentry {\dodoubleargument\doregisterbibtexentry}
+\def\applytobibtexsession {\dodoubleargument\doapplytobibtexsession}
+
+\def\doregisterbibtexfile [#1][#2]{\ctxcommand{registerbibtexfile("#1","#2")}}
+\def\doregisterbibtexentry [#1][#2]{\ctxcommand{registerbibtexentry("#1","#2")}}
+\def\doapplytobibtexsession[#1][#2]{\xmlprocessregistered{bibtex:#1}{#2}{#2}}
+
+\unexpanded\def\bibtexcommand#1%
+ {\ifcsname\??pb:c:#1\endcsname \else
+ \fakebibtexcommand{#1}%
+ \fi
+ \csname\??pb:c:#1\endcsname}
+
+\def\fakebibtexcommand#1%
+ {\ifcsname#1\endcsname
+ \writestatus{bibtex}{unknown command: #1, using built-in context variant}%
+ \setugvalue{\??pb:c:#1}{\dosomebibtexcommand{#1}}%
+ \else
+ \writestatus{bibtex}{unknown command: #1}%
+ \setugvalue{\??pb:c:#1}{\dofakebibtexcommand{#1}}%
+ \fi}
+
+\let\dosomebibtexcommand \getvalue
+\def\dofakebibtexcommand#1{{\tttf#1}}
+
+\def\defbibtexcommand#1%
+ {\setuvalue{\strippedcsname#1}}
+
+\def\bibxmldoifelse#1{\xmldoifelse\currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmldoif #1{\xmldoif \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmldoifnot #1{\xmldoifnot \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmlflush #1{\xmlcontext \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmlsetup {\xmlsetup \currentbibxmlnode} % {#1}
+
+\def\currentbibtexformat{apa} % how to interface this, maybe split loading and key
+\def\currentbibxmlnode {unset}
+\def\currentbibxmltag {unset}
+
+\startxmlsetups bibtex
+ \xmlregistereddocumentsetups{#1}{}
+ \xmlsetsetup{#1}{bibtex|entry|field}{bibtex:*}
+ \xmlmain{#1}
+\stopxmlsetups
+
+\startxmlsetups bibtex:format
+ \bibtexpublicationsparameter\c!before\relax % prevents lookahead
+ \edef\currentbibxmlnode {#1}
+ \edef\currentbibxmltag {\xmlatt{#1}{tag}}
+ \edef\currentbibxmlcategory{\xmlatt{#1}{category}}
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlintro\currentbibxmltag
+ \tracedbibxmlintro\currentbibxmlcategory
+ \fi
+ \ignorespaces
+ \xmlcommand{#1}{.}{bibtex:\currentbibtexformat:\currentbibxmlcategory}
+ \removeunwantedspaces
+ \bibtexpublicationsparameter\c!after\relax % prevents lookahead
+\stopxmlsetups
+
+\startxmlsetups bibtex:list
+ \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)}
+\stopxmlsetups
+
+\startxmlsetups bibtex:bibtex
+ \xmlfilter{#1}{/entry/command(bibtex:format)}
+\stopxmlsetups
+
+% formatters
+
+\let\normalbibxmlflush\bibxmlflush
+
+\definecolor[bibtextracecolor:field] [darkred]
+\definecolor[bibtextracecolor:crossref][darkblue]
+\definecolor[bibtextracecolor:key] [darkgreen]
+
+\def\tracedbibxmlintro #1{{\tttf#1 -> }}
+\def\tracedbibxmlflush #1{\color[bibtextracecolor:field] {\tttf[#1]}}
+\def\tracedbibxmltexts #1{\color[bibtextracecolor:field] {\tttf<#1>}}
+\def\tracedbibxmlcrossref#1{\color[bibtextracecolor:crossref]{\tttf#1}}
+\def\tracedbibxmlkey #1{\color[bibtextracecolor:key] {\tttf#1}}
+
+\def\tracedbibxmltext
+ {\ifconditional\tracebibtexformat
+ \expandafter\tracedbibxmltexts % plural
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\bibxmlflush
+ {\ifconditional\tracebibtexformat
+ \expandafter\tracedbibxmlflush
+ \else
+ \expandafter\normalbibxmlflush
+ \fi}
+
+\startxmlsetups bibtex:format:crossref
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlcrossref{\xmlfirst\currentbibxmlnode{/field[@name='crossref']/lower()}}
+ \else
+ \cite[\xmlfirst\currentbibxmlnode{/field[@name='crossref']/lower()}]
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:key
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlkey{\normalbibxmlflush{key}}
+ \else
+ \bibxmlflush{key}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:common:author
+ \ifconditional\tracebibtexformat
+ \bibxmlflush\currentbibtexvariant
+ \else
+ \xmlfilter{#1}{/field[@name='\currentbibtexvariant']/bibtexconcat('\currentbibtexvariant')}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:author
+ \begingroup
+ \def\currentbibtexvariant{author}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:artauthor
+ \begingroup
+ \def\currentbibtexvariant{artauthor}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:editor
+ \begingroup
+ \def\currentbibtexvariant{editor}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:doi
+% \bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}
+ *doi*
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:doi
+% \bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}
+ *url*
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:month
+% {\bibdoifelse\@@pb@month
+% {#1\doifnumberelse\@@pb@month
+% {\doifconversiondefinedelse\@@pbmonthconversion
+% {\convertnumber\@@pbmonthconversion\@@pb@month}{\@@pb@month}}%
+% {\@@pb@month}#2}%
+% {#3}
+ *month*
+\stopxmlsetups
+
+% lists
+
+\def\bibtexlistprocessor
+ {\ctxlua{bibtex.hacks.add(structures.lists.uservalue("\currentlist",\currentlistindex,"bibref"),\currentlistindex)}}
+
+\appendtoks
+ \definelist[\currentbibtexsession]%
+ \setuplist[\currentbibtexsession][\c!state=\v!start,\c!width=]%
+ \installstructurelistprocessor{\currentbibtexsession:userdata}{\bibtexlistprocessor}%
+\to \everydefinebibtexsession
+
+% \def\installbibtexsorter#1#2%
+% {\setvalue{\??pb:\c!sort:#1}{#2}}
+
+% \installbibtexsorter\v!no {no}
+% \installbibtexsorter\v!author {au}
+% \installbibtexsorter\v!title {ti}
+% \installbibtexsorter\v!short {ab}
+% \installbibtexsorter\empty {no}
+% \installbibtexsorter\s!default{no}
+
+% \setupbibtex
+% [\c!sorttype=\v!cite,
+% \c!sort=no]
+
+% \unexpanded\def\startpublication#1\stoppublication
+% {\blank
+% todo
+% \blank}
+
+% \let\stoppublication\relax
+
+\unexpanded\def\bibtexspace {\removeunwantedspaces\space}
+\unexpanded\def\bibtexperiod {\removeunwantedspaces.\space}
+\unexpanded\def\bibtexcomma {\removeunwantedspaces,\space}
+\unexpanded\def\bibtexlparent {\removeunwantedspaces\space(}
+\unexpanded\def\bibtexrparent {\removeunwantedspaces)\space}
+\unexpanded\def\bibtexlbracket{\removeunwantedspaces\space[}
+\unexpanded\def\bibtexrbracket{\removeunwantedspaces]\space}
+
+% interfacing
+
+% todo : lang en language
+% todo : directions
+
+% variables
+
+\ifdefined\bibtexblock \else \newcount\bibtexblock \fi \bibtexblock\plusone
+\ifdefined\bibtexcounter \else \newcount\bibtexcounter \fi
+
+\newtoks \everysetupbibtexpublications
+\newtoks \everysetupbibtexcitations
+
+\def\bibtexrefprefix{\number\bibtexblock:}
+
+\let\currentbibtexsession\s!default
+\let\currentbibtexvariant\s!default
+
+% parameters: session+variant variant session shared
+
+\def\bibtexpublicationsparameter#1%
+ {\csname
+ \ifcsname\??pb\currentbibtexsession:\currentbibtexvariant#1\endcsname
+ \??pb\currentbibtexsession:\currentbibtexvariant#1%
+ \else\ifcsname\??pb:\currentbibtexvariant#1\endcsname
+ \??pb:\currentbibtexvariant#1%
+ \else\ifcsname\??pb\currentbibtexsession#1\endcsname
+ \??pb\currentbibtexsession#1%
+ \else\ifcsname\??pb#1\endcsname
+ \??pb#1%
+ \else
+ \s!empty
+ \fi\fi\fi\fi
+ \endcsname}
+
+\def\bibtexcitationparameter#1%
+ {\csname
+ \ifcsname\??pv\currentbibtexsession:\currentbibtexvariant#1\endcsname
+ \??pv\currentbibtexsession:\currentbibtexvariant#1%
+ \else\ifcsname\??pv:\currentbibtexvariant#1\endcsname
+ \??pv:\currentbibtexvariant#1%
+ \else\ifcsname\??pv\currentbibtexsession#1\endcsname
+ \??pv\currentbibtexsession#1%
+ \else\ifcsname\??pv#1\endcsname
+ \??pv#1%
+ \else
+ \s!empty
+ \fi\fi\fi\fi
+ \endcsname}
+
+% setup commands
+
+\unexpanded\def\setupbibtexpublications
+ {\let\currentpublicationclass\??pb
+ \let\everysetupbibtexwhatever\everysetupbibtexpublications
+ \dodoubleargument\dosetupbibtexwhatever}
+
+\unexpanded\def\setupbibtexcitations
+ {\let\currentpublicationclass\??pv
+ \let\everysetupbibtexwhatever\everysetupbibtexcitations
+ \dodoubleargument\dosetupbibtexwhatever}
+
+\unexpanded\def\setupbibtexpublicationvariants
+ {\let\currentpublicationclass\??pb
+ \let\everysetupbibtexwhatever\everysetupbibtexpublications
+ \dotripleargument\dosetupbibtexwhatevervariant}
+
+\unexpanded\def\setupbibtexcitationvariants
+ {\let\currentpublicationclass\??pv
+ \let\everysetupbibtexwhatever\everysetupbibtexcitations
+ \dotripleargument\dosetupbibtexwhatevervariant}
+
+\def\dosetupbibtexwhatever[#1][#2]% [sessionlist] [setup]
+ {\ifsecondargument
+ % sessions setups
+ \def\dobtxcommand##1{\getparameters[\currentpublicationclass##1][#2]}%
+ \processcommalist[#1]\dobtxcommand
+ \else
+ % setups
+ \getparameters[\currentpublicationclass][#1]%
+ \the\everysetupbibtexwhatever
+ \fi}
+
+\def\dosetupbibtexwhatevervariant[#1][#2][#3]% [sessionlist] [variantlist] [setup]
+ {\ifthirdargument
+ % sessions variants setups
+ \def\dobtxcommand##1%
+ {\def\dodobtxcommand####1{\getparameters[\currentpublicationclass##1:####1][#3]}%
+ \processcommalist[#2]\dodobtxcommand}%
+ \processcommalist[#1]\docbtxommand
+ \else\ifsecondargument
+ % variants setups
+ \def\dobtxcommand##1{\getparameters[\currentpublicationclass:##1][#2]}%
+ \processcommalist[#1]\dobtxcommand
+ \else
+ % setups
+ \getparameters[\currentpublicationclass][#1]%
+ \the\everysetupbibtexwhatever
+ \fi\fi}
+
+% some initializations
+
+\setupbibtexcitationvariants
+ [author,authoryear,authoryears]
+ [\c!namesep={, }]
+
+% loading alternatives (apa etc)
+
+\def\doloadbibtexpublicationalternative
+ {\ifproductionrun
+ \edef\bibtexpublicationsalternative{\@@pbalternative}% parent
+ \ifx\bibtexpublicationsalternative\empty \else
+ \processcommacommand[\bibtexpublicationsalternative]\dodoloadbibtexpublicationalternative
+ \let\@@pbalternative\empty
+ \fi
+ \fi}
+
+\def\dodoloadbibtexpublicationalternative#1%
+ {\doonlyonce{#1}
+ {\startreadingfile
+ \readsysfile{bxml-#1.mkiv}
+ {\showmessage\m!publications{6}{bxml-#1}}
+ {\showmessage\m!publications{1}{bxml-#1}}%
+ \stopreadingfile}}
+
+\appendtoks
+ \doloadbibtexpublicationalternative
+\to \everysetupbibtexpublications
+
+% we expect at least one invocation of the setup commands
+% because otherwise we always load the apa style even if
+% no publications are used
+%
+% \appendtoks
+% \doloadbibtexpublicationalternative
+% \to \everystarttext
+
+% whatever, should be key
+
+\def\bibtexleftnumber#1{#1\hfill~}
+
+% testing
+
+% \showmessage\m!publications{5}{#1 is unknown}\secondoftwoarguments}
+
+\let\doifbibreferencefoundelse\secondofthreearguments
+
+% lists
+
+\newtoks\everysetupbibtexlistplacement
+
+% this will change as we need it too often .. we will use context.thebibtexnamesep
+
+\appendtoks
+ \ctxlua {bibtex.authors.setsettings {
+ namesep = \!!bs\bibtexpublicationsparameter\c!namesep\!!es,
+ lastnamesep = \!!bs\bibtexpublicationsparameter\c!lastnamesep\!!es,
+ finalnamesep = \!!bs\bibtexpublicationsparameter\c!finalnamesep\!!es,
+ firstnamesep = \!!bs\bibtexpublicationsparameter\c!firstnamesep\!!es,
+ juniorsep = \!!bs\bibtexpublicationsparameter\c!juniorsep\!!es,
+ vonsep = \!!bs\bibtexpublicationsparameter\c!vonsep\!!es,
+ surnamesep = \!!bs\bibtexpublicationsparameter\c!surnamesep\!!es,
+ namesep = \!!bs\bibtexpublicationsparameter\c!namesep\!!es,
+ lastnamesep = \!!bs\bibtexpublicationsparameter\c!lastnamesep\!!es,
+ finalnamesep = \!!bs\bibtexpublicationsparameter\c!finalnamesep\!!es,
+ author = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!authoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!authoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!authoretaltext\!!es,
+ },
+ editor = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!editoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!editoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!editoretaltext\!!es,
+ },
+ artauthor = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!artauthoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!artauthoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!artauthoretaltext\!!es,
+ },
+ } }%
+\to \everysetupbibtexlistplacement
+
+\def\completebibtexpublications{\dodoubleempty\docompletebibtexpublications}
+\unexpanded\def\placebibtexpublications {\dodoubleempty\doplacebibtexpublications}
+
+\def\docompletebibtexpublications[#1][#2]% title might become obsolete, just headtext
+ {\begingroup
+ \edef\currentbibtexsession{#1}%
+ \let\currentlist\currentbibtexsession
+ \setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]
+ \edef\currentbibtexsessiontitle{\namedlistparameter\currentbibtexsession\c!title}%
+ \ifx\currentbibtexsessiontitle\empty
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbibtexsession,\c!title={\headtext{\currentbibtexsession}}]}%
+ \else
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbibtexsession,\c!title={\currentbibtexsessiontitle}]}%
+ \fi
+ \dodoplacebibtexpublications
+ \stopnamedsection
+ \endgroup}
+
+\def\doplacebibtexpublications[#1][#2]%
+ {\begingroup
+ \edef\currentbibtexsession{#1}%
+ \let\currentlist\currentbibtexsession
+ \setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]%
+ \dodoplacebibtexpublications
+ \endgroup}
+
+\def\dodoplacebibtexpublications
+ {\determinelistcharacteristics[\currentbibtexsession]%
+ \the\everysetupbibtexlistplacement
+ \forgetall
+ \typesetbibtexlist
+ \global\advance\bibtexblock\plusone}
+
+\setvalue{\??pb:\c!numbering:\v!short}#1% todo var s -> short tag
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexgetshort\currentpublicationtag}}}
+
+\setvalue{\??pb:\c!numbering:\v!bib}#1% todo var n -> number
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexgetnumber\currentpublicationtag}}}
+
+\setvalue{\??pb:\c!numbering:\s!unknown}#1%
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{#1}}}
+
+\def\@@pblimitednumber % name
+ {\csname\??pb:\c!numbering:%
+ \ifcsname\??pb:\c!numbering:\currentbibtexnumbering\endcsname
+ \currentbibtexnumbering
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\appendtoks
+ \edef\currentbibtexnumbering{\bibtexpublicationsparameter\c!numbering}%
+ \ifx\currentbibtexnumbering\v!no
+ \setuplist[\currentbibtexsession][\c!numbercommand=,\c!symbol=\v!none,\c!textcommand=\outdented]%
+ \else
+ \setuplist[\currentbibtexsession][\c!numbercommand=\@@pblimitednumber]%
+ \fi
+\to \everysetupbibtexlistplacement
+
+\newdimen\bibtexnumberwidth
+
+\def\bibtexlistnumberbox{\hbox \ifcase\bibtexnumberwidth\else to \bibtexnumberwidth\fi}
+
+\appendtoks
+ \doifelse{\bibtexpublicationsparameter\c!autohang}\v!yes
+ {\ifx\currentbibtexnumbering\v!short
+ \setbox\scratchbox\hbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexpublicationsparameter\c!samplesize}}%
+ \else
+ \setbox\scratchbox\hbox{\bibtexpublicationsparameter\c!numbercommand{\ctxlua{tex.write(structures.lists.size())}}}%
+ \fi
+ \bibtexnumberwidth\wd\scratchbox
+ \setuplist[\currentbibtexsession][\c!distance=\zeropoint]}
+ {\doifelsenothing{\bibtexpublicationsparameter\c!width}
+ {\bibtexnumberwidth\zeropoint}
+ {\bibtexnumberwidth\bibtexpublicationsparameter\c!width}}%
+ \setuplist[\currentbibtexsession][\c!width=\bibtexnumberwidth]%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \let\maybeyear\gobbleoneargument
+ \let\noopsort \gobbleoneargument
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \doifelse{\bibtexpublicationsparameter\c!maybeyear}\v!off
+ {\let\maybeyear\gobbleoneargument}
+ {\let\maybeyear\firstofoneargument}%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \doifnot{\bibtexpublicationsparameter\c!option}\v!continue
+ {\global\bibtexcounter\zerocount}%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \edef\currentbibtexcriterium{\namedlistparameter\currentbibtexsession\c!criterium}%
+\to \everysetupbibtexlistplacement
+
+\def\typesetbibtexlist
+ {\begingroup
+ \startpacked[\v!blank]%
+ \doif{\namedlistparameter\currentbibtexsession\c!criterium}\v!cite
+ {\setuplist[\currentbibtexsession][\c!criterium=\v!here]}%
+ \doifelse{\bibtexpublicationsparameter\c!method}\v!local
+ {\ctxlua{bibtex.hacks.reset(1)}}% function can take method
+ {\ctxlua{bibtex.hacks.reset(2)}}%
+ \strc_lists_place_current
+ {\currentbibtexsession}
+ {\currentbibtexcriterium}
+ {}%
+ {\namedlistparameter\currentbibtexsession\c!extras}%
+ {\namedlistparameter\currentbibtexsession\c!order}%
+ \ctxlua{bibtex.hacks.flush("\bibtexpublicationsparameter\c!sorttype")}%
+ \stoppacked
+ \endgroup}
+
+\unexpanded\def\typesetbibtexpublication#1%
+ {\edef\currentbibtexsessiontag{#1}%
+ \ifx\currentbibtexsessiontag\empty
+ % can't really happen
+ \else\ifx\currentbibtexcriterium\v!all
+ \dotypesetbibtexpublication % was \doplacepublicationindeed
+ \else
+ \ctxlua{bibtex.hacks.doifalreadyplaced("\currentbibtexsessiontag")}
+ \donothing
+ \dotypesetbibtexpublication
+ \fi\fi}
+
+\def\dotypesetbibtexpublication
+ {\doifelsebibreferencefound\currentbibtexsessiontag
+ {\global\advance\bibtexcounter\plusone
+ \ctxlua{bibtex.hacks.registerplaced("\currentbibtexsessiontag")}%
+ \let\currentlist\currentbibtexsession
+ \let\currentlistentrynumber \bibtexcounter
+ \let\currentlistentrytitle \thebibtexpublicationlistelement
+ \let\currentlistentrypagenumber\empty
+ \strc_lists_apply_renderingsetup}
+ {}} % invalid
+
+\def\thebibtexpublicationlistelement
+ {\strut
+ \expanded{\reference[\bibtexrefprefix\currentbibtexsessiontag]{\number\bibtexcounter}}%
+ \dotypesetabibtexpublication\currentbibtexsessiontag
+ \strut}
+
+\def\dotypesetabibtexpublication#1%
+ {\begingroup
+ \ignorespaces
+ \xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/command(bibtex:format)}%
+ \removeunwantedspaces
+% \ignorespaces
+% \bibalternative{\bibgetvart{#1}}%
+% \removeunwantedspaces
+ \endgroup}
+
+\def\doprocessbibtexentry#1{\typesetbibtexpublication{#1}}
+
+% citations
+
+\unexpanded\def\bibtexcitation[#1]%
+ {\edef\currentbibtexsession{#1}%
+ \strictdoifelsenextoptional\dobibtexcitation\dobibtexref}
+
+\def\dobibtexref#1%
+ {\dodobibtexcitation[#1][]}
+
+\def\dobibtexcitation[#1]%
+ {\strictdoifelsenextoptional{\dodobibtexcitation[#1]}{\dodobibtexcitation[#1][]}}
+
+\def\dodobibtexcitation[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \doifelsenothing{#2}\secondargumentfalse\secondargumenttrue
+ \ifsecondargument
+ \dowhateverbibtexcitation{#1}{#2}%
+ \else
+ \donumberedbibtexcitation{#1}%
+ \fi
+ \endgroup}
+
+\def\dowhatevercitation#1#2%
+ {\processcommalist[#2]\dobibtexcitationindeed
+ \setupinteraction[\c!style=]% use flag instead
+ \doifelseassignment{#1}
+ {\getparameters[\??pb\??pb][\c!alternative=,\c!extras=,#1]%
+ \edef\currentbibtexvariant{\@@pb@@pbalternative}%
+ \ifx\currentbibtexvariant\empty
+ \edef\currentbibtexvariant{\bibtexpublicationparameter\c!refcommand}%
+ \fi
+ \ifx\@@pb@@pbextras\empty
+ \setupcite[\currentbibtexvariant][#1]%
+ \else
+ \edef\@@pb@@pbextras{{\@@pb@@pbextras\ifdefined\@@pb@@pbright\@@pb@@pbright\else\bibtexpublicationparameter\c!right\fi}}%
+ \expanded{\setupcite[\currentbibtexvariant][#1,\c!right=\@@pb@@pbextras]}%
+ \fi}%
+ {\def\currentbibtexvariant{#1}}%
+ \getvalue{bibtex\currentbibtexvariant ref}[#2]}
+
+\def\donumberedbibtexcitation#1%
+ {\processcommalist[#1]\dobibtexcitationindeed
+ \setupinteraction[\c!style=]%
+ \edef\currentbibtexvariant{\bibtexcitationparameter\c!refcommand}%
+ \getvalue{bibtex\currentbibtexvariant ref}[#1]}
+
+\def\dobibtexcitationindeed#1%
+ {\iftrialtypesetting \else
+ \expanded{\writedatatolist[\currentbibtexsession][bibref=#1]}%
+ \fi}
+
+\def\nobibtexcitation[#1]%
+ {\processcommalist[#1]\dobibtexcitationindeed}
+
+\def\bibtexnumref[#1]%
+ {\dontleavehmode
+ \begingroup
+ \bibtexcitationparameter\v!left
+ \penalty\plustenthousand
+ \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
+ \bibtexcitationparameter\v!right
+ \endgroup}
+
+\def\dowithbibtexnumrefconnector#1#2%
+ {\ifnum#1>\plusone
+ \ifnum#2>\plusone
+ \ifnum#2=#1\relax
+ \bibtexpublicationsparameter\c!lastpubsep
+ \else
+ \bibtexpublicationsparameter\c!pubsep
+ \fi
+ \fi
+ \fi}
+
+\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibtexrefprefix{#4:}%
+ \inbiblink[#5]}
+
+\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibtexrefprefix{#4:}%
+ \inbiblink[#5]%
+ \endash
+ \def\bibtexrefprefix{#6:}%
+ \inbiblink[#7]}
+
+\def\nobibtexnumref#1%
+ {[#1]}
+
+% hm
+
+% \def\@@pbinumbercommand{\executeifdefined{\??pb:\c!numbercommand:\@@pbnumbering}\firstofoneargument}
+
+% \letvalue{\??pb:\c!numbercommand:\v!yes }\firstofoneargument
+% \letvalue{\??pb:\c!numbercommand:\v!no }\gobbleoneargument
+% \setvalue{\??pb:\c!numbercommand:\v!short}{\bibtexgetshort\currentpublicationtag\gobbleoneargument}
+% \setvalue{\??pb:\c!numbercommand:\v!bib }{\bibtexgetnumber\currentpublicationtag\gobbleoneargument}
+
+% \def\bibalternative#1{\csname\??pv\@@currentalternative#1\endcsname}
+
+% basic setup
+
+% parent -> publicationlist
+%
+% \setuplist
+% [\currentbibtexsession]
+% [\c!samplesize={AA99},
+% \c!alternative=a,
+% \c!interaction=,
+% \c!pagenumber=\v!no,
+% #1,
+% \c!command=]
+
+% \setuppublicationlist
+% [\c!title=,
+% \c!command=\dospecialbibinsert,
+% \c!maybeyear=\v!on]
+
+\setupbibtexpublications
+ [\c!monthconversion=,
+ \c!alternative=apa,
+ \c!method=\v!global,
+ \c!refcommand=num,
+ \c!numbercommand=\bibtexleftnumber]
+
+\setupbibtexcitations % command ?
+ [\c!refcommand=num]
+
+% helpers
+
+\unexpanded\def\doifelsebibtexinteraction
+ {\iflocation
+ \edef\temp{\bibtexcitationparameter\c!interaction}%
+ \ifx\temp\v!stop
+ \@EA@EA@EA\secondoftwoarguments
+ \else
+ \@EA@EA@EA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+\let\doifbibtexinteractionelse\doifelsebibtexinteraction
+
+% variants
+
+% todo: lastsep here
+
+\newconditional\firstbibtexrefsep
+
+\def\bibtexresetrefsep
+ {\settrue\firstbibtexrefsep}
+
+\def\bibtexinsertrefsep
+ {\ifconditional\firstbibtexrefsep
+ \setfalse\firstbibtexrefsep
+ \else
+ \bibtexcitationparameter\c!pubsep
+ \fi}
+
+\def\inbibtexlink#1#2%
+ {\doifelsereferencefound{\bibtexrefprefix#1}
+ {\goto{#2}[\bibtexrefprefix#1]}
+ {!#1!}}
+
+\def\dobibtexgotolink#1#2%
+ {\doifelsereferencefound{\bibtexrefprefix#1}
+ {\goto{#2}[\bibtexrefprefix#1]}
+ {!#1!}}
+
+\def\dobibattexlink#1#2%
+ {\doifelsereferencefound{\bibtexrefprefix#1}
+ {\at{#2}[\bibtexrefprefix#1]}
+ {!#1!}}
+
+\def\dobibtexurllink#1#2%
+ {\expanded{\useURL[bibtex:url:#1][#2]}%
+ \doifelsebibtexinteraction
+ {\goto{\url[bibtex:url:#1]}[url(bibtex:url:#1)]}
+ {\url[bibtex:url:#1]}}
+
+% todo: style, color
+
+\unexpanded\def\bibtexdataref {\dodoubleargument\dobibtexdataref}
+\unexpanded\def\bibtextyperef {\dodoubleargument\dobibtextyperef}
+\unexpanded\def\bibtexkeyref {\dodoubleargument\dobibtexkeyref}
+\unexpanded\def\bibtexserialref {\dodoubleargument\dobibtexserialref}
+\unexpanded\def\bibtexurlref {\dodoubleargument\dobibtexurlref}
+\unexpanded\def\bibtexdoiref {\dodoubleargument\dobibtexdoiref}
+\unexpanded\def\bibtexpageref {\dodoubleargument\dobibtexpageref}
+\unexpanded\def\bibtexnoneref {\dodoubleargument\dobibtexnoneref}
+\unexpanded\def\bibtexshortref {\dodoubleargument\dobibtexshortref}
+\unexpanded\def\bibtexyearref {\dodoubleargument\dobibtexyearref}
+\unexpanded\def\bibtexauthorref {\dodoubleargument\dobibtexauthorref}
+\unexpanded\def\bibtexauthoryearref {\dodoubleargument\dobibtexauthoryearref}
+\unexpanded\def\bibtexauthoryearsref{\dodoubleargument\dobibtexauthoryearsref}
+
+\def\dobibtexdataref {\doprocessbibtexref\dodobibtexdataref {ref}} % [#1][#2]
+\def\dobibtextyperef {\doprocessbibtexref\dodobibtextyperef {type}} % [#1][#2]
+\def\dobibtexkeyref {\doprocessbibtexref\dodobibtexkeyref {key}} % [#1][#2]
+\def\dobibtexserialref {\doprocessbibtexref\dodobibtexserialref {serial}} % [#1][#2]
+\def\dobibtexurlref {\doprocessbibtexref\dodobibtexurlref {url}} % [#1][#2]
+\def\dobibtexdoiref {\doprocessbibtexref\dodobibtexdoiref {doi}} % [#1][#2]
+\def\dobibtexpageref {\doprocessbibtexref\dodobibtexpageref {page}} % [#1][#2]
+\def\dobibtexnoneref {\doprocessbibtexref\dodobibtexnoneref {none}} % [#1][#2]
+\def\dobibtexshortref {\doprocessbibtexref\dodobibtexshortref {short}} % [#1][#2]
+\def\dobibtexyearref {\doprocessbibtexref\dodobibtexyearref {year}} % [#1][#2]
+\def\dobibtexauthorref {\doprocessbibtexref\dodobibtexauthorref {author}} % [#1][#2]
+\def\dobibtexauthoryearref {\doprocessbibtexref\dodobibtexauthoryearref {authoryear}} % [#1][#2]
+\def\dobibtexauthoryearsref{\doprocessbibtexref\dodobibtexauthoryearsref{authoryears}} % [#1][#2]
+
+\def\doprocessbibtexref#1#2[#3][#4]%
+ {\edef\currentbibtexsession{#3}%
+ \edef\currentbibtexvariant{#2}%
+ \def\dodoprocessbibtexref##1%
+ {% test for existence
+ \edef\currentbibtextag{##1}%
+ \bibtexinsertrefsep
+ #1{##1}}%
+ \bibtexresetrefsep
+ \bibtexcitationparameter\v!left
+ \processcommalist[#4]\dodoprocessbibtexref\relax
+ \bibtexcitationparameter\v!right}
+
+\def\dodobibtexdataref#1%
+ {\dotypesetabibtexpublication{#1}}
+
+\def\dodobibtextyperef#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/attribute('category')}}%
+ \bibtexrefcontent}
+
+\def\dodobibtexkeyref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='key']/context()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexserialref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/match()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexurlref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='url']/context()}}%
+ \dobibtexurllink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexdoiref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='doi']/context()}}%
+ \dobibtexurllink{#1}{http://dx.doi.org/\bibtexrefcontent}}
+
+\def\dodobibtexpageref#1%
+ {\dobibtexatlink{#1}{}} % second argument can become 'page'
+
+\def\dodobibtexnoneref#1%
+ {}
+
+\def\dodobibtexshortref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/bibtexshort()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexyearref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='year']/context()}}%
+ \bibtexrefcontent}
+
+% \def\bibmaybeinteractive#1#2%
+% {\doifelsevalue{@@pv\@@currentalternative\c!compress}
+% {\ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}}
+% {#2}}
+
+% \def\bibauthornumref[#1]%
+% {\getcommalistsize[#1]%
+% \global\bibitemcounter\commalistsize
+% \bibresetrefsep
+% \processcommalist[#1]\dobibauthornumref }
+%
+% \def\dobibauthornumref#1%
+% {\bibinsertrefsep
+% \doifbibreferencefoundelse{#1}
+% {\begingroup
+% \bibgetvara{#1}%
+% \bibalternative\c!inbetween
+% \setuppublications[\c!refcommand=num]%
+% \cite[#1]%
+% \endgroup}
+% {}}
+
+% compress years
+% andtext namesep
+% otherstext authoretallimit
+
+% we will use context.* instead at the lua end because it saves us passing settings
+
+% \def\thebibtexpubsep {\bibtexpublicationsparameter\c!pubsep}
+% \def\thebibtexlastpubsep {\bibtexpublicationsparameter\c!lastpubsep}
+% \def\thebibtexfinalpubseparator{\bibtexpublicationsparameter\c!lastpubsep}
+
+\def\dodobibtexauthorref #1{\ctxlua{bibtex.authorref ("bibtex:\currentbibtexsession","#1","normal","author")}}
+\def\dodobibtexauthoryearref #1{\ctxlua{bibtex.authoryearref ("bibtex:\currentbibtexsession","#1","normal","author")}}
+\def\dodobibtexauthoryearsref#1{\ctxlua{bibtex.authoryearsref("bibtex:\currentbibtexsession","#1","normal","author")}}
+
+\unexpanded\def\bibtexsingularplural#1#2{\ctxlua{bibtex.singularorplural(\!!bs#1\!!es,\!!bs#2\!!es)}}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.lua b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.lua
new file mode 100644
index 00000000000..223554b4daa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.lua
@@ -0,0 +1,301 @@
+if not modules then modules = { } end modules ['bibl-tra'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- also see bibl-tra-new !
+
+-- temporary hack, needed for transition
+
+if not publications then
+
+ local hacks = utilities.storage.allocate()
+
+ job.register('publications.collected',hacks,function(t) publications.collected = t end)
+
+end
+
+-- end of hack
+
+
+local match, gmatch, format, concat, sort = string.match, string.gmatch, string.format, table.concat, table.sort
+
+bibtex = bibtex or { }
+local bibtex = bibtex
+
+bibtex.hacks = bibtex.hacks or { }
+local hacks = bibtex.hacks
+
+local trace_bibtex = false trackers.register("publications.bibtex", function(v) trace_bibtex = v end)
+
+local report_tex = logs.reporter("publications","tex")
+
+local context = context
+local structures = structures
+
+local references = structures.references
+local sections = structures.sections
+
+local variables = interfaces.variables
+
+local v_short = variables.short
+local v_cite = variables.cite
+local v_default = variables.default
+local v_reference = variables.default
+
+local list = { }
+local done = { }
+local alldone = { }
+local used = { }
+local registered = { }
+local ordered = { }
+local shorts = { }
+local mode = 0
+
+local template = [[
+\citation{*}
+\bibstyle{cont-%s}
+\bibdata{%s}
+]]
+
+local bibtexbin = environment.arguments.mlbibtex and "mlbibcontext" or "bibtex"
+
+directives.register("publications.usemlbibtex", function(v)
+ bibtexbin = v and "mlbibcontext" or "bibtex"
+end)
+
+function hacks.process(settings)
+ local style = settings.style or ""
+ local database = settings.database or ""
+ local jobname = tex.jobname
+ if database ~= "" then
+ local targetfile = file.addsuffix(jobname,"aux")
+ interfaces.showmessage("publications",3,targetfile)
+ io.savedata(targetfile,format(template,style,database))
+ if trace_bibtex then
+ report_tex("processing bibtex file %a using %a",jobname,bibtexbin)
+ end
+ os.execute(format("%s %q",bibtexbin,jobname))
+ -- purge 'm
+ end
+end
+
+function hacks.register(tag,short)
+ if not short or short == "" then
+ short = tag
+ end
+ if trace_bibtex then
+ report_tex("registering bibtex entry %a with shortcut %a",tag,short)
+ end
+ local top = #registered + 1
+ registered[top] = tag
+ ordered [tag] = top
+ shorts [tag] = short
+end
+
+function hacks.nofregistered()
+ return #registered
+end
+
+function hacks.reset(m)
+ mode, list, done = m, { }, { }
+end
+
+function hacks.add(str,listindex)
+ if not str or mode == 0 then
+ -- skip
+ elseif mode == 1 then
+ -- all locals but no duplicates
+ local sc = sections.currentid()
+ if done[str] ~= sc then
+ done[str], alldone[str] = sc, true
+ list[#list+1] = { str, listindex }
+ end
+ elseif mode == 2 then
+ -- all locals but no preceding
+ local sc = sections.currentid()
+ if not alldone[str] and done[str] ~= sc then
+ done[str], alldone[str] = sc, true
+ list[#list+1] = { str, listindex }
+ end
+ end
+end
+
+function hacks.flush(sortvariant)
+ local compare -- quite some checking for non-nil
+ if sortvariant == "" or sortvariant == v_cite or sortvariant == v_default then
+ -- order is cite order i.e. same as list
+ elseif sortvariant == v_short then
+ compare = function(a,b)
+ local aa, bb = a and a[1], b and b[1]
+ if aa and bb then
+ local oa, ob = shorts[aa], shorts[bb]
+ return oa and ob and oa < ob
+ end
+ return false
+ end
+ elseif sortvariant == v_reference then
+ compare = function(a,b)
+ local aa, bb = a and a[1], b and b[1]
+ if aa and bb then
+ return aa and bb and aa < bb
+ end
+ return false
+ end
+ else
+ compare = function(a,b)
+ local aa, bb = a and a[1], b and b[1]
+ if aa and bb then
+ local oa, ob = ordered[aa], ordered[bb]
+ return oa and ob and oa < ob
+ end
+ return false
+ end
+ end
+ if compare then
+ sort(list,compare)
+ end
+ for i=1,#list do
+ context.doprocessbibtexentry(list[i][1])
+ end
+end
+
+function hacks.filterall()
+ for i=1,#registered do
+ list[i] = { registered[i], i }
+ end
+end
+
+function hacks.registerplaced(str)
+ used[str] = true
+end
+
+function hacks.doifalreadyplaced(str)
+ commands.doifelse(used[str])
+end
+
+-- we ask for <n>:tag but when we can't find it we go back
+-- to look for previous definitions, and when not found again
+-- we look forward
+
+local function compare(a,b)
+ local aa, bb = a and a[3], b and b[3]
+ return aa and bb and aa < bb
+end
+
+function hacks.resolve(prefix,block,reference) -- maybe already feed it split
+ -- needs checking (the prefix in relation to components)
+ local subsets
+ local collected = references.collected
+ if prefix and prefix ~= "" then
+ subsets = { collected[prefix] or collected[""] }
+ else
+ local components = references.productdata.components
+ local subset = collected[""]
+ if subset then
+ subsets = { subset }
+ else
+ subsets = { }
+ end
+ for i=1,#components do
+ local subset = collected[components[i]]
+ if subset then
+ subsets[#subsets+1] = subset
+ end
+ end
+ end
+ if #subsets > 0 then
+ local result, nofresult, done = { }, 0, { }
+ block = tonumber(block)
+ for i=1,#subsets do
+ local subset = subsets[i]
+ for rest in gmatch(reference,"[^, ]+") do
+ local blk, tag, found = block, nil, nil
+ if block then
+ tag = blk .. ":" .. rest
+ found = subset[tag]
+ if not found then
+ for i=block-1,1,-1 do
+ tag = i .. ":" .. rest
+ found = subset[tag]
+ if found then
+ blk = i
+ break
+ end
+ end
+ end
+ end
+ if not found then
+ blk = "*"
+ tag = blk .. ":" .. rest
+ found = subset[tag]
+ end
+ if found then
+ local current = tonumber(found.entries and found.entries.text) -- tonumber needed
+ if current and not done[current] then
+ nofresult = nofresult + 1
+ result[nofresult] = { blk, rest, current }
+ done[current] = true
+ end
+ end
+ end
+ end
+ -- todo: ranges so the interface will change
+ sort(result,compare)
+ local first, last, firsti, lasti, firstr, lastr
+ local collected, nofcollected = { }, 0
+ for i=1,nofresult do
+ local r = result[i]
+ local current = r[3]
+ if not first then
+ first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r
+ elseif current == last + 1 then
+ last, lasti, lastr = current, i, r
+ else
+ if last > first + 1 then
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ else
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2] }
+ if last > first then
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { lastr[1], lastr[2] }
+ end
+ end
+ first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r
+ end
+ end
+ if first and last then
+ if last > first + 1 then
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ else
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2] }
+ if last > first then
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { lastr[1], lastr[2] }
+ end
+ end
+ end
+ if nofcollected > 0 then
+ for i=1,nofcollected do
+ local c = collected[i]
+ if c[3] then
+ context.dowithbibtexnumrefrange(#collected,i,prefix,c[1],c[2],c[3],c[4])
+ else
+-- print(#collected,i,prefix,c[1],c[2])
+ context.dowithbibtexnumref(#collected,i,prefix,c[1],c[2])
+ end
+ end
+ else
+ context.nobibtexnumref("error 1")
+ end
+ else
+ context.nobibtexnumref("error 2")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv
new file mode 100644
index 00000000000..4c9e83fdf9d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv
@@ -0,0 +1,1511 @@
+%D \module
+%D [ file=bibl-tra,
+%D version=2009.08.22,
+%D title=\CONTEXT\ Publication Module,
+%D subtitle=Publications,
+%D author=Taco Hoekwater,
+%D date=\currentdate,
+%D copyright={Public Domain}]
+%C
+%C Donated to the public domain.
+
+
+% % % % watch out ... bibl-tra-new.mkiv is work in progress % % % %
+
+% % % % mlbibtex also supports context and we can run that instead of bibtex % % % %
+
+%D This module has been adapted to \MKIV\ by Hans Hagen so if things go wrong,
+%D he is to blame. The changes concern references and lists but teh rendering
+%D itself is unchanged. Future versions might provide variants as we have plans
+%D for an upgrade.
+%D
+%D We use a still somewhat experimental extension to the list
+%D mechanism. Eventually the bibtex module will use the bibl loader
+%D and access the data by means of lpath expressions. In that case we
+%D don't need to process the bibliography but still need to track
+%D usage as done here.
+%D
+%D A bit ongoing: make more local macros prefixed with bib, i.e. the bib
+%D namespace is reserved.
+
+%D Todo: commandhandler
+
+\writestatus{loading}{ConTeXt Bibliography Support / BibTeX}
+
+\definefilesynonym[bib][obsolete]
+
+\registerctxluafile{bibl-tra}{1.001}
+
+%D The original was developed independantly by Taco Hoekwater while still working for Kluwer
+%D Academic publishers (it still used the dutch interface then). Development continued after
+%D he left Kluwer, and in Januari 2005, the then already internationalized file was merged
+%D with the core distribution by Hans Hagen. The current version is once again by Taco.
+%D
+%D More documentation and additional resources can be found on the contextgarden:
+%D \hyphenatedurl{http://wiki.contextgarden.net//Bibliography}.
+
+%D \subject{DONE (dd/mm/yyyy)}
+%D
+%D \startitemize
+%D \item add author definition (and associated system variable) (26/05/2005)
+%D \item add finalnamesep support for Oxford comma (17/09/2005)
+%D \item add \type{\insert...} for: doi, eprint, howpublished (19/09/2005)
+%D \item allow a defaulted \type{\setupcite} (19/11/2005)
+%D \item renamed citation type 'number' to 'serial' (19/11/2005)
+%D \item better definition of \type{\inverted...author} (19/11/2005)
+%D \item don't reset [numbercommand] in \type {\setuppublication} by default (20/11/2005)
+%D \item don't disable other \type {\setuppublication} keys if alternative is present (20/11/2005)
+%D \item drop \type{\sanitizeaccents} (20/11/2005)
+%D \item added \type{\nocite} and \type{\cite[none]} (21/11/2005)
+%D \item added headtext for it (23/11/2005)
+%D \item make \type{\cite[url]} and \type{\cite[doi]} interactive (23/11/2005)
+%D \item make right-aligned labels in the list work even when autohang=no
+%D \item use 'et al.' instead of 'et.al.'. Pointed out by Peter M\"unster (30/12/2005)
+%D \item added headtext for cz (31/12/2005)
+%D \item Keep whitespace after \type{\cite} with single argument (31/12/2005)
+%D \item Fix broken \type{\cite{}} support (31/12/2005)
+%D \item Use \type{\readfile} inside \type{\usepublications} instead of \type{\readsysfile} (12/01/2006)
+%D \item Use \type{\currentbibyear} and \type{\currentbibauthor} instead of \type{\YR} and \type{\AU} (05/02/2006)
+%D \item Fix compressed version of authoryear style (05/02/2006)
+%D \item Rename the clashing data fields \type{\url} and \type{\type} to \type{\biburl} and \type{\bibtype} (05/02/2006)
+%D \item Added two french bibl files from Renaud Aubin (06/02/2006)
+%D \item Five new bib class and eight extra bib fields, for IEEEtran (07/02/2006)
+%D \item French keyword translation, provided by Renaud (08/02/2006)
+%D \item fix underscores in undefined keys (22/02/2006)
+%D \item Destroy interactivity in labels of the publication list (13/03/2006)
+%D \item fix multi-cite list compression (11/4/2006)
+%D \item fix \type{\getcitedata} (11/4/2006)
+%D \item magic for chapter bibs (18-25/4/2006)
+%D \item language setting (25/4/2006)
+%D \item use \type{\hyphenatedurl} for \type{\inserturl} (25/4/2006)
+%D \item Add \type{\docitation} to \type{\nocite}(26/4/2006)
+%D \item patents can have numbers, added to bst files (26/4/2006)
+%D \item \type{\docitation} needs a \type{\iftrialtypesetting} (27/4/2006)
+%D \item \type{\filllocalpublist}'s loop is bound by definedness, not resolvedness (27/4/2006)
+%D \item \type{\setuppublications[monthconversion=]} added (15/5/2006)
+%D \item use \type{\undefinedreference} instead of bare question marks (15/5/2006)
+%D \item add grouping around \type{\placepublications} commands (16/5/2006)
+%D \item fix a bug in \type{\cite{<item>}} (17/5/2006)
+%D \item support \type{\cite[authornum]} (18/5/2006)
+%D \item make \type{\cite} unexpandable (20/6/2006)
+%D \item allow hyperlinks in author\&year combo's
+%D (cite list compression has to be off) (20/6/2006)
+%D \item fix duplicate labels for per-chapter style (20/6/2006)
+%D \item allow \type{\setupcite[interaction=(start|stop)]}
+%D \item fix the item number in the publication list with 'numbering=yes' (22/6/2006)
+%D \item make the default criterium for \type{\placepublications} be \type{previous} (23/6/2006)
+%D \item fix \type{\normalauthor} and \type{\normalshortauthor} spacing (29/6/2006)
+%D \item do not typeset empty arguments to \type{\typesetapublication} (29/6/2006)
+%D \item add \type{symbol=none} to \type{\setuplist} in unnumbered
+%D mode to prevent typesetting of bare numbers (29/6/2006)
+%D \item remove two incorrect spaces from bibl-num.tex (1/7/2006)
+%D \item reset font styles within \type{\cite}, so that font switches
+%D in \type{left} stay in effect (12/7/2006)
+%D \item guard added against loading bbl files multiple times (13/7/2006)
+%D \item fix \type{\cite[num]} with compression is on. (14/7/2006)
+%D \item test \type{\iflocation} before deciding to use the
+%D interactive version of cite (18/7/2006)
+%D \item support \type{\setupcite[authoretallimit=1]} (18/7/2006)
+%D \item support use of \type{\cite} within titles and captions by
+%D saveguarding the list item extraction and reference placement
+%D code (19/7/2006)
+%D \item support \type{\setuppublicationlist[title=\chapter]} (4/8/2006)
+%D \item use the expansion of \type{\headtext{pubs}} (4/8/2006)
+%D \item hook added for repeated authors in publication list
+%D \type{\setuppublicationlist[artauthorcommand=\mythreeargscommand]}
+%D (4/8/2006)
+%D \item make the bracketed arguments of \type{\artauthor}, \type{\author}
+%D and \type{\editor} (bbl commands) optional (4/8/2006)
+%D \item the constants \type{sorttype}, \type{compress} and
+%D \type{autohang} have moved to the core (8/8/2006)
+%D \item bibtex is now registered as a program to be run by texexec (8/8/2006)
+%D \item fix a bug in \type{\setupcite[authoretallimit=1]} (9/8/2006)
+%D \item fix a bug inside citations that prevented lastpubsep from ever being
+%D used due to a volatile \type{\commalistsize} (25/8/2006).
+%D \item added the possibility of \type{\placepublications[option=continue]}
+%D (6/9/2006)
+%D \item Mojca translated Master's Thesis to Masterarbeit (bibl-apa-de.tex)
+%D (12/9/2006)
+%D \item Added \type{\setuppublicationlist[maybeyear=off]} by request from
+%D Thomas Schmitz (15/9/2006)
+%D \item Removed some spurious spaces pointed out by willi egger (19/9/2006)
+%D \item Add configuration of bibtex executable name (4/11/2006)
+%D \item Fix numbering=short and numbering=bib (spotted by Matthias W\"achter) (4/11/2006)
+%D \item third attempt to get a correct release (5/11/2006)
+%D \item fix a few missing dots in bibl-num.tex (7/12/2006)
+%D \item Patch for DOI's by Tobias Burnus (17/4/2007)
+%D \item Patch for \type{\insertbiburl} and \type{\insertdoi} for Tobias Burnus (18/4/2007)
+%D \item Added a missing \type{\relax} in \type{\dospecialbibinsert},
+%D that made the space before the {\it et al.} text disappear. (18/4/2007)
+%D \item Attempt to fix percent signs in bbl files. As a side-effect,
+%D this prohibits comments in \tex{startpublication} blocks! (17/4/2008)
+%D \item Patch from Matthias W\"achter that allows arbitrary .bst
+%D files to be used with \tex{setupbibtex} (25/9/2008)
+%D \item Extended for the new multilingual setups for the Oct 2008 current of ConTeXt (23/10/2008)
+%D \item Multilingual setups needed another fix (27/10/2008)
+%D \item Two fixes for bibl-apa by Michael Green (27/10/2008)
+%D \item Catalan translation of 'References' (10/11/2008)
+%D \item 'chapter' -> 'chapitre' in bibl-apa-fr (27/11/2008)
+%D \item Run bibtex via os.execute in mkiv modee (01/12/2008)
+%D \item Small correction in bibl-apa's placement of volume
+%D information in articles (05/01/2009)
+%D \item Handle multi-author (more than two) cases in \type{\cite}
+%D (02/03/2009)
+%D \item Suppress a syntax error in \type{cont-xp} mode. The output is
+%D probably not right, though (02/03/2009)
+%D \item Added a \tex{loadmarkfile} at the end, and two new files
+%D from Hans. The \type{t-bib.mkiv} is needed to make the module
+%D work with the new structure code (17/04/2009)
+%D \item Added a patch to \type{t-bib.mkiv} from Hans to make the
+%D cross referencing between multiple citations an
+%D bibliographies work (27/04/2009)
+%D \item Remove a superfluous \type{\unprotect} in t-bib.mkiv (11/05/2009).
+%D \item Patch of incollection in bibl-ams.tex from Xan (08/06/2009).
+%D \item Patch of unpublished in bibl-ams.tex from Xan (22/07/2009).
+%D \item Modified \type{\bibdogetupsometextprefix} so it works for undefined
+%D language labels, from Hans (13/08/2009).
+%D \item Adapt referencing and list insertion to \MKIV. Update some code
+%D to the latest \CONTEXT. Change some names in order to avoid conflicts
+%D with existing core names (like \type {\insertpages}).
+%D \item All constants, variables, message etc.\ are now in the core.
+%D \item Added key: \type {method} (when \type {global}, previous shown entries are
+%D not shown again, when \type {local} they are repeated).
+%D \stopitemize
+%D
+%D \subject{WISHLIST}
+%D
+%D \startitemize
+%D \item link back from publication list to citation
+%D \item export \type {\citation{<cited item>}}
+%D \item support mlbibtex
+%D \item don't load the whole lot, but filter entries instead
+%D \item 9 vs 10, 19 vs 20 ... prevent extra runs when only subtle changes in wd of reference
+%D \stopitemize
+
+\unprotect
+
+\def\biblistname{pubs} % for compatibility
+
+\definelist
+ [pubs]
+
+\setuplist
+ [pubs]
+ [\c!state=\v!start,
+ \c!criterium=\@@pbcriterium,
+ \c!headnumber=\v!always, % needed as we provide our own and need to force
+ \c!width=]
+
+\installstructurelistprocessor{pubs:userdata}%
+ {\ctxlua{bibtex.hacks.add(structures.lists.uservalue("\currentlist",\currentlistindex,"bibref"),\currentlistindex)}}
+
+\ifdefined\bibtexblock \else \newcount\bibtexblock \fi \bibtexblock\plusone
+\ifdefined\bibtexcounter \else \newcount\bibtexcounter \fi
+
+%D \macros{bibdoif,bibdoifnot,bibdoifelse}
+%D
+%D Here are a few small helpers that are used a lot in all the typesetting commands
+%D (\type{\bibinsert...}) we will encounter later.
+
+\unexpanded\def\bibdoifelse#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\unexpanded\def\bibdoifnot#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\bibdoif#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D Unfortunately, \BIBTEX\ is not the best configurable program
+%D around. The names of the commands it parses as well as the \type{.aux}
+%D extension to the file name are both hardwired.
+%D
+%D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk!
+%D The good news is that it can be rather short. We'll just ask
+%D \BIBTEX\ to output the entire database(s) into the \type{bbl} file.
+%D
+%D The \type{\bibstyle} command controls how the \type{bbl} file will
+%D be sorted. The possibilities are:
+%D
+%D \startitemize[packed]
+%D \item by author (+year, title): cont-au.bst
+%D \item by title (+author, year): cont-ti.bst
+%D \item by short key as in abbrev.bst: cont-ab.bst
+%D \item not sorted at all: cont-no.bst
+%D \stopitemize
+
+\newtoks\everysetupbibtex
+
+\unexpanded\def\setupbibtex
+ {\dosingleempty\dosetupbibtex}
+
+\unexpanded\def\dosetupbibtex[#1]%
+ {\let\@@pbdatabase\empty
+ \getparameters[\??pb][#1]%
+ \the\everysetupbibtex}
+
+\unexpanded\def\installbibtexsorter#1#2%
+ {\setvalue{\??pb:\c!sort:#1}{#2}}
+
+\installbibtexsorter\v!no {no}
+\installbibtexsorter\v!author {au}
+\installbibtexsorter\v!title {ti}
+\installbibtexsorter\v!short {ab}
+\installbibtexsorter\empty {no}
+\installbibtexsorter\s!default{no}
+
+\def\thebibtexsorter{\executeifdefined{\??pb:\c!sort:\@@pbsort}\@@pbsort}
+
+\appendtoks
+ \ifx\@@pbdatabase\empty\else
+ \doifmode{*\v!first}{\ctxlua{bibtex.hacks.process { style="\thebibtexsorter", database="\@@pbdatabase" }}}%
+ \fi
+\to \everysetupbibtex
+
+\setupbibtex
+ [\c!sorttype=\v!cite,
+ \c!sort=no]
+
+%D \macros{iftypesetall,ifbibcitecompress}
+%D
+%D The module needs some new \type{\if} statements.
+
+\newtoks\everysetuppublications
+
+\unexpanded\def\setuppublications
+ {\dosingleargument\dosetuppublications}
+
+\unexpanded\def\dosetuppublications[#1]%
+ {\getparameters[\??pb][\c!alternative=,#1]%
+ \doifsomething\@@pbalternative
+ {\readsysfile{bibl-\@@pbalternative.tex}
+ {\showmessage\m!publications{6}{bibl-\@@pbalternative}}
+ {\showmessage\m!publications{1}{bibl-\@@pbalternative}}%
+ \let\@@pbalternative\empty}%
+ \let\setuppublicationlayout\normalsetuppublicationlayout % overloaded in bibl-num ... vadjust needs to be done with option
+ \getparameters[\??pb][#1]% as bibl-* can have set things back
+ \the\everysetuppublications
+ \ignorespaces}
+
+%D We can omit already shown references (\v!global) or use fresh
+%D lists each time (\v!local).
+
+\setnewconstant\bibtexoncemode\plusone % 0=disable, 1=local, 2=global
+
+\appendtoks
+ \doifelse\@@pbmethod\v!local
+ {\bibtexoncemode\plusone}%
+ {\bibtexoncemode\plustwo}%
+\to \everysetuppublications
+
+%D Cite lists are compressed, if possible. This is set later on.
+
+\newif\ifbibcitecompress\bibcitecompresstrue
+
+\def\@@pbinumbercommand{\executeifdefined{\??pb:\c!numbercommand:\@@pbnumbering}\firstofoneargument}
+
+\setvalue{\??pb:\c!numbercommand:\v!yes }#1{#1}%
+\setvalue{\??pb:\c!numbercommand:\v!no }#1{}
+\setvalue{\??pb:\c!numbercommand:\v!short}#1{\bibgetvars\currentpublicationkey}
+\setvalue{\??pb:\c!numbercommand:\v!bib }#1{\bibgetvarn\currentpublicationkey}
+
+% to be tested
+%
+% \setvalue{\??pb:\c!numbercommand:\v!short}{\bibgetvars\currentpublicationkey\firstofoneargument}
+% \setvalue{\??pb:\c!numbercommand:\v!bib }{\bibgetvarn\currentpublicationkey\firstofoneargument}
+
+\appendtoks
+ \processaction
+ [\@@pbrefcommand]
+ [\s!default=>\edef\@@citedefault{\@@pbrefcommand},
+ \s!unknown=>\edef\@@citedefault{\@@pbrefcommand}]%
+\to \everysetuppublications
+
+\unexpanded\def\bibleftnumber#1{#1\hfill~}
+
+%D \macros{usepublications}
+%D
+%D After discussing it with Thomas Schmitz it became clear that using external
+%D references makes no sense as one needs to refer to it in special ways and
+%D because similar numbers can be confusing. So, for the moment this is not
+%D supported in \MKIV. (So no: see reference [3-5,9] in "some other document")
+
+\unexpanded\def\usepublications[#1]%
+ {\processcommalist[#1]\dousepublications}
+
+\unexpanded\def\dousepublications#1%
+ {\doonlyonce{#1.\f!bibextension}{\dodousepublications{#1}}}
+
+\unexpanded\def\dodousepublications#1% brr, this par stuff
+ {\let\@@savedpar\par
+ \let\par\ignorespaces
+ \ifhmode\kern\zeropoint\fi
+ \pushcatcodetable
+ \setcatcodetable\ctxcatcodes
+ \readfile{#1.\f!bibextension}
+ {\showmessage\m!publications{4}{#1.\f!bibextension}}
+ {\showmessage\m!publications{2}{#1.\f!bibextension}}%
+ \popcatcodetable
+ \ifhmode\removeunwantedspaces\fi
+ \let\par\@@savedpar}
+
+%D \macros{setuppublicationlist}
+%D
+%D This will be the first command in (\BIBTEX-generated) \type{bbl}
+%D files. `samplesize' is a sample value (in case of \BIBTEX-generated
+%D files, this will be the longest `short' key). `totalnumber'
+%D is the total number of entries that will follow in this
+%D file.
+%D
+%D Both values are only needed for the label calculation
+%D if `autohang' is `true', so by default the command is
+%D not even needed, and therefore I saw no need to give
+%D it it's own system variable and it just re-uses \type{pb}.
+
+\def\publicationlistparameter#1{\csname\??pv:l:#1\endcsname}
+
+\unexpanded\def\setuppublicationlist
+ {\dosingleempty\dosetuppublicationlist}
+
+\unexpanded\def\dosetuppublicationlist[#1]%
+ {\getparameters[\??pv:l:][#1]%
+ \setuplist[pubs][\c!samplesize={AA99},\c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1,\c!command=]}
+
+\unexpanded\def\setuppublicationlayout[#1]#2%
+ {\setvalue{\??pv:l:#1}{#2}}
+
+\let\normalsetuppublicationlayout\setuppublicationlayout
+
+\setuppublicationlist
+ [\c!title=,
+ \c!command=\dospecialbibinsert,
+ \c!maybeyear=\v!on]
+
+%D \macros{bibalternative}
+%D
+%D A nice little shorthand that will be used so we don't have to
+%D key in the weird \type{\@@pv} parameter names all the time.
+
+\def\bibalternative#1%
+ {\csname\??pv\@@currentalternative#1\endcsname}
+
+%D \macros{simplebibdef,bibcommandlist}
+%D
+%D \type{\simplebibdef} defines \type{bib@#1}, which in turn will
+%D use one argument that is stored in \type{@@pb@#1}.
+%D
+%D \type{\simplebibdef} also defines \type{bibinsert#1}, which can be
+%D used in the argument of \type{\setuppublicationlayout} to fetch
+%D one of the \type{@@pb@} data entries. \type{bibinsert#1} then has
+%D three arguments: \type{#1} are commands to be executed before the
+%D data, \type{#2} are commands to be executed after the data, and
+%D \type{#3} are commands to be executed if the data is not found.
+%D
+%D \type{\bibcommandlist} is the list of commands that is affected
+%D by this approach. Later on, it will be used to do a series
+%D of assignments from \type{#1} to \type{bib@#1}: e.g
+%D \type{\title} becomes \type{\bib@title} when used within
+%D a publication.
+
+\newtoks\initializebibdefinitions % we need to prevent clashes
+
+\unexpanded\def\simplebibdef#1% hh: funny expansion ?
+ {\expandafter\def\csname bib@#1\endcsname##1%
+ {\setvalue{\??pb @#1}{##1}\ignorespaces}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1\expandafter\endcsname\csname bibinsert#1\endcsname
+ \to \initializebibdefinitions
+ \expandafter\unexpanded\expandafter\def\csname bibinsert#1\endcsname##1##2##3%
+ {\expandafter\bibdoifelse\expandafter{\csname\??pb @#1\endcsname}{##1\csname\??pb @#1\endcsname##2}{##3}}}
+
+\def\bibcommandlist
+ {abstract, annotate, arttitle, assignee, bibnumber, bibtype, biburl, chapter, city,
+ comment, country, day, dayfiled, doi, edition, eprint, howpublished, isbn, issn,
+ issue, journal, keyword, keywords, lastchecked, month, monthfiled, names, nationality,
+ note, notes, organization, pages, pubname, pubyear, revision, series, size, thekey,
+ title, volume, yearfiled}
+
+\processcommacommand[\bibcommandlist]\simplebibdef
+
+\unexpanded\def\bibinsertdoi#1#2#3% let's see how this fails
+ {\bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}}
+
+\unexpanded\def\bibinsertbiburl#1#2#3% let's see how this fails
+ {\bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}}
+
+\unexpanded\def\bibinsertmonth#1#2#3%
+ {\bibdoifelse\@@pb@month
+ {#1\doifelsenumber\@@pb@month
+ {\doifelseconversiondefined\@@pbmonthconversion
+ {\convertnumber\@@pbmonthconversion\@@pb@month}{\@@pb@month}}%
+ {\@@pb@month}#2}%
+ {#3}}
+
+\appendtoks
+ \let\inserturl \bibinsertbiburl % for backward compat.
+ \let\inserttype\bibinsertbibtype % for backward compat.
+\to\initializebibdefinitions
+
+\unexpanded\def\newbibfield[#1]%
+ {\simplebibdef{#1}%
+ \edef\bibcommandlist{\bibcommandlist,#1}}
+
+%D \macros{complexbibdef,specialbibinsert}
+%D
+%D The commands \type{\artauthor}, \type{\author} and
+%D \type{\editor} are more complex than the other commands.
+%D Their argument lists have this form:
+%D
+%D \type{\author[junior]{firstnames}[inits]{von}{surname}}
+%D
+%D (bracketed stuff is optional)
+%D
+%D And not only that, but there also might be more than one of each of
+%D these commands. This is why a special command is needed to insert
+%D them, as well as one extra counter for each command.
+
+% todo: instead of \getvalue{bla@num} in specs we should do
+% \bibentrynum{bla} so that we can create a better namespace
+
+%D All of these \type{\expandafter}'s and \type{\csnames} make this code
+%D look far more complex than it really is. For example, the argument
+%D \type{author} defines the macro \type{\bib@author} to do two
+%D things: increment the counter \type{\author@num} (let's say to 2)
+%D and next store it's arguments in the macro \type{\@@pb@author2}.
+%D And it defines \type{\bibinsertauthors} to expand into
+%D \starttyping
+%D \specialbibinsert{author}{\author@num}{<before>}{<after>}{<not>}
+%D \stoptyping
+
+\unexpanded\def\docomplexbibdef#1%
+ {\dodoubleempty\dodocomplexbibdef[#1]}
+
+\unexpanded\def\dodocomplexbibdef[#1][#2]#3%
+ {\doquadrupleempty\dododocomplexbibdef[#1][#2][#3]}
+
+\unexpanded\def\dododocomplexbibdef[#1][#2][#3][#4]#5#6%
+ {\expandafter\increment\csname#1@num\endcsname % todo: bib in name
+ \setevalue{\??pb @#1\csname#1@num\endcsname}{{#3}{#5}{#6}{#4}{#2}}\ignorespaces}
+
+\unexpanded\def\complexbibdef#1%
+ {\expandafter\newcounter\csname #1@num\endcsname
+ \expandafter\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1s\expandafter\endcsname\csname bibinsert#1s\endcsname
+ \to \initializebibdefinitions
+ \expandafter\def\csname bibinsert#1s\endcsname##1##2##3{\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
+
+\processcommalist[author,artauthor,editor]\complexbibdef
+
+%D Another level of indirection is needed to control the
+%D typesetting of all of these arguments.
+
+\newcount\etallimitcounter
+\newcount\etaldisplaycounter
+\newcount\todocounter
+
+\unexpanded\def\specialbibinsert#1#2#3#4#5%
+ {\bgroup
+ \ifnum#2>\zerocount
+ \etallimitcounter =0\bibalternative{#1etallimit}\relax
+ \etaldisplaycounter=0\bibalternative{#1etaldisplay}\relax
+ \ifnum #2>\etallimitcounter
+ \todocounter\etaldisplaycounter
+ % just in case ...
+ \ifnum\todocounter>\etallimitcounter
+ \todocounter\etallimitcounter
+ \fi
+ \else
+ \todocounter#2\relax
+ \fi
+ \ifnum\todocounter>\zerocount
+ % find the current author list
+ \let\templist\empty
+ \dorecurse{#2}
+ {\scratchtoks\doubleexpandafter{\csname\??pb @#1\recurselevel\endcsname}%
+ \edef\templist{\ifx\templist\empty\else\templist,\fi\the\scratchtoks}}%
+ #3\publicationlistparameter\c!command{#1}{\todocounter}{\templist}#4\relax
+ \else
+ #5%
+ \fi
+ \else
+ #5%
+ \fi
+ \egroup}
+
+%D This macro does the hard work of inserting a list of people in the
+%D output, with proper regard of all the inbetween strings that can
+%D arise depending on length of the list of people.
+
+%D \#1 = type
+%D \#2 = number of items to be typeset
+%D \#3 = commacommand containing authors
+
+\unexpanded\def\doprocessauthoritem#1#2#3%
+ {\advance\scratchcounter\plusone
+ \ifnum\numexpr\scratchcounter-\plusone\relax<#2\relax
+ \publicationlistparameter{#1}#3%
+ \ifnum\scratchcounter=#2\relax
+ \ifnum\etallimitcounter<\commalistsize\relax
+ \bibalternative{#1etaltext}%
+ \fi
+ \else\ifnum\numexpr\scratchcounter+\plusone\relax=#2\relax
+ \ifnum\commalistsize>\plustwo
+ \bibalternative\c!finalnamesep
+ \else
+ \bibalternative\c!lastnamesep
+ \fi
+ \else
+ \bibalternative\c!namesep
+ \fi\fi
+ \fi}
+
+\unexpanded\def\dospecialbibinsert#1#2#3%
+ {\getcommacommandsize[#3]%
+ \scratchcounter\zerocount
+ \processcommacommand[#3]{\doprocessauthoritem{#1}{#2}}}
+
+%D \macros{invertedauthor,normalauthor,invertedshortauthor,normalshortauthor}
+%D
+%D Just some commands that can be used in \type{\setuppublicationparameters}
+%D If you want to write an extension to the styles, you might
+%D as well define some of these commands yourself.
+%D
+%D The argument list has been reordered here, and the meanings
+%D are:
+%D
+%D \startlines
+%D \type{#1} firstnames
+%D \type{#2} von
+%D \type{#3} surname
+%D \type{#4} inits
+%D \type{#5} junior
+%D \stoplines
+
+\unexpanded\def\normalauthor#1#2#3#4#5%
+ {\bibdoif{#1}{#1\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\unexpanded\def\normalshortauthor#1#2#3#4#5%
+ {\bibdoif{#4}{#4\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\unexpanded\def\invertedauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep#5}%
+ \bibdoif{#1}{\bibalternative\c!surnamesep#1\unskip}}
+
+\unexpanded\def\invertedshortauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep#5}%
+ \bibdoif{#4}{\bibalternative\c!surnamesep#4\unskip}}
+
+%D \macros{clearbibitem,clearbibitemtwo,bibitemdefs}
+%D
+%D These are used in \type{\typesetapublication} to do
+%D initializations and cleanups.
+
+\unexpanded\def\clearbibitem#1{\setvalue{\??pb @#1}{}}%
+
+\unexpanded\def\clearbibitemtwo#1% is this reset really needed? after all we reset the counter and we are local
+ {%\dofastrecurse\plusone{\csname#1@num\endcsname}\plusone{\expandafter\let\csname\??pb @#1\recurselevel\undefined}%
+ \letvalue{#1@num}\!!zerocount}
+
+\unexpanded\def\bibitemdefs#1%
+ {\expandafter\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname}
+
+\unexpanded\def\presetbibvariables % make a fast resetter (toks)
+ {\processcommacommand[\bibcommandlist,crossref]\clearbibitem
+ \processcommalist [artauthor,author,editor]\clearbibitemtwo
+ \processcommacommand[\bibcommandlist]\bibitemdefs
+ \processcommalist [artauthor,author,editor,crossref]\bibitemdefs}
+
+%D \macros{startpublication}
+%D
+%D We are coming to the end of this module, to the macros that
+%D do typesetting and read the \type{bbl} file.
+
+%D Just a \type{\dosingleempty} is the most friendly
+%D of doing this: there need not even be an argument
+%D to \type{\startpublication}. Of course, then there
+%D is no key either, and it had better be an
+%D article (otherwise the layout will be all screwed up).
+%D
+%D Only specifying the key in the argument is also
+%D legal. In storing this stuff into macros, some trickery with
+%D token registers is needed to fix the expansion problems. Even so,
+%D this appears to not always be 100\% safe, so people are
+%D urgently advised to use \ETEX\ instead of traditional \TEX.
+%D
+%D In \ETEX, all expansion problems are conveniently solved by
+%D the primitive \type{\protected}. To put that another way:
+%D
+%D It's not a bug in this module if it does not appear in \ETEX!
+%D
+%D Now prohibits comments, so % can be used for urls
+
+\unexpanded\def\startpublication
+ {\dosingleempty\dostartpublication}
+
+\let\stoppublication\relax
+
+% this is rather memory hungry; some day i will rewrite this so that
+% we use the database instead
+
+%D \macros{doifbibreferencefoundelse}
+%D
+%D Some macros to fetch the information provided by
+%D \type{\startpublication}.
+
+% we can consider a faster variant in the bbl file; we can also consider
+% storing the keys in lua (and then do more in lua) and use calls to
+% fetch the variables
+
+% hm, we can store at the lua end ...
+
+\unexpanded\def\dostartpublication[#1]%
+ {\begingroup
+ \doifelseassignment{#1}%
+ {\getparameters[\??pb][k=\s!unknown,t=article,n=,s=,a=,y=,o=,u=,#1]}%
+ {\getparameters[\??pb][k=#1,t=article,n=,s=,a=,y=,o=,u=]}%
+ \ctxlua{bibtex.hacks.register(\!!bs\@@pbk\!!es,\!!bs\@@pbs\!!es)}%
+ \catcode\commentasciicode\othercatcode
+ \dodostartpublication}
+
+\unexpanded\def\dodostartpublication#1\stoppublication
+ {\setxvalue{pbd:\@@pbk}##1{\noexpand\ifcase##1\noexpand\or
+ \@@pbk\noexpand\or
+ \@@pba\noexpand\or
+ \@@pby\noexpand\or
+ \@@pbs\noexpand\or
+ \@@pbn\noexpand\or
+ \@@pbt\noexpand\or
+ \@@pbo\noexpand\or
+ \@@pbu\noexpand\or
+ \normalunexpanded{#1}\noexpand\fi}%
+ \endgroup
+ \ignorespaces}
+
+\def\bibgetvark#1{\csname pbd:#1\endcsname\plusone }
+\def\bibgetvara#1{\csname pbd:#1\endcsname\plustwo }
+\def\bibgetvary#1{\csname pbd:#1\endcsname\plusthree}
+\def\bibgetvars#1{\csname pbd:#1\endcsname\plusfour }
+\def\bibgetvarn#1{\csname pbd:#1\endcsname\plusfive }
+\def\bibgetvart#1{\csname pbd:#1\endcsname\plussix }
+\def\bibgetvaro#1{\csname pbd:#1\endcsname\plusseven}
+\def\bibgetvaru#1{\csname pbd:#1\endcsname\pluseight}
+\def\bibgetvard#1{\csname pbd:#1\endcsname\plusnine }
+
+\unexpanded\def\doifelsebibreferencefound#1%
+ {\preloadbiblist
+ \doifelsedefined{pbd:#1}
+ \firstoftwoarguments
+ {\showmessage\m!publications{5}{#1,\the\inputlineno}\secondoftwoarguments}}
+
+\let\doifbibreferencefoundelse\doifelsebibreferencefound
+
+%D \macros{bib@crossref}
+%D
+%D \type{\crossref} is used in database files to point to another
+%D entry. Because of this special situation, it has to be defined
+%D separately. Since this command will not be seen until at
+%D \type{\placepublications}, it may force extra runs. The same is
+%D true for \type{\cite} commands inside of publications.
+
+% used in bib self
+
+\unexpanded\def\bib@crossref#1% called via \csname \endcsname
+ {\setvalue{\??pb @crossref}{#1}\ignorespaces}
+
+\unexpanded\def\bibinsertcrossref#1#2#3%
+ {\bibdoifelse\@@pb@crossref{#1\cite[\@@pb@crossref]#2}{#3}}
+
+\let\insertcrossref\gobblethreearguments
+
+\appendtoks\let\insertcrossref\bibinsertcrossref\to\initializebibdefinitions
+
+%D The next macro is needed because the number command of the
+%D publist sometimes needs to fetch something from the current
+%D item (like the 'short' key). For this, the ID of the current
+%D item is passed in the implict parameter \type{\currentpublicationkey}
+
+\unexpanded\def\doprocessbibtexentry#1{\typesetapublication{#1}}
+
+\unexpanded\def\typesetpubslist
+ {\begingroup
+ \startpacked[\v!blank]%
+ \preloadbiblist
+ % \the\initializebibdefinitions % COMMENTED
+ \edef\currentlist{pubs}%
+ \ctxlua{bibtex.hacks.reset(\number\bibtexoncemode)}%
+ \doifelse{\listparameter\c!criterium}\v!all
+ {\showmessage\m!publications{7}{}%
+ \ctxlua{bibtex.hacks.filterall()}}
+ {\doif{\listparameter\c!criterium}\v!cite
+ {\setuplist[pubs][\c!criterium=\v!here]}%
+ \strc_lists_place_current
+ {pubs}%
+ {\listparameter\c!criterium}%
+ {}%
+ {\listparameter\c!extras}%
+ {\listparameter\c!order}}%
+ \ctxlua{bibtex.hacks.flush("\@@pbsorttype")}%
+ \stoppacked
+ \endgroup}
+
+\newif\ifinpublist
+
+\unexpanded\def\initializepubslist
+ {\def\currentlist{pubs}%
+ \edef\@@pbnumbering{\@@pbnumbering}%
+ \doifelse\@@pbautohang\v!yes
+ {\ifx\@@pbnumbering\v!short
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\listparameter\c!samplesize}}%
+ \else
+ \doifelse{\listparameter\c!criterium}\v!all
+ {\setbox\scratchbox\hbox{\@@pbnumbercommand{\ctxlua{tex.write{bibtex.hacks.nofregistered()}}}}}
+ {\determinelistcharacteristics[pubs]%
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\structurelistsize}}}%
+ \fi
+ \edef\publistnumberbox{\hbox to \the\wd\scratchbox}%
+ \expanded{\setuplist[pubs][\c!width=\the\wd\scratchbox,\c!distance=\zeropoint]}%
+ \ifx\@@pbnumbering\v!short
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvars\currentpublicationkey}}}%
+ \else\ifx\@@pbnumbering\v!bib
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}%
+ \else
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}%
+ \fi\fi}
+ {\doifelsenothing{\listparameter\c!width}
+ {\let \publistnumberbox \hbox}
+ {\edef\publistnumberbox{\hbox to \listparameter\c!width}}%
+ \ifx\@@pbnumbering\v!short
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvars\currentpublicationkey}}}%
+ \else\ifx\@@pbnumbering\v!bib
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}%
+ \else
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}%
+ \fi\fi}%
+ \ifx\@@pbnumbering\v!no
+ \setuplist[pubs][\c!numbercommand=,\c!symbol=\v!none,\c!textcommand=\outdented]%
+ \else
+ \setuplist[pubs][\c!numbercommand=\@@pblimitednumber]%
+ \fi
+ \doifelse{\publicationlistparameter\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}%
+ \forgetall}
+
+\unexpanded\def\outdented#1% move to supp-box ?
+ {\hskip-\hangindent#1\relax}
+
+%D The full list of publications
+
+\unexpanded\def\completepublications
+ {\dosingleempty\docompletepublications}
+
+\unexpanded\def\docompletepublications[#1]%
+ {\begingroup
+ \setuplist[pubs][#1]%
+ \edef\currentbibtexsessiontitle{\publicationlistparameter\c!title}%
+ \ifx\currentbibtexsessiontitle\empty
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=pubs,\c!title={\headtext{pubs}}]}%
+ \else
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=pubs,\c!title={\currentbibtexsessiontitle}]}%
+ \fi
+ \dodoplacepublications
+ \stopnamedsection
+ \endgroup}
+
+%D And the portion with the entries only.
+
+\def\bibrefprefix{\number\bibtexblock:}
+
+\unexpanded\def\placepublications
+ {\dosingleempty\doplacepublications}
+
+\unexpanded\def\doplacepublications[#1]%
+ {\begingroup
+ \setuplist[pubs][#1]%
+ \dodoplacepublications
+ \endgroup}
+
+\unexpanded\def\dodoplacepublications
+ {\determinelistcharacteristics[pubs]%
+ \initializepubslist
+ \doifnot{\namedlistparameter{pubs}\c!option}\v!continue
+ {\global\bibtexcounter\zerocount}%
+ \inpublisttrue
+ \typesetpubslist
+ \inpublistfalse
+ \global\advance\bibtexblock\plusone}
+
+%D \subsubject{What's in a publication}
+%D
+%D Watch out: here all means all publications in database, so use
+%D text when you want text only.
+
+\unexpanded\def\typesetapublication#1%
+ {\doifsomething{#1}
+ {\doifelse{\namedlistparameter{pubs}\c!criterium}\v!all
+ {\doplacepublicationindeed{#1}}%
+ {\ctxlua{bibtex.hacks.doifalreadyplaced("#1")}
+ {}
+ {\doplacepublicationindeed{#1}}}%
+ }}
+
+% for the moment we don't access the data directly but we will do that
+% later when we get away from storing the data and only deal with
+% references
+
+% we'll define proper handlers later
+
+\unexpanded\def\doplacepublicationindeed#1%
+ {\doifelsebibreferencefound{#1}
+ {\global\advance\bibtexcounter\plusone
+ \def\currentpublicationkey{#1}%
+ \ctxlua{bibtex.hacks.registerplaced("#1")}%
+ \def \currentlist {pubs}%
+ \edef\currentlistentrynumber {\number\bibtexcounter}%
+ \let \currentlistentrytitle \bibtexpubtext
+ \let \currentlistentrypagenumber\empty
+ \strc_lists_apply_renderingsetup}
+ {}} % invalid
+
+\unexpanded\def\bibtexpubtext
+ {\expanded{\reference[\bibrefprefix\currentpublicationkey]{\number\bibtexcounter}}%
+ \strut\dotypesetapublication\currentpublicationkey\strut}
+
+\unexpanded\def\dotypesetapublication#1%
+ {\bgroup
+ \the\initializebibdefinitions % NEW
+ \def\@@currentalternative{:l:}%
+ \presetbibvariables
+ \let\biblanguage\empty
+ \ignorespaces
+ \bibgetvard{#1}%
+ \removeunwantedspaces
+ \ignorespaces
+ \bibalternative{\bibgetvart{#1}}%
+ \removeunwantedspaces
+ \egroup}
+
+%D An few afterthoughts:
+
+\let\maybeyear\gobbleoneargument
+\let\noopsort \gobbleoneargument
+
+%D This is the result of bibtex's `language' field.
+
+\unexpanded\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}}
+
+\unexpanded\def\lang#1%
+ {\edef\biblanguage{#1}%
+ \ifcsname\??pb\s!language#1\endcsname
+ \language[\getvalue{\??pb\s!language#1}]%
+ \fi
+ \ignorespaces}
+
+%D \subject{Citations}
+
+%D \macros{cite,bibref}
+%D
+%D The indirection with \type{\dobibref} allows \LATEX\ style
+%D \type{\cite} commands with a braced argument (these might appear
+%D in included data from the \type{.bib} file).
+
+\unexpanded\def\cite
+ {\strictdoifelsenextoptional\dodocite\dobibref}
+
+\unexpanded\def\dobibref#1%
+ {\docite[#1][]}
+
+\unexpanded\def\dodocite[#1]%
+ {\strictdoifelsenextoptional{\docite[#1]}{\docite[#1][]}}
+
+\unexpanded\def\docite[#1][#2]%
+ {\begingroup
+ \doifelsenothing{#2}\secondargumentfalse\secondargumenttrue
+ \ifsecondargument
+ \dowhatevercite{#1}{#2}%
+ \else
+ \donumberedcite{#1}%
+ \fi
+ \endgroup}
+
+\unexpanded\def\dowhatevercite#1#2%
+ {\processcommalist[#2]\docitation
+ \setupinteraction[\c!style=]%
+ \doifelseassignment
+ {#1}%
+ {\getparameters[LO][\c!alternative=,\c!extras=,#1]%
+ \edef\@@currentalternative{\LOalternative}%
+ \ifx\@@currentalternative\empty
+ \edef\@@currentalternative{\@@citedefault}%
+ \fi
+ \ifx\LOextras\empty
+ \setupcite[\@@currentalternative][#1]%
+ \else
+ \expandafter\ifx\csname \??pv \@@currentalternative\c!right\endcsname\relax
+ % avoids tail recursion
+ \expandafter\let\csname \??pv \@@currentalternative\c!right\endcsname\empty
+ \fi
+ \expandafter\ifx\csname LOright\endcsname \relax
+ \edef\LOextras{{\LOextras\bibalternative\c!right}}%
+ \else
+ \edef\LOextras{{\LOextras\LOright}}%
+ \fi
+ \expanded{\setupcite[\@@currentalternative][#1,\c!right=\LOextras]}%
+ \fi}%
+ {\def\@@currentalternative{#1}}%
+ \doifelsevalue{@@pv\@@currentalternative\c!compress}\v!no\bibcitecompressfalse\bibcitecompresstrue
+ \getvalue{bib\@@currentalternative ref}[#2]}
+
+\unexpanded\def\donumberedcite#1%
+ {\processcommalist[#1]\docitation
+ \setupinteraction[\c!style=]%
+ \edef\@@currentalternative{\@@citedefault}%
+ \doifelsevalue{@@pv\@@currentalternative\c!compress}\v!no\bibcitecompressfalse\bibcitecompresstrue
+ \getvalue{bib\@@citedefault ref}[#1]}
+
+%D \macros{nocite}
+
+\unexpanded\def\nocite[#1]%
+ {\processcommalist[#1]\docitation}
+
+%D \macros{setupcite}
+
+\unexpanded\def\setupcite{\dodoubleempty\dosetupcite}
+
+\unexpanded\def\dosetupcite[#1][#2]%
+ {\ifsecondargument
+ \def\dodosetupcite##1{\getparameters[\??pv##1][#2]}%
+ \processcommalist[#1]\dodosetupcite
+ \else % default case
+ \getparameters[\??pv\@@citedefault][#1]%
+ \fi}
+
+%D Low-level stuff
+
+\unexpanded\def\getcitedata#1[#2]#3[#4]#5to#6%
+ {\bgroup
+ \dofetchapublication{#4}%
+ \doifelsedefined{\??pb @bib#2}%
+ {\xdef#6{\getvalue{\??pb @bib#2}}}%
+ {\xdef#6{\getvalue{\??pb @#2}}}%
+ \egroup}
+
+\unexpanded\def\dofetchapublication#1%
+ {\def\currentpublicationkey{#1}%
+ \presetbibvariables
+ \ignorespaces\bibgetvard{#1}}
+
+\unexpanded\def\docitation#1%
+ {\iftrialtypesetting \else
+ \expanded{\writedatatolist[pubs][bibref=#1]}%
+ \fi}
+
+\let\addthisref\gobbleoneargument % keep this for compatibility
+
+%D \macros{ixbibauthoryear,thebibauthors,thebibyears}
+%D
+%D If compression of \type{\cite}'s argument expansion is on,
+%D the macros that deal with authors and years call this internal
+%D command to do the actual typesetting.
+%D
+%D Two entries with same author but with different years may
+%D be condensed into ``Author (year1,year2)''. This is about the
+%D only optimization that makes sense for the (author,year)
+%D style of citations (years within one author have to be unique
+%D anyway so no need to test for that, and ``Author1, Author2 (year)''
+%D creates more confusion than it does good).
+%D
+%D In the code below,
+%D the macro \type{\thebibauthors} holds the names of the alternative
+%D author info fields for the current list. This is a commalist,
+%D and \type{\thebibyears} holds the (collection of) year(s) that go with
+%D this author (possibly as a nested commalist).
+%D
+%D There had better be an author for all cases, but there
+%D does not have to be year info always. \type{\thebibyears} is
+%D pre-initialized because this makes the insertion macros simpler.
+%D
+%D In normal \TEX, of course there are expansion problems again.
+
+%D Delegate this to \LUA.
+
+% \let\ixlastcommand \relax
+% \let\ixsecondcomman \relax
+% \let\ixfirstcommand \relax
+% \let\thebibauthors \empty
+% \let\thebibyears \empty
+% \let\authorcount \!!zerocount
+
+\let\currentbibauthor\empty
+
+\unexpanded\def\ixbibauthoryear#1#2#3#4%
+ {\bgroup
+ \gdef\ixlastcommand {#4}%
+ \gdef\ixsecondcommand{#3}%
+ \gdef\ixfirstcommand {#2}%
+ \glet\thebibauthors \empty
+ \glet\thebibyears \empty
+ \getcommalistsize[#1]%
+ \ifbibcitecompress
+ \dorecurse\commalistsize{\xdef\thebibyears{\thebibyears,}}%
+ \processcommalist[#1]\docompressbibauthoryear
+ \else
+ \processcommalist[#1]\donormalbibauthoryear
+ \fi
+ \egroup
+ \dobibauthoryear}
+
+%D \macros{dodobibauthoryear}
+%D
+%D This macro only has to make sure that the lists
+%D \type{\thebibauthors} and \type{\thebibyears} are printed.
+
+\unexpanded\def\dobibauthoryear
+ {\scratchcounter\zerocount
+ \getcommacommandsize[\thebibauthors]%
+ \edef\authorcount{\commalistsize}%
+ \expandafter\processcommalist\expandafter[\thebibauthors]\dodobibauthoryear}
+
+\unexpanded\def\dodobibauthoryear#1%
+ {\advance\scratchcounter\plusone
+ \edef\wantednumber{\the\scratchcounter}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \expandafter\def\expandafter\currentbibyear\expandafter{\commalistelement}%
+ \setcurrentbibauthor{#1}%
+ \ifnum\scratchcounter=\plusone
+ \ixfirstcommand
+ \else\ifnum \scratchcounter=\authorcount\relax
+ \ixlastcommand
+ \else
+ \ixsecondcommand
+ \fi\fi}
+
+\unexpanded\def\setcurrentbibauthor#1% sensitive for empty entries but I don't want to touch this
+ {\getcommacommandsize[#1]%
+ \ifcase\commalistsize
+ % anonymous?
+ \let\currentbibauthor\empty
+ \or
+ \def\currentbibauthor{#1}%
+ \or
+ \expanded{\docurrentbibauthor#1}%
+ \else
+ \handlemultiplebibauthors{\commalistsize}{#1}%
+ \fi}
+
+\newcount\citescratchcounter
+
+\unexpanded\def\handlemultiplebibauthors#1#2%
+ {\citescratchcounter\zerocount
+ \let\currentbibauthor\empty
+ \unexpanded\def\bibprocessauthoritem##1%
+ {\advance\citescratchcounter\plusone
+ \ifnum \citescratchcounter=#1\relax
+ \edef\currentbibauthor{\currentbibauthor##1}%
+ \else\ifnum\numexpr\citescratchcounter+\plusone\relax=#1\relax
+ \edef\currentbibauthor{\currentbibauthor##1\bibalternative{andtext}}%
+ \else
+ \edef\currentbibauthor{\currentbibauthor##1\bibalternative{namesep}}%
+ \fi\fi}%
+ \processcommalist[#2]\bibprocessauthoritem}
+
+\setupcite
+ [author,authoryear,authoryears]
+ [\c!namesep={, }]
+
+%D This discovery of authoretallimit is not the best one,
+%D but it will do for now.
+
+\unexpanded\def\docurrentbibauthor#1,#2%
+ {\doifelseempty{#2}
+ {\def\currentbibauthor{#1\bibalternative{otherstext}}}
+ {\expandafter\ifx\csname\??pv\@@currentalternative authoretallimit\endcsname\relax
+ \edef\currentbibauthor{#1\bibalternative{andtext}#2}%
+ \else
+ \edef\currentbibauthor{#1%
+ \ifcase0\bibalternative{authoretallimit}\relax\or
+ \bibalternative{otherstext}\else\bibalternative{andtext}#2\fi}%
+ \fi}}
+
+%D This is not the one Hans made for me, because I need a global
+%D edef, and the \type{\robustdoifinsetelse} doesn't listen to
+%D \type{\doglobal }
+
+\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
+ {\robustdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+%D \macros{donormalbibauthoryear}
+%D
+%D Now we get to the macros that fill the two lists.
+%D The `simple' one really is quite simple.
+
+\unexpanded\def\donormalbibauthoryear#1%
+ {\def\myauthor{Xxxxxxxxxx}%
+ \def\myyear{0000}%
+ \doifelsebibreferencefound{#1}
+ {\def\myauthor{{\bibgetvara{#1}}}%
+ \def\myyear {\bibgetvary{#1}}}%
+ {}%
+ \expandafter\doglobal\expandafter\appendtocommalist\expandafter{\myauthor}\thebibauthors
+ \expandafter\doglobal\expandafter\appendtocommalist\expandafter{\myyear }\thebibyears}
+
+%D \macros{docompressbibauthoryear}
+%D
+%D So much for the easy parts. Nothing at all will be done if
+%D the reference is not found or the reference does not contain
+%D author data. No questions marks o.s.s. (to be fixed later)
+
+\unexpanded\def\docompressbibauthoryear#1%
+ {\def\myauthor{Xxxxxxxxxx}%
+ \def\myyear {0000}%
+ \doifelsebibreferencefound{#1}
+ {\xdef\myauthor{\bibgetvara{#1}}%
+ \xdef\myyear {\bibgetvary{#1}}}
+ {}%
+ \ifx\myauthor\empty\else
+ \checkifmyauthoralreadyexists
+ \findmatchingyear
+ \fi}
+
+%D two temporary counters. One of these two can possibly be replaced
+%D by \type{\scratchcounter}.
+
+\newcount\bibitemcounter
+\newcount\bibitemwanted
+
+%D The first portion is simple enough: if this is the very first author
+%D it is quite straightforward to add it. \type{\bibitemcounter} and
+%D \type{\bibitemwanted} are needed later to insert the year
+%D information in the correct item of \type{\thebibyears}
+
+\unexpanded\def\checkifmyauthoralreadyexists
+ {\doifelseemptyvalue{thebibauthors}
+ {\global\bibitemwanted \plusone
+ \global\bibitemcounter\plusone
+ \xdef\thebibauthors{{\myauthor}}}
+ {% the next weirdness is because according to \getcommalistsize,
+ % the length of \type{[{{},{}}]} is 2.
+ \expandafter\getcommalistsize\expandafter[\thebibauthors,]%
+ \global\bibitemcounter\numexpr\commalistsize+\minusone\relax
+ \global\bibitemwanted \zerocount
+ \processcommacommand[\thebibauthors]\docomparemyauthor}}
+
+%D The outer \type{\ifnum} accomplishes the addition of
+%D a new author to \type{\thebibauthors}. The messing about with
+%D the two counters is again to make sure that \type{\thebibyears}
+%D will be updated correctly.If the author {\it was} found,
+%D the counters will stay at their present values and everything
+%D will be setup properly to insert the year info.
+
+\unexpanded\def\docomparemyauthor#1%
+ {\global\advance\bibitemwanted \plusone
+ \def\mytempc{#1}%
+ \ifx\mytempc\myauthor
+ \quitcommalist
+ \else\ifnum\bibitemwanted=\bibitemcounter\relax
+ \global\advance\bibitemwanted \plusone
+ \global\bibitemcounter\bibitemwanted\relax
+ \expandafter\doglobal\expandafter\robustaddtocommalist\expandafter{{\myauthor}}\thebibauthors
+ \fi\fi}
+
+%D This macro should be clear now.
+
+\unexpanded\def\findmatchingyear
+ {\edef\wantednumber{\the\bibitemwanted}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \ifx\commalistelement\empty
+ \edef\myyear{{\myyear}}%
+ \else
+ \edef\myyear{{\commalistelement,\myyear}}%
+ \fi
+ \edef\newcommalistelement{\myyear}%
+ \doglobal\replaceincommalist \thebibyears \wantednumber}
+
+%D \macros{gotobiblink,inbiblink,atbiblink}
+%D
+%D The final task is looping over that list until a match is found.
+
+%D Beware, we can have cites without reference match.
+
+\unexpanded\def\gotobiblink#1[#2]{\doifelsereferencefound{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}}
+\unexpanded\def\atbiblink [#1]{\doifelsereferencefound{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}}
+\unexpanded\def\inbiblink [#1]{\doifelsereferencefound{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{#1}}
+
+%D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref}
+%D
+%D Now that all the hard work has been done, these are simple.
+%D \type{\ixbibauthoryearref} stores the data in the macros
+%D \type{\currentbibauthor} and \type{\currentbibyear}.
+
+\unexpanded\def\doifelsebibinteraction
+ {\iflocation
+ \edef\test{\bibalternative\c!interaction}%
+ \ifx\test\v!stop
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifbibinteractionelse\doifelsebibinteraction
+
+\unexpanded\def\bibmaybeinteractive#1#2%
+ {\doifelsebibinteraction{\gotobiblink{#2}[#1]}{#2}}
+
+\unexpanded\def\bibauthoryearref[#1]%
+ {\ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left{\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}}
+
+\unexpanded\def\bibauthoryearsref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+\unexpanded\def\bibauthorref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibauthor}}}%
+ \bibalternative\v!right}
+
+\unexpanded\def\bibyearref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+%D \macros{bibshortref,bibkeyref,bibpageref,bibtyperef,bibserialref}
+%D
+%D There is hardly any point in trying to compress these. The only
+%D thing that needs to be done is making sure that
+%D the separations are inserted correctly. And that is
+%D what \type{\bibinsertrefsep} does.
+
+\newconditional\firstbibrefsep
+
+\unexpanded\def\bibresetrefsep
+ {\settrue\firstbibrefsep}
+
+\unexpanded\def\bibinsertrefsep
+ {\ifconditional\firstbibrefsep
+ \setfalse\firstbibrefsep
+ \else
+ \bibalternative\c!pubsep
+ \fi}
+
+\unexpanded\def\bibshortref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibshortref
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibshortref#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\gotobiblink{\bibgetvars{#1}}[#1]}
+ {}}
+
+\unexpanded\def\bibserialref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibserialref
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibserialref#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\gotobiblink{\bibgetvarn{#1}}[#1]}
+ {}}
+
+\unexpanded\def\bibkeyref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibkeyref
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibkeyref#1%
+ {\bibinsertrefsep
+ \gotobiblink{#1}[#1]}
+
+\unexpanded\def\bibgotoDOI#1#2%
+ {\doifelsebibinteraction
+ {\useURL[bibfooDoi#1][#2]%
+ \useURL[bibfoo#1][http://dx.doi.org/#2]%
+ \goto{\url[bibfooDoi#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\unexpanded\def\bibdoiref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibdoiref
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibdoiref#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\expanded{\bibgotoDOI{#1}{\bibgetvaro{#1}}}}
+ {}}
+
+\unexpanded\def\biburlref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobiburlref
+ \bibalternative\v!right}
+
+\unexpanded\def\bibgotoURL#1#2%
+ {\doifelsebibinteraction
+ {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\unexpanded\def\dobiburlref#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\expanded{\bibgotoURL{#1}{\bibgetvaru{#1}}}}
+ {}}
+
+\unexpanded\def\bibtyperef[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibtyperef
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibtyperef#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\gotobiblink{\bibgetvart{#1}}[#1]}
+ {}}
+
+\unexpanded\def\bibpageref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibpageref
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibpageref#1%
+ {\bibinsertrefsep
+ \doifelsebibinteraction
+ {\atbiblink[#1]}
+ {{\referencingfalse\at[#1]}}}
+
+\unexpanded\def\bibdataref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibdata
+ \bibalternative\v!right}
+
+\unexpanded\def\dobibdata#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\dotypesetapublication{#1}}
+ {}}
+
+\let\bibnoneref\nocite
+
+%D \macros{bibnumref}
+
+\unexpanded\def\bibnumref[#1]%
+ {\begingroup
+ \bibalternative\v!left
+ \penalty\plustenthousand
+ \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
+ \bibalternative\v!right
+ \endgroup}
+
+\unexpanded\def\dowithbibtexnumrefconnector#1#2%
+ {\ifnum#1>\plusone
+ \ifnum#2>\plusone
+ \ifnum#2=#1\relax
+ \bibalternative{lastpubsep}%
+ \else
+ \bibalternative{pubsep}%
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibrefprefix{#4:}%
+ \inbiblink[#5]}
+
+\unexpanded\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibrefprefix{#4:}%
+ \inbiblink[#5]%
+ \endash
+ \def\bibrefprefix{#6:}%
+ \inbiblink[#7]}
+
+%D By request from Sanjoy. This makes it easier to implement
+%D \type{\citeasnoun}.
+
+\unexpanded\def\bibauthornumref[#1]%
+ {\getcommalistsize[#1]%
+ \global\bibitemcounter\commalistsize
+ \bibresetrefsep
+ \processcommalist[#1]\dobibauthornumref}
+
+\unexpanded\def\dobibauthornumref#1%
+ {\bibinsertrefsep
+ \doifelsebibreferencefound{#1}
+ {\begingroup
+ \cite[\c!left=,\c!right=,\c!alternative=\v!author][#1]%
+ \bibalternative\c!inbetween
+ \cite[num][#1]%
+ \endgroup}
+ {}}
+
+%D And some defaults are loaded from bibl-apa:
+
+\setuppublications
+ [\c!monthconversion=,
+ \c!alternative=apa,
+ \c!method=\v!global,
+ %\c!criterium=\v!previous,
+ \c!criterium=\v!cite, % mojca wants this so bother her, not me
+ \c!refcommand=num,
+ \c!numbercommand=\bibleftnumber]
+
+\unexpanded\def\preloadbiblist
+ {\globallet\preloadbiblist\relax
+ \dousepublications\jobname}
+
+% \appendtoks \preloadbiblist \to \everysetuppublications
+% \appendtoks \preloadbiblist \to \everystarttext
+
+\let\ifbibinteractionelse\doifbibinteractionelse
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-tst.lua b/Master/texmf-dist/tex/context/base/mkiv/bibl-tst.lua
new file mode 100644
index 00000000000..5ff8f45709f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-tst.lua
@@ -0,0 +1,21 @@
+dofile("bibl-bib.lua")
+
+local session = bibtex.new()
+
+bibtex.load(session,"gut.bib")
+bibtex.load(session,"komoedie.bib")
+bibtex.load(session,"texbook1.bib")
+bibtex.load(session,"texbook2.bib")
+bibtex.load(session,"texbook3.bib")
+bibtex.load(session,"texgraph.bib")
+bibtex.load(session,"texjourn.bib")
+bibtex.load(session,"texnique.bib")
+bibtex.load(session,"tugboat.bib")
+print(bibtex.size,statistics.elapsedtime(bibtex))
+bibtex.toxml(session)
+print(bibtex.size,statistics.elapsedtime(bibtex))
+
+--~ print(table.serialize(session.data))
+--~ print(table.serialize(session.shortcuts))
+--~ print(xml.serialize(session.xml))
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/blob-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/blob-ini.lua
new file mode 100644
index 00000000000..106c10f4f32
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/blob-ini.lua
@@ -0,0 +1,194 @@
+if not modules then modules = { } end modules ['blob-ini'] = {
+ version = 1.001,
+ comment = "companion to blob-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module is just a playground. Occasionally we need to typeset at the lua and and
+-- this is one method. In principle we can construct pages this way too which sometimes
+-- makes sense in dumb cases. Actually, if one only needs this, one does not really need
+-- tex, okay maybe the parbuilder but that one can be simplified as well then.
+
+-- set fonts, attributes
+-- rest already done in packers etc
+-- add local par whatsit (or wait till cleaned up)
+-- collapse or new pars
+-- interline spacing etc
+
+-- blob.char
+-- blob.line
+-- blob.paragraph
+-- blob.page
+
+local type, tostring = type, tostring
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+local report_blobs = logs.reporter("blobs")
+
+local flush_node_list = node.flush_list
+local hpack_node_list = node.hpack
+local vpack_node_list = node.vpack
+local write_node = node.write
+
+local typesetters = nodes.typesetters
+local tonodes = typesetters.tonodes
+local tohpack = typesetters.tohpack
+local tovpack = typesetters.tovpack
+
+local implement = interfaces.implement
+
+-- provide copies here (nicer for manuals)
+
+blobs = blobs or { }
+local blobs = blobs
+
+blobs.tonodes = tonodes
+blobs.tohpack = tohpack
+blobs.tovpack = tovpack
+
+-- end of helpers
+
+local newline = lpeg.patterns.newline
+local space = lpeg.patterns.spacer
+local newpar = (space^0*newline*space^0)^2
+
+local ctxtextcapture = lpeg.Ct ( ( space^0 * ( newpar + lpeg.Cs(((space^1/" " + 1)-newpar)^1) ) )^0)
+
+function blobs.new()
+ return {
+ list = { },
+ }
+end
+
+function blobs.dispose(t)
+ local list = t.list
+ for i=1,#list do
+ local li = list[i]
+ local pack = li.pack
+ if pack then
+ flush_node_list(pack)
+ li.pack = nil
+ end
+ end
+end
+
+function blobs.append(t,str) -- compare concat and link
+ local typ = type(str)
+ local dummy = nil
+ if typ == "number" then
+ str = tostring(str)
+ typ = "string"
+ end
+ if typ == "string" then
+ local pars = lpegmatch(ctxtextcapture,str)
+ local list = t.list
+ for p=1,#pars do
+ local head, tail = tonodes(pars[p],nil,nil)
+ list[#list+1] = { head = head, tail = tail }
+ end
+ end
+end
+
+function blobs.pack(t,how)
+ local list = t.list
+ for i=1,#list do
+ local pack = list[i].pack
+ if pack then
+ flush_node_list(node.pack)
+ end
+ if how == "vertical" then
+ -- we need to prepend a local par node
+ -- list[i].pack = vpack_node_list(list[i].head,"exactly")
+ report_blobs("vpack not yet supported")
+ else
+ list[i].pack = hpack_node_list(list[i].head,"exactly")
+ end
+ end
+end
+
+function blobs.write(t)
+ local list = t.list
+ for i=1,#list do
+ local li = list[i]
+ local pack = li.pack
+ if pack then
+ write_node(pack)
+ flush_node_list(pack)
+ li.pack = nil
+ end
+ end
+end
+
+function blobs.dimensions(t)
+ local list = t.list
+ local first = list and list[1]
+ if first then
+ local pack = first.pack
+ return pack.width, pack.height, pack.depth
+ else
+ return 0, 0, 0
+ end
+end
+
+-- blob.char
+-- blob.line: head, tail
+-- blob.paragraph
+-- blob.page
+
+-- local lineblob = {
+-- type = "line",
+-- head = false,
+-- tail = false,
+-- pack = false,
+-- properties = { },
+-- end
+
+-- local parblob = {
+-- type = "line",
+-- head = false,
+-- tail = false,
+-- pack = false,
+-- properties = { },
+-- end
+
+-- for the moment here:
+
+local function strwd(str)
+ local l = tohpack(str)
+ local w = l.width
+ flush_node_list(l)
+ return w
+end
+
+local function strht(str)
+ local l = tohpack(str)
+ local h = l.height
+ flush_node_list(l)
+ return h
+end
+
+local function strdp(str)
+ local l = tohpack(str)
+ local d = l.depth
+ flush_node_list(l)
+ return d
+end
+
+local function strhd(str)
+ local l = tohpack(str)
+ local s = l.height + l.depth
+ flush_node_list(l)
+ return s
+end
+
+blobs.strwd = strwd
+blobs.strht = strht
+blobs.strdp = strdp
+blobs.strhd = strhd
+
+implement { name = "strwd", arguments = "string", actions = { strwd, context } }
+implement { name = "strht", arguments = "string", actions = { strht, context } }
+implement { name = "strdp", arguments = "string", actions = { strdp, context } }
+implement { name = "strhd", arguments = "string", actions = { strhd, context } }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/blob-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/blob-ini.mkiv
new file mode 100644
index 00000000000..64582c0db59
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/blob-ini.mkiv
@@ -0,0 +1,62 @@
+%D \module
+%D [ file=blob-ini,
+%D version=2010.04.06,
+%D title=\CONTEXT\ \LUA\ Typesetting,
+%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 Lua Typesetting / Initialization}
+
+%D This is a prelude to typesetting at the \LUA\ end. The code
+%D is already quite old but will only get nice when we are further
+%D down the road (close to version 1.00 of \LUATEX). Typesetting in
+%D pure \LUA\ sometimes makes sense.
+
+\registerctxluafile{node-typ}{1.001} % experimental
+\registerctxluafile{blob-ini}{1.001}
+
+%D For the moment here:
+
+\unprotect
+
+% this one takes simple (utf) strings
+
+\def\wdofstring#1{\dimexpr\clf_strwd{#1}\scaledpoint\relax}
+\def\htofstring#1{\dimexpr\clf_strht{#1}\scaledpoint\relax}
+\def\dpofstring#1{\dimexpr\clf_strdp{#1}\scaledpoint\relax}
+\def\hdofstring#1{\dimexpr\clf_strhd{#1}\scaledpoint\relax}
+
+\def\widthofstring {\the\wdofstring}
+\def\heightofstring {\the\htofstring}
+\def\depthofstring {\the\dpofstring}
+\def\heightanddepthofstring{\the\hdofstring}
+
+\let\htdpofstring \hdofstring
+
+\let\hd\htdp % if yes then move this
+
+% this one takes anything that can be typeset
+
+\unexpanded\def\setwidthof#1\to#2%
+ {\bgroup
+ \setbox\scratchbox\hbox{#1}%
+ \expanded{\egroup\def\noexpand#2{\the\wd\scratchbox}}}
+
+\protect \endinput
+
+% \starttext
+%
+% \startluacode
+% local b = blobs.new()
+% blobs.append(b,"Hello world.\n Here we are.\n\n And Again!")
+% blobs.pack(b)
+% blobs.write(b)
+% \stopluacode
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.lua
new file mode 100644
index 00000000000..79f01c47d31
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.lua
@@ -0,0 +1,42 @@
+if not modules then modules = { } end modules ['buff-imp-default'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-default.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local patterns, P, V = lpeg.patterns, lpeg.P, lpeg.V
+local makepattern = visualizers.makepattern
+
+local handler = visualizers.newhandler()
+
+local grammar = { "visualizer",
+
+ -- basic
+
+ signal = makepattern(handler,"signal", visualizers.signalpattern),
+ emptyline = makepattern(handler,"emptyline",patterns.emptyline),
+ beginline = makepattern(handler,"beginline",patterns.beginline),
+ newline = makepattern(handler,"newline", patterns.newline),
+ space = makepattern(handler,"space", patterns.space),
+ default = makepattern(handler,"default", patterns.utf8character),
+ content = makepattern(handler,"default", patterns.somecontent), -- not too efficient
+
+ -- handy
+
+ -- line = V("newline") * V("emptyline")^0 * V("beginline"),
+ line = V("newline") * V("emptyline")^0 * V("beginline") + V("emptyline") + V("newline"),
+ whitespace = (V("space") + V("line"))^1,
+ optionalwhitespace = (V("space") + V("line"))^0,
+
+ -- used
+
+ pattern = V("line") + V("space") + V("signal") + V("content"),
+ visualizer = V("pattern")^1
+
+}
+
+local parser = P(grammar)
+
+visualizers.register("default", { parser = parser, handler = handler, grammar = grammar })
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv
new file mode 100644
index 00000000000..5cff34c7006
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv
@@ -0,0 +1,43 @@
+%D \module
+%D [ file=buff-imp-default,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=Default,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-default.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [DefaultSnippet]
+ [\c!before=\blank,
+ \c!after=\blank,
+ \c!style=\tt]
+
+% Name
+% NamePrimitive
+% NamePlain
+% NameMetafun
+% Group
+% Boundary
+% Special
+% Comment
+% Constructor
+% Key
+% Entity
+% String
+% Equal
+% Cdata
+% Instruction
+
+% Value
+% Quote
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.lua
new file mode 100644
index 00000000000..159921e2a85
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.lua
@@ -0,0 +1,14 @@
+if not modules then modules = { } end modules ['buff-imp-escaped'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-escaped.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+visualizers.registerescapepattern("/BTEX/ETEX","/BTEX","/ETEX")
+
+visualizers.register("escaped", {
+ parser = visualizers.escapepatterns["/BTEX/ETEX"],
+ handler = visualizers.newhandler(),
+})
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.mkiv
new file mode 100644
index 00000000000..13850475a82
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-escaped.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=buff-imp-escaped,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=Escaped,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-escaped.lua}{1.001}
+
+\unprotect
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.lua
new file mode 100644
index 00000000000..e873a34d182
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.lua
@@ -0,0 +1,209 @@
+if not modules then modules = { } end modules ['buff-imp-lua'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-lua.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- borrowed from ctx scite lexers
+-- add goto/label scanning
+--
+-- depricated:
+--
+-- gcinfo unpack getfenv setfenv loadlib
+-- table.maxn table.getn table.setn
+-- math.log10 math.mod math.modf math.fmod
+
+local format, tohash = string.format, table.tohash
+local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
+local C, Cs, Cg, Cb, Cmt, Carg = lpeg.C, lpeg.Cs, lpeg.Cg, lpeg.Cb, lpeg.Cmt, lpeg.Carg
+
+local core = tohash {
+ "and", "break", "do", "else", "elseif", "end", "false", "for", "function",
+ "if", "in", "local", "nil", "not", "or", "repeat", "return", "then",
+ "true", "until", "while"
+}
+
+local base = tohash {
+ "assert", "collectgarbage", "dofile", "error", "loadfile",
+ "loadstring", "load", "print", "rawget", "rawset", "require", "tonumber",
+ "tostring", "type", "_G", "getmetatable", "ipairs", "next", "pairs",
+ "pcall", "rawequal", "setmetatable", "xpcall", "module", "select", "goto",
+}
+
+local libraries = {
+ coroutine = tohash {
+ "create", "resume", "status", "wrap", "yield", "running",
+ },
+ package = tohash{
+ "cpath", "loaded", "loadlib", "path", "config", "preload", "seeall",
+ },
+ io = tohash{
+ "close", "flush", "input", "lines", "open", "output", "read", "tmpfile",
+ "type", "write", "stdin", "stdout", "stderr", "popen",
+ },
+ math = tohash{
+ "abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "deg", "exp",
+ "floor ", "ldexp", "log", "max", "min", "pi", "pow", "rad", "random",
+ "randomseed", "sin", "sqrt", "tan", "cosh", "sinh", "tanh", "huge",
+ },
+ string = tohash{
+ "byte", "char", "dump", "find", "len", "lower", "rep", "sub", "upper",
+ "format", "gfind", "gsub", "gmatch", "match", "reverse",
+ },
+ table = tohash{
+ "concat", "foreach", "foreachi", "sort", "insert", "remove", "pack",
+ "unpack",
+ },
+ os = tohash{
+ "clock", "date", "difftime", "execute", "exit", "getenv", "remove",
+ "rename", "setlocale", "time", "tmpname",
+ },
+ lpeg = tohash{
+ "print", "match", "locale", "type", "version", "setmaxstack",
+ "P", "R", "S", "C", "V", "Cs", "Ct", "Cs", "Cc", "Cp", "Carg",
+ "Cg", "Cb", "Cmt", "Cf", "B",
+ },
+ -- bit
+ -- debug
+}
+
+local context = context
+local verbatim = context.verbatim
+local makepattern = visualizers.makepattern
+
+local LuaSnippet = context.LuaSnippet
+local startLuaSnippet = context.startLuaSnippet
+local stopLuaSnippet = context.stopLuaSnippet
+
+local LuaSnippetBoundary = verbatim.LuaSnippetBoundary
+local LuaSnippetQuote = verbatim.LuaSnippetQuote
+local LuaSnippetString = verbatim.LuaSnippetString
+local LuaSnippetSpecial = verbatim.LuaSnippetSpecial
+local LuaSnippetComment = verbatim.LuaSnippetComment
+local LuaSnippetNameCore = verbatim.LuaSnippetNameCore
+local LuaSnippetNameBase = verbatim.LuaSnippetNameBase
+local LuaSnippetNameLibraries = verbatim.LuaSnippetNameLibraries
+local LuaSnippetName = verbatim.LuaSnippetName
+
+local namespace
+
+local function visualizename_a(s)
+ if core[s] then
+ namespace = nil
+ LuaSnippetNameCore(s)
+ elseif base[s] then
+ namespace = nil
+ LuaSnippetNameBase(s)
+ else
+ namespace = libraries[s]
+ if namespace then
+ LuaSnippetNameLibraries(s)
+ else
+ LuaSnippetName(s)
+ end
+ end
+end
+
+local function visualizename_b(s)
+ if namespace and namespace[s] then
+ namespace = nil
+ LuaSnippetNameLibraries(s)
+ else
+ LuaSnippetName(s)
+ end
+end
+
+local function visualizename_c(s)
+ LuaSnippetName(s)
+end
+
+local handler = visualizers.newhandler {
+ startinline = function() LuaSnippet(false,"{") end,
+ stopinline = function() context("}") end,
+ startdisplay = function() startLuaSnippet() end,
+ stopdisplay = function() stopLuaSnippet() end ,
+ boundary = function(s) LuaSnippetBoundary(s) end,
+ special = function(s) LuaSnippetSpecial(s) end,
+ comment = function(s) LuaSnippetComment(s) end,
+ quote = function(s) LuaSnippetQuote(s) end,
+ string = function(s) LuaSnippetString(s) end,
+ period = function(s) verbatim(s) end,
+ name_a = visualizename_a,
+ name_b = visualizename_b,
+ name_c = visualizename_c,
+}
+
+local comment = P("--")
+local name = (patterns.letter + patterns.underscore)
+ * (patterns.letter + patterns.underscore + patterns.digit)^0
+local boundary = S('()[]{}')
+local special = S("-+/*^%=#~|<>") + P("..")
+
+-- The following longstring parser is taken from Roberto's documentation
+-- that can be found at http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html.
+
+local equals = P("=")^0
+local open = P("[") * Cg(equals, "init") * P("[") * P("\n")^-1 -- maybe better: patterns.newline^-1
+local close = P("]") * C(equals) * P("]")
+local closeeq = Cmt(close * Cb("init"), function(s,i,a,b) return a == b end) -- wrong return value
+local longstring = open * Cs((P(1) - closeeq)^0) * close * Carg(1)
+
+local function long(content,equals,settings)
+ handler.boundary(format("[%s[",equals or ""))
+ visualizers.write(content,settings) -- unhandled
+ handler.boundary(format("]%s]",equals or ""))
+end
+
+local grammar = visualizers.newgrammar("default", { "visualizer",
+ sstring =
+ makepattern(handler,"quote",patterns.dquote)
+ * (V("whitespace") + makepattern(handler,"string",(1-patterns.dquote-V("whitespace"))^1))^0 -- patterns.nodquote
+ * makepattern(handler,"quote",patterns.dquote),
+ dstring =
+ makepattern(handler,"quote",patterns.squote)
+ * (V("whitespace") + makepattern(handler,"string",(1-patterns.squote-V("whitespace"))^1))^0 -- patterns.nosquote
+ * makepattern(handler,"quote",patterns.squote),
+ longstring =
+ longstring / long,
+ comment =
+ makepattern(handler,"comment",comment)
+ * (V("space") + V("content"))^0,
+ longcomment =
+ makepattern(handler,"comment",comment)
+ * longstring / long,
+ name =
+ makepattern(handler,"name_a",name)
+ * ( V("optionalwhitespace")
+ * makepattern(handler,"default",patterns.period)
+ * V("optionalwhitespace")
+ * makepattern(handler,"name_b",name)
+ )^-1
+ * ( V("optionalwhitespace")
+ * makepattern(handler,"default",patterns.period)
+ * V("optionalwhitespace")
+ * makepattern(handler,"name_c",name)
+ )^0,
+
+ pattern =
+ V("longcomment")
+ + V("comment")
+ + V("longstring")
+ + V("dstring")
+ + V("sstring")
+ + V("name")
+ + makepattern(handler,"boundary",boundary)
+ + makepattern(handler,"special",special)
+
+ + V("space")
+ + V("line")
+ + V("default"),
+
+ visualizer =
+ V("pattern")^1
+} )
+
+local parser = P(grammar)
+
+visualizers.register("lua", { parser = parser, handler = handler, grammar = grammar } )
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.mkiv
new file mode 100644
index 00000000000..dc601bd7b8e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-lua.mkiv
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=buff-imp-lua,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=\LUA,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-lua.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [LuaSnippet]
+ [DefaultSnippet]
+
+\definestartstop
+ [LuaSnippetName]
+ [\c!color=,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetNameCore]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetNameBase]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetNameLibraries]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetBoundary]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetString]
+ [LuaSnippet]
+
+\definestartstop
+ [LuaSnippetQuote]
+ [LuaSnippetBoundary]
+
+\definestartstop
+ [LuaSnippetSpecial]
+ [\c!color=darkred,
+ \c!style=boldface]
+
+\definestartstop
+ [LuaSnippetComment]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definetyping
+ [LUA]
+ [\c!option=lua]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.lua
new file mode 100644
index 00000000000..bcd18dd47a0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.lua
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['buff-imp-mp'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-mp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Now that we also use lpeg lexers in scite, we can share the keywords
+-- so we have moved the keyword lists to mult-mps.lua. Don't confuse the
+-- scite lexers with the ones we use here. Of course all those lexers
+-- boil down to doing similar things, but here we need more control over
+-- the rendering and have a different way of nesting. It is no coincidence
+-- that the coloring looks similar: both are derived from earlier lexing (in
+-- texedit, mkii and the c++ scite lexer).
+--
+-- In the meantime we have lpeg based lexers in scite! And, as all this
+-- lexing boils down to the same principles (associating symbolic rendering
+-- with ranges of characters) and as the scite lexers do nesting, it makes
+-- sense at some point to share code. However, keep in mind that the pretty
+-- printers are also supposed to support invalid code (for educational
+-- purposes). The scite lexers are more recent and there a different color
+-- scheme is used. So, we might move away from the traditional coloring.
+
+local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
+
+local context = context
+local verbatim = context.verbatim
+local makepattern = visualizers.makepattern
+
+local MetapostSnippet = context.MetapostSnippet
+local startMetapostSnippet = context.startMetapostSnippet
+local stopMetapostSnippet = context.stopMetapostSnippet
+
+local MetapostSnippetConstructor = verbatim.MetapostSnippetConstructor
+local MetapostSnippetBoundary = verbatim.MetapostSnippetBoundary
+local MetapostSnippetSpecial = verbatim.MetapostSnippetSpecial
+local MetapostSnippetComment = verbatim.MetapostSnippetComment
+local MetapostSnippetQuote = verbatim.MetapostSnippetQuote
+local MetapostSnippetString = verbatim.MetapostSnippetString
+local MetapostSnippetNamePrimitive = verbatim.MetapostSnippetNamePrimitive
+local MetapostSnippetNamePlain = verbatim.MetapostSnippetNamePlain
+local MetapostSnippetNameMetafun = verbatim.MetapostSnippetNameMetafun
+local MetapostSnippetName = verbatim.MetapostSnippetName
+
+local primitives, plain, metafun
+
+local function initialize()
+ local mps = dofile(resolvers.findfile("mult-mps.lua","tex")) or {
+ primitives = { },
+ plain = { },
+ metafun = { },
+ }
+ primitives = table.tohash(mps.primitives)
+ plain = table.tohash(mps.plain)
+ metafun = table.tohash(mps.metafun)
+end
+
+local function visualizename(s)
+ if not primitives then
+ initialize()
+ end
+ if primitives[s] then
+ MetapostSnippetNamePrimitive(s)
+ elseif plain[s] then
+ MetapostSnippetNamePlain(s)
+ elseif metafun[s] then
+ MetapostSnippetNameMetafun(s)
+ else
+ MetapostSnippetName(s)
+ end
+end
+
+local handler = visualizers.newhandler {
+ startinline = function() MetapostSnippet(false,"{") end,
+ stopinline = function() context("}") end,
+ startdisplay = function() startMetapostSnippet() end,
+ stopdisplay = function() stopMetapostSnippet() end ,
+ constructor = function(s) MetapostSnippetConstructor(s) end,
+ boundary = function(s) MetapostSnippetBoundary(s) end,
+ special = function(s) MetapostSnippetSpecial(s) end,
+ comment = function(s) MetapostSnippetComment(s) end,
+ string = function(s) MetapostSnippetString(s) end,
+ quote = function(s) MetapostSnippetQuote(s) end,
+ name = visualizename,
+}
+
+local comment = S("%")
+local name = (patterns.letter + S("_"))^1
+local constructor = S("$@#")
+local boundary = S('()[]:=<>;"')
+local special = S("-+/*|`!?^&%.,")
+
+local grammar = visualizers.newgrammar("default", { "visualizer",
+
+ comment = makepattern(handler,"comment",comment)
+ * (V("space") + V("content"))^0,
+ dstring = makepattern(handler,"quote",patterns.dquote)
+ * makepattern(handler,"string",patterns.nodquote)
+ * makepattern(handler,"quote",patterns.dquote),
+ name = makepattern(handler,"name",name),
+ constructor = makepattern(handler,"constructor",constructor),
+ boundary = makepattern(handler,"boundary",boundary),
+ special = makepattern(handler,"special",special),
+
+ pattern =
+ V("comment") + V("dstring") + V("name") + V("constructor") + V("boundary") + V("special")
+ + V("newline") * V("emptyline")^0 * V("beginline")
+ + V("space")
+ + V("default"),
+
+ visualizer =
+ V("pattern")^1
+
+} )
+
+local parser = P(grammar)
+
+visualizers.register("mp", { parser = parser, handler = handler, grammar = grammar } )
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.mkiv
new file mode 100644
index 00000000000..a40eb6c303f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-mp.mkiv
@@ -0,0 +1,76 @@
+%D \module
+%D [ file=buff-imp-mp,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=\METAPOST,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-mp.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [MetapostSnippet]
+ [DefaultSnippet]
+
+\definestartstop
+ [MetapostSnippetName]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [MetapostSnippetNamePrimitive]
+ [\c!color=darkgreen,
+ \c!style=swapface]
+
+\definestartstop
+ [MetapostSnippetNamePlain]
+ [\c!color=darkblue,
+ \c!color=darkgreen,
+ \c!style=swapface]
+
+\definestartstop
+ [MetapostSnippetNameMetafun]
+ [\c!color=darkred,
+ \c!color=darkgreen,
+ \c!style=swapface]
+
+\definestartstop
+ [MetapostSnippetConstructor]
+ [\c!color=darkred,
+ \c!style=boldface]
+
+\definestartstop
+ [MetapostSnippetBoundary]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [MetapostSnippetQuote]
+ [MetapostSnippetBoundary]
+
+\definestartstop
+ [MetapostSnippetSpecial]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definestartstop
+ [MetapostSnippetString]
+ [MetapostSnippet]
+
+\definestartstop
+ [MetapostSnippetComment]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definetyping
+ [MP]
+ [\c!option=mp]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.lua
new file mode 100644
index 00000000000..019cd996d6e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.lua
@@ -0,0 +1,80 @@
+if not modules then modules = { } end modules ['buff-imp-nested'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-nested.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, V, Carg = lpeg.P, lpeg.V, lpeg.Carg
+
+local context = context
+local verbatim = context.verbatim
+local variables = interfaces.variables
+
+local makepattern = visualizers.makepattern
+local getvisualizer = visualizers.getvisualizer
+
+local nested = nil
+
+local donestedtypingstart = context.donestedtypingstart
+local donestedtypingstop = context.donestedtypingstop
+
+local v_none = variables.none
+local v_slanted = variables.slanted
+
+local handler = visualizers.newhandler {
+ initialize = function(settings)
+ local option = settings and settings.option
+ if not option or option == "" then
+ nested = nil
+ elseif option == v_slanted then
+ nested = nil
+ elseif option == v_none then
+ nested = nil
+ else
+ nested = getvisualizer(option,"direct")
+ end
+ end,
+ open = function()
+ donestedtypingstart()
+ end,
+ close = function()
+ donestedtypingstop()
+ end,
+ content = function(s)
+ if nested then
+ nested(s)
+ else
+ verbatim(s)
+ end
+ end,
+}
+
+local open = P("<<")
+local close = P(">>")
+local rest = (1 - open - close - patterns.space - patterns.newline)^1
+
+local grammar = visualizers.newgrammar("default", {
+
+ initialize = patterns.beginofstring * Carg(1) / handler.initialize,
+
+ open = makepattern(handler,"open",open),
+ close = makepattern(handler,"close",close),
+ rest = makepattern(handler,"content",rest),
+
+ nested = V("open") * (V("pattern")^0) * V("close"),
+ pattern = V("line") + V("space") + V("nested") + V("rest"),
+
+ visualizer = V("initialize") * (V("pattern")^1)
+
+} )
+
+local parser = P(grammar)
+
+visualizers.register("nested", { parser = parser, handler = handler, grammar = grammar } )
+
+-- lpeg.match(parser,[[<<tf<<sl>>tf<<sl>>tf>>]]) context.par()
+-- lpeg.match(parser,[[<<tf<<sl<<tf>>sl>>tf>>]]) context.par()
+-- lpeg.match(parser,[[sl<<tf<<sl>>tf>>sl]]) context.par()
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.mkiv
new file mode 100644
index 00000000000..7815086dbfa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-nested.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=buff-imp-nested,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=Nested,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-nested.lua}{1.001}
+
+\unprotect
+
+\unexpanded\def\donestedtypingstart{\bgroup\swaptypeface{}}
+\unexpanded\def\donestedtypingstop {\egroup{}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.lua
new file mode 100644
index 00000000000..22611ac8ab7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['buff-imp-parsed-xml'] = {
+ version = 1.001,
+ comment = "companion to buff-imp-parsed-xml.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local context = context
+local verbatim = context.verbatim
+
+local write = visualizers.write
+local writespace = visualizers.writespace
+local writeargument = visualizers.writeargument
+
+local ParsedXmlSnippetKey = context.ParsedXmlSnippetKey
+local ParsedXmlSnippetValue = context.ParsedXmlSnippetValue
+
+local ParsedXmlSnippetElement = verbatim.ParsedXmlSnippetElement
+local ParsedXmlSnippetInstruction = verbatim.ParsedXmlSnippetInstruction
+local ParsedXmlSnippetComment = verbatim.ParsedXmlSnippetComment
+local ParsedXmlSnippetCdata = verbatim.ParsedXmlSnippetCdata
+local ParsedXmlSnippetDoctype = verbatim.ParsedXmlSnippetDoctype
+
+local startParsedXmlSnippet = context.startParsedXmlSnippet
+local stopParsedXmlSnippet = context.stopParsedXmlSnippet
+
+local parsedxmlhandler = xml.newhandlers { -- todo: treat spaces and tabs
+ name = "parsedxml",
+ handle = function(...)
+ print("error:",...) -- we need a handler as fallback, even if not used
+ end,
+ functions = {
+ ["@el@"] = function(e,handler)
+ local at = e.at
+ if at and next(at) then
+ ParsedXmlSnippetElement(format("<%s",e.tg))
+ for k, v in next, at do
+ writespace()
+ ParsedXmlSnippetKey()
+ writeargument(k)
+ verbatim("=")
+ ParsedXmlSnippetValue()
+ writeargument(format("%q",k))
+ end
+ ParsedXmlSnippetElement(">")
+ else
+ ParsedXmlSnippetElement(format("<%s>",e.tg))
+ end
+ handler.serialize(e.dt,handler)
+ ParsedXmlSnippetElement(format("</%s>",e.tg))
+ end,
+ ["@pi@"] = function(e,handler)
+ ParsedXmlSnippetInstruction("<?")
+ write(e.dt[1])
+ ParsedXmlSnippetInstruction("?>")
+ end ,
+ ["@cm@"] = function(e,handler)
+ ParsedXmlSnippetComment("<!--")
+ write(e.dt[1])
+ ParsedXmlSnippetComment("-->")
+ end,
+ ["@cd@"] = function(e,handler)
+ ParsedXmlSnippetCdata("<![CDATA[")
+ write(e.dt[1])
+ ParsedXmlSnippetCdata("]]>")
+ end,
+ ["@dt@"] = function(e,handler)
+ ParsedXmlSnippetDoctype("<!DOCTYPE")
+ write(e.dt[1])
+ ParsedXmlSnippetDoctype(">")
+ end,
+ ["@tx@"] = function(s,handler)
+ write(s)
+ end,
+ }
+}
+
+local function parsedxml(root,pattern)
+ if root then
+ if pattern then
+ root = xml.filter(root,pattern)
+ end
+ if root then
+ context.startParsedXmlSnippet()
+ xml.serialize(root,parsedxmlhandler)
+ context.stopParsedXmlSnippet()
+ end
+ end
+end
+
+local function parser(str,settings)
+ parsedxml(xml.convert(str),settings and settings.pattern)
+end
+
+visualizers.parsedxml = parsedxml -- for use at the lua end (maybe namespace needed)
+
+visualizers.register("parsed-xml", { parser = parser } )
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.mkiv
new file mode 100644
index 00000000000..bd348a67dd8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-parsed-xml.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=buff-imp-parsed-xml,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=Parsed \XML,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: color specific elements
+
+\registerctxluafile{buff-imp-parsed-xml.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [ParsedXmlSnippet]
+ [%\c!before=\blank,
+ %\c!after=\blank,
+ \c!style=\tt]
+
+\definestartstop
+ [ParsedXmlSnippetDocType]
+ [\c!style=boldface,
+ \c!color=darkgreen]
+
+\definestartstop
+ [ParsedXmlSnippetElement]
+ [\c!style=boldface,
+ \c!color=darkblue]
+
+\definestartstop
+ [ParsedXmlSnippetInstruction]
+ [\c!style=boldface,
+ \c!color=darkgreen]
+
+\definestartstop
+ [ParsedXmlSnippetCdata]
+ [\c!style=boldface,
+ \c!color=darkgreen]
+
+\definestartstop
+ [ParsedXmlSnippetComment]
+ [\c!style=boldface,
+ \c!color=darkgreen]
+
+\definestartstop
+ [ParsedXmlSnippetKey]
+ [\c!style=boldface,
+ \c!color=darkred]
+
+% \definestartstop
+% [ParsedXmlSnippetQuote]
+% [\c!style=,
+% \c!color=]
+
+\definestartstop
+ [ParsedXmlSnippetValue]
+ [\c!style=,
+ \c!color=]
+
+\definetyping
+ [PARSEDXML]
+ [option=parsed-xml]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.lua
new file mode 100644
index 00000000000..097dff21246
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.lua
@@ -0,0 +1,132 @@
+if not modules then modules = { } end modules ['buff-imp-tex'] = {
+ version = 1.001,
+ comment = "companion to v-tex.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- needs an update, use mult-low
+
+local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
+
+local context = context
+local verbatim = context.verbatim
+local makepattern = visualizers.makepattern
+local makenested = visualizers.makenested
+local getvisualizer = visualizers.getvisualizer
+
+local TexSnippet = context.TexSnippet
+local startTexSnippet = context.startTexSnippet
+local stopTexSnippet = context.stopTexSnippet
+
+local TexSnippetName = verbatim.TexSnippetName
+local TexSnippetGroup = verbatim.TexSnippetGroup
+local TexSnippetBoundary = verbatim.TexSnippetBoundary
+local TexSnippetSpecial = verbatim.TexSnippetSpecial
+local TexSnippetComment = verbatim.TexSnippetComment
+
+local handler = visualizers.newhandler {
+ startinline = function() TexSnippet(false,"{") end,
+ stopinline = function() context("}") end,
+ startdisplay = function() startTexSnippet() end,
+ stopdisplay = function() stopTexSnippet() end ,
+ name = function(s) TexSnippetName(s) end,
+ group = function(s) TexSnippetGroup(s) end,
+ boundary = function(s) TexSnippetBoundary(s) end,
+ special = function(s) TexSnippetSpecial(s) end,
+ comment = function(s) TexSnippetComment(s) end,
+}
+
+-- todo: unicode letters in control sequences (slow as we need to test the nature)
+
+local comment = S("%")
+local name = P("\\") * (patterns.letter + S("@!?_"))^1
+local escape = P("\\") * (patterns.anything - patterns.newline)^-1 -- else we get \n
+local group = S("${}")
+local boundary = S('[]()<>#="')
+local special = S("/^_-&+'`|")
+
+local p_comment = makepattern(handler,"comment",comment)
+ * (V("space") + V("content"))^0
+local p_name = makepattern(handler,"name",name)
+local p_escape = makepattern(handler,"name",escape)
+local p_group = makepattern(handler,"group",group)
+local p_boundary = makepattern(handler,"boundary",boundary)
+local p_special = makepattern(handler,"special",special)
+local p_somespace = V("newline") * V("emptyline")^0 * V("beginline")
+ + V("space")
+
+--~ local pattern = visualizers.pattern
+
+local grammar = visualizers.newgrammar("default", { "visualizer",
+
+ comment = p_comment,
+ name = p_name,
+ escape = p_escape,
+ group = p_group,
+ boundary = p_boundary,
+ special = p_special,
+ somespace = p_somespace,
+
+ pattern = V("comment")
+ + V("name") + V("escape") + V("group") + V("boundary") + V("special")
+ + V("newline") * V("emptyline")^0 * V("beginline")
+ + V("space")
+ + V("default"),
+
+ visualizer = V("pattern")^1
+
+} )
+
+local parser = P(grammar)
+
+visualizers.register("tex", { parser = parser, handler = handler, grammar = grammar } )
+
+local function makecommand(handler,how,start,left,right)
+ local c, l, r, f = P(start), P(left), P(right), how
+ local n = ( P { l * ((1 - (l + r)) + V(1))^0 * r } + P(1-r) )^0
+ if type(how) == "string" then
+ f = function(s) getvisualizer(how,"direct")(s) end
+ end
+ return makepattern(handler,"name",c)
+ * V("somespace")^0
+ * makepattern(handler,"group",l)
+ * (n/f)
+ * makepattern(handler,"group",r)
+end
+
+local grammar = visualizers.newgrammar("default", { "visualizer",
+
+ comment = p_comment,
+ name = p_name,
+ escape = p_escape,
+ group = p_group,
+ boundary = p_boundary,
+ special = p_special,
+ somespace = p_somespace,
+
+ mpcode = makenested(handler,"mp","\\startMPcode","\\stopMPcode")
+ + makenested(handler,"mp","\\startMPgraphic","\\stopMPgraphic")
+ + makenested(handler,"mp","\\startuseMPgraphic","\\stopuseMPgraphic")
+ + makenested(handler,"mp","\\startreusableMPgraphic","\\stopreusableMPgraphic")
+ + makenested(handler,"mp","\\startuniqueMPgraphic","\\stopuniqueMPgraphic")
+ + makenested(handler,"mp","\\startMPpage","\\stopMPpage"),
+
+ luacode = makenested (handler,"lua","\\startluacode","\\stopluacode")
+ + makecommand(handler,"lua","\\ctxlua","{","}"),
+
+ pattern = V("comment")
+ + V("mpcode") + V("luacode")
+ + V("name") + V("escape") + V("group") + V("boundary") + V("special")
+ + V("newline") * V("emptyline")^0 * V("beginline")
+ + V("space")
+ + V("default"),
+
+ visualizer = V("pattern")^1
+
+} )
+
+local parser = P(grammar)
+
+visualizers.register("context", { parser = parser, handler = handler, grammar = grammar } )
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.mkiv
new file mode 100644
index 00000000000..c582523d53b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-tex.mkiv
@@ -0,0 +1,82 @@
+%D \module
+%D [ file=buff-imp-tex,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=\TEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-tex.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [TexSnippet]
+ [DefaultSnippet]
+
+\definestartstop
+ [TexSnippetName]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [TexSnippetGroup]
+ [\c!color=darkred,
+ \c!style=boldface]
+
+\definestartstop
+ [TexSnippetBoundary]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [TexSnippetSpecial]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definestartstop
+ [TexSnippetComment]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definetyping
+ [TEX]
+ [\c!option=tex]
+
+\protect \endinput
+
+% needs thinking ... (esp outer start/stop)
+%
+% \definestartstop
+% [TexSnippet]
+% [DefaultSnippet]
+%
+% \definevisualizer
+% [TexSnippetName]
+% [\c!color=darkgreen,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetGroup]
+% [\c!color=darkred,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetBoundary]
+% [\c!color=darkblue,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetSpecial]
+% [\c!color=darkyellow,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetComment]
+% [\c!color=darkyellow,
+% \c!style=boldface]
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.lua
new file mode 100644
index 00000000000..0c48ed3b090
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.lua
@@ -0,0 +1,133 @@
+if not modules then modules = { } end modules ['buff-imp-xml'] = {
+ version = 1.001,
+ comment = "companion to v-xml.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
+
+local context = context
+local verbatim = context.verbatim
+local makepattern = visualizers.makepattern
+
+local XmlSnippet = context.XmlSnippet
+local startXmlSnippet = context.startXmlSnippet
+local stopXmlSnippet = context.stopXmlSnippet
+
+local XmlSnippetName = verbatim.XmlSnippetName
+local XmlSnippetKey = verbatim.XmlSnippetKey
+local XmlSnippetBoundary = verbatim.XmlSnippetBoundary
+local XmlSnippetString = verbatim.XmlSnippetString
+local XmlSnippetEqual = verbatim.XmlSnippetEqual
+local XmlSnippetEntity = verbatim.XmlSnippetEntity
+local XmlSnippetComment = verbatim.XmlSnippetComment
+local XmlSnippetCdata = verbatim.XmlSnippetCdata
+
+local handler = visualizers.newhandler {
+ startinline = function() XmlSnippet(false,"{") end,
+ stopinline = function() context("}") end,
+ startdisplay = function() startXmlSnippet() end,
+ stopdisplay = function() stopXmlSnippet () end,
+ name = function(s) XmlSnippetName(s) end,
+ key = function(s) XmlSnippetKey(s) end,
+ boundary = function(s) XmlSnippetBoundary(s) end,
+ string = function(s) XmlSnippetString(s) end,
+ equal = function(s) XmlSnippetEqual(s) end,
+ entity = function(s) XmlSnippetEntity(s) end,
+ comment = function(s) XmlSnippetComment(s) end,
+ cdata = function(s) XmlSnippetCdata(s) end,
+}
+
+local comment = P("--")
+local name = (patterns.letter + patterns.digit + S('_-.'))^1
+local entity = P("&") * (1-P(";"))^1 * P(";")
+local openbegin = P("<")
+local openend = P("</")
+local closebegin = P("/>") + P(">")
+local closeend = P(">")
+local opencomment = P("<!--")
+local closecomment = P("-->")
+local openinstruction = P("<?")
+local closeinstruction = P("?>")
+local opencdata = P("<![CDATA[")
+local closecdata = P("]]>")
+
+local grammar = visualizers.newgrammar("default", { "visualizer",
+ sstring =
+ makepattern(handler,"string",patterns.dquote)
+ * (V("whitespace") + makepattern(handler,"default",1-patterns.dquote))^0
+ * makepattern(handler,"string",patterns.dquote),
+ dstring =
+ makepattern(handler,"string",patterns.squote)
+ * (V("whitespace") + makepattern(handler,"default",1-patterns.squote))^0
+ * makepattern(handler,"string",patterns.squote),
+ entity =
+ makepattern(handler,"entity",entity),
+ name =
+ makepattern(handler,"name",name)
+ * (
+ makepattern(handler,"default",patterns.colon)
+ * makepattern(handler,"name",name)
+ )^0,
+ key =
+ makepattern(handler,"key",name)
+ * (
+ makepattern(handler,"default",patterns.colon)
+ * makepattern(handler,"key",name)
+ )^0,
+ attributes = (
+ V("optionalwhitespace")
+ * V("key")
+ * V("optionalwhitespace")
+ * makepattern(handler,"equal",patterns.equal)
+ * V("optionalwhitespace")
+ * (V("dstring") + V("sstring"))
+ * V("optionalwhitespace")
+ )^0,
+ open =
+ makepattern(handler,"boundary",openbegin)
+ * V("name")
+ * V("optionalwhitespace")
+ * V("attributes")
+ * makepattern(handler,"boundary",closebegin),
+ close =
+ makepattern(handler,"boundary",openend)
+ * V("name")
+ * V("optionalwhitespace")
+ * makepattern(handler,"boundary",closeend),
+ comment =
+ makepattern(handler,"boundary",opencomment)
+ * (V("whitespace") + makepattern(handler,"comment",(1-closecomment)^1))^0 -- slow
+ * makepattern(handler,"boundary",closecomment),
+ cdata =
+ makepattern(handler,"boundary",opencdata)
+ * (V("whitespace") + makepattern(handler,"comment",(1-closecdata)^1))^0 -- slow
+ * makepattern(handler,"boundary",closecdata),
+ instruction =
+ makepattern(handler,"boundary",openinstruction)
+ * V("name")
+ * V("optionalwhitespace")
+ * V("attributes")
+ * V("optionalwhitespace")
+ * makepattern(handler,"boundary",closeinstruction),
+
+ pattern =
+ V("comment")
+ + V("instruction")
+ + V("cdata")
+ + V("close")
+ + V("open")
+ + V("entity")
+ + V("space")
+ + V("line")
+ + V("default"),
+
+ visualizer =
+ V("pattern")^1
+} )
+
+local parser = P(grammar)
+
+visualizers.register("xml", { parser = parser, handler = handler, grammar = grammar } )
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.mkiv
new file mode 100644
index 00000000000..f880ab88225
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-xml.mkiv
@@ -0,0 +1,71 @@
+%D \module
+%D [ file=buff-imp-xml,
+%D version=2010.10.19,
+%D title=\CONTEXT\ Visualizer Macros,
+%D subtitle=\XML,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{buff-imp-xml.lua}{1.001}
+
+\unprotect
+
+\definestartstop
+ [XmlSnippet]
+ [DefaultSnippet]
+
+\definestartstop
+ [XmlSnippetName]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetKey]
+ [\c!color=darkgreen,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetBoundary]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetEntity]
+ [\c!color=darkred,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetString]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetEqual]
+ [\c!color=darkblue,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetComment]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetCdata]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definestartstop
+ [XmlSnippetInstruction]
+ [\c!color=darkyellow,
+ \c!style=boldface]
+
+\definetyping
+ [XML]
+ [\c!option=xml]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua
new file mode 100644
index 00000000000..c41c516073b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua
@@ -0,0 +1,607 @@
+if not modules then modules = { } end modules ['buff-ini'] = {
+ version = 1.001,
+ comment = "companion to buff-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+local type, next, load = type, next, load
+local sub, format = string.sub, string.format
+local splitlines, validstring, replacenewlines = string.splitlines, string.valid, string.replacenewlines
+local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match
+local utfchar = utf.char
+local totable = string.totable
+
+local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end)
+local trace_grab = false trackers.register("buffers.grab", function(v) trace_grab = v end)
+local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
+
+local report_buffers = logs.reporter("buffers","usage")
+local report_typeset = logs.reporter("buffers","typeset")
+local report_grabbing = logs.reporter("buffers","grabbing")
+
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local scanners = tokens.scanners
+local scanstring = scanners.string
+local scaninteger = scanners.integer
+local scanboolean = scanners.boolean
+local scancode = scanners.code
+local scantoken = scanners.token
+
+local getters = tokens.getters
+local gettoken = getters.token
+
+local compilescanner = tokens.compile
+local scanners = interfaces.scanners
+
+local variables = interfaces.variables
+local settings_to_array = utilities.parsers.settings_to_array
+local formatters = string.formatters
+local addsuffix = file.addsuffix
+local replacesuffix = file.replacesuffix
+
+local registertempfile = luatex.registertempfile
+
+local v_yes = variables.yes
+
+local eol = patterns.eol
+local space = patterns.space
+local whitespace = patterns.whitespace
+local blackspace = whitespace - eol
+local whatever = (1-eol)^1 * eol^0
+local emptyline = space^0 * eol
+
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+
+buffers = buffers or { }
+local buffers = buffers
+
+local cache = { }
+
+local function erase(name)
+ cache[name] = nil
+end
+
+local function assign(name,str,catcodes)
+ cache[name] = {
+ data = str,
+ catcodes = catcodes,
+ typeset = false,
+ }
+end
+
+local function combine(name,str,prepend)
+ local buffer = cache[name]
+ if buffer then
+ buffer.data = prepend and (str .. buffer.data) or (buffer.data .. str)
+ buffer.typeset = false
+ else
+ cache[name] = {
+ data = str,
+ typeset = false,
+ }
+ end
+end
+
+local function prepend(name,str)
+ combine(name,str,true)
+end
+
+local function append(name,str)
+ combine(name,str)
+end
+
+local function exists(name)
+ return cache[name]
+end
+
+local function getcontent(name)
+ local buffer = name and cache[name]
+ return buffer and buffer.data or ""
+end
+
+local function getlines(name)
+ local buffer = name and cache[name]
+ return buffer and splitlines(buffer.data)
+end
+
+local function getnames(name)
+ if type(name) == "string" then
+ return settings_to_array(name)
+ else
+ return name
+ end
+end
+
+local function istypeset(name)
+ local names = getnames(name)
+ if #names == 0 then
+ return false
+ end
+ for i=1,#names do
+ local c = cache[names[i]]
+ if c and not c.typeset then
+ return false
+ end
+ end
+ return true
+end
+
+local function markastypeset(name)
+ local names = getnames(name)
+ for i=1,#names do
+ local c = cache[names[i]]
+ if c then
+ c.typeset = true
+ end
+ end
+end
+
+local function collectcontent(name,separator) -- no print
+ local names = getnames(name)
+ local nnames = #names
+ if nnames == 0 then
+ return getcontent("") -- default buffer
+ elseif nnames == 1 then
+ return getcontent(names[1])
+ else
+ local t, n = { }, 0
+ for i=1,nnames do
+ local c = getcontent(names[i])
+ if c ~= "" then
+ n = n + 1
+ t[n] = c
+ end
+ end
+ -- the default separator was \r, then \n and is now os.newline because buffers
+ -- can be loaded in other applications
+ return concat(t,separator or os.newline)
+ end
+end
+
+local function loadcontent(name) -- no print
+ local content = collectcontent(name,"\n") -- tex likes \n
+ local ok, err = load(content)
+ if ok then
+ return ok()
+ else
+ report_buffers("invalid lua code in buffer %a: %s",name,err or "unknown error")
+ end
+end
+
+buffers.raw = getcontent
+buffers.erase = erase
+buffers.assign = assign
+buffers.prepend = prepend
+buffers.append = append
+buffers.exists = exists
+buffers.getcontent = getcontent
+buffers.getlines = getlines
+buffers.collectcontent = collectcontent
+buffers.loadcontent = loadcontent
+
+-- the context interface
+
+implement {
+ name = "assignbuffer",
+ actions = assign,
+ arguments = { "string", "string", "integer" }
+}
+
+implement {
+ name = "erasebuffer",
+ actions = erase,
+ arguments = "string"
+}
+
+local anything = patterns.anything
+local alwaysmatched = patterns.alwaysmatched
+local utf8character = patterns.utf8character
+
+local function countnesting(b,e)
+ local n
+ local g = P(b) / function() n = n + 1 end
+ + P(e) / function() n = n - 1 end
+ -- + anything
+ + utf8character
+ local p = alwaysmatched / function() n = 0 end
+ * g^0
+ * alwaysmatched / function() return n end
+ return p
+end
+
+local counters = { }
+local nesting = 0
+local autoundent = true
+local continue = false
+
+-- Beware: the first character of bufferdata has to be discarded as it's there to
+-- prevent gobbling of newlines in the case of nested buffers. The last one is
+-- a newlinechar and is removed too.
+--
+-- An \n is unlikely to show up as \r is the endlinechar but \n is more generic
+-- for us.
+
+-- This fits the way we fetch verbatim: the indentation before the sentinel
+-- determines the stripping.
+
+-- str = [[
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+--
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+-- ]]
+
+-- local function undent(str)
+-- local margin = match(str,"[\n\r]( +)[\n\r]*$") or ""
+-- local indent = #margin
+-- if indent > 0 then
+-- local lines = splitlines(str)
+-- local ok = true
+-- local pattern = "^" .. margin
+-- for i=1,#lines do
+-- local l = lines[i]
+-- if find(l,pattern) then
+-- lines[i] = sub(l,indent+1)
+-- else
+-- ok = false
+-- break
+-- end
+-- end
+-- if ok then
+-- return concat(lines,"\n")
+-- end
+-- end
+-- return str
+-- end
+
+-- how about tabs
+
+local strippers = { }
+local nofspaces = 0
+
+local normalline = space^0 / function(s) local n = #s if n < nofspaces then nofspaces = n end end
+ * whatever
+
+local getmargin = (emptyline + normalline)^1
+
+local function undent(str) -- new version, needs testing: todo: not always needed, like in xtables
+ nofspaces = #str
+ local margin = lpegmatch(getmargin,str)
+ if nofspaces == #str or nofspaces ==0 then
+ return str
+ end
+ local stripper = strippers[nofspaces]
+ if not stripper then
+ stripper = Cs(((space^-nofspaces)/"" * whatever + emptyline)^1)
+ strippers[nofspaces] = stripper
+ end
+ return lpegmatch(stripper,str) or str
+end
+
+buffers.undent = undent
+
+-- function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes,doundent) -- maybe move \\ to call
+-- local dn = getcontent(name)
+-- if dn == "" then
+-- nesting = 0
+-- continue = false
+-- end
+-- if trace_grab then
+-- if #bufferdata > 30 then
+-- report_grabbing("%s => |%s..%s|",name,sub(bufferdata,1,10),sub(bufferdata,-10,#bufferdata))
+-- else
+-- report_grabbing("%s => |%s|",name,bufferdata)
+-- end
+-- end
+-- local counter = counters[begintag]
+-- if not counter then
+-- counter = countnesting(begintag,endtag)
+-- counters[begintag] = counter
+-- end
+-- nesting = nesting + lpegmatch(counter,bufferdata)
+-- local more = nesting > 0
+-- if more then
+-- dn = dn .. sub(bufferdata,2,-1) .. endtag
+-- nesting = nesting - 1
+-- continue = true
+-- else
+-- if continue then
+-- dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+-- elseif dn == "" then
+-- dn = sub(bufferdata,2,-2)
+-- else
+-- dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+-- end
+-- local last = sub(dn,-1)
+-- if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar
+-- dn = sub(dn,1,-2)
+-- end
+-- if doundent or (autoundent and doundent == nil) then
+-- dn = undent(dn)
+-- end
+-- end
+-- assign(name,dn,catcodes)
+-- commands.doifelse(more)
+-- end
+
+function tokens.pickup(start,stop)
+ local stoplist = totable(stop)
+ local stoplength = #stoplist
+ local stoplast = stoplist[stoplength]
+ local startlist = totable(start)
+ local startlength = #startlist
+ local startlast = startlist[startlength]
+ local list = { }
+ local size = 0
+ local depth = 0
+-- local done = 32
+ while true do -- or use depth
+ local char = scancode()
+ if char then
+-- if char < done then
+-- -- we skip leading control characters so that we can use them to
+-- -- obey spaces (a dirty trick)
+-- else
+-- done = 0
+ char = utfchar(char)
+ size = size + 1
+ list[size] = char
+ if char == stoplast and size >= stoplength then
+ local done = true
+ local last = size
+ for i=stoplength,1,-1 do
+ if stoplist[i] ~= list[last] then
+ done = false
+ break
+ end
+ last = last - 1
+ end
+ if done then
+ if depth > 0 then
+ depth = depth - 1
+ else
+ break
+ end
+ char = false -- trick: let's skip the next (start) test
+ end
+ end
+ if char == startlast and size >= startlength then
+ local done = true
+ local last = size
+ for i=startlength,1,-1 do
+ if startlist[i] ~= list[last] then
+ done = false
+ break
+ end
+ last = last - 1
+ end
+ if done then
+ depth = depth + 1
+ end
+ end
+-- end
+ else
+ -- local t = scantoken()
+ local t = gettoken()
+ if t then
+ -- we're skipping leading stuff, like obeyedlines and relaxes
+ else
+ break
+ end
+ end
+ end
+ local start = 1
+ local stop = size-stoplength-1
+ -- not good enough: only empty lines, but even then we miss the leading
+ -- for verbatim
+ for i=start,stop do
+ local li = list[i]
+ if lpegmatch(blackspace,li) then
+ -- keep going
+ elseif lpegmatch(eol,li) then
+ -- okay
+ start = i + 1
+ else
+ break
+ end
+ end
+ for i=stop,start,-1 do
+ if lpegmatch(whitespace,list[i]) then
+ stop = i - 1
+ else
+ break
+ end
+ end
+ if start <= stop then
+ return concat(list,"",start,stop)
+ else
+ return ""
+ end
+end
+
+-- function buffers.pickup(name,start,stop,finish,catcodes,doundent)
+-- local data = tokens.pickup(start,stop)
+-- if doundent or (autoundent and doundent == nil) then
+-- data = buffers.undent(data)
+-- end
+-- buffers.assign(name,data,catcodes)
+-- context(finish)
+-- end
+
+-- commands.pickupbuffer = buffers.pickup
+
+scanners.pickupbuffer = function()
+ local name = scanstring()
+ local start = scanstring()
+ local stop = scanstring()
+ local finish = scanstring()
+ local catcodes = scaninteger()
+ local doundent = scanboolean()
+ local data = tokens.pickup(start,stop)
+ if doundent or (autoundent and doundent == nil) then
+ data = undent(data)
+ end
+ buffers.assign(name,data,catcodes)
+ -- context[finish]()
+ context(finish)
+end
+
+local function savebuffer(list,name,prefix) -- name is optional
+ if not list or list == "" then
+ list = name
+ end
+ if not name or name == "" then
+ name = list
+ end
+ local content = collectcontent(list,nil) or ""
+ if content == "" then
+ content = "empty buffer"
+ end
+ if prefix == v_yes then
+ name = addsuffix(tex.jobname .. "-" .. name,"tmp")
+ end
+ io.savedata(name,replacenewlines(content))
+end
+
+implement {
+ name = "savebuffer",
+ actions = savebuffer,
+ arguments = { "string", "string", "string" }
+}
+
+-- we can consider adding a size to avoid unlikely clashes
+
+local oldhashes = nil
+local newhashes = nil
+
+local function runbuffer(name,encapsulate)
+ if not oldhashes then
+ oldhashes = job.datasets.getdata("typeset buffers","hashes") or { }
+ for hash, n in next, oldhashes do
+ local tag = formatters["%s-t-b-%s"](tex.jobname,hash)
+ registertempfile(addsuffix(tag,"tmp")) -- to be sure
+ registertempfile(addsuffix(tag,"pdf"))
+ end
+ newhashes = { }
+ job.datasets.setdata {
+ name = "typeset buffers",
+ tag = "hashes",
+ data = newhashes,
+ }
+ end
+ local names = getnames(name)
+ local content = collectcontent(names,nil) or ""
+ if content == "" then
+ content = "empty buffer"
+ end
+ if encapsulate then
+ content = formatters["\\starttext\n%s\n\\stoptext\n"](content)
+ end
+ --
+ local hash = md5.hex(content)
+ local tag = formatters["%s-t-b-%s"](tex.jobname,hash)
+ --
+ local filename = addsuffix(tag,"tmp")
+ local resultname = addsuffix(tag,"pdf")
+ --
+ if newhashes[hash] then
+ -- done
+ elseif not oldhashes[hash] or not lfs.isfile(resultname) then
+ if trace_run then
+ report_typeset("changes in %a, processing forced",name)
+ end
+ io.savedata(filename,content)
+ local command = formatters["context --purgeall %s %s"](jit and "--jit" or "",filename)
+ report_typeset("running: %s\n",command)
+ os.execute(command)
+ end
+ newhashes[hash] = (newhashes[hash] or 0) + 1
+ report_typeset("no changes in %a, processing skipped",name)
+ registertempfile(filename)
+ registertempfile(resultname,nil,true)
+ --
+ return resultname
+end
+
+local function getbuffer(name)
+ local str = getcontent(name)
+ if str ~= "" then
+ -- characters.showstring(str)
+ context.viafile(str,formatters["buffer.%s"](validstring(name,"noname")))
+ end
+end
+
+local function getbuffermkvi(name) -- rather direct !
+ context.viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname")))
+end
+
+local function gettexbuffer(name)
+ local buffer = name and cache[name]
+ if buffer and buffer.data ~= "" then
+ context.pushcatcodetable()
+ if buffer.catcodes == txtcatcodes then
+ context.setcatcodetable(txtcatcodes)
+ else
+ context.setcatcodetable(ctxcatcodes)
+ end
+ -- context(function() context.viafile(buffer.data) end)
+ context.getbuffer { name } -- viafile flushes too soon
+ context.popcatcodetable()
+ end
+end
+
+implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" }
+implement { name = "getbuffer", actions = getbuffer, arguments = "string" }
+implement { name = "getbuffermkvi", actions = getbuffermkvi, arguments = "string" }
+implement { name = "gettexbuffer", actions = gettexbuffer, arguments = "string" }
+
+implement {
+ name = "runbuffer",
+ actions = { runbuffer, context },
+ arguments = { "string", true }
+}
+
+implement {
+ name = "doifelsebuffer",
+ actions = { exists, commands.doifelse },
+ arguments = "string"
+}
+
+-- This only used for mp buffers and is a kludge. Don't change the
+-- texprint into texsprint as it fails because "p<nl>enddef" becomes
+-- "penddef" then.
+
+implement {
+ name = "feedback", -- bad name, maybe rename to injectbuffercontent
+ actions = { collectcontent, context.printlines },
+ arguments = "string"
+}
+
+local startbuffer = context.startbuffer
+local stopbuffer = context.stopbuffer
+
+local startcollecting = context.startcollecting
+local stopcollecting = context.stopcollecting
+
+function context.startbuffer(...)
+ startcollecting()
+ startbuffer(...)
+end
+
+function context.stopbuffer()
+ stopbuffer()
+ stopcollecting()
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv
new file mode 100644
index 00000000000..7cc6cdbd4f2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv
@@ -0,0 +1,301 @@
+%D \module
+%D [ file=buff-ini,
+%D version=2011.11.22, % previous big effort 2000.01.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Buffers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Buffer Macros / Buffers}
+
+\registerctxluafile{buff-ini}{1.001}
+
+\unprotect
+
+% number is messy and not needed as we store the number anyway
+% we can get rid of \c!number
+
+\let\currentbuffer\empty
+
+\def\doifelsebuffer#1%
+ {\clf_doifelsebuffer{#1}}
+
+\let\doifbufferelse\doifelsebuffer
+
+\unexpanded\def\resetbuffer
+ {\dosingleempty\buff_reset}
+
+\def\buff_reset[#1]%
+ {\clf_erasebuffer{#1}}
+
+\setuvalue{\e!start\v!buffer}%
+ {\begingroup % (3)
+ \obeylines
+ \dodoubleempty\buff_start}
+
+\def\buff_start[#1][#2]%
+ {\buff_start_indeed{}{#1}{\e!start\v!buffer}{\e!stop\v!buffer}}
+
+% \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}}
+
+\unexpanded\def\grabbufferdata % was: \dostartbuffer
+ {\begingroup % (4)
+ \obeylines
+ \doquadrupleempty\buff_grab_direct_indeed}
+
+\unexpanded\def\grabbufferdatadirect % name start stop
+ {\begingroup % (6)
+ \buff_start_indeed\empty}
+
+\def\buff_grab_direct_indeed % [category] [name] [start] [stop]
+ {\iffourthargument
+ \expandafter\buff_grab_direct_indeed_a
+ \else
+ \expandafter\buff_grab_direct_indeed_b
+ \fi}
+
+\def\buff_grab_direct_indeed_a[#1][#2][#3][#4]{\buff_start_indeed {#1}{#2}{#3}{#4}}
+\def\buff_grab_direct_indeed_b[#1][#2][#3][#4]{\buff_start_indeed\empty{#1}{#2}{#3}}
+
+\let\buff_finish\relax
+\let\buff_gobble\relax
+
+% \unexpanded\def\buff_pickup#1#2#3#4#5#6% name, startsequence, stopsequence, before, after, undent
+% {\begingroup % (1)
+% #4%
+% \begingroup % (2)
+% \edef\catcodetableofbuffer{\number\catcodetable}%
+% \clf_erasebuffer{#1}%
+% \setcatcodetable\vrbcatcodes
+% \def\buff_finish
+% {\endgroup % (1)
+% \endgroup % (2)
+% #5}%
+% \def\buff_gobble##1#3% is detokenize needed? TEST
+% %{\ctxcommand{grabbuffer("#1","#2","#3",\!!bs\detokenize{##1}\!!es)} % space ?
+% {\ctxcommand{grabbuffer("#1","#2","#3",\!!bs>##1\!!es,\catcodetableofbuffer,\ifnum#6=\plusone true\else false\fi)}% space ?
+% \buff_gobble
+% \buff_finish}%
+% \buff_gobble}
+
+% % \def\startgrab
+% % {\begingroup
+% % \setcatcodetable\vrbcatcodes
+% % \ctxlua{tokens.pickup("\\startgrab","\\stopgrab") context("\\endgroup")}}
+% %
+% % \def\stopgrab
+% % {}
+
+\unexpanded\def\buff_pickup#1#2#3#4#5#6% name, startsequence, stopsequence, before, after, undent
+ {\begingroup % (1)
+ #4%
+ \begingroup % (2)
+ \scratchcounter\catcodetable
+ \clf_erasebuffer{#1}%
+ \setcatcodetable\vrbcatcodes
+ \unexpanded\def\dofinishpickupbuffer
+ {\endgroup % (1)
+ \endgroup % (2)
+ #5}%
+ % todo: we need to skip the first lineending which is na active character
+ % but sometimes we have something different ... this is a side effect of
+ % checking for optional arguments i.e. the next token is already tokenized
+ % and for that reason we have the \relax as well as the \string
+ \clf_pickupbuffer
+ {#1}%
+ {#2}%
+ {#3}%
+ {\string\dofinishpickupbuffer}%
+ \scratchcounter
+ \ifnum#6=\plusone\s!true\else\s!false\fi
+ % \relax}
+ \expandafter\relax\string} % maybe \normalexpanded{\relax\utfchar{7}}} signal
+
+\unexpanded\def\buff_stop#1%
+ {\endgroup % (3 & 4 & 5 & 6)
+ \csname#1\endcsname}
+
+% \installctxfunction\dopickupbuffer{commands.dopickupbuffer}
+
+\unexpanded\def\setbuffer
+ {\dosingleempty\buff_set}
+
+\let\endbuffer\relax
+
+\def\buff_set[#1]#2\endbuffer % seldom used so we just pass #2
+ {\clf_assignbuffer{#1}{\detokenize{#2}}\catcodetable\relax}
+
+% beware, never adapt the global buffer settings, actually we might introduce
+% a broken parent chain for this purpose but on the other hand it's not that
+% different from framed cum suis
+
+\installcorenamespace{buffer}
+
+\installcommandhandler \??buffer {buffer} \??buffer
+
+\setupbuffer
+ [\c!before=,
+ \c!after=]
+
+\newcount\c_buff_n_of_defined
+
+\let\currentdefinedbuffer\s!dummy
+
+\appendtoks
+ \global\advance\c_buff_n_of_defined\plusone
+ \setexpandedbufferparameter\c!number{\number\c_buff_n_of_defined}%
+ \edef\currentdefinedbuffer{def-\number\c_buff_n_of_defined}%
+ \setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}%
+ \setuevalue{\e!get\currentbuffer }{\buff_get_stored{\currentbuffer}{\currentdefinedbuffer}}%
+\to \everydefinebuffer
+
+\unexpanded\def\buff_start_defined
+ {\begingroup % (5)
+ \buff_start_indeed}
+
+\def\thebuffernumber #1{\namedbufferparameter{#1}\c!number}
+\def\thedefinedbuffer#1{def-\namedbufferparameter{#1}\c!number}
+
+\unexpanded\def\getbuffer % no [settings yet]
+ {\dosingleempty\buff_get}
+
+\unexpanded\def\buff_get[#1]% [name]
+ {\namedbufferparameter\empty\c!before
+ \doifelsenothing{#1}
+ {\buff_get_stored_indeed\empty}
+ {\processcommalist[#1]\buff_get_stored_indeed}%
+ \namedbufferparameter\empty\c!after}
+
+\unexpanded\def\buff_get_stored#1#2%
+ {\namedbufferparameter{#1}\c!before
+ \buff_get_stored_indeed{#2}%
+ \namedbufferparameter{#1}\c!after}
+
+\unexpanded\def\buff_get_stored_indeed#1%
+ {\clf_getbuffer{#1}}
+
+\unexpanded\def\getdefinedbuffer[#1]%
+ {\buff_get_stored{#1}{\thedefinedbuffer{#1}}}%
+
+\unexpanded\def\inlinebuffer
+ {\dosingleempty\buff_get_inline}
+
+\unexpanded\def\buff_get_inline[#1]% [name]
+ {\doifelsenothing{#1}
+ {\buff_get_stored_inline_indeed\empty}
+ {\processcommalist[#1]\buff_get_stored_inline_indeed}}
+
+\unexpanded\def\buff_get_stored_inline_indeed#1%
+ {\ignorespaces\clf_getbuffer{#1}\removeunwantedspaces}
+
+\def\rawbuffer#1% expandable
+ {\clf_getbuffer{#1}}
+
+\definebuffer
+ [\v!hiding]
+
+\setupbuffer
+ [\v!hiding]
+ [\c!before=,
+ \c!after=]
+
+\unexpanded\def\processTEXbuffer % keep case, maybe also lower
+ {\dosingleempty\buff_process_tex}
+
+\def\buff_process_tex[#1]%
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes % \setcatcodetable
+ \buff_get_stored_indeed{#1}%
+ \popcatcodetable}
+
+% only mkiv:
+%
+% \startbuffer[x]
+% x
+% \stopbuffer
+%
+% \savebuffer[x] [temp] % gets name: jobname-temp.tmp
+% \savebufferinfile[x][temp.log] % gets name: temp.log
+
+\installcorenamespace{savebuffer}
+
+\installsetuponlycommandhandler \??savebuffer {savebuffer}
+
+\setupsavebuffer
+ [\c!list=,
+ \c!file=,
+ \c!prefix=\v!yes]
+
+\unexpanded\def\savebuffer
+ {\dodoubleempty\buff_save}
+
+\def\buff_save[#1][#2]%
+ {\begingroup
+ \doifelseassignment{#1}
+ {\setupcurrentsavebuffer[#1]}%
+ {\setupcurrentsavebuffer[\c!list={#1},\c!file=#2]}%
+ \clf_savebuffer{\directsavebufferparameter\c!list}{\directsavebufferparameter\c!file}{\directsavebufferparameter\c!prefix}%
+ \endgroup}
+
+%D Experimental: no expansion of commands in buffer!
+
+% \startbuffer[what]
+% context("WHAT")
+% \stopbuffer
+% \startbuffer
+% context("JOBNAME")
+% \stopbuffer
+%
+% \ctxluabuffer[what] \ctxluabuffer
+
+\unexpanded\def\ctxluabuffer {\dosingleempty\buff_ctxlua}
+\unexpanded\def\mkvibuffer {\dosingleempty\buff_mkvi}
+% what was: \mkvibufferraw
+
+\def\buff_ctxlua[#1]{\clf_getbufferctxlua{#1}}
+\def\buff_mkvi [#1]{\clf_getbuffermkvi {#1}}
+
+% used elsewhere
+
+\unexpanded\def\doprocesstexbuffer#1{\buff_process_tex[#1]} % still used?
+
+\let\dostartbuffer\grabbufferdata % for old times sake
+
+% new (expandable):
+
+\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/Master/texmf-dist/tex/context/base/mkiv/buff-par.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-par.lua
new file mode 100644
index 00000000000..58ea9ab9d06
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-par.lua
@@ -0,0 +1,232 @@
+if not modules then modules = { } end modules ['buff-par'] = {
+ version = 1.001,
+ comment = "companion to buff-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, find, gmatch = table.insert, table.remove, string.find, string.gmatch
+local fullstrip, formatters = string.fullstrip, string.formatters
+
+local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
+
+local report_parallel = logs.reporter("buffers","parallel")
+
+local variables = interfaces.variables
+local v_all = variables.all
+
+local parallel = buffers.parallel or { }
+buffers.parallel = parallel
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local context = context
+local implement = interfaces.implement
+
+local data = { }
+
+function parallel.define(category,tags)
+ local tags = settings_to_array(tags)
+ local entries = { }
+ data[category] = {
+ tags = tags,
+ entries = entries,
+ }
+ for i=1,#tags do
+ entries[tags[i]] = {
+ lines = { },
+ number = 0,
+ }
+ end
+end
+
+function parallel.reset(category,tags)
+ if not tags or tags == "" or tags == v_all then
+ tags = table.keys(entries)
+ else
+ tags = settings_to_array(tags)
+ end
+ for i=1,#tags do
+ entries[tags[i]] = {
+ lines = { },
+ number = 0,
+ }
+ end
+end
+
+function parallel.next(category)
+ local dc = data[category]
+ local tags = dc.tags
+ local entries = dc.entries
+ for i=1,#tags do
+ insert(entries[tags[i]].lines, { })
+ end
+end
+
+function parallel.save(category,tag,content,frombuffer)
+ if frombuffer then
+ content = buffers.raw(content)
+ end
+ local dc = data[category]
+ if not dc then
+ report_parallel("unknown category %a",category)
+ return
+ end
+ local entries = dc.entries[tag]
+ if not entries then
+ report_parallel("unknown entry %a",tag)
+ return
+ end
+ local lines = entries.lines
+ if not lines then
+ return
+ end
+ local line = lines[#lines]
+ if not line then
+ return
+ end
+ -- maybe no strip
+ -- use lpeg
+ if find(content,"%s*%[") then
+ local done = false
+ for label, content in gmatch(content,"%s*%[(.-)%]%s*([^%[]+)") do
+ if done then
+ line = { }
+ insert(lines,line)
+ else
+ done = true
+ end
+ if trace_parallel and label ~= "" then
+ report_parallel("reference found of category %a, tag %a, label %a",category,tag,label)
+ end
+ line.content = fullstrip(content)
+ line.label = label
+ end
+ else
+ line.content = fullstrip(content)
+ line.label = ""
+ end
+ -- print("[["..line.content.."]]")
+end
+
+function parallel.hassomecontent(category,tags)
+ local dc = data[category]
+ if not dc then
+ return false
+ end
+ local entries = dc.entries
+ if not tags or tags == "" or tags == v_all then
+ tags = table.keys(entries)
+ else
+ tags = utilities.parsers.settings_to_array(tags)
+ end
+ for t=1,#tags do
+ local tag = tags[t]
+ local lines = entries[tag].lines
+ for i=1,#lines do
+ local content = lines[i].content
+ if content and content ~= "" then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+local ctx_doflushparallel = context.doflushparallel
+local f_content = formatters["\\input{%s}"]
+local save_byscheme = resolvers.savers.byscheme
+
+function parallel.place(category,tags,options)
+ local dc = data[category]
+ if not dc then
+ return
+ end
+ local entries = dc.entries
+ local tags = utilities.parsers.settings_to_array(tags)
+ local options = utilities.parsers.settings_to_hash(options) -- options can be hash too
+ local start = tonumber(options.start)
+ local n = tonumber(options.n)
+ local criterium = options.criterium
+ local max = 1
+ if n then
+ max = n
+ elseif criterium == v_all then
+ max = 0
+ for t=1,#tags do
+ local tag = tags[t]
+ local lines = entries[tag].lines
+ if #lines > max then
+ max = #lines
+ end
+ end
+ end
+ for i=1,max do
+ for t=1,#tags do
+ local tag = tags[t]
+ local entry = entries[tag]
+ if entry then
+ local lines = entry.lines
+ local number = entry.number + 1
+ entry.number = number
+ local line = remove(lines,1)
+ local content = line and line.content
+ local label = line and line.label or ""
+ if content then
+ local virtual = save_byscheme("virtual","parallel",content)
+ ctx_doflushparallel(tag,1,number,label,f_content(virtual))
+ else
+ ctx_doflushparallel(tag,0,number,"","")
+ end
+ end
+ end
+ end
+end
+
+-- interface
+
+implement {
+ name = "defineparallel",
+ actions = parallel.define,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "nextparallel",
+ actions = parallel.next,
+ arguments = "string"
+}
+
+implement {
+ name = "saveparallel",
+ actions = parallel.save,
+ arguments = { "string", "string", "string", true },
+}
+
+implement {
+ name = "placeparallel",
+ actions = parallel.place,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "start" },
+ { "n" },
+ { "criterium" },
+ { "setups" },
+ }
+ }
+}
+
+implement {
+ name = "resetparallel",
+ actions = parallel.reset,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "doifelseparallel",
+ actions = { parallel.hassomecontent, commands.doifelse } ,
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-par.mkvi b/Master/texmf-dist/tex/context/base/mkiv/buff-par.mkvi
new file mode 100644
index 00000000000..b17edb1736c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-par.mkvi
@@ -0,0 +1,167 @@
+%D \module
+%D [ file=buff-par,
+%D version=2010.12.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Parallel,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Buffer Macros / Parallel}
+
+\registerctxluafile{buff-par}{1.001}
+
+%D This module is developped for Thomas Schmitz as part of a project. There is
+%D no documentation yet.
+%D
+%D \starttyping
+%D \defineparallel[main][one,two]
+%D
+%D \startmain
+%D \startone
+%D first 1
+%D [reference] first 2
+%D first 3
+%D \stopone
+%D \starttwo
+%D second 1
+%D \stoptwo
+%D \stopmain
+%D
+%D \placeparallel[main][one,two][criterium=all]
+
+%D criterium=all start=<number> n=<number>
+
+\unprotect
+
+\installcorenamespace{parallel}
+\installcorenamespace{parallelhandler}
+
+\installcommandhandler \??parallel {parallel} \??parallel
+
+\setupparallel
+ [\c!setups=parallel:place:default]
+
+\let\buff_parallel_define_saved\defineparallel
+\let\buff_parallel_setup_saved \setupparallel
+
+\unexpanded\def\defineparallel{\dodoubleargument\buff_parallel_define}
+\unexpanded\def\setupparallel {\dotripleargument\buff_parallel_setup}
+
+\def\buff_parallel_define[#name][#instances]%
+ {\buff_parallel_define_saved[#name][\c!list={#instances}]% list is internal
+ \clf_defineparallel{#name}{#instances}%
+ \expandafter\newtoks\csname\??parallelhandler#name\endcsname
+ \processcommacommand[#instances]{\buff_parallel_define_instance{#name}}%
+ \setuevalue{\e!start#name}{\buff_parallel_start{#name}}%
+ \setuevalue{\e!stop #name}{\buff_parallel_stop}}
+
+\let\buff_process_parallel_instance\relax
+
+\def\buff_process_parallel_instances
+ {\the\csname\??parallelhandler\currentparallel\endcsname}
+
+\def\buff_parallel_define_instance#name#instance%
+ {\normalexpanded{\buff_parallel_define_saved[#instance][#name]}%
+ \definebuffer[#instance]%
+ %\edef\t_buff_parallel{\csname\??parallelhandler#name\endcsname}%
+ \expandafter\let\expandafter\t_buff_parallel\csname\??parallelhandler#name\endcsname
+ \appendtoks
+ \edef\currentparallelinstance{#instance}%
+ \buff_process_parallel_instance\relax
+ \to \t_buff_parallel
+ \setuevalue{\e!stop#instance}{\buff_parallel_save{#instance}}}
+
+\def\buff_parallel_setup[#name][#instances][#setups]%
+ {\processcommalist[#instances]{\buff_parallel_setup_instance{#name}{#setups}}}
+
+\def\buff_parallel_setup_instance#name#setups#instance%
+ {\buff_parallel_setup_saved[#name:#instance][#setups]}
+
+\unexpanded\def\buff_parallel_start#name%
+ {\pushmacro\currentparallel
+ \edef\currentparallel{#name}%
+ \clf_nextparallel{\currentparallel}}
+
+\unexpanded\def\buff_parallel_stop
+ {\popmacro\currentparallel}
+
+\unexpanded\def\buff_parallel_save#instance% defined moet ook aan de lua kant kunnen
+ {\clf_saveparallel
+ {\currentparallel}%
+ {#instance}%
+ {\thedefinedbuffer{#instance}}%
+ \relax}
+
+\unexpanded\def\placeparallel
+ {\dotripleempty\buff_parallel_place}
+
+\def\buff_parallel_place[#name][#instance][#settings]%
+ {\begingroup
+ \edef\currentparallel{#name}%
+ \setupcurrentparallel[#settings]%
+ \clf_placeparallel
+ {\currentparallel}%
+ {#instance}%
+ {%
+ % setups {\parallelparameter\c!setups}%
+ start {\parallelparameter\c!start}%
+ n {\parallelparameter\c!n}%
+ criterium {\parallelparameter\c!criterium}%
+ }%
+ \relax
+ \endgroup}
+
+\def\doflushparallel#instance#status#line#label#content% called at lua end
+ {\begingroup
+ \def\currentparallelinstance{#instance}%
+ \def\currentparallelnumber {#status}%
+ \def\currentparallelline {#line}%
+ \def\currentparallellabel {#label}%
+ \def\currentparallelcontent {#content}% can be kep at the lua end .. no need to use a virtual file
+ \ifcase#status\relax
+ \expandafter\buff_parallel_flush_nop
+ \or
+ \expandafter\buff_parallel_flush_yes
+ \fi
+ \endgroup}
+
+\def\buff_parallel_flush_nop
+ {}
+
+\def\buff_parallel_flush_yes
+ {\directsetup{\namedparallelparameter{\currentparallel:\currentparallelinstance}\c!setups}}
+
+\unexpanded\def\doifelseparallel#name#instance%
+ {\clf_doifelseparallel{#name}{#instance}}
+
+\let\doifparallelelse\doifelseparallel
+
+\unexpanded\def\resetparallel
+ {\dodoubleempty\buff_parallel_reset}
+
+\def\buff_parallel_reset[#name][#instance]%
+ {\clf_resetparallel{#name}{#instance}}
+
+\startsetups parallel:place:default
+ \hangafter\plusone
+ \hangindent4\emwidth
+ \dontleavehmode
+ \hbox to 3\emwidth \bgroup
+ \hss
+ \bf
+ \doifsomething \currentparallellabel {
+ \textreference[\currentparallellabel]{\currentparallelline}
+ }
+ \currentparallelline
+ \quad
+ \egroup
+ \currentparallelcontent
+ \par
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua
new file mode 100644
index 00000000000..448d1a60cf7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua
@@ -0,0 +1,908 @@
+if not modules then modules = { } end modules ['buff-ver'] = {
+ version = 1.001,
+ comment = "companion to buff-ver.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The default visualizers have reserved names starting with buff-imp-*. Users are
+-- supposed to use different names for their own variants.
+--
+-- todo: skip=auto
+--
+-- todo: update to match context scite lexing
+
+local type, next, rawset, rawget, setmetatable, getmetatable, tonumber = type, next, rawset, rawget, setmetatable, getmetatable, tonumber
+local format, lower, upper,match, find, sub = string.format, string.lower, string.upper, string.match, string.find, string.sub
+local splitlines = string.splitlines
+local concat = table.concat
+local C, P, R, S, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs
+local patterns, lpegmatch, is_lpeg = lpeg.patterns, lpeg.match, lpeg.is_lpeg
+
+local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
+local report_visualizers = logs.reporter("buffers","visualizers")
+
+local allocate = utilities.storage.allocate
+
+visualizers = visualizers or { }
+local specifications = allocate()
+visualizers.specifications = specifications
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local tabtospace = utilities.strings.tabtospace
+local variables = interfaces.variables
+local settings_to_array = utilities.parsers.settings_to_array
+local variables = interfaces.variables
+local findfile = resolvers.findfile
+local addsuffix = file.addsuffix
+
+local v_auto = variables.auto
+local v_yes = variables.yes
+local v_last = variables.last
+local v_all = variables.all
+local v_absolute = variables.absolute
+
+-- beware, all macros have an argument:
+
+local ctx_inlineverbatimnewline = context.doinlineverbatimnewline
+local ctx_inlineverbatimbeginline = context.doinlineverbatimbeginline
+local ctx_inlineverbatimemptyline = context.doinlineverbatimemptyline
+local ctx_inlineverbatimstart = context.doinlineverbatimstart
+local ctx_inlineverbatimstop = context.doinlineverbatimstop
+
+local ctx_displayverbatiminitialize = context.dodisplayverbatiminitialize -- the number of arguments might change over time
+local ctx_displayverbatimnewline = context.dodisplayverbatimnewline
+local ctx_displayverbatimbeginline = context.dodisplayverbatimbeginline
+local ctx_displayverbatimemptyline = context.dodisplayverbatimemptyline
+local ctx_displayverbatimstart = context.dodisplayverbatimstart
+local ctx_displayverbatimstop = context.dodisplayverbatimstop
+
+local ctx_verbatim = context.verbatim
+local ctx_verbatimspace = context.doverbatimspace
+
+local CargOne = Carg(1)
+
+local function f_emptyline(s,settings)
+ if settings and settings.nature == "inline" then
+ ctx_inlineverbatimemptyline()
+ else
+ ctx_displayverbatimemptyline()
+ end
+end
+
+local function f_beginline(s,settings)
+ if settings and settings.nature == "inline" then
+ ctx_inlineverbatimbeginline()
+ else
+ ctx_displayverbatimbeginline()
+ end
+end
+
+local function f_newline(s,settings)
+ if settings and settings.nature == "inline" then
+ ctx_inlineverbatimnewline()
+ else
+ ctx_displayverbatimnewline()
+ end
+end
+
+local function f_start(s,settings)
+ if settings and settings.nature == "inline" then
+ ctx_inlineverbatimstart()
+ else
+ ctx_displayverbatimstart()
+ end
+end
+
+local function f_stop(s,settings)
+ if settings and settings.nature == "inline" then
+ ctx_inlineverbatimstop()
+ else
+ ctx_displayverbatimstop()
+ end
+end
+
+local function f_default(s) -- (s,settings)
+ ctx_verbatim(s)
+end
+
+local function f_space() -- (s,settings)
+ ctx_verbatimspace()
+end
+
+local function f_signal() -- (s,settings)
+ -- we use these for special purposes
+end
+
+local signal = "\000"
+
+visualizers.signal = signal
+visualizers.signalpattern = P(signal)
+
+local functions = { __index = {
+ emptyline = f_emptyline,
+ newline = f_newline,
+ default = f_default,
+ beginline = f_beginline,
+ space = f_space,
+ start = f_start,
+ stop = f_stop,
+ signal = f_signal,
+ }
+}
+
+local handlers = { }
+
+function visualizers.newhandler(name,data)
+ local tname, tdata = type(name), type(data)
+ if tname == "table" then -- (data)
+ setmetatable(name,getmetatable(name) or functions)
+ return name
+ elseif tname == "string" then
+ if tdata == "string" then -- ("name","parent")
+ local result = { }
+ setmetatable(result,getmetatable(handlers[data]) or functions)
+ handlers[name] = result
+ return result
+ elseif tdata == "table" then -- ("name",data)
+ setmetatable(data,getmetatable(data) or functions)
+ handlers[name] = data
+ return data
+ else -- ("name")
+ local result = { }
+ setmetatable(result,functions)
+ handlers[name] = result
+ return result
+ end
+ else -- ()
+ local result = { }
+ setmetatable(result,functions)
+ return result
+ end
+end
+
+function visualizers.newgrammar(name,t)
+ name = lower(name)
+ t = t or { }
+ local g = visualizers.specifications[name]
+ g = g and g.grammar
+ if g then
+ if trace_visualize then
+ report_visualizers("cloning grammar %a",name)
+ end
+ for k,v in next, g do
+ if not t[k] then
+ t[k] = v
+ end
+ if is_lpeg(v) then
+ t[name..":"..k] = v
+ end
+ end
+ end
+ return t
+end
+
+local function getvisualizer(method,nature)
+ method = lower(method)
+ local m = specifications[method] or specifications.default
+ if nature then
+ if trace_visualize then
+ report_visualizers("getting visualizer %a with nature %a",method,nature)
+ end
+ return m and (m[nature] or m.parser) or nil
+ else
+ if trace_visualize then
+ report_visualizers("getting visualizer %a",method)
+ end
+ return m and m.parser or nil
+ end
+end
+
+local ctx_fallback = ctx_verbatim
+
+local function makepattern(visualizer,replacement,pattern)
+ if not pattern then
+ report_visualizers("error in visualizer %a",replacement)
+ return patterns.alwaystrue
+ else
+ if type(visualizer) == "table" and type(replacement) == "string" then
+ replacement = visualizer[replacement] or ctx_fallback
+ else
+ replacement = ctx_fallback
+ end
+ return (C(pattern) * CargOne) / replacement
+ end
+end
+
+local function makenested(handler,how,start,stop)
+ local b, e, f = P(start), P(stop), how
+ if type(how) == "string" then
+ f = function(s) getvisualizer(how,"direct")(s) end
+ end
+ return makepattern(handler,"name",b)
+ * ((1-e)^1/f)
+ * makepattern(handler,"name",e)
+end
+
+visualizers.pattern = makepattern
+visualizers.makepattern = makepattern
+visualizers.makenested = makenested
+
+function visualizers.load(name)
+ name = lower(name)
+ if rawget(specifications,name) == nil then
+ name = lower(name)
+ local texname = findfile(format("buff-imp-%s.mkiv",name))
+ local luaname = findfile(format("buff-imp-%s.lua" ,name))
+ if texname == "" or luaname == "" then
+ -- assume a user specific file
+ luaname = findfile(addsuffix(name,"mkiv"))
+ texname = findfile(addsuffix(name,"lua" ))
+ end
+ if texname == "" or luaname == "" then
+ if trace_visualize then
+ report_visualizers("unknown visualizer %a",name)
+ end
+ else
+ if trace_visualize then
+ report_visualizers("loading visualizer %a",name)
+ end
+ lua.registercode(luaname)
+ context.input(texname)
+ end
+ if rawget(specifications,name) == nil then
+ rawset(specifications,name,false)
+ end
+ end
+end
+
+function visualizers.register(name,specification)
+ name = lower(name)
+ if trace_visualize then
+ report_visualizers("registering visualizer %a",name)
+ end
+ specifications[name] = specification
+ local parser, handler = specification.parser, specification.handler
+ local displayparser = specification.display or parser
+ local inlineparser = specification.inline or parser
+ local isparser = is_lpeg(parser)
+ local start, stop
+ if isparser then
+ start = makepattern(handler,"start",patterns.alwaysmatched)
+ stop = makepattern(handler,"stop",patterns.alwaysmatched)
+ end
+ if handler then
+ if isparser then
+ specification.display = function(content,settings)
+ if handler.startdisplay then handler.startdisplay(settings) end
+ lpegmatch(start * displayparser * stop,content,1,settings)
+ if handler.stopdisplay then handler.stopdisplay(settings) end
+ end
+ specification.inline = function(content,settings)
+ if handler.startinline then handler.startinline(settings) end
+ lpegmatch(start * inlineparser * stop,content,1,settings)
+ if handler.stopinline then handler.stopinline(settings) end
+ end
+ specification.direct = function(content,settings)
+ lpegmatch(parser,content,1,settings)
+ end
+ elseif parser then
+ specification.display = function(content,settings)
+ if handler.startdisplay then handler.startdisplay(settings) end
+ parser(content,settings)
+ if handler.stopdisplay then handler.stopdisplay(settings) end
+ end
+ specification.inline = function(content,settings)
+ if handler.startinline then handler.startinline(settings) end
+ parser(content,settings)
+ if handler.stopinline then handler.stopinline(settings) end
+ end
+ specification.direct = parser
+ end
+ elseif isparser then
+ specification.display = function(content,settings)
+ lpegmatch(start * displayparser * stop,content,1,settings)
+ end
+ specification.inline = function(content,settings)
+ lpegmatch(start * inlineparser * stop,content,1,settings)
+ end
+ specification.direct = function(content,settings)
+ lpegmatch(parser,content,1,settings)
+ end
+ elseif parser then
+ specification.display = parser
+ specification.inline = parser
+ specification.direct = parser
+ end
+ return specification
+end
+
+function visualizers.getspecification(name)
+ return specifications[lower(name)]
+end
+
+local escapepatterns = allocate()
+visualizers.escapepatterns = escapepatterns
+
+local function texmethod(s)
+ context.bgroup()
+ context(s)
+ context.egroup()
+end
+
+local function texcommand(s)
+ context[s]()
+end
+
+local function defaultmethod(s,settings)
+ lpegmatch(getvisualizer("default"),lower(s),1,settings)
+end
+
+-- we can consider using a nested instead
+
+local space_pattern = patterns.space^0
+local name_pattern = R("az","AZ")^1
+
+-- the hack is needed in order to retain newlines when an escape happens at the
+-- at the begin of a line; it also ensures proper line numbering; a bit messy
+
+local function hack(pattern)
+ return Cs(pattern * Cc(signal))
+end
+
+local split_processor = typesetters.processors.split
+local apply_processor = typesetters.processors.apply
+
+-- todo: { before = b, after = a, processor = p }, ...
+
+function visualizers.registerescapepattern(name,befores,afters,normalmethod,escapemethod,processors)
+ local escapepattern = escapepatterns[name]
+ if not escapepattern then
+ if type(befores) ~= "table" then befores = { befores } end
+ if type(afters) ~= "table" then afters = { afters } end
+ if type(processors) ~= "table" then processors = { processors } end
+ for i=1,#befores do
+ local before = befores[i]
+ local after = afters[i]
+ local processor = processors[i]
+ if trace_visualize then
+ report_visualizers("registering escape pattern, name %a, index %a, before %a, after %a, processor %a",
+ name,i,before,after,processor or "default")
+ end
+ before = P(before) * space_pattern
+ after = space_pattern * P(after)
+ local action
+ if processor then
+ action = function(s) apply_processor(processor,s) end
+ else
+ action = escapemethod or texmethod
+ end
+ local ep = (before / "") * ((1 - after)^0 / action) * (after / "")
+ if escapepattern then
+ escapepattern = escapepattern + ep
+ else
+ escapepattern = ep
+ end
+ end
+ escapepattern = (
+ escapepattern
+ + hack((1 - escapepattern)^1) / (normalmethod or defaultmethod)
+ )^0
+ escapepatterns[name] = escapepattern
+ end
+ return escapepattern
+end
+
+function visualizers.registerescapeline(name,befores,normalmethod,escapemethod,processors)
+ local escapepattern = escapepatterns[name]
+ if not escapepattern then
+ if type(befores) ~= "table" then befores = { befores } end
+ if type(processors) ~= "table" then processors = { processors } end
+ for i=1,#befores do
+ local before = befores[i]
+ local processor = processors[i]
+ if trace_visualize then
+ report_visualizers("registering escape line pattern, name %a, before %a, after <<newline>>",name,before)
+ end
+ before = P(before) * space_pattern
+ after = space_pattern * P("\n")
+ local action
+ if processor then
+ action = function(s) apply_processor(processor,s) end
+ else
+ action = escapemethod or texmethod
+ end
+ local ep = (before / "") * ((1 - after)^0 / action) * (space_pattern / "")
+ if escapepattern then
+ escapepattern = escapepattern + ep
+ else
+ escapepattern = ep
+ end
+ end
+ escapepattern = (
+ escapepattern
+ + hack((1 - escapepattern)^1) / (normalmethod or defaultmethod)
+ )^0
+ escapepatterns[name] = escapepattern
+ end
+ return escapepattern
+end
+
+function visualizers.registerescapecommand(name,token,normalmethod,escapecommand,processor)
+ local escapepattern = escapepatterns[name]
+ if not escapepattern then
+ if trace_visualize then
+ report_visualizers("registering escape token, name %a, token %a",name,token)
+ end
+ token = P(token)
+ local notoken = hack((1 - token)^1)
+ local cstoken = name_pattern * space_pattern
+ escapepattern = (
+ (token / "")
+ * (cstoken / (escapecommand or texcommand))
+ + (notoken / (normalmethod or defaultmethod))
+ )^0
+ escapepatterns[name] = escapepattern
+ end
+ return escapepattern
+end
+
+local escapedvisualizers = { }
+
+local function visualize(content,settings) -- maybe also method in settings
+ if content and content ~= "" then
+ local method = lower(settings.method or "default")
+ local m
+ local e = settings.escape
+ if e and e ~= "" then
+ local newname = format("%s : %s",method,e)
+ local newspec = specifications[newname]
+ if newspec then
+ m = newspec
+ else
+ local starts, stops, processors = { }, { }, { }
+ if e == v_yes then
+ starts[1] = "/BTEX"
+ stops [1] = "/ETEX"
+ else
+ local s = settings_to_array(e,true)
+ for i=1,#s do
+ local si = s[i]
+ local processor, pattern = split_processor(si)
+ si = processor and pattern or si
+ local start, stop = match(si,"^(.-),(.-)$")
+ if start then
+ local n = #starts + 1
+ starts[n] = start
+ stops [n] = stop or ""
+ processors[n] = processor
+ end
+ end
+ end
+ local oldvisualizer = specifications[method] or specifications.default
+ local oldparser = oldvisualizer.direct
+ local newparser
+ if starts[1] and stops[1] ~= "" then
+ newparser = visualizers.registerescapepattern(newname,starts,stops,oldparser,nil,processors)
+ elseif starts[1] then
+ newparser = visualizers.registerescapeline(newname,starts,oldparser,nil,processors)
+ else -- for old times sake: /em
+ newparser = visualizers.registerescapecommand(newname,e,oldparser,nil,processors)
+ end
+ m = visualizers.register(newname, {
+ parser = newparser,
+ handler = oldvisualizer.handler,
+ })
+ end
+ else
+ m = specifications[method] or specifications.default
+ end
+ local nature = settings.nature or "display"
+ local n = m and m[nature]
+ if n then
+ if trace_visualize then
+ report_visualizers("visualize using method %a and nature %a",method,nature)
+ end
+ n(content,settings)
+ else
+ if trace_visualize then
+ report_visualizers("visualize using method %a",method)
+ end
+ ctx_fallback(content,1,settings)
+ end
+ end
+end
+
+visualizers.visualize = visualize
+visualizers.getvisualizer = getvisualizer
+
+local fallbacks = { } table.setmetatableindex(fallbacks,function(t,k) local v = { nature = k } t[k] = v return v end)
+
+local function checkedsettings(settings,nature)
+ if not settings then
+ -- let's avoid dummy tables as much as possible
+ return fallbacks[nature]
+ else
+ if not settings.nature then
+ settings.nature = nature
+ end
+ return settings
+ end
+end
+
+function visualizers.visualizestring(content,settings)
+ visualize(content,checkedsettings(settings,"inline"))
+end
+
+function visualizers.visualizefile(name,settings)
+ visualize(resolvers.loadtexfile(name),checkedsettings(settings,"display"))
+end
+
+function visualizers.visualizebuffer(name,settings)
+ visualize(buffers.getcontent(name),checkedsettings(settings,"display"))
+end
+
+-- --
+
+local space = C(patterns.space) * CargOne / f_space
+local newline = C(patterns.newline) * CargOne / f_newline
+local emptyline = C(patterns.emptyline) * CargOne / f_emptyline
+local beginline = C(patterns.beginline) * CargOne / f_beginline
+local anything = C(patterns.somecontent) * CargOne / f_default
+
+----- verbosed = (space + newline * (emptyline^0) * beginline + anything)^0
+local verbosed = (space + newline * (emptyline^0) * beginline + emptyline + newline + anything)^0
+
+local function write(s,settings) -- bad name
+ lpegmatch(verbosed,s,1,settings or false)
+end
+
+visualizers.write = write
+visualizers.writenewline = f_newline
+visualizers.writeemptyline = f_emptyline
+visualizers.writespace = f_space
+visualizers.writedefault = f_default
+
+function visualizers.writeargument(...)
+ context("{") -- If we didn't have tracing then we could
+ write(...) -- use a faster print to tex variant for the
+ context("}") -- { } tokens as they always have ctxcatcodes.
+end
+
+-- helpers
+
+local function realign(lines,strip) -- "yes", <number>
+ local n
+ if strip == v_yes then
+ n = math.huge
+ for i=1, #lines do
+ local spaces = find(lines[i],"%S") -- can be lpeg
+ if not spaces then
+ -- empty line
+ elseif spaces == 0 then
+ n = 0
+ break
+ elseif spaces < n then
+ n = spaces
+ end
+ end
+ n = n - 1
+ else
+ n = tonumber(strip)
+ end
+ if n and n > 0 then
+ local copy = { }
+ for i=1,#lines do
+ copy[i] = sub(lines[i],n+1)
+ end
+ return copy
+ end
+ return lines
+end
+
+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
+ for i=first,last do
+ local li = lines[i]
+ if #li == 0 or lpegmatch(onlyspaces,li) then
+ first = first + 1
+ else
+ break
+ end
+ end
+ for i=last,first,-1 do
+ local li = lines[i]
+ if #li == 0 or lpegmatch(onlyspaces,li) then
+ last = last - 1
+ else
+ break
+ end
+ end
+ return first, last, last - first + 1
+end
+
+-- we look for text (todo):
+--
+-- "foo" : start after line with "foo"
+-- "=" : ignore first blob
+-- "=foo" : start at "foo"
+-- "!foo" : maybe a not "foo"
+
+-- % - # lines start a comment
+
+local comment = "^[%%%-#]"
+
+local function getrange(lines,first,last,range) -- 1,3 1,+3 fromhere,tothere
+ local noflines = #lines
+ local first = first or 1
+ local last = last or noflines
+ if last < 0 then
+ last = noflines + last
+ end
+ local what = settings_to_array(range) -- maybe also n:m
+ local r_first = what[1]
+ local r_last = what[2]
+ local f = tonumber(r_first)
+ local l = tonumber(r_last)
+ if r_first then
+ if f then
+ if f > first then
+ first = f
+ end
+ elseif r_first == "=" then
+ for i=first,last do
+ if find(lines[i],comment) then
+ first = i + 1
+ else
+ break
+ end
+ end
+ elseif r_first ~= "" then
+ local exact, r_first = match(r_first,"^([=]?)(.*)")
+ for i=first,last do
+ if find(lines[i],r_first) then
+ if exact == "=" then
+ first = i
+ else
+ first = i + 1
+ end
+ break
+ else
+ first = i
+ end
+ end
+ end
+ end
+ if r_last then
+ if l then
+ if l < 0 then
+ l = noflines + l
+ end
+ if find(r_last,"^[%+]") then -- 1,+3
+ l = first + l
+ end
+ if l < last then
+ last = l
+ end
+ elseif r_first == "=" then
+ for i=first,last do
+ if find(lines[i],comment) then
+ break
+ else
+ last = i
+ end
+ end
+ elseif r_last ~= "" then
+ local exact, r_last = match(r_last,"^([=]?)(.*)")
+ for i=first,last do
+ if find(lines[i],r_last) then
+ if exact == "=" then
+ last = i
+ end
+ break
+ else
+ last = i
+ end
+ end
+ end
+ end
+ return first, last
+end
+
+local tablength = 7
+
+local function dotabs(content,settings)
+ local tab = settings.tab
+ tab = tab and (tab == v_yes and tablength or tonumber(tab))
+ if tab then
+ return tabtospace(content,tab)
+ else
+ return content
+ end
+end
+
+local function filter(lines,settings) -- todo: inline or display in settings
+ local strip = settings.strip
+ if strip and strip ~= "" then
+ lines = realign(lines,strip)
+ end
+ local line, n = 0, 0
+ local first, last, m = getstrip(lines)
+ local range = settings.range
+ if range then
+ first, last = getrange(lines,first,last,range)
+ first, last = getstrip(lines,first,last)
+ end
+ -- \r is \endlinechar but \n would is more generic so this choice is debatable
+ local content = concat(lines,(settings.nature == "inline" and " ") or "\n",first,last)
+ return content, m
+end
+
+local getlines = buffers.getlines
+
+-- local decodecomment = resolvers.macros.decodecomment -- experiment
+
+local function typebuffer(settings)
+ local lines = getlines(settings.name)
+ if lines then
+ ctx_displayverbatiminitialize(#lines)
+ local content, m = filter(lines,settings)
+ if content and content ~= "" then
+ -- content = decodecomment(content)
+ content = dotabs(content,settings)
+ visualize(content,checkedsettings(settings,"display"))
+ end
+ end
+end
+
+local function processbuffer(settings)
+ local lines = getlines(settings.name)
+ if lines then
+ local content, m = filter(lines,settings)
+ if content and content ~= "" then
+ content = dotabs(content,settings)
+ visualize(content,checkedsettings(settings,"direct"))
+ end
+ end
+end
+
+-- not really buffers but it's closely related
+
+-- A string.gsub(str,"(\\.-) +$","%1") is faster than an lpeg when there is a
+-- match but slower when there is no match. But anyway, we need a more clever
+-- parser so we use lpeg.
+--
+-- [[\text ]] [[\text{}]] [[\foo\bar .tex]] [[\text \text ]] [[\text \\ \text ]]
+--
+-- needed in e.g. tabulate (manuals)
+
+local fences = S([[[{]])
+local symbols = S([[!#"$%&'*()+,-./:;<=>?@[]^_`{|}~]])
+local space = S([[ ]])
+local backslash = S([[\]])
+local nospace = space^1/""
+local endstring = P(-1)
+
+local compactors = {
+ [v_all] = Cs((backslash * (1-backslash-space)^1 * nospace * (endstring + fences) + 1)^0),
+ [v_absolute] = Cs((backslash * (1-symbols -space)^1 * nospace * (symbols+backslash) + 1) ^0),
+ [v_last] = Cs((space^1 * endstring/"" + 1)^0),
+}
+
+local function typestring(settings)
+ local content = settings.data
+ if content and content ~= "" then
+ local compact = settings.compact
+ local compactor = compact and compactors[compact]
+ if compactor then
+ content = lpegmatch(compactor,content)
+ end
+ -- content = decodecomment(content)
+ -- content = dotabs(content,settings)
+ visualize(content,checkedsettings(settings,"inline"))
+ end
+end
+
+local function typefile(settings)
+ local filename = settings.name
+ local foundname = resolvers.findtexfile(filename)
+ if foundname and foundname ~= "" then
+ local str = resolvers.loadtexfile(foundname)
+ if str and str ~= "" then
+ local regime = settings.regime
+ if regime and regime ~= "" then
+ str = regimes.translate(str,regime)
+ end
+ if str and str~= "" then
+ -- content = decodecomment(content)
+ local lines = splitlines(str)
+ local content, m = filter(lines,settings)
+ if content and content ~= "" then
+ content = dotabs(content,settings)
+ visualize(content,checkedsettings(settings,"display"))
+ end
+ end
+ end
+ end
+end
+
+implement {
+ name = "type",
+ actions = typestring,
+ arguments = {
+ {
+ { "data" },
+ { "tab" },
+ { "method" },
+ { "compact" },
+ { "nature" },
+ { "escape" },
+ }
+ }
+}
+
+implement {
+ name = "processbuffer",
+ actions = processbuffer,
+ arguments = {
+ {
+ { "name" },
+ { "strip" },
+ { "tab" },
+ { "method" },
+ { "nature" },
+ }
+ }
+}
+
+implement {
+ name = "typebuffer",
+ actions = typebuffer,
+ arguments = {
+ {
+ { "name" },
+ { "strip" },
+ { "range" },
+ { "regime" },
+ { "tab" },
+ { "method" },
+ { "escape" },
+ { "nature" },
+ }
+ }
+}
+
+implement {
+ name = "typefile",
+ actions = typefile,
+ arguments = {
+ {
+ { "name" },
+ { "strip" },
+ { "range" },
+ { "regime" },
+ { "tab" },
+ { "method" },
+ { "escape" },
+ { "nature" },
+ }
+ }
+}
+
+implement {
+ name = "doifelsevisualizer",
+ actions = { visualizers.getspecification, commands.doifelse },
+ arguments = "string"
+}
+
+implement {
+ name = "loadvisualizer",
+ actions = visualizers.load,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv
new file mode 100644
index 00000000000..5b3ed6f2a74
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv
@@ -0,0 +1,1004 @@
+%D \module
+%D [ file=buff-ver, % was core-ver
+%D version=2000.05.09,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Verbatim,
+%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.
+
+% check after-first and before-last breaks
+
+\writestatus{loading}{ConTeXt Buffer Macros / Verbatim}
+
+\registerctxluafile{buff-ver}{1.001}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+\definesystemattribute[verbatimline][public]
+
+\appendtoksonce
+ \attribute\verbatimlineattribute\attributeunsetvalue
+\to \everyforgetall
+
+%D Initializations.
+
+\installcorenamespace{typinglines}
+\installcorenamespace{typingspace}
+\installcorenamespace{typingblank} % needs checking ... used?
+
+\newtoks\everyinitializeverbatim
+
+\appendtoks
+ \the\everyresettypesetting
+ \resetfontfeature
+ \resetcharacterspacing
+\to \everyinitializeverbatim
+
+\def\setverbatimspaceskip % to be checked: must happen after font switch
+ {\spaceskip\fontcharwd\font`x\relax
+ \xspaceskip\spaceskip}
+
+\setvalue{\??typinglines\v!no }{\buff_verbatim_ignore_hyphens}
+\setvalue{\??typinglines\v!normal }{\buff_verbatim_ignore_hyphens}
+\setvalue{\??typinglines\v!yes }{\buff_verbatim_obey_breakpoints}
+\setvalue{\??typinglines\v!hyphenated}{\buff_verbatim_obey_hyphens}
+
+\setvalue{\??typingspace\v!on }{\let\obeyedspace\specialcontrolspace}
+\setvalue{\??typingspace\v!stretch }{\let\obeyedspace\specialstretchedspace}
+\setvalue{\??typingspace\v!normal }{}
+\setvalue{\??typingspace\v!fixed }{\let\obeyedspace\specialfixedspace}
+
+\setvalue{\??typingblank\v!standard }{\s_spac_whitespace_parskip}
+\setvalue{\??typingblank\v!small }{\smallskipamount}
+\setvalue{\??typingblank\v!medium }{\medskipamount}
+\setvalue{\??typingblank\v!big }{\bigskipamount}
+\setvalue{\??typingblank\v!halfline }{.5\baselineskip}
+\setvalue{\??typingblank\v!line }{\baselineskip}
+\setvalue{\??typingblank\v!none }{\zeropoint}
+
+\unexpanded\def\buff_verbatim_obey_hyphens
+ {}
+
+\unexpanded\def\buff_verbatim_obey_breakpoints
+ {\language\minusone % tricky as this affects the pagebuilder
+ \veryraggedright}
+
+\unexpanded\def\buff_verbatim_ignore_hyphens
+ {\language\minusone} % tricky as this affects the pagebuilder
+
+\def\buff_verbatim_initialize_type_one
+ {\let\obeylines\ignorelines
+ \edef\p_buff_option{\typeparameter\c!option}%
+ \ifx\p_buff_option\v!none
+ \usetypestyleandcolor\c!style\c!color
+ \else\ifx\p_buff_option\empty
+ \usetypestyleandcolor\c!style\c!color
+ \else
+ \usetypestyleparameter\c!style % no color
+ \fi\fi
+ \setcatcodetable\vrbcatcodes}
+
+\def\buff_verbatim_initialize_type_two
+ {\spaceskip.5\emwidth\relax
+ \let\obeyedspace\specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \edef\p_buff_lines{\typeparameter\c!lines}%
+ \begincsname\??typinglines\p_buff_lines\endcsname
+ \edef\p_buff_space{\typeparameter\c!space}%
+ \begincsname\??typingspace\p_buff_space\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
+\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
+ {\buff_verbatim_initialize_type_one
+ \buff_verbatim_initialize_type_two}
+
+\let\buff_verbatim_set_line_margin\relax
+
+\def\buff_verbatim_set_line_margin_indeed
+ {\hskip\doifelseoddpage{\typingparameter\c!oddmargin}{\typingparameter\c!evenmargin}\relax}
+
+\def\buff_verbatim_initialize_typing_one
+ {\usebodyfontparameter\typingparameter
+ \scratchskip\typingparameter\c!oddmargin\relax
+ \ifzeropt\scratchskip \else
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
+ \fi
+ \scratchskip\typingparameter\c!evenmargin\relax
+ \ifzeropt\scratchskip \else
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
+ \fi
+ \ifx\buff_verbatim_set_line_margin\relax
+ \doadaptleftskip{\typingparameter\c!margin}%
+ \fi
+ \edef\p_buff_option{\typingparameter\c!option}%
+ \ifx\p_buff_option\v!none
+ \usetypingstyleandcolor\c!style\c!color
+ \else\ifx\p_buff_option\empty
+ \usetypingstyleandcolor\c!style\c!color
+ \else
+ \usetypingstyleparameter\c!style % no color !
+ \fi\fi
+ \usealignparameter\typingparameter}
+
+\def\buff_verbatim_initialize_typing_two
+ {\spaceskip.5\emwidth\relax
+ \let\obeyedspace\specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \edef\p_buff_lines{\typingparameter\c!lines}%
+ \begincsname\??typinglines\p_buff_lines\endcsname
+ \edef\p_buff_space{\typingparameter\c!space}%
+ \begincsname\??typingspace\p_buff_space\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
+%D \macros
+%D {definetype,setuptype}
+%D
+%D Specific inline verbatim commands can be defined with the
+%D following command.
+
+\installcorenamespace{type}
+
+\installcommandhandler \??type {type} \??type
+
+\appendtoks
+ \setuevalue{\currenttype}{\buff_verbatim_type{\currenttype}}%
+\to \everydefinetype
+
+\appendtoks
+ \buff_verbatim_initialize_visualizer{\typeparameter\c!option}%
+\to \everysetuptype
+
+%D \macros
+%D {definetyping,setuptyping}
+%D
+%D For most users the standard \type{\start}||\type{\stop}||pair
+%D will suffice, but for documentation purposes the next
+%D definition command can be of use:
+%D
+%D \starttyping
+%D \definetyping[extratyping][margin=3em]
+%D
+%D \startextratyping
+%D these extra ones are indented by 1 em
+%D \stopextratyping
+%D \stoptyping
+%D
+%D The definitions default to the standard typing values.
+
+\installcorenamespace{typing}
+
+\installcommandhandler \??typing {typing} \??typing
+
+\appendtoks
+ \setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}%
+ \setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}%
+ \ifx\currenttypingparent\empty
+ \normalexpanded{\definelinenumbering[\currenttyping]}%
+ \else
+ \normalexpanded{\definelinenumbering[\currenttyping][\currenttypingparent]}%
+ \fi
+\to \everydefinetyping
+
+\appendtoks
+ \buff_verbatim_initialize_visualizer{\typingparameter\c!option}% we can check at the tex end
+\to \everysetuptyping
+
+\def\buff_verbatim_initialize_visualizer#1%
+ {\ifproductionrun\clf_loadvisualizer{#1}\fi}
+
+\unexpanded\def\doifelsevisualizer#1%
+ {\clf_doifelsevisualizer{#1}}
+
+\let\doifvisualizerelse\doifelsevisualizer
+
+%D Verbatim command are very sensitive to argument processing,
+%D which is a direct result of the \CATCODES\ being fixed at
+%D reading time.
+%D
+%D Typesetting inline verbatim can be accomplished by
+%D \type{\type}, which in this sentence was typeset by saying
+%D just \type{\type{\type}}, which in turn was typeset by
+%D \unknown. Using the normal grouping characters \type{{}} is
+%D the most natural way of using this command.
+%D
+%D A second, more or less redundant, alternative is delimiting
+%D the argument with an own character. This method was
+%D implemented in the context of a publication in the \MAPS,
+%D where this way of delimiting is recognized by \LATEX\ users.
+%D
+%D The third, more original alternative, is the one using
+%D \type{<<} and \type{>>} as delimiters. This alternative can
+%D be used in situations where slanted typeseting is needed.
+
+%D \macros
+%D {type}
+%D
+%D We define \type{\type} as a protected command. This command
+%D has several invocations: grouped, wirt boundary characters,
+%D and with font switches.
+%D
+%D \starttyping
+%D normal: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
+%D normal: \par \type{xx<..xx..<xx <slanted> >..>xx} \par \type{<....>} \par \type{<..<xx>..>}
+%D \setuptype[option=slanted]
+%D slanted: \par \type{xx<<..sl..<<xx <<sl>> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<<sl>>..>> \par
+%D slanted: \par \type{xx<<..sl..<xx <sl> xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<sl>..>> \par
+%D \setuptype[option=none]
+%D none: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
+%D \stoptyping
+%D
+%D When writing the manual to \CONTEXT\ and documenting this
+%D source we needed to typeset \type{<<} and \type{>>}. Because
+%D we wanted to do this in the natural way, we've adapted the
+%D original definition a bit. This implementation went through
+%D several live cycles. The final implementation looks a bit
+%D further and treats the lone \type{<<} and \type{>>} a bit
+%D different. The \type {\null} prevents ligatures, which
+%D unfortunately turn up in Lucida fonts.
+%D
+%D The following lines show what happens when we set
+%D \type {option=commands}.
+%D
+%D \startbuffer
+%D \starttyping
+%D test//test test/BTEX \footnote{test test test}/ETEX test
+%D test//test test/BTEX \footnote{test test test}/ETEX test
+%D test test test/BTEX \bf(nota bene)/ETEX test
+%D test test test /BTEX \bf(nota bene)/ETEX test
+%D \stoptyping
+%D \stopbuffer
+%D
+%D % \bgroup\setuptyping[option=commands]\getbuffer\egroup
+%D
+%D this was keyed in as:
+%D
+%D \typebuffer
+
+% Beware, the command is supposed to do something like \framed and not
+% manipulate content i.e. it gets no argument but something b/egrouped
+% instead:
+
+\def\buff_verbatim_left_of_type
+ {\typeparameter\c!left
+ \typeparameter\c!command\bgroup}
+
+\def\buff_verbatim_right_of_type
+ {\egroup
+ \typeparameter\c!right}
+
+\unexpanded\def\type{\buff_verbatim_type\empty}
+\unexpanded\def\typ {\buff_verbatim_typ \empty}
+
+\unexpanded\def\buff_verbatim_type#1%
+ {\dontleavehmode
+ \bgroup
+ \edef\currenttype{#1}%
+ \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
+
+\def\buff_verbatim_type_yes[#1]%
+ {\setupcurrenttype[#1]%
+ \buff_verbatim_type_nop}
+
+\def\buff_verbatim_type_nop
+ {\buff_verbatim_left_of_type
+ \futurelet\next\buff_verbatim_type_one}
+
+\def\buff_verbatim_typ#1%
+ {\dontleavehmode
+ \bgroup
+ \edef\currenttype{#1}%
+ \lettypeparameter\c!lines\v!hyphenated
+ \let\specialobeyedspace\specialstretchedspace
+ \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
+
+\def\buff_verbatim_type_one
+ {\ifx\next\bgroup
+ \expandafter\buff_verbatim_type_a
+ \else
+ \expandafter\buff_verbatim_type_two
+ \fi}
+
+\def\buff_verbatim_type_two
+ {\catcode`<=\othercatcode % old precaution
+ \catcode`>=\othercatcode % old precaution
+ \futurelet\next\buff_verbatim_type_three}
+
+\def\buff_verbatim_type_three
+ {\if\next<%
+ \expandafter\buff_verbatim_type_b
+ \else
+ \expandafter\buff_verbatim_type_c
+ \fi}
+
+\def\buff_verbatim_type_a
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\tpacatcodes
+ \buff_verbatim_type_normal}
+
+\def\buff_verbatim_type_b#1%
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\tpbcatcodes
+ \buff_verbatim_type_nested}
+
+\def\buff_verbatim_type_c#1%
+ {\buff_verbatim_initialize_type_one
+ \setcatcodetable\vrbcatcodes
+ \def\next##1#1{\buff_verbatim_type_normal{##1}}%
+ \next}
+
+\def\buff_verbatim_type_normal#1%
+ {\buff_verbatim_initialize_type_two
+ \dostarttaggedchained\t!verbatim\currenttype\??type
+ \clf_type
+ data {\detokenize{#1}}%
+ tab {\typeparameter\c!tab}%
+ method {\p_buff_option}%
+ compact {\typeparameter\c!compact}% % none | all | last (all needed in tabulate etc for manuals)
+ escape {\typeparameter\c!escape}% % new but rather useless imo (escaping in general is not used much)
+ % nature {inline}% is default
+ \relax
+ \dostoptagged
+ \buff_verbatim_right_of_type
+ \egroup}
+
+\def\buff_verbatim_type_nested#1%
+ {\buff_verbatim_initialize_type_two
+ \dostarttaggedchained\t!verbatim\currenttype\??type
+ \clf_type
+ data {\detokenize{#1}}%
+ tab {\typeparameter\c!tab}%
+ method {\p_buff_option}% % extra visualizer (maybe: nested,\typeparameter\c!option)
+ escape {\typeparameter\c!escape}% % new but rather useless imo (escaping in general is not used much)
+ % nature {inline}% is default
+ method {nested}%
+ \relax
+ \dostoptagged
+ \buff_verbatim_right_of_type
+ \egroup
+ \gobbleoneargument} % grab last >
+
+%D The \type {compact} option can come in handy in the case of inline argument passing
+%D
+%D \starttyping
+%D \definetype[TeXcodeA][option=TEX]
+%D \definetype[TeXcodeB][option=TEX,compact=all]
+%D \definetype[TeXcodeC][option=TEX,compact=absolute]
+%D
+%D \def\argA#1{\TeXcodeA{{#1}}}
+%D \def\argB#1{\TeXcodeB{{#1}}}
+%D \def\argC#1{\TeXcodeC{{#1}}}
+%D \stoptyping
+
+%D \macros
+%D {obeyhyphens,obeybreakpoints}
+%D
+%D Although it's not clear from the macros, one character
+%D trait of this macros, which are build on top of the support
+%D module, is that they don't hyphenate. We therefore offer
+%D the alternative \type{\typ}. The current implementation
+%D works all right, but a decent hyphenation support of
+%D \type{\tt} text will be implemented soon.
+
+\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
+\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
+\unexpanded\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero
+\unexpanded\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback
+
+\unexpanded\def\explicitfixedspace {\asciispacechar}
+\unexpanded\def\explicitobeyedspace {\asciispacechar\allowbreak}
+\unexpanded\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}%
+\unexpanded\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace
+
+\appendtoks
+ \unexpanded\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}%
+\to \everyenableelements
+
+\unexpanded\def\obeyhyphens
+ {\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.25\emwidth\relax} % hm a bit of stretch !
+
+\unexpanded\def\obeybreakpoints
+ {\ignorehyphens
+ \veryraggedright}
+
+\unexpanded\def\ignorehyphens
+ {\language\minusone % extra bonus, the \null should do the job too
+ \let\obeyedspace \specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.5\emwidth\relax}
+
+%D \macros
+%D {tex,arg,mat,dis,astype}
+%D
+%D Sometimes, for instance when we pass verbatim text as an
+%D argument, the fixed \CATCODES\ interfere with our wishes. An
+%D experimental implementation of character by character
+%D processing of verbatim text did overcome this limitation,
+%D but we've decided not to use that slow and sometimes
+%D troublesome solution. Instead we stick to some 'old'
+%D \CONTEXT\ macros for typesetting typical \TEX\ characters.
+
+\def\lesscharacter {<} % obsolete
+\def\morecharacter {>} % obsolete
+
+\let\texescape \textbackslash
+\let\leftargument \textbraceleft
+\let\rightargument \textbraceright
+\let\inlinemathmarker \textdollar
+\def\displaymathmarker{\textdollar\textdollar}
+
+\def\buff_verbatim_special_type#1#2#% # gobbles spaces
+ {\dontleavehmode\bgroup
+ \buff_verbatim_initialize_type_one
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ #1%
+ \bgroup % else wrong font for #2
+ \aftergroup#2%
+ \aftergroup\egroup
+ \let\nexttoken}
+
+\unexpanded\def\tex{\buff_verbatim_special_type\texescape \relax}
+\unexpanded\def\arg{\buff_verbatim_special_type\leftargument \rightargument}
+\unexpanded\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker}
+\unexpanded\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker}
+
+\let\normaltexttex\tex
+\let\normaltextarg\arg
+\let\normaltextmat\mat
+\let\normaltextdis\dis
+
+\unexpanded\def\astype
+ {\dontleavehmode
+ \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
+
+\unexpanded\def\asciistr#1% used in some old styles
+ {\dontleavehmode\begingroup
+ \dostarttagged\t!verbatim\empty
+ \usetypestyleandcolor\c!style\c!color\detokenize{#1}%
+ \dostoptagged
+ \endgroup}
+
+%D The basic display verbatim commands are defined in an indirect way. As we
+%D will see, they are a specific case of a more general mechanism.
+
+\let\beginofverbatimlines\relax % hooks
+\let\endofverbatimlines \relax % hooks
+
+\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
+ {\begingroup
+ \edef\currenttyping{#1}%
+ \obeylines
+ \futurelet\nexttoken\buff_verbatim_typing_start_indeed}
+
+\def\buff_verbatim_typing_start_indeed
+ {\ifx\nexttoken[%
+ \expandafter\buff_verbatim_typing_start_yes
+ \else
+ \expandafter\buff_verbatim_typing_start_nop
+ \fi}
+
+\unexpanded\def\buff_verbatim_setup_keep_together
+ {\edef\p_keeptogether{\typingparameter\c!keeptogether}%
+ \ifx\p_keeptogether\v!yes
+ \settrue \c_buff_optimize_linebreaks
+ \else
+ \setfalse\c_buff_optimize_linebreaks
+ \fi}
+
+\def\buff_verbatim_typing_start_nop
+ {\typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_setup_keep_together
+ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
+
+\def\buff_verbatim_typing_start_yes[#1]%
+ {\typingparameter\c!before
+ \startpacked[\v!blank]
+ \doifelseassignment{#1}
+ {\setupcurrenttyping[#1]}
+ {\doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}}%
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_setup_keep_together
+ \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%
+ {\buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock\currenttyping\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typebuffer
+ name {_typing_}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ escape {\typingparameter\c!escape}%
+ nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \csname#2\endcsname}
+
+\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
+ {\stoppacked
+ \typingparameter\c!after
+ \useindentnextparameter\typingparameter
+ \endgroup
+ \dorechecknextindentation}
+
+%D Line numbering for files is combined with filtering, while
+%D display verbatim has the ability to continue.
+%D
+%D \starttyping
+%D \typefile[numbering=file,start=10,stop=12]{test.tex}
+%D
+%D \definetyping[code][numbering=line]
+%D
+%D \starttext
+%D \startcode
+%D ...
+%D ...
+%D \stopcode
+%D
+%D \startcode[start=continue]
+%D ...
+%D ...
+%D \stopcode
+%D
+%D \startcode[start=10]
+%D ...
+%D \stopcode
+%D \stoptyping
+
+%D Ranges:
+%D
+%D \starttyping
+%D % label:start:one
+%D
+%D \def\MyMacro
+%D {just an example}
+%D
+%D % label:stop:one
+%D
+%D \starttext
+%D
+%D % \typefile[file][range={3,6}] {whatever.tex}
+%D % \typefile[file][range={3,+2}]{whatever.tex}
+%D
+%D \typefile[file][range={label:start:one,label:stop:one}]{whatever.tex}
+%D
+%D \stoptext
+%D \stoptyping
+
+%D \macros
+%D {typefile}
+%D
+%D Typesetting files verbatim (for the moment) only supports
+%D colorization of \TEX\ sources as valid option. The other
+%D setup values are inherited from display verbatim.
+%D The implementation of \type{\typefile} is straightforward:
+
+% [category] [settings] {name} % for historic reasons, all filenames are {}
+
+\unexpanded\def\typefile
+ {\dodoubleempty\buff_verbatim_type_file}
+
+\appendtoks
+ \setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}%
+\to \everydefinetyping
+
+\def\buff_verbatim_type_file[#1][#2]#3%
+ {\begingroup
+ \ifsecondargument
+ \setuptyping[#1][#2]%
+ \buff_verbatim_type_file_checked{#1}{#3}%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\setuptyping[\v!file][#1]
+ \buff_verbatim_type_file_checked\v!file{#3}}
+ {\buff_verbatim_type_file_checked{#1}{#3}}%
+ \else
+ \buff_verbatim_type_file_checked\v!file{#3}%
+ \fi\fi
+ \endgroup}
+
+\def\buff_verbatim_type_file_checked#1#2%
+ {\doifelsetypingfile{#2}
+ {\buff_verbatim_type_file_indeed{#1}\askedtypingfile}
+ {\showmessage\m!verbatims1{#2}}}
+
+\unexpanded\def\doifelsetypingfile#1%
+ {\edef\askedtypingfile{\locfilename{#1}}%
+ \ifx\askedtypingfile\empty
+ \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible
+ \fi
+ \ifx\askedtypingfile\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doiftypingfileelse\doifelsetypingfile
+
+\def\buff_verbatim_type_file_indeed#1#2% category name
+ {\edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock\currenttyping\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typefile
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ regime {\currentregime}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \stoppacked
+ \typingparameter\c!after}
+
+%D Line numbering:
+
+\newconditional\verbatimnumberinglines
+
+\def\beginofverbatimlinenumbering
+ {\startlinenumbering
+ [\currenttyping]%
+ [\c!continue=\typingparameter\c!continue,
+ \c!method=\v!type,
+ \c!start=\typingparameter\c!start,
+ \c!stop=\typingparameter\c!stop, % ?
+ \c!step=\typingparameter\c!step]}
+
+\def\endofverbatimlinenumbering
+ {\stoplinenumbering}
+
+\def\buff_verbatim_setup_line_numbering
+ {\ifdefined\startlinenumbering
+ \edef\currenttypingnumbering{\typingparameter\c!numbering}%
+ \ifx\currenttypingnumbering\v!file
+ \setuplinenumbering[\currenttyping][\c!method=\v!file]%
+ \settrue\verbatimnumberinglines
+ \else\ifx\currenttypingnumbering\v!line
+ \settrue\verbatimnumberinglines
+ \else
+ \setfalse\verbatimnumberinglines
+ \fi\fi
+ \ifconditional\verbatimnumberinglines
+ \let\beginofverbatimlines\beginofverbatimlinenumbering
+ \let\endofverbatimlines \endofverbatimlinenumbering
+ \fi
+ \fi}
+
+%D \macros
+%D {filename}
+%D
+%D Typesetting filenames in monospaced fonts is possible with
+%D
+%D \starttyping
+%D \filename{here/there/filename.suffix}
+%D \stoptyping
+%D
+%D The definition is not that spectacular.
+
+\unexpanded\def\filename#1{{\tttf\hyphenatedfilename{#1}}}
+
+%D \macros
+%D {verbatim}
+%d
+%D And a bonus macro, an unexpanded detokenize:
+
+\unexpanded\def\verbatim#1{\detokenize{#1}}
+
+%D The setups for display verbatim and file verbatim are
+%D shared. One can adapt the extra defined typing environments,
+%D but they also default to the values below. Watch the
+%D alternative escape character.
+
+% \tttf gives problems with {\tx \type...}
+% \tt\tf does not adapt to e.g. \bf
+
+\setuptyping
+ [\c!before=\blank,
+ \c!after=\blank,
+ %\c!keeptogether=yes, % this will become default (when tested enough)
+ %\c!bodyfont=,
+ %\c!color=,
+ \c!space=\v!off,
+ \c!lines=\v!no,
+ \c!page=\v!no,
+ \c!tab=\v!yes, % what is this: \s!ascii ?
+ \c!option=\v!none,
+ \c!text=\v!no,
+ \c!style=\tt,
+ \c!indentnext=\v!yes,
+ \c!margin=\zeropoint,
+ \c!evenmargin=\zeropoint,
+ \c!oddmargin=\zeropoint,
+ \c!blank=\v!line,
+ %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
+ \c!numbering=\v!no,
+ %\c!range=,
+ \c!start=1,
+ %\c!stop=,
+ \c!step=1,
+ %\c!continue=,
+ \c!strip=\v!no] % auto or number
+
+\definetyping[\v!typing]
+
+\setuptyping [\v!file] [\s!parent=\??typing \v!typing] % we don't want \start..\stop overload
+\setuplinenumbering[\v!file] [\s!parent=\??linenumbering\v!typing]
+
+\setuptyping [\v!buffer][\s!parent=\??typing \v!file] % we don't want \start..\stop overload
+\setuplinenumbering[\v!buffer][\s!parent=\??linenumbering\v!file]
+
+%D The setups for inline verbatim default to:
+
+\setuptype
+ [\c!space=\v!off,
+ \c!lines=\v!no,
+ %\c!color=,
+ \c!style=\tt,
+ %\c!option=\v!normal,
+ \c!page=\v!no,
+ \c!tab=\v!yes,
+ \c!compact=\v!all]
+
+%D Buffers
+
+% [name] [settings] | [name] | [settings]
+
+% \unexpanded\def\typebuffer
+% {\dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\typebuffer
+ {\begingroup
+ \let\currenttyping\v!buffer
+ \dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\buff_verbatim_type_defined_buffer
+ {\dotripleempty\buff_verbatim_type_defined_buffer_indeed}
+
+\unexpanded\def\typedefinedbuffer[#1]%
+ {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}%
+
+\appendtoks
+ \setuevalue{\e!type\currentbuffer}{\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}%
+\to \everydefinebuffer
+
+\appendtoks % \e!buffer
+ \setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}%
+\to \everydefinetyping
+
+% \unexpanded\def\buff_verbatim_type_buffer[#1][#2]%
+% {\begingroup
+% \ifsecondargument
+% \setuptyping[\v!buffer][#2]%
+% \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\v!buffer}% [name] [settings]
+% \else\iffirstargument
+% \doifelseassignment{#1}
+% {\setuptyping[\v!buffer][#1]%
+% \buff_verbatim_type_buffer_indeed\v!buffer\empty}% [settings]
+% {\processcommalist[#1]{\buff_verbatim_type_buffer_indeed\v!buffer}}% [name]
+% \else
+% \buff_verbatim_type_buffer_indeed\v!buffer\empty% []
+% \fi\fi
+% \endgroup}
+
+\unexpanded\def\buff_verbatim_type_buffer[#1][#2]%
+ {\ifsecondargument
+ \setupcurrenttyping[#2]%
+ \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings]
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\setupcurrenttyping[#1]%
+ \buff_verbatim_type_buffer_indeed\currenttyping\empty}% [settings]
+ {\processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}}% [name]
+ \else
+ \buff_verbatim_type_buffer_indeed\currenttyping\empty% []
+ \fi\fi
+ \endgroup}
+
+\unexpanded\def\buff_verbatim_type_buffer_class#1%
+ {\begingroup
+ \edef\currenttyping{#1}%
+ \dodoubleempty\buff_verbatim_type_buffer}
+
+\unexpanded\def\buff_verbatim_type_defined_buffer_indeed[#1][#2][#3]% category name settings
+ {\begingroup
+ \ifthirdargument
+ \setuptyping[#1][#3]%
+ \fi
+ \buff_verbatim_type_buffer_indeed{#1}{#2}%
+ \endgroup}
+
+\unexpanded\def\buff_verbatim_type_buffer_indeed#1#2% category name
+ {\edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
+ \dostarttaggedchained\t!verbatimblock{#1}\??typing
+ \beginofverbatimlines
+ \dostarttagged\t!verbatimlines\empty
+ \clf_typebuffer
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ range {\typingparameter\c!range}%
+ regime {\currentregime}%
+ tab {\typingparameter\c!tab}%
+ method {\p_buff_option}%
+ escape {\typingparameter\c!escape}%
+ % nature {display}%
+ \relax
+ \dostoptagged
+ \endofverbatimlines
+ \dostoptagged
+ \stoppacked
+ \typingparameter\c!after}
+
+% get : before/after of buffer
+% typing : before/after of typing
+% process : no before/after (special case anyway)
+
+% the next one is obsolete (bad name and used nowhere) so if it stays
+% the name will change
+
+\unexpanded\def\processbuffer
+ {\writestatus{nota bene}{\string\processbuffer\space is obsolete}%
+ \dodoubleempty\buff_verbatim_process}
+
+\def\buff_verbatim_process[#1][#2]%
+ {\begingroup
+ \ifsecondargument
+ \setuptyping[\v!buffer][#2]%
+ \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\setuptyping[\v!buffer][#1]%
+ \buff_verbatim_process_indeed\v!buffer\empty}% [settings]
+ {\processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}}% [name]
+ \else
+ \buff_verbatim_process_indeed\v!buffer\empty% []
+ \fi\fi
+ \endgroup}
+
+\def\buff_verbatim_process_indeed#1#2%
+ {\edef\currenttyping{#1}%
+ \clf_processbuffer
+ name {#2}%
+ strip {\typingparameter\c!strip}%
+ tab {\typingparameter\c!tab}%
+ % method {\p_buff_option}%
+ nature {direct}%
+ \relax}
+
+% so far for obsolete
+
+% line numbering, keep broken lines together
+
+\newcount\nofverbatimlines
+
+\unexpanded\def\buff_verbatim_begin_of_line
+ {\ifconditional\verbatimnumberinglines
+ \global\advance\nofverbatimlines\plusone
+ \attribute\verbatimlineattribute\nofverbatimlines
+ \fi
+ \noindent
+ \buff_verbatim_set_line_margin
+ \the\everyline % maybe also after starttagged
+ \strut % after starttagged, else break !
+ \dostarttagged\t!verbatimline\empty
+ }
+
+\unexpanded\def\buff_verbatim_end_of_line
+ {\dostoptagged
+ \obeyedline % still needed?
+ \par
+ \ifconditional\verbatimnumberinglines
+ \attribute\verbatimlineattribute\attributeunsetvalue
+ \fi}
+
+\unexpanded\def\buff_verbatim_empty_line
+ {\dostoptagged
+ \ifconditional\verbatimnumberinglines
+ \par\strut\par % this will be an option where we use a signal instead of a strut
+ \else
+ \blank[\typingparameter\c!blank]%
+ \fi
+ \dostarttagged\t!verbatimlines\empty}
+
+% hooks:
+
+\newcount \c_buff_verbatim_noflines
+\newcount \c_buff_verbatim_current
+\newconditional\c_buff_optimize_linebreaks
+
+ \def\doverbatimspace {\obeyedspace}
+
+\unexpanded\def\doinlineverbatimstart {}
+\unexpanded\def\doinlineverbatimstop {}
+\unexpanded\def\doinlineverbatimbeginline {}
+\unexpanded\def\doinlineverbatimnewline {\obeyedspace}
+\unexpanded\def\doinlineverbatimemptyline {\obeyedspace}
+
+\unexpanded\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\unexpanded\def\dodisplayverbatimstop {\buff_verbatim_end_of_line}
+\unexpanded\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\unexpanded\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line
+ \par
+ \ifconditional\c_buff_optimize_linebreaks
+ \buff_verbatim_inject_breaks
+ \fi}
+\unexpanded\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line}
+
+\unexpanded\def\buff_verbatim_inject_breaks
+ {\ifnum\c_buff_verbatim_current=\plusone
+ \nobreak
+ \else\ifnum\c_buff_verbatim_noflines=\plusthree
+ \nobreak
+ \else\ifnum\c_buff_verbatim_current=\numexpr\c_buff_verbatim_noflines-\plusone\relax
+ \nobreak
+ \fi\fi\fi}
+
+\unexpanded\def\dodisplayverbatiminitialize#1%
+ {\c_buff_verbatim_noflines#1\relax
+ \c_buff_verbatim_current\zerocount}
+
+\loadmarkfile{buff-imp-default} % preloaded as otherwise spurious spaces inline due to loading
+\loadmarkfile{buff-imp-nested} % preloaded as otherwise spurious spaces inline due to loading
+\loadmarkfile{buff-imp-escaped} % for completeness
+
+%D To be considered:
+
+% \installcorenamespace{visualizer}
+%
+% \installcommandhandler \??visualizer {visualizer} \??visualizer
+%
+% \appendtoks
+% \setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}%
+% \to \everydefinevisualizer
+%
+% \unexpanded\def\buff_verbatim_visualize#1%
+% {\bgroup
+% \def\currentvisualizer{#1}%
+% \usevisualizerstyleandcolor\c!style\c!color
+% \let\next}
+
+\appendtoks
+ %def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+ \def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize
+ \def\tex #1{\letterbackslash#1}%
+\to \everysimplifycommands
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/bxml-apa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/bxml-apa.mkiv
new file mode 100644
index 00000000000..6513a71c2df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/bxml-apa.mkiv
@@ -0,0 +1,615 @@
+%D \module
+%D [ file=bxml-apa,
+%D version=2010.05.14, % based on bibl-apa.tex
+%D title=APA bibliography style,
+%D subtitle=Publications,
+%D author={Taco Hoekwater \& 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
+
+% helpers (todo)
+
+\let\maybeyear\firstofoneargument
+\let\etalchar \firstofoneargument
+
+\setupbibtexcitationvariants
+ [author,year]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!no,
+ \c!inbetween={ },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [authoryear]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={ },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [authoryears]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={, },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [key,serial,authornum,page,short,type,doi,url]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!no,
+ \c!inbetween={ },
+ \c!left={[},
+ \c!right={]}]
+
+\setupbibtexcitationvariants
+ [num]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={--},
+ \c!left={[},
+ \c!right={]}]
+
+\setupbibtexpublications
+ [\c!sorttype=,
+ \c!criterium=,
+ \c!refcommand=authoryears,
+ \c!numbering=\v!no,
+ \c!autohang=\v!no]
+
+\setupbibtexpublications
+ [\c!width=2em, % 24pt,
+ \c!artauthor=invertedshort,
+ \c!editor=invertedshort,
+ \c!author=invertedshort,
+ \c!namesep={, },
+ \c!lastnamesep={ and },
+ \c!finalnamesep={ and },
+ \c!firstnamesep={, },
+ \c!juniorsep={ },
+ \c!vonsep={ },
+ \c!surnamesep={, },
+ \c!authoretallimit=5,
+ \c!editoretallimit=5,
+ \c!artauthoretallimit=5,
+ \c!authoretaldisplay=5,
+ \c!editoretaldisplay=5,
+ \c!artauthoretaldisplay=5,
+ \c!authoretaltext={ et al.},
+ \c!editoretaltext={ et al.},
+ \c!artauthoretaltext={ et al.}]
+
+% common
+
+\startxmlsetups bibtex:apa:common:wherefrom
+ \bibxmldoifelse {address} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmldoifelse {country} {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{country}: \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{country}
+ }
+ } {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{address}
+ }
+ }
+ \getvariable{bibtex:temp}{right}
+ } {
+ \bibxmldoifelse {country} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{country}: \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{country}
+ }
+ \getvariable{bibtex:temp}{right}
+ } {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ \getvariable{bibtex:temp}{right}
+ } {
+ \getvariable{bibtex:temp}{otherwise}
+ }
+ }
+ }
+\stopxmlsetups
+
+% we can inherit .. less assignments
+
+\startxmlsetups bibtex:apa:common:publisher
+ \setvariables[bibtex:temp][label=publisher,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:organization
+ \setvariables[bibtex:temp][label=organization,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:school
+ \setvariables[bibtex:temp][label=school,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:institution
+ \setvariables[bibtex:temp][label=institution,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:school:subsentence
+ \setvariables[bibtex:temp][label=school,left=\bibtexcomma,right=\bibtexperiod,otherwise=\bibtexperiod]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:institution:subsentence
+ \setvariables[bibtex:temp][label=institution,left=\bibtexcomma,right=\bibtexperiod,otherwise=\bibtexperiod]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:publisher:sentence
+ \setvariables[bibtex:temp][label=publisher,left=\bibtexspace,right=\bibtexperiod,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:organization:sentence
+ \setvariables[bibtex:temp][label=organization,left=\bibtexspace,right=\bibtexperiod,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:title-and-series
+ \bibxmldoif {title} {
+ \bibxmlflush{title}
+ \bibxmldoif {series} {
+ \bibtexlparent\bibxmlflush{series}\bibtexrparent
+ }
+ \bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:title-it-and-series
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibtexlparent\bibxmlflush{series}\bibtexrparent
+ }
+ \bibtexperiod
+ }
+\stopxmlsetups
+
+\disablemode[bibtex:apa:edited-book]
+
+\startxmlsetups bibtex:apa:common:author-and-year
+ \bibxmldoif {author} {
+ \bibxmlsetup{bibtex:format:author}
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:author-or-key-and-year
+ \bibxmldoifelse {author} {
+ \bibxmlsetup{bibtex:format:author}
+ } {
+ \bibxmldoif {key} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:key}\bibtexrbracket
+ }
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:author-editors-crossref-year
+ \bibxmldoif {author} {
+ \bibxmlsetup{bibtex:format:author}
+ } {
+ \bibxmldoifelse {editor} {
+ \enablemode[bibtex:apa:edited-book]
+ \xmlsetup{#1}{bibtex:format:editor}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}
+ } {
+ % weird period
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket\bibtexperiod
+ }
+ }
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:editor-or-key-and-year
+ \bibxmldoifelse {editor} {
+ \enablemode[bibtex:apa:edited-book]
+ \xmlsetup{#1}{bibtex:format:editor}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}
+ } {
+ \bibxmldoif {key} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:key}\bibtexrbracket
+ }
+ }
+ \bibtexspace
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:note
+ \bibxmldoif {note} {
+ \bibtexspace\bibxmlflush{note}\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:comment
+ \bibxmldoif {comment} {
+ \bibtexspace\bibxmlflush{comment}\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:p
+ \bibxmldoif {pages} {
+ \bibtexspace\bibxmlflush{pages}\bibtexspace p\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:pp
+ \bibxmldoif {pages} {
+ \bibtexspace\bibxmlflush{pages}\bibtexspace pp\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:pages
+ \bibxmldoif {pages} {
+ \bibtexcomma pages~\bibxmlflush{pages}
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:edition:sentense
+ \bibxmldoif {edition} {
+ \bibtexspace\bibxmlflush{edition}\bibtexspace edition\bibtexperiod
+ }
+\stopxmlsetups
+
+% check ewhen the next is used (no period)
+
+% \startxmlsetups bibtex:apa:common:edition
+% \bibxmldoif {edition} {
+% \bibtexspace\bibxmlflush{edition}\bibtexspace edition
+% }
+% \stopxmlsetups
+
+% we can share more, todo
+
+% specific
+
+\startxmlsetups bibtex:apa:article
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmldoif {title} {
+ \bibxmlflush{title}\bibtexperiod
+ }
+ \bibxmldoifelse {journal} {
+ \bgroup\it\bibxmlflush{journal}\/\egroup
+ } {
+ \bibxmldoif {crossref} {
+ In\bibtexspace\bibxmlflush{crossref}
+ }
+ }
+ \bibxmldoifelse {volume} {
+ \bibtexcomma\bgroup\it\bibxmlflush{volume}\/\egroup
+ \bibxmldoif {issue} {
+ \bibtexlparent\bibxmlflush{issue}\bibtexlparent
+ }
+ \bibxmldoif {pages} {
+ \bibtexcomma\bibxmlflush{pages}
+ }
+ \bibtexperiod
+ } {
+ \bibxmlsetup{bibtex:apa:common:pages:pp}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+ \bibxmlsetup{bibtex:apa:common:comment}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:book
+ \bibxmlsetup{bibtex:apa:common:author-editors-crossref-year}
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \doifelsemode {bibtex:apa:edited-book} {
+ \bibxmldoifelse {volume} {
+ \bibtexspace Number\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoifelse {series} {
+ \bibtexspace in\nonbreakablespace\bibxmlflush{series}\bibtexperiod
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibtexspace in\bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ } {
+ \bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoif {series} {
+ \bibtexspace\bibxmlflush{series}
+ }
+ \bibtexperiod
+ }
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmldoif {volume} {
+ Volume\nonbreakablespace\bibxmlflush{volume}\bibtexspace of\nonbreakablespace
+ }
+ } {
+ \bibxmldoif {volume} {
+ \bibtexcomma volume\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoif {series} {
+ \bibtexspace of\nonbreakablespace\bgroup\it\bibxmlflush{series}\/\egroup
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ }
+ }
+ }
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}% twice?
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:inbook
+ \bibxmlsetup{bibtex:apa:common:author-editors-crossref-year}
+ \bibxmldoifelse {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ } {
+ \doifelsemode {bibtex:apa:edited-book} {
+ \bibxmldoifelse {volume} {
+ \bibtexspace number\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoifelse {series} {
+ \bibtexspace in\nonbreakablespace\bibxmlflush{series}\bibtexperiod
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibtexspace in\bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ } {
+ \bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoif {series} {
+ \bibtexspace\bibxmlflush{series}\bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibxmldoif {volume} {
+ Volume\nonbreakablespace\bibxmlflush{volume}\bibtexspace of\nonbreakablespace
+ }
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ } {
+ \bibxmldoif {volume} {
+ \bibtexcomma volume\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoif {series} {
+ \bibtexspace of\nonbreakablespace\bgroup\it\bibxmlflush{series}\/\egroup
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ }
+ }
+ }
+ \bibtexspace
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publisher}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:booklet
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publication:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:manual
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:incollection
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmldoif {arttitle} {
+ \bibxmlflush{arttitle}\bibtexperiod
+ }
+ In\bibtexspace
+ \bibxmldoifelse {title} {
+ \bibxmlsetup{bibtex:format:editors}\bibtexcomma
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibxmldoif {volume} {
+ \bibtexcomma number\bibtexspace\bibxmlflush{volume}\bibtexspace in
+ }
+ \bibtexspace\bibxmlflush{series}
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibxmldoif {edition} {
+ \bibtexspace\bibxmlflush{edition}\bibtexspace edition
+ }
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ } {
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibtexspace
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:inproceedings
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmldoif {arttitle} {
+ \bibxmlflush{arttitle}\bibtexperiod
+ }
+ In\bibtexspace
+ \bibxmldoifelse {title} {
+ \bibxmldoif {editors} {
+ \bibxmlflush{bibtex:apa:format:editors}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}\bibtexcomma
+ }
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibxmldoif {volume} {
+ \bibtexcomma number~\bibxmlflush{volume} in
+ }
+ \bibtexspace
+ \bibxmlflush{series}
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ } {
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:proceedings
+ \bibxmlsetup{bibtex:apa:common:editor-or-key-and-year}
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {volume} {
+ \bibtexcomma number\bibtexspace\bibxmlflush{volume}\bibtexspace in\bibtexspace
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:thesis
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmldoifelse {type} {
+ \bibxmlflush{type}
+ } {
+ \getvariable{bibtex:temp}{label}
+ }
+ \bibxmlsetup{bibtex:apa:common:school:subsentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:mastersthesis
+ \setvariables[bibtex:temp][label=Master's thesis]
+ \bibxmlsetup{bibtex:apa:common:thesis}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:phdthesis
+ \setvariables[bibtex:temp][label=PhD thesis]
+ \bibxmlsetup{bibtex:apa:common:thesis}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:techreport
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmldoifelse {type} {
+ \bibxmlflush{type}
+ \bibxmldoif {volume} {
+ \bibtexspace\bibxmlflush{volume}
+ }
+ } {
+ \bibtexspace Technical Report
+ }
+ \bibxmlsetup{bibtex:apa:common:institution:subsentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:misc
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:unpublished
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmldoif {type} {
+ \bibtexlparent\bibxmlflush{type}\bibtexrparent
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-act.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-act.mkiv
new file mode 100644
index 00000000000..bd1ffd38d7d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-act.mkiv
@@ -0,0 +1,74 @@
+%D \module
+%D [ file=catc-act,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Default Catcode Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module deals with some active character handling. Use
+%D with care.
+
+\unprotect
+
+% todo: \letcharcode<number>=\something
+
+%D \macros
+%D {installactivecharacter}
+
+\let\m_syst_catcodes_temp\empty
+
+\normalprotected\def\installactivecharacter#1 %
+ {\edef\m_syst_catcodes_temp{\detokenize{#1}}%
+ \c_syst_catcodes_c\expandafter`\m_syst_catcodes_temp\relax % relax needed
+ \expandafter\startextendcatcodetable
+ \expandafter\ctxcatcodes\expandafter\catcode\the\c_syst_catcodes_c\activecatcode
+ \stopextendcatcodetable
+ \letcatcodecommand \ctxcatcodes \c_syst_catcodes_c \m_syst_catcodes_temp \relax
+ \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi
+ \let\m_syst_catcodes_temp\empty}
+
+%D \macros
+%D {defineactivecharacter}
+%D
+%D Use this one with care, esp in combination with catcode
+%D vectors. There are better ways now.
+
+\setnewconstant\c_syst_catcodes_hack\tildeasciicode % also defined in catc-ini.mkiv
+
+\normalprotected\def\defineactivecharacter #1#2 #3% uses \doifelsenumber which is not yet defined
+ {\c_syst_catcodes_c\uccode\c_syst_catcodes_hack
+ \if#1"\uccode\c_syst_catcodes_hack\expandafter\doifelsenumber\expandafter{\string#1#2}\empty #1#2\else
+ \uccode\c_syst_catcodes_hack\expandafter\doifelsenumber\expandafter{\string#1#2}\empty`#1#2\fi
+ \catcode\uccode\c_syst_catcodes_hack\activecatcode
+ \uppercase{\def\m_syst_catcodes_temp{~}}% brrr
+ \uccode\c_syst_catcodes_hack\c_syst_catcodes_c
+ \expandafter\expandafter\expandafter\def\expandafter\m_syst_catcodes_temp\expandafter
+ {\expandafter\syst_catcodes_handle\m_syst_catcodes_temp{#3}}%
+ \let\m_syst_catcodes_temp\empty}
+
+\chardef\activecharactermode\plusone % overloading still backward compatible
+
+\def\syst_catcodes_handle
+ {\ifcase\activecharactermode
+ \expandafter\syst_catcodes_handle_nop
+ \else
+ \expandafter\syst_catcodes_handle_yes
+ \fi}
+
+\def\syst_catcodes_handle_yes#1#2{#2}
+\def\syst_catcodes_handle_nop#1#2{\noexpand#1}
+
+\normalprotected\def\makecharacteractive #1 %
+ {\catcode`#1\activecatcode}
+
+\normalprotected\def\installanddefineactivecharacter #1 % #2%
+ {\normalexpanded{\noexpand\installactivecharacter \utfchar{#1} }%
+ \defineactivecharacter #1 }% {#2}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-ctx.mkiv
new file mode 100644
index 00000000000..5af8a50356f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-ctx.mkiv
@@ -0,0 +1,179 @@
+%D \module
+%D [ file=catc-cys,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Extra Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We prefer to define relevant catcode tables in this file instead
+%D of everywhere around.
+
+\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi
+\ifdefined \prtcatcodes \else \newcatcodetable \prtcatcodes \fi
+\ifdefined \txtcatcodes \else \newcatcodetable \txtcatcodes \fi
+%ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky
+\ifdefined \tpacatcodes \else \newcatcodetable \tpacatcodes \fi % { }
+\ifdefined \tpbcatcodes \else \newcatcodetable \tpbcatcodes \fi % < >
+
+\setnewconstant \doublecommentsignal "10FF25 %% < 110000 (last valid range)
+
+\startcatcodetable \ctxcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ % \catcode\circumflexasciicode\superscriptcatcode
+ % \catcode\underscoreasciicode\subscriptcatcode
+ % \catcode\ampersandasciicode \alignmentcatcode
+ \catcode\underscoreasciicode\othercatcode
+ \catcode\circumflexasciicode\othercatcode
+ \catcode\ampersandasciicode \othercatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+\startcatcodetable \prtcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode % candidate
+ \catcode\underscoreasciicode \lettercatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+% \catcode\colonasciicode \lettercatcode % candidate
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode \endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+%startcatcodetable \mthcatcodes
+% \catcode\tabasciicode \spacecatcode
+% \catcode\endoflineasciicode \endoflinecatcode
+% %\catcode\newlineasciicode \spacecatcode
+% \catcode\formfeedasciicode \endoflinecatcode
+% \catcode\spaceasciicode \spacecatcode
+% \catcode\endoffileasciicode \ignorecatcode
+% \catcode\circumflexasciicode\superscriptcatcode
+% \catcode\underscoreasciicode\subscriptcatcode
+% \catcode\ampersandasciicode \alignmentcatcode
+% \catcode\backslashasciicode \escapecatcode
+% \catcode\leftbraceasciicode \begingroupcatcode
+% \catcode\rightbraceasciicode\endgroupcatcode
+% \catcode\dollarasciicode \mathshiftcatcode
+% \catcode\hashasciicode \parametercatcode
+% \catcode\commentasciicode \commentcatcode
+% %\catcode\tildeasciicode \activecatcode
+% %\catcode\barasciicode \activecatcode
+%stopcatcodetable
+
+\startcatcodetable \tpacatcodes
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode \othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode \othercatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+\stopcatcodetable
+
+\startcatcodetable \tpbcatcodes
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode \othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode \othercatcode
+ \catcode\lessthanasciicode \begingroupcatcode
+ \catcode\morethanasciicode \endgroupcatcode
+\stopcatcodetable
+
+\startcatcodetable \txtcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\doublecommentsignal\commentcatcode
+\stopcatcodetable
+
+\letcatcodecommand \ctxcatcodes \barasciicode \relax
+\letcatcodecommand \ctxcatcodes \tildeasciicode \relax
+
+ \catcodetable \ctxcatcodes
+\let \defaultcatcodetable \ctxcatcodes
+
+% for the moment here:
+
+\normalprotected\def\starttexcode
+ {\pushcatcodetable
+ \catcodetable\prtcatcodes}
+
+\normalprotected\def\stoptexcode
+ {\popcatcodetable}
+
+\normalprotected\def\startcontextcode
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes}
+
+\normalprotected\def\stopcontextcode
+ {\popcatcodetable}
+
+% not visible, only for special cases
+
+\newcatcodetable \ctdcatcodes % context definitions
+
+\startcatcodetable \ctdcatcodes
+ \catcode\tabasciicode \ignorecatcode
+ \catcode\endoflineasciicode \ignorecatcode
+ \catcode\formfeedasciicode \ignorecatcode
+ \catcode\spaceasciicode \ignorecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode % candidate
+ \catcode\underscoreasciicode \lettercatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+% \catcode\colonasciicode \lettercatcode % candidate
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode \endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+\normalprotected\def\startcontextdefinitioncode
+ {\pushcatcodetable
+ \catcodetable\ctdcatcodes}
+
+\normalprotected\def\stopcontextdefinitioncode
+ {\popcatcodetable}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-def.mkiv
new file mode 100644
index 00000000000..bf794f045dc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-def.mkiv
@@ -0,0 +1,147 @@
+%D \module
+%D [ file=catc-def,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Default Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The following catcode tables are rather \CONTEXT\ independent.
+
+\ifdefined\nilcatcodes \else \newcatcodetable \nilcatcodes \fi
+\ifdefined\texcatcodes \else \newcatcodetable \texcatcodes \fi
+\ifdefined\luacatcodes \else \newcatcodetable \luacatcodes \fi
+\ifdefined\notcatcodes \else \newcatcodetable \notcatcodes \fi
+\ifdefined\vrbcatcodes \else \newcatcodetable \vrbcatcodes \fi
+\ifdefined\prtcatcodes \else \newcatcodetable \prtcatcodes \fi
+
+\startcatcodetable \nilcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+\stopcatcodetable
+
+\startcatcodetable \texcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode\superscriptcatcode
+ \catcode\underscoreasciicode\subscriptcatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+\stopcatcodetable
+
+\startcatcodetable \luacatcodes
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode \othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode\othercatcode
+ \catcode\underscoreasciicode\othercatcode
+ \catcode\ampersandasciicode \othercatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\commentasciicode \othercatcode
+ \catcode\hashasciicode \othercatcode
+ \catcode\barasciicode \othercatcode
+ \catcode\leftbraceasciicode \othercatcode
+ \catcode\rightbraceasciicode\othercatcode
+ \catcode\tildeasciicode \othercatcode
+ \catcode\dollarasciicode \othercatcode
+\stopcatcodetable
+
+\startcatcodetable \notcatcodes % probably less needed
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \othercatcode
+ \catcode\underscoreasciicode \othercatcode
+ \catcode\ampersandasciicode \othercatcode
+ \catcode\tildeasciicode \othercatcode
+ \catcode\hashasciicode \othercatcode
+ \catcode\dollarasciicode \othercatcode
+ \catcode\commentasciicode \othercatcode
+ \catcode\lessthanasciicode \othercatcode
+ \catcode\morethanasciicode \othercatcode
+ \catcode\leftbraceasciicode \othercatcode
+ \catcode\rightbraceasciicode \othercatcode
+ \catcode\doublequoteasciicode \othercatcode
+ \catcode\singlequoteasciicode \othercatcode
+ \catcode\forwardslashasciicode\othercatcode
+ \catcode\backslashasciicode \othercatcode
+ \catcode\barasciicode \othercatcode
+\stopcatcodetable
+
+\startcatcodetable \vrbcatcodes % probably less needed
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode\othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode\othercatcode
+\stopcatcodetable
+
+\startcatcodetable \prtcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode
+ %catcode\underscoreasciicode \subscriptcatcode
+ \catcode\underscoreasciicode \lettercatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode \endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+%D Because some characters have a special meaning, we provide
+%D shortcuts to their character representation.
+
+\chardef \^ = \circumflexasciicode
+\chardef \_ = \underscoreasciicode
+\chardef \& = \ampersandasciicode
+\chardef \% = \commentasciicode
+\chardef \# = \hashasciicode
+\chardef \$ = \dollarasciicode
+\chardef \{ = \leftbraceasciicode
+\chardef \} = \rightbraceasciicode
+\chardef \\ = \backslashasciicode
+\chardef \| = \barasciicode
+
+% way too wide in lm, so one can also use:
+%
+% \def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
+
+%D From now on we can use the protection mechanisms.
+
+\normalprotected\def\unprotect{\pushcatcodetable\setcatcodetable\prtcatcodes}
+\normalprotected\def\protect {\popcatcodetable}
+
+% \prependtoks \catcodetable\ctxcatcodes \to \everyjob
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.lua
new file mode 100644
index 00000000000..9241f5a1b16
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.lua
@@ -0,0 +1,45 @@
+if not modules then modules = { } end modules ['catc-ini'] = {
+ version = 1.001,
+ comment = "companion to catc-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+catcodes = catcodes or { }
+catcodes.numbers = catcodes.numbers or { }
+catcodes.names = catcodes.names or { }
+
+storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers")
+storage.register("catcodes/names", catcodes.names, "catcodes.names")
+
+local numbers = catcodes.numbers
+local names = catcodes.names
+
+-- this only happens at initime
+
+function catcodes.register(name,number)
+ numbers[name] = number
+ local cnn = names[number]
+ if cnn then
+ cnn[#cnn+1] = name
+ else
+ names[number] = { name }
+ end
+ tex[name] = number -- downward compatible
+end
+
+-- this only happens at runtime
+
+for k, v in next, numbers do
+ tex[k] = v -- downward compatible
+end
+
+-- nasty
+
+table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
+table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
+
+commands.registercatcodetable = catcodes.register
+--------.definecatcodetable = characters.define -- not yet defined
+--------.setcharactercodes = characters.setcodes -- not yet defined
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv
new file mode 100644
index 00000000000..440d53efed2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv
@@ -0,0 +1,354 @@
+%D \module
+%D [ file=catc-ini,
+%D version=2006.09.18,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Catcode Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We've split the functionality of syst-cat.* over more files
+%D now so that we can load more selectively.
+
+\registerctxluafile{catc-ini}{1.001}
+
+\unprotect
+
+%D A long standing wish has been the availability of catcode arrays. Because
+%D traditional \TEX\ does not provide this we implement a fake method in the
+%D \MKII\ file. There is some overlap in code with \MKII\ but we take that
+%D for granted. Also, in \MKIV\ less active characters are used.
+
+\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
+
+\begingroup
+ \catcode \tabasciicode \activecatcode \gdef\activetabtoken {^^I}
+ \gdef\outputnewlinechar {^^J}
+ \catcode \formfeedasciicode \activecatcode \gdef\activeformfeedtoken {^^L}
+ \catcode \endoflineasciicode \activecatcode \gdef\activeendoflinetoken{^^M}
+\endgroup
+
+% \endlinechar = \endoflineasciicode % appended to input lines
+% \newlinechar = \newlineasciicode % can be used in write
+
+% rather special and used in writing to file: \let\par\outputnewlinechar
+
+\normalprotected\def\initializenewlinechar % operating system dependent
+ {\begingroup
+ \newlinechar\newlineasciicode
+ \xdef\outputnewlinechar{^^J}%
+ \endgroup}
+
+%D We predefine some prefixes ahead of syst-aux and mult-sys.
+
+% We reserve 8 slots for catcodes.
+%
+% \def\??catcodelet {1>>} % let : \let
+% \def\??catcodedef {2>>} % def : \def
+% \def\??catcodeued {3>>} % ued : \unexpanded\def
+% \def\??catcodeget {4>>} % \meaning
+%
+% \def\??catcodetablet{5>>}
+% \def\??catcodetablen{6>>}
+
+\installsystemnamespace {catcodelet} % let : \let
+\installsystemnamespace {catcodedef} % def : \def
+\installsystemnamespace {catcodeued} % ued : \unexpanded\def
+\installsystemnamespace {catcodeget} % \meaning
+
+\installsystemnamespace {catcodetablet}
+\installsystemnamespace {catcodetablen}
+
+\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate
+\newcount\c_syst_catcodes_a
+\newcount\c_syst_catcodes_b
+\newcount\c_syst_catcodes_c
+
+\normalprotected\def\newcatcodetable#1% we could move the cctdefcounter to lua
+ {\global\advance\c_syst_catcodes_n\plusone
+ \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
+ \newconstant#1%
+ #1\c_syst_catcodes_n
+ \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}}
+
+\newtoks \everysetdefaultcatcodes
+
+\everysetdefaultcatcodes % this might get dropped
+ {\catcode\backslashasciicode\othercatcode
+ \catcode\endoflineasciicode\othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\commentasciicode \othercatcode
+ \catcode\delasciicode \othercatcode}
+
+\normalprotected\def\startcatcodetable#1#2\stopcatcodetable
+ {\begingroup
+ \catcodetable\inicatcodes
+ \the\everysetdefaultcatcodes
+ #2%
+ \savecatcodetable#1\relax
+ \endgroup}
+
+\let\stopcatcodetable\relax
+
+\normalprotected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+ {\begingroup
+ \catcodetable#1\relax
+ \globaldefs\plusone
+ #2%
+ \globaldefs\zerocount
+ \endgroup}
+
+\let\stopextendcatcodetable\relax
+
+\normalprotected\def\permitcircumflexescape % to be used grouped
+ {\catcode\circumflexasciicode\superscriptcatcode}
+
+\let\permitcaretescape\permitcircumflexescape
+
+% ==
+%
+% \normalprotected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+% {\bgroup
+% \scratchcounter\the\catcodetable
+% \catcodetable #1 #2
+% \catcodetable\scratchcounter
+% \egroup}
+
+%D The next command can be defined in a cleaner way in the MkIV way but we want
+%D to have a fast one with a minimal chance for interference. Do we still need
+%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use
+%D active characters for very special cases.
+
+\setnewconstant\c_syst_catcodes_hack\tildeasciicode
+
+%D Once a catcode is assigned, the next assignments will happen faster. However,
+%D redefinitions probably happen seldom so it's sort of overkill.
+
+\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a}
+\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a}
+\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a}
+
+\def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b}
+\def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b}
+\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b}
+
+\def\syst_catcodes_let_b % each time
+ {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_let_c
+ \fi}
+
+\def\syst_catcodes_def_b % each time
+ {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_def_c
+ \fi}
+
+\def\syst_catcodes_ued_b % each time
+ {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_ued_c
+ \fi}
+
+\def\syst_catcodes_let_c % only first time
+ {\expandafter\gdef\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
+ {\expandafter\let\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here)
+ {\expandafter\gdef\csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_normal
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\def\syst_catcodes_ued_c % only first time
+ {\expandafter\gdef\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\normalprotected\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b}
+
+\def\syst_catcodes_reinstate_normal % can be used when a direct definition has been done
+ {\begingroup % and the selector has been lost
+ \uccode\c_syst_catcodes_hack\c_syst_catcodes_b
+ \catcode\uccode\c_syst_catcodes_hack\activecatcode
+ \uppercase{\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}%
+ \endgroup}
+
+\def\syst_catcodes_reinstate_unexpanded % can be used when a direct definition has been done
+ {\begingroup % and the selector has been lost
+ \uccode\c_syst_catcodes_hack\c_syst_catcodes_b
+ \catcode\uccode\c_syst_catcodes_hack\activecatcode
+ \uppercase{\normalprotected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}%
+ \endgroup}
+
+%D This can be used when a direct definition has been done and the selector has been
+%D lost.
+
+% problem: \next needs to be unique (as it gets bound)
+%
+% \def\syst_catcodes_reinstate_normal
+% {\begingroup
+% \edef\next{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}%
+% \global\letcharcode\c_syst_catcodes_b\next
+% \endgroup}
+%
+% \def\syst_catcodes_reinstate_unexpanded
+% {\begingroup
+% \normalprotected\edef\next{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}%
+% \global\letcharcode\c_syst_catcodes_b\next
+% \endgroup}
+
+\newconstant\defaultcatcodetable
+
+\def\catcodecommand#1%
+ {\csname\??catcodeget\number
+ \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname
+ \currentcatcodetable \else \defaultcatcodetable
+ \fi
+ :\number#1\endcsname}
+
+%D \macros
+%D {restorecatcodes,pushcatcodetable,popcatcodetable}
+%D
+%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary
+%D file, which deals with tables of contents, registers, two pass tracking, references
+%D etc. This file, as well as files concerning graphics, is processed when needed,
+%D which can be in the mid of typesetting verbatim. However, when reading in data in
+%D verbatim mode, we should temporary restore the normal \CATCODES, and that's exactly
+%D what the next macros do. Saving the catcodes can be disabled by saying \type
+%D {\localcatcodestrue}. In \MKIV\ instead we can push and pop catcode tables and as
+%D we keep track of used tables users seldom need to deal with this themselves.
+
+\newcount\c_syst_catcodes_level
+
+\normalprotected\def\pushcatcodetable
+ {\advance\c_syst_catcodes_level\plusone
+ \syst_catcodes_trace_push
+ \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
+
+\normalprotected\def\popcatcodetable
+ {\ifcase\c_syst_catcodes_level
+ \syst_catcodes_trace_nesting_error
+ \else
+ \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname
+ \syst_catcodes_trace_pop
+ \advance\c_syst_catcodes_level\minusone
+ \fi}
+
+\normalprotected\def\syst_catcodes_trace_nesting_error
+ {\immediate\write\statuswrite{}%
+ \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end
+ \immediate\write\statuswrite{}}
+
+\normalprotected\def\restorecatcodes % takes previous level
+ {\ifnum\c_syst_catcodes_level>\plusone
+ \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
+ \fi}
+
+% \newtoks\everycatcodetable
+
+\normalprotected\def\setcatcodetable#1%
+ {\catcodetable#1%
+% \the\everycatcodetable
+ \syst_catcodes_trace_set}
+
+%D Handy for debugging:
+%D
+%D \starttyping
+%D \tracecatcodetables
+%D \stoptyping
+
+\normalprotected\def\tracecatcodetables
+ {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \number\c_syst_catcodes_level}}%
+ \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}%
+ \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}}
+
+\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}}
+
+\def\syst_catcodes_prev
+ {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount
+ \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
+ \else
+ -%
+ \fi}
+
+\def\catcodetablename
+ {\ifnum\currentcatcodetable>\zerocount
+ \csname\??catcodetablen\number\currentcatcodetable\endcsname
+ \else
+ -%
+ \fi}
+
+\let\syst_catcodes_trace_set \empty
+\let\syst_catcodes_trace_push\empty
+\let\syst_catcodes_trace_pop \empty
+
+% \tracecatcodetables
+
+\protect
+
+%D We still have to define these so let's do that now:
+
+\newcatcodetable \inicatcodes
+\initcatcodetable\inicatcodes
+
+\let\currentcatcodetable\catcodetable
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-sym.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-sym.mkiv
new file mode 100644
index 00000000000..ae12532720d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-sym.mkiv
@@ -0,0 +1,190 @@
+%D \module
+%D [ file=catc-sym,
+%D version=1997.01.03, % moved code
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Some Handy Constants,
+%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 want to have access to the raw alternatives of the special characters. We
+%D use a \type {\xdef} instead of \type {\let} because we need an expandable token
+%D in a \type {\write}.
+
+\bgroup
+
+\catcode`B=\begingroupcatcode
+\catcode`E=\endgroupcatcode
+\catcode`.=\escapecatcode
+
+.catcode `.{ 12 .xdef .letterleftbrace B.string{E
+.catcode `.} 12 .xdef .letterrightbrace B.string}E
+.catcode `.& 12 .xdef .letterampersand B.string&E
+.catcode `.< 12 .xdef .letterless B.string<E
+.catcode `.> 12 .xdef .lettermore B.string>E
+.catcode `.# 12 .xdef .letterhash B.string#E
+.catcode `." 12 .xdef .letterdoublequote B.string"E
+.catcode `.' 12 .xdef .lettersinglequote B.string'E
+.catcode `.$ 12 .xdef .letterdollar B.string$E
+.catcode `.% 12 .xdef .letterpercent B.string%E
+.catcode `.^ 12 .xdef .letterhat B.string^E
+.catcode `._ 12 .xdef .letterunderscore B.string_E
+.catcode `.| 12 .xdef .letterbar B.string|E
+.catcode `.~ 12 .xdef .lettertilde B.string~E
+.catcode `.\ 12 .xdef .letterbackslash B.string\E
+.catcode `./ 12 .xdef .letterslash B.string/E
+.catcode `.? 12 .xdef .letterquestionmark B.string?E
+.catcode `.! 12 .xdef .letterexclamationmark B.string!E
+.catcode `.@ 12 .xdef .letterat B.string@E
+.catcode `.: 12 .xdef .lettercolon B.string:E
+
+.catcode `.( 12 .xdef .letterleftparenthesis B.string(E
+.catcode `.) 12 .xdef .letterrightparenthesis B.string)E
+.catcode `.[ 12 .xdef .letterleftbracket B.string[E
+.catcode `.] 12 .xdef .letterrightbracket B.string]E
+
+ .global .let .letterescape .letterbackslash
+ .global .let .letterbgroup .letterleftbrace
+ .global .let .letteregroup .letterrightbrace
+ .global .let .letteropenbrace .letterleftbrace
+ .global .let .letterclosebrace .letterrightbrace
+
+.egroup
+
+%D \macros
+%D {uncatcodespecials,setnaturalcatcodes,setnormalcatcodes,
+%D uncatcodecharacters,uncatcodeallcharacters,
+%D uncatcodespacetokens}
+%D
+%D The following macros are more or less replaced by switching
+%D to a catcode table (which we simulate in \MKII) but we keep
+%D them for convenience and compatibility. Some old engine code
+%D has been removed.
+
+\normalprotected\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens}
+\normalprotected\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes}
+\normalprotected\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes
+\normalprotected\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now
+\normalprotected\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore
+
+\normalprotected\def\uncatcodespacetokens
+ {\catcode\spaceasciicode \spacecatcode
+ \catcode\tabasciicode \spacecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\endoflineasciicode\endoflinecatcode
+ \catcode\delasciicode \ignorecatcode}
+
+%D \macros
+%D {setverbosecharacter,setverbosecscharacters}
+%D
+%D Next follows a definition that lets some shortcuts expand to
+%D themselves. This macro is meant for \POSTSCRIPT\ and \PDF\
+%D code passed on to the backend.
+
+\newtoks\everyverbosechacters
+
+\normalprotected\def\setverbosecscharacter#1%
+ {\edef#1{\string#1}}
+
+\normalprotected\def\setverbosecscharacters
+ {\the\everyverbosechacters}
+
+\bgroup
+
+ % if used often we can move the code inline
+
+ \catcode\barasciicode \activecatcode
+ \catcode\tildeasciicode\activecatcode
+
+ \global \everyverbosechacters =
+ {\setverbosecscharacter |\setverbosecscharacter ~% context specific
+ \setverbosecscharacter\|\setverbosecscharacter\~%
+ \setverbosecscharacter\:\setverbosecscharacter\;%
+ \setverbosecscharacter\+\setverbosecscharacter\-%
+ \setverbosecscharacter\[\setverbosecscharacter\]%
+ \setverbosecscharacter\.\setverbosecscharacter\\%
+ \setverbosecscharacter\)\setverbosecscharacter\(%
+ \setverbosecscharacter\0\setverbosecscharacter\1%
+ \setverbosecscharacter\2\setverbosecscharacter\3%
+ \setverbosecscharacter\4\setverbosecscharacter\5%
+ \setverbosecscharacter\6\setverbosecscharacter\7%
+ \setverbosecscharacter\8\setverbosecscharacter\9%
+ \setverbosecscharacter\n\setverbosecscharacter\s%
+ \setverbosecscharacter\/}
+
+\egroup
+
+%D (Inspired by a discussion on the \CONTEXT\ mailing list)
+%D
+%D In \TEX\ each character can have one of 16 catcodes. This way the
+%D backslash, dollar, ampersand, hash and some more characters get
+%D their special meaning. If you want to process tokens under a
+%D certain catcode regime, passing arguments can interfere badly.
+%D
+%D \startbuffer[a]
+%D \def\whatever#1{[#1]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D Here we pass an argument to \type {\whatever} but part of that
+%D argument is to be processed under a different catcode regime, i.e.\
+%D all characters that need to be typeset verbatim need to get
+%D the catcode that makes it a letter. This is what we get when we typeset
+%D the text verbatim:
+%D
+%D \starttyping
+%D whatever \type {\whatever{you want}} $or$ not!
+%D \stoptyping
+%D
+%D However, when passed to \type {\whatever} we get:
+%D
+%D \getbuffer[a]
+%D
+%D In \ETEX\ one can use \type {\scantokens} to circumvent this problem.
+%D
+%D \startbuffer[b]
+%D \def\rescan#1{\scantokens{#1}}
+%D \def\whatever#1{[\rescan{#1}]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \getbuffer[b] \typebuffer[b]
+%D
+%D This time the \type {\whatever} call gives:
+%D
+%D \getbuffer[b]
+%D
+%D In this example, two spaces have crept in. The first one, after the
+%D macro name, is inserted by \TEX\ and cannot be avoided. The last space
+%D is inserted by \type {\scantokens}, and is the consequence of the fact
+%D that this macro mimics reading from a file. You can avoid the last
+%D space by a slightly different definition:
+%D
+%D \startbuffer[c]
+%D \def\rescan#1{\scantokens{#1\ignorespaces}}
+%D \def\whatever#1{[\rescan{#1}]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \typebuffer[c]
+%D
+%D Unfortunately we still keep the first space, but at least it's better than
+%D a failure:
+%D
+%D \getbuffer[c]
+
+\def\rescan #1{\scantokens{#1\ignorespaces}}
+\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantokens{#2\ignorespaces}\endgroup}
+
+\ifx\scantextokens\undefined \else
+ \def\rescan #1{\scantextokens{#1}}
+ \def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup}
+\fi
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-xml.mkiv
new file mode 100644
index 00000000000..a23a2fe0a26
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/catc-xml.mkiv
@@ -0,0 +1,124 @@
+%D \module
+%D [ file=catc-xml,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=\XML\ Catcode Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Catcode Regimes / XML}
+
+\ifdefined \xmlcatcodesn \else \newcatcodetable \xmlcatcodesn \fi % normal
+\ifdefined \xmlcatcodese \else \newcatcodetable \xmlcatcodese \fi % entitle
+\ifdefined \xmlcatcodesr \else \newcatcodetable \xmlcatcodesr \fi % reduce
+
+\startcatcodetable \xmlcatcodesn
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\ampersandasciicode \activecatcode
+ \catcode`\< \activecatcode
+ \catcode`\> \othercatcode
+ \catcode`\" \othercatcode % probably not needed any more
+ \catcode`\/ \othercatcode % probably not needed any more
+ \catcode`\' \othercatcode % probably not needed any more
+ \catcode\tildeasciicode \othercatcode % probably not needed any more
+ \catcode\hashasciicode \othercatcode % probably not needed any more
+ \catcode\backslashasciicode \othercatcode % probably not needed any more
+\stopcatcodetable
+
+\startcatcodetable \xmlcatcodese
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\ampersandasciicode \activecatcode
+ \catcode`\< \activecatcode
+ \catcode`\> \activecatcode
+ \catcode\hashasciicode \activecatcode
+ \catcode\dollarasciicode \activecatcode
+ \catcode\commentasciicode \activecatcode
+ \catcode\backslashasciicode \activecatcode
+ \catcode\circumflexasciicode\activecatcode
+ \catcode\underscoreasciicode\activecatcode
+ \catcode\leftbraceasciicode \activecatcode
+ \catcode\rightbraceasciicode\activecatcode
+ \catcode\barasciicode \activecatcode
+ \catcode\tildeasciicode \activecatcode
+\stopcatcodetable
+
+\startcatcodetable \xmlcatcodesr
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\ampersandasciicode \activecatcode
+ \catcode`\< \activecatcode
+ \catcode`\> \activecatcode
+ \catcode\hashasciicode \activecatcode
+ \catcode\dollarasciicode \activecatcode
+ \catcode\commentasciicode \activecatcode
+ \catcode\backslashasciicode \activecatcode
+ \catcode\circumflexasciicode\activecatcode
+ \catcode\underscoreasciicode\activecatcode
+ \catcode\leftbraceasciicode \activecatcode
+ \catcode\rightbraceasciicode\activecatcode
+ \catcode\barasciicode \activecatcode
+ \catcode\tildeasciicode \activecatcode
+\stopcatcodetable
+
+%D Next we hook in some active character definitions.
+
+\letcatcodecommand \xmlcatcodesn \ampersandasciicode \relax
+\letcatcodecommand \xmlcatcodesn `\< \relax
+
+\letcatcodecommand \xmlcatcodese \ampersandasciicode \relax
+\letcatcodecommand \xmlcatcodese `\< \relax
+
+\letcatcodecommand \xmlcatcodesr \ampersandasciicode \relax
+\letcatcodecommand \xmlcatcodesr `\< \relax
+
+\letcatcodecommand \xmlcatcodese \hashasciicode \relax
+\letcatcodecommand \xmlcatcodese \dollarasciicode \relax
+\letcatcodecommand \xmlcatcodese \commentasciicode \relax
+\letcatcodecommand \xmlcatcodese \backslashasciicode \relax
+\letcatcodecommand \xmlcatcodese \circumflexasciicode \relax
+\letcatcodecommand \xmlcatcodese \underscoreasciicode \relax
+\letcatcodecommand \xmlcatcodese \leftbraceasciicode \relax
+\letcatcodecommand \xmlcatcodese \rightbraceasciicode \relax
+\letcatcodecommand \xmlcatcodese \barasciicode \relax
+\letcatcodecommand \xmlcatcodese \tildeasciicode \relax
+
+\letcatcodecommand \xmlcatcodesr \hashasciicode \relax
+\letcatcodecommand \xmlcatcodesr \dollarasciicode \relax
+\letcatcodecommand \xmlcatcodesr \commentasciicode \relax
+\letcatcodecommand \xmlcatcodesr \backslashasciicode \relax
+\letcatcodecommand \xmlcatcodesr \circumflexasciicode \relax
+\letcatcodecommand \xmlcatcodesr \underscoreasciicode \relax
+\letcatcodecommand \xmlcatcodesr \leftbraceasciicode \relax
+\letcatcodecommand \xmlcatcodesr \rightbraceasciicode \relax
+\letcatcodecommand \xmlcatcodesr \barasciicode \relax
+\letcatcodecommand \xmlcatcodesr \tildeasciicode \relax
+
+\let\xmlcatcodes \xmlcatcodesn % beware, in mkiv we use \notcatcodes
+
+%D We register the catcodetables at the \LUA\ end where some further
+%D initializations take place.
+
+\ctxcommand{definecatcodetable(
+ {\number\xmlcatcodesn,\number\xmlcatcodese,\number\xmlcatcodesr},% letter catcodes
+ {\number\xmlcatcodesn,\number\xmlcatcodese,\number\xmlcatcodesr} % activate catcodes
+)}
+
+\ctxcommand{registercatcodetable("xmlcatcodes",\number\xmlcatcodes)}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv
new file mode 100644
index 00000000000..7d7268c8ba6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=char-act,
+%D version=2006.12.05,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Active,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Character Support / Active}
+
+\unprotect
+
+\ifdefined\page_otr_fill_and_eject_page \else \let\page_otr_fill_and_eject_page\relax \fi % forward reference
+
+%D \macros
+%D {obeyedspace, obeyedtab, obeyedline, obeyedpage}
+%D
+%D We have followed Knuth in naming macros that make \SPACE,
+%D \NEWLINE\ and \NEWPAGE\ active and assigning them
+%D \type{\obeysomething}, but first we set some default values.
+
+% These are expandable!
+
+\def\obeyedspace {\space}
+\def\obeyedtab {\obeyedspace}
+\def\obeyedline {\par}
+\def\obeyedpage {\page_otr_fill_and_eject_page}
+
+%D \macros
+%D {controlspace,setcontrolspaces}
+%D
+%D First we define \type{\obeyspaces}. When we want visible
+%D spaces (control spaces) we only have to adapt the definition
+%D of \type{\obeyedspace} to:
+
+\chardef\asciispacechar\spaceasciicode % a real space character
+
+\unexpanded\def\naturalspace{\asciispacechar}
+\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
+
+%D \macros
+%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages}
+%D
+%D Next we take care of \NEWLINE\ and \NEWPAGE\ and because we
+%D want to be able to typeset listings that contain \TAB, we
+%D have to handle those too. Because we have to redefine the
+%D \NEWPAGE\ character locally, we redefine the meaning of
+%D this (often already) active character.
+
+\expandafter\def\activeformfeedtoken{\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\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
+\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+\unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
+\unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+
+%D \macros
+%D {naturaltextext}
+%D
+%D When one uses \ETEX, switching to normal \TEX\ is possible
+%D too. We also introduce a switch that can be used in the
+%D drivers and set in higher level shell macros.
+
+\unexpanded\def\naturaltextext#1\relax % this command will become obsolete
+ {\begingroup
+ \def\ascii{#1}%
+ \setcatcodetable\ctxcatcodes
+ \prettynaturalfont{\scantextokens\expandafter{\ascii}\ifhmode\unskip\fi}%
+ \endgroup}
+
+\endinput \protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-cjk.lua b/Master/texmf-dist/tex/context/base/mkiv/char-cjk.lua
new file mode 100644
index 00000000000..9d6b28a603a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-cjk.lua
@@ -0,0 +1,1293 @@
+if not modules then modules = { } end modules ['char-cjk'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, next = setmetatable, next
+local insert = table.insert
+local floor = math.floor
+local formatters = string.formatters
+local utfchar = utf.char
+
+local setmetatableindex = table.setmetatableindex
+
+characters = characters or { }
+local ranges = characters.ranges
+local allocate = utilities.storage.allocate
+
+-- Hangul Syllable
+
+-- The following conversion is taken from unicode.org/reports/tr15/tr15-23.html#Hangul
+-- but adapted to our needs.
+
+-- local SBase = 0xAC00
+--
+-- local LBase, LCount = 0x1100, 19
+-- local VBase, VCount = 0x1161, 21
+-- local TBase, TCount = 0x11A7, 28
+--
+-- local NCount = VCount * TCount
+-- local SCount = LCount * NCount
+--
+-- local function decomposed(unicode)
+-- local SIndex = unicode - SBase
+-- if SIndex >= 0 and SIndex < SCount then
+-- local lead_consonant = LBase + floor( SIndex / NCount)
+-- local medial_vowel = VBase + floor((SIndex % NCount) / TCount)
+-- local tail_consonant = TBase + SIndex % TCount
+-- if tail_consonant ~= TBase then
+-- return lead_consonant, medial_vowel, tail_consonant
+-- else
+-- return lead_consonant, medial_vowel
+-- end
+-- end
+-- end
+--
+-- Lua will optimize the inline constants so the next variant is
+-- 10% faster. In practice this will go unnoticed, but it's also less
+-- code, so let's do it. Pushing the constant section into the
+-- function body saves 5%.
+
+local function decomposed(unicode)
+ local index = unicode - 0xAC00
+ if index >= 0 and index < 19 * 21 * 28 then
+ local lead_consonant = 0x1100 + floor( index / (21 * 28))
+ local medial_vowel = 0x1161 + floor((index % (21 * 28)) / 28)
+ local tail_consonant = 0x11A7 + index % 28
+ if tail_consonant ~= 0x11A7 then
+ return lead_consonant, medial_vowel, tail_consonant
+ else
+ return lead_consonant, medial_vowel
+ end
+ end
+end
+
+local lead_consonants = { [0] =
+ "G", "GG", "N", "D", "DD", "R", "M", "B", "BB",
+ "S", "SS", "", "J", "JJ", "C", "K", "T", "P", "H"
+}
+
+local medial_vowels = { [0] =
+ "A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O",
+ "WA", "WAE", "OE", "YO", "U", "WEO", "WE", "WI",
+ "YU", "EU", "YI", "I"
+}
+
+local tail_consonants = { [0] =
+ "", "G", "GG", "GS", "N", "NJ", "NH", "D", "L", "LG", "LM",
+ "LB", "LS", "LT", "LP", "LH", "M", "B", "BS",
+ "S", "SS", "NG", "J", "C", "K", "T", "P", "H"
+}
+
+-- local function description(unicode)
+-- local index = unicode - 0xAC00
+-- if index >= 0 and index < 19 * 21 * 28 then
+-- local lead_consonant = floor( index / NCount)
+-- local medial_vowel = floor((index % NCount) / TCount)
+-- local tail_consonant = index % TCount
+-- return formatters["HANGUL SYLLABLE %s%s%s"](
+-- lead_consonants[lead_consonant],
+-- medial_vowels [medial_vowel ],
+-- tail_consonants[tail_consonant]
+-- )
+-- end
+-- end
+
+local function description(unicode)
+ local index = unicode - 0xAC00
+ if index >= 0 and index < 19 * 21 * 28 then
+ local lead_consonant = floor( index / (21 * 28))
+ local medial_vowel = floor((index % (21 * 28)) / 28)
+ local tail_consonant = index % 28
+ return formatters["HANGUL SYLLABLE %s%s%s"](
+ lead_consonants[lead_consonant],
+ medial_vowels [medial_vowel ],
+ tail_consonants[tail_consonant]
+ )
+ end
+end
+
+-- so far
+
+-- We have a [lead consonant,medial vowel,tail consonant] where the last one
+-- is optional. For sort ranges we need the first one but some are collapsed.
+-- Beware, we map to modern so the font should support it.
+
+local function leadconsonant(unicode)
+ return
+ -- unicode < 0xAC00 and nil -- original
+ -- unicode > 0xD7AF and nil or -- original
+ unicode >= 0xD558 and 0x314E or -- 하 => ㅎ
+ unicode >= 0xD30C and 0x314D or -- 파 => ㅍ
+ unicode >= 0xD0C0 and 0x314C or -- 타 => ㅌ
+ unicode >= 0xCE74 and 0x314B or -- 카 => ㅋ
+ unicode >= 0xCC28 and 0x314A or -- 차 => ㅊ
+ unicode >= 0xC790 and 0x3148 or -- 자 => ㅈ
+ unicode >= 0xC544 and 0x3147 or -- 아 => ㅇ
+ unicode >= 0xC0AC and 0x3145 or -- 사 => ㅅ
+ unicode >= 0xBC14 and 0x3142 or -- 바 => ㅂ
+ unicode >= 0xB9C8 and 0x3141 or -- 마 => ㅁ
+ unicode >= 0xB77C and 0x3139 or -- 라 => ㄹ
+ unicode >= 0xB2E4 and 0x3137 or -- 다 => ㄷ
+ unicode >= 0xB098 and 0x3134 or -- 나 => ㄴ
+ unicode >= 0xAC00 and 0x3131 or -- 가 => ㄱ
+ nil -- can't happen
+end
+
+local remapped = { -- this might be merged into char-def.lua
+ [0x1100] = 0x3131, -- G
+ [0x1101] = 0x3132, -- GG
+ [0x1102] = 0x3134, -- N
+ [0x1103] = 0x3137, -- D
+ [0x1104] = 0x3138, -- DD
+ [0x1105] = 0x3139, -- R
+ -- [0X111A] = 0x3140, -- LH used for last sound
+ [0x1106] = 0x3141, -- M
+ [0x1107] = 0x3142, -- B
+ [0x1108] = 0x3143, -- BB
+ -- [0x1121] = 0x3144, -- BS used for last sound
+ [0x1109] = 0x3145, -- S
+ [0x110A] = 0x3146, -- SS
+ [0x110B] = 0x3147, -- (IEUNG) no sound but has form
+ [0x110C] = 0x3148, -- J
+ [0x110D] = 0x3149, -- JJ
+ [0x110E] = 0x314A, -- C
+ [0x110F] = 0x314B, -- K
+ [0x1110] = 0x314C, -- T
+ [0x1111] = 0x314D, -- P
+ [0x1112] = 0x314E, -- H
+
+ [0x1161] = 0x314F, -- A
+ [0x1162] = 0x3150, -- AE
+ [0x1163] = 0x3151, -- YA
+ [0x1164] = 0x3152, -- YAE
+ [0x1165] = 0x3153, -- EO
+ [0x1166] = 0x3154, -- E
+ [0x1167] = 0x3155, -- YEO
+ [0x1168] = 0x3156, -- YE
+ [0x1169] = 0x3157, -- O
+ [0x116A] = 0x3158, -- WA
+ [0x116B] = 0x3159, -- WAE
+ [0x116C] = 0x315A, -- OE
+ [0x116D] = 0x315B, -- YO
+ [0x116E] = 0x315C, -- U
+ [0x116F] = 0x315D, -- WEO
+ [0x1170] = 0x315E, -- WE
+ [0x1171] = 0x315F, -- WI
+ [0x1172] = 0x3160, -- YU
+ [0x1173] = 0x3161, -- EU
+ [0x1174] = 0x3162, -- YI
+ [0x1175] = 0x3163, -- I
+
+ [0x11A8] = 0x3131, -- G
+ [0x11A9] = 0x3132, -- GG
+ [0x11AA] = 0x3133, -- GS
+ [0x11AB] = 0x3134, -- N
+ [0x11AC] = 0x3135, -- NJ
+ [0x11AD] = 0x3136, -- NH
+ [0x11AE] = 0x3137, -- D
+ [0x11AF] = 0x3139, -- L
+ [0x11B0] = 0x313A, -- LG
+ [0x11B1] = 0x313B, -- LM
+ [0x11B2] = 0x313C, -- LB
+ [0x11B3] = 0x313D, -- LS
+ [0x11B4] = 0x313E, -- LT
+ [0x11B5] = 0x313F, -- LP
+ [0x11B6] = 0x3140, -- LH
+ [0x11B7] = 0x3141, -- M
+ [0x11B8] = 0x3142, -- B
+ [0x11B9] = 0x3144, -- BS
+ [0x11BA] = 0x3145, -- S
+ [0x11BB] = 0x3146, -- SS
+ [0x11BC] = 0x3147, -- NG
+ [0x11BD] = 0x3148, -- J
+ [0x11BE] = 0x314A, -- C
+ [0x11BF] = 0x314B, -- K
+ [0x11C0] = 0x314C, -- T
+ [0x11C1] = 0x314D, -- P
+ [0x11C2] = 0x314E, -- H
+}
+
+characters.hangul = allocate {
+ decomposed = decomposed,
+ description = description,
+ leadconsonant = leadconsonant,
+ remapped = remapped,
+}
+
+-- so far
+
+local hangul_syllable_basetable = {
+ category = "lo",
+ cjkwd = "w",
+ description = "<Hangul Syllable>",
+ direction = "l",
+ linebreak = "h2",
+}
+
+local hangul_syllable_metatable = {
+ __index = function(t,k)
+ local u = t.unicodeslot
+ if k == "fscode" or k == "leadconsonant" then
+ return leadconsonant(u)
+ elseif k == "decomposed" then
+ return { decomposed(u) }
+ elseif k == "specials" then
+ return { "char", decomposed(u) }
+ elseif k == "description" then
+ return description(u)
+ else
+ return hangul_syllable_basetable[k]
+ end
+ end
+}
+
+function characters.remap_hangul_syllabe(t)
+ local tt = type(t)
+ if tt == "number" then
+ return remapped[t] or t
+ elseif tt == "table" then
+ local r = { }
+ for i=1,#t do
+ local ti = t[i]
+ r[i] = remapped[ti] or ti
+ end
+ return r
+ else
+ return t
+ end
+end
+
+local hangul_syllable_extender = function(k)
+ local t = {
+ unicodeslot = k,
+ }
+ setmetatable(t,hangul_syllable_metatable)
+ return t
+end
+
+local hangul_syllable_range = {
+ name = "hangul",
+ first = 0xAC00,
+ last = 0xD7A3,
+ extender = hangul_syllable_extender,
+}
+
+setmetatable(hangul_syllable_range, hangul_syllable_metatable)
+
+-- CJK Ideograph
+
+local knownvariants = {
+ [0x0349E] = { [0x0FE00] = 0x2F80C },
+ [0x034B9] = { [0x0FE00] = 0x2F813 },
+ [0x034BB] = { [0x0FE00] = 0x2F9CA },
+ [0x034DF] = { [0x0FE00] = 0x2F81F },
+ [0x03515] = { [0x0FE00] = 0x2F824 },
+ [0x036EE] = { [0x0FE00] = 0x2F867 },
+ [0x036FC] = { [0x0FE00] = 0x2F868 },
+ [0x03781] = { [0x0FE00] = 0x2F876 },
+ [0x0382F] = { [0x0FE00] = 0x2F883 },
+ [0x03862] = { [0x0FE00] = 0x2F888 },
+ [0x0387C] = { [0x0FE00] = 0x2F88A },
+ [0x038C7] = { [0x0FE00] = 0x2F896 },
+ [0x038E3] = { [0x0FE00] = 0x2F89B },
+ [0x0391C] = { [0x0FE00] = 0x2F8A2 },
+ [0x0393A] = { [0x0FE00] = 0x2F8A1 },
+ [0x03A2E] = { [0x0FE00] = 0x2F8C2 },
+ [0x03A6C] = { [0x0FE00] = 0x2F8C7 },
+ [0x03AE4] = { [0x0FE00] = 0x2F8D1 },
+ [0x03B08] = { [0x0FE00] = 0x2F8D0 },
+ [0x03B19] = { [0x0FE00] = 0x2F8CE },
+ [0x03B49] = { [0x0FE00] = 0x2F8DE },
+ [0x03B9D] = { [0x0FE00] = 0x0FAD2, [0x0FE01] = 0x2F8E7 },
+ [0x03C18] = { [0x0FE00] = 0x2F8EE },
+ [0x03C4E] = { [0x0FE00] = 0x2F8F2 },
+ [0x03D33] = { [0x0FE00] = 0x2F90A },
+ [0x03D96] = { [0x0FE00] = 0x2F916 },
+ [0x03EAC] = { [0x0FE00] = 0x2F92A },
+ [0x03EB8] = { [0x0FE00] = 0x2F92C, [0x0FE01] = 0x2F92D },
+ [0x03F1B] = { [0x0FE00] = 0x2F933 },
+ [0x03FFC] = { [0x0FE00] = 0x2F93E },
+ [0x04008] = { [0x0FE00] = 0x2F93F },
+ [0x04018] = { [0x0FE00] = 0x0FAD3 },
+ [0x04039] = { [0x0FE00] = 0x0FAD4, [0x0FE01] = 0x2F949 },
+ [0x04046] = { [0x0FE00] = 0x2F94B },
+ [0x04096] = { [0x0FE00] = 0x2F94C },
+ [0x040E3] = { [0x0FE00] = 0x2F951 },
+ [0x0412F] = { [0x0FE00] = 0x2F958 },
+ [0x04202] = { [0x0FE00] = 0x2F960 },
+ [0x04227] = { [0x0FE00] = 0x2F964 },
+ [0x042A0] = { [0x0FE00] = 0x2F967 },
+ [0x04301] = { [0x0FE00] = 0x2F96D },
+ [0x04334] = { [0x0FE00] = 0x2F971 },
+ [0x04359] = { [0x0FE00] = 0x2F974 },
+ [0x043D5] = { [0x0FE00] = 0x2F981 },
+ [0x043D9] = { [0x0FE00] = 0x2F8D7 },
+ [0x0440B] = { [0x0FE00] = 0x2F984 },
+ [0x0446B] = { [0x0FE00] = 0x2F98E },
+ [0x0452B] = { [0x0FE00] = 0x2F9A7 },
+ [0x0455D] = { [0x0FE00] = 0x2F9AE },
+ [0x04561] = { [0x0FE00] = 0x2F9AF },
+ [0x0456B] = { [0x0FE00] = 0x2F9B2 },
+ [0x045D7] = { [0x0FE00] = 0x2F9BF },
+ [0x045F9] = { [0x0FE00] = 0x2F9C2 },
+ [0x04635] = { [0x0FE00] = 0x2F9C8 },
+ [0x046BE] = { [0x0FE00] = 0x2F9CD },
+ [0x046C7] = { [0x0FE00] = 0x2F9CE },
+ [0x04995] = { [0x0FE00] = 0x2F9EF },
+ [0x049E6] = { [0x0FE00] = 0x2F9F2 },
+ [0x04A6E] = { [0x0FE00] = 0x2F9F8 },
+ [0x04A76] = { [0x0FE00] = 0x2F9F9 },
+ [0x04AB2] = { [0x0FE00] = 0x2F9FC },
+ [0x04B33] = { [0x0FE00] = 0x2FA03 },
+ [0x04BCE] = { [0x0FE00] = 0x2FA08 },
+ [0x04CCE] = { [0x0FE00] = 0x2FA0D },
+ [0x04CED] = { [0x0FE00] = 0x2FA0E },
+ [0x04CF8] = { [0x0FE00] = 0x2FA11 },
+ [0x04D56] = { [0x0FE00] = 0x2FA16 },
+ [0x04E0D] = { [0x0FE00] = 0x0F967 },
+ [0x04E26] = { [0x0FE00] = 0x0FA70 },
+ [0x04E32] = { [0x0FE00] = 0x0F905 },
+ [0x04E38] = { [0x0FE00] = 0x2F801 },
+ [0x04E39] = { [0x0FE00] = 0x0F95E },
+ [0x04E3D] = { [0x0FE00] = 0x2F800 },
+ [0x04E41] = { [0x0FE00] = 0x2F802 },
+ [0x04E82] = { [0x0FE00] = 0x0F91B },
+ [0x04E86] = { [0x0FE00] = 0x0F9BA },
+ [0x04EAE] = { [0x0FE00] = 0x0F977 },
+ [0x04EC0] = { [0x0FE00] = 0x0F9FD },
+ [0x04ECC] = { [0x0FE00] = 0x2F819 },
+ [0x04EE4] = { [0x0FE00] = 0x0F9A8 },
+ [0x04F60] = { [0x0FE00] = 0x2F804 },
+ [0x04F80] = { [0x0FE00] = 0x0FA73 },
+ [0x04F86] = { [0x0FE00] = 0x0F92D },
+ [0x04F8B] = { [0x0FE00] = 0x0F9B5 },
+ [0x04FAE] = { [0x0FE00] = 0x0FA30, [0x0FE01] = 0x2F805 },
+ [0x04FBB] = { [0x0FE00] = 0x2F806 },
+ [0x04FBF] = { [0x0FE00] = 0x0F965 },
+ [0x05002] = { [0x0FE00] = 0x2F807 },
+ [0x0502B] = { [0x0FE00] = 0x0F9D4 },
+ [0x0507A] = { [0x0FE00] = 0x2F808 },
+ [0x05099] = { [0x0FE00] = 0x2F809 },
+ [0x050CF] = { [0x0FE00] = 0x2F80B },
+ [0x050DA] = { [0x0FE00] = 0x0F9BB },
+ [0x050E7] = { [0x0FE00] = 0x0FA31, [0x0FE01] = 0x2F80A },
+ [0x05140] = { [0x0FE00] = 0x0FA0C },
+ [0x05145] = { [0x0FE00] = 0x0FA74 },
+ [0x0514D] = { [0x0FE00] = 0x0FA32, [0x0FE01] = 0x2F80E },
+ [0x05154] = { [0x0FE00] = 0x2F80F },
+ [0x05164] = { [0x0FE00] = 0x2F810 },
+ [0x05167] = { [0x0FE00] = 0x2F814 },
+ [0x05168] = { [0x0FE00] = 0x0FA72 },
+ [0x05169] = { [0x0FE00] = 0x0F978 },
+ [0x0516D] = { [0x0FE00] = 0x0F9D1 },
+ [0x05177] = { [0x0FE00] = 0x2F811 },
+ [0x05180] = { [0x0FE00] = 0x0FA75 },
+ [0x0518D] = { [0x0FE00] = 0x2F815 },
+ [0x05192] = { [0x0FE00] = 0x2F8D2 },
+ [0x05195] = { [0x0FE00] = 0x2F8D3 },
+ [0x05197] = { [0x0FE00] = 0x2F817 },
+ [0x051A4] = { [0x0FE00] = 0x2F818 },
+ [0x051AC] = { [0x0FE00] = 0x2F81A },
+ [0x051B5] = { [0x0FE00] = 0x0FA71, [0x0FE01] = 0x2F81B },
+ [0x051B7] = { [0x0FE00] = 0x0F92E },
+ [0x051C9] = { [0x0FE00] = 0x0F979 },
+ [0x051CC] = { [0x0FE00] = 0x0F955 },
+ [0x051DC] = { [0x0FE00] = 0x0F954 },
+ [0x051DE] = { [0x0FE00] = 0x0FA15 },
+ [0x051F5] = { [0x0FE00] = 0x2F81D },
+ [0x05203] = { [0x0FE00] = 0x2F81E },
+ [0x05207] = { [0x0FE00] = 0x0FA00, [0x0FE01] = 0x2F850 },
+ [0x05217] = { [0x0FE00] = 0x0F99C },
+ [0x05229] = { [0x0FE00] = 0x0F9DD },
+ [0x0523A] = { [0x0FE00] = 0x0F9FF },
+ [0x0523B] = { [0x0FE00] = 0x2F820 },
+ [0x05246] = { [0x0FE00] = 0x2F821 },
+ [0x05272] = { [0x0FE00] = 0x2F822 },
+ [0x05277] = { [0x0FE00] = 0x2F823 },
+ [0x05289] = { [0x0FE00] = 0x0F9C7 },
+ [0x0529B] = { [0x0FE00] = 0x0F98A },
+ [0x052A3] = { [0x0FE00] = 0x0F99D },
+ [0x052B3] = { [0x0FE00] = 0x2F992 },
+ [0x052C7] = { [0x0FE00] = 0x0FA76, [0x0FE01] = 0x2F825 },
+ [0x052C9] = { [0x0FE00] = 0x0FA33, [0x0FE01] = 0x2F826 },
+ [0x052D2] = { [0x0FE00] = 0x0F952 },
+ [0x052DE] = { [0x0FE00] = 0x0F92F },
+ [0x052E4] = { [0x0FE00] = 0x0FA34, [0x0FE01] = 0x2F827 },
+ [0x052F5] = { [0x0FE00] = 0x0F97F },
+ [0x052FA] = { [0x0FE00] = 0x0FA77, [0x0FE01] = 0x2F828 },
+ [0x05305] = { [0x0FE00] = 0x2F829 },
+ [0x05306] = { [0x0FE00] = 0x2F82A },
+ [0x05317] = { [0x0FE00] = 0x0F963, [0x0FE01] = 0x2F82B },
+ [0x0533F] = { [0x0FE00] = 0x0F9EB },
+ [0x05349] = { [0x0FE00] = 0x2F82C },
+ [0x05351] = { [0x0FE00] = 0x0FA35, [0x0FE01] = 0x2F82D },
+ [0x0535A] = { [0x0FE00] = 0x2F82E },
+ [0x05373] = { [0x0FE00] = 0x2F82F },
+ [0x05375] = { [0x0FE00] = 0x0F91C },
+ [0x0537D] = { [0x0FE00] = 0x2F830 },
+ [0x0537F] = { [0x0FE00] = 0x2F831, [0x0FE01] = 0x2F832, [0x0FE02] = 0x2F833 },
+ [0x053C3] = { [0x0FE00] = 0x0F96B },
+ [0x053CA] = { [0x0FE00] = 0x2F836 },
+ [0x053DF] = { [0x0FE00] = 0x2F837 },
+ [0x053E5] = { [0x0FE00] = 0x0F906 },
+ [0x053EB] = { [0x0FE00] = 0x2F839 },
+ [0x053F1] = { [0x0FE00] = 0x2F83A },
+ [0x05406] = { [0x0FE00] = 0x2F83B },
+ [0x0540F] = { [0x0FE00] = 0x0F9DE },
+ [0x0541D] = { [0x0FE00] = 0x0F9ED },
+ [0x05438] = { [0x0FE00] = 0x2F83D },
+ [0x05442] = { [0x0FE00] = 0x0F980 },
+ [0x05448] = { [0x0FE00] = 0x2F83E },
+ [0x05468] = { [0x0FE00] = 0x2F83F },
+ [0x0549E] = { [0x0FE00] = 0x2F83C },
+ [0x054A2] = { [0x0FE00] = 0x2F840 },
+ [0x054BD] = { [0x0FE00] = 0x0F99E },
+ [0x054F6] = { [0x0FE00] = 0x2F841 },
+ [0x05510] = { [0x0FE00] = 0x2F842 },
+ [0x05553] = { [0x0FE00] = 0x2F843 },
+ [0x05555] = { [0x0FE00] = 0x0FA79 },
+ [0x05563] = { [0x0FE00] = 0x2F844 },
+ [0x05584] = { [0x0FE00] = 0x2F845, [0x0FE01] = 0x2F846 },
+ [0x05587] = { [0x0FE00] = 0x0F90B },
+ [0x05599] = { [0x0FE00] = 0x0FA7A, [0x0FE01] = 0x2F847 },
+ [0x0559D] = { [0x0FE00] = 0x0FA36, [0x0FE01] = 0x0FA78 },
+ [0x055AB] = { [0x0FE00] = 0x2F848 },
+ [0x055B3] = { [0x0FE00] = 0x2F849 },
+ [0x055C0] = { [0x0FE00] = 0x0FA0D },
+ [0x055C2] = { [0x0FE00] = 0x2F84A },
+ [0x055E2] = { [0x0FE00] = 0x0FA7B },
+ [0x05606] = { [0x0FE00] = 0x0FA37, [0x0FE01] = 0x2F84C },
+ [0x05651] = { [0x0FE00] = 0x2F84E },
+ [0x05668] = { [0x0FE00] = 0x0FA38 },
+ [0x05674] = { [0x0FE00] = 0x2F84F },
+ [0x056F9] = { [0x0FE00] = 0x0F9A9 },
+ [0x05716] = { [0x0FE00] = 0x2F84B },
+ [0x05717] = { [0x0FE00] = 0x2F84D },
+ [0x0578B] = { [0x0FE00] = 0x2F855 },
+ [0x057CE] = { [0x0FE00] = 0x2F852 },
+ [0x057F4] = { [0x0FE00] = 0x2F853 },
+ [0x0580D] = { [0x0FE00] = 0x2F854 },
+ [0x05831] = { [0x0FE00] = 0x2F857 },
+ [0x05832] = { [0x0FE00] = 0x2F856 },
+ [0x05840] = { [0x0FE00] = 0x0FA39 },
+ [0x0585A] = { [0x0FE00] = 0x0FA10, [0x0FE01] = 0x0FA7C },
+ [0x0585E] = { [0x0FE00] = 0x0F96C },
+ [0x058A8] = { [0x0FE00] = 0x0FA3A },
+ [0x058AC] = { [0x0FE00] = 0x2F858 },
+ [0x058B3] = { [0x0FE00] = 0x0FA7D },
+ [0x058D8] = { [0x0FE00] = 0x0F94A },
+ [0x058DF] = { [0x0FE00] = 0x0F942 },
+ [0x058EE] = { [0x0FE00] = 0x2F851 },
+ [0x058F2] = { [0x0FE00] = 0x2F85A },
+ [0x058F7] = { [0x0FE00] = 0x2F85B },
+ [0x05906] = { [0x0FE00] = 0x2F85C },
+ [0x0591A] = { [0x0FE00] = 0x2F85D },
+ [0x05922] = { [0x0FE00] = 0x2F85E },
+ [0x05944] = { [0x0FE00] = 0x0FA7E },
+ [0x05948] = { [0x0FE00] = 0x0F90C },
+ [0x05951] = { [0x0FE00] = 0x0F909 },
+ [0x05954] = { [0x0FE00] = 0x0FA7F },
+ [0x05962] = { [0x0FE00] = 0x2F85F },
+ [0x05973] = { [0x0FE00] = 0x0F981 },
+ [0x059D8] = { [0x0FE00] = 0x2F865 },
+ [0x059EC] = { [0x0FE00] = 0x2F862 },
+ [0x05A1B] = { [0x0FE00] = 0x2F863 },
+ [0x05A27] = { [0x0FE00] = 0x2F864 },
+ [0x05A62] = { [0x0FE00] = 0x0FA80 },
+ [0x05A66] = { [0x0FE00] = 0x2F866 },
+ [0x05AB5] = { [0x0FE00] = 0x2F986 },
+ [0x05B08] = { [0x0FE00] = 0x2F869 },
+ [0x05B28] = { [0x0FE00] = 0x0FA81 },
+ [0x05B3E] = { [0x0FE00] = 0x2F86A, [0x0FE01] = 0x2F86B },
+ [0x05B85] = { [0x0FE00] = 0x0FA04 },
+ [0x05BC3] = { [0x0FE00] = 0x2F86D },
+ [0x05BD8] = { [0x0FE00] = 0x2F86E },
+ [0x05BE7] = { [0x0FE00] = 0x0F95F, [0x0FE01] = 0x0F9AA, [0x0FE02] = 0x2F86F },
+ [0x05BEE] = { [0x0FE00] = 0x0F9BC },
+ [0x05BF3] = { [0x0FE00] = 0x2F870 },
+ [0x05BFF] = { [0x0FE00] = 0x2F872 },
+ [0x05C06] = { [0x0FE00] = 0x2F873 },
+ [0x05C22] = { [0x0FE00] = 0x2F875 },
+ [0x05C3F] = { [0x0FE00] = 0x0F9BD },
+ [0x05C60] = { [0x0FE00] = 0x2F877 },
+ [0x05C62] = { [0x0FE00] = 0x0F94B },
+ [0x05C64] = { [0x0FE00] = 0x0FA3B },
+ [0x05C65] = { [0x0FE00] = 0x0F9DF },
+ [0x05C6E] = { [0x0FE00] = 0x0FA3C, [0x0FE01] = 0x2F878 },
+ [0x05C8D] = { [0x0FE00] = 0x2F87A },
+ [0x05CC0] = { [0x0FE00] = 0x2F879 },
+ [0x05D19] = { [0x0FE00] = 0x0F9D5 },
+ [0x05D43] = { [0x0FE00] = 0x2F87C },
+ [0x05D50] = { [0x0FE00] = 0x0F921 },
+ [0x05D6B] = { [0x0FE00] = 0x2F87F },
+ [0x05D6E] = { [0x0FE00] = 0x2F87E },
+ [0x05D7C] = { [0x0FE00] = 0x2F880 },
+ [0x05DB2] = { [0x0FE00] = 0x2F9F4 },
+ [0x05DBA] = { [0x0FE00] = 0x0F9AB },
+ [0x05DE1] = { [0x0FE00] = 0x2F881 },
+ [0x05DE2] = { [0x0FE00] = 0x2F882 },
+ [0x05DFD] = { [0x0FE00] = 0x2F884 },
+ [0x05E28] = { [0x0FE00] = 0x2F885 },
+ [0x05E3D] = { [0x0FE00] = 0x2F886 },
+ [0x05E69] = { [0x0FE00] = 0x2F887 },
+ [0x05E74] = { [0x0FE00] = 0x0F98E },
+ [0x05EA6] = { [0x0FE00] = 0x0FA01 },
+ [0x05EB0] = { [0x0FE00] = 0x2F88B },
+ [0x05EB3] = { [0x0FE00] = 0x2F88C },
+ [0x05EB6] = { [0x0FE00] = 0x2F88D },
+ [0x05EC9] = { [0x0FE00] = 0x0F9A2 },
+ [0x05ECA] = { [0x0FE00] = 0x0F928, [0x0FE01] = 0x2F88E },
+ [0x05ED2] = { [0x0FE00] = 0x0FA82 },
+ [0x05ED3] = { [0x0FE00] = 0x0FA0B },
+ [0x05ED9] = { [0x0FE00] = 0x0FA83 },
+ [0x05EEC] = { [0x0FE00] = 0x0F982 },
+ [0x05EFE] = { [0x0FE00] = 0x2F890 },
+ [0x05F04] = { [0x0FE00] = 0x0F943 },
+ [0x05F22] = { [0x0FE00] = 0x2F894, [0x0FE01] = 0x2F895 },
+ [0x05F53] = { [0x0FE00] = 0x2F874 },
+ [0x05F62] = { [0x0FE00] = 0x2F899 },
+ [0x05F69] = { [0x0FE00] = 0x0FA84 },
+ [0x05F6B] = { [0x0FE00] = 0x2F89A },
+ [0x05F8B] = { [0x0FE00] = 0x0F9D8 },
+ [0x05F9A] = { [0x0FE00] = 0x2F89C },
+ [0x05FA9] = { [0x0FE00] = 0x0F966 },
+ [0x05FAD] = { [0x0FE00] = 0x0FA85 },
+ [0x05FCD] = { [0x0FE00] = 0x2F89D },
+ [0x05FD7] = { [0x0FE00] = 0x2F89E },
+ [0x05FF5] = { [0x0FE00] = 0x0F9A3 },
+ [0x05FF9] = { [0x0FE00] = 0x2F89F },
+ [0x06012] = { [0x0FE00] = 0x0F960 },
+ [0x0601C] = { [0x0FE00] = 0x0F9AC },
+ [0x06075] = { [0x0FE00] = 0x0FA6B },
+ [0x06081] = { [0x0FE00] = 0x2F8A0 },
+ [0x06094] = { [0x0FE00] = 0x0FA3D, [0x0FE01] = 0x2F8A3 },
+ [0x060C7] = { [0x0FE00] = 0x2F8A5 },
+ [0x060D8] = { [0x0FE00] = 0x0FA86 },
+ [0x060E1] = { [0x0FE00] = 0x0F9B9 },
+ [0x06108] = { [0x0FE00] = 0x0FA88 },
+ [0x06144] = { [0x0FE00] = 0x0F9D9 },
+ [0x06148] = { [0x0FE00] = 0x2F8A6 },
+ [0x0614C] = { [0x0FE00] = 0x2F8A7, [0x0FE01] = 0x2F8A9 },
+ [0x0614E] = { [0x0FE00] = 0x0FA87, [0x0FE01] = 0x2F8A8 },
+ [0x06160] = { [0x0FE00] = 0x0FA8A },
+ [0x06168] = { [0x0FE00] = 0x0FA3E },
+ [0x0617A] = { [0x0FE00] = 0x2F8AA },
+ [0x0618E] = { [0x0FE00] = 0x0FA3F, [0x0FE01] = 0x0FA89, [0x0FE02] = 0x2F8AB },
+ [0x06190] = { [0x0FE00] = 0x0F98F },
+ [0x061A4] = { [0x0FE00] = 0x2F8AD },
+ [0x061AF] = { [0x0FE00] = 0x2F8AE },
+ [0x061B2] = { [0x0FE00] = 0x2F8AC },
+ [0x061DE] = { [0x0FE00] = 0x2F8AF },
+ [0x061F2] = { [0x0FE00] = 0x0FA40, [0x0FE01] = 0x0FA8B, [0x0FE02] = 0x2F8B0 },
+ [0x061F6] = { [0x0FE00] = 0x0F90D, [0x0FE01] = 0x2F8B1 },
+ [0x06200] = { [0x0FE00] = 0x0F990 },
+ [0x06210] = { [0x0FE00] = 0x2F8B2 },
+ [0x0621B] = { [0x0FE00] = 0x2F8B3 },
+ [0x0622E] = { [0x0FE00] = 0x0F9D2 },
+ [0x06234] = { [0x0FE00] = 0x0FA8C },
+ [0x0625D] = { [0x0FE00] = 0x2F8B4 },
+ [0x062B1] = { [0x0FE00] = 0x2F8B5 },
+ [0x062C9] = { [0x0FE00] = 0x0F925 },
+ [0x062CF] = { [0x0FE00] = 0x0F95B },
+ [0x062D3] = { [0x0FE00] = 0x0FA02 },
+ [0x062D4] = { [0x0FE00] = 0x2F8B6 },
+ [0x062FC] = { [0x0FE00] = 0x2F8BA },
+ [0x062FE] = { [0x0FE00] = 0x0F973 },
+ [0x0633D] = { [0x0FE00] = 0x2F8B9 },
+ [0x06350] = { [0x0FE00] = 0x2F8B7 },
+ [0x06368] = { [0x0FE00] = 0x2F8BB },
+ [0x0637B] = { [0x0FE00] = 0x0F9A4 },
+ [0x06383] = { [0x0FE00] = 0x2F8BC },
+ [0x063A0] = { [0x0FE00] = 0x0F975 },
+ [0x063A9] = { [0x0FE00] = 0x2F8C1 },
+ [0x063C4] = { [0x0FE00] = 0x0FA8D },
+ [0x063C5] = { [0x0FE00] = 0x2F8C0 },
+ [0x063E4] = { [0x0FE00] = 0x2F8BD },
+ [0x0641C] = { [0x0FE00] = 0x0FA8E },
+ [0x06422] = { [0x0FE00] = 0x2F8BF },
+ [0x06452] = { [0x0FE00] = 0x0FA8F },
+ [0x06469] = { [0x0FE00] = 0x2F8C3 },
+ [0x06477] = { [0x0FE00] = 0x2F8C6 },
+ [0x0647E] = { [0x0FE00] = 0x2F8C4 },
+ [0x0649A] = { [0x0FE00] = 0x0F991 },
+ [0x0649D] = { [0x0FE00] = 0x2F8C5 },
+ [0x064C4] = { [0x0FE00] = 0x0F930 },
+ [0x0654F] = { [0x0FE00] = 0x0FA41, [0x0FE01] = 0x2F8C8 },
+ [0x06556] = { [0x0FE00] = 0x0FA90 },
+ [0x0656C] = { [0x0FE00] = 0x2F8C9 },
+ [0x06578] = { [0x0FE00] = 0x0F969 },
+ [0x06599] = { [0x0FE00] = 0x0F9BE },
+ [0x065C5] = { [0x0FE00] = 0x0F983 },
+ [0x065E2] = { [0x0FE00] = 0x0FA42 },
+ [0x065E3] = { [0x0FE00] = 0x2F8CB },
+ [0x06613] = { [0x0FE00] = 0x0F9E0 },
+ [0x06649] = { [0x0FE00] = 0x2F8CD },
+ [0x06674] = { [0x0FE00] = 0x0FA12, [0x0FE01] = 0x0FA91 },
+ [0x06688] = { [0x0FE00] = 0x0F9C5 },
+ [0x06691] = { [0x0FE00] = 0x0FA43, [0x0FE01] = 0x2F8CF },
+ [0x0669C] = { [0x0FE00] = 0x2F8D5 },
+ [0x066B4] = { [0x0FE00] = 0x0FA06 },
+ [0x066C6] = { [0x0FE00] = 0x0F98B },
+ [0x066F4] = { [0x0FE00] = 0x0F901 },
+ [0x066F8] = { [0x0FE00] = 0x2F8CC },
+ [0x06700] = { [0x0FE00] = 0x2F8D4 },
+ [0x06717] = { [0x0FE00] = 0x0F929, [0x0FE01] = 0x0FA92, [0x0FE02] = 0x2F8D8 },
+ [0x0671B] = { [0x0FE00] = 0x0FA93, [0x0FE01] = 0x2F8D9 },
+ [0x06721] = { [0x0FE00] = 0x2F8DA },
+ [0x0674E] = { [0x0FE00] = 0x0F9E1 },
+ [0x06753] = { [0x0FE00] = 0x2F8DC },
+ [0x06756] = { [0x0FE00] = 0x0FA94 },
+ [0x0675E] = { [0x0FE00] = 0x2F8DB },
+ [0x0677B] = { [0x0FE00] = 0x0F9C8 },
+ [0x06785] = { [0x0FE00] = 0x2F8E0 },
+ [0x06797] = { [0x0FE00] = 0x0F9F4 },
+ [0x067F3] = { [0x0FE00] = 0x0F9C9 },
+ [0x067FA] = { [0x0FE00] = 0x2F8DF },
+ [0x06817] = { [0x0FE00] = 0x0F9DA },
+ [0x0681F] = { [0x0FE00] = 0x2F8E5 },
+ [0x06852] = { [0x0FE00] = 0x2F8E1 },
+ [0x06881] = { [0x0FE00] = 0x0F97A },
+ [0x06885] = { [0x0FE00] = 0x0FA44, [0x0FE01] = 0x2F8E2 },
+ [0x0688E] = { [0x0FE00] = 0x2F8E4 },
+ [0x068A8] = { [0x0FE00] = 0x0F9E2 },
+ [0x06914] = { [0x0FE00] = 0x2F8E6 },
+ [0x06942] = { [0x0FE00] = 0x2F8E8 },
+ [0x069A3] = { [0x0FE00] = 0x2F8E9 },
+ [0x069EA] = { [0x0FE00] = 0x2F8EA },
+ [0x06A02] = { [0x0FE00] = 0x0F914, [0x0FE01] = 0x0F95C, [0x0FE02] = 0x0F9BF },
+ [0x06A13] = { [0x0FE00] = 0x0F94C },
+ [0x06AA8] = { [0x0FE00] = 0x2F8EB },
+ [0x06AD3] = { [0x0FE00] = 0x0F931 },
+ [0x06ADB] = { [0x0FE00] = 0x2F8ED },
+ [0x06B04] = { [0x0FE00] = 0x0F91D },
+ [0x06B21] = { [0x0FE00] = 0x2F8EF },
+ [0x06B54] = { [0x0FE00] = 0x2F8F1 },
+ [0x06B72] = { [0x0FE00] = 0x2F8F3 },
+ [0x06B77] = { [0x0FE00] = 0x0F98C },
+ [0x06B79] = { [0x0FE00] = 0x0FA95 },
+ [0x06B9F] = { [0x0FE00] = 0x2F8F4 },
+ [0x06BAE] = { [0x0FE00] = 0x0F9A5 },
+ [0x06BBA] = { [0x0FE00] = 0x0F970, [0x0FE01] = 0x0FA96, [0x0FE02] = 0x2F8F5 },
+ [0x06BBB] = { [0x0FE00] = 0x2F8F6 },
+ [0x06C4E] = { [0x0FE00] = 0x2F8FA },
+ [0x06C67] = { [0x0FE00] = 0x2F8FE },
+ [0x06C88] = { [0x0FE00] = 0x0F972 },
+ [0x06CBF] = { [0x0FE00] = 0x2F8FC },
+ [0x06CCC] = { [0x0FE00] = 0x0F968 },
+ [0x06CCD] = { [0x0FE00] = 0x2F8FD },
+ [0x06CE5] = { [0x0FE00] = 0x0F9E3 },
+ [0x06D16] = { [0x0FE00] = 0x2F8FF },
+ [0x06D1B] = { [0x0FE00] = 0x0F915 },
+ [0x06D1E] = { [0x0FE00] = 0x0FA05 },
+ [0x06D34] = { [0x0FE00] = 0x2F907 },
+ [0x06D3E] = { [0x0FE00] = 0x2F900 },
+ [0x06D41] = { [0x0FE00] = 0x0F9CA, [0x0FE01] = 0x0FA97, [0x0FE02] = 0x2F902 },
+ [0x06D69] = { [0x0FE00] = 0x2F903 },
+ [0x06D6A] = { [0x0FE00] = 0x0F92A },
+ [0x06D77] = { [0x0FE00] = 0x0FA45, [0x0FE01] = 0x2F901 },
+ [0x06D78] = { [0x0FE00] = 0x2F904 },
+ [0x06D85] = { [0x0FE00] = 0x2F905 },
+ [0x06DCB] = { [0x0FE00] = 0x0F9F5 },
+ [0x06DDA] = { [0x0FE00] = 0x0F94D },
+ [0x06DEA] = { [0x0FE00] = 0x0F9D6 },
+ [0x06DF9] = { [0x0FE00] = 0x2F90E },
+ [0x06E1A] = { [0x0FE00] = 0x0FA46 },
+ [0x06E2F] = { [0x0FE00] = 0x2F908 },
+ [0x06E6E] = { [0x0FE00] = 0x2F909 },
+ [0x06E9C] = { [0x0FE00] = 0x0F9CB },
+ [0x06EBA] = { [0x0FE00] = 0x0F9EC },
+ [0x06EC7] = { [0x0FE00] = 0x2F90C },
+ [0x06ECB] = { [0x0FE00] = 0x0FA99, [0x0FE01] = 0x2F90B },
+ [0x06ED1] = { [0x0FE00] = 0x0F904 },
+ [0x06EDB] = { [0x0FE00] = 0x0FA98 },
+ [0x06F0F] = { [0x0FE00] = 0x0F94E },
+ [0x06F22] = { [0x0FE00] = 0x0FA47, [0x0FE01] = 0x0FA9A },
+ [0x06F23] = { [0x0FE00] = 0x0F992 },
+ [0x06F6E] = { [0x0FE00] = 0x2F90F },
+ [0x06FC6] = { [0x0FE00] = 0x2F912 },
+ [0x06FEB] = { [0x0FE00] = 0x0F922 },
+ [0x06FFE] = { [0x0FE00] = 0x0F984 },
+ [0x0701B] = { [0x0FE00] = 0x2F915 },
+ [0x0701E] = { [0x0FE00] = 0x0FA9B, [0x0FE01] = 0x2F914 },
+ [0x07039] = { [0x0FE00] = 0x2F913 },
+ [0x0704A] = { [0x0FE00] = 0x2F917 },
+ [0x07070] = { [0x0FE00] = 0x2F835 },
+ [0x07077] = { [0x0FE00] = 0x2F919 },
+ [0x0707D] = { [0x0FE00] = 0x2F918 },
+ [0x07099] = { [0x0FE00] = 0x0F9FB },
+ [0x070AD] = { [0x0FE00] = 0x2F91A },
+ [0x070C8] = { [0x0FE00] = 0x0F99F },
+ [0x070D9] = { [0x0FE00] = 0x0F916 },
+ [0x07145] = { [0x0FE00] = 0x2F91C },
+ [0x07149] = { [0x0FE00] = 0x0F993 },
+ [0x0716E] = { [0x0FE00] = 0x0FA48, [0x0FE01] = 0x0FA9C },
+ [0x0719C] = { [0x0FE00] = 0x2F91E },
+ [0x071CE] = { [0x0FE00] = 0x0F9C0 },
+ [0x071D0] = { [0x0FE00] = 0x0F9EE },
+ [0x07210] = { [0x0FE00] = 0x0F932 },
+ [0x0721B] = { [0x0FE00] = 0x0F91E },
+ [0x07228] = { [0x0FE00] = 0x2F920 },
+ [0x0722B] = { [0x0FE00] = 0x0FA49 },
+ [0x07235] = { [0x0FE00] = 0x0FA9E, [0x0FE01] = 0x2F921 },
+ [0x07250] = { [0x0FE00] = 0x2F922 },
+ [0x07262] = { [0x0FE00] = 0x0F946 },
+ [0x07280] = { [0x0FE00] = 0x2F924 },
+ [0x07295] = { [0x0FE00] = 0x2F925 },
+ [0x072AF] = { [0x0FE00] = 0x0FA9F },
+ [0x072C0] = { [0x0FE00] = 0x0F9FA },
+ [0x072FC] = { [0x0FE00] = 0x0F92B },
+ [0x0732A] = { [0x0FE00] = 0x0FA16, [0x0FE01] = 0x0FAA0 },
+ [0x07375] = { [0x0FE00] = 0x0F9A7 },
+ [0x0737A] = { [0x0FE00] = 0x2F928 },
+ [0x07387] = { [0x0FE00] = 0x0F961, [0x0FE01] = 0x0F9DB },
+ [0x0738B] = { [0x0FE00] = 0x2F929 },
+ [0x073A5] = { [0x0FE00] = 0x2F92B },
+ [0x073B2] = { [0x0FE00] = 0x0F9AD },
+ [0x073DE] = { [0x0FE00] = 0x0F917 },
+ [0x07406] = { [0x0FE00] = 0x0F9E4 },
+ [0x07409] = { [0x0FE00] = 0x0F9CC },
+ [0x07422] = { [0x0FE00] = 0x0FA4A },
+ [0x07447] = { [0x0FE00] = 0x2F92E },
+ [0x0745C] = { [0x0FE00] = 0x2F92F },
+ [0x07469] = { [0x0FE00] = 0x0F9AE },
+ [0x07471] = { [0x0FE00] = 0x0FAA1, [0x0FE01] = 0x2F930 },
+ [0x07485] = { [0x0FE00] = 0x2F931 },
+ [0x07489] = { [0x0FE00] = 0x0F994 },
+ [0x07498] = { [0x0FE00] = 0x0F9EF },
+ [0x074CA] = { [0x0FE00] = 0x2F932 },
+ [0x07506] = { [0x0FE00] = 0x0FAA2 },
+ [0x07524] = { [0x0FE00] = 0x2F934 },
+ [0x0753B] = { [0x0FE00] = 0x0FAA3 },
+ [0x0753E] = { [0x0FE00] = 0x2F936 },
+ [0x07559] = { [0x0FE00] = 0x0F9CD },
+ [0x07565] = { [0x0FE00] = 0x0F976 },
+ [0x07570] = { [0x0FE00] = 0x0F962, [0x0FE01] = 0x2F938 },
+ [0x075E2] = { [0x0FE00] = 0x0F9E5 },
+ [0x07610] = { [0x0FE00] = 0x2F93A },
+ [0x0761D] = { [0x0FE00] = 0x0FAA4 },
+ [0x0761F] = { [0x0FE00] = 0x0FAA5 },
+ [0x07642] = { [0x0FE00] = 0x0F9C1 },
+ [0x07669] = { [0x0FE00] = 0x0F90E },
+ [0x076CA] = { [0x0FE00] = 0x0FA17, [0x0FE01] = 0x0FAA6 },
+ [0x076DB] = { [0x0FE00] = 0x0FAA7 },
+ [0x076E7] = { [0x0FE00] = 0x0F933 },
+ [0x076F4] = { [0x0FE00] = 0x0FAA8, [0x0FE01] = 0x2F940 },
+ [0x07701] = { [0x0FE00] = 0x0F96D },
+ [0x0771E] = { [0x0FE00] = 0x2F945 },
+ [0x0771F] = { [0x0FE00] = 0x2F946, [0x0FE01] = 0x2F947 },
+ [0x07740] = { [0x0FE00] = 0x0FAAA },
+ [0x0774A] = { [0x0FE00] = 0x0FAA9, [0x0FE01] = 0x2F948 },
+ [0x0778B] = { [0x0FE00] = 0x2F94A },
+ [0x077A7] = { [0x0FE00] = 0x0FA9D },
+ [0x0784E] = { [0x0FE00] = 0x2F94E },
+ [0x0786B] = { [0x0FE00] = 0x0F9CE },
+ [0x0788C] = { [0x0FE00] = 0x0F93B, [0x0FE01] = 0x2F94F },
+ [0x07891] = { [0x0FE00] = 0x0FA4B },
+ [0x078CA] = { [0x0FE00] = 0x0F947 },
+ [0x078CC] = { [0x0FE00] = 0x0FAAB, [0x0FE01] = 0x2F950 },
+ [0x078FB] = { [0x0FE00] = 0x0F964 },
+ [0x0792A] = { [0x0FE00] = 0x0F985 },
+ [0x0793C] = { [0x0FE00] = 0x0FA18 },
+ [0x0793E] = { [0x0FE00] = 0x0FA4C },
+ [0x07948] = { [0x0FE00] = 0x0FA4E },
+ [0x07949] = { [0x0FE00] = 0x0FA4D },
+ [0x07950] = { [0x0FE00] = 0x0FA4F },
+ [0x07956] = { [0x0FE00] = 0x0FA50, [0x0FE01] = 0x2F953 },
+ [0x0795D] = { [0x0FE00] = 0x0FA51 },
+ [0x0795E] = { [0x0FE00] = 0x0FA19 },
+ [0x07965] = { [0x0FE00] = 0x0FA1A },
+ [0x0797F] = { [0x0FE00] = 0x0F93C },
+ [0x0798D] = { [0x0FE00] = 0x0FA52 },
+ [0x0798E] = { [0x0FE00] = 0x0FA53 },
+ [0x0798F] = { [0x0FE00] = 0x0FA1B, [0x0FE01] = 0x2F956 },
+ [0x079AE] = { [0x0FE00] = 0x0F9B6 },
+ [0x079CA] = { [0x0FE00] = 0x0F995 },
+ [0x079EB] = { [0x0FE00] = 0x2F957 },
+ [0x07A1C] = { [0x0FE00] = 0x0F956 },
+ [0x07A40] = { [0x0FE00] = 0x0FA54, [0x0FE01] = 0x2F959 },
+ [0x07A4A] = { [0x0FE00] = 0x2F95A },
+ [0x07A4F] = { [0x0FE00] = 0x2F95B },
+ [0x07A81] = { [0x0FE00] = 0x0FA55 },
+ [0x07AB1] = { [0x0FE00] = 0x0FAAC },
+ [0x07ACB] = { [0x0FE00] = 0x0F9F7 },
+ [0x07AEE] = { [0x0FE00] = 0x2F95F },
+ [0x07B20] = { [0x0FE00] = 0x0F9F8 },
+ [0x07BC0] = { [0x0FE00] = 0x0FA56, [0x0FE01] = 0x0FAAD },
+ [0x07BC6] = { [0x0FE00] = 0x2F962 },
+ [0x07BC9] = { [0x0FE00] = 0x2F963 },
+ [0x07C3E] = { [0x0FE00] = 0x0F9A6 },
+ [0x07C60] = { [0x0FE00] = 0x0F944 },
+ [0x07C7B] = { [0x0FE00] = 0x0FAAE },
+ [0x07C92] = { [0x0FE00] = 0x0F9F9 },
+ [0x07CBE] = { [0x0FE00] = 0x0FA1D },
+ [0x07CD2] = { [0x0FE00] = 0x2F966 },
+ [0x07CD6] = { [0x0FE00] = 0x0FA03 },
+ [0x07CE3] = { [0x0FE00] = 0x2F969 },
+ [0x07CE7] = { [0x0FE00] = 0x0F97B },
+ [0x07CE8] = { [0x0FE00] = 0x2F968 },
+ [0x07D00] = { [0x0FE00] = 0x2F96A },
+ [0x07D10] = { [0x0FE00] = 0x0F9CF },
+ [0x07D22] = { [0x0FE00] = 0x0F96A },
+ [0x07D2F] = { [0x0FE00] = 0x0F94F },
+ [0x07D5B] = { [0x0FE00] = 0x0FAAF },
+ [0x07D63] = { [0x0FE00] = 0x2F96C },
+ [0x07DA0] = { [0x0FE00] = 0x0F93D },
+ [0x07DBE] = { [0x0FE00] = 0x0F957 },
+ [0x07DC7] = { [0x0FE00] = 0x2F96E },
+ [0x07DF4] = { [0x0FE00] = 0x0F996, [0x0FE01] = 0x0FA57, [0x0FE02] = 0x0FAB0 },
+ [0x07E02] = { [0x0FE00] = 0x2F96F },
+ [0x07E09] = { [0x0FE00] = 0x0FA58 },
+ [0x07E37] = { [0x0FE00] = 0x0F950 },
+ [0x07E41] = { [0x0FE00] = 0x0FA59 },
+ [0x07E45] = { [0x0FE00] = 0x2F970 },
+ [0x07F3E] = { [0x0FE00] = 0x0FAB1 },
+ [0x07F72] = { [0x0FE00] = 0x0FA5A },
+ [0x07F79] = { [0x0FE00] = 0x0F9E6 },
+ [0x07F7A] = { [0x0FE00] = 0x2F976 },
+ [0x07F85] = { [0x0FE00] = 0x0F90F },
+ [0x07F95] = { [0x0FE00] = 0x2F978 },
+ [0x07F9A] = { [0x0FE00] = 0x0F9AF },
+ [0x07FBD] = { [0x0FE00] = 0x0FA1E },
+ [0x07FFA] = { [0x0FE00] = 0x2F979 },
+ [0x08001] = { [0x0FE00] = 0x0F934 },
+ [0x08005] = { [0x0FE00] = 0x0FA5B, [0x0FE01] = 0x0FAB2, [0x0FE02] = 0x2F97A },
+ [0x08046] = { [0x0FE00] = 0x0F9B0 },
+ [0x08060] = { [0x0FE00] = 0x2F97D },
+ [0x0806F] = { [0x0FE00] = 0x0F997 },
+ [0x08070] = { [0x0FE00] = 0x2F97F },
+ [0x0807E] = { [0x0FE00] = 0x0F945 },
+ [0x0808B] = { [0x0FE00] = 0x0F953 },
+ [0x080AD] = { [0x0FE00] = 0x2F8D6 },
+ [0x080B2] = { [0x0FE00] = 0x2F982 },
+ [0x08103] = { [0x0FE00] = 0x2F983 },
+ [0x0813E] = { [0x0FE00] = 0x2F985 },
+ [0x081D8] = { [0x0FE00] = 0x0F926 },
+ [0x081E8] = { [0x0FE00] = 0x0F9F6 },
+ [0x081ED] = { [0x0FE00] = 0x0FA5C },
+ [0x08201] = { [0x0FE00] = 0x2F893, [0x0FE01] = 0x2F98B },
+ [0x08204] = { [0x0FE00] = 0x2F98C },
+ [0x08218] = { [0x0FE00] = 0x0FA6D },
+ [0x0826F] = { [0x0FE00] = 0x0F97C },
+ [0x08279] = { [0x0FE00] = 0x0FA5D, [0x0FE01] = 0x0FA5E },
+ [0x0828B] = { [0x0FE00] = 0x2F990 },
+ [0x08291] = { [0x0FE00] = 0x2F98F },
+ [0x0829D] = { [0x0FE00] = 0x2F991 },
+ [0x082B1] = { [0x0FE00] = 0x2F993 },
+ [0x082B3] = { [0x0FE00] = 0x2F994 },
+ [0x082BD] = { [0x0FE00] = 0x2F995 },
+ [0x082E5] = { [0x0FE00] = 0x0F974, [0x0FE01] = 0x2F998 },
+ [0x082E6] = { [0x0FE00] = 0x2F996 },
+ [0x0831D] = { [0x0FE00] = 0x2F999 },
+ [0x08323] = { [0x0FE00] = 0x2F99C },
+ [0x08336] = { [0x0FE00] = 0x0F9FE },
+ [0x08352] = { [0x0FE00] = 0x0FAB3 },
+ [0x08353] = { [0x0FE00] = 0x2F9A0 },
+ [0x08363] = { [0x0FE00] = 0x2F99A },
+ [0x083AD] = { [0x0FE00] = 0x2F99B },
+ [0x083BD] = { [0x0FE00] = 0x2F99D },
+ [0x083C9] = { [0x0FE00] = 0x0F93E },
+ [0x083CA] = { [0x0FE00] = 0x2F9A1 },
+ [0x083CC] = { [0x0FE00] = 0x2F9A2 },
+ [0x083DC] = { [0x0FE00] = 0x2F9A3 },
+ [0x083E7] = { [0x0FE00] = 0x2F99E },
+ [0x083EF] = { [0x0FE00] = 0x0FAB4 },
+ [0x083F1] = { [0x0FE00] = 0x0F958 },
+ [0x0843D] = { [0x0FE00] = 0x0F918 },
+ [0x08449] = { [0x0FE00] = 0x0F96E },
+ [0x08457] = { [0x0FE00] = 0x0FA5F, [0x0FE01] = 0x2F99F },
+ [0x084EE] = { [0x0FE00] = 0x0F999 },
+ [0x084F1] = { [0x0FE00] = 0x2F9A8 },
+ [0x084F3] = { [0x0FE00] = 0x2F9A9 },
+ [0x084FC] = { [0x0FE00] = 0x0F9C2 },
+ [0x08516] = { [0x0FE00] = 0x2F9AA },
+ [0x08564] = { [0x0FE00] = 0x2F9AC },
+ [0x085CD] = { [0x0FE00] = 0x0F923 },
+ [0x085FA] = { [0x0FE00] = 0x0F9F0 },
+ [0x08606] = { [0x0FE00] = 0x0F935 },
+ [0x08612] = { [0x0FE00] = 0x0FA20 },
+ [0x0862D] = { [0x0FE00] = 0x0F91F },
+ [0x0863F] = { [0x0FE00] = 0x0F910 },
+ [0x08650] = { [0x0FE00] = 0x2F9B3 },
+ [0x0865C] = { [0x0FE00] = 0x0F936, [0x0FE01] = 0x2F9B4 },
+ [0x08667] = { [0x0FE00] = 0x2F9B5 },
+ [0x08669] = { [0x0FE00] = 0x2F9B6 },
+ [0x08688] = { [0x0FE00] = 0x2F9B8 },
+ [0x086A9] = { [0x0FE00] = 0x2F9B7 },
+ [0x086E2] = { [0x0FE00] = 0x2F9BA },
+ [0x0870E] = { [0x0FE00] = 0x2F9B9 },
+ [0x08728] = { [0x0FE00] = 0x2F9BC },
+ [0x0876B] = { [0x0FE00] = 0x2F9BD },
+ [0x08779] = { [0x0FE00] = 0x0FAB5, [0x0FE01] = 0x2F9BB },
+ [0x08786] = { [0x0FE00] = 0x2F9BE },
+ [0x087BA] = { [0x0FE00] = 0x0F911 },
+ [0x087E1] = { [0x0FE00] = 0x2F9C0 },
+ [0x08801] = { [0x0FE00] = 0x2F9C1 },
+ [0x0881F] = { [0x0FE00] = 0x0F927 },
+ [0x0884C] = { [0x0FE00] = 0x0FA08 },
+ [0x08860] = { [0x0FE00] = 0x2F9C3 },
+ [0x08863] = { [0x0FE00] = 0x2F9C4 },
+ [0x088C2] = { [0x0FE00] = 0x0F9A0 },
+ [0x088CF] = { [0x0FE00] = 0x0F9E7 },
+ [0x088D7] = { [0x0FE00] = 0x2F9C6 },
+ [0x088DE] = { [0x0FE00] = 0x2F9C7 },
+ [0x088E1] = { [0x0FE00] = 0x0F9E8 },
+ [0x088F8] = { [0x0FE00] = 0x0F912 },
+ [0x088FA] = { [0x0FE00] = 0x2F9C9 },
+ [0x08910] = { [0x0FE00] = 0x0FA60 },
+ [0x08941] = { [0x0FE00] = 0x0FAB6 },
+ [0x08964] = { [0x0FE00] = 0x0F924 },
+ [0x08986] = { [0x0FE00] = 0x0FAB7 },
+ [0x0898B] = { [0x0FE00] = 0x0FA0A },
+ [0x08996] = { [0x0FE00] = 0x0FA61, [0x0FE01] = 0x0FAB8 },
+ [0x08AA0] = { [0x0FE00] = 0x2F9CF },
+ [0x08AAA] = { [0x0FE00] = 0x0F96F, [0x0FE01] = 0x0F9A1 },
+ [0x08ABF] = { [0x0FE00] = 0x0FAB9 },
+ [0x08ACB] = { [0x0FE00] = 0x0FABB },
+ [0x08AD2] = { [0x0FE00] = 0x0F97D },
+ [0x08AD6] = { [0x0FE00] = 0x0F941 },
+ [0x08AED] = { [0x0FE00] = 0x0FABE, [0x0FE01] = 0x2F9D0 },
+ [0x08AF8] = { [0x0FE00] = 0x0FA22, [0x0FE01] = 0x0FABA },
+ [0x08AFE] = { [0x0FE00] = 0x0F95D, [0x0FE01] = 0x0FABD },
+ [0x08B01] = { [0x0FE00] = 0x0FA62, [0x0FE01] = 0x0FABC },
+ [0x08B39] = { [0x0FE00] = 0x0FA63, [0x0FE01] = 0x0FABF },
+ [0x08B58] = { [0x0FE00] = 0x0F9FC },
+ [0x08B80] = { [0x0FE00] = 0x0F95A },
+ [0x08B8A] = { [0x0FE00] = 0x0FAC0, [0x0FE01] = 0x2F9D1 },
+ [0x08C48] = { [0x0FE00] = 0x0F900 },
+ [0x08C55] = { [0x0FE00] = 0x2F9D2 },
+ [0x08CAB] = { [0x0FE00] = 0x2F9D4 },
+ [0x08CC1] = { [0x0FE00] = 0x2F9D5 },
+ [0x08CC2] = { [0x0FE00] = 0x0F948 },
+ [0x08CC8] = { [0x0FE00] = 0x0F903 },
+ [0x08CD3] = { [0x0FE00] = 0x0FA64 },
+ [0x08D08] = { [0x0FE00] = 0x0FA65, [0x0FE01] = 0x0FAC1 },
+ [0x08D1B] = { [0x0FE00] = 0x2F9D6 },
+ [0x08D77] = { [0x0FE00] = 0x2F9D7 },
+ [0x08DBC] = { [0x0FE00] = 0x2F9DB },
+ [0x08DCB] = { [0x0FE00] = 0x2F9DA },
+ [0x08DEF] = { [0x0FE00] = 0x0F937 },
+ [0x08DF0] = { [0x0FE00] = 0x2F9DC },
+ [0x08ECA] = { [0x0FE00] = 0x0F902 },
+ [0x08ED4] = { [0x0FE00] = 0x2F9DE },
+ [0x08F26] = { [0x0FE00] = 0x0F998 },
+ [0x08F2A] = { [0x0FE00] = 0x0F9D7 },
+ [0x08F38] = { [0x0FE00] = 0x0FAC2, [0x0FE01] = 0x2F9DF },
+ [0x08F3B] = { [0x0FE00] = 0x0FA07 },
+ [0x08F62] = { [0x0FE00] = 0x0F98D },
+ [0x08F9E] = { [0x0FE00] = 0x2F98D },
+ [0x08FB0] = { [0x0FE00] = 0x0F971 },
+ [0x08FB6] = { [0x0FE00] = 0x0FA66 },
+ [0x09023] = { [0x0FE00] = 0x0F99A },
+ [0x09038] = { [0x0FE00] = 0x0FA25, [0x0FE01] = 0x0FA67 },
+ [0x09072] = { [0x0FE00] = 0x0FAC3 },
+ [0x0907C] = { [0x0FE00] = 0x0F9C3 },
+ [0x0908F] = { [0x0FE00] = 0x0F913 },
+ [0x09094] = { [0x0FE00] = 0x2F9E2 },
+ [0x090CE] = { [0x0FE00] = 0x0F92C },
+ [0x090DE] = { [0x0FE00] = 0x0FA2E },
+ [0x090F1] = { [0x0FE00] = 0x2F9E3 },
+ [0x090FD] = { [0x0FE00] = 0x0FA26 },
+ [0x09111] = { [0x0FE00] = 0x2F9E4 },
+ [0x0911B] = { [0x0FE00] = 0x2F9E6 },
+ [0x0916A] = { [0x0FE00] = 0x0F919 },
+ [0x09199] = { [0x0FE00] = 0x0FAC4 },
+ [0x091B4] = { [0x0FE00] = 0x0F9B7 },
+ [0x091CC] = { [0x0FE00] = 0x0F9E9 },
+ [0x091CF] = { [0x0FE00] = 0x0F97E },
+ [0x091D1] = { [0x0FE00] = 0x0F90A },
+ [0x09234] = { [0x0FE00] = 0x0F9B1 },
+ [0x09238] = { [0x0FE00] = 0x2F9E7 },
+ [0x09276] = { [0x0FE00] = 0x0FAC5 },
+ [0x0927C] = { [0x0FE00] = 0x2F9EA },
+ [0x092D7] = { [0x0FE00] = 0x2F9E8 },
+ [0x092D8] = { [0x0FE00] = 0x2F9E9 },
+ [0x09304] = { [0x0FE00] = 0x0F93F },
+ [0x0934A] = { [0x0FE00] = 0x0F99B },
+ [0x093F9] = { [0x0FE00] = 0x2F9EB },
+ [0x09415] = { [0x0FE00] = 0x2F9EC },
+ [0x0958B] = { [0x0FE00] = 0x2F9EE },
+ [0x095AD] = { [0x0FE00] = 0x0F986 },
+ [0x095B7] = { [0x0FE00] = 0x2F9F0 },
+ [0x0962E] = { [0x0FE00] = 0x0F9C6 },
+ [0x0964B] = { [0x0FE00] = 0x0F951 },
+ [0x0964D] = { [0x0FE00] = 0x0FA09 },
+ [0x09675] = { [0x0FE00] = 0x0F959 },
+ [0x09678] = { [0x0FE00] = 0x0F9D3 },
+ [0x0967C] = { [0x0FE00] = 0x0FAC6 },
+ [0x09686] = { [0x0FE00] = 0x0F9DC },
+ [0x096A3] = { [0x0FE00] = 0x0F9F1 },
+ [0x096B7] = { [0x0FE00] = 0x0FA2F },
+ [0x096B8] = { [0x0FE00] = 0x0F9B8 },
+ [0x096C3] = { [0x0FE00] = 0x2F9F3 },
+ [0x096E2] = { [0x0FE00] = 0x0F9EA },
+ [0x096E3] = { [0x0FE00] = 0x0FA68, [0x0FE01] = 0x0FAC7 },
+ [0x096F6] = { [0x0FE00] = 0x0F9B2 },
+ [0x096F7] = { [0x0FE00] = 0x0F949 },
+ [0x09723] = { [0x0FE00] = 0x2F9F5 },
+ [0x09732] = { [0x0FE00] = 0x0F938 },
+ [0x09748] = { [0x0FE00] = 0x0F9B3 },
+ [0x09756] = { [0x0FE00] = 0x0FA1C, [0x0FE01] = 0x0FAC8 },
+ [0x097DB] = { [0x0FE00] = 0x0FAC9 },
+ [0x097E0] = { [0x0FE00] = 0x2F9FA },
+ [0x097FF] = { [0x0FE00] = 0x0FA69, [0x0FE01] = 0x0FACA },
+ [0x0980B] = { [0x0FE00] = 0x0FACB, [0x0FE01] = 0x2F9FE, [0x0FE02] = 0x2F9FF },
+ [0x09818] = { [0x0FE00] = 0x0F9B4 },
+ [0x09829] = { [0x0FE00] = 0x2FA00 },
+ [0x0983B] = { [0x0FE00] = 0x0FA6A, [0x0FE01] = 0x0FACC },
+ [0x0985E] = { [0x0FE00] = 0x0F9D0 },
+ [0x098E2] = { [0x0FE00] = 0x2FA02 },
+ [0x098EF] = { [0x0FE00] = 0x0FA2A },
+ [0x098FC] = { [0x0FE00] = 0x0FA2B },
+ [0x09928] = { [0x0FE00] = 0x0FA2C },
+ [0x09929] = { [0x0FE00] = 0x2FA04 },
+ [0x099A7] = { [0x0FE00] = 0x2FA05 },
+ [0x099C2] = { [0x0FE00] = 0x2FA06 },
+ [0x099F1] = { [0x0FE00] = 0x0F91A },
+ [0x099FE] = { [0x0FE00] = 0x2FA07 },
+ [0x09A6A] = { [0x0FE00] = 0x0F987 },
+ [0x09B12] = { [0x0FE00] = 0x0FACD, [0x0FE01] = 0x2FA0A },
+ [0x09B6F] = { [0x0FE00] = 0x0F939 },
+ [0x09C40] = { [0x0FE00] = 0x2FA0B },
+ [0x09C57] = { [0x0FE00] = 0x0F9F2 },
+ [0x09CFD] = { [0x0FE00] = 0x2FA0C },
+ [0x09D67] = { [0x0FE00] = 0x2FA0F },
+ [0x09DB4] = { [0x0FE00] = 0x0FA2D },
+ [0x09DFA] = { [0x0FE00] = 0x0F93A },
+ [0x09E1E] = { [0x0FE00] = 0x0F920 },
+ [0x09E7F] = { [0x0FE00] = 0x0F940 },
+ [0x09E97] = { [0x0FE00] = 0x0F988 },
+ [0x09E9F] = { [0x0FE00] = 0x0F9F3 },
+ [0x09EBB] = { [0x0FE00] = 0x2FA15 },
+ [0x09ECE] = { [0x0FE00] = 0x0F989 },
+ [0x09EF9] = { [0x0FE00] = 0x2FA17 },
+ [0x09EFE] = { [0x0FE00] = 0x2FA18 },
+ [0x09F05] = { [0x0FE00] = 0x2FA19 },
+ [0x09F0F] = { [0x0FE00] = 0x2FA1A },
+ [0x09F16] = { [0x0FE00] = 0x2FA1B },
+ [0x09F3B] = { [0x0FE00] = 0x2FA1C },
+ [0x09F43] = { [0x0FE00] = 0x0FAD8 },
+ [0x09F8D] = { [0x0FE00] = 0x0F9C4 },
+ [0x09F8E] = { [0x0FE00] = 0x0FAD9 },
+ [0x09F9C] = { [0x0FE00] = 0x0F907, [0x0FE01] = 0x0F908, [0x0FE02] = 0x0FACE },
+ [0x20122] = { [0x0FE00] = 0x2F803 },
+ [0x2051C] = { [0x0FE00] = 0x2F812 },
+ [0x20525] = { [0x0FE00] = 0x2F91B },
+ [0x2054B] = { [0x0FE00] = 0x2F816 },
+ [0x2063A] = { [0x0FE00] = 0x2F80D },
+ [0x20804] = { [0x0FE00] = 0x2F9D9 },
+ [0x208DE] = { [0x0FE00] = 0x2F9DD },
+ [0x20A2C] = { [0x0FE00] = 0x2F834 },
+ [0x20B63] = { [0x0FE00] = 0x2F838 },
+ [0x214E4] = { [0x0FE00] = 0x2F859 },
+ [0x216A8] = { [0x0FE00] = 0x2F860 },
+ [0x216EA] = { [0x0FE00] = 0x2F861 },
+ [0x219C8] = { [0x0FE00] = 0x2F86C },
+ [0x21B18] = { [0x0FE00] = 0x2F871 },
+ [0x21D0B] = { [0x0FE00] = 0x2F8F8 },
+ [0x21DE4] = { [0x0FE00] = 0x2F87B },
+ [0x21DE6] = { [0x0FE00] = 0x2F87D },
+ [0x22183] = { [0x0FE00] = 0x2F889 },
+ [0x2219F] = { [0x0FE00] = 0x2F939 },
+ [0x22331] = { [0x0FE00] = 0x2F891, [0x0FE01] = 0x2F892 },
+ [0x226D4] = { [0x0FE00] = 0x2F8A4 },
+ [0x22844] = { [0x0FE00] = 0x0FAD0 },
+ [0x2284A] = { [0x0FE00] = 0x0FACF },
+ [0x22B0C] = { [0x0FE00] = 0x2F8B8 },
+ [0x22BF1] = { [0x0FE00] = 0x2F8BE },
+ [0x2300A] = { [0x0FE00] = 0x2F8CA },
+ [0x232B8] = { [0x0FE00] = 0x2F897 },
+ [0x2335F] = { [0x0FE00] = 0x2F980 },
+ [0x23393] = { [0x0FE00] = 0x2F989 },
+ [0x2339C] = { [0x0FE00] = 0x2F98A },
+ [0x233C3] = { [0x0FE00] = 0x2F8DD },
+ [0x233D5] = { [0x0FE00] = 0x0FAD1 },
+ [0x2346D] = { [0x0FE00] = 0x2F8E3 },
+ [0x236A3] = { [0x0FE00] = 0x2F8EC },
+ [0x238A7] = { [0x0FE00] = 0x2F8F0 },
+ [0x23A8D] = { [0x0FE00] = 0x2F8F7 },
+ [0x23AFA] = { [0x0FE00] = 0x2F8F9 },
+ [0x23CBC] = { [0x0FE00] = 0x2F8FB },
+ [0x23D1E] = { [0x0FE00] = 0x2F906 },
+ [0x23ED1] = { [0x0FE00] = 0x2F90D },
+ [0x23F5E] = { [0x0FE00] = 0x2F910 },
+ [0x23F8E] = { [0x0FE00] = 0x2F911 },
+ [0x24263] = { [0x0FE00] = 0x2F91D },
+ [0x242EE] = { [0x0FE00] = 0x0FA6C },
+ [0x243AB] = { [0x0FE00] = 0x2F91F },
+ [0x24608] = { [0x0FE00] = 0x2F923 },
+ [0x24735] = { [0x0FE00] = 0x2F926 },
+ [0x24814] = { [0x0FE00] = 0x2F927 },
+ [0x24C36] = { [0x0FE00] = 0x2F935 },
+ [0x24C92] = { [0x0FE00] = 0x2F937 },
+ [0x24FA1] = { [0x0FE00] = 0x2F93B },
+ [0x24FB8] = { [0x0FE00] = 0x2F93C },
+ [0x25044] = { [0x0FE00] = 0x2F93D },
+ [0x250F2] = { [0x0FE00] = 0x2F942 },
+ [0x250F3] = { [0x0FE00] = 0x2F941 },
+ [0x25119] = { [0x0FE00] = 0x2F943 },
+ [0x25133] = { [0x0FE00] = 0x2F944 },
+ [0x25249] = { [0x0FE00] = 0x0FAD5 },
+ [0x2541D] = { [0x0FE00] = 0x2F94D },
+ [0x25626] = { [0x0FE00] = 0x2F952 },
+ [0x2569A] = { [0x0FE00] = 0x2F954 },
+ [0x256C5] = { [0x0FE00] = 0x2F955 },
+ [0x2597C] = { [0x0FE00] = 0x2F95C },
+ [0x25AA7] = { [0x0FE00] = 0x2F95D, [0x0FE01] = 0x2F95E },
+ [0x25BAB] = { [0x0FE00] = 0x2F961 },
+ [0x25C80] = { [0x0FE00] = 0x2F965 },
+ [0x25CD0] = { [0x0FE00] = 0x0FAD6 },
+ [0x25F86] = { [0x0FE00] = 0x2F96B },
+ [0x261DA] = { [0x0FE00] = 0x2F898 },
+ [0x26228] = { [0x0FE00] = 0x2F972 },
+ [0x26247] = { [0x0FE00] = 0x2F973 },
+ [0x262D9] = { [0x0FE00] = 0x2F975 },
+ [0x2633E] = { [0x0FE00] = 0x2F977 },
+ [0x264DA] = { [0x0FE00] = 0x2F97B },
+ [0x26523] = { [0x0FE00] = 0x2F97C },
+ [0x265A8] = { [0x0FE00] = 0x2F97E },
+ [0x267A7] = { [0x0FE00] = 0x2F987 },
+ [0x267B5] = { [0x0FE00] = 0x2F988 },
+ [0x26B3C] = { [0x0FE00] = 0x2F997 },
+ [0x26C36] = { [0x0FE00] = 0x2F9A4 },
+ [0x26CD5] = { [0x0FE00] = 0x2F9A6 },
+ [0x26D6B] = { [0x0FE00] = 0x2F9A5 },
+ [0x26F2C] = { [0x0FE00] = 0x2F9AD },
+ [0x26FB1] = { [0x0FE00] = 0x2F9B0 },
+ [0x270D2] = { [0x0FE00] = 0x2F9B1 },
+ [0x273CA] = { [0x0FE00] = 0x2F9AB },
+ [0x27667] = { [0x0FE00] = 0x2F9C5 },
+ [0x278AE] = { [0x0FE00] = 0x2F9CB },
+ [0x27966] = { [0x0FE00] = 0x2F9CC },
+ [0x27CA8] = { [0x0FE00] = 0x2F9D3 },
+ [0x27ED3] = { [0x0FE00] = 0x0FAD7 },
+ [0x27F2F] = { [0x0FE00] = 0x2F9D8 },
+ [0x285D2] = { [0x0FE00] = 0x2F9E0 },
+ [0x285ED] = { [0x0FE00] = 0x2F9E1 },
+ [0x2872E] = { [0x0FE00] = 0x2F9E5 },
+ [0x28BFA] = { [0x0FE00] = 0x2F9ED },
+ [0x28D77] = { [0x0FE00] = 0x2F9F1 },
+ [0x29145] = { [0x0FE00] = 0x2F9F6 },
+ [0x291DF] = { [0x0FE00] = 0x2F81C },
+ [0x2921A] = { [0x0FE00] = 0x2F9F7 },
+ [0x2940A] = { [0x0FE00] = 0x2F9FB },
+ [0x29496] = { [0x0FE00] = 0x2F9FD },
+ [0x295B6] = { [0x0FE00] = 0x2FA01 },
+ [0x29B30] = { [0x0FE00] = 0x2FA09 },
+ [0x2A0CE] = { [0x0FE00] = 0x2FA10 },
+ [0x2A105] = { [0x0FE00] = 0x2FA12 },
+ [0x2A20E] = { [0x0FE00] = 0x2FA13 },
+ [0x2A291] = { [0x0FE00] = 0x2FA14 },
+ [0x2A392] = { [0x0FE00] = 0x2F88F },
+ [0x2A600] = { [0x0FE00] = 0x2FA1D },
+}
+
+local cjk_ideograph_metatable = {
+ __index = {
+ category = "lo",
+ cjkwd = "w",
+ description = "<CJK Ideograph>",
+ direction = "l",
+ linebreak = "id",
+ }
+}
+
+local f_variant_name = formatters["CJK COMPATIBILITY IDEOGRAPH-%X"]
+
+local variants = setmetatableindex(function(t,k)
+ local kv = knownvariants[k]
+ if kv then
+ for k, v in next, kv do
+ kv[k] = f_variant_name(v)
+ end
+ end
+ knownvariants[k] = nil
+ return kv
+end)
+
+local cjk_ideograph_extender = function(k)
+ local t = {
+ -- shcode = shcode,
+ unicodeslot = k,
+ variants = variants[k],
+ }
+ setmetatable(t,cjk_ideograph_metatable)
+ return t
+end
+
+local cjk_ideograph_range = {
+ name = "cjk ideograph",
+ first = 0x4E00,
+ last = 0x9FBB,
+ extender = cjk_ideograph_extender,
+}
+
+-- CJK Ideograph Extension A
+
+local cjk_ideograph_extension_a_metatable = {
+ __index = {
+ category = "lo",
+ cjkwd = "w",
+ description = "<CJK Ideograph Extension A>",
+ direction = "l",
+ linebreak = "id",
+ }
+}
+
+local cjk_ideograph_extension_a_extender = function(k)
+ local t = {
+ -- shcode = shcode,
+ unicodeslot = k,
+ variants = variants[k],
+ }
+ setmetatable(t,cjk_ideograph_extension_a_metatable)
+ return t
+end
+
+local cjk_ideograph_extension_a_range = {
+ name = "cjk ideograph extension a",
+ first = 0x3400,
+ last = 0x4DB5,
+ extender = cjk_ideograph_extension_a_extender,
+}
+
+-- CJK Ideograph Extension B
+
+local cjk_ideograph_extension_b_metatable = {
+ __index = {
+ category = "lo",
+ cjkwd = "w",
+ description = "<CJK Ideograph Extension B>",
+ direction = "l",
+ linebreak = "id",
+ }
+}
+
+local cjk_ideograph_extension_b_extender = function(k)
+ local t = {
+ -- shcode = shcode,
+ unicodeslot = k,
+ variants = variants[k],
+ }
+ setmetatable(t,cjk_ideograph_extension_b_metatable)
+ return t
+end
+
+local cjk_ideograph_extension_b_range = {
+ name = "cjk ideograph extension b",
+ first = 0x20000,
+ last = 0x2A6D6,
+ extender = cjk_ideograph_extension_b_extender,
+}
+
+-- Ranges
+
+insert(ranges, hangul_syllable_range)
+insert(ranges, cjk_ideograph_range)
+insert(ranges, cjk_ideograph_extension_a_range)
+insert(ranges, cjk_ideograph_extension_b_range)
+
+-- Japanese
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-def.lua b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua
new file mode 100644
index 00000000000..bf21be70c37
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua
@@ -0,0 +1,227055 @@
+if not modules then modules = { } end modules ['char-def'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+--[[
+The first version of this table was generated from unicode tables but after that was
+mostly updated manual using data present in ConTeXt and elsewhere. I did my best to
+make this table as complete as needed for proper use in ConTeXt MkIV. All errors are
+mine. If you find an error or ommision, just let me know. This file is updated every
+now and then using mtx-unicode where we check against the latest unicode txt files
+(normally once per year around the tex live code freeze) and checked afterwards for
+differences. We could save some bytes by sharing variant tables but it's not worth
+the trouble. Some additional data is kept in other files.
+]]--
+
+characters = characters or { }
+
+characters.data={
+ [0x0]={
+ category="cc",
+ description="NULL",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x0,
+ },
+ {
+ adobename="controlSTX",
+ category="cc",
+ description="START OF HEADING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1,
+ },
+ {
+ adobename="controlSOT",
+ category="cc",
+ description="START OF TEXT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x2,
+ },
+ {
+ adobename="controlETX",
+ category="cc",
+ description="END OF TEXT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x3,
+ },
+ {
+ adobename="controlEOT",
+ category="cc",
+ description="END OF TRANSMISSION",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x4,
+ },
+ {
+ adobename="controlENQ",
+ category="cc",
+ description="ENQUIRY",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x5,
+ },
+ {
+ adobename="controlACK",
+ category="cc",
+ description="ACKNOWLEDGE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x6,
+ },
+ {
+ adobename="controlBEL",
+ category="cc",
+ description="BELL",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x7,
+ },
+ {
+ adobename="controlBS",
+ category="cc",
+ description="BACKSPACE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8,
+ },
+ {
+ adobename="controlHT",
+ category="cc",
+ description="CHARACTER TABULATION",
+ direction="s",
+ linebreak="ba",
+ unicodeslot=0x9,
+ },
+ {
+ adobename="controlLF",
+ category="cc",
+ description="LINE FEED (LF)",
+ direction="b",
+ linebreak="lf",
+ unicodeslot=0xA,
+ },
+ {
+ adobename="controlVT",
+ category="cc",
+ description="LINE TABULATION",
+ direction="s",
+ linebreak="bk",
+ unicodeslot=0xB,
+ },
+ {
+ adobename="controlFF",
+ category="cc",
+ description="FORM FEED (FF)",
+ direction="ws",
+ linebreak="bk",
+ unicodeslot=0xC,
+ },
+ {
+ adobename="controlCR",
+ category="cc",
+ description="CARRIAGE RETURN (CR)",
+ direction="b",
+ linebreak="cr",
+ unicodeslot=0xD,
+ },
+ {
+ adobename="controlSO",
+ category="cc",
+ description="SHIFT OUT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE,
+ },
+ {
+ adobename="controlSI",
+ category="cc",
+ description="SHIFT IN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xF,
+ },
+ {
+ adobename="controlDLE",
+ category="cc",
+ description="DATA LINK ESCAPE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x10,
+ },
+ {
+ adobename="controlDC1",
+ category="cc",
+ description="DEVICE CONTROL ONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x11,
+ },
+ {
+ adobename="controlDC2",
+ category="cc",
+ description="DEVICE CONTROL TWO",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x12,
+ },
+ {
+ adobename="controlDC3",
+ category="cc",
+ description="DEVICE CONTROL THREE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x13,
+ },
+ {
+ adobename="controlDC4",
+ category="cc",
+ description="DEVICE CONTROL FOUR",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x14,
+ },
+ {
+ adobename="controlNAK",
+ category="cc",
+ description="NEGATIVE ACKNOWLEDGE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x15,
+ },
+ {
+ adobename="controlSYN",
+ category="cc",
+ description="SYNCHRONOUS IDLE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x16,
+ },
+ {
+ adobename="controlETB",
+ category="cc",
+ description="END OF TRANSMISSION BLOCK",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x17,
+ },
+ {
+ adobename="controlCAN",
+ category="cc",
+ description="CANCEL",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x18,
+ },
+ {
+ adobename="controlEM",
+ category="cc",
+ description="END OF MEDIUM",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x19,
+ },
+ {
+ adobename="controlSUB",
+ category="cc",
+ description="SUBSTITUTE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1A,
+ },
+ {
+ adobename="controlESC",
+ category="cc",
+ description="ESCAPE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1B,
+ },
+ {
+ adobename="controlFS",
+ category="cc",
+ description="INFORMATION SEPARATOR FOUR",
+ direction="b",
+ linebreak="cm",
+ unicodeslot=0x1C,
+ },
+ {
+ adobename="controlGS",
+ category="cc",
+ description="INFORMATION SEPARATOR THREE",
+ direction="b",
+ linebreak="cm",
+ unicodeslot=0x1D,
+ },
+ {
+ adobename="controlRS",
+ category="cc",
+ description="INFORMATION SEPARATOR TWO",
+ direction="b",
+ linebreak="cm",
+ unicodeslot=0x1E,
+ },
+ {
+ adobename="controlUS",
+ category="cc",
+ description="INFORMATION SEPARATOR ONE",
+ direction="s",
+ linebreak="cm",
+ unicodeslot=0x1F,
+ },
+ {
+ adobename="space",
+ category="zs",
+ cjkwd="na",
+ description="SPACE",
+ direction="ws",
+ linebreak="sp",
+ unicodeslot=0x20,
+ },
+ {
+ adobename="exclam",
+ category="po",
+ cjkwd="na",
+ description="EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ mathclass="close",
+ unicodeslot=0x21,
+ },
+ {
+ adobename="quotedbl",
+ category="po",
+ cjkwd="na",
+ contextname="quotedbl",
+ description="QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ mathclass="default",
+ unicodeslot=0x22,
+ },
+ {
+ adobename="numbersign",
+ category="po",
+ cjkwd="na",
+ contextname="texthash",
+ description="NUMBER SIGN",
+ direction="et",
+ linebreak="al",
+ mathclass="binary",
+ mathname="mathhash",
+ unicodeslot=0x23,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="dollar",
+ category="sc",
+ cjkwd="na",
+ contextname="textdollar",
+ description="DOLLAR SIGN",
+ direction="et",
+ linebreak="pr",
+ mathclass="binary",
+ mathname="mathdollar",
+ unicodeslot=0x24,
+ },
+ {
+ adobename="percent",
+ category="po",
+ cjkwd="na",
+ contextname="textpercent",
+ description="PERCENT SIGN",
+ direction="et",
+ linebreak="po",
+ mathclass="binary",
+ mathname="mathpercent",
+ unicodeslot=0x25,
+ },
+ {
+ adobename="ampersand",
+ category="po",
+ cjkwd="na",
+ contextname="textampersand",
+ description="AMPERSAND",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="mathampersand",
+ unicodeslot=0x26,
+ },
+ {
+ adobename="quotesingle",
+ category="po",
+ cjkwd="na",
+ contextname="quotesingle",
+ description="APOSTROPHE",
+ direction="on",
+ linebreak="qu",
+ mathclass="default",
+ unicodeslot=0x27,
+ },
+ {
+ adobename="parenleft",
+ category="ps",
+ cjkwd="na",
+ description="LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lparent",
+ mirror=0x29,
+ textclass="open",
+ unicodeslot=0x28,
+ },
+ {
+ adobename="parenright",
+ category="pe",
+ cjkwd="na",
+ description="RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cp",
+ mathclass="close",
+ mathname="rparent",
+ mirror=0x28,
+ textclass="close",
+ unicodeslot=0x29,
+ },
+ {
+ adobename="asterisk",
+ category="po",
+ cjkwd="na",
+ description="ASTERISK",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="ast",
+ mathsymbol=0x2217,
+ unicodeslot=0x2A,
+ },
+ {
+ adobename="plus",
+ category="sm",
+ cjkwd="na",
+ description="PLUS SIGN",
+ direction="es",
+ linebreak="pr",
+ mathclass="binary",
+ unicodeslot=0x2B,
+ },
+ {
+ adobename="comma",
+ category="po",
+ cjkwd="na",
+ contextname="textcomma",
+ description="COMMA",
+ direction="cs",
+ linebreak="is",
+ mathclass="punctuation",
+ unicodeslot=0x2C,
+ },
+ {
+ adobename="hyphen",
+ category="pd",
+ cjkwd="na",
+ description="HYPHEN-MINUS",
+ direction="es",
+ linebreak="hy",
+ mathextensible="h",
+ mathfiller="relfill",
+ mathsymbol=0x2212,
+ unicodeslot=0x2D,
+ },
+ {
+ adobename="period",
+ category="po",
+ cjkwd="na",
+ comment="class needed for autopunctuation",
+ contextname="textperiod",
+ description="FULL STOP",
+ direction="cs",
+ linebreak="is",
+ mathclass="punctuation",
+ mathspec={
+ {
+ class="punctuation",
+ name="ldotp",
+ },
+ },
+ unicodeslot=0x2E,
+ },
+ {
+ adobename="slash",
+ category="po",
+ cjkwd="na",
+ contextname="textslash",
+ description="SOLIDUS",
+ direction="cs",
+ linebreak="sy",
+ mathspec={
+ {
+ class="middle",
+ },
+ {
+ class="ordinary",
+ },
+ },
+ unicodeslot=0x2F,
+ },
+ {
+ adobename="zero",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x30,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="one",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x31,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="two",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x32,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="three",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x33,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="four",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x34,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="five",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x35,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="six",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x36,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="seven",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x37,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="eight",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x38,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="nine",
+ category="nd",
+ cjkwd="na",
+ description="DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ mathclass="number",
+ unicodeslot=0x39,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="colon",
+ category="po",
+ cjkwd="na",
+ comment="mathclass=punctuation,mathname=colon,mathsymbol=0x2236",
+ description="COLON",
+ direction="cs",
+ linebreak="is",
+ mathclass="relation",
+--mathsymbol=0x2236,
+ unicodeslot=0x3A,
+ },
+ {
+ adobename="semicolon",
+ category="po",
+ cjkwd="na",
+ description="SEMICOLON",
+ direction="on",
+ linebreak="is",
+ mathclass="punctuation",
+ unicodeslot=0x3B,
+ },
+ {
+ adobename="less",
+ category="sm",
+ cjkwd="na",
+ description="LESS-THAN SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lt",
+ mirror=0x3E,
+ textclass="open",
+ unicodeslot=0x3C,
+ },
+ {
+ adobename="equal",
+ category="sm",
+ cjkwd="na",
+ comment="mathclass=binary",
+ description="EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathextensible="h",
+ mathfiller="equalfill",
+ mathspec={
+ {
+ class="relation",
+ name="eq",
+ },
+ {
+ class="relation",
+ name="Relbar",
+ },
+ },
+ unicodeslot=0x3D,
+ },
+ {
+ adobename="greater",
+ category="sm",
+ cjkwd="na",
+ description="GREATER-THAN SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gt",
+ mirror=0x3C,
+ textclass="close",
+ unicodeslot=0x3E,
+ },
+ {
+ adobename="question",
+ category="po",
+ cjkwd="na",
+ description="QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ mathclass="close",
+ unicodeslot=0x3F,
+ },
+ {
+ adobename="at",
+ category="po",
+ cjkwd="na",
+ contextname="textat",
+ description="COMMERCIAL AT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x40,
+ },
+ {
+ adobename="A",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER A",
+ direction="l",
+ lccode=0x61,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x41,
+ },
+ {
+ adobename="B",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER B",
+ direction="l",
+ lccode=0x62,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x42,
+ },
+ {
+ adobename="C",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER C",
+ direction="l",
+ lccode=0x63,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x43,
+ },
+ {
+ adobename="D",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER D",
+ direction="l",
+ lccode=0x64,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x44,
+ },
+ {
+ adobename="E",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER E",
+ direction="l",
+ lccode=0x65,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x45,
+ },
+ {
+ adobename="F",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER F",
+ direction="l",
+ lccode=0x66,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x46,
+ },
+ {
+ adobename="G",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER G",
+ direction="l",
+ lccode=0x67,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x47,
+ },
+ {
+ adobename="H",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER H",
+ direction="l",
+ lccode=0x68,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x48,
+ },
+ {
+ adobename="I",
+ category="lu",
+ cjkwd="na",
+ contextname="dotlessI",
+ description="LATIN CAPITAL LETTER I",
+ direction="l",
+ lccode=0x69,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x49,
+ },
+ {
+ adobename="J",
+ category="lu",
+ cjkwd="na",
+ contextname="dotlessJ",
+ description="LATIN CAPITAL LETTER J",
+ direction="l",
+ lccode=0x6A,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4A,
+ },
+ {
+ adobename="K",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER K",
+ direction="l",
+ lccode=0x6B,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4B,
+ },
+ {
+ adobename="L",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER L",
+ direction="l",
+ lccode=0x6C,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4C,
+ },
+ {
+ adobename="M",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER M",
+ direction="l",
+ lccode=0x6D,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4D,
+ },
+ {
+ adobename="N",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER N",
+ direction="l",
+ lccode=0x6E,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4E,
+ },
+ {
+ adobename="O",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER O",
+ direction="l",
+ lccode=0x6F,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x4F,
+ },
+ {
+ adobename="P",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER P",
+ direction="l",
+ lccode=0x70,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x50,
+ },
+ {
+ adobename="Q",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER Q",
+ direction="l",
+ lccode=0x71,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x51,
+ },
+ {
+ adobename="R",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER R",
+ direction="l",
+ lccode=0x72,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x52,
+ },
+ {
+ adobename="S",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER S",
+ direction="l",
+ lccode=0x73,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x53,
+ },
+ {
+ adobename="T",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER T",
+ direction="l",
+ lccode=0x74,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x54,
+ },
+ {
+ adobename="U",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER U",
+ direction="l",
+ lccode=0x75,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x55,
+ },
+ {
+ adobename="V",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER V",
+ direction="l",
+ lccode=0x76,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x56,
+ },
+ {
+ adobename="W",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER W",
+ direction="l",
+ lccode=0x77,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x57,
+ },
+ {
+ adobename="X",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER X",
+ direction="l",
+ lccode=0x78,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x58,
+ },
+ {
+ adobename="Y",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER Y",
+ direction="l",
+ lccode=0x79,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x59,
+ },
+ {
+ adobename="Z",
+ category="lu",
+ cjkwd="na",
+ description="LATIN CAPITAL LETTER Z",
+ direction="l",
+ lccode=0x7A,
+ linebreak="al",
+ mathclass="variable",
+ unicodeslot=0x5A,
+ },
+ {
+ adobename="bracketleft",
+ category="ps",
+ cjkwd="na",
+ description="LEFT SQUARE BRACKET",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lbracket",
+ mirror=0x5D,
+ textclass="open",
+ unicodeslot=0x5B,
+ },
+ {
+ adobename="backslash",
+ category="po",
+ cjkwd="na",
+ contextname="textbackslash",
+ description="REVERSE SOLIDUS",
+ direction="on",
+ linebreak="pr",
+ mathclass="nothing",
+ mathname="backslash",
+ unicodeslot=0x5C,
+ },
+ {
+ adobename="bracketright",
+ category="pe",
+ cjkwd="na",
+ description="RIGHT SQUARE BRACKET",
+ direction="on",
+ linebreak="cp",
+ mathclass="close",
+ mathname="rbracket",
+ mirror=0x5B,
+ textclass="close",
+ unicodeslot=0x5D,
+ },
+ {
+ adobename="asciicircum",
+ category="sk",
+ cjkwd="na",
+ contextname="textasciicircum",
+ description="CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathname="Hat",
+ unicodeslot=0x5E,
+ },
+ {
+ adobename="underscore",
+ category="pc",
+ cjkwd="na",
+ contextname="textunderscore",
+ description="LOW LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x5F,
+ },
+ {
+ adobename="grave",
+ category="sk",
+ cjkwd="na",
+ contextname="textgrave",
+ description="GRAVE ACCENT",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathname="grave",
+ unicodeslot=0x60,
+ },
+ {
+ adobename="a",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x41,
+ unicodeslot=0x61,
+ },
+ {
+ adobename="b",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER B",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x42,
+ unicodeslot=0x62,
+ },
+ {
+ adobename="c",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER C",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x43,
+ unicodeslot=0x63,
+ },
+ {
+ adobename="d",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER D",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x44,
+ unicodeslot=0x64,
+ },
+ {
+ adobename="e",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x45,
+ unicodeslot=0x65,
+ },
+ {
+ adobename="f",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER F",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x46,
+ unicodeslot=0x66,
+ },
+ {
+ adobename="g",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER G",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x47,
+ unicodeslot=0x67,
+ },
+ {
+ adobename="h",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER H",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x48,
+ unicodeslot=0x68,
+ },
+ {
+ adobename="i",
+ category="ll",
+ cjkwd="na",
+ contextname="idotaccent",
+ description="LATIN SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x49,
+ unicodeslot=0x69,
+ },
+ {
+ adobename="j",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER J",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4A,
+ unicodeslot=0x6A,
+ },
+ {
+ adobename="k",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER K",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4B,
+ unicodeslot=0x6B,
+ },
+ {
+ adobename="l",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER L",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4C,
+ unicodeslot=0x6C,
+ },
+ {
+ adobename="m",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER M",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4D,
+ unicodeslot=0x6D,
+ },
+ {
+ adobename="n",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER N",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4E,
+ unicodeslot=0x6E,
+ },
+ {
+ adobename="o",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x4F,
+ unicodeslot=0x6F,
+ },
+ {
+ adobename="p",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER P",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x50,
+ unicodeslot=0x70,
+ },
+ {
+ adobename="q",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER Q",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x51,
+ unicodeslot=0x71,
+ },
+ {
+ adobename="r",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER R",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x52,
+ unicodeslot=0x72,
+ },
+ {
+ adobename="s",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER S",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x53,
+ unicodeslot=0x73,
+ },
+ {
+ adobename="t",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER T",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x54,
+ unicodeslot=0x74,
+ },
+ {
+ adobename="u",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER U",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x55,
+ unicodeslot=0x75,
+ },
+ {
+ adobename="v",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER V",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x56,
+ unicodeslot=0x76,
+ },
+ {
+ adobename="w",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER W",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x57,
+ unicodeslot=0x77,
+ },
+ {
+ adobename="x",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER X",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x58,
+ unicodeslot=0x78,
+ },
+ {
+ adobename="y",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER Y",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x59,
+ unicodeslot=0x79,
+ },
+ {
+ adobename="z",
+ category="ll",
+ cjkwd="na",
+ description="LATIN SMALL LETTER Z",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ uccode=0x5A,
+ unicodeslot=0x7A,
+ },
+ {
+ adobename="braceleft",
+ category="ps",
+ cjkwd="na",
+ contextname="textbraceleft",
+ description="LEFT CURLY BRACKET",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lbrace",
+ mirror=0x7D,
+ textclass="open",
+ unicodeslot=0x7B,
+ },
+ {
+ adobename="verticalbar",
+ category="sm",
+ cjkwd="na",
+ comment="mathclass=binary,mathname=bar",
+ contextname="textbar",
+ description="VERTICAL LINE",
+ direction="on",
+ linebreak="ba",
+ mathspec={
+ {
+ class="nothing",
+ name="arrowvert",
+ },
+ {
+ class="delimiter",
+ name="vert",
+ },
+ {
+ class="open",
+ name="lvert",
+ },
+ {
+ class="close",
+ name="rvert",
+ },
+ {
+ class="relation",
+ name="mid",
+ },
+ {
+ class="delimiter",
+ name="singleverticalbar",
+ },
+ },
+ unicodeslot=0x7C,
+ },
+ {
+ adobename="braceright",
+ category="pe",
+ cjkwd="na",
+ contextname="textbraceright",
+ description="RIGHT CURLY BRACKET",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rbrace",
+ mirror=0x7B,
+ textclass="close",
+ unicodeslot=0x7D,
+ },
+ {
+ adobename="asciitilde",
+ category="sm",
+ cjkwd="na",
+ contextname="textasciitilde",
+ description="TILDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x7E,
+ },
+ {
+ adobename="controlDEL",
+ category="cc",
+ description="DELETE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x7F,
+ },
+ {
+ category="cc",
+ description="NONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x80,
+ },
+ {
+ category="cc",
+ description="NONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x81,
+ },
+ {
+ category="cc",
+ description="BREAK PERMITTED HERE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x82,
+ },
+ {
+ category="cc",
+ description="NO BREAK HERE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x83,
+ },
+ {
+ category="cc",
+ description="NONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x84,
+ },
+ {
+ category="cc",
+ description="NEXT LINE (NEL)",
+ direction="b",
+ linebreak="nl",
+ unicodeslot=0x85,
+ },
+ {
+ category="cc",
+ description="START OF SELECTED AREA",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x86,
+ },
+ {
+ category="cc",
+ description="END OF SELECTED AREA",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x87,
+ },
+ {
+ category="cc",
+ description="CHARACTER TABULATION SET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x88,
+ },
+ {
+ category="cc",
+ description="CHARACTER TABULATION WITH JUSTIFICATION",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x89,
+ },
+ {
+ category="cc",
+ description="LINE TABULATION SET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8A,
+ },
+ {
+ category="cc",
+ description="PARTIAL LINE FORWARD",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8B,
+ },
+ {
+ category="cc",
+ description="PARTIAL LINE BACKWARD",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8C,
+ },
+ {
+ category="cc",
+ description="REVERSE LINE FEED",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8D,
+ },
+ {
+ category="cc",
+ description="SINGLE SHIFT TWO",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8E,
+ },
+ {
+ category="cc",
+ description="SINGLE SHIFT THREE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x8F,
+ },
+ {
+ category="cc",
+ description="DEVICE CONTROL STRING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x90,
+ },
+ {
+ category="cc",
+ description="PRIVATE USE ONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x91,
+ },
+ {
+ category="cc",
+ description="PRIVATE USE TWO",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x92,
+ },
+ {
+ category="cc",
+ description="SET TRANSMIT STATE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x93,
+ },
+ {
+ category="cc",
+ description="CANCEL CHARACTER",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x94,
+ },
+ {
+ category="cc",
+ description="MESSAGE WAITING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x95,
+ },
+ {
+ category="cc",
+ description="START OF GUARDED AREA",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x96,
+ },
+ {
+ category="cc",
+ description="END OF GUARDED AREA",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x97,
+ },
+ {
+ category="cc",
+ description="START OF STRING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x98,
+ },
+ {
+ category="cc",
+ description="NONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x99,
+ },
+ {
+ category="cc",
+ description="SINGLE CHARACTER INTRODUCER",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9A,
+ },
+ {
+ category="cc",
+ description="CONTROL SEQUENCE INTRODUCER",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9B,
+ },
+ {
+ category="cc",
+ description="STRING TERMINATOR",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9C,
+ },
+ {
+ category="cc",
+ description="OPERATING SYSTEM COMMAND",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9D,
+ },
+ {
+ category="cc",
+ description="PRIVACY MESSAGE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9E,
+ },
+ {
+ category="cc",
+ description="APPLICATION PROGRAM COMMAND",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x9F,
+ },
+ {
+ adobename="nonbreakingspace",
+ category="zs",
+ contextname="nobreakspace",
+ description="NO-BREAK SPACE",
+ direction="cs",
+ linebreak="gl",
+ specials={ "nobreak", 0x20 },
+ unicodeslot=0xA0,
+ },
+ {
+ adobename="exclamdown",
+ category="po",
+ cjkwd="a",
+ contextname="exclamdown",
+ description="INVERTED EXCLAMATION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0xA1,
+ },
+ {
+ adobename="cent",
+ category="sc",
+ cjkwd="na",
+ contextname="textcent",
+ description="CENT SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0xA2,
+ },
+ {
+ adobename="sterling",
+ category="sc",
+ cjkwd="na",
+ contextname="textsterling",
+ description="POUND SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0xA3,
+ },
+ {
+ adobename="currency",
+ category="sc",
+ cjkwd="a",
+ contextname="textcurrency",
+ description="CURRENCY SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0xA4,
+ },
+ {
+ adobename="yen",
+ category="sc",
+ cjkwd="na",
+ contextname="textyen",
+ description="YEN SIGN",
+ direction="et",
+ linebreak="pr",
+ mathclass="nothing",
+ mathname="yen",
+ unicodeslot=0xA5,
+ },
+ {
+ adobename="brokenbar",
+ category="so",
+ cjkwd="na",
+ contextname="textbrokenbar",
+ description="BROKEN BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA6,
+ },
+ {
+ adobename="section",
+ category="so",
+ cjkwd="a",
+ contextname="sectionmark",
+ description="SECTION SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="box",
+ mathname="S",
+ unicodeslot=0xA7,
+ },
+ {
+ adobename="dieresis",
+ category="sk",
+ cjkwd="a",
+ contextname="textdiaeresis",
+ description="DIAERESIS",
+ direction="on",
+ linebreak="ai",
+ mathclass="topaccent",
+ mathname="ddot",
+ specials={ "compat", 0x20, 0x308 },
+ unicodeslot=0xA8,
+ },
+ {
+ adobename="copyright",
+ category="so",
+ contextname="copyright",
+ description="COPYRIGHT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA9,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="ordfeminine",
+ category="ll",
+ cjkwd="a",
+ contextname="ordfeminine",
+ description="FEMININE ORDINAL INDICATOR",
+ direction="l",
+ linebreak="ai",
+ specials={ "super", 0x61 },
+ unicodeslot=0xAA,
+ },
+ {
+ adobename="guillemotleft",
+ category="pi",
+ contextname="leftguillemot",
+ description="LEFT-POINTING DOUBLE ANGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ mirror=0xBB,
+ textclass="open",
+ unicodeslot=0xAB,
+ },
+ {
+ adobename="logicalnot",
+ category="sm",
+ cjkwd="na",
+ contextname="textlognot",
+ description="NOT SIGN",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="ordinary",
+ name="lnot",
+ },
+ {
+ class="ordinary",
+ name="neg",
+ },
+ },
+ unicodeslot=0xAC,
+ },
+ {
+ adobename="softhyphen",
+ category="cf",
+ cjkwd="a",
+ contextname="softhyphen",
+ description="SOFT HYPHEN",
+ direction="bn",
+ linebreak="ba",
+ unicodeslot=0xAD,
+ },
+ {
+ adobename="registered",
+ category="so",
+ cjkwd="a",
+ contextname="registered",
+ description="REGISTERED SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xAE,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ {
+ adobename="macron",
+ category="sk",
+ cjkwd="na",
+ contextname="textmacron",
+ description="MACRON",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathfiller="barfill",
+ mathmleq=0x203E,
+ mathname="bar",
+ specials={ "compat", 0x20, 0x304 },
+ unicodeslot=0xAF,
+ },
+ {
+ adobename="degree",
+ category="so",
+ cjkwd="a",
+ contextname="textdegree",
+ description="DEGREE SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0xB0,
+ },
+ {
+ adobename="plusminus",
+ category="sm",
+ cjkwd="a",
+ contextname="textpm",
+ description="PLUS-MINUS SIGN",
+ direction="et",
+ linebreak="pr",
+ mathclass="binary",
+ mathname="pm",
+ unicodeslot=0xB1,
+ },
+ {
+ adobename="twosuperior",
+ category="no",
+ cjkwd="a",
+ contextname="twosuperior",
+ description="SUPERSCRIPT TWO",
+ direction="en",
+ linebreak="ai",
+ specials={ "super", 0x32 },
+ unicodeslot=0xB2,
+ },
+ {
+ adobename="threesuperior",
+ category="no",
+ cjkwd="a",
+ contextname="threesuperior",
+ description="SUPERSCRIPT THREE",
+ direction="en",
+ linebreak="ai",
+ specials={ "super", 0x33 },
+ unicodeslot=0xB3,
+ },
+ {
+ adobename="acute",
+ category="sk",
+ cjkwd="a",
+ contextname="textacute",
+ description="ACUTE ACCENT",
+ direction="on",
+ linebreak="bb",
+ mathclass="topaccent",
+ mathname="acute",
+ specials={ "compat", 0x20, 0x301 },
+ unicodeslot=0xB4,
+ },
+ {
+ adobename="mu1",
+ category="ll",
+ contextname="textmu",
+ description="MICRO SIGN",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x3BC },
+ uccode=0x39C,
+ unicodeslot=0xB5,
+ },
+ {
+ adobename="paragraph",
+ category="so",
+ cjkwd="a",
+ contextname="paragraphmark",
+ description="PILCROW SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="box",
+ mathname="P",
+ unicodeslot=0xB6,
+ },
+ {
+ adobename="periodcentered",
+ category="po",
+ cjkwd="a",
+ contextname="periodcentered",
+ description="MIDDLE DOT",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="centerdot",
+ unicodeslot=0xB7,
+ },
+ {
+ adobename="cedilla",
+ category="sk",
+ cjkwd="a",
+ contextname="textcedilla",
+ description="CEDILLA",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x20, 0x327 },
+ unicodeslot=0xB8,
+ },
+ {
+ adobename="onesuperior",
+ category="no",
+ cjkwd="a",
+ contextname="onesuperior",
+ description="SUPERSCRIPT ONE",
+ direction="en",
+ linebreak="ai",
+ specials={ "super", 0x31 },
+ unicodeslot=0xB9,
+ },
+ {
+ adobename="ordmasculine",
+ category="ll",
+ cjkwd="a",
+ contextname="ordmasculine",
+ description="MASCULINE ORDINAL INDICATOR",
+ direction="l",
+ linebreak="ai",
+ specials={ "super", 0x6F },
+ unicodeslot=0xBA,
+ },
+ {
+ adobename="guillemotright",
+ category="pf",
+ contextname="rightguillemot",
+ description="RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ mirror=0xAB,
+ textclass="close",
+ unicodeslot=0xBB,
+ },
+ {
+ adobename="onequarter",
+ category="no",
+ cjkwd="a",
+ contextname="onequarter",
+ description="VULGAR FRACTION ONE QUARTER",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x31, 0x2044, 0x34 },
+ unicodeslot=0xBC,
+ },
+ {
+ adobename="onehalf",
+ category="no",
+ cjkwd="a",
+ contextname="onehalf",
+ description="VULGAR FRACTION ONE HALF",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x31, 0x2044, 0x32 },
+ unicodeslot=0xBD,
+ },
+ {
+ adobename="threequarters",
+ category="no",
+ cjkwd="a",
+ contextname="threequarter",
+ description="VULGAR FRACTION THREE QUARTERS",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x33, 0x2044, 0x34 },
+ unicodeslot=0xBE,
+ },
+ {
+ adobename="questiondown",
+ category="po",
+ cjkwd="a",
+ contextname="questiondown",
+ description="INVERTED QUESTION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0xBF,
+ },
+ {
+ adobename="Agrave",
+ category="lu",
+ contextname="Agrave",
+ description="LATIN CAPITAL LETTER A WITH GRAVE",
+ direction="l",
+ lccode=0xE0,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x300 },
+ unicodeslot=0xC0,
+ },
+ {
+ adobename="Aacute",
+ category="lu",
+ contextname="Aacute",
+ description="LATIN CAPITAL LETTER A WITH ACUTE",
+ direction="l",
+ lccode=0xE1,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x301 },
+ unicodeslot=0xC1,
+ },
+ {
+ adobename="Acircumflex",
+ category="lu",
+ contextname="Acircumflex",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0xE2,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x302 },
+ unicodeslot=0xC2,
+ },
+ {
+ adobename="Atilde",
+ category="lu",
+ contextname="Atilde",
+ description="LATIN CAPITAL LETTER A WITH TILDE",
+ direction="l",
+ lccode=0xE3,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x303 },
+ unicodeslot=0xC3,
+ },
+ {
+ adobename="Adieresis",
+ category="lu",
+ contextname="Adiaeresis",
+ description="LATIN CAPITAL LETTER A WITH DIAERESIS",
+ direction="l",
+ lccode=0xE4,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x308 },
+ unicodeslot=0xC4,
+ },
+ {
+ adobename="Aring",
+ category="lu",
+ contextname="Aring",
+ description="LATIN CAPITAL LETTER A WITH RING ABOVE",
+ direction="l",
+ lccode=0xE5,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x30A },
+ unicodeslot=0xC5,
+ },
+ {
+ adobename="AE",
+ category="lu",
+ cjkwd="a",
+ contextname="AEligature",
+ description="LATIN CAPITAL LETTER AE",
+ direction="l",
+ lccode=0xE6,
+ linebreak="al",
+ shcode={ 0x41, 0x45 },
+ unicodeslot=0xC6,
+ },
+ {
+ adobename="Ccedilla",
+ category="lu",
+ contextname="Ccedilla",
+ description="LATIN CAPITAL LETTER C WITH CEDILLA",
+ direction="l",
+ lccode=0xE7,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0x43, 0x327 },
+ unicodeslot=0xC7,
+ },
+ {
+ adobename="Egrave",
+ category="lu",
+ contextname="Egrave",
+ description="LATIN CAPITAL LETTER E WITH GRAVE",
+ direction="l",
+ lccode=0xE8,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x300 },
+ unicodeslot=0xC8,
+ },
+ {
+ adobename="Eacute",
+ category="lu",
+ contextname="Eacute",
+ description="LATIN CAPITAL LETTER E WITH ACUTE",
+ direction="l",
+ lccode=0xE9,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x301 },
+ unicodeslot=0xC9,
+ },
+ {
+ adobename="Ecircumflex",
+ category="lu",
+ contextname="Ecircumflex",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0xEA,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x302 },
+ unicodeslot=0xCA,
+ },
+ {
+ adobename="Edieresis",
+ category="lu",
+ contextname="Ediaeresis",
+ description="LATIN CAPITAL LETTER E WITH DIAERESIS",
+ direction="l",
+ lccode=0xEB,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x308 },
+ unicodeslot=0xCB,
+ },
+ {
+ adobename="Igrave",
+ category="lu",
+ contextname="Igrave",
+ description="LATIN CAPITAL LETTER I WITH GRAVE",
+ direction="l",
+ lccode=0xEC,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x300 },
+ unicodeslot=0xCC,
+ },
+ {
+ adobename="Iacute",
+ category="lu",
+ contextname="Iacute",
+ description="LATIN CAPITAL LETTER I WITH ACUTE",
+ direction="l",
+ lccode=0xED,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x301 },
+ unicodeslot=0xCD,
+ },
+ {
+ adobename="Icircumflex",
+ category="lu",
+ contextname="Icircumflex",
+ description="LATIN CAPITAL LETTER I WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0xEE,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x302 },
+ unicodeslot=0xCE,
+ },
+ {
+ adobename="Idieresis",
+ category="lu",
+ contextname="Idiaeresis",
+ description="LATIN CAPITAL LETTER I WITH DIAERESIS",
+ direction="l",
+ lccode=0xEF,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x308 },
+ unicodeslot=0xCF,
+ },
+ {
+ adobename="Eth",
+ category="lu",
+ cjkwd="a",
+ contextname="Eth",
+ description="LATIN CAPITAL LETTER ETH",
+ direction="l",
+ lccode=0xF0,
+ linebreak="al",
+ unicodeslot=0xD0,
+ },
+ {
+ adobename="Ntilde",
+ category="lu",
+ contextname="Ntilde",
+ description="LATIN CAPITAL LETTER N WITH TILDE",
+ direction="l",
+ lccode=0xF1,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x303 },
+ unicodeslot=0xD1,
+ },
+ {
+ adobename="Ograve",
+ category="lu",
+ contextname="Ograve",
+ description="LATIN CAPITAL LETTER O WITH GRAVE",
+ direction="l",
+ lccode=0xF2,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x300 },
+ unicodeslot=0xD2,
+ },
+ {
+ adobename="Oacute",
+ category="lu",
+ contextname="Oacute",
+ description="LATIN CAPITAL LETTER O WITH ACUTE",
+ direction="l",
+ lccode=0xF3,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x301 },
+ unicodeslot=0xD3,
+ },
+ {
+ adobename="Ocircumflex",
+ category="lu",
+ contextname="Ocircumflex",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0xF4,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x302 },
+ unicodeslot=0xD4,
+ },
+ {
+ adobename="Otilde",
+ category="lu",
+ contextname="Otilde",
+ description="LATIN CAPITAL LETTER O WITH TILDE",
+ direction="l",
+ lccode=0xF5,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x303 },
+ unicodeslot=0xD5,
+ },
+ {
+ adobename="Odieresis",
+ category="lu",
+ contextname="Odiaeresis",
+ description="LATIN CAPITAL LETTER O WITH DIAERESIS",
+ direction="l",
+ lccode=0xF6,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x308 },
+ unicodeslot=0xD6,
+ },
+ {
+ adobename="multiply",
+ category="sm",
+ cjkwd="a",
+ contextname="textmultiply",
+ description="MULTIPLICATION SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="times",
+ unicodeslot=0xD7,
+ },
+ {
+ adobename="Oslash",
+ category="lu",
+ cjkwd="a",
+ contextname="Ostroke",
+ description="LATIN CAPITAL LETTER O WITH STROKE",
+ direction="l",
+ lccode=0xF8,
+ linebreak="al",
+ shcode=0x4F,
+ unicodeslot=0xD8,
+ },
+ {
+ adobename="Ugrave",
+ category="lu",
+ contextname="Ugrave",
+ description="LATIN CAPITAL LETTER U WITH GRAVE",
+ direction="l",
+ lccode=0xF9,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x300 },
+ unicodeslot=0xD9,
+ },
+ {
+ adobename="Uacute",
+ category="lu",
+ contextname="Uacute",
+ description="LATIN CAPITAL LETTER U WITH ACUTE",
+ direction="l",
+ lccode=0xFA,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x301 },
+ unicodeslot=0xDA,
+ },
+ {
+ adobename="Ucircumflex",
+ category="lu",
+ contextname="Ucircumflex",
+ description="LATIN CAPITAL LETTER U WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0xFB,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x302 },
+ unicodeslot=0xDB,
+ },
+ {
+ adobename="Udieresis",
+ category="lu",
+ contextname="Udiaeresis",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS",
+ direction="l",
+ lccode=0xFC,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x308 },
+ unicodeslot=0xDC,
+ },
+ {
+ adobename="Yacute",
+ category="lu",
+ contextname="Yacute",
+ description="LATIN CAPITAL LETTER Y WITH ACUTE",
+ direction="l",
+ lccode=0xFD,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x301 },
+ unicodeslot=0xDD,
+ },
+ {
+ adobename="Thorn",
+ category="lu",
+ cjkwd="a",
+ contextname="Thorn",
+ description="LATIN CAPITAL LETTER THORN",
+ direction="l",
+ lccode=0xFE,
+ linebreak="al",
+ unicodeslot=0xDE,
+ },
+ {
+ adobename="germandbls",
+ category="ll",
+ cjkwd="a",
+ comment="uppercase can be 0x1E9E",
+ contextname="ssharp",
+ description="LATIN SMALL LETTER SHARP S",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x73, 0x73 },
+ uccode={ 0x53, 0x53 },
+ unicodeslot=0xDF,
+ },
+ {
+ adobename="agrave",
+ category="ll",
+ cjkwd="a",
+ contextname="agrave",
+ description="LATIN SMALL LETTER A WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x300 },
+ uccode=0xC0,
+ unicodeslot=0xE0,
+ },
+ {
+ adobename="aacute",
+ category="ll",
+ cjkwd="a",
+ contextname="aacute",
+ description="LATIN SMALL LETTER A WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x301 },
+ uccode=0xC1,
+ unicodeslot=0xE1,
+ },
+ {
+ adobename="acircumflex",
+ category="ll",
+ contextname="acircumflex",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x302 },
+ uccode=0xC2,
+ unicodeslot=0xE2,
+ },
+ {
+ adobename="atilde",
+ category="ll",
+ contextname="atilde",
+ description="LATIN SMALL LETTER A WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x303 },
+ uccode=0xC3,
+ unicodeslot=0xE3,
+ },
+ {
+ adobename="adieresis",
+ category="ll",
+ contextname="adiaeresis",
+ description="LATIN SMALL LETTER A WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x308 },
+ uccode=0xC4,
+ unicodeslot=0xE4,
+ },
+ {
+ adobename="aring",
+ category="ll",
+ contextname="aring",
+ description="LATIN SMALL LETTER A WITH RING ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x30A },
+ uccode=0xC5,
+ unicodeslot=0xE5,
+ },
+ {
+ adobename="ae",
+ category="ll",
+ cjkwd="a",
+ contextname="aeligature",
+ description="LATIN SMALL LETTER AE",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x61, 0x65 },
+ uccode=0xC6,
+ unicodeslot=0xE6,
+ },
+ {
+ adobename="ccedilla",
+ category="ll",
+ contextname="ccedilla",
+ description="LATIN SMALL LETTER C WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0x63, 0x327 },
+ uccode=0xC7,
+ unicodeslot=0xE7,
+ },
+ {
+ adobename="egrave",
+ category="ll",
+ cjkwd="a",
+ contextname="egrave",
+ description="LATIN SMALL LETTER E WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x300 },
+ uccode=0xC8,
+ unicodeslot=0xE8,
+ },
+ {
+ adobename="eacute",
+ category="ll",
+ cjkwd="a",
+ contextname="eacute",
+ description="LATIN SMALL LETTER E WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x301 },
+ uccode=0xC9,
+ unicodeslot=0xE9,
+ },
+ {
+ adobename="ecircumflex",
+ category="ll",
+ cjkwd="a",
+ contextname="ecircumflex",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x302 },
+ uccode=0xCA,
+ unicodeslot=0xEA,
+ },
+ {
+ adobename="edieresis",
+ category="ll",
+ contextname="ediaeresis",
+ description="LATIN SMALL LETTER E WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x308 },
+ uccode=0xCB,
+ unicodeslot=0xEB,
+ },
+ {
+ adobename="igrave",
+ category="ll",
+ cjkwd="a",
+ contextname="igrave",
+ description="LATIN SMALL LETTER I WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x300 },
+ uccode=0xCC,
+ unicodeslot=0xEC,
+ },
+ {
+ adobename="iacute",
+ category="ll",
+ cjkwd="a",
+ contextname="iacute",
+ description="LATIN SMALL LETTER I WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x301 },
+ uccode=0xCD,
+ unicodeslot=0xED,
+ },
+ {
+ adobename="icircumflex",
+ category="ll",
+ contextname="icircumflex",
+ description="LATIN SMALL LETTER I WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x302 },
+ uccode=0xCE,
+ unicodeslot=0xEE,
+ },
+ {
+ adobename="idieresis",
+ category="ll",
+ contextname="idiaeresis",
+ description="LATIN SMALL LETTER I WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x308 },
+ uccode=0xCF,
+ unicodeslot=0xEF,
+ },
+ {
+ adobename="eth",
+ category="ll",
+ cjkwd="a",
+ comment="contextname=eth",
+ description="LATIN SMALL LETTER ETH",
+ direction="l",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="eth",
+ uccode=0xD0,
+ unicodeslot=0xF0,
+ },
+ {
+ adobename="ntilde",
+ category="ll",
+ contextname="ntilde",
+ description="LATIN SMALL LETTER N WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x303 },
+ uccode=0xD1,
+ unicodeslot=0xF1,
+ },
+ {
+ adobename="ograve",
+ category="ll",
+ cjkwd="a",
+ contextname="ograve",
+ description="LATIN SMALL LETTER O WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x300 },
+ uccode=0xD2,
+ unicodeslot=0xF2,
+ },
+ {
+ adobename="oacute",
+ category="ll",
+ cjkwd="a",
+ contextname="oacute",
+ description="LATIN SMALL LETTER O WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x301 },
+ uccode=0xD3,
+ unicodeslot=0xF3,
+ },
+ {
+ adobename="ocircumflex",
+ category="ll",
+ contextname="ocircumflex",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x302 },
+ uccode=0xD4,
+ unicodeslot=0xF4,
+ },
+ {
+ adobename="otilde",
+ category="ll",
+ contextname="otilde",
+ description="LATIN SMALL LETTER O WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x303 },
+ uccode=0xD5,
+ unicodeslot=0xF5,
+ },
+ {
+ adobename="odieresis",
+ category="ll",
+ contextname="odiaeresis",
+ description="LATIN SMALL LETTER O WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x308 },
+ uccode=0xD6,
+ unicodeslot=0xF6,
+ },
+ {
+ adobename="divide",
+ category="sm",
+ cjkwd="a",
+ contextname="textdiv",
+ description="DIVISION SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="div",
+ unicodeslot=0xF7,
+ },
+ {
+ adobename="oslash",
+ category="ll",
+ cjkwd="a",
+ contextname="ostroke",
+ description="LATIN SMALL LETTER O WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ uccode=0xD8,
+ unicodeslot=0xF8,
+ },
+ {
+ adobename="ugrave",
+ category="ll",
+ cjkwd="a",
+ contextname="ugrave",
+ description="LATIN SMALL LETTER U WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x300 },
+ uccode=0xD9,
+ unicodeslot=0xF9,
+ },
+ {
+ adobename="uacute",
+ category="ll",
+ cjkwd="a",
+ contextname="uacute",
+ description="LATIN SMALL LETTER U WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x301 },
+ uccode=0xDA,
+ unicodeslot=0xFA,
+ },
+ {
+ adobename="ucircumflex",
+ category="ll",
+ contextname="ucircumflex",
+ description="LATIN SMALL LETTER U WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x302 },
+ uccode=0xDB,
+ unicodeslot=0xFB,
+ },
+ {
+ adobename="udieresis",
+ category="ll",
+ cjkwd="a",
+ contextname="udiaeresis",
+ description="LATIN SMALL LETTER U WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x308 },
+ uccode=0xDC,
+ unicodeslot=0xFC,
+ },
+ {
+ adobename="yacute",
+ category="ll",
+ contextname="yacute",
+ description="LATIN SMALL LETTER Y WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x301 },
+ uccode=0xDD,
+ unicodeslot=0xFD,
+ },
+ {
+ adobename="thorn",
+ category="ll",
+ cjkwd="a",
+ contextname="thorn",
+ description="LATIN SMALL LETTER THORN",
+ direction="l",
+ linebreak="al",
+ uccode=0xDE,
+ unicodeslot=0xFE,
+ },
+ {
+ adobename="ydieresis",
+ category="ll",
+ contextname="ydiaeresis",
+ description="LATIN SMALL LETTER Y WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x308 },
+ uccode=0x178,
+ unicodeslot=0xFF,
+ },
+ {
+ adobename="Amacron",
+ category="lu",
+ contextname="Amacron",
+ description="LATIN CAPITAL LETTER A WITH MACRON",
+ direction="l",
+ lccode=0x101,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x304 },
+ unicodeslot=0x100,
+ },
+ {
+ adobename="amacron",
+ category="ll",
+ cjkwd="a",
+ contextname="amacron",
+ description="LATIN SMALL LETTER A WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x304 },
+ uccode=0x100,
+ unicodeslot=0x101,
+ },
+ {
+ adobename="Abreve",
+ category="lu",
+ contextname="Abreve",
+ description="LATIN CAPITAL LETTER A WITH BREVE",
+ direction="l",
+ lccode=0x103,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x306 },
+ unicodeslot=0x102,
+ },
+ {
+ adobename="abreve",
+ category="ll",
+ contextname="abreve",
+ description="LATIN SMALL LETTER A WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x306 },
+ uccode=0x102,
+ unicodeslot=0x103,
+ },
+ {
+ adobename="Aogonek",
+ category="lu",
+ contextname="Aogonek",
+ description="LATIN CAPITAL LETTER A WITH OGONEK",
+ direction="l",
+ lccode=0x105,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x328 },
+ unicodeslot=0x104,
+ },
+ {
+ adobename="aogonek",
+ category="ll",
+ contextname="aogonek",
+ description="LATIN SMALL LETTER A WITH OGONEK",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x328 },
+ uccode=0x104,
+ unicodeslot=0x105,
+ },
+ {
+ adobename="Cacute",
+ category="lu",
+ contextname="Cacute",
+ description="LATIN CAPITAL LETTER C WITH ACUTE",
+ direction="l",
+ lccode=0x107,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0x43, 0x301 },
+ unicodeslot=0x106,
+ },
+ {
+ adobename="cacute",
+ category="ll",
+ contextname="cacute",
+ description="LATIN SMALL LETTER C WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0x63, 0x301 },
+ uccode=0x106,
+ unicodeslot=0x107,
+ },
+ {
+ adobename="Ccircumflex",
+ category="lu",
+ contextname="Ccircumflex",
+ description="LATIN CAPITAL LETTER C WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x109,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0x43, 0x302 },
+ unicodeslot=0x108,
+ },
+ {
+ adobename="ccircumflex",
+ category="ll",
+ contextname="ccircumflex",
+ description="LATIN SMALL LETTER C WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0x63, 0x302 },
+ uccode=0x108,
+ unicodeslot=0x109,
+ },
+ {
+ adobename="Cdotaccent",
+ category="lu",
+ contextname="Cdotaccent",
+ description="LATIN CAPITAL LETTER C WITH DOT ABOVE",
+ direction="l",
+ lccode=0x10B,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0x43, 0x307 },
+ unicodeslot=0x10A,
+ },
+ {
+ adobename="cdotaccent",
+ category="ll",
+ contextname="cdotaccent",
+ description="LATIN SMALL LETTER C WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0x63, 0x307 },
+ uccode=0x10A,
+ unicodeslot=0x10B,
+ },
+ {
+ adobename="Ccaron",
+ category="lu",
+ contextname="Ccaron",
+ description="LATIN CAPITAL LETTER C WITH CARON",
+ direction="l",
+ lccode=0x10D,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0x43, 0x30C },
+ unicodeslot=0x10C,
+ },
+ {
+ adobename="ccaron",
+ category="ll",
+ contextname="ccaron",
+ description="LATIN SMALL LETTER C WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0x63, 0x30C },
+ uccode=0x10C,
+ unicodeslot=0x10D,
+ },
+ {
+ adobename="Dcaron",
+ category="lu",
+ contextname="Dcaron",
+ description="LATIN CAPITAL LETTER D WITH CARON",
+ direction="l",
+ lccode=0x10F,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x30C },
+ unicodeslot=0x10E,
+ },
+ {
+ adobename="dcaron",
+ category="ll",
+ contextname="dcaron",
+ description="LATIN SMALL LETTER D WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x30C },
+ uccode=0x10E,
+ unicodeslot=0x10F,
+ },
+ {
+ adobename="Dslash",
+ category="lu",
+ contextname="Dstroke",
+ description="LATIN CAPITAL LETTER D WITH STROKE",
+ direction="l",
+ lccode=0x111,
+ linebreak="al",
+ shcode=0x44,
+ unicodeslot=0x110,
+ },
+ {
+ adobename="dmacron",
+ category="ll",
+ cjkwd="a",
+ contextname="dstroke",
+ description="LATIN SMALL LETTER D WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ uccode=0x110,
+ unicodeslot=0x111,
+ },
+ {
+ adobename="Emacron",
+ category="lu",
+ contextname="Emacron",
+ description="LATIN CAPITAL LETTER E WITH MACRON",
+ direction="l",
+ lccode=0x113,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x304 },
+ unicodeslot=0x112,
+ },
+ {
+ adobename="emacron",
+ category="ll",
+ cjkwd="a",
+ contextname="emacron",
+ description="LATIN SMALL LETTER E WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x304 },
+ uccode=0x112,
+ unicodeslot=0x113,
+ },
+ {
+ adobename="Ebreve",
+ category="lu",
+ contextname="Ebreve",
+ description="LATIN CAPITAL LETTER E WITH BREVE",
+ direction="l",
+ lccode=0x115,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x306 },
+ unicodeslot=0x114,
+ },
+ {
+ adobename="ebreve",
+ category="ll",
+ contextname="ebreve",
+ description="LATIN SMALL LETTER E WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x306 },
+ uccode=0x114,
+ unicodeslot=0x115,
+ },
+ {
+ adobename="Edotaccent",
+ category="lu",
+ contextname="Edotaccent",
+ description="LATIN CAPITAL LETTER E WITH DOT ABOVE",
+ direction="l",
+ lccode=0x117,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x307 },
+ unicodeslot=0x116,
+ },
+ {
+ adobename="edotaccent",
+ category="ll",
+ contextname="edotaccent",
+ description="LATIN SMALL LETTER E WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x307 },
+ uccode=0x116,
+ unicodeslot=0x117,
+ },
+ {
+ adobename="Eogonek",
+ category="lu",
+ contextname="Eogonek",
+ description="LATIN CAPITAL LETTER E WITH OGONEK",
+ direction="l",
+ lccode=0x119,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x328 },
+ unicodeslot=0x118,
+ },
+ {
+ adobename="eogonek",
+ category="ll",
+ contextname="eogonek",
+ description="LATIN SMALL LETTER E WITH OGONEK",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x328 },
+ uccode=0x118,
+ unicodeslot=0x119,
+ },
+ {
+ adobename="Ecaron",
+ category="lu",
+ contextname="Ecaron",
+ description="LATIN CAPITAL LETTER E WITH CARON",
+ direction="l",
+ lccode=0x11B,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x30C },
+ unicodeslot=0x11A,
+ },
+ {
+ adobename="ecaron",
+ category="ll",
+ cjkwd="a",
+ contextname="ecaron",
+ description="LATIN SMALL LETTER E WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x30C },
+ uccode=0x11A,
+ unicodeslot=0x11B,
+ },
+ {
+ adobename="Gcircumflex",
+ category="lu",
+ contextname="Gcircumflex",
+ description="LATIN CAPITAL LETTER G WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x11D,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x302 },
+ unicodeslot=0x11C,
+ },
+ {
+ adobename="gcircumflex",
+ category="ll",
+ contextname="gcircumflex",
+ description="LATIN SMALL LETTER G WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x302 },
+ uccode=0x11C,
+ unicodeslot=0x11D,
+ },
+ {
+ adobename="Gbreve",
+ category="lu",
+ contextname="Gbreve",
+ description="LATIN CAPITAL LETTER G WITH BREVE",
+ direction="l",
+ lccode=0x11F,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x306 },
+ unicodeslot=0x11E,
+ },
+ {
+ adobename="gbreve",
+ category="ll",
+ contextname="gbreve",
+ description="LATIN SMALL LETTER G WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x306 },
+ uccode=0x11E,
+ unicodeslot=0x11F,
+ },
+ {
+ adobename="Gdotaccent",
+ category="lu",
+ contextname="Gdotaccent",
+ description="LATIN CAPITAL LETTER G WITH DOT ABOVE",
+ direction="l",
+ lccode=0x121,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x307 },
+ unicodeslot=0x120,
+ },
+ {
+ adobename="gdotaccent",
+ category="ll",
+ contextname="gdotaccent",
+ description="LATIN SMALL LETTER G WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x307 },
+ uccode=0x120,
+ unicodeslot=0x121,
+ },
+ {
+ adobename="Gcommaaccent",
+ category="lu",
+ contextname="Gcommaaccent",
+ description="LATIN CAPITAL LETTER G WITH CEDILLA",
+ direction="l",
+ lccode=0x123,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x327 },
+ unicodeslot=0x122,
+ },
+ {
+ adobename="gcommaaccent",
+ category="ll",
+ contextname="gcommaaccent",
+ description="LATIN SMALL LETTER G WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x327 },
+ uccode=0x122,
+ unicodeslot=0x123,
+ },
+ {
+ adobename="Hcircumflex",
+ category="lu",
+ contextname="Hcircumflex",
+ description="LATIN CAPITAL LETTER H WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x125,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x302 },
+ unicodeslot=0x124,
+ },
+ {
+ adobename="hcircumflex",
+ category="ll",
+ contextname="hcircumflex",
+ description="LATIN SMALL LETTER H WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x302 },
+ uccode=0x124,
+ unicodeslot=0x125,
+ },
+ {
+ adobename="Hbar",
+ category="lu",
+ cjkwd="a",
+ contextname="Hstroke",
+ description="LATIN CAPITAL LETTER H WITH STROKE",
+ direction="l",
+ lccode=0x127,
+ linebreak="al",
+ shcode=0x48,
+ unicodeslot=0x126,
+ },
+ {
+ adobename="hbar",
+ category="ll",
+ cjkwd="a",
+ contextname="hstroke",
+ description="LATIN SMALL LETTER H WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ uccode=0x126,
+ unicodeslot=0x127,
+ },
+ {
+ adobename="Itilde",
+ category="lu",
+ contextname="Itilde",
+ description="LATIN CAPITAL LETTER I WITH TILDE",
+ direction="l",
+ lccode=0x129,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x303 },
+ unicodeslot=0x128,
+ },
+ {
+ adobename="itilde",
+ category="ll",
+ contextname="itilde",
+ description="LATIN SMALL LETTER I WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x303 },
+ uccode=0x128,
+ unicodeslot=0x129,
+ },
+ {
+ adobename="Imacron",
+ category="lu",
+ contextname="Imacron",
+ description="LATIN CAPITAL LETTER I WITH MACRON",
+ direction="l",
+ lccode=0x12B,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x304 },
+ unicodeslot=0x12A,
+ },
+ {
+ adobename="imacron",
+ category="ll",
+ cjkwd="a",
+ contextname="imacron",
+ description="LATIN SMALL LETTER I WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x304 },
+ uccode=0x12A,
+ unicodeslot=0x12B,
+ },
+ {
+ adobename="Ibreve",
+ category="lu",
+ contextname="Ibreve",
+ description="LATIN CAPITAL LETTER I WITH BREVE",
+ direction="l",
+ lccode=0x12D,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x306 },
+ unicodeslot=0x12C,
+ },
+ {
+ adobename="ibreve",
+ category="ll",
+ contextname="ibreve",
+ description="LATIN SMALL LETTER I WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x306 },
+ uccode=0x12C,
+ unicodeslot=0x12D,
+ },
+ {
+ adobename="Iogonek",
+ category="lu",
+ contextname="Iogonek",
+ description="LATIN CAPITAL LETTER I WITH OGONEK",
+ direction="l",
+ lccode=0x12F,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x328 },
+ unicodeslot=0x12E,
+ },
+ {
+ adobename="iogonek",
+ category="ll",
+ contextname="iogonek",
+ description="LATIN SMALL LETTER I WITH OGONEK",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x328 },
+ uccode=0x12E,
+ unicodeslot=0x12F,
+ },
+ {
+ adobename="Idotaccent",
+ category="lu",
+ contextname="Idotaccent",
+ description="LATIN CAPITAL LETTER I WITH DOT ABOVE",
+ direction="l",
+ lccode=0x69,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x307 },
+ unicodeslot=0x130,
+ },
+ {
+ adobename="dotlessi",
+ category="ll",
+ cjkwd="a",
+ contextname="dotlessi",
+ description="LATIN SMALL LETTER DOTLESS I",
+ direction="l",
+ linebreak="al",
+ uccode=0x49,
+ unicodeslot=0x131,
+ },
+ {
+ adobename="IJ",
+ category="lu",
+ cjkwd="a",
+ contextname="IJligature",
+ description="LATIN CAPITAL LIGATURE IJ",
+ direction="l",
+ lccode=0x133,
+ linebreak="al",
+ shcode={ 0x49, 0x4A },
+ specials={ "compat", 0x49, 0x4A },
+ unicodeslot=0x132,
+ },
+ {
+ adobename="ij",
+ category="ll",
+ cjkwd="a",
+ contextname="ijligature",
+ description="LATIN SMALL LIGATURE IJ",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x69, 0x6A },
+ specials={ "compat", 0x69, 0x6A },
+ uccode=0x132,
+ unicodeslot=0x133,
+ },
+ {
+ adobename="Jcircumflex",
+ category="lu",
+ contextname="Jcircumflex",
+ description="LATIN CAPITAL LETTER J WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x135,
+ linebreak="al",
+ shcode=0x4A,
+ specials={ "char", 0x4A, 0x302 },
+ unicodeslot=0x134,
+ },
+ {
+ adobename="jcircumflex",
+ category="ll",
+ contextname="jcircumflex",
+ description="LATIN SMALL LETTER J WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x6A,
+ specials={ "char", 0x6A, 0x302 },
+ uccode=0x134,
+ unicodeslot=0x135,
+ },
+ {
+ adobename="Kcommaaccent",
+ category="lu",
+ contextname="Kcommaaccent",
+ description="LATIN CAPITAL LETTER K WITH CEDILLA",
+ direction="l",
+ lccode=0x137,
+ linebreak="al",
+ shcode=0x4B,
+ specials={ "char", 0x4B, 0x327 },
+ unicodeslot=0x136,
+ },
+ {
+ adobename="kcommaaccent",
+ category="ll",
+ contextname="kcommaaccent",
+ description="LATIN SMALL LETTER K WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ specials={ "char", 0x6B, 0x327 },
+ uccode=0x136,
+ unicodeslot=0x137,
+ },
+ {
+ adobename="kgreenlandic",
+ category="ll",
+ cjkwd="a",
+ contextname="kkra",
+ description="LATIN SMALL LETTER KRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138,
+ },
+ {
+ adobename="Lacute",
+ category="lu",
+ contextname="Lacute",
+ description="LATIN CAPITAL LETTER L WITH ACUTE",
+ direction="l",
+ lccode=0x13A,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x301 },
+ unicodeslot=0x139,
+ },
+ {
+ adobename="lacute",
+ category="ll",
+ contextname="lacute",
+ description="LATIN SMALL LETTER L WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x301 },
+ uccode=0x139,
+ unicodeslot=0x13A,
+ },
+ {
+ adobename="Lcommaaccent",
+ category="lu",
+ contextname="Lcommaaccent",
+ description="LATIN CAPITAL LETTER L WITH CEDILLA",
+ direction="l",
+ lccode=0x13C,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x327 },
+ unicodeslot=0x13B,
+ },
+ {
+ adobename="lcommaaccent",
+ category="ll",
+ contextname="lcommaaccent",
+ description="LATIN SMALL LETTER L WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x327 },
+ uccode=0x13B,
+ unicodeslot=0x13C,
+ },
+ {
+ adobename="Lcaron",
+ category="lu",
+ contextname="Lcaron",
+ description="LATIN CAPITAL LETTER L WITH CARON",
+ direction="l",
+ lccode=0x13E,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x30C },
+ unicodeslot=0x13D,
+ },
+ {
+ adobename="lcaron",
+ category="ll",
+ contextname="lcaron",
+ description="LATIN SMALL LETTER L WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x30C },
+ uccode=0x13D,
+ unicodeslot=0x13E,
+ },
+ {
+ adobename="Ldotaccent",
+ category="lu",
+ cjkwd="a",
+ contextname="Ldotmiddle",
+ description="LATIN CAPITAL LETTER L WITH MIDDLE DOT",
+ direction="l",
+ lccode=0x140,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "compat", 0x4C, 0xB7 },
+ unicodeslot=0x13F,
+ },
+ {
+ adobename="ldotaccent",
+ category="ll",
+ cjkwd="a",
+ contextname="ldotmiddle",
+ description="LATIN SMALL LETTER L WITH MIDDLE DOT",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "compat", 0x6C, 0xB7 },
+ uccode=0x13F,
+ unicodeslot=0x140,
+ },
+ {
+ adobename="Lslash",
+ category="lu",
+ cjkwd="a",
+ contextname="Lstroke",
+ description="LATIN CAPITAL LETTER L WITH STROKE",
+ direction="l",
+ lccode=0x142,
+ linebreak="al",
+ shcode=0x4C,
+ unicodeslot=0x141,
+ },
+ {
+ adobename="lslash",
+ category="ll",
+ cjkwd="a",
+ contextname="lstroke",
+ description="LATIN SMALL LETTER L WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ uccode=0x141,
+ unicodeslot=0x142,
+ },
+ {
+ adobename="Nacute",
+ category="lu",
+ contextname="Nacute",
+ description="LATIN CAPITAL LETTER N WITH ACUTE",
+ direction="l",
+ lccode=0x144,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x301 },
+ unicodeslot=0x143,
+ },
+ {
+ adobename="nacute",
+ category="ll",
+ cjkwd="a",
+ contextname="nacute",
+ description="LATIN SMALL LETTER N WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x301 },
+ uccode=0x143,
+ unicodeslot=0x144,
+ },
+ {
+ adobename="Ncommaaccent",
+ category="lu",
+ contextname="Ncommaaccent",
+ description="LATIN CAPITAL LETTER N WITH CEDILLA",
+ direction="l",
+ lccode=0x146,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x327 },
+ unicodeslot=0x145,
+ },
+ {
+ adobename="ncommaaccent",
+ category="ll",
+ contextname="ncommaaccent",
+ description="LATIN SMALL LETTER N WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x327 },
+ uccode=0x145,
+ unicodeslot=0x146,
+ },
+ {
+ adobename="Ncaron",
+ category="lu",
+ contextname="Ncaron",
+ description="LATIN CAPITAL LETTER N WITH CARON",
+ direction="l",
+ lccode=0x148,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x30C },
+ unicodeslot=0x147,
+ },
+ {
+ adobename="ncaron",
+ category="ll",
+ cjkwd="a",
+ contextname="ncaron",
+ description="LATIN SMALL LETTER N WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x30C },
+ uccode=0x147,
+ unicodeslot=0x148,
+ },
+ {
+ adobename="quoterightn",
+ category="ll",
+ cjkwd="a",
+ contextname="napostrophe",
+ description="LATIN SMALL LETTER N PRECEDED BY APOSTROPHE",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x2BC, 0x6E },
+ unicodeslot=0x149,
+ },
+ {
+ adobename="Eng",
+ category="lu",
+ cjkwd="a",
+ contextname="Neng",
+ description="LATIN CAPITAL LETTER ENG",
+ direction="l",
+ lccode=0x14B,
+ linebreak="al",
+ unicodeslot=0x14A,
+ },
+ {
+ adobename="eng",
+ category="ll",
+ cjkwd="a",
+ contextname="neng",
+ description="LATIN SMALL LETTER ENG",
+ direction="l",
+ linebreak="al",
+ uccode=0x14A,
+ unicodeslot=0x14B,
+ },
+ {
+ adobename="Omacron",
+ category="lu",
+ contextname="Omacron",
+ description="LATIN CAPITAL LETTER O WITH MACRON",
+ direction="l",
+ lccode=0x14D,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x304 },
+ unicodeslot=0x14C,
+ },
+ {
+ adobename="omacron",
+ category="ll",
+ cjkwd="a",
+ contextname="omacron",
+ description="LATIN SMALL LETTER O WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x304 },
+ uccode=0x14C,
+ unicodeslot=0x14D,
+ },
+ {
+ adobename="Obreve",
+ category="lu",
+ contextname="Obreve",
+ description="LATIN CAPITAL LETTER O WITH BREVE",
+ direction="l",
+ lccode=0x14F,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x306 },
+ unicodeslot=0x14E,
+ },
+ {
+ adobename="obreve",
+ category="ll",
+ contextname="obreve",
+ description="LATIN SMALL LETTER O WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x306 },
+ uccode=0x14E,
+ unicodeslot=0x14F,
+ },
+ {
+ adobename="Ohungarumlaut",
+ category="lu",
+ contextname="Ohungarumlaut",
+ description="LATIN CAPITAL LETTER O WITH DOUBLE ACUTE",
+ direction="l",
+ lccode=0x151,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x30B },
+ unicodeslot=0x150,
+ },
+ {
+ adobename="ohungarumlaut",
+ category="ll",
+ contextname="ohungarumlaut",
+ description="LATIN SMALL LETTER O WITH DOUBLE ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x30B },
+ uccode=0x150,
+ unicodeslot=0x151,
+ },
+ {
+ adobename="OE",
+ category="lu",
+ cjkwd="a",
+ contextname="OEligature",
+ description="LATIN CAPITAL LIGATURE OE",
+ direction="l",
+ lccode=0x153,
+ linebreak="al",
+ shcode={ 0x4F, 0x45 },
+ unicodeslot=0x152,
+ },
+ {
+ adobename="oe",
+ category="ll",
+ cjkwd="a",
+ contextname="oeligature",
+ description="LATIN SMALL LIGATURE OE",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x6F, 0x65 },
+ uccode=0x152,
+ unicodeslot=0x153,
+ },
+ {
+ adobename="Racute",
+ category="lu",
+ contextname="Racute",
+ description="LATIN CAPITAL LETTER R WITH ACUTE",
+ direction="l",
+ lccode=0x155,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x301 },
+ unicodeslot=0x154,
+ },
+ {
+ adobename="racute",
+ category="ll",
+ contextname="racute",
+ description="LATIN SMALL LETTER R WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x301 },
+ uccode=0x154,
+ unicodeslot=0x155,
+ },
+ {
+ adobename="Rcommaaccent",
+ category="lu",
+ contextname="Rcommaaccent",
+ description="LATIN CAPITAL LETTER R WITH CEDILLA",
+ direction="l",
+ lccode=0x157,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x327 },
+ unicodeslot=0x156,
+ },
+ {
+ adobename="rcommaaccent",
+ category="ll",
+ contextname="rcommaaccent",
+ description="LATIN SMALL LETTER R WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x327 },
+ uccode=0x156,
+ unicodeslot=0x157,
+ },
+ {
+ adobename="Rcaron",
+ category="lu",
+ contextname="Rcaron",
+ description="LATIN CAPITAL LETTER R WITH CARON",
+ direction="l",
+ lccode=0x159,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x30C },
+ unicodeslot=0x158,
+ },
+ {
+ adobename="rcaron",
+ category="ll",
+ contextname="rcaron",
+ description="LATIN SMALL LETTER R WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x30C },
+ uccode=0x158,
+ unicodeslot=0x159,
+ },
+ {
+ adobename="Sacute",
+ category="lu",
+ contextname="Sacute",
+ description="LATIN CAPITAL LETTER S WITH ACUTE",
+ direction="l",
+ lccode=0x15B,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x301 },
+ unicodeslot=0x15A,
+ },
+ {
+ adobename="sacute",
+ category="ll",
+ contextname="sacute",
+ description="LATIN SMALL LETTER S WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x301 },
+ uccode=0x15A,
+ unicodeslot=0x15B,
+ },
+ {
+ adobename="Scircumflex",
+ category="lu",
+ contextname="Scircumflex",
+ description="LATIN CAPITAL LETTER S WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x15D,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x302 },
+ unicodeslot=0x15C,
+ },
+ {
+ adobename="scircumflex",
+ category="ll",
+ contextname="scircumflex",
+ description="LATIN SMALL LETTER S WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x302 },
+ uccode=0x15C,
+ unicodeslot=0x15D,
+ },
+ {
+ adobename="Scedilla",
+ category="lu",
+ contextname="Scedilla",
+ description="LATIN CAPITAL LETTER S WITH CEDILLA",
+ direction="l",
+ lccode=0x15F,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x327 },
+ unicodeslot=0x15E,
+ },
+ {
+ adobename="scedilla",
+ category="ll",
+ contextname="scedilla",
+ description="LATIN SMALL LETTER S WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x327 },
+ uccode=0x15E,
+ unicodeslot=0x15F,
+ },
+ {
+ adobename="Scaron",
+ category="lu",
+ contextname="Scaron",
+ description="LATIN CAPITAL LETTER S WITH CARON",
+ direction="l",
+ lccode=0x161,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x30C },
+ unicodeslot=0x160,
+ },
+ {
+ adobename="scaron",
+ category="ll",
+ contextname="scaron",
+ description="LATIN SMALL LETTER S WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x30C },
+ uccode=0x160,
+ unicodeslot=0x161,
+ },
+ {
+ adobename="Tcommaaccent",
+ category="lu",
+ contextname="Tcedilla",
+ description="LATIN CAPITAL LETTER T WITH CEDILLA",
+ direction="l",
+ lccode=0x163,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x327 },
+ unicodeslot=0x162,
+ },
+ {
+ adobename="tcommaaccent",
+ category="ll",
+ contextname="tcedilla",
+ description="LATIN SMALL LETTER T WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x327 },
+ uccode=0x162,
+ unicodeslot=0x163,
+ },
+ {
+ adobename="Tcaron",
+ category="lu",
+ contextname="Tcaron",
+ description="LATIN CAPITAL LETTER T WITH CARON",
+ direction="l",
+ lccode=0x165,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x30C },
+ unicodeslot=0x164,
+ },
+ {
+ adobename="tcaron",
+ category="ll",
+ contextname="tcaron",
+ description="LATIN SMALL LETTER T WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x30C },
+ uccode=0x164,
+ unicodeslot=0x165,
+ },
+ {
+ adobename="Tbar",
+ category="lu",
+ cjkwd="a",
+ contextname="Tstroke",
+ description="LATIN CAPITAL LETTER T WITH STROKE",
+ direction="l",
+ lccode=0x167,
+ linebreak="al",
+ shcode=0x54,
+ unicodeslot=0x166,
+ },
+ {
+ adobename="tbar",
+ category="ll",
+ cjkwd="a",
+ contextname="tstroke",
+ description="LATIN SMALL LETTER T WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ uccode=0x166,
+ unicodeslot=0x167,
+ },
+ {
+ adobename="Utilde",
+ category="lu",
+ contextname="Utilde",
+ description="LATIN CAPITAL LETTER U WITH TILDE",
+ direction="l",
+ lccode=0x169,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x303 },
+ unicodeslot=0x168,
+ },
+ {
+ adobename="utilde",
+ category="ll",
+ contextname="utilde",
+ description="LATIN SMALL LETTER U WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x303 },
+ uccode=0x168,
+ unicodeslot=0x169,
+ },
+ {
+ adobename="Umacron",
+ category="lu",
+ contextname="Umacron",
+ description="LATIN CAPITAL LETTER U WITH MACRON",
+ direction="l",
+ lccode=0x16B,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x304 },
+ unicodeslot=0x16A,
+ },
+ {
+ adobename="umacron",
+ category="ll",
+ cjkwd="a",
+ contextname="umacron",
+ description="LATIN SMALL LETTER U WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x304 },
+ uccode=0x16A,
+ unicodeslot=0x16B,
+ },
+ {
+ adobename="Ubreve",
+ category="lu",
+ contextname="Ubreve",
+ description="LATIN CAPITAL LETTER U WITH BREVE",
+ direction="l",
+ lccode=0x16D,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x306 },
+ unicodeslot=0x16C,
+ },
+ {
+ adobename="ubreve",
+ category="ll",
+ contextname="ubreve",
+ description="LATIN SMALL LETTER U WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x306 },
+ uccode=0x16C,
+ unicodeslot=0x16D,
+ },
+ {
+ adobename="Uring",
+ category="lu",
+ contextname="Uring",
+ description="LATIN CAPITAL LETTER U WITH RING ABOVE",
+ direction="l",
+ lccode=0x16F,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x30A },
+ unicodeslot=0x16E,
+ },
+ {
+ adobename="uring",
+ category="ll",
+ contextname="uring",
+ description="LATIN SMALL LETTER U WITH RING ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x30A },
+ uccode=0x16E,
+ unicodeslot=0x16F,
+ },
+ {
+ adobename="Uhungarumlaut",
+ category="lu",
+ contextname="Uhungarumlaut",
+ description="LATIN CAPITAL LETTER U WITH DOUBLE ACUTE",
+ direction="l",
+ lccode=0x171,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x30B },
+ unicodeslot=0x170,
+ },
+ {
+ adobename="uhungarumlaut",
+ category="ll",
+ contextname="uhungarumlaut",
+ description="LATIN SMALL LETTER U WITH DOUBLE ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x30B },
+ uccode=0x170,
+ unicodeslot=0x171,
+ },
+ {
+ adobename="Uogonek",
+ category="lu",
+ contextname="Uogonek",
+ description="LATIN CAPITAL LETTER U WITH OGONEK",
+ direction="l",
+ lccode=0x173,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x328 },
+ unicodeslot=0x172,
+ },
+ {
+ adobename="uogonek",
+ category="ll",
+ contextname="uogonek",
+ description="LATIN SMALL LETTER U WITH OGONEK",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x328 },
+ uccode=0x172,
+ unicodeslot=0x173,
+ },
+ {
+ adobename="Wcircumflex",
+ category="lu",
+ contextname="Wcircumflex",
+ description="LATIN CAPITAL LETTER W WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x175,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x302 },
+ unicodeslot=0x174,
+ },
+ {
+ adobename="wcircumflex",
+ category="ll",
+ contextname="wcircumflex",
+ description="LATIN SMALL LETTER W WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x302 },
+ uccode=0x174,
+ unicodeslot=0x175,
+ },
+ {
+ adobename="Ycircumflex",
+ category="lu",
+ contextname="Ycircumflex",
+ description="LATIN CAPITAL LETTER Y WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x177,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x302 },
+ unicodeslot=0x176,
+ },
+ {
+ adobename="ycircumflex",
+ category="ll",
+ contextname="ycircumflex",
+ description="LATIN SMALL LETTER Y WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x302 },
+ uccode=0x176,
+ unicodeslot=0x177,
+ },
+ {
+ adobename="Ydieresis",
+ category="lu",
+ contextname="Ydiaeresis",
+ description="LATIN CAPITAL LETTER Y WITH DIAERESIS",
+ direction="l",
+ lccode=0xFF,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x308 },
+ unicodeslot=0x178,
+ },
+ {
+ adobename="Zacute",
+ category="lu",
+ contextname="Zacute",
+ description="LATIN CAPITAL LETTER Z WITH ACUTE",
+ direction="l",
+ lccode=0x17A,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x301 },
+ unicodeslot=0x179,
+ },
+ {
+ adobename="zacute",
+ category="ll",
+ contextname="zacute",
+ description="LATIN SMALL LETTER Z WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x301 },
+ uccode=0x179,
+ unicodeslot=0x17A,
+ },
+ {
+ adobename="Zdotaccent",
+ category="lu",
+ contextname="Zdotaccent",
+ description="LATIN CAPITAL LETTER Z WITH DOT ABOVE",
+ direction="l",
+ lccode=0x17C,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x307 },
+ unicodeslot=0x17B,
+ },
+ {
+ adobename="zdotaccent",
+ category="ll",
+ contextname="zdotaccent",
+ description="LATIN SMALL LETTER Z WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x307 },
+ uccode=0x17B,
+ unicodeslot=0x17C,
+ },
+ {
+ adobename="Zcaron",
+ category="lu",
+ contextname="Zcaron",
+ description="LATIN CAPITAL LETTER Z WITH CARON",
+ direction="l",
+ lccode=0x17E,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x30C },
+ unicodeslot=0x17D,
+ },
+ {
+ adobename="zcaron",
+ category="ll",
+ contextname="zcaron",
+ description="LATIN SMALL LETTER Z WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x30C },
+ uccode=0x17D,
+ unicodeslot=0x17E,
+ },
+ {
+ adobename="slong",
+ category="ll",
+ contextname="slong",
+ description="LATIN SMALL LETTER LONG S",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x73 },
+ uccode=0x53,
+ unicodeslot=0x17F,
+ },
+ {
+ adobename="bstroke",
+ category="ll",
+ contextname="bstroke",
+ description="LATIN SMALL LETTER B WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ uccode=0x243,
+ unicodeslot=0x180,
+ },
+ {
+ adobename="Bhook",
+ category="lu",
+ contextname="Bhook",
+ description="LATIN CAPITAL LETTER B WITH HOOK",
+ direction="l",
+ lccode=0x253,
+ linebreak="al",
+ shcode=0x42,
+ unicodeslot=0x181,
+ },
+ {
+ adobename="Btopbar",
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH TOPBAR",
+ direction="l",
+ lccode=0x183,
+ linebreak="al",
+ shcode=0x42,
+ unicodeslot=0x182,
+ },
+ {
+ adobename="btopbar",
+ category="ll",
+ description="LATIN SMALL LETTER B WITH TOPBAR",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ uccode=0x182,
+ unicodeslot=0x183,
+ },
+ {
+ adobename="Tonesix",
+ category="lu",
+ description="LATIN CAPITAL LETTER TONE SIX",
+ direction="l",
+ lccode=0x185,
+ linebreak="al",
+ unicodeslot=0x184,
+ },
+ {
+ adobename="tonesix",
+ category="ll",
+ description="LATIN SMALL LETTER TONE SIX",
+ direction="l",
+ linebreak="al",
+ uccode=0x184,
+ unicodeslot=0x185,
+ },
+ {
+ adobename="Oopen",
+ category="lu",
+ description="LATIN CAPITAL LETTER OPEN O",
+ direction="l",
+ lccode=0x254,
+ linebreak="al",
+ unicodeslot=0x186,
+ },
+ {
+ adobename="Chook",
+ category="lu",
+ contextname="Chook",
+ description="LATIN CAPITAL LETTER C WITH HOOK",
+ direction="l",
+ lccode=0x188,
+ linebreak="al",
+ shcode=0x43,
+ unicodeslot=0x187,
+ },
+ {
+ adobename="chook",
+ category="ll",
+ contextname="chook",
+ description="LATIN SMALL LETTER C WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ uccode=0x187,
+ unicodeslot=0x188,
+ },
+ {
+ adobename="Dafrican",
+ category="lu",
+ contextname="Dafrican",
+ description="LATIN CAPITAL LETTER AFRICAN D",
+ direction="l",
+ lccode=0x256,
+ linebreak="al",
+ unicodeslot=0x189,
+ },
+ {
+ adobename="Dhook",
+ category="lu",
+ contextname="Dhook",
+ description="LATIN CAPITAL LETTER D WITH HOOK",
+ direction="l",
+ lccode=0x257,
+ linebreak="al",
+ shcode=0x44,
+ unicodeslot=0x18A,
+ },
+ {
+ adobename="Dtopbar",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH TOPBAR",
+ direction="l",
+ lccode=0x18C,
+ linebreak="al",
+ shcode=0x44,
+ unicodeslot=0x18B,
+ },
+ {
+ adobename="dtopbar",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH TOPBAR",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ uccode=0x18B,
+ unicodeslot=0x18C,
+ },
+ {
+ adobename="deltaturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED DELTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D,
+ },
+ {
+ adobename="Ereversed",
+ category="lu",
+ description="LATIN CAPITAL LETTER REVERSED E",
+ direction="l",
+ lccode=0x1DD,
+ linebreak="al",
+ unicodeslot=0x18E,
+ },
+ {
+ adobename="Schwa",
+ category="lu",
+ contextname="Schwa",
+ description="LATIN CAPITAL LETTER SCHWA",
+ direction="l",
+ lccode=0x259,
+ linebreak="al",
+ unicodeslot=0x18F,
+ },
+ {
+ adobename="Eopen",
+ category="lu",
+ description="LATIN CAPITAL LETTER OPEN E",
+ direction="l",
+ lccode=0x25B,
+ linebreak="al",
+ unicodeslot=0x190,
+ },
+ {
+ adobename="Fhook",
+ category="lu",
+ contextname="Fhook",
+ description="LATIN CAPITAL LETTER F WITH HOOK",
+ direction="l",
+ lccode=0x192,
+ linebreak="al",
+ shcode=0x46,
+ unicodeslot=0x191,
+ },
+ {
+ adobename="florin",
+ category="ll",
+ contextname="fhook",
+ description="LATIN SMALL LETTER F WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x66,
+ uccode=0x191,
+ unicodeslot=0x192,
+ },
+ {
+ adobename="Ghook",
+ category="lu",
+ contextname="Ghook",
+ description="LATIN CAPITAL LETTER G WITH HOOK",
+ direction="l",
+ lccode=0x260,
+ linebreak="al",
+ shcode=0x47,
+ unicodeslot=0x193,
+ },
+ {
+ adobename="Gammaafrican",
+ category="lu",
+ description="LATIN CAPITAL LETTER GAMMA",
+ direction="l",
+ lccode=0x263,
+ linebreak="al",
+ unicodeslot=0x194,
+ },
+ {
+ adobename="hv",
+ category="ll",
+ description="LATIN SMALL LETTER HV",
+ direction="l",
+ linebreak="al",
+ uccode=0x1F6,
+ unicodeslot=0x195,
+ },
+ {
+ adobename="Iotaafrican",
+ category="lu",
+ description="LATIN CAPITAL LETTER IOTA",
+ direction="l",
+ lccode=0x269,
+ linebreak="al",
+ unicodeslot=0x196,
+ },
+ {
+ adobename="Istroke",
+ category="lu",
+ contextname="Istroke",
+ description="LATIN CAPITAL LETTER I WITH STROKE",
+ direction="l",
+ lccode=0x268,
+ linebreak="al",
+ shcode=0x49,
+ unicodeslot=0x197,
+ },
+ {
+ adobename="Khook",
+ category="lu",
+ contextname="Khook",
+ description="LATIN CAPITAL LETTER K WITH HOOK",
+ direction="l",
+ lccode=0x199,
+ linebreak="al",
+ shcode=0x4B,
+ unicodeslot=0x198,
+ },
+ {
+ adobename="khook",
+ category="ll",
+ contextname="khook",
+ description="LATIN SMALL LETTER K WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ uccode=0x198,
+ unicodeslot=0x199,
+ },
+ {
+ adobename="lbar",
+ category="ll",
+ contextname="lbar",
+ description="LATIN SMALL LETTER L WITH BAR",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ uccode=0x23D,
+ unicodeslot=0x19A,
+ },
+ {
+ adobename="lambdastroke",
+ category="ll",
+ description="LATIN SMALL LETTER LAMBDA WITH STROKE",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="lambdabar",
+ unicodeslot=0x19B,
+ },
+ {
+ adobename="Mturned",
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED M",
+ direction="l",
+ lccode=0x26F,
+ linebreak="al",
+ unicodeslot=0x19C,
+ },
+ {
+ adobename="Nhookleft",
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH LEFT HOOK",
+ direction="l",
+ lccode=0x272,
+ linebreak="al",
+ shcode=0x4E,
+ unicodeslot=0x19D,
+ },
+ {
+ adobename="nlegrightlong",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH LONG RIGHT LEG",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ uccode=0x220,
+ unicodeslot=0x19E,
+ },
+ {
+ adobename="Ocenteredtilde",
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH MIDDLE TILDE",
+ direction="l",
+ lccode=0x275,
+ linebreak="al",
+ shcode=0x4F,
+ unicodeslot=0x19F,
+ },
+ {
+ adobename="Ohorn",
+ category="lu",
+ contextname="Ohorn",
+ description="LATIN CAPITAL LETTER O WITH HORN",
+ direction="l",
+ lccode=0x1A1,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x31B },
+ unicodeslot=0x1A0,
+ },
+ {
+ adobename="ohorn",
+ category="ll",
+ contextname="ohorn",
+ description="LATIN SMALL LETTER O WITH HORN",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x31B },
+ uccode=0x1A0,
+ unicodeslot=0x1A1,
+ },
+ {
+ adobename="Oi",
+ category="lu",
+ description="LATIN CAPITAL LETTER OI",
+ direction="l",
+ lccode=0x1A3,
+ linebreak="al",
+ unicodeslot=0x1A2,
+ },
+ {
+ adobename="oi",
+ category="ll",
+ description="LATIN SMALL LETTER OI",
+ direction="l",
+ linebreak="al",
+ uccode=0x1A2,
+ unicodeslot=0x1A3,
+ },
+ {
+ adobename="Phook",
+ category="lu",
+ contextname="Phook",
+ description="LATIN CAPITAL LETTER P WITH HOOK",
+ direction="l",
+ lccode=0x1A5,
+ linebreak="al",
+ shcode=0x50,
+ unicodeslot=0x1A4,
+ },
+ {
+ adobename="phook",
+ category="ll",
+ contextname="phook",
+ description="LATIN SMALL LETTER P WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ uccode=0x1A4,
+ unicodeslot=0x1A5,
+ },
+ {
+ adobename="yr",
+ category="lu",
+ description="LATIN LETTER YR",
+ direction="l",
+ lccode=0x280,
+ linebreak="al",
+ unicodeslot=0x1A6,
+ },
+ {
+ adobename="Tonetwo",
+ category="lu",
+ description="LATIN CAPITAL LETTER TONE TWO",
+ direction="l",
+ lccode=0x1A8,
+ linebreak="al",
+ unicodeslot=0x1A7,
+ },
+ {
+ adobename="tonetwo",
+ category="ll",
+ description="LATIN SMALL LETTER TONE TWO",
+ direction="l",
+ linebreak="al",
+ uccode=0x1A7,
+ unicodeslot=0x1A8,
+ },
+ {
+ adobename="Esh",
+ category="lu",
+ description="LATIN CAPITAL LETTER ESH",
+ direction="l",
+ lccode=0x283,
+ linebreak="al",
+ unicodeslot=0x1A9,
+ },
+ {
+ adobename="eshreversedloop",
+ category="ll",
+ description="LATIN LETTER REVERSED ESH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1AA,
+ },
+ {
+ adobename="tpalatalhook",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ unicodeslot=0x1AB,
+ },
+ {
+ adobename="Thook",
+ category="lu",
+ contextname="Thook",
+ description="LATIN CAPITAL LETTER T WITH HOOK",
+ direction="l",
+ lccode=0x1AD,
+ linebreak="al",
+ shcode=0x54,
+ unicodeslot=0x1AC,
+ },
+ {
+ adobename="thook",
+ category="ll",
+ contextname="thook",
+ description="LATIN SMALL LETTER T WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ uccode=0x1AC,
+ unicodeslot=0x1AD,
+ },
+ {
+ adobename="Tretroflexhook",
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH RETROFLEX HOOK",
+ direction="l",
+ lccode=0x288,
+ linebreak="al",
+ shcode=0x54,
+ unicodeslot=0x1AE,
+ },
+ {
+ adobename="Uhorn",
+ category="lu",
+ contextname="Uhorn",
+ description="LATIN CAPITAL LETTER U WITH HORN",
+ direction="l",
+ lccode=0x1B0,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x31B },
+ unicodeslot=0x1AF,
+ },
+ {
+ adobename="uhorn",
+ category="ll",
+ contextname="uhorn",
+ description="LATIN SMALL LETTER U WITH HORN",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x31B },
+ uccode=0x1AF,
+ unicodeslot=0x1B0,
+ },
+ {
+ adobename="Upsilonafrican",
+ category="lu",
+ description="LATIN CAPITAL LETTER UPSILON",
+ direction="l",
+ lccode=0x28A,
+ linebreak="al",
+ unicodeslot=0x1B1,
+ },
+ {
+ adobename="Vhook",
+ category="lu",
+ contextname="Uhook",
+ description="LATIN CAPITAL LETTER V WITH HOOK",
+ direction="l",
+ lccode=0x28B,
+ linebreak="al",
+ shcode=0x56,
+ unicodeslot=0x1B2,
+ },
+ {
+ adobename="Yhook",
+ category="lu",
+ contextname="Yhook",
+ description="LATIN CAPITAL LETTER Y WITH HOOK",
+ direction="l",
+ lccode=0x1B4,
+ linebreak="al",
+ shcode=0x59,
+ unicodeslot=0x1B3,
+ },
+ {
+ adobename="yhook",
+ category="ll",
+ contextname="yhook",
+ description="LATIN SMALL LETTER Y WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ uccode=0x1B3,
+ unicodeslot=0x1B4,
+ },
+ {
+ adobename="Zstroke",
+ category="lu",
+ contextname="Zstroke",
+ description="LATIN CAPITAL LETTER Z WITH STROKE",
+ direction="l",
+ lccode=0x1B6,
+ linebreak="al",
+ shcode=0x5A,
+ unicodeslot=0x1B5,
+ },
+ {
+ adobename="zstroke",
+ category="ll",
+ contextname="zstroke",
+ description="LATIN SMALL LETTER Z WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ uccode=0x1B5,
+ unicodeslot=0x1B6,
+ },
+ {
+ adobename="Ezh",
+ category="lu",
+ description="LATIN CAPITAL LETTER EZH",
+ direction="l",
+ lccode=0x292,
+ linebreak="al",
+ unicodeslot=0x1B7,
+ },
+ {
+ adobename="Ezhreversed",
+ category="lu",
+ description="LATIN CAPITAL LETTER EZH REVERSED",
+ direction="l",
+ lccode=0x1B9,
+ linebreak="al",
+ unicodeslot=0x1B8,
+ },
+ {
+ adobename="ezhreversed",
+ category="ll",
+ description="LATIN SMALL LETTER EZH REVERSED",
+ direction="l",
+ linebreak="al",
+ uccode=0x1B8,
+ unicodeslot=0x1B9,
+ },
+ {
+ adobename="ezhtail",
+ category="ll",
+ description="LATIN SMALL LETTER EZH WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x292,
+ unicodeslot=0x1BA,
+ },
+ {
+ adobename="twostroke",
+ category="lo",
+ description="LATIN LETTER TWO WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BB,
+ },
+ {
+ adobename="Tonefive",
+ category="lu",
+ description="LATIN CAPITAL LETTER TONE FIVE",
+ direction="l",
+ lccode=0x1BD,
+ linebreak="al",
+ unicodeslot=0x1BC,
+ },
+ {
+ adobename="tonefive",
+ category="ll",
+ description="LATIN SMALL LETTER TONE FIVE",
+ direction="l",
+ linebreak="al",
+ uccode=0x1BC,
+ unicodeslot=0x1BD,
+ },
+ {
+ adobename="glottalinvertedstroke",
+ category="ll",
+ description="LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE,
+ },
+ {
+ adobename="wynn",
+ category="ll",
+ description="LATIN LETTER WYNN",
+ direction="l",
+ linebreak="al",
+ uccode=0x1F7,
+ unicodeslot=0x1BF,
+ },
+ {
+ adobename="clickdental",
+ category="lo",
+ description="LATIN LETTER DENTAL CLICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0,
+ },
+ {
+ adobename="clicklateral",
+ category="lo",
+ description="LATIN LETTER LATERAL CLICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1,
+ },
+ {
+ adobename="clickalveolar",
+ category="lo",
+ description="LATIN LETTER ALVEOLAR CLICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C2,
+ },
+ {
+ adobename="clickretroflex",
+ category="lo",
+ description="LATIN LETTER RETROFLEX CLICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C3,
+ },
+ {
+ adobename="DZcaron",
+ category="lu",
+ contextname="DZcaronligature",
+ description="LATIN CAPITAL LETTER DZ WITH CARON",
+ direction="l",
+ lccode=0x1C6,
+ linebreak="al",
+ shcode=0x1F1,
+ specials={ "compat", 0x44, 0x17D },
+ uccode=0x1C5,
+ unicodeslot=0x1C4,
+ },
+ {
+ adobename="Dzcaron",
+ category="lt",
+ contextname="Dzcaronligature",
+ description="LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON",
+ direction="l",
+ lccode=0x1C6,
+ linebreak="al",
+ shcode=0x1F2,
+ specials={ "compat", 0x44, 0x17E },
+ uccode=0x1C4,
+ unicodeslot=0x1C5,
+ },
+ {
+ adobename="dzcaron",
+ category="ll",
+ contextname="dzcaronligature",
+ description="LATIN SMALL LETTER DZ WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x1F3,
+ specials={ "compat", 0x64, 0x17E },
+ uccode=0x1C4,
+ unicodeslot=0x1C6,
+ },
+ {
+ adobename="LJ",
+ category="lu",
+ contextname="LJligature",
+ description="LATIN CAPITAL LETTER LJ",
+ direction="l",
+ lccode=0x1C9,
+ linebreak="al",
+ shcode={ 0x4C, 0x4A },
+ specials={ "compat", 0x4C, 0x4A },
+ uccode=0x1C8,
+ unicodeslot=0x1C7,
+ },
+ {
+ adobename="Lj",
+ category="lt",
+ contextname="Ljligature",
+ description="LATIN CAPITAL LETTER L WITH SMALL LETTER J",
+ direction="l",
+ lccode=0x1C9,
+ linebreak="al",
+ shcode={ 0x4C, 0x6A },
+ specials={ "compat", 0x4C, 0x6A },
+ uccode=0x1C7,
+ unicodeslot=0x1C8,
+ },
+ {
+ adobename="lj",
+ category="ll",
+ contextname="ljligature",
+ description="LATIN SMALL LETTER LJ",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x6C, 0x6A },
+ specials={ "compat", 0x6C, 0x6A },
+ uccode=0x1C7,
+ unicodeslot=0x1C9,
+ },
+ {
+ adobename="NJ",
+ category="lu",
+ contextname="NJligature",
+ description="LATIN CAPITAL LETTER NJ",
+ direction="l",
+ lccode=0x1CC,
+ linebreak="al",
+ shcode={ 0x4E, 0x4A },
+ specials={ "compat", 0x4E, 0x4A },
+ uccode=0x1CB,
+ unicodeslot=0x1CA,
+ },
+ {
+ adobename="Nj",
+ category="lt",
+ contextname="Njligature",
+ description="LATIN CAPITAL LETTER N WITH SMALL LETTER J",
+ direction="l",
+ lccode=0x1CC,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "compat", 0x4E, 0x6A },
+ uccode=0x1CA,
+ unicodeslot=0x1CB,
+ },
+ {
+ adobename="nj",
+ category="ll",
+ contextname="njligature",
+ description="LATIN SMALL LETTER NJ",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x6E, 0x6A },
+ specials={ "compat", 0x6E, 0x6A },
+ uccode=0x1CA,
+ unicodeslot=0x1CC,
+ },
+ {
+ adobename="Acaron",
+ category="lu",
+ contextname="Acaron",
+ description="LATIN CAPITAL LETTER A WITH CARON",
+ direction="l",
+ lccode=0x1CE,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x30C },
+ unicodeslot=0x1CD,
+ },
+ {
+ adobename="acaron",
+ category="ll",
+ cjkwd="a",
+ contextname="acaron",
+ description="LATIN SMALL LETTER A WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x30C },
+ uccode=0x1CD,
+ unicodeslot=0x1CE,
+ },
+ {
+ adobename="Icaron",
+ category="lu",
+ contextname="Icaron",
+ description="LATIN CAPITAL LETTER I WITH CARON",
+ direction="l",
+ lccode=0x1D0,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x30C },
+ unicodeslot=0x1CF,
+ },
+ {
+ adobename="icaron",
+ category="ll",
+ cjkwd="a",
+ contextname="icaron",
+ description="LATIN SMALL LETTER I WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x30C },
+ uccode=0x1CF,
+ unicodeslot=0x1D0,
+ },
+ {
+ adobename="Ocaron",
+ category="lu",
+ contextname="Ocaron",
+ description="LATIN CAPITAL LETTER O WITH CARON",
+ direction="l",
+ lccode=0x1D2,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x30C },
+ unicodeslot=0x1D1,
+ },
+ {
+ adobename="ocaron",
+ category="ll",
+ cjkwd="a",
+ contextname="ocaron",
+ description="LATIN SMALL LETTER O WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x30C },
+ uccode=0x1D1,
+ unicodeslot=0x1D2,
+ },
+ {
+ adobename="Ucaron",
+ category="lu",
+ contextname="Ucaron",
+ description="LATIN CAPITAL LETTER U WITH CARON",
+ direction="l",
+ lccode=0x1D4,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x30C },
+ unicodeslot=0x1D3,
+ },
+ {
+ adobename="ucaron",
+ category="ll",
+ cjkwd="a",
+ contextname="ucaron",
+ description="LATIN SMALL LETTER U WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x30C },
+ uccode=0x1D3,
+ unicodeslot=0x1D4,
+ },
+ {
+ adobename="Udieresismacron",
+ category="lu",
+ contextname="Udiaeresismacron",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON",
+ direction="l",
+ lccode=0x1D6,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0xDC, 0x304 },
+ unicodeslot=0x1D5,
+ },
+ {
+ adobename="udieresismacron",
+ category="ll",
+ cjkwd="a",
+ contextname="udiaeresismacron",
+ description="LATIN SMALL LETTER U WITH DIAERESIS AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0xFC, 0x304 },
+ uccode=0x1D5,
+ unicodeslot=0x1D6,
+ },
+ {
+ adobename="Udieresisacute",
+ category="lu",
+ contextname="Udiaeresisacute",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE",
+ direction="l",
+ lccode=0x1D8,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0xDC, 0x301 },
+ unicodeslot=0x1D7,
+ },
+ {
+ adobename="udieresisacute",
+ category="ll",
+ cjkwd="a",
+ contextname="udiaeresisacute",
+ description="LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0xFC, 0x301 },
+ uccode=0x1D7,
+ unicodeslot=0x1D8,
+ },
+ {
+ adobename="Udieresiscaron",
+ category="lu",
+ contextname="Udiaeresiscaron",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON",
+ direction="l",
+ lccode=0x1DA,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0xDC, 0x30C },
+ unicodeslot=0x1D9,
+ },
+ {
+ adobename="udieresiscaron",
+ category="ll",
+ cjkwd="a",
+ contextname="udiaeresiscaron",
+ description="LATIN SMALL LETTER U WITH DIAERESIS AND CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0xFC, 0x30C },
+ uccode=0x1D9,
+ unicodeslot=0x1DA,
+ },
+ {
+ adobename="Udieresisgrave",
+ category="lu",
+ contextname="Udiaeresisgrave",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE",
+ direction="l",
+ lccode=0x1DC,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0xDC, 0x300 },
+ unicodeslot=0x1DB,
+ },
+ {
+ adobename="udieresisgrave",
+ category="ll",
+ cjkwd="a",
+ contextname="udiaeresisgrave",
+ description="LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0xFC, 0x300 },
+ uccode=0x1DB,
+ unicodeslot=0x1DC,
+ },
+ {
+ adobename="eturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED E",
+ direction="l",
+ linebreak="al",
+ uccode=0x18E,
+ unicodeslot=0x1DD,
+ },
+ {
+ adobename="Adieresismacron",
+ category="lu",
+ contextname="Adiaeresismacron",
+ description="LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON",
+ direction="l",
+ lccode=0x1DF,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC4, 0x304 },
+ unicodeslot=0x1DE,
+ },
+ {
+ adobename="adieresismacron",
+ category="ll",
+ contextname="adiaeresismacron",
+ description="LATIN SMALL LETTER A WITH DIAERESIS AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE4, 0x304 },
+ uccode=0x1DE,
+ unicodeslot=0x1DF,
+ },
+ {
+ adobename="Adotmacron",
+ category="lu",
+ contextname="Adotaccentmacron",
+ description="LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON",
+ direction="l",
+ lccode=0x1E1,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x226, 0x304 },
+ unicodeslot=0x1E0,
+ },
+ {
+ adobename="adotmacron",
+ category="ll",
+ contextname="adotaccentmacron",
+ description="LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x227, 0x304 },
+ uccode=0x1E0,
+ unicodeslot=0x1E1,
+ },
+ {
+ adobename="AEmacron",
+ category="lu",
+ contextname="AEmacron",
+ description="LATIN CAPITAL LETTER AE WITH MACRON",
+ direction="l",
+ lccode=0x1E3,
+ linebreak="al",
+ shcode=0xC6,
+ specials={ "char", 0xC6, 0x304 },
+ unicodeslot=0x1E2,
+ },
+ {
+ adobename="aemacron",
+ category="ll",
+ contextname="aemacron",
+ description="LATIN SMALL LETTER AE WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0xE6,
+ specials={ "char", 0xE6, 0x304 },
+ uccode=0x1E2,
+ unicodeslot=0x1E3,
+ },
+ {
+ adobename="Gstroke",
+ category="lu",
+ contextname="Gstroke",
+ description="LATIN CAPITAL LETTER G WITH STROKE",
+ direction="l",
+ lccode=0x1E5,
+ linebreak="al",
+ shcode=0x47,
+ unicodeslot=0x1E4,
+ },
+ {
+ adobename="gstroke",
+ category="ll",
+ contextname="gstroke",
+ description="LATIN SMALL LETTER G WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ uccode=0x1E4,
+ unicodeslot=0x1E5,
+ },
+ {
+ adobename="Gcaron",
+ category="lu",
+ contextname="Gcaron",
+ description="LATIN CAPITAL LETTER G WITH CARON",
+ direction="l",
+ lccode=0x1E7,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x30C },
+ unicodeslot=0x1E6,
+ },
+ {
+ adobename="gcaron",
+ category="ll",
+ contextname="gcaron",
+ description="LATIN SMALL LETTER G WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x30C },
+ uccode=0x1E6,
+ unicodeslot=0x1E7,
+ },
+ {
+ adobename="Kcaron",
+ category="lu",
+ contextname="Kcaron",
+ description="LATIN CAPITAL LETTER K WITH CARON",
+ direction="l",
+ lccode=0x1E9,
+ linebreak="al",
+ shcode=0x4B,
+ specials={ "char", 0x4B, 0x30C },
+ unicodeslot=0x1E8,
+ },
+ {
+ adobename="kcaron",
+ category="ll",
+ contextname="kcaron",
+ description="LATIN SMALL LETTER K WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ specials={ "char", 0x6B, 0x30C },
+ uccode=0x1E8,
+ unicodeslot=0x1E9,
+ },
+ {
+ adobename="Oogonek",
+ category="lu",
+ contextname="Oogonek",
+ description="LATIN CAPITAL LETTER O WITH OGONEK",
+ direction="l",
+ lccode=0x1EB,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x328 },
+ unicodeslot=0x1EA,
+ },
+ {
+ adobename="oogonek",
+ category="ll",
+ contextname="oogonek",
+ description="LATIN SMALL LETTER O WITH OGONEK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x328 },
+ uccode=0x1EA,
+ unicodeslot=0x1EB,
+ },
+ {
+ adobename="Oogonekmacron",
+ category="lu",
+ contextname="Oogonekmacron",
+ description="LATIN CAPITAL LETTER O WITH OGONEK AND MACRON",
+ direction="l",
+ lccode=0x1ED,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1EA, 0x304 },
+ unicodeslot=0x1EC,
+ },
+ {
+ adobename="oogonekmacron",
+ category="ll",
+ contextname="oogonekmacron",
+ description="LATIN SMALL LETTER O WITH OGONEK AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1EB, 0x304 },
+ uccode=0x1EC,
+ unicodeslot=0x1ED,
+ },
+ {
+ adobename="Ezhcaron",
+ category="lu",
+ description="LATIN CAPITAL LETTER EZH WITH CARON",
+ direction="l",
+ lccode=0x1EF,
+ linebreak="al",
+ shcode=0x1B7,
+ specials={ "char", 0x1B7, 0x30C },
+ unicodeslot=0x1EE,
+ },
+ {
+ adobename="ezhcaron",
+ category="ll",
+ description="LATIN SMALL LETTER EZH WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x292,
+ specials={ "char", 0x292, 0x30C },
+ uccode=0x1EE,
+ unicodeslot=0x1EF,
+ },
+ {
+ adobename="jcaron",
+ category="ll",
+ contextname="jcaron",
+ description="LATIN SMALL LETTER J WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6A,
+ specials={ "char", 0x6A, 0x30C },
+ unicodeslot=0x1F0,
+ },
+ {
+ adobename="DZ",
+ category="lu",
+ contextname="DZligature",
+ description="LATIN CAPITAL LETTER DZ",
+ direction="l",
+ lccode=0x1F3,
+ linebreak="al",
+ specials={ "compat", 0x44, 0x5A },
+ uccode=0x1F2,
+ unicodeslot=0x1F1,
+ },
+ {
+ adobename="Dz",
+ category="lt",
+ contextname="Dzligature",
+ description="LATIN CAPITAL LETTER D WITH SMALL LETTER Z",
+ direction="l",
+ lccode=0x1F3,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "compat", 0x44, 0x7A },
+ uccode=0x1F1,
+ unicodeslot=0x1F2,
+ },
+ {
+ adobename="dz",
+ category="ll",
+ contextname="dzligature",
+ description="LATIN SMALL LETTER DZ",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x64, 0x7A },
+ uccode=0x1F1,
+ unicodeslot=0x1F3,
+ },
+ {
+ adobename="Gacute",
+ category="lu",
+ contextname="Gacute",
+ description="LATIN CAPITAL LETTER G WITH ACUTE",
+ direction="l",
+ lccode=0x1F5,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x301 },
+ unicodeslot=0x1F4,
+ },
+ {
+ adobename="gacute",
+ category="ll",
+ contextname="gacute",
+ description="LATIN SMALL LETTER G WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x301 },
+ uccode=0x1F4,
+ unicodeslot=0x1F5,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER HWAIR",
+ direction="l",
+ lccode=0x195,
+ linebreak="al",
+ unicodeslot=0x1F6,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER WYNN",
+ direction="l",
+ lccode=0x1BF,
+ linebreak="al",
+ unicodeslot=0x1F7,
+ },
+ {
+ category="lu",
+ contextname="Ngrave",
+ description="LATIN CAPITAL LETTER N WITH GRAVE",
+ direction="l",
+ lccode=0x1F9,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x300 },
+ unicodeslot=0x1F8,
+ },
+ {
+ category="ll",
+ contextname="ngrave",
+ description="LATIN SMALL LETTER N WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x300 },
+ uccode=0x1F8,
+ unicodeslot=0x1F9,
+ },
+ {
+ adobename="Aringacute",
+ category="lu",
+ contextname="Aringacute",
+ description="LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE",
+ direction="l",
+ lccode=0x1FB,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC5, 0x301 },
+ unicodeslot=0x1FA,
+ },
+ {
+ adobename="aringacute",
+ category="ll",
+ contextname="aringacute",
+ description="LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE5, 0x301 },
+ uccode=0x1FA,
+ unicodeslot=0x1FB,
+ },
+ {
+ adobename="AEacute",
+ category="lu",
+ contextname="AEacute",
+ description="LATIN CAPITAL LETTER AE WITH ACUTE",
+ direction="l",
+ lccode=0x1FD,
+ linebreak="al",
+ shcode=0xC6,
+ specials={ "char", 0xC6, 0x301 },
+ unicodeslot=0x1FC,
+ },
+ {
+ adobename="aeacute",
+ category="ll",
+ contextname="aeacute",
+ description="LATIN SMALL LETTER AE WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0xE6,
+ specials={ "char", 0xE6, 0x301 },
+ uccode=0x1FC,
+ unicodeslot=0x1FD,
+ },
+ {
+ adobename="Ostrokeacute",
+ category="lu",
+ contextname="Ostrokeacute",
+ description="LATIN CAPITAL LETTER O WITH STROKE AND ACUTE",
+ direction="l",
+ lccode=0x1FF,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD8, 0x301 },
+ unicodeslot=0x1FE,
+ },
+ {
+ adobename="ostrokeacute",
+ category="ll",
+ contextname="ostrokeacute",
+ description="LATIN SMALL LETTER O WITH STROKE AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF8, 0x301 },
+ uccode=0x1FE,
+ unicodeslot=0x1FF,
+ },
+ {
+ adobename="Adblgrave",
+ category="lu",
+ contextname="Adoublegrave",
+ description="LATIN CAPITAL LETTER A WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x201,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x30F },
+ unicodeslot=0x200,
+ },
+ {
+ adobename="adblgrave",
+ category="ll",
+ contextname="adoublegrave",
+ description="LATIN SMALL LETTER A WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x30F },
+ uccode=0x200,
+ unicodeslot=0x201,
+ },
+ {
+ adobename="Ainvertedbreve",
+ category="lu",
+ contextname="Ainvertedbreve",
+ description="LATIN CAPITAL LETTER A WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x203,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x311 },
+ unicodeslot=0x202,
+ },
+ {
+ adobename="ainvertedbreve",
+ category="ll",
+ contextname="ainvertedbreve",
+ description="LATIN SMALL LETTER A WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x311 },
+ uccode=0x202,
+ unicodeslot=0x203,
+ },
+ {
+ adobename="Edblgrave",
+ category="lu",
+ contextname="Edoublegrave",
+ description="LATIN CAPITAL LETTER E WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x205,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x30F },
+ unicodeslot=0x204,
+ },
+ {
+ adobename="edblgrave",
+ category="ll",
+ contextname="edoublegrave",
+ description="LATIN SMALL LETTER E WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x30F },
+ uccode=0x204,
+ unicodeslot=0x205,
+ },
+ {
+ adobename="Einvertedbreve",
+ category="lu",
+ contextname="Einvertedbreve",
+ description="LATIN CAPITAL LETTER E WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x207,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x311 },
+ unicodeslot=0x206,
+ },
+ {
+ adobename="einvertedbreve",
+ category="ll",
+ contextname="einvertedbreve",
+ description="LATIN SMALL LETTER E WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x311 },
+ uccode=0x206,
+ unicodeslot=0x207,
+ },
+ {
+ adobename="Idblgrave",
+ category="lu",
+ contextname="Idoublegrave",
+ description="LATIN CAPITAL LETTER I WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x209,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x30F },
+ unicodeslot=0x208,
+ },
+ {
+ adobename="idblgrave",
+ category="ll",
+ contextname="idoublegrave",
+ description="LATIN SMALL LETTER I WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x30F },
+ uccode=0x208,
+ unicodeslot=0x209,
+ },
+ {
+ adobename="Iinvertedbreve",
+ category="lu",
+ contextname="Iinvertedbreve",
+ description="LATIN CAPITAL LETTER I WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x20B,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x311 },
+ unicodeslot=0x20A,
+ },
+ {
+ adobename="iinvertedbreve",
+ category="ll",
+ contextname="iinvertedbreve",
+ description="LATIN SMALL LETTER I WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x311 },
+ uccode=0x20A,
+ unicodeslot=0x20B,
+ },
+ {
+ adobename="Odblgrave",
+ category="lu",
+ contextname="Odoublegrave",
+ description="LATIN CAPITAL LETTER O WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x20D,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x30F },
+ unicodeslot=0x20C,
+ },
+ {
+ adobename="odblgrave",
+ category="ll",
+ contextname="odoublegrave",
+ description="LATIN SMALL LETTER O WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x30F },
+ uccode=0x20C,
+ unicodeslot=0x20D,
+ },
+ {
+ adobename="Oinvertedbreve",
+ category="lu",
+ contextname="Oinvertedbreve",
+ description="LATIN CAPITAL LETTER O WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x20F,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x311 },
+ unicodeslot=0x20E,
+ },
+ {
+ adobename="oinvertedbreve",
+ category="ll",
+ contextname="oinvertedbreve",
+ description="LATIN SMALL LETTER O WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x311 },
+ uccode=0x20E,
+ unicodeslot=0x20F,
+ },
+ {
+ adobename="Rdblgrave",
+ category="lu",
+ contextname="Rdoublegrave",
+ description="LATIN CAPITAL LETTER R WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x211,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x30F },
+ unicodeslot=0x210,
+ },
+ {
+ adobename="rdblgrave",
+ category="ll",
+ contextname="rdoublegrave",
+ description="LATIN SMALL LETTER R WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x30F },
+ uccode=0x210,
+ unicodeslot=0x211,
+ },
+ {
+ adobename="Rinvertedbreve",
+ category="lu",
+ contextname="Rinvertedbreve",
+ description="LATIN CAPITAL LETTER R WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x213,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x311 },
+ unicodeslot=0x212,
+ },
+ {
+ adobename="rinvertedbreve",
+ category="ll",
+ contextname="rinvertedbreve",
+ description="LATIN SMALL LETTER R WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x311 },
+ uccode=0x212,
+ unicodeslot=0x213,
+ },
+ {
+ adobename="Udblgrave",
+ category="lu",
+ contextname="Udoublegrave",
+ description="LATIN CAPITAL LETTER U WITH DOUBLE GRAVE",
+ direction="l",
+ lccode=0x215,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x30F },
+ unicodeslot=0x214,
+ },
+ {
+ adobename="udblgrave",
+ category="ll",
+ contextname="udoublegrave",
+ description="LATIN SMALL LETTER U WITH DOUBLE GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x30F },
+ uccode=0x214,
+ unicodeslot=0x215,
+ },
+ {
+ adobename="Uinvertedbreve",
+ category="lu",
+ contextname="Uinvertedbreve",
+ description="LATIN CAPITAL LETTER U WITH INVERTED BREVE",
+ direction="l",
+ lccode=0x217,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x311 },
+ unicodeslot=0x216,
+ },
+ {
+ adobename="uinvertedbreve",
+ category="ll",
+ contextname="uinvertedbreve",
+ description="LATIN SMALL LETTER U WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x311 },
+ uccode=0x216,
+ unicodeslot=0x217,
+ },
+ {
+ adobename="Scommaaccent",
+ category="lu",
+ contextname="Scommaaccent",
+ description="LATIN CAPITAL LETTER S WITH COMMA BELOW",
+ direction="l",
+ lccode=0x219,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x326 },
+ unicodeslot=0x218,
+ },
+ {
+ adobename="scommaaccent",
+ category="ll",
+ contextname="scommaaccent",
+ description="LATIN SMALL LETTER S WITH COMMA BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x326 },
+ uccode=0x218,
+ unicodeslot=0x219,
+ },
+ {
+ category="lu",
+ contextname="Tcommaaccent",
+ description="LATIN CAPITAL LETTER T WITH COMMA BELOW",
+ direction="l",
+ lccode=0x21B,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x326 },
+ unicodeslot=0x21A,
+ },
+ {
+ category="ll",
+ contextname="tcommaaccent",
+ description="LATIN SMALL LETTER T WITH COMMA BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x326 },
+ uccode=0x21A,
+ unicodeslot=0x21B,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER YOGH",
+ direction="l",
+ lccode=0x21D,
+ linebreak="al",
+ unicodeslot=0x21C,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER YOGH",
+ direction="l",
+ linebreak="al",
+ uccode=0x21C,
+ unicodeslot=0x21D,
+ },
+ {
+ category="lu",
+ contextname="Hcaron",
+ description="LATIN CAPITAL LETTER H WITH CARON",
+ direction="l",
+ lccode=0x21F,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x30C },
+ unicodeslot=0x21E,
+ },
+ {
+ category="ll",
+ contextname="hcaron",
+ description="LATIN SMALL LETTER H WITH CARON",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x30C },
+ uccode=0x21E,
+ unicodeslot=0x21F,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH LONG RIGHT LEG",
+ direction="l",
+ lccode=0x19E,
+ linebreak="al",
+ shcode=0x4E,
+ unicodeslot=0x220,
+ },
+ {
+ category="ll",
+ contextname="dcurl",
+ description="LATIN SMALL LETTER D WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ unicodeslot=0x221,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER OU",
+ direction="l",
+ lccode=0x223,
+ linebreak="al",
+ unicodeslot=0x222,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER OU",
+ direction="l",
+ linebreak="al",
+ uccode=0x222,
+ unicodeslot=0x223,
+ },
+ {
+ category="lu",
+ contextname="Zhook",
+ description="LATIN CAPITAL LETTER Z WITH HOOK",
+ direction="l",
+ lccode=0x225,
+ linebreak="al",
+ shcode=0x5A,
+ unicodeslot=0x224,
+ },
+ {
+ category="ll",
+ contextname="zhook",
+ description="LATIN SMALL LETTER Z WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ uccode=0x224,
+ unicodeslot=0x225,
+ },
+ {
+ category="lu",
+ contextname="Adotaccent",
+ description="LATIN CAPITAL LETTER A WITH DOT ABOVE",
+ direction="l",
+ lccode=0x227,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x307 },
+ unicodeslot=0x226,
+ },
+ {
+ category="ll",
+ contextname="adotaccent",
+ description="LATIN SMALL LETTER A WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x307 },
+ uccode=0x226,
+ unicodeslot=0x227,
+ },
+ {
+ category="lu",
+ contextname="Ecedilla",
+ description="LATIN CAPITAL LETTER E WITH CEDILLA",
+ direction="l",
+ lccode=0x229,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x327 },
+ unicodeslot=0x228,
+ },
+ {
+ category="ll",
+ contextname="ecedilla",
+ description="LATIN SMALL LETTER E WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x327 },
+ uccode=0x228,
+ unicodeslot=0x229,
+ },
+ {
+ category="lu",
+ contextname="Odiaeresismacron",
+ description="LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON",
+ direction="l",
+ lccode=0x22B,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD6, 0x304 },
+ unicodeslot=0x22A,
+ },
+ {
+ category="ll",
+ contextname="odiaeresismacron",
+ description="LATIN SMALL LETTER O WITH DIAERESIS AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF6, 0x304 },
+ uccode=0x22A,
+ unicodeslot=0x22B,
+ },
+ {
+ category="lu",
+ contextname="Otildemacron",
+ description="LATIN CAPITAL LETTER O WITH TILDE AND MACRON",
+ direction="l",
+ lccode=0x22D,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD5, 0x304 },
+ unicodeslot=0x22C,
+ },
+ {
+ category="ll",
+ contextname="otildemacron",
+ description="LATIN SMALL LETTER O WITH TILDE AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF5, 0x304 },
+ uccode=0x22C,
+ unicodeslot=0x22D,
+ },
+ {
+ category="lu",
+ contextname="Odotaccent",
+ description="LATIN CAPITAL LETTER O WITH DOT ABOVE",
+ direction="l",
+ lccode=0x22F,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x307 },
+ unicodeslot=0x22E,
+ },
+ {
+ category="ll",
+ contextname="odotaccent",
+ description="LATIN SMALL LETTER O WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x307 },
+ uccode=0x22E,
+ unicodeslot=0x22F,
+ },
+ {
+ category="lu",
+ contextname="Odotaccentmacron",
+ description="LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON",
+ direction="l",
+ lccode=0x231,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x22E, 0x304 },
+ unicodeslot=0x230,
+ },
+ {
+ category="ll",
+ contextname="odotaccentmacron",
+ description="LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x22F, 0x304 },
+ uccode=0x230,
+ unicodeslot=0x231,
+ },
+ {
+ category="lu",
+ contextname="Ymacron",
+ description="LATIN CAPITAL LETTER Y WITH MACRON",
+ direction="l",
+ lccode=0x233,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x304 },
+ unicodeslot=0x232,
+ },
+ {
+ category="ll",
+ contextname="ymacron",
+ description="LATIN SMALL LETTER Y WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x304 },
+ uccode=0x232,
+ unicodeslot=0x233,
+ },
+ {
+ category="ll",
+ contextname="lcurl",
+ description="LATIN SMALL LETTER L WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ unicodeslot=0x234,
+ },
+ {
+ category="ll",
+ contextname="ncurl",
+ description="LATIN SMALL LETTER N WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ unicodeslot=0x235,
+ },
+ {
+ category="ll",
+ contextname="tcurl",
+ description="LATIN SMALL LETTER T WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ unicodeslot=0x236,
+ },
+ {
+ category="ll",
+ contextname="dotlessj",
+ description="LATIN SMALL LETTER DOTLESS J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x237,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER DB DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x238,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER QP DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x239,
+ },
+ {
+ category="lu",
+ contextname="Astroke",
+ description="LATIN CAPITAL LETTER A WITH STROKE",
+ direction="l",
+ lccode=0x2C65,
+ linebreak="al",
+ shcode=0x41,
+ unicodeslot=0x23A,
+ },
+ {
+ category="lu",
+ contextname="Cstroke",
+ description="LATIN CAPITAL LETTER C WITH STROKE",
+ direction="l",
+ lccode=0x23C,
+ linebreak="al",
+ shcode=0x43,
+ unicodeslot=0x23B,
+ },
+ {
+ category="ll",
+ contextname="cstroke",
+ description="LATIN SMALL LETTER C WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ uccode=0x23B,
+ unicodeslot=0x23C,
+ },
+ {
+ category="lu",
+ contextname="Lbar",
+ description="LATIN CAPITAL LETTER L WITH BAR",
+ direction="l",
+ lccode=0x19A,
+ linebreak="al",
+ shcode=0x4C,
+ unicodeslot=0x23D,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH DIAGONAL STROKE",
+ direction="l",
+ lccode=0x2C66,
+ linebreak="al",
+ shcode=0x54,
+ unicodeslot=0x23E,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER S WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ unicodeslot=0x23F,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ unicodeslot=0x240,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER GLOTTAL STOP",
+ direction="l",
+ lccode=0x242,
+ linebreak="al",
+ unicodeslot=0x241,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ uccode=0x241,
+ unicodeslot=0x242,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH STROKE",
+ direction="l",
+ lccode=0x180,
+ linebreak="al",
+ shcode=0x42,
+ unicodeslot=0x243,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER U BAR",
+ direction="l",
+ lccode=0x289,
+ linebreak="al",
+ unicodeslot=0x244,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED V",
+ direction="l",
+ lccode=0x28C,
+ linebreak="al",
+ unicodeslot=0x245,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH STROKE",
+ direction="l",
+ lccode=0x247,
+ linebreak="al",
+ shcode=0x45,
+ unicodeslot=0x246,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER E WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ uccode=0x246,
+ unicodeslot=0x247,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER J WITH STROKE",
+ direction="l",
+ lccode=0x249,
+ linebreak="al",
+ shcode=0x4A,
+ unicodeslot=0x248,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER J WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6A,
+ uccode=0x248,
+ unicodeslot=0x249,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL",
+ direction="l",
+ lccode=0x24B,
+ linebreak="al",
+ unicodeslot=0x24A,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH HOOK TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x71,
+ uccode=0x24A,
+ unicodeslot=0x24B,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH STROKE",
+ direction="l",
+ lccode=0x24D,
+ linebreak="al",
+ shcode=0x52,
+ unicodeslot=0x24C,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER R WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ uccode=0x24C,
+ unicodeslot=0x24D,
+ },
+ {
+ category="lu",
+ description="LATIN CAPITAL LETTER Y WITH STROKE",
+ direction="l",
+ lccode=0x24F,
+ linebreak="al",
+ shcode=0x59,
+ unicodeslot=0x24E,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ uccode=0x24E,
+ unicodeslot=0x24F,
+ },
+ {
+ adobename="aturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x250,
+ },
+ {
+ adobename="ascript",
+ category="ll",
+ cjkwd="a",
+ description="LATIN SMALL LETTER ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x251,
+ },
+ {
+ adobename="ascriptturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x252,
+ },
+ {
+ adobename="bhook",
+ category="ll",
+ contextname="bhook",
+ description="LATIN SMALL LETTER B WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ uccode=0x181,
+ unicodeslot=0x253,
+ },
+ {
+ adobename="oopen",
+ category="ll",
+ description="LATIN SMALL LETTER OPEN O",
+ direction="l",
+ linebreak="al",
+ uccode=0x186,
+ unicodeslot=0x254,
+ },
+ {
+ adobename="ccurl",
+ category="ll",
+ contextname="ccurl",
+ description="LATIN SMALL LETTER C WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ unicodeslot=0x255,
+ },
+ {
+ adobename="dtail",
+ category="ll",
+ contextname="dtail",
+ description="LATIN SMALL LETTER D WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ uccode=0x189,
+ unicodeslot=0x256,
+ },
+ {
+ adobename="dhook",
+ category="ll",
+ contextname="dhook",
+ description="LATIN SMALL LETTER D WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ uccode=0x18A,
+ unicodeslot=0x257,
+ },
+ {
+ adobename="ereversed",
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x258,
+ },
+ {
+ adobename="schwa",
+ category="ll",
+ contextname="schwa",
+ description="LATIN SMALL LETTER SCHWA",
+ direction="l",
+ linebreak="al",
+ uccode=0x18F,
+ unicodeslot=0x259,
+ },
+ {
+ adobename="schwahook",
+ category="ll",
+ contextname="schwahook",
+ description="LATIN SMALL LETTER SCHWA WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x259,
+ unicodeslot=0x25A,
+ },
+ {
+ adobename="eopen",
+ category="ll",
+ description="LATIN SMALL LETTER OPEN E",
+ direction="l",
+ linebreak="al",
+ uccode=0x190,
+ unicodeslot=0x25B,
+ },
+ {
+ adobename="eopenreversed",
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED OPEN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x25C,
+ },
+ {
+ adobename="eopenreversedhook",
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED OPEN E WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x25D,
+ },
+ {
+ adobename="eopenreversedclosed",
+ category="ll",
+ description="LATIN SMALL LETTER CLOSED REVERSED OPEN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x25E,
+ },
+ {
+ adobename="jdotlessstroke",
+ category="ll",
+ contextname="dotlessjstroke",
+ description="LATIN SMALL LETTER DOTLESS J WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x25F,
+ },
+ {
+ adobename="ghook",
+ category="ll",
+ description="LATIN SMALL LETTER G WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ uccode=0x193,
+ unicodeslot=0x260,
+ },
+ {
+ adobename="gscript",
+ category="ll",
+ cjkwd="a",
+ description="LATIN SMALL LETTER SCRIPT G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x261,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x262,
+ },
+ {
+ adobename="gammalatinsmall",
+ category="ll",
+ description="LATIN SMALL LETTER GAMMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x194,
+ unicodeslot=0x263,
+ },
+ {
+ adobename="ramshorn",
+ category="ll",
+ description="LATIN SMALL LETTER RAMS HORN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x264,
+ },
+ {
+ adobename="hturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x265,
+ },
+ {
+ adobename="hhook",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ unicodeslot=0x266,
+ },
+ {
+ adobename="henghook",
+ category="ll",
+ description="LATIN SMALL LETTER HENG WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x267,
+ },
+ {
+ adobename="istroke",
+ category="ll",
+ description="LATIN SMALL LETTER I WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ uccode=0x197,
+ unicodeslot=0x268,
+ },
+ {
+ adobename="iotalatin",
+ category="ll",
+ description="LATIN SMALL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ uccode=0x196,
+ unicodeslot=0x269,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x26A,
+ },
+ {
+ adobename="lmiddletilde",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ uccode=0x2C62,
+ unicodeslot=0x26B,
+ },
+ {
+ adobename="lbelt",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH BELT",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ unicodeslot=0x26C,
+ },
+ {
+ adobename="lhookretroflex",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ unicodeslot=0x26D,
+ },
+ {
+ adobename="lezh",
+ category="ll",
+ description="LATIN SMALL LETTER LEZH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x26E,
+ },
+ {
+ adobename="mturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED M",
+ direction="l",
+ linebreak="al",
+ uccode=0x19C,
+ unicodeslot=0x26F,
+ },
+ {
+ adobename="mlonglegturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED M WITH LONG LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x270,
+ },
+ {
+ adobename="mhook",
+ category="ll",
+ description="LATIN SMALL LETTER M WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ unicodeslot=0x271,
+ },
+ {
+ adobename="nhookleft",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ uccode=0x19D,
+ unicodeslot=0x272,
+ },
+ {
+ adobename="nhookretroflex",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ unicodeslot=0x273,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x274,
+ },
+ {
+ adobename="obarred",
+ category="ll",
+ description="LATIN SMALL LETTER BARRED O",
+ direction="l",
+ linebreak="al",
+ uccode=0x19F,
+ unicodeslot=0x275,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x276,
+ },
+ {
+ adobename="omegalatinclosed",
+ category="ll",
+ description="LATIN SMALL LETTER CLOSED OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x277,
+ },
+ {
+ adobename="philatin",
+ category="ll",
+ description="LATIN SMALL LETTER PHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x278,
+ },
+ {
+ adobename="rturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x279,
+ },
+ {
+ adobename="rlonglegturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED R WITH LONG LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x27A,
+ },
+ {
+ adobename="rhookturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED R WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x27B,
+ },
+ {
+ adobename="rlongleg",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH LONG LEG",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ unicodeslot=0x27C,
+ },
+ {
+ adobename="rhook",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ uccode=0x2C64,
+ unicodeslot=0x27D,
+ },
+ {
+ adobename="rfishhook",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH FISHHOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ unicodeslot=0x27E,
+ },
+ {
+ adobename="rfishhookreversed",
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED R WITH FISHHOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x27F,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL R",
+ direction="l",
+ linebreak="al",
+ uccode=0x1A6,
+ unicodeslot=0x280,
+ },
+ {
+ adobename="Rsmallinverted",
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL INVERTED R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281,
+ },
+ {
+ adobename="shook",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ unicodeslot=0x282,
+ },
+ {
+ adobename="esh",
+ category="ll",
+ description="LATIN SMALL LETTER ESH",
+ direction="l",
+ linebreak="al",
+ uccode=0x1A9,
+ unicodeslot=0x283,
+ },
+ {
+ adobename="dotlessjstrokehook",
+ category="ll",
+ description="LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284,
+ },
+ {
+ adobename="eshsquatreversed",
+ category="ll",
+ description="LATIN SMALL LETTER SQUAT REVERSED ESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285,
+ },
+ {
+ adobename="eshcurl",
+ category="ll",
+ description="LATIN SMALL LETTER ESH WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x283,
+ unicodeslot=0x286,
+ },
+ {
+ adobename="tturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287,
+ },
+ {
+ adobename="tretroflexhook",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ uccode=0x1AE,
+ unicodeslot=0x288,
+ },
+ {
+ adobename="ubar",
+ category="ll",
+ description="LATIN SMALL LETTER U BAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x244,
+ unicodeslot=0x289,
+ },
+ {
+ adobename="upsilonlatin",
+ category="ll",
+ description="LATIN SMALL LETTER UPSILON",
+ direction="l",
+ linebreak="al",
+ uccode=0x1B1,
+ unicodeslot=0x28A,
+ },
+ {
+ adobename="vhook",
+ category="ll",
+ description="LATIN SMALL LETTER V WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x76,
+ uccode=0x1B2,
+ unicodeslot=0x28B,
+ },
+ {
+ adobename="vturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED V",
+ direction="l",
+ linebreak="al",
+ uccode=0x245,
+ unicodeslot=0x28C,
+ },
+ {
+ adobename="wturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D,
+ },
+ {
+ adobename="yturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F,
+ },
+ {
+ adobename="zretroflexhook",
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ unicodeslot=0x290,
+ },
+ {
+ adobename="zcurl",
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ unicodeslot=0x291,
+ },
+ {
+ adobename="ezh",
+ category="ll",
+ description="LATIN SMALL LETTER EZH",
+ direction="l",
+ linebreak="al",
+ uccode=0x1B7,
+ unicodeslot=0x292,
+ },
+ {
+ adobename="ezhcurl",
+ category="ll",
+ description="LATIN SMALL LETTER EZH WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x292,
+ unicodeslot=0x293,
+ },
+ {
+ adobename="glottalstop",
+ category="lo",
+ description="LATIN LETTER GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x294,
+ },
+ {
+ adobename="glottalstopreversed",
+ category="ll",
+ description="LATIN LETTER PHARYNGEAL VOICED FRICATIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x295,
+ },
+ {
+ adobename="glottalstopinverted",
+ category="ll",
+ description="LATIN LETTER INVERTED GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x296,
+ },
+ {
+ adobename="cstretched",
+ category="ll",
+ description="LATIN LETTER STRETCHED C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x297,
+ },
+ {
+ adobename="bilabialclick",
+ category="ll",
+ description="LATIN LETTER BILABIAL CLICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x298,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x299,
+ },
+ {
+ adobename="eopenclosed",
+ category="ll",
+ description="LATIN SMALL LETTER CLOSED OPEN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x29A,
+ },
+ {
+ adobename="Gsmallhook",
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL G WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x29B,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x29C,
+ },
+ {
+ adobename="jcrossedtail",
+ category="ll",
+ description="LATIN SMALL LETTER J WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x6A,
+ unicodeslot=0x29D,
+ },
+ {
+ adobename="kturned",
+ category="ll",
+ description="LATIN SMALL LETTER TURNED K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x29E,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x29F,
+ },
+ {
+ adobename="qhook",
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x71,
+ unicodeslot=0x2A0,
+ },
+ {
+ adobename="glottalstopstroke",
+ category="ll",
+ description="LATIN LETTER GLOTTAL STOP WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A1,
+ },
+ {
+ adobename="glottalstopstrokereversed",
+ category="ll",
+ description="LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A2,
+ },
+ {
+ adobename="dzaltone",
+ category="ll",
+ description="LATIN SMALL LETTER DZ DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A3,
+ },
+ {
+ adobename="dezh",
+ category="ll",
+ description="LATIN SMALL LETTER DEZH DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A4,
+ },
+ {
+ adobename="dzcurl",
+ category="ll",
+ description="LATIN SMALL LETTER DZ DIGRAPH WITH CURL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A5,
+ },
+ {
+ adobename="ts",
+ category="ll",
+ description="LATIN SMALL LETTER TS DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A6,
+ },
+ {
+ adobename="tesh",
+ category="ll",
+ description="LATIN SMALL LETTER TESH DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A7,
+ },
+ {
+ adobename="tccurl",
+ category="ll",
+ description="LATIN SMALL LETTER TC DIGRAPH WITH CURL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A8,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER FENG DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2A9,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER LS DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AA,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER LZ DIGRAPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AB,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER BILABIAL PERCUSSIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AC,
+ },
+ {
+ category="ll",
+ description="LATIN LETTER BIDENTAL PERCUSSIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AD,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER TURNED H WITH FISHHOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AE,
+ },
+ {
+ category="ll",
+ description="LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2AF,
+ },
+ {
+ adobename="hsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x68 },
+ unicodeslot=0x2B0,
+ },
+ {
+ adobename="hhooksuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL H WITH HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x266 },
+ unicodeslot=0x2B1,
+ },
+ {
+ adobename="jsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x6A },
+ unicodeslot=0x2B2,
+ },
+ {
+ category="lm",
+ description="MODIFIER LETTER SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x72 },
+ unicodeslot=0x2B3,
+ },
+ {
+ adobename="rturnedsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED R",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x279 },
+ unicodeslot=0x2B4,
+ },
+ {
+ adobename="rhookturnedsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED R WITH HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x27B },
+ unicodeslot=0x2B5,
+ },
+ {
+ adobename="Rsmallinvertedsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL INVERTED R",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x281 },
+ unicodeslot=0x2B6,
+ },
+ {
+ adobename="wsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x77 },
+ unicodeslot=0x2B7,
+ },
+ {
+ adobename="ysuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x79 },
+ unicodeslot=0x2B8,
+ },
+ {
+ adobename="primemod",
+ category="lm",
+ description="MODIFIER LETTER PRIME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9,
+ },
+ {
+ adobename="dblprimemod",
+ category="lm",
+ description="MODIFIER LETTER DOUBLE PRIME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA,
+ },
+ {
+ adobename="commaturnedmod",
+ category="lm",
+ description="MODIFIER LETTER TURNED COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2BB,
+ },
+ {
+ adobename="apostrophemod",
+ category="lm",
+ description="MODIFIER LETTER APOSTROPHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2BC,
+ },
+ {
+ adobename="commareversedmod",
+ category="lm",
+ description="MODIFIER LETTER REVERSED COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2BD,
+ },
+ {
+ adobename="ringhalfright",
+ category="lm",
+ description="MODIFIER LETTER RIGHT HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2BE,
+ },
+ {
+ adobename="ringhalfleft",
+ category="lm",
+ description="MODIFIER LETTER LEFT HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2BF,
+ },
+ {
+ adobename="glottalstopmod",
+ category="lm",
+ description="MODIFIER LETTER GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C0,
+ },
+ {
+ adobename="glottalstopreversedmod",
+ category="lm",
+ description="MODIFIER LETTER REVERSED GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C1,
+ },
+ {
+ adobename="arrowheadleftmod",
+ category="sk",
+ description="MODIFIER LETTER LEFT ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2C2,
+ },
+ {
+ adobename="arrowheadrightmod",
+ category="sk",
+ description="MODIFIER LETTER RIGHT ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2C3,
+ },
+ {
+ adobename="arrowheadupmod",
+ category="sk",
+ cjkwd="a",
+ description="MODIFIER LETTER UP ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2C4,
+ },
+ {
+ adobename="arrowheaddownmod",
+ category="sk",
+ description="MODIFIER LETTER DOWN ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2C5,
+ },
+ {
+ adobename="circumflex",
+ category="lm",
+ comment="check special",
+ contextname="textcircumflex",
+ description="MODIFIER LETTER CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathname="hat",
+ specials={ "compat", 0x20, 0x302 },
+ unicodeslot=0x2C6,
+ },
+ {
+ adobename="caron",
+ category="lm",
+ cjkwd="a",
+ comment="check special",
+ contextname="textcaron",
+ description="CARON",
+ direction="on",
+ linebreak="ai",
+ mathclass="topaccent",
+ mathname="check",
+ specials={ "compat", 0x20, 0x30C },
+ unicodeslot=0x2C7,
+ },
+ {
+ adobename="verticallinemod",
+ category="lm",
+ description="MODIFIER LETTER VERTICAL LINE",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0x2C8,
+ },
+ {
+ adobename="firsttonechinese",
+ category="lm",
+ cjkwd="a",
+ description="MODIFIER LETTER MACRON",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2C9,
+ },
+ {
+ adobename="secondtonechinese",
+ category="lm",
+ cjkwd="a",
+ description="MODIFIER LETTER ACUTE ACCENT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2CA,
+ },
+ {
+ adobename="fourthtonechinese",
+ category="lm",
+ cjkwd="a",
+ description="MODIFIER LETTER GRAVE ACCENT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2CB,
+ },
+ {
+ adobename="verticallinelowmod",
+ category="lm",
+ description="MODIFIER LETTER LOW VERTICAL LINE",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0x2CC,
+ },
+ {
+ adobename="macronlowmod",
+ category="lm",
+ cjkwd="a",
+ description="MODIFIER LETTER LOW MACRON",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2CD,
+ },
+ {
+ adobename="gravelowmod",
+ category="lm",
+ description="MODIFIER LETTER LOW GRAVE ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE,
+ },
+ {
+ adobename="acutelowmod",
+ category="lm",
+ description="MODIFIER LETTER LOW ACUTE ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CF,
+ },
+ {
+ adobename="colontriangularmod",
+ category="lm",
+ cjkwd="a",
+ description="MODIFIER LETTER TRIANGULAR COLON",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x2D0,
+ },
+ {
+ adobename="colontriangularhalfmod",
+ category="lm",
+ description="MODIFIER LETTER HALF TRIANGULAR COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D1,
+ },
+ {
+ adobename="ringhalfrightcentered",
+ category="sk",
+ description="MODIFIER LETTER CENTRED RIGHT HALF RING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D2,
+ },
+ {
+ adobename="ringhalfleftcentered",
+ category="sk",
+ description="MODIFIER LETTER CENTRED LEFT HALF RING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D3,
+ },
+ {
+ adobename="uptackmod",
+ category="sk",
+ description="MODIFIER LETTER UP TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D4,
+ },
+ {
+ adobename="downtackmod",
+ category="sk",
+ description="MODIFIER LETTER DOWN TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D5,
+ },
+ {
+ adobename="plusmod",
+ category="sk",
+ description="MODIFIER LETTER PLUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D6,
+ },
+ {
+ adobename="minusmod",
+ category="sk",
+ description="MODIFIER LETTER MINUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2D7,
+ },
+ {
+ adobename="breve",
+ category="sk",
+ cjkwd="a",
+ contextname="textbreve",
+ description="BREVE",
+ direction="on",
+ linebreak="ai",
+ mathclass="topaccent",
+ mathname="breve",
+ specials={ "compat", 0x20, 0x306 },
+ unicodeslot=0x2D8,
+ },
+ {
+ adobename="dotaccent",
+ category="sk",
+ cjkwd="a",
+ contextname="textdotaccent",
+ description="DOT ABOVE",
+ direction="on",
+ linebreak="ai",
+ mathclass="topaccent",
+ mathname="dot",
+ specials={ "compat", 0x20, 0x307 },
+ unicodeslot=0x2D9,
+ },
+ {
+ adobename="ring",
+ category="sk",
+ cjkwd="a",
+ contextname="textring",
+ description="RING ABOVE",
+ direction="on",
+ linebreak="ai",
+ mathclass="topaccent",
+ mathname="mathring",
+ specials={ "compat", 0x20, 0x30A },
+ unicodeslot=0x2DA,
+ },
+ {
+ adobename="ogonek",
+ category="sk",
+ cjkwd="a",
+ contextname="textogonek",
+ description="OGONEK",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x20, 0x328 },
+ unicodeslot=0x2DB,
+ },
+ {
+ adobename="tilde",
+ category="sk",
+ contextname="texttilde",
+ description="SMALL TILDE",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathname="tilde",
+ specials={ "compat", 0x20, 0x303 },
+ unicodeslot=0x2DC,
+ },
+ {
+ adobename="hungarumlaut",
+ category="sk",
+ cjkwd="a",
+ contextname="texthungarumlaut",
+ description="DOUBLE ACUTE ACCENT",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x20, 0x30B },
+ unicodeslot=0x2DD,
+ },
+ {
+ adobename="rhotichookmod",
+ category="sk",
+ description="MODIFIER LETTER RHOTIC HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2DE,
+ },
+ {
+ category="sk",
+ cjkwd="a",
+ description="MODIFIER LETTER CROSS ACCENT",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0x2DF,
+ },
+ {
+ adobename="gammasuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x263 },
+ unicodeslot=0x2E0,
+ },
+ {
+ category="lm",
+ description="MODIFIER LETTER SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x6C },
+ unicodeslot=0x2E1,
+ },
+ {
+ category="lm",
+ description="MODIFIER LETTER SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x73 },
+ unicodeslot=0x2E2,
+ },
+ {
+ adobename="xsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x78 },
+ unicodeslot=0x2E3,
+ },
+ {
+ adobename="glottalstopreversedsuperior",
+ category="lm",
+ description="MODIFIER LETTER SMALL REVERSED GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x295 },
+ unicodeslot=0x2E4,
+ },
+ {
+ adobename="tonebarextrahighmod",
+ category="sk",
+ description="MODIFIER LETTER EXTRA-HIGH TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E5,
+ },
+ {
+ adobename="tonebarhighmod",
+ category="sk",
+ description="MODIFIER LETTER HIGH TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E6,
+ },
+ {
+ adobename="tonebarmidmod",
+ category="sk",
+ description="MODIFIER LETTER MID TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E7,
+ },
+ {
+ adobename="tonebarlowmod",
+ category="sk",
+ description="MODIFIER LETTER LOW TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E8,
+ },
+ {
+ adobename="tonebarextralowmod",
+ category="sk",
+ description="MODIFIER LETTER EXTRA-LOW TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E9,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER YIN DEPARTING TONE MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2EA,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER YANG DEPARTING TONE MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2EB,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER VOICING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2EC,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER UNASPIRATED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ED,
+ },
+ {
+ category="lm",
+ description="MODIFIER LETTER DOUBLE APOSTROPHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2EE,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW DOWN ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2EF,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW UP ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F0,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW LEFT ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F1,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW RIGHT ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F2,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW RING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F3,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER MIDDLE GRAVE ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F4,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F5,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F6,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW TILDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F7,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER RAISED COLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F8,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER BEGIN HIGH TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2F9,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER END HIGH TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FA,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER BEGIN LOW TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FB,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER END LOW TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FC,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER SHELF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FD,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER OPEN SHELF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FE,
+ },
+ {
+ category="sk",
+ description="MODIFIER LETTER LOW LEFT ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2FF,
+ },
+ {
+ adobename="gravecomb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING GRAVE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x300,
+ },
+ {
+ adobename="acutecomb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING ACUTE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x301,
+ },
+ {
+ adobename="circumflexcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING CIRCUMFLEX ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ mathname="widehat",
+ mathstretch="h",
+ unicodeslot=0x302,
+ },
+ {
+ adobename="tildecomb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING TILDE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ mathname="widetilde",
+ mathstretch="h",
+ unicodeslot=0x303,
+ },
+ {
+ adobename="macroncmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x304,
+ },
+ {
+ adobename="overlinecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING OVERLINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x305,
+ },
+ {
+ adobename="brevecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING BREVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x306,
+ },
+ {
+ adobename="dotaccentcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x307,
+ },
+ {
+ adobename="dieresiscmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DIAERESIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x308,
+ },
+ {
+ adobename="hookcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING HOOK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x309,
+ },
+ {
+ adobename="ringcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING RING ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30A,
+ },
+ {
+ adobename="hungarumlautcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DOUBLE ACUTE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30B,
+ },
+ {
+ adobename="caroncmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING CARON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30C,
+ },
+ {
+ adobename="verticallineabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING VERTICAL LINE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30D,
+ },
+ {
+ adobename="dblverticallineabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DOUBLE VERTICAL LINE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30E,
+ },
+ {
+ adobename="dblgravecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DOUBLE GRAVE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x30F,
+ },
+ {
+ adobename="candrabinducmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x310,
+ },
+ {
+ adobename="breveinvertedcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING INVERTED BREVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x311,
+ },
+ {
+ adobename="commaturnedabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING TURNED COMMA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x312,
+ },
+ {
+ adobename="commaabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING COMMA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x313,
+ },
+ {
+ adobename="commareversedabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING REVERSED COMMA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x314,
+ },
+ {
+ adobename="commaaboverightcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE8,
+ description="COMBINING COMMA ABOVE RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x315,
+ },
+ {
+ adobename="gravebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING GRAVE ACCENT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x316,
+ },
+ {
+ adobename="acutebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING ACUTE ACCENT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x317,
+ },
+ {
+ adobename="lefttackbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LEFT TACK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x318,
+ },
+ {
+ adobename="righttackbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING RIGHT TACK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x319,
+ },
+ {
+ adobename="leftangleabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE8,
+ description="COMBINING LEFT ANGLE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31A,
+ },
+ {
+ adobename="horncmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xD8,
+ description="COMBINING HORN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31B,
+ },
+ {
+ adobename="ringhalfleftbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LEFT HALF RING BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31C,
+ },
+ {
+ adobename="uptackbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING UP TACK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31D,
+ },
+ {
+ adobename="downtackbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING DOWN TACK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31E,
+ },
+ {
+ adobename="plusbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING PLUS SIGN BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x31F,
+ },
+ {
+ adobename="minusbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING MINUS SIGN BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x320,
+ },
+ {
+ adobename="hookpalatalizedbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xCA,
+ description="COMBINING PALATALIZED HOOK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x321,
+ },
+ {
+ adobename="hookretroflexbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xCA,
+ description="COMBINING RETROFLEX HOOK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x322,
+ },
+ {
+ adobename="dotbelowcomb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ contextname="textbottomdot",
+ description="COMBINING DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x323,
+ },
+ {
+ adobename="dieresisbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING DIAERESIS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x324,
+ },
+ {
+ adobename="ringbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING RING BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x325,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ contextname="textbottomcomma",
+ description="COMBINING COMMA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x326,
+ },
+ {
+ adobename="cedillacmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xCA,
+ description="COMBINING CEDILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x327,
+ },
+ {
+ adobename="ogonekcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xCA,
+ description="COMBINING OGONEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x328,
+ },
+ {
+ adobename="verticallinebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING VERTICAL LINE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x329,
+ },
+ {
+ adobename="bridgebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING BRIDGE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32A,
+ },
+ {
+ adobename="dblarchinvertedbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING INVERTED DOUBLE ARCH BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32B,
+ },
+ {
+ adobename="caronbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING CARON BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32C,
+ },
+ {
+ adobename="circumflexbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING CIRCUMFLEX ACCENT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32D,
+ },
+ {
+ adobename="brevebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING BREVE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32E,
+ },
+ {
+ adobename="breveinvertedbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING INVERTED BREVE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x32F,
+ },
+ {
+ adobename="tildebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING TILDE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x330,
+ },
+ {
+ adobename="macronbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING MACRON BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x331,
+ },
+ {
+ adobename="lowlinecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LOW LINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x332,
+ },
+ {
+ adobename="dbllowlinecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING DOUBLE LOW LINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x333,
+ },
+ {
+ adobename="tildeoverlaycmb",
+ category="mn",
+ cjkwd="a",
+ combining=0x1,
+ description="COMBINING TILDE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x334,
+ },
+ {
+ adobename="strokeshortoverlaycmb",
+ category="mn",
+ cjkwd="a",
+ combining=0x1,
+ description="COMBINING SHORT STROKE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x335,
+ },
+ {
+ adobename="strokelongoverlaycmb",
+ category="mn",
+ cjkwd="a",
+ combining=0x1,
+ description="COMBINING LONG STROKE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x336,
+ },
+ {
+ adobename="solidusshortoverlaycmb",
+ category="mn",
+ cjkwd="a",
+ combining=0x1,
+ description="COMBINING SHORT SOLIDUS OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x337,
+ },
+ {
+ adobename="soliduslongoverlaycmb",
+ category="mn",
+ cjkwd="a",
+ combining=0x1,
+ description="COMBINING LONG SOLIDUS OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="relation",
+ mathname="not",
+ unicodeslot=0x338,
+ },
+ {
+ adobename="ringhalfrightbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING RIGHT HALF RING BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x339,
+ },
+ {
+ adobename="bridgeinvertedbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING INVERTED BRIDGE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33A,
+ },
+ {
+ adobename="squarebelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING SQUARE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33B,
+ },
+ {
+ adobename="seagullbelowcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING SEAGULL BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33C,
+ },
+ {
+ adobename="xabovecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING X ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33D,
+ },
+ {
+ adobename="tildeverticalcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING VERTICAL TILDE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33E,
+ },
+ {
+ adobename="dbloverlinecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING DOUBLE OVERLINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x33F,
+ },
+ {
+ adobename="gravetonecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING GRAVE TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x300 },
+ unicodeslot=0x340,
+ },
+ {
+ adobename="acutetonecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING ACUTE TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x301 },
+ unicodeslot=0x341,
+ },
+ {
+ adobename="perispomenigreekcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING GREEK PERISPOMENI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x342,
+ },
+ {
+ adobename="koroniscmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING GREEK KORONIS",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x313 },
+ unicodeslot=0x343,
+ },
+ {
+ adobename="dialytikatonoscmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING GREEK DIALYTIKA TONOS",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x308, 0x301 },
+ unicodeslot=0x344,
+ },
+ {
+ adobename="ypogegrammenigreekcmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xF0,
+ description="COMBINING GREEK YPOGEGRAMMENI",
+ direction="nsm",
+ linebreak="cm",
+ uccode=0x399,
+ unicodeslot=0x345,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING BRIDGE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x346,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING EQUALS SIGN BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x347,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING DOUBLE VERTICAL LINE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x348,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LEFT ANGLE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x349,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING NOT TILDE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x34A,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING HOMOTHETIC ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x34B,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING ALMOST EQUAL TO ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x34C,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LEFT RIGHT ARROW BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x34D,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING UPWARDS ARROW BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x34E,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ description="COMBINING GRAPHEME JOINER",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x34F,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING RIGHT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x350,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LEFT HALF RING ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x351,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING FERMATA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x352,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING X BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x353,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING LEFT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x354,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING RIGHT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x355,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x356,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING RIGHT HALF RING ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x357,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE8,
+ description="COMBINING DOT ABOVE RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x358,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING ASTERISK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x359,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xDC,
+ description="COMBINING DOUBLE RING BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x35A,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING ZIGZAG ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x35B,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE9,
+ description="COMBINING DOUBLE BREVE BELOW",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x35C,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xEA,
+ description="COMBINING DOUBLE BREVE",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x35D,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xEA,
+ description="COMBINING DOUBLE MACRON",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x35E,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE9,
+ description="COMBINING DOUBLE MACRON BELOW",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x35F,
+ },
+ {
+ adobename="tildedoublecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xEA,
+ description="COMBINING DOUBLE TILDE",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x360,
+ },
+ {
+ adobename="breveinverteddoublecmb",
+ category="mn",
+ cjkwd="a",
+ combining=0xEA,
+ description="COMBINING DOUBLE INVERTED BREVE",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x361,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE9,
+ description="COMBINING DOUBLE RIGHTWARDS ARROW BELOW",
+ direction="nsm",
+ linebreak="gl",
+ unicodeslot=0x362,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x363,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x364,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x365,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x366,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x367,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER C",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x368,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER D",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x369,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER H",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36A,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36B,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36C,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER T",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36D,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER V",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36E,
+ },
+ {
+ category="mn",
+ cjkwd="a",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER X",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x36F,
+ },
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER HETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x370,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER HETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x371,
+ },
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER ARCHAIC SAMPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x372,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER ARCHAIC SAMPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x373,
+ },
+ {
+ adobename="numeralsigngreek",
+ category="sk",
+ description="GREEK NUMERAL SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x2B9 },
+ unicodeslot=0x374,
+ },
+ {
+ adobename="numeralsignlowergreek",
+ category="sk",
+ description="GREEK LOWER NUMERAL SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x375,
+ },
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x376,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER PAMPHYLIAN DIGAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x377,
+ },
+ [0x37A]={
+ adobename="ypogegrammeni",
+ category="lm",
+ description="GREEK YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x345 },
+ unicodeslot=0x37A,
+ },
+ [0x37B]={
+ category="ll",
+ description="GREEK SMALL REVERSED LUNATE SIGMA SYMBOL",
+ direction="l",
+ linebreak="al",
+ uccode=0x3FD,
+ unicodeslot=0x37B,
+ },
+ [0x37C]={
+ category="ll",
+ description="GREEK SMALL DOTTED LUNATE SIGMA SYMBOL",
+ direction="l",
+ linebreak="al",
+ uccode=0x3FE,
+ unicodeslot=0x37C,
+ },
+ [0x37D]={
+ category="ll",
+ description="GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL",
+ direction="l",
+ linebreak="al",
+ uccode=0x3FF,
+ unicodeslot=0x37D,
+ },
+ [0x37E]={
+ adobename="questiongreek",
+ category="po",
+ description="GREEK QUESTION MARK",
+ direction="on",
+ linebreak="is",
+ specials={ "char", 0x3B },
+ unicodeslot=0x37E,
+ },
+ [0x37F]={
+ category="lu",
+ description="GREEK CAPITAL LETTER YOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x37F,
+ },
+ [0x384]={
+ adobename="tonos",
+ category="sk",
+ contextname="greektonos",
+ description="GREEK TONOS",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x301 },
+ unicodeslot=0x384,
+ },
+ [0x385]={
+ adobename="dieresistonos",
+ category="sk",
+ contextname="greekdialytikatonos",
+ description="GREEK DIALYTIKA TONOS",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0xA8, 0x301 },
+ unicodeslot=0x385,
+ },
+ [0x386]={
+ adobename="Alphatonos",
+ category="lu",
+ contextname="greekAlphatonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH TONOS",
+ direction="l",
+ lccode=0x3AC,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x301 },
+ unicodeslot=0x386,
+ },
+ [0x387]={
+ adobename="anoteleia",
+ category="po",
+ description="GREEK ANO TELEIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0xB7 },
+ unicodeslot=0x387,
+ },
+ [0x388]={
+ adobename="Epsilontonos",
+ category="lu",
+ contextname="greekEpsilontonos",
+ description="GREEK CAPITAL LETTER EPSILON WITH TONOS",
+ direction="l",
+ lccode=0x3AD,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x395, 0x301 },
+ unicodeslot=0x388,
+ },
+ [0x389]={
+ adobename="Etatonos",
+ category="lu",
+ contextname="greekEtatonos",
+ description="GREEK CAPITAL LETTER ETA WITH TONOS",
+ direction="l",
+ lccode=0x3AE,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x397, 0x301 },
+ unicodeslot=0x389,
+ },
+ [0x38A]={
+ adobename="Iotatonos",
+ category="lu",
+ contextname="greekIotatonos",
+ description="GREEK CAPITAL LETTER IOTA WITH TONOS",
+ direction="l",
+ lccode=0x3AF,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x301 },
+ unicodeslot=0x38A,
+ },
+ [0x38C]={
+ adobename="Omicrontonos",
+ category="lu",
+ contextname="greekOmicrontonos",
+ description="GREEK CAPITAL LETTER OMICRON WITH TONOS",
+ direction="l",
+ lccode=0x3CC,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x39F, 0x301 },
+ unicodeslot=0x38C,
+ },
+ [0x38E]={
+ adobename="Upsilontonos",
+ category="lu",
+ contextname="greekUpsilontonos",
+ description="GREEK CAPITAL LETTER UPSILON WITH TONOS",
+ direction="l",
+ lccode=0x3CD,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x301 },
+ unicodeslot=0x38E,
+ },
+ [0x38F]={
+ adobename="Omegatonos",
+ category="lu",
+ contextname="greekOmegatonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH TONOS",
+ direction="l",
+ lccode=0x3CE,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x3A9, 0x301 },
+ unicodeslot=0x38F,
+ },
+ [0x390]={
+ adobename="iotadieresistonos",
+ category="ll",
+ contextname="greekiotadialytikatonos",
+ description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3CA, 0x301 },
+ unicodeslot=0x390,
+ },
+ [0x391]={
+ adobename="Alpha",
+ category="lu",
+ cjkwd="a",
+ contextname="greekAlpha",
+ description="GREEK CAPITAL LETTER ALPHA",
+ direction="l",
+ lccode=0x3B1,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Alpha",
+ unicodeslot=0x391,
+ },
+ [0x392]={
+ adobename="Beta",
+ category="lu",
+ cjkwd="a",
+ contextname="greekBeta",
+ description="GREEK CAPITAL LETTER BETA",
+ direction="l",
+ lccode=0x3B2,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Beta",
+ unicodeslot=0x392,
+ },
+ [0x393]={
+ adobename="Gamma",
+ category="lu",
+ cjkwd="a",
+ contextname="greekGamma",
+ description="GREEK CAPITAL LETTER GAMMA",
+ direction="l",
+ lccode=0x3B3,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Gamma",
+ unicodeslot=0x393,
+ },
+ [0x394]={
+ adobename="Deltagreek",
+ category="lu",
+ cjkwd="a",
+ contextname="greekDelta",
+ description="GREEK CAPITAL LETTER DELTA",
+ direction="l",
+ lccode=0x3B4,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Delta",
+ unicodeslot=0x394,
+ },
+ [0x395]={
+ adobename="Epsilon",
+ category="lu",
+ cjkwd="a",
+ contextname="greekEpsilon",
+ description="GREEK CAPITAL LETTER EPSILON",
+ direction="l",
+ lccode=0x3B5,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Epsilon",
+ unicodeslot=0x395,
+ },
+ [0x396]={
+ adobename="Zeta",
+ category="lu",
+ cjkwd="a",
+ contextname="greekZeta",
+ description="GREEK CAPITAL LETTER ZETA",
+ direction="l",
+ lccode=0x3B6,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Zeta",
+ unicodeslot=0x396,
+ },
+ [0x397]={
+ adobename="Eta",
+ category="lu",
+ cjkwd="a",
+ contextname="greekEta",
+ description="GREEK CAPITAL LETTER ETA",
+ direction="l",
+ lccode=0x3B7,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Eta",
+ unicodeslot=0x397,
+ },
+ [0x398]={
+ adobename="Theta",
+ category="lu",
+ cjkwd="a",
+ contextname="greekTheta",
+ description="GREEK CAPITAL LETTER THETA",
+ direction="l",
+ lccode=0x3B8,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Theta",
+ unicodeslot=0x398,
+ },
+ [0x399]={
+ adobename="Iota",
+ category="lu",
+ cjkwd="a",
+ contextname="greekIota",
+ description="GREEK CAPITAL LETTER IOTA",
+ direction="l",
+ lccode=0x3B9,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Iota",
+ unicodeslot=0x399,
+ },
+ [0x39A]={
+ adobename="Kappa",
+ category="lu",
+ cjkwd="a",
+ contextname="greekKappa",
+ description="GREEK CAPITAL LETTER KAPPA",
+ direction="l",
+ lccode=0x3BA,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Kappa",
+ unicodeslot=0x39A,
+ },
+ [0x39B]={
+ adobename="Lambda",
+ category="lu",
+ cjkwd="a",
+ contextname="greekLambda",
+ description="GREEK CAPITAL LETTER LAMDA",
+ direction="l",
+ lccode=0x3BB,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Lambda",
+ unicodeslot=0x39B,
+ },
+ [0x39C]={
+ adobename="Mu",
+ category="lu",
+ cjkwd="a",
+ contextname="greekMu",
+ description="GREEK CAPITAL LETTER MU",
+ direction="l",
+ lccode=0x3BC,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Mu",
+ unicodeslot=0x39C,
+ },
+ [0x39D]={
+ adobename="Nu",
+ category="lu",
+ cjkwd="a",
+ contextname="greekNu",
+ description="GREEK CAPITAL LETTER NU",
+ direction="l",
+ lccode=0x3BD,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Nu",
+ unicodeslot=0x39D,
+ },
+ [0x39E]={
+ adobename="Xi",
+ category="lu",
+ cjkwd="a",
+ contextname="greekXi",
+ description="GREEK CAPITAL LETTER XI",
+ direction="l",
+ lccode=0x3BE,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Xi",
+ unicodeslot=0x39E,
+ },
+ [0x39F]={
+ adobename="Omicron",
+ category="lu",
+ cjkwd="a",
+ contextname="greekOmicron",
+ description="GREEK CAPITAL LETTER OMICRON",
+ direction="l",
+ lccode=0x3BF,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Omicron",
+ unicodeslot=0x39F,
+ },
+ [0x3A0]={
+ adobename="Pi",
+ category="lu",
+ cjkwd="a",
+ contextname="greekPi",
+ description="GREEK CAPITAL LETTER PI",
+ direction="l",
+ lccode=0x3C0,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Pi",
+ unicodeslot=0x3A0,
+ },
+ [0x3A1]={
+ adobename="Rho",
+ category="lu",
+ cjkwd="a",
+ contextname="greekRho",
+ description="GREEK CAPITAL LETTER RHO",
+ direction="l",
+ lccode=0x3C1,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Rho",
+ unicodeslot=0x3A1,
+ },
+ [0x3A3]={
+ adobename="Sigma",
+ category="lu",
+ cjkwd="a",
+ contextname="greekSigma",
+ description="GREEK CAPITAL LETTER SIGMA",
+ direction="l",
+ lccode=0x3C3,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Sigma",
+ unicodeslot=0x3A3,
+ },
+ [0x3A4]={
+ adobename="Tau",
+ category="lu",
+ cjkwd="a",
+ contextname="greekTau",
+ description="GREEK CAPITAL LETTER TAU",
+ direction="l",
+ lccode=0x3C4,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Tau",
+ unicodeslot=0x3A4,
+ },
+ [0x3A5]={
+ adobename="Upsilon",
+ category="lu",
+ cjkwd="a",
+ contextname="greekUpsilon",
+ description="GREEK CAPITAL LETTER UPSILON",
+ direction="l",
+ lccode=0x3C5,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Upsilon",
+ unicodeslot=0x3A5,
+ },
+ [0x3A6]={
+ adobename="Phi",
+ category="lu",
+ cjkwd="a",
+ contextname="greekPhi",
+ description="GREEK CAPITAL LETTER PHI",
+ direction="l",
+ lccode=0x3C6,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Phi",
+ unicodeslot=0x3A6,
+ },
+ [0x3A7]={
+ adobename="Chi",
+ category="lu",
+ cjkwd="a",
+ contextname="greekChi",
+ description="GREEK CAPITAL LETTER CHI",
+ direction="l",
+ lccode=0x3C7,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Chi",
+ unicodeslot=0x3A7,
+ },
+ [0x3A8]={
+ adobename="Psi",
+ category="lu",
+ cjkwd="a",
+ contextname="greekPsi",
+ description="GREEK CAPITAL LETTER PSI",
+ direction="l",
+ lccode=0x3C8,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Psi",
+ unicodeslot=0x3A8,
+ },
+ [0x3A9]={
+ adobename="Omegagreek",
+ category="lu",
+ cjkwd="a",
+ contextname="greekOmega",
+ description="GREEK CAPITAL LETTER OMEGA",
+ direction="l",
+ lccode=0x3C9,
+ linebreak="al",
+ mathclass="variable",
+ mathname="Omega",
+ unicodeslot=0x3A9,
+ },
+ [0x3AA]={
+ adobename="Iotadieresis",
+ category="lu",
+ contextname="greekIotadialytika",
+ description="GREEK CAPITAL LETTER IOTA WITH DIALYTIKA",
+ direction="l",
+ lccode=0x3CA,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x308 },
+ unicodeslot=0x3AA,
+ },
+ [0x3AB]={
+ adobename="Upsilondieresis",
+ category="lu",
+ contextname="greekUpsilondialytika",
+ description="GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA",
+ direction="l",
+ lccode=0x3CB,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x308 },
+ unicodeslot=0x3AB,
+ },
+ [0x3AC]={
+ adobename="alphatonos",
+ category="ll",
+ contextname="greekalphatonos",
+ description="GREEK SMALL LETTER ALPHA WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x301 },
+ uccode=0x386,
+ unicodeslot=0x3AC,
+ },
+ [0x3AD]={
+ adobename="epsilontonos",
+ category="ll",
+ contextname="greekepsilontonos",
+ description="GREEK SMALL LETTER EPSILON WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x3B5, 0x301 },
+ uccode=0x388,
+ unicodeslot=0x3AD,
+ },
+ [0x3AE]={
+ adobename="etatonos",
+ category="ll",
+ contextname="greeketatonos",
+ description="GREEK SMALL LETTER ETA WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x301 },
+ uccode=0x389,
+ unicodeslot=0x3AE,
+ },
+ [0x3AF]={
+ adobename="iotatonos",
+ category="ll",
+ contextname="greekiotatonos",
+ description="GREEK SMALL LETTER IOTA WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x301 },
+ uccode=0x38A,
+ unicodeslot=0x3AF,
+ },
+ [0x3B0]={
+ adobename="upsilondieresistonos",
+ category="ll",
+ contextname="greekupsilondialytikatonos",
+ description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3CB, 0x301 },
+ unicodeslot=0x3B0,
+ },
+ [0x3B1]={
+ adobename="alpha",
+ category="ll",
+ cjkwd="a",
+ contextname="greekalpha",
+ description="GREEK SMALL LETTER ALPHA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="alpha",
+ uccode=0x391,
+ unicodeslot=0x3B1,
+ },
+ [0x3B2]={
+ adobename="beta",
+ category="ll",
+ cjkwd="a",
+ contextname="greekbeta",
+ description="GREEK SMALL LETTER BETA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="beta",
+ uccode=0x392,
+ unicodeslot=0x3B2,
+ },
+ [0x3B3]={
+ adobename="gamma",
+ category="ll",
+ cjkwd="a",
+ contextname="greekgamma",
+ description="GREEK SMALL LETTER GAMMA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="gamma",
+ uccode=0x393,
+ unicodeslot=0x3B3,
+ },
+ [0x3B4]={
+ adobename="delta",
+ category="ll",
+ cjkwd="a",
+ contextname="greekdelta",
+ description="GREEK SMALL LETTER DELTA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="delta",
+ uccode=0x394,
+ unicodeslot=0x3B4,
+ },
+ [0x3B5]={
+ adobename="epsilon",
+ category="ll",
+ cjkwd="a",
+ contextname="greekepsilon",
+ description="GREEK SMALL LETTER EPSILON",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varepsilon",
+ uccode=0x395,
+ unicodeslot=0x3B5,
+ },
+ [0x3B6]={
+ adobename="zeta",
+ category="ll",
+ cjkwd="a",
+ contextname="greekzeta",
+ description="GREEK SMALL LETTER ZETA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="zeta",
+ uccode=0x396,
+ unicodeslot=0x3B6,
+ },
+ [0x3B7]={
+ adobename="eta",
+ category="ll",
+ cjkwd="a",
+ contextname="greeketa",
+ description="GREEK SMALL LETTER ETA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="eta",
+ uccode=0x397,
+ unicodeslot=0x3B7,
+ },
+ [0x3B8]={
+ adobename="theta",
+ category="ll",
+ cjkwd="a",
+ contextname="greektheta",
+ description="GREEK SMALL LETTER THETA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="theta",
+ uccode=0x398,
+ unicodeslot=0x3B8,
+ },
+ [0x3B9]={
+ adobename="iota",
+ category="ll",
+ cjkwd="a",
+ contextname="greekiota",
+ description="GREEK SMALL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="iota",
+ uccode=0x399,
+ unicodeslot=0x3B9,
+ },
+ [0x3BA]={
+ adobename="kappa",
+ category="ll",
+ cjkwd="a",
+ contextname="greekkappa",
+ description="GREEK SMALL LETTER KAPPA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="kappa",
+ uccode=0x39A,
+ unicodeslot=0x3BA,
+ },
+ [0x3BB]={
+ adobename="lambda",
+ category="ll",
+ cjkwd="a",
+ contextname="greeklambda",
+ description="GREEK SMALL LETTER LAMDA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="lambda",
+ uccode=0x39B,
+ unicodeslot=0x3BB,
+ },
+ [0x3BC]={
+ adobename="mugreek",
+ category="ll",
+ cjkwd="a",
+ contextname="greekmu",
+ description="GREEK SMALL LETTER MU",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="mu",
+ uccode=0x39C,
+ unicodeslot=0x3BC,
+ },
+ [0x3BD]={
+ adobename="nu",
+ category="ll",
+ cjkwd="a",
+ contextname="greeknu",
+ description="GREEK SMALL LETTER NU",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="nu",
+ uccode=0x39D,
+ unicodeslot=0x3BD,
+ },
+ [0x3BE]={
+ adobename="xi",
+ category="ll",
+ cjkwd="a",
+ contextname="greekxi",
+ description="GREEK SMALL LETTER XI",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="xi",
+ uccode=0x39E,
+ unicodeslot=0x3BE,
+ },
+ [0x3BF]={
+ adobename="omicron",
+ category="ll",
+ cjkwd="a",
+ contextname="greekomicron",
+ description="GREEK SMALL LETTER OMICRON",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="omicron",
+ uccode=0x39F,
+ unicodeslot=0x3BF,
+ },
+ [0x3C0]={
+ adobename="pi",
+ category="ll",
+ cjkwd="a",
+ contextname="greekpi",
+ description="GREEK SMALL LETTER PI",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="pi",
+ uccode=0x3A0,
+ unicodeslot=0x3C0,
+ },
+ [0x3C1]={
+ adobename="rho",
+ category="ll",
+ cjkwd="a",
+ contextname="greekrho",
+ description="GREEK SMALL LETTER RHO",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="rho",
+ uccode=0x3A1,
+ unicodeslot=0x3C1,
+ },
+ [0x3C2]={
+ adobename="sigmafinal",
+ category="ll",
+ contextname="greekfinalsigma",
+ description="GREEK SMALL LETTER FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varsigma",
+ uccode=0x3A3,
+ unicodeslot=0x3C2,
+ },
+ [0x3C3]={
+ adobename="sigma",
+ category="ll",
+ cjkwd="a",
+ contextname="greeksigma",
+ description="GREEK SMALL LETTER SIGMA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="sigma",
+ uccode=0x3A3,
+ unicodeslot=0x3C3,
+ },
+ [0x3C4]={
+ adobename="tau",
+ category="ll",
+ cjkwd="a",
+ contextname="greektau",
+ description="GREEK SMALL LETTER TAU",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="tau",
+ uccode=0x3A4,
+ unicodeslot=0x3C4,
+ },
+ [0x3C5]={
+ adobename="upsilon",
+ category="ll",
+ cjkwd="a",
+ contextname="greekupsilon",
+ description="GREEK SMALL LETTER UPSILON",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="upsilon",
+ uccode=0x3A5,
+ unicodeslot=0x3C5,
+ },
+ [0x3C6]={
+ adobename="phi",
+ category="ll",
+ cjkwd="a",
+ contextname="greekphi",
+ description="GREEK SMALL LETTER PHI",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varphi",
+ uccode=0x3A6,
+ unicodeslot=0x3C6,
+ },
+ [0x3C7]={
+ adobename="chi",
+ category="ll",
+ cjkwd="a",
+ contextname="greekchi",
+ description="GREEK SMALL LETTER CHI",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="chi",
+ uccode=0x3A7,
+ unicodeslot=0x3C7,
+ },
+ [0x3C8]={
+ adobename="psi",
+ category="ll",
+ cjkwd="a",
+ contextname="greekpsi",
+ description="GREEK SMALL LETTER PSI",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="psi",
+ uccode=0x3A8,
+ unicodeslot=0x3C8,
+ },
+ [0x3C9]={
+ adobename="omega",
+ category="ll",
+ cjkwd="a",
+ contextname="greekomega",
+ description="GREEK SMALL LETTER OMEGA",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="omega",
+ uccode=0x3A9,
+ unicodeslot=0x3C9,
+ },
+ [0x3CA]={
+ adobename="iotadieresis",
+ category="ll",
+ contextname="greekiotadialytika",
+ description="GREEK SMALL LETTER IOTA WITH DIALYTIKA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x308 },
+ uccode=0x3AA,
+ unicodeslot=0x3CA,
+ },
+ [0x3CB]={
+ adobename="upsilondieresis",
+ category="ll",
+ contextname="greekupsilondiaeresis",
+ description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x308 },
+ uccode=0x3AB,
+ unicodeslot=0x3CB,
+ },
+ [0x3CC]={
+ adobename="omicrontonos",
+ category="ll",
+ contextname="greekomicrontonos",
+ description="GREEK SMALL LETTER OMICRON WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x3BF, 0x301 },
+ uccode=0x38C,
+ unicodeslot=0x3CC,
+ },
+ [0x3CD]={
+ adobename="upsilontonos",
+ category="ll",
+ contextname="greekupsilontonos",
+ description="GREEK SMALL LETTER UPSILON WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x301 },
+ uccode=0x38E,
+ unicodeslot=0x3CD,
+ },
+ [0x3CE]={
+ adobename="omegatonos",
+ category="ll",
+ contextname="greekomegatonos",
+ description="GREEK SMALL LETTER OMEGA WITH TONOS",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x301 },
+ uccode=0x38F,
+ unicodeslot=0x3CE,
+ },
+ [0x3CF]={
+ category="lu",
+ description="GREEK CAPITAL KAI SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x3CF,
+ },
+ [0x3D0]={
+ adobename="betasymbolgreek",
+ category="ll",
+ description="GREEK BETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x3B2 },
+ uccode=0x392,
+ unicodeslot=0x3D0,
+ },
+ [0x3D1]={
+ adobename="thetasymbolgreek",
+ category="ll",
+ contextname="greekthetaalt",
+ description="GREEK THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varTheta",
+ specials={ "compat", 0x3B8 },
+ uccode=0x398,
+ unicodeslot=0x3D1,
+ },
+ [0x3D2]={
+ adobename="Upsilonhooksymbol",
+ category="lu",
+ description="GREEK UPSILON WITH HOOK SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x3A5 },
+ unicodeslot=0x3D2,
+ },
+ [0x3D3]={
+ adobename="Upsilonacutehooksymbolgreek",
+ category="lu",
+ description="GREEK UPSILON WITH ACUTE AND HOOK SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x3D2, 0x301 },
+ unicodeslot=0x3D3,
+ },
+ [0x3D4]={
+ adobename="Upsilondieresishooksymbolgreek",
+ category="lu",
+ description="GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x3D2, 0x308 },
+ unicodeslot=0x3D4,
+ },
+ [0x3D5]={
+ adobename="phisymbolgreek",
+ category="ll",
+ contextname="greekphialt",
+ description="GREEK PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="phi",
+ specials={ "compat", 0x3C6 },
+ uccode=0x3A6,
+ unicodeslot=0x3D5,
+ },
+ [0x3D6]={
+ adobename="pisymbolgreek",
+ category="ll",
+ contextname="greekpialt",
+ description="GREEK PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varpi",
+ specials={ "compat", 0x3C0 },
+ uccode=0x3A0,
+ unicodeslot=0x3D6,
+ },
+ [0x3D7]={
+ category="ll",
+ description="GREEK KAI SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x3D7,
+ },
+ [0x3D8]={
+ category="lu",
+ description="GREEK LETTER ARCHAIC KOPPA",
+ direction="l",
+ lccode=0x3D9,
+ linebreak="al",
+ unicodeslot=0x3D8,
+ },
+ [0x3D9]={
+ category="ll",
+ contextname="greekkoppa",
+ description="GREEK SMALL LETTER ARCHAIC KOPPA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3D8,
+ unicodeslot=0x3D9,
+ },
+ [0x3DA]={
+ adobename="Stigmagreek",
+ category="lu",
+ description="GREEK LETTER STIGMA",
+ direction="l",
+ lccode=0x3DB,
+ linebreak="al",
+ unicodeslot=0x3DA,
+ },
+ [0x3DB]={
+ category="ll",
+ contextname="greekstigma",
+ description="GREEK SMALL LETTER STIGMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3DA,
+ unicodeslot=0x3DB,
+ },
+ [0x3DC]={
+ adobename="Digammagreek",
+ category="lu",
+ description="GREEK LETTER DIGAMMA",
+ direction="l",
+ lccode=0x3DD,
+ linebreak="al",
+ mathclass="variable",
+ mathname="digamma",
+ unicodeslot=0x3DC,
+ },
+ [0x3DD]={
+ category="ll",
+ contextname="greekdigamma",
+ description="GREEK SMALL LETTER DIGAMMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3DC,
+ unicodeslot=0x3DD,
+ },
+ [0x3DE]={
+ adobename="Koppagreek",
+ category="lu",
+ description="GREEK LETTER KOPPA",
+ direction="l",
+ lccode=0x3DF,
+ linebreak="al",
+ unicodeslot=0x3DE,
+ },
+ [0x3DF]={
+ category="ll",
+ contextname="greeknumkoppa",
+ description="GREEK SMALL LETTER KOPPA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3DE,
+ unicodeslot=0x3DF,
+ },
+ [0x3E0]={
+ adobename="Sampigreek",
+ category="lu",
+ description="GREEK LETTER SAMPI",
+ direction="l",
+ lccode=0x3E1,
+ linebreak="al",
+ unicodeslot=0x3E0,
+ },
+ [0x3E1]={
+ category="ll",
+ contextname="greeksampi",
+ description="GREEK SMALL LETTER SAMPI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3E0,
+ unicodeslot=0x3E1,
+ },
+ [0x3E2]={
+ adobename="Sheicoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER SHEI",
+ direction="l",
+ lccode=0x3E3,
+ linebreak="al",
+ unicodeslot=0x3E2,
+ },
+ [0x3E3]={
+ adobename="sheicoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER SHEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3E2,
+ unicodeslot=0x3E3,
+ },
+ [0x3E4]={
+ adobename="Feicoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER FEI",
+ direction="l",
+ lccode=0x3E5,
+ linebreak="al",
+ unicodeslot=0x3E4,
+ },
+ [0x3E5]={
+ adobename="feicoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER FEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3E4,
+ unicodeslot=0x3E5,
+ },
+ [0x3E6]={
+ adobename="Kheicoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER KHEI",
+ direction="l",
+ lccode=0x3E7,
+ linebreak="al",
+ unicodeslot=0x3E6,
+ },
+ [0x3E7]={
+ adobename="kheicoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER KHEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3E6,
+ unicodeslot=0x3E7,
+ },
+ [0x3E8]={
+ adobename="Horicoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER HORI",
+ direction="l",
+ lccode=0x3E9,
+ linebreak="al",
+ unicodeslot=0x3E8,
+ },
+ [0x3E9]={
+ adobename="horicoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER HORI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3E8,
+ unicodeslot=0x3E9,
+ },
+ [0x3EA]={
+ adobename="Gangiacoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER GANGIA",
+ direction="l",
+ lccode=0x3EB,
+ linebreak="al",
+ unicodeslot=0x3EA,
+ },
+ [0x3EB]={
+ adobename="gangiacoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER GANGIA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3EA,
+ unicodeslot=0x3EB,
+ },
+ [0x3EC]={
+ adobename="Shimacoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER SHIMA",
+ direction="l",
+ lccode=0x3ED,
+ linebreak="al",
+ unicodeslot=0x3EC,
+ },
+ [0x3ED]={
+ adobename="shimacoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER SHIMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x3EC,
+ unicodeslot=0x3ED,
+ },
+ [0x3EE]={
+ adobename="Deicoptic",
+ category="lu",
+ description="COPTIC CAPITAL LETTER DEI",
+ direction="l",
+ lccode=0x3EF,
+ linebreak="al",
+ unicodeslot=0x3EE,
+ },
+ [0x3EF]={
+ adobename="deicoptic",
+ category="ll",
+ description="COPTIC SMALL LETTER DEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x3EE,
+ unicodeslot=0x3EF,
+ },
+ [0x3F0]={
+ adobename="kappasymbolgreek",
+ category="ll",
+ description="GREEK KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="varkappa",
+ specials={ "compat", 0x3BA },
+ uccode=0x39A,
+ unicodeslot=0x3F0,
+ },
+ [0x3F1]={
+ adobename="rhosymbolgreek",
+ category="ll",
+ contextname="greekrhoalt",
+ description="GREEK RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x3C1 },
+ uccode=0x3A1,
+ unicodeslot=0x3F1,
+ },
+ [0x3F2]={
+ adobename="sigmalunatesymbolgreek",
+ category="ll",
+ contextname="greeksigmalunate",
+ description="GREEK LUNATE SIGMA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x3C2 },
+ uccode=0x3F9,
+ unicodeslot=0x3F2,
+ },
+ [0x3F3]={
+ adobename="yotgreek",
+ category="ll",
+ description="GREEK LETTER YOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x3F3,
+ },
+ [0x3F4]={
+ category="lu",
+ description="GREEK CAPITAL THETA SYMBOL",
+ direction="l",
+ lccode=0x3B8,
+ linebreak="al",
+ specials={ "compat", 0x398 },
+ unicodeslot=0x3F4,
+ },
+ [0x3F5]={
+ category="ll",
+ contextname="greekepsilonalt",
+ description="GREEK LUNATE EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="epsilon",
+ specials={ "compat", 0x3B5 },
+ uccode=0x395,
+ unicodeslot=0x3F5,
+ },
+ [0x3F6]={
+ category="sm",
+ description="GREEK REVERSED LUNATE EPSILON SYMBOL",
+ direction="on",
+ linebreak="al",
+ mathclass="variable",
+ mathname="backepsilon",
+ unicodeslot=0x3F6,
+ },
+ [0x3F7]={
+ category="lu",
+ description="GREEK CAPITAL LETTER SHO",
+ direction="l",
+ lccode=0x3F8,
+ linebreak="al",
+ unicodeslot=0x3F7,
+ },
+ [0x3F8]={
+ category="ll",
+ description="GREEK SMALL LETTER SHO",
+ direction="l",
+ linebreak="al",
+ uccode=0x3F7,
+ unicodeslot=0x3F8,
+ },
+ [0x3F9]={
+ category="lu",
+ contextname="greekSigmalunate",
+ description="GREEK CAPITAL LUNATE SIGMA SYMBOL",
+ direction="l",
+ lccode=0x3F2,
+ linebreak="al",
+ specials={ "compat", 0x3A3 },
+ unicodeslot=0x3F9,
+ },
+ [0x3FA]={
+ category="lu",
+ description="GREEK CAPITAL LETTER SAN",
+ direction="l",
+ lccode=0x3FB,
+ linebreak="al",
+ unicodeslot=0x3FA,
+ },
+ [0x3FB]={
+ category="ll",
+ description="GREEK SMALL LETTER SAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x3FA,
+ unicodeslot=0x3FB,
+ },
+ [0x3FC]={
+ category="ll",
+ description="GREEK RHO WITH STROKE SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x3FC,
+ },
+ [0x3FD]={
+ category="lu",
+ description="GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL",
+ direction="l",
+ lccode=0x37B,
+ linebreak="al",
+ unicodeslot=0x3FD,
+ },
+ [0x3FE]={
+ category="lu",
+ description="GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL",
+ direction="l",
+ lccode=0x37C,
+ linebreak="al",
+ unicodeslot=0x3FE,
+ },
+ [0x3FF]={
+ category="lu",
+ description="GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL",
+ direction="l",
+ lccode=0x37D,
+ linebreak="al",
+ unicodeslot=0x3FF,
+ },
+ [0x400]={
+ category="lu",
+ contextname="cyrillicEgrave",
+ description="CYRILLIC CAPITAL LETTER IE WITH GRAVE",
+ direction="l",
+ lccode=0x450,
+ linebreak="al",
+ shcode=0x415,
+ specials={ "char", 0x415, 0x300 },
+ unicodeslot=0x400,
+ },
+ [0x401]={
+ adobename="afii10023",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicYO",
+ description="CYRILLIC CAPITAL LETTER IO",
+ direction="l",
+ lccode=0x451,
+ linebreak="al",
+ specials={ "char", 0x415, 0x308 },
+ unicodeslot=0x401,
+ },
+ [0x402]={
+ adobename="afii10051",
+ category="lu",
+ contextname="cyrillicDJE",
+ description="CYRILLIC CAPITAL LETTER DJE",
+ direction="l",
+ lccode=0x452,
+ linebreak="al",
+ unicodeslot=0x402,
+ },
+ [0x403]={
+ adobename="afii10052",
+ category="lu",
+ contextname="cyrillicGJE",
+ description="CYRILLIC CAPITAL LETTER GJE",
+ direction="l",
+ lccode=0x453,
+ linebreak="al",
+ specials={ "char", 0x413, 0x301 },
+ unicodeslot=0x403,
+ },
+ [0x404]={
+ adobename="afii10053",
+ category="lu",
+ contextname="cyrillicIE",
+ description="CYRILLIC CAPITAL LETTER UKRAINIAN IE",
+ direction="l",
+ lccode=0x454,
+ linebreak="al",
+ unicodeslot=0x404,
+ },
+ [0x405]={
+ adobename="afii10054",
+ category="lu",
+ contextname="cyrillicDZE",
+ description="CYRILLIC CAPITAL LETTER DZE",
+ direction="l",
+ lccode=0x455,
+ linebreak="al",
+ unicodeslot=0x405,
+ },
+ [0x406]={
+ adobename="afii10055",
+ category="lu",
+ contextname="cyrillicII",
+ description="CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I",
+ direction="l",
+ lccode=0x456,
+ linebreak="al",
+ unicodeslot=0x406,
+ },
+ [0x407]={
+ adobename="afii10056",
+ category="lu",
+ contextname="cyrillicYI",
+ description="CYRILLIC CAPITAL LETTER YI",
+ direction="l",
+ lccode=0x457,
+ linebreak="al",
+ specials={ "char", 0x406, 0x308 },
+ unicodeslot=0x407,
+ },
+ [0x408]={
+ adobename="afii10057",
+ category="lu",
+ contextname="cyrillicJE",
+ description="CYRILLIC CAPITAL LETTER JE",
+ direction="l",
+ lccode=0x458,
+ linebreak="al",
+ unicodeslot=0x408,
+ },
+ [0x409]={
+ adobename="afii10058",
+ category="lu",
+ contextname="cyrillicLJE",
+ description="CYRILLIC CAPITAL LETTER LJE",
+ direction="l",
+ lccode=0x459,
+ linebreak="al",
+ unicodeslot=0x409,
+ },
+ [0x40A]={
+ adobename="afii10059",
+ category="lu",
+ contextname="cyrillicNJE",
+ description="CYRILLIC CAPITAL LETTER NJE",
+ direction="l",
+ lccode=0x45A,
+ linebreak="al",
+ unicodeslot=0x40A,
+ },
+ [0x40B]={
+ adobename="afii10060",
+ category="lu",
+ contextname="cyrillicTSHE",
+ description="CYRILLIC CAPITAL LETTER TSHE",
+ direction="l",
+ lccode=0x45B,
+ linebreak="al",
+ unicodeslot=0x40B,
+ },
+ [0x40C]={
+ adobename="afii10061",
+ category="lu",
+ contextname="cyrillicKJE",
+ description="CYRILLIC CAPITAL LETTER KJE",
+ direction="l",
+ lccode=0x45C,
+ linebreak="al",
+ specials={ "char", 0x41A, 0x301 },
+ unicodeslot=0x40C,
+ },
+ [0x40D]={
+ category="lu",
+ contextname="cyrillicIgrave",
+ description="CYRILLIC CAPITAL LETTER I WITH GRAVE",
+ direction="l",
+ lccode=0x45D,
+ linebreak="al",
+ shcode=0x418,
+ specials={ "char", 0x418, 0x300 },
+ unicodeslot=0x40D,
+ },
+ [0x40E]={
+ adobename="afii10062",
+ category="lu",
+ contextname="cyrillicUSHRT",
+ description="CYRILLIC CAPITAL LETTER SHORT U",
+ direction="l",
+ lccode=0x45E,
+ linebreak="al",
+ specials={ "char", 0x423, 0x306 },
+ unicodeslot=0x40E,
+ },
+ [0x40F]={
+ adobename="afii10145",
+ category="lu",
+ contextname="cyrillicDZHE",
+ description="CYRILLIC CAPITAL LETTER DZHE",
+ direction="l",
+ lccode=0x45F,
+ linebreak="al",
+ unicodeslot=0x40F,
+ },
+ [0x410]={
+ adobename="afii10017",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicA",
+ description="CYRILLIC CAPITAL LETTER A",
+ direction="l",
+ lccode=0x430,
+ linebreak="al",
+ unicodeslot=0x410,
+ },
+ [0x411]={
+ adobename="afii10018",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicB",
+ description="CYRILLIC CAPITAL LETTER BE",
+ direction="l",
+ lccode=0x431,
+ linebreak="al",
+ unicodeslot=0x411,
+ },
+ [0x412]={
+ adobename="afii10019",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicV",
+ description="CYRILLIC CAPITAL LETTER VE",
+ direction="l",
+ lccode=0x432,
+ linebreak="al",
+ unicodeslot=0x412,
+ },
+ [0x413]={
+ adobename="afii10020",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicG",
+ description="CYRILLIC CAPITAL LETTER GHE",
+ direction="l",
+ lccode=0x433,
+ linebreak="al",
+ unicodeslot=0x413,
+ },
+ [0x414]={
+ adobename="afii10021",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicD",
+ description="CYRILLIC CAPITAL LETTER DE",
+ direction="l",
+ lccode=0x434,
+ linebreak="al",
+ unicodeslot=0x414,
+ },
+ [0x415]={
+ adobename="afii10022",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicE",
+ description="CYRILLIC CAPITAL LETTER IE",
+ direction="l",
+ lccode=0x435,
+ linebreak="al",
+ unicodeslot=0x415,
+ },
+ [0x416]={
+ adobename="afii10024",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicZH",
+ description="CYRILLIC CAPITAL LETTER ZHE",
+ direction="l",
+ lccode=0x436,
+ linebreak="al",
+ unicodeslot=0x416,
+ },
+ [0x417]={
+ adobename="afii10025",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicZ",
+ description="CYRILLIC CAPITAL LETTER ZE",
+ direction="l",
+ lccode=0x437,
+ linebreak="al",
+ unicodeslot=0x417,
+ },
+ [0x418]={
+ adobename="afii10026",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicI",
+ description="CYRILLIC CAPITAL LETTER I",
+ direction="l",
+ lccode=0x438,
+ linebreak="al",
+ unicodeslot=0x418,
+ },
+ [0x419]={
+ adobename="afii10027",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicISHRT",
+ description="CYRILLIC CAPITAL LETTER SHORT I",
+ direction="l",
+ lccode=0x439,
+ linebreak="al",
+ specials={ "char", 0x418, 0x306 },
+ unicodeslot=0x419,
+ },
+ [0x41A]={
+ adobename="afii10028",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicK",
+ description="CYRILLIC CAPITAL LETTER KA",
+ direction="l",
+ lccode=0x43A,
+ linebreak="al",
+ unicodeslot=0x41A,
+ },
+ [0x41B]={
+ adobename="afii10029",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicL",
+ description="CYRILLIC CAPITAL LETTER EL",
+ direction="l",
+ lccode=0x43B,
+ linebreak="al",
+ unicodeslot=0x41B,
+ },
+ [0x41C]={
+ adobename="afii10030",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicM",
+ description="CYRILLIC CAPITAL LETTER EM",
+ direction="l",
+ lccode=0x43C,
+ linebreak="al",
+ unicodeslot=0x41C,
+ },
+ [0x41D]={
+ adobename="afii10031",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicN",
+ description="CYRILLIC CAPITAL LETTER EN",
+ direction="l",
+ lccode=0x43D,
+ linebreak="al",
+ unicodeslot=0x41D,
+ },
+ [0x41E]={
+ adobename="afii10032",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicO",
+ description="CYRILLIC CAPITAL LETTER O",
+ direction="l",
+ lccode=0x43E,
+ linebreak="al",
+ unicodeslot=0x41E,
+ },
+ [0x41F]={
+ adobename="afii10033",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicP",
+ description="CYRILLIC CAPITAL LETTER PE",
+ direction="l",
+ lccode=0x43F,
+ linebreak="al",
+ unicodeslot=0x41F,
+ },
+ [0x420]={
+ adobename="afii10034",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicR",
+ description="CYRILLIC CAPITAL LETTER ER",
+ direction="l",
+ lccode=0x440,
+ linebreak="al",
+ unicodeslot=0x420,
+ },
+ [0x421]={
+ adobename="afii10035",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicS",
+ description="CYRILLIC CAPITAL LETTER ES",
+ direction="l",
+ lccode=0x441,
+ linebreak="al",
+ unicodeslot=0x421,
+ },
+ [0x422]={
+ adobename="afii10036",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicT",
+ description="CYRILLIC CAPITAL LETTER TE",
+ direction="l",
+ lccode=0x442,
+ linebreak="al",
+ unicodeslot=0x422,
+ },
+ [0x423]={
+ adobename="afii10037",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicU",
+ description="CYRILLIC CAPITAL LETTER U",
+ direction="l",
+ lccode=0x443,
+ linebreak="al",
+ unicodeslot=0x423,
+ },
+ [0x424]={
+ adobename="afii10038",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicF",
+ description="CYRILLIC CAPITAL LETTER EF",
+ direction="l",
+ lccode=0x444,
+ linebreak="al",
+ unicodeslot=0x424,
+ },
+ [0x425]={
+ adobename="afii10039",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicH",
+ description="CYRILLIC CAPITAL LETTER HA",
+ direction="l",
+ lccode=0x445,
+ linebreak="al",
+ unicodeslot=0x425,
+ },
+ [0x426]={
+ adobename="afii10040",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicC",
+ description="CYRILLIC CAPITAL LETTER TSE",
+ direction="l",
+ lccode=0x446,
+ linebreak="al",
+ unicodeslot=0x426,
+ },
+ [0x427]={
+ adobename="afii10041",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicCH",
+ description="CYRILLIC CAPITAL LETTER CHE",
+ direction="l",
+ lccode=0x447,
+ linebreak="al",
+ unicodeslot=0x427,
+ },
+ [0x428]={
+ adobename="afii10042",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicSH",
+ description="CYRILLIC CAPITAL LETTER SHA",
+ direction="l",
+ lccode=0x448,
+ linebreak="al",
+ unicodeslot=0x428,
+ },
+ [0x429]={
+ adobename="afii10043",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicSHCH",
+ description="CYRILLIC CAPITAL LETTER SHCHA",
+ direction="l",
+ lccode=0x449,
+ linebreak="al",
+ unicodeslot=0x429,
+ },
+ [0x42A]={
+ adobename="afii10044",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicHRDSN",
+ description="CYRILLIC CAPITAL LETTER HARD SIGN",
+ direction="l",
+ lccode=0x44A,
+ linebreak="al",
+ unicodeslot=0x42A,
+ },
+ [0x42B]={
+ adobename="afii10045",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicERY",
+ description="CYRILLIC CAPITAL LETTER YERU",
+ direction="l",
+ lccode=0x44B,
+ linebreak="al",
+ unicodeslot=0x42B,
+ },
+ [0x42C]={
+ adobename="afii10046",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicSFTSN",
+ description="CYRILLIC CAPITAL LETTER SOFT SIGN",
+ direction="l",
+ lccode=0x44C,
+ linebreak="al",
+ unicodeslot=0x42C,
+ },
+ [0x42D]={
+ adobename="afii10047",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicEREV",
+ description="CYRILLIC CAPITAL LETTER E",
+ direction="l",
+ lccode=0x44D,
+ linebreak="al",
+ unicodeslot=0x42D,
+ },
+ [0x42E]={
+ adobename="afii10048",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicYU",
+ description="CYRILLIC CAPITAL LETTER YU",
+ direction="l",
+ lccode=0x44E,
+ linebreak="al",
+ unicodeslot=0x42E,
+ },
+ [0x42F]={
+ adobename="afii10049",
+ category="lu",
+ cjkwd="a",
+ contextname="cyrillicYA",
+ description="CYRILLIC CAPITAL LETTER YA",
+ direction="l",
+ lccode=0x44F,
+ linebreak="al",
+ unicodeslot=0x42F,
+ },
+ [0x430]={
+ adobename="afii10065",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillica",
+ description="CYRILLIC SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ uccode=0x410,
+ unicodeslot=0x430,
+ },
+ [0x431]={
+ adobename="becyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicb",
+ description="CYRILLIC SMALL LETTER BE",
+ direction="l",
+ linebreak="al",
+ uccode=0x411,
+ unicodeslot=0x431,
+ },
+ [0x432]={
+ adobename="vecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicv",
+ description="CYRILLIC SMALL LETTER VE",
+ direction="l",
+ linebreak="al",
+ uccode=0x412,
+ unicodeslot=0x432,
+ },
+ [0x433]={
+ adobename="gecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicg",
+ description="CYRILLIC SMALL LETTER GHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x413,
+ unicodeslot=0x433,
+ },
+ [0x434]={
+ adobename="decyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicd",
+ description="CYRILLIC SMALL LETTER DE",
+ direction="l",
+ linebreak="al",
+ uccode=0x414,
+ unicodeslot=0x434,
+ },
+ [0x435]={
+ adobename="iecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillice",
+ description="CYRILLIC SMALL LETTER IE",
+ direction="l",
+ linebreak="al",
+ uccode=0x415,
+ unicodeslot=0x435,
+ },
+ [0x436]={
+ adobename="zhecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrilliczh",
+ description="CYRILLIC SMALL LETTER ZHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x416,
+ unicodeslot=0x436,
+ },
+ [0x437]={
+ adobename="zecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicz",
+ description="CYRILLIC SMALL LETTER ZE",
+ direction="l",
+ linebreak="al",
+ uccode=0x417,
+ unicodeslot=0x437,
+ },
+ [0x438]={
+ adobename="iicyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillici",
+ description="CYRILLIC SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ uccode=0x418,
+ unicodeslot=0x438,
+ },
+ [0x439]={
+ adobename="iishortcyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicishrt",
+ description="CYRILLIC SMALL LETTER SHORT I",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x438, 0x306 },
+ uccode=0x419,
+ unicodeslot=0x439,
+ },
+ [0x43A]={
+ adobename="kacyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillick",
+ description="CYRILLIC SMALL LETTER KA",
+ direction="l",
+ linebreak="al",
+ uccode=0x41A,
+ unicodeslot=0x43A,
+ },
+ [0x43B]={
+ adobename="elcyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicl",
+ description="CYRILLIC SMALL LETTER EL",
+ direction="l",
+ linebreak="al",
+ uccode=0x41B,
+ unicodeslot=0x43B,
+ },
+ [0x43C]={
+ adobename="emcyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicm",
+ description="CYRILLIC SMALL LETTER EM",
+ direction="l",
+ linebreak="al",
+ uccode=0x41C,
+ unicodeslot=0x43C,
+ },
+ [0x43D]={
+ adobename="encyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicn",
+ description="CYRILLIC SMALL LETTER EN",
+ direction="l",
+ linebreak="al",
+ uccode=0x41D,
+ unicodeslot=0x43D,
+ },
+ [0x43E]={
+ adobename="ocyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillico",
+ description="CYRILLIC SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ uccode=0x41E,
+ unicodeslot=0x43E,
+ },
+ [0x43F]={
+ adobename="pecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicp",
+ description="CYRILLIC SMALL LETTER PE",
+ direction="l",
+ linebreak="al",
+ uccode=0x41F,
+ unicodeslot=0x43F,
+ },
+ [0x440]={
+ adobename="ercyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicr",
+ description="CYRILLIC SMALL LETTER ER",
+ direction="l",
+ linebreak="al",
+ uccode=0x420,
+ unicodeslot=0x440,
+ },
+ [0x441]={
+ adobename="escyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillics",
+ description="CYRILLIC SMALL LETTER ES",
+ direction="l",
+ linebreak="al",
+ uccode=0x421,
+ unicodeslot=0x441,
+ },
+ [0x442]={
+ adobename="tecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillict",
+ description="CYRILLIC SMALL LETTER TE",
+ direction="l",
+ linebreak="al",
+ uccode=0x422,
+ unicodeslot=0x442,
+ },
+ [0x443]={
+ adobename="ucyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicu",
+ description="CYRILLIC SMALL LETTER U",
+ direction="l",
+ linebreak="al",
+ uccode=0x423,
+ unicodeslot=0x443,
+ },
+ [0x444]={
+ adobename="efcyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicf",
+ description="CYRILLIC SMALL LETTER EF",
+ direction="l",
+ linebreak="al",
+ uccode=0x424,
+ unicodeslot=0x444,
+ },
+ [0x445]={
+ adobename="khacyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillich",
+ description="CYRILLIC SMALL LETTER HA",
+ direction="l",
+ linebreak="al",
+ uccode=0x425,
+ unicodeslot=0x445,
+ },
+ [0x446]={
+ adobename="tsecyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicc",
+ description="CYRILLIC SMALL LETTER TSE",
+ direction="l",
+ linebreak="al",
+ uccode=0x426,
+ unicodeslot=0x446,
+ },
+ [0x447]={
+ adobename="checyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicch",
+ description="CYRILLIC SMALL LETTER CHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x427,
+ unicodeslot=0x447,
+ },
+ [0x448]={
+ adobename="shacyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicsh",
+ description="CYRILLIC SMALL LETTER SHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x428,
+ unicodeslot=0x448,
+ },
+ [0x449]={
+ adobename="shchacyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicshch",
+ description="CYRILLIC SMALL LETTER SHCHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x429,
+ unicodeslot=0x449,
+ },
+ [0x44A]={
+ adobename="hardsigncyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillichrdsn",
+ description="CYRILLIC SMALL LETTER HARD SIGN",
+ direction="l",
+ linebreak="al",
+ uccode=0x42A,
+ unicodeslot=0x44A,
+ },
+ [0x44B]={
+ adobename="yericyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicery",
+ description="CYRILLIC SMALL LETTER YERU",
+ direction="l",
+ linebreak="al",
+ uccode=0x42B,
+ unicodeslot=0x44B,
+ },
+ [0x44C]={
+ adobename="softsigncyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicsftsn",
+ description="CYRILLIC SMALL LETTER SOFT SIGN",
+ direction="l",
+ linebreak="al",
+ uccode=0x42C,
+ unicodeslot=0x44C,
+ },
+ [0x44D]={
+ adobename="ereversedcyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicerev",
+ description="CYRILLIC SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ uccode=0x42D,
+ unicodeslot=0x44D,
+ },
+ [0x44E]={
+ adobename="iucyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicyu",
+ description="CYRILLIC SMALL LETTER YU",
+ direction="l",
+ linebreak="al",
+ uccode=0x42E,
+ unicodeslot=0x44E,
+ },
+ [0x44F]={
+ adobename="iacyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicya",
+ description="CYRILLIC SMALL LETTER YA",
+ direction="l",
+ linebreak="al",
+ uccode=0x42F,
+ unicodeslot=0x44F,
+ },
+ [0x450]={
+ category="ll",
+ contextname="cyrillicegrave",
+ description="CYRILLIC SMALL LETTER IE WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x435,
+ specials={ "char", 0x435, 0x300 },
+ uccode=0x400,
+ unicodeslot=0x450,
+ },
+ [0x451]={
+ adobename="iocyrillic",
+ category="ll",
+ cjkwd="a",
+ contextname="cyrillicyo",
+ description="CYRILLIC SMALL LETTER IO",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x435, 0x308 },
+ uccode=0x401,
+ unicodeslot=0x451,
+ },
+ [0x452]={
+ adobename="djecyrillic",
+ category="ll",
+ contextname="cyrillicdje",
+ description="CYRILLIC SMALL LETTER DJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x402,
+ unicodeslot=0x452,
+ },
+ [0x453]={
+ adobename="gjecyrillic",
+ category="ll",
+ contextname="cyrillicgje",
+ description="CYRILLIC SMALL LETTER GJE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x433, 0x301 },
+ uccode=0x403,
+ unicodeslot=0x453,
+ },
+ [0x454]={
+ adobename="ecyrillic",
+ category="ll",
+ contextname="cyrillicie",
+ description="CYRILLIC SMALL LETTER UKRAINIAN IE",
+ direction="l",
+ linebreak="al",
+ uccode=0x404,
+ unicodeslot=0x454,
+ },
+ [0x455]={
+ adobename="dzecyrillic",
+ category="ll",
+ contextname="cyrillicdze",
+ description="CYRILLIC SMALL LETTER DZE",
+ direction="l",
+ linebreak="al",
+ uccode=0x405,
+ unicodeslot=0x455,
+ },
+ [0x456]={
+ adobename="icyrillic",
+ category="ll",
+ contextname="cyrillicii",
+ description="CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I",
+ direction="l",
+ linebreak="al",
+ uccode=0x406,
+ unicodeslot=0x456,
+ },
+ [0x457]={
+ adobename="yicyrillic",
+ category="ll",
+ contextname="cyrillicyi",
+ description="CYRILLIC SMALL LETTER YI",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x456, 0x308 },
+ uccode=0x407,
+ unicodeslot=0x457,
+ },
+ [0x458]={
+ adobename="jecyrillic",
+ category="ll",
+ contextname="cyrillicje",
+ description="CYRILLIC SMALL LETTER JE",
+ direction="l",
+ linebreak="al",
+ uccode=0x408,
+ unicodeslot=0x458,
+ },
+ [0x459]={
+ adobename="ljecyrillic",
+ category="ll",
+ contextname="cyrilliclje",
+ description="CYRILLIC SMALL LETTER LJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x409,
+ unicodeslot=0x459,
+ },
+ [0x45A]={
+ adobename="njecyrillic",
+ category="ll",
+ contextname="cyrillicnje",
+ description="CYRILLIC SMALL LETTER NJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x40A,
+ unicodeslot=0x45A,
+ },
+ [0x45B]={
+ adobename="tshecyrillic",
+ category="ll",
+ contextname="cyrillictshe",
+ description="CYRILLIC SMALL LETTER TSHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x40B,
+ unicodeslot=0x45B,
+ },
+ [0x45C]={
+ adobename="kjecyrillic",
+ category="ll",
+ contextname="cyrillickje",
+ description="CYRILLIC SMALL LETTER KJE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x43A, 0x301 },
+ uccode=0x40C,
+ unicodeslot=0x45C,
+ },
+ [0x45D]={
+ category="ll",
+ contextname="cyrillicigrave",
+ description="CYRILLIC SMALL LETTER I WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x438,
+ specials={ "char", 0x438, 0x300 },
+ uccode=0x40D,
+ unicodeslot=0x45D,
+ },
+ [0x45E]={
+ adobename="ushortcyrillic",
+ category="ll",
+ contextname="cyrillicushrt",
+ description="CYRILLIC SMALL LETTER SHORT U",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x443, 0x306 },
+ uccode=0x40E,
+ unicodeslot=0x45E,
+ },
+ [0x45F]={
+ adobename="dzhecyrillic",
+ category="ll",
+ contextname="cyrillicdzhe",
+ description="CYRILLIC SMALL LETTER DZHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x40F,
+ unicodeslot=0x45F,
+ },
+ [0x460]={
+ adobename="Omegacyrillic",
+ category="lu",
+ contextname="cyrillicOMEGA",
+ description="CYRILLIC CAPITAL LETTER OMEGA",
+ direction="l",
+ lccode=0x461,
+ linebreak="al",
+ unicodeslot=0x460,
+ },
+ [0x461]={
+ adobename="omegacyrillic",
+ category="ll",
+ contextname="cyrillicomega",
+ description="CYRILLIC SMALL LETTER OMEGA",
+ direction="l",
+ linebreak="al",
+ uccode=0x460,
+ unicodeslot=0x461,
+ },
+ [0x462]={
+ adobename="afii10146",
+ category="lu",
+ contextname="cyrillicYAT",
+ description="CYRILLIC CAPITAL LETTER YAT",
+ direction="l",
+ lccode=0x463,
+ linebreak="al",
+ unicodeslot=0x462,
+ },
+ [0x463]={
+ adobename="yatcyrillic",
+ category="ll",
+ contextname="cyrillicyat",
+ description="CYRILLIC SMALL LETTER YAT",
+ direction="l",
+ linebreak="al",
+ uccode=0x462,
+ unicodeslot=0x463,
+ },
+ [0x464]={
+ adobename="Eiotifiedcyrillic",
+ category="lu",
+ contextname="cyrillicEiotified",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED E",
+ direction="l",
+ lccode=0x465,
+ linebreak="al",
+ unicodeslot=0x464,
+ },
+ [0x465]={
+ adobename="eiotifiedcyrillic",
+ category="ll",
+ contextname="cyrilliceiotified",
+ description="CYRILLIC SMALL LETTER IOTIFIED E",
+ direction="l",
+ linebreak="al",
+ uccode=0x464,
+ unicodeslot=0x465,
+ },
+ [0x466]={
+ adobename="Yuslittlecyrillic",
+ category="lu",
+ contextname="cyrillicLITTLEYUS",
+ description="CYRILLIC CAPITAL LETTER LITTLE YUS",
+ direction="l",
+ lccode=0x467,
+ linebreak="al",
+ unicodeslot=0x466,
+ },
+ [0x467]={
+ adobename="yuslittlecyrillic",
+ category="ll",
+ contextname="cyrilliclittleyus",
+ description="CYRILLIC SMALL LETTER LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x466,
+ unicodeslot=0x467,
+ },
+ [0x468]={
+ adobename="Yuslittleiotifiedcyrillic",
+ category="lu",
+ contextname="cyrillicLITTLEYUSiotified",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS",
+ direction="l",
+ lccode=0x469,
+ linebreak="al",
+ unicodeslot=0x468,
+ },
+ [0x469]={
+ adobename="yuslittleiotifiedcyrillic",
+ category="ll",
+ contextname="cyrilliclittleyusiotified",
+ description="CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x468,
+ unicodeslot=0x469,
+ },
+ [0x46A]={
+ adobename="Yusbigcyrillic",
+ category="lu",
+ contextname="cyrillicBIGYUS",
+ description="CYRILLIC CAPITAL LETTER BIG YUS",
+ direction="l",
+ lccode=0x46B,
+ linebreak="al",
+ unicodeslot=0x46A,
+ },
+ [0x46B]={
+ adobename="yusbigcyrillic",
+ category="ll",
+ contextname="cyrillicbigyus",
+ description="CYRILLIC SMALL LETTER BIG YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x46A,
+ unicodeslot=0x46B,
+ },
+ [0x46C]={
+ adobename="Yusbigiotifiedcyrillic",
+ category="lu",
+ contextname="cyrillicBIGYUSiotified",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS",
+ direction="l",
+ lccode=0x46D,
+ linebreak="al",
+ unicodeslot=0x46C,
+ },
+ [0x46D]={
+ adobename="yusbigiotifiedcyrillic",
+ category="ll",
+ contextname="cyrillicbigyusiotified",
+ description="CYRILLIC SMALL LETTER IOTIFIED BIG YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x46C,
+ unicodeslot=0x46D,
+ },
+ [0x46E]={
+ adobename="Ksicyrillic",
+ category="lu",
+ contextname="cyrillicKSI",
+ description="CYRILLIC CAPITAL LETTER KSI",
+ direction="l",
+ lccode=0x46F,
+ linebreak="al",
+ unicodeslot=0x46E,
+ },
+ [0x46F]={
+ adobename="ksicyrillic",
+ category="ll",
+ contextname="cyrillicksi",
+ description="CYRILLIC SMALL LETTER KSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x46E,
+ unicodeslot=0x46F,
+ },
+ [0x470]={
+ adobename="Psicyrillic",
+ category="lu",
+ contextname="cyrillicPSI",
+ description="CYRILLIC CAPITAL LETTER PSI",
+ direction="l",
+ lccode=0x471,
+ linebreak="al",
+ unicodeslot=0x470,
+ },
+ [0x471]={
+ adobename="psicyrillic",
+ category="ll",
+ contextname="cyrillicpsi",
+ description="CYRILLIC SMALL LETTER PSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x470,
+ unicodeslot=0x471,
+ },
+ [0x472]={
+ adobename="afii10147",
+ category="lu",
+ contextname="cyrillicFITA",
+ description="CYRILLIC CAPITAL LETTER FITA",
+ direction="l",
+ lccode=0x473,
+ linebreak="al",
+ unicodeslot=0x472,
+ },
+ [0x473]={
+ adobename="fitacyrillic",
+ category="ll",
+ contextname="cyrillicfita",
+ description="CYRILLIC SMALL LETTER FITA",
+ direction="l",
+ linebreak="al",
+ uccode=0x472,
+ unicodeslot=0x473,
+ },
+ [0x474]={
+ adobename="afii10148",
+ category="lu",
+ contextname="cyrillicIZHITSA",
+ description="CYRILLIC CAPITAL LETTER IZHITSA",
+ direction="l",
+ lccode=0x475,
+ linebreak="al",
+ unicodeslot=0x474,
+ },
+ [0x475]={
+ adobename="izhitsacyrillic",
+ category="ll",
+ contextname="cyrillicizhitsa",
+ description="CYRILLIC SMALL LETTER IZHITSA",
+ direction="l",
+ linebreak="al",
+ uccode=0x474,
+ unicodeslot=0x475,
+ },
+ [0x476]={
+ adobename="Izhitsadblgravecyrillic",
+ category="lu",
+ contextname="cyrillicIZHITSAdoublegrave",
+ description="CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT",
+ direction="l",
+ lccode=0x477,
+ linebreak="al",
+ shcode=0x474,
+ specials={ "char", 0x474, 0x30F },
+ unicodeslot=0x476,
+ },
+ [0x477]={
+ adobename="izhitsadblgravecyrillic",
+ category="ll",
+ contextname="cyrillicizhitsadoublegrave",
+ description="CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT",
+ direction="l",
+ linebreak="al",
+ shcode=0x475,
+ specials={ "char", 0x475, 0x30F },
+ uccode=0x476,
+ unicodeslot=0x477,
+ },
+ [0x478]={
+ adobename="Ukcyrillic",
+ category="lu",
+ contextname="cyrillicUK",
+ description="CYRILLIC CAPITAL LETTER UK",
+ direction="l",
+ lccode=0x479,
+ linebreak="al",
+ unicodeslot=0x478,
+ },
+ [0x479]={
+ adobename="ukcyrillic",
+ category="ll",
+ contextname="cyrillicuk",
+ description="CYRILLIC SMALL LETTER UK",
+ direction="l",
+ linebreak="al",
+ uccode=0x478,
+ unicodeslot=0x479,
+ },
+ [0x47A]={
+ adobename="Omegaroundcyrillic",
+ category="lu",
+ contextname="cyrillicOMEGAround",
+ description="CYRILLIC CAPITAL LETTER ROUND OMEGA",
+ direction="l",
+ lccode=0x47B,
+ linebreak="al",
+ unicodeslot=0x47A,
+ },
+ [0x47B]={
+ adobename="omegaroundcyrillic",
+ category="ll",
+ contextname="cyrillicomegaround",
+ description="CYRILLIC SMALL LETTER ROUND OMEGA",
+ direction="l",
+ linebreak="al",
+ uccode=0x47A,
+ unicodeslot=0x47B,
+ },
+ [0x47C]={
+ adobename="Omegatitlocyrillic",
+ category="lu",
+ contextname="cyrillicOMEGAtitlo",
+ description="CYRILLIC CAPITAL LETTER OMEGA WITH TITLO",
+ direction="l",
+ lccode=0x47D,
+ linebreak="al",
+ shcode=0x460,
+ unicodeslot=0x47C,
+ },
+ [0x47D]={
+ adobename="omegatitlocyrillic",
+ category="ll",
+ contextname="cyrillicomegatitlo",
+ description="CYRILLIC SMALL LETTER OMEGA WITH TITLO",
+ direction="l",
+ linebreak="al",
+ shcode=0x461,
+ uccode=0x47C,
+ unicodeslot=0x47D,
+ },
+ [0x47E]={
+ adobename="Otcyrillic",
+ category="lu",
+ contextname="cyrillicOT",
+ description="CYRILLIC CAPITAL LETTER OT",
+ direction="l",
+ lccode=0x47F,
+ linebreak="al",
+ unicodeslot=0x47E,
+ },
+ [0x47F]={
+ adobename="otcyrillic",
+ category="ll",
+ contextname="cyrillicot",
+ description="CYRILLIC SMALL LETTER OT",
+ direction="l",
+ linebreak="al",
+ uccode=0x47E,
+ unicodeslot=0x47F,
+ },
+ [0x480]={
+ adobename="Koppacyrillic",
+ category="lu",
+ contextname="cyrillicKOPPA",
+ description="CYRILLIC CAPITAL LETTER KOPPA",
+ direction="l",
+ lccode=0x481,
+ linebreak="al",
+ unicodeslot=0x480,
+ },
+ [0x481]={
+ adobename="koppacyrillic",
+ category="ll",
+ contextname="cyrillickoppa",
+ description="CYRILLIC SMALL LETTER KOPPA",
+ direction="l",
+ linebreak="al",
+ uccode=0x480,
+ unicodeslot=0x481,
+ },
+ [0x482]={
+ adobename="thousandcyrillic",
+ category="so",
+ description="CYRILLIC THOUSANDS SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x482,
+ },
+ [0x483]={
+ adobename="titlocyrilliccmb",
+ category="mn",
+ combining=0xE6,
+ contextname="cyrillicTITLO",
+ description="COMBINING CYRILLIC TITLO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x483,
+ },
+ [0x484]={
+ adobename="palatalizationcyrilliccmb",
+ category="mn",
+ combining=0xE6,
+ contextname="cyrillicPALATALIZATION",
+ description="COMBINING CYRILLIC PALATALIZATION",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x484,
+ },
+ [0x485]={
+ adobename="dasiapneumatacyrilliccmb",
+ category="mn",
+ combining=0xE6,
+ contextname="cyrillicDASIAPNEUMATA",
+ description="COMBINING CYRILLIC DASIA PNEUMATA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x485,
+ },
+ [0x486]={
+ adobename="psilipneumatacyrilliccmb",
+ category="mn",
+ combining=0xE6,
+ contextname="cyrillicPSILIPNEUMATA",
+ description="COMBINING CYRILLIC PSILI PNEUMATA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x486,
+ },
+ [0x487]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC POKRYTIE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x487,
+ },
+ [0x488]={
+ category="me",
+ description="COMBINING CYRILLIC HUNDRED THOUSANDS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x488,
+ },
+ [0x489]={
+ category="me",
+ description="COMBINING CYRILLIC MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x489,
+ },
+ [0x48A]={
+ category="lu",
+ contextname="cyrillicISHRTtail",
+ description="CYRILLIC CAPITAL LETTER SHORT I WITH TAIL",
+ direction="l",
+ lccode=0x48B,
+ linebreak="al",
+ unicodeslot=0x48A,
+ },
+ [0x48B]={
+ category="ll",
+ contextname="cyrillicishrttail",
+ description="CYRILLIC SMALL LETTER SHORT I WITH TAIL",
+ direction="l",
+ linebreak="al",
+ uccode=0x48A,
+ unicodeslot=0x48B,
+ },
+ [0x48C]={
+ category="lu",
+ contextname="cyrillicSEMISOFT",
+ description="CYRILLIC CAPITAL LETTER SEMISOFT SIGN",
+ direction="l",
+ lccode=0x48D,
+ linebreak="al",
+ unicodeslot=0x48C,
+ },
+ [0x48D]={
+ category="ll",
+ contextname="cyrillicsemisoft",
+ description="CYRILLIC SMALL LETTER SEMISOFT SIGN",
+ direction="l",
+ linebreak="al",
+ uccode=0x48C,
+ unicodeslot=0x48D,
+ },
+ [0x48E]={
+ category="lu",
+ contextname="cyrillicERtick",
+ description="CYRILLIC CAPITAL LETTER ER WITH TICK",
+ direction="l",
+ lccode=0x48F,
+ linebreak="al",
+ shcode=0x420,
+ unicodeslot=0x48E,
+ },
+ [0x48F]={
+ category="ll",
+ contextname="cyrillicertick",
+ description="CYRILLIC SMALL LETTER ER WITH TICK",
+ direction="l",
+ linebreak="al",
+ shcode=0x440,
+ uccode=0x48E,
+ unicodeslot=0x48F,
+ },
+ [0x490]={
+ adobename="afii10050",
+ category="lu",
+ contextname="cyrillicGHEupturn",
+ description="CYRILLIC CAPITAL LETTER GHE WITH UPTURN",
+ direction="l",
+ lccode=0x491,
+ linebreak="al",
+ shcode=0x413,
+ unicodeslot=0x490,
+ },
+ [0x491]={
+ adobename="gheupturncyrillic",
+ category="ll",
+ contextname="cyrillicgheupturn",
+ description="CYRILLIC SMALL LETTER GHE WITH UPTURN",
+ direction="l",
+ linebreak="al",
+ shcode=0x433,
+ uccode=0x490,
+ unicodeslot=0x491,
+ },
+ [0x492]={
+ adobename="Ghestrokecyrillic",
+ category="lu",
+ contextname="cyrillicGHEstroke",
+ description="CYRILLIC CAPITAL LETTER GHE WITH STROKE",
+ direction="l",
+ lccode=0x493,
+ linebreak="al",
+ shcode=0x413,
+ unicodeslot=0x492,
+ },
+ [0x493]={
+ adobename="ghestrokecyrillic",
+ category="ll",
+ contextname="cyrillicghestroke",
+ description="CYRILLIC SMALL LETTER GHE WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x433,
+ uccode=0x492,
+ unicodeslot=0x493,
+ },
+ [0x494]={
+ adobename="Ghemiddlehookcyrillic",
+ category="lu",
+ contextname="cyrillicGHEmidhook",
+ description="CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK",
+ direction="l",
+ lccode=0x495,
+ linebreak="al",
+ shcode=0x413,
+ unicodeslot=0x494,
+ },
+ [0x495]={
+ adobename="ghemiddlehookcyrillic",
+ category="ll",
+ contextname="cyrillicghemidhook",
+ description="CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x433,
+ uccode=0x494,
+ unicodeslot=0x495,
+ },
+ [0x496]={
+ adobename="Zhedescendercyrillic",
+ category="lu",
+ contextname="cyrillicZHEdescender",
+ description="CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER",
+ direction="l",
+ lccode=0x497,
+ linebreak="al",
+ shcode=0x416,
+ unicodeslot=0x496,
+ },
+ [0x497]={
+ adobename="zhedescendercyrillic",
+ category="ll",
+ contextname="cyrilliczhedescender",
+ description="CYRILLIC SMALL LETTER ZHE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x436,
+ uccode=0x496,
+ unicodeslot=0x497,
+ },
+ [0x498]={
+ adobename="Zedescendercyrillic",
+ category="lu",
+ contextname="cyrillicZDSC",
+ description="CYRILLIC CAPITAL LETTER ZE WITH DESCENDER",
+ direction="l",
+ lccode=0x499,
+ linebreak="al",
+ shcode=0x417,
+ unicodeslot=0x498,
+ },
+ [0x499]={
+ adobename="zedescendercyrillic",
+ category="ll",
+ contextname="cyrilliczdsc",
+ description="CYRILLIC SMALL LETTER ZE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x437,
+ uccode=0x498,
+ unicodeslot=0x499,
+ },
+ [0x49A]={
+ adobename="Kadescendercyrillic",
+ category="lu",
+ contextname="cyrillicKADC",
+ description="CYRILLIC CAPITAL LETTER KA WITH DESCENDER",
+ direction="l",
+ lccode=0x49B,
+ linebreak="al",
+ shcode=0x41A,
+ unicodeslot=0x49A,
+ },
+ [0x49B]={
+ adobename="kadescendercyrillic",
+ category="ll",
+ contextname="cyrillickadc",
+ description="CYRILLIC SMALL LETTER KA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x43A,
+ uccode=0x49A,
+ unicodeslot=0x49B,
+ },
+ [0x49C]={
+ adobename="Kaverticalstrokecyrillic",
+ category="lu",
+ contextname="cyrillicKAvertstroke",
+ description="CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE",
+ direction="l",
+ lccode=0x49D,
+ linebreak="al",
+ shcode=0x41A,
+ unicodeslot=0x49C,
+ },
+ [0x49D]={
+ adobename="kaverticalstrokecyrillic",
+ category="ll",
+ contextname="cyrillickavertstroke",
+ description="CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x43A,
+ uccode=0x49C,
+ unicodeslot=0x49D,
+ },
+ [0x49E]={
+ adobename="Kastrokecyrillic",
+ category="lu",
+ contextname="cyrillicKAstroke",
+ description="CYRILLIC CAPITAL LETTER KA WITH STROKE",
+ direction="l",
+ lccode=0x49F,
+ linebreak="al",
+ shcode=0x41A,
+ unicodeslot=0x49E,
+ },
+ [0x49F]={
+ adobename="kastrokecyrillic",
+ category="ll",
+ contextname="cyrillickastroke",
+ description="CYRILLIC SMALL LETTER KA WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x43A,
+ uccode=0x49E,
+ unicodeslot=0x49F,
+ },
+ [0x4A0]={
+ adobename="Kabashkircyrillic",
+ category="lu",
+ contextname="cyrillicKAbashkir",
+ description="CYRILLIC CAPITAL LETTER BASHKIR KA",
+ direction="l",
+ lccode=0x4A1,
+ linebreak="al",
+ unicodeslot=0x4A0,
+ },
+ [0x4A1]={
+ adobename="kabashkircyrillic",
+ category="ll",
+ contextname="cyrillickabashkir",
+ description="CYRILLIC SMALL LETTER BASHKIR KA",
+ direction="l",
+ linebreak="al",
+ uccode=0x4A0,
+ unicodeslot=0x4A1,
+ },
+ [0x4A2]={
+ adobename="Endescendercyrillic",
+ category="lu",
+ contextname="cyrillicENDC",
+ description="CYRILLIC CAPITAL LETTER EN WITH DESCENDER",
+ direction="l",
+ lccode=0x4A3,
+ linebreak="al",
+ shcode=0x41D,
+ unicodeslot=0x4A2,
+ },
+ [0x4A3]={
+ adobename="endescendercyrillic",
+ category="ll",
+ contextname="cyrillicendc",
+ description="CYRILLIC SMALL LETTER EN WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x43D,
+ uccode=0x4A2,
+ unicodeslot=0x4A3,
+ },
+ [0x4A4]={
+ adobename="Enghecyrillic",
+ category="lu",
+ contextname="cyrillicENGHE",
+ description="CYRILLIC CAPITAL LIGATURE EN GHE",
+ direction="l",
+ lccode=0x4A5,
+ linebreak="al",
+ unicodeslot=0x4A4,
+ },
+ [0x4A5]={
+ adobename="enghecyrillic",
+ category="ll",
+ contextname="cyrillicenghe",
+ description="CYRILLIC SMALL LIGATURE EN GHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4A4,
+ unicodeslot=0x4A5,
+ },
+ [0x4A6]={
+ adobename="Pemiddlehookcyrillic",
+ category="lu",
+ contextname="cyrillicPEmidhook",
+ description="CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK",
+ direction="l",
+ lccode=0x4A7,
+ linebreak="al",
+ shcode=0x41F,
+ unicodeslot=0x4A6,
+ },
+ [0x4A7]={
+ adobename="pemiddlehookcyrillic",
+ category="ll",
+ contextname="cyrillicpemidhook",
+ description="CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x43F,
+ uccode=0x4A6,
+ unicodeslot=0x4A7,
+ },
+ [0x4A8]={
+ adobename="Haabkhasiancyrillic",
+ category="lu",
+ contextname="cyrillicHA",
+ description="CYRILLIC CAPITAL LETTER ABKHASIAN HA",
+ direction="l",
+ lccode=0x4A9,
+ linebreak="al",
+ unicodeslot=0x4A8,
+ },
+ [0x4A9]={
+ adobename="haabkhasiancyrillic",
+ category="ll",
+ contextname="cyrillicha",
+ description="CYRILLIC SMALL LETTER ABKHASIAN HA",
+ direction="l",
+ linebreak="al",
+ uccode=0x4A8,
+ unicodeslot=0x4A9,
+ },
+ [0x4AA]={
+ adobename="Esdescendercyrillic",
+ category="lu",
+ contextname="cyrillicSDSC",
+ description="CYRILLIC CAPITAL LETTER ES WITH DESCENDER",
+ direction="l",
+ lccode=0x4AB,
+ linebreak="al",
+ shcode=0x421,
+ unicodeslot=0x4AA,
+ },
+ [0x4AB]={
+ adobename="esdescendercyrillic",
+ category="ll",
+ contextname="cyrillicsdsc",
+ description="CYRILLIC SMALL LETTER ES WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x441,
+ uccode=0x4AA,
+ unicodeslot=0x4AB,
+ },
+ [0x4AC]={
+ adobename="Tedescendercyrillic",
+ category="lu",
+ contextname="cyrillicTEDC",
+ description="CYRILLIC CAPITAL LETTER TE WITH DESCENDER",
+ direction="l",
+ lccode=0x4AD,
+ linebreak="al",
+ shcode=0x422,
+ unicodeslot=0x4AC,
+ },
+ [0x4AD]={
+ adobename="tedescendercyrillic",
+ category="ll",
+ contextname="cyrillictedc",
+ description="CYRILLIC SMALL LETTER TE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x442,
+ uccode=0x4AC,
+ unicodeslot=0x4AD,
+ },
+ [0x4AE]={
+ adobename="Ustraightcyrillic",
+ category="lu",
+ contextname="cyrillicYstr",
+ description="CYRILLIC CAPITAL LETTER STRAIGHT U",
+ direction="l",
+ lccode=0x4AF,
+ linebreak="al",
+ unicodeslot=0x4AE,
+ },
+ [0x4AF]={
+ adobename="ustraightcyrillic",
+ category="ll",
+ contextname="cyrillicystr",
+ description="CYRILLIC SMALL LETTER STRAIGHT U",
+ direction="l",
+ linebreak="al",
+ uccode=0x4AE,
+ unicodeslot=0x4AF,
+ },
+ [0x4B0]={
+ adobename="Ustraightstrokecyrillic",
+ category="lu",
+ contextname="cyrillicYstrstroke",
+ description="CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE",
+ direction="l",
+ lccode=0x4B1,
+ linebreak="al",
+ unicodeslot=0x4B0,
+ },
+ [0x4B1]={
+ adobename="ustraightstrokecyrillic",
+ category="ll",
+ contextname="cyrillicystrstroke",
+ description="CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4B0,
+ unicodeslot=0x4B1,
+ },
+ [0x4B2]={
+ adobename="Hadescendercyrillic",
+ category="lu",
+ contextname="cyrillicHADC",
+ description="CYRILLIC CAPITAL LETTER HA WITH DESCENDER",
+ direction="l",
+ lccode=0x4B3,
+ linebreak="al",
+ shcode=0x425,
+ unicodeslot=0x4B2,
+ },
+ [0x4B3]={
+ adobename="hadescendercyrillic",
+ category="ll",
+ contextname="cyrillichadc",
+ description="CYRILLIC SMALL LETTER HA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x445,
+ uccode=0x4B2,
+ unicodeslot=0x4B3,
+ },
+ [0x4B4]={
+ adobename="Tetsecyrillic",
+ category="lu",
+ contextname="cyrillicTETSE",
+ description="CYRILLIC CAPITAL LIGATURE TE TSE",
+ direction="l",
+ lccode=0x4B5,
+ linebreak="al",
+ unicodeslot=0x4B4,
+ },
+ [0x4B5]={
+ adobename="tetsecyrillic",
+ category="ll",
+ contextname="cyrillictetse",
+ description="CYRILLIC SMALL LIGATURE TE TSE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4B4,
+ unicodeslot=0x4B5,
+ },
+ [0x4B6]={
+ adobename="Chedescendercyrillic",
+ category="lu",
+ contextname="cyrillicCHEDC",
+ description="CYRILLIC CAPITAL LETTER CHE WITH DESCENDER",
+ direction="l",
+ lccode=0x4B7,
+ linebreak="al",
+ shcode=0x427,
+ unicodeslot=0x4B6,
+ },
+ [0x4B7]={
+ adobename="chedescendercyrillic",
+ category="ll",
+ contextname="cyrillicchedc",
+ description="CYRILLIC SMALL LETTER CHE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x447,
+ uccode=0x4B6,
+ unicodeslot=0x4B7,
+ },
+ [0x4B8]={
+ adobename="Cheverticalstrokecyrillic",
+ category="lu",
+ contextname="cyrillicCHEvertstroke",
+ description="CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE",
+ direction="l",
+ lccode=0x4B9,
+ linebreak="al",
+ shcode=0x427,
+ unicodeslot=0x4B8,
+ },
+ [0x4B9]={
+ adobename="cheverticalstrokecyrillic",
+ category="ll",
+ contextname="cyrillicchevertstroke",
+ description="CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x447,
+ uccode=0x4B8,
+ unicodeslot=0x4B9,
+ },
+ [0x4BA]={
+ adobename="Shhacyrillic",
+ category="lu",
+ contextname="cyrillicSHHA",
+ description="CYRILLIC CAPITAL LETTER SHHA",
+ direction="l",
+ lccode=0x4BB,
+ linebreak="al",
+ unicodeslot=0x4BA,
+ },
+ [0x4BB]={
+ adobename="shhacyrillic",
+ category="ll",
+ contextname="cyrillicshha",
+ description="CYRILLIC SMALL LETTER SHHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x4BA,
+ unicodeslot=0x4BB,
+ },
+ [0x4BC]={
+ adobename="Cheabkhasiancyrillic",
+ category="lu",
+ contextname="cyrillicCHEabkhasian",
+ description="CYRILLIC CAPITAL LETTER ABKHASIAN CHE",
+ direction="l",
+ lccode=0x4BD,
+ linebreak="al",
+ unicodeslot=0x4BC,
+ },
+ [0x4BD]={
+ adobename="cheabkhasiancyrillic",
+ category="ll",
+ contextname="cyrilliccheabkhasian",
+ description="CYRILLIC SMALL LETTER ABKHASIAN CHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4BC,
+ unicodeslot=0x4BD,
+ },
+ [0x4BE]={
+ adobename="Chedescenderabkhasiancyrillic",
+ category="lu",
+ contextname="cyrillicCHEDCabkhasian",
+ description="CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER",
+ direction="l",
+ lccode=0x4BF,
+ linebreak="al",
+ unicodeslot=0x4BE,
+ },
+ [0x4BF]={
+ adobename="chedescenderabkhasiancyrillic",
+ category="ll",
+ contextname="cyrillicchedcabkhasian",
+ description="CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ uccode=0x4BE,
+ unicodeslot=0x4BF,
+ },
+ [0x4C0]={
+ adobename="palochkacyrillic",
+ category="lu",
+ contextname="cyrillicPALOCHKA",
+ description="CYRILLIC LETTER PALOCHKA",
+ direction="l",
+ lccode=0x4CF,
+ linebreak="al",
+ unicodeslot=0x4C0,
+ },
+ [0x4C1]={
+ adobename="Zhebrevecyrillic",
+ category="lu",
+ contextname="cyrillicZHEbreve",
+ description="CYRILLIC CAPITAL LETTER ZHE WITH BREVE",
+ direction="l",
+ lccode=0x4C2,
+ linebreak="al",
+ shcode=0x416,
+ specials={ "char", 0x416, 0x306 },
+ unicodeslot=0x4C1,
+ },
+ [0x4C2]={
+ adobename="zhebrevecyrillic",
+ category="ll",
+ contextname="cyrilliczhebreve",
+ description="CYRILLIC SMALL LETTER ZHE WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x436,
+ specials={ "char", 0x436, 0x306 },
+ uccode=0x4C1,
+ unicodeslot=0x4C2,
+ },
+ [0x4C3]={
+ adobename="Kahookcyrillic",
+ category="lu",
+ contextname="cyrillicKAhook",
+ description="CYRILLIC CAPITAL LETTER KA WITH HOOK",
+ direction="l",
+ lccode=0x4C4,
+ linebreak="al",
+ shcode=0x41A,
+ unicodeslot=0x4C3,
+ },
+ [0x4C4]={
+ adobename="kahookcyrillic",
+ category="ll",
+ contextname="cyrillickahook",
+ description="CYRILLIC SMALL LETTER KA WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x43A,
+ uccode=0x4C3,
+ unicodeslot=0x4C4,
+ },
+ [0x4C5]={
+ category="lu",
+ contextname="cyrillicELtail",
+ description="CYRILLIC CAPITAL LETTER EL WITH TAIL",
+ direction="l",
+ lccode=0x4C6,
+ linebreak="al",
+ shcode=0x41B,
+ unicodeslot=0x4C5,
+ },
+ [0x4C6]={
+ category="ll",
+ contextname="cyrilliceltail",
+ description="CYRILLIC SMALL LETTER EL WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x43B,
+ uccode=0x4C5,
+ unicodeslot=0x4C6,
+ },
+ [0x4C7]={
+ adobename="Enhookcyrillic",
+ category="lu",
+ contextname="cyrillicENhook",
+ description="CYRILLIC CAPITAL LETTER EN WITH HOOK",
+ direction="l",
+ lccode=0x4C8,
+ linebreak="al",
+ shcode=0x41D,
+ unicodeslot=0x4C7,
+ },
+ [0x4C8]={
+ adobename="enhookcyrillic",
+ category="ll",
+ contextname="cyrillicenhook",
+ description="CYRILLIC SMALL LETTER EN WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x43D,
+ uccode=0x4C7,
+ unicodeslot=0x4C8,
+ },
+ [0x4C9]={
+ category="lu",
+ contextname="cyrillicENtail",
+ description="CYRILLIC CAPITAL LETTER EN WITH TAIL",
+ direction="l",
+ lccode=0x4CA,
+ linebreak="al",
+ shcode=0x41D,
+ unicodeslot=0x4C9,
+ },
+ [0x4CA]={
+ category="ll",
+ contextname="cyrillicentail",
+ description="CYRILLIC SMALL LETTER EN WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x43D,
+ uccode=0x4C9,
+ unicodeslot=0x4CA,
+ },
+ [0x4CB]={
+ adobename="Chekhakassiancyrillic",
+ category="lu",
+ contextname="cyrillicCHEkhakassian",
+ description="CYRILLIC CAPITAL LETTER KHAKASSIAN CHE",
+ direction="l",
+ lccode=0x4CC,
+ linebreak="al",
+ unicodeslot=0x4CB,
+ },
+ [0x4CC]={
+ adobename="chekhakassiancyrillic",
+ category="ll",
+ contextname="cyrillicchekhakassian",
+ description="CYRILLIC SMALL LETTER KHAKASSIAN CHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4CB,
+ unicodeslot=0x4CC,
+ },
+ [0x4CD]={
+ category="lu",
+ contextname="cyrillicEMtail",
+ description="CYRILLIC CAPITAL LETTER EM WITH TAIL",
+ direction="l",
+ lccode=0x4CE,
+ linebreak="al",
+ shcode=0x41C,
+ unicodeslot=0x4CD,
+ },
+ [0x4CE]={
+ category="ll",
+ contextname="cyrillicemtail",
+ description="CYRILLIC SMALL LETTER EM WITH TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x43C,
+ uccode=0x4CD,
+ unicodeslot=0x4CE,
+ },
+ [0x4CF]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER PALOCHKA",
+ direction="l",
+ linebreak="al",
+ uccode=0x4C0,
+ unicodeslot=0x4CF,
+ },
+ [0x4D0]={
+ adobename="Abrevecyrillic",
+ category="lu",
+ contextname="cyrillicAbreve",
+ description="CYRILLIC CAPITAL LETTER A WITH BREVE",
+ direction="l",
+ lccode=0x4D1,
+ linebreak="al",
+ shcode=0x410,
+ specials={ "char", 0x410, 0x306 },
+ unicodeslot=0x4D0,
+ },
+ [0x4D1]={
+ adobename="abrevecyrillic",
+ category="ll",
+ contextname="cyrillicabreve",
+ description="CYRILLIC SMALL LETTER A WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x430,
+ specials={ "char", 0x430, 0x306 },
+ uccode=0x4D0,
+ unicodeslot=0x4D1,
+ },
+ [0x4D2]={
+ adobename="Adieresiscyrillic",
+ category="lu",
+ contextname="cyrillicAdiaeresis",
+ description="CYRILLIC CAPITAL LETTER A WITH DIAERESIS",
+ direction="l",
+ lccode=0x4D3,
+ linebreak="al",
+ shcode=0x410,
+ specials={ "char", 0x410, 0x308 },
+ unicodeslot=0x4D2,
+ },
+ [0x4D3]={
+ adobename="adieresiscyrillic",
+ category="ll",
+ contextname="cyrillicadiaeresis",
+ description="CYRILLIC SMALL LETTER A WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x430,
+ specials={ "char", 0x430, 0x308 },
+ uccode=0x4D2,
+ unicodeslot=0x4D3,
+ },
+ [0x4D4]={
+ adobename="Aiecyrillic",
+ category="lu",
+ contextname="cyrillicAE",
+ description="CYRILLIC CAPITAL LIGATURE A IE",
+ direction="l",
+ lccode=0x4D5,
+ linebreak="al",
+ unicodeslot=0x4D4,
+ },
+ [0x4D5]={
+ adobename="aiecyrillic",
+ category="ll",
+ contextname="cyrillicae",
+ description="CYRILLIC SMALL LIGATURE A IE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4D4,
+ unicodeslot=0x4D5,
+ },
+ [0x4D6]={
+ adobename="Iebrevecyrillic",
+ category="lu",
+ contextname="cyrillicEbreve",
+ description="CYRILLIC CAPITAL LETTER IE WITH BREVE",
+ direction="l",
+ lccode=0x4D7,
+ linebreak="al",
+ shcode=0x415,
+ specials={ "char", 0x415, 0x306 },
+ unicodeslot=0x4D6,
+ },
+ [0x4D7]={
+ adobename="iebrevecyrillic",
+ category="ll",
+ contextname="cyrillicebreve",
+ description="CYRILLIC SMALL LETTER IE WITH BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x435,
+ specials={ "char", 0x435, 0x306 },
+ uccode=0x4D6,
+ unicodeslot=0x4D7,
+ },
+ [0x4D8]={
+ adobename="Schwacyrillic",
+ category="lu",
+ contextname="cyrillicSCHWA",
+ description="CYRILLIC CAPITAL LETTER SCHWA",
+ direction="l",
+ lccode=0x4D9,
+ linebreak="al",
+ unicodeslot=0x4D8,
+ },
+ [0x4D9]={
+ adobename="schwacyrillic",
+ category="ll",
+ contextname="cyrillicschwa",
+ description="CYRILLIC SMALL LETTER SCHWA",
+ direction="l",
+ linebreak="al",
+ uccode=0x4D8,
+ unicodeslot=0x4D9,
+ },
+ [0x4DA]={
+ adobename="Schwadieresiscyrillic",
+ category="lu",
+ contextname="cyrillicSCHWAdiaeresis",
+ description="CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS",
+ direction="l",
+ lccode=0x4DB,
+ linebreak="al",
+ shcode=0x4D8,
+ specials={ "char", 0x4D8, 0x308 },
+ unicodeslot=0x4DA,
+ },
+ [0x4DB]={
+ adobename="schwadieresiscyrillic",
+ category="ll",
+ contextname="cyrillicschwadiaeresis",
+ description="CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x4D9,
+ specials={ "char", 0x4D9, 0x308 },
+ uccode=0x4DA,
+ unicodeslot=0x4DB,
+ },
+ [0x4DC]={
+ adobename="Zhedieresiscyrillic",
+ category="lu",
+ contextname="cyrillicZHEdiaeresis",
+ description="CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS",
+ direction="l",
+ lccode=0x4DD,
+ linebreak="al",
+ shcode=0x416,
+ specials={ "char", 0x416, 0x308 },
+ unicodeslot=0x4DC,
+ },
+ [0x4DD]={
+ adobename="zhedieresiscyrillic",
+ category="ll",
+ contextname="cyrilliczhediaeresis",
+ description="CYRILLIC SMALL LETTER ZHE WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x436,
+ specials={ "char", 0x436, 0x308 },
+ uccode=0x4DC,
+ unicodeslot=0x4DD,
+ },
+ [0x4DE]={
+ adobename="Zedieresiscyrillic",
+ category="lu",
+ contextname="cyrillicZEdiaeresis",
+ description="CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS",
+ direction="l",
+ lccode=0x4DF,
+ linebreak="al",
+ shcode=0x417,
+ specials={ "char", 0x417, 0x308 },
+ unicodeslot=0x4DE,
+ },
+ [0x4DF]={
+ adobename="zedieresiscyrillic",
+ category="ll",
+ contextname="cyrilliczediaeresis",
+ description="CYRILLIC SMALL LETTER ZE WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x437,
+ specials={ "char", 0x437, 0x308 },
+ uccode=0x4DE,
+ unicodeslot=0x4DF,
+ },
+ [0x4E0]={
+ adobename="Dzeabkhasiancyrillic",
+ category="lu",
+ contextname="cyrillicDZEabkhasian",
+ description="CYRILLIC CAPITAL LETTER ABKHASIAN DZE",
+ direction="l",
+ lccode=0x4E1,
+ linebreak="al",
+ unicodeslot=0x4E0,
+ },
+ [0x4E1]={
+ adobename="dzeabkhasiancyrillic",
+ category="ll",
+ contextname="cyrillicdzeabkhasian",
+ description="CYRILLIC SMALL LETTER ABKHASIAN DZE",
+ direction="l",
+ linebreak="al",
+ uccode=0x4E0,
+ unicodeslot=0x4E1,
+ },
+ [0x4E2]={
+ adobename="Imacroncyrillic",
+ category="lu",
+ contextname="cyrillicImacron",
+ description="CYRILLIC CAPITAL LETTER I WITH MACRON",
+ direction="l",
+ lccode=0x4E3,
+ linebreak="al",
+ shcode=0x418,
+ specials={ "char", 0x418, 0x304 },
+ unicodeslot=0x4E2,
+ },
+ [0x4E3]={
+ adobename="imacroncyrillic",
+ category="ll",
+ contextname="cyrillicimacron",
+ description="CYRILLIC SMALL LETTER I WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x438,
+ specials={ "char", 0x438, 0x304 },
+ uccode=0x4E2,
+ unicodeslot=0x4E3,
+ },
+ [0x4E4]={
+ adobename="Idieresiscyrillic",
+ category="lu",
+ contextname="cyrillicIdiaeresis",
+ description="CYRILLIC CAPITAL LETTER I WITH DIAERESIS",
+ direction="l",
+ lccode=0x4E5,
+ linebreak="al",
+ shcode=0x418,
+ specials={ "char", 0x418, 0x308 },
+ unicodeslot=0x4E4,
+ },
+ [0x4E5]={
+ adobename="idieresiscyrillic",
+ category="ll",
+ contextname="cyrillicidiaeresis",
+ description="CYRILLIC SMALL LETTER I WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x438,
+ specials={ "char", 0x438, 0x308 },
+ uccode=0x4E4,
+ unicodeslot=0x4E5,
+ },
+ [0x4E6]={
+ adobename="Odieresiscyrillic",
+ category="lu",
+ contextname="cyrillicOdiaeresis",
+ description="CYRILLIC CAPITAL LETTER O WITH DIAERESIS",
+ direction="l",
+ lccode=0x4E7,
+ linebreak="al",
+ shcode=0x41E,
+ specials={ "char", 0x41E, 0x308 },
+ unicodeslot=0x4E6,
+ },
+ [0x4E7]={
+ adobename="odieresiscyrillic",
+ category="ll",
+ contextname="cyrillicodiaeresis",
+ description="CYRILLIC SMALL LETTER O WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x43E,
+ specials={ "char", 0x43E, 0x308 },
+ uccode=0x4E6,
+ unicodeslot=0x4E7,
+ },
+ [0x4E8]={
+ adobename="Obarredcyrillic",
+ category="lu",
+ contextname="cyrillicObarred",
+ description="CYRILLIC CAPITAL LETTER BARRED O",
+ direction="l",
+ lccode=0x4E9,
+ linebreak="al",
+ unicodeslot=0x4E8,
+ },
+ [0x4E9]={
+ adobename="obarredcyrillic",
+ category="ll",
+ contextname="cyrillicobarred",
+ description="CYRILLIC SMALL LETTER BARRED O",
+ direction="l",
+ linebreak="al",
+ uccode=0x4E8,
+ unicodeslot=0x4E9,
+ },
+ [0x4EA]={
+ adobename="Obarreddieresiscyrillic",
+ category="lu",
+ contextname="cyrillicObarreddiaeresis",
+ description="CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS",
+ direction="l",
+ lccode=0x4EB,
+ linebreak="al",
+ specials={ "char", 0x4E8, 0x308 },
+ unicodeslot=0x4EA,
+ },
+ [0x4EB]={
+ adobename="obarreddieresiscyrillic",
+ category="ll",
+ contextname="cyrillicobarreddiaeresis",
+ description="CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x4E9, 0x308 },
+ uccode=0x4EA,
+ unicodeslot=0x4EB,
+ },
+ [0x4EC]={
+ category="lu",
+ contextname="cyrillicEdiaeresis",
+ description="CYRILLIC CAPITAL LETTER E WITH DIAERESIS",
+ direction="l",
+ lccode=0x4ED,
+ linebreak="al",
+ shcode=0x42D,
+ specials={ "char", 0x42D, 0x308 },
+ unicodeslot=0x4EC,
+ },
+ [0x4ED]={
+ category="ll",
+ contextname="cyrillicediaeresis",
+ description="CYRILLIC SMALL LETTER E WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x44D,
+ specials={ "char", 0x44D, 0x308 },
+ uccode=0x4EC,
+ unicodeslot=0x4ED,
+ },
+ [0x4EE]={
+ adobename="Umacroncyrillic",
+ category="lu",
+ contextname="cyrillicUmacron",
+ description="CYRILLIC CAPITAL LETTER U WITH MACRON",
+ direction="l",
+ lccode=0x4EF,
+ linebreak="al",
+ shcode=0x423,
+ specials={ "char", 0x423, 0x304 },
+ unicodeslot=0x4EE,
+ },
+ [0x4EF]={
+ adobename="umacroncyrillic",
+ category="ll",
+ contextname="cyrillicumacron",
+ description="CYRILLIC SMALL LETTER U WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x443,
+ specials={ "char", 0x443, 0x304 },
+ uccode=0x4EE,
+ unicodeslot=0x4EF,
+ },
+ [0x4F0]={
+ adobename="Udieresiscyrillic",
+ category="lu",
+ contextname="cyrillicUdiaeresis",
+ description="CYRILLIC CAPITAL LETTER U WITH DIAERESIS",
+ direction="l",
+ lccode=0x4F1,
+ linebreak="al",
+ shcode=0x423,
+ specials={ "char", 0x423, 0x308 },
+ unicodeslot=0x4F0,
+ },
+ [0x4F1]={
+ adobename="udieresiscyrillic",
+ category="ll",
+ contextname="cyrillicudiaeresis",
+ description="CYRILLIC SMALL LETTER U WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x443,
+ specials={ "char", 0x443, 0x308 },
+ uccode=0x4F0,
+ unicodeslot=0x4F1,
+ },
+ [0x4F2]={
+ adobename="Uhungarumlautcyrillic",
+ category="lu",
+ contextname="cyrillicUdoubleacute",
+ description="CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE",
+ direction="l",
+ lccode=0x4F3,
+ linebreak="al",
+ shcode=0x423,
+ specials={ "char", 0x423, 0x30B },
+ unicodeslot=0x4F2,
+ },
+ [0x4F3]={
+ adobename="uhungarumlautcyrillic",
+ category="ll",
+ contextname="cyrillicudoubleacute",
+ description="CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x443,
+ specials={ "char", 0x443, 0x30B },
+ uccode=0x4F2,
+ unicodeslot=0x4F3,
+ },
+ [0x4F4]={
+ adobename="Chedieresiscyrillic",
+ category="lu",
+ contextname="cyrillicCHEdiaeresis",
+ description="CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS",
+ direction="l",
+ lccode=0x4F5,
+ linebreak="al",
+ shcode=0x427,
+ specials={ "char", 0x427, 0x308 },
+ unicodeslot=0x4F4,
+ },
+ [0x4F5]={
+ adobename="chedieresiscyrillic",
+ category="ll",
+ contextname="cyrillicchediaeresis",
+ description="CYRILLIC SMALL LETTER CHE WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x447,
+ specials={ "char", 0x447, 0x308 },
+ uccode=0x4F4,
+ unicodeslot=0x4F5,
+ },
+ [0x4F6]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER GHE WITH DESCENDER",
+ direction="l",
+ lccode=0x4F7,
+ linebreak="al",
+ shcode=0x413,
+ unicodeslot=0x4F6,
+ },
+ [0x4F7]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER GHE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x433,
+ uccode=0x4F6,
+ unicodeslot=0x4F7,
+ },
+ [0x4F8]={
+ adobename="Yerudieresiscyrillic",
+ category="lu",
+ contextname="cyrillicYERUdiaeresis",
+ description="CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS",
+ direction="l",
+ lccode=0x4F9,
+ linebreak="al",
+ shcode=0x42B,
+ specials={ "char", 0x42B, 0x308 },
+ unicodeslot=0x4F8,
+ },
+ [0x4F9]={
+ adobename="yerudieresiscyrillic",
+ category="ll",
+ contextname="cyrillicyerudiaeresis",
+ description="CYRILLIC SMALL LETTER YERU WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x44B,
+ specials={ "char", 0x44B, 0x308 },
+ uccode=0x4F8,
+ unicodeslot=0x4F9,
+ },
+ [0x4FA]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK",
+ direction="l",
+ lccode=0x4FB,
+ linebreak="al",
+ shcode=0x413,
+ unicodeslot=0x4FA,
+ },
+ [0x4FB]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x433,
+ uccode=0x4FA,
+ unicodeslot=0x4FB,
+ },
+ [0x4FC]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER HA WITH HOOK",
+ direction="l",
+ lccode=0x4FD,
+ linebreak="al",
+ shcode=0x425,
+ unicodeslot=0x4FC,
+ },
+ [0x4FD]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER HA WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x445,
+ uccode=0x4FC,
+ unicodeslot=0x4FD,
+ },
+ [0x4FE]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER HA WITH STROKE",
+ direction="l",
+ lccode=0x4FF,
+ linebreak="al",
+ shcode=0x425,
+ unicodeslot=0x4FE,
+ },
+ [0x4FF]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER HA WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x445,
+ uccode=0x4FE,
+ unicodeslot=0x4FF,
+ },
+ [0x500]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI DE",
+ direction="l",
+ lccode=0x501,
+ linebreak="al",
+ unicodeslot=0x500,
+ },
+ [0x501]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI DE",
+ direction="l",
+ linebreak="al",
+ uccode=0x500,
+ unicodeslot=0x501,
+ },
+ [0x502]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI DJE",
+ direction="l",
+ lccode=0x503,
+ linebreak="al",
+ unicodeslot=0x502,
+ },
+ [0x503]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI DJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x502,
+ unicodeslot=0x503,
+ },
+ [0x504]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI ZJE",
+ direction="l",
+ lccode=0x505,
+ linebreak="al",
+ unicodeslot=0x504,
+ },
+ [0x505]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI ZJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x504,
+ unicodeslot=0x505,
+ },
+ [0x506]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI DZJE",
+ direction="l",
+ lccode=0x507,
+ linebreak="al",
+ unicodeslot=0x506,
+ },
+ [0x507]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI DZJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x506,
+ unicodeslot=0x507,
+ },
+ [0x508]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI LJE",
+ direction="l",
+ lccode=0x509,
+ linebreak="al",
+ unicodeslot=0x508,
+ },
+ [0x509]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI LJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x508,
+ unicodeslot=0x509,
+ },
+ [0x50A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI NJE",
+ direction="l",
+ lccode=0x50B,
+ linebreak="al",
+ unicodeslot=0x50A,
+ },
+ [0x50B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI NJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x50A,
+ unicodeslot=0x50B,
+ },
+ [0x50C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI SJE",
+ direction="l",
+ lccode=0x50D,
+ linebreak="al",
+ unicodeslot=0x50C,
+ },
+ [0x50D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI SJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x50C,
+ unicodeslot=0x50D,
+ },
+ [0x50E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER KOMI TJE",
+ direction="l",
+ lccode=0x50F,
+ linebreak="al",
+ unicodeslot=0x50E,
+ },
+ [0x50F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER KOMI TJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x50E,
+ unicodeslot=0x50F,
+ },
+ [0x510]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED ZE",
+ direction="l",
+ lccode=0x511,
+ linebreak="al",
+ unicodeslot=0x510,
+ },
+ [0x511]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED ZE",
+ direction="l",
+ linebreak="al",
+ uccode=0x510,
+ unicodeslot=0x511,
+ },
+ [0x512]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EL WITH HOOK",
+ direction="l",
+ lccode=0x513,
+ linebreak="al",
+ shcode=0x41B,
+ unicodeslot=0x512,
+ },
+ [0x513]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EL WITH HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x43B,
+ uccode=0x512,
+ unicodeslot=0x513,
+ },
+ [0x514]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x514,
+ },
+ [0x515]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x515,
+ },
+ [0x516]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER RHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x516,
+ },
+ [0x517]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER RHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x517,
+ },
+ [0x518]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x518,
+ },
+ [0x519]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x519,
+ },
+ [0x51A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51A,
+ },
+ [0x51B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51B,
+ },
+ [0x51C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51C,
+ },
+ [0x51D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51D,
+ },
+ [0x51E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ALEUT KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51E,
+ },
+ [0x51F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ALEUT KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x51F,
+ },
+ [0x520]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x520,
+ },
+ [0x521]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x521,
+ },
+ [0x522]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x522,
+ },
+ [0x523]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x523,
+ },
+ [0x524]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER PE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x524,
+ },
+ [0x525]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER PE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x525,
+ },
+ [0x526]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x526,
+ },
+ [0x527]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SHHA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x527,
+ },
+ [0x528]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x528,
+ },
+ [0x529]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EN WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x529,
+ },
+ [0x52A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52A,
+ },
+ [0x52B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52B,
+ },
+ [0x52C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52C,
+ },
+ [0x52D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52D,
+ },
+ [0x52E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EL WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52E,
+ },
+ [0x52F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EL WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x52F,
+ },
+ [0x531]={
+ adobename="Aybarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER AYB",
+ direction="l",
+ lccode=0x561,
+ linebreak="al",
+ unicodeslot=0x531,
+ },
+ [0x532]={
+ adobename="Benarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER BEN",
+ direction="l",
+ lccode=0x562,
+ linebreak="al",
+ unicodeslot=0x532,
+ },
+ [0x533]={
+ adobename="Gimarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER GIM",
+ direction="l",
+ lccode=0x563,
+ linebreak="al",
+ unicodeslot=0x533,
+ },
+ [0x534]={
+ adobename="Daarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER DA",
+ direction="l",
+ lccode=0x564,
+ linebreak="al",
+ unicodeslot=0x534,
+ },
+ [0x535]={
+ adobename="Echarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER ECH",
+ direction="l",
+ lccode=0x565,
+ linebreak="al",
+ unicodeslot=0x535,
+ },
+ [0x536]={
+ adobename="Zaarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER ZA",
+ direction="l",
+ lccode=0x566,
+ linebreak="al",
+ unicodeslot=0x536,
+ },
+ [0x537]={
+ adobename="Eharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER EH",
+ direction="l",
+ lccode=0x567,
+ linebreak="al",
+ unicodeslot=0x537,
+ },
+ [0x538]={
+ adobename="Etarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER ET",
+ direction="l",
+ lccode=0x568,
+ linebreak="al",
+ unicodeslot=0x538,
+ },
+ [0x539]={
+ adobename="Toarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER TO",
+ direction="l",
+ lccode=0x569,
+ linebreak="al",
+ unicodeslot=0x539,
+ },
+ [0x53A]={
+ adobename="Zhearmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER ZHE",
+ direction="l",
+ lccode=0x56A,
+ linebreak="al",
+ unicodeslot=0x53A,
+ },
+ [0x53B]={
+ adobename="Iniarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER INI",
+ direction="l",
+ lccode=0x56B,
+ linebreak="al",
+ unicodeslot=0x53B,
+ },
+ [0x53C]={
+ adobename="Liwnarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER LIWN",
+ direction="l",
+ lccode=0x56C,
+ linebreak="al",
+ unicodeslot=0x53C,
+ },
+ [0x53D]={
+ adobename="Xeharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER XEH",
+ direction="l",
+ lccode=0x56D,
+ linebreak="al",
+ unicodeslot=0x53D,
+ },
+ [0x53E]={
+ adobename="Caarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER CA",
+ direction="l",
+ lccode=0x56E,
+ linebreak="al",
+ unicodeslot=0x53E,
+ },
+ [0x53F]={
+ adobename="Kenarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER KEN",
+ direction="l",
+ lccode=0x56F,
+ linebreak="al",
+ unicodeslot=0x53F,
+ },
+ [0x540]={
+ adobename="Hoarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER HO",
+ direction="l",
+ lccode=0x570,
+ linebreak="al",
+ unicodeslot=0x540,
+ },
+ [0x541]={
+ adobename="Jaarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER JA",
+ direction="l",
+ lccode=0x571,
+ linebreak="al",
+ unicodeslot=0x541,
+ },
+ [0x542]={
+ adobename="Ghadarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER GHAD",
+ direction="l",
+ lccode=0x572,
+ linebreak="al",
+ unicodeslot=0x542,
+ },
+ [0x543]={
+ adobename="Cheharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER CHEH",
+ direction="l",
+ lccode=0x573,
+ linebreak="al",
+ unicodeslot=0x543,
+ },
+ [0x544]={
+ adobename="Menarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER MEN",
+ direction="l",
+ lccode=0x574,
+ linebreak="al",
+ unicodeslot=0x544,
+ },
+ [0x545]={
+ adobename="Yiarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER YI",
+ direction="l",
+ lccode=0x575,
+ linebreak="al",
+ unicodeslot=0x545,
+ },
+ [0x546]={
+ adobename="Nowarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER NOW",
+ direction="l",
+ lccode=0x576,
+ linebreak="al",
+ unicodeslot=0x546,
+ },
+ [0x547]={
+ adobename="Shaarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER SHA",
+ direction="l",
+ lccode=0x577,
+ linebreak="al",
+ unicodeslot=0x547,
+ },
+ [0x548]={
+ adobename="Voarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER VO",
+ direction="l",
+ lccode=0x578,
+ linebreak="al",
+ unicodeslot=0x548,
+ },
+ [0x549]={
+ adobename="Chaarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER CHA",
+ direction="l",
+ lccode=0x579,
+ linebreak="al",
+ unicodeslot=0x549,
+ },
+ [0x54A]={
+ adobename="Peharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER PEH",
+ direction="l",
+ lccode=0x57A,
+ linebreak="al",
+ unicodeslot=0x54A,
+ },
+ [0x54B]={
+ adobename="Jheharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER JHEH",
+ direction="l",
+ lccode=0x57B,
+ linebreak="al",
+ unicodeslot=0x54B,
+ },
+ [0x54C]={
+ adobename="Raarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER RA",
+ direction="l",
+ lccode=0x57C,
+ linebreak="al",
+ unicodeslot=0x54C,
+ },
+ [0x54D]={
+ adobename="Seharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER SEH",
+ direction="l",
+ lccode=0x57D,
+ linebreak="al",
+ unicodeslot=0x54D,
+ },
+ [0x54E]={
+ adobename="Vewarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER VEW",
+ direction="l",
+ lccode=0x57E,
+ linebreak="al",
+ unicodeslot=0x54E,
+ },
+ [0x54F]={
+ adobename="Tiwnarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER TIWN",
+ direction="l",
+ lccode=0x57F,
+ linebreak="al",
+ unicodeslot=0x54F,
+ },
+ [0x550]={
+ adobename="Reharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER REH",
+ direction="l",
+ lccode=0x580,
+ linebreak="al",
+ unicodeslot=0x550,
+ },
+ [0x551]={
+ adobename="Coarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER CO",
+ direction="l",
+ lccode=0x581,
+ linebreak="al",
+ unicodeslot=0x551,
+ },
+ [0x552]={
+ adobename="Yiwnarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER YIWN",
+ direction="l",
+ lccode=0x582,
+ linebreak="al",
+ unicodeslot=0x552,
+ },
+ [0x553]={
+ adobename="Piwrarmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER PIWR",
+ direction="l",
+ lccode=0x583,
+ linebreak="al",
+ unicodeslot=0x553,
+ },
+ [0x554]={
+ adobename="Keharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER KEH",
+ direction="l",
+ lccode=0x584,
+ linebreak="al",
+ unicodeslot=0x554,
+ },
+ [0x555]={
+ adobename="Oharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER OH",
+ direction="l",
+ lccode=0x585,
+ linebreak="al",
+ unicodeslot=0x555,
+ },
+ [0x556]={
+ adobename="Feharmenian",
+ category="lu",
+ description="ARMENIAN CAPITAL LETTER FEH",
+ direction="l",
+ lccode=0x586,
+ linebreak="al",
+ unicodeslot=0x556,
+ },
+ [0x559]={
+ adobename="ringhalfleftarmenian",
+ category="lm",
+ description="ARMENIAN MODIFIER LETTER LEFT HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x559,
+ },
+ [0x55A]={
+ adobename="apostrophearmenian",
+ category="po",
+ description="ARMENIAN APOSTROPHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55A,
+ },
+ [0x55B]={
+ adobename="emphasismarkarmenian",
+ category="po",
+ description="ARMENIAN EMPHASIS MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55B,
+ },
+ [0x55C]={
+ adobename="exclamarmenian",
+ category="po",
+ description="ARMENIAN EXCLAMATION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55C,
+ },
+ [0x55D]={
+ adobename="commaarmenian",
+ category="po",
+ description="ARMENIAN COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55D,
+ },
+ [0x55E]={
+ adobename="questionarmenian",
+ category="po",
+ description="ARMENIAN QUESTION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55E,
+ },
+ [0x55F]={
+ adobename="abbreviationmarkarmenian",
+ category="po",
+ description="ARMENIAN ABBREVIATION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x55F,
+ },
+ [0x561]={
+ adobename="aybarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER AYB",
+ direction="l",
+ linebreak="al",
+ uccode=0x531,
+ unicodeslot=0x561,
+ },
+ [0x562]={
+ adobename="benarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER BEN",
+ direction="l",
+ linebreak="al",
+ uccode=0x532,
+ unicodeslot=0x562,
+ },
+ [0x563]={
+ adobename="gimarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER GIM",
+ direction="l",
+ linebreak="al",
+ uccode=0x533,
+ unicodeslot=0x563,
+ },
+ [0x564]={
+ adobename="daarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER DA",
+ direction="l",
+ linebreak="al",
+ uccode=0x534,
+ unicodeslot=0x564,
+ },
+ [0x565]={
+ adobename="echarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER ECH",
+ direction="l",
+ linebreak="al",
+ uccode=0x535,
+ unicodeslot=0x565,
+ },
+ [0x566]={
+ adobename="zaarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER ZA",
+ direction="l",
+ linebreak="al",
+ uccode=0x536,
+ unicodeslot=0x566,
+ },
+ [0x567]={
+ adobename="eharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER EH",
+ direction="l",
+ linebreak="al",
+ uccode=0x537,
+ unicodeslot=0x567,
+ },
+ [0x568]={
+ adobename="etarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER ET",
+ direction="l",
+ linebreak="al",
+ uccode=0x538,
+ unicodeslot=0x568,
+ },
+ [0x569]={
+ adobename="toarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER TO",
+ direction="l",
+ linebreak="al",
+ uccode=0x539,
+ unicodeslot=0x569,
+ },
+ [0x56A]={
+ adobename="zhearmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER ZHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x53A,
+ unicodeslot=0x56A,
+ },
+ [0x56B]={
+ adobename="iniarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER INI",
+ direction="l",
+ linebreak="al",
+ uccode=0x53B,
+ unicodeslot=0x56B,
+ },
+ [0x56C]={
+ adobename="liwnarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER LIWN",
+ direction="l",
+ linebreak="al",
+ uccode=0x53C,
+ unicodeslot=0x56C,
+ },
+ [0x56D]={
+ adobename="xeharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER XEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x53D,
+ unicodeslot=0x56D,
+ },
+ [0x56E]={
+ adobename="caarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER CA",
+ direction="l",
+ linebreak="al",
+ uccode=0x53E,
+ unicodeslot=0x56E,
+ },
+ [0x56F]={
+ adobename="kenarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER KEN",
+ direction="l",
+ linebreak="al",
+ uccode=0x53F,
+ unicodeslot=0x56F,
+ },
+ [0x570]={
+ adobename="hoarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER HO",
+ direction="l",
+ linebreak="al",
+ uccode=0x540,
+ unicodeslot=0x570,
+ },
+ [0x571]={
+ adobename="jaarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER JA",
+ direction="l",
+ linebreak="al",
+ uccode=0x541,
+ unicodeslot=0x571,
+ },
+ [0x572]={
+ adobename="ghadarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER GHAD",
+ direction="l",
+ linebreak="al",
+ uccode=0x542,
+ unicodeslot=0x572,
+ },
+ [0x573]={
+ adobename="cheharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER CHEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x543,
+ unicodeslot=0x573,
+ },
+ [0x574]={
+ adobename="menarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER MEN",
+ direction="l",
+ linebreak="al",
+ uccode=0x544,
+ unicodeslot=0x574,
+ },
+ [0x575]={
+ adobename="yiarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER YI",
+ direction="l",
+ linebreak="al",
+ uccode=0x545,
+ unicodeslot=0x575,
+ },
+ [0x576]={
+ adobename="nowarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER NOW",
+ direction="l",
+ linebreak="al",
+ uccode=0x546,
+ unicodeslot=0x576,
+ },
+ [0x577]={
+ adobename="shaarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER SHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x547,
+ unicodeslot=0x577,
+ },
+ [0x578]={
+ adobename="voarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER VO",
+ direction="l",
+ linebreak="al",
+ uccode=0x548,
+ unicodeslot=0x578,
+ },
+ [0x579]={
+ adobename="chaarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER CHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x549,
+ unicodeslot=0x579,
+ },
+ [0x57A]={
+ adobename="peharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER PEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x54A,
+ unicodeslot=0x57A,
+ },
+ [0x57B]={
+ adobename="jheharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER JHEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x54B,
+ unicodeslot=0x57B,
+ },
+ [0x57C]={
+ adobename="raarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER RA",
+ direction="l",
+ linebreak="al",
+ uccode=0x54C,
+ unicodeslot=0x57C,
+ },
+ [0x57D]={
+ adobename="seharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER SEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x54D,
+ unicodeslot=0x57D,
+ },
+ [0x57E]={
+ adobename="vewarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER VEW",
+ direction="l",
+ linebreak="al",
+ uccode=0x54E,
+ unicodeslot=0x57E,
+ },
+ [0x57F]={
+ adobename="tiwnarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER TIWN",
+ direction="l",
+ linebreak="al",
+ uccode=0x54F,
+ unicodeslot=0x57F,
+ },
+ [0x580]={
+ adobename="reharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER REH",
+ direction="l",
+ linebreak="al",
+ uccode=0x550,
+ unicodeslot=0x580,
+ },
+ [0x581]={
+ adobename="coarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER CO",
+ direction="l",
+ linebreak="al",
+ uccode=0x551,
+ unicodeslot=0x581,
+ },
+ [0x582]={
+ adobename="yiwnarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER YIWN",
+ direction="l",
+ linebreak="al",
+ uccode=0x552,
+ unicodeslot=0x582,
+ },
+ [0x583]={
+ adobename="piwrarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER PIWR",
+ direction="l",
+ linebreak="al",
+ uccode=0x553,
+ unicodeslot=0x583,
+ },
+ [0x584]={
+ adobename="keharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER KEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x554,
+ unicodeslot=0x584,
+ },
+ [0x585]={
+ adobename="oharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER OH",
+ direction="l",
+ linebreak="al",
+ uccode=0x555,
+ unicodeslot=0x585,
+ },
+ [0x586]={
+ adobename="feharmenian",
+ category="ll",
+ description="ARMENIAN SMALL LETTER FEH",
+ direction="l",
+ linebreak="al",
+ uccode=0x556,
+ unicodeslot=0x586,
+ },
+ [0x587]={
+ adobename="echyiwnarmenian",
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE ECH YIWN",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x565, 0x582 },
+ unicodeslot=0x587,
+ },
+ [0x589]={
+ adobename="periodarmenian",
+ category="po",
+ description="ARMENIAN FULL STOP",
+ direction="l",
+ linebreak="is",
+ unicodeslot=0x589,
+ },
+ [0x58A]={
+ category="pd",
+ description="ARMENIAN HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x58A,
+ },
+ [0x58D]={
+ category="so",
+ description="RIGHT-FACING ARMENIAN ETERNITY SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x58D,
+ },
+ [0x58E]={
+ category="so",
+ description="LEFT-FACING ARMENIAN ETERNITY SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x58E,
+ },
+ [0x58F]={
+ category="sc",
+ description="ARMENIAN DRAM SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x58F,
+ },
+ [0x591]={
+ adobename="etnahtalefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT ETNAHTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x591,
+ },
+ [0x592]={
+ adobename="segoltahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT SEGOL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x592,
+ },
+ [0x593]={
+ adobename="shalshelethebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT SHALSHELET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x593,
+ },
+ [0x594]={
+ adobename="zaqefqatanhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT ZAQEF QATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x594,
+ },
+ [0x595]={
+ adobename="zaqefgadolhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT ZAQEF GADOL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x595,
+ },
+ [0x596]={
+ adobename="tipehalefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT TIPEHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x596,
+ },
+ [0x597]={
+ adobename="reviamugrashhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT REVIA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x597,
+ },
+ [0x598]={
+ adobename="zarqahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT ZARQA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x598,
+ },
+ [0x599]={
+ adobename="pashtahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT PASHTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x599,
+ },
+ [0x59A]={
+ adobename="yetivhebrew",
+ category="mn",
+ combining=0xDE,
+ description="HEBREW ACCENT YETIV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59A,
+ },
+ [0x59B]={
+ adobename="tevirlefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT TEVIR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59B,
+ },
+ [0x59C]={
+ adobename="gereshaccenthebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT GERESH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59C,
+ },
+ [0x59D]={
+ adobename="gereshmuqdamhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT GERESH MUQDAM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59D,
+ },
+ [0x59E]={
+ adobename="gershayimaccenthebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT GERSHAYIM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59E,
+ },
+ [0x59F]={
+ adobename="qarneyparahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT QARNEY PARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x59F,
+ },
+ [0x5A0]={
+ adobename="telishagedolahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT TELISHA GEDOLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A0,
+ },
+ [0x5A1]={
+ adobename="pazerhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT PAZER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A1,
+ },
+ [0x5A2]={
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT ATNAH HAFUKH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A2,
+ },
+ [0x5A3]={
+ adobename="munahlefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT MUNAH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A3,
+ },
+ [0x5A4]={
+ adobename="mahapakhlefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT MAHAPAKH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A4,
+ },
+ [0x5A5]={
+ adobename="merkhalefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT MERKHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A5,
+ },
+ [0x5A6]={
+ adobename="merkhakefulalefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT MERKHA KEFULA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A6,
+ },
+ [0x5A7]={
+ adobename="dargalefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT DARGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A7,
+ },
+ [0x5A8]={
+ adobename="qadmahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT QADMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A8,
+ },
+ [0x5A9]={
+ adobename="telishaqetanahebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT TELISHA QETANA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5A9,
+ },
+ [0x5AA]={
+ adobename="yerahbenyomolefthebrew",
+ category="mn",
+ combining=0xDC,
+ description="HEBREW ACCENT YERAH BEN YOMO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AA,
+ },
+ [0x5AB]={
+ adobename="olehebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT OLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AB,
+ },
+ [0x5AC]={
+ adobename="iluyhebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW ACCENT ILUY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AC,
+ },
+ [0x5AD]={
+ adobename="dehihebrew",
+ category="mn",
+ combining=0xDE,
+ description="HEBREW ACCENT DEHI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AD,
+ },
+ [0x5AE]={
+ adobename="zinorhebrew",
+ category="mn",
+ combining=0xE4,
+ description="HEBREW ACCENT ZINOR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AE,
+ },
+ [0x5AF]={
+ adobename="masoracirclehebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW MARK MASORA CIRCLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5AF,
+ },
+ [0x5B0]={
+ adobename="shevawidehebrew",
+ category="mn",
+ combining=0xA,
+ description="HEBREW POINT SHEVA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B0,
+ },
+ [0x5B1]={
+ adobename="hatafsegolwidehebrew",
+ category="mn",
+ combining=0xB,
+ description="HEBREW POINT HATAF SEGOL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B1,
+ },
+ [0x5B2]={
+ adobename="hatafpatahwidehebrew",
+ category="mn",
+ combining=0xC,
+ description="HEBREW POINT HATAF PATAH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B2,
+ },
+ [0x5B3]={
+ adobename="hatafqamatswidehebrew",
+ category="mn",
+ combining=0xD,
+ description="HEBREW POINT HATAF QAMATS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B3,
+ },
+ [0x5B4]={
+ adobename="hiriqwidehebrew",
+ category="mn",
+ combining=0xE,
+ description="HEBREW POINT HIRIQ",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B4,
+ },
+ [0x5B5]={
+ adobename="tserewidehebrew",
+ category="mn",
+ combining=0xF,
+ description="HEBREW POINT TSERE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B5,
+ },
+ [0x5B6]={
+ adobename="segolwidehebrew",
+ category="mn",
+ combining=0x10,
+ description="HEBREW POINT SEGOL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B6,
+ },
+ [0x5B7]={
+ adobename="patahwidehebrew",
+ category="mn",
+ combining=0x11,
+ description="HEBREW POINT PATAH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B7,
+ },
+ [0x5B8]={
+ adobename="qamatswidehebrew",
+ category="mn",
+ combining=0x12,
+ description="HEBREW POINT QAMATS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B8,
+ },
+ [0x5B9]={
+ adobename="holamwidehebrew",
+ category="mn",
+ combining=0x13,
+ description="HEBREW POINT HOLAM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5B9,
+ },
+ [0x5BA]={
+ category="mn",
+ combining=0x13,
+ description="HEBREW POINT HOLAM HASER FOR VAV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5BA,
+ },
+ [0x5BB]={
+ adobename="qubutswidehebrew",
+ category="mn",
+ combining=0x14,
+ description="HEBREW POINT QUBUTS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5BB,
+ },
+ [0x5BC]={
+ adobename="dageshhebrew",
+ category="mn",
+ combining=0x15,
+ description="HEBREW POINT DAGESH OR MAPIQ",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5BC,
+ },
+ [0x5BD]={
+ adobename="siluqlefthebrew",
+ category="mn",
+ combining=0x16,
+ description="HEBREW POINT METEG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5BD,
+ },
+ [0x5BE]={
+ adobename="maqafhebrew",
+ category="po",
+ description="HEBREW PUNCTUATION MAQAF",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x5BE,
+ },
+ [0x5BF]={
+ adobename="rafehebrew",
+ category="mn",
+ combining=0x17,
+ description="HEBREW POINT RAFE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5BF,
+ },
+ [0x5C0]={
+ adobename="paseqhebrew",
+ category="po",
+ description="HEBREW PUNCTUATION PASEQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x5C0,
+ },
+ [0x5C1]={
+ adobename="shindothebrew",
+ category="mn",
+ combining=0x18,
+ description="HEBREW POINT SHIN DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5C1,
+ },
+ [0x5C2]={
+ adobename="sindothebrew",
+ category="mn",
+ combining=0x19,
+ description="HEBREW POINT SIN DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5C2,
+ },
+ [0x5C3]={
+ adobename="sofpasuqhebrew",
+ category="po",
+ description="HEBREW PUNCTUATION SOF PASUQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x5C3,
+ },
+ [0x5C4]={
+ adobename="upperdothebrew",
+ category="mn",
+ combining=0xE6,
+ description="HEBREW MARK UPPER DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5C4,
+ },
+ [0x5C5]={
+ category="mn",
+ combining=0xDC,
+ description="HEBREW MARK LOWER DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5C5,
+ },
+ [0x5C6]={
+ category="po",
+ description="HEBREW PUNCTUATION NUN HAFUKHA",
+ direction="r",
+ linebreak="ex",
+ unicodeslot=0x5C6,
+ },
+ [0x5C7]={
+ category="mn",
+ combining=0x12,
+ description="HEBREW POINT QAMATS QATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x5C7,
+ },
+ [0x5D0]={
+ adobename="alefhebrew",
+ category="lo",
+ contextname="hebrewAlef",
+ description="HEBREW LETTER ALEF",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D0,
+ },
+ [0x5D1]={
+ adobename="bethebrew",
+ category="lo",
+ contextname="hebrewBet",
+ description="HEBREW LETTER BET",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D1,
+ },
+ [0x5D2]={
+ adobename="gimelhebrew",
+ category="lo",
+ contextname="hebrewGimel",
+ description="HEBREW LETTER GIMEL",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D2,
+ },
+ [0x5D3]={
+ adobename="dalettserehebrew",
+ category="lo",
+ contextname="hebrewDalet",
+ description="HEBREW LETTER DALET",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D3,
+ },
+ [0x5D4]={
+ adobename="hehebrew",
+ category="lo",
+ contextname="hebrewHe",
+ description="HEBREW LETTER HE",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D4,
+ },
+ [0x5D5]={
+ adobename="vavhebrew",
+ category="lo",
+ contextname="hebrewVav",
+ description="HEBREW LETTER VAV",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D5,
+ },
+ [0x5D6]={
+ adobename="zayinhebrew",
+ category="lo",
+ contextname="hebrewZayin",
+ description="HEBREW LETTER ZAYIN",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D6,
+ },
+ [0x5D7]={
+ adobename="hethebrew",
+ category="lo",
+ contextname="hebrewHet",
+ description="HEBREW LETTER HET",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D7,
+ },
+ [0x5D8]={
+ adobename="tethebrew",
+ category="lo",
+ contextname="hebrewTet",
+ description="HEBREW LETTER TET",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D8,
+ },
+ [0x5D9]={
+ adobename="yodhebrew",
+ category="lo",
+ contextname="hebrewYod",
+ description="HEBREW LETTER YOD",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5D9,
+ },
+ [0x5DA]={
+ adobename="finalkafshevahebrew",
+ category="lo",
+ contextname="hebrewKaffinal",
+ description="HEBREW LETTER FINAL KAF",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DA,
+ },
+ [0x5DB]={
+ adobename="kafhebrew",
+ category="lo",
+ contextname="hebrewKaf",
+ description="HEBREW LETTER KAF",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DB,
+ },
+ [0x5DC]={
+ adobename="lamedholamhebrew",
+ category="lo",
+ contextname="hebrewLamed",
+ description="HEBREW LETTER LAMED",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DC,
+ },
+ [0x5DD]={
+ adobename="finalmemhebrew",
+ category="lo",
+ contextname="hebrewMemfinal",
+ description="HEBREW LETTER FINAL MEM",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DD,
+ },
+ [0x5DE]={
+ adobename="memhebrew",
+ category="lo",
+ contextname="hebrewMem",
+ description="HEBREW LETTER MEM",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DE,
+ },
+ [0x5DF]={
+ adobename="finalnunhebrew",
+ category="lo",
+ contextname="hebrewNunfinal",
+ description="HEBREW LETTER FINAL NUN",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5DF,
+ },
+ [0x5E0]={
+ adobename="nunhebrew",
+ category="lo",
+ contextname="hebrewNun",
+ description="HEBREW LETTER NUN",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E0,
+ },
+ [0x5E1]={
+ adobename="samekhhebrew",
+ category="lo",
+ contextname="hebrewSamekh",
+ description="HEBREW LETTER SAMEKH",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E1,
+ },
+ [0x5E2]={
+ adobename="ayinhebrew",
+ category="lo",
+ contextname="hebrewAyin",
+ description="HEBREW LETTER AYIN",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E2,
+ },
+ [0x5E3]={
+ adobename="finalpehebrew",
+ category="lo",
+ contextname="hebrewPefinal",
+ description="HEBREW LETTER FINAL PE",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E3,
+ },
+ [0x5E4]={
+ adobename="pehebrew",
+ category="lo",
+ contextname="hebrewPe",
+ description="HEBREW LETTER PE",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E4,
+ },
+ [0x5E5]={
+ adobename="finaltsadihebrew",
+ category="lo",
+ contextname="hebrewTsadifinal",
+ description="HEBREW LETTER FINAL TSADI",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E5,
+ },
+ [0x5E6]={
+ adobename="tsadihebrew",
+ category="lo",
+ contextname="hebrewTsadi",
+ description="HEBREW LETTER TSADI",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E6,
+ },
+ [0x5E7]={
+ adobename="qoftserehebrew",
+ category="lo",
+ contextname="hebrewQof",
+ description="HEBREW LETTER QOF",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E7,
+ },
+ [0x5E8]={
+ adobename="reshtserehebrew",
+ category="lo",
+ contextname="hebrewResh",
+ description="HEBREW LETTER RESH",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E8,
+ },
+ [0x5E9]={
+ adobename="shinhebrew",
+ category="lo",
+ contextname="hebrewShin",
+ description="HEBREW LETTER SHIN",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5E9,
+ },
+ [0x5EA]={
+ adobename="tavhebrew",
+ category="lo",
+ contextname="hebrewTav",
+ description="HEBREW LETTER TAV",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5EA,
+ },
+ [0x5F0]={
+ adobename="vavvavhebrew",
+ category="lo",
+ description="HEBREW LIGATURE YIDDISH DOUBLE VAV",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5F0,
+ },
+ [0x5F1]={
+ adobename="vavyodhebrew",
+ category="lo",
+ description="HEBREW LIGATURE YIDDISH VAV YOD",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5F1,
+ },
+ [0x5F2]={
+ adobename="yodyodhebrew",
+ category="lo",
+ description="HEBREW LIGATURE YIDDISH DOUBLE YOD",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5F2,
+ },
+ [0x5F3]={
+ adobename="gereshhebrew",
+ category="po",
+ description="HEBREW PUNCTUATION GERESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x5F3,
+ },
+ [0x5F4]={
+ adobename="gershayimhebrew",
+ category="po",
+ description="HEBREW PUNCTUATION GERSHAYIM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x5F4,
+ },
+ [0x600]={
+ arabic="u",
+ category="cf",
+ description="ARABIC NUMBER SIGN",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x600,
+ visible="yes",
+ },
+ [0x601]={
+ arabic="u",
+ category="cf",
+ description="ARABIC SIGN SANAH",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x601,
+ visible="yes",
+ },
+ [0x602]={
+ arabic="u",
+ category="cf",
+ description="ARABIC FOOTNOTE MARKER",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x602,
+ visible="yes",
+ },
+ [0x603]={
+ arabic="u",
+ category="cf",
+ description="ARABIC SIGN SAFHA",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x603,
+ visible="yes",
+ },
+ [0x604]={
+ arabic="u",
+ category="cf",
+ description="ARABIC SIGN SAMVAT",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x604,
+ },
+ [0x605]={
+ arabic="u",
+ category="cf",
+ description="ARABIC NUMBER MARK ABOVE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x605,
+ },
+ [0x606]={
+ category="sm",
+ description="ARABIC-INDIC CUBE ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x606,
+ },
+ [0x607]={
+ category="sm",
+ description="ARABIC-INDIC FOURTH ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x607,
+ },
+ [0x608]={
+ arabic="u",
+ category="sm",
+ description="ARABIC RAY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x608,
+ },
+ [0x609]={
+ category="po",
+ description="ARABIC-INDIC PER MILLE SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x609,
+ },
+ [0x60A]={
+ category="po",
+ description="ARABIC-INDIC PER TEN THOUSAND SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x60A,
+ },
+ [0x60B]={
+ arabic="u",
+ category="sc",
+ description="AFGHANI SIGN",
+ direction="al",
+ linebreak="po",
+ unicodeslot=0x60B,
+ },
+ [0x60C]={
+ adobename="commaarabic",
+ category="po",
+ description="ARABIC COMMA",
+ direction="cs",
+ linebreak="is",
+ unicodeslot=0x60C,
+ },
+ [0x60D]={
+ category="po",
+ description="ARABIC DATE SEPARATOR",
+ direction="al",
+ linebreak="is",
+ unicodeslot=0x60D,
+ },
+ [0x60E]={
+ category="so",
+ description="ARABIC POETIC VERSE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x60E,
+ },
+ [0x60F]={
+ category="so",
+ description="ARABIC SIGN MISRA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x60F,
+ },
+ [0x610]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x610,
+ },
+ [0x611]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SIGN ALAYHE ASSALLAM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x611,
+ },
+ [0x612]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SIGN RAHMATULLAH ALAYHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x612,
+ },
+ [0x613]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SIGN RADI ALLAHOU ANHU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x613,
+ },
+ [0x614]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SIGN TAKHALLUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x614,
+ },
+ [0x615]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH TAH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x615,
+ },
+ [0x616]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x616,
+ },
+ [0x617]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH ZAIN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x617,
+ },
+ [0x618]={
+ category="mn",
+ combining=0x1E,
+ description="ARABIC SMALL FATHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x618,
+ },
+ [0x619]={
+ category="mn",
+ combining=0x1F,
+ description="ARABIC SMALL DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x619,
+ },
+ [0x61A]={
+ category="mn",
+ combining=0x20,
+ description="ARABIC SMALL KASRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x61A,
+ },
+ [0x61B]={
+ adobename="semicolonarabic",
+ category="po",
+ description="ARABIC SEMICOLON",
+ direction="al",
+ linebreak="ex",
+ unicodeslot=0x61B,
+ },
+ [0x61C]={
+ category="cf",
+ description="ARABIC LETTER MARK",
+ direction="al",
+ linebreak="cm",
+ unicodeslot=0x61C,
+ },
+ [0x61E]={
+ category="po",
+ description="ARABIC TRIPLE DOT PUNCTUATION MARK",
+ direction="al",
+ linebreak="ex",
+ unicodeslot=0x61E,
+ },
+ [0x61F]={
+ adobename="questionarabic",
+ category="po",
+ description="ARABIC QUESTION MARK",
+ direction="al",
+ linebreak="ex",
+ unicodeslot=0x61F,
+ },
+ [0x620]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KASHMIRI YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x620,
+ },
+ [0x621]={
+ adobename="hamzasukunarabic",
+ arabic="u",
+ category="lo",
+ description="ARABIC LETTER HAMZA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x621,
+ },
+ [0x622]={
+ adobename="alefmaddaabovearabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH MADDA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "char", 0x627, 0x653 },
+ unicodeslot=0x622,
+ },
+ [0x623]={
+ adobename="alefhamzaabovearabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "char", 0x627, 0x654 },
+ unicodeslot=0x623,
+ },
+ [0x624]={
+ adobename="wawhamzaabovearabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ specials={ "char", 0x648, 0x654 },
+ unicodeslot=0x624,
+ },
+ [0x625]={
+ adobename="alefhamzabelowarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "char", 0x627, 0x655 },
+ unicodeslot=0x625,
+ },
+ [0x626]={
+ adobename="yehhamzaabovearabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ specials={ "char", 0x64A, 0x654 },
+ unicodeslot=0x626,
+ },
+ [0x627]={
+ adobename="alefarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x627,
+ },
+ [0x628]={
+ adobename="beharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x628,
+ },
+ [0x629]={
+ adobename="tehmarbutaarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER TEH MARBUTA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x629,
+ },
+ [0x62A]={
+ adobename="teharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62A,
+ },
+ [0x62B]={
+ adobename="theharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER THEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62B,
+ },
+ [0x62C]={
+ adobename="jeemarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER JEEM",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62C,
+ },
+ [0x62D]={
+ adobename="haharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62D,
+ },
+ [0x62E]={
+ adobename="khaharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KHAH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62E,
+ },
+ [0x62F]={
+ adobename="dalarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x62F,
+ },
+ [0x630]={
+ adobename="thalarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER THAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x630,
+ },
+ [0x631]={
+ adobename="rehyehaleflamarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x631,
+ },
+ [0x632]={
+ adobename="zainarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ZAIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x632,
+ },
+ [0x633]={
+ adobename="seenarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x633,
+ },
+ [0x634]={
+ adobename="sheenarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SHEEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x634,
+ },
+ [0x635]={
+ adobename="sadarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SAD",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x635,
+ },
+ [0x636]={
+ adobename="dadarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DAD",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x636,
+ },
+ [0x637]={
+ adobename="taharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TAH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x637,
+ },
+ [0x638]={
+ adobename="zaharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER ZAH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x638,
+ },
+ [0x639]={
+ adobename="ainarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x639,
+ },
+ [0x63A]={
+ adobename="ghainarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GHAIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63A,
+ },
+ [0x63B]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63B,
+ },
+ [0x63C]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63C,
+ },
+ [0x63D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63D,
+ },
+ [0x63E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63E,
+ },
+ [0x63F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x63F,
+ },
+ [0x640]={
+ adobename="tatweelarabic",
+ arabic="c",
+ category="lm",
+ description="ARABIC TATWEEL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x640,
+ },
+ [0x641]={
+ adobename="feharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x641,
+ },
+ [0x642]={
+ adobename="qafarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER QAF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x642,
+ },
+ [0x643]={
+ adobename="kafarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x643,
+ },
+ [0x644]={
+ adobename="lamarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x644,
+ },
+ [0x645]={
+ adobename="meemarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER MEEM",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x645,
+ },
+ [0x646]={
+ adobename="noonarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x646,
+ },
+ [0x647]={
+ adobename="heharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x647,
+ },
+ [0x648]={
+ adobename="wawarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x648,
+ },
+ [0x649]={
+ adobename="alefmaksuraarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER ALEF MAKSURA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x649,
+ },
+ [0x64A]={
+ adobename="yeharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x64A,
+ },
+ [0x64B]={
+ adobename="fathatanarabic",
+ category="mn",
+ combining=0x1B,
+ description="ARABIC FATHATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x64B,
+ },
+ [0x64C]={
+ adobename="dammatanarabic",
+ category="mn",
+ combining=0x1C,
+ description="ARABIC DAMMATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x64C,
+ },
+ [0x64D]={
+ adobename="kasratanarabic",
+ category="mn",
+ combining=0x1D,
+ description="ARABIC KASRATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x64D,
+ },
+ [0x64E]={
+ adobename="fathalowarabic",
+ category="mn",
+ combining=0x1E,
+ description="ARABIC FATHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x64E,
+ },
+ [0x64F]={
+ adobename="dammalowarabic",
+ category="mn",
+ combining=0x1F,
+ description="ARABIC DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x64F,
+ },
+ [0x650]={
+ adobename="kasraarabic",
+ category="mn",
+ combining=0x20,
+ description="ARABIC KASRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x650,
+ },
+ [0x651]={
+ adobename="shaddafathatanarabic",
+ category="mn",
+ combining=0x21,
+ description="ARABIC SHADDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x651,
+ },
+ [0x652]={
+ adobename="sukunarabic",
+ category="mn",
+ combining=0x22,
+ description="ARABIC SUKUN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x652,
+ },
+ [0x653]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC MADDAH ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x653,
+ },
+ [0x654]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC HAMZA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x654,
+ },
+ [0x655]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC HAMZA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x655,
+ },
+ [0x656]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC SUBSCRIPT ALEF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x656,
+ },
+ [0x657]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC INVERTED DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x657,
+ },
+ [0x658]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC MARK NOON GHUNNA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x658,
+ },
+ [0x659]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC ZWARAKAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x659,
+ },
+ [0x65A]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC VOWEL SIGN SMALL V ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65A,
+ },
+ [0x65B]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC VOWEL SIGN INVERTED SMALL V ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65B,
+ },
+ [0x65C]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC VOWEL SIGN DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65C,
+ },
+ [0x65D]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC REVERSED DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65D,
+ },
+ [0x65E]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC FATHA WITH TWO DOTS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65E,
+ },
+ [0x65F]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC WAVY HAMZA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x65F,
+ },
+ [0x660]={
+ adobename="zerohackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT ZERO",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x660,
+ },
+ [0x661]={
+ adobename="onehackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT ONE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x661,
+ },
+ [0x662]={
+ adobename="twohackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT TWO",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x662,
+ },
+ [0x663]={
+ adobename="threehackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT THREE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x663,
+ },
+ [0x664]={
+ adobename="fourhackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT FOUR",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x664,
+ },
+ [0x665]={
+ adobename="fivehackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT FIVE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x665,
+ },
+ [0x666]={
+ adobename="sixhackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT SIX",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x666,
+ },
+ [0x667]={
+ adobename="sevenhackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT SEVEN",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x667,
+ },
+ [0x668]={
+ adobename="eighthackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT EIGHT",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x668,
+ },
+ [0x669]={
+ adobename="ninehackarabic",
+ category="nd",
+ description="ARABIC-INDIC DIGIT NINE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x669,
+ },
+ [0x66A]={
+ adobename="percentarabic",
+ category="po",
+ description="ARABIC PERCENT SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x66A,
+ },
+ [0x66B]={
+ adobename="decimalseparatorpersian",
+ category="po",
+ description="ARABIC DECIMAL SEPARATOR",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x66B,
+ },
+ [0x66C]={
+ adobename="thousandsseparatorpersian",
+ category="po",
+ description="ARABIC THOUSANDS SEPARATOR",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x66C,
+ },
+ [0x66D]={
+ adobename="asteriskarabic",
+ category="po",
+ description="ARABIC FIVE POINTED STAR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x66D,
+ },
+ [0x66E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DOTLESS BEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x66E,
+ },
+ [0x66F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DOTLESS QAF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x66F,
+ },
+ [0x670]={
+ category="mn",
+ combining=0x23,
+ description="ARABIC LETTER SUPERSCRIPT ALEF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x670,
+ },
+ [0x671]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WASLA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x671,
+ },
+ [0x672]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ unicodeslot=0x672,
+ },
+ [0x673]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH WAVY HAMZA BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ unicodeslot=0x673,
+ },
+ [0x674]={
+ arabic="u",
+ category="lo",
+ description="ARABIC LETTER HIGH HAMZA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x674,
+ },
+ [0x675]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER HIGH HAMZA ALEF",
+ direction="al",
+ linebreak="al",
+ specials={ "compat", 0x627, 0x674 },
+ unicodeslot=0x675,
+ },
+ [0x676]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER HIGH HAMZA WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "compat", 0x648, 0x674 },
+ unicodeslot=0x676,
+ },
+ [0x677]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER U WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x6C7,
+ specials={ "compat", 0x6C7, 0x674 },
+ unicodeslot=0x677,
+ },
+ [0x678]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HIGH HAMZA YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "compat", 0x64A, 0x674 },
+ unicodeslot=0x678,
+ },
+ [0x679]={
+ adobename="tteharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TTEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x679,
+ },
+ [0x67A]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TTEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x67A,
+ },
+ [0x67B]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x67B,
+ },
+ [0x67C]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TEH WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x62A,
+ unicodeslot=0x67C,
+ },
+ [0x67D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS",
+ direction="al",
+ linebreak="al",
+ shcode=0x62A,
+ unicodeslot=0x67D,
+ },
+ [0x67E]={
+ adobename="peharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER PEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x67E,
+ },
+ [0x67F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x67F,
+ },
+ [0x680]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x680,
+ },
+ [0x681]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x62D,
+ unicodeslot=0x681,
+ },
+ [0x682]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x62D,
+ unicodeslot=0x682,
+ },
+ [0x683]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NYEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x683,
+ },
+ [0x684]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DYEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x684,
+ },
+ [0x685]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x62D,
+ unicodeslot=0x685,
+ },
+ [0x686]={
+ adobename="tcheharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TCHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x686,
+ },
+ [0x687]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TCHEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x687,
+ },
+ [0x688]={
+ adobename="ddalarabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DDAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x688,
+ },
+ [0x689]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x689,
+ },
+ [0x68A]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x68A,
+ },
+ [0x68B]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x68B,
+ },
+ [0x68C]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAHAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x68C,
+ },
+ [0x68D]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DDAHAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x68D,
+ },
+ [0x68E]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DUL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x68E,
+ },
+ [0x68F]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x68F,
+ },
+ [0x690]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH FOUR DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x690,
+ },
+ [0x691]={
+ adobename="rreharabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER RREH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x691,
+ },
+ [0x692]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH SMALL V",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x692,
+ },
+ [0x693]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x693,
+ },
+ [0x694]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x694,
+ },
+ [0x695]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH SMALL V BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x695,
+ },
+ [0x696]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x696,
+ },
+ [0x697]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x697,
+ },
+ [0x698]={
+ adobename="jeharabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER JEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x698,
+ },
+ [0x699]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH FOUR DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x699,
+ },
+ [0x69A]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x633,
+ unicodeslot=0x69A,
+ },
+ [0x69B]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x633,
+ unicodeslot=0x69B,
+ },
+ [0x69C]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x633,
+ unicodeslot=0x69C,
+ },
+ [0x69D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SAD WITH TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x635,
+ unicodeslot=0x69D,
+ },
+ [0x69E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SAD WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x635,
+ unicodeslot=0x69E,
+ },
+ [0x69F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TAH WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x637,
+ unicodeslot=0x69F,
+ },
+ [0x6A0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x639,
+ unicodeslot=0x6A0,
+ },
+ [0x6A1]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DOTLESS FEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6A1,
+ },
+ [0x6A2]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH DOT MOVED BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x641,
+ unicodeslot=0x6A2,
+ },
+ [0x6A3]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x641,
+ unicodeslot=0x6A3,
+ },
+ [0x6A4]={
+ adobename="veharabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER VEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6A4,
+ },
+ [0x6A5]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x641,
+ unicodeslot=0x6A5,
+ },
+ [0x6A6]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER PEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6A6,
+ },
+ [0x6A7]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER QAF WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x642,
+ unicodeslot=0x6A7,
+ },
+ [0x6A8]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER QAF WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x642,
+ unicodeslot=0x6A8,
+ },
+ [0x6A9]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6A9,
+ },
+ [0x6AA]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SWASH KAF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6AA,
+ },
+ [0x6AB]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x643,
+ unicodeslot=0x6AB,
+ },
+ [0x6AC]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x643,
+ unicodeslot=0x6AC,
+ },
+ [0x6AD]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NG",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6AD,
+ },
+ [0x6AE]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x643,
+ unicodeslot=0x6AE,
+ },
+ [0x6AF]={
+ adobename="gafarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GAF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6AF,
+ },
+ [0x6B0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GAF WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x6AF,
+ unicodeslot=0x6B0,
+ },
+ [0x6B1]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NGOEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6B1,
+ },
+ [0x6B2]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GAF WITH TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x6AF,
+ unicodeslot=0x6B2,
+ },
+ [0x6B3]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GUEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6B3,
+ },
+ [0x6B4]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GAF WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x6AF,
+ unicodeslot=0x6B4,
+ },
+ [0x6B5]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH SMALL V",
+ direction="al",
+ linebreak="al",
+ shcode=0x644,
+ unicodeslot=0x6B5,
+ },
+ [0x6B6]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x644,
+ unicodeslot=0x6B6,
+ },
+ [0x6B7]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x644,
+ unicodeslot=0x6B7,
+ },
+ [0x6B8]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x644,
+ unicodeslot=0x6B8,
+ },
+ [0x6B9]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x6B9,
+ },
+ [0x6BA]={
+ adobename="noonghunnaarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON GHUNNA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6BA,
+ },
+ [0x6BB]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER RNOON",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6BB,
+ },
+ [0x6BC]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x6BC,
+ },
+ [0x6BD]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x6BD,
+ },
+ [0x6BE]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HEH DOACHASHMEE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6BE,
+ },
+ [0x6BF]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TCHEH WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x686,
+ unicodeslot=0x6BF,
+ },
+ [0x6C0]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER HEH WITH YEH ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x647,
+ specials={ "char", 0x6D5, 0x654 },
+ unicodeslot=0x6C0,
+ },
+ [0x6C1]={
+ adobename="hehaltonearabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HEH GOAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C1,
+ },
+ [0x6C2]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HEH GOAL WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ specials={ "char", 0x6C1, 0x654 },
+ unicodeslot=0x6C2,
+ },
+ [0x6C3]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER TEH MARBUTA GOAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C3,
+ },
+ [0x6C4]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH RING",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ unicodeslot=0x6C4,
+ },
+ [0x6C5]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ OE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C5,
+ },
+ [0x6C6]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER OE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C6,
+ },
+ [0x6C7]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER U",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C7,
+ },
+ [0x6C8]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER YU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C8,
+ },
+ [0x6C9]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ YU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6C9,
+ },
+ [0x6CA]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ unicodeslot=0x6CA,
+ },
+ [0x6CB]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER VE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6CB,
+ },
+ [0x6CC]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6CC,
+ },
+ [0x6CD]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER YEH WITH TAIL",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ unicodeslot=0x6CD,
+ },
+ [0x6CE]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH SMALL V",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ unicodeslot=0x6CE,
+ },
+ [0x6CF]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ unicodeslot=0x6CF,
+ },
+ [0x6D0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER E",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6D0,
+ },
+ [0x6D1]={
+ adobename="yehthreedotsbelowarabic",
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ unicodeslot=0x6D1,
+ },
+ [0x6D2]={
+ adobename="yehbarreearabic",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER YEH BARREE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6D2,
+ },
+ [0x6D3]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ specials={ "char", 0x6D2, 0x654 },
+ unicodeslot=0x6D3,
+ },
+ [0x6D4]={
+ category="po",
+ description="ARABIC FULL STOP",
+ direction="al",
+ linebreak="ex",
+ unicodeslot=0x6D4,
+ },
+ [0x6D5]={
+ adobename="afii57534",
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER AE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6D5,
+ },
+ [0x6D6]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6D6,
+ },
+ [0x6D7]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6D7,
+ },
+ [0x6D8]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH MEEM INITIAL FORM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6D8,
+ },
+ [0x6D9]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH LAM ALEF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6D9,
+ },
+ [0x6DA]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH JEEM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6DA,
+ },
+ [0x6DB]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH THREE DOTS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6DB,
+ },
+ [0x6DC]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH SEEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6DC,
+ },
+ [0x6DD]={
+ arabic="u",
+ category="cf",
+ description="ARABIC END OF AYAH",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x6DD,
+ visible="yes",
+ },
+ [0x6DE]={
+ category="me",
+ description="ARABIC START OF RUB EL HIZB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x6DE,
+ },
+ [0x6DF]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH ROUNDED ZERO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6DF,
+ },
+ [0x6E0]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E0,
+ },
+ [0x6E1]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH DOTLESS HEAD OF KHAH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E1,
+ },
+ [0x6E2]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH MEEM ISOLATED FORM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E2,
+ },
+ [0x6E3]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC SMALL LOW SEEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E3,
+ },
+ [0x6E4]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH MADDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E4,
+ },
+ [0x6E5]={
+ category="lm",
+ description="ARABIC SMALL WAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6E5,
+ },
+ [0x6E6]={
+ category="lm",
+ description="ARABIC SMALL YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6E6,
+ },
+ [0x6E7]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH YEH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E7,
+ },
+ [0x6E8]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH NOON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6E8,
+ },
+ [0x6E9]={
+ category="so",
+ description="ARABIC PLACE OF SAJDAH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x6E9,
+ },
+ [0x6EA]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC EMPTY CENTRE LOW STOP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6EA,
+ },
+ [0x6EB]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC EMPTY CENTRE HIGH STOP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6EB,
+ },
+ [0x6EC]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6EC,
+ },
+ [0x6ED]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC SMALL LOW MEEM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x6ED,
+ },
+ [0x6EE]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x6EE,
+ },
+ [0x6EF]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x6EF,
+ },
+ [0x6F0]={
+ adobename="zeropersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F0,
+ },
+ [0x6F1]={
+ adobename="onepersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F1,
+ },
+ [0x6F2]={
+ adobename="twopersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F2,
+ },
+ [0x6F3]={
+ adobename="threepersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F3,
+ },
+ [0x6F4]={
+ adobename="fourpersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F4,
+ },
+ [0x6F5]={
+ adobename="fivepersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F5,
+ },
+ [0x6F6]={
+ adobename="sixpersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F6,
+ },
+ [0x6F7]={
+ adobename="sevenpersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F7,
+ },
+ [0x6F8]={
+ adobename="eightpersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F8,
+ },
+ [0x6F9]={
+ adobename="ninepersian",
+ category="nd",
+ description="EXTENDED ARABIC-INDIC DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ unicodeslot=0x6F9,
+ },
+ [0x6FA]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SHEEN WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x634,
+ unicodeslot=0x6FA,
+ },
+ [0x6FB]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER DAD WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x636,
+ unicodeslot=0x6FB,
+ },
+ [0x6FC]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GHAIN WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x63A,
+ unicodeslot=0x6FC,
+ },
+ [0x6FD]={
+ category="so",
+ description="ARABIC SIGN SINDHI AMPERSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6FD,
+ },
+ [0x6FE]={
+ category="so",
+ description="ARABIC SIGN SINDHI POSTPOSITION MEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x6FE,
+ },
+ [0x6FF]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HEH WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ shcode=0x647,
+ unicodeslot=0x6FF,
+ },
+ [0x700]={
+ category="po",
+ description="SYRIAC END OF PARAGRAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x700,
+ },
+ [0x701]={
+ category="po",
+ description="SYRIAC SUPRALINEAR FULL STOP",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x701,
+ },
+ [0x702]={
+ category="po",
+ description="SYRIAC SUBLINEAR FULL STOP",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x702,
+ },
+ [0x703]={
+ category="po",
+ description="SYRIAC SUPRALINEAR COLON",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x703,
+ },
+ [0x704]={
+ category="po",
+ description="SYRIAC SUBLINEAR COLON",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x704,
+ },
+ [0x705]={
+ category="po",
+ description="SYRIAC HORIZONTAL COLON",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x705,
+ },
+ [0x706]={
+ category="po",
+ description="SYRIAC COLON SKEWED LEFT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x706,
+ },
+ [0x707]={
+ category="po",
+ description="SYRIAC COLON SKEWED RIGHT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x707,
+ },
+ [0x708]={
+ category="po",
+ description="SYRIAC SUPRALINEAR COLON SKEWED LEFT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x708,
+ },
+ [0x709]={
+ category="po",
+ description="SYRIAC SUBLINEAR COLON SKEWED RIGHT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x709,
+ },
+ [0x70A]={
+ category="po",
+ description="SYRIAC CONTRACTION",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x70A,
+ },
+ [0x70B]={
+ category="po",
+ description="SYRIAC HARKLEAN OBELUS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x70B,
+ },
+ [0x70C]={
+ category="po",
+ description="SYRIAC HARKLEAN METOBELUS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x70C,
+ },
+ [0x70D]={
+ category="po",
+ description="SYRIAC HARKLEAN ASTERISCUS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x70D,
+ },
+ [0x70F]={
+ category="cf",
+ description="SYRIAC ABBREVIATION MARK",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x70F,
+ visible="yes",
+ },
+ [0x710]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER ALAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x710,
+ },
+ [0x711]={
+ category="mn",
+ combining=0x24,
+ description="SYRIAC LETTER SUPERSCRIPT ALAPH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x711,
+ },
+ [0x712]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER BETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x712,
+ },
+ [0x713]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER GAMAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x713,
+ },
+ [0x714]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER GAMAL GARSHUNI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x714,
+ },
+ [0x715]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER DALATH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x715,
+ },
+ [0x716]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER DOTLESS DALATH RISH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x716,
+ },
+ [0x717]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER HE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x717,
+ },
+ [0x718]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER WAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x718,
+ },
+ [0x719]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER ZAIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x719,
+ },
+ [0x71A]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER HETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71A,
+ },
+ [0x71B]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER TETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71B,
+ },
+ [0x71C]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER TETH GARSHUNI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71C,
+ },
+ [0x71D]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER YUDH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71D,
+ },
+ [0x71E]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER YUDH HE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71E,
+ },
+ [0x71F]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER KAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x71F,
+ },
+ [0x720]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER LAMADH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x720,
+ },
+ [0x721]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER MIM",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x721,
+ },
+ [0x722]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER NUN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x722,
+ },
+ [0x723]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER SEMKATH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x723,
+ },
+ [0x724]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER FINAL SEMKATH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x724,
+ },
+ [0x725]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER E",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x725,
+ },
+ [0x726]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER PE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x726,
+ },
+ [0x727]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER REVERSED PE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x727,
+ },
+ [0x728]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER SADHE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x728,
+ },
+ [0x729]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER QAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x729,
+ },
+ [0x72A]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER RISH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72A,
+ },
+ [0x72B]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER SHIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72B,
+ },
+ [0x72C]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER TAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72C,
+ },
+ [0x72D]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER PERSIAN BHETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72D,
+ },
+ [0x72E]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER PERSIAN GHAMAL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72E,
+ },
+ [0x72F]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER PERSIAN DHALATH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x72F,
+ },
+ [0x730]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC PTHAHA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x730,
+ },
+ [0x731]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC PTHAHA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x731,
+ },
+ [0x732]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC PTHAHA DOTTED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x732,
+ },
+ [0x733]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC ZQAPHA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x733,
+ },
+ [0x734]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC ZQAPHA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x734,
+ },
+ [0x735]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC ZQAPHA DOTTED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x735,
+ },
+ [0x736]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC RBASA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x736,
+ },
+ [0x737]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC RBASA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x737,
+ },
+ [0x738]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC DOTTED ZLAMA HORIZONTAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x738,
+ },
+ [0x739]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC DOTTED ZLAMA ANGULAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x739,
+ },
+ [0x73A]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC HBASA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73A,
+ },
+ [0x73B]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC HBASA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73B,
+ },
+ [0x73C]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC HBASA-ESASA DOTTED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73C,
+ },
+ [0x73D]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC ESASA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73D,
+ },
+ [0x73E]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC ESASA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73E,
+ },
+ [0x73F]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC RWAHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x73F,
+ },
+ [0x740]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC FEMININE DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x740,
+ },
+ [0x741]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC QUSHSHAYA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x741,
+ },
+ [0x742]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC RUKKAKHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x742,
+ },
+ [0x743]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC TWO VERTICAL DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x743,
+ },
+ [0x744]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC TWO VERTICAL DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x744,
+ },
+ [0x745]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC THREE DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x745,
+ },
+ [0x746]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC THREE DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x746,
+ },
+ [0x747]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC OBLIQUE LINE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x747,
+ },
+ [0x748]={
+ category="mn",
+ combining=0xDC,
+ description="SYRIAC OBLIQUE LINE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x748,
+ },
+ [0x749]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC MUSIC",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x749,
+ },
+ [0x74A]={
+ category="mn",
+ combining=0xE6,
+ description="SYRIAC BARREKH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x74A,
+ },
+ [0x74D]={
+ arabic="r",
+ category="lo",
+ description="SYRIAC LETTER SOGDIAN ZHAIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x74D,
+ },
+ [0x74E]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER SOGDIAN KHAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x74E,
+ },
+ [0x74F]={
+ arabic="d",
+ category="lo",
+ description="SYRIAC LETTER SOGDIAN FE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x74F,
+ },
+ [0x750]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x750,
+ },
+ [0x751]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x751,
+ },
+ [0x752]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x752,
+ },
+ [0x753]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x753,
+ },
+ [0x754]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x754,
+ },
+ [0x755]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH INVERTED SMALL V BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x755,
+ },
+ [0x756]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH SMALL V",
+ direction="al",
+ linebreak="al",
+ shcode=0x628,
+ unicodeslot=0x756,
+ },
+ [0x757]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x62D,
+ unicodeslot=0x757,
+ },
+ [0x758]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x62D,
+ unicodeslot=0x758,
+ },
+ [0x759]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x759,
+ },
+ [0x75A]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH INVERTED SMALL V BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x62F,
+ unicodeslot=0x75A,
+ },
+ [0x75B]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH STROKE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x75B,
+ },
+ [0x75C]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH FOUR DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x633,
+ unicodeslot=0x75C,
+ },
+ [0x75D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x639,
+ unicodeslot=0x75D,
+ },
+ [0x75E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x639,
+ unicodeslot=0x75E,
+ },
+ [0x75F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x639,
+ unicodeslot=0x75F,
+ },
+ [0x760]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x641,
+ unicodeslot=0x760,
+ },
+ [0x761]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x641,
+ unicodeslot=0x761,
+ },
+ [0x762]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x6A9,
+ unicodeslot=0x762,
+ },
+ [0x763]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x6A9,
+ unicodeslot=0x763,
+ },
+ [0x764]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x6A9,
+ unicodeslot=0x764,
+ },
+ [0x765]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER MEEM WITH DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x645,
+ unicodeslot=0x765,
+ },
+ [0x766]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER MEEM WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x645,
+ unicodeslot=0x766,
+ },
+ [0x767]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x767,
+ },
+ [0x768]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH SMALL TAH",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x768,
+ },
+ [0x769]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER NOON WITH SMALL V",
+ direction="al",
+ linebreak="al",
+ shcode=0x646,
+ unicodeslot=0x769,
+ },
+ [0x76A]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH BAR",
+ direction="al",
+ linebreak="al",
+ shcode=0x644,
+ unicodeslot=0x76A,
+ },
+ [0x76B]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x76B,
+ },
+ [0x76C]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x631,
+ unicodeslot=0x76C,
+ },
+ [0x76D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE",
+ direction="al",
+ linebreak="al",
+ shcode=0x633,
+ unicodeslot=0x76D,
+ },
+ [0x76E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x76E,
+ },
+ [0x76F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x76F,
+ },
+ [0x770]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x770,
+ },
+ [0x771]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x771,
+ },
+ [0x772]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x772,
+ },
+ [0x773]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x773,
+ },
+ [0x774]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x774,
+ },
+ [0x775]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x775,
+ },
+ [0x776]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x776,
+ },
+ [0x777]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x777,
+ },
+ [0x778]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x778,
+ },
+ [0x779]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x779,
+ },
+ [0x77A]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77A,
+ },
+ [0x77B]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77B,
+ },
+ [0x77C]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77C,
+ },
+ [0x77D]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77D,
+ },
+ [0x77E]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SEEN WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77E,
+ },
+ [0x77F]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x77F,
+ },
+ [0x780]={
+ category="lo",
+ description="THAANA LETTER HAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x780,
+ },
+ [0x781]={
+ category="lo",
+ description="THAANA LETTER SHAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x781,
+ },
+ [0x782]={
+ category="lo",
+ description="THAANA LETTER NOONU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x782,
+ },
+ [0x783]={
+ category="lo",
+ description="THAANA LETTER RAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x783,
+ },
+ [0x784]={
+ category="lo",
+ description="THAANA LETTER BAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x784,
+ },
+ [0x785]={
+ category="lo",
+ description="THAANA LETTER LHAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x785,
+ },
+ [0x786]={
+ category="lo",
+ description="THAANA LETTER KAAFU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x786,
+ },
+ [0x787]={
+ category="lo",
+ description="THAANA LETTER ALIFU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x787,
+ },
+ [0x788]={
+ category="lo",
+ description="THAANA LETTER VAAVU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x788,
+ },
+ [0x789]={
+ category="lo",
+ description="THAANA LETTER MEEMU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x789,
+ },
+ [0x78A]={
+ category="lo",
+ description="THAANA LETTER FAAFU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78A,
+ },
+ [0x78B]={
+ category="lo",
+ description="THAANA LETTER DHAALU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78B,
+ },
+ [0x78C]={
+ category="lo",
+ description="THAANA LETTER THAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78C,
+ },
+ [0x78D]={
+ category="lo",
+ description="THAANA LETTER LAAMU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78D,
+ },
+ [0x78E]={
+ category="lo",
+ description="THAANA LETTER GAAFU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78E,
+ },
+ [0x78F]={
+ category="lo",
+ description="THAANA LETTER GNAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x78F,
+ },
+ [0x790]={
+ category="lo",
+ description="THAANA LETTER SEENU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x790,
+ },
+ [0x791]={
+ category="lo",
+ description="THAANA LETTER DAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x791,
+ },
+ [0x792]={
+ category="lo",
+ description="THAANA LETTER ZAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x792,
+ },
+ [0x793]={
+ category="lo",
+ description="THAANA LETTER TAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x793,
+ },
+ [0x794]={
+ category="lo",
+ description="THAANA LETTER YAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x794,
+ },
+ [0x795]={
+ category="lo",
+ description="THAANA LETTER PAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x795,
+ },
+ [0x796]={
+ category="lo",
+ description="THAANA LETTER JAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x796,
+ },
+ [0x797]={
+ category="lo",
+ description="THAANA LETTER CHAVIYANI",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x797,
+ },
+ [0x798]={
+ category="lo",
+ description="THAANA LETTER TTAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x798,
+ },
+ [0x799]={
+ category="lo",
+ description="THAANA LETTER HHAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x799,
+ },
+ [0x79A]={
+ category="lo",
+ description="THAANA LETTER KHAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79A,
+ },
+ [0x79B]={
+ category="lo",
+ description="THAANA LETTER THAALU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79B,
+ },
+ [0x79C]={
+ category="lo",
+ description="THAANA LETTER ZAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79C,
+ },
+ [0x79D]={
+ category="lo",
+ description="THAANA LETTER SHEENU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79D,
+ },
+ [0x79E]={
+ category="lo",
+ description="THAANA LETTER SAADHU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79E,
+ },
+ [0x79F]={
+ category="lo",
+ description="THAANA LETTER DAADHU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x79F,
+ },
+ [0x7A0]={
+ category="lo",
+ description="THAANA LETTER TO",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A0,
+ },
+ [0x7A1]={
+ category="lo",
+ description="THAANA LETTER ZO",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A1,
+ },
+ [0x7A2]={
+ category="lo",
+ description="THAANA LETTER AINU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A2,
+ },
+ [0x7A3]={
+ category="lo",
+ description="THAANA LETTER GHAINU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A3,
+ },
+ [0x7A4]={
+ category="lo",
+ description="THAANA LETTER QAAFU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A4,
+ },
+ [0x7A5]={
+ category="lo",
+ description="THAANA LETTER WAAVU",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7A5,
+ },
+ [0x7A6]={
+ category="mn",
+ description="THAANA ABAFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7A6,
+ },
+ [0x7A7]={
+ category="mn",
+ description="THAANA AABAAFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7A7,
+ },
+ [0x7A8]={
+ category="mn",
+ description="THAANA IBIFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7A8,
+ },
+ [0x7A9]={
+ category="mn",
+ description="THAANA EEBEEFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7A9,
+ },
+ [0x7AA]={
+ category="mn",
+ description="THAANA UBUFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AA,
+ },
+ [0x7AB]={
+ category="mn",
+ description="THAANA OOBOOFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AB,
+ },
+ [0x7AC]={
+ category="mn",
+ description="THAANA EBEFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AC,
+ },
+ [0x7AD]={
+ category="mn",
+ description="THAANA EYBEYFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AD,
+ },
+ [0x7AE]={
+ category="mn",
+ description="THAANA OBOFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AE,
+ },
+ [0x7AF]={
+ category="mn",
+ description="THAANA OABOAFILI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7AF,
+ },
+ [0x7B0]={
+ category="mn",
+ description="THAANA SUKUN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7B0,
+ },
+ [0x7B1]={
+ category="lo",
+ description="THAANA LETTER NAA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x7B1,
+ },
+ [0x7C0]={
+ category="nd",
+ description="NKO DIGIT ZERO",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C0,
+ },
+ [0x7C1]={
+ category="nd",
+ description="NKO DIGIT ONE",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C1,
+ },
+ [0x7C2]={
+ category="nd",
+ description="NKO DIGIT TWO",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C2,
+ },
+ [0x7C3]={
+ category="nd",
+ description="NKO DIGIT THREE",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C3,
+ },
+ [0x7C4]={
+ category="nd",
+ description="NKO DIGIT FOUR",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C4,
+ },
+ [0x7C5]={
+ category="nd",
+ description="NKO DIGIT FIVE",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C5,
+ },
+ [0x7C6]={
+ category="nd",
+ description="NKO DIGIT SIX",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C6,
+ },
+ [0x7C7]={
+ category="nd",
+ description="NKO DIGIT SEVEN",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C7,
+ },
+ [0x7C8]={
+ category="nd",
+ description="NKO DIGIT EIGHT",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C8,
+ },
+ [0x7C9]={
+ category="nd",
+ description="NKO DIGIT NINE",
+ direction="r",
+ linebreak="nu",
+ unicodeslot=0x7C9,
+ },
+ [0x7CA]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CA,
+ },
+ [0x7CB]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CB,
+ },
+ [0x7CC]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CC,
+ },
+ [0x7CD]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CD,
+ },
+ [0x7CE]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CE,
+ },
+ [0x7CF]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7CF,
+ },
+ [0x7D0]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D0,
+ },
+ [0x7D1]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER DAGBASINNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D1,
+ },
+ [0x7D2]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER N",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D2,
+ },
+ [0x7D3]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D3,
+ },
+ [0x7D4]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D4,
+ },
+ [0x7D5]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D5,
+ },
+ [0x7D6]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER JA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D6,
+ },
+ [0x7D7]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER CHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D7,
+ },
+ [0x7D8]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D8,
+ },
+ [0x7D9]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7D9,
+ },
+ [0x7DA]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER RRA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DA,
+ },
+ [0x7DB]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DB,
+ },
+ [0x7DC]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER GBA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DC,
+ },
+ [0x7DD]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER FA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DD,
+ },
+ [0x7DE]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DE,
+ },
+ [0x7DF]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7DF,
+ },
+ [0x7E0]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER NA WOLOSO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E0,
+ },
+ [0x7E1]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E1,
+ },
+ [0x7E2]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER NYA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E2,
+ },
+ [0x7E3]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E3,
+ },
+ [0x7E4]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER HA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E4,
+ },
+ [0x7E5]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E5,
+ },
+ [0x7E6]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E6,
+ },
+ [0x7E7]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER NYA WOLOSO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E7,
+ },
+ [0x7E8]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER JONA JA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E8,
+ },
+ [0x7E9]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER JONA CHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7E9,
+ },
+ [0x7EA]={
+ arabic="d",
+ category="lo",
+ description="NKO LETTER JONA RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7EA,
+ },
+ [0x7EB]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING SHORT HIGH TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7EB,
+ },
+ [0x7EC]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING SHORT LOW TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7EC,
+ },
+ [0x7ED]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING SHORT RISING TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7ED,
+ },
+ [0x7EE]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING LONG DESCENDING TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7EE,
+ },
+ [0x7EF]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING LONG HIGH TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7EF,
+ },
+ [0x7F0]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING LONG LOW TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7F0,
+ },
+ [0x7F1]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING LONG RISING TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7F1,
+ },
+ [0x7F2]={
+ category="mn",
+ combining=0xDC,
+ description="NKO COMBINING NASALIZATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7F2,
+ },
+ [0x7F3]={
+ category="mn",
+ combining=0xE6,
+ description="NKO COMBINING DOUBLE DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7F3,
+ },
+ [0x7F4]={
+ category="lm",
+ description="NKO HIGH TONE APOSTROPHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7F4,
+ },
+ [0x7F5]={
+ category="lm",
+ description="NKO LOW TONE APOSTROPHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7F5,
+ },
+ [0x7F6]={
+ category="so",
+ description="NKO SYMBOL OO DENNEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x7F6,
+ },
+ [0x7F7]={
+ category="po",
+ description="NKO SYMBOL GBAKURUNEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x7F7,
+ },
+ [0x7F8]={
+ category="po",
+ description="NKO COMMA",
+ direction="on",
+ linebreak="is",
+ unicodeslot=0x7F8,
+ },
+ [0x7F9]={
+ category="po",
+ description="NKO EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x7F9,
+ },
+ [0x7FA]={
+ arabic="c",
+ category="lm",
+ description="NKO LAJANYALAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x7FA,
+ },
+ [0x800]={
+ category="lo",
+ description="SAMARITAN LETTER ALAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x800,
+ },
+ [0x801]={
+ category="lo",
+ description="SAMARITAN LETTER BIT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x801,
+ },
+ [0x802]={
+ category="lo",
+ description="SAMARITAN LETTER GAMAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x802,
+ },
+ [0x803]={
+ category="lo",
+ description="SAMARITAN LETTER DALAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x803,
+ },
+ [0x804]={
+ category="lo",
+ description="SAMARITAN LETTER IY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x804,
+ },
+ [0x805]={
+ category="lo",
+ description="SAMARITAN LETTER BAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x805,
+ },
+ [0x806]={
+ category="lo",
+ description="SAMARITAN LETTER ZEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x806,
+ },
+ [0x807]={
+ category="lo",
+ description="SAMARITAN LETTER IT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x807,
+ },
+ [0x808]={
+ category="lo",
+ description="SAMARITAN LETTER TIT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x808,
+ },
+ [0x809]={
+ category="lo",
+ description="SAMARITAN LETTER YUT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x809,
+ },
+ [0x80A]={
+ category="lo",
+ description="SAMARITAN LETTER KAAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80A,
+ },
+ [0x80B]={
+ category="lo",
+ description="SAMARITAN LETTER LABAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80B,
+ },
+ [0x80C]={
+ category="lo",
+ description="SAMARITAN LETTER MIM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80C,
+ },
+ [0x80D]={
+ category="lo",
+ description="SAMARITAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80D,
+ },
+ [0x80E]={
+ category="lo",
+ description="SAMARITAN LETTER SINGAAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80E,
+ },
+ [0x80F]={
+ category="lo",
+ description="SAMARITAN LETTER IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x80F,
+ },
+ [0x810]={
+ category="lo",
+ description="SAMARITAN LETTER FI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x810,
+ },
+ [0x811]={
+ category="lo",
+ description="SAMARITAN LETTER TSAADIY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x811,
+ },
+ [0x812]={
+ category="lo",
+ description="SAMARITAN LETTER QUF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x812,
+ },
+ [0x813]={
+ category="lo",
+ description="SAMARITAN LETTER RISH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x813,
+ },
+ [0x814]={
+ category="lo",
+ description="SAMARITAN LETTER SHAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x814,
+ },
+ [0x815]={
+ category="lo",
+ description="SAMARITAN LETTER TAAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x815,
+ },
+ [0x816]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK IN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x816,
+ },
+ [0x817]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK IN-ALAF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x817,
+ },
+ [0x818]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK OCCLUSION",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x818,
+ },
+ [0x819]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK DAGESH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x819,
+ },
+ [0x81A]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER EPENTHETIC YUT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x81A,
+ },
+ [0x81B]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK EPENTHETIC YUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x81B,
+ },
+ [0x81C]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN LONG E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x81C,
+ },
+ [0x81D]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x81D,
+ },
+ [0x81E]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN OVERLONG AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x81E,
+ },
+ [0x81F]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN LONG AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x81F,
+ },
+ [0x820]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x820,
+ },
+ [0x821]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN OVERLONG A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x821,
+ },
+ [0x822]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN LONG A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x822,
+ },
+ [0x823]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x823,
+ },
+ [0x824]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER SHORT A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x824,
+ },
+ [0x825]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN SHORT A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x825,
+ },
+ [0x826]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN LONG U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x826,
+ },
+ [0x827]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x827,
+ },
+ [0x828]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x828,
+ },
+ [0x829]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN LONG I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x829,
+ },
+ [0x82A]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x82A,
+ },
+ [0x82B]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x82B,
+ },
+ [0x82C]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN VOWEL SIGN SUKUN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x82C,
+ },
+ [0x82D]={
+ category="mn",
+ combining=0xE6,
+ description="SAMARITAN MARK NEQUDAA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x82D,
+ },
+ [0x830]={
+ category="po",
+ description="SAMARITAN PUNCTUATION NEQUDAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x830,
+ },
+ [0x831]={
+ category="po",
+ description="SAMARITAN PUNCTUATION AFSAAQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x831,
+ },
+ [0x832]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ANGED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x832,
+ },
+ [0x833]={
+ category="po",
+ description="SAMARITAN PUNCTUATION BAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x833,
+ },
+ [0x834]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ATMAAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x834,
+ },
+ [0x835]={
+ category="po",
+ description="SAMARITAN PUNCTUATION SHIYYAALAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x835,
+ },
+ [0x836]={
+ category="po",
+ description="SAMARITAN ABBREVIATION MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x836,
+ },
+ [0x837]={
+ category="po",
+ description="SAMARITAN PUNCTUATION MELODIC QITSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x837,
+ },
+ [0x838]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ZIQAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x838,
+ },
+ [0x839]={
+ category="po",
+ description="SAMARITAN PUNCTUATION QITSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x839,
+ },
+ [0x83A]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ZAEF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x83A,
+ },
+ [0x83B]={
+ category="po",
+ description="SAMARITAN PUNCTUATION TURU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x83B,
+ },
+ [0x83C]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ARKAANU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x83C,
+ },
+ [0x83D]={
+ category="po",
+ description="SAMARITAN PUNCTUATION SOF MASHFAAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x83D,
+ },
+ [0x83E]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ANNAAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x83E,
+ },
+ [0x840]={
+ arabic="r",
+ category="lo",
+ description="MANDAIC LETTER HALQA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x840,
+ },
+ [0x841]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x841,
+ },
+ [0x842]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x842,
+ },
+ [0x843]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x843,
+ },
+ [0x844]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x844,
+ },
+ [0x845]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER USHENNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x845,
+ },
+ [0x846]={
+ arabic="r",
+ category="lo",
+ description="MANDAIC LETTER AZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x846,
+ },
+ [0x847]={
+ arabic="r",
+ category="lo",
+ description="MANDAIC LETTER IT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x847,
+ },
+ [0x848]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER ATT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x848,
+ },
+ [0x849]={
+ arabic="r",
+ category="lo",
+ description="MANDAIC LETTER AKSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x849,
+ },
+ [0x84A]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84A,
+ },
+ [0x84B]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84B,
+ },
+ [0x84C]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84C,
+ },
+ [0x84D]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84D,
+ },
+ [0x84E]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84E,
+ },
+ [0x84F]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x84F,
+ },
+ [0x850]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x850,
+ },
+ [0x851]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER ASZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x851,
+ },
+ [0x852]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x852,
+ },
+ [0x853]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x853,
+ },
+ [0x854]={
+ arabic="r",
+ category="lo",
+ description="MANDAIC LETTER ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x854,
+ },
+ [0x855]={
+ arabic="d",
+ category="lo",
+ description="MANDAIC LETTER AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x855,
+ },
+ [0x856]={
+ arabic="u",
+ category="lo",
+ description="MANDAIC LETTER DUSHENNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x856,
+ },
+ [0x857]={
+ arabic="u",
+ category="lo",
+ description="MANDAIC LETTER KAD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x857,
+ },
+ [0x858]={
+ arabic="u",
+ category="lo",
+ description="MANDAIC LETTER AIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x858,
+ },
+ [0x859]={
+ category="mn",
+ combining=0xDC,
+ description="MANDAIC AFFRICATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x859,
+ },
+ [0x85A]={
+ category="mn",
+ combining=0xDC,
+ description="MANDAIC VOCALIZATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x85A,
+ },
+ [0x85B]={
+ category="mn",
+ combining=0xDC,
+ description="MANDAIC GEMINATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x85B,
+ },
+ [0x85E]={
+ category="po",
+ description="MANDAIC PUNCTUATION",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x85E,
+ },
+ [0x8A0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH SMALL V BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A0,
+ },
+ [0x8A1]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A1,
+ },
+ [0x8A2]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER JEEM WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A2,
+ },
+ [0x8A3]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TAH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A3,
+ },
+ [0x8A4]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A4,
+ },
+ [0x8A5]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER QAF WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A5,
+ },
+ [0x8A6]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH DOUBLE BAR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A6,
+ },
+ [0x8A7]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER MEEM WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A7,
+ },
+ [0x8A8]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A8,
+ },
+ [0x8A9]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8A9,
+ },
+ [0x8AA]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH LOOP",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AA,
+ },
+ [0x8AB]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH DOT WITHIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AB,
+ },
+ [0x8AC]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ROHINGYA YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AC,
+ },
+ [0x8AD]={
+ arabic="u",
+ category="lo",
+ description="ARABIC LETTER LOW ALEF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AD,
+ },
+ [0x8AE]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER DAL WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AE,
+ },
+ [0x8AF]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER SAD WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8AF,
+ },
+ [0x8B0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER GAF WITH INVERTED STROKE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8B0,
+ },
+ [0x8B1]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER STRAIGHT WAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8B1,
+ },
+ [0x8B2]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ZAIN WITH INVERTED V ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8B2,
+ },
+ [0x8B3]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER AIN WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8B3,
+ },
+ [0x8B4]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER KAF WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x8B4,
+ },
+ [0x8E3]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC TURNED DAMMA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E3,
+ },
+ [0x8E4]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC CURLY FATHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E4,
+ },
+ [0x8E5]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC CURLY DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E5,
+ },
+ [0x8E6]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC CURLY KASRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E6,
+ },
+ [0x8E7]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC CURLY FATHATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E7,
+ },
+ [0x8E8]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC CURLY DAMMATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E8,
+ },
+ [0x8E9]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC CURLY KASRATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8E9,
+ },
+ [0x8EA]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC TONE ONE DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8EA,
+ },
+ [0x8EB]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC TONE TWO DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8EB,
+ },
+ [0x8EC]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC TONE LOOP ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8EC,
+ },
+ [0x8ED]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC TONE ONE DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8ED,
+ },
+ [0x8EE]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC TONE TWO DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8EE,
+ },
+ [0x8EF]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC TONE LOOP BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8EF,
+ },
+ [0x8F0]={
+ category="mn",
+ combining=0x1B,
+ description="ARABIC OPEN FATHATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F0,
+ },
+ [0x8F1]={
+ category="mn",
+ combining=0x1C,
+ description="ARABIC OPEN DAMMATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F1,
+ },
+ [0x8F2]={
+ category="mn",
+ combining=0x1D,
+ description="ARABIC OPEN KASRATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F2,
+ },
+ [0x8F3]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC SMALL HIGH WAW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F3,
+ },
+ [0x8F4]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC FATHA WITH RING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F4,
+ },
+ [0x8F5]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC FATHA WITH DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F5,
+ },
+ [0x8F6]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC KASRA WITH DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F6,
+ },
+ [0x8F7]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC LEFT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F7,
+ },
+ [0x8F8]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC RIGHT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F8,
+ },
+ [0x8F9]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC LEFT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8F9,
+ },
+ [0x8FA]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC RIGHT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FA,
+ },
+ [0x8FB]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC DOUBLE RIGHT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FB,
+ },
+ [0x8FC]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FC,
+ },
+ [0x8FD]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC RIGHT ARROWHEAD ABOVE WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FD,
+ },
+ [0x8FE]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC DAMMA WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FE,
+ },
+ [0x8FF]={
+ category="mn",
+ combining=0xE6,
+ description="ARABIC MARK SIDEWAYS NOON GHUNNA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8FF,
+ },
+ [0x900]={
+ category="mn",
+ description="DEVANAGARI SIGN INVERTED CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x900,
+ },
+ [0x901]={
+ adobename="candrabindudeva",
+ category="mn",
+ description="DEVANAGARI SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x901,
+ },
+ [0x902]={
+ adobename="anusvaradeva",
+ category="mn",
+ description="DEVANAGARI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x902,
+ },
+ [0x903]={
+ adobename="visargadeva",
+ category="mc",
+ description="DEVANAGARI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x903,
+ },
+ [0x904]={
+ category="lo",
+ description="DEVANAGARI LETTER SHORT A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x904,
+ },
+ [0x905]={
+ adobename="adeva",
+ category="lo",
+ description="DEVANAGARI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x905,
+ },
+ [0x906]={
+ adobename="aadeva",
+ category="lo",
+ description="DEVANAGARI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x906,
+ },
+ [0x907]={
+ adobename="ideva",
+ category="lo",
+ description="DEVANAGARI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x907,
+ },
+ [0x908]={
+ adobename="iideva",
+ category="lo",
+ description="DEVANAGARI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x908,
+ },
+ [0x909]={
+ adobename="udeva",
+ category="lo",
+ description="DEVANAGARI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x909,
+ },
+ [0x90A]={
+ adobename="uudeva",
+ category="lo",
+ description="DEVANAGARI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90A,
+ },
+ [0x90B]={
+ adobename="rvocalicdeva",
+ category="lo",
+ description="DEVANAGARI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90B,
+ },
+ [0x90C]={
+ adobename="lvocalicdeva",
+ category="lo",
+ description="DEVANAGARI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90C,
+ },
+ [0x90D]={
+ adobename="ecandradeva",
+ category="lo",
+ description="DEVANAGARI LETTER CANDRA E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90D,
+ },
+ [0x90E]={
+ adobename="eshortdeva",
+ category="lo",
+ description="DEVANAGARI LETTER SHORT E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90E,
+ },
+ [0x90F]={
+ adobename="edeva",
+ category="lo",
+ description="DEVANAGARI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x90F,
+ },
+ [0x910]={
+ adobename="aideva",
+ category="lo",
+ description="DEVANAGARI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x910,
+ },
+ [0x911]={
+ adobename="ocandradeva",
+ category="lo",
+ description="DEVANAGARI LETTER CANDRA O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x911,
+ },
+ [0x912]={
+ adobename="oshortdeva",
+ category="lo",
+ description="DEVANAGARI LETTER SHORT O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x912,
+ },
+ [0x913]={
+ adobename="odeva",
+ category="lo",
+ description="DEVANAGARI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x913,
+ },
+ [0x914]={
+ adobename="audeva",
+ category="lo",
+ description="DEVANAGARI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x914,
+ },
+ [0x915]={
+ adobename="kadeva",
+ category="lo",
+ description="DEVANAGARI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x915,
+ },
+ [0x916]={
+ adobename="khadeva",
+ category="lo",
+ description="DEVANAGARI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x916,
+ },
+ [0x917]={
+ adobename="gadeva",
+ category="lo",
+ description="DEVANAGARI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x917,
+ },
+ [0x918]={
+ adobename="ghadeva",
+ category="lo",
+ description="DEVANAGARI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x918,
+ },
+ [0x919]={
+ adobename="ngadeva",
+ category="lo",
+ description="DEVANAGARI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x919,
+ },
+ [0x91A]={
+ adobename="cadeva",
+ category="lo",
+ description="DEVANAGARI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91A,
+ },
+ [0x91B]={
+ adobename="chadeva",
+ category="lo",
+ description="DEVANAGARI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91B,
+ },
+ [0x91C]={
+ adobename="jadeva",
+ category="lo",
+ description="DEVANAGARI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91C,
+ },
+ [0x91D]={
+ adobename="jhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91D,
+ },
+ [0x91E]={
+ adobename="nyadeva",
+ category="lo",
+ description="DEVANAGARI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91E,
+ },
+ [0x91F]={
+ adobename="ttadeva",
+ category="lo",
+ description="DEVANAGARI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x91F,
+ },
+ [0x920]={
+ adobename="tthadeva",
+ category="lo",
+ description="DEVANAGARI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x920,
+ },
+ [0x921]={
+ adobename="ddadeva",
+ category="lo",
+ description="DEVANAGARI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x921,
+ },
+ [0x922]={
+ adobename="ddhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x922,
+ },
+ [0x923]={
+ adobename="nnadeva",
+ category="lo",
+ description="DEVANAGARI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x923,
+ },
+ [0x924]={
+ adobename="tadeva",
+ category="lo",
+ description="DEVANAGARI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x924,
+ },
+ [0x925]={
+ adobename="thadeva",
+ category="lo",
+ description="DEVANAGARI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x925,
+ },
+ [0x926]={
+ adobename="dadeva",
+ category="lo",
+ description="DEVANAGARI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x926,
+ },
+ [0x927]={
+ adobename="dhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x927,
+ },
+ [0x928]={
+ adobename="nadeva",
+ category="lo",
+ description="DEVANAGARI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x928,
+ },
+ [0x929]={
+ adobename="nnnadeva",
+ category="lo",
+ description="DEVANAGARI LETTER NNNA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x928, 0x93C },
+ unicodeslot=0x929,
+ },
+ [0x92A]={
+ adobename="padeva",
+ category="lo",
+ description="DEVANAGARI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92A,
+ },
+ [0x92B]={
+ adobename="phadeva",
+ category="lo",
+ description="DEVANAGARI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92B,
+ },
+ [0x92C]={
+ adobename="badeva",
+ category="lo",
+ description="DEVANAGARI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92C,
+ },
+ [0x92D]={
+ adobename="bhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92D,
+ },
+ [0x92E]={
+ adobename="madeva",
+ category="lo",
+ description="DEVANAGARI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92E,
+ },
+ [0x92F]={
+ adobename="yadeva",
+ category="lo",
+ description="DEVANAGARI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x92F,
+ },
+ [0x930]={
+ adobename="radeva",
+ category="lo",
+ description="DEVANAGARI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x930,
+ },
+ [0x931]={
+ adobename="rradeva",
+ category="lo",
+ description="DEVANAGARI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x930, 0x93C },
+ unicodeslot=0x931,
+ },
+ [0x932]={
+ adobename="ladeva",
+ category="lo",
+ description="DEVANAGARI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x932,
+ },
+ [0x933]={
+ adobename="lladeva",
+ category="lo",
+ description="DEVANAGARI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x933,
+ },
+ [0x934]={
+ adobename="llladeva",
+ category="lo",
+ description="DEVANAGARI LETTER LLLA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x933, 0x93C },
+ unicodeslot=0x934,
+ },
+ [0x935]={
+ adobename="vadeva",
+ category="lo",
+ description="DEVANAGARI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x935,
+ },
+ [0x936]={
+ adobename="shadeva",
+ category="lo",
+ description="DEVANAGARI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x936,
+ },
+ [0x937]={
+ adobename="ssadeva",
+ category="lo",
+ description="DEVANAGARI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x937,
+ },
+ [0x938]={
+ adobename="sadeva",
+ category="lo",
+ description="DEVANAGARI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x938,
+ },
+ [0x939]={
+ adobename="hadeva",
+ category="lo",
+ description="DEVANAGARI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x939,
+ },
+ [0x93A]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN OE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x93A,
+ },
+ [0x93B]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN OOE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x93B,
+ },
+ [0x93C]={
+ adobename="nuktadeva",
+ category="mn",
+ combining=0x7,
+ description="DEVANAGARI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x93C,
+ },
+ [0x93D]={
+ adobename="avagrahadeva",
+ category="lo",
+ description="DEVANAGARI SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x93D,
+ },
+ [0x93E]={
+ adobename="aavowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x93E,
+ },
+ [0x93F]={
+ adobename="ivowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x93F,
+ },
+ [0x940]={
+ adobename="iivowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x940,
+ },
+ [0x941]={
+ adobename="uvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x941,
+ },
+ [0x942]={
+ adobename="uuvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x942,
+ },
+ [0x943]={
+ adobename="rvocalicvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x943,
+ },
+ [0x944]={
+ adobename="rrvocalicvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x944,
+ },
+ [0x945]={
+ adobename="ecandravowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN CANDRA E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x945,
+ },
+ [0x946]={
+ adobename="eshortvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN SHORT E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x946,
+ },
+ [0x947]={
+ adobename="evowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x947,
+ },
+ [0x948]={
+ adobename="aivowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x948,
+ },
+ [0x949]={
+ adobename="ocandravowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN CANDRA O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x949,
+ },
+ [0x94A]={
+ adobename="oshortvowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN SHORT O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x94A,
+ },
+ [0x94B]={
+ adobename="ovowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x94B,
+ },
+ [0x94C]={
+ adobename="auvowelsigndeva",
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x94C,
+ },
+ [0x94D]={
+ adobename="viramadeva",
+ category="mn",
+ combining=0x9,
+ description="DEVANAGARI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x94D,
+ },
+ [0x94E]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN PRISHTHAMATRA E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x94E,
+ },
+ [0x94F]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN AW",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x94F,
+ },
+ [0x950]={
+ adobename="omdeva",
+ category="lo",
+ description="DEVANAGARI OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x950,
+ },
+ [0x951]={
+ adobename="udattadeva",
+ category="mn",
+ combining=0xE6,
+ description="DEVANAGARI STRESS SIGN UDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x951,
+ },
+ [0x952]={
+ adobename="anudattadeva",
+ category="mn",
+ combining=0xDC,
+ description="DEVANAGARI STRESS SIGN ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x952,
+ },
+ [0x953]={
+ adobename="gravedeva",
+ category="mn",
+ combining=0xE6,
+ description="DEVANAGARI GRAVE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x953,
+ },
+ [0x954]={
+ adobename="acutedeva",
+ category="mn",
+ combining=0xE6,
+ description="DEVANAGARI ACUTE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x954,
+ },
+ [0x955]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN CANDRA LONG E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x955,
+ },
+ [0x956]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x956,
+ },
+ [0x957]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN UUE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x957,
+ },
+ [0x958]={
+ adobename="qadeva",
+ category="lo",
+ description="DEVANAGARI LETTER QA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x915, 0x93C },
+ unicodeslot=0x958,
+ },
+ [0x959]={
+ adobename="khhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER KHHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x916, 0x93C },
+ unicodeslot=0x959,
+ },
+ [0x95A]={
+ adobename="ghhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER GHHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x917, 0x93C },
+ unicodeslot=0x95A,
+ },
+ [0x95B]={
+ adobename="zadeva",
+ category="lo",
+ description="DEVANAGARI LETTER ZA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x91C, 0x93C },
+ unicodeslot=0x95B,
+ },
+ [0x95C]={
+ adobename="dddhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER DDDHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x921, 0x93C },
+ unicodeslot=0x95C,
+ },
+ [0x95D]={
+ adobename="rhadeva",
+ category="lo",
+ description="DEVANAGARI LETTER RHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x922, 0x93C },
+ unicodeslot=0x95D,
+ },
+ [0x95E]={
+ adobename="fadeva",
+ category="lo",
+ description="DEVANAGARI LETTER FA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x92B, 0x93C },
+ unicodeslot=0x95E,
+ },
+ [0x95F]={
+ adobename="yyadeva",
+ category="lo",
+ description="DEVANAGARI LETTER YYA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x92F, 0x93C },
+ unicodeslot=0x95F,
+ },
+ [0x960]={
+ adobename="rrvocalicdeva",
+ category="lo",
+ description="DEVANAGARI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x960,
+ },
+ [0x961]={
+ adobename="llvocalicdeva",
+ category="lo",
+ description="DEVANAGARI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x961,
+ },
+ [0x962]={
+ adobename="lvocalicvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x962,
+ },
+ [0x963]={
+ adobename="llvocalicvowelsigndeva",
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x963,
+ },
+ [0x964]={
+ adobename="danda",
+ category="po",
+ description="DEVANAGARI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x964,
+ },
+ [0x965]={
+ adobename="dbldanda",
+ category="po",
+ description="DEVANAGARI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x965,
+ },
+ [0x966]={
+ adobename="zerodeva",
+ category="nd",
+ description="DEVANAGARI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x966,
+ },
+ [0x967]={
+ adobename="onedeva",
+ category="nd",
+ description="DEVANAGARI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x967,
+ },
+ [0x968]={
+ adobename="twodeva",
+ category="nd",
+ description="DEVANAGARI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x968,
+ },
+ [0x969]={
+ adobename="threedeva",
+ category="nd",
+ description="DEVANAGARI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x969,
+ },
+ [0x96A]={
+ adobename="fourdeva",
+ category="nd",
+ description="DEVANAGARI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96A,
+ },
+ [0x96B]={
+ adobename="fivedeva",
+ category="nd",
+ description="DEVANAGARI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96B,
+ },
+ [0x96C]={
+ adobename="sixdeva",
+ category="nd",
+ description="DEVANAGARI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96C,
+ },
+ [0x96D]={
+ adobename="sevendeva",
+ category="nd",
+ description="DEVANAGARI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96D,
+ },
+ [0x96E]={
+ adobename="eightdeva",
+ category="nd",
+ description="DEVANAGARI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96E,
+ },
+ [0x96F]={
+ adobename="ninedeva",
+ category="nd",
+ description="DEVANAGARI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x96F,
+ },
+ [0x970]={
+ adobename="abbreviationsigndeva",
+ category="po",
+ description="DEVANAGARI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x970,
+ },
+ [0x971]={
+ category="lm",
+ description="DEVANAGARI SIGN HIGH SPACING DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x971,
+ },
+ [0x972]={
+ category="lo",
+ description="DEVANAGARI LETTER CANDRA A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x972,
+ },
+ [0x973]={
+ category="lo",
+ description="DEVANAGARI LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x973,
+ },
+ [0x974]={
+ category="lo",
+ description="DEVANAGARI LETTER OOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x974,
+ },
+ [0x975]={
+ category="lo",
+ description="DEVANAGARI LETTER AW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x975,
+ },
+ [0x976]={
+ category="lo",
+ description="DEVANAGARI LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x976,
+ },
+ [0x977]={
+ category="lo",
+ description="DEVANAGARI LETTER UUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x977,
+ },
+ [0x978]={
+ category="lo",
+ description="DEVANAGARI LETTER MARWARI DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x978,
+ },
+ [0x979]={
+ category="lo",
+ description="DEVANAGARI LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x979,
+ },
+ [0x97A]={
+ category="lo",
+ description="DEVANAGARI LETTER HEAVY YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97A,
+ },
+ [0x97B]={
+ category="lo",
+ description="DEVANAGARI LETTER GGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97B,
+ },
+ [0x97C]={
+ category="lo",
+ description="DEVANAGARI LETTER JJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97C,
+ },
+ [0x97D]={
+ category="lo",
+ description="DEVANAGARI LETTER GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97D,
+ },
+ [0x97E]={
+ category="lo",
+ description="DEVANAGARI LETTER DDDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97E,
+ },
+ [0x97F]={
+ category="lo",
+ description="DEVANAGARI LETTER BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x97F,
+ },
+ [0x980]={
+ category="lo",
+ description="BENGALI ANJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x980,
+ },
+ [0x981]={
+ adobename="candrabindubengali",
+ category="mn",
+ description="BENGALI SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x981,
+ },
+ [0x982]={
+ adobename="anusvarabengali",
+ category="mc",
+ description="BENGALI SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x982,
+ },
+ [0x983]={
+ adobename="visargabengali",
+ category="mc",
+ description="BENGALI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x983,
+ },
+ [0x985]={
+ adobename="abengali",
+ category="lo",
+ description="BENGALI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x985,
+ },
+ [0x986]={
+ adobename="aabengali",
+ category="lo",
+ description="BENGALI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x986,
+ },
+ [0x987]={
+ adobename="ibengali",
+ category="lo",
+ description="BENGALI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x987,
+ },
+ [0x988]={
+ adobename="iibengali",
+ category="lo",
+ description="BENGALI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x988,
+ },
+ [0x989]={
+ adobename="ubengali",
+ category="lo",
+ description="BENGALI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x989,
+ },
+ [0x98A]={
+ adobename="uubengali",
+ category="lo",
+ description="BENGALI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x98A,
+ },
+ [0x98B]={
+ adobename="rvocalicbengali",
+ category="lo",
+ description="BENGALI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x98B,
+ },
+ [0x98C]={
+ adobename="lvocalicbengali",
+ category="lo",
+ description="BENGALI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x98C,
+ },
+ [0x98F]={
+ adobename="ebengali",
+ category="lo",
+ description="BENGALI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x98F,
+ },
+ [0x990]={
+ adobename="aibengali",
+ category="lo",
+ description="BENGALI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x990,
+ },
+ [0x993]={
+ adobename="obengali",
+ category="lo",
+ description="BENGALI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x993,
+ },
+ [0x994]={
+ adobename="aubengali",
+ category="lo",
+ description="BENGALI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x994,
+ },
+ [0x995]={
+ adobename="kabengali",
+ category="lo",
+ description="BENGALI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x995,
+ },
+ [0x996]={
+ adobename="khabengali",
+ category="lo",
+ description="BENGALI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x996,
+ },
+ [0x997]={
+ adobename="gabengali",
+ category="lo",
+ description="BENGALI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x997,
+ },
+ [0x998]={
+ adobename="ghabengali",
+ category="lo",
+ description="BENGALI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x998,
+ },
+ [0x999]={
+ adobename="ngabengali",
+ category="lo",
+ description="BENGALI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x999,
+ },
+ [0x99A]={
+ adobename="cabengali",
+ category="lo",
+ description="BENGALI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99A,
+ },
+ [0x99B]={
+ adobename="chabengali",
+ category="lo",
+ description="BENGALI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99B,
+ },
+ [0x99C]={
+ adobename="jabengali",
+ category="lo",
+ description="BENGALI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99C,
+ },
+ [0x99D]={
+ adobename="jhabengali",
+ category="lo",
+ description="BENGALI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99D,
+ },
+ [0x99E]={
+ adobename="nyabengali",
+ category="lo",
+ description="BENGALI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99E,
+ },
+ [0x99F]={
+ adobename="ttabengali",
+ category="lo",
+ description="BENGALI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x99F,
+ },
+ [0x9A0]={
+ adobename="tthabengali",
+ category="lo",
+ description="BENGALI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A0,
+ },
+ [0x9A1]={
+ adobename="ddabengali",
+ category="lo",
+ description="BENGALI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A1,
+ },
+ [0x9A2]={
+ adobename="ddhabengali",
+ category="lo",
+ description="BENGALI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A2,
+ },
+ [0x9A3]={
+ adobename="nnabengali",
+ category="lo",
+ description="BENGALI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A3,
+ },
+ [0x9A4]={
+ adobename="tabengali",
+ category="lo",
+ description="BENGALI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A4,
+ },
+ [0x9A5]={
+ adobename="thabengali",
+ category="lo",
+ description="BENGALI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A5,
+ },
+ [0x9A6]={
+ adobename="dabengali",
+ category="lo",
+ description="BENGALI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A6,
+ },
+ [0x9A7]={
+ adobename="dhabengali",
+ category="lo",
+ description="BENGALI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A7,
+ },
+ [0x9A8]={
+ adobename="nabengali",
+ category="lo",
+ description="BENGALI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9A8,
+ },
+ [0x9AA]={
+ adobename="pabengali",
+ category="lo",
+ description="BENGALI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AA,
+ },
+ [0x9AB]={
+ adobename="phabengali",
+ category="lo",
+ description="BENGALI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AB,
+ },
+ [0x9AC]={
+ adobename="babengali",
+ category="lo",
+ description="BENGALI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AC,
+ },
+ [0x9AD]={
+ adobename="bhabengali",
+ category="lo",
+ description="BENGALI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AD,
+ },
+ [0x9AE]={
+ adobename="mabengali",
+ category="lo",
+ description="BENGALI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AE,
+ },
+ [0x9AF]={
+ adobename="yabengali",
+ category="lo",
+ description="BENGALI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9AF,
+ },
+ [0x9B0]={
+ adobename="rabengali",
+ category="lo",
+ description="BENGALI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B0,
+ },
+ [0x9B2]={
+ adobename="labengali",
+ category="lo",
+ description="BENGALI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B2,
+ },
+ [0x9B6]={
+ adobename="shabengali",
+ category="lo",
+ description="BENGALI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B6,
+ },
+ [0x9B7]={
+ adobename="ssabengali",
+ category="lo",
+ description="BENGALI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B7,
+ },
+ [0x9B8]={
+ adobename="sabengali",
+ category="lo",
+ description="BENGALI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B8,
+ },
+ [0x9B9]={
+ adobename="habengali",
+ category="lo",
+ description="BENGALI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9B9,
+ },
+ [0x9BC]={
+ adobename="nuktabengali",
+ category="mn",
+ combining=0x7,
+ description="BENGALI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9BC,
+ },
+ [0x9BD]={
+ category="lo",
+ description="BENGALI SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9BD,
+ },
+ [0x9BE]={
+ adobename="aavowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9BE,
+ },
+ [0x9BF]={
+ adobename="ivowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9BF,
+ },
+ [0x9C0]={
+ adobename="iivowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9C0,
+ },
+ [0x9C1]={
+ adobename="uvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9C1,
+ },
+ [0x9C2]={
+ adobename="uuvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9C2,
+ },
+ [0x9C3]={
+ adobename="rvocalicvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9C3,
+ },
+ [0x9C4]={
+ adobename="rrvocalicvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9C4,
+ },
+ [0x9C7]={
+ adobename="evowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9C7,
+ },
+ [0x9C8]={
+ adobename="aivowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9C8,
+ },
+ [0x9CB]={
+ adobename="ovowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x9C7, 0x9BE },
+ unicodeslot=0x9CB,
+ },
+ [0x9CC]={
+ adobename="auvowelsignbengali",
+ category="mc",
+ description="BENGALI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x9C7, 0x9D7 },
+ unicodeslot=0x9CC,
+ },
+ [0x9CD]={
+ adobename="viramabengali",
+ category="mn",
+ combining=0x9,
+ description="BENGALI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9CD,
+ },
+ [0x9CE]={
+ category="lo",
+ description="BENGALI LETTER KHANDA TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9CE,
+ },
+ [0x9D7]={
+ adobename="aulengthmarkbengali",
+ category="mc",
+ description="BENGALI AU LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x9D7,
+ },
+ [0x9DC]={
+ adobename="rrabengali",
+ category="lo",
+ description="BENGALI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x9A1, 0x9BC },
+ unicodeslot=0x9DC,
+ },
+ [0x9DD]={
+ adobename="rhabengali",
+ category="lo",
+ description="BENGALI LETTER RHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x9A2, 0x9BC },
+ unicodeslot=0x9DD,
+ },
+ [0x9DF]={
+ adobename="yyabengali",
+ category="lo",
+ description="BENGALI LETTER YYA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x9AF, 0x9BC },
+ unicodeslot=0x9DF,
+ },
+ [0x9E0]={
+ adobename="rrvocalicbengali",
+ category="lo",
+ description="BENGALI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9E0,
+ },
+ [0x9E1]={
+ adobename="llvocalicbengali",
+ category="lo",
+ description="BENGALI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9E1,
+ },
+ [0x9E2]={
+ adobename="lvocalicvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9E2,
+ },
+ [0x9E3]={
+ adobename="llvocalicvowelsignbengali",
+ category="mn",
+ description="BENGALI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9E3,
+ },
+ [0x9E6]={
+ adobename="zerobengali",
+ category="nd",
+ description="BENGALI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9E6,
+ },
+ [0x9E7]={
+ adobename="onebengali",
+ category="nd",
+ description="BENGALI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9E7,
+ },
+ [0x9E8]={
+ adobename="twobengali",
+ category="nd",
+ description="BENGALI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9E8,
+ },
+ [0x9E9]={
+ adobename="threebengali",
+ category="nd",
+ description="BENGALI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9E9,
+ },
+ [0x9EA]={
+ adobename="fourbengali",
+ category="nd",
+ description="BENGALI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9EA,
+ },
+ [0x9EB]={
+ adobename="fivebengali",
+ category="nd",
+ description="BENGALI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9EB,
+ },
+ [0x9EC]={
+ adobename="sixbengali",
+ category="nd",
+ description="BENGALI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9EC,
+ },
+ [0x9ED]={
+ adobename="sevenbengali",
+ category="nd",
+ description="BENGALI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9ED,
+ },
+ [0x9EE]={
+ adobename="eightbengali",
+ category="nd",
+ description="BENGALI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9EE,
+ },
+ [0x9EF]={
+ adobename="ninebengali",
+ category="nd",
+ description="BENGALI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x9EF,
+ },
+ [0x9F0]={
+ adobename="ramiddlediagonalbengali",
+ category="lo",
+ description="BENGALI LETTER RA WITH MIDDLE DIAGONAL",
+ direction="l",
+ linebreak="al",
+ shcode=0x9B0,
+ unicodeslot=0x9F0,
+ },
+ [0x9F1]={
+ adobename="ralowerdiagonalbengali",
+ category="lo",
+ description="BENGALI LETTER RA WITH LOWER DIAGONAL",
+ direction="l",
+ linebreak="al",
+ shcode=0x9B0,
+ unicodeslot=0x9F1,
+ },
+ [0x9F2]={
+ adobename="rupeemarkbengali",
+ category="sc",
+ description="BENGALI RUPEE MARK",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x9F2,
+ },
+ [0x9F3]={
+ adobename="rupeesignbengali",
+ category="sc",
+ description="BENGALI RUPEE SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x9F3,
+ },
+ [0x9F4]={
+ adobename="onenumeratorbengali",
+ category="no",
+ description="BENGALI CURRENCY NUMERATOR ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9F4,
+ },
+ [0x9F5]={
+ adobename="twonumeratorbengali",
+ category="no",
+ description="BENGALI CURRENCY NUMERATOR TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9F5,
+ },
+ [0x9F6]={
+ adobename="threenumeratorbengali",
+ category="no",
+ description="BENGALI CURRENCY NUMERATOR THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9F6,
+ },
+ [0x9F7]={
+ adobename="fournumeratorbengali",
+ category="no",
+ description="BENGALI CURRENCY NUMERATOR FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9F7,
+ },
+ [0x9F8]={
+ adobename="denominatorminusonenumeratorbengali",
+ category="no",
+ description="BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9F8,
+ },
+ [0x9F9]={
+ adobename="sixteencurrencydenominatorbengali",
+ category="no",
+ description="BENGALI CURRENCY DENOMINATOR SIXTEEN",
+ direction="l",
+ linebreak="po",
+ unicodeslot=0x9F9,
+ },
+ [0x9FA]={
+ adobename="issharbengali",
+ category="so",
+ description="BENGALI ISSHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x9FA,
+ },
+ [0x9FB]={
+ category="sc",
+ description="BENGALI GANDA MARK",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x9FB,
+ },
+ [0xA01]={
+ category="mn",
+ description="GURMUKHI SIGN ADAK BINDI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA01,
+ },
+ [0xA02]={
+ adobename="bindigurmukhi",
+ category="mn",
+ description="GURMUKHI SIGN BINDI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA02,
+ },
+ [0xA03]={
+ category="mc",
+ description="GURMUKHI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA03,
+ },
+ [0xA05]={
+ adobename="agurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA05,
+ },
+ [0xA06]={
+ adobename="aagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA06,
+ },
+ [0xA07]={
+ adobename="igurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA07,
+ },
+ [0xA08]={
+ adobename="iigurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA08,
+ },
+ [0xA09]={
+ adobename="ugurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA09,
+ },
+ [0xA0A]={
+ adobename="uugurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA0A,
+ },
+ [0xA0F]={
+ adobename="eegurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA0F,
+ },
+ [0xA10]={
+ adobename="aigurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA10,
+ },
+ [0xA13]={
+ adobename="oogurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA13,
+ },
+ [0xA14]={
+ adobename="augurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA14,
+ },
+ [0xA15]={
+ adobename="kagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA15,
+ },
+ [0xA16]={
+ adobename="khagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA16,
+ },
+ [0xA17]={
+ adobename="gagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA17,
+ },
+ [0xA18]={
+ adobename="ghagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA18,
+ },
+ [0xA19]={
+ adobename="ngagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA19,
+ },
+ [0xA1A]={
+ adobename="cagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1A,
+ },
+ [0xA1B]={
+ adobename="chagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1B,
+ },
+ [0xA1C]={
+ adobename="jagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1C,
+ },
+ [0xA1D]={
+ adobename="jhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1D,
+ },
+ [0xA1E]={
+ adobename="nyagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1E,
+ },
+ [0xA1F]={
+ adobename="ttagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA1F,
+ },
+ [0xA20]={
+ adobename="tthagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA20,
+ },
+ [0xA21]={
+ adobename="ddagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA21,
+ },
+ [0xA22]={
+ adobename="ddhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA22,
+ },
+ [0xA23]={
+ adobename="nnagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA23,
+ },
+ [0xA24]={
+ adobename="tagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA24,
+ },
+ [0xA25]={
+ adobename="thagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA25,
+ },
+ [0xA26]={
+ adobename="dagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA26,
+ },
+ [0xA27]={
+ adobename="dhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA27,
+ },
+ [0xA28]={
+ adobename="nagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA28,
+ },
+ [0xA2A]={
+ adobename="pagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2A,
+ },
+ [0xA2B]={
+ adobename="phagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2B,
+ },
+ [0xA2C]={
+ adobename="bagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2C,
+ },
+ [0xA2D]={
+ adobename="bhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2D,
+ },
+ [0xA2E]={
+ adobename="magurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2E,
+ },
+ [0xA2F]={
+ adobename="yagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA2F,
+ },
+ [0xA30]={
+ adobename="ragurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA30,
+ },
+ [0xA32]={
+ adobename="lagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA32,
+ },
+ [0xA33]={
+ category="lo",
+ description="GURMUKHI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA32, 0xA3C },
+ unicodeslot=0xA33,
+ },
+ [0xA35]={
+ adobename="vagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA35,
+ },
+ [0xA36]={
+ adobename="shagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA38, 0xA3C },
+ unicodeslot=0xA36,
+ },
+ [0xA38]={
+ adobename="sagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA38,
+ },
+ [0xA39]={
+ adobename="hagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA39,
+ },
+ [0xA3C]={
+ adobename="nuktagurmukhi",
+ category="mn",
+ combining=0x7,
+ description="GURMUKHI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA3C,
+ },
+ [0xA3E]={
+ adobename="aamatragurmukhi",
+ category="mc",
+ description="GURMUKHI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA3E,
+ },
+ [0xA3F]={
+ adobename="imatragurmukhi",
+ category="mc",
+ description="GURMUKHI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA3F,
+ },
+ [0xA40]={
+ adobename="iimatragurmukhi",
+ category="mc",
+ description="GURMUKHI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA40,
+ },
+ [0xA41]={
+ adobename="umatragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA41,
+ },
+ [0xA42]={
+ adobename="uumatragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA42,
+ },
+ [0xA47]={
+ adobename="eematragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA47,
+ },
+ [0xA48]={
+ adobename="aimatragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA48,
+ },
+ [0xA4B]={
+ adobename="oomatragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN OO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA4B,
+ },
+ [0xA4C]={
+ adobename="aumatragurmukhi",
+ category="mn",
+ description="GURMUKHI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA4C,
+ },
+ [0xA4D]={
+ adobename="halantgurmukhi",
+ category="mn",
+ combining=0x9,
+ description="GURMUKHI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA4D,
+ },
+ [0xA51]={
+ category="mn",
+ description="GURMUKHI SIGN UDAAT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA51,
+ },
+ [0xA59]={
+ adobename="khhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER KHHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA16, 0xA3C },
+ unicodeslot=0xA59,
+ },
+ [0xA5A]={
+ adobename="ghhagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER GHHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA17, 0xA3C },
+ unicodeslot=0xA5A,
+ },
+ [0xA5B]={
+ adobename="zagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER ZA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA1C, 0xA3C },
+ unicodeslot=0xA5B,
+ },
+ [0xA5C]={
+ adobename="rragurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C,
+ },
+ [0xA5E]={
+ adobename="fagurmukhi",
+ category="lo",
+ description="GURMUKHI LETTER FA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xA2B, 0xA3C },
+ unicodeslot=0xA5E,
+ },
+ [0xA66]={
+ adobename="zerogurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA66,
+ },
+ [0xA67]={
+ adobename="onegurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA67,
+ },
+ [0xA68]={
+ adobename="twogurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA68,
+ },
+ [0xA69]={
+ adobename="threegurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA69,
+ },
+ [0xA6A]={
+ adobename="fourgurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6A,
+ },
+ [0xA6B]={
+ adobename="fivegurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6B,
+ },
+ [0xA6C]={
+ adobename="sixgurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6C,
+ },
+ [0xA6D]={
+ adobename="sevengurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6D,
+ },
+ [0xA6E]={
+ adobename="eightgurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6E,
+ },
+ [0xA6F]={
+ adobename="ninegurmukhi",
+ category="nd",
+ description="GURMUKHI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA6F,
+ },
+ [0xA70]={
+ adobename="tippigurmukhi",
+ category="mn",
+ description="GURMUKHI TIPPI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA70,
+ },
+ [0xA71]={
+ adobename="addakgurmukhi",
+ category="mn",
+ description="GURMUKHI ADDAK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA71,
+ },
+ [0xA72]={
+ adobename="irigurmukhi",
+ category="lo",
+ description="GURMUKHI IRI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72,
+ },
+ [0xA73]={
+ adobename="uragurmukhi",
+ category="lo",
+ description="GURMUKHI URA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73,
+ },
+ [0xA74]={
+ adobename="ekonkargurmukhi",
+ category="lo",
+ description="GURMUKHI EK ONKAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74,
+ },
+ [0xA75]={
+ category="mn",
+ description="GURMUKHI SIGN YAKASH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA75,
+ },
+ [0xA81]={
+ adobename="candrabindugujarati",
+ category="mn",
+ description="GUJARATI SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA81,
+ },
+ [0xA82]={
+ adobename="anusvaragujarati",
+ category="mn",
+ description="GUJARATI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA82,
+ },
+ [0xA83]={
+ adobename="visargagujarati",
+ category="mc",
+ description="GUJARATI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA83,
+ },
+ [0xA85]={
+ adobename="agujarati",
+ category="lo",
+ description="GUJARATI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85,
+ },
+ [0xA86]={
+ adobename="aagujarati",
+ category="lo",
+ description="GUJARATI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86,
+ },
+ [0xA87]={
+ adobename="igujarati",
+ category="lo",
+ description="GUJARATI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA87,
+ },
+ [0xA88]={
+ adobename="iigujarati",
+ category="lo",
+ description="GUJARATI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88,
+ },
+ [0xA89]={
+ adobename="ugujarati",
+ category="lo",
+ description="GUJARATI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89,
+ },
+ [0xA8A]={
+ adobename="uugujarati",
+ category="lo",
+ description="GUJARATI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A,
+ },
+ [0xA8B]={
+ adobename="rvocalicgujarati",
+ category="lo",
+ description="GUJARATI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B,
+ },
+ [0xA8C]={
+ category="lo",
+ description="GUJARATI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8C,
+ },
+ [0xA8D]={
+ adobename="ecandragujarati",
+ category="lo",
+ description="GUJARATI VOWEL CANDRA E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8D,
+ },
+ [0xA8F]={
+ adobename="egujarati",
+ category="lo",
+ description="GUJARATI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F,
+ },
+ [0xA90]={
+ adobename="aigujarati",
+ category="lo",
+ description="GUJARATI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90,
+ },
+ [0xA91]={
+ adobename="ocandragujarati",
+ category="lo",
+ description="GUJARATI VOWEL CANDRA O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91,
+ },
+ [0xA93]={
+ adobename="ogujarati",
+ category="lo",
+ description="GUJARATI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93,
+ },
+ [0xA94]={
+ adobename="augujarati",
+ category="lo",
+ description="GUJARATI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA94,
+ },
+ [0xA95]={
+ adobename="kagujarati",
+ category="lo",
+ description="GUJARATI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA95,
+ },
+ [0xA96]={
+ adobename="khagujarati",
+ category="lo",
+ description="GUJARATI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA96,
+ },
+ [0xA97]={
+ adobename="gagujarati",
+ category="lo",
+ description="GUJARATI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA97,
+ },
+ [0xA98]={
+ adobename="ghagujarati",
+ category="lo",
+ description="GUJARATI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98,
+ },
+ [0xA99]={
+ adobename="ngagujarati",
+ category="lo",
+ description="GUJARATI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99,
+ },
+ [0xA9A]={
+ adobename="cagujarati",
+ category="lo",
+ description="GUJARATI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A,
+ },
+ [0xA9B]={
+ adobename="chagujarati",
+ category="lo",
+ description="GUJARATI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B,
+ },
+ [0xA9C]={
+ adobename="jagujarati",
+ category="lo",
+ description="GUJARATI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C,
+ },
+ [0xA9D]={
+ adobename="jhagujarati",
+ category="lo",
+ description="GUJARATI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9D,
+ },
+ [0xA9E]={
+ adobename="nyagujarati",
+ category="lo",
+ description="GUJARATI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9E,
+ },
+ [0xA9F]={
+ adobename="ttagujarati",
+ category="lo",
+ description="GUJARATI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9F,
+ },
+ [0xAA0]={
+ adobename="tthagujarati",
+ category="lo",
+ description="GUJARATI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0,
+ },
+ [0xAA1]={
+ adobename="ddagujarati",
+ category="lo",
+ description="GUJARATI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1,
+ },
+ [0xAA2]={
+ adobename="ddhagujarati",
+ category="lo",
+ description="GUJARATI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA2,
+ },
+ [0xAA3]={
+ adobename="nnagujarati",
+ category="lo",
+ description="GUJARATI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA3,
+ },
+ [0xAA4]={
+ adobename="tagujarati",
+ category="lo",
+ description="GUJARATI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA4,
+ },
+ [0xAA5]={
+ adobename="thagujarati",
+ category="lo",
+ description="GUJARATI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA5,
+ },
+ [0xAA6]={
+ adobename="dagujarati",
+ category="lo",
+ description="GUJARATI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA6,
+ },
+ [0xAA7]={
+ adobename="dhagujarati",
+ category="lo",
+ description="GUJARATI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA7,
+ },
+ [0xAA8]={
+ adobename="nagujarati",
+ category="lo",
+ description="GUJARATI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA8,
+ },
+ [0xAAA]={
+ adobename="pagujarati",
+ category="lo",
+ description="GUJARATI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAA,
+ },
+ [0xAAB]={
+ adobename="phagujarati",
+ category="lo",
+ description="GUJARATI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAB,
+ },
+ [0xAAC]={
+ adobename="bagujarati",
+ category="lo",
+ description="GUJARATI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAC,
+ },
+ [0xAAD]={
+ adobename="bhagujarati",
+ category="lo",
+ description="GUJARATI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAD,
+ },
+ [0xAAE]={
+ adobename="magujarati",
+ category="lo",
+ description="GUJARATI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE,
+ },
+ [0xAAF]={
+ adobename="yagujarati",
+ category="lo",
+ description="GUJARATI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF,
+ },
+ [0xAB0]={
+ adobename="ragujarati",
+ category="lo",
+ description="GUJARATI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0,
+ },
+ [0xAB2]={
+ adobename="lagujarati",
+ category="lo",
+ description="GUJARATI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2,
+ },
+ [0xAB3]={
+ adobename="llagujarati",
+ category="lo",
+ description="GUJARATI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3,
+ },
+ [0xAB5]={
+ adobename="vagujarati",
+ category="lo",
+ description="GUJARATI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB5,
+ },
+ [0xAB6]={
+ adobename="shagujarati",
+ category="lo",
+ description="GUJARATI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB6,
+ },
+ [0xAB7]={
+ adobename="ssagujarati",
+ category="lo",
+ description="GUJARATI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7,
+ },
+ [0xAB8]={
+ adobename="sagujarati",
+ category="lo",
+ description="GUJARATI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8,
+ },
+ [0xAB9]={
+ adobename="hagujarati",
+ category="lo",
+ description="GUJARATI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9,
+ },
+ [0xABC]={
+ adobename="nuktagujarati",
+ category="mn",
+ combining=0x7,
+ description="GUJARATI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABC,
+ },
+ [0xABD]={
+ category="lo",
+ description="GUJARATI SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD,
+ },
+ [0xABE]={
+ adobename="aavowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE,
+ },
+ [0xABF]={
+ adobename="ivowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABF,
+ },
+ [0xAC0]={
+ adobename="iivowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAC0,
+ },
+ [0xAC1]={
+ adobename="uvowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC1,
+ },
+ [0xAC2]={
+ adobename="uuvowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC2,
+ },
+ [0xAC3]={
+ adobename="rvocalicvowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC3,
+ },
+ [0xAC4]={
+ adobename="rrvocalicvowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC4,
+ },
+ [0xAC5]={
+ adobename="ecandravowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN CANDRA E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC5,
+ },
+ [0xAC7]={
+ adobename="evowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC7,
+ },
+ [0xAC8]={
+ adobename="aivowelsigngujarati",
+ category="mn",
+ description="GUJARATI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAC8,
+ },
+ [0xAC9]={
+ adobename="ocandravowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN CANDRA O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAC9,
+ },
+ [0xACB]={
+ adobename="ovowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xACB,
+ },
+ [0xACC]={
+ adobename="auvowelsigngujarati",
+ category="mc",
+ description="GUJARATI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xACC,
+ },
+ [0xACD]={
+ adobename="viramagujarati",
+ category="mn",
+ combining=0x9,
+ description="GUJARATI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xACD,
+ },
+ [0xAD0]={
+ adobename="omgujarati",
+ category="lo",
+ description="GUJARATI OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAD0,
+ },
+ [0xAE0]={
+ adobename="rrvocalicgujarati",
+ category="lo",
+ description="GUJARATI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAE0,
+ },
+ [0xAE1]={
+ category="lo",
+ description="GUJARATI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAE1,
+ },
+ [0xAE2]={
+ category="mn",
+ description="GUJARATI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAE2,
+ },
+ [0xAE3]={
+ category="mn",
+ description="GUJARATI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAE3,
+ },
+ [0xAE6]={
+ adobename="zerogujarati",
+ category="nd",
+ description="GUJARATI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAE6,
+ },
+ [0xAE7]={
+ adobename="onegujarati",
+ category="nd",
+ description="GUJARATI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAE7,
+ },
+ [0xAE8]={
+ adobename="twogujarati",
+ category="nd",
+ description="GUJARATI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAE8,
+ },
+ [0xAE9]={
+ adobename="threegujarati",
+ category="nd",
+ description="GUJARATI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAE9,
+ },
+ [0xAEA]={
+ adobename="fourgujarati",
+ category="nd",
+ description="GUJARATI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAEA,
+ },
+ [0xAEB]={
+ adobename="fivegujarati",
+ category="nd",
+ description="GUJARATI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAEB,
+ },
+ [0xAEC]={
+ adobename="sixgujarati",
+ category="nd",
+ description="GUJARATI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAEC,
+ },
+ [0xAED]={
+ adobename="sevengujarati",
+ category="nd",
+ description="GUJARATI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAED,
+ },
+ [0xAEE]={
+ adobename="eightgujarati",
+ category="nd",
+ description="GUJARATI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAEE,
+ },
+ [0xAEF]={
+ adobename="ninegujarati",
+ category="nd",
+ description="GUJARATI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAEF,
+ },
+ [0xAF0]={
+ category="po",
+ description="GUJARATI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAF0,
+ },
+ [0xAF1]={
+ category="sc",
+ description="GUJARATI RUPEE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0xAF1,
+ },
+ [0xAF9]={
+ category="lo",
+ description="GUJARATI LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAF9,
+ },
+ [0xB01]={
+ category="mn",
+ description="ORIYA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB01,
+ },
+ [0xB02]={
+ category="mc",
+ description="ORIYA SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB02,
+ },
+ [0xB03]={
+ category="mc",
+ description="ORIYA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB03,
+ },
+ [0xB05]={
+ category="lo",
+ description="ORIYA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB05,
+ },
+ [0xB06]={
+ category="lo",
+ description="ORIYA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB06,
+ },
+ [0xB07]={
+ category="lo",
+ description="ORIYA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB07,
+ },
+ [0xB08]={
+ category="lo",
+ description="ORIYA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB08,
+ },
+ [0xB09]={
+ category="lo",
+ description="ORIYA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB09,
+ },
+ [0xB0A]={
+ category="lo",
+ description="ORIYA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB0A,
+ },
+ [0xB0B]={
+ category="lo",
+ description="ORIYA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB0B,
+ },
+ [0xB0C]={
+ category="lo",
+ description="ORIYA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB0C,
+ },
+ [0xB0F]={
+ category="lo",
+ description="ORIYA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB0F,
+ },
+ [0xB10]={
+ category="lo",
+ description="ORIYA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB10,
+ },
+ [0xB13]={
+ category="lo",
+ description="ORIYA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB13,
+ },
+ [0xB14]={
+ category="lo",
+ description="ORIYA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB14,
+ },
+ [0xB15]={
+ category="lo",
+ description="ORIYA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB15,
+ },
+ [0xB16]={
+ category="lo",
+ description="ORIYA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB16,
+ },
+ [0xB17]={
+ category="lo",
+ description="ORIYA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB17,
+ },
+ [0xB18]={
+ category="lo",
+ description="ORIYA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB18,
+ },
+ [0xB19]={
+ category="lo",
+ description="ORIYA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB19,
+ },
+ [0xB1A]={
+ category="lo",
+ description="ORIYA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1A,
+ },
+ [0xB1B]={
+ category="lo",
+ description="ORIYA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1B,
+ },
+ [0xB1C]={
+ category="lo",
+ description="ORIYA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1C,
+ },
+ [0xB1D]={
+ category="lo",
+ description="ORIYA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1D,
+ },
+ [0xB1E]={
+ category="lo",
+ description="ORIYA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1E,
+ },
+ [0xB1F]={
+ category="lo",
+ description="ORIYA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB1F,
+ },
+ [0xB20]={
+ category="lo",
+ description="ORIYA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB20,
+ },
+ [0xB21]={
+ category="lo",
+ description="ORIYA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB21,
+ },
+ [0xB22]={
+ category="lo",
+ description="ORIYA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB22,
+ },
+ [0xB23]={
+ category="lo",
+ description="ORIYA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB23,
+ },
+ [0xB24]={
+ category="lo",
+ description="ORIYA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB24,
+ },
+ [0xB25]={
+ category="lo",
+ description="ORIYA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB25,
+ },
+ [0xB26]={
+ category="lo",
+ description="ORIYA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB26,
+ },
+ [0xB27]={
+ category="lo",
+ description="ORIYA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB27,
+ },
+ [0xB28]={
+ category="lo",
+ description="ORIYA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB28,
+ },
+ [0xB2A]={
+ category="lo",
+ description="ORIYA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2A,
+ },
+ [0xB2B]={
+ category="lo",
+ description="ORIYA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2B,
+ },
+ [0xB2C]={
+ category="lo",
+ description="ORIYA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2C,
+ },
+ [0xB2D]={
+ category="lo",
+ description="ORIYA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2D,
+ },
+ [0xB2E]={
+ category="lo",
+ description="ORIYA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2E,
+ },
+ [0xB2F]={
+ category="lo",
+ description="ORIYA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB2F,
+ },
+ [0xB30]={
+ category="lo",
+ description="ORIYA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB30,
+ },
+ [0xB32]={
+ category="lo",
+ description="ORIYA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB32,
+ },
+ [0xB33]={
+ category="lo",
+ description="ORIYA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB33,
+ },
+ [0xB35]={
+ category="lo",
+ description="ORIYA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB35,
+ },
+ [0xB36]={
+ category="lo",
+ description="ORIYA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB36,
+ },
+ [0xB37]={
+ category="lo",
+ description="ORIYA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB37,
+ },
+ [0xB38]={
+ category="lo",
+ description="ORIYA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB38,
+ },
+ [0xB39]={
+ category="lo",
+ description="ORIYA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB39,
+ },
+ [0xB3C]={
+ category="mn",
+ combining=0x7,
+ description="ORIYA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB3C,
+ },
+ [0xB3D]={
+ category="lo",
+ description="ORIYA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB3D,
+ },
+ [0xB3E]={
+ category="mc",
+ description="ORIYA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB3E,
+ },
+ [0xB3F]={
+ category="mn",
+ description="ORIYA VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB3F,
+ },
+ [0xB40]={
+ category="mc",
+ description="ORIYA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB40,
+ },
+ [0xB41]={
+ category="mn",
+ description="ORIYA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB41,
+ },
+ [0xB42]={
+ category="mn",
+ description="ORIYA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB42,
+ },
+ [0xB43]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB43,
+ },
+ [0xB44]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB44,
+ },
+ [0xB47]={
+ category="mc",
+ description="ORIYA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB47,
+ },
+ [0xB48]={
+ category="mc",
+ description="ORIYA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xB47, 0xB56 },
+ unicodeslot=0xB48,
+ },
+ [0xB4B]={
+ category="mc",
+ description="ORIYA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xB47, 0xB3E },
+ unicodeslot=0xB4B,
+ },
+ [0xB4C]={
+ category="mc",
+ description="ORIYA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xB47, 0xB57 },
+ unicodeslot=0xB4C,
+ },
+ [0xB4D]={
+ category="mn",
+ combining=0x9,
+ description="ORIYA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB4D,
+ },
+ [0xB56]={
+ category="mn",
+ description="ORIYA AI LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB56,
+ },
+ [0xB57]={
+ category="mc",
+ description="ORIYA AU LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xB57,
+ },
+ [0xB5C]={
+ category="lo",
+ description="ORIYA LETTER RRA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xB21, 0xB3C },
+ unicodeslot=0xB5C,
+ },
+ [0xB5D]={
+ category="lo",
+ description="ORIYA LETTER RHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xB22, 0xB3C },
+ unicodeslot=0xB5D,
+ },
+ [0xB5F]={
+ category="lo",
+ description="ORIYA LETTER YYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB5F,
+ },
+ [0xB60]={
+ category="lo",
+ description="ORIYA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB60,
+ },
+ [0xB61]={
+ category="lo",
+ description="ORIYA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB61,
+ },
+ [0xB62]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB62,
+ },
+ [0xB63]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB63,
+ },
+ [0xB66]={
+ category="nd",
+ description="ORIYA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB66,
+ },
+ [0xB67]={
+ category="nd",
+ description="ORIYA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB67,
+ },
+ [0xB68]={
+ category="nd",
+ description="ORIYA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB68,
+ },
+ [0xB69]={
+ category="nd",
+ description="ORIYA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB69,
+ },
+ [0xB6A]={
+ category="nd",
+ description="ORIYA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6A,
+ },
+ [0xB6B]={
+ category="nd",
+ description="ORIYA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6B,
+ },
+ [0xB6C]={
+ category="nd",
+ description="ORIYA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6C,
+ },
+ [0xB6D]={
+ category="nd",
+ description="ORIYA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6D,
+ },
+ [0xB6E]={
+ category="nd",
+ description="ORIYA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6E,
+ },
+ [0xB6F]={
+ category="nd",
+ description="ORIYA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xB6F,
+ },
+ [0xB70]={
+ category="so",
+ description="ORIYA ISSHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB70,
+ },
+ [0xB71]={
+ category="lo",
+ description="ORIYA LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB71,
+ },
+ [0xB72]={
+ category="no",
+ description="ORIYA FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB72,
+ },
+ [0xB73]={
+ category="no",
+ description="ORIYA FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB73,
+ },
+ [0xB74]={
+ category="no",
+ description="ORIYA FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB74,
+ },
+ [0xB75]={
+ category="no",
+ description="ORIYA FRACTION ONE SIXTEENTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB75,
+ },
+ [0xB76]={
+ category="no",
+ description="ORIYA FRACTION ONE EIGHTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB76,
+ },
+ [0xB77]={
+ category="no",
+ description="ORIYA FRACTION THREE SIXTEENTHS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB77,
+ },
+ [0xB82]={
+ category="mn",
+ description="TAMIL SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xB82,
+ },
+ [0xB83]={
+ category="lo",
+ description="TAMIL SIGN VISARGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB83,
+ },
+ [0xB85]={
+ category="lo",
+ description="TAMIL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB85,
+ },
+ [0xB86]={
+ category="lo",
+ description="TAMIL LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB86,
+ },
+ [0xB87]={
+ category="lo",
+ description="TAMIL LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB87,
+ },
+ [0xB88]={
+ category="lo",
+ description="TAMIL LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB88,
+ },
+ [0xB89]={
+ category="lo",
+ description="TAMIL LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB89,
+ },
+ [0xB8A]={
+ category="lo",
+ description="TAMIL LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB8A,
+ },
+ [0xB8E]={
+ category="lo",
+ description="TAMIL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB8E,
+ },
+ [0xB8F]={
+ category="lo",
+ description="TAMIL LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB8F,
+ },
+ [0xB90]={
+ category="lo",
+ description="TAMIL LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB90,
+ },
+ [0xB92]={
+ category="lo",
+ description="TAMIL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB92,
+ },
+ [0xB93]={
+ category="lo",
+ description="TAMIL LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB93,
+ },
+ [0xB94]={
+ category="lo",
+ description="TAMIL LETTER AU",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xB92, 0xBD7 },
+ unicodeslot=0xB94,
+ },
+ [0xB95]={
+ category="lo",
+ description="TAMIL LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB95,
+ },
+ [0xB99]={
+ category="lo",
+ description="TAMIL LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB99,
+ },
+ [0xB9A]={
+ category="lo",
+ description="TAMIL LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB9A,
+ },
+ [0xB9C]={
+ category="lo",
+ description="TAMIL LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB9C,
+ },
+ [0xB9E]={
+ category="lo",
+ description="TAMIL LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB9E,
+ },
+ [0xB9F]={
+ category="lo",
+ description="TAMIL LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xB9F,
+ },
+ [0xBA3]={
+ category="lo",
+ description="TAMIL LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBA3,
+ },
+ [0xBA4]={
+ category="lo",
+ description="TAMIL LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBA4,
+ },
+ [0xBA8]={
+ category="lo",
+ description="TAMIL LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBA8,
+ },
+ [0xBA9]={
+ category="lo",
+ description="TAMIL LETTER NNNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBA9,
+ },
+ [0xBAA]={
+ category="lo",
+ description="TAMIL LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBAA,
+ },
+ [0xBAE]={
+ category="lo",
+ description="TAMIL LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBAE,
+ },
+ [0xBAF]={
+ category="lo",
+ description="TAMIL LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBAF,
+ },
+ [0xBB0]={
+ category="lo",
+ description="TAMIL LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB0,
+ },
+ [0xBB1]={
+ category="lo",
+ description="TAMIL LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB1,
+ },
+ [0xBB2]={
+ category="lo",
+ description="TAMIL LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB2,
+ },
+ [0xBB3]={
+ category="lo",
+ description="TAMIL LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB3,
+ },
+ [0xBB4]={
+ category="lo",
+ description="TAMIL LETTER LLLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB4,
+ },
+ [0xBB5]={
+ category="lo",
+ description="TAMIL LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB5,
+ },
+ [0xBB6]={
+ category="lo",
+ description="TAMIL LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB6,
+ },
+ [0xBB7]={
+ category="lo",
+ description="TAMIL LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB7,
+ },
+ [0xBB8]={
+ category="lo",
+ description="TAMIL LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB8,
+ },
+ [0xBB9]={
+ category="lo",
+ description="TAMIL LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBB9,
+ },
+ [0xBBE]={
+ category="mc",
+ description="TAMIL VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBBE,
+ },
+ [0xBBF]={
+ category="mc",
+ description="TAMIL VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBBF,
+ },
+ [0xBC0]={
+ category="mn",
+ description="TAMIL VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xBC0,
+ },
+ [0xBC1]={
+ category="mc",
+ description="TAMIL VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBC1,
+ },
+ [0xBC2]={
+ category="mc",
+ description="TAMIL VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBC2,
+ },
+ [0xBC6]={
+ category="mc",
+ description="TAMIL VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBC6,
+ },
+ [0xBC7]={
+ category="mc",
+ description="TAMIL VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBC7,
+ },
+ [0xBC8]={
+ category="mc",
+ description="TAMIL VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBC8,
+ },
+ [0xBCA]={
+ category="mc",
+ description="TAMIL VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xBC6, 0xBBE },
+ unicodeslot=0xBCA,
+ },
+ [0xBCB]={
+ category="mc",
+ description="TAMIL VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xBC7, 0xBBE },
+ unicodeslot=0xBCB,
+ },
+ [0xBCC]={
+ category="mc",
+ description="TAMIL VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xBC6, 0xBD7 },
+ unicodeslot=0xBCC,
+ },
+ [0xBCD]={
+ category="mn",
+ combining=0x9,
+ description="TAMIL SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xBCD,
+ },
+ [0xBD0]={
+ category="lo",
+ description="TAMIL OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBD0,
+ },
+ [0xBD7]={
+ category="mc",
+ description="TAMIL AU LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xBD7,
+ },
+ [0xBE6]={
+ category="nd",
+ description="TAMIL DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBE6,
+ },
+ [0xBE7]={
+ category="nd",
+ description="TAMIL DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBE7,
+ },
+ [0xBE8]={
+ category="nd",
+ description="TAMIL DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBE8,
+ },
+ [0xBE9]={
+ category="nd",
+ description="TAMIL DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBE9,
+ },
+ [0xBEA]={
+ category="nd",
+ description="TAMIL DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBEA,
+ },
+ [0xBEB]={
+ category="nd",
+ description="TAMIL DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBEB,
+ },
+ [0xBEC]={
+ category="nd",
+ description="TAMIL DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBEC,
+ },
+ [0xBED]={
+ category="nd",
+ description="TAMIL DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBED,
+ },
+ [0xBEE]={
+ category="nd",
+ description="TAMIL DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBEE,
+ },
+ [0xBEF]={
+ category="nd",
+ description="TAMIL DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xBEF,
+ },
+ [0xBF0]={
+ category="no",
+ description="TAMIL NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBF0,
+ },
+ [0xBF1]={
+ category="no",
+ description="TAMIL NUMBER ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBF1,
+ },
+ [0xBF2]={
+ category="no",
+ description="TAMIL NUMBER ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xBF2,
+ },
+ [0xBF3]={
+ category="so",
+ description="TAMIL DAY SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF3,
+ },
+ [0xBF4]={
+ category="so",
+ description="TAMIL MONTH SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF4,
+ },
+ [0xBF5]={
+ category="so",
+ description="TAMIL YEAR SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF5,
+ },
+ [0xBF6]={
+ category="so",
+ description="TAMIL DEBIT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF6,
+ },
+ [0xBF7]={
+ category="so",
+ description="TAMIL CREDIT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF7,
+ },
+ [0xBF8]={
+ category="so",
+ description="TAMIL AS ABOVE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBF8,
+ },
+ [0xBF9]={
+ category="sc",
+ description="TAMIL RUPEE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0xBF9,
+ },
+ [0xBFA]={
+ category="so",
+ description="TAMIL NUMBER SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xBFA,
+ },
+ [0xC00]={
+ category="mn",
+ description="TELUGU SIGN COMBINING CANDRABINDU ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC00,
+ },
+ [0xC01]={
+ category="mc",
+ description="TELUGU SIGN CANDRABINDU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC01,
+ },
+ [0xC02]={
+ category="mc",
+ description="TELUGU SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC02,
+ },
+ [0xC03]={
+ category="mc",
+ description="TELUGU SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC03,
+ },
+ [0xC05]={
+ category="lo",
+ description="TELUGU LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC05,
+ },
+ [0xC06]={
+ category="lo",
+ description="TELUGU LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC06,
+ },
+ [0xC07]={
+ category="lo",
+ description="TELUGU LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC07,
+ },
+ [0xC08]={
+ category="lo",
+ description="TELUGU LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC08,
+ },
+ [0xC09]={
+ category="lo",
+ description="TELUGU LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC09,
+ },
+ [0xC0A]={
+ category="lo",
+ description="TELUGU LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC0A,
+ },
+ [0xC0B]={
+ category="lo",
+ description="TELUGU LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC0B,
+ },
+ [0xC0C]={
+ category="lo",
+ description="TELUGU LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC0C,
+ },
+ [0xC0E]={
+ category="lo",
+ description="TELUGU LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC0E,
+ },
+ [0xC0F]={
+ category="lo",
+ description="TELUGU LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC0F,
+ },
+ [0xC10]={
+ category="lo",
+ description="TELUGU LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC10,
+ },
+ [0xC12]={
+ category="lo",
+ description="TELUGU LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC12,
+ },
+ [0xC13]={
+ category="lo",
+ description="TELUGU LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC13,
+ },
+ [0xC14]={
+ category="lo",
+ description="TELUGU LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC14,
+ },
+ [0xC15]={
+ category="lo",
+ description="TELUGU LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC15,
+ },
+ [0xC16]={
+ category="lo",
+ description="TELUGU LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC16,
+ },
+ [0xC17]={
+ category="lo",
+ description="TELUGU LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC17,
+ },
+ [0xC18]={
+ category="lo",
+ description="TELUGU LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC18,
+ },
+ [0xC19]={
+ category="lo",
+ description="TELUGU LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC19,
+ },
+ [0xC1A]={
+ category="lo",
+ description="TELUGU LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1A,
+ },
+ [0xC1B]={
+ category="lo",
+ description="TELUGU LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1B,
+ },
+ [0xC1C]={
+ category="lo",
+ description="TELUGU LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1C,
+ },
+ [0xC1D]={
+ category="lo",
+ description="TELUGU LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1D,
+ },
+ [0xC1E]={
+ category="lo",
+ description="TELUGU LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1E,
+ },
+ [0xC1F]={
+ category="lo",
+ description="TELUGU LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC1F,
+ },
+ [0xC20]={
+ category="lo",
+ description="TELUGU LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC20,
+ },
+ [0xC21]={
+ category="lo",
+ description="TELUGU LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC21,
+ },
+ [0xC22]={
+ category="lo",
+ description="TELUGU LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC22,
+ },
+ [0xC23]={
+ category="lo",
+ description="TELUGU LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC23,
+ },
+ [0xC24]={
+ category="lo",
+ description="TELUGU LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC24,
+ },
+ [0xC25]={
+ category="lo",
+ description="TELUGU LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC25,
+ },
+ [0xC26]={
+ category="lo",
+ description="TELUGU LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC26,
+ },
+ [0xC27]={
+ category="lo",
+ description="TELUGU LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC27,
+ },
+ [0xC28]={
+ category="lo",
+ description="TELUGU LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC28,
+ },
+ [0xC2A]={
+ category="lo",
+ description="TELUGU LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2A,
+ },
+ [0xC2B]={
+ category="lo",
+ description="TELUGU LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2B,
+ },
+ [0xC2C]={
+ category="lo",
+ description="TELUGU LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2C,
+ },
+ [0xC2D]={
+ category="lo",
+ description="TELUGU LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2D,
+ },
+ [0xC2E]={
+ category="lo",
+ description="TELUGU LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2E,
+ },
+ [0xC2F]={
+ category="lo",
+ description="TELUGU LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC2F,
+ },
+ [0xC30]={
+ category="lo",
+ description="TELUGU LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC30,
+ },
+ [0xC31]={
+ category="lo",
+ description="TELUGU LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC31,
+ },
+ [0xC32]={
+ category="lo",
+ description="TELUGU LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC32,
+ },
+ [0xC33]={
+ category="lo",
+ description="TELUGU LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC33,
+ },
+ [0xC34]={
+ category="lo",
+ description="TELUGU LETTER LLLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC34,
+ },
+ [0xC35]={
+ category="lo",
+ description="TELUGU LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC35,
+ },
+ [0xC36]={
+ category="lo",
+ description="TELUGU LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC36,
+ },
+ [0xC37]={
+ category="lo",
+ description="TELUGU LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC37,
+ },
+ [0xC38]={
+ category="lo",
+ description="TELUGU LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC38,
+ },
+ [0xC39]={
+ category="lo",
+ description="TELUGU LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC39,
+ },
+ [0xC3D]={
+ category="lo",
+ description="TELUGU SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC3D,
+ },
+ [0xC3E]={
+ category="mn",
+ description="TELUGU VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC3E,
+ },
+ [0xC3F]={
+ category="mn",
+ description="TELUGU VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC3F,
+ },
+ [0xC40]={
+ category="mn",
+ description="TELUGU VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC40,
+ },
+ [0xC41]={
+ category="mc",
+ description="TELUGU VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC41,
+ },
+ [0xC42]={
+ category="mc",
+ description="TELUGU VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC42,
+ },
+ [0xC43]={
+ category="mc",
+ description="TELUGU VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC43,
+ },
+ [0xC44]={
+ category="mc",
+ description="TELUGU VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC44,
+ },
+ [0xC46]={
+ category="mn",
+ description="TELUGU VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC46,
+ },
+ [0xC47]={
+ category="mn",
+ description="TELUGU VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC47,
+ },
+ [0xC48]={
+ category="mn",
+ description="TELUGU VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xC46, 0xC56 },
+ unicodeslot=0xC48,
+ },
+ [0xC4A]={
+ category="mn",
+ description="TELUGU VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC4A,
+ },
+ [0xC4B]={
+ category="mn",
+ description="TELUGU VOWEL SIGN OO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC4B,
+ },
+ [0xC4C]={
+ category="mn",
+ description="TELUGU VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC4C,
+ },
+ [0xC4D]={
+ category="mn",
+ combining=0x9,
+ description="TELUGU SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC4D,
+ },
+ [0xC55]={
+ category="mn",
+ combining=0x54,
+ description="TELUGU LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC55,
+ },
+ [0xC56]={
+ category="mn",
+ combining=0x5B,
+ description="TELUGU AI LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC56,
+ },
+ [0xC58]={
+ category="lo",
+ description="TELUGU LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC58,
+ },
+ [0xC59]={
+ category="lo",
+ description="TELUGU LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC59,
+ },
+ [0xC5A]={
+ category="lo",
+ description="TELUGU LETTER RRRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC5A,
+ },
+ [0xC60]={
+ category="lo",
+ description="TELUGU LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC60,
+ },
+ [0xC61]={
+ category="lo",
+ description="TELUGU LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC61,
+ },
+ [0xC62]={
+ category="mn",
+ description="TELUGU VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC62,
+ },
+ [0xC63]={
+ category="mn",
+ description="TELUGU VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC63,
+ },
+ [0xC66]={
+ category="nd",
+ description="TELUGU DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC66,
+ },
+ [0xC67]={
+ category="nd",
+ description="TELUGU DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC67,
+ },
+ [0xC68]={
+ category="nd",
+ description="TELUGU DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC68,
+ },
+ [0xC69]={
+ category="nd",
+ description="TELUGU DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC69,
+ },
+ [0xC6A]={
+ category="nd",
+ description="TELUGU DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6A,
+ },
+ [0xC6B]={
+ category="nd",
+ description="TELUGU DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6B,
+ },
+ [0xC6C]={
+ category="nd",
+ description="TELUGU DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6C,
+ },
+ [0xC6D]={
+ category="nd",
+ description="TELUGU DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6D,
+ },
+ [0xC6E]={
+ category="nd",
+ description="TELUGU DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6E,
+ },
+ [0xC6F]={
+ category="nd",
+ description="TELUGU DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xC6F,
+ },
+ [0xC78]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC78,
+ },
+ [0xC79]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC79,
+ },
+ [0xC7A]={
+ category="no",
+ description="TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC7A,
+ },
+ [0xC7B]={
+ category="no",
+ description="TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC7B,
+ },
+ [0xC7C]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC7C,
+ },
+ [0xC7D]={
+ category="no",
+ description="TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC7D,
+ },
+ [0xC7E]={
+ category="no",
+ description="TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xC7E,
+ },
+ [0xC7F]={
+ category="so",
+ description="TELUGU SIGN TUUMU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC7F,
+ },
+ [0xC81]={
+ category="mn",
+ description="KANNADA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC81,
+ },
+ [0xC82]={
+ category="mc",
+ description="KANNADA SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC82,
+ },
+ [0xC83]={
+ category="mc",
+ description="KANNADA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xC83,
+ },
+ [0xC85]={
+ category="lo",
+ description="KANNADA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC85,
+ },
+ [0xC86]={
+ category="lo",
+ description="KANNADA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC86,
+ },
+ [0xC87]={
+ category="lo",
+ description="KANNADA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC87,
+ },
+ [0xC88]={
+ category="lo",
+ description="KANNADA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC88,
+ },
+ [0xC89]={
+ category="lo",
+ description="KANNADA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC89,
+ },
+ [0xC8A]={
+ category="lo",
+ description="KANNADA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC8A,
+ },
+ [0xC8B]={
+ category="lo",
+ description="KANNADA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC8B,
+ },
+ [0xC8C]={
+ category="lo",
+ description="KANNADA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC8C,
+ },
+ [0xC8E]={
+ category="lo",
+ description="KANNADA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC8E,
+ },
+ [0xC8F]={
+ category="lo",
+ description="KANNADA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC8F,
+ },
+ [0xC90]={
+ category="lo",
+ description="KANNADA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC90,
+ },
+ [0xC92]={
+ category="lo",
+ description="KANNADA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC92,
+ },
+ [0xC93]={
+ category="lo",
+ description="KANNADA LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC93,
+ },
+ [0xC94]={
+ category="lo",
+ description="KANNADA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC94,
+ },
+ [0xC95]={
+ category="lo",
+ description="KANNADA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC95,
+ },
+ [0xC96]={
+ category="lo",
+ description="KANNADA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC96,
+ },
+ [0xC97]={
+ category="lo",
+ description="KANNADA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC97,
+ },
+ [0xC98]={
+ category="lo",
+ description="KANNADA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC98,
+ },
+ [0xC99]={
+ category="lo",
+ description="KANNADA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC99,
+ },
+ [0xC9A]={
+ category="lo",
+ description="KANNADA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9A,
+ },
+ [0xC9B]={
+ category="lo",
+ description="KANNADA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9B,
+ },
+ [0xC9C]={
+ category="lo",
+ description="KANNADA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9C,
+ },
+ [0xC9D]={
+ category="lo",
+ description="KANNADA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9D,
+ },
+ [0xC9E]={
+ category="lo",
+ description="KANNADA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9E,
+ },
+ [0xC9F]={
+ category="lo",
+ description="KANNADA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xC9F,
+ },
+ [0xCA0]={
+ category="lo",
+ description="KANNADA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA0,
+ },
+ [0xCA1]={
+ category="lo",
+ description="KANNADA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA1,
+ },
+ [0xCA2]={
+ category="lo",
+ description="KANNADA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA2,
+ },
+ [0xCA3]={
+ category="lo",
+ description="KANNADA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA3,
+ },
+ [0xCA4]={
+ category="lo",
+ description="KANNADA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA4,
+ },
+ [0xCA5]={
+ category="lo",
+ description="KANNADA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA5,
+ },
+ [0xCA6]={
+ category="lo",
+ description="KANNADA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA6,
+ },
+ [0xCA7]={
+ category="lo",
+ description="KANNADA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA7,
+ },
+ [0xCA8]={
+ category="lo",
+ description="KANNADA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCA8,
+ },
+ [0xCAA]={
+ category="lo",
+ description="KANNADA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAA,
+ },
+ [0xCAB]={
+ category="lo",
+ description="KANNADA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAB,
+ },
+ [0xCAC]={
+ category="lo",
+ description="KANNADA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAC,
+ },
+ [0xCAD]={
+ category="lo",
+ description="KANNADA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAD,
+ },
+ [0xCAE]={
+ category="lo",
+ description="KANNADA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAE,
+ },
+ [0xCAF]={
+ category="lo",
+ description="KANNADA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCAF,
+ },
+ [0xCB0]={
+ category="lo",
+ description="KANNADA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB0,
+ },
+ [0xCB1]={
+ category="lo",
+ description="KANNADA LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB1,
+ },
+ [0xCB2]={
+ category="lo",
+ description="KANNADA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB2,
+ },
+ [0xCB3]={
+ category="lo",
+ description="KANNADA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB3,
+ },
+ [0xCB5]={
+ category="lo",
+ description="KANNADA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB5,
+ },
+ [0xCB6]={
+ category="lo",
+ description="KANNADA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB6,
+ },
+ [0xCB7]={
+ category="lo",
+ description="KANNADA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB7,
+ },
+ [0xCB8]={
+ category="lo",
+ description="KANNADA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB8,
+ },
+ [0xCB9]={
+ category="lo",
+ description="KANNADA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCB9,
+ },
+ [0xCBC]={
+ category="mn",
+ combining=0x7,
+ description="KANNADA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xCBC,
+ },
+ [0xCBD]={
+ category="lo",
+ description="KANNADA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCBD,
+ },
+ [0xCBE]={
+ category="mc",
+ description="KANNADA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCBE,
+ },
+ [0xCBF]={
+ category="mn",
+ description="KANNADA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCBF,
+ },
+ [0xCC0]={
+ category="mc",
+ description="KANNADA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xCBF, 0xCD5 },
+ unicodeslot=0xCC0,
+ },
+ [0xCC1]={
+ category="mc",
+ description="KANNADA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCC1,
+ },
+ [0xCC2]={
+ category="mc",
+ description="KANNADA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCC2,
+ },
+ [0xCC3]={
+ category="mc",
+ description="KANNADA VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCC3,
+ },
+ [0xCC4]={
+ category="mc",
+ description="KANNADA VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCC4,
+ },
+ [0xCC6]={
+ category="mn",
+ description="KANNADA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCC6,
+ },
+ [0xCC7]={
+ category="mc",
+ description="KANNADA VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xCC6, 0xCD5 },
+ unicodeslot=0xCC7,
+ },
+ [0xCC8]={
+ category="mc",
+ description="KANNADA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xCC6, 0xCD6 },
+ unicodeslot=0xCC8,
+ },
+ [0xCCA]={
+ category="mc",
+ description="KANNADA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xCC6, 0xCC2 },
+ unicodeslot=0xCCA,
+ },
+ [0xCCB]={
+ category="mc",
+ description="KANNADA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xCCA, 0xCD5 },
+ unicodeslot=0xCCB,
+ },
+ [0xCCC]={
+ category="mn",
+ description="KANNADA VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xCCC,
+ },
+ [0xCCD]={
+ category="mn",
+ combining=0x9,
+ description="KANNADA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xCCD,
+ },
+ [0xCD5]={
+ category="mc",
+ description="KANNADA LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCD5,
+ },
+ [0xCD6]={
+ category="mc",
+ description="KANNADA AI LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xCD6,
+ },
+ [0xCDE]={
+ category="lo",
+ description="KANNADA LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCDE,
+ },
+ [0xCE0]={
+ category="lo",
+ description="KANNADA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCE0,
+ },
+ [0xCE1]={
+ category="lo",
+ description="KANNADA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCE1,
+ },
+ [0xCE2]={
+ category="mn",
+ description="KANNADA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xCE2,
+ },
+ [0xCE3]={
+ category="mn",
+ description="KANNADA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xCE3,
+ },
+ [0xCE6]={
+ category="nd",
+ description="KANNADA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCE6,
+ },
+ [0xCE7]={
+ category="nd",
+ description="KANNADA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCE7,
+ },
+ [0xCE8]={
+ category="nd",
+ description="KANNADA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCE8,
+ },
+ [0xCE9]={
+ category="nd",
+ description="KANNADA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCE9,
+ },
+ [0xCEA]={
+ category="nd",
+ description="KANNADA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCEA,
+ },
+ [0xCEB]={
+ category="nd",
+ description="KANNADA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCEB,
+ },
+ [0xCEC]={
+ category="nd",
+ description="KANNADA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCEC,
+ },
+ [0xCED]={
+ category="nd",
+ description="KANNADA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCED,
+ },
+ [0xCEE]={
+ category="nd",
+ description="KANNADA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCEE,
+ },
+ [0xCEF]={
+ category="nd",
+ description="KANNADA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xCEF,
+ },
+ [0xCF1]={
+ category="so",
+ description="KANNADA SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCF1,
+ },
+ [0xCF2]={
+ category="so",
+ description="KANNADA SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xCF2,
+ },
+ [0xD01]={
+ category="mn",
+ description="MALAYALAM SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD01,
+ },
+ [0xD02]={
+ category="mc",
+ description="MALAYALAM SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD02,
+ },
+ [0xD03]={
+ category="mc",
+ description="MALAYALAM SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD03,
+ },
+ [0xD05]={
+ category="lo",
+ description="MALAYALAM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD05,
+ },
+ [0xD06]={
+ category="lo",
+ description="MALAYALAM LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD06,
+ },
+ [0xD07]={
+ category="lo",
+ description="MALAYALAM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD07,
+ },
+ [0xD08]={
+ category="lo",
+ description="MALAYALAM LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD08,
+ },
+ [0xD09]={
+ category="lo",
+ description="MALAYALAM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD09,
+ },
+ [0xD0A]={
+ category="lo",
+ description="MALAYALAM LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD0A,
+ },
+ [0xD0B]={
+ category="lo",
+ description="MALAYALAM LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD0B,
+ },
+ [0xD0C]={
+ category="lo",
+ description="MALAYALAM LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD0C,
+ },
+ [0xD0E]={
+ category="lo",
+ description="MALAYALAM LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD0E,
+ },
+ [0xD0F]={
+ category="lo",
+ description="MALAYALAM LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD0F,
+ },
+ [0xD10]={
+ category="lo",
+ description="MALAYALAM LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD10,
+ },
+ [0xD12]={
+ category="lo",
+ description="MALAYALAM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD12,
+ },
+ [0xD13]={
+ category="lo",
+ description="MALAYALAM LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD13,
+ },
+ [0xD14]={
+ category="lo",
+ description="MALAYALAM LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD14,
+ },
+ [0xD15]={
+ category="lo",
+ description="MALAYALAM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD15,
+ },
+ [0xD16]={
+ category="lo",
+ description="MALAYALAM LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD16,
+ },
+ [0xD17]={
+ category="lo",
+ description="MALAYALAM LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD17,
+ },
+ [0xD18]={
+ category="lo",
+ description="MALAYALAM LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD18,
+ },
+ [0xD19]={
+ category="lo",
+ description="MALAYALAM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD19,
+ },
+ [0xD1A]={
+ category="lo",
+ description="MALAYALAM LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1A,
+ },
+ [0xD1B]={
+ category="lo",
+ description="MALAYALAM LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1B,
+ },
+ [0xD1C]={
+ category="lo",
+ description="MALAYALAM LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1C,
+ },
+ [0xD1D]={
+ category="lo",
+ description="MALAYALAM LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1D,
+ },
+ [0xD1E]={
+ category="lo",
+ description="MALAYALAM LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1E,
+ },
+ [0xD1F]={
+ category="lo",
+ description="MALAYALAM LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD1F,
+ },
+ [0xD20]={
+ category="lo",
+ description="MALAYALAM LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD20,
+ },
+ [0xD21]={
+ category="lo",
+ description="MALAYALAM LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD21,
+ },
+ [0xD22]={
+ category="lo",
+ description="MALAYALAM LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD22,
+ },
+ [0xD23]={
+ category="lo",
+ description="MALAYALAM LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD23,
+ },
+ [0xD24]={
+ category="lo",
+ description="MALAYALAM LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD24,
+ },
+ [0xD25]={
+ category="lo",
+ description="MALAYALAM LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD25,
+ },
+ [0xD26]={
+ category="lo",
+ description="MALAYALAM LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD26,
+ },
+ [0xD27]={
+ category="lo",
+ description="MALAYALAM LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD27,
+ },
+ [0xD28]={
+ category="lo",
+ description="MALAYALAM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD28,
+ },
+ [0xD29]={
+ category="lo",
+ description="MALAYALAM LETTER NNNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD29,
+ },
+ [0xD2A]={
+ category="lo",
+ description="MALAYALAM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2A,
+ },
+ [0xD2B]={
+ category="lo",
+ description="MALAYALAM LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2B,
+ },
+ [0xD2C]={
+ category="lo",
+ description="MALAYALAM LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2C,
+ },
+ [0xD2D]={
+ category="lo",
+ description="MALAYALAM LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2D,
+ },
+ [0xD2E]={
+ category="lo",
+ description="MALAYALAM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2E,
+ },
+ [0xD2F]={
+ category="lo",
+ description="MALAYALAM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD2F,
+ },
+ [0xD30]={
+ category="lo",
+ description="MALAYALAM LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD30,
+ },
+ [0xD31]={
+ category="lo",
+ description="MALAYALAM LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD31,
+ },
+ [0xD32]={
+ category="lo",
+ description="MALAYALAM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD32,
+ },
+ [0xD33]={
+ category="lo",
+ description="MALAYALAM LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD33,
+ },
+ [0xD34]={
+ category="lo",
+ description="MALAYALAM LETTER LLLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD34,
+ },
+ [0xD35]={
+ category="lo",
+ description="MALAYALAM LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD35,
+ },
+ [0xD36]={
+ category="lo",
+ description="MALAYALAM LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD36,
+ },
+ [0xD37]={
+ category="lo",
+ description="MALAYALAM LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD37,
+ },
+ [0xD38]={
+ category="lo",
+ description="MALAYALAM LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD38,
+ },
+ [0xD39]={
+ category="lo",
+ description="MALAYALAM LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD39,
+ },
+ [0xD3A]={
+ category="lo",
+ description="MALAYALAM LETTER TTTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD3A,
+ },
+ [0xD3D]={
+ category="lo",
+ description="MALAYALAM SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD3D,
+ },
+ [0xD3E]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD3E,
+ },
+ [0xD3F]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD3F,
+ },
+ [0xD40]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD40,
+ },
+ [0xD41]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD41,
+ },
+ [0xD42]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD42,
+ },
+ [0xD43]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD43,
+ },
+ [0xD44]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD44,
+ },
+ [0xD46]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD46,
+ },
+ [0xD47]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD47,
+ },
+ [0xD48]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD48,
+ },
+ [0xD4A]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xD46, 0xD3E },
+ unicodeslot=0xD4A,
+ },
+ [0xD4B]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xD47, 0xD3E },
+ unicodeslot=0xD4B,
+ },
+ [0xD4C]={
+ category="mc",
+ description="MALAYALAM VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xD46, 0xD57 },
+ unicodeslot=0xD4C,
+ },
+ [0xD4D]={
+ category="mn",
+ combining=0x9,
+ description="MALAYALAM SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD4D,
+ },
+ [0xD4E]={
+ category="lo",
+ description="MALAYALAM LETTER DOT REPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD4E,
+ },
+ [0xD57]={
+ category="mc",
+ description="MALAYALAM AU LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD57,
+ },
+ [0xD5F]={
+ category="lo",
+ description="MALAYALAM LETTER ARCHAIC II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD5F,
+ },
+ [0xD60]={
+ category="lo",
+ description="MALAYALAM LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD60,
+ },
+ [0xD61]={
+ category="lo",
+ description="MALAYALAM LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD61,
+ },
+ [0xD62]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD62,
+ },
+ [0xD63]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xD63,
+ },
+ [0xD66]={
+ category="nd",
+ description="MALAYALAM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD66,
+ },
+ [0xD67]={
+ category="nd",
+ description="MALAYALAM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD67,
+ },
+ [0xD68]={
+ category="nd",
+ description="MALAYALAM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD68,
+ },
+ [0xD69]={
+ category="nd",
+ description="MALAYALAM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD69,
+ },
+ [0xD6A]={
+ category="nd",
+ description="MALAYALAM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6A,
+ },
+ [0xD6B]={
+ category="nd",
+ description="MALAYALAM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6B,
+ },
+ [0xD6C]={
+ category="nd",
+ description="MALAYALAM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6C,
+ },
+ [0xD6D]={
+ category="nd",
+ description="MALAYALAM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6D,
+ },
+ [0xD6E]={
+ category="nd",
+ description="MALAYALAM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6E,
+ },
+ [0xD6F]={
+ category="nd",
+ description="MALAYALAM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xD6F,
+ },
+ [0xD70]={
+ category="no",
+ description="MALAYALAM NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD70,
+ },
+ [0xD71]={
+ category="no",
+ description="MALAYALAM NUMBER ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD71,
+ },
+ [0xD72]={
+ category="no",
+ description="MALAYALAM NUMBER ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD72,
+ },
+ [0xD73]={
+ category="no",
+ description="MALAYALAM FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD73,
+ },
+ [0xD74]={
+ category="no",
+ description="MALAYALAM FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD74,
+ },
+ [0xD75]={
+ category="no",
+ description="MALAYALAM FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD75,
+ },
+ [0xD79]={
+ category="so",
+ description="MALAYALAM DATE MARK",
+ direction="l",
+ linebreak="po",
+ unicodeslot=0xD79,
+ },
+ [0xD7A]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7A,
+ },
+ [0xD7B]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7B,
+ },
+ [0xD7C]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7C,
+ },
+ [0xD7D]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7D,
+ },
+ [0xD7E]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7E,
+ },
+ [0xD7F]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD7F,
+ },
+ [0xD82]={
+ category="mc",
+ description="SINHALA SIGN ANUSVARAYA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD82,
+ },
+ [0xD83]={
+ category="mc",
+ description="SINHALA SIGN VISARGAYA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xD83,
+ },
+ [0xD85]={
+ category="lo",
+ description="SINHALA LETTER AYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD85,
+ },
+ [0xD86]={
+ category="lo",
+ description="SINHALA LETTER AAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD86,
+ },
+ [0xD87]={
+ category="lo",
+ description="SINHALA LETTER AEYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD87,
+ },
+ [0xD88]={
+ category="lo",
+ description="SINHALA LETTER AEEYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD88,
+ },
+ [0xD89]={
+ category="lo",
+ description="SINHALA LETTER IYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD89,
+ },
+ [0xD8A]={
+ category="lo",
+ description="SINHALA LETTER IIYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8A,
+ },
+ [0xD8B]={
+ category="lo",
+ description="SINHALA LETTER UYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8B,
+ },
+ [0xD8C]={
+ category="lo",
+ description="SINHALA LETTER UUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8C,
+ },
+ [0xD8D]={
+ category="lo",
+ description="SINHALA LETTER IRUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8D,
+ },
+ [0xD8E]={
+ category="lo",
+ description="SINHALA LETTER IRUUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8E,
+ },
+ [0xD8F]={
+ category="lo",
+ description="SINHALA LETTER ILUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD8F,
+ },
+ [0xD90]={
+ category="lo",
+ description="SINHALA LETTER ILUUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD90,
+ },
+ [0xD91]={
+ category="lo",
+ description="SINHALA LETTER EYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD91,
+ },
+ [0xD92]={
+ category="lo",
+ description="SINHALA LETTER EEYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD92,
+ },
+ [0xD93]={
+ category="lo",
+ description="SINHALA LETTER AIYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD93,
+ },
+ [0xD94]={
+ category="lo",
+ description="SINHALA LETTER OYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD94,
+ },
+ [0xD95]={
+ category="lo",
+ description="SINHALA LETTER OOYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD95,
+ },
+ [0xD96]={
+ category="lo",
+ description="SINHALA LETTER AUYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD96,
+ },
+ [0xD9A]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA KAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9A,
+ },
+ [0xD9B]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA KAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9B,
+ },
+ [0xD9C]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA GAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9C,
+ },
+ [0xD9D]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA GAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9D,
+ },
+ [0xD9E]={
+ category="lo",
+ description="SINHALA LETTER KANTAJA NAASIKYAYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9E,
+ },
+ [0xD9F]={
+ category="lo",
+ description="SINHALA LETTER SANYAKA GAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xD9F,
+ },
+ [0xDA0]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA CAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA0,
+ },
+ [0xDA1]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA CAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA1,
+ },
+ [0xDA2]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA JAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA2,
+ },
+ [0xDA3]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA JAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA3,
+ },
+ [0xDA4]={
+ category="lo",
+ description="SINHALA LETTER TAALUJA NAASIKYAYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA4,
+ },
+ [0xDA5]={
+ category="lo",
+ description="SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA5,
+ },
+ [0xDA6]={
+ category="lo",
+ description="SINHALA LETTER SANYAKA JAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA6,
+ },
+ [0xDA7]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA TTAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA7,
+ },
+ [0xDA8]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA TTAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA8,
+ },
+ [0xDA9]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA DDAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDA9,
+ },
+ [0xDAA]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA DDAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAA,
+ },
+ [0xDAB]={
+ category="lo",
+ description="SINHALA LETTER MUURDHAJA NAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAB,
+ },
+ [0xDAC]={
+ category="lo",
+ description="SINHALA LETTER SANYAKA DDAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAC,
+ },
+ [0xDAD]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA TAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAD,
+ },
+ [0xDAE]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA TAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAE,
+ },
+ [0xDAF]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA DAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDAF,
+ },
+ [0xDB0]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA DAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB0,
+ },
+ [0xDB1]={
+ category="lo",
+ description="SINHALA LETTER DANTAJA NAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB1,
+ },
+ [0xDB3]={
+ category="lo",
+ description="SINHALA LETTER SANYAKA DAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB3,
+ },
+ [0xDB4]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA PAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB4,
+ },
+ [0xDB5]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA PAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB5,
+ },
+ [0xDB6]={
+ category="lo",
+ description="SINHALA LETTER ALPAPRAANA BAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB6,
+ },
+ [0xDB7]={
+ category="lo",
+ description="SINHALA LETTER MAHAAPRAANA BAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB7,
+ },
+ [0xDB8]={
+ category="lo",
+ description="SINHALA LETTER MAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB8,
+ },
+ [0xDB9]={
+ category="lo",
+ description="SINHALA LETTER AMBA BAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDB9,
+ },
+ [0xDBA]={
+ category="lo",
+ description="SINHALA LETTER YAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDBA,
+ },
+ [0xDBB]={
+ category="lo",
+ description="SINHALA LETTER RAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDBB,
+ },
+ [0xDBD]={
+ category="lo",
+ description="SINHALA LETTER DANTAJA LAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDBD,
+ },
+ [0xDC0]={
+ category="lo",
+ description="SINHALA LETTER VAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC0,
+ },
+ [0xDC1]={
+ category="lo",
+ description="SINHALA LETTER TAALUJA SAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC1,
+ },
+ [0xDC2]={
+ category="lo",
+ description="SINHALA LETTER MUURDHAJA SAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC2,
+ },
+ [0xDC3]={
+ category="lo",
+ description="SINHALA LETTER DANTAJA SAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC3,
+ },
+ [0xDC4]={
+ category="lo",
+ description="SINHALA LETTER HAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC4,
+ },
+ [0xDC5]={
+ category="lo",
+ description="SINHALA LETTER MUURDHAJA LAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC5,
+ },
+ [0xDC6]={
+ category="lo",
+ description="SINHALA LETTER FAYANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDC6,
+ },
+ [0xDCA]={
+ category="mn",
+ combining=0x9,
+ description="SINHALA SIGN AL-LAKUNA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xDCA,
+ },
+ [0xDCF]={
+ category="mc",
+ description="SINHALA VOWEL SIGN AELA-PILLA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDCF,
+ },
+ [0xDD0]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KETTI AEDA-PILLA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDD0,
+ },
+ [0xDD1]={
+ category="mc",
+ description="SINHALA VOWEL SIGN DIGA AEDA-PILLA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDD1,
+ },
+ [0xDD2]={
+ category="mn",
+ description="SINHALA VOWEL SIGN KETTI IS-PILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xDD2,
+ },
+ [0xDD3]={
+ category="mn",
+ description="SINHALA VOWEL SIGN DIGA IS-PILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xDD3,
+ },
+ [0xDD4]={
+ category="mn",
+ description="SINHALA VOWEL SIGN KETTI PAA-PILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xDD4,
+ },
+ [0xDD6]={
+ category="mn",
+ description="SINHALA VOWEL SIGN DIGA PAA-PILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xDD6,
+ },
+ [0xDD8]={
+ category="mc",
+ description="SINHALA VOWEL SIGN GAETTA-PILLA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDD8,
+ },
+ [0xDD9]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KOMBUVA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDD9,
+ },
+ [0xDDA]={
+ category="mc",
+ description="SINHALA VOWEL SIGN DIGA KOMBUVA",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xDD9, 0xDCA },
+ unicodeslot=0xDDA,
+ },
+ [0xDDB]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KOMBU DEKA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDDB,
+ },
+ [0xDDC]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xDD9, 0xDCF },
+ unicodeslot=0xDDC,
+ },
+ [0xDDD]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xDDC, 0xDCA },
+ unicodeslot=0xDDD,
+ },
+ [0xDDE]={
+ category="mc",
+ description="SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0xDD9, 0xDDF },
+ unicodeslot=0xDDE,
+ },
+ [0xDDF]={
+ category="mc",
+ description="SINHALA VOWEL SIGN GAYANUKITTA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDDF,
+ },
+ [0xDE6]={
+ category="nd",
+ description="SINHALA LITH DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDE6,
+ },
+ [0xDE7]={
+ category="nd",
+ description="SINHALA LITH DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDE7,
+ },
+ [0xDE8]={
+ category="nd",
+ description="SINHALA LITH DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDE8,
+ },
+ [0xDE9]={
+ category="nd",
+ description="SINHALA LITH DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDE9,
+ },
+ [0xDEA]={
+ category="nd",
+ description="SINHALA LITH DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDEA,
+ },
+ [0xDEB]={
+ category="nd",
+ description="SINHALA LITH DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDEB,
+ },
+ [0xDEC]={
+ category="nd",
+ description="SINHALA LITH DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDEC,
+ },
+ [0xDED]={
+ category="nd",
+ description="SINHALA LITH DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDED,
+ },
+ [0xDEE]={
+ category="nd",
+ description="SINHALA LITH DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDEE,
+ },
+ [0xDEF]={
+ category="nd",
+ description="SINHALA LITH DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xDEF,
+ },
+ [0xDF2]={
+ category="mc",
+ description="SINHALA VOWEL SIGN DIGA GAETTA-PILLA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDF2,
+ },
+ [0xDF3]={
+ category="mc",
+ description="SINHALA VOWEL SIGN DIGA GAYANUKITTA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xDF3,
+ },
+ [0xDF4]={
+ category="po",
+ description="SINHALA PUNCTUATION KUNDDALIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xDF4,
+ },
+ [0xE01]={
+ adobename="kokaithai",
+ category="lo",
+ description="THAI CHARACTER KO KAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE01,
+ },
+ [0xE02]={
+ adobename="khokhaithai",
+ category="lo",
+ description="THAI CHARACTER KHO KHAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE02,
+ },
+ [0xE03]={
+ adobename="khokhuatthai",
+ category="lo",
+ description="THAI CHARACTER KHO KHUAT",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE03,
+ },
+ [0xE04]={
+ adobename="khokhwaithai",
+ category="lo",
+ description="THAI CHARACTER KHO KHWAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE04,
+ },
+ [0xE05]={
+ adobename="khokhonthai",
+ category="lo",
+ description="THAI CHARACTER KHO KHON",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE05,
+ },
+ [0xE06]={
+ adobename="khorakhangthai",
+ category="lo",
+ description="THAI CHARACTER KHO RAKHANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE06,
+ },
+ [0xE07]={
+ adobename="ngonguthai",
+ category="lo",
+ description="THAI CHARACTER NGO NGU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE07,
+ },
+ [0xE08]={
+ adobename="chochanthai",
+ category="lo",
+ description="THAI CHARACTER CHO CHAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE08,
+ },
+ [0xE09]={
+ adobename="chochingthai",
+ category="lo",
+ description="THAI CHARACTER CHO CHING",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE09,
+ },
+ [0xE0A]={
+ adobename="chochangthai",
+ category="lo",
+ description="THAI CHARACTER CHO CHANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0A,
+ },
+ [0xE0B]={
+ adobename="sosothai",
+ category="lo",
+ description="THAI CHARACTER SO SO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0B,
+ },
+ [0xE0C]={
+ adobename="chochoethai",
+ category="lo",
+ description="THAI CHARACTER CHO CHOE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0C,
+ },
+ [0xE0D]={
+ adobename="yoyingthai",
+ category="lo",
+ description="THAI CHARACTER YO YING",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0D,
+ },
+ [0xE0E]={
+ adobename="dochadathai",
+ category="lo",
+ description="THAI CHARACTER DO CHADA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0E,
+ },
+ [0xE0F]={
+ adobename="topatakthai",
+ category="lo",
+ description="THAI CHARACTER TO PATAK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE0F,
+ },
+ [0xE10]={
+ adobename="thothanthai",
+ category="lo",
+ description="THAI CHARACTER THO THAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE10,
+ },
+ [0xE11]={
+ adobename="thonangmonthothai",
+ category="lo",
+ description="THAI CHARACTER THO NANGMONTHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE11,
+ },
+ [0xE12]={
+ adobename="thophuthaothai",
+ category="lo",
+ description="THAI CHARACTER THO PHUTHAO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE12,
+ },
+ [0xE13]={
+ adobename="nonenthai",
+ category="lo",
+ description="THAI CHARACTER NO NEN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE13,
+ },
+ [0xE14]={
+ adobename="dodekthai",
+ category="lo",
+ description="THAI CHARACTER DO DEK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE14,
+ },
+ [0xE15]={
+ adobename="totaothai",
+ category="lo",
+ description="THAI CHARACTER TO TAO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE15,
+ },
+ [0xE16]={
+ adobename="thothungthai",
+ category="lo",
+ description="THAI CHARACTER THO THUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE16,
+ },
+ [0xE17]={
+ adobename="thothahanthai",
+ category="lo",
+ description="THAI CHARACTER THO THAHAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE17,
+ },
+ [0xE18]={
+ adobename="thothongthai",
+ category="lo",
+ description="THAI CHARACTER THO THONG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE18,
+ },
+ [0xE19]={
+ adobename="nonuthai",
+ category="lo",
+ description="THAI CHARACTER NO NU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE19,
+ },
+ [0xE1A]={
+ adobename="bobaimaithai",
+ category="lo",
+ description="THAI CHARACTER BO BAIMAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1A,
+ },
+ [0xE1B]={
+ adobename="poplathai",
+ category="lo",
+ description="THAI CHARACTER PO PLA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1B,
+ },
+ [0xE1C]={
+ adobename="phophungthai",
+ category="lo",
+ description="THAI CHARACTER PHO PHUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1C,
+ },
+ [0xE1D]={
+ adobename="fofathai",
+ category="lo",
+ description="THAI CHARACTER FO FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1D,
+ },
+ [0xE1E]={
+ adobename="phophanthai",
+ category="lo",
+ description="THAI CHARACTER PHO PHAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1E,
+ },
+ [0xE1F]={
+ adobename="fofanthai",
+ category="lo",
+ description="THAI CHARACTER FO FAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE1F,
+ },
+ [0xE20]={
+ adobename="phosamphaothai",
+ category="lo",
+ description="THAI CHARACTER PHO SAMPHAO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE20,
+ },
+ [0xE21]={
+ adobename="momathai",
+ category="lo",
+ description="THAI CHARACTER MO MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE21,
+ },
+ [0xE22]={
+ adobename="yoyakthai",
+ category="lo",
+ description="THAI CHARACTER YO YAK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE22,
+ },
+ [0xE23]={
+ adobename="roruathai",
+ category="lo",
+ description="THAI CHARACTER RO RUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE23,
+ },
+ [0xE24]={
+ adobename="ruthai",
+ category="lo",
+ description="THAI CHARACTER RU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE24,
+ },
+ [0xE25]={
+ adobename="lolingthai",
+ category="lo",
+ description="THAI CHARACTER LO LING",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE25,
+ },
+ [0xE26]={
+ adobename="luthai",
+ category="lo",
+ description="THAI CHARACTER LU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE26,
+ },
+ [0xE27]={
+ adobename="wowaenthai",
+ category="lo",
+ description="THAI CHARACTER WO WAEN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE27,
+ },
+ [0xE28]={
+ adobename="sosalathai",
+ category="lo",
+ description="THAI CHARACTER SO SALA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE28,
+ },
+ [0xE29]={
+ adobename="sorusithai",
+ category="lo",
+ description="THAI CHARACTER SO RUSI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE29,
+ },
+ [0xE2A]={
+ adobename="sosuathai",
+ category="lo",
+ description="THAI CHARACTER SO SUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2A,
+ },
+ [0xE2B]={
+ adobename="hohipthai",
+ category="lo",
+ description="THAI CHARACTER HO HIP",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2B,
+ },
+ [0xE2C]={
+ adobename="lochulathai",
+ category="lo",
+ description="THAI CHARACTER LO CHULA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2C,
+ },
+ [0xE2D]={
+ adobename="oangthai",
+ category="lo",
+ description="THAI CHARACTER O ANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2D,
+ },
+ [0xE2E]={
+ adobename="honokhukthai",
+ category="lo",
+ description="THAI CHARACTER HO NOKHUK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2E,
+ },
+ [0xE2F]={
+ adobename="paiyannoithai",
+ category="lo",
+ description="THAI CHARACTER PAIYANNOI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE2F,
+ },
+ [0xE30]={
+ adobename="saraathai",
+ category="lo",
+ description="THAI CHARACTER SARA A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE30,
+ },
+ [0xE31]={
+ adobename="maihanakatthai",
+ category="mn",
+ description="THAI CHARACTER MAI HAN-AKAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE31,
+ },
+ [0xE32]={
+ adobename="saraaathai",
+ category="lo",
+ description="THAI CHARACTER SARA AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE32,
+ },
+ [0xE33]={
+ adobename="saraamthai",
+ category="lo",
+ description="THAI CHARACTER SARA AM",
+ direction="l",
+ linebreak="sa",
+ specials={ "compat", 0xE4D, 0xE32 },
+ unicodeslot=0xE33,
+ },
+ [0xE34]={
+ adobename="saraithai",
+ category="mn",
+ description="THAI CHARACTER SARA I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE34,
+ },
+ [0xE35]={
+ adobename="saraiithai",
+ category="mn",
+ description="THAI CHARACTER SARA II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE35,
+ },
+ [0xE36]={
+ adobename="sarauethai",
+ category="mn",
+ description="THAI CHARACTER SARA UE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE36,
+ },
+ [0xE37]={
+ adobename="saraueethai",
+ category="mn",
+ description="THAI CHARACTER SARA UEE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE37,
+ },
+ [0xE38]={
+ adobename="sarauthai",
+ category="mn",
+ combining=0x67,
+ description="THAI CHARACTER SARA U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE38,
+ },
+ [0xE39]={
+ adobename="sarauuthai",
+ category="mn",
+ combining=0x67,
+ description="THAI CHARACTER SARA UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE39,
+ },
+ [0xE3A]={
+ adobename="phinthuthai",
+ category="mn",
+ combining=0x9,
+ description="THAI CHARACTER PHINTHU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE3A,
+ },
+ [0xE3F]={
+ adobename="bahtthai",
+ category="sc",
+ description="THAI CURRENCY SYMBOL BAHT",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0xE3F,
+ },
+ [0xE40]={
+ adobename="saraethai",
+ category="lo",
+ description="THAI CHARACTER SARA E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE40,
+ },
+ [0xE41]={
+ adobename="saraaethai",
+ category="lo",
+ description="THAI CHARACTER SARA AE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE41,
+ },
+ [0xE42]={
+ adobename="saraothai",
+ category="lo",
+ description="THAI CHARACTER SARA O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE42,
+ },
+ [0xE43]={
+ adobename="saraaimaimuanthai",
+ category="lo",
+ description="THAI CHARACTER SARA AI MAIMUAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE43,
+ },
+ [0xE44]={
+ adobename="saraaimaimalaithai",
+ category="lo",
+ description="THAI CHARACTER SARA AI MAIMALAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE44,
+ },
+ [0xE45]={
+ adobename="lakkhangyaothai",
+ category="lo",
+ description="THAI CHARACTER LAKKHANGYAO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE45,
+ },
+ [0xE46]={
+ adobename="maiyamokthai",
+ category="lm",
+ description="THAI CHARACTER MAIYAMOK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE46,
+ },
+ [0xE47]={
+ adobename="maitaikhuthai",
+ category="mn",
+ description="THAI CHARACTER MAITAIKHU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE47,
+ },
+ [0xE48]={
+ adobename="maiekthai",
+ category="mn",
+ combining=0x6B,
+ description="THAI CHARACTER MAI EK",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE48,
+ },
+ [0xE49]={
+ adobename="maithothai",
+ category="mn",
+ combining=0x6B,
+ description="THAI CHARACTER MAI THO",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE49,
+ },
+ [0xE4A]={
+ adobename="maitrithai",
+ category="mn",
+ combining=0x6B,
+ description="THAI CHARACTER MAI TRI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE4A,
+ },
+ [0xE4B]={
+ adobename="maichattawathai",
+ category="mn",
+ combining=0x6B,
+ description="THAI CHARACTER MAI CHATTAWA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE4B,
+ },
+ [0xE4C]={
+ adobename="thanthakhatthai",
+ category="mn",
+ description="THAI CHARACTER THANTHAKHAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE4C,
+ },
+ [0xE4D]={
+ adobename="nikhahitthai",
+ category="mn",
+ description="THAI CHARACTER NIKHAHIT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE4D,
+ },
+ [0xE4E]={
+ adobename="yamakkanthai",
+ category="mn",
+ description="THAI CHARACTER YAMAKKAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xE4E,
+ },
+ [0xE4F]={
+ adobename="fongmanthai",
+ category="po",
+ description="THAI CHARACTER FONGMAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xE4F,
+ },
+ [0xE50]={
+ adobename="zerothai",
+ category="nd",
+ description="THAI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE50,
+ },
+ [0xE51]={
+ adobename="onethai",
+ category="nd",
+ description="THAI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE51,
+ },
+ [0xE52]={
+ adobename="twothai",
+ category="nd",
+ description="THAI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE52,
+ },
+ [0xE53]={
+ adobename="threethai",
+ category="nd",
+ description="THAI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE53,
+ },
+ [0xE54]={
+ adobename="fourthai",
+ category="nd",
+ description="THAI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE54,
+ },
+ [0xE55]={
+ adobename="fivethai",
+ category="nd",
+ description="THAI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE55,
+ },
+ [0xE56]={
+ adobename="sixthai",
+ category="nd",
+ description="THAI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE56,
+ },
+ [0xE57]={
+ adobename="seventhai",
+ category="nd",
+ description="THAI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE57,
+ },
+ [0xE58]={
+ adobename="eightthai",
+ category="nd",
+ description="THAI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE58,
+ },
+ [0xE59]={
+ adobename="ninethai",
+ category="nd",
+ description="THAI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xE59,
+ },
+ [0xE5A]={
+ adobename="angkhankhuthai",
+ category="po",
+ description="THAI CHARACTER ANGKHANKHU",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xE5A,
+ },
+ [0xE5B]={
+ adobename="khomutthai",
+ category="po",
+ description="THAI CHARACTER KHOMUT",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xE5B,
+ },
+ [0xE81]={
+ category="lo",
+ description="LAO LETTER KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE81,
+ },
+ [0xE82]={
+ category="lo",
+ description="LAO LETTER KHO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE82,
+ },
+ [0xE84]={
+ category="lo",
+ description="LAO LETTER KHO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE84,
+ },
+ [0xE87]={
+ category="lo",
+ description="LAO LETTER NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE87,
+ },
+ [0xE88]={
+ category="lo",
+ description="LAO LETTER CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE88,
+ },
+ [0xE8A]={
+ category="lo",
+ description="LAO LETTER SO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE8A,
+ },
+ [0xE8D]={
+ category="lo",
+ description="LAO LETTER NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE8D,
+ },
+ [0xE94]={
+ category="lo",
+ description="LAO LETTER DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE94,
+ },
+ [0xE95]={
+ category="lo",
+ description="LAO LETTER TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE95,
+ },
+ [0xE96]={
+ category="lo",
+ description="LAO LETTER THO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE96,
+ },
+ [0xE97]={
+ category="lo",
+ description="LAO LETTER THO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE97,
+ },
+ [0xE99]={
+ category="lo",
+ description="LAO LETTER NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE99,
+ },
+ [0xE9A]={
+ category="lo",
+ description="LAO LETTER BO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9A,
+ },
+ [0xE9B]={
+ category="lo",
+ description="LAO LETTER PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9B,
+ },
+ [0xE9C]={
+ category="lo",
+ description="LAO LETTER PHO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9C,
+ },
+ [0xE9D]={
+ category="lo",
+ description="LAO LETTER FO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9D,
+ },
+ [0xE9E]={
+ category="lo",
+ description="LAO LETTER PHO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9E,
+ },
+ [0xE9F]={
+ category="lo",
+ description="LAO LETTER FO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xE9F,
+ },
+ [0xEA1]={
+ category="lo",
+ description="LAO LETTER MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEA1,
+ },
+ [0xEA2]={
+ category="lo",
+ description="LAO LETTER YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEA2,
+ },
+ [0xEA3]={
+ category="lo",
+ description="LAO LETTER LO LING",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEA3,
+ },
+ [0xEA5]={
+ category="lo",
+ description="LAO LETTER LO LOOT",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEA5,
+ },
+ [0xEA7]={
+ category="lo",
+ description="LAO LETTER WO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEA7,
+ },
+ [0xEAA]={
+ category="lo",
+ description="LAO LETTER SO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEAA,
+ },
+ [0xEAB]={
+ category="lo",
+ description="LAO LETTER HO SUNG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEAB,
+ },
+ [0xEAD]={
+ category="lo",
+ description="LAO LETTER O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEAD,
+ },
+ [0xEAE]={
+ category="lo",
+ description="LAO LETTER HO TAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEAE,
+ },
+ [0xEAF]={
+ category="lo",
+ description="LAO ELLIPSIS",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEAF,
+ },
+ [0xEB0]={
+ category="lo",
+ description="LAO VOWEL SIGN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEB0,
+ },
+ [0xEB1]={
+ category="mn",
+ description="LAO VOWEL SIGN MAI KAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB1,
+ },
+ [0xEB2]={
+ category="lo",
+ description="LAO VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEB2,
+ },
+ [0xEB3]={
+ category="lo",
+ description="LAO VOWEL SIGN AM",
+ direction="l",
+ linebreak="sa",
+ specials={ "compat", 0xECD, 0xEB2 },
+ unicodeslot=0xEB3,
+ },
+ [0xEB4]={
+ category="mn",
+ description="LAO VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB4,
+ },
+ [0xEB5]={
+ category="mn",
+ description="LAO VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB5,
+ },
+ [0xEB6]={
+ category="mn",
+ description="LAO VOWEL SIGN Y",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB6,
+ },
+ [0xEB7]={
+ category="mn",
+ description="LAO VOWEL SIGN YY",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB7,
+ },
+ [0xEB8]={
+ category="mn",
+ combining=0x76,
+ description="LAO VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB8,
+ },
+ [0xEB9]={
+ category="mn",
+ combining=0x76,
+ description="LAO VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEB9,
+ },
+ [0xEBB]={
+ category="mn",
+ description="LAO VOWEL SIGN MAI KON",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEBB,
+ },
+ [0xEBC]={
+ category="mn",
+ description="LAO SEMIVOWEL SIGN LO",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEBC,
+ },
+ [0xEBD]={
+ category="lo",
+ description="LAO SEMIVOWEL SIGN NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEBD,
+ },
+ [0xEC0]={
+ category="lo",
+ description="LAO VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC0,
+ },
+ [0xEC1]={
+ category="lo",
+ description="LAO VOWEL SIGN EI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC1,
+ },
+ [0xEC2]={
+ category="lo",
+ description="LAO VOWEL SIGN O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC2,
+ },
+ [0xEC3]={
+ category="lo",
+ description="LAO VOWEL SIGN AY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC3,
+ },
+ [0xEC4]={
+ category="lo",
+ description="LAO VOWEL SIGN AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC4,
+ },
+ [0xEC6]={
+ category="lm",
+ description="LAO KO LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEC6,
+ },
+ [0xEC8]={
+ category="mn",
+ combining=0x7A,
+ description="LAO TONE MAI EK",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEC8,
+ },
+ [0xEC9]={
+ category="mn",
+ combining=0x7A,
+ description="LAO TONE MAI THO",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xEC9,
+ },
+ [0xECA]={
+ category="mn",
+ combining=0x7A,
+ description="LAO TONE MAI TI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xECA,
+ },
+ [0xECB]={
+ category="mn",
+ combining=0x7A,
+ description="LAO TONE MAI CATAWA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xECB,
+ },
+ [0xECC]={
+ category="mn",
+ description="LAO CANCELLATION MARK",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xECC,
+ },
+ [0xECD]={
+ category="mn",
+ description="LAO NIGGAHITA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xECD,
+ },
+ [0xED0]={
+ category="nd",
+ description="LAO DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED0,
+ },
+ [0xED1]={
+ category="nd",
+ description="LAO DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED1,
+ },
+ [0xED2]={
+ category="nd",
+ description="LAO DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED2,
+ },
+ [0xED3]={
+ category="nd",
+ description="LAO DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED3,
+ },
+ [0xED4]={
+ category="nd",
+ description="LAO DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED4,
+ },
+ [0xED5]={
+ category="nd",
+ description="LAO DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED5,
+ },
+ [0xED6]={
+ category="nd",
+ description="LAO DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED6,
+ },
+ [0xED7]={
+ category="nd",
+ description="LAO DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED7,
+ },
+ [0xED8]={
+ category="nd",
+ description="LAO DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED8,
+ },
+ [0xED9]={
+ category="nd",
+ description="LAO DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xED9,
+ },
+ [0xEDC]={
+ category="lo",
+ description="LAO HO NO",
+ direction="l",
+ linebreak="sa",
+ specials={ "compat", 0xEAB, 0xE99 },
+ unicodeslot=0xEDC,
+ },
+ [0xEDD]={
+ category="lo",
+ description="LAO HO MO",
+ direction="l",
+ linebreak="sa",
+ specials={ "compat", 0xEAB, 0xEA1 },
+ unicodeslot=0xEDD,
+ },
+ [0xEDE]={
+ category="lo",
+ description="LAO LETTER KHMU GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEDE,
+ },
+ [0xEDF]={
+ category="lo",
+ description="LAO LETTER KHMU NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xEDF,
+ },
+ [0xF00]={
+ category="lo",
+ description="TIBETAN SYLLABLE OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF00,
+ },
+ [0xF01]={
+ category="so",
+ description="TIBETAN MARK GTER YIG MGO TRUNCATED A",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF01,
+ },
+ [0xF02]={
+ category="so",
+ description="TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF02,
+ },
+ [0xF03]={
+ category="so",
+ description="TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF03,
+ },
+ [0xF04]={
+ category="po",
+ description="TIBETAN MARK INITIAL YIG MGO MDUN MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF04,
+ },
+ [0xF05]={
+ category="po",
+ description="TIBETAN MARK CLOSING YIG MGO SGAB MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF05,
+ },
+ [0xF06]={
+ category="po",
+ description="TIBETAN MARK CARET YIG MGO PHUR SHAD MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF06,
+ },
+ [0xF07]={
+ category="po",
+ description="TIBETAN MARK YIG MGO TSHEG SHAD MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF07,
+ },
+ [0xF08]={
+ category="po",
+ description="TIBETAN MARK SBRUL SHAD",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0xF08,
+ },
+ [0xF09]={
+ category="po",
+ description="TIBETAN MARK BSKUR YIG MGO",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF09,
+ },
+ [0xF0A]={
+ category="po",
+ description="TIBETAN MARK BKA- SHOG YIG MGO",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xF0A,
+ },
+ [0xF0B]={
+ category="po",
+ description="TIBETAN MARK INTERSYLLABIC TSHEG",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xF0B,
+ },
+ [0xF0C]={
+ category="po",
+ description="TIBETAN MARK DELIMITER TSHEG BSTAR",
+ direction="l",
+ linebreak="gl",
+ specials={ "nobreak", 0xF0B },
+ unicodeslot=0xF0C,
+ },
+ [0xF0D]={
+ category="po",
+ description="TIBETAN MARK SHAD",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF0D,
+ },
+ [0xF0E]={
+ category="po",
+ description="TIBETAN MARK NYIS SHAD",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF0E,
+ },
+ [0xF0F]={
+ category="po",
+ description="TIBETAN MARK TSHEG SHAD",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF0F,
+ },
+ [0xF10]={
+ category="po",
+ description="TIBETAN MARK NYIS TSHEG SHAD",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF10,
+ },
+ [0xF11]={
+ category="po",
+ description="TIBETAN MARK RIN CHEN SPUNGS SHAD",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF11,
+ },
+ [0xF12]={
+ category="po",
+ description="TIBETAN MARK RGYA GRAM SHAD",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0xF12,
+ },
+ [0xF13]={
+ category="so",
+ description="TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF13,
+ },
+ [0xF14]={
+ category="so",
+ description="TIBETAN MARK GTER TSHEG",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0xF14,
+ },
+ [0xF15]={
+ category="so",
+ description="TIBETAN LOGOTYPE SIGN CHAD RTAGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF15,
+ },
+ [0xF16]={
+ category="so",
+ description="TIBETAN LOGOTYPE SIGN LHAG RTAGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF16,
+ },
+ [0xF17]={
+ category="so",
+ description="TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF17,
+ },
+ [0xF18]={
+ category="mn",
+ combining=0xDC,
+ description="TIBETAN ASTROLOGICAL SIGN -KHYUD PA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF18,
+ },
+ [0xF19]={
+ category="mn",
+ combining=0xDC,
+ description="TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF19,
+ },
+ [0xF1A]={
+ category="so",
+ description="TIBETAN SIGN RDEL DKAR GCIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1A,
+ },
+ [0xF1B]={
+ category="so",
+ description="TIBETAN SIGN RDEL DKAR GNYIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1B,
+ },
+ [0xF1C]={
+ category="so",
+ description="TIBETAN SIGN RDEL DKAR GSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1C,
+ },
+ [0xF1D]={
+ category="so",
+ description="TIBETAN SIGN RDEL NAG GCIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1D,
+ },
+ [0xF1E]={
+ category="so",
+ description="TIBETAN SIGN RDEL NAG GNYIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1E,
+ },
+ [0xF1F]={
+ category="so",
+ description="TIBETAN SIGN RDEL DKAR RDEL NAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF1F,
+ },
+ [0xF20]={
+ category="nd",
+ description="TIBETAN DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF20,
+ },
+ [0xF21]={
+ category="nd",
+ description="TIBETAN DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF21,
+ },
+ [0xF22]={
+ category="nd",
+ description="TIBETAN DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF22,
+ },
+ [0xF23]={
+ category="nd",
+ description="TIBETAN DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF23,
+ },
+ [0xF24]={
+ category="nd",
+ description="TIBETAN DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF24,
+ },
+ [0xF25]={
+ category="nd",
+ description="TIBETAN DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF25,
+ },
+ [0xF26]={
+ category="nd",
+ description="TIBETAN DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF26,
+ },
+ [0xF27]={
+ category="nd",
+ description="TIBETAN DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF27,
+ },
+ [0xF28]={
+ category="nd",
+ description="TIBETAN DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF28,
+ },
+ [0xF29]={
+ category="nd",
+ description="TIBETAN DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xF29,
+ },
+ [0xF2A]={
+ category="no",
+ description="TIBETAN DIGIT HALF ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2A,
+ },
+ [0xF2B]={
+ category="no",
+ description="TIBETAN DIGIT HALF TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2B,
+ },
+ [0xF2C]={
+ category="no",
+ description="TIBETAN DIGIT HALF THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2C,
+ },
+ [0xF2D]={
+ category="no",
+ description="TIBETAN DIGIT HALF FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2D,
+ },
+ [0xF2E]={
+ category="no",
+ description="TIBETAN DIGIT HALF FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2E,
+ },
+ [0xF2F]={
+ category="no",
+ description="TIBETAN DIGIT HALF SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF2F,
+ },
+ [0xF30]={
+ category="no",
+ description="TIBETAN DIGIT HALF SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF30,
+ },
+ [0xF31]={
+ category="no",
+ description="TIBETAN DIGIT HALF EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF31,
+ },
+ [0xF32]={
+ category="no",
+ description="TIBETAN DIGIT HALF NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF32,
+ },
+ [0xF33]={
+ category="no",
+ description="TIBETAN DIGIT HALF ZERO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF33,
+ },
+ [0xF34]={
+ category="so",
+ description="TIBETAN MARK BSDUS RTAGS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xF34,
+ },
+ [0xF35]={
+ category="mn",
+ combining=0xDC,
+ description="TIBETAN MARK NGAS BZUNG NYI ZLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF35,
+ },
+ [0xF36]={
+ category="so",
+ description="TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF36,
+ },
+ [0xF37]={
+ category="mn",
+ combining=0xDC,
+ description="TIBETAN MARK NGAS BZUNG SGOR RTAGS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF37,
+ },
+ [0xF38]={
+ category="so",
+ description="TIBETAN MARK CHE MGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF38,
+ },
+ [0xF39]={
+ category="mn",
+ combining=0xD8,
+ description="TIBETAN MARK TSA -PHRU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF39,
+ },
+ [0xF3A]={
+ category="ps",
+ description="TIBETAN MARK GUG RTAGS GYON",
+ direction="on",
+ linebreak="op",
+ mirror=0xF3B,
+ unicodeslot=0xF3A,
+ },
+ [0xF3B]={
+ category="pe",
+ description="TIBETAN MARK GUG RTAGS GYAS",
+ direction="on",
+ linebreak="cl",
+ mirror=0xF3A,
+ unicodeslot=0xF3B,
+ },
+ [0xF3C]={
+ category="ps",
+ description="TIBETAN MARK ANG KHANG GYON",
+ direction="on",
+ linebreak="op",
+ mirror=0xF3D,
+ unicodeslot=0xF3C,
+ },
+ [0xF3D]={
+ category="pe",
+ description="TIBETAN MARK ANG KHANG GYAS",
+ direction="on",
+ linebreak="cl",
+ mirror=0xF3C,
+ unicodeslot=0xF3D,
+ },
+ [0xF3E]={
+ category="mc",
+ description="TIBETAN SIGN YAR TSHES",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xF3E,
+ },
+ [0xF3F]={
+ category="mc",
+ description="TIBETAN SIGN MAR TSHES",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xF3F,
+ },
+ [0xF40]={
+ category="lo",
+ description="TIBETAN LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF40,
+ },
+ [0xF41]={
+ category="lo",
+ description="TIBETAN LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF41,
+ },
+ [0xF42]={
+ category="lo",
+ description="TIBETAN LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF42,
+ },
+ [0xF43]={
+ category="lo",
+ description="TIBETAN LETTER GHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF42, 0xFB7 },
+ unicodeslot=0xF43,
+ },
+ [0xF44]={
+ category="lo",
+ description="TIBETAN LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF44,
+ },
+ [0xF45]={
+ category="lo",
+ description="TIBETAN LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF45,
+ },
+ [0xF46]={
+ category="lo",
+ description="TIBETAN LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF46,
+ },
+ [0xF47]={
+ category="lo",
+ description="TIBETAN LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF47,
+ },
+ [0xF49]={
+ category="lo",
+ description="TIBETAN LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF49,
+ },
+ [0xF4A]={
+ category="lo",
+ description="TIBETAN LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF4A,
+ },
+ [0xF4B]={
+ category="lo",
+ description="TIBETAN LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF4B,
+ },
+ [0xF4C]={
+ category="lo",
+ description="TIBETAN LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF4C,
+ },
+ [0xF4D]={
+ category="lo",
+ description="TIBETAN LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF4C, 0xFB7 },
+ unicodeslot=0xF4D,
+ },
+ [0xF4E]={
+ category="lo",
+ description="TIBETAN LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF4E,
+ },
+ [0xF4F]={
+ category="lo",
+ description="TIBETAN LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF4F,
+ },
+ [0xF50]={
+ category="lo",
+ description="TIBETAN LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF50,
+ },
+ [0xF51]={
+ category="lo",
+ description="TIBETAN LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF51,
+ },
+ [0xF52]={
+ category="lo",
+ description="TIBETAN LETTER DHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF51, 0xFB7 },
+ unicodeslot=0xF52,
+ },
+ [0xF53]={
+ category="lo",
+ description="TIBETAN LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF53,
+ },
+ [0xF54]={
+ category="lo",
+ description="TIBETAN LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF54,
+ },
+ [0xF55]={
+ category="lo",
+ description="TIBETAN LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF55,
+ },
+ [0xF56]={
+ category="lo",
+ description="TIBETAN LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF56,
+ },
+ [0xF57]={
+ category="lo",
+ description="TIBETAN LETTER BHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF56, 0xFB7 },
+ unicodeslot=0xF57,
+ },
+ [0xF58]={
+ category="lo",
+ description="TIBETAN LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF58,
+ },
+ [0xF59]={
+ category="lo",
+ description="TIBETAN LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF59,
+ },
+ [0xF5A]={
+ category="lo",
+ description="TIBETAN LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF5A,
+ },
+ [0xF5B]={
+ category="lo",
+ description="TIBETAN LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF5B,
+ },
+ [0xF5C]={
+ category="lo",
+ description="TIBETAN LETTER DZHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF5B, 0xFB7 },
+ unicodeslot=0xF5C,
+ },
+ [0xF5D]={
+ category="lo",
+ description="TIBETAN LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF5D,
+ },
+ [0xF5E]={
+ category="lo",
+ description="TIBETAN LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF5E,
+ },
+ [0xF5F]={
+ category="lo",
+ description="TIBETAN LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF5F,
+ },
+ [0xF60]={
+ category="lo",
+ description="TIBETAN LETTER -A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF60,
+ },
+ [0xF61]={
+ category="lo",
+ description="TIBETAN LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF61,
+ },
+ [0xF62]={
+ category="lo",
+ description="TIBETAN LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF62,
+ },
+ [0xF63]={
+ category="lo",
+ description="TIBETAN LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF63,
+ },
+ [0xF64]={
+ category="lo",
+ description="TIBETAN LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF64,
+ },
+ [0xF65]={
+ category="lo",
+ description="TIBETAN LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF65,
+ },
+ [0xF66]={
+ category="lo",
+ description="TIBETAN LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF66,
+ },
+ [0xF67]={
+ category="lo",
+ description="TIBETAN LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF67,
+ },
+ [0xF68]={
+ category="lo",
+ description="TIBETAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF68,
+ },
+ [0xF69]={
+ category="lo",
+ description="TIBETAN LETTER KSSA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0xF40, 0xFB5 },
+ unicodeslot=0xF69,
+ },
+ [0xF6A]={
+ category="lo",
+ description="TIBETAN LETTER FIXED-FORM RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF6A,
+ },
+ [0xF6B]={
+ category="lo",
+ description="TIBETAN LETTER KKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF6B,
+ },
+ [0xF6C]={
+ category="lo",
+ description="TIBETAN LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF6C,
+ },
+ [0xF71]={
+ category="mn",
+ combining=0x81,
+ description="TIBETAN VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF71,
+ },
+ [0xF72]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF72,
+ },
+ [0xF73]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF71, 0xF72 },
+ unicodeslot=0xF73,
+ },
+ [0xF74]={
+ category="mn",
+ combining=0x84,
+ description="TIBETAN VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF74,
+ },
+ [0xF75]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF71, 0xF74 },
+ unicodeslot=0xF75,
+ },
+ [0xF76]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xFB2, 0xF80 },
+ unicodeslot=0xF76,
+ },
+ [0xF77]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "compat", 0xFB2, 0xF81 },
+ unicodeslot=0xF77,
+ },
+ [0xF78]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xFB3, 0xF80 },
+ unicodeslot=0xF78,
+ },
+ [0xF79]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "compat", 0xFB3, 0xF81 },
+ unicodeslot=0xF79,
+ },
+ [0xF7A]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF7A,
+ },
+ [0xF7B]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF7B,
+ },
+ [0xF7C]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF7C,
+ },
+ [0xF7D]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN OO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF7D,
+ },
+ [0xF7E]={
+ category="mn",
+ description="TIBETAN SIGN RJES SU NGA RO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF7E,
+ },
+ [0xF7F]={
+ category="mc",
+ description="TIBETAN SIGN RNAM BCAD",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xF7F,
+ },
+ [0xF80]={
+ category="mn",
+ combining=0x82,
+ description="TIBETAN VOWEL SIGN REVERSED I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF80,
+ },
+ [0xF81]={
+ category="mn",
+ description="TIBETAN VOWEL SIGN REVERSED II",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF71, 0xF80 },
+ unicodeslot=0xF81,
+ },
+ [0xF82]={
+ category="mn",
+ combining=0xE6,
+ description="TIBETAN SIGN NYI ZLA NAA DA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF82,
+ },
+ [0xF83]={
+ category="mn",
+ combining=0xE6,
+ description="TIBETAN SIGN SNA LDAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF83,
+ },
+ [0xF84]={
+ category="mn",
+ combining=0x9,
+ description="TIBETAN MARK HALANTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF84,
+ },
+ [0xF85]={
+ category="po",
+ description="TIBETAN MARK PALUTA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xF85,
+ },
+ [0xF86]={
+ category="mn",
+ combining=0xE6,
+ description="TIBETAN SIGN LCI RTAGS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF86,
+ },
+ [0xF87]={
+ category="mn",
+ combining=0xE6,
+ description="TIBETAN SIGN YANG RTAGS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF87,
+ },
+ [0xF88]={
+ category="lo",
+ description="TIBETAN SIGN LCE TSA CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF88,
+ },
+ [0xF89]={
+ category="lo",
+ description="TIBETAN SIGN MCHU CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF89,
+ },
+ [0xF8A]={
+ category="lo",
+ description="TIBETAN SIGN GRU CAN RGYINGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF8A,
+ },
+ [0xF8B]={
+ category="lo",
+ description="TIBETAN SIGN GRU MED RGYINGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF8B,
+ },
+ [0xF8C]={
+ category="lo",
+ description="TIBETAN SIGN INVERTED MCHU CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xF8C,
+ },
+ [0xF8D]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN LCE TSA CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF8D,
+ },
+ [0xF8E]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN MCHU CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF8E,
+ },
+ [0xF8F]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN INVERTED MCHU CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF8F,
+ },
+ [0xF90]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF90,
+ },
+ [0xF91]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER KHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF91,
+ },
+ [0xF92]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER GA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF92,
+ },
+ [0xF93]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER GHA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF92, 0xFB7 },
+ unicodeslot=0xF93,
+ },
+ [0xF94]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER NGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF94,
+ },
+ [0xF95]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER CA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF95,
+ },
+ [0xF96]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER CHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF96,
+ },
+ [0xF97]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER JA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF97,
+ },
+ [0xF99]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER NYA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF99,
+ },
+ [0xF9A]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER TTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF9A,
+ },
+ [0xF9B]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER TTHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF9B,
+ },
+ [0xF9C]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF9C,
+ },
+ [0xF9D]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DDHA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF9C, 0xFB7 },
+ unicodeslot=0xF9D,
+ },
+ [0xF9E]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER NNA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF9E,
+ },
+ [0xF9F]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER TA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xF9F,
+ },
+ [0xFA0]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER THA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA0,
+ },
+ [0xFA1]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA1,
+ },
+ [0xFA2]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DHA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xFA1, 0xFB7 },
+ unicodeslot=0xFA2,
+ },
+ [0xFA3]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER NA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA3,
+ },
+ [0xFA4]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER PA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA4,
+ },
+ [0xFA5]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER PHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA5,
+ },
+ [0xFA6]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER BA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA6,
+ },
+ [0xFA7]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER BHA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xFA6, 0xFB7 },
+ unicodeslot=0xFA7,
+ },
+ [0xFA8]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER MA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA8,
+ },
+ [0xFA9]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER TSA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFA9,
+ },
+ [0xFAA]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER TSHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFAA,
+ },
+ [0xFAB]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DZA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFAB,
+ },
+ [0xFAC]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER DZHA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xFAB, 0xFB7 },
+ unicodeslot=0xFAC,
+ },
+ [0xFAD]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER WA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFAD,
+ },
+ [0xFAE]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER ZHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFAE,
+ },
+ [0xFAF]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER ZA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFAF,
+ },
+ [0xFB0]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER -A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB0,
+ },
+ [0xFB1]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER YA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB1,
+ },
+ [0xFB2]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER RA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB2,
+ },
+ [0xFB3]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER LA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB3,
+ },
+ [0xFB4]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER SHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB4,
+ },
+ [0xFB5]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER SSA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB5,
+ },
+ [0xFB6]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER SA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB6,
+ },
+ [0xFB7]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER HA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB7,
+ },
+ [0xFB8]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB8,
+ },
+ [0xFB9]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER KSSA",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0xF90, 0xFB5 },
+ unicodeslot=0xFB9,
+ },
+ [0xFBA]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER FIXED-FORM WA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFBA,
+ },
+ [0xFBB]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER FIXED-FORM YA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFBB,
+ },
+ [0xFBC]={
+ category="mn",
+ description="TIBETAN SUBJOINED LETTER FIXED-FORM RA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFBC,
+ },
+ [0xFBE]={
+ category="so",
+ description="TIBETAN KU RU KHA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xFBE,
+ },
+ [0xFBF]={
+ category="so",
+ description="TIBETAN KU RU KHA BZHI MIG CAN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xFBF,
+ },
+ [0xFC0]={
+ category="so",
+ description="TIBETAN CANTILLATION SIGN HEAVY BEAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC0,
+ },
+ [0xFC1]={
+ category="so",
+ description="TIBETAN CANTILLATION SIGN LIGHT BEAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC1,
+ },
+ [0xFC2]={
+ category="so",
+ description="TIBETAN CANTILLATION SIGN CANG TE-U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC2,
+ },
+ [0xFC3]={
+ category="so",
+ description="TIBETAN CANTILLATION SIGN SBUB -CHAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC3,
+ },
+ [0xFC4]={
+ category="so",
+ description="TIBETAN SYMBOL DRIL BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC4,
+ },
+ [0xFC5]={
+ category="so",
+ description="TIBETAN SYMBOL RDO RJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC5,
+ },
+ [0xFC6]={
+ category="mn",
+ combining=0xDC,
+ description="TIBETAN SYMBOL PADMA GDAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFC6,
+ },
+ [0xFC7]={
+ category="so",
+ description="TIBETAN SYMBOL RDO RJE RGYA GRAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC7,
+ },
+ [0xFC8]={
+ category="so",
+ description="TIBETAN SYMBOL PHUR PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC8,
+ },
+ [0xFC9]={
+ category="so",
+ description="TIBETAN SYMBOL NOR BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFC9,
+ },
+ [0xFCA]={
+ category="so",
+ description="TIBETAN SYMBOL NOR BU NYIS -KHYIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFCA,
+ },
+ [0xFCB]={
+ category="so",
+ description="TIBETAN SYMBOL NOR BU GSUM -KHYIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFCB,
+ },
+ [0xFCC]={
+ category="so",
+ description="TIBETAN SYMBOL NOR BU BZHI -KHYIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFCC,
+ },
+ [0xFCE]={
+ category="so",
+ description="TIBETAN SIGN RDEL NAG RDEL DKAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFCE,
+ },
+ [0xFCF]={
+ category="so",
+ description="TIBETAN SIGN RDEL NAG GSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFCF,
+ },
+ [0xFD0]={
+ category="po",
+ description="TIBETAN MARK BSKA- SHOG GI MGO RGYAN",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xFD0,
+ },
+ [0xFD1]={
+ category="po",
+ description="TIBETAN MARK MNYAM YIG GI MGO RGYAN",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xFD1,
+ },
+ [0xFD2]={
+ category="po",
+ description="TIBETAN MARK NYIS TSHEG",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xFD2,
+ },
+ [0xFD3]={
+ category="po",
+ description="TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xFD3,
+ },
+ [0xFD4]={
+ category="po",
+ description="TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFD4,
+ },
+ [0xFD5]={
+ category="so",
+ description="RIGHT-FACING SVASTI SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFD5,
+ },
+ [0xFD6]={
+ category="so",
+ description="LEFT-FACING SVASTI SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFD6,
+ },
+ [0xFD7]={
+ category="so",
+ description="RIGHT-FACING SVASTI SIGN WITH DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFD7,
+ },
+ [0xFD8]={
+ category="so",
+ description="LEFT-FACING SVASTI SIGN WITH DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xFD8,
+ },
+ [0xFD9]={
+ category="po",
+ description="TIBETAN MARK LEADING MCHAN RTAGS",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0xFD9,
+ },
+ [0xFDA]={
+ category="po",
+ description="TIBETAN MARK TRAILING MCHAN RTAGS",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0xFDA,
+ },
+ [0x1000]={
+ category="lo",
+ description="MYANMAR LETTER KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1000,
+ },
+ [0x1001]={
+ category="lo",
+ description="MYANMAR LETTER KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1001,
+ },
+ [0x1002]={
+ category="lo",
+ description="MYANMAR LETTER GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1002,
+ },
+ [0x1003]={
+ category="lo",
+ description="MYANMAR LETTER GHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1003,
+ },
+ [0x1004]={
+ category="lo",
+ description="MYANMAR LETTER NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1004,
+ },
+ [0x1005]={
+ category="lo",
+ description="MYANMAR LETTER CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1005,
+ },
+ [0x1006]={
+ category="lo",
+ description="MYANMAR LETTER CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1006,
+ },
+ [0x1007]={
+ category="lo",
+ description="MYANMAR LETTER JA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1007,
+ },
+ [0x1008]={
+ category="lo",
+ description="MYANMAR LETTER JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1008,
+ },
+ [0x1009]={
+ category="lo",
+ description="MYANMAR LETTER NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1009,
+ },
+ [0x100A]={
+ category="lo",
+ description="MYANMAR LETTER NNYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100A,
+ },
+ [0x100B]={
+ category="lo",
+ description="MYANMAR LETTER TTA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100B,
+ },
+ [0x100C]={
+ category="lo",
+ description="MYANMAR LETTER TTHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100C,
+ },
+ [0x100D]={
+ category="lo",
+ description="MYANMAR LETTER DDA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100D,
+ },
+ [0x100E]={
+ category="lo",
+ description="MYANMAR LETTER DDHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100E,
+ },
+ [0x100F]={
+ category="lo",
+ description="MYANMAR LETTER NNA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x100F,
+ },
+ [0x1010]={
+ category="lo",
+ description="MYANMAR LETTER TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1010,
+ },
+ [0x1011]={
+ category="lo",
+ description="MYANMAR LETTER THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1011,
+ },
+ [0x1012]={
+ category="lo",
+ description="MYANMAR LETTER DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1012,
+ },
+ [0x1013]={
+ category="lo",
+ description="MYANMAR LETTER DHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1013,
+ },
+ [0x1014]={
+ category="lo",
+ description="MYANMAR LETTER NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1014,
+ },
+ [0x1015]={
+ category="lo",
+ description="MYANMAR LETTER PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1015,
+ },
+ [0x1016]={
+ category="lo",
+ description="MYANMAR LETTER PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1016,
+ },
+ [0x1017]={
+ category="lo",
+ description="MYANMAR LETTER BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1017,
+ },
+ [0x1018]={
+ category="lo",
+ description="MYANMAR LETTER BHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1018,
+ },
+ [0x1019]={
+ category="lo",
+ description="MYANMAR LETTER MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1019,
+ },
+ [0x101A]={
+ category="lo",
+ description="MYANMAR LETTER YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101A,
+ },
+ [0x101B]={
+ category="lo",
+ description="MYANMAR LETTER RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101B,
+ },
+ [0x101C]={
+ category="lo",
+ description="MYANMAR LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101C,
+ },
+ [0x101D]={
+ category="lo",
+ description="MYANMAR LETTER WA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101D,
+ },
+ [0x101E]={
+ category="lo",
+ description="MYANMAR LETTER SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101E,
+ },
+ [0x101F]={
+ category="lo",
+ description="MYANMAR LETTER HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x101F,
+ },
+ [0x1020]={
+ category="lo",
+ description="MYANMAR LETTER LLA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1020,
+ },
+ [0x1021]={
+ category="lo",
+ description="MYANMAR LETTER A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1021,
+ },
+ [0x1022]={
+ category="lo",
+ description="MYANMAR LETTER SHAN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1022,
+ },
+ [0x1023]={
+ category="lo",
+ description="MYANMAR LETTER I",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1023,
+ },
+ [0x1024]={
+ category="lo",
+ description="MYANMAR LETTER II",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1024,
+ },
+ [0x1025]={
+ category="lo",
+ description="MYANMAR LETTER U",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1025,
+ },
+ [0x1026]={
+ category="lo",
+ description="MYANMAR LETTER UU",
+ direction="l",
+ linebreak="sa",
+ specials={ "char", 0x1025, 0x102E },
+ unicodeslot=0x1026,
+ },
+ [0x1027]={
+ category="lo",
+ description="MYANMAR LETTER E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1027,
+ },
+ [0x1028]={
+ category="lo",
+ description="MYANMAR LETTER MON E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1028,
+ },
+ [0x1029]={
+ category="lo",
+ description="MYANMAR LETTER O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1029,
+ },
+ [0x102A]={
+ category="lo",
+ description="MYANMAR LETTER AU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x102A,
+ },
+ [0x102B]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN TALL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x102B,
+ },
+ [0x102C]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x102C,
+ },
+ [0x102D]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x102D,
+ },
+ [0x102E]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x102E,
+ },
+ [0x102F]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x102F,
+ },
+ [0x1030]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1030,
+ },
+ [0x1031]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1031,
+ },
+ [0x1032]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1032,
+ },
+ [0x1033]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN MON II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1033,
+ },
+ [0x1034]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN MON O",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1034,
+ },
+ [0x1035]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN E ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1035,
+ },
+ [0x1036]={
+ category="mn",
+ description="MYANMAR SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1036,
+ },
+ [0x1037]={
+ category="mn",
+ combining=0x7,
+ description="MYANMAR SIGN DOT BELOW",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1037,
+ },
+ [0x1038]={
+ category="mc",
+ description="MYANMAR SIGN VISARGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1038,
+ },
+ [0x1039]={
+ category="mn",
+ combining=0x9,
+ description="MYANMAR SIGN VIRAMA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1039,
+ },
+ [0x103A]={
+ category="mn",
+ combining=0x9,
+ description="MYANMAR SIGN ASAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103A,
+ },
+ [0x103B]={
+ category="mc",
+ description="MYANMAR CONSONANT SIGN MEDIAL YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103B,
+ },
+ [0x103C]={
+ category="mc",
+ description="MYANMAR CONSONANT SIGN MEDIAL RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103C,
+ },
+ [0x103D]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MEDIAL WA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103D,
+ },
+ [0x103E]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MEDIAL HA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103E,
+ },
+ [0x103F]={
+ category="lo",
+ description="MYANMAR LETTER GREAT SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103F,
+ },
+ [0x1040]={
+ category="nd",
+ description="MYANMAR DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1040,
+ },
+ [0x1041]={
+ category="nd",
+ description="MYANMAR DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1041,
+ },
+ [0x1042]={
+ category="nd",
+ description="MYANMAR DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1042,
+ },
+ [0x1043]={
+ category="nd",
+ description="MYANMAR DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1043,
+ },
+ [0x1044]={
+ category="nd",
+ description="MYANMAR DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1044,
+ },
+ [0x1045]={
+ category="nd",
+ description="MYANMAR DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1045,
+ },
+ [0x1046]={
+ category="nd",
+ description="MYANMAR DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1046,
+ },
+ [0x1047]={
+ category="nd",
+ description="MYANMAR DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1047,
+ },
+ [0x1048]={
+ category="nd",
+ description="MYANMAR DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1048,
+ },
+ [0x1049]={
+ category="nd",
+ description="MYANMAR DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1049,
+ },
+ [0x104A]={
+ category="po",
+ description="MYANMAR SIGN LITTLE SECTION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x104A,
+ },
+ [0x104B]={
+ category="po",
+ description="MYANMAR SIGN SECTION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x104B,
+ },
+ [0x104C]={
+ category="po",
+ description="MYANMAR SYMBOL LOCATIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x104C,
+ },
+ [0x104D]={
+ category="po",
+ description="MYANMAR SYMBOL COMPLETED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x104D,
+ },
+ [0x104E]={
+ category="po",
+ description="MYANMAR SYMBOL AFOREMENTIONED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x104E,
+ },
+ [0x104F]={
+ category="po",
+ description="MYANMAR SYMBOL GENITIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x104F,
+ },
+ [0x1050]={
+ category="lo",
+ description="MYANMAR LETTER SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1050,
+ },
+ [0x1051]={
+ category="lo",
+ description="MYANMAR LETTER SSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1051,
+ },
+ [0x1052]={
+ category="lo",
+ description="MYANMAR LETTER VOCALIC R",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1052,
+ },
+ [0x1053]={
+ category="lo",
+ description="MYANMAR LETTER VOCALIC RR",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1053,
+ },
+ [0x1054]={
+ category="lo",
+ description="MYANMAR LETTER VOCALIC L",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1054,
+ },
+ [0x1055]={
+ category="lo",
+ description="MYANMAR LETTER VOCALIC LL",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1055,
+ },
+ [0x1056]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1056,
+ },
+ [0x1057]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1057,
+ },
+ [0x1058]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1058,
+ },
+ [0x1059]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1059,
+ },
+ [0x105A]={
+ category="lo",
+ description="MYANMAR LETTER MON NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105A,
+ },
+ [0x105B]={
+ category="lo",
+ description="MYANMAR LETTER MON JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105B,
+ },
+ [0x105C]={
+ category="lo",
+ description="MYANMAR LETTER MON BBA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105C,
+ },
+ [0x105D]={
+ category="lo",
+ description="MYANMAR LETTER MON BBE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105D,
+ },
+ [0x105E]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL NA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x105E,
+ },
+ [0x105F]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL MA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x105F,
+ },
+ [0x1060]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL LA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1060,
+ },
+ [0x1061]={
+ category="lo",
+ description="MYANMAR LETTER SGAW KAREN SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1061,
+ },
+ [0x1062]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SGAW KAREN EU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1062,
+ },
+ [0x1063]={
+ category="mc",
+ description="MYANMAR TONE MARK SGAW KAREN HATHI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1063,
+ },
+ [0x1064]={
+ category="mc",
+ description="MYANMAR TONE MARK SGAW KAREN KE PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1064,
+ },
+ [0x1065]={
+ category="lo",
+ description="MYANMAR LETTER WESTERN PWO KAREN THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1065,
+ },
+ [0x1066]={
+ category="lo",
+ description="MYANMAR LETTER WESTERN PWO KAREN PWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1066,
+ },
+ [0x1067]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN WESTERN PWO KAREN EU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1067,
+ },
+ [0x1068]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN WESTERN PWO KAREN UE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1068,
+ },
+ [0x1069]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-1",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1069,
+ },
+ [0x106A]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106A,
+ },
+ [0x106B]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106B,
+ },
+ [0x106C]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-4",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106C,
+ },
+ [0x106D]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106D,
+ },
+ [0x106E]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN NNA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106E,
+ },
+ [0x106F]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN YWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106F,
+ },
+ [0x1070]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN GHWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1070,
+ },
+ [0x1071]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN GEBA KAREN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1071,
+ },
+ [0x1072]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH OE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1072,
+ },
+ [0x1073]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1073,
+ },
+ [0x1074]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH EE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1074,
+ },
+ [0x1075]={
+ category="lo",
+ description="MYANMAR LETTER SHAN KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1075,
+ },
+ [0x1076]={
+ category="lo",
+ description="MYANMAR LETTER SHAN KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1076,
+ },
+ [0x1077]={
+ category="lo",
+ description="MYANMAR LETTER SHAN GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1077,
+ },
+ [0x1078]={
+ category="lo",
+ description="MYANMAR LETTER SHAN CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1078,
+ },
+ [0x1079]={
+ category="lo",
+ description="MYANMAR LETTER SHAN ZA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1079,
+ },
+ [0x107A]={
+ category="lo",
+ description="MYANMAR LETTER SHAN NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107A,
+ },
+ [0x107B]={
+ category="lo",
+ description="MYANMAR LETTER SHAN DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107B,
+ },
+ [0x107C]={
+ category="lo",
+ description="MYANMAR LETTER SHAN NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107C,
+ },
+ [0x107D]={
+ category="lo",
+ description="MYANMAR LETTER SHAN PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107D,
+ },
+ [0x107E]={
+ category="lo",
+ description="MYANMAR LETTER SHAN FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107E,
+ },
+ [0x107F]={
+ category="lo",
+ description="MYANMAR LETTER SHAN BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107F,
+ },
+ [0x1080]={
+ category="lo",
+ description="MYANMAR LETTER SHAN THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1080,
+ },
+ [0x1081]={
+ category="lo",
+ description="MYANMAR LETTER SHAN HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1081,
+ },
+ [0x1082]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN SHAN MEDIAL WA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1082,
+ },
+ [0x1083]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SHAN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1083,
+ },
+ [0x1084]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SHAN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1084,
+ },
+ [0x1085]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN SHAN E ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1085,
+ },
+ [0x1086]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN SHAN FINAL Y",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1086,
+ },
+ [0x1087]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1087,
+ },
+ [0x1088]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1088,
+ },
+ [0x1089]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1089,
+ },
+ [0x108A]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-6",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108A,
+ },
+ [0x108B]={
+ category="mc",
+ description="MYANMAR SIGN SHAN COUNCIL TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108B,
+ },
+ [0x108C]={
+ category="mc",
+ description="MYANMAR SIGN SHAN COUNCIL TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108C,
+ },
+ [0x108D]={
+ category="mn",
+ combining=0xDC,
+ description="MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x108D,
+ },
+ [0x108E]={
+ category="lo",
+ description="MYANMAR LETTER RUMAI PALAUNG FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108E,
+ },
+ [0x108F]={
+ category="mc",
+ description="MYANMAR SIGN RUMAI PALAUNG TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108F,
+ },
+ [0x1090]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1090,
+ },
+ [0x1091]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1091,
+ },
+ [0x1092]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1092,
+ },
+ [0x1093]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1093,
+ },
+ [0x1094]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1094,
+ },
+ [0x1095]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1095,
+ },
+ [0x1096]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1096,
+ },
+ [0x1097]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1097,
+ },
+ [0x1098]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1098,
+ },
+ [0x1099]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1099,
+ },
+ [0x109A]={
+ category="mc",
+ description="MYANMAR SIGN KHAMTI TONE-1",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109A,
+ },
+ [0x109B]={
+ category="mc",
+ description="MYANMAR SIGN KHAMTI TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109B,
+ },
+ [0x109C]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN AITON A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109C,
+ },
+ [0x109D]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN AITON AI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x109D,
+ },
+ [0x109E]={
+ category="so",
+ description="MYANMAR SYMBOL SHAN ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109E,
+ },
+ [0x109F]={
+ category="so",
+ description="MYANMAR SYMBOL SHAN EXCLAMATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109F,
+ },
+ [0x10A0]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER AN",
+ direction="l",
+ lccode=0x2D00,
+ linebreak="al",
+ unicodeslot=0x10A0,
+ },
+ [0x10A1]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER BAN",
+ direction="l",
+ lccode=0x2D01,
+ linebreak="al",
+ unicodeslot=0x10A1,
+ },
+ [0x10A2]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER GAN",
+ direction="l",
+ lccode=0x2D02,
+ linebreak="al",
+ unicodeslot=0x10A2,
+ },
+ [0x10A3]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER DON",
+ direction="l",
+ lccode=0x2D03,
+ linebreak="al",
+ unicodeslot=0x10A3,
+ },
+ [0x10A4]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER EN",
+ direction="l",
+ lccode=0x2D04,
+ linebreak="al",
+ unicodeslot=0x10A4,
+ },
+ [0x10A5]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER VIN",
+ direction="l",
+ lccode=0x2D05,
+ linebreak="al",
+ unicodeslot=0x10A5,
+ },
+ [0x10A6]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER ZEN",
+ direction="l",
+ lccode=0x2D06,
+ linebreak="al",
+ unicodeslot=0x10A6,
+ },
+ [0x10A7]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER TAN",
+ direction="l",
+ lccode=0x2D07,
+ linebreak="al",
+ unicodeslot=0x10A7,
+ },
+ [0x10A8]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER IN",
+ direction="l",
+ lccode=0x2D08,
+ linebreak="al",
+ unicodeslot=0x10A8,
+ },
+ [0x10A9]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER KAN",
+ direction="l",
+ lccode=0x2D09,
+ linebreak="al",
+ unicodeslot=0x10A9,
+ },
+ [0x10AA]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER LAS",
+ direction="l",
+ lccode=0x2D0A,
+ linebreak="al",
+ unicodeslot=0x10AA,
+ },
+ [0x10AB]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER MAN",
+ direction="l",
+ lccode=0x2D0B,
+ linebreak="al",
+ unicodeslot=0x10AB,
+ },
+ [0x10AC]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER NAR",
+ direction="l",
+ lccode=0x2D0C,
+ linebreak="al",
+ unicodeslot=0x10AC,
+ },
+ [0x10AD]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER ON",
+ direction="l",
+ lccode=0x2D0D,
+ linebreak="al",
+ unicodeslot=0x10AD,
+ },
+ [0x10AE]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER PAR",
+ direction="l",
+ lccode=0x2D0E,
+ linebreak="al",
+ unicodeslot=0x10AE,
+ },
+ [0x10AF]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER ZHAR",
+ direction="l",
+ lccode=0x2D0F,
+ linebreak="al",
+ unicodeslot=0x10AF,
+ },
+ [0x10B0]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER RAE",
+ direction="l",
+ lccode=0x2D10,
+ linebreak="al",
+ unicodeslot=0x10B0,
+ },
+ [0x10B1]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER SAN",
+ direction="l",
+ lccode=0x2D11,
+ linebreak="al",
+ unicodeslot=0x10B1,
+ },
+ [0x10B2]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER TAR",
+ direction="l",
+ lccode=0x2D12,
+ linebreak="al",
+ unicodeslot=0x10B2,
+ },
+ [0x10B3]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER UN",
+ direction="l",
+ lccode=0x2D13,
+ linebreak="al",
+ unicodeslot=0x10B3,
+ },
+ [0x10B4]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER PHAR",
+ direction="l",
+ lccode=0x2D14,
+ linebreak="al",
+ unicodeslot=0x10B4,
+ },
+ [0x10B5]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER KHAR",
+ direction="l",
+ lccode=0x2D15,
+ linebreak="al",
+ unicodeslot=0x10B5,
+ },
+ [0x10B6]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER GHAN",
+ direction="l",
+ lccode=0x2D16,
+ linebreak="al",
+ unicodeslot=0x10B6,
+ },
+ [0x10B7]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER QAR",
+ direction="l",
+ lccode=0x2D17,
+ linebreak="al",
+ unicodeslot=0x10B7,
+ },
+ [0x10B8]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER SHIN",
+ direction="l",
+ lccode=0x2D18,
+ linebreak="al",
+ unicodeslot=0x10B8,
+ },
+ [0x10B9]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER CHIN",
+ direction="l",
+ lccode=0x2D19,
+ linebreak="al",
+ unicodeslot=0x10B9,
+ },
+ [0x10BA]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER CAN",
+ direction="l",
+ lccode=0x2D1A,
+ linebreak="al",
+ unicodeslot=0x10BA,
+ },
+ [0x10BB]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER JIL",
+ direction="l",
+ lccode=0x2D1B,
+ linebreak="al",
+ unicodeslot=0x10BB,
+ },
+ [0x10BC]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER CIL",
+ direction="l",
+ lccode=0x2D1C,
+ linebreak="al",
+ unicodeslot=0x10BC,
+ },
+ [0x10BD]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER CHAR",
+ direction="l",
+ lccode=0x2D1D,
+ linebreak="al",
+ unicodeslot=0x10BD,
+ },
+ [0x10BE]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER XAN",
+ direction="l",
+ lccode=0x2D1E,
+ linebreak="al",
+ unicodeslot=0x10BE,
+ },
+ [0x10BF]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER JHAN",
+ direction="l",
+ lccode=0x2D1F,
+ linebreak="al",
+ unicodeslot=0x10BF,
+ },
+ [0x10C0]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER HAE",
+ direction="l",
+ lccode=0x2D20,
+ linebreak="al",
+ unicodeslot=0x10C0,
+ },
+ [0x10C1]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER HE",
+ direction="l",
+ lccode=0x2D21,
+ linebreak="al",
+ unicodeslot=0x10C1,
+ },
+ [0x10C2]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER HIE",
+ direction="l",
+ lccode=0x2D22,
+ linebreak="al",
+ unicodeslot=0x10C2,
+ },
+ [0x10C3]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER WE",
+ direction="l",
+ lccode=0x2D23,
+ linebreak="al",
+ unicodeslot=0x10C3,
+ },
+ [0x10C4]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER HAR",
+ direction="l",
+ lccode=0x2D24,
+ linebreak="al",
+ unicodeslot=0x10C4,
+ },
+ [0x10C5]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER HOE",
+ direction="l",
+ lccode=0x2D25,
+ linebreak="al",
+ unicodeslot=0x10C5,
+ },
+ [0x10C7]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10C7,
+ },
+ [0x10CD]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10CD,
+ },
+ [0x10D0]={
+ category="lo",
+ description="GEORGIAN LETTER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D0,
+ },
+ [0x10D1]={
+ category="lo",
+ description="GEORGIAN LETTER BAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D1,
+ },
+ [0x10D2]={
+ category="lo",
+ description="GEORGIAN LETTER GAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D2,
+ },
+ [0x10D3]={
+ category="lo",
+ description="GEORGIAN LETTER DON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D3,
+ },
+ [0x10D4]={
+ category="lo",
+ description="GEORGIAN LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D4,
+ },
+ [0x10D5]={
+ category="lo",
+ description="GEORGIAN LETTER VIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D5,
+ },
+ [0x10D6]={
+ category="lo",
+ description="GEORGIAN LETTER ZEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D6,
+ },
+ [0x10D7]={
+ category="lo",
+ description="GEORGIAN LETTER TAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D7,
+ },
+ [0x10D8]={
+ category="lo",
+ description="GEORGIAN LETTER IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D8,
+ },
+ [0x10D9]={
+ category="lo",
+ description="GEORGIAN LETTER KAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10D9,
+ },
+ [0x10DA]={
+ category="lo",
+ description="GEORGIAN LETTER LAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DA,
+ },
+ [0x10DB]={
+ category="lo",
+ description="GEORGIAN LETTER MAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DB,
+ },
+ [0x10DC]={
+ category="lo",
+ description="GEORGIAN LETTER NAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DC,
+ },
+ [0x10DD]={
+ category="lo",
+ description="GEORGIAN LETTER ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DD,
+ },
+ [0x10DE]={
+ category="lo",
+ description="GEORGIAN LETTER PAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DE,
+ },
+ [0x10DF]={
+ category="lo",
+ description="GEORGIAN LETTER ZHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10DF,
+ },
+ [0x10E0]={
+ category="lo",
+ description="GEORGIAN LETTER RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E0,
+ },
+ [0x10E1]={
+ category="lo",
+ description="GEORGIAN LETTER SAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E1,
+ },
+ [0x10E2]={
+ category="lo",
+ description="GEORGIAN LETTER TAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E2,
+ },
+ [0x10E3]={
+ category="lo",
+ description="GEORGIAN LETTER UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E3,
+ },
+ [0x10E4]={
+ category="lo",
+ description="GEORGIAN LETTER PHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E4,
+ },
+ [0x10E5]={
+ category="lo",
+ description="GEORGIAN LETTER KHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E5,
+ },
+ [0x10E6]={
+ category="lo",
+ description="GEORGIAN LETTER GHAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E6,
+ },
+ [0x10E7]={
+ category="lo",
+ description="GEORGIAN LETTER QAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E7,
+ },
+ [0x10E8]={
+ category="lo",
+ description="GEORGIAN LETTER SHIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E8,
+ },
+ [0x10E9]={
+ category="lo",
+ description="GEORGIAN LETTER CHIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10E9,
+ },
+ [0x10EA]={
+ category="lo",
+ description="GEORGIAN LETTER CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10EA,
+ },
+ [0x10EB]={
+ category="lo",
+ description="GEORGIAN LETTER JIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10EB,
+ },
+ [0x10EC]={
+ category="lo",
+ description="GEORGIAN LETTER CIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10EC,
+ },
+ [0x10ED]={
+ category="lo",
+ description="GEORGIAN LETTER CHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10ED,
+ },
+ [0x10EE]={
+ category="lo",
+ description="GEORGIAN LETTER XAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10EE,
+ },
+ [0x10EF]={
+ category="lo",
+ description="GEORGIAN LETTER JHAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10EF,
+ },
+ [0x10F0]={
+ category="lo",
+ description="GEORGIAN LETTER HAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F0,
+ },
+ [0x10F1]={
+ category="lo",
+ description="GEORGIAN LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F1,
+ },
+ [0x10F2]={
+ category="lo",
+ description="GEORGIAN LETTER HIE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F2,
+ },
+ [0x10F3]={
+ category="lo",
+ description="GEORGIAN LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F3,
+ },
+ [0x10F4]={
+ category="lo",
+ description="GEORGIAN LETTER HAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F4,
+ },
+ [0x10F5]={
+ category="lo",
+ description="GEORGIAN LETTER HOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F5,
+ },
+ [0x10F6]={
+ category="lo",
+ description="GEORGIAN LETTER FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F6,
+ },
+ [0x10F7]={
+ category="lo",
+ description="GEORGIAN LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F7,
+ },
+ [0x10F8]={
+ category="lo",
+ description="GEORGIAN LETTER ELIFI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F8,
+ },
+ [0x10F9]={
+ category="lo",
+ description="GEORGIAN LETTER TURNED GAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10F9,
+ },
+ [0x10FA]={
+ category="lo",
+ description="GEORGIAN LETTER AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FA,
+ },
+ [0x10FB]={
+ category="po",
+ description="GEORGIAN PARAGRAPH SEPARATOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FB,
+ },
+ [0x10FC]={
+ category="lm",
+ description="MODIFIER LETTER GEORGIAN NAR",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x10DC },
+ unicodeslot=0x10FC,
+ },
+ [0x10FD]={
+ category="lo",
+ description="GEORGIAN LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FD,
+ },
+ [0x10FE]={
+ category="lo",
+ description="GEORGIAN LETTER HARD SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FE,
+ },
+ [0x10FF]={
+ category="lo",
+ description="GEORGIAN LETTER LABIAL SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FF,
+ },
+ [0x1100]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1100,
+ },
+ [0x1101]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGKIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1101,
+ },
+ [0x1102]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1102,
+ },
+ [0x1103]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1103,
+ },
+ [0x1104]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGTIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1104,
+ },
+ [0x1105]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1105,
+ },
+ [0x1106]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1106,
+ },
+ [0x1107]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1107,
+ },
+ [0x1108]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1108,
+ },
+ [0x1109]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1109,
+ },
+ [0x110A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110A,
+ },
+ [0x110B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110B,
+ },
+ [0x110C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110C,
+ },
+ [0x110D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGCIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110D,
+ },
+ [0x110E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110E,
+ },
+ [0x110F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x110F,
+ },
+ [0x1110]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1110,
+ },
+ [0x1111]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PHIEUPH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1111,
+ },
+ [0x1112]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1112,
+ },
+ [0x1113]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1113,
+ },
+ [0x1114]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGNIEUN",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1114,
+ },
+ [0x1115]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1115,
+ },
+ [0x1116]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1116,
+ },
+ [0x1117]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1117,
+ },
+ [0x1118]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-NIEUN",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1118,
+ },
+ [0x1119]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGRIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1119,
+ },
+ [0x111A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111A,
+ },
+ [0x111B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KAPYEOUNRIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111B,
+ },
+ [0x111C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111C,
+ },
+ [0x111D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KAPYEOUNMIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111D,
+ },
+ [0x111E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111E,
+ },
+ [0x111F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-NIEUN",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x111F,
+ },
+ [0x1120]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1120,
+ },
+ [0x1121]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1121,
+ },
+ [0x1122]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1122,
+ },
+ [0x1123]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1123,
+ },
+ [0x1124]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1124,
+ },
+ [0x1125]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SSANGSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1125,
+ },
+ [0x1126]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1126,
+ },
+ [0x1127]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1127,
+ },
+ [0x1128]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-CHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1128,
+ },
+ [0x1129]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1129,
+ },
+ [0x112A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-PHIEUPH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112A,
+ },
+ [0x112B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112B,
+ },
+ [0x112C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KAPYEOUNSSANGPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112C,
+ },
+ [0x112D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112D,
+ },
+ [0x112E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-NIEUN",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112E,
+ },
+ [0x112F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x112F,
+ },
+ [0x1130]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1130,
+ },
+ [0x1131]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1131,
+ },
+ [0x1132]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1132,
+ },
+ [0x1133]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-PIEUP-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1133,
+ },
+ [0x1134]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-SSANGSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1134,
+ },
+ [0x1135]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-IEUNG",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1135,
+ },
+ [0x1136]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1136,
+ },
+ [0x1137]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-CHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1137,
+ },
+ [0x1138]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1138,
+ },
+ [0x1139]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1139,
+ },
+ [0x113A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-PHIEUPH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113A,
+ },
+ [0x113B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SIOS-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113B,
+ },
+ [0x113C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHITUEUMSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113C,
+ },
+ [0x113D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHITUEUMSSANGSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113D,
+ },
+ [0x113E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CEONGCHIEUMSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113E,
+ },
+ [0x113F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x113F,
+ },
+ [0x1140]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PANSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1140,
+ },
+ [0x1141]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1141,
+ },
+ [0x1142]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1142,
+ },
+ [0x1143]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1143,
+ },
+ [0x1144]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1144,
+ },
+ [0x1145]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1145,
+ },
+ [0x1146]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-PANSIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1146,
+ },
+ [0x1147]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGIEUNG",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1147,
+ },
+ [0x1148]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1148,
+ },
+ [0x1149]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-CHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1149,
+ },
+ [0x114A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114A,
+ },
+ [0x114B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-PHIEUPH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114B,
+ },
+ [0x114C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG YESIEUNG",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114C,
+ },
+ [0x114D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CIEUC-IEUNG",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114D,
+ },
+ [0x114E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHITUEUMCIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114E,
+ },
+ [0x114F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHITUEUMSSANGCIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x114F,
+ },
+ [0x1150]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CEONGCHIEUMCIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1150,
+ },
+ [0x1151]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1151,
+ },
+ [0x1152]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHIEUCH-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1152,
+ },
+ [0x1153]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHIEUCH-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1153,
+ },
+ [0x1154]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CHITUEUMCHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1154,
+ },
+ [0x1155]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG CEONGCHIEUMCHIEUCH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1155,
+ },
+ [0x1156]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PHIEUPH-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1156,
+ },
+ [0x1157]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KAPYEOUNPHIEUPH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1157,
+ },
+ [0x1158]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGHIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1158,
+ },
+ [0x1159]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG YEORINHIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x1159,
+ },
+ [0x115A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KIYEOK-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115A,
+ },
+ [0x115B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115B,
+ },
+ [0x115C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115C,
+ },
+ [0x115D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115D,
+ },
+ [0x115E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115E,
+ },
+ [0x115F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG FILLER",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115F,
+ },
+ [0x1160]={
+ category="lo",
+ description="HANGUL JUNGSEONG FILLER",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1160,
+ },
+ [0x1161]={
+ category="lo",
+ description="HANGUL JUNGSEONG A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1161,
+ },
+ [0x1162]={
+ category="lo",
+ description="HANGUL JUNGSEONG AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1162,
+ },
+ [0x1163]={
+ category="lo",
+ description="HANGUL JUNGSEONG YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1163,
+ },
+ [0x1164]={
+ category="lo",
+ description="HANGUL JUNGSEONG YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1164,
+ },
+ [0x1165]={
+ category="lo",
+ description="HANGUL JUNGSEONG EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1165,
+ },
+ [0x1166]={
+ category="lo",
+ description="HANGUL JUNGSEONG E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1166,
+ },
+ [0x1167]={
+ category="lo",
+ description="HANGUL JUNGSEONG YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1167,
+ },
+ [0x1168]={
+ category="lo",
+ description="HANGUL JUNGSEONG YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1168,
+ },
+ [0x1169]={
+ category="lo",
+ description="HANGUL JUNGSEONG O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1169,
+ },
+ [0x116A]={
+ category="lo",
+ description="HANGUL JUNGSEONG WA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116A,
+ },
+ [0x116B]={
+ category="lo",
+ description="HANGUL JUNGSEONG WAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116B,
+ },
+ [0x116C]={
+ category="lo",
+ description="HANGUL JUNGSEONG OE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116C,
+ },
+ [0x116D]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116D,
+ },
+ [0x116E]={
+ category="lo",
+ description="HANGUL JUNGSEONG U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116E,
+ },
+ [0x116F]={
+ category="lo",
+ description="HANGUL JUNGSEONG WEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x116F,
+ },
+ [0x1170]={
+ category="lo",
+ description="HANGUL JUNGSEONG WE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1170,
+ },
+ [0x1171]={
+ category="lo",
+ description="HANGUL JUNGSEONG WI",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1171,
+ },
+ [0x1172]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1172,
+ },
+ [0x1173]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1173,
+ },
+ [0x1174]={
+ category="lo",
+ description="HANGUL JUNGSEONG YI",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1174,
+ },
+ [0x1175]={
+ category="lo",
+ description="HANGUL JUNGSEONG I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1175,
+ },
+ [0x1176]={
+ category="lo",
+ description="HANGUL JUNGSEONG A-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1176,
+ },
+ [0x1177]={
+ category="lo",
+ description="HANGUL JUNGSEONG A-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1177,
+ },
+ [0x1178]={
+ category="lo",
+ description="HANGUL JUNGSEONG YA-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1178,
+ },
+ [0x1179]={
+ category="lo",
+ description="HANGUL JUNGSEONG YA-YO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1179,
+ },
+ [0x117A]={
+ category="lo",
+ description="HANGUL JUNGSEONG EO-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117A,
+ },
+ [0x117B]={
+ category="lo",
+ description="HANGUL JUNGSEONG EO-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117B,
+ },
+ [0x117C]={
+ category="lo",
+ description="HANGUL JUNGSEONG EO-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117C,
+ },
+ [0x117D]={
+ category="lo",
+ description="HANGUL JUNGSEONG YEO-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117D,
+ },
+ [0x117E]={
+ category="lo",
+ description="HANGUL JUNGSEONG YEO-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117E,
+ },
+ [0x117F]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x117F,
+ },
+ [0x1180]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1180,
+ },
+ [0x1181]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1181,
+ },
+ [0x1182]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1182,
+ },
+ [0x1183]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1183,
+ },
+ [0x1184]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1184,
+ },
+ [0x1185]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1185,
+ },
+ [0x1186]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1186,
+ },
+ [0x1187]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1187,
+ },
+ [0x1188]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1188,
+ },
+ [0x1189]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1189,
+ },
+ [0x118A]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118A,
+ },
+ [0x118B]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-EO-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118B,
+ },
+ [0x118C]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118C,
+ },
+ [0x118D]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118D,
+ },
+ [0x118E]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118E,
+ },
+ [0x118F]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x118F,
+ },
+ [0x1190]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1190,
+ },
+ [0x1191]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1191,
+ },
+ [0x1192]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1192,
+ },
+ [0x1193]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1193,
+ },
+ [0x1194]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1194,
+ },
+ [0x1195]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1195,
+ },
+ [0x1196]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1196,
+ },
+ [0x1197]={
+ category="lo",
+ description="HANGUL JUNGSEONG YI-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1197,
+ },
+ [0x1198]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1198,
+ },
+ [0x1199]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x1199,
+ },
+ [0x119A]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119A,
+ },
+ [0x119B]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119B,
+ },
+ [0x119C]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119C,
+ },
+ [0x119D]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-ARAEA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119D,
+ },
+ [0x119E]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119E,
+ },
+ [0x119F]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x119F,
+ },
+ [0x11A0]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A0,
+ },
+ [0x11A1]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A1,
+ },
+ [0x11A2]={
+ category="lo",
+ description="HANGUL JUNGSEONG SSANGARAEA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A2,
+ },
+ [0x11A3]={
+ category="lo",
+ description="HANGUL JUNGSEONG A-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A3,
+ },
+ [0x11A4]={
+ category="lo",
+ description="HANGUL JUNGSEONG YA-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A4,
+ },
+ [0x11A5]={
+ category="lo",
+ description="HANGUL JUNGSEONG YEO-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A5,
+ },
+ [0x11A6]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A6,
+ },
+ [0x11A7]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A7,
+ },
+ [0x11A8]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11A8,
+ },
+ [0x11A9]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGKIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11A9,
+ },
+ [0x11AA]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AA,
+ },
+ [0x11AB]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AB,
+ },
+ [0x11AC]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AC,
+ },
+ [0x11AD]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AD,
+ },
+ [0x11AE]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AE,
+ },
+ [0x11AF]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11AF,
+ },
+ [0x11B0]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B0,
+ },
+ [0x11B1]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B1,
+ },
+ [0x11B2]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B2,
+ },
+ [0x11B3]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B3,
+ },
+ [0x11B4]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B4,
+ },
+ [0x11B5]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B5,
+ },
+ [0x11B6]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B6,
+ },
+ [0x11B7]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B7,
+ },
+ [0x11B8]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B8,
+ },
+ [0x11B9]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11B9,
+ },
+ [0x11BA]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BA,
+ },
+ [0x11BB]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BB,
+ },
+ [0x11BC]={
+ category="lo",
+ description="HANGUL JONGSEONG IEUNG",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BC,
+ },
+ [0x11BD]={
+ category="lo",
+ description="HANGUL JONGSEONG CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BD,
+ },
+ [0x11BE]={
+ category="lo",
+ description="HANGUL JONGSEONG CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BE,
+ },
+ [0x11BF]={
+ category="lo",
+ description="HANGUL JONGSEONG KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11BF,
+ },
+ [0x11C0]={
+ category="lo",
+ description="HANGUL JONGSEONG THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C0,
+ },
+ [0x11C1]={
+ category="lo",
+ description="HANGUL JONGSEONG PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C1,
+ },
+ [0x11C2]={
+ category="lo",
+ description="HANGUL JONGSEONG HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C2,
+ },
+ [0x11C3]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C3,
+ },
+ [0x11C4]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C4,
+ },
+ [0x11C5]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C5,
+ },
+ [0x11C6]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C6,
+ },
+ [0x11C7]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C7,
+ },
+ [0x11C8]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C8,
+ },
+ [0x11C9]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11C9,
+ },
+ [0x11CA]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CA,
+ },
+ [0x11CB]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CB,
+ },
+ [0x11CC]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-KIYEOK-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CC,
+ },
+ [0x11CD]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CD,
+ },
+ [0x11CE]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CE,
+ },
+ [0x11CF]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11CF,
+ },
+ [0x11D0]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGRIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D0,
+ },
+ [0x11D1]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D1,
+ },
+ [0x11D2]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-MIEUM-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D2,
+ },
+ [0x11D3]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D3,
+ },
+ [0x11D4]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D4,
+ },
+ [0x11D5]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D5,
+ },
+ [0x11D6]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-SSANGSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D6,
+ },
+ [0x11D7]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D7,
+ },
+ [0x11D8]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D8,
+ },
+ [0x11D9]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-YEORINHIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11D9,
+ },
+ [0x11DA]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DA,
+ },
+ [0x11DB]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DB,
+ },
+ [0x11DC]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DC,
+ },
+ [0x11DD]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DD,
+ },
+ [0x11DE]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-SSANGSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DE,
+ },
+ [0x11DF]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11DF,
+ },
+ [0x11E0]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E0,
+ },
+ [0x11E1]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E1,
+ },
+ [0x11E2]={
+ category="lo",
+ description="HANGUL JONGSEONG KAPYEOUNMIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E2,
+ },
+ [0x11E3]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E3,
+ },
+ [0x11E4]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E4,
+ },
+ [0x11E5]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E5,
+ },
+ [0x11E6]={
+ category="lo",
+ description="HANGUL JONGSEONG KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E6,
+ },
+ [0x11E7]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E7,
+ },
+ [0x11E8]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E8,
+ },
+ [0x11E9]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11E9,
+ },
+ [0x11EA]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11EA,
+ },
+ [0x11EB]={
+ category="lo",
+ description="HANGUL JONGSEONG PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11EB,
+ },
+ [0x11EC]={
+ category="lo",
+ description="HANGUL JONGSEONG IEUNG-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11EC,
+ },
+ [0x11ED]={
+ category="lo",
+ description="HANGUL JONGSEONG IEUNG-SSANGKIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11ED,
+ },
+ [0x11EE]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGIEUNG",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11EE,
+ },
+ [0x11EF]={
+ category="lo",
+ description="HANGUL JONGSEONG IEUNG-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11EF,
+ },
+ [0x11F0]={
+ category="lo",
+ description="HANGUL JONGSEONG YESIEUNG",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F0,
+ },
+ [0x11F1]={
+ category="lo",
+ description="HANGUL JONGSEONG YESIEUNG-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F1,
+ },
+ [0x11F2]={
+ category="lo",
+ description="HANGUL JONGSEONG YESIEUNG-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F2,
+ },
+ [0x11F3]={
+ category="lo",
+ description="HANGUL JONGSEONG PHIEUPH-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F3,
+ },
+ [0x11F4]={
+ category="lo",
+ description="HANGUL JONGSEONG KAPYEOUNPHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F4,
+ },
+ [0x11F5]={
+ category="lo",
+ description="HANGUL JONGSEONG HIEUH-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F5,
+ },
+ [0x11F6]={
+ category="lo",
+ description="HANGUL JONGSEONG HIEUH-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F6,
+ },
+ [0x11F7]={
+ category="lo",
+ description="HANGUL JONGSEONG HIEUH-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F7,
+ },
+ [0x11F8]={
+ category="lo",
+ description="HANGUL JONGSEONG HIEUH-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F8,
+ },
+ [0x11F9]={
+ category="lo",
+ description="HANGUL JONGSEONG YEORINHIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11F9,
+ },
+ [0x11FA]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FA,
+ },
+ [0x11FB]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FB,
+ },
+ [0x11FC]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FC,
+ },
+ [0x11FD]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FD,
+ },
+ [0x11FE]={
+ category="lo",
+ description="HANGUL JONGSEONG KIYEOK-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FE,
+ },
+ [0x11FF]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGNIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FF,
+ },
+ [0x1200]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200,
+ },
+ [0x1201]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201,
+ },
+ [0x1202]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202,
+ },
+ [0x1203]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203,
+ },
+ [0x1204]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204,
+ },
+ [0x1205]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205,
+ },
+ [0x1206]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206,
+ },
+ [0x1207]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207,
+ },
+ [0x1208]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208,
+ },
+ [0x1209]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209,
+ },
+ [0x120A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A,
+ },
+ [0x120B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B,
+ },
+ [0x120C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C,
+ },
+ [0x120D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D,
+ },
+ [0x120E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E,
+ },
+ [0x120F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F,
+ },
+ [0x1210]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210,
+ },
+ [0x1211]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211,
+ },
+ [0x1212]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212,
+ },
+ [0x1213]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213,
+ },
+ [0x1214]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214,
+ },
+ [0x1215]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215,
+ },
+ [0x1216]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216,
+ },
+ [0x1217]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE HHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217,
+ },
+ [0x1218]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218,
+ },
+ [0x1219]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219,
+ },
+ [0x121A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A,
+ },
+ [0x121B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B,
+ },
+ [0x121C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C,
+ },
+ [0x121D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D,
+ },
+ [0x121E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E,
+ },
+ [0x121F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F,
+ },
+ [0x1220]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220,
+ },
+ [0x1221]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221,
+ },
+ [0x1222]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222,
+ },
+ [0x1223]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223,
+ },
+ [0x1224]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224,
+ },
+ [0x1225]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225,
+ },
+ [0x1226]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226,
+ },
+ [0x1227]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SZWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227,
+ },
+ [0x1228]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228,
+ },
+ [0x1229]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229,
+ },
+ [0x122A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A,
+ },
+ [0x122B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B,
+ },
+ [0x122C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C,
+ },
+ [0x122D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D,
+ },
+ [0x122E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E,
+ },
+ [0x122F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F,
+ },
+ [0x1230]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230,
+ },
+ [0x1231]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231,
+ },
+ [0x1232]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232,
+ },
+ [0x1233]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233,
+ },
+ [0x1234]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234,
+ },
+ [0x1235]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235,
+ },
+ [0x1236]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236,
+ },
+ [0x1237]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237,
+ },
+ [0x1238]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238,
+ },
+ [0x1239]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1239,
+ },
+ [0x123A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123A,
+ },
+ [0x123B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123B,
+ },
+ [0x123C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123C,
+ },
+ [0x123D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123D,
+ },
+ [0x123E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123E,
+ },
+ [0x123F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x123F,
+ },
+ [0x1240]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240,
+ },
+ [0x1241]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241,
+ },
+ [0x1242]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242,
+ },
+ [0x1243]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243,
+ },
+ [0x1244]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244,
+ },
+ [0x1245]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245,
+ },
+ [0x1246]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246,
+ },
+ [0x1247]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1247,
+ },
+ [0x1248]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248,
+ },
+ [0x124A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A,
+ },
+ [0x124B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B,
+ },
+ [0x124C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C,
+ },
+ [0x124D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D,
+ },
+ [0x1250]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250,
+ },
+ [0x1251]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251,
+ },
+ [0x1252]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252,
+ },
+ [0x1253]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253,
+ },
+ [0x1254]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1254,
+ },
+ [0x1255]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1255,
+ },
+ [0x1256]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1256,
+ },
+ [0x1258]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1258,
+ },
+ [0x125A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x125A,
+ },
+ [0x125B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x125B,
+ },
+ [0x125C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x125C,
+ },
+ [0x125D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x125D,
+ },
+ [0x1260]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1260,
+ },
+ [0x1261]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1261,
+ },
+ [0x1262]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1262,
+ },
+ [0x1263]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1263,
+ },
+ [0x1264]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1264,
+ },
+ [0x1265]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1265,
+ },
+ [0x1266]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1266,
+ },
+ [0x1267]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1267,
+ },
+ [0x1268]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1268,
+ },
+ [0x1269]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1269,
+ },
+ [0x126A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126A,
+ },
+ [0x126B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126B,
+ },
+ [0x126C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126C,
+ },
+ [0x126D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126D,
+ },
+ [0x126E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126E,
+ },
+ [0x126F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE VWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x126F,
+ },
+ [0x1270]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1270,
+ },
+ [0x1271]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1271,
+ },
+ [0x1272]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1272,
+ },
+ [0x1273]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1273,
+ },
+ [0x1274]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1274,
+ },
+ [0x1275]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1275,
+ },
+ [0x1276]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1276,
+ },
+ [0x1277]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1277,
+ },
+ [0x1278]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1278,
+ },
+ [0x1279]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1279,
+ },
+ [0x127A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127A,
+ },
+ [0x127B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127B,
+ },
+ [0x127C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127C,
+ },
+ [0x127D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127D,
+ },
+ [0x127E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127E,
+ },
+ [0x127F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x127F,
+ },
+ [0x1280]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1280,
+ },
+ [0x1281]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1281,
+ },
+ [0x1282]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1282,
+ },
+ [0x1283]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1283,
+ },
+ [0x1284]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1284,
+ },
+ [0x1285]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1285,
+ },
+ [0x1286]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1286,
+ },
+ [0x1287]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1287,
+ },
+ [0x1288]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1288,
+ },
+ [0x128A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x128A,
+ },
+ [0x128B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x128B,
+ },
+ [0x128C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x128C,
+ },
+ [0x128D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x128D,
+ },
+ [0x1290]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1290,
+ },
+ [0x1291]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1291,
+ },
+ [0x1292]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1292,
+ },
+ [0x1293]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1293,
+ },
+ [0x1294]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1294,
+ },
+ [0x1295]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1295,
+ },
+ [0x1296]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1296,
+ },
+ [0x1297]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1297,
+ },
+ [0x1298]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1298,
+ },
+ [0x1299]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1299,
+ },
+ [0x129A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129A,
+ },
+ [0x129B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129B,
+ },
+ [0x129C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129C,
+ },
+ [0x129D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129D,
+ },
+ [0x129E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129E,
+ },
+ [0x129F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x129F,
+ },
+ [0x12A0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A0,
+ },
+ [0x12A1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A1,
+ },
+ [0x12A2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A2,
+ },
+ [0x12A3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A3,
+ },
+ [0x12A4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A4,
+ },
+ [0x12A5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A5,
+ },
+ [0x12A6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A6,
+ },
+ [0x12A7]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A7,
+ },
+ [0x12A8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A8,
+ },
+ [0x12A9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12A9,
+ },
+ [0x12AA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AA,
+ },
+ [0x12AB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AB,
+ },
+ [0x12AC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AC,
+ },
+ [0x12AD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AD,
+ },
+ [0x12AE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AE,
+ },
+ [0x12AF]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12AF,
+ },
+ [0x12B0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B0,
+ },
+ [0x12B2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B2,
+ },
+ [0x12B3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B3,
+ },
+ [0x12B4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B4,
+ },
+ [0x12B5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B5,
+ },
+ [0x12B8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B8,
+ },
+ [0x12B9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12B9,
+ },
+ [0x12BA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12BA,
+ },
+ [0x12BB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12BB,
+ },
+ [0x12BC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12BC,
+ },
+ [0x12BD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12BD,
+ },
+ [0x12BE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12BE,
+ },
+ [0x12C0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C0,
+ },
+ [0x12C2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C2,
+ },
+ [0x12C3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C3,
+ },
+ [0x12C4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C4,
+ },
+ [0x12C5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KXWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C5,
+ },
+ [0x12C8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C8,
+ },
+ [0x12C9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12C9,
+ },
+ [0x12CA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CA,
+ },
+ [0x12CB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CB,
+ },
+ [0x12CC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CC,
+ },
+ [0x12CD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CD,
+ },
+ [0x12CE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CE,
+ },
+ [0x12CF]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE WOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12CF,
+ },
+ [0x12D0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D0,
+ },
+ [0x12D1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D1,
+ },
+ [0x12D2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D2,
+ },
+ [0x12D3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D3,
+ },
+ [0x12D4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D4,
+ },
+ [0x12D5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D5,
+ },
+ [0x12D6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHARYNGEAL O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D6,
+ },
+ [0x12D8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D8,
+ },
+ [0x12D9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12D9,
+ },
+ [0x12DA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DA,
+ },
+ [0x12DB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DB,
+ },
+ [0x12DC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DC,
+ },
+ [0x12DD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DD,
+ },
+ [0x12DE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DE,
+ },
+ [0x12DF]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12DF,
+ },
+ [0x12E0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E0,
+ },
+ [0x12E1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E1,
+ },
+ [0x12E2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E2,
+ },
+ [0x12E3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E3,
+ },
+ [0x12E4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E4,
+ },
+ [0x12E5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E5,
+ },
+ [0x12E6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E6,
+ },
+ [0x12E7]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E7,
+ },
+ [0x12E8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E8,
+ },
+ [0x12E9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12E9,
+ },
+ [0x12EA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12EA,
+ },
+ [0x12EB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12EB,
+ },
+ [0x12EC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12EC,
+ },
+ [0x12ED]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12ED,
+ },
+ [0x12EE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12EE,
+ },
+ [0x12EF]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE YOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12EF,
+ },
+ [0x12F0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F0,
+ },
+ [0x12F1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F1,
+ },
+ [0x12F2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F2,
+ },
+ [0x12F3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F3,
+ },
+ [0x12F4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F4,
+ },
+ [0x12F5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F5,
+ },
+ [0x12F6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F6,
+ },
+ [0x12F7]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F7,
+ },
+ [0x12F8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F8,
+ },
+ [0x12F9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12F9,
+ },
+ [0x12FA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FA,
+ },
+ [0x12FB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FB,
+ },
+ [0x12FC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FC,
+ },
+ [0x12FD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FD,
+ },
+ [0x12FE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FE,
+ },
+ [0x12FF]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12FF,
+ },
+ [0x1300]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300,
+ },
+ [0x1301]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301,
+ },
+ [0x1302]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302,
+ },
+ [0x1303]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303,
+ },
+ [0x1304]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304,
+ },
+ [0x1305]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305,
+ },
+ [0x1306]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306,
+ },
+ [0x1307]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307,
+ },
+ [0x1308]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308,
+ },
+ [0x1309]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309,
+ },
+ [0x130A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A,
+ },
+ [0x130B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B,
+ },
+ [0x130C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C,
+ },
+ [0x130D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D,
+ },
+ [0x130E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E,
+ },
+ [0x130F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F,
+ },
+ [0x1310]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310,
+ },
+ [0x1312]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312,
+ },
+ [0x1313]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313,
+ },
+ [0x1314]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314,
+ },
+ [0x1315]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315,
+ },
+ [0x1318]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318,
+ },
+ [0x1319]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319,
+ },
+ [0x131A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A,
+ },
+ [0x131B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B,
+ },
+ [0x131C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C,
+ },
+ [0x131D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D,
+ },
+ [0x131E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E,
+ },
+ [0x131F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F,
+ },
+ [0x1320]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320,
+ },
+ [0x1321]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321,
+ },
+ [0x1322]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322,
+ },
+ [0x1323]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323,
+ },
+ [0x1324]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324,
+ },
+ [0x1325]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1325,
+ },
+ [0x1326]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326,
+ },
+ [0x1327]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327,
+ },
+ [0x1328]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328,
+ },
+ [0x1329]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329,
+ },
+ [0x132A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A,
+ },
+ [0x132B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B,
+ },
+ [0x132C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C,
+ },
+ [0x132D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D,
+ },
+ [0x132E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E,
+ },
+ [0x132F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F,
+ },
+ [0x1330]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330,
+ },
+ [0x1331]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331,
+ },
+ [0x1332]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332,
+ },
+ [0x1333]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333,
+ },
+ [0x1334]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334,
+ },
+ [0x1335]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335,
+ },
+ [0x1336]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336,
+ },
+ [0x1337]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337,
+ },
+ [0x1338]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338,
+ },
+ [0x1339]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339,
+ },
+ [0x133A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A,
+ },
+ [0x133B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B,
+ },
+ [0x133C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C,
+ },
+ [0x133D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D,
+ },
+ [0x133E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E,
+ },
+ [0x133F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TSWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F,
+ },
+ [0x1340]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340,
+ },
+ [0x1341]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341,
+ },
+ [0x1342]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342,
+ },
+ [0x1343]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1343,
+ },
+ [0x1344]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1344,
+ },
+ [0x1345]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1345,
+ },
+ [0x1346]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1346,
+ },
+ [0x1347]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TZOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1347,
+ },
+ [0x1348]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1348,
+ },
+ [0x1349]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1349,
+ },
+ [0x134A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134A,
+ },
+ [0x134B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134B,
+ },
+ [0x134C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134C,
+ },
+ [0x134D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134D,
+ },
+ [0x134E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134E,
+ },
+ [0x134F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x134F,
+ },
+ [0x1350]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1350,
+ },
+ [0x1351]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1351,
+ },
+ [0x1352]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1352,
+ },
+ [0x1353]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1353,
+ },
+ [0x1354]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1354,
+ },
+ [0x1355]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1355,
+ },
+ [0x1356]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1356,
+ },
+ [0x1357]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1357,
+ },
+ [0x1358]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE RYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1358,
+ },
+ [0x1359]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1359,
+ },
+ [0x135A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x135A,
+ },
+ [0x135D]={
+ category="mn",
+ combining=0xE6,
+ description="ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x135D,
+ },
+ [0x135E]={
+ category="mn",
+ combining=0xE6,
+ description="ETHIOPIC COMBINING VOWEL LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x135E,
+ },
+ [0x135F]={
+ category="mn",
+ combining=0xE6,
+ description="ETHIOPIC COMBINING GEMINATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x135F,
+ },
+ [0x1360]={
+ category="so",
+ description="ETHIOPIC SECTION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1360,
+ },
+ [0x1361]={
+ category="po",
+ description="ETHIOPIC WORDSPACE",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1361,
+ },
+ [0x1362]={
+ category="po",
+ description="ETHIOPIC FULL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1362,
+ },
+ [0x1363]={
+ category="po",
+ description="ETHIOPIC COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1363,
+ },
+ [0x1364]={
+ category="po",
+ description="ETHIOPIC SEMICOLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1364,
+ },
+ [0x1365]={
+ category="po",
+ description="ETHIOPIC COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1365,
+ },
+ [0x1366]={
+ category="po",
+ description="ETHIOPIC PREFACE COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1366,
+ },
+ [0x1367]={
+ category="po",
+ description="ETHIOPIC QUESTION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1367,
+ },
+ [0x1368]={
+ category="po",
+ description="ETHIOPIC PARAGRAPH SEPARATOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1368,
+ },
+ [0x1369]={
+ category="no",
+ description="ETHIOPIC DIGIT ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1369,
+ },
+ [0x136A]={
+ category="no",
+ description="ETHIOPIC DIGIT TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136A,
+ },
+ [0x136B]={
+ category="no",
+ description="ETHIOPIC DIGIT THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136B,
+ },
+ [0x136C]={
+ category="no",
+ description="ETHIOPIC DIGIT FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136C,
+ },
+ [0x136D]={
+ category="no",
+ description="ETHIOPIC DIGIT FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136D,
+ },
+ [0x136E]={
+ category="no",
+ description="ETHIOPIC DIGIT SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136E,
+ },
+ [0x136F]={
+ category="no",
+ description="ETHIOPIC DIGIT SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x136F,
+ },
+ [0x1370]={
+ category="no",
+ description="ETHIOPIC DIGIT EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1370,
+ },
+ [0x1371]={
+ category="no",
+ description="ETHIOPIC DIGIT NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1371,
+ },
+ [0x1372]={
+ category="no",
+ description="ETHIOPIC NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1372,
+ },
+ [0x1373]={
+ category="no",
+ description="ETHIOPIC NUMBER TWENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1373,
+ },
+ [0x1374]={
+ category="no",
+ description="ETHIOPIC NUMBER THIRTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1374,
+ },
+ [0x1375]={
+ category="no",
+ description="ETHIOPIC NUMBER FORTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1375,
+ },
+ [0x1376]={
+ category="no",
+ description="ETHIOPIC NUMBER FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1376,
+ },
+ [0x1377]={
+ category="no",
+ description="ETHIOPIC NUMBER SIXTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1377,
+ },
+ [0x1378]={
+ category="no",
+ description="ETHIOPIC NUMBER SEVENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1378,
+ },
+ [0x1379]={
+ category="no",
+ description="ETHIOPIC NUMBER EIGHTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1379,
+ },
+ [0x137A]={
+ category="no",
+ description="ETHIOPIC NUMBER NINETY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x137A,
+ },
+ [0x137B]={
+ category="no",
+ description="ETHIOPIC NUMBER HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x137B,
+ },
+ [0x137C]={
+ category="no",
+ description="ETHIOPIC NUMBER TEN THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x137C,
+ },
+ [0x1380]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SEBATBEIT MWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1380,
+ },
+ [0x1381]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1381,
+ },
+ [0x1382]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1382,
+ },
+ [0x1383]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1383,
+ },
+ [0x1384]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SEBATBEIT BWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1384,
+ },
+ [0x1385]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1385,
+ },
+ [0x1386]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1386,
+ },
+ [0x1387]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1387,
+ },
+ [0x1388]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SEBATBEIT FWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1388,
+ },
+ [0x1389]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1389,
+ },
+ [0x138A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138A,
+ },
+ [0x138B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE FWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138B,
+ },
+ [0x138C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SEBATBEIT PWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138C,
+ },
+ [0x138D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138D,
+ },
+ [0x138E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138E,
+ },
+ [0x138F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x138F,
+ },
+ [0x1390]={
+ category="so",
+ description="ETHIOPIC TONAL MARK YIZET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1390,
+ },
+ [0x1391]={
+ category="so",
+ description="ETHIOPIC TONAL MARK DERET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1391,
+ },
+ [0x1392]={
+ category="so",
+ description="ETHIOPIC TONAL MARK RIKRIK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1392,
+ },
+ [0x1393]={
+ category="so",
+ description="ETHIOPIC TONAL MARK SHORT RIKRIK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1393,
+ },
+ [0x1394]={
+ category="so",
+ description="ETHIOPIC TONAL MARK DIFAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1394,
+ },
+ [0x1395]={
+ category="so",
+ description="ETHIOPIC TONAL MARK KENAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1395,
+ },
+ [0x1396]={
+ category="so",
+ description="ETHIOPIC TONAL MARK CHIRET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1396,
+ },
+ [0x1397]={
+ category="so",
+ description="ETHIOPIC TONAL MARK HIDET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1397,
+ },
+ [0x1398]={
+ category="so",
+ description="ETHIOPIC TONAL MARK DERET-HIDET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1398,
+ },
+ [0x1399]={
+ category="so",
+ description="ETHIOPIC TONAL MARK KURT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1399,
+ },
+ [0x13A0]={
+ category="lo",
+ description="CHEROKEE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A0,
+ },
+ [0x13A1]={
+ category="lo",
+ description="CHEROKEE LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A1,
+ },
+ [0x13A2]={
+ category="lo",
+ description="CHEROKEE LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A2,
+ },
+ [0x13A3]={
+ category="lo",
+ description="CHEROKEE LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A3,
+ },
+ [0x13A4]={
+ category="lo",
+ description="CHEROKEE LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A4,
+ },
+ [0x13A5]={
+ category="lo",
+ description="CHEROKEE LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A5,
+ },
+ [0x13A6]={
+ category="lo",
+ description="CHEROKEE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A6,
+ },
+ [0x13A7]={
+ category="lo",
+ description="CHEROKEE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A7,
+ },
+ [0x13A8]={
+ category="lo",
+ description="CHEROKEE LETTER GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A8,
+ },
+ [0x13A9]={
+ category="lo",
+ description="CHEROKEE LETTER GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13A9,
+ },
+ [0x13AA]={
+ category="lo",
+ description="CHEROKEE LETTER GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AA,
+ },
+ [0x13AB]={
+ category="lo",
+ description="CHEROKEE LETTER GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AB,
+ },
+ [0x13AC]={
+ category="lo",
+ description="CHEROKEE LETTER GV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AC,
+ },
+ [0x13AD]={
+ category="lo",
+ description="CHEROKEE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AD,
+ },
+ [0x13AE]={
+ category="lo",
+ description="CHEROKEE LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AE,
+ },
+ [0x13AF]={
+ category="lo",
+ description="CHEROKEE LETTER HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13AF,
+ },
+ [0x13B0]={
+ category="lo",
+ description="CHEROKEE LETTER HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B0,
+ },
+ [0x13B1]={
+ category="lo",
+ description="CHEROKEE LETTER HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B1,
+ },
+ [0x13B2]={
+ category="lo",
+ description="CHEROKEE LETTER HV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B2,
+ },
+ [0x13B3]={
+ category="lo",
+ description="CHEROKEE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B3,
+ },
+ [0x13B4]={
+ category="lo",
+ description="CHEROKEE LETTER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B4,
+ },
+ [0x13B5]={
+ category="lo",
+ description="CHEROKEE LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B5,
+ },
+ [0x13B6]={
+ category="lo",
+ description="CHEROKEE LETTER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B6,
+ },
+ [0x13B7]={
+ category="lo",
+ description="CHEROKEE LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B7,
+ },
+ [0x13B8]={
+ category="lo",
+ description="CHEROKEE LETTER LV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B8,
+ },
+ [0x13B9]={
+ category="lo",
+ description="CHEROKEE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13B9,
+ },
+ [0x13BA]={
+ category="lo",
+ description="CHEROKEE LETTER ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BA,
+ },
+ [0x13BB]={
+ category="lo",
+ description="CHEROKEE LETTER MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BB,
+ },
+ [0x13BC]={
+ category="lo",
+ description="CHEROKEE LETTER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BC,
+ },
+ [0x13BD]={
+ category="lo",
+ description="CHEROKEE LETTER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BD,
+ },
+ [0x13BE]={
+ category="lo",
+ description="CHEROKEE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BE,
+ },
+ [0x13BF]={
+ category="lo",
+ description="CHEROKEE LETTER HNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13BF,
+ },
+ [0x13C0]={
+ category="lo",
+ description="CHEROKEE LETTER NAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C0,
+ },
+ [0x13C1]={
+ category="lo",
+ description="CHEROKEE LETTER NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C1,
+ },
+ [0x13C2]={
+ category="lo",
+ description="CHEROKEE LETTER NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C2,
+ },
+ [0x13C3]={
+ category="lo",
+ description="CHEROKEE LETTER NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C3,
+ },
+ [0x13C4]={
+ category="lo",
+ description="CHEROKEE LETTER NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C4,
+ },
+ [0x13C5]={
+ category="lo",
+ description="CHEROKEE LETTER NV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C5,
+ },
+ [0x13C6]={
+ category="lo",
+ description="CHEROKEE LETTER QUA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C6,
+ },
+ [0x13C7]={
+ category="lo",
+ description="CHEROKEE LETTER QUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C7,
+ },
+ [0x13C8]={
+ category="lo",
+ description="CHEROKEE LETTER QUI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C8,
+ },
+ [0x13C9]={
+ category="lo",
+ description="CHEROKEE LETTER QUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13C9,
+ },
+ [0x13CA]={
+ category="lo",
+ description="CHEROKEE LETTER QUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CA,
+ },
+ [0x13CB]={
+ category="lo",
+ description="CHEROKEE LETTER QUV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CB,
+ },
+ [0x13CC]={
+ category="lo",
+ description="CHEROKEE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CC,
+ },
+ [0x13CD]={
+ category="lo",
+ description="CHEROKEE LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CD,
+ },
+ [0x13CE]={
+ category="lo",
+ description="CHEROKEE LETTER SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CE,
+ },
+ [0x13CF]={
+ category="lo",
+ description="CHEROKEE LETTER SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13CF,
+ },
+ [0x13D0]={
+ category="lo",
+ description="CHEROKEE LETTER SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D0,
+ },
+ [0x13D1]={
+ category="lo",
+ description="CHEROKEE LETTER SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D1,
+ },
+ [0x13D2]={
+ category="lo",
+ description="CHEROKEE LETTER SV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D2,
+ },
+ [0x13D3]={
+ category="lo",
+ description="CHEROKEE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D3,
+ },
+ [0x13D4]={
+ category="lo",
+ description="CHEROKEE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D4,
+ },
+ [0x13D5]={
+ category="lo",
+ description="CHEROKEE LETTER DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D5,
+ },
+ [0x13D6]={
+ category="lo",
+ description="CHEROKEE LETTER TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D6,
+ },
+ [0x13D7]={
+ category="lo",
+ description="CHEROKEE LETTER DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D7,
+ },
+ [0x13D8]={
+ category="lo",
+ description="CHEROKEE LETTER TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D8,
+ },
+ [0x13D9]={
+ category="lo",
+ description="CHEROKEE LETTER DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13D9,
+ },
+ [0x13DA]={
+ category="lo",
+ description="CHEROKEE LETTER DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DA,
+ },
+ [0x13DB]={
+ category="lo",
+ description="CHEROKEE LETTER DV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DB,
+ },
+ [0x13DC]={
+ category="lo",
+ description="CHEROKEE LETTER DLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DC,
+ },
+ [0x13DD]={
+ category="lo",
+ description="CHEROKEE LETTER TLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DD,
+ },
+ [0x13DE]={
+ category="lo",
+ description="CHEROKEE LETTER TLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DE,
+ },
+ [0x13DF]={
+ category="lo",
+ description="CHEROKEE LETTER TLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13DF,
+ },
+ [0x13E0]={
+ category="lo",
+ description="CHEROKEE LETTER TLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E0,
+ },
+ [0x13E1]={
+ category="lo",
+ description="CHEROKEE LETTER TLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E1,
+ },
+ [0x13E2]={
+ category="lo",
+ description="CHEROKEE LETTER TLV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E2,
+ },
+ [0x13E3]={
+ category="lo",
+ description="CHEROKEE LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E3,
+ },
+ [0x13E4]={
+ category="lo",
+ description="CHEROKEE LETTER TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E4,
+ },
+ [0x13E5]={
+ category="lo",
+ description="CHEROKEE LETTER TSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E5,
+ },
+ [0x13E6]={
+ category="lo",
+ description="CHEROKEE LETTER TSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E6,
+ },
+ [0x13E7]={
+ category="lo",
+ description="CHEROKEE LETTER TSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E7,
+ },
+ [0x13E8]={
+ category="lo",
+ description="CHEROKEE LETTER TSV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E8,
+ },
+ [0x13E9]={
+ category="lo",
+ description="CHEROKEE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13E9,
+ },
+ [0x13EA]={
+ category="lo",
+ description="CHEROKEE LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13EA,
+ },
+ [0x13EB]={
+ category="lo",
+ description="CHEROKEE LETTER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13EB,
+ },
+ [0x13EC]={
+ category="lo",
+ description="CHEROKEE LETTER WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13EC,
+ },
+ [0x13ED]={
+ category="lo",
+ description="CHEROKEE LETTER WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13ED,
+ },
+ [0x13EE]={
+ category="lo",
+ description="CHEROKEE LETTER WV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13EE,
+ },
+ [0x13EF]={
+ category="lo",
+ description="CHEROKEE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13EF,
+ },
+ [0x13F0]={
+ category="lo",
+ description="CHEROKEE LETTER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F0,
+ },
+ [0x13F1]={
+ category="lo",
+ description="CHEROKEE LETTER YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F1,
+ },
+ [0x13F2]={
+ category="lo",
+ description="CHEROKEE LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F2,
+ },
+ [0x13F3]={
+ category="lo",
+ description="CHEROKEE LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F3,
+ },
+ [0x13F4]={
+ category="lo",
+ description="CHEROKEE LETTER YV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F4,
+ },
+ [0x13F5]={
+ category="lu",
+ description="CHEROKEE LETTER MV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F5,
+ },
+ [0x13F8]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F8,
+ },
+ [0x13F9]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13F9,
+ },
+ [0x13FA]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13FA,
+ },
+ [0x13FB]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13FB,
+ },
+ [0x13FC]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13FC,
+ },
+ [0x13FD]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER MV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13FD,
+ },
+ [0x1400]={
+ category="pd",
+ description="CANADIAN SYLLABICS HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x1400,
+ },
+ [0x1401]={
+ category="lo",
+ description="CANADIAN SYLLABICS E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1401,
+ },
+ [0x1402]={
+ category="lo",
+ description="CANADIAN SYLLABICS AAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1402,
+ },
+ [0x1403]={
+ category="lo",
+ description="CANADIAN SYLLABICS I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1403,
+ },
+ [0x1404]={
+ category="lo",
+ description="CANADIAN SYLLABICS II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1404,
+ },
+ [0x1405]={
+ category="lo",
+ description="CANADIAN SYLLABICS O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1405,
+ },
+ [0x1406]={
+ category="lo",
+ description="CANADIAN SYLLABICS OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1406,
+ },
+ [0x1407]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1407,
+ },
+ [0x1408]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1408,
+ },
+ [0x1409]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1409,
+ },
+ [0x140A]={
+ category="lo",
+ description="CANADIAN SYLLABICS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140A,
+ },
+ [0x140B]={
+ category="lo",
+ description="CANADIAN SYLLABICS AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140B,
+ },
+ [0x140C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140C,
+ },
+ [0x140D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140D,
+ },
+ [0x140E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140E,
+ },
+ [0x140F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x140F,
+ },
+ [0x1410]={
+ category="lo",
+ description="CANADIAN SYLLABICS WII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1410,
+ },
+ [0x1411]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1411,
+ },
+ [0x1412]={
+ category="lo",
+ description="CANADIAN SYLLABICS WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1412,
+ },
+ [0x1413]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1413,
+ },
+ [0x1414]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1414,
+ },
+ [0x1415]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1415,
+ },
+ [0x1416]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI WOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1416,
+ },
+ [0x1417]={
+ category="lo",
+ description="CANADIAN SYLLABICS WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1417,
+ },
+ [0x1418]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1418,
+ },
+ [0x1419]={
+ category="lo",
+ description="CANADIAN SYLLABICS WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1419,
+ },
+ [0x141A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141A,
+ },
+ [0x141B]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141B,
+ },
+ [0x141C]={
+ category="lo",
+ description="CANADIAN SYLLABICS AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141C,
+ },
+ [0x141D]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141D,
+ },
+ [0x141E]={
+ category="lo",
+ description="CANADIAN SYLLABICS GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141E,
+ },
+ [0x141F]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x141F,
+ },
+ [0x1420]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL GRAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1420,
+ },
+ [0x1421]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL BOTTOM HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1421,
+ },
+ [0x1422]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL TOP HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1422,
+ },
+ [0x1423]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL RIGHT HALF RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1423,
+ },
+ [0x1424]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1424,
+ },
+ [0x1425]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL DOUBLE ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1425,
+ },
+ [0x1426]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1426,
+ },
+ [0x1427]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL MIDDLE DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1427,
+ },
+ [0x1428]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1428,
+ },
+ [0x1429]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL PLUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1429,
+ },
+ [0x142A]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL DOWN TACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142A,
+ },
+ [0x142B]={
+ category="lo",
+ description="CANADIAN SYLLABICS EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142B,
+ },
+ [0x142C]={
+ category="lo",
+ description="CANADIAN SYLLABICS IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142C,
+ },
+ [0x142D]={
+ category="lo",
+ description="CANADIAN SYLLABICS ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142D,
+ },
+ [0x142E]={
+ category="lo",
+ description="CANADIAN SYLLABICS AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142E,
+ },
+ [0x142F]={
+ category="lo",
+ description="CANADIAN SYLLABICS PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x142F,
+ },
+ [0x1430]={
+ category="lo",
+ description="CANADIAN SYLLABICS PAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1430,
+ },
+ [0x1431]={
+ category="lo",
+ description="CANADIAN SYLLABICS PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1431,
+ },
+ [0x1432]={
+ category="lo",
+ description="CANADIAN SYLLABICS PII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1432,
+ },
+ [0x1433]={
+ category="lo",
+ description="CANADIAN SYLLABICS PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1433,
+ },
+ [0x1434]={
+ category="lo",
+ description="CANADIAN SYLLABICS POO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1434,
+ },
+ [0x1435]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE POO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1435,
+ },
+ [0x1436]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1436,
+ },
+ [0x1437]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1437,
+ },
+ [0x1438]={
+ category="lo",
+ description="CANADIAN SYLLABICS PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1438,
+ },
+ [0x1439]={
+ category="lo",
+ description="CANADIAN SYLLABICS PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1439,
+ },
+ [0x143A]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143A,
+ },
+ [0x143B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143B,
+ },
+ [0x143C]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143C,
+ },
+ [0x143D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143D,
+ },
+ [0x143E]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143E,
+ },
+ [0x143F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x143F,
+ },
+ [0x1440]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440,
+ },
+ [0x1441]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441,
+ },
+ [0x1442]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442,
+ },
+ [0x1443]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443,
+ },
+ [0x1444]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444,
+ },
+ [0x1445]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445,
+ },
+ [0x1446]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446,
+ },
+ [0x1447]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE PWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447,
+ },
+ [0x1448]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE PWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448,
+ },
+ [0x1449]={
+ category="lo",
+ description="CANADIAN SYLLABICS P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449,
+ },
+ [0x144A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A,
+ },
+ [0x144B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B,
+ },
+ [0x144C]={
+ category="lo",
+ description="CANADIAN SYLLABICS TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C,
+ },
+ [0x144D]={
+ category="lo",
+ description="CANADIAN SYLLABICS TAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D,
+ },
+ [0x144E]={
+ category="lo",
+ description="CANADIAN SYLLABICS TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E,
+ },
+ [0x144F]={
+ category="lo",
+ description="CANADIAN SYLLABICS TII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F,
+ },
+ [0x1450]={
+ category="lo",
+ description="CANADIAN SYLLABICS TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450,
+ },
+ [0x1451]={
+ category="lo",
+ description="CANADIAN SYLLABICS TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451,
+ },
+ [0x1452]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452,
+ },
+ [0x1453]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453,
+ },
+ [0x1454]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454,
+ },
+ [0x1455]={
+ category="lo",
+ description="CANADIAN SYLLABICS TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455,
+ },
+ [0x1456]={
+ category="lo",
+ description="CANADIAN SYLLABICS TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456,
+ },
+ [0x1457]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457,
+ },
+ [0x1458]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458,
+ },
+ [0x1459]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459,
+ },
+ [0x145A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A,
+ },
+ [0x145B]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B,
+ },
+ [0x145C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C,
+ },
+ [0x145D]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D,
+ },
+ [0x145E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E,
+ },
+ [0x145F]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F,
+ },
+ [0x1460]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460,
+ },
+ [0x1461]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461,
+ },
+ [0x1462]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462,
+ },
+ [0x1463]={
+ category="lo",
+ description="CANADIAN SYLLABICS TWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463,
+ },
+ [0x1464]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE TWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1464,
+ },
+ [0x1465]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI TWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1465,
+ },
+ [0x1466]={
+ category="lo",
+ description="CANADIAN SYLLABICS T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1466,
+ },
+ [0x1467]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1467,
+ },
+ [0x1468]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1468,
+ },
+ [0x1469]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1469,
+ },
+ [0x146A]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146A,
+ },
+ [0x146B]={
+ category="lo",
+ description="CANADIAN SYLLABICS KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146B,
+ },
+ [0x146C]={
+ category="lo",
+ description="CANADIAN SYLLABICS KAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146C,
+ },
+ [0x146D]={
+ category="lo",
+ description="CANADIAN SYLLABICS KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146D,
+ },
+ [0x146E]={
+ category="lo",
+ description="CANADIAN SYLLABICS KII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146E,
+ },
+ [0x146F]={
+ category="lo",
+ description="CANADIAN SYLLABICS KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x146F,
+ },
+ [0x1470]={
+ category="lo",
+ description="CANADIAN SYLLABICS KOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1470,
+ },
+ [0x1471]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE KOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1471,
+ },
+ [0x1472]={
+ category="lo",
+ description="CANADIAN SYLLABICS KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1472,
+ },
+ [0x1473]={
+ category="lo",
+ description="CANADIAN SYLLABICS KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1473,
+ },
+ [0x1474]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1474,
+ },
+ [0x1475]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1475,
+ },
+ [0x1476]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1476,
+ },
+ [0x1477]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1477,
+ },
+ [0x1478]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1478,
+ },
+ [0x1479]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1479,
+ },
+ [0x147A]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147A,
+ },
+ [0x147B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147B,
+ },
+ [0x147C]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147C,
+ },
+ [0x147D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147D,
+ },
+ [0x147E]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147E,
+ },
+ [0x147F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x147F,
+ },
+ [0x1480]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1480,
+ },
+ [0x1481]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE KWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1481,
+ },
+ [0x1482]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI KWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1482,
+ },
+ [0x1483]={
+ category="lo",
+ description="CANADIAN SYLLABICS K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1483,
+ },
+ [0x1484]={
+ category="lo",
+ description="CANADIAN SYLLABICS KW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1484,
+ },
+ [0x1485]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOUTH-SLAVEY KEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1485,
+ },
+ [0x1486]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOUTH-SLAVEY KIH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1486,
+ },
+ [0x1487]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOUTH-SLAVEY KOH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1487,
+ },
+ [0x1488]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOUTH-SLAVEY KAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1488,
+ },
+ [0x1489]={
+ category="lo",
+ description="CANADIAN SYLLABICS CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1489,
+ },
+ [0x148A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148A,
+ },
+ [0x148B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148B,
+ },
+ [0x148C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148C,
+ },
+ [0x148D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148D,
+ },
+ [0x148E]={
+ category="lo",
+ description="CANADIAN SYLLABICS COO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148E,
+ },
+ [0x148F]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE COO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x148F,
+ },
+ [0x1490]={
+ category="lo",
+ description="CANADIAN SYLLABICS CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1490,
+ },
+ [0x1491]={
+ category="lo",
+ description="CANADIAN SYLLABICS CAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1491,
+ },
+ [0x1492]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1492,
+ },
+ [0x1493]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1493,
+ },
+ [0x1494]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1494,
+ },
+ [0x1495]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1495,
+ },
+ [0x1496]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1496,
+ },
+ [0x1497]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1497,
+ },
+ [0x1498]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1498,
+ },
+ [0x1499]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1499,
+ },
+ [0x149A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149A,
+ },
+ [0x149B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149B,
+ },
+ [0x149C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149C,
+ },
+ [0x149D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149D,
+ },
+ [0x149E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149E,
+ },
+ [0x149F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE CWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x149F,
+ },
+ [0x14A0]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI CWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A0,
+ },
+ [0x14A1]={
+ category="lo",
+ description="CANADIAN SYLLABICS C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A1,
+ },
+ [0x14A2]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A2,
+ },
+ [0x14A3]={
+ category="lo",
+ description="CANADIAN SYLLABICS ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A3,
+ },
+ [0x14A4]={
+ category="lo",
+ description="CANADIAN SYLLABICS MAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A4,
+ },
+ [0x14A5]={
+ category="lo",
+ description="CANADIAN SYLLABICS MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A5,
+ },
+ [0x14A6]={
+ category="lo",
+ description="CANADIAN SYLLABICS MII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A6,
+ },
+ [0x14A7]={
+ category="lo",
+ description="CANADIAN SYLLABICS MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A7,
+ },
+ [0x14A8]={
+ category="lo",
+ description="CANADIAN SYLLABICS MOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A8,
+ },
+ [0x14A9]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE MOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14A9,
+ },
+ [0x14AA]={
+ category="lo",
+ description="CANADIAN SYLLABICS MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AA,
+ },
+ [0x14AB]={
+ category="lo",
+ description="CANADIAN SYLLABICS MAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AB,
+ },
+ [0x14AC]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AC,
+ },
+ [0x14AD]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AD,
+ },
+ [0x14AE]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AE,
+ },
+ [0x14AF]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14AF,
+ },
+ [0x14B0]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B0,
+ },
+ [0x14B1]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B1,
+ },
+ [0x14B2]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B2,
+ },
+ [0x14B3]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B3,
+ },
+ [0x14B4]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B4,
+ },
+ [0x14B5]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B5,
+ },
+ [0x14B6]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B6,
+ },
+ [0x14B7]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B7,
+ },
+ [0x14B8]={
+ category="lo",
+ description="CANADIAN SYLLABICS MWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B8,
+ },
+ [0x14B9]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE MWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14B9,
+ },
+ [0x14BA]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI MWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BA,
+ },
+ [0x14BB]={
+ category="lo",
+ description="CANADIAN SYLLABICS M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BB,
+ },
+ [0x14BC]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BC,
+ },
+ [0x14BD]={
+ category="lo",
+ description="CANADIAN SYLLABICS MH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BD,
+ },
+ [0x14BE]={
+ category="lo",
+ description="CANADIAN SYLLABICS ATHAPASCAN M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BE,
+ },
+ [0x14BF]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14BF,
+ },
+ [0x14C0]={
+ category="lo",
+ description="CANADIAN SYLLABICS NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C0,
+ },
+ [0x14C1]={
+ category="lo",
+ description="CANADIAN SYLLABICS NAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C1,
+ },
+ [0x14C2]={
+ category="lo",
+ description="CANADIAN SYLLABICS NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C2,
+ },
+ [0x14C3]={
+ category="lo",
+ description="CANADIAN SYLLABICS NII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C3,
+ },
+ [0x14C4]={
+ category="lo",
+ description="CANADIAN SYLLABICS NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C4,
+ },
+ [0x14C5]={
+ category="lo",
+ description="CANADIAN SYLLABICS NOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C5,
+ },
+ [0x14C6]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE NOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C6,
+ },
+ [0x14C7]={
+ category="lo",
+ description="CANADIAN SYLLABICS NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C7,
+ },
+ [0x14C8]={
+ category="lo",
+ description="CANADIAN SYLLABICS NAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C8,
+ },
+ [0x14C9]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14C9,
+ },
+ [0x14CA]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE NWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CA,
+ },
+ [0x14CB]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CB,
+ },
+ [0x14CC]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE NWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CC,
+ },
+ [0x14CD]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CD,
+ },
+ [0x14CE]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE NWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CE,
+ },
+ [0x14CF]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI NWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14CF,
+ },
+ [0x14D0]={
+ category="lo",
+ description="CANADIAN SYLLABICS N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D0,
+ },
+ [0x14D1]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D1,
+ },
+ [0x14D2]={
+ category="lo",
+ description="CANADIAN SYLLABICS NH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D2,
+ },
+ [0x14D3]={
+ category="lo",
+ description="CANADIAN SYLLABICS LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D3,
+ },
+ [0x14D4]={
+ category="lo",
+ description="CANADIAN SYLLABICS LAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D4,
+ },
+ [0x14D5]={
+ category="lo",
+ description="CANADIAN SYLLABICS LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D5,
+ },
+ [0x14D6]={
+ category="lo",
+ description="CANADIAN SYLLABICS LII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D6,
+ },
+ [0x14D7]={
+ category="lo",
+ description="CANADIAN SYLLABICS LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D7,
+ },
+ [0x14D8]={
+ category="lo",
+ description="CANADIAN SYLLABICS LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D8,
+ },
+ [0x14D9]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14D9,
+ },
+ [0x14DA]={
+ category="lo",
+ description="CANADIAN SYLLABICS LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DA,
+ },
+ [0x14DB]={
+ category="lo",
+ description="CANADIAN SYLLABICS LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DB,
+ },
+ [0x14DC]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DC,
+ },
+ [0x14DD]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DD,
+ },
+ [0x14DE]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DE,
+ },
+ [0x14DF]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14DF,
+ },
+ [0x14E0]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E0,
+ },
+ [0x14E1]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E1,
+ },
+ [0x14E2]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E2,
+ },
+ [0x14E3]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E3,
+ },
+ [0x14E4]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E4,
+ },
+ [0x14E5]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E5,
+ },
+ [0x14E6]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E6,
+ },
+ [0x14E7]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E7,
+ },
+ [0x14E8]={
+ category="lo",
+ description="CANADIAN SYLLABICS LWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E8,
+ },
+ [0x14E9]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14E9,
+ },
+ [0x14EA]={
+ category="lo",
+ description="CANADIAN SYLLABICS L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14EA,
+ },
+ [0x14EB]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14EB,
+ },
+ [0x14EC]={
+ category="lo",
+ description="CANADIAN SYLLABICS MEDIAL L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14EC,
+ },
+ [0x14ED]={
+ category="lo",
+ description="CANADIAN SYLLABICS SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14ED,
+ },
+ [0x14EE]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14EE,
+ },
+ [0x14EF]={
+ category="lo",
+ description="CANADIAN SYLLABICS SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14EF,
+ },
+ [0x14F0]={
+ category="lo",
+ description="CANADIAN SYLLABICS SII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F0,
+ },
+ [0x14F1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F1,
+ },
+ [0x14F2]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F2,
+ },
+ [0x14F3]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F3,
+ },
+ [0x14F4]={
+ category="lo",
+ description="CANADIAN SYLLABICS SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F4,
+ },
+ [0x14F5]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F5,
+ },
+ [0x14F6]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F6,
+ },
+ [0x14F7]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F7,
+ },
+ [0x14F8]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F8,
+ },
+ [0x14F9]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14F9,
+ },
+ [0x14FA]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FA,
+ },
+ [0x14FB]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FB,
+ },
+ [0x14FC]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FC,
+ },
+ [0x14FD]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FD,
+ },
+ [0x14FE]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FE,
+ },
+ [0x14FF]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14FF,
+ },
+ [0x1500]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1500,
+ },
+ [0x1501]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1501,
+ },
+ [0x1502]={
+ category="lo",
+ description="CANADIAN SYLLABICS SWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1502,
+ },
+ [0x1503]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1503,
+ },
+ [0x1504]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI SWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1504,
+ },
+ [0x1505]={
+ category="lo",
+ description="CANADIAN SYLLABICS S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1505,
+ },
+ [0x1506]={
+ category="lo",
+ description="CANADIAN SYLLABICS ATHAPASCAN S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1506,
+ },
+ [0x1507]={
+ category="lo",
+ description="CANADIAN SYLLABICS SW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1507,
+ },
+ [0x1508]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1508,
+ },
+ [0x1509]={
+ category="lo",
+ description="CANADIAN SYLLABICS MOOSE-CREE SK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1509,
+ },
+ [0x150A]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI SKW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150A,
+ },
+ [0x150B]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI S-W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150B,
+ },
+ [0x150C]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI SPWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150C,
+ },
+ [0x150D]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI STWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150D,
+ },
+ [0x150E]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI SKWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150E,
+ },
+ [0x150F]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI SCWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x150F,
+ },
+ [0x1510]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1510,
+ },
+ [0x1511]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1511,
+ },
+ [0x1512]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1512,
+ },
+ [0x1513]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1513,
+ },
+ [0x1514]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1514,
+ },
+ [0x1515]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1515,
+ },
+ [0x1516]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1516,
+ },
+ [0x1517]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1517,
+ },
+ [0x1518]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1518,
+ },
+ [0x1519]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1519,
+ },
+ [0x151A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151A,
+ },
+ [0x151B]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151B,
+ },
+ [0x151C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151C,
+ },
+ [0x151D]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151D,
+ },
+ [0x151E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151E,
+ },
+ [0x151F]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x151F,
+ },
+ [0x1520]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1520,
+ },
+ [0x1521]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1521,
+ },
+ [0x1522]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1522,
+ },
+ [0x1523]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1523,
+ },
+ [0x1524]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE SHWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1524,
+ },
+ [0x1525]={
+ category="lo",
+ description="CANADIAN SYLLABICS SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1525,
+ },
+ [0x1526]={
+ category="lo",
+ description="CANADIAN SYLLABICS YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1526,
+ },
+ [0x1527]={
+ category="lo",
+ description="CANADIAN SYLLABICS YAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1527,
+ },
+ [0x1528]={
+ category="lo",
+ description="CANADIAN SYLLABICS YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1528,
+ },
+ [0x1529]={
+ category="lo",
+ description="CANADIAN SYLLABICS YII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1529,
+ },
+ [0x152A]={
+ category="lo",
+ description="CANADIAN SYLLABICS YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152A,
+ },
+ [0x152B]={
+ category="lo",
+ description="CANADIAN SYLLABICS YOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152B,
+ },
+ [0x152C]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y-CREE YOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152C,
+ },
+ [0x152D]={
+ category="lo",
+ description="CANADIAN SYLLABICS YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152D,
+ },
+ [0x152E]={
+ category="lo",
+ description="CANADIAN SYLLABICS YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152E,
+ },
+ [0x152F]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x152F,
+ },
+ [0x1530]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1530,
+ },
+ [0x1531]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1531,
+ },
+ [0x1532]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1532,
+ },
+ [0x1533]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1533,
+ },
+ [0x1534]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1534,
+ },
+ [0x1535]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1535,
+ },
+ [0x1536]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1536,
+ },
+ [0x1537]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1537,
+ },
+ [0x1538]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1538,
+ },
+ [0x1539]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1539,
+ },
+ [0x153A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153A,
+ },
+ [0x153B]={
+ category="lo",
+ description="CANADIAN SYLLABICS YWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153B,
+ },
+ [0x153C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE YWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153C,
+ },
+ [0x153D]={
+ category="lo",
+ description="CANADIAN SYLLABICS NASKAPI YWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153D,
+ },
+ [0x153E]={
+ category="lo",
+ description="CANADIAN SYLLABICS Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153E,
+ },
+ [0x153F]={
+ category="lo",
+ description="CANADIAN SYLLABICS BIBLE-CREE Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x153F,
+ },
+ [0x1540]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1540,
+ },
+ [0x1541]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1541,
+ },
+ [0x1542]={
+ category="lo",
+ description="CANADIAN SYLLABICS RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1542,
+ },
+ [0x1543]={
+ category="lo",
+ description="CANADIAN SYLLABICS R-CREE RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1543,
+ },
+ [0x1544]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1544,
+ },
+ [0x1545]={
+ category="lo",
+ description="CANADIAN SYLLABICS RAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1545,
+ },
+ [0x1546]={
+ category="lo",
+ description="CANADIAN SYLLABICS RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1546,
+ },
+ [0x1547]={
+ category="lo",
+ description="CANADIAN SYLLABICS RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1547,
+ },
+ [0x1548]={
+ category="lo",
+ description="CANADIAN SYLLABICS RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1548,
+ },
+ [0x1549]={
+ category="lo",
+ description="CANADIAN SYLLABICS ROO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1549,
+ },
+ [0x154A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154A,
+ },
+ [0x154B]={
+ category="lo",
+ description="CANADIAN SYLLABICS RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154B,
+ },
+ [0x154C]={
+ category="lo",
+ description="CANADIAN SYLLABICS RAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154C,
+ },
+ [0x154D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154D,
+ },
+ [0x154E]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154E,
+ },
+ [0x154F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE RWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x154F,
+ },
+ [0x1550]={
+ category="lo",
+ description="CANADIAN SYLLABICS R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1550,
+ },
+ [0x1551]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1551,
+ },
+ [0x1552]={
+ category="lo",
+ description="CANADIAN SYLLABICS MEDIAL R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1552,
+ },
+ [0x1553]={
+ category="lo",
+ description="CANADIAN SYLLABICS FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1553,
+ },
+ [0x1554]={
+ category="lo",
+ description="CANADIAN SYLLABICS FAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1554,
+ },
+ [0x1555]={
+ category="lo",
+ description="CANADIAN SYLLABICS FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1555,
+ },
+ [0x1556]={
+ category="lo",
+ description="CANADIAN SYLLABICS FII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1556,
+ },
+ [0x1557]={
+ category="lo",
+ description="CANADIAN SYLLABICS FO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1557,
+ },
+ [0x1558]={
+ category="lo",
+ description="CANADIAN SYLLABICS FOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1558,
+ },
+ [0x1559]={
+ category="lo",
+ description="CANADIAN SYLLABICS FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1559,
+ },
+ [0x155A]={
+ category="lo",
+ description="CANADIAN SYLLABICS FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155A,
+ },
+ [0x155B]={
+ category="lo",
+ description="CANADIAN SYLLABICS FWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155B,
+ },
+ [0x155C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE FWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155C,
+ },
+ [0x155D]={
+ category="lo",
+ description="CANADIAN SYLLABICS F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155D,
+ },
+ [0x155E]={
+ category="lo",
+ description="CANADIAN SYLLABICS THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155E,
+ },
+ [0x155F]={
+ category="lo",
+ description="CANADIAN SYLLABICS N-CREE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x155F,
+ },
+ [0x1560]={
+ category="lo",
+ description="CANADIAN SYLLABICS THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1560,
+ },
+ [0x1561]={
+ category="lo",
+ description="CANADIAN SYLLABICS N-CREE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1561,
+ },
+ [0x1562]={
+ category="lo",
+ description="CANADIAN SYLLABICS THII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1562,
+ },
+ [0x1563]={
+ category="lo",
+ description="CANADIAN SYLLABICS N-CREE THII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1563,
+ },
+ [0x1564]={
+ category="lo",
+ description="CANADIAN SYLLABICS THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1564,
+ },
+ [0x1565]={
+ category="lo",
+ description="CANADIAN SYLLABICS THOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1565,
+ },
+ [0x1566]={
+ category="lo",
+ description="CANADIAN SYLLABICS THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1566,
+ },
+ [0x1567]={
+ category="lo",
+ description="CANADIAN SYLLABICS THAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1567,
+ },
+ [0x1568]={
+ category="lo",
+ description="CANADIAN SYLLABICS THWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1568,
+ },
+ [0x1569]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE THWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1569,
+ },
+ [0x156A]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156A,
+ },
+ [0x156B]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156B,
+ },
+ [0x156C]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156C,
+ },
+ [0x156D]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156D,
+ },
+ [0x156E]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156E,
+ },
+ [0x156F]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x156F,
+ },
+ [0x1570]={
+ category="lo",
+ description="CANADIAN SYLLABICS TYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1570,
+ },
+ [0x1571]={
+ category="lo",
+ description="CANADIAN SYLLABICS TYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1571,
+ },
+ [0x1572]={
+ category="lo",
+ description="CANADIAN SYLLABICS TYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1572,
+ },
+ [0x1573]={
+ category="lo",
+ description="CANADIAN SYLLABICS TYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1573,
+ },
+ [0x1574]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1574,
+ },
+ [0x1575]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1575,
+ },
+ [0x1576]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1576,
+ },
+ [0x1577]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1577,
+ },
+ [0x1578]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1578,
+ },
+ [0x1579]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1579,
+ },
+ [0x157A]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157A,
+ },
+ [0x157B]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVIK H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157B,
+ },
+ [0x157C]={
+ category="lo",
+ description="CANADIAN SYLLABICS NUNAVUT H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157C,
+ },
+ [0x157D]={
+ category="lo",
+ description="CANADIAN SYLLABICS HK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157D,
+ },
+ [0x157E]={
+ category="lo",
+ description="CANADIAN SYLLABICS QAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157E,
+ },
+ [0x157F]={
+ category="lo",
+ description="CANADIAN SYLLABICS QI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x157F,
+ },
+ [0x1580]={
+ category="lo",
+ description="CANADIAN SYLLABICS QII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1580,
+ },
+ [0x1581]={
+ category="lo",
+ description="CANADIAN SYLLABICS QO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1581,
+ },
+ [0x1582]={
+ category="lo",
+ description="CANADIAN SYLLABICS QOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1582,
+ },
+ [0x1583]={
+ category="lo",
+ description="CANADIAN SYLLABICS QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1583,
+ },
+ [0x1584]={
+ category="lo",
+ description="CANADIAN SYLLABICS QAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1584,
+ },
+ [0x1585]={
+ category="lo",
+ description="CANADIAN SYLLABICS Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1585,
+ },
+ [0x1586]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1586,
+ },
+ [0x1587]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1587,
+ },
+ [0x1588]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1588,
+ },
+ [0x1589]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1589,
+ },
+ [0x158A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158A,
+ },
+ [0x158B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158B,
+ },
+ [0x158C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158C,
+ },
+ [0x158D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158D,
+ },
+ [0x158E]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGAAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158E,
+ },
+ [0x158F]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x158F,
+ },
+ [0x1590]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1590,
+ },
+ [0x1591]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1591,
+ },
+ [0x1592]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1592,
+ },
+ [0x1593]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1593,
+ },
+ [0x1594]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1594,
+ },
+ [0x1595]={
+ category="lo",
+ description="CANADIAN SYLLABICS NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1595,
+ },
+ [0x1596]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1596,
+ },
+ [0x1597]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1597,
+ },
+ [0x1598]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1598,
+ },
+ [0x1599]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1599,
+ },
+ [0x159A]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159A,
+ },
+ [0x159B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159B,
+ },
+ [0x159C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159C,
+ },
+ [0x159D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159D,
+ },
+ [0x159E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159E,
+ },
+ [0x159F]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x159F,
+ },
+ [0x15A0]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A0,
+ },
+ [0x15A1]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A1,
+ },
+ [0x15A2]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A2,
+ },
+ [0x15A3]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A3,
+ },
+ [0x15A4]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A4,
+ },
+ [0x15A5]={
+ category="lo",
+ description="CANADIAN SYLLABICS LHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A5,
+ },
+ [0x15A6]={
+ category="lo",
+ description="CANADIAN SYLLABICS LH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A6,
+ },
+ [0x15A7]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A7,
+ },
+ [0x15A8]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A8,
+ },
+ [0x15A9]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15A9,
+ },
+ [0x15AA]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AA,
+ },
+ [0x15AB]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AB,
+ },
+ [0x15AC]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AC,
+ },
+ [0x15AD]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE THAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AD,
+ },
+ [0x15AE]={
+ category="lo",
+ description="CANADIAN SYLLABICS TH-CREE TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AE,
+ },
+ [0x15AF]={
+ category="lo",
+ description="CANADIAN SYLLABICS AIVILIK B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15AF,
+ },
+ [0x15B0]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B0,
+ },
+ [0x15B1]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B1,
+ },
+ [0x15B2]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B2,
+ },
+ [0x15B3]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B3,
+ },
+ [0x15B4]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B4,
+ },
+ [0x15B5]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B5,
+ },
+ [0x15B6]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B6,
+ },
+ [0x15B7]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B7,
+ },
+ [0x15B8]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B8,
+ },
+ [0x15B9]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15B9,
+ },
+ [0x15BA]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BA,
+ },
+ [0x15BB]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BB,
+ },
+ [0x15BC]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BC,
+ },
+ [0x15BD]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BD,
+ },
+ [0x15BE]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BE,
+ },
+ [0x15BF]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15BF,
+ },
+ [0x15C0]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C0,
+ },
+ [0x15C1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C1,
+ },
+ [0x15C2]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C2,
+ },
+ [0x15C3]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C3,
+ },
+ [0x15C4]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C4,
+ },
+ [0x15C5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C5,
+ },
+ [0x15C6]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C6,
+ },
+ [0x15C7]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C7,
+ },
+ [0x15C8]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C8,
+ },
+ [0x15C9]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15C9,
+ },
+ [0x15CA]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CA,
+ },
+ [0x15CB]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CB,
+ },
+ [0x15CC]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CC,
+ },
+ [0x15CD]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CD,
+ },
+ [0x15CE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CE,
+ },
+ [0x15CF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15CF,
+ },
+ [0x15D0]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D0,
+ },
+ [0x15D1]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D1,
+ },
+ [0x15D2]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D2,
+ },
+ [0x15D3]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D3,
+ },
+ [0x15D4]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D4,
+ },
+ [0x15D5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D5,
+ },
+ [0x15D6]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D6,
+ },
+ [0x15D7]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D7,
+ },
+ [0x15D8]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D8,
+ },
+ [0x15D9]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15D9,
+ },
+ [0x15DA]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DA,
+ },
+ [0x15DB]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER HWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DB,
+ },
+ [0x15DC]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DC,
+ },
+ [0x15DD]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DD,
+ },
+ [0x15DE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DE,
+ },
+ [0x15DF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15DF,
+ },
+ [0x15E0]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E0,
+ },
+ [0x15E1]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E1,
+ },
+ [0x15E2]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E2,
+ },
+ [0x15E3]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E3,
+ },
+ [0x15E4]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E4,
+ },
+ [0x15E5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E5,
+ },
+ [0x15E6]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E6,
+ },
+ [0x15E7]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E7,
+ },
+ [0x15E8]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E8,
+ },
+ [0x15E9]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15E9,
+ },
+ [0x15EA]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15EA,
+ },
+ [0x15EB]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15EB,
+ },
+ [0x15EC]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15EC,
+ },
+ [0x15ED]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15ED,
+ },
+ [0x15EE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15EE,
+ },
+ [0x15EF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15EF,
+ },
+ [0x15F0]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F0,
+ },
+ [0x15F1]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F1,
+ },
+ [0x15F2]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F2,
+ },
+ [0x15F3]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F3,
+ },
+ [0x15F4]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F4,
+ },
+ [0x15F5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F5,
+ },
+ [0x15F6]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F6,
+ },
+ [0x15F7]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F7,
+ },
+ [0x15F8]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F8,
+ },
+ [0x15F9]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15F9,
+ },
+ [0x15FA]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FA,
+ },
+ [0x15FB]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FB,
+ },
+ [0x15FC]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FC,
+ },
+ [0x15FD]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FD,
+ },
+ [0x15FE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FE,
+ },
+ [0x15FF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x15FF,
+ },
+ [0x1600]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1600,
+ },
+ [0x1601]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER KK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1601,
+ },
+ [0x1602]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1602,
+ },
+ [0x1603]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1603,
+ },
+ [0x1604]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1604,
+ },
+ [0x1605]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1605,
+ },
+ [0x1606]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1606,
+ },
+ [0x1607]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1607,
+ },
+ [0x1608]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1608,
+ },
+ [0x1609]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1609,
+ },
+ [0x160A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160A,
+ },
+ [0x160B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER MEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160B,
+ },
+ [0x160C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160C,
+ },
+ [0x160D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160D,
+ },
+ [0x160E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160E,
+ },
+ [0x160F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x160F,
+ },
+ [0x1610]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1610,
+ },
+ [0x1611]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1611,
+ },
+ [0x1612]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1612,
+ },
+ [0x1613]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1613,
+ },
+ [0x1614]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1614,
+ },
+ [0x1615]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1615,
+ },
+ [0x1616]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1616,
+ },
+ [0x1617]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1617,
+ },
+ [0x1618]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1618,
+ },
+ [0x1619]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1619,
+ },
+ [0x161A]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161A,
+ },
+ [0x161B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161B,
+ },
+ [0x161C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161C,
+ },
+ [0x161D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161D,
+ },
+ [0x161E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161E,
+ },
+ [0x161F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x161F,
+ },
+ [0x1620]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1620,
+ },
+ [0x1621]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1621,
+ },
+ [0x1622]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1622,
+ },
+ [0x1623]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1623,
+ },
+ [0x1624]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1624,
+ },
+ [0x1625]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1625,
+ },
+ [0x1626]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1626,
+ },
+ [0x1627]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1627,
+ },
+ [0x1628]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1628,
+ },
+ [0x1629]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1629,
+ },
+ [0x162A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162A,
+ },
+ [0x162B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162B,
+ },
+ [0x162C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162C,
+ },
+ [0x162D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162D,
+ },
+ [0x162E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162E,
+ },
+ [0x162F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x162F,
+ },
+ [0x1630]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1630,
+ },
+ [0x1631]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1631,
+ },
+ [0x1632]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1632,
+ },
+ [0x1633]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1633,
+ },
+ [0x1634]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1634,
+ },
+ [0x1635]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1635,
+ },
+ [0x1636]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1636,
+ },
+ [0x1637]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1637,
+ },
+ [0x1638]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1638,
+ },
+ [0x1639]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1639,
+ },
+ [0x163A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163A,
+ },
+ [0x163B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163B,
+ },
+ [0x163C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163C,
+ },
+ [0x163D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163D,
+ },
+ [0x163E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163E,
+ },
+ [0x163F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x163F,
+ },
+ [0x1640]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1640,
+ },
+ [0x1641]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1641,
+ },
+ [0x1642]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1642,
+ },
+ [0x1643]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1643,
+ },
+ [0x1644]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1644,
+ },
+ [0x1645]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1645,
+ },
+ [0x1646]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1646,
+ },
+ [0x1647]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER INITIAL Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1647,
+ },
+ [0x1648]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1648,
+ },
+ [0x1649]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1649,
+ },
+ [0x164A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164A,
+ },
+ [0x164B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164B,
+ },
+ [0x164C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164C,
+ },
+ [0x164D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164D,
+ },
+ [0x164E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164E,
+ },
+ [0x164F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x164F,
+ },
+ [0x1650]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1650,
+ },
+ [0x1651]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1651,
+ },
+ [0x1652]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1652,
+ },
+ [0x1653]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1653,
+ },
+ [0x1654]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1654,
+ },
+ [0x1655]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1655,
+ },
+ [0x1656]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1656,
+ },
+ [0x1657]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1657,
+ },
+ [0x1658]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1658,
+ },
+ [0x1659]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1659,
+ },
+ [0x165A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165A,
+ },
+ [0x165B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165B,
+ },
+ [0x165C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165C,
+ },
+ [0x165D]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165D,
+ },
+ [0x165E]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165E,
+ },
+ [0x165F]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x165F,
+ },
+ [0x1660]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1660,
+ },
+ [0x1661]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1661,
+ },
+ [0x1662]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1662,
+ },
+ [0x1663]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1663,
+ },
+ [0x1664]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1664,
+ },
+ [0x1665]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1665,
+ },
+ [0x1666]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1666,
+ },
+ [0x1667]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1667,
+ },
+ [0x1668]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1668,
+ },
+ [0x1669]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1669,
+ },
+ [0x166A]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166A,
+ },
+ [0x166B]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166B,
+ },
+ [0x166C]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER TTSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166C,
+ },
+ [0x166D]={
+ category="po",
+ description="CANADIAN SYLLABICS CHI SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166D,
+ },
+ [0x166E]={
+ category="po",
+ description="CANADIAN SYLLABICS FULL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166E,
+ },
+ [0x166F]={
+ category="lo",
+ description="CANADIAN SYLLABICS QAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x166F,
+ },
+ [0x1670]={
+ category="lo",
+ description="CANADIAN SYLLABICS NGAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1670,
+ },
+ [0x1671]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1671,
+ },
+ [0x1672]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1672,
+ },
+ [0x1673]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1673,
+ },
+ [0x1674]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1674,
+ },
+ [0x1675]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1675,
+ },
+ [0x1676]={
+ category="lo",
+ description="CANADIAN SYLLABICS NNGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1676,
+ },
+ [0x1677]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1677,
+ },
+ [0x1678]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1678,
+ },
+ [0x1679]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1679,
+ },
+ [0x167A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167A,
+ },
+ [0x167B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167B,
+ },
+ [0x167C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167C,
+ },
+ [0x167D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167D,
+ },
+ [0x167E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE FINAL TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167E,
+ },
+ [0x167F]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167F,
+ },
+ [0x1680]={
+ category="zs",
+ description="OGHAM SPACE MARK",
+ direction="ws",
+ linebreak="ba",
+ unicodeslot=0x1680,
+ },
+ [0x1681]={
+ category="lo",
+ description="OGHAM LETTER BEITH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681,
+ },
+ [0x1682]={
+ category="lo",
+ description="OGHAM LETTER LUIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682,
+ },
+ [0x1683]={
+ category="lo",
+ description="OGHAM LETTER FEARN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683,
+ },
+ [0x1684]={
+ category="lo",
+ description="OGHAM LETTER SAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684,
+ },
+ [0x1685]={
+ category="lo",
+ description="OGHAM LETTER NION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685,
+ },
+ [0x1686]={
+ category="lo",
+ description="OGHAM LETTER UATH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686,
+ },
+ [0x1687]={
+ category="lo",
+ description="OGHAM LETTER DAIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687,
+ },
+ [0x1688]={
+ category="lo",
+ description="OGHAM LETTER TINNE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688,
+ },
+ [0x1689]={
+ category="lo",
+ description="OGHAM LETTER COLL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689,
+ },
+ [0x168A]={
+ category="lo",
+ description="OGHAM LETTER CEIRT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A,
+ },
+ [0x168B]={
+ category="lo",
+ description="OGHAM LETTER MUIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B,
+ },
+ [0x168C]={
+ category="lo",
+ description="OGHAM LETTER GORT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C,
+ },
+ [0x168D]={
+ category="lo",
+ description="OGHAM LETTER NGEADAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D,
+ },
+ [0x168E]={
+ category="lo",
+ description="OGHAM LETTER STRAIF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E,
+ },
+ [0x168F]={
+ category="lo",
+ description="OGHAM LETTER RUIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F,
+ },
+ [0x1690]={
+ category="lo",
+ description="OGHAM LETTER AILM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690,
+ },
+ [0x1691]={
+ category="lo",
+ description="OGHAM LETTER ONN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691,
+ },
+ [0x1692]={
+ category="lo",
+ description="OGHAM LETTER UR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692,
+ },
+ [0x1693]={
+ category="lo",
+ description="OGHAM LETTER EADHADH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693,
+ },
+ [0x1694]={
+ category="lo",
+ description="OGHAM LETTER IODHADH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694,
+ },
+ [0x1695]={
+ category="lo",
+ description="OGHAM LETTER EABHADH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695,
+ },
+ [0x1696]={
+ category="lo",
+ description="OGHAM LETTER OR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696,
+ },
+ [0x1697]={
+ category="lo",
+ description="OGHAM LETTER UILLEANN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697,
+ },
+ [0x1698]={
+ category="lo",
+ description="OGHAM LETTER IFIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698,
+ },
+ [0x1699]={
+ category="lo",
+ description="OGHAM LETTER EAMHANCHOLL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699,
+ },
+ [0x169A]={
+ category="lo",
+ description="OGHAM LETTER PEITH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A,
+ },
+ [0x169B]={
+ category="ps",
+ description="OGHAM FEATHER MARK",
+ direction="on",
+ linebreak="op",
+ mirror=0x169C,
+ unicodeslot=0x169B,
+ },
+ [0x169C]={
+ category="pe",
+ description="OGHAM REVERSED FEATHER MARK",
+ direction="on",
+ linebreak="cl",
+ mirror=0x169B,
+ unicodeslot=0x169C,
+ },
+ [0x16A0]={
+ category="lo",
+ description="RUNIC LETTER FEHU FEOH FE F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0,
+ },
+ [0x16A1]={
+ category="lo",
+ description="RUNIC LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1,
+ },
+ [0x16A2]={
+ category="lo",
+ description="RUNIC LETTER URUZ UR U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2,
+ },
+ [0x16A3]={
+ category="lo",
+ description="RUNIC LETTER YR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A3,
+ },
+ [0x16A4]={
+ category="lo",
+ description="RUNIC LETTER Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4,
+ },
+ [0x16A5]={
+ category="lo",
+ description="RUNIC LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5,
+ },
+ [0x16A6]={
+ category="lo",
+ description="RUNIC LETTER THURISAZ THURS THORN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A6,
+ },
+ [0x16A7]={
+ category="lo",
+ description="RUNIC LETTER ETH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A7,
+ },
+ [0x16A8]={
+ category="lo",
+ description="RUNIC LETTER ANSUZ A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A8,
+ },
+ [0x16A9]={
+ category="lo",
+ description="RUNIC LETTER OS O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A9,
+ },
+ [0x16AA]={
+ category="lo",
+ description="RUNIC LETTER AC A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AA,
+ },
+ [0x16AB]={
+ category="lo",
+ description="RUNIC LETTER AESC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AB,
+ },
+ [0x16AC]={
+ category="lo",
+ description="RUNIC LETTER LONG-BRANCH-OSS O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AC,
+ },
+ [0x16AD]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-OSS O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD,
+ },
+ [0x16AE]={
+ category="lo",
+ description="RUNIC LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE,
+ },
+ [0x16AF]={
+ category="lo",
+ description="RUNIC LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AF,
+ },
+ [0x16B0]={
+ category="lo",
+ description="RUNIC LETTER ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0,
+ },
+ [0x16B1]={
+ category="lo",
+ description="RUNIC LETTER RAIDO RAD REID R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1,
+ },
+ [0x16B2]={
+ category="lo",
+ description="RUNIC LETTER KAUNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2,
+ },
+ [0x16B3]={
+ category="lo",
+ description="RUNIC LETTER CEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3,
+ },
+ [0x16B4]={
+ category="lo",
+ description="RUNIC LETTER KAUN K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B4,
+ },
+ [0x16B5]={
+ category="lo",
+ description="RUNIC LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5,
+ },
+ [0x16B6]={
+ category="lo",
+ description="RUNIC LETTER ENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6,
+ },
+ [0x16B7]={
+ category="lo",
+ description="RUNIC LETTER GEBO GYFU G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B7,
+ },
+ [0x16B8]={
+ category="lo",
+ description="RUNIC LETTER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8,
+ },
+ [0x16B9]={
+ category="lo",
+ description="RUNIC LETTER WUNJO WYNN W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B9,
+ },
+ [0x16BA]={
+ category="lo",
+ description="RUNIC LETTER HAGLAZ H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BA,
+ },
+ [0x16BB]={
+ category="lo",
+ description="RUNIC LETTER HAEGL H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BB,
+ },
+ [0x16BC]={
+ category="lo",
+ description="RUNIC LETTER LONG-BRANCH-HAGALL H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BC,
+ },
+ [0x16BD]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-HAGALL H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BD,
+ },
+ [0x16BE]={
+ category="lo",
+ description="RUNIC LETTER NAUDIZ NYD NAUD N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BE,
+ },
+ [0x16BF]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-NAUD N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16BF,
+ },
+ [0x16C0]={
+ category="lo",
+ description="RUNIC LETTER DOTTED-N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C0,
+ },
+ [0x16C1]={
+ category="lo",
+ description="RUNIC LETTER ISAZ IS ISS I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C1,
+ },
+ [0x16C2]={
+ category="lo",
+ description="RUNIC LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C2,
+ },
+ [0x16C3]={
+ category="lo",
+ description="RUNIC LETTER JERAN J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C3,
+ },
+ [0x16C4]={
+ category="lo",
+ description="RUNIC LETTER GER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C4,
+ },
+ [0x16C5]={
+ category="lo",
+ description="RUNIC LETTER LONG-BRANCH-AR AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C5,
+ },
+ [0x16C6]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-AR A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C6,
+ },
+ [0x16C7]={
+ category="lo",
+ description="RUNIC LETTER IWAZ EOH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C7,
+ },
+ [0x16C8]={
+ category="lo",
+ description="RUNIC LETTER PERTHO PEORTH P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C8,
+ },
+ [0x16C9]={
+ category="lo",
+ description="RUNIC LETTER ALGIZ EOLHX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16C9,
+ },
+ [0x16CA]={
+ category="lo",
+ description="RUNIC LETTER SOWILO S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CA,
+ },
+ [0x16CB]={
+ category="lo",
+ description="RUNIC LETTER SIGEL LONG-BRANCH-SOL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CB,
+ },
+ [0x16CC]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-SOL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CC,
+ },
+ [0x16CD]={
+ category="lo",
+ description="RUNIC LETTER C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CD,
+ },
+ [0x16CE]={
+ category="lo",
+ description="RUNIC LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CE,
+ },
+ [0x16CF]={
+ category="lo",
+ description="RUNIC LETTER TIWAZ TIR TYR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16CF,
+ },
+ [0x16D0]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-TYR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D0,
+ },
+ [0x16D1]={
+ category="lo",
+ description="RUNIC LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D1,
+ },
+ [0x16D2]={
+ category="lo",
+ description="RUNIC LETTER BERKANAN BEORC BJARKAN B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D2,
+ },
+ [0x16D3]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-BJARKAN B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D3,
+ },
+ [0x16D4]={
+ category="lo",
+ description="RUNIC LETTER DOTTED-P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D4,
+ },
+ [0x16D5]={
+ category="lo",
+ description="RUNIC LETTER OPEN-P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D5,
+ },
+ [0x16D6]={
+ category="lo",
+ description="RUNIC LETTER EHWAZ EH E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D6,
+ },
+ [0x16D7]={
+ category="lo",
+ description="RUNIC LETTER MANNAZ MAN M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D7,
+ },
+ [0x16D8]={
+ category="lo",
+ description="RUNIC LETTER LONG-BRANCH-MADR M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D8,
+ },
+ [0x16D9]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-MADR M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16D9,
+ },
+ [0x16DA]={
+ category="lo",
+ description="RUNIC LETTER LAUKAZ LAGU LOGR L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DA,
+ },
+ [0x16DB]={
+ category="lo",
+ description="RUNIC LETTER DOTTED-L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DB,
+ },
+ [0x16DC]={
+ category="lo",
+ description="RUNIC LETTER INGWAZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DC,
+ },
+ [0x16DD]={
+ category="lo",
+ description="RUNIC LETTER ING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DD,
+ },
+ [0x16DE]={
+ category="lo",
+ description="RUNIC LETTER DAGAZ DAEG D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DE,
+ },
+ [0x16DF]={
+ category="lo",
+ description="RUNIC LETTER OTHALAN ETHEL O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16DF,
+ },
+ [0x16E0]={
+ category="lo",
+ description="RUNIC LETTER EAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E0,
+ },
+ [0x16E1]={
+ category="lo",
+ description="RUNIC LETTER IOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E1,
+ },
+ [0x16E2]={
+ category="lo",
+ description="RUNIC LETTER CWEORTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E2,
+ },
+ [0x16E3]={
+ category="lo",
+ description="RUNIC LETTER CALC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E3,
+ },
+ [0x16E4]={
+ category="lo",
+ description="RUNIC LETTER CEALC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4,
+ },
+ [0x16E5]={
+ category="lo",
+ description="RUNIC LETTER STAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5,
+ },
+ [0x16E6]={
+ category="lo",
+ description="RUNIC LETTER LONG-BRANCH-YR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6,
+ },
+ [0x16E7]={
+ category="lo",
+ description="RUNIC LETTER SHORT-TWIG-YR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7,
+ },
+ [0x16E8]={
+ category="lo",
+ description="RUNIC LETTER ICELANDIC-YR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8,
+ },
+ [0x16E9]={
+ category="lo",
+ description="RUNIC LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E9,
+ },
+ [0x16EA]={
+ category="lo",
+ description="RUNIC LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16EA,
+ },
+ [0x16EB]={
+ category="po",
+ description="RUNIC SINGLE PUNCTUATION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16EB,
+ },
+ [0x16EC]={
+ category="po",
+ description="RUNIC MULTIPLE PUNCTUATION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16EC,
+ },
+ [0x16ED]={
+ category="po",
+ description="RUNIC CROSS PUNCTUATION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16ED,
+ },
+ [0x16EE]={
+ category="nl",
+ description="RUNIC ARLAUG SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16EE,
+ },
+ [0x16EF]={
+ category="nl",
+ description="RUNIC TVIMADUR SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16EF,
+ },
+ [0x16F0]={
+ category="nl",
+ description="RUNIC BELGTHOR SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0,
+ },
+ [0x16F1]={
+ category="lo",
+ description="RUNIC LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1,
+ },
+ [0x16F2]={
+ category="lo",
+ description="RUNIC LETTER SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2,
+ },
+ [0x16F3]={
+ category="lo",
+ description="RUNIC LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3,
+ },
+ [0x16F4]={
+ category="lo",
+ description="RUNIC LETTER FRANKS CASKET OS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F4,
+ },
+ [0x16F5]={
+ category="lo",
+ description="RUNIC LETTER FRANKS CASKET IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F5,
+ },
+ [0x16F6]={
+ category="lo",
+ description="RUNIC LETTER FRANKS CASKET EH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F6,
+ },
+ [0x16F7]={
+ category="lo",
+ description="RUNIC LETTER FRANKS CASKET AC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F7,
+ },
+ [0x16F8]={
+ category="lo",
+ description="RUNIC LETTER FRANKS CASKET AESC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F8,
+ },
+ [0x1700]={
+ category="lo",
+ description="TAGALOG LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1700,
+ },
+ [0x1701]={
+ category="lo",
+ description="TAGALOG LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1701,
+ },
+ [0x1702]={
+ category="lo",
+ description="TAGALOG LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1702,
+ },
+ [0x1703]={
+ category="lo",
+ description="TAGALOG LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1703,
+ },
+ [0x1704]={
+ category="lo",
+ description="TAGALOG LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1704,
+ },
+ [0x1705]={
+ category="lo",
+ description="TAGALOG LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1705,
+ },
+ [0x1706]={
+ category="lo",
+ description="TAGALOG LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1706,
+ },
+ [0x1707]={
+ category="lo",
+ description="TAGALOG LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1707,
+ },
+ [0x1708]={
+ category="lo",
+ description="TAGALOG LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1708,
+ },
+ [0x1709]={
+ category="lo",
+ description="TAGALOG LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1709,
+ },
+ [0x170A]={
+ category="lo",
+ description="TAGALOG LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x170A,
+ },
+ [0x170B]={
+ category="lo",
+ description="TAGALOG LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x170B,
+ },
+ [0x170C]={
+ category="lo",
+ description="TAGALOG LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x170C,
+ },
+ [0x170E]={
+ category="lo",
+ description="TAGALOG LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x170E,
+ },
+ [0x170F]={
+ category="lo",
+ description="TAGALOG LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x170F,
+ },
+ [0x1710]={
+ category="lo",
+ description="TAGALOG LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1710,
+ },
+ [0x1711]={
+ category="lo",
+ description="TAGALOG LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1711,
+ },
+ [0x1712]={
+ category="mn",
+ description="TAGALOG VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1712,
+ },
+ [0x1713]={
+ category="mn",
+ description="TAGALOG VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1713,
+ },
+ [0x1714]={
+ category="mn",
+ combining=0x9,
+ description="TAGALOG SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1714,
+ },
+ [0x1720]={
+ category="lo",
+ description="HANUNOO LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1720,
+ },
+ [0x1721]={
+ category="lo",
+ description="HANUNOO LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1721,
+ },
+ [0x1722]={
+ category="lo",
+ description="HANUNOO LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1722,
+ },
+ [0x1723]={
+ category="lo",
+ description="HANUNOO LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1723,
+ },
+ [0x1724]={
+ category="lo",
+ description="HANUNOO LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1724,
+ },
+ [0x1725]={
+ category="lo",
+ description="HANUNOO LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1725,
+ },
+ [0x1726]={
+ category="lo",
+ description="HANUNOO LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1726,
+ },
+ [0x1727]={
+ category="lo",
+ description="HANUNOO LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1727,
+ },
+ [0x1728]={
+ category="lo",
+ description="HANUNOO LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1728,
+ },
+ [0x1729]={
+ category="lo",
+ description="HANUNOO LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1729,
+ },
+ [0x172A]={
+ category="lo",
+ description="HANUNOO LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172A,
+ },
+ [0x172B]={
+ category="lo",
+ description="HANUNOO LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172B,
+ },
+ [0x172C]={
+ category="lo",
+ description="HANUNOO LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172C,
+ },
+ [0x172D]={
+ category="lo",
+ description="HANUNOO LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172D,
+ },
+ [0x172E]={
+ category="lo",
+ description="HANUNOO LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172E,
+ },
+ [0x172F]={
+ category="lo",
+ description="HANUNOO LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x172F,
+ },
+ [0x1730]={
+ category="lo",
+ description="HANUNOO LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1730,
+ },
+ [0x1731]={
+ category="lo",
+ description="HANUNOO LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1731,
+ },
+ [0x1732]={
+ category="mn",
+ description="HANUNOO VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1732,
+ },
+ [0x1733]={
+ category="mn",
+ description="HANUNOO VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1733,
+ },
+ [0x1734]={
+ category="mn",
+ combining=0x9,
+ description="HANUNOO SIGN PAMUDPOD",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1734,
+ },
+ [0x1735]={
+ category="po",
+ description="PHILIPPINE SINGLE PUNCTUATION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1735,
+ },
+ [0x1736]={
+ category="po",
+ description="PHILIPPINE DOUBLE PUNCTUATION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1736,
+ },
+ [0x1740]={
+ category="lo",
+ description="BUHID LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1740,
+ },
+ [0x1741]={
+ category="lo",
+ description="BUHID LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1741,
+ },
+ [0x1742]={
+ category="lo",
+ description="BUHID LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1742,
+ },
+ [0x1743]={
+ category="lo",
+ description="BUHID LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1743,
+ },
+ [0x1744]={
+ category="lo",
+ description="BUHID LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1744,
+ },
+ [0x1745]={
+ category="lo",
+ description="BUHID LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1745,
+ },
+ [0x1746]={
+ category="lo",
+ description="BUHID LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1746,
+ },
+ [0x1747]={
+ category="lo",
+ description="BUHID LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1747,
+ },
+ [0x1748]={
+ category="lo",
+ description="BUHID LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1748,
+ },
+ [0x1749]={
+ category="lo",
+ description="BUHID LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1749,
+ },
+ [0x174A]={
+ category="lo",
+ description="BUHID LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174A,
+ },
+ [0x174B]={
+ category="lo",
+ description="BUHID LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174B,
+ },
+ [0x174C]={
+ category="lo",
+ description="BUHID LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174C,
+ },
+ [0x174D]={
+ category="lo",
+ description="BUHID LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174D,
+ },
+ [0x174E]={
+ category="lo",
+ description="BUHID LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174E,
+ },
+ [0x174F]={
+ category="lo",
+ description="BUHID LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x174F,
+ },
+ [0x1750]={
+ category="lo",
+ description="BUHID LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1750,
+ },
+ [0x1751]={
+ category="lo",
+ description="BUHID LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1751,
+ },
+ [0x1752]={
+ category="mn",
+ description="BUHID VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1752,
+ },
+ [0x1753]={
+ category="mn",
+ description="BUHID VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1753,
+ },
+ [0x1760]={
+ category="lo",
+ description="TAGBANWA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1760,
+ },
+ [0x1761]={
+ category="lo",
+ description="TAGBANWA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1761,
+ },
+ [0x1762]={
+ category="lo",
+ description="TAGBANWA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1762,
+ },
+ [0x1763]={
+ category="lo",
+ description="TAGBANWA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1763,
+ },
+ [0x1764]={
+ category="lo",
+ description="TAGBANWA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1764,
+ },
+ [0x1765]={
+ category="lo",
+ description="TAGBANWA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1765,
+ },
+ [0x1766]={
+ category="lo",
+ description="TAGBANWA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1766,
+ },
+ [0x1767]={
+ category="lo",
+ description="TAGBANWA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1767,
+ },
+ [0x1768]={
+ category="lo",
+ description="TAGBANWA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1768,
+ },
+ [0x1769]={
+ category="lo",
+ description="TAGBANWA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1769,
+ },
+ [0x176A]={
+ category="lo",
+ description="TAGBANWA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x176A,
+ },
+ [0x176B]={
+ category="lo",
+ description="TAGBANWA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x176B,
+ },
+ [0x176C]={
+ category="lo",
+ description="TAGBANWA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x176C,
+ },
+ [0x176E]={
+ category="lo",
+ description="TAGBANWA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x176E,
+ },
+ [0x176F]={
+ category="lo",
+ description="TAGBANWA LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x176F,
+ },
+ [0x1770]={
+ category="lo",
+ description="TAGBANWA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1770,
+ },
+ [0x1772]={
+ category="mn",
+ description="TAGBANWA VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1772,
+ },
+ [0x1773]={
+ category="mn",
+ description="TAGBANWA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1773,
+ },
+ [0x1780]={
+ category="lo",
+ description="KHMER LETTER KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1780,
+ },
+ [0x1781]={
+ category="lo",
+ description="KHMER LETTER KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1781,
+ },
+ [0x1782]={
+ category="lo",
+ description="KHMER LETTER KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1782,
+ },
+ [0x1783]={
+ category="lo",
+ description="KHMER LETTER KHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1783,
+ },
+ [0x1784]={
+ category="lo",
+ description="KHMER LETTER NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1784,
+ },
+ [0x1785]={
+ category="lo",
+ description="KHMER LETTER CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1785,
+ },
+ [0x1786]={
+ category="lo",
+ description="KHMER LETTER CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1786,
+ },
+ [0x1787]={
+ category="lo",
+ description="KHMER LETTER CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1787,
+ },
+ [0x1788]={
+ category="lo",
+ description="KHMER LETTER CHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1788,
+ },
+ [0x1789]={
+ category="lo",
+ description="KHMER LETTER NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1789,
+ },
+ [0x178A]={
+ category="lo",
+ description="KHMER LETTER DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178A,
+ },
+ [0x178B]={
+ category="lo",
+ description="KHMER LETTER TTHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178B,
+ },
+ [0x178C]={
+ category="lo",
+ description="KHMER LETTER DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178C,
+ },
+ [0x178D]={
+ category="lo",
+ description="KHMER LETTER TTHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178D,
+ },
+ [0x178E]={
+ category="lo",
+ description="KHMER LETTER NNO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178E,
+ },
+ [0x178F]={
+ category="lo",
+ description="KHMER LETTER TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x178F,
+ },
+ [0x1790]={
+ category="lo",
+ description="KHMER LETTER THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1790,
+ },
+ [0x1791]={
+ category="lo",
+ description="KHMER LETTER TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1791,
+ },
+ [0x1792]={
+ category="lo",
+ description="KHMER LETTER THO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1792,
+ },
+ [0x1793]={
+ category="lo",
+ description="KHMER LETTER NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1793,
+ },
+ [0x1794]={
+ category="lo",
+ description="KHMER LETTER BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1794,
+ },
+ [0x1795]={
+ category="lo",
+ description="KHMER LETTER PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1795,
+ },
+ [0x1796]={
+ category="lo",
+ description="KHMER LETTER PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1796,
+ },
+ [0x1797]={
+ category="lo",
+ description="KHMER LETTER PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1797,
+ },
+ [0x1798]={
+ category="lo",
+ description="KHMER LETTER MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1798,
+ },
+ [0x1799]={
+ category="lo",
+ description="KHMER LETTER YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1799,
+ },
+ [0x179A]={
+ category="lo",
+ description="KHMER LETTER RO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179A,
+ },
+ [0x179B]={
+ category="lo",
+ description="KHMER LETTER LO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179B,
+ },
+ [0x179C]={
+ category="lo",
+ description="KHMER LETTER VO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179C,
+ },
+ [0x179D]={
+ category="lo",
+ description="KHMER LETTER SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179D,
+ },
+ [0x179E]={
+ category="lo",
+ description="KHMER LETTER SSO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179E,
+ },
+ [0x179F]={
+ category="lo",
+ description="KHMER LETTER SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x179F,
+ },
+ [0x17A0]={
+ category="lo",
+ description="KHMER LETTER HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A0,
+ },
+ [0x17A1]={
+ category="lo",
+ description="KHMER LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A1,
+ },
+ [0x17A2]={
+ category="lo",
+ description="KHMER LETTER QA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A2,
+ },
+ [0x17A3]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QAQ",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A3,
+ },
+ [0x17A4]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QAA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A4,
+ },
+ [0x17A5]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A5,
+ },
+ [0x17A6]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QII",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A6,
+ },
+ [0x17A7]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A7,
+ },
+ [0x17A8]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QUK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A8,
+ },
+ [0x17A9]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QUU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17A9,
+ },
+ [0x17AA]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QUUV",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AA,
+ },
+ [0x17AB]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL RY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AB,
+ },
+ [0x17AC]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL RYY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AC,
+ },
+ [0x17AD]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL LY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AD,
+ },
+ [0x17AE]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL LYY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AE,
+ },
+ [0x17AF]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17AF,
+ },
+ [0x17B0]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17B0,
+ },
+ [0x17B1]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QOO TYPE ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17B1,
+ },
+ [0x17B2]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QOO TYPE TWO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17B2,
+ },
+ [0x17B3]={
+ category="lo",
+ description="KHMER INDEPENDENT VOWEL QAU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17B3,
+ },
+ [0x17B4]={
+ category="cf",
+ description="KHMER VOWEL INHERENT AQ",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17B4,
+ },
+ [0x17B5]={
+ category="cf",
+ description="KHMER VOWEL INHERENT AA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17B5,
+ },
+ [0x17B6]={
+ category="mc",
+ description="KHMER VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17B6,
+ },
+ [0x17B7]={
+ category="mn",
+ description="KHMER VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17B7,
+ },
+ [0x17B8]={
+ category="mn",
+ description="KHMER VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17B8,
+ },
+ [0x17B9]={
+ category="mn",
+ description="KHMER VOWEL SIGN Y",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17B9,
+ },
+ [0x17BA]={
+ category="mn",
+ description="KHMER VOWEL SIGN YY",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17BA,
+ },
+ [0x17BB]={
+ category="mn",
+ description="KHMER VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17BB,
+ },
+ [0x17BC]={
+ category="mn",
+ description="KHMER VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17BC,
+ },
+ [0x17BD]={
+ category="mn",
+ description="KHMER VOWEL SIGN UA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17BD,
+ },
+ [0x17BE]={
+ category="mc",
+ description="KHMER VOWEL SIGN OE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17BE,
+ },
+ [0x17BF]={
+ category="mc",
+ description="KHMER VOWEL SIGN YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17BF,
+ },
+ [0x17C0]={
+ category="mc",
+ description="KHMER VOWEL SIGN IE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C0,
+ },
+ [0x17C1]={
+ category="mc",
+ description="KHMER VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C1,
+ },
+ [0x17C2]={
+ category="mc",
+ description="KHMER VOWEL SIGN AE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C2,
+ },
+ [0x17C3]={
+ category="mc",
+ description="KHMER VOWEL SIGN AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C3,
+ },
+ [0x17C4]={
+ category="mc",
+ description="KHMER VOWEL SIGN OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C4,
+ },
+ [0x17C5]={
+ category="mc",
+ description="KHMER VOWEL SIGN AU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C5,
+ },
+ [0x17C6]={
+ category="mn",
+ description="KHMER SIGN NIKAHIT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17C6,
+ },
+ [0x17C7]={
+ category="mc",
+ description="KHMER SIGN REAHMUK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C7,
+ },
+ [0x17C8]={
+ category="mc",
+ description="KHMER SIGN YUUKALEAPINTU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17C8,
+ },
+ [0x17C9]={
+ category="mn",
+ description="KHMER SIGN MUUSIKATOAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17C9,
+ },
+ [0x17CA]={
+ category="mn",
+ description="KHMER SIGN TRIISAP",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CA,
+ },
+ [0x17CB]={
+ category="mn",
+ description="KHMER SIGN BANTOC",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CB,
+ },
+ [0x17CC]={
+ category="mn",
+ description="KHMER SIGN ROBAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CC,
+ },
+ [0x17CD]={
+ category="mn",
+ description="KHMER SIGN TOANDAKHIAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CD,
+ },
+ [0x17CE]={
+ category="mn",
+ description="KHMER SIGN KAKABAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CE,
+ },
+ [0x17CF]={
+ category="mn",
+ description="KHMER SIGN AHSDA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17CF,
+ },
+ [0x17D0]={
+ category="mn",
+ description="KHMER SIGN SAMYOK SANNYA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17D0,
+ },
+ [0x17D1]={
+ category="mn",
+ description="KHMER SIGN VIRIAM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17D1,
+ },
+ [0x17D2]={
+ category="mn",
+ combining=0x9,
+ description="KHMER SIGN COENG",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17D2,
+ },
+ [0x17D3]={
+ category="mn",
+ description="KHMER SIGN BATHAMASAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17D3,
+ },
+ [0x17D4]={
+ category="po",
+ description="KHMER SIGN KHAN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x17D4,
+ },
+ [0x17D5]={
+ category="po",
+ description="KHMER SIGN BARIYOOSAN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x17D5,
+ },
+ [0x17D6]={
+ category="po",
+ description="KHMER SIGN CAMNUC PII KUUH",
+ direction="l",
+ linebreak="ns",
+ unicodeslot=0x17D6,
+ },
+ [0x17D7]={
+ category="lm",
+ description="KHMER SIGN LEK TOO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17D7,
+ },
+ [0x17D8]={
+ category="po",
+ description="KHMER SIGN BEYYAL",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x17D8,
+ },
+ [0x17D9]={
+ category="po",
+ description="KHMER SIGN PHNAEK MUAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x17D9,
+ },
+ [0x17DA]={
+ category="po",
+ description="KHMER SIGN KOOMUUT",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x17DA,
+ },
+ [0x17DB]={
+ category="sc",
+ description="KHMER CURRENCY SYMBOL RIEL",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x17DB,
+ },
+ [0x17DC]={
+ category="lo",
+ description="KHMER SIGN AVAKRAHASANYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x17DC,
+ },
+ [0x17DD]={
+ category="mn",
+ combining=0xE6,
+ description="KHMER SIGN ATTHACAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x17DD,
+ },
+ [0x17E0]={
+ category="nd",
+ description="KHMER DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E0,
+ },
+ [0x17E1]={
+ category="nd",
+ description="KHMER DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E1,
+ },
+ [0x17E2]={
+ category="nd",
+ description="KHMER DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E2,
+ },
+ [0x17E3]={
+ category="nd",
+ description="KHMER DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E3,
+ },
+ [0x17E4]={
+ category="nd",
+ description="KHMER DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E4,
+ },
+ [0x17E5]={
+ category="nd",
+ description="KHMER DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E5,
+ },
+ [0x17E6]={
+ category="nd",
+ description="KHMER DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E6,
+ },
+ [0x17E7]={
+ category="nd",
+ description="KHMER DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E7,
+ },
+ [0x17E8]={
+ category="nd",
+ description="KHMER DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E8,
+ },
+ [0x17E9]={
+ category="nd",
+ description="KHMER DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x17E9,
+ },
+ [0x17F0]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK SON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F0,
+ },
+ [0x17F1]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK MUOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F1,
+ },
+ [0x17F2]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PII",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F2,
+ },
+ [0x17F3]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK BEI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F3,
+ },
+ [0x17F4]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK BUON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F4,
+ },
+ [0x17F5]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F5,
+ },
+ [0x17F6]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PRAM-MUOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F6,
+ },
+ [0x17F7]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PRAM-PII",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F7,
+ },
+ [0x17F8]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PRAM-BEI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F8,
+ },
+ [0x17F9]={
+ category="no",
+ description="KHMER SYMBOL LEK ATTAK PRAM-BUON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x17F9,
+ },
+ [0x1800]={
+ category="po",
+ description="MONGOLIAN BIRGA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1800,
+ },
+ [0x1801]={
+ category="po",
+ description="MONGOLIAN ELLIPSIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1801,
+ },
+ [0x1802]={
+ category="po",
+ description="MONGOLIAN COMMA",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1802,
+ },
+ [0x1803]={
+ category="po",
+ description="MONGOLIAN FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1803,
+ },
+ [0x1804]={
+ category="po",
+ description="MONGOLIAN COLON",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x1804,
+ },
+ [0x1805]={
+ category="po",
+ description="MONGOLIAN FOUR DOTS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x1805,
+ },
+ [0x1806]={
+ arabic="u",
+ category="pd",
+ description="MONGOLIAN TODO SOFT HYPHEN",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0x1806,
+ },
+ [0x1807]={
+ arabic="d",
+ category="po",
+ description="MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1807,
+ },
+ [0x1808]={
+ category="po",
+ description="MONGOLIAN MANCHU COMMA",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1808,
+ },
+ [0x1809]={
+ category="po",
+ description="MONGOLIAN MANCHU FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1809,
+ },
+ [0x180A]={
+ arabic="c",
+ category="po",
+ description="MONGOLIAN NIRUGU",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x180A,
+ },
+ [0x180B]={
+ category="mn",
+ description="MONGOLIAN FREE VARIATION SELECTOR ONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x180B,
+ },
+ [0x180C]={
+ category="mn",
+ description="MONGOLIAN FREE VARIATION SELECTOR TWO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x180C,
+ },
+ [0x180D]={
+ category="mn",
+ description="MONGOLIAN FREE VARIATION SELECTOR THREE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x180D,
+ },
+ [0x180E]={
+ arabic="u",
+ category="zs",
+ description="MONGOLIAN VOWEL SEPARATOR",
+ direction="bn",
+ linebreak="gl",
+ unicodeslot=0x180E,
+ },
+ [0x1810]={
+ category="nd",
+ description="MONGOLIAN DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1810,
+ },
+ [0x1811]={
+ category="nd",
+ description="MONGOLIAN DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1811,
+ },
+ [0x1812]={
+ category="nd",
+ description="MONGOLIAN DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1812,
+ },
+ [0x1813]={
+ category="nd",
+ description="MONGOLIAN DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1813,
+ },
+ [0x1814]={
+ category="nd",
+ description="MONGOLIAN DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1814,
+ },
+ [0x1815]={
+ category="nd",
+ description="MONGOLIAN DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1815,
+ },
+ [0x1816]={
+ category="nd",
+ description="MONGOLIAN DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1816,
+ },
+ [0x1817]={
+ category="nd",
+ description="MONGOLIAN DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1817,
+ },
+ [0x1818]={
+ category="nd",
+ description="MONGOLIAN DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1818,
+ },
+ [0x1819]={
+ category="nd",
+ description="MONGOLIAN DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1819,
+ },
+ [0x1820]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1820,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1821]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1821,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1822]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1822,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1823]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1823,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1824]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1824,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1825]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1825,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1826]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1826,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1827]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1827,
+ },
+ [0x1828]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1828,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="separate form",
+ },
+ },
+ [0x1829]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1829,
+ },
+ [0x182A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182A,
+ variants={
+ [0x180B]="alternative form",
+ },
+ },
+ [0x182B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182B,
+ },
+ [0x182C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182C,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
+ },
+ [0x182D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182D,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="feminine form",
+ },
+ },
+ [0x182E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182E,
+ },
+ [0x182F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x182F,
+ },
+ [0x1830]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1830,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1831]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1831,
+ },
+ [0x1832]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1832,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1833]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1833,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1834]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1834,
+ },
+ [0x1835]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1835,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1836]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1836,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1837]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1837,
+ },
+ [0x1838]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1838,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1839]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1839,
+ },
+ [0x183A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183A,
+ },
+ [0x183B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183B,
+ },
+ [0x183C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183C,
+ },
+ [0x183D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183D,
+ },
+ [0x183E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183E,
+ },
+ [0x183F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ZRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x183F,
+ },
+ [0x1840]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1840,
+ },
+ [0x1841]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ZHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1841,
+ },
+ [0x1842]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1842,
+ },
+ [0x1843]={
+ arabic="d",
+ category="lm",
+ description="MONGOLIAN LETTER TODO LONG VOWEL SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1843,
+ },
+ [0x1844]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1844,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1845]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1845,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1846]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1846,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1847]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1847,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1848]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1848,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1849]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1849,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x184A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184A,
+ },
+ [0x184B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184B,
+ },
+ [0x184C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184C,
+ },
+ [0x184D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184D,
+ variants={
+ [0x180B]="feminine form",
+ },
+ },
+ [0x184E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184E,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x184F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x184F,
+ },
+ [0x1850]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1850,
+ },
+ [0x1851]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1851,
+ },
+ [0x1852]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1852,
+ },
+ [0x1853]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1853,
+ },
+ [0x1854]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1854,
+ },
+ [0x1855]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1855,
+ },
+ [0x1856]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1856,
+ },
+ [0x1857]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1857,
+ },
+ [0x1858]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1858,
+ },
+ [0x1859]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1859,
+ },
+ [0x185A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO JIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185A,
+ },
+ [0x185B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO NIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185B,
+ },
+ [0x185C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185C,
+ },
+ [0x185D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185D,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x185E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185E,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x185F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE IY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x185F,
+ },
+ [0x1860]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1860,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1861]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1861,
+ },
+ [0x1862]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1862,
+ },
+ [0x1863]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1863,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1864]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1864,
+ },
+ [0x1865]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1865,
+ },
+ [0x1866]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1866,
+ },
+ [0x1867]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1867,
+ },
+ [0x1868]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1868,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
+ },
+ [0x1869]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1869,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x186A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186A,
+ },
+ [0x186B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186B,
+ },
+ [0x186C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186C,
+ },
+ [0x186D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186D,
+ },
+ [0x186E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186E,
+ },
+ [0x186F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x186F,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1870]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE RAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1870,
+ },
+ [0x1871]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1871,
+ },
+ [0x1872]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER SIBE ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1872,
+ },
+ [0x1873]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1873,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
+ },
+ [0x1874]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1874,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="feminine first medial form",
+ [0x180D]="feminine second medial form",
+ },
+ },
+ [0x1875]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1875,
+ },
+ [0x1876]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1876,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1877]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1877,
+ },
+ [0x1880]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI ANUSVARA ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1880,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1881]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI VISARGA ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1881,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1882]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI DAMARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1882,
+ },
+ [0x1883]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI UBADAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1883,
+ },
+ [0x1884]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI INVERTED UBADAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1884,
+ },
+ [0x1885]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI BALUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1885,
+ },
+ [0x1886]={
+ arabic="u",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI THREE BALUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1886,
+ },
+ [0x1887]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1887,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
+ },
+ [0x1888]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1888,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x1889]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1889,
+ },
+ [0x188A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188A,
+ variants={
+ [0x180B]="second form",
+ },
+ },
+ [0x188B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188B,
+ },
+ [0x188C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188C,
+ },
+ [0x188D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188D,
+ },
+ [0x188E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188E,
+ },
+ [0x188F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x188F,
+ },
+ [0x1890]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1890,
+ },
+ [0x1891]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1891,
+ },
+ [0x1892]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1892,
+ },
+ [0x1893]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1893,
+ },
+ [0x1894]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1894,
+ },
+ [0x1895]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1895,
+ },
+ [0x1896]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1896,
+ },
+ [0x1897]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1897,
+ },
+ [0x1898]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO ALI GALI TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1898,
+ },
+ [0x1899]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER TODO ALI GALI ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1899,
+ },
+ [0x189A]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189A,
+ },
+ [0x189B]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189B,
+ },
+ [0x189C]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189C,
+ },
+ [0x189D]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189D,
+ },
+ [0x189E]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189E,
+ },
+ [0x189F]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x189F,
+ },
+ [0x18A0]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A0,
+ },
+ [0x18A1]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A1,
+ },
+ [0x18A2]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A2,
+ },
+ [0x18A3]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI CYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A3,
+ },
+ [0x18A4]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A4,
+ },
+ [0x18A5]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A5,
+ },
+ [0x18A6]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI HALF U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A6,
+ },
+ [0x18A7]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER ALI GALI HALF YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A7,
+ },
+ [0x18A8]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18A8,
+ },
+ [0x18A9]={
+ category="mn",
+ combining=0xE4,
+ description="MONGOLIAN LETTER ALI GALI DAGALGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x18A9,
+ },
+ [0x18AA]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18AA,
+ },
+ [0x18B0]={
+ category="lo",
+ description="CANADIAN SYLLABICS OY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B0,
+ },
+ [0x18B1]={
+ category="lo",
+ description="CANADIAN SYLLABICS AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B1,
+ },
+ [0x18B2]={
+ category="lo",
+ description="CANADIAN SYLLABICS AAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B2,
+ },
+ [0x18B3]={
+ category="lo",
+ description="CANADIAN SYLLABICS WAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B3,
+ },
+ [0x18B4]={
+ category="lo",
+ description="CANADIAN SYLLABICS POY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B4,
+ },
+ [0x18B5]={
+ category="lo",
+ description="CANADIAN SYLLABICS PAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B5,
+ },
+ [0x18B6]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B6,
+ },
+ [0x18B7]={
+ category="lo",
+ description="CANADIAN SYLLABICS TAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B7,
+ },
+ [0x18B8]={
+ category="lo",
+ description="CANADIAN SYLLABICS KAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B8,
+ },
+ [0x18B9]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B9,
+ },
+ [0x18BA]={
+ category="lo",
+ description="CANADIAN SYLLABICS MAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BA,
+ },
+ [0x18BB]={
+ category="lo",
+ description="CANADIAN SYLLABICS NOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BB,
+ },
+ [0x18BC]={
+ category="lo",
+ description="CANADIAN SYLLABICS NAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BC,
+ },
+ [0x18BD]={
+ category="lo",
+ description="CANADIAN SYLLABICS LAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BD,
+ },
+ [0x18BE]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BE,
+ },
+ [0x18BF]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BF,
+ },
+ [0x18C0]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C0,
+ },
+ [0x18C1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C1,
+ },
+ [0x18C2]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C2,
+ },
+ [0x18C3]={
+ category="lo",
+ description="CANADIAN SYLLABICS YOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C3,
+ },
+ [0x18C4]={
+ category="lo",
+ description="CANADIAN SYLLABICS YAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C4,
+ },
+ [0x18C5]={
+ category="lo",
+ description="CANADIAN SYLLABICS RAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C5,
+ },
+ [0x18C6]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C6,
+ },
+ [0x18C7]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C7,
+ },
+ [0x18C8]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C8,
+ },
+ [0x18C9]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C9,
+ },
+ [0x18CA]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CA,
+ },
+ [0x18CB]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CB,
+ },
+ [0x18CC]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CC,
+ },
+ [0x18CD]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CD,
+ },
+ [0x18CE]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CE,
+ },
+ [0x18CF]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CF,
+ },
+ [0x18D0]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D0,
+ },
+ [0x18D1]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D1,
+ },
+ [0x18D2]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D2,
+ },
+ [0x18D3]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D3,
+ },
+ [0x18D4]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D4,
+ },
+ [0x18D5]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D5,
+ },
+ [0x18D6]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D6,
+ },
+ [0x18D7]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D7,
+ },
+ [0x18D8]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D8,
+ },
+ [0x18D9]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D9,
+ },
+ [0x18DA]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DA,
+ },
+ [0x18DB]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DB,
+ },
+ [0x18DC]={
+ category="lo",
+ description="CANADIAN SYLLABICS EASTERN W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DC,
+ },
+ [0x18DD]={
+ category="lo",
+ description="CANADIAN SYLLABICS WESTERN W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DD,
+ },
+ [0x18DE]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL SMALL RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DE,
+ },
+ [0x18DF]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL RAISED DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DF,
+ },
+ [0x18E0]={
+ category="lo",
+ description="CANADIAN SYLLABICS R-CREE RWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E0,
+ },
+ [0x18E1]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E1,
+ },
+ [0x18E2]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E2,
+ },
+ [0x18E3]={
+ category="lo",
+ description="CANADIAN SYLLABICS THWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E3,
+ },
+ [0x18E4]={
+ category="lo",
+ description="CANADIAN SYLLABICS THWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E4,
+ },
+ [0x18E5]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E5,
+ },
+ [0x18E6]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E6,
+ },
+ [0x18E7]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E7,
+ },
+ [0x18E8]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E8,
+ },
+ [0x18E9]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E9,
+ },
+ [0x18EA]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EA,
+ },
+ [0x18EB]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EB,
+ },
+ [0x18EC]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EC,
+ },
+ [0x18ED]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GWU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18ED,
+ },
+ [0x18EE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DENE GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EE,
+ },
+ [0x18EF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EF,
+ },
+ [0x18F0]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F0,
+ },
+ [0x18F1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI JUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F1,
+ },
+ [0x18F2]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F2,
+ },
+ [0x18F3]={
+ category="lo",
+ description="CANADIAN SYLLABICS BEAVER DENE L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F3,
+ },
+ [0x18F4]={
+ category="lo",
+ description="CANADIAN SYLLABICS BEAVER DENE R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F4,
+ },
+ [0x18F5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DENTAL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F5,
+ },
+ [0x1900]={
+ category="lo",
+ description="LIMBU VOWEL-CARRIER LETTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1900,
+ },
+ [0x1901]={
+ category="lo",
+ description="LIMBU LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1901,
+ },
+ [0x1902]={
+ category="lo",
+ description="LIMBU LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1902,
+ },
+ [0x1903]={
+ category="lo",
+ description="LIMBU LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1903,
+ },
+ [0x1904]={
+ category="lo",
+ description="LIMBU LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1904,
+ },
+ [0x1905]={
+ category="lo",
+ description="LIMBU LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1905,
+ },
+ [0x1906]={
+ category="lo",
+ description="LIMBU LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1906,
+ },
+ [0x1907]={
+ category="lo",
+ description="LIMBU LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1907,
+ },
+ [0x1908]={
+ category="lo",
+ description="LIMBU LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1908,
+ },
+ [0x1909]={
+ category="lo",
+ description="LIMBU LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1909,
+ },
+ [0x190A]={
+ category="lo",
+ description="LIMBU LETTER YAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190A,
+ },
+ [0x190B]={
+ category="lo",
+ description="LIMBU LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190B,
+ },
+ [0x190C]={
+ category="lo",
+ description="LIMBU LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190C,
+ },
+ [0x190D]={
+ category="lo",
+ description="LIMBU LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190D,
+ },
+ [0x190E]={
+ category="lo",
+ description="LIMBU LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190E,
+ },
+ [0x190F]={
+ category="lo",
+ description="LIMBU LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x190F,
+ },
+ [0x1910]={
+ category="lo",
+ description="LIMBU LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1910,
+ },
+ [0x1911]={
+ category="lo",
+ description="LIMBU LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1911,
+ },
+ [0x1912]={
+ category="lo",
+ description="LIMBU LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1912,
+ },
+ [0x1913]={
+ category="lo",
+ description="LIMBU LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1913,
+ },
+ [0x1914]={
+ category="lo",
+ description="LIMBU LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1914,
+ },
+ [0x1915]={
+ category="lo",
+ description="LIMBU LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1915,
+ },
+ [0x1916]={
+ category="lo",
+ description="LIMBU LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1916,
+ },
+ [0x1917]={
+ category="lo",
+ description="LIMBU LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1917,
+ },
+ [0x1918]={
+ category="lo",
+ description="LIMBU LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1918,
+ },
+ [0x1919]={
+ category="lo",
+ description="LIMBU LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1919,
+ },
+ [0x191A]={
+ category="lo",
+ description="LIMBU LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x191A,
+ },
+ [0x191B]={
+ category="lo",
+ description="LIMBU LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x191B,
+ },
+ [0x191C]={
+ category="lo",
+ description="LIMBU LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x191C,
+ },
+ [0x191D]={
+ category="lo",
+ description="LIMBU LETTER GYAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x191D,
+ },
+ [0x191E]={
+ category="lo",
+ description="LIMBU LETTER TRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x191E,
+ },
+ [0x1920]={
+ category="mn",
+ description="LIMBU VOWEL SIGN A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1920,
+ },
+ [0x1921]={
+ category="mn",
+ description="LIMBU VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1921,
+ },
+ [0x1922]={
+ category="mn",
+ description="LIMBU VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1922,
+ },
+ [0x1923]={
+ category="mc",
+ description="LIMBU VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1923,
+ },
+ [0x1924]={
+ category="mc",
+ description="LIMBU VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1924,
+ },
+ [0x1925]={
+ category="mc",
+ description="LIMBU VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1925,
+ },
+ [0x1926]={
+ category="mc",
+ description="LIMBU VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1926,
+ },
+ [0x1927]={
+ category="mn",
+ description="LIMBU VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1927,
+ },
+ [0x1928]={
+ category="mn",
+ description="LIMBU VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1928,
+ },
+ [0x1929]={
+ category="mc",
+ description="LIMBU SUBJOINED LETTER YA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1929,
+ },
+ [0x192A]={
+ category="mc",
+ description="LIMBU SUBJOINED LETTER RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x192A,
+ },
+ [0x192B]={
+ category="mc",
+ description="LIMBU SUBJOINED LETTER WA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x192B,
+ },
+ [0x1930]={
+ category="mc",
+ description="LIMBU SMALL LETTER KA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1930,
+ },
+ [0x1931]={
+ category="mc",
+ description="LIMBU SMALL LETTER NGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1931,
+ },
+ [0x1932]={
+ category="mn",
+ description="LIMBU SMALL LETTER ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1932,
+ },
+ [0x1933]={
+ category="mc",
+ description="LIMBU SMALL LETTER TA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1933,
+ },
+ [0x1934]={
+ category="mc",
+ description="LIMBU SMALL LETTER NA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1934,
+ },
+ [0x1935]={
+ category="mc",
+ description="LIMBU SMALL LETTER PA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1935,
+ },
+ [0x1936]={
+ category="mc",
+ description="LIMBU SMALL LETTER MA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1936,
+ },
+ [0x1937]={
+ category="mc",
+ description="LIMBU SMALL LETTER RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1937,
+ },
+ [0x1938]={
+ category="mc",
+ description="LIMBU SMALL LETTER LA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1938,
+ },
+ [0x1939]={
+ category="mn",
+ combining=0xDE,
+ description="LIMBU SIGN MUKPHRENG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1939,
+ },
+ [0x193A]={
+ category="mn",
+ combining=0xE6,
+ description="LIMBU SIGN KEMPHRENG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x193A,
+ },
+ [0x193B]={
+ category="mn",
+ combining=0xDC,
+ description="LIMBU SIGN SA-I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x193B,
+ },
+ [0x1940]={
+ category="so",
+ description="LIMBU SIGN LOO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1940,
+ },
+ [0x1944]={
+ category="po",
+ description="LIMBU EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1944,
+ },
+ [0x1945]={
+ category="po",
+ description="LIMBU QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x1945,
+ },
+ [0x1946]={
+ category="nd",
+ description="LIMBU DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1946,
+ },
+ [0x1947]={
+ category="nd",
+ description="LIMBU DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1947,
+ },
+ [0x1948]={
+ category="nd",
+ description="LIMBU DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1948,
+ },
+ [0x1949]={
+ category="nd",
+ description="LIMBU DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1949,
+ },
+ [0x194A]={
+ category="nd",
+ description="LIMBU DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194A,
+ },
+ [0x194B]={
+ category="nd",
+ description="LIMBU DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194B,
+ },
+ [0x194C]={
+ category="nd",
+ description="LIMBU DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194C,
+ },
+ [0x194D]={
+ category="nd",
+ description="LIMBU DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194D,
+ },
+ [0x194E]={
+ category="nd",
+ description="LIMBU DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194E,
+ },
+ [0x194F]={
+ category="nd",
+ description="LIMBU DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x194F,
+ },
+ [0x1950]={
+ category="lo",
+ description="TAI LE LETTER KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1950,
+ },
+ [0x1951]={
+ category="lo",
+ description="TAI LE LETTER XA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1951,
+ },
+ [0x1952]={
+ category="lo",
+ description="TAI LE LETTER NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1952,
+ },
+ [0x1953]={
+ category="lo",
+ description="TAI LE LETTER TSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1953,
+ },
+ [0x1954]={
+ category="lo",
+ description="TAI LE LETTER SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1954,
+ },
+ [0x1955]={
+ category="lo",
+ description="TAI LE LETTER YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1955,
+ },
+ [0x1956]={
+ category="lo",
+ description="TAI LE LETTER TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1956,
+ },
+ [0x1957]={
+ category="lo",
+ description="TAI LE LETTER THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1957,
+ },
+ [0x1958]={
+ category="lo",
+ description="TAI LE LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1958,
+ },
+ [0x1959]={
+ category="lo",
+ description="TAI LE LETTER PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1959,
+ },
+ [0x195A]={
+ category="lo",
+ description="TAI LE LETTER PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195A,
+ },
+ [0x195B]={
+ category="lo",
+ description="TAI LE LETTER MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195B,
+ },
+ [0x195C]={
+ category="lo",
+ description="TAI LE LETTER FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195C,
+ },
+ [0x195D]={
+ category="lo",
+ description="TAI LE LETTER VA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195D,
+ },
+ [0x195E]={
+ category="lo",
+ description="TAI LE LETTER HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195E,
+ },
+ [0x195F]={
+ category="lo",
+ description="TAI LE LETTER QA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x195F,
+ },
+ [0x1960]={
+ category="lo",
+ description="TAI LE LETTER KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1960,
+ },
+ [0x1961]={
+ category="lo",
+ description="TAI LE LETTER TSHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1961,
+ },
+ [0x1962]={
+ category="lo",
+ description="TAI LE LETTER NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1962,
+ },
+ [0x1963]={
+ category="lo",
+ description="TAI LE LETTER A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1963,
+ },
+ [0x1964]={
+ category="lo",
+ description="TAI LE LETTER I",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1964,
+ },
+ [0x1965]={
+ category="lo",
+ description="TAI LE LETTER EE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1965,
+ },
+ [0x1966]={
+ category="lo",
+ description="TAI LE LETTER EH",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1966,
+ },
+ [0x1967]={
+ category="lo",
+ description="TAI LE LETTER U",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1967,
+ },
+ [0x1968]={
+ category="lo",
+ description="TAI LE LETTER OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1968,
+ },
+ [0x1969]={
+ category="lo",
+ description="TAI LE LETTER O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1969,
+ },
+ [0x196A]={
+ category="lo",
+ description="TAI LE LETTER UE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x196A,
+ },
+ [0x196B]={
+ category="lo",
+ description="TAI LE LETTER E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x196B,
+ },
+ [0x196C]={
+ category="lo",
+ description="TAI LE LETTER AUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x196C,
+ },
+ [0x196D]={
+ category="lo",
+ description="TAI LE LETTER AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x196D,
+ },
+ [0x1970]={
+ category="lo",
+ description="TAI LE LETTER TONE-0x0002",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1970,
+ },
+ [0x1971]={
+ category="lo",
+ description="TAI LE LETTER TONE-0x0003",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1971,
+ },
+ [0x1972]={
+ category="lo",
+ description="TAI LE LETTER TONE-0x0004",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1972,
+ },
+ [0x1973]={
+ category="lo",
+ description="TAI LE LETTER TONE-0x0005",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1973,
+ },
+ [0x1974]={
+ category="lo",
+ description="TAI LE LETTER TONE-0x0006",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1974,
+ },
+ [0x1980]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH QA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1980,
+ },
+ [0x1981]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW QA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1981,
+ },
+ [0x1982]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1982,
+ },
+ [0x1983]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH XA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1983,
+ },
+ [0x1984]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1984,
+ },
+ [0x1985]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1985,
+ },
+ [0x1986]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW XA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1986,
+ },
+ [0x1987]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1987,
+ },
+ [0x1988]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH TSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1988,
+ },
+ [0x1989]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1989,
+ },
+ [0x198A]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198A,
+ },
+ [0x198B]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW TSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198B,
+ },
+ [0x198C]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198C,
+ },
+ [0x198D]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198D,
+ },
+ [0x198E]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198E,
+ },
+ [0x198F]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x198F,
+ },
+ [0x1990]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1990,
+ },
+ [0x1991]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1991,
+ },
+ [0x1992]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1992,
+ },
+ [0x1993]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1993,
+ },
+ [0x1994]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1994,
+ },
+ [0x1995]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1995,
+ },
+ [0x1996]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1996,
+ },
+ [0x1997]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1997,
+ },
+ [0x1998]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1998,
+ },
+ [0x1999]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1999,
+ },
+ [0x199A]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199A,
+ },
+ [0x199B]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH VA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199B,
+ },
+ [0x199C]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199C,
+ },
+ [0x199D]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199D,
+ },
+ [0x199E]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW VA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199E,
+ },
+ [0x199F]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x199F,
+ },
+ [0x19A0]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A0,
+ },
+ [0x19A1]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A1,
+ },
+ [0x19A2]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A2,
+ },
+ [0x19A3]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A3,
+ },
+ [0x19A4]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A4,
+ },
+ [0x19A5]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A5,
+ },
+ [0x19A6]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH KVA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A6,
+ },
+ [0x19A7]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH XVA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A7,
+ },
+ [0x19A8]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW KVA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A8,
+ },
+ [0x19A9]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW XVA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19A9,
+ },
+ [0x19AA]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH SUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19AA,
+ },
+ [0x19AB]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW SUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19AB,
+ },
+ [0x19B0]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN VOWEL SHORTENER",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B0,
+ },
+ [0x19B1]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B1,
+ },
+ [0x19B2]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN II",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B2,
+ },
+ [0x19B3]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN U",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B3,
+ },
+ [0x19B4]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN UU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B4,
+ },
+ [0x19B5]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B5,
+ },
+ [0x19B6]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN AE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B6,
+ },
+ [0x19B7]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B7,
+ },
+ [0x19B8]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN OA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B8,
+ },
+ [0x19B9]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN UE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19B9,
+ },
+ [0x19BA]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN AY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BA,
+ },
+ [0x19BB]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN AAY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BB,
+ },
+ [0x19BC]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN UY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BC,
+ },
+ [0x19BD]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN OY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BD,
+ },
+ [0x19BE]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN OAY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BE,
+ },
+ [0x19BF]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN UEY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19BF,
+ },
+ [0x19C0]={
+ category="mc",
+ description="NEW TAI LUE VOWEL SIGN IY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C0,
+ },
+ [0x19C1]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL V",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C1,
+ },
+ [0x19C2]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL NG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C2,
+ },
+ [0x19C3]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL N",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C3,
+ },
+ [0x19C4]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL M",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C4,
+ },
+ [0x19C5]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL K",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C5,
+ },
+ [0x19C6]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL D",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C6,
+ },
+ [0x19C7]={
+ category="lo",
+ description="NEW TAI LUE LETTER FINAL B",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C7,
+ },
+ [0x19C8]={
+ category="mc",
+ description="NEW TAI LUE TONE MARK-0x0001",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C8,
+ },
+ [0x19C9]={
+ category="mc",
+ description="NEW TAI LUE TONE MARK-0x0002",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19C9,
+ },
+ [0x19D0]={
+ category="nd",
+ description="NEW TAI LUE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D0,
+ },
+ [0x19D1]={
+ category="nd",
+ description="NEW TAI LUE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D1,
+ },
+ [0x19D2]={
+ category="nd",
+ description="NEW TAI LUE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D2,
+ },
+ [0x19D3]={
+ category="nd",
+ description="NEW TAI LUE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D3,
+ },
+ [0x19D4]={
+ category="nd",
+ description="NEW TAI LUE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D4,
+ },
+ [0x19D5]={
+ category="nd",
+ description="NEW TAI LUE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D5,
+ },
+ [0x19D6]={
+ category="nd",
+ description="NEW TAI LUE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D6,
+ },
+ [0x19D7]={
+ category="nd",
+ description="NEW TAI LUE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D7,
+ },
+ [0x19D8]={
+ category="nd",
+ description="NEW TAI LUE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D8,
+ },
+ [0x19D9]={
+ category="nd",
+ description="NEW TAI LUE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x19D9,
+ },
+ [0x19DA]={
+ category="no",
+ description="NEW TAI LUE THAM DIGIT ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19DA,
+ },
+ [0x19DE]={
+ category="po",
+ description="NEW TAI LUE SIGN LAE",
+ direction="on",
+ linebreak="sa",
+ unicodeslot=0x19DE,
+ },
+ [0x19DF]={
+ category="po",
+ description="NEW TAI LUE SIGN LAEV",
+ direction="on",
+ linebreak="sa",
+ unicodeslot=0x19DF,
+ },
+ [0x19E0]={
+ category="so",
+ description="KHMER SYMBOL PATHAMASAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E0,
+ },
+ [0x19E1]={
+ category="so",
+ description="KHMER SYMBOL MUOY KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E1,
+ },
+ [0x19E2]={
+ category="so",
+ description="KHMER SYMBOL PII KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E2,
+ },
+ [0x19E3]={
+ category="so",
+ description="KHMER SYMBOL BEI KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E3,
+ },
+ [0x19E4]={
+ category="so",
+ description="KHMER SYMBOL BUON KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E4,
+ },
+ [0x19E5]={
+ category="so",
+ description="KHMER SYMBOL PRAM KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E5,
+ },
+ [0x19E6]={
+ category="so",
+ description="KHMER SYMBOL PRAM-MUOY KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E6,
+ },
+ [0x19E7]={
+ category="so",
+ description="KHMER SYMBOL PRAM-PII KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E7,
+ },
+ [0x19E8]={
+ category="so",
+ description="KHMER SYMBOL PRAM-BEI KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E8,
+ },
+ [0x19E9]={
+ category="so",
+ description="KHMER SYMBOL PRAM-BUON KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19E9,
+ },
+ [0x19EA]={
+ category="so",
+ description="KHMER SYMBOL DAP KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19EA,
+ },
+ [0x19EB]={
+ category="so",
+ description="KHMER SYMBOL DAP-MUOY KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19EB,
+ },
+ [0x19EC]={
+ category="so",
+ description="KHMER SYMBOL DAP-PII KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19EC,
+ },
+ [0x19ED]={
+ category="so",
+ description="KHMER SYMBOL DAP-BEI KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19ED,
+ },
+ [0x19EE]={
+ category="so",
+ description="KHMER SYMBOL DAP-BUON KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19EE,
+ },
+ [0x19EF]={
+ category="so",
+ description="KHMER SYMBOL DAP-PRAM KOET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19EF,
+ },
+ [0x19F0]={
+ category="so",
+ description="KHMER SYMBOL TUTEYASAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F0,
+ },
+ [0x19F1]={
+ category="so",
+ description="KHMER SYMBOL MUOY ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F1,
+ },
+ [0x19F2]={
+ category="so",
+ description="KHMER SYMBOL PII ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F2,
+ },
+ [0x19F3]={
+ category="so",
+ description="KHMER SYMBOL BEI ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F3,
+ },
+ [0x19F4]={
+ category="so",
+ description="KHMER SYMBOL BUON ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F4,
+ },
+ [0x19F5]={
+ category="so",
+ description="KHMER SYMBOL PRAM ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F5,
+ },
+ [0x19F6]={
+ category="so",
+ description="KHMER SYMBOL PRAM-MUOY ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F6,
+ },
+ [0x19F7]={
+ category="so",
+ description="KHMER SYMBOL PRAM-PII ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F7,
+ },
+ [0x19F8]={
+ category="so",
+ description="KHMER SYMBOL PRAM-BEI ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F8,
+ },
+ [0x19F9]={
+ category="so",
+ description="KHMER SYMBOL PRAM-BUON ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19F9,
+ },
+ [0x19FA]={
+ category="so",
+ description="KHMER SYMBOL DAP ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FA,
+ },
+ [0x19FB]={
+ category="so",
+ description="KHMER SYMBOL DAP-MUOY ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FB,
+ },
+ [0x19FC]={
+ category="so",
+ description="KHMER SYMBOL DAP-PII ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FC,
+ },
+ [0x19FD]={
+ category="so",
+ description="KHMER SYMBOL DAP-BEI ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FD,
+ },
+ [0x19FE]={
+ category="so",
+ description="KHMER SYMBOL DAP-BUON ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FE,
+ },
+ [0x19FF]={
+ category="so",
+ description="KHMER SYMBOL DAP-PRAM ROC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x19FF,
+ },
+ [0x1A00]={
+ category="lo",
+ description="BUGINESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A00,
+ },
+ [0x1A01]={
+ category="lo",
+ description="BUGINESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A01,
+ },
+ [0x1A02]={
+ category="lo",
+ description="BUGINESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A02,
+ },
+ [0x1A03]={
+ category="lo",
+ description="BUGINESE LETTER NGKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A03,
+ },
+ [0x1A04]={
+ category="lo",
+ description="BUGINESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A04,
+ },
+ [0x1A05]={
+ category="lo",
+ description="BUGINESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A05,
+ },
+ [0x1A06]={
+ category="lo",
+ description="BUGINESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A06,
+ },
+ [0x1A07]={
+ category="lo",
+ description="BUGINESE LETTER MPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A07,
+ },
+ [0x1A08]={
+ category="lo",
+ description="BUGINESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A08,
+ },
+ [0x1A09]={
+ category="lo",
+ description="BUGINESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A09,
+ },
+ [0x1A0A]={
+ category="lo",
+ description="BUGINESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0A,
+ },
+ [0x1A0B]={
+ category="lo",
+ description="BUGINESE LETTER NRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0B,
+ },
+ [0x1A0C]={
+ category="lo",
+ description="BUGINESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0C,
+ },
+ [0x1A0D]={
+ category="lo",
+ description="BUGINESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0D,
+ },
+ [0x1A0E]={
+ category="lo",
+ description="BUGINESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0E,
+ },
+ [0x1A0F]={
+ category="lo",
+ description="BUGINESE LETTER NYCA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A0F,
+ },
+ [0x1A10]={
+ category="lo",
+ description="BUGINESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A10,
+ },
+ [0x1A11]={
+ category="lo",
+ description="BUGINESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A11,
+ },
+ [0x1A12]={
+ category="lo",
+ description="BUGINESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A12,
+ },
+ [0x1A13]={
+ category="lo",
+ description="BUGINESE LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A13,
+ },
+ [0x1A14]={
+ category="lo",
+ description="BUGINESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A14,
+ },
+ [0x1A15]={
+ category="lo",
+ description="BUGINESE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A15,
+ },
+ [0x1A16]={
+ category="lo",
+ description="BUGINESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A16,
+ },
+ [0x1A17]={
+ category="mn",
+ combining=0xE6,
+ description="BUGINESE VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1A17,
+ },
+ [0x1A18]={
+ category="mn",
+ combining=0xDC,
+ description="BUGINESE VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1A18,
+ },
+ [0x1A19]={
+ category="mc",
+ description="BUGINESE VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1A19,
+ },
+ [0x1A1A]={
+ category="mc",
+ description="BUGINESE VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1A1A,
+ },
+ [0x1A1B]={
+ category="mc",
+ description="BUGINESE VOWEL SIGN AE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1A1B,
+ },
+ [0x1A1E]={
+ category="po",
+ description="BUGINESE PALLAWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A1E,
+ },
+ [0x1A1F]={
+ category="po",
+ description="BUGINESE END OF SECTION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1A1F,
+ },
+ [0x1A20]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A20,
+ },
+ [0x1A21]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A21,
+ },
+ [0x1A22]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KXA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A22,
+ },
+ [0x1A23]={
+ category="lo",
+ description="TAI THAM LETTER LOW KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A23,
+ },
+ [0x1A24]={
+ category="lo",
+ description="TAI THAM LETTER LOW KXA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A24,
+ },
+ [0x1A25]={
+ category="lo",
+ description="TAI THAM LETTER LOW KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A25,
+ },
+ [0x1A26]={
+ category="lo",
+ description="TAI THAM LETTER NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A26,
+ },
+ [0x1A27]={
+ category="lo",
+ description="TAI THAM LETTER HIGH CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A27,
+ },
+ [0x1A28]={
+ category="lo",
+ description="TAI THAM LETTER HIGH CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A28,
+ },
+ [0x1A29]={
+ category="lo",
+ description="TAI THAM LETTER LOW CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A29,
+ },
+ [0x1A2A]={
+ category="lo",
+ description="TAI THAM LETTER LOW SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2A,
+ },
+ [0x1A2B]={
+ category="lo",
+ description="TAI THAM LETTER LOW CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2B,
+ },
+ [0x1A2C]={
+ category="lo",
+ description="TAI THAM LETTER NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2C,
+ },
+ [0x1A2D]={
+ category="lo",
+ description="TAI THAM LETTER RATA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2D,
+ },
+ [0x1A2E]={
+ category="lo",
+ description="TAI THAM LETTER HIGH RATHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2E,
+ },
+ [0x1A2F]={
+ category="lo",
+ description="TAI THAM LETTER DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2F,
+ },
+ [0x1A30]={
+ category="lo",
+ description="TAI THAM LETTER LOW RATHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A30,
+ },
+ [0x1A31]={
+ category="lo",
+ description="TAI THAM LETTER RANA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A31,
+ },
+ [0x1A32]={
+ category="lo",
+ description="TAI THAM LETTER HIGH TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A32,
+ },
+ [0x1A33]={
+ category="lo",
+ description="TAI THAM LETTER HIGH THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A33,
+ },
+ [0x1A34]={
+ category="lo",
+ description="TAI THAM LETTER LOW TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A34,
+ },
+ [0x1A35]={
+ category="lo",
+ description="TAI THAM LETTER LOW THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A35,
+ },
+ [0x1A36]={
+ category="lo",
+ description="TAI THAM LETTER NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A36,
+ },
+ [0x1A37]={
+ category="lo",
+ description="TAI THAM LETTER BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A37,
+ },
+ [0x1A38]={
+ category="lo",
+ description="TAI THAM LETTER HIGH PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A38,
+ },
+ [0x1A39]={
+ category="lo",
+ description="TAI THAM LETTER HIGH PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A39,
+ },
+ [0x1A3A]={
+ category="lo",
+ description="TAI THAM LETTER HIGH FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3A,
+ },
+ [0x1A3B]={
+ category="lo",
+ description="TAI THAM LETTER LOW PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3B,
+ },
+ [0x1A3C]={
+ category="lo",
+ description="TAI THAM LETTER LOW FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3C,
+ },
+ [0x1A3D]={
+ category="lo",
+ description="TAI THAM LETTER LOW PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3D,
+ },
+ [0x1A3E]={
+ category="lo",
+ description="TAI THAM LETTER MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3E,
+ },
+ [0x1A3F]={
+ category="lo",
+ description="TAI THAM LETTER LOW YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3F,
+ },
+ [0x1A40]={
+ category="lo",
+ description="TAI THAM LETTER HIGH YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A40,
+ },
+ [0x1A41]={
+ category="lo",
+ description="TAI THAM LETTER RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A41,
+ },
+ [0x1A42]={
+ category="lo",
+ description="TAI THAM LETTER RUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A42,
+ },
+ [0x1A43]={
+ category="lo",
+ description="TAI THAM LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A43,
+ },
+ [0x1A44]={
+ category="lo",
+ description="TAI THAM LETTER LUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A44,
+ },
+ [0x1A45]={
+ category="lo",
+ description="TAI THAM LETTER WA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A45,
+ },
+ [0x1A46]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A46,
+ },
+ [0x1A47]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A47,
+ },
+ [0x1A48]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A48,
+ },
+ [0x1A49]={
+ category="lo",
+ description="TAI THAM LETTER HIGH HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A49,
+ },
+ [0x1A4A]={
+ category="lo",
+ description="TAI THAM LETTER LLA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4A,
+ },
+ [0x1A4B]={
+ category="lo",
+ description="TAI THAM LETTER A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4B,
+ },
+ [0x1A4C]={
+ category="lo",
+ description="TAI THAM LETTER LOW HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4C,
+ },
+ [0x1A4D]={
+ category="lo",
+ description="TAI THAM LETTER I",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4D,
+ },
+ [0x1A4E]={
+ category="lo",
+ description="TAI THAM LETTER II",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4E,
+ },
+ [0x1A4F]={
+ category="lo",
+ description="TAI THAM LETTER U",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4F,
+ },
+ [0x1A50]={
+ category="lo",
+ description="TAI THAM LETTER UU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A50,
+ },
+ [0x1A51]={
+ category="lo",
+ description="TAI THAM LETTER EE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A51,
+ },
+ [0x1A52]={
+ category="lo",
+ description="TAI THAM LETTER OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A52,
+ },
+ [0x1A53]={
+ category="lo",
+ description="TAI THAM LETTER LAE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A53,
+ },
+ [0x1A54]={
+ category="lo",
+ description="TAI THAM LETTER GREAT SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A54,
+ },
+ [0x1A55]={
+ category="mc",
+ description="TAI THAM CONSONANT SIGN MEDIAL RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A55,
+ },
+ [0x1A56]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN MEDIAL LA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A56,
+ },
+ [0x1A57]={
+ category="mc",
+ description="TAI THAM CONSONANT SIGN LA TANG LAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A57,
+ },
+ [0x1A58]={
+ category="mn",
+ description="TAI THAM SIGN MAI KANG LAI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A58,
+ },
+ [0x1A59]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN FINAL NGA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A59,
+ },
+ [0x1A5A]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN LOW PA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5A,
+ },
+ [0x1A5B]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5B,
+ },
+ [0x1A5C]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN MA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5C,
+ },
+ [0x1A5D]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN BA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5D,
+ },
+ [0x1A5E]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN SA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5E,
+ },
+ [0x1A60]={
+ category="mn",
+ combining=0x9,
+ description="TAI THAM SIGN SAKOT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A60,
+ },
+ [0x1A61]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A61,
+ },
+ [0x1A62]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN MAI SAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A62,
+ },
+ [0x1A63]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A63,
+ },
+ [0x1A64]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN TALL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A64,
+ },
+ [0x1A65]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A65,
+ },
+ [0x1A66]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A66,
+ },
+ [0x1A67]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A67,
+ },
+ [0x1A68]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UUE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A68,
+ },
+ [0x1A69]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A69,
+ },
+ [0x1A6A]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6A,
+ },
+ [0x1A6B]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN O",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6B,
+ },
+ [0x1A6C]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN OA BELOW",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6C,
+ },
+ [0x1A6D]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN OY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6D,
+ },
+ [0x1A6E]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6E,
+ },
+ [0x1A6F]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6F,
+ },
+ [0x1A70]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A70,
+ },
+ [0x1A71]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A71,
+ },
+ [0x1A72]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN THAM AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A72,
+ },
+ [0x1A73]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN OA ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A73,
+ },
+ [0x1A74]={
+ category="mn",
+ description="TAI THAM SIGN MAI KANG",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A74,
+ },
+ [0x1A75]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN TONE-1",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A75,
+ },
+ [0x1A76]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN TONE-2",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A76,
+ },
+ [0x1A77]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN KHUEN TONE-3",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A77,
+ },
+ [0x1A78]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN KHUEN TONE-4",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A78,
+ },
+ [0x1A79]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN KHUEN TONE-5",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A79,
+ },
+ [0x1A7A]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN RA HAAM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7A,
+ },
+ [0x1A7B]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN MAI SAM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7B,
+ },
+ [0x1A7C]={
+ category="mn",
+ combining=0xE6,
+ description="TAI THAM SIGN KHUEN-LUE KARAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7C,
+ },
+ [0x1A7F]={
+ category="mn",
+ combining=0xDC,
+ description="TAI THAM COMBINING CRYPTOGRAMMIC DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1A7F,
+ },
+ [0x1A80]={
+ category="nd",
+ description="TAI THAM HORA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A80,
+ },
+ [0x1A81]={
+ category="nd",
+ description="TAI THAM HORA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A81,
+ },
+ [0x1A82]={
+ category="nd",
+ description="TAI THAM HORA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A82,
+ },
+ [0x1A83]={
+ category="nd",
+ description="TAI THAM HORA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A83,
+ },
+ [0x1A84]={
+ category="nd",
+ description="TAI THAM HORA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A84,
+ },
+ [0x1A85]={
+ category="nd",
+ description="TAI THAM HORA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A85,
+ },
+ [0x1A86]={
+ category="nd",
+ description="TAI THAM HORA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A86,
+ },
+ [0x1A87]={
+ category="nd",
+ description="TAI THAM HORA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A87,
+ },
+ [0x1A88]={
+ category="nd",
+ description="TAI THAM HORA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A88,
+ },
+ [0x1A89]={
+ category="nd",
+ description="TAI THAM HORA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A89,
+ },
+ [0x1A90]={
+ category="nd",
+ description="TAI THAM THAM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A90,
+ },
+ [0x1A91]={
+ category="nd",
+ description="TAI THAM THAM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A91,
+ },
+ [0x1A92]={
+ category="nd",
+ description="TAI THAM THAM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A92,
+ },
+ [0x1A93]={
+ category="nd",
+ description="TAI THAM THAM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A93,
+ },
+ [0x1A94]={
+ category="nd",
+ description="TAI THAM THAM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A94,
+ },
+ [0x1A95]={
+ category="nd",
+ description="TAI THAM THAM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A95,
+ },
+ [0x1A96]={
+ category="nd",
+ description="TAI THAM THAM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A96,
+ },
+ [0x1A97]={
+ category="nd",
+ description="TAI THAM THAM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A97,
+ },
+ [0x1A98]={
+ category="nd",
+ description="TAI THAM THAM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A98,
+ },
+ [0x1A99]={
+ category="nd",
+ description="TAI THAM THAM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A99,
+ },
+ [0x1AA0]={
+ category="po",
+ description="TAI THAM SIGN WIANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA0,
+ },
+ [0x1AA1]={
+ category="po",
+ description="TAI THAM SIGN WIANGWAAK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA1,
+ },
+ [0x1AA2]={
+ category="po",
+ description="TAI THAM SIGN SAWAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA2,
+ },
+ [0x1AA3]={
+ category="po",
+ description="TAI THAM SIGN KEOW",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA3,
+ },
+ [0x1AA4]={
+ category="po",
+ description="TAI THAM SIGN HOY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA4,
+ },
+ [0x1AA5]={
+ category="po",
+ description="TAI THAM SIGN DOKMAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA5,
+ },
+ [0x1AA6]={
+ category="po",
+ description="TAI THAM SIGN REVERSED ROTATED RANA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA6,
+ },
+ [0x1AA7]={
+ category="lm",
+ description="TAI THAM SIGN MAI YAMOK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA7,
+ },
+ [0x1AA8]={
+ category="po",
+ description="TAI THAM SIGN KAAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA8,
+ },
+ [0x1AA9]={
+ category="po",
+ description="TAI THAM SIGN KAANKUU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA9,
+ },
+ [0x1AAA]={
+ category="po",
+ description="TAI THAM SIGN SATKAAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAA,
+ },
+ [0x1AAB]={
+ category="po",
+ description="TAI THAM SIGN SATKAANKUU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAB,
+ },
+ [0x1AAC]={
+ category="po",
+ description="TAI THAM SIGN HANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAC,
+ },
+ [0x1AAD]={
+ category="po",
+ description="TAI THAM SIGN CAANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAD,
+ },
+ [0x1AB0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOUBLED CIRCUMFLEX ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB0,
+ },
+ [0x1AB1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DIAERESIS-RING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB1,
+ },
+ [0x1AB2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING INFINITY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB2,
+ },
+ [0x1AB3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOWNWARDS ARROW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB3,
+ },
+ [0x1AB4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING TRIPLE DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB4,
+ },
+ [0x1AB5]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING X-X BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB5,
+ },
+ [0x1AB6]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING WIGGLY LINE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB6,
+ },
+ [0x1AB7]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING OPEN MARK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB7,
+ },
+ [0x1AB8]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING DOUBLE OPEN MARK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB8,
+ },
+ [0x1AB9]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LIGHT CENTRALIZATION STROKE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1AB9,
+ },
+ [0x1ABA]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING STRONG CENTRALIZATION STROKE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1ABA,
+ },
+ [0x1ABB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING PARENTHESES ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1ABB,
+ },
+ [0x1ABC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOUBLE PARENTHESES ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1ABC,
+ },
+ [0x1ABD]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING PARENTHESES BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1ABD,
+ },
+ [0x1ABE]={
+ category="me",
+ description="COMBINING PARENTHESES OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1ABE,
+ },
+ [0x1B00]={
+ category="mn",
+ description="BALINESE SIGN ULU RICEM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B00,
+ },
+ [0x1B01]={
+ category="mn",
+ description="BALINESE SIGN ULU CANDRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B01,
+ },
+ [0x1B02]={
+ category="mn",
+ description="BALINESE SIGN CECEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B02,
+ },
+ [0x1B03]={
+ category="mn",
+ description="BALINESE SIGN SURANG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B03,
+ },
+ [0x1B04]={
+ category="mc",
+ description="BALINESE SIGN BISAH",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B04,
+ },
+ [0x1B05]={
+ category="lo",
+ description="BALINESE LETTER AKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B05,
+ },
+ [0x1B06]={
+ category="lo",
+ description="BALINESE LETTER AKARA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B05, 0x1B35 },
+ unicodeslot=0x1B06,
+ },
+ [0x1B07]={
+ category="lo",
+ description="BALINESE LETTER IKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B07,
+ },
+ [0x1B08]={
+ category="lo",
+ description="BALINESE LETTER IKARA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B07, 0x1B35 },
+ unicodeslot=0x1B08,
+ },
+ [0x1B09]={
+ category="lo",
+ description="BALINESE LETTER UKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B09,
+ },
+ [0x1B0A]={
+ category="lo",
+ description="BALINESE LETTER UKARA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B09, 0x1B35 },
+ unicodeslot=0x1B0A,
+ },
+ [0x1B0B]={
+ category="lo",
+ description="BALINESE LETTER RA REPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B0B,
+ },
+ [0x1B0C]={
+ category="lo",
+ description="BALINESE LETTER RA REPA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B0B, 0x1B35 },
+ unicodeslot=0x1B0C,
+ },
+ [0x1B0D]={
+ category="lo",
+ description="BALINESE LETTER LA LENGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B0D,
+ },
+ [0x1B0E]={
+ category="lo",
+ description="BALINESE LETTER LA LENGA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B0D, 0x1B35 },
+ unicodeslot=0x1B0E,
+ },
+ [0x1B0F]={
+ category="lo",
+ description="BALINESE LETTER EKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B0F,
+ },
+ [0x1B10]={
+ category="lo",
+ description="BALINESE LETTER AIKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B10,
+ },
+ [0x1B11]={
+ category="lo",
+ description="BALINESE LETTER OKARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B11,
+ },
+ [0x1B12]={
+ category="lo",
+ description="BALINESE LETTER OKARA TEDUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1B11, 0x1B35 },
+ unicodeslot=0x1B12,
+ },
+ [0x1B13]={
+ category="lo",
+ description="BALINESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B13,
+ },
+ [0x1B14]={
+ category="lo",
+ description="BALINESE LETTER KA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B14,
+ },
+ [0x1B15]={
+ category="lo",
+ description="BALINESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B15,
+ },
+ [0x1B16]={
+ category="lo",
+ description="BALINESE LETTER GA GORA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B16,
+ },
+ [0x1B17]={
+ category="lo",
+ description="BALINESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B17,
+ },
+ [0x1B18]={
+ category="lo",
+ description="BALINESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B18,
+ },
+ [0x1B19]={
+ category="lo",
+ description="BALINESE LETTER CA LACA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B19,
+ },
+ [0x1B1A]={
+ category="lo",
+ description="BALINESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1A,
+ },
+ [0x1B1B]={
+ category="lo",
+ description="BALINESE LETTER JA JERA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1B,
+ },
+ [0x1B1C]={
+ category="lo",
+ description="BALINESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1C,
+ },
+ [0x1B1D]={
+ category="lo",
+ description="BALINESE LETTER TA LATIK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1D,
+ },
+ [0x1B1E]={
+ category="lo",
+ description="BALINESE LETTER TA MURDA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1E,
+ },
+ [0x1B1F]={
+ category="lo",
+ description="BALINESE LETTER DA MURDA ALPAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B1F,
+ },
+ [0x1B20]={
+ category="lo",
+ description="BALINESE LETTER DA MURDA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B20,
+ },
+ [0x1B21]={
+ category="lo",
+ description="BALINESE LETTER NA RAMBAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B21,
+ },
+ [0x1B22]={
+ category="lo",
+ description="BALINESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B22,
+ },
+ [0x1B23]={
+ category="lo",
+ description="BALINESE LETTER TA TAWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B23,
+ },
+ [0x1B24]={
+ category="lo",
+ description="BALINESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B24,
+ },
+ [0x1B25]={
+ category="lo",
+ description="BALINESE LETTER DA MADU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B25,
+ },
+ [0x1B26]={
+ category="lo",
+ description="BALINESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B26,
+ },
+ [0x1B27]={
+ category="lo",
+ description="BALINESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B27,
+ },
+ [0x1B28]={
+ category="lo",
+ description="BALINESE LETTER PA KAPAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B28,
+ },
+ [0x1B29]={
+ category="lo",
+ description="BALINESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B29,
+ },
+ [0x1B2A]={
+ category="lo",
+ description="BALINESE LETTER BA KEMBANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2A,
+ },
+ [0x1B2B]={
+ category="lo",
+ description="BALINESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2B,
+ },
+ [0x1B2C]={
+ category="lo",
+ description="BALINESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2C,
+ },
+ [0x1B2D]={
+ category="lo",
+ description="BALINESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2D,
+ },
+ [0x1B2E]={
+ category="lo",
+ description="BALINESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2E,
+ },
+ [0x1B2F]={
+ category="lo",
+ description="BALINESE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B2F,
+ },
+ [0x1B30]={
+ category="lo",
+ description="BALINESE LETTER SA SAGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B30,
+ },
+ [0x1B31]={
+ category="lo",
+ description="BALINESE LETTER SA SAPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B31,
+ },
+ [0x1B32]={
+ category="lo",
+ description="BALINESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B32,
+ },
+ [0x1B33]={
+ category="lo",
+ description="BALINESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B33,
+ },
+ [0x1B34]={
+ category="mn",
+ combining=0x7,
+ description="BALINESE SIGN REREKAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B34,
+ },
+ [0x1B35]={
+ category="mc",
+ description="BALINESE VOWEL SIGN TEDUNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B35,
+ },
+ [0x1B36]={
+ category="mn",
+ description="BALINESE VOWEL SIGN ULU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B36,
+ },
+ [0x1B37]={
+ category="mn",
+ description="BALINESE VOWEL SIGN ULU SARI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B37,
+ },
+ [0x1B38]={
+ category="mn",
+ description="BALINESE VOWEL SIGN SUKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B38,
+ },
+ [0x1B39]={
+ category="mn",
+ description="BALINESE VOWEL SIGN SUKU ILUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B39,
+ },
+ [0x1B3A]={
+ category="mn",
+ description="BALINESE VOWEL SIGN RA REPA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B3A,
+ },
+ [0x1B3B]={
+ category="mc",
+ description="BALINESE VOWEL SIGN RA REPA TEDUNG",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x1B3A, 0x1B35 },
+ unicodeslot=0x1B3B,
+ },
+ [0x1B3C]={
+ category="mn",
+ description="BALINESE VOWEL SIGN LA LENGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B3C,
+ },
+ [0x1B3D]={
+ category="mc",
+ description="BALINESE VOWEL SIGN LA LENGA TEDUNG",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x1B3C, 0x1B35 },
+ unicodeslot=0x1B3D,
+ },
+ [0x1B3E]={
+ category="mc",
+ description="BALINESE VOWEL SIGN TALING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B3E,
+ },
+ [0x1B3F]={
+ category="mc",
+ description="BALINESE VOWEL SIGN TALING REPA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B3F,
+ },
+ [0x1B40]={
+ category="mc",
+ description="BALINESE VOWEL SIGN TALING TEDUNG",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x1B3E, 0x1B35 },
+ unicodeslot=0x1B40,
+ },
+ [0x1B41]={
+ category="mc",
+ description="BALINESE VOWEL SIGN TALING REPA TEDUNG",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x1B3F, 0x1B35 },
+ unicodeslot=0x1B41,
+ },
+ [0x1B42]={
+ category="mn",
+ description="BALINESE VOWEL SIGN PEPET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B42,
+ },
+ [0x1B43]={
+ category="mc",
+ description="BALINESE VOWEL SIGN PEPET TEDUNG",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x1B42, 0x1B35 },
+ unicodeslot=0x1B43,
+ },
+ [0x1B44]={
+ category="mc",
+ combining=0x9,
+ description="BALINESE ADEG ADEG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B44,
+ },
+ [0x1B45]={
+ category="lo",
+ description="BALINESE LETTER KAF SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B45,
+ },
+ [0x1B46]={
+ category="lo",
+ description="BALINESE LETTER KHOT SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B46,
+ },
+ [0x1B47]={
+ category="lo",
+ description="BALINESE LETTER TZIR SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B47,
+ },
+ [0x1B48]={
+ category="lo",
+ description="BALINESE LETTER EF SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B48,
+ },
+ [0x1B49]={
+ category="lo",
+ description="BALINESE LETTER VE SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B49,
+ },
+ [0x1B4A]={
+ category="lo",
+ description="BALINESE LETTER ZAL SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B4A,
+ },
+ [0x1B4B]={
+ category="lo",
+ description="BALINESE LETTER ASYURA SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B4B,
+ },
+ [0x1B50]={
+ category="nd",
+ description="BALINESE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B50,
+ },
+ [0x1B51]={
+ category="nd",
+ description="BALINESE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B51,
+ },
+ [0x1B52]={
+ category="nd",
+ description="BALINESE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B52,
+ },
+ [0x1B53]={
+ category="nd",
+ description="BALINESE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B53,
+ },
+ [0x1B54]={
+ category="nd",
+ description="BALINESE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B54,
+ },
+ [0x1B55]={
+ category="nd",
+ description="BALINESE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B55,
+ },
+ [0x1B56]={
+ category="nd",
+ description="BALINESE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B56,
+ },
+ [0x1B57]={
+ category="nd",
+ description="BALINESE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B57,
+ },
+ [0x1B58]={
+ category="nd",
+ description="BALINESE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B58,
+ },
+ [0x1B59]={
+ category="nd",
+ description="BALINESE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1B59,
+ },
+ [0x1B5A]={
+ category="po",
+ description="BALINESE PANTI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B5A,
+ },
+ [0x1B5B]={
+ category="po",
+ description="BALINESE PAMADA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B5B,
+ },
+ [0x1B5C]={
+ category="po",
+ description="BALINESE WINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B5C,
+ },
+ [0x1B5D]={
+ category="po",
+ description="BALINESE CARIK PAMUNGKAH",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B5D,
+ },
+ [0x1B5E]={
+ category="po",
+ description="BALINESE CARIK SIKI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B5E,
+ },
+ [0x1B5F]={
+ category="po",
+ description="BALINESE CARIK PAREREN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B5F,
+ },
+ [0x1B60]={
+ category="po",
+ description="BALINESE PAMENENG",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1B60,
+ },
+ [0x1B61]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B61,
+ },
+ [0x1B62]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B62,
+ },
+ [0x1B63]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B63,
+ },
+ [0x1B64]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B64,
+ },
+ [0x1B65]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DANG SURANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B65,
+ },
+ [0x1B66]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B66,
+ },
+ [0x1B67]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DAENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B67,
+ },
+ [0x1B68]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DEUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B68,
+ },
+ [0x1B69]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DAING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B69,
+ },
+ [0x1B6A]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL DANG GEDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B6A,
+ },
+ [0x1B6B]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING TEGEH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B6B,
+ },
+ [0x1B6C]={
+ category="mn",
+ combining=0xDC,
+ description="BALINESE MUSICAL SYMBOL COMBINING ENDEP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B6C,
+ },
+ [0x1B6D]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING KEMPUL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B6D,
+ },
+ [0x1B6E]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING KEMPLI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B6E,
+ },
+ [0x1B6F]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING JEGOGAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B6F,
+ },
+ [0x1B70]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B70,
+ },
+ [0x1B71]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B71,
+ },
+ [0x1B72]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING BENDE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B72,
+ },
+ [0x1B73]={
+ category="mn",
+ combining=0xE6,
+ description="BALINESE MUSICAL SYMBOL COMBINING GONG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B73,
+ },
+ [0x1B74]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B74,
+ },
+ [0x1B75]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B75,
+ },
+ [0x1B76]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B76,
+ },
+ [0x1B77]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B77,
+ },
+ [0x1B78]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B78,
+ },
+ [0x1B79]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B79,
+ },
+ [0x1B7A]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B7A,
+ },
+ [0x1B7B]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B7B,
+ },
+ [0x1B7C]={
+ category="so",
+ description="BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B7C,
+ },
+ [0x1B80]={
+ category="mn",
+ description="SUNDANESE SIGN PANYECEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B80,
+ },
+ [0x1B81]={
+ category="mn",
+ description="SUNDANESE SIGN PANGLAYAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B81,
+ },
+ [0x1B82]={
+ category="mc",
+ description="SUNDANESE SIGN PANGWISAD",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B82,
+ },
+ [0x1B83]={
+ category="lo",
+ description="SUNDANESE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B83,
+ },
+ [0x1B84]={
+ category="lo",
+ description="SUNDANESE LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B84,
+ },
+ [0x1B85]={
+ category="lo",
+ description="SUNDANESE LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B85,
+ },
+ [0x1B86]={
+ category="lo",
+ description="SUNDANESE LETTER AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B86,
+ },
+ [0x1B87]={
+ category="lo",
+ description="SUNDANESE LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B87,
+ },
+ [0x1B88]={
+ category="lo",
+ description="SUNDANESE LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B88,
+ },
+ [0x1B89]={
+ category="lo",
+ description="SUNDANESE LETTER EU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B89,
+ },
+ [0x1B8A]={
+ category="lo",
+ description="SUNDANESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8A,
+ },
+ [0x1B8B]={
+ category="lo",
+ description="SUNDANESE LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8B,
+ },
+ [0x1B8C]={
+ category="lo",
+ description="SUNDANESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8C,
+ },
+ [0x1B8D]={
+ category="lo",
+ description="SUNDANESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8D,
+ },
+ [0x1B8E]={
+ category="lo",
+ description="SUNDANESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8E,
+ },
+ [0x1B8F]={
+ category="lo",
+ description="SUNDANESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8F,
+ },
+ [0x1B90]={
+ category="lo",
+ description="SUNDANESE LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B90,
+ },
+ [0x1B91]={
+ category="lo",
+ description="SUNDANESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B91,
+ },
+ [0x1B92]={
+ category="lo",
+ description="SUNDANESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B92,
+ },
+ [0x1B93]={
+ category="lo",
+ description="SUNDANESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B93,
+ },
+ [0x1B94]={
+ category="lo",
+ description="SUNDANESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B94,
+ },
+ [0x1B95]={
+ category="lo",
+ description="SUNDANESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B95,
+ },
+ [0x1B96]={
+ category="lo",
+ description="SUNDANESE LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B96,
+ },
+ [0x1B97]={
+ category="lo",
+ description="SUNDANESE LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B97,
+ },
+ [0x1B98]={
+ category="lo",
+ description="SUNDANESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B98,
+ },
+ [0x1B99]={
+ category="lo",
+ description="SUNDANESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B99,
+ },
+ [0x1B9A]={
+ category="lo",
+ description="SUNDANESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9A,
+ },
+ [0x1B9B]={
+ category="lo",
+ description="SUNDANESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9B,
+ },
+ [0x1B9C]={
+ category="lo",
+ description="SUNDANESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9C,
+ },
+ [0x1B9D]={
+ category="lo",
+ description="SUNDANESE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9D,
+ },
+ [0x1B9E]={
+ category="lo",
+ description="SUNDANESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9E,
+ },
+ [0x1B9F]={
+ category="lo",
+ description="SUNDANESE LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9F,
+ },
+ [0x1BA0]={
+ category="lo",
+ description="SUNDANESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BA0,
+ },
+ [0x1BA1]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PAMINGKAL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA1,
+ },
+ [0x1BA2]={
+ category="mn",
+ description="SUNDANESE CONSONANT SIGN PANYAKRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA2,
+ },
+ [0x1BA3]={
+ category="mn",
+ description="SUNDANESE CONSONANT SIGN PANYIKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA3,
+ },
+ [0x1BA4]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANGHULU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA4,
+ },
+ [0x1BA5]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANYUKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA5,
+ },
+ [0x1BA6]={
+ category="mc",
+ description="SUNDANESE VOWEL SIGN PANAELAENG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA6,
+ },
+ [0x1BA7]={
+ category="mc",
+ description="SUNDANESE VOWEL SIGN PANOLONG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA7,
+ },
+ [0x1BA8]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PAMEPET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA8,
+ },
+ [0x1BA9]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANEULEUNG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA9,
+ },
+ [0x1BAA]={
+ category="mc",
+ combining=0x9,
+ description="SUNDANESE SIGN PAMAAEH",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BAA,
+ },
+ [0x1BAB]={
+ category="mn",
+ combining=0x9,
+ description="SUNDANESE SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BAB,
+ },
+ [0x1BAC]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PASANGAN MA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BAC,
+ },
+ [0x1BAD]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PASANGAN WA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BAD,
+ },
+ [0x1BAE]={
+ category="lo",
+ description="SUNDANESE LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BAE,
+ },
+ [0x1BAF]={
+ category="lo",
+ description="SUNDANESE LETTER SYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BAF,
+ },
+ [0x1BB0]={
+ category="nd",
+ description="SUNDANESE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB0,
+ },
+ [0x1BB1]={
+ category="nd",
+ description="SUNDANESE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB1,
+ },
+ [0x1BB2]={
+ category="nd",
+ description="SUNDANESE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB2,
+ },
+ [0x1BB3]={
+ category="nd",
+ description="SUNDANESE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB3,
+ },
+ [0x1BB4]={
+ category="nd",
+ description="SUNDANESE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB4,
+ },
+ [0x1BB5]={
+ category="nd",
+ description="SUNDANESE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB5,
+ },
+ [0x1BB6]={
+ category="nd",
+ description="SUNDANESE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB6,
+ },
+ [0x1BB7]={
+ category="nd",
+ description="SUNDANESE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB7,
+ },
+ [0x1BB8]={
+ category="nd",
+ description="SUNDANESE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB8,
+ },
+ [0x1BB9]={
+ category="nd",
+ description="SUNDANESE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB9,
+ },
+ [0x1BBA]={
+ category="lo",
+ description="SUNDANESE AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBA,
+ },
+ [0x1BBB]={
+ category="lo",
+ description="SUNDANESE LETTER REU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBB,
+ },
+ [0x1BBC]={
+ category="lo",
+ description="SUNDANESE LETTER LEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBC,
+ },
+ [0x1BBD]={
+ category="lo",
+ description="SUNDANESE LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBD,
+ },
+ [0x1BBE]={
+ category="lo",
+ description="SUNDANESE LETTER FINAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBE,
+ },
+ [0x1BBF]={
+ category="lo",
+ description="SUNDANESE LETTER FINAL M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBF,
+ },
+ [0x1BC0]={
+ category="lo",
+ description="BATAK LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0,
+ },
+ [0x1BC1]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1,
+ },
+ [0x1BC2]={
+ category="lo",
+ description="BATAK LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2,
+ },
+ [0x1BC3]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3,
+ },
+ [0x1BC4]={
+ category="lo",
+ description="BATAK LETTER MANDAILING HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4,
+ },
+ [0x1BC5]={
+ category="lo",
+ description="BATAK LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5,
+ },
+ [0x1BC6]={
+ category="lo",
+ description="BATAK LETTER KARO BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC6,
+ },
+ [0x1BC7]={
+ category="lo",
+ description="BATAK LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC7,
+ },
+ [0x1BC8]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC8,
+ },
+ [0x1BC9]={
+ category="lo",
+ description="BATAK LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC9,
+ },
+ [0x1BCA]={
+ category="lo",
+ description="BATAK LETTER MANDAILING NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCA,
+ },
+ [0x1BCB]={
+ category="lo",
+ description="BATAK LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCB,
+ },
+ [0x1BCC]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCC,
+ },
+ [0x1BCD]={
+ category="lo",
+ description="BATAK LETTER PAKPAK WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCD,
+ },
+ [0x1BCE]={
+ category="lo",
+ description="BATAK LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCE,
+ },
+ [0x1BCF]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCF,
+ },
+ [0x1BD0]={
+ category="lo",
+ description="BATAK LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD0,
+ },
+ [0x1BD1]={
+ category="lo",
+ description="BATAK LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD1,
+ },
+ [0x1BD2]={
+ category="lo",
+ description="BATAK LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD2,
+ },
+ [0x1BD3]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD3,
+ },
+ [0x1BD4]={
+ category="lo",
+ description="BATAK LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD4,
+ },
+ [0x1BD5]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD5,
+ },
+ [0x1BD6]={
+ category="lo",
+ description="BATAK LETTER SOUTHERN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD6,
+ },
+ [0x1BD7]={
+ category="lo",
+ description="BATAK LETTER NORTHERN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD7,
+ },
+ [0x1BD8]={
+ category="lo",
+ description="BATAK LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD8,
+ },
+ [0x1BD9]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD9,
+ },
+ [0x1BDA]={
+ category="lo",
+ description="BATAK LETTER MANDAILING SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDA,
+ },
+ [0x1BDB]={
+ category="lo",
+ description="BATAK LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDB,
+ },
+ [0x1BDC]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDC,
+ },
+ [0x1BDD]={
+ category="lo",
+ description="BATAK LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDD,
+ },
+ [0x1BDE]={
+ category="lo",
+ description="BATAK LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDE,
+ },
+ [0x1BDF]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDF,
+ },
+ [0x1BE0]={
+ category="lo",
+ description="BATAK LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE0,
+ },
+ [0x1BE1]={
+ category="lo",
+ description="BATAK LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE1,
+ },
+ [0x1BE2]={
+ category="lo",
+ description="BATAK LETTER NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE2,
+ },
+ [0x1BE3]={
+ category="lo",
+ description="BATAK LETTER MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE3,
+ },
+ [0x1BE4]={
+ category="lo",
+ description="BATAK LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE4,
+ },
+ [0x1BE5]={
+ category="lo",
+ description="BATAK LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE5,
+ },
+ [0x1BE6]={
+ category="mn",
+ combining=0x7,
+ description="BATAK SIGN TOMPI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE6,
+ },
+ [0x1BE7]={
+ category="mc",
+ description="BATAK VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BE7,
+ },
+ [0x1BE8]={
+ category="mn",
+ description="BATAK VOWEL SIGN PAKPAK E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE8,
+ },
+ [0x1BE9]={
+ category="mn",
+ description="BATAK VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE9,
+ },
+ [0x1BEA]={
+ category="mc",
+ description="BATAK VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEA,
+ },
+ [0x1BEB]={
+ category="mc",
+ description="BATAK VOWEL SIGN KARO I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEB,
+ },
+ [0x1BEC]={
+ category="mc",
+ description="BATAK VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEC,
+ },
+ [0x1BED]={
+ category="mn",
+ description="BATAK VOWEL SIGN KARO O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BED,
+ },
+ [0x1BEE]={
+ category="mc",
+ description="BATAK VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEE,
+ },
+ [0x1BEF]={
+ category="mn",
+ description="BATAK VOWEL SIGN U FOR SIMALUNGUN SA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BEF,
+ },
+ [0x1BF0]={
+ category="mn",
+ description="BATAK CONSONANT SIGN NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BF0,
+ },
+ [0x1BF1]={
+ category="mn",
+ description="BATAK CONSONANT SIGN H",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BF1,
+ },
+ [0x1BF2]={
+ category="mc",
+ combining=0x9,
+ description="BATAK PANGOLAT",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BF2,
+ },
+ [0x1BF3]={
+ category="mc",
+ combining=0x9,
+ description="BATAK PANONGONAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BF3,
+ },
+ [0x1BFC]={
+ category="po",
+ description="BATAK SYMBOL BINDU NA METEK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFC,
+ },
+ [0x1BFD]={
+ category="po",
+ description="BATAK SYMBOL BINDU PINARBORAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFD,
+ },
+ [0x1BFE]={
+ category="po",
+ description="BATAK SYMBOL BINDU JUDUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFE,
+ },
+ [0x1BFF]={
+ category="po",
+ description="BATAK SYMBOL BINDU PANGOLAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFF,
+ },
+ [0x1C00]={
+ category="lo",
+ description="LEPCHA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C00,
+ },
+ [0x1C01]={
+ category="lo",
+ description="LEPCHA LETTER KLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C01,
+ },
+ [0x1C02]={
+ category="lo",
+ description="LEPCHA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C02,
+ },
+ [0x1C03]={
+ category="lo",
+ description="LEPCHA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C03,
+ },
+ [0x1C04]={
+ category="lo",
+ description="LEPCHA LETTER GLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C04,
+ },
+ [0x1C05]={
+ category="lo",
+ description="LEPCHA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C05,
+ },
+ [0x1C06]={
+ category="lo",
+ description="LEPCHA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C06,
+ },
+ [0x1C07]={
+ category="lo",
+ description="LEPCHA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C07,
+ },
+ [0x1C08]={
+ category="lo",
+ description="LEPCHA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C08,
+ },
+ [0x1C09]={
+ category="lo",
+ description="LEPCHA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C09,
+ },
+ [0x1C0A]={
+ category="lo",
+ description="LEPCHA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0A,
+ },
+ [0x1C0B]={
+ category="lo",
+ description="LEPCHA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0B,
+ },
+ [0x1C0C]={
+ category="lo",
+ description="LEPCHA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0C,
+ },
+ [0x1C0D]={
+ category="lo",
+ description="LEPCHA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0D,
+ },
+ [0x1C0E]={
+ category="lo",
+ description="LEPCHA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0E,
+ },
+ [0x1C0F]={
+ category="lo",
+ description="LEPCHA LETTER PLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0F,
+ },
+ [0x1C10]={
+ category="lo",
+ description="LEPCHA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C10,
+ },
+ [0x1C11]={
+ category="lo",
+ description="LEPCHA LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C11,
+ },
+ [0x1C12]={
+ category="lo",
+ description="LEPCHA LETTER FLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C12,
+ },
+ [0x1C13]={
+ category="lo",
+ description="LEPCHA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C13,
+ },
+ [0x1C14]={
+ category="lo",
+ description="LEPCHA LETTER BLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C14,
+ },
+ [0x1C15]={
+ category="lo",
+ description="LEPCHA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C15,
+ },
+ [0x1C16]={
+ category="lo",
+ description="LEPCHA LETTER MLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C16,
+ },
+ [0x1C17]={
+ category="lo",
+ description="LEPCHA LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C17,
+ },
+ [0x1C18]={
+ category="lo",
+ description="LEPCHA LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C18,
+ },
+ [0x1C19]={
+ category="lo",
+ description="LEPCHA LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C19,
+ },
+ [0x1C1A]={
+ category="lo",
+ description="LEPCHA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1A,
+ },
+ [0x1C1B]={
+ category="lo",
+ description="LEPCHA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1B,
+ },
+ [0x1C1C]={
+ category="lo",
+ description="LEPCHA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1C,
+ },
+ [0x1C1D]={
+ category="lo",
+ description="LEPCHA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1D,
+ },
+ [0x1C1E]={
+ category="lo",
+ description="LEPCHA LETTER HLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1E,
+ },
+ [0x1C1F]={
+ category="lo",
+ description="LEPCHA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1F,
+ },
+ [0x1C20]={
+ category="lo",
+ description="LEPCHA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C20,
+ },
+ [0x1C21]={
+ category="lo",
+ description="LEPCHA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C21,
+ },
+ [0x1C22]={
+ category="lo",
+ description="LEPCHA LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C22,
+ },
+ [0x1C23]={
+ category="lo",
+ description="LEPCHA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C23,
+ },
+ [0x1C24]={
+ category="mc",
+ description="LEPCHA SUBJOINED LETTER YA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C24,
+ },
+ [0x1C25]={
+ category="mc",
+ description="LEPCHA SUBJOINED LETTER RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C25,
+ },
+ [0x1C26]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C26,
+ },
+ [0x1C27]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C27,
+ },
+ [0x1C28]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C28,
+ },
+ [0x1C29]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C29,
+ },
+ [0x1C2A]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C2A,
+ },
+ [0x1C2B]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C2B,
+ },
+ [0x1C2C]={
+ category="mn",
+ description="LEPCHA VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2C,
+ },
+ [0x1C2D]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN K",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2D,
+ },
+ [0x1C2E]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2E,
+ },
+ [0x1C2F]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2F,
+ },
+ [0x1C30]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C30,
+ },
+ [0x1C31]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN P",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C31,
+ },
+ [0x1C32]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C32,
+ },
+ [0x1C33]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN T",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C33,
+ },
+ [0x1C34]={
+ category="mc",
+ description="LEPCHA CONSONANT SIGN NYIN-DO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C34,
+ },
+ [0x1C35]={
+ category="mc",
+ description="LEPCHA CONSONANT SIGN KANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C35,
+ },
+ [0x1C36]={
+ category="mn",
+ description="LEPCHA SIGN RAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C36,
+ },
+ [0x1C37]={
+ category="mn",
+ combining=0x7,
+ description="LEPCHA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C37,
+ },
+ [0x1C3B]={
+ category="po",
+ description="LEPCHA PUNCTUATION TA-ROL",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3B,
+ },
+ [0x1C3C]={
+ category="po",
+ description="LEPCHA PUNCTUATION NYET THYOOM TA-ROL",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3C,
+ },
+ [0x1C3D]={
+ category="po",
+ description="LEPCHA PUNCTUATION CER-WA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3D,
+ },
+ [0x1C3E]={
+ category="po",
+ description="LEPCHA PUNCTUATION TSHOOK CER-WA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3E,
+ },
+ [0x1C3F]={
+ category="po",
+ description="LEPCHA PUNCTUATION TSHOOK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3F,
+ },
+ [0x1C40]={
+ category="nd",
+ description="LEPCHA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C40,
+ },
+ [0x1C41]={
+ category="nd",
+ description="LEPCHA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C41,
+ },
+ [0x1C42]={
+ category="nd",
+ description="LEPCHA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C42,
+ },
+ [0x1C43]={
+ category="nd",
+ description="LEPCHA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C43,
+ },
+ [0x1C44]={
+ category="nd",
+ description="LEPCHA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C44,
+ },
+ [0x1C45]={
+ category="nd",
+ description="LEPCHA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C45,
+ },
+ [0x1C46]={
+ category="nd",
+ description="LEPCHA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C46,
+ },
+ [0x1C47]={
+ category="nd",
+ description="LEPCHA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C47,
+ },
+ [0x1C48]={
+ category="nd",
+ description="LEPCHA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C48,
+ },
+ [0x1C49]={
+ category="nd",
+ description="LEPCHA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C49,
+ },
+ [0x1C4D]={
+ category="lo",
+ description="LEPCHA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4D,
+ },
+ [0x1C4E]={
+ category="lo",
+ description="LEPCHA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4E,
+ },
+ [0x1C4F]={
+ category="lo",
+ description="LEPCHA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4F,
+ },
+ [0x1C50]={
+ category="nd",
+ description="OL CHIKI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C50,
+ },
+ [0x1C51]={
+ category="nd",
+ description="OL CHIKI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C51,
+ },
+ [0x1C52]={
+ category="nd",
+ description="OL CHIKI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C52,
+ },
+ [0x1C53]={
+ category="nd",
+ description="OL CHIKI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C53,
+ },
+ [0x1C54]={
+ category="nd",
+ description="OL CHIKI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C54,
+ },
+ [0x1C55]={
+ category="nd",
+ description="OL CHIKI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C55,
+ },
+ [0x1C56]={
+ category="nd",
+ description="OL CHIKI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C56,
+ },
+ [0x1C57]={
+ category="nd",
+ description="OL CHIKI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C57,
+ },
+ [0x1C58]={
+ category="nd",
+ description="OL CHIKI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C58,
+ },
+ [0x1C59]={
+ category="nd",
+ description="OL CHIKI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C59,
+ },
+ [0x1C5A]={
+ category="lo",
+ description="OL CHIKI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5A,
+ },
+ [0x1C5B]={
+ category="lo",
+ description="OL CHIKI LETTER AT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5B,
+ },
+ [0x1C5C]={
+ category="lo",
+ description="OL CHIKI LETTER AG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5C,
+ },
+ [0x1C5D]={
+ category="lo",
+ description="OL CHIKI LETTER ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5D,
+ },
+ [0x1C5E]={
+ category="lo",
+ description="OL CHIKI LETTER AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5E,
+ },
+ [0x1C5F]={
+ category="lo",
+ description="OL CHIKI LETTER LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5F,
+ },
+ [0x1C60]={
+ category="lo",
+ description="OL CHIKI LETTER AAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C60,
+ },
+ [0x1C61]={
+ category="lo",
+ description="OL CHIKI LETTER AAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C61,
+ },
+ [0x1C62]={
+ category="lo",
+ description="OL CHIKI LETTER AAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C62,
+ },
+ [0x1C63]={
+ category="lo",
+ description="OL CHIKI LETTER AAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C63,
+ },
+ [0x1C64]={
+ category="lo",
+ description="OL CHIKI LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C64,
+ },
+ [0x1C65]={
+ category="lo",
+ description="OL CHIKI LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C65,
+ },
+ [0x1C66]={
+ category="lo",
+ description="OL CHIKI LETTER IH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C66,
+ },
+ [0x1C67]={
+ category="lo",
+ description="OL CHIKI LETTER INY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C67,
+ },
+ [0x1C68]={
+ category="lo",
+ description="OL CHIKI LETTER IR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C68,
+ },
+ [0x1C69]={
+ category="lo",
+ description="OL CHIKI LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C69,
+ },
+ [0x1C6A]={
+ category="lo",
+ description="OL CHIKI LETTER UC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6A,
+ },
+ [0x1C6B]={
+ category="lo",
+ description="OL CHIKI LETTER UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6B,
+ },
+ [0x1C6C]={
+ category="lo",
+ description="OL CHIKI LETTER UNN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6C,
+ },
+ [0x1C6D]={
+ category="lo",
+ description="OL CHIKI LETTER UY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6D,
+ },
+ [0x1C6E]={
+ category="lo",
+ description="OL CHIKI LETTER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6E,
+ },
+ [0x1C6F]={
+ category="lo",
+ description="OL CHIKI LETTER EP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6F,
+ },
+ [0x1C70]={
+ category="lo",
+ description="OL CHIKI LETTER EDD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C70,
+ },
+ [0x1C71]={
+ category="lo",
+ description="OL CHIKI LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C71,
+ },
+ [0x1C72]={
+ category="lo",
+ description="OL CHIKI LETTER ERR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C72,
+ },
+ [0x1C73]={
+ category="lo",
+ description="OL CHIKI LETTER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C73,
+ },
+ [0x1C74]={
+ category="lo",
+ description="OL CHIKI LETTER OTT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C74,
+ },
+ [0x1C75]={
+ category="lo",
+ description="OL CHIKI LETTER OB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C75,
+ },
+ [0x1C76]={
+ category="lo",
+ description="OL CHIKI LETTER OV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C76,
+ },
+ [0x1C77]={
+ category="lo",
+ description="OL CHIKI LETTER OH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C77,
+ },
+ [0x1C78]={
+ category="lm",
+ description="OL CHIKI MU TTUDDAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C78,
+ },
+ [0x1C79]={
+ category="lm",
+ description="OL CHIKI GAAHLAA TTUDDAAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C79,
+ },
+ [0x1C7A]={
+ category="lm",
+ description="OL CHIKI MU-GAAHLAA TTUDDAAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7A,
+ },
+ [0x1C7B]={
+ category="lm",
+ description="OL CHIKI RELAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7B,
+ },
+ [0x1C7C]={
+ category="lm",
+ description="OL CHIKI PHAARKAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7C,
+ },
+ [0x1C7D]={
+ category="lm",
+ description="OL CHIKI AHAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7D,
+ },
+ [0x1C7E]={
+ category="po",
+ description="OL CHIKI PUNCTUATION MUCAAD",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C7E,
+ },
+ [0x1C7F]={
+ category="po",
+ description="OL CHIKI PUNCTUATION DOUBLE MUCAAD",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C7F,
+ },
+ [0x1CC0]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU SURYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC0,
+ },
+ [0x1CC1]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU PANGLONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC1,
+ },
+ [0x1CC2]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU PURNAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC2,
+ },
+ [0x1CC3]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU CAKRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC3,
+ },
+ [0x1CC4]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU LEU SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC4,
+ },
+ [0x1CC5]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU KA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC5,
+ },
+ [0x1CC6]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU DA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC6,
+ },
+ [0x1CC7]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU BA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC7,
+ },
+ [0x1CD0]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE KARSHANA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD0,
+ },
+ [0x1CD1]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE SHARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD1,
+ },
+ [0x1CD2]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE PRENKHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD2,
+ },
+ [0x1CD3]={
+ category="po",
+ description="VEDIC SIGN NIHSHVASA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CD3,
+ },
+ [0x1CD4]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN YAJURVEDIC MIDLINE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD4,
+ },
+ [0x1CD5]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD5,
+ },
+ [0x1CD6]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD6,
+ },
+ [0x1CD7]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD7,
+ },
+ [0x1CD8]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE CANDRA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD8,
+ },
+ [0x1CD9]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD9,
+ },
+ [0x1CDA]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE DOUBLE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDA,
+ },
+ [0x1CDB]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE TRIPLE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDB,
+ },
+ [0x1CDC]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE KATHAKA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDC,
+ },
+ [0x1CDD]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDD,
+ },
+ [0x1CDE]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE TWO DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDE,
+ },
+ [0x1CDF]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC TONE THREE DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDF,
+ },
+ [0x1CE0]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE0,
+ },
+ [0x1CE1]={
+ category="mc",
+ description="VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CE1,
+ },
+ [0x1CE2]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN VISARGA SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE2,
+ },
+ [0x1CE3]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN VISARGA UDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE3,
+ },
+ [0x1CE4]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN REVERSED VISARGA UDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE4,
+ },
+ [0x1CE5]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN VISARGA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE5,
+ },
+ [0x1CE6]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN REVERSED VISARGA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE6,
+ },
+ [0x1CE7]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN VISARGA UDATTA WITH TAIL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE7,
+ },
+ [0x1CE8]={
+ category="mn",
+ combining=0x1,
+ description="VEDIC SIGN VISARGA ANUDATTA WITH TAIL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE8,
+ },
+ [0x1CE9]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA ANTARGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CE9,
+ },
+ [0x1CEA]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA BAHIRGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEA,
+ },
+ [0x1CEB]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA VAMAGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEB,
+ },
+ [0x1CEC]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEC,
+ },
+ [0x1CED]={
+ category="mn",
+ combining=0xDC,
+ description="VEDIC SIGN TIRYAK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CED,
+ },
+ [0x1CEE]={
+ category="lo",
+ description="VEDIC SIGN HEXIFORM LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEE,
+ },
+ [0x1CEF]={
+ category="lo",
+ description="VEDIC SIGN LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEF,
+ },
+ [0x1CF0]={
+ category="lo",
+ description="VEDIC SIGN RTHANG LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF0,
+ },
+ [0x1CF1]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA UBHAYATO MUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF1,
+ },
+ [0x1CF2]={
+ category="mc",
+ description="VEDIC SIGN ARDHAVISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CF2,
+ },
+ [0x1CF3]={
+ category="mc",
+ description="VEDIC SIGN ROTATED ARDHAVISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CF3,
+ },
+ [0x1CF4]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE CANDRA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CF4,
+ },
+ [0x1CF5]={
+ category="lo",
+ description="VEDIC SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF5,
+ },
+ [0x1CF6]={
+ category="lo",
+ description="VEDIC SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF6,
+ },
+ [0x1CF8]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE RING ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CF8,
+ },
+ [0x1CF9]={
+ category="mn",
+ combining=0xE6,
+ description="VEDIC TONE DOUBLE RING ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CF9,
+ },
+ [0x1D00]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00,
+ },
+ [0x1D01]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01,
+ },
+ [0x1D02]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02,
+ },
+ [0x1D03]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL BARRED B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03,
+ },
+ [0x1D04]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04,
+ },
+ [0x1D05]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05,
+ },
+ [0x1D06]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL ETH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06,
+ },
+ [0x1D07]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07,
+ },
+ [0x1D08]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED OPEN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08,
+ },
+ [0x1D09]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09,
+ },
+ [0x1D0A]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A,
+ },
+ [0x1D0B]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B,
+ },
+ [0x1D0C]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL L WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C,
+ },
+ [0x1D0D]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D,
+ },
+ [0x1D0E]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL REVERSED N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E,
+ },
+ [0x1D0F]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F,
+ },
+ [0x1D10]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL OPEN O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10,
+ },
+ [0x1D11]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11,
+ },
+ [0x1D12]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS OPEN O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12,
+ },
+ [0x1D13]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS O WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13,
+ },
+ [0x1D14]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14,
+ },
+ [0x1D15]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL OU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D15,
+ },
+ [0x1D16]={
+ category="ll",
+ description="LATIN SMALL LETTER TOP HALF O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D16,
+ },
+ [0x1D17]={
+ category="ll",
+ description="LATIN SMALL LETTER BOTTOM HALF O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D17,
+ },
+ [0x1D18]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D18,
+ },
+ [0x1D19]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL REVERSED R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19,
+ },
+ [0x1D1A]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL TURNED R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A,
+ },
+ [0x1D1B]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B,
+ },
+ [0x1D1C]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C,
+ },
+ [0x1D1D]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D,
+ },
+ [0x1D1E]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS DIAERESIZED U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E,
+ },
+ [0x1D1F]={
+ category="ll",
+ description="LATIN SMALL LETTER SIDEWAYS TURNED M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1F,
+ },
+ [0x1D20]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D20,
+ },
+ [0x1D21]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D21,
+ },
+ [0x1D22]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D22,
+ },
+ [0x1D23]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL EZH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D23,
+ },
+ [0x1D24]={
+ category="ll",
+ description="LATIN LETTER VOICED LARYNGEAL SPIRANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D24,
+ },
+ [0x1D25]={
+ category="ll",
+ description="LATIN LETTER AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D25,
+ },
+ [0x1D26]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D26,
+ },
+ [0x1D27]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D27,
+ },
+ [0x1D28]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D28,
+ },
+ [0x1D29]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D29,
+ },
+ [0x1D2A]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2A,
+ },
+ [0x1D2B]={
+ category="ll",
+ description="CYRILLIC LETTER SMALL CAPITAL EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2B,
+ },
+ [0x1D2C]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x41 },
+ unicodeslot=0x1D2C,
+ },
+ [0x1D2D]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL AE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xC6 },
+ unicodeslot=0x1D2D,
+ },
+ [0x1D2E]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x42 },
+ unicodeslot=0x1D2E,
+ },
+ [0x1D2F]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL BARRED B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2F,
+ },
+ [0x1D30]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x44 },
+ unicodeslot=0x1D30,
+ },
+ [0x1D31]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x45 },
+ unicodeslot=0x1D31,
+ },
+ [0x1D32]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL REVERSED E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x18E },
+ unicodeslot=0x1D32,
+ },
+ [0x1D33]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x47 },
+ unicodeslot=0x1D33,
+ },
+ [0x1D34]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x48 },
+ unicodeslot=0x1D34,
+ },
+ [0x1D35]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x49 },
+ unicodeslot=0x1D35,
+ },
+ [0x1D36]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4A },
+ unicodeslot=0x1D36,
+ },
+ [0x1D37]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4B },
+ unicodeslot=0x1D37,
+ },
+ [0x1D38]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4C },
+ unicodeslot=0x1D38,
+ },
+ [0x1D39]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4D },
+ unicodeslot=0x1D39,
+ },
+ [0x1D3A]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4E },
+ unicodeslot=0x1D3A,
+ },
+ [0x1D3B]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL REVERSED N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D3B,
+ },
+ [0x1D3C]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x4F },
+ unicodeslot=0x1D3C,
+ },
+ [0x1D3D]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL OU",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x222 },
+ unicodeslot=0x1D3D,
+ },
+ [0x1D3E]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x50 },
+ unicodeslot=0x1D3E,
+ },
+ [0x1D3F]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x52 },
+ unicodeslot=0x1D3F,
+ },
+ [0x1D40]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x54 },
+ unicodeslot=0x1D40,
+ },
+ [0x1D41]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x55 },
+ unicodeslot=0x1D41,
+ },
+ [0x1D42]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x57 },
+ unicodeslot=0x1D42,
+ },
+ [0x1D43]={
+ category="lm",
+ description="MODIFIER LETTER SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x61 },
+ unicodeslot=0x1D43,
+ },
+ [0x1D44]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED A",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x250 },
+ unicodeslot=0x1D44,
+ },
+ [0x1D45]={
+ category="lm",
+ description="MODIFIER LETTER SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x251 },
+ unicodeslot=0x1D45,
+ },
+ [0x1D46]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED AE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D02 },
+ unicodeslot=0x1D46,
+ },
+ [0x1D47]={
+ category="lm",
+ description="MODIFIER LETTER SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x62 },
+ unicodeslot=0x1D47,
+ },
+ [0x1D48]={
+ category="lm",
+ description="MODIFIER LETTER SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x64 },
+ unicodeslot=0x1D48,
+ },
+ [0x1D49]={
+ category="lm",
+ description="MODIFIER LETTER SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x65 },
+ unicodeslot=0x1D49,
+ },
+ [0x1D4A]={
+ category="lm",
+ description="MODIFIER LETTER SMALL SCHWA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x259 },
+ unicodeslot=0x1D4A,
+ },
+ [0x1D4B]={
+ category="lm",
+ description="MODIFIER LETTER SMALL OPEN E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x25B },
+ unicodeslot=0x1D4B,
+ },
+ [0x1D4C]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED OPEN E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x25C },
+ unicodeslot=0x1D4C,
+ },
+ [0x1D4D]={
+ category="lm",
+ description="MODIFIER LETTER SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x67 },
+ unicodeslot=0x1D4D,
+ },
+ [0x1D4E]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D4E,
+ },
+ [0x1D4F]={
+ category="lm",
+ description="MODIFIER LETTER SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x6B },
+ unicodeslot=0x1D4F,
+ },
+ [0x1D50]={
+ category="lm",
+ description="MODIFIER LETTER SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x6D },
+ unicodeslot=0x1D50,
+ },
+ [0x1D51]={
+ category="lm",
+ description="MODIFIER LETTER SMALL ENG",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x14B },
+ unicodeslot=0x1D51,
+ },
+ [0x1D52]={
+ category="lm",
+ description="MODIFIER LETTER SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x6F },
+ unicodeslot=0x1D52,
+ },
+ [0x1D53]={
+ category="lm",
+ description="MODIFIER LETTER SMALL OPEN O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x254 },
+ unicodeslot=0x1D53,
+ },
+ [0x1D54]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TOP HALF O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D16 },
+ unicodeslot=0x1D54,
+ },
+ [0x1D55]={
+ category="lm",
+ description="MODIFIER LETTER SMALL BOTTOM HALF O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D17 },
+ unicodeslot=0x1D55,
+ },
+ [0x1D56]={
+ category="lm",
+ description="MODIFIER LETTER SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x70 },
+ unicodeslot=0x1D56,
+ },
+ [0x1D57]={
+ category="lm",
+ description="MODIFIER LETTER SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x74 },
+ unicodeslot=0x1D57,
+ },
+ [0x1D58]={
+ category="lm",
+ description="MODIFIER LETTER SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x75 },
+ unicodeslot=0x1D58,
+ },
+ [0x1D59]={
+ category="lm",
+ description="MODIFIER LETTER SMALL SIDEWAYS U",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D1D },
+ unicodeslot=0x1D59,
+ },
+ [0x1D5A]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED M",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x26F },
+ unicodeslot=0x1D5A,
+ },
+ [0x1D5B]={
+ category="lm",
+ description="MODIFIER LETTER SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x76 },
+ unicodeslot=0x1D5B,
+ },
+ [0x1D5C]={
+ category="lm",
+ description="MODIFIER LETTER SMALL AIN",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D25 },
+ unicodeslot=0x1D5C,
+ },
+ [0x1D5D]={
+ category="lm",
+ description="MODIFIER LETTER SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3B2 },
+ unicodeslot=0x1D5D,
+ },
+ [0x1D5E]={
+ category="lm",
+ description="MODIFIER LETTER SMALL GREEK GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3B3 },
+ unicodeslot=0x1D5E,
+ },
+ [0x1D5F]={
+ category="lm",
+ description="MODIFIER LETTER SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3B4 },
+ unicodeslot=0x1D5F,
+ },
+ [0x1D60]={
+ category="lm",
+ description="MODIFIER LETTER SMALL GREEK PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3C6 },
+ unicodeslot=0x1D60,
+ },
+ [0x1D61]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3C7 },
+ unicodeslot=0x1D61,
+ },
+ [0x1D62]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x69 },
+ unicodeslot=0x1D62,
+ },
+ [0x1D63]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER R",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x72 },
+ unicodeslot=0x1D63,
+ },
+ [0x1D64]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER U",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x75 },
+ unicodeslot=0x1D64,
+ },
+ [0x1D65]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER V",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x76 },
+ unicodeslot=0x1D65,
+ },
+ [0x1D66]={
+ category="ll",
+ description="GREEK SUBSCRIPT SMALL LETTER BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x3B2 },
+ unicodeslot=0x1D66,
+ },
+ [0x1D67]={
+ category="ll",
+ description="GREEK SUBSCRIPT SMALL LETTER GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x3B3 },
+ unicodeslot=0x1D67,
+ },
+ [0x1D68]={
+ category="ll",
+ description="GREEK SUBSCRIPT SMALL LETTER RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x3C1 },
+ unicodeslot=0x1D68,
+ },
+ [0x1D69]={
+ category="ll",
+ description="GREEK SUBSCRIPT SMALL LETTER PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x3C6 },
+ unicodeslot=0x1D69,
+ },
+ [0x1D6A]={
+ category="ll",
+ description="GREEK SUBSCRIPT SMALL LETTER CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x3C7 },
+ unicodeslot=0x1D6A,
+ },
+ [0x1D6B]={
+ category="ll",
+ description="LATIN SMALL LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D6B,
+ },
+ [0x1D6C]={
+ category="ll",
+ description="LATIN SMALL LETTER B WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ unicodeslot=0x1D6C,
+ },
+ [0x1D6D]={
+ category="ll",
+ description="LATIN SMALL LETTER D WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ unicodeslot=0x1D6D,
+ },
+ [0x1D6E]={
+ category="ll",
+ description="LATIN SMALL LETTER F WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x66,
+ unicodeslot=0x1D6E,
+ },
+ [0x1D6F]={
+ category="ll",
+ description="LATIN SMALL LETTER M WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ unicodeslot=0x1D6F,
+ },
+ [0x1D70]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ unicodeslot=0x1D70,
+ },
+ [0x1D71]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ unicodeslot=0x1D71,
+ },
+ [0x1D72]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ unicodeslot=0x1D72,
+ },
+ [0x1D73]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ unicodeslot=0x1D73,
+ },
+ [0x1D74]={
+ category="ll",
+ description="LATIN SMALL LETTER S WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ unicodeslot=0x1D74,
+ },
+ [0x1D75]={
+ category="ll",
+ description="LATIN SMALL LETTER T WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ unicodeslot=0x1D75,
+ },
+ [0x1D76]={
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ unicodeslot=0x1D76,
+ },
+ [0x1D77]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D77,
+ },
+ [0x1D78]={
+ category="lm",
+ description="MODIFIER LETTER CYRILLIC EN",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x43D },
+ unicodeslot=0x1D78,
+ },
+ [0x1D79]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D79,
+ },
+ [0x1D7A]={
+ category="ll",
+ description="LATIN SMALL LETTER TH WITH STRIKETHROUGH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D7A,
+ },
+ [0x1D7B]={
+ category="ll",
+ description="LATIN SMALL CAPITAL LETTER I WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D7B,
+ },
+ [0x1D7C]={
+ category="ll",
+ description="LATIN SMALL LETTER IOTA WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x269,
+ unicodeslot=0x1D7C,
+ },
+ [0x1D7D]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ uccode=0x2C63,
+ unicodeslot=0x1D7D,
+ },
+ [0x1D7E]={
+ category="ll",
+ description="LATIN SMALL CAPITAL LETTER U WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D7E,
+ },
+ [0x1D7F]={
+ category="ll",
+ description="LATIN SMALL LETTER UPSILON WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x28A,
+ unicodeslot=0x1D7F,
+ },
+ [0x1D80]={
+ category="ll",
+ description="LATIN SMALL LETTER B WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ unicodeslot=0x1D80,
+ },
+ [0x1D81]={
+ category="ll",
+ description="LATIN SMALL LETTER D WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ unicodeslot=0x1D81,
+ },
+ [0x1D82]={
+ category="ll",
+ description="LATIN SMALL LETTER F WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x66,
+ unicodeslot=0x1D82,
+ },
+ [0x1D83]={
+ category="ll",
+ description="LATIN SMALL LETTER G WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ unicodeslot=0x1D83,
+ },
+ [0x1D84]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ unicodeslot=0x1D84,
+ },
+ [0x1D85]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ unicodeslot=0x1D85,
+ },
+ [0x1D86]={
+ category="ll",
+ description="LATIN SMALL LETTER M WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ unicodeslot=0x1D86,
+ },
+ [0x1D87]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ unicodeslot=0x1D87,
+ },
+ [0x1D88]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ unicodeslot=0x1D88,
+ },
+ [0x1D89]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ unicodeslot=0x1D89,
+ },
+ [0x1D8A]={
+ category="ll",
+ description="LATIN SMALL LETTER S WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ unicodeslot=0x1D8A,
+ },
+ [0x1D8B]={
+ category="ll",
+ description="LATIN SMALL LETTER ESH WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x283,
+ unicodeslot=0x1D8B,
+ },
+ [0x1D8C]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x76,
+ unicodeslot=0x1D8C,
+ },
+ [0x1D8D]={
+ category="ll",
+ description="LATIN SMALL LETTER X WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x78,
+ unicodeslot=0x1D8D,
+ },
+ [0x1D8E]={
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ unicodeslot=0x1D8E,
+ },
+ [0x1D8F]={
+ category="ll",
+ description="LATIN SMALL LETTER A WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ unicodeslot=0x1D8F,
+ },
+ [0x1D90]={
+ category="ll",
+ description="LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x251,
+ unicodeslot=0x1D90,
+ },
+ [0x1D91]={
+ category="ll",
+ description="LATIN SMALL LETTER D WITH HOOK AND TAIL",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ unicodeslot=0x1D91,
+ },
+ [0x1D92]={
+ category="ll",
+ description="LATIN SMALL LETTER E WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ unicodeslot=0x1D92,
+ },
+ [0x1D93]={
+ category="ll",
+ description="LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93,
+ },
+ [0x1D94]={
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94,
+ },
+ [0x1D95]={
+ category="ll",
+ description="LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x259,
+ unicodeslot=0x1D95,
+ },
+ [0x1D96]={
+ category="ll",
+ description="LATIN SMALL LETTER I WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ unicodeslot=0x1D96,
+ },
+ [0x1D97]={
+ category="ll",
+ description="LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97,
+ },
+ [0x1D98]={
+ category="ll",
+ description="LATIN SMALL LETTER ESH WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x283,
+ unicodeslot=0x1D98,
+ },
+ [0x1D99]={
+ category="ll",
+ description="LATIN SMALL LETTER U WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ unicodeslot=0x1D99,
+ },
+ [0x1D9A]={
+ category="ll",
+ description="LATIN SMALL LETTER EZH WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ shcode=0x292,
+ unicodeslot=0x1D9A,
+ },
+ [0x1D9B]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x252 },
+ unicodeslot=0x1D9B,
+ },
+ [0x1D9C]={
+ category="lm",
+ description="MODIFIER LETTER SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x63 },
+ unicodeslot=0x1D9C,
+ },
+ [0x1D9D]={
+ category="lm",
+ description="MODIFIER LETTER SMALL C WITH CURL",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x255 },
+ unicodeslot=0x1D9D,
+ },
+ [0x1D9E]={
+ category="lm",
+ description="MODIFIER LETTER SMALL ETH",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xF0 },
+ unicodeslot=0x1D9E,
+ },
+ [0x1D9F]={
+ category="lm",
+ description="MODIFIER LETTER SMALL REVERSED OPEN E",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x25C },
+ unicodeslot=0x1D9F,
+ },
+ [0x1DA0]={
+ category="lm",
+ description="MODIFIER LETTER SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x66 },
+ unicodeslot=0x1DA0,
+ },
+ [0x1DA1]={
+ category="lm",
+ description="MODIFIER LETTER SMALL DOTLESS J WITH STROKE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x25F },
+ unicodeslot=0x1DA1,
+ },
+ [0x1DA2]={
+ category="lm",
+ description="MODIFIER LETTER SMALL SCRIPT G",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x261 },
+ unicodeslot=0x1DA2,
+ },
+ [0x1DA3]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED H",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x265 },
+ unicodeslot=0x1DA3,
+ },
+ [0x1DA4]={
+ category="lm",
+ description="MODIFIER LETTER SMALL I WITH STROKE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x268 },
+ unicodeslot=0x1DA4,
+ },
+ [0x1DA5]={
+ category="lm",
+ description="MODIFIER LETTER SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x269 },
+ unicodeslot=0x1DA5,
+ },
+ [0x1DA6]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x26A },
+ unicodeslot=0x1DA6,
+ },
+ [0x1DA7]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL I WITH STROKE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D7B },
+ unicodeslot=0x1DA7,
+ },
+ [0x1DA8]={
+ category="lm",
+ description="MODIFIER LETTER SMALL J WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x29D },
+ unicodeslot=0x1DA8,
+ },
+ [0x1DA9]={
+ category="lm",
+ description="MODIFIER LETTER SMALL L WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x26D },
+ unicodeslot=0x1DA9,
+ },
+ [0x1DAA]={
+ category="lm",
+ description="MODIFIER LETTER SMALL L WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D85 },
+ unicodeslot=0x1DAA,
+ },
+ [0x1DAB]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x29F },
+ unicodeslot=0x1DAB,
+ },
+ [0x1DAC]={
+ category="lm",
+ description="MODIFIER LETTER SMALL M WITH HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x271 },
+ unicodeslot=0x1DAC,
+ },
+ [0x1DAD]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED M WITH LONG LEG",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x270 },
+ unicodeslot=0x1DAD,
+ },
+ [0x1DAE]={
+ category="lm",
+ description="MODIFIER LETTER SMALL N WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x272 },
+ unicodeslot=0x1DAE,
+ },
+ [0x1DAF]={
+ category="lm",
+ description="MODIFIER LETTER SMALL N WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x273 },
+ unicodeslot=0x1DAF,
+ },
+ [0x1DB0]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x274 },
+ unicodeslot=0x1DB0,
+ },
+ [0x1DB1]={
+ category="lm",
+ description="MODIFIER LETTER SMALL BARRED O",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x275 },
+ unicodeslot=0x1DB1,
+ },
+ [0x1DB2]={
+ category="lm",
+ description="MODIFIER LETTER SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x278 },
+ unicodeslot=0x1DB2,
+ },
+ [0x1DB3]={
+ category="lm",
+ description="MODIFIER LETTER SMALL S WITH HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x282 },
+ unicodeslot=0x1DB3,
+ },
+ [0x1DB4]={
+ category="lm",
+ description="MODIFIER LETTER SMALL ESH",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x283 },
+ unicodeslot=0x1DB4,
+ },
+ [0x1DB5]={
+ category="lm",
+ description="MODIFIER LETTER SMALL T WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1AB },
+ unicodeslot=0x1DB5,
+ },
+ [0x1DB6]={
+ category="lm",
+ description="MODIFIER LETTER SMALL U BAR",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x289 },
+ unicodeslot=0x1DB6,
+ },
+ [0x1DB7]={
+ category="lm",
+ description="MODIFIER LETTER SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x28A },
+ unicodeslot=0x1DB7,
+ },
+ [0x1DB8]={
+ category="lm",
+ description="MODIFIER LETTER SMALL CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x1D1C },
+ unicodeslot=0x1DB8,
+ },
+ [0x1DB9]={
+ category="lm",
+ description="MODIFIER LETTER SMALL V WITH HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x28B },
+ unicodeslot=0x1DB9,
+ },
+ [0x1DBA]={
+ category="lm",
+ description="MODIFIER LETTER SMALL TURNED V",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x28C },
+ unicodeslot=0x1DBA,
+ },
+ [0x1DBB]={
+ category="lm",
+ description="MODIFIER LETTER SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x7A },
+ unicodeslot=0x1DBB,
+ },
+ [0x1DBC]={
+ category="lm",
+ description="MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x290 },
+ unicodeslot=0x1DBC,
+ },
+ [0x1DBD]={
+ category="lm",
+ description="MODIFIER LETTER SMALL Z WITH CURL",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x291 },
+ unicodeslot=0x1DBD,
+ },
+ [0x1DBE]={
+ category="lm",
+ description="MODIFIER LETTER SMALL EZH",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x292 },
+ unicodeslot=0x1DBE,
+ },
+ [0x1DBF]={
+ category="lm",
+ description="MODIFIER LETTER SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x3B8 },
+ unicodeslot=0x1DBF,
+ },
+ [0x1DC0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOTTED GRAVE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC0,
+ },
+ [0x1DC1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOTTED ACUTE ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC1,
+ },
+ [0x1DC2]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING SNAKE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC2,
+ },
+ [0x1DC3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING SUSPENSION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC3,
+ },
+ [0x1DC4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING MACRON-ACUTE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC4,
+ },
+ [0x1DC5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRAVE-MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC5,
+ },
+ [0x1DC6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING MACRON-GRAVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC6,
+ },
+ [0x1DC7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING ACUTE-MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC7,
+ },
+ [0x1DC8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRAVE-ACUTE-GRAVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC8,
+ },
+ [0x1DC9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING ACUTE-GRAVE-ACUTE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DC9,
+ },
+ [0x1DCA]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LATIN SMALL LETTER R BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCA,
+ },
+ [0x1DCB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING BREVE-MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCB,
+ },
+ [0x1DCC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING MACRON-BREVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCC,
+ },
+ [0x1DCD]={
+ category="mn",
+ combining=0xEA,
+ description="COMBINING DOUBLE CIRCUMFLEX ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCD,
+ },
+ [0x1DCE]={
+ category="mn",
+ combining=0xD6,
+ description="COMBINING OGONEK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCE,
+ },
+ [0x1DCF]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING ZIGZAG BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCF,
+ },
+ [0x1DD0]={
+ category="mn",
+ combining=0xCA,
+ description="COMBINING IS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD0,
+ },
+ [0x1DD1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING UR ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD1,
+ },
+ [0x1DD2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING US ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD2,
+ },
+ [0x1DD3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD3,
+ },
+ [0x1DD4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER AE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD4,
+ },
+ [0x1DD5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER AO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD5,
+ },
+ [0x1DD6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER AV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD6,
+ },
+ [0x1DD7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER C CEDILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD7,
+ },
+ [0x1DD8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER INSULAR D",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD8,
+ },
+ [0x1DD9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER ETH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD9,
+ },
+ [0x1DDA]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER G",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDA,
+ },
+ [0x1DDB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN LETTER SMALL CAPITAL G",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDB,
+ },
+ [0x1DDC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER K",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDC,
+ },
+ [0x1DDD]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDD,
+ },
+ [0x1DDE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN LETTER SMALL CAPITAL L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDE,
+ },
+ [0x1DDF]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN LETTER SMALL CAPITAL M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDF,
+ },
+ [0x1DE0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE0,
+ },
+ [0x1DE1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN LETTER SMALL CAPITAL N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE1,
+ },
+ [0x1DE2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN LETTER SMALL CAPITAL R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE2,
+ },
+ [0x1DE3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER R ROTUNDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE3,
+ },
+ [0x1DE4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER S",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE4,
+ },
+ [0x1DE5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER LONG S",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE5,
+ },
+ [0x1DE6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER Z",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE6,
+ },
+ [0x1DE7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER ALPHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE7,
+ },
+ [0x1DE8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER B",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE8,
+ },
+ [0x1DE9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER BETA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE9,
+ },
+ [0x1DEA]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER SCHWA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DEA,
+ },
+ [0x1DEB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER F",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DEB,
+ },
+ [0x1DEC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DEC,
+ },
+ [0x1DED]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER O WITH LIGHT CENTRALIZATION STROKE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DED,
+ },
+ [0x1DEE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER P",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DEE,
+ },
+ [0x1DEF]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER ESH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DEF,
+ },
+ [0x1DF0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER U WITH LIGHT CENTRALIZATION STROKE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF0,
+ },
+ [0x1DF1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER W",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF1,
+ },
+ [0x1DF2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER A WITH DIAERESIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF2,
+ },
+ [0x1DF3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER O WITH DIAERESIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF3,
+ },
+ [0x1DF4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LATIN SMALL LETTER U WITH DIAERESIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF4,
+ },
+ [0x1DF5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING UP TACK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DF5,
+ },
+ [0x1DFC]={
+ category="mn",
+ combining=0xE9,
+ description="COMBINING DOUBLE INVERTED BREVE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFC,
+ },
+ [0x1DFD]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING ALMOST EQUAL TO BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFD,
+ },
+ [0x1DFE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LEFT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFE,
+ },
+ [0x1DFF]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFF,
+ },
+ [0x1E00]={
+ adobename="Aringbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER A WITH RING BELOW",
+ direction="l",
+ lccode=0x1E01,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x325 },
+ unicodeslot=0x1E00,
+ },
+ [0x1E01]={
+ adobename="aringbelow",
+ category="ll",
+ description="LATIN SMALL LETTER A WITH RING BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x325 },
+ uccode=0x1E00,
+ unicodeslot=0x1E01,
+ },
+ [0x1E02]={
+ adobename="Bdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E03,
+ linebreak="al",
+ shcode=0x42,
+ specials={ "char", 0x42, 0x307 },
+ unicodeslot=0x1E02,
+ },
+ [0x1E03]={
+ adobename="bdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER B WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ specials={ "char", 0x62, 0x307 },
+ uccode=0x1E02,
+ unicodeslot=0x1E03,
+ },
+ [0x1E04]={
+ adobename="Bdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E05,
+ linebreak="al",
+ shcode=0x42,
+ specials={ "char", 0x42, 0x323 },
+ unicodeslot=0x1E04,
+ },
+ [0x1E05]={
+ adobename="bdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER B WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ specials={ "char", 0x62, 0x323 },
+ uccode=0x1E04,
+ unicodeslot=0x1E05,
+ },
+ [0x1E06]={
+ adobename="Blinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E07,
+ linebreak="al",
+ shcode=0x42,
+ specials={ "char", 0x42, 0x331 },
+ unicodeslot=0x1E06,
+ },
+ [0x1E07]={
+ adobename="blinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER B WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x62,
+ specials={ "char", 0x62, 0x331 },
+ uccode=0x1E06,
+ unicodeslot=0x1E07,
+ },
+ [0x1E08]={
+ adobename="Ccedillaacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE",
+ direction="l",
+ lccode=0x1E09,
+ linebreak="al",
+ shcode=0x43,
+ specials={ "char", 0xC7, 0x301 },
+ unicodeslot=0x1E08,
+ },
+ [0x1E09]={
+ adobename="ccedillaacute",
+ category="ll",
+ description="LATIN SMALL LETTER C WITH CEDILLA AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x63,
+ specials={ "char", 0xE7, 0x301 },
+ uccode=0x1E08,
+ unicodeslot=0x1E09,
+ },
+ [0x1E0A]={
+ adobename="Ddotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E0B,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x307 },
+ unicodeslot=0x1E0A,
+ },
+ [0x1E0B]={
+ adobename="ddotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x307 },
+ uccode=0x1E0A,
+ unicodeslot=0x1E0B,
+ },
+ [0x1E0C]={
+ adobename="Ddotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E0D,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x323 },
+ unicodeslot=0x1E0C,
+ },
+ [0x1E0D]={
+ adobename="ddotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x323 },
+ uccode=0x1E0C,
+ unicodeslot=0x1E0D,
+ },
+ [0x1E0E]={
+ adobename="Dlinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E0F,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x331 },
+ unicodeslot=0x1E0E,
+ },
+ [0x1E0F]={
+ adobename="dlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x331 },
+ uccode=0x1E0E,
+ unicodeslot=0x1E0F,
+ },
+ [0x1E10]={
+ adobename="Dcedilla",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH CEDILLA",
+ direction="l",
+ lccode=0x1E11,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x327 },
+ unicodeslot=0x1E10,
+ },
+ [0x1E11]={
+ adobename="dcedilla",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x327 },
+ uccode=0x1E10,
+ unicodeslot=0x1E11,
+ },
+ [0x1E12]={
+ adobename="Dcircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E13,
+ linebreak="al",
+ shcode=0x44,
+ specials={ "char", 0x44, 0x32D },
+ unicodeslot=0x1E12,
+ },
+ [0x1E13]={
+ adobename="dcircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x64,
+ specials={ "char", 0x64, 0x32D },
+ uccode=0x1E12,
+ unicodeslot=0x1E13,
+ },
+ [0x1E14]={
+ adobename="Emacrongrave",
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH MACRON AND GRAVE",
+ direction="l",
+ lccode=0x1E15,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x112, 0x300 },
+ unicodeslot=0x1E14,
+ },
+ [0x1E15]={
+ adobename="emacrongrave",
+ category="ll",
+ description="LATIN SMALL LETTER E WITH MACRON AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x113, 0x300 },
+ uccode=0x1E14,
+ unicodeslot=0x1E15,
+ },
+ [0x1E16]={
+ adobename="Emacronacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH MACRON AND ACUTE",
+ direction="l",
+ lccode=0x1E17,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x112, 0x301 },
+ unicodeslot=0x1E16,
+ },
+ [0x1E17]={
+ adobename="emacronacute",
+ category="ll",
+ description="LATIN SMALL LETTER E WITH MACRON AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x113, 0x301 },
+ uccode=0x1E16,
+ unicodeslot=0x1E17,
+ },
+ [0x1E18]={
+ adobename="Ecircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E19,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x32D },
+ unicodeslot=0x1E18,
+ },
+ [0x1E19]={
+ adobename="ecircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x32D },
+ uccode=0x1E18,
+ unicodeslot=0x1E19,
+ },
+ [0x1E1A]={
+ adobename="Etildebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH TILDE BELOW",
+ direction="l",
+ lccode=0x1E1B,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x330 },
+ unicodeslot=0x1E1A,
+ },
+ [0x1E1B]={
+ adobename="etildebelow",
+ category="ll",
+ description="LATIN SMALL LETTER E WITH TILDE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x330 },
+ uccode=0x1E1A,
+ unicodeslot=0x1E1B,
+ },
+ [0x1E1C]={
+ adobename="Ecedillabreve",
+ category="lu",
+ description="LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE",
+ direction="l",
+ lccode=0x1E1D,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x228, 0x306 },
+ unicodeslot=0x1E1C,
+ },
+ [0x1E1D]={
+ adobename="ecedillabreve",
+ category="ll",
+ description="LATIN SMALL LETTER E WITH CEDILLA AND BREVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x229, 0x306 },
+ uccode=0x1E1C,
+ unicodeslot=0x1E1D,
+ },
+ [0x1E1E]={
+ adobename="Fdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER F WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E1F,
+ linebreak="al",
+ shcode=0x46,
+ specials={ "char", 0x46, 0x307 },
+ unicodeslot=0x1E1E,
+ },
+ [0x1E1F]={
+ adobename="fdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER F WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x66,
+ specials={ "char", 0x66, 0x307 },
+ uccode=0x1E1E,
+ unicodeslot=0x1E1F,
+ },
+ [0x1E20]={
+ adobename="Gmacron",
+ category="lu",
+ description="LATIN CAPITAL LETTER G WITH MACRON",
+ direction="l",
+ lccode=0x1E21,
+ linebreak="al",
+ shcode=0x47,
+ specials={ "char", 0x47, 0x304 },
+ unicodeslot=0x1E20,
+ },
+ [0x1E21]={
+ adobename="gmacron",
+ category="ll",
+ description="LATIN SMALL LETTER G WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x67,
+ specials={ "char", 0x67, 0x304 },
+ uccode=0x1E20,
+ unicodeslot=0x1E21,
+ },
+ [0x1E22]={
+ adobename="Hdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E23,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x307 },
+ unicodeslot=0x1E22,
+ },
+ [0x1E23]={
+ adobename="hdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x307 },
+ uccode=0x1E22,
+ unicodeslot=0x1E23,
+ },
+ [0x1E24]={
+ adobename="Hdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E25,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x323 },
+ unicodeslot=0x1E24,
+ },
+ [0x1E25]={
+ adobename="hdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x323 },
+ uccode=0x1E24,
+ unicodeslot=0x1E25,
+ },
+ [0x1E26]={
+ adobename="Hdieresis",
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH DIAERESIS",
+ direction="l",
+ lccode=0x1E27,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x308 },
+ unicodeslot=0x1E26,
+ },
+ [0x1E27]={
+ adobename="hdieresis",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x308 },
+ uccode=0x1E26,
+ unicodeslot=0x1E27,
+ },
+ [0x1E28]={
+ adobename="Hcedilla",
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH CEDILLA",
+ direction="l",
+ lccode=0x1E29,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x327 },
+ unicodeslot=0x1E28,
+ },
+ [0x1E29]={
+ adobename="hcedilla",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH CEDILLA",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x327 },
+ uccode=0x1E28,
+ unicodeslot=0x1E29,
+ },
+ [0x1E2A]={
+ adobename="Hbrevebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH BREVE BELOW",
+ direction="l",
+ lccode=0x1E2B,
+ linebreak="al",
+ shcode=0x48,
+ specials={ "char", 0x48, 0x32E },
+ unicodeslot=0x1E2A,
+ },
+ [0x1E2B]={
+ adobename="hbrevebelow",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH BREVE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x32E },
+ uccode=0x1E2A,
+ unicodeslot=0x1E2B,
+ },
+ [0x1E2C]={
+ adobename="Itildebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER I WITH TILDE BELOW",
+ direction="l",
+ lccode=0x1E2D,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x330 },
+ unicodeslot=0x1E2C,
+ },
+ [0x1E2D]={
+ adobename="itildebelow",
+ category="ll",
+ description="LATIN SMALL LETTER I WITH TILDE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x330 },
+ uccode=0x1E2C,
+ unicodeslot=0x1E2D,
+ },
+ [0x1E2E]={
+ adobename="Idieresisacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE",
+ direction="l",
+ lccode=0x1E2F,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0xCF, 0x301 },
+ unicodeslot=0x1E2E,
+ },
+ [0x1E2F]={
+ adobename="idieresisacute",
+ category="ll",
+ description="LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0xEF, 0x301 },
+ uccode=0x1E2E,
+ unicodeslot=0x1E2F,
+ },
+ [0x1E30]={
+ adobename="Kacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH ACUTE",
+ direction="l",
+ lccode=0x1E31,
+ linebreak="al",
+ shcode=0x4B,
+ specials={ "char", 0x4B, 0x301 },
+ unicodeslot=0x1E30,
+ },
+ [0x1E31]={
+ adobename="kacute",
+ category="ll",
+ description="LATIN SMALL LETTER K WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ specials={ "char", 0x6B, 0x301 },
+ uccode=0x1E30,
+ unicodeslot=0x1E31,
+ },
+ [0x1E32]={
+ adobename="Kdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E33,
+ linebreak="al",
+ shcode=0x4B,
+ specials={ "char", 0x4B, 0x323 },
+ unicodeslot=0x1E32,
+ },
+ [0x1E33]={
+ adobename="kdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER K WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ specials={ "char", 0x6B, 0x323 },
+ uccode=0x1E32,
+ unicodeslot=0x1E33,
+ },
+ [0x1E34]={
+ adobename="Klinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E35,
+ linebreak="al",
+ shcode=0x4B,
+ specials={ "char", 0x4B, 0x331 },
+ unicodeslot=0x1E34,
+ },
+ [0x1E35]={
+ adobename="klinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER K WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ specials={ "char", 0x6B, 0x331 },
+ uccode=0x1E34,
+ unicodeslot=0x1E35,
+ },
+ [0x1E36]={
+ adobename="Ldotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E37,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x323 },
+ unicodeslot=0x1E36,
+ },
+ [0x1E37]={
+ adobename="ldotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x323 },
+ uccode=0x1E36,
+ unicodeslot=0x1E37,
+ },
+ [0x1E38]={
+ adobename="Ldotbelowmacron",
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON",
+ direction="l",
+ lccode=0x1E39,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x1E36, 0x304 },
+ unicodeslot=0x1E38,
+ },
+ [0x1E39]={
+ adobename="ldotbelowmacron",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH DOT BELOW AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x1E37, 0x304 },
+ uccode=0x1E38,
+ unicodeslot=0x1E39,
+ },
+ [0x1E3A]={
+ adobename="Llinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E3B,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x331 },
+ unicodeslot=0x1E3A,
+ },
+ [0x1E3B]={
+ adobename="llinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x331 },
+ uccode=0x1E3A,
+ unicodeslot=0x1E3B,
+ },
+ [0x1E3C]={
+ adobename="Lcircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E3D,
+ linebreak="al",
+ shcode=0x4C,
+ specials={ "char", 0x4C, 0x32D },
+ unicodeslot=0x1E3C,
+ },
+ [0x1E3D]={
+ adobename="lcircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ specials={ "char", 0x6C, 0x32D },
+ uccode=0x1E3C,
+ unicodeslot=0x1E3D,
+ },
+ [0x1E3E]={
+ adobename="Macute",
+ category="lu",
+ description="LATIN CAPITAL LETTER M WITH ACUTE",
+ direction="l",
+ lccode=0x1E3F,
+ linebreak="al",
+ shcode=0x4D,
+ specials={ "char", 0x4D, 0x301 },
+ unicodeslot=0x1E3E,
+ },
+ [0x1E3F]={
+ adobename="macute",
+ category="ll",
+ description="LATIN SMALL LETTER M WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ specials={ "char", 0x6D, 0x301 },
+ uccode=0x1E3E,
+ unicodeslot=0x1E3F,
+ },
+ [0x1E40]={
+ adobename="Mdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER M WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E41,
+ linebreak="al",
+ shcode=0x4D,
+ specials={ "char", 0x4D, 0x307 },
+ unicodeslot=0x1E40,
+ },
+ [0x1E41]={
+ adobename="mdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER M WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ specials={ "char", 0x6D, 0x307 },
+ uccode=0x1E40,
+ unicodeslot=0x1E41,
+ },
+ [0x1E42]={
+ adobename="Mdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER M WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E43,
+ linebreak="al",
+ shcode=0x4D,
+ specials={ "char", 0x4D, 0x323 },
+ unicodeslot=0x1E42,
+ },
+ [0x1E43]={
+ adobename="mdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER M WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6D,
+ specials={ "char", 0x6D, 0x323 },
+ uccode=0x1E42,
+ unicodeslot=0x1E43,
+ },
+ [0x1E44]={
+ adobename="Ndotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E45,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x307 },
+ unicodeslot=0x1E44,
+ },
+ [0x1E45]={
+ adobename="ndotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x307 },
+ uccode=0x1E44,
+ unicodeslot=0x1E45,
+ },
+ [0x1E46]={
+ adobename="Ndotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E47,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x323 },
+ unicodeslot=0x1E46,
+ },
+ [0x1E47]={
+ adobename="ndotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x323 },
+ uccode=0x1E46,
+ unicodeslot=0x1E47,
+ },
+ [0x1E48]={
+ adobename="Nlinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E49,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x331 },
+ unicodeslot=0x1E48,
+ },
+ [0x1E49]={
+ adobename="nlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x331 },
+ uccode=0x1E48,
+ unicodeslot=0x1E49,
+ },
+ [0x1E4A]={
+ adobename="Ncircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E4B,
+ linebreak="al",
+ shcode=0x4E,
+ specials={ "char", 0x4E, 0x32D },
+ unicodeslot=0x1E4A,
+ },
+ [0x1E4B]={
+ adobename="ncircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6E,
+ specials={ "char", 0x6E, 0x32D },
+ uccode=0x1E4A,
+ unicodeslot=0x1E4B,
+ },
+ [0x1E4C]={
+ adobename="Otildeacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH TILDE AND ACUTE",
+ direction="l",
+ lccode=0x1E4D,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD5, 0x301 },
+ unicodeslot=0x1E4C,
+ },
+ [0x1E4D]={
+ adobename="otildeacute",
+ category="ll",
+ description="LATIN SMALL LETTER O WITH TILDE AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF5, 0x301 },
+ uccode=0x1E4C,
+ unicodeslot=0x1E4D,
+ },
+ [0x1E4E]={
+ adobename="Otildedieresis",
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS",
+ direction="l",
+ lccode=0x1E4F,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD5, 0x308 },
+ unicodeslot=0x1E4E,
+ },
+ [0x1E4F]={
+ adobename="otildedieresis",
+ category="ll",
+ description="LATIN SMALL LETTER O WITH TILDE AND DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF5, 0x308 },
+ uccode=0x1E4E,
+ unicodeslot=0x1E4F,
+ },
+ [0x1E50]={
+ adobename="Omacrongrave",
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH MACRON AND GRAVE",
+ direction="l",
+ lccode=0x1E51,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x14C, 0x300 },
+ unicodeslot=0x1E50,
+ },
+ [0x1E51]={
+ adobename="omacrongrave",
+ category="ll",
+ description="LATIN SMALL LETTER O WITH MACRON AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x14D, 0x300 },
+ uccode=0x1E50,
+ unicodeslot=0x1E51,
+ },
+ [0x1E52]={
+ adobename="Omacronacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH MACRON AND ACUTE",
+ direction="l",
+ lccode=0x1E53,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x14C, 0x301 },
+ unicodeslot=0x1E52,
+ },
+ [0x1E53]={
+ adobename="omacronacute",
+ category="ll",
+ description="LATIN SMALL LETTER O WITH MACRON AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x14D, 0x301 },
+ uccode=0x1E52,
+ unicodeslot=0x1E53,
+ },
+ [0x1E54]={
+ adobename="Pacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH ACUTE",
+ direction="l",
+ lccode=0x1E55,
+ linebreak="al",
+ shcode=0x50,
+ specials={ "char", 0x50, 0x301 },
+ unicodeslot=0x1E54,
+ },
+ [0x1E55]={
+ adobename="pacute",
+ category="ll",
+ description="LATIN SMALL LETTER P WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ specials={ "char", 0x70, 0x301 },
+ uccode=0x1E54,
+ unicodeslot=0x1E55,
+ },
+ [0x1E56]={
+ adobename="Pdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E57,
+ linebreak="al",
+ shcode=0x50,
+ specials={ "char", 0x50, 0x307 },
+ unicodeslot=0x1E56,
+ },
+ [0x1E57]={
+ adobename="pdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER P WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x70,
+ specials={ "char", 0x70, 0x307 },
+ uccode=0x1E56,
+ unicodeslot=0x1E57,
+ },
+ [0x1E58]={
+ adobename="Rdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E59,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x307 },
+ unicodeslot=0x1E58,
+ },
+ [0x1E59]={
+ adobename="rdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x307 },
+ uccode=0x1E58,
+ unicodeslot=0x1E59,
+ },
+ [0x1E5A]={
+ adobename="Rdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E5B,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x323 },
+ unicodeslot=0x1E5A,
+ },
+ [0x1E5B]={
+ adobename="rdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x323 },
+ uccode=0x1E5A,
+ unicodeslot=0x1E5B,
+ },
+ [0x1E5C]={
+ adobename="Rdotbelowmacron",
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON",
+ direction="l",
+ lccode=0x1E5D,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x1E5A, 0x304 },
+ unicodeslot=0x1E5C,
+ },
+ [0x1E5D]={
+ adobename="rdotbelowmacron",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH DOT BELOW AND MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x1E5B, 0x304 },
+ uccode=0x1E5C,
+ unicodeslot=0x1E5D,
+ },
+ [0x1E5E]={
+ adobename="Rlinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E5F,
+ linebreak="al",
+ shcode=0x52,
+ specials={ "char", 0x52, 0x331 },
+ unicodeslot=0x1E5E,
+ },
+ [0x1E5F]={
+ adobename="rlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER R WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x72,
+ specials={ "char", 0x72, 0x331 },
+ uccode=0x1E5E,
+ unicodeslot=0x1E5F,
+ },
+ [0x1E60]={
+ adobename="Sdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E61,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x307 },
+ unicodeslot=0x1E60,
+ },
+ [0x1E61]={
+ adobename="sdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x307 },
+ uccode=0x1E60,
+ unicodeslot=0x1E61,
+ },
+ [0x1E62]={
+ adobename="Sdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E63,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x53, 0x323 },
+ unicodeslot=0x1E62,
+ },
+ [0x1E63]={
+ adobename="sdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x73, 0x323 },
+ uccode=0x1E62,
+ unicodeslot=0x1E63,
+ },
+ [0x1E64]={
+ adobename="Sacutedotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE",
+ direction="l",
+ lccode=0x1E65,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x15A, 0x307 },
+ unicodeslot=0x1E64,
+ },
+ [0x1E65]={
+ adobename="sacutedotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x15B, 0x307 },
+ uccode=0x1E64,
+ unicodeslot=0x1E65,
+ },
+ [0x1E66]={
+ adobename="Scarondotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE",
+ direction="l",
+ lccode=0x1E67,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x160, 0x307 },
+ unicodeslot=0x1E66,
+ },
+ [0x1E67]={
+ adobename="scarondotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH CARON AND DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x161, 0x307 },
+ uccode=0x1E66,
+ unicodeslot=0x1E67,
+ },
+ [0x1E68]={
+ adobename="Sdotbelowdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE",
+ direction="l",
+ lccode=0x1E69,
+ linebreak="al",
+ shcode=0x53,
+ specials={ "char", 0x1E62, 0x307 },
+ unicodeslot=0x1E68,
+ },
+ [0x1E69]={
+ adobename="sdotbelowdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x73,
+ specials={ "char", 0x1E63, 0x307 },
+ uccode=0x1E68,
+ unicodeslot=0x1E69,
+ },
+ [0x1E6A]={
+ adobename="Tdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E6B,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x307 },
+ unicodeslot=0x1E6A,
+ },
+ [0x1E6B]={
+ adobename="tdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x307 },
+ uccode=0x1E6A,
+ unicodeslot=0x1E6B,
+ },
+ [0x1E6C]={
+ adobename="Tdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E6D,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x323 },
+ unicodeslot=0x1E6C,
+ },
+ [0x1E6D]={
+ adobename="tdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x323 },
+ uccode=0x1E6C,
+ unicodeslot=0x1E6D,
+ },
+ [0x1E6E]={
+ adobename="Tlinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E6F,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x331 },
+ unicodeslot=0x1E6E,
+ },
+ [0x1E6F]={
+ adobename="tlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x331 },
+ uccode=0x1E6E,
+ unicodeslot=0x1E6F,
+ },
+ [0x1E70]={
+ adobename="Tcircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E71,
+ linebreak="al",
+ shcode=0x54,
+ specials={ "char", 0x54, 0x32D },
+ unicodeslot=0x1E70,
+ },
+ [0x1E71]={
+ adobename="tcircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x32D },
+ uccode=0x1E70,
+ unicodeslot=0x1E71,
+ },
+ [0x1E72]={
+ adobename="Udieresisbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH DIAERESIS BELOW",
+ direction="l",
+ lccode=0x1E73,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x324 },
+ unicodeslot=0x1E72,
+ },
+ [0x1E73]={
+ adobename="udieresisbelow",
+ category="ll",
+ description="LATIN SMALL LETTER U WITH DIAERESIS BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x324 },
+ uccode=0x1E72,
+ unicodeslot=0x1E73,
+ },
+ [0x1E74]={
+ adobename="Utildebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH TILDE BELOW",
+ direction="l",
+ lccode=0x1E75,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x330 },
+ unicodeslot=0x1E74,
+ },
+ [0x1E75]={
+ adobename="utildebelow",
+ category="ll",
+ description="LATIN SMALL LETTER U WITH TILDE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x330 },
+ uccode=0x1E74,
+ unicodeslot=0x1E75,
+ },
+ [0x1E76]={
+ adobename="Ucircumflexbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW",
+ direction="l",
+ lccode=0x1E77,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x32D },
+ unicodeslot=0x1E76,
+ },
+ [0x1E77]={
+ adobename="ucircumflexbelow",
+ category="ll",
+ description="LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x32D },
+ uccode=0x1E76,
+ unicodeslot=0x1E77,
+ },
+ [0x1E78]={
+ adobename="Utildeacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH TILDE AND ACUTE",
+ direction="l",
+ lccode=0x1E79,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x168, 0x301 },
+ unicodeslot=0x1E78,
+ },
+ [0x1E79]={
+ adobename="utildeacute",
+ category="ll",
+ description="LATIN SMALL LETTER U WITH TILDE AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x169, 0x301 },
+ uccode=0x1E78,
+ unicodeslot=0x1E79,
+ },
+ [0x1E7A]={
+ adobename="Umacrondieresis",
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS",
+ direction="l",
+ lccode=0x1E7B,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x16A, 0x308 },
+ unicodeslot=0x1E7A,
+ },
+ [0x1E7B]={
+ adobename="umacrondieresis",
+ category="ll",
+ description="LATIN SMALL LETTER U WITH MACRON AND DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x16B, 0x308 },
+ uccode=0x1E7A,
+ unicodeslot=0x1E7B,
+ },
+ [0x1E7C]={
+ adobename="Vtilde",
+ category="lu",
+ description="LATIN CAPITAL LETTER V WITH TILDE",
+ direction="l",
+ lccode=0x1E7D,
+ linebreak="al",
+ shcode=0x56,
+ specials={ "char", 0x56, 0x303 },
+ unicodeslot=0x1E7C,
+ },
+ [0x1E7D]={
+ adobename="vtilde",
+ category="ll",
+ description="LATIN SMALL LETTER V WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x76,
+ specials={ "char", 0x76, 0x303 },
+ uccode=0x1E7C,
+ unicodeslot=0x1E7D,
+ },
+ [0x1E7E]={
+ adobename="Vdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER V WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E7F,
+ linebreak="al",
+ shcode=0x56,
+ specials={ "char", 0x56, 0x323 },
+ unicodeslot=0x1E7E,
+ },
+ [0x1E7F]={
+ adobename="vdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER V WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x76,
+ specials={ "char", 0x76, 0x323 },
+ uccode=0x1E7E,
+ unicodeslot=0x1E7F,
+ },
+ [0x1E80]={
+ adobename="Wgrave",
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH GRAVE",
+ direction="l",
+ lccode=0x1E81,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x300 },
+ unicodeslot=0x1E80,
+ },
+ [0x1E81]={
+ adobename="wgrave",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x300 },
+ uccode=0x1E80,
+ unicodeslot=0x1E81,
+ },
+ [0x1E82]={
+ adobename="Wacute",
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH ACUTE",
+ direction="l",
+ lccode=0x1E83,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x301 },
+ unicodeslot=0x1E82,
+ },
+ [0x1E83]={
+ adobename="wacute",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x301 },
+ uccode=0x1E82,
+ unicodeslot=0x1E83,
+ },
+ [0x1E84]={
+ adobename="Wdieresis",
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH DIAERESIS",
+ direction="l",
+ lccode=0x1E85,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x308 },
+ unicodeslot=0x1E84,
+ },
+ [0x1E85]={
+ adobename="wdieresis",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x308 },
+ uccode=0x1E84,
+ unicodeslot=0x1E85,
+ },
+ [0x1E86]={
+ adobename="Wdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E87,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x307 },
+ unicodeslot=0x1E86,
+ },
+ [0x1E87]={
+ adobename="wdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x307 },
+ uccode=0x1E86,
+ unicodeslot=0x1E87,
+ },
+ [0x1E88]={
+ adobename="Wdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E89,
+ linebreak="al",
+ shcode=0x57,
+ specials={ "char", 0x57, 0x323 },
+ unicodeslot=0x1E88,
+ },
+ [0x1E89]={
+ adobename="wdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x323 },
+ uccode=0x1E88,
+ unicodeslot=0x1E89,
+ },
+ [0x1E8A]={
+ adobename="Xdotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER X WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E8B,
+ linebreak="al",
+ shcode=0x58,
+ specials={ "char", 0x58, 0x307 },
+ unicodeslot=0x1E8A,
+ },
+ [0x1E8B]={
+ adobename="xdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER X WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x78,
+ specials={ "char", 0x78, 0x307 },
+ uccode=0x1E8A,
+ unicodeslot=0x1E8B,
+ },
+ [0x1E8C]={
+ adobename="Xdieresis",
+ category="lu",
+ description="LATIN CAPITAL LETTER X WITH DIAERESIS",
+ direction="l",
+ lccode=0x1E8D,
+ linebreak="al",
+ shcode=0x58,
+ specials={ "char", 0x58, 0x308 },
+ unicodeslot=0x1E8C,
+ },
+ [0x1E8D]={
+ adobename="xdieresis",
+ category="ll",
+ description="LATIN SMALL LETTER X WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x78,
+ specials={ "char", 0x78, 0x308 },
+ uccode=0x1E8C,
+ unicodeslot=0x1E8D,
+ },
+ [0x1E8E]={
+ adobename="Ydotaccent",
+ category="lu",
+ description="LATIN CAPITAL LETTER Y WITH DOT ABOVE",
+ direction="l",
+ lccode=0x1E8F,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x307 },
+ unicodeslot=0x1E8E,
+ },
+ [0x1E8F]={
+ adobename="ydotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x307 },
+ uccode=0x1E8E,
+ unicodeslot=0x1E8F,
+ },
+ [0x1E90]={
+ adobename="Zcircumflex",
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH CIRCUMFLEX",
+ direction="l",
+ lccode=0x1E91,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x302 },
+ unicodeslot=0x1E90,
+ },
+ [0x1E91]={
+ adobename="zcircumflex",
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH CIRCUMFLEX",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x302 },
+ uccode=0x1E90,
+ unicodeslot=0x1E91,
+ },
+ [0x1E92]={
+ adobename="Zdotbelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH DOT BELOW",
+ direction="l",
+ lccode=0x1E93,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x323 },
+ unicodeslot=0x1E92,
+ },
+ [0x1E93]={
+ adobename="zdotbelow",
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x323 },
+ uccode=0x1E92,
+ unicodeslot=0x1E93,
+ },
+ [0x1E94]={
+ adobename="Zlinebelow",
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH LINE BELOW",
+ direction="l",
+ lccode=0x1E95,
+ linebreak="al",
+ shcode=0x5A,
+ specials={ "char", 0x5A, 0x331 },
+ unicodeslot=0x1E94,
+ },
+ [0x1E95]={
+ adobename="zlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ specials={ "char", 0x7A, 0x331 },
+ uccode=0x1E94,
+ unicodeslot=0x1E95,
+ },
+ [0x1E96]={
+ adobename="hlinebelow",
+ category="ll",
+ description="LATIN SMALL LETTER H WITH LINE BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ specials={ "char", 0x68, 0x331 },
+ unicodeslot=0x1E96,
+ },
+ [0x1E97]={
+ adobename="tdieresis",
+ category="ll",
+ description="LATIN SMALL LETTER T WITH DIAERESIS",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ specials={ "char", 0x74, 0x308 },
+ unicodeslot=0x1E97,
+ },
+ [0x1E98]={
+ adobename="wring",
+ category="ll",
+ description="LATIN SMALL LETTER W WITH RING ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x77,
+ specials={ "char", 0x77, 0x30A },
+ unicodeslot=0x1E98,
+ },
+ [0x1E99]={
+ adobename="yring",
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH RING ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x30A },
+ unicodeslot=0x1E99,
+ },
+ [0x1E9A]={
+ adobename="arighthalfring",
+ category="ll",
+ description="LATIN SMALL LETTER A WITH RIGHT HALF RING",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "compat", 0x61, 0x2BE },
+ unicodeslot=0x1E9A,
+ },
+ [0x1E9B]={
+ adobename="slongdotaccent",
+ category="ll",
+ description="LATIN SMALL LETTER LONG S WITH DOT ABOVE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x17F, 0x307 },
+ uccode=0x1E60,
+ unicodeslot=0x1E9B,
+ },
+ [0x1E9C]={
+ category="ll",
+ description="LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9C,
+ },
+ [0x1E9D]={
+ category="ll",
+ description="LATIN SMALL LETTER LONG S WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9D,
+ },
+ [0x1E9E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER SHARP S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9E,
+ lccode=0xDF,
+ shcode={ 0x53, 0x53 },
+ },
+ [0x1E9F]={
+ category="ll",
+ description="LATIN SMALL LETTER DELTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9F,
+ },
+ [0x1EA0]={
+ adobename="Adotbelow",
+ category="lu",
+ contextname="Adotbelow",
+ description="LATIN CAPITAL LETTER A WITH DOT BELOW",
+ direction="l",
+ lccode=0x1EA1,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x323 },
+ unicodeslot=0x1EA0,
+ },
+ [0x1EA1]={
+ adobename="adotbelow",
+ category="ll",
+ contextname="adotbelow",
+ description="LATIN SMALL LETTER A WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x323 },
+ uccode=0x1EA0,
+ unicodeslot=0x1EA1,
+ },
+ [0x1EA2]={
+ adobename="Ahookabove",
+ category="lu",
+ contextname="Ahook",
+ description="LATIN CAPITAL LETTER A WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1EA3,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x41, 0x309 },
+ unicodeslot=0x1EA2,
+ },
+ [0x1EA3]={
+ adobename="ahookabove",
+ category="ll",
+ contextname="ahook",
+ description="LATIN SMALL LETTER A WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x61, 0x309 },
+ uccode=0x1EA2,
+ unicodeslot=0x1EA3,
+ },
+ [0x1EA4]={
+ adobename="Acircumflexacute",
+ category="lu",
+ contextname="Acircumflexacute",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ lccode=0x1EA5,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC2, 0x301 },
+ unicodeslot=0x1EA4,
+ },
+ [0x1EA5]={
+ adobename="acircumflexacute",
+ category="ll",
+ contextname="acircumflexacute",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE2, 0x301 },
+ uccode=0x1EA4,
+ unicodeslot=0x1EA5,
+ },
+ [0x1EA6]={
+ adobename="Acircumflexgrave",
+ category="lu",
+ contextname="Acircumflexgrave",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ lccode=0x1EA7,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC2, 0x300 },
+ unicodeslot=0x1EA6,
+ },
+ [0x1EA7]={
+ adobename="acircumflexgrave",
+ category="ll",
+ contextname="acircumflexgrave",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE2, 0x300 },
+ uccode=0x1EA6,
+ unicodeslot=0x1EA7,
+ },
+ [0x1EA8]={
+ adobename="Acircumflexhookabove",
+ category="lu",
+ contextname="Acircumflexhook",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1EA9,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC2, 0x309 },
+ unicodeslot=0x1EA8,
+ },
+ [0x1EA9]={
+ adobename="acircumflexhookabove",
+ category="ll",
+ contextname="acircumflexhook",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE2, 0x309 },
+ uccode=0x1EA8,
+ unicodeslot=0x1EA9,
+ },
+ [0x1EAA]={
+ adobename="Acircumflextilde",
+ category="lu",
+ contextname="Acircumflextilde",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ lccode=0x1EAB,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0xC2, 0x303 },
+ unicodeslot=0x1EAA,
+ },
+ [0x1EAB]={
+ adobename="acircumflextilde",
+ category="ll",
+ contextname="acircumflextilde",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0xE2, 0x303 },
+ uccode=0x1EAA,
+ unicodeslot=0x1EAB,
+ },
+ [0x1EAC]={
+ adobename="Acircumflexdotbelow",
+ category="lu",
+ contextname="Acircumflexdotbelow",
+ description="LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ lccode=0x1EAD,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x1EA0, 0x302 },
+ unicodeslot=0x1EAC,
+ },
+ [0x1EAD]={
+ adobename="acircumflexdotbelow",
+ category="ll",
+ contextname="acircumflexdotbelow",
+ description="LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x1EA1, 0x302 },
+ uccode=0x1EAC,
+ unicodeslot=0x1EAD,
+ },
+ [0x1EAE]={
+ adobename="Abreveacute",
+ category="lu",
+ contextname="Abreveacute",
+ description="LATIN CAPITAL LETTER A WITH BREVE AND ACUTE",
+ direction="l",
+ lccode=0x1EAF,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x102, 0x301 },
+ unicodeslot=0x1EAE,
+ },
+ [0x1EAF]={
+ adobename="abreveacute",
+ category="ll",
+ contextname="abreveacute",
+ description="LATIN SMALL LETTER A WITH BREVE AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x103, 0x301 },
+ uccode=0x1EAE,
+ unicodeslot=0x1EAF,
+ },
+ [0x1EB0]={
+ adobename="Abrevegrave",
+ category="lu",
+ contextname="Abrevegrave",
+ description="LATIN CAPITAL LETTER A WITH BREVE AND GRAVE",
+ direction="l",
+ lccode=0x1EB1,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x102, 0x300 },
+ unicodeslot=0x1EB0,
+ },
+ [0x1EB1]={
+ adobename="abrevegrave",
+ category="ll",
+ contextname="abrevegrave",
+ description="LATIN SMALL LETTER A WITH BREVE AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x103, 0x300 },
+ uccode=0x1EB0,
+ unicodeslot=0x1EB1,
+ },
+ [0x1EB2]={
+ adobename="Abrevehookabove",
+ category="lu",
+ contextname="Abrevehook",
+ description="LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1EB3,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x102, 0x309 },
+ unicodeslot=0x1EB2,
+ },
+ [0x1EB3]={
+ adobename="abrevehookabove",
+ category="ll",
+ contextname="abrevehook",
+ description="LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x103, 0x309 },
+ uccode=0x1EB2,
+ unicodeslot=0x1EB3,
+ },
+ [0x1EB4]={
+ adobename="Abrevetilde",
+ category="lu",
+ contextname="Abrevetilde",
+ description="LATIN CAPITAL LETTER A WITH BREVE AND TILDE",
+ direction="l",
+ lccode=0x1EB5,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x102, 0x303 },
+ unicodeslot=0x1EB4,
+ },
+ [0x1EB5]={
+ adobename="abrevetilde",
+ category="ll",
+ contextname="abrevetilde",
+ description="LATIN SMALL LETTER A WITH BREVE AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x103, 0x303 },
+ uccode=0x1EB4,
+ unicodeslot=0x1EB5,
+ },
+ [0x1EB6]={
+ adobename="Abrevedotbelow",
+ category="lu",
+ contextname="Abrevedotbelow",
+ description="LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW",
+ direction="l",
+ lccode=0x1EB7,
+ linebreak="al",
+ shcode=0x41,
+ specials={ "char", 0x1EA0, 0x306 },
+ unicodeslot=0x1EB6,
+ },
+ [0x1EB7]={
+ adobename="abrevedotbelow",
+ category="ll",
+ contextname="abrevedotbelow",
+ description="LATIN SMALL LETTER A WITH BREVE AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ specials={ "char", 0x1EA1, 0x306 },
+ uccode=0x1EB6,
+ unicodeslot=0x1EB7,
+ },
+ [0x1EB8]={
+ adobename="Edotbelow",
+ category="lu",
+ contextname="Edotbelow",
+ description="LATIN CAPITAL LETTER E WITH DOT BELOW",
+ direction="l",
+ lccode=0x1EB9,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x323 },
+ unicodeslot=0x1EB8,
+ },
+ [0x1EB9]={
+ adobename="edotbelow",
+ category="ll",
+ contextname="edotbelow",
+ description="LATIN SMALL LETTER E WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x323 },
+ uccode=0x1EB8,
+ unicodeslot=0x1EB9,
+ },
+ [0x1EBA]={
+ adobename="Ehookabove",
+ category="lu",
+ contextname="Ehook",
+ description="LATIN CAPITAL LETTER E WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1EBB,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x309 },
+ unicodeslot=0x1EBA,
+ },
+ [0x1EBB]={
+ adobename="ehookabove",
+ category="ll",
+ contextname="ehook",
+ description="LATIN SMALL LETTER E WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x309 },
+ uccode=0x1EBA,
+ unicodeslot=0x1EBB,
+ },
+ [0x1EBC]={
+ adobename="Etilde",
+ category="lu",
+ contextname="Etilde",
+ description="LATIN CAPITAL LETTER E WITH TILDE",
+ direction="l",
+ lccode=0x1EBD,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x45, 0x303 },
+ unicodeslot=0x1EBC,
+ },
+ [0x1EBD]={
+ adobename="etilde",
+ category="ll",
+ contextname="etilde",
+ description="LATIN SMALL LETTER E WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x65, 0x303 },
+ uccode=0x1EBC,
+ unicodeslot=0x1EBD,
+ },
+ [0x1EBE]={
+ adobename="Ecircumflexacute",
+ category="lu",
+ contextname="Ecircumflexacute",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ lccode=0x1EBF,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0xCA, 0x301 },
+ unicodeslot=0x1EBE,
+ },
+ [0x1EBF]={
+ adobename="ecircumflexacute",
+ category="ll",
+ contextname="ecircumflexacute",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0xEA, 0x301 },
+ uccode=0x1EBE,
+ unicodeslot=0x1EBF,
+ },
+ [0x1EC0]={
+ adobename="Ecircumflexgrave",
+ category="lu",
+ contextname="Ecircumflexgrave",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ lccode=0x1EC1,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0xCA, 0x300 },
+ unicodeslot=0x1EC0,
+ },
+ [0x1EC1]={
+ adobename="ecircumflexgrave",
+ category="ll",
+ contextname="ecircumflexgrave",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0xEA, 0x300 },
+ uccode=0x1EC0,
+ unicodeslot=0x1EC1,
+ },
+ [0x1EC2]={
+ adobename="Ecircumflexhookabove",
+ category="lu",
+ contextname="Ecircumflexhook",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1EC3,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0xCA, 0x309 },
+ unicodeslot=0x1EC2,
+ },
+ [0x1EC3]={
+ adobename="ecircumflexhookabove",
+ category="ll",
+ contextname="ecircumflexhook",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0xEA, 0x309 },
+ uccode=0x1EC2,
+ unicodeslot=0x1EC3,
+ },
+ [0x1EC4]={
+ adobename="Ecircumflextilde",
+ category="lu",
+ contextname="Ecircumflextilde",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ lccode=0x1EC5,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0xCA, 0x303 },
+ unicodeslot=0x1EC4,
+ },
+ [0x1EC5]={
+ adobename="ecircumflextilde",
+ category="ll",
+ contextname="ecircumflextilde",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0xEA, 0x303 },
+ uccode=0x1EC4,
+ unicodeslot=0x1EC5,
+ },
+ [0x1EC6]={
+ adobename="Ecircumflexdotbelow",
+ category="lu",
+ contextname="Ecircumflexdotbelow",
+ description="LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ lccode=0x1EC7,
+ linebreak="al",
+ shcode=0x45,
+ specials={ "char", 0x1EB8, 0x302 },
+ unicodeslot=0x1EC6,
+ },
+ [0x1EC7]={
+ adobename="ecircumflexdotbelow",
+ category="ll",
+ contextname="ecircumflexdotbelow",
+ description="LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x65,
+ specials={ "char", 0x1EB9, 0x302 },
+ uccode=0x1EC6,
+ unicodeslot=0x1EC7,
+ },
+ [0x1EC8]={
+ adobename="Ihookabove",
+ category="lu",
+ contextname="Ihook",
+ description="LATIN CAPITAL LETTER I WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1EC9,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x309 },
+ unicodeslot=0x1EC8,
+ },
+ [0x1EC9]={
+ adobename="ihookabove",
+ category="ll",
+ contextname="ihook",
+ description="LATIN SMALL LETTER I WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x309 },
+ uccode=0x1EC8,
+ unicodeslot=0x1EC9,
+ },
+ [0x1ECA]={
+ adobename="Idotbelow",
+ category="lu",
+ contextname="Idotbelow",
+ description="LATIN CAPITAL LETTER I WITH DOT BELOW",
+ direction="l",
+ lccode=0x1ECB,
+ linebreak="al",
+ shcode=0x49,
+ specials={ "char", 0x49, 0x323 },
+ unicodeslot=0x1ECA,
+ },
+ [0x1ECB]={
+ adobename="idotbelow",
+ category="ll",
+ contextname="idotbelow",
+ description="LATIN SMALL LETTER I WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x69,
+ specials={ "char", 0x69, 0x323 },
+ uccode=0x1ECA,
+ unicodeslot=0x1ECB,
+ },
+ [0x1ECC]={
+ adobename="Odotbelow",
+ category="lu",
+ contextname="Odotbelow",
+ description="LATIN CAPITAL LETTER O WITH DOT BELOW",
+ direction="l",
+ lccode=0x1ECD,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x323 },
+ unicodeslot=0x1ECC,
+ },
+ [0x1ECD]={
+ adobename="odotbelow",
+ category="ll",
+ contextname="odotbelow",
+ description="LATIN SMALL LETTER O WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x323 },
+ uccode=0x1ECC,
+ unicodeslot=0x1ECD,
+ },
+ [0x1ECE]={
+ adobename="Ohookabove",
+ category="lu",
+ contextname="Ohook",
+ description="LATIN CAPITAL LETTER O WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1ECF,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x4F, 0x309 },
+ unicodeslot=0x1ECE,
+ },
+ [0x1ECF]={
+ adobename="ohookabove",
+ category="ll",
+ contextname="ohook",
+ description="LATIN SMALL LETTER O WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x6F, 0x309 },
+ uccode=0x1ECE,
+ unicodeslot=0x1ECF,
+ },
+ [0x1ED0]={
+ adobename="Ocircumflexacute",
+ category="lu",
+ contextname="Ocircumflexacute",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ lccode=0x1ED1,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD4, 0x301 },
+ unicodeslot=0x1ED0,
+ },
+ [0x1ED1]={
+ adobename="ocircumflexacute",
+ category="ll",
+ contextname="ocircumflexacute",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF4, 0x301 },
+ uccode=0x1ED0,
+ unicodeslot=0x1ED1,
+ },
+ [0x1ED2]={
+ adobename="Ocircumflexgrave",
+ category="lu",
+ contextname="Ocircumflexgrave",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ lccode=0x1ED3,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD4, 0x300 },
+ unicodeslot=0x1ED2,
+ },
+ [0x1ED3]={
+ adobename="ocircumflexgrave",
+ category="ll",
+ contextname="ocircumflexgrave",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF4, 0x300 },
+ uccode=0x1ED2,
+ unicodeslot=0x1ED3,
+ },
+ [0x1ED4]={
+ adobename="Ocircumflexhookabove",
+ category="lu",
+ contextname="Ocircumflexhook",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1ED5,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD4, 0x309 },
+ unicodeslot=0x1ED4,
+ },
+ [0x1ED5]={
+ adobename="ocircumflexhookabove",
+ category="ll",
+ contextname="ocircumflexhook",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF4, 0x309 },
+ uccode=0x1ED4,
+ unicodeslot=0x1ED5,
+ },
+ [0x1ED6]={
+ adobename="Ocircumflextilde",
+ category="lu",
+ contextname="Ocircumflextilde",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ lccode=0x1ED7,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0xD4, 0x303 },
+ unicodeslot=0x1ED6,
+ },
+ [0x1ED7]={
+ adobename="ocircumflextilde",
+ category="ll",
+ contextname="ocircumflextilde",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0xF4, 0x303 },
+ uccode=0x1ED6,
+ unicodeslot=0x1ED7,
+ },
+ [0x1ED8]={
+ adobename="Ocircumflexdotbelow",
+ category="lu",
+ contextname="Ocircumflexdotbelow",
+ description="LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ lccode=0x1ED9,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1ECC, 0x302 },
+ unicodeslot=0x1ED8,
+ },
+ [0x1ED9]={
+ adobename="ocircumflexdotbelow",
+ category="ll",
+ contextname="ocircumflexdotbelow",
+ description="LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1ECD, 0x302 },
+ uccode=0x1ED8,
+ unicodeslot=0x1ED9,
+ },
+ [0x1EDA]={
+ adobename="Ohornacute",
+ category="lu",
+ contextname="Ohornacute",
+ description="LATIN CAPITAL LETTER O WITH HORN AND ACUTE",
+ direction="l",
+ lccode=0x1EDB,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1A0, 0x301 },
+ unicodeslot=0x1EDA,
+ },
+ [0x1EDB]={
+ adobename="ohornacute",
+ category="ll",
+ contextname="ohornacute",
+ description="LATIN SMALL LETTER O WITH HORN AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1A1, 0x301 },
+ uccode=0x1EDA,
+ unicodeslot=0x1EDB,
+ },
+ [0x1EDC]={
+ adobename="Ohorngrave",
+ category="lu",
+ contextname="Ohorngrave",
+ description="LATIN CAPITAL LETTER O WITH HORN AND GRAVE",
+ direction="l",
+ lccode=0x1EDD,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1A0, 0x300 },
+ unicodeslot=0x1EDC,
+ },
+ [0x1EDD]={
+ adobename="ohorngrave",
+ category="ll",
+ contextname="ohorngrave",
+ description="LATIN SMALL LETTER O WITH HORN AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1A1, 0x300 },
+ uccode=0x1EDC,
+ unicodeslot=0x1EDD,
+ },
+ [0x1EDE]={
+ adobename="Ohornhookabove",
+ category="lu",
+ contextname="Ohornhook",
+ description="LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1EDF,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1A0, 0x309 },
+ unicodeslot=0x1EDE,
+ },
+ [0x1EDF]={
+ adobename="ohornhookabove",
+ category="ll",
+ contextname="ohornhook",
+ description="LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1A1, 0x309 },
+ uccode=0x1EDE,
+ unicodeslot=0x1EDF,
+ },
+ [0x1EE0]={
+ adobename="Ohorntilde",
+ category="lu",
+ contextname="Ohorntilde",
+ description="LATIN CAPITAL LETTER O WITH HORN AND TILDE",
+ direction="l",
+ lccode=0x1EE1,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1A0, 0x303 },
+ unicodeslot=0x1EE0,
+ },
+ [0x1EE1]={
+ adobename="ohorntilde",
+ category="ll",
+ contextname="ohorntilde",
+ description="LATIN SMALL LETTER O WITH HORN AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1A1, 0x303 },
+ uccode=0x1EE0,
+ unicodeslot=0x1EE1,
+ },
+ [0x1EE2]={
+ adobename="Ohorndotbelow",
+ category="lu",
+ contextname="Ohorndotbelow",
+ description="LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW",
+ direction="l",
+ lccode=0x1EE3,
+ linebreak="al",
+ shcode=0x4F,
+ specials={ "char", 0x1A0, 0x323 },
+ unicodeslot=0x1EE2,
+ },
+ [0x1EE3]={
+ adobename="ohorndotbelow",
+ category="ll",
+ contextname="ohorndotbelow",
+ description="LATIN SMALL LETTER O WITH HORN AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x6F,
+ specials={ "char", 0x1A1, 0x323 },
+ uccode=0x1EE2,
+ unicodeslot=0x1EE3,
+ },
+ [0x1EE4]={
+ adobename="Udotbelow",
+ category="lu",
+ contextname="Udotbelow",
+ description="LATIN CAPITAL LETTER U WITH DOT BELOW",
+ direction="l",
+ lccode=0x1EE5,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x323 },
+ unicodeslot=0x1EE4,
+ },
+ [0x1EE5]={
+ adobename="udotbelow",
+ category="ll",
+ contextname="udotbelow",
+ description="LATIN SMALL LETTER U WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x323 },
+ uccode=0x1EE4,
+ unicodeslot=0x1EE5,
+ },
+ [0x1EE6]={
+ adobename="Uhookabove",
+ category="lu",
+ contextname="Uhook",
+ description="LATIN CAPITAL LETTER U WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1EE7,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x55, 0x309 },
+ unicodeslot=0x1EE6,
+ },
+ [0x1EE7]={
+ adobename="uhookabove",
+ category="ll",
+ contextname="uhook",
+ description="LATIN SMALL LETTER U WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x75, 0x309 },
+ uccode=0x1EE6,
+ unicodeslot=0x1EE7,
+ },
+ [0x1EE8]={
+ adobename="Uhornacute",
+ category="lu",
+ contextname="Uhornacute",
+ description="LATIN CAPITAL LETTER U WITH HORN AND ACUTE",
+ direction="l",
+ lccode=0x1EE9,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x1AF, 0x301 },
+ unicodeslot=0x1EE8,
+ },
+ [0x1EE9]={
+ adobename="uhornacute",
+ category="ll",
+ contextname="uhornacute",
+ description="LATIN SMALL LETTER U WITH HORN AND ACUTE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x1B0, 0x301 },
+ uccode=0x1EE8,
+ unicodeslot=0x1EE9,
+ },
+ [0x1EEA]={
+ adobename="Uhorngrave",
+ category="lu",
+ contextname="Uhorngrave",
+ description="LATIN CAPITAL LETTER U WITH HORN AND GRAVE",
+ direction="l",
+ lccode=0x1EEB,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x1AF, 0x300 },
+ unicodeslot=0x1EEA,
+ },
+ [0x1EEB]={
+ adobename="uhorngrave",
+ category="ll",
+ contextname="uhorngrave",
+ description="LATIN SMALL LETTER U WITH HORN AND GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x1B0, 0x300 },
+ uccode=0x1EEA,
+ unicodeslot=0x1EEB,
+ },
+ [0x1EEC]={
+ adobename="Uhornhookabove",
+ category="lu",
+ contextname="Uhornhook",
+ description="LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE",
+ direction="l",
+ lccode=0x1EED,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x1AF, 0x309 },
+ unicodeslot=0x1EEC,
+ },
+ [0x1EED]={
+ adobename="uhornhookabove",
+ category="ll",
+ contextname="uhornhook",
+ description="LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x1B0, 0x309 },
+ uccode=0x1EEC,
+ unicodeslot=0x1EED,
+ },
+ [0x1EEE]={
+ adobename="Uhorntilde",
+ category="lu",
+ contextname="Uhorntilde",
+ description="LATIN CAPITAL LETTER U WITH HORN AND TILDE",
+ direction="l",
+ lccode=0x1EEF,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x1AF, 0x303 },
+ unicodeslot=0x1EEE,
+ },
+ [0x1EEF]={
+ adobename="uhorntilde",
+ category="ll",
+ contextname="uhorntilde",
+ description="LATIN SMALL LETTER U WITH HORN AND TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x1B0, 0x303 },
+ uccode=0x1EEE,
+ unicodeslot=0x1EEF,
+ },
+ [0x1EF0]={
+ adobename="Uhorndotbelow",
+ category="lu",
+ contextname="Uhorndotbelow",
+ description="LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW",
+ direction="l",
+ lccode=0x1EF1,
+ linebreak="al",
+ shcode=0x55,
+ specials={ "char", 0x1AF, 0x323 },
+ unicodeslot=0x1EF0,
+ },
+ [0x1EF1]={
+ adobename="uhorndotbelow",
+ category="ll",
+ contextname="uhorndotbelow",
+ description="LATIN SMALL LETTER U WITH HORN AND DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x75,
+ specials={ "char", 0x1B0, 0x323 },
+ uccode=0x1EF0,
+ unicodeslot=0x1EF1,
+ },
+ [0x1EF2]={
+ adobename="Ygrave",
+ category="lu",
+ contextname="Ygrave",
+ description="LATIN CAPITAL LETTER Y WITH GRAVE",
+ direction="l",
+ lccode=0x1EF3,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x300 },
+ unicodeslot=0x1EF2,
+ },
+ [0x1EF3]={
+ adobename="ygrave",
+ category="ll",
+ contextname="ygrave",
+ description="LATIN SMALL LETTER Y WITH GRAVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x300 },
+ uccode=0x1EF2,
+ unicodeslot=0x1EF3,
+ },
+ [0x1EF4]={
+ adobename="Ydotbelow",
+ category="lu",
+ contextname="Ydotbelow",
+ description="LATIN CAPITAL LETTER Y WITH DOT BELOW",
+ direction="l",
+ lccode=0x1EF5,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x323 },
+ unicodeslot=0x1EF4,
+ },
+ [0x1EF5]={
+ adobename="ydotbelow",
+ category="ll",
+ contextname="ydotbelow",
+ description="LATIN SMALL LETTER Y WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x323 },
+ uccode=0x1EF4,
+ unicodeslot=0x1EF5,
+ },
+ [0x1EF6]={
+ adobename="Yhookabove",
+ category="lu",
+ contextname="Yhook",
+ description="LATIN CAPITAL LETTER Y WITH HOOK ABOVE",
+ direction="l",
+ lccode=0x1EF7,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x309 },
+ unicodeslot=0x1EF6,
+ },
+ [0x1EF7]={
+ adobename="yhookabove",
+ category="ll",
+ contextname="yhook",
+ description="LATIN SMALL LETTER Y WITH HOOK ABOVE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x309 },
+ uccode=0x1EF6,
+ unicodeslot=0x1EF7,
+ },
+ [0x1EF8]={
+ adobename="Ytilde",
+ category="lu",
+ contextname="Ytilde",
+ description="LATIN CAPITAL LETTER Y WITH TILDE",
+ direction="l",
+ lccode=0x1EF9,
+ linebreak="al",
+ shcode=0x59,
+ specials={ "char", 0x59, 0x303 },
+ unicodeslot=0x1EF8,
+ },
+ [0x1EF9]={
+ adobename="ytilde",
+ category="ll",
+ contextname="ytilde",
+ description="LATIN SMALL LETTER Y WITH TILDE",
+ direction="l",
+ linebreak="al",
+ shcode=0x79,
+ specials={ "char", 0x79, 0x303 },
+ uccode=0x1EF8,
+ unicodeslot=0x1EF9,
+ },
+ [0x1EFA]={
+ category="lu",
+ description="LATIN CAPITAL LETTER MIDDLE-WELSH LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFA,
+ },
+ [0x1EFB]={
+ category="ll",
+ description="LATIN SMALL LETTER MIDDLE-WELSH LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFB,
+ },
+ [0x1EFC]={
+ category="lu",
+ description="LATIN CAPITAL LETTER MIDDLE-WELSH V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFC,
+ },
+ [0x1EFD]={
+ category="ll",
+ description="LATIN SMALL LETTER MIDDLE-WELSH V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFD,
+ },
+ [0x1EFE]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Y WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFE,
+ },
+ [0x1EFF]={
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFF,
+ },
+ [0x1F00]={
+ category="ll",
+ contextname="greekalphapsili",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x313 },
+ uccode=0x1F08,
+ unicodeslot=0x1F00,
+ },
+ [0x1F01]={
+ category="ll",
+ contextname="greekalphadasia",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x314 },
+ uccode=0x1F09,
+ unicodeslot=0x1F01,
+ },
+ [0x1F02]={
+ category="ll",
+ contextname="greekalphapsilivaria",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F00, 0x300 },
+ uccode=0x1F0A,
+ unicodeslot=0x1F02,
+ },
+ [0x1F03]={
+ category="ll",
+ contextname="greekalphadasiavaria",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F01, 0x300 },
+ uccode=0x1F0B,
+ unicodeslot=0x1F03,
+ },
+ [0x1F04]={
+ category="ll",
+ contextname="greekalphapsilitonos",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F00, 0x301 },
+ uccode=0x1F0C,
+ unicodeslot=0x1F04,
+ },
+ [0x1F05]={
+ category="ll",
+ contextname="greekalphadasiatonos",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F01, 0x301 },
+ uccode=0x1F0D,
+ unicodeslot=0x1F05,
+ },
+ [0x1F06]={
+ category="ll",
+ contextname="greekalphapsiliperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F00, 0x342 },
+ uccode=0x1F0E,
+ unicodeslot=0x1F06,
+ },
+ [0x1F07]={
+ category="ll",
+ contextname="greekalphadasiaperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F01, 0x342 },
+ uccode=0x1F0F,
+ unicodeslot=0x1F07,
+ },
+ [0x1F08]={
+ category="lu",
+ contextname="greekAlphapsili",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI",
+ direction="l",
+ lccode=0x1F00,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x313 },
+ unicodeslot=0x1F08,
+ },
+ [0x1F09]={
+ category="lu",
+ contextname="greekAlphadasia",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA",
+ direction="l",
+ lccode=0x1F01,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x314 },
+ unicodeslot=0x1F09,
+ },
+ [0x1F0A]={
+ category="lu",
+ contextname="greekAlphapsilivaria",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F02,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F08, 0x300 },
+ unicodeslot=0x1F0A,
+ },
+ [0x1F0B]={
+ category="lu",
+ contextname="greekAlphadasiavaria",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F03,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F09, 0x300 },
+ unicodeslot=0x1F0B,
+ },
+ [0x1F0C]={
+ category="lu",
+ contextname="greekAlphapsilitonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F04,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F08, 0x301 },
+ unicodeslot=0x1F0C,
+ },
+ [0x1F0D]={
+ category="lu",
+ contextname="greekAlphadasiatonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F05,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F09, 0x301 },
+ unicodeslot=0x1F0D,
+ },
+ [0x1F0E]={
+ category="lu",
+ contextname="greekAlphapsiliperispomeni",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F06,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F08, 0x342 },
+ unicodeslot=0x1F0E,
+ },
+ [0x1F0F]={
+ category="lu",
+ contextname="greekAlphadasiaperispomeni",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F07,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F09, 0x342 },
+ unicodeslot=0x1F0F,
+ },
+ [0x1F10]={
+ category="ll",
+ contextname="greekepsilonpsili",
+ description="GREEK SMALL LETTER EPSILON WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x3B5, 0x313 },
+ uccode=0x1F18,
+ unicodeslot=0x1F10,
+ },
+ [0x1F11]={
+ category="ll",
+ contextname="greekepsilondasia",
+ description="GREEK SMALL LETTER EPSILON WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x3B5, 0x314 },
+ uccode=0x1F19,
+ unicodeslot=0x1F11,
+ },
+ [0x1F12]={
+ category="ll",
+ contextname="greekepsilonpsilivaria",
+ description="GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x1F10, 0x300 },
+ uccode=0x1F1A,
+ unicodeslot=0x1F12,
+ },
+ [0x1F13]={
+ category="ll",
+ contextname="greekepsilondasiavaria",
+ description="GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x1F11, 0x300 },
+ uccode=0x1F1B,
+ unicodeslot=0x1F13,
+ },
+ [0x1F14]={
+ category="ll",
+ contextname="greekepsilonpsilitonos",
+ description="GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x1F10, 0x301 },
+ uccode=0x1F1C,
+ unicodeslot=0x1F14,
+ },
+ [0x1F15]={
+ category="ll",
+ contextname="greekepsilondasiatonos",
+ description="GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x1F11, 0x301 },
+ uccode=0x1F1D,
+ unicodeslot=0x1F15,
+ },
+ [0x1F18]={
+ category="lu",
+ contextname="greekEpsilonpsili",
+ description="GREEK CAPITAL LETTER EPSILON WITH PSILI",
+ direction="l",
+ lccode=0x1F10,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x395, 0x313 },
+ unicodeslot=0x1F18,
+ },
+ [0x1F19]={
+ category="lu",
+ contextname="greekEpsilondasia",
+ description="GREEK CAPITAL LETTER EPSILON WITH DASIA",
+ direction="l",
+ lccode=0x1F11,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x395, 0x314 },
+ unicodeslot=0x1F19,
+ },
+ [0x1F1A]={
+ category="lu",
+ contextname="greekEpsilonpsilivaria",
+ description="GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F12,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x1F18, 0x300 },
+ unicodeslot=0x1F1A,
+ },
+ [0x1F1B]={
+ category="lu",
+ contextname="greekEpsilondasiavaria",
+ description="GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F13,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x1F19, 0x300 },
+ unicodeslot=0x1F1B,
+ },
+ [0x1F1C]={
+ category="lu",
+ contextname="greekEpsilonpsilitonos",
+ description="GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F14,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x1F18, 0x301 },
+ unicodeslot=0x1F1C,
+ },
+ [0x1F1D]={
+ category="lu",
+ contextname="greekEpsilondasiatonos",
+ description="GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F15,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x1F19, 0x301 },
+ unicodeslot=0x1F1D,
+ },
+ [0x1F20]={
+ category="ll",
+ contextname="greeketapsili",
+ description="GREEK SMALL LETTER ETA WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x313 },
+ uccode=0x1F28,
+ unicodeslot=0x1F20,
+ },
+ [0x1F21]={
+ category="ll",
+ contextname="greeketadasia",
+ description="GREEK SMALL LETTER ETA WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x314 },
+ uccode=0x1F29,
+ unicodeslot=0x1F21,
+ },
+ [0x1F22]={
+ category="ll",
+ contextname="greeketapsilivaria",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F20, 0x300 },
+ uccode=0x1F2A,
+ unicodeslot=0x1F22,
+ },
+ [0x1F23]={
+ category="ll",
+ contextname="greeketadasiavaria",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F21, 0x300 },
+ uccode=0x1F2B,
+ unicodeslot=0x1F23,
+ },
+ [0x1F24]={
+ category="ll",
+ contextname="greeketapsilitonos",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F20, 0x301 },
+ uccode=0x1F2C,
+ unicodeslot=0x1F24,
+ },
+ [0x1F25]={
+ category="ll",
+ contextname="greeketadasiatonos",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F21, 0x301 },
+ uccode=0x1F2D,
+ unicodeslot=0x1F25,
+ },
+ [0x1F26]={
+ category="ll",
+ contextname="greeketapsiliperispomeni",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F20, 0x342 },
+ uccode=0x1F2E,
+ unicodeslot=0x1F26,
+ },
+ [0x1F27]={
+ category="ll",
+ contextname="greeketadasiaperispomeni",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F21, 0x342 },
+ uccode=0x1F2F,
+ unicodeslot=0x1F27,
+ },
+ [0x1F28]={
+ category="lu",
+ contextname="greekEtapsili",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI",
+ direction="l",
+ lccode=0x1F20,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x397, 0x313 },
+ unicodeslot=0x1F28,
+ },
+ [0x1F29]={
+ category="lu",
+ contextname="greekEtadasia",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA",
+ direction="l",
+ lccode=0x1F21,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x397, 0x314 },
+ unicodeslot=0x1F29,
+ },
+ [0x1F2A]={
+ category="lu",
+ contextname="greekEtapsilivaria",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F22,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F28, 0x300 },
+ unicodeslot=0x1F2A,
+ },
+ [0x1F2B]={
+ category="lu",
+ contextname="greekEtadasiavaria",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F23,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F29, 0x300 },
+ unicodeslot=0x1F2B,
+ },
+ [0x1F2C]={
+ category="lu",
+ contextname="greekEtapsilitonos",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F24,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F28, 0x301 },
+ unicodeslot=0x1F2C,
+ },
+ [0x1F2D]={
+ category="lu",
+ contextname="greekEtadasiatonos",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F25,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F29, 0x301 },
+ unicodeslot=0x1F2D,
+ },
+ [0x1F2E]={
+ category="lu",
+ contextname="greekEtapsiliperispomeni",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F26,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F28, 0x342 },
+ unicodeslot=0x1F2E,
+ },
+ [0x1F2F]={
+ category="lu",
+ contextname="greekEtadasiaperispomeni",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F27,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F29, 0x342 },
+ unicodeslot=0x1F2F,
+ },
+ [0x1F30]={
+ category="ll",
+ contextname="greekiotapsili",
+ description="GREEK SMALL LETTER IOTA WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x313 },
+ uccode=0x1F38,
+ unicodeslot=0x1F30,
+ },
+ [0x1F31]={
+ category="ll",
+ contextname="greekiotadasia",
+ description="GREEK SMALL LETTER IOTA WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x314 },
+ uccode=0x1F39,
+ unicodeslot=0x1F31,
+ },
+ [0x1F32]={
+ category="ll",
+ contextname="greekiotapsilivaria",
+ description="GREEK SMALL LETTER IOTA WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F30, 0x300 },
+ uccode=0x1F3A,
+ unicodeslot=0x1F32,
+ },
+ [0x1F33]={
+ category="ll",
+ contextname="greekiotadasiavaria",
+ description="GREEK SMALL LETTER IOTA WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F31, 0x300 },
+ uccode=0x1F3B,
+ unicodeslot=0x1F33,
+ },
+ [0x1F34]={
+ category="ll",
+ contextname="greekiotapsilitonos",
+ description="GREEK SMALL LETTER IOTA WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F30, 0x301 },
+ uccode=0x1F3C,
+ unicodeslot=0x1F34,
+ },
+ [0x1F35]={
+ category="ll",
+ contextname="greekiotadasiatonos",
+ description="GREEK SMALL LETTER IOTA WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F31, 0x301 },
+ uccode=0x1F3D,
+ unicodeslot=0x1F35,
+ },
+ [0x1F36]={
+ category="ll",
+ contextname="greekiotapsiliperispomeni",
+ description="GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F30, 0x342 },
+ uccode=0x1F3E,
+ unicodeslot=0x1F36,
+ },
+ [0x1F37]={
+ category="ll",
+ contextname="greekiotadasiaperispomeni",
+ description="GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x1F31, 0x342 },
+ uccode=0x1F3F,
+ unicodeslot=0x1F37,
+ },
+ [0x1F38]={
+ category="lu",
+ contextname="greekIotapsili",
+ description="GREEK CAPITAL LETTER IOTA WITH PSILI",
+ direction="l",
+ lccode=0x1F30,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x313 },
+ unicodeslot=0x1F38,
+ },
+ [0x1F39]={
+ category="lu",
+ contextname="greekIotadasia",
+ description="GREEK CAPITAL LETTER IOTA WITH DASIA",
+ direction="l",
+ lccode=0x1F31,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x314 },
+ unicodeslot=0x1F39,
+ },
+ [0x1F3A]={
+ category="lu",
+ contextname="greekIotapsilivaria",
+ description="GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F32,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F38, 0x300 },
+ unicodeslot=0x1F3A,
+ },
+ [0x1F3B]={
+ category="lu",
+ contextname="greekIotadasiavaria",
+ description="GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F33,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F39, 0x300 },
+ unicodeslot=0x1F3B,
+ },
+ [0x1F3C]={
+ category="lu",
+ contextname="greekIotapsilitonos",
+ description="GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F34,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F38, 0x301 },
+ unicodeslot=0x1F3C,
+ },
+ [0x1F3D]={
+ category="lu",
+ contextname="greekIotadasiatonos",
+ description="GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F35,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F39, 0x301 },
+ unicodeslot=0x1F3D,
+ },
+ [0x1F3E]={
+ category="lu",
+ contextname="greekIotapsiliperispomeni",
+ description="GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F36,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F38, 0x342 },
+ unicodeslot=0x1F3E,
+ },
+ [0x1F3F]={
+ category="lu",
+ contextname="greekIotadasiaperispomeni",
+ description="GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F37,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x1F39, 0x342 },
+ unicodeslot=0x1F3F,
+ },
+ [0x1F40]={
+ category="ll",
+ contextname="greekomicronpsili",
+ description="GREEK SMALL LETTER OMICRON WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x3BF, 0x313 },
+ uccode=0x1F48,
+ unicodeslot=0x1F40,
+ },
+ [0x1F41]={
+ category="ll",
+ contextname="greekomicrondasia",
+ description="GREEK SMALL LETTER OMICRON WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x3BF, 0x314 },
+ uccode=0x1F49,
+ unicodeslot=0x1F41,
+ },
+ [0x1F42]={
+ category="ll",
+ contextname="greekomicronpsilivaria",
+ description="GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x1F40, 0x300 },
+ uccode=0x1F4A,
+ unicodeslot=0x1F42,
+ },
+ [0x1F43]={
+ category="ll",
+ contextname="greekomicrondasiavaria",
+ description="GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x1F41, 0x300 },
+ uccode=0x1F4B,
+ unicodeslot=0x1F43,
+ },
+ [0x1F44]={
+ category="ll",
+ contextname="greekomicronpsilitonos",
+ description="GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x1F40, 0x301 },
+ uccode=0x1F4C,
+ unicodeslot=0x1F44,
+ },
+ [0x1F45]={
+ category="ll",
+ contextname="greekomicrondasiatonos",
+ description="GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x1F41, 0x301 },
+ uccode=0x1F4D,
+ unicodeslot=0x1F45,
+ },
+ [0x1F48]={
+ category="lu",
+ contextname="greekOmicronpsili",
+ description="GREEK CAPITAL LETTER OMICRON WITH PSILI",
+ direction="l",
+ lccode=0x1F40,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x39F, 0x313 },
+ unicodeslot=0x1F48,
+ },
+ [0x1F49]={
+ category="lu",
+ contextname="greekOmicrondasia",
+ description="GREEK CAPITAL LETTER OMICRON WITH DASIA",
+ direction="l",
+ lccode=0x1F41,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x39F, 0x314 },
+ unicodeslot=0x1F49,
+ },
+ [0x1F4A]={
+ category="lu",
+ contextname="greekOmicronpsilivaria",
+ description="GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F42,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x1F48, 0x300 },
+ unicodeslot=0x1F4A,
+ },
+ [0x1F4B]={
+ category="lu",
+ contextname="greekOmicrondasiavaria",
+ description="GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F43,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x1F49, 0x300 },
+ unicodeslot=0x1F4B,
+ },
+ [0x1F4C]={
+ category="lu",
+ contextname="greekOmicronpsilitonos",
+ description="GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F44,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x1F48, 0x301 },
+ unicodeslot=0x1F4C,
+ },
+ [0x1F4D]={
+ category="lu",
+ contextname="greekOmicrondasiatonos",
+ description="GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F45,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x1F49, 0x301 },
+ unicodeslot=0x1F4D,
+ },
+ [0x1F50]={
+ category="ll",
+ contextname="greekupsilonpsili",
+ description="GREEK SMALL LETTER UPSILON WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x313 },
+ unicodeslot=0x1F50,
+ },
+ [0x1F51]={
+ category="ll",
+ contextname="greekupsilondasia",
+ description="GREEK SMALL LETTER UPSILON WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x314 },
+ uccode=0x1F59,
+ unicodeslot=0x1F51,
+ },
+ [0x1F52]={
+ category="ll",
+ contextname="greekupsilonpsilivaria",
+ description="GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F50, 0x300 },
+ unicodeslot=0x1F52,
+ },
+ [0x1F53]={
+ category="ll",
+ contextname="greekupsilondasiavaria",
+ description="GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F51, 0x300 },
+ uccode=0x1F5B,
+ unicodeslot=0x1F53,
+ },
+ [0x1F54]={
+ category="ll",
+ contextname="greekupsilonpsilitonos",
+ description="GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F50, 0x301 },
+ unicodeslot=0x1F54,
+ },
+ [0x1F55]={
+ category="ll",
+ contextname="greekupsilondasiatonos",
+ description="GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F51, 0x301 },
+ uccode=0x1F5D,
+ unicodeslot=0x1F55,
+ },
+ [0x1F56]={
+ category="ll",
+ contextname="greekupsilonpsiliperispomeni",
+ description="GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F50, 0x342 },
+ unicodeslot=0x1F56,
+ },
+ [0x1F57]={
+ category="ll",
+ contextname="greekupsilondasiaperispomeni",
+ description="GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x1F51, 0x342 },
+ uccode=0x1F5F,
+ unicodeslot=0x1F57,
+ },
+ [0x1F59]={
+ category="lu",
+ contextname="greekUpsilondasia",
+ description="GREEK CAPITAL LETTER UPSILON WITH DASIA",
+ direction="l",
+ lccode=0x1F51,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x314 },
+ unicodeslot=0x1F59,
+ },
+ [0x1F5B]={
+ category="lu",
+ contextname="greekUpsilondasiavaria",
+ description="GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F53,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x1F59, 0x300 },
+ unicodeslot=0x1F5B,
+ },
+ [0x1F5D]={
+ category="lu",
+ contextname="greekUpsilondasiatonos",
+ description="GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F55,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x1F59, 0x301 },
+ unicodeslot=0x1F5D,
+ },
+ [0x1F5F]={
+ category="lu",
+ contextname="greekUpsilondasiaperispomeni",
+ description="GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F57,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x1F59, 0x342 },
+ unicodeslot=0x1F5F,
+ },
+ [0x1F60]={
+ category="ll",
+ contextname="greekomegapsili",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x313 },
+ uccode=0x1F68,
+ unicodeslot=0x1F60,
+ },
+ [0x1F61]={
+ category="ll",
+ contextname="greekomegadasia",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x314 },
+ uccode=0x1F69,
+ unicodeslot=0x1F61,
+ },
+ [0x1F62]={
+ category="ll",
+ contextname="greekomegapsilivaria",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F60, 0x300 },
+ uccode=0x1F6A,
+ unicodeslot=0x1F62,
+ },
+ [0x1F63]={
+ category="ll",
+ contextname="greekomegadasiavaria",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F61, 0x300 },
+ uccode=0x1F6B,
+ unicodeslot=0x1F63,
+ },
+ [0x1F64]={
+ category="ll",
+ contextname="greekomegapsilitonos",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F60, 0x301 },
+ uccode=0x1F6C,
+ unicodeslot=0x1F64,
+ },
+ [0x1F65]={
+ category="ll",
+ contextname="greekomegadasiatonos",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F61, 0x301 },
+ uccode=0x1F6D,
+ unicodeslot=0x1F65,
+ },
+ [0x1F66]={
+ category="ll",
+ contextname="greekomegapsiliperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F60, 0x342 },
+ uccode=0x1F6E,
+ unicodeslot=0x1F66,
+ },
+ [0x1F67]={
+ category="ll",
+ contextname="greekomegadasiaperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F61, 0x342 },
+ uccode=0x1F6F,
+ unicodeslot=0x1F67,
+ },
+ [0x1F68]={
+ category="lu",
+ contextname="greekOmegapsili",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI",
+ direction="l",
+ lccode=0x1F60,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x3A9, 0x313 },
+ unicodeslot=0x1F68,
+ },
+ [0x1F69]={
+ category="lu",
+ contextname="greekOmegadasia",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA",
+ direction="l",
+ lccode=0x1F61,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x3A9, 0x314 },
+ unicodeslot=0x1F69,
+ },
+ [0x1F6A]={
+ category="lu",
+ contextname="greekOmegapsilivaria",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA",
+ direction="l",
+ lccode=0x1F62,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F68, 0x300 },
+ unicodeslot=0x1F6A,
+ },
+ [0x1F6B]={
+ category="lu",
+ contextname="greekOmegadasiavaria",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA",
+ direction="l",
+ lccode=0x1F63,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F69, 0x300 },
+ unicodeslot=0x1F6B,
+ },
+ [0x1F6C]={
+ category="lu",
+ contextname="greekOmegapsilitonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA",
+ direction="l",
+ lccode=0x1F64,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F68, 0x301 },
+ unicodeslot=0x1F6C,
+ },
+ [0x1F6D]={
+ category="lu",
+ contextname="greekOmegadasiatonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA",
+ direction="l",
+ lccode=0x1F65,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F69, 0x301 },
+ unicodeslot=0x1F6D,
+ },
+ [0x1F6E]={
+ category="lu",
+ contextname="greekOmegapsiliperispomeni",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F66,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F68, 0x342 },
+ unicodeslot=0x1F6E,
+ },
+ [0x1F6F]={
+ category="lu",
+ contextname="greekOmegadasiaperispomeni",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI",
+ direction="l",
+ lccode=0x1F67,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F69, 0x342 },
+ unicodeslot=0x1F6F,
+ },
+ [0x1F70]={
+ category="ll",
+ contextname="greekalphavaria",
+ description="GREEK SMALL LETTER ALPHA WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x300 },
+ uccode=0x1FBA,
+ unicodeslot=0x1F70,
+ },
+ [0x1F71]={
+ category="ll",
+ contextname="greekalphaoxia",
+ description="GREEK SMALL LETTER ALPHA WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3AC },
+ uccode=0x1FBB,
+ unicodeslot=0x1F71,
+ },
+ [0x1F72]={
+ category="ll",
+ contextname="greekepsilonvaria",
+ description="GREEK SMALL LETTER EPSILON WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x3B5, 0x300 },
+ uccode=0x1FC8,
+ unicodeslot=0x1F72,
+ },
+ [0x1F73]={
+ category="ll",
+ contextname="greekepsilonoxia",
+ description="GREEK SMALL LETTER EPSILON WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B5,
+ specials={ "char", 0x3AD },
+ uccode=0x1FC9,
+ unicodeslot=0x1F73,
+ },
+ [0x1F74]={
+ category="ll",
+ contextname="greeketavaria",
+ description="GREEK SMALL LETTER ETA WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x300 },
+ uccode=0x1FCA,
+ unicodeslot=0x1F74,
+ },
+ [0x1F75]={
+ category="ll",
+ contextname="greeketaoxia",
+ description="GREEK SMALL LETTER ETA WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3AE },
+ uccode=0x1FCB,
+ unicodeslot=0x1F75,
+ },
+ [0x1F76]={
+ category="ll",
+ contextname="greekiotavaria",
+ description="GREEK SMALL LETTER IOTA WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x300 },
+ uccode=0x1FDA,
+ unicodeslot=0x1F76,
+ },
+ [0x1F77]={
+ category="ll",
+ contextname="greekiotaoxia",
+ description="GREEK SMALL LETTER IOTA WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3AF },
+ uccode=0x1FDB,
+ unicodeslot=0x1F77,
+ },
+ [0x1F78]={
+ category="ll",
+ contextname="greekomicronvaria",
+ description="GREEK SMALL LETTER OMICRON WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x3BF, 0x300 },
+ uccode=0x1FF8,
+ unicodeslot=0x1F78,
+ },
+ [0x1F79]={
+ category="ll",
+ contextname="greekomicronoxia",
+ description="GREEK SMALL LETTER OMICRON WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3BF,
+ specials={ "char", 0x3CC },
+ uccode=0x1FF9,
+ unicodeslot=0x1F79,
+ },
+ [0x1F7A]={
+ category="ll",
+ contextname="greekupsilonvaria",
+ description="GREEK SMALL LETTER UPSILON WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x300 },
+ uccode=0x1FEA,
+ unicodeslot=0x1F7A,
+ },
+ [0x1F7B]={
+ category="ll",
+ contextname="greekupsilonoxia",
+ description="GREEK SMALL LETTER UPSILON WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3CD },
+ uccode=0x1FEB,
+ unicodeslot=0x1F7B,
+ },
+ [0x1F7C]={
+ category="ll",
+ contextname="greekomegavaria",
+ description="GREEK SMALL LETTER OMEGA WITH VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x300 },
+ uccode=0x1FFA,
+ unicodeslot=0x1F7C,
+ },
+ [0x1F7D]={
+ category="ll",
+ contextname="greekomegaoxia",
+ description="GREEK SMALL LETTER OMEGA WITH OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3CE },
+ uccode=0x1FFB,
+ unicodeslot=0x1F7D,
+ },
+ [0x1F80]={
+ category="ll",
+ contextname="greekalphaiotasubpsili",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F00, 0x345 },
+ uccode=0x1F88,
+ unicodeslot=0x1F80,
+ },
+ [0x1F81]={
+ category="ll",
+ contextname="greekalphaiotasubdasia",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F01, 0x345 },
+ uccode=0x1F89,
+ unicodeslot=0x1F81,
+ },
+ [0x1F82]={
+ category="ll",
+ contextname="greekalphaiotasubpsilivaria",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F02, 0x345 },
+ uccode=0x1F8A,
+ unicodeslot=0x1F82,
+ },
+ [0x1F83]={
+ category="ll",
+ contextname="greekalphaiotasubdasiavaria",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F03, 0x345 },
+ uccode=0x1F8B,
+ unicodeslot=0x1F83,
+ },
+ [0x1F84]={
+ category="ll",
+ contextname="greekalphaiotasubpsilitonos",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F04, 0x345 },
+ uccode=0x1F8C,
+ unicodeslot=0x1F84,
+ },
+ [0x1F85]={
+ category="ll",
+ contextname="greekalphaiotasubdasiatonos",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F05, 0x345 },
+ uccode=0x1F8D,
+ unicodeslot=0x1F85,
+ },
+ [0x1F86]={
+ category="ll",
+ contextname="greekalphaiotasubpsiliperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F06, 0x345 },
+ uccode=0x1F8E,
+ unicodeslot=0x1F86,
+ },
+ [0x1F87]={
+ category="ll",
+ contextname="greekalphaiotasubdasiaperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F07, 0x345 },
+ uccode=0x1F8F,
+ unicodeslot=0x1F87,
+ },
+ [0x1F88]={
+ category="lt",
+ contextname="greekAlphaiotasubpsili",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F80,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F08, 0x345 },
+ unicodeslot=0x1F88,
+ },
+ [0x1F89]={
+ category="lt",
+ contextname="greekAlphaiotasubdasia",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F81,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F09, 0x345 },
+ unicodeslot=0x1F89,
+ },
+ [0x1F8A]={
+ category="lt",
+ contextname="greekAlphaiotasubpsilivaria",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F82,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0A, 0x345 },
+ unicodeslot=0x1F8A,
+ },
+ [0x1F8B]={
+ category="lt",
+ contextname="greekAlphaiotasubdasiavaria",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F83,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0B, 0x345 },
+ unicodeslot=0x1F8B,
+ },
+ [0x1F8C]={
+ category="lt",
+ contextname="greekAlphaiotasubpsilitonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F84,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0C, 0x345 },
+ unicodeslot=0x1F8C,
+ },
+ [0x1F8D]={
+ category="lt",
+ contextname="greekAlphaiotasubdasiatonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F85,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0D, 0x345 },
+ unicodeslot=0x1F8D,
+ },
+ [0x1F8E]={
+ category="lt",
+ contextname="greekAlphaiotasubpsiliperispomeni",
+ description="GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F86,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0E, 0x345 },
+ unicodeslot=0x1F8E,
+ },
+ [0x1F8F]={
+ category="lt",
+ contextname="greekAlphaiotasubdasiaperispomeni",
+ description="GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F87,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x1F0F, 0x345 },
+ unicodeslot=0x1F8F,
+ },
+ [0x1F90]={
+ category="ll",
+ contextname="greeketaiotasubpsili",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F20, 0x345 },
+ uccode=0x1F98,
+ unicodeslot=0x1F90,
+ },
+ [0x1F91]={
+ category="ll",
+ contextname="greeketaiotasubdasia",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F21, 0x345 },
+ uccode=0x1F99,
+ unicodeslot=0x1F91,
+ },
+ [0x1F92]={
+ category="ll",
+ contextname="greeketaiotasubpsilivaria",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F22, 0x345 },
+ uccode=0x1F9A,
+ unicodeslot=0x1F92,
+ },
+ [0x1F93]={
+ category="ll",
+ contextname="greeketaiotasubdasiavaria",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F23, 0x345 },
+ uccode=0x1F9B,
+ unicodeslot=0x1F93,
+ },
+ [0x1F94]={
+ category="ll",
+ contextname="greeketaiotasubpsilitonos",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F24, 0x345 },
+ uccode=0x1F9C,
+ unicodeslot=0x1F94,
+ },
+ [0x1F95]={
+ category="ll",
+ contextname="greeketaiotasubdasiatonos",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F25, 0x345 },
+ uccode=0x1F9D,
+ unicodeslot=0x1F95,
+ },
+ [0x1F96]={
+ category="ll",
+ contextname="greeketaiotasubpsiliperispomeni",
+ description="GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F26, 0x345 },
+ uccode=0x1F9E,
+ unicodeslot=0x1F96,
+ },
+ [0x1F97]={
+ category="ll",
+ contextname="greeketaiotasubdasiaperispomeni",
+ description="GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F27, 0x345 },
+ uccode=0x1F9F,
+ unicodeslot=0x1F97,
+ },
+ [0x1F98]={
+ category="lt",
+ contextname="greekEtaiotasubpsili",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F90,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F28, 0x345 },
+ unicodeslot=0x1F98,
+ },
+ [0x1F99]={
+ category="lt",
+ contextname="greekEtaiotasubdasia",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F91,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F29, 0x345 },
+ unicodeslot=0x1F99,
+ },
+ [0x1F9A]={
+ category="lt",
+ contextname="greekEtaiotasubpsilivaria",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F92,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2A, 0x345 },
+ unicodeslot=0x1F9A,
+ },
+ [0x1F9B]={
+ category="lt",
+ contextname="greekEtaiotasubdasiavaria",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F93,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2B, 0x345 },
+ unicodeslot=0x1F9B,
+ },
+ [0x1F9C]={
+ category="lt",
+ contextname="greekEtaiotasubpsilitonos",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F94,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2C, 0x345 },
+ unicodeslot=0x1F9C,
+ },
+ [0x1F9D]={
+ category="lt",
+ contextname="greekEtaiotasubdasiatonos",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F95,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2D, 0x345 },
+ unicodeslot=0x1F9D,
+ },
+ [0x1F9E]={
+ category="lt",
+ contextname="greekEtaiotasubpsiliperispomeni",
+ description="GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F96,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2E, 0x345 },
+ unicodeslot=0x1F9E,
+ },
+ [0x1F9F]={
+ category="lt",
+ contextname="greekEtaiotasubdasiaperispomeni",
+ description="GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1F97,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x1F2F, 0x345 },
+ unicodeslot=0x1F9F,
+ },
+ [0x1FA0]={
+ category="ll",
+ contextname="greekomegaiotasubpsili",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F60, 0x345 },
+ uccode=0x1FA8,
+ unicodeslot=0x1FA0,
+ },
+ [0x1FA1]={
+ category="ll",
+ contextname="greekomegaiotasubdasia",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F61, 0x345 },
+ uccode=0x1FA9,
+ unicodeslot=0x1FA1,
+ },
+ [0x1FA2]={
+ category="ll",
+ contextname="greekomegaiotasubpsilivaria",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F62, 0x345 },
+ uccode=0x1FAA,
+ unicodeslot=0x1FA2,
+ },
+ [0x1FA3]={
+ category="ll",
+ contextname="greekomegaiotasubdasiavaria",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F63, 0x345 },
+ uccode=0x1FAB,
+ unicodeslot=0x1FA3,
+ },
+ [0x1FA4]={
+ category="ll",
+ contextname="greekomegaiotasubpsilitonos",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F64, 0x345 },
+ uccode=0x1FAC,
+ unicodeslot=0x1FA4,
+ },
+ [0x1FA5]={
+ category="ll",
+ contextname="greekomegaiotasubdasiatonos",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F65, 0x345 },
+ uccode=0x1FAD,
+ unicodeslot=0x1FA5,
+ },
+ [0x1FA6]={
+ category="ll",
+ contextname="greekomegaiotasubpsiliperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F66, 0x345 },
+ uccode=0x1FAE,
+ unicodeslot=0x1FA6,
+ },
+ [0x1FA7]={
+ category="ll",
+ contextname="greekomegaiotasubdasiaperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F67, 0x345 },
+ uccode=0x1FAF,
+ unicodeslot=0x1FA7,
+ },
+ [0x1FA8]={
+ category="lt",
+ contextname="greekOmegaiotasubpsili",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA0,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F68, 0x345 },
+ unicodeslot=0x1FA8,
+ },
+ [0x1FA9]={
+ category="lt",
+ contextname="greekOmegaiotasubdasia",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA1,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F69, 0x345 },
+ unicodeslot=0x1FA9,
+ },
+ [0x1FAA]={
+ category="lt",
+ contextname="greekOmegaiotasubpsilivaria",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA2,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6A, 0x345 },
+ unicodeslot=0x1FAA,
+ },
+ [0x1FAB]={
+ category="lt",
+ contextname="greekOmegaiotasubdasiavaria",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA3,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6B, 0x345 },
+ unicodeslot=0x1FAB,
+ },
+ [0x1FAC]={
+ category="lt",
+ contextname="greekOmegaiotasubpsilitonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA4,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6C, 0x345 },
+ unicodeslot=0x1FAC,
+ },
+ [0x1FAD]={
+ category="lt",
+ contextname="greekOmegaiotasubdasiatonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA5,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6D, 0x345 },
+ unicodeslot=0x1FAD,
+ },
+ [0x1FAE]={
+ category="lt",
+ contextname="greekOmegaiotasubpsiliperispomeni",
+ description="GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA6,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6E, 0x345 },
+ unicodeslot=0x1FAE,
+ },
+ [0x1FAF]={
+ category="lt",
+ contextname="greekOmegaiotasubdasiaperispomeni",
+ description="GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FA7,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x1F6F, 0x345 },
+ unicodeslot=0x1FAF,
+ },
+ [0x1FB0]={
+ category="ll",
+ contextname="greekalphavrachy",
+ description="GREEK SMALL LETTER ALPHA WITH VRACHY",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x306 },
+ uccode=0x1FB8,
+ unicodeslot=0x1FB0,
+ },
+ [0x1FB1]={
+ category="ll",
+ contextname="greekalphamacron",
+ description="GREEK SMALL LETTER ALPHA WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x304 },
+ uccode=0x1FB9,
+ unicodeslot=0x1FB1,
+ },
+ [0x1FB2]={
+ category="ll",
+ contextname="greekalphaiotasubvaria",
+ description="GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1F70, 0x345 },
+ unicodeslot=0x1FB2,
+ },
+ [0x1FB3]={
+ category="ll",
+ contextname="greekalphaiotasub",
+ description="GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x345 },
+ uccode=0x1FBC,
+ unicodeslot=0x1FB3,
+ },
+ [0x1FB4]={
+ category="ll",
+ contextname="greekalphaiotasubtonos",
+ description="GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3AC, 0x345 },
+ unicodeslot=0x1FB4,
+ },
+ [0x1FB6]={
+ category="ll",
+ contextname="greekalphaperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x3B1, 0x342 },
+ unicodeslot=0x1FB6,
+ },
+ [0x1FB7]={
+ category="ll",
+ contextname="greekalphaiotasubperispomeni",
+ description="GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B1,
+ specials={ "char", 0x1FB6, 0x345 },
+ unicodeslot=0x1FB7,
+ },
+ [0x1FB8]={
+ category="lu",
+ contextname="greekAlphavrachy",
+ description="GREEK CAPITAL LETTER ALPHA WITH VRACHY",
+ direction="l",
+ lccode=0x1FB0,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x306 },
+ unicodeslot=0x1FB8,
+ },
+ [0x1FB9]={
+ category="lu",
+ contextname="greekAlphamacron",
+ description="GREEK CAPITAL LETTER ALPHA WITH MACRON",
+ direction="l",
+ lccode=0x1FB1,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x304 },
+ unicodeslot=0x1FB9,
+ },
+ [0x1FBA]={
+ category="lu",
+ contextname="greekAlphavaria",
+ description="GREEK CAPITAL LETTER ALPHA WITH VARIA",
+ direction="l",
+ lccode=0x1F70,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x300 },
+ unicodeslot=0x1FBA,
+ },
+ [0x1FBB]={
+ category="lu",
+ contextname="greekAlphatonos",
+ description="GREEK CAPITAL LETTER ALPHA WITH OXIA",
+ direction="l",
+ lccode=0x1F71,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x386 },
+ unicodeslot=0x1FBB,
+ },
+ [0x1FBC]={
+ category="lt",
+ contextname="greekAlphaiotasub",
+ description="GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FB3,
+ linebreak="al",
+ shcode=0x391,
+ specials={ "char", 0x391, 0x345 },
+ unicodeslot=0x1FBC,
+ },
+ [0x1FBD]={
+ category="sk",
+ contextname="greekCoronis",
+ description="GREEK KORONIS",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x313 },
+ unicodeslot=0x1FBD,
+ },
+ [0x1FBE]={
+ category="ll",
+ contextname="greekprosgegrammeni",
+ description="GREEK PROSGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x3B9 },
+ uccode=0x399,
+ unicodeslot=0x1FBE,
+ },
+ [0x1FBF]={
+ category="sk",
+ contextname="greekpsili",
+ description="GREEK PSILI",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x313 },
+ unicodeslot=0x1FBF,
+ },
+ [0x1FC0]={
+ category="sk",
+ contextname="greekperispomeni",
+ description="GREEK PERISPOMENI",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x342 },
+ unicodeslot=0x1FC0,
+ },
+ [0x1FC1]={
+ category="sk",
+ contextname="greekdialytikaperispomeni",
+ description="GREEK DIALYTIKA AND PERISPOMENI",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0xA8, 0x342 },
+ unicodeslot=0x1FC1,
+ },
+ [0x1FC2]={
+ category="ll",
+ contextname="greeketaiotasubvaria",
+ description="GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1F74, 0x345 },
+ unicodeslot=0x1FC2,
+ },
+ [0x1FC3]={
+ category="ll",
+ contextname="greeketaiotasub",
+ description="GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x345 },
+ uccode=0x1FCC,
+ unicodeslot=0x1FC3,
+ },
+ [0x1FC4]={
+ category="ll",
+ contextname="greeketaiotasubtonos",
+ description="GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3AE, 0x345 },
+ unicodeslot=0x1FC4,
+ },
+ [0x1FC6]={
+ category="ll",
+ contextname="greeketaperispomeni",
+ description="GREEK SMALL LETTER ETA WITH PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x3B7, 0x342 },
+ unicodeslot=0x1FC6,
+ },
+ [0x1FC7]={
+ category="ll",
+ contextname="greeketaiotasubperispomeni",
+ description="GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B7,
+ specials={ "char", 0x1FC6, 0x345 },
+ unicodeslot=0x1FC7,
+ },
+ [0x1FC8]={
+ category="lu",
+ contextname="greekEpsilonvaria",
+ description="GREEK CAPITAL LETTER EPSILON WITH VARIA",
+ direction="l",
+ lccode=0x1F72,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x395, 0x300 },
+ unicodeslot=0x1FC8,
+ },
+ [0x1FC9]={
+ category="lu",
+ contextname="greekEpsilontonos",
+ description="GREEK CAPITAL LETTER EPSILON WITH OXIA",
+ direction="l",
+ lccode=0x1F73,
+ linebreak="al",
+ shcode=0x395,
+ specials={ "char", 0x388 },
+ unicodeslot=0x1FC9,
+ },
+ [0x1FCA]={
+ category="lu",
+ contextname="greekEtavaria",
+ description="GREEK CAPITAL LETTER ETA WITH VARIA",
+ direction="l",
+ lccode=0x1F74,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x397, 0x300 },
+ unicodeslot=0x1FCA,
+ },
+ [0x1FCB]={
+ category="lu",
+ contextname="greekEtatonos",
+ description="GREEK CAPITAL LETTER ETA WITH OXIA",
+ direction="l",
+ lccode=0x1F75,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x389 },
+ unicodeslot=0x1FCB,
+ },
+ [0x1FCC]={
+ category="lt",
+ contextname="greekEtaiotasub",
+ description="GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FC3,
+ linebreak="al",
+ shcode=0x397,
+ specials={ "char", 0x397, 0x345 },
+ unicodeslot=0x1FCC,
+ },
+ [0x1FCD]={
+ category="sk",
+ contextname="greekpsilivaria",
+ description="GREEK PSILI AND VARIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FBF, 0x300 },
+ unicodeslot=0x1FCD,
+ },
+ [0x1FCE]={
+ category="sk",
+ contextname="greekpsilitonos",
+ description="GREEK PSILI AND OXIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FBF, 0x301 },
+ unicodeslot=0x1FCE,
+ },
+ [0x1FCF]={
+ category="sk",
+ contextname="greekpsiliperispomeni",
+ description="GREEK PSILI AND PERISPOMENI",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FBF, 0x342 },
+ unicodeslot=0x1FCF,
+ },
+ [0x1FD0]={
+ category="ll",
+ contextname="greekiotavrachy",
+ description="GREEK SMALL LETTER IOTA WITH VRACHY",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x306 },
+ uccode=0x1FD8,
+ unicodeslot=0x1FD0,
+ },
+ [0x1FD1]={
+ category="ll",
+ contextname="greekiotamacron",
+ description="GREEK SMALL LETTER IOTA WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x304 },
+ uccode=0x1FD9,
+ unicodeslot=0x1FD1,
+ },
+ [0x1FD2]={
+ category="ll",
+ contextname="greekiotadialytikavaria",
+ description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3CA, 0x300 },
+ unicodeslot=0x1FD2,
+ },
+ [0x1FD3]={
+ category="ll",
+ contextname="greekiotadialytikatonos",
+ description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x390 },
+ unicodeslot=0x1FD3,
+ },
+ [0x1FD6]={
+ category="ll",
+ contextname="greekiotaperispomeni",
+ description="GREEK SMALL LETTER IOTA WITH PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3B9, 0x342 },
+ unicodeslot=0x1FD6,
+ },
+ [0x1FD7]={
+ category="ll",
+ contextname="greekiotadialytikaperispomeni",
+ description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3B9,
+ specials={ "char", 0x3CA, 0x342 },
+ unicodeslot=0x1FD7,
+ },
+ [0x1FD8]={
+ category="lu",
+ contextname="greekIotavrachy",
+ description="GREEK CAPITAL LETTER IOTA WITH VRACHY",
+ direction="l",
+ lccode=0x1FD0,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x306 },
+ unicodeslot=0x1FD8,
+ },
+ [0x1FD9]={
+ category="lu",
+ contextname="greekIotamacron",
+ description="GREEK CAPITAL LETTER IOTA WITH MACRON",
+ direction="l",
+ lccode=0x1FD1,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x304 },
+ unicodeslot=0x1FD9,
+ },
+ [0x1FDA]={
+ category="lu",
+ contextname="greekIotavaria",
+ description="GREEK CAPITAL LETTER IOTA WITH VARIA",
+ direction="l",
+ lccode=0x1F76,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x399, 0x300 },
+ unicodeslot=0x1FDA,
+ },
+ [0x1FDB]={
+ category="lu",
+ contextname="greekIotatonos",
+ description="GREEK CAPITAL LETTER IOTA WITH OXIA",
+ direction="l",
+ lccode=0x1F77,
+ linebreak="al",
+ shcode=0x399,
+ specials={ "char", 0x38A },
+ unicodeslot=0x1FDB,
+ },
+ [0x1FDD]={
+ category="sk",
+ contextname="greekdasiavaria",
+ description="GREEK DASIA AND VARIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FFE, 0x300 },
+ unicodeslot=0x1FDD,
+ },
+ [0x1FDE]={
+ category="sk",
+ contextname="greekdasiatonos",
+ description="GREEK DASIA AND OXIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FFE, 0x301 },
+ unicodeslot=0x1FDE,
+ },
+ [0x1FDF]={
+ category="sk",
+ contextname="greekdasiaperispomeni",
+ description="GREEK DASIA AND PERISPOMENI",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x1FFE, 0x342 },
+ unicodeslot=0x1FDF,
+ },
+ [0x1FE0]={
+ category="ll",
+ contextname="greekupsilonvrachy",
+ description="GREEK SMALL LETTER UPSILON WITH VRACHY",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x306 },
+ uccode=0x1FE8,
+ unicodeslot=0x1FE0,
+ },
+ [0x1FE1]={
+ category="ll",
+ contextname="greekupsilonmacron",
+ description="GREEK SMALL LETTER UPSILON WITH MACRON",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x304 },
+ uccode=0x1FE9,
+ unicodeslot=0x1FE1,
+ },
+ [0x1FE2]={
+ category="ll",
+ contextname="greekupsilondialytikavaria",
+ description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3CB, 0x300 },
+ unicodeslot=0x1FE2,
+ },
+ [0x1FE3]={
+ category="ll",
+ contextname="greekupsilondialytikatonos",
+ description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3B0 },
+ unicodeslot=0x1FE3,
+ },
+ [0x1FE4]={
+ category="ll",
+ contextname="greekrhopsili",
+ description="GREEK SMALL LETTER RHO WITH PSILI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C1,
+ specials={ "char", 0x3C1, 0x313 },
+ unicodeslot=0x1FE4,
+ },
+ [0x1FE5]={
+ category="ll",
+ contextname="greekrhodasia",
+ description="GREEK SMALL LETTER RHO WITH DASIA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C1,
+ specials={ "char", 0x3C1, 0x314 },
+ uccode=0x1FEC,
+ unicodeslot=0x1FE5,
+ },
+ [0x1FE6]={
+ category="ll",
+ contextname="greekupsilonperispomeni",
+ description="GREEK SMALL LETTER UPSILON WITH PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3C5, 0x342 },
+ unicodeslot=0x1FE6,
+ },
+ [0x1FE7]={
+ category="ll",
+ contextname="greekupsilondialytikaperispomeni",
+ description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C5,
+ specials={ "char", 0x3CB, 0x342 },
+ unicodeslot=0x1FE7,
+ },
+ [0x1FE8]={
+ category="lu",
+ contextname="greekUpsilonvrachy",
+ description="GREEK CAPITAL LETTER UPSILON WITH VRACHY",
+ direction="l",
+ lccode=0x1FE0,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x306 },
+ unicodeslot=0x1FE8,
+ },
+ [0x1FE9]={
+ category="lu",
+ contextname="greekUpsilonmacron",
+ description="GREEK CAPITAL LETTER UPSILON WITH MACRON",
+ direction="l",
+ lccode=0x1FE1,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x304 },
+ unicodeslot=0x1FE9,
+ },
+ [0x1FEA]={
+ category="lu",
+ contextname="greekUpsilonvaria",
+ description="GREEK CAPITAL LETTER UPSILON WITH VARIA",
+ direction="l",
+ lccode=0x1F7A,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x3A5, 0x300 },
+ unicodeslot=0x1FEA,
+ },
+ [0x1FEB]={
+ category="lu",
+ contextname="greekUpsilontonos",
+ description="GREEK CAPITAL LETTER UPSILON WITH OXIA",
+ direction="l",
+ lccode=0x1F7B,
+ linebreak="al",
+ shcode=0x3A5,
+ specials={ "char", 0x38E },
+ unicodeslot=0x1FEB,
+ },
+ [0x1FEC]={
+ category="lu",
+ contextname="greekRhodasia",
+ description="GREEK CAPITAL LETTER RHO WITH DASIA",
+ direction="l",
+ lccode=0x1FE5,
+ linebreak="al",
+ shcode=0x3A1,
+ specials={ "char", 0x3A1, 0x314 },
+ unicodeslot=0x1FEC,
+ },
+ [0x1FED]={
+ category="sk",
+ contextname="greekdialytikavaria",
+ description="GREEK DIALYTIKA AND VARIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0xA8, 0x300 },
+ unicodeslot=0x1FED,
+ },
+ [0x1FEE]={
+ category="sk",
+ contextname="greekdialytikatonos",
+ description="GREEK DIALYTIKA AND OXIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x385 },
+ unicodeslot=0x1FEE,
+ },
+ [0x1FEF]={
+ category="sk",
+ contextname="greekvaria",
+ description="GREEK VARIA",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x60 },
+ unicodeslot=0x1FEF,
+ },
+ [0x1FF2]={
+ category="ll",
+ contextname="greekomegaiotasubvaria",
+ description="GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1F7C, 0x345 },
+ unicodeslot=0x1FF2,
+ },
+ [0x1FF3]={
+ category="ll",
+ contextname="greekomegaiotasub",
+ description="GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x345 },
+ uccode=0x1FFC,
+ unicodeslot=0x1FF3,
+ },
+ [0x1FF4]={
+ category="ll",
+ contextname="greekomegaiotasubtonos",
+ description="GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3CE, 0x345 },
+ unicodeslot=0x1FF4,
+ },
+ [0x1FF6]={
+ category="ll",
+ contextname="greekomegaperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x3C9, 0x342 },
+ unicodeslot=0x1FF6,
+ },
+ [0x1FF7]={
+ category="ll",
+ contextname="greekomegaiotasubperispomeni",
+ description="GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3C9,
+ specials={ "char", 0x1FF6, 0x345 },
+ unicodeslot=0x1FF7,
+ },
+ [0x1FF8]={
+ category="lu",
+ contextname="greekOmicronvaria",
+ description="GREEK CAPITAL LETTER OMICRON WITH VARIA",
+ direction="l",
+ lccode=0x1F78,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x39F, 0x300 },
+ unicodeslot=0x1FF8,
+ },
+ [0x1FF9]={
+ category="lu",
+ contextname="greekOmicrontonos",
+ description="GREEK CAPITAL LETTER OMICRON WITH OXIA",
+ direction="l",
+ lccode=0x1F79,
+ linebreak="al",
+ shcode=0x39F,
+ specials={ "char", 0x38C },
+ unicodeslot=0x1FF9,
+ },
+ [0x1FFA]={
+ category="lu",
+ contextname="greekOmegavaria",
+ description="GREEK CAPITAL LETTER OMEGA WITH VARIA",
+ direction="l",
+ lccode=0x1F7C,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x3A9, 0x300 },
+ unicodeslot=0x1FFA,
+ },
+ [0x1FFB]={
+ category="lu",
+ contextname="greekOmegatonos",
+ description="GREEK CAPITAL LETTER OMEGA WITH OXIA",
+ direction="l",
+ lccode=0x1F7D,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x38F },
+ unicodeslot=0x1FFB,
+ },
+ [0x1FFC]={
+ category="lt",
+ contextname="greekOmegaiotasub",
+ description="GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI",
+ direction="l",
+ lccode=0x1FF3,
+ linebreak="al",
+ shcode=0x3A9,
+ specials={ "char", 0x3A9, 0x345 },
+ unicodeslot=0x1FFC,
+ },
+ [0x1FFD]={
+ category="sk",
+ contextname="greekoxia",
+ description="GREEK OXIA",
+ direction="on",
+ linebreak="bb",
+ specials={ "char", 0xB4 },
+ unicodeslot=0x1FFD,
+ },
+ [0x1FFE]={
+ category="sk",
+ contextname="greekdasia",
+ description="GREEK DASIA",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x314 },
+ unicodeslot=0x1FFE,
+ },
+ [0x2000]={
+ category="zs",
+ description="EN QUAD",
+ direction="ws",
+ linebreak="ba",
+ specials={ "char", 0x2002 },
+ unicodeslot=0x2000,
+ },
+ [0x2001]={
+ category="zs",
+ description="EM QUAD",
+ direction="ws",
+ linebreak="ba",
+ specials={ "char", 0x2003 },
+ unicodeslot=0x2001,
+ },
+ [0x2002]={
+ adobename="enspace",
+ category="zs",
+ contextname="enspace",
+ description="EN SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2002,
+ },
+ [0x2003]={
+ category="zs",
+ contextname="emspace",
+ description="EM SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2003,
+ },
+ [0x2004]={
+ category="zs",
+ contextname="threeperemspace",
+ description="THREE-PER-EM SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2004,
+ },
+ [0x2005]={
+ category="zs",
+ contextname="fourperemspace",
+ description="FOUR-PER-EM SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2005,
+ },
+ [0x2006]={
+ category="zs",
+ contextname="sixperemspace",
+ description="SIX-PER-EM SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2006,
+ },
+ [0x2007]={
+ category="zs",
+ contextname="figurespace",
+ description="FIGURE SPACE",
+ direction="ws",
+ linebreak="gl",
+ specials={ "nobreak", 0x20 },
+ unicodeslot=0x2007,
+ },
+ [0x2008]={
+ category="zs",
+ contextname="punctuationspace",
+ description="PUNCTUATION SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2008,
+ },
+ [0x2009]={
+ category="zs",
+ contextname="breakablethinspace",
+ description="THIN SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x2009,
+ },
+ [0x200A]={
+ category="zs",
+ contextname="hairspace",
+ description="HAIR SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x200A,
+ },
+ [0x200B]={
+ adobename="zerowidthspace",
+ category="cf",
+ contextname="zerowidthspace",
+ description="ZERO WIDTH SPACE",
+ direction="bn",
+ linebreak="zw",
+ unicodeslot=0x200B,
+ },
+ [0x200C]={
+ adobename="zerowidthnonjoiner",
+ arabic="u",
+ category="cf",
+ contextname="zwnj",
+ description="ZERO WIDTH NON-JOINER",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x200C,
+ },
+ [0x200D]={
+ adobename="afii301",
+ arabic="c",
+ category="cf",
+ contextname="zwj",
+ description="ZERO WIDTH JOINER",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x200D,
+ },
+ [0x200E]={
+ adobename="afii299",
+ category="cf",
+ description="LEFT-TO-RIGHT MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x200E,
+ },
+ [0x200F]={
+ adobename="afii300",
+ category="cf",
+ description="RIGHT-TO-LEFT MARK",
+ direction="r",
+ linebreak="cm",
+ unicodeslot=0x200F,
+ },
+ [0x2010]={
+ adobename="hyphentwo",
+ category="pd",
+ cjkwd="a",
+ description="HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2010,
+ },
+ [0x2011]={
+ category="pd",
+ description="NON-BREAKING HYPHEN",
+ direction="on",
+ linebreak="gl",
+ specials={ "nobreak", 0x2010 },
+ unicodeslot=0x2011,
+ },
+ [0x2012]={
+ adobename="figuredash",
+ category="pd",
+ contextname="textminus",
+ description="FIGURE DASH",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2012,
+ },
+ [0x2013]={
+ adobename="endash",
+ category="pd",
+ cjkwd="a",
+ contextname="endash",
+ description="EN DASH",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2013,
+ },
+ [0x2014]={
+ adobename="emdash",
+ category="pd",
+ cjkwd="a",
+ contextname="emdash",
+ description="EM DASH",
+ direction="on",
+ linebreak="b2",
+ unicodeslot=0x2014,
+ },
+ [0x2015]={
+ adobename="horizontalbar",
+ category="pd",
+ cjkwd="a",
+ contextname="texthorizontalbar",
+ description="HORIZONTAL BAR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2015,
+ },
+ [0x2016]={
+ adobename="dblverticalbar",
+ category="po",
+ cjkwd="a",
+ description="DOUBLE VERTICAL LINE",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="delimiter",
+ name="Vert",
+ },
+ {
+ class="nothing",
+ name="Arrowvert",
+ },
+ {
+ class="open",
+ name="lVert",
+ },
+ {
+ class="close",
+ name="rVert",
+ },
+ {
+ class="delimiter",
+ name="doubleverticalbar",
+ },
+ },
+ unicodeslot=0x2016,
+ },
+ [0x2017]={
+ adobename="underscoredbl",
+ category="po",
+ description="DOUBLE LOW LINE",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x20, 0x333 },
+ unicodeslot=0x2017,
+ },
+ [0x2018]={
+ adobename="quoteleft",
+ category="pi",
+ cjkwd="a",
+ contextname="quoteleft",
+ description="LEFT SINGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2018,
+ },
+ [0x2019]={
+ adobename="quoteright",
+ category="pf",
+ cjkwd="a",
+ contextname="quoteright",
+ description="RIGHT SINGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2019,
+ },
+ [0x201A]={
+ adobename="quotesinglbase",
+ category="ps",
+ contextname="quotesinglebase",
+ description="SINGLE LOW-0x0009 QUOTATION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x201A,
+ },
+ [0x201B]={
+ adobename="quotereversed",
+ category="pi",
+ description="SINGLE HIGH-REVERSED-0x0009 QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x201B,
+ },
+ [0x201C]={
+ adobename="quotedblleft",
+ category="pi",
+ cjkwd="a",
+ contextname="quotedblleft",
+ description="LEFT DOUBLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x201C,
+ },
+ [0x201D]={
+ adobename="quotedblright",
+ category="pf",
+ cjkwd="a",
+ contextname="quotedblright",
+ description="RIGHT DOUBLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x201D,
+ },
+ [0x201E]={
+ adobename="quotedblbase",
+ category="ps",
+ contextname="quotedblbase",
+ description="DOUBLE LOW-0x0009 QUOTATION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x201E,
+ },
+ [0x201F]={
+ category="pi",
+ description="DOUBLE HIGH-REVERSED-0x0009 QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x201F,
+ },
+ [0x2020]={
+ adobename="dagger",
+ category="po",
+ cjkwd="a",
+ contextname="textdag",
+ description="DAGGER",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="binary",
+ name="dagger",
+ },
+ {
+ class="box",
+ name="dag",
+ },
+ },
+ unicodeslot=0x2020,
+ },
+ [0x2021]={
+ adobename="daggerdbl",
+ category="po",
+ cjkwd="a",
+ contextname="textddag",
+ description="DOUBLE DAGGER",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="binary",
+ name="ddagger",
+ },
+ {
+ class="box",
+ name="ddag",
+ },
+ },
+ unicodeslot=0x2021,
+ },
+ [0x2022]={
+ adobename="bullet",
+ category="po",
+ cjkwd="a",
+ contextname="textbullet",
+ description="BULLET",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="bullet",
+ unicodeslot=0x2022,
+ },
+ [0x2023]={
+ category="po",
+ description="TRIANGULAR BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2023,
+ },
+ [0x2024]={
+ adobename="onedotenleader",
+ category="po",
+ cjkwd="a",
+ description="ONE DOT LEADER",
+ direction="on",
+ linebreak="in",
+ specials={ "compat", 0x2E },
+ unicodeslot=0x2024,
+ },
+ [0x2025]={
+ adobename="twodotleader",
+ category="po",
+ cjkwd="a",
+ description="TWO DOT LEADER",
+ direction="on",
+ linebreak="in",
+ specials={ "compat", 0x2E, 0x2E },
+ unicodeslot=0x2025,
+ },
+ [0x2026]={
+ adobename="ellipsis",
+ category="po",
+ cjkwd="a",
+ contextname="textellipsis",
+ description="HORIZONTAL ELLIPSIS",
+ direction="on",
+ linebreak="in",
+ mathspec={
+ {
+ class="inner",
+ name="ldots",
+ },
+ {
+ class="inner",
+ name="dots",
+ },
+ },
+ specials={ "compat", 0x2E, 0x2E, 0x2E },
+ unicodeslot=0x2026,
+ },
+ [0x2027]={
+ category="po",
+ cjkwd="a",
+ description="HYPHENATION POINT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2027,
+ },
+ [0x2028]={
+ category="zl",
+ description="LINE SEPARATOR",
+ direction="ws",
+ linebreak="bk",
+ unicodeslot=0x2028,
+ },
+ [0x2029]={
+ category="zp",
+ description="PARAGRAPH SEPARATOR",
+ direction="b",
+ linebreak="bk",
+ unicodeslot=0x2029,
+ },
+ [0x202A]={
+ category="cf",
+ description="LEFT-TO-RIGHT EMBEDDING",
+ direction="lre",
+ linebreak="cm",
+ unicodeslot=0x202A,
+ },
+ [0x202B]={
+ category="cf",
+ description="RIGHT-TO-LEFT EMBEDDING",
+ direction="rle",
+ linebreak="cm",
+ unicodeslot=0x202B,
+ },
+ [0x202C]={
+ adobename="afii61573",
+ category="cf",
+ description="POP DIRECTIONAL FORMATTING",
+ direction="pdf",
+ linebreak="cm",
+ unicodeslot=0x202C,
+ },
+ [0x202D]={
+ adobename="afii61574",
+ category="cf",
+ description="LEFT-TO-RIGHT OVERRIDE",
+ direction="lro",
+ linebreak="cm",
+ unicodeslot=0x202D,
+ },
+ [0x202E]={
+ adobename="afii61575",
+ category="cf",
+ description="RIGHT-TO-LEFT OVERRIDE",
+ direction="rlo",
+ linebreak="cm",
+ unicodeslot=0x202E,
+ },
+ [0x202F]={
+ category="zs",
+ contextname="narrownobreakspace",
+ description="NARROW NO-BREAK SPACE",
+ direction="cs",
+ linebreak="gl",
+ specials={ "nobreak", 0x20 },
+ unicodeslot=0x202F,
+ },
+ [0x2030]={
+ adobename="perthousand",
+ category="po",
+ cjkwd="a",
+ contextname="perthousand",
+ description="PER MILLE SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x2030,
+ },
+ [0x2031]={
+ category="po",
+ description="PER TEN THOUSAND SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x2031,
+ },
+ [0x2032]={
+ adobename="minute",
+ category="po",
+ cjkwd="a",
+ description="PRIME",
+ direction="et",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="prime",
+ unicodeslot=0x2032,
+ },
+ [0x2033]={
+ adobename="second",
+ category="po",
+ cjkwd="a",
+ description="DOUBLE PRIME",
+ direction="et",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="doubleprime",
+ specials={ "compat", 0x2032, 0x2032 },
+ unicodeslot=0x2033,
+ },
+ [0x2034]={
+ category="po",
+ description="TRIPLE PRIME",
+ direction="et",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="tripleprime",
+ specials={ "compat", 0x2032, 0x2032, 0x2032 },
+ unicodeslot=0x2034,
+ },
+ [0x2035]={
+ adobename="primereversed",
+ category="po",
+ cjkwd="a",
+ description="REVERSED PRIME",
+ direction="on",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="reversedprime",
+ unicodeslot=0x2035,
+ },
+ [0x2036]={
+ category="po",
+ description="REVERSED DOUBLE PRIME",
+ direction="on",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="reverseddoubleprime",
+ specials={ "compat", 0x2035, 0x2035 },
+ unicodeslot=0x2036,
+ },
+ [0x2037]={
+ category="po",
+ description="REVERSED TRIPLE PRIME",
+ direction="on",
+ linebreak="po",
+ mathclass="nothing",
+ mathname="reversedtripleprime",
+ specials={ "compat", 0x2035, 0x2035, 0x2035 },
+ unicodeslot=0x2037,
+ },
+ [0x2038]={
+ category="po",
+ description="CARET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2038,
+ },
+ [0x2039]={
+ adobename="guilsinglleft",
+ category="pi",
+ contextname="guilsingleleft",
+ description="SINGLE LEFT-POINTING ANGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ mirror=0x203A,
+ textclass="open",
+ unicodeslot=0x2039,
+ },
+ [0x203A]={
+ adobename="guilsinglright",
+ category="pf",
+ contextname="guilsingleright",
+ description="SINGLE RIGHT-POINTING ANGLE QUOTATION MARK",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2039,
+ textclass="close",
+ unicodeslot=0x203A,
+ },
+ [0x203B]={
+ adobename="referencemark",
+ category="po",
+ cjkwd="a",
+ description="REFERENCE MARK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x203B,
+ },
+ [0x203C]={
+ adobename="exclamdbl",
+ category="po",
+ description="DOUBLE EXCLAMATION MARK",
+ direction="on",
+ linebreak="ns",
+ specials={ "compat", 0x21, 0x21 },
+ unicodeslot=0x203C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x203D]={
+ category="po",
+ description="INTERROBANG",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x203D,
+ },
+ [0x203E]={
+ adobename="overline",
+ category="po",
+ cjkwd="a",
+ comment="mathspec={ { class=\"topaccent\", name=\"overbar\" }, { class=\"botaccent\", name=\"underbar\" } }\"",
+ description="OVERLINE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ mathfiller="barfill",
+ mathspec={
+ {
+ class="under",
+ name="underbar",
+ },
+ {
+ class="over",
+ name="overbar",
+ },
+ },
+ mathstretch="h",
+ specials={ "compat", 0x20, 0x305 },
+ unicodeslot=0x203E,
+ },
+ [0x203F]={
+ category="pc",
+ description="UNDERTIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x203F,
+ },
+ [0x2040]={
+ category="pc",
+ description="CHARACTER TIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2040,
+ },
+ [0x2041]={
+ category="po",
+ description="CARET INSERTION POINT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2041,
+ },
+ [0x2042]={
+ adobename="asterism",
+ category="po",
+ description="ASTERISM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2042,
+ },
+ [0x2043]={
+ category="po",
+ description="HYPHEN BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2043,
+ },
+ [0x2044]={
+ adobename="fraction",
+ category="sm",
+ contextname="textfraction",
+ description="FRACTION SLASH",
+ direction="cs",
+ linebreak="is",
+ mathspec={
+ {
+ class="ordinary",
+ name="slash",
+ },
+ {
+ class="close",
+ name="solidus",
+ },
+ },
+ unicodeslot=0x2044,
+ },
+ [0x2045]={
+ category="ps",
+ description="LEFT SQUARE BRACKET WITH QUILL",
+ direction="on",
+ linebreak="op",
+ mirror=0x2046,
+ unicodeslot=0x2045,
+ },
+ [0x2046]={
+ category="pe",
+ description="RIGHT SQUARE BRACKET WITH QUILL",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2045,
+ unicodeslot=0x2046,
+ },
+ [0x2047]={
+ category="po",
+ description="DOUBLE QUESTION MARK",
+ direction="on",
+ linebreak="ns",
+ specials={ "compat", 0x3F, 0x3F },
+ unicodeslot=0x2047,
+ },
+ [0x2048]={
+ category="po",
+ description="QUESTION EXCLAMATION MARK",
+ direction="on",
+ linebreak="ns",
+ specials={ "compat", 0x3F, 0x21 },
+ unicodeslot=0x2048,
+ },
+ [0x2049]={
+ category="po",
+ description="EXCLAMATION QUESTION MARK",
+ direction="on",
+ linebreak="ns",
+ specials={ "compat", 0x21, 0x3F },
+ unicodeslot=0x2049,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x204A]={
+ category="po",
+ description="TIRONIAN SIGN ET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204A,
+ },
+ [0x204B]={
+ category="po",
+ description="REVERSED PILCROW SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204B,
+ },
+ [0x204C]={
+ category="po",
+ description="BLACK LEFTWARDS BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204C,
+ },
+ [0x204D]={
+ category="po",
+ description="BLACK RIGHTWARDS BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204D,
+ },
+ [0x204E]={
+ category="po",
+ description="LOW ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204E,
+ },
+ [0x204F]={
+ category="po",
+ description="REVERSED SEMICOLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x204F,
+ },
+ [0x2050]={
+ category="po",
+ description="CLOSE UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2050,
+ },
+ [0x2051]={
+ category="po",
+ description="TWO ASTERISKS ALIGNED VERTICALLY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2051,
+ },
+ [0x2052]={
+ category="sm",
+ description="COMMERCIAL MINUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2052,
+ },
+ [0x2053]={
+ category="po",
+ description="SWUNG DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2053,
+ },
+ [0x2054]={
+ category="pc",
+ description="INVERTED UNDERTIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2054,
+ },
+ [0x2055]={
+ category="po",
+ description="FLOWER PUNCTUATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2055,
+ },
+ [0x2056]={
+ category="po",
+ description="THREE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2056,
+ },
+ [0x2057]={
+ category="po",
+ description="QUADRUPLE PRIME",
+ direction="on",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="quadrupleprime",
+ specials={ "compat", 0x2032, 0x2032, 0x2032, 0x2032 },
+ unicodeslot=0x2057,
+ },
+ [0x2058]={
+ category="po",
+ description="FOUR DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2058,
+ },
+ [0x2059]={
+ category="po",
+ description="FIVE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2059,
+ },
+ [0x205A]={
+ category="po",
+ description="TWO DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x205A,
+ },
+ [0x205B]={
+ category="po",
+ description="FOUR DOT MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x205B,
+ },
+ [0x205C]={
+ category="po",
+ description="DOTTED CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x205C,
+ },
+ [0x205D]={
+ category="po",
+ description="TRICOLON",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x205D,
+ },
+ [0x205E]={
+ category="po",
+ description="VERTICAL FOUR DOTS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x205E,
+ },
+ [0x205F]={
+ category="zs",
+ contextname="medspace",
+ description="MEDIUM MATHEMATICAL SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "compat", 0x20 },
+ unicodeslot=0x205F,
+ },
+ [0x2060]={
+ category="cf",
+ description="WORD JOINER",
+ direction="bn",
+ linebreak="wj",
+ unicodeslot=0x2060,
+ },
+ [0x2061]={
+ category="cf",
+ comment="maybe: nulloperator",
+ description="FUNCTION APPLICATION",
+ direction="bn",
+ linebreak="al",
+ unicodeslot=0x2061,
+ },
+ [0x2062]={
+ category="cf",
+ description="INVISIBLE TIMES",
+ direction="bn",
+ linebreak="al",
+ unicodeslot=0x2062,
+ },
+ [0x2063]={
+ category="cf",
+ description="INVISIBLE SEPARATOR",
+ direction="bn",
+ linebreak="al",
+ mathclass="binary",
+ mathname="invisibletimes",
+ unicodeslot=0x2063,
+ },
+ [0x2064]={
+ category="cf",
+ description="INVISIBLE PLUS",
+ direction="bn",
+ linebreak="al",
+ unicodeslot=0x2064,
+ },
+ [0x2066]={
+ arabic="u",
+ category="cf",
+ description="LEFT-TO-RIGHT ISOLATE",
+ direction="lri",
+ linebreak="cm",
+ unicodeslot=0x2066,
+ },
+ [0x2067]={
+ arabic="u",
+ category="cf",
+ description="RIGHT-TO-LEFT ISOLATE",
+ direction="rli",
+ linebreak="cm",
+ unicodeslot=0x2067,
+ },
+ [0x2068]={
+ arabic="u",
+ category="cf",
+ description="FIRST STRONG ISOLATE",
+ direction="fsi",
+ linebreak="cm",
+ unicodeslot=0x2068,
+ },
+ [0x2069]={
+ arabic="u",
+ category="cf",
+ description="POP DIRECTIONAL ISOLATE",
+ direction="pdi",
+ linebreak="cm",
+ unicodeslot=0x2069,
+ },
+ [0x206A]={
+ category="cf",
+ description="INHIBIT SYMMETRIC SWAPPING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206A,
+ },
+ [0x206B]={
+ category="cf",
+ description="ACTIVATE SYMMETRIC SWAPPING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206B,
+ },
+ [0x206C]={
+ category="cf",
+ description="INHIBIT ARABIC FORM SHAPING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206C,
+ },
+ [0x206D]={
+ category="cf",
+ description="ACTIVATE ARABIC FORM SHAPING",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206D,
+ },
+ [0x206E]={
+ category="cf",
+ description="NATIONAL DIGIT SHAPES",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206E,
+ },
+ [0x206F]={
+ category="cf",
+ description="NOMINAL DIGIT SHAPES",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x206F,
+ },
+ [0x2070]={
+ adobename="zerosuperior",
+ category="no",
+ description="SUPERSCRIPT ZERO",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x30 },
+ unicodeslot=0x2070,
+ },
+ [0x2071]={
+ category="ll",
+ description="SUPERSCRIPT LATIN SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x69 },
+ unicodeslot=0x2071,
+ },
+ [0x2074]={
+ adobename="foursuperior",
+ category="no",
+ cjkwd="a",
+ description="SUPERSCRIPT FOUR",
+ direction="en",
+ linebreak="ai",
+ specials={ "super", 0x34 },
+ unicodeslot=0x2074,
+ },
+ [0x2075]={
+ adobename="fivesuperior",
+ category="no",
+ description="SUPERSCRIPT FIVE",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x35 },
+ unicodeslot=0x2075,
+ },
+ [0x2076]={
+ adobename="sixsuperior",
+ category="no",
+ description="SUPERSCRIPT SIX",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x36 },
+ unicodeslot=0x2076,
+ },
+ [0x2077]={
+ adobename="sevensuperior",
+ category="no",
+ description="SUPERSCRIPT SEVEN",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x37 },
+ unicodeslot=0x2077,
+ },
+ [0x2078]={
+ adobename="eightsuperior",
+ category="no",
+ description="SUPERSCRIPT EIGHT",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x38 },
+ unicodeslot=0x2078,
+ },
+ [0x2079]={
+ adobename="ninesuperior",
+ category="no",
+ description="SUPERSCRIPT NINE",
+ direction="en",
+ linebreak="al",
+ specials={ "super", 0x39 },
+ unicodeslot=0x2079,
+ },
+ [0x207A]={
+ adobename="plussuperior",
+ category="sm",
+ description="SUPERSCRIPT PLUS SIGN",
+ direction="es",
+ linebreak="al",
+ mathclass="binary",
+ mathname="positivesign",
+ specials={ "super", 0x2B },
+ unicodeslot=0x207A,
+ },
+ [0x207B]={
+ category="sm",
+ description="SUPERSCRIPT MINUS",
+ direction="es",
+ linebreak="al",
+ mathclass="binary",
+ mathname="negativesign",
+ specials={ "super", 0x2212 },
+ unicodeslot=0x207B,
+ },
+ [0x207C]={
+ adobename="equalsuperior",
+ category="sm",
+ description="SUPERSCRIPT EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x3D },
+ unicodeslot=0x207C,
+ },
+ [0x207D]={
+ adobename="parenleftsuperior",
+ category="ps",
+ description="SUPERSCRIPT LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0x207E,
+ specials={ "super", 0x28 },
+ textclass="open",
+ unicodeslot=0x207D,
+ },
+ [0x207E]={
+ adobename="parenrightsuperior",
+ category="pe",
+ description="SUPERSCRIPT RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0x207D,
+ specials={ "super", 0x29 },
+ textclass="close",
+ unicodeslot=0x207E,
+ },
+ [0x207F]={
+ adobename="nsuperior",
+ category="ll",
+ cjkwd="a",
+ description="SUPERSCRIPT LATIN SMALL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "super", 0x6E },
+ unicodeslot=0x207F,
+ },
+ [0x2080]={
+ adobename="zeroinferior",
+ category="no",
+ description="SUBSCRIPT ZERO",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x30 },
+ unicodeslot=0x2080,
+ },
+ [0x2081]={
+ adobename="oneinferior",
+ category="no",
+ cjkwd="a",
+ description="SUBSCRIPT ONE",
+ direction="en",
+ linebreak="ai",
+ specials={ "sub", 0x31 },
+ unicodeslot=0x2081,
+ },
+ [0x2082]={
+ adobename="twoinferior",
+ category="no",
+ cjkwd="a",
+ description="SUBSCRIPT TWO",
+ direction="en",
+ linebreak="ai",
+ specials={ "sub", 0x32 },
+ unicodeslot=0x2082,
+ },
+ [0x2083]={
+ adobename="threeinferior",
+ category="no",
+ cjkwd="a",
+ description="SUBSCRIPT THREE",
+ direction="en",
+ linebreak="ai",
+ specials={ "sub", 0x33 },
+ unicodeslot=0x2083,
+ },
+ [0x2084]={
+ adobename="fourinferior",
+ category="no",
+ cjkwd="a",
+ description="SUBSCRIPT FOUR",
+ direction="en",
+ linebreak="ai",
+ specials={ "sub", 0x34 },
+ unicodeslot=0x2084,
+ },
+ [0x2085]={
+ adobename="fiveinferior",
+ category="no",
+ description="SUBSCRIPT FIVE",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x35 },
+ unicodeslot=0x2085,
+ },
+ [0x2086]={
+ adobename="sixinferior",
+ category="no",
+ description="SUBSCRIPT SIX",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x36 },
+ unicodeslot=0x2086,
+ },
+ [0x2087]={
+ adobename="seveninferior",
+ category="no",
+ description="SUBSCRIPT SEVEN",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x37 },
+ unicodeslot=0x2087,
+ },
+ [0x2088]={
+ adobename="eightinferior",
+ category="no",
+ description="SUBSCRIPT EIGHT",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x38 },
+ unicodeslot=0x2088,
+ },
+ [0x2089]={
+ adobename="nineinferior",
+ category="no",
+ description="SUBSCRIPT NINE",
+ direction="en",
+ linebreak="al",
+ specials={ "sub", 0x39 },
+ unicodeslot=0x2089,
+ },
+ [0x208A]={
+ category="sm",
+ description="SUBSCRIPT PLUS SIGN",
+ direction="es",
+ linebreak="al",
+ specials={ "sub", 0x2B },
+ unicodeslot=0x208A,
+ },
+ [0x208B]={
+ category="sm",
+ description="SUBSCRIPT MINUS",
+ direction="es",
+ linebreak="al",
+ specials={ "sub", 0x2212 },
+ unicodeslot=0x208B,
+ },
+ [0x208C]={
+ category="sm",
+ description="SUBSCRIPT EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "sub", 0x3D },
+ unicodeslot=0x208C,
+ },
+ [0x208D]={
+ adobename="parenleftinferior",
+ category="ps",
+ description="SUBSCRIPT LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0x208E,
+ specials={ "sub", 0x28 },
+ textclass="open",
+ unicodeslot=0x208D,
+ },
+ [0x208E]={
+ adobename="parenrightinferior",
+ category="pe",
+ description="SUBSCRIPT RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0x208D,
+ specials={ "sub", 0x29 },
+ textclass="close",
+ unicodeslot=0x208E,
+ },
+ [0x2090]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x61 },
+ unicodeslot=0x2090,
+ },
+ [0x2091]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x65 },
+ unicodeslot=0x2091,
+ },
+ [0x2092]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6F },
+ unicodeslot=0x2092,
+ },
+ [0x2093]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER X",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x78 },
+ unicodeslot=0x2093,
+ },
+ [0x2094]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER SCHWA",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x259 },
+ unicodeslot=0x2094,
+ },
+ [0x2095]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER H",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x68 },
+ unicodeslot=0x2095,
+ },
+ [0x2096]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER K",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6B },
+ unicodeslot=0x2096,
+ },
+ [0x2097]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER L",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6C },
+ unicodeslot=0x2097,
+ },
+ [0x2098]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER M",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6D },
+ unicodeslot=0x2098,
+ },
+ [0x2099]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER N",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6E },
+ unicodeslot=0x2099,
+ },
+ [0x209A]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER P",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x70 },
+ unicodeslot=0x209A,
+ },
+ [0x209B]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER S",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x73 },
+ unicodeslot=0x209B,
+ },
+ [0x209C]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER T",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x74 },
+ unicodeslot=0x209C,
+ },
+ [0x20A0]={
+ category="sc",
+ description="EURO-CURRENCY SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A0,
+ },
+ [0x20A1]={
+ adobename="colonsign",
+ category="sc",
+ description="COLON SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A1,
+ },
+ [0x20A2]={
+ adobename="cruzeiro",
+ category="sc",
+ description="CRUZEIRO SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A2,
+ },
+ [0x20A3]={
+ adobename="franc",
+ category="sc",
+ description="FRENCH FRANC SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A3,
+ },
+ [0x20A4]={
+ adobename="lira",
+ category="sc",
+ description="LIRA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A4,
+ },
+ [0x20A5]={
+ category="sc",
+ description="MILL SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A5,
+ },
+ [0x20A6]={
+ category="sc",
+ description="NAIRA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A6,
+ },
+ [0x20A7]={
+ adobename="peseta",
+ category="sc",
+ description="PESETA SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x20A7,
+ },
+ [0x20A8]={
+ category="sc",
+ description="RUPEE SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "compat", 0x52, 0x73 },
+ unicodeslot=0x20A8,
+ },
+ [0x20A9]={
+ adobename="won",
+ category="sc",
+ cjkwd="h",
+ description="WON SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20A9,
+ },
+ [0x20AA]={
+ adobename="sheqelhebrew",
+ category="sc",
+ description="NEW SHEQEL SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AA,
+ },
+ [0x20AB]={
+ adobename="dong",
+ category="sc",
+ contextname="textdong",
+ description="DONG SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AB,
+ },
+ [0x20AC]={
+ adobename="euro",
+ category="sc",
+ cjkwd="a",
+ contextname="texteuro",
+ description="EURO SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AC,
+ },
+ [0x20AD]={
+ category="sc",
+ description="KIP SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AD,
+ },
+ [0x20AE]={
+ category="sc",
+ description="TUGRIK SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AE,
+ },
+ [0x20AF]={
+ category="sc",
+ description="DRACHMA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20AF,
+ },
+ [0x20B0]={
+ category="sc",
+ description="GERMAN PENNY SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B0,
+ },
+ [0x20B1]={
+ category="sc",
+ description="PESO SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B1,
+ },
+ [0x20B2]={
+ category="sc",
+ description="GUARANI SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B2,
+ },
+ [0x20B3]={
+ category="sc",
+ description="AUSTRAL SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B3,
+ },
+ [0x20B4]={
+ category="sc",
+ description="HRYVNIA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B4,
+ },
+ [0x20B5]={
+ category="sc",
+ description="CEDI SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B5,
+ },
+ [0x20B6]={
+ category="sc",
+ description="LIVRE TOURNOIS SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x20B6,
+ },
+ [0x20B7]={
+ category="sc",
+ description="SPESMILO SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B7,
+ },
+ [0x20B8]={
+ category="sc",
+ description="TENGE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B8,
+ },
+ [0x20B9]={
+ category="sc",
+ description="INDIAN RUPEE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B9,
+ },
+ [0x20BA]={
+ category="sc",
+ description="TURKISH LIRA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20BA,
+ },
+ [0x20BB]={
+ category="sc",
+ description="NORDIC MARK SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x20BB,
+ },
+ [0x20BC]={
+ category="sc",
+ description="MANAT SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20BC,
+ },
+ [0x20BD]={
+ category="sc",
+ description="RUBLE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20BD,
+ },
+ [0x20BE]={
+ category="sc",
+ description="LARI SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x20BE,
+ },
+ [0x20D0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LEFT HARPOON ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D0,
+ },
+ [0x20D1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING RIGHT HARPOON ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D1,
+ },
+ [0x20D2]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING LONG VERTICAL LINE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D2,
+ },
+ [0x20D3]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING SHORT VERTICAL LINE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D3,
+ },
+ [0x20D4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING ANTICLOCKWISE ARROW ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D4,
+ },
+ [0x20D5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CLOCKWISE ARROW ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D5,
+ },
+ [0x20D6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LEFT ARROW ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D6,
+ },
+ [0x20D7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING RIGHT ARROW ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ mathname="vec",
+ unicodeslot=0x20D7,
+ },
+ [0x20D8]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING RING OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D8,
+ },
+ [0x20D9]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING CLOCKWISE RING OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20D9,
+ },
+ [0x20DA]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING ANTICLOCKWISE RING OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20DA,
+ },
+ [0x20DB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING THREE DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ mathname="dddot",
+ unicodeslot=0x20DB,
+ },
+ [0x20DC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING FOUR DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20DC,
+ },
+ [0x20DD]={
+ category="me",
+ description="COMBINING ENCLOSING CIRCLE",
+ direction="nsm",
+ linebreak="cm",
+ mathspec={
+ {
+ class="default",
+ name="bigcircle",
+ },
+ {
+ class="binary",
+ name="bigcircle",
+ },
+ },
+ unicodeslot=0x20DD,
+ },
+ [0x20DE]={
+ category="me",
+ description="COMBINING ENCLOSING SQUARE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="default",
+ mathname="bigsquare",
+ unicodeslot=0x20DE,
+ },
+ [0x20DF]={
+ category="me",
+ description="COMBINING ENCLOSING DIAMOND",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="default",
+ mathname="bigdiamond",
+ unicodeslot=0x20DF,
+ },
+ [0x20E0]={
+ category="me",
+ description="COMBINING ENCLOSING CIRCLE BACKSLASH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E0,
+ },
+ [0x20E1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LEFT RIGHT ARROW ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E1,
+ },
+ [0x20E2]={
+ category="me",
+ description="COMBINING ENCLOSING SCREEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E2,
+ },
+ [0x20E3]={
+ category="me",
+ description="COMBINING ENCLOSING KEYCAP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E3,
+ },
+ [0x20E4]={
+ category="me",
+ description="COMBINING ENCLOSING UPWARD POINTING TRIANGLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E4,
+ },
+ [0x20E5]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING REVERSE SOLIDUS OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E5,
+ },
+ [0x20E6]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING DOUBLE VERTICAL STROKE OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E6,
+ },
+ [0x20E7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING ANNUITY SYMBOL",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ mathname="actuarial",
+ unicodeslot=0x20E7,
+ },
+ [0x20E8]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING TRIPLE UNDERDOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20E8,
+ },
+ [0x20E9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING WIDE BRIDGE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="topaccent",
+ unicodeslot=0x20E9,
+ },
+ [0x20EA]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING LEFTWARDS ARROW OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20EA,
+ },
+ [0x20EB]={
+ category="mn",
+ combining=0x1,
+ description="COMBINING LONG DOUBLE SOLIDUS OVERLAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20EB,
+ },
+ [0x20EC]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20EC,
+ },
+ [0x20ED]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20ED,
+ },
+ [0x20EE]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LEFT ARROW BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20EE,
+ },
+ [0x20EF]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING RIGHT ARROW BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20EF,
+ },
+ [0x20F0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING ASTERISK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20F0,
+ },
+ [0x2100]={
+ category="so",
+ description="ACCOUNT OF",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x61, 0x2F, 0x63 },
+ unicodeslot=0x2100,
+ },
+ [0x2101]={
+ category="so",
+ description="ADDRESSED TO THE SUBJECT",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x61, 0x2F, 0x73 },
+ unicodeslot=0x2101,
+ },
+ [0x2102]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL C",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="complexes",
+ specials={ "font", 0x43 },
+ unicodeslot=0x2102,
+ },
+ [0x2103]={
+ adobename="centigrade",
+ category="so",
+ cjkwd="a",
+ contextname="textcelsius",
+ description="DEGREE CELSIUS",
+ direction="on",
+ linebreak="po",
+ specials={ "compat", 0xB0, 0x43 },
+ unicodeslot=0x2103,
+ },
+ [0x2104]={
+ category="so",
+ description="CENTRE LINE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2104,
+ },
+ [0x2105]={
+ adobename="careof",
+ category="so",
+ cjkwd="a",
+ description="CARE OF",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x63, 0x2F, 0x6F },
+ unicodeslot=0x2105,
+ },
+ [0x2106]={
+ category="so",
+ description="CADA UNA",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x63, 0x2F, 0x75 },
+ unicodeslot=0x2106,
+ },
+ [0x2107]={
+ category="lu",
+ description="EULER CONSTANT",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="Eulerconst",
+ specials={ "compat", 0x190 },
+ unicodeslot=0x2107,
+ },
+ [0x2108]={
+ category="so",
+ description="SCRUPLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2108,
+ },
+ [0x2109]={
+ adobename="fahrenheit",
+ category="so",
+ cjkwd="a",
+ description="DEGREE FAHRENHEIT",
+ direction="on",
+ linebreak="po",
+ specials={ "compat", 0xB0, 0x46 },
+ unicodeslot=0x2109,
+ },
+ [0x210A]={
+ category="ll",
+ description="SCRIPT SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x210A,
+ },
+ [0x210B]={
+ category="lu",
+ description="SCRIPT CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x210B,
+ },
+ [0x210C]={
+ category="lu",
+ description="BLACK-LETTER CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x210C,
+ },
+ [0x210D]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x210D,
+ },
+ [0x210E]={
+ category="ll",
+ description="PLANCK CONSTANT",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="Plankconst",
+ specials={ "font", 0x68 },
+ unicodeslot=0x210E,
+ },
+ [0x210F]={
+ category="ll",
+ description="PLANCK CONSTANT OVER TWO PI",
+ direction="l",
+ linebreak="al",
+ mathspec={
+ {
+ class="variable",
+ name="hslash",
+ },
+ {
+ class="ordinary",
+ name="hbar",
+ },
+ },
+ specials={ "font", 0x127 },
+ unicodeslot=0x210F,
+ },
+ [0x2110]={
+ category="lu",
+ description="SCRIPT CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x2110,
+ },
+ [0x2111]={
+ adobename="Ifraktur",
+ category="lu",
+ description="BLACK-LETTER CAPITAL I",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="Im",
+ specials={ "font", 0x49 },
+ unicodeslot=0x2111,
+ },
+ [0x2112]={
+ category="lu",
+ description="SCRIPT CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x2112,
+ },
+ [0x2113]={
+ adobename="lsquare",
+ category="ll",
+ cjkwd="a",
+ description="SCRIPT SMALL L",
+ direction="l",
+ linebreak="ai",
+ mathclass="default",
+ mathname="ell",
+ specials={ "font", 0x6C },
+ unicodeslot=0x2113,
+ },
+ [0x2114]={
+ category="so",
+ description="L B BAR SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2114,
+ },
+ [0x2115]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL N",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="naturalnumbers",
+ specials={ "font", 0x4E },
+ unicodeslot=0x2115,
+ },
+ [0x2116]={
+ adobename="numero",
+ category="so",
+ cjkwd="a",
+ contextname="textnumero",
+ description="NUMERO SIGN",
+ direction="on",
+ linebreak="pr",
+ specials={ "compat", 0x4E, 0x6F },
+ unicodeslot=0x2116,
+ },
+ [0x2117]={
+ category="so",
+ contextname="textcircledP",
+ description="SOUND RECORDING COPYRIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2117,
+ },
+ [0x2118]={
+ adobename="weierstrass",
+ category="so",
+ description="SCRIPT CAPITAL P",
+ direction="on",
+ linebreak="al",
+ mathclass="default",
+ mathname="wp",
+ unicodeslot=0x2118,
+ },
+ [0x2119]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL P",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="primes",
+ specials={ "font", 0x50 },
+ unicodeslot=0x2119,
+ },
+ [0x211A]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="rationals",
+ specials={ "font", 0x51 },
+ unicodeslot=0x211A,
+ },
+ [0x211B]={
+ category="lu",
+ description="SCRIPT CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x211B,
+ },
+ [0x211C]={
+ adobename="Rfraktur",
+ category="lu",
+ description="BLACK-LETTER CAPITAL R",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="Re",
+ specials={ "font", 0x52 },
+ unicodeslot=0x211C,
+ },
+ [0x211D]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL R",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="reals",
+ specials={ "font", 0x52 },
+ unicodeslot=0x211D,
+ },
+ [0x211E]={
+ adobename="prescription",
+ category="so",
+ description="PRESCRIPTION TAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x211E,
+ },
+ [0x211F]={
+ category="so",
+ description="RESPONSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x211F,
+ },
+ [0x2120]={
+ category="so",
+ description="SERVICE MARK",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x53, 0x4D },
+ unicodeslot=0x2120,
+ },
+ [0x2121]={
+ adobename="telephone",
+ category="so",
+ cjkwd="a",
+ description="TELEPHONE SIGN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x54, 0x45, 0x4C },
+ unicodeslot=0x2121,
+ },
+ [0x2122]={
+ adobename="trademark",
+ category="so",
+ cjkwd="a",
+ contextname="trademark",
+ description="TRADE MARK SIGN",
+ direction="on",
+ linebreak="ai",
+ specials={ "super", 0x54, 0x4D },
+ unicodeslot=0x2122,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2123]={
+ category="so",
+ description="VERSICLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2123,
+ },
+ [0x2124]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="integers",
+ specials={ "font", 0x5A },
+ unicodeslot=0x2124,
+ },
+ [0x2125]={
+ category="so",
+ contextname="textounce",
+ description="OUNCE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2125,
+ },
+ [0x2126]={
+ adobename="Omega",
+ category="lu",
+ cjkwd="a",
+ contextname="textohm",
+ description="OHM SIGN",
+ direction="l",
+ lccode=0x3C9,
+ linebreak="al",
+ mathclass="variable",
+ mathname="ohm",
+ specials={ "char", 0x3A9 },
+ unicodeslot=0x2126,
+ },
+ [0x2127]={
+ category="so",
+ contextname="textmho",
+ description="INVERTED OHM SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="variable",
+ mathname="mho",
+ unicodeslot=0x2127,
+ },
+ [0x2128]={
+ category="lu",
+ description="BLACK-LETTER CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x2128,
+ },
+ [0x2129]={
+ category="so",
+ description="TURNED GREEK SMALL LETTER IOTA",
+ direction="on",
+ linebreak="al",
+ mathclass="variable",
+ mathname="turnediota",
+ unicodeslot=0x2129,
+ },
+ [0x212A]={
+ category="lu",
+ contextname="textkelvin",
+ description="KELVIN SIGN",
+ direction="l",
+ lccode=0x6B,
+ linebreak="al",
+ specials={ "char", 0x4B },
+ unicodeslot=0x212A,
+ },
+ [0x212B]={
+ adobename="angstrom",
+ category="lu",
+ cjkwd="a",
+ contextname="textAngstrom",
+ description="ANGSTROM SIGN",
+ direction="l",
+ lccode=0xE5,
+ linebreak="ai",
+ mathclass="variable",
+ mathname="Angstrom",
+ specials={ "char", 0xC5 },
+ unicodeslot=0x212B,
+ },
+ [0x212C]={
+ category="lu",
+ description="SCRIPT CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x212C,
+ },
+ [0x212D]={
+ category="lu",
+ description="BLACK-LETTER CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x212D,
+ },
+ [0x212E]={
+ adobename="estimated",
+ category="so",
+ description="ESTIMATED SYMBOL",
+ direction="et",
+ linebreak="al",
+ unicodeslot=0x212E,
+ },
+ [0x212F]={
+ category="ll",
+ description="SCRIPT SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x212F,
+ },
+ [0x2130]={
+ category="lu",
+ description="SCRIPT CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x2130,
+ },
+ [0x2131]={
+ category="lu",
+ description="SCRIPT CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x2131,
+ },
+ [0x2132]={
+ category="lu",
+ description="TURNED CAPITAL F",
+ direction="l",
+ lccode=0x214E,
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="Finv",
+ unicodeslot=0x2132,
+ },
+ [0x2133]={
+ category="lu",
+ description="SCRIPT CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x2133,
+ },
+ [0x2134]={
+ category="ll",
+ description="SCRIPT SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x2134,
+ },
+ [0x2135]={
+ adobename="aleph",
+ category="lo",
+ description="ALEF SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="aleph",
+ specials={ "compat", 0x5D0 },
+ unicodeslot=0x2135,
+ },
+ [0x2136]={
+ category="lo",
+ description="BET SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="beth",
+ specials={ "compat", 0x5D1 },
+ unicodeslot=0x2136,
+ },
+ [0x2137]={
+ category="lo",
+ description="GIMEL SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="gimel",
+ specials={ "compat", 0x5D2 },
+ unicodeslot=0x2137,
+ },
+ [0x2138]={
+ category="lo",
+ description="DALET SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="daleth",
+ specials={ "compat", 0x5D3 },
+ unicodeslot=0x2138,
+ },
+ [0x2139]={
+ category="ll",
+ description="INFORMATION SOURCE",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x2139,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x213A]={
+ category="so",
+ description="ROTATED CAPITAL Q",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x213A,
+ },
+ [0x213B]={
+ category="so",
+ description="FACSIMILE SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x46, 0x41, 0x58 },
+ unicodeslot=0x213B,
+ },
+ [0x213C]={
+ category="ll",
+ description="DOUBLE-STRUCK SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x213C,
+ },
+ [0x213D]={
+ category="ll",
+ description="DOUBLE-STRUCK SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x213D,
+ },
+ [0x213E]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x213E,
+ },
+ [0x213F]={
+ category="lu",
+ description="DOUBLE-STRUCK CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x213F,
+ },
+ [0x2140]={
+ category="sm",
+ description="DOUBLE-STRUCK N-ARY SUMMATION",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2211 },
+ unicodeslot=0x2140,
+ },
+ [0x2141]={
+ category="sm",
+ description="TURNED SANS-SERIF CAPITAL G",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="Game",
+ unicodeslot=0x2141,
+ },
+ [0x2142]={
+ category="sm",
+ comment="mathname=sansLturned",
+ description="TURNED SANS-SERIF CAPITAL L",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ unicodeslot=0x2142,
+ },
+ [0x2143]={
+ category="sm",
+ comment="mathname=sansLmirrored",
+ description="REVERSED SANS-SERIF CAPITAL L",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ unicodeslot=0x2143,
+ },
+ [0x2144]={
+ category="sm",
+ comment="mathname=Yup",
+ description="TURNED SANS-SERIF CAPITAL Y",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ unicodeslot=0x2144,
+ },
+ [0x2145]={
+ category="lu",
+ description="DOUBLE-STRUCK ITALIC CAPITAL D",
+ direction="l",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="differentialD",
+ specials={ "font", 0x44 },
+ unicodeslot=0x2145,
+ },
+ [0x2146]={
+ category="ll",
+ description="DOUBLE-STRUCK ITALIC SMALL D",
+ direction="l",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="differentiald",
+ specials={ "font", 0x64 },
+ unicodeslot=0x2146,
+ },
+ [0x2147]={
+ category="ll",
+ description="DOUBLE-STRUCK ITALIC SMALL E",
+ direction="l",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="exponentiale",
+ specials={ "font", 0x65 },
+ unicodeslot=0x2147,
+ },
+ [0x2148]={
+ category="ll",
+ description="DOUBLE-STRUCK ITALIC SMALL I",
+ direction="l",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="imaginaryi",
+ specials={ "font", 0x69 },
+ unicodeslot=0x2148,
+ },
+ [0x2149]={
+ category="ll",
+ description="DOUBLE-STRUCK ITALIC SMALL J",
+ direction="l",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="imaginaryj",
+ specials={ "font", 0x6A },
+ unicodeslot=0x2149,
+ },
+ [0x214A]={
+ category="so",
+ description="PROPERTY LINE",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="PropertyLine",
+ unicodeslot=0x214A,
+ },
+ [0x214B]={
+ category="sm",
+ description="TURNED AMPERSAND",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="upand",
+ unicodeslot=0x214B,
+ },
+ [0x214C]={
+ category="so",
+ description="PER SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x214C,
+ },
+ [0x214D]={
+ category="so",
+ description="AKTIESELSKAB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x214D,
+ },
+ [0x214E]={
+ category="ll",
+ description="TURNED SMALL F",
+ direction="l",
+ linebreak="al",
+ uccode=0x2132,
+ unicodeslot=0x214E,
+ },
+ [0x214F]={
+ category="so",
+ description="SYMBOL FOR SAMARITAN SOURCE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x214F,
+ },
+ [0x2150]={
+ category="no",
+ description="VULGAR FRACTION ONE SEVENTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044, 0x37 },
+ unicodeslot=0x2150,
+ },
+ [0x2151]={
+ category="no",
+ description="VULGAR FRACTION ONE NINTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044, 0x39 },
+ unicodeslot=0x2151,
+ },
+ [0x2152]={
+ category="no",
+ description="VULGAR FRACTION ONE TENTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044, 0x31, 0x30 },
+ unicodeslot=0x2152,
+ },
+ [0x2153]={
+ adobename="onethird",
+ category="no",
+ cjkwd="a",
+ contextname="onethird",
+ description="VULGAR FRACTION ONE THIRD",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044, 0x33 },
+ unicodeslot=0x2153,
+ },
+ [0x2154]={
+ adobename="twothirds",
+ category="no",
+ cjkwd="a",
+ contextname="twothirds",
+ description="VULGAR FRACTION TWO THIRDS",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x32, 0x2044, 0x33 },
+ unicodeslot=0x2154,
+ },
+ [0x2155]={
+ category="no",
+ contextname="onefifth",
+ description="VULGAR FRACTION ONE FIFTH",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x31, 0x2044, 0x35 },
+ unicodeslot=0x2155,
+ },
+ [0x2156]={
+ category="no",
+ contextname="twofifths",
+ description="VULGAR FRACTION TWO FIFTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x32, 0x2044, 0x35 },
+ unicodeslot=0x2156,
+ },
+ [0x2157]={
+ category="no",
+ contextname="threefifths",
+ description="VULGAR FRACTION THREE FIFTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x33, 0x2044, 0x35 },
+ unicodeslot=0x2157,
+ },
+ [0x2158]={
+ category="no",
+ contextname="fourfifths",
+ description="VULGAR FRACTION FOUR FIFTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x34, 0x2044, 0x35 },
+ unicodeslot=0x2158,
+ },
+ [0x2159]={
+ category="no",
+ contextname="onesixth",
+ description="VULGAR FRACTION ONE SIXTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044, 0x36 },
+ unicodeslot=0x2159,
+ },
+ [0x215A]={
+ category="no",
+ contextname="fivesixths",
+ description="VULGAR FRACTION FIVE SIXTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x35, 0x2044, 0x36 },
+ unicodeslot=0x215A,
+ },
+ [0x215B]={
+ adobename="oneeighth",
+ category="no",
+ cjkwd="a",
+ contextname="oneeighth",
+ description="VULGAR FRACTION ONE EIGHTH",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x31, 0x2044, 0x38 },
+ unicodeslot=0x215B,
+ },
+ [0x215C]={
+ adobename="threeeighths",
+ category="no",
+ cjkwd="a",
+ contextname="threeeighths",
+ description="VULGAR FRACTION THREE EIGHTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x33, 0x2044, 0x38 },
+ unicodeslot=0x215C,
+ },
+ [0x215D]={
+ adobename="fiveeighths",
+ category="no",
+ cjkwd="a",
+ contextname="fiveeighths",
+ description="VULGAR FRACTION FIVE EIGHTHS",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x35, 0x2044, 0x38 },
+ unicodeslot=0x215D,
+ },
+ [0x215E]={
+ adobename="seveneighths",
+ category="no",
+ cjkwd="a",
+ contextname="seveneighths",
+ description="VULGAR FRACTION SEVEN EIGHTHS",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x37, 0x2044, 0x38 },
+ unicodeslot=0x215E,
+ },
+ [0x215F]={
+ category="no",
+ description="FRACTION NUMERATOR ONE",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x31, 0x2044 },
+ unicodeslot=0x215F,
+ },
+ [0x2160]={
+ adobename="Oneroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanI",
+ description="ROMAN NUMERAL ONE",
+ direction="l",
+ lccode=0x2170,
+ linebreak="ai",
+ specials={ "compat", 0x49 },
+ unicodeslot=0x2160,
+ },
+ [0x2161]={
+ adobename="Tworoman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanII",
+ description="ROMAN NUMERAL TWO",
+ direction="l",
+ lccode=0x2171,
+ linebreak="ai",
+ specials={ "compat", 0x49, 0x49 },
+ unicodeslot=0x2161,
+ },
+ [0x2162]={
+ adobename="Threeroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanIII",
+ description="ROMAN NUMERAL THREE",
+ direction="l",
+ lccode=0x2172,
+ linebreak="ai",
+ specials={ "compat", 0x49, 0x49, 0x49 },
+ unicodeslot=0x2162,
+ },
+ [0x2163]={
+ adobename="Fourroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanIV",
+ description="ROMAN NUMERAL FOUR",
+ direction="l",
+ lccode=0x2173,
+ linebreak="ai",
+ specials={ "compat", 0x49, 0x56 },
+ unicodeslot=0x2163,
+ },
+ [0x2164]={
+ adobename="Fiveroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanV",
+ description="ROMAN NUMERAL FIVE",
+ direction="l",
+ lccode=0x2174,
+ linebreak="ai",
+ specials={ "compat", 0x56 },
+ unicodeslot=0x2164,
+ },
+ [0x2165]={
+ adobename="Sixroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanVI",
+ description="ROMAN NUMERAL SIX",
+ direction="l",
+ lccode=0x2175,
+ linebreak="ai",
+ specials={ "compat", 0x56, 0x49 },
+ unicodeslot=0x2165,
+ },
+ [0x2166]={
+ adobename="Sevenroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanVII",
+ description="ROMAN NUMERAL SEVEN",
+ direction="l",
+ lccode=0x2176,
+ linebreak="ai",
+ specials={ "compat", 0x56, 0x49, 0x49 },
+ unicodeslot=0x2166,
+ },
+ [0x2167]={
+ adobename="Eightroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanVIII",
+ description="ROMAN NUMERAL EIGHT",
+ direction="l",
+ lccode=0x2177,
+ linebreak="ai",
+ specials={ "compat", 0x56, 0x49, 0x49, 0x49 },
+ unicodeslot=0x2167,
+ },
+ [0x2168]={
+ adobename="Nineroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanIX",
+ description="ROMAN NUMERAL NINE",
+ direction="l",
+ lccode=0x2178,
+ linebreak="ai",
+ specials={ "compat", 0x49, 0x58 },
+ unicodeslot=0x2168,
+ },
+ [0x2169]={
+ adobename="Tenroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanX",
+ description="ROMAN NUMERAL TEN",
+ direction="l",
+ lccode=0x2179,
+ linebreak="ai",
+ specials={ "compat", 0x58 },
+ unicodeslot=0x2169,
+ },
+ [0x216A]={
+ adobename="Elevenroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanXI",
+ description="ROMAN NUMERAL ELEVEN",
+ direction="l",
+ lccode=0x217A,
+ linebreak="ai",
+ specials={ "compat", 0x58, 0x49 },
+ unicodeslot=0x216A,
+ },
+ [0x216B]={
+ adobename="Twelveroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanXII",
+ description="ROMAN NUMERAL TWELVE",
+ direction="l",
+ lccode=0x217B,
+ linebreak="ai",
+ specials={ "compat", 0x58, 0x49, 0x49 },
+ unicodeslot=0x216B,
+ },
+ [0x216C]={
+ category="nl",
+ contextname="romanL",
+ description="ROMAN NUMERAL FIFTY",
+ direction="l",
+ lccode=0x217C,
+ linebreak="al",
+ specials={ "compat", 0x4C },
+ unicodeslot=0x216C,
+ },
+ [0x216D]={
+ category="nl",
+ contextname="romanC",
+ description="ROMAN NUMERAL ONE HUNDRED",
+ direction="l",
+ lccode=0x217D,
+ linebreak="al",
+ specials={ "compat", 0x43 },
+ unicodeslot=0x216D,
+ },
+ [0x216E]={
+ category="nl",
+ contextname="romanD",
+ description="ROMAN NUMERAL FIVE HUNDRED",
+ direction="l",
+ lccode=0x217E,
+ linebreak="al",
+ specials={ "compat", 0x44 },
+ unicodeslot=0x216E,
+ },
+ [0x216F]={
+ category="nl",
+ contextname="romanM",
+ description="ROMAN NUMERAL ONE THOUSAND",
+ direction="l",
+ lccode=0x217F,
+ linebreak="al",
+ specials={ "compat", 0x4D },
+ unicodeslot=0x216F,
+ },
+ [0x2170]={
+ adobename="oneroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romani",
+ description="SMALL ROMAN NUMERAL ONE",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x69 },
+ uccode=0x2160,
+ unicodeslot=0x2170,
+ },
+ [0x2171]={
+ adobename="tworoman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanii",
+ description="SMALL ROMAN NUMERAL TWO",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x69, 0x69 },
+ uccode=0x2161,
+ unicodeslot=0x2171,
+ },
+ [0x2172]={
+ adobename="threeroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romaniii",
+ description="SMALL ROMAN NUMERAL THREE",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x69, 0x69, 0x69 },
+ uccode=0x2162,
+ unicodeslot=0x2172,
+ },
+ [0x2173]={
+ adobename="fourroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romaniv",
+ description="SMALL ROMAN NUMERAL FOUR",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x69, 0x76 },
+ uccode=0x2163,
+ unicodeslot=0x2173,
+ },
+ [0x2174]={
+ adobename="fiveroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanv",
+ description="SMALL ROMAN NUMERAL FIVE",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x76 },
+ uccode=0x2164,
+ unicodeslot=0x2174,
+ },
+ [0x2175]={
+ adobename="sixroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanvi",
+ description="SMALL ROMAN NUMERAL SIX",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x76, 0x69 },
+ uccode=0x2165,
+ unicodeslot=0x2175,
+ },
+ [0x2176]={
+ adobename="sevenroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanvii",
+ description="SMALL ROMAN NUMERAL SEVEN",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x76, 0x69, 0x69 },
+ uccode=0x2166,
+ unicodeslot=0x2176,
+ },
+ [0x2177]={
+ adobename="eightroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanviii",
+ description="SMALL ROMAN NUMERAL EIGHT",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x76, 0x69, 0x69, 0x69 },
+ uccode=0x2167,
+ unicodeslot=0x2177,
+ },
+ [0x2178]={
+ adobename="nineroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanix",
+ description="SMALL ROMAN NUMERAL NINE",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x69, 0x78 },
+ uccode=0x2168,
+ unicodeslot=0x2178,
+ },
+ [0x2179]={
+ adobename="tenroman",
+ category="nl",
+ cjkwd="a",
+ contextname="romanx",
+ description="SMALL ROMAN NUMERAL TEN",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x78 },
+ uccode=0x2169,
+ unicodeslot=0x2179,
+ },
+ [0x217A]={
+ adobename="elevenroman",
+ category="nl",
+ contextname="romanxi",
+ description="SMALL ROMAN NUMERAL ELEVEN",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x78, 0x69 },
+ uccode=0x216A,
+ unicodeslot=0x217A,
+ },
+ [0x217B]={
+ adobename="twelveroman",
+ category="nl",
+ contextname="romanxii",
+ description="SMALL ROMAN NUMERAL TWELVE",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x78, 0x69, 0x69 },
+ uccode=0x216B,
+ unicodeslot=0x217B,
+ },
+ [0x217C]={
+ category="nl",
+ contextname="romanl",
+ description="SMALL ROMAN NUMERAL FIFTY",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x6C },
+ uccode=0x216C,
+ unicodeslot=0x217C,
+ },
+ [0x217D]={
+ category="nl",
+ contextname="romanc",
+ description="SMALL ROMAN NUMERAL ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x63 },
+ uccode=0x216D,
+ unicodeslot=0x217D,
+ },
+ [0x217E]={
+ category="nl",
+ contextname="romand",
+ description="SMALL ROMAN NUMERAL FIVE HUNDRED",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x64 },
+ uccode=0x216E,
+ unicodeslot=0x217E,
+ },
+ [0x217F]={
+ category="nl",
+ contextname="romanm",
+ description="SMALL ROMAN NUMERAL ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x6D },
+ uccode=0x216F,
+ unicodeslot=0x217F,
+ },
+ [0x2180]={
+ category="nl",
+ description="ROMAN NUMERAL ONE THOUSAND C D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2180,
+ },
+ [0x2181]={
+ category="nl",
+ description="ROMAN NUMERAL FIVE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2181,
+ },
+ [0x2182]={
+ category="nl",
+ description="ROMAN NUMERAL TEN THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2182,
+ },
+ [0x2183]={
+ category="lu",
+ description="ROMAN NUMERAL REVERSED ONE HUNDRED",
+ direction="l",
+ lccode=0x2184,
+ linebreak="al",
+ unicodeslot=0x2183,
+ },
+ [0x2184]={
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED C",
+ direction="l",
+ linebreak="al",
+ uccode=0x2183,
+ unicodeslot=0x2184,
+ },
+ [0x2185]={
+ category="nl",
+ description="ROMAN NUMERAL SIX LATE FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2185,
+ },
+ [0x2186]={
+ category="nl",
+ description="ROMAN NUMERAL FIFTY EARLY FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2186,
+ },
+ [0x2187]={
+ category="nl",
+ description="ROMAN NUMERAL FIFTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2187,
+ },
+ [0x2188]={
+ category="nl",
+ description="ROMAN NUMERAL ONE HUNDRED THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2188,
+ },
+ [0x2189]={
+ category="no",
+ cjkwd="a",
+ description="VULGAR FRACTION ZERO THIRDS",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x30, 0x2044, 0x33 },
+ unicodeslot=0x2189,
+ },
+ [0x218A]={
+ category="so",
+ description="TURNED DIGIT TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x218A,
+ },
+ [0x218B]={
+ category="so",
+ description="TURNED DIGIT THREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x218B,
+ },
+ [0x2190]={
+ adobename="arrowleft",
+ category="sm",
+ cjkwd="a",
+ description="LEFTWARDS ARROW",
+ direction="on",
+ linebreak="ai",
+ mathextensible="l",
+ mathfiller="leftarrowfill",
+ mathspec={
+ {
+ class="relation",
+ name="leftarrow",
+ },
+ {
+ class="relation",
+ name="gets",
+ },
+ {
+ class="under",
+ name="underleftarrow",
+ },
+ {
+ class="over",
+ name="overleftarrow",
+ },
+ },
+ mathstretch="h",
+ unicodeslot=0x2190,
+ },
+ [0x2191]={
+ adobename="arrowup",
+ category="sm",
+ cjkwd="a",
+ description="UPWARDS ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="uparrow",
+ unicodeslot=0x2191,
+ },
+ [0x2192]={
+ adobename="arrowright",
+ category="sm",
+ cjkwd="a",
+ description="RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="ai",
+ mathextensible="r",
+ mathfiller="rightarrowfill",
+ mathspec={
+ {
+ class="relation",
+ name="rightarrow",
+ },
+ {
+ class="relation",
+ name="to",
+ },
+ {
+ class="under",
+ name="underrightarrow",
+ },
+ {
+ class="over",
+ name="overrightarrow",
+ },
+ },
+ mathstretch="h",
+ unicodeslot=0x2192,
+ },
+ [0x2193]={
+ adobename="arrowdown",
+ category="sm",
+ cjkwd="a",
+ description="DOWNWARDS ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="downarrow",
+ unicodeslot=0x2193,
+ },
+ [0x2194]={
+ adobename="arrowboth",
+ category="sm",
+ cjkwd="a",
+ description="LEFT RIGHT ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="leftrightarrow",
+ unicodeslot=0x2194,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2195]={
+ adobename="arrowupdn",
+ category="so",
+ cjkwd="a",
+ description="UP DOWN ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="v",
+ mathname="updownarrow",
+ unicodeslot=0x2195,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2196]={
+ adobename="arrowupleft",
+ category="so",
+ cjkwd="a",
+ description="NORTH WEST ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="nwarrow",
+ unicodeslot=0x2196,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2197]={
+ adobename="arrowupright",
+ category="so",
+ cjkwd="a",
+ description="NORTH EAST ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="nearrow",
+ unicodeslot=0x2197,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2198]={
+ adobename="arrowdownright",
+ category="so",
+ cjkwd="a",
+ description="SOUTH EAST ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="searrow",
+ unicodeslot=0x2198,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2199]={
+ adobename="arrowdownleft",
+ category="so",
+ cjkwd="a",
+ description="SOUTH WEST ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="swarrow",
+ unicodeslot=0x2199,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x219A]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="nleftarrow",
+ specials={ "char", 0x2190, 0x338 },
+ unicodeslot=0x219A,
+ },
+ [0x219B]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="nrightarrow",
+ specials={ "char", 0x2192, 0x338 },
+ unicodeslot=0x219B,
+ },
+ [0x219C]={
+ category="so",
+ description="LEFTWARDS WAVE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftwavearrow",
+ unicodeslot=0x219C,
+ },
+ [0x219D]={
+ category="so",
+ description="RIGHTWARDS WAVE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightwavearrow",
+ unicodeslot=0x219D,
+ },
+ [0x219E]={
+ category="so",
+ description="LEFTWARDS TWO HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathfiller="twoheadleftarrowfill",
+ mathname="twoheadleftarrow",
+ unicodeslot=0x219E,
+ },
+ [0x219F]={
+ category="so",
+ description="UPWARDS TWO HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="twoheaduparrow",
+ unicodeslot=0x219F,
+ },
+ [0x21A0]={
+ category="sm",
+ description="RIGHTWARDS TWO HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="twoheadrightarrowfill",
+ mathname="twoheadrightarrow",
+ unicodeslot=0x21A0,
+ },
+ [0x21A1]={
+ category="so",
+ description="DOWNWARDS TWO HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="twoheaddownarrow",
+ unicodeslot=0x21A1,
+ },
+ [0x21A2]={
+ category="so",
+ description="LEFTWARDS ARROW WITH TAIL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftarrowtail",
+ unicodeslot=0x21A2,
+ },
+ [0x21A3]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH TAIL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightarrowtail",
+ unicodeslot=0x21A3,
+ },
+ [0x21A4]={
+ category="so",
+ description="LEFTWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="mapsfrom",
+ unicodeslot=0x21A4,
+ },
+ [0x21A5]={
+ category="so",
+ description="UPWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="mapsup",
+ unicodeslot=0x21A5,
+ },
+ [0x21A6]={
+ category="sm",
+ description="RIGHTWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="mapstofill",
+ mathname="mapsto",
+ unicodeslot=0x21A6,
+ },
+ [0x21A7]={
+ category="so",
+ description="DOWNWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="mapsdown",
+ unicodeslot=0x21A7,
+ },
+ [0x21A8]={
+ adobename="arrowupdownbase",
+ category="so",
+ description="UP DOWN ARROW WITH BASE",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="v",
+ mathname="updownarrowbar",
+ unicodeslot=0x21A8,
+ },
+ [0x21A9]={
+ category="so",
+ description="LEFTWARDS ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathfiller="hookleftarrowfill",
+ mathname="hookleftarrow",
+ unicodeslot=0x21A9,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x21AA]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="hookrightarrowfill",
+ mathname="hookrightarrow",
+ unicodeslot=0x21AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x21AB]={
+ category="so",
+ description="LEFTWARDS ARROW WITH LOOP",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="looparrowleft",
+ unicodeslot=0x21AB,
+ },
+ [0x21AC]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH LOOP",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="looparrowright",
+ unicodeslot=0x21AC,
+ },
+ [0x21AD]={
+ category="so",
+ description="LEFT RIGHT WAVE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="leftrightsquigarrow",
+ unicodeslot=0x21AD,
+ },
+ [0x21AE]={
+ category="sm",
+ description="LEFT RIGHT ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="nleftrightarrow",
+ specials={ "char", 0x2194, 0x338 },
+ unicodeslot=0x21AE,
+ },
+ [0x21AF]={
+ category="so",
+ description="DOWNWARDS ZIGZAG ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="downzigzagarrow",
+ unicodeslot=0x21AF,
+ },
+ [0x21B0]={
+ category="so",
+ description="UPWARDS ARROW WITH TIP LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="Lsh",
+ unicodeslot=0x21B0,
+ },
+ [0x21B1]={
+ category="so",
+ description="UPWARDS ARROW WITH TIP RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="Rsh",
+ unicodeslot=0x21B1,
+ },
+ [0x21B2]={
+ category="so",
+ description="DOWNWARDS ARROW WITH TIP LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="Ldsh",
+ unicodeslot=0x21B2,
+ },
+ [0x21B3]={
+ category="so",
+ description="DOWNWARDS ARROW WITH TIP RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="Rdsh",
+ unicodeslot=0x21B3,
+ },
+ [0x21B4]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH CORNER DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="m",
+ mathname="linefeed",
+ unicodeslot=0x21B4,
+ },
+ [0x21B5]={
+ adobename="carriagereturn",
+ category="so",
+ contextname="carriagereturn",
+ description="DOWNWARDS ARROW WITH CORNER LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="m",
+ mathname="carriagereturn",
+ unicodeslot=0x21B5,
+ },
+ [0x21B6]={
+ category="so",
+ description="ANTICLOCKWISE TOP SEMICIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="curvearrowleft",
+ unicodeslot=0x21B6,
+ },
+ [0x21B7]={
+ category="so",
+ description="CLOCKWISE TOP SEMICIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="curvearrowright",
+ unicodeslot=0x21B7,
+ },
+ [0x21B8]={
+ category="so",
+ cjkwd="a",
+ description="NORTH WEST ARROW TO LONG BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="barovernorthwestarrow",
+ unicodeslot=0x21B8,
+ },
+ [0x21B9]={
+ category="so",
+ cjkwd="a",
+ description="LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="barleftarrowrightarrowbar",
+ unicodeslot=0x21B9,
+ },
+ [0x21BA]={
+ category="so",
+ description="ANTICLOCKWISE OPEN CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="circlearrowright",
+ },
+ {
+ class="relation",
+ name="acwopencirclearrow",
+ },
+ },
+ unicodeslot=0x21BA,
+ },
+ [0x21BB]={
+ category="so",
+ description="CLOCKWISE OPEN CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="circlearrowleft",
+ },
+ {
+ class="relation",
+ name="cwopencirclearrow",
+ },
+ },
+ unicodeslot=0x21BB,
+ },
+ [0x21BC]={
+ adobename="harpoonleftbarbup",
+ category="so",
+ description="LEFTWARDS HARPOON WITH BARB UPWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathfiller="leftharpoonupfill",
+ mathname="leftharpoonup",
+ unicodeslot=0x21BC,
+ },
+ [0x21BD]={
+ category="so",
+ description="LEFTWARDS HARPOON WITH BARB DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathfiller="leftharpoondownfill",
+ mathname="leftharpoondown",
+ unicodeslot=0x21BD,
+ },
+ [0x21BE]={
+ category="so",
+ description="UPWARDS HARPOON WITH BARB RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="upharpoonright",
+ },
+ {
+ class="relation",
+ name="restriction",
+ },
+ },
+ unicodeslot=0x21BE,
+ },
+ [0x21BF]={
+ category="so",
+ description="UPWARDS HARPOON WITH BARB LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="upharpoonleft",
+ unicodeslot=0x21BF,
+ },
+ [0x21C0]={
+ adobename="harpoonrightbarbup",
+ category="so",
+ description="RIGHTWARDS HARPOON WITH BARB UPWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="rightharpoonupfill",
+ mathname="rightharpoonup",
+ unicodeslot=0x21C0,
+ },
+ [0x21C1]={
+ category="so",
+ description="RIGHTWARDS HARPOON WITH BARB DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="rightharpoondownfill",
+ mathname="rightharpoondown",
+ unicodeslot=0x21C1,
+ },
+ [0x21C2]={
+ category="so",
+ description="DOWNWARDS HARPOON WITH BARB RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="downharpoonright",
+ unicodeslot=0x21C2,
+ },
+ [0x21C3]={
+ category="so",
+ description="DOWNWARDS HARPOON WITH BARB LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="downharpoonleft",
+ unicodeslot=0x21C3,
+ },
+ [0x21C4]={
+ adobename="arrowrightoverleft",
+ category="so",
+ description="RIGHTWARDS ARROW OVER LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="rightoverleftarrowfill",
+ mathname="rightleftarrows",
+ unicodeslot=0x21C4,
+ },
+ [0x21C5]={
+ adobename="arrowupleftofdown",
+ category="so",
+ description="UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="updownarrows",
+ unicodeslot=0x21C5,
+ },
+ [0x21C6]={
+ adobename="arrowleftoverright",
+ category="so",
+ description="LEFTWARDS ARROW OVER RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="lefgtoverrightarrowfill",
+ mathname="leftrightarrows",
+ unicodeslot=0x21C6,
+ },
+ [0x21C7]={
+ category="so",
+ description="LEFTWARDS PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftleftarrows",
+ unicodeslot=0x21C7,
+ },
+ [0x21C8]={
+ category="so",
+ description="UPWARDS PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="upuparrows",
+ unicodeslot=0x21C8,
+ },
+ [0x21C9]={
+ category="so",
+ description="RIGHTWARDS PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightrightarrows",
+ unicodeslot=0x21C9,
+ },
+ [0x21CA]={
+ category="so",
+ description="DOWNWARDS PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="downdownarrows",
+ unicodeslot=0x21CA,
+ },
+ [0x21CB]={
+ category="so",
+ description="LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="leftrightharpoonsfill",
+ mathname="leftrightharpoons",
+ unicodeslot=0x21CB,
+ },
+ [0x21CC]={
+ category="so",
+ description="RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="rightleftharpoonsfill",
+ mathname="rightleftharpoons",
+ unicodeslot=0x21CC,
+ },
+ [0x21CD]={
+ adobename="arrowleftdblstroke",
+ category="so",
+ description="LEFTWARDS DOUBLE ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="nLeftarrow",
+ specials={ "char", 0x21D0, 0x338 },
+ unicodeslot=0x21CD,
+ },
+ [0x21CE]={
+ category="sm",
+ description="LEFT RIGHT DOUBLE ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="nLeftrightarrow",
+ specials={ "char", 0x21D4, 0x338 },
+ unicodeslot=0x21CE,
+ },
+ [0x21CF]={
+ adobename="arrowrightdblstroke",
+ category="sm",
+ description="RIGHTWARDS DOUBLE ARROW WITH STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="nRightarrow",
+ specials={ "char", 0x21D2, 0x338 },
+ unicodeslot=0x21CF,
+ },
+ [0x21D0]={
+ adobename="arrowleftdbl",
+ category="so",
+ description="LEFTWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="Leftarrow",
+ unicodeslot=0x21D0,
+ },
+ [0x21D1]={
+ adobename="arrowdblup",
+ category="so",
+ description="UPWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="Uparrow",
+ unicodeslot=0x21D1,
+ },
+ [0x21D2]={
+ adobename="dblarrowright",
+ category="sm",
+ cjkwd="a",
+ description="RIGHTWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="ai",
+ mathextensible="r",
+ mathspec={
+ {
+ class="relation",
+ name="Rightarrow",
+ },
+ {
+ class="relation",
+ name="imply",
+ },
+ },
+ unicodeslot=0x21D2,
+ },
+ [0x21D3]={
+ adobename="arrowdbldown",
+ category="so",
+ description="DOWNWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="Downarrow",
+ unicodeslot=0x21D3,
+ },
+ [0x21D4]={
+ adobename="dblarrowleft",
+ category="sm",
+ cjkwd="a",
+ description="LEFT RIGHT DOUBLE ARROW",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="Leftrightarrow",
+ unicodeslot=0x21D4,
+ },
+ [0x21D5]={
+ category="so",
+ description="UP DOWN DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="v",
+ mathname="Updownarrow",
+ unicodeslot=0x21D5,
+ },
+ [0x21D6]={
+ category="so",
+ description="NORTH WEST DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Nwarrow",
+ unicodeslot=0x21D6,
+ },
+ [0x21D7]={
+ category="so",
+ description="NORTH EAST DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Nearrow",
+ unicodeslot=0x21D7,
+ },
+ [0x21D8]={
+ category="so",
+ description="SOUTH EAST DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Searrow",
+ unicodeslot=0x21D8,
+ },
+ [0x21D9]={
+ category="so",
+ description="SOUTH WEST DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Swarrow",
+ unicodeslot=0x21D9,
+ },
+ [0x21DA]={
+ category="so",
+ description="LEFTWARDS TRIPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="Lleftarrow",
+ unicodeslot=0x21DA,
+ },
+ [0x21DB]={
+ category="so",
+ description="RIGHTWARDS TRIPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="Rrightarrow",
+ unicodeslot=0x21DB,
+ },
+ [0x21DC]={
+ category="so",
+ description="LEFTWARDS SQUIGGLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftsquigarrow",
+ unicodeslot=0x21DC,
+ },
+ [0x21DD]={
+ category="so",
+ description="RIGHTWARDS SQUIGGLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="rightsquigarrow",
+ },
+ {
+ class="relation",
+ name="leadsto",
+ },
+ },
+ unicodeslot=0x21DD,
+ },
+ [0x21DE]={
+ adobename="pageup",
+ category="so",
+ description="UPWARDS ARROW WITH DOUBLE STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="nHuparrow",
+ unicodeslot=0x21DE,
+ },
+ [0x21DF]={
+ adobename="pagedown",
+ category="so",
+ description="DOWNWARDS ARROW WITH DOUBLE STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="nHdownarrow",
+ unicodeslot=0x21DF,
+ },
+ [0x21E0]={
+ adobename="arrowdashleft",
+ category="so",
+ description="LEFTWARDS DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftdasharrow",
+ unicodeslot=0x21E0,
+ },
+ [0x21E1]={
+ adobename="arrowdashup",
+ category="so",
+ description="UPWARDS DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="updasharrow",
+ unicodeslot=0x21E1,
+ },
+ [0x21E2]={
+ adobename="arrowdashright",
+ category="so",
+ description="RIGHTWARDS DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="rightdasharrow",
+ },
+ {
+ class="relation",
+ name="dasharrow",
+ },
+ },
+ unicodeslot=0x21E2,
+ },
+ [0x21E3]={
+ adobename="arrowdashdown",
+ category="so",
+ description="DOWNWARDS DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="downdasharrow",
+ unicodeslot=0x21E3,
+ },
+ [0x21E4]={
+ adobename="arrowtableft",
+ category="so",
+ description="LEFTWARDS ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="barleftarrow",
+ unicodeslot=0x21E4,
+ },
+ [0x21E5]={
+ adobename="arrowtabright",
+ category="so",
+ description="RIGHTWARDS ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightarrowbar",
+ unicodeslot=0x21E5,
+ },
+ [0x21E6]={
+ adobename="arrowleftwhite",
+ category="so",
+ description="LEFTWARDS WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="l",
+ mathname="leftwhitearrow",
+ unicodeslot=0x21E6,
+ },
+ [0x21E7]={
+ adobename="arrowupwhite",
+ category="so",
+ cjkwd="a",
+ description="UPWARDS WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="u",
+ mathname="upwhitearrow",
+ unicodeslot=0x21E7,
+ },
+ [0x21E8]={
+ adobename="arrowrightwhite",
+ category="so",
+ description="RIGHTWARDS WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="r",
+ mathname="rightwhitearrow",
+ unicodeslot=0x21E8,
+ },
+ [0x21E9]={
+ adobename="arrowdownwhite",
+ category="so",
+ description="DOWNWARDS WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="d",
+ mathname="downwhitearrow",
+ unicodeslot=0x21E9,
+ },
+ [0x21EA]={
+ adobename="capslock",
+ category="so",
+ description="UPWARDS WHITE ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21EA,
+ },
+ [0x21EB]={
+ category="so",
+ description="UPWARDS WHITE ARROW ON PEDESTAL",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathextensible="u",
+ mathname="whitearrowupfrombar",
+ unicodeslot=0x21EB,
+ },
+ [0x21EC]={
+ category="so",
+ description="UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21EC,
+ },
+ [0x21ED]={
+ category="so",
+ description="UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21ED,
+ },
+ [0x21EE]={
+ category="so",
+ description="UPWARDS WHITE DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21EE,
+ },
+ [0x21EF]={
+ category="so",
+ description="UPWARDS WHITE DOUBLE ARROW ON PEDESTAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21EF,
+ },
+ [0x21F0]={
+ category="so",
+ description="RIGHTWARDS WHITE ARROW FROM WALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21F0,
+ },
+ [0x21F1]={
+ category="so",
+ description="NORTH WEST ARROW TO CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21F1,
+ },
+ [0x21F2]={
+ category="so",
+ description="SOUTH EAST ARROW TO CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21F2,
+ },
+ [0x21F3]={
+ category="so",
+ description="UP DOWN WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x21F3,
+ },
+ [0x21F4]={
+ category="sm",
+ description="RIGHT ARROW WITH SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="circleonrightarrow",
+ unicodeslot=0x21F4,
+ },
+ [0x21F5]={
+ category="sm",
+ description="DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="m",
+ mathname="downuparrows",
+ unicodeslot=0x21F5,
+ },
+ [0x21F6]={
+ category="sm",
+ description="THREE RIGHTWARDS ARROWS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightthreearrows",
+ unicodeslot=0x21F6,
+ },
+ [0x21F7]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="nvleftarrow",
+ unicodeslot=0x21F7,
+ },
+ [0x21F8]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="nvrightarrow",
+ unicodeslot=0x21F8,
+ },
+ [0x21F9]={
+ category="sm",
+ description="LEFT RIGHT ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="nvleftrightarrow",
+ unicodeslot=0x21F9,
+ },
+ [0x21FA]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="nVleftarrow",
+ unicodeslot=0x21FA,
+ },
+ [0x21FB]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="nVrightarrow",
+ unicodeslot=0x21FB,
+ },
+ [0x21FC]={
+ category="sm",
+ description="LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="nVleftrightarrow",
+ unicodeslot=0x21FC,
+ },
+ [0x21FD]={
+ category="sm",
+ description="LEFTWARDS OPEN-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="leftarrowtriangle",
+ unicodeslot=0x21FD,
+ },
+ [0x21FE]={
+ category="sm",
+ description="RIGHTWARDS OPEN-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="rightarrowtriangle",
+ unicodeslot=0x21FE,
+ },
+ [0x21FF]={
+ category="sm",
+ description="LEFT RIGHT OPEN-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="leftrightarrowtriangle",
+ unicodeslot=0x21FF,
+ },
+ [0x2200]={
+ adobename="universal",
+ category="sm",
+ cjkwd="a",
+ description="FOR ALL",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="forall",
+ unicodeslot=0x2200,
+ },
+ [0x2201]={
+ category="sm",
+ description="COMPLEMENT",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="complement",
+ unicodeslot=0x2201,
+ },
+ [0x2202]={
+ adobename="partialdiff",
+ category="sm",
+ cjkwd="a",
+ description="PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="partial",
+ unicodeslot=0x2202,
+ },
+ [0x2203]={
+ adobename="thereexists",
+ category="sm",
+ cjkwd="a",
+ description="THERE EXISTS",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="exists",
+ unicodeslot=0x2203,
+ },
+ [0x2204]={
+ category="sm",
+ description="THERE DOES NOT EXIST",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="nexists",
+ specials={ "char", 0x2203, 0x338 },
+ unicodeslot=0x2204,
+ },
+ [0x2205]={
+ adobename="emptyset",
+ category="sm",
+ description="EMPTY SET",
+ direction="on",
+ linebreak="al",
+ mathclass="default",
+ mathname="emptyset",
+ unicodeslot=0x2205,
+ },
+ [0x2206]={
+ adobename="increment",
+ category="sm",
+ description="INCREMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2206,
+ },
+ [0x2207]={
+ adobename="nabla",
+ category="sm",
+ cjkwd="a",
+ description="NABLA",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="nabla",
+ unicodeslot=0x2207,
+ },
+ [0x2208]={
+ adobename="element",
+ category="sm",
+ cjkwd="a",
+ description="ELEMENT OF",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="in",
+ mirror=0x220B,
+ unicodeslot=0x2208,
+ },
+ [0x2209]={
+ adobename="notelementof",
+ category="sm",
+ description="NOT AN ELEMENT OF",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="notin",
+ },
+ {
+ class="relation",
+ name="nin",
+ },
+ },
+ mirror=0x220C,
+ specials={ "char", 0x2208, 0x338 },
+ unicodeslot=0x2209,
+ },
+ [0x220A]={
+ category="sm",
+ description="SMALL ELEMENT OF",
+ direction="on",
+ linebreak="al",
+ mirror=0x220D,
+ unicodeslot=0x220A,
+ },
+ [0x220B]={
+ adobename="suchthat",
+ category="sm",
+ cjkwd="a",
+ description="CONTAINS AS MEMBER",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="relation",
+ name="ni",
+ },
+ {
+ class="relation",
+ name="owns",
+ },
+ },
+ mirror=0x2208,
+ unicodeslot=0x220B,
+ },
+ [0x220C]={
+ adobename="notcontains",
+ category="sm",
+ description="DOES NOT CONTAIN AS MEMBER",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="nni",
+ },
+ {
+ class="relation",
+ name="nowns",
+ },
+ },
+ mirror=0x2209,
+ specials={ "char", 0x220B, 0x338 },
+ unicodeslot=0x220C,
+ },
+ [0x220D]={
+ category="sm",
+ description="SMALL CONTAINS AS MEMBER",
+ direction="on",
+ linebreak="al",
+ mirror=0x220A,
+ unicodeslot=0x220D,
+ },
+ [0x220E]={
+ category="sm",
+ description="END OF PROOF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x220E,
+ },
+ [0x220F]={
+ adobename="product",
+ category="sm",
+ cjkwd="a",
+ description="N-ARY PRODUCT",
+ direction="on",
+ linebreak="ai",
+ mathclass="limop",
+ mathname="prod",
+ unicodeslot=0x220F,
+ },
+ [0x2210]={
+ category="sm",
+ description="N-ARY COPRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="coprod",
+ unicodeslot=0x2210,
+ },
+ [0x2211]={
+ adobename="summation",
+ category="sm",
+ cjkwd="a",
+ description="N-ARY SUMMATION",
+ direction="on",
+ linebreak="ai",
+ mathclass="limop",
+ mathname="sum",
+ unicodeslot=0x2211,
+ },
+ [0x2212]={
+ adobename="minus",
+ category="sm",
+ description="MINUS SIGN",
+ direction="es",
+ linebreak="pr",
+ mathspec={
+ {
+ class="binary",
+ name="minus",
+ },
+ {
+ class="relation",
+ name="relbar",
+ },
+ },
+ unicodeslot=0x2212,
+ },
+ [0x2213]={
+ adobename="minusplus",
+ category="sm",
+ description="MINUS-OR-PLUS SIGN",
+ direction="et",
+ linebreak="pr",
+ mathclass="binary",
+ mathname="mp",
+ unicodeslot=0x2213,
+ },
+ [0x2214]={
+ category="sm",
+ description="DOT PLUS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="dotplus",
+ unicodeslot=0x2214,
+ },
+ [0x2215]={
+ adobename="divisionslash",
+ category="sm",
+ cjkwd="a",
+ comment="mathclass=ordinary,mathname=diagup",
+ description="DIVISION SLASH",
+ direction="on",
+ linebreak="ai",
+ mirror=0x29F5,
+ unicodeslot=0x2215,
+ },
+ [0x2216]={
+ category="sm",
+ comment="mathclass=ordinary,mathname=diagdown",
+ description="SET MINUS",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="binary",
+ name="setminus",
+ },
+ },
+ unicodeslot=0x2216,
+ },
+ [0x2217]={
+ adobename="asteriskmath",
+ category="sm",
+ description="ASTERISK OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="ast",
+ unicodeslot=0x2217,
+ },
+ [0x2218]={
+ category="sm",
+ description="RING OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="circ",
+ unicodeslot=0x2218,
+ },
+ [0x2219]={
+ adobename="bulletoperator",
+ category="sm",
+ description="BULLET OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="bullet",
+ unicodeslot=0x2219,
+ },
+ [0x221A]={
+ adobename="radical",
+ category="sm",
+ cjkwd="a",
+ description="SQUARE ROOT",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="root",
+ name="rootradical",
+ },
+ {
+ class="radical",
+ name="surdradical",
+ },
+ {
+ class="ordinary",
+ name="surd",
+ },
+ },
+ unicodeslot=0x221A,
+ },
+ [0x221B]={
+ category="sm",
+ description="CUBE ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x221B,
+ },
+ [0x221C]={
+ category="sm",
+ description="FOURTH ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x221C,
+ },
+ [0x221D]={
+ adobename="proportional",
+ category="sm",
+ cjkwd="a",
+ description="PROPORTIONAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="propto",
+ unicodeslot=0x221D,
+ },
+ [0x221E]={
+ adobename="infinity",
+ category="sm",
+ cjkwd="a",
+ description="INFINITY",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="infty",
+ unicodeslot=0x221E,
+ },
+ [0x221F]={
+ adobename="rightangle",
+ category="sm",
+ cjkwd="a",
+ description="RIGHT ANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="rightangle",
+ unicodeslot=0x221F,
+ },
+ [0x2220]={
+ adobename="angle",
+ category="sm",
+ cjkwd="a",
+ description="ANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="angle",
+ unicodeslot=0x2220,
+ },
+ [0x2221]={
+ category="sm",
+ description="MEASURED ANGLE",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="measuredangle",
+ unicodeslot=0x2221,
+ },
+ [0x2222]={
+ category="sm",
+ description="SPHERICAL ANGLE",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="sphericalangle",
+ unicodeslot=0x2222,
+ },
+ [0x2223]={
+ adobename="divides",
+ category="sm",
+ cjkwd="a",
+ description="DIVIDES",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="divides",
+ unicodeslot=0x2223,
+ },
+ [0x2224]={
+ category="sm",
+ description="DOES NOT DIVIDE",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="binary",
+ name="ndivides",
+ },
+ {
+ class="relation",
+ name="nmid",
+ },
+ },
+ specials={ "char", 0x2223, 0x338 },
+ unicodeslot=0x2224,
+ },
+ [0x2225]={
+ adobename="parallel",
+ category="sm",
+ cjkwd="a",
+ description="PARALLEL TO",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="relation",
+ name="parallel",
+ },
+ },
+ unicodeslot=0x2225,
+ },
+ [0x2226]={
+ adobename="notparallel",
+ category="sm",
+ description="NOT PARALLEL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nparallel",
+ specials={ "char", 0x2225, 0x338 },
+ unicodeslot=0x2226,
+ },
+ [0x2227]={
+ adobename="logicaland",
+ category="sm",
+ cjkwd="a",
+ description="LOGICAL AND",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="binary",
+ name="wedge",
+ },
+ {
+ class="binary",
+ name="land",
+ },
+ },
+ unicodeslot=0x2227,
+ },
+ [0x2228]={
+ adobename="logicalor",
+ category="sm",
+ cjkwd="a",
+ description="LOGICAL OR",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="binary",
+ name="vee",
+ },
+ {
+ class="binary",
+ name="lor",
+ },
+ },
+ unicodeslot=0x2228,
+ },
+ [0x2229]={
+ adobename="intersection",
+ category="sm",
+ cjkwd="a",
+ description="INTERSECTION",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="cap",
+ unicodeslot=0x2229,
+ variants={
+ [0xFE00]="with serifs",
+ },
+ },
+ [0x222A]={
+ adobename="union",
+ category="sm",
+ cjkwd="a",
+ description="UNION",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="cup",
+ unicodeslot=0x222A,
+ variants={
+ [0xFE00]="with serifs",
+ },
+ },
+ [0x222B]={
+ adobename="integral",
+ category="sm",
+ cjkwd="a",
+ description="INTEGRAL",
+ direction="on",
+ linebreak="ai",
+ mathclass="limop",
+ mathspec={
+ {
+ class="limop",
+ name="int",
+ },
+ {
+ class="nothing",
+ name="intop",
+ },
+ },
+ unicodeslot=0x222B,
+ },
+ [0x222C]={
+ adobename="dblintegral",
+ category="sm",
+ cjkwd="a",
+ description="DOUBLE INTEGRAL",
+ direction="on",
+ linebreak="ai",
+ mathclass="limop",
+ mathspec={
+ {
+ class="limop",
+ name="iint",
+ },
+ {
+ class="nothing",
+ name="iintop",
+ },
+ },
+ specials={ "compat", 0x222B, 0x222B },
+ unicodeslot=0x222C,
+ },
+ [0x222D]={
+ category="sm",
+ description="TRIPLE INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathspec={
+ {
+ class="limop",
+ name="iiint",
+ },
+ {
+ class="nothing",
+ name="iiintop",
+ },
+ },
+ specials={ "compat", 0x222B, 0x222B, 0x222B },
+ unicodeslot=0x222D,
+ },
+ [0x222E]={
+ adobename="contourintegral",
+ category="sm",
+ cjkwd="a",
+ description="CONTOUR INTEGRAL",
+ direction="on",
+ linebreak="ai",
+ mathclass="limop",
+ mathname="oint",
+ unicodeslot=0x222E,
+ },
+ [0x222F]={
+ category="sm",
+ description="SURFACE INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="oiint",
+ specials={ "compat", 0x222E, 0x222E },
+ unicodeslot=0x222F,
+ },
+ [0x2230]={
+ category="sm",
+ description="VOLUME INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="oiiint",
+ specials={ "compat", 0x222E, 0x222E, 0x222E },
+ unicodeslot=0x2230,
+ },
+ [0x2231]={
+ category="sm",
+ description="CLOCKWISE INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="intclockwise",
+ unicodeslot=0x2231,
+ },
+ [0x2232]={
+ category="sm",
+ description="CLOCKWISE CONTOUR INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="ointclockwise",
+ unicodeslot=0x2232,
+ },
+ [0x2233]={
+ category="sm",
+ description="ANTICLOCKWISE CONTOUR INTEGRAL",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="ointctrclockwise",
+ unicodeslot=0x2233,
+ },
+ [0x2234]={
+ adobename="therefore",
+ category="sm",
+ cjkwd="a",
+ description="THEREFORE",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="therefore",
+ unicodeslot=0x2234,
+ },
+ [0x2235]={
+ adobename="because",
+ category="sm",
+ cjkwd="a",
+ description="BECAUSE",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="because",
+ unicodeslot=0x2235,
+ },
+ [0x2236]={
+ adobename="ratio",
+ category="sm",
+ cjkwd="a",
+ description="RATIO",
+ direction="on",
+ linebreak="ai",
+ mathclass="punctuation",
+ mathname="colon",
+ unicodeslot=0x2236,
+ },
+ [0x2237]={
+ adobename="proportion",
+ category="sm",
+ cjkwd="a",
+ description="PROPORTION",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="squaredots",
+ unicodeslot=0x2237,
+ },
+ [0x2238]={
+ category="sm",
+ description="DOT MINUS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="dotminus",
+ unicodeslot=0x2238,
+ },
+ [0x2239]={
+ category="sm",
+ description="EXCESS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="minuscolon",
+ unicodeslot=0x2239,
+ },
+ [0x223A]={
+ category="sm",
+ description="GEOMETRIC PROPORTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x223A,
+ },
+ [0x223B]={
+ category="sm",
+ description="HOMOTHETIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x223B,
+ },
+ [0x223C]={
+ adobename="tildeoperator",
+ category="sm",
+ cjkwd="a",
+ description="TILDE OPERATOR",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="sim",
+ mirror=0x223D,
+ unicodeslot=0x223C,
+ },
+ [0x223D]={
+ adobename="reversedtilde",
+ category="sm",
+ cjkwd="a",
+ description="REVERSED TILDE",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="backsim",
+ mirror=0x223C,
+ unicodeslot=0x223D,
+ },
+ [0x223E]={
+ category="sm",
+ description="INVERTED LAZY S",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x223E,
+ },
+ [0x223F]={
+ category="sm",
+ description="SINE WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x223F,
+ },
+ [0x2240]={
+ category="sm",
+ description="WREATH PRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="wr",
+ unicodeslot=0x2240,
+ },
+ [0x2241]={
+ category="sm",
+ description="NOT TILDE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsim",
+ specials={ "char", 0x223C, 0x338 },
+ unicodeslot=0x2241,
+ },
+ [0x2242]={
+ category="sm",
+ description="MINUS TILDE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqsim",
+ unicodeslot=0x2242,
+ },
+ [0x2243]={
+ adobename="asymptoticallyequal",
+ category="sm",
+ description="ASYMPTOTICALLY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="simeq",
+ mirror=0x22CD,
+ unicodeslot=0x2243,
+ },
+ [0x2244]={
+ category="sm",
+ description="NOT ASYMPTOTICALLY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsimeq",
+ specials={ "char", 0x2243, 0x338 },
+ unicodeslot=0x2244,
+ },
+ [0x2245]={
+ adobename="congruent",
+ category="sm",
+ description="APPROXIMATELY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="approxEq",
+ },
+ {
+ class="relation",
+ name="cong",
+ },
+ },
+ unicodeslot=0x2245,
+ },
+ [0x2246]={
+ category="sm",
+ description="APPROXIMATELY BUT NOT ACTUALLY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="napproxEq",
+ },
+ {
+ class="relation",
+ name="ncong",
+ },
+ },
+ unicodeslot=0x2246,
+ },
+ [0x2247]={
+ category="sm",
+ description="NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="approxnEq",
+ specials={ "char", 0x2245, 0x338 },
+ unicodeslot=0x2247,
+ },
+ [0x2248]={
+ adobename="approxequal",
+ category="sm",
+ cjkwd="a",
+ description="ALMOST EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="approx",
+ unicodeslot=0x2248,
+ },
+ [0x2249]={
+ category="sm",
+ description="NOT ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="napprox",
+ specials={ "char", 0x2248, 0x338 },
+ unicodeslot=0x2249,
+ },
+ [0x224A]={
+ category="sm",
+ description="ALMOST EQUAL OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="approxeq",
+ unicodeslot=0x224A,
+ },
+ [0x224B]={
+ category="sm",
+ description="TRIPLE TILDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x224B,
+ },
+ [0x224C]={
+ adobename="allequal",
+ category="sm",
+ cjkwd="a",
+ description="ALL EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ unicodeslot=0x224C,
+ },
+ [0x224D]={
+ category="sm",
+ description="EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="asymp",
+ unicodeslot=0x224D,
+ },
+ [0x224E]={
+ category="sm",
+ description="GEOMETRICALLY EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Bumpeq",
+ unicodeslot=0x224E,
+ },
+ [0x224F]={
+ category="sm",
+ description="DIFFERENCE BETWEEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x224F,
+ },
+ [0x2250]={
+ adobename="approaches",
+ category="sm",
+ description="APPROACHES THE LIMIT",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="doteq",
+ unicodeslot=0x2250,
+ },
+ [0x2251]={
+ adobename="geometricallyequal",
+ category="sm",
+ description="GEOMETRICALLY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="doteqdot",
+ },
+ {
+ class="relation",
+ name="Doteq",
+ },
+ },
+ unicodeslot=0x2251,
+ },
+ [0x2252]={
+ adobename="approxequalorimage",
+ category="sm",
+ cjkwd="a",
+ description="APPROXIMATELY EQUAL TO OR THE IMAGE OF",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="fallingdotseq",
+ mirror=0x2253,
+ unicodeslot=0x2252,
+ },
+ [0x2253]={
+ adobename="imageorapproximatelyequal",
+ category="sm",
+ description="IMAGE OF OR APPROXIMATELY EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="risingdotseq",
+ mirror=0x2252,
+ unicodeslot=0x2253,
+ },
+ [0x2254]={
+ category="sm",
+ description="COLON EQUALS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="colonequals",
+ mathpair={ 0x3A, 0x3D },
+ mirror=0x2255,
+ unicodeslot=0x2254,
+ },
+ [0x2255]={
+ category="sm",
+ description="EQUALS COLON",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="equalscolon",
+ mathpair={ 0x3D, 0x3A },
+ mirror=0x2254,
+ unicodeslot=0x2255,
+ },
+ [0x2256]={
+ category="sm",
+ description="RING IN EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqcirc",
+ unicodeslot=0x2256,
+ },
+ [0x2257]={
+ category="sm",
+ description="RING EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="circeq",
+ unicodeslot=0x2257,
+ },
+ [0x2258]={
+ category="sm",
+ description="CORRESPONDS TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2258,
+ },
+ [0x2259]={
+ category="sm",
+ description="ESTIMATES",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="wedgeeq",
+ unicodeslot=0x2259,
+ },
+ [0x225A]={
+ category="sm",
+ description="EQUIANGULAR TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="veeeq",
+ unicodeslot=0x225A,
+ },
+ [0x225B]={
+ category="sm",
+ description="STAR EQUALS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="stareq",
+ unicodeslot=0x225B,
+ },
+ [0x225C]={
+ category="sm",
+ description="DELTA EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="triangleq",
+ unicodeslot=0x225C,
+ },
+ [0x225D]={
+ category="sm",
+ description="EQUAL TO BY DEFINITION",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="definedeq",
+ unicodeslot=0x225D,
+ },
+ [0x225E]={
+ category="sm",
+ description="MEASURED BY",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="measuredeq",
+ unicodeslot=0x225E,
+ },
+ [0x225F]={
+ category="sm",
+ description="QUESTIONED EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="questionedeq",
+ unicodeslot=0x225F,
+ },
+ [0x2260]={
+ adobename="notequal",
+ category="sm",
+ cjkwd="a",
+ description="NOT EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="relation",
+ name="neq",
+ },
+ {
+ class="relation",
+ name="ne",
+ },
+ },
+ specials={ "char", 0x3D, 0x338 },
+ unicodeslot=0x2260,
+ },
+ [0x2261]={
+ adobename="equivalence",
+ category="sm",
+ cjkwd="a",
+ description="IDENTICAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathextensible="h",
+ mathname="equiv",
+ unicodeslot=0x2261,
+ },
+ [0x2262]={
+ adobename="notidentical",
+ category="sm",
+ description="NOT IDENTICAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="triplerelfill",
+ mathname="nequiv",
+ specials={ "char", 0x2261, 0x338 },
+ unicodeslot=0x2262,
+ },
+ [0x2263]={
+ category="sm",
+ description="STRICTLY EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ unicodeslot=0x2263,
+ },
+ [0x2264]={
+ adobename="lessequal",
+ category="sm",
+ cjkwd="a",
+ description="LESS-THAN OR EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathpair={ 0x3C, 0x3D },
+ mathspec={
+ {
+ class="relation",
+ name="leq",
+ },
+ {
+ class="relation",
+ name="le",
+ },
+ },
+ mirror=0x2265,
+ unicodeslot=0x2264,
+ },
+ [0x2265]={
+ adobename="greaterequal",
+ category="sm",
+ cjkwd="a",
+ description="GREATER-THAN OR EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathpair={ 0x3E, 0x3D },
+ mathspec={
+ {
+ class="relation",
+ name="geq",
+ },
+ {
+ class="relation",
+ name="ge",
+ },
+ },
+ mirror=0x2264,
+ unicodeslot=0x2265,
+ },
+ [0x2266]={
+ adobename="lessoverequal",
+ category="sm",
+ cjkwd="a",
+ description="LESS-THAN OVER EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="leqq",
+ mirror=0x2267,
+ unicodeslot=0x2266,
+ },
+ [0x2267]={
+ adobename="greateroverequal",
+ category="sm",
+ cjkwd="a",
+ description="GREATER-THAN OVER EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="geqq",
+ mirror=0x2266,
+ unicodeslot=0x2267,
+ },
+ [0x2268]={
+ category="sm",
+ description="LESS-THAN BUT NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lneqq",
+ mirror=0x2269,
+ unicodeslot=0x2268,
+ variants={
+ [0xFE00]="with vertical stroke",
+ },
+ },
+ [0x2269]={
+ category="sm",
+ description="GREATER-THAN BUT NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gneqq",
+ mirror=0x2268,
+ unicodeslot=0x2269,
+ variants={
+ [0xFE00]="with vertical stroke",
+ },
+ },
+ [0x226A]={
+ adobename="muchless",
+ category="sm",
+ cjkwd="a",
+ description="MUCH LESS-THAN",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="ll",
+ mirror=0x226B,
+ unicodeslot=0x226A,
+ },
+ [0x226B]={
+ adobename="muchgreater",
+ category="sm",
+ cjkwd="a",
+ description="MUCH GREATER-THAN",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="gg",
+ mirror=0x226A,
+ unicodeslot=0x226B,
+ },
+ [0x226C]={
+ category="sm",
+ description="BETWEEN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="between",
+ unicodeslot=0x226C,
+ },
+ [0x226D]={
+ category="sm",
+ description="NOT EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nasymp",
+ specials={ "char", 0x224D, 0x338 },
+ unicodeslot=0x226D,
+ },
+ [0x226E]={
+ adobename="notless",
+ category="sm",
+ cjkwd="a",
+ description="NOT LESS-THAN",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="nless",
+ mirror=0x226F,
+ specials={ "char", 0x3C, 0x338 },
+ unicodeslot=0x226E,
+ },
+ [0x226F]={
+ adobename="notgreater",
+ category="sm",
+ cjkwd="a",
+ description="NOT GREATER-THAN",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="ngtr",
+ mirror=0x226E,
+ specials={ "char", 0x3E, 0x338 },
+ unicodeslot=0x226F,
+ },
+ [0x2270]={
+ adobename="notlessnorequal",
+ category="sm",
+ description="NEITHER LESS-THAN NOR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nleq",
+ mirror=0x2271,
+ specials={ "char", 0x2264, 0x338 },
+ unicodeslot=0x2270,
+ },
+ [0x2271]={
+ adobename="notgreaternorequal",
+ category="sm",
+ description="NEITHER GREATER-THAN NOR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ngeq",
+ mirror=0x2270,
+ specials={ "char", 0x2265, 0x338 },
+ unicodeslot=0x2271,
+ },
+ [0x2272]={
+ adobename="lessorequivalent",
+ category="sm",
+ description="LESS-THAN OR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lesssim",
+ mirror=0x2273,
+ unicodeslot=0x2272,
+ variants={
+ [0xFE00]="following the slant of the lower leg",
+ },
+ },
+ [0x2273]={
+ adobename="greaterorequivalent",
+ category="sm",
+ description="GREATER-THAN OR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gtrsim",
+ mirror=0x2272,
+ unicodeslot=0x2273,
+ variants={
+ [0xFE00]="following the slant of the lower leg",
+ },
+ },
+ [0x2274]={
+ category="sm",
+ description="NEITHER LESS-THAN NOR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nlesssim",
+ mirror=0x2275,
+ specials={ "char", 0x2272, 0x338 },
+ unicodeslot=0x2274,
+ },
+ [0x2275]={
+ category="sm",
+ description="NEITHER GREATER-THAN NOR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ngtrsim",
+ mirror=0x2274,
+ specials={ "char", 0x2273, 0x338 },
+ unicodeslot=0x2275,
+ },
+ [0x2276]={
+ adobename="lessorgreater",
+ category="sm",
+ description="LESS-THAN OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lessgtr",
+ mirror=0x2277,
+ unicodeslot=0x2276,
+ },
+ [0x2277]={
+ adobename="greaterorless",
+ category="sm",
+ description="GREATER-THAN OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gtrless",
+ mirror=0x2276,
+ unicodeslot=0x2277,
+ },
+ [0x2278]={
+ category="sm",
+ description="NEITHER LESS-THAN NOR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nlessgtr",
+ mirror=0x2279,
+ specials={ "char", 0x2276, 0x338 },
+ unicodeslot=0x2278,
+ },
+ [0x2279]={
+ adobename="notgreaternorless",
+ category="sm",
+ description="NEITHER GREATER-THAN NOR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ngtrless",
+ mirror=0x2278,
+ specials={ "char", 0x2277, 0x338 },
+ unicodeslot=0x2279,
+ },
+ [0x227A]={
+ adobename="precedes",
+ category="sm",
+ description="PRECEDES",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="prec",
+ mirror=0x227B,
+ unicodeslot=0x227A,
+ },
+ [0x227B]={
+ adobename="succeeds",
+ category="sm",
+ description="SUCCEEDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succ",
+ mirror=0x227A,
+ unicodeslot=0x227B,
+ },
+ [0x227C]={
+ category="sm",
+ description="PRECEDES OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="preccurlyeq",
+ mirror=0x227D,
+ unicodeslot=0x227C,
+ },
+ [0x227D]={
+ category="sm",
+ description="SUCCEEDS OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succcurlyeq",
+ mirror=0x227C,
+ unicodeslot=0x227D,
+ },
+ [0x227E]={
+ category="sm",
+ description="PRECEDES OR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precsim",
+ mirror=0x227F,
+ unicodeslot=0x227E,
+ },
+ [0x227F]={
+ category="sm",
+ description="SUCCEEDS OR EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succsim",
+ mirror=0x227E,
+ unicodeslot=0x227F,
+ },
+ [0x2280]={
+ adobename="notprecedes",
+ category="sm",
+ description="DOES NOT PRECEDE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nprec",
+ mirror=0x2281,
+ specials={ "char", 0x227A, 0x338 },
+ unicodeslot=0x2280,
+ },
+ [0x2281]={
+ adobename="notsucceeds",
+ category="sm",
+ description="DOES NOT SUCCEED",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsucc",
+ mirror=0x2280,
+ specials={ "char", 0x227B, 0x338 },
+ unicodeslot=0x2281,
+ },
+ [0x2282]={
+ adobename="subset",
+ category="sm",
+ cjkwd="a",
+ description="SUBSET OF",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="subset",
+ mirror=0x2283,
+ unicodeslot=0x2282,
+ },
+ [0x2283]={
+ adobename="superset",
+ category="sm",
+ cjkwd="a",
+ description="SUPERSET OF",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="supset",
+ mirror=0x2282,
+ unicodeslot=0x2283,
+ },
+ [0x2284]={
+ adobename="notsubset",
+ category="sm",
+ description="NOT A SUBSET OF",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsubset",
+ mirror=0x2285,
+ specials={ "char", 0x2282, 0x338 },
+ unicodeslot=0x2284,
+ },
+ [0x2285]={
+ adobename="notsuperset",
+ category="sm",
+ description="NOT A SUPERSET OF",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsupset",
+ mirror=0x2284,
+ specials={ "char", 0x2283, 0x338 },
+ unicodeslot=0x2285,
+ },
+ [0x2286]={
+ adobename="subsetorequal",
+ category="sm",
+ cjkwd="a",
+ description="SUBSET OF OR EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="subseteq",
+ mirror=0x2287,
+ unicodeslot=0x2286,
+ },
+ [0x2287]={
+ adobename="supersetorequal",
+ category="sm",
+ cjkwd="a",
+ description="SUPERSET OF OR EQUAL TO",
+ direction="on",
+ linebreak="ai",
+ mathclass="relation",
+ mathname="supseteq",
+ mirror=0x2286,
+ unicodeslot=0x2287,
+ },
+ [0x2288]={
+ category="sm",
+ description="NEITHER A SUBSET OF NOR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsubseteq",
+ mirror=0x2289,
+ specials={ "char", 0x2286, 0x338 },
+ unicodeslot=0x2288,
+ },
+ [0x2289]={
+ category="sm",
+ description="NEITHER A SUPERSET OF NOR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsupseteq",
+ mirror=0x2288,
+ specials={ "char", 0x2287, 0x338 },
+ unicodeslot=0x2289,
+ },
+ [0x228A]={
+ adobename="subsetnotequal",
+ category="sm",
+ description="SUBSET OF WITH NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="subsetneq",
+ mirror=0x228B,
+ unicodeslot=0x228A,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
+ },
+ [0x228B]={
+ adobename="supersetnotequal",
+ category="sm",
+ description="SUPERSET OF WITH NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="supsetneq",
+ mirror=0x228A,
+ unicodeslot=0x228B,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
+ },
+ [0x228C]={
+ category="sm",
+ description="MULTISET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x228C,
+ },
+ [0x228D]={
+ category="sm",
+ description="MULTISET MULTIPLICATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x228D,
+ },
+ [0x228E]={
+ category="sm",
+ description="MULTISET UNION",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="uplus",
+ unicodeslot=0x228E,
+ },
+ [0x228F]={
+ category="sm",
+ description="SQUARE IMAGE OF",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="sqsubset",
+ mirror=0x2290,
+ unicodeslot=0x228F,
+ },
+ [0x2290]={
+ category="sm",
+ description="SQUARE ORIGINAL OF",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="sqsupset",
+ mirror=0x228F,
+ unicodeslot=0x2290,
+ },
+ [0x2291]={
+ category="sm",
+ description="SQUARE IMAGE OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="sqsubseteq",
+ mirror=0x2292,
+ unicodeslot=0x2291,
+ },
+ [0x2292]={
+ category="sm",
+ description="SQUARE ORIGINAL OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="sqsupseteq",
+ mirror=0x2291,
+ unicodeslot=0x2292,
+ },
+ [0x2293]={
+ category="sm",
+ description="SQUARE CAP",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="sqcap",
+ unicodeslot=0x2293,
+ variants={
+ [0xFE00]="with serifs",
+ },
+ },
+ [0x2294]={
+ category="sm",
+ description="SQUARE CUP",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="sqcup",
+ unicodeslot=0x2294,
+ variants={
+ [0xFE00]="with serifs",
+ },
+ },
+ [0x2295]={
+ adobename="pluscircle",
+ category="sm",
+ cjkwd="a",
+ description="CIRCLED PLUS",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="oplus",
+ unicodeslot=0x2295,
+ variants={
+ [0xFE00]="with white rim",
+ },
+ },
+ [0x2296]={
+ adobename="minuscircle",
+ category="sm",
+ description="CIRCLED MINUS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="ominus",
+ unicodeslot=0x2296,
+ },
+ [0x2297]={
+ adobename="timescircle",
+ category="sm",
+ description="CIRCLED TIMES",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="otimes",
+ unicodeslot=0x2297,
+ variants={
+ [0xFE00]="with white rim",
+ },
+ },
+ [0x2298]={
+ category="sm",
+ description="CIRCLED DIVISION SLASH",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="oslash",
+ mirror=0x29B8,
+ unicodeslot=0x2298,
+ },
+ [0x2299]={
+ adobename="circleot",
+ category="sm",
+ cjkwd="a",
+ description="CIRCLED DOT OPERATOR",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="odot",
+ unicodeslot=0x2299,
+ },
+ [0x229A]={
+ category="sm",
+ description="CIRCLED RING OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="circledcirc",
+ unicodeslot=0x229A,
+ },
+ [0x229B]={
+ category="sm",
+ description="CIRCLED ASTERISK OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="circledast",
+ unicodeslot=0x229B,
+ },
+ [0x229C]={
+ category="sm",
+ description="CIRCLED EQUALS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="circledequals",
+ unicodeslot=0x229C,
+ variants={
+ [0xFE00]="with equal sign touching the circle",
+ },
+ },
+ [0x229D]={
+ category="sm",
+ description="CIRCLED DASH",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="circleddash",
+ unicodeslot=0x229D,
+ },
+ [0x229E]={
+ category="sm",
+ description="SQUARED PLUS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="boxplus",
+ unicodeslot=0x229E,
+ },
+ [0x229F]={
+ category="sm",
+ description="SQUARED MINUS",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="boxminus",
+ unicodeslot=0x229F,
+ },
+ [0x22A0]={
+ category="sm",
+ description="SQUARED TIMES",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="boxtimes",
+ unicodeslot=0x22A0,
+ },
+ [0x22A1]={
+ category="sm",
+ description="SQUARED DOT OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="boxdot",
+ unicodeslot=0x22A1,
+ },
+ [0x22A2]={
+ category="sm",
+ description="RIGHT TACK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="vdash",
+ mirror=0x22A3,
+ unicodeslot=0x22A2,
+ },
+ [0x22A3]={
+ adobename="tackleft",
+ category="sm",
+ description="LEFT TACK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="dashv",
+ mirror=0x22A2,
+ unicodeslot=0x22A3,
+ },
+ [0x22A4]={
+ adobename="tackdown",
+ category="sm",
+ description="DOWN TACK",
+ direction="on",
+ linebreak="al",
+ mathclass="default",
+ mathname="top",
+ unicodeslot=0x22A4,
+ },
+ [0x22A5]={
+ adobename="perpendicular",
+ category="sm",
+ cjkwd="a",
+ description="UP TACK",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="default",
+ name="bot",
+ },
+ {
+ class="relation",
+ name="perp",
+ },
+ },
+ unicodeslot=0x22A5,
+ },
+ [0x22A6]={
+ category="sm",
+ description="ASSERTION",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ADE,
+ unicodeslot=0x22A6,
+ },
+ [0x22A7]={
+ category="sm",
+ description="MODELS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="models",
+ unicodeslot=0x22A7,
+ },
+ [0x22A8]={
+ category="sm",
+ description="TRUE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="vDash",
+ mirror=0x2AE4,
+ unicodeslot=0x22A8,
+ },
+ [0x22A9]={
+ category="sm",
+ description="FORCES",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Vdash",
+ mirror=0x2AE3,
+ unicodeslot=0x22A9,
+ },
+ [0x22AA]={
+ category="sm",
+ description="TRIPLE VERTICAL BAR RIGHT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Vvdash",
+ unicodeslot=0x22AA,
+ },
+ [0x22AB]={
+ category="sm",
+ description="DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="VDash",
+ mirror=0x2AE5,
+ unicodeslot=0x22AB,
+ },
+ [0x22AC]={
+ category="sm",
+ description="DOES NOT PROVE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nvdash",
+ specials={ "char", 0x22A2, 0x338 },
+ unicodeslot=0x22AC,
+ },
+ [0x22AD]={
+ category="sm",
+ description="NOT TRUE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nvDash",
+ specials={ "char", 0x22A8, 0x338 },
+ unicodeslot=0x22AD,
+ },
+ [0x22AE]={
+ category="sm",
+ description="DOES NOT FORCE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nVdash",
+ specials={ "char", 0x22A9, 0x338 },
+ unicodeslot=0x22AE,
+ },
+ [0x22AF]={
+ category="sm",
+ description="NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nVDash",
+ specials={ "char", 0x22AB, 0x338 },
+ unicodeslot=0x22AF,
+ },
+ [0x22B0]={
+ category="sm",
+ description="PRECEDES UNDER RELATION",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B1,
+ unicodeslot=0x22B0,
+ },
+ [0x22B1]={
+ category="sm",
+ description="SUCCEEDS UNDER RELATION",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B0,
+ unicodeslot=0x22B1,
+ },
+ [0x22B2]={
+ category="sm",
+ comment="cramped triangleleft",
+ description="NORMAL SUBGROUP OF",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mirror=0x22B3,
+ unicodeslot=0x22B2,
+ },
+ [0x22B3]={
+ category="sm",
+ comment="cramped triangleright",
+ description="CONTAINS AS NORMAL SUBGROUP",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mirror=0x22B2,
+ unicodeslot=0x22B3,
+ },
+ [0x22B4]={
+ category="sm",
+ description="NORMAL SUBGROUP OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B5,
+ unicodeslot=0x22B4,
+ },
+ [0x22B5]={
+ category="sm",
+ description="CONTAINS AS NORMAL SUBGROUP OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B4,
+ unicodeslot=0x22B5,
+ },
+ [0x22B6]={
+ category="sm",
+ description="ORIGINAL OF",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B7,
+ unicodeslot=0x22B6,
+ },
+ [0x22B7]={
+ category="sm",
+ description="IMAGE OF",
+ direction="on",
+ linebreak="al",
+ mirror=0x22B6,
+ unicodeslot=0x22B7,
+ },
+ [0x22B8]={
+ category="sm",
+ description="MULTIMAP",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="multimap",
+ unicodeslot=0x22B8,
+ },
+ [0x22B9]={
+ category="sm",
+ description="HERMITIAN CONJUGATE MATRIX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22B9,
+ },
+ [0x22BA]={
+ category="sm",
+ description="INTERCALATE",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="intercal",
+ unicodeslot=0x22BA,
+ },
+ [0x22BB]={
+ category="sm",
+ description="XOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="veebar",
+ unicodeslot=0x22BB,
+ },
+ [0x22BC]={
+ category="sm",
+ description="NAND",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="barwedge",
+ unicodeslot=0x22BC,
+ },
+ [0x22BD]={
+ category="sm",
+ description="NOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22BD,
+ },
+ [0x22BE]={
+ category="sm",
+ description="RIGHT ANGLE WITH ARC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22BE,
+ },
+ [0x22BF]={
+ adobename="righttriangle",
+ category="sm",
+ cjkwd="a",
+ description="RIGHT TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x22BF,
+ },
+ [0x22C0]={
+ category="sm",
+ description="N-ARY LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigwedge",
+ unicodeslot=0x22C0,
+ },
+ [0x22C1]={
+ category="sm",
+ description="N-ARY LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigvee",
+ unicodeslot=0x22C1,
+ },
+ [0x22C2]={
+ category="sm",
+ description="N-ARY INTERSECTION",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigcap",
+ unicodeslot=0x22C2,
+ },
+ [0x22C3]={
+ category="sm",
+ description="N-ARY UNION",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigcup",
+ unicodeslot=0x22C3,
+ },
+ [0x22C4]={
+ category="sm",
+ description="DIAMOND OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="diamond",
+ unicodeslot=0x22C4,
+ },
+ [0x22C5]={
+ adobename="dotmath",
+ category="sm",
+ description="DOT OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="binary",
+ name="cdot",
+ },
+ {
+ class="punctuation",
+ name="cdotp",
+ },
+ },
+ unicodeslot=0x22C5,
+ },
+ [0x22C6]={
+ category="sm",
+ description="STAR OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="star",
+ unicodeslot=0x22C6,
+ },
+ [0x22C7]={
+ category="sm",
+ description="DIVISION TIMES",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="divideontimes",
+ unicodeslot=0x22C7,
+ },
+ [0x22C8]={
+ category="sm",
+ description="BOWTIE",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="bowtie",
+ },
+ {
+ class="relation",
+ name="Join",
+ },
+ },
+ unicodeslot=0x22C8,
+ },
+ [0x22C9]={
+ category="sm",
+ description="LEFT NORMAL FACTOR SEMIDIRECT PRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="ltimes",
+ mirror=0x22CA,
+ unicodeslot=0x22C9,
+ },
+ [0x22CA]={
+ category="sm",
+ description="RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="rtimes",
+ mirror=0x22C9,
+ unicodeslot=0x22CA,
+ },
+ [0x22CB]={
+ category="sm",
+ description="LEFT SEMIDIRECT PRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="leftthreetimes",
+ mirror=0x22CC,
+ unicodeslot=0x22CB,
+ },
+ [0x22CC]={
+ category="sm",
+ description="RIGHT SEMIDIRECT PRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="rightthreetimes",
+ mirror=0x22CB,
+ unicodeslot=0x22CC,
+ },
+ [0x22CD]={
+ category="sm",
+ description="REVERSED TILDE EQUALS",
+ direction="on",
+ linebreak="al",
+ mirror=0x2243,
+ unicodeslot=0x22CD,
+ },
+ [0x22CE]={
+ adobename="curlyor",
+ category="sm",
+ description="CURLY LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="curlyvee",
+ unicodeslot=0x22CE,
+ },
+ [0x22CF]={
+ adobename="curlyand",
+ category="sm",
+ description="CURLY LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="curlywedge",
+ unicodeslot=0x22CF,
+ },
+ [0x22D0]={
+ category="sm",
+ description="DOUBLE SUBSET",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Subset",
+ mirror=0x22D1,
+ unicodeslot=0x22D0,
+ },
+ [0x22D1]={
+ category="sm",
+ description="DOUBLE SUPERSET",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="Supset",
+ mirror=0x22D0,
+ unicodeslot=0x22D1,
+ },
+ [0x22D2]={
+ category="sm",
+ description="DOUBLE INTERSECTION",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="binary",
+ name="Cap",
+ },
+ {
+ class="binary",
+ name="doublecap",
+ },
+ },
+ unicodeslot=0x22D2,
+ },
+ [0x22D3]={
+ category="sm",
+ description="DOUBLE UNION",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="binary",
+ name="Cup",
+ },
+ {
+ class="binary",
+ name="doublecup",
+ },
+ },
+ unicodeslot=0x22D3,
+ },
+ [0x22D4]={
+ category="sm",
+ description="PITCHFORK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="pitchfork",
+ unicodeslot=0x22D4,
+ },
+ [0x22D5]={
+ category="sm",
+ description="EQUAL AND PARALLEL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22D5,
+ },
+ [0x22D6]={
+ category="sm",
+ description="LESS-THAN WITH DOT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="lessdot",
+ mirror=0x22D7,
+ unicodeslot=0x22D6,
+ },
+ [0x22D7]={
+ category="sm",
+ description="GREATER-THAN WITH DOT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="gtrdot",
+ mirror=0x22D6,
+ unicodeslot=0x22D7,
+ },
+ [0x22D8]={
+ category="sm",
+ description="VERY MUCH LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="lll",
+ },
+ {
+ class="relation",
+ name="llless",
+ },
+ },
+ mirror=0x22D9,
+ unicodeslot=0x22D8,
+ },
+ [0x22D9]={
+ category="sm",
+ description="VERY MUCH GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="relation",
+ name="ggg",
+ },
+ {
+ class="relation",
+ name="gggtr",
+ },
+ },
+ mirror=0x22D8,
+ unicodeslot=0x22D9,
+ },
+ [0x22DA]={
+ adobename="lessequalorgreater",
+ category="sm",
+ description="LESS-THAN EQUAL TO OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lesseqgtr",
+ mirror=0x22DB,
+ unicodeslot=0x22DA,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
+ },
+ [0x22DB]={
+ adobename="greaterequalorless",
+ category="sm",
+ description="GREATER-THAN EQUAL TO OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gtreqless",
+ mirror=0x22DA,
+ unicodeslot=0x22DB,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
+ },
+ [0x22DC]={
+ category="sm",
+ description="EQUAL TO OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqless",
+ mirror=0x22DD,
+ unicodeslot=0x22DC,
+ },
+ [0x22DD]={
+ category="sm",
+ description="EQUAL TO OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqgtr",
+ mirror=0x22DC,
+ unicodeslot=0x22DD,
+ },
+ [0x22DE]={
+ category="sm",
+ description="EQUAL TO OR PRECEDES",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="curlyeqprec",
+ mirror=0x22DF,
+ unicodeslot=0x22DE,
+ },
+ [0x22DF]={
+ category="sm",
+ description="EQUAL TO OR SUCCEEDS",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="curlyeqsucc",
+ mirror=0x22DE,
+ unicodeslot=0x22DF,
+ },
+ [0x22E0]={
+ category="sm",
+ description="DOES NOT PRECEDE OR EQUAL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="npreccurlyeq",
+ mirror=0x22E1,
+ specials={ "char", 0x227C, 0x338 },
+ unicodeslot=0x22E0,
+ },
+ [0x22E1]={
+ category="sm",
+ description="DOES NOT SUCCEED OR EQUAL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsucccurlyeq",
+ mirror=0x22E0,
+ specials={ "char", 0x227D, 0x338 },
+ unicodeslot=0x22E1,
+ },
+ [0x22E2]={
+ category="sm",
+ description="NOT SQUARE IMAGE OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsqsubseteq",
+ mirror=0x22E3,
+ specials={ "char", 0x2291, 0x338 },
+ unicodeslot=0x22E2,
+ },
+ [0x22E3]={
+ category="sm",
+ description="NOT SQUARE ORIGINAL OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nsqsupseteq",
+ mirror=0x22E2,
+ specials={ "char", 0x2292, 0x338 },
+ unicodeslot=0x22E3,
+ },
+ [0x22E4]={
+ category="sm",
+ description="SQUARE IMAGE OF OR NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="sqsubsetneq",
+ mirror=0x22E5,
+ unicodeslot=0x22E4,
+ },
+ [0x22E5]={
+ category="sm",
+ description="SQUARE ORIGINAL OF OR NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="sqsupsetneq",
+ mirror=0x22E4,
+ unicodeslot=0x22E5,
+ },
+ [0x22E6]={
+ category="sm",
+ description="LESS-THAN BUT NOT EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lnsim",
+ mirror=0x22E7,
+ unicodeslot=0x22E6,
+ },
+ [0x22E7]={
+ category="sm",
+ description="GREATER-THAN BUT NOT EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gnsim",
+ mirror=0x22E6,
+ unicodeslot=0x22E7,
+ },
+ [0x22E8]={
+ category="sm",
+ description="PRECEDES BUT NOT EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precnsim",
+ mirror=0x22E9,
+ unicodeslot=0x22E8,
+ },
+ [0x22E9]={
+ category="sm",
+ description="SUCCEEDS BUT NOT EQUIVALENT TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succnsim",
+ mirror=0x22E8,
+ unicodeslot=0x22E9,
+ },
+ [0x22EA]={
+ category="sm",
+ description="NOT NORMAL SUBGROUP OF",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ntriangleright",
+ mirror=0x22EB,
+ specials={ "char", 0x22B2, 0x338 },
+ unicodeslot=0x22EA,
+ },
+ [0x22EB]={
+ category="sm",
+ description="DOES NOT CONTAIN AS NORMAL SUBGROUP",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ntriangleleft",
+ mirror=0x22EA,
+ specials={ "char", 0x22B3, 0x338 },
+ unicodeslot=0x22EB,
+ },
+ [0x22EC]={
+ category="sm",
+ description="NOT NORMAL SUBGROUP OF OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ntrianglelefteq",
+ mirror=0x22ED,
+ specials={ "char", 0x22B4, 0x338 },
+ unicodeslot=0x22EC,
+ },
+ [0x22ED]={
+ category="sm",
+ description="DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="ntrianglerighteq",
+ mirror=0x22EC,
+ specials={ "char", 0x22B5, 0x338 },
+ unicodeslot=0x22ED,
+ },
+ [0x22EE]={
+ adobename="ellipsisvertical",
+ category="sm",
+ description="VERTICAL ELLIPSIS",
+ direction="on",
+ linebreak="al",
+ mathclass="inner",
+ mathname="vdots",
+ unicodeslot=0x22EE,
+ },
+ [0x22EF]={
+ category="sm",
+ description="MIDLINE HORIZONTAL ELLIPSIS",
+ direction="on",
+ linebreak="in",
+ mathclass="inner",
+ mathname="cdots",
+ unicodeslot=0x22EF,
+ },
+ [0x22F0]={
+ category="sm",
+ description="UP RIGHT DIAGONAL ELLIPSIS",
+ direction="on",
+ linebreak="al",
+ mathclass="inner",
+ mathname="udots",
+ mirror=0x22F1,
+ unicodeslot=0x22F0,
+ },
+ [0x22F1]={
+ category="sm",
+ description="DOWN RIGHT DIAGONAL ELLIPSIS",
+ direction="on",
+ linebreak="al",
+ mathclass="inner",
+ mathname="ddots",
+ mirror=0x22F0,
+ unicodeslot=0x22F1,
+ },
+ [0x22F2]={
+ category="sm",
+ description="ELEMENT OF WITH LONG HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22FA,
+ unicodeslot=0x22F2,
+ },
+ [0x22F3]={
+ category="sm",
+ description="ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22FB,
+ unicodeslot=0x22F3,
+ },
+ [0x22F4]={
+ category="sm",
+ description="SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22FC,
+ unicodeslot=0x22F4,
+ },
+ [0x22F5]={
+ category="sm",
+ description="ELEMENT OF WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22F5,
+ },
+ [0x22F6]={
+ category="sm",
+ description="ELEMENT OF WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ mirror=0x22FD,
+ unicodeslot=0x22F6,
+ },
+ [0x22F7]={
+ category="sm",
+ description="SMALL ELEMENT OF WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ mirror=0x22FE,
+ unicodeslot=0x22F7,
+ },
+ [0x22F8]={
+ category="sm",
+ description="ELEMENT OF WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22F8,
+ },
+ [0x22F9]={
+ category="sm",
+ description="ELEMENT OF WITH TWO HORIZONTAL STROKES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22F9,
+ },
+ [0x22FA]={
+ category="sm",
+ description="CONTAINS WITH LONG HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22F2,
+ unicodeslot=0x22FA,
+ },
+ [0x22FB]={
+ category="sm",
+ description="CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22F3,
+ unicodeslot=0x22FB,
+ },
+ [0x22FC]={
+ category="sm",
+ description="SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22F4,
+ unicodeslot=0x22FC,
+ },
+ [0x22FD]={
+ category="sm",
+ description="CONTAINS WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ mirror=0x22F6,
+ unicodeslot=0x22FD,
+ },
+ [0x22FE]={
+ category="sm",
+ description="SMALL CONTAINS WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ mirror=0x22F7,
+ unicodeslot=0x22FE,
+ },
+ [0x22FF]={
+ category="sm",
+ description="Z NOTATION BAG MEMBERSHIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x22FF,
+ },
+ [0x2300]={
+ category="so",
+ description="DIAMETER SIGN",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="ord",
+ name="varnothing",
+ },
+ {
+ class="ord",
+ name="diameter",
+ },
+ },
+ unicodeslot=0x2300,
+ },
+ [0x2301]={
+ category="so",
+ description="ELECTRIC ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2301,
+ },
+ [0x2302]={
+ adobename="house",
+ category="so",
+ description="HOUSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2302,
+ },
+ [0x2303]={
+ adobename="control",
+ category="so",
+ description="UP ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2303,
+ },
+ [0x2304]={
+ category="so",
+ description="DOWN ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2304,
+ },
+ [0x2305]={
+ adobename="projective",
+ category="so",
+ description="PROJECTIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2305,
+ },
+ [0x2306]={
+ category="so",
+ description="PERSPECTIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2306,
+ },
+ [0x2307]={
+ category="so",
+ description="WAVY LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2307,
+ },
+ [0x2308]={
+ category="sm",
+ description="LEFT CEILING",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lceil",
+ mirror=0x2309,
+ unicodeslot=0x2308,
+ },
+ [0x2309]={
+ category="sm",
+ description="RIGHT CEILING",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rceil",
+ mirror=0x2308,
+ unicodeslot=0x2309,
+ },
+ [0x230A]={
+ category="sm",
+ description="LEFT FLOOR",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lfloor",
+ mirror=0x230B,
+ unicodeslot=0x230A,
+ },
+ [0x230B]={
+ category="sm",
+ description="RIGHT FLOOR",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rfloor",
+ mirror=0x230A,
+ unicodeslot=0x230B,
+ },
+ [0x230C]={
+ category="so",
+ description="BOTTOM RIGHT CROP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x230C,
+ },
+ [0x230D]={
+ category="so",
+ description="BOTTOM LEFT CROP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x230D,
+ },
+ [0x230E]={
+ category="so",
+ description="TOP RIGHT CROP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x230E,
+ },
+ [0x230F]={
+ category="so",
+ description="TOP LEFT CROP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x230F,
+ },
+ [0x2310]={
+ adobename="revlogicalnot",
+ category="so",
+ description="REVERSED NOT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2310,
+ },
+ [0x2311]={
+ category="so",
+ description="SQUARE LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2311,
+ },
+ [0x2312]={
+ adobename="arc",
+ category="so",
+ cjkwd="a",
+ description="ARC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2312,
+ },
+ [0x2313]={
+ category="so",
+ description="SEGMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2313,
+ },
+ [0x2314]={
+ category="so",
+ description="SECTOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2314,
+ },
+ [0x2315]={
+ category="so",
+ description="TELEPHONE RECORDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2315,
+ },
+ [0x2316]={
+ category="so",
+ description="POSITION INDICATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2316,
+ },
+ [0x2317]={
+ category="so",
+ description="VIEWDATA SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2317,
+ },
+ [0x2318]={
+ adobename="propellor",
+ category="so",
+ description="PLACE OF INTEREST SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2318,
+ },
+ [0x2319]={
+ category="so",
+ description="TURNED NOT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2319,
+ },
+ [0x231A]={
+ category="so",
+ description="WATCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x231A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x231B]={
+ category="so",
+ description="HOURGLASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x231B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x231C]={
+ category="so",
+ description="TOP LEFT CORNER",
+ direction="on",
+ linebreak="al",
+ mathclass="open",
+ mathname="ulcorner",
+ unicodeslot=0x231C,
+ },
+ [0x231D]={
+ category="so",
+ description="TOP RIGHT CORNER",
+ direction="on",
+ linebreak="al",
+ mathclass="close",
+ mathname="urcorner",
+ unicodeslot=0x231D,
+ },
+ [0x231E]={
+ category="so",
+ description="BOTTOM LEFT CORNER",
+ direction="on",
+ linebreak="al",
+ mathclass="open",
+ mathname="llcorner",
+ unicodeslot=0x231E,
+ },
+ [0x231F]={
+ category="so",
+ description="BOTTOM RIGHT CORNER",
+ direction="on",
+ linebreak="al",
+ mathclass="close",
+ mathname="lrcorner",
+ unicodeslot=0x231F,
+ },
+ [0x2320]={
+ adobename="integraltp",
+ category="sm",
+ description="TOP HALF INTEGRAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2320,
+ },
+ [0x2321]={
+ adobename="integralbt",
+ category="sm",
+ description="BOTTOM HALF INTEGRAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2321,
+ },
+ [0x2322]={
+ category="so",
+ description="FROWN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="frown",
+ unicodeslot=0x2322,
+ },
+ [0x2323]={
+ category="so",
+ description="SMILE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="smile",
+ unicodeslot=0x2323,
+ },
+ [0x2324]={
+ category="so",
+ description="UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2324,
+ },
+ [0x2325]={
+ adobename="option",
+ category="so",
+ description="OPTION KEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2325,
+ },
+ [0x2326]={
+ adobename="deleteright",
+ category="so",
+ description="ERASE TO THE RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2326,
+ },
+ [0x2327]={
+ adobename="clear",
+ category="so",
+ description="X IN A RECTANGLE BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2327,
+ },
+ [0x2328]={
+ category="so",
+ description="KEYBOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2328,
+ },
+ [0x2329]={
+ adobename="angleleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT-POINTING ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x232A,
+ specials={ "char", 0x3008 },
+ unicodeslot=0x2329,
+ },
+ [0x232A]={
+ adobename="angleright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT-POINTING ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2329,
+ specials={ "char", 0x3009 },
+ unicodeslot=0x232A,
+ },
+ [0x232B]={
+ adobename="deleteleft",
+ category="so",
+ description="ERASE TO THE LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x232B,
+ },
+ [0x232C]={
+ category="so",
+ description="BENZENE RING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x232C,
+ },
+ [0x232D]={
+ category="so",
+ description="CYLINDRICITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x232D,
+ },
+ [0x232E]={
+ category="so",
+ description="ALL AROUND-PROFILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x232E,
+ },
+ [0x232F]={
+ category="so",
+ description="SYMMETRY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x232F,
+ },
+ [0x2330]={
+ category="so",
+ description="TOTAL RUNOUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2330,
+ },
+ [0x2331]={
+ category="so",
+ description="DIMENSION ORIGIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2331,
+ },
+ [0x2332]={
+ category="so",
+ description="CONICAL TAPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2332,
+ },
+ [0x2333]={
+ category="so",
+ description="SLOPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2333,
+ },
+ [0x2334]={
+ category="so",
+ description="COUNTERBORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2334,
+ },
+ [0x2335]={
+ category="so",
+ description="COUNTERSINK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2335,
+ },
+ [0x2336]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL I-BEAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2336,
+ },
+ [0x2337]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL SQUISH QUAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2337,
+ },
+ [0x2338]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD EQUAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2338,
+ },
+ [0x2339]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DIVIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2339,
+ },
+ [0x233A]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DIAMOND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233A,
+ },
+ [0x233B]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD JOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233B,
+ },
+ [0x233C]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233C,
+ },
+ [0x233D]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE STILE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233D,
+ },
+ [0x233E]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE JOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233E,
+ },
+ [0x233F]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL SLASH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x233F,
+ },
+ [0x2340]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL BACKSLASH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2340,
+ },
+ [0x2341]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD SLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2341,
+ },
+ [0x2342]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD BACKSLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2342,
+ },
+ [0x2343]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD LESS-THAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2343,
+ },
+ [0x2344]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD GREATER-THAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2344,
+ },
+ [0x2345]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL LEFTWARDS VANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2345,
+ },
+ [0x2346]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL RIGHTWARDS VANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2346,
+ },
+ [0x2347]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2347,
+ },
+ [0x2348]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2348,
+ },
+ [0x2349]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2349,
+ },
+ [0x234A]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234A,
+ },
+ [0x234B]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DELTA STILE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234B,
+ },
+ [0x234C]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DOWN CARET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234C,
+ },
+ [0x234D]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DELTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234D,
+ },
+ [0x234E]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DOWN TACK JOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234E,
+ },
+ [0x234F]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UPWARDS VANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x234F,
+ },
+ [0x2350]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2350,
+ },
+ [0x2351]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UP TACK OVERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2351,
+ },
+ [0x2352]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DEL STILE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2352,
+ },
+ [0x2353]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD UP CARET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2353,
+ },
+ [0x2354]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2354,
+ },
+ [0x2355]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UP TACK JOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2355,
+ },
+ [0x2356]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DOWNWARDS VANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2356,
+ },
+ [0x2357]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2357,
+ },
+ [0x2358]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUOTE UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2358,
+ },
+ [0x2359]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DELTA UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2359,
+ },
+ [0x235A]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235A,
+ },
+ [0x235B]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL JOT UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235B,
+ },
+ [0x235C]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235C,
+ },
+ [0x235D]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UP SHOE JOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235D,
+ },
+ [0x235E]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUOTE QUAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235E,
+ },
+ [0x235F]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE STAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x235F,
+ },
+ [0x2360]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2360,
+ },
+ [0x2361]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UP TACK DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2361,
+ },
+ [0x2362]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DEL DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2362,
+ },
+ [0x2363]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL STAR DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2363,
+ },
+ [0x2364]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL JOT DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2364,
+ },
+ [0x2365]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2365,
+ },
+ [0x2366]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DOWN SHOE STILE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2366,
+ },
+ [0x2367]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL LEFT SHOE STILE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2367,
+ },
+ [0x2368]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL TILDE DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2368,
+ },
+ [0x2369]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2369,
+ },
+ [0x236A]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL COMMA BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236A,
+ },
+ [0x236B]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DEL TILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236B,
+ },
+ [0x236C]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL ZILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236C,
+ },
+ [0x236D]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL STILE TILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236D,
+ },
+ [0x236E]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236E,
+ },
+ [0x236F]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD NOT EQUAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x236F,
+ },
+ [0x2370]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD QUESTION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2370,
+ },
+ [0x2371]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL DOWN CARET TILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2371,
+ },
+ [0x2372]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL UP CARET TILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2372,
+ },
+ [0x2373]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL IOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2373,
+ },
+ [0x2374]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL RHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2374,
+ },
+ [0x2375]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2375,
+ },
+ [0x2376]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL ALPHA UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2376,
+ },
+ [0x2377]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL EPSILON UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2377,
+ },
+ [0x2378]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL IOTA UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2378,
+ },
+ [0x2379]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL OMEGA UNDERBAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2379,
+ },
+ [0x237A]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x237A,
+ },
+ [0x237B]={
+ category="so",
+ description="NOT CHECK MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x237B,
+ },
+ [0x237C]={
+ category="sm",
+ description="RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x237C,
+ },
+ [0x237D]={
+ category="so",
+ description="SHOULDERED OPEN BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x237D,
+ },
+ [0x237E]={
+ category="so",
+ description="BELL SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x237E,
+ },
+ [0x237F]={
+ category="so",
+ description="VERTICAL LINE WITH MIDDLE DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x237F,
+ },
+ [0x2380]={
+ category="so",
+ description="INSERTION SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2380,
+ },
+ [0x2381]={
+ category="so",
+ description="CONTINUOUS UNDERLINE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2381,
+ },
+ [0x2382]={
+ category="so",
+ description="DISCONTINUOUS UNDERLINE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2382,
+ },
+ [0x2383]={
+ category="so",
+ description="EMPHASIS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2383,
+ },
+ [0x2384]={
+ category="so",
+ description="COMPOSITION SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2384,
+ },
+ [0x2385]={
+ category="so",
+ description="WHITE SQUARE WITH CENTRE VERTICAL LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2385,
+ },
+ [0x2386]={
+ category="so",
+ description="ENTER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2386,
+ },
+ [0x2387]={
+ category="so",
+ description="ALTERNATIVE KEY SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2387,
+ },
+ [0x2388]={
+ category="so",
+ description="HELM SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2388,
+ },
+ [0x2389]={
+ category="so",
+ description="CIRCLED HORIZONTAL BAR WITH NOTCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2389,
+ },
+ [0x238A]={
+ category="so",
+ description="CIRCLED TRIANGLE DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238A,
+ },
+ [0x238B]={
+ category="so",
+ description="BROKEN CIRCLE WITH NORTHWEST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238B,
+ },
+ [0x238C]={
+ category="so",
+ description="UNDO SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238C,
+ },
+ [0x238D]={
+ category="so",
+ description="MONOSTABLE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238D,
+ },
+ [0x238E]={
+ category="so",
+ description="HYSTERESIS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238E,
+ },
+ [0x238F]={
+ category="so",
+ description="OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x238F,
+ },
+ [0x2390]={
+ category="so",
+ description="OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2390,
+ },
+ [0x2391]={
+ category="so",
+ description="PASSIVE-PULL-DOWN-OUTPUT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2391,
+ },
+ [0x2392]={
+ category="so",
+ description="PASSIVE-PULL-UP-OUTPUT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2392,
+ },
+ [0x2393]={
+ category="so",
+ description="DIRECT CURRENT SYMBOL FORM TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2393,
+ },
+ [0x2394]={
+ category="so",
+ description="SOFTWARE-FUNCTION SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2394,
+ },
+ [0x2395]={
+ category="so",
+ description="APL FUNCTIONAL SYMBOL QUAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2395,
+ },
+ [0x2396]={
+ category="so",
+ description="DECIMAL SEPARATOR KEY SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2396,
+ },
+ [0x2397]={
+ category="so",
+ description="PREVIOUS PAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2397,
+ },
+ [0x2398]={
+ category="so",
+ description="NEXT PAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2398,
+ },
+ [0x2399]={
+ category="so",
+ description="PRINT SCREEN SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2399,
+ },
+ [0x239A]={
+ category="so",
+ description="CLEAR SCREEN SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239A,
+ },
+ [0x239B]={
+ category="sm",
+ description="LEFT PARENTHESIS UPPER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239B,
+ },
+ [0x239C]={
+ category="sm",
+ description="LEFT PARENTHESIS EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239C,
+ },
+ [0x239D]={
+ category="sm",
+ description="LEFT PARENTHESIS LOWER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239D,
+ },
+ [0x239E]={
+ category="sm",
+ description="RIGHT PARENTHESIS UPPER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239E,
+ },
+ [0x239F]={
+ category="sm",
+ description="RIGHT PARENTHESIS EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x239F,
+ },
+ [0x23A0]={
+ category="sm",
+ description="RIGHT PARENTHESIS LOWER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A0,
+ },
+ [0x23A1]={
+ category="sm",
+ description="LEFT SQUARE BRACKET UPPER CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A1,
+ },
+ [0x23A2]={
+ category="sm",
+ description="LEFT SQUARE BRACKET EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A2,
+ },
+ [0x23A3]={
+ category="sm",
+ description="LEFT SQUARE BRACKET LOWER CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A3,
+ },
+ [0x23A4]={
+ category="sm",
+ description="RIGHT SQUARE BRACKET UPPER CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A4,
+ },
+ [0x23A5]={
+ category="sm",
+ description="RIGHT SQUARE BRACKET EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A5,
+ },
+ [0x23A6]={
+ category="sm",
+ description="RIGHT SQUARE BRACKET LOWER CORNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A6,
+ },
+ [0x23A7]={
+ category="sm",
+ description="LEFT CURLY BRACKET UPPER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A7,
+ },
+ [0x23A8]={
+ category="sm",
+ description="LEFT CURLY BRACKET MIDDLE PIECE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A8,
+ },
+ [0x23A9]={
+ category="sm",
+ description="LEFT CURLY BRACKET LOWER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23A9,
+ },
+ [0x23AA]={
+ category="sm",
+ description="CURLY BRACKET EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AA,
+ },
+ [0x23AB]={
+ category="sm",
+ description="RIGHT CURLY BRACKET UPPER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AB,
+ },
+ [0x23AC]={
+ category="sm",
+ description="RIGHT CURLY BRACKET MIDDLE PIECE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AC,
+ },
+ [0x23AD]={
+ category="sm",
+ description="RIGHT CURLY BRACKET LOWER HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AD,
+ },
+ [0x23AE]={
+ category="sm",
+ description="INTEGRAL EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AE,
+ },
+ [0x23AF]={
+ category="sm",
+ description="HORIZONTAL LINE EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23AF,
+ },
+ [0x23B0]={
+ category="sm",
+ description="UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION",
+ direction="on",
+ linebreak="al",
+ mathclass="open",
+ mathname="lmoustache",
+ unicodeslot=0x23B0,
+ },
+ [0x23B1]={
+ category="sm",
+ description="UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION",
+ direction="on",
+ linebreak="al",
+ mathclass="close",
+ mathname="rmoustache",
+ unicodeslot=0x23B1,
+ },
+ [0x23B2]={
+ category="sm",
+ description="SUMMATION TOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B2,
+ },
+ [0x23B3]={
+ category="sm",
+ description="SUMMATION BOTTOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B3,
+ },
+ [0x23B4]={
+ category="so",
+ description="TOP SQUARE BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathextensible="h",
+ mathfiller="overbracketfill",
+ mathname="overbracket",
+ unicodeslot=0x23B4,
+ },
+ [0x23B5]={
+ category="so",
+ description="BOTTOM SQUARE BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="botaccent",
+ mathextensible="h",
+ mathfiller="underbracketfill",
+ mathname="underbracket",
+ unicodeslot=0x23B5,
+ },
+ [0x23B6]={
+ category="so",
+ description="BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B6,
+ },
+ [0x23B7]={
+ category="so",
+ description="RADICAL SYMBOL BOTTOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B7,
+ },
+ [0x23B8]={
+ category="so",
+ description="LEFT VERTICAL BOX LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B8,
+ },
+ [0x23B9]={
+ category="so",
+ description="RIGHT VERTICAL BOX LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23B9,
+ },
+ [0x23BA]={
+ category="so",
+ description="HORIZONTAL SCAN LINE-0x0001",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BA,
+ },
+ [0x23BB]={
+ category="so",
+ description="HORIZONTAL SCAN LINE-0x0003",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BB,
+ },
+ [0x23BC]={
+ category="so",
+ description="HORIZONTAL SCAN LINE-0x0007",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BC,
+ },
+ [0x23BD]={
+ category="so",
+ description="HORIZONTAL SCAN LINE-0x0009",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BD,
+ },
+ [0x23BE]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BE,
+ },
+ [0x23BF]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23BF,
+ },
+ [0x23C0]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C0,
+ },
+ [0x23C1]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C1,
+ },
+ [0x23C2]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C2,
+ },
+ [0x23C3]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C3,
+ },
+ [0x23C4]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C4,
+ },
+ [0x23C5]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C5,
+ },
+ [0x23C6]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C6,
+ },
+ [0x23C7]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C7,
+ },
+ [0x23C8]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C8,
+ },
+ [0x23C9]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23C9,
+ },
+ [0x23CA]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CA,
+ },
+ [0x23CB]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CB,
+ },
+ [0x23CC]={
+ category="so",
+ description="DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CC,
+ },
+ [0x23CD]={
+ category="so",
+ description="SQUARE FOOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CD,
+ },
+ [0x23CE]={
+ category="so",
+ description="RETURN SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CE,
+ },
+ [0x23CF]={
+ category="so",
+ description="EJECT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23CF,
+ },
+ [0x23D0]={
+ category="so",
+ description="VERTICAL LINE EXTENSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D0,
+ },
+ [0x23D1]={
+ category="so",
+ description="METRICAL BREVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D1,
+ },
+ [0x23D2]={
+ category="so",
+ description="METRICAL LONG OVER SHORT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D2,
+ },
+ [0x23D3]={
+ category="so",
+ description="METRICAL SHORT OVER LONG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D3,
+ },
+ [0x23D4]={
+ category="so",
+ description="METRICAL LONG OVER TWO SHORTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D4,
+ },
+ [0x23D5]={
+ category="so",
+ description="METRICAL TWO SHORTS OVER LONG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D5,
+ },
+ [0x23D6]={
+ category="so",
+ description="METRICAL TWO SHORTS JOINED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D6,
+ },
+ [0x23D7]={
+ category="so",
+ description="METRICAL TRISEME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D7,
+ },
+ [0x23D8]={
+ category="so",
+ description="METRICAL TETRASEME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D8,
+ },
+ [0x23D9]={
+ category="so",
+ description="METRICAL PENTASEME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23D9,
+ },
+ [0x23DA]={
+ category="so",
+ description="EARTH GROUND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23DA,
+ },
+ [0x23DB]={
+ category="so",
+ description="FUSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23DB,
+ },
+ [0x23DC]={
+ category="sm",
+ description="TOP PARENTHESIS",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathextensible="h",
+ mathfiller="overparentfill",
+ mathname="overparent",
+ unicodeslot=0x23DC,
+ },
+ [0x23DD]={
+ category="sm",
+ description="BOTTOM PARENTHESIS",
+ direction="on",
+ linebreak="al",
+ mathclass="botaccent",
+ mathextensible="h",
+ mathfiller="underparentfill",
+ mathname="underparent",
+ unicodeslot=0x23DD,
+ },
+ [0x23DE]={
+ category="sm",
+ description="TOP CURLY BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ mathextensible="h",
+ mathfiller="overbracefill",
+ mathname="overbrace",
+ unicodeslot=0x23DE,
+ },
+ [0x23DF]={
+ category="sm",
+ description="BOTTOM CURLY BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="botaccent",
+ mathextensible="h",
+ mathfiller="underbracefill",
+ mathname="underbrace",
+ unicodeslot=0x23DF,
+ },
+ [0x23E0]={
+ category="sm",
+ description="TOP TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="topaccent",
+ unicodeslot=0x23E0,
+ },
+ [0x23E1]={
+ category="sm",
+ description="BOTTOM TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="al",
+ mathclass="botaccent",
+ unicodeslot=0x23E1,
+ },
+ [0x23E2]={
+ category="so",
+ description="WHITE TRAPEZIUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E2,
+ },
+ [0x23E3]={
+ category="so",
+ description="BENZENE RING WITH CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E3,
+ },
+ [0x23E4]={
+ category="so",
+ description="STRAIGHTNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E4,
+ },
+ [0x23E5]={
+ category="so",
+ description="FLATNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E5,
+ },
+ [0x23E6]={
+ category="so",
+ description="AC CURRENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E6,
+ },
+ [0x23E7]={
+ category="so",
+ description="ELECTRICAL INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E7,
+ },
+ [0x23E8]={
+ category="so",
+ description="DECIMAL EXPONENT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E8,
+ },
+ [0x23E9]={
+ category="so",
+ description="BLACK RIGHT-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E9,
+ },
+ [0x23EA]={
+ category="so",
+ description="BLACK LEFT-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EA,
+ },
+ [0x23EB]={
+ category="so",
+ description="BLACK UP-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EB,
+ },
+ [0x23EC]={
+ category="so",
+ description="BLACK DOWN-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EC,
+ },
+ [0x23ED]={
+ category="so",
+ description="BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23ED,
+ },
+ [0x23EE]={
+ category="so",
+ description="BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EE,
+ },
+ [0x23EF]={
+ category="so",
+ description="BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EF,
+ },
+ [0x23F0]={
+ category="so",
+ description="ALARM CLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x23F0,
+ },
+ [0x23F1]={
+ category="so",
+ description="STOPWATCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x23F1,
+ },
+ [0x23F2]={
+ category="so",
+ description="TIMER CLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x23F2,
+ },
+ [0x23F3]={
+ category="so",
+ description="HOURGLASS WITH FLOWING SAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x23F3,
+ },
+ [0x23F4]={
+ category="so",
+ description="BLACK MEDIUM LEFT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F4,
+ },
+ [0x23F5]={
+ category="so",
+ description="BLACK MEDIUM RIGHT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F5,
+ },
+ [0x23F6]={
+ category="so",
+ description="BLACK MEDIUM UP-POINTING TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F6,
+ },
+ [0x23F7]={
+ category="so",
+ description="BLACK MEDIUM DOWN-POINTING TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F7,
+ },
+ [0x23F8]={
+ category="so",
+ description="DOUBLE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F8,
+ },
+ [0x23F9]={
+ category="so",
+ description="BLACK SQUARE FOR STOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F9,
+ },
+ [0x23FA]={
+ category="so",
+ description="BLACK CIRCLE FOR RECORD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23FA,
+ },
+ [0x2400]={
+ category="so",
+ description="SYMBOL FOR NULL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2400,
+ },
+ [0x2401]={
+ category="so",
+ description="SYMBOL FOR START OF HEADING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2401,
+ },
+ [0x2402]={
+ category="so",
+ description="SYMBOL FOR START OF TEXT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2402,
+ },
+ [0x2403]={
+ category="so",
+ description="SYMBOL FOR END OF TEXT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2403,
+ },
+ [0x2404]={
+ category="so",
+ description="SYMBOL FOR END OF TRANSMISSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2404,
+ },
+ [0x2405]={
+ category="so",
+ description="SYMBOL FOR ENQUIRY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2405,
+ },
+ [0x2406]={
+ category="so",
+ description="SYMBOL FOR ACKNOWLEDGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2406,
+ },
+ [0x2407]={
+ category="so",
+ description="SYMBOL FOR BELL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2407,
+ },
+ [0x2408]={
+ category="so",
+ description="SYMBOL FOR BACKSPACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2408,
+ },
+ [0x2409]={
+ category="so",
+ description="SYMBOL FOR HORIZONTAL TABULATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2409,
+ },
+ [0x240A]={
+ category="so",
+ description="SYMBOL FOR LINE FEED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240A,
+ },
+ [0x240B]={
+ category="so",
+ description="SYMBOL FOR VERTICAL TABULATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240B,
+ },
+ [0x240C]={
+ category="so",
+ description="SYMBOL FOR FORM FEED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240C,
+ },
+ [0x240D]={
+ category="so",
+ description="SYMBOL FOR CARRIAGE RETURN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240D,
+ },
+ [0x240E]={
+ category="so",
+ description="SYMBOL FOR SHIFT OUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240E,
+ },
+ [0x240F]={
+ category="so",
+ description="SYMBOL FOR SHIFT IN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x240F,
+ },
+ [0x2410]={
+ category="so",
+ description="SYMBOL FOR DATA LINK ESCAPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2410,
+ },
+ [0x2411]={
+ category="so",
+ description="SYMBOL FOR DEVICE CONTROL ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2411,
+ },
+ [0x2412]={
+ category="so",
+ description="SYMBOL FOR DEVICE CONTROL TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2412,
+ },
+ [0x2413]={
+ category="so",
+ description="SYMBOL FOR DEVICE CONTROL THREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2413,
+ },
+ [0x2414]={
+ category="so",
+ description="SYMBOL FOR DEVICE CONTROL FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2414,
+ },
+ [0x2415]={
+ category="so",
+ description="SYMBOL FOR NEGATIVE ACKNOWLEDGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2415,
+ },
+ [0x2416]={
+ category="so",
+ description="SYMBOL FOR SYNCHRONOUS IDLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2416,
+ },
+ [0x2417]={
+ category="so",
+ description="SYMBOL FOR END OF TRANSMISSION BLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2417,
+ },
+ [0x2418]={
+ category="so",
+ description="SYMBOL FOR CANCEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2418,
+ },
+ [0x2419]={
+ category="so",
+ description="SYMBOL FOR END OF MEDIUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2419,
+ },
+ [0x241A]={
+ category="so",
+ description="SYMBOL FOR SUBSTITUTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241A,
+ },
+ [0x241B]={
+ category="so",
+ description="SYMBOL FOR ESCAPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241B,
+ },
+ [0x241C]={
+ category="so",
+ description="SYMBOL FOR FILE SEPARATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241C,
+ },
+ [0x241D]={
+ category="so",
+ description="SYMBOL FOR GROUP SEPARATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241D,
+ },
+ [0x241E]={
+ category="so",
+ description="SYMBOL FOR RECORD SEPARATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241E,
+ },
+ [0x241F]={
+ category="so",
+ description="SYMBOL FOR UNIT SEPARATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x241F,
+ },
+ [0x2420]={
+ category="so",
+ description="SYMBOL FOR SPACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2420,
+ },
+ [0x2421]={
+ category="so",
+ description="SYMBOL FOR DELETE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2421,
+ },
+ [0x2422]={
+ category="so",
+ description="BLANK SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2422,
+ },
+ [0x2423]={
+ adobename="blank",
+ category="so",
+ description="OPEN BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2423,
+ },
+ [0x2424]={
+ category="so",
+ description="SYMBOL FOR NEWLINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2424,
+ },
+ [0x2425]={
+ category="so",
+ description="SYMBOL FOR DELETE FORM TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2425,
+ },
+ [0x2426]={
+ category="so",
+ description="SYMBOL FOR SUBSTITUTE FORM TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2426,
+ },
+ [0x2440]={
+ category="so",
+ description="OCR HOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2440,
+ },
+ [0x2441]={
+ category="so",
+ description="OCR CHAIR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2441,
+ },
+ [0x2442]={
+ category="so",
+ description="OCR FORK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2442,
+ },
+ [0x2443]={
+ category="so",
+ description="OCR INVERTED FORK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2443,
+ },
+ [0x2444]={
+ category="so",
+ description="OCR BELT BUCKLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2444,
+ },
+ [0x2445]={
+ category="so",
+ description="OCR BOW TIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2445,
+ },
+ [0x2446]={
+ category="so",
+ description="OCR BRANCH BANK IDENTIFICATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2446,
+ },
+ [0x2447]={
+ category="so",
+ description="OCR AMOUNT OF CHECK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2447,
+ },
+ [0x2448]={
+ category="so",
+ description="OCR DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2448,
+ },
+ [0x2449]={
+ category="so",
+ description="OCR CUSTOMER ACCOUNT NUMBER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2449,
+ },
+ [0x244A]={
+ category="so",
+ description="OCR DOUBLE BACKSLASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x244A,
+ },
+ [0x2460]={
+ adobename="onecircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31 },
+ unicodeslot=0x2460,
+ },
+ [0x2461]={
+ adobename="twocircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x32 },
+ unicodeslot=0x2461,
+ },
+ [0x2462]={
+ adobename="threecircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x33 },
+ unicodeslot=0x2462,
+ },
+ [0x2463]={
+ adobename="fourcircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x34 },
+ unicodeslot=0x2463,
+ },
+ [0x2464]={
+ adobename="fivecircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x35 },
+ unicodeslot=0x2464,
+ },
+ [0x2465]={
+ adobename="sixcircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x36 },
+ unicodeslot=0x2465,
+ },
+ [0x2466]={
+ adobename="sevencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x37 },
+ unicodeslot=0x2466,
+ },
+ [0x2467]={
+ adobename="eightcircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x38 },
+ unicodeslot=0x2467,
+ },
+ [0x2468]={
+ adobename="ninecircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x39 },
+ unicodeslot=0x2468,
+ },
+ [0x2469]={
+ adobename="tencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x30 },
+ unicodeslot=0x2469,
+ },
+ [0x246A]={
+ adobename="elevencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER ELEVEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x31 },
+ unicodeslot=0x246A,
+ },
+ [0x246B]={
+ adobename="twelvecircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER TWELVE",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x32 },
+ unicodeslot=0x246B,
+ },
+ [0x246C]={
+ adobename="thirteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER THIRTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x33 },
+ unicodeslot=0x246C,
+ },
+ [0x246D]={
+ adobename="fourteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER FOURTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x34 },
+ unicodeslot=0x246D,
+ },
+ [0x246E]={
+ adobename="fifteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER FIFTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x35 },
+ unicodeslot=0x246E,
+ },
+ [0x246F]={
+ adobename="sixteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER SIXTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x36 },
+ unicodeslot=0x246F,
+ },
+ [0x2470]={
+ adobename="seventeencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER SEVENTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x37 },
+ unicodeslot=0x2470,
+ },
+ [0x2471]={
+ adobename="eighteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER EIGHTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x38 },
+ unicodeslot=0x2471,
+ },
+ [0x2472]={
+ adobename="nineteencircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER NINETEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x31, 0x39 },
+ unicodeslot=0x2472,
+ },
+ [0x2473]={
+ adobename="twentycircle",
+ category="no",
+ cjkwd="a",
+ description="CIRCLED NUMBER TWENTY",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x32, 0x30 },
+ unicodeslot=0x2473,
+ },
+ [0x2474]={
+ adobename="oneparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x29 },
+ unicodeslot=0x2474,
+ },
+ [0x2475]={
+ adobename="twoparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x32, 0x29 },
+ unicodeslot=0x2475,
+ },
+ [0x2476]={
+ adobename="threeparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x33, 0x29 },
+ unicodeslot=0x2476,
+ },
+ [0x2477]={
+ adobename="fourparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x34, 0x29 },
+ unicodeslot=0x2477,
+ },
+ [0x2478]={
+ adobename="fiveparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x35, 0x29 },
+ unicodeslot=0x2478,
+ },
+ [0x2479]={
+ adobename="sixparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x36, 0x29 },
+ unicodeslot=0x2479,
+ },
+ [0x247A]={
+ adobename="sevenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x37, 0x29 },
+ unicodeslot=0x247A,
+ },
+ [0x247B]={
+ adobename="eightparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x38, 0x29 },
+ unicodeslot=0x247B,
+ },
+ [0x247C]={
+ adobename="nineparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x39, 0x29 },
+ unicodeslot=0x247C,
+ },
+ [0x247D]={
+ adobename="tenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x30, 0x29 },
+ unicodeslot=0x247D,
+ },
+ [0x247E]={
+ adobename="elevenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER ELEVEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x31, 0x29 },
+ unicodeslot=0x247E,
+ },
+ [0x247F]={
+ adobename="twelveparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER TWELVE",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x32, 0x29 },
+ unicodeslot=0x247F,
+ },
+ [0x2480]={
+ adobename="thirteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER THIRTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x33, 0x29 },
+ unicodeslot=0x2480,
+ },
+ [0x2481]={
+ adobename="fourteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER FOURTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x34, 0x29 },
+ unicodeslot=0x2481,
+ },
+ [0x2482]={
+ adobename="fifteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER FIFTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x35, 0x29 },
+ unicodeslot=0x2482,
+ },
+ [0x2483]={
+ adobename="sixteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER SIXTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x36, 0x29 },
+ unicodeslot=0x2483,
+ },
+ [0x2484]={
+ adobename="seventeenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER SEVENTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x37, 0x29 },
+ unicodeslot=0x2484,
+ },
+ [0x2485]={
+ adobename="eighteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER EIGHTEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x38, 0x29 },
+ unicodeslot=0x2485,
+ },
+ [0x2486]={
+ adobename="nineteenparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER NINETEEN",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x31, 0x39, 0x29 },
+ unicodeslot=0x2486,
+ },
+ [0x2487]={
+ adobename="twentyparen",
+ category="no",
+ cjkwd="a",
+ description="PARENTHESIZED NUMBER TWENTY",
+ direction="on",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x32, 0x30, 0x29 },
+ unicodeslot=0x2487,
+ },
+ [0x2488]={
+ adobename="oneperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT ONE FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x2E },
+ unicodeslot=0x2488,
+ },
+ [0x2489]={
+ adobename="twoperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT TWO FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x32, 0x2E },
+ unicodeslot=0x2489,
+ },
+ [0x248A]={
+ adobename="threeperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT THREE FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x33, 0x2E },
+ unicodeslot=0x248A,
+ },
+ [0x248B]={
+ adobename="fourperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT FOUR FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x34, 0x2E },
+ unicodeslot=0x248B,
+ },
+ [0x248C]={
+ adobename="fiveperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT FIVE FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x35, 0x2E },
+ unicodeslot=0x248C,
+ },
+ [0x248D]={
+ adobename="sixperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT SIX FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x36, 0x2E },
+ unicodeslot=0x248D,
+ },
+ [0x248E]={
+ adobename="sevenperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT SEVEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x37, 0x2E },
+ unicodeslot=0x248E,
+ },
+ [0x248F]={
+ adobename="eightperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT EIGHT FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x38, 0x2E },
+ unicodeslot=0x248F,
+ },
+ [0x2490]={
+ adobename="nineperiod",
+ category="no",
+ cjkwd="a",
+ description="DIGIT NINE FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x39, 0x2E },
+ unicodeslot=0x2490,
+ },
+ [0x2491]={
+ adobename="tenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER TEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x30, 0x2E },
+ unicodeslot=0x2491,
+ },
+ [0x2492]={
+ adobename="elevenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER ELEVEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x31, 0x2E },
+ unicodeslot=0x2492,
+ },
+ [0x2493]={
+ adobename="twelveperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER TWELVE FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x32, 0x2E },
+ unicodeslot=0x2493,
+ },
+ [0x2494]={
+ adobename="thirteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER THIRTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x33, 0x2E },
+ unicodeslot=0x2494,
+ },
+ [0x2495]={
+ adobename="fourteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER FOURTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x34, 0x2E },
+ unicodeslot=0x2495,
+ },
+ [0x2496]={
+ adobename="fifteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER FIFTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x35, 0x2E },
+ unicodeslot=0x2496,
+ },
+ [0x2497]={
+ adobename="sixteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER SIXTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x36, 0x2E },
+ unicodeslot=0x2497,
+ },
+ [0x2498]={
+ adobename="seventeenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER SEVENTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x37, 0x2E },
+ unicodeslot=0x2498,
+ },
+ [0x2499]={
+ adobename="eighteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER EIGHTEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x38, 0x2E },
+ unicodeslot=0x2499,
+ },
+ [0x249A]={
+ adobename="nineteenperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER NINETEEN FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x39, 0x2E },
+ unicodeslot=0x249A,
+ },
+ [0x249B]={
+ adobename="twentyperiod",
+ category="no",
+ cjkwd="a",
+ description="NUMBER TWENTY FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x32, 0x30, 0x2E },
+ unicodeslot=0x249B,
+ },
+ [0x249C]={
+ adobename="aparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x61, 0x29 },
+ unicodeslot=0x249C,
+ },
+ [0x249D]={
+ adobename="bparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x62, 0x29 },
+ unicodeslot=0x249D,
+ },
+ [0x249E]={
+ adobename="cparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x63, 0x29 },
+ unicodeslot=0x249E,
+ },
+ [0x249F]={
+ adobename="dparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x64, 0x29 },
+ unicodeslot=0x249F,
+ },
+ [0x24A0]={
+ adobename="eparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x65, 0x29 },
+ unicodeslot=0x24A0,
+ },
+ [0x24A1]={
+ adobename="fparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x66, 0x29 },
+ unicodeslot=0x24A1,
+ },
+ [0x24A2]={
+ adobename="gparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x67, 0x29 },
+ unicodeslot=0x24A2,
+ },
+ [0x24A3]={
+ adobename="hparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x68, 0x29 },
+ unicodeslot=0x24A3,
+ },
+ [0x24A4]={
+ adobename="iparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x69, 0x29 },
+ unicodeslot=0x24A4,
+ },
+ [0x24A5]={
+ adobename="jparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6A, 0x29 },
+ unicodeslot=0x24A5,
+ },
+ [0x24A6]={
+ adobename="kparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6B, 0x29 },
+ unicodeslot=0x24A6,
+ },
+ [0x24A7]={
+ adobename="lparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6C, 0x29 },
+ unicodeslot=0x24A7,
+ },
+ [0x24A8]={
+ adobename="mparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6D, 0x29 },
+ unicodeslot=0x24A8,
+ },
+ [0x24A9]={
+ adobename="nparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6E, 0x29 },
+ unicodeslot=0x24A9,
+ },
+ [0x24AA]={
+ adobename="oparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x6F, 0x29 },
+ unicodeslot=0x24AA,
+ },
+ [0x24AB]={
+ adobename="pparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x70, 0x29 },
+ unicodeslot=0x24AB,
+ },
+ [0x24AC]={
+ adobename="qparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x71, 0x29 },
+ unicodeslot=0x24AC,
+ },
+ [0x24AD]={
+ adobename="rparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x72, 0x29 },
+ unicodeslot=0x24AD,
+ },
+ [0x24AE]={
+ adobename="sparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x73, 0x29 },
+ unicodeslot=0x24AE,
+ },
+ [0x24AF]={
+ adobename="tparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x74, 0x29 },
+ unicodeslot=0x24AF,
+ },
+ [0x24B0]={
+ adobename="uparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x75, 0x29 },
+ unicodeslot=0x24B0,
+ },
+ [0x24B1]={
+ adobename="vparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x76, 0x29 },
+ unicodeslot=0x24B1,
+ },
+ [0x24B2]={
+ adobename="wparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x77, 0x29 },
+ unicodeslot=0x24B2,
+ },
+ [0x24B3]={
+ adobename="xparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x78, 0x29 },
+ unicodeslot=0x24B3,
+ },
+ [0x24B4]={
+ adobename="yparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x79, 0x29 },
+ unicodeslot=0x24B4,
+ },
+ [0x24B5]={
+ adobename="zparen",
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN SMALL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x7A, 0x29 },
+ unicodeslot=0x24B5,
+ },
+ [0x24B6]={
+ adobename="Acircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER A",
+ direction="l",
+ lccode=0x24D0,
+ linebreak="ai",
+ specials={ "circle", 0x41 },
+ unicodeslot=0x24B6,
+ },
+ [0x24B7]={
+ adobename="Bcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER B",
+ direction="l",
+ lccode=0x24D1,
+ linebreak="ai",
+ specials={ "circle", 0x42 },
+ unicodeslot=0x24B7,
+ },
+ [0x24B8]={
+ adobename="Ccircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER C",
+ direction="l",
+ lccode=0x24D2,
+ linebreak="ai",
+ specials={ "circle", 0x43 },
+ unicodeslot=0x24B8,
+ },
+ [0x24B9]={
+ adobename="Dcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER D",
+ direction="l",
+ lccode=0x24D3,
+ linebreak="ai",
+ specials={ "circle", 0x44 },
+ unicodeslot=0x24B9,
+ },
+ [0x24BA]={
+ adobename="Ecircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER E",
+ direction="l",
+ lccode=0x24D4,
+ linebreak="ai",
+ specials={ "circle", 0x45 },
+ unicodeslot=0x24BA,
+ },
+ [0x24BB]={
+ adobename="Fcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER F",
+ direction="l",
+ lccode=0x24D5,
+ linebreak="ai",
+ specials={ "circle", 0x46 },
+ unicodeslot=0x24BB,
+ },
+ [0x24BC]={
+ adobename="Gcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER G",
+ direction="l",
+ lccode=0x24D6,
+ linebreak="ai",
+ specials={ "circle", 0x47 },
+ unicodeslot=0x24BC,
+ },
+ [0x24BD]={
+ adobename="Hcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER H",
+ direction="l",
+ lccode=0x24D7,
+ linebreak="ai",
+ specials={ "circle", 0x48 },
+ unicodeslot=0x24BD,
+ },
+ [0x24BE]={
+ adobename="Icircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER I",
+ direction="l",
+ lccode=0x24D8,
+ linebreak="ai",
+ specials={ "circle", 0x49 },
+ unicodeslot=0x24BE,
+ },
+ [0x24BF]={
+ adobename="Jcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER J",
+ direction="l",
+ lccode=0x24D9,
+ linebreak="ai",
+ specials={ "circle", 0x4A },
+ unicodeslot=0x24BF,
+ },
+ [0x24C0]={
+ adobename="Kcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER K",
+ direction="l",
+ lccode=0x24DA,
+ linebreak="ai",
+ specials={ "circle", 0x4B },
+ unicodeslot=0x24C0,
+ },
+ [0x24C1]={
+ adobename="Lcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER L",
+ direction="l",
+ lccode=0x24DB,
+ linebreak="ai",
+ specials={ "circle", 0x4C },
+ unicodeslot=0x24C1,
+ },
+ [0x24C2]={
+ adobename="Mcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER M",
+ direction="l",
+ lccode=0x24DC,
+ linebreak="ai",
+ specials={ "circle", 0x4D },
+ unicodeslot=0x24C2,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x24C3]={
+ adobename="Ncircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER N",
+ direction="l",
+ lccode=0x24DD,
+ linebreak="ai",
+ specials={ "circle", 0x4E },
+ unicodeslot=0x24C3,
+ },
+ [0x24C4]={
+ adobename="Ocircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER O",
+ direction="l",
+ lccode=0x24DE,
+ linebreak="ai",
+ specials={ "circle", 0x4F },
+ unicodeslot=0x24C4,
+ },
+ [0x24C5]={
+ adobename="Pcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER P",
+ direction="l",
+ lccode=0x24DF,
+ linebreak="ai",
+ specials={ "circle", 0x50 },
+ unicodeslot=0x24C5,
+ },
+ [0x24C6]={
+ adobename="Qcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER Q",
+ direction="l",
+ lccode=0x24E0,
+ linebreak="ai",
+ specials={ "circle", 0x51 },
+ unicodeslot=0x24C6,
+ },
+ [0x24C7]={
+ adobename="Rcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER R",
+ direction="l",
+ lccode=0x24E1,
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="circledR",
+ specials={ "circle", 0x52 },
+ unicodeslot=0x24C7,
+ },
+ [0x24C8]={
+ adobename="Scircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER S",
+ direction="l",
+ lccode=0x24E2,
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="circledS",
+ specials={ "circle", 0x53 },
+ unicodeslot=0x24C8,
+ },
+ [0x24C9]={
+ adobename="Tcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER T",
+ direction="l",
+ lccode=0x24E3,
+ linebreak="ai",
+ specials={ "circle", 0x54 },
+ unicodeslot=0x24C9,
+ },
+ [0x24CA]={
+ adobename="Ucircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER U",
+ direction="l",
+ lccode=0x24E4,
+ linebreak="ai",
+ specials={ "circle", 0x55 },
+ unicodeslot=0x24CA,
+ },
+ [0x24CB]={
+ adobename="Vcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER V",
+ direction="l",
+ lccode=0x24E5,
+ linebreak="ai",
+ specials={ "circle", 0x56 },
+ unicodeslot=0x24CB,
+ },
+ [0x24CC]={
+ adobename="Wcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER W",
+ direction="l",
+ lccode=0x24E6,
+ linebreak="ai",
+ specials={ "circle", 0x57 },
+ unicodeslot=0x24CC,
+ },
+ [0x24CD]={
+ adobename="Xcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER X",
+ direction="l",
+ lccode=0x24E7,
+ linebreak="ai",
+ specials={ "circle", 0x58 },
+ unicodeslot=0x24CD,
+ },
+ [0x24CE]={
+ adobename="Ycircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER Y",
+ direction="l",
+ lccode=0x24E8,
+ linebreak="ai",
+ specials={ "circle", 0x59 },
+ unicodeslot=0x24CE,
+ },
+ [0x24CF]={
+ adobename="Zcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN CAPITAL LETTER Z",
+ direction="l",
+ lccode=0x24E9,
+ linebreak="ai",
+ specials={ "circle", 0x5A },
+ unicodeslot=0x24CF,
+ },
+ [0x24D0]={
+ adobename="acircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x61 },
+ uccode=0x24B6,
+ unicodeslot=0x24D0,
+ },
+ [0x24D1]={
+ adobename="bcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x62 },
+ uccode=0x24B7,
+ unicodeslot=0x24D1,
+ },
+ [0x24D2]={
+ adobename="ccircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x63 },
+ uccode=0x24B8,
+ unicodeslot=0x24D2,
+ },
+ [0x24D3]={
+ adobename="dcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x64 },
+ uccode=0x24B9,
+ unicodeslot=0x24D3,
+ },
+ [0x24D4]={
+ adobename="ecircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x65 },
+ uccode=0x24BA,
+ unicodeslot=0x24D4,
+ },
+ [0x24D5]={
+ adobename="fcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x66 },
+ uccode=0x24BB,
+ unicodeslot=0x24D5,
+ },
+ [0x24D6]={
+ adobename="gcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x67 },
+ uccode=0x24BC,
+ unicodeslot=0x24D6,
+ },
+ [0x24D7]={
+ adobename="hcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x68 },
+ uccode=0x24BD,
+ unicodeslot=0x24D7,
+ },
+ [0x24D8]={
+ adobename="icircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x69 },
+ uccode=0x24BE,
+ unicodeslot=0x24D8,
+ },
+ [0x24D9]={
+ adobename="jcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6A },
+ uccode=0x24BF,
+ unicodeslot=0x24D9,
+ },
+ [0x24DA]={
+ adobename="kcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6B },
+ uccode=0x24C0,
+ unicodeslot=0x24DA,
+ },
+ [0x24DB]={
+ adobename="lcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6C },
+ uccode=0x24C1,
+ unicodeslot=0x24DB,
+ },
+ [0x24DC]={
+ adobename="mcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6D },
+ uccode=0x24C2,
+ unicodeslot=0x24DC,
+ },
+ [0x24DD]={
+ adobename="ncircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6E },
+ uccode=0x24C3,
+ unicodeslot=0x24DD,
+ },
+ [0x24DE]={
+ adobename="ocircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x6F },
+ uccode=0x24C4,
+ unicodeslot=0x24DE,
+ },
+ [0x24DF]={
+ adobename="pcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x70 },
+ uccode=0x24C5,
+ unicodeslot=0x24DF,
+ },
+ [0x24E0]={
+ adobename="qcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x71 },
+ uccode=0x24C6,
+ unicodeslot=0x24E0,
+ },
+ [0x24E1]={
+ adobename="rcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x72 },
+ uccode=0x24C7,
+ unicodeslot=0x24E1,
+ },
+ [0x24E2]={
+ adobename="scircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x73 },
+ uccode=0x24C8,
+ unicodeslot=0x24E2,
+ },
+ [0x24E3]={
+ adobename="tcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x74 },
+ uccode=0x24C9,
+ unicodeslot=0x24E3,
+ },
+ [0x24E4]={
+ adobename="ucircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x75 },
+ uccode=0x24CA,
+ unicodeslot=0x24E4,
+ },
+ [0x24E5]={
+ adobename="vcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x76 },
+ uccode=0x24CB,
+ unicodeslot=0x24E5,
+ },
+ [0x24E6]={
+ adobename="wcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x77 },
+ uccode=0x24CC,
+ unicodeslot=0x24E6,
+ },
+ [0x24E7]={
+ adobename="xcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x78 },
+ uccode=0x24CD,
+ unicodeslot=0x24E7,
+ },
+ [0x24E8]={
+ adobename="ycircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x79 },
+ uccode=0x24CE,
+ unicodeslot=0x24E8,
+ },
+ [0x24E9]={
+ adobename="zcircle",
+ category="so",
+ cjkwd="a",
+ description="CIRCLED LATIN SMALL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x7A },
+ uccode=0x24CF,
+ unicodeslot=0x24E9,
+ },
+ [0x24EA]={
+ category="no",
+ description="CIRCLED DIGIT ZERO",
+ direction="on",
+ linebreak="ai",
+ specials={ "circle", 0x30 },
+ unicodeslot=0x24EA,
+ },
+ [0x24EB]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER ELEVEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24EB,
+ },
+ [0x24EC]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER TWELVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24EC,
+ },
+ [0x24ED]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER THIRTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24ED,
+ },
+ [0x24EE]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER FOURTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24EE,
+ },
+ [0x24EF]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER FIFTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24EF,
+ },
+ [0x24F0]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER SIXTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F0,
+ },
+ [0x24F1]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER SEVENTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F1,
+ },
+ [0x24F2]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER EIGHTEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F2,
+ },
+ [0x24F3]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER NINETEEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F3,
+ },
+ [0x24F4]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED NUMBER TWENTY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F4,
+ },
+ [0x24F5]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F5,
+ },
+ [0x24F6]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F6,
+ },
+ [0x24F7]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F7,
+ },
+ [0x24F8]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F8,
+ },
+ [0x24F9]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24F9,
+ },
+ [0x24FA]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24FA,
+ },
+ [0x24FB]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24FB,
+ },
+ [0x24FC]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24FC,
+ },
+ [0x24FD]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24FD,
+ },
+ [0x24FE]={
+ category="no",
+ cjkwd="a",
+ description="DOUBLE CIRCLED NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x24FE,
+ },
+ [0x24FF]={
+ category="no",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED DIGIT ZERO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x24FF,
+ },
+ [0x2500]={
+ adobename="SF100000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2500,
+ },
+ [0x2501]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2501,
+ },
+ [0x2502]={
+ adobename="SF110000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2502,
+ },
+ [0x2503]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2503,
+ },
+ [0x2504]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2504,
+ },
+ [0x2505]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2505,
+ },
+ [0x2506]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2506,
+ },
+ [0x2507]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2507,
+ },
+ [0x2508]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2508,
+ },
+ [0x2509]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2509,
+ },
+ [0x250A]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250A,
+ },
+ [0x250B]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250B,
+ },
+ [0x250C]={
+ adobename="SF010000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DOWN AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250C,
+ },
+ [0x250D]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250D,
+ },
+ [0x250E]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250E,
+ },
+ [0x250F]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY DOWN AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x250F,
+ },
+ [0x2510]={
+ adobename="SF030000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DOWN AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2510,
+ },
+ [0x2511]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2511,
+ },
+ [0x2512]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2512,
+ },
+ [0x2513]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY DOWN AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2513,
+ },
+ [0x2514]={
+ adobename="SF020000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT UP AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2514,
+ },
+ [0x2515]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND RIGHT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2515,
+ },
+ [0x2516]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND RIGHT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2516,
+ },
+ [0x2517]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY UP AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2517,
+ },
+ [0x2518]={
+ adobename="SF040000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT UP AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2518,
+ },
+ [0x2519]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND LEFT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2519,
+ },
+ [0x251A]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND LEFT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251A,
+ },
+ [0x251B]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY UP AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251B,
+ },
+ [0x251C]={
+ adobename="SF080000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT VERTICAL AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251C,
+ },
+ [0x251D]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251D,
+ },
+ [0x251E]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251E,
+ },
+ [0x251F]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x251F,
+ },
+ [0x2520]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2520,
+ },
+ [0x2521]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2521,
+ },
+ [0x2522]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2522,
+ },
+ [0x2523]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY VERTICAL AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2523,
+ },
+ [0x2524]={
+ adobename="SF090000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT VERTICAL AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2524,
+ },
+ [0x2525]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2525,
+ },
+ [0x2526]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2526,
+ },
+ [0x2527]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2527,
+ },
+ [0x2528]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2528,
+ },
+ [0x2529]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2529,
+ },
+ [0x252A]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252A,
+ },
+ [0x252B]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY VERTICAL AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252B,
+ },
+ [0x252C]={
+ adobename="SF060000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DOWN AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252C,
+ },
+ [0x252D]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252D,
+ },
+ [0x252E]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252E,
+ },
+ [0x252F]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x252F,
+ },
+ [0x2530]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2530,
+ },
+ [0x2531]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2531,
+ },
+ [0x2532]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2532,
+ },
+ [0x2533]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY DOWN AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2533,
+ },
+ [0x2534]={
+ adobename="SF070000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT UP AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2534,
+ },
+ [0x2535]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2535,
+ },
+ [0x2536]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2536,
+ },
+ [0x2537]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2537,
+ },
+ [0x2538]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2538,
+ },
+ [0x2539]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2539,
+ },
+ [0x253A]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253A,
+ },
+ [0x253B]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY UP AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253B,
+ },
+ [0x253C]={
+ adobename="SF050000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253C,
+ },
+ [0x253D]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253D,
+ },
+ [0x253E]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253E,
+ },
+ [0x253F]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x253F,
+ },
+ [0x2540]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2540,
+ },
+ [0x2541]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2541,
+ },
+ [0x2542]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2542,
+ },
+ [0x2543]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2543,
+ },
+ [0x2544]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2544,
+ },
+ [0x2545]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2545,
+ },
+ [0x2546]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2546,
+ },
+ [0x2547]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2547,
+ },
+ [0x2548]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2548,
+ },
+ [0x2549]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2549,
+ },
+ [0x254A]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x254A,
+ },
+ [0x254B]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x254B,
+ },
+ [0x254C]={
+ category="so",
+ description="BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x254C,
+ },
+ [0x254D]={
+ category="so",
+ description="BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x254D,
+ },
+ [0x254E]={
+ category="so",
+ description="BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x254E,
+ },
+ [0x254F]={
+ category="so",
+ description="BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x254F,
+ },
+ [0x2550]={
+ adobename="SF430000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2550,
+ },
+ [0x2551]={
+ adobename="SF240000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE VERTICAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2551,
+ },
+ [0x2552]={
+ adobename="SF510000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2552,
+ },
+ [0x2553]={
+ adobename="SF520000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2553,
+ },
+ [0x2554]={
+ adobename="SF390000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE DOWN AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2554,
+ },
+ [0x2555]={
+ adobename="SF220000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2555,
+ },
+ [0x2556]={
+ adobename="SF210000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2556,
+ },
+ [0x2557]={
+ adobename="SF250000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE DOWN AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2557,
+ },
+ [0x2558]={
+ adobename="SF500000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2558,
+ },
+ [0x2559]={
+ adobename="SF490000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2559,
+ },
+ [0x255A]={
+ adobename="SF380000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE UP AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255A,
+ },
+ [0x255B]={
+ adobename="SF280000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP SINGLE AND LEFT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255B,
+ },
+ [0x255C]={
+ adobename="SF270000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP DOUBLE AND LEFT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255C,
+ },
+ [0x255D]={
+ adobename="SF260000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE UP AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255D,
+ },
+ [0x255E]={
+ adobename="SF360000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255E,
+ },
+ [0x255F]={
+ adobename="SF370000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x255F,
+ },
+ [0x2560]={
+ adobename="SF420000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE VERTICAL AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2560,
+ },
+ [0x2561]={
+ adobename="SF190000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2561,
+ },
+ [0x2562]={
+ adobename="SF200000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2562,
+ },
+ [0x2563]={
+ adobename="SF230000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE VERTICAL AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2563,
+ },
+ [0x2564]={
+ adobename="SF470000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2564,
+ },
+ [0x2565]={
+ adobename="SF480000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2565,
+ },
+ [0x2566]={
+ adobename="SF410000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2566,
+ },
+ [0x2567]={
+ adobename="SF450000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2567,
+ },
+ [0x2568]={
+ adobename="SF460000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2568,
+ },
+ [0x2569]={
+ adobename="SF400000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE UP AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2569,
+ },
+ [0x256A]={
+ adobename="SF540000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256A,
+ },
+ [0x256B]={
+ adobename="SF530000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256B,
+ },
+ [0x256C]={
+ adobename="SF440000",
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256C,
+ },
+ [0x256D]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT ARC DOWN AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256D,
+ },
+ [0x256E]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT ARC DOWN AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256E,
+ },
+ [0x256F]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT ARC UP AND LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x256F,
+ },
+ [0x2570]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT ARC UP AND RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2570,
+ },
+ [0x2571]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2571,
+ },
+ [0x2572]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2572,
+ },
+ [0x2573]={
+ category="so",
+ cjkwd="a",
+ description="BOX DRAWINGS LIGHT DIAGONAL CROSS",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2573,
+ },
+ [0x2574]={
+ category="so",
+ description="BOX DRAWINGS LIGHT LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2574,
+ },
+ [0x2575]={
+ category="so",
+ description="BOX DRAWINGS LIGHT UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2575,
+ },
+ [0x2576]={
+ category="so",
+ description="BOX DRAWINGS LIGHT RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2576,
+ },
+ [0x2577]={
+ category="so",
+ description="BOX DRAWINGS LIGHT DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2577,
+ },
+ [0x2578]={
+ category="so",
+ description="BOX DRAWINGS HEAVY LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2578,
+ },
+ [0x2579]={
+ category="so",
+ description="BOX DRAWINGS HEAVY UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2579,
+ },
+ [0x257A]={
+ category="so",
+ description="BOX DRAWINGS HEAVY RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257A,
+ },
+ [0x257B]={
+ category="so",
+ description="BOX DRAWINGS HEAVY DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257B,
+ },
+ [0x257C]={
+ category="so",
+ description="BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257C,
+ },
+ [0x257D]={
+ category="so",
+ description="BOX DRAWINGS LIGHT UP AND HEAVY DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257D,
+ },
+ [0x257E]={
+ category="so",
+ description="BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257E,
+ },
+ [0x257F]={
+ category="so",
+ description="BOX DRAWINGS HEAVY UP AND LIGHT DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x257F,
+ },
+ [0x2580]={
+ adobename="upblock",
+ category="so",
+ cjkwd="a",
+ description="UPPER HALF BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2580,
+ },
+ [0x2581]={
+ category="so",
+ cjkwd="a",
+ description="LOWER ONE EIGHTH BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2581,
+ },
+ [0x2582]={
+ category="so",
+ cjkwd="a",
+ description="LOWER ONE QUARTER BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2582,
+ },
+ [0x2583]={
+ category="so",
+ cjkwd="a",
+ description="LOWER THREE EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2583,
+ },
+ [0x2584]={
+ adobename="dnblock",
+ category="so",
+ cjkwd="a",
+ description="LOWER HALF BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2584,
+ },
+ [0x2585]={
+ category="so",
+ cjkwd="a",
+ description="LOWER FIVE EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2585,
+ },
+ [0x2586]={
+ category="so",
+ cjkwd="a",
+ description="LOWER THREE QUARTERS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2586,
+ },
+ [0x2587]={
+ category="so",
+ cjkwd="a",
+ description="LOWER SEVEN EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2587,
+ },
+ [0x2588]={
+ adobename="block",
+ category="so",
+ cjkwd="a",
+ description="FULL BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2588,
+ },
+ [0x2589]={
+ category="so",
+ cjkwd="a",
+ description="LEFT SEVEN EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2589,
+ },
+ [0x258A]={
+ category="so",
+ cjkwd="a",
+ description="LEFT THREE QUARTERS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258A,
+ },
+ [0x258B]={
+ category="so",
+ cjkwd="a",
+ description="LEFT FIVE EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258B,
+ },
+ [0x258C]={
+ adobename="lfblock",
+ category="so",
+ cjkwd="a",
+ description="LEFT HALF BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258C,
+ },
+ [0x258D]={
+ category="so",
+ cjkwd="a",
+ description="LEFT THREE EIGHTHS BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258D,
+ },
+ [0x258E]={
+ category="so",
+ cjkwd="a",
+ description="LEFT ONE QUARTER BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258E,
+ },
+ [0x258F]={
+ category="so",
+ cjkwd="a",
+ description="LEFT ONE EIGHTH BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x258F,
+ },
+ [0x2590]={
+ adobename="rtblock",
+ category="so",
+ description="RIGHT HALF BLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2590,
+ },
+ [0x2591]={
+ adobename="shadelight",
+ category="so",
+ description="LIGHT SHADE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2591,
+ },
+ [0x2592]={
+ adobename="shademedium",
+ category="so",
+ cjkwd="a",
+ description="MEDIUM SHADE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2592,
+ },
+ [0x2593]={
+ adobename="shadedark",
+ category="so",
+ cjkwd="a",
+ description="DARK SHADE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2593,
+ },
+ [0x2594]={
+ category="so",
+ cjkwd="a",
+ description="UPPER ONE EIGHTH BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2594,
+ },
+ [0x2595]={
+ category="so",
+ cjkwd="a",
+ description="RIGHT ONE EIGHTH BLOCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2595,
+ },
+ [0x2596]={
+ category="so",
+ description="QUADRANT LOWER LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2596,
+ },
+ [0x2597]={
+ category="so",
+ description="QUADRANT LOWER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2597,
+ },
+ [0x2598]={
+ category="so",
+ description="QUADRANT UPPER LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2598,
+ },
+ [0x2599]={
+ category="so",
+ description="QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2599,
+ },
+ [0x259A]={
+ category="so",
+ description="QUADRANT UPPER LEFT AND LOWER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259A,
+ },
+ [0x259B]={
+ category="so",
+ description="QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259B,
+ },
+ [0x259C]={
+ category="so",
+ description="QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259C,
+ },
+ [0x259D]={
+ category="so",
+ description="QUADRANT UPPER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259D,
+ },
+ [0x259E]={
+ category="so",
+ description="QUADRANT UPPER RIGHT AND LOWER LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259E,
+ },
+ [0x259F]={
+ category="so",
+ description="QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x259F,
+ },
+ [0x25A0]={
+ adobename="filledbox",
+ category="so",
+ cjkwd="a",
+ description="BLACK SQUARE",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="blacksquare",
+ unicodeslot=0x25A0,
+ },
+ [0x25A1]={
+ adobename="whitesquare",
+ category="so",
+ cjkwd="a",
+ description="WHITE SQUARE",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="ordinary",
+ name="square",
+ },
+ {
+ class="ordinary",
+ name="Box",
+ },
+ },
+ unicodeslot=0x25A1,
+ },
+ [0x25A2]={
+ category="so",
+ description="WHITE SQUARE WITH ROUNDED CORNERS",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ unicodeslot=0x25A2,
+ },
+ [0x25A3]={
+ adobename="squarewhitewithsmallblack",
+ category="so",
+ cjkwd="a",
+ description="WHITE SQUARE CONTAINING BLACK SMALL SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A3,
+ },
+ [0x25A4]={
+ adobename="squarehorizontalfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH HORIZONTAL FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A4,
+ },
+ [0x25A5]={
+ adobename="squareverticalfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH VERTICAL FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A5,
+ },
+ [0x25A6]={
+ adobename="squareorthogonalcrosshatchfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH ORTHOGONAL CROSSHATCH FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A6,
+ },
+ [0x25A7]={
+ adobename="squareupperlefttolowerrightfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A7,
+ },
+ [0x25A8]={
+ adobename="squareupperrighttolowerleftfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A8,
+ },
+ [0x25A9]={
+ adobename="squarediagonalcrosshatchfill",
+ category="so",
+ cjkwd="a",
+ description="SQUARE WITH DIAGONAL CROSSHATCH FILL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25A9,
+ },
+ [0x25AA]={
+ adobename="blacksmallsquare",
+ category="so",
+ description="BLACK SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25AB]={
+ adobename="whitesmallsquare",
+ category="so",
+ description="WHITE SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25AC]={
+ adobename="filledrect",
+ category="so",
+ description="BLACK RECTANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AC,
+ },
+ [0x25AD]={
+ category="so",
+ description="WHITE RECTANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AD,
+ },
+ [0x25AE]={
+ category="so",
+ description="BLACK VERTICAL RECTANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AE,
+ },
+ [0x25AF]={
+ category="so",
+ description="WHITE VERTICAL RECTANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25AF,
+ },
+ [0x25B0]={
+ category="so",
+ description="BLACK PARALLELOGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B0,
+ },
+ [0x25B1]={
+ category="so",
+ description="WHITE PARALLELOGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B1,
+ },
+ [0x25B2]={
+ adobename="triagup",
+ category="so",
+ cjkwd="a",
+ description="BLACK UP-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangle",
+ unicodeslot=0x25B2,
+ },
+ [0x25B3]={
+ adobename="whiteuppointingtriangle",
+ category="so",
+ cjkwd="a",
+ description="WHITE UP-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="ordinary",
+ name="triangle",
+ },
+ {
+ class="binary",
+ name="bigtriangleup",
+ },
+ },
+ unicodeslot=0x25B3,
+ },
+ [0x25B4]={
+ adobename="blackuppointingsmalltriangle",
+ category="so",
+ description="BLACK UP-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B4,
+ },
+ [0x25B5]={
+ adobename="whiteuppointingsmalltriangle",
+ category="so",
+ description="WHITE UP-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B5,
+ },
+ [0x25B6]={
+ adobename="blackrightpointingtriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK RIGHT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangleright",
+ unicodeslot=0x25B6,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25B7]={
+ adobename="whiterightpointingtriangle",
+ category="sm",
+ cjkwd="a",
+ description="WHITE RIGHT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="triangleright",
+ unicodeslot=0x25B7,
+ },
+ [0x25B8]={
+ category="so",
+ description="BLACK RIGHT-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B8,
+ },
+ [0x25B9]={
+ adobename="whiterightpointingsmalltriangle",
+ category="so",
+ description="WHITE RIGHT-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25B9,
+ },
+ [0x25BA]={
+ adobename="triagrt",
+ category="so",
+ description="BLACK RIGHT-POINTING POINTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25BA,
+ },
+ [0x25BB]={
+ category="so",
+ description="WHITE RIGHT-POINTING POINTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25BB,
+ },
+ [0x25BC]={
+ adobename="triagdn",
+ category="so",
+ cjkwd="a",
+ description="BLACK DOWN-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangledown",
+ unicodeslot=0x25BC,
+ },
+ [0x25BD]={
+ adobename="whitedownpointingtriangle",
+ category="so",
+ cjkwd="a",
+ description="WHITE DOWN-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathspec={
+ {
+ class="binary",
+ name="triangledown",
+ },
+ {
+ class="binary",
+ name="bigtriangledown",
+ },
+ },
+ unicodeslot=0x25BD,
+ },
+ [0x25BE]={
+ category="so",
+ description="BLACK DOWN-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25BE,
+ },
+ [0x25BF]={
+ adobename="whitedownpointingsmalltriangle",
+ category="so",
+ description="WHITE DOWN-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25BF,
+ },
+ [0x25C0]={
+ adobename="blackleftpointingtriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK LEFT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangleleft",
+ unicodeslot=0x25C0,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25C1]={
+ adobename="whiteleftpointingtriangle",
+ category="sm",
+ cjkwd="a",
+ description="WHITE LEFT-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="triangleleft",
+ unicodeslot=0x25C1,
+ },
+ [0x25C2]={
+ category="so",
+ description="BLACK LEFT-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25C2,
+ },
+ [0x25C3]={
+ adobename="whiteleftpointingsmalltriangle",
+ category="so",
+ description="WHITE LEFT-POINTING SMALL TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25C3,
+ },
+ [0x25C4]={
+ adobename="triaglf",
+ category="so",
+ description="BLACK LEFT-POINTING POINTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25C4,
+ },
+ [0x25C5]={
+ category="so",
+ description="WHITE LEFT-POINTING POINTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25C5,
+ },
+ [0x25C6]={
+ adobename="blackdiamond",
+ category="so",
+ cjkwd="a",
+ description="BLACK DIAMOND",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25C6,
+ },
+ [0x25C7]={
+ adobename="whitediamond",
+ category="so",
+ cjkwd="a",
+ description="WHITE DIAMOND",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25C7,
+ },
+ [0x25C8]={
+ adobename="whitediamondcontainingblacksmalldiamond",
+ category="so",
+ cjkwd="a",
+ description="WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25C8,
+ },
+ [0x25C9]={
+ adobename="fisheye",
+ category="so",
+ description="FISHEYE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25C9,
+ },
+ [0x25CA]={
+ adobename="lozenge",
+ category="so",
+ description="LOZENGE",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="lozenge",
+ unicodeslot=0x25CA,
+ },
+ [0x25CB]={
+ adobename="whitecircle",
+ category="so",
+ cjkwd="a",
+ description="WHITE CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25CB,
+ },
+ [0x25CC]={
+ adobename="dottedcircle",
+ category="so",
+ description="DOTTED CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25CC,
+ },
+ [0x25CD]={
+ category="so",
+ description="CIRCLE WITH VERTICAL FILL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25CD,
+ },
+ [0x25CE]={
+ adobename="bullseye",
+ category="so",
+ cjkwd="a",
+ description="BULLSEYE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25CE,
+ },
+ [0x25CF]={
+ adobename="blackcircle",
+ category="so",
+ cjkwd="a",
+ description="BLACK CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25CF,
+ },
+ [0x25D0]={
+ adobename="circlewithlefthalfblack",
+ category="so",
+ cjkwd="a",
+ description="CIRCLE WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25D0,
+ },
+ [0x25D1]={
+ adobename="circlewithrighthalfblack",
+ category="so",
+ cjkwd="a",
+ description="CIRCLE WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25D1,
+ },
+ [0x25D2]={
+ category="so",
+ description="CIRCLE WITH LOWER HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D2,
+ },
+ [0x25D3]={
+ category="so",
+ description="CIRCLE WITH UPPER HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D3,
+ },
+ [0x25D4]={
+ category="so",
+ description="CIRCLE WITH UPPER RIGHT QUADRANT BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D4,
+ },
+ [0x25D5]={
+ category="so",
+ description="CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D5,
+ },
+ [0x25D6]={
+ category="so",
+ description="LEFT HALF BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D6,
+ },
+ [0x25D7]={
+ category="so",
+ description="RIGHT HALF BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D7,
+ },
+ [0x25D8]={
+ adobename="invbullet",
+ category="so",
+ description="INVERSE BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D8,
+ },
+ [0x25D9]={
+ adobename="whitecircleinverse",
+ category="so",
+ description="INVERSE WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25D9,
+ },
+ [0x25DA]={
+ category="so",
+ description="UPPER HALF INVERSE WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DA,
+ },
+ [0x25DB]={
+ category="so",
+ description="LOWER HALF INVERSE WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DB,
+ },
+ [0x25DC]={
+ category="so",
+ description="UPPER LEFT QUADRANT CIRCULAR ARC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DC,
+ },
+ [0x25DD]={
+ category="so",
+ description="UPPER RIGHT QUADRANT CIRCULAR ARC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DD,
+ },
+ [0x25DE]={
+ category="so",
+ description="LOWER RIGHT QUADRANT CIRCULAR ARC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DE,
+ },
+ [0x25DF]={
+ category="so",
+ description="LOWER LEFT QUADRANT CIRCULAR ARC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25DF,
+ },
+ [0x25E0]={
+ category="so",
+ description="UPPER HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E0,
+ },
+ [0x25E1]={
+ category="so",
+ description="LOWER HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E1,
+ },
+ [0x25E2]={
+ adobename="blacklowerrighttriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK LOWER RIGHT TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25E2,
+ },
+ [0x25E3]={
+ adobename="blacklowerlefttriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK LOWER LEFT TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25E3,
+ },
+ [0x25E4]={
+ adobename="blackupperlefttriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK UPPER LEFT TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25E4,
+ },
+ [0x25E5]={
+ adobename="blackupperrighttriangle",
+ category="so",
+ cjkwd="a",
+ description="BLACK UPPER RIGHT TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x25E5,
+ },
+ [0x25E6]={
+ adobename="whitebullet",
+ category="so",
+ description="WHITE BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E6,
+ },
+ [0x25E7]={
+ category="so",
+ description="SQUARE WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E7,
+ },
+ [0x25E8]={
+ category="so",
+ description="SQUARE WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E8,
+ },
+ [0x25E9]={
+ category="so",
+ description="SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25E9,
+ },
+ [0x25EA]={
+ category="so",
+ description="SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25EA,
+ },
+ [0x25EB]={
+ category="so",
+ description="WHITE SQUARE WITH VERTICAL BISECTING LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25EB,
+ },
+ [0x25EC]={
+ category="so",
+ description="WHITE UP-POINTING TRIANGLE WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25EC,
+ },
+ [0x25ED]={
+ category="so",
+ description="UP-POINTING TRIANGLE WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25ED,
+ },
+ [0x25EE]={
+ category="so",
+ description="UP-POINTING TRIANGLE WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25EE,
+ },
+ [0x25EF]={
+ adobename="largecircle",
+ category="so",
+ cjkwd="a",
+ description="LARGE CIRCLE",
+ direction="on",
+ linebreak="ai",
+ mathclass="binary",
+ mathname="bigcirc",
+ unicodeslot=0x25EF,
+ },
+ [0x25F0]={
+ category="so",
+ description="WHITE SQUARE WITH UPPER LEFT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F0,
+ },
+ [0x25F1]={
+ category="so",
+ description="WHITE SQUARE WITH LOWER LEFT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F1,
+ },
+ [0x25F2]={
+ category="so",
+ description="WHITE SQUARE WITH LOWER RIGHT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F2,
+ },
+ [0x25F3]={
+ category="so",
+ description="WHITE SQUARE WITH UPPER RIGHT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F3,
+ },
+ [0x25F4]={
+ category="so",
+ description="WHITE CIRCLE WITH UPPER LEFT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F4,
+ },
+ [0x25F5]={
+ category="so",
+ description="WHITE CIRCLE WITH LOWER LEFT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F5,
+ },
+ [0x25F6]={
+ category="so",
+ description="WHITE CIRCLE WITH LOWER RIGHT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F6,
+ },
+ [0x25F7]={
+ category="so",
+ description="WHITE CIRCLE WITH UPPER RIGHT QUADRANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F7,
+ },
+ [0x25F8]={
+ category="sm",
+ description="UPPER LEFT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F8,
+ },
+ [0x25F9]={
+ category="sm",
+ description="UPPER RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25F9,
+ },
+ [0x25FA]={
+ category="sm",
+ description="LOWER LEFT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FA,
+ },
+ [0x25FB]={
+ category="sm",
+ description="WHITE MEDIUM SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25FC]={
+ category="sm",
+ description="BLACK MEDIUM SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FC,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25FD]={
+ category="sm",
+ description="WHITE MEDIUM SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25FE]={
+ category="sm",
+ description="BLACK MEDIUM SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FE,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x25FF]={
+ category="sm",
+ description="LOWER RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x25FF,
+ },
+ [0x2600]={
+ category="so",
+ description="BLACK SUN WITH RAYS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2600,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2601]={
+ category="so",
+ description="CLOUD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2601,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2602]={
+ category="so",
+ description="UMBRELLA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2602,
+ },
+ [0x2603]={
+ category="so",
+ description="SNOWMAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2603,
+ },
+ [0x2604]={
+ category="so",
+ description="COMET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2604,
+ },
+ [0x2605]={
+ adobename="blackstar",
+ category="so",
+ cjkwd="a",
+ description="BLACK STAR",
+ direction="on",
+ linebreak="ai",
+ mathclass="ordinary",
+ mathname="bigstar",
+ unicodeslot=0x2605,
+ },
+ [0x2606]={
+ adobename="whitestar",
+ category="so",
+ cjkwd="a",
+ description="WHITE STAR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2606,
+ },
+ [0x2607]={
+ category="so",
+ description="LIGHTNING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2607,
+ },
+ [0x2608]={
+ category="so",
+ description="THUNDERSTORM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2608,
+ },
+ [0x2609]={
+ category="so",
+ cjkwd="a",
+ description="SUN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2609,
+ },
+ [0x260A]={
+ category="so",
+ description="ASCENDING NODE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x260A,
+ },
+ [0x260B]={
+ category="so",
+ description="DESCENDING NODE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x260B,
+ },
+ [0x260C]={
+ category="so",
+ description="CONJUNCTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x260C,
+ },
+ [0x260D]={
+ category="so",
+ description="OPPOSITION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x260D,
+ },
+ [0x260E]={
+ adobename="telephoneblack",
+ category="so",
+ cjkwd="a",
+ description="BLACK TELEPHONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x260E,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x260F]={
+ adobename="whitetelephone",
+ category="so",
+ cjkwd="a",
+ description="WHITE TELEPHONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x260F,
+ },
+ [0x2610]={
+ category="so",
+ description="BALLOT BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2610,
+ },
+ [0x2611]={
+ category="so",
+ description="BALLOT BOX WITH CHECK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2611,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2612]={
+ category="so",
+ description="BALLOT BOX WITH X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2612,
+ },
+ [0x2613]={
+ category="so",
+ description="SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2613,
+ },
+ [0x2614]={
+ category="so",
+ cjkwd="a",
+ description="UMBRELLA WITH RAIN DROPS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2614,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2615]={
+ category="so",
+ cjkwd="a",
+ description="HOT BEVERAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2615,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2616]={
+ category="so",
+ description="WHITE SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2616,
+ },
+ [0x2617]={
+ category="so",
+ description="BLACK SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2617,
+ },
+ [0x2618]={
+ category="so",
+ description="SHAMROCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2618,
+ },
+ [0x2619]={
+ category="so",
+ description="REVERSED ROTATED FLORAL HEART BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2619,
+ },
+ [0x261A]={
+ category="so",
+ description="BLACK LEFT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261A,
+ },
+ [0x261B]={
+ category="so",
+ description="BLACK RIGHT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261B,
+ },
+ [0x261C]={
+ adobename="pointingindexleftwhite",
+ category="so",
+ cjkwd="a",
+ description="WHITE LEFT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261C,
+ },
+ [0x261D]={
+ adobename="pointingindexupwhite",
+ category="so",
+ description="WHITE UP POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x261E]={
+ adobename="pointingindexrightwhite",
+ category="so",
+ cjkwd="a",
+ description="WHITE RIGHT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261E,
+ },
+ [0x261F]={
+ adobename="pointingindexdownwhite",
+ category="so",
+ description="WHITE DOWN POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x261F,
+ },
+ [0x2620]={
+ category="so",
+ description="SKULL AND CROSSBONES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2620,
+ },
+ [0x2621]={
+ category="so",
+ description="CAUTION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2621,
+ },
+ [0x2622]={
+ category="so",
+ description="RADIOACTIVE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2622,
+ },
+ [0x2623]={
+ category="so",
+ description="BIOHAZARD SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2623,
+ },
+ [0x2624]={
+ category="so",
+ description="CADUCEUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2624,
+ },
+ [0x2625]={
+ category="so",
+ description="ANKH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2625,
+ },
+ [0x2626]={
+ category="so",
+ description="ORTHODOX CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2626,
+ },
+ [0x2627]={
+ category="so",
+ description="CHI RHO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2627,
+ },
+ [0x2628]={
+ category="so",
+ description="CROSS OF LORRAINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2628,
+ },
+ [0x2629]={
+ category="so",
+ description="CROSS OF JERUSALEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2629,
+ },
+ [0x262A]={
+ category="so",
+ description="STAR AND CRESCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262A,
+ },
+ [0x262B]={
+ category="so",
+ description="FARSI SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262B,
+ },
+ [0x262C]={
+ category="so",
+ description="ADI SHAKTI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262C,
+ },
+ [0x262D]={
+ category="so",
+ description="HAMMER AND SICKLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262D,
+ },
+ [0x262E]={
+ category="so",
+ description="PEACE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262E,
+ },
+ [0x262F]={
+ adobename="yinyang",
+ category="so",
+ description="YIN YANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x262F,
+ },
+ [0x2630]={
+ category="so",
+ description="TRIGRAM FOR HEAVEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2630,
+ },
+ [0x2631]={
+ category="so",
+ description="TRIGRAM FOR LAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2631,
+ },
+ [0x2632]={
+ category="so",
+ description="TRIGRAM FOR FIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2632,
+ },
+ [0x2633]={
+ category="so",
+ description="TRIGRAM FOR THUNDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2633,
+ },
+ [0x2634]={
+ category="so",
+ description="TRIGRAM FOR WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2634,
+ },
+ [0x2635]={
+ category="so",
+ description="TRIGRAM FOR WATER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2635,
+ },
+ [0x2636]={
+ category="so",
+ description="TRIGRAM FOR MOUNTAIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2636,
+ },
+ [0x2637]={
+ category="so",
+ description="TRIGRAM FOR EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2637,
+ },
+ [0x2638]={
+ category="so",
+ description="WHEEL OF DHARMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2638,
+ },
+ [0x2639]={
+ category="so",
+ description="WHITE FROWNING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2639,
+ },
+ [0x263A]={
+ adobename="whitesmilingface",
+ category="so",
+ description="WHITE SMILING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x263A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x263B]={
+ adobename="invsmileface",
+ category="so",
+ description="BLACK SMILING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x263B,
+ },
+ [0x263C]={
+ adobename="sun",
+ category="so",
+ description="WHITE SUN WITH RAYS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x263C,
+ },
+ [0x263D]={
+ category="so",
+ description="FIRST QUARTER MOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x263D,
+ },
+ [0x263E]={
+ category="so",
+ description="LAST QUARTER MOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x263E,
+ },
+ [0x263F]={
+ category="so",
+ description="MERCURY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x263F,
+ },
+ [0x2640]={
+ adobename="venus",
+ category="so",
+ cjkwd="a",
+ description="FEMALE SIGN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2640,
+ },
+ [0x2641]={
+ adobename="earth",
+ category="so",
+ description="EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2641,
+ },
+ [0x2642]={
+ adobename="mars",
+ category="so",
+ cjkwd="a",
+ description="MALE SIGN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2642,
+ },
+ [0x2643]={
+ category="so",
+ description="JUPITER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2643,
+ },
+ [0x2644]={
+ category="so",
+ description="SATURN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2644,
+ },
+ [0x2645]={
+ category="so",
+ description="URANUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2645,
+ },
+ [0x2646]={
+ category="so",
+ description="NEPTUNE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2646,
+ },
+ [0x2647]={
+ category="so",
+ description="PLUTO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2647,
+ },
+ [0x2648]={
+ category="so",
+ description="ARIES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2648,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2649]={
+ category="so",
+ description="TAURUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2649,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264A]={
+ category="so",
+ description="GEMINI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264B]={
+ category="so",
+ description="CANCER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264C]={
+ category="so",
+ description="LEO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264D]={
+ category="so",
+ description="VIRGO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264E]={
+ category="so",
+ description="LIBRA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264E,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x264F]={
+ category="so",
+ description="SCORPIUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x264F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2650]={
+ category="so",
+ description="SAGITTARIUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2650,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2651]={
+ category="so",
+ description="CAPRICORN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2651,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2652]={
+ category="so",
+ description="AQUARIUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2652,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2653]={
+ category="so",
+ description="PISCES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2653,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2654]={
+ category="so",
+ description="WHITE CHESS KING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2654,
+ },
+ [0x2655]={
+ category="so",
+ description="WHITE CHESS QUEEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2655,
+ },
+ [0x2656]={
+ category="so",
+ description="WHITE CHESS ROOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2656,
+ },
+ [0x2657]={
+ category="so",
+ description="WHITE CHESS BISHOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2657,
+ },
+ [0x2658]={
+ category="so",
+ description="WHITE CHESS KNIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2658,
+ },
+ [0x2659]={
+ category="so",
+ description="WHITE CHESS PAWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2659,
+ },
+ [0x265A]={
+ category="so",
+ description="BLACK CHESS KING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265A,
+ },
+ [0x265B]={
+ category="so",
+ description="BLACK CHESS QUEEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265B,
+ },
+ [0x265C]={
+ category="so",
+ description="BLACK CHESS ROOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265C,
+ },
+ [0x265D]={
+ category="so",
+ description="BLACK CHESS BISHOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265D,
+ },
+ [0x265E]={
+ category="so",
+ description="BLACK CHESS KNIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265E,
+ },
+ [0x265F]={
+ category="so",
+ description="BLACK CHESS PAWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x265F,
+ },
+ [0x2660]={
+ adobename="spadesuitblack",
+ category="so",
+ cjkwd="a",
+ description="BLACK SPADE SUIT",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="spadesuit",
+ unicodeslot=0x2660,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2661]={
+ adobename="heartsuitwhite",
+ category="so",
+ cjkwd="a",
+ description="WHITE HEART SUIT",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="heartsuit",
+ unicodeslot=0x2661,
+ },
+ [0x2662]={
+ adobename="diamondsuitwhite",
+ category="so",
+ description="WHITE DIAMOND SUIT",
+ direction="on",
+ linebreak="al",
+ mathclass="default",
+ mathname="diamondsuit",
+ unicodeslot=0x2662,
+ },
+ [0x2663]={
+ adobename="clubsuitblack",
+ category="so",
+ cjkwd="a",
+ description="BLACK CLUB SUIT",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="clubsuit",
+ unicodeslot=0x2663,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2664]={
+ adobename="spadesuitwhite",
+ category="so",
+ cjkwd="a",
+ description="WHITE SPADE SUIT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2664,
+ },
+ [0x2665]={
+ adobename="heartsuitblack",
+ category="so",
+ cjkwd="a",
+ description="BLACK HEART SUIT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2665,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2666]={
+ adobename="diamond",
+ category="so",
+ description="BLACK DIAMOND SUIT",
+ direction="on",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="blacklozenge",
+ unicodeslot=0x2666,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2667]={
+ adobename="clubsuitwhite",
+ category="so",
+ cjkwd="a",
+ description="WHITE CLUB SUIT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2667,
+ },
+ [0x2668]={
+ adobename="hotsprings",
+ category="so",
+ cjkwd="a",
+ description="HOT SPRINGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2668,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2669]={
+ adobename="quarternote",
+ category="so",
+ cjkwd="a",
+ description="QUARTER NOTE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2669,
+ },
+ [0x266A]={
+ adobename="musicalnote",
+ category="so",
+ cjkwd="a",
+ description="EIGHTH NOTE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x266A,
+ },
+ [0x266B]={
+ adobename="musicalnotedbl",
+ category="so",
+ description="BEAMED EIGHTH NOTES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x266B,
+ },
+ [0x266C]={
+ adobename="beamedsixteenthnotes",
+ category="so",
+ cjkwd="a",
+ description="BEAMED SIXTEENTH NOTES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x266C,
+ },
+ [0x266D]={
+ adobename="musicflatsign",
+ category="so",
+ cjkwd="a",
+ description="MUSIC FLAT SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="flat",
+ unicodeslot=0x266D,
+ },
+ [0x266E]={
+ category="so",
+ description="MUSIC NATURAL SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="default",
+ mathname="natural",
+ unicodeslot=0x266E,
+ },
+ [0x266F]={
+ adobename="musicsharpsign",
+ category="sm",
+ cjkwd="a",
+ description="MUSIC SHARP SIGN",
+ direction="on",
+ linebreak="ai",
+ mathclass="default",
+ mathname="sharp",
+ unicodeslot=0x266F,
+ },
+ [0x2670]={
+ category="so",
+ description="WEST SYRIAC CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2670,
+ },
+ [0x2671]={
+ category="so",
+ description="EAST SYRIAC CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2671,
+ },
+ [0x2672]={
+ category="so",
+ description="UNIVERSAL RECYCLING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2672,
+ },
+ [0x2673]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0001 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2673,
+ },
+ [0x2674]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0002 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2674,
+ },
+ [0x2675]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0003 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2675,
+ },
+ [0x2676]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0004 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2676,
+ },
+ [0x2677]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0005 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2677,
+ },
+ [0x2678]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0006 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2678,
+ },
+ [0x2679]={
+ category="so",
+ description="RECYCLING SYMBOL FOR TYPE-0x0007 PLASTICS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2679,
+ },
+ [0x267A]={
+ category="so",
+ description="RECYCLING SYMBOL FOR GENERIC MATERIALS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x267A,
+ },
+ [0x267B]={
+ category="so",
+ description="BLACK UNIVERSAL RECYCLING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x267B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x267C]={
+ category="so",
+ description="RECYCLED PAPER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x267C,
+ },
+ [0x267D]={
+ category="so",
+ description="PARTIALLY-RECYCLED PAPER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x267D,
+ },
+ [0x267E]={
+ category="so",
+ description="PERMANENT PAPER SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x267E,
+ },
+ [0x267F]={
+ category="so",
+ description="WHEELCHAIR SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x267F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2680]={
+ category="so",
+ description="DIE FACE-0x0001",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2680,
+ },
+ [0x2681]={
+ category="so",
+ description="DIE FACE-0x0002",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2681,
+ },
+ [0x2682]={
+ category="so",
+ description="DIE FACE-0x0003",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2682,
+ },
+ [0x2683]={
+ category="so",
+ description="DIE FACE-0x0004",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2683,
+ },
+ [0x2684]={
+ category="so",
+ description="DIE FACE-0x0005",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2684,
+ },
+ [0x2685]={
+ category="so",
+ description="DIE FACE-0x0006",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2685,
+ },
+ [0x2686]={
+ category="so",
+ description="WHITE CIRCLE WITH DOT RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2686,
+ },
+ [0x2687]={
+ category="so",
+ description="WHITE CIRCLE WITH TWO DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2687,
+ },
+ [0x2688]={
+ category="so",
+ description="BLACK CIRCLE WITH WHITE DOT RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2688,
+ },
+ [0x2689]={
+ category="so",
+ description="BLACK CIRCLE WITH TWO WHITE DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2689,
+ },
+ [0x268A]={
+ category="so",
+ description="MONOGRAM FOR YANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268A,
+ },
+ [0x268B]={
+ category="so",
+ description="MONOGRAM FOR YIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268B,
+ },
+ [0x268C]={
+ category="so",
+ description="DIGRAM FOR GREATER YANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268C,
+ },
+ [0x268D]={
+ category="so",
+ description="DIGRAM FOR LESSER YIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268D,
+ },
+ [0x268E]={
+ category="so",
+ description="DIGRAM FOR LESSER YANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268E,
+ },
+ [0x268F]={
+ category="so",
+ description="DIGRAM FOR GREATER YIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x268F,
+ },
+ [0x2690]={
+ category="so",
+ description="WHITE FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2690,
+ },
+ [0x2691]={
+ category="so",
+ description="BLACK FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2691,
+ },
+ [0x2692]={
+ category="so",
+ description="HAMMER AND PICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2692,
+ },
+ [0x2693]={
+ category="so",
+ description="ANCHOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2693,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2694]={
+ category="so",
+ description="CROSSED SWORDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2694,
+ },
+ [0x2695]={
+ category="so",
+ description="STAFF OF AESCULAPIUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2695,
+ },
+ [0x2696]={
+ category="so",
+ description="SCALES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2696,
+ },
+ [0x2697]={
+ category="so",
+ description="ALEMBIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2697,
+ },
+ [0x2698]={
+ category="so",
+ description="FLOWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2698,
+ },
+ [0x2699]={
+ category="so",
+ description="GEAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2699,
+ },
+ [0x269A]={
+ category="so",
+ description="STAFF OF HERMES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x269A,
+ },
+ [0x269B]={
+ category="so",
+ description="ATOM SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x269B,
+ },
+ [0x269C]={
+ category="so",
+ description="FLEUR-DE-LIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x269C,
+ },
+ [0x269D]={
+ category="so",
+ description="OUTLINED WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x269D,
+ },
+ [0x269E]={
+ category="so",
+ cjkwd="a",
+ description="THREE LINES CONVERGING RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x269E,
+ },
+ [0x269F]={
+ category="so",
+ cjkwd="a",
+ description="THREE LINES CONVERGING LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x269F,
+ },
+ [0x26A0]={
+ category="so",
+ description="WARNING SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A0,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26A1]={
+ category="so",
+ description="HIGH VOLTAGE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A1,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26A2]={
+ category="so",
+ description="DOUBLED FEMALE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A2,
+ },
+ [0x26A3]={
+ category="so",
+ description="DOUBLED MALE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A3,
+ },
+ [0x26A4]={
+ category="so",
+ description="INTERLOCKED FEMALE AND MALE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A4,
+ },
+ [0x26A5]={
+ category="so",
+ description="MALE AND FEMALE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A5,
+ },
+ [0x26A6]={
+ category="so",
+ description="MALE WITH STROKE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A6,
+ },
+ [0x26A7]={
+ category="so",
+ description="MALE WITH STROKE AND MALE AND FEMALE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A7,
+ },
+ [0x26A8]={
+ category="so",
+ description="VERTICAL MALE WITH STROKE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A8,
+ },
+ [0x26A9]={
+ category="so",
+ description="HORIZONTAL MALE WITH STROKE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26A9,
+ },
+ [0x26AA]={
+ category="so",
+ description="MEDIUM WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26AB]={
+ category="so",
+ description="MEDIUM BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26AB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26AC]={
+ category="so",
+ description="MEDIUM SMALL WHITE CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x26AC,
+ },
+ [0x26AD]={
+ category="so",
+ description="MARRIAGE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26AD,
+ },
+ [0x26AE]={
+ category="so",
+ description="DIVORCE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26AE,
+ },
+ [0x26AF]={
+ category="so",
+ description="UNMARRIED PARTNERSHIP SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26AF,
+ },
+ [0x26B0]={
+ category="so",
+ description="COFFIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B0,
+ },
+ [0x26B1]={
+ category="so",
+ description="FUNERAL URN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B1,
+ },
+ [0x26B2]={
+ category="so",
+ description="NEUTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B2,
+ },
+ [0x26B3]={
+ category="so",
+ description="CERES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B3,
+ },
+ [0x26B4]={
+ category="so",
+ description="PALLAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B4,
+ },
+ [0x26B5]={
+ category="so",
+ description="JUNO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B5,
+ },
+ [0x26B6]={
+ category="so",
+ description="VESTA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B6,
+ },
+ [0x26B7]={
+ category="so",
+ description="CHIRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B7,
+ },
+ [0x26B8]={
+ category="so",
+ description="BLACK MOON LILITH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B8,
+ },
+ [0x26B9]={
+ category="so",
+ description="SEXTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B9,
+ },
+ [0x26BA]={
+ category="so",
+ description="SEMISEXTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BA,
+ },
+ [0x26BB]={
+ category="so",
+ description="QUINCUNX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BB,
+ },
+ [0x26BC]={
+ category="so",
+ description="SESQUIQUADRATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BC,
+ },
+ [0x26BD]={
+ category="so",
+ description="SOCCER BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26BD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26BE]={
+ category="so",
+ cjkwd="a",
+ description="BASEBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26BE,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26BF]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED KEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26BF,
+ },
+ [0x26C0]={
+ category="so",
+ description="WHITE DRAUGHTS MAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C0,
+ },
+ [0x26C1]={
+ category="so",
+ description="WHITE DRAUGHTS KING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C1,
+ },
+ [0x26C2]={
+ category="so",
+ description="BLACK DRAUGHTS MAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C2,
+ },
+ [0x26C3]={
+ category="so",
+ description="BLACK DRAUGHTS KING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C3,
+ },
+ [0x26C4]={
+ category="so",
+ cjkwd="a",
+ description="SNOWMAN WITHOUT SNOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C4,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26C5]={
+ category="so",
+ cjkwd="a",
+ description="SUN BEHIND CLOUD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C5,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26C6]={
+ category="so",
+ cjkwd="a",
+ description="RAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C6,
+ },
+ [0x26C7]={
+ category="so",
+ cjkwd="a",
+ description="BLACK SNOWMAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C7,
+ },
+ [0x26C8]={
+ category="so",
+ cjkwd="a",
+ description="THUNDER CLOUD AND RAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26C8,
+ },
+ [0x26C9]={
+ category="so",
+ cjkwd="a",
+ description="TURNED WHITE SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C9,
+ },
+ [0x26CA]={
+ category="so",
+ cjkwd="a",
+ description="TURNED BLACK SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CA,
+ },
+ [0x26CB]={
+ category="so",
+ cjkwd="a",
+ description="WHITE DIAMOND IN SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CB,
+ },
+ [0x26CC]={
+ category="so",
+ cjkwd="a",
+ description="CROSSING LANES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CC,
+ },
+ [0x26CD]={
+ category="so",
+ cjkwd="a",
+ description="DISABLED CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26CD,
+ },
+ [0x26CE]={
+ category="so",
+ description="OPHIUCHUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26CE,
+ },
+ [0x26CF]={
+ category="so",
+ cjkwd="a",
+ description="PICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26CF,
+ },
+ [0x26D0]={
+ category="so",
+ cjkwd="a",
+ description="CAR SLIDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D0,
+ },
+ [0x26D1]={
+ category="so",
+ cjkwd="a",
+ description="HELMET WITH WHITE CROSS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D1,
+ },
+ [0x26D2]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED CROSSING LANES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D2,
+ },
+ [0x26D3]={
+ category="so",
+ cjkwd="a",
+ description="CHAINS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D3,
+ },
+ [0x26D4]={
+ category="so",
+ cjkwd="a",
+ description="NO ENTRY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D4,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26D5]={
+ category="so",
+ cjkwd="a",
+ description="ALTERNATE ONE-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D5,
+ },
+ [0x26D6]={
+ category="so",
+ cjkwd="a",
+ description="BLACK TWO-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D6,
+ },
+ [0x26D7]={
+ category="so",
+ cjkwd="a",
+ description="WHITE TWO-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D7,
+ },
+ [0x26D8]={
+ category="so",
+ cjkwd="a",
+ description="BLACK LEFT LANE MERGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D8,
+ },
+ [0x26D9]={
+ category="so",
+ cjkwd="a",
+ description="WHITE LEFT LANE MERGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26D9,
+ },
+ [0x26DA]={
+ category="so",
+ cjkwd="a",
+ description="DRIVE SLOW SIGN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DA,
+ },
+ [0x26DB]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY WHITE DOWN-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DB,
+ },
+ [0x26DC]={
+ category="so",
+ cjkwd="a",
+ description="LEFT CLOSED ENTRY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26DC,
+ },
+ [0x26DD]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SALTIRE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DD,
+ },
+ [0x26DE]={
+ category="so",
+ cjkwd="a",
+ description="FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DE,
+ },
+ [0x26DF]={
+ category="so",
+ cjkwd="a",
+ description="BLACK TRUCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26DF,
+ },
+ [0x26E0]={
+ category="so",
+ cjkwd="a",
+ description="RESTRICTED LEFT ENTRY-1",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26E0,
+ },
+ [0x26E1]={
+ category="so",
+ cjkwd="a",
+ description="RESTRICTED LEFT ENTRY-2",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26E1,
+ },
+ [0x26E2]={
+ category="so",
+ description="ASTRONOMICAL SYMBOL FOR URANUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E2,
+ },
+ [0x26E3]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E3,
+ },
+ [0x26E4]={
+ category="so",
+ description="PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E4,
+ },
+ [0x26E5]={
+ category="so",
+ description="RIGHT-HANDED INTERLACED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E5,
+ },
+ [0x26E6]={
+ category="so",
+ description="LEFT-HANDED INTERLACED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E6,
+ },
+ [0x26E7]={
+ category="so",
+ description="INVERTED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E7,
+ },
+ [0x26E8]={
+ category="so",
+ cjkwd="a",
+ description="BLACK CROSS ON SHIELD",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E8,
+ },
+ [0x26E9]={
+ category="so",
+ cjkwd="a",
+ description="SHINTO SHRINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E9,
+ },
+ [0x26EA]={
+ category="so",
+ cjkwd="a",
+ description="CHURCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26EA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26EB]={
+ category="so",
+ cjkwd="a",
+ description="CASTLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EB,
+ },
+ [0x26EC]={
+ category="so",
+ cjkwd="a",
+ description="HISTORIC SITE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EC,
+ },
+ [0x26ED]={
+ category="so",
+ cjkwd="a",
+ description="GEAR WITHOUT HUB",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26ED,
+ },
+ [0x26EE]={
+ category="so",
+ cjkwd="a",
+ description="GEAR WITH HANDLES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EE,
+ },
+ [0x26EF]={
+ category="so",
+ cjkwd="a",
+ description="MAP SYMBOL FOR LIGHTHOUSE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EF,
+ },
+ [0x26F0]={
+ category="so",
+ cjkwd="a",
+ description="MOUNTAIN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F0,
+ },
+ [0x26F1]={
+ category="so",
+ cjkwd="a",
+ description="UMBRELLA ON GROUND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F1,
+ },
+ [0x26F2]={
+ category="so",
+ cjkwd="a",
+ description="FOUNTAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F2,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26F3]={
+ category="so",
+ cjkwd="a",
+ description="FLAG IN HOLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F3,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26F4]={
+ category="so",
+ cjkwd="a",
+ description="FERRY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F4,
+ },
+ [0x26F5]={
+ category="so",
+ cjkwd="a",
+ description="SAILBOAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F5,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26F6]={
+ category="so",
+ cjkwd="a",
+ description="SQUARE FOUR CORNERS",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F6,
+ },
+ [0x26F7]={
+ category="so",
+ cjkwd="a",
+ description="SKIER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F7,
+ },
+ [0x26F8]={
+ category="so",
+ cjkwd="a",
+ description="ICE SKATE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F8,
+ },
+ [0x26F9]={
+ category="so",
+ cjkwd="a",
+ description="PERSON WITH BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26F9,
+ },
+ [0x26FA]={
+ category="so",
+ cjkwd="a",
+ description="TENT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26FA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26FB]={
+ category="so",
+ cjkwd="a",
+ description="JAPANESE BANK SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FB,
+ },
+ [0x26FC]={
+ category="so",
+ cjkwd="a",
+ description="HEADSTONE GRAVEYARD SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FC,
+ },
+ [0x26FD]={
+ category="so",
+ cjkwd="a",
+ description="FUEL PUMP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26FD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x26FE]={
+ category="so",
+ cjkwd="a",
+ description="CUP ON BLACK SQUARE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26FE,
+ },
+ [0x26FF]={
+ category="so",
+ cjkwd="a",
+ description="WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x26FF,
+ },
+ [0x2700]={
+ category="so",
+ description="BLACK SAFETY SCISSORS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2700,
+ },
+ [0x2701]={
+ category="so",
+ description="UPPER BLADE SCISSORS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2701,
+ },
+ [0x2702]={
+ category="so",
+ description="BLACK SCISSORS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2702,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2703]={
+ category="so",
+ description="LOWER BLADE SCISSORS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2703,
+ },
+ [0x2704]={
+ category="so",
+ description="WHITE SCISSORS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2704,
+ },
+ [0x2705]={
+ category="so",
+ description="WHITE HEAVY CHECK MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2705,
+ },
+ [0x2706]={
+ category="so",
+ description="TELEPHONE LOCATION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2706,
+ },
+ [0x2707]={
+ category="so",
+ description="TAPE DRIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2707,
+ },
+ [0x2708]={
+ category="so",
+ description="AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2708,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2709]={
+ category="so",
+ description="ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2709,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x270A]={
+ category="so",
+ description="RAISED FIST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x270A,
+ },
+ [0x270B]={
+ category="so",
+ description="RAISED HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x270B,
+ },
+ [0x270C]={
+ category="so",
+ description="VICTORY HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x270C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x270D]={
+ category="so",
+ description="WRITING HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x270D,
+ },
+ [0x270E]={
+ category="so",
+ description="LOWER RIGHT PENCIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x270E,
+ },
+ [0x270F]={
+ category="so",
+ description="PENCIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x270F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2710]={
+ category="so",
+ description="UPPER RIGHT PENCIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2710,
+ },
+ [0x2711]={
+ category="so",
+ description="WHITE NIB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2711,
+ },
+ [0x2712]={
+ category="so",
+ description="BLACK NIB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2712,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2713]={
+ adobename="checkmark",
+ category="so",
+ description="CHECK MARK",
+ direction="on",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="checkmark",
+ unicodeslot=0x2713,
+ },
+ [0x2714]={
+ category="so",
+ description="HEAVY CHECK MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2714,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2715]={
+ category="so",
+ description="MULTIPLICATION X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2715,
+ },
+ [0x2716]={
+ category="so",
+ description="HEAVY MULTIPLICATION X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2716,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2717]={
+ category="so",
+ description="BALLOT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2717,
+ },
+ [0x2718]={
+ category="so",
+ description="HEAVY BALLOT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2718,
+ },
+ [0x2719]={
+ category="so",
+ description="OUTLINED GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2719,
+ },
+ [0x271A]={
+ category="so",
+ description="HEAVY GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271A,
+ },
+ [0x271B]={
+ category="so",
+ description="OPEN CENTRE CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271B,
+ },
+ [0x271C]={
+ category="so",
+ description="HEAVY OPEN CENTRE CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271C,
+ },
+ [0x271D]={
+ category="so",
+ description="LATIN CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271D,
+ },
+ [0x271E]={
+ category="so",
+ description="SHADOWED WHITE LATIN CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271E,
+ },
+ [0x271F]={
+ category="so",
+ description="OUTLINED LATIN CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x271F,
+ },
+ [0x2720]={
+ category="so",
+ description="MALTESE CROSS",
+ direction="on",
+ linebreak="al",
+ mathclass="nothing",
+ mathname="maltese",
+ unicodeslot=0x2720,
+ },
+ [0x2721]={
+ category="so",
+ description="STAR OF DAVID",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2721,
+ },
+ [0x2722]={
+ category="so",
+ description="FOUR TEARDROP-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2722,
+ },
+ [0x2723]={
+ category="so",
+ description="FOUR BALLOON-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2723,
+ },
+ [0x2724]={
+ category="so",
+ description="HEAVY FOUR BALLOON-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2724,
+ },
+ [0x2725]={
+ category="so",
+ description="FOUR CLUB-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2725,
+ },
+ [0x2726]={
+ category="so",
+ description="BLACK FOUR POINTED STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2726,
+ },
+ [0x2727]={
+ category="so",
+ description="WHITE FOUR POINTED STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2727,
+ },
+ [0x2728]={
+ category="so",
+ description="SPARKLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2728,
+ },
+ [0x2729]={
+ category="so",
+ description="STRESS OUTLINED WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2729,
+ },
+ [0x272A]={
+ category="so",
+ description="CIRCLED WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272A,
+ },
+ [0x272B]={
+ category="so",
+ description="OPEN CENTRE BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272B,
+ },
+ [0x272C]={
+ category="so",
+ description="BLACK CENTRE WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272C,
+ },
+ [0x272D]={
+ category="so",
+ description="OUTLINED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272D,
+ },
+ [0x272E]={
+ category="so",
+ description="HEAVY OUTLINED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272E,
+ },
+ [0x272F]={
+ category="so",
+ description="PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x272F,
+ },
+ [0x2730]={
+ category="so",
+ description="SHADOWED WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2730,
+ },
+ [0x2731]={
+ category="so",
+ description="HEAVY ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2731,
+ },
+ [0x2732]={
+ category="so",
+ description="OPEN CENTRE ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2732,
+ },
+ [0x2733]={
+ category="so",
+ description="EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2733,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2734]={
+ category="so",
+ description="EIGHT POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2734,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2735]={
+ category="so",
+ description="EIGHT POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2735,
+ },
+ [0x2736]={
+ category="so",
+ description="SIX POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2736,
+ },
+ [0x2737]={
+ category="so",
+ description="EIGHT POINTED RECTILINEAR BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2737,
+ },
+ [0x2738]={
+ category="so",
+ description="HEAVY EIGHT POINTED RECTILINEAR BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2738,
+ },
+ [0x2739]={
+ category="so",
+ description="TWELVE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2739,
+ },
+ [0x273A]={
+ category="so",
+ description="SIXTEEN POINTED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273A,
+ },
+ [0x273B]={
+ category="so",
+ description="TEARDROP-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273B,
+ },
+ [0x273C]={
+ category="so",
+ description="OPEN CENTRE TEARDROP-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273C,
+ },
+ [0x273D]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY TEARDROP-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273D,
+ },
+ [0x273E]={
+ category="so",
+ description="SIX PETALLED BLACK AND WHITE FLORETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273E,
+ },
+ [0x273F]={
+ category="so",
+ description="BLACK FLORETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x273F,
+ },
+ [0x2740]={
+ category="so",
+ description="WHITE FLORETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2740,
+ },
+ [0x2741]={
+ category="so",
+ description="EIGHT PETALLED OUTLINED BLACK FLORETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2741,
+ },
+ [0x2742]={
+ category="so",
+ description="CIRCLED OPEN CENTRE EIGHT POINTED STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2742,
+ },
+ [0x2743]={
+ category="so",
+ description="HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2743,
+ },
+ [0x2744]={
+ category="so",
+ description="SNOWFLAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2744,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2745]={
+ category="so",
+ description="TIGHT TRIFOLIATE SNOWFLAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2745,
+ },
+ [0x2746]={
+ category="so",
+ description="HEAVY CHEVRON SNOWFLAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2746,
+ },
+ [0x2747]={
+ category="so",
+ description="SPARKLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2747,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2748]={
+ category="so",
+ description="HEAVY SPARKLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2748,
+ },
+ [0x2749]={
+ category="so",
+ description="BALLOON-SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2749,
+ },
+ [0x274A]={
+ category="so",
+ description="EIGHT TEARDROP-SPOKED PROPELLER ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274A,
+ },
+ [0x274B]={
+ category="so",
+ description="HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274B,
+ },
+ [0x274C]={
+ category="so",
+ description="CROSS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274C,
+ },
+ [0x274D]={
+ category="so",
+ description="SHADOWED WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274D,
+ },
+ [0x274E]={
+ category="so",
+ description="NEGATIVE SQUARED CROSS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274E,
+ },
+ [0x274F]={
+ category="so",
+ description="LOWER RIGHT DROP-SHADOWED WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274F,
+ },
+ [0x2750]={
+ category="so",
+ description="UPPER RIGHT DROP-SHADOWED WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2750,
+ },
+ [0x2751]={
+ category="so",
+ description="LOWER RIGHT SHADOWED WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2751,
+ },
+ [0x2752]={
+ category="so",
+ description="UPPER RIGHT SHADOWED WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2752,
+ },
+ [0x2753]={
+ category="so",
+ description="BLACK QUESTION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2753,
+ },
+ [0x2754]={
+ category="so",
+ description="WHITE QUESTION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2754,
+ },
+ [0x2755]={
+ category="so",
+ description="WHITE EXCLAMATION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2755,
+ },
+ [0x2756]={
+ category="so",
+ description="BLACK DIAMOND MINUS WHITE X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2756,
+ },
+ [0x2757]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY EXCLAMATION MARK SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2757,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2758]={
+ category="so",
+ description="LIGHT VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2758,
+ },
+ [0x2759]={
+ category="so",
+ description="MEDIUM VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2759,
+ },
+ [0x275A]={
+ category="so",
+ description="HEAVY VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x275A,
+ },
+ [0x275B]={
+ category="so",
+ description="HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x275B,
+ },
+ [0x275C]={
+ category="so",
+ description="HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x275C,
+ },
+ [0x275D]={
+ category="so",
+ description="HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x275D,
+ },
+ [0x275E]={
+ category="so",
+ description="HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x275E,
+ },
+ [0x275F]={
+ category="so",
+ description="HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x275F,
+ },
+ [0x2760]={
+ category="so",
+ description="HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2760,
+ },
+ [0x2761]={
+ category="so",
+ description="CURVED STEM PARAGRAPH SIGN ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2761,
+ },
+ [0x2762]={
+ category="so",
+ description="HEAVY EXCLAMATION MARK ORNAMENT",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2762,
+ },
+ [0x2763]={
+ category="so",
+ description="HEAVY HEART EXCLAMATION MARK ORNAMENT",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2763,
+ },
+ [0x2764]={
+ category="so",
+ description="HEAVY BLACK HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2764,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2765]={
+ category="so",
+ description="ROTATED HEAVY BLACK HEART BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2765,
+ },
+ [0x2766]={
+ category="so",
+ description="FLORAL HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2766,
+ },
+ [0x2767]={
+ category="so",
+ description="ROTATED FLORAL HEART BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2767,
+ },
+ [0x2768]={
+ category="ps",
+ description="MEDIUM LEFT PARENTHESIS ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x2769,
+ unicodeslot=0x2768,
+ },
+ [0x2769]={
+ category="pe",
+ description="MEDIUM RIGHT PARENTHESIS ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2768,
+ unicodeslot=0x2769,
+ },
+ [0x276A]={
+ category="ps",
+ description="MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x276B,
+ unicodeslot=0x276A,
+ },
+ [0x276B]={
+ category="pe",
+ description="MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x276A,
+ unicodeslot=0x276B,
+ },
+ [0x276C]={
+ category="ps",
+ description="MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x276D,
+ unicodeslot=0x276C,
+ },
+ [0x276D]={
+ category="pe",
+ description="MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x276C,
+ unicodeslot=0x276D,
+ },
+ [0x276E]={
+ category="ps",
+ description="HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x276F,
+ unicodeslot=0x276E,
+ },
+ [0x276F]={
+ category="pe",
+ description="HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x276E,
+ unicodeslot=0x276F,
+ },
+ [0x2770]={
+ category="ps",
+ description="HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x2771,
+ unicodeslot=0x2770,
+ },
+ [0x2771]={
+ category="pe",
+ description="HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2770,
+ unicodeslot=0x2771,
+ },
+ [0x2772]={
+ category="ps",
+ description="LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x2773,
+ unicodeslot=0x2772,
+ },
+ [0x2773]={
+ category="pe",
+ description="LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2772,
+ unicodeslot=0x2773,
+ },
+ [0x2774]={
+ category="ps",
+ description="MEDIUM LEFT CURLY BRACKET ORNAMENT",
+ direction="on",
+ linebreak="op",
+ mirror=0x2775,
+ unicodeslot=0x2774,
+ },
+ [0x2775]={
+ category="pe",
+ description="MEDIUM RIGHT CURLY BRACKET ORNAMENT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2774,
+ unicodeslot=0x2775,
+ },
+ [0x2776]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2776,
+ },
+ [0x2777]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2777,
+ },
+ [0x2778]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2778,
+ },
+ [0x2779]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2779,
+ },
+ [0x277A]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277A,
+ },
+ [0x277B]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277B,
+ },
+ [0x277C]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277C,
+ },
+ [0x277D]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277D,
+ },
+ [0x277E]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277E,
+ },
+ [0x277F]={
+ category="no",
+ cjkwd="a",
+ description="DINGBAT NEGATIVE CIRCLED NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x277F,
+ },
+ [0x2780]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2780,
+ },
+ [0x2781]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2781,
+ },
+ [0x2782]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2782,
+ },
+ [0x2783]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2783,
+ },
+ [0x2784]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2784,
+ },
+ [0x2785]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2785,
+ },
+ [0x2786]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2786,
+ },
+ [0x2787]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2787,
+ },
+ [0x2788]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2788,
+ },
+ [0x2789]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2789,
+ },
+ [0x278A]={
+ adobename="onecircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278A,
+ },
+ [0x278B]={
+ adobename="twocircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278B,
+ },
+ [0x278C]={
+ adobename="threecircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278C,
+ },
+ [0x278D]={
+ adobename="fourcircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278D,
+ },
+ [0x278E]={
+ adobename="fivecircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278E,
+ },
+ [0x278F]={
+ adobename="sixcircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x278F,
+ },
+ [0x2790]={
+ adobename="sevencircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2790,
+ },
+ [0x2791]={
+ adobename="eightcircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2791,
+ },
+ [0x2792]={
+ adobename="ninecircleinversesansserif",
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2792,
+ },
+ [0x2793]={
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2793,
+ },
+ [0x2794]={
+ category="so",
+ description="HEAVY WIDE-HEADED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2794,
+ },
+ [0x2795]={
+ category="so",
+ description="HEAVY PLUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2795,
+ },
+ [0x2796]={
+ category="so",
+ description="HEAVY MINUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2796,
+ },
+ [0x2797]={
+ category="so",
+ description="HEAVY DIVISION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2797,
+ },
+ [0x2798]={
+ category="so",
+ description="HEAVY SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2798,
+ },
+ [0x2799]={
+ category="so",
+ description="HEAVY RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2799,
+ },
+ [0x279A]={
+ category="so",
+ description="HEAVY NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279A,
+ },
+ [0x279B]={
+ category="so",
+ description="DRAFTING POINT RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279B,
+ },
+ [0x279C]={
+ category="so",
+ description="HEAVY ROUND-TIPPED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279C,
+ },
+ [0x279D]={
+ category="so",
+ description="TRIANGLE-HEADED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279D,
+ },
+ [0x279E]={
+ adobename="arrowrightheavy",
+ category="so",
+ description="HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279E,
+ },
+ [0x279F]={
+ category="so",
+ description="DASHED TRIANGLE-HEADED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x279F,
+ },
+ [0x27A0]={
+ category="so",
+ description="HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A0,
+ },
+ [0x27A1]={
+ category="so",
+ description="BLACK RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A1,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x27A2]={
+ category="so",
+ description="THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A2,
+ },
+ [0x27A3]={
+ category="so",
+ description="THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A3,
+ },
+ [0x27A4]={
+ category="so",
+ description="BLACK RIGHTWARDS ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A4,
+ },
+ [0x27A5]={
+ category="so",
+ description="HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A5,
+ },
+ [0x27A6]={
+ category="so",
+ description="HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A6,
+ },
+ [0x27A7]={
+ category="so",
+ description="SQUAT BLACK RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A7,
+ },
+ [0x27A8]={
+ category="so",
+ description="HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A8,
+ },
+ [0x27A9]={
+ category="so",
+ description="RIGHT-SHADED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27A9,
+ },
+ [0x27AA]={
+ category="so",
+ description="LEFT-SHADED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AA,
+ },
+ [0x27AB]={
+ category="so",
+ description="BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AB,
+ },
+ [0x27AC]={
+ category="so",
+ description="FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AC,
+ },
+ [0x27AD]={
+ category="so",
+ description="HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AD,
+ },
+ [0x27AE]={
+ category="so",
+ description="HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AE,
+ },
+ [0x27AF]={
+ category="so",
+ description="NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27AF,
+ },
+ [0x27B0]={
+ category="so",
+ description="CURLY LOOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B0,
+ },
+ [0x27B1]={
+ category="so",
+ description="NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B1,
+ },
+ [0x27B2]={
+ category="so",
+ description="CIRCLED HEAVY WHITE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B2,
+ },
+ [0x27B3]={
+ category="so",
+ description="WHITE-FEATHERED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B3,
+ },
+ [0x27B4]={
+ category="so",
+ description="BLACK-FEATHERED SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B4,
+ },
+ [0x27B5]={
+ category="so",
+ description="BLACK-FEATHERED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B5,
+ },
+ [0x27B6]={
+ category="so",
+ description="BLACK-FEATHERED NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B6,
+ },
+ [0x27B7]={
+ category="so",
+ description="HEAVY BLACK-FEATHERED SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B7,
+ },
+ [0x27B8]={
+ category="so",
+ description="HEAVY BLACK-FEATHERED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B8,
+ },
+ [0x27B9]={
+ category="so",
+ description="HEAVY BLACK-FEATHERED NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B9,
+ },
+ [0x27BA]={
+ category="so",
+ description="TEARDROP-BARBED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BA,
+ },
+ [0x27BB]={
+ category="so",
+ description="HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BB,
+ },
+ [0x27BC]={
+ category="so",
+ description="WEDGE-TAILED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BC,
+ },
+ [0x27BD]={
+ category="so",
+ description="HEAVY WEDGE-TAILED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BD,
+ },
+ [0x27BE]={
+ category="so",
+ description="OPEN-OUTLINED RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BE,
+ },
+ [0x27BF]={
+ category="so",
+ description="DOUBLE CURLY LOOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BF,
+ },
+ [0x27C0]={
+ category="sm",
+ description="THREE DIMENSIONAL ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27C0,
+ },
+ [0x27C1]={
+ category="sm",
+ description="WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27C1,
+ },
+ [0x27C2]={
+ category="sm",
+ description="PERPENDICULAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27C2,
+ },
+ [0x27C3]={
+ category="sm",
+ description="OPEN SUBSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x27C4,
+ unicodeslot=0x27C3,
+ },
+ [0x27C4]={
+ category="sm",
+ description="OPEN SUPERSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x27C3,
+ unicodeslot=0x27C4,
+ },
+ [0x27C5]={
+ category="ps",
+ description="LEFT S-SHAPED BAG DELIMITER",
+ direction="on",
+ linebreak="op",
+ mirror=0x27C6,
+ unicodeslot=0x27C5,
+ },
+ [0x27C6]={
+ category="pe",
+ description="RIGHT S-SHAPED BAG DELIMITER",
+ direction="on",
+ linebreak="cl",
+ mirror=0x27C5,
+ unicodeslot=0x27C6,
+ },
+ [0x27C7]={
+ category="sm",
+ description="OR WITH DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27C7,
+ },
+ [0x27C8]={
+ category="sm",
+ description="REVERSE SOLIDUS PRECEDING SUBSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x27C9,
+ unicodeslot=0x27C8,
+ },
+ [0x27C9]={
+ category="sm",
+ description="SUPERSET PRECEDING SOLIDUS",
+ direction="on",
+ linebreak="al",
+ mirror=0x27C8,
+ unicodeslot=0x27C9,
+ },
+ [0x27CA]={
+ category="sm",
+ description="VERTICAL BAR WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CA,
+ },
+ [0x27CB]={
+ category="sm",
+ comment="check math properties",
+ description="MATHEMATICAL RISING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x27CD,
+ unicodeslot=0x27CB,
+ },
+ [0x27CC]={
+ category="sm",
+ description="LONG DIVISION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CC,
+ },
+ [0x27CD]={
+ category="sm",
+ comment="check math properties",
+ description="MATHEMATICAL FALLING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x27CB,
+ unicodeslot=0x27CD,
+ },
+ [0x27CE]={
+ category="sm",
+ description="SQUARED LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CE,
+ },
+ [0x27CF]={
+ category="sm",
+ description="SQUARED LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CF,
+ },
+ [0x27D0]={
+ category="sm",
+ description="WHITE DIAMOND WITH CENTRED DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D0,
+ },
+ [0x27D1]={
+ category="sm",
+ description="AND WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D1,
+ },
+ [0x27D2]={
+ category="sm",
+ description="ELEMENT OF OPENING UPWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D2,
+ },
+ [0x27D3]={
+ category="sm",
+ description="LOWER RIGHT CORNER WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D3,
+ },
+ [0x27D4]={
+ category="sm",
+ description="UPPER LEFT CORNER WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D4,
+ },
+ [0x27D5]={
+ category="sm",
+ description="LEFT OUTER JOIN",
+ direction="on",
+ linebreak="al",
+ mirror=0x27D6,
+ unicodeslot=0x27D5,
+ },
+ [0x27D6]={
+ category="sm",
+ description="RIGHT OUTER JOIN",
+ direction="on",
+ linebreak="al",
+ mirror=0x27D5,
+ unicodeslot=0x27D6,
+ },
+ [0x27D7]={
+ category="sm",
+ description="FULL OUTER JOIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D7,
+ },
+ [0x27D8]={
+ category="sm",
+ description="LARGE UP TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D8,
+ },
+ [0x27D9]={
+ category="sm",
+ description="LARGE DOWN TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27D9,
+ },
+ [0x27DA]={
+ category="sm",
+ description="LEFT AND RIGHT DOUBLE TURNSTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27DA,
+ },
+ [0x27DB]={
+ category="sm",
+ description="LEFT AND RIGHT TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27DB,
+ },
+ [0x27DC]={
+ category="sm",
+ description="LEFT MULTIMAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27DC,
+ },
+ [0x27DD]={
+ category="sm",
+ description="LONG RIGHT TACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27DE,
+ unicodeslot=0x27DD,
+ },
+ [0x27DE]={
+ category="sm",
+ description="LONG LEFT TACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27DD,
+ unicodeslot=0x27DE,
+ },
+ [0x27DF]={
+ category="sm",
+ description="UP TACK WITH CIRCLE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27DF,
+ },
+ [0x27E0]={
+ category="sm",
+ description="LOZENGE DIVIDED BY HORIZONTAL RULE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27E0,
+ },
+ [0x27E1]={
+ category="sm",
+ description="WHITE CONCAVE-SIDED DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27E1,
+ },
+ [0x27E2]={
+ category="sm",
+ description="WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27E3,
+ unicodeslot=0x27E2,
+ },
+ [0x27E3]={
+ category="sm",
+ description="WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27E2,
+ unicodeslot=0x27E3,
+ },
+ [0x27E4]={
+ category="sm",
+ description="WHITE SQUARE WITH LEFTWARDS TICK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27E5,
+ unicodeslot=0x27E4,
+ },
+ [0x27E5]={
+ category="sm",
+ description="WHITE SQUARE WITH RIGHTWARDS TICK",
+ direction="on",
+ linebreak="al",
+ mirror=0x27E4,
+ unicodeslot=0x27E5,
+ },
+ [0x27E6]={
+ category="ps",
+ cjkwd="na",
+ description="MATHEMATICAL LEFT WHITE SQUARE BRACKET",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="llbracket",
+ mirror=0x27E7,
+ unicodeslot=0x27E6,
+ },
+ [0x27E7]={
+ category="pe",
+ cjkwd="na",
+ description="MATHEMATICAL RIGHT WHITE SQUARE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rrbracket",
+ mirror=0x27E6,
+ unicodeslot=0x27E7,
+ },
+ [0x27E8]={
+ category="ps",
+ cjkwd="na",
+ description="MATHEMATICAL LEFT ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="langle",
+ mirror=0x27E9,
+ unicodeslot=0x27E8,
+ },
+ [0x27E9]={
+ category="pe",
+ cjkwd="na",
+ description="MATHEMATICAL RIGHT ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rangle",
+ mirror=0x27E8,
+ unicodeslot=0x27E9,
+ },
+ [0x27EA]={
+ category="ps",
+ cjkwd="na",
+ description="MATHEMATICAL LEFT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="llangle",
+ mirror=0x27EB,
+ unicodeslot=0x27EA,
+ },
+ [0x27EB]={
+ category="pe",
+ cjkwd="na",
+ description="MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rrangle",
+ mirror=0x27EA,
+ unicodeslot=0x27EB,
+ },
+ [0x27EC]={
+ category="ps",
+ cjkwd="na",
+ description="MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x27ED,
+ unicodeslot=0x27EC,
+ },
+ [0x27ED]={
+ category="pe",
+ cjkwd="na",
+ description="MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x27EC,
+ unicodeslot=0x27ED,
+ },
+ [0x27EE]={
+ category="ps",
+ description="MATHEMATICAL LEFT FLATTENED PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mathclass="open",
+ mathname="lgroup",
+ mirror=0x27EF,
+ unicodeslot=0x27EE,
+ },
+ [0x27EF]={
+ category="pe",
+ description="MATHEMATICAL RIGHT FLATTENED PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mathclass="close",
+ mathname="rgroup",
+ mirror=0x27EE,
+ unicodeslot=0x27EF,
+ },
+ [0x27F0]={
+ category="sm",
+ description="UPWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="u",
+ unicodeslot=0x27F0,
+ },
+ [0x27F1]={
+ category="sm",
+ description="DOWNWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="v",
+ unicodeslot=0x27F1,
+ },
+ [0x27F2]={
+ category="sm",
+ description="ANTICLOCKWISE GAPPED CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27F2,
+ },
+ [0x27F3]={
+ category="sm",
+ description="CLOCKWISE GAPPED CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27F3,
+ },
+ [0x27F4]={
+ category="sm",
+ description="RIGHT ARROW WITH CIRCLED PLUS",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x27F4,
+ },
+ [0x27F5]={
+ category="sm",
+ description="LONG LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="longleftarrow",
+ unicodeslot=0x27F5,
+ },
+ [0x27F6]={
+ category="sm",
+ comment="the parent hack is needed for mathml",
+ description="LONG RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="rightarrowfill",
+ mathname="longrightarrow",
+ mathparent=0x2192,
+ unicodeslot=0x27F6,
+ },
+ [0x27F7]={
+ category="sm",
+ comment="the parent hack is needed for mathml",
+ description="LONG LEFT RIGHT ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="leftrightarrowfill",
+ mathname="longleftrightarrow",
+ mathparent=0x2190,
+ unicodeslot=0x27F7,
+ },
+ [0x27F8]={
+ category="sm",
+ description="LONG LEFTWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathfiller="Leftarrowfill",
+ mathname="Longleftarrow",
+ unicodeslot=0x27F8,
+ },
+ [0x27F9]={
+ category="sm",
+ description="LONG RIGHTWARDS DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathfiller="Rightarrowfill",
+ mathname="Longrightarrow",
+ unicodeslot=0x27F9,
+ },
+ [0x27FA]={
+ category="sm",
+ description="LONG LEFT RIGHT DOUBLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
+ mathfiller="Leftrightarrowfill",
+ mathname="Longleftrightarrow",
+ unicodeslot=0x27FA,
+ },
+ [0x27FB]={
+ category="sm",
+ description="LONG LEFTWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="longmapsfrom",
+ unicodeslot=0x27FB,
+ },
+ [0x27FC]={
+ category="sm",
+ description="LONG RIGHTWARDS ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="longmapsto",
+ unicodeslot=0x27FC,
+ },
+ [0x27FD]={
+ category="sm",
+ description="LONG LEFTWARDS DOUBLE ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="Longmapsfrom",
+ unicodeslot=0x27FD,
+ },
+ [0x27FE]={
+ category="sm",
+ description="LONG RIGHTWARDS DOUBLE ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="Longmapsto",
+ unicodeslot=0x27FE,
+ },
+ [0x27FF]={
+ category="sm",
+ description="LONG RIGHTWARDS SQUIGGLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="longrightsquigarrow",
+ unicodeslot=0x27FF,
+ },
+ [0x2800]={
+ category="so",
+ description="BRAILLE PATTERN BLANK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2800,
+ },
+ [0x2801]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2801,
+ },
+ [0x2802]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2802,
+ },
+ [0x2803]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x000C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2803,
+ },
+ [0x2804]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2804,
+ },
+ [0x2805]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x000D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2805,
+ },
+ [0x2806]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2806,
+ },
+ [0x2807]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2807,
+ },
+ [0x2808]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2808,
+ },
+ [0x2809]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x000E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2809,
+ },
+ [0x280A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280A,
+ },
+ [0x280B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x007C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280B,
+ },
+ [0x280C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280C,
+ },
+ [0x280D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0086",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280D,
+ },
+ [0x280E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00EA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280E,
+ },
+ [0x280F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04D2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x280F,
+ },
+ [0x2810]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2810,
+ },
+ [0x2811]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x000F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2811,
+ },
+ [0x2812]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2812,
+ },
+ [0x2813]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x007D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2813,
+ },
+ [0x2814]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2814,
+ },
+ [0x2815]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0087",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2815,
+ },
+ [0x2816]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00EB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2816,
+ },
+ [0x2817]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04D3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2817,
+ },
+ [0x2818]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x002D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2818,
+ },
+ [0x2819]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0091",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2819,
+ },
+ [0x281A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00F5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281A,
+ },
+ [0x281B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04DD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281B,
+ },
+ [0x281C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0159",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281C,
+ },
+ [0x281D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0541",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281D,
+ },
+ [0x281E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0929",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281E,
+ },
+ [0x281F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x281F,
+ },
+ [0x2820]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2820,
+ },
+ [0x2821]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2821,
+ },
+ [0x2822]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2822,
+ },
+ [0x2823]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x007E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2823,
+ },
+ [0x2824]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2824,
+ },
+ [0x2825]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0088",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2825,
+ },
+ [0x2826]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00EC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2826,
+ },
+ [0x2827]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04D4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2827,
+ },
+ [0x2828]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x002E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2828,
+ },
+ [0x2829]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0092",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2829,
+ },
+ [0x282A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00F6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282A,
+ },
+ [0x282B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282B,
+ },
+ [0x282C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x015A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282C,
+ },
+ [0x282D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0542",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282D,
+ },
+ [0x282E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x092A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282E,
+ },
+ [0x282F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x303A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x282F,
+ },
+ [0x2830]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2830,
+ },
+ [0x2831]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x009C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2831,
+ },
+ [0x2832]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0100",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2832,
+ },
+ [0x2833]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04E8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2833,
+ },
+ [0x2834]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0164",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2834,
+ },
+ [0x2835]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x054C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2835,
+ },
+ [0x2836]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0934",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2836,
+ },
+ [0x2837]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2837,
+ },
+ [0x2838]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01C8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2838,
+ },
+ [0x2839]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05B0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2839,
+ },
+ [0x283A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0998",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283A,
+ },
+ [0x283B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30A8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283B,
+ },
+ [0x283C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D80",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283C,
+ },
+ [0x283D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3490",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283D,
+ },
+ [0x283E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BA0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283E,
+ },
+ [0x283F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E240",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x283F,
+ },
+ [0x2840]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2840,
+ },
+ [0x2841]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2841,
+ },
+ [0x2842]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x001B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2842,
+ },
+ [0x2843]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x007F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2843,
+ },
+ [0x2844]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2844,
+ },
+ [0x2845]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0089",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2845,
+ },
+ [0x2846]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00ED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2846,
+ },
+ [0x2847]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04D5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2847,
+ },
+ [0x2848]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x002F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2848,
+ },
+ [0x2849]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0093",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2849,
+ },
+ [0x284A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00F7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284A,
+ },
+ [0x284B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04DF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284B,
+ },
+ [0x284C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x015B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284C,
+ },
+ [0x284D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0543",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284D,
+ },
+ [0x284E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x092B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284E,
+ },
+ [0x284F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x303B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x284F,
+ },
+ [0x2850]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2850,
+ },
+ [0x2851]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x009D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2851,
+ },
+ [0x2852]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0101",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2852,
+ },
+ [0x2853]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04E9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2853,
+ },
+ [0x2854]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0165",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2854,
+ },
+ [0x2855]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x054D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2855,
+ },
+ [0x2856]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0935",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2856,
+ },
+ [0x2857]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2857,
+ },
+ [0x2858]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01C9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2858,
+ },
+ [0x2859]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05B1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2859,
+ },
+ [0x285A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0999",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285A,
+ },
+ [0x285B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30A9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285B,
+ },
+ [0x285C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D81",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285C,
+ },
+ [0x285D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3491",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285D,
+ },
+ [0x285E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BA1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285E,
+ },
+ [0x285F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E241",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x285F,
+ },
+ [0x2860]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2860,
+ },
+ [0x2861]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00A7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2861,
+ },
+ [0x2862]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x010B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2862,
+ },
+ [0x2863]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04F3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2863,
+ },
+ [0x2864]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x016F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2864,
+ },
+ [0x2865]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0557",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2865,
+ },
+ [0x2866]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x093F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2866,
+ },
+ [0x2867]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x304F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2867,
+ },
+ [0x2868]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01D3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2868,
+ },
+ [0x2869]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05BB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2869,
+ },
+ [0x286A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x09A3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286A,
+ },
+ [0x286B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30B3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286B,
+ },
+ [0x286C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D8B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286C,
+ },
+ [0x286D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x349B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286D,
+ },
+ [0x286E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286E,
+ },
+ [0x286F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E24B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x286F,
+ },
+ [0x2870]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0237",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2870,
+ },
+ [0x2871]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x061F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2871,
+ },
+ [0x2872]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0A07",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2872,
+ },
+ [0x2873]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3117",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2873,
+ },
+ [0x2874]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0DEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2874,
+ },
+ [0x2875]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x34FF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2875,
+ },
+ [0x2876]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5C0F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2876,
+ },
+ [0x2877]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E2AF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2877,
+ },
+ [0x2878]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x11D7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2878,
+ },
+ [0x2879]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x38E7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2879,
+ },
+ [0x287A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5FF7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287A,
+ },
+ [0x287B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E697",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287B,
+ },
+ [0x287C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x8707",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287C,
+ },
+ [0x287D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x20DA7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287D,
+ },
+ [0x287E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x39447",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287E,
+ },
+ [0x287F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x12D687",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x287F,
+ },
+ [0x2880]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2880,
+ },
+ [0x2881]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2881,
+ },
+ [0x2882]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x001C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2882,
+ },
+ [0x2883]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0080",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2883,
+ },
+ [0x2884]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2884,
+ },
+ [0x2885]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2885,
+ },
+ [0x2886]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2886,
+ },
+ [0x2887]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04D6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2887,
+ },
+ [0x2888]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2888,
+ },
+ [0x2889]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0094",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2889,
+ },
+ [0x288A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00F8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288A,
+ },
+ [0x288B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04E0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288B,
+ },
+ [0x288C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x015C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288C,
+ },
+ [0x288D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0544",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288D,
+ },
+ [0x288E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x092C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288E,
+ },
+ [0x288F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x303C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x288F,
+ },
+ [0x2890]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2890,
+ },
+ [0x2891]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x009E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2891,
+ },
+ [0x2892]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0102",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2892,
+ },
+ [0x2893]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04EA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2893,
+ },
+ [0x2894]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0166",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2894,
+ },
+ [0x2895]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x054E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2895,
+ },
+ [0x2896]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0936",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2896,
+ },
+ [0x2897]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2897,
+ },
+ [0x2898]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2898,
+ },
+ [0x2899]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05B2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2899,
+ },
+ [0x289A]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x099A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289A,
+ },
+ [0x289B]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289B,
+ },
+ [0x289C]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D82",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289C,
+ },
+ [0x289D]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3492",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289D,
+ },
+ [0x289E]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BA2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289E,
+ },
+ [0x289F]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E242",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x289F,
+ },
+ [0x28A0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A0,
+ },
+ [0x28A1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00A8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A1,
+ },
+ [0x28A2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x010C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A2,
+ },
+ [0x28A3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04F4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A3,
+ },
+ [0x28A4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0170",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A4,
+ },
+ [0x28A5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0558",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A5,
+ },
+ [0x28A6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0940",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A6,
+ },
+ [0x28A7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A7,
+ },
+ [0x28A8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01D4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A8,
+ },
+ [0x28A9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05BC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28A9,
+ },
+ [0x28AA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x09A4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AA,
+ },
+ [0x28AB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30B4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AB,
+ },
+ [0x28AC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D8C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AC,
+ },
+ [0x28AD]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x349C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AD,
+ },
+ [0x28AE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BAC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AE,
+ },
+ [0x28AF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E24C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28AF,
+ },
+ [0x28B0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0238",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B0,
+ },
+ [0x28B1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0620",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B1,
+ },
+ [0x28B2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0A08",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B2,
+ },
+ [0x28B3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3118",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B3,
+ },
+ [0x28B4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0DF0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B4,
+ },
+ [0x28B5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3500",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B5,
+ },
+ [0x28B6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5C10",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B6,
+ },
+ [0x28B7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E2B0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B7,
+ },
+ [0x28B8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x11D8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B8,
+ },
+ [0x28B9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x38E8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28B9,
+ },
+ [0x28BA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5FF8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BA,
+ },
+ [0x28BB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E698",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BB,
+ },
+ [0x28BC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x8708",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BC,
+ },
+ [0x28BD]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x20DA8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BD,
+ },
+ [0x28BE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x39448",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BE,
+ },
+ [0x28BF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x12D688",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28BF,
+ },
+ [0x28C0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x004E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C0,
+ },
+ [0x28C1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x00B2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C1,
+ },
+ [0x28C2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0116",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C2,
+ },
+ [0x28C3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x04FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C3,
+ },
+ [0x28C4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C4,
+ },
+ [0x28C5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0562",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C5,
+ },
+ [0x28C6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x094A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C6,
+ },
+ [0x28C7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x305A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C7,
+ },
+ [0x28C8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x01DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C8,
+ },
+ [0x28C9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x05C6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28C9,
+ },
+ [0x28CA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x09AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CA,
+ },
+ [0x28CB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x30BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CB,
+ },
+ [0x28CC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0D96",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CC,
+ },
+ [0x28CD]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x34A6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CD,
+ },
+ [0x28CE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5BB6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CE,
+ },
+ [0x28CF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E256",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28CF,
+ },
+ [0x28D0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0242",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D0,
+ },
+ [0x28D1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x062A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D1,
+ },
+ [0x28D2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0A12",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D2,
+ },
+ [0x28D3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3122",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D3,
+ },
+ [0x28D4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0DFA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D4,
+ },
+ [0x28D5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x350A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D5,
+ },
+ [0x28D6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5C1A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D6,
+ },
+ [0x28D7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E2BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D7,
+ },
+ [0x28D8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x11E2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D8,
+ },
+ [0x28D9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x38F2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28D9,
+ },
+ [0x28DA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x6002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DA,
+ },
+ [0x28DB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E6A2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DB,
+ },
+ [0x28DC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x8712",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DC,
+ },
+ [0x28DD]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x20DB2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DD,
+ },
+ [0x28DE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x39452",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DE,
+ },
+ [0x28DF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x12D692",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28DF,
+ },
+ [0x28E0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x02A6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E0,
+ },
+ [0x28E1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x068E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E1,
+ },
+ [0x28E2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0A76",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E2,
+ },
+ [0x28E3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3186",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E3,
+ },
+ [0x28E4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x0E5E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E4,
+ },
+ [0x28E5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x356E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E5,
+ },
+ [0x28E6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5C7E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E6,
+ },
+ [0x28E7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E31E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E7,
+ },
+ [0x28E8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1246",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E8,
+ },
+ [0x28E9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3956",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28E9,
+ },
+ [0x28EA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x6066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28EA,
+ },
+ [0x28EB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1E706",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28EB,
+ },
+ [0x28EC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x8776",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28EC,
+ },
+ [0x28ED]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x20E16",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28ED,
+ },
+ [0x28EE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x394B6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28EE,
+ },
+ [0x28EF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x12D6F6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28EF,
+ },
+ [0x28F0]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x162E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F0,
+ },
+ [0x28F1]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3D3E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F1,
+ },
+ [0x28F2]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x644E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F2,
+ },
+ [0x28F3]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1EAEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F3,
+ },
+ [0x28F4]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x8B5E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F4,
+ },
+ [0x28F5]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x211FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F5,
+ },
+ [0x28F6]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3989E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F6,
+ },
+ [0x28F7]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x12DADE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F7,
+ },
+ [0x28F8]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0xB26E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F8,
+ },
+ [0x28F9]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x2390E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28F9,
+ },
+ [0x28FA]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x3BFAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FA,
+ },
+ [0x28FB]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x1301EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FB,
+ },
+ [0x28FC]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x5464E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FC,
+ },
+ [0x28FD]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x14888E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FD,
+ },
+ [0x28FE]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0x23CACE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FE,
+ },
+ [0x28FF]={
+ category="so",
+ description="BRAILLE PATTERN DOTS-0xBC614E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x28FF,
+ },
+ [0x2900]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2900,
+ },
+ [0x2901]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2901,
+ },
+ [0x2902]={
+ category="sm",
+ description="LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2902,
+ },
+ [0x2903]={
+ category="sm",
+ description="RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2903,
+ },
+ [0x2904]={
+ category="sm",
+ description="LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="h",
+ unicodeslot=0x2904,
+ },
+ [0x2905]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2905,
+ },
+ [0x2906]={
+ category="sm",
+ description="LEFTWARDS DOUBLE ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="Mapsfrom",
+ unicodeslot=0x2906,
+ },
+ [0x2907]={
+ category="sm",
+ description="RIGHTWARDS DOUBLE ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="Mapsto",
+ unicodeslot=0x2907,
+ },
+ [0x2908]={
+ category="sm",
+ description="DOWNWARDS ARROW WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="d",
+ unicodeslot=0x2908,
+ },
+ [0x2909]={
+ category="sm",
+ description="UPWARDS ARROW WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="u",
+ unicodeslot=0x2909,
+ },
+ [0x290A]={
+ category="sm",
+ description="UPWARDS TRIPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="u",
+ mathname="Uuparrow",
+ unicodeslot=0x290A,
+ },
+ [0x290B]={
+ category="sm",
+ description="DOWNWARDS TRIPLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="d",
+ mathname="Ddownarrow",
+ unicodeslot=0x290B,
+ },
+ [0x290C]={
+ category="sm",
+ description="LEFTWARDS DOUBLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="l",
+ mathname="dashedleftarrow",
+ unicodeslot=0x290C,
+ },
+ [0x290D]={
+ category="sm",
+ description="RIGHTWARDS DOUBLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="dashedrightarrow",
+ unicodeslot=0x290D,
+ },
+ [0x290E]={
+ category="sm",
+ description="LEFTWARDS TRIPLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x290E,
+ },
+ [0x290F]={
+ category="sm",
+ description="RIGHTWARDS TRIPLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x290F,
+ },
+ [0x2910]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2910,
+ },
+ [0x2911]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH DOTTED STEM",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="dottedrightarrow",
+ unicodeslot=0x2911,
+ },
+ [0x2912]={
+ category="sm",
+ description="UPWARDS ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ mathextensible="u",
+ unicodeslot=0x2912,
+ },
+ [0x2913]={
+ category="sm",
+ description="DOWNWARDS ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ mathextensible="d",
+ unicodeslot=0x2913,
+ },
+ [0x2914]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2914,
+ },
+ [0x2915]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2915,
+ },
+ [0x2916]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH TAIL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ mathname="twoheadrightarrowtail",
+ unicodeslot=0x2916,
+ },
+ [0x2917]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathextensible="r",
+ unicodeslot=0x2917,
+ },
+ [0x2918]={
+ category="sm",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2918,
+ },
+ [0x2919]={
+ category="sm",
+ description="LEFTWARDS ARROW-TAIL",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2919,
+ },
+ [0x291A]={
+ category="sm",
+ description="RIGHTWARDS ARROW-TAIL",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x291A,
+ },
+ [0x291B]={
+ category="sm",
+ description="LEFTWARDS DOUBLE ARROW-TAIL",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x291B,
+ },
+ [0x291C]={
+ category="sm",
+ description="RIGHTWARDS DOUBLE ARROW-TAIL",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x291C,
+ },
+ [0x291D]={
+ category="sm",
+ description="LEFTWARDS ARROW TO BLACK DIAMOND",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x291D,
+ },
+ [0x291E]={
+ category="sm",
+ description="RIGHTWARDS ARROW TO BLACK DIAMOND",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x291E,
+ },
+ [0x291F]={
+ category="sm",
+ description="LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x291F,
+ },
+ [0x2920]={
+ category="sm",
+ description="RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2920,
+ },
+ [0x2921]={
+ category="sm",
+ description="NORTH WEST AND SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="nwsearrow",
+ unicodeslot=0x2921,
+ },
+ [0x2922]={
+ category="sm",
+ description="NORTH EAST AND SOUTH WEST ARROW",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="neswarrow",
+ unicodeslot=0x2922,
+ },
+ [0x2923]={
+ category="sm",
+ description="NORTH WEST ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lhooknwarrow",
+ unicodeslot=0x2923,
+ },
+ [0x2924]={
+ category="sm",
+ description="NORTH EAST ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="rhooknearrow",
+ unicodeslot=0x2924,
+ },
+ [0x2925]={
+ category="sm",
+ description="SOUTH EAST ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lhooksearrow",
+ unicodeslot=0x2925,
+ },
+ [0x2926]={
+ category="sm",
+ description="SOUTH WEST ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="rhookswarrow",
+ unicodeslot=0x2926,
+ },
+ [0x2927]={
+ category="sm",
+ description="NORTH WEST ARROW AND NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2927,
+ },
+ [0x2928]={
+ category="sm",
+ description="NORTH EAST ARROW AND SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2928,
+ },
+ [0x2929]={
+ category="sm",
+ description="SOUTH EAST ARROW AND SOUTH WEST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2929,
+ },
+ [0x292A]={
+ category="sm",
+ description="SOUTH WEST ARROW AND NORTH WEST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292A,
+ },
+ [0x292B]={
+ category="sm",
+ description="RISING DIAGONAL CROSSING FALLING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292B,
+ },
+ [0x292C]={
+ category="sm",
+ description="FALLING DIAGONAL CROSSING RISING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292C,
+ },
+ [0x292D]={
+ category="sm",
+ description="SOUTH EAST ARROW CROSSING NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292D,
+ },
+ [0x292E]={
+ category="sm",
+ description="NORTH EAST ARROW CROSSING SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292E,
+ },
+ [0x292F]={
+ category="sm",
+ description="FALLING DIAGONAL CROSSING NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x292F,
+ },
+ [0x2930]={
+ category="sm",
+ description="RISING DIAGONAL CROSSING SOUTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2930,
+ },
+ [0x2931]={
+ category="sm",
+ description="NORTH EAST ARROW CROSSING NORTH WEST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2931,
+ },
+ [0x2932]={
+ category="sm",
+ description="NORTH WEST ARROW CROSSING NORTH EAST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2932,
+ },
+ [0x2933]={
+ category="sm",
+ description="WAVE ARROW POINTING DIRECTLY RIGHT",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2933,
+ },
+ [0x2934]={
+ category="sm",
+ description="ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS",
+ direction="on",
+ linebreak="al",
+ mathextensible="m",
+ unicodeslot=0x2934,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2935]={
+ category="sm",
+ description="ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ mathextensible="m",
+ unicodeslot=0x2935,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2936]={
+ category="sm",
+ description="ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ mathextensible="m",
+ unicodeslot=0x2936,
+ },
+ [0x2937]={
+ category="sm",
+ description="ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ mathextensible="m",
+ unicodeslot=0x2937,
+ },
+ [0x2938]={
+ category="sm",
+ description="RIGHT-SIDE ARC CLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2938,
+ },
+ [0x2939]={
+ category="sm",
+ description="LEFT-SIDE ARC ANTICLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2939,
+ },
+ [0x293A]={
+ category="sm",
+ description="TOP ARC ANTICLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x293A,
+ },
+ [0x293B]={
+ category="sm",
+ description="BOTTOM ARC ANTICLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x293B,
+ },
+ [0x293C]={
+ category="sm",
+ description="TOP ARC CLOCKWISE ARROW WITH MINUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x293C,
+ },
+ [0x293D]={
+ category="sm",
+ description="TOP ARC ANTICLOCKWISE ARROW WITH PLUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x293D,
+ },
+ [0x293E]={
+ category="sm",
+ description="LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x293E,
+ },
+ [0x293F]={
+ category="sm",
+ description="LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x293F,
+ },
+ [0x2940]={
+ category="sm",
+ description="ANTICLOCKWISE CLOSED CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2940,
+ },
+ [0x2941]={
+ category="sm",
+ description="CLOCKWISE CLOSED CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2941,
+ },
+ [0x2942]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2942,
+ },
+ [0x2943]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2943,
+ },
+ [0x2944]={
+ category="sm",
+ description="SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2944,
+ },
+ [0x2945]={
+ category="sm",
+ description="RIGHTWARDS ARROW WITH PLUS BELOW",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2945,
+ },
+ [0x2946]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH PLUS BELOW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2946,
+ },
+ [0x2947]={
+ category="sm",
+ description="RIGHTWARDS ARROW THROUGH X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2947,
+ },
+ [0x2948]={
+ category="sm",
+ description="LEFT RIGHT ARROW THROUGH SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2948,
+ },
+ [0x2949]={
+ category="sm",
+ description="UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ mathextensible="u",
+ unicodeslot=0x2949,
+ },
+ [0x294A]={
+ category="sm",
+ description="LEFT BARB UP RIGHT BARB DOWN HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294A,
+ },
+ [0x294B]={
+ category="sm",
+ description="LEFT BARB DOWN RIGHT BARB UP HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294B,
+ },
+ [0x294C]={
+ category="sm",
+ description="UP BARB RIGHT DOWN BARB LEFT HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294C,
+ },
+ [0x294D]={
+ category="sm",
+ description="UP BARB LEFT DOWN BARB RIGHT HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294D,
+ },
+ [0x294E]={
+ category="sm",
+ description="LEFT BARB UP RIGHT BARB UP HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294E,
+ },
+ [0x294F]={
+ category="sm",
+ description="UP BARB RIGHT DOWN BARB RIGHT HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x294F,
+ },
+ [0x2950]={
+ category="sm",
+ description="LEFT BARB DOWN RIGHT BARB DOWN HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2950,
+ },
+ [0x2951]={
+ category="sm",
+ description="UP BARB LEFT DOWN BARB LEFT HARPOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2951,
+ },
+ [0x2952]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB UP TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2952,
+ },
+ [0x2953]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB UP TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2953,
+ },
+ [0x2954]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB RIGHT TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2954,
+ },
+ [0x2955]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB RIGHT TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2955,
+ },
+ [0x2956]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB DOWN TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2956,
+ },
+ [0x2957]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB DOWN TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2957,
+ },
+ [0x2958]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB LEFT TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2958,
+ },
+ [0x2959]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB LEFT TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2959,
+ },
+ [0x295A]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB UP FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295A,
+ },
+ [0x295B]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB UP FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295B,
+ },
+ [0x295C]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB RIGHT FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295C,
+ },
+ [0x295D]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295D,
+ },
+ [0x295E]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB DOWN FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295E,
+ },
+ [0x295F]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x295F,
+ },
+ [0x2960]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB LEFT FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2960,
+ },
+ [0x2961]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB LEFT FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2961,
+ },
+ [0x2962]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2962,
+ },
+ [0x2963]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2963,
+ },
+ [0x2964]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2964,
+ },
+ [0x2965]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2965,
+ },
+ [0x2966]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2966,
+ },
+ [0x2967]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2967,
+ },
+ [0x2968]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2968,
+ },
+ [0x2969]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2969,
+ },
+ [0x296A]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296A,
+ },
+ [0x296B]={
+ category="sm",
+ description="LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296B,
+ },
+ [0x296C]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296C,
+ },
+ [0x296D]={
+ category="sm",
+ description="RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296D,
+ },
+ [0x296E]={
+ category="sm",
+ description="UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296E,
+ },
+ [0x296F]={
+ category="sm",
+ description="DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x296F,
+ },
+ [0x2970]={
+ category="sm",
+ description="RIGHT DOUBLE ARROW WITH ROUNDED HEAD",
+ direction="on",
+ linebreak="al",
+ mathextensible="r",
+ unicodeslot=0x2970,
+ },
+ [0x2971]={
+ category="sm",
+ description="EQUALS SIGN ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2971,
+ },
+ [0x2972]={
+ category="sm",
+ description="TILDE OPERATOR ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2972,
+ },
+ [0x2973]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2973,
+ },
+ [0x2974]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2974,
+ },
+ [0x2975]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2975,
+ },
+ [0x2976]={
+ category="sm",
+ description="LESS-THAN ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2976,
+ },
+ [0x2977]={
+ category="sm",
+ description="LEFTWARDS ARROW THROUGH LESS-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2977,
+ },
+ [0x2978]={
+ category="sm",
+ description="GREATER-THAN ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2978,
+ },
+ [0x2979]={
+ category="sm",
+ description="SUBSET ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2979,
+ },
+ [0x297A]={
+ category="sm",
+ description="LEFTWARDS ARROW THROUGH SUBSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297A,
+ },
+ [0x297B]={
+ category="sm",
+ description="SUPERSET ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297B,
+ },
+ [0x297C]={
+ category="sm",
+ description="LEFT FISH TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297C,
+ },
+ [0x297D]={
+ category="sm",
+ description="RIGHT FISH TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297D,
+ },
+ [0x297E]={
+ category="sm",
+ description="UP FISH TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297E,
+ },
+ [0x297F]={
+ category="sm",
+ description="DOWN FISH TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x297F,
+ },
+ [0x2980]={
+ category="sm",
+ description="TRIPLE VERTICAL BAR DELIMITER",
+ direction="on",
+ linebreak="al",
+ mathspec={
+ {
+ class="delimiter",
+ name="tripleverticalbar",
+ },
+ },
+ unicodeslot=0x2980,
+ },
+ [0x2981]={
+ category="sm",
+ description="Z NOTATION SPOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2981,
+ },
+ [0x2982]={
+ category="sm",
+ description="Z NOTATION TYPE COLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2982,
+ },
+ [0x2983]={
+ category="ps",
+ description="LEFT WHITE CURLY BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2984,
+ unicodeslot=0x2983,
+ },
+ [0x2984]={
+ category="pe",
+ description="RIGHT WHITE CURLY BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2983,
+ unicodeslot=0x2984,
+ },
+ [0x2985]={
+ category="ps",
+ cjkwd="na",
+ description="LEFT WHITE PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0x2986,
+ unicodeslot=0x2985,
+ },
+ [0x2986]={
+ category="pe",
+ cjkwd="na",
+ description="RIGHT WHITE PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2985,
+ unicodeslot=0x2986,
+ },
+ [0x2987]={
+ category="ps",
+ description="Z NOTATION LEFT IMAGE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2988,
+ unicodeslot=0x2987,
+ },
+ [0x2988]={
+ category="pe",
+ description="Z NOTATION RIGHT IMAGE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2987,
+ unicodeslot=0x2988,
+ },
+ [0x2989]={
+ category="ps",
+ description="Z NOTATION LEFT BINDING BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x298A,
+ unicodeslot=0x2989,
+ },
+ [0x298A]={
+ category="pe",
+ description="Z NOTATION RIGHT BINDING BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2989,
+ unicodeslot=0x298A,
+ },
+ [0x298B]={
+ category="ps",
+ description="LEFT SQUARE BRACKET WITH UNDERBAR",
+ direction="on",
+ linebreak="op",
+ mirror=0x298C,
+ unicodeslot=0x298B,
+ },
+ [0x298C]={
+ category="pe",
+ description="RIGHT SQUARE BRACKET WITH UNDERBAR",
+ direction="on",
+ linebreak="cl",
+ mirror=0x298B,
+ unicodeslot=0x298C,
+ },
+ [0x298D]={
+ category="ps",
+ description="LEFT SQUARE BRACKET WITH TICK IN TOP CORNER",
+ direction="on",
+ linebreak="op",
+ mirror=0x2990,
+ unicodeslot=0x298D,
+ },
+ [0x298E]={
+ category="pe",
+ description="RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER",
+ direction="on",
+ linebreak="cl",
+ mirror=0x298F,
+ unicodeslot=0x298E,
+ },
+ [0x298F]={
+ category="ps",
+ description="LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER",
+ direction="on",
+ linebreak="op",
+ mirror=0x298E,
+ unicodeslot=0x298F,
+ },
+ [0x2990]={
+ category="pe",
+ description="RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER",
+ direction="on",
+ linebreak="cl",
+ mirror=0x298D,
+ unicodeslot=0x2990,
+ },
+ [0x2991]={
+ category="ps",
+ description="LEFT ANGLE BRACKET WITH DOT",
+ direction="on",
+ linebreak="op",
+ mirror=0x2992,
+ unicodeslot=0x2991,
+ },
+ [0x2992]={
+ category="pe",
+ description="RIGHT ANGLE BRACKET WITH DOT",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2991,
+ unicodeslot=0x2992,
+ },
+ [0x2993]={
+ category="ps",
+ description="LEFT ARC LESS-THAN BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2994,
+ unicodeslot=0x2993,
+ },
+ [0x2994]={
+ category="pe",
+ description="RIGHT ARC GREATER-THAN BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2993,
+ unicodeslot=0x2994,
+ },
+ [0x2995]={
+ category="ps",
+ description="DOUBLE LEFT ARC GREATER-THAN BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2996,
+ unicodeslot=0x2995,
+ },
+ [0x2996]={
+ category="pe",
+ description="DOUBLE RIGHT ARC LESS-THAN BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2995,
+ unicodeslot=0x2996,
+ },
+ [0x2997]={
+ category="ps",
+ description="LEFT BLACK TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2998,
+ unicodeslot=0x2997,
+ },
+ [0x2998]={
+ category="pe",
+ description="RIGHT BLACK TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2997,
+ unicodeslot=0x2998,
+ },
+ [0x2999]={
+ category="sm",
+ description="DOTTED FENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2999,
+ },
+ [0x299A]={
+ category="sm",
+ description="VERTICAL ZIGZAG LINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299A,
+ },
+ [0x299B]={
+ category="sm",
+ description="MEASURED ANGLE OPENING LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299B,
+ },
+ [0x299C]={
+ category="sm",
+ description="RIGHT ANGLE VARIANT WITH SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299C,
+ },
+ [0x299D]={
+ category="sm",
+ description="MEASURED RIGHT ANGLE WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299D,
+ },
+ [0x299E]={
+ category="sm",
+ description="ANGLE WITH S INSIDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299E,
+ },
+ [0x299F]={
+ category="sm",
+ description="ACUTE ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x299F,
+ },
+ [0x29A0]={
+ category="sm",
+ description="SPHERICAL ANGLE OPENING LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A0,
+ },
+ [0x29A1]={
+ category="sm",
+ description="SPHERICAL ANGLE OPENING UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A1,
+ },
+ [0x29A2]={
+ category="sm",
+ description="TURNED ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A2,
+ },
+ [0x29A3]={
+ category="sm",
+ description="REVERSED ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A3,
+ },
+ [0x29A4]={
+ category="sm",
+ description="ANGLE WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A4,
+ },
+ [0x29A5]={
+ category="sm",
+ description="REVERSED ANGLE WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A5,
+ },
+ [0x29A6]={
+ category="sm",
+ description="OBLIQUE ANGLE OPENING UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A6,
+ },
+ [0x29A7]={
+ category="sm",
+ description="OBLIQUE ANGLE OPENING DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A7,
+ },
+ [0x29A8]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A8,
+ },
+ [0x29A9]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29A9,
+ },
+ [0x29AA]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AA,
+ },
+ [0x29AB]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AB,
+ },
+ [0x29AC]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AC,
+ },
+ [0x29AD]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AD,
+ },
+ [0x29AE]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AE,
+ },
+ [0x29AF]={
+ category="sm",
+ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29AF,
+ },
+ [0x29B0]={
+ category="sm",
+ description="REVERSED EMPTY SET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B0,
+ },
+ [0x29B1]={
+ category="sm",
+ description="EMPTY SET WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B1,
+ },
+ [0x29B2]={
+ category="sm",
+ description="EMPTY SET WITH SMALL CIRCLE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B2,
+ },
+ [0x29B3]={
+ category="sm",
+ description="EMPTY SET WITH RIGHT ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B3,
+ },
+ [0x29B4]={
+ category="sm",
+ description="EMPTY SET WITH LEFT ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B4,
+ },
+ [0x29B5]={
+ category="sm",
+ description="CIRCLE WITH HORIZONTAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B5,
+ },
+ [0x29B6]={
+ category="sm",
+ description="CIRCLED VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B6,
+ },
+ [0x29B7]={
+ category="sm",
+ description="CIRCLED PARALLEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B7,
+ },
+ [0x29B8]={
+ category="sm",
+ description="CIRCLED REVERSE SOLIDUS",
+ direction="on",
+ linebreak="al",
+ mirror=0x2298,
+ unicodeslot=0x29B8,
+ },
+ [0x29B9]={
+ category="sm",
+ description="CIRCLED PERPENDICULAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29B9,
+ },
+ [0x29BA]={
+ category="sm",
+ description="CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BA,
+ },
+ [0x29BB]={
+ category="sm",
+ description="CIRCLE WITH SUPERIMPOSED X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BB,
+ },
+ [0x29BC]={
+ category="sm",
+ description="CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BC,
+ },
+ [0x29BD]={
+ category="sm",
+ description="UP ARROW THROUGH CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BD,
+ },
+ [0x29BE]={
+ category="sm",
+ description="CIRCLED WHITE BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BE,
+ },
+ [0x29BF]={
+ category="sm",
+ description="CIRCLED BULLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29BF,
+ },
+ [0x29C0]={
+ category="sm",
+ description="CIRCLED LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x29C1,
+ unicodeslot=0x29C0,
+ },
+ [0x29C1]={
+ category="sm",
+ description="CIRCLED GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x29C0,
+ unicodeslot=0x29C1,
+ },
+ [0x29C2]={
+ category="sm",
+ description="CIRCLE WITH SMALL CIRCLE TO THE RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C2,
+ },
+ [0x29C3]={
+ category="sm",
+ description="CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C3,
+ },
+ [0x29C4]={
+ category="sm",
+ description="SQUARED RISING DIAGONAL SLASH",
+ direction="on",
+ linebreak="al",
+ mirror=0x29C5,
+ unicodeslot=0x29C4,
+ },
+ [0x29C5]={
+ category="sm",
+ description="SQUARED FALLING DIAGONAL SLASH",
+ direction="on",
+ linebreak="al",
+ mirror=0x29C4,
+ unicodeslot=0x29C5,
+ },
+ [0x29C6]={
+ category="sm",
+ description="SQUARED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C6,
+ },
+ [0x29C7]={
+ category="sm",
+ description="SQUARED SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C7,
+ },
+ [0x29C8]={
+ category="sm",
+ description="SQUARED SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C8,
+ },
+ [0x29C9]={
+ category="sm",
+ description="TWO JOINED SQUARES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29C9,
+ },
+ [0x29CA]={
+ category="sm",
+ description="TRIANGLE WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29CA,
+ },
+ [0x29CB]={
+ category="sm",
+ description="TRIANGLE WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29CB,
+ },
+ [0x29CC]={
+ category="sm",
+ description="S IN TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29CC,
+ },
+ [0x29CD]={
+ category="sm",
+ description="TRIANGLE WITH SERIFS AT BOTTOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29CD,
+ },
+ [0x29CE]={
+ category="sm",
+ description="RIGHT TRIANGLE ABOVE LEFT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29CE,
+ },
+ [0x29CF]={
+ category="sm",
+ description="LEFT TRIANGLE BESIDE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ mirror=0x29D0,
+ unicodeslot=0x29CF,
+ },
+ [0x29D0]={
+ category="sm",
+ description="VERTICAL BAR BESIDE RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x29CF,
+ unicodeslot=0x29D0,
+ },
+ [0x29D1]={
+ category="sm",
+ description="BOWTIE WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x29D2,
+ unicodeslot=0x29D1,
+ },
+ [0x29D2]={
+ category="sm",
+ description="BOWTIE WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x29D1,
+ unicodeslot=0x29D2,
+ },
+ [0x29D3]={
+ category="sm",
+ description="BLACK BOWTIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29D3,
+ },
+ [0x29D4]={
+ category="sm",
+ description="TIMES WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x29D5,
+ unicodeslot=0x29D4,
+ },
+ [0x29D5]={
+ category="sm",
+ description="TIMES WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x29D4,
+ unicodeslot=0x29D5,
+ },
+ [0x29D6]={
+ category="sm",
+ description="WHITE HOURGLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29D6,
+ },
+ [0x29D7]={
+ category="sm",
+ description="BLACK HOURGLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29D7,
+ },
+ [0x29D8]={
+ category="ps",
+ description="LEFT WIGGLY FENCE",
+ direction="on",
+ linebreak="op",
+ mirror=0x29D9,
+ unicodeslot=0x29D8,
+ },
+ [0x29D9]={
+ category="pe",
+ description="RIGHT WIGGLY FENCE",
+ direction="on",
+ linebreak="cl",
+ mirror=0x29D8,
+ unicodeslot=0x29D9,
+ },
+ [0x29DA]={
+ category="ps",
+ description="LEFT DOUBLE WIGGLY FENCE",
+ direction="on",
+ linebreak="op",
+ mirror=0x29DB,
+ unicodeslot=0x29DA,
+ },
+ [0x29DB]={
+ category="pe",
+ description="RIGHT DOUBLE WIGGLY FENCE",
+ direction="on",
+ linebreak="cl",
+ mirror=0x29DA,
+ unicodeslot=0x29DB,
+ },
+ [0x29DC]={
+ category="sm",
+ description="INCOMPLETE INFINITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29DC,
+ },
+ [0x29DD]={
+ category="sm",
+ description="TIE OVER INFINITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29DD,
+ },
+ [0x29DE]={
+ category="sm",
+ description="INFINITY NEGATED WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29DE,
+ },
+ [0x29DF]={
+ category="sm",
+ description="DOUBLE-ENDED MULTIMAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29DF,
+ },
+ [0x29E0]={
+ category="sm",
+ description="SQUARE WITH CONTOURED OUTLINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E0,
+ },
+ [0x29E1]={
+ category="sm",
+ description="INCREASES AS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E1,
+ },
+ [0x29E2]={
+ category="sm",
+ description="SHUFFLE PRODUCT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E2,
+ },
+ [0x29E3]={
+ category="sm",
+ description="EQUALS SIGN AND SLANTED PARALLEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E3,
+ },
+ [0x29E4]={
+ category="sm",
+ description="EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E4,
+ },
+ [0x29E5]={
+ category="sm",
+ description="IDENTICAL TO AND SLANTED PARALLEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E5,
+ },
+ [0x29E6]={
+ category="sm",
+ description="GLEICH STARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E6,
+ },
+ [0x29E7]={
+ category="sm",
+ description="THERMODYNAMIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E7,
+ },
+ [0x29E8]={
+ category="sm",
+ description="DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E8,
+ },
+ [0x29E9]={
+ category="sm",
+ description="DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29E9,
+ },
+ [0x29EA]={
+ category="sm",
+ description="BLACK DIAMOND WITH DOWN ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="d",
+ unicodeslot=0x29EA,
+ },
+ [0x29EB]={
+ category="sm",
+ description="BLACK LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29EB,
+ },
+ [0x29EC]={
+ category="sm",
+ description="WHITE CIRCLE WITH DOWN ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="d",
+ unicodeslot=0x29EC,
+ },
+ [0x29ED]={
+ category="sm",
+ description="BLACK CIRCLE WITH DOWN ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="d",
+ unicodeslot=0x29ED,
+ },
+ [0x29EE]={
+ category="sm",
+ description="ERROR-BARRED WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29EE,
+ },
+ [0x29EF]={
+ category="sm",
+ description="ERROR-BARRED BLACK SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29EF,
+ },
+ [0x29F0]={
+ category="sm",
+ description="ERROR-BARRED WHITE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F0,
+ },
+ [0x29F1]={
+ category="sm",
+ description="ERROR-BARRED BLACK DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F1,
+ },
+ [0x29F2]={
+ category="sm",
+ description="ERROR-BARRED WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F2,
+ },
+ [0x29F3]={
+ category="sm",
+ description="ERROR-BARRED BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F3,
+ },
+ [0x29F4]={
+ category="sm",
+ description="RULE-DELAYED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F4,
+ },
+ [0x29F5]={
+ category="sm",
+ description="REVERSE SOLIDUS OPERATOR",
+ direction="on",
+ linebreak="al",
+ mirror=0x2215,
+ unicodeslot=0x29F5,
+ },
+ [0x29F6]={
+ category="sm",
+ description="SOLIDUS WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F6,
+ },
+ [0x29F7]={
+ category="sm",
+ description="REVERSE SOLIDUS WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29F7,
+ },
+ [0x29F8]={
+ category="sm",
+ description="BIG SOLIDUS",
+ direction="on",
+ linebreak="al",
+ mirror=0x29F9,
+ unicodeslot=0x29F8,
+ },
+ [0x29F9]={
+ category="sm",
+ description="BIG REVERSE SOLIDUS",
+ direction="on",
+ linebreak="al",
+ mirror=0x29F8,
+ unicodeslot=0x29F9,
+ },
+ [0x29FA]={
+ category="sm",
+ description="DOUBLE PLUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29FA,
+ },
+ [0x29FB]={
+ category="sm",
+ description="TRIPLE PLUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29FB,
+ },
+ [0x29FC]={
+ category="ps",
+ description="LEFT-POINTING CURVED ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x29FD,
+ unicodeslot=0x29FC,
+ },
+ [0x29FD]={
+ category="pe",
+ description="RIGHT-POINTING CURVED ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x29FC,
+ unicodeslot=0x29FD,
+ },
+ [0x29FE]={
+ category="sm",
+ description="TINY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29FE,
+ },
+ [0x29FF]={
+ category="sm",
+ description="MINY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x29FF,
+ },
+ [0x2A00]={
+ category="sm",
+ description="N-ARY CIRCLED DOT OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigodot",
+ unicodeslot=0x2A00,
+ },
+ [0x2A01]={
+ category="sm",
+ description="N-ARY CIRCLED PLUS OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigoplus",
+ unicodeslot=0x2A01,
+ },
+ [0x2A02]={
+ category="sm",
+ description="N-ARY CIRCLED TIMES OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigotimes",
+ unicodeslot=0x2A02,
+ },
+ [0x2A03]={
+ category="sm",
+ description="N-ARY UNION OPERATOR WITH DOT",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigudot",
+ unicodeslot=0x2A03,
+ },
+ [0x2A04]={
+ category="sm",
+ description="N-ARY UNION OPERATOR WITH PLUS",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="biguplus",
+ unicodeslot=0x2A04,
+ },
+ [0x2A05]={
+ category="sm",
+ description="N-ARY SQUARE INTERSECTION OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigsqcap",
+ unicodeslot=0x2A05,
+ },
+ [0x2A06]={
+ category="sm",
+ description="N-ARY SQUARE UNION OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigsqcup",
+ unicodeslot=0x2A06,
+ },
+ [0x2A07]={
+ category="sm",
+ description="TWO LOGICAL AND OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A07,
+ },
+ [0x2A08]={
+ category="sm",
+ description="TWO LOGICAL OR OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A08,
+ },
+ [0x2A09]={
+ category="sm",
+ description="N-ARY TIMES OPERATOR",
+ direction="on",
+ linebreak="al",
+ mathclass="limop",
+ mathname="bigtimes",
+ unicodeslot=0x2A09,
+ },
+ [0x2A0A]={
+ category="sm",
+ description="MODULO TWO SUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A0A,
+ },
+ [0x2A0B]={
+ category="sm",
+ description="SUMMATION WITH INTEGRAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A0B,
+ },
+ [0x2A0C]={
+ category="sm",
+ description="QUADRUPLE INTEGRAL OPERATOR",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x222B, 0x222B, 0x222B, 0x222B },
+ unicodeslot=0x2A0C,
+ },
+ [0x2A0D]={
+ category="sm",
+ description="FINITE PART INTEGRAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A0D,
+ },
+ [0x2A0E]={
+ category="sm",
+ description="INTEGRAL WITH DOUBLE STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A0E,
+ },
+ [0x2A0F]={
+ category="sm",
+ description="INTEGRAL AVERAGE WITH SLASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A0F,
+ },
+ [0x2A10]={
+ category="sm",
+ description="CIRCULATION FUNCTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A10,
+ },
+ [0x2A11]={
+ category="sm",
+ description="ANTICLOCKWISE INTEGRATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A11,
+ },
+ [0x2A12]={
+ category="sm",
+ description="LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A12,
+ },
+ [0x2A13]={
+ category="sm",
+ description="LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A13,
+ },
+ [0x2A14]={
+ category="sm",
+ description="LINE INTEGRATION NOT INCLUDING THE POLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A14,
+ },
+ [0x2A15]={
+ category="sm",
+ description="INTEGRAL AROUND A POINT OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A15,
+ },
+ [0x2A16]={
+ category="sm",
+ description="QUATERNION INTEGRAL OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A16,
+ },
+ [0x2A17]={
+ category="sm",
+ description="INTEGRAL WITH LEFTWARDS ARROW WITH HOOK",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2A17,
+ },
+ [0x2A18]={
+ category="sm",
+ description="INTEGRAL WITH TIMES SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A18,
+ },
+ [0x2A19]={
+ category="sm",
+ description="INTEGRAL WITH INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A19,
+ },
+ [0x2A1A]={
+ category="sm",
+ description="INTEGRAL WITH UNION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1A,
+ },
+ [0x2A1B]={
+ category="sm",
+ description="INTEGRAL WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1B,
+ },
+ [0x2A1C]={
+ category="sm",
+ description="INTEGRAL WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1C,
+ },
+ [0x2A1D]={
+ category="sm",
+ description="JOIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1D,
+ },
+ [0x2A1E]={
+ category="sm",
+ description="LARGE LEFT TRIANGLE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1E,
+ },
+ [0x2A1F]={
+ category="sm",
+ description="Z NOTATION SCHEMA COMPOSITION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A1F,
+ },
+ [0x2A20]={
+ category="sm",
+ description="Z NOTATION SCHEMA PIPING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A20,
+ },
+ [0x2A21]={
+ category="sm",
+ description="Z NOTATION SCHEMA PROJECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A21,
+ },
+ [0x2A22]={
+ category="sm",
+ description="PLUS SIGN WITH SMALL CIRCLE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A22,
+ },
+ [0x2A23]={
+ category="sm",
+ description="PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A23,
+ },
+ [0x2A24]={
+ category="sm",
+ description="PLUS SIGN WITH TILDE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A24,
+ },
+ [0x2A25]={
+ category="sm",
+ description="PLUS SIGN WITH DOT BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A25,
+ },
+ [0x2A26]={
+ category="sm",
+ description="PLUS SIGN WITH TILDE BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A26,
+ },
+ [0x2A27]={
+ category="sm",
+ description="PLUS SIGN WITH SUBSCRIPT TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A27,
+ },
+ [0x2A28]={
+ category="sm",
+ description="PLUS SIGN WITH BLACK TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A28,
+ },
+ [0x2A29]={
+ category="sm",
+ description="MINUS SIGN WITH COMMA ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A29,
+ },
+ [0x2A2A]={
+ category="sm",
+ description="MINUS SIGN WITH DOT BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A2A,
+ },
+ [0x2A2B]={
+ category="sm",
+ description="MINUS SIGN WITH FALLING DOTS",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A2C,
+ unicodeslot=0x2A2B,
+ },
+ [0x2A2C]={
+ category="sm",
+ description="MINUS SIGN WITH RISING DOTS",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A2B,
+ unicodeslot=0x2A2C,
+ },
+ [0x2A2D]={
+ category="sm",
+ description="PLUS SIGN IN LEFT HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A2E,
+ unicodeslot=0x2A2D,
+ },
+ [0x2A2E]={
+ category="sm",
+ description="PLUS SIGN IN RIGHT HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A2D,
+ unicodeslot=0x2A2E,
+ },
+ [0x2A2F]={
+ category="sm",
+ description="VECTOR OR CROSS PRODUCT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A2F,
+ },
+ [0x2A30]={
+ category="sm",
+ description="MULTIPLICATION SIGN WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A30,
+ },
+ [0x2A31]={
+ category="sm",
+ description="MULTIPLICATION SIGN WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A31,
+ },
+ [0x2A32]={
+ category="sm",
+ description="SEMIDIRECT PRODUCT WITH BOTTOM CLOSED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A32,
+ },
+ [0x2A33]={
+ category="sm",
+ description="SMASH PRODUCT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A33,
+ },
+ [0x2A34]={
+ category="sm",
+ description="MULTIPLICATION SIGN IN LEFT HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A35,
+ unicodeslot=0x2A34,
+ },
+ [0x2A35]={
+ category="sm",
+ description="MULTIPLICATION SIGN IN RIGHT HALF CIRCLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A34,
+ unicodeslot=0x2A35,
+ },
+ [0x2A36]={
+ category="sm",
+ description="CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A36,
+ },
+ [0x2A37]={
+ category="sm",
+ description="MULTIPLICATION SIGN IN DOUBLE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A37,
+ },
+ [0x2A38]={
+ category="sm",
+ description="CIRCLED DIVISION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A38,
+ },
+ [0x2A39]={
+ category="sm",
+ description="PLUS SIGN IN TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A39,
+ },
+ [0x2A3A]={
+ category="sm",
+ description="MINUS SIGN IN TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A3A,
+ },
+ [0x2A3B]={
+ category="sm",
+ description="MULTIPLICATION SIGN IN TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A3B,
+ },
+ [0x2A3C]={
+ category="sm",
+ description="INTERIOR PRODUCT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A3D,
+ unicodeslot=0x2A3C,
+ variants={
+ [0xFE00]="tall variant with narrow foot",
+ },
+ },
+ [0x2A3D]={
+ category="sm",
+ description="RIGHTHAND INTERIOR PRODUCT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A3C,
+ unicodeslot=0x2A3D,
+ variants={
+ [0xFE00]="tall variant with narrow foot",
+ },
+ },
+ [0x2A3E]={
+ category="sm",
+ description="Z NOTATION RELATIONAL COMPOSITION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A3E,
+ },
+ [0x2A3F]={
+ category="sm",
+ description="AMALGAMATION OR COPRODUCT",
+ direction="on",
+ linebreak="al",
+ mathclass="binary",
+ mathname="amalg",
+ unicodeslot=0x2A3F,
+ },
+ [0x2A40]={
+ category="sm",
+ description="INTERSECTION WITH DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A40,
+ },
+ [0x2A41]={
+ category="sm",
+ description="UNION WITH MINUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A41,
+ },
+ [0x2A42]={
+ category="sm",
+ description="UNION WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A42,
+ },
+ [0x2A43]={
+ category="sm",
+ description="INTERSECTION WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A43,
+ },
+ [0x2A44]={
+ category="sm",
+ description="INTERSECTION WITH LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A44,
+ },
+ [0x2A45]={
+ category="sm",
+ description="UNION WITH LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A45,
+ },
+ [0x2A46]={
+ category="sm",
+ description="UNION ABOVE INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A46,
+ },
+ [0x2A47]={
+ category="sm",
+ description="INTERSECTION ABOVE UNION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A47,
+ },
+ [0x2A48]={
+ category="sm",
+ description="UNION ABOVE BAR ABOVE INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A48,
+ },
+ [0x2A49]={
+ category="sm",
+ description="INTERSECTION ABOVE BAR ABOVE UNION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A49,
+ },
+ [0x2A4A]={
+ category="sm",
+ description="UNION BESIDE AND JOINED WITH UNION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4A,
+ },
+ [0x2A4B]={
+ category="sm",
+ description="INTERSECTION BESIDE AND JOINED WITH INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4B,
+ },
+ [0x2A4C]={
+ category="sm",
+ description="CLOSED UNION WITH SERIFS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4C,
+ },
+ [0x2A4D]={
+ category="sm",
+ description="CLOSED INTERSECTION WITH SERIFS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4D,
+ },
+ [0x2A4E]={
+ category="sm",
+ description="DOUBLE SQUARE INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4E,
+ },
+ [0x2A4F]={
+ category="sm",
+ description="DOUBLE SQUARE UNION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A4F,
+ },
+ [0x2A50]={
+ category="sm",
+ description="CLOSED UNION WITH SERIFS AND SMASH PRODUCT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A50,
+ },
+ [0x2A51]={
+ category="sm",
+ description="LOGICAL AND WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A51,
+ },
+ [0x2A52]={
+ category="sm",
+ description="LOGICAL OR WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A52,
+ },
+ [0x2A53]={
+ category="sm",
+ description="DOUBLE LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A53,
+ },
+ [0x2A54]={
+ category="sm",
+ description="DOUBLE LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A54,
+ },
+ [0x2A55]={
+ category="sm",
+ description="TWO INTERSECTING LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A55,
+ },
+ [0x2A56]={
+ category="sm",
+ description="TWO INTERSECTING LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A56,
+ },
+ [0x2A57]={
+ category="sm",
+ description="SLOPING LARGE OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A57,
+ },
+ [0x2A58]={
+ category="sm",
+ description="SLOPING LARGE AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A58,
+ },
+ [0x2A59]={
+ category="sm",
+ description="LOGICAL OR OVERLAPPING LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A59,
+ },
+ [0x2A5A]={
+ category="sm",
+ description="LOGICAL AND WITH MIDDLE STEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5A,
+ },
+ [0x2A5B]={
+ category="sm",
+ description="LOGICAL OR WITH MIDDLE STEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5B,
+ },
+ [0x2A5C]={
+ category="sm",
+ description="LOGICAL AND WITH HORIZONTAL DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5C,
+ },
+ [0x2A5D]={
+ category="sm",
+ description="LOGICAL OR WITH HORIZONTAL DASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5D,
+ },
+ [0x2A5E]={
+ category="sm",
+ description="LOGICAL AND WITH DOUBLE OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5E,
+ },
+ [0x2A5F]={
+ category="sm",
+ description="LOGICAL AND WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A5F,
+ },
+ [0x2A60]={
+ category="sm",
+ description="LOGICAL AND WITH DOUBLE UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A60,
+ },
+ [0x2A61]={
+ category="sm",
+ description="SMALL VEE WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A61,
+ },
+ [0x2A62]={
+ category="sm",
+ description="LOGICAL OR WITH DOUBLE OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A62,
+ },
+ [0x2A63]={
+ category="sm",
+ description="LOGICAL OR WITH DOUBLE UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A63,
+ },
+ [0x2A64]={
+ category="sm",
+ description="Z NOTATION DOMAIN ANTIRESTRICTION",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A65,
+ unicodeslot=0x2A64,
+ },
+ [0x2A65]={
+ category="sm",
+ description="Z NOTATION RANGE ANTIRESTRICTION",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A64,
+ unicodeslot=0x2A65,
+ },
+ [0x2A66]={
+ category="sm",
+ description="EQUALS SIGN WITH DOT BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A66,
+ },
+ [0x2A67]={
+ category="sm",
+ description="IDENTICAL WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A67,
+ },
+ [0x2A68]={
+ category="sm",
+ description="TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A68,
+ },
+ [0x2A69]={
+ category="sm",
+ description="TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A69,
+ },
+ [0x2A6A]={
+ category="sm",
+ description="TILDE OPERATOR WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6A,
+ },
+ [0x2A6B]={
+ category="sm",
+ description="TILDE OPERATOR WITH RISING DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6B,
+ },
+ [0x2A6C]={
+ category="sm",
+ description="SIMILAR MINUS SIMILAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6C,
+ },
+ [0x2A6D]={
+ category="sm",
+ description="CONGRUENT WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6D,
+ },
+ [0x2A6E]={
+ category="sm",
+ description="EQUALS WITH ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6E,
+ },
+ [0x2A6F]={
+ category="sm",
+ description="ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A6F,
+ },
+ [0x2A70]={
+ category="sm",
+ description="APPROXIMATELY EQUAL OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A70,
+ },
+ [0x2A71]={
+ category="sm",
+ description="EQUALS SIGN ABOVE PLUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A71,
+ },
+ [0x2A72]={
+ category="sm",
+ description="PLUS SIGN ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A72,
+ },
+ [0x2A73]={
+ category="sm",
+ description="EQUALS SIGN ABOVE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A73,
+ },
+ [0x2A74]={
+ category="sm",
+ description="DOUBLE COLON EQUAL",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="coloncolonequals",
+ specials={ "compat", 0x3A, 0x3A, 0x3D },
+ unicodeslot=0x2A74,
+ },
+ [0x2A75]={
+ category="sm",
+ description="TWO CONSECUTIVE EQUALS SIGNS",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x3D, 0x3D },
+ unicodeslot=0x2A75,
+ },
+ [0x2A76]={
+ category="sm",
+ description="THREE CONSECUTIVE EQUALS SIGNS",
+ direction="on",
+ linebreak="al",
+ specials={ "compat", 0x3D, 0x3D, 0x3D },
+ unicodeslot=0x2A76,
+ },
+ [0x2A77]={
+ category="sm",
+ description="EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A77,
+ },
+ [0x2A78]={
+ category="sm",
+ description="EQUIVALENT WITH FOUR DOTS ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A78,
+ },
+ [0x2A79]={
+ category="sm",
+ description="LESS-THAN WITH CIRCLE INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A7A,
+ unicodeslot=0x2A79,
+ },
+ [0x2A7A]={
+ category="sm",
+ description="GREATER-THAN WITH CIRCLE INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A79,
+ unicodeslot=0x2A7A,
+ },
+ [0x2A7B]={
+ category="sm",
+ description="LESS-THAN WITH QUESTION MARK ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A7B,
+ },
+ [0x2A7C]={
+ category="sm",
+ description="GREATER-THAN WITH QUESTION MARK ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A7C,
+ },
+ [0x2A7D]={
+ category="sm",
+ description="LESS-THAN OR SLANTED EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="leqslant",
+ mirror=0x2A7E,
+ unicodeslot=0x2A7D,
+ },
+ [0x2A7E]={
+ category="sm",
+ description="GREATER-THAN OR SLANTED EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="geqslant",
+ mirror=0x2A7D,
+ unicodeslot=0x2A7E,
+ },
+ [0x2A7F]={
+ category="sm",
+ description="LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A80,
+ unicodeslot=0x2A7F,
+ },
+ [0x2A80]={
+ category="sm",
+ description="GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A7F,
+ unicodeslot=0x2A80,
+ },
+ [0x2A81]={
+ category="sm",
+ description="LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A82,
+ unicodeslot=0x2A81,
+ },
+ [0x2A82]={
+ category="sm",
+ description="GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A81,
+ unicodeslot=0x2A82,
+ },
+ [0x2A83]={
+ category="sm",
+ description="LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A84,
+ unicodeslot=0x2A83,
+ },
+ [0x2A84]={
+ category="sm",
+ description="GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A83,
+ unicodeslot=0x2A84,
+ },
+ [0x2A85]={
+ category="sm",
+ description="LESS-THAN OR APPROXIMATE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lessapprox",
+ unicodeslot=0x2A85,
+ },
+ [0x2A86]={
+ category="sm",
+ description="GREATER-THAN OR APPROXIMATE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gtrapprox",
+ unicodeslot=0x2A86,
+ },
+ [0x2A87]={
+ category="sm",
+ description="LESS-THAN AND SINGLE-LINE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lneq",
+ unicodeslot=0x2A87,
+ },
+ [0x2A88]={
+ category="sm",
+ description="GREATER-THAN AND SINGLE-LINE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="rneq",
+ unicodeslot=0x2A88,
+ },
+ [0x2A89]={
+ category="sm",
+ description="LESS-THAN AND NOT APPROXIMATE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lnapprox",
+ unicodeslot=0x2A89,
+ },
+ [0x2A8A]={
+ category="sm",
+ description="GREATER-THAN AND NOT APPROXIMATE",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gnapprox",
+ unicodeslot=0x2A8A,
+ },
+ [0x2A8B]={
+ category="sm",
+ description="LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="lesseqqgtr",
+ mirror=0x2A8C,
+ unicodeslot=0x2A8B,
+ },
+ [0x2A8C]={
+ category="sm",
+ description="GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="gtreqqless",
+ mirror=0x2A8B,
+ unicodeslot=0x2A8C,
+ },
+ [0x2A8D]={
+ category="sm",
+ description="LESS-THAN ABOVE SIMILAR OR EQUAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A8D,
+ },
+ [0x2A8E]={
+ category="sm",
+ description="GREATER-THAN ABOVE SIMILAR OR EQUAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A8E,
+ },
+ [0x2A8F]={
+ category="sm",
+ description="LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A8F,
+ },
+ [0x2A90]={
+ category="sm",
+ description="GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A90,
+ },
+ [0x2A91]={
+ category="sm",
+ description="LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A92,
+ unicodeslot=0x2A91,
+ },
+ [0x2A92]={
+ category="sm",
+ description="GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A91,
+ unicodeslot=0x2A92,
+ },
+ [0x2A93]={
+ category="sm",
+ description="LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A94,
+ unicodeslot=0x2A93,
+ },
+ [0x2A94]={
+ category="sm",
+ description="GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A93,
+ unicodeslot=0x2A94,
+ },
+ [0x2A95]={
+ category="sm",
+ description="SLANTED EQUAL TO OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqslantless",
+ mirror=0x2A96,
+ unicodeslot=0x2A95,
+ },
+ [0x2A96]={
+ category="sm",
+ description="SLANTED EQUAL TO OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="eqslantgtr",
+ mirror=0x2A95,
+ unicodeslot=0x2A96,
+ },
+ [0x2A97]={
+ category="sm",
+ description="SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A98,
+ unicodeslot=0x2A97,
+ },
+ [0x2A98]={
+ category="sm",
+ description="SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A97,
+ unicodeslot=0x2A98,
+ },
+ [0x2A99]={
+ category="sm",
+ description="DOUBLE-LINE EQUAL TO OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A9A,
+ unicodeslot=0x2A99,
+ },
+ [0x2A9A]={
+ category="sm",
+ description="DOUBLE-LINE EQUAL TO OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A99,
+ unicodeslot=0x2A9A,
+ },
+ [0x2A9B]={
+ category="sm",
+ description="DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A9C,
+ unicodeslot=0x2A9B,
+ },
+ [0x2A9C]={
+ category="sm",
+ description="DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2A9B,
+ unicodeslot=0x2A9C,
+ },
+ [0x2A9D]={
+ category="sm",
+ description="SIMILAR OR LESS-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A9D,
+ variants={
+ [0xFE00]="with similar following the slant of the upper leg",
+ },
+ },
+ [0x2A9E]={
+ category="sm",
+ description="SIMILAR OR GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A9E,
+ variants={
+ [0xFE00]="with similar following the slant of the upper leg",
+ },
+ },
+ [0x2A9F]={
+ category="sm",
+ description="SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2A9F,
+ },
+ [0x2AA0]={
+ category="sm",
+ description="SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AA0,
+ },
+ [0x2AA1]={
+ category="sm",
+ description="DOUBLE NESTED LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA2,
+ unicodeslot=0x2AA1,
+ },
+ [0x2AA2]={
+ category="sm",
+ description="DOUBLE NESTED GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA1,
+ unicodeslot=0x2AA2,
+ },
+ [0x2AA3]={
+ category="sm",
+ description="DOUBLE NESTED LESS-THAN WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AA3,
+ },
+ [0x2AA4]={
+ category="sm",
+ description="GREATER-THAN OVERLAPPING LESS-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AA4,
+ },
+ [0x2AA5]={
+ category="sm",
+ description="GREATER-THAN BESIDE LESS-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AA5,
+ },
+ [0x2AA6]={
+ category="sm",
+ description="LESS-THAN CLOSED BY CURVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA7,
+ unicodeslot=0x2AA6,
+ },
+ [0x2AA7]={
+ category="sm",
+ description="GREATER-THAN CLOSED BY CURVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA6,
+ unicodeslot=0x2AA7,
+ },
+ [0x2AA8]={
+ category="sm",
+ description="LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA9,
+ unicodeslot=0x2AA8,
+ },
+ [0x2AA9]={
+ category="sm",
+ description="GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AA8,
+ unicodeslot=0x2AA9,
+ },
+ [0x2AAA]={
+ category="sm",
+ description="SMALLER THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AAB,
+ unicodeslot=0x2AAA,
+ },
+ [0x2AAB]={
+ category="sm",
+ description="LARGER THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AAA,
+ unicodeslot=0x2AAB,
+ },
+ [0x2AAC]={
+ category="sm",
+ description="SMALLER THAN OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AAD,
+ unicodeslot=0x2AAC,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
+ },
+ [0x2AAD]={
+ category="sm",
+ description="LARGER THAN OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AAC,
+ unicodeslot=0x2AAD,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
+ },
+ [0x2AAE]={
+ category="sm",
+ description="EQUALS SIGN WITH BUMPY ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AAE,
+ },
+ [0x2AAF]={
+ category="sm",
+ description="PRECEDES ABOVE SINGLE-LINE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="preceq",
+ mirror=0x2AB0,
+ unicodeslot=0x2AAF,
+ },
+ [0x2AB0]={
+ category="sm",
+ description="SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succeq",
+ mirror=0x2AAF,
+ unicodeslot=0x2AB0,
+ },
+ [0x2AB1]={
+ category="sm",
+ description="PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precneq",
+ unicodeslot=0x2AB1,
+ },
+ [0x2AB2]={
+ category="sm",
+ description="SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succneq",
+ unicodeslot=0x2AB2,
+ },
+ [0x2AB3]={
+ category="sm",
+ description="PRECEDES ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="preceqq",
+ mirror=0x2AB4,
+ unicodeslot=0x2AB3,
+ },
+ [0x2AB4]={
+ category="sm",
+ description="SUCCEEDS ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succeqq",
+ mirror=0x2AB3,
+ unicodeslot=0x2AB4,
+ },
+ [0x2AB5]={
+ category="sm",
+ description="PRECEDES ABOVE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precneqq",
+ unicodeslot=0x2AB5,
+ },
+ [0x2AB6]={
+ category="sm",
+ description="SUCCEEDS ABOVE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succneqq",
+ unicodeslot=0x2AB6,
+ },
+ [0x2AB7]={
+ category="sm",
+ description="PRECEDES ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precapprox",
+ unicodeslot=0x2AB7,
+ },
+ [0x2AB8]={
+ category="sm",
+ description="SUCCEEDS ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succapprox",
+ unicodeslot=0x2AB8,
+ },
+ [0x2AB9]={
+ category="sm",
+ description="PRECEDES ABOVE NOT ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="precnapprox",
+ unicodeslot=0x2AB9,
+ },
+ [0x2ABA]={
+ category="sm",
+ description="SUCCEEDS ABOVE NOT ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="succnapprox",
+ unicodeslot=0x2ABA,
+ },
+ [0x2ABB]={
+ category="sm",
+ description="DOUBLE PRECEDES",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ABC,
+ unicodeslot=0x2ABB,
+ },
+ [0x2ABC]={
+ category="sm",
+ description="DOUBLE SUCCEEDS",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ABB,
+ unicodeslot=0x2ABC,
+ },
+ [0x2ABD]={
+ category="sm",
+ description="SUBSET WITH DOT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ABE,
+ unicodeslot=0x2ABD,
+ },
+ [0x2ABE]={
+ category="sm",
+ description="SUPERSET WITH DOT",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ABD,
+ unicodeslot=0x2ABE,
+ },
+ [0x2ABF]={
+ category="sm",
+ description="SUBSET WITH PLUS SIGN BELOW",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AC0,
+ unicodeslot=0x2ABF,
+ },
+ [0x2AC0]={
+ category="sm",
+ description="SUPERSET WITH PLUS SIGN BELOW",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ABF,
+ unicodeslot=0x2AC0,
+ },
+ [0x2AC1]={
+ category="sm",
+ description="SUBSET WITH MULTIPLICATION SIGN BELOW",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AC2,
+ unicodeslot=0x2AC1,
+ },
+ [0x2AC2]={
+ category="sm",
+ description="SUPERSET WITH MULTIPLICATION SIGN BELOW",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AC1,
+ unicodeslot=0x2AC2,
+ },
+ [0x2AC3]={
+ category="sm",
+ description="SUBSET OF OR EQUAL TO WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AC4,
+ unicodeslot=0x2AC3,
+ },
+ [0x2AC4]={
+ category="sm",
+ description="SUPERSET OF OR EQUAL TO WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AC3,
+ unicodeslot=0x2AC4,
+ },
+ [0x2AC5]={
+ category="sm",
+ description="SUBSET OF ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="subseteqq",
+ mirror=0x2AC6,
+ unicodeslot=0x2AC5,
+ },
+ [0x2AC6]={
+ category="sm",
+ description="SUPERSET OF ABOVE EQUALS SIGN",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="supseteqq",
+ mirror=0x2AC5,
+ unicodeslot=0x2AC6,
+ },
+ [0x2AC7]={
+ category="sm",
+ description="SUBSET OF ABOVE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AC7,
+ },
+ [0x2AC8]={
+ category="sm",
+ description="SUPERSET OF ABOVE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AC8,
+ },
+ [0x2AC9]={
+ category="sm",
+ description="SUBSET OF ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AC9,
+ },
+ [0x2ACA]={
+ category="sm",
+ description="SUPERSET OF ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ACA,
+ },
+ [0x2ACB]={
+ category="sm",
+ description="SUBSET OF ABOVE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="subsetneqq",
+ unicodeslot=0x2ACB,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
+ },
+ [0x2ACC]={
+ category="sm",
+ description="SUPERSET OF ABOVE NOT EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mathclass="relation",
+ mathname="supsetneqq",
+ unicodeslot=0x2ACC,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
+ },
+ [0x2ACD]={
+ category="sm",
+ description="SQUARE LEFT OPEN BOX OPERATOR",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ACE,
+ unicodeslot=0x2ACD,
+ },
+ [0x2ACE]={
+ category="sm",
+ description="SQUARE RIGHT OPEN BOX OPERATOR",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ACD,
+ unicodeslot=0x2ACE,
+ },
+ [0x2ACF]={
+ category="sm",
+ description="CLOSED SUBSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD0,
+ unicodeslot=0x2ACF,
+ },
+ [0x2AD0]={
+ category="sm",
+ description="CLOSED SUPERSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2ACF,
+ unicodeslot=0x2AD0,
+ },
+ [0x2AD1]={
+ category="sm",
+ description="CLOSED SUBSET OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD2,
+ unicodeslot=0x2AD1,
+ },
+ [0x2AD2]={
+ category="sm",
+ description="CLOSED SUPERSET OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD1,
+ unicodeslot=0x2AD2,
+ },
+ [0x2AD3]={
+ category="sm",
+ description="SUBSET ABOVE SUPERSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD4,
+ unicodeslot=0x2AD3,
+ },
+ [0x2AD4]={
+ category="sm",
+ description="SUPERSET ABOVE SUBSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD3,
+ unicodeslot=0x2AD4,
+ },
+ [0x2AD5]={
+ category="sm",
+ description="SUBSET ABOVE SUBSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD6,
+ unicodeslot=0x2AD5,
+ },
+ [0x2AD6]={
+ category="sm",
+ description="SUPERSET ABOVE SUPERSET",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AD5,
+ unicodeslot=0x2AD6,
+ },
+ [0x2AD7]={
+ category="sm",
+ description="SUPERSET BESIDE SUBSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AD7,
+ },
+ [0x2AD8]={
+ category="sm",
+ description="SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AD8,
+ },
+ [0x2AD9]={
+ category="sm",
+ description="ELEMENT OF OPENING DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AD9,
+ },
+ [0x2ADA]={
+ category="sm",
+ description="PITCHFORK WITH TEE TOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ADA,
+ },
+ [0x2ADB]={
+ category="sm",
+ description="TRANSVERSAL INTERSECTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ADB,
+ },
+ [0x2ADC]={
+ category="sm",
+ description="FORKING",
+ direction="on",
+ linebreak="al",
+ specials={ "char", 0x2ADD, 0x338 },
+ unicodeslot=0x2ADC,
+ },
+ [0x2ADD]={
+ category="sm",
+ description="NONFORKING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ADD,
+ },
+ [0x2ADE]={
+ category="sm",
+ description="SHORT LEFT TACK",
+ direction="on",
+ linebreak="al",
+ mirror=0x22A6,
+ unicodeslot=0x2ADE,
+ },
+ [0x2ADF]={
+ category="sm",
+ description="SHORT DOWN TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2ADF,
+ },
+ [0x2AE0]={
+ category="sm",
+ description="SHORT UP TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE0,
+ },
+ [0x2AE1]={
+ category="sm",
+ description="PERPENDICULAR WITH S",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE1,
+ },
+ [0x2AE2]={
+ category="sm",
+ description="VERTICAL BAR TRIPLE RIGHT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE2,
+ },
+ [0x2AE3]={
+ category="sm",
+ description="DOUBLE VERTICAL BAR LEFT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22A9,
+ unicodeslot=0x2AE3,
+ },
+ [0x2AE4]={
+ category="sm",
+ description="VERTICAL BAR DOUBLE LEFT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22A8,
+ unicodeslot=0x2AE4,
+ },
+ [0x2AE5]={
+ category="sm",
+ description="DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE",
+ direction="on",
+ linebreak="al",
+ mirror=0x22AB,
+ unicodeslot=0x2AE5,
+ },
+ [0x2AE6]={
+ category="sm",
+ description="LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE6,
+ },
+ [0x2AE7]={
+ category="sm",
+ description="SHORT DOWN TACK WITH OVERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE7,
+ },
+ [0x2AE8]={
+ category="sm",
+ description="SHORT UP TACK WITH UNDERBAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE8,
+ },
+ [0x2AE9]={
+ category="sm",
+ description="SHORT UP TACK ABOVE SHORT DOWN TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AE9,
+ },
+ [0x2AEA]={
+ category="sm",
+ description="DOUBLE DOWN TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AEA,
+ },
+ [0x2AEB]={
+ category="sm",
+ description="DOUBLE UP TACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AEB,
+ },
+ [0x2AEC]={
+ category="sm",
+ description="DOUBLE STROKE NOT SIGN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AED,
+ unicodeslot=0x2AEC,
+ },
+ [0x2AED]={
+ category="sm",
+ description="REVERSED DOUBLE STROKE NOT SIGN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AEC,
+ unicodeslot=0x2AED,
+ },
+ [0x2AEE]={
+ category="sm",
+ description="DOES NOT DIVIDE WITH REVERSED NEGATION SLASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AEE,
+ },
+ [0x2AEF]={
+ category="sm",
+ description="VERTICAL LINE WITH CIRCLE ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AEF,
+ },
+ [0x2AF0]={
+ category="sm",
+ description="VERTICAL LINE WITH CIRCLE BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF0,
+ },
+ [0x2AF1]={
+ category="sm",
+ description="DOWN TACK WITH CIRCLE BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF1,
+ },
+ [0x2AF2]={
+ category="sm",
+ description="PARALLEL WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF2,
+ },
+ [0x2AF3]={
+ category="sm",
+ description="PARALLEL WITH TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF3,
+ },
+ [0x2AF4]={
+ category="sm",
+ description="TRIPLE VERTICAL BAR BINARY RELATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF4,
+ },
+ [0x2AF5]={
+ category="sm",
+ description="TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF5,
+ },
+ [0x2AF6]={
+ category="sm",
+ description="TRIPLE COLON OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AF6,
+ },
+ [0x2AF7]={
+ category="sm",
+ description="TRIPLE NESTED LESS-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AF8,
+ unicodeslot=0x2AF7,
+ },
+ [0x2AF8]={
+ category="sm",
+ description="TRIPLE NESTED GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AF7,
+ unicodeslot=0x2AF8,
+ },
+ [0x2AF9]={
+ category="sm",
+ description="DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AFA,
+ unicodeslot=0x2AF9,
+ },
+ [0x2AFA]={
+ category="sm",
+ description="DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO",
+ direction="on",
+ linebreak="al",
+ mirror=0x2AF9,
+ unicodeslot=0x2AFA,
+ },
+ [0x2AFB]={
+ category="sm",
+ description="TRIPLE SOLIDUS BINARY RELATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AFB,
+ },
+ [0x2AFC]={
+ category="sm",
+ description="LARGE TRIPLE VERTICAL BAR OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AFC,
+ },
+ [0x2AFD]={
+ category="sm",
+ description="DOUBLE SOLIDUS OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AFD,
+ },
+ [0x2AFE]={
+ category="sm",
+ description="WHITE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AFE,
+ },
+ [0x2AFF]={
+ category="sm",
+ description="N-ARY WHITE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2AFF,
+ },
+ [0x2B00]={
+ category="so",
+ description="NORTH EAST WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B00,
+ },
+ [0x2B01]={
+ category="so",
+ description="NORTH WEST WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B01,
+ },
+ [0x2B02]={
+ category="so",
+ description="SOUTH EAST WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B02,
+ },
+ [0x2B03]={
+ category="so",
+ description="SOUTH WEST WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B03,
+ },
+ [0x2B04]={
+ category="so",
+ description="LEFT RIGHT WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B04,
+ },
+ [0x2B05]={
+ category="so",
+ description="LEFTWARDS BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B05,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B06]={
+ category="so",
+ description="UPWARDS BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B06,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B07]={
+ category="so",
+ description="DOWNWARDS BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B07,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B08]={
+ category="so",
+ description="NORTH EAST BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B08,
+ },
+ [0x2B09]={
+ category="so",
+ description="NORTH WEST BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B09,
+ },
+ [0x2B0A]={
+ category="so",
+ description="SOUTH EAST BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0A,
+ },
+ [0x2B0B]={
+ category="so",
+ description="SOUTH WEST BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0B,
+ },
+ [0x2B0C]={
+ category="so",
+ description="LEFT RIGHT BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0C,
+ },
+ [0x2B0D]={
+ category="so",
+ description="UP DOWN BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0D,
+ },
+ [0x2B0E]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH TIP DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0E,
+ },
+ [0x2B0F]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH TIP UPWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B0F,
+ },
+ [0x2B10]={
+ category="so",
+ description="LEFTWARDS ARROW WITH TIP DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B10,
+ },
+ [0x2B11]={
+ category="so",
+ description="LEFTWARDS ARROW WITH TIP UPWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B11,
+ },
+ [0x2B12]={
+ category="so",
+ description="SQUARE WITH TOP HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B12,
+ },
+ [0x2B13]={
+ category="so",
+ description="SQUARE WITH BOTTOM HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B13,
+ },
+ [0x2B14]={
+ category="so",
+ description="SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B14,
+ },
+ [0x2B15]={
+ category="so",
+ description="SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B15,
+ },
+ [0x2B16]={
+ category="so",
+ description="DIAMOND WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B16,
+ },
+ [0x2B17]={
+ category="so",
+ description="DIAMOND WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B17,
+ },
+ [0x2B18]={
+ category="so",
+ description="DIAMOND WITH TOP HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B18,
+ },
+ [0x2B19]={
+ category="so",
+ description="DIAMOND WITH BOTTOM HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B19,
+ },
+ [0x2B1A]={
+ category="so",
+ description="DOTTED SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1A,
+ },
+ [0x2B1B]={
+ category="so",
+ description="BLACK LARGE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B1C]={
+ category="so",
+ description="WHITE LARGE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B1D]={
+ category="so",
+ description="BLACK VERY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1D,
+ },
+ [0x2B1E]={
+ category="so",
+ description="WHITE VERY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1E,
+ },
+ [0x2B1F]={
+ category="so",
+ description="BLACK PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1F,
+ },
+ [0x2B20]={
+ category="so",
+ description="WHITE PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B20,
+ },
+ [0x2B21]={
+ category="so",
+ description="WHITE HEXAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B21,
+ },
+ [0x2B22]={
+ category="so",
+ description="BLACK HEXAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B22,
+ },
+ [0x2B23]={
+ category="so",
+ description="HORIZONTAL BLACK HEXAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B23,
+ },
+ [0x2B24]={
+ category="so",
+ description="BLACK LARGE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B24,
+ },
+ [0x2B25]={
+ category="so",
+ description="BLACK MEDIUM DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B25,
+ },
+ [0x2B26]={
+ category="so",
+ description="WHITE MEDIUM DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B26,
+ },
+ [0x2B27]={
+ category="so",
+ description="BLACK MEDIUM LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B27,
+ },
+ [0x2B28]={
+ category="so",
+ description="WHITE MEDIUM LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B28,
+ },
+ [0x2B29]={
+ category="so",
+ description="BLACK SMALL DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B29,
+ },
+ [0x2B2A]={
+ category="so",
+ description="BLACK SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2A,
+ },
+ [0x2B2B]={
+ category="so",
+ description="WHITE SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2B,
+ },
+ [0x2B2C]={
+ category="so",
+ description="BLACK HORIZONTAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2C,
+ },
+ [0x2B2D]={
+ category="so",
+ description="WHITE HORIZONTAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2D,
+ },
+ [0x2B2E]={
+ category="so",
+ description="BLACK VERTICAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2E,
+ },
+ [0x2B2F]={
+ category="so",
+ description="WHITE VERTICAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2F,
+ },
+ [0x2B30]={
+ category="sm",
+ description="LEFT ARROW WITH SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B30,
+ },
+ [0x2B31]={
+ category="sm",
+ description="THREE LEFTWARDS ARROWS",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B31,
+ },
+ [0x2B32]={
+ category="sm",
+ description="LEFT ARROW WITH CIRCLED PLUS",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B32,
+ },
+ [0x2B33]={
+ category="sm",
+ description="LONG LEFTWARDS SQUIGGLE ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B33,
+ },
+ [0x2B34]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B34,
+ },
+ [0x2B35]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B35,
+ },
+ [0x2B36]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B36,
+ },
+ [0x2B37]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED TRIPLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B37,
+ },
+ [0x2B38]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH DOTTED STEM",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B38,
+ },
+ [0x2B39]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B39,
+ },
+ [0x2B3A]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B3A,
+ },
+ [0x2B3B]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B3B,
+ },
+ [0x2B3C]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B3C,
+ },
+ [0x2B3D]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B3D,
+ },
+ [0x2B3E]={
+ category="sm",
+ description="LEFTWARDS ARROW THROUGH X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3E,
+ },
+ [0x2B3F]={
+ category="sm",
+ description="WAVE ARROW POINTING DIRECTLY LEFT",
+ direction="on",
+ linebreak="al",
+ mathextensible="l",
+ unicodeslot=0x2B3F,
+ },
+ [0x2B40]={
+ category="sm",
+ description="EQUALS SIGN ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B40,
+ },
+ [0x2B41]={
+ category="sm",
+ description="REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B41,
+ },
+ [0x2B42]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B42,
+ },
+ [0x2B43]={
+ category="sm",
+ description="RIGHTWARDS ARROW THROUGH GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B43,
+ },
+ [0x2B44]={
+ category="sm",
+ description="RIGHTWARDS ARROW THROUGH SUPERSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B44,
+ },
+ [0x2B45]={
+ category="so",
+ description="LEFTWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B45,
+ },
+ [0x2B46]={
+ category="so",
+ description="RIGHTWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B46,
+ },
+ [0x2B47]={
+ category="sm",
+ description="REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B47,
+ },
+ [0x2B48]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B48,
+ },
+ [0x2B49]={
+ category="sm",
+ description="TILDE OPERATOR ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B49,
+ },
+ [0x2B4A]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4A,
+ },
+ [0x2B4B]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4B,
+ },
+ [0x2B4C]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4C,
+ },
+ [0x2B4D]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4D,
+ },
+ [0x2B4E]={
+ category="so",
+ description="SHORT SLANTED NORTH ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4E,
+ },
+ [0x2B4F]={
+ category="so",
+ description="SHORT BACKSLANTED SOUTH ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4F,
+ },
+ [0x2B50]={
+ category="so",
+ description="WHITE MEDIUM STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B50,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B51]={
+ category="so",
+ description="BLACK SMALL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B51,
+ },
+ [0x2B52]={
+ category="so",
+ description="WHITE SMALL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B52,
+ },
+ [0x2B53]={
+ category="so",
+ description="BLACK RIGHT-POINTING PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B53,
+ },
+ [0x2B54]={
+ category="so",
+ description="WHITE RIGHT-POINTING PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B54,
+ },
+ [0x2B55]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY LARGE CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B55,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x2B56]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY OVAL WITH OVAL INSIDE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B56,
+ },
+ [0x2B57]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE WITH CIRCLE INSIDE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B57,
+ },
+ [0x2B58]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B58,
+ },
+ [0x2B59]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLED SALTIRE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B59,
+ },
+ [0x2B5A]={
+ category="so",
+ description="SLANTED NORTH ARROW WITH HOOKED HEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5A,
+ },
+ [0x2B5B]={
+ category="so",
+ description="BACKSLANTED SOUTH ARROW WITH HOOKED TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5B,
+ },
+ [0x2B5C]={
+ category="so",
+ description="SLANTED NORTH ARROW WITH HORIZONTAL TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5C,
+ },
+ [0x2B5D]={
+ category="so",
+ description="BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5D,
+ },
+ [0x2B5E]={
+ category="so",
+ description="BENT ARROW POINTING DOWNWARDS THEN NORTH EAST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5E,
+ },
+ [0x2B5F]={
+ category="so",
+ description="SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B5F,
+ },
+ [0x2B60]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B60,
+ },
+ [0x2B61]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B61,
+ },
+ [0x2B62]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B62,
+ },
+ [0x2B63]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B63,
+ },
+ [0x2B64]={
+ category="so",
+ description="LEFT RIGHT TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B64,
+ },
+ [0x2B65]={
+ category="so",
+ description="UP DOWN TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B65,
+ },
+ [0x2B66]={
+ category="so",
+ description="NORTH WEST TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B66,
+ },
+ [0x2B67]={
+ category="so",
+ description="NORTH EAST TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B67,
+ },
+ [0x2B68]={
+ category="so",
+ description="SOUTH EAST TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B68,
+ },
+ [0x2B69]={
+ category="so",
+ description="SOUTH WEST TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B69,
+ },
+ [0x2B6A]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6A,
+ },
+ [0x2B6B]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6B,
+ },
+ [0x2B6C]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6C,
+ },
+ [0x2B6D]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED DASHED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6D,
+ },
+ [0x2B6E]={
+ category="so",
+ description="CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6E,
+ },
+ [0x2B6F]={
+ category="so",
+ description="ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B6F,
+ },
+ [0x2B70]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B70,
+ },
+ [0x2B71]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B71,
+ },
+ [0x2B72]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B72,
+ },
+ [0x2B73]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B73,
+ },
+ [0x2B76]={
+ category="so",
+ description="NORTH WEST TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B76,
+ },
+ [0x2B77]={
+ category="so",
+ description="NORTH EAST TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B77,
+ },
+ [0x2B78]={
+ category="so",
+ description="SOUTH EAST TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B78,
+ },
+ [0x2B79]={
+ category="so",
+ description="SOUTH WEST TRIANGLE-HEADED ARROW TO BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B79,
+ },
+ [0x2B7A]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7A,
+ },
+ [0x2B7B]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7B,
+ },
+ [0x2B7C]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7C,
+ },
+ [0x2B7D]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7D,
+ },
+ [0x2B7E]={
+ category="so",
+ description="HORIZONTAL TAB KEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7E,
+ },
+ [0x2B7F]={
+ category="so",
+ description="VERTICAL TAB KEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B7F,
+ },
+ [0x2B80]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B80,
+ },
+ [0x2B81]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B81,
+ },
+ [0x2B82]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B82,
+ },
+ [0x2B83]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B83,
+ },
+ [0x2B84]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B84,
+ },
+ [0x2B85]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B85,
+ },
+ [0x2B86]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B86,
+ },
+ [0x2B87]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B87,
+ },
+ [0x2B88]={
+ category="so",
+ description="LEFTWARDS BLACK CIRCLED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B88,
+ },
+ [0x2B89]={
+ category="so",
+ description="UPWARDS BLACK CIRCLED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B89,
+ },
+ [0x2B8A]={
+ category="so",
+ description="RIGHTWARDS BLACK CIRCLED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8A,
+ },
+ [0x2B8B]={
+ category="so",
+ description="DOWNWARDS BLACK CIRCLED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8B,
+ },
+ [0x2B8C]={
+ category="so",
+ description="ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8C,
+ },
+ [0x2B8D]={
+ category="so",
+ description="ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8D,
+ },
+ [0x2B8E]={
+ category="so",
+ description="ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8E,
+ },
+ [0x2B8F]={
+ category="so",
+ description="ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B8F,
+ },
+ [0x2B90]={
+ category="so",
+ description="RETURN LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B90,
+ },
+ [0x2B91]={
+ category="so",
+ description="RETURN RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B91,
+ },
+ [0x2B92]={
+ category="so",
+ description="NEWLINE LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B92,
+ },
+ [0x2B93]={
+ category="so",
+ description="NEWLINE RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B93,
+ },
+ [0x2B94]={
+ category="so",
+ description="FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B94,
+ },
+ [0x2B95]={
+ category="so",
+ description="RIGHTWARDS BLACK ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B95,
+ },
+ [0x2B98]={
+ category="so",
+ description="THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B98,
+ },
+ [0x2B99]={
+ category="so",
+ description="THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B99,
+ },
+ [0x2B9A]={
+ category="so",
+ description="THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9A,
+ },
+ [0x2B9B]={
+ category="so",
+ description="THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9B,
+ },
+ [0x2B9C]={
+ category="so",
+ description="BLACK LEFTWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9C,
+ },
+ [0x2B9D]={
+ category="so",
+ description="BLACK UPWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9D,
+ },
+ [0x2B9E]={
+ category="so",
+ description="BLACK RIGHTWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9E,
+ },
+ [0x2B9F]={
+ category="so",
+ description="BLACK DOWNWARDS EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B9F,
+ },
+ [0x2BA0]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA0,
+ },
+ [0x2BA1]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA1,
+ },
+ [0x2BA2]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA2,
+ },
+ [0x2BA3]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA3,
+ },
+ [0x2BA4]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA4,
+ },
+ [0x2BA5]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA5,
+ },
+ [0x2BA6]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA6,
+ },
+ [0x2BA7]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA7,
+ },
+ [0x2BA8]={
+ category="so",
+ description="BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA8,
+ },
+ [0x2BA9]={
+ category="so",
+ description="BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BA9,
+ },
+ [0x2BAA]={
+ category="so",
+ description="BLACK CURVED UPWARDS AND LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAA,
+ },
+ [0x2BAB]={
+ category="so",
+ description="BLACK CURVED UPWARDS AND RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAB,
+ },
+ [0x2BAC]={
+ category="so",
+ description="BLACK CURVED LEFTWARDS AND UPWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAC,
+ },
+ [0x2BAD]={
+ category="so",
+ description="BLACK CURVED RIGHTWARDS AND UPWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAD,
+ },
+ [0x2BAE]={
+ category="so",
+ description="BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAE,
+ },
+ [0x2BAF]={
+ category="so",
+ description="BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BAF,
+ },
+ [0x2BB0]={
+ category="so",
+ description="RIBBON ARROW DOWN LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB0,
+ },
+ [0x2BB1]={
+ category="so",
+ description="RIBBON ARROW DOWN RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB1,
+ },
+ [0x2BB2]={
+ category="so",
+ description="RIBBON ARROW UP LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB2,
+ },
+ [0x2BB3]={
+ category="so",
+ description="RIBBON ARROW UP RIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB3,
+ },
+ [0x2BB4]={
+ category="so",
+ description="RIBBON ARROW LEFT UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB4,
+ },
+ [0x2BB5]={
+ category="so",
+ description="RIBBON ARROW RIGHT UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB5,
+ },
+ [0x2BB6]={
+ category="so",
+ description="RIBBON ARROW LEFT DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB6,
+ },
+ [0x2BB7]={
+ category="so",
+ description="RIBBON ARROW RIGHT DOWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB7,
+ },
+ [0x2BB8]={
+ category="so",
+ description="UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB8,
+ },
+ [0x2BB9]={
+ category="so",
+ description="UP ARROWHEAD IN A RECTANGLE BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BB9,
+ },
+ [0x2BBD]={
+ category="so",
+ description="BALLOT BOX WITH LIGHT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBD,
+ },
+ [0x2BBE]={
+ category="so",
+ description="CIRCLED X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBE,
+ },
+ [0x2BBF]={
+ category="so",
+ description="CIRCLED BOLD X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBF,
+ },
+ [0x2BC0]={
+ category="so",
+ description="BLACK SQUARE CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC0,
+ },
+ [0x2BC1]={
+ category="so",
+ description="BLACK DIAMOND CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC1,
+ },
+ [0x2BC2]={
+ category="so",
+ description="TURNED BLACK PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC2,
+ },
+ [0x2BC3]={
+ category="so",
+ description="HORIZONTAL BLACK OCTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC3,
+ },
+ [0x2BC4]={
+ category="so",
+ description="BLACK OCTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC4,
+ },
+ [0x2BC5]={
+ category="so",
+ description="BLACK MEDIUM UP-POINTING TRIANGLE CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC5,
+ },
+ [0x2BC6]={
+ category="so",
+ description="BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC6,
+ },
+ [0x2BC7]={
+ category="so",
+ description="BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC7,
+ },
+ [0x2BC8]={
+ category="so",
+ description="BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BC8,
+ },
+ [0x2BCA]={
+ category="so",
+ description="TOP HALF BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCA,
+ },
+ [0x2BCB]={
+ category="so",
+ description="BOTTOM HALF BLACK CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCB,
+ },
+ [0x2BCC]={
+ category="so",
+ description="LIGHT FOUR POINTED BLACK CUSP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCC,
+ },
+ [0x2BCD]={
+ category="so",
+ description="ROTATED LIGHT FOUR POINTED BLACK CUSP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCD,
+ },
+ [0x2BCE]={
+ category="so",
+ description="WHITE FOUR POINTED CUSP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCE,
+ },
+ [0x2BCF]={
+ category="so",
+ description="ROTATED WHITE FOUR POINTED CUSP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BCF,
+ },
+ [0x2BD0]={
+ category="so",
+ description="SQUARE POSITION INDICATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD0,
+ },
+ [0x2BD1]={
+ category="so",
+ description="UNCERTAINTY SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD1,
+ },
+ [0x2BEC]={
+ category="so",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BEC,
+ },
+ [0x2BED]={
+ category="so",
+ description="UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BED,
+ },
+ [0x2BEE]={
+ category="so",
+ description="RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BEE,
+ },
+ [0x2BEF]={
+ category="so",
+ description="DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BEF,
+ },
+ [0x2C00]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER AZU",
+ direction="l",
+ lccode=0x2C30,
+ linebreak="al",
+ unicodeslot=0x2C00,
+ },
+ [0x2C01]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER BUKY",
+ direction="l",
+ lccode=0x2C31,
+ linebreak="al",
+ unicodeslot=0x2C01,
+ },
+ [0x2C02]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER VEDE",
+ direction="l",
+ lccode=0x2C32,
+ linebreak="al",
+ unicodeslot=0x2C02,
+ },
+ [0x2C03]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER GLAGOLI",
+ direction="l",
+ lccode=0x2C33,
+ linebreak="al",
+ unicodeslot=0x2C03,
+ },
+ [0x2C04]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER DOBRO",
+ direction="l",
+ lccode=0x2C34,
+ linebreak="al",
+ unicodeslot=0x2C04,
+ },
+ [0x2C05]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YESTU",
+ direction="l",
+ lccode=0x2C35,
+ linebreak="al",
+ unicodeslot=0x2C05,
+ },
+ [0x2C06]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER ZHIVETE",
+ direction="l",
+ lccode=0x2C36,
+ linebreak="al",
+ unicodeslot=0x2C06,
+ },
+ [0x2C07]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER DZELO",
+ direction="l",
+ lccode=0x2C37,
+ linebreak="al",
+ unicodeslot=0x2C07,
+ },
+ [0x2C08]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER ZEMLJA",
+ direction="l",
+ lccode=0x2C38,
+ linebreak="al",
+ unicodeslot=0x2C08,
+ },
+ [0x2C09]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER IZHE",
+ direction="l",
+ lccode=0x2C39,
+ linebreak="al",
+ unicodeslot=0x2C09,
+ },
+ [0x2C0A]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER INITIAL IZHE",
+ direction="l",
+ lccode=0x2C3A,
+ linebreak="al",
+ unicodeslot=0x2C0A,
+ },
+ [0x2C0B]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER I",
+ direction="l",
+ lccode=0x2C3B,
+ linebreak="al",
+ unicodeslot=0x2C0B,
+ },
+ [0x2C0C]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER DJERVI",
+ direction="l",
+ lccode=0x2C3C,
+ linebreak="al",
+ unicodeslot=0x2C0C,
+ },
+ [0x2C0D]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER KAKO",
+ direction="l",
+ lccode=0x2C3D,
+ linebreak="al",
+ unicodeslot=0x2C0D,
+ },
+ [0x2C0E]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER LJUDIJE",
+ direction="l",
+ lccode=0x2C3E,
+ linebreak="al",
+ unicodeslot=0x2C0E,
+ },
+ [0x2C0F]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER MYSLITE",
+ direction="l",
+ lccode=0x2C3F,
+ linebreak="al",
+ unicodeslot=0x2C0F,
+ },
+ [0x2C10]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER NASHI",
+ direction="l",
+ lccode=0x2C40,
+ linebreak="al",
+ unicodeslot=0x2C10,
+ },
+ [0x2C11]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER ONU",
+ direction="l",
+ lccode=0x2C41,
+ linebreak="al",
+ unicodeslot=0x2C11,
+ },
+ [0x2C12]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER POKOJI",
+ direction="l",
+ lccode=0x2C42,
+ linebreak="al",
+ unicodeslot=0x2C12,
+ },
+ [0x2C13]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER RITSI",
+ direction="l",
+ lccode=0x2C43,
+ linebreak="al",
+ unicodeslot=0x2C13,
+ },
+ [0x2C14]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SLOVO",
+ direction="l",
+ lccode=0x2C44,
+ linebreak="al",
+ unicodeslot=0x2C14,
+ },
+ [0x2C15]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER TVRIDO",
+ direction="l",
+ lccode=0x2C45,
+ linebreak="al",
+ unicodeslot=0x2C15,
+ },
+ [0x2C16]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER UKU",
+ direction="l",
+ lccode=0x2C46,
+ linebreak="al",
+ unicodeslot=0x2C16,
+ },
+ [0x2C17]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER FRITU",
+ direction="l",
+ lccode=0x2C47,
+ linebreak="al",
+ unicodeslot=0x2C17,
+ },
+ [0x2C18]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER HERU",
+ direction="l",
+ lccode=0x2C48,
+ linebreak="al",
+ unicodeslot=0x2C18,
+ },
+ [0x2C19]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER OTU",
+ direction="l",
+ lccode=0x2C49,
+ linebreak="al",
+ unicodeslot=0x2C19,
+ },
+ [0x2C1A]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER PE",
+ direction="l",
+ lccode=0x2C4A,
+ linebreak="al",
+ unicodeslot=0x2C1A,
+ },
+ [0x2C1B]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SHTA",
+ direction="l",
+ lccode=0x2C4B,
+ linebreak="al",
+ unicodeslot=0x2C1B,
+ },
+ [0x2C1C]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER TSI",
+ direction="l",
+ lccode=0x2C4C,
+ linebreak="al",
+ unicodeslot=0x2C1C,
+ },
+ [0x2C1D]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER CHRIVI",
+ direction="l",
+ lccode=0x2C4D,
+ linebreak="al",
+ unicodeslot=0x2C1D,
+ },
+ [0x2C1E]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SHA",
+ direction="l",
+ lccode=0x2C4E,
+ linebreak="al",
+ unicodeslot=0x2C1E,
+ },
+ [0x2C1F]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YERU",
+ direction="l",
+ lccode=0x2C4F,
+ linebreak="al",
+ unicodeslot=0x2C1F,
+ },
+ [0x2C20]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YERI",
+ direction="l",
+ lccode=0x2C50,
+ linebreak="al",
+ unicodeslot=0x2C20,
+ },
+ [0x2C21]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YATI",
+ direction="l",
+ lccode=0x2C51,
+ linebreak="al",
+ unicodeslot=0x2C21,
+ },
+ [0x2C22]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SPIDERY HA",
+ direction="l",
+ lccode=0x2C52,
+ linebreak="al",
+ unicodeslot=0x2C22,
+ },
+ [0x2C23]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YU",
+ direction="l",
+ lccode=0x2C53,
+ linebreak="al",
+ unicodeslot=0x2C23,
+ },
+ [0x2C24]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SMALL YUS",
+ direction="l",
+ lccode=0x2C54,
+ linebreak="al",
+ unicodeslot=0x2C24,
+ },
+ [0x2C25]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL",
+ direction="l",
+ lccode=0x2C55,
+ linebreak="al",
+ unicodeslot=0x2C25,
+ },
+ [0x2C26]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER YO",
+ direction="l",
+ lccode=0x2C56,
+ linebreak="al",
+ unicodeslot=0x2C26,
+ },
+ [0x2C27]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS",
+ direction="l",
+ lccode=0x2C57,
+ linebreak="al",
+ unicodeslot=0x2C27,
+ },
+ [0x2C28]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER BIG YUS",
+ direction="l",
+ lccode=0x2C58,
+ linebreak="al",
+ unicodeslot=0x2C28,
+ },
+ [0x2C29]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS",
+ direction="l",
+ lccode=0x2C59,
+ linebreak="al",
+ unicodeslot=0x2C29,
+ },
+ [0x2C2A]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER FITA",
+ direction="l",
+ lccode=0x2C5A,
+ linebreak="al",
+ unicodeslot=0x2C2A,
+ },
+ [0x2C2B]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER IZHITSA",
+ direction="l",
+ lccode=0x2C5B,
+ linebreak="al",
+ unicodeslot=0x2C2B,
+ },
+ [0x2C2C]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER SHTAPIC",
+ direction="l",
+ lccode=0x2C5C,
+ linebreak="al",
+ unicodeslot=0x2C2C,
+ },
+ [0x2C2D]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER TROKUTASTI A",
+ direction="l",
+ lccode=0x2C5D,
+ linebreak="al",
+ unicodeslot=0x2C2D,
+ },
+ [0x2C2E]={
+ category="lu",
+ description="GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE",
+ direction="l",
+ lccode=0x2C5E,
+ linebreak="al",
+ unicodeslot=0x2C2E,
+ },
+ [0x2C30]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER AZU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C00,
+ unicodeslot=0x2C30,
+ },
+ [0x2C31]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER BUKY",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C01,
+ unicodeslot=0x2C31,
+ },
+ [0x2C32]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER VEDE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C02,
+ unicodeslot=0x2C32,
+ },
+ [0x2C33]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER GLAGOLI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C03,
+ unicodeslot=0x2C33,
+ },
+ [0x2C34]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER DOBRO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C04,
+ unicodeslot=0x2C34,
+ },
+ [0x2C35]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YESTU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C05,
+ unicodeslot=0x2C35,
+ },
+ [0x2C36]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER ZHIVETE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C06,
+ unicodeslot=0x2C36,
+ },
+ [0x2C37]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER DZELO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C07,
+ unicodeslot=0x2C37,
+ },
+ [0x2C38]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER ZEMLJA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C08,
+ unicodeslot=0x2C38,
+ },
+ [0x2C39]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER IZHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C09,
+ unicodeslot=0x2C39,
+ },
+ [0x2C3A]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER INITIAL IZHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0A,
+ unicodeslot=0x2C3A,
+ },
+ [0x2C3B]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0B,
+ unicodeslot=0x2C3B,
+ },
+ [0x2C3C]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER DJERVI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0C,
+ unicodeslot=0x2C3C,
+ },
+ [0x2C3D]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER KAKO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0D,
+ unicodeslot=0x2C3D,
+ },
+ [0x2C3E]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER LJUDIJE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0E,
+ unicodeslot=0x2C3E,
+ },
+ [0x2C3F]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER MYSLITE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C0F,
+ unicodeslot=0x2C3F,
+ },
+ [0x2C40]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER NASHI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C10,
+ unicodeslot=0x2C40,
+ },
+ [0x2C41]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER ONU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C11,
+ unicodeslot=0x2C41,
+ },
+ [0x2C42]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER POKOJI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C12,
+ unicodeslot=0x2C42,
+ },
+ [0x2C43]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER RITSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C13,
+ unicodeslot=0x2C43,
+ },
+ [0x2C44]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SLOVO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C14,
+ unicodeslot=0x2C44,
+ },
+ [0x2C45]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER TVRIDO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C15,
+ unicodeslot=0x2C45,
+ },
+ [0x2C46]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER UKU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C16,
+ unicodeslot=0x2C46,
+ },
+ [0x2C47]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER FRITU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C17,
+ unicodeslot=0x2C47,
+ },
+ [0x2C48]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER HERU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C18,
+ unicodeslot=0x2C48,
+ },
+ [0x2C49]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER OTU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C19,
+ unicodeslot=0x2C49,
+ },
+ [0x2C4A]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER PE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1A,
+ unicodeslot=0x2C4A,
+ },
+ [0x2C4B]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SHTA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1B,
+ unicodeslot=0x2C4B,
+ },
+ [0x2C4C]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER TSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1C,
+ unicodeslot=0x2C4C,
+ },
+ [0x2C4D]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER CHRIVI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1D,
+ unicodeslot=0x2C4D,
+ },
+ [0x2C4E]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SHA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1E,
+ unicodeslot=0x2C4E,
+ },
+ [0x2C4F]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YERU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C1F,
+ unicodeslot=0x2C4F,
+ },
+ [0x2C50]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YERI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C20,
+ unicodeslot=0x2C50,
+ },
+ [0x2C51]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YATI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C21,
+ unicodeslot=0x2C51,
+ },
+ [0x2C52]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SPIDERY HA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C22,
+ unicodeslot=0x2C52,
+ },
+ [0x2C53]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C23,
+ unicodeslot=0x2C53,
+ },
+ [0x2C54]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SMALL YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C24,
+ unicodeslot=0x2C54,
+ },
+ [0x2C55]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C25,
+ unicodeslot=0x2C55,
+ },
+ [0x2C56]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER YO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C26,
+ unicodeslot=0x2C56,
+ },
+ [0x2C57]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER IOTATED SMALL YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C27,
+ unicodeslot=0x2C57,
+ },
+ [0x2C58]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER BIG YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C28,
+ unicodeslot=0x2C58,
+ },
+ [0x2C59]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER IOTATED BIG YUS",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C29,
+ unicodeslot=0x2C59,
+ },
+ [0x2C5A]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER FITA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C2A,
+ unicodeslot=0x2C5A,
+ },
+ [0x2C5B]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER IZHITSA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C2B,
+ unicodeslot=0x2C5B,
+ },
+ [0x2C5C]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER SHTAPIC",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C2C,
+ unicodeslot=0x2C5C,
+ },
+ [0x2C5D]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER TROKUTASTI A",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C2D,
+ unicodeslot=0x2C5D,
+ },
+ [0x2C5E]={
+ category="ll",
+ description="GLAGOLITIC SMALL LETTER LATINATE MYSLITE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C2E,
+ unicodeslot=0x2C5E,
+ },
+ [0x2C60]={
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH DOUBLE BAR",
+ direction="l",
+ lccode=0x2C61,
+ linebreak="al",
+ shcode=0x4C,
+ unicodeslot=0x2C60,
+ },
+ [0x2C61]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH DOUBLE BAR",
+ direction="l",
+ linebreak="al",
+ shcode=0x6C,
+ uccode=0x2C60,
+ unicodeslot=0x2C61,
+ },
+ [0x2C62]={
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH MIDDLE TILDE",
+ direction="l",
+ lccode=0x26B,
+ linebreak="al",
+ shcode=0x4C,
+ unicodeslot=0x2C62,
+ },
+ [0x2C63]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH STROKE",
+ direction="l",
+ lccode=0x1D7D,
+ linebreak="al",
+ shcode=0x50,
+ unicodeslot=0x2C63,
+ },
+ [0x2C64]={
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH TAIL",
+ direction="l",
+ lccode=0x27D,
+ linebreak="al",
+ shcode=0x52,
+ unicodeslot=0x2C64,
+ },
+ [0x2C65]={
+ category="ll",
+ description="LATIN SMALL LETTER A WITH STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x61,
+ uccode=0x23A,
+ unicodeslot=0x2C65,
+ },
+ [0x2C66]={
+ category="ll",
+ description="LATIN SMALL LETTER T WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ shcode=0x74,
+ uccode=0x23E,
+ unicodeslot=0x2C66,
+ },
+ [0x2C67]={
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH DESCENDER",
+ direction="l",
+ lccode=0x2C68,
+ linebreak="al",
+ shcode=0x48,
+ unicodeslot=0x2C67,
+ },
+ [0x2C68]={
+ category="ll",
+ description="LATIN SMALL LETTER H WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x68,
+ uccode=0x2C67,
+ unicodeslot=0x2C68,
+ },
+ [0x2C69]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH DESCENDER",
+ direction="l",
+ lccode=0x2C6A,
+ linebreak="al",
+ shcode=0x4B,
+ unicodeslot=0x2C69,
+ },
+ [0x2C6A]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x6B,
+ uccode=0x2C69,
+ unicodeslot=0x2C6A,
+ },
+ [0x2C6B]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH DESCENDER",
+ direction="l",
+ lccode=0x2C6C,
+ linebreak="al",
+ shcode=0x5A,
+ unicodeslot=0x2C6B,
+ },
+ [0x2C6C]={
+ category="ll",
+ description="LATIN SMALL LETTER Z WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ shcode=0x7A,
+ uccode=0x2C6B,
+ unicodeslot=0x2C6C,
+ },
+ [0x2C6D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6D,
+ },
+ [0x2C6E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER M WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6E,
+ },
+ [0x2C6F]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6F,
+ },
+ [0x2C70]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C70,
+ },
+ [0x2C71]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH RIGHT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C71,
+ },
+ [0x2C72]={
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C72,
+ },
+ [0x2C73]={
+ category="ll",
+ description="LATIN SMALL LETTER W WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C73,
+ },
+ [0x2C74]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH CURL",
+ direction="l",
+ linebreak="al",
+ shcode=0x76,
+ unicodeslot=0x2C74,
+ },
+ [0x2C75]={
+ category="lu",
+ description="LATIN CAPITAL LETTER HALF H",
+ direction="l",
+ lccode=0x2C76,
+ linebreak="al",
+ unicodeslot=0x2C75,
+ },
+ [0x2C76]={
+ category="ll",
+ description="LATIN SMALL LETTER HALF H",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C75,
+ unicodeslot=0x2C76,
+ },
+ [0x2C77]={
+ category="ll",
+ description="LATIN SMALL LETTER TAILLESS PHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C77,
+ },
+ [0x2C78]={
+ category="ll",
+ description="LATIN SMALL LETTER E WITH NOTCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C78,
+ },
+ [0x2C79]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED R WITH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C79,
+ },
+ [0x2C7A]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LOW RING INSIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7A,
+ },
+ [0x2C7B]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL TURNED E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7B,
+ },
+ [0x2C7C]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER J",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x6A },
+ unicodeslot=0x2C7C,
+ },
+ [0x2C7D]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x56 },
+ unicodeslot=0x2C7D,
+ },
+ [0x2C7E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7E,
+ },
+ [0x2C7F]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7F,
+ },
+ [0x2C80]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER ALFA",
+ direction="l",
+ lccode=0x2C81,
+ linebreak="al",
+ unicodeslot=0x2C80,
+ },
+ [0x2C81]={
+ category="ll",
+ description="COPTIC SMALL LETTER ALFA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C80,
+ unicodeslot=0x2C81,
+ },
+ [0x2C82]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER VIDA",
+ direction="l",
+ lccode=0x2C83,
+ linebreak="al",
+ unicodeslot=0x2C82,
+ },
+ [0x2C83]={
+ category="ll",
+ description="COPTIC SMALL LETTER VIDA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C82,
+ unicodeslot=0x2C83,
+ },
+ [0x2C84]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER GAMMA",
+ direction="l",
+ lccode=0x2C85,
+ linebreak="al",
+ unicodeslot=0x2C84,
+ },
+ [0x2C85]={
+ category="ll",
+ description="COPTIC SMALL LETTER GAMMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C84,
+ unicodeslot=0x2C85,
+ },
+ [0x2C86]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER DALDA",
+ direction="l",
+ lccode=0x2C87,
+ linebreak="al",
+ unicodeslot=0x2C86,
+ },
+ [0x2C87]={
+ category="ll",
+ description="COPTIC SMALL LETTER DALDA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C86,
+ unicodeslot=0x2C87,
+ },
+ [0x2C88]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER EIE",
+ direction="l",
+ lccode=0x2C89,
+ linebreak="al",
+ unicodeslot=0x2C88,
+ },
+ [0x2C89]={
+ category="ll",
+ description="COPTIC SMALL LETTER EIE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C88,
+ unicodeslot=0x2C89,
+ },
+ [0x2C8A]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER SOU",
+ direction="l",
+ lccode=0x2C8B,
+ linebreak="al",
+ unicodeslot=0x2C8A,
+ },
+ [0x2C8B]={
+ category="ll",
+ description="COPTIC SMALL LETTER SOU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C8A,
+ unicodeslot=0x2C8B,
+ },
+ [0x2C8C]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER ZATA",
+ direction="l",
+ lccode=0x2C8D,
+ linebreak="al",
+ unicodeslot=0x2C8C,
+ },
+ [0x2C8D]={
+ category="ll",
+ description="COPTIC SMALL LETTER ZATA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C8C,
+ unicodeslot=0x2C8D,
+ },
+ [0x2C8E]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER HATE",
+ direction="l",
+ lccode=0x2C8F,
+ linebreak="al",
+ unicodeslot=0x2C8E,
+ },
+ [0x2C8F]={
+ category="ll",
+ description="COPTIC SMALL LETTER HATE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C8E,
+ unicodeslot=0x2C8F,
+ },
+ [0x2C90]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER THETHE",
+ direction="l",
+ lccode=0x2C91,
+ linebreak="al",
+ unicodeslot=0x2C90,
+ },
+ [0x2C91]={
+ category="ll",
+ description="COPTIC SMALL LETTER THETHE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C90,
+ unicodeslot=0x2C91,
+ },
+ [0x2C92]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER IAUDA",
+ direction="l",
+ lccode=0x2C93,
+ linebreak="al",
+ unicodeslot=0x2C92,
+ },
+ [0x2C93]={
+ category="ll",
+ description="COPTIC SMALL LETTER IAUDA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C92,
+ unicodeslot=0x2C93,
+ },
+ [0x2C94]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER KAPA",
+ direction="l",
+ lccode=0x2C95,
+ linebreak="al",
+ unicodeslot=0x2C94,
+ },
+ [0x2C95]={
+ category="ll",
+ description="COPTIC SMALL LETTER KAPA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C94,
+ unicodeslot=0x2C95,
+ },
+ [0x2C96]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER LAULA",
+ direction="l",
+ lccode=0x2C97,
+ linebreak="al",
+ unicodeslot=0x2C96,
+ },
+ [0x2C97]={
+ category="ll",
+ description="COPTIC SMALL LETTER LAULA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C96,
+ unicodeslot=0x2C97,
+ },
+ [0x2C98]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER MI",
+ direction="l",
+ lccode=0x2C99,
+ linebreak="al",
+ unicodeslot=0x2C98,
+ },
+ [0x2C99]={
+ category="ll",
+ description="COPTIC SMALL LETTER MI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C98,
+ unicodeslot=0x2C99,
+ },
+ [0x2C9A]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER NI",
+ direction="l",
+ lccode=0x2C9B,
+ linebreak="al",
+ unicodeslot=0x2C9A,
+ },
+ [0x2C9B]={
+ category="ll",
+ description="COPTIC SMALL LETTER NI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C9A,
+ unicodeslot=0x2C9B,
+ },
+ [0x2C9C]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER KSI",
+ direction="l",
+ lccode=0x2C9D,
+ linebreak="al",
+ unicodeslot=0x2C9C,
+ },
+ [0x2C9D]={
+ category="ll",
+ description="COPTIC SMALL LETTER KSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C9C,
+ unicodeslot=0x2C9D,
+ },
+ [0x2C9E]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER O",
+ direction="l",
+ lccode=0x2C9F,
+ linebreak="al",
+ unicodeslot=0x2C9E,
+ },
+ [0x2C9F]={
+ category="ll",
+ description="COPTIC SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ uccode=0x2C9E,
+ unicodeslot=0x2C9F,
+ },
+ [0x2CA0]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER PI",
+ direction="l",
+ lccode=0x2CA1,
+ linebreak="al",
+ unicodeslot=0x2CA0,
+ },
+ [0x2CA1]={
+ category="ll",
+ description="COPTIC SMALL LETTER PI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CA0,
+ unicodeslot=0x2CA1,
+ },
+ [0x2CA2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER RO",
+ direction="l",
+ lccode=0x2CA3,
+ linebreak="al",
+ unicodeslot=0x2CA2,
+ },
+ [0x2CA3]={
+ category="ll",
+ description="COPTIC SMALL LETTER RO",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CA2,
+ unicodeslot=0x2CA3,
+ },
+ [0x2CA4]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER SIMA",
+ direction="l",
+ lccode=0x2CA5,
+ linebreak="al",
+ unicodeslot=0x2CA4,
+ },
+ [0x2CA5]={
+ category="ll",
+ description="COPTIC SMALL LETTER SIMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CA4,
+ unicodeslot=0x2CA5,
+ },
+ [0x2CA6]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER TAU",
+ direction="l",
+ lccode=0x2CA7,
+ linebreak="al",
+ unicodeslot=0x2CA6,
+ },
+ [0x2CA7]={
+ category="ll",
+ description="COPTIC SMALL LETTER TAU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CA6,
+ unicodeslot=0x2CA7,
+ },
+ [0x2CA8]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER UA",
+ direction="l",
+ lccode=0x2CA9,
+ linebreak="al",
+ unicodeslot=0x2CA8,
+ },
+ [0x2CA9]={
+ category="ll",
+ description="COPTIC SMALL LETTER UA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CA8,
+ unicodeslot=0x2CA9,
+ },
+ [0x2CAA]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER FI",
+ direction="l",
+ lccode=0x2CAB,
+ linebreak="al",
+ unicodeslot=0x2CAA,
+ },
+ [0x2CAB]={
+ category="ll",
+ description="COPTIC SMALL LETTER FI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CAA,
+ unicodeslot=0x2CAB,
+ },
+ [0x2CAC]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER KHI",
+ direction="l",
+ lccode=0x2CAD,
+ linebreak="al",
+ unicodeslot=0x2CAC,
+ },
+ [0x2CAD]={
+ category="ll",
+ description="COPTIC SMALL LETTER KHI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CAC,
+ unicodeslot=0x2CAD,
+ },
+ [0x2CAE]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER PSI",
+ direction="l",
+ lccode=0x2CAF,
+ linebreak="al",
+ unicodeslot=0x2CAE,
+ },
+ [0x2CAF]={
+ category="ll",
+ description="COPTIC SMALL LETTER PSI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CAE,
+ unicodeslot=0x2CAF,
+ },
+ [0x2CB0]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OOU",
+ direction="l",
+ lccode=0x2CB1,
+ linebreak="al",
+ unicodeslot=0x2CB0,
+ },
+ [0x2CB1]={
+ category="ll",
+ description="COPTIC SMALL LETTER OOU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CB0,
+ unicodeslot=0x2CB1,
+ },
+ [0x2CB2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER DIALECT-P ALEF",
+ direction="l",
+ lccode=0x2CB3,
+ linebreak="al",
+ unicodeslot=0x2CB2,
+ },
+ [0x2CB3]={
+ category="ll",
+ description="COPTIC SMALL LETTER DIALECT-P ALEF",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CB2,
+ unicodeslot=0x2CB3,
+ },
+ [0x2CB4]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC AIN",
+ direction="l",
+ lccode=0x2CB5,
+ linebreak="al",
+ unicodeslot=0x2CB4,
+ },
+ [0x2CB5]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC AIN",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CB4,
+ unicodeslot=0x2CB5,
+ },
+ [0x2CB6]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE",
+ direction="l",
+ lccode=0x2CB7,
+ linebreak="al",
+ unicodeslot=0x2CB6,
+ },
+ [0x2CB7]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC EIE",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CB6,
+ unicodeslot=0x2CB7,
+ },
+ [0x2CB8]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER DIALECT-P KAPA",
+ direction="l",
+ lccode=0x2CB9,
+ linebreak="al",
+ unicodeslot=0x2CB8,
+ },
+ [0x2CB9]={
+ category="ll",
+ description="COPTIC SMALL LETTER DIALECT-P KAPA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CB8,
+ unicodeslot=0x2CB9,
+ },
+ [0x2CBA]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER DIALECT-P NI",
+ direction="l",
+ lccode=0x2CBB,
+ linebreak="al",
+ unicodeslot=0x2CBA,
+ },
+ [0x2CBB]={
+ category="ll",
+ description="COPTIC SMALL LETTER DIALECT-P NI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CBA,
+ unicodeslot=0x2CBB,
+ },
+ [0x2CBC]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI",
+ direction="l",
+ lccode=0x2CBD,
+ linebreak="al",
+ unicodeslot=0x2CBC,
+ },
+ [0x2CBD]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC NI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CBC,
+ unicodeslot=0x2CBD,
+ },
+ [0x2CBE]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC OOU",
+ direction="l",
+ lccode=0x2CBF,
+ linebreak="al",
+ unicodeslot=0x2CBE,
+ },
+ [0x2CBF]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC OOU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CBE,
+ unicodeslot=0x2CBF,
+ },
+ [0x2CC0]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER SAMPI",
+ direction="l",
+ lccode=0x2CC1,
+ linebreak="al",
+ unicodeslot=0x2CC0,
+ },
+ [0x2CC1]={
+ category="ll",
+ description="COPTIC SMALL LETTER SAMPI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CC0,
+ unicodeslot=0x2CC1,
+ },
+ [0x2CC2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CROSSED SHEI",
+ direction="l",
+ lccode=0x2CC3,
+ linebreak="al",
+ unicodeslot=0x2CC2,
+ },
+ [0x2CC3]={
+ category="ll",
+ description="COPTIC SMALL LETTER CROSSED SHEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CC2,
+ unicodeslot=0x2CC3,
+ },
+ [0x2CC4]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC SHEI",
+ direction="l",
+ lccode=0x2CC5,
+ linebreak="al",
+ unicodeslot=0x2CC4,
+ },
+ [0x2CC5]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC SHEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CC4,
+ unicodeslot=0x2CC5,
+ },
+ [0x2CC6]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC ESH",
+ direction="l",
+ lccode=0x2CC7,
+ linebreak="al",
+ unicodeslot=0x2CC6,
+ },
+ [0x2CC7]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC ESH",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CC6,
+ unicodeslot=0x2CC7,
+ },
+ [0x2CC8]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER AKHMIMIC KHEI",
+ direction="l",
+ lccode=0x2CC9,
+ linebreak="al",
+ unicodeslot=0x2CC8,
+ },
+ [0x2CC9]={
+ category="ll",
+ description="COPTIC SMALL LETTER AKHMIMIC KHEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CC8,
+ unicodeslot=0x2CC9,
+ },
+ [0x2CCA]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER DIALECT-P HORI",
+ direction="l",
+ lccode=0x2CCB,
+ linebreak="al",
+ unicodeslot=0x2CCA,
+ },
+ [0x2CCB]={
+ category="ll",
+ description="COPTIC SMALL LETTER DIALECT-P HORI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CCA,
+ unicodeslot=0x2CCB,
+ },
+ [0x2CCC]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC HORI",
+ direction="l",
+ lccode=0x2CCD,
+ linebreak="al",
+ unicodeslot=0x2CCC,
+ },
+ [0x2CCD]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC HORI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CCC,
+ unicodeslot=0x2CCD,
+ },
+ [0x2CCE]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC HA",
+ direction="l",
+ lccode=0x2CCF,
+ linebreak="al",
+ unicodeslot=0x2CCE,
+ },
+ [0x2CCF]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC HA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CCE,
+ unicodeslot=0x2CCF,
+ },
+ [0x2CD0]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER L-SHAPED HA",
+ direction="l",
+ lccode=0x2CD1,
+ linebreak="al",
+ unicodeslot=0x2CD0,
+ },
+ [0x2CD1]={
+ category="ll",
+ description="COPTIC SMALL LETTER L-SHAPED HA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CD0,
+ unicodeslot=0x2CD1,
+ },
+ [0x2CD2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC HEI",
+ direction="l",
+ lccode=0x2CD3,
+ linebreak="al",
+ unicodeslot=0x2CD2,
+ },
+ [0x2CD3]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC HEI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CD2,
+ unicodeslot=0x2CD3,
+ },
+ [0x2CD4]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC HAT",
+ direction="l",
+ lccode=0x2CD5,
+ linebreak="al",
+ unicodeslot=0x2CD4,
+ },
+ [0x2CD5]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC HAT",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CD4,
+ unicodeslot=0x2CD5,
+ },
+ [0x2CD6]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC GANGIA",
+ direction="l",
+ lccode=0x2CD7,
+ linebreak="al",
+ unicodeslot=0x2CD6,
+ },
+ [0x2CD7]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC GANGIA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CD6,
+ unicodeslot=0x2CD7,
+ },
+ [0x2CD8]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC DJA",
+ direction="l",
+ lccode=0x2CD9,
+ linebreak="al",
+ unicodeslot=0x2CD8,
+ },
+ [0x2CD9]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC DJA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CD8,
+ unicodeslot=0x2CD9,
+ },
+ [0x2CDA]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD COPTIC SHIMA",
+ direction="l",
+ lccode=0x2CDB,
+ linebreak="al",
+ unicodeslot=0x2CDA,
+ },
+ [0x2CDB]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD COPTIC SHIMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CDA,
+ unicodeslot=0x2CDB,
+ },
+ [0x2CDC]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD NUBIAN SHIMA",
+ direction="l",
+ lccode=0x2CDD,
+ linebreak="al",
+ unicodeslot=0x2CDC,
+ },
+ [0x2CDD]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD NUBIAN SHIMA",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CDC,
+ unicodeslot=0x2CDD,
+ },
+ [0x2CDE]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD NUBIAN NGI",
+ direction="l",
+ lccode=0x2CDF,
+ linebreak="al",
+ unicodeslot=0x2CDE,
+ },
+ [0x2CDF]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD NUBIAN NGI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CDE,
+ unicodeslot=0x2CDF,
+ },
+ [0x2CE0]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD NUBIAN NYI",
+ direction="l",
+ lccode=0x2CE1,
+ linebreak="al",
+ unicodeslot=0x2CE0,
+ },
+ [0x2CE1]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD NUBIAN NYI",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CE0,
+ unicodeslot=0x2CE1,
+ },
+ [0x2CE2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER OLD NUBIAN WAU",
+ direction="l",
+ lccode=0x2CE3,
+ linebreak="al",
+ unicodeslot=0x2CE2,
+ },
+ [0x2CE3]={
+ category="ll",
+ description="COPTIC SMALL LETTER OLD NUBIAN WAU",
+ direction="l",
+ linebreak="al",
+ uccode=0x2CE2,
+ unicodeslot=0x2CE3,
+ },
+ [0x2CE4]={
+ category="ll",
+ description="COPTIC SYMBOL KAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CE4,
+ },
+ [0x2CE5]={
+ category="so",
+ description="COPTIC SYMBOL MI RO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE5,
+ },
+ [0x2CE6]={
+ category="so",
+ description="COPTIC SYMBOL PI RO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE6,
+ },
+ [0x2CE7]={
+ category="so",
+ description="COPTIC SYMBOL STAUROS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE7,
+ },
+ [0x2CE8]={
+ category="so",
+ description="COPTIC SYMBOL TAU RO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE8,
+ },
+ [0x2CE9]={
+ category="so",
+ description="COPTIC SYMBOL KHI RO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CE9,
+ },
+ [0x2CEA]={
+ category="so",
+ description="COPTIC SYMBOL SHIMA SIMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CEA,
+ },
+ [0x2CEB]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEB,
+ },
+ [0x2CEC]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEC,
+ },
+ [0x2CED]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CED,
+ },
+ [0x2CEE]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEE,
+ },
+ [0x2CEF]={
+ category="mn",
+ combining=0xE6,
+ description="COPTIC COMBINING NI ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CEF,
+ },
+ [0x2CF0]={
+ category="mn",
+ combining=0xE6,
+ description="COPTIC COMBINING SPIRITUS ASPER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CF0,
+ },
+ [0x2CF1]={
+ category="mn",
+ combining=0xE6,
+ description="COPTIC COMBINING SPIRITUS LENIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CF1,
+ },
+ [0x2CF2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER BOHAIRIC KHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CF2,
+ },
+ [0x2CF3]={
+ category="ll",
+ description="COPTIC SMALL LETTER BOHAIRIC KHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CF3,
+ },
+ [0x2CF9]={
+ category="po",
+ description="COPTIC OLD NUBIAN FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2CF9,
+ },
+ [0x2CFA]={
+ category="po",
+ description="COPTIC OLD NUBIAN DIRECT QUESTION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2CFA,
+ },
+ [0x2CFB]={
+ category="po",
+ description="COPTIC OLD NUBIAN INDIRECT QUESTION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2CFB,
+ },
+ [0x2CFC]={
+ category="po",
+ description="COPTIC OLD NUBIAN VERSE DIVIDER",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2CFC,
+ },
+ [0x2CFD]={
+ category="no",
+ description="COPTIC FRACTION ONE HALF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2CFD,
+ },
+ [0x2CFE]={
+ category="po",
+ description="COPTIC FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2CFE,
+ },
+ [0x2CFF]={
+ category="po",
+ description="COPTIC MORPHOLOGICAL DIVIDER",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2CFF,
+ },
+ [0x2D00]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER AN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A0,
+ unicodeslot=0x2D00,
+ },
+ [0x2D01]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER BAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A1,
+ unicodeslot=0x2D01,
+ },
+ [0x2D02]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER GAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A2,
+ unicodeslot=0x2D02,
+ },
+ [0x2D03]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER DON",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A3,
+ unicodeslot=0x2D03,
+ },
+ [0x2D04]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER EN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A4,
+ unicodeslot=0x2D04,
+ },
+ [0x2D05]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER VIN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A5,
+ unicodeslot=0x2D05,
+ },
+ [0x2D06]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER ZEN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A6,
+ unicodeslot=0x2D06,
+ },
+ [0x2D07]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER TAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A7,
+ unicodeslot=0x2D07,
+ },
+ [0x2D08]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER IN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A8,
+ unicodeslot=0x2D08,
+ },
+ [0x2D09]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER KAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10A9,
+ unicodeslot=0x2D09,
+ },
+ [0x2D0A]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER LAS",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AA,
+ unicodeslot=0x2D0A,
+ },
+ [0x2D0B]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER MAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AB,
+ unicodeslot=0x2D0B,
+ },
+ [0x2D0C]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER NAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AC,
+ unicodeslot=0x2D0C,
+ },
+ [0x2D0D]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER ON",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AD,
+ unicodeslot=0x2D0D,
+ },
+ [0x2D0E]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER PAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AE,
+ unicodeslot=0x2D0E,
+ },
+ [0x2D0F]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER ZHAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10AF,
+ unicodeslot=0x2D0F,
+ },
+ [0x2D10]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER RAE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B0,
+ unicodeslot=0x2D10,
+ },
+ [0x2D11]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER SAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B1,
+ unicodeslot=0x2D11,
+ },
+ [0x2D12]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER TAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B2,
+ unicodeslot=0x2D12,
+ },
+ [0x2D13]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER UN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B3,
+ unicodeslot=0x2D13,
+ },
+ [0x2D14]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER PHAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B4,
+ unicodeslot=0x2D14,
+ },
+ [0x2D15]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER KHAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B5,
+ unicodeslot=0x2D15,
+ },
+ [0x2D16]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER GHAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B6,
+ unicodeslot=0x2D16,
+ },
+ [0x2D17]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER QAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B7,
+ unicodeslot=0x2D17,
+ },
+ [0x2D18]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER SHIN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B8,
+ unicodeslot=0x2D18,
+ },
+ [0x2D19]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER CHIN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10B9,
+ unicodeslot=0x2D19,
+ },
+ [0x2D1A]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER CAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BA,
+ unicodeslot=0x2D1A,
+ },
+ [0x2D1B]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER JIL",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BB,
+ unicodeslot=0x2D1B,
+ },
+ [0x2D1C]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER CIL",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BC,
+ unicodeslot=0x2D1C,
+ },
+ [0x2D1D]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER CHAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BD,
+ unicodeslot=0x2D1D,
+ },
+ [0x2D1E]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER XAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BE,
+ unicodeslot=0x2D1E,
+ },
+ [0x2D1F]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER JHAN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10BF,
+ unicodeslot=0x2D1F,
+ },
+ [0x2D20]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER HAE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C0,
+ unicodeslot=0x2D20,
+ },
+ [0x2D21]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER HE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C1,
+ unicodeslot=0x2D21,
+ },
+ [0x2D22]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER HIE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C2,
+ unicodeslot=0x2D22,
+ },
+ [0x2D23]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER WE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C3,
+ unicodeslot=0x2D23,
+ },
+ [0x2D24]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER HAR",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C4,
+ unicodeslot=0x2D24,
+ },
+ [0x2D25]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER HOE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10C5,
+ unicodeslot=0x2D25,
+ },
+ [0x2D27]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D27,
+ },
+ [0x2D2D]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D2D,
+ },
+ [0x2D30]={
+ category="lo",
+ description="TIFINAGH LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D30,
+ },
+ [0x2D31]={
+ category="lo",
+ description="TIFINAGH LETTER YAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D31,
+ },
+ [0x2D32]={
+ category="lo",
+ description="TIFINAGH LETTER YABH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D32,
+ },
+ [0x2D33]={
+ category="lo",
+ description="TIFINAGH LETTER YAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D33,
+ },
+ [0x2D34]={
+ category="lo",
+ description="TIFINAGH LETTER YAGHH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D34,
+ },
+ [0x2D35]={
+ category="lo",
+ description="TIFINAGH LETTER BERBER ACADEMY YAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D35,
+ },
+ [0x2D36]={
+ category="lo",
+ description="TIFINAGH LETTER YAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D36,
+ },
+ [0x2D37]={
+ category="lo",
+ description="TIFINAGH LETTER YAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D37,
+ },
+ [0x2D38]={
+ category="lo",
+ description="TIFINAGH LETTER YADH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D38,
+ },
+ [0x2D39]={
+ category="lo",
+ description="TIFINAGH LETTER YADD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D39,
+ },
+ [0x2D3A]={
+ category="lo",
+ description="TIFINAGH LETTER YADDH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3A,
+ },
+ [0x2D3B]={
+ category="lo",
+ description="TIFINAGH LETTER YEY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3B,
+ },
+ [0x2D3C]={
+ category="lo",
+ description="TIFINAGH LETTER YAF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3C,
+ },
+ [0x2D3D]={
+ category="lo",
+ description="TIFINAGH LETTER YAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3D,
+ },
+ [0x2D3E]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3E,
+ },
+ [0x2D3F]={
+ category="lo",
+ description="TIFINAGH LETTER YAKHH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D3F,
+ },
+ [0x2D40]={
+ category="lo",
+ description="TIFINAGH LETTER YAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D40,
+ },
+ [0x2D41]={
+ category="lo",
+ description="TIFINAGH LETTER BERBER ACADEMY YAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D41,
+ },
+ [0x2D42]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D42,
+ },
+ [0x2D43]={
+ category="lo",
+ description="TIFINAGH LETTER YAHH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D43,
+ },
+ [0x2D44]={
+ category="lo",
+ description="TIFINAGH LETTER YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D44,
+ },
+ [0x2D45]={
+ category="lo",
+ description="TIFINAGH LETTER YAKH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D45,
+ },
+ [0x2D46]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAKH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D46,
+ },
+ [0x2D47]={
+ category="lo",
+ description="TIFINAGH LETTER YAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D47,
+ },
+ [0x2D48]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D48,
+ },
+ [0x2D49]={
+ category="lo",
+ description="TIFINAGH LETTER YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D49,
+ },
+ [0x2D4A]={
+ category="lo",
+ description="TIFINAGH LETTER YAZH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4A,
+ },
+ [0x2D4B]={
+ category="lo",
+ description="TIFINAGH LETTER AHAGGAR YAZH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4B,
+ },
+ [0x2D4C]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAZH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4C,
+ },
+ [0x2D4D]={
+ category="lo",
+ description="TIFINAGH LETTER YAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4D,
+ },
+ [0x2D4E]={
+ category="lo",
+ description="TIFINAGH LETTER YAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4E,
+ },
+ [0x2D4F]={
+ category="lo",
+ description="TIFINAGH LETTER YAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D4F,
+ },
+ [0x2D50]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D50,
+ },
+ [0x2D51]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D51,
+ },
+ [0x2D52]={
+ category="lo",
+ description="TIFINAGH LETTER YAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D52,
+ },
+ [0x2D53]={
+ category="lo",
+ description="TIFINAGH LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D53,
+ },
+ [0x2D54]={
+ category="lo",
+ description="TIFINAGH LETTER YAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D54,
+ },
+ [0x2D55]={
+ category="lo",
+ description="TIFINAGH LETTER YARR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D55,
+ },
+ [0x2D56]={
+ category="lo",
+ description="TIFINAGH LETTER YAGH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D56,
+ },
+ [0x2D57]={
+ category="lo",
+ description="TIFINAGH LETTER TUAREG YAGH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D57,
+ },
+ [0x2D58]={
+ category="lo",
+ description="TIFINAGH LETTER AYER YAGH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D58,
+ },
+ [0x2D59]={
+ category="lo",
+ description="TIFINAGH LETTER YAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D59,
+ },
+ [0x2D5A]={
+ category="lo",
+ description="TIFINAGH LETTER YASS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5A,
+ },
+ [0x2D5B]={
+ category="lo",
+ description="TIFINAGH LETTER YASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5B,
+ },
+ [0x2D5C]={
+ category="lo",
+ description="TIFINAGH LETTER YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5C,
+ },
+ [0x2D5D]={
+ category="lo",
+ description="TIFINAGH LETTER YATH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5D,
+ },
+ [0x2D5E]={
+ category="lo",
+ description="TIFINAGH LETTER YACH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5E,
+ },
+ [0x2D5F]={
+ category="lo",
+ description="TIFINAGH LETTER YATT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D5F,
+ },
+ [0x2D60]={
+ category="lo",
+ description="TIFINAGH LETTER YAV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D60,
+ },
+ [0x2D61]={
+ category="lo",
+ description="TIFINAGH LETTER YAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D61,
+ },
+ [0x2D62]={
+ category="lo",
+ description="TIFINAGH LETTER YAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D62,
+ },
+ [0x2D63]={
+ category="lo",
+ description="TIFINAGH LETTER YAZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D63,
+ },
+ [0x2D64]={
+ category="lo",
+ description="TIFINAGH LETTER TAWELLEMET YAZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D64,
+ },
+ [0x2D65]={
+ category="lo",
+ description="TIFINAGH LETTER YAZZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D65,
+ },
+ [0x2D66]={
+ category="lo",
+ description="TIFINAGH LETTER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D66,
+ },
+ [0x2D67]={
+ category="lo",
+ description="TIFINAGH LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D67,
+ },
+ [0x2D6F]={
+ category="lm",
+ description="TIFINAGH MODIFIER LETTER LABIALIZATION MARK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x2D61 },
+ unicodeslot=0x2D6F,
+ },
+ [0x2D70]={
+ category="po",
+ description="TIFINAGH SEPARATOR MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x2D70,
+ },
+ [0x2D7F]={
+ category="mn",
+ combining=0x9,
+ description="TIFINAGH CONSONANT JOINER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2D7F,
+ },
+ [0x2D80]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE LOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D80,
+ },
+ [0x2D81]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE MOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D81,
+ },
+ [0x2D82]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ROA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D82,
+ },
+ [0x2D83]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D83,
+ },
+ [0x2D84]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SHOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D84,
+ },
+ [0x2D85]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D85,
+ },
+ [0x2D86]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D86,
+ },
+ [0x2D87]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE COA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D87,
+ },
+ [0x2D88]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D88,
+ },
+ [0x2D89]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE NYOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D89,
+ },
+ [0x2D8A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GLOTTAL OA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8A,
+ },
+ [0x2D8B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8B,
+ },
+ [0x2D8C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8C,
+ },
+ [0x2D8D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8D,
+ },
+ [0x2D8E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE JOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8E,
+ },
+ [0x2D8F]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE THOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D8F,
+ },
+ [0x2D90]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CHOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D90,
+ },
+ [0x2D91]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE PHOA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D91,
+ },
+ [0x2D92]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE POA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D92,
+ },
+ [0x2D93]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D93,
+ },
+ [0x2D94]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D94,
+ },
+ [0x2D95]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D95,
+ },
+ [0x2D96]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GGWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D96,
+ },
+ [0x2DA0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA0,
+ },
+ [0x2DA1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA1,
+ },
+ [0x2DA2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA2,
+ },
+ [0x2DA3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA3,
+ },
+ [0x2DA4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA4,
+ },
+ [0x2DA5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA5,
+ },
+ [0x2DA6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE SSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA6,
+ },
+ [0x2DA8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA8,
+ },
+ [0x2DA9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DA9,
+ },
+ [0x2DAA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DAA,
+ },
+ [0x2DAB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DAB,
+ },
+ [0x2DAC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DAC,
+ },
+ [0x2DAD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DAD,
+ },
+ [0x2DAE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DAE,
+ },
+ [0x2DB0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB0,
+ },
+ [0x2DB1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB1,
+ },
+ [0x2DB2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB2,
+ },
+ [0x2DB3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB3,
+ },
+ [0x2DB4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB4,
+ },
+ [0x2DB5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB5,
+ },
+ [0x2DB6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE ZZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB6,
+ },
+ [0x2DB8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB8,
+ },
+ [0x2DB9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DB9,
+ },
+ [0x2DBA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DBA,
+ },
+ [0x2DBB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DBB,
+ },
+ [0x2DBC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DBC,
+ },
+ [0x2DBD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DBD,
+ },
+ [0x2DBE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DBE,
+ },
+ [0x2DC0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC0,
+ },
+ [0x2DC1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC1,
+ },
+ [0x2DC2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC2,
+ },
+ [0x2DC3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC3,
+ },
+ [0x2DC4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC4,
+ },
+ [0x2DC5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC5,
+ },
+ [0x2DC6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE QYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC6,
+ },
+ [0x2DC8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC8,
+ },
+ [0x2DC9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DC9,
+ },
+ [0x2DCA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DCA,
+ },
+ [0x2DCB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DCB,
+ },
+ [0x2DCC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DCC,
+ },
+ [0x2DCD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DCD,
+ },
+ [0x2DCE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE KYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DCE,
+ },
+ [0x2DD0]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD0,
+ },
+ [0x2DD1]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD1,
+ },
+ [0x2DD2]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD2,
+ },
+ [0x2DD3]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD3,
+ },
+ [0x2DD4]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD4,
+ },
+ [0x2DD5]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD5,
+ },
+ [0x2DD6]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE XYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD6,
+ },
+ [0x2DD8]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD8,
+ },
+ [0x2DD9]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DD9,
+ },
+ [0x2DDA]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DDA,
+ },
+ [0x2DDB]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DDB,
+ },
+ [0x2DDC]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DDC,
+ },
+ [0x2DDD]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DDD,
+ },
+ [0x2DDE]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE GYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2DDE,
+ },
+ [0x2DE0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER BE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE0,
+ },
+ [0x2DE1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER VE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE1,
+ },
+ [0x2DE2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER GHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE2,
+ },
+ [0x2DE3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER DE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE3,
+ },
+ [0x2DE4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER ZHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE4,
+ },
+ [0x2DE5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER ZE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE5,
+ },
+ [0x2DE6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE6,
+ },
+ [0x2DE7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER EL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE7,
+ },
+ [0x2DE8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER EM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE8,
+ },
+ [0x2DE9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER EN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE9,
+ },
+ [0x2DEA]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEA,
+ },
+ [0x2DEB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER PE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEB,
+ },
+ [0x2DEC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER ER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEC,
+ },
+ [0x2DED]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER ES",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DED,
+ },
+ [0x2DEE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER TE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEE,
+ },
+ [0x2DEF]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER HA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEF,
+ },
+ [0x2DF0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER TSE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF0,
+ },
+ [0x2DF1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER CHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF1,
+ },
+ [0x2DF2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER SHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF2,
+ },
+ [0x2DF3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER SHCHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF3,
+ },
+ [0x2DF4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER FITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF4,
+ },
+ [0x2DF5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER ES-TE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF5,
+ },
+ [0x2DF6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF6,
+ },
+ [0x2DF7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER IE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF7,
+ },
+ [0x2DF8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER DJERV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF8,
+ },
+ [0x2DF9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER MONOGRAPH UK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF9,
+ },
+ [0x2DFA]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER YAT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFA,
+ },
+ [0x2DFB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER YU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFB,
+ },
+ [0x2DFC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER IOTIFIED A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFC,
+ },
+ [0x2DFD]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER LITTLE YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFD,
+ },
+ [0x2DFE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER BIG YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFE,
+ },
+ [0x2DFF]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER IOTIFIED BIG YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFF,
+ },
+ [0x2E00]={
+ category="po",
+ description="RIGHT ANGLE SUBSTITUTION MARKER",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E00,
+ },
+ [0x2E01]={
+ category="po",
+ description="RIGHT ANGLE DOTTED SUBSTITUTION MARKER",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E01,
+ },
+ [0x2E02]={
+ category="pi",
+ description="LEFT SUBSTITUTION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E03,
+ unicodeslot=0x2E02,
+ },
+ [0x2E03]={
+ category="pf",
+ description="RIGHT SUBSTITUTION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E02,
+ unicodeslot=0x2E03,
+ },
+ [0x2E04]={
+ category="pi",
+ description="LEFT DOTTED SUBSTITUTION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E05,
+ unicodeslot=0x2E04,
+ },
+ [0x2E05]={
+ category="pf",
+ description="RIGHT DOTTED SUBSTITUTION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E04,
+ unicodeslot=0x2E05,
+ },
+ [0x2E06]={
+ category="po",
+ description="RAISED INTERPOLATION MARKER",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E06,
+ },
+ [0x2E07]={
+ category="po",
+ description="RAISED DOTTED INTERPOLATION MARKER",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E07,
+ },
+ [0x2E08]={
+ category="po",
+ description="DOTTED TRANSPOSITION MARKER",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E08,
+ },
+ [0x2E09]={
+ category="pi",
+ description="LEFT TRANSPOSITION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E0A,
+ unicodeslot=0x2E09,
+ },
+ [0x2E0A]={
+ category="pf",
+ description="RIGHT TRANSPOSITION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E09,
+ unicodeslot=0x2E0A,
+ },
+ [0x2E0B]={
+ category="po",
+ description="RAISED SQUARE",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x2E0B,
+ },
+ [0x2E0C]={
+ category="pi",
+ description="LEFT RAISED OMISSION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E0D,
+ unicodeslot=0x2E0C,
+ },
+ [0x2E0D]={
+ category="pf",
+ description="RIGHT RAISED OMISSION BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E0C,
+ unicodeslot=0x2E0D,
+ },
+ [0x2E0E]={
+ category="po",
+ description="EDITORIAL CORONIS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E0E,
+ },
+ [0x2E0F]={
+ category="po",
+ description="PARAGRAPHOS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E0F,
+ },
+ [0x2E10]={
+ category="po",
+ description="FORKED PARAGRAPHOS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E10,
+ },
+ [0x2E11]={
+ category="po",
+ description="REVERSED FORKED PARAGRAPHOS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E11,
+ },
+ [0x2E12]={
+ category="po",
+ description="HYPODIASTOLE",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E12,
+ },
+ [0x2E13]={
+ category="po",
+ description="DOTTED OBELOS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E13,
+ },
+ [0x2E14]={
+ category="po",
+ description="DOWNWARDS ANCORA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E14,
+ },
+ [0x2E15]={
+ category="po",
+ description="UPWARDS ANCORA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E15,
+ },
+ [0x2E16]={
+ category="po",
+ description="DOTTED RIGHT-POINTING ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E16,
+ },
+ [0x2E17]={
+ category="pd",
+ description="DOUBLE OBLIQUE HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E17,
+ },
+ [0x2E18]={
+ category="po",
+ description="INVERTED INTERROBANG",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x2E18,
+ },
+ [0x2E19]={
+ category="po",
+ description="PALM BRANCH",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E19,
+ },
+ [0x2E1A]={
+ category="pd",
+ description="HYPHEN WITH DIAERESIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1A,
+ },
+ [0x2E1B]={
+ category="po",
+ description="TILDE WITH RING ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1B,
+ },
+ [0x2E1C]={
+ category="pi",
+ description="LEFT LOW PARAPHRASE BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E1D,
+ unicodeslot=0x2E1C,
+ },
+ [0x2E1D]={
+ category="pf",
+ description="RIGHT LOW PARAPHRASE BRACKET",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E1C,
+ unicodeslot=0x2E1D,
+ },
+ [0x2E1E]={
+ category="po",
+ description="TILDE WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1E,
+ },
+ [0x2E1F]={
+ category="po",
+ description="TILDE WITH DOT BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1F,
+ },
+ [0x2E20]={
+ category="pi",
+ description="LEFT VERTICAL BAR WITH QUILL",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E21,
+ unicodeslot=0x2E20,
+ },
+ [0x2E21]={
+ category="pf",
+ description="RIGHT VERTICAL BAR WITH QUILL",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E20,
+ unicodeslot=0x2E21,
+ },
+ [0x2E22]={
+ category="ps",
+ description="TOP LEFT HALF BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E23,
+ unicodeslot=0x2E22,
+ },
+ [0x2E23]={
+ category="pe",
+ description="TOP RIGHT HALF BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E22,
+ unicodeslot=0x2E23,
+ },
+ [0x2E24]={
+ category="ps",
+ description="BOTTOM LEFT HALF BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E25,
+ unicodeslot=0x2E24,
+ },
+ [0x2E25]={
+ category="pe",
+ description="BOTTOM RIGHT HALF BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E24,
+ unicodeslot=0x2E25,
+ },
+ [0x2E26]={
+ category="ps",
+ description="LEFT SIDEWAYS U BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E27,
+ unicodeslot=0x2E26,
+ },
+ [0x2E27]={
+ category="pe",
+ description="RIGHT SIDEWAYS U BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E26,
+ unicodeslot=0x2E27,
+ },
+ [0x2E28]={
+ category="ps",
+ description="LEFT DOUBLE PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E29,
+ unicodeslot=0x2E28,
+ },
+ [0x2E29]={
+ category="pe",
+ description="RIGHT DOUBLE PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E28,
+ unicodeslot=0x2E29,
+ },
+ [0x2E2A]={
+ category="po",
+ description="TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2A,
+ },
+ [0x2E2B]={
+ category="po",
+ description="ONE DOT OVER TWO DOTS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2B,
+ },
+ [0x2E2C]={
+ category="po",
+ description="SQUARED FOUR DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2C,
+ },
+ [0x2E2D]={
+ category="po",
+ description="FIVE DOT MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2D,
+ },
+ [0x2E2E]={
+ category="po",
+ description="REVERSED QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2E2E,
+ },
+ [0x2E2F]={
+ category="lm",
+ description="VERTICAL TILDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E2F,
+ },
+ [0x2E30]={
+ category="po",
+ description="RING POINT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E30,
+ },
+ [0x2E31]={
+ category="po",
+ description="WORD SEPARATOR MIDDLE DOT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E31,
+ },
+ [0x2E32]={
+ category="po",
+ description="TURNED COMMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E32,
+ },
+ [0x2E33]={
+ category="po",
+ description="RAISED DOT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E33,
+ },
+ [0x2E34]={
+ category="po",
+ description="RAISED COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E34,
+ },
+ [0x2E35]={
+ category="po",
+ description="TURNED SEMICOLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E35,
+ },
+ [0x2E36]={
+ category="po",
+ description="DAGGER WITH LEFT GUARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E36,
+ },
+ [0x2E37]={
+ category="po",
+ description="DAGGER WITH RIGHT GUARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E37,
+ },
+ [0x2E38]={
+ category="po",
+ description="TURNED DAGGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E38,
+ },
+ [0x2E39]={
+ category="po",
+ description="TOP HALF SECTION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E39,
+ },
+ [0x2E3A]={
+ category="pd",
+ description="TWO-EM DASH",
+ direction="on",
+ linebreak="b2",
+ unicodeslot=0x2E3A,
+ },
+ [0x2E3B]={
+ category="pd",
+ description="THREE-EM DASH",
+ direction="on",
+ linebreak="b2",
+ unicodeslot=0x2E3B,
+ },
+ [0x2E3C]={
+ category="po",
+ description="STENOGRAPHIC FULL STOP",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E3C,
+ },
+ [0x2E3D]={
+ category="po",
+ description="VERTICAL SIX DOTS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E3D,
+ },
+ [0x2E3E]={
+ category="po",
+ description="WIGGLY VERTICAL LINE",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E3E,
+ },
+ [0x2E3F]={
+ category="po",
+ description="CAPITULUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E3F,
+ },
+ [0x2E40]={
+ category="pd",
+ description="DOUBLE HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E40,
+ },
+ [0x2E41]={
+ category="po",
+ description="REVERSED COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E41,
+ },
+ [0x2E42]={
+ category="ps",
+ description="DOUBLE LOW-REVERSED-9 QUOTATION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x2E42,
+ },
+ [0x2E80]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL REPEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E80,
+ },
+ [0x2E81]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL CLIFF",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E81,
+ },
+ [0x2E82]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SECOND ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E82,
+ },
+ [0x2E83]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SECOND TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E83,
+ },
+ [0x2E84]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SECOND THREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E84,
+ },
+ [0x2E85]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL PERSON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E85,
+ },
+ [0x2E86]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BOX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E86,
+ },
+ [0x2E87]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL TABLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E87,
+ },
+ [0x2E88]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL KNIFE ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E88,
+ },
+ [0x2E89]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL KNIFE TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E89,
+ },
+ [0x2E8A]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL DIVINATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8A,
+ },
+ [0x2E8B]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SEAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8B,
+ },
+ [0x2E8C]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SMALL ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8C,
+ },
+ [0x2E8D]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SMALL TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8D,
+ },
+ [0x2E8E]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LAME ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8E,
+ },
+ [0x2E8F]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LAME TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E8F,
+ },
+ [0x2E90]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LAME THREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E90,
+ },
+ [0x2E91]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LAME FOUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E91,
+ },
+ [0x2E92]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SNAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E92,
+ },
+ [0x2E93]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL THREAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E93,
+ },
+ [0x2E94]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SNOUT ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E94,
+ },
+ [0x2E95]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SNOUT TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E95,
+ },
+ [0x2E96]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL HEART ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E96,
+ },
+ [0x2E97]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL HEART TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E97,
+ },
+ [0x2E98]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E98,
+ },
+ [0x2E99]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL RAP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E99,
+ },
+ [0x2E9B]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL CHOKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E9B,
+ },
+ [0x2E9C]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SUN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E9C,
+ },
+ [0x2E9D]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E9D,
+ },
+ [0x2E9E]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL DEATH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2E9E,
+ },
+ [0x2E9F]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MOTHER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6BCD },
+ unicodeslot=0x2E9F,
+ },
+ [0x2EA0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL CIVILIAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA0,
+ },
+ [0x2EA1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WATER ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA1,
+ },
+ [0x2EA2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WATER TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA2,
+ },
+ [0x2EA3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL FIRE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA3,
+ },
+ [0x2EA4]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL PAW ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA4,
+ },
+ [0x2EA5]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL PAW TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA5,
+ },
+ [0x2EA6]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SIMPLIFIED HALF TREE TRUNK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA6,
+ },
+ [0x2EA7]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL COW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA7,
+ },
+ [0x2EA8]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL DOG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA8,
+ },
+ [0x2EA9]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL JADE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EA9,
+ },
+ [0x2EAA]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BOLT OF CLOTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAA,
+ },
+ [0x2EAB]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL EYE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAB,
+ },
+ [0x2EAC]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SPIRIT ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAC,
+ },
+ [0x2EAD]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SPIRIT TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAD,
+ },
+ [0x2EAE]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BAMBOO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAE,
+ },
+ [0x2EAF]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SILK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EAF,
+ },
+ [0x2EB0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED SILK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB0,
+ },
+ [0x2EB1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL NET ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB1,
+ },
+ [0x2EB2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL NET TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB2,
+ },
+ [0x2EB3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL NET THREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB3,
+ },
+ [0x2EB4]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL NET FOUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB4,
+ },
+ [0x2EB5]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MESH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB5,
+ },
+ [0x2EB6]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SHEEP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB6,
+ },
+ [0x2EB7]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL RAM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB7,
+ },
+ [0x2EB8]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL EWE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB8,
+ },
+ [0x2EB9]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL OLD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EB9,
+ },
+ [0x2EBA]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BRUSH ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBA,
+ },
+ [0x2EBB]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BRUSH TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBB,
+ },
+ [0x2EBC]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBC,
+ },
+ [0x2EBD]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MORTAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBD,
+ },
+ [0x2EBE]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL GRASS ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBE,
+ },
+ [0x2EBF]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL GRASS TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EBF,
+ },
+ [0x2EC0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL GRASS THREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC0,
+ },
+ [0x2EC1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL TIGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC1,
+ },
+ [0x2EC2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL CLOTHES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC2,
+ },
+ [0x2EC3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WEST ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC3,
+ },
+ [0x2EC4]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WEST TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC4,
+ },
+ [0x2EC5]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED SEE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC5,
+ },
+ [0x2EC6]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SIMPLIFIED HORN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC6,
+ },
+ [0x2EC7]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL HORN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC7,
+ },
+ [0x2EC8]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED SPEECH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC8,
+ },
+ [0x2EC9]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED SHELL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EC9,
+ },
+ [0x2ECA]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL FOOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECA,
+ },
+ [0x2ECB]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED CART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECB,
+ },
+ [0x2ECC]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SIMPLIFIED WALK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECC,
+ },
+ [0x2ECD]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WALK ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECD,
+ },
+ [0x2ECE]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL WALK TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECE,
+ },
+ [0x2ECF]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL CITY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ECF,
+ },
+ [0x2ED0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED GOLD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED0,
+ },
+ [0x2ED1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LONG ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED1,
+ },
+ [0x2ED2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL LONG TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED2,
+ },
+ [0x2ED3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED LONG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED3,
+ },
+ [0x2ED4]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED GATE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED4,
+ },
+ [0x2ED5]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MOUND ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED5,
+ },
+ [0x2ED6]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL MOUND TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED6,
+ },
+ [0x2ED7]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL RAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED7,
+ },
+ [0x2ED8]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BLUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED8,
+ },
+ [0x2ED9]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED TANNED LEATHER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2ED9,
+ },
+ [0x2EDA]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED LEAF",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDA,
+ },
+ [0x2EDB]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDB,
+ },
+ [0x2EDC]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED FLY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDC,
+ },
+ [0x2EDD]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL EAT ONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDD,
+ },
+ [0x2EDE]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL EAT TWO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDE,
+ },
+ [0x2EDF]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL EAT THREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EDF,
+ },
+ [0x2EE0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED EAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE0,
+ },
+ [0x2EE1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL HEAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE1,
+ },
+ [0x2EE2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED HORSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE2,
+ },
+ [0x2EE3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL BONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE3,
+ },
+ [0x2EE4]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL GHOST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE4,
+ },
+ [0x2EE5]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED FISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE5,
+ },
+ [0x2EE6]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED BIRD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE6,
+ },
+ [0x2EE7]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED SALT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE7,
+ },
+ [0x2EE8]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SIMPLIFIED WHEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE8,
+ },
+ [0x2EE9]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL SIMPLIFIED YELLOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EE9,
+ },
+ [0x2EEA]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED FROG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EEA,
+ },
+ [0x2EEB]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL J-SIMPLIFIED EVEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EEB,
+ },
+ [0x2EEC]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED EVEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EEC,
+ },
+ [0x2EED]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL J-SIMPLIFIED TOOTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EED,
+ },
+ [0x2EEE]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED TOOTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EEE,
+ },
+ [0x2EEF]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL J-SIMPLIFIED DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EEF,
+ },
+ [0x2EF0]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EF0,
+ },
+ [0x2EF1]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL TURTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EF1,
+ },
+ [0x2EF2]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL J-SIMPLIFIED TURTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2EF2,
+ },
+ [0x2EF3]={
+ category="so",
+ cjkwd="w",
+ description="CJK RADICAL C-SIMPLIFIED TURTLE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F9F },
+ unicodeslot=0x2EF3,
+ },
+ [0x2F00]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ONE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E00 },
+ unicodeslot=0x2F00,
+ },
+ [0x2F01]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E28 },
+ unicodeslot=0x2F01,
+ },
+ [0x2F02]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E36 },
+ unicodeslot=0x2F02,
+ },
+ [0x2F03]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SLASH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E3F },
+ unicodeslot=0x2F03,
+ },
+ [0x2F04]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SECOND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E59 },
+ unicodeslot=0x2F04,
+ },
+ [0x2F05]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HOOK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E85 },
+ unicodeslot=0x2F05,
+ },
+ [0x2F06]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TWO",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4E8C },
+ unicodeslot=0x2F06,
+ },
+ [0x2F07]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LID",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4EA0 },
+ unicodeslot=0x2F07,
+ },
+ [0x2F08]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MAN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x4EBA },
+ unicodeslot=0x2F08,
+ },
+ [0x2F09]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LEGS",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x513F },
+ unicodeslot=0x2F09,
+ },
+ [0x2F0A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ENTER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5165 },
+ unicodeslot=0x2F0A,
+ },
+ [0x2F0B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EIGHT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x516B },
+ unicodeslot=0x2F0B,
+ },
+ [0x2F0C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOWN BOX",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5182 },
+ unicodeslot=0x2F0C,
+ },
+ [0x2F0D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL COVER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5196 },
+ unicodeslot=0x2F0D,
+ },
+ [0x2F0E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ICE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x51AB },
+ unicodeslot=0x2F0E,
+ },
+ [0x2F0F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TABLE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x51E0 },
+ unicodeslot=0x2F0F,
+ },
+ [0x2F10]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL OPEN BOX",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x51F5 },
+ unicodeslot=0x2F10,
+ },
+ [0x2F11]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL KNIFE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5200 },
+ unicodeslot=0x2F11,
+ },
+ [0x2F12]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL POWER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x529B },
+ unicodeslot=0x2F12,
+ },
+ [0x2F13]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WRAP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x52F9 },
+ unicodeslot=0x2F13,
+ },
+ [0x2F14]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SPOON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5315 },
+ unicodeslot=0x2F14,
+ },
+ [0x2F15]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RIGHT OPEN BOX",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x531A },
+ unicodeslot=0x2F15,
+ },
+ [0x2F16]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HIDING ENCLOSURE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5338 },
+ unicodeslot=0x2F16,
+ },
+ [0x2F17]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TEN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5341 },
+ unicodeslot=0x2F17,
+ },
+ [0x2F18]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DIVINATION",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x535C },
+ unicodeslot=0x2F18,
+ },
+ [0x2F19]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SEAL",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5369 },
+ unicodeslot=0x2F19,
+ },
+ [0x2F1A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CLIFF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5382 },
+ unicodeslot=0x2F1A,
+ },
+ [0x2F1B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL PRIVATE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x53B6 },
+ unicodeslot=0x2F1B,
+ },
+ [0x2F1C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL AGAIN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x53C8 },
+ unicodeslot=0x2F1C,
+ },
+ [0x2F1D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MOUTH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x53E3 },
+ unicodeslot=0x2F1D,
+ },
+ [0x2F1E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ENCLOSURE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x56D7 },
+ unicodeslot=0x2F1E,
+ },
+ [0x2F1F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EARTH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x571F },
+ unicodeslot=0x2F1F,
+ },
+ [0x2F20]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SCHOLAR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x58EB },
+ unicodeslot=0x2F20,
+ },
+ [0x2F21]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GO",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5902 },
+ unicodeslot=0x2F21,
+ },
+ [0x2F22]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GO SLOWLY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x590A },
+ unicodeslot=0x2F22,
+ },
+ [0x2F23]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EVENING",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5915 },
+ unicodeslot=0x2F23,
+ },
+ [0x2F24]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BIG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5927 },
+ unicodeslot=0x2F24,
+ },
+ [0x2F25]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WOMAN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5973 },
+ unicodeslot=0x2F25,
+ },
+ [0x2F26]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CHILD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5B50 },
+ unicodeslot=0x2F26,
+ },
+ [0x2F27]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ROOF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5B80 },
+ unicodeslot=0x2F27,
+ },
+ [0x2F28]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL INCH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5BF8 },
+ unicodeslot=0x2F28,
+ },
+ [0x2F29]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SMALL",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5C0F },
+ unicodeslot=0x2F29,
+ },
+ [0x2F2A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LAME",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5C22 },
+ unicodeslot=0x2F2A,
+ },
+ [0x2F2B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CORPSE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5C38 },
+ unicodeslot=0x2F2B,
+ },
+ [0x2F2C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SPROUT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5C6E },
+ unicodeslot=0x2F2C,
+ },
+ [0x2F2D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MOUNTAIN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5C71 },
+ unicodeslot=0x2F2D,
+ },
+ [0x2F2E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RIVER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5DDB },
+ unicodeslot=0x2F2E,
+ },
+ [0x2F2F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WORK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5DE5 },
+ unicodeslot=0x2F2F,
+ },
+ [0x2F30]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ONESELF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5DF1 },
+ unicodeslot=0x2F30,
+ },
+ [0x2F31]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TURBAN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5DFE },
+ unicodeslot=0x2F31,
+ },
+ [0x2F32]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DRY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5E72 },
+ unicodeslot=0x2F32,
+ },
+ [0x2F33]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SHORT THREAD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5E7A },
+ unicodeslot=0x2F33,
+ },
+ [0x2F34]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOTTED CLIFF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5E7F },
+ unicodeslot=0x2F34,
+ },
+ [0x2F35]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LONG STRIDE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5EF4 },
+ unicodeslot=0x2F35,
+ },
+ [0x2F36]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TWO HANDS",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5EFE },
+ unicodeslot=0x2F36,
+ },
+ [0x2F37]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SHOOT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F0B },
+ unicodeslot=0x2F37,
+ },
+ [0x2F38]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BOW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F13 },
+ unicodeslot=0x2F38,
+ },
+ [0x2F39]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SNOUT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F50 },
+ unicodeslot=0x2F39,
+ },
+ [0x2F3A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BRISTLE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F61 },
+ unicodeslot=0x2F3A,
+ },
+ [0x2F3B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STEP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F73 },
+ unicodeslot=0x2F3B,
+ },
+ [0x2F3C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HEART",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5FC3 },
+ unicodeslot=0x2F3C,
+ },
+ [0x2F3D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HALBERD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6208 },
+ unicodeslot=0x2F3D,
+ },
+ [0x2F3E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOOR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6236 },
+ unicodeslot=0x2F3E,
+ },
+ [0x2F3F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HAND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x624B },
+ unicodeslot=0x2F3F,
+ },
+ [0x2F40]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BRANCH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x652F },
+ unicodeslot=0x2F40,
+ },
+ [0x2F41]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RAP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6534 },
+ unicodeslot=0x2F41,
+ },
+ [0x2F42]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SCRIPT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6587 },
+ unicodeslot=0x2F42,
+ },
+ [0x2F43]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DIPPER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6597 },
+ unicodeslot=0x2F43,
+ },
+ [0x2F44]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL AXE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x65A4 },
+ unicodeslot=0x2F44,
+ },
+ [0x2F45]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SQUARE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x65B9 },
+ unicodeslot=0x2F45,
+ },
+ [0x2F46]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL NOT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x65E0 },
+ unicodeslot=0x2F46,
+ },
+ [0x2F47]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SUN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x65E5 },
+ unicodeslot=0x2F47,
+ },
+ [0x2F48]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SAY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x66F0 },
+ unicodeslot=0x2F48,
+ },
+ [0x2F49]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MOON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6708 },
+ unicodeslot=0x2F49,
+ },
+ [0x2F4A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TREE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6728 },
+ unicodeslot=0x2F4A,
+ },
+ [0x2F4B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LACK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6B20 },
+ unicodeslot=0x2F4B,
+ },
+ [0x2F4C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STOP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6B62 },
+ unicodeslot=0x2F4C,
+ },
+ [0x2F4D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DEATH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6B79 },
+ unicodeslot=0x2F4D,
+ },
+ [0x2F4E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WEAPON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6BB3 },
+ unicodeslot=0x2F4E,
+ },
+ [0x2F4F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DO NOT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6BCB },
+ unicodeslot=0x2F4F,
+ },
+ [0x2F50]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL COMPARE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6BD4 },
+ unicodeslot=0x2F50,
+ },
+ [0x2F51]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FUR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6BDB },
+ unicodeslot=0x2F51,
+ },
+ [0x2F52]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CLAN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6C0F },
+ unicodeslot=0x2F52,
+ },
+ [0x2F53]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STEAM",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6C14 },
+ unicodeslot=0x2F53,
+ },
+ [0x2F54]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WATER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x6C34 },
+ unicodeslot=0x2F54,
+ },
+ [0x2F55]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FIRE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x706B },
+ unicodeslot=0x2F55,
+ },
+ [0x2F56]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CLAW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x722A },
+ unicodeslot=0x2F56,
+ },
+ [0x2F57]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FATHER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7236 },
+ unicodeslot=0x2F57,
+ },
+ [0x2F58]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOUBLE X",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x723B },
+ unicodeslot=0x2F58,
+ },
+ [0x2F59]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HALF TREE TRUNK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x723F },
+ unicodeslot=0x2F59,
+ },
+ [0x2F5A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SLICE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7247 },
+ unicodeslot=0x2F5A,
+ },
+ [0x2F5B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FANG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7259 },
+ unicodeslot=0x2F5B,
+ },
+ [0x2F5C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL COW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x725B },
+ unicodeslot=0x2F5C,
+ },
+ [0x2F5D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x72AC },
+ unicodeslot=0x2F5D,
+ },
+ [0x2F5E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL PROFOUND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7384 },
+ unicodeslot=0x2F5E,
+ },
+ [0x2F5F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL JADE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7389 },
+ unicodeslot=0x2F5F,
+ },
+ [0x2F60]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MELON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x74DC },
+ unicodeslot=0x2F60,
+ },
+ [0x2F61]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TILE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x74E6 },
+ unicodeslot=0x2F61,
+ },
+ [0x2F62]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SWEET",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7518 },
+ unicodeslot=0x2F62,
+ },
+ [0x2F63]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LIFE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x751F },
+ unicodeslot=0x2F63,
+ },
+ [0x2F64]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL USE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7528 },
+ unicodeslot=0x2F64,
+ },
+ [0x2F65]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FIELD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7530 },
+ unicodeslot=0x2F65,
+ },
+ [0x2F66]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BOLT OF CLOTH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x758B },
+ unicodeslot=0x2F66,
+ },
+ [0x2F67]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SICKNESS",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7592 },
+ unicodeslot=0x2F67,
+ },
+ [0x2F68]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DOTTED TENT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7676 },
+ unicodeslot=0x2F68,
+ },
+ [0x2F69]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WHITE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x767D },
+ unicodeslot=0x2F69,
+ },
+ [0x2F6A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SKIN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x76AE },
+ unicodeslot=0x2F6A,
+ },
+ [0x2F6B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DISH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x76BF },
+ unicodeslot=0x2F6B,
+ },
+ [0x2F6C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EYE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x76EE },
+ unicodeslot=0x2F6C,
+ },
+ [0x2F6D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SPEAR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x77DB },
+ unicodeslot=0x2F6D,
+ },
+ [0x2F6E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ARROW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x77E2 },
+ unicodeslot=0x2F6E,
+ },
+ [0x2F6F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STONE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x77F3 },
+ unicodeslot=0x2F6F,
+ },
+ [0x2F70]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SPIRIT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x793A },
+ unicodeslot=0x2F70,
+ },
+ [0x2F71]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TRACK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x79B8 },
+ unicodeslot=0x2F71,
+ },
+ [0x2F72]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GRAIN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x79BE },
+ unicodeslot=0x2F72,
+ },
+ [0x2F73]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CAVE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7A74 },
+ unicodeslot=0x2F73,
+ },
+ [0x2F74]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STAND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7ACB },
+ unicodeslot=0x2F74,
+ },
+ [0x2F75]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BAMBOO",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7AF9 },
+ unicodeslot=0x2F75,
+ },
+ [0x2F76]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RICE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7C73 },
+ unicodeslot=0x2F76,
+ },
+ [0x2F77]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SILK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7CF8 },
+ unicodeslot=0x2F77,
+ },
+ [0x2F78]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL JAR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7F36 },
+ unicodeslot=0x2F78,
+ },
+ [0x2F79]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL NET",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7F51 },
+ unicodeslot=0x2F79,
+ },
+ [0x2F7A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SHEEP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7F8A },
+ unicodeslot=0x2F7A,
+ },
+ [0x2F7B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FEATHER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x7FBD },
+ unicodeslot=0x2F7B,
+ },
+ [0x2F7C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL OLD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8001 },
+ unicodeslot=0x2F7C,
+ },
+ [0x2F7D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL AND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x800C },
+ unicodeslot=0x2F7D,
+ },
+ [0x2F7E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL PLOW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8012 },
+ unicodeslot=0x2F7E,
+ },
+ [0x2F7F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EAR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8033 },
+ unicodeslot=0x2F7F,
+ },
+ [0x2F80]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BRUSH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x807F },
+ unicodeslot=0x2F80,
+ },
+ [0x2F81]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MEAT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8089 },
+ unicodeslot=0x2F81,
+ },
+ [0x2F82]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MINISTER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x81E3 },
+ unicodeslot=0x2F82,
+ },
+ [0x2F83]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SELF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x81EA },
+ unicodeslot=0x2F83,
+ },
+ [0x2F84]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL ARRIVE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x81F3 },
+ unicodeslot=0x2F84,
+ },
+ [0x2F85]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MORTAR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x81FC },
+ unicodeslot=0x2F85,
+ },
+ [0x2F86]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TONGUE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x820C },
+ unicodeslot=0x2F86,
+ },
+ [0x2F87]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL OPPOSE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x821B },
+ unicodeslot=0x2F87,
+ },
+ [0x2F88]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BOAT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x821F },
+ unicodeslot=0x2F88,
+ },
+ [0x2F89]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL STOPPING",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x826E },
+ unicodeslot=0x2F89,
+ },
+ [0x2F8A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL COLOR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8272 },
+ unicodeslot=0x2F8A,
+ },
+ [0x2F8B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GRASS",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8278 },
+ unicodeslot=0x2F8B,
+ },
+ [0x2F8C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TIGER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x864D },
+ unicodeslot=0x2F8C,
+ },
+ [0x2F8D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL INSECT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x866B },
+ unicodeslot=0x2F8D,
+ },
+ [0x2F8E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BLOOD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8840 },
+ unicodeslot=0x2F8E,
+ },
+ [0x2F8F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WALK ENCLOSURE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x884C },
+ unicodeslot=0x2F8F,
+ },
+ [0x2F90]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CLOTHES",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8863 },
+ unicodeslot=0x2F90,
+ },
+ [0x2F91]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WEST",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x897E },
+ unicodeslot=0x2F91,
+ },
+ [0x2F92]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SEE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x898B },
+ unicodeslot=0x2F92,
+ },
+ [0x2F93]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HORN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x89D2 },
+ unicodeslot=0x2F93,
+ },
+ [0x2F94]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SPEECH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8A00 },
+ unicodeslot=0x2F94,
+ },
+ [0x2F95]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL VALLEY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8C37 },
+ unicodeslot=0x2F95,
+ },
+ [0x2F96]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BEAN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8C46 },
+ unicodeslot=0x2F96,
+ },
+ [0x2F97]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL PIG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8C55 },
+ unicodeslot=0x2F97,
+ },
+ [0x2F98]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BADGER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8C78 },
+ unicodeslot=0x2F98,
+ },
+ [0x2F99]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SHELL",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8C9D },
+ unicodeslot=0x2F99,
+ },
+ [0x2F9A]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RED",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8D64 },
+ unicodeslot=0x2F9A,
+ },
+ [0x2F9B]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RUN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8D70 },
+ unicodeslot=0x2F9B,
+ },
+ [0x2F9C]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FOOT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8DB3 },
+ unicodeslot=0x2F9C,
+ },
+ [0x2F9D]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BODY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8EAB },
+ unicodeslot=0x2F9D,
+ },
+ [0x2F9E]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CART",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8ECA },
+ unicodeslot=0x2F9E,
+ },
+ [0x2F9F]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BITTER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8F9B },
+ unicodeslot=0x2F9F,
+ },
+ [0x2FA0]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MORNING",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8FB0 },
+ unicodeslot=0x2FA0,
+ },
+ [0x2FA1]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WALK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x8FB5 },
+ unicodeslot=0x2FA1,
+ },
+ [0x2FA2]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CITY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9091 },
+ unicodeslot=0x2FA2,
+ },
+ [0x2FA3]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9149 },
+ unicodeslot=0x2FA3,
+ },
+ [0x2FA4]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DISTINGUISH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x91C6 },
+ unicodeslot=0x2FA4,
+ },
+ [0x2FA5]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL VILLAGE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x91CC },
+ unicodeslot=0x2FA5,
+ },
+ [0x2FA6]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GOLD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x91D1 },
+ unicodeslot=0x2FA6,
+ },
+ [0x2FA7]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LONG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9577 },
+ unicodeslot=0x2FA7,
+ },
+ [0x2FA8]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GATE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9580 },
+ unicodeslot=0x2FA8,
+ },
+ [0x2FA9]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MOUND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x961C },
+ unicodeslot=0x2FA9,
+ },
+ [0x2FAA]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SLAVE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x96B6 },
+ unicodeslot=0x2FAA,
+ },
+ [0x2FAB]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SHORT TAILED BIRD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x96B9 },
+ unicodeslot=0x2FAB,
+ },
+ [0x2FAC]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RAIN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x96E8 },
+ unicodeslot=0x2FAC,
+ },
+ [0x2FAD]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BLUE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9751 },
+ unicodeslot=0x2FAD,
+ },
+ [0x2FAE]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WRONG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x975E },
+ unicodeslot=0x2FAE,
+ },
+ [0x2FAF]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FACE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9762 },
+ unicodeslot=0x2FAF,
+ },
+ [0x2FB0]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LEATHER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9769 },
+ unicodeslot=0x2FB0,
+ },
+ [0x2FB1]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TANNED LEATHER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x97CB },
+ unicodeslot=0x2FB1,
+ },
+ [0x2FB2]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LEEK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x97ED },
+ unicodeslot=0x2FB2,
+ },
+ [0x2FB3]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SOUND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x97F3 },
+ unicodeslot=0x2FB3,
+ },
+ [0x2FB4]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL LEAF",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9801 },
+ unicodeslot=0x2FB4,
+ },
+ [0x2FB5]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WIND",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x98A8 },
+ unicodeslot=0x2FB5,
+ },
+ [0x2FB6]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FLY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x98DB },
+ unicodeslot=0x2FB6,
+ },
+ [0x2FB7]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EAT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x98DF },
+ unicodeslot=0x2FB7,
+ },
+ [0x2FB8]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HEAD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9996 },
+ unicodeslot=0x2FB8,
+ },
+ [0x2FB9]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FRAGRANT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9999 },
+ unicodeslot=0x2FB9,
+ },
+ [0x2FBA]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HORSE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x99AC },
+ unicodeslot=0x2FBA,
+ },
+ [0x2FBB]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BONE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9AA8 },
+ unicodeslot=0x2FBB,
+ },
+ [0x2FBC]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TALL",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9AD8 },
+ unicodeslot=0x2FBC,
+ },
+ [0x2FBD]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HAIR",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9ADF },
+ unicodeslot=0x2FBD,
+ },
+ [0x2FBE]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FIGHT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9B25 },
+ unicodeslot=0x2FBE,
+ },
+ [0x2FBF]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SACRIFICIAL WINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9B2F },
+ unicodeslot=0x2FBF,
+ },
+ [0x2FC0]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL CAULDRON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9B32 },
+ unicodeslot=0x2FC0,
+ },
+ [0x2FC1]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL GHOST",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9B3C },
+ unicodeslot=0x2FC1,
+ },
+ [0x2FC2]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FISH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9B5A },
+ unicodeslot=0x2FC2,
+ },
+ [0x2FC3]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BIRD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9CE5 },
+ unicodeslot=0x2FC3,
+ },
+ [0x2FC4]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL SALT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9E75 },
+ unicodeslot=0x2FC4,
+ },
+ [0x2FC5]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DEER",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9E7F },
+ unicodeslot=0x2FC5,
+ },
+ [0x2FC6]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL WHEAT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9EA5 },
+ unicodeslot=0x2FC6,
+ },
+ [0x2FC7]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL HEMP",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9EBB },
+ unicodeslot=0x2FC7,
+ },
+ [0x2FC8]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL YELLOW",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9EC3 },
+ unicodeslot=0x2FC8,
+ },
+ [0x2FC9]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL MILLET",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9ECD },
+ unicodeslot=0x2FC9,
+ },
+ [0x2FCA]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL BLACK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9ED1 },
+ unicodeslot=0x2FCA,
+ },
+ [0x2FCB]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EMBROIDERY",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9EF9 },
+ unicodeslot=0x2FCB,
+ },
+ [0x2FCC]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FROG",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9EFD },
+ unicodeslot=0x2FCC,
+ },
+ [0x2FCD]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TRIPOD",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F0E },
+ unicodeslot=0x2FCD,
+ },
+ [0x2FCE]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DRUM",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F13 },
+ unicodeslot=0x2FCE,
+ },
+ [0x2FCF]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL RAT",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F20 },
+ unicodeslot=0x2FCF,
+ },
+ [0x2FD0]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL NOSE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F3B },
+ unicodeslot=0x2FD0,
+ },
+ [0x2FD1]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL EVEN",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F4A },
+ unicodeslot=0x2FD1,
+ },
+ [0x2FD2]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TOOTH",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F52 },
+ unicodeslot=0x2FD2,
+ },
+ [0x2FD3]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL DRAGON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F8D },
+ unicodeslot=0x2FD3,
+ },
+ [0x2FD4]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL TURTLE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9F9C },
+ unicodeslot=0x2FD4,
+ },
+ [0x2FD5]={
+ category="so",
+ cjkwd="w",
+ description="KANGXI RADICAL FLUTE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x9FA0 },
+ unicodeslot=0x2FD5,
+ },
+ [0x2FF0]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF0,
+ },
+ [0x2FF1]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF1,
+ },
+ [0x2FF2]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF2,
+ },
+ [0x2FF3]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF3,
+ },
+ [0x2FF4]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF4,
+ },
+ [0x2FF5]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF5,
+ },
+ [0x2FF6]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF6,
+ },
+ [0x2FF7]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF7,
+ },
+ [0x2FF8]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF8,
+ },
+ [0x2FF9]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FF9,
+ },
+ [0x2FFA]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FFA,
+ },
+ [0x2FFB]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x2FFB,
+ },
+ [0x3000]={
+ adobename="ideographicspace",
+ category="zs",
+ cjkwd="f",
+ contextname="ideographicspace",
+ description="IDEOGRAPHIC SPACE",
+ direction="ws",
+ linebreak="ba",
+ specials={ "wide", 0x20 },
+ unicodeslot=0x3000,
+ },
+ [0x3001]={
+ adobename="ideographiccomma",
+ category="po",
+ cjkwd="w",
+ description="IDEOGRAPHIC COMMA",
+ direction="on",
+ linebreak="cl",
+ unicodeslot=0x3001,
+ },
+ [0x3002]={
+ adobename="ideographicperiod",
+ category="po",
+ cjkwd="w",
+ description="IDEOGRAPHIC FULL STOP",
+ direction="on",
+ linebreak="cl",
+ unicodeslot=0x3002,
+ },
+ [0x3003]={
+ adobename="dittomark",
+ category="po",
+ cjkwd="w",
+ description="DITTO MARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3003,
+ },
+ [0x3004]={
+ adobename="jis",
+ category="so",
+ cjkwd="w",
+ description="JAPANESE INDUSTRIAL STANDARD SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3004,
+ },
+ [0x3005]={
+ adobename="ideographiciterationmark",
+ category="lm",
+ cjkwd="w",
+ description="IDEOGRAPHIC ITERATION MARK",
+ direction="l",
+ linebreak="ns",
+ unicodeslot=0x3005,
+ },
+ [0x3006]={
+ adobename="ideographicclose",
+ category="lo",
+ cjkwd="w",
+ description="IDEOGRAPHIC CLOSING MARK",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3006,
+ },
+ [0x3007]={
+ adobename="ideographiczero",
+ category="nl",
+ cjkwd="w",
+ description="IDEOGRAPHIC NUMBER ZERO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3007,
+ },
+ [0x3008]={
+ adobename="anglebracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x3009,
+ unicodeslot=0x3008,
+ },
+ [0x3009]={
+ adobename="anglebracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x3008,
+ unicodeslot=0x3009,
+ },
+ [0x300A]={
+ adobename="dblanglebracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x300B,
+ unicodeslot=0x300A,
+ },
+ [0x300B]={
+ adobename="dblanglebracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x300A,
+ unicodeslot=0x300B,
+ },
+ [0x300C]={
+ adobename="cornerbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT CORNER BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x300D,
+ unicodeslot=0x300C,
+ },
+ [0x300D]={
+ adobename="cornerbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT CORNER BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x300C,
+ unicodeslot=0x300D,
+ },
+ [0x300E]={
+ adobename="whitecornerbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT WHITE CORNER BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x300F,
+ unicodeslot=0x300E,
+ },
+ [0x300F]={
+ adobename="whitecornerbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT WHITE CORNER BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x300E,
+ unicodeslot=0x300F,
+ },
+ [0x3010]={
+ adobename="blacklenticularbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT BLACK LENTICULAR BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x3011,
+ unicodeslot=0x3010,
+ },
+ [0x3011]={
+ adobename="blacklenticularbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT BLACK LENTICULAR BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x3010,
+ unicodeslot=0x3011,
+ },
+ [0x3012]={
+ adobename="postalmark",
+ category="so",
+ cjkwd="w",
+ description="POSTAL MARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3012,
+ },
+ [0x3013]={
+ adobename="getamark",
+ category="so",
+ cjkwd="w",
+ description="GETA MARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3013,
+ },
+ [0x3014]={
+ adobename="tortoiseshellbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x3015,
+ unicodeslot=0x3014,
+ },
+ [0x3015]={
+ adobename="tortoiseshellbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x3014,
+ unicodeslot=0x3015,
+ },
+ [0x3016]={
+ adobename="whitelenticularbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT WHITE LENTICULAR BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x3017,
+ unicodeslot=0x3016,
+ },
+ [0x3017]={
+ adobename="whitelenticularbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT WHITE LENTICULAR BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x3016,
+ unicodeslot=0x3017,
+ },
+ [0x3018]={
+ adobename="whitetortoiseshellbracketleft",
+ category="ps",
+ cjkwd="w",
+ description="LEFT WHITE TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x3019,
+ unicodeslot=0x3018,
+ },
+ [0x3019]={
+ adobename="whitetortoiseshellbracketright",
+ category="pe",
+ cjkwd="w",
+ description="RIGHT WHITE TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x3018,
+ unicodeslot=0x3019,
+ },
+ [0x301A]={
+ category="ps",
+ cjkwd="w",
+ description="LEFT WHITE SQUARE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x301B,
+ unicodeslot=0x301A,
+ },
+ [0x301B]={
+ category="pe",
+ cjkwd="w",
+ description="RIGHT WHITE SQUARE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x301A,
+ unicodeslot=0x301B,
+ },
+ [0x301C]={
+ adobename="wavedash",
+ category="pd",
+ cjkwd="w",
+ description="WAVE DASH",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x301C,
+ },
+ [0x301D]={
+ adobename="quotedblprimereversed",
+ category="ps",
+ cjkwd="w",
+ description="REVERSED DOUBLE PRIME QUOTATION MARK",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x301D,
+ },
+ [0x301E]={
+ adobename="quotedblprime",
+ category="pe",
+ cjkwd="w",
+ description="DOUBLE PRIME QUOTATION MARK",
+ direction="on",
+ linebreak="cl",
+ unicodeslot=0x301E,
+ },
+ [0x301F]={
+ category="pe",
+ cjkwd="w",
+ description="LOW DOUBLE PRIME QUOTATION MARK",
+ direction="on",
+ linebreak="cl",
+ unicodeslot=0x301F,
+ },
+ [0x3020]={
+ adobename="postalmarkface",
+ category="so",
+ cjkwd="w",
+ description="POSTAL MARK FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3020,
+ },
+ [0x3021]={
+ adobename="onehangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL ONE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3021,
+ },
+ [0x3022]={
+ adobename="twohangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL TWO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3022,
+ },
+ [0x3023]={
+ adobename="threehangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL THREE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3023,
+ },
+ [0x3024]={
+ adobename="fourhangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL FOUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3024,
+ },
+ [0x3025]={
+ adobename="fivehangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL FIVE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3025,
+ },
+ [0x3026]={
+ adobename="sixhangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL SIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3026,
+ },
+ [0x3027]={
+ adobename="sevenhangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL SEVEN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3027,
+ },
+ [0x3028]={
+ adobename="eighthangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL EIGHT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3028,
+ },
+ [0x3029]={
+ adobename="ninehangzhou",
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL NINE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3029,
+ },
+ [0x302A]={
+ category="mn",
+ cjkwd="w",
+ combining=0xDA,
+ description="IDEOGRAPHIC LEVEL TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x302A,
+ },
+ [0x302B]={
+ category="mn",
+ cjkwd="w",
+ combining=0xE4,
+ description="IDEOGRAPHIC RISING TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x302B,
+ },
+ [0x302C]={
+ category="mn",
+ cjkwd="w",
+ combining=0xE8,
+ description="IDEOGRAPHIC DEPARTING TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x302C,
+ },
+ [0x302D]={
+ category="mn",
+ cjkwd="w",
+ combining=0xDE,
+ description="IDEOGRAPHIC ENTERING TONE MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x302D,
+ },
+ [0x302E]={
+ category="mn",
+ cjkwd="w",
+ combining=0xE0,
+ description="HANGUL SINGLE DOT TONE MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x302E,
+ },
+ [0x302F]={
+ category="mn",
+ cjkwd="w",
+ combining=0xE0,
+ description="HANGUL DOUBLE DOT TONE MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x302F,
+ },
+ [0x3030]={
+ category="pd",
+ cjkwd="w",
+ description="WAVY DASH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3030,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x3031]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL KANA REPEAT MARK",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3031,
+ },
+ [0x3032]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL KANA REPEAT WITH VOICED SOUND MARK",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3032,
+ },
+ [0x3033]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL KANA REPEAT MARK UPPER HALF",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3033,
+ },
+ [0x3034]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3034,
+ },
+ [0x3035]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL KANA REPEAT MARK LOWER HALF",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x3035,
+ },
+ [0x3036]={
+ adobename="circlepostalmark",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED POSTAL MARK",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x3012 },
+ unicodeslot=0x3036,
+ },
+ [0x3037]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x3037,
+ },
+ [0x3038]={
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL TEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x5341 },
+ unicodeslot=0x3038,
+ },
+ [0x3039]={
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL TWENTY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x5344 },
+ unicodeslot=0x3039,
+ },
+ [0x303A]={
+ category="nl",
+ cjkwd="w",
+ description="HANGZHOU NUMERAL THIRTY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x5345 },
+ unicodeslot=0x303A,
+ },
+ [0x303B]={
+ category="lm",
+ cjkwd="w",
+ description="VERTICAL IDEOGRAPHIC ITERATION MARK",
+ direction="l",
+ linebreak="ns",
+ unicodeslot=0x303B,
+ },
+ [0x303C]={
+ category="lo",
+ cjkwd="w",
+ description="MASU MARK",
+ direction="l",
+ linebreak="ns",
+ unicodeslot=0x303C,
+ },
+ [0x303D]={
+ category="po",
+ cjkwd="w",
+ description="PART ALTERNATION MARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x303D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x303E]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC VARIATION INDICATOR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x303E,
+ },
+ [0x303F]={
+ category="so",
+ contextname="ideographichalffillspace",
+ description="IDEOGRAPHIC HALF FILL SPACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x303F,
+ },
+ [0x3041]={
+ adobename="asmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL A",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3042,
+ sound="unvoiced",
+ unicodeslot=0x3041,
+ },
+ [0x3042]={
+ adobename="ahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER A",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3042,
+ sound="unvoiced",
+ unicodeslot=0x3042,
+ },
+ [0x3043]={
+ adobename="ismallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL I",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3044,
+ sound="unvoiced",
+ unicodeslot=0x3043,
+ },
+ [0x3044]={
+ adobename="ihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER I",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3044,
+ sound="unvoiced",
+ unicodeslot=0x3044,
+ },
+ [0x3045]={
+ adobename="usmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL U",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3046,
+ sound="unvoiced",
+ unicodeslot=0x3045,
+ },
+ [0x3046]={
+ adobename="uhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER U",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3046,
+ sound="unvoiced",
+ unicodeslot=0x3046,
+ },
+ [0x3047]={
+ adobename="esmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL E",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3048,
+ sound="unvoiced",
+ unicodeslot=0x3047,
+ },
+ [0x3048]={
+ adobename="ehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER E",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3048,
+ sound="unvoiced",
+ unicodeslot=0x3048,
+ },
+ [0x3049]={
+ adobename="osmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL O",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x304A,
+ sound="unvoiced",
+ unicodeslot=0x3049,
+ },
+ [0x304A]={
+ adobename="ohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER O",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304A,
+ sound="unvoiced",
+ unicodeslot=0x304A,
+ },
+ [0x304B]={
+ adobename="kahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER KA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304B,
+ sound="unvoiced",
+ unicodeslot=0x304B,
+ },
+ [0x304C]={
+ adobename="gahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER GA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304B,
+ sound="voiced",
+ specials={ "char", 0x304B, 0x3099 },
+ unicodeslot=0x304C,
+ },
+ [0x304D]={
+ adobename="kihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER KI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304D,
+ sound="unvoiced",
+ unicodeslot=0x304D,
+ },
+ [0x304E]={
+ adobename="gihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER GI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304D,
+ sound="voiced",
+ specials={ "char", 0x304D, 0x3099 },
+ unicodeslot=0x304E,
+ },
+ [0x304F]={
+ adobename="kuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER KU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304F,
+ sound="unvoiced",
+ unicodeslot=0x304F,
+ },
+ [0x3050]={
+ adobename="guhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER GU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304F,
+ sound="voiced",
+ specials={ "char", 0x304F, 0x3099 },
+ unicodeslot=0x3050,
+ },
+ [0x3051]={
+ adobename="kehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER KE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3051,
+ sound="unvoiced",
+ unicodeslot=0x3051,
+ },
+ [0x3052]={
+ adobename="gehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER GE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3051,
+ sound="voiced",
+ specials={ "char", 0x3051, 0x3099 },
+ unicodeslot=0x3052,
+ },
+ [0x3053]={
+ adobename="kohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER KO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3053,
+ sound="unvoiced",
+ unicodeslot=0x3053,
+ },
+ [0x3054]={
+ adobename="gohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER GO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3053,
+ sound="voiced",
+ specials={ "char", 0x3053, 0x3099 },
+ unicodeslot=0x3054,
+ },
+ [0x3055]={
+ adobename="sahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3055,
+ sound="unvoiced",
+ unicodeslot=0x3055,
+ },
+ [0x3056]={
+ adobename="zahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ZA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3055,
+ sound="voiced",
+ specials={ "char", 0x3055, 0x3099 },
+ unicodeslot=0x3056,
+ },
+ [0x3057]={
+ adobename="sihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3057,
+ sound="unvoiced",
+ unicodeslot=0x3057,
+ },
+ [0x3058]={
+ adobename="zihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ZI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3057,
+ sound="voiced",
+ specials={ "char", 0x3057, 0x3099 },
+ unicodeslot=0x3058,
+ },
+ [0x3059]={
+ adobename="suhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3059,
+ sound="unvoiced",
+ unicodeslot=0x3059,
+ },
+ [0x305A]={
+ adobename="zuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ZU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3059,
+ sound="voiced",
+ specials={ "char", 0x3059, 0x3099 },
+ unicodeslot=0x305A,
+ },
+ [0x305B]={
+ adobename="sehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305B,
+ sound="unvoiced",
+ unicodeslot=0x305B,
+ },
+ [0x305C]={
+ adobename="zehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ZE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305B,
+ sound="voiced",
+ specials={ "char", 0x305B, 0x3099 },
+ unicodeslot=0x305C,
+ },
+ [0x305D]={
+ adobename="sohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305D,
+ sound="unvoiced",
+ unicodeslot=0x305D,
+ },
+ [0x305E]={
+ adobename="zohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ZO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305D,
+ sound="voiced",
+ specials={ "char", 0x305D, 0x3099 },
+ unicodeslot=0x305E,
+ },
+ [0x305F]={
+ adobename="tahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER TA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305F,
+ sound="unvoiced",
+ unicodeslot=0x305F,
+ },
+ [0x3060]={
+ adobename="dahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER DA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305F,
+ sound="voiced",
+ specials={ "char", 0x305F, 0x3099 },
+ unicodeslot=0x3060,
+ },
+ [0x3061]={
+ adobename="tihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER TI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3061,
+ sound="unvoiced",
+ unicodeslot=0x3061,
+ },
+ [0x3062]={
+ adobename="dihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER DI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3061,
+ sound="voiced",
+ specials={ "char", 0x3061, 0x3099 },
+ unicodeslot=0x3062,
+ },
+ [0x3063]={
+ adobename="tusmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL TU",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3064,
+ sound="unvoiced",
+ unicodeslot=0x3063,
+ },
+ [0x3064]={
+ adobename="tuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER TU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3064,
+ sound="unvoiced",
+ unicodeslot=0x3064,
+ },
+ [0x3065]={
+ adobename="duhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER DU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3064,
+ sound="voiced",
+ specials={ "char", 0x3064, 0x3099 },
+ unicodeslot=0x3065,
+ },
+ [0x3066]={
+ adobename="tehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER TE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3066,
+ sound="unvoiced",
+ unicodeslot=0x3066,
+ },
+ [0x3067]={
+ adobename="dehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER DE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3066,
+ sound="voiced",
+ specials={ "char", 0x3066, 0x3099 },
+ unicodeslot=0x3067,
+ },
+ [0x3068]={
+ adobename="tohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER TO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3068,
+ sound="unvoiced",
+ unicodeslot=0x3068,
+ },
+ [0x3069]={
+ adobename="dohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER DO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3068,
+ sound="voiced",
+ specials={ "char", 0x3068, 0x3099 },
+ unicodeslot=0x3069,
+ },
+ [0x306A]={
+ adobename="nahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER NA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306A,
+ sound="unvoiced",
+ unicodeslot=0x306A,
+ },
+ [0x306B]={
+ adobename="nihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER NI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306B,
+ sound="unvoiced",
+ unicodeslot=0x306B,
+ },
+ [0x306C]={
+ adobename="nuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER NU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306C,
+ sound="unvoiced",
+ unicodeslot=0x306C,
+ },
+ [0x306D]={
+ adobename="nehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER NE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306D,
+ sound="unvoiced",
+ unicodeslot=0x306D,
+ },
+ [0x306E]={
+ adobename="nohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER NO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306E,
+ sound="unvoiced",
+ unicodeslot=0x306E,
+ },
+ [0x306F]={
+ adobename="hahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER HA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="unvoiced",
+ unicodeslot=0x306F,
+ },
+ [0x3070]={
+ adobename="bahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER BA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="voiced",
+ specials={ "char", 0x306F, 0x3099 },
+ unicodeslot=0x3070,
+ },
+ [0x3071]={
+ adobename="pahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER PA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="semivoiced",
+ specials={ "char", 0x306F, 0x309A },
+ unicodeslot=0x3071,
+ },
+ [0x3072]={
+ adobename="hihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER HI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="unvoiced",
+ unicodeslot=0x3072,
+ },
+ [0x3073]={
+ adobename="bihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER BI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="voiced",
+ specials={ "char", 0x3072, 0x3099 },
+ unicodeslot=0x3073,
+ },
+ [0x3074]={
+ adobename="pihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER PI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="semivoiced",
+ specials={ "char", 0x3072, 0x309A },
+ unicodeslot=0x3074,
+ },
+ [0x3075]={
+ adobename="huhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER HU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="unvoiced",
+ unicodeslot=0x3075,
+ },
+ [0x3076]={
+ adobename="buhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER BU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="voiced",
+ specials={ "char", 0x3075, 0x3099 },
+ unicodeslot=0x3076,
+ },
+ [0x3077]={
+ adobename="puhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER PU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="semivoiced",
+ specials={ "char", 0x3075, 0x309A },
+ unicodeslot=0x3077,
+ },
+ [0x3078]={
+ adobename="hehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER HE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="unvoiced",
+ unicodeslot=0x3078,
+ },
+ [0x3079]={
+ adobename="behiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER BE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="voiced",
+ specials={ "char", 0x3078, 0x3099 },
+ unicodeslot=0x3079,
+ },
+ [0x307A]={
+ adobename="pehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER PE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="semivoiced",
+ specials={ "char", 0x3078, 0x309A },
+ unicodeslot=0x307A,
+ },
+ [0x307B]={
+ adobename="hohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER HO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="unvoiced",
+ unicodeslot=0x307B,
+ },
+ [0x307C]={
+ adobename="bohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER BO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="voiced",
+ specials={ "char", 0x307B, 0x3099 },
+ unicodeslot=0x307C,
+ },
+ [0x307D]={
+ adobename="pohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER PO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="semivoiced",
+ specials={ "char", 0x307B, 0x309A },
+ unicodeslot=0x307D,
+ },
+ [0x307E]={
+ adobename="mahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER MA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307E,
+ sound="unvoiced",
+ unicodeslot=0x307E,
+ },
+ [0x307F]={
+ adobename="mihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER MI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307F,
+ sound="unvoiced",
+ unicodeslot=0x307F,
+ },
+ [0x3080]={
+ adobename="muhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER MU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3080,
+ sound="unvoiced",
+ unicodeslot=0x3080,
+ },
+ [0x3081]={
+ adobename="mehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ME",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3081,
+ sound="unvoiced",
+ unicodeslot=0x3081,
+ },
+ [0x3082]={
+ adobename="mohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER MO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3082,
+ sound="unvoiced",
+ unicodeslot=0x3082,
+ },
+ [0x3083]={
+ adobename="yasmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL YA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3084,
+ sound="unvoiced",
+ unicodeslot=0x3083,
+ },
+ [0x3084]={
+ adobename="yahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER YA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3084,
+ sound="unvoiced",
+ unicodeslot=0x3084,
+ },
+ [0x3085]={
+ adobename="yusmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL YU",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3086,
+ sound="unvoiced",
+ unicodeslot=0x3085,
+ },
+ [0x3086]={
+ adobename="yuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER YU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3086,
+ sound="unvoiced",
+ unicodeslot=0x3086,
+ },
+ [0x3087]={
+ adobename="yosmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL YO",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3088,
+ sound="unvoiced",
+ unicodeslot=0x3087,
+ },
+ [0x3088]={
+ adobename="yohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER YO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3088,
+ sound="unvoiced",
+ unicodeslot=0x3088,
+ },
+ [0x3089]={
+ adobename="rahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER RA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3089,
+ sound="unvoiced",
+ unicodeslot=0x3089,
+ },
+ [0x308A]={
+ adobename="rihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER RI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308A,
+ sound="unvoiced",
+ unicodeslot=0x308A,
+ },
+ [0x308B]={
+ adobename="ruhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER RU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308B,
+ sound="unvoiced",
+ unicodeslot=0x308B,
+ },
+ [0x308C]={
+ adobename="rehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER RE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308C,
+ sound="unvoiced",
+ unicodeslot=0x308C,
+ },
+ [0x308D]={
+ adobename="rohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER RO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308D,
+ sound="unvoiced",
+ unicodeslot=0x308D,
+ },
+ [0x308E]={
+ adobename="wasmallhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL WA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x308F,
+ sound="unvoiced",
+ unicodeslot=0x308E,
+ },
+ [0x308F]={
+ adobename="wahiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER WA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308F,
+ sound="unvoiced",
+ unicodeslot=0x308F,
+ },
+ [0x3090]={
+ adobename="wihiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER WI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3090,
+ sound="unvoiced",
+ unicodeslot=0x3090,
+ },
+ [0x3091]={
+ adobename="wehiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER WE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3091,
+ sound="unvoiced",
+ unicodeslot=0x3091,
+ },
+ [0x3092]={
+ adobename="wohiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER WO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3092,
+ sound="unvoiced",
+ unicodeslot=0x3092,
+ },
+ [0x3093]={
+ adobename="nhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER N",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3093,
+ sound="unvoiced",
+ unicodeslot=0x3093,
+ },
+ [0x3094]={
+ adobename="vuhiragana",
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER VU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3046,
+ sound="voiced",
+ specials={ "char", 0x3046, 0x3099 },
+ unicodeslot=0x3094,
+ },
+ [0x3095]={
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL KA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x304B,
+ sound="unvoiced",
+ unicodeslot=0x3095,
+ },
+ [0x3096]={
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER SMALL KE",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3051,
+ sound="unvoiced",
+ unicodeslot=0x3096,
+ },
+ [0x3099]={
+ category="mn",
+ cjkwd="w",
+ combining=0x8,
+ description="COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK",
+ direction="nsm",
+ linebreak="cm",
+ sound="voiced",
+ unicodeslot=0x3099,
+ },
+ [0x309A]={
+ category="mn",
+ cjkwd="w",
+ combining=0x8,
+ description="COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK",
+ direction="nsm",
+ linebreak="cm",
+ sound="semivoiced",
+ unicodeslot=0x309A,
+ },
+ [0x309B]={
+ adobename="voicedmarkkana",
+ category="sk",
+ cjkwd="w",
+ description="KATAKANA-HIRAGANA VOICED SOUND MARK",
+ direction="on",
+ linebreak="ns",
+ sound="voiced",
+ specials={ "compat", 0x20, 0x3099 },
+ unicodeslot=0x309B,
+ },
+ [0x309C]={
+ adobename="semivoicedmarkkana",
+ category="sk",
+ cjkwd="w",
+ description="KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK",
+ direction="on",
+ linebreak="ns",
+ sound="semivoiced",
+ specials={ "compat", 0x20, 0x309A },
+ unicodeslot=0x309C,
+ },
+ [0x309D]={
+ adobename="iterationhiragana",
+ category="lm",
+ cjkwd="w",
+ description="HIRAGANA ITERATION MARK",
+ detail="im",
+ direction="l",
+ linebreak="ns",
+ shcode=0x309D,
+ sound="unvoiced",
+ unicodeslot=0x309D,
+ },
+ [0x309E]={
+ adobename="voicediterationhiragana",
+ category="lm",
+ cjkwd="w",
+ description="HIRAGANA VOICED ITERATION MARK",
+ detail="im",
+ direction="l",
+ linebreak="ns",
+ shcode=0x309D,
+ sound="voiced",
+ specials={ "char", 0x309D, 0x3099 },
+ unicodeslot=0x309E,
+ },
+ [0x309F]={
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA DIGRAPH YORI",
+ direction="l",
+ linebreak="id",
+ specials={ "vertical", 0x3088, 0x308A },
+ unicodeslot=0x309F,
+ },
+ [0x30A0]={
+ category="pd",
+ cjkwd="w",
+ description="KATAKANA-HIRAGANA DOUBLE HYPHEN",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x30A0,
+ },
+ [0x30A1]={
+ adobename="asmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL A",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3042,
+ sound="unvoiced",
+ unicodeslot=0x30A1,
+ },
+ [0x30A2]={
+ adobename="akatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER A",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3042,
+ sound="unvoiced",
+ unicodeslot=0x30A2,
+ },
+ [0x30A3]={
+ adobename="ismallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL I",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3044,
+ sound="unvoiced",
+ unicodeslot=0x30A3,
+ },
+ [0x30A4]={
+ adobename="ikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER I",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3044,
+ sound="unvoiced",
+ unicodeslot=0x30A4,
+ },
+ [0x30A5]={
+ adobename="usmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL U",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3046,
+ sound="unvoiced",
+ unicodeslot=0x30A5,
+ },
+ [0x30A6]={
+ adobename="ukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER U",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3046,
+ sound="unvoiced",
+ unicodeslot=0x30A6,
+ },
+ [0x30A7]={
+ adobename="esmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL E",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3048,
+ sound="unvoiced",
+ unicodeslot=0x30A7,
+ },
+ [0x30A8]={
+ adobename="ekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER E",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3048,
+ sound="unvoiced",
+ unicodeslot=0x30A8,
+ },
+ [0x30A9]={
+ adobename="osmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL O",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x304A,
+ sound="unvoiced",
+ unicodeslot=0x30A9,
+ },
+ [0x30AA]={
+ adobename="okatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER O",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304A,
+ sound="unvoiced",
+ unicodeslot=0x30AA,
+ },
+ [0x30AB]={
+ adobename="kakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER KA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304B,
+ sound="unvoiced",
+ unicodeslot=0x30AB,
+ },
+ [0x30AC]={
+ adobename="gakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER GA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304B,
+ sound="voiced",
+ specials={ "char", 0x30AB, 0x3099 },
+ unicodeslot=0x30AC,
+ },
+ [0x30AD]={
+ adobename="kikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER KI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304D,
+ sound="unvoiced",
+ unicodeslot=0x30AD,
+ },
+ [0x30AE]={
+ adobename="gikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER GI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304D,
+ sound="voiced",
+ specials={ "char", 0x30AD, 0x3099 },
+ unicodeslot=0x30AE,
+ },
+ [0x30AF]={
+ adobename="kukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER KU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304F,
+ sound="unvoiced",
+ unicodeslot=0x30AF,
+ },
+ [0x30B0]={
+ adobename="gukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER GU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x304F,
+ sound="voiced",
+ specials={ "char", 0x30AF, 0x3099 },
+ unicodeslot=0x30B0,
+ },
+ [0x30B1]={
+ adobename="kekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER KE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3051,
+ sound="unvoiced",
+ unicodeslot=0x30B1,
+ },
+ [0x30B2]={
+ adobename="gekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER GE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3051,
+ sound="voiced",
+ specials={ "char", 0x30B1, 0x3099 },
+ unicodeslot=0x30B2,
+ },
+ [0x30B3]={
+ adobename="kokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER KO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3053,
+ sound="unvoiced",
+ unicodeslot=0x30B3,
+ },
+ [0x30B4]={
+ adobename="gokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER GO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3053,
+ sound="voiced",
+ specials={ "char", 0x30B3, 0x3099 },
+ unicodeslot=0x30B4,
+ },
+ [0x30B5]={
+ adobename="sakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3055,
+ sound="unvoiced",
+ unicodeslot=0x30B5,
+ },
+ [0x30B6]={
+ adobename="zakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ZA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3055,
+ sound="voiced",
+ specials={ "char", 0x30B5, 0x3099 },
+ unicodeslot=0x30B6,
+ },
+ [0x30B7]={
+ adobename="sikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3057,
+ sound="unvoiced",
+ unicodeslot=0x30B7,
+ },
+ [0x30B8]={
+ adobename="zikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ZI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3057,
+ sound="voiced",
+ specials={ "char", 0x30B7, 0x3099 },
+ unicodeslot=0x30B8,
+ },
+ [0x30B9]={
+ adobename="sukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3059,
+ sound="unvoiced",
+ unicodeslot=0x30B9,
+ },
+ [0x30BA]={
+ adobename="zukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ZU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3059,
+ sound="voiced",
+ specials={ "char", 0x30B9, 0x3099 },
+ unicodeslot=0x30BA,
+ },
+ [0x30BB]={
+ adobename="sekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305B,
+ sound="unvoiced",
+ unicodeslot=0x30BB,
+ },
+ [0x30BC]={
+ adobename="zekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ZE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305B,
+ sound="voiced",
+ specials={ "char", 0x30BB, 0x3099 },
+ unicodeslot=0x30BC,
+ },
+ [0x30BD]={
+ adobename="sokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305D,
+ sound="unvoiced",
+ unicodeslot=0x30BD,
+ },
+ [0x30BE]={
+ adobename="zokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ZO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305D,
+ sound="voiced",
+ specials={ "char", 0x30BD, 0x3099 },
+ unicodeslot=0x30BE,
+ },
+ [0x30BF]={
+ adobename="takatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER TA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305F,
+ sound="unvoiced",
+ unicodeslot=0x30BF,
+ },
+ [0x30C0]={
+ adobename="dakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER DA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x305F,
+ sound="voiced",
+ specials={ "char", 0x30BF, 0x3099 },
+ unicodeslot=0x30C0,
+ },
+ [0x30C1]={
+ adobename="tikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER TI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3061,
+ sound="unvoiced",
+ unicodeslot=0x30C1,
+ },
+ [0x30C2]={
+ adobename="dikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER DI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3061,
+ sound="voiced",
+ specials={ "char", 0x30C1, 0x3099 },
+ unicodeslot=0x30C2,
+ },
+ [0x30C3]={
+ adobename="tusmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL TU",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3064,
+ sound="unvoiced",
+ unicodeslot=0x30C3,
+ },
+ [0x30C4]={
+ adobename="tukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER TU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3064,
+ sound="unvoiced",
+ unicodeslot=0x30C4,
+ },
+ [0x30C5]={
+ adobename="dukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER DU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3064,
+ sound="voiced",
+ specials={ "char", 0x30C4, 0x3099 },
+ unicodeslot=0x30C5,
+ },
+ [0x30C6]={
+ adobename="tekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER TE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3066,
+ sound="unvoiced",
+ unicodeslot=0x30C6,
+ },
+ [0x30C7]={
+ adobename="dekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER DE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3066,
+ sound="voiced",
+ specials={ "char", 0x30C6, 0x3099 },
+ unicodeslot=0x30C7,
+ },
+ [0x30C8]={
+ adobename="tokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER TO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3068,
+ sound="unvoiced",
+ unicodeslot=0x30C8,
+ },
+ [0x30C9]={
+ adobename="dokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER DO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3068,
+ sound="voiced",
+ specials={ "char", 0x30C8, 0x3099 },
+ unicodeslot=0x30C9,
+ },
+ [0x30CA]={
+ adobename="nakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER NA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306A,
+ sound="unvoiced",
+ unicodeslot=0x30CA,
+ },
+ [0x30CB]={
+ adobename="nikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER NI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306B,
+ sound="unvoiced",
+ unicodeslot=0x30CB,
+ },
+ [0x30CC]={
+ adobename="nukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER NU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306C,
+ sound="unvoiced",
+ unicodeslot=0x30CC,
+ },
+ [0x30CD]={
+ adobename="nekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER NE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306D,
+ sound="unvoiced",
+ unicodeslot=0x30CD,
+ },
+ [0x30CE]={
+ adobename="nokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER NO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306E,
+ sound="unvoiced",
+ unicodeslot=0x30CE,
+ },
+ [0x30CF]={
+ adobename="hakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER HA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="unvoiced",
+ unicodeslot=0x30CF,
+ },
+ [0x30D0]={
+ adobename="bakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER BA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="voiced",
+ specials={ "char", 0x30CF, 0x3099 },
+ unicodeslot=0x30D0,
+ },
+ [0x30D1]={
+ adobename="pakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER PA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x306F,
+ sound="semivoiced",
+ specials={ "char", 0x30CF, 0x309A },
+ unicodeslot=0x30D1,
+ },
+ [0x30D2]={
+ adobename="hikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER HI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="unvoiced",
+ unicodeslot=0x30D2,
+ },
+ [0x30D3]={
+ adobename="bikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER BI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="voiced",
+ specials={ "char", 0x30D2, 0x3099 },
+ unicodeslot=0x30D3,
+ },
+ [0x30D4]={
+ adobename="pikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER PI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3072,
+ sound="semivoiced",
+ specials={ "char", 0x30D2, 0x309A },
+ unicodeslot=0x30D4,
+ },
+ [0x30D5]={
+ adobename="hukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER HU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="unvoiced",
+ unicodeslot=0x30D5,
+ },
+ [0x30D6]={
+ adobename="bukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER BU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="voiced",
+ specials={ "char", 0x30D5, 0x3099 },
+ unicodeslot=0x30D6,
+ },
+ [0x30D7]={
+ adobename="pukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER PU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3075,
+ sound="semivoiced",
+ specials={ "char", 0x30D5, 0x309A },
+ unicodeslot=0x30D7,
+ },
+ [0x30D8]={
+ adobename="hekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER HE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="unvoiced",
+ unicodeslot=0x30D8,
+ },
+ [0x30D9]={
+ adobename="bekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER BE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="voiced",
+ specials={ "char", 0x30D8, 0x3099 },
+ unicodeslot=0x30D9,
+ },
+ [0x30DA]={
+ adobename="pekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER PE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3078,
+ sound="semivoiced",
+ specials={ "char", 0x30D8, 0x309A },
+ unicodeslot=0x30DA,
+ },
+ [0x30DB]={
+ adobename="hokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER HO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="unvoiced",
+ unicodeslot=0x30DB,
+ },
+ [0x30DC]={
+ adobename="bokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER BO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="voiced",
+ specials={ "char", 0x30DB, 0x3099 },
+ unicodeslot=0x30DC,
+ },
+ [0x30DD]={
+ adobename="pokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER PO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307B,
+ sound="semivoiced",
+ specials={ "char", 0x30DB, 0x309A },
+ unicodeslot=0x30DD,
+ },
+ [0x30DE]={
+ adobename="makatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER MA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307E,
+ sound="unvoiced",
+ unicodeslot=0x30DE,
+ },
+ [0x30DF]={
+ adobename="mikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER MI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x307F,
+ sound="unvoiced",
+ unicodeslot=0x30DF,
+ },
+ [0x30E0]={
+ adobename="mukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER MU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3080,
+ sound="unvoiced",
+ unicodeslot=0x30E0,
+ },
+ [0x30E1]={
+ adobename="mekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ME",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3081,
+ sound="unvoiced",
+ unicodeslot=0x30E1,
+ },
+ [0x30E2]={
+ adobename="mokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER MO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3082,
+ sound="unvoiced",
+ unicodeslot=0x30E2,
+ },
+ [0x30E3]={
+ adobename="yasmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL YA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3084,
+ sound="unvoiced",
+ unicodeslot=0x30E3,
+ },
+ [0x30E4]={
+ adobename="yakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER YA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3084,
+ sound="unvoiced",
+ unicodeslot=0x30E4,
+ },
+ [0x30E5]={
+ adobename="yusmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL YU",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3086,
+ sound="unvoiced",
+ unicodeslot=0x30E5,
+ },
+ [0x30E6]={
+ adobename="yukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER YU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3086,
+ sound="unvoiced",
+ unicodeslot=0x30E6,
+ },
+ [0x30E7]={
+ adobename="yosmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL YO",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3088,
+ sound="unvoiced",
+ unicodeslot=0x30E7,
+ },
+ [0x30E8]={
+ adobename="yokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER YO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3088,
+ sound="unvoiced",
+ unicodeslot=0x30E8,
+ },
+ [0x30E9]={
+ adobename="rakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER RA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3089,
+ sound="unvoiced",
+ unicodeslot=0x30E9,
+ },
+ [0x30EA]={
+ adobename="rikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER RI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308A,
+ sound="unvoiced",
+ unicodeslot=0x30EA,
+ },
+ [0x30EB]={
+ adobename="rukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER RU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308B,
+ sound="unvoiced",
+ unicodeslot=0x30EB,
+ },
+ [0x30EC]={
+ adobename="rekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER RE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308C,
+ sound="unvoiced",
+ unicodeslot=0x30EC,
+ },
+ [0x30ED]={
+ adobename="rokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER RO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308D,
+ sound="unvoiced",
+ unicodeslot=0x30ED,
+ },
+ [0x30EE]={
+ adobename="wasmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL WA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x308F,
+ sound="unvoiced",
+ unicodeslot=0x30EE,
+ },
+ [0x30EF]={
+ adobename="wakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER WA",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x308F,
+ sound="unvoiced",
+ unicodeslot=0x30EF,
+ },
+ [0x30F0]={
+ adobename="wikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER WI",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3090,
+ sound="unvoiced",
+ unicodeslot=0x30F0,
+ },
+ [0x30F1]={
+ adobename="wekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER WE",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3091,
+ sound="unvoiced",
+ unicodeslot=0x30F1,
+ },
+ [0x30F2]={
+ adobename="wokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER WO",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3092,
+ sound="unvoiced",
+ unicodeslot=0x30F2,
+ },
+ [0x30F3]={
+ adobename="nkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER N",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3093,
+ sound="unvoiced",
+ unicodeslot=0x30F3,
+ },
+ [0x30F4]={
+ adobename="vukatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER VU",
+ detail="bl",
+ direction="l",
+ linebreak="id",
+ shcode=0x3046,
+ sound="voiced",
+ specials={ "char", 0x30A6, 0x3099 },
+ unicodeslot=0x30F4,
+ },
+ [0x30F5]={
+ adobename="kasmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL KA",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x304B,
+ sound="unvoiced",
+ unicodeslot=0x30F5,
+ },
+ [0x30F6]={
+ adobename="kesmallkatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL KE",
+ detail="sl",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3051,
+ sound="unvoiced",
+ unicodeslot=0x30F6,
+ },
+ [0x30F7]={
+ adobename="vakatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER VA",
+ direction="l",
+ linebreak="id",
+ shcode=0x308F,
+ sound="voiced",
+ specials={ "char", 0x30EF, 0x3099 },
+ unicodeslot=0x30F7,
+ },
+ [0x30F8]={
+ adobename="vikatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER VI",
+ direction="l",
+ linebreak="id",
+ shcode=0x3090,
+ sound="voiced",
+ specials={ "char", 0x30F0, 0x3099 },
+ unicodeslot=0x30F8,
+ },
+ [0x30F9]={
+ adobename="vekatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER VE",
+ direction="l",
+ linebreak="id",
+ shcode=0x3091,
+ sound="voiced",
+ specials={ "char", 0x30F1, 0x3099 },
+ unicodeslot=0x30F9,
+ },
+ [0x30FA]={
+ adobename="vokatakana",
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER VO",
+ direction="l",
+ linebreak="id",
+ shcode=0x3092,
+ sound="voiced",
+ specials={ "char", 0x30F2, 0x3099 },
+ unicodeslot=0x30FA,
+ },
+ [0x30FB]={
+ adobename="dotkatakana",
+ category="po",
+ cjkwd="w",
+ description="KATAKANA MIDDLE DOT",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x30FB,
+ },
+ [0x30FC]={
+ adobename="prolongedkana",
+ category="lm",
+ cjkwd="w",
+ description="KATAKANA-HIRAGANA PROLONGED SOUND MARK",
+ detail="pm",
+ direction="l",
+ linebreak="cj",
+ shcode=0x30FC,
+ sound="unvoiced",
+ unicodeslot=0x30FC,
+ },
+ [0x30FD]={
+ adobename="iterationkatakana",
+ category="lm",
+ cjkwd="w",
+ description="KATAKANA ITERATION MARK",
+ detail="im",
+ direction="l",
+ linebreak="ns",
+ shcode=0x309D,
+ sound="unvoiced",
+ unicodeslot=0x30FD,
+ },
+ [0x30FE]={
+ adobename="voicediterationkatakana",
+ category="lm",
+ cjkwd="w",
+ description="KATAKANA VOICED ITERATION MARK",
+ detail="im",
+ direction="l",
+ linebreak="ns",
+ shcode=0x309D,
+ sound="voiced",
+ specials={ "char", 0x30FD, 0x3099 },
+ unicodeslot=0x30FE,
+ },
+ [0x30FF]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA DIGRAPH KOTO",
+ direction="l",
+ linebreak="id",
+ specials={ "vertical", 0x30B3, 0x30C8 },
+ unicodeslot=0x30FF,
+ },
+ [0x3105]={
+ adobename="bbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER B",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3105,
+ },
+ [0x3106]={
+ adobename="pbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER P",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3106,
+ },
+ [0x3107]={
+ adobename="mbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER M",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3107,
+ },
+ [0x3108]={
+ adobename="fbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER F",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3108,
+ },
+ [0x3109]={
+ adobename="dbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER D",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3109,
+ },
+ [0x310A]={
+ adobename="tbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER T",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310A,
+ },
+ [0x310B]={
+ adobename="nbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER N",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310B,
+ },
+ [0x310C]={
+ adobename="lbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER L",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310C,
+ },
+ [0x310D]={
+ adobename="gbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER G",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310D,
+ },
+ [0x310E]={
+ adobename="kbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER K",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310E,
+ },
+ [0x310F]={
+ adobename="hbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER H",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x310F,
+ },
+ [0x3110]={
+ adobename="jbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER J",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3110,
+ },
+ [0x3111]={
+ adobename="qbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER Q",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3111,
+ },
+ [0x3112]={
+ adobename="xbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER X",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3112,
+ },
+ [0x3113]={
+ adobename="zhbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ZH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3113,
+ },
+ [0x3114]={
+ adobename="chbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER CH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3114,
+ },
+ [0x3115]={
+ adobename="shbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER SH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3115,
+ },
+ [0x3116]={
+ adobename="rbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER R",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3116,
+ },
+ [0x3117]={
+ adobename="zbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER Z",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3117,
+ },
+ [0x3118]={
+ adobename="cbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER C",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3118,
+ },
+ [0x3119]={
+ adobename="sbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER S",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3119,
+ },
+ [0x311A]={
+ adobename="abopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER A",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311A,
+ },
+ [0x311B]={
+ adobename="obopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER O",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311B,
+ },
+ [0x311C]={
+ adobename="ebopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311C,
+ },
+ [0x311D]={
+ adobename="ehbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER EH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311D,
+ },
+ [0x311E]={
+ adobename="aibopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311E,
+ },
+ [0x311F]={
+ adobename="eibopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER EI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x311F,
+ },
+ [0x3120]={
+ adobename="aubopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3120,
+ },
+ [0x3121]={
+ adobename="oubopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER OU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3121,
+ },
+ [0x3122]={
+ adobename="anbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3122,
+ },
+ [0x3123]={
+ adobename="enbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER EN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3123,
+ },
+ [0x3124]={
+ adobename="angbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ANG",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3124,
+ },
+ [0x3125]={
+ adobename="engbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ENG",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3125,
+ },
+ [0x3126]={
+ adobename="erbopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ER",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3126,
+ },
+ [0x3127]={
+ adobename="ibopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER I",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3127,
+ },
+ [0x3128]={
+ adobename="ubopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER U",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3128,
+ },
+ [0x3129]={
+ adobename="iubopomofo",
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER IU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3129,
+ },
+ [0x312A]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER V",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312A,
+ },
+ [0x312B]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER NG",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312B,
+ },
+ [0x312C]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER GN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312C,
+ },
+ [0x312D]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER IH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312D,
+ },
+ [0x3131]={
+ adobename="kiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1100 },
+ unicodeslot=0x3131,
+ },
+ [0x3132]={
+ adobename="ssangkiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGKIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1101 },
+ unicodeslot=0x3132,
+ },
+ [0x3133]={
+ adobename="kiyeoksioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KIYEOK-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11AA },
+ unicodeslot=0x3133,
+ },
+ [0x3134]={
+ adobename="nieunkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1102 },
+ unicodeslot=0x3134,
+ },
+ [0x3135]={
+ adobename="nieuncieuckorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN-CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11AC },
+ unicodeslot=0x3135,
+ },
+ [0x3136]={
+ adobename="nieunhieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN-HIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11AD },
+ unicodeslot=0x3136,
+ },
+ [0x3137]={
+ adobename="tikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1103 },
+ unicodeslot=0x3137,
+ },
+ [0x3138]={
+ adobename="ssangtikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGTIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1104 },
+ unicodeslot=0x3138,
+ },
+ [0x3139]={
+ adobename="rieulkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1105 },
+ unicodeslot=0x3139,
+ },
+ [0x313A]={
+ adobename="rieulkiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B0 },
+ unicodeslot=0x313A,
+ },
+ [0x313B]={
+ adobename="rieulmieumkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-MIEUM",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B1 },
+ unicodeslot=0x313B,
+ },
+ [0x313C]={
+ adobename="rieulpieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B2 },
+ unicodeslot=0x313C,
+ },
+ [0x313D]={
+ adobename="rieulsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B3 },
+ unicodeslot=0x313D,
+ },
+ [0x313E]={
+ adobename="rieulthieuthkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-THIEUTH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B4 },
+ unicodeslot=0x313E,
+ },
+ [0x313F]={
+ adobename="rieulphieuphkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-PHIEUPH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11B5 },
+ unicodeslot=0x313F,
+ },
+ [0x3140]={
+ adobename="rieulhieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-HIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x111A },
+ unicodeslot=0x3140,
+ },
+ [0x3141]={
+ adobename="mieumkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER MIEUM",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1106 },
+ unicodeslot=0x3141,
+ },
+ [0x3142]={
+ adobename="pieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1107 },
+ unicodeslot=0x3142,
+ },
+ [0x3143]={
+ adobename="ssangpieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGPIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1108 },
+ unicodeslot=0x3143,
+ },
+ [0x3144]={
+ adobename="pieupsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1121 },
+ unicodeslot=0x3144,
+ },
+ [0x3145]={
+ adobename="sioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1109 },
+ unicodeslot=0x3145,
+ },
+ [0x3146]={
+ adobename="ssangsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110A },
+ unicodeslot=0x3146,
+ },
+ [0x3147]={
+ adobename="ieungkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER IEUNG",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110B },
+ unicodeslot=0x3147,
+ },
+ [0x3148]={
+ adobename="cieuckorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110C },
+ unicodeslot=0x3148,
+ },
+ [0x3149]={
+ adobename="ssangcieuckorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGCIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110D },
+ unicodeslot=0x3149,
+ },
+ [0x314A]={
+ adobename="chieuchkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER CHIEUCH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110E },
+ unicodeslot=0x314A,
+ },
+ [0x314B]={
+ adobename="khieukhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KHIEUKH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x110F },
+ unicodeslot=0x314B,
+ },
+ [0x314C]={
+ adobename="thieuthkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER THIEUTH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1110 },
+ unicodeslot=0x314C,
+ },
+ [0x314D]={
+ adobename="phieuphkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PHIEUPH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1111 },
+ unicodeslot=0x314D,
+ },
+ [0x314E]={
+ adobename="hieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER HIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1112 },
+ unicodeslot=0x314E,
+ },
+ [0x314F]={
+ adobename="akorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1161 },
+ unicodeslot=0x314F,
+ },
+ [0x3150]={
+ adobename="aekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER AE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1162 },
+ unicodeslot=0x3150,
+ },
+ [0x3151]={
+ adobename="yakorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YA",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1163 },
+ unicodeslot=0x3151,
+ },
+ [0x3152]={
+ adobename="yaekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YAE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1164 },
+ unicodeslot=0x3152,
+ },
+ [0x3153]={
+ adobename="eokorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER EO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1165 },
+ unicodeslot=0x3153,
+ },
+ [0x3154]={
+ adobename="ekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER E",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1166 },
+ unicodeslot=0x3154,
+ },
+ [0x3155]={
+ adobename="yeokorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YEO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1167 },
+ unicodeslot=0x3155,
+ },
+ [0x3156]={
+ adobename="yekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1168 },
+ unicodeslot=0x3156,
+ },
+ [0x3157]={
+ adobename="okorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER O",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1169 },
+ unicodeslot=0x3157,
+ },
+ [0x3158]={
+ adobename="wakorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER WA",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116A },
+ unicodeslot=0x3158,
+ },
+ [0x3159]={
+ adobename="waekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER WAE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116B },
+ unicodeslot=0x3159,
+ },
+ [0x315A]={
+ adobename="oekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER OE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116C },
+ unicodeslot=0x315A,
+ },
+ [0x315B]={
+ adobename="yokorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116D },
+ unicodeslot=0x315B,
+ },
+ [0x315C]={
+ adobename="ukorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER U",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116E },
+ unicodeslot=0x315C,
+ },
+ [0x315D]={
+ adobename="weokorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER WEO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x116F },
+ unicodeslot=0x315D,
+ },
+ [0x315E]={
+ adobename="wekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER WE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1170 },
+ unicodeslot=0x315E,
+ },
+ [0x315F]={
+ adobename="wikorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER WI",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1171 },
+ unicodeslot=0x315F,
+ },
+ [0x3160]={
+ adobename="yukorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YU",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1172 },
+ unicodeslot=0x3160,
+ },
+ [0x3161]={
+ adobename="eukorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER EU",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1173 },
+ unicodeslot=0x3161,
+ },
+ [0x3162]={
+ adobename="yikorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YI",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1174 },
+ unicodeslot=0x3162,
+ },
+ [0x3163]={
+ adobename="ikorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER I",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1175 },
+ unicodeslot=0x3163,
+ },
+ [0x3164]={
+ adobename="hangulfiller",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL FILLER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1160 },
+ unicodeslot=0x3164,
+ },
+ [0x3165]={
+ adobename="ssangnieunkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGNIEUN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1114 },
+ unicodeslot=0x3165,
+ },
+ [0x3166]={
+ adobename="nieuntikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN-TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1115 },
+ unicodeslot=0x3166,
+ },
+ [0x3167]={
+ adobename="nieunsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11C7 },
+ unicodeslot=0x3167,
+ },
+ [0x3168]={
+ adobename="nieunpansioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER NIEUN-PANSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11C8 },
+ unicodeslot=0x3168,
+ },
+ [0x3169]={
+ adobename="rieulkiyeoksioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-KIYEOK-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11CC },
+ unicodeslot=0x3169,
+ },
+ [0x316A]={
+ adobename="rieultikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11CE },
+ unicodeslot=0x316A,
+ },
+ [0x316B]={
+ adobename="rieulpieupsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-PIEUP-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11D3 },
+ unicodeslot=0x316B,
+ },
+ [0x316C]={
+ adobename="rieulpansioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-PANSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11D7 },
+ unicodeslot=0x316C,
+ },
+ [0x316D]={
+ adobename="rieulyeorinhieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER RIEUL-YEORINHIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11D9 },
+ unicodeslot=0x316D,
+ },
+ [0x316E]={
+ adobename="mieumpieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER MIEUM-PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x111C },
+ unicodeslot=0x316E,
+ },
+ [0x316F]={
+ adobename="mieumsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER MIEUM-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11DD },
+ unicodeslot=0x316F,
+ },
+ [0x3170]={
+ adobename="mieumpansioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER MIEUM-PANSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11DF },
+ unicodeslot=0x3170,
+ },
+ [0x3171]={
+ adobename="kapyeounmieumkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KAPYEOUNMIEUM",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x111D },
+ unicodeslot=0x3171,
+ },
+ [0x3172]={
+ adobename="pieupkiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x111E },
+ unicodeslot=0x3172,
+ },
+ [0x3173]={
+ adobename="pieuptikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1120 },
+ unicodeslot=0x3173,
+ },
+ [0x3174]={
+ adobename="pieupsioskiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-SIOS-KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1122 },
+ unicodeslot=0x3174,
+ },
+ [0x3175]={
+ adobename="pieupsiostikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-SIOS-TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1123 },
+ unicodeslot=0x3175,
+ },
+ [0x3176]={
+ adobename="pieupcieuckorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1127 },
+ unicodeslot=0x3176,
+ },
+ [0x3177]={
+ adobename="pieupthieuthkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PIEUP-THIEUTH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1129 },
+ unicodeslot=0x3177,
+ },
+ [0x3178]={
+ adobename="kapyeounpieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x112B },
+ unicodeslot=0x3178,
+ },
+ [0x3179]={
+ adobename="kapyeounssangpieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KAPYEOUNSSANGPIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x112C },
+ unicodeslot=0x3179,
+ },
+ [0x317A]={
+ adobename="sioskiyeokkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS-KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x112D },
+ unicodeslot=0x317A,
+ },
+ [0x317B]={
+ adobename="siosnieunkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS-NIEUN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x112E },
+ unicodeslot=0x317B,
+ },
+ [0x317C]={
+ adobename="siostikeutkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS-TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x112F },
+ unicodeslot=0x317C,
+ },
+ [0x317D]={
+ adobename="siospieupkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS-PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1132 },
+ unicodeslot=0x317D,
+ },
+ [0x317E]={
+ adobename="sioscieuckorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SIOS-CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1136 },
+ unicodeslot=0x317E,
+ },
+ [0x317F]={
+ adobename="pansioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER PANSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1140 },
+ unicodeslot=0x317F,
+ },
+ [0x3180]={
+ adobename="ssangieungkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGIEUNG",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1147 },
+ unicodeslot=0x3180,
+ },
+ [0x3181]={
+ adobename="yesieungkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YESIEUNG",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x114C },
+ unicodeslot=0x3181,
+ },
+ [0x3182]={
+ adobename="yesieungsioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YESIEUNG-SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11F1 },
+ unicodeslot=0x3182,
+ },
+ [0x3183]={
+ adobename="yesieungpansioskorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YESIEUNG-PANSIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11F2 },
+ unicodeslot=0x3183,
+ },
+ [0x3184]={
+ adobename="kapyeounphieuphkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER KAPYEOUNPHIEUPH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1157 },
+ unicodeslot=0x3184,
+ },
+ [0x3185]={
+ adobename="ssanghieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER SSANGHIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1158 },
+ unicodeslot=0x3185,
+ },
+ [0x3186]={
+ adobename="yeorinhieuhkorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YEORINHIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1159 },
+ unicodeslot=0x3186,
+ },
+ [0x3187]={
+ adobename="yoyakorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YO-YA",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1184 },
+ unicodeslot=0x3187,
+ },
+ [0x3188]={
+ adobename="yoyaekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YO-YAE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1185 },
+ unicodeslot=0x3188,
+ },
+ [0x3189]={
+ adobename="yoikorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YO-I",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1188 },
+ unicodeslot=0x3189,
+ },
+ [0x318A]={
+ adobename="yuyeokorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YU-YEO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1191 },
+ unicodeslot=0x318A,
+ },
+ [0x318B]={
+ adobename="yuyekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YU-YE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1192 },
+ unicodeslot=0x318B,
+ },
+ [0x318C]={
+ adobename="yuikorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER YU-I",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x1194 },
+ unicodeslot=0x318C,
+ },
+ [0x318D]={
+ adobename="araeakorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER ARAEA",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x119E },
+ unicodeslot=0x318D,
+ },
+ [0x318E]={
+ adobename="araeaekorean",
+ category="lo",
+ cjkwd="w",
+ description="HANGUL LETTER ARAEAE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x11A1 },
+ unicodeslot=0x318E,
+ },
+ [0x3190]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION LINKING MARK",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3190,
+ },
+ [0x3191]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION REVERSE MARK",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x3191,
+ },
+ [0x3192]={
+ category="no",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION ONE MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E00 },
+ unicodeslot=0x3192,
+ },
+ [0x3193]={
+ category="no",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION TWO MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E8C },
+ unicodeslot=0x3193,
+ },
+ [0x3194]={
+ category="no",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION THREE MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E09 },
+ unicodeslot=0x3194,
+ },
+ [0x3195]={
+ category="no",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION FOUR MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x56DB },
+ unicodeslot=0x3195,
+ },
+ [0x3196]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION TOP MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E0A },
+ unicodeslot=0x3196,
+ },
+ [0x3197]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION MIDDLE MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E2D },
+ unicodeslot=0x3197,
+ },
+ [0x3198]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION BOTTOM MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E0B },
+ unicodeslot=0x3198,
+ },
+ [0x3199]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION FIRST MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x7532 },
+ unicodeslot=0x3199,
+ },
+ [0x319A]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION SECOND MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E59 },
+ unicodeslot=0x319A,
+ },
+ [0x319B]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION THIRD MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E19 },
+ unicodeslot=0x319B,
+ },
+ [0x319C]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION FOURTH MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4E01 },
+ unicodeslot=0x319C,
+ },
+ [0x319D]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION HEAVEN MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x5929 },
+ unicodeslot=0x319D,
+ },
+ [0x319E]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION EARTH MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x5730 },
+ unicodeslot=0x319E,
+ },
+ [0x319F]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC ANNOTATION MAN MARK",
+ direction="l",
+ linebreak="id",
+ specials={ "super", 0x4EBA },
+ unicodeslot=0x319F,
+ },
+ [0x31A0]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER BU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A0,
+ },
+ [0x31A1]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ZI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A1,
+ },
+ [0x31A2]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER JI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A2,
+ },
+ [0x31A3]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER GU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A3,
+ },
+ [0x31A4]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER EE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A4,
+ },
+ [0x31A5]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ENN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A5,
+ },
+ [0x31A6]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER OO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A6,
+ },
+ [0x31A7]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ONN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A7,
+ },
+ [0x31A8]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER IR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A8,
+ },
+ [0x31A9]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ANN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31A9,
+ },
+ [0x31AA]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER INN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AA,
+ },
+ [0x31AB]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER UNN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AB,
+ },
+ [0x31AC]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER IM",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AC,
+ },
+ [0x31AD]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER NGG",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AD,
+ },
+ [0x31AE]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AINN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AE,
+ },
+ [0x31AF]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AUNN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31AF,
+ },
+ [0x31B0]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER AM",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B0,
+ },
+ [0x31B1]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER OM",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B1,
+ },
+ [0x31B2]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ONG",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B2,
+ },
+ [0x31B3]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER INNN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B3,
+ },
+ [0x31B4]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO FINAL LETTER P",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B4,
+ },
+ [0x31B5]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO FINAL LETTER T",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B5,
+ },
+ [0x31B6]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO FINAL LETTER K",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B6,
+ },
+ [0x31B7]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO FINAL LETTER H",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B7,
+ },
+ [0x31B8]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER GH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B8,
+ },
+ [0x31B9]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER LH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B9,
+ },
+ [0x31BA]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ZY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31BA,
+ },
+ [0x31C0]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE T",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C0,
+ },
+ [0x31C1]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE WG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C1,
+ },
+ [0x31C2]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE XG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C2,
+ },
+ [0x31C3]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE BXG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C3,
+ },
+ [0x31C4]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C4,
+ },
+ [0x31C5]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C5,
+ },
+ [0x31C6]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C6,
+ },
+ [0x31C7]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C7,
+ },
+ [0x31C8]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C8,
+ },
+ [0x31C9]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SZWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31C9,
+ },
+ [0x31CA]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CA,
+ },
+ [0x31CB]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZZP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CB,
+ },
+ [0x31CC]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HPWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CC,
+ },
+ [0x31CD]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CD,
+ },
+ [0x31CE]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZZZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CE,
+ },
+ [0x31CF]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE N",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31CF,
+ },
+ [0x31D0]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE H",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D0,
+ },
+ [0x31D1]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE S",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D1,
+ },
+ [0x31D2]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE P",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D2,
+ },
+ [0x31D3]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D3,
+ },
+ [0x31D4]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE D",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D4,
+ },
+ [0x31D5]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D5,
+ },
+ [0x31D6]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D6,
+ },
+ [0x31D7]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D7,
+ },
+ [0x31D8]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SWZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D8,
+ },
+ [0x31D9]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE ST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D9,
+ },
+ [0x31DA]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DA,
+ },
+ [0x31DB]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DB,
+ },
+ [0x31DC]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DC,
+ },
+ [0x31DD]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE TN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DD,
+ },
+ [0x31DE]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SZZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DE,
+ },
+ [0x31DF]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DF,
+ },
+ [0x31E0]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HXWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E0,
+ },
+ [0x31E1]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZZZG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E1,
+ },
+ [0x31E2]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E2,
+ },
+ [0x31E3]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE Q",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E3,
+ },
+ [0x31F0]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL KU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x304F,
+ sound="unvoiced",
+ unicodeslot=0x31F0,
+ },
+ [0x31F1]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL SI",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3057,
+ sound="unvoiced",
+ unicodeslot=0x31F1,
+ },
+ [0x31F2]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL SU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3059,
+ sound="unvoiced",
+ unicodeslot=0x31F2,
+ },
+ [0x31F3]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL TO",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3068,
+ sound="unvoiced",
+ unicodeslot=0x31F3,
+ },
+ [0x31F4]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL NU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x306C,
+ sound="unvoiced",
+ unicodeslot=0x31F4,
+ },
+ [0x31F5]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL HA",
+ direction="l",
+ linebreak="cj",
+ shcode=0x306F,
+ sound="unvoiced",
+ unicodeslot=0x31F5,
+ },
+ [0x31F6]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL HI",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3072,
+ sound="unvoiced",
+ unicodeslot=0x31F6,
+ },
+ [0x31F7]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL HU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3075,
+ sound="unvoiced",
+ unicodeslot=0x31F7,
+ },
+ [0x31F8]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL HE",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3078,
+ sound="unvoiced",
+ unicodeslot=0x31F8,
+ },
+ [0x31F9]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL HO",
+ direction="l",
+ linebreak="cj",
+ shcode=0x307B,
+ sound="unvoiced",
+ unicodeslot=0x31F9,
+ },
+ [0x31FA]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL MU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3080,
+ sound="unvoiced",
+ unicodeslot=0x31FA,
+ },
+ [0x31FB]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL RA",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3089,
+ sound="unvoiced",
+ unicodeslot=0x31FB,
+ },
+ [0x31FC]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL RI",
+ direction="l",
+ linebreak="cj",
+ sound="unvoiced",
+ unicodeslot=0x31FC,
+ },
+ [0x31FD]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL RU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x308B,
+ sound="unvoiced",
+ unicodeslot=0x31FD,
+ },
+ [0x31FE]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL RE",
+ direction="l",
+ linebreak="cj",
+ shcode=0x308C,
+ sound="unvoiced",
+ unicodeslot=0x31FE,
+ },
+ [0x31FF]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER SMALL RO",
+ direction="l",
+ linebreak="cj",
+ shcode=0x308D,
+ sound="unvoiced",
+ unicodeslot=0x31FF,
+ },
+ [0x3200]={
+ adobename="kiyeokparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1100, 0x29 },
+ unicodeslot=0x3200,
+ },
+ [0x3201]={
+ adobename="nieunparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL NIEUN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1102, 0x29 },
+ unicodeslot=0x3201,
+ },
+ [0x3202]={
+ adobename="tikeutparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1103, 0x29 },
+ unicodeslot=0x3202,
+ },
+ [0x3203]={
+ adobename="rieulparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL RIEUL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1105, 0x29 },
+ unicodeslot=0x3203,
+ },
+ [0x3204]={
+ adobename="mieumparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL MIEUM",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1106, 0x29 },
+ unicodeslot=0x3204,
+ },
+ [0x3205]={
+ adobename="pieupparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1107, 0x29 },
+ unicodeslot=0x3205,
+ },
+ [0x3206]={
+ adobename="siosparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1109, 0x29 },
+ unicodeslot=0x3206,
+ },
+ [0x3207]={
+ adobename="ieungparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL IEUNG",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110B, 0x29 },
+ unicodeslot=0x3207,
+ },
+ [0x3208]={
+ adobename="cieucparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110C, 0x29 },
+ unicodeslot=0x3208,
+ },
+ [0x3209]={
+ adobename="chieuchparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL CHIEUCH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110E, 0x29 },
+ unicodeslot=0x3209,
+ },
+ [0x320A]={
+ adobename="khieukhparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL KHIEUKH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110F, 0x29 },
+ unicodeslot=0x320A,
+ },
+ [0x320B]={
+ adobename="thieuthparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL THIEUTH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1110, 0x29 },
+ unicodeslot=0x320B,
+ },
+ [0x320C]={
+ adobename="phieuphparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL PHIEUPH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1111, 0x29 },
+ unicodeslot=0x320C,
+ },
+ [0x320D]={
+ adobename="hieuhparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL HIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1112, 0x29 },
+ unicodeslot=0x320D,
+ },
+ [0x320E]={
+ adobename="kiyeokaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL KIYEOK A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1100, 0x1161, 0x29 },
+ unicodeslot=0x320E,
+ },
+ [0x320F]={
+ adobename="nieunaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL NIEUN A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1102, 0x1161, 0x29 },
+ unicodeslot=0x320F,
+ },
+ [0x3210]={
+ adobename="tikeutaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL TIKEUT A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1103, 0x1161, 0x29 },
+ unicodeslot=0x3210,
+ },
+ [0x3211]={
+ adobename="rieulaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL RIEUL A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1105, 0x1161, 0x29 },
+ unicodeslot=0x3211,
+ },
+ [0x3212]={
+ adobename="mieumaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL MIEUM A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1106, 0x1161, 0x29 },
+ unicodeslot=0x3212,
+ },
+ [0x3213]={
+ adobename="pieupaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL PIEUP A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1107, 0x1161, 0x29 },
+ unicodeslot=0x3213,
+ },
+ [0x3214]={
+ adobename="siosaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL SIOS A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1109, 0x1161, 0x29 },
+ unicodeslot=0x3214,
+ },
+ [0x3215]={
+ adobename="ieungaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL IEUNG A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110B, 0x1161, 0x29 },
+ unicodeslot=0x3215,
+ },
+ [0x3216]={
+ adobename="cieucaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL CIEUC A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110C, 0x1161, 0x29 },
+ unicodeslot=0x3216,
+ },
+ [0x3217]={
+ adobename="chieuchaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL CHIEUCH A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110E, 0x1161, 0x29 },
+ unicodeslot=0x3217,
+ },
+ [0x3218]={
+ adobename="khieukhaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL KHIEUKH A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110F, 0x1161, 0x29 },
+ unicodeslot=0x3218,
+ },
+ [0x3219]={
+ adobename="thieuthaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL THIEUTH A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1110, 0x1161, 0x29 },
+ unicodeslot=0x3219,
+ },
+ [0x321A]={
+ adobename="phieuphaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL PHIEUPH A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1111, 0x1161, 0x29 },
+ unicodeslot=0x321A,
+ },
+ [0x321B]={
+ adobename="hieuhaparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL HIEUH A",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x1112, 0x1161, 0x29 },
+ unicodeslot=0x321B,
+ },
+ [0x321C]={
+ adobename="cieucuparenkorean",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED HANGUL CIEUC U",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110C, 0x116E, 0x29 },
+ unicodeslot=0x321C,
+ },
+ [0x321D]={
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED KOREAN CHARACTER OJEON",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110B, 0x1169, 0x110C, 0x1165, 0x11AB, 0x29 },
+ unicodeslot=0x321D,
+ },
+ [0x321E]={
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED KOREAN CHARACTER O HU",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x110B, 0x1169, 0x1112, 0x116E, 0x29 },
+ unicodeslot=0x321E,
+ },
+ [0x3220]={
+ adobename="oneideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E00, 0x29 },
+ unicodeslot=0x3220,
+ },
+ [0x3221]={
+ adobename="twoideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E8C, 0x29 },
+ unicodeslot=0x3221,
+ },
+ [0x3222]={
+ adobename="threeideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E09, 0x29 },
+ unicodeslot=0x3222,
+ },
+ [0x3223]={
+ adobename="fourideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x56DB, 0x29 },
+ unicodeslot=0x3223,
+ },
+ [0x3224]={
+ adobename="fiveideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH FIVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E94, 0x29 },
+ unicodeslot=0x3224,
+ },
+ [0x3225]={
+ adobename="sixideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SIX",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x516D, 0x29 },
+ unicodeslot=0x3225,
+ },
+ [0x3226]={
+ adobename="sevenideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E03, 0x29 },
+ unicodeslot=0x3226,
+ },
+ [0x3227]={
+ adobename="eightideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH EIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x516B, 0x29 },
+ unicodeslot=0x3227,
+ },
+ [0x3228]={
+ adobename="nineideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH NINE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4E5D, 0x29 },
+ unicodeslot=0x3228,
+ },
+ [0x3229]={
+ adobename="tenideographicparen",
+ category="no",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH TEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x5341, 0x29 },
+ unicodeslot=0x3229,
+ },
+ [0x322A]={
+ adobename="ideographicmoonparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH MOON",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x6708, 0x29 },
+ unicodeslot=0x322A,
+ },
+ [0x322B]={
+ adobename="ideographicfireparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH FIRE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x706B, 0x29 },
+ unicodeslot=0x322B,
+ },
+ [0x322C]={
+ adobename="ideographicwaterparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH WATER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x6C34, 0x29 },
+ unicodeslot=0x322C,
+ },
+ [0x322D]={
+ adobename="ideographicwoodparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH WOOD",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x6728, 0x29 },
+ unicodeslot=0x322D,
+ },
+ [0x322E]={
+ adobename="ideographicmetalparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH METAL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x91D1, 0x29 },
+ unicodeslot=0x322E,
+ },
+ [0x322F]={
+ adobename="ideographicearthparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH EARTH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x571F, 0x29 },
+ unicodeslot=0x322F,
+ },
+ [0x3230]={
+ adobename="ideographicsunparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SUN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x65E5, 0x29 },
+ unicodeslot=0x3230,
+ },
+ [0x3231]={
+ adobename="ideographicstockparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH STOCK",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x682A, 0x29 },
+ unicodeslot=0x3231,
+ },
+ [0x3232]={
+ adobename="ideographichaveparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH HAVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x6709, 0x29 },
+ unicodeslot=0x3232,
+ },
+ [0x3233]={
+ adobename="ideographicsocietyparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SOCIETY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x793E, 0x29 },
+ unicodeslot=0x3233,
+ },
+ [0x3234]={
+ adobename="ideographicnameparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH NAME",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x540D, 0x29 },
+ unicodeslot=0x3234,
+ },
+ [0x3235]={
+ adobename="ideographicspecialparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SPECIAL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x7279, 0x29 },
+ unicodeslot=0x3235,
+ },
+ [0x3236]={
+ adobename="ideographicfinancialparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH FINANCIAL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x8CA1, 0x29 },
+ unicodeslot=0x3236,
+ },
+ [0x3237]={
+ adobename="ideographiccongratulationparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH CONGRATULATION",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x795D, 0x29 },
+ unicodeslot=0x3237,
+ },
+ [0x3238]={
+ adobename="ideographiclaborparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH LABOR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x52B4, 0x29 },
+ unicodeslot=0x3238,
+ },
+ [0x3239]={
+ adobename="ideographicrepresentparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH REPRESENT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4EE3, 0x29 },
+ unicodeslot=0x3239,
+ },
+ [0x323A]={
+ adobename="ideographiccallparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH CALL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x547C, 0x29 },
+ unicodeslot=0x323A,
+ },
+ [0x323B]={
+ adobename="ideographicstudyparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH STUDY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x5B66, 0x29 },
+ unicodeslot=0x323B,
+ },
+ [0x323C]={
+ adobename="ideographicsuperviseparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SUPERVISE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x76E3, 0x29 },
+ unicodeslot=0x323C,
+ },
+ [0x323D]={
+ adobename="ideographicenterpriseparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH ENTERPRISE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4F01, 0x29 },
+ unicodeslot=0x323D,
+ },
+ [0x323E]={
+ adobename="ideographicresourceparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH RESOURCE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x8CC7, 0x29 },
+ unicodeslot=0x323E,
+ },
+ [0x323F]={
+ adobename="ideographicallianceparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH ALLIANCE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x5354, 0x29 },
+ unicodeslot=0x323F,
+ },
+ [0x3240]={
+ adobename="ideographicfestivalparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH FESTIVAL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x796D, 0x29 },
+ unicodeslot=0x3240,
+ },
+ [0x3241]={
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH REST",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x4F11, 0x29 },
+ unicodeslot=0x3241,
+ },
+ [0x3242]={
+ adobename="ideographicselfparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH SELF",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x81EA, 0x29 },
+ unicodeslot=0x3242,
+ },
+ [0x3243]={
+ adobename="ideographicreachparen",
+ category="so",
+ cjkwd="w",
+ description="PARENTHESIZED IDEOGRAPH REACH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x28, 0x81F3, 0x29 },
+ unicodeslot=0x3243,
+ },
+ [0x3244]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH QUESTION",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x554F },
+ unicodeslot=0x3244,
+ },
+ [0x3245]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH KINDERGARTEN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5E7C },
+ unicodeslot=0x3245,
+ },
+ [0x3246]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SCHOOL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6587 },
+ unicodeslot=0x3246,
+ },
+ [0x3247]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH KOTO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x7B8F },
+ unicodeslot=0x3247,
+ },
+ [0x3248]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER TEN ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x3248,
+ },
+ [0x3249]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER TWENTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x3249,
+ },
+ [0x324A]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER THIRTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324A,
+ },
+ [0x324B]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER FORTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324B,
+ },
+ [0x324C]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER FIFTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324C,
+ },
+ [0x324D]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER SIXTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324D,
+ },
+ [0x324E]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER SEVENTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324E,
+ },
+ [0x324F]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER EIGHTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324F,
+ },
+ [0x3250]={
+ category="so",
+ cjkwd="w",
+ description="PARTNERSHIP SIGN",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x50, 0x54, 0x45 },
+ unicodeslot=0x3250,
+ },
+ [0x3251]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY ONE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x31 },
+ unicodeslot=0x3251,
+ },
+ [0x3252]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY TWO",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x32 },
+ unicodeslot=0x3252,
+ },
+ [0x3253]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY THREE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x33 },
+ unicodeslot=0x3253,
+ },
+ [0x3254]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY FOUR",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x34 },
+ unicodeslot=0x3254,
+ },
+ [0x3255]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY FIVE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x35 },
+ unicodeslot=0x3255,
+ },
+ [0x3256]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY SIX",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x36 },
+ unicodeslot=0x3256,
+ },
+ [0x3257]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY SEVEN",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x37 },
+ unicodeslot=0x3257,
+ },
+ [0x3258]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY EIGHT",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x38 },
+ unicodeslot=0x3258,
+ },
+ [0x3259]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER TWENTY NINE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x32, 0x39 },
+ unicodeslot=0x3259,
+ },
+ [0x325A]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x30 },
+ unicodeslot=0x325A,
+ },
+ [0x325B]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY ONE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x31 },
+ unicodeslot=0x325B,
+ },
+ [0x325C]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY TWO",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x32 },
+ unicodeslot=0x325C,
+ },
+ [0x325D]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY THREE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x33 },
+ unicodeslot=0x325D,
+ },
+ [0x325E]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY FOUR",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x34 },
+ unicodeslot=0x325E,
+ },
+ [0x325F]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY FIVE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x35 },
+ unicodeslot=0x325F,
+ },
+ [0x3260]={
+ adobename="kiyeokcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL KIYEOK",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1100 },
+ unicodeslot=0x3260,
+ },
+ [0x3261]={
+ adobename="nieuncirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL NIEUN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1102 },
+ unicodeslot=0x3261,
+ },
+ [0x3262]={
+ adobename="tikeutcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL TIKEUT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1103 },
+ unicodeslot=0x3262,
+ },
+ [0x3263]={
+ adobename="rieulcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL RIEUL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1105 },
+ unicodeslot=0x3263,
+ },
+ [0x3264]={
+ adobename="mieumcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL MIEUM",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1106 },
+ unicodeslot=0x3264,
+ },
+ [0x3265]={
+ adobename="pieupcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL PIEUP",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1107 },
+ unicodeslot=0x3265,
+ },
+ [0x3266]={
+ adobename="sioscirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL SIOS",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1109 },
+ unicodeslot=0x3266,
+ },
+ [0x3267]={
+ adobename="ieungcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL IEUNG",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110B },
+ unicodeslot=0x3267,
+ },
+ [0x3268]={
+ adobename="cieuccirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL CIEUC",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110C },
+ unicodeslot=0x3268,
+ },
+ [0x3269]={
+ adobename="chieuchcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL CHIEUCH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110E },
+ unicodeslot=0x3269,
+ },
+ [0x326A]={
+ adobename="khieukhcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL KHIEUKH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110F },
+ unicodeslot=0x326A,
+ },
+ [0x326B]={
+ adobename="thieuthcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL THIEUTH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1110 },
+ unicodeslot=0x326B,
+ },
+ [0x326C]={
+ adobename="phieuphcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL PHIEUPH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1111 },
+ unicodeslot=0x326C,
+ },
+ [0x326D]={
+ adobename="hieuhcirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL HIEUH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1112 },
+ unicodeslot=0x326D,
+ },
+ [0x326E]={
+ adobename="kiyeokacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL KIYEOK A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1100, 0x1161 },
+ unicodeslot=0x326E,
+ },
+ [0x326F]={
+ adobename="nieunacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL NIEUN A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1102, 0x1161 },
+ unicodeslot=0x326F,
+ },
+ [0x3270]={
+ adobename="tikeutacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL TIKEUT A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1103, 0x1161 },
+ unicodeslot=0x3270,
+ },
+ [0x3271]={
+ adobename="rieulacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL RIEUL A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1105, 0x1161 },
+ unicodeslot=0x3271,
+ },
+ [0x3272]={
+ adobename="mieumacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL MIEUM A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1106, 0x1161 },
+ unicodeslot=0x3272,
+ },
+ [0x3273]={
+ adobename="pieupacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL PIEUP A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1107, 0x1161 },
+ unicodeslot=0x3273,
+ },
+ [0x3274]={
+ adobename="siosacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL SIOS A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1109, 0x1161 },
+ unicodeslot=0x3274,
+ },
+ [0x3275]={
+ adobename="ieungacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL IEUNG A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110B, 0x1161 },
+ unicodeslot=0x3275,
+ },
+ [0x3276]={
+ adobename="cieucacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL CIEUC A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110C, 0x1161 },
+ unicodeslot=0x3276,
+ },
+ [0x3277]={
+ adobename="chieuchacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL CHIEUCH A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110E, 0x1161 },
+ unicodeslot=0x3277,
+ },
+ [0x3278]={
+ adobename="khieukhacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL KHIEUKH A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x110F, 0x1161 },
+ unicodeslot=0x3278,
+ },
+ [0x3279]={
+ adobename="thieuthacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL THIEUTH A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1110, 0x1161 },
+ unicodeslot=0x3279,
+ },
+ [0x327A]={
+ adobename="phieuphacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL PHIEUPH A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1111, 0x1161 },
+ unicodeslot=0x327A,
+ },
+ [0x327B]={
+ adobename="hieuhacirclekorean",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL HIEUH A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x1112, 0x1161 },
+ unicodeslot=0x327B,
+ },
+ [0x327C]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KOREAN CHARACTER CHAMKO",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x110E, 0x1161, 0x11B7, 0x1100, 0x1169 },
+ unicodeslot=0x327C,
+ },
+ [0x327D]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KOREAN CHARACTER JUEUI",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x110C, 0x116E, 0x110B, 0x1174 },
+ unicodeslot=0x327D,
+ },
+ [0x327E]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED HANGUL IEUNG U",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x110B, 0x116E },
+ unicodeslot=0x327E,
+ },
+ [0x327F]={
+ adobename="koreanstandardsymbol",
+ category="so",
+ cjkwd="w",
+ description="KOREAN STANDARD SYMBOL",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x327F,
+ },
+ [0x3280]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E00 },
+ unicodeslot=0x3280,
+ },
+ [0x3281]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E8C },
+ unicodeslot=0x3281,
+ },
+ [0x3282]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E09 },
+ unicodeslot=0x3282,
+ },
+ [0x3283]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x56DB },
+ unicodeslot=0x3283,
+ },
+ [0x3284]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH FIVE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E94 },
+ unicodeslot=0x3284,
+ },
+ [0x3285]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SIX",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x516D },
+ unicodeslot=0x3285,
+ },
+ [0x3286]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E03 },
+ unicodeslot=0x3286,
+ },
+ [0x3287]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH EIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x516B },
+ unicodeslot=0x3287,
+ },
+ [0x3288]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH NINE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E5D },
+ unicodeslot=0x3288,
+ },
+ [0x3289]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH TEN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5341 },
+ unicodeslot=0x3289,
+ },
+ [0x328A]={
+ adobename="ideographmooncircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH MOON",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6708 },
+ unicodeslot=0x328A,
+ },
+ [0x328B]={
+ adobename="ideographfirecircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH FIRE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x706B },
+ unicodeslot=0x328B,
+ },
+ [0x328C]={
+ adobename="ideographwatercircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH WATER",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6C34 },
+ unicodeslot=0x328C,
+ },
+ [0x328D]={
+ adobename="ideographwoodcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH WOOD",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6728 },
+ unicodeslot=0x328D,
+ },
+ [0x328E]={
+ adobename="ideographmetalcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH METAL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x91D1 },
+ unicodeslot=0x328E,
+ },
+ [0x328F]={
+ adobename="ideographearthcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH EARTH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x571F },
+ unicodeslot=0x328F,
+ },
+ [0x3290]={
+ adobename="ideographsuncircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SUN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x65E5 },
+ unicodeslot=0x3290,
+ },
+ [0x3291]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH STOCK",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x682A },
+ unicodeslot=0x3291,
+ },
+ [0x3292]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH HAVE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6709 },
+ unicodeslot=0x3292,
+ },
+ [0x3293]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SOCIETY",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x793E },
+ unicodeslot=0x3293,
+ },
+ [0x3294]={
+ adobename="ideographnamecircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH NAME",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x540D },
+ unicodeslot=0x3294,
+ },
+ [0x3295]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SPECIAL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x7279 },
+ unicodeslot=0x3295,
+ },
+ [0x3296]={
+ adobename="ideographicfinancialcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH FINANCIAL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x8CA1 },
+ unicodeslot=0x3296,
+ },
+ [0x3297]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH CONGRATULATION",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x795D },
+ unicodeslot=0x3297,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x3298]={
+ adobename="ideographiclaborcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH LABOR",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x52B4 },
+ unicodeslot=0x3298,
+ },
+ [0x3299]={
+ adobename="ideographicsecretcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SECRET",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x79D8 },
+ unicodeslot=0x3299,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x329A]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH MALE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x7537 },
+ unicodeslot=0x329A,
+ },
+ [0x329B]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH FEMALE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5973 },
+ unicodeslot=0x329B,
+ },
+ [0x329C]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SUITABLE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x9069 },
+ unicodeslot=0x329C,
+ },
+ [0x329D]={
+ adobename="ideographicexcellentcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH EXCELLENT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x512A },
+ unicodeslot=0x329D,
+ },
+ [0x329E]={
+ adobename="ideographicprintcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH PRINT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5370 },
+ unicodeslot=0x329E,
+ },
+ [0x329F]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ATTENTION",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6CE8 },
+ unicodeslot=0x329F,
+ },
+ [0x32A0]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ITEM",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x9805 },
+ unicodeslot=0x32A0,
+ },
+ [0x32A1]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH REST",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4F11 },
+ unicodeslot=0x32A1,
+ },
+ [0x32A2]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH COPY",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5199 },
+ unicodeslot=0x32A2,
+ },
+ [0x32A3]={
+ adobename="ideographiccorrectcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH CORRECT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6B63 },
+ unicodeslot=0x32A3,
+ },
+ [0x32A4]={
+ adobename="ideographichighcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH HIGH",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E0A },
+ unicodeslot=0x32A4,
+ },
+ [0x32A5]={
+ adobename="ideographiccentrecircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH CENTRE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E2D },
+ unicodeslot=0x32A5,
+ },
+ [0x32A6]={
+ adobename="ideographiclowcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH LOW",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4E0B },
+ unicodeslot=0x32A6,
+ },
+ [0x32A7]={
+ adobename="ideographicleftcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH LEFT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5DE6 },
+ unicodeslot=0x32A7,
+ },
+ [0x32A8]={
+ adobename="ideographicrightcircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH RIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x53F3 },
+ unicodeslot=0x32A8,
+ },
+ [0x32A9]={
+ adobename="ideographicmedicinecircle",
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH MEDICINE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x533B },
+ unicodeslot=0x32A9,
+ },
+ [0x32AA]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH RELIGION",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5B97 },
+ unicodeslot=0x32AA,
+ },
+ [0x32AB]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH STUDY",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5B66 },
+ unicodeslot=0x32AB,
+ },
+ [0x32AC]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SUPERVISE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x76E3 },
+ unicodeslot=0x32AC,
+ },
+ [0x32AD]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ENTERPRISE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x4F01 },
+ unicodeslot=0x32AD,
+ },
+ [0x32AE]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH RESOURCE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x8CC7 },
+ unicodeslot=0x32AE,
+ },
+ [0x32AF]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ALLIANCE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5354 },
+ unicodeslot=0x32AF,
+ },
+ [0x32B0]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH NIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x591C },
+ unicodeslot=0x32B0,
+ },
+ [0x32B1]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY SIX",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x36 },
+ unicodeslot=0x32B1,
+ },
+ [0x32B2]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY SEVEN",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x37 },
+ unicodeslot=0x32B2,
+ },
+ [0x32B3]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY EIGHT",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x38 },
+ unicodeslot=0x32B3,
+ },
+ [0x32B4]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER THIRTY NINE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x33, 0x39 },
+ unicodeslot=0x32B4,
+ },
+ [0x32B5]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x30 },
+ unicodeslot=0x32B5,
+ },
+ [0x32B6]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY ONE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x31 },
+ unicodeslot=0x32B6,
+ },
+ [0x32B7]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY TWO",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x32 },
+ unicodeslot=0x32B7,
+ },
+ [0x32B8]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY THREE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x33 },
+ unicodeslot=0x32B8,
+ },
+ [0x32B9]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY FOUR",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x34 },
+ unicodeslot=0x32B9,
+ },
+ [0x32BA]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY FIVE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x35 },
+ unicodeslot=0x32BA,
+ },
+ [0x32BB]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY SIX",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x36 },
+ unicodeslot=0x32BB,
+ },
+ [0x32BC]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY SEVEN",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x37 },
+ unicodeslot=0x32BC,
+ },
+ [0x32BD]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY EIGHT",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x38 },
+ unicodeslot=0x32BD,
+ },
+ [0x32BE]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FORTY NINE",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x34, 0x39 },
+ unicodeslot=0x32BE,
+ },
+ [0x32BF]={
+ category="no",
+ cjkwd="w",
+ description="CIRCLED NUMBER FIFTY",
+ direction="on",
+ linebreak="id",
+ specials={ "circle", 0x35, 0x30 },
+ unicodeslot=0x32BF,
+ },
+ [0x32C0]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x6708 },
+ unicodeslot=0x32C0,
+ },
+ [0x32C1]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x6708 },
+ unicodeslot=0x32C1,
+ },
+ [0x32C2]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x33, 0x6708 },
+ unicodeslot=0x32C2,
+ },
+ [0x32C3]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x34, 0x6708 },
+ unicodeslot=0x32C3,
+ },
+ [0x32C4]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x35, 0x6708 },
+ unicodeslot=0x32C4,
+ },
+ [0x32C5]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x36, 0x6708 },
+ unicodeslot=0x32C5,
+ },
+ [0x32C6]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x37, 0x6708 },
+ unicodeslot=0x32C6,
+ },
+ [0x32C7]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x38, 0x6708 },
+ unicodeslot=0x32C7,
+ },
+ [0x32C8]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x39, 0x6708 },
+ unicodeslot=0x32C8,
+ },
+ [0x32C9]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x30, 0x6708 },
+ unicodeslot=0x32C9,
+ },
+ [0x32CA]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x31, 0x6708 },
+ unicodeslot=0x32CA,
+ },
+ [0x32CB]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x32, 0x6708 },
+ unicodeslot=0x32CB,
+ },
+ [0x32CC]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HG",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x48, 0x67 },
+ unicodeslot=0x32CC,
+ },
+ [0x32CD]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ERG",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x65, 0x72, 0x67 },
+ unicodeslot=0x32CD,
+ },
+ [0x32CE]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE EV",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x65, 0x56 },
+ unicodeslot=0x32CE,
+ },
+ [0x32CF]={
+ category="so",
+ cjkwd="w",
+ description="LIMITED LIABILITY SIGN",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x4C, 0x54, 0x44 },
+ unicodeslot=0x32CF,
+ },
+ [0x32D0]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA A",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30A2 },
+ unicodeslot=0x32D0,
+ },
+ [0x32D1]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA I",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30A4 },
+ unicodeslot=0x32D1,
+ },
+ [0x32D2]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA U",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30A6 },
+ unicodeslot=0x32D2,
+ },
+ [0x32D3]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA E",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30A8 },
+ unicodeslot=0x32D3,
+ },
+ [0x32D4]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA O",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30AA },
+ unicodeslot=0x32D4,
+ },
+ [0x32D5]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA KA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30AB },
+ unicodeslot=0x32D5,
+ },
+ [0x32D6]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA KI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30AD },
+ unicodeslot=0x32D6,
+ },
+ [0x32D7]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA KU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30AF },
+ unicodeslot=0x32D7,
+ },
+ [0x32D8]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA KE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30B1 },
+ unicodeslot=0x32D8,
+ },
+ [0x32D9]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA KO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30B3 },
+ unicodeslot=0x32D9,
+ },
+ [0x32DA]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA SA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30B5 },
+ unicodeslot=0x32DA,
+ },
+ [0x32DB]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA SI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30B7 },
+ unicodeslot=0x32DB,
+ },
+ [0x32DC]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA SU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30B9 },
+ unicodeslot=0x32DC,
+ },
+ [0x32DD]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA SE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30BB },
+ unicodeslot=0x32DD,
+ },
+ [0x32DE]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA SO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30BD },
+ unicodeslot=0x32DE,
+ },
+ [0x32DF]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA TA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30BF },
+ unicodeslot=0x32DF,
+ },
+ [0x32E0]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA TI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30C1 },
+ unicodeslot=0x32E0,
+ },
+ [0x32E1]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA TU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30C4 },
+ unicodeslot=0x32E1,
+ },
+ [0x32E2]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA TE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30C6 },
+ unicodeslot=0x32E2,
+ },
+ [0x32E3]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA TO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30C8 },
+ unicodeslot=0x32E3,
+ },
+ [0x32E4]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA NA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CA },
+ unicodeslot=0x32E4,
+ },
+ [0x32E5]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA NI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CB },
+ unicodeslot=0x32E5,
+ },
+ [0x32E6]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA NU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CC },
+ unicodeslot=0x32E6,
+ },
+ [0x32E7]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA NE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CD },
+ unicodeslot=0x32E7,
+ },
+ [0x32E8]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA NO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CE },
+ unicodeslot=0x32E8,
+ },
+ [0x32E9]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA HA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30CF },
+ unicodeslot=0x32E9,
+ },
+ [0x32EA]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA HI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30D2 },
+ unicodeslot=0x32EA,
+ },
+ [0x32EB]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA HU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30D5 },
+ unicodeslot=0x32EB,
+ },
+ [0x32EC]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA HE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30D8 },
+ unicodeslot=0x32EC,
+ },
+ [0x32ED]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA HO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30DB },
+ unicodeslot=0x32ED,
+ },
+ [0x32EE]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA MA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30DE },
+ unicodeslot=0x32EE,
+ },
+ [0x32EF]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA MI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30DF },
+ unicodeslot=0x32EF,
+ },
+ [0x32F0]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA MU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E0 },
+ unicodeslot=0x32F0,
+ },
+ [0x32F1]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA ME",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E1 },
+ unicodeslot=0x32F1,
+ },
+ [0x32F2]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA MO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E2 },
+ unicodeslot=0x32F2,
+ },
+ [0x32F3]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA YA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E4 },
+ unicodeslot=0x32F3,
+ },
+ [0x32F4]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA YU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E6 },
+ unicodeslot=0x32F4,
+ },
+ [0x32F5]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA YO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E8 },
+ unicodeslot=0x32F5,
+ },
+ [0x32F6]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA RA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30E9 },
+ unicodeslot=0x32F6,
+ },
+ [0x32F7]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA RI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30EA },
+ unicodeslot=0x32F7,
+ },
+ [0x32F8]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA RU",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30EB },
+ unicodeslot=0x32F8,
+ },
+ [0x32F9]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA RE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30EC },
+ unicodeslot=0x32F9,
+ },
+ [0x32FA]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA RO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30ED },
+ unicodeslot=0x32FA,
+ },
+ [0x32FB]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA WA",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30EF },
+ unicodeslot=0x32FB,
+ },
+ [0x32FC]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA WI",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30F0 },
+ unicodeslot=0x32FC,
+ },
+ [0x32FD]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA WE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30F1 },
+ unicodeslot=0x32FD,
+ },
+ [0x32FE]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED KATAKANA WO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x30F2 },
+ unicodeslot=0x32FE,
+ },
+ [0x3300]={
+ adobename="apaatosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE APAATO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A2, 0x30D1, 0x30FC, 0x30C8 },
+ unicodeslot=0x3300,
+ },
+ [0x3301]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ARUHUA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A2, 0x30EB, 0x30D5, 0x30A1 },
+ unicodeslot=0x3301,
+ },
+ [0x3302]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ANPEA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A2, 0x30F3, 0x30DA, 0x30A2 },
+ unicodeslot=0x3302,
+ },
+ [0x3303]={
+ adobename="aarusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE AARU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A2, 0x30FC, 0x30EB },
+ unicodeslot=0x3303,
+ },
+ [0x3304]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ININGU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A4, 0x30CB, 0x30F3, 0x30B0 },
+ unicodeslot=0x3304,
+ },
+ [0x3305]={
+ adobename="intisquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE INTI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A4, 0x30F3, 0x30C1 },
+ unicodeslot=0x3305,
+ },
+ [0x3306]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE UON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A6, 0x30A9, 0x30F3 },
+ unicodeslot=0x3306,
+ },
+ [0x3307]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ESUKUUDO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9 },
+ unicodeslot=0x3307,
+ },
+ [0x3308]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE EEKAA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30A8, 0x30FC, 0x30AB, 0x30FC },
+ unicodeslot=0x3308,
+ },
+ [0x3309]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE ONSU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AA, 0x30F3, 0x30B9 },
+ unicodeslot=0x3309,
+ },
+ [0x330A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE OOMU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AA, 0x30FC, 0x30E0 },
+ unicodeslot=0x330A,
+ },
+ [0x330B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KAIRI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AB, 0x30A4, 0x30EA },
+ unicodeslot=0x330B,
+ },
+ [0x330C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KARATTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AB, 0x30E9, 0x30C3, 0x30C8 },
+ unicodeslot=0x330C,
+ },
+ [0x330D]={
+ adobename="karoriisquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KARORII",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AB, 0x30ED, 0x30EA, 0x30FC },
+ unicodeslot=0x330D,
+ },
+ [0x330E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GARON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AC, 0x30ED, 0x30F3 },
+ unicodeslot=0x330E,
+ },
+ [0x330F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GANMA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AC, 0x30F3, 0x30DE },
+ unicodeslot=0x330F,
+ },
+ [0x3310]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GIGA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AE, 0x30AC },
+ unicodeslot=0x3310,
+ },
+ [0x3311]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GINII",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AE, 0x30CB, 0x30FC },
+ unicodeslot=0x3311,
+ },
+ [0x3312]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KYURII",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AD, 0x30E5, 0x30EA, 0x30FC },
+ unicodeslot=0x3312,
+ },
+ [0x3313]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GIRUDAA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AE, 0x30EB, 0x30C0, 0x30FC },
+ unicodeslot=0x3313,
+ },
+ [0x3314]={
+ adobename="kirosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KIRO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AD, 0x30ED },
+ unicodeslot=0x3314,
+ },
+ [0x3315]={
+ adobename="kiroguramusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KIROGURAMU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0 },
+ unicodeslot=0x3315,
+ },
+ [0x3316]={
+ adobename="kiromeetorusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KIROMEETORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB },
+ unicodeslot=0x3316,
+ },
+ [0x3317]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KIROWATTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8 },
+ unicodeslot=0x3317,
+ },
+ [0x3318]={
+ adobename="guramusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE GURAMU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B0, 0x30E9, 0x30E0 },
+ unicodeslot=0x3318,
+ },
+ [0x3319]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GURAMUTON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3 },
+ unicodeslot=0x3319,
+ },
+ [0x331A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KURUZEIRO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED },
+ unicodeslot=0x331A,
+ },
+ [0x331B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KUROONE",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30AF, 0x30ED, 0x30FC, 0x30CD },
+ unicodeslot=0x331B,
+ },
+ [0x331C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KEESU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B1, 0x30FC, 0x30B9 },
+ unicodeslot=0x331C,
+ },
+ [0x331D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE KORUNA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B3, 0x30EB, 0x30CA },
+ unicodeslot=0x331D,
+ },
+ [0x331E]={
+ adobename="kooposquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KOOPO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B3, 0x30FC, 0x30DD },
+ unicodeslot=0x331E,
+ },
+ [0x331F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE SAIKURU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B5, 0x30A4, 0x30AF, 0x30EB },
+ unicodeslot=0x331F,
+ },
+ [0x3320]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE SANTIIMU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0 },
+ unicodeslot=0x3320,
+ },
+ [0x3321]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE SIRINGU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B7, 0x30EA, 0x30F3, 0x30B0 },
+ unicodeslot=0x3321,
+ },
+ [0x3322]={
+ adobename="sentisquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE SENTI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30BB, 0x30F3, 0x30C1 },
+ unicodeslot=0x3322,
+ },
+ [0x3323]={
+ adobename="sentosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE SENTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30BB, 0x30F3, 0x30C8 },
+ unicodeslot=0x3323,
+ },
+ [0x3324]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DAASU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C0, 0x30FC, 0x30B9 },
+ unicodeslot=0x3324,
+ },
+ [0x3325]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DESI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C7, 0x30B7 },
+ unicodeslot=0x3325,
+ },
+ [0x3326]={
+ adobename="dorusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE DORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C9, 0x30EB },
+ unicodeslot=0x3326,
+ },
+ [0x3327]={
+ adobename="tonsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE TON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C8, 0x30F3 },
+ unicodeslot=0x3327,
+ },
+ [0x3328]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE NANO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30CA, 0x30CE },
+ unicodeslot=0x3328,
+ },
+ [0x3329]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE NOTTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30CE, 0x30C3, 0x30C8 },
+ unicodeslot=0x3329,
+ },
+ [0x332A]={
+ adobename="haitusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HAITU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30CF, 0x30A4, 0x30C4 },
+ unicodeslot=0x332A,
+ },
+ [0x332B]={
+ adobename="paasentosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PAASENTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8 },
+ unicodeslot=0x332B,
+ },
+ [0x332C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PAATU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D1, 0x30FC, 0x30C4 },
+ unicodeslot=0x332C,
+ },
+ [0x332D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE BAARERU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D0, 0x30FC, 0x30EC, 0x30EB },
+ unicodeslot=0x332D,
+ },
+ [0x332E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PIASUTORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB },
+ unicodeslot=0x332E,
+ },
+ [0x332F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PIKURU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D4, 0x30AF, 0x30EB },
+ unicodeslot=0x332F,
+ },
+ [0x3330]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PIKO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D4, 0x30B3 },
+ unicodeslot=0x3330,
+ },
+ [0x3331]={
+ adobename="birusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE BIRU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D3, 0x30EB },
+ unicodeslot=0x3331,
+ },
+ [0x3332]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HUARADDO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9 },
+ unicodeslot=0x3332,
+ },
+ [0x3333]={
+ adobename="huiitosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HUIITO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D5, 0x30A3, 0x30FC, 0x30C8 },
+ unicodeslot=0x3333,
+ },
+ [0x3334]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE BUSSYERU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB },
+ unicodeslot=0x3334,
+ },
+ [0x3335]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HURAN",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D5, 0x30E9, 0x30F3 },
+ unicodeslot=0x3335,
+ },
+ [0x3336]={
+ adobename="hekutaarusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HEKUTAARU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB },
+ unicodeslot=0x3336,
+ },
+ [0x3337]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PESO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DA, 0x30BD },
+ unicodeslot=0x3337,
+ },
+ [0x3338]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PENIHI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DA, 0x30CB, 0x30D2 },
+ unicodeslot=0x3338,
+ },
+ [0x3339]={
+ adobename="herutusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HERUTU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D8, 0x30EB, 0x30C4 },
+ unicodeslot=0x3339,
+ },
+ [0x333A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PENSU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DA, 0x30F3, 0x30B9 },
+ unicodeslot=0x333A,
+ },
+ [0x333B]={
+ adobename="peezisquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PEEZI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DA, 0x30FC, 0x30B8 },
+ unicodeslot=0x333B,
+ },
+ [0x333C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE BEETA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30D9, 0x30FC, 0x30BF },
+ unicodeslot=0x333C,
+ },
+ [0x333D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE POINTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DD, 0x30A4, 0x30F3, 0x30C8 },
+ unicodeslot=0x333D,
+ },
+ [0x333E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE BORUTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DC, 0x30EB, 0x30C8 },
+ unicodeslot=0x333E,
+ },
+ [0x333F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DB, 0x30F3 },
+ unicodeslot=0x333F,
+ },
+ [0x3340]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PONDO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DD, 0x30F3, 0x30C9 },
+ unicodeslot=0x3340,
+ },
+ [0x3341]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HOORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DB, 0x30FC, 0x30EB },
+ unicodeslot=0x3341,
+ },
+ [0x3342]={
+ adobename="hoonsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HOON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DB, 0x30FC, 0x30F3 },
+ unicodeslot=0x3342,
+ },
+ [0x3343]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MAIKURO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DE, 0x30A4, 0x30AF, 0x30ED },
+ unicodeslot=0x3343,
+ },
+ [0x3344]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MAIRU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DE, 0x30A4, 0x30EB },
+ unicodeslot=0x3344,
+ },
+ [0x3345]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MAHHA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DE, 0x30C3, 0x30CF },
+ unicodeslot=0x3345,
+ },
+ [0x3346]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MARUKU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DE, 0x30EB, 0x30AF },
+ unicodeslot=0x3346,
+ },
+ [0x3347]={
+ adobename="mansyonsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MANSYON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3 },
+ unicodeslot=0x3347,
+ },
+ [0x3348]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MIKURON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DF, 0x30AF, 0x30ED, 0x30F3 },
+ unicodeslot=0x3348,
+ },
+ [0x3349]={
+ adobename="mirisquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MIRI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DF, 0x30EA },
+ unicodeslot=0x3349,
+ },
+ [0x334A]={
+ adobename="miribaarusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MIRIBAARU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB },
+ unicodeslot=0x334A,
+ },
+ [0x334B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MEGA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E1, 0x30AC },
+ unicodeslot=0x334B,
+ },
+ [0x334C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE MEGATON",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E1, 0x30AC, 0x30C8, 0x30F3 },
+ unicodeslot=0x334C,
+ },
+ [0x334D]={
+ adobename="meetorusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MEETORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E1, 0x30FC, 0x30C8, 0x30EB },
+ unicodeslot=0x334D,
+ },
+ [0x334E]={
+ adobename="yaadosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE YAADO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E4, 0x30FC, 0x30C9 },
+ unicodeslot=0x334E,
+ },
+ [0x334F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE YAARU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E4, 0x30FC, 0x30EB },
+ unicodeslot=0x334F,
+ },
+ [0x3350]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE YUAN",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30E6, 0x30A2, 0x30F3 },
+ unicodeslot=0x3350,
+ },
+ [0x3351]={
+ adobename="rittorusquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE RITTORU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EA, 0x30C3, 0x30C8, 0x30EB },
+ unicodeslot=0x3351,
+ },
+ [0x3352]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE RIRA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EA, 0x30E9 },
+ unicodeslot=0x3352,
+ },
+ [0x3353]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE RUPII",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EB, 0x30D4, 0x30FC },
+ unicodeslot=0x3353,
+ },
+ [0x3354]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE RUUBURU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EB, 0x30FC, 0x30D6, 0x30EB },
+ unicodeslot=0x3354,
+ },
+ [0x3355]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE REMU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EC, 0x30E0 },
+ unicodeslot=0x3355,
+ },
+ [0x3356]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE RENTOGEN",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3 },
+ unicodeslot=0x3356,
+ },
+ [0x3357]={
+ adobename="wattosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE WATTO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30EF, 0x30C3, 0x30C8 },
+ unicodeslot=0x3357,
+ },
+ [0x3358]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x30, 0x70B9 },
+ unicodeslot=0x3358,
+ },
+ [0x3359]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x70B9 },
+ unicodeslot=0x3359,
+ },
+ [0x335A]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x70B9 },
+ unicodeslot=0x335A,
+ },
+ [0x335B]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x33, 0x70B9 },
+ unicodeslot=0x335B,
+ },
+ [0x335C]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x34, 0x70B9 },
+ unicodeslot=0x335C,
+ },
+ [0x335D]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x35, 0x70B9 },
+ unicodeslot=0x335D,
+ },
+ [0x335E]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x36, 0x70B9 },
+ unicodeslot=0x335E,
+ },
+ [0x335F]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x37, 0x70B9 },
+ unicodeslot=0x335F,
+ },
+ [0x3360]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x38, 0x70B9 },
+ unicodeslot=0x3360,
+ },
+ [0x3361]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x39, 0x70B9 },
+ unicodeslot=0x3361,
+ },
+ [0x3362]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x30, 0x70B9 },
+ unicodeslot=0x3362,
+ },
+ [0x3363]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x31, 0x70B9 },
+ unicodeslot=0x3363,
+ },
+ [0x3364]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x32, 0x70B9 },
+ unicodeslot=0x3364,
+ },
+ [0x3365]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x33, 0x70B9 },
+ unicodeslot=0x3365,
+ },
+ [0x3366]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x34, 0x70B9 },
+ unicodeslot=0x3366,
+ },
+ [0x3367]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x35, 0x70B9 },
+ unicodeslot=0x3367,
+ },
+ [0x3368]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x36, 0x70B9 },
+ unicodeslot=0x3368,
+ },
+ [0x3369]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x37, 0x70B9 },
+ unicodeslot=0x3369,
+ },
+ [0x336A]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x38, 0x70B9 },
+ unicodeslot=0x336A,
+ },
+ [0x336B]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x39, 0x70B9 },
+ unicodeslot=0x336B,
+ },
+ [0x336C]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x30, 0x70B9 },
+ unicodeslot=0x336C,
+ },
+ [0x336D]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x31, 0x70B9 },
+ unicodeslot=0x336D,
+ },
+ [0x336E]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x32, 0x70B9 },
+ unicodeslot=0x336E,
+ },
+ [0x336F]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x33, 0x70B9 },
+ unicodeslot=0x336F,
+ },
+ [0x3370]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x34, 0x70B9 },
+ unicodeslot=0x3370,
+ },
+ [0x3371]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HPA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x68, 0x50, 0x61 },
+ unicodeslot=0x3371,
+ },
+ [0x3372]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x64, 0x61 },
+ unicodeslot=0x3372,
+ },
+ [0x3373]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE AU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x41, 0x55 },
+ unicodeslot=0x3373,
+ },
+ [0x3374]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE BAR",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x62, 0x61, 0x72 },
+ unicodeslot=0x3374,
+ },
+ [0x3375]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE OV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6F, 0x56 },
+ unicodeslot=0x3375,
+ },
+ [0x3376]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PC",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x63 },
+ unicodeslot=0x3376,
+ },
+ [0x3377]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DM",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x64, 0x6D },
+ unicodeslot=0x3377,
+ },
+ [0x3378]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DM SQUARED",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x64, 0x6D, 0xB2 },
+ unicodeslot=0x3378,
+ },
+ [0x3379]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE DM CUBED",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x64, 0x6D, 0xB3 },
+ unicodeslot=0x3379,
+ },
+ [0x337A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE IU",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x49, 0x55 },
+ unicodeslot=0x337A,
+ },
+ [0x337B]={
+ adobename="heiseierasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE ERA NAME HEISEI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5E73, 0x6210 },
+ unicodeslot=0x337B,
+ },
+ [0x337C]={
+ adobename="syouwaerasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE ERA NAME SYOUWA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x662D, 0x548C },
+ unicodeslot=0x337C,
+ },
+ [0x337D]={
+ adobename="taisyouerasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE ERA NAME TAISYOU",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5927, 0x6B63 },
+ unicodeslot=0x337D,
+ },
+ [0x337E]={
+ adobename="meizierasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE ERA NAME MEIZI",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x660E, 0x6CBB },
+ unicodeslot=0x337E,
+ },
+ [0x337F]={
+ adobename="corporationsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CORPORATION",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x682A, 0x5F0F, 0x4F1A, 0x793E },
+ unicodeslot=0x337F,
+ },
+ [0x3380]={
+ adobename="paampssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PA AMPS",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x41 },
+ unicodeslot=0x3380,
+ },
+ [0x3381]={
+ adobename="nasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x41 },
+ unicodeslot=0x3381,
+ },
+ [0x3382]={
+ adobename="muasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x41 },
+ unicodeslot=0x3382,
+ },
+ [0x3383]={
+ adobename="masquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x41 },
+ unicodeslot=0x3383,
+ },
+ [0x3384]={
+ adobename="kasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x41 },
+ unicodeslot=0x3384,
+ },
+ [0x3385]={
+ adobename="KBsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KB",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4B, 0x42 },
+ unicodeslot=0x3385,
+ },
+ [0x3386]={
+ adobename="MBsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MB",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x42 },
+ unicodeslot=0x3386,
+ },
+ [0x3387]={
+ adobename="GBsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE GB",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x47, 0x42 },
+ unicodeslot=0x3387,
+ },
+ [0x3388]={
+ adobename="calsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CAL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x61, 0x6C },
+ unicodeslot=0x3388,
+ },
+ [0x3389]={
+ adobename="kcalsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KCAL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x63, 0x61, 0x6C },
+ unicodeslot=0x3389,
+ },
+ [0x338A]={
+ adobename="pfsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PF",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x46 },
+ unicodeslot=0x338A,
+ },
+ [0x338B]={
+ adobename="nfsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NF",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x46 },
+ unicodeslot=0x338B,
+ },
+ [0x338C]={
+ adobename="mufsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU F",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x46 },
+ unicodeslot=0x338C,
+ },
+ [0x338D]={
+ adobename="mugsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU G",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x67 },
+ unicodeslot=0x338D,
+ },
+ [0x338E]={
+ adobename="squaremg",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MG",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x67 },
+ unicodeslot=0x338E,
+ },
+ [0x338F]={
+ adobename="squarekg",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KG",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x67 },
+ unicodeslot=0x338F,
+ },
+ [0x3390]={
+ adobename="Hzsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HZ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x48, 0x7A },
+ unicodeslot=0x3390,
+ },
+ [0x3391]={
+ adobename="khzsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KHZ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x48, 0x7A },
+ unicodeslot=0x3391,
+ },
+ [0x3392]={
+ adobename="mhzsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MHZ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x48, 0x7A },
+ unicodeslot=0x3392,
+ },
+ [0x3393]={
+ adobename="ghzsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE GHZ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x47, 0x48, 0x7A },
+ unicodeslot=0x3393,
+ },
+ [0x3394]={
+ adobename="thzsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE THZ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x54, 0x48, 0x7A },
+ unicodeslot=0x3394,
+ },
+ [0x3395]={
+ adobename="mulsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU L",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x2113 },
+ unicodeslot=0x3395,
+ },
+ [0x3396]={
+ adobename="mlsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE ML",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x2113 },
+ unicodeslot=0x3396,
+ },
+ [0x3397]={
+ adobename="dlsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE DL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x64, 0x2113 },
+ unicodeslot=0x3397,
+ },
+ [0x3398]={
+ adobename="klsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x2113 },
+ unicodeslot=0x3398,
+ },
+ [0x3399]={
+ adobename="fmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE FM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x66, 0x6D },
+ unicodeslot=0x3399,
+ },
+ [0x339A]={
+ adobename="nmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x6D },
+ unicodeslot=0x339A,
+ },
+ [0x339B]={
+ adobename="mumsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU M",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x6D },
+ unicodeslot=0x339B,
+ },
+ [0x339C]={
+ adobename="squaremm",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x6D },
+ unicodeslot=0x339C,
+ },
+ [0x339D]={
+ adobename="squarecm",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x6D },
+ unicodeslot=0x339D,
+ },
+ [0x339E]={
+ adobename="squarekm",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x6D },
+ unicodeslot=0x339E,
+ },
+ [0x339F]={
+ adobename="mmsquaredsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MM SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x6D, 0xB2 },
+ unicodeslot=0x339F,
+ },
+ [0x33A0]={
+ adobename="cmsquaredsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CM SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x6D, 0xB2 },
+ unicodeslot=0x33A0,
+ },
+ [0x33A1]={
+ adobename="squaremsquared",
+ category="so",
+ cjkwd="w",
+ description="SQUARE M SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0xB2 },
+ unicodeslot=0x33A1,
+ },
+ [0x33A2]={
+ adobename="kmsquaredsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KM SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x6D, 0xB2 },
+ unicodeslot=0x33A2,
+ },
+ [0x33A3]={
+ adobename="mmcubedsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MM CUBED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x6D, 0xB3 },
+ unicodeslot=0x33A3,
+ },
+ [0x33A4]={
+ adobename="cmcubedsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CM CUBED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x6D, 0xB3 },
+ unicodeslot=0x33A4,
+ },
+ [0x33A5]={
+ adobename="mcubedsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE M CUBED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0xB3 },
+ unicodeslot=0x33A5,
+ },
+ [0x33A6]={
+ adobename="kmcubedsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KM CUBED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x6D, 0xB3 },
+ unicodeslot=0x33A6,
+ },
+ [0x33A7]={
+ adobename="moverssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE M OVER S",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x2215, 0x73 },
+ unicodeslot=0x33A7,
+ },
+ [0x33A8]={
+ adobename="moverssquaredsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE M OVER S SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x2215, 0x73, 0xB2 },
+ unicodeslot=0x33A8,
+ },
+ [0x33A9]={
+ adobename="pasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x50, 0x61 },
+ unicodeslot=0x33A9,
+ },
+ [0x33AA]={
+ adobename="kpasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KPA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x50, 0x61 },
+ unicodeslot=0x33AA,
+ },
+ [0x33AB]={
+ adobename="mpasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MPA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x50, 0x61 },
+ unicodeslot=0x33AB,
+ },
+ [0x33AC]={
+ adobename="gpasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE GPA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x47, 0x50, 0x61 },
+ unicodeslot=0x33AC,
+ },
+ [0x33AD]={
+ adobename="radsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE RAD",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x72, 0x61, 0x64 },
+ unicodeslot=0x33AD,
+ },
+ [0x33AE]={
+ adobename="radoverssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE RAD OVER S",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x72, 0x61, 0x64, 0x2215, 0x73 },
+ unicodeslot=0x33AE,
+ },
+ [0x33AF]={
+ adobename="radoverssquaredsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE RAD OVER S SQUARED",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x72, 0x61, 0x64, 0x2215, 0x73, 0xB2 },
+ unicodeslot=0x33AF,
+ },
+ [0x33B0]={
+ adobename="pssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PS",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x73 },
+ unicodeslot=0x33B0,
+ },
+ [0x33B1]={
+ adobename="nssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NS",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x73 },
+ unicodeslot=0x33B1,
+ },
+ [0x33B2]={
+ adobename="mussquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU S",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x73 },
+ unicodeslot=0x33B2,
+ },
+ [0x33B3]={
+ adobename="mssquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MS",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x73 },
+ unicodeslot=0x33B3,
+ },
+ [0x33B4]={
+ adobename="pvsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x56 },
+ unicodeslot=0x33B4,
+ },
+ [0x33B5]={
+ adobename="nvsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x56 },
+ unicodeslot=0x33B5,
+ },
+ [0x33B6]={
+ adobename="muvsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU V",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x56 },
+ unicodeslot=0x33B6,
+ },
+ [0x33B7]={
+ adobename="mvsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x56 },
+ unicodeslot=0x33B7,
+ },
+ [0x33B8]={
+ adobename="kvsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x56 },
+ unicodeslot=0x33B8,
+ },
+ [0x33B9]={
+ adobename="mvmegasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MV MEGA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x56 },
+ unicodeslot=0x33B9,
+ },
+ [0x33BA]={
+ adobename="pwsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PW",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x57 },
+ unicodeslot=0x33BA,
+ },
+ [0x33BB]={
+ adobename="nwsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE NW",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E, 0x57 },
+ unicodeslot=0x33BB,
+ },
+ [0x33BC]={
+ adobename="muwsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MU W",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x3BC, 0x57 },
+ unicodeslot=0x33BC,
+ },
+ [0x33BD]={
+ adobename="mwsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MW",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x57 },
+ unicodeslot=0x33BD,
+ },
+ [0x33BE]={
+ adobename="kwsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KW",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x57 },
+ unicodeslot=0x33BE,
+ },
+ [0x33BF]={
+ adobename="mwmegasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MW MEGA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x57 },
+ unicodeslot=0x33BF,
+ },
+ [0x33C0]={
+ adobename="kohmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE K OHM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x3A9 },
+ unicodeslot=0x33C0,
+ },
+ [0x33C1]={
+ adobename="mohmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE M OHM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4D, 0x3A9 },
+ unicodeslot=0x33C1,
+ },
+ [0x33C2]={
+ adobename="amsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE AM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x61, 0x2E, 0x6D, 0x2E },
+ unicodeslot=0x33C2,
+ },
+ [0x33C3]={
+ adobename="bqsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE BQ",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x42, 0x71 },
+ unicodeslot=0x33C3,
+ },
+ [0x33C4]={
+ adobename="squarecc",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CC",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x63 },
+ unicodeslot=0x33C4,
+ },
+ [0x33C5]={
+ adobename="cdsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CD",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x63, 0x64 },
+ unicodeslot=0x33C5,
+ },
+ [0x33C6]={
+ adobename="coverkgsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE C OVER KG",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x43, 0x2215, 0x6B, 0x67 },
+ unicodeslot=0x33C6,
+ },
+ [0x33C7]={
+ adobename="cosquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE CO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x43, 0x6F, 0x2E },
+ unicodeslot=0x33C7,
+ },
+ [0x33C8]={
+ adobename="dbsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE DB",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x64, 0x42 },
+ unicodeslot=0x33C8,
+ },
+ [0x33C9]={
+ adobename="gysquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE GY",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x47, 0x79 },
+ unicodeslot=0x33C9,
+ },
+ [0x33CA]={
+ adobename="hasquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x68, 0x61 },
+ unicodeslot=0x33CA,
+ },
+ [0x33CB]={
+ adobename="HPsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE HP",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x48, 0x50 },
+ unicodeslot=0x33CB,
+ },
+ [0x33CC]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE IN",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x69, 0x6E },
+ unicodeslot=0x33CC,
+ },
+ [0x33CD]={
+ adobename="KKsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KK",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4B, 0x4B },
+ unicodeslot=0x33CD,
+ },
+ [0x33CE]={
+ adobename="squarekmcapital",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KM CAPITAL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4B, 0x4D },
+ unicodeslot=0x33CE,
+ },
+ [0x33CF]={
+ adobename="ktsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE KT",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6B, 0x74 },
+ unicodeslot=0x33CF,
+ },
+ [0x33D0]={
+ adobename="lmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE LM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6C, 0x6D },
+ unicodeslot=0x33D0,
+ },
+ [0x33D1]={
+ adobename="squareln",
+ category="so",
+ cjkwd="w",
+ description="SQUARE LN",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6C, 0x6E },
+ unicodeslot=0x33D1,
+ },
+ [0x33D2]={
+ adobename="squarelog",
+ category="so",
+ cjkwd="w",
+ description="SQUARE LOG",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6C, 0x6F, 0x67 },
+ unicodeslot=0x33D2,
+ },
+ [0x33D3]={
+ adobename="lxsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE LX",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6C, 0x78 },
+ unicodeslot=0x33D3,
+ },
+ [0x33D4]={
+ adobename="mbsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MB SMALL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x62 },
+ unicodeslot=0x33D4,
+ },
+ [0x33D5]={
+ adobename="squaremil",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MIL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x69, 0x6C },
+ unicodeslot=0x33D5,
+ },
+ [0x33D6]={
+ adobename="molsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE MOL",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6D, 0x6F, 0x6C },
+ unicodeslot=0x33D6,
+ },
+ [0x33D7]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PH",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x50, 0x48 },
+ unicodeslot=0x33D7,
+ },
+ [0x33D8]={
+ adobename="pmsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE PM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x70, 0x2E, 0x6D, 0x2E },
+ unicodeslot=0x33D8,
+ },
+ [0x33D9]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PPM",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x50, 0x50, 0x4D },
+ unicodeslot=0x33D9,
+ },
+ [0x33DA]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE PR",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x50, 0x52 },
+ unicodeslot=0x33DA,
+ },
+ [0x33DB]={
+ adobename="srsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE SR",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x73, 0x72 },
+ unicodeslot=0x33DB,
+ },
+ [0x33DC]={
+ adobename="svsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE SV",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x53, 0x76 },
+ unicodeslot=0x33DC,
+ },
+ [0x33DD]={
+ adobename="wbsquare",
+ category="so",
+ cjkwd="w",
+ description="SQUARE WB",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x57, 0x62 },
+ unicodeslot=0x33DD,
+ },
+ [0x33DE]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE V OVER M",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x56, 0x2215, 0x6D },
+ unicodeslot=0x33DE,
+ },
+ [0x33DF]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE A OVER M",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x41, 0x2215, 0x6D },
+ unicodeslot=0x33DF,
+ },
+ [0x33E0]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x65E5 },
+ unicodeslot=0x33E0,
+ },
+ [0x33E1]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x65E5 },
+ unicodeslot=0x33E1,
+ },
+ [0x33E2]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x33, 0x65E5 },
+ unicodeslot=0x33E2,
+ },
+ [0x33E3]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x34, 0x65E5 },
+ unicodeslot=0x33E3,
+ },
+ [0x33E4]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x35, 0x65E5 },
+ unicodeslot=0x33E4,
+ },
+ [0x33E5]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x36, 0x65E5 },
+ unicodeslot=0x33E5,
+ },
+ [0x33E6]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x37, 0x65E5 },
+ unicodeslot=0x33E6,
+ },
+ [0x33E7]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x38, 0x65E5 },
+ unicodeslot=0x33E7,
+ },
+ [0x33E8]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x39, 0x65E5 },
+ unicodeslot=0x33E8,
+ },
+ [0x33E9]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x30, 0x65E5 },
+ unicodeslot=0x33E9,
+ },
+ [0x33EA]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x31, 0x65E5 },
+ unicodeslot=0x33EA,
+ },
+ [0x33EB]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x32, 0x65E5 },
+ unicodeslot=0x33EB,
+ },
+ [0x33EC]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x33, 0x65E5 },
+ unicodeslot=0x33EC,
+ },
+ [0x33ED]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x34, 0x65E5 },
+ unicodeslot=0x33ED,
+ },
+ [0x33EE]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x35, 0x65E5 },
+ unicodeslot=0x33EE,
+ },
+ [0x33EF]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x36, 0x65E5 },
+ unicodeslot=0x33EF,
+ },
+ [0x33F0]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x37, 0x65E5 },
+ unicodeslot=0x33F0,
+ },
+ [0x33F1]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x38, 0x65E5 },
+ unicodeslot=0x33F1,
+ },
+ [0x33F2]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x31, 0x39, 0x65E5 },
+ unicodeslot=0x33F2,
+ },
+ [0x33F3]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x30, 0x65E5 },
+ unicodeslot=0x33F3,
+ },
+ [0x33F4]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x31, 0x65E5 },
+ unicodeslot=0x33F4,
+ },
+ [0x33F5]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x32, 0x65E5 },
+ unicodeslot=0x33F5,
+ },
+ [0x33F6]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x33, 0x65E5 },
+ unicodeslot=0x33F6,
+ },
+ [0x33F7]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x34, 0x65E5 },
+ unicodeslot=0x33F7,
+ },
+ [0x33F8]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x35, 0x65E5 },
+ unicodeslot=0x33F8,
+ },
+ [0x33F9]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x36, 0x65E5 },
+ unicodeslot=0x33F9,
+ },
+ [0x33FA]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x37, 0x65E5 },
+ unicodeslot=0x33FA,
+ },
+ [0x33FB]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x38, 0x65E5 },
+ unicodeslot=0x33FB,
+ },
+ [0x33FC]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x32, 0x39, 0x65E5 },
+ unicodeslot=0x33FC,
+ },
+ [0x33FD]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x33, 0x30, 0x65E5 },
+ unicodeslot=0x33FD,
+ },
+ [0x33FE]={
+ category="so",
+ cjkwd="w",
+ description="IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x33, 0x31, 0x65E5 },
+ unicodeslot=0x33FE,
+ },
+ [0x33FF]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE GAL",
+ direction="on",
+ linebreak="id",
+ specials={ "square", 0x67, 0x61, 0x6C },
+ unicodeslot=0x33FF,
+ },
+ [0x4DC0]={
+ category="so",
+ description="HEXAGRAM FOR THE CREATIVE HEAVEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC0,
+ },
+ [0x4DC1]={
+ category="so",
+ description="HEXAGRAM FOR THE RECEPTIVE EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC1,
+ },
+ [0x4DC2]={
+ category="so",
+ description="HEXAGRAM FOR DIFFICULTY AT THE BEGINNING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC2,
+ },
+ [0x4DC3]={
+ category="so",
+ description="HEXAGRAM FOR YOUTHFUL FOLLY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC3,
+ },
+ [0x4DC4]={
+ category="so",
+ description="HEXAGRAM FOR WAITING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC4,
+ },
+ [0x4DC5]={
+ category="so",
+ description="HEXAGRAM FOR CONFLICT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC5,
+ },
+ [0x4DC6]={
+ category="so",
+ description="HEXAGRAM FOR THE ARMY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC6,
+ },
+ [0x4DC7]={
+ category="so",
+ description="HEXAGRAM FOR HOLDING TOGETHER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC7,
+ },
+ [0x4DC8]={
+ category="so",
+ description="HEXAGRAM FOR SMALL TAMING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC8,
+ },
+ [0x4DC9]={
+ category="so",
+ description="HEXAGRAM FOR TREADING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DC9,
+ },
+ [0x4DCA]={
+ category="so",
+ description="HEXAGRAM FOR PEACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCA,
+ },
+ [0x4DCB]={
+ category="so",
+ description="HEXAGRAM FOR STANDSTILL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCB,
+ },
+ [0x4DCC]={
+ category="so",
+ description="HEXAGRAM FOR FELLOWSHIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCC,
+ },
+ [0x4DCD]={
+ category="so",
+ description="HEXAGRAM FOR GREAT POSSESSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCD,
+ },
+ [0x4DCE]={
+ category="so",
+ description="HEXAGRAM FOR MODESTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCE,
+ },
+ [0x4DCF]={
+ category="so",
+ description="HEXAGRAM FOR ENTHUSIASM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DCF,
+ },
+ [0x4DD0]={
+ category="so",
+ description="HEXAGRAM FOR FOLLOWING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD0,
+ },
+ [0x4DD1]={
+ category="so",
+ description="HEXAGRAM FOR WORK ON THE DECAYED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD1,
+ },
+ [0x4DD2]={
+ category="so",
+ description="HEXAGRAM FOR APPROACH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD2,
+ },
+ [0x4DD3]={
+ category="so",
+ description="HEXAGRAM FOR CONTEMPLATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD3,
+ },
+ [0x4DD4]={
+ category="so",
+ description="HEXAGRAM FOR BITING THROUGH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD4,
+ },
+ [0x4DD5]={
+ category="so",
+ description="HEXAGRAM FOR GRACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD5,
+ },
+ [0x4DD6]={
+ category="so",
+ description="HEXAGRAM FOR SPLITTING APART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD6,
+ },
+ [0x4DD7]={
+ category="so",
+ description="HEXAGRAM FOR RETURN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD7,
+ },
+ [0x4DD8]={
+ category="so",
+ description="HEXAGRAM FOR INNOCENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD8,
+ },
+ [0x4DD9]={
+ category="so",
+ description="HEXAGRAM FOR GREAT TAMING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DD9,
+ },
+ [0x4DDA]={
+ category="so",
+ description="HEXAGRAM FOR MOUTH CORNERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDA,
+ },
+ [0x4DDB]={
+ category="so",
+ description="HEXAGRAM FOR GREAT PREPONDERANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDB,
+ },
+ [0x4DDC]={
+ category="so",
+ description="HEXAGRAM FOR THE ABYSMAL WATER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDC,
+ },
+ [0x4DDD]={
+ category="so",
+ description="HEXAGRAM FOR THE CLINGING FIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDD,
+ },
+ [0x4DDE]={
+ category="so",
+ description="HEXAGRAM FOR INFLUENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDE,
+ },
+ [0x4DDF]={
+ category="so",
+ description="HEXAGRAM FOR DURATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DDF,
+ },
+ [0x4DE0]={
+ category="so",
+ description="HEXAGRAM FOR RETREAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE0,
+ },
+ [0x4DE1]={
+ category="so",
+ description="HEXAGRAM FOR GREAT POWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE1,
+ },
+ [0x4DE2]={
+ category="so",
+ description="HEXAGRAM FOR PROGRESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE2,
+ },
+ [0x4DE3]={
+ category="so",
+ description="HEXAGRAM FOR DARKENING OF THE LIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE3,
+ },
+ [0x4DE4]={
+ category="so",
+ description="HEXAGRAM FOR THE FAMILY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE4,
+ },
+ [0x4DE5]={
+ category="so",
+ description="HEXAGRAM FOR OPPOSITION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE5,
+ },
+ [0x4DE6]={
+ category="so",
+ description="HEXAGRAM FOR OBSTRUCTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE6,
+ },
+ [0x4DE7]={
+ category="so",
+ description="HEXAGRAM FOR DELIVERANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE7,
+ },
+ [0x4DE8]={
+ category="so",
+ description="HEXAGRAM FOR DECREASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE8,
+ },
+ [0x4DE9]={
+ category="so",
+ description="HEXAGRAM FOR INCREASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DE9,
+ },
+ [0x4DEA]={
+ category="so",
+ description="HEXAGRAM FOR BREAKTHROUGH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DEA,
+ },
+ [0x4DEB]={
+ category="so",
+ description="HEXAGRAM FOR COMING TO MEET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DEB,
+ },
+ [0x4DEC]={
+ category="so",
+ description="HEXAGRAM FOR GATHERING TOGETHER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DEC,
+ },
+ [0x4DED]={
+ category="so",
+ description="HEXAGRAM FOR PUSHING UPWARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DED,
+ },
+ [0x4DEE]={
+ category="so",
+ description="HEXAGRAM FOR OPPRESSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DEE,
+ },
+ [0x4DEF]={
+ category="so",
+ description="HEXAGRAM FOR THE WELL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DEF,
+ },
+ [0x4DF0]={
+ category="so",
+ description="HEXAGRAM FOR REVOLUTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF0,
+ },
+ [0x4DF1]={
+ category="so",
+ description="HEXAGRAM FOR THE CAULDRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF1,
+ },
+ [0x4DF2]={
+ category="so",
+ description="HEXAGRAM FOR THE AROUSING THUNDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF2,
+ },
+ [0x4DF3]={
+ category="so",
+ description="HEXAGRAM FOR THE KEEPING STILL MOUNTAIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF3,
+ },
+ [0x4DF4]={
+ category="so",
+ description="HEXAGRAM FOR DEVELOPMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF4,
+ },
+ [0x4DF5]={
+ category="so",
+ description="HEXAGRAM FOR THE MARRYING MAIDEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF5,
+ },
+ [0x4DF6]={
+ category="so",
+ description="HEXAGRAM FOR ABUNDANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF6,
+ },
+ [0x4DF7]={
+ category="so",
+ description="HEXAGRAM FOR THE WANDERER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF7,
+ },
+ [0x4DF8]={
+ category="so",
+ description="HEXAGRAM FOR THE GENTLE WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF8,
+ },
+ [0x4DF9]={
+ category="so",
+ description="HEXAGRAM FOR THE JOYOUS LAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DF9,
+ },
+ [0x4DFA]={
+ category="so",
+ description="HEXAGRAM FOR DISPERSION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFA,
+ },
+ [0x4DFB]={
+ category="so",
+ description="HEXAGRAM FOR LIMITATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFB,
+ },
+ [0x4DFC]={
+ category="so",
+ description="HEXAGRAM FOR INNER TRUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFC,
+ },
+ [0x4DFD]={
+ category="so",
+ description="HEXAGRAM FOR SMALL PREPONDERANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFD,
+ },
+ [0x4DFE]={
+ category="so",
+ description="HEXAGRAM FOR AFTER COMPLETION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFE,
+ },
+ [0x4DFF]={
+ category="so",
+ description="HEXAGRAM FOR BEFORE COMPLETION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x4DFF,
+ },
+ [0xA000]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA000,
+ },
+ [0xA001]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA001,
+ },
+ [0xA002]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE I",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA002,
+ },
+ [0xA003]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA003,
+ },
+ [0xA004]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA004,
+ },
+ [0xA005]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA005,
+ },
+ [0xA006]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA006,
+ },
+ [0xA007]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE IEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA007,
+ },
+ [0xA008]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE AT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA008,
+ },
+ [0xA009]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE AX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA009,
+ },
+ [0xA00A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE A",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00A,
+ },
+ [0xA00B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE AP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00B,
+ },
+ [0xA00C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE UOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00C,
+ },
+ [0xA00D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE UO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00D,
+ },
+ [0xA00E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE UOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00E,
+ },
+ [0xA00F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE OT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA00F,
+ },
+ [0xA010]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE OX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA010,
+ },
+ [0xA011]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE O",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA011,
+ },
+ [0xA012]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE OP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA012,
+ },
+ [0xA013]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE EX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA013,
+ },
+ [0xA014]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA014,
+ },
+ [0xA015]={
+ category="lm",
+ cjkwd="w",
+ description="YI SYLLABLE WU",
+ direction="l",
+ linebreak="ns",
+ unicodeslot=0xA015,
+ },
+ [0xA016]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA016,
+ },
+ [0xA017]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA017,
+ },
+ [0xA018]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA018,
+ },
+ [0xA019]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA019,
+ },
+ [0xA01A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01A,
+ },
+ [0xA01B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01B,
+ },
+ [0xA01C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01C,
+ },
+ [0xA01D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01D,
+ },
+ [0xA01E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01E,
+ },
+ [0xA01F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA01F,
+ },
+ [0xA020]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA020,
+ },
+ [0xA021]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA021,
+ },
+ [0xA022]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA022,
+ },
+ [0xA023]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA023,
+ },
+ [0xA024]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA024,
+ },
+ [0xA025]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA025,
+ },
+ [0xA026]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA026,
+ },
+ [0xA027]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA027,
+ },
+ [0xA028]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA028,
+ },
+ [0xA029]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA029,
+ },
+ [0xA02A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02A,
+ },
+ [0xA02B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02B,
+ },
+ [0xA02C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02C,
+ },
+ [0xA02D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02D,
+ },
+ [0xA02E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02E,
+ },
+ [0xA02F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA02F,
+ },
+ [0xA030]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA030,
+ },
+ [0xA031]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA031,
+ },
+ [0xA032]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA032,
+ },
+ [0xA033]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA033,
+ },
+ [0xA034]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA034,
+ },
+ [0xA035]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA035,
+ },
+ [0xA036]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA036,
+ },
+ [0xA037]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA037,
+ },
+ [0xA038]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA038,
+ },
+ [0xA039]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA039,
+ },
+ [0xA03A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03A,
+ },
+ [0xA03B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03B,
+ },
+ [0xA03C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03C,
+ },
+ [0xA03D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03D,
+ },
+ [0xA03E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03E,
+ },
+ [0xA03F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA03F,
+ },
+ [0xA040]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA040,
+ },
+ [0xA041]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA041,
+ },
+ [0xA042]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA042,
+ },
+ [0xA043]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA043,
+ },
+ [0xA044]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA044,
+ },
+ [0xA045]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA045,
+ },
+ [0xA046]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE POT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA046,
+ },
+ [0xA047]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE POX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA047,
+ },
+ [0xA048]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA048,
+ },
+ [0xA049]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE POP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA049,
+ },
+ [0xA04A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04A,
+ },
+ [0xA04B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04B,
+ },
+ [0xA04C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04C,
+ },
+ [0xA04D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04D,
+ },
+ [0xA04E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04E,
+ },
+ [0xA04F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA04F,
+ },
+ [0xA050]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA050,
+ },
+ [0xA051]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA051,
+ },
+ [0xA052]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA052,
+ },
+ [0xA053]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA053,
+ },
+ [0xA054]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA054,
+ },
+ [0xA055]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE PYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA055,
+ },
+ [0xA056]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA056,
+ },
+ [0xA057]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA057,
+ },
+ [0xA058]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA058,
+ },
+ [0xA059]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA059,
+ },
+ [0xA05A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05A,
+ },
+ [0xA05B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05B,
+ },
+ [0xA05C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05C,
+ },
+ [0xA05D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05D,
+ },
+ [0xA05E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05E,
+ },
+ [0xA05F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA05F,
+ },
+ [0xA060]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA060,
+ },
+ [0xA061]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA061,
+ },
+ [0xA062]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA062,
+ },
+ [0xA063]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA063,
+ },
+ [0xA064]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA064,
+ },
+ [0xA065]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA065,
+ },
+ [0xA066]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA066,
+ },
+ [0xA067]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA067,
+ },
+ [0xA068]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA068,
+ },
+ [0xA069]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA069,
+ },
+ [0xA06A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06A,
+ },
+ [0xA06B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06B,
+ },
+ [0xA06C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06C,
+ },
+ [0xA06D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06D,
+ },
+ [0xA06E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06E,
+ },
+ [0xA06F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA06F,
+ },
+ [0xA070]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA070,
+ },
+ [0xA071]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA071,
+ },
+ [0xA072]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA072,
+ },
+ [0xA073]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA073,
+ },
+ [0xA074]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA074,
+ },
+ [0xA075]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE BBYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA075,
+ },
+ [0xA076]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA076,
+ },
+ [0xA077]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA077,
+ },
+ [0xA078]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA078,
+ },
+ [0xA079]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA079,
+ },
+ [0xA07A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07A,
+ },
+ [0xA07B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07B,
+ },
+ [0xA07C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07C,
+ },
+ [0xA07D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07D,
+ },
+ [0xA07E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07E,
+ },
+ [0xA07F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA07F,
+ },
+ [0xA080]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA080,
+ },
+ [0xA081]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA081,
+ },
+ [0xA082]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA082,
+ },
+ [0xA083]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA083,
+ },
+ [0xA084]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA084,
+ },
+ [0xA085]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA085,
+ },
+ [0xA086]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA086,
+ },
+ [0xA087]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA087,
+ },
+ [0xA088]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA088,
+ },
+ [0xA089]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA089,
+ },
+ [0xA08A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08A,
+ },
+ [0xA08B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08B,
+ },
+ [0xA08C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08C,
+ },
+ [0xA08D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08D,
+ },
+ [0xA08E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08E,
+ },
+ [0xA08F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA08F,
+ },
+ [0xA090]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NBYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA090,
+ },
+ [0xA091]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA091,
+ },
+ [0xA092]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA092,
+ },
+ [0xA093]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA093,
+ },
+ [0xA094]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA094,
+ },
+ [0xA095]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA095,
+ },
+ [0xA096]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA096,
+ },
+ [0xA097]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA097,
+ },
+ [0xA098]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA098,
+ },
+ [0xA099]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA099,
+ },
+ [0xA09A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09A,
+ },
+ [0xA09B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09B,
+ },
+ [0xA09C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09C,
+ },
+ [0xA09D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09D,
+ },
+ [0xA09E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09E,
+ },
+ [0xA09F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA09F,
+ },
+ [0xA0A0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A0,
+ },
+ [0xA0A1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A1,
+ },
+ [0xA0A2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A2,
+ },
+ [0xA0A3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A3,
+ },
+ [0xA0A4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A4,
+ },
+ [0xA0A5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A5,
+ },
+ [0xA0A6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A6,
+ },
+ [0xA0A7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A7,
+ },
+ [0xA0A8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A8,
+ },
+ [0xA0A9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0A9,
+ },
+ [0xA0AA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AA,
+ },
+ [0xA0AB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AB,
+ },
+ [0xA0AC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AC,
+ },
+ [0xA0AD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HMYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AD,
+ },
+ [0xA0AE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AE,
+ },
+ [0xA0AF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0AF,
+ },
+ [0xA0B0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B0,
+ },
+ [0xA0B1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B1,
+ },
+ [0xA0B2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B2,
+ },
+ [0xA0B3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B3,
+ },
+ [0xA0B4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B4,
+ },
+ [0xA0B5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B5,
+ },
+ [0xA0B6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B6,
+ },
+ [0xA0B7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B7,
+ },
+ [0xA0B8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B8,
+ },
+ [0xA0B9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0B9,
+ },
+ [0xA0BA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BA,
+ },
+ [0xA0BB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BB,
+ },
+ [0xA0BC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BC,
+ },
+ [0xA0BD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BD,
+ },
+ [0xA0BE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BE,
+ },
+ [0xA0BF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0BF,
+ },
+ [0xA0C0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C0,
+ },
+ [0xA0C1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C1,
+ },
+ [0xA0C2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ME",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C2,
+ },
+ [0xA0C3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C3,
+ },
+ [0xA0C4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C4,
+ },
+ [0xA0C5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C5,
+ },
+ [0xA0C6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C6,
+ },
+ [0xA0C7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C7,
+ },
+ [0xA0C8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C8,
+ },
+ [0xA0C9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0C9,
+ },
+ [0xA0CA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CA,
+ },
+ [0xA0CB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CB,
+ },
+ [0xA0CC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CC,
+ },
+ [0xA0CD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CD,
+ },
+ [0xA0CE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CE,
+ },
+ [0xA0CF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0CF,
+ },
+ [0xA0D0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D0,
+ },
+ [0xA0D1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D1,
+ },
+ [0xA0D2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D2,
+ },
+ [0xA0D3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D3,
+ },
+ [0xA0D4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D4,
+ },
+ [0xA0D5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D5,
+ },
+ [0xA0D6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D6,
+ },
+ [0xA0D7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D7,
+ },
+ [0xA0D8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D8,
+ },
+ [0xA0D9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0D9,
+ },
+ [0xA0DA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DA,
+ },
+ [0xA0DB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DB,
+ },
+ [0xA0DC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DC,
+ },
+ [0xA0DD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DD,
+ },
+ [0xA0DE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DE,
+ },
+ [0xA0DF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0DF,
+ },
+ [0xA0E0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E0,
+ },
+ [0xA0E1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE FYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E1,
+ },
+ [0xA0E2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E2,
+ },
+ [0xA0E3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E3,
+ },
+ [0xA0E4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E4,
+ },
+ [0xA0E5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E5,
+ },
+ [0xA0E6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E6,
+ },
+ [0xA0E7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E7,
+ },
+ [0xA0E8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E8,
+ },
+ [0xA0E9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0E9,
+ },
+ [0xA0EA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0EA,
+ },
+ [0xA0EB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0EB,
+ },
+ [0xA0EC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0EC,
+ },
+ [0xA0ED]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0ED,
+ },
+ [0xA0EE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0EE,
+ },
+ [0xA0EF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0EF,
+ },
+ [0xA0F0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F0,
+ },
+ [0xA0F1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F1,
+ },
+ [0xA0F2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F2,
+ },
+ [0xA0F3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F3,
+ },
+ [0xA0F4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F4,
+ },
+ [0xA0F5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F5,
+ },
+ [0xA0F6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F6,
+ },
+ [0xA0F7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F7,
+ },
+ [0xA0F8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F8,
+ },
+ [0xA0F9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0F9,
+ },
+ [0xA0FA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FA,
+ },
+ [0xA0FB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FB,
+ },
+ [0xA0FC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FC,
+ },
+ [0xA0FD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FD,
+ },
+ [0xA0FE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FE,
+ },
+ [0xA0FF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE VYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA0FF,
+ },
+ [0xA100]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA100,
+ },
+ [0xA101]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA101,
+ },
+ [0xA102]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA102,
+ },
+ [0xA103]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA103,
+ },
+ [0xA104]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA104,
+ },
+ [0xA105]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA105,
+ },
+ [0xA106]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA106,
+ },
+ [0xA107]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA107,
+ },
+ [0xA108]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA108,
+ },
+ [0xA109]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA109,
+ },
+ [0xA10A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10A,
+ },
+ [0xA10B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10B,
+ },
+ [0xA10C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10C,
+ },
+ [0xA10D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10D,
+ },
+ [0xA10E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10E,
+ },
+ [0xA10F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA10F,
+ },
+ [0xA110]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA110,
+ },
+ [0xA111]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA111,
+ },
+ [0xA112]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA112,
+ },
+ [0xA113]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA113,
+ },
+ [0xA114]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA114,
+ },
+ [0xA115]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA115,
+ },
+ [0xA116]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA116,
+ },
+ [0xA117]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA117,
+ },
+ [0xA118]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA118,
+ },
+ [0xA119]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA119,
+ },
+ [0xA11A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11A,
+ },
+ [0xA11B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11B,
+ },
+ [0xA11C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11C,
+ },
+ [0xA11D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11D,
+ },
+ [0xA11E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11E,
+ },
+ [0xA11F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA11F,
+ },
+ [0xA120]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA120,
+ },
+ [0xA121]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA121,
+ },
+ [0xA122]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA122,
+ },
+ [0xA123]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA123,
+ },
+ [0xA124]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA124,
+ },
+ [0xA125]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA125,
+ },
+ [0xA126]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA126,
+ },
+ [0xA127]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA127,
+ },
+ [0xA128]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA128,
+ },
+ [0xA129]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA129,
+ },
+ [0xA12A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12A,
+ },
+ [0xA12B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12B,
+ },
+ [0xA12C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12C,
+ },
+ [0xA12D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12D,
+ },
+ [0xA12E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12E,
+ },
+ [0xA12F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA12F,
+ },
+ [0xA130]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA130,
+ },
+ [0xA131]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA131,
+ },
+ [0xA132]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA132,
+ },
+ [0xA133]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA133,
+ },
+ [0xA134]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA134,
+ },
+ [0xA135]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE TUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA135,
+ },
+ [0xA136]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA136,
+ },
+ [0xA137]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA137,
+ },
+ [0xA138]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA138,
+ },
+ [0xA139]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA139,
+ },
+ [0xA13A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13A,
+ },
+ [0xA13B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13B,
+ },
+ [0xA13C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13C,
+ },
+ [0xA13D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13D,
+ },
+ [0xA13E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13E,
+ },
+ [0xA13F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA13F,
+ },
+ [0xA140]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA140,
+ },
+ [0xA141]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA141,
+ },
+ [0xA142]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA142,
+ },
+ [0xA143]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA143,
+ },
+ [0xA144]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA144,
+ },
+ [0xA145]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA145,
+ },
+ [0xA146]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA146,
+ },
+ [0xA147]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA147,
+ },
+ [0xA148]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA148,
+ },
+ [0xA149]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA149,
+ },
+ [0xA14A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14A,
+ },
+ [0xA14B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14B,
+ },
+ [0xA14C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14C,
+ },
+ [0xA14D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14D,
+ },
+ [0xA14E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14E,
+ },
+ [0xA14F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA14F,
+ },
+ [0xA150]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE DDUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA150,
+ },
+ [0xA151]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA151,
+ },
+ [0xA152]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA152,
+ },
+ [0xA153]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA153,
+ },
+ [0xA154]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA154,
+ },
+ [0xA155]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA155,
+ },
+ [0xA156]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA156,
+ },
+ [0xA157]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA157,
+ },
+ [0xA158]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA158,
+ },
+ [0xA159]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA159,
+ },
+ [0xA15A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15A,
+ },
+ [0xA15B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15B,
+ },
+ [0xA15C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15C,
+ },
+ [0xA15D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15D,
+ },
+ [0xA15E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15E,
+ },
+ [0xA15F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA15F,
+ },
+ [0xA160]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA160,
+ },
+ [0xA161]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA161,
+ },
+ [0xA162]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA162,
+ },
+ [0xA163]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA163,
+ },
+ [0xA164]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA164,
+ },
+ [0xA165]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA165,
+ },
+ [0xA166]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA166,
+ },
+ [0xA167]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NDUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA167,
+ },
+ [0xA168]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA168,
+ },
+ [0xA169]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA169,
+ },
+ [0xA16A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16A,
+ },
+ [0xA16B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16B,
+ },
+ [0xA16C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16C,
+ },
+ [0xA16D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16D,
+ },
+ [0xA16E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16E,
+ },
+ [0xA16F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA16F,
+ },
+ [0xA170]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA170,
+ },
+ [0xA171]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA171,
+ },
+ [0xA172]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA172,
+ },
+ [0xA173]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA173,
+ },
+ [0xA174]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA174,
+ },
+ [0xA175]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA175,
+ },
+ [0xA176]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA176,
+ },
+ [0xA177]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA177,
+ },
+ [0xA178]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA178,
+ },
+ [0xA179]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA179,
+ },
+ [0xA17A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17A,
+ },
+ [0xA17B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17B,
+ },
+ [0xA17C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HNUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17C,
+ },
+ [0xA17D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17D,
+ },
+ [0xA17E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17E,
+ },
+ [0xA17F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA17F,
+ },
+ [0xA180]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA180,
+ },
+ [0xA181]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA181,
+ },
+ [0xA182]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA182,
+ },
+ [0xA183]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA183,
+ },
+ [0xA184]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA184,
+ },
+ [0xA185]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA185,
+ },
+ [0xA186]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA186,
+ },
+ [0xA187]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA187,
+ },
+ [0xA188]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA188,
+ },
+ [0xA189]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA189,
+ },
+ [0xA18A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18A,
+ },
+ [0xA18B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18B,
+ },
+ [0xA18C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18C,
+ },
+ [0xA18D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18D,
+ },
+ [0xA18E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18E,
+ },
+ [0xA18F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA18F,
+ },
+ [0xA190]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA190,
+ },
+ [0xA191]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA191,
+ },
+ [0xA192]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA192,
+ },
+ [0xA193]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA193,
+ },
+ [0xA194]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA194,
+ },
+ [0xA195]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA195,
+ },
+ [0xA196]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA196,
+ },
+ [0xA197]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA197,
+ },
+ [0xA198]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA198,
+ },
+ [0xA199]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA199,
+ },
+ [0xA19A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19A,
+ },
+ [0xA19B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19B,
+ },
+ [0xA19C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19C,
+ },
+ [0xA19D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19D,
+ },
+ [0xA19E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19E,
+ },
+ [0xA19F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA19F,
+ },
+ [0xA1A0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A0,
+ },
+ [0xA1A1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A1,
+ },
+ [0xA1A2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A2,
+ },
+ [0xA1A3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A3,
+ },
+ [0xA1A4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A4,
+ },
+ [0xA1A5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A5,
+ },
+ [0xA1A6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A6,
+ },
+ [0xA1A7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A7,
+ },
+ [0xA1A8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A8,
+ },
+ [0xA1A9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1A9,
+ },
+ [0xA1AA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AA,
+ },
+ [0xA1AB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AB,
+ },
+ [0xA1AC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AC,
+ },
+ [0xA1AD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AD,
+ },
+ [0xA1AE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AE,
+ },
+ [0xA1AF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1AF,
+ },
+ [0xA1B0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B0,
+ },
+ [0xA1B1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B1,
+ },
+ [0xA1B2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B2,
+ },
+ [0xA1B3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B3,
+ },
+ [0xA1B4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B4,
+ },
+ [0xA1B5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B5,
+ },
+ [0xA1B6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HLYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B6,
+ },
+ [0xA1B7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B7,
+ },
+ [0xA1B8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B8,
+ },
+ [0xA1B9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1B9,
+ },
+ [0xA1BA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BA,
+ },
+ [0xA1BB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BB,
+ },
+ [0xA1BC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BC,
+ },
+ [0xA1BD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BD,
+ },
+ [0xA1BE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BE,
+ },
+ [0xA1BF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1BF,
+ },
+ [0xA1C0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C0,
+ },
+ [0xA1C1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C1,
+ },
+ [0xA1C2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C2,
+ },
+ [0xA1C3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C3,
+ },
+ [0xA1C4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C4,
+ },
+ [0xA1C5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C5,
+ },
+ [0xA1C6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C6,
+ },
+ [0xA1C7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C7,
+ },
+ [0xA1C8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C8,
+ },
+ [0xA1C9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1C9,
+ },
+ [0xA1CA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CA,
+ },
+ [0xA1CB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CB,
+ },
+ [0xA1CC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CC,
+ },
+ [0xA1CD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CD,
+ },
+ [0xA1CE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CE,
+ },
+ [0xA1CF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1CF,
+ },
+ [0xA1D0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D0,
+ },
+ [0xA1D1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D1,
+ },
+ [0xA1D2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D2,
+ },
+ [0xA1D3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D3,
+ },
+ [0xA1D4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D4,
+ },
+ [0xA1D5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D5,
+ },
+ [0xA1D6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D6,
+ },
+ [0xA1D7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D7,
+ },
+ [0xA1D8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D8,
+ },
+ [0xA1D9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE LYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1D9,
+ },
+ [0xA1DA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DA,
+ },
+ [0xA1DB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DB,
+ },
+ [0xA1DC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DC,
+ },
+ [0xA1DD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DD,
+ },
+ [0xA1DE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DE,
+ },
+ [0xA1DF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1DF,
+ },
+ [0xA1E0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E0,
+ },
+ [0xA1E1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E1,
+ },
+ [0xA1E2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E2,
+ },
+ [0xA1E3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E3,
+ },
+ [0xA1E4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E4,
+ },
+ [0xA1E5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E5,
+ },
+ [0xA1E6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E6,
+ },
+ [0xA1E7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E7,
+ },
+ [0xA1E8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E8,
+ },
+ [0xA1E9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1E9,
+ },
+ [0xA1EA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1EA,
+ },
+ [0xA1EB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1EB,
+ },
+ [0xA1EC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1EC,
+ },
+ [0xA1ED]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1ED,
+ },
+ [0xA1EE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1EE,
+ },
+ [0xA1EF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1EF,
+ },
+ [0xA1F0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F0,
+ },
+ [0xA1F1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F1,
+ },
+ [0xA1F2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F2,
+ },
+ [0xA1F3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F3,
+ },
+ [0xA1F4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F4,
+ },
+ [0xA1F5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F5,
+ },
+ [0xA1F6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F6,
+ },
+ [0xA1F7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F7,
+ },
+ [0xA1F8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F8,
+ },
+ [0xA1F9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1F9,
+ },
+ [0xA1FA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FA,
+ },
+ [0xA1FB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FB,
+ },
+ [0xA1FC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FC,
+ },
+ [0xA1FD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FD,
+ },
+ [0xA1FE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FE,
+ },
+ [0xA1FF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA1FF,
+ },
+ [0xA200]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA200,
+ },
+ [0xA201]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA201,
+ },
+ [0xA202]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA202,
+ },
+ [0xA203]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA203,
+ },
+ [0xA204]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA204,
+ },
+ [0xA205]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA205,
+ },
+ [0xA206]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA206,
+ },
+ [0xA207]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA207,
+ },
+ [0xA208]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA208,
+ },
+ [0xA209]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA209,
+ },
+ [0xA20A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20A,
+ },
+ [0xA20B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20B,
+ },
+ [0xA20C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20C,
+ },
+ [0xA20D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20D,
+ },
+ [0xA20E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20E,
+ },
+ [0xA20F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA20F,
+ },
+ [0xA210]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA210,
+ },
+ [0xA211]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA211,
+ },
+ [0xA212]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA212,
+ },
+ [0xA213]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE KUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA213,
+ },
+ [0xA214]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA214,
+ },
+ [0xA215]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA215,
+ },
+ [0xA216]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA216,
+ },
+ [0xA217]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA217,
+ },
+ [0xA218]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA218,
+ },
+ [0xA219]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA219,
+ },
+ [0xA21A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21A,
+ },
+ [0xA21B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21B,
+ },
+ [0xA21C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21C,
+ },
+ [0xA21D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21D,
+ },
+ [0xA21E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21E,
+ },
+ [0xA21F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA21F,
+ },
+ [0xA220]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA220,
+ },
+ [0xA221]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA221,
+ },
+ [0xA222]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA222,
+ },
+ [0xA223]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA223,
+ },
+ [0xA224]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA224,
+ },
+ [0xA225]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA225,
+ },
+ [0xA226]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA226,
+ },
+ [0xA227]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA227,
+ },
+ [0xA228]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA228,
+ },
+ [0xA229]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA229,
+ },
+ [0xA22A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22A,
+ },
+ [0xA22B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22B,
+ },
+ [0xA22C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22C,
+ },
+ [0xA22D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22D,
+ },
+ [0xA22E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22E,
+ },
+ [0xA22F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE GGUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA22F,
+ },
+ [0xA230]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA230,
+ },
+ [0xA231]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA231,
+ },
+ [0xA232]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA232,
+ },
+ [0xA233]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA233,
+ },
+ [0xA234]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA234,
+ },
+ [0xA235]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA235,
+ },
+ [0xA236]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA236,
+ },
+ [0xA237]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA237,
+ },
+ [0xA238]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA238,
+ },
+ [0xA239]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA239,
+ },
+ [0xA23A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23A,
+ },
+ [0xA23B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23B,
+ },
+ [0xA23C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23C,
+ },
+ [0xA23D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23D,
+ },
+ [0xA23E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23E,
+ },
+ [0xA23F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA23F,
+ },
+ [0xA240]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA240,
+ },
+ [0xA241]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA241,
+ },
+ [0xA242]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA242,
+ },
+ [0xA243]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA243,
+ },
+ [0xA244]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA244,
+ },
+ [0xA245]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE MGUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA245,
+ },
+ [0xA246]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA246,
+ },
+ [0xA247]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA247,
+ },
+ [0xA248]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA248,
+ },
+ [0xA249]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA249,
+ },
+ [0xA24A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24A,
+ },
+ [0xA24B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24B,
+ },
+ [0xA24C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24C,
+ },
+ [0xA24D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24D,
+ },
+ [0xA24E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24E,
+ },
+ [0xA24F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA24F,
+ },
+ [0xA250]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA250,
+ },
+ [0xA251]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA251,
+ },
+ [0xA252]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA252,
+ },
+ [0xA253]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA253,
+ },
+ [0xA254]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA254,
+ },
+ [0xA255]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA255,
+ },
+ [0xA256]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA256,
+ },
+ [0xA257]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA257,
+ },
+ [0xA258]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA258,
+ },
+ [0xA259]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA259,
+ },
+ [0xA25A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25A,
+ },
+ [0xA25B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25B,
+ },
+ [0xA25C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HXEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25C,
+ },
+ [0xA25D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25D,
+ },
+ [0xA25E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25E,
+ },
+ [0xA25F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA25F,
+ },
+ [0xA260]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA260,
+ },
+ [0xA261]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA261,
+ },
+ [0xA262]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA262,
+ },
+ [0xA263]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA263,
+ },
+ [0xA264]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA264,
+ },
+ [0xA265]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA265,
+ },
+ [0xA266]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA266,
+ },
+ [0xA267]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA267,
+ },
+ [0xA268]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA268,
+ },
+ [0xA269]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA269,
+ },
+ [0xA26A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26A,
+ },
+ [0xA26B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26B,
+ },
+ [0xA26C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26C,
+ },
+ [0xA26D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NGEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26D,
+ },
+ [0xA26E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26E,
+ },
+ [0xA26F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA26F,
+ },
+ [0xA270]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA270,
+ },
+ [0xA271]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA271,
+ },
+ [0xA272]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA272,
+ },
+ [0xA273]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA273,
+ },
+ [0xA274]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA274,
+ },
+ [0xA275]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA275,
+ },
+ [0xA276]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA276,
+ },
+ [0xA277]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA277,
+ },
+ [0xA278]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA278,
+ },
+ [0xA279]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA279,
+ },
+ [0xA27A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27A,
+ },
+ [0xA27B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27B,
+ },
+ [0xA27C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27C,
+ },
+ [0xA27D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27D,
+ },
+ [0xA27E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27E,
+ },
+ [0xA27F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE HEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA27F,
+ },
+ [0xA280]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA280,
+ },
+ [0xA281]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA281,
+ },
+ [0xA282]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA282,
+ },
+ [0xA283]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA283,
+ },
+ [0xA284]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA284,
+ },
+ [0xA285]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA285,
+ },
+ [0xA286]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA286,
+ },
+ [0xA287]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA287,
+ },
+ [0xA288]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA288,
+ },
+ [0xA289]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA289,
+ },
+ [0xA28A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28A,
+ },
+ [0xA28B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28B,
+ },
+ [0xA28C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE WEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28C,
+ },
+ [0xA28D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28D,
+ },
+ [0xA28E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28E,
+ },
+ [0xA28F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA28F,
+ },
+ [0xA290]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA290,
+ },
+ [0xA291]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA291,
+ },
+ [0xA292]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA292,
+ },
+ [0xA293]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA293,
+ },
+ [0xA294]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA294,
+ },
+ [0xA295]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA295,
+ },
+ [0xA296]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA296,
+ },
+ [0xA297]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA297,
+ },
+ [0xA298]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA298,
+ },
+ [0xA299]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA299,
+ },
+ [0xA29A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29A,
+ },
+ [0xA29B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29B,
+ },
+ [0xA29C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29C,
+ },
+ [0xA29D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29D,
+ },
+ [0xA29E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29E,
+ },
+ [0xA29F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA29F,
+ },
+ [0xA2A0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A0,
+ },
+ [0xA2A1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A1,
+ },
+ [0xA2A2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A2,
+ },
+ [0xA2A3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A3,
+ },
+ [0xA2A4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A4,
+ },
+ [0xA2A5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A5,
+ },
+ [0xA2A6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A6,
+ },
+ [0xA2A7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A7,
+ },
+ [0xA2A8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A8,
+ },
+ [0xA2A9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2A9,
+ },
+ [0xA2AA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AA,
+ },
+ [0xA2AB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AB,
+ },
+ [0xA2AC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AC,
+ },
+ [0xA2AD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AD,
+ },
+ [0xA2AE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AE,
+ },
+ [0xA2AF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2AF,
+ },
+ [0xA2B0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B0,
+ },
+ [0xA2B1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B1,
+ },
+ [0xA2B2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B2,
+ },
+ [0xA2B3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B3,
+ },
+ [0xA2B4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B4,
+ },
+ [0xA2B5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B5,
+ },
+ [0xA2B6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B6,
+ },
+ [0xA2B7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B7,
+ },
+ [0xA2B8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B8,
+ },
+ [0xA2B9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2B9,
+ },
+ [0xA2BA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BA,
+ },
+ [0xA2BB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BB,
+ },
+ [0xA2BC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BC,
+ },
+ [0xA2BD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE COT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BD,
+ },
+ [0xA2BE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE COX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BE,
+ },
+ [0xA2BF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2BF,
+ },
+ [0xA2C0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE COP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C0,
+ },
+ [0xA2C1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C1,
+ },
+ [0xA2C2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C2,
+ },
+ [0xA2C3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C3,
+ },
+ [0xA2C4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C4,
+ },
+ [0xA2C5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C5,
+ },
+ [0xA2C6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C6,
+ },
+ [0xA2C7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C7,
+ },
+ [0xA2C8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C8,
+ },
+ [0xA2C9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2C9,
+ },
+ [0xA2CA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CA,
+ },
+ [0xA2CB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CB,
+ },
+ [0xA2CC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CC,
+ },
+ [0xA2CD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CD,
+ },
+ [0xA2CE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CE,
+ },
+ [0xA2CF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2CF,
+ },
+ [0xA2D0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D0,
+ },
+ [0xA2D1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D1,
+ },
+ [0xA2D2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D2,
+ },
+ [0xA2D3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D3,
+ },
+ [0xA2D4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D4,
+ },
+ [0xA2D5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D5,
+ },
+ [0xA2D6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D6,
+ },
+ [0xA2D7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D7,
+ },
+ [0xA2D8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D8,
+ },
+ [0xA2D9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2D9,
+ },
+ [0xA2DA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DA,
+ },
+ [0xA2DB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DB,
+ },
+ [0xA2DC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DC,
+ },
+ [0xA2DD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DD,
+ },
+ [0xA2DE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DE,
+ },
+ [0xA2DF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2DF,
+ },
+ [0xA2E0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E0,
+ },
+ [0xA2E1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E1,
+ },
+ [0xA2E2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E2,
+ },
+ [0xA2E3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E3,
+ },
+ [0xA2E4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E4,
+ },
+ [0xA2E5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E5,
+ },
+ [0xA2E6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E6,
+ },
+ [0xA2E7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E7,
+ },
+ [0xA2E8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E8,
+ },
+ [0xA2E9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2E9,
+ },
+ [0xA2EA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2EA,
+ },
+ [0xA2EB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2EB,
+ },
+ [0xA2EC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZZYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2EC,
+ },
+ [0xA2ED]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2ED,
+ },
+ [0xA2EE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2EE,
+ },
+ [0xA2EF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2EF,
+ },
+ [0xA2F0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F0,
+ },
+ [0xA2F1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F1,
+ },
+ [0xA2F2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F2,
+ },
+ [0xA2F3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F3,
+ },
+ [0xA2F4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F4,
+ },
+ [0xA2F5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F5,
+ },
+ [0xA2F6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F6,
+ },
+ [0xA2F7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F7,
+ },
+ [0xA2F8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F8,
+ },
+ [0xA2F9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2F9,
+ },
+ [0xA2FA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FA,
+ },
+ [0xA2FB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FB,
+ },
+ [0xA2FC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FC,
+ },
+ [0xA2FD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FD,
+ },
+ [0xA2FE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FE,
+ },
+ [0xA2FF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA2FF,
+ },
+ [0xA300]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA300,
+ },
+ [0xA301]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA301,
+ },
+ [0xA302]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA302,
+ },
+ [0xA303]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA303,
+ },
+ [0xA304]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA304,
+ },
+ [0xA305]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA305,
+ },
+ [0xA306]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA306,
+ },
+ [0xA307]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA307,
+ },
+ [0xA308]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NZYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA308,
+ },
+ [0xA309]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA309,
+ },
+ [0xA30A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30A,
+ },
+ [0xA30B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30B,
+ },
+ [0xA30C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30C,
+ },
+ [0xA30D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30D,
+ },
+ [0xA30E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30E,
+ },
+ [0xA30F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA30F,
+ },
+ [0xA310]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA310,
+ },
+ [0xA311]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA311,
+ },
+ [0xA312]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA312,
+ },
+ [0xA313]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA313,
+ },
+ [0xA314]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA314,
+ },
+ [0xA315]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA315,
+ },
+ [0xA316]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA316,
+ },
+ [0xA317]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA317,
+ },
+ [0xA318]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA318,
+ },
+ [0xA319]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA319,
+ },
+ [0xA31A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31A,
+ },
+ [0xA31B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31B,
+ },
+ [0xA31C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31C,
+ },
+ [0xA31D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31D,
+ },
+ [0xA31E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31E,
+ },
+ [0xA31F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA31F,
+ },
+ [0xA320]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA320,
+ },
+ [0xA321]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA321,
+ },
+ [0xA322]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA322,
+ },
+ [0xA323]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA323,
+ },
+ [0xA324]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA324,
+ },
+ [0xA325]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA325,
+ },
+ [0xA326]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA326,
+ },
+ [0xA327]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA327,
+ },
+ [0xA328]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA328,
+ },
+ [0xA329]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA329,
+ },
+ [0xA32A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32A,
+ },
+ [0xA32B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32B,
+ },
+ [0xA32C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32C,
+ },
+ [0xA32D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32D,
+ },
+ [0xA32E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32E,
+ },
+ [0xA32F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA32F,
+ },
+ [0xA330]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA330,
+ },
+ [0xA331]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA331,
+ },
+ [0xA332]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA332,
+ },
+ [0xA333]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA333,
+ },
+ [0xA334]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA334,
+ },
+ [0xA335]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA335,
+ },
+ [0xA336]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA336,
+ },
+ [0xA337]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA337,
+ },
+ [0xA338]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA338,
+ },
+ [0xA339]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA339,
+ },
+ [0xA33A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33A,
+ },
+ [0xA33B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33B,
+ },
+ [0xA33C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33C,
+ },
+ [0xA33D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33D,
+ },
+ [0xA33E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33E,
+ },
+ [0xA33F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA33F,
+ },
+ [0xA340]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA340,
+ },
+ [0xA341]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA341,
+ },
+ [0xA342]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA342,
+ },
+ [0xA343]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA343,
+ },
+ [0xA344]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA344,
+ },
+ [0xA345]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SSYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA345,
+ },
+ [0xA346]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA346,
+ },
+ [0xA347]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA347,
+ },
+ [0xA348]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA348,
+ },
+ [0xA349]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA349,
+ },
+ [0xA34A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34A,
+ },
+ [0xA34B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34B,
+ },
+ [0xA34C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34C,
+ },
+ [0xA34D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34D,
+ },
+ [0xA34E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34E,
+ },
+ [0xA34F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA34F,
+ },
+ [0xA350]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA350,
+ },
+ [0xA351]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA351,
+ },
+ [0xA352]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA352,
+ },
+ [0xA353]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA353,
+ },
+ [0xA354]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA354,
+ },
+ [0xA355]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA355,
+ },
+ [0xA356]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA356,
+ },
+ [0xA357]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA357,
+ },
+ [0xA358]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA358,
+ },
+ [0xA359]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA359,
+ },
+ [0xA35A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35A,
+ },
+ [0xA35B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35B,
+ },
+ [0xA35C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35C,
+ },
+ [0xA35D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35D,
+ },
+ [0xA35E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35E,
+ },
+ [0xA35F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA35F,
+ },
+ [0xA360]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ZHYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA360,
+ },
+ [0xA361]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA361,
+ },
+ [0xA362]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA362,
+ },
+ [0xA363]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA363,
+ },
+ [0xA364]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA364,
+ },
+ [0xA365]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA365,
+ },
+ [0xA366]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA366,
+ },
+ [0xA367]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA367,
+ },
+ [0xA368]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA368,
+ },
+ [0xA369]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA369,
+ },
+ [0xA36A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36A,
+ },
+ [0xA36B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36B,
+ },
+ [0xA36C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36C,
+ },
+ [0xA36D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36D,
+ },
+ [0xA36E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36E,
+ },
+ [0xA36F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA36F,
+ },
+ [0xA370]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA370,
+ },
+ [0xA371]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA371,
+ },
+ [0xA372]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA372,
+ },
+ [0xA373]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA373,
+ },
+ [0xA374]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA374,
+ },
+ [0xA375]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA375,
+ },
+ [0xA376]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA376,
+ },
+ [0xA377]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA377,
+ },
+ [0xA378]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA378,
+ },
+ [0xA379]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA379,
+ },
+ [0xA37A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37A,
+ },
+ [0xA37B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE CHYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37B,
+ },
+ [0xA37C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37C,
+ },
+ [0xA37D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37D,
+ },
+ [0xA37E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37E,
+ },
+ [0xA37F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA37F,
+ },
+ [0xA380]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RROT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA380,
+ },
+ [0xA381]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RROX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA381,
+ },
+ [0xA382]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA382,
+ },
+ [0xA383]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RROP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA383,
+ },
+ [0xA384]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA384,
+ },
+ [0xA385]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RREX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA385,
+ },
+ [0xA386]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA386,
+ },
+ [0xA387]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RREP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA387,
+ },
+ [0xA388]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA388,
+ },
+ [0xA389]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA389,
+ },
+ [0xA38A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38A,
+ },
+ [0xA38B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38B,
+ },
+ [0xA38C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38C,
+ },
+ [0xA38D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38D,
+ },
+ [0xA38E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38E,
+ },
+ [0xA38F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA38F,
+ },
+ [0xA390]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA390,
+ },
+ [0xA391]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA391,
+ },
+ [0xA392]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA392,
+ },
+ [0xA393]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RRYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA393,
+ },
+ [0xA394]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA394,
+ },
+ [0xA395]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA395,
+ },
+ [0xA396]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA396,
+ },
+ [0xA397]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA397,
+ },
+ [0xA398]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NROX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA398,
+ },
+ [0xA399]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA399,
+ },
+ [0xA39A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NROP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39A,
+ },
+ [0xA39B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39B,
+ },
+ [0xA39C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NREX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39C,
+ },
+ [0xA39D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39D,
+ },
+ [0xA39E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NREP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39E,
+ },
+ [0xA39F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA39F,
+ },
+ [0xA3A0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A0,
+ },
+ [0xA3A1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A1,
+ },
+ [0xA3A2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A2,
+ },
+ [0xA3A3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A3,
+ },
+ [0xA3A4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A4,
+ },
+ [0xA3A5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A5,
+ },
+ [0xA3A6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A6,
+ },
+ [0xA3A7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A7,
+ },
+ [0xA3A8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A8,
+ },
+ [0xA3A9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3A9,
+ },
+ [0xA3AA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NRYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AA,
+ },
+ [0xA3AB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AB,
+ },
+ [0xA3AC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AC,
+ },
+ [0xA3AD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AD,
+ },
+ [0xA3AE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AE,
+ },
+ [0xA3AF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3AF,
+ },
+ [0xA3B0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B0,
+ },
+ [0xA3B1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B1,
+ },
+ [0xA3B2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B2,
+ },
+ [0xA3B3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B3,
+ },
+ [0xA3B4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B4,
+ },
+ [0xA3B5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B5,
+ },
+ [0xA3B6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B6,
+ },
+ [0xA3B7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B7,
+ },
+ [0xA3B8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B8,
+ },
+ [0xA3B9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3B9,
+ },
+ [0xA3BA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BA,
+ },
+ [0xA3BB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BB,
+ },
+ [0xA3BC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BC,
+ },
+ [0xA3BD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BD,
+ },
+ [0xA3BE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BE,
+ },
+ [0xA3BF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3BF,
+ },
+ [0xA3C0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C0,
+ },
+ [0xA3C1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C1,
+ },
+ [0xA3C2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C2,
+ },
+ [0xA3C3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C3,
+ },
+ [0xA3C4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C4,
+ },
+ [0xA3C5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE SHYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C5,
+ },
+ [0xA3C6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RAT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C6,
+ },
+ [0xA3C7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RAX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C7,
+ },
+ [0xA3C8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RA",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C8,
+ },
+ [0xA3C9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RAP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3C9,
+ },
+ [0xA3CA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CA,
+ },
+ [0xA3CB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CB,
+ },
+ [0xA3CC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CC,
+ },
+ [0xA3CD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ROT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CD,
+ },
+ [0xA3CE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ROX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CE,
+ },
+ [0xA3CF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3CF,
+ },
+ [0xA3D0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE ROP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D0,
+ },
+ [0xA3D1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE REX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D1,
+ },
+ [0xA3D2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D2,
+ },
+ [0xA3D3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE REP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D3,
+ },
+ [0xA3D4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D4,
+ },
+ [0xA3D5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D5,
+ },
+ [0xA3D6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D6,
+ },
+ [0xA3D7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D7,
+ },
+ [0xA3D8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D8,
+ },
+ [0xA3D9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3D9,
+ },
+ [0xA3DA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DA,
+ },
+ [0xA3DB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DB,
+ },
+ [0xA3DC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DC,
+ },
+ [0xA3DD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DD,
+ },
+ [0xA3DE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DE,
+ },
+ [0xA3DF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE RYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3DF,
+ },
+ [0xA3E0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E0,
+ },
+ [0xA3E1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E1,
+ },
+ [0xA3E2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E2,
+ },
+ [0xA3E3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E3,
+ },
+ [0xA3E4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E4,
+ },
+ [0xA3E5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E5,
+ },
+ [0xA3E6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E6,
+ },
+ [0xA3E7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E7,
+ },
+ [0xA3E8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E8,
+ },
+ [0xA3E9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3E9,
+ },
+ [0xA3EA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3EA,
+ },
+ [0xA3EB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3EB,
+ },
+ [0xA3EC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3EC,
+ },
+ [0xA3ED]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3ED,
+ },
+ [0xA3EE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3EE,
+ },
+ [0xA3EF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3EF,
+ },
+ [0xA3F0]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F0,
+ },
+ [0xA3F1]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F1,
+ },
+ [0xA3F2]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F2,
+ },
+ [0xA3F3]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F3,
+ },
+ [0xA3F4]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F4,
+ },
+ [0xA3F5]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F5,
+ },
+ [0xA3F6]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F6,
+ },
+ [0xA3F7]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F7,
+ },
+ [0xA3F8]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F8,
+ },
+ [0xA3F9]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3F9,
+ },
+ [0xA3FA]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FA,
+ },
+ [0xA3FB]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FB,
+ },
+ [0xA3FC]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FC,
+ },
+ [0xA3FD]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FD,
+ },
+ [0xA3FE]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FE,
+ },
+ [0xA3FF]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA3FF,
+ },
+ [0xA400]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA400,
+ },
+ [0xA401]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA401,
+ },
+ [0xA402]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA402,
+ },
+ [0xA403]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA403,
+ },
+ [0xA404]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA404,
+ },
+ [0xA405]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA405,
+ },
+ [0xA406]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA406,
+ },
+ [0xA407]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA407,
+ },
+ [0xA408]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA408,
+ },
+ [0xA409]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA409,
+ },
+ [0xA40A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40A,
+ },
+ [0xA40B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40B,
+ },
+ [0xA40C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40C,
+ },
+ [0xA40D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40D,
+ },
+ [0xA40E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40E,
+ },
+ [0xA40F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA40F,
+ },
+ [0xA410]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA410,
+ },
+ [0xA411]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA411,
+ },
+ [0xA412]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA412,
+ },
+ [0xA413]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA413,
+ },
+ [0xA414]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA414,
+ },
+ [0xA415]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA415,
+ },
+ [0xA416]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA416,
+ },
+ [0xA417]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE QYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA417,
+ },
+ [0xA418]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA418,
+ },
+ [0xA419]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA419,
+ },
+ [0xA41A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41A,
+ },
+ [0xA41B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41B,
+ },
+ [0xA41C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41C,
+ },
+ [0xA41D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41D,
+ },
+ [0xA41E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41E,
+ },
+ [0xA41F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA41F,
+ },
+ [0xA420]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA420,
+ },
+ [0xA421]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA421,
+ },
+ [0xA422]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA422,
+ },
+ [0xA423]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA423,
+ },
+ [0xA424]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA424,
+ },
+ [0xA425]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA425,
+ },
+ [0xA426]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA426,
+ },
+ [0xA427]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA427,
+ },
+ [0xA428]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA428,
+ },
+ [0xA429]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA429,
+ },
+ [0xA42A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42A,
+ },
+ [0xA42B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42B,
+ },
+ [0xA42C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42C,
+ },
+ [0xA42D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42D,
+ },
+ [0xA42E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42E,
+ },
+ [0xA42F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA42F,
+ },
+ [0xA430]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE JJYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA430,
+ },
+ [0xA431]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA431,
+ },
+ [0xA432]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA432,
+ },
+ [0xA433]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA433,
+ },
+ [0xA434]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA434,
+ },
+ [0xA435]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA435,
+ },
+ [0xA436]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA436,
+ },
+ [0xA437]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA437,
+ },
+ [0xA438]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA438,
+ },
+ [0xA439]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA439,
+ },
+ [0xA43A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43A,
+ },
+ [0xA43B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43B,
+ },
+ [0xA43C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43C,
+ },
+ [0xA43D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43D,
+ },
+ [0xA43E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43E,
+ },
+ [0xA43F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA43F,
+ },
+ [0xA440]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA440,
+ },
+ [0xA441]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA441,
+ },
+ [0xA442]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA442,
+ },
+ [0xA443]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA443,
+ },
+ [0xA444]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA444,
+ },
+ [0xA445]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA445,
+ },
+ [0xA446]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA446,
+ },
+ [0xA447]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA447,
+ },
+ [0xA448]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA448,
+ },
+ [0xA449]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NJYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA449,
+ },
+ [0xA44A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44A,
+ },
+ [0xA44B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44B,
+ },
+ [0xA44C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44C,
+ },
+ [0xA44D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44D,
+ },
+ [0xA44E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44E,
+ },
+ [0xA44F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA44F,
+ },
+ [0xA450]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA450,
+ },
+ [0xA451]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA451,
+ },
+ [0xA452]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA452,
+ },
+ [0xA453]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA453,
+ },
+ [0xA454]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA454,
+ },
+ [0xA455]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA455,
+ },
+ [0xA456]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA456,
+ },
+ [0xA457]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA457,
+ },
+ [0xA458]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA458,
+ },
+ [0xA459]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA459,
+ },
+ [0xA45A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45A,
+ },
+ [0xA45B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45B,
+ },
+ [0xA45C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE NYUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45C,
+ },
+ [0xA45D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45D,
+ },
+ [0xA45E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45E,
+ },
+ [0xA45F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA45F,
+ },
+ [0xA460]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA460,
+ },
+ [0xA461]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA461,
+ },
+ [0xA462]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA462,
+ },
+ [0xA463]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA463,
+ },
+ [0xA464]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA464,
+ },
+ [0xA465]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA465,
+ },
+ [0xA466]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA466,
+ },
+ [0xA467]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA467,
+ },
+ [0xA468]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA468,
+ },
+ [0xA469]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA469,
+ },
+ [0xA46A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46A,
+ },
+ [0xA46B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46B,
+ },
+ [0xA46C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46C,
+ },
+ [0xA46D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46D,
+ },
+ [0xA46E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46E,
+ },
+ [0xA46F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA46F,
+ },
+ [0xA470]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE XYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA470,
+ },
+ [0xA471]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA471,
+ },
+ [0xA472]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA472,
+ },
+ [0xA473]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YI",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA473,
+ },
+ [0xA474]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA474,
+ },
+ [0xA475]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIET",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA475,
+ },
+ [0xA476]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIEX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA476,
+ },
+ [0xA477]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA477,
+ },
+ [0xA478]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YIEP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA478,
+ },
+ [0xA479]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA479,
+ },
+ [0xA47A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47A,
+ },
+ [0xA47B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47B,
+ },
+ [0xA47C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47C,
+ },
+ [0xA47D]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YOT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47D,
+ },
+ [0xA47E]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YOX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47E,
+ },
+ [0xA47F]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YO",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA47F,
+ },
+ [0xA480]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YOP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA480,
+ },
+ [0xA481]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA481,
+ },
+ [0xA482]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA482,
+ },
+ [0xA483]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YU",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA483,
+ },
+ [0xA484]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA484,
+ },
+ [0xA485]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YURX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA485,
+ },
+ [0xA486]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YUR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA486,
+ },
+ [0xA487]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YYT",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA487,
+ },
+ [0xA488]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YYX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA488,
+ },
+ [0xA489]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA489,
+ },
+ [0xA48A]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YYP",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA48A,
+ },
+ [0xA48B]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YYRX",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA48B,
+ },
+ [0xA48C]={
+ category="lo",
+ cjkwd="w",
+ description="YI SYLLABLE YYR",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xA48C,
+ },
+ [0xA490]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL QOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA490,
+ },
+ [0xA491]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL LI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA491,
+ },
+ [0xA492]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL KIT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA492,
+ },
+ [0xA493]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL NYIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA493,
+ },
+ [0xA494]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CYP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA494,
+ },
+ [0xA495]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL SSI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA495,
+ },
+ [0xA496]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL GGOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA496,
+ },
+ [0xA497]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL GEP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA497,
+ },
+ [0xA498]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL MI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA498,
+ },
+ [0xA499]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL HXIT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA499,
+ },
+ [0xA49A]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL LYR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49A,
+ },
+ [0xA49B]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL BBUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49B,
+ },
+ [0xA49C]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL MOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49C,
+ },
+ [0xA49D]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL YO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49D,
+ },
+ [0xA49E]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL PUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49E,
+ },
+ [0xA49F]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL HXUO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA49F,
+ },
+ [0xA4A0]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL TAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A0,
+ },
+ [0xA4A1]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL GA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A1,
+ },
+ [0xA4A2]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL ZUP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A2,
+ },
+ [0xA4A3]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CYT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A3,
+ },
+ [0xA4A4]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL DDUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A4,
+ },
+ [0xA4A5]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL BUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A5,
+ },
+ [0xA4A6]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL GGUO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A6,
+ },
+ [0xA4A7]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL NYOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A7,
+ },
+ [0xA4A8]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL TU",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A8,
+ },
+ [0xA4A9]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL OP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4A9,
+ },
+ [0xA4AA]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL JJUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AA,
+ },
+ [0xA4AB]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL ZOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AB,
+ },
+ [0xA4AC]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL PYT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AC,
+ },
+ [0xA4AD]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL HMO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AD,
+ },
+ [0xA4AE]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL YIT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AE,
+ },
+ [0xA4AF]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL VUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4AF,
+ },
+ [0xA4B0]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL SHY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B0,
+ },
+ [0xA4B1]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL VEP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B1,
+ },
+ [0xA4B2]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL ZA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B2,
+ },
+ [0xA4B3]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL JO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B3,
+ },
+ [0xA4B4]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL NZUP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B4,
+ },
+ [0xA4B5]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL JJY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B5,
+ },
+ [0xA4B6]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL GOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B6,
+ },
+ [0xA4B7]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL JJIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B7,
+ },
+ [0xA4B8]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL WO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B8,
+ },
+ [0xA4B9]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL DU",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4B9,
+ },
+ [0xA4BA]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL SHUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BA,
+ },
+ [0xA4BB]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL LIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BB,
+ },
+ [0xA4BC]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BC,
+ },
+ [0xA4BD]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CUOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BD,
+ },
+ [0xA4BE]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BE,
+ },
+ [0xA4BF]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL HXOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4BF,
+ },
+ [0xA4C0]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL SHAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C0,
+ },
+ [0xA4C1]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL ZUR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C1,
+ },
+ [0xA4C2]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL SHOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C2,
+ },
+ [0xA4C3]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL CHE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C3,
+ },
+ [0xA4C4]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL ZZIET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C4,
+ },
+ [0xA4C5]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL NBIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C5,
+ },
+ [0xA4C6]={
+ category="so",
+ cjkwd="w",
+ description="YI RADICAL KE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xA4C6,
+ },
+ [0xA4D0]={
+ category="lo",
+ description="LISU LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D0,
+ },
+ [0xA4D1]={
+ category="lo",
+ description="LISU LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D1,
+ },
+ [0xA4D2]={
+ category="lo",
+ description="LISU LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D2,
+ },
+ [0xA4D3]={
+ category="lo",
+ description="LISU LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D3,
+ },
+ [0xA4D4]={
+ category="lo",
+ description="LISU LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D4,
+ },
+ [0xA4D5]={
+ category="lo",
+ description="LISU LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D5,
+ },
+ [0xA4D6]={
+ category="lo",
+ description="LISU LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D6,
+ },
+ [0xA4D7]={
+ category="lo",
+ description="LISU LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D7,
+ },
+ [0xA4D8]={
+ category="lo",
+ description="LISU LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D8,
+ },
+ [0xA4D9]={
+ category="lo",
+ description="LISU LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D9,
+ },
+ [0xA4DA]={
+ category="lo",
+ description="LISU LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DA,
+ },
+ [0xA4DB]={
+ category="lo",
+ description="LISU LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DB,
+ },
+ [0xA4DC]={
+ category="lo",
+ description="LISU LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DC,
+ },
+ [0xA4DD]={
+ category="lo",
+ description="LISU LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DD,
+ },
+ [0xA4DE]={
+ category="lo",
+ description="LISU LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DE,
+ },
+ [0xA4DF]={
+ category="lo",
+ description="LISU LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DF,
+ },
+ [0xA4E0]={
+ category="lo",
+ description="LISU LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E0,
+ },
+ [0xA4E1]={
+ category="lo",
+ description="LISU LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E1,
+ },
+ [0xA4E2]={
+ category="lo",
+ description="LISU LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E2,
+ },
+ [0xA4E3]={
+ category="lo",
+ description="LISU LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E3,
+ },
+ [0xA4E4]={
+ category="lo",
+ description="LISU LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E4,
+ },
+ [0xA4E5]={
+ category="lo",
+ description="LISU LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E5,
+ },
+ [0xA4E6]={
+ category="lo",
+ description="LISU LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E6,
+ },
+ [0xA4E7]={
+ category="lo",
+ description="LISU LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E7,
+ },
+ [0xA4E8]={
+ category="lo",
+ description="LISU LETTER HHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E8,
+ },
+ [0xA4E9]={
+ category="lo",
+ description="LISU LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E9,
+ },
+ [0xA4EA]={
+ category="lo",
+ description="LISU LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EA,
+ },
+ [0xA4EB]={
+ category="lo",
+ description="LISU LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EB,
+ },
+ [0xA4EC]={
+ category="lo",
+ description="LISU LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EC,
+ },
+ [0xA4ED]={
+ category="lo",
+ description="LISU LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4ED,
+ },
+ [0xA4EE]={
+ category="lo",
+ description="LISU LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EE,
+ },
+ [0xA4EF]={
+ category="lo",
+ description="LISU LETTER AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EF,
+ },
+ [0xA4F0]={
+ category="lo",
+ description="LISU LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F0,
+ },
+ [0xA4F1]={
+ category="lo",
+ description="LISU LETTER EU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F1,
+ },
+ [0xA4F2]={
+ category="lo",
+ description="LISU LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F2,
+ },
+ [0xA4F3]={
+ category="lo",
+ description="LISU LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F3,
+ },
+ [0xA4F4]={
+ category="lo",
+ description="LISU LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F4,
+ },
+ [0xA4F5]={
+ category="lo",
+ description="LISU LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F5,
+ },
+ [0xA4F6]={
+ category="lo",
+ description="LISU LETTER UH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F6,
+ },
+ [0xA4F7]={
+ category="lo",
+ description="LISU LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F7,
+ },
+ [0xA4F8]={
+ category="lm",
+ description="LISU LETTER TONE MYA TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F8,
+ },
+ [0xA4F9]={
+ category="lm",
+ description="LISU LETTER TONE NA PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F9,
+ },
+ [0xA4FA]={
+ category="lm",
+ description="LISU LETTER TONE MYA CYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FA,
+ },
+ [0xA4FB]={
+ category="lm",
+ description="LISU LETTER TONE MYA BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FB,
+ },
+ [0xA4FC]={
+ category="lm",
+ description="LISU LETTER TONE MYA NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FC,
+ },
+ [0xA4FD]={
+ category="lm",
+ description="LISU LETTER TONE MYA JEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FD,
+ },
+ [0xA4FE]={
+ category="po",
+ description="LISU PUNCTUATION COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA4FE,
+ },
+ [0xA4FF]={
+ category="po",
+ description="LISU PUNCTUATION FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA4FF,
+ },
+ [0xA500]={
+ category="lo",
+ description="VAI SYLLABLE EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA500,
+ },
+ [0xA501]={
+ category="lo",
+ description="VAI SYLLABLE EEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA501,
+ },
+ [0xA502]={
+ category="lo",
+ description="VAI SYLLABLE HEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA502,
+ },
+ [0xA503]={
+ category="lo",
+ description="VAI SYLLABLE WEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA503,
+ },
+ [0xA504]={
+ category="lo",
+ description="VAI SYLLABLE WEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA504,
+ },
+ [0xA505]={
+ category="lo",
+ description="VAI SYLLABLE PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA505,
+ },
+ [0xA506]={
+ category="lo",
+ description="VAI SYLLABLE BHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA506,
+ },
+ [0xA507]={
+ category="lo",
+ description="VAI SYLLABLE BEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA507,
+ },
+ [0xA508]={
+ category="lo",
+ description="VAI SYLLABLE MBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA508,
+ },
+ [0xA509]={
+ category="lo",
+ description="VAI SYLLABLE KPEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA509,
+ },
+ [0xA50A]={
+ category="lo",
+ description="VAI SYLLABLE MGBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50A,
+ },
+ [0xA50B]={
+ category="lo",
+ description="VAI SYLLABLE GBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50B,
+ },
+ [0xA50C]={
+ category="lo",
+ description="VAI SYLLABLE FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50C,
+ },
+ [0xA50D]={
+ category="lo",
+ description="VAI SYLLABLE VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50D,
+ },
+ [0xA50E]={
+ category="lo",
+ description="VAI SYLLABLE TEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50E,
+ },
+ [0xA50F]={
+ category="lo",
+ description="VAI SYLLABLE THEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50F,
+ },
+ [0xA510]={
+ category="lo",
+ description="VAI SYLLABLE DHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA510,
+ },
+ [0xA511]={
+ category="lo",
+ description="VAI SYLLABLE DHHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA511,
+ },
+ [0xA512]={
+ category="lo",
+ description="VAI SYLLABLE LEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA512,
+ },
+ [0xA513]={
+ category="lo",
+ description="VAI SYLLABLE REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA513,
+ },
+ [0xA514]={
+ category="lo",
+ description="VAI SYLLABLE DEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA514,
+ },
+ [0xA515]={
+ category="lo",
+ description="VAI SYLLABLE NDEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA515,
+ },
+ [0xA516]={
+ category="lo",
+ description="VAI SYLLABLE SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA516,
+ },
+ [0xA517]={
+ category="lo",
+ description="VAI SYLLABLE SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA517,
+ },
+ [0xA518]={
+ category="lo",
+ description="VAI SYLLABLE ZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA518,
+ },
+ [0xA519]={
+ category="lo",
+ description="VAI SYLLABLE ZHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA519,
+ },
+ [0xA51A]={
+ category="lo",
+ description="VAI SYLLABLE CEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51A,
+ },
+ [0xA51B]={
+ category="lo",
+ description="VAI SYLLABLE JEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51B,
+ },
+ [0xA51C]={
+ category="lo",
+ description="VAI SYLLABLE NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51C,
+ },
+ [0xA51D]={
+ category="lo",
+ description="VAI SYLLABLE YEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51D,
+ },
+ [0xA51E]={
+ category="lo",
+ description="VAI SYLLABLE KEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51E,
+ },
+ [0xA51F]={
+ category="lo",
+ description="VAI SYLLABLE NGGEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51F,
+ },
+ [0xA520]={
+ category="lo",
+ description="VAI SYLLABLE GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA520,
+ },
+ [0xA521]={
+ category="lo",
+ description="VAI SYLLABLE MEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA521,
+ },
+ [0xA522]={
+ category="lo",
+ description="VAI SYLLABLE NEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA522,
+ },
+ [0xA523]={
+ category="lo",
+ description="VAI SYLLABLE NYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA523,
+ },
+ [0xA524]={
+ category="lo",
+ description="VAI SYLLABLE I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA524,
+ },
+ [0xA525]={
+ category="lo",
+ description="VAI SYLLABLE IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA525,
+ },
+ [0xA526]={
+ category="lo",
+ description="VAI SYLLABLE HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA526,
+ },
+ [0xA527]={
+ category="lo",
+ description="VAI SYLLABLE HIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA527,
+ },
+ [0xA528]={
+ category="lo",
+ description="VAI SYLLABLE WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA528,
+ },
+ [0xA529]={
+ category="lo",
+ description="VAI SYLLABLE WIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA529,
+ },
+ [0xA52A]={
+ category="lo",
+ description="VAI SYLLABLE PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52A,
+ },
+ [0xA52B]={
+ category="lo",
+ description="VAI SYLLABLE BHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52B,
+ },
+ [0xA52C]={
+ category="lo",
+ description="VAI SYLLABLE BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52C,
+ },
+ [0xA52D]={
+ category="lo",
+ description="VAI SYLLABLE MBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52D,
+ },
+ [0xA52E]={
+ category="lo",
+ description="VAI SYLLABLE KPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52E,
+ },
+ [0xA52F]={
+ category="lo",
+ description="VAI SYLLABLE MGBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52F,
+ },
+ [0xA530]={
+ category="lo",
+ description="VAI SYLLABLE GBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA530,
+ },
+ [0xA531]={
+ category="lo",
+ description="VAI SYLLABLE FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA531,
+ },
+ [0xA532]={
+ category="lo",
+ description="VAI SYLLABLE VI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA532,
+ },
+ [0xA533]={
+ category="lo",
+ description="VAI SYLLABLE TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA533,
+ },
+ [0xA534]={
+ category="lo",
+ description="VAI SYLLABLE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA534,
+ },
+ [0xA535]={
+ category="lo",
+ description="VAI SYLLABLE DHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA535,
+ },
+ [0xA536]={
+ category="lo",
+ description="VAI SYLLABLE DHHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA536,
+ },
+ [0xA537]={
+ category="lo",
+ description="VAI SYLLABLE LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA537,
+ },
+ [0xA538]={
+ category="lo",
+ description="VAI SYLLABLE RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA538,
+ },
+ [0xA539]={
+ category="lo",
+ description="VAI SYLLABLE DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA539,
+ },
+ [0xA53A]={
+ category="lo",
+ description="VAI SYLLABLE NDI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53A,
+ },
+ [0xA53B]={
+ category="lo",
+ description="VAI SYLLABLE SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53B,
+ },
+ [0xA53C]={
+ category="lo",
+ description="VAI SYLLABLE SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53C,
+ },
+ [0xA53D]={
+ category="lo",
+ description="VAI SYLLABLE ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53D,
+ },
+ [0xA53E]={
+ category="lo",
+ description="VAI SYLLABLE ZHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53E,
+ },
+ [0xA53F]={
+ category="lo",
+ description="VAI SYLLABLE CI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53F,
+ },
+ [0xA540]={
+ category="lo",
+ description="VAI SYLLABLE JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA540,
+ },
+ [0xA541]={
+ category="lo",
+ description="VAI SYLLABLE NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA541,
+ },
+ [0xA542]={
+ category="lo",
+ description="VAI SYLLABLE YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA542,
+ },
+ [0xA543]={
+ category="lo",
+ description="VAI SYLLABLE KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA543,
+ },
+ [0xA544]={
+ category="lo",
+ description="VAI SYLLABLE NGGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA544,
+ },
+ [0xA545]={
+ category="lo",
+ description="VAI SYLLABLE GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA545,
+ },
+ [0xA546]={
+ category="lo",
+ description="VAI SYLLABLE MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA546,
+ },
+ [0xA547]={
+ category="lo",
+ description="VAI SYLLABLE NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA547,
+ },
+ [0xA548]={
+ category="lo",
+ description="VAI SYLLABLE NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA548,
+ },
+ [0xA549]={
+ category="lo",
+ description="VAI SYLLABLE A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA549,
+ },
+ [0xA54A]={
+ category="lo",
+ description="VAI SYLLABLE AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54A,
+ },
+ [0xA54B]={
+ category="lo",
+ description="VAI SYLLABLE NGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54B,
+ },
+ [0xA54C]={
+ category="lo",
+ description="VAI SYLLABLE HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54C,
+ },
+ [0xA54D]={
+ category="lo",
+ description="VAI SYLLABLE HAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54D,
+ },
+ [0xA54E]={
+ category="lo",
+ description="VAI SYLLABLE WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54E,
+ },
+ [0xA54F]={
+ category="lo",
+ description="VAI SYLLABLE WAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54F,
+ },
+ [0xA550]={
+ category="lo",
+ description="VAI SYLLABLE PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA550,
+ },
+ [0xA551]={
+ category="lo",
+ description="VAI SYLLABLE BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA551,
+ },
+ [0xA552]={
+ category="lo",
+ description="VAI SYLLABLE BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA552,
+ },
+ [0xA553]={
+ category="lo",
+ description="VAI SYLLABLE MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA553,
+ },
+ [0xA554]={
+ category="lo",
+ description="VAI SYLLABLE KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA554,
+ },
+ [0xA555]={
+ category="lo",
+ description="VAI SYLLABLE KPAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA555,
+ },
+ [0xA556]={
+ category="lo",
+ description="VAI SYLLABLE MGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA556,
+ },
+ [0xA557]={
+ category="lo",
+ description="VAI SYLLABLE GBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA557,
+ },
+ [0xA558]={
+ category="lo",
+ description="VAI SYLLABLE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA558,
+ },
+ [0xA559]={
+ category="lo",
+ description="VAI SYLLABLE VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA559,
+ },
+ [0xA55A]={
+ category="lo",
+ description="VAI SYLLABLE TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55A,
+ },
+ [0xA55B]={
+ category="lo",
+ description="VAI SYLLABLE THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55B,
+ },
+ [0xA55C]={
+ category="lo",
+ description="VAI SYLLABLE DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55C,
+ },
+ [0xA55D]={
+ category="lo",
+ description="VAI SYLLABLE DHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55D,
+ },
+ [0xA55E]={
+ category="lo",
+ description="VAI SYLLABLE LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55E,
+ },
+ [0xA55F]={
+ category="lo",
+ description="VAI SYLLABLE RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55F,
+ },
+ [0xA560]={
+ category="lo",
+ description="VAI SYLLABLE DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA560,
+ },
+ [0xA561]={
+ category="lo",
+ description="VAI SYLLABLE NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA561,
+ },
+ [0xA562]={
+ category="lo",
+ description="VAI SYLLABLE SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA562,
+ },
+ [0xA563]={
+ category="lo",
+ description="VAI SYLLABLE SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA563,
+ },
+ [0xA564]={
+ category="lo",
+ description="VAI SYLLABLE ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA564,
+ },
+ [0xA565]={
+ category="lo",
+ description="VAI SYLLABLE ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA565,
+ },
+ [0xA566]={
+ category="lo",
+ description="VAI SYLLABLE CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA566,
+ },
+ [0xA567]={
+ category="lo",
+ description="VAI SYLLABLE JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA567,
+ },
+ [0xA568]={
+ category="lo",
+ description="VAI SYLLABLE NJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA568,
+ },
+ [0xA569]={
+ category="lo",
+ description="VAI SYLLABLE YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA569,
+ },
+ [0xA56A]={
+ category="lo",
+ description="VAI SYLLABLE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56A,
+ },
+ [0xA56B]={
+ category="lo",
+ description="VAI SYLLABLE KAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56B,
+ },
+ [0xA56C]={
+ category="lo",
+ description="VAI SYLLABLE NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56C,
+ },
+ [0xA56D]={
+ category="lo",
+ description="VAI SYLLABLE GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56D,
+ },
+ [0xA56E]={
+ category="lo",
+ description="VAI SYLLABLE MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56E,
+ },
+ [0xA56F]={
+ category="lo",
+ description="VAI SYLLABLE NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56F,
+ },
+ [0xA570]={
+ category="lo",
+ description="VAI SYLLABLE NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA570,
+ },
+ [0xA571]={
+ category="lo",
+ description="VAI SYLLABLE OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA571,
+ },
+ [0xA572]={
+ category="lo",
+ description="VAI SYLLABLE OON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA572,
+ },
+ [0xA573]={
+ category="lo",
+ description="VAI SYLLABLE HOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA573,
+ },
+ [0xA574]={
+ category="lo",
+ description="VAI SYLLABLE WOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA574,
+ },
+ [0xA575]={
+ category="lo",
+ description="VAI SYLLABLE WOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA575,
+ },
+ [0xA576]={
+ category="lo",
+ description="VAI SYLLABLE POO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA576,
+ },
+ [0xA577]={
+ category="lo",
+ description="VAI SYLLABLE BHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA577,
+ },
+ [0xA578]={
+ category="lo",
+ description="VAI SYLLABLE BOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA578,
+ },
+ [0xA579]={
+ category="lo",
+ description="VAI SYLLABLE MBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA579,
+ },
+ [0xA57A]={
+ category="lo",
+ description="VAI SYLLABLE KPOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57A,
+ },
+ [0xA57B]={
+ category="lo",
+ description="VAI SYLLABLE MGBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57B,
+ },
+ [0xA57C]={
+ category="lo",
+ description="VAI SYLLABLE GBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57C,
+ },
+ [0xA57D]={
+ category="lo",
+ description="VAI SYLLABLE FOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57D,
+ },
+ [0xA57E]={
+ category="lo",
+ description="VAI SYLLABLE VOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57E,
+ },
+ [0xA57F]={
+ category="lo",
+ description="VAI SYLLABLE TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57F,
+ },
+ [0xA580]={
+ category="lo",
+ description="VAI SYLLABLE THOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA580,
+ },
+ [0xA581]={
+ category="lo",
+ description="VAI SYLLABLE DHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA581,
+ },
+ [0xA582]={
+ category="lo",
+ description="VAI SYLLABLE DHHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA582,
+ },
+ [0xA583]={
+ category="lo",
+ description="VAI SYLLABLE LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA583,
+ },
+ [0xA584]={
+ category="lo",
+ description="VAI SYLLABLE ROO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA584,
+ },
+ [0xA585]={
+ category="lo",
+ description="VAI SYLLABLE DOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA585,
+ },
+ [0xA586]={
+ category="lo",
+ description="VAI SYLLABLE NDOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA586,
+ },
+ [0xA587]={
+ category="lo",
+ description="VAI SYLLABLE SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA587,
+ },
+ [0xA588]={
+ category="lo",
+ description="VAI SYLLABLE SHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA588,
+ },
+ [0xA589]={
+ category="lo",
+ description="VAI SYLLABLE ZOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA589,
+ },
+ [0xA58A]={
+ category="lo",
+ description="VAI SYLLABLE ZHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58A,
+ },
+ [0xA58B]={
+ category="lo",
+ description="VAI SYLLABLE COO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58B,
+ },
+ [0xA58C]={
+ category="lo",
+ description="VAI SYLLABLE JOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58C,
+ },
+ [0xA58D]={
+ category="lo",
+ description="VAI SYLLABLE NJOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58D,
+ },
+ [0xA58E]={
+ category="lo",
+ description="VAI SYLLABLE YOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58E,
+ },
+ [0xA58F]={
+ category="lo",
+ description="VAI SYLLABLE KOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58F,
+ },
+ [0xA590]={
+ category="lo",
+ description="VAI SYLLABLE NGGOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA590,
+ },
+ [0xA591]={
+ category="lo",
+ description="VAI SYLLABLE GOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA591,
+ },
+ [0xA592]={
+ category="lo",
+ description="VAI SYLLABLE MOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA592,
+ },
+ [0xA593]={
+ category="lo",
+ description="VAI SYLLABLE NOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA593,
+ },
+ [0xA594]={
+ category="lo",
+ description="VAI SYLLABLE NYOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA594,
+ },
+ [0xA595]={
+ category="lo",
+ description="VAI SYLLABLE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA595,
+ },
+ [0xA596]={
+ category="lo",
+ description="VAI SYLLABLE UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA596,
+ },
+ [0xA597]={
+ category="lo",
+ description="VAI SYLLABLE HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA597,
+ },
+ [0xA598]={
+ category="lo",
+ description="VAI SYLLABLE HUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA598,
+ },
+ [0xA599]={
+ category="lo",
+ description="VAI SYLLABLE WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA599,
+ },
+ [0xA59A]={
+ category="lo",
+ description="VAI SYLLABLE WUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59A,
+ },
+ [0xA59B]={
+ category="lo",
+ description="VAI SYLLABLE PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59B,
+ },
+ [0xA59C]={
+ category="lo",
+ description="VAI SYLLABLE BHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59C,
+ },
+ [0xA59D]={
+ category="lo",
+ description="VAI SYLLABLE BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59D,
+ },
+ [0xA59E]={
+ category="lo",
+ description="VAI SYLLABLE MBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59E,
+ },
+ [0xA59F]={
+ category="lo",
+ description="VAI SYLLABLE KPU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59F,
+ },
+ [0xA5A0]={
+ category="lo",
+ description="VAI SYLLABLE MGBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A0,
+ },
+ [0xA5A1]={
+ category="lo",
+ description="VAI SYLLABLE GBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A1,
+ },
+ [0xA5A2]={
+ category="lo",
+ description="VAI SYLLABLE FU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A2,
+ },
+ [0xA5A3]={
+ category="lo",
+ description="VAI SYLLABLE VU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A3,
+ },
+ [0xA5A4]={
+ category="lo",
+ description="VAI SYLLABLE TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A4,
+ },
+ [0xA5A5]={
+ category="lo",
+ description="VAI SYLLABLE THU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A5,
+ },
+ [0xA5A6]={
+ category="lo",
+ description="VAI SYLLABLE DHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A6,
+ },
+ [0xA5A7]={
+ category="lo",
+ description="VAI SYLLABLE DHHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A7,
+ },
+ [0xA5A8]={
+ category="lo",
+ description="VAI SYLLABLE LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A8,
+ },
+ [0xA5A9]={
+ category="lo",
+ description="VAI SYLLABLE RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A9,
+ },
+ [0xA5AA]={
+ category="lo",
+ description="VAI SYLLABLE DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AA,
+ },
+ [0xA5AB]={
+ category="lo",
+ description="VAI SYLLABLE NDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AB,
+ },
+ [0xA5AC]={
+ category="lo",
+ description="VAI SYLLABLE SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AC,
+ },
+ [0xA5AD]={
+ category="lo",
+ description="VAI SYLLABLE SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AD,
+ },
+ [0xA5AE]={
+ category="lo",
+ description="VAI SYLLABLE ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AE,
+ },
+ [0xA5AF]={
+ category="lo",
+ description="VAI SYLLABLE ZHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AF,
+ },
+ [0xA5B0]={
+ category="lo",
+ description="VAI SYLLABLE CU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B0,
+ },
+ [0xA5B1]={
+ category="lo",
+ description="VAI SYLLABLE JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B1,
+ },
+ [0xA5B2]={
+ category="lo",
+ description="VAI SYLLABLE NJU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B2,
+ },
+ [0xA5B3]={
+ category="lo",
+ description="VAI SYLLABLE YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B3,
+ },
+ [0xA5B4]={
+ category="lo",
+ description="VAI SYLLABLE KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B4,
+ },
+ [0xA5B5]={
+ category="lo",
+ description="VAI SYLLABLE NGGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B5,
+ },
+ [0xA5B6]={
+ category="lo",
+ description="VAI SYLLABLE GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B6,
+ },
+ [0xA5B7]={
+ category="lo",
+ description="VAI SYLLABLE MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B7,
+ },
+ [0xA5B8]={
+ category="lo",
+ description="VAI SYLLABLE NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B8,
+ },
+ [0xA5B9]={
+ category="lo",
+ description="VAI SYLLABLE NYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B9,
+ },
+ [0xA5BA]={
+ category="lo",
+ description="VAI SYLLABLE O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BA,
+ },
+ [0xA5BB]={
+ category="lo",
+ description="VAI SYLLABLE ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BB,
+ },
+ [0xA5BC]={
+ category="lo",
+ description="VAI SYLLABLE NGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BC,
+ },
+ [0xA5BD]={
+ category="lo",
+ description="VAI SYLLABLE HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BD,
+ },
+ [0xA5BE]={
+ category="lo",
+ description="VAI SYLLABLE HON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BE,
+ },
+ [0xA5BF]={
+ category="lo",
+ description="VAI SYLLABLE WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BF,
+ },
+ [0xA5C0]={
+ category="lo",
+ description="VAI SYLLABLE WON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C0,
+ },
+ [0xA5C1]={
+ category="lo",
+ description="VAI SYLLABLE PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C1,
+ },
+ [0xA5C2]={
+ category="lo",
+ description="VAI SYLLABLE BHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C2,
+ },
+ [0xA5C3]={
+ category="lo",
+ description="VAI SYLLABLE BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C3,
+ },
+ [0xA5C4]={
+ category="lo",
+ description="VAI SYLLABLE MBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C4,
+ },
+ [0xA5C5]={
+ category="lo",
+ description="VAI SYLLABLE KPO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C5,
+ },
+ [0xA5C6]={
+ category="lo",
+ description="VAI SYLLABLE MGBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C6,
+ },
+ [0xA5C7]={
+ category="lo",
+ description="VAI SYLLABLE GBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C7,
+ },
+ [0xA5C8]={
+ category="lo",
+ description="VAI SYLLABLE GBON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C8,
+ },
+ [0xA5C9]={
+ category="lo",
+ description="VAI SYLLABLE FO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C9,
+ },
+ [0xA5CA]={
+ category="lo",
+ description="VAI SYLLABLE VO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CA,
+ },
+ [0xA5CB]={
+ category="lo",
+ description="VAI SYLLABLE TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CB,
+ },
+ [0xA5CC]={
+ category="lo",
+ description="VAI SYLLABLE THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CC,
+ },
+ [0xA5CD]={
+ category="lo",
+ description="VAI SYLLABLE DHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CD,
+ },
+ [0xA5CE]={
+ category="lo",
+ description="VAI SYLLABLE DHHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CE,
+ },
+ [0xA5CF]={
+ category="lo",
+ description="VAI SYLLABLE LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CF,
+ },
+ [0xA5D0]={
+ category="lo",
+ description="VAI SYLLABLE RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D0,
+ },
+ [0xA5D1]={
+ category="lo",
+ description="VAI SYLLABLE DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D1,
+ },
+ [0xA5D2]={
+ category="lo",
+ description="VAI SYLLABLE NDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D2,
+ },
+ [0xA5D3]={
+ category="lo",
+ description="VAI SYLLABLE SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D3,
+ },
+ [0xA5D4]={
+ category="lo",
+ description="VAI SYLLABLE SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D4,
+ },
+ [0xA5D5]={
+ category="lo",
+ description="VAI SYLLABLE ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D5,
+ },
+ [0xA5D6]={
+ category="lo",
+ description="VAI SYLLABLE ZHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D6,
+ },
+ [0xA5D7]={
+ category="lo",
+ description="VAI SYLLABLE CO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D7,
+ },
+ [0xA5D8]={
+ category="lo",
+ description="VAI SYLLABLE JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D8,
+ },
+ [0xA5D9]={
+ category="lo",
+ description="VAI SYLLABLE NJO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D9,
+ },
+ [0xA5DA]={
+ category="lo",
+ description="VAI SYLLABLE YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DA,
+ },
+ [0xA5DB]={
+ category="lo",
+ description="VAI SYLLABLE KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DB,
+ },
+ [0xA5DC]={
+ category="lo",
+ description="VAI SYLLABLE NGGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DC,
+ },
+ [0xA5DD]={
+ category="lo",
+ description="VAI SYLLABLE GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DD,
+ },
+ [0xA5DE]={
+ category="lo",
+ description="VAI SYLLABLE MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DE,
+ },
+ [0xA5DF]={
+ category="lo",
+ description="VAI SYLLABLE NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DF,
+ },
+ [0xA5E0]={
+ category="lo",
+ description="VAI SYLLABLE NYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E0,
+ },
+ [0xA5E1]={
+ category="lo",
+ description="VAI SYLLABLE E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E1,
+ },
+ [0xA5E2]={
+ category="lo",
+ description="VAI SYLLABLE EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E2,
+ },
+ [0xA5E3]={
+ category="lo",
+ description="VAI SYLLABLE NGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E3,
+ },
+ [0xA5E4]={
+ category="lo",
+ description="VAI SYLLABLE HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E4,
+ },
+ [0xA5E5]={
+ category="lo",
+ description="VAI SYLLABLE HEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E5,
+ },
+ [0xA5E6]={
+ category="lo",
+ description="VAI SYLLABLE WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E6,
+ },
+ [0xA5E7]={
+ category="lo",
+ description="VAI SYLLABLE WEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E7,
+ },
+ [0xA5E8]={
+ category="lo",
+ description="VAI SYLLABLE PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E8,
+ },
+ [0xA5E9]={
+ category="lo",
+ description="VAI SYLLABLE BHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E9,
+ },
+ [0xA5EA]={
+ category="lo",
+ description="VAI SYLLABLE BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EA,
+ },
+ [0xA5EB]={
+ category="lo",
+ description="VAI SYLLABLE MBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EB,
+ },
+ [0xA5EC]={
+ category="lo",
+ description="VAI SYLLABLE KPE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EC,
+ },
+ [0xA5ED]={
+ category="lo",
+ description="VAI SYLLABLE KPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5ED,
+ },
+ [0xA5EE]={
+ category="lo",
+ description="VAI SYLLABLE MGBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EE,
+ },
+ [0xA5EF]={
+ category="lo",
+ description="VAI SYLLABLE GBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EF,
+ },
+ [0xA5F0]={
+ category="lo",
+ description="VAI SYLLABLE GBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F0,
+ },
+ [0xA5F1]={
+ category="lo",
+ description="VAI SYLLABLE FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F1,
+ },
+ [0xA5F2]={
+ category="lo",
+ description="VAI SYLLABLE VE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F2,
+ },
+ [0xA5F3]={
+ category="lo",
+ description="VAI SYLLABLE TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F3,
+ },
+ [0xA5F4]={
+ category="lo",
+ description="VAI SYLLABLE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F4,
+ },
+ [0xA5F5]={
+ category="lo",
+ description="VAI SYLLABLE DHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F5,
+ },
+ [0xA5F6]={
+ category="lo",
+ description="VAI SYLLABLE DHHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F6,
+ },
+ [0xA5F7]={
+ category="lo",
+ description="VAI SYLLABLE LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F7,
+ },
+ [0xA5F8]={
+ category="lo",
+ description="VAI SYLLABLE RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F8,
+ },
+ [0xA5F9]={
+ category="lo",
+ description="VAI SYLLABLE DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F9,
+ },
+ [0xA5FA]={
+ category="lo",
+ description="VAI SYLLABLE NDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FA,
+ },
+ [0xA5FB]={
+ category="lo",
+ description="VAI SYLLABLE SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FB,
+ },
+ [0xA5FC]={
+ category="lo",
+ description="VAI SYLLABLE SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FC,
+ },
+ [0xA5FD]={
+ category="lo",
+ description="VAI SYLLABLE ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FD,
+ },
+ [0xA5FE]={
+ category="lo",
+ description="VAI SYLLABLE ZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FE,
+ },
+ [0xA5FF]={
+ category="lo",
+ description="VAI SYLLABLE CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FF,
+ },
+ [0xA600]={
+ category="lo",
+ description="VAI SYLLABLE JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA600,
+ },
+ [0xA601]={
+ category="lo",
+ description="VAI SYLLABLE NJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA601,
+ },
+ [0xA602]={
+ category="lo",
+ description="VAI SYLLABLE YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA602,
+ },
+ [0xA603]={
+ category="lo",
+ description="VAI SYLLABLE KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA603,
+ },
+ [0xA604]={
+ category="lo",
+ description="VAI SYLLABLE NGGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA604,
+ },
+ [0xA605]={
+ category="lo",
+ description="VAI SYLLABLE NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA605,
+ },
+ [0xA606]={
+ category="lo",
+ description="VAI SYLLABLE GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA606,
+ },
+ [0xA607]={
+ category="lo",
+ description="VAI SYLLABLE GEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA607,
+ },
+ [0xA608]={
+ category="lo",
+ description="VAI SYLLABLE ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA608,
+ },
+ [0xA609]={
+ category="lo",
+ description="VAI SYLLABLE NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA609,
+ },
+ [0xA60A]={
+ category="lo",
+ description="VAI SYLLABLE NYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60A,
+ },
+ [0xA60B]={
+ category="lo",
+ description="VAI SYLLABLE NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60B,
+ },
+ [0xA60C]={
+ category="lm",
+ description="VAI SYLLABLE LENGTHENER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60C,
+ },
+ [0xA60D]={
+ category="po",
+ description="VAI COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0xA60D,
+ },
+ [0xA60E]={
+ category="po",
+ description="VAI FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0xA60E,
+ },
+ [0xA60F]={
+ category="po",
+ description="VAI QUESTION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0xA60F,
+ },
+ [0xA610]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA610,
+ },
+ [0xA611]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA611,
+ },
+ [0xA612]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA612,
+ },
+ [0xA613]={
+ category="lo",
+ description="VAI SYMBOL FEENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA613,
+ },
+ [0xA614]={
+ category="lo",
+ description="VAI SYMBOL KEENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA614,
+ },
+ [0xA615]={
+ category="lo",
+ description="VAI SYMBOL TING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA615,
+ },
+ [0xA616]={
+ category="lo",
+ description="VAI SYMBOL NII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA616,
+ },
+ [0xA617]={
+ category="lo",
+ description="VAI SYMBOL BANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA617,
+ },
+ [0xA618]={
+ category="lo",
+ description="VAI SYMBOL FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA618,
+ },
+ [0xA619]={
+ category="lo",
+ description="VAI SYMBOL TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA619,
+ },
+ [0xA61A]={
+ category="lo",
+ description="VAI SYMBOL DANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61A,
+ },
+ [0xA61B]={
+ category="lo",
+ description="VAI SYMBOL DOONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61B,
+ },
+ [0xA61C]={
+ category="lo",
+ description="VAI SYMBOL KUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61C,
+ },
+ [0xA61D]={
+ category="lo",
+ description="VAI SYMBOL TONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61D,
+ },
+ [0xA61E]={
+ category="lo",
+ description="VAI SYMBOL DO-O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61E,
+ },
+ [0xA61F]={
+ category="lo",
+ description="VAI SYMBOL JONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61F,
+ },
+ [0xA620]={
+ category="nd",
+ description="VAI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA620,
+ },
+ [0xA621]={
+ category="nd",
+ description="VAI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA621,
+ },
+ [0xA622]={
+ category="nd",
+ description="VAI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA622,
+ },
+ [0xA623]={
+ category="nd",
+ description="VAI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA623,
+ },
+ [0xA624]={
+ category="nd",
+ description="VAI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA624,
+ },
+ [0xA625]={
+ category="nd",
+ description="VAI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA625,
+ },
+ [0xA626]={
+ category="nd",
+ description="VAI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA626,
+ },
+ [0xA627]={
+ category="nd",
+ description="VAI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA627,
+ },
+ [0xA628]={
+ category="nd",
+ description="VAI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA628,
+ },
+ [0xA629]={
+ category="nd",
+ description="VAI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA629,
+ },
+ [0xA62A]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA62A,
+ },
+ [0xA62B]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA62B,
+ },
+ [0xA640]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ZEMLYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA640,
+ },
+ [0xA641]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ZEMLYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA641,
+ },
+ [0xA642]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZELO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA642,
+ },
+ [0xA643]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZELO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA643,
+ },
+ [0xA644]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA644,
+ },
+ [0xA645]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA645,
+ },
+ [0xA646]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA646,
+ },
+ [0xA647]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA647,
+ },
+ [0xA648]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DJERV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA648,
+ },
+ [0xA649]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DJERV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA649,
+ },
+ [0xA64A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER MONOGRAPH UK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64A,
+ },
+ [0xA64B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER MONOGRAPH UK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64B,
+ },
+ [0xA64C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BROAD OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64C,
+ },
+ [0xA64D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BROAD OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64D,
+ },
+ [0xA64E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER NEUTRAL YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64E,
+ },
+ [0xA64F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER NEUTRAL YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64F,
+ },
+ [0xA650]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YERU WITH BACK YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA650,
+ },
+ [0xA651]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YERU WITH BACK YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA651,
+ },
+ [0xA652]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA652,
+ },
+ [0xA653]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA653,
+ },
+ [0xA654]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA654,
+ },
+ [0xA655]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA655,
+ },
+ [0xA656]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA656,
+ },
+ [0xA657]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA657,
+ },
+ [0xA658]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA658,
+ },
+ [0xA659]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA659,
+ },
+ [0xA65A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BLENDED YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65A,
+ },
+ [0xA65B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BLENDED YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65B,
+ },
+ [0xA65C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65C,
+ },
+ [0xA65D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65D,
+ },
+ [0xA65E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65E,
+ },
+ [0xA65F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65F,
+ },
+ [0xA660]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA660,
+ },
+ [0xA661]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA661,
+ },
+ [0xA662]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA662,
+ },
+ [0xA663]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA663,
+ },
+ [0xA664]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA664,
+ },
+ [0xA665]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA665,
+ },
+ [0xA666]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT EM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA666,
+ },
+ [0xA667]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT EM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA667,
+ },
+ [0xA668]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA668,
+ },
+ [0xA669]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA669,
+ },
+ [0xA66A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BINOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66A,
+ },
+ [0xA66B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BINOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66B,
+ },
+ [0xA66C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66C,
+ },
+ [0xA66D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DOUBLE MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66D,
+ },
+ [0xA66E]={
+ category="lo",
+ description="CYRILLIC LETTER MULTIOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66E,
+ },
+ [0xA66F]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC VZMET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA66F,
+ },
+ [0xA670]={
+ category="me",
+ description="COMBINING CYRILLIC TEN MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA670,
+ },
+ [0xA671]={
+ category="me",
+ description="COMBINING CYRILLIC HUNDRED MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA671,
+ },
+ [0xA672]={
+ category="me",
+ description="COMBINING CYRILLIC THOUSAND MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA672,
+ },
+ [0xA673]={
+ category="po",
+ description="SLAVONIC ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA673,
+ },
+ [0xA674]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER UKRAINIAN IE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA674,
+ },
+ [0xA675]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA675,
+ },
+ [0xA676]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER YI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA676,
+ },
+ [0xA677]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA677,
+ },
+ [0xA678]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER HARD SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA678,
+ },
+ [0xA679]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER YERU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA679,
+ },
+ [0xA67A]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER SOFT SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67A,
+ },
+ [0xA67B]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER OMEGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67B,
+ },
+ [0xA67C]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC KAVYKA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67C,
+ },
+ [0xA67D]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC PAYEROK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67D,
+ },
+ [0xA67E]={
+ category="po",
+ description="CYRILLIC KAVYKA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA67E,
+ },
+ [0xA67F]={
+ category="lm",
+ description="CYRILLIC PAYEROK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA67F,
+ },
+ [0xA680]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA680,
+ },
+ [0xA681]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA681,
+ },
+ [0xA682]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA682,
+ },
+ [0xA683]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA683,
+ },
+ [0xA684]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ZHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA684,
+ },
+ [0xA685]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ZHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA685,
+ },
+ [0xA686]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER CCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA686,
+ },
+ [0xA687]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER CCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA687,
+ },
+ [0xA688]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA688,
+ },
+ [0xA689]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA689,
+ },
+ [0xA68A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68A,
+ },
+ [0xA68B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68B,
+ },
+ [0xA68C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68C,
+ },
+ [0xA68D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68D,
+ },
+ [0xA68E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TSWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68E,
+ },
+ [0xA68F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TSWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68F,
+ },
+ [0xA690]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TSSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA690,
+ },
+ [0xA691]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TSSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA691,
+ },
+ [0xA692]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA692,
+ },
+ [0xA693]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA693,
+ },
+ [0xA694]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER HWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA694,
+ },
+ [0xA695]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER HWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA695,
+ },
+ [0xA696]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA696,
+ },
+ [0xA697]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA697,
+ },
+ [0xA698]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DOUBLE O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA698,
+ },
+ [0xA699]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DOUBLE O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA699,
+ },
+ [0xA69A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER CROSSED O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA69A,
+ },
+ [0xA69B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER CROSSED O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA69B,
+ },
+ [0xA69C]={
+ category="lm",
+ description="MODIFIER LETTER CYRILLIC HARD SIGN",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x44A },
+ unicodeslot=0xA69C,
+ },
+ [0xA69D]={
+ category="lm",
+ description="MODIFIER LETTER CYRILLIC SOFT SIGN",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x44C },
+ unicodeslot=0xA69D,
+ },
+ [0xA69E]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER EF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA69E,
+ },
+ [0xA69F]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC LETTER IOTIFIED E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA69F,
+ },
+ [0xA6A0]={
+ category="lo",
+ description="BAMUM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A0,
+ },
+ [0xA6A1]={
+ category="lo",
+ description="BAMUM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A1,
+ },
+ [0xA6A2]={
+ category="lo",
+ description="BAMUM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A2,
+ },
+ [0xA6A3]={
+ category="lo",
+ description="BAMUM LETTER KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A3,
+ },
+ [0xA6A4]={
+ category="lo",
+ description="BAMUM LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A4,
+ },
+ [0xA6A5]={
+ category="lo",
+ description="BAMUM LETTER REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A5,
+ },
+ [0xA6A6]={
+ category="lo",
+ description="BAMUM LETTER TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A6,
+ },
+ [0xA6A7]={
+ category="lo",
+ description="BAMUM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A7,
+ },
+ [0xA6A8]={
+ category="lo",
+ description="BAMUM LETTER NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A8,
+ },
+ [0xA6A9]={
+ category="lo",
+ description="BAMUM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A9,
+ },
+ [0xA6AA]={
+ category="lo",
+ description="BAMUM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AA,
+ },
+ [0xA6AB]={
+ category="lo",
+ description="BAMUM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AB,
+ },
+ [0xA6AC]={
+ category="lo",
+ description="BAMUM LETTER RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AC,
+ },
+ [0xA6AD]={
+ category="lo",
+ description="BAMUM LETTER RIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AD,
+ },
+ [0xA6AE]={
+ category="lo",
+ description="BAMUM LETTER LEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AE,
+ },
+ [0xA6AF]={
+ category="lo",
+ description="BAMUM LETTER MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AF,
+ },
+ [0xA6B0]={
+ category="lo",
+ description="BAMUM LETTER TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B0,
+ },
+ [0xA6B1]={
+ category="lo",
+ description="BAMUM LETTER NDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B1,
+ },
+ [0xA6B2]={
+ category="lo",
+ description="BAMUM LETTER NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B2,
+ },
+ [0xA6B3]={
+ category="lo",
+ description="BAMUM LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B3,
+ },
+ [0xA6B4]={
+ category="lo",
+ description="BAMUM LETTER SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B4,
+ },
+ [0xA6B5]={
+ category="lo",
+ description="BAMUM LETTER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B5,
+ },
+ [0xA6B6]={
+ category="lo",
+ description="BAMUM LETTER SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B6,
+ },
+ [0xA6B7]={
+ category="lo",
+ description="BAMUM LETTER SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B7,
+ },
+ [0xA6B8]={
+ category="lo",
+ description="BAMUM LETTER SHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B8,
+ },
+ [0xA6B9]={
+ category="lo",
+ description="BAMUM LETTER SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B9,
+ },
+ [0xA6BA]={
+ category="lo",
+ description="BAMUM LETTER KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BA,
+ },
+ [0xA6BB]={
+ category="lo",
+ description="BAMUM LETTER KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BB,
+ },
+ [0xA6BC]={
+ category="lo",
+ description="BAMUM LETTER NUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BC,
+ },
+ [0xA6BD]={
+ category="lo",
+ description="BAMUM LETTER NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BD,
+ },
+ [0xA6BE]={
+ category="lo",
+ description="BAMUM LETTER NJUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BE,
+ },
+ [0xA6BF]={
+ category="lo",
+ description="BAMUM LETTER YOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BF,
+ },
+ [0xA6C0]={
+ category="lo",
+ description="BAMUM LETTER SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C0,
+ },
+ [0xA6C1]={
+ category="lo",
+ description="BAMUM LETTER YUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C1,
+ },
+ [0xA6C2]={
+ category="lo",
+ description="BAMUM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C2,
+ },
+ [0xA6C3]={
+ category="lo",
+ description="BAMUM LETTER NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C3,
+ },
+ [0xA6C4]={
+ category="lo",
+ description="BAMUM LETTER KEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C4,
+ },
+ [0xA6C5]={
+ category="lo",
+ description="BAMUM LETTER PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C5,
+ },
+ [0xA6C6]={
+ category="lo",
+ description="BAMUM LETTER NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C6,
+ },
+ [0xA6C7]={
+ category="lo",
+ description="BAMUM LETTER NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C7,
+ },
+ [0xA6C8]={
+ category="lo",
+ description="BAMUM LETTER PUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C8,
+ },
+ [0xA6C9]={
+ category="lo",
+ description="BAMUM LETTER WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C9,
+ },
+ [0xA6CA]={
+ category="lo",
+ description="BAMUM LETTER PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CA,
+ },
+ [0xA6CB]={
+ category="lo",
+ description="BAMUM LETTER FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CB,
+ },
+ [0xA6CC]={
+ category="lo",
+ description="BAMUM LETTER RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CC,
+ },
+ [0xA6CD]={
+ category="lo",
+ description="BAMUM LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CD,
+ },
+ [0xA6CE]={
+ category="lo",
+ description="BAMUM LETTER MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CE,
+ },
+ [0xA6CF]={
+ category="lo",
+ description="BAMUM LETTER NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CF,
+ },
+ [0xA6D0]={
+ category="lo",
+ description="BAMUM LETTER REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D0,
+ },
+ [0xA6D1]={
+ category="lo",
+ description="BAMUM LETTER RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D1,
+ },
+ [0xA6D2]={
+ category="lo",
+ description="BAMUM LETTER KEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D2,
+ },
+ [0xA6D3]={
+ category="lo",
+ description="BAMUM LETTER NGKWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D3,
+ },
+ [0xA6D4]={
+ category="lo",
+ description="BAMUM LETTER NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D4,
+ },
+ [0xA6D5]={
+ category="lo",
+ description="BAMUM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D5,
+ },
+ [0xA6D6]={
+ category="lo",
+ description="BAMUM LETTER SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D6,
+ },
+ [0xA6D7]={
+ category="lo",
+ description="BAMUM LETTER PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D7,
+ },
+ [0xA6D8]={
+ category="lo",
+ description="BAMUM LETTER FU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D8,
+ },
+ [0xA6D9]={
+ category="lo",
+ description="BAMUM LETTER FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D9,
+ },
+ [0xA6DA]={
+ category="lo",
+ description="BAMUM LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DA,
+ },
+ [0xA6DB]={
+ category="lo",
+ description="BAMUM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DB,
+ },
+ [0xA6DC]={
+ category="lo",
+ description="BAMUM LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DC,
+ },
+ [0xA6DD]={
+ category="lo",
+ description="BAMUM LETTER PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DD,
+ },
+ [0xA6DE]={
+ category="lo",
+ description="BAMUM LETTER LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DE,
+ },
+ [0xA6DF]={
+ category="lo",
+ description="BAMUM LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DF,
+ },
+ [0xA6E0]={
+ category="lo",
+ description="BAMUM LETTER MBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E0,
+ },
+ [0xA6E1]={
+ category="lo",
+ description="BAMUM LETTER REN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E1,
+ },
+ [0xA6E2]={
+ category="lo",
+ description="BAMUM LETTER MEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E2,
+ },
+ [0xA6E3]={
+ category="lo",
+ description="BAMUM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E3,
+ },
+ [0xA6E4]={
+ category="lo",
+ description="BAMUM LETTER TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E4,
+ },
+ [0xA6E5]={
+ category="lo",
+ description="BAMUM LETTER KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E5,
+ },
+ [0xA6E6]={
+ category="nl",
+ description="BAMUM LETTER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E6,
+ },
+ [0xA6E7]={
+ category="nl",
+ description="BAMUM LETTER MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E7,
+ },
+ [0xA6E8]={
+ category="nl",
+ description="BAMUM LETTER TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E8,
+ },
+ [0xA6E9]={
+ category="nl",
+ description="BAMUM LETTER KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E9,
+ },
+ [0xA6EA]={
+ category="nl",
+ description="BAMUM LETTER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EA,
+ },
+ [0xA6EB]={
+ category="nl",
+ description="BAMUM LETTER NTUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EB,
+ },
+ [0xA6EC]={
+ category="nl",
+ description="BAMUM LETTER SAMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EC,
+ },
+ [0xA6ED]={
+ category="nl",
+ description="BAMUM LETTER FAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6ED,
+ },
+ [0xA6EE]={
+ category="nl",
+ description="BAMUM LETTER KOVUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EE,
+ },
+ [0xA6EF]={
+ category="nl",
+ description="BAMUM LETTER KOGHOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EF,
+ },
+ [0xA6F0]={
+ category="mn",
+ combining=0xE6,
+ description="BAMUM COMBINING MARK KOQNDON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA6F0,
+ },
+ [0xA6F1]={
+ category="mn",
+ combining=0xE6,
+ description="BAMUM COMBINING MARK TUKWENTIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA6F1,
+ },
+ [0xA6F2]={
+ category="po",
+ description="BAMUM NJAEMLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6F2,
+ },
+ [0xA6F3]={
+ category="po",
+ description="BAMUM FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F3,
+ },
+ [0xA6F4]={
+ category="po",
+ description="BAMUM COLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F4,
+ },
+ [0xA6F5]={
+ category="po",
+ description="BAMUM COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F5,
+ },
+ [0xA6F6]={
+ category="po",
+ description="BAMUM SEMICOLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F6,
+ },
+ [0xA6F7]={
+ category="po",
+ description="BAMUM QUESTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F7,
+ },
+ [0xA700]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YIN PING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA700,
+ },
+ [0xA701]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YANG PING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA701,
+ },
+ [0xA702]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YIN SHANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA702,
+ },
+ [0xA703]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YANG SHANG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA703,
+ },
+ [0xA704]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YIN QU",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA704,
+ },
+ [0xA705]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YANG QU",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA705,
+ },
+ [0xA706]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YIN RU",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA706,
+ },
+ [0xA707]={
+ category="sk",
+ description="MODIFIER LETTER CHINESE TONE YANG RU",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA707,
+ },
+ [0xA708]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA708,
+ },
+ [0xA709]={
+ category="sk",
+ description="MODIFIER LETTER HIGH DOTTED TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA709,
+ },
+ [0xA70A]={
+ category="sk",
+ description="MODIFIER LETTER MID DOTTED TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70A,
+ },
+ [0xA70B]={
+ category="sk",
+ description="MODIFIER LETTER LOW DOTTED TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70B,
+ },
+ [0xA70C]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70C,
+ },
+ [0xA70D]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70D,
+ },
+ [0xA70E]={
+ category="sk",
+ description="MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70E,
+ },
+ [0xA70F]={
+ category="sk",
+ description="MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA70F,
+ },
+ [0xA710]={
+ category="sk",
+ description="MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA710,
+ },
+ [0xA711]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA711,
+ },
+ [0xA712]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA712,
+ },
+ [0xA713]={
+ category="sk",
+ description="MODIFIER LETTER HIGH LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA713,
+ },
+ [0xA714]={
+ category="sk",
+ description="MODIFIER LETTER MID LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA714,
+ },
+ [0xA715]={
+ category="sk",
+ description="MODIFIER LETTER LOW LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA715,
+ },
+ [0xA716]={
+ category="sk",
+ description="MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA716,
+ },
+ [0xA717]={
+ category="lm",
+ description="MODIFIER LETTER DOT VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA717,
+ },
+ [0xA718]={
+ category="lm",
+ description="MODIFIER LETTER DOT SLASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA718,
+ },
+ [0xA719]={
+ category="lm",
+ description="MODIFIER LETTER DOT HORIZONTAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA719,
+ },
+ [0xA71A]={
+ category="lm",
+ description="MODIFIER LETTER LOWER RIGHT CORNER ANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71A,
+ },
+ [0xA71B]={
+ category="lm",
+ description="MODIFIER LETTER RAISED UP ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71B,
+ },
+ [0xA71C]={
+ category="lm",
+ description="MODIFIER LETTER RAISED DOWN ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71C,
+ },
+ [0xA71D]={
+ category="lm",
+ description="MODIFIER LETTER RAISED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71D,
+ },
+ [0xA71E]={
+ category="lm",
+ description="MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71E,
+ },
+ [0xA71F]={
+ category="lm",
+ description="MODIFIER LETTER LOW INVERTED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71F,
+ },
+ [0xA720]={
+ category="sk",
+ description="MODIFIER LETTER STRESS AND HIGH TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA720,
+ },
+ [0xA721]={
+ category="sk",
+ description="MODIFIER LETTER STRESS AND LOW TONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA721,
+ },
+ [0xA722]={
+ category="lu",
+ description="LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA722,
+ },
+ [0xA723]={
+ category="ll",
+ description="LATIN SMALL LETTER EGYPTOLOGICAL ALEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA723,
+ },
+ [0xA724]={
+ category="lu",
+ description="LATIN CAPITAL LETTER EGYPTOLOGICAL AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA724,
+ },
+ [0xA725]={
+ category="ll",
+ description="LATIN SMALL LETTER EGYPTOLOGICAL AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA725,
+ },
+ [0xA726]={
+ category="lu",
+ description="LATIN CAPITAL LETTER HENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA726,
+ },
+ [0xA727]={
+ category="ll",
+ description="LATIN SMALL LETTER HENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA727,
+ },
+ [0xA728]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA728,
+ },
+ [0xA729]={
+ category="ll",
+ description="LATIN SMALL LETTER TZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA729,
+ },
+ [0xA72A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TRESILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72A,
+ },
+ [0xA72B]={
+ category="ll",
+ description="LATIN SMALL LETTER TRESILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72B,
+ },
+ [0xA72C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CUATRILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72C,
+ },
+ [0xA72D]={
+ category="ll",
+ description="LATIN SMALL LETTER CUATRILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72D,
+ },
+ [0xA72E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CUATRILLO WITH COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72E,
+ },
+ [0xA72F]={
+ category="ll",
+ description="LATIN SMALL LETTER CUATRILLO WITH COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72F,
+ },
+ [0xA730]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA730,
+ },
+ [0xA731]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA731,
+ },
+ [0xA732]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA732,
+ },
+ [0xA733]={
+ category="ll",
+ description="LATIN SMALL LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA733,
+ },
+ [0xA734]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA734,
+ },
+ [0xA735]={
+ category="ll",
+ description="LATIN SMALL LETTER AO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA735,
+ },
+ [0xA736]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA736,
+ },
+ [0xA737]={
+ category="ll",
+ description="LATIN SMALL LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA737,
+ },
+ [0xA738]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA738,
+ },
+ [0xA739]={
+ category="ll",
+ description="LATIN SMALL LETTER AV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA739,
+ },
+ [0xA73A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73A,
+ },
+ [0xA73B]={
+ category="ll",
+ description="LATIN SMALL LETTER AV WITH HORIZONTAL BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73B,
+ },
+ [0xA73C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73C,
+ },
+ [0xA73D]={
+ category="ll",
+ description="LATIN SMALL LETTER AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73D,
+ },
+ [0xA73E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER REVERSED C WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73E,
+ },
+ [0xA73F]={
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED C WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73F,
+ },
+ [0xA740]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA740,
+ },
+ [0xA741]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA741,
+ },
+ [0xA742]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA742,
+ },
+ [0xA743]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA743,
+ },
+ [0xA744]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA744,
+ },
+ [0xA745]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA745,
+ },
+ [0xA746]={
+ category="lu",
+ description="LATIN CAPITAL LETTER BROKEN L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA746,
+ },
+ [0xA747]={
+ category="ll",
+ description="LATIN SMALL LETTER BROKEN L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA747,
+ },
+ [0xA748]={
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA748,
+ },
+ [0xA749]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA749,
+ },
+ [0xA74A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74A,
+ },
+ [0xA74B]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LONG STROKE OVERLAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74B,
+ },
+ [0xA74C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74C,
+ },
+ [0xA74D]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74D,
+ },
+ [0xA74E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74E,
+ },
+ [0xA74F]={
+ category="ll",
+ description="LATIN SMALL LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74F,
+ },
+ [0xA750]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA750,
+ },
+ [0xA751]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA751,
+ },
+ [0xA752]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA752,
+ },
+ [0xA753]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA753,
+ },
+ [0xA754]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH SQUIRREL TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA754,
+ },
+ [0xA755]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH SQUIRREL TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA755,
+ },
+ [0xA756]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA756,
+ },
+ [0xA757]={
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA757,
+ },
+ [0xA758]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA758,
+ },
+ [0xA759]={
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA759,
+ },
+ [0xA75A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER R ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75A,
+ },
+ [0xA75B]={
+ category="ll",
+ description="LATIN SMALL LETTER R ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75B,
+ },
+ [0xA75C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER RUM ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75C,
+ },
+ [0xA75D]={
+ category="ll",
+ description="LATIN SMALL LETTER RUM ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75D,
+ },
+ [0xA75E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER V WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75E,
+ },
+ [0xA75F]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75F,
+ },
+ [0xA760]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA760,
+ },
+ [0xA761]={
+ category="ll",
+ description="LATIN SMALL LETTER VY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA761,
+ },
+ [0xA762]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VISIGOTHIC Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA762,
+ },
+ [0xA763]={
+ category="ll",
+ description="LATIN SMALL LETTER VISIGOTHIC Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA763,
+ },
+ [0xA764]={
+ category="lu",
+ description="LATIN CAPITAL LETTER THORN WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA764,
+ },
+ [0xA765]={
+ category="ll",
+ description="LATIN SMALL LETTER THORN WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA765,
+ },
+ [0xA766]={
+ category="lu",
+ description="LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA766,
+ },
+ [0xA767]={
+ category="ll",
+ description="LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA767,
+ },
+ [0xA768]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA768,
+ },
+ [0xA769]={
+ category="ll",
+ description="LATIN SMALL LETTER VEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA769,
+ },
+ [0xA76A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER ET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76A,
+ },
+ [0xA76B]={
+ category="ll",
+ description="LATIN SMALL LETTER ET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76B,
+ },
+ [0xA76C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76C,
+ },
+ [0xA76D]={
+ category="ll",
+ description="LATIN SMALL LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76D,
+ },
+ [0xA76E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76E,
+ },
+ [0xA76F]={
+ category="ll",
+ description="LATIN SMALL LETTER CON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76F,
+ },
+ [0xA770]={
+ category="lm",
+ description="MODIFIER LETTER US",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xA76F },
+ unicodeslot=0xA770,
+ },
+ [0xA771]={
+ category="ll",
+ description="LATIN SMALL LETTER DUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA771,
+ },
+ [0xA772]={
+ category="ll",
+ description="LATIN SMALL LETTER LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA772,
+ },
+ [0xA773]={
+ category="ll",
+ description="LATIN SMALL LETTER MUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA773,
+ },
+ [0xA774]={
+ category="ll",
+ description="LATIN SMALL LETTER NUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA774,
+ },
+ [0xA775]={
+ category="ll",
+ description="LATIN SMALL LETTER RUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA775,
+ },
+ [0xA776]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL RUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA776,
+ },
+ [0xA777]={
+ category="ll",
+ description="LATIN SMALL LETTER TUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA777,
+ },
+ [0xA778]={
+ category="ll",
+ description="LATIN SMALL LETTER UM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA778,
+ },
+ [0xA779]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA779,
+ },
+ [0xA77A]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77A,
+ },
+ [0xA77B]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77B,
+ },
+ [0xA77C]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77C,
+ },
+ [0xA77D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77D,
+ },
+ [0xA77E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77E,
+ },
+ [0xA77F]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77F,
+ },
+ [0xA780]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA780,
+ },
+ [0xA781]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA781,
+ },
+ [0xA782]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA782,
+ },
+ [0xA783]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA783,
+ },
+ [0xA784]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA784,
+ },
+ [0xA785]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA785,
+ },
+ [0xA786]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA786,
+ },
+ [0xA787]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA787,
+ },
+ [0xA788]={
+ category="lm",
+ description="MODIFIER LETTER LOW CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA788,
+ },
+ [0xA789]={
+ category="sk",
+ description="MODIFIER LETTER COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA789,
+ },
+ [0xA78A]={
+ category="sk",
+ description="MODIFIER LETTER SHORT EQUALS SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78A,
+ },
+ [0xA78B]={
+ category="lu",
+ description="LATIN CAPITAL LETTER SALTILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78B,
+ },
+ [0xA78C]={
+ category="ll",
+ description="LATIN SMALL LETTER SALTILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78C,
+ },
+ [0xA78D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78D,
+ },
+ [0xA78E]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78E,
+ },
+ [0xA78F]={
+ category="lo",
+ description="LATIN LETTER SINOLOGICAL DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78F,
+ },
+ [0xA790]={
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA790,
+ },
+ [0xA791]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA791,
+ },
+ [0xA792]={
+ category="lu",
+ description="LATIN CAPITAL LETTER C WITH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA792,
+ },
+ [0xA793]={
+ category="ll",
+ description="LATIN SMALL LETTER C WITH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA793,
+ },
+ [0xA794]={
+ category="ll",
+ description="LATIN SMALL LETTER C WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA794,
+ },
+ [0xA795]={
+ category="ll",
+ description="LATIN SMALL LETTER H WITH PALATAL HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA795,
+ },
+ [0xA796]={
+ category="lu",
+ description="LATIN CAPITAL LETTER B WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA796,
+ },
+ [0xA797]={
+ category="ll",
+ description="LATIN SMALL LETTER B WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA797,
+ },
+ [0xA798]={
+ category="lu",
+ description="LATIN CAPITAL LETTER F WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA798,
+ },
+ [0xA799]={
+ category="ll",
+ description="LATIN SMALL LETTER F WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA799,
+ },
+ [0xA79A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VOLAPUK AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79A,
+ },
+ [0xA79B]={
+ category="ll",
+ description="LATIN SMALL LETTER VOLAPUK AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79B,
+ },
+ [0xA79C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VOLAPUK OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79C,
+ },
+ [0xA79D]={
+ category="ll",
+ description="LATIN SMALL LETTER VOLAPUK OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79D,
+ },
+ [0xA79E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VOLAPUK UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79E,
+ },
+ [0xA79F]={
+ category="ll",
+ description="LATIN SMALL LETTER VOLAPUK UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA79F,
+ },
+ [0xA7A0]={
+ category="lu",
+ description="LATIN CAPITAL LETTER G WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A0,
+ },
+ [0xA7A1]={
+ category="ll",
+ description="LATIN SMALL LETTER G WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A1,
+ },
+ [0xA7A2]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A2,
+ },
+ [0xA7A3]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A3,
+ },
+ [0xA7A4]={
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A4,
+ },
+ [0xA7A5]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A5,
+ },
+ [0xA7A6]={
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A6,
+ },
+ [0xA7A7]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A7,
+ },
+ [0xA7A8]={
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A8,
+ },
+ [0xA7A9]={
+ category="ll",
+ description="LATIN SMALL LETTER S WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A9,
+ },
+ [0xA7AA]={
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AA,
+ },
+ [0xA7AB]={
+ category="lu",
+ description="LATIN CAPITAL LETTER REVERSED OPEN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AB,
+ },
+ [0xA7AC]={
+ category="lu",
+ description="LATIN CAPITAL LETTER SCRIPT G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AC,
+ },
+ [0xA7AD]={
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH BELT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AD,
+ },
+ [0xA7B0]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B0,
+ },
+ [0xA7B1]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B1,
+ },
+ [0xA7B2]={
+ category="lu",
+ description="LATIN CAPITAL LETTER J WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B2,
+ },
+ [0xA7B3]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B3,
+ },
+ [0xA7B4]={
+ category="lu",
+ description="LATIN CAPITAL LETTER BETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B4,
+ },
+ [0xA7B5]={
+ category="ll",
+ description="LATIN SMALL LETTER BETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B5,
+ },
+ [0xA7B6]={
+ category="lu",
+ description="LATIN CAPITAL LETTER OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B6,
+ },
+ [0xA7B7]={
+ category="ll",
+ description="LATIN SMALL LETTER OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B7,
+ },
+ [0xA7F7]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER SIDEWAYS I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7F7,
+ },
+ [0xA7F8]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL H WITH STROKE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x126 },
+ unicodeslot=0xA7F8,
+ },
+ [0xA7F9]={
+ category="lm",
+ description="MODIFIER LETTER SMALL LIGATURE OE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x153 },
+ unicodeslot=0xA7F9,
+ },
+ [0xA7FA]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL TURNED M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FA,
+ },
+ [0xA7FB]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER REVERSED F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FB,
+ },
+ [0xA7FC]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER REVERSED P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FC,
+ },
+ [0xA7FD]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER INVERTED M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FD,
+ },
+ [0xA7FE]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER I LONGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FE,
+ },
+ [0xA7FF]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER ARCHAIC M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FF,
+ },
+ [0xA800]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA800,
+ },
+ [0xA801]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA801,
+ },
+ [0xA802]={
+ category="mc",
+ description="SYLOTI NAGRI SIGN DVISVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA802,
+ },
+ [0xA803]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA803,
+ },
+ [0xA804]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA804,
+ },
+ [0xA805]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA805,
+ },
+ [0xA806]={
+ category="mn",
+ combining=0x9,
+ description="SYLOTI NAGRI SIGN HASANTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA806,
+ },
+ [0xA807]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA807,
+ },
+ [0xA808]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER KHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA808,
+ },
+ [0xA809]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA809,
+ },
+ [0xA80A]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER GHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA80A,
+ },
+ [0xA80B]={
+ category="mn",
+ description="SYLOTI NAGRI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA80B,
+ },
+ [0xA80C]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER CO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA80C,
+ },
+ [0xA80D]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER CHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA80D,
+ },
+ [0xA80E]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA80E,
+ },
+ [0xA80F]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER JHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA80F,
+ },
+ [0xA810]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER TTO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA810,
+ },
+ [0xA811]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER TTHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA811,
+ },
+ [0xA812]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER DDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA812,
+ },
+ [0xA813]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER DDHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA813,
+ },
+ [0xA814]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA814,
+ },
+ [0xA815]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA815,
+ },
+ [0xA816]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA816,
+ },
+ [0xA817]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER DHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA817,
+ },
+ [0xA818]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA818,
+ },
+ [0xA819]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA819,
+ },
+ [0xA81A]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER PHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81A,
+ },
+ [0xA81B]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81B,
+ },
+ [0xA81C]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER BHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81C,
+ },
+ [0xA81D]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81D,
+ },
+ [0xA81E]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81E,
+ },
+ [0xA81F]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA81F,
+ },
+ [0xA820]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER RRO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA820,
+ },
+ [0xA821]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA821,
+ },
+ [0xA822]={
+ category="lo",
+ description="SYLOTI NAGRI LETTER HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA822,
+ },
+ [0xA823]={
+ category="mc",
+ description="SYLOTI NAGRI VOWEL SIGN A",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA823,
+ },
+ [0xA824]={
+ category="mc",
+ description="SYLOTI NAGRI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA824,
+ },
+ [0xA825]={
+ category="mn",
+ description="SYLOTI NAGRI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA825,
+ },
+ [0xA826]={
+ category="mn",
+ description="SYLOTI NAGRI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA826,
+ },
+ [0xA827]={
+ category="mc",
+ description="SYLOTI NAGRI VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA827,
+ },
+ [0xA828]={
+ category="so",
+ description="SYLOTI NAGRI POETRY MARK-0x0001",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA828,
+ },
+ [0xA829]={
+ category="so",
+ description="SYLOTI NAGRI POETRY MARK-0x0002",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA829,
+ },
+ [0xA82A]={
+ category="so",
+ description="SYLOTI NAGRI POETRY MARK-0x0003",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA82A,
+ },
+ [0xA82B]={
+ category="so",
+ description="SYLOTI NAGRI POETRY MARK-0x0004",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA82B,
+ },
+ [0xA830]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA830,
+ },
+ [0xA831]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA831,
+ },
+ [0xA832]={
+ category="no",
+ description="NORTH INDIC FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA832,
+ },
+ [0xA833]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE SIXTEENTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA833,
+ },
+ [0xA834]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE EIGHTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA834,
+ },
+ [0xA835]={
+ category="no",
+ description="NORTH INDIC FRACTION THREE SIXTEENTHS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA835,
+ },
+ [0xA836]={
+ category="so",
+ description="NORTH INDIC QUARTER MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA836,
+ },
+ [0xA837]={
+ category="so",
+ description="NORTH INDIC PLACEHOLDER MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA837,
+ },
+ [0xA838]={
+ category="sc",
+ description="NORTH INDIC RUPEE MARK",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0xA838,
+ },
+ [0xA839]={
+ category="so",
+ description="NORTH INDIC QUANTITY MARK",
+ direction="et",
+ linebreak="al",
+ unicodeslot=0xA839,
+ },
+ [0xA840]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA840,
+ },
+ [0xA841]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA841,
+ },
+ [0xA842]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA842,
+ },
+ [0xA843]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA843,
+ },
+ [0xA844]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA844,
+ },
+ [0xA845]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA845,
+ },
+ [0xA846]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA846,
+ },
+ [0xA847]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA847,
+ },
+ [0xA848]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA848,
+ },
+ [0xA849]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA849,
+ },
+ [0xA84A]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84A,
+ },
+ [0xA84B]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84B,
+ },
+ [0xA84C]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84C,
+ },
+ [0xA84D]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84D,
+ },
+ [0xA84E]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84E,
+ },
+ [0xA84F]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA84F,
+ },
+ [0xA850]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA850,
+ },
+ [0xA851]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA851,
+ },
+ [0xA852]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA852,
+ },
+ [0xA853]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA853,
+ },
+ [0xA854]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA854,
+ },
+ [0xA855]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA855,
+ },
+ [0xA856]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER SMALL A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA856,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping small a",
+ },
+ },
+ [0xA857]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA857,
+ },
+ [0xA858]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA858,
+ },
+ [0xA859]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA859,
+ },
+ [0xA85A]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85A,
+ },
+ [0xA85B]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85B,
+ },
+ [0xA85C]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85C,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping ha",
+ },
+ },
+ [0xA85D]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85D,
+ },
+ [0xA85E]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85E,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping i",
+ },
+ },
+ [0xA85F]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA85F,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping u",
+ },
+ },
+ [0xA860]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA860,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping e",
+ },
+ },
+ [0xA861]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA861,
+ },
+ [0xA862]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA862,
+ },
+ [0xA863]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA863,
+ },
+ [0xA864]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA864,
+ },
+ [0xA865]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER GGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA865,
+ },
+ [0xA866]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA866,
+ },
+ [0xA867]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA SUBJOINED LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA867,
+ },
+ [0xA868]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA SUBJOINED LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA868,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping subjoined ya",
+ },
+ },
+ [0xA869]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA869,
+ },
+ [0xA86A]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86A,
+ },
+ [0xA86B]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86B,
+ },
+ [0xA86C]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86C,
+ },
+ [0xA86D]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER ALTERNATE YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86D,
+ },
+ [0xA86E]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER VOICELESS SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86E,
+ },
+ [0xA86F]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER VOICED HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA86F,
+ },
+ [0xA870]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA LETTER ASPIRATED FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA870,
+ },
+ [0xA871]={
+ arabic="d",
+ category="lo",
+ description="PHAGS-PA SUBJOINED LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA871,
+ },
+ [0xA872]={
+ arabic="l",
+ category="lo",
+ description="PHAGS-PA SUPERFIXED LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA872,
+ },
+ [0xA873]={
+ arabic="u",
+ category="lo",
+ description="PHAGS-PA LETTER CANDRABINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA873,
+ },
+ [0xA874]={
+ category="po",
+ description="PHAGS-PA SINGLE HEAD MARK",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0xA874,
+ },
+ [0xA875]={
+ category="po",
+ description="PHAGS-PA DOUBLE HEAD MARK",
+ direction="on",
+ linebreak="bb",
+ unicodeslot=0xA875,
+ },
+ [0xA876]={
+ category="po",
+ description="PHAGS-PA MARK SHAD",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0xA876,
+ },
+ [0xA877]={
+ category="po",
+ description="PHAGS-PA MARK DOUBLE SHAD",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0xA877,
+ },
+ [0xA880]={
+ category="mc",
+ description="SAURASHTRA SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA880,
+ },
+ [0xA881]={
+ category="mc",
+ description="SAURASHTRA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA881,
+ },
+ [0xA882]={
+ category="lo",
+ description="SAURASHTRA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA882,
+ },
+ [0xA883]={
+ category="lo",
+ description="SAURASHTRA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA883,
+ },
+ [0xA884]={
+ category="lo",
+ description="SAURASHTRA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA884,
+ },
+ [0xA885]={
+ category="lo",
+ description="SAURASHTRA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA885,
+ },
+ [0xA886]={
+ category="lo",
+ description="SAURASHTRA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA886,
+ },
+ [0xA887]={
+ category="lo",
+ description="SAURASHTRA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA887,
+ },
+ [0xA888]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA888,
+ },
+ [0xA889]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA889,
+ },
+ [0xA88A]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88A,
+ },
+ [0xA88B]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88B,
+ },
+ [0xA88C]={
+ category="lo",
+ description="SAURASHTRA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88C,
+ },
+ [0xA88D]={
+ category="lo",
+ description="SAURASHTRA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88D,
+ },
+ [0xA88E]={
+ category="lo",
+ description="SAURASHTRA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88E,
+ },
+ [0xA88F]={
+ category="lo",
+ description="SAURASHTRA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88F,
+ },
+ [0xA890]={
+ category="lo",
+ description="SAURASHTRA LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA890,
+ },
+ [0xA891]={
+ category="lo",
+ description="SAURASHTRA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA891,
+ },
+ [0xA892]={
+ category="lo",
+ description="SAURASHTRA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA892,
+ },
+ [0xA893]={
+ category="lo",
+ description="SAURASHTRA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA893,
+ },
+ [0xA894]={
+ category="lo",
+ description="SAURASHTRA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA894,
+ },
+ [0xA895]={
+ category="lo",
+ description="SAURASHTRA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA895,
+ },
+ [0xA896]={
+ category="lo",
+ description="SAURASHTRA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA896,
+ },
+ [0xA897]={
+ category="lo",
+ description="SAURASHTRA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA897,
+ },
+ [0xA898]={
+ category="lo",
+ description="SAURASHTRA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA898,
+ },
+ [0xA899]={
+ category="lo",
+ description="SAURASHTRA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA899,
+ },
+ [0xA89A]={
+ category="lo",
+ description="SAURASHTRA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89A,
+ },
+ [0xA89B]={
+ category="lo",
+ description="SAURASHTRA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89B,
+ },
+ [0xA89C]={
+ category="lo",
+ description="SAURASHTRA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89C,
+ },
+ [0xA89D]={
+ category="lo",
+ description="SAURASHTRA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89D,
+ },
+ [0xA89E]={
+ category="lo",
+ description="SAURASHTRA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89E,
+ },
+ [0xA89F]={
+ category="lo",
+ description="SAURASHTRA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89F,
+ },
+ [0xA8A0]={
+ category="lo",
+ description="SAURASHTRA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A0,
+ },
+ [0xA8A1]={
+ category="lo",
+ description="SAURASHTRA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A1,
+ },
+ [0xA8A2]={
+ category="lo",
+ description="SAURASHTRA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A2,
+ },
+ [0xA8A3]={
+ category="lo",
+ description="SAURASHTRA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A3,
+ },
+ [0xA8A4]={
+ category="lo",
+ description="SAURASHTRA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A4,
+ },
+ [0xA8A5]={
+ category="lo",
+ description="SAURASHTRA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A5,
+ },
+ [0xA8A6]={
+ category="lo",
+ description="SAURASHTRA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A6,
+ },
+ [0xA8A7]={
+ category="lo",
+ description="SAURASHTRA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A7,
+ },
+ [0xA8A8]={
+ category="lo",
+ description="SAURASHTRA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A8,
+ },
+ [0xA8A9]={
+ category="lo",
+ description="SAURASHTRA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A9,
+ },
+ [0xA8AA]={
+ category="lo",
+ description="SAURASHTRA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AA,
+ },
+ [0xA8AB]={
+ category="lo",
+ description="SAURASHTRA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AB,
+ },
+ [0xA8AC]={
+ category="lo",
+ description="SAURASHTRA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AC,
+ },
+ [0xA8AD]={
+ category="lo",
+ description="SAURASHTRA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AD,
+ },
+ [0xA8AE]={
+ category="lo",
+ description="SAURASHTRA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AE,
+ },
+ [0xA8AF]={
+ category="lo",
+ description="SAURASHTRA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AF,
+ },
+ [0xA8B0]={
+ category="lo",
+ description="SAURASHTRA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B0,
+ },
+ [0xA8B1]={
+ category="lo",
+ description="SAURASHTRA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B1,
+ },
+ [0xA8B2]={
+ category="lo",
+ description="SAURASHTRA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B2,
+ },
+ [0xA8B3]={
+ category="lo",
+ description="SAURASHTRA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B3,
+ },
+ [0xA8B4]={
+ category="mc",
+ description="SAURASHTRA CONSONANT SIGN HAARU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B4,
+ },
+ [0xA8B5]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B5,
+ },
+ [0xA8B6]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B6,
+ },
+ [0xA8B7]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B7,
+ },
+ [0xA8B8]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B8,
+ },
+ [0xA8B9]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B9,
+ },
+ [0xA8BA]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BA,
+ },
+ [0xA8BB]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BB,
+ },
+ [0xA8BC]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC L",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BC,
+ },
+ [0xA8BD]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC LL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BD,
+ },
+ [0xA8BE]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BE,
+ },
+ [0xA8BF]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BF,
+ },
+ [0xA8C0]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C0,
+ },
+ [0xA8C1]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C1,
+ },
+ [0xA8C2]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C2,
+ },
+ [0xA8C3]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C3,
+ },
+ [0xA8C4]={
+ category="mn",
+ combining=0x9,
+ description="SAURASHTRA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8C4,
+ },
+ [0xA8CE]={
+ category="po",
+ description="SAURASHTRA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA8CE,
+ },
+ [0xA8CF]={
+ category="po",
+ description="SAURASHTRA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA8CF,
+ },
+ [0xA8D0]={
+ category="nd",
+ description="SAURASHTRA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D0,
+ },
+ [0xA8D1]={
+ category="nd",
+ description="SAURASHTRA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D1,
+ },
+ [0xA8D2]={
+ category="nd",
+ description="SAURASHTRA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D2,
+ },
+ [0xA8D3]={
+ category="nd",
+ description="SAURASHTRA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D3,
+ },
+ [0xA8D4]={
+ category="nd",
+ description="SAURASHTRA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D4,
+ },
+ [0xA8D5]={
+ category="nd",
+ description="SAURASHTRA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D5,
+ },
+ [0xA8D6]={
+ category="nd",
+ description="SAURASHTRA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D6,
+ },
+ [0xA8D7]={
+ category="nd",
+ description="SAURASHTRA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D7,
+ },
+ [0xA8D8]={
+ category="nd",
+ description="SAURASHTRA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D8,
+ },
+ [0xA8D9]={
+ category="nd",
+ description="SAURASHTRA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D9,
+ },
+ [0xA8E0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT ZERO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E0,
+ },
+ [0xA8E1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT ONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E1,
+ },
+ [0xA8E2]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT TWO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E2,
+ },
+ [0xA8E3]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT THREE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E3,
+ },
+ [0xA8E4]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT FOUR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E4,
+ },
+ [0xA8E5]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT FIVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E5,
+ },
+ [0xA8E6]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT SIX",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E6,
+ },
+ [0xA8E7]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT SEVEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E7,
+ },
+ [0xA8E8]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT EIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E8,
+ },
+ [0xA8E9]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI DIGIT NINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E9,
+ },
+ [0xA8EA]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EA,
+ },
+ [0xA8EB]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EB,
+ },
+ [0xA8EC]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EC,
+ },
+ [0xA8ED]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER NA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8ED,
+ },
+ [0xA8EE]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER PA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EE,
+ },
+ [0xA8EF]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER RA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EF,
+ },
+ [0xA8F0]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI LETTER VI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8F0,
+ },
+ [0xA8F1]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DEVANAGARI SIGN AVAGRAHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8F1,
+ },
+ [0xA8F2]={
+ category="lo",
+ description="DEVANAGARI SIGN SPACING CANDRABINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F2,
+ },
+ [0xA8F3]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU VIRAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F3,
+ },
+ [0xA8F4]={
+ category="lo",
+ description="DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F4,
+ },
+ [0xA8F5]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F5,
+ },
+ [0xA8F6]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F6,
+ },
+ [0xA8F7]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F7,
+ },
+ [0xA8F8]={
+ category="po",
+ description="DEVANAGARI SIGN PUSHPIKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F8,
+ },
+ [0xA8F9]={
+ category="po",
+ description="DEVANAGARI GAP FILLER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F9,
+ },
+ [0xA8FA]={
+ category="po",
+ description="DEVANAGARI CARET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FA,
+ },
+ [0xA8FB]={
+ category="lo",
+ description="DEVANAGARI HEADSTROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FB,
+ },
+ [0xA8FC]={
+ category="po",
+ description="DEVANAGARI SIGN SIDDHAM",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xA8FC,
+ },
+ [0xA8FD]={
+ category="lo",
+ description="DEVANAGARI JAIN OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FD,
+ },
+ [0xA900]={
+ category="nd",
+ description="KAYAH LI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA900,
+ },
+ [0xA901]={
+ category="nd",
+ description="KAYAH LI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA901,
+ },
+ [0xA902]={
+ category="nd",
+ description="KAYAH LI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA902,
+ },
+ [0xA903]={
+ category="nd",
+ description="KAYAH LI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA903,
+ },
+ [0xA904]={
+ category="nd",
+ description="KAYAH LI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA904,
+ },
+ [0xA905]={
+ category="nd",
+ description="KAYAH LI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA905,
+ },
+ [0xA906]={
+ category="nd",
+ description="KAYAH LI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA906,
+ },
+ [0xA907]={
+ category="nd",
+ description="KAYAH LI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA907,
+ },
+ [0xA908]={
+ category="nd",
+ description="KAYAH LI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA908,
+ },
+ [0xA909]={
+ category="nd",
+ description="KAYAH LI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA909,
+ },
+ [0xA90A]={
+ category="lo",
+ description="KAYAH LI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90A,
+ },
+ [0xA90B]={
+ category="lo",
+ description="KAYAH LI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90B,
+ },
+ [0xA90C]={
+ category="lo",
+ description="KAYAH LI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90C,
+ },
+ [0xA90D]={
+ category="lo",
+ description="KAYAH LI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90D,
+ },
+ [0xA90E]={
+ category="lo",
+ description="KAYAH LI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90E,
+ },
+ [0xA90F]={
+ category="lo",
+ description="KAYAH LI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90F,
+ },
+ [0xA910]={
+ category="lo",
+ description="KAYAH LI LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA910,
+ },
+ [0xA911]={
+ category="lo",
+ description="KAYAH LI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA911,
+ },
+ [0xA912]={
+ category="lo",
+ description="KAYAH LI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA912,
+ },
+ [0xA913]={
+ category="lo",
+ description="KAYAH LI LETTER HTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA913,
+ },
+ [0xA914]={
+ category="lo",
+ description="KAYAH LI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA914,
+ },
+ [0xA915]={
+ category="lo",
+ description="KAYAH LI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA915,
+ },
+ [0xA916]={
+ category="lo",
+ description="KAYAH LI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA916,
+ },
+ [0xA917]={
+ category="lo",
+ description="KAYAH LI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA917,
+ },
+ [0xA918]={
+ category="lo",
+ description="KAYAH LI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA918,
+ },
+ [0xA919]={
+ category="lo",
+ description="KAYAH LI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA919,
+ },
+ [0xA91A]={
+ category="lo",
+ description="KAYAH LI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91A,
+ },
+ [0xA91B]={
+ category="lo",
+ description="KAYAH LI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91B,
+ },
+ [0xA91C]={
+ category="lo",
+ description="KAYAH LI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91C,
+ },
+ [0xA91D]={
+ category="lo",
+ description="KAYAH LI LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91D,
+ },
+ [0xA91E]={
+ category="lo",
+ description="KAYAH LI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91E,
+ },
+ [0xA91F]={
+ category="lo",
+ description="KAYAH LI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91F,
+ },
+ [0xA920]={
+ category="lo",
+ description="KAYAH LI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA920,
+ },
+ [0xA921]={
+ category="lo",
+ description="KAYAH LI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA921,
+ },
+ [0xA922]={
+ category="lo",
+ description="KAYAH LI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA922,
+ },
+ [0xA923]={
+ category="lo",
+ description="KAYAH LI LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA923,
+ },
+ [0xA924]={
+ category="lo",
+ description="KAYAH LI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA924,
+ },
+ [0xA925]={
+ category="lo",
+ description="KAYAH LI LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA925,
+ },
+ [0xA926]={
+ category="mn",
+ description="KAYAH LI VOWEL UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA926,
+ },
+ [0xA927]={
+ category="mn",
+ description="KAYAH LI VOWEL E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA927,
+ },
+ [0xA928]={
+ category="mn",
+ description="KAYAH LI VOWEL U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA928,
+ },
+ [0xA929]={
+ category="mn",
+ description="KAYAH LI VOWEL EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA929,
+ },
+ [0xA92A]={
+ category="mn",
+ description="KAYAH LI VOWEL O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92A,
+ },
+ [0xA92B]={
+ category="mn",
+ combining=0xDC,
+ description="KAYAH LI TONE PLOPHU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92B,
+ },
+ [0xA92C]={
+ category="mn",
+ combining=0xDC,
+ description="KAYAH LI TONE CALYA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92C,
+ },
+ [0xA92D]={
+ category="mn",
+ combining=0xDC,
+ description="KAYAH LI TONE CALYA PLOPHU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92D,
+ },
+ [0xA92E]={
+ category="po",
+ description="KAYAH LI SIGN CWI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA92E,
+ },
+ [0xA92F]={
+ category="po",
+ description="KAYAH LI SIGN SHYA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA92F,
+ },
+ [0xA930]={
+ category="lo",
+ description="REJANG LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA930,
+ },
+ [0xA931]={
+ category="lo",
+ description="REJANG LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA931,
+ },
+ [0xA932]={
+ category="lo",
+ description="REJANG LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA932,
+ },
+ [0xA933]={
+ category="lo",
+ description="REJANG LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA933,
+ },
+ [0xA934]={
+ category="lo",
+ description="REJANG LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA934,
+ },
+ [0xA935]={
+ category="lo",
+ description="REJANG LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA935,
+ },
+ [0xA936]={
+ category="lo",
+ description="REJANG LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA936,
+ },
+ [0xA937]={
+ category="lo",
+ description="REJANG LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA937,
+ },
+ [0xA938]={
+ category="lo",
+ description="REJANG LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA938,
+ },
+ [0xA939]={
+ category="lo",
+ description="REJANG LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA939,
+ },
+ [0xA93A]={
+ category="lo",
+ description="REJANG LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93A,
+ },
+ [0xA93B]={
+ category="lo",
+ description="REJANG LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93B,
+ },
+ [0xA93C]={
+ category="lo",
+ description="REJANG LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93C,
+ },
+ [0xA93D]={
+ category="lo",
+ description="REJANG LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93D,
+ },
+ [0xA93E]={
+ category="lo",
+ description="REJANG LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93E,
+ },
+ [0xA93F]={
+ category="lo",
+ description="REJANG LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93F,
+ },
+ [0xA940]={
+ category="lo",
+ description="REJANG LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA940,
+ },
+ [0xA941]={
+ category="lo",
+ description="REJANG LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA941,
+ },
+ [0xA942]={
+ category="lo",
+ description="REJANG LETTER MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA942,
+ },
+ [0xA943]={
+ category="lo",
+ description="REJANG LETTER NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA943,
+ },
+ [0xA944]={
+ category="lo",
+ description="REJANG LETTER NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA944,
+ },
+ [0xA945]={
+ category="lo",
+ description="REJANG LETTER NYJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA945,
+ },
+ [0xA946]={
+ category="lo",
+ description="REJANG LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA946,
+ },
+ [0xA947]={
+ category="mn",
+ description="REJANG VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA947,
+ },
+ [0xA948]={
+ category="mn",
+ description="REJANG VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA948,
+ },
+ [0xA949]={
+ category="mn",
+ description="REJANG VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA949,
+ },
+ [0xA94A]={
+ category="mn",
+ description="REJANG VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94A,
+ },
+ [0xA94B]={
+ category="mn",
+ description="REJANG VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94B,
+ },
+ [0xA94C]={
+ category="mn",
+ description="REJANG VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94C,
+ },
+ [0xA94D]={
+ category="mn",
+ description="REJANG VOWEL SIGN EU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94D,
+ },
+ [0xA94E]={
+ category="mn",
+ description="REJANG VOWEL SIGN EA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94E,
+ },
+ [0xA94F]={
+ category="mn",
+ description="REJANG CONSONANT SIGN NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94F,
+ },
+ [0xA950]={
+ category="mn",
+ description="REJANG CONSONANT SIGN N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA950,
+ },
+ [0xA951]={
+ category="mn",
+ description="REJANG CONSONANT SIGN R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA951,
+ },
+ [0xA952]={
+ category="mc",
+ description="REJANG CONSONANT SIGN H",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA952,
+ },
+ [0xA953]={
+ category="mc",
+ combining=0x9,
+ description="REJANG VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA953,
+ },
+ [0xA95F]={
+ category="po",
+ description="REJANG SECTION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA95F,
+ },
+ [0xA960]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA960,
+ },
+ [0xA961]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA961,
+ },
+ [0xA962]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA962,
+ },
+ [0xA963]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA963,
+ },
+ [0xA964]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA964,
+ },
+ [0xA965]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGKIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA965,
+ },
+ [0xA966]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA966,
+ },
+ [0xA967]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGTIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA967,
+ },
+ [0xA968]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA968,
+ },
+ [0xA969]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA969,
+ },
+ [0xA96A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96A,
+ },
+ [0xA96B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96B,
+ },
+ [0xA96C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96C,
+ },
+ [0xA96D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96D,
+ },
+ [0xA96E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96E,
+ },
+ [0xA96F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96F,
+ },
+ [0xA970]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA970,
+ },
+ [0xA971]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA971,
+ },
+ [0xA972]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA972,
+ },
+ [0xA973]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA973,
+ },
+ [0xA974]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA974,
+ },
+ [0xA975]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGSIOS-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA975,
+ },
+ [0xA976]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA976,
+ },
+ [0xA977]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA977,
+ },
+ [0xA978]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGCIEUC-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA978,
+ },
+ [0xA979]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGTHIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA979,
+ },
+ [0xA97A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PHIEUPH-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97A,
+ },
+ [0xA97B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG HIEUH-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97B,
+ },
+ [0xA97C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGYEORINHIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97C,
+ },
+ [0xA980]={
+ category="mn",
+ description="JAVANESE SIGN PANYANGGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA980,
+ },
+ [0xA981]={
+ category="mn",
+ description="JAVANESE SIGN CECAK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA981,
+ },
+ [0xA982]={
+ category="mn",
+ description="JAVANESE SIGN LAYAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA982,
+ },
+ [0xA983]={
+ category="mc",
+ description="JAVANESE SIGN WIGNYAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA983,
+ },
+ [0xA984]={
+ category="lo",
+ description="JAVANESE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA984,
+ },
+ [0xA985]={
+ category="lo",
+ description="JAVANESE LETTER I KAWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA985,
+ },
+ [0xA986]={
+ category="lo",
+ description="JAVANESE LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA986,
+ },
+ [0xA987]={
+ category="lo",
+ description="JAVANESE LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA987,
+ },
+ [0xA988]={
+ category="lo",
+ description="JAVANESE LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA988,
+ },
+ [0xA989]={
+ category="lo",
+ description="JAVANESE LETTER PA CEREK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA989,
+ },
+ [0xA98A]={
+ category="lo",
+ description="JAVANESE LETTER NGA LELET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98A,
+ },
+ [0xA98B]={
+ category="lo",
+ description="JAVANESE LETTER NGA LELET RASWADI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98B,
+ },
+ [0xA98C]={
+ category="lo",
+ description="JAVANESE LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98C,
+ },
+ [0xA98D]={
+ category="lo",
+ description="JAVANESE LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98D,
+ },
+ [0xA98E]={
+ category="lo",
+ description="JAVANESE LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98E,
+ },
+ [0xA98F]={
+ category="lo",
+ description="JAVANESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98F,
+ },
+ [0xA990]={
+ category="lo",
+ description="JAVANESE LETTER KA SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA990,
+ },
+ [0xA991]={
+ category="lo",
+ description="JAVANESE LETTER KA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA991,
+ },
+ [0xA992]={
+ category="lo",
+ description="JAVANESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA992,
+ },
+ [0xA993]={
+ category="lo",
+ description="JAVANESE LETTER GA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA993,
+ },
+ [0xA994]={
+ category="lo",
+ description="JAVANESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA994,
+ },
+ [0xA995]={
+ category="lo",
+ description="JAVANESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA995,
+ },
+ [0xA996]={
+ category="lo",
+ description="JAVANESE LETTER CA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA996,
+ },
+ [0xA997]={
+ category="lo",
+ description="JAVANESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA997,
+ },
+ [0xA998]={
+ category="lo",
+ description="JAVANESE LETTER NYA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA998,
+ },
+ [0xA999]={
+ category="lo",
+ description="JAVANESE LETTER JA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA999,
+ },
+ [0xA99A]={
+ category="lo",
+ description="JAVANESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99A,
+ },
+ [0xA99B]={
+ category="lo",
+ description="JAVANESE LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99B,
+ },
+ [0xA99C]={
+ category="lo",
+ description="JAVANESE LETTER TTA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99C,
+ },
+ [0xA99D]={
+ category="lo",
+ description="JAVANESE LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99D,
+ },
+ [0xA99E]={
+ category="lo",
+ description="JAVANESE LETTER DDA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99E,
+ },
+ [0xA99F]={
+ category="lo",
+ description="JAVANESE LETTER NA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99F,
+ },
+ [0xA9A0]={
+ category="lo",
+ description="JAVANESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A0,
+ },
+ [0xA9A1]={
+ category="lo",
+ description="JAVANESE LETTER TA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A1,
+ },
+ [0xA9A2]={
+ category="lo",
+ description="JAVANESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A2,
+ },
+ [0xA9A3]={
+ category="lo",
+ description="JAVANESE LETTER DA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A3,
+ },
+ [0xA9A4]={
+ category="lo",
+ description="JAVANESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A4,
+ },
+ [0xA9A5]={
+ category="lo",
+ description="JAVANESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A5,
+ },
+ [0xA9A6]={
+ category="lo",
+ description="JAVANESE LETTER PA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A6,
+ },
+ [0xA9A7]={
+ category="lo",
+ description="JAVANESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A7,
+ },
+ [0xA9A8]={
+ category="lo",
+ description="JAVANESE LETTER BA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A8,
+ },
+ [0xA9A9]={
+ category="lo",
+ description="JAVANESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A9,
+ },
+ [0xA9AA]={
+ category="lo",
+ description="JAVANESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AA,
+ },
+ [0xA9AB]={
+ category="lo",
+ description="JAVANESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AB,
+ },
+ [0xA9AC]={
+ category="lo",
+ description="JAVANESE LETTER RA AGUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AC,
+ },
+ [0xA9AD]={
+ category="lo",
+ description="JAVANESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AD,
+ },
+ [0xA9AE]={
+ category="lo",
+ description="JAVANESE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AE,
+ },
+ [0xA9AF]={
+ category="lo",
+ description="JAVANESE LETTER SA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AF,
+ },
+ [0xA9B0]={
+ category="lo",
+ description="JAVANESE LETTER SA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B0,
+ },
+ [0xA9B1]={
+ category="lo",
+ description="JAVANESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B1,
+ },
+ [0xA9B2]={
+ category="lo",
+ description="JAVANESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B2,
+ },
+ [0xA9B3]={
+ category="mn",
+ combining=0x7,
+ description="JAVANESE SIGN CECAK TELU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B3,
+ },
+ [0xA9B4]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TARUNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9B4,
+ },
+ [0xA9B5]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TOLONG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9B5,
+ },
+ [0xA9B6]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN WULU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B6,
+ },
+ [0xA9B7]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN WULU MELIK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B7,
+ },
+ [0xA9B8]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN SUKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B8,
+ },
+ [0xA9B9]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN SUKU MENDUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B9,
+ },
+ [0xA9BA]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TALING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BA,
+ },
+ [0xA9BB]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN DIRGA MURE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BB,
+ },
+ [0xA9BC]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN PEPET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9BC,
+ },
+ [0xA9BD]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN KERET",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BD,
+ },
+ [0xA9BE]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN PENGKAL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BE,
+ },
+ [0xA9BF]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN CAKRA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BF,
+ },
+ [0xA9C0]={
+ category="mc",
+ combining=0x9,
+ description="JAVANESE PANGKON",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9C0,
+ },
+ [0xA9C1]={
+ category="po",
+ description="JAVANESE LEFT RERENGGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C1,
+ },
+ [0xA9C2]={
+ category="po",
+ description="JAVANESE RIGHT RERENGGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C2,
+ },
+ [0xA9C3]={
+ category="po",
+ description="JAVANESE PADA ANDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C3,
+ },
+ [0xA9C4]={
+ category="po",
+ description="JAVANESE PADA MADYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C4,
+ },
+ [0xA9C5]={
+ category="po",
+ description="JAVANESE PADA LUHUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C5,
+ },
+ [0xA9C6]={
+ category="po",
+ description="JAVANESE PADA WINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C6,
+ },
+ [0xA9C7]={
+ category="po",
+ description="JAVANESE PADA PANGKAT",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C7,
+ },
+ [0xA9C8]={
+ category="po",
+ description="JAVANESE PADA LINGSA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C8,
+ },
+ [0xA9C9]={
+ category="po",
+ description="JAVANESE PADA LUNGSI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C9,
+ },
+ [0xA9CA]={
+ category="po",
+ description="JAVANESE PADA ADEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CA,
+ },
+ [0xA9CB]={
+ category="po",
+ description="JAVANESE PADA ADEG ADEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CB,
+ },
+ [0xA9CC]={
+ category="po",
+ description="JAVANESE PADA PISELEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CC,
+ },
+ [0xA9CD]={
+ category="po",
+ description="JAVANESE TURNED PADA PISELEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CD,
+ },
+ [0xA9CF]={
+ category="lm",
+ description="JAVANESE PANGRANGKEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CF,
+ },
+ [0xA9D0]={
+ category="nd",
+ description="JAVANESE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D0,
+ },
+ [0xA9D1]={
+ category="nd",
+ description="JAVANESE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D1,
+ },
+ [0xA9D2]={
+ category="nd",
+ description="JAVANESE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D2,
+ },
+ [0xA9D3]={
+ category="nd",
+ description="JAVANESE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D3,
+ },
+ [0xA9D4]={
+ category="nd",
+ description="JAVANESE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D4,
+ },
+ [0xA9D5]={
+ category="nd",
+ description="JAVANESE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D5,
+ },
+ [0xA9D6]={
+ category="nd",
+ description="JAVANESE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D6,
+ },
+ [0xA9D7]={
+ category="nd",
+ description="JAVANESE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D7,
+ },
+ [0xA9D8]={
+ category="nd",
+ description="JAVANESE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D8,
+ },
+ [0xA9D9]={
+ category="nd",
+ description="JAVANESE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D9,
+ },
+ [0xA9DE]={
+ category="po",
+ description="JAVANESE PADA TIRTA TUMETES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9DE,
+ },
+ [0xA9DF]={
+ category="po",
+ description="JAVANESE PADA ISEN-ISEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9DF,
+ },
+ [0xA9E0]={
+ category="lo",
+ description="MYANMAR LETTER SHAN GHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E0,
+ },
+ [0xA9E1]={
+ category="lo",
+ description="MYANMAR LETTER SHAN CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E1,
+ },
+ [0xA9E2]={
+ category="lo",
+ description="MYANMAR LETTER SHAN JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E2,
+ },
+ [0xA9E3]={
+ category="lo",
+ description="MYANMAR LETTER SHAN NNA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E3,
+ },
+ [0xA9E4]={
+ category="lo",
+ description="MYANMAR LETTER SHAN BHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E4,
+ },
+ [0xA9E5]={
+ category="mn",
+ description="MYANMAR SIGN SHAN SAW",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xA9E5,
+ },
+ [0xA9E6]={
+ category="lm",
+ description="MYANMAR MODIFIER LETTER SHAN REDUPLICATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E6,
+ },
+ [0xA9E7]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E7,
+ },
+ [0xA9E8]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E8,
+ },
+ [0xA9E9]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9E9,
+ },
+ [0xA9EA]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING GHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9EA,
+ },
+ [0xA9EB]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING JA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9EB,
+ },
+ [0xA9EC]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9EC,
+ },
+ [0xA9ED]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING DDA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9ED,
+ },
+ [0xA9EE]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING DDHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9EE,
+ },
+ [0xA9EF]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING NNA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9EF,
+ },
+ [0xA9F0]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F0,
+ },
+ [0xA9F1]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F1,
+ },
+ [0xA9F2]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F2,
+ },
+ [0xA9F3]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F3,
+ },
+ [0xA9F4]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F4,
+ },
+ [0xA9F5]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F5,
+ },
+ [0xA9F6]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F6,
+ },
+ [0xA9F7]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F7,
+ },
+ [0xA9F8]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F8,
+ },
+ [0xA9F9]={
+ category="nd",
+ description="MYANMAR TAI LAING DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9F9,
+ },
+ [0xA9FA]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING LLA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9FA,
+ },
+ [0xA9FB]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9FB,
+ },
+ [0xA9FC]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING DHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9FC,
+ },
+ [0xA9FD]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9FD,
+ },
+ [0xA9FE]={
+ category="lo",
+ description="MYANMAR LETTER TAI LAING BHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xA9FE,
+ },
+ [0xAA00]={
+ category="lo",
+ description="CHAM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA00,
+ },
+ [0xAA01]={
+ category="lo",
+ description="CHAM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA01,
+ },
+ [0xAA02]={
+ category="lo",
+ description="CHAM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA02,
+ },
+ [0xAA03]={
+ category="lo",
+ description="CHAM LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA03,
+ },
+ [0xAA04]={
+ category="lo",
+ description="CHAM LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA04,
+ },
+ [0xAA05]={
+ category="lo",
+ description="CHAM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA05,
+ },
+ [0xAA06]={
+ category="lo",
+ description="CHAM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA06,
+ },
+ [0xAA07]={
+ category="lo",
+ description="CHAM LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA07,
+ },
+ [0xAA08]={
+ category="lo",
+ description="CHAM LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA08,
+ },
+ [0xAA09]={
+ category="lo",
+ description="CHAM LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA09,
+ },
+ [0xAA0A]={
+ category="lo",
+ description="CHAM LETTER NGUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0A,
+ },
+ [0xAA0B]={
+ category="lo",
+ description="CHAM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0B,
+ },
+ [0xAA0C]={
+ category="lo",
+ description="CHAM LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0C,
+ },
+ [0xAA0D]={
+ category="lo",
+ description="CHAM LETTER CHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0D,
+ },
+ [0xAA0E]={
+ category="lo",
+ description="CHAM LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0E,
+ },
+ [0xAA0F]={
+ category="lo",
+ description="CHAM LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0F,
+ },
+ [0xAA10]={
+ category="lo",
+ description="CHAM LETTER NHUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA10,
+ },
+ [0xAA11]={
+ category="lo",
+ description="CHAM LETTER NHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA11,
+ },
+ [0xAA12]={
+ category="lo",
+ description="CHAM LETTER NHJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA12,
+ },
+ [0xAA13]={
+ category="lo",
+ description="CHAM LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA13,
+ },
+ [0xAA14]={
+ category="lo",
+ description="CHAM LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA14,
+ },
+ [0xAA15]={
+ category="lo",
+ description="CHAM LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA15,
+ },
+ [0xAA16]={
+ category="lo",
+ description="CHAM LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA16,
+ },
+ [0xAA17]={
+ category="lo",
+ description="CHAM LETTER NUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA17,
+ },
+ [0xAA18]={
+ category="lo",
+ description="CHAM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA18,
+ },
+ [0xAA19]={
+ category="lo",
+ description="CHAM LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA19,
+ },
+ [0xAA1A]={
+ category="lo",
+ description="CHAM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1A,
+ },
+ [0xAA1B]={
+ category="lo",
+ description="CHAM LETTER PPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1B,
+ },
+ [0xAA1C]={
+ category="lo",
+ description="CHAM LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1C,
+ },
+ [0xAA1D]={
+ category="lo",
+ description="CHAM LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1D,
+ },
+ [0xAA1E]={
+ category="lo",
+ description="CHAM LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1E,
+ },
+ [0xAA1F]={
+ category="lo",
+ description="CHAM LETTER MUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1F,
+ },
+ [0xAA20]={
+ category="lo",
+ description="CHAM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA20,
+ },
+ [0xAA21]={
+ category="lo",
+ description="CHAM LETTER BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA21,
+ },
+ [0xAA22]={
+ category="lo",
+ description="CHAM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA22,
+ },
+ [0xAA23]={
+ category="lo",
+ description="CHAM LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA23,
+ },
+ [0xAA24]={
+ category="lo",
+ description="CHAM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA24,
+ },
+ [0xAA25]={
+ category="lo",
+ description="CHAM LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA25,
+ },
+ [0xAA26]={
+ category="lo",
+ description="CHAM LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA26,
+ },
+ [0xAA27]={
+ category="lo",
+ description="CHAM LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA27,
+ },
+ [0xAA28]={
+ category="lo",
+ description="CHAM LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA28,
+ },
+ [0xAA29]={
+ category="mn",
+ description="CHAM VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA29,
+ },
+ [0xAA2A]={
+ category="mn",
+ description="CHAM VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2A,
+ },
+ [0xAA2B]={
+ category="mn",
+ description="CHAM VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2B,
+ },
+ [0xAA2C]={
+ category="mn",
+ description="CHAM VOWEL SIGN EI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2C,
+ },
+ [0xAA2D]={
+ category="mn",
+ description="CHAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2D,
+ },
+ [0xAA2E]={
+ category="mn",
+ description="CHAM VOWEL SIGN OE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2E,
+ },
+ [0xAA2F]={
+ category="mc",
+ description="CHAM VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA2F,
+ },
+ [0xAA30]={
+ category="mc",
+ description="CHAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA30,
+ },
+ [0xAA31]={
+ category="mn",
+ description="CHAM VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA31,
+ },
+ [0xAA32]={
+ category="mn",
+ description="CHAM VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA32,
+ },
+ [0xAA33]={
+ category="mc",
+ description="CHAM CONSONANT SIGN YA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA33,
+ },
+ [0xAA34]={
+ category="mc",
+ description="CHAM CONSONANT SIGN RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA34,
+ },
+ [0xAA35]={
+ category="mn",
+ description="CHAM CONSONANT SIGN LA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA35,
+ },
+ [0xAA36]={
+ category="mn",
+ description="CHAM CONSONANT SIGN WA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA36,
+ },
+ [0xAA40]={
+ category="lo",
+ description="CHAM LETTER FINAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA40,
+ },
+ [0xAA41]={
+ category="lo",
+ description="CHAM LETTER FINAL G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA41,
+ },
+ [0xAA42]={
+ category="lo",
+ description="CHAM LETTER FINAL NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA42,
+ },
+ [0xAA43]={
+ category="mn",
+ description="CHAM CONSONANT SIGN FINAL NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA43,
+ },
+ [0xAA44]={
+ category="lo",
+ description="CHAM LETTER FINAL CH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA44,
+ },
+ [0xAA45]={
+ category="lo",
+ description="CHAM LETTER FINAL T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA45,
+ },
+ [0xAA46]={
+ category="lo",
+ description="CHAM LETTER FINAL N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA46,
+ },
+ [0xAA47]={
+ category="lo",
+ description="CHAM LETTER FINAL P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA47,
+ },
+ [0xAA48]={
+ category="lo",
+ description="CHAM LETTER FINAL Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA48,
+ },
+ [0xAA49]={
+ category="lo",
+ description="CHAM LETTER FINAL R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA49,
+ },
+ [0xAA4A]={
+ category="lo",
+ description="CHAM LETTER FINAL L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA4A,
+ },
+ [0xAA4B]={
+ category="lo",
+ description="CHAM LETTER FINAL SS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA4B,
+ },
+ [0xAA4C]={
+ category="mn",
+ description="CHAM CONSONANT SIGN FINAL M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA4C,
+ },
+ [0xAA4D]={
+ category="mc",
+ description="CHAM CONSONANT SIGN FINAL H",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA4D,
+ },
+ [0xAA50]={
+ category="nd",
+ description="CHAM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA50,
+ },
+ [0xAA51]={
+ category="nd",
+ description="CHAM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA51,
+ },
+ [0xAA52]={
+ category="nd",
+ description="CHAM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA52,
+ },
+ [0xAA53]={
+ category="nd",
+ description="CHAM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA53,
+ },
+ [0xAA54]={
+ category="nd",
+ description="CHAM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA54,
+ },
+ [0xAA55]={
+ category="nd",
+ description="CHAM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA55,
+ },
+ [0xAA56]={
+ category="nd",
+ description="CHAM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA56,
+ },
+ [0xAA57]={
+ category="nd",
+ description="CHAM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA57,
+ },
+ [0xAA58]={
+ category="nd",
+ description="CHAM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA58,
+ },
+ [0xAA59]={
+ category="nd",
+ description="CHAM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA59,
+ },
+ [0xAA5C]={
+ category="po",
+ description="CHAM PUNCTUATION SPIRAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA5C,
+ },
+ [0xAA5D]={
+ category="po",
+ description="CHAM PUNCTUATION DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5D,
+ },
+ [0xAA5E]={
+ category="po",
+ description="CHAM PUNCTUATION DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5E,
+ },
+ [0xAA5F]={
+ category="po",
+ description="CHAM PUNCTUATION TRIPLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5F,
+ },
+ [0xAA60]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA60,
+ },
+ [0xAA61]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA61,
+ },
+ [0xAA62]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA62,
+ },
+ [0xAA63]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI JA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA63,
+ },
+ [0xAA64]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA64,
+ },
+ [0xAA65]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA65,
+ },
+ [0xAA66]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI TTA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA66,
+ },
+ [0xAA67]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI TTHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA67,
+ },
+ [0xAA68]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DDA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA68,
+ },
+ [0xAA69]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DDHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA69,
+ },
+ [0xAA6A]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6A,
+ },
+ [0xAA6B]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6B,
+ },
+ [0xAA6C]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6C,
+ },
+ [0xAA6D]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6D,
+ },
+ [0xAA6E]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI HHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6E,
+ },
+ [0xAA6F]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6F,
+ },
+ [0xAA70]={
+ category="lm",
+ description="MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA70,
+ },
+ [0xAA71]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI XA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA71,
+ },
+ [0xAA72]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI ZA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA72,
+ },
+ [0xAA73]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA73,
+ },
+ [0xAA74]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI OAY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA74,
+ },
+ [0xAA75]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI QN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA75,
+ },
+ [0xAA76]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI HM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA76,
+ },
+ [0xAA77]={
+ category="so",
+ description="MYANMAR SYMBOL AITON EXCLAMATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA77,
+ },
+ [0xAA78]={
+ category="so",
+ description="MYANMAR SYMBOL AITON ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA78,
+ },
+ [0xAA79]={
+ category="so",
+ description="MYANMAR SYMBOL AITON TWO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA79,
+ },
+ [0xAA7A]={
+ category="lo",
+ description="MYANMAR LETTER AITON RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7A,
+ },
+ [0xAA7B]={
+ category="mc",
+ description="MYANMAR SIGN PAO KAREN TONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7B,
+ },
+ [0xAA7C]={
+ category="mn",
+ description="MYANMAR SIGN TAI LAING TONE-2",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAA7C,
+ },
+ [0xAA7D]={
+ category="mc",
+ description="MYANMAR SIGN TAI LAING TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7D,
+ },
+ [0xAA7E]={
+ category="lo",
+ description="MYANMAR LETTER SHWE PALAUNG CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7E,
+ },
+ [0xAA7F]={
+ category="lo",
+ description="MYANMAR LETTER SHWE PALAUNG SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7F,
+ },
+ [0xAA80]={
+ category="lo",
+ description="TAI VIET LETTER LOW KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA80,
+ },
+ [0xAA81]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA81,
+ },
+ [0xAA82]={
+ category="lo",
+ description="TAI VIET LETTER LOW KHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA82,
+ },
+ [0xAA83]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA83,
+ },
+ [0xAA84]={
+ category="lo",
+ description="TAI VIET LETTER LOW KHHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA84,
+ },
+ [0xAA85]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KHHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA85,
+ },
+ [0xAA86]={
+ category="lo",
+ description="TAI VIET LETTER LOW GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA86,
+ },
+ [0xAA87]={
+ category="lo",
+ description="TAI VIET LETTER HIGH GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA87,
+ },
+ [0xAA88]={
+ category="lo",
+ description="TAI VIET LETTER LOW NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA88,
+ },
+ [0xAA89]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA89,
+ },
+ [0xAA8A]={
+ category="lo",
+ description="TAI VIET LETTER LOW CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8A,
+ },
+ [0xAA8B]={
+ category="lo",
+ description="TAI VIET LETTER HIGH CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8B,
+ },
+ [0xAA8C]={
+ category="lo",
+ description="TAI VIET LETTER LOW CHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8C,
+ },
+ [0xAA8D]={
+ category="lo",
+ description="TAI VIET LETTER HIGH CHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8D,
+ },
+ [0xAA8E]={
+ category="lo",
+ description="TAI VIET LETTER LOW SO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8E,
+ },
+ [0xAA8F]={
+ category="lo",
+ description="TAI VIET LETTER HIGH SO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8F,
+ },
+ [0xAA90]={
+ category="lo",
+ description="TAI VIET LETTER LOW NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA90,
+ },
+ [0xAA91]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA91,
+ },
+ [0xAA92]={
+ category="lo",
+ description="TAI VIET LETTER LOW DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA92,
+ },
+ [0xAA93]={
+ category="lo",
+ description="TAI VIET LETTER HIGH DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA93,
+ },
+ [0xAA94]={
+ category="lo",
+ description="TAI VIET LETTER LOW TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA94,
+ },
+ [0xAA95]={
+ category="lo",
+ description="TAI VIET LETTER HIGH TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA95,
+ },
+ [0xAA96]={
+ category="lo",
+ description="TAI VIET LETTER LOW THO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA96,
+ },
+ [0xAA97]={
+ category="lo",
+ description="TAI VIET LETTER HIGH THO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA97,
+ },
+ [0xAA98]={
+ category="lo",
+ description="TAI VIET LETTER LOW NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA98,
+ },
+ [0xAA99]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA99,
+ },
+ [0xAA9A]={
+ category="lo",
+ description="TAI VIET LETTER LOW BO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9A,
+ },
+ [0xAA9B]={
+ category="lo",
+ description="TAI VIET LETTER HIGH BO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9B,
+ },
+ [0xAA9C]={
+ category="lo",
+ description="TAI VIET LETTER LOW PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9C,
+ },
+ [0xAA9D]={
+ category="lo",
+ description="TAI VIET LETTER HIGH PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9D,
+ },
+ [0xAA9E]={
+ category="lo",
+ description="TAI VIET LETTER LOW PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9E,
+ },
+ [0xAA9F]={
+ category="lo",
+ description="TAI VIET LETTER HIGH PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9F,
+ },
+ [0xAAA0]={
+ category="lo",
+ description="TAI VIET LETTER LOW FO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA0,
+ },
+ [0xAAA1]={
+ category="lo",
+ description="TAI VIET LETTER HIGH FO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA1,
+ },
+ [0xAAA2]={
+ category="lo",
+ description="TAI VIET LETTER LOW MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA2,
+ },
+ [0xAAA3]={
+ category="lo",
+ description="TAI VIET LETTER HIGH MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA3,
+ },
+ [0xAAA4]={
+ category="lo",
+ description="TAI VIET LETTER LOW YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA4,
+ },
+ [0xAAA5]={
+ category="lo",
+ description="TAI VIET LETTER HIGH YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA5,
+ },
+ [0xAAA6]={
+ category="lo",
+ description="TAI VIET LETTER LOW RO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA6,
+ },
+ [0xAAA7]={
+ category="lo",
+ description="TAI VIET LETTER HIGH RO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA7,
+ },
+ [0xAAA8]={
+ category="lo",
+ description="TAI VIET LETTER LOW LO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA8,
+ },
+ [0xAAA9]={
+ category="lo",
+ description="TAI VIET LETTER HIGH LO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA9,
+ },
+ [0xAAAA]={
+ category="lo",
+ description="TAI VIET LETTER LOW VO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAA,
+ },
+ [0xAAAB]={
+ category="lo",
+ description="TAI VIET LETTER HIGH VO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAB,
+ },
+ [0xAAAC]={
+ category="lo",
+ description="TAI VIET LETTER LOW HO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAC,
+ },
+ [0xAAAD]={
+ category="lo",
+ description="TAI VIET LETTER HIGH HO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAD,
+ },
+ [0xAAAE]={
+ category="lo",
+ description="TAI VIET LETTER LOW O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAE,
+ },
+ [0xAAAF]={
+ category="lo",
+ description="TAI VIET LETTER HIGH O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAF,
+ },
+ [0xAAB0]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET MAI KANG",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB0,
+ },
+ [0xAAB1]={
+ category="lo",
+ description="TAI VIET VOWEL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB1,
+ },
+ [0xAAB2]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET VOWEL I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB2,
+ },
+ [0xAAB3]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET VOWEL UE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB3,
+ },
+ [0xAAB4]={
+ category="mn",
+ combining=0xDC,
+ description="TAI VIET VOWEL U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB4,
+ },
+ [0xAAB5]={
+ category="lo",
+ description="TAI VIET VOWEL E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB5,
+ },
+ [0xAAB6]={
+ category="lo",
+ description="TAI VIET VOWEL O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB6,
+ },
+ [0xAAB7]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET MAI KHIT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB7,
+ },
+ [0xAAB8]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET VOWEL IA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB8,
+ },
+ [0xAAB9]={
+ category="lo",
+ description="TAI VIET VOWEL UEA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB9,
+ },
+ [0xAABA]={
+ category="lo",
+ description="TAI VIET VOWEL UA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABA,
+ },
+ [0xAABB]={
+ category="lo",
+ description="TAI VIET VOWEL AUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABB,
+ },
+ [0xAABC]={
+ category="lo",
+ description="TAI VIET VOWEL AY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABC,
+ },
+ [0xAABD]={
+ category="lo",
+ description="TAI VIET VOWEL AN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABD,
+ },
+ [0xAABE]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET VOWEL AM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAABE,
+ },
+ [0xAABF]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET TONE MAI EK",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAABF,
+ },
+ [0xAAC0]={
+ category="lo",
+ description="TAI VIET TONE MAI NUENG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAC0,
+ },
+ [0xAAC1]={
+ category="mn",
+ combining=0xE6,
+ description="TAI VIET TONE MAI THO",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAC1,
+ },
+ [0xAAC2]={
+ category="lo",
+ description="TAI VIET TONE MAI SONG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAC2,
+ },
+ [0xAADB]={
+ category="lo",
+ description="TAI VIET SYMBOL KON",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADB,
+ },
+ [0xAADC]={
+ category="lo",
+ description="TAI VIET SYMBOL NUENG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADC,
+ },
+ [0xAADD]={
+ category="lm",
+ description="TAI VIET SYMBOL SAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADD,
+ },
+ [0xAADE]={
+ category="po",
+ description="TAI VIET SYMBOL HO HOI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADE,
+ },
+ [0xAADF]={
+ category="po",
+ description="TAI VIET SYMBOL KOI KOI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADF,
+ },
+ [0xAAE0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE0,
+ },
+ [0xAAE1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE1,
+ },
+ [0xAAE2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE2,
+ },
+ [0xAAE3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE3,
+ },
+ [0xAAE4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE4,
+ },
+ [0xAAE5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE5,
+ },
+ [0xAAE6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE6,
+ },
+ [0xAAE7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE7,
+ },
+ [0xAAE8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE8,
+ },
+ [0xAAE9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE9,
+ },
+ [0xAAEA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAEA,
+ },
+ [0xAAEB]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEB,
+ },
+ [0xAAEC]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAEC,
+ },
+ [0xAAED]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN AAI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAED,
+ },
+ [0xAAEE]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEE,
+ },
+ [0xAAEF]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN AAU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEF,
+ },
+ [0xAAF0]={
+ category="po",
+ description="MEETEI MAYEK CHEIKHAN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAAF0,
+ },
+ [0xAAF1]={
+ category="po",
+ description="MEETEI MAYEK AHANG KHUDAM",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAAF1,
+ },
+ [0xAAF2]={
+ category="lo",
+ description="MEETEI MAYEK ANJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF2,
+ },
+ [0xAAF3]={
+ category="lm",
+ description="MEETEI MAYEK SYLLABLE REPETITION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF3,
+ },
+ [0xAAF4]={
+ category="lm",
+ description="MEETEI MAYEK WORD REPETITION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF4,
+ },
+ [0xAAF5]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAF5,
+ },
+ [0xAAF6]={
+ category="mn",
+ combining=0x9,
+ description="MEETEI MAYEK VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAF6,
+ },
+ [0xAB01]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB01,
+ },
+ [0xAB02]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB02,
+ },
+ [0xAB03]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB03,
+ },
+ [0xAB04]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB04,
+ },
+ [0xAB05]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB05,
+ },
+ [0xAB06]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB06,
+ },
+ [0xAB09]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB09,
+ },
+ [0xAB0A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0A,
+ },
+ [0xAB0B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0B,
+ },
+ [0xAB0C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0C,
+ },
+ [0xAB0D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0D,
+ },
+ [0xAB0E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0E,
+ },
+ [0xAB11]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB11,
+ },
+ [0xAB12]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB12,
+ },
+ [0xAB13]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB13,
+ },
+ [0xAB14]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB14,
+ },
+ [0xAB15]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB15,
+ },
+ [0xAB16]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB16,
+ },
+ [0xAB20]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB20,
+ },
+ [0xAB21]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB21,
+ },
+ [0xAB22]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB22,
+ },
+ [0xAB23]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB23,
+ },
+ [0xAB24]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB24,
+ },
+ [0xAB25]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB25,
+ },
+ [0xAB26]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB26,
+ },
+ [0xAB28]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB28,
+ },
+ [0xAB29]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB29,
+ },
+ [0xAB2A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2A,
+ },
+ [0xAB2B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2B,
+ },
+ [0xAB2C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2C,
+ },
+ [0xAB2D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2D,
+ },
+ [0xAB2E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2E,
+ },
+ [0xAB30]={
+ category="ll",
+ description="LATIN SMALL LETTER BARRED ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB30,
+ },
+ [0xAB31]={
+ category="ll",
+ description="LATIN SMALL LETTER A REVERSED-SCHWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB31,
+ },
+ [0xAB32]={
+ category="ll",
+ description="LATIN SMALL LETTER BLACKLETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB32,
+ },
+ [0xAB33]={
+ category="ll",
+ description="LATIN SMALL LETTER BARRED E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB33,
+ },
+ [0xAB34]={
+ category="ll",
+ description="LATIN SMALL LETTER E WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB34,
+ },
+ [0xAB35]={
+ category="ll",
+ description="LATIN SMALL LETTER LENIS F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB35,
+ },
+ [0xAB36]={
+ category="ll",
+ description="LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB36,
+ },
+ [0xAB37]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH INVERTED LAZY S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB37,
+ },
+ [0xAB38]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB38,
+ },
+ [0xAB39]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB39,
+ },
+ [0xAB3A]={
+ category="ll",
+ description="LATIN SMALL LETTER M WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3A,
+ },
+ [0xAB3B]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3B,
+ },
+ [0xAB3C]={
+ category="ll",
+ description="LATIN SMALL LETTER ENG WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3C,
+ },
+ [0xAB3D]={
+ category="ll",
+ description="LATIN SMALL LETTER BLACKLETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3D,
+ },
+ [0xAB3E]={
+ category="ll",
+ description="LATIN SMALL LETTER BLACKLETTER O WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3E,
+ },
+ [0xAB3F]={
+ category="ll",
+ description="LATIN SMALL LETTER OPEN O WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB3F,
+ },
+ [0xAB40]={
+ category="ll",
+ description="LATIN SMALL LETTER INVERTED OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB40,
+ },
+ [0xAB41]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED OE WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB41,
+ },
+ [0xAB42]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB42,
+ },
+ [0xAB43]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED O OPEN-O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB43,
+ },
+ [0xAB44]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB44,
+ },
+ [0xAB45]={
+ category="ll",
+ description="LATIN SMALL LETTER STIRRUP R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB45,
+ },
+ [0xAB46]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB46,
+ },
+ [0xAB47]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITHOUT HANDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB47,
+ },
+ [0xAB48]={
+ category="ll",
+ description="LATIN SMALL LETTER DOUBLE R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB48,
+ },
+ [0xAB49]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB49,
+ },
+ [0xAB4A]={
+ category="ll",
+ description="LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4A,
+ },
+ [0xAB4B]={
+ category="ll",
+ description="LATIN SMALL LETTER SCRIPT R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4B,
+ },
+ [0xAB4C]={
+ category="ll",
+ description="LATIN SMALL LETTER SCRIPT R WITH RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4C,
+ },
+ [0xAB4D]={
+ category="ll",
+ description="LATIN SMALL LETTER BASELINE ESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4D,
+ },
+ [0xAB4E]={
+ category="ll",
+ description="LATIN SMALL LETTER U WITH SHORT RIGHT LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4E,
+ },
+ [0xAB4F]={
+ category="ll",
+ description="LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB4F,
+ },
+ [0xAB50]={
+ category="ll",
+ description="LATIN SMALL LETTER UI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB50,
+ },
+ [0xAB51]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED UI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB51,
+ },
+ [0xAB52]={
+ category="ll",
+ description="LATIN SMALL LETTER U WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB52,
+ },
+ [0xAB53]={
+ category="ll",
+ description="LATIN SMALL LETTER CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB53,
+ },
+ [0xAB54]={
+ category="ll",
+ description="LATIN SMALL LETTER CHI WITH LOW RIGHT RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB54,
+ },
+ [0xAB55]={
+ category="ll",
+ description="LATIN SMALL LETTER CHI WITH LOW LEFT SERIF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB55,
+ },
+ [0xAB56]={
+ category="ll",
+ description="LATIN SMALL LETTER X WITH LOW RIGHT RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB56,
+ },
+ [0xAB57]={
+ category="ll",
+ description="LATIN SMALL LETTER X WITH LONG LEFT LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB57,
+ },
+ [0xAB58]={
+ category="ll",
+ description="LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB58,
+ },
+ [0xAB59]={
+ category="ll",
+ description="LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB59,
+ },
+ [0xAB5A]={
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH SHORT RIGHT LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB5A,
+ },
+ [0xAB5B]={
+ category="sk",
+ description="MODIFIER BREVE WITH INVERTED BREVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB5B,
+ },
+ [0xAB5C]={
+ category="lm",
+ description="MODIFIER LETTER SMALL HENG",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xA727 },
+ unicodeslot=0xAB5C,
+ },
+ [0xAB5D]={
+ category="lm",
+ description="MODIFIER LETTER SMALL L WITH INVERTED LAZY S",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xAB37 },
+ unicodeslot=0xAB5D,
+ },
+ [0xAB5E]={
+ category="lm",
+ description="MODIFIER LETTER SMALL L WITH MIDDLE TILDE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x26B },
+ unicodeslot=0xAB5E,
+ },
+ [0xAB5F]={
+ category="lm",
+ description="MODIFIER LETTER SMALL U WITH LEFT HOOK",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xAB52 },
+ unicodeslot=0xAB5F,
+ },
+ [0xAB60]={
+ category="ll",
+ description="LATIN SMALL LETTER SAKHA YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB60,
+ },
+ [0xAB61]={
+ category="ll",
+ description="LATIN SMALL LETTER IOTIFIED E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB61,
+ },
+ [0xAB62]={
+ category="ll",
+ description="LATIN SMALL LETTER OPEN OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB62,
+ },
+ [0xAB63]={
+ category="ll",
+ description="LATIN SMALL LETTER UO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB63,
+ },
+ [0xAB64]={
+ category="ll",
+ description="LATIN SMALL LETTER INVERTED ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB64,
+ },
+ [0xAB65]={
+ category="ll",
+ description="GREEK LETTER SMALL CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB65,
+ },
+ [0xAB70]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB70,
+ },
+ [0xAB71]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB71,
+ },
+ [0xAB72]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB72,
+ },
+ [0xAB73]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB73,
+ },
+ [0xAB74]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB74,
+ },
+ [0xAB75]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB75,
+ },
+ [0xAB76]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB76,
+ },
+ [0xAB77]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB77,
+ },
+ [0xAB78]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB78,
+ },
+ [0xAB79]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB79,
+ },
+ [0xAB7A]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7A,
+ },
+ [0xAB7B]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7B,
+ },
+ [0xAB7C]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER GV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7C,
+ },
+ [0xAB7D]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7D,
+ },
+ [0xAB7E]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7E,
+ },
+ [0xAB7F]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB7F,
+ },
+ [0xAB80]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB80,
+ },
+ [0xAB81]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB81,
+ },
+ [0xAB82]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB82,
+ },
+ [0xAB83]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB83,
+ },
+ [0xAB84]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB84,
+ },
+ [0xAB85]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB85,
+ },
+ [0xAB86]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB86,
+ },
+ [0xAB87]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB87,
+ },
+ [0xAB88]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER LV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB88,
+ },
+ [0xAB89]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB89,
+ },
+ [0xAB8A]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8A,
+ },
+ [0xAB8B]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8B,
+ },
+ [0xAB8C]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8C,
+ },
+ [0xAB8D]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8D,
+ },
+ [0xAB8E]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8E,
+ },
+ [0xAB8F]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER HNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB8F,
+ },
+ [0xAB90]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB90,
+ },
+ [0xAB91]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB91,
+ },
+ [0xAB92]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB92,
+ },
+ [0xAB93]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB93,
+ },
+ [0xAB94]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB94,
+ },
+ [0xAB95]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER NV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB95,
+ },
+ [0xAB96]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB96,
+ },
+ [0xAB97]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB97,
+ },
+ [0xAB98]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB98,
+ },
+ [0xAB99]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB99,
+ },
+ [0xAB9A]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9A,
+ },
+ [0xAB9B]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER QUV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9B,
+ },
+ [0xAB9C]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9C,
+ },
+ [0xAB9D]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9D,
+ },
+ [0xAB9E]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9E,
+ },
+ [0xAB9F]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB9F,
+ },
+ [0xABA0]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA0,
+ },
+ [0xABA1]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA1,
+ },
+ [0xABA2]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER SV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA2,
+ },
+ [0xABA3]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA3,
+ },
+ [0xABA4]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA4,
+ },
+ [0xABA5]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA5,
+ },
+ [0xABA6]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA6,
+ },
+ [0xABA7]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA7,
+ },
+ [0xABA8]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA8,
+ },
+ [0xABA9]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABA9,
+ },
+ [0xABAA]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAA,
+ },
+ [0xABAB]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAB,
+ },
+ [0xABAC]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER DLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAC,
+ },
+ [0xABAD]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAD,
+ },
+ [0xABAE]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAE,
+ },
+ [0xABAF]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABAF,
+ },
+ [0xABB0]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB0,
+ },
+ [0xABB1]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB1,
+ },
+ [0xABB2]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TLV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB2,
+ },
+ [0xABB3]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB3,
+ },
+ [0xABB4]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB4,
+ },
+ [0xABB5]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB5,
+ },
+ [0xABB6]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB6,
+ },
+ [0xABB7]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB7,
+ },
+ [0xABB8]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER TSV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB8,
+ },
+ [0xABB9]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABB9,
+ },
+ [0xABBA]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBA,
+ },
+ [0xABBB]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBB,
+ },
+ [0xABBC]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBC,
+ },
+ [0xABBD]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBD,
+ },
+ [0xABBE]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER WV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBE,
+ },
+ [0xABBF]={
+ category="ll",
+ description="CHEROKEE SMALL LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABBF,
+ },
+ [0xABC0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC0,
+ },
+ [0xABC1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC1,
+ },
+ [0xABC2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER LAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC2,
+ },
+ [0xABC3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER MIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC3,
+ },
+ [0xABC4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC4,
+ },
+ [0xABC5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC5,
+ },
+ [0xABC6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER CHIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC6,
+ },
+ [0xABC7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC7,
+ },
+ [0xABC8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC8,
+ },
+ [0xABC9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NGOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC9,
+ },
+ [0xABCA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER THOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCA,
+ },
+ [0xABCB]={
+ category="lo",
+ description="MEETEI MAYEK LETTER WAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCB,
+ },
+ [0xABCC]={
+ category="lo",
+ description="MEETEI MAYEK LETTER YANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCC,
+ },
+ [0xABCD]={
+ category="lo",
+ description="MEETEI MAYEK LETTER HUK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCD,
+ },
+ [0xABCE]={
+ category="lo",
+ description="MEETEI MAYEK LETTER UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCE,
+ },
+ [0xABCF]={
+ category="lo",
+ description="MEETEI MAYEK LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCF,
+ },
+ [0xABD0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD0,
+ },
+ [0xABD1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER ATIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD1,
+ },
+ [0xABD2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER GOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD2,
+ },
+ [0xABD3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER JHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD3,
+ },
+ [0xABD4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER RAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD4,
+ },
+ [0xABD5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD5,
+ },
+ [0xABD6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER JIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD6,
+ },
+ [0xABD7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD7,
+ },
+ [0xABD8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER GHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD8,
+ },
+ [0xABD9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD9,
+ },
+ [0xABDA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER BHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDA,
+ },
+ [0xABDB]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KOK LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDB,
+ },
+ [0xABDC]={
+ category="lo",
+ description="MEETEI MAYEK LETTER LAI LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDC,
+ },
+ [0xABDD]={
+ category="lo",
+ description="MEETEI MAYEK LETTER MIT LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDD,
+ },
+ [0xABDE]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PA LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDE,
+ },
+ [0xABDF]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NA LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDF,
+ },
+ [0xABE0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TIL LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE0,
+ },
+ [0xABE1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NGOU LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE1,
+ },
+ [0xABE2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER I LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE2,
+ },
+ [0xABE3]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN ONAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE3,
+ },
+ [0xABE4]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN INAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE4,
+ },
+ [0xABE5]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN ANAP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABE5,
+ },
+ [0xABE6]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN YENAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE6,
+ },
+ [0xABE7]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN SOUNAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE7,
+ },
+ [0xABE8]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN UNAP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABE8,
+ },
+ [0xABE9]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN CHEINAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE9,
+ },
+ [0xABEA]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN NUNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABEA,
+ },
+ [0xABEB]={
+ category="po",
+ description="MEETEI MAYEK CHEIKHEI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xABEB,
+ },
+ [0xABEC]={
+ category="mc",
+ description="MEETEI MAYEK LUM IYEK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABEC,
+ },
+ [0xABED]={
+ category="mn",
+ combining=0x9,
+ description="MEETEI MAYEK APUN IYEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABED,
+ },
+ [0xABF0]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF0,
+ },
+ [0xABF1]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF1,
+ },
+ [0xABF2]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF2,
+ },
+ [0xABF3]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF3,
+ },
+ [0xABF4]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF4,
+ },
+ [0xABF5]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF5,
+ },
+ [0xABF6]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF6,
+ },
+ [0xABF7]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF7,
+ },
+ [0xABF8]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF8,
+ },
+ [0xABF9]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF9,
+ },
+ [0xD7B0]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B0,
+ },
+ [0xD7B1]={
+ category="lo",
+ description="HANGUL JUNGSEONG O-O-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B1,
+ },
+ [0xD7B2]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B2,
+ },
+ [0xD7B3]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B3,
+ },
+ [0xD7B4]={
+ category="lo",
+ description="HANGUL JUNGSEONG YO-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B4,
+ },
+ [0xD7B5]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B5,
+ },
+ [0xD7B6]={
+ category="lo",
+ description="HANGUL JUNGSEONG U-I-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B6,
+ },
+ [0xD7B7]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B7,
+ },
+ [0xD7B8]={
+ category="lo",
+ description="HANGUL JUNGSEONG YU-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B8,
+ },
+ [0xD7B9]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B9,
+ },
+ [0xD7BA]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BA,
+ },
+ [0xD7BB]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BB,
+ },
+ [0xD7BC]={
+ category="lo",
+ description="HANGUL JUNGSEONG EU-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BC,
+ },
+ [0xD7BD]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YA-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BD,
+ },
+ [0xD7BE]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BE,
+ },
+ [0xD7BF]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BF,
+ },
+ [0xD7C0]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C0,
+ },
+ [0xD7C1]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-O-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C1,
+ },
+ [0xD7C2]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C2,
+ },
+ [0xD7C3]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-YU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C3,
+ },
+ [0xD7C4]={
+ category="lo",
+ description="HANGUL JUNGSEONG I-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C4,
+ },
+ [0xD7C5]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C5,
+ },
+ [0xD7C6]={
+ category="lo",
+ description="HANGUL JUNGSEONG ARAEA-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C6,
+ },
+ [0xD7CB]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CB,
+ },
+ [0xD7CC]={
+ category="lo",
+ description="HANGUL JONGSEONG NIEUN-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CC,
+ },
+ [0xD7CD]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGTIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CD,
+ },
+ [0xD7CE]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGTIKEUT-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CE,
+ },
+ [0xD7CF]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CF,
+ },
+ [0xD7D0]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D0,
+ },
+ [0xD7D1]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D1,
+ },
+ [0xD7D2]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D2,
+ },
+ [0xD7D3]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D3,
+ },
+ [0xD7D4]={
+ category="lo",
+ description="HANGUL JONGSEONG TIKEUT-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D4,
+ },
+ [0xD7D5]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-SSANGKIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D5,
+ },
+ [0xD7D6]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D6,
+ },
+ [0xD7D7]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGRIEUL-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D7,
+ },
+ [0xD7D8]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-MIEUM-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D8,
+ },
+ [0xD7D9]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D9,
+ },
+ [0xD7DA]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DA,
+ },
+ [0xD7DB]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-YESIEUNG",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DB,
+ },
+ [0xD7DC]={
+ category="lo",
+ description="HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DC,
+ },
+ [0xD7DD]={
+ category="lo",
+ description="HANGUL JONGSEONG KAPYEOUNRIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DD,
+ },
+ [0xD7DE]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DE,
+ },
+ [0xD7DF]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-SSANGNIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DF,
+ },
+ [0xD7E0]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGMIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E0,
+ },
+ [0xD7E1]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-PIEUP-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E1,
+ },
+ [0xD7E2]={
+ category="lo",
+ description="HANGUL JONGSEONG MIEUM-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E2,
+ },
+ [0xD7E3]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E3,
+ },
+ [0xD7E4]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E4,
+ },
+ [0xD7E5]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E5,
+ },
+ [0xD7E6]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E6,
+ },
+ [0xD7E7]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-SIOS-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E7,
+ },
+ [0xD7E8]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E8,
+ },
+ [0xD7E9]={
+ category="lo",
+ description="HANGUL JONGSEONG PIEUP-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E9,
+ },
+ [0xD7EA]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EA,
+ },
+ [0xD7EB]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EB,
+ },
+ [0xD7EC]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGSIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EC,
+ },
+ [0xD7ED]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGSIOS-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7ED,
+ },
+ [0xD7EE]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EE,
+ },
+ [0xD7EF]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EF,
+ },
+ [0xD7F0]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F0,
+ },
+ [0xD7F1]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F1,
+ },
+ [0xD7F2]={
+ category="lo",
+ description="HANGUL JONGSEONG SIOS-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F2,
+ },
+ [0xD7F3]={
+ category="lo",
+ description="HANGUL JONGSEONG PANSIOS-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F3,
+ },
+ [0xD7F4]={
+ category="lo",
+ description="HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F4,
+ },
+ [0xD7F5]={
+ category="lo",
+ description="HANGUL JONGSEONG YESIEUNG-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F5,
+ },
+ [0xD7F6]={
+ category="lo",
+ description="HANGUL JONGSEONG YESIEUNG-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F6,
+ },
+ [0xD7F7]={
+ category="lo",
+ description="HANGUL JONGSEONG CIEUC-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F7,
+ },
+ [0xD7F8]={
+ category="lo",
+ description="HANGUL JONGSEONG CIEUC-SSANGPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F8,
+ },
+ [0xD7F9]={
+ category="lo",
+ description="HANGUL JONGSEONG SSANGCIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F9,
+ },
+ [0xD7FA]={
+ category="lo",
+ description="HANGUL JONGSEONG PHIEUPH-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7FA,
+ },
+ [0xD7FB]={
+ category="lo",
+ description="HANGUL JONGSEONG PHIEUPH-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7FB,
+ },
+ [0xD800]={
+ category="cs",
+ description="<Non Private Use High Surrogate, First>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xD800,
+ },
+ [0xDB7F]={
+ category="cs",
+ description="<Non Private Use High Surrogate, Last>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xDB7F,
+ },
+ [0xDB80]={
+ category="cs",
+ description="<Private Use High Surrogate, First>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xDB80,
+ },
+ [0xDBFF]={
+ category="cs",
+ description="<Private Use High Surrogate, Last>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xDBFF,
+ },
+ [0xDC00]={
+ category="cs",
+ description="<Low Surrogate, First>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xDC00,
+ },
+ [0xDFFF]={
+ category="cs",
+ description="<Low Surrogate, Last>",
+ direction="l",
+ linebreak="sg",
+ unicodeslot=0xDFFF,
+ },
+ [0xE000]={
+ category="co",
+ cjkwd="a",
+ description="<Private Use, First>",
+ direction="l",
+ unicodeslot=0xE000,
+ },
+ [0xF8FF]={
+ adobename="apple",
+ category="co",
+ cjkwd="a",
+ description="<Private Use, Last>",
+ direction="l",
+ unicodeslot=0xF8FF,
+ },
+ [0xF900]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0384",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8C48 },
+ unicodeslot=0xF900,
+ },
+ [0xF901]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0385",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x66F4 },
+ unicodeslot=0xF901,
+ },
+ [0xF902]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0386",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8ECA },
+ unicodeslot=0xF902,
+ },
+ [0xF903]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0387",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8CC8 },
+ unicodeslot=0xF903,
+ },
+ [0xF904]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0388",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6ED1 },
+ unicodeslot=0xF904,
+ },
+ [0xF905]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0389",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E32 },
+ unicodeslot=0xF905,
+ },
+ [0xF906]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53E5 },
+ unicodeslot=0xF906,
+ },
+ [0xF907]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F9C },
+ unicodeslot=0xF907,
+ },
+ [0xF908]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F9C },
+ unicodeslot=0xF908,
+ },
+ [0xF909]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5951 },
+ unicodeslot=0xF909,
+ },
+ [0xF90A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x91D1 },
+ unicodeslot=0xF90A,
+ },
+ [0xF90B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5587 },
+ unicodeslot=0xF90B,
+ },
+ [0xF90C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5948 },
+ unicodeslot=0xF90C,
+ },
+ [0xF90D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61F6 },
+ unicodeslot=0xF90D,
+ },
+ [0xF90E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7669 },
+ unicodeslot=0xF90E,
+ },
+ [0xF90F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F85 },
+ unicodeslot=0xF90F,
+ },
+ [0xF910]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x863F },
+ unicodeslot=0xF910,
+ },
+ [0xF911]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x038F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x87BA },
+ unicodeslot=0xF911,
+ },
+ [0xF912]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0390",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88F8 },
+ unicodeslot=0xF912,
+ },
+ [0xF913]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0391",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x908F },
+ unicodeslot=0xF913,
+ },
+ [0xF914]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0392",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6A02 },
+ unicodeslot=0xF914,
+ },
+ [0xF915]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0393",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D1B },
+ unicodeslot=0xF915,
+ },
+ [0xF916]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0394",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x70D9 },
+ unicodeslot=0xF916,
+ },
+ [0xF917]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0395",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x73DE },
+ unicodeslot=0xF917,
+ },
+ [0xF918]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0396",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x843D },
+ unicodeslot=0xF918,
+ },
+ [0xF919]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0397",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x916A },
+ unicodeslot=0xF919,
+ },
+ [0xF91A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x99F1 },
+ unicodeslot=0xF91A,
+ },
+ [0xF91B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E82 },
+ unicodeslot=0xF91B,
+ },
+ [0xF91C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5375 },
+ unicodeslot=0xF91C,
+ },
+ [0xF91D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B04 },
+ unicodeslot=0xF91D,
+ },
+ [0xF91E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x721B },
+ unicodeslot=0xF91E,
+ },
+ [0xF91F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x862D },
+ unicodeslot=0xF91F,
+ },
+ [0xF920]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0398",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9E1E },
+ unicodeslot=0xF920,
+ },
+ [0xF921]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0399",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D50 },
+ unicodeslot=0xF921,
+ },
+ [0xF922]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6FEB },
+ unicodeslot=0xF922,
+ },
+ [0xF923]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x85CD },
+ unicodeslot=0xF923,
+ },
+ [0xF924]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8964 },
+ unicodeslot=0xF924,
+ },
+ [0xF925]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62C9 },
+ unicodeslot=0xF925,
+ },
+ [0xF926]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x81D8 },
+ unicodeslot=0xF926,
+ },
+ [0xF927]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x039F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x881F },
+ unicodeslot=0xF927,
+ },
+ [0xF928]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5ECA },
+ unicodeslot=0xF928,
+ },
+ [0xF929]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6717 },
+ unicodeslot=0xF929,
+ },
+ [0xF92A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D6A },
+ unicodeslot=0xF92A,
+ },
+ [0xF92B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x72FC },
+ unicodeslot=0xF92B,
+ },
+ [0xF92C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x90CE },
+ unicodeslot=0xF92C,
+ },
+ [0xF92D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4F86 },
+ unicodeslot=0xF92D,
+ },
+ [0xF92E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51B7 },
+ unicodeslot=0xF92E,
+ },
+ [0xF92F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52DE },
+ unicodeslot=0xF92F,
+ },
+ [0xF930]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x64C4 },
+ unicodeslot=0xF930,
+ },
+ [0xF931]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6AD3 },
+ unicodeslot=0xF931,
+ },
+ [0xF932]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7210 },
+ unicodeslot=0xF932,
+ },
+ [0xF933]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76E7 },
+ unicodeslot=0xF933,
+ },
+ [0xF934]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8001 },
+ unicodeslot=0xF934,
+ },
+ [0xF935]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8606 },
+ unicodeslot=0xF935,
+ },
+ [0xF936]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x865C },
+ unicodeslot=0xF936,
+ },
+ [0xF937]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03A9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8DEF },
+ unicodeslot=0xF937,
+ },
+ [0xF938]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9732 },
+ unicodeslot=0xF938,
+ },
+ [0xF939]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9B6F },
+ unicodeslot=0xF939,
+ },
+ [0xF93A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9DFA },
+ unicodeslot=0xF93A,
+ },
+ [0xF93B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x788C },
+ unicodeslot=0xF93B,
+ },
+ [0xF93C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x797F },
+ unicodeslot=0xF93C,
+ },
+ [0xF93D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DA0 },
+ unicodeslot=0xF93D,
+ },
+ [0xF93E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83C9 },
+ unicodeslot=0xF93E,
+ },
+ [0xF93F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9304 },
+ unicodeslot=0xF93F,
+ },
+ [0xF940]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9E7F },
+ unicodeslot=0xF940,
+ },
+ [0xF941]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AD6 },
+ unicodeslot=0xF941,
+ },
+ [0xF942]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58DF },
+ unicodeslot=0xF942,
+ },
+ [0xF943]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F04 },
+ unicodeslot=0xF943,
+ },
+ [0xF944]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7C60 },
+ unicodeslot=0xF944,
+ },
+ [0xF945]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x807E },
+ unicodeslot=0xF945,
+ },
+ [0xF946]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7262 },
+ unicodeslot=0xF946,
+ },
+ [0xF947]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x78CA },
+ unicodeslot=0xF947,
+ },
+ [0xF948]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8CC2 },
+ unicodeslot=0xF948,
+ },
+ [0xF949]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96F7 },
+ unicodeslot=0xF949,
+ },
+ [0xF94A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005EA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58D8 },
+ unicodeslot=0xF94A,
+ },
+ [0xF94B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005EB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C62 },
+ unicodeslot=0xF94B,
+ },
+ [0xF94C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005EC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6A13 },
+ unicodeslot=0xF94C,
+ },
+ [0xF94D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005ED",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6DDA },
+ unicodeslot=0xF94D,
+ },
+ [0xF94E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005EE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6F0F },
+ unicodeslot=0xF94E,
+ },
+ [0xF94F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005EF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D2F },
+ unicodeslot=0xF94F,
+ },
+ [0xF950]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7E37 },
+ unicodeslot=0xF950,
+ },
+ [0xF951]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x964B },
+ unicodeslot=0xF951,
+ },
+ [0xF952]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52D2 },
+ unicodeslot=0xF952,
+ },
+ [0xF953]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03B9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x808B },
+ unicodeslot=0xF953,
+ },
+ [0xF954]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51DC },
+ unicodeslot=0xF954,
+ },
+ [0xF955]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51CC },
+ unicodeslot=0xF955,
+ },
+ [0xF956]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A1C },
+ unicodeslot=0xF956,
+ },
+ [0xF957]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DBE },
+ unicodeslot=0xF957,
+ },
+ [0xF958]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83F1 },
+ unicodeslot=0xF958,
+ },
+ [0xF959]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9675 },
+ unicodeslot=0xF959,
+ },
+ [0xF95A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B80 },
+ unicodeslot=0xF95A,
+ },
+ [0xF95B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62CF },
+ unicodeslot=0xF95B,
+ },
+ [0xF95C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6A02 },
+ unicodeslot=0xF95C,
+ },
+ [0xF95D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AFE },
+ unicodeslot=0xF95D,
+ },
+ [0xF95E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E39 },
+ unicodeslot=0xF95E,
+ },
+ [0xF95F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x005FF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BE7 },
+ unicodeslot=0xF95F,
+ },
+ [0xF960]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6012 },
+ unicodeslot=0xF960,
+ },
+ [0xF961]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7387 },
+ unicodeslot=0xF961,
+ },
+ [0xF962]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7570 },
+ unicodeslot=0xF962,
+ },
+ [0xF963]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5317 },
+ unicodeslot=0xF963,
+ },
+ [0xF964]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x78FB },
+ unicodeslot=0xF964,
+ },
+ [0xF965]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4FBF },
+ unicodeslot=0xF965,
+ },
+ [0xF966]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FA9 },
+ unicodeslot=0xF966,
+ },
+ [0xF967]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E0D },
+ unicodeslot=0xF967,
+ },
+ [0xF968]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6CCC },
+ unicodeslot=0xF968,
+ },
+ [0xF969]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03C9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6578 },
+ unicodeslot=0xF969,
+ },
+ [0xF96A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D22 },
+ unicodeslot=0xF96A,
+ },
+ [0xF96B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53C3 },
+ unicodeslot=0xF96B,
+ },
+ [0xF96C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x585E },
+ unicodeslot=0xF96C,
+ },
+ [0xF96D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7701 },
+ unicodeslot=0xF96D,
+ },
+ [0xF96E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8449 },
+ unicodeslot=0xF96E,
+ },
+ [0xF96F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0060F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AAA },
+ unicodeslot=0xF96F,
+ },
+ [0xF970]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6BBA },
+ unicodeslot=0xF970,
+ },
+ [0xF971]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8FB0 },
+ unicodeslot=0xF971,
+ },
+ [0xF972]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6C88 },
+ unicodeslot=0xF972,
+ },
+ [0xF973]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62FE },
+ unicodeslot=0xF973,
+ },
+ [0xF974]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82E5 },
+ unicodeslot=0xF974,
+ },
+ [0xF975]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x63A0 },
+ unicodeslot=0xF975,
+ },
+ [0xF976]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7565 },
+ unicodeslot=0xF976,
+ },
+ [0xF977]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4EAE },
+ unicodeslot=0xF977,
+ },
+ [0xF978]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5169 },
+ unicodeslot=0xF978,
+ },
+ [0xF979]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51C9 },
+ unicodeslot=0xF979,
+ },
+ [0xF97A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6881 },
+ unicodeslot=0xF97A,
+ },
+ [0xF97B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CE7 },
+ unicodeslot=0xF97B,
+ },
+ [0xF97C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x826F },
+ unicodeslot=0xF97C,
+ },
+ [0xF97D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AD2 },
+ unicodeslot=0xF97D,
+ },
+ [0xF97E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x91CF },
+ unicodeslot=0xF97E,
+ },
+ [0xF97F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0061F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52F5 },
+ unicodeslot=0xF97F,
+ },
+ [0xF980]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5442 },
+ unicodeslot=0xF980,
+ },
+ [0xF981]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5973 },
+ unicodeslot=0xF981,
+ },
+ [0xF982]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EEC },
+ unicodeslot=0xF982,
+ },
+ [0xF983]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x65C5 },
+ unicodeslot=0xF983,
+ },
+ [0xF984]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6FFE },
+ unicodeslot=0xF984,
+ },
+ [0xF985]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03D9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x792A },
+ unicodeslot=0xF985,
+ },
+ [0xF986]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x95AD },
+ unicodeslot=0xF986,
+ },
+ [0xF987]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9A6A },
+ unicodeslot=0xF987,
+ },
+ [0xF988]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9E97 },
+ unicodeslot=0xF988,
+ },
+ [0xF989]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9ECE },
+ unicodeslot=0xF989,
+ },
+ [0xF98A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x529B },
+ unicodeslot=0xF98A,
+ },
+ [0xF98B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x66C6 },
+ unicodeslot=0xF98B,
+ },
+ [0xF98C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B77 },
+ unicodeslot=0xF98C,
+ },
+ [0xF98D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F62 },
+ unicodeslot=0xF98D,
+ },
+ [0xF98E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5E74 },
+ unicodeslot=0xF98E,
+ },
+ [0xF98F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0062F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6190 },
+ unicodeslot=0xF98F,
+ },
+ [0xF990]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6200 },
+ unicodeslot=0xF990,
+ },
+ [0xF991]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x649A },
+ unicodeslot=0xF991,
+ },
+ [0xF992]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6F23 },
+ unicodeslot=0xF992,
+ },
+ [0xF993]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7149 },
+ unicodeslot=0xF993,
+ },
+ [0xF994]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7489 },
+ unicodeslot=0xF994,
+ },
+ [0xF995]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x79CA },
+ unicodeslot=0xF995,
+ },
+ [0xF996]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DF4 },
+ unicodeslot=0xF996,
+ },
+ [0xF997]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x806F },
+ unicodeslot=0xF997,
+ },
+ [0xF998]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F26 },
+ unicodeslot=0xF998,
+ },
+ [0xF999]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x03E7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x84EE },
+ unicodeslot=0xF999,
+ },
+ [0xF99A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9023 },
+ unicodeslot=0xF99A,
+ },
+ [0xF99B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x934A },
+ unicodeslot=0xF99B,
+ },
+ [0xF99C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5217 },
+ unicodeslot=0xF99C,
+ },
+ [0xF99D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52A3 },
+ unicodeslot=0xF99D,
+ },
+ [0xF99E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x54BD },
+ unicodeslot=0xF99E,
+ },
+ [0xF99F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0063F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x70C8 },
+ unicodeslot=0xF99F,
+ },
+ [0xF9A0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88C2 },
+ unicodeslot=0xF9A0,
+ },
+ [0xF9A1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AAA },
+ unicodeslot=0xF9A1,
+ },
+ [0xF9A2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EC9 },
+ unicodeslot=0xF9A2,
+ },
+ [0xF9A3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FF5 },
+ unicodeslot=0xF9A3,
+ },
+ [0xF9A4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x637B },
+ unicodeslot=0xF9A4,
+ },
+ [0xF9A5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6BAE },
+ unicodeslot=0xF9A5,
+ },
+ [0xF9A6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7C3E },
+ unicodeslot=0xF9A6,
+ },
+ [0xF9A7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7375 },
+ unicodeslot=0xF9A7,
+ },
+ [0xF9A8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4EE4 },
+ unicodeslot=0xF9A8,
+ },
+ [0xF9A9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009A0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x56F9 },
+ unicodeslot=0xF9A9,
+ },
+ [0xF9AA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BE7 },
+ unicodeslot=0xF9AA,
+ },
+ [0xF9AB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5DBA },
+ unicodeslot=0xF9AB,
+ },
+ [0xF9AC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x601C },
+ unicodeslot=0xF9AC,
+ },
+ [0xF9AD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x73B2 },
+ unicodeslot=0xF9AD,
+ },
+ [0xF9AE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7469 },
+ unicodeslot=0xF9AE,
+ },
+ [0xF9AF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F9A },
+ unicodeslot=0xF9AF,
+ },
+ [0xF9B0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8046 },
+ unicodeslot=0xF9B0,
+ },
+ [0xF9B1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9234 },
+ unicodeslot=0xF9B1,
+ },
+ [0xF9B2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96F6 },
+ unicodeslot=0xF9B2,
+ },
+ [0xF9B3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9748 },
+ unicodeslot=0xF9B3,
+ },
+ [0xF9B4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9818 },
+ unicodeslot=0xF9B4,
+ },
+ [0xF9B5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4F8B },
+ unicodeslot=0xF9B5,
+ },
+ [0xF9B6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x79AE },
+ unicodeslot=0xF9B6,
+ },
+ [0xF9B7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x91B4 },
+ unicodeslot=0xF9B7,
+ },
+ [0xF9B8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96B8 },
+ unicodeslot=0xF9B8,
+ },
+ [0xF9B9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009B0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x60E1 },
+ unicodeslot=0xF9B9,
+ },
+ [0xF9BA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E86 },
+ unicodeslot=0xF9BA,
+ },
+ [0xF9BB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x50DA },
+ unicodeslot=0xF9BB,
+ },
+ [0xF9BC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BEE },
+ unicodeslot=0xF9BC,
+ },
+ [0xF9BD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C3F },
+ unicodeslot=0xF9BD,
+ },
+ [0xF9BE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6599 },
+ unicodeslot=0xF9BE,
+ },
+ [0xF9BF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6A02 },
+ unicodeslot=0xF9BF,
+ },
+ [0xF9C0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x71CE },
+ unicodeslot=0xF9C0,
+ },
+ [0xF9C1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7642 },
+ unicodeslot=0xF9C1,
+ },
+ [0xF9C2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x84FC },
+ unicodeslot=0xF9C2,
+ },
+ [0xF9C3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x907C },
+ unicodeslot=0xF9C3,
+ },
+ [0xF9C4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F8D },
+ unicodeslot=0xF9C4,
+ },
+ [0xF9C5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6688 },
+ unicodeslot=0xF9C5,
+ },
+ [0xF9C6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x962E },
+ unicodeslot=0xF9C6,
+ },
+ [0xF9C7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5289 },
+ unicodeslot=0xF9C7,
+ },
+ [0xF9C8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x677B },
+ unicodeslot=0xF9C8,
+ },
+ [0xF9C9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009C0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x67F3 },
+ unicodeslot=0xF9C9,
+ },
+ [0xF9CA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D41 },
+ unicodeslot=0xF9CA,
+ },
+ [0xF9CB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6E9C },
+ unicodeslot=0xF9CB,
+ },
+ [0xF9CC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7409 },
+ unicodeslot=0xF9CC,
+ },
+ [0xF9CD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7559 },
+ unicodeslot=0xF9CD,
+ },
+ [0xF9CE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x786B },
+ unicodeslot=0xF9CE,
+ },
+ [0xF9CF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D10 },
+ unicodeslot=0xF9CF,
+ },
+ [0xF9D0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x985E },
+ unicodeslot=0xF9D0,
+ },
+ [0xF9D1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x516D },
+ unicodeslot=0xF9D1,
+ },
+ [0xF9D2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x622E },
+ unicodeslot=0xF9D2,
+ },
+ [0xF9D3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9678 },
+ unicodeslot=0xF9D3,
+ },
+ [0xF9D4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x502B },
+ unicodeslot=0xF9D4,
+ },
+ [0xF9D5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D19 },
+ unicodeslot=0xF9D5,
+ },
+ [0xF9D6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6DEA },
+ unicodeslot=0xF9D6,
+ },
+ [0xF9D7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F2A },
+ unicodeslot=0xF9D7,
+ },
+ [0xF9D8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F8B },
+ unicodeslot=0xF9D8,
+ },
+ [0xF9D9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009D0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6144 },
+ unicodeslot=0xF9D9,
+ },
+ [0xF9DA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6817 },
+ unicodeslot=0xF9DA,
+ },
+ [0xF9DB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7387 },
+ unicodeslot=0xF9DB,
+ },
+ [0xF9DC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9686 },
+ unicodeslot=0xF9DC,
+ },
+ [0xF9DD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5229 },
+ unicodeslot=0xF9DD,
+ },
+ [0xF9DE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x540F },
+ unicodeslot=0xF9DE,
+ },
+ [0xF9DF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C65 },
+ unicodeslot=0xF9DF,
+ },
+ [0xF9E0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6613 },
+ unicodeslot=0xF9E0,
+ },
+ [0xF9E1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x674E },
+ unicodeslot=0xF9E1,
+ },
+ [0xF9E2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x68A8 },
+ unicodeslot=0xF9E2,
+ },
+ [0xF9E3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6CE5 },
+ unicodeslot=0xF9E3,
+ },
+ [0xF9E4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7406 },
+ unicodeslot=0xF9E4,
+ },
+ [0xF9E5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x75E2 },
+ unicodeslot=0xF9E5,
+ },
+ [0xF9E6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F79 },
+ unicodeslot=0xF9E6,
+ },
+ [0xF9E7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88CF },
+ unicodeslot=0xF9E7,
+ },
+ [0xF9E8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88E1 },
+ unicodeslot=0xF9E8,
+ },
+ [0xF9E9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009E0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x91CC },
+ unicodeslot=0xF9E9,
+ },
+ [0xF9EA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009EA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96E2 },
+ unicodeslot=0xF9EA,
+ },
+ [0xF9EB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009EB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x533F },
+ unicodeslot=0xF9EB,
+ },
+ [0xF9EC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009EC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6EBA },
+ unicodeslot=0xF9EC,
+ },
+ [0xF9ED]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009ED",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x541D },
+ unicodeslot=0xF9ED,
+ },
+ [0xF9EE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009EE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x71D0 },
+ unicodeslot=0xF9EE,
+ },
+ [0xF9EF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009EF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7498 },
+ unicodeslot=0xF9EF,
+ },
+ [0xF9F0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x85FA },
+ unicodeslot=0xF9F0,
+ },
+ [0xF9F1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96A3 },
+ unicodeslot=0xF9F1,
+ },
+ [0xF9F2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9C57 },
+ unicodeslot=0xF9F2,
+ },
+ [0xF9F3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9E9F },
+ unicodeslot=0xF9F3,
+ },
+ [0xF9F4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6797 },
+ unicodeslot=0xF9F4,
+ },
+ [0xF9F5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6DCB },
+ unicodeslot=0xF9F5,
+ },
+ [0xF9F6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x81E8 },
+ unicodeslot=0xF9F6,
+ },
+ [0xF9F7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7ACB },
+ unicodeslot=0xF9F7,
+ },
+ [0xF9F8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7B20 },
+ unicodeslot=0xF9F8,
+ },
+ [0xF9F9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009F0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7C92 },
+ unicodeslot=0xF9F9,
+ },
+ [0xF9FA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x72C0 },
+ unicodeslot=0xF9FA,
+ },
+ [0xF9FB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7099 },
+ unicodeslot=0xF9FB,
+ },
+ [0xF9FC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B58 },
+ unicodeslot=0xF9FC,
+ },
+ [0xF9FD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4EC0 },
+ unicodeslot=0xF9FD,
+ },
+ [0xF9FE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8336 },
+ unicodeslot=0xF9FE,
+ },
+ [0xF9FF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-F0x0009FF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x523A },
+ unicodeslot=0xF9FF,
+ },
+ [0xFA00]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5207 },
+ unicodeslot=0xFA00,
+ },
+ [0xFA01]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EA6 },
+ unicodeslot=0xFA01,
+ },
+ [0xFA02]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62D3 },
+ unicodeslot=0xFA02,
+ },
+ [0xFA03]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CD6 },
+ unicodeslot=0xFA03,
+ },
+ [0xFA04]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5B85 },
+ unicodeslot=0xFA04,
+ },
+ [0xFA05]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D1E },
+ unicodeslot=0xFA05,
+ },
+ [0xFA06]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x66B4 },
+ unicodeslot=0xFA06,
+ },
+ [0xFA07]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F3B },
+ unicodeslot=0xFA07,
+ },
+ [0xFA08]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x884C },
+ unicodeslot=0xFA08,
+ },
+ [0xFA09]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x964D },
+ unicodeslot=0xFA09,
+ },
+ [0xFA0A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x898B },
+ unicodeslot=0xFA0A,
+ },
+ [0xFA0B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5ED3 },
+ unicodeslot=0xFA0B,
+ },
+ [0xFA0C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5140 },
+ unicodeslot=0xFA0C,
+ },
+ [0xFA0D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x55C0 },
+ unicodeslot=0xFA0D,
+ },
+ [0xFA0E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA0E,
+ },
+ [0xFA0F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0000F",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA0F,
+ },
+ [0xFA10]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x585A },
+ unicodeslot=0xFA10,
+ },
+ [0xFA11]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000B",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA11,
+ },
+ [0xFA12]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6674 },
+ unicodeslot=0xFA12,
+ },
+ [0xFA13]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000D",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA13,
+ },
+ [0xFA14]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA14,
+ },
+ [0xFA15]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x000F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51DE },
+ unicodeslot=0xFA15,
+ },
+ [0xFA16]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0010",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x732A },
+ unicodeslot=0xFA16,
+ },
+ [0xFA17]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0011",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76CA },
+ unicodeslot=0xFA17,
+ },
+ [0xFA18]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0012",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x793C },
+ unicodeslot=0xFA18,
+ },
+ [0xFA19]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0013",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x795E },
+ unicodeslot=0xFA19,
+ },
+ [0xFA1A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7965 },
+ unicodeslot=0xFA1A,
+ },
+ [0xFA1B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x798F },
+ unicodeslot=0xFA1B,
+ },
+ [0xFA1C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9756 },
+ unicodeslot=0xFA1C,
+ },
+ [0xFA1D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CBE },
+ unicodeslot=0xFA1D,
+ },
+ [0xFA1E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7FBD },
+ unicodeslot=0xFA1E,
+ },
+ [0xFA1F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0001F",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA1F,
+ },
+ [0xFA20]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0014",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8612 },
+ unicodeslot=0xFA20,
+ },
+ [0xFA21]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0015",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA21,
+ },
+ [0xFA22]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0016",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AF8 },
+ unicodeslot=0xFA22,
+ },
+ [0xFA23]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0017",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA23,
+ },
+ [0xFA24]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0018",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA24,
+ },
+ [0xFA25]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0019",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9038 },
+ unicodeslot=0xFA25,
+ },
+ [0xFA26]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x90FD },
+ unicodeslot=0xFA26,
+ },
+ [0xFA27]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001B",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA27,
+ },
+ [0xFA28]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001C",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA28,
+ },
+ [0xFA29]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001D",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0xFA29,
+ },
+ [0xFA2A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0002A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x98EF },
+ unicodeslot=0xFA2A,
+ },
+ [0xFA2B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0002B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x98FC },
+ unicodeslot=0xFA2B,
+ },
+ [0xFA2C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0002C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9928 },
+ unicodeslot=0xFA2C,
+ },
+ [0xFA2D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0002D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9DB4 },
+ unicodeslot=0xFA2D,
+ },
+ [0xFA2E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA2E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x90DE },
+ unicodeslot=0xFA2E,
+ },
+ [0xFA2F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA2F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96B7 },
+ unicodeslot=0xFA2F,
+ },
+ [0xFA30]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4FAE },
+ unicodeslot=0xFA30,
+ },
+ [0xFA31]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x001F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x50E7 },
+ unicodeslot=0xFA31,
+ },
+ [0xFA32]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0020",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x514D },
+ unicodeslot=0xFA32,
+ },
+ [0xFA33]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0021",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52C9 },
+ unicodeslot=0xFA33,
+ },
+ [0xFA34]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0022",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52E4 },
+ unicodeslot=0xFA34,
+ },
+ [0xFA35]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0023",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5351 },
+ unicodeslot=0xFA35,
+ },
+ [0xFA36]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0024",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x559D },
+ unicodeslot=0xFA36,
+ },
+ [0xFA37]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0025",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5606 },
+ unicodeslot=0xFA37,
+ },
+ [0xFA38]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0026",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5668 },
+ unicodeslot=0xFA38,
+ },
+ [0xFA39]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0027",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5840 },
+ unicodeslot=0xFA39,
+ },
+ [0xFA3A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58A8 },
+ unicodeslot=0xFA3A,
+ },
+ [0xFA3B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C64 },
+ unicodeslot=0xFA3B,
+ },
+ [0xFA3C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C6E },
+ unicodeslot=0xFA3C,
+ },
+ [0xFA3D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6094 },
+ unicodeslot=0xFA3D,
+ },
+ [0xFA3E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6168 },
+ unicodeslot=0xFA3E,
+ },
+ [0xFA3F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0003F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x618E },
+ unicodeslot=0xFA3F,
+ },
+ [0xFA40]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0028",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61F2 },
+ unicodeslot=0xFA40,
+ },
+ [0xFA41]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0029",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x654F },
+ unicodeslot=0xFA41,
+ },
+ [0xFA42]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x65E2 },
+ unicodeslot=0xFA42,
+ },
+ [0xFA43]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6691 },
+ unicodeslot=0xFA43,
+ },
+ [0xFA44]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6885 },
+ unicodeslot=0xFA44,
+ },
+ [0xFA45]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D77 },
+ unicodeslot=0xFA45,
+ },
+ [0xFA46]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6E1A },
+ unicodeslot=0xFA46,
+ },
+ [0xFA47]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x002F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6F22 },
+ unicodeslot=0xFA47,
+ },
+ [0xFA48]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0030",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x716E },
+ unicodeslot=0xFA48,
+ },
+ [0xFA49]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0031",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x722B },
+ unicodeslot=0xFA49,
+ },
+ [0xFA4A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7422 },
+ unicodeslot=0xFA4A,
+ },
+ [0xFA4B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7891 },
+ unicodeslot=0xFA4B,
+ },
+ [0xFA4C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x793E },
+ unicodeslot=0xFA4C,
+ },
+ [0xFA4D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7949 },
+ unicodeslot=0xFA4D,
+ },
+ [0xFA4E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7948 },
+ unicodeslot=0xFA4E,
+ },
+ [0xFA4F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0004F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7950 },
+ unicodeslot=0xFA4F,
+ },
+ [0xFA50]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0032",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7956 },
+ unicodeslot=0xFA50,
+ },
+ [0xFA51]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0033",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x795D },
+ unicodeslot=0xFA51,
+ },
+ [0xFA52]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0034",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x798D },
+ unicodeslot=0xFA52,
+ },
+ [0xFA53]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0035",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x798E },
+ unicodeslot=0xFA53,
+ },
+ [0xFA54]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0036",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A40 },
+ unicodeslot=0xFA54,
+ },
+ [0xFA55]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0037",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A81 },
+ unicodeslot=0xFA55,
+ },
+ [0xFA56]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0038",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7BC0 },
+ unicodeslot=0xFA56,
+ },
+ [0xFA57]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0039",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DF4 },
+ unicodeslot=0xFA57,
+ },
+ [0xFA58]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7E09 },
+ unicodeslot=0xFA58,
+ },
+ [0xFA59]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7E41 },
+ unicodeslot=0xFA59,
+ },
+ [0xFA5A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F72 },
+ unicodeslot=0xFA5A,
+ },
+ [0xFA5B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8005 },
+ unicodeslot=0xFA5B,
+ },
+ [0xFA5C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x81ED },
+ unicodeslot=0xFA5C,
+ },
+ [0xFA5D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8279 },
+ unicodeslot=0xFA5D,
+ },
+ [0xFA5E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8279 },
+ unicodeslot=0xFA5E,
+ },
+ [0xFA5F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0005F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8457 },
+ unicodeslot=0xFA5F,
+ },
+ [0xFA60]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8910 },
+ unicodeslot=0xFA60,
+ },
+ [0xFA61]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8996 },
+ unicodeslot=0xFA61,
+ },
+ [0xFA62]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B01 },
+ unicodeslot=0xFA62,
+ },
+ [0xFA63]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x003F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B39 },
+ unicodeslot=0xFA63,
+ },
+ [0xFA64]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0040",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8CD3 },
+ unicodeslot=0xFA64,
+ },
+ [0xFA65]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0041",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8D08 },
+ unicodeslot=0xFA65,
+ },
+ [0xFA66]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0042",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8FB6 },
+ unicodeslot=0xFA66,
+ },
+ [0xFA67]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0043",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9038 },
+ unicodeslot=0xFA67,
+ },
+ [0xFA68]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0044",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96E3 },
+ unicodeslot=0xFA68,
+ },
+ [0xFA69]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0045",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x97FF },
+ unicodeslot=0xFA69,
+ },
+ [0xFA6A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0006A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x983B },
+ unicodeslot=0xFA6A,
+ },
+ [0xFA6B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6075 },
+ unicodeslot=0xFA6B,
+ },
+ [0xFA6C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x242EE },
+ unicodeslot=0xFA6C,
+ },
+ [0xFA6D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8218 },
+ unicodeslot=0xFA6D,
+ },
+ [0xFA70]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0046",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E26 },
+ unicodeslot=0xFA70,
+ },
+ [0xFA71]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0047",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51B5 },
+ unicodeslot=0xFA71,
+ },
+ [0xFA72]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0048",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5168 },
+ unicodeslot=0xFA72,
+ },
+ [0xFA73]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0049",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4F80 },
+ unicodeslot=0xFA73,
+ },
+ [0xFA74]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5145 },
+ unicodeslot=0xFA74,
+ },
+ [0xFA75]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5180 },
+ unicodeslot=0xFA75,
+ },
+ [0xFA76]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52C7 },
+ unicodeslot=0xFA76,
+ },
+ [0xFA77]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52FA },
+ unicodeslot=0xFA77,
+ },
+ [0xFA78]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x559D },
+ unicodeslot=0xFA78,
+ },
+ [0xFA79]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x004F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5555 },
+ unicodeslot=0xFA79,
+ },
+ [0xFA7A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5599 },
+ unicodeslot=0xFA7A,
+ },
+ [0xFA7B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x55E2 },
+ unicodeslot=0xFA7B,
+ },
+ [0xFA7C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x585A },
+ unicodeslot=0xFA7C,
+ },
+ [0xFA7D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58B3 },
+ unicodeslot=0xFA7D,
+ },
+ [0xFA7E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5944 },
+ unicodeslot=0xFA7E,
+ },
+ [0xFA7F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0007F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5954 },
+ unicodeslot=0xFA7F,
+ },
+ [0xFA80]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0050",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5A62 },
+ unicodeslot=0xFA80,
+ },
+ [0xFA81]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0051",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5B28 },
+ unicodeslot=0xFA81,
+ },
+ [0xFA82]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0052",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5ED2 },
+ unicodeslot=0xFA82,
+ },
+ [0xFA83]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0053",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5ED9 },
+ unicodeslot=0xFA83,
+ },
+ [0xFA84]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0054",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F69 },
+ unicodeslot=0xFA84,
+ },
+ [0xFA85]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0055",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FAD },
+ unicodeslot=0xFA85,
+ },
+ [0xFA86]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0056",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x60D8 },
+ unicodeslot=0xFA86,
+ },
+ [0xFA87]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0057",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x614E },
+ unicodeslot=0xFA87,
+ },
+ [0xFA88]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0058",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6108 },
+ unicodeslot=0xFA88,
+ },
+ [0xFA89]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0059",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x618E },
+ unicodeslot=0xFA89,
+ },
+ [0xFA8A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6160 },
+ unicodeslot=0xFA8A,
+ },
+ [0xFA8B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61F2 },
+ unicodeslot=0xFA8B,
+ },
+ [0xFA8C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6234 },
+ unicodeslot=0xFA8C,
+ },
+ [0xFA8D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x63C4 },
+ unicodeslot=0xFA8D,
+ },
+ [0xFA8E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x641C },
+ unicodeslot=0xFA8E,
+ },
+ [0xFA8F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0008F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6452 },
+ unicodeslot=0xFA8F,
+ },
+ [0xFA90]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6556 },
+ unicodeslot=0xFA90,
+ },
+ [0xFA91]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6674 },
+ unicodeslot=0xFA91,
+ },
+ [0xFA92]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6717 },
+ unicodeslot=0xFA92,
+ },
+ [0xFA93]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x671B },
+ unicodeslot=0xFA93,
+ },
+ [0xFA94]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6756 },
+ unicodeslot=0xFA94,
+ },
+ [0xFA95]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x005F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B79 },
+ unicodeslot=0xFA95,
+ },
+ [0xFA96]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0060",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6BBA },
+ unicodeslot=0xFA96,
+ },
+ [0xFA97]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0061",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D41 },
+ unicodeslot=0xFA97,
+ },
+ [0xFA98]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0062",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6EDB },
+ unicodeslot=0xFA98,
+ },
+ [0xFA99]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0063",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6ECB },
+ unicodeslot=0xFA99,
+ },
+ [0xFA9A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6F22 },
+ unicodeslot=0xFA9A,
+ },
+ [0xFA9B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x701E },
+ unicodeslot=0xFA9B,
+ },
+ [0xFA9C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x716E },
+ unicodeslot=0xFA9C,
+ },
+ [0xFA9D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x77A7 },
+ unicodeslot=0xFA9D,
+ },
+ [0xFA9E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7235 },
+ unicodeslot=0xFA9E,
+ },
+ [0xFA9F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA0x0009F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x72AF },
+ unicodeslot=0xFA9F,
+ },
+ [0xFAA0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x732A },
+ unicodeslot=0xFAA0,
+ },
+ [0xFAA1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7471 },
+ unicodeslot=0xFAA1,
+ },
+ [0xFAA2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7506 },
+ unicodeslot=0xFAA2,
+ },
+ [0xFAA3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x753B },
+ unicodeslot=0xFAA3,
+ },
+ [0xFAA4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x761D },
+ unicodeslot=0xFAA4,
+ },
+ [0xFAA5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x761F },
+ unicodeslot=0xFAA5,
+ },
+ [0xFAA6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76CA },
+ unicodeslot=0xFAA6,
+ },
+ [0xFAA7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76DB },
+ unicodeslot=0xFAA7,
+ },
+ [0xFAA8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76F4 },
+ unicodeslot=0xFAA8,
+ },
+ [0xFAA9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAA0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x774A },
+ unicodeslot=0xFAA9,
+ },
+ [0xFAAA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7740 },
+ unicodeslot=0xFAAA,
+ },
+ [0xFAAB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x78CC },
+ unicodeslot=0xFAAB,
+ },
+ [0xFAAC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7AB1 },
+ unicodeslot=0xFAAC,
+ },
+ [0xFAAD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7BC0 },
+ unicodeslot=0xFAAD,
+ },
+ [0xFAAE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7C7B },
+ unicodeslot=0xFAAE,
+ },
+ [0xFAAF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAAF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D5B },
+ unicodeslot=0xFAAF,
+ },
+ [0xFAB0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DF4 },
+ unicodeslot=0xFAB0,
+ },
+ [0xFAB1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F3E },
+ unicodeslot=0xFAB1,
+ },
+ [0xFAB2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8005 },
+ unicodeslot=0xFAB2,
+ },
+ [0xFAB3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8352 },
+ unicodeslot=0xFAB3,
+ },
+ [0xFAB4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83EF },
+ unicodeslot=0xFAB4,
+ },
+ [0xFAB5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8779 },
+ unicodeslot=0xFAB5,
+ },
+ [0xFAB6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8941 },
+ unicodeslot=0xFAB6,
+ },
+ [0xFAB7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8986 },
+ unicodeslot=0xFAB7,
+ },
+ [0xFAB8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8996 },
+ unicodeslot=0xFAB8,
+ },
+ [0xFAB9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAB0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8ABF },
+ unicodeslot=0xFAB9,
+ },
+ [0xFABA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AF8 },
+ unicodeslot=0xFABA,
+ },
+ [0xFABB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8ACB },
+ unicodeslot=0xFABB,
+ },
+ [0xFABC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B01 },
+ unicodeslot=0xFABC,
+ },
+ [0xFABD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AFE },
+ unicodeslot=0xFABD,
+ },
+ [0xFABE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AED },
+ unicodeslot=0xFABE,
+ },
+ [0xFABF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FABF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B39 },
+ unicodeslot=0xFABF,
+ },
+ [0xFAC0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B8A },
+ unicodeslot=0xFAC0,
+ },
+ [0xFAC1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8D08 },
+ unicodeslot=0xFAC1,
+ },
+ [0xFAC2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F38 },
+ unicodeslot=0xFAC2,
+ },
+ [0xFAC3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9072 },
+ unicodeslot=0xFAC3,
+ },
+ [0xFAC4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9199 },
+ unicodeslot=0xFAC4,
+ },
+ [0xFAC5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9276 },
+ unicodeslot=0xFAC5,
+ },
+ [0xFAC6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x967C },
+ unicodeslot=0xFAC6,
+ },
+ [0xFAC7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96E3 },
+ unicodeslot=0xFAC7,
+ },
+ [0xFAC8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9756 },
+ unicodeslot=0xFAC8,
+ },
+ [0xFAC9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAC0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x97DB },
+ unicodeslot=0xFAC9,
+ },
+ [0xFACA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x97FF },
+ unicodeslot=0xFACA,
+ },
+ [0xFACB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x980B },
+ unicodeslot=0xFACB,
+ },
+ [0xFACC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x983B },
+ unicodeslot=0xFACC,
+ },
+ [0xFACD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9B12 },
+ unicodeslot=0xFACD,
+ },
+ [0xFACE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F9C },
+ unicodeslot=0xFACE,
+ },
+ [0xFACF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FACF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2284A },
+ unicodeslot=0xFACF,
+ },
+ [0xFAD0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22844 },
+ unicodeslot=0xFAD0,
+ },
+ [0xFAD1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x233D5 },
+ unicodeslot=0xFAD1,
+ },
+ [0xFAD2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3B9D },
+ unicodeslot=0xFAD2,
+ },
+ [0xFAD3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4018 },
+ unicodeslot=0xFAD3,
+ },
+ [0xFAD4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4039 },
+ unicodeslot=0xFAD4,
+ },
+ [0xFAD5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25249 },
+ unicodeslot=0xFAD5,
+ },
+ [0xFAD6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25CD0 },
+ unicodeslot=0xFAD6,
+ },
+ [0xFAD7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x27ED3 },
+ unicodeslot=0xFAD7,
+ },
+ [0xFAD8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F43 },
+ unicodeslot=0xFAD8,
+ },
+ [0xFAD9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FAD0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F8E },
+ unicodeslot=0xFAD9,
+ },
+ [0xFB00]={
+ adobename="ff",
+ category="ll",
+ contextname="ffligature",
+ description="LATIN SMALL LIGATURE FF",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x66, 0x66 },
+ unicodeslot=0xFB00,
+ },
+ [0xFB01]={
+ adobename="fi",
+ category="ll",
+ contextname="filigature",
+ description="LATIN SMALL LIGATURE FI",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x66, 0x69 },
+ specials={ "compat", 0x66, 0x69 },
+ unicodeslot=0xFB01,
+ },
+ [0xFB02]={
+ adobename="fl",
+ category="ll",
+ contextname="flligature",
+ description="LATIN SMALL LIGATURE FL",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x66, 0x6C },
+ specials={ "compat", 0x66, 0x6C },
+ unicodeslot=0xFB02,
+ },
+ [0xFB03]={
+ adobename="ffi",
+ category="ll",
+ contextname="ffiligature",
+ description="LATIN SMALL LIGATURE FFI",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x66, 0x69 },
+ specials={ "compat", 0x66, 0x66, 0x69 },
+ unicodeslot=0xFB03,
+ },
+ [0xFB04]={
+ adobename="ffl",
+ category="ll",
+ contextname="fflligature",
+ description="LATIN SMALL LIGATURE FFL",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x66, 0x6C },
+ specials={ "compat", 0x66, 0x66, 0x6C },
+ unicodeslot=0xFB04,
+ },
+ [0xFB05]={
+ category="ll",
+ description="LATIN SMALL LIGATURE LONG S T",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x17F, 0x74 },
+ unicodeslot=0xFB05,
+ },
+ [0xFB06]={
+ category="ll",
+ contextname="stligature",
+ description="LATIN SMALL LIGATURE ST",
+ direction="l",
+ linebreak="al",
+ shcode={ 0x73, 0x74 },
+ specials={ "compat", 0x73, 0x74 },
+ unicodeslot=0xFB06,
+ },
+ [0xFB13]={
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE MEN NOW",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x574, 0x576 },
+ unicodeslot=0xFB13,
+ },
+ [0xFB14]={
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE MEN ECH",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x574, 0x565 },
+ unicodeslot=0xFB14,
+ },
+ [0xFB15]={
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE MEN INI",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x574, 0x56B },
+ unicodeslot=0xFB15,
+ },
+ [0xFB16]={
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE VEW NOW",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x57E, 0x576 },
+ unicodeslot=0xFB16,
+ },
+ [0xFB17]={
+ category="ll",
+ description="ARMENIAN SMALL LIGATURE MEN XEH",
+ direction="l",
+ linebreak="al",
+ specials={ "compat", 0x574, 0x56D },
+ unicodeslot=0xFB17,
+ },
+ [0xFB1D]={
+ category="lo",
+ description="HEBREW LETTER YOD WITH HIRIQ",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D9,
+ specials={ "char", 0x5D9, 0x5B4 },
+ unicodeslot=0xFB1D,
+ },
+ [0xFB1E]={
+ category="mn",
+ combining=0x1A,
+ description="HEBREW POINT JUDEO-SPANISH VARIKA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFB1E,
+ },
+ [0xFB1F]={
+ adobename="yodyodpatahhebrew",
+ category="lo",
+ description="HEBREW LIGATURE YIDDISH YOD YOD PATAH",
+ direction="r",
+ linebreak="hl",
+ specials={ "char", 0x5F2, 0x5B7 },
+ unicodeslot=0xFB1F,
+ },
+ [0xFB20]={
+ adobename="ayinaltonehebrew",
+ category="lo",
+ description="HEBREW LETTER ALTERNATIVE AYIN",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5E2 },
+ unicodeslot=0xFB20,
+ },
+ [0xFB21]={
+ category="lo",
+ description="HEBREW LETTER WIDE ALEF",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5D0 },
+ unicodeslot=0xFB21,
+ },
+ [0xFB22]={
+ category="lo",
+ description="HEBREW LETTER WIDE DALET",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5D3 },
+ unicodeslot=0xFB22,
+ },
+ [0xFB23]={
+ category="lo",
+ description="HEBREW LETTER WIDE HE",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5D4 },
+ unicodeslot=0xFB23,
+ },
+ [0xFB24]={
+ category="lo",
+ description="HEBREW LETTER WIDE KAF",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5DB },
+ unicodeslot=0xFB24,
+ },
+ [0xFB25]={
+ category="lo",
+ description="HEBREW LETTER WIDE LAMED",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5DC },
+ unicodeslot=0xFB25,
+ },
+ [0xFB26]={
+ category="lo",
+ description="HEBREW LETTER WIDE FINAL MEM",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5DD },
+ unicodeslot=0xFB26,
+ },
+ [0xFB27]={
+ category="lo",
+ description="HEBREW LETTER WIDE RESH",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5E8 },
+ unicodeslot=0xFB27,
+ },
+ [0xFB28]={
+ category="lo",
+ description="HEBREW LETTER WIDE TAV",
+ direction="r",
+ linebreak="hl",
+ specials={ "font", 0x5EA },
+ unicodeslot=0xFB28,
+ },
+ [0xFB29]={
+ category="sm",
+ description="HEBREW LETTER ALTERNATIVE PLUS SIGN",
+ direction="es",
+ linebreak="al",
+ specials={ "font", 0x2B },
+ unicodeslot=0xFB29,
+ },
+ [0xFB2A]={
+ adobename="shinshindothebrew",
+ category="lo",
+ description="HEBREW LETTER SHIN WITH SHIN DOT",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E9,
+ specials={ "char", 0x5E9, 0x5C1 },
+ unicodeslot=0xFB2A,
+ },
+ [0xFB2B]={
+ adobename="shinsindothebrew",
+ category="lo",
+ description="HEBREW LETTER SHIN WITH SIN DOT",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E9,
+ specials={ "char", 0x5E9, 0x5C2 },
+ unicodeslot=0xFB2B,
+ },
+ [0xFB2C]={
+ adobename="shindageshshindothebrew",
+ category="lo",
+ description="HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E9,
+ specials={ "char", 0xFB49, 0x5C1 },
+ unicodeslot=0xFB2C,
+ },
+ [0xFB2D]={
+ adobename="shindageshsindothebrew",
+ category="lo",
+ description="HEBREW LETTER SHIN WITH DAGESH AND SIN DOT",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E9,
+ specials={ "char", 0xFB49, 0x5C2 },
+ unicodeslot=0xFB2D,
+ },
+ [0xFB2E]={
+ adobename="alefpatahhebrew",
+ category="lo",
+ description="HEBREW LETTER ALEF WITH PATAH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D0,
+ specials={ "char", 0x5D0, 0x5B7 },
+ unicodeslot=0xFB2E,
+ },
+ [0xFB2F]={
+ adobename="alefqamatshebrew",
+ category="lo",
+ description="HEBREW LETTER ALEF WITH QAMATS",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D0,
+ specials={ "char", 0x5D0, 0x5B8 },
+ unicodeslot=0xFB2F,
+ },
+ [0xFB30]={
+ adobename="alefdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER ALEF WITH MAPIQ",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D0,
+ specials={ "char", 0x5D0, 0x5BC },
+ unicodeslot=0xFB30,
+ },
+ [0xFB31]={
+ adobename="betdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER BET WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D1,
+ specials={ "char", 0x5D1, 0x5BC },
+ unicodeslot=0xFB31,
+ },
+ [0xFB32]={
+ adobename="gimeldageshhebrew",
+ category="lo",
+ description="HEBREW LETTER GIMEL WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D2,
+ specials={ "char", 0x5D2, 0x5BC },
+ unicodeslot=0xFB32,
+ },
+ [0xFB33]={
+ adobename="daletdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER DALET WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D3,
+ specials={ "char", 0x5D3, 0x5BC },
+ unicodeslot=0xFB33,
+ },
+ [0xFB34]={
+ adobename="hedageshhebrew",
+ category="lo",
+ description="HEBREW LETTER HE WITH MAPIQ",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D4,
+ specials={ "char", 0x5D4, 0x5BC },
+ unicodeslot=0xFB34,
+ },
+ [0xFB35]={
+ adobename="vavdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER VAV WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D5,
+ specials={ "char", 0x5D5, 0x5BC },
+ unicodeslot=0xFB35,
+ },
+ [0xFB36]={
+ adobename="zayindageshhebrew",
+ category="lo",
+ description="HEBREW LETTER ZAYIN WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D6,
+ specials={ "char", 0x5D6, 0x5BC },
+ unicodeslot=0xFB36,
+ },
+ [0xFB38]={
+ adobename="tetdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER TET WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D8,
+ specials={ "char", 0x5D8, 0x5BC },
+ unicodeslot=0xFB38,
+ },
+ [0xFB39]={
+ adobename="yoddageshhebrew",
+ category="lo",
+ description="HEBREW LETTER YOD WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D9,
+ specials={ "char", 0x5D9, 0x5BC },
+ unicodeslot=0xFB39,
+ },
+ [0xFB3A]={
+ adobename="finalkafdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER FINAL KAF WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ specials={ "char", 0x5DA, 0x5BC },
+ unicodeslot=0xFB3A,
+ },
+ [0xFB3B]={
+ adobename="kafdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER KAF WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5DB,
+ specials={ "char", 0x5DB, 0x5BC },
+ unicodeslot=0xFB3B,
+ },
+ [0xFB3C]={
+ adobename="lameddageshhebrew",
+ category="lo",
+ description="HEBREW LETTER LAMED WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5DC,
+ specials={ "char", 0x5DC, 0x5BC },
+ unicodeslot=0xFB3C,
+ },
+ [0xFB3E]={
+ adobename="memdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER MEM WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5DE,
+ specials={ "char", 0x5DE, 0x5BC },
+ unicodeslot=0xFB3E,
+ },
+ [0xFB40]={
+ adobename="nundageshhebrew",
+ category="lo",
+ description="HEBREW LETTER NUN WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E0,
+ specials={ "char", 0x5E0, 0x5BC },
+ unicodeslot=0xFB40,
+ },
+ [0xFB41]={
+ adobename="samekhdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER SAMEKH WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E1,
+ specials={ "char", 0x5E1, 0x5BC },
+ unicodeslot=0xFB41,
+ },
+ [0xFB43]={
+ adobename="pefinaldageshhebrew",
+ category="lo",
+ description="HEBREW LETTER FINAL PE WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ specials={ "char", 0x5E3, 0x5BC },
+ unicodeslot=0xFB43,
+ },
+ [0xFB44]={
+ adobename="pedageshhebrew",
+ category="lo",
+ description="HEBREW LETTER PE WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E4,
+ specials={ "char", 0x5E4, 0x5BC },
+ unicodeslot=0xFB44,
+ },
+ [0xFB46]={
+ adobename="tsadidageshhebrew",
+ category="lo",
+ description="HEBREW LETTER TSADI WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E6,
+ specials={ "char", 0x5E6, 0x5BC },
+ unicodeslot=0xFB46,
+ },
+ [0xFB47]={
+ adobename="qofdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER QOF WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E7,
+ specials={ "char", 0x5E7, 0x5BC },
+ unicodeslot=0xFB47,
+ },
+ [0xFB48]={
+ adobename="reshdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER RESH WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E8,
+ specials={ "char", 0x5E8, 0x5BC },
+ unicodeslot=0xFB48,
+ },
+ [0xFB49]={
+ adobename="shindageshhebrew",
+ category="lo",
+ description="HEBREW LETTER SHIN WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E9,
+ specials={ "char", 0x5E9, 0x5BC },
+ unicodeslot=0xFB49,
+ },
+ [0xFB4A]={
+ adobename="tavdageshhebrew",
+ category="lo",
+ description="HEBREW LETTER TAV WITH DAGESH",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5EA,
+ specials={ "char", 0x5EA, 0x5BC },
+ unicodeslot=0xFB4A,
+ },
+ [0xFB4B]={
+ adobename="vavholamhebrew",
+ category="lo",
+ description="HEBREW LETTER VAV WITH HOLAM",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D5,
+ specials={ "char", 0x5D5, 0x5B9 },
+ unicodeslot=0xFB4B,
+ },
+ [0xFB4C]={
+ adobename="betrafehebrew",
+ category="lo",
+ description="HEBREW LETTER BET WITH RAFE",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5D1,
+ specials={ "char", 0x5D1, 0x5BF },
+ unicodeslot=0xFB4C,
+ },
+ [0xFB4D]={
+ adobename="kafrafehebrew",
+ category="lo",
+ description="HEBREW LETTER KAF WITH RAFE",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5DB,
+ specials={ "char", 0x5DB, 0x5BF },
+ unicodeslot=0xFB4D,
+ },
+ [0xFB4E]={
+ adobename="perafehebrew",
+ category="lo",
+ description="HEBREW LETTER PE WITH RAFE",
+ direction="r",
+ linebreak="hl",
+ shcode=0x5E4,
+ specials={ "char", 0x5E4, 0x5BF },
+ unicodeslot=0xFB4E,
+ },
+ [0xFB4F]={
+ adobename="aleflamedhebrew",
+ category="lo",
+ description="HEBREW LIGATURE ALEF LAMED",
+ direction="r",
+ linebreak="hl",
+ specials={ "compat", 0x5D0, 0x5DC },
+ unicodeslot=0xFB4F,
+ },
+ [0xFB50]={
+ category="lo",
+ description="ARABIC LETTER ALEF WASLA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x671 },
+ unicodeslot=0xFB50,
+ },
+ [0xFB51]={
+ category="lo",
+ description="ARABIC LETTER ALEF WASLA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x671 },
+ unicodeslot=0xFB51,
+ },
+ [0xFB52]={
+ category="lo",
+ description="ARABIC LETTER BEEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x67B },
+ unicodeslot=0xFB52,
+ },
+ [0xFB53]={
+ category="lo",
+ description="ARABIC LETTER BEEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x67B },
+ unicodeslot=0xFB53,
+ },
+ [0xFB54]={
+ category="lo",
+ description="ARABIC LETTER BEEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x67B },
+ unicodeslot=0xFB54,
+ },
+ [0xFB55]={
+ category="lo",
+ description="ARABIC LETTER BEEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x67B },
+ unicodeslot=0xFB55,
+ },
+ [0xFB56]={
+ category="lo",
+ description="ARABIC LETTER PEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x67E },
+ unicodeslot=0xFB56,
+ },
+ [0xFB57]={
+ adobename="pehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER PEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x67E },
+ unicodeslot=0xFB57,
+ },
+ [0xFB58]={
+ adobename="pehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER PEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x67E },
+ unicodeslot=0xFB58,
+ },
+ [0xFB59]={
+ adobename="pehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER PEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x67E },
+ unicodeslot=0xFB59,
+ },
+ [0xFB5A]={
+ category="lo",
+ description="ARABIC LETTER BEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x680 },
+ unicodeslot=0xFB5A,
+ },
+ [0xFB5B]={
+ category="lo",
+ description="ARABIC LETTER BEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x680 },
+ unicodeslot=0xFB5B,
+ },
+ [0xFB5C]={
+ category="lo",
+ description="ARABIC LETTER BEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x680 },
+ unicodeslot=0xFB5C,
+ },
+ [0xFB5D]={
+ category="lo",
+ description="ARABIC LETTER BEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x680 },
+ unicodeslot=0xFB5D,
+ },
+ [0xFB5E]={
+ category="lo",
+ description="ARABIC LETTER TTEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x67A },
+ unicodeslot=0xFB5E,
+ },
+ [0xFB5F]={
+ category="lo",
+ description="ARABIC LETTER TTEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x67A },
+ unicodeslot=0xFB5F,
+ },
+ [0xFB60]={
+ category="lo",
+ description="ARABIC LETTER TTEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x67A },
+ unicodeslot=0xFB60,
+ },
+ [0xFB61]={
+ category="lo",
+ description="ARABIC LETTER TTEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x67A },
+ unicodeslot=0xFB61,
+ },
+ [0xFB62]={
+ category="lo",
+ description="ARABIC LETTER TEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x67F },
+ unicodeslot=0xFB62,
+ },
+ [0xFB63]={
+ category="lo",
+ description="ARABIC LETTER TEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x67F },
+ unicodeslot=0xFB63,
+ },
+ [0xFB64]={
+ category="lo",
+ description="ARABIC LETTER TEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x67F },
+ unicodeslot=0xFB64,
+ },
+ [0xFB65]={
+ category="lo",
+ description="ARABIC LETTER TEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x67F },
+ unicodeslot=0xFB65,
+ },
+ [0xFB66]={
+ category="lo",
+ description="ARABIC LETTER TTEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x679 },
+ unicodeslot=0xFB66,
+ },
+ [0xFB67]={
+ adobename="ttehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER TTEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x679 },
+ unicodeslot=0xFB67,
+ },
+ [0xFB68]={
+ adobename="ttehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER TTEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x679 },
+ unicodeslot=0xFB68,
+ },
+ [0xFB69]={
+ adobename="ttehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER TTEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x679 },
+ unicodeslot=0xFB69,
+ },
+ [0xFB6A]={
+ category="lo",
+ description="ARABIC LETTER VEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6A4 },
+ unicodeslot=0xFB6A,
+ },
+ [0xFB6B]={
+ adobename="vehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER VEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6A4 },
+ unicodeslot=0xFB6B,
+ },
+ [0xFB6C]={
+ adobename="vehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER VEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6A4 },
+ unicodeslot=0xFB6C,
+ },
+ [0xFB6D]={
+ adobename="vehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER VEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6A4 },
+ unicodeslot=0xFB6D,
+ },
+ [0xFB6E]={
+ category="lo",
+ description="ARABIC LETTER PEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6A6 },
+ unicodeslot=0xFB6E,
+ },
+ [0xFB6F]={
+ category="lo",
+ description="ARABIC LETTER PEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6A6 },
+ unicodeslot=0xFB6F,
+ },
+ [0xFB70]={
+ category="lo",
+ description="ARABIC LETTER PEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6A6 },
+ unicodeslot=0xFB70,
+ },
+ [0xFB71]={
+ category="lo",
+ description="ARABIC LETTER PEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6A6 },
+ unicodeslot=0xFB71,
+ },
+ [0xFB72]={
+ category="lo",
+ description="ARABIC LETTER DYEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x684 },
+ unicodeslot=0xFB72,
+ },
+ [0xFB73]={
+ category="lo",
+ description="ARABIC LETTER DYEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x684 },
+ unicodeslot=0xFB73,
+ },
+ [0xFB74]={
+ category="lo",
+ description="ARABIC LETTER DYEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x684 },
+ unicodeslot=0xFB74,
+ },
+ [0xFB75]={
+ category="lo",
+ description="ARABIC LETTER DYEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x684 },
+ unicodeslot=0xFB75,
+ },
+ [0xFB76]={
+ category="lo",
+ description="ARABIC LETTER NYEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x683 },
+ unicodeslot=0xFB76,
+ },
+ [0xFB77]={
+ category="lo",
+ description="ARABIC LETTER NYEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x683 },
+ unicodeslot=0xFB77,
+ },
+ [0xFB78]={
+ category="lo",
+ description="ARABIC LETTER NYEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x683 },
+ unicodeslot=0xFB78,
+ },
+ [0xFB79]={
+ category="lo",
+ description="ARABIC LETTER NYEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x683 },
+ unicodeslot=0xFB79,
+ },
+ [0xFB7A]={
+ category="lo",
+ description="ARABIC LETTER TCHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x686 },
+ unicodeslot=0xFB7A,
+ },
+ [0xFB7B]={
+ adobename="tchehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER TCHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x686 },
+ unicodeslot=0xFB7B,
+ },
+ [0xFB7C]={
+ adobename="tchehmeeminitialarabic",
+ category="lo",
+ description="ARABIC LETTER TCHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x686 },
+ unicodeslot=0xFB7C,
+ },
+ [0xFB7D]={
+ adobename="tchehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER TCHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x686 },
+ unicodeslot=0xFB7D,
+ },
+ [0xFB7E]={
+ category="lo",
+ description="ARABIC LETTER TCHEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x687 },
+ unicodeslot=0xFB7E,
+ },
+ [0xFB7F]={
+ category="lo",
+ description="ARABIC LETTER TCHEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x687 },
+ unicodeslot=0xFB7F,
+ },
+ [0xFB80]={
+ category="lo",
+ description="ARABIC LETTER TCHEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x687 },
+ unicodeslot=0xFB80,
+ },
+ [0xFB81]={
+ category="lo",
+ description="ARABIC LETTER TCHEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x687 },
+ unicodeslot=0xFB81,
+ },
+ [0xFB82]={
+ category="lo",
+ description="ARABIC LETTER DDAHAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x68D },
+ unicodeslot=0xFB82,
+ },
+ [0xFB83]={
+ category="lo",
+ description="ARABIC LETTER DDAHAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x68D },
+ unicodeslot=0xFB83,
+ },
+ [0xFB84]={
+ category="lo",
+ description="ARABIC LETTER DAHAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x68C },
+ unicodeslot=0xFB84,
+ },
+ [0xFB85]={
+ category="lo",
+ description="ARABIC LETTER DAHAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x68C },
+ unicodeslot=0xFB85,
+ },
+ [0xFB86]={
+ category="lo",
+ description="ARABIC LETTER DUL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x68E },
+ unicodeslot=0xFB86,
+ },
+ [0xFB87]={
+ category="lo",
+ description="ARABIC LETTER DUL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x68E },
+ unicodeslot=0xFB87,
+ },
+ [0xFB88]={
+ category="lo",
+ description="ARABIC LETTER DDAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x688 },
+ unicodeslot=0xFB88,
+ },
+ [0xFB89]={
+ adobename="ddalfinalarabic",
+ category="lo",
+ description="ARABIC LETTER DDAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x688 },
+ unicodeslot=0xFB89,
+ },
+ [0xFB8A]={
+ category="lo",
+ description="ARABIC LETTER JEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x698 },
+ unicodeslot=0xFB8A,
+ },
+ [0xFB8B]={
+ adobename="jehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER JEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x698 },
+ unicodeslot=0xFB8B,
+ },
+ [0xFB8C]={
+ category="lo",
+ description="ARABIC LETTER RREH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x691 },
+ unicodeslot=0xFB8C,
+ },
+ [0xFB8D]={
+ adobename="rrehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER RREH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x691 },
+ unicodeslot=0xFB8D,
+ },
+ [0xFB8E]={
+ category="lo",
+ description="ARABIC LETTER KEHEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6A9 },
+ unicodeslot=0xFB8E,
+ },
+ [0xFB8F]={
+ category="lo",
+ description="ARABIC LETTER KEHEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6A9 },
+ unicodeslot=0xFB8F,
+ },
+ [0xFB90]={
+ category="lo",
+ description="ARABIC LETTER KEHEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6A9 },
+ unicodeslot=0xFB90,
+ },
+ [0xFB91]={
+ category="lo",
+ description="ARABIC LETTER KEHEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6A9 },
+ unicodeslot=0xFB91,
+ },
+ [0xFB92]={
+ category="lo",
+ description="ARABIC LETTER GAF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6AF },
+ unicodeslot=0xFB92,
+ },
+ [0xFB93]={
+ adobename="gaffinalarabic",
+ category="lo",
+ description="ARABIC LETTER GAF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6AF },
+ unicodeslot=0xFB93,
+ },
+ [0xFB94]={
+ adobename="gafinitialarabic",
+ category="lo",
+ description="ARABIC LETTER GAF INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6AF },
+ unicodeslot=0xFB94,
+ },
+ [0xFB95]={
+ adobename="gafmedialarabic",
+ category="lo",
+ description="ARABIC LETTER GAF MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6AF },
+ unicodeslot=0xFB95,
+ },
+ [0xFB96]={
+ category="lo",
+ description="ARABIC LETTER GUEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6B3 },
+ unicodeslot=0xFB96,
+ },
+ [0xFB97]={
+ category="lo",
+ description="ARABIC LETTER GUEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6B3 },
+ unicodeslot=0xFB97,
+ },
+ [0xFB98]={
+ category="lo",
+ description="ARABIC LETTER GUEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6B3 },
+ unicodeslot=0xFB98,
+ },
+ [0xFB99]={
+ category="lo",
+ description="ARABIC LETTER GUEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6B3 },
+ unicodeslot=0xFB99,
+ },
+ [0xFB9A]={
+ category="lo",
+ description="ARABIC LETTER NGOEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6B1 },
+ unicodeslot=0xFB9A,
+ },
+ [0xFB9B]={
+ category="lo",
+ description="ARABIC LETTER NGOEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6B1 },
+ unicodeslot=0xFB9B,
+ },
+ [0xFB9C]={
+ category="lo",
+ description="ARABIC LETTER NGOEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6B1 },
+ unicodeslot=0xFB9C,
+ },
+ [0xFB9D]={
+ category="lo",
+ description="ARABIC LETTER NGOEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6B1 },
+ unicodeslot=0xFB9D,
+ },
+ [0xFB9E]={
+ category="lo",
+ description="ARABIC LETTER NOON GHUNNA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6BA },
+ unicodeslot=0xFB9E,
+ },
+ [0xFB9F]={
+ adobename="noonghunnafinalarabic",
+ category="lo",
+ description="ARABIC LETTER NOON GHUNNA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6BA },
+ unicodeslot=0xFB9F,
+ },
+ [0xFBA0]={
+ category="lo",
+ description="ARABIC LETTER RNOON ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6BB },
+ unicodeslot=0xFBA0,
+ },
+ [0xFBA1]={
+ category="lo",
+ description="ARABIC LETTER RNOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6BB },
+ unicodeslot=0xFBA1,
+ },
+ [0xFBA2]={
+ category="lo",
+ description="ARABIC LETTER RNOON INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6BB },
+ unicodeslot=0xFBA2,
+ },
+ [0xFBA3]={
+ category="lo",
+ description="ARABIC LETTER RNOON MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6BB },
+ unicodeslot=0xFBA3,
+ },
+ [0xFBA4]={
+ adobename="hehhamzaaboveisolatedarabic",
+ category="lo",
+ description="ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x647,
+ specials={ "isolated", 0x6C0 },
+ unicodeslot=0xFBA4,
+ },
+ [0xFBA5]={
+ adobename="hehhamzaabovefinalarabic",
+ category="lo",
+ description="ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x647,
+ specials={ "final", 0x6C0 },
+ unicodeslot=0xFBA5,
+ },
+ [0xFBA6]={
+ category="lo",
+ description="ARABIC LETTER HEH GOAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C1 },
+ unicodeslot=0xFBA6,
+ },
+ [0xFBA7]={
+ adobename="hehfinalaltonearabic",
+ category="lo",
+ description="ARABIC LETTER HEH GOAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C1 },
+ unicodeslot=0xFBA7,
+ },
+ [0xFBA8]={
+ adobename="hehinitialaltonearabic",
+ category="lo",
+ description="ARABIC LETTER HEH GOAL INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6C1 },
+ unicodeslot=0xFBA8,
+ },
+ [0xFBA9]={
+ adobename="hehmedialaltonearabic",
+ category="lo",
+ description="ARABIC LETTER HEH GOAL MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6C1 },
+ unicodeslot=0xFBA9,
+ },
+ [0xFBAA]={
+ category="lo",
+ description="ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6BE },
+ unicodeslot=0xFBAA,
+ },
+ [0xFBAB]={
+ category="lo",
+ description="ARABIC LETTER HEH DOACHASHMEE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6BE },
+ unicodeslot=0xFBAB,
+ },
+ [0xFBAC]={
+ category="lo",
+ description="ARABIC LETTER HEH DOACHASHMEE INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6BE },
+ unicodeslot=0xFBAC,
+ },
+ [0xFBAD]={
+ category="lo",
+ description="ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6BE },
+ unicodeslot=0xFBAD,
+ },
+ [0xFBAE]={
+ category="lo",
+ description="ARABIC LETTER YEH BARREE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6D2 },
+ unicodeslot=0xFBAE,
+ },
+ [0xFBAF]={
+ adobename="yehbarreefinalarabic",
+ category="lo",
+ description="ARABIC LETTER YEH BARREE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6D2 },
+ unicodeslot=0xFBAF,
+ },
+ [0xFBB0]={
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6D3 },
+ unicodeslot=0xFBB0,
+ },
+ [0xFBB1]={
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6D3 },
+ unicodeslot=0xFBB1,
+ },
+ [0xFBB2]={
+ category="sk",
+ description="ARABIC SYMBOL DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB2,
+ },
+ [0xFBB3]={
+ category="sk",
+ description="ARABIC SYMBOL DOT BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB3,
+ },
+ [0xFBB4]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB4,
+ },
+ [0xFBB5]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB5,
+ },
+ [0xFBB6]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB6,
+ },
+ [0xFBB7]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB7,
+ },
+ [0xFBB8]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB8,
+ },
+ [0xFBB9]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB9,
+ },
+ [0xFBBA]={
+ category="sk",
+ description="ARABIC SYMBOL FOUR DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBA,
+ },
+ [0xFBBB]={
+ category="sk",
+ description="ARABIC SYMBOL FOUR DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBB,
+ },
+ [0xFBBC]={
+ category="sk",
+ description="ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBC,
+ },
+ [0xFBBD]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBD,
+ },
+ [0xFBBE]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS VERTICALLY BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBE,
+ },
+ [0xFBBF]={
+ category="sk",
+ description="ARABIC SYMBOL RING",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBF,
+ },
+ [0xFBC0]={
+ category="sk",
+ description="ARABIC SYMBOL SMALL TAH ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBC0,
+ },
+ [0xFBC1]={
+ category="sk",
+ description="ARABIC SYMBOL SMALL TAH BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBC1,
+ },
+ [0xFBD3]={
+ category="lo",
+ description="ARABIC LETTER NG ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6AD },
+ unicodeslot=0xFBD3,
+ },
+ [0xFBD4]={
+ category="lo",
+ description="ARABIC LETTER NG FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6AD },
+ unicodeslot=0xFBD4,
+ },
+ [0xFBD5]={
+ category="lo",
+ description="ARABIC LETTER NG INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6AD },
+ unicodeslot=0xFBD5,
+ },
+ [0xFBD6]={
+ category="lo",
+ description="ARABIC LETTER NG MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6AD },
+ unicodeslot=0xFBD6,
+ },
+ [0xFBD7]={
+ category="lo",
+ description="ARABIC LETTER U ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C7 },
+ unicodeslot=0xFBD7,
+ },
+ [0xFBD8]={
+ category="lo",
+ description="ARABIC LETTER U FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C7 },
+ unicodeslot=0xFBD8,
+ },
+ [0xFBD9]={
+ category="lo",
+ description="ARABIC LETTER OE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C6 },
+ unicodeslot=0xFBD9,
+ },
+ [0xFBDA]={
+ category="lo",
+ description="ARABIC LETTER OE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C6 },
+ unicodeslot=0xFBDA,
+ },
+ [0xFBDB]={
+ category="lo",
+ description="ARABIC LETTER YU ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C8 },
+ unicodeslot=0xFBDB,
+ },
+ [0xFBDC]={
+ category="lo",
+ description="ARABIC LETTER YU FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C8 },
+ unicodeslot=0xFBDC,
+ },
+ [0xFBDD]={
+ category="lo",
+ description="ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x6C7,
+ specials={ "isolated", 0x677 },
+ unicodeslot=0xFBDD,
+ },
+ [0xFBDE]={
+ category="lo",
+ description="ARABIC LETTER VE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6CB },
+ unicodeslot=0xFBDE,
+ },
+ [0xFBDF]={
+ category="lo",
+ description="ARABIC LETTER VE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6CB },
+ unicodeslot=0xFBDF,
+ },
+ [0xFBE0]={
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ OE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C5 },
+ unicodeslot=0xFBE0,
+ },
+ [0xFBE1]={
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ OE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C5 },
+ unicodeslot=0xFBE1,
+ },
+ [0xFBE2]={
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ YU ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6C9 },
+ unicodeslot=0xFBE2,
+ },
+ [0xFBE3]={
+ category="lo",
+ description="ARABIC LETTER KIRGHIZ YU FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6C9 },
+ unicodeslot=0xFBE3,
+ },
+ [0xFBE4]={
+ category="lo",
+ description="ARABIC LETTER E ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6D0 },
+ unicodeslot=0xFBE4,
+ },
+ [0xFBE5]={
+ category="lo",
+ description="ARABIC LETTER E FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6D0 },
+ unicodeslot=0xFBE5,
+ },
+ [0xFBE6]={
+ category="lo",
+ description="ARABIC LETTER E INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6D0 },
+ unicodeslot=0xFBE6,
+ },
+ [0xFBE7]={
+ category="lo",
+ description="ARABIC LETTER E MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6D0 },
+ unicodeslot=0xFBE7,
+ },
+ [0xFBE8]={
+ category="lo",
+ description="ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x649 },
+ unicodeslot=0xFBE8,
+ },
+ [0xFBE9]={
+ category="lo",
+ description="ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x649 },
+ unicodeslot=0xFBE9,
+ },
+ [0xFBEA]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x627 },
+ unicodeslot=0xFBEA,
+ },
+ [0xFBEB]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x627 },
+ unicodeslot=0xFBEB,
+ },
+ [0xFBEC]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x6D5 },
+ unicodeslot=0xFBEC,
+ },
+ [0xFBED]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x6D5 },
+ unicodeslot=0xFBED,
+ },
+ [0xFBEE]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x648 },
+ unicodeslot=0xFBEE,
+ },
+ [0xFBEF]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x648 },
+ unicodeslot=0xFBEF,
+ },
+ [0xFBF0]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x6C7 },
+ unicodeslot=0xFBF0,
+ },
+ [0xFBF1]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x6C7 },
+ unicodeslot=0xFBF1,
+ },
+ [0xFBF2]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x6C6 },
+ unicodeslot=0xFBF2,
+ },
+ [0xFBF3]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x6C6 },
+ unicodeslot=0xFBF3,
+ },
+ [0xFBF4]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x6C8 },
+ unicodeslot=0xFBF4,
+ },
+ [0xFBF5]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x6C8 },
+ unicodeslot=0xFBF5,
+ },
+ [0xFBF6]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x6D0 },
+ unicodeslot=0xFBF6,
+ },
+ [0xFBF7]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x6D0 },
+ unicodeslot=0xFBF7,
+ },
+ [0xFBF8]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x6D0 },
+ unicodeslot=0xFBF8,
+ },
+ [0xFBF9]={
+ category="lo",
+ description="ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x649 },
+ unicodeslot=0xFBF9,
+ },
+ [0xFBFA]={
+ category="lo",
+ description="ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x649 },
+ unicodeslot=0xFBFA,
+ },
+ [0xFBFB]={
+ category="lo",
+ description="ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x649 },
+ unicodeslot=0xFBFB,
+ },
+ [0xFBFC]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x6CC },
+ unicodeslot=0xFBFC,
+ },
+ [0xFBFD]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x6CC },
+ unicodeslot=0xFBFD,
+ },
+ [0xFBFE]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x6CC },
+ unicodeslot=0xFBFE,
+ },
+ [0xFBFF]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x6CC },
+ unicodeslot=0xFBFF,
+ },
+ [0xFC00]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x62C },
+ unicodeslot=0xFC00,
+ },
+ [0xFC01]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x62D },
+ unicodeslot=0xFC01,
+ },
+ [0xFC02]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x645 },
+ unicodeslot=0xFC02,
+ },
+ [0xFC03]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x649 },
+ unicodeslot=0xFC03,
+ },
+ [0xFC04]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x626, 0x64A },
+ unicodeslot=0xFC04,
+ },
+ [0xFC05]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x62C },
+ unicodeslot=0xFC05,
+ },
+ [0xFC06]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x62D },
+ unicodeslot=0xFC06,
+ },
+ [0xFC07]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x62E },
+ unicodeslot=0xFC07,
+ },
+ [0xFC08]={
+ adobename="behmeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x645 },
+ unicodeslot=0xFC08,
+ },
+ [0xFC09]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x649 },
+ unicodeslot=0xFC09,
+ },
+ [0xFC0A]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628, 0x64A },
+ unicodeslot=0xFC0A,
+ },
+ [0xFC0B]={
+ adobename="tehjeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x62C },
+ unicodeslot=0xFC0B,
+ },
+ [0xFC0C]={
+ adobename="tehhahisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x62D },
+ unicodeslot=0xFC0C,
+ },
+ [0xFC0D]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x62E },
+ unicodeslot=0xFC0D,
+ },
+ [0xFC0E]={
+ adobename="tehmeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x645 },
+ unicodeslot=0xFC0E,
+ },
+ [0xFC0F]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x649 },
+ unicodeslot=0xFC0F,
+ },
+ [0xFC10]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A, 0x64A },
+ unicodeslot=0xFC10,
+ },
+ [0xFC11]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62B, 0x62C },
+ unicodeslot=0xFC11,
+ },
+ [0xFC12]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62B, 0x645 },
+ unicodeslot=0xFC12,
+ },
+ [0xFC13]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62B, 0x649 },
+ unicodeslot=0xFC13,
+ },
+ [0xFC14]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62B, 0x64A },
+ unicodeslot=0xFC14,
+ },
+ [0xFC15]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C, 0x62D },
+ unicodeslot=0xFC15,
+ },
+ [0xFC16]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C, 0x645 },
+ unicodeslot=0xFC16,
+ },
+ [0xFC17]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62D, 0x62C },
+ unicodeslot=0xFC17,
+ },
+ [0xFC18]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62D, 0x645 },
+ unicodeslot=0xFC18,
+ },
+ [0xFC19]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E, 0x62C },
+ unicodeslot=0xFC19,
+ },
+ [0xFC1A]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E, 0x62D },
+ unicodeslot=0xFC1A,
+ },
+ [0xFC1B]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E, 0x645 },
+ unicodeslot=0xFC1B,
+ },
+ [0xFC1C]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x62C },
+ unicodeslot=0xFC1C,
+ },
+ [0xFC1D]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x62D },
+ unicodeslot=0xFC1D,
+ },
+ [0xFC1E]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x62E },
+ unicodeslot=0xFC1E,
+ },
+ [0xFC1F]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x645 },
+ unicodeslot=0xFC1F,
+ },
+ [0xFC20]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x62D },
+ unicodeslot=0xFC20,
+ },
+ [0xFC21]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x645 },
+ unicodeslot=0xFC21,
+ },
+ [0xFC22]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x62C },
+ unicodeslot=0xFC22,
+ },
+ [0xFC23]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x62D },
+ unicodeslot=0xFC23,
+ },
+ [0xFC24]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x62E },
+ unicodeslot=0xFC24,
+ },
+ [0xFC25]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x645 },
+ unicodeslot=0xFC25,
+ },
+ [0xFC26]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x637, 0x62D },
+ unicodeslot=0xFC26,
+ },
+ [0xFC27]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x637, 0x645 },
+ unicodeslot=0xFC27,
+ },
+ [0xFC28]={
+ category="lo",
+ description="ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x638, 0x645 },
+ unicodeslot=0xFC28,
+ },
+ [0xFC29]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639, 0x62C },
+ unicodeslot=0xFC29,
+ },
+ [0xFC2A]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639, 0x645 },
+ unicodeslot=0xFC2A,
+ },
+ [0xFC2B]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x63A, 0x62C },
+ unicodeslot=0xFC2B,
+ },
+ [0xFC2C]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x63A, 0x645 },
+ unicodeslot=0xFC2C,
+ },
+ [0xFC2D]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x62C },
+ unicodeslot=0xFC2D,
+ },
+ [0xFC2E]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x62D },
+ unicodeslot=0xFC2E,
+ },
+ [0xFC2F]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x62E },
+ unicodeslot=0xFC2F,
+ },
+ [0xFC30]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x645 },
+ unicodeslot=0xFC30,
+ },
+ [0xFC31]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x649 },
+ unicodeslot=0xFC31,
+ },
+ [0xFC32]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641, 0x64A },
+ unicodeslot=0xFC32,
+ },
+ [0xFC33]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642, 0x62D },
+ unicodeslot=0xFC33,
+ },
+ [0xFC34]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642, 0x645 },
+ unicodeslot=0xFC34,
+ },
+ [0xFC35]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642, 0x649 },
+ unicodeslot=0xFC35,
+ },
+ [0xFC36]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642, 0x64A },
+ unicodeslot=0xFC36,
+ },
+ [0xFC37]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x627 },
+ unicodeslot=0xFC37,
+ },
+ [0xFC38]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x62C },
+ unicodeslot=0xFC38,
+ },
+ [0xFC39]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x62D },
+ unicodeslot=0xFC39,
+ },
+ [0xFC3A]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x62E },
+ unicodeslot=0xFC3A,
+ },
+ [0xFC3B]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH LAM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x644 },
+ unicodeslot=0xFC3B,
+ },
+ [0xFC3C]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x645 },
+ unicodeslot=0xFC3C,
+ },
+ [0xFC3D]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x649 },
+ unicodeslot=0xFC3D,
+ },
+ [0xFC3E]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643, 0x64A },
+ unicodeslot=0xFC3E,
+ },
+ [0xFC3F]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x62C },
+ unicodeslot=0xFC3F,
+ },
+ [0xFC40]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x62D },
+ unicodeslot=0xFC40,
+ },
+ [0xFC41]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x62E },
+ unicodeslot=0xFC41,
+ },
+ [0xFC42]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x645 },
+ unicodeslot=0xFC42,
+ },
+ [0xFC43]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x649 },
+ unicodeslot=0xFC43,
+ },
+ [0xFC44]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x64A },
+ unicodeslot=0xFC44,
+ },
+ [0xFC45]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x62C },
+ unicodeslot=0xFC45,
+ },
+ [0xFC46]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x62D },
+ unicodeslot=0xFC46,
+ },
+ [0xFC47]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x62E },
+ unicodeslot=0xFC47,
+ },
+ [0xFC48]={
+ adobename="meemmeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x645 },
+ unicodeslot=0xFC48,
+ },
+ [0xFC49]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x649 },
+ unicodeslot=0xFC49,
+ },
+ [0xFC4A]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x64A },
+ unicodeslot=0xFC4A,
+ },
+ [0xFC4B]={
+ adobename="noonjeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x62C },
+ unicodeslot=0xFC4B,
+ },
+ [0xFC4C]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x62D },
+ unicodeslot=0xFC4C,
+ },
+ [0xFC4D]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x62E },
+ unicodeslot=0xFC4D,
+ },
+ [0xFC4E]={
+ adobename="noonmeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x645 },
+ unicodeslot=0xFC4E,
+ },
+ [0xFC4F]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x649 },
+ unicodeslot=0xFC4F,
+ },
+ [0xFC50]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646, 0x64A },
+ unicodeslot=0xFC50,
+ },
+ [0xFC51]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x647, 0x62C },
+ unicodeslot=0xFC51,
+ },
+ [0xFC52]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x647, 0x645 },
+ unicodeslot=0xFC52,
+ },
+ [0xFC53]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x647, 0x649 },
+ unicodeslot=0xFC53,
+ },
+ [0xFC54]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x647, 0x64A },
+ unicodeslot=0xFC54,
+ },
+ [0xFC55]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x62C },
+ unicodeslot=0xFC55,
+ },
+ [0xFC56]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x62D },
+ unicodeslot=0xFC56,
+ },
+ [0xFC57]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x62E },
+ unicodeslot=0xFC57,
+ },
+ [0xFC58]={
+ adobename="yehmeemisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x645 },
+ unicodeslot=0xFC58,
+ },
+ [0xFC59]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x649 },
+ unicodeslot=0xFC59,
+ },
+ [0xFC5A]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A, 0x64A },
+ unicodeslot=0xFC5A,
+ },
+ [0xFC5B]={
+ category="lo",
+ description="ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x630, 0x670 },
+ unicodeslot=0xFC5B,
+ },
+ [0xFC5C]={
+ category="lo",
+ description="ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x631, 0x670 },
+ unicodeslot=0xFC5C,
+ },
+ [0xFC5D]={
+ category="lo",
+ description="ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x649, 0x670 },
+ unicodeslot=0xFC5D,
+ },
+ [0xFC5E]={
+ adobename="shaddadammatanarabic",
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64C, 0x651 },
+ unicodeslot=0xFC5E,
+ },
+ [0xFC5F]={
+ adobename="shaddakasratanarabic",
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64D, 0x651 },
+ unicodeslot=0xFC5F,
+ },
+ [0xFC60]={
+ adobename="shaddafathaarabic",
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64E, 0x651 },
+ unicodeslot=0xFC60,
+ },
+ [0xFC61]={
+ adobename="shaddadammaarabic",
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64F, 0x651 },
+ unicodeslot=0xFC61,
+ },
+ [0xFC62]={
+ adobename="shaddakasraarabic",
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x650, 0x651 },
+ unicodeslot=0xFC62,
+ },
+ [0xFC63]={
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x651, 0x670 },
+ unicodeslot=0xFC63,
+ },
+ [0xFC64]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x631 },
+ unicodeslot=0xFC64,
+ },
+ [0xFC65]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x632 },
+ unicodeslot=0xFC65,
+ },
+ [0xFC66]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x645 },
+ unicodeslot=0xFC66,
+ },
+ [0xFC67]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x646 },
+ unicodeslot=0xFC67,
+ },
+ [0xFC68]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x649 },
+ unicodeslot=0xFC68,
+ },
+ [0xFC69]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x626, 0x64A },
+ unicodeslot=0xFC69,
+ },
+ [0xFC6A]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x631 },
+ unicodeslot=0xFC6A,
+ },
+ [0xFC6B]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x632 },
+ unicodeslot=0xFC6B,
+ },
+ [0xFC6C]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x645 },
+ unicodeslot=0xFC6C,
+ },
+ [0xFC6D]={
+ adobename="behnoonfinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x646 },
+ unicodeslot=0xFC6D,
+ },
+ [0xFC6E]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x649 },
+ unicodeslot=0xFC6E,
+ },
+ [0xFC6F]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x64A },
+ unicodeslot=0xFC6F,
+ },
+ [0xFC70]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x631 },
+ unicodeslot=0xFC70,
+ },
+ [0xFC71]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x632 },
+ unicodeslot=0xFC71,
+ },
+ [0xFC72]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x645 },
+ unicodeslot=0xFC72,
+ },
+ [0xFC73]={
+ adobename="tehnoonfinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x646 },
+ unicodeslot=0xFC73,
+ },
+ [0xFC74]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x649 },
+ unicodeslot=0xFC74,
+ },
+ [0xFC75]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x64A },
+ unicodeslot=0xFC75,
+ },
+ [0xFC76]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x631 },
+ unicodeslot=0xFC76,
+ },
+ [0xFC77]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x632 },
+ unicodeslot=0xFC77,
+ },
+ [0xFC78]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x645 },
+ unicodeslot=0xFC78,
+ },
+ [0xFC79]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x646 },
+ unicodeslot=0xFC79,
+ },
+ [0xFC7A]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x649 },
+ unicodeslot=0xFC7A,
+ },
+ [0xFC7B]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B, 0x64A },
+ unicodeslot=0xFC7B,
+ },
+ [0xFC7C]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x641, 0x649 },
+ unicodeslot=0xFC7C,
+ },
+ [0xFC7D]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x641, 0x64A },
+ unicodeslot=0xFC7D,
+ },
+ [0xFC7E]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642, 0x649 },
+ unicodeslot=0xFC7E,
+ },
+ [0xFC7F]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642, 0x64A },
+ unicodeslot=0xFC7F,
+ },
+ [0xFC80]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x627 },
+ unicodeslot=0xFC80,
+ },
+ [0xFC81]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH LAM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x644 },
+ unicodeslot=0xFC81,
+ },
+ [0xFC82]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x645 },
+ unicodeslot=0xFC82,
+ },
+ [0xFC83]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x649 },
+ unicodeslot=0xFC83,
+ },
+ [0xFC84]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x64A },
+ unicodeslot=0xFC84,
+ },
+ [0xFC85]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x645 },
+ unicodeslot=0xFC85,
+ },
+ [0xFC86]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x649 },
+ unicodeslot=0xFC86,
+ },
+ [0xFC87]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x64A },
+ unicodeslot=0xFC87,
+ },
+ [0xFC88]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x627 },
+ unicodeslot=0xFC88,
+ },
+ [0xFC89]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x645 },
+ unicodeslot=0xFC89,
+ },
+ [0xFC8A]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x631 },
+ unicodeslot=0xFC8A,
+ },
+ [0xFC8B]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x632 },
+ unicodeslot=0xFC8B,
+ },
+ [0xFC8C]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x645 },
+ unicodeslot=0xFC8C,
+ },
+ [0xFC8D]={
+ adobename="noonnoonfinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x646 },
+ unicodeslot=0xFC8D,
+ },
+ [0xFC8E]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x649 },
+ unicodeslot=0xFC8E,
+ },
+ [0xFC8F]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x64A },
+ unicodeslot=0xFC8F,
+ },
+ [0xFC90]={
+ category="lo",
+ description="ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x649, 0x670 },
+ unicodeslot=0xFC90,
+ },
+ [0xFC91]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x631 },
+ unicodeslot=0xFC91,
+ },
+ [0xFC92]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x632 },
+ unicodeslot=0xFC92,
+ },
+ [0xFC93]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x645 },
+ unicodeslot=0xFC93,
+ },
+ [0xFC94]={
+ adobename="yehnoonfinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x646 },
+ unicodeslot=0xFC94,
+ },
+ [0xFC95]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x649 },
+ unicodeslot=0xFC95,
+ },
+ [0xFC96]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x64A },
+ unicodeslot=0xFC96,
+ },
+ [0xFC97]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x62C },
+ unicodeslot=0xFC97,
+ },
+ [0xFC98]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x62D },
+ unicodeslot=0xFC98,
+ },
+ [0xFC99]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x62E },
+ unicodeslot=0xFC99,
+ },
+ [0xFC9A]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x645 },
+ unicodeslot=0xFC9A,
+ },
+ [0xFC9B]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x626, 0x647 },
+ unicodeslot=0xFC9B,
+ },
+ [0xFC9C]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628, 0x62C },
+ unicodeslot=0xFC9C,
+ },
+ [0xFC9D]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628, 0x62D },
+ unicodeslot=0xFC9D,
+ },
+ [0xFC9E]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628, 0x62E },
+ unicodeslot=0xFC9E,
+ },
+ [0xFC9F]={
+ adobename="behmeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628, 0x645 },
+ unicodeslot=0xFC9F,
+ },
+ [0xFCA0]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628, 0x647 },
+ unicodeslot=0xFCA0,
+ },
+ [0xFCA1]={
+ adobename="tehjeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62C },
+ unicodeslot=0xFCA1,
+ },
+ [0xFCA2]={
+ adobename="tehhahinitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62D },
+ unicodeslot=0xFCA2,
+ },
+ [0xFCA3]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62E },
+ unicodeslot=0xFCA3,
+ },
+ [0xFCA4]={
+ adobename="tehmeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x645 },
+ unicodeslot=0xFCA4,
+ },
+ [0xFCA5]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x647 },
+ unicodeslot=0xFCA5,
+ },
+ [0xFCA6]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62B, 0x645 },
+ unicodeslot=0xFCA6,
+ },
+ [0xFCA7]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62C, 0x62D },
+ unicodeslot=0xFCA7,
+ },
+ [0xFCA8]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62C, 0x645 },
+ unicodeslot=0xFCA8,
+ },
+ [0xFCA9]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62D, 0x62C },
+ unicodeslot=0xFCA9,
+ },
+ [0xFCAA]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62D, 0x645 },
+ unicodeslot=0xFCAA,
+ },
+ [0xFCAB]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62E, 0x62C },
+ unicodeslot=0xFCAB,
+ },
+ [0xFCAC]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62E, 0x645 },
+ unicodeslot=0xFCAC,
+ },
+ [0xFCAD]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x62C },
+ unicodeslot=0xFCAD,
+ },
+ [0xFCAE]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x62D },
+ unicodeslot=0xFCAE,
+ },
+ [0xFCAF]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x62E },
+ unicodeslot=0xFCAF,
+ },
+ [0xFCB0]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x645 },
+ unicodeslot=0xFCB0,
+ },
+ [0xFCB1]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635, 0x62D },
+ unicodeslot=0xFCB1,
+ },
+ [0xFCB2]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635, 0x62E },
+ unicodeslot=0xFCB2,
+ },
+ [0xFCB3]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635, 0x645 },
+ unicodeslot=0xFCB3,
+ },
+ [0xFCB4]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636, 0x62C },
+ unicodeslot=0xFCB4,
+ },
+ [0xFCB5]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636, 0x62D },
+ unicodeslot=0xFCB5,
+ },
+ [0xFCB6]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636, 0x62E },
+ unicodeslot=0xFCB6,
+ },
+ [0xFCB7]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636, 0x645 },
+ unicodeslot=0xFCB7,
+ },
+ [0xFCB8]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x637, 0x62D },
+ unicodeslot=0xFCB8,
+ },
+ [0xFCB9]={
+ category="lo",
+ description="ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x638, 0x645 },
+ unicodeslot=0xFCB9,
+ },
+ [0xFCBA]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x639, 0x62C },
+ unicodeslot=0xFCBA,
+ },
+ [0xFCBB]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x639, 0x645 },
+ unicodeslot=0xFCBB,
+ },
+ [0xFCBC]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x63A, 0x62C },
+ unicodeslot=0xFCBC,
+ },
+ [0xFCBD]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x63A, 0x645 },
+ unicodeslot=0xFCBD,
+ },
+ [0xFCBE]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641, 0x62C },
+ unicodeslot=0xFCBE,
+ },
+ [0xFCBF]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641, 0x62D },
+ unicodeslot=0xFCBF,
+ },
+ [0xFCC0]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641, 0x62E },
+ unicodeslot=0xFCC0,
+ },
+ [0xFCC1]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641, 0x645 },
+ unicodeslot=0xFCC1,
+ },
+ [0xFCC2]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x642, 0x62D },
+ unicodeslot=0xFCC2,
+ },
+ [0xFCC3]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x642, 0x645 },
+ unicodeslot=0xFCC3,
+ },
+ [0xFCC4]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x62C },
+ unicodeslot=0xFCC4,
+ },
+ [0xFCC5]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x62D },
+ unicodeslot=0xFCC5,
+ },
+ [0xFCC6]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x62E },
+ unicodeslot=0xFCC6,
+ },
+ [0xFCC7]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH LAM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x644 },
+ unicodeslot=0xFCC7,
+ },
+ [0xFCC8]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x645 },
+ unicodeslot=0xFCC8,
+ },
+ [0xFCC9]={
+ adobename="lamjeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62C },
+ unicodeslot=0xFCC9,
+ },
+ [0xFCCA]={
+ adobename="lamhahinitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62D },
+ unicodeslot=0xFCCA,
+ },
+ [0xFCCB]={
+ adobename="lamkhahinitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62E },
+ unicodeslot=0xFCCB,
+ },
+ [0xFCCC]={
+ adobename="lammeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x645 },
+ unicodeslot=0xFCCC,
+ },
+ [0xFCCD]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x647 },
+ unicodeslot=0xFCCD,
+ },
+ [0xFCCE]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62C },
+ unicodeslot=0xFCCE,
+ },
+ [0xFCCF]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62D },
+ unicodeslot=0xFCCF,
+ },
+ [0xFCD0]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62E },
+ unicodeslot=0xFCD0,
+ },
+ [0xFCD1]={
+ adobename="meemmeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x645 },
+ unicodeslot=0xFCD1,
+ },
+ [0xFCD2]={
+ adobename="noonjeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62C },
+ unicodeslot=0xFCD2,
+ },
+ [0xFCD3]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62D },
+ unicodeslot=0xFCD3,
+ },
+ [0xFCD4]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62E },
+ unicodeslot=0xFCD4,
+ },
+ [0xFCD5]={
+ adobename="noonmeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x645 },
+ unicodeslot=0xFCD5,
+ },
+ [0xFCD6]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x647 },
+ unicodeslot=0xFCD6,
+ },
+ [0xFCD7]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647, 0x62C },
+ unicodeslot=0xFCD7,
+ },
+ [0xFCD8]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647, 0x645 },
+ unicodeslot=0xFCD8,
+ },
+ [0xFCD9]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647, 0x670 },
+ unicodeslot=0xFCD9,
+ },
+ [0xFCDA]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x62C },
+ unicodeslot=0xFCDA,
+ },
+ [0xFCDB]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x62D },
+ unicodeslot=0xFCDB,
+ },
+ [0xFCDC]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x62E },
+ unicodeslot=0xFCDC,
+ },
+ [0xFCDD]={
+ adobename="yehmeeminitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x645 },
+ unicodeslot=0xFCDD,
+ },
+ [0xFCDE]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x647 },
+ unicodeslot=0xFCDE,
+ },
+ [0xFCDF]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x626, 0x645 },
+ unicodeslot=0xFCDF,
+ },
+ [0xFCE0]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x626, 0x647 },
+ unicodeslot=0xFCE0,
+ },
+ [0xFCE1]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x628, 0x645 },
+ unicodeslot=0xFCE1,
+ },
+ [0xFCE2]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x628, 0x647 },
+ unicodeslot=0xFCE2,
+ },
+ [0xFCE3]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62A, 0x645 },
+ unicodeslot=0xFCE3,
+ },
+ [0xFCE4]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62A, 0x647 },
+ unicodeslot=0xFCE4,
+ },
+ [0xFCE5]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62B, 0x645 },
+ unicodeslot=0xFCE5,
+ },
+ [0xFCE6]={
+ category="lo",
+ description="ARABIC LIGATURE THEH WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62B, 0x647 },
+ unicodeslot=0xFCE6,
+ },
+ [0xFCE7]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633, 0x645 },
+ unicodeslot=0xFCE7,
+ },
+ [0xFCE8]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633, 0x647 },
+ unicodeslot=0xFCE8,
+ },
+ [0xFCE9]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634, 0x645 },
+ unicodeslot=0xFCE9,
+ },
+ [0xFCEA]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634, 0x647 },
+ unicodeslot=0xFCEA,
+ },
+ [0xFCEB]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH LAM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x643, 0x644 },
+ unicodeslot=0xFCEB,
+ },
+ [0xFCEC]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x643, 0x645 },
+ unicodeslot=0xFCEC,
+ },
+ [0xFCED]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x644, 0x645 },
+ unicodeslot=0xFCED,
+ },
+ [0xFCEE]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x646, 0x645 },
+ unicodeslot=0xFCEE,
+ },
+ [0xFCEF]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x646, 0x647 },
+ unicodeslot=0xFCEF,
+ },
+ [0xFCF0]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x64A, 0x645 },
+ unicodeslot=0xFCF0,
+ },
+ [0xFCF1]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x64A, 0x647 },
+ unicodeslot=0xFCF1,
+ },
+ [0xFCF2]={
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x64E, 0x651 },
+ unicodeslot=0xFCF2,
+ },
+ [0xFCF3]={
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x64F, 0x651 },
+ unicodeslot=0xFCF3,
+ },
+ [0xFCF4]={
+ category="lo",
+ description="ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x650, 0x651 },
+ unicodeslot=0xFCF4,
+ },
+ [0xFCF5]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x637, 0x649 },
+ unicodeslot=0xFCF5,
+ },
+ [0xFCF6]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x637, 0x64A },
+ unicodeslot=0xFCF6,
+ },
+ [0xFCF7]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639, 0x649 },
+ unicodeslot=0xFCF7,
+ },
+ [0xFCF8]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639, 0x64A },
+ unicodeslot=0xFCF8,
+ },
+ [0xFCF9]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x63A, 0x649 },
+ unicodeslot=0xFCF9,
+ },
+ [0xFCFA]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x63A, 0x64A },
+ unicodeslot=0xFCFA,
+ },
+ [0xFCFB]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x649 },
+ unicodeslot=0xFCFB,
+ },
+ [0xFCFC]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x64A },
+ unicodeslot=0xFCFC,
+ },
+ [0xFCFD]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x649 },
+ unicodeslot=0xFCFD,
+ },
+ [0xFCFE]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x64A },
+ unicodeslot=0xFCFE,
+ },
+ [0xFCFF]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62D, 0x649 },
+ unicodeslot=0xFCFF,
+ },
+ [0xFD00]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62D, 0x64A },
+ unicodeslot=0xFD00,
+ },
+ [0xFD01]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C, 0x649 },
+ unicodeslot=0xFD01,
+ },
+ [0xFD02]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C, 0x64A },
+ unicodeslot=0xFD02,
+ },
+ [0xFD03]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E, 0x649 },
+ unicodeslot=0xFD03,
+ },
+ [0xFD04]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E, 0x64A },
+ unicodeslot=0xFD04,
+ },
+ [0xFD05]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x649 },
+ unicodeslot=0xFD05,
+ },
+ [0xFD06]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x64A },
+ unicodeslot=0xFD06,
+ },
+ [0xFD07]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x649 },
+ unicodeslot=0xFD07,
+ },
+ [0xFD08]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x64A },
+ unicodeslot=0xFD08,
+ },
+ [0xFD09]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x62C },
+ unicodeslot=0xFD09,
+ },
+ [0xFD0A]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x62D },
+ unicodeslot=0xFD0A,
+ },
+ [0xFD0B]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x62E },
+ unicodeslot=0xFD0B,
+ },
+ [0xFD0C]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x645 },
+ unicodeslot=0xFD0C,
+ },
+ [0xFD0D]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634, 0x631 },
+ unicodeslot=0xFD0D,
+ },
+ [0xFD0E]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH REH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633, 0x631 },
+ unicodeslot=0xFD0E,
+ },
+ [0xFD0F]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH REH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x631 },
+ unicodeslot=0xFD0F,
+ },
+ [0xFD10]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH REH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636, 0x631 },
+ unicodeslot=0xFD10,
+ },
+ [0xFD11]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x637, 0x649 },
+ unicodeslot=0xFD11,
+ },
+ [0xFD12]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x637, 0x64A },
+ unicodeslot=0xFD12,
+ },
+ [0xFD13]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x649 },
+ unicodeslot=0xFD13,
+ },
+ [0xFD14]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x64A },
+ unicodeslot=0xFD14,
+ },
+ [0xFD15]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A, 0x649 },
+ unicodeslot=0xFD15,
+ },
+ [0xFD16]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A, 0x64A },
+ unicodeslot=0xFD16,
+ },
+ [0xFD17]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x649 },
+ unicodeslot=0xFD17,
+ },
+ [0xFD18]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x64A },
+ unicodeslot=0xFD18,
+ },
+ [0xFD19]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x649 },
+ unicodeslot=0xFD19,
+ },
+ [0xFD1A]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x64A },
+ unicodeslot=0xFD1A,
+ },
+ [0xFD1B]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D, 0x649 },
+ unicodeslot=0xFD1B,
+ },
+ [0xFD1C]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D, 0x64A },
+ unicodeslot=0xFD1C,
+ },
+ [0xFD1D]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x649 },
+ unicodeslot=0xFD1D,
+ },
+ [0xFD1E]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x64A },
+ unicodeslot=0xFD1E,
+ },
+ [0xFD1F]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62E, 0x649 },
+ unicodeslot=0xFD1F,
+ },
+ [0xFD20]={
+ category="lo",
+ description="ARABIC LIGATURE KHAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62E, 0x64A },
+ unicodeslot=0xFD20,
+ },
+ [0xFD21]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x649 },
+ unicodeslot=0xFD21,
+ },
+ [0xFD22]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x64A },
+ unicodeslot=0xFD22,
+ },
+ [0xFD23]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x649 },
+ unicodeslot=0xFD23,
+ },
+ [0xFD24]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x64A },
+ unicodeslot=0xFD24,
+ },
+ [0xFD25]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62C },
+ unicodeslot=0xFD25,
+ },
+ [0xFD26]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62D },
+ unicodeslot=0xFD26,
+ },
+ [0xFD27]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62E },
+ unicodeslot=0xFD27,
+ },
+ [0xFD28]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x645 },
+ unicodeslot=0xFD28,
+ },
+ [0xFD29]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x631 },
+ unicodeslot=0xFD29,
+ },
+ [0xFD2A]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x631 },
+ unicodeslot=0xFD2A,
+ },
+ [0xFD2B]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x631 },
+ unicodeslot=0xFD2B,
+ },
+ [0xFD2C]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x631 },
+ unicodeslot=0xFD2C,
+ },
+ [0xFD2D]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x62C },
+ unicodeslot=0xFD2D,
+ },
+ [0xFD2E]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x62D },
+ unicodeslot=0xFD2E,
+ },
+ [0xFD2F]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x62E },
+ unicodeslot=0xFD2F,
+ },
+ [0xFD30]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x645 },
+ unicodeslot=0xFD30,
+ },
+ [0xFD31]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x647 },
+ unicodeslot=0xFD31,
+ },
+ [0xFD32]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x647 },
+ unicodeslot=0xFD32,
+ },
+ [0xFD33]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x637, 0x645 },
+ unicodeslot=0xFD33,
+ },
+ [0xFD34]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633, 0x62C },
+ unicodeslot=0xFD34,
+ },
+ [0xFD35]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633, 0x62D },
+ unicodeslot=0xFD35,
+ },
+ [0xFD36]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633, 0x62E },
+ unicodeslot=0xFD36,
+ },
+ [0xFD37]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634, 0x62C },
+ unicodeslot=0xFD37,
+ },
+ [0xFD38]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634, 0x62D },
+ unicodeslot=0xFD38,
+ },
+ [0xFD39]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634, 0x62E },
+ unicodeslot=0xFD39,
+ },
+ [0xFD3A]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x637, 0x645 },
+ unicodeslot=0xFD3A,
+ },
+ [0xFD3B]={
+ category="lo",
+ description="ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x638, 0x645 },
+ unicodeslot=0xFD3B,
+ },
+ [0xFD3C]={
+ category="lo",
+ description="ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x627, 0x64B },
+ unicodeslot=0xFD3C,
+ },
+ [0xFD3D]={
+ category="lo",
+ description="ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x627, 0x64B },
+ unicodeslot=0xFD3D,
+ },
+ [0xFD3E]={
+ adobename="parenleftaltonearabic",
+ category="ps",
+ description="ORNATE LEFT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ unicodeslot=0xFD3E,
+ },
+ [0xFD3F]={
+ adobename="parenrightaltonearabic",
+ category="pe",
+ description="ORNATE RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0xFD3F,
+ },
+ [0xFD50]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62C, 0x645 },
+ unicodeslot=0xFD50,
+ },
+ [0xFD51]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x62D, 0x62C },
+ unicodeslot=0xFD51,
+ },
+ [0xFD52]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62D, 0x62C },
+ unicodeslot=0xFD52,
+ },
+ [0xFD53]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62D, 0x645 },
+ unicodeslot=0xFD53,
+ },
+ [0xFD54]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x62E, 0x645 },
+ unicodeslot=0xFD54,
+ },
+ [0xFD55]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x645, 0x62C },
+ unicodeslot=0xFD55,
+ },
+ [0xFD56]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x645, 0x62D },
+ unicodeslot=0xFD56,
+ },
+ [0xFD57]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A, 0x645, 0x62E },
+ unicodeslot=0xFD57,
+ },
+ [0xFD58]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x645, 0x62D },
+ unicodeslot=0xFD58,
+ },
+ [0xFD59]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62C, 0x645, 0x62D },
+ unicodeslot=0xFD59,
+ },
+ [0xFD5A]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D, 0x645, 0x64A },
+ unicodeslot=0xFD5A,
+ },
+ [0xFD5B]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D, 0x645, 0x649 },
+ unicodeslot=0xFD5B,
+ },
+ [0xFD5C]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x62D, 0x62C },
+ unicodeslot=0xFD5C,
+ },
+ [0xFD5D]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x62C, 0x62D },
+ unicodeslot=0xFD5D,
+ },
+ [0xFD5E]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x62C, 0x649 },
+ unicodeslot=0xFD5E,
+ },
+ [0xFD5F]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x645, 0x62D },
+ unicodeslot=0xFD5F,
+ },
+ [0xFD60]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x645, 0x62D },
+ unicodeslot=0xFD60,
+ },
+ [0xFD61]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x645, 0x62C },
+ unicodeslot=0xFD61,
+ },
+ [0xFD62]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x645, 0x645 },
+ unicodeslot=0xFD62,
+ },
+ [0xFD63]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633, 0x645, 0x645 },
+ unicodeslot=0xFD63,
+ },
+ [0xFD64]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x62D, 0x62D },
+ unicodeslot=0xFD64,
+ },
+ [0xFD65]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635, 0x62D, 0x62D },
+ unicodeslot=0xFD65,
+ },
+ [0xFD66]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x645, 0x645 },
+ unicodeslot=0xFD66,
+ },
+ [0xFD67]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62D, 0x645 },
+ unicodeslot=0xFD67,
+ },
+ [0xFD68]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x62D, 0x645 },
+ unicodeslot=0xFD68,
+ },
+ [0xFD69]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62C, 0x64A },
+ unicodeslot=0xFD69,
+ },
+ [0xFD6A]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x645, 0x62E },
+ unicodeslot=0xFD6A,
+ },
+ [0xFD6B]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x645, 0x62E },
+ unicodeslot=0xFD6B,
+ },
+ [0xFD6C]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x645, 0x645 },
+ unicodeslot=0xFD6C,
+ },
+ [0xFD6D]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634, 0x645, 0x645 },
+ unicodeslot=0xFD6D,
+ },
+ [0xFD6E]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x62D, 0x649 },
+ unicodeslot=0xFD6E,
+ },
+ [0xFD6F]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x62E, 0x645 },
+ unicodeslot=0xFD6F,
+ },
+ [0xFD70]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636, 0x62E, 0x645 },
+ unicodeslot=0xFD70,
+ },
+ [0xFD71]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x637, 0x645, 0x62D },
+ unicodeslot=0xFD71,
+ },
+ [0xFD72]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x637, 0x645, 0x62D },
+ unicodeslot=0xFD72,
+ },
+ [0xFD73]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x637, 0x645, 0x645 },
+ unicodeslot=0xFD73,
+ },
+ [0xFD74]={
+ category="lo",
+ description="ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x637, 0x645, 0x64A },
+ unicodeslot=0xFD74,
+ },
+ [0xFD75]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x62C, 0x645 },
+ unicodeslot=0xFD75,
+ },
+ [0xFD76]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x645, 0x645 },
+ unicodeslot=0xFD76,
+ },
+ [0xFD77]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x639, 0x645, 0x645 },
+ unicodeslot=0xFD77,
+ },
+ [0xFD78]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x645, 0x649 },
+ unicodeslot=0xFD78,
+ },
+ [0xFD79]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A, 0x645, 0x645 },
+ unicodeslot=0xFD79,
+ },
+ [0xFD7A]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A, 0x645, 0x64A },
+ unicodeslot=0xFD7A,
+ },
+ [0xFD7B]={
+ category="lo",
+ description="ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A, 0x645, 0x649 },
+ unicodeslot=0xFD7B,
+ },
+ [0xFD7C]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x641, 0x62E, 0x645 },
+ unicodeslot=0xFD7C,
+ },
+ [0xFD7D]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641, 0x62E, 0x645 },
+ unicodeslot=0xFD7D,
+ },
+ [0xFD7E]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642, 0x645, 0x62D },
+ unicodeslot=0xFD7E,
+ },
+ [0xFD7F]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642, 0x645, 0x645 },
+ unicodeslot=0xFD7F,
+ },
+ [0xFD80]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62D, 0x645 },
+ unicodeslot=0xFD80,
+ },
+ [0xFD81]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62D, 0x64A },
+ unicodeslot=0xFD81,
+ },
+ [0xFD82]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62D, 0x649 },
+ unicodeslot=0xFD82,
+ },
+ [0xFD83]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62C, 0x62C },
+ unicodeslot=0xFD83,
+ },
+ [0xFD84]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62C, 0x62C },
+ unicodeslot=0xFD84,
+ },
+ [0xFD85]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62E, 0x645 },
+ unicodeslot=0xFD85,
+ },
+ [0xFD86]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62E, 0x645 },
+ unicodeslot=0xFD86,
+ },
+ [0xFD87]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x645, 0x62D },
+ unicodeslot=0xFD87,
+ },
+ [0xFD88]={
+ adobename="lammeemhahinitialarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x645, 0x62D },
+ unicodeslot=0xFD88,
+ },
+ [0xFD89]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62D, 0x62C },
+ unicodeslot=0xFD89,
+ },
+ [0xFD8A]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62D, 0x645 },
+ unicodeslot=0xFD8A,
+ },
+ [0xFD8B]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x62D, 0x64A },
+ unicodeslot=0xFD8B,
+ },
+ [0xFD8C]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62C, 0x62D },
+ unicodeslot=0xFD8C,
+ },
+ [0xFD8D]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62C, 0x645 },
+ unicodeslot=0xFD8D,
+ },
+ [0xFD8E]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62E, 0x62C },
+ unicodeslot=0xFD8E,
+ },
+ [0xFD8F]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62E, 0x645 },
+ unicodeslot=0xFD8F,
+ },
+ [0xFD92]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645, 0x62C, 0x62E },
+ unicodeslot=0xFD92,
+ },
+ [0xFD93]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647, 0x645, 0x62C },
+ unicodeslot=0xFD93,
+ },
+ [0xFD94]={
+ category="lo",
+ description="ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647, 0x645, 0x645 },
+ unicodeslot=0xFD94,
+ },
+ [0xFD95]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62D, 0x645 },
+ unicodeslot=0xFD95,
+ },
+ [0xFD96]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62D, 0x649 },
+ unicodeslot=0xFD96,
+ },
+ [0xFD97]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62C, 0x645 },
+ unicodeslot=0xFD97,
+ },
+ [0xFD98]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62C, 0x645 },
+ unicodeslot=0xFD98,
+ },
+ [0xFD99]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62C, 0x649 },
+ unicodeslot=0xFD99,
+ },
+ [0xFD9A]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x645, 0x64A },
+ unicodeslot=0xFD9A,
+ },
+ [0xFD9B]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x645, 0x649 },
+ unicodeslot=0xFD9B,
+ },
+ [0xFD9C]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x645, 0x645 },
+ unicodeslot=0xFD9C,
+ },
+ [0xFD9D]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A, 0x645, 0x645 },
+ unicodeslot=0xFD9D,
+ },
+ [0xFD9E]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x62E, 0x64A },
+ unicodeslot=0xFD9E,
+ },
+ [0xFD9F]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x62C, 0x64A },
+ unicodeslot=0xFD9F,
+ },
+ [0xFDA0]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x62C, 0x649 },
+ unicodeslot=0xFDA0,
+ },
+ [0xFDA1]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x62E, 0x64A },
+ unicodeslot=0xFDA1,
+ },
+ [0xFDA2]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x62E, 0x649 },
+ unicodeslot=0xFDA2,
+ },
+ [0xFDA3]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x645, 0x64A },
+ unicodeslot=0xFDA3,
+ },
+ [0xFDA4]={
+ category="lo",
+ description="ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A, 0x645, 0x649 },
+ unicodeslot=0xFDA4,
+ },
+ [0xFDA5]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x645, 0x64A },
+ unicodeslot=0xFDA5,
+ },
+ [0xFDA6]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x62D, 0x649 },
+ unicodeslot=0xFDA6,
+ },
+ [0xFDA7]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x645, 0x649 },
+ unicodeslot=0xFDA7,
+ },
+ [0xFDA8]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x62E, 0x649 },
+ unicodeslot=0xFDA8,
+ },
+ [0xFDA9]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635, 0x62D, 0x64A },
+ unicodeslot=0xFDA9,
+ },
+ [0xFDAA]={
+ category="lo",
+ description="ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634, 0x62D, 0x64A },
+ unicodeslot=0xFDAA,
+ },
+ [0xFDAB]={
+ category="lo",
+ description="ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636, 0x62D, 0x64A },
+ unicodeslot=0xFDAB,
+ },
+ [0xFDAC]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62C, 0x64A },
+ unicodeslot=0xFDAC,
+ },
+ [0xFDAD]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x645, 0x64A },
+ unicodeslot=0xFDAD,
+ },
+ [0xFDAE]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x62D, 0x64A },
+ unicodeslot=0xFDAE,
+ },
+ [0xFDAF]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x62C, 0x64A },
+ unicodeslot=0xFDAF,
+ },
+ [0xFDB0]={
+ category="lo",
+ description="ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A, 0x645, 0x64A },
+ unicodeslot=0xFDB0,
+ },
+ [0xFDB1]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x645, 0x64A },
+ unicodeslot=0xFDB1,
+ },
+ [0xFDB2]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642, 0x645, 0x64A },
+ unicodeslot=0xFDB2,
+ },
+ [0xFDB3]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62D, 0x64A },
+ unicodeslot=0xFDB3,
+ },
+ [0xFDB4]={
+ category="lo",
+ description="ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x642, 0x645, 0x62D },
+ unicodeslot=0xFDB4,
+ },
+ [0xFDB5]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62D, 0x645 },
+ unicodeslot=0xFDB5,
+ },
+ [0xFDB6]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639, 0x645, 0x64A },
+ unicodeslot=0xFDB6,
+ },
+ [0xFDB7]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x645, 0x64A },
+ unicodeslot=0xFDB7,
+ },
+ [0xFDB8]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646, 0x62C, 0x62D },
+ unicodeslot=0xFDB8,
+ },
+ [0xFDB9]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x62E, 0x64A },
+ unicodeslot=0xFDB9,
+ },
+ [0xFDBA]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644, 0x62C, 0x645 },
+ unicodeslot=0xFDBA,
+ },
+ [0xFDBB]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643, 0x645, 0x645 },
+ unicodeslot=0xFDBB,
+ },
+ [0xFDBC]={
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x62C, 0x645 },
+ unicodeslot=0xFDBC,
+ },
+ [0xFDBD]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62C, 0x62D },
+ unicodeslot=0xFDBD,
+ },
+ [0xFDBE]={
+ category="lo",
+ description="ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C, 0x62D, 0x64A },
+ unicodeslot=0xFDBE,
+ },
+ [0xFDBF]={
+ category="lo",
+ description="ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D, 0x62C, 0x64A },
+ unicodeslot=0xFDBF,
+ },
+ [0xFDC0]={
+ category="lo",
+ description="ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645, 0x62C, 0x64A },
+ unicodeslot=0xFDC0,
+ },
+ [0xFDC1]={
+ category="lo",
+ description="ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x641, 0x645, 0x64A },
+ unicodeslot=0xFDC1,
+ },
+ [0xFDC2]={
+ category="lo",
+ description="ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628, 0x62D, 0x64A },
+ unicodeslot=0xFDC2,
+ },
+ [0xFDC3]={
+ category="lo",
+ description="ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643, 0x645, 0x645 },
+ unicodeslot=0xFDC3,
+ },
+ [0xFDC4]={
+ category="lo",
+ description="ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x639, 0x62C, 0x645 },
+ unicodeslot=0xFDC4,
+ },
+ [0xFDC5]={
+ category="lo",
+ description="ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635, 0x645, 0x645 },
+ unicodeslot=0xFDC5,
+ },
+ [0xFDC6]={
+ category="lo",
+ description="ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633, 0x62E, 0x64A },
+ unicodeslot=0xFDC6,
+ },
+ [0xFDC7]={
+ category="lo",
+ description="ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646, 0x62C, 0x64A },
+ unicodeslot=0xFDC7,
+ },
+ [0xFDF0]={
+ category="lo",
+ description="ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x644, 0x6D2 },
+ unicodeslot=0xFDF0,
+ },
+ [0xFDF1]={
+ category="lo",
+ description="ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642, 0x644, 0x6D2 },
+ unicodeslot=0xFDF1,
+ },
+ [0xFDF2]={
+ adobename="lamlamhehisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE ALLAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x627, 0x644, 0x644, 0x647 },
+ unicodeslot=0xFDF2,
+ },
+ [0xFDF3]={
+ category="lo",
+ description="ARABIC LIGATURE AKBAR ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x627, 0x643, 0x628, 0x631 },
+ unicodeslot=0xFDF3,
+ },
+ [0xFDF4]={
+ category="lo",
+ description="ARABIC LIGATURE MOHAMMAD ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645, 0x62D, 0x645, 0x62F },
+ unicodeslot=0xFDF4,
+ },
+ [0xFDF5]={
+ category="lo",
+ description="ARABIC LIGATURE SALAM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x644, 0x639, 0x645 },
+ unicodeslot=0xFDF5,
+ },
+ [0xFDF6]={
+ category="lo",
+ description="ARABIC LIGATURE RASOUL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x631, 0x633, 0x648, 0x644 },
+ unicodeslot=0xFDF6,
+ },
+ [0xFDF7]={
+ category="lo",
+ description="ARABIC LIGATURE ALAYHE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639, 0x644, 0x64A, 0x647 },
+ unicodeslot=0xFDF7,
+ },
+ [0xFDF8]={
+ category="lo",
+ description="ARABIC LIGATURE WASALLAM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x648, 0x633, 0x644, 0x645 },
+ unicodeslot=0xFDF8,
+ },
+ [0xFDF9]={
+ category="lo",
+ description="ARABIC LIGATURE SALLA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x644, 0x649 },
+ unicodeslot=0xFDF9,
+ },
+ [0xFDFA]={
+ adobename="sallallahoualayhewasallamarabic",
+ category="lo",
+ description="ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635, 0x644, 0x649, 0x20, 0x627, 0x644, 0x644, 0x647, 0x20, 0x639, 0x644, 0x64A, 0x647, 0x20, 0x648, 0x633, 0x644, 0x645 },
+ unicodeslot=0xFDFA,
+ },
+ [0xFDFB]={
+ category="lo",
+ description="ARABIC LIGATURE JALLAJALALOUHOU",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C, 0x644, 0x20, 0x62C, 0x644, 0x627, 0x644, 0x647 },
+ unicodeslot=0xFDFB,
+ },
+ [0xFDFC]={
+ category="sc",
+ description="RIAL SIGN",
+ direction="al",
+ linebreak="po",
+ specials={ "isolated", 0x631, 0x6CC, 0x627, 0x644 },
+ unicodeslot=0xFDFC,
+ },
+ [0xFDFD]={
+ category="so",
+ description="ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xFDFD,
+ },
+ [0xFE10]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL COMMA",
+ direction="on",
+ linebreak="is",
+ specials={ "vertical", 0x2C },
+ unicodeslot=0xFE10,
+ },
+ [0xFE11]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3001 },
+ unicodeslot=0xFE11,
+ },
+ [0xFE12]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3002 },
+ unicodeslot=0xFE12,
+ },
+ [0xFE13]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL COLON",
+ direction="on",
+ linebreak="is",
+ specials={ "vertical", 0x3A },
+ unicodeslot=0xFE13,
+ },
+ [0xFE14]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL SEMICOLON",
+ direction="on",
+ linebreak="is",
+ specials={ "vertical", 0x3B },
+ unicodeslot=0xFE14,
+ },
+ [0xFE15]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "vertical", 0x21 },
+ unicodeslot=0xFE15,
+ },
+ [0xFE16]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "vertical", 0x3F },
+ unicodeslot=0xFE16,
+ },
+ [0xFE17]={
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x3016 },
+ unicodeslot=0xFE17,
+ },
+ [0xFE18]={
+ category="pe",
+ cjkwd="w",
+ comment="corrected description: brakcet",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3017 },
+ unicodeslot=0xFE18,
+ },
+ [0xFE19]={
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS",
+ direction="on",
+ linebreak="in",
+ specials={ "vertical", 0x2026 },
+ unicodeslot=0xFE19,
+ },
+ [0xFE20]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LIGATURE LEFT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE20,
+ },
+ [0xFE21]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING LIGATURE RIGHT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE21,
+ },
+ [0xFE22]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOUBLE TILDE LEFT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE22,
+ },
+ [0xFE23]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING DOUBLE TILDE RIGHT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE23,
+ },
+ [0xFE24]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING MACRON LEFT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE24,
+ },
+ [0xFE25]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING MACRON RIGHT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE25,
+ },
+ [0xFE26]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CONJOINING MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE26,
+ },
+ [0xFE27]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LIGATURE LEFT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE27,
+ },
+ [0xFE28]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING LIGATURE RIGHT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE28,
+ },
+ [0xFE29]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING TILDE LEFT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE29,
+ },
+ [0xFE2A]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING TILDE RIGHT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2A,
+ },
+ [0xFE2B]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING MACRON LEFT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2B,
+ },
+ [0xFE2C]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING MACRON RIGHT HALF BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2C,
+ },
+ [0xFE2D]={
+ category="mn",
+ combining=0xDC,
+ description="COMBINING CONJOINING MACRON BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2D,
+ },
+ [0xFE2E]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC TITLO LEFT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2E,
+ },
+ [0xFE2F]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING CYRILLIC TITLO RIGHT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE2F,
+ },
+ [0xFE30]={
+ adobename="twodotleadervertical",
+ category="po",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL TWO DOT LEADER",
+ direction="on",
+ linebreak="id",
+ specials={ "vertical", 0x2025 },
+ unicodeslot=0xFE30,
+ },
+ [0xFE31]={
+ adobename="emdashvertical",
+ category="pd",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL EM DASH",
+ direction="on",
+ linebreak="id",
+ specials={ "vertical", 0x2014 },
+ unicodeslot=0xFE31,
+ },
+ [0xFE32]={
+ adobename="endashvertical",
+ category="pd",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL EN DASH",
+ direction="on",
+ linebreak="id",
+ specials={ "vertical", 0x2013 },
+ unicodeslot=0xFE32,
+ },
+ [0xFE33]={
+ adobename="underscorevertical",
+ category="pc",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "vertical", 0x5F },
+ unicodeslot=0xFE33,
+ },
+ [0xFE34]={
+ adobename="wavyunderscorevertical",
+ category="pc",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL WAVY LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "vertical", 0x5F },
+ unicodeslot=0xFE34,
+ },
+ [0xFE35]={
+ adobename="parenleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x28 },
+ unicodeslot=0xFE35,
+ },
+ [0xFE36]={
+ adobename="parenrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x29 },
+ unicodeslot=0xFE36,
+ },
+ [0xFE37]={
+ adobename="braceleftvertical",
+ category="ps",
+ cjkwd="w",
+ comment="weird math needed for mathml",
+ description="PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET",
+ direction="on",
+ linebreak="op",
+ mathfiller="downbracefill",
+ specials={ "vertical", 0x7B },
+ unicodeslot=0xFE37,
+ },
+ [0xFE38]={
+ adobename="bracerightvertical",
+ category="pe",
+ cjkwd="w",
+ comment="weird math needed for mathml",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET",
+ direction="on",
+ linebreak="cl",
+ mathfiller="upbracefill",
+ specials={ "vertical", 0x7D },
+ unicodeslot=0xFE38,
+ },
+ [0xFE39]={
+ adobename="tortoiseshellbracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x3014 },
+ unicodeslot=0xFE39,
+ },
+ [0xFE3A]={
+ adobename="tortoiseshellbracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3015 },
+ unicodeslot=0xFE3A,
+ },
+ [0xFE3B]={
+ adobename="blacklenticularbracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x3010 },
+ unicodeslot=0xFE3B,
+ },
+ [0xFE3C]={
+ adobename="blacklenticularbracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3011 },
+ unicodeslot=0xFE3C,
+ },
+ [0xFE3D]={
+ adobename="dblanglebracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x300A },
+ unicodeslot=0xFE3D,
+ },
+ [0xFE3E]={
+ adobename="dblanglebracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x300B },
+ unicodeslot=0xFE3E,
+ },
+ [0xFE3F]={
+ adobename="anglebracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x3008 },
+ unicodeslot=0xFE3F,
+ },
+ [0xFE40]={
+ adobename="anglebracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x3009 },
+ unicodeslot=0xFE40,
+ },
+ [0xFE41]={
+ adobename="cornerbracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x300C },
+ unicodeslot=0xFE41,
+ },
+ [0xFE42]={
+ adobename="cornerbracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x300D },
+ unicodeslot=0xFE42,
+ },
+ [0xFE43]={
+ adobename="whitecornerbracketleftvertical",
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x300E },
+ unicodeslot=0xFE43,
+ },
+ [0xFE44]={
+ adobename="whitecornerbracketrightvertical",
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x300F },
+ unicodeslot=0xFE44,
+ },
+ [0xFE45]={
+ category="po",
+ cjkwd="w",
+ description="SESAME DOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xFE45,
+ },
+ [0xFE46]={
+ category="po",
+ cjkwd="w",
+ description="WHITE SESAME DOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0xFE46,
+ },
+ [0xFE47]={
+ category="ps",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET",
+ direction="on",
+ linebreak="op",
+ specials={ "vertical", 0x5B },
+ unicodeslot=0xFE47,
+ },
+ [0xFE48]={
+ category="pe",
+ cjkwd="w",
+ description="PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET",
+ direction="on",
+ linebreak="cl",
+ specials={ "vertical", 0x5D },
+ unicodeslot=0xFE48,
+ },
+ [0xFE49]={
+ adobename="overlinedashed",
+ category="po",
+ cjkwd="w",
+ description="DASHED OVERLINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x203E },
+ unicodeslot=0xFE49,
+ },
+ [0xFE4A]={
+ adobename="overlinecenterline",
+ category="po",
+ cjkwd="w",
+ description="CENTRELINE OVERLINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x203E },
+ unicodeslot=0xFE4A,
+ },
+ [0xFE4B]={
+ adobename="overlinewavy",
+ category="po",
+ cjkwd="w",
+ description="WAVY OVERLINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x203E },
+ unicodeslot=0xFE4B,
+ },
+ [0xFE4C]={
+ adobename="overlinedblwavy",
+ category="po",
+ cjkwd="w",
+ description="DOUBLE WAVY OVERLINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x203E },
+ unicodeslot=0xFE4C,
+ },
+ [0xFE4D]={
+ adobename="lowlinedashed",
+ category="pc",
+ cjkwd="w",
+ description="DASHED LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F },
+ unicodeslot=0xFE4D,
+ },
+ [0xFE4E]={
+ adobename="lowlinecenterline",
+ category="pc",
+ cjkwd="w",
+ description="CENTRELINE LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F },
+ unicodeslot=0xFE4E,
+ },
+ [0xFE4F]={
+ adobename="underscorewavy",
+ category="pc",
+ cjkwd="w",
+ description="WAVY LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "compat", 0x5F },
+ unicodeslot=0xFE4F,
+ },
+ [0xFE50]={
+ adobename="commasmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL COMMA",
+ direction="cs",
+ linebreak="cl",
+ specials={ "small", 0x2C },
+ unicodeslot=0xFE50,
+ },
+ [0xFE51]={
+ category="po",
+ cjkwd="w",
+ description="SMALL IDEOGRAPHIC COMMA",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x3001 },
+ unicodeslot=0xFE51,
+ },
+ [0xFE52]={
+ adobename="periodsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL FULL STOP",
+ direction="cs",
+ linebreak="cl",
+ specials={ "small", 0x2E },
+ unicodeslot=0xFE52,
+ },
+ [0xFE54]={
+ adobename="semicolonsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL SEMICOLON",
+ direction="on",
+ linebreak="ns",
+ specials={ "small", 0x3B },
+ unicodeslot=0xFE54,
+ },
+ [0xFE55]={
+ adobename="colonsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL COLON",
+ direction="cs",
+ linebreak="ns",
+ specials={ "small", 0x3A },
+ unicodeslot=0xFE55,
+ },
+ [0xFE56]={
+ category="po",
+ cjkwd="w",
+ description="SMALL QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "small", 0x3F },
+ unicodeslot=0xFE56,
+ },
+ [0xFE57]={
+ category="po",
+ cjkwd="w",
+ description="SMALL EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "small", 0x21 },
+ unicodeslot=0xFE57,
+ },
+ [0xFE58]={
+ category="pd",
+ cjkwd="w",
+ description="SMALL EM DASH",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x2014 },
+ unicodeslot=0xFE58,
+ },
+ [0xFE59]={
+ adobename="parenleftsmall",
+ category="ps",
+ cjkwd="w",
+ description="SMALL LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0xFE5A,
+ specials={ "small", 0x28 },
+ textclass="open",
+ unicodeslot=0xFE59,
+ },
+ [0xFE5A]={
+ adobename="parenrightsmall",
+ category="pe",
+ cjkwd="w",
+ description="SMALL RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFE59,
+ specials={ "small", 0x29 },
+ textclass="close",
+ unicodeslot=0xFE5A,
+ },
+ [0xFE5B]={
+ adobename="braceleftsmall",
+ category="ps",
+ cjkwd="w",
+ description="SMALL LEFT CURLY BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0xFE5C,
+ specials={ "small", 0x7B },
+ textclass="open",
+ unicodeslot=0xFE5B,
+ },
+ [0xFE5C]={
+ adobename="bracerightsmall",
+ category="pe",
+ cjkwd="w",
+ description="SMALL RIGHT CURLY BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFE5B,
+ specials={ "small", 0x7D },
+ textclass="close",
+ unicodeslot=0xFE5C,
+ },
+ [0xFE5D]={
+ adobename="tortoiseshellbracketleftsmall",
+ category="ps",
+ cjkwd="w",
+ description="SMALL LEFT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0xFE5E,
+ specials={ "small", 0x3014 },
+ textclass="open",
+ unicodeslot=0xFE5D,
+ },
+ [0xFE5E]={
+ adobename="tortoiseshellbracketrightsmall",
+ category="pe",
+ cjkwd="w",
+ description="SMALL RIGHT TORTOISE SHELL BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFE5D,
+ specials={ "small", 0x3015 },
+ textclass="close",
+ unicodeslot=0xFE5E,
+ },
+ [0xFE5F]={
+ adobename="numbersignsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL NUMBER SIGN",
+ direction="et",
+ linebreak="id",
+ specials={ "small", 0x23 },
+ unicodeslot=0xFE5F,
+ },
+ [0xFE60]={
+ category="po",
+ cjkwd="w",
+ description="SMALL AMPERSAND",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x26 },
+ unicodeslot=0xFE60,
+ },
+ [0xFE61]={
+ adobename="asterisksmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL ASTERISK",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x2A },
+ unicodeslot=0xFE61,
+ },
+ [0xFE62]={
+ adobename="plussmall",
+ category="sm",
+ cjkwd="w",
+ description="SMALL PLUS SIGN",
+ direction="es",
+ linebreak="id",
+ specials={ "small", 0x2B },
+ unicodeslot=0xFE62,
+ },
+ [0xFE63]={
+ adobename="hyphensmall",
+ category="pd",
+ cjkwd="w",
+ description="SMALL HYPHEN-MINUS",
+ direction="es",
+ linebreak="id",
+ specials={ "small", 0x2D },
+ unicodeslot=0xFE63,
+ },
+ [0xFE64]={
+ adobename="lesssmall",
+ category="sm",
+ cjkwd="w",
+ description="SMALL LESS-THAN SIGN",
+ direction="on",
+ linebreak="id",
+ mirror=0xFE65,
+ specials={ "small", 0x3C },
+ textclass="open",
+ unicodeslot=0xFE64,
+ },
+ [0xFE65]={
+ adobename="greatersmall",
+ category="sm",
+ cjkwd="w",
+ description="SMALL GREATER-THAN SIGN",
+ direction="on",
+ linebreak="id",
+ mirror=0xFE64,
+ specials={ "small", 0x3E },
+ textclass="close",
+ unicodeslot=0xFE65,
+ },
+ [0xFE66]={
+ adobename="equalsmall",
+ category="sm",
+ cjkwd="w",
+ description="SMALL EQUALS SIGN",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x3D },
+ unicodeslot=0xFE66,
+ },
+ [0xFE68]={
+ category="po",
+ cjkwd="w",
+ description="SMALL REVERSE SOLIDUS",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x5C },
+ unicodeslot=0xFE68,
+ },
+ [0xFE69]={
+ adobename="dollarsmall",
+ category="sc",
+ cjkwd="w",
+ description="SMALL DOLLAR SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "small", 0x24 },
+ unicodeslot=0xFE69,
+ },
+ [0xFE6A]={
+ adobename="percentsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL PERCENT SIGN",
+ direction="et",
+ linebreak="po",
+ specials={ "small", 0x25 },
+ unicodeslot=0xFE6A,
+ },
+ [0xFE6B]={
+ adobename="atsmall",
+ category="po",
+ cjkwd="w",
+ description="SMALL COMMERCIAL AT",
+ direction="on",
+ linebreak="id",
+ specials={ "small", 0x40 },
+ unicodeslot=0xFE6B,
+ },
+ [0xFE70]={
+ category="lo",
+ description="ARABIC FATHATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64B },
+ unicodeslot=0xFE70,
+ },
+ [0xFE71]={
+ category="lo",
+ description="ARABIC TATWEEL WITH FATHATAN ABOVE",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x64B },
+ unicodeslot=0xFE71,
+ },
+ [0xFE72]={
+ category="lo",
+ description="ARABIC DAMMATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64C },
+ unicodeslot=0xFE72,
+ },
+ [0xFE73]={
+ category="lo",
+ description="ARABIC TAIL FRAGMENT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFE73,
+ },
+ [0xFE74]={
+ category="lo",
+ description="ARABIC KASRATAN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64D },
+ unicodeslot=0xFE74,
+ },
+ [0xFE76]={
+ category="lo",
+ description="ARABIC FATHA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64E },
+ unicodeslot=0xFE76,
+ },
+ [0xFE77]={
+ category="lo",
+ description="ARABIC FATHA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x64E },
+ unicodeslot=0xFE77,
+ },
+ [0xFE78]={
+ category="lo",
+ description="ARABIC DAMMA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x64F },
+ unicodeslot=0xFE78,
+ },
+ [0xFE79]={
+ category="lo",
+ description="ARABIC DAMMA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x64F },
+ unicodeslot=0xFE79,
+ },
+ [0xFE7A]={
+ category="lo",
+ description="ARABIC KASRA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x650 },
+ unicodeslot=0xFE7A,
+ },
+ [0xFE7B]={
+ category="lo",
+ description="ARABIC KASRA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x650 },
+ unicodeslot=0xFE7B,
+ },
+ [0xFE7C]={
+ category="lo",
+ description="ARABIC SHADDA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x651 },
+ unicodeslot=0xFE7C,
+ },
+ [0xFE7D]={
+ category="lo",
+ description="ARABIC SHADDA MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x651 },
+ unicodeslot=0xFE7D,
+ },
+ [0xFE7E]={
+ category="lo",
+ description="ARABIC SUKUN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x20, 0x652 },
+ unicodeslot=0xFE7E,
+ },
+ [0xFE7F]={
+ category="lo",
+ description="ARABIC SUKUN MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x640, 0x652 },
+ unicodeslot=0xFE7F,
+ },
+ [0xFE80]={
+ category="lo",
+ description="ARABIC LETTER HAMZA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x621 },
+ unicodeslot=0xFE80,
+ },
+ [0xFE81]={
+ category="lo",
+ description="ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "isolated", 0x622 },
+ unicodeslot=0xFE81,
+ },
+ [0xFE82]={
+ adobename="alefmaddaabovefinalarabic",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "final", 0x622 },
+ unicodeslot=0xFE82,
+ },
+ [0xFE83]={
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "isolated", 0x623 },
+ unicodeslot=0xFE83,
+ },
+ [0xFE84]={
+ adobename="alefhamzaabovefinalarabic",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "final", 0x623 },
+ unicodeslot=0xFE84,
+ },
+ [0xFE85]={
+ category="lo",
+ description="ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ specials={ "isolated", 0x624 },
+ unicodeslot=0xFE85,
+ },
+ [0xFE86]={
+ adobename="wawhamzaabovefinalarabic",
+ category="lo",
+ description="ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x648,
+ specials={ "final", 0x624 },
+ unicodeslot=0xFE86,
+ },
+ [0xFE87]={
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "isolated", 0x625 },
+ unicodeslot=0xFE87,
+ },
+ [0xFE88]={
+ adobename="alefhamzabelowfinalarabic",
+ category="lo",
+ description="ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x627,
+ specials={ "final", 0x625 },
+ unicodeslot=0xFE88,
+ },
+ [0xFE89]={
+ category="lo",
+ description="ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ specials={ "isolated", 0x626 },
+ unicodeslot=0xFE89,
+ },
+ [0xFE8A]={
+ adobename="yehhamzaabovefinalarabic",
+ category="lo",
+ description="ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ specials={ "final", 0x626 },
+ unicodeslot=0xFE8A,
+ },
+ [0xFE8B]={
+ adobename="yehhamzaaboveinitialarabic",
+ category="lo",
+ description="ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ specials={ "initial", 0x626 },
+ unicodeslot=0xFE8B,
+ },
+ [0xFE8C]={
+ adobename="yehhamzaabovemedialarabic",
+ category="lo",
+ description="ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ shcode=0x64A,
+ specials={ "medial", 0x626 },
+ unicodeslot=0xFE8C,
+ },
+ [0xFE8D]={
+ category="lo",
+ description="ARABIC LETTER ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x627 },
+ unicodeslot=0xFE8D,
+ },
+ [0xFE8E]={
+ adobename="aleffinalarabic",
+ category="lo",
+ description="ARABIC LETTER ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x627 },
+ unicodeslot=0xFE8E,
+ },
+ [0xFE8F]={
+ category="lo",
+ description="ARABIC LETTER BEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x628 },
+ unicodeslot=0xFE8F,
+ },
+ [0xFE90]={
+ adobename="behfinalarabic",
+ category="lo",
+ description="ARABIC LETTER BEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x628 },
+ unicodeslot=0xFE90,
+ },
+ [0xFE91]={
+ adobename="behinitialarabic",
+ category="lo",
+ description="ARABIC LETTER BEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x628 },
+ unicodeslot=0xFE91,
+ },
+ [0xFE92]={
+ adobename="behmedialarabic",
+ category="lo",
+ description="ARABIC LETTER BEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x628 },
+ unicodeslot=0xFE92,
+ },
+ [0xFE93]={
+ category="lo",
+ description="ARABIC LETTER TEH MARBUTA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x629 },
+ unicodeslot=0xFE93,
+ },
+ [0xFE94]={
+ adobename="tehmarbutafinalarabic",
+ category="lo",
+ description="ARABIC LETTER TEH MARBUTA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x629 },
+ unicodeslot=0xFE94,
+ },
+ [0xFE95]={
+ category="lo",
+ description="ARABIC LETTER TEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62A },
+ unicodeslot=0xFE95,
+ },
+ [0xFE96]={
+ adobename="tehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER TEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62A },
+ unicodeslot=0xFE96,
+ },
+ [0xFE97]={
+ adobename="tehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER TEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62A },
+ unicodeslot=0xFE97,
+ },
+ [0xFE98]={
+ adobename="tehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER TEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62A },
+ unicodeslot=0xFE98,
+ },
+ [0xFE99]={
+ category="lo",
+ description="ARABIC LETTER THEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62B },
+ unicodeslot=0xFE99,
+ },
+ [0xFE9A]={
+ adobename="thehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER THEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62B },
+ unicodeslot=0xFE9A,
+ },
+ [0xFE9B]={
+ adobename="thehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER THEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62B },
+ unicodeslot=0xFE9B,
+ },
+ [0xFE9C]={
+ adobename="thehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER THEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62B },
+ unicodeslot=0xFE9C,
+ },
+ [0xFE9D]={
+ category="lo",
+ description="ARABIC LETTER JEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62C },
+ unicodeslot=0xFE9D,
+ },
+ [0xFE9E]={
+ adobename="jeemfinalarabic",
+ category="lo",
+ description="ARABIC LETTER JEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62C },
+ unicodeslot=0xFE9E,
+ },
+ [0xFE9F]={
+ adobename="jeeminitialarabic",
+ category="lo",
+ description="ARABIC LETTER JEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62C },
+ unicodeslot=0xFE9F,
+ },
+ [0xFEA0]={
+ adobename="jeemmedialarabic",
+ category="lo",
+ description="ARABIC LETTER JEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62C },
+ unicodeslot=0xFEA0,
+ },
+ [0xFEA1]={
+ category="lo",
+ description="ARABIC LETTER HAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62D },
+ unicodeslot=0xFEA1,
+ },
+ [0xFEA2]={
+ adobename="hahfinalarabic",
+ category="lo",
+ description="ARABIC LETTER HAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62D },
+ unicodeslot=0xFEA2,
+ },
+ [0xFEA3]={
+ adobename="hahinitialarabic",
+ category="lo",
+ description="ARABIC LETTER HAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62D },
+ unicodeslot=0xFEA3,
+ },
+ [0xFEA4]={
+ adobename="hahmedialarabic",
+ category="lo",
+ description="ARABIC LETTER HAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62D },
+ unicodeslot=0xFEA4,
+ },
+ [0xFEA5]={
+ category="lo",
+ description="ARABIC LETTER KHAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62E },
+ unicodeslot=0xFEA5,
+ },
+ [0xFEA6]={
+ adobename="khahfinalarabic",
+ category="lo",
+ description="ARABIC LETTER KHAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62E },
+ unicodeslot=0xFEA6,
+ },
+ [0xFEA7]={
+ adobename="khahinitialarabic",
+ category="lo",
+ description="ARABIC LETTER KHAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x62E },
+ unicodeslot=0xFEA7,
+ },
+ [0xFEA8]={
+ adobename="khahmedialarabic",
+ category="lo",
+ description="ARABIC LETTER KHAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x62E },
+ unicodeslot=0xFEA8,
+ },
+ [0xFEA9]={
+ category="lo",
+ description="ARABIC LETTER DAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x62F },
+ unicodeslot=0xFEA9,
+ },
+ [0xFEAA]={
+ adobename="dalfinalarabic",
+ category="lo",
+ description="ARABIC LETTER DAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x62F },
+ unicodeslot=0xFEAA,
+ },
+ [0xFEAB]={
+ category="lo",
+ description="ARABIC LETTER THAL ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x630 },
+ unicodeslot=0xFEAB,
+ },
+ [0xFEAC]={
+ adobename="thalfinalarabic",
+ category="lo",
+ description="ARABIC LETTER THAL FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x630 },
+ unicodeslot=0xFEAC,
+ },
+ [0xFEAD]={
+ category="lo",
+ description="ARABIC LETTER REH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x631 },
+ unicodeslot=0xFEAD,
+ },
+ [0xFEAE]={
+ adobename="rehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER REH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x631 },
+ unicodeslot=0xFEAE,
+ },
+ [0xFEAF]={
+ category="lo",
+ description="ARABIC LETTER ZAIN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x632 },
+ unicodeslot=0xFEAF,
+ },
+ [0xFEB0]={
+ adobename="zainfinalarabic",
+ category="lo",
+ description="ARABIC LETTER ZAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x632 },
+ unicodeslot=0xFEB0,
+ },
+ [0xFEB1]={
+ category="lo",
+ description="ARABIC LETTER SEEN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x633 },
+ unicodeslot=0xFEB1,
+ },
+ [0xFEB2]={
+ adobename="seenfinalarabic",
+ category="lo",
+ description="ARABIC LETTER SEEN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x633 },
+ unicodeslot=0xFEB2,
+ },
+ [0xFEB3]={
+ adobename="seeninitialarabic",
+ category="lo",
+ description="ARABIC LETTER SEEN INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x633 },
+ unicodeslot=0xFEB3,
+ },
+ [0xFEB4]={
+ adobename="seenmedialarabic",
+ category="lo",
+ description="ARABIC LETTER SEEN MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x633 },
+ unicodeslot=0xFEB4,
+ },
+ [0xFEB5]={
+ category="lo",
+ description="ARABIC LETTER SHEEN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x634 },
+ unicodeslot=0xFEB5,
+ },
+ [0xFEB6]={
+ adobename="sheenfinalarabic",
+ category="lo",
+ description="ARABIC LETTER SHEEN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x634 },
+ unicodeslot=0xFEB6,
+ },
+ [0xFEB7]={
+ adobename="sheeninitialarabic",
+ category="lo",
+ description="ARABIC LETTER SHEEN INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x634 },
+ unicodeslot=0xFEB7,
+ },
+ [0xFEB8]={
+ adobename="sheenmedialarabic",
+ category="lo",
+ description="ARABIC LETTER SHEEN MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x634 },
+ unicodeslot=0xFEB8,
+ },
+ [0xFEB9]={
+ category="lo",
+ description="ARABIC LETTER SAD ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x635 },
+ unicodeslot=0xFEB9,
+ },
+ [0xFEBA]={
+ adobename="sadfinalarabic",
+ category="lo",
+ description="ARABIC LETTER SAD FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x635 },
+ unicodeslot=0xFEBA,
+ },
+ [0xFEBB]={
+ adobename="sadinitialarabic",
+ category="lo",
+ description="ARABIC LETTER SAD INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x635 },
+ unicodeslot=0xFEBB,
+ },
+ [0xFEBC]={
+ adobename="sadmedialarabic",
+ category="lo",
+ description="ARABIC LETTER SAD MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x635 },
+ unicodeslot=0xFEBC,
+ },
+ [0xFEBD]={
+ category="lo",
+ description="ARABIC LETTER DAD ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x636 },
+ unicodeslot=0xFEBD,
+ },
+ [0xFEBE]={
+ adobename="dadfinalarabic",
+ category="lo",
+ description="ARABIC LETTER DAD FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x636 },
+ unicodeslot=0xFEBE,
+ },
+ [0xFEBF]={
+ adobename="dadinitialarabic",
+ category="lo",
+ description="ARABIC LETTER DAD INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x636 },
+ unicodeslot=0xFEBF,
+ },
+ [0xFEC0]={
+ adobename="dadmedialarabic",
+ category="lo",
+ description="ARABIC LETTER DAD MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x636 },
+ unicodeslot=0xFEC0,
+ },
+ [0xFEC1]={
+ category="lo",
+ description="ARABIC LETTER TAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x637 },
+ unicodeslot=0xFEC1,
+ },
+ [0xFEC2]={
+ adobename="tahfinalarabic",
+ category="lo",
+ description="ARABIC LETTER TAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x637 },
+ unicodeslot=0xFEC2,
+ },
+ [0xFEC3]={
+ adobename="tahinitialarabic",
+ category="lo",
+ description="ARABIC LETTER TAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x637 },
+ unicodeslot=0xFEC3,
+ },
+ [0xFEC4]={
+ adobename="tahmedialarabic",
+ category="lo",
+ description="ARABIC LETTER TAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x637 },
+ unicodeslot=0xFEC4,
+ },
+ [0xFEC5]={
+ category="lo",
+ description="ARABIC LETTER ZAH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x638 },
+ unicodeslot=0xFEC5,
+ },
+ [0xFEC6]={
+ adobename="zahfinalarabic",
+ category="lo",
+ description="ARABIC LETTER ZAH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x638 },
+ unicodeslot=0xFEC6,
+ },
+ [0xFEC7]={
+ adobename="zahinitialarabic",
+ category="lo",
+ description="ARABIC LETTER ZAH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x638 },
+ unicodeslot=0xFEC7,
+ },
+ [0xFEC8]={
+ adobename="zahmedialarabic",
+ category="lo",
+ description="ARABIC LETTER ZAH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x638 },
+ unicodeslot=0xFEC8,
+ },
+ [0xFEC9]={
+ category="lo",
+ description="ARABIC LETTER AIN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x639 },
+ unicodeslot=0xFEC9,
+ },
+ [0xFECA]={
+ adobename="ainfinalarabic",
+ category="lo",
+ description="ARABIC LETTER AIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x639 },
+ unicodeslot=0xFECA,
+ },
+ [0xFECB]={
+ adobename="aininitialarabic",
+ category="lo",
+ description="ARABIC LETTER AIN INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x639 },
+ unicodeslot=0xFECB,
+ },
+ [0xFECC]={
+ adobename="ainmedialarabic",
+ category="lo",
+ description="ARABIC LETTER AIN MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x639 },
+ unicodeslot=0xFECC,
+ },
+ [0xFECD]={
+ category="lo",
+ description="ARABIC LETTER GHAIN ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x63A },
+ unicodeslot=0xFECD,
+ },
+ [0xFECE]={
+ adobename="ghainfinalarabic",
+ category="lo",
+ description="ARABIC LETTER GHAIN FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x63A },
+ unicodeslot=0xFECE,
+ },
+ [0xFECF]={
+ adobename="ghaininitialarabic",
+ category="lo",
+ description="ARABIC LETTER GHAIN INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x63A },
+ unicodeslot=0xFECF,
+ },
+ [0xFED0]={
+ adobename="ghainmedialarabic",
+ category="lo",
+ description="ARABIC LETTER GHAIN MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x63A },
+ unicodeslot=0xFED0,
+ },
+ [0xFED1]={
+ category="lo",
+ description="ARABIC LETTER FEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x641 },
+ unicodeslot=0xFED1,
+ },
+ [0xFED2]={
+ adobename="fehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER FEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x641 },
+ unicodeslot=0xFED2,
+ },
+ [0xFED3]={
+ adobename="fehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER FEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x641 },
+ unicodeslot=0xFED3,
+ },
+ [0xFED4]={
+ adobename="fehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER FEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x641 },
+ unicodeslot=0xFED4,
+ },
+ [0xFED5]={
+ category="lo",
+ description="ARABIC LETTER QAF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x642 },
+ unicodeslot=0xFED5,
+ },
+ [0xFED6]={
+ adobename="qaffinalarabic",
+ category="lo",
+ description="ARABIC LETTER QAF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x642 },
+ unicodeslot=0xFED6,
+ },
+ [0xFED7]={
+ adobename="qafinitialarabic",
+ category="lo",
+ description="ARABIC LETTER QAF INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x642 },
+ unicodeslot=0xFED7,
+ },
+ [0xFED8]={
+ adobename="qafmedialarabic",
+ category="lo",
+ description="ARABIC LETTER QAF MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x642 },
+ unicodeslot=0xFED8,
+ },
+ [0xFED9]={
+ category="lo",
+ description="ARABIC LETTER KAF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x643 },
+ unicodeslot=0xFED9,
+ },
+ [0xFEDA]={
+ adobename="kaffinalarabic",
+ category="lo",
+ description="ARABIC LETTER KAF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x643 },
+ unicodeslot=0xFEDA,
+ },
+ [0xFEDB]={
+ adobename="kafinitialarabic",
+ category="lo",
+ description="ARABIC LETTER KAF INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x643 },
+ unicodeslot=0xFEDB,
+ },
+ [0xFEDC]={
+ adobename="kafmedialarabic",
+ category="lo",
+ description="ARABIC LETTER KAF MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x643 },
+ unicodeslot=0xFEDC,
+ },
+ [0xFEDD]={
+ category="lo",
+ description="ARABIC LETTER LAM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644 },
+ unicodeslot=0xFEDD,
+ },
+ [0xFEDE]={
+ adobename="lamfinalarabic",
+ category="lo",
+ description="ARABIC LETTER LAM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644 },
+ unicodeslot=0xFEDE,
+ },
+ [0xFEDF]={
+ adobename="lammeemkhahinitialarabic",
+ category="lo",
+ description="ARABIC LETTER LAM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x644 },
+ unicodeslot=0xFEDF,
+ },
+ [0xFEE0]={
+ adobename="lammedialarabic",
+ category="lo",
+ description="ARABIC LETTER LAM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x644 },
+ unicodeslot=0xFEE0,
+ },
+ [0xFEE1]={
+ category="lo",
+ description="ARABIC LETTER MEEM ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x645 },
+ unicodeslot=0xFEE1,
+ },
+ [0xFEE2]={
+ adobename="meemfinalarabic",
+ category="lo",
+ description="ARABIC LETTER MEEM FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x645 },
+ unicodeslot=0xFEE2,
+ },
+ [0xFEE3]={
+ adobename="meeminitialarabic",
+ category="lo",
+ description="ARABIC LETTER MEEM INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x645 },
+ unicodeslot=0xFEE3,
+ },
+ [0xFEE4]={
+ adobename="meemmedialarabic",
+ category="lo",
+ description="ARABIC LETTER MEEM MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x645 },
+ unicodeslot=0xFEE4,
+ },
+ [0xFEE5]={
+ category="lo",
+ description="ARABIC LETTER NOON ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x646 },
+ unicodeslot=0xFEE5,
+ },
+ [0xFEE6]={
+ adobename="noonfinalarabic",
+ category="lo",
+ description="ARABIC LETTER NOON FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x646 },
+ unicodeslot=0xFEE6,
+ },
+ [0xFEE7]={
+ adobename="nooninitialarabic",
+ category="lo",
+ description="ARABIC LETTER NOON INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x646 },
+ unicodeslot=0xFEE7,
+ },
+ [0xFEE8]={
+ adobename="noonmedialarabic",
+ category="lo",
+ description="ARABIC LETTER NOON MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x646 },
+ unicodeslot=0xFEE8,
+ },
+ [0xFEE9]={
+ category="lo",
+ description="ARABIC LETTER HEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x647 },
+ unicodeslot=0xFEE9,
+ },
+ [0xFEEA]={
+ adobename="hehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER HEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x647 },
+ unicodeslot=0xFEEA,
+ },
+ [0xFEEB]={
+ adobename="hehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER HEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x647 },
+ unicodeslot=0xFEEB,
+ },
+ [0xFEEC]={
+ adobename="hehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER HEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x647 },
+ unicodeslot=0xFEEC,
+ },
+ [0xFEED]={
+ category="lo",
+ description="ARABIC LETTER WAW ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x648 },
+ unicodeslot=0xFEED,
+ },
+ [0xFEEE]={
+ adobename="wawfinalarabic",
+ category="lo",
+ description="ARABIC LETTER WAW FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x648 },
+ unicodeslot=0xFEEE,
+ },
+ [0xFEEF]={
+ category="lo",
+ description="ARABIC LETTER ALEF MAKSURA ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x649 },
+ unicodeslot=0xFEEF,
+ },
+ [0xFEF0]={
+ adobename="alefmaksurafinalarabic",
+ category="lo",
+ description="ARABIC LETTER ALEF MAKSURA FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x649 },
+ unicodeslot=0xFEF0,
+ },
+ [0xFEF1]={
+ category="lo",
+ description="ARABIC LETTER YEH ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x64A },
+ unicodeslot=0xFEF1,
+ },
+ [0xFEF2]={
+ adobename="yehfinalarabic",
+ category="lo",
+ description="ARABIC LETTER YEH FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x64A },
+ unicodeslot=0xFEF2,
+ },
+ [0xFEF3]={
+ adobename="yehinitialarabic",
+ category="lo",
+ description="ARABIC LETTER YEH INITIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "initial", 0x64A },
+ unicodeslot=0xFEF3,
+ },
+ [0xFEF4]={
+ adobename="yehmedialarabic",
+ category="lo",
+ description="ARABIC LETTER YEH MEDIAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "medial", 0x64A },
+ unicodeslot=0xFEF4,
+ },
+ [0xFEF5]={
+ adobename="lamalefmaddaaboveisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x622 },
+ unicodeslot=0xFEF5,
+ },
+ [0xFEF6]={
+ adobename="lamalefmaddaabovefinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x622 },
+ unicodeslot=0xFEF6,
+ },
+ [0xFEF7]={
+ adobename="lamalefhamzaaboveisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x623 },
+ unicodeslot=0xFEF7,
+ },
+ [0xFEF8]={
+ adobename="lamalefhamzaabovefinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x623 },
+ unicodeslot=0xFEF8,
+ },
+ [0xFEF9]={
+ adobename="lamalefhamzabelowisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x625 },
+ unicodeslot=0xFEF9,
+ },
+ [0xFEFA]={
+ adobename="lamalefhamzabelowfinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x625 },
+ unicodeslot=0xFEFA,
+ },
+ [0xFEFB]={
+ adobename="lamalefisolatedarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "isolated", 0x644, 0x627 },
+ unicodeslot=0xFEFB,
+ },
+ [0xFEFC]={
+ adobename="lamaleffinalarabic",
+ category="lo",
+ description="ARABIC LIGATURE LAM WITH ALEF FINAL FORM",
+ direction="al",
+ linebreak="al",
+ specials={ "final", 0x644, 0x627 },
+ unicodeslot=0xFEFC,
+ },
+ [0xFEFF]={
+ adobename="zerowidthjoiner",
+ category="cf",
+ contextname="zerowidthnobreakspace",
+ description="ZERO WIDTH NO-BREAK SPACE",
+ direction="bn",
+ linebreak="wj",
+ unicodeslot=0xFEFF,
+ },
+ [0xFF01]={
+ adobename="exclammonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH EXCLAMATION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "wide", 0x21 },
+ unicodeslot=0xFF01,
+ },
+ [0xFF02]={
+ adobename="quotedblmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH QUOTATION MARK",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x22 },
+ unicodeslot=0xFF02,
+ },
+ [0xFF03]={
+ adobename="numbersignmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH NUMBER SIGN",
+ direction="et",
+ linebreak="id",
+ specials={ "wide", 0x23 },
+ unicodeslot=0xFF03,
+ },
+ [0xFF04]={
+ adobename="dollarmonospace",
+ category="sc",
+ cjkwd="f",
+ description="FULLWIDTH DOLLAR SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "wide", 0x24 },
+ unicodeslot=0xFF04,
+ },
+ [0xFF05]={
+ adobename="percentmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH PERCENT SIGN",
+ direction="et",
+ linebreak="po",
+ specials={ "wide", 0x25 },
+ unicodeslot=0xFF05,
+ },
+ [0xFF06]={
+ adobename="ampersandmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH AMPERSAND",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x26 },
+ unicodeslot=0xFF06,
+ },
+ [0xFF07]={
+ adobename="quotesinglemonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH APOSTROPHE",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x27 },
+ unicodeslot=0xFF07,
+ },
+ [0xFF08]={
+ adobename="parenleftmonospace",
+ category="ps",
+ cjkwd="f",
+ description="FULLWIDTH LEFT PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0xFF09,
+ specials={ "wide", 0x28 },
+ textclass="open",
+ unicodeslot=0xFF08,
+ },
+ [0xFF09]={
+ adobename="parenrightmonospace",
+ category="pe",
+ cjkwd="f",
+ description="FULLWIDTH RIGHT PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFF08,
+ specials={ "wide", 0x29 },
+ textclass="close",
+ unicodeslot=0xFF09,
+ },
+ [0xFF0A]={
+ adobename="asteriskmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH ASTERISK",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x2A },
+ unicodeslot=0xFF0A,
+ },
+ [0xFF0B]={
+ adobename="plusmonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH PLUS SIGN",
+ direction="es",
+ linebreak="id",
+ specials={ "wide", 0x2B },
+ unicodeslot=0xFF0B,
+ },
+ [0xFF0C]={
+ adobename="commamonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH COMMA",
+ direction="cs",
+ linebreak="cl",
+ specials={ "wide", 0x2C },
+ unicodeslot=0xFF0C,
+ },
+ [0xFF0D]={
+ adobename="hyphenmonospace",
+ category="pd",
+ cjkwd="f",
+ description="FULLWIDTH HYPHEN-MINUS",
+ direction="es",
+ linebreak="id",
+ specials={ "wide", 0x2D },
+ unicodeslot=0xFF0D,
+ },
+ [0xFF0E]={
+ adobename="periodmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH FULL STOP",
+ direction="cs",
+ linebreak="cl",
+ specials={ "wide", 0x2E },
+ unicodeslot=0xFF0E,
+ },
+ [0xFF0F]={
+ adobename="slashmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH SOLIDUS",
+ direction="cs",
+ linebreak="id",
+ specials={ "wide", 0x2F },
+ unicodeslot=0xFF0F,
+ },
+ [0xFF10]={
+ adobename="zeromonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT ZERO",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x30 },
+ unicodeslot=0xFF10,
+ },
+ [0xFF11]={
+ adobename="onemonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT ONE",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x31 },
+ unicodeslot=0xFF11,
+ },
+ [0xFF12]={
+ adobename="twomonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT TWO",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x32 },
+ unicodeslot=0xFF12,
+ },
+ [0xFF13]={
+ adobename="threemonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT THREE",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x33 },
+ unicodeslot=0xFF13,
+ },
+ [0xFF14]={
+ adobename="fourmonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT FOUR",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x34 },
+ unicodeslot=0xFF14,
+ },
+ [0xFF15]={
+ adobename="fivemonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT FIVE",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x35 },
+ unicodeslot=0xFF15,
+ },
+ [0xFF16]={
+ adobename="sixmonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT SIX",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x36 },
+ unicodeslot=0xFF16,
+ },
+ [0xFF17]={
+ adobename="sevenmonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT SEVEN",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x37 },
+ unicodeslot=0xFF17,
+ },
+ [0xFF18]={
+ adobename="eightmonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT EIGHT",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x38 },
+ unicodeslot=0xFF18,
+ },
+ [0xFF19]={
+ adobename="ninemonospace",
+ category="nd",
+ cjkwd="f",
+ description="FULLWIDTH DIGIT NINE",
+ direction="en",
+ linebreak="id",
+ specials={ "wide", 0x39 },
+ unicodeslot=0xFF19,
+ },
+ [0xFF1A]={
+ adobename="colonmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH COLON",
+ direction="cs",
+ linebreak="ns",
+ specials={ "wide", 0x3A },
+ unicodeslot=0xFF1A,
+ },
+ [0xFF1B]={
+ adobename="semicolonmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH SEMICOLON",
+ direction="on",
+ linebreak="ns",
+ specials={ "wide", 0x3B },
+ unicodeslot=0xFF1B,
+ },
+ [0xFF1C]={
+ adobename="lessmonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH LESS-THAN SIGN",
+ direction="on",
+ linebreak="id",
+ mirror=0xFF1E,
+ specials={ "wide", 0x3C },
+ textclass="open",
+ unicodeslot=0xFF1C,
+ },
+ [0xFF1D]={
+ adobename="equalmonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH EQUALS SIGN",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x3D },
+ unicodeslot=0xFF1D,
+ },
+ [0xFF1E]={
+ adobename="greatermonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH GREATER-THAN SIGN",
+ direction="on",
+ linebreak="id",
+ mirror=0xFF1C,
+ specials={ "wide", 0x3E },
+ textclass="close",
+ unicodeslot=0xFF1E,
+ },
+ [0xFF1F]={
+ adobename="questionmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ specials={ "wide", 0x3F },
+ unicodeslot=0xFF1F,
+ },
+ [0xFF20]={
+ adobename="atmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH COMMERCIAL AT",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x40 },
+ unicodeslot=0xFF20,
+ },
+ [0xFF21]={
+ adobename="Amonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER A",
+ direction="l",
+ lccode=0xFF41,
+ linebreak="id",
+ specials={ "wide", 0x41 },
+ unicodeslot=0xFF21,
+ },
+ [0xFF22]={
+ adobename="Bmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER B",
+ direction="l",
+ lccode=0xFF42,
+ linebreak="id",
+ specials={ "wide", 0x42 },
+ unicodeslot=0xFF22,
+ },
+ [0xFF23]={
+ adobename="Cmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER C",
+ direction="l",
+ lccode=0xFF43,
+ linebreak="id",
+ specials={ "wide", 0x43 },
+ unicodeslot=0xFF23,
+ },
+ [0xFF24]={
+ adobename="Dmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER D",
+ direction="l",
+ lccode=0xFF44,
+ linebreak="id",
+ specials={ "wide", 0x44 },
+ unicodeslot=0xFF24,
+ },
+ [0xFF25]={
+ adobename="Emonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER E",
+ direction="l",
+ lccode=0xFF45,
+ linebreak="id",
+ specials={ "wide", 0x45 },
+ unicodeslot=0xFF25,
+ },
+ [0xFF26]={
+ adobename="Fmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER F",
+ direction="l",
+ lccode=0xFF46,
+ linebreak="id",
+ specials={ "wide", 0x46 },
+ unicodeslot=0xFF26,
+ },
+ [0xFF27]={
+ adobename="Gmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER G",
+ direction="l",
+ lccode=0xFF47,
+ linebreak="id",
+ specials={ "wide", 0x47 },
+ unicodeslot=0xFF27,
+ },
+ [0xFF28]={
+ adobename="Hmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER H",
+ direction="l",
+ lccode=0xFF48,
+ linebreak="id",
+ specials={ "wide", 0x48 },
+ unicodeslot=0xFF28,
+ },
+ [0xFF29]={
+ adobename="Imonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER I",
+ direction="l",
+ lccode=0xFF49,
+ linebreak="id",
+ specials={ "wide", 0x49 },
+ unicodeslot=0xFF29,
+ },
+ [0xFF2A]={
+ adobename="Jmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER J",
+ direction="l",
+ lccode=0xFF4A,
+ linebreak="id",
+ specials={ "wide", 0x4A },
+ unicodeslot=0xFF2A,
+ },
+ [0xFF2B]={
+ adobename="Kmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER K",
+ direction="l",
+ lccode=0xFF4B,
+ linebreak="id",
+ specials={ "wide", 0x4B },
+ unicodeslot=0xFF2B,
+ },
+ [0xFF2C]={
+ adobename="Lmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER L",
+ direction="l",
+ lccode=0xFF4C,
+ linebreak="id",
+ specials={ "wide", 0x4C },
+ unicodeslot=0xFF2C,
+ },
+ [0xFF2D]={
+ adobename="Mmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER M",
+ direction="l",
+ lccode=0xFF4D,
+ linebreak="id",
+ specials={ "wide", 0x4D },
+ unicodeslot=0xFF2D,
+ },
+ [0xFF2E]={
+ adobename="Nmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER N",
+ direction="l",
+ lccode=0xFF4E,
+ linebreak="id",
+ specials={ "wide", 0x4E },
+ unicodeslot=0xFF2E,
+ },
+ [0xFF2F]={
+ adobename="Omonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER O",
+ direction="l",
+ lccode=0xFF4F,
+ linebreak="id",
+ specials={ "wide", 0x4F },
+ unicodeslot=0xFF2F,
+ },
+ [0xFF30]={
+ adobename="Pmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER P",
+ direction="l",
+ lccode=0xFF50,
+ linebreak="id",
+ specials={ "wide", 0x50 },
+ unicodeslot=0xFF30,
+ },
+ [0xFF31]={
+ adobename="Qmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER Q",
+ direction="l",
+ lccode=0xFF51,
+ linebreak="id",
+ specials={ "wide", 0x51 },
+ unicodeslot=0xFF31,
+ },
+ [0xFF32]={
+ adobename="Rmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER R",
+ direction="l",
+ lccode=0xFF52,
+ linebreak="id",
+ specials={ "wide", 0x52 },
+ unicodeslot=0xFF32,
+ },
+ [0xFF33]={
+ adobename="Smonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER S",
+ direction="l",
+ lccode=0xFF53,
+ linebreak="id",
+ specials={ "wide", 0x53 },
+ unicodeslot=0xFF33,
+ },
+ [0xFF34]={
+ adobename="Tmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER T",
+ direction="l",
+ lccode=0xFF54,
+ linebreak="id",
+ specials={ "wide", 0x54 },
+ unicodeslot=0xFF34,
+ },
+ [0xFF35]={
+ adobename="Umonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER U",
+ direction="l",
+ lccode=0xFF55,
+ linebreak="id",
+ specials={ "wide", 0x55 },
+ unicodeslot=0xFF35,
+ },
+ [0xFF36]={
+ adobename="Vmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER V",
+ direction="l",
+ lccode=0xFF56,
+ linebreak="id",
+ specials={ "wide", 0x56 },
+ unicodeslot=0xFF36,
+ },
+ [0xFF37]={
+ adobename="Wmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER W",
+ direction="l",
+ lccode=0xFF57,
+ linebreak="id",
+ specials={ "wide", 0x57 },
+ unicodeslot=0xFF37,
+ },
+ [0xFF38]={
+ adobename="Xmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER X",
+ direction="l",
+ lccode=0xFF58,
+ linebreak="id",
+ specials={ "wide", 0x58 },
+ unicodeslot=0xFF38,
+ },
+ [0xFF39]={
+ adobename="Ymonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER Y",
+ direction="l",
+ lccode=0xFF59,
+ linebreak="id",
+ specials={ "wide", 0x59 },
+ unicodeslot=0xFF39,
+ },
+ [0xFF3A]={
+ adobename="Zmonospace",
+ category="lu",
+ cjkwd="f",
+ description="FULLWIDTH LATIN CAPITAL LETTER Z",
+ direction="l",
+ lccode=0xFF5A,
+ linebreak="id",
+ specials={ "wide", 0x5A },
+ unicodeslot=0xFF3A,
+ },
+ [0xFF3B]={
+ adobename="bracketleftmonospace",
+ category="ps",
+ cjkwd="f",
+ description="FULLWIDTH LEFT SQUARE BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0xFF3D,
+ specials={ "wide", 0x5B },
+ textclass="open",
+ unicodeslot=0xFF3B,
+ },
+ [0xFF3C]={
+ adobename="backslashmonospace",
+ category="po",
+ cjkwd="f",
+ description="FULLWIDTH REVERSE SOLIDUS",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x5C },
+ unicodeslot=0xFF3C,
+ },
+ [0xFF3D]={
+ adobename="bracketrightmonospace",
+ category="pe",
+ cjkwd="f",
+ description="FULLWIDTH RIGHT SQUARE BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFF3B,
+ specials={ "wide", 0x5D },
+ textclass="close",
+ unicodeslot=0xFF3D,
+ },
+ [0xFF3E]={
+ adobename="asciicircummonospace",
+ category="sk",
+ cjkwd="f",
+ description="FULLWIDTH CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x5E },
+ unicodeslot=0xFF3E,
+ },
+ [0xFF3F]={
+ adobename="underscoremonospace",
+ category="pc",
+ cjkwd="f",
+ description="FULLWIDTH LOW LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x5F },
+ unicodeslot=0xFF3F,
+ },
+ [0xFF40]={
+ adobename="gravemonospace",
+ category="sk",
+ cjkwd="f",
+ description="FULLWIDTH GRAVE ACCENT",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x60 },
+ unicodeslot=0xFF40,
+ },
+ [0xFF41]={
+ adobename="amonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER A",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x61 },
+ uccode=0xFF21,
+ unicodeslot=0xFF41,
+ },
+ [0xFF42]={
+ adobename="bmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER B",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x62 },
+ uccode=0xFF22,
+ unicodeslot=0xFF42,
+ },
+ [0xFF43]={
+ adobename="cmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER C",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x63 },
+ uccode=0xFF23,
+ unicodeslot=0xFF43,
+ },
+ [0xFF44]={
+ adobename="dmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER D",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x64 },
+ uccode=0xFF24,
+ unicodeslot=0xFF44,
+ },
+ [0xFF45]={
+ adobename="emonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER E",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x65 },
+ uccode=0xFF25,
+ unicodeslot=0xFF45,
+ },
+ [0xFF46]={
+ adobename="fmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER F",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x66 },
+ uccode=0xFF26,
+ unicodeslot=0xFF46,
+ },
+ [0xFF47]={
+ adobename="gmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER G",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x67 },
+ uccode=0xFF27,
+ unicodeslot=0xFF47,
+ },
+ [0xFF48]={
+ adobename="hmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER H",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x68 },
+ uccode=0xFF28,
+ unicodeslot=0xFF48,
+ },
+ [0xFF49]={
+ adobename="imonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER I",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x69 },
+ uccode=0xFF29,
+ unicodeslot=0xFF49,
+ },
+ [0xFF4A]={
+ adobename="jmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER J",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6A },
+ uccode=0xFF2A,
+ unicodeslot=0xFF4A,
+ },
+ [0xFF4B]={
+ adobename="kmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER K",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6B },
+ uccode=0xFF2B,
+ unicodeslot=0xFF4B,
+ },
+ [0xFF4C]={
+ adobename="lmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER L",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6C },
+ uccode=0xFF2C,
+ unicodeslot=0xFF4C,
+ },
+ [0xFF4D]={
+ adobename="mmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER M",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6D },
+ uccode=0xFF2D,
+ unicodeslot=0xFF4D,
+ },
+ [0xFF4E]={
+ adobename="nmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER N",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6E },
+ uccode=0xFF2E,
+ unicodeslot=0xFF4E,
+ },
+ [0xFF4F]={
+ adobename="omonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER O",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x6F },
+ uccode=0xFF2F,
+ unicodeslot=0xFF4F,
+ },
+ [0xFF50]={
+ adobename="pmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER P",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x70 },
+ uccode=0xFF30,
+ unicodeslot=0xFF50,
+ },
+ [0xFF51]={
+ adobename="qmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER Q",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x71 },
+ uccode=0xFF31,
+ unicodeslot=0xFF51,
+ },
+ [0xFF52]={
+ adobename="rmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER R",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x72 },
+ uccode=0xFF32,
+ unicodeslot=0xFF52,
+ },
+ [0xFF53]={
+ adobename="smonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER S",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x73 },
+ uccode=0xFF33,
+ unicodeslot=0xFF53,
+ },
+ [0xFF54]={
+ adobename="tmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER T",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x74 },
+ uccode=0xFF34,
+ unicodeslot=0xFF54,
+ },
+ [0xFF55]={
+ adobename="umonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER U",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x75 },
+ uccode=0xFF35,
+ unicodeslot=0xFF55,
+ },
+ [0xFF56]={
+ adobename="vmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER V",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x76 },
+ uccode=0xFF36,
+ unicodeslot=0xFF56,
+ },
+ [0xFF57]={
+ adobename="wmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER W",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x77 },
+ uccode=0xFF37,
+ unicodeslot=0xFF57,
+ },
+ [0xFF58]={
+ adobename="xmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER X",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x78 },
+ uccode=0xFF38,
+ unicodeslot=0xFF58,
+ },
+ [0xFF59]={
+ adobename="ymonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER Y",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x79 },
+ uccode=0xFF39,
+ unicodeslot=0xFF59,
+ },
+ [0xFF5A]={
+ adobename="zmonospace",
+ category="ll",
+ cjkwd="f",
+ description="FULLWIDTH LATIN SMALL LETTER Z",
+ direction="l",
+ linebreak="id",
+ specials={ "wide", 0x7A },
+ uccode=0xFF3A,
+ unicodeslot=0xFF5A,
+ },
+ [0xFF5B]={
+ adobename="braceleftmonospace",
+ category="ps",
+ cjkwd="f",
+ description="FULLWIDTH LEFT CURLY BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0xFF5D,
+ specials={ "wide", 0x7B },
+ textclass="open",
+ unicodeslot=0xFF5B,
+ },
+ [0xFF5C]={
+ adobename="barmonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH VERTICAL LINE",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x7C },
+ unicodeslot=0xFF5C,
+ },
+ [0xFF5D]={
+ adobename="bracerightmonospace",
+ category="pe",
+ cjkwd="f",
+ description="FULLWIDTH RIGHT CURLY BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFF5B,
+ specials={ "wide", 0x7D },
+ textclass="close",
+ unicodeslot=0xFF5D,
+ },
+ [0xFF5E]={
+ adobename="asciitildemonospace",
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH TILDE",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0x7E },
+ unicodeslot=0xFF5E,
+ },
+ [0xFF5F]={
+ category="ps",
+ cjkwd="f",
+ description="FULLWIDTH LEFT WHITE PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0xFF60,
+ specials={ "wide", 0x2985 },
+ textclass="open",
+ unicodeslot=0xFF5F,
+ },
+ [0xFF60]={
+ category="pe",
+ cjkwd="f",
+ description="FULLWIDTH RIGHT WHITE PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFF5F,
+ specials={ "wide", 0x2986 },
+ textclass="close",
+ unicodeslot=0xFF60,
+ },
+ [0xFF61]={
+ adobename="periodhalfwidth",
+ category="po",
+ cjkwd="h",
+ description="HALFWIDTH IDEOGRAPHIC FULL STOP",
+ direction="on",
+ linebreak="cl",
+ specials={ "narrow", 0x3002 },
+ unicodeslot=0xFF61,
+ },
+ [0xFF62]={
+ adobename="cornerbracketlefthalfwidth",
+ category="ps",
+ cjkwd="h",
+ description="HALFWIDTH LEFT CORNER BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0xFF63,
+ specials={ "narrow", 0x300C },
+ textclass="open",
+ unicodeslot=0xFF62,
+ },
+ [0xFF63]={
+ adobename="cornerbracketrighthalfwidth",
+ category="pe",
+ cjkwd="h",
+ description="HALFWIDTH RIGHT CORNER BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0xFF62,
+ specials={ "narrow", 0x300D },
+ textclass="close",
+ unicodeslot=0xFF63,
+ },
+ [0xFF64]={
+ adobename="ideographiccommaleft",
+ category="po",
+ cjkwd="h",
+ description="HALFWIDTH IDEOGRAPHIC COMMA",
+ direction="on",
+ linebreak="cl",
+ specials={ "narrow", 0x3001 },
+ unicodeslot=0xFF64,
+ },
+ [0xFF65]={
+ adobename="middledotkatakanahalfwidth",
+ category="po",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA MIDDLE DOT",
+ direction="on",
+ linebreak="ns",
+ specials={ "narrow", 0x30FB },
+ unicodeslot=0xFF65,
+ },
+ [0xFF66]={
+ adobename="wokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER WO",
+ direction="l",
+ linebreak="al",
+ shcode=0x3092,
+ specials={ "narrow", 0x30F2 },
+ unicodeslot=0xFF66,
+ },
+ [0xFF67]={
+ adobename="asmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL A",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30A1 },
+ unicodeslot=0xFF67,
+ },
+ [0xFF68]={
+ adobename="ismallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL I",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30A3 },
+ unicodeslot=0xFF68,
+ },
+ [0xFF69]={
+ adobename="usmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL U",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30A5 },
+ unicodeslot=0xFF69,
+ },
+ [0xFF6A]={
+ adobename="esmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL E",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30A7 },
+ unicodeslot=0xFF6A,
+ },
+ [0xFF6B]={
+ adobename="osmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL O",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30A9 },
+ unicodeslot=0xFF6B,
+ },
+ [0xFF6C]={
+ adobename="yasmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL YA",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3084,
+ specials={ "narrow", 0x30E3 },
+ unicodeslot=0xFF6C,
+ },
+ [0xFF6D]={
+ adobename="yusmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL YU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3086,
+ specials={ "narrow", 0x30E5 },
+ unicodeslot=0xFF6D,
+ },
+ [0xFF6E]={
+ adobename="yosmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL YO",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3088,
+ specials={ "narrow", 0x30E7 },
+ unicodeslot=0xFF6E,
+ },
+ [0xFF6F]={
+ adobename="tusmallkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SMALL TU",
+ direction="l",
+ linebreak="cj",
+ shcode=0x3064,
+ specials={ "narrow", 0x30C3 },
+ unicodeslot=0xFF6F,
+ },
+ [0xFF70]={
+ adobename="katahiraprolongmarkhalfwidth",
+ category="lm",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK",
+ direction="l",
+ linebreak="cj",
+ specials={ "narrow", 0x30FC },
+ unicodeslot=0xFF70,
+ },
+ [0xFF71]={
+ adobename="akatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER A",
+ direction="l",
+ linebreak="al",
+ shcode=0x3042,
+ specials={ "narrow", 0x30A2 },
+ unicodeslot=0xFF71,
+ },
+ [0xFF72]={
+ adobename="ikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER I",
+ direction="l",
+ linebreak="al",
+ shcode=0x3044,
+ specials={ "narrow", 0x30A4 },
+ unicodeslot=0xFF72,
+ },
+ [0xFF73]={
+ adobename="ukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER U",
+ direction="l",
+ linebreak="al",
+ shcode=0x3046,
+ specials={ "narrow", 0x30A6 },
+ unicodeslot=0xFF73,
+ },
+ [0xFF74]={
+ adobename="ekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER E",
+ direction="l",
+ linebreak="al",
+ shcode=0x3048,
+ specials={ "narrow", 0x30A8 },
+ unicodeslot=0xFF74,
+ },
+ [0xFF75]={
+ adobename="okatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER O",
+ direction="l",
+ linebreak="al",
+ shcode=0x304A,
+ specials={ "narrow", 0x30AA },
+ unicodeslot=0xFF75,
+ },
+ [0xFF76]={
+ adobename="kakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER KA",
+ direction="l",
+ linebreak="al",
+ shcode=0x304B,
+ specials={ "narrow", 0x30AB },
+ unicodeslot=0xFF76,
+ },
+ [0xFF77]={
+ adobename="kikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER KI",
+ direction="l",
+ linebreak="al",
+ shcode=0x304D,
+ specials={ "narrow", 0x30AD },
+ unicodeslot=0xFF77,
+ },
+ [0xFF78]={
+ adobename="kukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER KU",
+ direction="l",
+ linebreak="al",
+ shcode=0x304F,
+ specials={ "narrow", 0x30AF },
+ unicodeslot=0xFF78,
+ },
+ [0xFF79]={
+ adobename="kekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER KE",
+ direction="l",
+ linebreak="al",
+ shcode=0x3051,
+ specials={ "narrow", 0x30B1 },
+ unicodeslot=0xFF79,
+ },
+ [0xFF7A]={
+ adobename="kokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER KO",
+ direction="l",
+ linebreak="al",
+ shcode=0x3053,
+ specials={ "narrow", 0x30B3 },
+ unicodeslot=0xFF7A,
+ },
+ [0xFF7B]={
+ adobename="sakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3055,
+ specials={ "narrow", 0x30B5 },
+ unicodeslot=0xFF7B,
+ },
+ [0xFF7C]={
+ adobename="sikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3057,
+ specials={ "narrow", 0x30B7 },
+ unicodeslot=0xFF7C,
+ },
+ [0xFF7D]={
+ adobename="sukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SU",
+ direction="l",
+ linebreak="al",
+ shcode=0x3059,
+ specials={ "narrow", 0x30B9 },
+ unicodeslot=0xFF7D,
+ },
+ [0xFF7E]={
+ adobename="sekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SE",
+ direction="l",
+ linebreak="al",
+ shcode=0x305B,
+ specials={ "narrow", 0x30BB },
+ unicodeslot=0xFF7E,
+ },
+ [0xFF7F]={
+ adobename="sokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER SO",
+ direction="l",
+ linebreak="al",
+ shcode=0x305D,
+ specials={ "narrow", 0x30BD },
+ unicodeslot=0xFF7F,
+ },
+ [0xFF80]={
+ adobename="takatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER TA",
+ direction="l",
+ linebreak="al",
+ shcode=0x305F,
+ specials={ "narrow", 0x30BF },
+ unicodeslot=0xFF80,
+ },
+ [0xFF81]={
+ adobename="tikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER TI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3061,
+ specials={ "narrow", 0x30C1 },
+ unicodeslot=0xFF81,
+ },
+ [0xFF82]={
+ adobename="tukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER TU",
+ direction="l",
+ linebreak="al",
+ shcode=0x3064,
+ specials={ "narrow", 0x30C4 },
+ unicodeslot=0xFF82,
+ },
+ [0xFF83]={
+ adobename="tekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER TE",
+ direction="l",
+ linebreak="al",
+ shcode=0x3066,
+ specials={ "narrow", 0x30C6 },
+ unicodeslot=0xFF83,
+ },
+ [0xFF84]={
+ adobename="tokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER TO",
+ direction="l",
+ linebreak="al",
+ shcode=0x3068,
+ specials={ "narrow", 0x30C8 },
+ unicodeslot=0xFF84,
+ },
+ [0xFF85]={
+ adobename="nakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER NA",
+ direction="l",
+ linebreak="al",
+ shcode=0x306A,
+ specials={ "narrow", 0x30CA },
+ unicodeslot=0xFF85,
+ },
+ [0xFF86]={
+ adobename="nikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER NI",
+ direction="l",
+ linebreak="al",
+ shcode=0x306B,
+ specials={ "narrow", 0x30CB },
+ unicodeslot=0xFF86,
+ },
+ [0xFF87]={
+ adobename="nukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER NU",
+ direction="l",
+ linebreak="al",
+ shcode=0x306C,
+ specials={ "narrow", 0x30CC },
+ unicodeslot=0xFF87,
+ },
+ [0xFF88]={
+ adobename="nekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER NE",
+ direction="l",
+ linebreak="al",
+ shcode=0x306D,
+ specials={ "narrow", 0x30CD },
+ unicodeslot=0xFF88,
+ },
+ [0xFF89]={
+ adobename="nokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER NO",
+ direction="l",
+ linebreak="al",
+ shcode=0x306E,
+ specials={ "narrow", 0x30CE },
+ unicodeslot=0xFF89,
+ },
+ [0xFF8A]={
+ adobename="hakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER HA",
+ direction="l",
+ linebreak="al",
+ shcode=0x306F,
+ specials={ "narrow", 0x30CF },
+ unicodeslot=0xFF8A,
+ },
+ [0xFF8B]={
+ adobename="hikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER HI",
+ direction="l",
+ linebreak="al",
+ shcode=0x3072,
+ specials={ "narrow", 0x30D2 },
+ unicodeslot=0xFF8B,
+ },
+ [0xFF8C]={
+ adobename="hukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER HU",
+ direction="l",
+ linebreak="al",
+ shcode=0x3075,
+ specials={ "narrow", 0x30D5 },
+ unicodeslot=0xFF8C,
+ },
+ [0xFF8D]={
+ adobename="hekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER HE",
+ direction="l",
+ linebreak="al",
+ shcode=0x3078,
+ specials={ "narrow", 0x30D8 },
+ unicodeslot=0xFF8D,
+ },
+ [0xFF8E]={
+ adobename="hokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER HO",
+ direction="l",
+ linebreak="al",
+ shcode=0x307B,
+ specials={ "narrow", 0x30DB },
+ unicodeslot=0xFF8E,
+ },
+ [0xFF8F]={
+ adobename="makatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER MA",
+ direction="l",
+ linebreak="al",
+ shcode=0x307E,
+ specials={ "narrow", 0x30DE },
+ unicodeslot=0xFF8F,
+ },
+ [0xFF90]={
+ adobename="mikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER MI",
+ direction="l",
+ linebreak="al",
+ shcode=0x307F,
+ specials={ "narrow", 0x30DF },
+ unicodeslot=0xFF90,
+ },
+ [0xFF91]={
+ adobename="mukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER MU",
+ direction="l",
+ linebreak="al",
+ shcode=0x3080,
+ specials={ "narrow", 0x30E0 },
+ unicodeslot=0xFF91,
+ },
+ [0xFF92]={
+ adobename="mekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER ME",
+ direction="l",
+ linebreak="al",
+ shcode=0x3081,
+ specials={ "narrow", 0x30E1 },
+ unicodeslot=0xFF92,
+ },
+ [0xFF93]={
+ adobename="mokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER MO",
+ direction="l",
+ linebreak="al",
+ shcode=0x3082,
+ specials={ "narrow", 0x30E2 },
+ unicodeslot=0xFF93,
+ },
+ [0xFF94]={
+ adobename="yakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER YA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3084,
+ specials={ "narrow", 0x30E4 },
+ unicodeslot=0xFF94,
+ },
+ [0xFF95]={
+ adobename="yukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER YU",
+ direction="l",
+ linebreak="al",
+ shcode=0x3086,
+ specials={ "narrow", 0x30E6 },
+ unicodeslot=0xFF95,
+ },
+ [0xFF96]={
+ adobename="yokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER YO",
+ direction="l",
+ linebreak="al",
+ shcode=0x3088,
+ specials={ "narrow", 0x30E8 },
+ unicodeslot=0xFF96,
+ },
+ [0xFF97]={
+ adobename="rakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER RA",
+ direction="l",
+ linebreak="al",
+ shcode=0x3089,
+ specials={ "narrow", 0x30E9 },
+ unicodeslot=0xFF97,
+ },
+ [0xFF98]={
+ adobename="rikatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER RI",
+ direction="l",
+ linebreak="al",
+ shcode=0x308A,
+ specials={ "narrow", 0x30EA },
+ unicodeslot=0xFF98,
+ },
+ [0xFF99]={
+ adobename="rukatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER RU",
+ direction="l",
+ linebreak="al",
+ shcode=0x308B,
+ specials={ "narrow", 0x30EB },
+ unicodeslot=0xFF99,
+ },
+ [0xFF9A]={
+ adobename="rekatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER RE",
+ direction="l",
+ linebreak="al",
+ shcode=0x308C,
+ specials={ "narrow", 0x30EC },
+ unicodeslot=0xFF9A,
+ },
+ [0xFF9B]={
+ adobename="rokatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER RO",
+ direction="l",
+ linebreak="al",
+ shcode=0x308D,
+ specials={ "narrow", 0x30ED },
+ unicodeslot=0xFF9B,
+ },
+ [0xFF9C]={
+ adobename="wakatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER WA",
+ direction="l",
+ linebreak="al",
+ shcode=0x308F,
+ specials={ "narrow", 0x30EF },
+ unicodeslot=0xFF9C,
+ },
+ [0xFF9D]={
+ adobename="nkatakanahalfwidth",
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA LETTER N",
+ direction="l",
+ linebreak="al",
+ shcode=0x3093,
+ specials={ "narrow", 0x30F3 },
+ unicodeslot=0xFF9D,
+ },
+ [0xFF9E]={
+ adobename="voicedmarkkanahalfwidth",
+ category="lm",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA VOICED SOUND MARK",
+ direction="l",
+ linebreak="ns",
+ specials={ "narrow", 0x3099 },
+ unicodeslot=0xFF9E,
+ },
+ [0xFF9F]={
+ adobename="semivoicedmarkkanahalfwidth",
+ category="lm",
+ cjkwd="h",
+ description="HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK",
+ direction="l",
+ linebreak="ns",
+ specials={ "narrow", 0x309A },
+ unicodeslot=0xFF9F,
+ },
+ [0xFFA0]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL FILLER",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3164 },
+ unicodeslot=0xFFA0,
+ },
+ [0xFFA1]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER KIYEOK",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3131 },
+ unicodeslot=0xFFA1,
+ },
+ [0xFFA2]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SSANGKIYEOK",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3132 },
+ unicodeslot=0xFFA2,
+ },
+ [0xFFA3]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER KIYEOK-SIOS",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3133 },
+ unicodeslot=0xFFA3,
+ },
+ [0xFFA4]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER NIEUN",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3134 },
+ unicodeslot=0xFFA4,
+ },
+ [0xFFA5]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER NIEUN-CIEUC",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3135 },
+ unicodeslot=0xFFA5,
+ },
+ [0xFFA6]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER NIEUN-HIEUH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3136 },
+ unicodeslot=0xFFA6,
+ },
+ [0xFFA7]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER TIKEUT",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3137 },
+ unicodeslot=0xFFA7,
+ },
+ [0xFFA8]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SSANGTIKEUT",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3138 },
+ unicodeslot=0xFFA8,
+ },
+ [0xFFA9]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3139 },
+ unicodeslot=0xFFA9,
+ },
+ [0xFFAA]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-KIYEOK",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313A },
+ unicodeslot=0xFFAA,
+ },
+ [0xFFAB]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-MIEUM",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313B },
+ unicodeslot=0xFFAB,
+ },
+ [0xFFAC]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-PIEUP",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313C },
+ unicodeslot=0xFFAC,
+ },
+ [0xFFAD]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-SIOS",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313D },
+ unicodeslot=0xFFAD,
+ },
+ [0xFFAE]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-THIEUTH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313E },
+ unicodeslot=0xFFAE,
+ },
+ [0xFFAF]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x313F },
+ unicodeslot=0xFFAF,
+ },
+ [0xFFB0]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER RIEUL-HIEUH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3140 },
+ unicodeslot=0xFFB0,
+ },
+ [0xFFB1]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER MIEUM",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3141 },
+ unicodeslot=0xFFB1,
+ },
+ [0xFFB2]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER PIEUP",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3142 },
+ unicodeslot=0xFFB2,
+ },
+ [0xFFB3]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SSANGPIEUP",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3143 },
+ unicodeslot=0xFFB3,
+ },
+ [0xFFB4]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER PIEUP-SIOS",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3144 },
+ unicodeslot=0xFFB4,
+ },
+ [0xFFB5]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SIOS",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3145 },
+ unicodeslot=0xFFB5,
+ },
+ [0xFFB6]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SSANGSIOS",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3146 },
+ unicodeslot=0xFFB6,
+ },
+ [0xFFB7]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER IEUNG",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3147 },
+ unicodeslot=0xFFB7,
+ },
+ [0xFFB8]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER CIEUC",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3148 },
+ unicodeslot=0xFFB8,
+ },
+ [0xFFB9]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER SSANGCIEUC",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3149 },
+ unicodeslot=0xFFB9,
+ },
+ [0xFFBA]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER CHIEUCH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314A },
+ unicodeslot=0xFFBA,
+ },
+ [0xFFBB]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER KHIEUKH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314B },
+ unicodeslot=0xFFBB,
+ },
+ [0xFFBC]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER THIEUTH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314C },
+ unicodeslot=0xFFBC,
+ },
+ [0xFFBD]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER PHIEUPH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314D },
+ unicodeslot=0xFFBD,
+ },
+ [0xFFBE]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER HIEUH",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314E },
+ unicodeslot=0xFFBE,
+ },
+ [0xFFC2]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER A",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x314F },
+ unicodeslot=0xFFC2,
+ },
+ [0xFFC3]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER AE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3150 },
+ unicodeslot=0xFFC3,
+ },
+ [0xFFC4]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YA",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3151 },
+ unicodeslot=0xFFC4,
+ },
+ [0xFFC5]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YAE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3152 },
+ unicodeslot=0xFFC5,
+ },
+ [0xFFC6]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER EO",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3153 },
+ unicodeslot=0xFFC6,
+ },
+ [0xFFC7]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER E",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3154 },
+ unicodeslot=0xFFC7,
+ },
+ [0xFFCA]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YEO",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3155 },
+ unicodeslot=0xFFCA,
+ },
+ [0xFFCB]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3156 },
+ unicodeslot=0xFFCB,
+ },
+ [0xFFCC]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER O",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3157 },
+ unicodeslot=0xFFCC,
+ },
+ [0xFFCD]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER WA",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3158 },
+ unicodeslot=0xFFCD,
+ },
+ [0xFFCE]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER WAE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3159 },
+ unicodeslot=0xFFCE,
+ },
+ [0xFFCF]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER OE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315A },
+ unicodeslot=0xFFCF,
+ },
+ [0xFFD2]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YO",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315B },
+ unicodeslot=0xFFD2,
+ },
+ [0xFFD3]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER U",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315C },
+ unicodeslot=0xFFD3,
+ },
+ [0xFFD4]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER WEO",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315D },
+ unicodeslot=0xFFD4,
+ },
+ [0xFFD5]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER WE",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315E },
+ unicodeslot=0xFFD5,
+ },
+ [0xFFD6]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER WI",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x315F },
+ unicodeslot=0xFFD6,
+ },
+ [0xFFD7]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YU",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3160 },
+ unicodeslot=0xFFD7,
+ },
+ [0xFFDA]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER EU",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3161 },
+ unicodeslot=0xFFDA,
+ },
+ [0xFFDB]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER YI",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3162 },
+ unicodeslot=0xFFDB,
+ },
+ [0xFFDC]={
+ category="lo",
+ cjkwd="h",
+ description="HALFWIDTH HANGUL LETTER I",
+ direction="l",
+ linebreak="al",
+ specials={ "narrow", 0x3163 },
+ unicodeslot=0xFFDC,
+ },
+ [0xFFE0]={
+ adobename="centmonospace",
+ category="sc",
+ cjkwd="f",
+ description="FULLWIDTH CENT SIGN",
+ direction="et",
+ linebreak="po",
+ specials={ "wide", 0xA2 },
+ unicodeslot=0xFFE0,
+ },
+ [0xFFE1]={
+ adobename="sterlingmonospace",
+ category="sc",
+ cjkwd="f",
+ description="FULLWIDTH POUND SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "wide", 0xA3 },
+ unicodeslot=0xFFE1,
+ },
+ [0xFFE2]={
+ category="sm",
+ cjkwd="f",
+ description="FULLWIDTH NOT SIGN",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0xAC },
+ unicodeslot=0xFFE2,
+ },
+ [0xFFE3]={
+ adobename="macronmonospace",
+ category="sk",
+ cjkwd="f",
+ description="FULLWIDTH MACRON",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0xAF },
+ unicodeslot=0xFFE3,
+ },
+ [0xFFE4]={
+ category="so",
+ cjkwd="f",
+ description="FULLWIDTH BROKEN BAR",
+ direction="on",
+ linebreak="id",
+ specials={ "wide", 0xA6 },
+ unicodeslot=0xFFE4,
+ },
+ [0xFFE5]={
+ adobename="yenmonospace",
+ category="sc",
+ cjkwd="f",
+ description="FULLWIDTH YEN SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "wide", 0xA5 },
+ unicodeslot=0xFFE5,
+ },
+ [0xFFE6]={
+ adobename="wonmonospace",
+ category="sc",
+ cjkwd="f",
+ description="FULLWIDTH WON SIGN",
+ direction="et",
+ linebreak="pr",
+ specials={ "wide", 0x20A9 },
+ unicodeslot=0xFFE6,
+ },
+ [0xFFE8]={
+ category="so",
+ cjkwd="h",
+ description="HALFWIDTH FORMS LIGHT VERTICAL",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x2502 },
+ unicodeslot=0xFFE8,
+ },
+ [0xFFE9]={
+ category="sm",
+ cjkwd="h",
+ description="HALFWIDTH LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x2190 },
+ unicodeslot=0xFFE9,
+ },
+ [0xFFEA]={
+ category="sm",
+ cjkwd="h",
+ description="HALFWIDTH UPWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x2191 },
+ unicodeslot=0xFFEA,
+ },
+ [0xFFEB]={
+ category="sm",
+ cjkwd="h",
+ description="HALFWIDTH RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x2192 },
+ unicodeslot=0xFFEB,
+ },
+ [0xFFEC]={
+ category="sm",
+ cjkwd="h",
+ description="HALFWIDTH DOWNWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x2193 },
+ unicodeslot=0xFFEC,
+ },
+ [0xFFED]={
+ category="so",
+ cjkwd="h",
+ description="HALFWIDTH BLACK SQUARE",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x25A0 },
+ unicodeslot=0xFFED,
+ },
+ [0xFFEE]={
+ category="so",
+ cjkwd="h",
+ description="HALFWIDTH WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ specials={ "narrow", 0x25CB },
+ unicodeslot=0xFFEE,
+ },
+ [0xFFF9]={
+ category="cf",
+ description="INTERLINEAR ANNOTATION ANCHOR",
+ direction="on",
+ linebreak="cm",
+ unicodeslot=0xFFF9,
+ visible="yes",
+ },
+ [0xFFFA]={
+ category="cf",
+ description="INTERLINEAR ANNOTATION SEPARATOR",
+ direction="on",
+ linebreak="cm",
+ unicodeslot=0xFFFA,
+ visible="yes",
+ },
+ [0xFFFB]={
+ category="cf",
+ description="INTERLINEAR ANNOTATION TERMINATOR",
+ direction="on",
+ linebreak="cm",
+ unicodeslot=0xFFFB,
+ visible="yes",
+ },
+ [0xFFFC]={
+ category="so",
+ description="OBJECT REPLACEMENT CHARACTER",
+ direction="on",
+ linebreak="cb",
+ unicodeslot=0xFFFC,
+ },
+ [0xFFFD]={
+ category="so",
+ cjkwd="a",
+ description="REPLACEMENT CHARACTER",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0xFFFD,
+ },
+ [0x10000]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0008 A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10000,
+ },
+ [0x10001]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0026 E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10001,
+ },
+ [0x10002]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001C I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10002,
+ },
+ [0x10003]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x003D O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10003,
+ },
+ [0x10004]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000A U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10004,
+ },
+ [0x10005]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0001 DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10005,
+ },
+ [0x10006]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x002D DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10006,
+ },
+ [0x10007]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0007 DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10007,
+ },
+ [0x10008]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000E DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10008,
+ },
+ [0x10009]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0033 DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10009,
+ },
+ [0x1000A]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0039 JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1000A,
+ },
+ [0x1000B]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x002E JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1000B,
+ },
+ [0x1000D]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0024 JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1000D,
+ },
+ [0x1000E]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0041 JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1000E,
+ },
+ [0x1000F]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x004D KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1000F,
+ },
+ [0x10010]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x002C KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10010,
+ },
+ [0x10011]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0043 KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10011,
+ },
+ [0x10012]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0046 KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10012,
+ },
+ [0x10013]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0051 KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10013,
+ },
+ [0x10014]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0050 MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10014,
+ },
+ [0x10015]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000D ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10015,
+ },
+ [0x10016]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0049 MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10016,
+ },
+ [0x10017]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000F MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10017,
+ },
+ [0x10018]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0017 MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10018,
+ },
+ [0x10019]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0006 NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10019,
+ },
+ [0x1001A]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0018 NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001A,
+ },
+ [0x1001B]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001E NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001B,
+ },
+ [0x1001C]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0034 NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001C,
+ },
+ [0x1001D]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0037 NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001D,
+ },
+ [0x1001E]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0003 PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001E,
+ },
+ [0x1001F]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0048 PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1001F,
+ },
+ [0x10020]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0027 PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10020,
+ },
+ [0x10021]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000B PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10021,
+ },
+ [0x10022]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0032 PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10022,
+ },
+ [0x10023]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0010 QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10023,
+ },
+ [0x10024]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x004E QE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10024,
+ },
+ [0x10025]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0015 QI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10025,
+ },
+ [0x10026]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0020 QO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10026,
+ },
+ [0x10028]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x003C RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10028,
+ },
+ [0x10029]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001B RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10029,
+ },
+ [0x1002A]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0035 RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002A,
+ },
+ [0x1002B]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0002 RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002B,
+ },
+ [0x1002C]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001A RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002C,
+ },
+ [0x1002D]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001F SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002D,
+ },
+ [0x1002E]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0009 SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002E,
+ },
+ [0x1002F]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0029 SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1002F,
+ },
+ [0x10030]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x000C SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10030,
+ },
+ [0x10031]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x003A SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10031,
+ },
+ [0x10032]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x003B TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10032,
+ },
+ [0x10033]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0004 TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10033,
+ },
+ [0x10034]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0025 TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10034,
+ },
+ [0x10035]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0005 TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10035,
+ },
+ [0x10036]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0045 TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10036,
+ },
+ [0x10037]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0036 WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10037,
+ },
+ [0x10038]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x004B WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10038,
+ },
+ [0x10039]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0028 WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10039,
+ },
+ [0x1003A]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x002A WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1003A,
+ },
+ [0x1003C]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0011 ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1003C,
+ },
+ [0x1003D]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x004A ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1003D,
+ },
+ [0x1003F]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0014 ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1003F,
+ },
+ [0x10040]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0019 A0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10040,
+ },
+ [0x10041]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x002B A0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10041,
+ },
+ [0x10042]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0055 AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10042,
+ },
+ [0x10043]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0047 DWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10043,
+ },
+ [0x10044]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x005A DWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10044,
+ },
+ [0x10045]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0030 NWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10045,
+ },
+ [0x10046]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x001D PU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10046,
+ },
+ [0x10047]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x003E PTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10047,
+ },
+ [0x10048]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x004C RA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10048,
+ },
+ [0x10049]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0021 RA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10049,
+ },
+ [0x1004A]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0044 RO0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1004A,
+ },
+ [0x1004B]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0042 TA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1004B,
+ },
+ [0x1004C]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x0057 TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1004C,
+ },
+ [0x1004D]={
+ category="lo",
+ description="LINEAR B SYLLABLE B0x005B TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1004D,
+ },
+ [0x10050]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10050,
+ },
+ [0x10051]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10051,
+ },
+ [0x10052]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10052,
+ },
+ [0x10053]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10053,
+ },
+ [0x10054]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x002F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10054,
+ },
+ [0x10055]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10055,
+ },
+ [0x10056]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10056,
+ },
+ [0x10057]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x003F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10057,
+ },
+ [0x10058]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10058,
+ },
+ [0x10059]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x004F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10059,
+ },
+ [0x1005A]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1005A,
+ },
+ [0x1005B]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1005B,
+ },
+ [0x1005C]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1005C,
+ },
+ [0x1005D]={
+ category="lo",
+ description="LINEAR B SYMBOL B0x0059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1005D,
+ },
+ [0x10080]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0064 MAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10080,
+ },
+ [0x10081]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0066 WOMAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10081,
+ },
+ [0x10082]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0068 DEER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10082,
+ },
+ [0x10083]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0069 EQUID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10083,
+ },
+ [0x10084]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0069F MARE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10084,
+ },
+ [0x10085]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0069M STALLION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10085,
+ },
+ [0x10086]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006AF EWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10086,
+ },
+ [0x10087]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006AM RAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10087,
+ },
+ [0x10088]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006BF SHE-GOAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10088,
+ },
+ [0x10089]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006BM HE-GOAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10089,
+ },
+ [0x1008A]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006CF SOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008A,
+ },
+ [0x1008B]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006CM BOAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008B,
+ },
+ [0x1008C]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006DF COW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008C,
+ },
+ [0x1008D]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x006DM BULL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008D,
+ },
+ [0x1008E]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0078 WHEAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008E,
+ },
+ [0x1008F]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0079 BARLEY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1008F,
+ },
+ [0x10090]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x007A OLIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10090,
+ },
+ [0x10091]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x007B SPICE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10091,
+ },
+ [0x10092]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x007D CYPERUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10092,
+ },
+ [0x10093]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x007F KAPO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10093,
+ },
+ [0x10094]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x0080 KANAKO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10094,
+ },
+ [0x10095]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0082 OIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10095,
+ },
+ [0x10096]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0083 WINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10096,
+ },
+ [0x10097]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0084",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10097,
+ },
+ [0x10098]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x0085 AREPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10098,
+ },
+ [0x10099]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x0087 MERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10099,
+ },
+ [0x1009A]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x008C BRONZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009A,
+ },
+ [0x1009B]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x008D GOLD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009B,
+ },
+ [0x1009C]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x008E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009C,
+ },
+ [0x1009D]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0091 WOOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009D,
+ },
+ [0x1009E]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0092",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009E,
+ },
+ [0x1009F]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0096",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1009F,
+ },
+ [0x100A0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0097 HORN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A0,
+ },
+ [0x100A1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0098",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A1,
+ },
+ [0x100A2]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0099",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A2,
+ },
+ [0x100A3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A3,
+ },
+ [0x100A4]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x009C TURO0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A4,
+ },
+ [0x100A5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x009D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A5,
+ },
+ [0x100A6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x009E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A6,
+ },
+ [0x100A7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x009F CLOTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A7,
+ },
+ [0x100A8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A8,
+ },
+ [0x100A9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100A9,
+ },
+ [0x100AA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A2 GARMENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AA,
+ },
+ [0x100AB]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A3 ARMOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AB,
+ },
+ [0x100AC]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AC,
+ },
+ [0x100AD]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AD,
+ },
+ [0x100AE]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AE,
+ },
+ [0x100AF]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100AF,
+ },
+ [0x100B0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B0,
+ },
+ [0x100B1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00A9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B1,
+ },
+ [0x100B2]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B2,
+ },
+ [0x100B3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00AB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B3,
+ },
+ [0x100B4]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00AC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B4,
+ },
+ [0x100B5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00AD MONTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B5,
+ },
+ [0x100B6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B6,
+ },
+ [0x100B7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B0 TREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B7,
+ },
+ [0x100B8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B8,
+ },
+ [0x100B9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100B9,
+ },
+ [0x100BA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BA,
+ },
+ [0x100BB]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BB,
+ },
+ [0x100BC]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BC,
+ },
+ [0x100BD]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BD,
+ },
+ [0x100BE]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BE,
+ },
+ [0x100BF]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100BF,
+ },
+ [0x100C0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00B9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C0,
+ },
+ [0x100C1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00BD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C1,
+ },
+ [0x100C2]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C2,
+ },
+ [0x100C3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00BF HELMET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C3,
+ },
+ [0x100C4]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00DC FOOTSTOOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C4,
+ },
+ [0x100C5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00E1 BATHTUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C5,
+ },
+ [0x100C6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00E6 SPEAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C6,
+ },
+ [0x100C7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00E7 ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C7,
+ },
+ [0x100C8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00E8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C8,
+ },
+ [0x100C9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00E9 SWORD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100C9,
+ },
+ [0x100CA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00EA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CA,
+ },
+ [0x100CB]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00EC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CB,
+ },
+ [0x100CC]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F0 WHEELED CHARIOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CC,
+ },
+ [0x100CD]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F1 CHARIOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CD,
+ },
+ [0x100CE]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F2 CHARIOT FRAME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CE,
+ },
+ [0x100CF]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F3 WHEEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100CF,
+ },
+ [0x100D0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D0,
+ },
+ [0x100D1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D1,
+ },
+ [0x100D2]={
+ category="lo",
+ description="LINEAR B MONOGRAM B0x00F7 DIPTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D2,
+ },
+ [0x100D3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D3,
+ },
+ [0x100D4]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00F9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D4,
+ },
+ [0x100D5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00FB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D5,
+ },
+ [0x100D6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00FC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D6,
+ },
+ [0x100D7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00FD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D7,
+ },
+ [0x100D8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00FE DART",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D8,
+ },
+ [0x100D9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x00FF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100D9,
+ },
+ [0x100DA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0100",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DA,
+ },
+ [0x100DB]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0101",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DB,
+ },
+ [0x100DC]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0102",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DC,
+ },
+ [0x100DD]={
+ category="lo",
+ description="LINEAR B IDEOGRAM B0x0103",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DD,
+ },
+ [0x100DE]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x009B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DE,
+ },
+ [0x100DF]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00C8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100DF,
+ },
+ [0x100E0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00C9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E0,
+ },
+ [0x100E1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E1,
+ },
+ [0x100E2]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E2,
+ },
+ [0x100E3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E3,
+ },
+ [0x100E4]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E4,
+ },
+ [0x100E5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E5,
+ },
+ [0x100E6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00CF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E6,
+ },
+ [0x100E7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D0",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E7,
+ },
+ [0x100E8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E8,
+ },
+ [0x100E9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100E9,
+ },
+ [0x100EA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100EA,
+ },
+ [0x100EB]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100EB,
+ },
+ [0x100EC]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100EC,
+ },
+ [0x100ED]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100ED,
+ },
+ [0x100EE]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100EE,
+ },
+ [0x100EF]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100EF,
+ },
+ [0x100F0]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00D9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F0,
+ },
+ [0x100F1]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F1,
+ },
+ [0x100F2]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00DB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F2,
+ },
+ [0x100F3]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00DD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F3,
+ },
+ [0x100F4]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F4,
+ },
+ [0x100F5]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00E2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F5,
+ },
+ [0x100F6]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00E3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F6,
+ },
+ [0x100F7]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00E4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F7,
+ },
+ [0x100F8]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00E5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F8,
+ },
+ [0x100F9]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x00FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100F9,
+ },
+ [0x100FA]={
+ category="lo",
+ description="LINEAR B IDEOGRAM VESSEL B0x0131",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x100FA,
+ },
+ [0x10100]={
+ category="po",
+ description="AEGEAN WORD SEPARATOR LINE",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x10100,
+ },
+ [0x10101]={
+ category="po",
+ description="AEGEAN WORD SEPARATOR DOT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10101,
+ },
+ [0x10102]={
+ category="so",
+ description="AEGEAN CHECK MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x10102,
+ },
+ [0x10107]={
+ category="no",
+ description="AEGEAN NUMBER ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10107,
+ },
+ [0x10108]={
+ category="no",
+ description="AEGEAN NUMBER TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10108,
+ },
+ [0x10109]={
+ category="no",
+ description="AEGEAN NUMBER THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10109,
+ },
+ [0x1010A]={
+ category="no",
+ description="AEGEAN NUMBER FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010A,
+ },
+ [0x1010B]={
+ category="no",
+ description="AEGEAN NUMBER FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010B,
+ },
+ [0x1010C]={
+ category="no",
+ description="AEGEAN NUMBER SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010C,
+ },
+ [0x1010D]={
+ category="no",
+ description="AEGEAN NUMBER SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010D,
+ },
+ [0x1010E]={
+ category="no",
+ description="AEGEAN NUMBER EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010E,
+ },
+ [0x1010F]={
+ category="no",
+ description="AEGEAN NUMBER NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1010F,
+ },
+ [0x10110]={
+ category="no",
+ description="AEGEAN NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10110,
+ },
+ [0x10111]={
+ category="no",
+ description="AEGEAN NUMBER TWENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10111,
+ },
+ [0x10112]={
+ category="no",
+ description="AEGEAN NUMBER THIRTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10112,
+ },
+ [0x10113]={
+ category="no",
+ description="AEGEAN NUMBER FORTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10113,
+ },
+ [0x10114]={
+ category="no",
+ description="AEGEAN NUMBER FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10114,
+ },
+ [0x10115]={
+ category="no",
+ description="AEGEAN NUMBER SIXTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10115,
+ },
+ [0x10116]={
+ category="no",
+ description="AEGEAN NUMBER SEVENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10116,
+ },
+ [0x10117]={
+ category="no",
+ description="AEGEAN NUMBER EIGHTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10117,
+ },
+ [0x10118]={
+ category="no",
+ description="AEGEAN NUMBER NINETY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10118,
+ },
+ [0x10119]={
+ category="no",
+ description="AEGEAN NUMBER ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10119,
+ },
+ [0x1011A]={
+ category="no",
+ description="AEGEAN NUMBER TWO HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011A,
+ },
+ [0x1011B]={
+ category="no",
+ description="AEGEAN NUMBER THREE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011B,
+ },
+ [0x1011C]={
+ category="no",
+ description="AEGEAN NUMBER FOUR HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011C,
+ },
+ [0x1011D]={
+ category="no",
+ description="AEGEAN NUMBER FIVE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011D,
+ },
+ [0x1011E]={
+ category="no",
+ description="AEGEAN NUMBER SIX HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011E,
+ },
+ [0x1011F]={
+ category="no",
+ description="AEGEAN NUMBER SEVEN HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1011F,
+ },
+ [0x10120]={
+ category="no",
+ description="AEGEAN NUMBER EIGHT HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10120,
+ },
+ [0x10121]={
+ category="no",
+ description="AEGEAN NUMBER NINE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10121,
+ },
+ [0x10122]={
+ category="no",
+ description="AEGEAN NUMBER ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10122,
+ },
+ [0x10123]={
+ category="no",
+ description="AEGEAN NUMBER TWO THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10123,
+ },
+ [0x10124]={
+ category="no",
+ description="AEGEAN NUMBER THREE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10124,
+ },
+ [0x10125]={
+ category="no",
+ description="AEGEAN NUMBER FOUR THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10125,
+ },
+ [0x10126]={
+ category="no",
+ description="AEGEAN NUMBER FIVE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10126,
+ },
+ [0x10127]={
+ category="no",
+ description="AEGEAN NUMBER SIX THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10127,
+ },
+ [0x10128]={
+ category="no",
+ description="AEGEAN NUMBER SEVEN THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10128,
+ },
+ [0x10129]={
+ category="no",
+ description="AEGEAN NUMBER EIGHT THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10129,
+ },
+ [0x1012A]={
+ category="no",
+ description="AEGEAN NUMBER NINE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012A,
+ },
+ [0x1012B]={
+ category="no",
+ description="AEGEAN NUMBER TEN THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012B,
+ },
+ [0x1012C]={
+ category="no",
+ description="AEGEAN NUMBER TWENTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012C,
+ },
+ [0x1012D]={
+ category="no",
+ description="AEGEAN NUMBER THIRTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012D,
+ },
+ [0x1012E]={
+ category="no",
+ description="AEGEAN NUMBER FORTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012E,
+ },
+ [0x1012F]={
+ category="no",
+ description="AEGEAN NUMBER FIFTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1012F,
+ },
+ [0x10130]={
+ category="no",
+ description="AEGEAN NUMBER SIXTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10130,
+ },
+ [0x10131]={
+ category="no",
+ description="AEGEAN NUMBER SEVENTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10131,
+ },
+ [0x10132]={
+ category="no",
+ description="AEGEAN NUMBER EIGHTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10132,
+ },
+ [0x10133]={
+ category="no",
+ description="AEGEAN NUMBER NINETY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10133,
+ },
+ [0x10137]={
+ category="so",
+ description="AEGEAN WEIGHT BASE UNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10137,
+ },
+ [0x10138]={
+ category="so",
+ description="AEGEAN WEIGHT FIRST SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10138,
+ },
+ [0x10139]={
+ category="so",
+ description="AEGEAN WEIGHT SECOND SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10139,
+ },
+ [0x1013A]={
+ category="so",
+ description="AEGEAN WEIGHT THIRD SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013A,
+ },
+ [0x1013B]={
+ category="so",
+ description="AEGEAN WEIGHT FOURTH SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013B,
+ },
+ [0x1013C]={
+ category="so",
+ description="AEGEAN DRY MEASURE FIRST SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013C,
+ },
+ [0x1013D]={
+ category="so",
+ description="AEGEAN LIQUID MEASURE FIRST SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013D,
+ },
+ [0x1013E]={
+ category="so",
+ description="AEGEAN MEASURE SECOND SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013E,
+ },
+ [0x1013F]={
+ category="so",
+ description="AEGEAN MEASURE THIRD SUBUNIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1013F,
+ },
+ [0x10140]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE QUARTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10140,
+ },
+ [0x10141]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE HALF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10141,
+ },
+ [0x10142]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE DRACHMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10142,
+ },
+ [0x10143]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10143,
+ },
+ [0x10144]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10144,
+ },
+ [0x10145]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10145,
+ },
+ [0x10146]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10146,
+ },
+ [0x10147]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIFTY THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10147,
+ },
+ [0x10148]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10148,
+ },
+ [0x10149]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC TEN TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10149,
+ },
+ [0x1014A]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIFTY TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014A,
+ },
+ [0x1014B]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014B,
+ },
+ [0x1014C]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014C,
+ },
+ [0x1014D]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014D,
+ },
+ [0x1014E]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014E,
+ },
+ [0x1014F]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1014F,
+ },
+ [0x10150]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC TEN STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10150,
+ },
+ [0x10151]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIFTY STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10151,
+ },
+ [0x10152]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10152,
+ },
+ [0x10153]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10153,
+ },
+ [0x10154]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10154,
+ },
+ [0x10155]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10155,
+ },
+ [0x10156]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10156,
+ },
+ [0x10157]={
+ category="nl",
+ description="GREEK ACROPHONIC ATTIC TEN MNAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10157,
+ },
+ [0x10158]={
+ category="nl",
+ description="GREEK ACROPHONIC HERAEUM ONE PLETHRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10158,
+ },
+ [0x10159]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10159,
+ },
+ [0x1015A]={
+ category="nl",
+ description="GREEK ACROPHONIC HERMIONIAN ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015A,
+ },
+ [0x1015B]={
+ category="nl",
+ description="GREEK ACROPHONIC EPIDAUREAN TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015B,
+ },
+ [0x1015C]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015C,
+ },
+ [0x1015D]={
+ category="nl",
+ description="GREEK ACROPHONIC CYRENAIC TWO DRACHMAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015D,
+ },
+ [0x1015E]={
+ category="nl",
+ description="GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015E,
+ },
+ [0x1015F]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN FIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1015F,
+ },
+ [0x10160]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10160,
+ },
+ [0x10161]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10161,
+ },
+ [0x10162]={
+ category="nl",
+ description="GREEK ACROPHONIC HERMIONIAN TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10162,
+ },
+ [0x10163]={
+ category="nl",
+ description="GREEK ACROPHONIC MESSENIAN TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10163,
+ },
+ [0x10164]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10164,
+ },
+ [0x10165]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10165,
+ },
+ [0x10166]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10166,
+ },
+ [0x10167]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10167,
+ },
+ [0x10168]={
+ category="nl",
+ description="GREEK ACROPHONIC HERMIONIAN FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10168,
+ },
+ [0x10169]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10169,
+ },
+ [0x1016A]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN ONE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016A,
+ },
+ [0x1016B]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN THREE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016B,
+ },
+ [0x1016C]={
+ category="nl",
+ description="GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016C,
+ },
+ [0x1016D]={
+ category="nl",
+ description="GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016D,
+ },
+ [0x1016E]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016E,
+ },
+ [0x1016F]={
+ category="nl",
+ description="GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1016F,
+ },
+ [0x10170]={
+ category="nl",
+ description="GREEK ACROPHONIC NAXIAN FIVE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10170,
+ },
+ [0x10171]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN ONE THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10171,
+ },
+ [0x10172]={
+ category="nl",
+ description="GREEK ACROPHONIC THESPIAN FIVE THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10172,
+ },
+ [0x10173]={
+ category="nl",
+ description="GREEK ACROPHONIC DELPHIC FIVE MNAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10173,
+ },
+ [0x10174]={
+ category="nl",
+ description="GREEK ACROPHONIC STRATIAN FIFTY MNAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10174,
+ },
+ [0x10175]={
+ category="no",
+ description="GREEK ONE HALF SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10175,
+ },
+ [0x10176]={
+ category="no",
+ description="GREEK ONE HALF SIGN ALTERNATE FORM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10176,
+ },
+ [0x10177]={
+ category="no",
+ description="GREEK TWO THIRDS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10177,
+ },
+ [0x10178]={
+ category="no",
+ description="GREEK THREE QUARTERS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10178,
+ },
+ [0x10179]={
+ category="so",
+ description="GREEK YEAR SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10179,
+ },
+ [0x1017A]={
+ category="so",
+ description="GREEK TALENT SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017A,
+ },
+ [0x1017B]={
+ category="so",
+ description="GREEK DRACHMA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017B,
+ },
+ [0x1017C]={
+ category="so",
+ description="GREEK OBOL SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017C,
+ },
+ [0x1017D]={
+ category="so",
+ description="GREEK TWO OBOLS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017D,
+ },
+ [0x1017E]={
+ category="so",
+ description="GREEK THREE OBOLS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017E,
+ },
+ [0x1017F]={
+ category="so",
+ description="GREEK FOUR OBOLS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1017F,
+ },
+ [0x10180]={
+ category="so",
+ description="GREEK FIVE OBOLS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10180,
+ },
+ [0x10181]={
+ category="so",
+ description="GREEK METRETES SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10181,
+ },
+ [0x10182]={
+ category="so",
+ description="GREEK KYATHOS BASE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10182,
+ },
+ [0x10183]={
+ category="so",
+ description="GREEK LITRA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10183,
+ },
+ [0x10184]={
+ category="so",
+ description="GREEK OUNKIA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10184,
+ },
+ [0x10185]={
+ category="so",
+ description="GREEK XESTES SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10185,
+ },
+ [0x10186]={
+ category="so",
+ description="GREEK ARTABE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10186,
+ },
+ [0x10187]={
+ category="so",
+ description="GREEK AROURA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10187,
+ },
+ [0x10188]={
+ category="so",
+ description="GREEK GRAMMA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10188,
+ },
+ [0x10189]={
+ category="so",
+ description="GREEK TRYBLION BASE SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10189,
+ },
+ [0x1018A]={
+ category="no",
+ description="GREEK ZERO SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1018A,
+ },
+ [0x1018B]={
+ category="no",
+ description="GREEK ONE QUARTER SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1018B,
+ },
+ [0x1018C]={
+ category="so",
+ description="GREEK SINUSOID SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1018C,
+ },
+ [0x10190]={
+ category="so",
+ description="ROMAN SEXTANS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10190,
+ },
+ [0x10191]={
+ category="so",
+ description="ROMAN UNCIA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10191,
+ },
+ [0x10192]={
+ category="so",
+ description="ROMAN SEMUNCIA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10192,
+ },
+ [0x10193]={
+ category="so",
+ description="ROMAN SEXTULA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10193,
+ },
+ [0x10194]={
+ category="so",
+ description="ROMAN DIMIDIA SEXTULA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10194,
+ },
+ [0x10195]={
+ category="so",
+ description="ROMAN SILIQUA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10195,
+ },
+ [0x10196]={
+ category="so",
+ description="ROMAN DENARIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10196,
+ },
+ [0x10197]={
+ category="so",
+ description="ROMAN QUINARIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10197,
+ },
+ [0x10198]={
+ category="so",
+ description="ROMAN SESTERTIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10198,
+ },
+ [0x10199]={
+ category="so",
+ description="ROMAN DUPONDIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10199,
+ },
+ [0x1019A]={
+ category="so",
+ description="ROMAN AS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1019A,
+ },
+ [0x1019B]={
+ category="so",
+ description="ROMAN CENTURIAL SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1019B,
+ },
+ [0x101A0]={
+ category="so",
+ description="GREEK SYMBOL TAU RHO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x101A0,
+ },
+ [0x101D0]={
+ category="so",
+ description="PHAISTOS DISC SIGN PEDESTRIAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D0,
+ },
+ [0x101D1]={
+ category="so",
+ description="PHAISTOS DISC SIGN PLUMED HEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D1,
+ },
+ [0x101D2]={
+ category="so",
+ description="PHAISTOS DISC SIGN TATTOOED HEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D2,
+ },
+ [0x101D3]={
+ category="so",
+ description="PHAISTOS DISC SIGN CAPTIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D3,
+ },
+ [0x101D4]={
+ category="so",
+ description="PHAISTOS DISC SIGN CHILD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D4,
+ },
+ [0x101D5]={
+ category="so",
+ description="PHAISTOS DISC SIGN WOMAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D5,
+ },
+ [0x101D6]={
+ category="so",
+ description="PHAISTOS DISC SIGN HELMET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D6,
+ },
+ [0x101D7]={
+ category="so",
+ description="PHAISTOS DISC SIGN GAUNTLET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D7,
+ },
+ [0x101D8]={
+ category="so",
+ description="PHAISTOS DISC SIGN TIARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D8,
+ },
+ [0x101D9]={
+ category="so",
+ description="PHAISTOS DISC SIGN ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D9,
+ },
+ [0x101DA]={
+ category="so",
+ description="PHAISTOS DISC SIGN BOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DA,
+ },
+ [0x101DB]={
+ category="so",
+ description="PHAISTOS DISC SIGN SHIELD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DB,
+ },
+ [0x101DC]={
+ category="so",
+ description="PHAISTOS DISC SIGN CLUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DC,
+ },
+ [0x101DD]={
+ category="so",
+ description="PHAISTOS DISC SIGN MANACLES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DD,
+ },
+ [0x101DE]={
+ category="so",
+ description="PHAISTOS DISC SIGN MATTOCK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DE,
+ },
+ [0x101DF]={
+ category="so",
+ description="PHAISTOS DISC SIGN SAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DF,
+ },
+ [0x101E0]={
+ category="so",
+ description="PHAISTOS DISC SIGN LID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E0,
+ },
+ [0x101E1]={
+ category="so",
+ description="PHAISTOS DISC SIGN BOOMERANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E1,
+ },
+ [0x101E2]={
+ category="so",
+ description="PHAISTOS DISC SIGN CARPENTRY PLANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E2,
+ },
+ [0x101E3]={
+ category="so",
+ description="PHAISTOS DISC SIGN DOLIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E3,
+ },
+ [0x101E4]={
+ category="so",
+ description="PHAISTOS DISC SIGN COMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E4,
+ },
+ [0x101E5]={
+ category="so",
+ description="PHAISTOS DISC SIGN SLING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E5,
+ },
+ [0x101E6]={
+ category="so",
+ description="PHAISTOS DISC SIGN COLUMN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E6,
+ },
+ [0x101E7]={
+ category="so",
+ description="PHAISTOS DISC SIGN BEEHIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E7,
+ },
+ [0x101E8]={
+ category="so",
+ description="PHAISTOS DISC SIGN SHIP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E8,
+ },
+ [0x101E9]={
+ category="so",
+ description="PHAISTOS DISC SIGN HORN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E9,
+ },
+ [0x101EA]={
+ category="so",
+ description="PHAISTOS DISC SIGN HIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EA,
+ },
+ [0x101EB]={
+ category="so",
+ description="PHAISTOS DISC SIGN BULLS LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EB,
+ },
+ [0x101EC]={
+ category="so",
+ description="PHAISTOS DISC SIGN CAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EC,
+ },
+ [0x101ED]={
+ category="so",
+ description="PHAISTOS DISC SIGN RAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101ED,
+ },
+ [0x101EE]={
+ category="so",
+ description="PHAISTOS DISC SIGN EAGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EE,
+ },
+ [0x101EF]={
+ category="so",
+ description="PHAISTOS DISC SIGN DOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EF,
+ },
+ [0x101F0]={
+ category="so",
+ description="PHAISTOS DISC SIGN TUNNY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F0,
+ },
+ [0x101F1]={
+ category="so",
+ description="PHAISTOS DISC SIGN BEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F1,
+ },
+ [0x101F2]={
+ category="so",
+ description="PHAISTOS DISC SIGN PLANE TREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F2,
+ },
+ [0x101F3]={
+ category="so",
+ description="PHAISTOS DISC SIGN VINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F3,
+ },
+ [0x101F4]={
+ category="so",
+ description="PHAISTOS DISC SIGN PAPYRUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F4,
+ },
+ [0x101F5]={
+ category="so",
+ description="PHAISTOS DISC SIGN ROSETTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F5,
+ },
+ [0x101F6]={
+ category="so",
+ description="PHAISTOS DISC SIGN LILY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F6,
+ },
+ [0x101F7]={
+ category="so",
+ description="PHAISTOS DISC SIGN OX BACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F7,
+ },
+ [0x101F8]={
+ category="so",
+ description="PHAISTOS DISC SIGN FLUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F8,
+ },
+ [0x101F9]={
+ category="so",
+ description="PHAISTOS DISC SIGN GRATER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F9,
+ },
+ [0x101FA]={
+ category="so",
+ description="PHAISTOS DISC SIGN STRAINER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FA,
+ },
+ [0x101FB]={
+ category="so",
+ description="PHAISTOS DISC SIGN SMALL AXE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FB,
+ },
+ [0x101FC]={
+ category="so",
+ description="PHAISTOS DISC SIGN WAVY BAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FC,
+ },
+ [0x101FD]={
+ category="mn",
+ combining=0xDC,
+ description="PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x101FD,
+ },
+ [0x10280]={
+ category="lo",
+ description="LYCIAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10280,
+ },
+ [0x10281]={
+ category="lo",
+ description="LYCIAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10281,
+ },
+ [0x10282]={
+ category="lo",
+ description="LYCIAN LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10282,
+ },
+ [0x10283]={
+ category="lo",
+ description="LYCIAN LETTER BH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10283,
+ },
+ [0x10284]={
+ category="lo",
+ description="LYCIAN LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10284,
+ },
+ [0x10285]={
+ category="lo",
+ description="LYCIAN LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10285,
+ },
+ [0x10286]={
+ category="lo",
+ description="LYCIAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10286,
+ },
+ [0x10287]={
+ category="lo",
+ description="LYCIAN LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10287,
+ },
+ [0x10288]={
+ category="lo",
+ description="LYCIAN LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10288,
+ },
+ [0x10289]={
+ category="lo",
+ description="LYCIAN LETTER TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10289,
+ },
+ [0x1028A]={
+ category="lo",
+ description="LYCIAN LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028A,
+ },
+ [0x1028B]={
+ category="lo",
+ description="LYCIAN LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028B,
+ },
+ [0x1028C]={
+ category="lo",
+ description="LYCIAN LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028C,
+ },
+ [0x1028D]={
+ category="lo",
+ description="LYCIAN LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028D,
+ },
+ [0x1028E]={
+ category="lo",
+ description="LYCIAN LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028E,
+ },
+ [0x1028F]={
+ category="lo",
+ description="LYCIAN LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028F,
+ },
+ [0x10290]={
+ category="lo",
+ description="LYCIAN LETTER MM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10290,
+ },
+ [0x10291]={
+ category="lo",
+ description="LYCIAN LETTER NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10291,
+ },
+ [0x10292]={
+ category="lo",
+ description="LYCIAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10292,
+ },
+ [0x10293]={
+ category="lo",
+ description="LYCIAN LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10293,
+ },
+ [0x10294]={
+ category="lo",
+ description="LYCIAN LETTER KK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10294,
+ },
+ [0x10295]={
+ category="lo",
+ description="LYCIAN LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10295,
+ },
+ [0x10296]={
+ category="lo",
+ description="LYCIAN LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10296,
+ },
+ [0x10297]={
+ category="lo",
+ description="LYCIAN LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10297,
+ },
+ [0x10298]={
+ category="lo",
+ description="LYCIAN LETTER TT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10298,
+ },
+ [0x10299]={
+ category="lo",
+ description="LYCIAN LETTER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10299,
+ },
+ [0x1029A]={
+ category="lo",
+ description="LYCIAN LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029A,
+ },
+ [0x1029B]={
+ category="lo",
+ description="LYCIAN LETTER H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029B,
+ },
+ [0x1029C]={
+ category="lo",
+ description="LYCIAN LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029C,
+ },
+ [0x102A0]={
+ category="lo",
+ description="CARIAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A0,
+ },
+ [0x102A1]={
+ category="lo",
+ description="CARIAN LETTER P2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A1,
+ },
+ [0x102A2]={
+ category="lo",
+ description="CARIAN LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A2,
+ },
+ [0x102A3]={
+ category="lo",
+ description="CARIAN LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A3,
+ },
+ [0x102A4]={
+ category="lo",
+ description="CARIAN LETTER UUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A4,
+ },
+ [0x102A5]={
+ category="lo",
+ description="CARIAN LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A5,
+ },
+ [0x102A6]={
+ category="lo",
+ description="CARIAN LETTER LD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A6,
+ },
+ [0x102A7]={
+ category="lo",
+ description="CARIAN LETTER A2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A7,
+ },
+ [0x102A8]={
+ category="lo",
+ description="CARIAN LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A8,
+ },
+ [0x102A9]={
+ category="lo",
+ description="CARIAN LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A9,
+ },
+ [0x102AA]={
+ category="lo",
+ description="CARIAN LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AA,
+ },
+ [0x102AB]={
+ category="lo",
+ description="CARIAN LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AB,
+ },
+ [0x102AC]={
+ category="lo",
+ description="CARIAN LETTER D2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AC,
+ },
+ [0x102AD]={
+ category="lo",
+ description="CARIAN LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AD,
+ },
+ [0x102AE]={
+ category="lo",
+ description="CARIAN LETTER SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AE,
+ },
+ [0x102AF]={
+ category="lo",
+ description="CARIAN LETTER SH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AF,
+ },
+ [0x102B0]={
+ category="lo",
+ description="CARIAN LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B0,
+ },
+ [0x102B1]={
+ category="lo",
+ description="CARIAN LETTER C-18",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B1,
+ },
+ [0x102B2]={
+ category="lo",
+ description="CARIAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B2,
+ },
+ [0x102B3]={
+ category="lo",
+ description="CARIAN LETTER NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B3,
+ },
+ [0x102B4]={
+ category="lo",
+ description="CARIAN LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B4,
+ },
+ [0x102B5]={
+ category="lo",
+ description="CARIAN LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B5,
+ },
+ [0x102B6]={
+ category="lo",
+ description="CARIAN LETTER TT2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B6,
+ },
+ [0x102B7]={
+ category="lo",
+ description="CARIAN LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B7,
+ },
+ [0x102B8]={
+ category="lo",
+ description="CARIAN LETTER SS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B8,
+ },
+ [0x102B9]={
+ category="lo",
+ description="CARIAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B9,
+ },
+ [0x102BA]={
+ category="lo",
+ description="CARIAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BA,
+ },
+ [0x102BB]={
+ category="lo",
+ description="CARIAN LETTER UUUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BB,
+ },
+ [0x102BC]={
+ category="lo",
+ description="CARIAN LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BC,
+ },
+ [0x102BD]={
+ category="lo",
+ description="CARIAN LETTER K2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BD,
+ },
+ [0x102BE]={
+ category="lo",
+ description="CARIAN LETTER ND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BE,
+ },
+ [0x102BF]={
+ category="lo",
+ description="CARIAN LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BF,
+ },
+ [0x102C0]={
+ category="lo",
+ description="CARIAN LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C0,
+ },
+ [0x102C1]={
+ category="lo",
+ description="CARIAN LETTER G2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C1,
+ },
+ [0x102C2]={
+ category="lo",
+ description="CARIAN LETTER ST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C2,
+ },
+ [0x102C3]={
+ category="lo",
+ description="CARIAN LETTER ST2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C3,
+ },
+ [0x102C4]={
+ category="lo",
+ description="CARIAN LETTER NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C4,
+ },
+ [0x102C5]={
+ category="lo",
+ description="CARIAN LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C5,
+ },
+ [0x102C6]={
+ category="lo",
+ description="CARIAN LETTER C-39",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C6,
+ },
+ [0x102C7]={
+ category="lo",
+ description="CARIAN LETTER TT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C7,
+ },
+ [0x102C8]={
+ category="lo",
+ description="CARIAN LETTER UUU2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C8,
+ },
+ [0x102C9]={
+ category="lo",
+ description="CARIAN LETTER RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C9,
+ },
+ [0x102CA]={
+ category="lo",
+ description="CARIAN LETTER MB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CA,
+ },
+ [0x102CB]={
+ category="lo",
+ description="CARIAN LETTER MB2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CB,
+ },
+ [0x102CC]={
+ category="lo",
+ description="CARIAN LETTER MB3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CC,
+ },
+ [0x102CD]={
+ category="lo",
+ description="CARIAN LETTER MB4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CD,
+ },
+ [0x102CE]={
+ category="lo",
+ description="CARIAN LETTER LD2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CE,
+ },
+ [0x102CF]={
+ category="lo",
+ description="CARIAN LETTER E2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CF,
+ },
+ [0x102D0]={
+ category="lo",
+ description="CARIAN LETTER UUU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102D0,
+ },
+ [0x102E0]={
+ category="mn",
+ combining=0xDC,
+ description="COPTIC EPACT THOUSANDS MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x102E0,
+ },
+ [0x102E1]={
+ category="no",
+ description="COPTIC EPACT DIGIT ONE",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E1,
+ },
+ [0x102E2]={
+ category="no",
+ description="COPTIC EPACT DIGIT TWO",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E2,
+ },
+ [0x102E3]={
+ category="no",
+ description="COPTIC EPACT DIGIT THREE",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E3,
+ },
+ [0x102E4]={
+ category="no",
+ description="COPTIC EPACT DIGIT FOUR",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E4,
+ },
+ [0x102E5]={
+ category="no",
+ description="COPTIC EPACT DIGIT FIVE",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E5,
+ },
+ [0x102E6]={
+ category="no",
+ description="COPTIC EPACT DIGIT SIX",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E6,
+ },
+ [0x102E7]={
+ category="no",
+ description="COPTIC EPACT DIGIT SEVEN",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E7,
+ },
+ [0x102E8]={
+ category="no",
+ description="COPTIC EPACT DIGIT EIGHT",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E8,
+ },
+ [0x102E9]={
+ category="no",
+ description="COPTIC EPACT DIGIT NINE",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102E9,
+ },
+ [0x102EA]={
+ category="no",
+ description="COPTIC EPACT NUMBER TEN",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102EA,
+ },
+ [0x102EB]={
+ category="no",
+ description="COPTIC EPACT NUMBER TWENTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102EB,
+ },
+ [0x102EC]={
+ category="no",
+ description="COPTIC EPACT NUMBER THIRTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102EC,
+ },
+ [0x102ED]={
+ category="no",
+ description="COPTIC EPACT NUMBER FORTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102ED,
+ },
+ [0x102EE]={
+ category="no",
+ description="COPTIC EPACT NUMBER FIFTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102EE,
+ },
+ [0x102EF]={
+ category="no",
+ description="COPTIC EPACT NUMBER SIXTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102EF,
+ },
+ [0x102F0]={
+ category="no",
+ description="COPTIC EPACT NUMBER SEVENTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F0,
+ },
+ [0x102F1]={
+ category="no",
+ description="COPTIC EPACT NUMBER EIGHTY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F1,
+ },
+ [0x102F2]={
+ category="no",
+ description="COPTIC EPACT NUMBER NINETY",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F2,
+ },
+ [0x102F3]={
+ category="no",
+ description="COPTIC EPACT NUMBER ONE HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F3,
+ },
+ [0x102F4]={
+ category="no",
+ description="COPTIC EPACT NUMBER TWO HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F4,
+ },
+ [0x102F5]={
+ category="no",
+ description="COPTIC EPACT NUMBER THREE HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F5,
+ },
+ [0x102F6]={
+ category="no",
+ description="COPTIC EPACT NUMBER FOUR HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F6,
+ },
+ [0x102F7]={
+ category="no",
+ description="COPTIC EPACT NUMBER FIVE HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F7,
+ },
+ [0x102F8]={
+ category="no",
+ description="COPTIC EPACT NUMBER SIX HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F8,
+ },
+ [0x102F9]={
+ category="no",
+ description="COPTIC EPACT NUMBER SEVEN HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102F9,
+ },
+ [0x102FA]={
+ category="no",
+ description="COPTIC EPACT NUMBER EIGHT HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102FA,
+ },
+ [0x102FB]={
+ category="no",
+ description="COPTIC EPACT NUMBER NINE HUNDRED",
+ direction="en",
+ linebreak="al",
+ unicodeslot=0x102FB,
+ },
+ [0x10300]={
+ category="lo",
+ description="OLD ITALIC LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10300,
+ },
+ [0x10301]={
+ category="lo",
+ description="OLD ITALIC LETTER BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10301,
+ },
+ [0x10302]={
+ category="lo",
+ description="OLD ITALIC LETTER KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10302,
+ },
+ [0x10303]={
+ category="lo",
+ description="OLD ITALIC LETTER DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10303,
+ },
+ [0x10304]={
+ category="lo",
+ description="OLD ITALIC LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10304,
+ },
+ [0x10305]={
+ category="lo",
+ description="OLD ITALIC LETTER VE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10305,
+ },
+ [0x10306]={
+ category="lo",
+ description="OLD ITALIC LETTER ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10306,
+ },
+ [0x10307]={
+ category="lo",
+ description="OLD ITALIC LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10307,
+ },
+ [0x10308]={
+ category="lo",
+ description="OLD ITALIC LETTER THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10308,
+ },
+ [0x10309]={
+ category="lo",
+ description="OLD ITALIC LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10309,
+ },
+ [0x1030A]={
+ category="lo",
+ description="OLD ITALIC LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030A,
+ },
+ [0x1030B]={
+ category="lo",
+ description="OLD ITALIC LETTER EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030B,
+ },
+ [0x1030C]={
+ category="lo",
+ description="OLD ITALIC LETTER EM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030C,
+ },
+ [0x1030D]={
+ category="lo",
+ description="OLD ITALIC LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030D,
+ },
+ [0x1030E]={
+ category="lo",
+ description="OLD ITALIC LETTER ESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030E,
+ },
+ [0x1030F]={
+ category="lo",
+ description="OLD ITALIC LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1030F,
+ },
+ [0x10310]={
+ category="lo",
+ description="OLD ITALIC LETTER PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10310,
+ },
+ [0x10311]={
+ category="lo",
+ description="OLD ITALIC LETTER SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10311,
+ },
+ [0x10312]={
+ category="lo",
+ description="OLD ITALIC LETTER KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10312,
+ },
+ [0x10313]={
+ category="lo",
+ description="OLD ITALIC LETTER ER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10313,
+ },
+ [0x10314]={
+ category="lo",
+ description="OLD ITALIC LETTER ES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10314,
+ },
+ [0x10315]={
+ category="lo",
+ description="OLD ITALIC LETTER TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10315,
+ },
+ [0x10316]={
+ category="lo",
+ description="OLD ITALIC LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10316,
+ },
+ [0x10317]={
+ category="lo",
+ description="OLD ITALIC LETTER EKS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10317,
+ },
+ [0x10318]={
+ category="lo",
+ description="OLD ITALIC LETTER PHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10318,
+ },
+ [0x10319]={
+ category="lo",
+ description="OLD ITALIC LETTER KHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10319,
+ },
+ [0x1031A]={
+ category="lo",
+ description="OLD ITALIC LETTER EF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031A,
+ },
+ [0x1031B]={
+ category="lo",
+ description="OLD ITALIC LETTER ERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031B,
+ },
+ [0x1031C]={
+ category="lo",
+ description="OLD ITALIC LETTER CHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031C,
+ },
+ [0x1031D]={
+ category="lo",
+ description="OLD ITALIC LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031D,
+ },
+ [0x1031E]={
+ category="lo",
+ description="OLD ITALIC LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031E,
+ },
+ [0x1031F]={
+ category="lo",
+ description="OLD ITALIC LETTER ESS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1031F,
+ },
+ [0x10320]={
+ category="no",
+ description="OLD ITALIC NUMERAL ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10320,
+ },
+ [0x10321]={
+ category="no",
+ description="OLD ITALIC NUMERAL FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10321,
+ },
+ [0x10322]={
+ category="no",
+ description="OLD ITALIC NUMERAL TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10322,
+ },
+ [0x10323]={
+ category="no",
+ description="OLD ITALIC NUMERAL FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10323,
+ },
+ [0x10330]={
+ category="lo",
+ description="GOTHIC LETTER AHSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10330,
+ },
+ [0x10331]={
+ category="lo",
+ description="GOTHIC LETTER BAIRKAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10331,
+ },
+ [0x10332]={
+ category="lo",
+ description="GOTHIC LETTER GIBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10332,
+ },
+ [0x10333]={
+ category="lo",
+ description="GOTHIC LETTER DAGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10333,
+ },
+ [0x10334]={
+ category="lo",
+ description="GOTHIC LETTER AIHVUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10334,
+ },
+ [0x10335]={
+ category="lo",
+ description="GOTHIC LETTER QAIRTHRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10335,
+ },
+ [0x10336]={
+ category="lo",
+ description="GOTHIC LETTER IUJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10336,
+ },
+ [0x10337]={
+ category="lo",
+ description="GOTHIC LETTER HAGL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10337,
+ },
+ [0x10338]={
+ category="lo",
+ description="GOTHIC LETTER THIUTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10338,
+ },
+ [0x10339]={
+ category="lo",
+ description="GOTHIC LETTER EIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10339,
+ },
+ [0x1033A]={
+ category="lo",
+ description="GOTHIC LETTER KUSMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033A,
+ },
+ [0x1033B]={
+ category="lo",
+ description="GOTHIC LETTER LAGUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033B,
+ },
+ [0x1033C]={
+ category="lo",
+ description="GOTHIC LETTER MANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033C,
+ },
+ [0x1033D]={
+ category="lo",
+ description="GOTHIC LETTER NAUTHS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033D,
+ },
+ [0x1033E]={
+ category="lo",
+ description="GOTHIC LETTER JER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033E,
+ },
+ [0x1033F]={
+ category="lo",
+ description="GOTHIC LETTER URUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1033F,
+ },
+ [0x10340]={
+ category="lo",
+ description="GOTHIC LETTER PAIRTHRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10340,
+ },
+ [0x10341]={
+ category="nl",
+ description="GOTHIC LETTER NINETY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10341,
+ },
+ [0x10342]={
+ category="lo",
+ description="GOTHIC LETTER RAIDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10342,
+ },
+ [0x10343]={
+ category="lo",
+ description="GOTHIC LETTER SAUIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10343,
+ },
+ [0x10344]={
+ category="lo",
+ description="GOTHIC LETTER TEIWS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10344,
+ },
+ [0x10345]={
+ category="lo",
+ description="GOTHIC LETTER WINJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10345,
+ },
+ [0x10346]={
+ category="lo",
+ description="GOTHIC LETTER FAIHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10346,
+ },
+ [0x10347]={
+ category="lo",
+ description="GOTHIC LETTER IGGWS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10347,
+ },
+ [0x10348]={
+ category="lo",
+ description="GOTHIC LETTER HWAIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10348,
+ },
+ [0x10349]={
+ category="lo",
+ description="GOTHIC LETTER OTHAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10349,
+ },
+ [0x1034A]={
+ category="nl",
+ description="GOTHIC LETTER NINE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1034A,
+ },
+ [0x10350]={
+ category="lo",
+ description="OLD PERMIC LETTER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10350,
+ },
+ [0x10351]={
+ category="lo",
+ description="OLD PERMIC LETTER BUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10351,
+ },
+ [0x10352]={
+ category="lo",
+ description="OLD PERMIC LETTER GAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10352,
+ },
+ [0x10353]={
+ category="lo",
+ description="OLD PERMIC LETTER DOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10353,
+ },
+ [0x10354]={
+ category="lo",
+ description="OLD PERMIC LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10354,
+ },
+ [0x10355]={
+ category="lo",
+ description="OLD PERMIC LETTER ZHOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10355,
+ },
+ [0x10356]={
+ category="lo",
+ description="OLD PERMIC LETTER DZHOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10356,
+ },
+ [0x10357]={
+ category="lo",
+ description="OLD PERMIC LETTER ZATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10357,
+ },
+ [0x10358]={
+ category="lo",
+ description="OLD PERMIC LETTER DZITA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10358,
+ },
+ [0x10359]={
+ category="lo",
+ description="OLD PERMIC LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10359,
+ },
+ [0x1035A]={
+ category="lo",
+ description="OLD PERMIC LETTER KOKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035A,
+ },
+ [0x1035B]={
+ category="lo",
+ description="OLD PERMIC LETTER LEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035B,
+ },
+ [0x1035C]={
+ category="lo",
+ description="OLD PERMIC LETTER MENOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035C,
+ },
+ [0x1035D]={
+ category="lo",
+ description="OLD PERMIC LETTER NENOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035D,
+ },
+ [0x1035E]={
+ category="lo",
+ description="OLD PERMIC LETTER VOOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035E,
+ },
+ [0x1035F]={
+ category="lo",
+ description="OLD PERMIC LETTER PEEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1035F,
+ },
+ [0x10360]={
+ category="lo",
+ description="OLD PERMIC LETTER REI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10360,
+ },
+ [0x10361]={
+ category="lo",
+ description="OLD PERMIC LETTER SII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10361,
+ },
+ [0x10362]={
+ category="lo",
+ description="OLD PERMIC LETTER TAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10362,
+ },
+ [0x10363]={
+ category="lo",
+ description="OLD PERMIC LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10363,
+ },
+ [0x10364]={
+ category="lo",
+ description="OLD PERMIC LETTER CHERY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10364,
+ },
+ [0x10365]={
+ category="lo",
+ description="OLD PERMIC LETTER SHOOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10365,
+ },
+ [0x10366]={
+ category="lo",
+ description="OLD PERMIC LETTER SHCHOOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10366,
+ },
+ [0x10367]={
+ category="lo",
+ description="OLD PERMIC LETTER YRY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10367,
+ },
+ [0x10368]={
+ category="lo",
+ description="OLD PERMIC LETTER YERU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10368,
+ },
+ [0x10369]={
+ category="lo",
+ description="OLD PERMIC LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10369,
+ },
+ [0x1036A]={
+ category="lo",
+ description="OLD PERMIC LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036A,
+ },
+ [0x1036B]={
+ category="lo",
+ description="OLD PERMIC LETTER EF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036B,
+ },
+ [0x1036C]={
+ category="lo",
+ description="OLD PERMIC LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036C,
+ },
+ [0x1036D]={
+ category="lo",
+ description="OLD PERMIC LETTER TSIU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036D,
+ },
+ [0x1036E]={
+ category="lo",
+ description="OLD PERMIC LETTER VER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036E,
+ },
+ [0x1036F]={
+ category="lo",
+ description="OLD PERMIC LETTER YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1036F,
+ },
+ [0x10370]={
+ category="lo",
+ description="OLD PERMIC LETTER YERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10370,
+ },
+ [0x10371]={
+ category="lo",
+ description="OLD PERMIC LETTER YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10371,
+ },
+ [0x10372]={
+ category="lo",
+ description="OLD PERMIC LETTER IE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10372,
+ },
+ [0x10373]={
+ category="lo",
+ description="OLD PERMIC LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10373,
+ },
+ [0x10374]={
+ category="lo",
+ description="OLD PERMIC LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10374,
+ },
+ [0x10375]={
+ category="lo",
+ description="OLD PERMIC LETTER IA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10375,
+ },
+ [0x10376]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING OLD PERMIC LETTER AN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10376,
+ },
+ [0x10377]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING OLD PERMIC LETTER DOI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10377,
+ },
+ [0x10378]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING OLD PERMIC LETTER ZATA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10378,
+ },
+ [0x10379]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING OLD PERMIC LETTER NENOE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10379,
+ },
+ [0x1037A]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING OLD PERMIC LETTER SII",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1037A,
+ },
+ [0x10380]={
+ category="lo",
+ description="UGARITIC LETTER ALPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10380,
+ },
+ [0x10381]={
+ category="lo",
+ description="UGARITIC LETTER BETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10381,
+ },
+ [0x10382]={
+ category="lo",
+ description="UGARITIC LETTER GAMLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10382,
+ },
+ [0x10383]={
+ category="lo",
+ description="UGARITIC LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10383,
+ },
+ [0x10384]={
+ category="lo",
+ description="UGARITIC LETTER DELTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10384,
+ },
+ [0x10385]={
+ category="lo",
+ description="UGARITIC LETTER HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10385,
+ },
+ [0x10386]={
+ category="lo",
+ description="UGARITIC LETTER WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10386,
+ },
+ [0x10387]={
+ category="lo",
+ description="UGARITIC LETTER ZETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10387,
+ },
+ [0x10388]={
+ category="lo",
+ description="UGARITIC LETTER HOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10388,
+ },
+ [0x10389]={
+ category="lo",
+ description="UGARITIC LETTER TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10389,
+ },
+ [0x1038A]={
+ category="lo",
+ description="UGARITIC LETTER YOD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038A,
+ },
+ [0x1038B]={
+ category="lo",
+ description="UGARITIC LETTER KAF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038B,
+ },
+ [0x1038C]={
+ category="lo",
+ description="UGARITIC LETTER SHIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038C,
+ },
+ [0x1038D]={
+ category="lo",
+ description="UGARITIC LETTER LAMDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038D,
+ },
+ [0x1038E]={
+ category="lo",
+ description="UGARITIC LETTER MEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038E,
+ },
+ [0x1038F]={
+ category="lo",
+ description="UGARITIC LETTER DHAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1038F,
+ },
+ [0x10390]={
+ category="lo",
+ description="UGARITIC LETTER NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10390,
+ },
+ [0x10391]={
+ category="lo",
+ description="UGARITIC LETTER ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10391,
+ },
+ [0x10392]={
+ category="lo",
+ description="UGARITIC LETTER SAMKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10392,
+ },
+ [0x10393]={
+ category="lo",
+ description="UGARITIC LETTER AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10393,
+ },
+ [0x10394]={
+ category="lo",
+ description="UGARITIC LETTER PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10394,
+ },
+ [0x10395]={
+ category="lo",
+ description="UGARITIC LETTER SADE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10395,
+ },
+ [0x10396]={
+ category="lo",
+ description="UGARITIC LETTER QOPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10396,
+ },
+ [0x10397]={
+ category="lo",
+ description="UGARITIC LETTER RASHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10397,
+ },
+ [0x10398]={
+ category="lo",
+ description="UGARITIC LETTER THANNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10398,
+ },
+ [0x10399]={
+ category="lo",
+ description="UGARITIC LETTER GHAIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10399,
+ },
+ [0x1039A]={
+ category="lo",
+ description="UGARITIC LETTER TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1039A,
+ },
+ [0x1039B]={
+ category="lo",
+ description="UGARITIC LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1039B,
+ },
+ [0x1039C]={
+ category="lo",
+ description="UGARITIC LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1039C,
+ },
+ [0x1039D]={
+ category="lo",
+ description="UGARITIC LETTER SSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1039D,
+ },
+ [0x1039F]={
+ category="po",
+ description="UGARITIC WORD DIVIDER",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1039F,
+ },
+ [0x103A0]={
+ category="lo",
+ description="OLD PERSIAN SIGN A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A0,
+ },
+ [0x103A1]={
+ category="lo",
+ description="OLD PERSIAN SIGN I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A1,
+ },
+ [0x103A2]={
+ category="lo",
+ description="OLD PERSIAN SIGN U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A2,
+ },
+ [0x103A3]={
+ category="lo",
+ description="OLD PERSIAN SIGN KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A3,
+ },
+ [0x103A4]={
+ category="lo",
+ description="OLD PERSIAN SIGN KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A4,
+ },
+ [0x103A5]={
+ category="lo",
+ description="OLD PERSIAN SIGN GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A5,
+ },
+ [0x103A6]={
+ category="lo",
+ description="OLD PERSIAN SIGN GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A6,
+ },
+ [0x103A7]={
+ category="lo",
+ description="OLD PERSIAN SIGN XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A7,
+ },
+ [0x103A8]={
+ category="lo",
+ description="OLD PERSIAN SIGN CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A8,
+ },
+ [0x103A9]={
+ category="lo",
+ description="OLD PERSIAN SIGN JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103A9,
+ },
+ [0x103AA]={
+ category="lo",
+ description="OLD PERSIAN SIGN JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AA,
+ },
+ [0x103AB]={
+ category="lo",
+ description="OLD PERSIAN SIGN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AB,
+ },
+ [0x103AC]={
+ category="lo",
+ description="OLD PERSIAN SIGN TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AC,
+ },
+ [0x103AD]={
+ category="lo",
+ description="OLD PERSIAN SIGN DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AD,
+ },
+ [0x103AE]={
+ category="lo",
+ description="OLD PERSIAN SIGN DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AE,
+ },
+ [0x103AF]={
+ category="lo",
+ description="OLD PERSIAN SIGN DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103AF,
+ },
+ [0x103B0]={
+ category="lo",
+ description="OLD PERSIAN SIGN THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B0,
+ },
+ [0x103B1]={
+ category="lo",
+ description="OLD PERSIAN SIGN PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B1,
+ },
+ [0x103B2]={
+ category="lo",
+ description="OLD PERSIAN SIGN BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B2,
+ },
+ [0x103B3]={
+ category="lo",
+ description="OLD PERSIAN SIGN FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B3,
+ },
+ [0x103B4]={
+ category="lo",
+ description="OLD PERSIAN SIGN NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B4,
+ },
+ [0x103B5]={
+ category="lo",
+ description="OLD PERSIAN SIGN NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B5,
+ },
+ [0x103B6]={
+ category="lo",
+ description="OLD PERSIAN SIGN MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B6,
+ },
+ [0x103B7]={
+ category="lo",
+ description="OLD PERSIAN SIGN MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B7,
+ },
+ [0x103B8]={
+ category="lo",
+ description="OLD PERSIAN SIGN MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B8,
+ },
+ [0x103B9]={
+ category="lo",
+ description="OLD PERSIAN SIGN YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103B9,
+ },
+ [0x103BA]={
+ category="lo",
+ description="OLD PERSIAN SIGN VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BA,
+ },
+ [0x103BB]={
+ category="lo",
+ description="OLD PERSIAN SIGN VI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BB,
+ },
+ [0x103BC]={
+ category="lo",
+ description="OLD PERSIAN SIGN RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BC,
+ },
+ [0x103BD]={
+ category="lo",
+ description="OLD PERSIAN SIGN RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BD,
+ },
+ [0x103BE]={
+ category="lo",
+ description="OLD PERSIAN SIGN LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BE,
+ },
+ [0x103BF]={
+ category="lo",
+ description="OLD PERSIAN SIGN SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103BF,
+ },
+ [0x103C0]={
+ category="lo",
+ description="OLD PERSIAN SIGN ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C0,
+ },
+ [0x103C1]={
+ category="lo",
+ description="OLD PERSIAN SIGN SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C1,
+ },
+ [0x103C2]={
+ category="lo",
+ description="OLD PERSIAN SIGN SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C2,
+ },
+ [0x103C3]={
+ category="lo",
+ description="OLD PERSIAN SIGN HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C3,
+ },
+ [0x103C8]={
+ category="lo",
+ description="OLD PERSIAN SIGN AURAMAZDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C8,
+ },
+ [0x103C9]={
+ category="lo",
+ description="OLD PERSIAN SIGN AURAMAZDAA-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103C9,
+ },
+ [0x103CA]={
+ category="lo",
+ description="OLD PERSIAN SIGN AURAMAZDAAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CA,
+ },
+ [0x103CB]={
+ category="lo",
+ description="OLD PERSIAN SIGN XSHAAYATHIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CB,
+ },
+ [0x103CC]={
+ category="lo",
+ description="OLD PERSIAN SIGN DAHYAAUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CC,
+ },
+ [0x103CD]={
+ category="lo",
+ description="OLD PERSIAN SIGN DAHYAAUSH-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CD,
+ },
+ [0x103CE]={
+ category="lo",
+ description="OLD PERSIAN SIGN BAGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CE,
+ },
+ [0x103CF]={
+ category="lo",
+ description="OLD PERSIAN SIGN BUUMISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103CF,
+ },
+ [0x103D0]={
+ category="po",
+ description="OLD PERSIAN WORD DIVIDER",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x103D0,
+ },
+ [0x103D1]={
+ category="nl",
+ description="OLD PERSIAN NUMBER ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103D1,
+ },
+ [0x103D2]={
+ category="nl",
+ description="OLD PERSIAN NUMBER TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103D2,
+ },
+ [0x103D3]={
+ category="nl",
+ description="OLD PERSIAN NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103D3,
+ },
+ [0x103D4]={
+ category="nl",
+ description="OLD PERSIAN NUMBER TWENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103D4,
+ },
+ [0x103D5]={
+ category="nl",
+ description="OLD PERSIAN NUMBER HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x103D5,
+ },
+ [0x10400]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG I",
+ direction="l",
+ lccode=0x10428,
+ linebreak="al",
+ unicodeslot=0x10400,
+ },
+ [0x10401]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG E",
+ direction="l",
+ lccode=0x10429,
+ linebreak="al",
+ unicodeslot=0x10401,
+ },
+ [0x10402]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG A",
+ direction="l",
+ lccode=0x1042A,
+ linebreak="al",
+ unicodeslot=0x10402,
+ },
+ [0x10403]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG AH",
+ direction="l",
+ lccode=0x1042B,
+ linebreak="al",
+ unicodeslot=0x10403,
+ },
+ [0x10404]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG O",
+ direction="l",
+ lccode=0x1042C,
+ linebreak="al",
+ unicodeslot=0x10404,
+ },
+ [0x10405]={
+ category="lu",
+ description="DESERET CAPITAL LETTER LONG OO",
+ direction="l",
+ lccode=0x1042D,
+ linebreak="al",
+ unicodeslot=0x10405,
+ },
+ [0x10406]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT I",
+ direction="l",
+ lccode=0x1042E,
+ linebreak="al",
+ unicodeslot=0x10406,
+ },
+ [0x10407]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT E",
+ direction="l",
+ lccode=0x1042F,
+ linebreak="al",
+ unicodeslot=0x10407,
+ },
+ [0x10408]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT A",
+ direction="l",
+ lccode=0x10430,
+ linebreak="al",
+ unicodeslot=0x10408,
+ },
+ [0x10409]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT AH",
+ direction="l",
+ lccode=0x10431,
+ linebreak="al",
+ unicodeslot=0x10409,
+ },
+ [0x1040A]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT O",
+ direction="l",
+ lccode=0x10432,
+ linebreak="al",
+ unicodeslot=0x1040A,
+ },
+ [0x1040B]={
+ category="lu",
+ description="DESERET CAPITAL LETTER SHORT OO",
+ direction="l",
+ lccode=0x10433,
+ linebreak="al",
+ unicodeslot=0x1040B,
+ },
+ [0x1040C]={
+ category="lu",
+ description="DESERET CAPITAL LETTER AY",
+ direction="l",
+ lccode=0x10434,
+ linebreak="al",
+ unicodeslot=0x1040C,
+ },
+ [0x1040D]={
+ category="lu",
+ description="DESERET CAPITAL LETTER OW",
+ direction="l",
+ lccode=0x10435,
+ linebreak="al",
+ unicodeslot=0x1040D,
+ },
+ [0x1040E]={
+ category="lu",
+ description="DESERET CAPITAL LETTER WU",
+ direction="l",
+ lccode=0x10436,
+ linebreak="al",
+ unicodeslot=0x1040E,
+ },
+ [0x1040F]={
+ category="lu",
+ description="DESERET CAPITAL LETTER YEE",
+ direction="l",
+ lccode=0x10437,
+ linebreak="al",
+ unicodeslot=0x1040F,
+ },
+ [0x10410]={
+ category="lu",
+ description="DESERET CAPITAL LETTER H",
+ direction="l",
+ lccode=0x10438,
+ linebreak="al",
+ unicodeslot=0x10410,
+ },
+ [0x10411]={
+ category="lu",
+ description="DESERET CAPITAL LETTER PEE",
+ direction="l",
+ lccode=0x10439,
+ linebreak="al",
+ unicodeslot=0x10411,
+ },
+ [0x10412]={
+ category="lu",
+ description="DESERET CAPITAL LETTER BEE",
+ direction="l",
+ lccode=0x1043A,
+ linebreak="al",
+ unicodeslot=0x10412,
+ },
+ [0x10413]={
+ category="lu",
+ description="DESERET CAPITAL LETTER TEE",
+ direction="l",
+ lccode=0x1043B,
+ linebreak="al",
+ unicodeslot=0x10413,
+ },
+ [0x10414]={
+ category="lu",
+ description="DESERET CAPITAL LETTER DEE",
+ direction="l",
+ lccode=0x1043C,
+ linebreak="al",
+ unicodeslot=0x10414,
+ },
+ [0x10415]={
+ category="lu",
+ description="DESERET CAPITAL LETTER CHEE",
+ direction="l",
+ lccode=0x1043D,
+ linebreak="al",
+ unicodeslot=0x10415,
+ },
+ [0x10416]={
+ category="lu",
+ description="DESERET CAPITAL LETTER JEE",
+ direction="l",
+ lccode=0x1043E,
+ linebreak="al",
+ unicodeslot=0x10416,
+ },
+ [0x10417]={
+ category="lu",
+ description="DESERET CAPITAL LETTER KAY",
+ direction="l",
+ lccode=0x1043F,
+ linebreak="al",
+ unicodeslot=0x10417,
+ },
+ [0x10418]={
+ category="lu",
+ description="DESERET CAPITAL LETTER GAY",
+ direction="l",
+ lccode=0x10440,
+ linebreak="al",
+ unicodeslot=0x10418,
+ },
+ [0x10419]={
+ category="lu",
+ description="DESERET CAPITAL LETTER EF",
+ direction="l",
+ lccode=0x10441,
+ linebreak="al",
+ unicodeslot=0x10419,
+ },
+ [0x1041A]={
+ category="lu",
+ description="DESERET CAPITAL LETTER VEE",
+ direction="l",
+ lccode=0x10442,
+ linebreak="al",
+ unicodeslot=0x1041A,
+ },
+ [0x1041B]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ETH",
+ direction="l",
+ lccode=0x10443,
+ linebreak="al",
+ unicodeslot=0x1041B,
+ },
+ [0x1041C]={
+ category="lu",
+ description="DESERET CAPITAL LETTER THEE",
+ direction="l",
+ lccode=0x10444,
+ linebreak="al",
+ unicodeslot=0x1041C,
+ },
+ [0x1041D]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ES",
+ direction="l",
+ lccode=0x10445,
+ linebreak="al",
+ unicodeslot=0x1041D,
+ },
+ [0x1041E]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ZEE",
+ direction="l",
+ lccode=0x10446,
+ linebreak="al",
+ unicodeslot=0x1041E,
+ },
+ [0x1041F]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ESH",
+ direction="l",
+ lccode=0x10447,
+ linebreak="al",
+ unicodeslot=0x1041F,
+ },
+ [0x10420]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ZHEE",
+ direction="l",
+ lccode=0x10448,
+ linebreak="al",
+ unicodeslot=0x10420,
+ },
+ [0x10421]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ER",
+ direction="l",
+ lccode=0x10449,
+ linebreak="al",
+ unicodeslot=0x10421,
+ },
+ [0x10422]={
+ category="lu",
+ description="DESERET CAPITAL LETTER EL",
+ direction="l",
+ lccode=0x1044A,
+ linebreak="al",
+ unicodeslot=0x10422,
+ },
+ [0x10423]={
+ category="lu",
+ description="DESERET CAPITAL LETTER EM",
+ direction="l",
+ lccode=0x1044B,
+ linebreak="al",
+ unicodeslot=0x10423,
+ },
+ [0x10424]={
+ category="lu",
+ description="DESERET CAPITAL LETTER EN",
+ direction="l",
+ lccode=0x1044C,
+ linebreak="al",
+ unicodeslot=0x10424,
+ },
+ [0x10425]={
+ category="lu",
+ description="DESERET CAPITAL LETTER ENG",
+ direction="l",
+ lccode=0x1044D,
+ linebreak="al",
+ unicodeslot=0x10425,
+ },
+ [0x10426]={
+ category="lu",
+ description="DESERET CAPITAL LETTER OI",
+ direction="l",
+ lccode=0x1044E,
+ linebreak="al",
+ unicodeslot=0x10426,
+ },
+ [0x10427]={
+ category="lu",
+ description="DESERET CAPITAL LETTER EW",
+ direction="l",
+ lccode=0x1044F,
+ linebreak="al",
+ unicodeslot=0x10427,
+ },
+ [0x10428]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG I",
+ direction="l",
+ linebreak="al",
+ uccode=0x10400,
+ unicodeslot=0x10428,
+ },
+ [0x10429]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG E",
+ direction="l",
+ linebreak="al",
+ uccode=0x10401,
+ unicodeslot=0x10429,
+ },
+ [0x1042A]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG A",
+ direction="l",
+ linebreak="al",
+ uccode=0x10402,
+ unicodeslot=0x1042A,
+ },
+ [0x1042B]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG AH",
+ direction="l",
+ linebreak="al",
+ uccode=0x10403,
+ unicodeslot=0x1042B,
+ },
+ [0x1042C]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG O",
+ direction="l",
+ linebreak="al",
+ uccode=0x10404,
+ unicodeslot=0x1042C,
+ },
+ [0x1042D]={
+ category="ll",
+ description="DESERET SMALL LETTER LONG OO",
+ direction="l",
+ linebreak="al",
+ uccode=0x10405,
+ unicodeslot=0x1042D,
+ },
+ [0x1042E]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT I",
+ direction="l",
+ linebreak="al",
+ uccode=0x10406,
+ unicodeslot=0x1042E,
+ },
+ [0x1042F]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT E",
+ direction="l",
+ linebreak="al",
+ uccode=0x10407,
+ unicodeslot=0x1042F,
+ },
+ [0x10430]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT A",
+ direction="l",
+ linebreak="al",
+ uccode=0x10408,
+ unicodeslot=0x10430,
+ },
+ [0x10431]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT AH",
+ direction="l",
+ linebreak="al",
+ uccode=0x10409,
+ unicodeslot=0x10431,
+ },
+ [0x10432]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT O",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040A,
+ unicodeslot=0x10432,
+ },
+ [0x10433]={
+ category="ll",
+ description="DESERET SMALL LETTER SHORT OO",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040B,
+ unicodeslot=0x10433,
+ },
+ [0x10434]={
+ category="ll",
+ description="DESERET SMALL LETTER AY",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040C,
+ unicodeslot=0x10434,
+ },
+ [0x10435]={
+ category="ll",
+ description="DESERET SMALL LETTER OW",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040D,
+ unicodeslot=0x10435,
+ },
+ [0x10436]={
+ category="ll",
+ description="DESERET SMALL LETTER WU",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040E,
+ unicodeslot=0x10436,
+ },
+ [0x10437]={
+ category="ll",
+ description="DESERET SMALL LETTER YEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x1040F,
+ unicodeslot=0x10437,
+ },
+ [0x10438]={
+ category="ll",
+ description="DESERET SMALL LETTER H",
+ direction="l",
+ linebreak="al",
+ uccode=0x10410,
+ unicodeslot=0x10438,
+ },
+ [0x10439]={
+ category="ll",
+ description="DESERET SMALL LETTER PEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10411,
+ unicodeslot=0x10439,
+ },
+ [0x1043A]={
+ category="ll",
+ description="DESERET SMALL LETTER BEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10412,
+ unicodeslot=0x1043A,
+ },
+ [0x1043B]={
+ category="ll",
+ description="DESERET SMALL LETTER TEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10413,
+ unicodeslot=0x1043B,
+ },
+ [0x1043C]={
+ category="ll",
+ description="DESERET SMALL LETTER DEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10414,
+ unicodeslot=0x1043C,
+ },
+ [0x1043D]={
+ category="ll",
+ description="DESERET SMALL LETTER CHEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10415,
+ unicodeslot=0x1043D,
+ },
+ [0x1043E]={
+ category="ll",
+ description="DESERET SMALL LETTER JEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10416,
+ unicodeslot=0x1043E,
+ },
+ [0x1043F]={
+ category="ll",
+ description="DESERET SMALL LETTER KAY",
+ direction="l",
+ linebreak="al",
+ uccode=0x10417,
+ unicodeslot=0x1043F,
+ },
+ [0x10440]={
+ category="ll",
+ description="DESERET SMALL LETTER GAY",
+ direction="l",
+ linebreak="al",
+ uccode=0x10418,
+ unicodeslot=0x10440,
+ },
+ [0x10441]={
+ category="ll",
+ description="DESERET SMALL LETTER EF",
+ direction="l",
+ linebreak="al",
+ uccode=0x10419,
+ unicodeslot=0x10441,
+ },
+ [0x10442]={
+ category="ll",
+ description="DESERET SMALL LETTER VEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041A,
+ unicodeslot=0x10442,
+ },
+ [0x10443]={
+ category="ll",
+ description="DESERET SMALL LETTER ETH",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041B,
+ unicodeslot=0x10443,
+ },
+ [0x10444]={
+ category="ll",
+ description="DESERET SMALL LETTER THEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041C,
+ unicodeslot=0x10444,
+ },
+ [0x10445]={
+ category="ll",
+ description="DESERET SMALL LETTER ES",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041D,
+ unicodeslot=0x10445,
+ },
+ [0x10446]={
+ category="ll",
+ description="DESERET SMALL LETTER ZEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041E,
+ unicodeslot=0x10446,
+ },
+ [0x10447]={
+ category="ll",
+ description="DESERET SMALL LETTER ESH",
+ direction="l",
+ linebreak="al",
+ uccode=0x1041F,
+ unicodeslot=0x10447,
+ },
+ [0x10448]={
+ category="ll",
+ description="DESERET SMALL LETTER ZHEE",
+ direction="l",
+ linebreak="al",
+ uccode=0x10420,
+ unicodeslot=0x10448,
+ },
+ [0x10449]={
+ category="ll",
+ description="DESERET SMALL LETTER ER",
+ direction="l",
+ linebreak="al",
+ uccode=0x10421,
+ unicodeslot=0x10449,
+ },
+ [0x1044A]={
+ category="ll",
+ description="DESERET SMALL LETTER EL",
+ direction="l",
+ linebreak="al",
+ uccode=0x10422,
+ unicodeslot=0x1044A,
+ },
+ [0x1044B]={
+ category="ll",
+ description="DESERET SMALL LETTER EM",
+ direction="l",
+ linebreak="al",
+ uccode=0x10423,
+ unicodeslot=0x1044B,
+ },
+ [0x1044C]={
+ category="ll",
+ description="DESERET SMALL LETTER EN",
+ direction="l",
+ linebreak="al",
+ uccode=0x10424,
+ unicodeslot=0x1044C,
+ },
+ [0x1044D]={
+ category="ll",
+ description="DESERET SMALL LETTER ENG",
+ direction="l",
+ linebreak="al",
+ uccode=0x10425,
+ unicodeslot=0x1044D,
+ },
+ [0x1044E]={
+ category="ll",
+ description="DESERET SMALL LETTER OI",
+ direction="l",
+ linebreak="al",
+ uccode=0x10426,
+ unicodeslot=0x1044E,
+ },
+ [0x1044F]={
+ category="ll",
+ description="DESERET SMALL LETTER EW",
+ direction="l",
+ linebreak="al",
+ uccode=0x10427,
+ unicodeslot=0x1044F,
+ },
+ [0x10450]={
+ category="lo",
+ description="SHAVIAN LETTER PEEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10450,
+ },
+ [0x10451]={
+ category="lo",
+ description="SHAVIAN LETTER TOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10451,
+ },
+ [0x10452]={
+ category="lo",
+ description="SHAVIAN LETTER KICK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10452,
+ },
+ [0x10453]={
+ category="lo",
+ description="SHAVIAN LETTER FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10453,
+ },
+ [0x10454]={
+ category="lo",
+ description="SHAVIAN LETTER THIGH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10454,
+ },
+ [0x10455]={
+ category="lo",
+ description="SHAVIAN LETTER SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10455,
+ },
+ [0x10456]={
+ category="lo",
+ description="SHAVIAN LETTER SURE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10456,
+ },
+ [0x10457]={
+ category="lo",
+ description="SHAVIAN LETTER CHURCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10457,
+ },
+ [0x10458]={
+ category="lo",
+ description="SHAVIAN LETTER YEA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10458,
+ },
+ [0x10459]={
+ category="lo",
+ description="SHAVIAN LETTER HUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10459,
+ },
+ [0x1045A]={
+ category="lo",
+ description="SHAVIAN LETTER BIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045A,
+ },
+ [0x1045B]={
+ category="lo",
+ description="SHAVIAN LETTER DEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045B,
+ },
+ [0x1045C]={
+ category="lo",
+ description="SHAVIAN LETTER GAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045C,
+ },
+ [0x1045D]={
+ category="lo",
+ description="SHAVIAN LETTER VOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045D,
+ },
+ [0x1045E]={
+ category="lo",
+ description="SHAVIAN LETTER THEY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045E,
+ },
+ [0x1045F]={
+ category="lo",
+ description="SHAVIAN LETTER ZOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1045F,
+ },
+ [0x10460]={
+ category="lo",
+ description="SHAVIAN LETTER MEASURE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10460,
+ },
+ [0x10461]={
+ category="lo",
+ description="SHAVIAN LETTER JUDGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10461,
+ },
+ [0x10462]={
+ category="lo",
+ description="SHAVIAN LETTER WOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10462,
+ },
+ [0x10463]={
+ category="lo",
+ description="SHAVIAN LETTER HA-HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10463,
+ },
+ [0x10464]={
+ category="lo",
+ description="SHAVIAN LETTER LOLL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10464,
+ },
+ [0x10465]={
+ category="lo",
+ description="SHAVIAN LETTER MIME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10465,
+ },
+ [0x10466]={
+ category="lo",
+ description="SHAVIAN LETTER IF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10466,
+ },
+ [0x10467]={
+ category="lo",
+ description="SHAVIAN LETTER EGG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10467,
+ },
+ [0x10468]={
+ category="lo",
+ description="SHAVIAN LETTER ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10468,
+ },
+ [0x10469]={
+ category="lo",
+ description="SHAVIAN LETTER ADO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10469,
+ },
+ [0x1046A]={
+ category="lo",
+ description="SHAVIAN LETTER ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046A,
+ },
+ [0x1046B]={
+ category="lo",
+ description="SHAVIAN LETTER WOOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046B,
+ },
+ [0x1046C]={
+ category="lo",
+ description="SHAVIAN LETTER OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046C,
+ },
+ [0x1046D]={
+ category="lo",
+ description="SHAVIAN LETTER AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046D,
+ },
+ [0x1046E]={
+ category="lo",
+ description="SHAVIAN LETTER ROAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046E,
+ },
+ [0x1046F]={
+ category="lo",
+ description="SHAVIAN LETTER NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1046F,
+ },
+ [0x10470]={
+ category="lo",
+ description="SHAVIAN LETTER EAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10470,
+ },
+ [0x10471]={
+ category="lo",
+ description="SHAVIAN LETTER AGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10471,
+ },
+ [0x10472]={
+ category="lo",
+ description="SHAVIAN LETTER ICE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10472,
+ },
+ [0x10473]={
+ category="lo",
+ description="SHAVIAN LETTER UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10473,
+ },
+ [0x10474]={
+ category="lo",
+ description="SHAVIAN LETTER OAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10474,
+ },
+ [0x10475]={
+ category="lo",
+ description="SHAVIAN LETTER OOZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10475,
+ },
+ [0x10476]={
+ category="lo",
+ description="SHAVIAN LETTER OIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10476,
+ },
+ [0x10477]={
+ category="lo",
+ description="SHAVIAN LETTER AWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10477,
+ },
+ [0x10478]={
+ category="lo",
+ description="SHAVIAN LETTER ARE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10478,
+ },
+ [0x10479]={
+ category="lo",
+ description="SHAVIAN LETTER OR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10479,
+ },
+ [0x1047A]={
+ category="lo",
+ description="SHAVIAN LETTER AIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047A,
+ },
+ [0x1047B]={
+ category="lo",
+ description="SHAVIAN LETTER ERR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047B,
+ },
+ [0x1047C]={
+ category="lo",
+ description="SHAVIAN LETTER ARRAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047C,
+ },
+ [0x1047D]={
+ category="lo",
+ description="SHAVIAN LETTER EAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047D,
+ },
+ [0x1047E]={
+ category="lo",
+ description="SHAVIAN LETTER IAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047E,
+ },
+ [0x1047F]={
+ category="lo",
+ description="SHAVIAN LETTER YEW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1047F,
+ },
+ [0x10480]={
+ category="lo",
+ description="OSMANYA LETTER ALEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10480,
+ },
+ [0x10481]={
+ category="lo",
+ description="OSMANYA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10481,
+ },
+ [0x10482]={
+ category="lo",
+ description="OSMANYA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10482,
+ },
+ [0x10483]={
+ category="lo",
+ description="OSMANYA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10483,
+ },
+ [0x10484]={
+ category="lo",
+ description="OSMANYA LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10484,
+ },
+ [0x10485]={
+ category="lo",
+ description="OSMANYA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10485,
+ },
+ [0x10486]={
+ category="lo",
+ description="OSMANYA LETTER DEEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10486,
+ },
+ [0x10487]={
+ category="lo",
+ description="OSMANYA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10487,
+ },
+ [0x10488]={
+ category="lo",
+ description="OSMANYA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10488,
+ },
+ [0x10489]={
+ category="lo",
+ description="OSMANYA LETTER SHIIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10489,
+ },
+ [0x1048A]={
+ category="lo",
+ description="OSMANYA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048A,
+ },
+ [0x1048B]={
+ category="lo",
+ description="OSMANYA LETTER CAYN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048B,
+ },
+ [0x1048C]={
+ category="lo",
+ description="OSMANYA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048C,
+ },
+ [0x1048D]={
+ category="lo",
+ description="OSMANYA LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048D,
+ },
+ [0x1048E]={
+ category="lo",
+ description="OSMANYA LETTER QAAF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048E,
+ },
+ [0x1048F]={
+ category="lo",
+ description="OSMANYA LETTER KAAF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1048F,
+ },
+ [0x10490]={
+ category="lo",
+ description="OSMANYA LETTER LAAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10490,
+ },
+ [0x10491]={
+ category="lo",
+ description="OSMANYA LETTER MIIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10491,
+ },
+ [0x10492]={
+ category="lo",
+ description="OSMANYA LETTER NUUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10492,
+ },
+ [0x10493]={
+ category="lo",
+ description="OSMANYA LETTER WAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10493,
+ },
+ [0x10494]={
+ category="lo",
+ description="OSMANYA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10494,
+ },
+ [0x10495]={
+ category="lo",
+ description="OSMANYA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10495,
+ },
+ [0x10496]={
+ category="lo",
+ description="OSMANYA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10496,
+ },
+ [0x10497]={
+ category="lo",
+ description="OSMANYA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10497,
+ },
+ [0x10498]={
+ category="lo",
+ description="OSMANYA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10498,
+ },
+ [0x10499]={
+ category="lo",
+ description="OSMANYA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10499,
+ },
+ [0x1049A]={
+ category="lo",
+ description="OSMANYA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1049A,
+ },
+ [0x1049B]={
+ category="lo",
+ description="OSMANYA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1049B,
+ },
+ [0x1049C]={
+ category="lo",
+ description="OSMANYA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1049C,
+ },
+ [0x1049D]={
+ category="lo",
+ description="OSMANYA LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1049D,
+ },
+ [0x104A0]={
+ category="nd",
+ description="OSMANYA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A0,
+ },
+ [0x104A1]={
+ category="nd",
+ description="OSMANYA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A1,
+ },
+ [0x104A2]={
+ category="nd",
+ description="OSMANYA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A2,
+ },
+ [0x104A3]={
+ category="nd",
+ description="OSMANYA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A3,
+ },
+ [0x104A4]={
+ category="nd",
+ description="OSMANYA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A4,
+ },
+ [0x104A5]={
+ category="nd",
+ description="OSMANYA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A5,
+ },
+ [0x104A6]={
+ category="nd",
+ description="OSMANYA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A6,
+ },
+ [0x104A7]={
+ category="nd",
+ description="OSMANYA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A7,
+ },
+ [0x104A8]={
+ category="nd",
+ description="OSMANYA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A8,
+ },
+ [0x104A9]={
+ category="nd",
+ description="OSMANYA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x104A9,
+ },
+ [0x10500]={
+ category="lo",
+ description="ELBASAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10500,
+ },
+ [0x10501]={
+ category="lo",
+ description="ELBASAN LETTER BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10501,
+ },
+ [0x10502]={
+ category="lo",
+ description="ELBASAN LETTER CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10502,
+ },
+ [0x10503]={
+ category="lo",
+ description="ELBASAN LETTER CHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10503,
+ },
+ [0x10504]={
+ category="lo",
+ description="ELBASAN LETTER DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10504,
+ },
+ [0x10505]={
+ category="lo",
+ description="ELBASAN LETTER NDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10505,
+ },
+ [0x10506]={
+ category="lo",
+ description="ELBASAN LETTER DHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10506,
+ },
+ [0x10507]={
+ category="lo",
+ description="ELBASAN LETTER EI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10507,
+ },
+ [0x10508]={
+ category="lo",
+ description="ELBASAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10508,
+ },
+ [0x10509]={
+ category="lo",
+ description="ELBASAN LETTER FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10509,
+ },
+ [0x1050A]={
+ category="lo",
+ description="ELBASAN LETTER GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050A,
+ },
+ [0x1050B]={
+ category="lo",
+ description="ELBASAN LETTER GJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050B,
+ },
+ [0x1050C]={
+ category="lo",
+ description="ELBASAN LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050C,
+ },
+ [0x1050D]={
+ category="lo",
+ description="ELBASAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050D,
+ },
+ [0x1050E]={
+ category="lo",
+ description="ELBASAN LETTER JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050E,
+ },
+ [0x1050F]={
+ category="lo",
+ description="ELBASAN LETTER KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1050F,
+ },
+ [0x10510]={
+ category="lo",
+ description="ELBASAN LETTER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10510,
+ },
+ [0x10511]={
+ category="lo",
+ description="ELBASAN LETTER LLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10511,
+ },
+ [0x10512]={
+ category="lo",
+ description="ELBASAN LETTER ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10512,
+ },
+ [0x10513]={
+ category="lo",
+ description="ELBASAN LETTER NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10513,
+ },
+ [0x10514]={
+ category="lo",
+ description="ELBASAN LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10514,
+ },
+ [0x10515]={
+ category="lo",
+ description="ELBASAN LETTER NJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10515,
+ },
+ [0x10516]={
+ category="lo",
+ description="ELBASAN LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10516,
+ },
+ [0x10517]={
+ category="lo",
+ description="ELBASAN LETTER PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10517,
+ },
+ [0x10518]={
+ category="lo",
+ description="ELBASAN LETTER QE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10518,
+ },
+ [0x10519]={
+ category="lo",
+ description="ELBASAN LETTER RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10519,
+ },
+ [0x1051A]={
+ category="lo",
+ description="ELBASAN LETTER RRE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051A,
+ },
+ [0x1051B]={
+ category="lo",
+ description="ELBASAN LETTER SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051B,
+ },
+ [0x1051C]={
+ category="lo",
+ description="ELBASAN LETTER SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051C,
+ },
+ [0x1051D]={
+ category="lo",
+ description="ELBASAN LETTER TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051D,
+ },
+ [0x1051E]={
+ category="lo",
+ description="ELBASAN LETTER THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051E,
+ },
+ [0x1051F]={
+ category="lo",
+ description="ELBASAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1051F,
+ },
+ [0x10520]={
+ category="lo",
+ description="ELBASAN LETTER VE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10520,
+ },
+ [0x10521]={
+ category="lo",
+ description="ELBASAN LETTER XE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10521,
+ },
+ [0x10522]={
+ category="lo",
+ description="ELBASAN LETTER Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10522,
+ },
+ [0x10523]={
+ category="lo",
+ description="ELBASAN LETTER ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10523,
+ },
+ [0x10524]={
+ category="lo",
+ description="ELBASAN LETTER ZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10524,
+ },
+ [0x10525]={
+ category="lo",
+ description="ELBASAN LETTER GHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10525,
+ },
+ [0x10526]={
+ category="lo",
+ description="ELBASAN LETTER GHAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10526,
+ },
+ [0x10527]={
+ category="lo",
+ description="ELBASAN LETTER KHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10527,
+ },
+ [0x10530]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER ALT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10530,
+ },
+ [0x10531]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER BET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10531,
+ },
+ [0x10532]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER GIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10532,
+ },
+ [0x10533]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER DAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10533,
+ },
+ [0x10534]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER EB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10534,
+ },
+ [0x10535]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER ZARL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10535,
+ },
+ [0x10536]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER EYN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10536,
+ },
+ [0x10537]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER ZHIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10537,
+ },
+ [0x10538]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER TAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10538,
+ },
+ [0x10539]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10539,
+ },
+ [0x1053A]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER YOWD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053A,
+ },
+ [0x1053B]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053B,
+ },
+ [0x1053C]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER IRB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053C,
+ },
+ [0x1053D]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053D,
+ },
+ [0x1053E]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER LAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053E,
+ },
+ [0x1053F]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER INYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1053F,
+ },
+ [0x10540]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER XEYN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10540,
+ },
+ [0x10541]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER DYAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10541,
+ },
+ [0x10542]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10542,
+ },
+ [0x10543]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER JHOX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10543,
+ },
+ [0x10544]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER KAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10544,
+ },
+ [0x10545]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER LYIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10545,
+ },
+ [0x10546]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER HEYT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10546,
+ },
+ [0x10547]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER QAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10547,
+ },
+ [0x10548]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER AOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10548,
+ },
+ [0x10549]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CHOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10549,
+ },
+ [0x1054A]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054A,
+ },
+ [0x1054B]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CYAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054B,
+ },
+ [0x1054C]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER MAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054C,
+ },
+ [0x1054D]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER QAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054D,
+ },
+ [0x1054E]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER NOWC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054E,
+ },
+ [0x1054F]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER DZYAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1054F,
+ },
+ [0x10550]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER SHAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10550,
+ },
+ [0x10551]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER JAYN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10551,
+ },
+ [0x10552]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10552,
+ },
+ [0x10553]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER TYAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10553,
+ },
+ [0x10554]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER FAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10554,
+ },
+ [0x10555]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER DZAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10555,
+ },
+ [0x10556]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CHAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10556,
+ },
+ [0x10557]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER PEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10557,
+ },
+ [0x10558]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER GHEYS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10558,
+ },
+ [0x10559]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER RAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10559,
+ },
+ [0x1055A]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER SEYK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055A,
+ },
+ [0x1055B]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER VEYZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055B,
+ },
+ [0x1055C]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER TIWR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055C,
+ },
+ [0x1055D]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER SHOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055D,
+ },
+ [0x1055E]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER IWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055E,
+ },
+ [0x1055F]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CYAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1055F,
+ },
+ [0x10560]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER CAYN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10560,
+ },
+ [0x10561]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER YAYD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10561,
+ },
+ [0x10562]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER PIWR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10562,
+ },
+ [0x10563]={
+ category="lo",
+ description="CAUCASIAN ALBANIAN LETTER KIW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10563,
+ },
+ [0x1056F]={
+ category="po",
+ description="CAUCASIAN ALBANIAN CITATION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1056F,
+ },
+ [0x10600]={
+ category="lo",
+ description="LINEAR A SIGN AB001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10600,
+ },
+ [0x10601]={
+ category="lo",
+ description="LINEAR A SIGN AB002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10601,
+ },
+ [0x10602]={
+ category="lo",
+ description="LINEAR A SIGN AB003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10602,
+ },
+ [0x10603]={
+ category="lo",
+ description="LINEAR A SIGN AB004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10603,
+ },
+ [0x10604]={
+ category="lo",
+ description="LINEAR A SIGN AB005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10604,
+ },
+ [0x10605]={
+ category="lo",
+ description="LINEAR A SIGN AB006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10605,
+ },
+ [0x10606]={
+ category="lo",
+ description="LINEAR A SIGN AB007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10606,
+ },
+ [0x10607]={
+ category="lo",
+ description="LINEAR A SIGN AB008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10607,
+ },
+ [0x10608]={
+ category="lo",
+ description="LINEAR A SIGN AB009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10608,
+ },
+ [0x10609]={
+ category="lo",
+ description="LINEAR A SIGN AB010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10609,
+ },
+ [0x1060A]={
+ category="lo",
+ description="LINEAR A SIGN AB011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060A,
+ },
+ [0x1060B]={
+ category="lo",
+ description="LINEAR A SIGN AB013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060B,
+ },
+ [0x1060C]={
+ category="lo",
+ description="LINEAR A SIGN AB016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060C,
+ },
+ [0x1060D]={
+ category="lo",
+ description="LINEAR A SIGN AB017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060D,
+ },
+ [0x1060E]={
+ category="lo",
+ description="LINEAR A SIGN AB020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060E,
+ },
+ [0x1060F]={
+ category="lo",
+ description="LINEAR A SIGN AB021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1060F,
+ },
+ [0x10610]={
+ category="lo",
+ description="LINEAR A SIGN AB021F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10610,
+ },
+ [0x10611]={
+ category="lo",
+ description="LINEAR A SIGN AB021M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10611,
+ },
+ [0x10612]={
+ category="lo",
+ description="LINEAR A SIGN AB022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10612,
+ },
+ [0x10613]={
+ category="lo",
+ description="LINEAR A SIGN AB022F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10613,
+ },
+ [0x10614]={
+ category="lo",
+ description="LINEAR A SIGN AB022M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10614,
+ },
+ [0x10615]={
+ category="lo",
+ description="LINEAR A SIGN AB023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10615,
+ },
+ [0x10616]={
+ category="lo",
+ description="LINEAR A SIGN AB023M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10616,
+ },
+ [0x10617]={
+ category="lo",
+ description="LINEAR A SIGN AB024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10617,
+ },
+ [0x10618]={
+ category="lo",
+ description="LINEAR A SIGN AB026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10618,
+ },
+ [0x10619]={
+ category="lo",
+ description="LINEAR A SIGN AB027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10619,
+ },
+ [0x1061A]={
+ category="lo",
+ description="LINEAR A SIGN AB028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061A,
+ },
+ [0x1061B]={
+ category="lo",
+ description="LINEAR A SIGN A028B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061B,
+ },
+ [0x1061C]={
+ category="lo",
+ description="LINEAR A SIGN AB029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061C,
+ },
+ [0x1061D]={
+ category="lo",
+ description="LINEAR A SIGN AB030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061D,
+ },
+ [0x1061E]={
+ category="lo",
+ description="LINEAR A SIGN AB031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061E,
+ },
+ [0x1061F]={
+ category="lo",
+ description="LINEAR A SIGN AB034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1061F,
+ },
+ [0x10620]={
+ category="lo",
+ description="LINEAR A SIGN AB037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10620,
+ },
+ [0x10621]={
+ category="lo",
+ description="LINEAR A SIGN AB038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10621,
+ },
+ [0x10622]={
+ category="lo",
+ description="LINEAR A SIGN AB039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10622,
+ },
+ [0x10623]={
+ category="lo",
+ description="LINEAR A SIGN AB040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10623,
+ },
+ [0x10624]={
+ category="lo",
+ description="LINEAR A SIGN AB041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10624,
+ },
+ [0x10625]={
+ category="lo",
+ description="LINEAR A SIGN AB044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10625,
+ },
+ [0x10626]={
+ category="lo",
+ description="LINEAR A SIGN AB045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10626,
+ },
+ [0x10627]={
+ category="lo",
+ description="LINEAR A SIGN AB046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10627,
+ },
+ [0x10628]={
+ category="lo",
+ description="LINEAR A SIGN AB047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10628,
+ },
+ [0x10629]={
+ category="lo",
+ description="LINEAR A SIGN AB048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10629,
+ },
+ [0x1062A]={
+ category="lo",
+ description="LINEAR A SIGN AB049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062A,
+ },
+ [0x1062B]={
+ category="lo",
+ description="LINEAR A SIGN AB050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062B,
+ },
+ [0x1062C]={
+ category="lo",
+ description="LINEAR A SIGN AB051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062C,
+ },
+ [0x1062D]={
+ category="lo",
+ description="LINEAR A SIGN AB053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062D,
+ },
+ [0x1062E]={
+ category="lo",
+ description="LINEAR A SIGN AB054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062E,
+ },
+ [0x1062F]={
+ category="lo",
+ description="LINEAR A SIGN AB055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1062F,
+ },
+ [0x10630]={
+ category="lo",
+ description="LINEAR A SIGN AB056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10630,
+ },
+ [0x10631]={
+ category="lo",
+ description="LINEAR A SIGN AB057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10631,
+ },
+ [0x10632]={
+ category="lo",
+ description="LINEAR A SIGN AB058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10632,
+ },
+ [0x10633]={
+ category="lo",
+ description="LINEAR A SIGN AB059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10633,
+ },
+ [0x10634]={
+ category="lo",
+ description="LINEAR A SIGN AB060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10634,
+ },
+ [0x10635]={
+ category="lo",
+ description="LINEAR A SIGN AB061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10635,
+ },
+ [0x10636]={
+ category="lo",
+ description="LINEAR A SIGN AB065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10636,
+ },
+ [0x10637]={
+ category="lo",
+ description="LINEAR A SIGN AB066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10637,
+ },
+ [0x10638]={
+ category="lo",
+ description="LINEAR A SIGN AB067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10638,
+ },
+ [0x10639]={
+ category="lo",
+ description="LINEAR A SIGN AB069",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10639,
+ },
+ [0x1063A]={
+ category="lo",
+ description="LINEAR A SIGN AB070",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063A,
+ },
+ [0x1063B]={
+ category="lo",
+ description="LINEAR A SIGN AB073",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063B,
+ },
+ [0x1063C]={
+ category="lo",
+ description="LINEAR A SIGN AB074",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063C,
+ },
+ [0x1063D]={
+ category="lo",
+ description="LINEAR A SIGN AB076",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063D,
+ },
+ [0x1063E]={
+ category="lo",
+ description="LINEAR A SIGN AB077",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063E,
+ },
+ [0x1063F]={
+ category="lo",
+ description="LINEAR A SIGN AB078",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1063F,
+ },
+ [0x10640]={
+ category="lo",
+ description="LINEAR A SIGN AB079",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10640,
+ },
+ [0x10641]={
+ category="lo",
+ description="LINEAR A SIGN AB080",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10641,
+ },
+ [0x10642]={
+ category="lo",
+ description="LINEAR A SIGN AB081",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10642,
+ },
+ [0x10643]={
+ category="lo",
+ description="LINEAR A SIGN AB082",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10643,
+ },
+ [0x10644]={
+ category="lo",
+ description="LINEAR A SIGN AB085",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10644,
+ },
+ [0x10645]={
+ category="lo",
+ description="LINEAR A SIGN AB086",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10645,
+ },
+ [0x10646]={
+ category="lo",
+ description="LINEAR A SIGN AB087",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10646,
+ },
+ [0x10647]={
+ category="lo",
+ description="LINEAR A SIGN A100-102",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10647,
+ },
+ [0x10648]={
+ category="lo",
+ description="LINEAR A SIGN AB118",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10648,
+ },
+ [0x10649]={
+ category="lo",
+ description="LINEAR A SIGN AB120",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10649,
+ },
+ [0x1064A]={
+ category="lo",
+ description="LINEAR A SIGN A120B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064A,
+ },
+ [0x1064B]={
+ category="lo",
+ description="LINEAR A SIGN AB122",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064B,
+ },
+ [0x1064C]={
+ category="lo",
+ description="LINEAR A SIGN AB123",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064C,
+ },
+ [0x1064D]={
+ category="lo",
+ description="LINEAR A SIGN AB131A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064D,
+ },
+ [0x1064E]={
+ category="lo",
+ description="LINEAR A SIGN AB131B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064E,
+ },
+ [0x1064F]={
+ category="lo",
+ description="LINEAR A SIGN A131C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1064F,
+ },
+ [0x10650]={
+ category="lo",
+ description="LINEAR A SIGN AB164",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10650,
+ },
+ [0x10651]={
+ category="lo",
+ description="LINEAR A SIGN AB171",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10651,
+ },
+ [0x10652]={
+ category="lo",
+ description="LINEAR A SIGN AB180",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10652,
+ },
+ [0x10653]={
+ category="lo",
+ description="LINEAR A SIGN AB188",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10653,
+ },
+ [0x10654]={
+ category="lo",
+ description="LINEAR A SIGN AB191",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10654,
+ },
+ [0x10655]={
+ category="lo",
+ description="LINEAR A SIGN A301",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10655,
+ },
+ [0x10656]={
+ category="lo",
+ description="LINEAR A SIGN A302",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10656,
+ },
+ [0x10657]={
+ category="lo",
+ description="LINEAR A SIGN A303",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10657,
+ },
+ [0x10658]={
+ category="lo",
+ description="LINEAR A SIGN A304",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10658,
+ },
+ [0x10659]={
+ category="lo",
+ description="LINEAR A SIGN A305",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10659,
+ },
+ [0x1065A]={
+ category="lo",
+ description="LINEAR A SIGN A306",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065A,
+ },
+ [0x1065B]={
+ category="lo",
+ description="LINEAR A SIGN A307",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065B,
+ },
+ [0x1065C]={
+ category="lo",
+ description="LINEAR A SIGN A308",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065C,
+ },
+ [0x1065D]={
+ category="lo",
+ description="LINEAR A SIGN A309A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065D,
+ },
+ [0x1065E]={
+ category="lo",
+ description="LINEAR A SIGN A309B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065E,
+ },
+ [0x1065F]={
+ category="lo",
+ description="LINEAR A SIGN A309C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1065F,
+ },
+ [0x10660]={
+ category="lo",
+ description="LINEAR A SIGN A310",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10660,
+ },
+ [0x10661]={
+ category="lo",
+ description="LINEAR A SIGN A311",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10661,
+ },
+ [0x10662]={
+ category="lo",
+ description="LINEAR A SIGN A312",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10662,
+ },
+ [0x10663]={
+ category="lo",
+ description="LINEAR A SIGN A313A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10663,
+ },
+ [0x10664]={
+ category="lo",
+ description="LINEAR A SIGN A313B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10664,
+ },
+ [0x10665]={
+ category="lo",
+ description="LINEAR A SIGN A313C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10665,
+ },
+ [0x10666]={
+ category="lo",
+ description="LINEAR A SIGN A314",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10666,
+ },
+ [0x10667]={
+ category="lo",
+ description="LINEAR A SIGN A315",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10667,
+ },
+ [0x10668]={
+ category="lo",
+ description="LINEAR A SIGN A316",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10668,
+ },
+ [0x10669]={
+ category="lo",
+ description="LINEAR A SIGN A317",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10669,
+ },
+ [0x1066A]={
+ category="lo",
+ description="LINEAR A SIGN A318",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066A,
+ },
+ [0x1066B]={
+ category="lo",
+ description="LINEAR A SIGN A319",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066B,
+ },
+ [0x1066C]={
+ category="lo",
+ description="LINEAR A SIGN A320",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066C,
+ },
+ [0x1066D]={
+ category="lo",
+ description="LINEAR A SIGN A321",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066D,
+ },
+ [0x1066E]={
+ category="lo",
+ description="LINEAR A SIGN A322",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066E,
+ },
+ [0x1066F]={
+ category="lo",
+ description="LINEAR A SIGN A323",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1066F,
+ },
+ [0x10670]={
+ category="lo",
+ description="LINEAR A SIGN A324",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10670,
+ },
+ [0x10671]={
+ category="lo",
+ description="LINEAR A SIGN A325",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10671,
+ },
+ [0x10672]={
+ category="lo",
+ description="LINEAR A SIGN A326",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10672,
+ },
+ [0x10673]={
+ category="lo",
+ description="LINEAR A SIGN A327",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10673,
+ },
+ [0x10674]={
+ category="lo",
+ description="LINEAR A SIGN A328",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10674,
+ },
+ [0x10675]={
+ category="lo",
+ description="LINEAR A SIGN A329",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10675,
+ },
+ [0x10676]={
+ category="lo",
+ description="LINEAR A SIGN A330",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10676,
+ },
+ [0x10677]={
+ category="lo",
+ description="LINEAR A SIGN A331",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10677,
+ },
+ [0x10678]={
+ category="lo",
+ description="LINEAR A SIGN A332",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10678,
+ },
+ [0x10679]={
+ category="lo",
+ description="LINEAR A SIGN A333",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10679,
+ },
+ [0x1067A]={
+ category="lo",
+ description="LINEAR A SIGN A334",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067A,
+ },
+ [0x1067B]={
+ category="lo",
+ description="LINEAR A SIGN A335",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067B,
+ },
+ [0x1067C]={
+ category="lo",
+ description="LINEAR A SIGN A336",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067C,
+ },
+ [0x1067D]={
+ category="lo",
+ description="LINEAR A SIGN A337",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067D,
+ },
+ [0x1067E]={
+ category="lo",
+ description="LINEAR A SIGN A338",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067E,
+ },
+ [0x1067F]={
+ category="lo",
+ description="LINEAR A SIGN A339",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1067F,
+ },
+ [0x10680]={
+ category="lo",
+ description="LINEAR A SIGN A340",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10680,
+ },
+ [0x10681]={
+ category="lo",
+ description="LINEAR A SIGN A341",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10681,
+ },
+ [0x10682]={
+ category="lo",
+ description="LINEAR A SIGN A342",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10682,
+ },
+ [0x10683]={
+ category="lo",
+ description="LINEAR A SIGN A343",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10683,
+ },
+ [0x10684]={
+ category="lo",
+ description="LINEAR A SIGN A344",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10684,
+ },
+ [0x10685]={
+ category="lo",
+ description="LINEAR A SIGN A345",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10685,
+ },
+ [0x10686]={
+ category="lo",
+ description="LINEAR A SIGN A346",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10686,
+ },
+ [0x10687]={
+ category="lo",
+ description="LINEAR A SIGN A347",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10687,
+ },
+ [0x10688]={
+ category="lo",
+ description="LINEAR A SIGN A348",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10688,
+ },
+ [0x10689]={
+ category="lo",
+ description="LINEAR A SIGN A349",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10689,
+ },
+ [0x1068A]={
+ category="lo",
+ description="LINEAR A SIGN A350",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068A,
+ },
+ [0x1068B]={
+ category="lo",
+ description="LINEAR A SIGN A351",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068B,
+ },
+ [0x1068C]={
+ category="lo",
+ description="LINEAR A SIGN A352",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068C,
+ },
+ [0x1068D]={
+ category="lo",
+ description="LINEAR A SIGN A353",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068D,
+ },
+ [0x1068E]={
+ category="lo",
+ description="LINEAR A SIGN A354",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068E,
+ },
+ [0x1068F]={
+ category="lo",
+ description="LINEAR A SIGN A355",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1068F,
+ },
+ [0x10690]={
+ category="lo",
+ description="LINEAR A SIGN A356",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10690,
+ },
+ [0x10691]={
+ category="lo",
+ description="LINEAR A SIGN A357",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10691,
+ },
+ [0x10692]={
+ category="lo",
+ description="LINEAR A SIGN A358",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10692,
+ },
+ [0x10693]={
+ category="lo",
+ description="LINEAR A SIGN A359",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10693,
+ },
+ [0x10694]={
+ category="lo",
+ description="LINEAR A SIGN A360",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10694,
+ },
+ [0x10695]={
+ category="lo",
+ description="LINEAR A SIGN A361",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10695,
+ },
+ [0x10696]={
+ category="lo",
+ description="LINEAR A SIGN A362",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10696,
+ },
+ [0x10697]={
+ category="lo",
+ description="LINEAR A SIGN A363",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10697,
+ },
+ [0x10698]={
+ category="lo",
+ description="LINEAR A SIGN A364",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10698,
+ },
+ [0x10699]={
+ category="lo",
+ description="LINEAR A SIGN A365",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10699,
+ },
+ [0x1069A]={
+ category="lo",
+ description="LINEAR A SIGN A366",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069A,
+ },
+ [0x1069B]={
+ category="lo",
+ description="LINEAR A SIGN A367",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069B,
+ },
+ [0x1069C]={
+ category="lo",
+ description="LINEAR A SIGN A368",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069C,
+ },
+ [0x1069D]={
+ category="lo",
+ description="LINEAR A SIGN A369",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069D,
+ },
+ [0x1069E]={
+ category="lo",
+ description="LINEAR A SIGN A370",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069E,
+ },
+ [0x1069F]={
+ category="lo",
+ description="LINEAR A SIGN A371",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1069F,
+ },
+ [0x106A0]={
+ category="lo",
+ description="LINEAR A SIGN A400-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A0,
+ },
+ [0x106A1]={
+ category="lo",
+ description="LINEAR A SIGN A401-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A1,
+ },
+ [0x106A2]={
+ category="lo",
+ description="LINEAR A SIGN A402-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A2,
+ },
+ [0x106A3]={
+ category="lo",
+ description="LINEAR A SIGN A403-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A3,
+ },
+ [0x106A4]={
+ category="lo",
+ description="LINEAR A SIGN A404-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A4,
+ },
+ [0x106A5]={
+ category="lo",
+ description="LINEAR A SIGN A405-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A5,
+ },
+ [0x106A6]={
+ category="lo",
+ description="LINEAR A SIGN A406-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A6,
+ },
+ [0x106A7]={
+ category="lo",
+ description="LINEAR A SIGN A407-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A7,
+ },
+ [0x106A8]={
+ category="lo",
+ description="LINEAR A SIGN A408-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A8,
+ },
+ [0x106A9]={
+ category="lo",
+ description="LINEAR A SIGN A409-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106A9,
+ },
+ [0x106AA]={
+ category="lo",
+ description="LINEAR A SIGN A410-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AA,
+ },
+ [0x106AB]={
+ category="lo",
+ description="LINEAR A SIGN A411-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AB,
+ },
+ [0x106AC]={
+ category="lo",
+ description="LINEAR A SIGN A412-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AC,
+ },
+ [0x106AD]={
+ category="lo",
+ description="LINEAR A SIGN A413-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AD,
+ },
+ [0x106AE]={
+ category="lo",
+ description="LINEAR A SIGN A414-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AE,
+ },
+ [0x106AF]={
+ category="lo",
+ description="LINEAR A SIGN A415-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106AF,
+ },
+ [0x106B0]={
+ category="lo",
+ description="LINEAR A SIGN A416-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B0,
+ },
+ [0x106B1]={
+ category="lo",
+ description="LINEAR A SIGN A417-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B1,
+ },
+ [0x106B2]={
+ category="lo",
+ description="LINEAR A SIGN A418-VAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B2,
+ },
+ [0x106B3]={
+ category="lo",
+ description="LINEAR A SIGN A501",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B3,
+ },
+ [0x106B4]={
+ category="lo",
+ description="LINEAR A SIGN A502",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B4,
+ },
+ [0x106B5]={
+ category="lo",
+ description="LINEAR A SIGN A503",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B5,
+ },
+ [0x106B6]={
+ category="lo",
+ description="LINEAR A SIGN A504",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B6,
+ },
+ [0x106B7]={
+ category="lo",
+ description="LINEAR A SIGN A505",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B7,
+ },
+ [0x106B8]={
+ category="lo",
+ description="LINEAR A SIGN A506",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B8,
+ },
+ [0x106B9]={
+ category="lo",
+ description="LINEAR A SIGN A508",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106B9,
+ },
+ [0x106BA]={
+ category="lo",
+ description="LINEAR A SIGN A509",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BA,
+ },
+ [0x106BB]={
+ category="lo",
+ description="LINEAR A SIGN A510",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BB,
+ },
+ [0x106BC]={
+ category="lo",
+ description="LINEAR A SIGN A511",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BC,
+ },
+ [0x106BD]={
+ category="lo",
+ description="LINEAR A SIGN A512",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BD,
+ },
+ [0x106BE]={
+ category="lo",
+ description="LINEAR A SIGN A513",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BE,
+ },
+ [0x106BF]={
+ category="lo",
+ description="LINEAR A SIGN A515",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106BF,
+ },
+ [0x106C0]={
+ category="lo",
+ description="LINEAR A SIGN A516",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C0,
+ },
+ [0x106C1]={
+ category="lo",
+ description="LINEAR A SIGN A520",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C1,
+ },
+ [0x106C2]={
+ category="lo",
+ description="LINEAR A SIGN A521",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C2,
+ },
+ [0x106C3]={
+ category="lo",
+ description="LINEAR A SIGN A523",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C3,
+ },
+ [0x106C4]={
+ category="lo",
+ description="LINEAR A SIGN A524",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C4,
+ },
+ [0x106C5]={
+ category="lo",
+ description="LINEAR A SIGN A525",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C5,
+ },
+ [0x106C6]={
+ category="lo",
+ description="LINEAR A SIGN A526",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C6,
+ },
+ [0x106C7]={
+ category="lo",
+ description="LINEAR A SIGN A527",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C7,
+ },
+ [0x106C8]={
+ category="lo",
+ description="LINEAR A SIGN A528",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C8,
+ },
+ [0x106C9]={
+ category="lo",
+ description="LINEAR A SIGN A529",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106C9,
+ },
+ [0x106CA]={
+ category="lo",
+ description="LINEAR A SIGN A530",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CA,
+ },
+ [0x106CB]={
+ category="lo",
+ description="LINEAR A SIGN A531",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CB,
+ },
+ [0x106CC]={
+ category="lo",
+ description="LINEAR A SIGN A532",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CC,
+ },
+ [0x106CD]={
+ category="lo",
+ description="LINEAR A SIGN A534",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CD,
+ },
+ [0x106CE]={
+ category="lo",
+ description="LINEAR A SIGN A535",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CE,
+ },
+ [0x106CF]={
+ category="lo",
+ description="LINEAR A SIGN A536",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106CF,
+ },
+ [0x106D0]={
+ category="lo",
+ description="LINEAR A SIGN A537",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D0,
+ },
+ [0x106D1]={
+ category="lo",
+ description="LINEAR A SIGN A538",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D1,
+ },
+ [0x106D2]={
+ category="lo",
+ description="LINEAR A SIGN A539",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D2,
+ },
+ [0x106D3]={
+ category="lo",
+ description="LINEAR A SIGN A540",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D3,
+ },
+ [0x106D4]={
+ category="lo",
+ description="LINEAR A SIGN A541",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D4,
+ },
+ [0x106D5]={
+ category="lo",
+ description="LINEAR A SIGN A542",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D5,
+ },
+ [0x106D6]={
+ category="lo",
+ description="LINEAR A SIGN A545",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D6,
+ },
+ [0x106D7]={
+ category="lo",
+ description="LINEAR A SIGN A547",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D7,
+ },
+ [0x106D8]={
+ category="lo",
+ description="LINEAR A SIGN A548",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D8,
+ },
+ [0x106D9]={
+ category="lo",
+ description="LINEAR A SIGN A549",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106D9,
+ },
+ [0x106DA]={
+ category="lo",
+ description="LINEAR A SIGN A550",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DA,
+ },
+ [0x106DB]={
+ category="lo",
+ description="LINEAR A SIGN A551",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DB,
+ },
+ [0x106DC]={
+ category="lo",
+ description="LINEAR A SIGN A552",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DC,
+ },
+ [0x106DD]={
+ category="lo",
+ description="LINEAR A SIGN A553",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DD,
+ },
+ [0x106DE]={
+ category="lo",
+ description="LINEAR A SIGN A554",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DE,
+ },
+ [0x106DF]={
+ category="lo",
+ description="LINEAR A SIGN A555",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106DF,
+ },
+ [0x106E0]={
+ category="lo",
+ description="LINEAR A SIGN A556",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E0,
+ },
+ [0x106E1]={
+ category="lo",
+ description="LINEAR A SIGN A557",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E1,
+ },
+ [0x106E2]={
+ category="lo",
+ description="LINEAR A SIGN A559",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E2,
+ },
+ [0x106E3]={
+ category="lo",
+ description="LINEAR A SIGN A563",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E3,
+ },
+ [0x106E4]={
+ category="lo",
+ description="LINEAR A SIGN A564",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E4,
+ },
+ [0x106E5]={
+ category="lo",
+ description="LINEAR A SIGN A565",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E5,
+ },
+ [0x106E6]={
+ category="lo",
+ description="LINEAR A SIGN A566",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E6,
+ },
+ [0x106E7]={
+ category="lo",
+ description="LINEAR A SIGN A568",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E7,
+ },
+ [0x106E8]={
+ category="lo",
+ description="LINEAR A SIGN A569",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E8,
+ },
+ [0x106E9]={
+ category="lo",
+ description="LINEAR A SIGN A570",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106E9,
+ },
+ [0x106EA]={
+ category="lo",
+ description="LINEAR A SIGN A571",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106EA,
+ },
+ [0x106EB]={
+ category="lo",
+ description="LINEAR A SIGN A572",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106EB,
+ },
+ [0x106EC]={
+ category="lo",
+ description="LINEAR A SIGN A573",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106EC,
+ },
+ [0x106ED]={
+ category="lo",
+ description="LINEAR A SIGN A574",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106ED,
+ },
+ [0x106EE]={
+ category="lo",
+ description="LINEAR A SIGN A575",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106EE,
+ },
+ [0x106EF]={
+ category="lo",
+ description="LINEAR A SIGN A576",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106EF,
+ },
+ [0x106F0]={
+ category="lo",
+ description="LINEAR A SIGN A577",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F0,
+ },
+ [0x106F1]={
+ category="lo",
+ description="LINEAR A SIGN A578",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F1,
+ },
+ [0x106F2]={
+ category="lo",
+ description="LINEAR A SIGN A579",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F2,
+ },
+ [0x106F3]={
+ category="lo",
+ description="LINEAR A SIGN A580",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F3,
+ },
+ [0x106F4]={
+ category="lo",
+ description="LINEAR A SIGN A581",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F4,
+ },
+ [0x106F5]={
+ category="lo",
+ description="LINEAR A SIGN A582",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F5,
+ },
+ [0x106F6]={
+ category="lo",
+ description="LINEAR A SIGN A583",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F6,
+ },
+ [0x106F7]={
+ category="lo",
+ description="LINEAR A SIGN A584",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F7,
+ },
+ [0x106F8]={
+ category="lo",
+ description="LINEAR A SIGN A585",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F8,
+ },
+ [0x106F9]={
+ category="lo",
+ description="LINEAR A SIGN A586",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106F9,
+ },
+ [0x106FA]={
+ category="lo",
+ description="LINEAR A SIGN A587",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FA,
+ },
+ [0x106FB]={
+ category="lo",
+ description="LINEAR A SIGN A588",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FB,
+ },
+ [0x106FC]={
+ category="lo",
+ description="LINEAR A SIGN A589",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FC,
+ },
+ [0x106FD]={
+ category="lo",
+ description="LINEAR A SIGN A591",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FD,
+ },
+ [0x106FE]={
+ category="lo",
+ description="LINEAR A SIGN A592",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FE,
+ },
+ [0x106FF]={
+ category="lo",
+ description="LINEAR A SIGN A594",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x106FF,
+ },
+ [0x10700]={
+ category="lo",
+ description="LINEAR A SIGN A595",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10700,
+ },
+ [0x10701]={
+ category="lo",
+ description="LINEAR A SIGN A596",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10701,
+ },
+ [0x10702]={
+ category="lo",
+ description="LINEAR A SIGN A598",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10702,
+ },
+ [0x10703]={
+ category="lo",
+ description="LINEAR A SIGN A600",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10703,
+ },
+ [0x10704]={
+ category="lo",
+ description="LINEAR A SIGN A601",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10704,
+ },
+ [0x10705]={
+ category="lo",
+ description="LINEAR A SIGN A602",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10705,
+ },
+ [0x10706]={
+ category="lo",
+ description="LINEAR A SIGN A603",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10706,
+ },
+ [0x10707]={
+ category="lo",
+ description="LINEAR A SIGN A604",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10707,
+ },
+ [0x10708]={
+ category="lo",
+ description="LINEAR A SIGN A606",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10708,
+ },
+ [0x10709]={
+ category="lo",
+ description="LINEAR A SIGN A608",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10709,
+ },
+ [0x1070A]={
+ category="lo",
+ description="LINEAR A SIGN A609",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070A,
+ },
+ [0x1070B]={
+ category="lo",
+ description="LINEAR A SIGN A610",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070B,
+ },
+ [0x1070C]={
+ category="lo",
+ description="LINEAR A SIGN A611",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070C,
+ },
+ [0x1070D]={
+ category="lo",
+ description="LINEAR A SIGN A612",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070D,
+ },
+ [0x1070E]={
+ category="lo",
+ description="LINEAR A SIGN A613",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070E,
+ },
+ [0x1070F]={
+ category="lo",
+ description="LINEAR A SIGN A614",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1070F,
+ },
+ [0x10710]={
+ category="lo",
+ description="LINEAR A SIGN A615",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10710,
+ },
+ [0x10711]={
+ category="lo",
+ description="LINEAR A SIGN A616",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10711,
+ },
+ [0x10712]={
+ category="lo",
+ description="LINEAR A SIGN A617",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10712,
+ },
+ [0x10713]={
+ category="lo",
+ description="LINEAR A SIGN A618",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10713,
+ },
+ [0x10714]={
+ category="lo",
+ description="LINEAR A SIGN A619",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10714,
+ },
+ [0x10715]={
+ category="lo",
+ description="LINEAR A SIGN A620",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10715,
+ },
+ [0x10716]={
+ category="lo",
+ description="LINEAR A SIGN A621",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10716,
+ },
+ [0x10717]={
+ category="lo",
+ description="LINEAR A SIGN A622",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10717,
+ },
+ [0x10718]={
+ category="lo",
+ description="LINEAR A SIGN A623",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10718,
+ },
+ [0x10719]={
+ category="lo",
+ description="LINEAR A SIGN A624",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10719,
+ },
+ [0x1071A]={
+ category="lo",
+ description="LINEAR A SIGN A626",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071A,
+ },
+ [0x1071B]={
+ category="lo",
+ description="LINEAR A SIGN A627",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071B,
+ },
+ [0x1071C]={
+ category="lo",
+ description="LINEAR A SIGN A628",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071C,
+ },
+ [0x1071D]={
+ category="lo",
+ description="LINEAR A SIGN A629",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071D,
+ },
+ [0x1071E]={
+ category="lo",
+ description="LINEAR A SIGN A634",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071E,
+ },
+ [0x1071F]={
+ category="lo",
+ description="LINEAR A SIGN A637",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1071F,
+ },
+ [0x10720]={
+ category="lo",
+ description="LINEAR A SIGN A638",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10720,
+ },
+ [0x10721]={
+ category="lo",
+ description="LINEAR A SIGN A640",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10721,
+ },
+ [0x10722]={
+ category="lo",
+ description="LINEAR A SIGN A642",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10722,
+ },
+ [0x10723]={
+ category="lo",
+ description="LINEAR A SIGN A643",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10723,
+ },
+ [0x10724]={
+ category="lo",
+ description="LINEAR A SIGN A644",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10724,
+ },
+ [0x10725]={
+ category="lo",
+ description="LINEAR A SIGN A645",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10725,
+ },
+ [0x10726]={
+ category="lo",
+ description="LINEAR A SIGN A646",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10726,
+ },
+ [0x10727]={
+ category="lo",
+ description="LINEAR A SIGN A648",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10727,
+ },
+ [0x10728]={
+ category="lo",
+ description="LINEAR A SIGN A649",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10728,
+ },
+ [0x10729]={
+ category="lo",
+ description="LINEAR A SIGN A651",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10729,
+ },
+ [0x1072A]={
+ category="lo",
+ description="LINEAR A SIGN A652",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072A,
+ },
+ [0x1072B]={
+ category="lo",
+ description="LINEAR A SIGN A653",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072B,
+ },
+ [0x1072C]={
+ category="lo",
+ description="LINEAR A SIGN A654",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072C,
+ },
+ [0x1072D]={
+ category="lo",
+ description="LINEAR A SIGN A655",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072D,
+ },
+ [0x1072E]={
+ category="lo",
+ description="LINEAR A SIGN A656",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072E,
+ },
+ [0x1072F]={
+ category="lo",
+ description="LINEAR A SIGN A657",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1072F,
+ },
+ [0x10730]={
+ category="lo",
+ description="LINEAR A SIGN A658",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10730,
+ },
+ [0x10731]={
+ category="lo",
+ description="LINEAR A SIGN A659",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10731,
+ },
+ [0x10732]={
+ category="lo",
+ description="LINEAR A SIGN A660",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10732,
+ },
+ [0x10733]={
+ category="lo",
+ description="LINEAR A SIGN A661",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10733,
+ },
+ [0x10734]={
+ category="lo",
+ description="LINEAR A SIGN A662",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10734,
+ },
+ [0x10735]={
+ category="lo",
+ description="LINEAR A SIGN A663",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10735,
+ },
+ [0x10736]={
+ category="lo",
+ description="LINEAR A SIGN A664",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10736,
+ },
+ [0x10740]={
+ category="lo",
+ description="LINEAR A SIGN A701 A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10740,
+ },
+ [0x10741]={
+ category="lo",
+ description="LINEAR A SIGN A702 B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10741,
+ },
+ [0x10742]={
+ category="lo",
+ description="LINEAR A SIGN A703 D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10742,
+ },
+ [0x10743]={
+ category="lo",
+ description="LINEAR A SIGN A704 E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10743,
+ },
+ [0x10744]={
+ category="lo",
+ description="LINEAR A SIGN A705 F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10744,
+ },
+ [0x10745]={
+ category="lo",
+ description="LINEAR A SIGN A706 H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10745,
+ },
+ [0x10746]={
+ category="lo",
+ description="LINEAR A SIGN A707 J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10746,
+ },
+ [0x10747]={
+ category="lo",
+ description="LINEAR A SIGN A708 K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10747,
+ },
+ [0x10748]={
+ category="lo",
+ description="LINEAR A SIGN A709 L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10748,
+ },
+ [0x10749]={
+ category="lo",
+ description="LINEAR A SIGN A709-2 L2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10749,
+ },
+ [0x1074A]={
+ category="lo",
+ description="LINEAR A SIGN A709-3 L3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074A,
+ },
+ [0x1074B]={
+ category="lo",
+ description="LINEAR A SIGN A709-4 L4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074B,
+ },
+ [0x1074C]={
+ category="lo",
+ description="LINEAR A SIGN A709-6 L6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074C,
+ },
+ [0x1074D]={
+ category="lo",
+ description="LINEAR A SIGN A710 W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074D,
+ },
+ [0x1074E]={
+ category="lo",
+ description="LINEAR A SIGN A711 X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074E,
+ },
+ [0x1074F]={
+ category="lo",
+ description="LINEAR A SIGN A712 Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1074F,
+ },
+ [0x10750]={
+ category="lo",
+ description="LINEAR A SIGN A713 OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10750,
+ },
+ [0x10751]={
+ category="lo",
+ description="LINEAR A SIGN A714 ABB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10751,
+ },
+ [0x10752]={
+ category="lo",
+ description="LINEAR A SIGN A715 BB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10752,
+ },
+ [0x10753]={
+ category="lo",
+ description="LINEAR A SIGN A717 DD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10753,
+ },
+ [0x10754]={
+ category="lo",
+ description="LINEAR A SIGN A726 EYYY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10754,
+ },
+ [0x10755]={
+ category="lo",
+ description="LINEAR A SIGN A732 JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10755,
+ },
+ [0x10760]={
+ category="lo",
+ description="LINEAR A SIGN A800",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10760,
+ },
+ [0x10761]={
+ category="lo",
+ description="LINEAR A SIGN A801",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10761,
+ },
+ [0x10762]={
+ category="lo",
+ description="LINEAR A SIGN A802",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10762,
+ },
+ [0x10763]={
+ category="lo",
+ description="LINEAR A SIGN A803",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10763,
+ },
+ [0x10764]={
+ category="lo",
+ description="LINEAR A SIGN A804",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10764,
+ },
+ [0x10765]={
+ category="lo",
+ description="LINEAR A SIGN A805",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10765,
+ },
+ [0x10766]={
+ category="lo",
+ description="LINEAR A SIGN A806",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10766,
+ },
+ [0x10767]={
+ category="lo",
+ description="LINEAR A SIGN A807",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10767,
+ },
+ [0x10800]={
+ category="lo",
+ description="CYPRIOT SYLLABLE A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10800,
+ },
+ [0x10801]={
+ category="lo",
+ description="CYPRIOT SYLLABLE E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10801,
+ },
+ [0x10802]={
+ category="lo",
+ description="CYPRIOT SYLLABLE I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10802,
+ },
+ [0x10803]={
+ category="lo",
+ description="CYPRIOT SYLLABLE O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10803,
+ },
+ [0x10804]={
+ category="lo",
+ description="CYPRIOT SYLLABLE U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10804,
+ },
+ [0x10805]={
+ category="lo",
+ description="CYPRIOT SYLLABLE JA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10805,
+ },
+ [0x10808]={
+ category="lo",
+ description="CYPRIOT SYLLABLE JO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10808,
+ },
+ [0x1080A]={
+ category="lo",
+ description="CYPRIOT SYLLABLE KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080A,
+ },
+ [0x1080B]={
+ category="lo",
+ description="CYPRIOT SYLLABLE KE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080B,
+ },
+ [0x1080C]={
+ category="lo",
+ description="CYPRIOT SYLLABLE KI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080C,
+ },
+ [0x1080D]={
+ category="lo",
+ description="CYPRIOT SYLLABLE KO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080D,
+ },
+ [0x1080E]={
+ category="lo",
+ description="CYPRIOT SYLLABLE KU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080E,
+ },
+ [0x1080F]={
+ category="lo",
+ description="CYPRIOT SYLLABLE LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1080F,
+ },
+ [0x10810]={
+ category="lo",
+ description="CYPRIOT SYLLABLE LE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10810,
+ },
+ [0x10811]={
+ category="lo",
+ description="CYPRIOT SYLLABLE LI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10811,
+ },
+ [0x10812]={
+ category="lo",
+ description="CYPRIOT SYLLABLE LO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10812,
+ },
+ [0x10813]={
+ category="lo",
+ description="CYPRIOT SYLLABLE LU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10813,
+ },
+ [0x10814]={
+ category="lo",
+ description="CYPRIOT SYLLABLE MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10814,
+ },
+ [0x10815]={
+ category="lo",
+ description="CYPRIOT SYLLABLE ME",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10815,
+ },
+ [0x10816]={
+ category="lo",
+ description="CYPRIOT SYLLABLE MI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10816,
+ },
+ [0x10817]={
+ category="lo",
+ description="CYPRIOT SYLLABLE MO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10817,
+ },
+ [0x10818]={
+ category="lo",
+ description="CYPRIOT SYLLABLE MU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10818,
+ },
+ [0x10819]={
+ category="lo",
+ description="CYPRIOT SYLLABLE NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10819,
+ },
+ [0x1081A]={
+ category="lo",
+ description="CYPRIOT SYLLABLE NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081A,
+ },
+ [0x1081B]={
+ category="lo",
+ description="CYPRIOT SYLLABLE NI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081B,
+ },
+ [0x1081C]={
+ category="lo",
+ description="CYPRIOT SYLLABLE NO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081C,
+ },
+ [0x1081D]={
+ category="lo",
+ description="CYPRIOT SYLLABLE NU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081D,
+ },
+ [0x1081E]={
+ category="lo",
+ description="CYPRIOT SYLLABLE PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081E,
+ },
+ [0x1081F]={
+ category="lo",
+ description="CYPRIOT SYLLABLE PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1081F,
+ },
+ [0x10820]={
+ category="lo",
+ description="CYPRIOT SYLLABLE PI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10820,
+ },
+ [0x10821]={
+ category="lo",
+ description="CYPRIOT SYLLABLE PO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10821,
+ },
+ [0x10822]={
+ category="lo",
+ description="CYPRIOT SYLLABLE PU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10822,
+ },
+ [0x10823]={
+ category="lo",
+ description="CYPRIOT SYLLABLE RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10823,
+ },
+ [0x10824]={
+ category="lo",
+ description="CYPRIOT SYLLABLE RE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10824,
+ },
+ [0x10825]={
+ category="lo",
+ description="CYPRIOT SYLLABLE RI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10825,
+ },
+ [0x10826]={
+ category="lo",
+ description="CYPRIOT SYLLABLE RO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10826,
+ },
+ [0x10827]={
+ category="lo",
+ description="CYPRIOT SYLLABLE RU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10827,
+ },
+ [0x10828]={
+ category="lo",
+ description="CYPRIOT SYLLABLE SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10828,
+ },
+ [0x10829]={
+ category="lo",
+ description="CYPRIOT SYLLABLE SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10829,
+ },
+ [0x1082A]={
+ category="lo",
+ description="CYPRIOT SYLLABLE SI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082A,
+ },
+ [0x1082B]={
+ category="lo",
+ description="CYPRIOT SYLLABLE SO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082B,
+ },
+ [0x1082C]={
+ category="lo",
+ description="CYPRIOT SYLLABLE SU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082C,
+ },
+ [0x1082D]={
+ category="lo",
+ description="CYPRIOT SYLLABLE TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082D,
+ },
+ [0x1082E]={
+ category="lo",
+ description="CYPRIOT SYLLABLE TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082E,
+ },
+ [0x1082F]={
+ category="lo",
+ description="CYPRIOT SYLLABLE TI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1082F,
+ },
+ [0x10830]={
+ category="lo",
+ description="CYPRIOT SYLLABLE TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10830,
+ },
+ [0x10831]={
+ category="lo",
+ description="CYPRIOT SYLLABLE TU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10831,
+ },
+ [0x10832]={
+ category="lo",
+ description="CYPRIOT SYLLABLE WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10832,
+ },
+ [0x10833]={
+ category="lo",
+ description="CYPRIOT SYLLABLE WE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10833,
+ },
+ [0x10834]={
+ category="lo",
+ description="CYPRIOT SYLLABLE WI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10834,
+ },
+ [0x10835]={
+ category="lo",
+ description="CYPRIOT SYLLABLE WO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10835,
+ },
+ [0x10837]={
+ category="lo",
+ description="CYPRIOT SYLLABLE XA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10837,
+ },
+ [0x10838]={
+ category="lo",
+ description="CYPRIOT SYLLABLE XE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10838,
+ },
+ [0x1083C]={
+ category="lo",
+ description="CYPRIOT SYLLABLE ZA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1083C,
+ },
+ [0x1083F]={
+ category="lo",
+ description="CYPRIOT SYLLABLE ZO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1083F,
+ },
+ [0x10840]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10840,
+ },
+ [0x10841]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10841,
+ },
+ [0x10842]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10842,
+ },
+ [0x10843]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10843,
+ },
+ [0x10844]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10844,
+ },
+ [0x10845]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10845,
+ },
+ [0x10846]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10846,
+ },
+ [0x10847]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10847,
+ },
+ [0x10848]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10848,
+ },
+ [0x10849]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10849,
+ },
+ [0x1084A]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084A,
+ },
+ [0x1084B]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084B,
+ },
+ [0x1084C]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084C,
+ },
+ [0x1084D]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084D,
+ },
+ [0x1084E]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084E,
+ },
+ [0x1084F]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084F,
+ },
+ [0x10850]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10850,
+ },
+ [0x10851]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10851,
+ },
+ [0x10852]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10852,
+ },
+ [0x10853]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10853,
+ },
+ [0x10854]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10854,
+ },
+ [0x10855]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10855,
+ },
+ [0x10857]={
+ category="po",
+ description="IMPERIAL ARAMAIC SECTION SIGN",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10857,
+ },
+ [0x10858]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10858,
+ },
+ [0x10859]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10859,
+ },
+ [0x1085A]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085A,
+ },
+ [0x1085B]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085B,
+ },
+ [0x1085C]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085C,
+ },
+ [0x1085D]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085D,
+ },
+ [0x1085E]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085E,
+ },
+ [0x1085F]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TEN THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085F,
+ },
+ [0x10860]={
+ category="lo",
+ description="PALMYRENE LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10860,
+ },
+ [0x10861]={
+ category="lo",
+ description="PALMYRENE LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10861,
+ },
+ [0x10862]={
+ category="lo",
+ description="PALMYRENE LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10862,
+ },
+ [0x10863]={
+ category="lo",
+ description="PALMYRENE LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10863,
+ },
+ [0x10864]={
+ category="lo",
+ description="PALMYRENE LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10864,
+ },
+ [0x10865]={
+ category="lo",
+ description="PALMYRENE LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10865,
+ },
+ [0x10866]={
+ category="lo",
+ description="PALMYRENE LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10866,
+ },
+ [0x10867]={
+ category="lo",
+ description="PALMYRENE LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10867,
+ },
+ [0x10868]={
+ category="lo",
+ description="PALMYRENE LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10868,
+ },
+ [0x10869]={
+ category="lo",
+ description="PALMYRENE LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10869,
+ },
+ [0x1086A]={
+ category="lo",
+ description="PALMYRENE LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086A,
+ },
+ [0x1086B]={
+ category="lo",
+ description="PALMYRENE LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086B,
+ },
+ [0x1086C]={
+ category="lo",
+ description="PALMYRENE LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086C,
+ },
+ [0x1086D]={
+ category="lo",
+ description="PALMYRENE LETTER FINAL NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086D,
+ },
+ [0x1086E]={
+ category="lo",
+ description="PALMYRENE LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086E,
+ },
+ [0x1086F]={
+ category="lo",
+ description="PALMYRENE LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1086F,
+ },
+ [0x10870]={
+ category="lo",
+ description="PALMYRENE LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10870,
+ },
+ [0x10871]={
+ category="lo",
+ description="PALMYRENE LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10871,
+ },
+ [0x10872]={
+ category="lo",
+ description="PALMYRENE LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10872,
+ },
+ [0x10873]={
+ category="lo",
+ description="PALMYRENE LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10873,
+ },
+ [0x10874]={
+ category="lo",
+ description="PALMYRENE LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10874,
+ },
+ [0x10875]={
+ category="lo",
+ description="PALMYRENE LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10875,
+ },
+ [0x10876]={
+ category="lo",
+ description="PALMYRENE LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10876,
+ },
+ [0x10877]={
+ category="so",
+ description="PALMYRENE LEFT-POINTING FLEURON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10877,
+ },
+ [0x10878]={
+ category="so",
+ description="PALMYRENE RIGHT-POINTING FLEURON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10878,
+ },
+ [0x10879]={
+ category="no",
+ description="PALMYRENE NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10879,
+ },
+ [0x1087A]={
+ category="no",
+ description="PALMYRENE NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087A,
+ },
+ [0x1087B]={
+ category="no",
+ description="PALMYRENE NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087B,
+ },
+ [0x1087C]={
+ category="no",
+ description="PALMYRENE NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087C,
+ },
+ [0x1087D]={
+ category="no",
+ description="PALMYRENE NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087D,
+ },
+ [0x1087E]={
+ category="no",
+ description="PALMYRENE NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087E,
+ },
+ [0x1087F]={
+ category="no",
+ description="PALMYRENE NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1087F,
+ },
+ [0x10880]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10880,
+ },
+ [0x10881]={
+ category="lo",
+ description="NABATAEAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10881,
+ },
+ [0x10882]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10882,
+ },
+ [0x10883]={
+ category="lo",
+ description="NABATAEAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10883,
+ },
+ [0x10884]={
+ category="lo",
+ description="NABATAEAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10884,
+ },
+ [0x10885]={
+ category="lo",
+ description="NABATAEAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10885,
+ },
+ [0x10886]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10886,
+ },
+ [0x10887]={
+ category="lo",
+ description="NABATAEAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10887,
+ },
+ [0x10888]={
+ category="lo",
+ description="NABATAEAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10888,
+ },
+ [0x10889]={
+ category="lo",
+ description="NABATAEAN LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10889,
+ },
+ [0x1088A]={
+ category="lo",
+ description="NABATAEAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088A,
+ },
+ [0x1088B]={
+ category="lo",
+ description="NABATAEAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088B,
+ },
+ [0x1088C]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088C,
+ },
+ [0x1088D]={
+ category="lo",
+ description="NABATAEAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088D,
+ },
+ [0x1088E]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088E,
+ },
+ [0x1088F]={
+ category="lo",
+ description="NABATAEAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1088F,
+ },
+ [0x10890]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10890,
+ },
+ [0x10891]={
+ category="lo",
+ description="NABATAEAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10891,
+ },
+ [0x10892]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10892,
+ },
+ [0x10893]={
+ category="lo",
+ description="NABATAEAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10893,
+ },
+ [0x10894]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10894,
+ },
+ [0x10895]={
+ category="lo",
+ description="NABATAEAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10895,
+ },
+ [0x10896]={
+ category="lo",
+ description="NABATAEAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10896,
+ },
+ [0x10897]={
+ category="lo",
+ description="NABATAEAN LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10897,
+ },
+ [0x10898]={
+ category="lo",
+ description="NABATAEAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10898,
+ },
+ [0x10899]={
+ category="lo",
+ description="NABATAEAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10899,
+ },
+ [0x1089A]={
+ category="lo",
+ description="NABATAEAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1089A,
+ },
+ [0x1089B]={
+ category="lo",
+ description="NABATAEAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1089B,
+ },
+ [0x1089C]={
+ category="lo",
+ description="NABATAEAN LETTER FINAL SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1089C,
+ },
+ [0x1089D]={
+ category="lo",
+ description="NABATAEAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1089D,
+ },
+ [0x1089E]={
+ category="lo",
+ description="NABATAEAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1089E,
+ },
+ [0x108A7]={
+ category="no",
+ description="NABATAEAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108A7,
+ },
+ [0x108A8]={
+ category="no",
+ description="NABATAEAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108A8,
+ },
+ [0x108A9]={
+ category="no",
+ description="NABATAEAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108A9,
+ },
+ [0x108AA]={
+ category="no",
+ description="NABATAEAN NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AA,
+ },
+ [0x108AB]={
+ category="no",
+ description="NABATAEAN CRUCIFORM NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AB,
+ },
+ [0x108AC]={
+ category="no",
+ description="NABATAEAN NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AC,
+ },
+ [0x108AD]={
+ category="no",
+ description="NABATAEAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AD,
+ },
+ [0x108AE]={
+ category="no",
+ description="NABATAEAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AE,
+ },
+ [0x108AF]={
+ category="no",
+ description="NABATAEAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108AF,
+ },
+ [0x108E0]={
+ category="lo",
+ description="HATRAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E0,
+ },
+ [0x108E1]={
+ category="lo",
+ description="HATRAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E1,
+ },
+ [0x108E2]={
+ category="lo",
+ description="HATRAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E2,
+ },
+ [0x108E3]={
+ category="lo",
+ description="HATRAN LETTER DALETH-RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E3,
+ },
+ [0x108E4]={
+ category="lo",
+ description="HATRAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E4,
+ },
+ [0x108E5]={
+ category="lo",
+ description="HATRAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E5,
+ },
+ [0x108E6]={
+ category="lo",
+ description="HATRAN LETTER ZAYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E6,
+ },
+ [0x108E7]={
+ category="lo",
+ description="HATRAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E7,
+ },
+ [0x108E8]={
+ category="lo",
+ description="HATRAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E8,
+ },
+ [0x108E9]={
+ category="lo",
+ description="HATRAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108E9,
+ },
+ [0x108EA]={
+ category="lo",
+ description="HATRAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108EA,
+ },
+ [0x108EB]={
+ category="lo",
+ description="HATRAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108EB,
+ },
+ [0x108EC]={
+ category="lo",
+ description="HATRAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108EC,
+ },
+ [0x108ED]={
+ category="lo",
+ description="HATRAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108ED,
+ },
+ [0x108EE]={
+ category="lo",
+ description="HATRAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108EE,
+ },
+ [0x108EF]={
+ category="lo",
+ description="HATRAN LETTER AYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108EF,
+ },
+ [0x108F0]={
+ category="lo",
+ description="HATRAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108F0,
+ },
+ [0x108F1]={
+ category="lo",
+ description="HATRAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108F1,
+ },
+ [0x108F2]={
+ category="lo",
+ description="HATRAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108F2,
+ },
+ [0x108F4]={
+ category="lo",
+ description="HATRAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108F4,
+ },
+ [0x108F5]={
+ category="lo",
+ description="HATRAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108F5,
+ },
+ [0x108FB]={
+ category="no",
+ description="HATRAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108FB,
+ },
+ [0x108FC]={
+ category="no",
+ description="HATRAN NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108FC,
+ },
+ [0x108FD]={
+ category="no",
+ description="HATRAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108FD,
+ },
+ [0x108FE]={
+ category="no",
+ description="HATRAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108FE,
+ },
+ [0x108FF]={
+ category="no",
+ description="HATRAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x108FF,
+ },
+ [0x10900]={
+ category="lo",
+ description="PHOENICIAN LETTER ALF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10900,
+ },
+ [0x10901]={
+ category="lo",
+ description="PHOENICIAN LETTER BET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10901,
+ },
+ [0x10902]={
+ category="lo",
+ description="PHOENICIAN LETTER GAML",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10902,
+ },
+ [0x10903]={
+ category="lo",
+ description="PHOENICIAN LETTER DELT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10903,
+ },
+ [0x10904]={
+ category="lo",
+ description="PHOENICIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10904,
+ },
+ [0x10905]={
+ category="lo",
+ description="PHOENICIAN LETTER WAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10905,
+ },
+ [0x10906]={
+ category="lo",
+ description="PHOENICIAN LETTER ZAI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10906,
+ },
+ [0x10907]={
+ category="lo",
+ description="PHOENICIAN LETTER HET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10907,
+ },
+ [0x10908]={
+ category="lo",
+ description="PHOENICIAN LETTER TET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10908,
+ },
+ [0x10909]={
+ category="lo",
+ description="PHOENICIAN LETTER YOD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10909,
+ },
+ [0x1090A]={
+ category="lo",
+ description="PHOENICIAN LETTER KAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090A,
+ },
+ [0x1090B]={
+ category="lo",
+ description="PHOENICIAN LETTER LAMD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090B,
+ },
+ [0x1090C]={
+ category="lo",
+ description="PHOENICIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090C,
+ },
+ [0x1090D]={
+ category="lo",
+ description="PHOENICIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090D,
+ },
+ [0x1090E]={
+ category="lo",
+ description="PHOENICIAN LETTER SEMK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090E,
+ },
+ [0x1090F]={
+ category="lo",
+ description="PHOENICIAN LETTER AIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1090F,
+ },
+ [0x10910]={
+ category="lo",
+ description="PHOENICIAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10910,
+ },
+ [0x10911]={
+ category="lo",
+ description="PHOENICIAN LETTER SADE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10911,
+ },
+ [0x10912]={
+ category="lo",
+ description="PHOENICIAN LETTER QOF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10912,
+ },
+ [0x10913]={
+ category="lo",
+ description="PHOENICIAN LETTER ROSH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10913,
+ },
+ [0x10914]={
+ category="lo",
+ description="PHOENICIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10914,
+ },
+ [0x10915]={
+ category="lo",
+ description="PHOENICIAN LETTER TAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10915,
+ },
+ [0x10916]={
+ category="no",
+ description="PHOENICIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10916,
+ },
+ [0x10917]={
+ category="no",
+ description="PHOENICIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10917,
+ },
+ [0x10918]={
+ category="no",
+ description="PHOENICIAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10918,
+ },
+ [0x10919]={
+ category="no",
+ description="PHOENICIAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10919,
+ },
+ [0x1091A]={
+ category="no",
+ description="PHOENICIAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1091A,
+ },
+ [0x1091B]={
+ category="no",
+ description="PHOENICIAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1091B,
+ },
+ [0x1091F]={
+ category="po",
+ description="PHOENICIAN WORD SEPARATOR",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x1091F,
+ },
+ [0x10920]={
+ category="lo",
+ description="LYDIAN LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10920,
+ },
+ [0x10921]={
+ category="lo",
+ description="LYDIAN LETTER B",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10921,
+ },
+ [0x10922]={
+ category="lo",
+ description="LYDIAN LETTER G",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10922,
+ },
+ [0x10923]={
+ category="lo",
+ description="LYDIAN LETTER D",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10923,
+ },
+ [0x10924]={
+ category="lo",
+ description="LYDIAN LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10924,
+ },
+ [0x10925]={
+ category="lo",
+ description="LYDIAN LETTER V",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10925,
+ },
+ [0x10926]={
+ category="lo",
+ description="LYDIAN LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10926,
+ },
+ [0x10927]={
+ category="lo",
+ description="LYDIAN LETTER Y",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10927,
+ },
+ [0x10928]={
+ category="lo",
+ description="LYDIAN LETTER K",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10928,
+ },
+ [0x10929]={
+ category="lo",
+ description="LYDIAN LETTER L",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10929,
+ },
+ [0x1092A]={
+ category="lo",
+ description="LYDIAN LETTER M",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092A,
+ },
+ [0x1092B]={
+ category="lo",
+ description="LYDIAN LETTER N",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092B,
+ },
+ [0x1092C]={
+ category="lo",
+ description="LYDIAN LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092C,
+ },
+ [0x1092D]={
+ category="lo",
+ description="LYDIAN LETTER R",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092D,
+ },
+ [0x1092E]={
+ category="lo",
+ description="LYDIAN LETTER SS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092E,
+ },
+ [0x1092F]={
+ category="lo",
+ description="LYDIAN LETTER T",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092F,
+ },
+ [0x10930]={
+ category="lo",
+ description="LYDIAN LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10930,
+ },
+ [0x10931]={
+ category="lo",
+ description="LYDIAN LETTER F",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10931,
+ },
+ [0x10932]={
+ category="lo",
+ description="LYDIAN LETTER Q",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10932,
+ },
+ [0x10933]={
+ category="lo",
+ description="LYDIAN LETTER S",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10933,
+ },
+ [0x10934]={
+ category="lo",
+ description="LYDIAN LETTER TT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10934,
+ },
+ [0x10935]={
+ category="lo",
+ description="LYDIAN LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10935,
+ },
+ [0x10936]={
+ category="lo",
+ description="LYDIAN LETTER EN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10936,
+ },
+ [0x10937]={
+ category="lo",
+ description="LYDIAN LETTER LY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10937,
+ },
+ [0x10938]={
+ category="lo",
+ description="LYDIAN LETTER NN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10938,
+ },
+ [0x10939]={
+ category="lo",
+ description="LYDIAN LETTER C",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10939,
+ },
+ [0x1093F]={
+ category="po",
+ description="LYDIAN TRIANGULAR MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1093F,
+ },
+ [0x10980]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10980,
+ },
+ [0x10981]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10981,
+ },
+ [0x10982]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10982,
+ },
+ [0x10983]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10983,
+ },
+ [0x10984]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10984,
+ },
+ [0x10985]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10985,
+ },
+ [0x10986]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10986,
+ },
+ [0x10987]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER BA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10987,
+ },
+ [0x10988]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10988,
+ },
+ [0x10989]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10989,
+ },
+ [0x1098A]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098A,
+ },
+ [0x1098B]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098B,
+ },
+ [0x1098C]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098C,
+ },
+ [0x1098D]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NE-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098D,
+ },
+ [0x1098E]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098E,
+ },
+ [0x1098F]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER RA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098F,
+ },
+ [0x10990]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10990,
+ },
+ [0x10991]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER KHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10991,
+ },
+ [0x10992]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER HHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10992,
+ },
+ [0x10993]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10993,
+ },
+ [0x10994]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10994,
+ },
+ [0x10995]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10995,
+ },
+ [0x10996]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10996,
+ },
+ [0x10997]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER QA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10997,
+ },
+ [0x10998]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10998,
+ },
+ [0x10999]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10999,
+ },
+ [0x1099A]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099A,
+ },
+ [0x1099B]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TE-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099B,
+ },
+ [0x1099C]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099C,
+ },
+ [0x1099D]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099D,
+ },
+ [0x1099E]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC SYMBOL VIDJ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099E,
+ },
+ [0x1099F]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099F,
+ },
+ [0x109A0]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A0,
+ },
+ [0x109A1]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A1,
+ },
+ [0x109A2]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A2,
+ },
+ [0x109A3]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A3,
+ },
+ [0x109A4]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A4,
+ },
+ [0x109A5]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A5,
+ },
+ [0x109A6]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A6,
+ },
+ [0x109A7]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A7,
+ },
+ [0x109A8]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A8,
+ },
+ [0x109A9]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A9,
+ },
+ [0x109AA]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AA,
+ },
+ [0x109AB]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AB,
+ },
+ [0x109AC]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AC,
+ },
+ [0x109AD]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER KHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AD,
+ },
+ [0x109AE]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER HHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AE,
+ },
+ [0x109AF]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AF,
+ },
+ [0x109B0]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER ARCHAIC SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B0,
+ },
+ [0x109B1]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B1,
+ },
+ [0x109B2]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B2,
+ },
+ [0x109B3]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER QA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B3,
+ },
+ [0x109B4]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B4,
+ },
+ [0x109B5]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B5,
+ },
+ [0x109B6]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B6,
+ },
+ [0x109B7]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B7,
+ },
+ [0x109BC]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BC,
+ },
+ [0x109BD]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION ONE HALF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BD,
+ },
+ [0x109BE]={
+ category="lo",
+ description="MEROITIC CURSIVE LOGOGRAM RMT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BE,
+ },
+ [0x109BF]={
+ category="lo",
+ description="MEROITIC CURSIVE LOGOGRAM IMN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BF,
+ },
+ [0x109C0]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C0,
+ },
+ [0x109C1]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C1,
+ },
+ [0x109C2]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C2,
+ },
+ [0x109C3]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C3,
+ },
+ [0x109C4]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C4,
+ },
+ [0x109C5]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIX",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C5,
+ },
+ [0x109C6]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C6,
+ },
+ [0x109C7]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER EIGHT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C7,
+ },
+ [0x109C8]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER NINE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C8,
+ },
+ [0x109C9]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109C9,
+ },
+ [0x109CA]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CA,
+ },
+ [0x109CB]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THIRTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CB,
+ },
+ [0x109CC]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FORTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CC,
+ },
+ [0x109CD]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIFTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CD,
+ },
+ [0x109CE]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIXTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CE,
+ },
+ [0x109CF]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109CF,
+ },
+ [0x109D2]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D2,
+ },
+ [0x109D3]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWO HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D3,
+ },
+ [0x109D4]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THREE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D4,
+ },
+ [0x109D5]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FOUR HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D5,
+ },
+ [0x109D6]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIVE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D6,
+ },
+ [0x109D7]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIX HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D7,
+ },
+ [0x109D8]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVEN HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D8,
+ },
+ [0x109D9]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER EIGHT HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109D9,
+ },
+ [0x109DA]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER NINE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DA,
+ },
+ [0x109DB]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DB,
+ },
+ [0x109DC]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWO THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DC,
+ },
+ [0x109DD]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THREE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DD,
+ },
+ [0x109DE]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FOUR THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DE,
+ },
+ [0x109DF]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIVE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109DF,
+ },
+ [0x109E0]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIX THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E0,
+ },
+ [0x109E1]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVEN THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E1,
+ },
+ [0x109E2]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER EIGHT THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E2,
+ },
+ [0x109E3]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER NINE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E3,
+ },
+ [0x109E4]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TEN THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E4,
+ },
+ [0x109E5]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWENTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E5,
+ },
+ [0x109E6]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THIRTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E6,
+ },
+ [0x109E7]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FORTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E7,
+ },
+ [0x109E8]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIFTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E8,
+ },
+ [0x109E9]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIXTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109E9,
+ },
+ [0x109EA]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVENTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109EA,
+ },
+ [0x109EB]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER EIGHTY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109EB,
+ },
+ [0x109EC]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER NINETY THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109EC,
+ },
+ [0x109ED]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109ED,
+ },
+ [0x109EE]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109EE,
+ },
+ [0x109EF]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109EF,
+ },
+ [0x109F0]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F0,
+ },
+ [0x109F1]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F1,
+ },
+ [0x109F2]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F2,
+ },
+ [0x109F3]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F3,
+ },
+ [0x109F4]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F4,
+ },
+ [0x109F5]={
+ category="no",
+ description="MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F5,
+ },
+ [0x109F6]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION ONE TWELFTH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F6,
+ },
+ [0x109F7]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION TWO TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F7,
+ },
+ [0x109F8]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION THREE TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F8,
+ },
+ [0x109F9]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION FOUR TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109F9,
+ },
+ [0x109FA]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION FIVE TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FA,
+ },
+ [0x109FB]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION SIX TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FB,
+ },
+ [0x109FC]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION SEVEN TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FC,
+ },
+ [0x109FD]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION EIGHT TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FD,
+ },
+ [0x109FE]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION NINE TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FE,
+ },
+ [0x109FF]={
+ category="no",
+ description="MEROITIC CURSIVE FRACTION TEN TWELFTHS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109FF,
+ },
+ [0x10A00]={
+ category="lo",
+ description="KHAROSHTHI LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A00,
+ },
+ [0x10A01]={
+ category="mn",
+ description="KHAROSHTHI VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A01,
+ },
+ [0x10A02]={
+ category="mn",
+ description="KHAROSHTHI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A02,
+ },
+ [0x10A03]={
+ category="mn",
+ description="KHAROSHTHI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A03,
+ },
+ [0x10A05]={
+ category="mn",
+ description="KHAROSHTHI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A05,
+ },
+ [0x10A06]={
+ category="mn",
+ description="KHAROSHTHI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A06,
+ },
+ [0x10A0C]={
+ category="mn",
+ description="KHAROSHTHI VOWEL LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A0C,
+ },
+ [0x10A0D]={
+ category="mn",
+ combining=0xDC,
+ description="KHAROSHTHI SIGN DOUBLE RING BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A0D,
+ },
+ [0x10A0E]={
+ category="mn",
+ description="KHAROSHTHI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A0E,
+ },
+ [0x10A0F]={
+ category="mn",
+ combining=0xE6,
+ description="KHAROSHTHI SIGN VISARGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A0F,
+ },
+ [0x10A10]={
+ category="lo",
+ description="KHAROSHTHI LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A10,
+ },
+ [0x10A11]={
+ category="lo",
+ description="KHAROSHTHI LETTER KHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A11,
+ },
+ [0x10A12]={
+ category="lo",
+ description="KHAROSHTHI LETTER GA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A12,
+ },
+ [0x10A13]={
+ category="lo",
+ description="KHAROSHTHI LETTER GHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A13,
+ },
+ [0x10A15]={
+ category="lo",
+ description="KHAROSHTHI LETTER CA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A15,
+ },
+ [0x10A16]={
+ category="lo",
+ description="KHAROSHTHI LETTER CHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A16,
+ },
+ [0x10A17]={
+ category="lo",
+ description="KHAROSHTHI LETTER JA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A17,
+ },
+ [0x10A19]={
+ category="lo",
+ description="KHAROSHTHI LETTER NYA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A19,
+ },
+ [0x10A1A]={
+ category="lo",
+ description="KHAROSHTHI LETTER TTA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1A,
+ },
+ [0x10A1B]={
+ category="lo",
+ description="KHAROSHTHI LETTER TTHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1B,
+ },
+ [0x10A1C]={
+ category="lo",
+ description="KHAROSHTHI LETTER DDA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1C,
+ },
+ [0x10A1D]={
+ category="lo",
+ description="KHAROSHTHI LETTER DDHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1D,
+ },
+ [0x10A1E]={
+ category="lo",
+ description="KHAROSHTHI LETTER NNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1E,
+ },
+ [0x10A1F]={
+ category="lo",
+ description="KHAROSHTHI LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A1F,
+ },
+ [0x10A20]={
+ category="lo",
+ description="KHAROSHTHI LETTER THA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A20,
+ },
+ [0x10A21]={
+ category="lo",
+ description="KHAROSHTHI LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A21,
+ },
+ [0x10A22]={
+ category="lo",
+ description="KHAROSHTHI LETTER DHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A22,
+ },
+ [0x10A23]={
+ category="lo",
+ description="KHAROSHTHI LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A23,
+ },
+ [0x10A24]={
+ category="lo",
+ description="KHAROSHTHI LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A24,
+ },
+ [0x10A25]={
+ category="lo",
+ description="KHAROSHTHI LETTER PHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A25,
+ },
+ [0x10A26]={
+ category="lo",
+ description="KHAROSHTHI LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A26,
+ },
+ [0x10A27]={
+ category="lo",
+ description="KHAROSHTHI LETTER BHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A27,
+ },
+ [0x10A28]={
+ category="lo",
+ description="KHAROSHTHI LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A28,
+ },
+ [0x10A29]={
+ category="lo",
+ description="KHAROSHTHI LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A29,
+ },
+ [0x10A2A]={
+ category="lo",
+ description="KHAROSHTHI LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2A,
+ },
+ [0x10A2B]={
+ category="lo",
+ description="KHAROSHTHI LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2B,
+ },
+ [0x10A2C]={
+ category="lo",
+ description="KHAROSHTHI LETTER VA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2C,
+ },
+ [0x10A2D]={
+ category="lo",
+ description="KHAROSHTHI LETTER SHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2D,
+ },
+ [0x10A2E]={
+ category="lo",
+ description="KHAROSHTHI LETTER SSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2E,
+ },
+ [0x10A2F]={
+ category="lo",
+ description="KHAROSHTHI LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A2F,
+ },
+ [0x10A30]={
+ category="lo",
+ description="KHAROSHTHI LETTER ZA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A30,
+ },
+ [0x10A31]={
+ category="lo",
+ description="KHAROSHTHI LETTER HA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A31,
+ },
+ [0x10A32]={
+ category="lo",
+ description="KHAROSHTHI LETTER KKA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A32,
+ },
+ [0x10A33]={
+ category="lo",
+ description="KHAROSHTHI LETTER TTTHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A33,
+ },
+ [0x10A38]={
+ category="mn",
+ combining=0xE6,
+ description="KHAROSHTHI SIGN BAR ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A38,
+ },
+ [0x10A39]={
+ category="mn",
+ combining=0x1,
+ description="KHAROSHTHI SIGN CAUDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A39,
+ },
+ [0x10A3A]={
+ category="mn",
+ combining=0xDC,
+ description="KHAROSHTHI SIGN DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A3A,
+ },
+ [0x10A3F]={
+ category="mn",
+ combining=0x9,
+ description="KHAROSHTHI VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10A3F,
+ },
+ [0x10A40]={
+ category="no",
+ description="KHAROSHTHI DIGIT ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A40,
+ },
+ [0x10A41]={
+ category="no",
+ description="KHAROSHTHI DIGIT TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A41,
+ },
+ [0x10A42]={
+ category="no",
+ description="KHAROSHTHI DIGIT THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A42,
+ },
+ [0x10A43]={
+ category="no",
+ description="KHAROSHTHI DIGIT FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A43,
+ },
+ [0x10A44]={
+ category="no",
+ description="KHAROSHTHI NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A44,
+ },
+ [0x10A45]={
+ category="no",
+ description="KHAROSHTHI NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A45,
+ },
+ [0x10A46]={
+ category="no",
+ description="KHAROSHTHI NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A46,
+ },
+ [0x10A47]={
+ category="no",
+ description="KHAROSHTHI NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A47,
+ },
+ [0x10A50]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION DOT",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A50,
+ },
+ [0x10A51]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION SMALL CIRCLE",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A51,
+ },
+ [0x10A52]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION CIRCLE",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A52,
+ },
+ [0x10A53]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION CRESCENT BAR",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A53,
+ },
+ [0x10A54]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION MANGALAM",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A54,
+ },
+ [0x10A55]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION LOTUS",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A55,
+ },
+ [0x10A56]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION DANDA",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A56,
+ },
+ [0x10A57]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION DOUBLE DANDA",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10A57,
+ },
+ [0x10A58]={
+ category="po",
+ description="KHAROSHTHI PUNCTUATION LINES",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A58,
+ },
+ [0x10A60]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A60,
+ },
+ [0x10A61]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A61,
+ },
+ [0x10A62]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A62,
+ },
+ [0x10A63]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A63,
+ },
+ [0x10A64]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A64,
+ },
+ [0x10A65]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A65,
+ },
+ [0x10A66]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A66,
+ },
+ [0x10A67]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A67,
+ },
+ [0x10A68]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A68,
+ },
+ [0x10A69]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A69,
+ },
+ [0x10A6A]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6A,
+ },
+ [0x10A6B]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6B,
+ },
+ [0x10A6C]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6C,
+ },
+ [0x10A6D]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER KHETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6D,
+ },
+ [0x10A6E]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6E,
+ },
+ [0x10A6F]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6F,
+ },
+ [0x10A70]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A70,
+ },
+ [0x10A71]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER ALEF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A71,
+ },
+ [0x10A72]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER AYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A72,
+ },
+ [0x10A73]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DHADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A73,
+ },
+ [0x10A74]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A74,
+ },
+ [0x10A75]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A75,
+ },
+ [0x10A76]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER GHAYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A76,
+ },
+ [0x10A77]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A77,
+ },
+ [0x10A78]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER ZAYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A78,
+ },
+ [0x10A79]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DHALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A79,
+ },
+ [0x10A7A]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7A,
+ },
+ [0x10A7B]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER THAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7B,
+ },
+ [0x10A7C]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER THETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7C,
+ },
+ [0x10A7D]={
+ category="no",
+ description="OLD SOUTH ARABIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7D,
+ },
+ [0x10A7E]={
+ category="no",
+ description="OLD SOUTH ARABIAN NUMBER FIFTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7E,
+ },
+ [0x10A7F]={
+ category="po",
+ description="OLD SOUTH ARABIAN NUMERIC INDICATOR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7F,
+ },
+ [0x10A80]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER HEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A80,
+ },
+ [0x10A81]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER LAM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A81,
+ },
+ [0x10A82]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER HAH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A82,
+ },
+ [0x10A83]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER MEEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A83,
+ },
+ [0x10A84]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER QAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A84,
+ },
+ [0x10A85]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A85,
+ },
+ [0x10A86]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ES-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A86,
+ },
+ [0x10A87]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER REH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A87,
+ },
+ [0x10A88]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER BEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A88,
+ },
+ [0x10A89]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER TEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A89,
+ },
+ [0x10A8A]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ES-1",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8A,
+ },
+ [0x10A8B]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER KAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8B,
+ },
+ [0x10A8C]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER NOON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8C,
+ },
+ [0x10A8D]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER KHAH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8D,
+ },
+ [0x10A8E]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER SAD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8E,
+ },
+ [0x10A8F]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ES-3",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A8F,
+ },
+ [0x10A90]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER FEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A90,
+ },
+ [0x10A91]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ALEF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A91,
+ },
+ [0x10A92]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER AIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A92,
+ },
+ [0x10A93]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER DAD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A93,
+ },
+ [0x10A94]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER GEEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A94,
+ },
+ [0x10A95]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER DAL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A95,
+ },
+ [0x10A96]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER GHAIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A96,
+ },
+ [0x10A97]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER TAH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A97,
+ },
+ [0x10A98]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ZAIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A98,
+ },
+ [0x10A99]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER THAL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A99,
+ },
+ [0x10A9A]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER YEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9A,
+ },
+ [0x10A9B]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER THEH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9B,
+ },
+ [0x10A9C]={
+ category="lo",
+ description="OLD NORTH ARABIAN LETTER ZAH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9C,
+ },
+ [0x10A9D]={
+ category="no",
+ description="OLD NORTH ARABIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9D,
+ },
+ [0x10A9E]={
+ category="no",
+ description="OLD NORTH ARABIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9E,
+ },
+ [0x10A9F]={
+ category="no",
+ description="OLD NORTH ARABIAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A9F,
+ },
+ [0x10AC0]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC0,
+ },
+ [0x10AC1]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC1,
+ },
+ [0x10AC2]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER BHETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC2,
+ },
+ [0x10AC3]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC3,
+ },
+ [0x10AC4]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER GHIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC4,
+ },
+ [0x10AC5]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC5,
+ variants={
+ [0xFE00]="alternate form",
+ },
+ },
+ [0x10AC6]={
+ arabic="u",
+ category="lo",
+ description="MANICHAEAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC6,
+ variants={
+ [0xFE00]="alternate form",
+ },
+ },
+ [0x10AC7]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC7,
+ },
+ [0x10AC8]={
+ arabic="u",
+ category="so",
+ description="MANICHAEAN SIGN UD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC8,
+ },
+ [0x10AC9]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AC9,
+ },
+ [0x10ACA]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER ZHAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACA,
+ },
+ [0x10ACB]={
+ arabic="u",
+ category="lo",
+ description="MANICHAEAN LETTER JAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACB,
+ },
+ [0x10ACC]={
+ arabic="u",
+ category="lo",
+ description="MANICHAEAN LETTER JHAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACC,
+ },
+ [0x10ACD]={
+ arabic="l",
+ category="lo",
+ description="MANICHAEAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACD,
+ },
+ [0x10ACE]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACE,
+ },
+ [0x10ACF]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ACF,
+ },
+ [0x10AD0]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD0,
+ },
+ [0x10AD1]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER XAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD1,
+ },
+ [0x10AD2]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER KHAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD2,
+ },
+ [0x10AD3]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD3,
+ },
+ [0x10AD4]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER DHAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD4,
+ },
+ [0x10AD5]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER THAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD5,
+ },
+ [0x10AD6]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD6,
+ variants={
+ [0xFE00]="alternate form",
+ },
+ },
+ [0x10AD7]={
+ arabic="l",
+ category="lo",
+ description="MANICHAEAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD7,
+ variants={
+ [0xFE00]="alternate form",
+ },
+ },
+ [0x10AD8]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD8,
+ },
+ [0x10AD9]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AD9,
+ },
+ [0x10ADA]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER AAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADA,
+ },
+ [0x10ADB]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADB,
+ },
+ [0x10ADC]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADC,
+ },
+ [0x10ADD]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADD,
+ },
+ [0x10ADE]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADE,
+ },
+ [0x10ADF]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER XOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10ADF,
+ },
+ [0x10AE0]={
+ arabic="d",
+ category="lo",
+ description="MANICHAEAN LETTER QHOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AE0,
+ },
+ [0x10AE1]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AE1,
+ variants={
+ [0xFE00]="alternate form",
+ },
+ },
+ [0x10AE2]={
+ arabic="u",
+ category="lo",
+ description="MANICHAEAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AE2,
+ },
+ [0x10AE3]={
+ arabic="u",
+ category="lo",
+ description="MANICHAEAN LETTER SSHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AE3,
+ },
+ [0x10AE4]={
+ arabic="r",
+ category="lo",
+ description="MANICHAEAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AE4,
+ },
+ [0x10AE5]={
+ category="mn",
+ combining=0xE6,
+ description="MANICHAEAN ABBREVIATION MARK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10AE5,
+ },
+ [0x10AE6]={
+ category="mn",
+ combining=0xDC,
+ description="MANICHAEAN ABBREVIATION MARK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10AE6,
+ },
+ [0x10AEB]={
+ arabic="d",
+ category="no",
+ description="MANICHAEAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AEB,
+ },
+ [0x10AEC]={
+ arabic="d",
+ category="no",
+ description="MANICHAEAN NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AEC,
+ },
+ [0x10AED]={
+ arabic="d",
+ category="no",
+ description="MANICHAEAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AED,
+ },
+ [0x10AEE]={
+ arabic="d",
+ category="no",
+ description="MANICHAEAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AEE,
+ },
+ [0x10AEF]={
+ arabic="r",
+ category="no",
+ description="MANICHAEAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10AEF,
+ },
+ [0x10AF0]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION STAR",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF0,
+ },
+ [0x10AF1]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION FLEURON",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF1,
+ },
+ [0x10AF2]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF2,
+ },
+ [0x10AF3]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION DOT WITHIN DOT",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF3,
+ },
+ [0x10AF4]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION DOT",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF4,
+ },
+ [0x10AF5]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION TWO DOTS",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10AF5,
+ },
+ [0x10AF6]={
+ category="po",
+ description="MANICHAEAN PUNCTUATION LINE FILLER",
+ direction="r",
+ linebreak="in",
+ unicodeslot=0x10AF6,
+ },
+ [0x10B00]={
+ category="lo",
+ description="AVESTAN LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B00,
+ },
+ [0x10B01]={
+ category="lo",
+ description="AVESTAN LETTER AA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B01,
+ },
+ [0x10B02]={
+ category="lo",
+ description="AVESTAN LETTER AO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B02,
+ },
+ [0x10B03]={
+ category="lo",
+ description="AVESTAN LETTER AAO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B03,
+ },
+ [0x10B04]={
+ category="lo",
+ description="AVESTAN LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B04,
+ },
+ [0x10B05]={
+ category="lo",
+ description="AVESTAN LETTER AAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B05,
+ },
+ [0x10B06]={
+ category="lo",
+ description="AVESTAN LETTER AE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B06,
+ },
+ [0x10B07]={
+ category="lo",
+ description="AVESTAN LETTER AEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B07,
+ },
+ [0x10B08]={
+ category="lo",
+ description="AVESTAN LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B08,
+ },
+ [0x10B09]={
+ category="lo",
+ description="AVESTAN LETTER EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B09,
+ },
+ [0x10B0A]={
+ category="lo",
+ description="AVESTAN LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0A,
+ },
+ [0x10B0B]={
+ category="lo",
+ description="AVESTAN LETTER OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0B,
+ },
+ [0x10B0C]={
+ category="lo",
+ description="AVESTAN LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0C,
+ },
+ [0x10B0D]={
+ category="lo",
+ description="AVESTAN LETTER II",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0D,
+ },
+ [0x10B0E]={
+ category="lo",
+ description="AVESTAN LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0E,
+ },
+ [0x10B0F]={
+ category="lo",
+ description="AVESTAN LETTER UU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0F,
+ },
+ [0x10B10]={
+ category="lo",
+ description="AVESTAN LETTER KE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B10,
+ },
+ [0x10B11]={
+ category="lo",
+ description="AVESTAN LETTER XE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B11,
+ },
+ [0x10B12]={
+ category="lo",
+ description="AVESTAN LETTER XYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B12,
+ },
+ [0x10B13]={
+ category="lo",
+ description="AVESTAN LETTER XVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B13,
+ },
+ [0x10B14]={
+ category="lo",
+ description="AVESTAN LETTER GE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B14,
+ },
+ [0x10B15]={
+ category="lo",
+ description="AVESTAN LETTER GGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B15,
+ },
+ [0x10B16]={
+ category="lo",
+ description="AVESTAN LETTER GHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B16,
+ },
+ [0x10B17]={
+ category="lo",
+ description="AVESTAN LETTER CE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B17,
+ },
+ [0x10B18]={
+ category="lo",
+ description="AVESTAN LETTER JE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B18,
+ },
+ [0x10B19]={
+ category="lo",
+ description="AVESTAN LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B19,
+ },
+ [0x10B1A]={
+ category="lo",
+ description="AVESTAN LETTER THE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1A,
+ },
+ [0x10B1B]={
+ category="lo",
+ description="AVESTAN LETTER DE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1B,
+ },
+ [0x10B1C]={
+ category="lo",
+ description="AVESTAN LETTER DHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1C,
+ },
+ [0x10B1D]={
+ category="lo",
+ description="AVESTAN LETTER TTE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1D,
+ },
+ [0x10B1E]={
+ category="lo",
+ description="AVESTAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1E,
+ },
+ [0x10B1F]={
+ category="lo",
+ description="AVESTAN LETTER FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1F,
+ },
+ [0x10B20]={
+ category="lo",
+ description="AVESTAN LETTER BE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B20,
+ },
+ [0x10B21]={
+ category="lo",
+ description="AVESTAN LETTER BHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B21,
+ },
+ [0x10B22]={
+ category="lo",
+ description="AVESTAN LETTER NGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B22,
+ },
+ [0x10B23]={
+ category="lo",
+ description="AVESTAN LETTER NGYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B23,
+ },
+ [0x10B24]={
+ category="lo",
+ description="AVESTAN LETTER NGVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B24,
+ },
+ [0x10B25]={
+ category="lo",
+ description="AVESTAN LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B25,
+ },
+ [0x10B26]={
+ category="lo",
+ description="AVESTAN LETTER NYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B26,
+ },
+ [0x10B27]={
+ category="lo",
+ description="AVESTAN LETTER NNE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B27,
+ },
+ [0x10B28]={
+ category="lo",
+ description="AVESTAN LETTER ME",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B28,
+ },
+ [0x10B29]={
+ category="lo",
+ description="AVESTAN LETTER HME",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B29,
+ },
+ [0x10B2A]={
+ category="lo",
+ description="AVESTAN LETTER YYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2A,
+ },
+ [0x10B2B]={
+ category="lo",
+ description="AVESTAN LETTER YE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2B,
+ },
+ [0x10B2C]={
+ category="lo",
+ description="AVESTAN LETTER VE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2C,
+ },
+ [0x10B2D]={
+ category="lo",
+ description="AVESTAN LETTER RE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2D,
+ },
+ [0x10B2E]={
+ category="lo",
+ description="AVESTAN LETTER LE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2E,
+ },
+ [0x10B2F]={
+ category="lo",
+ description="AVESTAN LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2F,
+ },
+ [0x10B30]={
+ category="lo",
+ description="AVESTAN LETTER ZE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B30,
+ },
+ [0x10B31]={
+ category="lo",
+ description="AVESTAN LETTER SHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B31,
+ },
+ [0x10B32]={
+ category="lo",
+ description="AVESTAN LETTER ZHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B32,
+ },
+ [0x10B33]={
+ category="lo",
+ description="AVESTAN LETTER SHYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B33,
+ },
+ [0x10B34]={
+ category="lo",
+ description="AVESTAN LETTER SSHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B34,
+ },
+ [0x10B35]={
+ category="lo",
+ description="AVESTAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B35,
+ },
+ [0x10B39]={
+ category="po",
+ description="AVESTAN ABBREVIATION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B39,
+ },
+ [0x10B3A]={
+ category="po",
+ description="TINY TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3A,
+ },
+ [0x10B3B]={
+ category="po",
+ description="SMALL TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3B,
+ },
+ [0x10B3C]={
+ category="po",
+ description="LARGE TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3C,
+ },
+ [0x10B3D]={
+ category="po",
+ description="LARGE ONE DOT OVER TWO DOTS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3D,
+ },
+ [0x10B3E]={
+ category="po",
+ description="LARGE TWO RINGS OVER ONE RING PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3E,
+ },
+ [0x10B3F]={
+ category="po",
+ description="LARGE ONE RING OVER TWO RINGS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3F,
+ },
+ [0x10B40]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B40,
+ },
+ [0x10B41]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B41,
+ },
+ [0x10B42]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B42,
+ },
+ [0x10B43]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B43,
+ },
+ [0x10B44]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B44,
+ },
+ [0x10B45]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B45,
+ },
+ [0x10B46]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B46,
+ },
+ [0x10B47]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B47,
+ },
+ [0x10B48]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B48,
+ },
+ [0x10B49]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B49,
+ },
+ [0x10B4A]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4A,
+ },
+ [0x10B4B]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4B,
+ },
+ [0x10B4C]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4C,
+ },
+ [0x10B4D]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4D,
+ },
+ [0x10B4E]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4E,
+ },
+ [0x10B4F]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4F,
+ },
+ [0x10B50]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B50,
+ },
+ [0x10B51]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B51,
+ },
+ [0x10B52]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B52,
+ },
+ [0x10B53]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B53,
+ },
+ [0x10B54]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B54,
+ },
+ [0x10B55]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B55,
+ },
+ [0x10B58]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B58,
+ },
+ [0x10B59]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B59,
+ },
+ [0x10B5A]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5A,
+ },
+ [0x10B5B]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5B,
+ },
+ [0x10B5C]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5C,
+ },
+ [0x10B5D]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5D,
+ },
+ [0x10B5E]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5E,
+ },
+ [0x10B5F]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5F,
+ },
+ [0x10B60]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B60,
+ },
+ [0x10B61]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B61,
+ },
+ [0x10B62]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B62,
+ },
+ [0x10B63]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B63,
+ },
+ [0x10B64]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B64,
+ },
+ [0x10B65]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B65,
+ },
+ [0x10B66]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B66,
+ },
+ [0x10B67]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B67,
+ },
+ [0x10B68]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B68,
+ },
+ [0x10B69]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B69,
+ },
+ [0x10B6A]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6A,
+ },
+ [0x10B6B]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6B,
+ },
+ [0x10B6C]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6C,
+ },
+ [0x10B6D]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6D,
+ },
+ [0x10B6E]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6E,
+ },
+ [0x10B6F]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6F,
+ },
+ [0x10B70]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B70,
+ },
+ [0x10B71]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B71,
+ },
+ [0x10B72]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B72,
+ },
+ [0x10B78]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B78,
+ },
+ [0x10B79]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B79,
+ },
+ [0x10B7A]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7A,
+ },
+ [0x10B7B]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7B,
+ },
+ [0x10B7C]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7C,
+ },
+ [0x10B7D]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7D,
+ },
+ [0x10B7E]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7E,
+ },
+ [0x10B7F]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7F,
+ },
+ [0x10B80]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B80,
+ },
+ [0x10B81]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B81,
+ },
+ [0x10B82]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B82,
+ },
+ [0x10B83]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B83,
+ },
+ [0x10B84]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B84,
+ },
+ [0x10B85]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER WAW-AYIN-RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B85,
+ },
+ [0x10B86]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B86,
+ },
+ [0x10B87]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B87,
+ },
+ [0x10B88]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B88,
+ },
+ [0x10B89]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B89,
+ },
+ [0x10B8A]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8A,
+ },
+ [0x10B8B]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER MEM-QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8B,
+ },
+ [0x10B8C]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8C,
+ },
+ [0x10B8D]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8D,
+ },
+ [0x10B8E]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8E,
+ },
+ [0x10B8F]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B8F,
+ },
+ [0x10B90]={
+ arabic="d",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B90,
+ },
+ [0x10B91]={
+ arabic="r",
+ category="lo",
+ description="PSALTER PAHLAVI LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B91,
+ },
+ [0x10B99]={
+ category="po",
+ description="PSALTER PAHLAVI SECTION MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B99,
+ },
+ [0x10B9A]={
+ category="po",
+ description="PSALTER PAHLAVI TURNED SECTION MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B9A,
+ },
+ [0x10B9B]={
+ category="po",
+ description="PSALTER PAHLAVI FOUR DOTS WITH CROSS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B9B,
+ },
+ [0x10B9C]={
+ category="po",
+ description="PSALTER PAHLAVI FOUR DOTS WITH DOT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B9C,
+ },
+ [0x10BA9]={
+ arabic="r",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BA9,
+ },
+ [0x10BAA]={
+ arabic="r",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAA,
+ },
+ [0x10BAB]={
+ arabic="r",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAB,
+ },
+ [0x10BAC]={
+ arabic="r",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAC,
+ },
+ [0x10BAD]={
+ arabic="d",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAD,
+ },
+ [0x10BAE]={
+ arabic="d",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAE,
+ },
+ [0x10BAF]={
+ arabic="u",
+ category="no",
+ description="PSALTER PAHLAVI NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10BAF,
+ },
+ [0x10C00]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C00,
+ },
+ [0x10C01]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C01,
+ },
+ [0x10C02]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C02,
+ },
+ [0x10C03]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C03,
+ },
+ [0x10C04]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C04,
+ },
+ [0x10C05]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C05,
+ },
+ [0x10C06]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C06,
+ },
+ [0x10C07]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C07,
+ },
+ [0x10C08]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C08,
+ },
+ [0x10C09]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C09,
+ },
+ [0x10C0A]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0A,
+ },
+ [0x10C0B]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0B,
+ },
+ [0x10C0C]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0C,
+ },
+ [0x10C0D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0D,
+ },
+ [0x10C0E]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0E,
+ },
+ [0x10C0F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0F,
+ },
+ [0x10C10]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C10,
+ },
+ [0x10C11]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C11,
+ },
+ [0x10C12]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C12,
+ },
+ [0x10C13]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C13,
+ },
+ [0x10C14]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C14,
+ },
+ [0x10C15]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C15,
+ },
+ [0x10C16]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C16,
+ },
+ [0x10C17]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C17,
+ },
+ [0x10C18]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C18,
+ },
+ [0x10C19]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C19,
+ },
+ [0x10C1A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1A,
+ },
+ [0x10C1B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1B,
+ },
+ [0x10C1C]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1C,
+ },
+ [0x10C1D]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1D,
+ },
+ [0x10C1E]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1E,
+ },
+ [0x10C1F]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1F,
+ },
+ [0x10C20]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C20,
+ },
+ [0x10C21]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ELT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C21,
+ },
+ [0x10C22]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C22,
+ },
+ [0x10C23]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C23,
+ },
+ [0x10C24]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C24,
+ },
+ [0x10C25]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C25,
+ },
+ [0x10C26]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C26,
+ },
+ [0x10C27]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C27,
+ },
+ [0x10C28]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C28,
+ },
+ [0x10C29]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C29,
+ },
+ [0x10C2A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2A,
+ },
+ [0x10C2B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2B,
+ },
+ [0x10C2C]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ANG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2C,
+ },
+ [0x10C2D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2D,
+ },
+ [0x10C2E]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AENG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2E,
+ },
+ [0x10C2F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2F,
+ },
+ [0x10C30]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C30,
+ },
+ [0x10C31]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON IC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C31,
+ },
+ [0x10C32]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C32,
+ },
+ [0x10C33]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C33,
+ },
+ [0x10C34]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C34,
+ },
+ [0x10C35]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C35,
+ },
+ [0x10C36]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON IQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C36,
+ },
+ [0x10C37]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI IQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C37,
+ },
+ [0x10C38]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C38,
+ },
+ [0x10C39]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C39,
+ },
+ [0x10C3A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3A,
+ },
+ [0x10C3B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3B,
+ },
+ [0x10C3C]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3C,
+ },
+ [0x10C3D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3D,
+ },
+ [0x10C3E]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AES",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3E,
+ },
+ [0x10C3F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3F,
+ },
+ [0x10C40]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C40,
+ },
+ [0x10C41]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C41,
+ },
+ [0x10C42]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C42,
+ },
+ [0x10C43]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C43,
+ },
+ [0x10C44]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C44,
+ },
+ [0x10C45]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C45,
+ },
+ [0x10C46]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C46,
+ },
+ [0x10C47]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C47,
+ },
+ [0x10C48]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON BASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C48,
+ },
+ [0x10C80]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C80,
+ },
+ [0x10C81]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER AA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C81,
+ },
+ [0x10C82]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C82,
+ },
+ [0x10C83]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER AMB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C83,
+ },
+ [0x10C84]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C84,
+ },
+ [0x10C85]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C85,
+ },
+ [0x10C86]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ECS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C86,
+ },
+ [0x10C87]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C87,
+ },
+ [0x10C88]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER AND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C88,
+ },
+ [0x10C89]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C89,
+ },
+ [0x10C8A]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER CLOSE E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8A,
+ },
+ [0x10C8B]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8B,
+ },
+ [0x10C8C]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8C,
+ },
+ [0x10C8D]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8D,
+ },
+ [0x10C8E]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EGY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8E,
+ },
+ [0x10C8F]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C8F,
+ },
+ [0x10C90]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C90,
+ },
+ [0x10C91]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER II",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C91,
+ },
+ [0x10C92]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EJ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C92,
+ },
+ [0x10C93]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C93,
+ },
+ [0x10C94]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER AK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C94,
+ },
+ [0x10C95]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER UNK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C95,
+ },
+ [0x10C96]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C96,
+ },
+ [0x10C97]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ELY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C97,
+ },
+ [0x10C98]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C98,
+ },
+ [0x10C99]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C99,
+ },
+ [0x10C9A]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9A,
+ },
+ [0x10C9B]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9B,
+ },
+ [0x10C9C]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9C,
+ },
+ [0x10C9D]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9D,
+ },
+ [0x10C9E]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9E,
+ },
+ [0x10C9F]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER OEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C9F,
+ },
+ [0x10CA0]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA0,
+ },
+ [0x10CA1]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EMP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA1,
+ },
+ [0x10CA2]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA2,
+ },
+ [0x10CA3]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER SHORT ER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA3,
+ },
+ [0x10CA4]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ES",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA4,
+ },
+ [0x10CA5]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ESZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA5,
+ },
+ [0x10CA6]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA6,
+ },
+ [0x10CA7]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA7,
+ },
+ [0x10CA8]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ETY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA8,
+ },
+ [0x10CA9]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ECH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CA9,
+ },
+ [0x10CAA]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAA,
+ },
+ [0x10CAB]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER UU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAB,
+ },
+ [0x10CAC]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAC,
+ },
+ [0x10CAD]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAD,
+ },
+ [0x10CAE]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EV",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAE,
+ },
+ [0x10CAF]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CAF,
+ },
+ [0x10CB0]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER EZS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CB0,
+ },
+ [0x10CB1]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CB1,
+ },
+ [0x10CB2]={
+ category="lu",
+ description="OLD HUNGARIAN CAPITAL LETTER US",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CB2,
+ },
+ [0x10CC0]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC0,
+ },
+ [0x10CC1]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER AA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC1,
+ },
+ [0x10CC2]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC2,
+ },
+ [0x10CC3]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER AMB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC3,
+ },
+ [0x10CC4]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC4,
+ },
+ [0x10CC5]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC5,
+ },
+ [0x10CC6]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ECS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC6,
+ },
+ [0x10CC7]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC7,
+ },
+ [0x10CC8]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER AND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC8,
+ },
+ [0x10CC9]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CC9,
+ },
+ [0x10CCA]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER CLOSE E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCA,
+ },
+ [0x10CCB]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCB,
+ },
+ [0x10CCC]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCC,
+ },
+ [0x10CCD]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCD,
+ },
+ [0x10CCE]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EGY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCE,
+ },
+ [0x10CCF]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CCF,
+ },
+ [0x10CD0]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD0,
+ },
+ [0x10CD1]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER II",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD1,
+ },
+ [0x10CD2]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EJ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD2,
+ },
+ [0x10CD3]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD3,
+ },
+ [0x10CD4]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER AK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD4,
+ },
+ [0x10CD5]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER UNK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD5,
+ },
+ [0x10CD6]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD6,
+ },
+ [0x10CD7]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ELY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD7,
+ },
+ [0x10CD8]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD8,
+ },
+ [0x10CD9]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CD9,
+ },
+ [0x10CDA]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDA,
+ },
+ [0x10CDB]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDB,
+ },
+ [0x10CDC]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDC,
+ },
+ [0x10CDD]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDD,
+ },
+ [0x10CDE]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER RUDIMENTA OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDE,
+ },
+ [0x10CDF]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER OEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CDF,
+ },
+ [0x10CE0]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE0,
+ },
+ [0x10CE1]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EMP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE1,
+ },
+ [0x10CE2]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE2,
+ },
+ [0x10CE3]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER SHORT ER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE3,
+ },
+ [0x10CE4]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ES",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE4,
+ },
+ [0x10CE5]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ESZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE5,
+ },
+ [0x10CE6]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE6,
+ },
+ [0x10CE7]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE7,
+ },
+ [0x10CE8]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ETY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE8,
+ },
+ [0x10CE9]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ECH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CE9,
+ },
+ [0x10CEA]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CEA,
+ },
+ [0x10CEB]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER UU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CEB,
+ },
+ [0x10CEC]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CEC,
+ },
+ [0x10CED]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER RUDIMENTA UE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CED,
+ },
+ [0x10CEE]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EV",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CEE,
+ },
+ [0x10CEF]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CEF,
+ },
+ [0x10CF0]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER EZS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CF0,
+ },
+ [0x10CF1]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CF1,
+ },
+ [0x10CF2]={
+ category="ll",
+ description="OLD HUNGARIAN SMALL LETTER US",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CF2,
+ },
+ [0x10CFA]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFA,
+ },
+ [0x10CFB]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFB,
+ },
+ [0x10CFC]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFC,
+ },
+ [0x10CFD]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER FIFTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFD,
+ },
+ [0x10CFE]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFE,
+ },
+ [0x10CFF]={
+ category="no",
+ description="OLD HUNGARIAN NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10CFF,
+ },
+ [0x10E60]={
+ category="no",
+ description="RUMI DIGIT ONE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E60,
+ },
+ [0x10E61]={
+ category="no",
+ description="RUMI DIGIT TWO",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E61,
+ },
+ [0x10E62]={
+ category="no",
+ description="RUMI DIGIT THREE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E62,
+ },
+ [0x10E63]={
+ category="no",
+ description="RUMI DIGIT FOUR",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E63,
+ },
+ [0x10E64]={
+ category="no",
+ description="RUMI DIGIT FIVE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E64,
+ },
+ [0x10E65]={
+ category="no",
+ description="RUMI DIGIT SIX",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E65,
+ },
+ [0x10E66]={
+ category="no",
+ description="RUMI DIGIT SEVEN",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E66,
+ },
+ [0x10E67]={
+ category="no",
+ description="RUMI DIGIT EIGHT",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E67,
+ },
+ [0x10E68]={
+ category="no",
+ description="RUMI DIGIT NINE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E68,
+ },
+ [0x10E69]={
+ category="no",
+ description="RUMI NUMBER TEN",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E69,
+ },
+ [0x10E6A]={
+ category="no",
+ description="RUMI NUMBER TWENTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6A,
+ },
+ [0x10E6B]={
+ category="no",
+ description="RUMI NUMBER THIRTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6B,
+ },
+ [0x10E6C]={
+ category="no",
+ description="RUMI NUMBER FORTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6C,
+ },
+ [0x10E6D]={
+ category="no",
+ description="RUMI NUMBER FIFTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6D,
+ },
+ [0x10E6E]={
+ category="no",
+ description="RUMI NUMBER SIXTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6E,
+ },
+ [0x10E6F]={
+ category="no",
+ description="RUMI NUMBER SEVENTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6F,
+ },
+ [0x10E70]={
+ category="no",
+ description="RUMI NUMBER EIGHTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E70,
+ },
+ [0x10E71]={
+ category="no",
+ description="RUMI NUMBER NINETY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E71,
+ },
+ [0x10E72]={
+ category="no",
+ description="RUMI NUMBER ONE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E72,
+ },
+ [0x10E73]={
+ category="no",
+ description="RUMI NUMBER TWO HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E73,
+ },
+ [0x10E74]={
+ category="no",
+ description="RUMI NUMBER THREE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E74,
+ },
+ [0x10E75]={
+ category="no",
+ description="RUMI NUMBER FOUR HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E75,
+ },
+ [0x10E76]={
+ category="no",
+ description="RUMI NUMBER FIVE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E76,
+ },
+ [0x10E77]={
+ category="no",
+ description="RUMI NUMBER SIX HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E77,
+ },
+ [0x10E78]={
+ category="no",
+ description="RUMI NUMBER SEVEN HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E78,
+ },
+ [0x10E79]={
+ category="no",
+ description="RUMI NUMBER EIGHT HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E79,
+ },
+ [0x10E7A]={
+ category="no",
+ description="RUMI NUMBER NINE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7A,
+ },
+ [0x10E7B]={
+ category="no",
+ description="RUMI FRACTION ONE HALF",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7B,
+ },
+ [0x10E7C]={
+ category="no",
+ description="RUMI FRACTION ONE QUARTER",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7C,
+ },
+ [0x10E7D]={
+ category="no",
+ description="RUMI FRACTION ONE THIRD",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7D,
+ },
+ [0x10E7E]={
+ category="no",
+ description="RUMI FRACTION TWO THIRDS",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7E,
+ },
+ [0x11000]={
+ category="mc",
+ description="BRAHMI SIGN CANDRABINDU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11000,
+ },
+ [0x11001]={
+ category="mn",
+ description="BRAHMI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11001,
+ },
+ [0x11002]={
+ category="mc",
+ description="BRAHMI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11002,
+ },
+ [0x11003]={
+ category="lo",
+ description="BRAHMI SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11003,
+ },
+ [0x11004]={
+ category="lo",
+ description="BRAHMI SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11004,
+ },
+ [0x11005]={
+ category="lo",
+ description="BRAHMI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11005,
+ },
+ [0x11006]={
+ category="lo",
+ description="BRAHMI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11006,
+ },
+ [0x11007]={
+ category="lo",
+ description="BRAHMI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11007,
+ },
+ [0x11008]={
+ category="lo",
+ description="BRAHMI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11008,
+ },
+ [0x11009]={
+ category="lo",
+ description="BRAHMI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11009,
+ },
+ [0x1100A]={
+ category="lo",
+ description="BRAHMI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100A,
+ },
+ [0x1100B]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100B,
+ },
+ [0x1100C]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100C,
+ },
+ [0x1100D]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100D,
+ },
+ [0x1100E]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100E,
+ },
+ [0x1100F]={
+ category="lo",
+ description="BRAHMI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100F,
+ },
+ [0x11010]={
+ category="lo",
+ description="BRAHMI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11010,
+ },
+ [0x11011]={
+ category="lo",
+ description="BRAHMI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11011,
+ },
+ [0x11012]={
+ category="lo",
+ description="BRAHMI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11012,
+ },
+ [0x11013]={
+ category="lo",
+ description="BRAHMI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11013,
+ },
+ [0x11014]={
+ category="lo",
+ description="BRAHMI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11014,
+ },
+ [0x11015]={
+ category="lo",
+ description="BRAHMI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11015,
+ },
+ [0x11016]={
+ category="lo",
+ description="BRAHMI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11016,
+ },
+ [0x11017]={
+ category="lo",
+ description="BRAHMI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11017,
+ },
+ [0x11018]={
+ category="lo",
+ description="BRAHMI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11018,
+ },
+ [0x11019]={
+ category="lo",
+ description="BRAHMI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11019,
+ },
+ [0x1101A]={
+ category="lo",
+ description="BRAHMI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101A,
+ },
+ [0x1101B]={
+ category="lo",
+ description="BRAHMI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101B,
+ },
+ [0x1101C]={
+ category="lo",
+ description="BRAHMI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101C,
+ },
+ [0x1101D]={
+ category="lo",
+ description="BRAHMI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101D,
+ },
+ [0x1101E]={
+ category="lo",
+ description="BRAHMI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101E,
+ },
+ [0x1101F]={
+ category="lo",
+ description="BRAHMI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101F,
+ },
+ [0x11020]={
+ category="lo",
+ description="BRAHMI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11020,
+ },
+ [0x11021]={
+ category="lo",
+ description="BRAHMI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11021,
+ },
+ [0x11022]={
+ category="lo",
+ description="BRAHMI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11022,
+ },
+ [0x11023]={
+ category="lo",
+ description="BRAHMI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11023,
+ },
+ [0x11024]={
+ category="lo",
+ description="BRAHMI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11024,
+ },
+ [0x11025]={
+ category="lo",
+ description="BRAHMI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11025,
+ },
+ [0x11026]={
+ category="lo",
+ description="BRAHMI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11026,
+ },
+ [0x11027]={
+ category="lo",
+ description="BRAHMI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11027,
+ },
+ [0x11028]={
+ category="lo",
+ description="BRAHMI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11028,
+ },
+ [0x11029]={
+ category="lo",
+ description="BRAHMI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11029,
+ },
+ [0x1102A]={
+ category="lo",
+ description="BRAHMI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102A,
+ },
+ [0x1102B]={
+ category="lo",
+ description="BRAHMI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102B,
+ },
+ [0x1102C]={
+ category="lo",
+ description="BRAHMI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102C,
+ },
+ [0x1102D]={
+ category="lo",
+ description="BRAHMI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102D,
+ },
+ [0x1102E]={
+ category="lo",
+ description="BRAHMI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102E,
+ },
+ [0x1102F]={
+ category="lo",
+ description="BRAHMI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102F,
+ },
+ [0x11030]={
+ category="lo",
+ description="BRAHMI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11030,
+ },
+ [0x11031]={
+ category="lo",
+ description="BRAHMI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11031,
+ },
+ [0x11032]={
+ category="lo",
+ description="BRAHMI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11032,
+ },
+ [0x11033]={
+ category="lo",
+ description="BRAHMI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11033,
+ },
+ [0x11034]={
+ category="lo",
+ description="BRAHMI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11034,
+ },
+ [0x11035]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL LLLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11035,
+ },
+ [0x11036]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11036,
+ },
+ [0x11037]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL NNNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11037,
+ },
+ [0x11038]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11038,
+ },
+ [0x11039]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN BHATTIPROLU AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11039,
+ },
+ [0x1103A]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103A,
+ },
+ [0x1103B]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103B,
+ },
+ [0x1103C]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103C,
+ },
+ [0x1103D]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103D,
+ },
+ [0x1103E]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103E,
+ },
+ [0x1103F]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103F,
+ },
+ [0x11040]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11040,
+ },
+ [0x11041]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11041,
+ },
+ [0x11042]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11042,
+ },
+ [0x11043]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11043,
+ },
+ [0x11044]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11044,
+ },
+ [0x11045]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11045,
+ },
+ [0x11046]={
+ category="mn",
+ combining=0x9,
+ description="BRAHMI VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11046,
+ },
+ [0x11047]={
+ category="po",
+ description="BRAHMI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11047,
+ },
+ [0x11048]={
+ category="po",
+ description="BRAHMI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11048,
+ },
+ [0x11049]={
+ category="po",
+ description="BRAHMI PUNCTUATION DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11049,
+ },
+ [0x1104A]={
+ category="po",
+ description="BRAHMI PUNCTUATION DOUBLE DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104A,
+ },
+ [0x1104B]={
+ category="po",
+ description="BRAHMI PUNCTUATION LINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104B,
+ },
+ [0x1104C]={
+ category="po",
+ description="BRAHMI PUNCTUATION CRESCENT BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104C,
+ },
+ [0x1104D]={
+ category="po",
+ description="BRAHMI PUNCTUATION LOTUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104D,
+ },
+ [0x11052]={
+ category="no",
+ description="BRAHMI NUMBER ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11052,
+ },
+ [0x11053]={
+ category="no",
+ description="BRAHMI NUMBER TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11053,
+ },
+ [0x11054]={
+ category="no",
+ description="BRAHMI NUMBER THREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11054,
+ },
+ [0x11055]={
+ category="no",
+ description="BRAHMI NUMBER FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11055,
+ },
+ [0x11056]={
+ category="no",
+ description="BRAHMI NUMBER FIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11056,
+ },
+ [0x11057]={
+ category="no",
+ description="BRAHMI NUMBER SIX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11057,
+ },
+ [0x11058]={
+ category="no",
+ description="BRAHMI NUMBER SEVEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11058,
+ },
+ [0x11059]={
+ category="no",
+ description="BRAHMI NUMBER EIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11059,
+ },
+ [0x1105A]={
+ category="no",
+ description="BRAHMI NUMBER NINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105A,
+ },
+ [0x1105B]={
+ category="no",
+ description="BRAHMI NUMBER TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105B,
+ },
+ [0x1105C]={
+ category="no",
+ description="BRAHMI NUMBER TWENTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105C,
+ },
+ [0x1105D]={
+ category="no",
+ description="BRAHMI NUMBER THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105D,
+ },
+ [0x1105E]={
+ category="no",
+ description="BRAHMI NUMBER FORTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105E,
+ },
+ [0x1105F]={
+ category="no",
+ description="BRAHMI NUMBER FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105F,
+ },
+ [0x11060]={
+ category="no",
+ description="BRAHMI NUMBER SIXTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11060,
+ },
+ [0x11061]={
+ category="no",
+ description="BRAHMI NUMBER SEVENTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11061,
+ },
+ [0x11062]={
+ category="no",
+ description="BRAHMI NUMBER EIGHTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11062,
+ },
+ [0x11063]={
+ category="no",
+ description="BRAHMI NUMBER NINETY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11063,
+ },
+ [0x11064]={
+ category="no",
+ description="BRAHMI NUMBER ONE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11064,
+ },
+ [0x11065]={
+ category="no",
+ description="BRAHMI NUMBER ONE THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11065,
+ },
+ [0x11066]={
+ category="nd",
+ description="BRAHMI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11066,
+ },
+ [0x11067]={
+ category="nd",
+ description="BRAHMI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11067,
+ },
+ [0x11068]={
+ category="nd",
+ description="BRAHMI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11068,
+ },
+ [0x11069]={
+ category="nd",
+ description="BRAHMI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11069,
+ },
+ [0x1106A]={
+ category="nd",
+ description="BRAHMI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106A,
+ },
+ [0x1106B]={
+ category="nd",
+ description="BRAHMI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106B,
+ },
+ [0x1106C]={
+ category="nd",
+ description="BRAHMI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106C,
+ },
+ [0x1106D]={
+ category="nd",
+ description="BRAHMI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106D,
+ },
+ [0x1106E]={
+ category="nd",
+ description="BRAHMI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106E,
+ },
+ [0x1106F]={
+ category="nd",
+ description="BRAHMI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106F,
+ },
+ [0x1107F]={
+ category="mn",
+ combining=0x9,
+ description="BRAHMI NUMBER JOINER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1107F,
+ },
+ [0x11080]={
+ category="mn",
+ description="KAITHI SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11080,
+ },
+ [0x11081]={
+ category="mn",
+ description="KAITHI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11081,
+ },
+ [0x11082]={
+ category="mc",
+ description="KAITHI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11082,
+ },
+ [0x11083]={
+ category="lo",
+ description="KAITHI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11083,
+ },
+ [0x11084]={
+ category="lo",
+ description="KAITHI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11084,
+ },
+ [0x11085]={
+ category="lo",
+ description="KAITHI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11085,
+ },
+ [0x11086]={
+ category="lo",
+ description="KAITHI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11086,
+ },
+ [0x11087]={
+ category="lo",
+ description="KAITHI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11087,
+ },
+ [0x11088]={
+ category="lo",
+ description="KAITHI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11088,
+ },
+ [0x11089]={
+ category="lo",
+ description="KAITHI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11089,
+ },
+ [0x1108A]={
+ category="lo",
+ description="KAITHI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108A,
+ },
+ [0x1108B]={
+ category="lo",
+ description="KAITHI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108B,
+ },
+ [0x1108C]={
+ category="lo",
+ description="KAITHI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108C,
+ },
+ [0x1108D]={
+ category="lo",
+ description="KAITHI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108D,
+ },
+ [0x1108E]={
+ category="lo",
+ description="KAITHI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108E,
+ },
+ [0x1108F]={
+ category="lo",
+ description="KAITHI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108F,
+ },
+ [0x11090]={
+ category="lo",
+ description="KAITHI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11090,
+ },
+ [0x11091]={
+ category="lo",
+ description="KAITHI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11091,
+ },
+ [0x11092]={
+ category="lo",
+ description="KAITHI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11092,
+ },
+ [0x11093]={
+ category="lo",
+ description="KAITHI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11093,
+ },
+ [0x11094]={
+ category="lo",
+ description="KAITHI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11094,
+ },
+ [0x11095]={
+ category="lo",
+ description="KAITHI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11095,
+ },
+ [0x11096]={
+ category="lo",
+ description="KAITHI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11096,
+ },
+ [0x11097]={
+ category="lo",
+ description="KAITHI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11097,
+ },
+ [0x11098]={
+ category="lo",
+ description="KAITHI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11098,
+ },
+ [0x11099]={
+ category="lo",
+ description="KAITHI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11099,
+ },
+ [0x1109A]={
+ category="lo",
+ description="KAITHI LETTER DDDHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x11099, 0x110BA },
+ unicodeslot=0x1109A,
+ },
+ [0x1109B]={
+ category="lo",
+ description="KAITHI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109B,
+ },
+ [0x1109C]={
+ category="lo",
+ description="KAITHI LETTER RHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1109B, 0x110BA },
+ unicodeslot=0x1109C,
+ },
+ [0x1109D]={
+ category="lo",
+ description="KAITHI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109D,
+ },
+ [0x1109E]={
+ category="lo",
+ description="KAITHI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109E,
+ },
+ [0x1109F]={
+ category="lo",
+ description="KAITHI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109F,
+ },
+ [0x110A0]={
+ category="lo",
+ description="KAITHI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A0,
+ },
+ [0x110A1]={
+ category="lo",
+ description="KAITHI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A1,
+ },
+ [0x110A2]={
+ category="lo",
+ description="KAITHI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A2,
+ },
+ [0x110A3]={
+ category="lo",
+ description="KAITHI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A3,
+ },
+ [0x110A4]={
+ category="lo",
+ description="KAITHI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A4,
+ },
+ [0x110A5]={
+ category="lo",
+ description="KAITHI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A5,
+ },
+ [0x110A6]={
+ category="lo",
+ description="KAITHI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A6,
+ },
+ [0x110A7]={
+ category="lo",
+ description="KAITHI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A7,
+ },
+ [0x110A8]={
+ category="lo",
+ description="KAITHI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A8,
+ },
+ [0x110A9]={
+ category="lo",
+ description="KAITHI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A9,
+ },
+ [0x110AA]={
+ category="lo",
+ description="KAITHI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AA,
+ },
+ [0x110AB]={
+ category="lo",
+ description="KAITHI LETTER VA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x110A5, 0x110BA },
+ unicodeslot=0x110AB,
+ },
+ [0x110AC]={
+ category="lo",
+ description="KAITHI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AC,
+ },
+ [0x110AD]={
+ category="lo",
+ description="KAITHI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AD,
+ },
+ [0x110AE]={
+ category="lo",
+ description="KAITHI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AE,
+ },
+ [0x110AF]={
+ category="lo",
+ description="KAITHI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AF,
+ },
+ [0x110B0]={
+ category="mc",
+ description="KAITHI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B0,
+ },
+ [0x110B1]={
+ category="mc",
+ description="KAITHI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B1,
+ },
+ [0x110B2]={
+ category="mc",
+ description="KAITHI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B2,
+ },
+ [0x110B3]={
+ category="mn",
+ description="KAITHI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B3,
+ },
+ [0x110B4]={
+ category="mn",
+ description="KAITHI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B4,
+ },
+ [0x110B5]={
+ category="mn",
+ description="KAITHI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B5,
+ },
+ [0x110B6]={
+ category="mn",
+ description="KAITHI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B6,
+ },
+ [0x110B7]={
+ category="mc",
+ description="KAITHI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B7,
+ },
+ [0x110B8]={
+ category="mc",
+ description="KAITHI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B8,
+ },
+ [0x110B9]={
+ category="mn",
+ combining=0x9,
+ description="KAITHI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B9,
+ },
+ [0x110BA]={
+ category="mn",
+ combining=0x7,
+ description="KAITHI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110BA,
+ },
+ [0x110BB]={
+ category="po",
+ description="KAITHI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BB,
+ },
+ [0x110BC]={
+ category="po",
+ description="KAITHI ENUMERATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BC,
+ },
+ [0x110BD]={
+ category="cf",
+ description="KAITHI NUMBER SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BD,
+ },
+ [0x110BE]={
+ category="po",
+ description="KAITHI SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110BE,
+ },
+ [0x110BF]={
+ category="po",
+ description="KAITHI DOUBLE SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110BF,
+ },
+ [0x110C0]={
+ category="po",
+ description="KAITHI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110C0,
+ },
+ [0x110C1]={
+ category="po",
+ description="KAITHI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110C1,
+ },
+ [0x110D0]={
+ category="lo",
+ description="SORA SOMPENG LETTER SAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D0,
+ },
+ [0x110D1]={
+ category="lo",
+ description="SORA SOMPENG LETTER TAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D1,
+ },
+ [0x110D2]={
+ category="lo",
+ description="SORA SOMPENG LETTER BAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D2,
+ },
+ [0x110D3]={
+ category="lo",
+ description="SORA SOMPENG LETTER CAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D3,
+ },
+ [0x110D4]={
+ category="lo",
+ description="SORA SOMPENG LETTER DAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D4,
+ },
+ [0x110D5]={
+ category="lo",
+ description="SORA SOMPENG LETTER GAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D5,
+ },
+ [0x110D6]={
+ category="lo",
+ description="SORA SOMPENG LETTER MAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D6,
+ },
+ [0x110D7]={
+ category="lo",
+ description="SORA SOMPENG LETTER NGAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D7,
+ },
+ [0x110D8]={
+ category="lo",
+ description="SORA SOMPENG LETTER LAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D8,
+ },
+ [0x110D9]={
+ category="lo",
+ description="SORA SOMPENG LETTER NAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D9,
+ },
+ [0x110DA]={
+ category="lo",
+ description="SORA SOMPENG LETTER VAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DA,
+ },
+ [0x110DB]={
+ category="lo",
+ description="SORA SOMPENG LETTER PAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DB,
+ },
+ [0x110DC]={
+ category="lo",
+ description="SORA SOMPENG LETTER YAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DC,
+ },
+ [0x110DD]={
+ category="lo",
+ description="SORA SOMPENG LETTER RAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DD,
+ },
+ [0x110DE]={
+ category="lo",
+ description="SORA SOMPENG LETTER HAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DE,
+ },
+ [0x110DF]={
+ category="lo",
+ description="SORA SOMPENG LETTER KAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DF,
+ },
+ [0x110E0]={
+ category="lo",
+ description="SORA SOMPENG LETTER JAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E0,
+ },
+ [0x110E1]={
+ category="lo",
+ description="SORA SOMPENG LETTER NYAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E1,
+ },
+ [0x110E2]={
+ category="lo",
+ description="SORA SOMPENG LETTER AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E2,
+ },
+ [0x110E3]={
+ category="lo",
+ description="SORA SOMPENG LETTER EEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E3,
+ },
+ [0x110E4]={
+ category="lo",
+ description="SORA SOMPENG LETTER IH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E4,
+ },
+ [0x110E5]={
+ category="lo",
+ description="SORA SOMPENG LETTER UH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E5,
+ },
+ [0x110E6]={
+ category="lo",
+ description="SORA SOMPENG LETTER OH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E6,
+ },
+ [0x110E7]={
+ category="lo",
+ description="SORA SOMPENG LETTER EH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E7,
+ },
+ [0x110E8]={
+ category="lo",
+ description="SORA SOMPENG LETTER MAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E8,
+ },
+ [0x110F0]={
+ category="nd",
+ description="SORA SOMPENG DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F0,
+ },
+ [0x110F1]={
+ category="nd",
+ description="SORA SOMPENG DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F1,
+ },
+ [0x110F2]={
+ category="nd",
+ description="SORA SOMPENG DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F2,
+ },
+ [0x110F3]={
+ category="nd",
+ description="SORA SOMPENG DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F3,
+ },
+ [0x110F4]={
+ category="nd",
+ description="SORA SOMPENG DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F4,
+ },
+ [0x110F5]={
+ category="nd",
+ description="SORA SOMPENG DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F5,
+ },
+ [0x110F6]={
+ category="nd",
+ description="SORA SOMPENG DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F6,
+ },
+ [0x110F7]={
+ category="nd",
+ description="SORA SOMPENG DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F7,
+ },
+ [0x110F8]={
+ category="nd",
+ description="SORA SOMPENG DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F8,
+ },
+ [0x110F9]={
+ category="nd",
+ description="SORA SOMPENG DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F9,
+ },
+ [0x11100]={
+ category="mn",
+ combining=0xE6,
+ description="CHAKMA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11100,
+ },
+ [0x11101]={
+ category="mn",
+ combining=0xE6,
+ description="CHAKMA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11101,
+ },
+ [0x11102]={
+ category="mn",
+ combining=0xE6,
+ description="CHAKMA SIGN VISARGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11102,
+ },
+ [0x11103]={
+ category="lo",
+ description="CHAKMA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11103,
+ },
+ [0x11104]={
+ category="lo",
+ description="CHAKMA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11104,
+ },
+ [0x11105]={
+ category="lo",
+ description="CHAKMA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11105,
+ },
+ [0x11106]={
+ category="lo",
+ description="CHAKMA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11106,
+ },
+ [0x11107]={
+ category="lo",
+ description="CHAKMA LETTER KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11107,
+ },
+ [0x11108]={
+ category="lo",
+ description="CHAKMA LETTER KHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11108,
+ },
+ [0x11109]={
+ category="lo",
+ description="CHAKMA LETTER GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11109,
+ },
+ [0x1110A]={
+ category="lo",
+ description="CHAKMA LETTER GHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110A,
+ },
+ [0x1110B]={
+ category="lo",
+ description="CHAKMA LETTER NGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110B,
+ },
+ [0x1110C]={
+ category="lo",
+ description="CHAKMA LETTER CAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110C,
+ },
+ [0x1110D]={
+ category="lo",
+ description="CHAKMA LETTER CHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110D,
+ },
+ [0x1110E]={
+ category="lo",
+ description="CHAKMA LETTER JAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110E,
+ },
+ [0x1110F]={
+ category="lo",
+ description="CHAKMA LETTER JHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110F,
+ },
+ [0x11110]={
+ category="lo",
+ description="CHAKMA LETTER NYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11110,
+ },
+ [0x11111]={
+ category="lo",
+ description="CHAKMA LETTER TTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11111,
+ },
+ [0x11112]={
+ category="lo",
+ description="CHAKMA LETTER TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11112,
+ },
+ [0x11113]={
+ category="lo",
+ description="CHAKMA LETTER DDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11113,
+ },
+ [0x11114]={
+ category="lo",
+ description="CHAKMA LETTER DDHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11114,
+ },
+ [0x11115]={
+ category="lo",
+ description="CHAKMA LETTER NNAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11115,
+ },
+ [0x11116]={
+ category="lo",
+ description="CHAKMA LETTER TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11116,
+ },
+ [0x11117]={
+ category="lo",
+ description="CHAKMA LETTER THAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11117,
+ },
+ [0x11118]={
+ category="lo",
+ description="CHAKMA LETTER DAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11118,
+ },
+ [0x11119]={
+ category="lo",
+ description="CHAKMA LETTER DHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11119,
+ },
+ [0x1111A]={
+ category="lo",
+ description="CHAKMA LETTER NAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111A,
+ },
+ [0x1111B]={
+ category="lo",
+ description="CHAKMA LETTER PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111B,
+ },
+ [0x1111C]={
+ category="lo",
+ description="CHAKMA LETTER PHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111C,
+ },
+ [0x1111D]={
+ category="lo",
+ description="CHAKMA LETTER BAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111D,
+ },
+ [0x1111E]={
+ category="lo",
+ description="CHAKMA LETTER BHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111E,
+ },
+ [0x1111F]={
+ category="lo",
+ description="CHAKMA LETTER MAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111F,
+ },
+ [0x11120]={
+ category="lo",
+ description="CHAKMA LETTER YYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11120,
+ },
+ [0x11121]={
+ category="lo",
+ description="CHAKMA LETTER YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11121,
+ },
+ [0x11122]={
+ category="lo",
+ description="CHAKMA LETTER RAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11122,
+ },
+ [0x11123]={
+ category="lo",
+ description="CHAKMA LETTER LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11123,
+ },
+ [0x11124]={
+ category="lo",
+ description="CHAKMA LETTER WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11124,
+ },
+ [0x11125]={
+ category="lo",
+ description="CHAKMA LETTER SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11125,
+ },
+ [0x11126]={
+ category="lo",
+ description="CHAKMA LETTER HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11126,
+ },
+ [0x11127]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11127,
+ },
+ [0x11128]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11128,
+ },
+ [0x11129]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11129,
+ },
+ [0x1112A]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112A,
+ },
+ [0x1112B]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112B,
+ },
+ [0x1112C]={
+ category="mc",
+ description="CHAKMA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1112C,
+ },
+ [0x1112D]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112D,
+ },
+ [0x1112E]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x11131, 0x11127 },
+ unicodeslot=0x1112E,
+ },
+ [0x1112F]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x11132, 0x11127 },
+ unicodeslot=0x1112F,
+ },
+ [0x11130]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN OI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11130,
+ },
+ [0x11131]={
+ category="mn",
+ description="CHAKMA O MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11131,
+ },
+ [0x11132]={
+ category="mn",
+ description="CHAKMA AU MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11132,
+ },
+ [0x11133]={
+ category="mn",
+ combining=0x9,
+ description="CHAKMA VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11133,
+ },
+ [0x11134]={
+ category="mn",
+ combining=0x9,
+ description="CHAKMA MAAYYAA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11134,
+ },
+ [0x11136]={
+ category="nd",
+ description="CHAKMA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11136,
+ },
+ [0x11137]={
+ category="nd",
+ description="CHAKMA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11137,
+ },
+ [0x11138]={
+ category="nd",
+ description="CHAKMA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11138,
+ },
+ [0x11139]={
+ category="nd",
+ description="CHAKMA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11139,
+ },
+ [0x1113A]={
+ category="nd",
+ description="CHAKMA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113A,
+ },
+ [0x1113B]={
+ category="nd",
+ description="CHAKMA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113B,
+ },
+ [0x1113C]={
+ category="nd",
+ description="CHAKMA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113C,
+ },
+ [0x1113D]={
+ category="nd",
+ description="CHAKMA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113D,
+ },
+ [0x1113E]={
+ category="nd",
+ description="CHAKMA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113E,
+ },
+ [0x1113F]={
+ category="nd",
+ description="CHAKMA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113F,
+ },
+ [0x11140]={
+ category="po",
+ description="CHAKMA SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11140,
+ },
+ [0x11141]={
+ category="po",
+ description="CHAKMA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11141,
+ },
+ [0x11142]={
+ category="po",
+ description="CHAKMA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11142,
+ },
+ [0x11143]={
+ category="po",
+ description="CHAKMA QUESTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11143,
+ },
+ [0x11150]={
+ category="lo",
+ description="MAHAJANI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11150,
+ },
+ [0x11151]={
+ category="lo",
+ description="MAHAJANI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11151,
+ },
+ [0x11152]={
+ category="lo",
+ description="MAHAJANI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11152,
+ },
+ [0x11153]={
+ category="lo",
+ description="MAHAJANI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11153,
+ },
+ [0x11154]={
+ category="lo",
+ description="MAHAJANI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11154,
+ },
+ [0x11155]={
+ category="lo",
+ description="MAHAJANI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11155,
+ },
+ [0x11156]={
+ category="lo",
+ description="MAHAJANI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11156,
+ },
+ [0x11157]={
+ category="lo",
+ description="MAHAJANI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11157,
+ },
+ [0x11158]={
+ category="lo",
+ description="MAHAJANI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11158,
+ },
+ [0x11159]={
+ category="lo",
+ description="MAHAJANI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11159,
+ },
+ [0x1115A]={
+ category="lo",
+ description="MAHAJANI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115A,
+ },
+ [0x1115B]={
+ category="lo",
+ description="MAHAJANI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115B,
+ },
+ [0x1115C]={
+ category="lo",
+ description="MAHAJANI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115C,
+ },
+ [0x1115D]={
+ category="lo",
+ description="MAHAJANI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115D,
+ },
+ [0x1115E]={
+ category="lo",
+ description="MAHAJANI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115E,
+ },
+ [0x1115F]={
+ category="lo",
+ description="MAHAJANI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1115F,
+ },
+ [0x11160]={
+ category="lo",
+ description="MAHAJANI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11160,
+ },
+ [0x11161]={
+ category="lo",
+ description="MAHAJANI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11161,
+ },
+ [0x11162]={
+ category="lo",
+ description="MAHAJANI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11162,
+ },
+ [0x11163]={
+ category="lo",
+ description="MAHAJANI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11163,
+ },
+ [0x11164]={
+ category="lo",
+ description="MAHAJANI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11164,
+ },
+ [0x11165]={
+ category="lo",
+ description="MAHAJANI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11165,
+ },
+ [0x11166]={
+ category="lo",
+ description="MAHAJANI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11166,
+ },
+ [0x11167]={
+ category="lo",
+ description="MAHAJANI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11167,
+ },
+ [0x11168]={
+ category="lo",
+ description="MAHAJANI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11168,
+ },
+ [0x11169]={
+ category="lo",
+ description="MAHAJANI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11169,
+ },
+ [0x1116A]={
+ category="lo",
+ description="MAHAJANI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116A,
+ },
+ [0x1116B]={
+ category="lo",
+ description="MAHAJANI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116B,
+ },
+ [0x1116C]={
+ category="lo",
+ description="MAHAJANI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116C,
+ },
+ [0x1116D]={
+ category="lo",
+ description="MAHAJANI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116D,
+ },
+ [0x1116E]={
+ category="lo",
+ description="MAHAJANI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116E,
+ },
+ [0x1116F]={
+ category="lo",
+ description="MAHAJANI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1116F,
+ },
+ [0x11170]={
+ category="lo",
+ description="MAHAJANI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11170,
+ },
+ [0x11171]={
+ category="lo",
+ description="MAHAJANI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11171,
+ },
+ [0x11172]={
+ category="lo",
+ description="MAHAJANI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11172,
+ },
+ [0x11173]={
+ category="mn",
+ combining=0x7,
+ description="MAHAJANI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11173,
+ },
+ [0x11174]={
+ category="po",
+ description="MAHAJANI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11174,
+ },
+ [0x11175]={
+ category="po",
+ description="MAHAJANI SECTION MARK",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0x11175,
+ },
+ [0x11176]={
+ category="lo",
+ description="MAHAJANI LIGATURE SHRI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11176,
+ },
+ [0x11180]={
+ category="mn",
+ description="SHARADA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11180,
+ },
+ [0x11181]={
+ category="mn",
+ description="SHARADA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11181,
+ },
+ [0x11182]={
+ category="mc",
+ description="SHARADA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11182,
+ },
+ [0x11183]={
+ category="lo",
+ description="SHARADA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11183,
+ },
+ [0x11184]={
+ category="lo",
+ description="SHARADA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11184,
+ },
+ [0x11185]={
+ category="lo",
+ description="SHARADA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11185,
+ },
+ [0x11186]={
+ category="lo",
+ description="SHARADA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11186,
+ },
+ [0x11187]={
+ category="lo",
+ description="SHARADA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11187,
+ },
+ [0x11188]={
+ category="lo",
+ description="SHARADA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11188,
+ },
+ [0x11189]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11189,
+ },
+ [0x1118A]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118A,
+ },
+ [0x1118B]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118B,
+ },
+ [0x1118C]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118C,
+ },
+ [0x1118D]={
+ category="lo",
+ description="SHARADA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118D,
+ },
+ [0x1118E]={
+ category="lo",
+ description="SHARADA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118E,
+ },
+ [0x1118F]={
+ category="lo",
+ description="SHARADA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118F,
+ },
+ [0x11190]={
+ category="lo",
+ description="SHARADA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11190,
+ },
+ [0x11191]={
+ category="lo",
+ description="SHARADA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11191,
+ },
+ [0x11192]={
+ category="lo",
+ description="SHARADA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11192,
+ },
+ [0x11193]={
+ category="lo",
+ description="SHARADA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11193,
+ },
+ [0x11194]={
+ category="lo",
+ description="SHARADA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11194,
+ },
+ [0x11195]={
+ category="lo",
+ description="SHARADA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11195,
+ },
+ [0x11196]={
+ category="lo",
+ description="SHARADA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11196,
+ },
+ [0x11197]={
+ category="lo",
+ description="SHARADA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11197,
+ },
+ [0x11198]={
+ category="lo",
+ description="SHARADA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11198,
+ },
+ [0x11199]={
+ category="lo",
+ description="SHARADA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11199,
+ },
+ [0x1119A]={
+ category="lo",
+ description="SHARADA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119A,
+ },
+ [0x1119B]={
+ category="lo",
+ description="SHARADA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119B,
+ },
+ [0x1119C]={
+ category="lo",
+ description="SHARADA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119C,
+ },
+ [0x1119D]={
+ category="lo",
+ description="SHARADA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119D,
+ },
+ [0x1119E]={
+ category="lo",
+ description="SHARADA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119E,
+ },
+ [0x1119F]={
+ category="lo",
+ description="SHARADA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119F,
+ },
+ [0x111A0]={
+ category="lo",
+ description="SHARADA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A0,
+ },
+ [0x111A1]={
+ category="lo",
+ description="SHARADA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A1,
+ },
+ [0x111A2]={
+ category="lo",
+ description="SHARADA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A2,
+ },
+ [0x111A3]={
+ category="lo",
+ description="SHARADA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A3,
+ },
+ [0x111A4]={
+ category="lo",
+ description="SHARADA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A4,
+ },
+ [0x111A5]={
+ category="lo",
+ description="SHARADA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A5,
+ },
+ [0x111A6]={
+ category="lo",
+ description="SHARADA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A6,
+ },
+ [0x111A7]={
+ category="lo",
+ description="SHARADA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A7,
+ },
+ [0x111A8]={
+ category="lo",
+ description="SHARADA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A8,
+ },
+ [0x111A9]={
+ category="lo",
+ description="SHARADA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A9,
+ },
+ [0x111AA]={
+ category="lo",
+ description="SHARADA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AA,
+ },
+ [0x111AB]={
+ category="lo",
+ description="SHARADA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AB,
+ },
+ [0x111AC]={
+ category="lo",
+ description="SHARADA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AC,
+ },
+ [0x111AD]={
+ category="lo",
+ description="SHARADA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AD,
+ },
+ [0x111AE]={
+ category="lo",
+ description="SHARADA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AE,
+ },
+ [0x111AF]={
+ category="lo",
+ description="SHARADA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AF,
+ },
+ [0x111B0]={
+ category="lo",
+ description="SHARADA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B0,
+ },
+ [0x111B1]={
+ category="lo",
+ description="SHARADA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B1,
+ },
+ [0x111B2]={
+ category="lo",
+ description="SHARADA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B2,
+ },
+ [0x111B3]={
+ category="mc",
+ description="SHARADA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B3,
+ },
+ [0x111B4]={
+ category="mc",
+ description="SHARADA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B4,
+ },
+ [0x111B5]={
+ category="mc",
+ description="SHARADA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B5,
+ },
+ [0x111B6]={
+ category="mn",
+ description="SHARADA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B6,
+ },
+ [0x111B7]={
+ category="mn",
+ description="SHARADA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B7,
+ },
+ [0x111B8]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B8,
+ },
+ [0x111B9]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B9,
+ },
+ [0x111BA]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BA,
+ },
+ [0x111BB]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BB,
+ },
+ [0x111BC]={
+ category="mn",
+ description="SHARADA VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BC,
+ },
+ [0x111BD]={
+ category="mn",
+ description="SHARADA VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BD,
+ },
+ [0x111BE]={
+ category="mn",
+ description="SHARADA VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BE,
+ },
+ [0x111BF]={
+ category="mc",
+ description="SHARADA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111BF,
+ },
+ [0x111C0]={
+ category="mc",
+ combining=0x9,
+ description="SHARADA SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111C0,
+ },
+ [0x111C1]={
+ category="lo",
+ description="SHARADA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C1,
+ },
+ [0x111C2]={
+ category="lo",
+ description="SHARADA SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C2,
+ },
+ [0x111C3]={
+ category="lo",
+ description="SHARADA SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C3,
+ },
+ [0x111C4]={
+ category="lo",
+ description="SHARADA OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C4,
+ },
+ [0x111C5]={
+ category="po",
+ description="SHARADA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C5,
+ },
+ [0x111C6]={
+ category="po",
+ description="SHARADA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C6,
+ },
+ [0x111C7]={
+ category="po",
+ description="SHARADA ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C7,
+ },
+ [0x111C8]={
+ category="po",
+ description="SHARADA SEPARATOR",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C8,
+ },
+ [0x111C9]={
+ category="po",
+ description="SHARADA SANDHI MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C9,
+ },
+ [0x111CA]={
+ category="mn",
+ combining=0x7,
+ description="SHARADA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111CA,
+ },
+ [0x111CB]={
+ category="mn",
+ description="SHARADA VOWEL MODIFIER MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111CB,
+ },
+ [0x111CC]={
+ category="mn",
+ description="SHARADA EXTRA SHORT VOWEL MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111CC,
+ },
+ [0x111CD]={
+ category="po",
+ description="SHARADA SUTRA MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111CD,
+ },
+ [0x111D0]={
+ category="nd",
+ description="SHARADA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D0,
+ },
+ [0x111D1]={
+ category="nd",
+ description="SHARADA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D1,
+ },
+ [0x111D2]={
+ category="nd",
+ description="SHARADA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D2,
+ },
+ [0x111D3]={
+ category="nd",
+ description="SHARADA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D3,
+ },
+ [0x111D4]={
+ category="nd",
+ description="SHARADA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D4,
+ },
+ [0x111D5]={
+ category="nd",
+ description="SHARADA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D5,
+ },
+ [0x111D6]={
+ category="nd",
+ description="SHARADA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D6,
+ },
+ [0x111D7]={
+ category="nd",
+ description="SHARADA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D7,
+ },
+ [0x111D8]={
+ category="nd",
+ description="SHARADA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D8,
+ },
+ [0x111D9]={
+ category="nd",
+ description="SHARADA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D9,
+ },
+ [0x111DA]={
+ category="lo",
+ description="SHARADA EKAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111DA,
+ },
+ [0x111DB]={
+ category="po",
+ description="SHARADA SIGN SIDDHAM",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0x111DB,
+ },
+ [0x111DC]={
+ category="lo",
+ description="SHARADA HEADSTROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111DC,
+ },
+ [0x111DD]={
+ category="po",
+ description="SHARADA CONTINUATION SIGN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111DD,
+ },
+ [0x111DE]={
+ category="po",
+ description="SHARADA SECTION MARK-1",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111DE,
+ },
+ [0x111DF]={
+ category="po",
+ description="SHARADA SECTION MARK-2",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111DF,
+ },
+ [0x111E1]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E1,
+ },
+ [0x111E2]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E2,
+ },
+ [0x111E3]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E3,
+ },
+ [0x111E4]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E4,
+ },
+ [0x111E5]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E5,
+ },
+ [0x111E6]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E6,
+ },
+ [0x111E7]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E7,
+ },
+ [0x111E8]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E8,
+ },
+ [0x111E9]={
+ category="no",
+ description="SINHALA ARCHAIC DIGIT NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111E9,
+ },
+ [0x111EA]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111EA,
+ },
+ [0x111EB]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER TWENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111EB,
+ },
+ [0x111EC]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER THIRTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111EC,
+ },
+ [0x111ED]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER FORTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111ED,
+ },
+ [0x111EE]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111EE,
+ },
+ [0x111EF]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER SIXTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111EF,
+ },
+ [0x111F0]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER SEVENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111F0,
+ },
+ [0x111F1]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER EIGHTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111F1,
+ },
+ [0x111F2]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER NINETY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111F2,
+ },
+ [0x111F3]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111F3,
+ },
+ [0x111F4]={
+ category="no",
+ description="SINHALA ARCHAIC NUMBER ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111F4,
+ },
+ [0x11200]={
+ category="lo",
+ description="KHOJKI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11200,
+ },
+ [0x11201]={
+ category="lo",
+ description="KHOJKI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11201,
+ },
+ [0x11202]={
+ category="lo",
+ description="KHOJKI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11202,
+ },
+ [0x11203]={
+ category="lo",
+ description="KHOJKI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11203,
+ },
+ [0x11204]={
+ category="lo",
+ description="KHOJKI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11204,
+ },
+ [0x11205]={
+ category="lo",
+ description="KHOJKI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11205,
+ },
+ [0x11206]={
+ category="lo",
+ description="KHOJKI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11206,
+ },
+ [0x11207]={
+ category="lo",
+ description="KHOJKI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11207,
+ },
+ [0x11208]={
+ category="lo",
+ description="KHOJKI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11208,
+ },
+ [0x11209]={
+ category="lo",
+ description="KHOJKI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11209,
+ },
+ [0x1120A]={
+ category="lo",
+ description="KHOJKI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120A,
+ },
+ [0x1120B]={
+ category="lo",
+ description="KHOJKI LETTER GGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120B,
+ },
+ [0x1120C]={
+ category="lo",
+ description="KHOJKI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120C,
+ },
+ [0x1120D]={
+ category="lo",
+ description="KHOJKI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120D,
+ },
+ [0x1120E]={
+ category="lo",
+ description="KHOJKI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120E,
+ },
+ [0x1120F]={
+ category="lo",
+ description="KHOJKI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1120F,
+ },
+ [0x11210]={
+ category="lo",
+ description="KHOJKI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11210,
+ },
+ [0x11211]={
+ category="lo",
+ description="KHOJKI LETTER JJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11211,
+ },
+ [0x11213]={
+ category="lo",
+ description="KHOJKI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11213,
+ },
+ [0x11214]={
+ category="lo",
+ description="KHOJKI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11214,
+ },
+ [0x11215]={
+ category="lo",
+ description="KHOJKI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11215,
+ },
+ [0x11216]={
+ category="lo",
+ description="KHOJKI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11216,
+ },
+ [0x11217]={
+ category="lo",
+ description="KHOJKI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11217,
+ },
+ [0x11218]={
+ category="lo",
+ description="KHOJKI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11218,
+ },
+ [0x11219]={
+ category="lo",
+ description="KHOJKI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11219,
+ },
+ [0x1121A]={
+ category="lo",
+ description="KHOJKI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121A,
+ },
+ [0x1121B]={
+ category="lo",
+ description="KHOJKI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121B,
+ },
+ [0x1121C]={
+ category="lo",
+ description="KHOJKI LETTER DDDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121C,
+ },
+ [0x1121D]={
+ category="lo",
+ description="KHOJKI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121D,
+ },
+ [0x1121E]={
+ category="lo",
+ description="KHOJKI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121E,
+ },
+ [0x1121F]={
+ category="lo",
+ description="KHOJKI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1121F,
+ },
+ [0x11220]={
+ category="lo",
+ description="KHOJKI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11220,
+ },
+ [0x11221]={
+ category="lo",
+ description="KHOJKI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11221,
+ },
+ [0x11222]={
+ category="lo",
+ description="KHOJKI LETTER BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11222,
+ },
+ [0x11223]={
+ category="lo",
+ description="KHOJKI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11223,
+ },
+ [0x11224]={
+ category="lo",
+ description="KHOJKI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11224,
+ },
+ [0x11225]={
+ category="lo",
+ description="KHOJKI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11225,
+ },
+ [0x11226]={
+ category="lo",
+ description="KHOJKI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11226,
+ },
+ [0x11227]={
+ category="lo",
+ description="KHOJKI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11227,
+ },
+ [0x11228]={
+ category="lo",
+ description="KHOJKI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11228,
+ },
+ [0x11229]={
+ category="lo",
+ description="KHOJKI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11229,
+ },
+ [0x1122A]={
+ category="lo",
+ description="KHOJKI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1122A,
+ },
+ [0x1122B]={
+ category="lo",
+ description="KHOJKI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1122B,
+ },
+ [0x1122C]={
+ category="mc",
+ description="KHOJKI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1122C,
+ },
+ [0x1122D]={
+ category="mc",
+ description="KHOJKI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1122D,
+ },
+ [0x1122E]={
+ category="mc",
+ description="KHOJKI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1122E,
+ },
+ [0x1122F]={
+ category="mn",
+ description="KHOJKI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1122F,
+ },
+ [0x11230]={
+ category="mn",
+ description="KHOJKI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11230,
+ },
+ [0x11231]={
+ category="mn",
+ description="KHOJKI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11231,
+ },
+ [0x11232]={
+ category="mc",
+ description="KHOJKI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11232,
+ },
+ [0x11233]={
+ category="mc",
+ description="KHOJKI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11233,
+ },
+ [0x11234]={
+ category="mn",
+ description="KHOJKI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11234,
+ },
+ [0x11235]={
+ category="mc",
+ combining=0x9,
+ description="KHOJKI SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11235,
+ },
+ [0x11236]={
+ category="mn",
+ combining=0x7,
+ description="KHOJKI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11236,
+ },
+ [0x11237]={
+ category="mn",
+ description="KHOJKI SIGN SHADDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11237,
+ },
+ [0x11238]={
+ category="po",
+ description="KHOJKI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11238,
+ },
+ [0x11239]={
+ category="po",
+ description="KHOJKI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11239,
+ },
+ [0x1123A]={
+ category="po",
+ description="KHOJKI WORD SEPARATOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1123A,
+ },
+ [0x1123B]={
+ category="po",
+ description="KHOJKI SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1123B,
+ },
+ [0x1123C]={
+ category="po",
+ description="KHOJKI DOUBLE SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1123C,
+ },
+ [0x1123D]={
+ category="po",
+ description="KHOJKI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1123D,
+ },
+ [0x11280]={
+ category="lo",
+ description="MULTANI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11280,
+ },
+ [0x11281]={
+ category="lo",
+ description="MULTANI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11281,
+ },
+ [0x11282]={
+ category="lo",
+ description="MULTANI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11282,
+ },
+ [0x11283]={
+ category="lo",
+ description="MULTANI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11283,
+ },
+ [0x11284]={
+ category="lo",
+ description="MULTANI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11284,
+ },
+ [0x11285]={
+ category="lo",
+ description="MULTANI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11285,
+ },
+ [0x11286]={
+ category="lo",
+ description="MULTANI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11286,
+ },
+ [0x11288]={
+ category="lo",
+ description="MULTANI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11288,
+ },
+ [0x1128A]={
+ category="lo",
+ description="MULTANI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1128A,
+ },
+ [0x1128B]={
+ category="lo",
+ description="MULTANI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1128B,
+ },
+ [0x1128C]={
+ category="lo",
+ description="MULTANI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1128C,
+ },
+ [0x1128D]={
+ category="lo",
+ description="MULTANI LETTER JJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1128D,
+ },
+ [0x1128F]={
+ category="lo",
+ description="MULTANI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1128F,
+ },
+ [0x11290]={
+ category="lo",
+ description="MULTANI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11290,
+ },
+ [0x11291]={
+ category="lo",
+ description="MULTANI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11291,
+ },
+ [0x11292]={
+ category="lo",
+ description="MULTANI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11292,
+ },
+ [0x11293]={
+ category="lo",
+ description="MULTANI LETTER DDDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11293,
+ },
+ [0x11294]={
+ category="lo",
+ description="MULTANI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11294,
+ },
+ [0x11295]={
+ category="lo",
+ description="MULTANI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11295,
+ },
+ [0x11296]={
+ category="lo",
+ description="MULTANI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11296,
+ },
+ [0x11297]={
+ category="lo",
+ description="MULTANI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11297,
+ },
+ [0x11298]={
+ category="lo",
+ description="MULTANI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11298,
+ },
+ [0x11299]={
+ category="lo",
+ description="MULTANI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11299,
+ },
+ [0x1129A]={
+ category="lo",
+ description="MULTANI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1129A,
+ },
+ [0x1129B]={
+ category="lo",
+ description="MULTANI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1129B,
+ },
+ [0x1129C]={
+ category="lo",
+ description="MULTANI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1129C,
+ },
+ [0x1129D]={
+ category="lo",
+ description="MULTANI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1129D,
+ },
+ [0x1129F]={
+ category="lo",
+ description="MULTANI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1129F,
+ },
+ [0x112A0]={
+ category="lo",
+ description="MULTANI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A0,
+ },
+ [0x112A1]={
+ category="lo",
+ description="MULTANI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A1,
+ },
+ [0x112A2]={
+ category="lo",
+ description="MULTANI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A2,
+ },
+ [0x112A3]={
+ category="lo",
+ description="MULTANI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A3,
+ },
+ [0x112A4]={
+ category="lo",
+ description="MULTANI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A4,
+ },
+ [0x112A5]={
+ category="lo",
+ description="MULTANI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A5,
+ },
+ [0x112A6]={
+ category="lo",
+ description="MULTANI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A6,
+ },
+ [0x112A7]={
+ category="lo",
+ description="MULTANI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A7,
+ },
+ [0x112A8]={
+ category="lo",
+ description="MULTANI LETTER RHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112A8,
+ },
+ [0x112A9]={
+ category="po",
+ description="MULTANI SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x112A9,
+ },
+ [0x112B0]={
+ category="lo",
+ description="KHUDAWADI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B0,
+ },
+ [0x112B1]={
+ category="lo",
+ description="KHUDAWADI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B1,
+ },
+ [0x112B2]={
+ category="lo",
+ description="KHUDAWADI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B2,
+ },
+ [0x112B3]={
+ category="lo",
+ description="KHUDAWADI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B3,
+ },
+ [0x112B4]={
+ category="lo",
+ description="KHUDAWADI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B4,
+ },
+ [0x112B5]={
+ category="lo",
+ description="KHUDAWADI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B5,
+ },
+ [0x112B6]={
+ category="lo",
+ description="KHUDAWADI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B6,
+ },
+ [0x112B7]={
+ category="lo",
+ description="KHUDAWADI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B7,
+ },
+ [0x112B8]={
+ category="lo",
+ description="KHUDAWADI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B8,
+ },
+ [0x112B9]={
+ category="lo",
+ description="KHUDAWADI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112B9,
+ },
+ [0x112BA]={
+ category="lo",
+ description="KHUDAWADI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BA,
+ },
+ [0x112BB]={
+ category="lo",
+ description="KHUDAWADI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BB,
+ },
+ [0x112BC]={
+ category="lo",
+ description="KHUDAWADI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BC,
+ },
+ [0x112BD]={
+ category="lo",
+ description="KHUDAWADI LETTER GGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BD,
+ },
+ [0x112BE]={
+ category="lo",
+ description="KHUDAWADI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BE,
+ },
+ [0x112BF]={
+ category="lo",
+ description="KHUDAWADI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112BF,
+ },
+ [0x112C0]={
+ category="lo",
+ description="KHUDAWADI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C0,
+ },
+ [0x112C1]={
+ category="lo",
+ description="KHUDAWADI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C1,
+ },
+ [0x112C2]={
+ category="lo",
+ description="KHUDAWADI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C2,
+ },
+ [0x112C3]={
+ category="lo",
+ description="KHUDAWADI LETTER JJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C3,
+ },
+ [0x112C4]={
+ category="lo",
+ description="KHUDAWADI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C4,
+ },
+ [0x112C5]={
+ category="lo",
+ description="KHUDAWADI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C5,
+ },
+ [0x112C6]={
+ category="lo",
+ description="KHUDAWADI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C6,
+ },
+ [0x112C7]={
+ category="lo",
+ description="KHUDAWADI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C7,
+ },
+ [0x112C8]={
+ category="lo",
+ description="KHUDAWADI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C8,
+ },
+ [0x112C9]={
+ category="lo",
+ description="KHUDAWADI LETTER DDDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112C9,
+ },
+ [0x112CA]={
+ category="lo",
+ description="KHUDAWADI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CA,
+ },
+ [0x112CB]={
+ category="lo",
+ description="KHUDAWADI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CB,
+ },
+ [0x112CC]={
+ category="lo",
+ description="KHUDAWADI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CC,
+ },
+ [0x112CD]={
+ category="lo",
+ description="KHUDAWADI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CD,
+ },
+ [0x112CE]={
+ category="lo",
+ description="KHUDAWADI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CE,
+ },
+ [0x112CF]={
+ category="lo",
+ description="KHUDAWADI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112CF,
+ },
+ [0x112D0]={
+ category="lo",
+ description="KHUDAWADI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D0,
+ },
+ [0x112D1]={
+ category="lo",
+ description="KHUDAWADI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D1,
+ },
+ [0x112D2]={
+ category="lo",
+ description="KHUDAWADI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D2,
+ },
+ [0x112D3]={
+ category="lo",
+ description="KHUDAWADI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D3,
+ },
+ [0x112D4]={
+ category="lo",
+ description="KHUDAWADI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D4,
+ },
+ [0x112D5]={
+ category="lo",
+ description="KHUDAWADI LETTER BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D5,
+ },
+ [0x112D6]={
+ category="lo",
+ description="KHUDAWADI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D6,
+ },
+ [0x112D7]={
+ category="lo",
+ description="KHUDAWADI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D7,
+ },
+ [0x112D8]={
+ category="lo",
+ description="KHUDAWADI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D8,
+ },
+ [0x112D9]={
+ category="lo",
+ description="KHUDAWADI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112D9,
+ },
+ [0x112DA]={
+ category="lo",
+ description="KHUDAWADI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112DA,
+ },
+ [0x112DB]={
+ category="lo",
+ description="KHUDAWADI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112DB,
+ },
+ [0x112DC]={
+ category="lo",
+ description="KHUDAWADI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112DC,
+ },
+ [0x112DD]={
+ category="lo",
+ description="KHUDAWADI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112DD,
+ },
+ [0x112DE]={
+ category="lo",
+ description="KHUDAWADI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x112DE,
+ },
+ [0x112DF]={
+ category="mn",
+ description="KHUDAWADI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112DF,
+ },
+ [0x112E0]={
+ category="mc",
+ description="KHUDAWADI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x112E0,
+ },
+ [0x112E1]={
+ category="mc",
+ description="KHUDAWADI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x112E1,
+ },
+ [0x112E2]={
+ category="mc",
+ description="KHUDAWADI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x112E2,
+ },
+ [0x112E3]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E3,
+ },
+ [0x112E4]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E4,
+ },
+ [0x112E5]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E5,
+ },
+ [0x112E6]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E6,
+ },
+ [0x112E7]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E7,
+ },
+ [0x112E8]={
+ category="mn",
+ description="KHUDAWADI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E8,
+ },
+ [0x112E9]={
+ category="mn",
+ combining=0x7,
+ description="KHUDAWADI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112E9,
+ },
+ [0x112EA]={
+ category="mn",
+ combining=0x9,
+ description="KHUDAWADI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x112EA,
+ },
+ [0x112F0]={
+ category="nd",
+ description="KHUDAWADI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F0,
+ },
+ [0x112F1]={
+ category="nd",
+ description="KHUDAWADI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F1,
+ },
+ [0x112F2]={
+ category="nd",
+ description="KHUDAWADI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F2,
+ },
+ [0x112F3]={
+ category="nd",
+ description="KHUDAWADI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F3,
+ },
+ [0x112F4]={
+ category="nd",
+ description="KHUDAWADI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F4,
+ },
+ [0x112F5]={
+ category="nd",
+ description="KHUDAWADI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F5,
+ },
+ [0x112F6]={
+ category="nd",
+ description="KHUDAWADI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F6,
+ },
+ [0x112F7]={
+ category="nd",
+ description="KHUDAWADI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F7,
+ },
+ [0x112F8]={
+ category="nd",
+ description="KHUDAWADI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F8,
+ },
+ [0x112F9]={
+ category="nd",
+ description="KHUDAWADI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x112F9,
+ },
+ [0x11300]={
+ category="mn",
+ description="GRANTHA SIGN COMBINING ANUSVARA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11300,
+ },
+ [0x11301]={
+ category="mn",
+ description="GRANTHA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11301,
+ },
+ [0x11302]={
+ category="mc",
+ description="GRANTHA SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11302,
+ },
+ [0x11303]={
+ category="mc",
+ description="GRANTHA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11303,
+ },
+ [0x11305]={
+ category="lo",
+ description="GRANTHA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11305,
+ },
+ [0x11306]={
+ category="lo",
+ description="GRANTHA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11306,
+ },
+ [0x11307]={
+ category="lo",
+ description="GRANTHA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11307,
+ },
+ [0x11308]={
+ category="lo",
+ description="GRANTHA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11308,
+ },
+ [0x11309]={
+ category="lo",
+ description="GRANTHA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11309,
+ },
+ [0x1130A]={
+ category="lo",
+ description="GRANTHA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1130A,
+ },
+ [0x1130B]={
+ category="lo",
+ description="GRANTHA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1130B,
+ },
+ [0x1130C]={
+ category="lo",
+ description="GRANTHA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1130C,
+ },
+ [0x1130F]={
+ category="lo",
+ description="GRANTHA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1130F,
+ },
+ [0x11310]={
+ category="lo",
+ description="GRANTHA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11310,
+ },
+ [0x11313]={
+ category="lo",
+ description="GRANTHA LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11313,
+ },
+ [0x11314]={
+ category="lo",
+ description="GRANTHA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11314,
+ },
+ [0x11315]={
+ category="lo",
+ description="GRANTHA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11315,
+ },
+ [0x11316]={
+ category="lo",
+ description="GRANTHA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11316,
+ },
+ [0x11317]={
+ category="lo",
+ description="GRANTHA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11317,
+ },
+ [0x11318]={
+ category="lo",
+ description="GRANTHA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11318,
+ },
+ [0x11319]={
+ category="lo",
+ description="GRANTHA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11319,
+ },
+ [0x1131A]={
+ category="lo",
+ description="GRANTHA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131A,
+ },
+ [0x1131B]={
+ category="lo",
+ description="GRANTHA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131B,
+ },
+ [0x1131C]={
+ category="lo",
+ description="GRANTHA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131C,
+ },
+ [0x1131D]={
+ category="lo",
+ description="GRANTHA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131D,
+ },
+ [0x1131E]={
+ category="lo",
+ description="GRANTHA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131E,
+ },
+ [0x1131F]={
+ category="lo",
+ description="GRANTHA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1131F,
+ },
+ [0x11320]={
+ category="lo",
+ description="GRANTHA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11320,
+ },
+ [0x11321]={
+ category="lo",
+ description="GRANTHA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11321,
+ },
+ [0x11322]={
+ category="lo",
+ description="GRANTHA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11322,
+ },
+ [0x11323]={
+ category="lo",
+ description="GRANTHA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11323,
+ },
+ [0x11324]={
+ category="lo",
+ description="GRANTHA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11324,
+ },
+ [0x11325]={
+ category="lo",
+ description="GRANTHA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11325,
+ },
+ [0x11326]={
+ category="lo",
+ description="GRANTHA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11326,
+ },
+ [0x11327]={
+ category="lo",
+ description="GRANTHA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11327,
+ },
+ [0x11328]={
+ category="lo",
+ description="GRANTHA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11328,
+ },
+ [0x1132A]={
+ category="lo",
+ description="GRANTHA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132A,
+ },
+ [0x1132B]={
+ category="lo",
+ description="GRANTHA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132B,
+ },
+ [0x1132C]={
+ category="lo",
+ description="GRANTHA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132C,
+ },
+ [0x1132D]={
+ category="lo",
+ description="GRANTHA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132D,
+ },
+ [0x1132E]={
+ category="lo",
+ description="GRANTHA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132E,
+ },
+ [0x1132F]={
+ category="lo",
+ description="GRANTHA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1132F,
+ },
+ [0x11330]={
+ category="lo",
+ description="GRANTHA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11330,
+ },
+ [0x11332]={
+ category="lo",
+ description="GRANTHA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11332,
+ },
+ [0x11333]={
+ category="lo",
+ description="GRANTHA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11333,
+ },
+ [0x11335]={
+ category="lo",
+ description="GRANTHA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11335,
+ },
+ [0x11336]={
+ category="lo",
+ description="GRANTHA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11336,
+ },
+ [0x11337]={
+ category="lo",
+ description="GRANTHA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11337,
+ },
+ [0x11338]={
+ category="lo",
+ description="GRANTHA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11338,
+ },
+ [0x11339]={
+ category="lo",
+ description="GRANTHA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11339,
+ },
+ [0x1133C]={
+ category="mn",
+ combining=0x7,
+ description="GRANTHA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1133C,
+ },
+ [0x1133D]={
+ category="lo",
+ description="GRANTHA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1133D,
+ },
+ [0x1133E]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1133E,
+ },
+ [0x1133F]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1133F,
+ },
+ [0x11340]={
+ category="mn",
+ description="GRANTHA VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11340,
+ },
+ [0x11341]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11341,
+ },
+ [0x11342]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11342,
+ },
+ [0x11343]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11343,
+ },
+ [0x11344]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11344,
+ },
+ [0x11347]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11347,
+ },
+ [0x11348]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11348,
+ },
+ [0x1134B]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x11347, 0x1133E },
+ unicodeslot=0x1134B,
+ },
+ [0x1134C]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x11347, 0x11357 },
+ unicodeslot=0x1134C,
+ },
+ [0x1134D]={
+ category="mc",
+ combining=0x9,
+ description="GRANTHA SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1134D,
+ },
+ [0x11350]={
+ category="lo",
+ description="GRANTHA OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11350,
+ },
+ [0x11357]={
+ category="mc",
+ description="GRANTHA AU LENGTH MARK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11357,
+ },
+ [0x1135D]={
+ category="lo",
+ description="GRANTHA SIGN PLUTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1135D,
+ },
+ [0x1135E]={
+ category="lo",
+ description="GRANTHA LETTER VEDIC ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1135E,
+ },
+ [0x1135F]={
+ category="lo",
+ description="GRANTHA LETTER VEDIC DOUBLE ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1135F,
+ },
+ [0x11360]={
+ category="lo",
+ description="GRANTHA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11360,
+ },
+ [0x11361]={
+ category="lo",
+ description="GRANTHA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11361,
+ },
+ [0x11362]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN VOCALIC L",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11362,
+ },
+ [0x11363]={
+ category="mc",
+ description="GRANTHA VOWEL SIGN VOCALIC LL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11363,
+ },
+ [0x11366]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT ZERO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11366,
+ },
+ [0x11367]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT ONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11367,
+ },
+ [0x11368]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT TWO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11368,
+ },
+ [0x11369]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT THREE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11369,
+ },
+ [0x1136A]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT FOUR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1136A,
+ },
+ [0x1136B]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT FIVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1136B,
+ },
+ [0x1136C]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA DIGIT SIX",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1136C,
+ },
+ [0x11370]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11370,
+ },
+ [0x11371]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11371,
+ },
+ [0x11372]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA LETTER NA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11372,
+ },
+ [0x11373]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA LETTER VI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11373,
+ },
+ [0x11374]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GRANTHA LETTER PA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11374,
+ },
+ [0x11480]={
+ category="lo",
+ description="TIRHUTA ANJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11480,
+ },
+ [0x11481]={
+ category="lo",
+ description="TIRHUTA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11481,
+ },
+ [0x11482]={
+ category="lo",
+ description="TIRHUTA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11482,
+ },
+ [0x11483]={
+ category="lo",
+ description="TIRHUTA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11483,
+ },
+ [0x11484]={
+ category="lo",
+ description="TIRHUTA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11484,
+ },
+ [0x11485]={
+ category="lo",
+ description="TIRHUTA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11485,
+ },
+ [0x11486]={
+ category="lo",
+ description="TIRHUTA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11486,
+ },
+ [0x11487]={
+ category="lo",
+ description="TIRHUTA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11487,
+ },
+ [0x11488]={
+ category="lo",
+ description="TIRHUTA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11488,
+ },
+ [0x11489]={
+ category="lo",
+ description="TIRHUTA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11489,
+ },
+ [0x1148A]={
+ category="lo",
+ description="TIRHUTA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148A,
+ },
+ [0x1148B]={
+ category="lo",
+ description="TIRHUTA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148B,
+ },
+ [0x1148C]={
+ category="lo",
+ description="TIRHUTA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148C,
+ },
+ [0x1148D]={
+ category="lo",
+ description="TIRHUTA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148D,
+ },
+ [0x1148E]={
+ category="lo",
+ description="TIRHUTA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148E,
+ },
+ [0x1148F]={
+ category="lo",
+ description="TIRHUTA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1148F,
+ },
+ [0x11490]={
+ category="lo",
+ description="TIRHUTA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11490,
+ },
+ [0x11491]={
+ category="lo",
+ description="TIRHUTA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11491,
+ },
+ [0x11492]={
+ category="lo",
+ description="TIRHUTA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11492,
+ },
+ [0x11493]={
+ category="lo",
+ description="TIRHUTA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11493,
+ },
+ [0x11494]={
+ category="lo",
+ description="TIRHUTA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11494,
+ },
+ [0x11495]={
+ category="lo",
+ description="TIRHUTA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11495,
+ },
+ [0x11496]={
+ category="lo",
+ description="TIRHUTA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11496,
+ },
+ [0x11497]={
+ category="lo",
+ description="TIRHUTA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11497,
+ },
+ [0x11498]={
+ category="lo",
+ description="TIRHUTA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11498,
+ },
+ [0x11499]={
+ category="lo",
+ description="TIRHUTA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11499,
+ },
+ [0x1149A]={
+ category="lo",
+ description="TIRHUTA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149A,
+ },
+ [0x1149B]={
+ category="lo",
+ description="TIRHUTA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149B,
+ },
+ [0x1149C]={
+ category="lo",
+ description="TIRHUTA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149C,
+ },
+ [0x1149D]={
+ category="lo",
+ description="TIRHUTA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149D,
+ },
+ [0x1149E]={
+ category="lo",
+ description="TIRHUTA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149E,
+ },
+ [0x1149F]={
+ category="lo",
+ description="TIRHUTA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1149F,
+ },
+ [0x114A0]={
+ category="lo",
+ description="TIRHUTA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A0,
+ },
+ [0x114A1]={
+ category="lo",
+ description="TIRHUTA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A1,
+ },
+ [0x114A2]={
+ category="lo",
+ description="TIRHUTA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A2,
+ },
+ [0x114A3]={
+ category="lo",
+ description="TIRHUTA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A3,
+ },
+ [0x114A4]={
+ category="lo",
+ description="TIRHUTA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A4,
+ },
+ [0x114A5]={
+ category="lo",
+ description="TIRHUTA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A5,
+ },
+ [0x114A6]={
+ category="lo",
+ description="TIRHUTA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A6,
+ },
+ [0x114A7]={
+ category="lo",
+ description="TIRHUTA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A7,
+ },
+ [0x114A8]={
+ category="lo",
+ description="TIRHUTA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A8,
+ },
+ [0x114A9]={
+ category="lo",
+ description="TIRHUTA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114A9,
+ },
+ [0x114AA]={
+ category="lo",
+ description="TIRHUTA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AA,
+ },
+ [0x114AB]={
+ category="lo",
+ description="TIRHUTA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AB,
+ },
+ [0x114AC]={
+ category="lo",
+ description="TIRHUTA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AC,
+ },
+ [0x114AD]={
+ category="lo",
+ description="TIRHUTA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AD,
+ },
+ [0x114AE]={
+ category="lo",
+ description="TIRHUTA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AE,
+ },
+ [0x114AF]={
+ category="lo",
+ description="TIRHUTA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114AF,
+ },
+ [0x114B0]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114B0,
+ },
+ [0x114B1]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114B1,
+ },
+ [0x114B2]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114B2,
+ },
+ [0x114B3]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B3,
+ },
+ [0x114B4]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B4,
+ },
+ [0x114B5]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B5,
+ },
+ [0x114B6]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B6,
+ },
+ [0x114B7]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B7,
+ },
+ [0x114B8]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114B8,
+ },
+ [0x114B9]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114B9,
+ },
+ [0x114BA]={
+ category="mn",
+ description="TIRHUTA VOWEL SIGN SHORT E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114BA,
+ },
+ [0x114BB]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x114B9, 0x114BA },
+ unicodeslot=0x114BB,
+ },
+ [0x114BC]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x114B9, 0x114B0 },
+ unicodeslot=0x114BC,
+ },
+ [0x114BD]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN SHORT O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114BD,
+ },
+ [0x114BE]={
+ category="mc",
+ description="TIRHUTA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x114B9, 0x114BD },
+ unicodeslot=0x114BE,
+ },
+ [0x114BF]={
+ category="mn",
+ description="TIRHUTA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114BF,
+ },
+ [0x114C0]={
+ category="mn",
+ description="TIRHUTA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114C0,
+ },
+ [0x114C1]={
+ category="mc",
+ description="TIRHUTA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x114C1,
+ },
+ [0x114C2]={
+ category="mn",
+ combining=0x9,
+ description="TIRHUTA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114C2,
+ },
+ [0x114C3]={
+ category="mn",
+ combining=0x7,
+ description="TIRHUTA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x114C3,
+ },
+ [0x114C4]={
+ category="lo",
+ description="TIRHUTA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114C4,
+ },
+ [0x114C5]={
+ category="lo",
+ description="TIRHUTA GVANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114C5,
+ },
+ [0x114C6]={
+ category="po",
+ description="TIRHUTA ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114C6,
+ },
+ [0x114C7]={
+ category="lo",
+ description="TIRHUTA OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x114C7,
+ },
+ [0x114D0]={
+ category="nd",
+ description="TIRHUTA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D0,
+ },
+ [0x114D1]={
+ category="nd",
+ description="TIRHUTA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D1,
+ },
+ [0x114D2]={
+ category="nd",
+ description="TIRHUTA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D2,
+ },
+ [0x114D3]={
+ category="nd",
+ description="TIRHUTA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D3,
+ },
+ [0x114D4]={
+ category="nd",
+ description="TIRHUTA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D4,
+ },
+ [0x114D5]={
+ category="nd",
+ description="TIRHUTA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D5,
+ },
+ [0x114D6]={
+ category="nd",
+ description="TIRHUTA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D6,
+ },
+ [0x114D7]={
+ category="nd",
+ description="TIRHUTA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D7,
+ },
+ [0x114D8]={
+ category="nd",
+ description="TIRHUTA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D8,
+ },
+ [0x114D9]={
+ category="nd",
+ description="TIRHUTA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x114D9,
+ },
+ [0x11580]={
+ category="lo",
+ description="SIDDHAM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11580,
+ },
+ [0x11581]={
+ category="lo",
+ description="SIDDHAM LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11581,
+ },
+ [0x11582]={
+ category="lo",
+ description="SIDDHAM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11582,
+ },
+ [0x11583]={
+ category="lo",
+ description="SIDDHAM LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11583,
+ },
+ [0x11584]={
+ category="lo",
+ description="SIDDHAM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11584,
+ },
+ [0x11585]={
+ category="lo",
+ description="SIDDHAM LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11585,
+ },
+ [0x11586]={
+ category="lo",
+ description="SIDDHAM LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11586,
+ },
+ [0x11587]={
+ category="lo",
+ description="SIDDHAM LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11587,
+ },
+ [0x11588]={
+ category="lo",
+ description="SIDDHAM LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11588,
+ },
+ [0x11589]={
+ category="lo",
+ description="SIDDHAM LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11589,
+ },
+ [0x1158A]={
+ category="lo",
+ description="SIDDHAM LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158A,
+ },
+ [0x1158B]={
+ category="lo",
+ description="SIDDHAM LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158B,
+ },
+ [0x1158C]={
+ category="lo",
+ description="SIDDHAM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158C,
+ },
+ [0x1158D]={
+ category="lo",
+ description="SIDDHAM LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158D,
+ },
+ [0x1158E]={
+ category="lo",
+ description="SIDDHAM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158E,
+ },
+ [0x1158F]={
+ category="lo",
+ description="SIDDHAM LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1158F,
+ },
+ [0x11590]={
+ category="lo",
+ description="SIDDHAM LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11590,
+ },
+ [0x11591]={
+ category="lo",
+ description="SIDDHAM LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11591,
+ },
+ [0x11592]={
+ category="lo",
+ description="SIDDHAM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11592,
+ },
+ [0x11593]={
+ category="lo",
+ description="SIDDHAM LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11593,
+ },
+ [0x11594]={
+ category="lo",
+ description="SIDDHAM LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11594,
+ },
+ [0x11595]={
+ category="lo",
+ description="SIDDHAM LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11595,
+ },
+ [0x11596]={
+ category="lo",
+ description="SIDDHAM LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11596,
+ },
+ [0x11597]={
+ category="lo",
+ description="SIDDHAM LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11597,
+ },
+ [0x11598]={
+ category="lo",
+ description="SIDDHAM LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11598,
+ },
+ [0x11599]={
+ category="lo",
+ description="SIDDHAM LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11599,
+ },
+ [0x1159A]={
+ category="lo",
+ description="SIDDHAM LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159A,
+ },
+ [0x1159B]={
+ category="lo",
+ description="SIDDHAM LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159B,
+ },
+ [0x1159C]={
+ category="lo",
+ description="SIDDHAM LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159C,
+ },
+ [0x1159D]={
+ category="lo",
+ description="SIDDHAM LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159D,
+ },
+ [0x1159E]={
+ category="lo",
+ description="SIDDHAM LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159E,
+ },
+ [0x1159F]={
+ category="lo",
+ description="SIDDHAM LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1159F,
+ },
+ [0x115A0]={
+ category="lo",
+ description="SIDDHAM LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A0,
+ },
+ [0x115A1]={
+ category="lo",
+ description="SIDDHAM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A1,
+ },
+ [0x115A2]={
+ category="lo",
+ description="SIDDHAM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A2,
+ },
+ [0x115A3]={
+ category="lo",
+ description="SIDDHAM LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A3,
+ },
+ [0x115A4]={
+ category="lo",
+ description="SIDDHAM LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A4,
+ },
+ [0x115A5]={
+ category="lo",
+ description="SIDDHAM LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A5,
+ },
+ [0x115A6]={
+ category="lo",
+ description="SIDDHAM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A6,
+ },
+ [0x115A7]={
+ category="lo",
+ description="SIDDHAM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A7,
+ },
+ [0x115A8]={
+ category="lo",
+ description="SIDDHAM LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A8,
+ },
+ [0x115A9]={
+ category="lo",
+ description="SIDDHAM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115A9,
+ },
+ [0x115AA]={
+ category="lo",
+ description="SIDDHAM LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115AA,
+ },
+ [0x115AB]={
+ category="lo",
+ description="SIDDHAM LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115AB,
+ },
+ [0x115AC]={
+ category="lo",
+ description="SIDDHAM LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115AC,
+ },
+ [0x115AD]={
+ category="lo",
+ description="SIDDHAM LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115AD,
+ },
+ [0x115AE]={
+ category="lo",
+ description="SIDDHAM LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115AE,
+ },
+ [0x115AF]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115AF,
+ },
+ [0x115B0]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115B0,
+ },
+ [0x115B1]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115B1,
+ },
+ [0x115B2]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115B2,
+ },
+ [0x115B3]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115B3,
+ },
+ [0x115B4]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115B4,
+ },
+ [0x115B5]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115B5,
+ },
+ [0x115B8]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115B8,
+ },
+ [0x115B9]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115B9,
+ },
+ [0x115BA]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x115B8, 0x115AF },
+ unicodeslot=0x115BA,
+ },
+ [0x115BB]={
+ category="mc",
+ description="SIDDHAM VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ specials={ "char", 0x115B9, 0x115AF },
+ unicodeslot=0x115BB,
+ },
+ [0x115BC]={
+ category="mn",
+ description="SIDDHAM SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115BC,
+ },
+ [0x115BD]={
+ category="mn",
+ description="SIDDHAM SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115BD,
+ },
+ [0x115BE]={
+ category="mc",
+ description="SIDDHAM SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x115BE,
+ },
+ [0x115BF]={
+ category="mn",
+ combining=0x9,
+ description="SIDDHAM SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115BF,
+ },
+ [0x115C0]={
+ category="mn",
+ combining=0x7,
+ description="SIDDHAM SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115C0,
+ },
+ [0x115C1]={
+ category="po",
+ description="SIDDHAM SIGN SIDDHAM",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0x115C1,
+ },
+ [0x115C2]={
+ category="po",
+ description="SIDDHAM DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115C2,
+ },
+ [0x115C3]={
+ category="po",
+ description="SIDDHAM DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115C3,
+ },
+ [0x115C4]={
+ category="po",
+ description="SIDDHAM SEPARATOR DOT",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0x115C4,
+ },
+ [0x115C5]={
+ category="po",
+ description="SIDDHAM SEPARATOR BAR",
+ direction="l",
+ linebreak="ex",
+ unicodeslot=0x115C5,
+ },
+ [0x115C6]={
+ category="po",
+ description="SIDDHAM REPETITION MARK-1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115C6,
+ },
+ [0x115C7]={
+ category="po",
+ description="SIDDHAM REPETITION MARK-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115C7,
+ },
+ [0x115C8]={
+ category="po",
+ description="SIDDHAM REPETITION MARK-3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115C8,
+ },
+ [0x115C9]={
+ category="po",
+ description="SIDDHAM END OF TEXT MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115C9,
+ },
+ [0x115CA]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CA,
+ },
+ [0x115CB]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CB,
+ },
+ [0x115CC]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CC,
+ },
+ [0x115CD]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CD,
+ },
+ [0x115CE]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CE,
+ },
+ [0x115CF]={
+ category="po",
+ description="SIDDHAM SECTION MARK DOUBLE RING",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115CF,
+ },
+ [0x115D0]={
+ category="po",
+ description="SIDDHAM SECTION MARK DOUBLE RING WITH RAYS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D0,
+ },
+ [0x115D1]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D1,
+ },
+ [0x115D2]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D2,
+ },
+ [0x115D3]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D3,
+ },
+ [0x115D4]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D4,
+ },
+ [0x115D5]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH CIRCLES AND RAYS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D5,
+ },
+ [0x115D6]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D6,
+ },
+ [0x115D7]={
+ category="po",
+ description="SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x115D7,
+ },
+ [0x115D8]={
+ category="lo",
+ description="SIDDHAM LETTER THREE-CIRCLE ALTERNATE I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115D8,
+ },
+ [0x115D9]={
+ category="lo",
+ description="SIDDHAM LETTER TWO-CIRCLE ALTERNATE I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115D9,
+ },
+ [0x115DA]={
+ category="lo",
+ description="SIDDHAM LETTER TWO-CIRCLE ALTERNATE II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115DA,
+ },
+ [0x115DB]={
+ category="lo",
+ description="SIDDHAM LETTER ALTERNATE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x115DB,
+ },
+ [0x115DC]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN ALTERNATE U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115DC,
+ },
+ [0x115DD]={
+ category="mn",
+ description="SIDDHAM VOWEL SIGN ALTERNATE UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x115DD,
+ },
+ [0x11600]={
+ category="lo",
+ description="MODI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11600,
+ },
+ [0x11601]={
+ category="lo",
+ description="MODI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11601,
+ },
+ [0x11602]={
+ category="lo",
+ description="MODI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11602,
+ },
+ [0x11603]={
+ category="lo",
+ description="MODI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11603,
+ },
+ [0x11604]={
+ category="lo",
+ description="MODI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11604,
+ },
+ [0x11605]={
+ category="lo",
+ description="MODI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11605,
+ },
+ [0x11606]={
+ category="lo",
+ description="MODI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11606,
+ },
+ [0x11607]={
+ category="lo",
+ description="MODI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11607,
+ },
+ [0x11608]={
+ category="lo",
+ description="MODI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11608,
+ },
+ [0x11609]={
+ category="lo",
+ description="MODI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11609,
+ },
+ [0x1160A]={
+ category="lo",
+ description="MODI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160A,
+ },
+ [0x1160B]={
+ category="lo",
+ description="MODI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160B,
+ },
+ [0x1160C]={
+ category="lo",
+ description="MODI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160C,
+ },
+ [0x1160D]={
+ category="lo",
+ description="MODI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160D,
+ },
+ [0x1160E]={
+ category="lo",
+ description="MODI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160E,
+ },
+ [0x1160F]={
+ category="lo",
+ description="MODI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1160F,
+ },
+ [0x11610]={
+ category="lo",
+ description="MODI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11610,
+ },
+ [0x11611]={
+ category="lo",
+ description="MODI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11611,
+ },
+ [0x11612]={
+ category="lo",
+ description="MODI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11612,
+ },
+ [0x11613]={
+ category="lo",
+ description="MODI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11613,
+ },
+ [0x11614]={
+ category="lo",
+ description="MODI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11614,
+ },
+ [0x11615]={
+ category="lo",
+ description="MODI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11615,
+ },
+ [0x11616]={
+ category="lo",
+ description="MODI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11616,
+ },
+ [0x11617]={
+ category="lo",
+ description="MODI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11617,
+ },
+ [0x11618]={
+ category="lo",
+ description="MODI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11618,
+ },
+ [0x11619]={
+ category="lo",
+ description="MODI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11619,
+ },
+ [0x1161A]={
+ category="lo",
+ description="MODI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161A,
+ },
+ [0x1161B]={
+ category="lo",
+ description="MODI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161B,
+ },
+ [0x1161C]={
+ category="lo",
+ description="MODI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161C,
+ },
+ [0x1161D]={
+ category="lo",
+ description="MODI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161D,
+ },
+ [0x1161E]={
+ category="lo",
+ description="MODI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161E,
+ },
+ [0x1161F]={
+ category="lo",
+ description="MODI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1161F,
+ },
+ [0x11620]={
+ category="lo",
+ description="MODI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11620,
+ },
+ [0x11621]={
+ category="lo",
+ description="MODI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11621,
+ },
+ [0x11622]={
+ category="lo",
+ description="MODI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11622,
+ },
+ [0x11623]={
+ category="lo",
+ description="MODI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11623,
+ },
+ [0x11624]={
+ category="lo",
+ description="MODI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11624,
+ },
+ [0x11625]={
+ category="lo",
+ description="MODI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11625,
+ },
+ [0x11626]={
+ category="lo",
+ description="MODI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11626,
+ },
+ [0x11627]={
+ category="lo",
+ description="MODI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11627,
+ },
+ [0x11628]={
+ category="lo",
+ description="MODI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11628,
+ },
+ [0x11629]={
+ category="lo",
+ description="MODI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11629,
+ },
+ [0x1162A]={
+ category="lo",
+ description="MODI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162A,
+ },
+ [0x1162B]={
+ category="lo",
+ description="MODI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162B,
+ },
+ [0x1162C]={
+ category="lo",
+ description="MODI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162C,
+ },
+ [0x1162D]={
+ category="lo",
+ description="MODI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162D,
+ },
+ [0x1162E]={
+ category="lo",
+ description="MODI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162E,
+ },
+ [0x1162F]={
+ category="lo",
+ description="MODI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1162F,
+ },
+ [0x11630]={
+ category="mc",
+ description="MODI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11630,
+ },
+ [0x11631]={
+ category="mc",
+ description="MODI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11631,
+ },
+ [0x11632]={
+ category="mc",
+ description="MODI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11632,
+ },
+ [0x11633]={
+ category="mn",
+ description="MODI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11633,
+ },
+ [0x11634]={
+ category="mn",
+ description="MODI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11634,
+ },
+ [0x11635]={
+ category="mn",
+ description="MODI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11635,
+ },
+ [0x11636]={
+ category="mn",
+ description="MODI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11636,
+ },
+ [0x11637]={
+ category="mn",
+ description="MODI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11637,
+ },
+ [0x11638]={
+ category="mn",
+ description="MODI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11638,
+ },
+ [0x11639]={
+ category="mn",
+ description="MODI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11639,
+ },
+ [0x1163A]={
+ category="mn",
+ description="MODI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1163A,
+ },
+ [0x1163B]={
+ category="mc",
+ description="MODI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1163B,
+ },
+ [0x1163C]={
+ category="mc",
+ description="MODI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1163C,
+ },
+ [0x1163D]={
+ category="mn",
+ description="MODI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1163D,
+ },
+ [0x1163E]={
+ category="mc",
+ description="MODI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1163E,
+ },
+ [0x1163F]={
+ category="mn",
+ combining=0x9,
+ description="MODI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1163F,
+ },
+ [0x11640]={
+ category="mn",
+ description="MODI SIGN ARDHACANDRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11640,
+ },
+ [0x11641]={
+ category="po",
+ description="MODI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11641,
+ },
+ [0x11642]={
+ category="po",
+ description="MODI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11642,
+ },
+ [0x11643]={
+ category="po",
+ description="MODI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11643,
+ },
+ [0x11644]={
+ category="lo",
+ description="MODI SIGN HUVA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11644,
+ },
+ [0x11650]={
+ category="nd",
+ description="MODI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11650,
+ },
+ [0x11651]={
+ category="nd",
+ description="MODI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11651,
+ },
+ [0x11652]={
+ category="nd",
+ description="MODI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11652,
+ },
+ [0x11653]={
+ category="nd",
+ description="MODI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11653,
+ },
+ [0x11654]={
+ category="nd",
+ description="MODI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11654,
+ },
+ [0x11655]={
+ category="nd",
+ description="MODI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11655,
+ },
+ [0x11656]={
+ category="nd",
+ description="MODI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11656,
+ },
+ [0x11657]={
+ category="nd",
+ description="MODI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11657,
+ },
+ [0x11658]={
+ category="nd",
+ description="MODI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11658,
+ },
+ [0x11659]={
+ category="nd",
+ description="MODI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11659,
+ },
+ [0x11680]={
+ category="lo",
+ description="TAKRI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11680,
+ },
+ [0x11681]={
+ category="lo",
+ description="TAKRI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11681,
+ },
+ [0x11682]={
+ category="lo",
+ description="TAKRI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11682,
+ },
+ [0x11683]={
+ category="lo",
+ description="TAKRI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11683,
+ },
+ [0x11684]={
+ category="lo",
+ description="TAKRI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11684,
+ },
+ [0x11685]={
+ category="lo",
+ description="TAKRI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11685,
+ },
+ [0x11686]={
+ category="lo",
+ description="TAKRI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11686,
+ },
+ [0x11687]={
+ category="lo",
+ description="TAKRI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11687,
+ },
+ [0x11688]={
+ category="lo",
+ description="TAKRI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11688,
+ },
+ [0x11689]={
+ category="lo",
+ description="TAKRI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11689,
+ },
+ [0x1168A]={
+ category="lo",
+ description="TAKRI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168A,
+ },
+ [0x1168B]={
+ category="lo",
+ description="TAKRI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168B,
+ },
+ [0x1168C]={
+ category="lo",
+ description="TAKRI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168C,
+ },
+ [0x1168D]={
+ category="lo",
+ description="TAKRI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168D,
+ },
+ [0x1168E]={
+ category="lo",
+ description="TAKRI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168E,
+ },
+ [0x1168F]={
+ category="lo",
+ description="TAKRI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168F,
+ },
+ [0x11690]={
+ category="lo",
+ description="TAKRI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11690,
+ },
+ [0x11691]={
+ category="lo",
+ description="TAKRI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11691,
+ },
+ [0x11692]={
+ category="lo",
+ description="TAKRI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11692,
+ },
+ [0x11693]={
+ category="lo",
+ description="TAKRI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11693,
+ },
+ [0x11694]={
+ category="lo",
+ description="TAKRI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11694,
+ },
+ [0x11695]={
+ category="lo",
+ description="TAKRI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11695,
+ },
+ [0x11696]={
+ category="lo",
+ description="TAKRI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11696,
+ },
+ [0x11697]={
+ category="lo",
+ description="TAKRI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11697,
+ },
+ [0x11698]={
+ category="lo",
+ description="TAKRI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11698,
+ },
+ [0x11699]={
+ category="lo",
+ description="TAKRI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11699,
+ },
+ [0x1169A]={
+ category="lo",
+ description="TAKRI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169A,
+ },
+ [0x1169B]={
+ category="lo",
+ description="TAKRI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169B,
+ },
+ [0x1169C]={
+ category="lo",
+ description="TAKRI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169C,
+ },
+ [0x1169D]={
+ category="lo",
+ description="TAKRI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169D,
+ },
+ [0x1169E]={
+ category="lo",
+ description="TAKRI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169E,
+ },
+ [0x1169F]={
+ category="lo",
+ description="TAKRI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169F,
+ },
+ [0x116A0]={
+ category="lo",
+ description="TAKRI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A0,
+ },
+ [0x116A1]={
+ category="lo",
+ description="TAKRI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A1,
+ },
+ [0x116A2]={
+ category="lo",
+ description="TAKRI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A2,
+ },
+ [0x116A3]={
+ category="lo",
+ description="TAKRI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A3,
+ },
+ [0x116A4]={
+ category="lo",
+ description="TAKRI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A4,
+ },
+ [0x116A5]={
+ category="lo",
+ description="TAKRI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A5,
+ },
+ [0x116A6]={
+ category="lo",
+ description="TAKRI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A6,
+ },
+ [0x116A7]={
+ category="lo",
+ description="TAKRI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A7,
+ },
+ [0x116A8]={
+ category="lo",
+ description="TAKRI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A8,
+ },
+ [0x116A9]={
+ category="lo",
+ description="TAKRI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A9,
+ },
+ [0x116AA]={
+ category="lo",
+ description="TAKRI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116AA,
+ },
+ [0x116AB]={
+ category="mn",
+ description="TAKRI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116AB,
+ },
+ [0x116AC]={
+ category="mc",
+ description="TAKRI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AC,
+ },
+ [0x116AD]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116AD,
+ },
+ [0x116AE]={
+ category="mc",
+ description="TAKRI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AE,
+ },
+ [0x116AF]={
+ category="mc",
+ description="TAKRI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AF,
+ },
+ [0x116B0]={
+ category="mn",
+ description="TAKRI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B0,
+ },
+ [0x116B1]={
+ category="mn",
+ description="TAKRI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B1,
+ },
+ [0x116B2]={
+ category="mn",
+ description="TAKRI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B2,
+ },
+ [0x116B3]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B3,
+ },
+ [0x116B4]={
+ category="mn",
+ description="TAKRI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B4,
+ },
+ [0x116B5]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B5,
+ },
+ [0x116B6]={
+ category="mc",
+ combining=0x9,
+ description="TAKRI SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116B6,
+ },
+ [0x116B7]={
+ category="mn",
+ combining=0x7,
+ description="TAKRI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B7,
+ },
+ [0x116C0]={
+ category="nd",
+ description="TAKRI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C0,
+ },
+ [0x116C1]={
+ category="nd",
+ description="TAKRI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C1,
+ },
+ [0x116C2]={
+ category="nd",
+ description="TAKRI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C2,
+ },
+ [0x116C3]={
+ category="nd",
+ description="TAKRI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C3,
+ },
+ [0x116C4]={
+ category="nd",
+ description="TAKRI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C4,
+ },
+ [0x116C5]={
+ category="nd",
+ description="TAKRI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C5,
+ },
+ [0x116C6]={
+ category="nd",
+ description="TAKRI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C6,
+ },
+ [0x116C7]={
+ category="nd",
+ description="TAKRI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C7,
+ },
+ [0x116C8]={
+ category="nd",
+ description="TAKRI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C8,
+ },
+ [0x116C9]={
+ category="nd",
+ description="TAKRI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C9,
+ },
+ [0x11700]={
+ category="lo",
+ description="AHOM LETTER KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11700,
+ },
+ [0x11701]={
+ category="lo",
+ description="AHOM LETTER KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11701,
+ },
+ [0x11702]={
+ category="lo",
+ description="AHOM LETTER NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11702,
+ },
+ [0x11703]={
+ category="lo",
+ description="AHOM LETTER NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11703,
+ },
+ [0x11704]={
+ category="lo",
+ description="AHOM LETTER TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11704,
+ },
+ [0x11705]={
+ category="lo",
+ description="AHOM LETTER ALTERNATE TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11705,
+ },
+ [0x11706]={
+ category="lo",
+ description="AHOM LETTER PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11706,
+ },
+ [0x11707]={
+ category="lo",
+ description="AHOM LETTER PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11707,
+ },
+ [0x11708]={
+ category="lo",
+ description="AHOM LETTER BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11708,
+ },
+ [0x11709]={
+ category="lo",
+ description="AHOM LETTER MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11709,
+ },
+ [0x1170A]={
+ category="lo",
+ description="AHOM LETTER JA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170A,
+ },
+ [0x1170B]={
+ category="lo",
+ description="AHOM LETTER CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170B,
+ },
+ [0x1170C]={
+ category="lo",
+ description="AHOM LETTER THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170C,
+ },
+ [0x1170D]={
+ category="lo",
+ description="AHOM LETTER RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170D,
+ },
+ [0x1170E]={
+ category="lo",
+ description="AHOM LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170E,
+ },
+ [0x1170F]={
+ category="lo",
+ description="AHOM LETTER SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1170F,
+ },
+ [0x11710]={
+ category="lo",
+ description="AHOM LETTER NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11710,
+ },
+ [0x11711]={
+ category="lo",
+ description="AHOM LETTER HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11711,
+ },
+ [0x11712]={
+ category="lo",
+ description="AHOM LETTER A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11712,
+ },
+ [0x11713]={
+ category="lo",
+ description="AHOM LETTER DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11713,
+ },
+ [0x11714]={
+ category="lo",
+ description="AHOM LETTER DHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11714,
+ },
+ [0x11715]={
+ category="lo",
+ description="AHOM LETTER GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11715,
+ },
+ [0x11716]={
+ category="lo",
+ description="AHOM LETTER ALTERNATE GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11716,
+ },
+ [0x11717]={
+ category="lo",
+ description="AHOM LETTER GHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11717,
+ },
+ [0x11718]={
+ category="lo",
+ description="AHOM LETTER BHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11718,
+ },
+ [0x11719]={
+ category="lo",
+ description="AHOM LETTER JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11719,
+ },
+ [0x1171D]={
+ category="mn",
+ description="AHOM CONSONANT SIGN MEDIAL LA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1171D,
+ },
+ [0x1171E]={
+ category="mn",
+ description="AHOM CONSONANT SIGN MEDIAL RA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1171E,
+ },
+ [0x1171F]={
+ category="mn",
+ description="AHOM CONSONANT SIGN MEDIAL LIGATING RA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1171F,
+ },
+ [0x11720]={
+ category="mc",
+ description="AHOM VOWEL SIGN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11720,
+ },
+ [0x11721]={
+ category="mc",
+ description="AHOM VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11721,
+ },
+ [0x11722]={
+ category="mn",
+ description="AHOM VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11722,
+ },
+ [0x11723]={
+ category="mn",
+ description="AHOM VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11723,
+ },
+ [0x11724]={
+ category="mn",
+ description="AHOM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11724,
+ },
+ [0x11725]={
+ category="mn",
+ description="AHOM VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11725,
+ },
+ [0x11726]={
+ category="mc",
+ description="AHOM VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x11726,
+ },
+ [0x11727]={
+ category="mn",
+ description="AHOM VOWEL SIGN AW",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11727,
+ },
+ [0x11728]={
+ category="mn",
+ description="AHOM VOWEL SIGN O",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11728,
+ },
+ [0x11729]={
+ category="mn",
+ description="AHOM VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x11729,
+ },
+ [0x1172A]={
+ category="mn",
+ description="AHOM VOWEL SIGN AM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1172A,
+ },
+ [0x1172B]={
+ category="mn",
+ combining=0x9,
+ description="AHOM SIGN KILLER",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1172B,
+ },
+ [0x11730]={
+ category="nd",
+ description="AHOM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11730,
+ },
+ [0x11731]={
+ category="nd",
+ description="AHOM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11731,
+ },
+ [0x11732]={
+ category="nd",
+ description="AHOM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11732,
+ },
+ [0x11733]={
+ category="nd",
+ description="AHOM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11733,
+ },
+ [0x11734]={
+ category="nd",
+ description="AHOM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11734,
+ },
+ [0x11735]={
+ category="nd",
+ description="AHOM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11735,
+ },
+ [0x11736]={
+ category="nd",
+ description="AHOM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11736,
+ },
+ [0x11737]={
+ category="nd",
+ description="AHOM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11737,
+ },
+ [0x11738]={
+ category="nd",
+ description="AHOM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11738,
+ },
+ [0x11739]={
+ category="nd",
+ description="AHOM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11739,
+ },
+ [0x1173A]={
+ category="no",
+ description="AHOM NUMBER TEN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1173A,
+ },
+ [0x1173B]={
+ category="no",
+ description="AHOM NUMBER TWENTY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1173B,
+ },
+ [0x1173C]={
+ category="po",
+ description="AHOM SIGN SMALL SECTION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1173C,
+ },
+ [0x1173D]={
+ category="po",
+ description="AHOM SIGN SECTION",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1173D,
+ },
+ [0x1173E]={
+ category="po",
+ description="AHOM SIGN RULAI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1173E,
+ },
+ [0x1173F]={
+ category="so",
+ description="AHOM SYMBOL VI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1173F,
+ },
+ [0x118A0]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER NGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A0,
+ },
+ [0x118A1]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A1,
+ },
+ [0x118A2]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A2,
+ },
+ [0x118A3]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A3,
+ },
+ [0x118A4]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A4,
+ },
+ [0x118A5]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A5,
+ },
+ [0x118A6]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A6,
+ },
+ [0x118A7]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A7,
+ },
+ [0x118A8]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A8,
+ },
+ [0x118A9]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118A9,
+ },
+ [0x118AA]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AA,
+ },
+ [0x118AB]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AB,
+ },
+ [0x118AC]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AC,
+ },
+ [0x118AD]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER ENY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AD,
+ },
+ [0x118AE]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER YUJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AE,
+ },
+ [0x118AF]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER UC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118AF,
+ },
+ [0x118B0]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER ENN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B0,
+ },
+ [0x118B1]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER ODD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B1,
+ },
+ [0x118B2]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER TTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B2,
+ },
+ [0x118B3]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER NUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B3,
+ },
+ [0x118B4]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B4,
+ },
+ [0x118B5]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER AT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B5,
+ },
+ [0x118B6]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER AM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B6,
+ },
+ [0x118B7]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B7,
+ },
+ [0x118B8]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B8,
+ },
+ [0x118B9]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER HIYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118B9,
+ },
+ [0x118BA]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER HOLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BA,
+ },
+ [0x118BB]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER HORR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BB,
+ },
+ [0x118BC]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER HAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BC,
+ },
+ [0x118BD]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER SSUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BD,
+ },
+ [0x118BE]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER SII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BE,
+ },
+ [0x118BF]={
+ category="lu",
+ description="WARANG CITI CAPITAL LETTER VIYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118BF,
+ },
+ [0x118C0]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER NGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C0,
+ },
+ [0x118C1]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C1,
+ },
+ [0x118C2]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C2,
+ },
+ [0x118C3]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C3,
+ },
+ [0x118C4]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C4,
+ },
+ [0x118C5]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C5,
+ },
+ [0x118C6]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C6,
+ },
+ [0x118C7]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C7,
+ },
+ [0x118C8]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C8,
+ },
+ [0x118C9]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118C9,
+ },
+ [0x118CA]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CA,
+ },
+ [0x118CB]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CB,
+ },
+ [0x118CC]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CC,
+ },
+ [0x118CD]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER ENY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CD,
+ },
+ [0x118CE]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER YUJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CE,
+ },
+ [0x118CF]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER UC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118CF,
+ },
+ [0x118D0]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER ENN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D0,
+ },
+ [0x118D1]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER ODD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D1,
+ },
+ [0x118D2]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER TTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D2,
+ },
+ [0x118D3]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER NUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D3,
+ },
+ [0x118D4]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D4,
+ },
+ [0x118D5]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER AT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D5,
+ },
+ [0x118D6]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER AM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D6,
+ },
+ [0x118D7]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D7,
+ },
+ [0x118D8]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D8,
+ },
+ [0x118D9]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER HIYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118D9,
+ },
+ [0x118DA]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER HOLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DA,
+ },
+ [0x118DB]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER HORR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DB,
+ },
+ [0x118DC]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER HAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DC,
+ },
+ [0x118DD]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER SSUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DD,
+ },
+ [0x118DE]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER SII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DE,
+ },
+ [0x118DF]={
+ category="ll",
+ description="WARANG CITI SMALL LETTER VIYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118DF,
+ },
+ [0x118E0]={
+ category="nd",
+ description="WARANG CITI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E0,
+ },
+ [0x118E1]={
+ category="nd",
+ description="WARANG CITI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E1,
+ },
+ [0x118E2]={
+ category="nd",
+ description="WARANG CITI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E2,
+ },
+ [0x118E3]={
+ category="nd",
+ description="WARANG CITI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E3,
+ },
+ [0x118E4]={
+ category="nd",
+ description="WARANG CITI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E4,
+ },
+ [0x118E5]={
+ category="nd",
+ description="WARANG CITI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E5,
+ },
+ [0x118E6]={
+ category="nd",
+ description="WARANG CITI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E6,
+ },
+ [0x118E7]={
+ category="nd",
+ description="WARANG CITI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E7,
+ },
+ [0x118E8]={
+ category="nd",
+ description="WARANG CITI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E8,
+ },
+ [0x118E9]={
+ category="nd",
+ description="WARANG CITI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x118E9,
+ },
+ [0x118EA]={
+ category="no",
+ description="WARANG CITI NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118EA,
+ },
+ [0x118EB]={
+ category="no",
+ description="WARANG CITI NUMBER TWENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118EB,
+ },
+ [0x118EC]={
+ category="no",
+ description="WARANG CITI NUMBER THIRTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118EC,
+ },
+ [0x118ED]={
+ category="no",
+ description="WARANG CITI NUMBER FORTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118ED,
+ },
+ [0x118EE]={
+ category="no",
+ description="WARANG CITI NUMBER FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118EE,
+ },
+ [0x118EF]={
+ category="no",
+ description="WARANG CITI NUMBER SIXTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118EF,
+ },
+ [0x118F0]={
+ category="no",
+ description="WARANG CITI NUMBER SEVENTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118F0,
+ },
+ [0x118F1]={
+ category="no",
+ description="WARANG CITI NUMBER EIGHTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118F1,
+ },
+ [0x118F2]={
+ category="no",
+ description="WARANG CITI NUMBER NINETY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118F2,
+ },
+ [0x118FF]={
+ category="lo",
+ description="WARANG CITI OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x118FF,
+ },
+ [0x11AC0]={
+ category="lo",
+ description="PAU CIN HAU LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC0,
+ },
+ [0x11AC1]={
+ category="lo",
+ description="PAU CIN HAU LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC1,
+ },
+ [0x11AC2]={
+ category="lo",
+ description="PAU CIN HAU LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC2,
+ },
+ [0x11AC3]={
+ category="lo",
+ description="PAU CIN HAU LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC3,
+ },
+ [0x11AC4]={
+ category="lo",
+ description="PAU CIN HAU LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC4,
+ },
+ [0x11AC5]={
+ category="lo",
+ description="PAU CIN HAU LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC5,
+ },
+ [0x11AC6]={
+ category="lo",
+ description="PAU CIN HAU LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC6,
+ },
+ [0x11AC7]={
+ category="lo",
+ description="PAU CIN HAU LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC7,
+ },
+ [0x11AC8]={
+ category="lo",
+ description="PAU CIN HAU LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC8,
+ },
+ [0x11AC9]={
+ category="lo",
+ description="PAU CIN HAU LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AC9,
+ },
+ [0x11ACA]={
+ category="lo",
+ description="PAU CIN HAU LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACA,
+ },
+ [0x11ACB]={
+ category="lo",
+ description="PAU CIN HAU LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACB,
+ },
+ [0x11ACC]={
+ category="lo",
+ description="PAU CIN HAU LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACC,
+ },
+ [0x11ACD]={
+ category="lo",
+ description="PAU CIN HAU LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACD,
+ },
+ [0x11ACE]={
+ category="lo",
+ description="PAU CIN HAU LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACE,
+ },
+ [0x11ACF]={
+ category="lo",
+ description="PAU CIN HAU LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ACF,
+ },
+ [0x11AD0]={
+ category="lo",
+ description="PAU CIN HAU LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD0,
+ },
+ [0x11AD1]={
+ category="lo",
+ description="PAU CIN HAU LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD1,
+ },
+ [0x11AD2]={
+ category="lo",
+ description="PAU CIN HAU LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD2,
+ },
+ [0x11AD3]={
+ category="lo",
+ description="PAU CIN HAU LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD3,
+ },
+ [0x11AD4]={
+ category="lo",
+ description="PAU CIN HAU LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD4,
+ },
+ [0x11AD5]={
+ category="lo",
+ description="PAU CIN HAU LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD5,
+ },
+ [0x11AD6]={
+ category="lo",
+ description="PAU CIN HAU LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD6,
+ },
+ [0x11AD7]={
+ category="lo",
+ description="PAU CIN HAU LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD7,
+ },
+ [0x11AD8]={
+ category="lo",
+ description="PAU CIN HAU LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD8,
+ },
+ [0x11AD9]={
+ category="lo",
+ description="PAU CIN HAU LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AD9,
+ },
+ [0x11ADA]={
+ category="lo",
+ description="PAU CIN HAU LETTER UA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADA,
+ },
+ [0x11ADB]={
+ category="lo",
+ description="PAU CIN HAU LETTER IA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADB,
+ },
+ [0x11ADC]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADC,
+ },
+ [0x11ADD]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADD,
+ },
+ [0x11ADE]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADE,
+ },
+ [0x11ADF]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11ADF,
+ },
+ [0x11AE0]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE0,
+ },
+ [0x11AE1]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE1,
+ },
+ [0x11AE2]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE2,
+ },
+ [0x11AE3]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE3,
+ },
+ [0x11AE4]={
+ category="lo",
+ description="PAU CIN HAU LETTER FINAL Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE4,
+ },
+ [0x11AE5]={
+ category="lo",
+ description="PAU CIN HAU RISING TONE LONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE5,
+ },
+ [0x11AE6]={
+ category="lo",
+ description="PAU CIN HAU RISING TONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE6,
+ },
+ [0x11AE7]={
+ category="lo",
+ description="PAU CIN HAU SANDHI GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE7,
+ },
+ [0x11AE8]={
+ category="lo",
+ description="PAU CIN HAU RISING TONE LONG FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE8,
+ },
+ [0x11AE9]={
+ category="lo",
+ description="PAU CIN HAU RISING TONE FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AE9,
+ },
+ [0x11AEA]={
+ category="lo",
+ description="PAU CIN HAU SANDHI GLOTTAL STOP FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AEA,
+ },
+ [0x11AEB]={
+ category="lo",
+ description="PAU CIN HAU SANDHI TONE LONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AEB,
+ },
+ [0x11AEC]={
+ category="lo",
+ description="PAU CIN HAU SANDHI TONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AEC,
+ },
+ [0x11AED]={
+ category="lo",
+ description="PAU CIN HAU SANDHI TONE LONG FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AED,
+ },
+ [0x11AEE]={
+ category="lo",
+ description="PAU CIN HAU SANDHI TONE FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AEE,
+ },
+ [0x11AEF]={
+ category="lo",
+ description="PAU CIN HAU MID-LEVEL TONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AEF,
+ },
+ [0x11AF0]={
+ category="lo",
+ description="PAU CIN HAU GLOTTAL STOP VARIANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF0,
+ },
+ [0x11AF1]={
+ category="lo",
+ description="PAU CIN HAU MID-LEVEL TONE LONG FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF1,
+ },
+ [0x11AF2]={
+ category="lo",
+ description="PAU CIN HAU MID-LEVEL TONE FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF2,
+ },
+ [0x11AF3]={
+ category="lo",
+ description="PAU CIN HAU LOW-FALLING TONE LONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF3,
+ },
+ [0x11AF4]={
+ category="lo",
+ description="PAU CIN HAU LOW-FALLING TONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF4,
+ },
+ [0x11AF5]={
+ category="lo",
+ description="PAU CIN HAU GLOTTAL STOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF5,
+ },
+ [0x11AF6]={
+ category="lo",
+ description="PAU CIN HAU LOW-FALLING TONE LONG FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF6,
+ },
+ [0x11AF7]={
+ category="lo",
+ description="PAU CIN HAU LOW-FALLING TONE FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF7,
+ },
+ [0x11AF8]={
+ category="lo",
+ description="PAU CIN HAU GLOTTAL STOP FINAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11AF8,
+ },
+ [0x12000]={
+ category="lo",
+ description="CUNEIFORM SIGN A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12000,
+ },
+ [0x12001]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12001,
+ },
+ [0x12002]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12002,
+ },
+ [0x12003]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12003,
+ },
+ [0x12004]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12004,
+ },
+ [0x12005]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12005,
+ },
+ [0x12006]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES LAGAR GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12006,
+ },
+ [0x12007]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12007,
+ },
+ [0x12008]={
+ category="lo",
+ description="CUNEIFORM SIGN A TIMES SAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12008,
+ },
+ [0x12009]={
+ category="lo",
+ description="CUNEIFORM SIGN A0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12009,
+ },
+ [0x1200A]={
+ category="lo",
+ description="CUNEIFORM SIGN AB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200A,
+ },
+ [0x1200B]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200B,
+ },
+ [0x1200C]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES DUN0x0003 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200C,
+ },
+ [0x1200D]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES GAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200D,
+ },
+ [0x1200E]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200E,
+ },
+ [0x1200F]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1200F,
+ },
+ [0x12010]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12010,
+ },
+ [0x12011]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES IMIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12011,
+ },
+ [0x12012]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES LAGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12012,
+ },
+ [0x12013]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES SHESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12013,
+ },
+ [0x12014]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES U PLUS U PLUS U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12014,
+ },
+ [0x12015]={
+ category="lo",
+ description="CUNEIFORM SIGN AB GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12015,
+ },
+ [0x12016]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12016,
+ },
+ [0x12017]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002 TIMES BALAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12017,
+ },
+ [0x12018]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002 TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12018,
+ },
+ [0x12019]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002 TIMES ME PLUS EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12019,
+ },
+ [0x1201A]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002 TIMES SHA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201A,
+ },
+ [0x1201B]={
+ category="lo",
+ description="CUNEIFORM SIGN AB0x0002 TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201B,
+ },
+ [0x1201C]={
+ category="lo",
+ description="CUNEIFORM SIGN AD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201C,
+ },
+ [0x1201D]={
+ category="lo",
+ description="CUNEIFORM SIGN AK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201D,
+ },
+ [0x1201E]={
+ category="lo",
+ description="CUNEIFORM SIGN AK TIMES ERIN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201E,
+ },
+ [0x1201F]={
+ category="lo",
+ description="CUNEIFORM SIGN AK TIMES SHITA PLUS GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1201F,
+ },
+ [0x12020]={
+ category="lo",
+ description="CUNEIFORM SIGN AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12020,
+ },
+ [0x12021]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12021,
+ },
+ [0x12022]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES DIM0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12022,
+ },
+ [0x12023]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12023,
+ },
+ [0x12024]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12024,
+ },
+ [0x12025]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES KAD0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12025,
+ },
+ [0x12026]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12026,
+ },
+ [0x12027]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12027,
+ },
+ [0x12028]={
+ category="lo",
+ description="CUNEIFORM SIGN AL TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12028,
+ },
+ [0x12029]={
+ category="lo",
+ description="CUNEIFORM SIGN ALAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12029,
+ },
+ [0x1202A]={
+ category="lo",
+ description="CUNEIFORM SIGN ALEPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202A,
+ },
+ [0x1202B]={
+ category="lo",
+ description="CUNEIFORM SIGN AMAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202B,
+ },
+ [0x1202C]={
+ category="lo",
+ description="CUNEIFORM SIGN AMAR TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202C,
+ },
+ [0x1202D]={
+ category="lo",
+ description="CUNEIFORM SIGN AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202D,
+ },
+ [0x1202E]={
+ category="lo",
+ description="CUNEIFORM SIGN AN OVER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202E,
+ },
+ [0x1202F]={
+ category="lo",
+ description="CUNEIFORM SIGN AN THREE TIMES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1202F,
+ },
+ [0x12030]={
+ category="lo",
+ description="CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12030,
+ },
+ [0x12031]={
+ category="lo",
+ description="CUNEIFORM SIGN AN PLUS NAGA SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12031,
+ },
+ [0x12032]={
+ category="lo",
+ description="CUNEIFORM SIGN ANSHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12032,
+ },
+ [0x12033]={
+ category="lo",
+ description="CUNEIFORM SIGN APIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12033,
+ },
+ [0x12034]={
+ category="lo",
+ description="CUNEIFORM SIGN ARAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12034,
+ },
+ [0x12035]={
+ category="lo",
+ description="CUNEIFORM SIGN ARAD TIMES KUR",
+ direction="l",
+ linebreak="al",
+ mathclass="ordinary",
+ mathname="backprime",
+ unicodeslot=0x12035,
+ },
+ [0x12036]={
+ category="lo",
+ description="CUNEIFORM SIGN ARKAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12036,
+ },
+ [0x12037]={
+ category="lo",
+ description="CUNEIFORM SIGN ASAL0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12037,
+ },
+ [0x12038]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12038,
+ },
+ [0x12039]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH ZIDA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12039,
+ },
+ [0x1203A]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH KABA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203A,
+ },
+ [0x1203B]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH OVER ASH TUG0x0002 OVER TUG0x0002 TUG0x0002 OVER TUG0x0002 PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203B,
+ },
+ [0x1203C]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH OVER ASH OVER ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203C,
+ },
+ [0x1203D]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203D,
+ },
+ [0x1203E]={
+ category="lo",
+ description="CUNEIFORM SIGN ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203E,
+ },
+ [0x1203F]={
+ category="lo",
+ description="CUNEIFORM SIGN ASHGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1203F,
+ },
+ [0x12040]={
+ category="lo",
+ description="CUNEIFORM SIGN BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12040,
+ },
+ [0x12041]={
+ category="lo",
+ description="CUNEIFORM SIGN BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12041,
+ },
+ [0x12042]={
+ category="lo",
+ description="CUNEIFORM SIGN BAG0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12042,
+ },
+ [0x12043]={
+ category="lo",
+ description="CUNEIFORM SIGN BAHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12043,
+ },
+ [0x12044]={
+ category="lo",
+ description="CUNEIFORM SIGN BAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12044,
+ },
+ [0x12045]={
+ category="lo",
+ description="CUNEIFORM SIGN BAL OVER BAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12045,
+ },
+ [0x12046]={
+ category="lo",
+ description="CUNEIFORM SIGN BALAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12046,
+ },
+ [0x12047]={
+ category="lo",
+ description="CUNEIFORM SIGN BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12047,
+ },
+ [0x12048]={
+ category="lo",
+ description="CUNEIFORM SIGN BARA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12048,
+ },
+ [0x12049]={
+ category="lo",
+ description="CUNEIFORM SIGN BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12049,
+ },
+ [0x1204A]={
+ category="lo",
+ description="CUNEIFORM SIGN BI TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204A,
+ },
+ [0x1204B]={
+ category="lo",
+ description="CUNEIFORM SIGN BI TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204B,
+ },
+ [0x1204C]={
+ category="lo",
+ description="CUNEIFORM SIGN BI TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204C,
+ },
+ [0x1204D]={
+ category="lo",
+ description="CUNEIFORM SIGN BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204D,
+ },
+ [0x1204E]={
+ category="lo",
+ description="CUNEIFORM SIGN BU OVER BU AB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204E,
+ },
+ [0x1204F]={
+ category="lo",
+ description="CUNEIFORM SIGN BU OVER BU UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1204F,
+ },
+ [0x12050]={
+ category="lo",
+ description="CUNEIFORM SIGN BU CROSSING BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12050,
+ },
+ [0x12051]={
+ category="lo",
+ description="CUNEIFORM SIGN BULUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12051,
+ },
+ [0x12052]={
+ category="lo",
+ description="CUNEIFORM SIGN BULUG OVER BULUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12052,
+ },
+ [0x12053]={
+ category="lo",
+ description="CUNEIFORM SIGN BUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12053,
+ },
+ [0x12054]={
+ category="lo",
+ description="CUNEIFORM SIGN BUR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12054,
+ },
+ [0x12055]={
+ category="lo",
+ description="CUNEIFORM SIGN DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12055,
+ },
+ [0x12056]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12056,
+ },
+ [0x12057]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES A PLUS MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12057,
+ },
+ [0x12058]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES AMAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12058,
+ },
+ [0x12059]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES BALAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12059,
+ },
+ [0x1205A]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205A,
+ },
+ [0x1205B]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205B,
+ },
+ [0x1205C]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES GA PLUS MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205C,
+ },
+ [0x1205D]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205D,
+ },
+ [0x1205E]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES GIR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205E,
+ },
+ [0x1205F]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1205F,
+ },
+ [0x12060]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12060,
+ },
+ [0x12061]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES IR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12061,
+ },
+ [0x12062]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES IR PLUS LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12062,
+ },
+ [0x12063]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12063,
+ },
+ [0x12064]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12064,
+ },
+ [0x12065]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12065,
+ },
+ [0x12066]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES LU PLUS MASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12066,
+ },
+ [0x12067]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12067,
+ },
+ [0x12068]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12068,
+ },
+ [0x12069]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES PAP PLUS PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12069,
+ },
+ [0x1206A]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206A,
+ },
+ [0x1206B]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206B,
+ },
+ [0x1206C]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES U0x0002 PLUS GIR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206C,
+ },
+ [0x1206D]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM0x0005 TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206D,
+ },
+ [0x1206E]={
+ category="lo",
+ description="CUNEIFORM SIGN DAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206E,
+ },
+ [0x1206F]={
+ category="lo",
+ description="CUNEIFORM SIGN DAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1206F,
+ },
+ [0x12070]={
+ category="lo",
+ description="CUNEIFORM SIGN DARA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12070,
+ },
+ [0x12071]={
+ category="lo",
+ description="CUNEIFORM SIGN DARA0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12071,
+ },
+ [0x12072]={
+ category="lo",
+ description="CUNEIFORM SIGN DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12072,
+ },
+ [0x12073]={
+ category="lo",
+ description="CUNEIFORM SIGN DIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12073,
+ },
+ [0x12074]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12074,
+ },
+ [0x12075]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12075,
+ },
+ [0x12076]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12076,
+ },
+ [0x12077]={
+ category="lo",
+ description="CUNEIFORM SIGN DIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12077,
+ },
+ [0x12078]={
+ category="lo",
+ description="CUNEIFORM SIGN DIN KASKAL U GUNU DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12078,
+ },
+ [0x12079]={
+ category="lo",
+ description="CUNEIFORM SIGN DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12079,
+ },
+ [0x1207A]={
+ category="lo",
+ description="CUNEIFORM SIGN DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207A,
+ },
+ [0x1207B]={
+ category="lo",
+ description="CUNEIFORM SIGN DU OVER DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207B,
+ },
+ [0x1207C]={
+ category="lo",
+ description="CUNEIFORM SIGN DU GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207C,
+ },
+ [0x1207D]={
+ category="lo",
+ description="CUNEIFORM SIGN DU SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207D,
+ },
+ [0x1207E]={
+ category="lo",
+ description="CUNEIFORM SIGN DUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207E,
+ },
+ [0x1207F]={
+ category="lo",
+ description="CUNEIFORM SIGN DUB TIMES ESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1207F,
+ },
+ [0x12080]={
+ category="lo",
+ description="CUNEIFORM SIGN DUB0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12080,
+ },
+ [0x12081]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12081,
+ },
+ [0x12082]={
+ category="lo",
+ description="CUNEIFORM SIGN DUGUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12082,
+ },
+ [0x12083]={
+ category="lo",
+ description="CUNEIFORM SIGN DUH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12083,
+ },
+ [0x12084]={
+ category="lo",
+ description="CUNEIFORM SIGN DUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12084,
+ },
+ [0x12085]={
+ category="lo",
+ description="CUNEIFORM SIGN DUN0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12085,
+ },
+ [0x12086]={
+ category="lo",
+ description="CUNEIFORM SIGN DUN0x0003 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12086,
+ },
+ [0x12087]={
+ category="lo",
+ description="CUNEIFORM SIGN DUN0x0003 GUNU GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12087,
+ },
+ [0x12088]={
+ category="lo",
+ description="CUNEIFORM SIGN DUN0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12088,
+ },
+ [0x12089]={
+ category="lo",
+ description="CUNEIFORM SIGN DUR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12089,
+ },
+ [0x1208A]={
+ category="lo",
+ description="CUNEIFORM SIGN E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208A,
+ },
+ [0x1208B]={
+ category="lo",
+ description="CUNEIFORM SIGN E TIMES PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208B,
+ },
+ [0x1208C]={
+ category="lo",
+ description="CUNEIFORM SIGN E OVER E NUN OVER NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208C,
+ },
+ [0x1208D]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208D,
+ },
+ [0x1208E]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES A PLUS HA PLUS DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208E,
+ },
+ [0x1208F]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1208F,
+ },
+ [0x12090]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12090,
+ },
+ [0x12091]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12091,
+ },
+ [0x12092]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12092,
+ },
+ [0x12093]={
+ category="lo",
+ description="CUNEIFORM SIGN E0x0002 TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12093,
+ },
+ [0x12094]={
+ category="lo",
+ description="CUNEIFORM SIGN EDIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12094,
+ },
+ [0x12095]={
+ category="lo",
+ description="CUNEIFORM SIGN EGIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12095,
+ },
+ [0x12096]={
+ category="lo",
+ description="CUNEIFORM SIGN EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12096,
+ },
+ [0x12097]={
+ category="lo",
+ description="CUNEIFORM SIGN EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12097,
+ },
+ [0x12098]={
+ category="lo",
+ description="CUNEIFORM SIGN EN TIMES GAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12098,
+ },
+ [0x12099]={
+ category="lo",
+ description="CUNEIFORM SIGN EN TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12099,
+ },
+ [0x1209A]={
+ category="lo",
+ description="CUNEIFORM SIGN EN TIMES ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209A,
+ },
+ [0x1209B]={
+ category="lo",
+ description="CUNEIFORM SIGN EN CROSSING EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209B,
+ },
+ [0x1209C]={
+ category="lo",
+ description="CUNEIFORM SIGN EN OPPOSING EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209C,
+ },
+ [0x1209D]={
+ category="lo",
+ description="CUNEIFORM SIGN EN SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209D,
+ },
+ [0x1209E]={
+ category="lo",
+ description="CUNEIFORM SIGN EREN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209E,
+ },
+ [0x1209F]={
+ category="lo",
+ description="CUNEIFORM SIGN ERIN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1209F,
+ },
+ [0x120A0]={
+ category="lo",
+ description="CUNEIFORM SIGN ESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A0,
+ },
+ [0x120A1]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A1,
+ },
+ [0x120A2]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A2,
+ },
+ [0x120A3]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES A PLUS LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A3,
+ },
+ [0x120A4]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A4,
+ },
+ [0x120A5]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A5,
+ },
+ [0x120A6]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A6,
+ },
+ [0x120A7]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES DUN0x0003 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A7,
+ },
+ [0x120A8]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES DUN0x0003 GUNU GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A8,
+ },
+ [0x120A9]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120A9,
+ },
+ [0x120AA]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES HA GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AA,
+ },
+ [0x120AB]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AB,
+ },
+ [0x120AC]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AC,
+ },
+ [0x120AD]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AD,
+ },
+ [0x120AE]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES KU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AE,
+ },
+ [0x120AF]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120AF,
+ },
+ [0x120B0]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B0,
+ },
+ [0x120B1]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B1,
+ },
+ [0x120B2]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B2,
+ },
+ [0x120B3]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B3,
+ },
+ [0x120B4]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B4,
+ },
+ [0x120B5]={
+ category="lo",
+ description="CUNEIFORM SIGN GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B5,
+ },
+ [0x120B6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B6,
+ },
+ [0x120B7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B7,
+ },
+ [0x120B8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES A PLUS DA PLUS HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B8,
+ },
+ [0x120B9]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES A PLUS HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120B9,
+ },
+ [0x120BA]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES A PLUS IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BA,
+ },
+ [0x120BB]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES AB0x0002 TENU PLUS TAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BB,
+ },
+ [0x120BC]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BC,
+ },
+ [0x120BD]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BD,
+ },
+ [0x120BE]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES ASH0x0002 PLUS GAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BE,
+ },
+ [0x120BF]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120BF,
+ },
+ [0x120C0]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES BAR PLUS RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C0,
+ },
+ [0x120C1]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES BUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C1,
+ },
+ [0x120C2]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES BUR PLUS RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C2,
+ },
+ [0x120C3]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C3,
+ },
+ [0x120C4]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C4,
+ },
+ [0x120C5]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES DIM TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C5,
+ },
+ [0x120C6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES DUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C6,
+ },
+ [0x120C7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C7,
+ },
+ [0x120C8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES EL PLUS LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C8,
+ },
+ [0x120C9]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120C9,
+ },
+ [0x120CA]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES EN TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CA,
+ },
+ [0x120CB]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CB,
+ },
+ [0x120CC]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CC,
+ },
+ [0x120CD]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CD,
+ },
+ [0x120CE]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GI0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CE,
+ },
+ [0x120CF]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GI0x0004 PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120CF,
+ },
+ [0x120D0]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES GIR0x0002 PLUS SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D0,
+ },
+ [0x120D1]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES HA PLUS LU PLUS ESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D1,
+ },
+ [0x120D2]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES HAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D2,
+ },
+ [0x120D3]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES HAL PLUS LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D3,
+ },
+ [0x120D4]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES HI PLUS LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D4,
+ },
+ [0x120D5]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES HUB0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D5,
+ },
+ [0x120D6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D6,
+ },
+ [0x120D7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES ISH PLUS HU PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D7,
+ },
+ [0x120D8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D8,
+ },
+ [0x120D9]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120D9,
+ },
+ [0x120DA]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES KID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DA,
+ },
+ [0x120DB]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES KID PLUS LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DB,
+ },
+ [0x120DC]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES KU0x0003 PLUS AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DC,
+ },
+ [0x120DD]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DD,
+ },
+ [0x120DE]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES ME PLUS EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DE,
+ },
+ [0x120DF]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120DF,
+ },
+ [0x120E0]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E0,
+ },
+ [0x120E1]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES NUN OVER NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E1,
+ },
+ [0x120E2]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E2,
+ },
+ [0x120E3]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E3,
+ },
+ [0x120E4]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E4,
+ },
+ [0x120E5]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E5,
+ },
+ [0x120E6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SHE PLUS TUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E6,
+ },
+ [0x120E7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SHID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E7,
+ },
+ [0x120E8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES SUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E8,
+ },
+ [0x120E9]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120E9,
+ },
+ [0x120EA]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120EA,
+ },
+ [0x120EB]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120EB,
+ },
+ [0x120EC]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 TIMES UD PLUS DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120EC,
+ },
+ [0x120ED]={
+ category="lo",
+ description="CUNEIFORM SIGN GA0x0002 OVER GA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120ED,
+ },
+ [0x120EE]={
+ category="lo",
+ description="CUNEIFORM SIGN GABA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120EE,
+ },
+ [0x120EF]={
+ category="lo",
+ description="CUNEIFORM SIGN GABA CROSSING GABA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120EF,
+ },
+ [0x120F0]={
+ category="lo",
+ description="CUNEIFORM SIGN GAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F0,
+ },
+ [0x120F1]={
+ category="lo",
+ description="CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F1,
+ },
+ [0x120F2]={
+ category="lo",
+ description="CUNEIFORM SIGN GAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F2,
+ },
+ [0x120F3]={
+ category="lo",
+ description="CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F3,
+ },
+ [0x120F4]={
+ category="lo",
+ description="CUNEIFORM SIGN GALAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F4,
+ },
+ [0x120F5]={
+ category="lo",
+ description="CUNEIFORM SIGN GAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F5,
+ },
+ [0x120F6]={
+ category="lo",
+ description="CUNEIFORM SIGN GAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F6,
+ },
+ [0x120F7]={
+ category="lo",
+ description="CUNEIFORM SIGN GAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F7,
+ },
+ [0x120F8]={
+ category="lo",
+ description="CUNEIFORM SIGN GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F8,
+ },
+ [0x120F9]={
+ category="lo",
+ description="CUNEIFORM SIGN GAN0x0002 OVER GAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120F9,
+ },
+ [0x120FA]={
+ category="lo",
+ description="CUNEIFORM SIGN GAN0x0002 CROSSING GAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FA,
+ },
+ [0x120FB]={
+ category="lo",
+ description="CUNEIFORM SIGN GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FB,
+ },
+ [0x120FC]={
+ category="lo",
+ description="CUNEIFORM SIGN GAR0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FC,
+ },
+ [0x120FD]={
+ category="lo",
+ description="CUNEIFORM SIGN GASHAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FD,
+ },
+ [0x120FE]={
+ category="lo",
+ description="CUNEIFORM SIGN GESHTIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FE,
+ },
+ [0x120FF]={
+ category="lo",
+ description="CUNEIFORM SIGN GESHTIN TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x120FF,
+ },
+ [0x12100]={
+ category="lo",
+ description="CUNEIFORM SIGN GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12100,
+ },
+ [0x12101]={
+ category="lo",
+ description="CUNEIFORM SIGN GI TIMES E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12101,
+ },
+ [0x12102]={
+ category="lo",
+ description="CUNEIFORM SIGN GI TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12102,
+ },
+ [0x12103]={
+ category="lo",
+ description="CUNEIFORM SIGN GI CROSSING GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12103,
+ },
+ [0x12104]={
+ category="lo",
+ description="CUNEIFORM SIGN GI0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12104,
+ },
+ [0x12105]={
+ category="lo",
+ description="CUNEIFORM SIGN GI0x0004 OVER GI0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12105,
+ },
+ [0x12106]={
+ category="lo",
+ description="CUNEIFORM SIGN GI0x0004 CROSSING GI0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12106,
+ },
+ [0x12107]={
+ category="lo",
+ description="CUNEIFORM SIGN GIDIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12107,
+ },
+ [0x12108]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12108,
+ },
+ [0x12109]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0002 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12109,
+ },
+ [0x1210A]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210A,
+ },
+ [0x1210B]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003 TIMES A PLUS IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210B,
+ },
+ [0x1210C]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003 TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210C,
+ },
+ [0x1210D]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003 TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210D,
+ },
+ [0x1210E]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003 TIMES LU PLUS IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210E,
+ },
+ [0x1210F]={
+ category="lo",
+ description="CUNEIFORM SIGN GIR0x0003 TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1210F,
+ },
+ [0x12110]={
+ category="lo",
+ description="CUNEIFORM SIGN GISAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12110,
+ },
+ [0x12111]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12111,
+ },
+ [0x12112]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH CROSSING GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12112,
+ },
+ [0x12113]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12113,
+ },
+ [0x12114]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12114,
+ },
+ [0x12115]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12115,
+ },
+ [0x12116]={
+ category="lo",
+ description="CUNEIFORM SIGN GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12116,
+ },
+ [0x12117]={
+ category="lo",
+ description="CUNEIFORM SIGN GU CROSSING GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12117,
+ },
+ [0x12118]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12118,
+ },
+ [0x12119]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002 TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12119,
+ },
+ [0x1211A]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002 TIMES KAK TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211A,
+ },
+ [0x1211B]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002 TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211B,
+ },
+ [0x1211C]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002 TIMES SAL PLUS TUG0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211C,
+ },
+ [0x1211D]={
+ category="lo",
+ description="CUNEIFORM SIGN GU0x0002 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211D,
+ },
+ [0x1211E]={
+ category="lo",
+ description="CUNEIFORM SIGN GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211E,
+ },
+ [0x1211F]={
+ category="lo",
+ description="CUNEIFORM SIGN GUD TIMES A PLUS KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1211F,
+ },
+ [0x12120]={
+ category="lo",
+ description="CUNEIFORM SIGN GUD TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12120,
+ },
+ [0x12121]={
+ category="lo",
+ description="CUNEIFORM SIGN GUD OVER GUD LUGAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12121,
+ },
+ [0x12122]={
+ category="lo",
+ description="CUNEIFORM SIGN GUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12122,
+ },
+ [0x12123]={
+ category="lo",
+ description="CUNEIFORM SIGN GUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12123,
+ },
+ [0x12124]={
+ category="lo",
+ description="CUNEIFORM SIGN GUM TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12124,
+ },
+ [0x12125]={
+ category="lo",
+ description="CUNEIFORM SIGN GUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12125,
+ },
+ [0x12126]={
+ category="lo",
+ description="CUNEIFORM SIGN GUR0x0007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12126,
+ },
+ [0x12127]={
+ category="lo",
+ description="CUNEIFORM SIGN GURUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12127,
+ },
+ [0x12128]={
+ category="lo",
+ description="CUNEIFORM SIGN GURUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12128,
+ },
+ [0x12129]={
+ category="lo",
+ description="CUNEIFORM SIGN HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12129,
+ },
+ [0x1212A]={
+ category="lo",
+ description="CUNEIFORM SIGN HA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212A,
+ },
+ [0x1212B]={
+ category="lo",
+ description="CUNEIFORM SIGN HA GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212B,
+ },
+ [0x1212C]={
+ category="lo",
+ description="CUNEIFORM SIGN HAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212C,
+ },
+ [0x1212D]={
+ category="lo",
+ description="CUNEIFORM SIGN HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212D,
+ },
+ [0x1212E]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212E,
+ },
+ [0x1212F]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1212F,
+ },
+ [0x12130]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12130,
+ },
+ [0x12131]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12131,
+ },
+ [0x12132]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES GAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12132,
+ },
+ [0x12133]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES KIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12133,
+ },
+ [0x12134]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12134,
+ },
+ [0x12135]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12135,
+ },
+ [0x12136]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12136,
+ },
+ [0x12137]={
+ category="lo",
+ description="CUNEIFORM SIGN HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12137,
+ },
+ [0x12138]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12138,
+ },
+ [0x12139]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002 TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12139,
+ },
+ [0x1213A]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002 TIMES HAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213A,
+ },
+ [0x1213B]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002 TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213B,
+ },
+ [0x1213C]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002 TIMES LISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213C,
+ },
+ [0x1213D]={
+ category="lo",
+ description="CUNEIFORM SIGN HUB0x0002 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213D,
+ },
+ [0x1213E]={
+ category="lo",
+ description="CUNEIFORM SIGN HUL0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213E,
+ },
+ [0x1213F]={
+ category="lo",
+ description="CUNEIFORM SIGN I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1213F,
+ },
+ [0x12140]={
+ category="lo",
+ description="CUNEIFORM SIGN I A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12140,
+ },
+ [0x12141]={
+ category="lo",
+ description="CUNEIFORM SIGN IB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12141,
+ },
+ [0x12142]={
+ category="lo",
+ description="CUNEIFORM SIGN IDIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12142,
+ },
+ [0x12143]={
+ category="lo",
+ description="CUNEIFORM SIGN IDIM OVER IDIM BUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12143,
+ },
+ [0x12144]={
+ category="lo",
+ description="CUNEIFORM SIGN IDIM OVER IDIM SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12144,
+ },
+ [0x12145]={
+ category="lo",
+ description="CUNEIFORM SIGN IG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12145,
+ },
+ [0x12146]={
+ category="lo",
+ description="CUNEIFORM SIGN IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12146,
+ },
+ [0x12147]={
+ category="lo",
+ description="CUNEIFORM SIGN IGI DIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12147,
+ },
+ [0x12148]={
+ category="lo",
+ description="CUNEIFORM SIGN IGI RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12148,
+ },
+ [0x12149]={
+ category="lo",
+ description="CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12149,
+ },
+ [0x1214A]={
+ category="lo",
+ description="CUNEIFORM SIGN IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214A,
+ },
+ [0x1214B]={
+ category="lo",
+ description="CUNEIFORM SIGN IL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214B,
+ },
+ [0x1214C]={
+ category="lo",
+ description="CUNEIFORM SIGN IL TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214C,
+ },
+ [0x1214D]={
+ category="lo",
+ description="CUNEIFORM SIGN IL0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214D,
+ },
+ [0x1214E]={
+ category="lo",
+ description="CUNEIFORM SIGN IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214E,
+ },
+ [0x1214F]={
+ category="lo",
+ description="CUNEIFORM SIGN IM TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1214F,
+ },
+ [0x12150]={
+ category="lo",
+ description="CUNEIFORM SIGN IM CROSSING IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12150,
+ },
+ [0x12151]={
+ category="lo",
+ description="CUNEIFORM SIGN IM OPPOSING IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12151,
+ },
+ [0x12152]={
+ category="lo",
+ description="CUNEIFORM SIGN IM SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12152,
+ },
+ [0x12153]={
+ category="lo",
+ description="CUNEIFORM SIGN IMIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12153,
+ },
+ [0x12154]={
+ category="lo",
+ description="CUNEIFORM SIGN IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12154,
+ },
+ [0x12155]={
+ category="lo",
+ description="CUNEIFORM SIGN IR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12155,
+ },
+ [0x12156]={
+ category="lo",
+ description="CUNEIFORM SIGN ISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12156,
+ },
+ [0x12157]={
+ category="lo",
+ description="CUNEIFORM SIGN KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12157,
+ },
+ [0x12158]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12158,
+ },
+ [0x12159]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES AD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12159,
+ },
+ [0x1215A]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES AD PLUS KU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215A,
+ },
+ [0x1215B]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215B,
+ },
+ [0x1215C]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215C,
+ },
+ [0x1215D]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES BALAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215D,
+ },
+ [0x1215E]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215E,
+ },
+ [0x1215F]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1215F,
+ },
+ [0x12160]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ERIN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12160,
+ },
+ [0x12161]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12161,
+ },
+ [0x12162]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12162,
+ },
+ [0x12163]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12163,
+ },
+ [0x12164]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12164,
+ },
+ [0x12165]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12165,
+ },
+ [0x12166]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GAR PLUS SHA0x0003 PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12166,
+ },
+ [0x12167]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12167,
+ },
+ [0x12168]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GIR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12168,
+ },
+ [0x12169]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GISH PLUS SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12169,
+ },
+ [0x1216A]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GISH CROSSING GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216A,
+ },
+ [0x1216B]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216B,
+ },
+ [0x1216C]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GUR0x0007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216C,
+ },
+ [0x1216D]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216D,
+ },
+ [0x1216E]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216E,
+ },
+ [0x1216F]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1216F,
+ },
+ [0x12170]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12170,
+ },
+ [0x12171]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES KID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12171,
+ },
+ [0x12172]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12172,
+ },
+ [0x12173]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12173,
+ },
+ [0x12174]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12174,
+ },
+ [0x12175]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ME PLUS DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12175,
+ },
+ [0x12176]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ME PLUS GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12176,
+ },
+ [0x12177]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ME PLUS TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12177,
+ },
+ [0x12178]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12178,
+ },
+ [0x12179]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12179,
+ },
+ [0x1217A]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217A,
+ },
+ [0x1217B]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217B,
+ },
+ [0x1217C]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217C,
+ },
+ [0x1217D]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217D,
+ },
+ [0x1217E]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217E,
+ },
+ [0x1217F]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1217F,
+ },
+ [0x12180]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12180,
+ },
+ [0x12181]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12181,
+ },
+ [0x12182]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SHID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12182,
+ },
+ [0x12183]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12183,
+ },
+ [0x12184]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12184,
+ },
+ [0x12185]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SUHUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12185,
+ },
+ [0x12186]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES TAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12186,
+ },
+ [0x12187]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12187,
+ },
+ [0x12188]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12188,
+ },
+ [0x12189]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12189,
+ },
+ [0x1218A]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES UMUM TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218A,
+ },
+ [0x1218B]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218B,
+ },
+ [0x1218C]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218C,
+ },
+ [0x1218D]={
+ category="lo",
+ description="CUNEIFORM SIGN KA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218D,
+ },
+ [0x1218E]={
+ category="lo",
+ description="CUNEIFORM SIGN KA0x0002 CROSSING KA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218E,
+ },
+ [0x1218F]={
+ category="lo",
+ description="CUNEIFORM SIGN KAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1218F,
+ },
+ [0x12190]={
+ category="lo",
+ description="CUNEIFORM SIGN KAD0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12190,
+ },
+ [0x12191]={
+ category="lo",
+ description="CUNEIFORM SIGN KAD0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12191,
+ },
+ [0x12192]={
+ category="lo",
+ description="CUNEIFORM SIGN KAD0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12192,
+ },
+ [0x12193]={
+ category="lo",
+ description="CUNEIFORM SIGN KAD0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12193,
+ },
+ [0x12194]={
+ category="lo",
+ description="CUNEIFORM SIGN KAD0x0005 OVER KAD0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12194,
+ },
+ [0x12195]={
+ category="lo",
+ description="CUNEIFORM SIGN KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12195,
+ },
+ [0x12196]={
+ category="lo",
+ description="CUNEIFORM SIGN KAK TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12196,
+ },
+ [0x12197]={
+ category="lo",
+ description="CUNEIFORM SIGN KAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12197,
+ },
+ [0x12198]={
+ category="lo",
+ description="CUNEIFORM SIGN KAL TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12198,
+ },
+ [0x12199]={
+ category="lo",
+ description="CUNEIFORM SIGN KAL CROSSING KAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12199,
+ },
+ [0x1219A]={
+ category="lo",
+ description="CUNEIFORM SIGN KAM0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219A,
+ },
+ [0x1219B]={
+ category="lo",
+ description="CUNEIFORM SIGN KAM0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219B,
+ },
+ [0x1219C]={
+ category="lo",
+ description="CUNEIFORM SIGN KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219C,
+ },
+ [0x1219D]={
+ category="lo",
+ description="CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219D,
+ },
+ [0x1219E]={
+ category="lo",
+ description="CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219E,
+ },
+ [0x1219F]={
+ category="lo",
+ description="CUNEIFORM SIGN KESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1219F,
+ },
+ [0x121A0]={
+ category="lo",
+ description="CUNEIFORM SIGN KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A0,
+ },
+ [0x121A1]={
+ category="lo",
+ description="CUNEIFORM SIGN KI TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A1,
+ },
+ [0x121A2]={
+ category="lo",
+ description="CUNEIFORM SIGN KI TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A2,
+ },
+ [0x121A3]={
+ category="lo",
+ description="CUNEIFORM SIGN KI TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A3,
+ },
+ [0x121A4]={
+ category="lo",
+ description="CUNEIFORM SIGN KID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A4,
+ },
+ [0x121A5]={
+ category="lo",
+ description="CUNEIFORM SIGN KIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A5,
+ },
+ [0x121A6]={
+ category="lo",
+ description="CUNEIFORM SIGN KISAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A6,
+ },
+ [0x121A7]={
+ category="lo",
+ description="CUNEIFORM SIGN KISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A7,
+ },
+ [0x121A8]={
+ category="lo",
+ description="CUNEIFORM SIGN KISIM0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A8,
+ },
+ [0x121A9]={
+ category="lo",
+ description="CUNEIFORM SIGN KISIM0x0005 OVER KISIM0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121A9,
+ },
+ [0x121AA]={
+ category="lo",
+ description="CUNEIFORM SIGN KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AA,
+ },
+ [0x121AB]={
+ category="lo",
+ description="CUNEIFORM SIGN KU OVER HI TIMES ASH0x0002 KU OVER HI TIMES ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AB,
+ },
+ [0x121AC]={
+ category="lo",
+ description="CUNEIFORM SIGN KU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AC,
+ },
+ [0x121AD]={
+ category="lo",
+ description="CUNEIFORM SIGN KU0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AD,
+ },
+ [0x121AE]={
+ category="lo",
+ description="CUNEIFORM SIGN KU0x0004 VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AE,
+ },
+ [0x121AF]={
+ category="lo",
+ description="CUNEIFORM SIGN KU0x0007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121AF,
+ },
+ [0x121B0]={
+ category="lo",
+ description="CUNEIFORM SIGN KUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B0,
+ },
+ [0x121B1]={
+ category="lo",
+ description="CUNEIFORM SIGN KUL GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B1,
+ },
+ [0x121B2]={
+ category="lo",
+ description="CUNEIFORM SIGN KUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B2,
+ },
+ [0x121B3]={
+ category="lo",
+ description="CUNEIFORM SIGN KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B3,
+ },
+ [0x121B4]={
+ category="lo",
+ description="CUNEIFORM SIGN KUR OPPOSING KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B4,
+ },
+ [0x121B5]={
+ category="lo",
+ description="CUNEIFORM SIGN KUSHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B5,
+ },
+ [0x121B6]={
+ category="lo",
+ description="CUNEIFORM SIGN KWU0x013E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B6,
+ },
+ [0x121B7]={
+ category="lo",
+ description="CUNEIFORM SIGN LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B7,
+ },
+ [0x121B8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B8,
+ },
+ [0x121B9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121B9,
+ },
+ [0x121BA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BA,
+ },
+ [0x121BB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES A PLUS GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BB,
+ },
+ [0x121BC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES A PLUS LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BC,
+ },
+ [0x121BD]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BD,
+ },
+ [0x121BE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BE,
+ },
+ [0x121BF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121BF,
+ },
+ [0x121C0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C0,
+ },
+ [0x121C1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C1,
+ },
+ [0x121C2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES DAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C2,
+ },
+ [0x121C3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C3,
+ },
+ [0x121C4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C4,
+ },
+ [0x121C5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C5,
+ },
+ [0x121C6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C6,
+ },
+ [0x121C7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C7,
+ },
+ [0x121C8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C8,
+ },
+ [0x121C9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES HAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121C9,
+ },
+ [0x121CA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CA,
+ },
+ [0x121CB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CB,
+ },
+ [0x121CC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CC,
+ },
+ [0x121CD]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES IM PLUS HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CD,
+ },
+ [0x121CE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES IM PLUS LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CE,
+ },
+ [0x121CF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121CF,
+ },
+ [0x121D0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES KIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D0,
+ },
+ [0x121D1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES KU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D1,
+ },
+ [0x121D2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES KUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D2,
+ },
+ [0x121D3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D3,
+ },
+ [0x121D4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES LAGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D4,
+ },
+ [0x121D5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES LISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D5,
+ },
+ [0x121D6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D6,
+ },
+ [0x121D7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES LUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D7,
+ },
+ [0x121D8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D8,
+ },
+ [0x121D9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES ME PLUS EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121D9,
+ },
+ [0x121DA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DA,
+ },
+ [0x121DB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DB,
+ },
+ [0x121DC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DC,
+ },
+ [0x121DD]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DD,
+ },
+ [0x121DE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DE,
+ },
+ [0x121DF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121DF,
+ },
+ [0x121E0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SHU0x0002 PLUS SHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E0,
+ },
+ [0x121E1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES SUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E1,
+ },
+ [0x121E2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES TAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E2,
+ },
+ [0x121E3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E3,
+ },
+ [0x121E4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E4,
+ },
+ [0x121E5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E5,
+ },
+ [0x121E6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES U PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E6,
+ },
+ [0x121E7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E7,
+ },
+ [0x121E8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES U0x0002 PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E8,
+ },
+ [0x121E9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121E9,
+ },
+ [0x121EA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121EA,
+ },
+ [0x121EB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121EB,
+ },
+ [0x121EC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121EC,
+ },
+ [0x121ED]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAR TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121ED,
+ },
+ [0x121EE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121EE,
+ },
+ [0x121EF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAR GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121EF,
+ },
+ [0x121F0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F0,
+ },
+ [0x121F1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAHSHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F1,
+ },
+ [0x121F2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F2,
+ },
+ [0x121F3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAL TIMES LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F3,
+ },
+ [0x121F4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F4,
+ },
+ [0x121F5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAM TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F5,
+ },
+ [0x121F6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAM TIMES KUR PLUS RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F6,
+ },
+ [0x121F7]={
+ category="lo",
+ description="CUNEIFORM SIGN LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F7,
+ },
+ [0x121F8]={
+ category="lo",
+ description="CUNEIFORM SIGN LIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F8,
+ },
+ [0x121F9]={
+ category="lo",
+ description="CUNEIFORM SIGN LIMMU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121F9,
+ },
+ [0x121FA]={
+ category="lo",
+ description="CUNEIFORM SIGN LISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FA,
+ },
+ [0x121FB]={
+ category="lo",
+ description="CUNEIFORM SIGN LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FB,
+ },
+ [0x121FC]={
+ category="lo",
+ description="CUNEIFORM SIGN LU TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FC,
+ },
+ [0x121FD]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FD,
+ },
+ [0x121FE]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FE,
+ },
+ [0x121FF]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x121FF,
+ },
+ [0x12200]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES ESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12200,
+ },
+ [0x12201]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES ESH0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12201,
+ },
+ [0x12202]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12202,
+ },
+ [0x12203]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES HI TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12203,
+ },
+ [0x12204]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12204,
+ },
+ [0x12205]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES KAD0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12205,
+ },
+ [0x12206]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES KAD0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12206,
+ },
+ [0x12207]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES KAD0x0003 PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12207,
+ },
+ [0x12208]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12208,
+ },
+ [0x12209]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES LA PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12209,
+ },
+ [0x1220A]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES LAGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220A,
+ },
+ [0x1220B]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES ME PLUS EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220B,
+ },
+ [0x1220C]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220C,
+ },
+ [0x1220D]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220D,
+ },
+ [0x1220E]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES SI PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220E,
+ },
+ [0x1220F]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES SIK0x0002 PLUS BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1220F,
+ },
+ [0x12210]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TIMES TUG0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12210,
+ },
+ [0x12211]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12211,
+ },
+ [0x12212]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 CROSSING LU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12212,
+ },
+ [0x12213]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 OPPOSING LU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12213,
+ },
+ [0x12214]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12214,
+ },
+ [0x12215]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0002 SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12215,
+ },
+ [0x12216]={
+ category="lo",
+ description="CUNEIFORM SIGN LU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12216,
+ },
+ [0x12217]={
+ category="lo",
+ description="CUNEIFORM SIGN LUGAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12217,
+ },
+ [0x12218]={
+ category="lo",
+ description="CUNEIFORM SIGN LUGAL OVER LUGAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12218,
+ },
+ [0x12219]={
+ category="lo",
+ description="CUNEIFORM SIGN LUGAL OPPOSING LUGAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12219,
+ },
+ [0x1221A]={
+ category="lo",
+ description="CUNEIFORM SIGN LUGAL SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221A,
+ },
+ [0x1221B]={
+ category="lo",
+ description="CUNEIFORM SIGN LUH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221B,
+ },
+ [0x1221C]={
+ category="lo",
+ description="CUNEIFORM SIGN LUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221C,
+ },
+ [0x1221D]={
+ category="lo",
+ description="CUNEIFORM SIGN LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221D,
+ },
+ [0x1221E]={
+ category="lo",
+ description="CUNEIFORM SIGN LUM OVER LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221E,
+ },
+ [0x1221F]={
+ category="lo",
+ description="CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1221F,
+ },
+ [0x12220]={
+ category="lo",
+ description="CUNEIFORM SIGN MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12220,
+ },
+ [0x12221]={
+ category="lo",
+ description="CUNEIFORM SIGN MA TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12221,
+ },
+ [0x12222]={
+ category="lo",
+ description="CUNEIFORM SIGN MA GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12222,
+ },
+ [0x12223]={
+ category="lo",
+ description="CUNEIFORM SIGN MA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12223,
+ },
+ [0x12224]={
+ category="lo",
+ description="CUNEIFORM SIGN MAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12224,
+ },
+ [0x12225]={
+ category="lo",
+ description="CUNEIFORM SIGN MAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12225,
+ },
+ [0x12226]={
+ category="lo",
+ description="CUNEIFORM SIGN MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12226,
+ },
+ [0x12227]={
+ category="lo",
+ description="CUNEIFORM SIGN MASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12227,
+ },
+ [0x12228]={
+ category="lo",
+ description="CUNEIFORM SIGN ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12228,
+ },
+ [0x12229]={
+ category="lo",
+ description="CUNEIFORM SIGN MES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12229,
+ },
+ [0x1222A]={
+ category="lo",
+ description="CUNEIFORM SIGN MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222A,
+ },
+ [0x1222B]={
+ category="lo",
+ description="CUNEIFORM SIGN MIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222B,
+ },
+ [0x1222C]={
+ category="lo",
+ description="CUNEIFORM SIGN MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222C,
+ },
+ [0x1222D]={
+ category="lo",
+ description="CUNEIFORM SIGN MU OVER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222D,
+ },
+ [0x1222E]={
+ category="lo",
+ description="CUNEIFORM SIGN MUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222E,
+ },
+ [0x1222F]={
+ category="lo",
+ description="CUNEIFORM SIGN MUG GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1222F,
+ },
+ [0x12230]={
+ category="lo",
+ description="CUNEIFORM SIGN MUNSUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12230,
+ },
+ [0x12231]={
+ category="lo",
+ description="CUNEIFORM SIGN MURGU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12231,
+ },
+ [0x12232]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12232,
+ },
+ [0x12233]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12233,
+ },
+ [0x12234]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12234,
+ },
+ [0x12235]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH TIMES ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12235,
+ },
+ [0x12236]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH OVER MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12236,
+ },
+ [0x12237]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12237,
+ },
+ [0x12238]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH CROSSING MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12238,
+ },
+ [0x12239]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12239,
+ },
+ [0x1223A]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH0x0003 TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223A,
+ },
+ [0x1223B]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH0x0003 TIMES A PLUS DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223B,
+ },
+ [0x1223C]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH0x0003 TIMES DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223C,
+ },
+ [0x1223D]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH0x0003 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223D,
+ },
+ [0x1223E]={
+ category="lo",
+ description="CUNEIFORM SIGN NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223E,
+ },
+ [0x1223F]={
+ category="lo",
+ description="CUNEIFORM SIGN NA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1223F,
+ },
+ [0x12240]={
+ category="lo",
+ description="CUNEIFORM SIGN NAGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12240,
+ },
+ [0x12241]={
+ category="lo",
+ description="CUNEIFORM SIGN NAGA INVERTED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12241,
+ },
+ [0x12242]={
+ category="lo",
+ description="CUNEIFORM SIGN NAGA TIMES SHU TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12242,
+ },
+ [0x12243]={
+ category="lo",
+ description="CUNEIFORM SIGN NAGA OPPOSING NAGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12243,
+ },
+ [0x12244]={
+ category="lo",
+ description="CUNEIFORM SIGN NAGAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12244,
+ },
+ [0x12245]={
+ category="lo",
+ description="CUNEIFORM SIGN NAM NUTILLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12245,
+ },
+ [0x12246]={
+ category="lo",
+ description="CUNEIFORM SIGN NAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12246,
+ },
+ [0x12247]={
+ category="lo",
+ description="CUNEIFORM SIGN NAM0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12247,
+ },
+ [0x12248]={
+ category="lo",
+ description="CUNEIFORM SIGN NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12248,
+ },
+ [0x12249]={
+ category="lo",
+ description="CUNEIFORM SIGN NE TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12249,
+ },
+ [0x1224A]={
+ category="lo",
+ description="CUNEIFORM SIGN NE TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224A,
+ },
+ [0x1224B]={
+ category="lo",
+ description="CUNEIFORM SIGN NE SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224B,
+ },
+ [0x1224C]={
+ category="lo",
+ description="CUNEIFORM SIGN NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224C,
+ },
+ [0x1224D]={
+ category="lo",
+ description="CUNEIFORM SIGN NI TIMES E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224D,
+ },
+ [0x1224E]={
+ category="lo",
+ description="CUNEIFORM SIGN NI0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224E,
+ },
+ [0x1224F]={
+ category="lo",
+ description="CUNEIFORM SIGN NIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1224F,
+ },
+ [0x12250]={
+ category="lo",
+ description="CUNEIFORM SIGN NIM TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12250,
+ },
+ [0x12251]={
+ category="lo",
+ description="CUNEIFORM SIGN NIM TIMES GAR PLUS GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12251,
+ },
+ [0x12252]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12252,
+ },
+ [0x12253]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12253,
+ },
+ [0x12254]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12254,
+ },
+ [0x12255]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES ASH PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12255,
+ },
+ [0x12256]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12256,
+ },
+ [0x12257]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES ME PLUS GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12257,
+ },
+ [0x12258]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12258,
+ },
+ [0x12259]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12259,
+ },
+ [0x1225A]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225A,
+ },
+ [0x1225B]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES SHE PLUS A AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225B,
+ },
+ [0x1225C]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES SHE PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225C,
+ },
+ [0x1225D]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES SHE PLUS ASH PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225D,
+ },
+ [0x1225E]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES U0x0002 PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225E,
+ },
+ [0x1225F]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA0x0002 TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1225F,
+ },
+ [0x12260]={
+ category="lo",
+ description="CUNEIFORM SIGN NISAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12260,
+ },
+ [0x12261]={
+ category="lo",
+ description="CUNEIFORM SIGN NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12261,
+ },
+ [0x12262]={
+ category="lo",
+ description="CUNEIFORM SIGN NU0x000B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12262,
+ },
+ [0x12263]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12263,
+ },
+ [0x12264]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN LAGAR TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12264,
+ },
+ [0x12265]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN LAGAR TIMES MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12265,
+ },
+ [0x12266]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN LAGAR TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12266,
+ },
+ [0x12267]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12267,
+ },
+ [0x12268]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN LAGAR TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12268,
+ },
+ [0x12269]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12269,
+ },
+ [0x1226A]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN OVER NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226A,
+ },
+ [0x1226B]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN CROSSING NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226B,
+ },
+ [0x1226C]={
+ category="lo",
+ description="CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226C,
+ },
+ [0x1226D]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226D,
+ },
+ [0x1226E]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES ASHGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226E,
+ },
+ [0x1226F]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1226F,
+ },
+ [0x12270]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES DUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12270,
+ },
+ [0x12271]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12271,
+ },
+ [0x12272]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12272,
+ },
+ [0x12273]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES KAD0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12273,
+ },
+ [0x12274]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12274,
+ },
+ [0x12275]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12275,
+ },
+ [0x12276]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES SILA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12276,
+ },
+ [0x12277]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ AB0x0002 TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12277,
+ },
+ [0x12278]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ KISIM0x0005 TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12278,
+ },
+ [0x12279]={
+ category="lo",
+ description="CUNEIFORM SIGN NUNUZ KISIM0x0005 TIMES BI U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12279,
+ },
+ [0x1227A]={
+ category="lo",
+ description="CUNEIFORM SIGN PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227A,
+ },
+ [0x1227B]={
+ category="lo",
+ description="CUNEIFORM SIGN PAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227B,
+ },
+ [0x1227C]={
+ category="lo",
+ description="CUNEIFORM SIGN PAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227C,
+ },
+ [0x1227D]={
+ category="lo",
+ description="CUNEIFORM SIGN PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227D,
+ },
+ [0x1227E]={
+ category="lo",
+ description="CUNEIFORM SIGN PESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227E,
+ },
+ [0x1227F]={
+ category="lo",
+ description="CUNEIFORM SIGN PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1227F,
+ },
+ [0x12280]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12280,
+ },
+ [0x12281]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES AB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12281,
+ },
+ [0x12282]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12282,
+ },
+ [0x12283]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12283,
+ },
+ [0x12284]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12284,
+ },
+ [0x12285]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12285,
+ },
+ [0x12286]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES IB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12286,
+ },
+ [0x12287]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12287,
+ },
+ [0x12288]={
+ category="lo",
+ description="CUNEIFORM SIGN PI TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12288,
+ },
+ [0x12289]={
+ category="lo",
+ description="CUNEIFORM SIGN PI CROSSING PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12289,
+ },
+ [0x1228A]={
+ category="lo",
+ description="CUNEIFORM SIGN PIRIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228A,
+ },
+ [0x1228B]={
+ category="lo",
+ description="CUNEIFORM SIGN PIRIG TIMES KAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228B,
+ },
+ [0x1228C]={
+ category="lo",
+ description="CUNEIFORM SIGN PIRIG TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228C,
+ },
+ [0x1228D]={
+ category="lo",
+ description="CUNEIFORM SIGN PIRIG TIMES ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228D,
+ },
+ [0x1228E]={
+ category="lo",
+ description="CUNEIFORM SIGN PIRIG OPPOSING PIRIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228E,
+ },
+ [0x1228F]={
+ category="lo",
+ description="CUNEIFORM SIGN RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1228F,
+ },
+ [0x12290]={
+ category="lo",
+ description="CUNEIFORM SIGN RAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12290,
+ },
+ [0x12291]={
+ category="lo",
+ description="CUNEIFORM SIGN RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12291,
+ },
+ [0x12292]={
+ category="lo",
+ description="CUNEIFORM SIGN RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12292,
+ },
+ [0x12293]={
+ category="lo",
+ description="CUNEIFORM SIGN SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12293,
+ },
+ [0x12294]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG NUTILLU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12294,
+ },
+ [0x12295]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12295,
+ },
+ [0x12296]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12296,
+ },
+ [0x12297]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12297,
+ },
+ [0x12298]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES DUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12298,
+ },
+ [0x12299]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12299,
+ },
+ [0x1229A]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229A,
+ },
+ [0x1229B]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229B,
+ },
+ [0x1229C]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229C,
+ },
+ [0x1229D]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229D,
+ },
+ [0x1229E]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229E,
+ },
+ [0x1229F]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1229F,
+ },
+ [0x122A0]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES SHID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A0,
+ },
+ [0x122A1]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES TAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A1,
+ },
+ [0x122A2]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A2,
+ },
+ [0x122A3]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES UB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A3,
+ },
+ [0x122A4]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES UM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A4,
+ },
+ [0x122A5]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES UR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A5,
+ },
+ [0x122A6]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A6,
+ },
+ [0x122A7]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG OVER SAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A7,
+ },
+ [0x122A8]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A8,
+ },
+ [0x122A9]={
+ category="lo",
+ description="CUNEIFORM SIGN SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122A9,
+ },
+ [0x122AA]={
+ category="lo",
+ description="CUNEIFORM SIGN SAL LAGAB TIMES ASH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AA,
+ },
+ [0x122AB]={
+ category="lo",
+ description="CUNEIFORM SIGN SANGA0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AB,
+ },
+ [0x122AC]={
+ category="lo",
+ description="CUNEIFORM SIGN SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AC,
+ },
+ [0x122AD]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AD,
+ },
+ [0x122AE]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AE,
+ },
+ [0x122AF]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122AF,
+ },
+ [0x122B0]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B0,
+ },
+ [0x122B1]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B1,
+ },
+ [0x122B2]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B2,
+ },
+ [0x122B3]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES SHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B3,
+ },
+ [0x122B4]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES TUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B4,
+ },
+ [0x122B5]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B5,
+ },
+ [0x122B6]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0003 TIMES U PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B6,
+ },
+ [0x122B7]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA0x0006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B7,
+ },
+ [0x122B8]={
+ category="lo",
+ description="CUNEIFORM SIGN SHAB0x0006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B8,
+ },
+ [0x122B9]={
+ category="lo",
+ description="CUNEIFORM SIGN SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122B9,
+ },
+ [0x122BA]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BA,
+ },
+ [0x122BB]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BB,
+ },
+ [0x122BC]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BC,
+ },
+ [0x122BD]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BD,
+ },
+ [0x122BE]={
+ category="lo",
+ description="CUNEIFORM SIGN SHEG0x0009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BE,
+ },
+ [0x122BF]={
+ category="lo",
+ description="CUNEIFORM SIGN SHEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122BF,
+ },
+ [0x122C0]={
+ category="lo",
+ description="CUNEIFORM SIGN SHESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C0,
+ },
+ [0x122C1]={
+ category="lo",
+ description="CUNEIFORM SIGN SHESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C1,
+ },
+ [0x122C2]={
+ category="lo",
+ description="CUNEIFORM SIGN SHESHLAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C2,
+ },
+ [0x122C3]={
+ category="lo",
+ description="CUNEIFORM SIGN SHID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C3,
+ },
+ [0x122C4]={
+ category="lo",
+ description="CUNEIFORM SIGN SHID TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C4,
+ },
+ [0x122C5]={
+ category="lo",
+ description="CUNEIFORM SIGN SHID TIMES IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C5,
+ },
+ [0x122C6]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C6,
+ },
+ [0x122C7]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C7,
+ },
+ [0x122C8]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES BAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C8,
+ },
+ [0x122C9]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES BULUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122C9,
+ },
+ [0x122CA]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES DIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CA,
+ },
+ [0x122CB]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CB,
+ },
+ [0x122CC]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CC,
+ },
+ [0x122CD]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CD,
+ },
+ [0x122CE]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES KUSHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CE,
+ },
+ [0x122CF]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES LUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122CF,
+ },
+ [0x122D0]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES MUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D0,
+ },
+ [0x122D1]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIM TIMES SAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D1,
+ },
+ [0x122D2]={
+ category="lo",
+ description="CUNEIFORM SIGN SHINIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D2,
+ },
+ [0x122D3]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D3,
+ },
+ [0x122D4]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIR TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D4,
+ },
+ [0x122D5]={
+ category="lo",
+ description="CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D5,
+ },
+ [0x122D6]={
+ category="lo",
+ description="CUNEIFORM SIGN SHITA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D6,
+ },
+ [0x122D7]={
+ category="lo",
+ description="CUNEIFORM SIGN SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D7,
+ },
+ [0x122D8]={
+ category="lo",
+ description="CUNEIFORM SIGN SHU OVER INVERTED SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D8,
+ },
+ [0x122D9]={
+ category="lo",
+ description="CUNEIFORM SIGN SHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122D9,
+ },
+ [0x122DA]={
+ category="lo",
+ description="CUNEIFORM SIGN SHUBUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DA,
+ },
+ [0x122DB]={
+ category="lo",
+ description="CUNEIFORM SIGN SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DB,
+ },
+ [0x122DC]={
+ category="lo",
+ description="CUNEIFORM SIGN SI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DC,
+ },
+ [0x122DD]={
+ category="lo",
+ description="CUNEIFORM SIGN SIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DD,
+ },
+ [0x122DE]={
+ category="lo",
+ description="CUNEIFORM SIGN SIG0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DE,
+ },
+ [0x122DF]={
+ category="lo",
+ description="CUNEIFORM SIGN SIG0x0004 OVER SIG0x0004 SHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122DF,
+ },
+ [0x122E0]={
+ category="lo",
+ description="CUNEIFORM SIGN SIK0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E0,
+ },
+ [0x122E1]={
+ category="lo",
+ description="CUNEIFORM SIGN SILA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E1,
+ },
+ [0x122E2]={
+ category="lo",
+ description="CUNEIFORM SIGN SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E2,
+ },
+ [0x122E3]={
+ category="lo",
+ description="CUNEIFORM SIGN SU OVER SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E3,
+ },
+ [0x122E4]={
+ category="lo",
+ description="CUNEIFORM SIGN SUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E4,
+ },
+ [0x122E5]={
+ category="lo",
+ description="CUNEIFORM SIGN SUD0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E5,
+ },
+ [0x122E6]={
+ category="lo",
+ description="CUNEIFORM SIGN SUHUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E6,
+ },
+ [0x122E7]={
+ category="lo",
+ description="CUNEIFORM SIGN SUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E7,
+ },
+ [0x122E8]={
+ category="lo",
+ description="CUNEIFORM SIGN SUMASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E8,
+ },
+ [0x122E9]={
+ category="lo",
+ description="CUNEIFORM SIGN SUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122E9,
+ },
+ [0x122EA]={
+ category="lo",
+ description="CUNEIFORM SIGN SUR0x0009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122EA,
+ },
+ [0x122EB]={
+ category="lo",
+ description="CUNEIFORM SIGN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122EB,
+ },
+ [0x122EC]={
+ category="lo",
+ description="CUNEIFORM SIGN TA ASTERISK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122EC,
+ },
+ [0x122ED]={
+ category="lo",
+ description="CUNEIFORM SIGN TA TIMES HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122ED,
+ },
+ [0x122EE]={
+ category="lo",
+ description="CUNEIFORM SIGN TA TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122EE,
+ },
+ [0x122EF]={
+ category="lo",
+ description="CUNEIFORM SIGN TA GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122EF,
+ },
+ [0x122F0]={
+ category="lo",
+ description="CUNEIFORM SIGN TAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F0,
+ },
+ [0x122F1]={
+ category="lo",
+ description="CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F1,
+ },
+ [0x122F2]={
+ category="lo",
+ description="CUNEIFORM SIGN TAB SQUARED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F2,
+ },
+ [0x122F3]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F3,
+ },
+ [0x122F4]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F4,
+ },
+ [0x122F5]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F5,
+ },
+ [0x122F6]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F6,
+ },
+ [0x122F7]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F7,
+ },
+ [0x122F8]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES TUG0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F8,
+ },
+ [0x122F9]={
+ category="lo",
+ description="CUNEIFORM SIGN TAG TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122F9,
+ },
+ [0x122FA]={
+ category="lo",
+ description="CUNEIFORM SIGN TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FA,
+ },
+ [0x122FB]={
+ category="lo",
+ description="CUNEIFORM SIGN TAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FB,
+ },
+ [0x122FC]={
+ category="lo",
+ description="CUNEIFORM SIGN TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FC,
+ },
+ [0x122FD]={
+ category="lo",
+ description="CUNEIFORM SIGN TE GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FD,
+ },
+ [0x122FE]={
+ category="lo",
+ description="CUNEIFORM SIGN TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FE,
+ },
+ [0x122FF]={
+ category="lo",
+ description="CUNEIFORM SIGN TI TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x122FF,
+ },
+ [0x12300]={
+ category="lo",
+ description="CUNEIFORM SIGN TIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12300,
+ },
+ [0x12301]={
+ category="lo",
+ description="CUNEIFORM SIGN TIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12301,
+ },
+ [0x12302]={
+ category="lo",
+ description="CUNEIFORM SIGN TIR TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12302,
+ },
+ [0x12303]={
+ category="lo",
+ description="CUNEIFORM SIGN TIR OVER TIR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12303,
+ },
+ [0x12304]={
+ category="lo",
+ description="CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12304,
+ },
+ [0x12305]={
+ category="lo",
+ description="CUNEIFORM SIGN TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12305,
+ },
+ [0x12306]={
+ category="lo",
+ description="CUNEIFORM SIGN TUG0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12306,
+ },
+ [0x12307]={
+ category="lo",
+ description="CUNEIFORM SIGN TUK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12307,
+ },
+ [0x12308]={
+ category="lo",
+ description="CUNEIFORM SIGN TUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12308,
+ },
+ [0x12309]={
+ category="lo",
+ description="CUNEIFORM SIGN TUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12309,
+ },
+ [0x1230A]={
+ category="lo",
+ description="CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230A,
+ },
+ [0x1230B]={
+ category="lo",
+ description="CUNEIFORM SIGN U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230B,
+ },
+ [0x1230C]={
+ category="lo",
+ description="CUNEIFORM SIGN U GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230C,
+ },
+ [0x1230D]={
+ category="lo",
+ description="CUNEIFORM SIGN U U U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230D,
+ },
+ [0x1230E]={
+ category="lo",
+ description="CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230E,
+ },
+ [0x1230F]={
+ category="lo",
+ description="CUNEIFORM SIGN U OVER U SUR OVER SUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1230F,
+ },
+ [0x12310]={
+ category="lo",
+ description="CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12310,
+ },
+ [0x12311]={
+ category="lo",
+ description="CUNEIFORM SIGN U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12311,
+ },
+ [0x12312]={
+ category="lo",
+ description="CUNEIFORM SIGN UB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12312,
+ },
+ [0x12313]={
+ category="lo",
+ description="CUNEIFORM SIGN UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12313,
+ },
+ [0x12314]={
+ category="lo",
+ description="CUNEIFORM SIGN UD KUSHU0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12314,
+ },
+ [0x12315]={
+ category="lo",
+ description="CUNEIFORM SIGN UD TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12315,
+ },
+ [0x12316]={
+ category="lo",
+ description="CUNEIFORM SIGN UD TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12316,
+ },
+ [0x12317]={
+ category="lo",
+ description="CUNEIFORM SIGN UD TIMES U PLUS U PLUS U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12317,
+ },
+ [0x12318]={
+ category="lo",
+ description="CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12318,
+ },
+ [0x12319]={
+ category="lo",
+ description="CUNEIFORM SIGN UD GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12319,
+ },
+ [0x1231A]={
+ category="lo",
+ description="CUNEIFORM SIGN UD SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231A,
+ },
+ [0x1231B]={
+ category="lo",
+ description="CUNEIFORM SIGN UD SHESHIG TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231B,
+ },
+ [0x1231C]={
+ category="lo",
+ description="CUNEIFORM SIGN UDUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231C,
+ },
+ [0x1231D]={
+ category="lo",
+ description="CUNEIFORM SIGN UM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231D,
+ },
+ [0x1231E]={
+ category="lo",
+ description="CUNEIFORM SIGN UM TIMES LAGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231E,
+ },
+ [0x1231F]={
+ category="lo",
+ description="CUNEIFORM SIGN UM TIMES ME PLUS DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1231F,
+ },
+ [0x12320]={
+ category="lo",
+ description="CUNEIFORM SIGN UM TIMES SHA0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12320,
+ },
+ [0x12321]={
+ category="lo",
+ description="CUNEIFORM SIGN UM TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12321,
+ },
+ [0x12322]={
+ category="lo",
+ description="CUNEIFORM SIGN UMBIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12322,
+ },
+ [0x12323]={
+ category="lo",
+ description="CUNEIFORM SIGN UMUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12323,
+ },
+ [0x12324]={
+ category="lo",
+ description="CUNEIFORM SIGN UMUM TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12324,
+ },
+ [0x12325]={
+ category="lo",
+ description="CUNEIFORM SIGN UMUM TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12325,
+ },
+ [0x12326]={
+ category="lo",
+ description="CUNEIFORM SIGN UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12326,
+ },
+ [0x12327]={
+ category="lo",
+ description="CUNEIFORM SIGN UN GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12327,
+ },
+ [0x12328]={
+ category="lo",
+ description="CUNEIFORM SIGN UR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12328,
+ },
+ [0x12329]={
+ category="lo",
+ description="CUNEIFORM SIGN UR CROSSING UR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12329,
+ },
+ [0x1232A]={
+ category="lo",
+ description="CUNEIFORM SIGN UR SHESHIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232A,
+ },
+ [0x1232B]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232B,
+ },
+ [0x1232C]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES A PLUS HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232C,
+ },
+ [0x1232D]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES A PLUS NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232D,
+ },
+ [0x1232E]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232E,
+ },
+ [0x1232F]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1232F,
+ },
+ [0x12330]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12330,
+ },
+ [0x12331]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES U0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12331,
+ },
+ [0x12332]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES U0x0002 PLUS ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12332,
+ },
+ [0x12333]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0002 TIMES U0x0002 PLUS BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12333,
+ },
+ [0x12334]={
+ category="lo",
+ description="CUNEIFORM SIGN UR0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12334,
+ },
+ [0x12335]={
+ category="lo",
+ description="CUNEIFORM SIGN URI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12335,
+ },
+ [0x12336]={
+ category="lo",
+ description="CUNEIFORM SIGN URI0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12336,
+ },
+ [0x12337]={
+ category="lo",
+ description="CUNEIFORM SIGN URU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12337,
+ },
+ [0x12338]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12338,
+ },
+ [0x12339]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES ASHGAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12339,
+ },
+ [0x1233A]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233A,
+ },
+ [0x1233B]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES DUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233B,
+ },
+ [0x1233C]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233C,
+ },
+ [0x1233D]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES GAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233D,
+ },
+ [0x1233E]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES GAN0x0002 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233E,
+ },
+ [0x1233F]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES GAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1233F,
+ },
+ [0x12340]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12340,
+ },
+ [0x12341]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12341,
+ },
+ [0x12342]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12342,
+ },
+ [0x12343]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES IM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12343,
+ },
+ [0x12344]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES ISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12344,
+ },
+ [0x12345]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12345,
+ },
+ [0x12346]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12346,
+ },
+ [0x12347]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES MIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12347,
+ },
+ [0x12348]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12348,
+ },
+ [0x12349]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12349,
+ },
+ [0x1234A]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES SIG0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234A,
+ },
+ [0x1234B]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234B,
+ },
+ [0x1234C]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES U PLUS GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234C,
+ },
+ [0x1234D]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234D,
+ },
+ [0x1234E]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES URUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234E,
+ },
+ [0x1234F]={
+ category="lo",
+ description="CUNEIFORM SIGN URUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1234F,
+ },
+ [0x12350]={
+ category="lo",
+ description="CUNEIFORM SIGN URUDA TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12350,
+ },
+ [0x12351]={
+ category="lo",
+ description="CUNEIFORM SIGN USH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12351,
+ },
+ [0x12352]={
+ category="lo",
+ description="CUNEIFORM SIGN USH TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12352,
+ },
+ [0x12353]={
+ category="lo",
+ description="CUNEIFORM SIGN USH TIMES KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12353,
+ },
+ [0x12354]={
+ category="lo",
+ description="CUNEIFORM SIGN USH TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12354,
+ },
+ [0x12355]={
+ category="lo",
+ description="CUNEIFORM SIGN USH TIMES TAK0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12355,
+ },
+ [0x12356]={
+ category="lo",
+ description="CUNEIFORM SIGN USHX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12356,
+ },
+ [0x12357]={
+ category="lo",
+ description="CUNEIFORM SIGN USH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12357,
+ },
+ [0x12358]={
+ category="lo",
+ description="CUNEIFORM SIGN USHUMX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12358,
+ },
+ [0x12359]={
+ category="lo",
+ description="CUNEIFORM SIGN UTUKI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12359,
+ },
+ [0x1235A]={
+ category="lo",
+ description="CUNEIFORM SIGN UZ0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235A,
+ },
+ [0x1235B]={
+ category="lo",
+ description="CUNEIFORM SIGN UZ0x0003 TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235B,
+ },
+ [0x1235C]={
+ category="lo",
+ description="CUNEIFORM SIGN UZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235C,
+ },
+ [0x1235D]={
+ category="lo",
+ description="CUNEIFORM SIGN ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235D,
+ },
+ [0x1235E]={
+ category="lo",
+ description="CUNEIFORM SIGN ZA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235E,
+ },
+ [0x1235F]={
+ category="lo",
+ description="CUNEIFORM SIGN ZA SQUARED TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1235F,
+ },
+ [0x12360]={
+ category="lo",
+ description="CUNEIFORM SIGN ZAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12360,
+ },
+ [0x12361]={
+ category="lo",
+ description="CUNEIFORM SIGN ZAMX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12361,
+ },
+ [0x12362]={
+ category="lo",
+ description="CUNEIFORM SIGN ZE0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12362,
+ },
+ [0x12363]={
+ category="lo",
+ description="CUNEIFORM SIGN ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12363,
+ },
+ [0x12364]={
+ category="lo",
+ description="CUNEIFORM SIGN ZI OVER ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12364,
+ },
+ [0x12365]={
+ category="lo",
+ description="CUNEIFORM SIGN ZI0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12365,
+ },
+ [0x12366]={
+ category="lo",
+ description="CUNEIFORM SIGN ZIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12366,
+ },
+ [0x12367]={
+ category="lo",
+ description="CUNEIFORM SIGN ZIB KABA TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12367,
+ },
+ [0x12368]={
+ category="lo",
+ description="CUNEIFORM SIGN ZIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12368,
+ },
+ [0x12369]={
+ category="lo",
+ description="CUNEIFORM SIGN ZIZ0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12369,
+ },
+ [0x1236A]={
+ category="lo",
+ description="CUNEIFORM SIGN ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236A,
+ },
+ [0x1236B]={
+ category="lo",
+ description="CUNEIFORM SIGN ZU0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236B,
+ },
+ [0x1236C]={
+ category="lo",
+ description="CUNEIFORM SIGN ZU0x0005 TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236C,
+ },
+ [0x1236D]={
+ category="lo",
+ description="CUNEIFORM SIGN ZUBUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236D,
+ },
+ [0x1236E]={
+ category="lo",
+ description="CUNEIFORM SIGN ZUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236E,
+ },
+ [0x1236F]={
+ category="lo",
+ description="CUNEIFORM SIGN KAP ELAMITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1236F,
+ },
+ [0x12370]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES NUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12370,
+ },
+ [0x12371]={
+ category="lo",
+ description="CUNEIFORM SIGN AB2 TIMES A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12371,
+ },
+ [0x12372]={
+ category="lo",
+ description="CUNEIFORM SIGN AMAR TIMES KUG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12372,
+ },
+ [0x12373]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12373,
+ },
+ [0x12374]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12374,
+ },
+ [0x12375]={
+ category="lo",
+ description="CUNEIFORM SIGN DISH PLUS SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12375,
+ },
+ [0x12376]={
+ category="lo",
+ description="CUNEIFORM SIGN DUB TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12376,
+ },
+ [0x12377]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12377,
+ },
+ [0x12378]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12378,
+ },
+ [0x12379]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES AN PLUS KAK PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12379,
+ },
+ [0x1237A]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES ASH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237A,
+ },
+ [0x1237B]={
+ category="lo",
+ description="CUNEIFORM SIGN GE22",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237B,
+ },
+ [0x1237C]={
+ category="lo",
+ description="CUNEIFORM SIGN GIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237C,
+ },
+ [0x1237D]={
+ category="lo",
+ description="CUNEIFORM SIGN HUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237D,
+ },
+ [0x1237E]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ANSHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237E,
+ },
+ [0x1237F]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES ASH3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1237F,
+ },
+ [0x12380]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12380,
+ },
+ [0x12381]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES GUD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12381,
+ },
+ [0x12382]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES HI TIMES ASH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12382,
+ },
+ [0x12383]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12383,
+ },
+ [0x12384]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12384,
+ },
+ [0x12385]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES SHUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12385,
+ },
+ [0x12386]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12386,
+ },
+ [0x12387]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES UR2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12387,
+ },
+ [0x12388]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12388,
+ },
+ [0x12389]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 SHESHIG TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12389,
+ },
+ [0x1238A]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES ESH2 PLUS LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238A,
+ },
+ [0x1238B]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238B,
+ },
+ [0x1238C]={
+ category="lo",
+ description="CUNEIFORM SIGN MESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238C,
+ },
+ [0x1238D]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH3 TIMES ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238D,
+ },
+ [0x1238E]={
+ category="lo",
+ description="CUNEIFORM SIGN NA4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238E,
+ },
+ [0x1238F]={
+ category="lo",
+ description="CUNEIFORM SIGN NIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1238F,
+ },
+ [0x12390]={
+ category="lo",
+ description="CUNEIFORM SIGN NIN9",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12390,
+ },
+ [0x12391]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES BAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12391,
+ },
+ [0x12392]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12392,
+ },
+ [0x12393]={
+ category="lo",
+ description="CUNEIFORM SIGN NU11 ROTATED NINETY DEGREES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12393,
+ },
+ [0x12394]={
+ category="lo",
+ description="CUNEIFORM SIGN PESH2 ASTERISK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12394,
+ },
+ [0x12395]={
+ category="lo",
+ description="CUNEIFORM SIGN PIR2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12395,
+ },
+ [0x12396]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12396,
+ },
+ [0x12397]={
+ category="lo",
+ description="CUNEIFORM SIGN TI2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12397,
+ },
+ [0x12398]={
+ category="lo",
+ description="CUNEIFORM SIGN UM TIMES ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12398,
+ },
+ [0x12399]={
+ category="lo",
+ description="CUNEIFORM SIGN U U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12399,
+ },
+ [0x12400]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12400,
+ },
+ [0x12401]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12401,
+ },
+ [0x12402]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12402,
+ },
+ [0x12403]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12403,
+ },
+ [0x12404]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12404,
+ },
+ [0x12405]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12405,
+ },
+ [0x12406]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12406,
+ },
+ [0x12407]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12407,
+ },
+ [0x12408]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12408,
+ },
+ [0x12409]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12409,
+ },
+ [0x1240A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240A,
+ },
+ [0x1240B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240B,
+ },
+ [0x1240C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240C,
+ },
+ [0x1240D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240D,
+ },
+ [0x1240E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240E,
+ },
+ [0x1240F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1240F,
+ },
+ [0x12410]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12410,
+ },
+ [0x12411]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12411,
+ },
+ [0x12412]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12412,
+ },
+ [0x12413]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12413,
+ },
+ [0x12414]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12414,
+ },
+ [0x12415]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12415,
+ },
+ [0x12416]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12416,
+ },
+ [0x12417]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12417,
+ },
+ [0x12418]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12418,
+ },
+ [0x12419]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12419,
+ },
+ [0x1241A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241A,
+ },
+ [0x1241B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241B,
+ },
+ [0x1241C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241C,
+ },
+ [0x1241D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE GESH0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241D,
+ },
+ [0x1241E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE GESHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241E,
+ },
+ [0x1241F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO GESHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1241F,
+ },
+ [0x12420]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE GESHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12420,
+ },
+ [0x12421]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR GESHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12421,
+ },
+ [0x12422]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE GESHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12422,
+ },
+ [0x12423]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12423,
+ },
+ [0x12424]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12424,
+ },
+ [0x12425]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE SHAR0x0002 VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12425,
+ },
+ [0x12426]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12426,
+ },
+ [0x12427]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12427,
+ },
+ [0x12428]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12428,
+ },
+ [0x12429]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12429,
+ },
+ [0x1242A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242A,
+ },
+ [0x1242B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE SHAR0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242B,
+ },
+ [0x1242C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE SHARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242C,
+ },
+ [0x1242D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO SHARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242D,
+ },
+ [0x1242E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE SHARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242E,
+ },
+ [0x1242F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1242F,
+ },
+ [0x12430]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR SHARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12430,
+ },
+ [0x12431]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE SHARU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12431,
+ },
+ [0x12432]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SHAR0x0002 TIMES GAL PLUS DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12432,
+ },
+ [0x12433]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SHAR0x0002 TIMES GAL PLUS MIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12433,
+ },
+ [0x12434]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE BURU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12434,
+ },
+ [0x12435]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO BURU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12435,
+ },
+ [0x12436]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE BURU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12436,
+ },
+ [0x12437]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12437,
+ },
+ [0x12438]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR BURU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12438,
+ },
+ [0x12439]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE BURU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12439,
+ },
+ [0x1243A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH0x0010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243A,
+ },
+ [0x1243B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH0x0015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243B,
+ },
+ [0x1243C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243C,
+ },
+ [0x1243D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243D,
+ },
+ [0x1243E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243E,
+ },
+ [0x1243F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1243F,
+ },
+ [0x12440]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH0x0009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12440,
+ },
+ [0x12441]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12441,
+ },
+ [0x12442]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12442,
+ },
+ [0x12443]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12443,
+ },
+ [0x12444]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12444,
+ },
+ [0x12445]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12445,
+ },
+ [0x12446]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12446,
+ },
+ [0x12447]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12447,
+ },
+ [0x12448]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12448,
+ },
+ [0x12449]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12449,
+ },
+ [0x1244A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO ASH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244A,
+ },
+ [0x1244B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE ASH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244B,
+ },
+ [0x1244C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR ASH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244C,
+ },
+ [0x1244D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE ASH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244D,
+ },
+ [0x1244E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX ASH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244E,
+ },
+ [0x1244F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE BAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1244F,
+ },
+ [0x12450]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO BAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12450,
+ },
+ [0x12451]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN THREE BAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12451,
+ },
+ [0x12452]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR BAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12452,
+ },
+ [0x12453]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR BAN0x0002 VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12453,
+ },
+ [0x12454]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE BAN0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12454,
+ },
+ [0x12455]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE BAN0x0002 VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12455,
+ },
+ [0x12456]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NIGIDAMIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12456,
+ },
+ [0x12457]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NIGIDAESH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12457,
+ },
+ [0x12458]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE ESHE0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12458,
+ },
+ [0x12459]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO ESHE0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12459,
+ },
+ [0x1245A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE THIRD DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245A,
+ },
+ [0x1245B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO THIRDS DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245B,
+ },
+ [0x1245C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245C,
+ },
+ [0x1245D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245D,
+ },
+ [0x1245E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245E,
+ },
+ [0x1245F]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1245F,
+ },
+ [0x12460]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE QUARTER ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12460,
+ },
+ [0x12461]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12461,
+ },
+ [0x12462]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12462,
+ },
+ [0x12463]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE QUARTER GUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12463,
+ },
+ [0x12464]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ONE HALF GUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12464,
+ },
+ [0x12465]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ELAMITE ONE THIRD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12465,
+ },
+ [0x12466]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ELAMITE TWO THIRDS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12466,
+ },
+ [0x12467]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ELAMITE FORTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12467,
+ },
+ [0x12468]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN ELAMITE FIFTY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12468,
+ },
+ [0x12469]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FOUR U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12469,
+ },
+ [0x1246A]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN FIVE U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246A,
+ },
+ [0x1246B]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SIX U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246B,
+ },
+ [0x1246C]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN SEVEN U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246C,
+ },
+ [0x1246D]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN EIGHT U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246D,
+ },
+ [0x1246E]={
+ category="nl",
+ description="CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1246E,
+ },
+ [0x12470]={
+ category="po",
+ description="CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x12470,
+ },
+ [0x12471]={
+ category="po",
+ description="CUNEIFORM PUNCTUATION SIGN VERTICAL COLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x12471,
+ },
+ [0x12472]={
+ category="po",
+ description="CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x12472,
+ },
+ [0x12473]={
+ category="po",
+ description="CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x12473,
+ },
+ [0x12474]={
+ category="po",
+ description="CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x12474,
+ },
+ [0x12480]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES NUN TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12480,
+ },
+ [0x12481]={
+ category="lo",
+ description="CUNEIFORM SIGN AB TIMES SHU2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12481,
+ },
+ [0x12482]={
+ category="lo",
+ description="CUNEIFORM SIGN AD TIMES ESH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12482,
+ },
+ [0x12483]={
+ category="lo",
+ description="CUNEIFORM SIGN BAD TIMES DISH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12483,
+ },
+ [0x12484]={
+ category="lo",
+ description="CUNEIFORM SIGN BAHAR2 TIMES AB2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12484,
+ },
+ [0x12485]={
+ category="lo",
+ description="CUNEIFORM SIGN BAHAR2 TIMES NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12485,
+ },
+ [0x12486]={
+ category="lo",
+ description="CUNEIFORM SIGN BAHAR2 TIMES ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12486,
+ },
+ [0x12487]={
+ category="lo",
+ description="CUNEIFORM SIGN BU OVER BU TIMES NA2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12487,
+ },
+ [0x12488]={
+ category="lo",
+ description="CUNEIFORM SIGN DA TIMES TAK4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12488,
+ },
+ [0x12489]={
+ category="lo",
+ description="CUNEIFORM SIGN DAG TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12489,
+ },
+ [0x1248A]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248A,
+ },
+ [0x1248B]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM TIMES U U U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248B,
+ },
+ [0x1248C]={
+ category="lo",
+ description="CUNEIFORM SIGN DIM2 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248C,
+ },
+ [0x1248D]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES ANSHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248D,
+ },
+ [0x1248E]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248E,
+ },
+ [0x1248F]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES ASH AT LEFT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1248F,
+ },
+ [0x12490]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES DIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12490,
+ },
+ [0x12491]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES DUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12491,
+ },
+ [0x12492]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES ERIN2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12492,
+ },
+ [0x12493]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12493,
+ },
+ [0x12494]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12494,
+ },
+ [0x12495]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES GIR2 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12495,
+ },
+ [0x12496]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12496,
+ },
+ [0x12497]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12497,
+ },
+ [0x12498]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12498,
+ },
+ [0x12499]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12499,
+ },
+ [0x1249A]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249A,
+ },
+ [0x1249B]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249B,
+ },
+ [0x1249C]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES KUSHU2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249C,
+ },
+ [0x1249D]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES KUSHU2 PLUS KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249D,
+ },
+ [0x1249E]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES LAK-020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249E,
+ },
+ [0x1249F]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES LAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1249F,
+ },
+ [0x124A0]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES LAM TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A0,
+ },
+ [0x124A1]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES LUH PLUS GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A1,
+ },
+ [0x124A2]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A2,
+ },
+ [0x124A3]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES MES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A3,
+ },
+ [0x124A4]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A4,
+ },
+ [0x124A5]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A5,
+ },
+ [0x124A6]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A6,
+ },
+ [0x124A7]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A7,
+ },
+ [0x124A8]={
+ category="lo",
+ description="CUNEIFORM SIGN DUG TIMES SI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A8,
+ },
+ [0x124A9]={
+ category="lo",
+ description="CUNEIFORM SIGN E2 TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124A9,
+ },
+ [0x124AA]={
+ category="lo",
+ description="CUNEIFORM SIGN E2 TIMES PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AA,
+ },
+ [0x124AB]={
+ category="lo",
+ description="CUNEIFORM SIGN ERIN2 X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AB,
+ },
+ [0x124AC]={
+ category="lo",
+ description="CUNEIFORM SIGN ESH2 CROSSING ESH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AC,
+ },
+ [0x124AD]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AD,
+ },
+ [0x124AE]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AE,
+ },
+ [0x124AF]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124AF,
+ },
+ [0x124B0]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B0,
+ },
+ [0x124B1]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES LAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B1,
+ },
+ [0x124B2]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B2,
+ },
+ [0x124B3]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES MES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B3,
+ },
+ [0x124B4]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN SHESHIG TIMES SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B4,
+ },
+ [0x124B5]={
+ category="lo",
+ description="CUNEIFORM SIGN EZEN TIMES SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B5,
+ },
+ [0x124B6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES BAHAR2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B6,
+ },
+ [0x124B7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES DIM GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B7,
+ },
+ [0x124B8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES DUG TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B8,
+ },
+ [0x124B9]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES DUG TIMES KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124B9,
+ },
+ [0x124BA]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES EREN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BA,
+ },
+ [0x124BB]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BB,
+ },
+ [0x124BC]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES GAR PLUS DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BC,
+ },
+ [0x124BD]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES GAR PLUS NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BD,
+ },
+ [0x124BE]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES HA PLUS A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BE,
+ },
+ [0x124BF]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES KUSHU2 PLUS KASKAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124BF,
+ },
+ [0x124C0]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES LAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C0,
+ },
+ [0x124C1]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES LAM TIMES KUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C1,
+ },
+ [0x124C2]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES LUH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C2,
+ },
+ [0x124C3]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES MUSH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C3,
+ },
+ [0x124C4]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C4,
+ },
+ [0x124C5]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES NE PLUS E2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C5,
+ },
+ [0x124C6]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES NE PLUS GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C6,
+ },
+ [0x124C7]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES SHIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C7,
+ },
+ [0x124C8]={
+ category="lo",
+ description="CUNEIFORM SIGN GA2 TIMES ZIZ2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C8,
+ },
+ [0x124C9]={
+ category="lo",
+ description="CUNEIFORM SIGN GABA ROTATED NINETY DEGREES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124C9,
+ },
+ [0x124CA]={
+ category="lo",
+ description="CUNEIFORM SIGN GESHTIN TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CA,
+ },
+ [0x124CB]={
+ category="lo",
+ description="CUNEIFORM SIGN GISH TIMES GISH CROSSING GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CB,
+ },
+ [0x124CC]={
+ category="lo",
+ description="CUNEIFORM SIGN GU2 TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CC,
+ },
+ [0x124CD]={
+ category="lo",
+ description="CUNEIFORM SIGN GUD PLUS GISH TIMES TAK4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CD,
+ },
+ [0x124CE]={
+ category="lo",
+ description="CUNEIFORM SIGN HA TENU GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CE,
+ },
+ [0x124CF]={
+ category="lo",
+ description="CUNEIFORM SIGN HI TIMES ASH OVER HI TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124CF,
+ },
+ [0x124D0]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D0,
+ },
+ [0x124D1]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D1,
+ },
+ [0x124D2]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES U U U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D2,
+ },
+ [0x124D3]={
+ category="lo",
+ description="CUNEIFORM SIGN KA TIMES UR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D3,
+ },
+ [0x124D4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAGAB TIMES ZU OVER ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D4,
+ },
+ [0x124D5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D5,
+ },
+ [0x124D6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D6,
+ },
+ [0x124D7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D7,
+ },
+ [0x124D8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D8,
+ },
+ [0x124D9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124D9,
+ },
+ [0x124DA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DA,
+ },
+ [0x124DB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DB,
+ },
+ [0x124DC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-079 OVER LAK-079 GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DC,
+ },
+ [0x124DD]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-080",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DD,
+ },
+ [0x124DE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-081 OVER LAK-081",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DE,
+ },
+ [0x124DF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-092",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124DF,
+ },
+ [0x124E0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-130",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E0,
+ },
+ [0x124E1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-142",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E1,
+ },
+ [0x124E2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-210",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E2,
+ },
+ [0x124E3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-219",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E3,
+ },
+ [0x124E4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-220",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E4,
+ },
+ [0x124E5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-225",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E5,
+ },
+ [0x124E6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-228",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E6,
+ },
+ [0x124E7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-238",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E7,
+ },
+ [0x124E8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-265",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E8,
+ },
+ [0x124E9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-266",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124E9,
+ },
+ [0x124EA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-343",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124EA,
+ },
+ [0x124EB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-347",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124EB,
+ },
+ [0x124EC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-348",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124EC,
+ },
+ [0x124ED]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-383",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124ED,
+ },
+ [0x124EE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-384",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124EE,
+ },
+ [0x124EF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-390",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124EF,
+ },
+ [0x124F0]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-441",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F0,
+ },
+ [0x124F1]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F1,
+ },
+ [0x124F2]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449 TIMES GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F2,
+ },
+ [0x124F3]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449 TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F3,
+ },
+ [0x124F4]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449 TIMES PAP PLUS LU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F4,
+ },
+ [0x124F5]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449 TIMES PAP PLUS PAP PLUS LU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F5,
+ },
+ [0x124F6]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-449 TIMES U2 PLUS BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F6,
+ },
+ [0x124F7]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-450",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F7,
+ },
+ [0x124F8]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-457",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F8,
+ },
+ [0x124F9]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-470",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124F9,
+ },
+ [0x124FA]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-483",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FA,
+ },
+ [0x124FB]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-490",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FB,
+ },
+ [0x124FC]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-492",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FC,
+ },
+ [0x124FD]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-493",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FD,
+ },
+ [0x124FE]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-495",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FE,
+ },
+ [0x124FF]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-550",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x124FF,
+ },
+ [0x12500]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-608",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12500,
+ },
+ [0x12501]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12501,
+ },
+ [0x12502]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12502,
+ },
+ [0x12503]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES BAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12503,
+ },
+ [0x12504]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES DUN3 GUNU GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12504,
+ },
+ [0x12505]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES KU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12505,
+ },
+ [0x12506]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12506,
+ },
+ [0x12507]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES TAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12507,
+ },
+ [0x12508]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12508,
+ },
+ [0x12509]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES U2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12509,
+ },
+ [0x1250A]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250A,
+ },
+ [0x1250B]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-617 TIMES URUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250B,
+ },
+ [0x1250C]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-636",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250C,
+ },
+ [0x1250D]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250D,
+ },
+ [0x1250E]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES DUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250E,
+ },
+ [0x1250F]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1250F,
+ },
+ [0x12510]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES IGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12510,
+ },
+ [0x12511]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES IGI GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12511,
+ },
+ [0x12512]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12512,
+ },
+ [0x12513]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES PAP PLUS PAP PLUS LU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12513,
+ },
+ [0x12514]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES SHESH PLUS KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12514,
+ },
+ [0x12515]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12515,
+ },
+ [0x12516]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-648 TIMES URUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12516,
+ },
+ [0x12517]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-724",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12517,
+ },
+ [0x12518]={
+ category="lo",
+ description="CUNEIFORM SIGN LAK-749",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12518,
+ },
+ [0x12519]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 GUNU TIMES ASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12519,
+ },
+ [0x1251A]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251A,
+ },
+ [0x1251B]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES HAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251B,
+ },
+ [0x1251C]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251C,
+ },
+ [0x1251D]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES PAP PLUS PAP PLUS LU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251D,
+ },
+ [0x1251E]={
+ category="lo",
+ description="CUNEIFORM SIGN LU2 TIMES TAK4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251E,
+ },
+ [0x1251F]={
+ category="lo",
+ description="CUNEIFORM SIGN MI PLUS ZA7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1251F,
+ },
+ [0x12520]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH OVER MUSH TIMES GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12520,
+ },
+ [0x12521]={
+ category="lo",
+ description="CUNEIFORM SIGN MUSH OVER MUSH TIMES KAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12521,
+ },
+ [0x12522]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES DIM GUNU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12522,
+ },
+ [0x12523]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES GISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12523,
+ },
+ [0x12524]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES GUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12524,
+ },
+ [0x12525]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12525,
+ },
+ [0x12526]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES KESH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12526,
+ },
+ [0x12527]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES LAK-050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12527,
+ },
+ [0x12528]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES MASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12528,
+ },
+ [0x12529]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES PAP PLUS PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12529,
+ },
+ [0x1252A]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252A,
+ },
+ [0x1252B]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES U PLUS U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252B,
+ },
+ [0x1252C]={
+ category="lo",
+ description="CUNEIFORM SIGN NINDA2 TIMES URUDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252C,
+ },
+ [0x1252D]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG GUNU TIMES HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252D,
+ },
+ [0x1252E]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252E,
+ },
+ [0x1252F]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES SHE AT LEFT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1252F,
+ },
+ [0x12530]={
+ category="lo",
+ description="CUNEIFORM SIGN SAG TIMES TAK4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12530,
+ },
+ [0x12531]={
+ category="lo",
+ description="CUNEIFORM SIGN SHA6 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12531,
+ },
+ [0x12532]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE OVER SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12532,
+ },
+ [0x12533]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE PLUS HUB2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12533,
+ },
+ [0x12534]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE PLUS NAM2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12534,
+ },
+ [0x12535]={
+ category="lo",
+ description="CUNEIFORM SIGN SHE PLUS SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12535,
+ },
+ [0x12536]={
+ category="lo",
+ description="CUNEIFORM SIGN SHU2 PLUS DUG TIMES NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12536,
+ },
+ [0x12537]={
+ category="lo",
+ description="CUNEIFORM SIGN SHU2 PLUS E2 TIMES AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12537,
+ },
+ [0x12538]={
+ category="lo",
+ description="CUNEIFORM SIGN SI TIMES TAK4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12538,
+ },
+ [0x12539]={
+ category="lo",
+ description="CUNEIFORM SIGN TAK4 PLUS SAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12539,
+ },
+ [0x1253A]={
+ category="lo",
+ description="CUNEIFORM SIGN TUM TIMES GAN2 TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253A,
+ },
+ [0x1253B]={
+ category="lo",
+ description="CUNEIFORM SIGN TUM TIMES THREE DISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253B,
+ },
+ [0x1253C]={
+ category="lo",
+ description="CUNEIFORM SIGN UR2 INVERTED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253C,
+ },
+ [0x1253D]={
+ category="lo",
+ description="CUNEIFORM SIGN UR2 TIMES UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253D,
+ },
+ [0x1253E]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES DARA3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253E,
+ },
+ [0x1253F]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES LAK-668",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1253F,
+ },
+ [0x12540]={
+ category="lo",
+ description="CUNEIFORM SIGN URU TIMES LU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12540,
+ },
+ [0x12541]={
+ category="lo",
+ description="CUNEIFORM SIGN ZA7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12541,
+ },
+ [0x12542]={
+ category="lo",
+ description="CUNEIFORM SIGN ZU OVER ZU PLUS SAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12542,
+ },
+ [0x12543]={
+ category="lo",
+ description="CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x12543,
+ },
+ [0x13000]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13000,
+ },
+ [0x13001]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13001,
+ },
+ [0x13002]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13002,
+ },
+ [0x13003]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13003,
+ },
+ [0x13004]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13004,
+ },
+ [0x13005]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13005,
+ },
+ [0x13006]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13006,
+ },
+ [0x13007]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13007,
+ },
+ [0x13008]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13008,
+ },
+ [0x13009]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13009,
+ },
+ [0x1300A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300A,
+ },
+ [0x1300B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300B,
+ },
+ [0x1300C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300C,
+ },
+ [0x1300D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300D,
+ },
+ [0x1300E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300E,
+ },
+ [0x1300F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300F,
+ },
+ [0x13010]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13010,
+ },
+ [0x13011]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13011,
+ },
+ [0x13012]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13012,
+ },
+ [0x13013]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13013,
+ },
+ [0x13014]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13014,
+ },
+ [0x13015]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13015,
+ },
+ [0x13016]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13016,
+ },
+ [0x13017]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13017,
+ },
+ [0x13018]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13018,
+ },
+ [0x13019]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13019,
+ },
+ [0x1301A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301A,
+ },
+ [0x1301B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301B,
+ },
+ [0x1301C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301C,
+ },
+ [0x1301D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301D,
+ },
+ [0x1301E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301E,
+ },
+ [0x1301F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301F,
+ },
+ [0x13020]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13020,
+ },
+ [0x13021]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13021,
+ },
+ [0x13022]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13022,
+ },
+ [0x13023]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13023,
+ },
+ [0x13024]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13024,
+ },
+ [0x13025]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13025,
+ },
+ [0x13026]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13026,
+ },
+ [0x13027]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13027,
+ },
+ [0x13028]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13028,
+ },
+ [0x13029]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13029,
+ },
+ [0x1302A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302A,
+ },
+ [0x1302B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302B,
+ },
+ [0x1302C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302C,
+ },
+ [0x1302D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302D,
+ },
+ [0x1302E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302E,
+ },
+ [0x1302F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302F,
+ },
+ [0x13030]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13030,
+ },
+ [0x13031]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A042A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13031,
+ },
+ [0x13032]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13032,
+ },
+ [0x13033]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A043A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13033,
+ },
+ [0x13034]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13034,
+ },
+ [0x13035]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13035,
+ },
+ [0x13036]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13036,
+ },
+ [0x13037]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13037,
+ },
+ [0x13038]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13038,
+ },
+ [0x13039]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13039,
+ },
+ [0x1303A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303A,
+ },
+ [0x1303B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303B,
+ },
+ [0x1303C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303C,
+ },
+ [0x1303D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303D,
+ },
+ [0x1303E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303E,
+ },
+ [0x1303F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303F,
+ },
+ [0x13040]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13040,
+ },
+ [0x13041]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13041,
+ },
+ [0x13042]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13042,
+ },
+ [0x13043]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13043,
+ },
+ [0x13044]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13044,
+ },
+ [0x13045]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13045,
+ },
+ [0x13046]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13046,
+ },
+ [0x13047]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13047,
+ },
+ [0x13048]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A063",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13048,
+ },
+ [0x13049]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A064",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13049,
+ },
+ [0x1304A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304A,
+ },
+ [0x1304B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304B,
+ },
+ [0x1304C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304C,
+ },
+ [0x1304D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A068",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304D,
+ },
+ [0x1304E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A069",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304E,
+ },
+ [0x1304F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A070",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304F,
+ },
+ [0x13050]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13050,
+ },
+ [0x13051]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13051,
+ },
+ [0x13052]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13052,
+ },
+ [0x13053]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13053,
+ },
+ [0x13054]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13054,
+ },
+ [0x13055]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13055,
+ },
+ [0x13056]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13056,
+ },
+ [0x13057]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13057,
+ },
+ [0x13058]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13058,
+ },
+ [0x13059]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13059,
+ },
+ [0x1305A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305A,
+ },
+ [0x1305B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305B,
+ },
+ [0x1305C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305C,
+ },
+ [0x1305D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305D,
+ },
+ [0x1305E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305E,
+ },
+ [0x1305F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305F,
+ },
+ [0x13060]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13060,
+ },
+ [0x13061]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13061,
+ },
+ [0x13062]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13062,
+ },
+ [0x13063]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13063,
+ },
+ [0x13064]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13064,
+ },
+ [0x13065]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13065,
+ },
+ [0x13066]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13066,
+ },
+ [0x13067]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13067,
+ },
+ [0x13068]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13068,
+ },
+ [0x13069]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13069,
+ },
+ [0x1306A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306A,
+ },
+ [0x1306B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306B,
+ },
+ [0x1306C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306C,
+ },
+ [0x1306D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306D,
+ },
+ [0x1306E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306E,
+ },
+ [0x1306F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306F,
+ },
+ [0x13070]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13070,
+ },
+ [0x13071]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13071,
+ },
+ [0x13072]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13072,
+ },
+ [0x13073]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13073,
+ },
+ [0x13074]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13074,
+ },
+ [0x13075]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13075,
+ },
+ [0x13076]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13076,
+ },
+ [0x13077]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13077,
+ },
+ [0x13078]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13078,
+ },
+ [0x13079]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13079,
+ },
+ [0x1307A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307A,
+ },
+ [0x1307B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307B,
+ },
+ [0x1307C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307C,
+ },
+ [0x1307D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307D,
+ },
+ [0x1307E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307E,
+ },
+ [0x1307F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307F,
+ },
+ [0x13080]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13080,
+ },
+ [0x13081]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13081,
+ },
+ [0x13082]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13082,
+ },
+ [0x13083]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13083,
+ },
+ [0x13084]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13084,
+ },
+ [0x13085]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13085,
+ },
+ [0x13086]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13086,
+ },
+ [0x13087]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13087,
+ },
+ [0x13088]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13088,
+ },
+ [0x13089]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13089,
+ },
+ [0x1308A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308A,
+ },
+ [0x1308B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308B,
+ },
+ [0x1308C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308C,
+ },
+ [0x1308D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308D,
+ },
+ [0x1308E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308E,
+ },
+ [0x1308F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308F,
+ },
+ [0x13090]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13090,
+ },
+ [0x13091]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13091,
+ },
+ [0x13092]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D027A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13092,
+ },
+ [0x13093]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13093,
+ },
+ [0x13094]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13094,
+ },
+ [0x13095]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13095,
+ },
+ [0x13096]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13096,
+ },
+ [0x13097]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13097,
+ },
+ [0x13098]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13098,
+ },
+ [0x13099]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13099,
+ },
+ [0x1309A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309A,
+ },
+ [0x1309B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309B,
+ },
+ [0x1309C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309C,
+ },
+ [0x1309D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309D,
+ },
+ [0x1309E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309E,
+ },
+ [0x1309F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309F,
+ },
+ [0x130A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A0,
+ },
+ [0x130A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A1,
+ },
+ [0x130A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A2,
+ },
+ [0x130A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A3,
+ },
+ [0x130A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A4,
+ },
+ [0x130A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A5,
+ },
+ [0x130A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A6,
+ },
+ [0x130A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A7,
+ },
+ [0x130A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D046A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A8,
+ },
+ [0x130A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A9,
+ },
+ [0x130AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AA,
+ },
+ [0x130AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D048A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AB,
+ },
+ [0x130AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AC,
+ },
+ [0x130AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AD,
+ },
+ [0x130AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AE,
+ },
+ [0x130AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AF,
+ },
+ [0x130B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B0,
+ },
+ [0x130B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B1,
+ },
+ [0x130B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B2,
+ },
+ [0x130B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B3,
+ },
+ [0x130B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B4,
+ },
+ [0x130B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B5,
+ },
+ [0x130B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B6,
+ },
+ [0x130B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B7,
+ },
+ [0x130B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B8,
+ },
+ [0x130B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D052A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B9,
+ },
+ [0x130BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BA,
+ },
+ [0x130BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BB,
+ },
+ [0x130BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D054A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BC,
+ },
+ [0x130BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BD,
+ },
+ [0x130BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BE,
+ },
+ [0x130BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BF,
+ },
+ [0x130C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C0,
+ },
+ [0x130C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C1,
+ },
+ [0x130C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C2,
+ },
+ [0x130C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C3,
+ },
+ [0x130C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C4,
+ },
+ [0x130C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D063",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C5,
+ },
+ [0x130C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D064",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C6,
+ },
+ [0x130C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C7,
+ },
+ [0x130C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C8,
+ },
+ [0x130C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C9,
+ },
+ [0x130CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CA,
+ },
+ [0x130CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CB,
+ },
+ [0x130CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CC,
+ },
+ [0x130CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CD,
+ },
+ [0x130CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CE,
+ },
+ [0x130CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CF,
+ },
+ [0x130D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D0,
+ },
+ [0x130D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D1,
+ },
+ [0x130D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D2,
+ },
+ [0x130D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D3,
+ },
+ [0x130D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D4,
+ },
+ [0x130D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D5,
+ },
+ [0x130D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D6,
+ },
+ [0x130D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D7,
+ },
+ [0x130D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D8,
+ },
+ [0x130D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D9,
+ },
+ [0x130DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DA,
+ },
+ [0x130DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DB,
+ },
+ [0x130DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DC,
+ },
+ [0x130DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DD,
+ },
+ [0x130DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DE,
+ },
+ [0x130DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DF,
+ },
+ [0x130E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E0,
+ },
+ [0x130E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E1,
+ },
+ [0x130E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E2,
+ },
+ [0x130E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E3,
+ },
+ [0x130E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E4,
+ },
+ [0x130E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E5,
+ },
+ [0x130E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E6,
+ },
+ [0x130E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E7,
+ },
+ [0x130E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E8,
+ },
+ [0x130E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E9,
+ },
+ [0x130EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EA,
+ },
+ [0x130EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EB,
+ },
+ [0x130EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EC,
+ },
+ [0x130ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130ED,
+ },
+ [0x130EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EE,
+ },
+ [0x130EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EF,
+ },
+ [0x130F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F0,
+ },
+ [0x130F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F1,
+ },
+ [0x130F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F2,
+ },
+ [0x130F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F3,
+ },
+ [0x130F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F4,
+ },
+ [0x130F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F5,
+ },
+ [0x130F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F6,
+ },
+ [0x130F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F7,
+ },
+ [0x130F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F8,
+ },
+ [0x130F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F9,
+ },
+ [0x130FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FA,
+ },
+ [0x130FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FB,
+ },
+ [0x130FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FC,
+ },
+ [0x130FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FD,
+ },
+ [0x130FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FE,
+ },
+ [0x130FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FF,
+ },
+ [0x13100]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13100,
+ },
+ [0x13101]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13101,
+ },
+ [0x13102]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13102,
+ },
+ [0x13103]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13103,
+ },
+ [0x13104]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13104,
+ },
+ [0x13105]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13105,
+ },
+ [0x13106]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13106,
+ },
+ [0x13107]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13107,
+ },
+ [0x13108]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13108,
+ },
+ [0x13109]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13109,
+ },
+ [0x1310A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310A,
+ },
+ [0x1310B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310B,
+ },
+ [0x1310C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F013A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310C,
+ },
+ [0x1310D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310D,
+ },
+ [0x1310E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310E,
+ },
+ [0x1310F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310F,
+ },
+ [0x13110]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13110,
+ },
+ [0x13111]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13111,
+ },
+ [0x13112]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13112,
+ },
+ [0x13113]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13113,
+ },
+ [0x13114]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13114,
+ },
+ [0x13115]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F021A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13115,
+ },
+ [0x13116]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13116,
+ },
+ [0x13117]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13117,
+ },
+ [0x13118]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13118,
+ },
+ [0x13119]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13119,
+ },
+ [0x1311A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311A,
+ },
+ [0x1311B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311B,
+ },
+ [0x1311C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311C,
+ },
+ [0x1311D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311D,
+ },
+ [0x1311E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311E,
+ },
+ [0x1311F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311F,
+ },
+ [0x13120]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13120,
+ },
+ [0x13121]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13121,
+ },
+ [0x13122]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13122,
+ },
+ [0x13123]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13123,
+ },
+ [0x13124]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13124,
+ },
+ [0x13125]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13125,
+ },
+ [0x13126]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13126,
+ },
+ [0x13127]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13127,
+ },
+ [0x13128]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13128,
+ },
+ [0x13129]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F038A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13129,
+ },
+ [0x1312A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312A,
+ },
+ [0x1312B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312B,
+ },
+ [0x1312C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312C,
+ },
+ [0x1312D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312D,
+ },
+ [0x1312E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312E,
+ },
+ [0x1312F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312F,
+ },
+ [0x13130]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13130,
+ },
+ [0x13131]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13131,
+ },
+ [0x13132]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13132,
+ },
+ [0x13133]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F046A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13133,
+ },
+ [0x13134]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13134,
+ },
+ [0x13135]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F047A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13135,
+ },
+ [0x13136]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13136,
+ },
+ [0x13137]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13137,
+ },
+ [0x13138]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13138,
+ },
+ [0x13139]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13139,
+ },
+ [0x1313A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313A,
+ },
+ [0x1313B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313B,
+ },
+ [0x1313C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313C,
+ },
+ [0x1313D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313D,
+ },
+ [0x1313E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313E,
+ },
+ [0x1313F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313F,
+ },
+ [0x13140]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13140,
+ },
+ [0x13141]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13141,
+ },
+ [0x13142]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13142,
+ },
+ [0x13143]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13143,
+ },
+ [0x13144]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13144,
+ },
+ [0x13145]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13145,
+ },
+ [0x13146]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13146,
+ },
+ [0x13147]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13147,
+ },
+ [0x13148]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13148,
+ },
+ [0x13149]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13149,
+ },
+ [0x1314A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314A,
+ },
+ [0x1314B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314B,
+ },
+ [0x1314C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314C,
+ },
+ [0x1314D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314D,
+ },
+ [0x1314E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314E,
+ },
+ [0x1314F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314F,
+ },
+ [0x13150]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13150,
+ },
+ [0x13151]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13151,
+ },
+ [0x13152]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13152,
+ },
+ [0x13153]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13153,
+ },
+ [0x13154]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13154,
+ },
+ [0x13155]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13155,
+ },
+ [0x13156]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13156,
+ },
+ [0x13157]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13157,
+ },
+ [0x13158]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13158,
+ },
+ [0x13159]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13159,
+ },
+ [0x1315A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315A,
+ },
+ [0x1315B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315B,
+ },
+ [0x1315C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315C,
+ },
+ [0x1315D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315D,
+ },
+ [0x1315E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G026A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315E,
+ },
+ [0x1315F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315F,
+ },
+ [0x13160]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13160,
+ },
+ [0x13161]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13161,
+ },
+ [0x13162]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13162,
+ },
+ [0x13163]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13163,
+ },
+ [0x13164]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13164,
+ },
+ [0x13165]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13165,
+ },
+ [0x13166]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13166,
+ },
+ [0x13167]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13167,
+ },
+ [0x13168]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13168,
+ },
+ [0x13169]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G036A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13169,
+ },
+ [0x1316A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316A,
+ },
+ [0x1316B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316B,
+ },
+ [0x1316C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316C,
+ },
+ [0x1316D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316D,
+ },
+ [0x1316E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316E,
+ },
+ [0x1316F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316F,
+ },
+ [0x13170]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13170,
+ },
+ [0x13171]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13171,
+ },
+ [0x13172]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G043A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13172,
+ },
+ [0x13173]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13173,
+ },
+ [0x13174]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13174,
+ },
+ [0x13175]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13175,
+ },
+ [0x13176]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13176,
+ },
+ [0x13177]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13177,
+ },
+ [0x13178]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13178,
+ },
+ [0x13179]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13179,
+ },
+ [0x1317A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317A,
+ },
+ [0x1317B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317B,
+ },
+ [0x1317C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317C,
+ },
+ [0x1317D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317D,
+ },
+ [0x1317E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317E,
+ },
+ [0x1317F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317F,
+ },
+ [0x13180]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13180,
+ },
+ [0x13181]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13181,
+ },
+ [0x13182]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13182,
+ },
+ [0x13183]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13183,
+ },
+ [0x13184]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13184,
+ },
+ [0x13185]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13185,
+ },
+ [0x13186]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13186,
+ },
+ [0x13187]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13187,
+ },
+ [0x13188]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13188,
+ },
+ [0x13189]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13189,
+ },
+ [0x1318A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318A,
+ },
+ [0x1318B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318B,
+ },
+ [0x1318C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318C,
+ },
+ [0x1318D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318D,
+ },
+ [0x1318E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318E,
+ },
+ [0x1318F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318F,
+ },
+ [0x13190]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13190,
+ },
+ [0x13191]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13191,
+ },
+ [0x13192]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13192,
+ },
+ [0x13193]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13193,
+ },
+ [0x13194]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13194,
+ },
+ [0x13195]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13195,
+ },
+ [0x13196]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13196,
+ },
+ [0x13197]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13197,
+ },
+ [0x13198]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13198,
+ },
+ [0x13199]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13199,
+ },
+ [0x1319A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319A,
+ },
+ [0x1319B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319B,
+ },
+ [0x1319C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319C,
+ },
+ [0x1319D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319D,
+ },
+ [0x1319E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319E,
+ },
+ [0x1319F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319F,
+ },
+ [0x131A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A0,
+ },
+ [0x131A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A1,
+ },
+ [0x131A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A2,
+ },
+ [0x131A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A3,
+ },
+ [0x131A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A4,
+ },
+ [0x131A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A5,
+ },
+ [0x131A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A6,
+ },
+ [0x131A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A7,
+ },
+ [0x131A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A8,
+ },
+ [0x131A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A9,
+ },
+ [0x131AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AA,
+ },
+ [0x131AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AB,
+ },
+ [0x131AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AC,
+ },
+ [0x131AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AD,
+ },
+ [0x131AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AE,
+ },
+ [0x131AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AF,
+ },
+ [0x131B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B0,
+ },
+ [0x131B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B1,
+ },
+ [0x131B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B2,
+ },
+ [0x131B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B3,
+ },
+ [0x131B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B4,
+ },
+ [0x131B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B5,
+ },
+ [0x131B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B6,
+ },
+ [0x131B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B7,
+ },
+ [0x131B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B8,
+ },
+ [0x131B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B9,
+ },
+ [0x131BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BA,
+ },
+ [0x131BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BB,
+ },
+ [0x131BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BC,
+ },
+ [0x131BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BD,
+ },
+ [0x131BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BE,
+ },
+ [0x131BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BF,
+ },
+ [0x131C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C0,
+ },
+ [0x131C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C1,
+ },
+ [0x131C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C2,
+ },
+ [0x131C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C3,
+ },
+ [0x131C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C4,
+ },
+ [0x131C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C5,
+ },
+ [0x131C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C6,
+ },
+ [0x131C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C7,
+ },
+ [0x131C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M015A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C8,
+ },
+ [0x131C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C9,
+ },
+ [0x131CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CA,
+ },
+ [0x131CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CB,
+ },
+ [0x131CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CC,
+ },
+ [0x131CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CD,
+ },
+ [0x131CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CE,
+ },
+ [0x131CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CF,
+ },
+ [0x131D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D0,
+ },
+ [0x131D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D1,
+ },
+ [0x131D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M022A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D2,
+ },
+ [0x131D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D3,
+ },
+ [0x131D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D4,
+ },
+ [0x131D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D5,
+ },
+ [0x131D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D6,
+ },
+ [0x131D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D7,
+ },
+ [0x131D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D8,
+ },
+ [0x131D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D9,
+ },
+ [0x131DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DA,
+ },
+ [0x131DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DB,
+ },
+ [0x131DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DC,
+ },
+ [0x131DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DD,
+ },
+ [0x131DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DE,
+ },
+ [0x131DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DF,
+ },
+ [0x131E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E0,
+ },
+ [0x131E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E1,
+ },
+ [0x131E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E2,
+ },
+ [0x131E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E3,
+ },
+ [0x131E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E4,
+ },
+ [0x131E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E5,
+ },
+ [0x131E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E6,
+ },
+ [0x131E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E7,
+ },
+ [0x131E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E8,
+ },
+ [0x131E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E9,
+ },
+ [0x131EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EA,
+ },
+ [0x131EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EB,
+ },
+ [0x131EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EC,
+ },
+ [0x131ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131ED,
+ },
+ [0x131EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EE,
+ },
+ [0x131EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EF,
+ },
+ [0x131F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F0,
+ },
+ [0x131F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F1,
+ },
+ [0x131F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F2,
+ },
+ [0x131F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F3,
+ },
+ [0x131F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F4,
+ },
+ [0x131F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F5,
+ },
+ [0x131F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F6,
+ },
+ [0x131F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F7,
+ },
+ [0x131F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F8,
+ },
+ [0x131F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F9,
+ },
+ [0x131FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FA,
+ },
+ [0x131FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FB,
+ },
+ [0x131FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FC,
+ },
+ [0x131FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FD,
+ },
+ [0x131FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FE,
+ },
+ [0x131FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FF,
+ },
+ [0x13200]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13200,
+ },
+ [0x13201]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13201,
+ },
+ [0x13202]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13202,
+ },
+ [0x13203]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13203,
+ },
+ [0x13204]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13204,
+ },
+ [0x13205]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13205,
+ },
+ [0x13206]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13206,
+ },
+ [0x13207]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13207,
+ },
+ [0x13208]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13208,
+ },
+ [0x13209]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13209,
+ },
+ [0x1320A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N025A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320A,
+ },
+ [0x1320B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320B,
+ },
+ [0x1320C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320C,
+ },
+ [0x1320D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320D,
+ },
+ [0x1320E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320E,
+ },
+ [0x1320F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320F,
+ },
+ [0x13210]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13210,
+ },
+ [0x13211]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13211,
+ },
+ [0x13212]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13212,
+ },
+ [0x13213]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13213,
+ },
+ [0x13214]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13214,
+ },
+ [0x13215]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13215,
+ },
+ [0x13216]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13216,
+ },
+ [0x13217]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N035A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13217,
+ },
+ [0x13218]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13218,
+ },
+ [0x13219]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13219,
+ },
+ [0x1321A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321A,
+ },
+ [0x1321B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321B,
+ },
+ [0x1321C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321C,
+ },
+ [0x1321D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321D,
+ },
+ [0x1321E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321E,
+ },
+ [0x1321F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321F,
+ },
+ [0x13220]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13220,
+ },
+ [0x13221]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13221,
+ },
+ [0x13222]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13222,
+ },
+ [0x13223]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13223,
+ },
+ [0x13224]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13224,
+ },
+ [0x13225]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13225,
+ },
+ [0x13226]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13226,
+ },
+ [0x13227]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13227,
+ },
+ [0x13228]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13228,
+ },
+ [0x13229]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13229,
+ },
+ [0x1322A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322A,
+ },
+ [0x1322B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322B,
+ },
+ [0x1322C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322C,
+ },
+ [0x1322D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322D,
+ },
+ [0x1322E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322E,
+ },
+ [0x1322F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322F,
+ },
+ [0x13230]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13230,
+ },
+ [0x13231]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13231,
+ },
+ [0x13232]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13232,
+ },
+ [0x13233]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13233,
+ },
+ [0x13234]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13234,
+ },
+ [0x13235]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13235,
+ },
+ [0x13236]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13236,
+ },
+ [0x13237]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13237,
+ },
+ [0x13238]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13238,
+ },
+ [0x13239]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13239,
+ },
+ [0x1323A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323A,
+ },
+ [0x1323B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323B,
+ },
+ [0x1323C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323C,
+ },
+ [0x1323D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323D,
+ },
+ [0x1323E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323E,
+ },
+ [0x1323F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323F,
+ },
+ [0x13240]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13240,
+ },
+ [0x13241]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13241,
+ },
+ [0x13242]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13242,
+ },
+ [0x13243]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13243,
+ },
+ [0x13244]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13244,
+ },
+ [0x13245]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13245,
+ },
+ [0x13246]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13246,
+ },
+ [0x13247]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13247,
+ },
+ [0x13248]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13248,
+ },
+ [0x13249]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13249,
+ },
+ [0x1324A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324A,
+ },
+ [0x1324B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324B,
+ },
+ [0x1324C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324C,
+ },
+ [0x1324D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324D,
+ },
+ [0x1324E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324E,
+ },
+ [0x1324F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU022A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324F,
+ },
+ [0x13250]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13250,
+ },
+ [0x13251]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13251,
+ },
+ [0x13252]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13252,
+ },
+ [0x13253]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13253,
+ },
+ [0x13254]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13254,
+ },
+ [0x13255]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13255,
+ },
+ [0x13256]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13256,
+ },
+ [0x13257]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13257,
+ },
+ [0x13258]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13258,
+ },
+ [0x13259]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006B",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13259,
+ },
+ [0x1325A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006C",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x1325A,
+ },
+ [0x1325B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006D",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325B,
+ },
+ [0x1325C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006E",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325C,
+ },
+ [0x1325D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006F",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325D,
+ },
+ [0x1325E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1325E,
+ },
+ [0x1325F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1325F,
+ },
+ [0x13260]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13260,
+ },
+ [0x13261]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13261,
+ },
+ [0x13262]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13262,
+ },
+ [0x13263]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13263,
+ },
+ [0x13264]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13264,
+ },
+ [0x13265]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13265,
+ },
+ [0x13266]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13266,
+ },
+ [0x13267]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13267,
+ },
+ [0x13268]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13268,
+ },
+ [0x13269]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13269,
+ },
+ [0x1326A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326A,
+ },
+ [0x1326B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326B,
+ },
+ [0x1326C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326C,
+ },
+ [0x1326D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326D,
+ },
+ [0x1326E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O019A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326E,
+ },
+ [0x1326F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326F,
+ },
+ [0x13270]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13270,
+ },
+ [0x13271]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13271,
+ },
+ [0x13272]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13272,
+ },
+ [0x13273]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13273,
+ },
+ [0x13274]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13274,
+ },
+ [0x13275]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13275,
+ },
+ [0x13276]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13276,
+ },
+ [0x13277]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O025A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13277,
+ },
+ [0x13278]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13278,
+ },
+ [0x13279]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13279,
+ },
+ [0x1327A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327A,
+ },
+ [0x1327B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327B,
+ },
+ [0x1327C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327C,
+ },
+ [0x1327D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327D,
+ },
+ [0x1327E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O030A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327E,
+ },
+ [0x1327F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327F,
+ },
+ [0x13280]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13280,
+ },
+ [0x13281]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13281,
+ },
+ [0x13282]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O033A",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13282,
+ },
+ [0x13283]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13283,
+ },
+ [0x13284]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13284,
+ },
+ [0x13285]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13285,
+ },
+ [0x13286]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13286,
+ },
+ [0x13287]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036B",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13287,
+ },
+ [0x13288]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036C",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13288,
+ },
+ [0x13289]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036D",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13289,
+ },
+ [0x1328A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328A,
+ },
+ [0x1328B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328B,
+ },
+ [0x1328C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328C,
+ },
+ [0x1328D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328D,
+ },
+ [0x1328E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328E,
+ },
+ [0x1328F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328F,
+ },
+ [0x13290]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13290,
+ },
+ [0x13291]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13291,
+ },
+ [0x13292]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13292,
+ },
+ [0x13293]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13293,
+ },
+ [0x13294]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13294,
+ },
+ [0x13295]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13295,
+ },
+ [0x13296]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13296,
+ },
+ [0x13297]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13297,
+ },
+ [0x13298]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13298,
+ },
+ [0x13299]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13299,
+ },
+ [0x1329A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329A,
+ },
+ [0x1329B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329B,
+ },
+ [0x1329C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329C,
+ },
+ [0x1329D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329D,
+ },
+ [0x1329E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329E,
+ },
+ [0x1329F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329F,
+ },
+ [0x132A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A0,
+ },
+ [0x132A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A1,
+ },
+ [0x132A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A2,
+ },
+ [0x132A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A3,
+ },
+ [0x132A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A4,
+ },
+ [0x132A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A5,
+ },
+ [0x132A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A6,
+ },
+ [0x132A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A7,
+ },
+ [0x132A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A8,
+ },
+ [0x132A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A9,
+ },
+ [0x132AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AA,
+ },
+ [0x132AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AB,
+ },
+ [0x132AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AC,
+ },
+ [0x132AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AD,
+ },
+ [0x132AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AE,
+ },
+ [0x132AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AF,
+ },
+ [0x132B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B0,
+ },
+ [0x132B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B1,
+ },
+ [0x132B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B2,
+ },
+ [0x132B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B3,
+ },
+ [0x132B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B4,
+ },
+ [0x132B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B5,
+ },
+ [0x132B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B6,
+ },
+ [0x132B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B7,
+ },
+ [0x132B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B8,
+ },
+ [0x132B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B9,
+ },
+ [0x132BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BA,
+ },
+ [0x132BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BB,
+ },
+ [0x132BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BC,
+ },
+ [0x132BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BD,
+ },
+ [0x132BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BE,
+ },
+ [0x132BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BF,
+ },
+ [0x132C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C0,
+ },
+ [0x132C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C1,
+ },
+ [0x132C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C2,
+ },
+ [0x132C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C3,
+ },
+ [0x132C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C4,
+ },
+ [0x132C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C5,
+ },
+ [0x132C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C6,
+ },
+ [0x132C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C7,
+ },
+ [0x132C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C8,
+ },
+ [0x132C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C9,
+ },
+ [0x132CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CA,
+ },
+ [0x132CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CB,
+ },
+ [0x132CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CC,
+ },
+ [0x132CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CD,
+ },
+ [0x132CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CE,
+ },
+ [0x132CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CF,
+ },
+ [0x132D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D0,
+ },
+ [0x132D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D1,
+ },
+ [0x132D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D2,
+ },
+ [0x132D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D3,
+ },
+ [0x132D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D4,
+ },
+ [0x132D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D5,
+ },
+ [0x132D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D6,
+ },
+ [0x132D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D7,
+ },
+ [0x132D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D8,
+ },
+ [0x132D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D9,
+ },
+ [0x132DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DA,
+ },
+ [0x132DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DB,
+ },
+ [0x132DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DC,
+ },
+ [0x132DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DD,
+ },
+ [0x132DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DE,
+ },
+ [0x132DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DF,
+ },
+ [0x132E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E0,
+ },
+ [0x132E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E1,
+ },
+ [0x132E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E2,
+ },
+ [0x132E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E3,
+ },
+ [0x132E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E4,
+ },
+ [0x132E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E5,
+ },
+ [0x132E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E6,
+ },
+ [0x132E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E7,
+ },
+ [0x132E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E8,
+ },
+ [0x132E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E9,
+ },
+ [0x132EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EA,
+ },
+ [0x132EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EB,
+ },
+ [0x132EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EC,
+ },
+ [0x132ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132ED,
+ },
+ [0x132EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EE,
+ },
+ [0x132EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EF,
+ },
+ [0x132F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F0,
+ },
+ [0x132F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F1,
+ },
+ [0x132F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F2,
+ },
+ [0x132F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F3,
+ },
+ [0x132F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F4,
+ },
+ [0x132F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F5,
+ },
+ [0x132F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F6,
+ },
+ [0x132F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F7,
+ },
+ [0x132F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F8,
+ },
+ [0x132F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F9,
+ },
+ [0x132FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FA,
+ },
+ [0x132FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S035A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FB,
+ },
+ [0x132FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FC,
+ },
+ [0x132FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FD,
+ },
+ [0x132FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FE,
+ },
+ [0x132FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FF,
+ },
+ [0x13300]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13300,
+ },
+ [0x13301]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13301,
+ },
+ [0x13302]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13302,
+ },
+ [0x13303]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13303,
+ },
+ [0x13304]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13304,
+ },
+ [0x13305]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13305,
+ },
+ [0x13306]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13306,
+ },
+ [0x13307]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13307,
+ },
+ [0x13308]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13308,
+ },
+ [0x13309]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13309,
+ },
+ [0x1330A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330A,
+ },
+ [0x1330B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330B,
+ },
+ [0x1330C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330C,
+ },
+ [0x1330D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330D,
+ },
+ [0x1330E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330E,
+ },
+ [0x1330F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330F,
+ },
+ [0x13310]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13310,
+ },
+ [0x13311]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13311,
+ },
+ [0x13312]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13312,
+ },
+ [0x13313]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13313,
+ },
+ [0x13314]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13314,
+ },
+ [0x13315]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13315,
+ },
+ [0x13316]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13316,
+ },
+ [0x13317]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13317,
+ },
+ [0x13318]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13318,
+ },
+ [0x13319]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13319,
+ },
+ [0x1331A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331A,
+ },
+ [0x1331B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331B,
+ },
+ [0x1331C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331C,
+ },
+ [0x1331D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331D,
+ },
+ [0x1331E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331E,
+ },
+ [0x1331F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331F,
+ },
+ [0x13320]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13320,
+ },
+ [0x13321]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13321,
+ },
+ [0x13322]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13322,
+ },
+ [0x13323]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13323,
+ },
+ [0x13324]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13324,
+ },
+ [0x13325]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13325,
+ },
+ [0x13326]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13326,
+ },
+ [0x13327]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13327,
+ },
+ [0x13328]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13328,
+ },
+ [0x13329]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13329,
+ },
+ [0x1332A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332A,
+ },
+ [0x1332B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332B,
+ },
+ [0x1332C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332C,
+ },
+ [0x1332D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332D,
+ },
+ [0x1332E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332E,
+ },
+ [0x1332F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332F,
+ },
+ [0x13330]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13330,
+ },
+ [0x13331]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13331,
+ },
+ [0x13332]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13332,
+ },
+ [0x13333]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13333,
+ },
+ [0x13334]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13334,
+ },
+ [0x13335]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13335,
+ },
+ [0x13336]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13336,
+ },
+ [0x13337]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13337,
+ },
+ [0x13338]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13338,
+ },
+ [0x13339]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13339,
+ },
+ [0x1333A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333A,
+ },
+ [0x1333B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333B,
+ },
+ [0x1333C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333C,
+ },
+ [0x1333D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333D,
+ },
+ [0x1333E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333E,
+ },
+ [0x1333F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333F,
+ },
+ [0x13340]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13340,
+ },
+ [0x13341]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13341,
+ },
+ [0x13342]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13342,
+ },
+ [0x13343]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13343,
+ },
+ [0x13344]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13344,
+ },
+ [0x13345]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13345,
+ },
+ [0x13346]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13346,
+ },
+ [0x13347]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13347,
+ },
+ [0x13348]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13348,
+ },
+ [0x13349]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13349,
+ },
+ [0x1334A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334A,
+ },
+ [0x1334B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334B,
+ },
+ [0x1334C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U023A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334C,
+ },
+ [0x1334D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334D,
+ },
+ [0x1334E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334E,
+ },
+ [0x1334F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334F,
+ },
+ [0x13350]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13350,
+ },
+ [0x13351]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13351,
+ },
+ [0x13352]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13352,
+ },
+ [0x13353]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13353,
+ },
+ [0x13354]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13354,
+ },
+ [0x13355]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13355,
+ },
+ [0x13356]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13356,
+ },
+ [0x13357]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13357,
+ },
+ [0x13358]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13358,
+ },
+ [0x13359]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13359,
+ },
+ [0x1335A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335A,
+ },
+ [0x1335B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335B,
+ },
+ [0x1335C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335C,
+ },
+ [0x1335D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335D,
+ },
+ [0x1335E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335E,
+ },
+ [0x1335F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335F,
+ },
+ [0x13360]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13360,
+ },
+ [0x13361]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13361,
+ },
+ [0x13362]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13362,
+ },
+ [0x13363]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13363,
+ },
+ [0x13364]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13364,
+ },
+ [0x13365]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13365,
+ },
+ [0x13366]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13366,
+ },
+ [0x13367]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13367,
+ },
+ [0x13368]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13368,
+ },
+ [0x13369]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13369,
+ },
+ [0x1336A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336A,
+ },
+ [0x1336B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336B,
+ },
+ [0x1336C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336C,
+ },
+ [0x1336D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336D,
+ },
+ [0x1336E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336E,
+ },
+ [0x1336F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336F,
+ },
+ [0x13370]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13370,
+ },
+ [0x13371]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13371,
+ },
+ [0x13372]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13372,
+ },
+ [0x13373]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13373,
+ },
+ [0x13374]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13374,
+ },
+ [0x13375]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13375,
+ },
+ [0x13376]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13376,
+ },
+ [0x13377]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13377,
+ },
+ [0x13378]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13378,
+ },
+ [0x13379]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13379,
+ },
+ [0x1337A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011B",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1337A,
+ },
+ [0x1337B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011C",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1337B,
+ },
+ [0x1337C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337C,
+ },
+ [0x1337D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337D,
+ },
+ [0x1337E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337E,
+ },
+ [0x1337F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337F,
+ },
+ [0x13380]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13380,
+ },
+ [0x13381]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13381,
+ },
+ [0x13382]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13382,
+ },
+ [0x13383]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13383,
+ },
+ [0x13384]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13384,
+ },
+ [0x13385]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13385,
+ },
+ [0x13386]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13386,
+ },
+ [0x13387]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13387,
+ },
+ [0x13388]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13388,
+ },
+ [0x13389]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13389,
+ },
+ [0x1338A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338A,
+ },
+ [0x1338B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338B,
+ },
+ [0x1338C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338C,
+ },
+ [0x1338D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338D,
+ },
+ [0x1338E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338E,
+ },
+ [0x1338F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338F,
+ },
+ [0x13390]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13390,
+ },
+ [0x13391]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13391,
+ },
+ [0x13392]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13392,
+ },
+ [0x13393]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13393,
+ },
+ [0x13394]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13394,
+ },
+ [0x13395]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13395,
+ },
+ [0x13396]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V023A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13396,
+ },
+ [0x13397]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13397,
+ },
+ [0x13398]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13398,
+ },
+ [0x13399]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13399,
+ },
+ [0x1339A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339A,
+ },
+ [0x1339B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339B,
+ },
+ [0x1339C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339C,
+ },
+ [0x1339D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339D,
+ },
+ [0x1339E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339E,
+ },
+ [0x1339F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339F,
+ },
+ [0x133A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V030A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A0,
+ },
+ [0x133A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A1,
+ },
+ [0x133A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A2,
+ },
+ [0x133A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A3,
+ },
+ [0x133A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A4,
+ },
+ [0x133A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A5,
+ },
+ [0x133A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A6,
+ },
+ [0x133A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A7,
+ },
+ [0x133A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A8,
+ },
+ [0x133A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A9,
+ },
+ [0x133AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AA,
+ },
+ [0x133AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AB,
+ },
+ [0x133AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AC,
+ },
+ [0x133AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AD,
+ },
+ [0x133AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AE,
+ },
+ [0x133AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AF,
+ },
+ [0x133B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B0,
+ },
+ [0x133B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B1,
+ },
+ [0x133B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B2,
+ },
+ [0x133B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B3,
+ },
+ [0x133B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B4,
+ },
+ [0x133B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B5,
+ },
+ [0x133B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B6,
+ },
+ [0x133B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B7,
+ },
+ [0x133B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B8,
+ },
+ [0x133B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B9,
+ },
+ [0x133BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BA,
+ },
+ [0x133BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BB,
+ },
+ [0x133BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BC,
+ },
+ [0x133BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BD,
+ },
+ [0x133BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BE,
+ },
+ [0x133BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BF,
+ },
+ [0x133C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C0,
+ },
+ [0x133C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C1,
+ },
+ [0x133C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C2,
+ },
+ [0x133C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C3,
+ },
+ [0x133C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C4,
+ },
+ [0x133C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C5,
+ },
+ [0x133C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C6,
+ },
+ [0x133C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C7,
+ },
+ [0x133C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C8,
+ },
+ [0x133C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C9,
+ },
+ [0x133CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CA,
+ },
+ [0x133CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CB,
+ },
+ [0x133CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CC,
+ },
+ [0x133CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CD,
+ },
+ [0x133CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CE,
+ },
+ [0x133CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CF,
+ },
+ [0x133D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D0,
+ },
+ [0x133D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D1,
+ },
+ [0x133D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D2,
+ },
+ [0x133D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D3,
+ },
+ [0x133D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D4,
+ },
+ [0x133D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D5,
+ },
+ [0x133D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D6,
+ },
+ [0x133D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D7,
+ },
+ [0x133D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D8,
+ },
+ [0x133D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D9,
+ },
+ [0x133DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DA,
+ },
+ [0x133DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DB,
+ },
+ [0x133DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DC,
+ },
+ [0x133DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DD,
+ },
+ [0x133DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DE,
+ },
+ [0x133DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DF,
+ },
+ [0x133E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E0,
+ },
+ [0x133E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E1,
+ },
+ [0x133E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E2,
+ },
+ [0x133E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E3,
+ },
+ [0x133E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E4,
+ },
+ [0x133E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E5,
+ },
+ [0x133E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E6,
+ },
+ [0x133E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E7,
+ },
+ [0x133E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E8,
+ },
+ [0x133E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E9,
+ },
+ [0x133EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EA,
+ },
+ [0x133EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EB,
+ },
+ [0x133EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EC,
+ },
+ [0x133ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133ED,
+ },
+ [0x133EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z004A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EE,
+ },
+ [0x133EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EF,
+ },
+ [0x133F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F0,
+ },
+ [0x133F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F1,
+ },
+ [0x133F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F2,
+ },
+ [0x133F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F3,
+ },
+ [0x133F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F4,
+ },
+ [0x133F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F5,
+ },
+ [0x133F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F6,
+ },
+ [0x133F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F7,
+ },
+ [0x133F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F8,
+ },
+ [0x133F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F9,
+ },
+ [0x133FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FA,
+ },
+ [0x133FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FB,
+ },
+ [0x133FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FC,
+ },
+ [0x133FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FD,
+ },
+ [0x133FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FE,
+ },
+ [0x133FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FF,
+ },
+ [0x13400]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13400,
+ },
+ [0x13401]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13401,
+ },
+ [0x13402]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13402,
+ },
+ [0x13403]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13403,
+ },
+ [0x13404]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13404,
+ },
+ [0x13405]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13405,
+ },
+ [0x13406]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13406,
+ },
+ [0x13407]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13407,
+ },
+ [0x13408]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13408,
+ },
+ [0x13409]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13409,
+ },
+ [0x1340A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340A,
+ },
+ [0x1340B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340B,
+ },
+ [0x1340C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340C,
+ },
+ [0x1340D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340D,
+ },
+ [0x1340E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340E,
+ },
+ [0x1340F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340F,
+ },
+ [0x13410]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13410,
+ },
+ [0x13411]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13411,
+ },
+ [0x13412]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13412,
+ },
+ [0x13413]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13413,
+ },
+ [0x13414]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13414,
+ },
+ [0x13415]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13415,
+ },
+ [0x13416]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13416,
+ },
+ [0x13417]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13417,
+ },
+ [0x13418]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13418,
+ },
+ [0x13419]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13419,
+ },
+ [0x1341A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341A,
+ },
+ [0x1341B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341B,
+ },
+ [0x1341C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341C,
+ },
+ [0x1341D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341D,
+ },
+ [0x1341E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341E,
+ },
+ [0x1341F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341F,
+ },
+ [0x13420]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13420,
+ },
+ [0x13421]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13421,
+ },
+ [0x13422]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13422,
+ },
+ [0x13423]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13423,
+ },
+ [0x13424]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13424,
+ },
+ [0x13425]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13425,
+ },
+ [0x13426]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13426,
+ },
+ [0x13427]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13427,
+ },
+ [0x13428]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13428,
+ },
+ [0x13429]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13429,
+ },
+ [0x1342A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342A,
+ },
+ [0x1342B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342B,
+ },
+ [0x1342C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342C,
+ },
+ [0x1342D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342D,
+ },
+ [0x1342E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342E,
+ },
+ [0x14400]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14400,
+ },
+ [0x14401]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14401,
+ },
+ [0x14402]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14402,
+ },
+ [0x14403]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14403,
+ },
+ [0x14404]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14404,
+ },
+ [0x14405]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14405,
+ },
+ [0x14406]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14406,
+ },
+ [0x14407]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14407,
+ },
+ [0x14408]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14408,
+ },
+ [0x14409]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14409,
+ },
+ [0x1440A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440A,
+ },
+ [0x1440B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440B,
+ },
+ [0x1440C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440C,
+ },
+ [0x1440D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440D,
+ },
+ [0x1440E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440E,
+ },
+ [0x1440F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1440F,
+ },
+ [0x14410]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14410,
+ },
+ [0x14411]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14411,
+ },
+ [0x14412]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14412,
+ },
+ [0x14413]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14413,
+ },
+ [0x14414]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14414,
+ },
+ [0x14415]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14415,
+ },
+ [0x14416]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14416,
+ },
+ [0x14417]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14417,
+ },
+ [0x14418]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14418,
+ },
+ [0x14419]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14419,
+ },
+ [0x1441A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441A,
+ },
+ [0x1441B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A026A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441B,
+ },
+ [0x1441C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441C,
+ },
+ [0x1441D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441D,
+ },
+ [0x1441E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441E,
+ },
+ [0x1441F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1441F,
+ },
+ [0x14420]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14420,
+ },
+ [0x14421]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14421,
+ },
+ [0x14422]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14422,
+ },
+ [0x14423]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14423,
+ },
+ [0x14424]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14424,
+ },
+ [0x14425]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14425,
+ },
+ [0x14426]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14426,
+ },
+ [0x14427]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14427,
+ },
+ [0x14428]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14428,
+ },
+ [0x14429]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A039A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14429,
+ },
+ [0x1442A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442A,
+ },
+ [0x1442B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442B,
+ },
+ [0x1442C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A041A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442C,
+ },
+ [0x1442D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442D,
+ },
+ [0x1442E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442E,
+ },
+ [0x1442F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1442F,
+ },
+ [0x14430]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14430,
+ },
+ [0x14431]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14431,
+ },
+ [0x14432]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14432,
+ },
+ [0x14433]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A046A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14433,
+ },
+ [0x14434]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A046B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14434,
+ },
+ [0x14435]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14435,
+ },
+ [0x14436]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14436,
+ },
+ [0x14437]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14437,
+ },
+ [0x14438]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14438,
+ },
+ [0x14439]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14439,
+ },
+ [0x1443A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443A,
+ },
+ [0x1443B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443B,
+ },
+ [0x1443C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443C,
+ },
+ [0x1443D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443D,
+ },
+ [0x1443E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443E,
+ },
+ [0x1443F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1443F,
+ },
+ [0x14440]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14440,
+ },
+ [0x14441]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14441,
+ },
+ [0x14442]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14442,
+ },
+ [0x14443]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14443,
+ },
+ [0x14444]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14444,
+ },
+ [0x14445]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A063",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14445,
+ },
+ [0x14446]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A064",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14446,
+ },
+ [0x14447]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14447,
+ },
+ [0x14448]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14448,
+ },
+ [0x14449]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A066A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14449,
+ },
+ [0x1444A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A066B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444A,
+ },
+ [0x1444B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A066C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444B,
+ },
+ [0x1444C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444C,
+ },
+ [0x1444D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A068",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444D,
+ },
+ [0x1444E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A069",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444E,
+ },
+ [0x1444F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A070",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1444F,
+ },
+ [0x14450]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A071",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14450,
+ },
+ [0x14451]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A072",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14451,
+ },
+ [0x14452]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A073",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14452,
+ },
+ [0x14453]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A074",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14453,
+ },
+ [0x14454]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A075",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14454,
+ },
+ [0x14455]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A076",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14455,
+ },
+ [0x14456]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A077",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14456,
+ },
+ [0x14457]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A078",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14457,
+ },
+ [0x14458]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A079",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14458,
+ },
+ [0x14459]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A080",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14459,
+ },
+ [0x1445A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A081",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445A,
+ },
+ [0x1445B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A082",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445B,
+ },
+ [0x1445C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A083",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445C,
+ },
+ [0x1445D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A084",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445D,
+ },
+ [0x1445E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A085",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445E,
+ },
+ [0x1445F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A086",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1445F,
+ },
+ [0x14460]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A087",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14460,
+ },
+ [0x14461]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A088",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14461,
+ },
+ [0x14462]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A089",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14462,
+ },
+ [0x14463]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A090",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14463,
+ },
+ [0x14464]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A091",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14464,
+ },
+ [0x14465]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A092",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14465,
+ },
+ [0x14466]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A093",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14466,
+ },
+ [0x14467]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A094",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14467,
+ },
+ [0x14468]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A095",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14468,
+ },
+ [0x14469]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A096",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14469,
+ },
+ [0x1446A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A097",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446A,
+ },
+ [0x1446B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A097A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446B,
+ },
+ [0x1446C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A098",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446C,
+ },
+ [0x1446D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A098A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446D,
+ },
+ [0x1446E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A099",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446E,
+ },
+ [0x1446F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A100",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1446F,
+ },
+ [0x14470]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A100A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14470,
+ },
+ [0x14471]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A101",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14471,
+ },
+ [0x14472]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A101A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14472,
+ },
+ [0x14473]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A102",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14473,
+ },
+ [0x14474]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A102A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14474,
+ },
+ [0x14475]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A103",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14475,
+ },
+ [0x14476]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A104",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14476,
+ },
+ [0x14477]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A104A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14477,
+ },
+ [0x14478]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A104B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14478,
+ },
+ [0x14479]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A104C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14479,
+ },
+ [0x1447A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A105",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447A,
+ },
+ [0x1447B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A105A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447B,
+ },
+ [0x1447C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A105B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447C,
+ },
+ [0x1447D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A106",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447D,
+ },
+ [0x1447E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A107",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447E,
+ },
+ [0x1447F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A107A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1447F,
+ },
+ [0x14480]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A107B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14480,
+ },
+ [0x14481]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A107C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14481,
+ },
+ [0x14482]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A108",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14482,
+ },
+ [0x14483]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A109",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14483,
+ },
+ [0x14484]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A110",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14484,
+ },
+ [0x14485]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A110A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14485,
+ },
+ [0x14486]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A110B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14486,
+ },
+ [0x14487]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A111",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14487,
+ },
+ [0x14488]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A112",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14488,
+ },
+ [0x14489]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A113",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14489,
+ },
+ [0x1448A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A114",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448A,
+ },
+ [0x1448B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A115",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448B,
+ },
+ [0x1448C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A115A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448C,
+ },
+ [0x1448D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A116",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448D,
+ },
+ [0x1448E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A117",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448E,
+ },
+ [0x1448F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A118",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1448F,
+ },
+ [0x14490]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A119",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14490,
+ },
+ [0x14491]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A120",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14491,
+ },
+ [0x14492]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A121",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14492,
+ },
+ [0x14493]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A122",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14493,
+ },
+ [0x14494]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A123",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14494,
+ },
+ [0x14495]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A124",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14495,
+ },
+ [0x14496]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A125",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14496,
+ },
+ [0x14497]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A125A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14497,
+ },
+ [0x14498]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A126",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14498,
+ },
+ [0x14499]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A127",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14499,
+ },
+ [0x1449A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A128",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449A,
+ },
+ [0x1449B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A129",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449B,
+ },
+ [0x1449C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A130",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449C,
+ },
+ [0x1449D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A131",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449D,
+ },
+ [0x1449E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A132",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449E,
+ },
+ [0x1449F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A133",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1449F,
+ },
+ [0x144A0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A134",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A0,
+ },
+ [0x144A1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A135",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A1,
+ },
+ [0x144A2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A135A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A2,
+ },
+ [0x144A3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A136",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A3,
+ },
+ [0x144A4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A137",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A4,
+ },
+ [0x144A5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A138",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A5,
+ },
+ [0x144A6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A139",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A6,
+ },
+ [0x144A7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A140",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A7,
+ },
+ [0x144A8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A141",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A8,
+ },
+ [0x144A9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A142",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144A9,
+ },
+ [0x144AA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A143",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AA,
+ },
+ [0x144AB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A144",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AB,
+ },
+ [0x144AC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A145",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AC,
+ },
+ [0x144AD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A146",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AD,
+ },
+ [0x144AE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A147",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AE,
+ },
+ [0x144AF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A148",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144AF,
+ },
+ [0x144B0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A149",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B0,
+ },
+ [0x144B1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A150",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B1,
+ },
+ [0x144B2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A151",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B2,
+ },
+ [0x144B3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A152",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B3,
+ },
+ [0x144B4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A153",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B4,
+ },
+ [0x144B5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A154",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B5,
+ },
+ [0x144B6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A155",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B6,
+ },
+ [0x144B7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A156",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B7,
+ },
+ [0x144B8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A157",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B8,
+ },
+ [0x144B9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A158",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144B9,
+ },
+ [0x144BA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A159",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BA,
+ },
+ [0x144BB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A160",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BB,
+ },
+ [0x144BC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A161",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BC,
+ },
+ [0x144BD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A162",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BD,
+ },
+ [0x144BE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A163",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BE,
+ },
+ [0x144BF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A164",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144BF,
+ },
+ [0x144C0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A165",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C0,
+ },
+ [0x144C1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A166",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C1,
+ },
+ [0x144C2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A167",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C2,
+ },
+ [0x144C3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A168",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C3,
+ },
+ [0x144C4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A169",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C4,
+ },
+ [0x144C5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A170",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C5,
+ },
+ [0x144C6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A171",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C6,
+ },
+ [0x144C7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A172",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C7,
+ },
+ [0x144C8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A173",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C8,
+ },
+ [0x144C9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A174",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144C9,
+ },
+ [0x144CA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A175",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CA,
+ },
+ [0x144CB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A176",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CB,
+ },
+ [0x144CC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A177",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CC,
+ },
+ [0x144CD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A178",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CD,
+ },
+ [0x144CE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A179",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CE,
+ },
+ [0x144CF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A180",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144CF,
+ },
+ [0x144D0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A181",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D0,
+ },
+ [0x144D1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A182",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D1,
+ },
+ [0x144D2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A183",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D2,
+ },
+ [0x144D3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A184",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D3,
+ },
+ [0x144D4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A185",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D4,
+ },
+ [0x144D5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A186",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D5,
+ },
+ [0x144D6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A187",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D6,
+ },
+ [0x144D7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A188",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D7,
+ },
+ [0x144D8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A189",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D8,
+ },
+ [0x144D9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A190",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144D9,
+ },
+ [0x144DA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A191",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DA,
+ },
+ [0x144DB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A192",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DB,
+ },
+ [0x144DC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A193",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DC,
+ },
+ [0x144DD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A194",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DD,
+ },
+ [0x144DE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A195",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DE,
+ },
+ [0x144DF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A196",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144DF,
+ },
+ [0x144E0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A197",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E0,
+ },
+ [0x144E1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A198",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E1,
+ },
+ [0x144E2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A199",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E2,
+ },
+ [0x144E3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A200",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E3,
+ },
+ [0x144E4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A201",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E4,
+ },
+ [0x144E5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A202",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E5,
+ },
+ [0x144E6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A202A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E6,
+ },
+ [0x144E7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A202B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E7,
+ },
+ [0x144E8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A203",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E8,
+ },
+ [0x144E9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A204",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144E9,
+ },
+ [0x144EA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A205",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144EA,
+ },
+ [0x144EB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A206",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144EB,
+ },
+ [0x144EC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A207",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144EC,
+ },
+ [0x144ED]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A207A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144ED,
+ },
+ [0x144EE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A208",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144EE,
+ },
+ [0x144EF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A209",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144EF,
+ },
+ [0x144F0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A209A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F0,
+ },
+ [0x144F1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A210",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F1,
+ },
+ [0x144F2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A211",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F2,
+ },
+ [0x144F3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A212",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F3,
+ },
+ [0x144F4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A213",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F4,
+ },
+ [0x144F5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A214",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F5,
+ },
+ [0x144F6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A215",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F6,
+ },
+ [0x144F7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A215A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F7,
+ },
+ [0x144F8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A216",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F8,
+ },
+ [0x144F9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A216A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144F9,
+ },
+ [0x144FA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A217",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FA,
+ },
+ [0x144FB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A218",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FB,
+ },
+ [0x144FC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A219",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FC,
+ },
+ [0x144FD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A220",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FD,
+ },
+ [0x144FE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A221",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FE,
+ },
+ [0x144FF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A222",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x144FF,
+ },
+ [0x14500]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A223",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14500,
+ },
+ [0x14501]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A224",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14501,
+ },
+ [0x14502]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A225",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14502,
+ },
+ [0x14503]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A226",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14503,
+ },
+ [0x14504]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A227",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14504,
+ },
+ [0x14505]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A227A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14505,
+ },
+ [0x14506]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A228",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14506,
+ },
+ [0x14507]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A229",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14507,
+ },
+ [0x14508]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A230",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14508,
+ },
+ [0x14509]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A231",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14509,
+ },
+ [0x1450A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A232",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450A,
+ },
+ [0x1450B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A233",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450B,
+ },
+ [0x1450C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A234",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450C,
+ },
+ [0x1450D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A235",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450D,
+ },
+ [0x1450E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A236",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450E,
+ },
+ [0x1450F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A237",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1450F,
+ },
+ [0x14510]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A238",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14510,
+ },
+ [0x14511]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A239",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14511,
+ },
+ [0x14512]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A240",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14512,
+ },
+ [0x14513]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A241",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14513,
+ },
+ [0x14514]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A242",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14514,
+ },
+ [0x14515]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A243",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14515,
+ },
+ [0x14516]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A244",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14516,
+ },
+ [0x14517]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A245",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14517,
+ },
+ [0x14518]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A246",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14518,
+ },
+ [0x14519]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A247",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14519,
+ },
+ [0x1451A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A248",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451A,
+ },
+ [0x1451B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A249",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451B,
+ },
+ [0x1451C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A250",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451C,
+ },
+ [0x1451D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A251",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451D,
+ },
+ [0x1451E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A252",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451E,
+ },
+ [0x1451F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A253",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1451F,
+ },
+ [0x14520]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A254",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14520,
+ },
+ [0x14521]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A255",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14521,
+ },
+ [0x14522]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A256",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14522,
+ },
+ [0x14523]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A257",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14523,
+ },
+ [0x14524]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A258",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14524,
+ },
+ [0x14525]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A259",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14525,
+ },
+ [0x14526]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A260",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14526,
+ },
+ [0x14527]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A261",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14527,
+ },
+ [0x14528]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A262",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14528,
+ },
+ [0x14529]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A263",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14529,
+ },
+ [0x1452A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A264",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452A,
+ },
+ [0x1452B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A265",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452B,
+ },
+ [0x1452C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A266",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452C,
+ },
+ [0x1452D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A267",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452D,
+ },
+ [0x1452E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A267A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452E,
+ },
+ [0x1452F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A268",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1452F,
+ },
+ [0x14530]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A269",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14530,
+ },
+ [0x14531]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A270",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14531,
+ },
+ [0x14532]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A271",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14532,
+ },
+ [0x14533]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A272",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14533,
+ },
+ [0x14534]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A273",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14534,
+ },
+ [0x14535]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A274",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14535,
+ },
+ [0x14536]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A275",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14536,
+ },
+ [0x14537]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A276",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14537,
+ },
+ [0x14538]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A277",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14538,
+ },
+ [0x14539]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A278",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14539,
+ },
+ [0x1453A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A279",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453A,
+ },
+ [0x1453B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A280",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453B,
+ },
+ [0x1453C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A281",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453C,
+ },
+ [0x1453D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A282",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453D,
+ },
+ [0x1453E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A283",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453E,
+ },
+ [0x1453F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A284",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1453F,
+ },
+ [0x14540]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A285",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14540,
+ },
+ [0x14541]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A286",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14541,
+ },
+ [0x14542]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A287",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14542,
+ },
+ [0x14543]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A288",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14543,
+ },
+ [0x14544]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A289",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14544,
+ },
+ [0x14545]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A289A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14545,
+ },
+ [0x14546]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A290",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14546,
+ },
+ [0x14547]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A291",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14547,
+ },
+ [0x14548]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A292",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14548,
+ },
+ [0x14549]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A293",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14549,
+ },
+ [0x1454A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A294",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454A,
+ },
+ [0x1454B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A294A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454B,
+ },
+ [0x1454C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A295",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454C,
+ },
+ [0x1454D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A296",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454D,
+ },
+ [0x1454E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A297",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454E,
+ },
+ [0x1454F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A298",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1454F,
+ },
+ [0x14550]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A299",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14550,
+ },
+ [0x14551]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A299A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14551,
+ },
+ [0x14552]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A300",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14552,
+ },
+ [0x14553]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A301",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14553,
+ },
+ [0x14554]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A302",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14554,
+ },
+ [0x14555]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A303",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14555,
+ },
+ [0x14556]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A304",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14556,
+ },
+ [0x14557]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A305",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14557,
+ },
+ [0x14558]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A306",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14558,
+ },
+ [0x14559]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A307",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14559,
+ },
+ [0x1455A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A308",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455A,
+ },
+ [0x1455B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A309",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455B,
+ },
+ [0x1455C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A309A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455C,
+ },
+ [0x1455D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A310",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455D,
+ },
+ [0x1455E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A311",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455E,
+ },
+ [0x1455F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A312",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1455F,
+ },
+ [0x14560]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A313",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14560,
+ },
+ [0x14561]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A314",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14561,
+ },
+ [0x14562]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A315",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14562,
+ },
+ [0x14563]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A316",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14563,
+ },
+ [0x14564]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A317",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14564,
+ },
+ [0x14565]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A318",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14565,
+ },
+ [0x14566]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A319",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14566,
+ },
+ [0x14567]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A320",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14567,
+ },
+ [0x14568]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A321",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14568,
+ },
+ [0x14569]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A322",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14569,
+ },
+ [0x1456A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A323",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456A,
+ },
+ [0x1456B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A324",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456B,
+ },
+ [0x1456C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A325",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456C,
+ },
+ [0x1456D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A326",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456D,
+ },
+ [0x1456E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A327",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456E,
+ },
+ [0x1456F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A328",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1456F,
+ },
+ [0x14570]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A329",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14570,
+ },
+ [0x14571]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A329A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14571,
+ },
+ [0x14572]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A330",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14572,
+ },
+ [0x14573]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A331",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14573,
+ },
+ [0x14574]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A332A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14574,
+ },
+ [0x14575]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A332B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14575,
+ },
+ [0x14576]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A332C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14576,
+ },
+ [0x14577]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A333",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14577,
+ },
+ [0x14578]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A334",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14578,
+ },
+ [0x14579]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A335",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14579,
+ },
+ [0x1457A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A336",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457A,
+ },
+ [0x1457B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A336A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457B,
+ },
+ [0x1457C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A336B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457C,
+ },
+ [0x1457D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A336C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457D,
+ },
+ [0x1457E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A337",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457E,
+ },
+ [0x1457F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A338",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1457F,
+ },
+ [0x14580]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A339",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14580,
+ },
+ [0x14581]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A340",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14581,
+ },
+ [0x14582]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A341",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14582,
+ },
+ [0x14583]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A342",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14583,
+ },
+ [0x14584]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A343",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14584,
+ },
+ [0x14585]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A344",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14585,
+ },
+ [0x14586]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A345",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14586,
+ },
+ [0x14587]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A346",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14587,
+ },
+ [0x14588]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A347",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14588,
+ },
+ [0x14589]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A348",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14589,
+ },
+ [0x1458A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A349",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458A,
+ },
+ [0x1458B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A350",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458B,
+ },
+ [0x1458C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A351",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458C,
+ },
+ [0x1458D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A352",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458D,
+ },
+ [0x1458E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A353",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458E,
+ },
+ [0x1458F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A354",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1458F,
+ },
+ [0x14590]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A355",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14590,
+ },
+ [0x14591]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A356",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14591,
+ },
+ [0x14592]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A357",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14592,
+ },
+ [0x14593]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A358",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14593,
+ },
+ [0x14594]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A359",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14594,
+ },
+ [0x14595]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A359A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14595,
+ },
+ [0x14596]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A360",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14596,
+ },
+ [0x14597]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A361",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14597,
+ },
+ [0x14598]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A362",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14598,
+ },
+ [0x14599]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A363",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14599,
+ },
+ [0x1459A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A364",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459A,
+ },
+ [0x1459B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A364A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459B,
+ },
+ [0x1459C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A365",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459C,
+ },
+ [0x1459D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A366",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459D,
+ },
+ [0x1459E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A367",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459E,
+ },
+ [0x1459F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A368",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1459F,
+ },
+ [0x145A0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A368A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A0,
+ },
+ [0x145A1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A369",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A1,
+ },
+ [0x145A2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A370",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A2,
+ },
+ [0x145A3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A371",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A3,
+ },
+ [0x145A4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A371A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A4,
+ },
+ [0x145A5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A372",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A5,
+ },
+ [0x145A6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A373",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A6,
+ },
+ [0x145A7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A374",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A7,
+ },
+ [0x145A8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A375",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A8,
+ },
+ [0x145A9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A376",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145A9,
+ },
+ [0x145AA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A377",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AA,
+ },
+ [0x145AB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A378",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AB,
+ },
+ [0x145AC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A379",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AC,
+ },
+ [0x145AD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A380",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AD,
+ },
+ [0x145AE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A381",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AE,
+ },
+ [0x145AF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A381A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145AF,
+ },
+ [0x145B0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A382",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B0,
+ },
+ [0x145B1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A383 RA OR RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B1,
+ },
+ [0x145B2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A383A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B2,
+ },
+ [0x145B3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A384",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B3,
+ },
+ [0x145B4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A385",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B4,
+ },
+ [0x145B5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A386",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B5,
+ },
+ [0x145B6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A386A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B6,
+ },
+ [0x145B7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A387",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B7,
+ },
+ [0x145B8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A388",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B8,
+ },
+ [0x145B9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A389",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145B9,
+ },
+ [0x145BA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A390",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BA,
+ },
+ [0x145BB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A391",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BB,
+ },
+ [0x145BC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A392",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BC,
+ },
+ [0x145BD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A393 EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BD,
+ },
+ [0x145BE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A394",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BE,
+ },
+ [0x145BF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A395",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145BF,
+ },
+ [0x145C0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A396",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C0,
+ },
+ [0x145C1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A397",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C1,
+ },
+ [0x145C2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A398",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C2,
+ },
+ [0x145C3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A399",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C3,
+ },
+ [0x145C4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A400",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C4,
+ },
+ [0x145C5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A401",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C5,
+ },
+ [0x145C6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A402",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C6,
+ },
+ [0x145C7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A403",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C7,
+ },
+ [0x145C8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A404",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C8,
+ },
+ [0x145C9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A405",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145C9,
+ },
+ [0x145CA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A406",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145CA,
+ },
+ [0x145CB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A407",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145CB,
+ },
+ [0x145CC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A408",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145CC,
+ },
+ [0x145CD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A409",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145CD,
+ },
+ [0x145CE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x145CE,
+ },
+ [0x145CF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x145CF,
+ },
+ [0x145D0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A411",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D0,
+ },
+ [0x145D1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A412",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D1,
+ },
+ [0x145D2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A413",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D2,
+ },
+ [0x145D3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A414",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D3,
+ },
+ [0x145D4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A415",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D4,
+ },
+ [0x145D5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A416",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D5,
+ },
+ [0x145D6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A417",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D6,
+ },
+ [0x145D7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A418",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D7,
+ },
+ [0x145D8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A419",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D8,
+ },
+ [0x145D9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A420",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145D9,
+ },
+ [0x145DA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A421",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DA,
+ },
+ [0x145DB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A422",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DB,
+ },
+ [0x145DC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A423",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DC,
+ },
+ [0x145DD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A424",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DD,
+ },
+ [0x145DE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A425",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DE,
+ },
+ [0x145DF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A426",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145DF,
+ },
+ [0x145E0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A427",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E0,
+ },
+ [0x145E1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A428",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E1,
+ },
+ [0x145E2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A429",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E2,
+ },
+ [0x145E3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A430",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E3,
+ },
+ [0x145E4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A431",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E4,
+ },
+ [0x145E5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A432",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E5,
+ },
+ [0x145E6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A433",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E6,
+ },
+ [0x145E7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A434",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E7,
+ },
+ [0x145E8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A435",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E8,
+ },
+ [0x145E9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A436",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145E9,
+ },
+ [0x145EA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A437",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145EA,
+ },
+ [0x145EB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A438",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145EB,
+ },
+ [0x145EC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A439",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145EC,
+ },
+ [0x145ED]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A440",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145ED,
+ },
+ [0x145EE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A441",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145EE,
+ },
+ [0x145EF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A442",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145EF,
+ },
+ [0x145F0]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A443",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F0,
+ },
+ [0x145F1]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A444",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F1,
+ },
+ [0x145F2]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A445",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F2,
+ },
+ [0x145F3]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A446",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F3,
+ },
+ [0x145F4]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A447",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F4,
+ },
+ [0x145F5]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A448",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F5,
+ },
+ [0x145F6]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A449",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F6,
+ },
+ [0x145F7]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A450",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F7,
+ },
+ [0x145F8]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A450A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F8,
+ },
+ [0x145F9]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A451",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145F9,
+ },
+ [0x145FA]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A452",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FA,
+ },
+ [0x145FB]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A453",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FB,
+ },
+ [0x145FC]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A454",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FC,
+ },
+ [0x145FD]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A455",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FD,
+ },
+ [0x145FE]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A456",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FE,
+ },
+ [0x145FF]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A457",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x145FF,
+ },
+ [0x14600]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A457A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14600,
+ },
+ [0x14601]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A458",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14601,
+ },
+ [0x14602]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A459",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14602,
+ },
+ [0x14603]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A460",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14603,
+ },
+ [0x14604]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A461",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14604,
+ },
+ [0x14605]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A462",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14605,
+ },
+ [0x14606]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A463",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14606,
+ },
+ [0x14607]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A464",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14607,
+ },
+ [0x14608]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A465",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14608,
+ },
+ [0x14609]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A466",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14609,
+ },
+ [0x1460A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A467",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460A,
+ },
+ [0x1460B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A468",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460B,
+ },
+ [0x1460C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A469",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460C,
+ },
+ [0x1460D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A470",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460D,
+ },
+ [0x1460E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A471",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460E,
+ },
+ [0x1460F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A472",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1460F,
+ },
+ [0x14610]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A473",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14610,
+ },
+ [0x14611]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A474",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14611,
+ },
+ [0x14612]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A475",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14612,
+ },
+ [0x14613]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A476",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14613,
+ },
+ [0x14614]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A477",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14614,
+ },
+ [0x14615]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A478",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14615,
+ },
+ [0x14616]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A479",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14616,
+ },
+ [0x14617]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A480",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14617,
+ },
+ [0x14618]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A481",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14618,
+ },
+ [0x14619]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A482",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14619,
+ },
+ [0x1461A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A483",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461A,
+ },
+ [0x1461B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A484",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461B,
+ },
+ [0x1461C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A485",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461C,
+ },
+ [0x1461D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A486",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461D,
+ },
+ [0x1461E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A487",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461E,
+ },
+ [0x1461F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A488",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1461F,
+ },
+ [0x14620]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A489",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14620,
+ },
+ [0x14621]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A490",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14621,
+ },
+ [0x14622]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A491",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14622,
+ },
+ [0x14623]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A492",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14623,
+ },
+ [0x14624]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A493",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14624,
+ },
+ [0x14625]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A494",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14625,
+ },
+ [0x14626]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A495",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14626,
+ },
+ [0x14627]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A496",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14627,
+ },
+ [0x14628]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A497",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14628,
+ },
+ [0x14629]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A501",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14629,
+ },
+ [0x1462A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A502",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462A,
+ },
+ [0x1462B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A503",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462B,
+ },
+ [0x1462C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A504",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462C,
+ },
+ [0x1462D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A505",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462D,
+ },
+ [0x1462E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A506",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462E,
+ },
+ [0x1462F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A507",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1462F,
+ },
+ [0x14630]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A508",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14630,
+ },
+ [0x14631]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A509",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14631,
+ },
+ [0x14632]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A510",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14632,
+ },
+ [0x14633]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A511",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14633,
+ },
+ [0x14634]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A512",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14634,
+ },
+ [0x14635]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A513",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14635,
+ },
+ [0x14636]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A514",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14636,
+ },
+ [0x14637]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A515",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14637,
+ },
+ [0x14638]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A516",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14638,
+ },
+ [0x14639]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A517",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14639,
+ },
+ [0x1463A]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A518",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463A,
+ },
+ [0x1463B]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A519",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463B,
+ },
+ [0x1463C]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A520",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463C,
+ },
+ [0x1463D]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A521",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463D,
+ },
+ [0x1463E]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A522",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463E,
+ },
+ [0x1463F]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A523",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1463F,
+ },
+ [0x14640]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A524",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14640,
+ },
+ [0x14641]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A525",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14641,
+ },
+ [0x14642]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A526",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14642,
+ },
+ [0x14643]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A527",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14643,
+ },
+ [0x14644]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A528",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14644,
+ },
+ [0x14645]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A529",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14645,
+ },
+ [0x14646]={
+ category="lo",
+ description="ANATOLIAN HIEROGLYPH A530",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x14646,
+ },
+ [0x16800]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGKUE MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16800,
+ },
+ [0x16801]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GBIEE FON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16801,
+ },
+ [0x16802]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16802,
+ },
+ [0x16803]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON MFON PIPAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16803,
+ },
+ [0x16804]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NAA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16804,
+ },
+ [0x16805]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHUENSHUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16805,
+ },
+ [0x16806]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TITA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16806,
+ },
+ [0x16807]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NZA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16807,
+ },
+ [0x16808]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHINDA PA NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16808,
+ },
+ [0x16809]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16809,
+ },
+ [0x1680A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680A,
+ },
+ [0x1680B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMBGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680B,
+ },
+ [0x1680C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TU MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680C,
+ },
+ [0x1680D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGANGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680D,
+ },
+ [0x1680E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMVEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680E,
+ },
+ [0x1680F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MANSUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680F,
+ },
+ [0x16810]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MVEUAENGAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16810,
+ },
+ [0x16811]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SEUNYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16811,
+ },
+ [0x16812]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTOQPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16812,
+ },
+ [0x16813]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KEUKEUTNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16813,
+ },
+ [0x16814]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NKINDI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16814,
+ },
+ [0x16815]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16815,
+ },
+ [0x16816]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGKUENZEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16816,
+ },
+ [0x16817]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LAPAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16817,
+ },
+ [0x16818]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LET KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16818,
+ },
+ [0x16819]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP MFAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16819,
+ },
+ [0x1681A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEKEUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681A,
+ },
+ [0x1681B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PASHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681B,
+ },
+ [0x1681C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GHEUAERAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681C,
+ },
+ [0x1681D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAMSHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681D,
+ },
+ [0x1681E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MON NGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681E,
+ },
+ [0x1681F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NZUN MEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681F,
+ },
+ [0x16820]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A U YUQ NAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16820,
+ },
+ [0x16821]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GHEUAEGHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16821,
+ },
+ [0x16822]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP NTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16822,
+ },
+ [0x16823]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SISA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16823,
+ },
+ [0x16824]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MGBASA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16824,
+ },
+ [0x16825]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MEUNJOMNDEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16825,
+ },
+ [0x16826]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MOOMPUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16826,
+ },
+ [0x16827]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KAFA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16827,
+ },
+ [0x16828]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PA LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16828,
+ },
+ [0x16829]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NDA LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16829,
+ },
+ [0x1682A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682A,
+ },
+ [0x1682B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMKPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682B,
+ },
+ [0x1682C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NIKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682C,
+ },
+ [0x1682D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682D,
+ },
+ [0x1682E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682E,
+ },
+ [0x1682F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682F,
+ },
+ [0x16830]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SONJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16830,
+ },
+ [0x16831]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TEUTEUWEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16831,
+ },
+ [0x16832]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAENYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16832,
+ },
+ [0x16833]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16833,
+ },
+ [0x16834]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NDAANGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16834,
+ },
+ [0x16835]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16835,
+ },
+ [0x16836]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MOOMEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16836,
+ },
+ [0x16837]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16837,
+ },
+ [0x16838]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LOMMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16838,
+ },
+ [0x16839]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A FIRI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16839,
+ },
+ [0x1683A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A ROM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683A,
+ },
+ [0x1683B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KPOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683B,
+ },
+ [0x1683C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683C,
+ },
+ [0x1683D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAP PIEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683D,
+ },
+ [0x1683E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHIRAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683E,
+ },
+ [0x1683F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683F,
+ },
+ [0x16840]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHOQ NSHUT YUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16840,
+ },
+ [0x16841]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYIT MONGKEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16841,
+ },
+ [0x16842]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16842,
+ },
+ [0x16843]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NKAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16843,
+ },
+ [0x16844]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A UNKNOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16844,
+ },
+ [0x16845]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16845,
+ },
+ [0x16846]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAESI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16846,
+ },
+ [0x16847]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16847,
+ },
+ [0x16848]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MBANYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16848,
+ },
+ [0x16849]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16849,
+ },
+ [0x1684A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684A,
+ },
+ [0x1684B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684B,
+ },
+ [0x1684C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684C,
+ },
+ [0x1684D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NSHIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684D,
+ },
+ [0x1684E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684E,
+ },
+ [0x1684F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684F,
+ },
+ [0x16850]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16850,
+ },
+ [0x16851]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16851,
+ },
+ [0x16852]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16852,
+ },
+ [0x16853]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16853,
+ },
+ [0x16854]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16854,
+ },
+ [0x16855]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16855,
+ },
+ [0x16856]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MBAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16856,
+ },
+ [0x16857]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NSHUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16857,
+ },
+ [0x16858]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TU MAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16858,
+ },
+ [0x16859]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16859,
+ },
+ [0x1685A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SET TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685A,
+ },
+ [0x1685B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LOM NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685B,
+ },
+ [0x1685C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBA MAELEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685C,
+ },
+ [0x1685D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KIEEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685D,
+ },
+ [0x1685E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B YEURAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685E,
+ },
+ [0x1685F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685F,
+ },
+ [0x16860]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16860,
+ },
+ [0x16861]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PEESHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16861,
+ },
+ [0x16862]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B YAFU LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16862,
+ },
+ [0x16863]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LAM NSHUT NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16863,
+ },
+ [0x16864]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NTIEE SHEUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16864,
+ },
+ [0x16865]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NDU NJAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16865,
+ },
+ [0x16866]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B GHEUGHEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16866,
+ },
+ [0x16867]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16867,
+ },
+ [0x16868]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TU NSIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16868,
+ },
+ [0x16869]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SHET NJAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16869,
+ },
+ [0x1686A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SHEUAEQTU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686A,
+ },
+ [0x1686B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MFON TEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686B,
+ },
+ [0x1686C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBIT MBAAKET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686C,
+ },
+ [0x1686D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NYI NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686D,
+ },
+ [0x1686E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUPUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686E,
+ },
+ [0x1686F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B GHEUGHEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686F,
+ },
+ [0x16870]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUYEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16870,
+ },
+ [0x16871]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LAANAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16871,
+ },
+ [0x16872]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PARUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16872,
+ },
+ [0x16873]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B VEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16873,
+ },
+ [0x16874]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGKINDI MVOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16874,
+ },
+ [0x16875]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGEU MBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16875,
+ },
+ [0x16876]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B WUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16876,
+ },
+ [0x16877]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SAKEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16877,
+ },
+ [0x16878]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16878,
+ },
+ [0x16879]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16879,
+ },
+ [0x1687A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687A,
+ },
+ [0x1687B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGUOQ LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687B,
+ },
+ [0x1687C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MFIYAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687C,
+ },
+ [0x1687D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687D,
+ },
+ [0x1687E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBEURI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687E,
+ },
+ [0x1687F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MONTIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687F,
+ },
+ [0x16880]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NYAEMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16880,
+ },
+ [0x16881]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PUNGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16881,
+ },
+ [0x16882]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MEUT NGGEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16882,
+ },
+ [0x16883]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B FEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16883,
+ },
+ [0x16884]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16884,
+ },
+ [0x16885]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16885,
+ },
+ [0x16886]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16886,
+ },
+ [0x16887]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA NJEUAENA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16887,
+ },
+ [0x16888]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA NJUQA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16888,
+ },
+ [0x16889]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16889,
+ },
+ [0x1688A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688A,
+ },
+ [0x1688B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NSEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688B,
+ },
+ [0x1688C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688C,
+ },
+ [0x1688D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688D,
+ },
+ [0x1688E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688E,
+ },
+ [0x1688F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGKUE MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688F,
+ },
+ [0x16890]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16890,
+ },
+ [0x16891]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16891,
+ },
+ [0x16892]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C WANGKUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16892,
+ },
+ [0x16893]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16893,
+ },
+ [0x16894]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDEUAEREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16894,
+ },
+ [0x16895]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGKAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16895,
+ },
+ [0x16896]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GHARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16896,
+ },
+ [0x16897]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEEKEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16897,
+ },
+ [0x16898]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GBAYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16898,
+ },
+ [0x16899]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16899,
+ },
+ [0x1689A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTU MBIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689A,
+ },
+ [0x1689B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689B,
+ },
+ [0x1689C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PIRIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689C,
+ },
+ [0x1689D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDOMBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689D,
+ },
+ [0x1689E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBAA CABBAGE-TREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689E,
+ },
+ [0x1689F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUSHEUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689F,
+ },
+ [0x168A0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GHAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A0,
+ },
+ [0x168A1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUKAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A1,
+ },
+ [0x168A2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YU MUOMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A2,
+ },
+ [0x168A3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NZEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A3,
+ },
+ [0x168A4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A4,
+ },
+ [0x168A5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A5,
+ },
+ [0x168A6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A6,
+ },
+ [0x168A7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A7,
+ },
+ [0x168A8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KPARAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A8,
+ },
+ [0x168A9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A9,
+ },
+ [0x168AA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AA,
+ },
+ [0x168AB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDIDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AB,
+ },
+ [0x168AC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TAASHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AC,
+ },
+ [0x168AD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AD,
+ },
+ [0x168AE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TITA YUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AE,
+ },
+ [0x168AF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AF,
+ },
+ [0x168B0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUAEN NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B0,
+ },
+ [0x168B1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C VEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B1,
+ },
+ [0x168B2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NANSANAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B2,
+ },
+ [0x168B3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MA KEUAERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B3,
+ },
+ [0x168B4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B4,
+ },
+ [0x168B5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B5,
+ },
+ [0x168B6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B6,
+ },
+ [0x168B7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBIRIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B7,
+ },
+ [0x168B8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MGBASAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B8,
+ },
+ [0x168B9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTEUNGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B9,
+ },
+ [0x168BA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TEUTEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BA,
+ },
+ [0x168BB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BB,
+ },
+ [0x168BC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C FUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BC,
+ },
+ [0x168BD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BD,
+ },
+ [0x168BE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BE,
+ },
+ [0x168BF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSHAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BF,
+ },
+ [0x168C0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C BUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C0,
+ },
+ [0x168C1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C VEUAEPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C1,
+ },
+ [0x168C2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBERAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C2,
+ },
+ [0x168C3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C3,
+ },
+ [0x168C4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C4,
+ },
+ [0x168C5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C5,
+ },
+ [0x168C6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TITUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C6,
+ },
+ [0x168C7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSUOT NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C7,
+ },
+ [0x168C8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C8,
+ },
+ [0x168C9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C9,
+ },
+ [0x168CA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CA,
+ },
+ [0x168CB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MAESI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CB,
+ },
+ [0x168CC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CC,
+ },
+ [0x168CD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CD,
+ },
+ [0x168CE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CE,
+ },
+ [0x168CF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CF,
+ },
+ [0x168D0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D0,
+ },
+ [0x168D1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C WUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D1,
+ },
+ [0x168D2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D2,
+ },
+ [0x168D3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D3,
+ },
+ [0x168D4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D4,
+ },
+ [0x168D5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KUOP NKAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D5,
+ },
+ [0x168D6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D6,
+ },
+ [0x168D7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D7,
+ },
+ [0x168D8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MA NSIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D8,
+ },
+ [0x168D9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D9,
+ },
+ [0x168DA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DA,
+ },
+ [0x168DB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SHUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DB,
+ },
+ [0x168DC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SETFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DC,
+ },
+ [0x168DD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DD,
+ },
+ [0x168DE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DE,
+ },
+ [0x168DF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBANYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DF,
+ },
+ [0x168E0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUSEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E0,
+ },
+ [0x168E1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E1,
+ },
+ [0x168E2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E2,
+ },
+ [0x168E3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBAA PICKET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E3,
+ },
+ [0x168E4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YUWOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E4,
+ },
+ [0x168E5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E5,
+ },
+ [0x168E6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E6,
+ },
+ [0x168E7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E7,
+ },
+ [0x168E8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SHIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E8,
+ },
+ [0x168E9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEN LAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E9,
+ },
+ [0x168EA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEN FATIGUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EA,
+ },
+ [0x168EB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EB,
+ },
+ [0x168EC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EC,
+ },
+ [0x168ED]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168ED,
+ },
+ [0x168EE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EE,
+ },
+ [0x168EF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EF,
+ },
+ [0x168F0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F0,
+ },
+ [0x168F1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F1,
+ },
+ [0x168F2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D WAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F2,
+ },
+ [0x168F3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F3,
+ },
+ [0x168F4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F4,
+ },
+ [0x168F5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F5,
+ },
+ [0x168F6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F6,
+ },
+ [0x168F7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F7,
+ },
+ [0x168F8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F8,
+ },
+ [0x168F9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F9,
+ },
+ [0x168FA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FA,
+ },
+ [0x168FB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D WUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FB,
+ },
+ [0x168FC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FC,
+ },
+ [0x168FD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FD,
+ },
+ [0x168FE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FE,
+ },
+ [0x168FF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUAETMEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FF,
+ },
+ [0x16900]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16900,
+ },
+ [0x16901]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16901,
+ },
+ [0x16902]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16902,
+ },
+ [0x16903]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16903,
+ },
+ [0x16904]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16904,
+ },
+ [0x16905]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YAEMMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16905,
+ },
+ [0x16906]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16906,
+ },
+ [0x16907]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16907,
+ },
+ [0x16908]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16908,
+ },
+ [0x16909]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16909,
+ },
+ [0x1690A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MALEERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690A,
+ },
+ [0x1690B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690B,
+ },
+ [0x1690C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690C,
+ },
+ [0x1690D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690D,
+ },
+ [0x1690E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690E,
+ },
+ [0x1690F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUOT MBUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690F,
+ },
+ [0x16910]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKEURI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16910,
+ },
+ [0x16911]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16911,
+ },
+ [0x16912]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D GHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16912,
+ },
+ [0x16913]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16913,
+ },
+ [0x16914]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D FEUFEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16914,
+ },
+ [0x16915]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16915,
+ },
+ [0x16916]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBOFUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16916,
+ },
+ [0x16917]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16917,
+ },
+ [0x16918]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16918,
+ },
+ [0x16919]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MONI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16919,
+ },
+ [0x1691A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691A,
+ },
+ [0x1691B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PUUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691B,
+ },
+ [0x1691C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691C,
+ },
+ [0x1691D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691D,
+ },
+ [0x1691E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691E,
+ },
+ [0x1691F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSIEEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691F,
+ },
+ [0x16920]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16920,
+ },
+ [0x16921]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KWAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16921,
+ },
+ [0x16922]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16922,
+ },
+ [0x16923]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16923,
+ },
+ [0x16924]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16924,
+ },
+ [0x16925]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUWOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16925,
+ },
+ [0x16926]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16926,
+ },
+ [0x16927]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D RAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16927,
+ },
+ [0x16928]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16928,
+ },
+ [0x16929]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16929,
+ },
+ [0x1692A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692A,
+ },
+ [0x1692B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSIEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692B,
+ },
+ [0x1692C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692C,
+ },
+ [0x1692D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PIP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692D,
+ },
+ [0x1692E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PEUTAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692E,
+ },
+ [0x1692F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692F,
+ },
+ [0x16930]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16930,
+ },
+ [0x16931]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16931,
+ },
+ [0x16932]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16932,
+ },
+ [0x16933]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16933,
+ },
+ [0x16934]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16934,
+ },
+ [0x16935]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16935,
+ },
+ [0x16936]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16936,
+ },
+ [0x16937]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16937,
+ },
+ [0x16938]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16938,
+ },
+ [0x16939]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16939,
+ },
+ [0x1693A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693A,
+ },
+ [0x1693B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693B,
+ },
+ [0x1693C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693C,
+ },
+ [0x1693D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TUOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693D,
+ },
+ [0x1693E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693E,
+ },
+ [0x1693F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693F,
+ },
+ [0x16940]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16940,
+ },
+ [0x16941]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16941,
+ },
+ [0x16942]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MAENJET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16942,
+ },
+ [0x16943]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16943,
+ },
+ [0x16944]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16944,
+ },
+ [0x16945]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16945,
+ },
+ [0x16946]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSHUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16946,
+ },
+ [0x16947]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16947,
+ },
+ [0x16948]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D GHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16948,
+ },
+ [0x16949]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16949,
+ },
+ [0x1694A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D REN OLD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694A,
+ },
+ [0x1694B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694B,
+ },
+ [0x1694C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694C,
+ },
+ [0x1694D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694D,
+ },
+ [0x1694E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694E,
+ },
+ [0x1694F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694F,
+ },
+ [0x16950]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16950,
+ },
+ [0x16951]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16951,
+ },
+ [0x16952]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16952,
+ },
+ [0x16953]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16953,
+ },
+ [0x16954]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16954,
+ },
+ [0x16955]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16955,
+ },
+ [0x16956]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16956,
+ },
+ [0x16957]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16957,
+ },
+ [0x16958]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16958,
+ },
+ [0x16959]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16959,
+ },
+ [0x1695A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695A,
+ },
+ [0x1695B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695B,
+ },
+ [0x1695C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695C,
+ },
+ [0x1695D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695D,
+ },
+ [0x1695E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MVOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695E,
+ },
+ [0x1695F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695F,
+ },
+ [0x16960]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D REN MUCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16960,
+ },
+ [0x16961]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16961,
+ },
+ [0x16962]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16962,
+ },
+ [0x16963]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBAA SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16963,
+ },
+ [0x16964]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16964,
+ },
+ [0x16965]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16965,
+ },
+ [0x16966]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16966,
+ },
+ [0x16967]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16967,
+ },
+ [0x16968]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MBEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16968,
+ },
+ [0x16969]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16969,
+ },
+ [0x1696A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696A,
+ },
+ [0x1696B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696B,
+ },
+ [0x1696C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696C,
+ },
+ [0x1696D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696D,
+ },
+ [0x1696E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696E,
+ },
+ [0x1696F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696F,
+ },
+ [0x16970]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16970,
+ },
+ [0x16971]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16971,
+ },
+ [0x16972]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16972,
+ },
+ [0x16973]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16973,
+ },
+ [0x16974]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KPEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16974,
+ },
+ [0x16975]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16975,
+ },
+ [0x16976]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16976,
+ },
+ [0x16977]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16977,
+ },
+ [0x16978]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16978,
+ },
+ [0x16979]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16979,
+ },
+ [0x1697A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697A,
+ },
+ [0x1697B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697B,
+ },
+ [0x1697C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697C,
+ },
+ [0x1697D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697D,
+ },
+ [0x1697E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697E,
+ },
+ [0x1697F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697F,
+ },
+ [0x16980]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16980,
+ },
+ [0x16981]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16981,
+ },
+ [0x16982]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RIMGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16982,
+ },
+ [0x16983]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16983,
+ },
+ [0x16984]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16984,
+ },
+ [0x16985]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16985,
+ },
+ [0x16986]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGURAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16986,
+ },
+ [0x16987]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16987,
+ },
+ [0x16988]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16988,
+ },
+ [0x16989]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16989,
+ },
+ [0x1698A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJAEMLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698A,
+ },
+ [0x1698B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698B,
+ },
+ [0x1698C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698C,
+ },
+ [0x1698D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698D,
+ },
+ [0x1698E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698E,
+ },
+ [0x1698F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAEN NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698F,
+ },
+ [0x16990]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16990,
+ },
+ [0x16991]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16991,
+ },
+ [0x16992]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAA SOFTNESS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16992,
+ },
+ [0x16993]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGUAESHAE NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16993,
+ },
+ [0x16994]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16994,
+ },
+ [0x16995]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16995,
+ },
+ [0x16996]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16996,
+ },
+ [0x16997]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16997,
+ },
+ [0x16998]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16998,
+ },
+ [0x16999]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16999,
+ },
+ [0x1699A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699A,
+ },
+ [0x1699B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699B,
+ },
+ [0x1699C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699C,
+ },
+ [0x1699D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699D,
+ },
+ [0x1699E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699E,
+ },
+ [0x1699F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699F,
+ },
+ [0x169A0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A0,
+ },
+ [0x169A1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A1,
+ },
+ [0x169A2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A2,
+ },
+ [0x169A3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGEUREUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A3,
+ },
+ [0x169A4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A4,
+ },
+ [0x169A5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MGBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A5,
+ },
+ [0x169A6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A6,
+ },
+ [0x169A7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NZAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A7,
+ },
+ [0x169A8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NKOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A8,
+ },
+ [0x169A9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GBET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A9,
+ },
+ [0x169AA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AA,
+ },
+ [0x169AB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AB,
+ },
+ [0x169AC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AC,
+ },
+ [0x169AD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NYI CLEAVER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AD,
+ },
+ [0x169AE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AE,
+ },
+ [0x169AF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MFEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AF,
+ },
+ [0x169B0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDIAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B0,
+ },
+ [0x169B1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PIEEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B1,
+ },
+ [0x169B2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B2,
+ },
+ [0x169B3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B3,
+ },
+ [0x169B4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B4,
+ },
+ [0x169B5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GBEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B5,
+ },
+ [0x169B6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B6,
+ },
+ [0x169B7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B7,
+ },
+ [0x169B8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B8,
+ },
+ [0x169B9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKAAMI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B9,
+ },
+ [0x169BA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BA,
+ },
+ [0x169BB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BB,
+ },
+ [0x169BC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NTUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BC,
+ },
+ [0x169BD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BD,
+ },
+ [0x169BE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BE,
+ },
+ [0x169BF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BF,
+ },
+ [0x169C0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NYI BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C0,
+ },
+ [0x169C1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NZUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C1,
+ },
+ [0x169C2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E POON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C2,
+ },
+ [0x169C3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C3,
+ },
+ [0x169C4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C4,
+ },
+ [0x169C5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C5,
+ },
+ [0x169C6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C6,
+ },
+ [0x169C7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C7,
+ },
+ [0x169C8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C8,
+ },
+ [0x169C9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MVI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C9,
+ },
+ [0x169CA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CA,
+ },
+ [0x169CB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CB,
+ },
+ [0x169CC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CC,
+ },
+ [0x169CD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PIET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CD,
+ },
+ [0x169CE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NTAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CE,
+ },
+ [0x169CF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CF,
+ },
+ [0x169D0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D0,
+ },
+ [0x169D1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PA PEOPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D1,
+ },
+ [0x169D2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU CALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D2,
+ },
+ [0x169D3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D3,
+ },
+ [0x169D4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D4,
+ },
+ [0x169D5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D5,
+ },
+ [0x169D6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D6,
+ },
+ [0x169D7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D7,
+ },
+ [0x169D8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D8,
+ },
+ [0x169D9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D9,
+ },
+ [0x169DA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PA PLURAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DA,
+ },
+ [0x169DB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DB,
+ },
+ [0x169DC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DC,
+ },
+ [0x169DD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAA MY HOUSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DD,
+ },
+ [0x169DE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DE,
+ },
+ [0x169DF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DF,
+ },
+ [0x169E0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E0,
+ },
+ [0x169E1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E1,
+ },
+ [0x169E2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YOQ SWIMMING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E2,
+ },
+ [0x169E3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YOQ COVER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E3,
+ },
+ [0x169E4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E4,
+ },
+ [0x169E5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E5,
+ },
+ [0x169E6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E6,
+ },
+ [0x169E7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E7,
+ },
+ [0x169E8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEE EPOCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E8,
+ },
+ [0x169E9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E9,
+ },
+ [0x169EA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EA,
+ },
+ [0x169EB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EB,
+ },
+ [0x169EC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EC,
+ },
+ [0x169ED]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169ED,
+ },
+ [0x169EE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EE,
+ },
+ [0x169EF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EF,
+ },
+ [0x169F0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F0,
+ },
+ [0x169F1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F1,
+ },
+ [0x169F2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F2,
+ },
+ [0x169F3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F3,
+ },
+ [0x169F4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F4,
+ },
+ [0x169F5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU REMEDY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F5,
+ },
+ [0x169F6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F6,
+ },
+ [0x169F7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F7,
+ },
+ [0x169F8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F8,
+ },
+ [0x169F9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F9,
+ },
+ [0x169FA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FA,
+ },
+ [0x169FB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FB,
+ },
+ [0x169FC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FC,
+ },
+ [0x169FD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FD,
+ },
+ [0x169FE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FE,
+ },
+ [0x169FF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FF,
+ },
+ [0x16A00]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A00,
+ },
+ [0x16A01]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A01,
+ },
+ [0x16A02]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A02,
+ },
+ [0x16A03]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A03,
+ },
+ [0x16A04]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A04,
+ },
+ [0x16A05]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A05,
+ },
+ [0x16A06]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A06,
+ },
+ [0x16A07]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A07,
+ },
+ [0x16A08]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A08,
+ },
+ [0x16A09]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A09,
+ },
+ [0x16A0A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0A,
+ },
+ [0x16A0B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0B,
+ },
+ [0x16A0C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0C,
+ },
+ [0x16A0D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0D,
+ },
+ [0x16A0E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0E,
+ },
+ [0x16A0F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0F,
+ },
+ [0x16A10]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A10,
+ },
+ [0x16A11]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A11,
+ },
+ [0x16A12]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A12,
+ },
+ [0x16A13]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A13,
+ },
+ [0x16A14]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A14,
+ },
+ [0x16A15]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A15,
+ },
+ [0x16A16]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A16,
+ },
+ [0x16A17]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A17,
+ },
+ [0x16A18]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A18,
+ },
+ [0x16A19]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A19,
+ },
+ [0x16A1A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NJUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1A,
+ },
+ [0x16A1B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F YOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1B,
+ },
+ [0x16A1C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1C,
+ },
+ [0x16A1D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1D,
+ },
+ [0x16A1E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1E,
+ },
+ [0x16A1F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1F,
+ },
+ [0x16A20]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A20,
+ },
+ [0x16A21]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A21,
+ },
+ [0x16A22]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A22,
+ },
+ [0x16A23]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A23,
+ },
+ [0x16A24]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A24,
+ },
+ [0x16A25]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A25,
+ },
+ [0x16A26]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A26,
+ },
+ [0x16A27]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NGKWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A27,
+ },
+ [0x16A28]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A28,
+ },
+ [0x16A29]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A29,
+ },
+ [0x16A2A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2A,
+ },
+ [0x16A2B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2B,
+ },
+ [0x16A2C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2C,
+ },
+ [0x16A2D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2D,
+ },
+ [0x16A2E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2E,
+ },
+ [0x16A2F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2F,
+ },
+ [0x16A30]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A30,
+ },
+ [0x16A31]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A31,
+ },
+ [0x16A32]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A32,
+ },
+ [0x16A33]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A33,
+ },
+ [0x16A34]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A34,
+ },
+ [0x16A35]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A35,
+ },
+ [0x16A36]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A36,
+ },
+ [0x16A37]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SAMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A37,
+ },
+ [0x16A38]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F VUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A38,
+ },
+ [0x16A40]={
+ category="lo",
+ description="MRO LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A40,
+ },
+ [0x16A41]={
+ category="lo",
+ description="MRO LETTER NGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A41,
+ },
+ [0x16A42]={
+ category="lo",
+ description="MRO LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A42,
+ },
+ [0x16A43]={
+ category="lo",
+ description="MRO LETTER MIM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A43,
+ },
+ [0x16A44]={
+ category="lo",
+ description="MRO LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A44,
+ },
+ [0x16A45]={
+ category="lo",
+ description="MRO LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A45,
+ },
+ [0x16A46]={
+ category="lo",
+ description="MRO LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A46,
+ },
+ [0x16A47]={
+ category="lo",
+ description="MRO LETTER PHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A47,
+ },
+ [0x16A48]={
+ category="lo",
+ description="MRO LETTER KHAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A48,
+ },
+ [0x16A49]={
+ category="lo",
+ description="MRO LETTER HAO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A49,
+ },
+ [0x16A4A]={
+ category="lo",
+ description="MRO LETTER DAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4A,
+ },
+ [0x16A4B]={
+ category="lo",
+ description="MRO LETTER CHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4B,
+ },
+ [0x16A4C]={
+ category="lo",
+ description="MRO LETTER KEAAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4C,
+ },
+ [0x16A4D]={
+ category="lo",
+ description="MRO LETTER OL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4D,
+ },
+ [0x16A4E]={
+ category="lo",
+ description="MRO LETTER MAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4E,
+ },
+ [0x16A4F]={
+ category="lo",
+ description="MRO LETTER NIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A4F,
+ },
+ [0x16A50]={
+ category="lo",
+ description="MRO LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A50,
+ },
+ [0x16A51]={
+ category="lo",
+ description="MRO LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A51,
+ },
+ [0x16A52]={
+ category="lo",
+ description="MRO LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A52,
+ },
+ [0x16A53]={
+ category="lo",
+ description="MRO LETTER RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A53,
+ },
+ [0x16A54]={
+ category="lo",
+ description="MRO LETTER SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A54,
+ },
+ [0x16A55]={
+ category="lo",
+ description="MRO LETTER THEA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A55,
+ },
+ [0x16A56]={
+ category="lo",
+ description="MRO LETTER EA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A56,
+ },
+ [0x16A57]={
+ category="lo",
+ description="MRO LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A57,
+ },
+ [0x16A58]={
+ category="lo",
+ description="MRO LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A58,
+ },
+ [0x16A59]={
+ category="lo",
+ description="MRO LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A59,
+ },
+ [0x16A5A]={
+ category="lo",
+ description="MRO LETTER LAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5A,
+ },
+ [0x16A5B]={
+ category="lo",
+ description="MRO LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5B,
+ },
+ [0x16A5C]={
+ category="lo",
+ description="MRO LETTER HAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5C,
+ },
+ [0x16A5D]={
+ category="lo",
+ description="MRO LETTER RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5D,
+ },
+ [0x16A5E]={
+ category="lo",
+ description="MRO LETTER TEK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A5E,
+ },
+ [0x16A60]={
+ category="nd",
+ description="MRO DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A60,
+ },
+ [0x16A61]={
+ category="nd",
+ description="MRO DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A61,
+ },
+ [0x16A62]={
+ category="nd",
+ description="MRO DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A62,
+ },
+ [0x16A63]={
+ category="nd",
+ description="MRO DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A63,
+ },
+ [0x16A64]={
+ category="nd",
+ description="MRO DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A64,
+ },
+ [0x16A65]={
+ category="nd",
+ description="MRO DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A65,
+ },
+ [0x16A66]={
+ category="nd",
+ description="MRO DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A66,
+ },
+ [0x16A67]={
+ category="nd",
+ description="MRO DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A67,
+ },
+ [0x16A68]={
+ category="nd",
+ description="MRO DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A68,
+ },
+ [0x16A69]={
+ category="nd",
+ description="MRO DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16A69,
+ },
+ [0x16A6E]={
+ category="po",
+ description="MRO DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16A6E,
+ },
+ [0x16A6F]={
+ category="po",
+ description="MRO DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16A6F,
+ },
+ [0x16AD0]={
+ category="lo",
+ description="BASSA VAH LETTER ENNI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD0,
+ },
+ [0x16AD1]={
+ category="lo",
+ description="BASSA VAH LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD1,
+ },
+ [0x16AD2]={
+ category="lo",
+ description="BASSA VAH LETTER SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD2,
+ },
+ [0x16AD3]={
+ category="lo",
+ description="BASSA VAH LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD3,
+ },
+ [0x16AD4]={
+ category="lo",
+ description="BASSA VAH LETTER MBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD4,
+ },
+ [0x16AD5]={
+ category="lo",
+ description="BASSA VAH LETTER YIE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD5,
+ },
+ [0x16AD6]={
+ category="lo",
+ description="BASSA VAH LETTER GAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD6,
+ },
+ [0x16AD7]={
+ category="lo",
+ description="BASSA VAH LETTER DHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD7,
+ },
+ [0x16AD8]={
+ category="lo",
+ description="BASSA VAH LETTER KPAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD8,
+ },
+ [0x16AD9]={
+ category="lo",
+ description="BASSA VAH LETTER JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AD9,
+ },
+ [0x16ADA]={
+ category="lo",
+ description="BASSA VAH LETTER HWAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADA,
+ },
+ [0x16ADB]={
+ category="lo",
+ description="BASSA VAH LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADB,
+ },
+ [0x16ADC]={
+ category="lo",
+ description="BASSA VAH LETTER ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADC,
+ },
+ [0x16ADD]={
+ category="lo",
+ description="BASSA VAH LETTER GBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADD,
+ },
+ [0x16ADE]={
+ category="lo",
+ description="BASSA VAH LETTER DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADE,
+ },
+ [0x16ADF]={
+ category="lo",
+ description="BASSA VAH LETTER CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16ADF,
+ },
+ [0x16AE0]={
+ category="lo",
+ description="BASSA VAH LETTER UWU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE0,
+ },
+ [0x16AE1]={
+ category="lo",
+ description="BASSA VAH LETTER TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE1,
+ },
+ [0x16AE2]={
+ category="lo",
+ description="BASSA VAH LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE2,
+ },
+ [0x16AE3]={
+ category="lo",
+ description="BASSA VAH LETTER VU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE3,
+ },
+ [0x16AE4]={
+ category="lo",
+ description="BASSA VAH LETTER YEIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE4,
+ },
+ [0x16AE5]={
+ category="lo",
+ description="BASSA VAH LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE5,
+ },
+ [0x16AE6]={
+ category="lo",
+ description="BASSA VAH LETTER WADDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE6,
+ },
+ [0x16AE7]={
+ category="lo",
+ description="BASSA VAH LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE7,
+ },
+ [0x16AE8]={
+ category="lo",
+ description="BASSA VAH LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE8,
+ },
+ [0x16AE9]={
+ category="lo",
+ description="BASSA VAH LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AE9,
+ },
+ [0x16AEA]={
+ category="lo",
+ description="BASSA VAH LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AEA,
+ },
+ [0x16AEB]={
+ category="lo",
+ description="BASSA VAH LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AEB,
+ },
+ [0x16AEC]={
+ category="lo",
+ description="BASSA VAH LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AEC,
+ },
+ [0x16AED]={
+ category="lo",
+ description="BASSA VAH LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16AED,
+ },
+ [0x16AF0]={
+ category="mn",
+ combining=0x1,
+ description="BASSA VAH COMBINING HIGH TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16AF0,
+ },
+ [0x16AF1]={
+ category="mn",
+ combining=0x1,
+ description="BASSA VAH COMBINING LOW TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16AF1,
+ },
+ [0x16AF2]={
+ category="mn",
+ combining=0x1,
+ description="BASSA VAH COMBINING MID TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16AF2,
+ },
+ [0x16AF3]={
+ category="mn",
+ combining=0x1,
+ description="BASSA VAH COMBINING LOW-MID TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16AF3,
+ },
+ [0x16AF4]={
+ category="mn",
+ combining=0x1,
+ description="BASSA VAH COMBINING HIGH-LOW TONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16AF4,
+ },
+ [0x16AF5]={
+ category="po",
+ description="BASSA VAH FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16AF5,
+ },
+ [0x16B00]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KEEB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B00,
+ },
+ [0x16B01]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KEEV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B01,
+ },
+ [0x16B02]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B02,
+ },
+ [0x16B03]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KIV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B03,
+ },
+ [0x16B04]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B04,
+ },
+ [0x16B05]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAUV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B05,
+ },
+ [0x16B06]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B06,
+ },
+ [0x16B07]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KUV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B07,
+ },
+ [0x16B08]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KEB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B08,
+ },
+ [0x16B09]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KEV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B09,
+ },
+ [0x16B0A]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0A,
+ },
+ [0x16B0B]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAIV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0B,
+ },
+ [0x16B0C]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KOOB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0C,
+ },
+ [0x16B0D]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KOOV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0D,
+ },
+ [0x16B0E]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAWB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0E,
+ },
+ [0x16B0F]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAWV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B0F,
+ },
+ [0x16B10]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KUAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B10,
+ },
+ [0x16B11]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KUAV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B11,
+ },
+ [0x16B12]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KOB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B12,
+ },
+ [0x16B13]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KOV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B13,
+ },
+ [0x16B14]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KIAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B14,
+ },
+ [0x16B15]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KIAV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B15,
+ },
+ [0x16B16]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B16,
+ },
+ [0x16B17]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B17,
+ },
+ [0x16B18]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KWB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B18,
+ },
+ [0x16B19]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KWV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B19,
+ },
+ [0x16B1A]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1A,
+ },
+ [0x16B1B]={
+ category="lo",
+ description="PAHAWH HMONG VOWEL KAAV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1B,
+ },
+ [0x16B1C]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT VAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1C,
+ },
+ [0x16B1D]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NTSAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1D,
+ },
+ [0x16B1E]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT LAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1E,
+ },
+ [0x16B1F]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT HAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B1F,
+ },
+ [0x16B20]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NLAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B20,
+ },
+ [0x16B21]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT RAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B21,
+ },
+ [0x16B22]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NKAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B22,
+ },
+ [0x16B23]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT QHAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B23,
+ },
+ [0x16B24]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT YAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B24,
+ },
+ [0x16B25]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT HLAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B25,
+ },
+ [0x16B26]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT MAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B26,
+ },
+ [0x16B27]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT CHAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B27,
+ },
+ [0x16B28]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NCHAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B28,
+ },
+ [0x16B29]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT HNAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B29,
+ },
+ [0x16B2A]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT PLHAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2A,
+ },
+ [0x16B2B]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NTHAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2B,
+ },
+ [0x16B2C]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT NAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2C,
+ },
+ [0x16B2D]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2D,
+ },
+ [0x16B2E]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT XAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2E,
+ },
+ [0x16B2F]={
+ category="lo",
+ description="PAHAWH HMONG CONSONANT CAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B2F,
+ },
+ [0x16B30]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM TUB",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B30,
+ },
+ [0x16B31]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM SO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B31,
+ },
+ [0x16B32]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM KES",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B32,
+ },
+ [0x16B33]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM KHAV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B33,
+ },
+ [0x16B34]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM SUAM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B34,
+ },
+ [0x16B35]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM HOM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B35,
+ },
+ [0x16B36]={
+ category="mn",
+ combining=0xE6,
+ description="PAHAWH HMONG MARK CIM TAUM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16B36,
+ },
+ [0x16B37]={
+ category="po",
+ description="PAHAWH HMONG SIGN VOS THOM",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16B37,
+ },
+ [0x16B38]={
+ category="po",
+ description="PAHAWH HMONG SIGN VOS TSHAB CEEB",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16B38,
+ },
+ [0x16B39]={
+ category="po",
+ description="PAHAWH HMONG SIGN CIM CHEEM",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16B39,
+ },
+ [0x16B3A]={
+ category="po",
+ description="PAHAWH HMONG SIGN VOS THIAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3A,
+ },
+ [0x16B3B]={
+ category="po",
+ description="PAHAWH HMONG SIGN VOS FEEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3B,
+ },
+ [0x16B3C]={
+ category="so",
+ description="PAHAWH HMONG SIGN XYEEM NTXIV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3C,
+ },
+ [0x16B3D]={
+ category="so",
+ description="PAHAWH HMONG SIGN XYEEM RHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3D,
+ },
+ [0x16B3E]={
+ category="so",
+ description="PAHAWH HMONG SIGN XYEEM TOV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3E,
+ },
+ [0x16B3F]={
+ category="so",
+ description="PAHAWH HMONG SIGN XYEEM FAIB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B3F,
+ },
+ [0x16B40]={
+ category="lm",
+ description="PAHAWH HMONG SIGN VOS SEEV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B40,
+ },
+ [0x16B41]={
+ category="lm",
+ description="PAHAWH HMONG SIGN MEEJ SUAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B41,
+ },
+ [0x16B42]={
+ category="lm",
+ description="PAHAWH HMONG SIGN VOS NRUA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B42,
+ },
+ [0x16B43]={
+ category="lm",
+ description="PAHAWH HMONG SIGN IB YAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B43,
+ },
+ [0x16B44]={
+ category="po",
+ description="PAHAWH HMONG SIGN XAUS",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16B44,
+ },
+ [0x16B45]={
+ category="so",
+ description="PAHAWH HMONG SIGN CIM TSOV ROG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B45,
+ },
+ [0x16B50]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B50,
+ },
+ [0x16B51]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B51,
+ },
+ [0x16B52]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B52,
+ },
+ [0x16B53]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B53,
+ },
+ [0x16B54]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B54,
+ },
+ [0x16B55]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B55,
+ },
+ [0x16B56]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B56,
+ },
+ [0x16B57]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B57,
+ },
+ [0x16B58]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B58,
+ },
+ [0x16B59]={
+ category="nd",
+ description="PAHAWH HMONG DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x16B59,
+ },
+ [0x16B5B]={
+ category="no",
+ description="PAHAWH HMONG NUMBER TENS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5B,
+ },
+ [0x16B5C]={
+ category="no",
+ description="PAHAWH HMONG NUMBER HUNDREDS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5C,
+ },
+ [0x16B5D]={
+ category="no",
+ description="PAHAWH HMONG NUMBER TEN THOUSANDS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5D,
+ },
+ [0x16B5E]={
+ category="no",
+ description="PAHAWH HMONG NUMBER MILLIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5E,
+ },
+ [0x16B5F]={
+ category="no",
+ description="PAHAWH HMONG NUMBER HUNDRED MILLIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B5F,
+ },
+ [0x16B60]={
+ category="no",
+ description="PAHAWH HMONG NUMBER TEN BILLIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B60,
+ },
+ [0x16B61]={
+ category="no",
+ description="PAHAWH HMONG NUMBER TRILLIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B61,
+ },
+ [0x16B63]={
+ category="lo",
+ description="PAHAWH HMONG SIGN VOS LUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B63,
+ },
+ [0x16B64]={
+ category="lo",
+ description="PAHAWH HMONG SIGN XYOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B64,
+ },
+ [0x16B65]={
+ category="lo",
+ description="PAHAWH HMONG SIGN HLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B65,
+ },
+ [0x16B66]={
+ category="lo",
+ description="PAHAWH HMONG SIGN THIRD-STAGE HLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B66,
+ },
+ [0x16B67]={
+ category="lo",
+ description="PAHAWH HMONG SIGN ZWJ THAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B67,
+ },
+ [0x16B68]={
+ category="lo",
+ description="PAHAWH HMONG SIGN HNUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B68,
+ },
+ [0x16B69]={
+ category="lo",
+ description="PAHAWH HMONG SIGN NQIG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B69,
+ },
+ [0x16B6A]={
+ category="lo",
+ description="PAHAWH HMONG SIGN XIAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6A,
+ },
+ [0x16B6B]={
+ category="lo",
+ description="PAHAWH HMONG SIGN NTUJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6B,
+ },
+ [0x16B6C]={
+ category="lo",
+ description="PAHAWH HMONG SIGN AV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6C,
+ },
+ [0x16B6D]={
+ category="lo",
+ description="PAHAWH HMONG SIGN TXHEEJ CEEV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6D,
+ },
+ [0x16B6E]={
+ category="lo",
+ description="PAHAWH HMONG SIGN MEEJ TSEEB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6E,
+ },
+ [0x16B6F]={
+ category="lo",
+ description="PAHAWH HMONG SIGN TAU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B6F,
+ },
+ [0x16B70]={
+ category="lo",
+ description="PAHAWH HMONG SIGN LOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B70,
+ },
+ [0x16B71]={
+ category="lo",
+ description="PAHAWH HMONG SIGN MUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B71,
+ },
+ [0x16B72]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM HAIS LUS NTOG NTOG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B72,
+ },
+ [0x16B73]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM CUAM TSHOOJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B73,
+ },
+ [0x16B74]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM TXWV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B74,
+ },
+ [0x16B75]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM TXWV CHWV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B75,
+ },
+ [0x16B76]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM PUB DAWB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B76,
+ },
+ [0x16B77]={
+ category="lo",
+ description="PAHAWH HMONG SIGN CIM NRES TOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B77,
+ },
+ [0x16B7D]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN TSHEEJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B7D,
+ },
+ [0x16B7E]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN YEEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B7E,
+ },
+ [0x16B7F]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN LIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B7F,
+ },
+ [0x16B80]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN LAUJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B80,
+ },
+ [0x16B81]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN XYOOJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B81,
+ },
+ [0x16B82]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN KOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B82,
+ },
+ [0x16B83]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN HAWJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B83,
+ },
+ [0x16B84]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN MUAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B84,
+ },
+ [0x16B85]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN THOJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B85,
+ },
+ [0x16B86]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN TSAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B86,
+ },
+ [0x16B87]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN PHAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B87,
+ },
+ [0x16B88]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN KHAB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B88,
+ },
+ [0x16B89]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN HAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B89,
+ },
+ [0x16B8A]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN VAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8A,
+ },
+ [0x16B8B]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN FAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8B,
+ },
+ [0x16B8C]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN YAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8C,
+ },
+ [0x16B8D]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN TSWB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8D,
+ },
+ [0x16B8E]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN KWM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8E,
+ },
+ [0x16B8F]={
+ category="lo",
+ description="PAHAWH HMONG CLAN SIGN VWJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16B8F,
+ },
+ [0x16F00]={
+ category="lo",
+ description="MIAO LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F00,
+ },
+ [0x16F01]={
+ category="lo",
+ description="MIAO LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F01,
+ },
+ [0x16F02]={
+ category="lo",
+ description="MIAO LETTER YI PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F02,
+ },
+ [0x16F03]={
+ category="lo",
+ description="MIAO LETTER PLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F03,
+ },
+ [0x16F04]={
+ category="lo",
+ description="MIAO LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F04,
+ },
+ [0x16F05]={
+ category="lo",
+ description="MIAO LETTER MHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F05,
+ },
+ [0x16F06]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F06,
+ },
+ [0x16F07]={
+ category="lo",
+ description="MIAO LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F07,
+ },
+ [0x16F08]={
+ category="lo",
+ description="MIAO LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F08,
+ },
+ [0x16F09]={
+ category="lo",
+ description="MIAO LETTER VFA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F09,
+ },
+ [0x16F0A]={
+ category="lo",
+ description="MIAO LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0A,
+ },
+ [0x16F0B]={
+ category="lo",
+ description="MIAO LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0B,
+ },
+ [0x16F0C]={
+ category="lo",
+ description="MIAO LETTER YI TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0C,
+ },
+ [0x16F0D]={
+ category="lo",
+ description="MIAO LETTER YI TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0D,
+ },
+ [0x16F0E]={
+ category="lo",
+ description="MIAO LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0E,
+ },
+ [0x16F0F]={
+ category="lo",
+ description="MIAO LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0F,
+ },
+ [0x16F10]={
+ category="lo",
+ description="MIAO LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F10,
+ },
+ [0x16F11]={
+ category="lo",
+ description="MIAO LETTER NHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F11,
+ },
+ [0x16F12]={
+ category="lo",
+ description="MIAO LETTER YI NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F12,
+ },
+ [0x16F13]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F13,
+ },
+ [0x16F14]={
+ category="lo",
+ description="MIAO LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F14,
+ },
+ [0x16F15]={
+ category="lo",
+ description="MIAO LETTER NNHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F15,
+ },
+ [0x16F16]={
+ category="lo",
+ description="MIAO LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F16,
+ },
+ [0x16F17]={
+ category="lo",
+ description="MIAO LETTER LYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F17,
+ },
+ [0x16F18]={
+ category="lo",
+ description="MIAO LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F18,
+ },
+ [0x16F19]={
+ category="lo",
+ description="MIAO LETTER LHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F19,
+ },
+ [0x16F1A]={
+ category="lo",
+ description="MIAO LETTER TLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1A,
+ },
+ [0x16F1B]={
+ category="lo",
+ description="MIAO LETTER DLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1B,
+ },
+ [0x16F1C]={
+ category="lo",
+ description="MIAO LETTER TLHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1C,
+ },
+ [0x16F1D]={
+ category="lo",
+ description="MIAO LETTER DLHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1D,
+ },
+ [0x16F1E]={
+ category="lo",
+ description="MIAO LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1E,
+ },
+ [0x16F1F]={
+ category="lo",
+ description="MIAO LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1F,
+ },
+ [0x16F20]={
+ category="lo",
+ description="MIAO LETTER YI KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F20,
+ },
+ [0x16F21]={
+ category="lo",
+ description="MIAO LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F21,
+ },
+ [0x16F22]={
+ category="lo",
+ description="MIAO LETTER QGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F22,
+ },
+ [0x16F23]={
+ category="lo",
+ description="MIAO LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F23,
+ },
+ [0x16F24]={
+ category="lo",
+ description="MIAO LETTER NGHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F24,
+ },
+ [0x16F25]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F25,
+ },
+ [0x16F26]={
+ category="lo",
+ description="MIAO LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F26,
+ },
+ [0x16F27]={
+ category="lo",
+ description="MIAO LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F27,
+ },
+ [0x16F28]={
+ category="lo",
+ description="MIAO LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F28,
+ },
+ [0x16F29]={
+ category="lo",
+ description="MIAO LETTER GHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F29,
+ },
+ [0x16F2A]={
+ category="lo",
+ description="MIAO LETTER TSSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2A,
+ },
+ [0x16F2B]={
+ category="lo",
+ description="MIAO LETTER DZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2B,
+ },
+ [0x16F2C]={
+ category="lo",
+ description="MIAO LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2C,
+ },
+ [0x16F2D]={
+ category="lo",
+ description="MIAO LETTER NYHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2D,
+ },
+ [0x16F2E]={
+ category="lo",
+ description="MIAO LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2E,
+ },
+ [0x16F2F]={
+ category="lo",
+ description="MIAO LETTER DZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2F,
+ },
+ [0x16F30]={
+ category="lo",
+ description="MIAO LETTER YI TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F30,
+ },
+ [0x16F31]={
+ category="lo",
+ description="MIAO LETTER YI DZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F31,
+ },
+ [0x16F32]={
+ category="lo",
+ description="MIAO LETTER REFORMED TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F32,
+ },
+ [0x16F33]={
+ category="lo",
+ description="MIAO LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F33,
+ },
+ [0x16F34]={
+ category="lo",
+ description="MIAO LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F34,
+ },
+ [0x16F35]={
+ category="lo",
+ description="MIAO LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F35,
+ },
+ [0x16F36]={
+ category="lo",
+ description="MIAO LETTER ZSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F36,
+ },
+ [0x16F37]={
+ category="lo",
+ description="MIAO LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F37,
+ },
+ [0x16F38]={
+ category="lo",
+ description="MIAO LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F38,
+ },
+ [0x16F39]={
+ category="lo",
+ description="MIAO LETTER YI TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F39,
+ },
+ [0x16F3A]={
+ category="lo",
+ description="MIAO LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3A,
+ },
+ [0x16F3B]={
+ category="lo",
+ description="MIAO LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3B,
+ },
+ [0x16F3C]={
+ category="lo",
+ description="MIAO LETTER ZSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3C,
+ },
+ [0x16F3D]={
+ category="lo",
+ description="MIAO LETTER ZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3D,
+ },
+ [0x16F3E]={
+ category="lo",
+ description="MIAO LETTER ZZSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3E,
+ },
+ [0x16F3F]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC ZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3F,
+ },
+ [0x16F40]={
+ category="lo",
+ description="MIAO LETTER ZZYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F40,
+ },
+ [0x16F41]={
+ category="lo",
+ description="MIAO LETTER ZZSYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F41,
+ },
+ [0x16F42]={
+ category="lo",
+ description="MIAO LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F42,
+ },
+ [0x16F43]={
+ category="lo",
+ description="MIAO LETTER AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F43,
+ },
+ [0x16F44]={
+ category="lo",
+ description="MIAO LETTER HHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F44,
+ },
+ [0x16F50]={
+ category="lo",
+ description="MIAO LETTER NASALIZATION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F50,
+ },
+ [0x16F51]={
+ category="mc",
+ description="MIAO SIGN ASPIRATION",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F51,
+ },
+ [0x16F52]={
+ category="mc",
+ description="MIAO SIGN REFORMED VOICING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F52,
+ },
+ [0x16F53]={
+ category="mc",
+ description="MIAO SIGN REFORMED ASPIRATION",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F53,
+ },
+ [0x16F54]={
+ category="mc",
+ description="MIAO VOWEL SIGN A",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F54,
+ },
+ [0x16F55]={
+ category="mc",
+ description="MIAO VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F55,
+ },
+ [0x16F56]={
+ category="mc",
+ description="MIAO VOWEL SIGN AHH",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F56,
+ },
+ [0x16F57]={
+ category="mc",
+ description="MIAO VOWEL SIGN AN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F57,
+ },
+ [0x16F58]={
+ category="mc",
+ description="MIAO VOWEL SIGN ANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F58,
+ },
+ [0x16F59]={
+ category="mc",
+ description="MIAO VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F59,
+ },
+ [0x16F5A]={
+ category="mc",
+ description="MIAO VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5A,
+ },
+ [0x16F5B]={
+ category="mc",
+ description="MIAO VOWEL SIGN WO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5B,
+ },
+ [0x16F5C]={
+ category="mc",
+ description="MIAO VOWEL SIGN W",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5C,
+ },
+ [0x16F5D]={
+ category="mc",
+ description="MIAO VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5D,
+ },
+ [0x16F5E]={
+ category="mc",
+ description="MIAO VOWEL SIGN EN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5E,
+ },
+ [0x16F5F]={
+ category="mc",
+ description="MIAO VOWEL SIGN ENG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5F,
+ },
+ [0x16F60]={
+ category="mc",
+ description="MIAO VOWEL SIGN OEY",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F60,
+ },
+ [0x16F61]={
+ category="mc",
+ description="MIAO VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F61,
+ },
+ [0x16F62]={
+ category="mc",
+ description="MIAO VOWEL SIGN IA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F62,
+ },
+ [0x16F63]={
+ category="mc",
+ description="MIAO VOWEL SIGN IAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F63,
+ },
+ [0x16F64]={
+ category="mc",
+ description="MIAO VOWEL SIGN IANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F64,
+ },
+ [0x16F65]={
+ category="mc",
+ description="MIAO VOWEL SIGN IO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F65,
+ },
+ [0x16F66]={
+ category="mc",
+ description="MIAO VOWEL SIGN IE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F66,
+ },
+ [0x16F67]={
+ category="mc",
+ description="MIAO VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F67,
+ },
+ [0x16F68]={
+ category="mc",
+ description="MIAO VOWEL SIGN IU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F68,
+ },
+ [0x16F69]={
+ category="mc",
+ description="MIAO VOWEL SIGN ING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F69,
+ },
+ [0x16F6A]={
+ category="mc",
+ description="MIAO VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6A,
+ },
+ [0x16F6B]={
+ category="mc",
+ description="MIAO VOWEL SIGN UA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6B,
+ },
+ [0x16F6C]={
+ category="mc",
+ description="MIAO VOWEL SIGN UAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6C,
+ },
+ [0x16F6D]={
+ category="mc",
+ description="MIAO VOWEL SIGN UANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6D,
+ },
+ [0x16F6E]={
+ category="mc",
+ description="MIAO VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6E,
+ },
+ [0x16F6F]={
+ category="mc",
+ description="MIAO VOWEL SIGN UEI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6F,
+ },
+ [0x16F70]={
+ category="mc",
+ description="MIAO VOWEL SIGN UNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F70,
+ },
+ [0x16F71]={
+ category="mc",
+ description="MIAO VOWEL SIGN Y",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F71,
+ },
+ [0x16F72]={
+ category="mc",
+ description="MIAO VOWEL SIGN YI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F72,
+ },
+ [0x16F73]={
+ category="mc",
+ description="MIAO VOWEL SIGN AE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F73,
+ },
+ [0x16F74]={
+ category="mc",
+ description="MIAO VOWEL SIGN AEE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F74,
+ },
+ [0x16F75]={
+ category="mc",
+ description="MIAO VOWEL SIGN ERR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F75,
+ },
+ [0x16F76]={
+ category="mc",
+ description="MIAO VOWEL SIGN ROUNDED ERR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F76,
+ },
+ [0x16F77]={
+ category="mc",
+ description="MIAO VOWEL SIGN ER",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F77,
+ },
+ [0x16F78]={
+ category="mc",
+ description="MIAO VOWEL SIGN ROUNDED ER",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F78,
+ },
+ [0x16F79]={
+ category="mc",
+ description="MIAO VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F79,
+ },
+ [0x16F7A]={
+ category="mc",
+ description="MIAO VOWEL SIGN EI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7A,
+ },
+ [0x16F7B]={
+ category="mc",
+ description="MIAO VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7B,
+ },
+ [0x16F7C]={
+ category="mc",
+ description="MIAO VOWEL SIGN OU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7C,
+ },
+ [0x16F7D]={
+ category="mc",
+ description="MIAO VOWEL SIGN N",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7D,
+ },
+ [0x16F7E]={
+ category="mc",
+ description="MIAO VOWEL SIGN NG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7E,
+ },
+ [0x16F8F]={
+ category="mn",
+ description="MIAO TONE RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F8F,
+ },
+ [0x16F90]={
+ category="mn",
+ description="MIAO TONE TOP RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F90,
+ },
+ [0x16F91]={
+ category="mn",
+ description="MIAO TONE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F91,
+ },
+ [0x16F92]={
+ category="mn",
+ description="MIAO TONE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F92,
+ },
+ [0x16F93]={
+ category="lm",
+ description="MIAO LETTER TONE-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F93,
+ },
+ [0x16F94]={
+ category="lm",
+ description="MIAO LETTER TONE-3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F94,
+ },
+ [0x16F95]={
+ category="lm",
+ description="MIAO LETTER TONE-4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F95,
+ },
+ [0x16F96]={
+ category="lm",
+ description="MIAO LETTER TONE-5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F96,
+ },
+ [0x16F97]={
+ category="lm",
+ description="MIAO LETTER TONE-6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F97,
+ },
+ [0x16F98]={
+ category="lm",
+ description="MIAO LETTER TONE-7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F98,
+ },
+ [0x16F99]={
+ category="lm",
+ description="MIAO LETTER TONE-8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F99,
+ },
+ [0x16F9A]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9A,
+ },
+ [0x16F9B]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9B,
+ },
+ [0x16F9C]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9C,
+ },
+ [0x16F9D]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9D,
+ },
+ [0x16F9E]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9E,
+ },
+ [0x16F9F]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9F,
+ },
+ [0x1B000]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ARCHAIC E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x1B000,
+ },
+ [0x1B001]={
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ARCHAIC YE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x1B001,
+ },
+ [0x1BC00]={
+ category="lo",
+ description="DUPLOYAN LETTER H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC00,
+ },
+ [0x1BC01]={
+ category="lo",
+ description="DUPLOYAN LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC01,
+ },
+ [0x1BC02]={
+ category="lo",
+ description="DUPLOYAN LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC02,
+ },
+ [0x1BC03]={
+ category="lo",
+ description="DUPLOYAN LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC03,
+ },
+ [0x1BC04]={
+ category="lo",
+ description="DUPLOYAN LETTER F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC04,
+ },
+ [0x1BC05]={
+ category="lo",
+ description="DUPLOYAN LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC05,
+ },
+ [0x1BC06]={
+ category="lo",
+ description="DUPLOYAN LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC06,
+ },
+ [0x1BC07]={
+ category="lo",
+ description="DUPLOYAN LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC07,
+ },
+ [0x1BC08]={
+ category="lo",
+ description="DUPLOYAN LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC08,
+ },
+ [0x1BC09]={
+ category="lo",
+ description="DUPLOYAN LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC09,
+ },
+ [0x1BC0A]={
+ category="lo",
+ description="DUPLOYAN LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0A,
+ },
+ [0x1BC0B]={
+ category="lo",
+ description="DUPLOYAN LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0B,
+ },
+ [0x1BC0C]={
+ category="lo",
+ description="DUPLOYAN LETTER P N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0C,
+ },
+ [0x1BC0D]={
+ category="lo",
+ description="DUPLOYAN LETTER D S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0D,
+ },
+ [0x1BC0E]={
+ category="lo",
+ description="DUPLOYAN LETTER F N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0E,
+ },
+ [0x1BC0F]={
+ category="lo",
+ description="DUPLOYAN LETTER K M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0F,
+ },
+ [0x1BC10]={
+ category="lo",
+ description="DUPLOYAN LETTER R S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC10,
+ },
+ [0x1BC11]={
+ category="lo",
+ description="DUPLOYAN LETTER TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC11,
+ },
+ [0x1BC12]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN DH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC12,
+ },
+ [0x1BC13]={
+ category="lo",
+ description="DUPLOYAN LETTER DH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC13,
+ },
+ [0x1BC14]={
+ category="lo",
+ description="DUPLOYAN LETTER KK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC14,
+ },
+ [0x1BC15]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC15,
+ },
+ [0x1BC16]={
+ category="lo",
+ description="DUPLOYAN LETTER HL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC16,
+ },
+ [0x1BC17]={
+ category="lo",
+ description="DUPLOYAN LETTER LH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC17,
+ },
+ [0x1BC18]={
+ category="lo",
+ description="DUPLOYAN LETTER RH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC18,
+ },
+ [0x1BC19]={
+ category="lo",
+ description="DUPLOYAN LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC19,
+ },
+ [0x1BC1A]={
+ category="lo",
+ description="DUPLOYAN LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1A,
+ },
+ [0x1BC1B]={
+ category="lo",
+ description="DUPLOYAN LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1B,
+ },
+ [0x1BC1C]={
+ category="lo",
+ description="DUPLOYAN LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1C,
+ },
+ [0x1BC1D]={
+ category="lo",
+ description="DUPLOYAN LETTER M N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1D,
+ },
+ [0x1BC1E]={
+ category="lo",
+ description="DUPLOYAN LETTER N M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1E,
+ },
+ [0x1BC1F]={
+ category="lo",
+ description="DUPLOYAN LETTER J M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1F,
+ },
+ [0x1BC20]={
+ category="lo",
+ description="DUPLOYAN LETTER S J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC20,
+ },
+ [0x1BC21]={
+ category="lo",
+ description="DUPLOYAN LETTER M WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC21,
+ },
+ [0x1BC22]={
+ category="lo",
+ description="DUPLOYAN LETTER N WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC22,
+ },
+ [0x1BC23]={
+ category="lo",
+ description="DUPLOYAN LETTER J WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC23,
+ },
+ [0x1BC24]={
+ category="lo",
+ description="DUPLOYAN LETTER J WITH DOTS INSIDE AND ABOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC24,
+ },
+ [0x1BC25]={
+ category="lo",
+ description="DUPLOYAN LETTER S WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC25,
+ },
+ [0x1BC26]={
+ category="lo",
+ description="DUPLOYAN LETTER S WITH DOT BELOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC26,
+ },
+ [0x1BC27]={
+ category="lo",
+ description="DUPLOYAN LETTER M S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC27,
+ },
+ [0x1BC28]={
+ category="lo",
+ description="DUPLOYAN LETTER N S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC28,
+ },
+ [0x1BC29]={
+ category="lo",
+ description="DUPLOYAN LETTER J S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC29,
+ },
+ [0x1BC2A]={
+ category="lo",
+ description="DUPLOYAN LETTER S S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2A,
+ },
+ [0x1BC2B]={
+ category="lo",
+ description="DUPLOYAN LETTER M N S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2B,
+ },
+ [0x1BC2C]={
+ category="lo",
+ description="DUPLOYAN LETTER N M S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2C,
+ },
+ [0x1BC2D]={
+ category="lo",
+ description="DUPLOYAN LETTER J M S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2D,
+ },
+ [0x1BC2E]={
+ category="lo",
+ description="DUPLOYAN LETTER S J S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2E,
+ },
+ [0x1BC2F]={
+ category="lo",
+ description="DUPLOYAN LETTER J S WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2F,
+ },
+ [0x1BC30]={
+ category="lo",
+ description="DUPLOYAN LETTER J N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC30,
+ },
+ [0x1BC31]={
+ category="lo",
+ description="DUPLOYAN LETTER J N S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC31,
+ },
+ [0x1BC32]={
+ category="lo",
+ description="DUPLOYAN LETTER S T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC32,
+ },
+ [0x1BC33]={
+ category="lo",
+ description="DUPLOYAN LETTER S T R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC33,
+ },
+ [0x1BC34]={
+ category="lo",
+ description="DUPLOYAN LETTER S P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC34,
+ },
+ [0x1BC35]={
+ category="lo",
+ description="DUPLOYAN LETTER S P R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC35,
+ },
+ [0x1BC36]={
+ category="lo",
+ description="DUPLOYAN LETTER T S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC36,
+ },
+ [0x1BC37]={
+ category="lo",
+ description="DUPLOYAN LETTER T R S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC37,
+ },
+ [0x1BC38]={
+ category="lo",
+ description="DUPLOYAN LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC38,
+ },
+ [0x1BC39]={
+ category="lo",
+ description="DUPLOYAN LETTER WH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC39,
+ },
+ [0x1BC3A]={
+ category="lo",
+ description="DUPLOYAN LETTER W R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3A,
+ },
+ [0x1BC3B]={
+ category="lo",
+ description="DUPLOYAN LETTER S N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3B,
+ },
+ [0x1BC3C]={
+ category="lo",
+ description="DUPLOYAN LETTER S M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3C,
+ },
+ [0x1BC3D]={
+ category="lo",
+ description="DUPLOYAN LETTER K R S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3D,
+ },
+ [0x1BC3E]={
+ category="lo",
+ description="DUPLOYAN LETTER G R S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3E,
+ },
+ [0x1BC3F]={
+ category="lo",
+ description="DUPLOYAN LETTER S K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3F,
+ },
+ [0x1BC40]={
+ category="lo",
+ description="DUPLOYAN LETTER S K R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC40,
+ },
+ [0x1BC41]={
+ category="lo",
+ description="DUPLOYAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC41,
+ },
+ [0x1BC42]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN OW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC42,
+ },
+ [0x1BC43]={
+ category="lo",
+ description="DUPLOYAN LETTER OA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC43,
+ },
+ [0x1BC44]={
+ category="lo",
+ description="DUPLOYAN LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC44,
+ },
+ [0x1BC45]={
+ category="lo",
+ description="DUPLOYAN LETTER AOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC45,
+ },
+ [0x1BC46]={
+ category="lo",
+ description="DUPLOYAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC46,
+ },
+ [0x1BC47]={
+ category="lo",
+ description="DUPLOYAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC47,
+ },
+ [0x1BC48]={
+ category="lo",
+ description="DUPLOYAN LETTER IE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC48,
+ },
+ [0x1BC49]={
+ category="lo",
+ description="DUPLOYAN LETTER SHORT I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC49,
+ },
+ [0x1BC4A]={
+ category="lo",
+ description="DUPLOYAN LETTER UI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4A,
+ },
+ [0x1BC4B]={
+ category="lo",
+ description="DUPLOYAN LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4B,
+ },
+ [0x1BC4C]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN EH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4C,
+ },
+ [0x1BC4D]={
+ category="lo",
+ description="DUPLOYAN LETTER ROMANIAN I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4D,
+ },
+ [0x1BC4E]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4E,
+ },
+ [0x1BC4F]={
+ category="lo",
+ description="DUPLOYAN LETTER LONG I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4F,
+ },
+ [0x1BC50]={
+ category="lo",
+ description="DUPLOYAN LETTER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC50,
+ },
+ [0x1BC51]={
+ category="lo",
+ description="DUPLOYAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC51,
+ },
+ [0x1BC52]={
+ category="lo",
+ description="DUPLOYAN LETTER EU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC52,
+ },
+ [0x1BC53]={
+ category="lo",
+ description="DUPLOYAN LETTER XW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC53,
+ },
+ [0x1BC54]={
+ category="lo",
+ description="DUPLOYAN LETTER U N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC54,
+ },
+ [0x1BC55]={
+ category="lo",
+ description="DUPLOYAN LETTER LONG U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC55,
+ },
+ [0x1BC56]={
+ category="lo",
+ description="DUPLOYAN LETTER ROMANIAN U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC56,
+ },
+ [0x1BC57]={
+ category="lo",
+ description="DUPLOYAN LETTER UH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC57,
+ },
+ [0x1BC58]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC58,
+ },
+ [0x1BC59]={
+ category="lo",
+ description="DUPLOYAN LETTER OOH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC59,
+ },
+ [0x1BC5A]={
+ category="lo",
+ description="DUPLOYAN LETTER OW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5A,
+ },
+ [0x1BC5B]={
+ category="lo",
+ description="DUPLOYAN LETTER OU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5B,
+ },
+ [0x1BC5C]={
+ category="lo",
+ description="DUPLOYAN LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5C,
+ },
+ [0x1BC5D]={
+ category="lo",
+ description="DUPLOYAN LETTER WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5D,
+ },
+ [0x1BC5E]={
+ category="lo",
+ description="DUPLOYAN LETTER WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5E,
+ },
+ [0x1BC5F]={
+ category="lo",
+ description="DUPLOYAN LETTER WEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5F,
+ },
+ [0x1BC60]={
+ category="lo",
+ description="DUPLOYAN LETTER WOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC60,
+ },
+ [0x1BC61]={
+ category="lo",
+ description="DUPLOYAN LETTER NASAL U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC61,
+ },
+ [0x1BC62]={
+ category="lo",
+ description="DUPLOYAN LETTER NASAL O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC62,
+ },
+ [0x1BC63]={
+ category="lo",
+ description="DUPLOYAN LETTER NASAL I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC63,
+ },
+ [0x1BC64]={
+ category="lo",
+ description="DUPLOYAN LETTER NASAL A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC64,
+ },
+ [0x1BC65]={
+ category="lo",
+ description="DUPLOYAN LETTER PERNIN AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC65,
+ },
+ [0x1BC66]={
+ category="lo",
+ description="DUPLOYAN LETTER PERNIN AM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC66,
+ },
+ [0x1BC67]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC67,
+ },
+ [0x1BC68]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC68,
+ },
+ [0x1BC69]={
+ category="lo",
+ description="DUPLOYAN LETTER SLOAN ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC69,
+ },
+ [0x1BC6A]={
+ category="lo",
+ description="DUPLOYAN LETTER VOCALIC M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC6A,
+ },
+ [0x1BC70]={
+ category="lo",
+ description="DUPLOYAN AFFIX LEFT HORIZONTAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC70,
+ },
+ [0x1BC71]={
+ category="lo",
+ description="DUPLOYAN AFFIX MID HORIZONTAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC71,
+ },
+ [0x1BC72]={
+ category="lo",
+ description="DUPLOYAN AFFIX RIGHT HORIZONTAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC72,
+ },
+ [0x1BC73]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW VERTICAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC73,
+ },
+ [0x1BC74]={
+ category="lo",
+ description="DUPLOYAN AFFIX MID VERTICAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC74,
+ },
+ [0x1BC75]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH VERTICAL SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC75,
+ },
+ [0x1BC76]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC76,
+ },
+ [0x1BC77]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED LEFT-TO-RIGHT SECANT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC77,
+ },
+ [0x1BC78]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED TANGENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC78,
+ },
+ [0x1BC79]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC79,
+ },
+ [0x1BC7A]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED E HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC7A,
+ },
+ [0x1BC7B]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED I HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC7B,
+ },
+ [0x1BC7C]={
+ category="lo",
+ description="DUPLOYAN AFFIX ATTACHED TANGENT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC7C,
+ },
+ [0x1BC80]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC80,
+ },
+ [0x1BC81]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH TIGHT ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC81,
+ },
+ [0x1BC82]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH GRAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC82,
+ },
+ [0x1BC83]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH LONG GRAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC83,
+ },
+ [0x1BC84]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC84,
+ },
+ [0x1BC85]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC85,
+ },
+ [0x1BC86]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH LINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC86,
+ },
+ [0x1BC87]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH WAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC87,
+ },
+ [0x1BC88]={
+ category="lo",
+ description="DUPLOYAN AFFIX HIGH VERTICAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC88,
+ },
+ [0x1BC90]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC90,
+ },
+ [0x1BC91]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW TIGHT ACUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC91,
+ },
+ [0x1BC92]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW GRAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC92,
+ },
+ [0x1BC93]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW LONG GRAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC93,
+ },
+ [0x1BC94]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC94,
+ },
+ [0x1BC95]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC95,
+ },
+ [0x1BC96]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW LINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC96,
+ },
+ [0x1BC97]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW WAVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC97,
+ },
+ [0x1BC98]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW VERTICAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC98,
+ },
+ [0x1BC99]={
+ category="lo",
+ description="DUPLOYAN AFFIX LOW ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC99,
+ },
+ [0x1BC9C]={
+ category="so",
+ description="DUPLOYAN SIGN O WITH CROSS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC9C,
+ },
+ [0x1BC9D]={
+ category="mn",
+ description="DUPLOYAN THICK LETTER SELECTOR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BC9D,
+ },
+ [0x1BC9E]={
+ category="mn",
+ combining=0x1,
+ description="DUPLOYAN DOUBLE MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BC9E,
+ },
+ [0x1BC9F]={
+ category="po",
+ description="DUPLOYAN PUNCTUATION CHINOOK FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1BC9F,
+ },
+ [0x1BCA0]={
+ category="cf",
+ description="SHORTHAND FORMAT LETTER OVERLAP",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1BCA0,
+ },
+ [0x1BCA1]={
+ category="cf",
+ description="SHORTHAND FORMAT CONTINUING OVERLAP",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1BCA1,
+ },
+ [0x1BCA2]={
+ category="cf",
+ description="SHORTHAND FORMAT DOWN STEP",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1BCA2,
+ },
+ [0x1BCA3]={
+ category="cf",
+ description="SHORTHAND FORMAT UP STEP",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1BCA3,
+ },
+ [0x1D000]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSILI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D000,
+ },
+ [0x1D001]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DASEIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D001,
+ },
+ [0x1D002]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PERISPOMENI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D002,
+ },
+ [0x1D003]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D003,
+ },
+ [0x1D004]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OXEIA DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D004,
+ },
+ [0x1D005]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D005,
+ },
+ [0x1D006]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL VAREIA DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D006,
+ },
+ [0x1D007]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KATHISTI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D007,
+ },
+ [0x1D008]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYRMATIKI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D008,
+ },
+ [0x1D009]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARAKLITIKI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D009,
+ },
+ [0x1D00A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YPOKRISIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00A,
+ },
+ [0x1D00B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00B,
+ },
+ [0x1D00C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KREMASTI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00C,
+ },
+ [0x1D00D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00D,
+ },
+ [0x1D00E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00E,
+ },
+ [0x1D00F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TELEIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D00F,
+ },
+ [0x1D010]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D010,
+ },
+ [0x1D011]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOSTROFOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D011,
+ },
+ [0x1D012]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D012,
+ },
+ [0x1D013]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYNEVMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D013,
+ },
+ [0x1D014]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THITA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D014,
+ },
+ [0x1D015]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D015,
+ },
+ [0x1D016]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGON ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D016,
+ },
+ [0x1D017]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSILON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D017,
+ },
+ [0x1D018]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHAMILON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D018,
+ },
+ [0x1D019]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL VATHY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D019,
+ },
+ [0x1D01A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ISON ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01A,
+ },
+ [0x1D01B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01B,
+ },
+ [0x1D01C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01C,
+ },
+ [0x1D01D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SAXIMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01D,
+ },
+ [0x1D01E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARICHON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01E,
+ },
+ [0x1D01F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D01F,
+ },
+ [0x1D020]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D020,
+ },
+ [0x1D021]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D021,
+ },
+ [0x1D022]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D022,
+ },
+ [0x1D023]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOTHEMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D023,
+ },
+ [0x1D024]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KLASMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D024,
+ },
+ [0x1D025]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL REVMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D025,
+ },
+ [0x1D026]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D026,
+ },
+ [0x1D027]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TINAGMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D027,
+ },
+ [0x1D028]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ANATRICHISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D028,
+ },
+ [0x1D029]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SEISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D029,
+ },
+ [0x1D02A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02A,
+ },
+ [0x1D02B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02B,
+ },
+ [0x1D02C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02C,
+ },
+ [0x1D02D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THEMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02D,
+ },
+ [0x1D02E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEMOI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02E,
+ },
+ [0x1D02F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D02F,
+ },
+ [0x1D030]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TRIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D030,
+ },
+ [0x1D031]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TESSERA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D031,
+ },
+ [0x1D032]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D032,
+ },
+ [0x1D033]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APESO EXO NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D033,
+ },
+ [0x1D034]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D034,
+ },
+ [0x1D035]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL IMIFTHORA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D035,
+ },
+ [0x1D036]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D036,
+ },
+ [0x1D037]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D037,
+ },
+ [0x1D038]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PELASTON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D038,
+ },
+ [0x1D039]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSIFISTON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D039,
+ },
+ [0x1D03A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KONTEVMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03A,
+ },
+ [0x1D03B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03B,
+ },
+ [0x1D03C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL RAPISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03C,
+ },
+ [0x1D03D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03D,
+ },
+ [0x1D03E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03E,
+ },
+ [0x1D03F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ICHADIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D03F,
+ },
+ [0x1D040]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL NANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D040,
+ },
+ [0x1D041]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PETASMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D041,
+ },
+ [0x1D042]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D042,
+ },
+ [0x1D043]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKON ALLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D043,
+ },
+ [0x1D044]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL STRAGGISMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D044,
+ },
+ [0x1D045]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GRONTHISMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D045,
+ },
+ [0x1D046]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ISON NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D046,
+ },
+ [0x1D047]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OLIGON NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D047,
+ },
+ [0x1D048]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OXEIA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D048,
+ },
+ [0x1D049]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PETASTI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D049,
+ },
+ [0x1D04A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KOUFISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04A,
+ },
+ [0x1D04B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04B,
+ },
+ [0x1D04C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04C,
+ },
+ [0x1D04D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PELASTON NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04D,
+ },
+ [0x1D04E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04E,
+ },
+ [0x1D04F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D04F,
+ },
+ [0x1D050]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YPSILI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D050,
+ },
+ [0x1D051]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D051,
+ },
+ [0x1D052]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D052,
+ },
+ [0x1D053]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YPORROI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D053,
+ },
+ [0x1D054]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D054,
+ },
+ [0x1D055]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ELAFRON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D055,
+ },
+ [0x1D056]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHAMILI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D056,
+ },
+ [0x1D057]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MIKRON ISON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D057,
+ },
+ [0x1D058]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL VAREIA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D058,
+ },
+ [0x1D059]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PIASMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D059,
+ },
+ [0x1D05A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSIFISTON NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05A,
+ },
+ [0x1D05B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OMALON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05B,
+ },
+ [0x1D05C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ANTIKENOMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05C,
+ },
+ [0x1D05D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LYGISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05D,
+ },
+ [0x1D05E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05E,
+ },
+ [0x1D05F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D05F,
+ },
+ [0x1D060]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D060,
+ },
+ [0x1D061]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KYLISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D061,
+ },
+ [0x1D062]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D062,
+ },
+ [0x1D063]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKON NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D063,
+ },
+ [0x1D064]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL EKSTREPTON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D064,
+ },
+ [0x1D065]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYNAGMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D065,
+ },
+ [0x1D066]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SYRMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D066,
+ },
+ [0x1D067]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHOREVMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D067,
+ },
+ [0x1D068]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL EPEGERMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D068,
+ },
+ [0x1D069]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SEISMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D069,
+ },
+ [0x1D06A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL XIRON KLASMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06A,
+ },
+ [0x1D06B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06B,
+ },
+ [0x1D06C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06C,
+ },
+ [0x1D06D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06D,
+ },
+ [0x1D06E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06E,
+ },
+ [0x1D06F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D06F,
+ },
+ [0x1D070]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D070,
+ },
+ [0x1D071]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D071,
+ },
+ [0x1D072]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D072,
+ },
+ [0x1D073]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D073,
+ },
+ [0x1D074]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D074,
+ },
+ [0x1D075]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL OYRANISMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D075,
+ },
+ [0x1D076]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D076,
+ },
+ [0x1D077]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D077,
+ },
+ [0x1D078]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THEMA APLOUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D078,
+ },
+ [0x1D079]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL THES KAI APOTHES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D079,
+ },
+ [0x1D07A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KATAVASMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07A,
+ },
+ [0x1D07B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ENDOFONON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07B,
+ },
+ [0x1D07C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFEN KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07C,
+ },
+ [0x1D07D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFEN ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07D,
+ },
+ [0x1D07E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL STAVROS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07E,
+ },
+ [0x1D07F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KLASMA ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D07F,
+ },
+ [0x1D080]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D080,
+ },
+ [0x1D081]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D081,
+ },
+ [0x1D082]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMA ALLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D082,
+ },
+ [0x1D083]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KRATIMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D083,
+ },
+ [0x1D084]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APODERMA NEO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D084,
+ },
+ [0x1D085]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D085,
+ },
+ [0x1D086]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D086,
+ },
+ [0x1D087]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TRIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D087,
+ },
+ [0x1D088]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TETRAPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D088,
+ },
+ [0x1D089]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KORONIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D089,
+ },
+ [0x1D08A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08A,
+ },
+ [0x1D08B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08B,
+ },
+ [0x1D08C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08C,
+ },
+ [0x1D08D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08D,
+ },
+ [0x1D08E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08E,
+ },
+ [0x1D08F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGON NEO ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D08F,
+ },
+ [0x1D090]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D090,
+ },
+ [0x1D091]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D091,
+ },
+ [0x1D092]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIGORGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D092,
+ },
+ [0x1D093]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D093,
+ },
+ [0x1D094]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D094,
+ },
+ [0x1D095]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D095,
+ },
+ [0x1D096]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL TRIGORGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D096,
+ },
+ [0x1D097]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D097,
+ },
+ [0x1D098]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL IMIDIARGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D098,
+ },
+ [0x1D099]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIARGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D099,
+ },
+ [0x1D09A]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09A,
+ },
+ [0x1D09B]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09B,
+ },
+ [0x1D09C]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI ARGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09C,
+ },
+ [0x1D09D]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI METRIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09D,
+ },
+ [0x1D09E]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI MESI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09E,
+ },
+ [0x1D09F]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI GORGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D09F,
+ },
+ [0x1D0A0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A0,
+ },
+ [0x1D0A1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A1,
+ },
+ [0x1D0A2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A2,
+ },
+ [0x1D0A3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A3,
+ },
+ [0x1D0A4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A4,
+ },
+ [0x1D0A5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A5,
+ },
+ [0x1D0A6]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A6,
+ },
+ [0x1D0A7]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A7,
+ },
+ [0x1D0A8]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A8,
+ },
+ [0x1D0A9]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0A9,
+ },
+ [0x1D0AA]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AA,
+ },
+ [0x1D0AB]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AB,
+ },
+ [0x1D0AC]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AC,
+ },
+ [0x1D0AD]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AD,
+ },
+ [0x1D0AE]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AE,
+ },
+ [0x1D0AF]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0AF,
+ },
+ [0x1D0B0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B0,
+ },
+ [0x1D0B1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B1,
+ },
+ [0x1D0B2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B2,
+ },
+ [0x1D0B3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B3,
+ },
+ [0x1D0B4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B4,
+ },
+ [0x1D0B5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B5,
+ },
+ [0x1D0B6]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B6,
+ },
+ [0x1D0B7]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL IMIFONON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B7,
+ },
+ [0x1D0B8]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL IMIFTHORON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B8,
+ },
+ [0x1D0B9]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0B9,
+ },
+ [0x1D0BA]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BA,
+ },
+ [0x1D0BB]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BB,
+ },
+ [0x1D0BC]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BC,
+ },
+ [0x1D0BD]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BD,
+ },
+ [0x1D0BE]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BE,
+ },
+ [0x1D0BF]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0BF,
+ },
+ [0x1D0C0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C0,
+ },
+ [0x1D0C1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C1,
+ },
+ [0x1D0C2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C2,
+ },
+ [0x1D0C3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C3,
+ },
+ [0x1D0C4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C4,
+ },
+ [0x1D0C5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C5,
+ },
+ [0x1D0C6]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C6,
+ },
+ [0x1D0C7]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA NENANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C7,
+ },
+ [0x1D0C8]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHROA ZYGOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C8,
+ },
+ [0x1D0C9]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHROA KLITON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0C9,
+ },
+ [0x1D0CA]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL CHROA SPATHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CA,
+ },
+ [0x1D0CB]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CB,
+ },
+ [0x1D0CC]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CC,
+ },
+ [0x1D0CD]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CD,
+ },
+ [0x1D0CE]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CE,
+ },
+ [0x1D0CF]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0CF,
+ },
+ [0x1D0D0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D0,
+ },
+ [0x1D0D1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D1,
+ },
+ [0x1D0D2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D2,
+ },
+ [0x1D0D3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D3,
+ },
+ [0x1D0D4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D4,
+ },
+ [0x1D0D5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D5,
+ },
+ [0x1D0D6]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D6,
+ },
+ [0x1D0D7]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D7,
+ },
+ [0x1D0D8]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GENIKI DIESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D8,
+ },
+ [0x1D0D9]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GENIKI YFESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0D9,
+ },
+ [0x1D0DA]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DA,
+ },
+ [0x1D0DB]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DB,
+ },
+ [0x1D0DC]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DC,
+ },
+ [0x1D0DD]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DD,
+ },
+ [0x1D0DE]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DE,
+ },
+ [0x1D0DF]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0DF,
+ },
+ [0x1D0E0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E0,
+ },
+ [0x1D0E1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E1,
+ },
+ [0x1D0E2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E2,
+ },
+ [0x1D0E3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E3,
+ },
+ [0x1D0E4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E4,
+ },
+ [0x1D0E5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E5,
+ },
+ [0x1D0E6]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIGRAMMA GG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E6,
+ },
+ [0x1D0E7]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E7,
+ },
+ [0x1D0E8]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL STIGMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E8,
+ },
+ [0x1D0E9]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0E9,
+ },
+ [0x1D0EA]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO VOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0EA,
+ },
+ [0x1D0EB]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0EB,
+ },
+ [0x1D0EC]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0EC,
+ },
+ [0x1D0ED]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0ED,
+ },
+ [0x1D0EE]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0EE,
+ },
+ [0x1D0EF]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL ARKTIKO NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0EF,
+ },
+ [0x1D0F0]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F0,
+ },
+ [0x1D0F1]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F1,
+ },
+ [0x1D0F2]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F2,
+ },
+ [0x1D0F3]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F3,
+ },
+ [0x1D0F4]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL KLASMA KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F4,
+ },
+ [0x1D0F5]={
+ category="so",
+ description="BYZANTINE MUSICAL SYMBOL GORGON NEO KATO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D0F5,
+ },
+ [0x1D100]={
+ category="so",
+ description="MUSICAL SYMBOL SINGLE BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D100,
+ },
+ [0x1D101]={
+ category="so",
+ description="MUSICAL SYMBOL DOUBLE BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D101,
+ },
+ [0x1D102]={
+ category="so",
+ description="MUSICAL SYMBOL FINAL BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D102,
+ },
+ [0x1D103]={
+ category="so",
+ description="MUSICAL SYMBOL REVERSE FINAL BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D103,
+ },
+ [0x1D104]={
+ category="so",
+ description="MUSICAL SYMBOL DASHED BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D104,
+ },
+ [0x1D105]={
+ category="so",
+ description="MUSICAL SYMBOL SHORT BARLINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D105,
+ },
+ [0x1D106]={
+ category="so",
+ description="MUSICAL SYMBOL LEFT REPEAT SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D106,
+ },
+ [0x1D107]={
+ category="so",
+ description="MUSICAL SYMBOL RIGHT REPEAT SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D107,
+ },
+ [0x1D108]={
+ category="so",
+ description="MUSICAL SYMBOL REPEAT DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D108,
+ },
+ [0x1D109]={
+ category="so",
+ description="MUSICAL SYMBOL DAL SEGNO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D109,
+ },
+ [0x1D10A]={
+ category="so",
+ description="MUSICAL SYMBOL DA CAPO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10A,
+ },
+ [0x1D10B]={
+ category="so",
+ description="MUSICAL SYMBOL SEGNO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10B,
+ },
+ [0x1D10C]={
+ category="so",
+ description="MUSICAL SYMBOL CODA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10C,
+ },
+ [0x1D10D]={
+ category="so",
+ description="MUSICAL SYMBOL REPEATED FIGURE-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10D,
+ },
+ [0x1D10E]={
+ category="so",
+ description="MUSICAL SYMBOL REPEATED FIGURE-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10E,
+ },
+ [0x1D10F]={
+ category="so",
+ description="MUSICAL SYMBOL REPEATED FIGURE-0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D10F,
+ },
+ [0x1D110]={
+ category="so",
+ description="MUSICAL SYMBOL FERMATA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D110,
+ },
+ [0x1D111]={
+ category="so",
+ description="MUSICAL SYMBOL FERMATA BELOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D111,
+ },
+ [0x1D112]={
+ category="so",
+ description="MUSICAL SYMBOL BREATH MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D112,
+ },
+ [0x1D113]={
+ category="so",
+ description="MUSICAL SYMBOL CAESURA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D113,
+ },
+ [0x1D114]={
+ category="so",
+ description="MUSICAL SYMBOL BRACE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D114,
+ },
+ [0x1D115]={
+ category="so",
+ description="MUSICAL SYMBOL BRACKET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D115,
+ },
+ [0x1D116]={
+ category="so",
+ description="MUSICAL SYMBOL ONE-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D116,
+ },
+ [0x1D117]={
+ category="so",
+ description="MUSICAL SYMBOL TWO-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D117,
+ },
+ [0x1D118]={
+ category="so",
+ description="MUSICAL SYMBOL THREE-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D118,
+ },
+ [0x1D119]={
+ category="so",
+ description="MUSICAL SYMBOL FOUR-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D119,
+ },
+ [0x1D11A]={
+ category="so",
+ description="MUSICAL SYMBOL FIVE-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11A,
+ },
+ [0x1D11B]={
+ category="so",
+ description="MUSICAL SYMBOL SIX-LINE STAFF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11B,
+ },
+ [0x1D11C]={
+ category="so",
+ description="MUSICAL SYMBOL SIX-STRING FRETBOARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11C,
+ },
+ [0x1D11D]={
+ category="so",
+ description="MUSICAL SYMBOL FOUR-STRING FRETBOARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11D,
+ },
+ [0x1D11E]={
+ category="so",
+ description="MUSICAL SYMBOL G CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11E,
+ },
+ [0x1D11F]={
+ category="so",
+ description="MUSICAL SYMBOL G CLEF OTTAVA ALTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D11F,
+ },
+ [0x1D120]={
+ category="so",
+ description="MUSICAL SYMBOL G CLEF OTTAVA BASSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D120,
+ },
+ [0x1D121]={
+ category="so",
+ description="MUSICAL SYMBOL C CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D121,
+ },
+ [0x1D122]={
+ category="so",
+ description="MUSICAL SYMBOL F CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D122,
+ },
+ [0x1D123]={
+ category="so",
+ description="MUSICAL SYMBOL F CLEF OTTAVA ALTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D123,
+ },
+ [0x1D124]={
+ category="so",
+ description="MUSICAL SYMBOL F CLEF OTTAVA BASSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D124,
+ },
+ [0x1D125]={
+ category="so",
+ description="MUSICAL SYMBOL DRUM CLEF-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D125,
+ },
+ [0x1D126]={
+ category="so",
+ description="MUSICAL SYMBOL DRUM CLEF-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D126,
+ },
+ [0x1D129]={
+ category="so",
+ description="MUSICAL SYMBOL MULTIPLE MEASURE REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D129,
+ },
+ [0x1D12A]={
+ category="so",
+ description="MUSICAL SYMBOL DOUBLE SHARP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12A,
+ },
+ [0x1D12B]={
+ category="so",
+ description="MUSICAL SYMBOL DOUBLE FLAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12B,
+ },
+ [0x1D12C]={
+ category="so",
+ description="MUSICAL SYMBOL FLAT UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12C,
+ },
+ [0x1D12D]={
+ category="so",
+ description="MUSICAL SYMBOL FLAT DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12D,
+ },
+ [0x1D12E]={
+ category="so",
+ description="MUSICAL SYMBOL NATURAL UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12E,
+ },
+ [0x1D12F]={
+ category="so",
+ description="MUSICAL SYMBOL NATURAL DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D12F,
+ },
+ [0x1D130]={
+ category="so",
+ description="MUSICAL SYMBOL SHARP UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D130,
+ },
+ [0x1D131]={
+ category="so",
+ description="MUSICAL SYMBOL SHARP DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D131,
+ },
+ [0x1D132]={
+ category="so",
+ description="MUSICAL SYMBOL QUARTER TONE SHARP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D132,
+ },
+ [0x1D133]={
+ category="so",
+ description="MUSICAL SYMBOL QUARTER TONE FLAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D133,
+ },
+ [0x1D134]={
+ category="so",
+ description="MUSICAL SYMBOL COMMON TIME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D134,
+ },
+ [0x1D135]={
+ category="so",
+ description="MUSICAL SYMBOL CUT TIME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D135,
+ },
+ [0x1D136]={
+ category="so",
+ description="MUSICAL SYMBOL OTTAVA ALTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D136,
+ },
+ [0x1D137]={
+ category="so",
+ description="MUSICAL SYMBOL OTTAVA BASSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D137,
+ },
+ [0x1D138]={
+ category="so",
+ description="MUSICAL SYMBOL QUINDICESIMA ALTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D138,
+ },
+ [0x1D139]={
+ category="so",
+ description="MUSICAL SYMBOL QUINDICESIMA BASSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D139,
+ },
+ [0x1D13A]={
+ category="so",
+ description="MUSICAL SYMBOL MULTI REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13A,
+ },
+ [0x1D13B]={
+ category="so",
+ description="MUSICAL SYMBOL WHOLE REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13B,
+ },
+ [0x1D13C]={
+ category="so",
+ description="MUSICAL SYMBOL HALF REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13C,
+ },
+ [0x1D13D]={
+ category="so",
+ description="MUSICAL SYMBOL QUARTER REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13D,
+ },
+ [0x1D13E]={
+ category="so",
+ description="MUSICAL SYMBOL EIGHTH REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13E,
+ },
+ [0x1D13F]={
+ category="so",
+ description="MUSICAL SYMBOL SIXTEENTH REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D13F,
+ },
+ [0x1D140]={
+ category="so",
+ description="MUSICAL SYMBOL THIRTY-SECOND REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D140,
+ },
+ [0x1D141]={
+ category="so",
+ description="MUSICAL SYMBOL SIXTY-FOURTH REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D141,
+ },
+ [0x1D142]={
+ category="so",
+ description="MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D142,
+ },
+ [0x1D143]={
+ category="so",
+ description="MUSICAL SYMBOL X NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D143,
+ },
+ [0x1D144]={
+ category="so",
+ description="MUSICAL SYMBOL PLUS NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D144,
+ },
+ [0x1D145]={
+ category="so",
+ description="MUSICAL SYMBOL CIRCLE X NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D145,
+ },
+ [0x1D146]={
+ category="so",
+ description="MUSICAL SYMBOL SQUARE NOTEHEAD WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D146,
+ },
+ [0x1D147]={
+ category="so",
+ description="MUSICAL SYMBOL SQUARE NOTEHEAD BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D147,
+ },
+ [0x1D148]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D148,
+ },
+ [0x1D149]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D149,
+ },
+ [0x1D14A]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14A,
+ },
+ [0x1D14B]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14B,
+ },
+ [0x1D14C]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14C,
+ },
+ [0x1D14D]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14D,
+ },
+ [0x1D14E]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14E,
+ },
+ [0x1D14F]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D14F,
+ },
+ [0x1D150]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D150,
+ },
+ [0x1D151]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D151,
+ },
+ [0x1D152]={
+ category="so",
+ description="MUSICAL SYMBOL MOON NOTEHEAD WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D152,
+ },
+ [0x1D153]={
+ category="so",
+ description="MUSICAL SYMBOL MOON NOTEHEAD BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D153,
+ },
+ [0x1D154]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D154,
+ },
+ [0x1D155]={
+ category="so",
+ description="MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D155,
+ },
+ [0x1D156]={
+ category="so",
+ description="MUSICAL SYMBOL PARENTHESIS NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D156,
+ },
+ [0x1D157]={
+ category="so",
+ description="MUSICAL SYMBOL VOID NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D157,
+ },
+ [0x1D158]={
+ category="so",
+ description="MUSICAL SYMBOL NOTEHEAD BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D158,
+ },
+ [0x1D159]={
+ category="so",
+ description="MUSICAL SYMBOL NULL NOTEHEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D159,
+ },
+ [0x1D15A]={
+ category="so",
+ description="MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D15A,
+ },
+ [0x1D15B]={
+ category="so",
+ description="MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D15B,
+ },
+ [0x1D15C]={
+ category="so",
+ description="MUSICAL SYMBOL BREVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D15C,
+ },
+ [0x1D15D]={
+ category="so",
+ description="MUSICAL SYMBOL WHOLE NOTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D15D,
+ },
+ [0x1D15E]={
+ category="so",
+ description="MUSICAL SYMBOL HALF NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D157, 0x1D165 },
+ unicodeslot=0x1D15E,
+ },
+ [0x1D15F]={
+ category="so",
+ description="MUSICAL SYMBOL QUARTER NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D158, 0x1D165 },
+ unicodeslot=0x1D15F,
+ },
+ [0x1D160]={
+ category="so",
+ description="MUSICAL SYMBOL EIGHTH NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D15F, 0x1D16E },
+ unicodeslot=0x1D160,
+ },
+ [0x1D161]={
+ category="so",
+ description="MUSICAL SYMBOL SIXTEENTH NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D15F, 0x1D16F },
+ unicodeslot=0x1D161,
+ },
+ [0x1D162]={
+ category="so",
+ description="MUSICAL SYMBOL THIRTY-SECOND NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D15F, 0x1D170 },
+ unicodeslot=0x1D162,
+ },
+ [0x1D163]={
+ category="so",
+ description="MUSICAL SYMBOL SIXTY-FOURTH NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D15F, 0x1D171 },
+ unicodeslot=0x1D163,
+ },
+ [0x1D164]={
+ category="so",
+ description="MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D15F, 0x1D172 },
+ unicodeslot=0x1D164,
+ },
+ [0x1D165]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING STEM",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D165,
+ },
+ [0x1D166]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING SPRECHGESANG STEM",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D166,
+ },
+ [0x1D167]={
+ category="mn",
+ combining=0x1,
+ description="MUSICAL SYMBOL COMBINING TREMOLO-0x0001",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D167,
+ },
+ [0x1D168]={
+ category="mn",
+ combining=0x1,
+ description="MUSICAL SYMBOL COMBINING TREMOLO-0x0002",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D168,
+ },
+ [0x1D169]={
+ category="mn",
+ combining=0x1,
+ description="MUSICAL SYMBOL COMBINING TREMOLO-0x0003",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D169,
+ },
+ [0x1D16A]={
+ category="so",
+ description="MUSICAL SYMBOL FINGERED TREMOLO-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D16A,
+ },
+ [0x1D16B]={
+ category="so",
+ description="MUSICAL SYMBOL FINGERED TREMOLO-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D16B,
+ },
+ [0x1D16C]={
+ category="so",
+ description="MUSICAL SYMBOL FINGERED TREMOLO-0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D16C,
+ },
+ [0x1D16D]={
+ category="mc",
+ combining=0xE2,
+ description="MUSICAL SYMBOL COMBINING AUGMENTATION DOT",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D16D,
+ },
+ [0x1D16E]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING FLAG-0x0001",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D16E,
+ },
+ [0x1D16F]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING FLAG-0x0002",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D16F,
+ },
+ [0x1D170]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING FLAG-0x0003",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D170,
+ },
+ [0x1D171]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING FLAG-0x0004",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D171,
+ },
+ [0x1D172]={
+ category="mc",
+ combining=0xD8,
+ description="MUSICAL SYMBOL COMBINING FLAG-0x0005",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1D172,
+ },
+ [0x1D173]={
+ category="cf",
+ description="MUSICAL SYMBOL BEGIN BEAM",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D173,
+ },
+ [0x1D174]={
+ category="cf",
+ description="MUSICAL SYMBOL END BEAM",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D174,
+ },
+ [0x1D175]={
+ category="cf",
+ description="MUSICAL SYMBOL BEGIN TIE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D175,
+ },
+ [0x1D176]={
+ category="cf",
+ description="MUSICAL SYMBOL END TIE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D176,
+ },
+ [0x1D177]={
+ category="cf",
+ description="MUSICAL SYMBOL BEGIN SLUR",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D177,
+ },
+ [0x1D178]={
+ category="cf",
+ description="MUSICAL SYMBOL END SLUR",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D178,
+ },
+ [0x1D179]={
+ category="cf",
+ description="MUSICAL SYMBOL BEGIN PHRASE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D179,
+ },
+ [0x1D17A]={
+ category="cf",
+ description="MUSICAL SYMBOL END PHRASE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0x1D17A,
+ },
+ [0x1D17B]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING ACCENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D17B,
+ },
+ [0x1D17C]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING STACCATO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D17C,
+ },
+ [0x1D17D]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING TENUTO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D17D,
+ },
+ [0x1D17E]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING STACCATISSIMO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D17E,
+ },
+ [0x1D17F]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING MARCATO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D17F,
+ },
+ [0x1D180]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING MARCATO-STACCATO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D180,
+ },
+ [0x1D181]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING ACCENT-STACCATO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D181,
+ },
+ [0x1D182]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING LOURE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D182,
+ },
+ [0x1D183]={
+ category="so",
+ description="MUSICAL SYMBOL ARPEGGIATO UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D183,
+ },
+ [0x1D184]={
+ category="so",
+ description="MUSICAL SYMBOL ARPEGGIATO DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D184,
+ },
+ [0x1D185]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING DOIT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D185,
+ },
+ [0x1D186]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING RIP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D186,
+ },
+ [0x1D187]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING FLIP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D187,
+ },
+ [0x1D188]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING SMEAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D188,
+ },
+ [0x1D189]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING BEND",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D189,
+ },
+ [0x1D18A]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING DOUBLE TONGUE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D18A,
+ },
+ [0x1D18B]={
+ category="mn",
+ combining=0xDC,
+ description="MUSICAL SYMBOL COMBINING TRIPLE TONGUE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D18B,
+ },
+ [0x1D18C]={
+ category="so",
+ description="MUSICAL SYMBOL RINFORZANDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D18C,
+ },
+ [0x1D18D]={
+ category="so",
+ description="MUSICAL SYMBOL SUBITO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D18D,
+ },
+ [0x1D18E]={
+ category="so",
+ description="MUSICAL SYMBOL Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D18E,
+ },
+ [0x1D18F]={
+ category="so",
+ description="MUSICAL SYMBOL PIANO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D18F,
+ },
+ [0x1D190]={
+ category="so",
+ description="MUSICAL SYMBOL MEZZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D190,
+ },
+ [0x1D191]={
+ category="so",
+ description="MUSICAL SYMBOL FORTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D191,
+ },
+ [0x1D192]={
+ category="so",
+ description="MUSICAL SYMBOL CRESCENDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D192,
+ },
+ [0x1D193]={
+ category="so",
+ description="MUSICAL SYMBOL DECRESCENDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D193,
+ },
+ [0x1D194]={
+ category="so",
+ description="MUSICAL SYMBOL GRACE NOTE SLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D194,
+ },
+ [0x1D195]={
+ category="so",
+ description="MUSICAL SYMBOL GRACE NOTE NO SLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D195,
+ },
+ [0x1D196]={
+ category="so",
+ description="MUSICAL SYMBOL TR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D196,
+ },
+ [0x1D197]={
+ category="so",
+ description="MUSICAL SYMBOL TURN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D197,
+ },
+ [0x1D198]={
+ category="so",
+ description="MUSICAL SYMBOL INVERTED TURN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D198,
+ },
+ [0x1D199]={
+ category="so",
+ description="MUSICAL SYMBOL TURN SLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D199,
+ },
+ [0x1D19A]={
+ category="so",
+ description="MUSICAL SYMBOL TURN UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19A,
+ },
+ [0x1D19B]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19B,
+ },
+ [0x1D19C]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19C,
+ },
+ [0x1D19D]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19D,
+ },
+ [0x1D19E]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19E,
+ },
+ [0x1D19F]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D19F,
+ },
+ [0x1D1A0]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A0,
+ },
+ [0x1D1A1]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A1,
+ },
+ [0x1D1A2]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A2,
+ },
+ [0x1D1A3]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x0009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A3,
+ },
+ [0x1D1A4]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x000A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A4,
+ },
+ [0x1D1A5]={
+ category="so",
+ description="MUSICAL SYMBOL ORNAMENT STROKE-0x000B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A5,
+ },
+ [0x1D1A6]={
+ category="so",
+ description="MUSICAL SYMBOL HAUPTSTIMME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A6,
+ },
+ [0x1D1A7]={
+ category="so",
+ description="MUSICAL SYMBOL NEBENSTIMME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A7,
+ },
+ [0x1D1A8]={
+ category="so",
+ description="MUSICAL SYMBOL END OF STIMME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A8,
+ },
+ [0x1D1A9]={
+ category="so",
+ description="MUSICAL SYMBOL DEGREE SLASH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1A9,
+ },
+ [0x1D1AA]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING DOWN BOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D1AA,
+ },
+ [0x1D1AB]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING UP BOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D1AB,
+ },
+ [0x1D1AC]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING HARMONIC",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D1AC,
+ },
+ [0x1D1AD]={
+ category="mn",
+ combining=0xE6,
+ description="MUSICAL SYMBOL COMBINING SNAP PIZZICATO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D1AD,
+ },
+ [0x1D1AE]={
+ category="so",
+ description="MUSICAL SYMBOL PEDAL MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1AE,
+ },
+ [0x1D1AF]={
+ category="so",
+ description="MUSICAL SYMBOL PEDAL UP MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1AF,
+ },
+ [0x1D1B0]={
+ category="so",
+ description="MUSICAL SYMBOL HALF PEDAL MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B0,
+ },
+ [0x1D1B1]={
+ category="so",
+ description="MUSICAL SYMBOL GLISSANDO UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B1,
+ },
+ [0x1D1B2]={
+ category="so",
+ description="MUSICAL SYMBOL GLISSANDO DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B2,
+ },
+ [0x1D1B3]={
+ category="so",
+ description="MUSICAL SYMBOL WITH FINGERNAILS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B3,
+ },
+ [0x1D1B4]={
+ category="so",
+ description="MUSICAL SYMBOL DAMP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B4,
+ },
+ [0x1D1B5]={
+ category="so",
+ description="MUSICAL SYMBOL DAMP ALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B5,
+ },
+ [0x1D1B6]={
+ category="so",
+ description="MUSICAL SYMBOL MAXIMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B6,
+ },
+ [0x1D1B7]={
+ category="so",
+ description="MUSICAL SYMBOL LONGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B7,
+ },
+ [0x1D1B8]={
+ category="so",
+ description="MUSICAL SYMBOL BREVIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B8,
+ },
+ [0x1D1B9]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIBREVIS WHITE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1B9,
+ },
+ [0x1D1BA]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIBREVIS BLACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1BA,
+ },
+ [0x1D1BB]={
+ category="so",
+ description="MUSICAL SYMBOL MINIMA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1B9, 0x1D165 },
+ unicodeslot=0x1D1BB,
+ },
+ [0x1D1BC]={
+ category="so",
+ description="MUSICAL SYMBOL MINIMA BLACK",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1BA, 0x1D165 },
+ unicodeslot=0x1D1BC,
+ },
+ [0x1D1BD]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIMINIMA WHITE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1BB, 0x1D16E },
+ unicodeslot=0x1D1BD,
+ },
+ [0x1D1BE]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIMINIMA BLACK",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1BC, 0x1D16E },
+ unicodeslot=0x1D1BE,
+ },
+ [0x1D1BF]={
+ category="so",
+ description="MUSICAL SYMBOL FUSA WHITE",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1BB, 0x1D16F },
+ unicodeslot=0x1D1BF,
+ },
+ [0x1D1C0]={
+ category="so",
+ description="MUSICAL SYMBOL FUSA BLACK",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1D1BC, 0x1D16F },
+ unicodeslot=0x1D1C0,
+ },
+ [0x1D1C1]={
+ category="so",
+ description="MUSICAL SYMBOL LONGA PERFECTA REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C1,
+ },
+ [0x1D1C2]={
+ category="so",
+ description="MUSICAL SYMBOL LONGA IMPERFECTA REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C2,
+ },
+ [0x1D1C3]={
+ category="so",
+ description="MUSICAL SYMBOL BREVIS REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C3,
+ },
+ [0x1D1C4]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIBREVIS REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C4,
+ },
+ [0x1D1C5]={
+ category="so",
+ description="MUSICAL SYMBOL MINIMA REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C5,
+ },
+ [0x1D1C6]={
+ category="so",
+ description="MUSICAL SYMBOL SEMIMINIMA REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C6,
+ },
+ [0x1D1C7]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C7,
+ },
+ [0x1D1C8]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C8,
+ },
+ [0x1D1C9]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1C9,
+ },
+ [0x1D1CA]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CA,
+ },
+ [0x1D1CB]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CB,
+ },
+ [0x1D1CC]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-0x0001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CC,
+ },
+ [0x1D1CD]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-0x0002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CD,
+ },
+ [0x1D1CE]={
+ category="so",
+ description="MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-0x0003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CE,
+ },
+ [0x1D1CF]={
+ category="so",
+ description="MUSICAL SYMBOL CROIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1CF,
+ },
+ [0x1D1D0]={
+ category="so",
+ description="MUSICAL SYMBOL GREGORIAN C CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D0,
+ },
+ [0x1D1D1]={
+ category="so",
+ description="MUSICAL SYMBOL GREGORIAN F CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D1,
+ },
+ [0x1D1D2]={
+ category="so",
+ description="MUSICAL SYMBOL SQUARE B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D2,
+ },
+ [0x1D1D3]={
+ category="so",
+ description="MUSICAL SYMBOL VIRGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D3,
+ },
+ [0x1D1D4]={
+ category="so",
+ description="MUSICAL SYMBOL PODATUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D4,
+ },
+ [0x1D1D5]={
+ category="so",
+ description="MUSICAL SYMBOL CLIVIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D5,
+ },
+ [0x1D1D6]={
+ category="so",
+ description="MUSICAL SYMBOL SCANDICUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D6,
+ },
+ [0x1D1D7]={
+ category="so",
+ description="MUSICAL SYMBOL CLIMACUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D7,
+ },
+ [0x1D1D8]={
+ category="so",
+ description="MUSICAL SYMBOL TORCULUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D8,
+ },
+ [0x1D1D9]={
+ category="so",
+ description="MUSICAL SYMBOL PORRECTUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1D9,
+ },
+ [0x1D1DA]={
+ category="so",
+ description="MUSICAL SYMBOL PORRECTUS FLEXUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DA,
+ },
+ [0x1D1DB]={
+ category="so",
+ description="MUSICAL SYMBOL SCANDICUS FLEXUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DB,
+ },
+ [0x1D1DC]={
+ category="so",
+ description="MUSICAL SYMBOL TORCULUS RESUPINUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DC,
+ },
+ [0x1D1DD]={
+ category="so",
+ description="MUSICAL SYMBOL PES SUBPUNCTIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DD,
+ },
+ [0x1D1DE]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN C CLEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DE,
+ },
+ [0x1D1DF]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN END OF PIECE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1DF,
+ },
+ [0x1D1E0]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN FINAL NOTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E0,
+ },
+ [0x1D1E1]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN RECITATIVE MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E1,
+ },
+ [0x1D1E2]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN WHOLE NOTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E2,
+ },
+ [0x1D1E3]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN HALF NOTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E3,
+ },
+ [0x1D1E4]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E4,
+ },
+ [0x1D1E5]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E5,
+ },
+ [0x1D1E6]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E6,
+ },
+ [0x1D1E7]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E7,
+ },
+ [0x1D1E8]={
+ category="so",
+ description="MUSICAL SYMBOL KIEVAN FLAT SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D1E8,
+ },
+ [0x1D200]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0001",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D200,
+ },
+ [0x1D201]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0002",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D201,
+ },
+ [0x1D202]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0003",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D202,
+ },
+ [0x1D203]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0004",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D203,
+ },
+ [0x1D204]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0005",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D204,
+ },
+ [0x1D205]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0006",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D205,
+ },
+ [0x1D206]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0007",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D206,
+ },
+ [0x1D207]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0008",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D207,
+ },
+ [0x1D208]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0009",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D208,
+ },
+ [0x1D209]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000A",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D209,
+ },
+ [0x1D20A]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000B",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20A,
+ },
+ [0x1D20B]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000C",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20B,
+ },
+ [0x1D20C]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000D",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20C,
+ },
+ [0x1D20D]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000E",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20D,
+ },
+ [0x1D20E]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x000F",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20E,
+ },
+ [0x1D20F]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0010",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D20F,
+ },
+ [0x1D210]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0011",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D210,
+ },
+ [0x1D211]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0012",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D211,
+ },
+ [0x1D212]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0013",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D212,
+ },
+ [0x1D213]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0014",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D213,
+ },
+ [0x1D214]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0015",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D214,
+ },
+ [0x1D215]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0016",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D215,
+ },
+ [0x1D216]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0017",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D216,
+ },
+ [0x1D217]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0018",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D217,
+ },
+ [0x1D218]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0032",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D218,
+ },
+ [0x1D219]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0033",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D219,
+ },
+ [0x1D21A]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0034",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21A,
+ },
+ [0x1D21B]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0035",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21B,
+ },
+ [0x1D21C]={
+ category="so",
+ description="GREEK VOCAL NOTATION SYMBOL-0x0036",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21C,
+ },
+ [0x1D21D]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0001",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21D,
+ },
+ [0x1D21E]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0002",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21E,
+ },
+ [0x1D21F]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0004",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D21F,
+ },
+ [0x1D220]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0005",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D220,
+ },
+ [0x1D221]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0007",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D221,
+ },
+ [0x1D222]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0008",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D222,
+ },
+ [0x1D223]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x000B",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D223,
+ },
+ [0x1D224]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x000C",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D224,
+ },
+ [0x1D225]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x000D",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D225,
+ },
+ [0x1D226]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x000E",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D226,
+ },
+ [0x1D227]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0011",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D227,
+ },
+ [0x1D228]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0012",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D228,
+ },
+ [0x1D229]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0013",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D229,
+ },
+ [0x1D22A]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0017",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22A,
+ },
+ [0x1D22B]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0018",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22B,
+ },
+ [0x1D22C]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0019",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22C,
+ },
+ [0x1D22D]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x001A",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22D,
+ },
+ [0x1D22E]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x001B",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22E,
+ },
+ [0x1D22F]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x001D",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D22F,
+ },
+ [0x1D230]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x001E",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D230,
+ },
+ [0x1D231]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0020",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D231,
+ },
+ [0x1D232]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0024",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D232,
+ },
+ [0x1D233]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0025",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D233,
+ },
+ [0x1D234]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0026",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D234,
+ },
+ [0x1D235]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0027",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D235,
+ },
+ [0x1D236]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0028",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D236,
+ },
+ [0x1D237]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x002A",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D237,
+ },
+ [0x1D238]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x002B",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D238,
+ },
+ [0x1D239]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x002D",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D239,
+ },
+ [0x1D23A]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x002F",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23A,
+ },
+ [0x1D23B]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0030",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23B,
+ },
+ [0x1D23C]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0031",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23C,
+ },
+ [0x1D23D]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0032",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23D,
+ },
+ [0x1D23E]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0033",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23E,
+ },
+ [0x1D23F]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0034",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D23F,
+ },
+ [0x1D240]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0035",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D240,
+ },
+ [0x1D241]={
+ category="so",
+ description="GREEK INSTRUMENTAL NOTATION SYMBOL-0x0036",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D241,
+ },
+ [0x1D242]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GREEK MUSICAL TRISEME",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D242,
+ },
+ [0x1D243]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GREEK MUSICAL TETRASEME",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D243,
+ },
+ [0x1D244]={
+ category="mn",
+ combining=0xE6,
+ description="COMBINING GREEK MUSICAL PENTASEME",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1D244,
+ },
+ [0x1D245]={
+ category="so",
+ description="GREEK MUSICAL LEIMMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D245,
+ },
+ [0x1D300]={
+ category="so",
+ description="MONOGRAM FOR EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D300,
+ },
+ [0x1D301]={
+ category="so",
+ description="DIGRAM FOR HEAVENLY EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D301,
+ },
+ [0x1D302]={
+ category="so",
+ description="DIGRAM FOR HUMAN EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D302,
+ },
+ [0x1D303]={
+ category="so",
+ description="DIGRAM FOR EARTHLY HEAVEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D303,
+ },
+ [0x1D304]={
+ category="so",
+ description="DIGRAM FOR EARTHLY HUMAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D304,
+ },
+ [0x1D305]={
+ category="so",
+ description="DIGRAM FOR EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D305,
+ },
+ [0x1D306]={
+ category="so",
+ description="TETRAGRAM FOR CENTRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D306,
+ },
+ [0x1D307]={
+ category="so",
+ description="TETRAGRAM FOR FULL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D307,
+ },
+ [0x1D308]={
+ category="so",
+ description="TETRAGRAM FOR MIRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D308,
+ },
+ [0x1D309]={
+ category="so",
+ description="TETRAGRAM FOR BARRIER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D309,
+ },
+ [0x1D30A]={
+ category="so",
+ description="TETRAGRAM FOR KEEPING SMALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30A,
+ },
+ [0x1D30B]={
+ category="so",
+ description="TETRAGRAM FOR CONTRARIETY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30B,
+ },
+ [0x1D30C]={
+ category="so",
+ description="TETRAGRAM FOR ASCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30C,
+ },
+ [0x1D30D]={
+ category="so",
+ description="TETRAGRAM FOR OPPOSITION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30D,
+ },
+ [0x1D30E]={
+ category="so",
+ description="TETRAGRAM FOR BRANCHING OUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30E,
+ },
+ [0x1D30F]={
+ category="so",
+ description="TETRAGRAM FOR DEFECTIVENESS OR DISTORTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D30F,
+ },
+ [0x1D310]={
+ category="so",
+ description="TETRAGRAM FOR DIVERGENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D310,
+ },
+ [0x1D311]={
+ category="so",
+ description="TETRAGRAM FOR YOUTHFULNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D311,
+ },
+ [0x1D312]={
+ category="so",
+ description="TETRAGRAM FOR INCREASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D312,
+ },
+ [0x1D313]={
+ category="so",
+ description="TETRAGRAM FOR PENETRATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D313,
+ },
+ [0x1D314]={
+ category="so",
+ description="TETRAGRAM FOR REACH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D314,
+ },
+ [0x1D315]={
+ category="so",
+ description="TETRAGRAM FOR CONTACT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D315,
+ },
+ [0x1D316]={
+ category="so",
+ description="TETRAGRAM FOR HOLDING BACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D316,
+ },
+ [0x1D317]={
+ category="so",
+ description="TETRAGRAM FOR WAITING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D317,
+ },
+ [0x1D318]={
+ category="so",
+ description="TETRAGRAM FOR FOLLOWING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D318,
+ },
+ [0x1D319]={
+ category="so",
+ description="TETRAGRAM FOR ADVANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D319,
+ },
+ [0x1D31A]={
+ category="so",
+ description="TETRAGRAM FOR RELEASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31A,
+ },
+ [0x1D31B]={
+ category="so",
+ description="TETRAGRAM FOR RESISTANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31B,
+ },
+ [0x1D31C]={
+ category="so",
+ description="TETRAGRAM FOR EASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31C,
+ },
+ [0x1D31D]={
+ category="so",
+ description="TETRAGRAM FOR JOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31D,
+ },
+ [0x1D31E]={
+ category="so",
+ description="TETRAGRAM FOR CONTENTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31E,
+ },
+ [0x1D31F]={
+ category="so",
+ description="TETRAGRAM FOR ENDEAVOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D31F,
+ },
+ [0x1D320]={
+ category="so",
+ description="TETRAGRAM FOR DUTIES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D320,
+ },
+ [0x1D321]={
+ category="so",
+ description="TETRAGRAM FOR CHANGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D321,
+ },
+ [0x1D322]={
+ category="so",
+ description="TETRAGRAM FOR DECISIVENESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D322,
+ },
+ [0x1D323]={
+ category="so",
+ description="TETRAGRAM FOR BOLD RESOLUTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D323,
+ },
+ [0x1D324]={
+ category="so",
+ description="TETRAGRAM FOR PACKING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D324,
+ },
+ [0x1D325]={
+ category="so",
+ description="TETRAGRAM FOR LEGION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D325,
+ },
+ [0x1D326]={
+ category="so",
+ description="TETRAGRAM FOR CLOSENESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D326,
+ },
+ [0x1D327]={
+ category="so",
+ description="TETRAGRAM FOR KINSHIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D327,
+ },
+ [0x1D328]={
+ category="so",
+ description="TETRAGRAM FOR GATHERING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D328,
+ },
+ [0x1D329]={
+ category="so",
+ description="TETRAGRAM FOR STRENGTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D329,
+ },
+ [0x1D32A]={
+ category="so",
+ description="TETRAGRAM FOR PURITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32A,
+ },
+ [0x1D32B]={
+ category="so",
+ description="TETRAGRAM FOR FULLNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32B,
+ },
+ [0x1D32C]={
+ category="so",
+ description="TETRAGRAM FOR RESIDENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32C,
+ },
+ [0x1D32D]={
+ category="so",
+ description="TETRAGRAM FOR LAW OR MODEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32D,
+ },
+ [0x1D32E]={
+ category="so",
+ description="TETRAGRAM FOR RESPONSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32E,
+ },
+ [0x1D32F]={
+ category="so",
+ description="TETRAGRAM FOR GOING TO MEET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D32F,
+ },
+ [0x1D330]={
+ category="so",
+ description="TETRAGRAM FOR ENCOUNTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D330,
+ },
+ [0x1D331]={
+ category="so",
+ description="TETRAGRAM FOR STOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D331,
+ },
+ [0x1D332]={
+ category="so",
+ description="TETRAGRAM FOR GREATNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D332,
+ },
+ [0x1D333]={
+ category="so",
+ description="TETRAGRAM FOR ENLARGEMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D333,
+ },
+ [0x1D334]={
+ category="so",
+ description="TETRAGRAM FOR PATTERN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D334,
+ },
+ [0x1D335]={
+ category="so",
+ description="TETRAGRAM FOR RITUAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D335,
+ },
+ [0x1D336]={
+ category="so",
+ description="TETRAGRAM FOR FLIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D336,
+ },
+ [0x1D337]={
+ category="so",
+ description="TETRAGRAM FOR VASTNESS OR WASTING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D337,
+ },
+ [0x1D338]={
+ category="so",
+ description="TETRAGRAM FOR CONSTANCY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D338,
+ },
+ [0x1D339]={
+ category="so",
+ description="TETRAGRAM FOR MEASURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D339,
+ },
+ [0x1D33A]={
+ category="so",
+ description="TETRAGRAM FOR ETERNITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33A,
+ },
+ [0x1D33B]={
+ category="so",
+ description="TETRAGRAM FOR UNITY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33B,
+ },
+ [0x1D33C]={
+ category="so",
+ description="TETRAGRAM FOR DIMINISHMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33C,
+ },
+ [0x1D33D]={
+ category="so",
+ description="TETRAGRAM FOR CLOSED MOUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33D,
+ },
+ [0x1D33E]={
+ category="so",
+ description="TETRAGRAM FOR GUARDEDNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33E,
+ },
+ [0x1D33F]={
+ category="so",
+ description="TETRAGRAM FOR GATHERING IN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D33F,
+ },
+ [0x1D340]={
+ category="so",
+ description="TETRAGRAM FOR MASSING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D340,
+ },
+ [0x1D341]={
+ category="so",
+ description="TETRAGRAM FOR ACCUMULATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D341,
+ },
+ [0x1D342]={
+ category="so",
+ description="TETRAGRAM FOR EMBELLISHMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D342,
+ },
+ [0x1D343]={
+ category="so",
+ description="TETRAGRAM FOR DOUBT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D343,
+ },
+ [0x1D344]={
+ category="so",
+ description="TETRAGRAM FOR WATCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D344,
+ },
+ [0x1D345]={
+ category="so",
+ description="TETRAGRAM FOR SINKING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D345,
+ },
+ [0x1D346]={
+ category="so",
+ description="TETRAGRAM FOR INNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D346,
+ },
+ [0x1D347]={
+ category="so",
+ description="TETRAGRAM FOR DEPARTURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D347,
+ },
+ [0x1D348]={
+ category="so",
+ description="TETRAGRAM FOR DARKENING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D348,
+ },
+ [0x1D349]={
+ category="so",
+ description="TETRAGRAM FOR DIMMING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D349,
+ },
+ [0x1D34A]={
+ category="so",
+ description="TETRAGRAM FOR EXHAUSTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34A,
+ },
+ [0x1D34B]={
+ category="so",
+ description="TETRAGRAM FOR SEVERANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34B,
+ },
+ [0x1D34C]={
+ category="so",
+ description="TETRAGRAM FOR STOPPAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34C,
+ },
+ [0x1D34D]={
+ category="so",
+ description="TETRAGRAM FOR HARDNESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34D,
+ },
+ [0x1D34E]={
+ category="so",
+ description="TETRAGRAM FOR COMPLETION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34E,
+ },
+ [0x1D34F]={
+ category="so",
+ description="TETRAGRAM FOR CLOSURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D34F,
+ },
+ [0x1D350]={
+ category="so",
+ description="TETRAGRAM FOR FAILURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D350,
+ },
+ [0x1D351]={
+ category="so",
+ description="TETRAGRAM FOR AGGRAVATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D351,
+ },
+ [0x1D352]={
+ category="so",
+ description="TETRAGRAM FOR COMPLIANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D352,
+ },
+ [0x1D353]={
+ category="so",
+ description="TETRAGRAM FOR ON THE VERGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D353,
+ },
+ [0x1D354]={
+ category="so",
+ description="TETRAGRAM FOR DIFFICULTIES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D354,
+ },
+ [0x1D355]={
+ category="so",
+ description="TETRAGRAM FOR LABOURING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D355,
+ },
+ [0x1D356]={
+ category="so",
+ description="TETRAGRAM FOR FOSTERING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1D356,
+ },
+ [0x1D360]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D360,
+ },
+ [0x1D361]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D361,
+ },
+ [0x1D362]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D362,
+ },
+ [0x1D363]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D363,
+ },
+ [0x1D364]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D364,
+ },
+ [0x1D365]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D365,
+ },
+ [0x1D366]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D366,
+ },
+ [0x1D367]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D367,
+ },
+ [0x1D368]={
+ category="no",
+ description="COUNTING ROD UNIT DIGIT NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D368,
+ },
+ [0x1D369]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D369,
+ },
+ [0x1D36A]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36A,
+ },
+ [0x1D36B]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36B,
+ },
+ [0x1D36C]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36C,
+ },
+ [0x1D36D]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36D,
+ },
+ [0x1D36E]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36E,
+ },
+ [0x1D36F]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D36F,
+ },
+ [0x1D370]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D370,
+ },
+ [0x1D371]={
+ category="no",
+ description="COUNTING ROD TENS DIGIT NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D371,
+ },
+ [0x1D400]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D400,
+ visual="bf",
+ },
+ [0x1D401]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D401,
+ visual="bf",
+ },
+ [0x1D402]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D402,
+ visual="bf",
+ },
+ [0x1D403]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D403,
+ visual="bf",
+ },
+ [0x1D404]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D404,
+ visual="bf",
+ },
+ [0x1D405]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D405,
+ visual="bf",
+ },
+ [0x1D406]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D406,
+ visual="bf",
+ },
+ [0x1D407]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D407,
+ visual="bf",
+ },
+ [0x1D408]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D408,
+ visual="bf",
+ },
+ [0x1D409]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D409,
+ visual="bf",
+ },
+ [0x1D40A]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D40A,
+ visual="bf",
+ },
+ [0x1D40B]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D40B,
+ visual="bf",
+ },
+ [0x1D40C]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D40C,
+ visual="bf",
+ },
+ [0x1D40D]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D40D,
+ visual="bf",
+ },
+ [0x1D40E]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D40E,
+ visual="bf",
+ },
+ [0x1D40F]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D40F,
+ visual="bf",
+ },
+ [0x1D410]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D410,
+ visual="bf",
+ },
+ [0x1D411]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D411,
+ visual="bf",
+ },
+ [0x1D412]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D412,
+ visual="bf",
+ },
+ [0x1D413]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D413,
+ visual="bf",
+ },
+ [0x1D414]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D414,
+ visual="bf",
+ },
+ [0x1D415]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D415,
+ visual="bf",
+ },
+ [0x1D416]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D416,
+ visual="bf",
+ },
+ [0x1D417]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D417,
+ visual="bf",
+ },
+ [0x1D418]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D418,
+ visual="bf",
+ },
+ [0x1D419]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D419,
+ visual="bf",
+ },
+ [0x1D41A]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D41A,
+ visual="bf",
+ },
+ [0x1D41B]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D41B,
+ visual="bf",
+ },
+ [0x1D41C]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D41C,
+ visual="bf",
+ },
+ [0x1D41D]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D41D,
+ visual="bf",
+ },
+ [0x1D41E]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D41E,
+ visual="bf",
+ },
+ [0x1D41F]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D41F,
+ visual="bf",
+ },
+ [0x1D420]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D420,
+ visual="bf",
+ },
+ [0x1D421]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D421,
+ visual="bf",
+ },
+ [0x1D422]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D422,
+ visual="bf",
+ },
+ [0x1D423]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D423,
+ visual="bf",
+ },
+ [0x1D424]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D424,
+ visual="bf",
+ },
+ [0x1D425]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D425,
+ visual="bf",
+ },
+ [0x1D426]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D426,
+ visual="bf",
+ },
+ [0x1D427]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D427,
+ visual="bf",
+ },
+ [0x1D428]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D428,
+ visual="bf",
+ },
+ [0x1D429]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D429,
+ visual="bf",
+ },
+ [0x1D42A]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D42A,
+ visual="bf",
+ },
+ [0x1D42B]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D42B,
+ visual="bf",
+ },
+ [0x1D42C]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D42C,
+ visual="bf",
+ },
+ [0x1D42D]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D42D,
+ visual="bf",
+ },
+ [0x1D42E]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D42E,
+ visual="bf",
+ },
+ [0x1D42F]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D42F,
+ visual="bf",
+ },
+ [0x1D430]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D430,
+ visual="bf",
+ },
+ [0x1D431]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D431,
+ visual="bf",
+ },
+ [0x1D432]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D432,
+ visual="bf",
+ },
+ [0x1D433]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D433,
+ visual="bf",
+ },
+ [0x1D434]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D434,
+ visual="it",
+ },
+ [0x1D435]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D435,
+ visual="it",
+ },
+ [0x1D436]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D436,
+ visual="it",
+ },
+ [0x1D437]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D437,
+ visual="it",
+ },
+ [0x1D438]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D438,
+ visual="it",
+ },
+ [0x1D439]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D439,
+ visual="it",
+ },
+ [0x1D43A]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D43A,
+ visual="it",
+ },
+ [0x1D43B]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D43B,
+ visual="it",
+ },
+ [0x1D43C]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D43C,
+ visual="it",
+ },
+ [0x1D43D]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D43D,
+ visual="it",
+ },
+ [0x1D43E]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D43E,
+ visual="it",
+ },
+ [0x1D43F]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D43F,
+ visual="it",
+ },
+ [0x1D440]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D440,
+ visual="it",
+ },
+ [0x1D441]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D441,
+ visual="it",
+ },
+ [0x1D442]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D442,
+ visual="it",
+ },
+ [0x1D443]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D443,
+ visual="it",
+ },
+ [0x1D444]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D444,
+ visual="it",
+ },
+ [0x1D445]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D445,
+ visual="it",
+ },
+ [0x1D446]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D446,
+ visual="it",
+ },
+ [0x1D447]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D447,
+ visual="it",
+ },
+ [0x1D448]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D448,
+ visual="it",
+ },
+ [0x1D449]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D449,
+ visual="it",
+ },
+ [0x1D44A]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D44A,
+ visual="it",
+ },
+ [0x1D44B]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D44B,
+ visual="it",
+ },
+ [0x1D44C]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D44C,
+ visual="it",
+ },
+ [0x1D44D]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D44D,
+ visual="it",
+ },
+ [0x1D44E]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D44E,
+ visual="it",
+ },
+ [0x1D44F]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D44F,
+ visual="it",
+ },
+ [0x1D450]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D450,
+ visual="it",
+ },
+ [0x1D451]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D451,
+ visual="it",
+ },
+ [0x1D452]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D452,
+ visual="it",
+ },
+ [0x1D453]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D453,
+ visual="it",
+ },
+ [0x1D454]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D454,
+ visual="it",
+ },
+ [0x1D456]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D456,
+ visual="it",
+ },
+ [0x1D457]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D457,
+ visual="it",
+ },
+ [0x1D458]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D458,
+ visual="it",
+ },
+ [0x1D459]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D459,
+ visual="it",
+ },
+ [0x1D45A]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D45A,
+ visual="it",
+ },
+ [0x1D45B]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D45B,
+ visual="it",
+ },
+ [0x1D45C]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D45C,
+ visual="it",
+ },
+ [0x1D45D]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D45D,
+ visual="it",
+ },
+ [0x1D45E]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D45E,
+ visual="it",
+ },
+ [0x1D45F]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D45F,
+ visual="it",
+ },
+ [0x1D460]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D460,
+ visual="it",
+ },
+ [0x1D461]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D461,
+ visual="it",
+ },
+ [0x1D462]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D462,
+ visual="it",
+ },
+ [0x1D463]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D463,
+ visual="it",
+ },
+ [0x1D464]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D464,
+ visual="it",
+ },
+ [0x1D465]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D465,
+ visual="it",
+ },
+ [0x1D466]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D466,
+ visual="it",
+ },
+ [0x1D467]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D467,
+ visual="it",
+ },
+ [0x1D468]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D468,
+ visual="bi",
+ },
+ [0x1D469]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D469,
+ visual="bi",
+ },
+ [0x1D46A]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D46A,
+ visual="bi",
+ },
+ [0x1D46B]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D46B,
+ visual="bi",
+ },
+ [0x1D46C]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D46C,
+ visual="bi",
+ },
+ [0x1D46D]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D46D,
+ visual="bi",
+ },
+ [0x1D46E]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D46E,
+ visual="bi",
+ },
+ [0x1D46F]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D46F,
+ visual="bi",
+ },
+ [0x1D470]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D470,
+ visual="bi",
+ },
+ [0x1D471]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D471,
+ visual="bi",
+ },
+ [0x1D472]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D472,
+ visual="bi",
+ },
+ [0x1D473]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D473,
+ visual="bi",
+ },
+ [0x1D474]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D474,
+ visual="bi",
+ },
+ [0x1D475]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D475,
+ visual="bi",
+ },
+ [0x1D476]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D476,
+ visual="bi",
+ },
+ [0x1D477]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D477,
+ visual="bi",
+ },
+ [0x1D478]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D478,
+ visual="bi",
+ },
+ [0x1D479]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D479,
+ visual="bi",
+ },
+ [0x1D47A]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D47A,
+ visual="bi",
+ },
+ [0x1D47B]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D47B,
+ visual="bi",
+ },
+ [0x1D47C]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D47C,
+ visual="bi",
+ },
+ [0x1D47D]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D47D,
+ visual="bi",
+ },
+ [0x1D47E]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D47E,
+ visual="bi",
+ },
+ [0x1D47F]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D47F,
+ visual="bi",
+ },
+ [0x1D480]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D480,
+ visual="bi",
+ },
+ [0x1D481]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D481,
+ visual="bi",
+ },
+ [0x1D482]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D482,
+ visual="bi",
+ },
+ [0x1D483]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D483,
+ visual="bi",
+ },
+ [0x1D484]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D484,
+ visual="bi",
+ },
+ [0x1D485]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D485,
+ visual="bi",
+ },
+ [0x1D486]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D486,
+ visual="bi",
+ },
+ [0x1D487]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D487,
+ visual="bi",
+ },
+ [0x1D488]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D488,
+ visual="bi",
+ },
+ [0x1D489]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D489,
+ visual="bi",
+ },
+ [0x1D48A]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D48A,
+ visual="bi",
+ },
+ [0x1D48B]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D48B,
+ visual="bi",
+ },
+ [0x1D48C]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D48C,
+ visual="bi",
+ },
+ [0x1D48D]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D48D,
+ visual="bi",
+ },
+ [0x1D48E]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D48E,
+ visual="bi",
+ },
+ [0x1D48F]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D48F,
+ visual="bi",
+ },
+ [0x1D490]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D490,
+ visual="bi",
+ },
+ [0x1D491]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D491,
+ visual="bi",
+ },
+ [0x1D492]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D492,
+ visual="bi",
+ },
+ [0x1D493]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D493,
+ visual="bi",
+ },
+ [0x1D494]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D494,
+ visual="bi",
+ },
+ [0x1D495]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D495,
+ visual="bi",
+ },
+ [0x1D496]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D496,
+ visual="bi",
+ },
+ [0x1D497]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D497,
+ visual="bi",
+ },
+ [0x1D498]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D498,
+ visual="bi",
+ },
+ [0x1D499]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D499,
+ visual="bi",
+ },
+ [0x1D49A]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D49A,
+ visual="bi",
+ },
+ [0x1D49B]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D49B,
+ visual="bi",
+ },
+ [0x1D49C]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D49C,
+ },
+ [0x1D49E]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D49E,
+ },
+ [0x1D49F]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D49F,
+ },
+ [0x1D4A2]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D4A2,
+ },
+ [0x1D4A5]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D4A5,
+ },
+ [0x1D4A6]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D4A6,
+ },
+ [0x1D4A9]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D4A9,
+ },
+ [0x1D4AA]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D4AA,
+ },
+ [0x1D4AB]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D4AB,
+ },
+ [0x1D4AC]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D4AC,
+ },
+ [0x1D4AE]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D4AE,
+ },
+ [0x1D4AF]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D4AF,
+ },
+ [0x1D4B0]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D4B0,
+ },
+ [0x1D4B1]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D4B1,
+ },
+ [0x1D4B2]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D4B2,
+ },
+ [0x1D4B3]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D4B3,
+ },
+ [0x1D4B4]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D4B4,
+ },
+ [0x1D4B5]={
+ category="lu",
+ description="MATHEMATICAL SCRIPT CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D4B5,
+ },
+ [0x1D4B6]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D4B6,
+ },
+ [0x1D4B7]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D4B7,
+ },
+ [0x1D4B8]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D4B8,
+ },
+ [0x1D4B9]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D4B9,
+ },
+ [0x1D4BB]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D4BB,
+ },
+ [0x1D4BD]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D4BD,
+ },
+ [0x1D4BE]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D4BE,
+ },
+ [0x1D4BF]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D4BF,
+ },
+ [0x1D4C0]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D4C0,
+ },
+ [0x1D4C1]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D4C1,
+ },
+ [0x1D4C2]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D4C2,
+ },
+ [0x1D4C3]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D4C3,
+ },
+ [0x1D4C5]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D4C5,
+ },
+ [0x1D4C6]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D4C6,
+ },
+ [0x1D4C7]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D4C7,
+ },
+ [0x1D4C8]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D4C8,
+ },
+ [0x1D4C9]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D4C9,
+ },
+ [0x1D4CA]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D4CA,
+ },
+ [0x1D4CB]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D4CB,
+ },
+ [0x1D4CC]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D4CC,
+ },
+ [0x1D4CD]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D4CD,
+ },
+ [0x1D4CE]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D4CE,
+ },
+ [0x1D4CF]={
+ category="ll",
+ description="MATHEMATICAL SCRIPT SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D4CF,
+ },
+ [0x1D4D0]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D4D0,
+ visual="bf",
+ },
+ [0x1D4D1]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D4D1,
+ visual="bf",
+ },
+ [0x1D4D2]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D4D2,
+ visual="bf",
+ },
+ [0x1D4D3]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D4D3,
+ visual="bf",
+ },
+ [0x1D4D4]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D4D4,
+ visual="bf",
+ },
+ [0x1D4D5]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D4D5,
+ visual="bf",
+ },
+ [0x1D4D6]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D4D6,
+ visual="bf",
+ },
+ [0x1D4D7]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D4D7,
+ visual="bf",
+ },
+ [0x1D4D8]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D4D8,
+ visual="bf",
+ },
+ [0x1D4D9]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D4D9,
+ visual="bf",
+ },
+ [0x1D4DA]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D4DA,
+ visual="bf",
+ },
+ [0x1D4DB]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D4DB,
+ visual="bf",
+ },
+ [0x1D4DC]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D4DC,
+ visual="bf",
+ },
+ [0x1D4DD]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D4DD,
+ visual="bf",
+ },
+ [0x1D4DE]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D4DE,
+ visual="bf",
+ },
+ [0x1D4DF]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D4DF,
+ visual="bf",
+ },
+ [0x1D4E0]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D4E0,
+ visual="bf",
+ },
+ [0x1D4E1]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D4E1,
+ visual="bf",
+ },
+ [0x1D4E2]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D4E2,
+ visual="bf",
+ },
+ [0x1D4E3]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D4E3,
+ visual="bf",
+ },
+ [0x1D4E4]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D4E4,
+ visual="bf",
+ },
+ [0x1D4E5]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D4E5,
+ visual="bf",
+ },
+ [0x1D4E6]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D4E6,
+ visual="bf",
+ },
+ [0x1D4E7]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D4E7,
+ visual="bf",
+ },
+ [0x1D4E8]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D4E8,
+ visual="bf",
+ },
+ [0x1D4E9]={
+ category="lu",
+ description="MATHEMATICAL BOLD SCRIPT CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D4E9,
+ visual="bf",
+ },
+ [0x1D4EA]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D4EA,
+ visual="bf",
+ },
+ [0x1D4EB]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D4EB,
+ visual="bf",
+ },
+ [0x1D4EC]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D4EC,
+ visual="bf",
+ },
+ [0x1D4ED]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D4ED,
+ visual="bf",
+ },
+ [0x1D4EE]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D4EE,
+ visual="bf",
+ },
+ [0x1D4EF]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D4EF,
+ visual="bf",
+ },
+ [0x1D4F0]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D4F0,
+ visual="bf",
+ },
+ [0x1D4F1]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D4F1,
+ visual="bf",
+ },
+ [0x1D4F2]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D4F2,
+ visual="bf",
+ },
+ [0x1D4F3]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D4F3,
+ visual="bf",
+ },
+ [0x1D4F4]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D4F4,
+ visual="bf",
+ },
+ [0x1D4F5]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D4F5,
+ visual="bf",
+ },
+ [0x1D4F6]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D4F6,
+ visual="bf",
+ },
+ [0x1D4F7]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D4F7,
+ visual="bf",
+ },
+ [0x1D4F8]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D4F8,
+ visual="bf",
+ },
+ [0x1D4F9]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D4F9,
+ visual="bf",
+ },
+ [0x1D4FA]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D4FA,
+ visual="bf",
+ },
+ [0x1D4FB]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D4FB,
+ visual="bf",
+ },
+ [0x1D4FC]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D4FC,
+ visual="bf",
+ },
+ [0x1D4FD]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D4FD,
+ visual="bf",
+ },
+ [0x1D4FE]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D4FE,
+ visual="bf",
+ },
+ [0x1D4FF]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D4FF,
+ visual="bf",
+ },
+ [0x1D500]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D500,
+ visual="bf",
+ },
+ [0x1D501]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D501,
+ visual="bf",
+ },
+ [0x1D502]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D502,
+ visual="bf",
+ },
+ [0x1D503]={
+ category="ll",
+ description="MATHEMATICAL BOLD SCRIPT SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D503,
+ visual="bf",
+ },
+ [0x1D504]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D504,
+ },
+ [0x1D505]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D505,
+ },
+ [0x1D507]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D507,
+ },
+ [0x1D508]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D508,
+ },
+ [0x1D509]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D509,
+ },
+ [0x1D50A]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D50A,
+ },
+ [0x1D50D]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D50D,
+ },
+ [0x1D50E]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D50E,
+ },
+ [0x1D50F]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D50F,
+ },
+ [0x1D510]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D510,
+ },
+ [0x1D511]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D511,
+ },
+ [0x1D512]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D512,
+ },
+ [0x1D513]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D513,
+ },
+ [0x1D514]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D514,
+ },
+ [0x1D516]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D516,
+ },
+ [0x1D517]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D517,
+ },
+ [0x1D518]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D518,
+ },
+ [0x1D519]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D519,
+ },
+ [0x1D51A]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D51A,
+ },
+ [0x1D51B]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D51B,
+ },
+ [0x1D51C]={
+ category="lu",
+ description="MATHEMATICAL FRAKTUR CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D51C,
+ },
+ [0x1D51E]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D51E,
+ },
+ [0x1D51F]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D51F,
+ },
+ [0x1D520]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D520,
+ },
+ [0x1D521]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D521,
+ },
+ [0x1D522]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D522,
+ },
+ [0x1D523]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D523,
+ },
+ [0x1D524]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D524,
+ },
+ [0x1D525]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D525,
+ },
+ [0x1D526]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D526,
+ },
+ [0x1D527]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D527,
+ },
+ [0x1D528]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D528,
+ },
+ [0x1D529]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D529,
+ },
+ [0x1D52A]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D52A,
+ },
+ [0x1D52B]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D52B,
+ },
+ [0x1D52C]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D52C,
+ },
+ [0x1D52D]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D52D,
+ },
+ [0x1D52E]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D52E,
+ },
+ [0x1D52F]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D52F,
+ },
+ [0x1D530]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D530,
+ },
+ [0x1D531]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D531,
+ },
+ [0x1D532]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D532,
+ },
+ [0x1D533]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D533,
+ },
+ [0x1D534]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D534,
+ },
+ [0x1D535]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D535,
+ },
+ [0x1D536]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D536,
+ },
+ [0x1D537]={
+ category="ll",
+ description="MATHEMATICAL FRAKTUR SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D537,
+ },
+ [0x1D538]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D538,
+ },
+ [0x1D539]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D539,
+ },
+ [0x1D53B]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D53B,
+ },
+ [0x1D53C]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D53C,
+ },
+ [0x1D53D]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D53D,
+ },
+ [0x1D53E]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D53E,
+ },
+ [0x1D540]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D540,
+ },
+ [0x1D541]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D541,
+ },
+ [0x1D542]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D542,
+ },
+ [0x1D543]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D543,
+ },
+ [0x1D544]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D544,
+ },
+ [0x1D546]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D546,
+ },
+ [0x1D54A]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D54A,
+ },
+ [0x1D54B]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D54B,
+ },
+ [0x1D54C]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D54C,
+ },
+ [0x1D54D]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D54D,
+ },
+ [0x1D54E]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D54E,
+ },
+ [0x1D54F]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D54F,
+ },
+ [0x1D550]={
+ category="lu",
+ description="MATHEMATICAL DOUBLE-STRUCK CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D550,
+ },
+ [0x1D552]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D552,
+ },
+ [0x1D553]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D553,
+ },
+ [0x1D554]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D554,
+ },
+ [0x1D555]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D555,
+ },
+ [0x1D556]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D556,
+ },
+ [0x1D557]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D557,
+ },
+ [0x1D558]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D558,
+ },
+ [0x1D559]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D559,
+ },
+ [0x1D55A]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D55A,
+ },
+ [0x1D55B]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D55B,
+ },
+ [0x1D55C]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D55C,
+ },
+ [0x1D55D]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D55D,
+ },
+ [0x1D55E]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D55E,
+ },
+ [0x1D55F]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D55F,
+ },
+ [0x1D560]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D560,
+ },
+ [0x1D561]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D561,
+ },
+ [0x1D562]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D562,
+ },
+ [0x1D563]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D563,
+ },
+ [0x1D564]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D564,
+ },
+ [0x1D565]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D565,
+ },
+ [0x1D566]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D566,
+ },
+ [0x1D567]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D567,
+ },
+ [0x1D568]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D568,
+ },
+ [0x1D569]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D569,
+ },
+ [0x1D56A]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D56A,
+ },
+ [0x1D56B]={
+ category="ll",
+ description="MATHEMATICAL DOUBLE-STRUCK SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D56B,
+ },
+ [0x1D56C]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D56C,
+ visual="bf",
+ },
+ [0x1D56D]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D56D,
+ visual="bf",
+ },
+ [0x1D56E]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D56E,
+ visual="bf",
+ },
+ [0x1D56F]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D56F,
+ visual="bf",
+ },
+ [0x1D570]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D570,
+ visual="bf",
+ },
+ [0x1D571]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D571,
+ visual="bf",
+ },
+ [0x1D572]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D572,
+ visual="bf",
+ },
+ [0x1D573]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D573,
+ visual="bf",
+ },
+ [0x1D574]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D574,
+ visual="bf",
+ },
+ [0x1D575]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D575,
+ visual="bf",
+ },
+ [0x1D576]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D576,
+ visual="bf",
+ },
+ [0x1D577]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D577,
+ visual="bf",
+ },
+ [0x1D578]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D578,
+ visual="bf",
+ },
+ [0x1D579]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D579,
+ visual="bf",
+ },
+ [0x1D57A]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D57A,
+ visual="bf",
+ },
+ [0x1D57B]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D57B,
+ visual="bf",
+ },
+ [0x1D57C]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D57C,
+ visual="bf",
+ },
+ [0x1D57D]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D57D,
+ visual="bf",
+ },
+ [0x1D57E]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D57E,
+ visual="bf",
+ },
+ [0x1D57F]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D57F,
+ visual="bf",
+ },
+ [0x1D580]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D580,
+ visual="bf",
+ },
+ [0x1D581]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D581,
+ visual="bf",
+ },
+ [0x1D582]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D582,
+ visual="bf",
+ },
+ [0x1D583]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D583,
+ visual="bf",
+ },
+ [0x1D584]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D584,
+ visual="bf",
+ },
+ [0x1D585]={
+ category="lu",
+ description="MATHEMATICAL BOLD FRAKTUR CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D585,
+ visual="bf",
+ },
+ [0x1D586]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D586,
+ visual="bf",
+ },
+ [0x1D587]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D587,
+ visual="bf",
+ },
+ [0x1D588]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D588,
+ visual="bf",
+ },
+ [0x1D589]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D589,
+ visual="bf",
+ },
+ [0x1D58A]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D58A,
+ visual="bf",
+ },
+ [0x1D58B]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D58B,
+ visual="bf",
+ },
+ [0x1D58C]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D58C,
+ visual="bf",
+ },
+ [0x1D58D]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D58D,
+ visual="bf",
+ },
+ [0x1D58E]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D58E,
+ visual="bf",
+ },
+ [0x1D58F]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D58F,
+ visual="bf",
+ },
+ [0x1D590]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D590,
+ visual="bf",
+ },
+ [0x1D591]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D591,
+ visual="bf",
+ },
+ [0x1D592]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D592,
+ visual="bf",
+ },
+ [0x1D593]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D593,
+ visual="bf",
+ },
+ [0x1D594]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D594,
+ visual="bf",
+ },
+ [0x1D595]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D595,
+ visual="bf",
+ },
+ [0x1D596]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D596,
+ visual="bf",
+ },
+ [0x1D597]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D597,
+ visual="bf",
+ },
+ [0x1D598]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D598,
+ visual="bf",
+ },
+ [0x1D599]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D599,
+ visual="bf",
+ },
+ [0x1D59A]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D59A,
+ visual="bf",
+ },
+ [0x1D59B]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D59B,
+ visual="bf",
+ },
+ [0x1D59C]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D59C,
+ visual="bf",
+ },
+ [0x1D59D]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D59D,
+ visual="bf",
+ },
+ [0x1D59E]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D59E,
+ visual="bf",
+ },
+ [0x1D59F]={
+ category="ll",
+ description="MATHEMATICAL BOLD FRAKTUR SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D59F,
+ visual="bf",
+ },
+ [0x1D5A0]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D5A0,
+ },
+ [0x1D5A1]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D5A1,
+ },
+ [0x1D5A2]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D5A2,
+ },
+ [0x1D5A3]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D5A3,
+ },
+ [0x1D5A4]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D5A4,
+ },
+ [0x1D5A5]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D5A5,
+ },
+ [0x1D5A6]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D5A6,
+ },
+ [0x1D5A7]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D5A7,
+ },
+ [0x1D5A8]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D5A8,
+ },
+ [0x1D5A9]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D5A9,
+ },
+ [0x1D5AA]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D5AA,
+ },
+ [0x1D5AB]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D5AB,
+ },
+ [0x1D5AC]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D5AC,
+ },
+ [0x1D5AD]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D5AD,
+ },
+ [0x1D5AE]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D5AE,
+ },
+ [0x1D5AF]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D5AF,
+ },
+ [0x1D5B0]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D5B0,
+ },
+ [0x1D5B1]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D5B1,
+ },
+ [0x1D5B2]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D5B2,
+ },
+ [0x1D5B3]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D5B3,
+ },
+ [0x1D5B4]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D5B4,
+ },
+ [0x1D5B5]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D5B5,
+ },
+ [0x1D5B6]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D5B6,
+ },
+ [0x1D5B7]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D5B7,
+ },
+ [0x1D5B8]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D5B8,
+ },
+ [0x1D5B9]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D5B9,
+ },
+ [0x1D5BA]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D5BA,
+ },
+ [0x1D5BB]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D5BB,
+ },
+ [0x1D5BC]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D5BC,
+ },
+ [0x1D5BD]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D5BD,
+ },
+ [0x1D5BE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D5BE,
+ },
+ [0x1D5BF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D5BF,
+ },
+ [0x1D5C0]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D5C0,
+ },
+ [0x1D5C1]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D5C1,
+ },
+ [0x1D5C2]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D5C2,
+ },
+ [0x1D5C3]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D5C3,
+ },
+ [0x1D5C4]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D5C4,
+ },
+ [0x1D5C5]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D5C5,
+ },
+ [0x1D5C6]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D5C6,
+ },
+ [0x1D5C7]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D5C7,
+ },
+ [0x1D5C8]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D5C8,
+ },
+ [0x1D5C9]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D5C9,
+ },
+ [0x1D5CA]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D5CA,
+ },
+ [0x1D5CB]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D5CB,
+ },
+ [0x1D5CC]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D5CC,
+ },
+ [0x1D5CD]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D5CD,
+ },
+ [0x1D5CE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D5CE,
+ },
+ [0x1D5CF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D5CF,
+ },
+ [0x1D5D0]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D5D0,
+ },
+ [0x1D5D1]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D5D1,
+ },
+ [0x1D5D2]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D5D2,
+ },
+ [0x1D5D3]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D5D3,
+ },
+ [0x1D5D4]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D5D4,
+ visual="bf",
+ },
+ [0x1D5D5]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D5D5,
+ visual="bf",
+ },
+ [0x1D5D6]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D5D6,
+ visual="bf",
+ },
+ [0x1D5D7]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D5D7,
+ visual="bf",
+ },
+ [0x1D5D8]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D5D8,
+ visual="bf",
+ },
+ [0x1D5D9]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D5D9,
+ visual="bf",
+ },
+ [0x1D5DA]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D5DA,
+ visual="bf",
+ },
+ [0x1D5DB]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D5DB,
+ visual="bf",
+ },
+ [0x1D5DC]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D5DC,
+ visual="bf",
+ },
+ [0x1D5DD]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D5DD,
+ visual="bf",
+ },
+ [0x1D5DE]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D5DE,
+ visual="bf",
+ },
+ [0x1D5DF]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D5DF,
+ visual="bf",
+ },
+ [0x1D5E0]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D5E0,
+ visual="bf",
+ },
+ [0x1D5E1]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D5E1,
+ visual="bf",
+ },
+ [0x1D5E2]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D5E2,
+ visual="bf",
+ },
+ [0x1D5E3]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D5E3,
+ visual="bf",
+ },
+ [0x1D5E4]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D5E4,
+ visual="bf",
+ },
+ [0x1D5E5]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D5E5,
+ visual="bf",
+ },
+ [0x1D5E6]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D5E6,
+ visual="bf",
+ },
+ [0x1D5E7]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D5E7,
+ visual="bf",
+ },
+ [0x1D5E8]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D5E8,
+ visual="bf",
+ },
+ [0x1D5E9]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D5E9,
+ visual="bf",
+ },
+ [0x1D5EA]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D5EA,
+ visual="bf",
+ },
+ [0x1D5EB]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D5EB,
+ visual="bf",
+ },
+ [0x1D5EC]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D5EC,
+ visual="bf",
+ },
+ [0x1D5ED]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D5ED,
+ visual="bf",
+ },
+ [0x1D5EE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D5EE,
+ visual="bf",
+ },
+ [0x1D5EF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D5EF,
+ visual="bf",
+ },
+ [0x1D5F0]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D5F0,
+ visual="bf",
+ },
+ [0x1D5F1]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D5F1,
+ visual="bf",
+ },
+ [0x1D5F2]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D5F2,
+ visual="bf",
+ },
+ [0x1D5F3]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D5F3,
+ visual="bf",
+ },
+ [0x1D5F4]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D5F4,
+ visual="bf",
+ },
+ [0x1D5F5]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D5F5,
+ visual="bf",
+ },
+ [0x1D5F6]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D5F6,
+ visual="bf",
+ },
+ [0x1D5F7]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D5F7,
+ visual="bf",
+ },
+ [0x1D5F8]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D5F8,
+ visual="bf",
+ },
+ [0x1D5F9]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D5F9,
+ visual="bf",
+ },
+ [0x1D5FA]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D5FA,
+ visual="bf",
+ },
+ [0x1D5FB]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D5FB,
+ visual="bf",
+ },
+ [0x1D5FC]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D5FC,
+ visual="bf",
+ },
+ [0x1D5FD]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D5FD,
+ visual="bf",
+ },
+ [0x1D5FE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D5FE,
+ visual="bf",
+ },
+ [0x1D5FF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D5FF,
+ visual="bf",
+ },
+ [0x1D600]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D600,
+ visual="bf",
+ },
+ [0x1D601]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D601,
+ visual="bf",
+ },
+ [0x1D602]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D602,
+ visual="bf",
+ },
+ [0x1D603]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D603,
+ visual="bf",
+ },
+ [0x1D604]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D604,
+ visual="bf",
+ },
+ [0x1D605]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D605,
+ visual="bf",
+ },
+ [0x1D606]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D606,
+ visual="bf",
+ },
+ [0x1D607]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D607,
+ visual="bf",
+ },
+ [0x1D608]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D608,
+ visual="it",
+ },
+ [0x1D609]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D609,
+ visual="it",
+ },
+ [0x1D60A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D60A,
+ visual="it",
+ },
+ [0x1D60B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D60B,
+ visual="it",
+ },
+ [0x1D60C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D60C,
+ visual="it",
+ },
+ [0x1D60D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D60D,
+ visual="it",
+ },
+ [0x1D60E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D60E,
+ visual="it",
+ },
+ [0x1D60F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D60F,
+ visual="it",
+ },
+ [0x1D610]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D610,
+ visual="it",
+ },
+ [0x1D611]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D611,
+ visual="it",
+ },
+ [0x1D612]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D612,
+ visual="it",
+ },
+ [0x1D613]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D613,
+ visual="it",
+ },
+ [0x1D614]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D614,
+ visual="it",
+ },
+ [0x1D615]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D615,
+ visual="it",
+ },
+ [0x1D616]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D616,
+ visual="it",
+ },
+ [0x1D617]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D617,
+ visual="it",
+ },
+ [0x1D618]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D618,
+ visual="it",
+ },
+ [0x1D619]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D619,
+ visual="it",
+ },
+ [0x1D61A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D61A,
+ visual="it",
+ },
+ [0x1D61B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D61B,
+ visual="it",
+ },
+ [0x1D61C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D61C,
+ visual="it",
+ },
+ [0x1D61D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D61D,
+ visual="it",
+ },
+ [0x1D61E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D61E,
+ visual="it",
+ },
+ [0x1D61F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D61F,
+ visual="it",
+ },
+ [0x1D620]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D620,
+ visual="it",
+ },
+ [0x1D621]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D621,
+ visual="it",
+ },
+ [0x1D622]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D622,
+ visual="it",
+ },
+ [0x1D623]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D623,
+ visual="it",
+ },
+ [0x1D624]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D624,
+ visual="it",
+ },
+ [0x1D625]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D625,
+ visual="it",
+ },
+ [0x1D626]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D626,
+ visual="it",
+ },
+ [0x1D627]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D627,
+ visual="it",
+ },
+ [0x1D628]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D628,
+ visual="it",
+ },
+ [0x1D629]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D629,
+ visual="it",
+ },
+ [0x1D62A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D62A,
+ visual="it",
+ },
+ [0x1D62B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D62B,
+ visual="it",
+ },
+ [0x1D62C]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D62C,
+ visual="it",
+ },
+ [0x1D62D]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D62D,
+ visual="it",
+ },
+ [0x1D62E]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D62E,
+ visual="it",
+ },
+ [0x1D62F]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D62F,
+ visual="it",
+ },
+ [0x1D630]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D630,
+ visual="it",
+ },
+ [0x1D631]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D631,
+ visual="it",
+ },
+ [0x1D632]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D632,
+ visual="it",
+ },
+ [0x1D633]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D633,
+ visual="it",
+ },
+ [0x1D634]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D634,
+ visual="it",
+ },
+ [0x1D635]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D635,
+ visual="it",
+ },
+ [0x1D636]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D636,
+ visual="it",
+ },
+ [0x1D637]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D637,
+ visual="it",
+ },
+ [0x1D638]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D638,
+ visual="it",
+ },
+ [0x1D639]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D639,
+ visual="it",
+ },
+ [0x1D63A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D63A,
+ visual="it",
+ },
+ [0x1D63B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF ITALIC SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D63B,
+ visual="it",
+ },
+ [0x1D63C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D63C,
+ visual="bi",
+ },
+ [0x1D63D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D63D,
+ visual="bi",
+ },
+ [0x1D63E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D63E,
+ visual="bi",
+ },
+ [0x1D63F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D63F,
+ visual="bi",
+ },
+ [0x1D640]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D640,
+ visual="bi",
+ },
+ [0x1D641]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D641,
+ visual="bi",
+ },
+ [0x1D642]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D642,
+ visual="bi",
+ },
+ [0x1D643]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D643,
+ visual="bi",
+ },
+ [0x1D644]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D644,
+ visual="bi",
+ },
+ [0x1D645]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D645,
+ visual="bi",
+ },
+ [0x1D646]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D646,
+ visual="bi",
+ },
+ [0x1D647]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D647,
+ visual="bi",
+ },
+ [0x1D648]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D648,
+ visual="bi",
+ },
+ [0x1D649]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D649,
+ visual="bi",
+ },
+ [0x1D64A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D64A,
+ visual="bi",
+ },
+ [0x1D64B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D64B,
+ visual="bi",
+ },
+ [0x1D64C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D64C,
+ visual="bi",
+ },
+ [0x1D64D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D64D,
+ visual="bi",
+ },
+ [0x1D64E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D64E,
+ visual="bi",
+ },
+ [0x1D64F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D64F,
+ visual="bi",
+ },
+ [0x1D650]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D650,
+ visual="bi",
+ },
+ [0x1D651]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D651,
+ visual="bi",
+ },
+ [0x1D652]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D652,
+ visual="bi",
+ },
+ [0x1D653]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D653,
+ visual="bi",
+ },
+ [0x1D654]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D654,
+ visual="bi",
+ },
+ [0x1D655]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D655,
+ visual="bi",
+ },
+ [0x1D656]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D656,
+ visual="bi",
+ },
+ [0x1D657]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D657,
+ visual="bi",
+ },
+ [0x1D658]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D658,
+ visual="bi",
+ },
+ [0x1D659]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D659,
+ visual="bi",
+ },
+ [0x1D65A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D65A,
+ visual="bi",
+ },
+ [0x1D65B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D65B,
+ visual="bi",
+ },
+ [0x1D65C]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D65C,
+ visual="bi",
+ },
+ [0x1D65D]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D65D,
+ visual="bi",
+ },
+ [0x1D65E]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D65E,
+ visual="bi",
+ },
+ [0x1D65F]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D65F,
+ visual="bi",
+ },
+ [0x1D660]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D660,
+ visual="bi",
+ },
+ [0x1D661]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D661,
+ visual="bi",
+ },
+ [0x1D662]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D662,
+ visual="bi",
+ },
+ [0x1D663]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D663,
+ visual="bi",
+ },
+ [0x1D664]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D664,
+ visual="bi",
+ },
+ [0x1D665]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D665,
+ visual="bi",
+ },
+ [0x1D666]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D666,
+ visual="bi",
+ },
+ [0x1D667]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D667,
+ visual="bi",
+ },
+ [0x1D668]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D668,
+ visual="bi",
+ },
+ [0x1D669]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D669,
+ visual="bi",
+ },
+ [0x1D66A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D66A,
+ visual="bi",
+ },
+ [0x1D66B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D66B,
+ visual="bi",
+ },
+ [0x1D66C]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D66C,
+ visual="bi",
+ },
+ [0x1D66D]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D66D,
+ visual="bi",
+ },
+ [0x1D66E]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D66E,
+ visual="bi",
+ },
+ [0x1D66F]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D66F,
+ visual="bi",
+ },
+ [0x1D670]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x41 },
+ unicodeslot=0x1D670,
+ },
+ [0x1D671]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x42 },
+ unicodeslot=0x1D671,
+ },
+ [0x1D672]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x43 },
+ unicodeslot=0x1D672,
+ },
+ [0x1D673]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x44 },
+ unicodeslot=0x1D673,
+ },
+ [0x1D674]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x45 },
+ unicodeslot=0x1D674,
+ },
+ [0x1D675]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x46 },
+ unicodeslot=0x1D675,
+ },
+ [0x1D676]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x47 },
+ unicodeslot=0x1D676,
+ },
+ [0x1D677]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x48 },
+ unicodeslot=0x1D677,
+ },
+ [0x1D678]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x49 },
+ unicodeslot=0x1D678,
+ },
+ [0x1D679]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4A },
+ unicodeslot=0x1D679,
+ },
+ [0x1D67A]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4B },
+ unicodeslot=0x1D67A,
+ },
+ [0x1D67B]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4C },
+ unicodeslot=0x1D67B,
+ },
+ [0x1D67C]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4D },
+ unicodeslot=0x1D67C,
+ },
+ [0x1D67D]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4E },
+ unicodeslot=0x1D67D,
+ },
+ [0x1D67E]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x4F },
+ unicodeslot=0x1D67E,
+ },
+ [0x1D67F]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x50 },
+ unicodeslot=0x1D67F,
+ },
+ [0x1D680]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x51 },
+ unicodeslot=0x1D680,
+ },
+ [0x1D681]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x52 },
+ unicodeslot=0x1D681,
+ },
+ [0x1D682]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x53 },
+ unicodeslot=0x1D682,
+ },
+ [0x1D683]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x54 },
+ unicodeslot=0x1D683,
+ },
+ [0x1D684]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x55 },
+ unicodeslot=0x1D684,
+ },
+ [0x1D685]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x56 },
+ unicodeslot=0x1D685,
+ },
+ [0x1D686]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x57 },
+ unicodeslot=0x1D686,
+ },
+ [0x1D687]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x58 },
+ unicodeslot=0x1D687,
+ },
+ [0x1D688]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x59 },
+ unicodeslot=0x1D688,
+ },
+ [0x1D689]={
+ category="lu",
+ description="MATHEMATICAL MONOSPACE CAPITAL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x5A },
+ unicodeslot=0x1D689,
+ },
+ [0x1D68A]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL A",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x61 },
+ unicodeslot=0x1D68A,
+ },
+ [0x1D68B]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL B",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x62 },
+ unicodeslot=0x1D68B,
+ },
+ [0x1D68C]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL C",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x63 },
+ unicodeslot=0x1D68C,
+ },
+ [0x1D68D]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL D",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x64 },
+ unicodeslot=0x1D68D,
+ },
+ [0x1D68E]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL E",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x65 },
+ unicodeslot=0x1D68E,
+ },
+ [0x1D68F]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL F",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x66 },
+ unicodeslot=0x1D68F,
+ },
+ [0x1D690]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL G",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x67 },
+ unicodeslot=0x1D690,
+ },
+ [0x1D691]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL H",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x68 },
+ unicodeslot=0x1D691,
+ },
+ [0x1D692]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL I",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x69 },
+ unicodeslot=0x1D692,
+ },
+ [0x1D693]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL J",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6A },
+ unicodeslot=0x1D693,
+ },
+ [0x1D694]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL K",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6B },
+ unicodeslot=0x1D694,
+ },
+ [0x1D695]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL L",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6C },
+ unicodeslot=0x1D695,
+ },
+ [0x1D696]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL M",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6D },
+ unicodeslot=0x1D696,
+ },
+ [0x1D697]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL N",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6E },
+ unicodeslot=0x1D697,
+ },
+ [0x1D698]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL O",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x6F },
+ unicodeslot=0x1D698,
+ },
+ [0x1D699]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL P",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x70 },
+ unicodeslot=0x1D699,
+ },
+ [0x1D69A]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL Q",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x71 },
+ unicodeslot=0x1D69A,
+ },
+ [0x1D69B]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL R",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x72 },
+ unicodeslot=0x1D69B,
+ },
+ [0x1D69C]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL S",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x73 },
+ unicodeslot=0x1D69C,
+ },
+ [0x1D69D]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL T",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x74 },
+ unicodeslot=0x1D69D,
+ },
+ [0x1D69E]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL U",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x75 },
+ unicodeslot=0x1D69E,
+ },
+ [0x1D69F]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL V",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x76 },
+ unicodeslot=0x1D69F,
+ },
+ [0x1D6A0]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL W",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x77 },
+ unicodeslot=0x1D6A0,
+ },
+ [0x1D6A1]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL X",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x78 },
+ unicodeslot=0x1D6A1,
+ },
+ [0x1D6A2]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL Y",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x79 },
+ unicodeslot=0x1D6A2,
+ },
+ [0x1D6A3]={
+ category="ll",
+ description="MATHEMATICAL MONOSPACE SMALL Z",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x7A },
+ unicodeslot=0x1D6A3,
+ },
+ [0x1D6A4]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL DOTLESS I",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="imath",
+ specials={ "font", 0x131 },
+ unicodeslot=0x1D6A4,
+ visual="it",
+ },
+ [0x1D6A5]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL DOTLESS J",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="jmath",
+ specials={ "font", 0x237 },
+ unicodeslot=0x1D6A5,
+ visual="it",
+ },
+ [0x1D6A8]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x391 },
+ unicodeslot=0x1D6A8,
+ visual="bf",
+ },
+ [0x1D6A9]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x392 },
+ unicodeslot=0x1D6A9,
+ visual="bf",
+ },
+ [0x1D6AA]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x1D6AA,
+ visual="bf",
+ },
+ [0x1D6AB]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x394 },
+ unicodeslot=0x1D6AB,
+ visual="bf",
+ },
+ [0x1D6AC]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x395 },
+ unicodeslot=0x1D6AC,
+ visual="bf",
+ },
+ [0x1D6AD]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x396 },
+ unicodeslot=0x1D6AD,
+ visual="bf",
+ },
+ [0x1D6AE]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x397 },
+ unicodeslot=0x1D6AE,
+ visual="bf",
+ },
+ [0x1D6AF]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x398 },
+ unicodeslot=0x1D6AF,
+ visual="bf",
+ },
+ [0x1D6B0]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x399 },
+ unicodeslot=0x1D6B0,
+ visual="bf",
+ },
+ [0x1D6B1]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39A },
+ unicodeslot=0x1D6B1,
+ visual="bf",
+ },
+ [0x1D6B2]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39B },
+ unicodeslot=0x1D6B2,
+ visual="bf",
+ },
+ [0x1D6B3]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39C },
+ unicodeslot=0x1D6B3,
+ visual="bf",
+ },
+ [0x1D6B4]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39D },
+ unicodeslot=0x1D6B4,
+ visual="bf",
+ },
+ [0x1D6B5]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39E },
+ unicodeslot=0x1D6B5,
+ visual="bf",
+ },
+ [0x1D6B6]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39F },
+ unicodeslot=0x1D6B6,
+ visual="bf",
+ },
+ [0x1D6B7]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x1D6B7,
+ visual="bf",
+ },
+ [0x1D6B8]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A1 },
+ unicodeslot=0x1D6B8,
+ visual="bf",
+ },
+ [0x1D6B9]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F4 },
+ unicodeslot=0x1D6B9,
+ visual="bf",
+ },
+ [0x1D6BA]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A3 },
+ unicodeslot=0x1D6BA,
+ visual="bf",
+ },
+ [0x1D6BB]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A4 },
+ unicodeslot=0x1D6BB,
+ visual="bf",
+ },
+ [0x1D6BC]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A5 },
+ unicodeslot=0x1D6BC,
+ visual="bf",
+ },
+ [0x1D6BD]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A6 },
+ unicodeslot=0x1D6BD,
+ visual="bf",
+ },
+ [0x1D6BE]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A7 },
+ unicodeslot=0x1D6BE,
+ visual="bf",
+ },
+ [0x1D6BF]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A8 },
+ unicodeslot=0x1D6BF,
+ visual="bf",
+ },
+ [0x1D6C0]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A9 },
+ unicodeslot=0x1D6C0,
+ visual="bf",
+ },
+ [0x1D6C1]={
+ category="sm",
+ description="MATHEMATICAL BOLD NABLA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x2207 },
+ unicodeslot=0x1D6C1,
+ visual="bf",
+ },
+ [0x1D6C2]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B1 },
+ unicodeslot=0x1D6C2,
+ visual="bf",
+ },
+ [0x1D6C3]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B2 },
+ unicodeslot=0x1D6C3,
+ visual="bf",
+ },
+ [0x1D6C4]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x1D6C4,
+ visual="bf",
+ },
+ [0x1D6C5]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B4 },
+ unicodeslot=0x1D6C5,
+ visual="bf",
+ },
+ [0x1D6C6]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B5 },
+ unicodeslot=0x1D6C6,
+ visual="bf",
+ },
+ [0x1D6C7]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B6 },
+ unicodeslot=0x1D6C7,
+ visual="bf",
+ },
+ [0x1D6C8]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B7 },
+ unicodeslot=0x1D6C8,
+ visual="bf",
+ },
+ [0x1D6C9]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B8 },
+ unicodeslot=0x1D6C9,
+ visual="bf",
+ },
+ [0x1D6CA]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B9 },
+ unicodeslot=0x1D6CA,
+ visual="bf",
+ },
+ [0x1D6CB]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BA },
+ unicodeslot=0x1D6CB,
+ visual="bf",
+ },
+ [0x1D6CC]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BB },
+ unicodeslot=0x1D6CC,
+ visual="bf",
+ },
+ [0x1D6CD]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BC },
+ unicodeslot=0x1D6CD,
+ visual="bf",
+ },
+ [0x1D6CE]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BD },
+ unicodeslot=0x1D6CE,
+ visual="bf",
+ },
+ [0x1D6CF]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BE },
+ unicodeslot=0x1D6CF,
+ visual="bf",
+ },
+ [0x1D6D0]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BF },
+ unicodeslot=0x1D6D0,
+ visual="bf",
+ },
+ [0x1D6D1]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x1D6D1,
+ visual="bf",
+ },
+ [0x1D6D2]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C1 },
+ unicodeslot=0x1D6D2,
+ visual="bf",
+ },
+ [0x1D6D3]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C2 },
+ unicodeslot=0x1D6D3,
+ visual="bf",
+ },
+ [0x1D6D4]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C3 },
+ unicodeslot=0x1D6D4,
+ visual="bf",
+ },
+ [0x1D6D5]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C4 },
+ unicodeslot=0x1D6D5,
+ visual="bf",
+ },
+ [0x1D6D6]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C5 },
+ unicodeslot=0x1D6D6,
+ visual="bf",
+ },
+ [0x1D6D7]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C6 },
+ unicodeslot=0x1D6D7,
+ visual="bf",
+ },
+ [0x1D6D8]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C7 },
+ unicodeslot=0x1D6D8,
+ visual="bf",
+ },
+ [0x1D6D9]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C8 },
+ unicodeslot=0x1D6D9,
+ visual="bf",
+ },
+ [0x1D6DA]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C9 },
+ unicodeslot=0x1D6DA,
+ visual="bf",
+ },
+ [0x1D6DB]={
+ category="sm",
+ description="MATHEMATICAL BOLD PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2202 },
+ unicodeslot=0x1D6DB,
+ visual="bf",
+ },
+ [0x1D6DC]={
+ category="ll",
+ description="MATHEMATICAL BOLD EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F5 },
+ unicodeslot=0x1D6DC,
+ visual="bf",
+ },
+ [0x1D6DD]={
+ category="ll",
+ description="MATHEMATICAL BOLD THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D1 },
+ unicodeslot=0x1D6DD,
+ visual="bf",
+ },
+ [0x1D6DE]={
+ category="ll",
+ description="MATHEMATICAL BOLD KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F0 },
+ unicodeslot=0x1D6DE,
+ visual="bf",
+ },
+ [0x1D6DF]={
+ category="ll",
+ description="MATHEMATICAL BOLD PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D5 },
+ unicodeslot=0x1D6DF,
+ visual="bf",
+ },
+ [0x1D6E0]={
+ category="ll",
+ description="MATHEMATICAL BOLD RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F1 },
+ unicodeslot=0x1D6E0,
+ visual="bf",
+ },
+ [0x1D6E1]={
+ category="ll",
+ description="MATHEMATICAL BOLD PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D6 },
+ unicodeslot=0x1D6E1,
+ visual="bf",
+ },
+ [0x1D6E2]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x391 },
+ unicodeslot=0x1D6E2,
+ visual="it",
+ },
+ [0x1D6E3]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x392 },
+ unicodeslot=0x1D6E3,
+ visual="it",
+ },
+ [0x1D6E4]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x1D6E4,
+ visual="it",
+ },
+ [0x1D6E5]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x394 },
+ unicodeslot=0x1D6E5,
+ visual="it",
+ },
+ [0x1D6E6]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x395 },
+ unicodeslot=0x1D6E6,
+ visual="it",
+ },
+ [0x1D6E7]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x396 },
+ unicodeslot=0x1D6E7,
+ visual="it",
+ },
+ [0x1D6E8]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x397 },
+ unicodeslot=0x1D6E8,
+ visual="it",
+ },
+ [0x1D6E9]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x398 },
+ unicodeslot=0x1D6E9,
+ visual="it",
+ },
+ [0x1D6EA]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x399 },
+ unicodeslot=0x1D6EA,
+ visual="it",
+ },
+ [0x1D6EB]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39A },
+ unicodeslot=0x1D6EB,
+ visual="it",
+ },
+ [0x1D6EC]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39B },
+ unicodeslot=0x1D6EC,
+ visual="it",
+ },
+ [0x1D6ED]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39C },
+ unicodeslot=0x1D6ED,
+ visual="it",
+ },
+ [0x1D6EE]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39D },
+ unicodeslot=0x1D6EE,
+ visual="it",
+ },
+ [0x1D6EF]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39E },
+ unicodeslot=0x1D6EF,
+ visual="it",
+ },
+ [0x1D6F0]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39F },
+ unicodeslot=0x1D6F0,
+ visual="it",
+ },
+ [0x1D6F1]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x1D6F1,
+ visual="it",
+ },
+ [0x1D6F2]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A1 },
+ unicodeslot=0x1D6F2,
+ visual="it",
+ },
+ [0x1D6F3]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F4 },
+ unicodeslot=0x1D6F3,
+ visual="it",
+ },
+ [0x1D6F4]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A3 },
+ unicodeslot=0x1D6F4,
+ visual="it",
+ },
+ [0x1D6F5]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A4 },
+ unicodeslot=0x1D6F5,
+ visual="it",
+ },
+ [0x1D6F6]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A5 },
+ unicodeslot=0x1D6F6,
+ visual="it",
+ },
+ [0x1D6F7]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A6 },
+ unicodeslot=0x1D6F7,
+ visual="it",
+ },
+ [0x1D6F8]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A7 },
+ unicodeslot=0x1D6F8,
+ visual="it",
+ },
+ [0x1D6F9]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A8 },
+ unicodeslot=0x1D6F9,
+ visual="it",
+ },
+ [0x1D6FA]={
+ category="lu",
+ description="MATHEMATICAL ITALIC CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A9 },
+ unicodeslot=0x1D6FA,
+ visual="it",
+ },
+ [0x1D6FB]={
+ category="sm",
+ description="MATHEMATICAL ITALIC NABLA",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ specials={ "font", 0x2207 },
+ unicodeslot=0x1D6FB,
+ visual="it",
+ },
+ [0x1D6FC]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B1 },
+ unicodeslot=0x1D6FC,
+ visual="it",
+ },
+ [0x1D6FD]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B2 },
+ unicodeslot=0x1D6FD,
+ visual="it",
+ },
+ [0x1D6FE]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x1D6FE,
+ visual="it",
+ },
+ [0x1D6FF]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B4 },
+ unicodeslot=0x1D6FF,
+ visual="it",
+ },
+ [0x1D700]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B5 },
+ unicodeslot=0x1D700,
+ visual="it",
+ },
+ [0x1D701]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B6 },
+ unicodeslot=0x1D701,
+ visual="it",
+ },
+ [0x1D702]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B7 },
+ unicodeslot=0x1D702,
+ visual="it",
+ },
+ [0x1D703]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B8 },
+ unicodeslot=0x1D703,
+ visual="it",
+ },
+ [0x1D704]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B9 },
+ unicodeslot=0x1D704,
+ visual="it",
+ },
+ [0x1D705]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BA },
+ unicodeslot=0x1D705,
+ visual="it",
+ },
+ [0x1D706]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BB },
+ unicodeslot=0x1D706,
+ visual="it",
+ },
+ [0x1D707]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BC },
+ unicodeslot=0x1D707,
+ visual="it",
+ },
+ [0x1D708]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BD },
+ unicodeslot=0x1D708,
+ visual="it",
+ },
+ [0x1D709]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BE },
+ unicodeslot=0x1D709,
+ visual="it",
+ },
+ [0x1D70A]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BF },
+ unicodeslot=0x1D70A,
+ visual="it",
+ },
+ [0x1D70B]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x1D70B,
+ visual="it",
+ },
+ [0x1D70C]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C1 },
+ unicodeslot=0x1D70C,
+ visual="it",
+ },
+ [0x1D70D]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C2 },
+ unicodeslot=0x1D70D,
+ visual="it",
+ },
+ [0x1D70E]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C3 },
+ unicodeslot=0x1D70E,
+ visual="it",
+ },
+ [0x1D70F]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C4 },
+ unicodeslot=0x1D70F,
+ visual="it",
+ },
+ [0x1D710]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C5 },
+ unicodeslot=0x1D710,
+ visual="it",
+ },
+ [0x1D711]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C6 },
+ unicodeslot=0x1D711,
+ visual="it",
+ },
+ [0x1D712]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C7 },
+ unicodeslot=0x1D712,
+ visual="it",
+ },
+ [0x1D713]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C8 },
+ unicodeslot=0x1D713,
+ visual="it",
+ },
+ [0x1D714]={
+ category="ll",
+ description="MATHEMATICAL ITALIC SMALL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C9 },
+ unicodeslot=0x1D714,
+ visual="it",
+ },
+ [0x1D715]={
+ category="sm",
+ description="MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2202 },
+ unicodeslot=0x1D715,
+ visual="it",
+ },
+ [0x1D716]={
+ category="ll",
+ description="MATHEMATICAL ITALIC EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F5 },
+ unicodeslot=0x1D716,
+ visual="it",
+ },
+ [0x1D717]={
+ category="ll",
+ description="MATHEMATICAL ITALIC THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="vartheta",
+ specials={ "font", 0x3D1 },
+ unicodeslot=0x1D717,
+ visual="it",
+ },
+ [0x1D718]={
+ category="ll",
+ description="MATHEMATICAL ITALIC KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="default",
+ mathname="varkappa",
+ specials={ "font", 0x3F0 },
+ unicodeslot=0x1D718,
+ visual="it",
+ },
+ [0x1D719]={
+ category="ll",
+ description="MATHEMATICAL ITALIC PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D5 },
+ unicodeslot=0x1D719,
+ visual="it",
+ },
+ [0x1D71A]={
+ category="ll",
+ description="MATHEMATICAL ITALIC RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ mathclass="variable",
+ mathname="varrho",
+ specials={ "font", 0x3F1 },
+ unicodeslot=0x1D71A,
+ visual="it",
+ },
+ [0x1D71B]={
+ category="ll",
+ description="MATHEMATICAL ITALIC PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D6 },
+ unicodeslot=0x1D71B,
+ visual="it",
+ },
+ [0x1D71C]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x391 },
+ unicodeslot=0x1D71C,
+ visual="bi",
+ },
+ [0x1D71D]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x392 },
+ unicodeslot=0x1D71D,
+ visual="bi",
+ },
+ [0x1D71E]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x1D71E,
+ visual="bi",
+ },
+ [0x1D71F]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x394 },
+ unicodeslot=0x1D71F,
+ visual="bi",
+ },
+ [0x1D720]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x395 },
+ unicodeslot=0x1D720,
+ visual="bi",
+ },
+ [0x1D721]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x396 },
+ unicodeslot=0x1D721,
+ visual="bi",
+ },
+ [0x1D722]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x397 },
+ unicodeslot=0x1D722,
+ visual="bi",
+ },
+ [0x1D723]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x398 },
+ unicodeslot=0x1D723,
+ visual="bi",
+ },
+ [0x1D724]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x399 },
+ unicodeslot=0x1D724,
+ visual="bi",
+ },
+ [0x1D725]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39A },
+ unicodeslot=0x1D725,
+ visual="bi",
+ },
+ [0x1D726]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39B },
+ unicodeslot=0x1D726,
+ visual="bi",
+ },
+ [0x1D727]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39C },
+ unicodeslot=0x1D727,
+ visual="bi",
+ },
+ [0x1D728]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39D },
+ unicodeslot=0x1D728,
+ visual="bi",
+ },
+ [0x1D729]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39E },
+ unicodeslot=0x1D729,
+ visual="bi",
+ },
+ [0x1D72A]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39F },
+ unicodeslot=0x1D72A,
+ visual="bi",
+ },
+ [0x1D72B]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x1D72B,
+ visual="bi",
+ },
+ [0x1D72C]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A1 },
+ unicodeslot=0x1D72C,
+ visual="bi",
+ },
+ [0x1D72D]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F4 },
+ unicodeslot=0x1D72D,
+ visual="bi",
+ },
+ [0x1D72E]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A3 },
+ unicodeslot=0x1D72E,
+ visual="bi",
+ },
+ [0x1D72F]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A4 },
+ unicodeslot=0x1D72F,
+ visual="bi",
+ },
+ [0x1D730]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A5 },
+ unicodeslot=0x1D730,
+ visual="bi",
+ },
+ [0x1D731]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A6 },
+ unicodeslot=0x1D731,
+ visual="bi",
+ },
+ [0x1D732]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A7 },
+ unicodeslot=0x1D732,
+ visual="bi",
+ },
+ [0x1D733]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A8 },
+ unicodeslot=0x1D733,
+ visual="bi",
+ },
+ [0x1D734]={
+ category="lu",
+ description="MATHEMATICAL BOLD ITALIC CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A9 },
+ unicodeslot=0x1D734,
+ visual="bi",
+ },
+ [0x1D735]={
+ category="sm",
+ description="MATHEMATICAL BOLD ITALIC NABLA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x2207 },
+ unicodeslot=0x1D735,
+ visual="bi",
+ },
+ [0x1D736]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B1 },
+ unicodeslot=0x1D736,
+ visual="bi",
+ },
+ [0x1D737]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B2 },
+ unicodeslot=0x1D737,
+ visual="bi",
+ },
+ [0x1D738]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x1D738,
+ visual="bi",
+ },
+ [0x1D739]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B4 },
+ unicodeslot=0x1D739,
+ visual="bi",
+ },
+ [0x1D73A]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B5 },
+ unicodeslot=0x1D73A,
+ visual="bi",
+ },
+ [0x1D73B]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B6 },
+ unicodeslot=0x1D73B,
+ visual="bi",
+ },
+ [0x1D73C]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B7 },
+ unicodeslot=0x1D73C,
+ visual="bi",
+ },
+ [0x1D73D]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B8 },
+ unicodeslot=0x1D73D,
+ visual="bi",
+ },
+ [0x1D73E]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B9 },
+ unicodeslot=0x1D73E,
+ visual="bi",
+ },
+ [0x1D73F]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BA },
+ unicodeslot=0x1D73F,
+ visual="bi",
+ },
+ [0x1D740]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BB },
+ unicodeslot=0x1D740,
+ visual="bi",
+ },
+ [0x1D741]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BC },
+ unicodeslot=0x1D741,
+ visual="bi",
+ },
+ [0x1D742]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BD },
+ unicodeslot=0x1D742,
+ visual="bi",
+ },
+ [0x1D743]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BE },
+ unicodeslot=0x1D743,
+ visual="bi",
+ },
+ [0x1D744]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BF },
+ unicodeslot=0x1D744,
+ visual="bi",
+ },
+ [0x1D745]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x1D745,
+ visual="bi",
+ },
+ [0x1D746]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C1 },
+ unicodeslot=0x1D746,
+ visual="bi",
+ },
+ [0x1D747]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C2 },
+ unicodeslot=0x1D747,
+ visual="bi",
+ },
+ [0x1D748]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C3 },
+ unicodeslot=0x1D748,
+ visual="bi",
+ },
+ [0x1D749]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C4 },
+ unicodeslot=0x1D749,
+ visual="bi",
+ },
+ [0x1D74A]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C5 },
+ unicodeslot=0x1D74A,
+ visual="bi",
+ },
+ [0x1D74B]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C6 },
+ unicodeslot=0x1D74B,
+ visual="bi",
+ },
+ [0x1D74C]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C7 },
+ unicodeslot=0x1D74C,
+ visual="bi",
+ },
+ [0x1D74D]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C8 },
+ unicodeslot=0x1D74D,
+ visual="bi",
+ },
+ [0x1D74E]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC SMALL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C9 },
+ unicodeslot=0x1D74E,
+ visual="bi",
+ },
+ [0x1D74F]={
+ category="sm",
+ description="MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2202 },
+ unicodeslot=0x1D74F,
+ visual="bi",
+ },
+ [0x1D750]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F5 },
+ unicodeslot=0x1D750,
+ visual="bi",
+ },
+ [0x1D751]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D1 },
+ unicodeslot=0x1D751,
+ visual="bi",
+ },
+ [0x1D752]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F0 },
+ unicodeslot=0x1D752,
+ visual="bi",
+ },
+ [0x1D753]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D5 },
+ unicodeslot=0x1D753,
+ visual="bi",
+ },
+ [0x1D754]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F1 },
+ unicodeslot=0x1D754,
+ visual="bi",
+ },
+ [0x1D755]={
+ category="ll",
+ description="MATHEMATICAL BOLD ITALIC PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D6 },
+ unicodeslot=0x1D755,
+ visual="bi",
+ },
+ [0x1D756]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x391 },
+ unicodeslot=0x1D756,
+ visual="bf",
+ },
+ [0x1D757]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x392 },
+ unicodeslot=0x1D757,
+ visual="bf",
+ },
+ [0x1D758]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x1D758,
+ visual="bf",
+ },
+ [0x1D759]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x394 },
+ unicodeslot=0x1D759,
+ visual="bf",
+ },
+ [0x1D75A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x395 },
+ unicodeslot=0x1D75A,
+ visual="bf",
+ },
+ [0x1D75B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x396 },
+ unicodeslot=0x1D75B,
+ visual="bf",
+ },
+ [0x1D75C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x397 },
+ unicodeslot=0x1D75C,
+ visual="bf",
+ },
+ [0x1D75D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x398 },
+ unicodeslot=0x1D75D,
+ visual="bf",
+ },
+ [0x1D75E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x399 },
+ unicodeslot=0x1D75E,
+ visual="bf",
+ },
+ [0x1D75F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39A },
+ unicodeslot=0x1D75F,
+ visual="bf",
+ },
+ [0x1D760]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39B },
+ unicodeslot=0x1D760,
+ visual="bf",
+ },
+ [0x1D761]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39C },
+ unicodeslot=0x1D761,
+ visual="bf",
+ },
+ [0x1D762]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39D },
+ unicodeslot=0x1D762,
+ visual="bf",
+ },
+ [0x1D763]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39E },
+ unicodeslot=0x1D763,
+ visual="bf",
+ },
+ [0x1D764]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39F },
+ unicodeslot=0x1D764,
+ visual="bf",
+ },
+ [0x1D765]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x1D765,
+ visual="bf",
+ },
+ [0x1D766]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A1 },
+ unicodeslot=0x1D766,
+ visual="bf",
+ },
+ [0x1D767]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F4 },
+ unicodeslot=0x1D767,
+ visual="bf",
+ },
+ [0x1D768]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A3 },
+ unicodeslot=0x1D768,
+ visual="bf",
+ },
+ [0x1D769]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A4 },
+ unicodeslot=0x1D769,
+ visual="bf",
+ },
+ [0x1D76A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A5 },
+ unicodeslot=0x1D76A,
+ visual="bf",
+ },
+ [0x1D76B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A6 },
+ unicodeslot=0x1D76B,
+ visual="bf",
+ },
+ [0x1D76C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A7 },
+ unicodeslot=0x1D76C,
+ visual="bf",
+ },
+ [0x1D76D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A8 },
+ unicodeslot=0x1D76D,
+ visual="bf",
+ },
+ [0x1D76E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A9 },
+ unicodeslot=0x1D76E,
+ visual="bf",
+ },
+ [0x1D76F]={
+ category="sm",
+ description="MATHEMATICAL SANS-SERIF BOLD NABLA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x2207 },
+ unicodeslot=0x1D76F,
+ visual="bf",
+ },
+ [0x1D770]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B1 },
+ unicodeslot=0x1D770,
+ visual="bf",
+ },
+ [0x1D771]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B2 },
+ unicodeslot=0x1D771,
+ visual="bf",
+ },
+ [0x1D772]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x1D772,
+ visual="bf",
+ },
+ [0x1D773]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B4 },
+ unicodeslot=0x1D773,
+ visual="bf",
+ },
+ [0x1D774]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B5 },
+ unicodeslot=0x1D774,
+ visual="bf",
+ },
+ [0x1D775]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B6 },
+ unicodeslot=0x1D775,
+ visual="bf",
+ },
+ [0x1D776]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B7 },
+ unicodeslot=0x1D776,
+ visual="bf",
+ },
+ [0x1D777]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B8 },
+ unicodeslot=0x1D777,
+ visual="bf",
+ },
+ [0x1D778]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B9 },
+ unicodeslot=0x1D778,
+ visual="bf",
+ },
+ [0x1D779]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BA },
+ unicodeslot=0x1D779,
+ visual="bf",
+ },
+ [0x1D77A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BB },
+ unicodeslot=0x1D77A,
+ visual="bf",
+ },
+ [0x1D77B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BC },
+ unicodeslot=0x1D77B,
+ visual="bf",
+ },
+ [0x1D77C]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BD },
+ unicodeslot=0x1D77C,
+ visual="bf",
+ },
+ [0x1D77D]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BE },
+ unicodeslot=0x1D77D,
+ visual="bf",
+ },
+ [0x1D77E]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BF },
+ unicodeslot=0x1D77E,
+ visual="bf",
+ },
+ [0x1D77F]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x1D77F,
+ visual="bf",
+ },
+ [0x1D780]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C1 },
+ unicodeslot=0x1D780,
+ visual="bf",
+ },
+ [0x1D781]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C2 },
+ unicodeslot=0x1D781,
+ visual="bf",
+ },
+ [0x1D782]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C3 },
+ unicodeslot=0x1D782,
+ visual="bf",
+ },
+ [0x1D783]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C4 },
+ unicodeslot=0x1D783,
+ visual="bf",
+ },
+ [0x1D784]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C5 },
+ unicodeslot=0x1D784,
+ visual="bf",
+ },
+ [0x1D785]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C6 },
+ unicodeslot=0x1D785,
+ visual="bf",
+ },
+ [0x1D786]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C7 },
+ unicodeslot=0x1D786,
+ visual="bf",
+ },
+ [0x1D787]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C8 },
+ unicodeslot=0x1D787,
+ visual="bf",
+ },
+ [0x1D788]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C9 },
+ unicodeslot=0x1D788,
+ visual="bf",
+ },
+ [0x1D789]={
+ category="sm",
+ description="MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2202 },
+ unicodeslot=0x1D789,
+ visual="bf",
+ },
+ [0x1D78A]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F5 },
+ unicodeslot=0x1D78A,
+ visual="bf",
+ },
+ [0x1D78B]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D1 },
+ unicodeslot=0x1D78B,
+ visual="bf",
+ },
+ [0x1D78C]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F0 },
+ unicodeslot=0x1D78C,
+ visual="bf",
+ },
+ [0x1D78D]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D5 },
+ unicodeslot=0x1D78D,
+ visual="bf",
+ },
+ [0x1D78E]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F1 },
+ unicodeslot=0x1D78E,
+ visual="bf",
+ },
+ [0x1D78F]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D6 },
+ unicodeslot=0x1D78F,
+ visual="bf",
+ },
+ [0x1D790]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x391 },
+ unicodeslot=0x1D790,
+ visual="bi",
+ },
+ [0x1D791]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x392 },
+ unicodeslot=0x1D791,
+ visual="bi",
+ },
+ [0x1D792]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x393 },
+ unicodeslot=0x1D792,
+ visual="bi",
+ },
+ [0x1D793]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x394 },
+ unicodeslot=0x1D793,
+ visual="bi",
+ },
+ [0x1D794]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x395 },
+ unicodeslot=0x1D794,
+ visual="bi",
+ },
+ [0x1D795]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x396 },
+ unicodeslot=0x1D795,
+ visual="bi",
+ },
+ [0x1D796]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x397 },
+ unicodeslot=0x1D796,
+ visual="bi",
+ },
+ [0x1D797]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x398 },
+ unicodeslot=0x1D797,
+ visual="bi",
+ },
+ [0x1D798]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x399 },
+ unicodeslot=0x1D798,
+ visual="bi",
+ },
+ [0x1D799]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39A },
+ unicodeslot=0x1D799,
+ visual="bi",
+ },
+ [0x1D79A]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39B },
+ unicodeslot=0x1D79A,
+ visual="bi",
+ },
+ [0x1D79B]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39C },
+ unicodeslot=0x1D79B,
+ visual="bi",
+ },
+ [0x1D79C]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39D },
+ unicodeslot=0x1D79C,
+ visual="bi",
+ },
+ [0x1D79D]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39E },
+ unicodeslot=0x1D79D,
+ visual="bi",
+ },
+ [0x1D79E]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x39F },
+ unicodeslot=0x1D79E,
+ visual="bi",
+ },
+ [0x1D79F]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A0 },
+ unicodeslot=0x1D79F,
+ visual="bi",
+ },
+ [0x1D7A0]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A1 },
+ unicodeslot=0x1D7A0,
+ visual="bi",
+ },
+ [0x1D7A1]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F4 },
+ unicodeslot=0x1D7A1,
+ visual="bi",
+ },
+ [0x1D7A2]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A3 },
+ unicodeslot=0x1D7A2,
+ visual="bi",
+ },
+ [0x1D7A3]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A4 },
+ unicodeslot=0x1D7A3,
+ visual="bi",
+ },
+ [0x1D7A4]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A5 },
+ unicodeslot=0x1D7A4,
+ visual="bi",
+ },
+ [0x1D7A5]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A6 },
+ unicodeslot=0x1D7A5,
+ visual="bi",
+ },
+ [0x1D7A6]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A7 },
+ unicodeslot=0x1D7A6,
+ visual="bi",
+ },
+ [0x1D7A7]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A8 },
+ unicodeslot=0x1D7A7,
+ visual="bi",
+ },
+ [0x1D7A8]={
+ category="lu",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3A9 },
+ unicodeslot=0x1D7A8,
+ visual="bi",
+ },
+ [0x1D7A9]={
+ category="sm",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x2207 },
+ unicodeslot=0x1D7A9,
+ visual="bi",
+ },
+ [0x1D7AA]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B1 },
+ unicodeslot=0x1D7AA,
+ visual="bi",
+ },
+ [0x1D7AB]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B2 },
+ unicodeslot=0x1D7AB,
+ visual="bi",
+ },
+ [0x1D7AC]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B3 },
+ unicodeslot=0x1D7AC,
+ visual="bi",
+ },
+ [0x1D7AD]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B4 },
+ unicodeslot=0x1D7AD,
+ visual="bi",
+ },
+ [0x1D7AE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B5 },
+ unicodeslot=0x1D7AE,
+ visual="bi",
+ },
+ [0x1D7AF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B6 },
+ unicodeslot=0x1D7AF,
+ visual="bi",
+ },
+ [0x1D7B0]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B7 },
+ unicodeslot=0x1D7B0,
+ visual="bi",
+ },
+ [0x1D7B1]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B8 },
+ unicodeslot=0x1D7B1,
+ visual="bi",
+ },
+ [0x1D7B2]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3B9 },
+ unicodeslot=0x1D7B2,
+ visual="bi",
+ },
+ [0x1D7B3]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BA },
+ unicodeslot=0x1D7B3,
+ visual="bi",
+ },
+ [0x1D7B4]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BB },
+ unicodeslot=0x1D7B4,
+ visual="bi",
+ },
+ [0x1D7B5]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BC },
+ unicodeslot=0x1D7B5,
+ visual="bi",
+ },
+ [0x1D7B6]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BD },
+ unicodeslot=0x1D7B6,
+ visual="bi",
+ },
+ [0x1D7B7]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BE },
+ unicodeslot=0x1D7B7,
+ visual="bi",
+ },
+ [0x1D7B8]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3BF },
+ unicodeslot=0x1D7B8,
+ visual="bi",
+ },
+ [0x1D7B9]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C0 },
+ unicodeslot=0x1D7B9,
+ visual="bi",
+ },
+ [0x1D7BA]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C1 },
+ unicodeslot=0x1D7BA,
+ visual="bi",
+ },
+ [0x1D7BB]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C2 },
+ unicodeslot=0x1D7BB,
+ visual="bi",
+ },
+ [0x1D7BC]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C3 },
+ unicodeslot=0x1D7BC,
+ visual="bi",
+ },
+ [0x1D7BD]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C4 },
+ unicodeslot=0x1D7BD,
+ visual="bi",
+ },
+ [0x1D7BE]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C5 },
+ unicodeslot=0x1D7BE,
+ visual="bi",
+ },
+ [0x1D7BF]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C6 },
+ unicodeslot=0x1D7BF,
+ visual="bi",
+ },
+ [0x1D7C0]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C7 },
+ unicodeslot=0x1D7C0,
+ visual="bi",
+ },
+ [0x1D7C1]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C8 },
+ unicodeslot=0x1D7C1,
+ visual="bi",
+ },
+ [0x1D7C2]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3C9 },
+ unicodeslot=0x1D7C2,
+ visual="bi",
+ },
+ [0x1D7C3]={
+ category="sm",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL",
+ direction="on",
+ linebreak="al",
+ specials={ "font", 0x2202 },
+ unicodeslot=0x1D7C3,
+ visual="bi",
+ },
+ [0x1D7C4]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F5 },
+ unicodeslot=0x1D7C4,
+ visual="bi",
+ },
+ [0x1D7C5]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D1 },
+ unicodeslot=0x1D7C5,
+ visual="bi",
+ },
+ [0x1D7C6]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F0 },
+ unicodeslot=0x1D7C6,
+ visual="bi",
+ },
+ [0x1D7C7]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D5 },
+ unicodeslot=0x1D7C7,
+ visual="bi",
+ },
+ [0x1D7C8]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3F1 },
+ unicodeslot=0x1D7C8,
+ visual="bi",
+ },
+ [0x1D7C9]={
+ category="ll",
+ description="MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3D6 },
+ unicodeslot=0x1D7C9,
+ visual="bi",
+ },
+ [0x1D7CA]={
+ category="lu",
+ description="MATHEMATICAL BOLD CAPITAL DIGAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3DC },
+ unicodeslot=0x1D7CA,
+ visual="bf",
+ },
+ [0x1D7CB]={
+ category="ll",
+ description="MATHEMATICAL BOLD SMALL DIGAMMA",
+ direction="l",
+ linebreak="al",
+ specials={ "font", 0x3DD },
+ unicodeslot=0x1D7CB,
+ visual="bf",
+ },
+ [0x1D7CE]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x30 },
+ unicodeslot=0x1D7CE,
+ visual="bf",
+ },
+ [0x1D7CF]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x31 },
+ unicodeslot=0x1D7CF,
+ visual="bf",
+ },
+ [0x1D7D0]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x32 },
+ unicodeslot=0x1D7D0,
+ visual="bf",
+ },
+ [0x1D7D1]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x33 },
+ unicodeslot=0x1D7D1,
+ visual="bf",
+ },
+ [0x1D7D2]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x34 },
+ unicodeslot=0x1D7D2,
+ visual="bf",
+ },
+ [0x1D7D3]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x35 },
+ unicodeslot=0x1D7D3,
+ visual="bf",
+ },
+ [0x1D7D4]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x36 },
+ unicodeslot=0x1D7D4,
+ visual="bf",
+ },
+ [0x1D7D5]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x37 },
+ unicodeslot=0x1D7D5,
+ visual="bf",
+ },
+ [0x1D7D6]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x38 },
+ unicodeslot=0x1D7D6,
+ visual="bf",
+ },
+ [0x1D7D7]={
+ category="nd",
+ description="MATHEMATICAL BOLD DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x39 },
+ unicodeslot=0x1D7D7,
+ visual="bf",
+ },
+ [0x1D7D8]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x30 },
+ unicodeslot=0x1D7D8,
+ },
+ [0x1D7D9]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x31 },
+ unicodeslot=0x1D7D9,
+ },
+ [0x1D7DA]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x32 },
+ unicodeslot=0x1D7DA,
+ },
+ [0x1D7DB]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x33 },
+ unicodeslot=0x1D7DB,
+ },
+ [0x1D7DC]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x34 },
+ unicodeslot=0x1D7DC,
+ },
+ [0x1D7DD]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x35 },
+ unicodeslot=0x1D7DD,
+ },
+ [0x1D7DE]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x36 },
+ unicodeslot=0x1D7DE,
+ },
+ [0x1D7DF]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x37 },
+ unicodeslot=0x1D7DF,
+ },
+ [0x1D7E0]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x38 },
+ unicodeslot=0x1D7E0,
+ },
+ [0x1D7E1]={
+ category="nd",
+ description="MATHEMATICAL DOUBLE-STRUCK DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x39 },
+ unicodeslot=0x1D7E1,
+ },
+ [0x1D7E2]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x30 },
+ unicodeslot=0x1D7E2,
+ },
+ [0x1D7E3]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x31 },
+ unicodeslot=0x1D7E3,
+ },
+ [0x1D7E4]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x32 },
+ unicodeslot=0x1D7E4,
+ },
+ [0x1D7E5]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x33 },
+ unicodeslot=0x1D7E5,
+ },
+ [0x1D7E6]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x34 },
+ unicodeslot=0x1D7E6,
+ },
+ [0x1D7E7]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x35 },
+ unicodeslot=0x1D7E7,
+ },
+ [0x1D7E8]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x36 },
+ unicodeslot=0x1D7E8,
+ },
+ [0x1D7E9]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x37 },
+ unicodeslot=0x1D7E9,
+ },
+ [0x1D7EA]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x38 },
+ unicodeslot=0x1D7EA,
+ },
+ [0x1D7EB]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x39 },
+ unicodeslot=0x1D7EB,
+ },
+ [0x1D7EC]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x30 },
+ unicodeslot=0x1D7EC,
+ visual="bf",
+ },
+ [0x1D7ED]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x31 },
+ unicodeslot=0x1D7ED,
+ visual="bf",
+ },
+ [0x1D7EE]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x32 },
+ unicodeslot=0x1D7EE,
+ visual="bf",
+ },
+ [0x1D7EF]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x33 },
+ unicodeslot=0x1D7EF,
+ visual="bf",
+ },
+ [0x1D7F0]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x34 },
+ unicodeslot=0x1D7F0,
+ visual="bf",
+ },
+ [0x1D7F1]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x35 },
+ unicodeslot=0x1D7F1,
+ visual="bf",
+ },
+ [0x1D7F2]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x36 },
+ unicodeslot=0x1D7F2,
+ visual="bf",
+ },
+ [0x1D7F3]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x37 },
+ unicodeslot=0x1D7F3,
+ visual="bf",
+ },
+ [0x1D7F4]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x38 },
+ unicodeslot=0x1D7F4,
+ visual="bf",
+ },
+ [0x1D7F5]={
+ category="nd",
+ description="MATHEMATICAL SANS-SERIF BOLD DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x39 },
+ unicodeslot=0x1D7F5,
+ visual="bf",
+ },
+ [0x1D7F6]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT ZERO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x30 },
+ unicodeslot=0x1D7F6,
+ },
+ [0x1D7F7]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT ONE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x31 },
+ unicodeslot=0x1D7F7,
+ },
+ [0x1D7F8]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT TWO",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x32 },
+ unicodeslot=0x1D7F8,
+ },
+ [0x1D7F9]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT THREE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x33 },
+ unicodeslot=0x1D7F9,
+ },
+ [0x1D7FA]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT FOUR",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x34 },
+ unicodeslot=0x1D7FA,
+ },
+ [0x1D7FB]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT FIVE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x35 },
+ unicodeslot=0x1D7FB,
+ },
+ [0x1D7FC]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT SIX",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x36 },
+ unicodeslot=0x1D7FC,
+ },
+ [0x1D7FD]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT SEVEN",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x37 },
+ unicodeslot=0x1D7FD,
+ },
+ [0x1D7FE]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT EIGHT",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x38 },
+ unicodeslot=0x1D7FE,
+ },
+ [0x1D7FF]={
+ category="nd",
+ description="MATHEMATICAL MONOSPACE DIGIT NINE",
+ direction="en",
+ linebreak="nu",
+ specials={ "font", 0x39 },
+ unicodeslot=0x1D7FF,
+ },
+ [0x1D800]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D800,
+ },
+ [0x1D801]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D801,
+ },
+ [0x1D802]={
+ category="so",
+ description="SIGNWRITING HAND-CUP INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D802,
+ },
+ [0x1D803]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D803,
+ },
+ [0x1D804]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D804,
+ },
+ [0x1D805]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D805,
+ },
+ [0x1D806]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D806,
+ },
+ [0x1D807]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D807,
+ },
+ [0x1D808]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB UNDER INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D808,
+ },
+ [0x1D809]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX RAISED KNUCKLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D809,
+ },
+ [0x1D80A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX CUPPED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80A,
+ },
+ [0x1D80B]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80B,
+ },
+ [0x1D80C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX HINGED LOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80C,
+ },
+ [0x1D80D]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX HINGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80D,
+ },
+ [0x1D80E]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80E,
+ },
+ [0x1D80F]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D80F,
+ },
+ [0x1D810]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D810,
+ },
+ [0x1D811]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE RAISED KNUCKLES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D811,
+ },
+ [0x1D812]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D812,
+ },
+ [0x1D813]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D813,
+ },
+ [0x1D814]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D814,
+ },
+ [0x1D815]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D815,
+ },
+ [0x1D816]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D816,
+ },
+ [0x1D817]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED MIDDLE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D817,
+ },
+ [0x1D818]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D818,
+ },
+ [0x1D819]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D819,
+ },
+ [0x1D81A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81A,
+ },
+ [0x1D81B]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSSED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81B,
+ },
+ [0x1D81C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE BENT OVER INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81C,
+ },
+ [0x1D81D]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX BENT OVER MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81D,
+ },
+ [0x1D81E]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81E,
+ },
+ [0x1D81F]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D81F,
+ },
+ [0x1D820]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE STRAIGHT THUMB BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D820,
+ },
+ [0x1D821]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE BENT THUMB STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D821,
+ },
+ [0x1D822]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D822,
+ },
+ [0x1D823]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE HINGED SPREAD THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D823,
+ },
+ [0x1D824]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D824,
+ },
+ [0x1D825]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D825,
+ },
+ [0x1D826]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D826,
+ },
+ [0x1D827]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE UP SPREAD THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D827,
+ },
+ [0x1D828]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CUPPED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D828,
+ },
+ [0x1D829]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CIRCLED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D829,
+ },
+ [0x1D82A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HOOKED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82A,
+ },
+ [0x1D82B]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82B,
+ },
+ [0x1D82C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82C,
+ },
+ [0x1D82D]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82D,
+ },
+ [0x1D82E]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82E,
+ },
+ [0x1D82F]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D82F,
+ },
+ [0x1D830]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB HOOKED INDEX UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D830,
+ },
+ [0x1D831]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D831,
+ },
+ [0x1D832]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D832,
+ },
+ [0x1D833]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D833,
+ },
+ [0x1D834]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D834,
+ },
+ [0x1D835]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D835,
+ },
+ [0x1D836]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB CUPPED INDEX UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D836,
+ },
+ [0x1D837]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CUPPED MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D837,
+ },
+ [0x1D838]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D838,
+ },
+ [0x1D839]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D839,
+ },
+ [0x1D83A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB ANGLED OUT MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83A,
+ },
+ [0x1D83B]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB ANGLED IN MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83B,
+ },
+ [0x1D83C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CIRCLED MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83C,
+ },
+ [0x1D83D]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CONJOINED HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83D,
+ },
+ [0x1D83E]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83E,
+ },
+ [0x1D83F]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D83F,
+ },
+ [0x1D840]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D840,
+ },
+ [0x1D841]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX CROSSED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D841,
+ },
+ [0x1D842]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED INDEX UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D842,
+ },
+ [0x1D843]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D843,
+ },
+ [0x1D844]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FOUR FINGERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D844,
+ },
+ [0x1D845]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FOUR FINGERS BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D845,
+ },
+ [0x1D846]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FOUR FINGERS HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D846,
+ },
+ [0x1D847]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D847,
+ },
+ [0x1D848]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED SPLIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D848,
+ },
+ [0x1D849]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW FOUR FINGERS CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D849,
+ },
+ [0x1D84A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST FOUR FINGERS CONJOINED BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84A,
+ },
+ [0x1D84B]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE FOUR FINGERS CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84B,
+ },
+ [0x1D84C]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84C,
+ },
+ [0x1D84D]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84D,
+ },
+ [0x1D84E]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD FOUR BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84E,
+ },
+ [0x1D84F]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD FOUR BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D84F,
+ },
+ [0x1D850]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D850,
+ },
+ [0x1D851]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D851,
+ },
+ [0x1D852]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D852,
+ },
+ [0x1D853]={
+ category="so",
+ description="SIGNWRITING HAND-CUP FIVE FINGERS SPREAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D853,
+ },
+ [0x1D854]={
+ category="so",
+ description="SIGNWRITING HAND-CUP FIVE FINGERS SPREAD OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D854,
+ },
+ [0x1D855]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE FIVE FINGERS SPREAD OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D855,
+ },
+ [0x1D856]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL FIVE FINGERS SPREAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D856,
+ },
+ [0x1D857]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D857,
+ },
+ [0x1D858]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D858,
+ },
+ [0x1D859]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D859,
+ },
+ [0x1D85A]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85A,
+ },
+ [0x1D85B]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT BETWEEN PALM FACINGS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85B,
+ },
+ [0x1D85C]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT HEEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85C,
+ },
+ [0x1D85D]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85D,
+ },
+ [0x1D85E]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT HEEL THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85E,
+ },
+ [0x1D85F]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT THUMB BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D85F,
+ },
+ [0x1D860]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D860,
+ },
+ [0x1D861]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT SPLIT INDEX THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D861,
+ },
+ [0x1D862]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT SPLIT CENTRE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D862,
+ },
+ [0x1D863]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D863,
+ },
+ [0x1D864]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D864,
+ },
+ [0x1D865]={
+ category="so",
+ description="SIGNWRITING HAND-FLAT SPLIT LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D865,
+ },
+ [0x1D866]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D866,
+ },
+ [0x1D867]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D867,
+ },
+ [0x1D868]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D868,
+ },
+ [0x1D869]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D869,
+ },
+ [0x1D86A]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK CURLICUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86A,
+ },
+ [0x1D86B]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86B,
+ },
+ [0x1D86C]={
+ category="so",
+ description="SIGNWRITING HAND-CUP OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86C,
+ },
+ [0x1D86D]={
+ category="so",
+ description="SIGNWRITING HAND-CUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86D,
+ },
+ [0x1D86E]={
+ category="so",
+ description="SIGNWRITING HAND-CUP OPEN THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86E,
+ },
+ [0x1D86F]={
+ category="so",
+ description="SIGNWRITING HAND-CUP THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D86F,
+ },
+ [0x1D870]={
+ category="so",
+ description="SIGNWRITING HAND-CUP OPEN NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D870,
+ },
+ [0x1D871]={
+ category="so",
+ description="SIGNWRITING HAND-CUP NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D871,
+ },
+ [0x1D872]={
+ category="so",
+ description="SIGNWRITING HAND-CUP OPEN THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D872,
+ },
+ [0x1D873]={
+ category="so",
+ description="SIGNWRITING HAND-CUP THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D873,
+ },
+ [0x1D874]={
+ category="so",
+ description="SIGNWRITING HAND-CURLICUE OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D874,
+ },
+ [0x1D875]={
+ category="so",
+ description="SIGNWRITING HAND-CURLICUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D875,
+ },
+ [0x1D876]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D876,
+ },
+ [0x1D877]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D877,
+ },
+ [0x1D878]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D878,
+ },
+ [0x1D879]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D879,
+ },
+ [0x1D87A]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87A,
+ },
+ [0x1D87B]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87B,
+ },
+ [0x1D87C]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE OPEN THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87C,
+ },
+ [0x1D87D]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87D,
+ },
+ [0x1D87E]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87E,
+ },
+ [0x1D87F]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE OPEN THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D87F,
+ },
+ [0x1D880]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D880,
+ },
+ [0x1D881]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE OPEN NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D881,
+ },
+ [0x1D882]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE NO THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D882,
+ },
+ [0x1D883]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE THUMB SIDE TOUCHING INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D883,
+ },
+ [0x1D884]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE THUMB BETWEEN MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D884,
+ },
+ [0x1D885]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D885,
+ },
+ [0x1D886]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D886,
+ },
+ [0x1D887]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D887,
+ },
+ [0x1D888]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D888,
+ },
+ [0x1D889]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D889,
+ },
+ [0x1D88A]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88A,
+ },
+ [0x1D88B]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE RING BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88B,
+ },
+ [0x1D88C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE RING CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88C,
+ },
+ [0x1D88D]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX MIDDLE RING CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88D,
+ },
+ [0x1D88E]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88E,
+ },
+ [0x1D88F]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D88F,
+ },
+ [0x1D890]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE CURVED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D890,
+ },
+ [0x1D891]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE DOWN OTHERS CIRCLED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D891,
+ },
+ [0x1D892]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D892,
+ },
+ [0x1D893]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB UNDER LITTLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D893,
+ },
+ [0x1D894]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE LITTLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D894,
+ },
+ [0x1D895]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL LITTLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D895,
+ },
+ [0x1D896]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE LITTLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D896,
+ },
+ [0x1D897]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE RAISED KNUCKLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D897,
+ },
+ [0x1D898]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D898,
+ },
+ [0x1D899]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE TOUCHES THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D899,
+ },
+ [0x1D89A]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89A,
+ },
+ [0x1D89B]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE LITTLE THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89B,
+ },
+ [0x1D89C]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89C,
+ },
+ [0x1D89D]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE LITTLE INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89D,
+ },
+ [0x1D89E]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89E,
+ },
+ [0x1D89F]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D89F,
+ },
+ [0x1D8A0]={
+ category="so",
+ description="SIGNWRITING HAND-FIST LITTLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A0,
+ },
+ [0x1D8A1]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE LITTLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A1,
+ },
+ [0x1D8A2]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE LITTLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A2,
+ },
+ [0x1D8A3]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE LITTLE INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A3,
+ },
+ [0x1D8A4]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A4,
+ },
+ [0x1D8A5]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A5,
+ },
+ [0x1D8A6]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX MIDDLE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A6,
+ },
+ [0x1D8A7]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A7,
+ },
+ [0x1D8A8]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX MIDDLE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A8,
+ },
+ [0x1D8A9]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX MIDDLE CROSS LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8A9,
+ },
+ [0x1D8AA]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSS LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AA,
+ },
+ [0x1D8AB]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AB,
+ },
+ [0x1D8AC]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE RING DOWN INDEX THUMB HOOK MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AC,
+ },
+ [0x1D8AD]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE RING DOWN MIDDLE THUMB INDEX CROSS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AD,
+ },
+ [0x1D8AE]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AE,
+ },
+ [0x1D8AF]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING RAISED KNUCKLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8AF,
+ },
+ [0x1D8B0]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B0,
+ },
+ [0x1D8B1]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B1,
+ },
+ [0x1D8B2]={
+ category="so",
+ description="SIGNWRITING HAND-OVAL RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B2,
+ },
+ [0x1D8B3]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B3,
+ },
+ [0x1D8B4]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B4,
+ },
+ [0x1D8B5]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING MIDDLE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B5,
+ },
+ [0x1D8B6]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING MIDDLE RAISED KNUCKLES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B6,
+ },
+ [0x1D8B7]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING INDEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B7,
+ },
+ [0x1D8B8]={
+ category="so",
+ description="SIGNWRITING HAND-FIST RING THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B8,
+ },
+ [0x1D8B9]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK RING THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8B9,
+ },
+ [0x1D8BA]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BA,
+ },
+ [0x1D8BB]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE INDEX RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BB,
+ },
+ [0x1D8BC]={
+ category="so",
+ description="SIGNWRITING HAND-CURLICUE INDEX RING LITTLE ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BC,
+ },
+ [0x1D8BD]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK INDEX RING LITTLE OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BD,
+ },
+ [0x1D8BE]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK INDEX RING LITTLE IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BE,
+ },
+ [0x1D8BF]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK INDEX RING LITTLE UNDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8BF,
+ },
+ [0x1D8C0]={
+ category="so",
+ description="SIGNWRITING HAND-CUP INDEX RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C0,
+ },
+ [0x1D8C1]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C1,
+ },
+ [0x1D8C2]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX RING LITTLE OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C2,
+ },
+ [0x1D8C3]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C3,
+ },
+ [0x1D8C4]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE DOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C4,
+ },
+ [0x1D8C5]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C5,
+ },
+ [0x1D8C6]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C6,
+ },
+ [0x1D8C7]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE MIDDLE UP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C7,
+ },
+ [0x1D8C8]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE RAISED KNUCKLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C8,
+ },
+ [0x1D8C9]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE UP THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8C9,
+ },
+ [0x1D8CA]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK MIDDLE THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CA,
+ },
+ [0x1D8CB]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE THUMB LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CB,
+ },
+ [0x1D8CC]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CC,
+ },
+ [0x1D8CD]={
+ category="so",
+ description="SIGNWRITING HAND-FIST MIDDLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CD,
+ },
+ [0x1D8CE]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CE,
+ },
+ [0x1D8CF]={
+ category="so",
+ description="SIGNWRITING HAND-CURLICUE MIDDLE RING LITTLE ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8CF,
+ },
+ [0x1D8D0]={
+ category="so",
+ description="SIGNWRITING HAND-CUP MIDDLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D0,
+ },
+ [0x1D8D1]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE MIDDLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D1,
+ },
+ [0x1D8D2]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D2,
+ },
+ [0x1D8D3]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D3,
+ },
+ [0x1D8D4]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D4,
+ },
+ [0x1D8D5]={
+ category="so",
+ description="SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D5,
+ },
+ [0x1D8D6]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D6,
+ },
+ [0x1D8D7]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D7,
+ },
+ [0x1D8D8]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D8,
+ },
+ [0x1D8D9]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8D9,
+ },
+ [0x1D8DA]={
+ category="so",
+ description="SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DA,
+ },
+ [0x1D8DB]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX HINGED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DB,
+ },
+ [0x1D8DC]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DC,
+ },
+ [0x1D8DD]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX THUMB SIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DD,
+ },
+ [0x1D8DE]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB DIAGONAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DE,
+ },
+ [0x1D8DF]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8DF,
+ },
+ [0x1D8E0]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E0,
+ },
+ [0x1D8E1]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E1,
+ },
+ [0x1D8E2]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE BOTH BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E2,
+ },
+ [0x1D8E3]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX HINGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E3,
+ },
+ [0x1D8E4]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E4,
+ },
+ [0x1D8E5]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E5,
+ },
+ [0x1D8E6]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E6,
+ },
+ [0x1D8E7]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CURLICUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E7,
+ },
+ [0x1D8E8]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB INSIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E8,
+ },
+ [0x1D8E9]={
+ category="so",
+ description="SIGNWRITING HAND-CLAW INDEX THUMB CURVE THUMB INSIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8E9,
+ },
+ [0x1D8EA]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB UNDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8EA,
+ },
+ [0x1D8EB]={
+ category="so",
+ description="SIGNWRITING HAND-FIST INDEX THUMB CIRCLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8EB,
+ },
+ [0x1D8EC]={
+ category="so",
+ description="SIGNWRITING HAND-CUP INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8EC,
+ },
+ [0x1D8ED]={
+ category="so",
+ description="SIGNWRITING HAND-CUP INDEX THUMB OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8ED,
+ },
+ [0x1D8EE]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX THUMB OPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8EE,
+ },
+ [0x1D8EF]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX THUMB LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8EF,
+ },
+ [0x1D8F0]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F0,
+ },
+ [0x1D8F1]={
+ category="so",
+ description="SIGNWRITING HAND-HINGE INDEX THUMB SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F1,
+ },
+ [0x1D8F2]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX THUMB OUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F2,
+ },
+ [0x1D8F3]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX THUMB IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F3,
+ },
+ [0x1D8F4]={
+ category="so",
+ description="SIGNWRITING HAND-ANGLE INDEX THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F4,
+ },
+ [0x1D8F5]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F5,
+ },
+ [0x1D8F6]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB HEEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F6,
+ },
+ [0x1D8F7]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB SIDE DIAGONAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F7,
+ },
+ [0x1D8F8]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB SIDE CONJOINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F8,
+ },
+ [0x1D8F9]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB SIDE BENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8F9,
+ },
+ [0x1D8FA]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB FORWARD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FA,
+ },
+ [0x1D8FB]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FB,
+ },
+ [0x1D8FC]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB BETWEEN MIDDLE RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FC,
+ },
+ [0x1D8FD]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB BETWEEN RING LITTLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FD,
+ },
+ [0x1D8FE]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB UNDER TWO FINGERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FE,
+ },
+ [0x1D8FF]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB OVER TWO FINGERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D8FF,
+ },
+ [0x1D900]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB UNDER THREE FINGERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D900,
+ },
+ [0x1D901]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB UNDER FOUR FINGERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D901,
+ },
+ [0x1D902]={
+ category="so",
+ description="SIGNWRITING HAND-FIST THUMB OVER FOUR RAISED KNUCKLES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D902,
+ },
+ [0x1D903]={
+ category="so",
+ description="SIGNWRITING HAND-FIST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D903,
+ },
+ [0x1D904]={
+ category="so",
+ description="SIGNWRITING HAND-FIST HEEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D904,
+ },
+ [0x1D905]={
+ category="so",
+ description="SIGNWRITING TOUCH SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D905,
+ },
+ [0x1D906]={
+ category="so",
+ description="SIGNWRITING TOUCH MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D906,
+ },
+ [0x1D907]={
+ category="so",
+ description="SIGNWRITING TOUCH BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D907,
+ },
+ [0x1D908]={
+ category="so",
+ description="SIGNWRITING GRASP SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D908,
+ },
+ [0x1D909]={
+ category="so",
+ description="SIGNWRITING GRASP MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D909,
+ },
+ [0x1D90A]={
+ category="so",
+ description="SIGNWRITING GRASP BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90A,
+ },
+ [0x1D90B]={
+ category="so",
+ description="SIGNWRITING STRIKE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90B,
+ },
+ [0x1D90C]={
+ category="so",
+ description="SIGNWRITING STRIKE MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90C,
+ },
+ [0x1D90D]={
+ category="so",
+ description="SIGNWRITING STRIKE BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90D,
+ },
+ [0x1D90E]={
+ category="so",
+ description="SIGNWRITING BRUSH SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90E,
+ },
+ [0x1D90F]={
+ category="so",
+ description="SIGNWRITING BRUSH MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D90F,
+ },
+ [0x1D910]={
+ category="so",
+ description="SIGNWRITING BRUSH BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D910,
+ },
+ [0x1D911]={
+ category="so",
+ description="SIGNWRITING RUB SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D911,
+ },
+ [0x1D912]={
+ category="so",
+ description="SIGNWRITING RUB MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D912,
+ },
+ [0x1D913]={
+ category="so",
+ description="SIGNWRITING RUB BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D913,
+ },
+ [0x1D914]={
+ category="so",
+ description="SIGNWRITING SURFACE SYMBOLS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D914,
+ },
+ [0x1D915]={
+ category="so",
+ description="SIGNWRITING SURFACE BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D915,
+ },
+ [0x1D916]={
+ category="so",
+ description="SIGNWRITING SQUEEZE LARGE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D916,
+ },
+ [0x1D917]={
+ category="so",
+ description="SIGNWRITING SQUEEZE SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D917,
+ },
+ [0x1D918]={
+ category="so",
+ description="SIGNWRITING SQUEEZE LARGE MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D918,
+ },
+ [0x1D919]={
+ category="so",
+ description="SIGNWRITING SQUEEZE SMALL MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D919,
+ },
+ [0x1D91A]={
+ category="so",
+ description="SIGNWRITING SQUEEZE SEQUENTIAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91A,
+ },
+ [0x1D91B]={
+ category="so",
+ description="SIGNWRITING FLICK LARGE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91B,
+ },
+ [0x1D91C]={
+ category="so",
+ description="SIGNWRITING FLICK SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91C,
+ },
+ [0x1D91D]={
+ category="so",
+ description="SIGNWRITING FLICK LARGE MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91D,
+ },
+ [0x1D91E]={
+ category="so",
+ description="SIGNWRITING FLICK SMALL MULTIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91E,
+ },
+ [0x1D91F]={
+ category="so",
+ description="SIGNWRITING FLICK SEQUENTIAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D91F,
+ },
+ [0x1D920]={
+ category="so",
+ description="SIGNWRITING SQUEEZE FLICK ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D920,
+ },
+ [0x1D921]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE UP DOWN LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D921,
+ },
+ [0x1D922]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE UP DOWN SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D922,
+ },
+ [0x1D923]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE UP SEQUENTIAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D923,
+ },
+ [0x1D924]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE DOWN SEQUENTIAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D924,
+ },
+ [0x1D925]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D925,
+ },
+ [0x1D926]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D926,
+ },
+ [0x1D927]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-HINGE SIDE TO SIDE SCISSORS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D927,
+ },
+ [0x1D928]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE FINGER CONTACT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D928,
+ },
+ [0x1D929]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE FINGER CONTACT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D929,
+ },
+ [0x1D92A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92A,
+ },
+ [0x1D92B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92B,
+ },
+ [0x1D92C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92C,
+ },
+ [0x1D92D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92D,
+ },
+ [0x1D92E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SINGLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92E,
+ },
+ [0x1D92F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE DOUBLE STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D92F,
+ },
+ [0x1D930]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE DOUBLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D930,
+ },
+ [0x1D931]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D931,
+ },
+ [0x1D932]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D932,
+ },
+ [0x1D933]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CROSS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D933,
+ },
+ [0x1D934]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE TRIPLE STRAIGHT MOVEMENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D934,
+ },
+ [0x1D935]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE TRIPLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D935,
+ },
+ [0x1D936]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D936,
+ },
+ [0x1D937]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D937,
+ },
+ [0x1D938]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BEND SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D938,
+ },
+ [0x1D939]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BEND MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D939,
+ },
+ [0x1D93A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BEND LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93A,
+ },
+ [0x1D93B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CORNER SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93B,
+ },
+ [0x1D93C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CORNER MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93C,
+ },
+ [0x1D93D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CORNER LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93D,
+ },
+ [0x1D93E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CORNER ROTATION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93E,
+ },
+ [0x1D93F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CHECK SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D93F,
+ },
+ [0x1D940]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CHECK MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D940,
+ },
+ [0x1D941]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CHECK LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D941,
+ },
+ [0x1D942]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BOX SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D942,
+ },
+ [0x1D943]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BOX MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D943,
+ },
+ [0x1D944]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE BOX LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D944,
+ },
+ [0x1D945]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D945,
+ },
+ [0x1D946]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D946,
+ },
+ [0x1D947]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D947,
+ },
+ [0x1D948]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE PEAKS SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D948,
+ },
+ [0x1D949]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE PEAKS MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D949,
+ },
+ [0x1D94A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE PEAKS LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94A,
+ },
+ [0x1D94B]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94B,
+ },
+ [0x1D94C]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94C,
+ },
+ [0x1D94D]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94D,
+ },
+ [0x1D94E]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94E,
+ },
+ [0x1D94F]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D94F,
+ },
+ [0x1D950]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D950,
+ },
+ [0x1D951]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE SHAKING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D951,
+ },
+ [0x1D952]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D952,
+ },
+ [0x1D953]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D953,
+ },
+ [0x1D954]={
+ category="so",
+ description="SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL TRIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D954,
+ },
+ [0x1D955]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL AWAY SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D955,
+ },
+ [0x1D956]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL AWAY MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D956,
+ },
+ [0x1D957]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D957,
+ },
+ [0x1D958]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D958,
+ },
+ [0x1D959]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL TOWARDS SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D959,
+ },
+ [0x1D95A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL TOWARDS MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95A,
+ },
+ [0x1D95B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95B,
+ },
+ [0x1D95C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95C,
+ },
+ [0x1D95D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95D,
+ },
+ [0x1D95E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95E,
+ },
+ [0x1D95F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D95F,
+ },
+ [0x1D960]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D960,
+ },
+ [0x1D961]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D961,
+ },
+ [0x1D962]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D962,
+ },
+ [0x1D963]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D963,
+ },
+ [0x1D964]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D964,
+ },
+ [0x1D965]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D965,
+ },
+ [0x1D966]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D966,
+ },
+ [0x1D967]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D967,
+ },
+ [0x1D968]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D968,
+ },
+ [0x1D969]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SINGLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D969,
+ },
+ [0x1D96A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96A,
+ },
+ [0x1D96B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96B,
+ },
+ [0x1D96C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96C,
+ },
+ [0x1D96D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96D,
+ },
+ [0x1D96E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CROSS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96E,
+ },
+ [0x1D96F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE STRAIGHT MOVEMENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D96F,
+ },
+ [0x1D970]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D970,
+ },
+ [0x1D971]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING MOVEMENT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D971,
+ },
+ [0x1D972]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING WRIST FLEX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D972,
+ },
+ [0x1D973]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE BEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D973,
+ },
+ [0x1D974]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CORNER SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D974,
+ },
+ [0x1D975]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CORNER MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D975,
+ },
+ [0x1D976]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CORNER LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D976,
+ },
+ [0x1D977]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CHECK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D977,
+ },
+ [0x1D978]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE BOX SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D978,
+ },
+ [0x1D979]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE BOX MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D979,
+ },
+ [0x1D97A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE BOX LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97A,
+ },
+ [0x1D97B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97B,
+ },
+ [0x1D97C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97C,
+ },
+ [0x1D97D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97D,
+ },
+ [0x1D97E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE PEAKS SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97E,
+ },
+ [0x1D97F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE PEAKS MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D97F,
+ },
+ [0x1D980]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE PEAKS LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D980,
+ },
+ [0x1D981]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D981,
+ },
+ [0x1D982]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D982,
+ },
+ [0x1D983]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D983,
+ },
+ [0x1D984]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D984,
+ },
+ [0x1D985]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D985,
+ },
+ [0x1D986]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D986,
+ },
+ [0x1D987]={
+ category="so",
+ description="SIGNWRITING TRAVEL-FLOORPLANE SHAKING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D987,
+ },
+ [0x1D988]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D988,
+ },
+ [0x1D989]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D989,
+ },
+ [0x1D98A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98A,
+ },
+ [0x1D98B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98B,
+ },
+ [0x1D98C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98C,
+ },
+ [0x1D98D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98D,
+ },
+ [0x1D98E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98E,
+ },
+ [0x1D98F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D98F,
+ },
+ [0x1D990]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D990,
+ },
+ [0x1D991]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D991,
+ },
+ [0x1D992]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE HUMP SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D992,
+ },
+ [0x1D993]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE HUMP MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D993,
+ },
+ [0x1D994]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE HUMP LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D994,
+ },
+ [0x1D995]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D995,
+ },
+ [0x1D996]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D996,
+ },
+ [0x1D997]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D997,
+ },
+ [0x1D998]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D998,
+ },
+ [0x1D999]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D999,
+ },
+ [0x1D99A]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99A,
+ },
+ [0x1D99B]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99B,
+ },
+ [0x1D99C]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99C,
+ },
+ [0x1D99D]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99D,
+ },
+ [0x1D99E]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99E,
+ },
+ [0x1D99F]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE THEN STRAIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D99F,
+ },
+ [0x1D9A0]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A0,
+ },
+ [0x1D9A1]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A1,
+ },
+ [0x1D9A2]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A2,
+ },
+ [0x1D9A3]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A3,
+ },
+ [0x1D9A4]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE ALTERNATE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A4,
+ },
+ [0x1D9A5]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE SHAKING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A5,
+ },
+ [0x1D9A6]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A6,
+ },
+ [0x1D9A7]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A7,
+ },
+ [0x1D9A8]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A8,
+ },
+ [0x1D9A9]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9A9,
+ },
+ [0x1D9AA]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AA,
+ },
+ [0x1D9AB]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AB,
+ },
+ [0x1D9AC]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING FRONT WALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AC,
+ },
+ [0x1D9AD]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AD,
+ },
+ [0x1D9AE]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AE,
+ },
+ [0x1D9AF]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9AF,
+ },
+ [0x1D9B0]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B0,
+ },
+ [0x1D9B1]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B1,
+ },
+ [0x1D9B2]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B2,
+ },
+ [0x1D9B3]={
+ category="so",
+ description="SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING CHEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B3,
+ },
+ [0x1D9B4]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B4,
+ },
+ [0x1D9B5]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B5,
+ },
+ [0x1D9B6]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B6,
+ },
+ [0x1D9B7]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B7,
+ },
+ [0x1D9B8]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B8,
+ },
+ [0x1D9B9]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9B9,
+ },
+ [0x1D9BA]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BA,
+ },
+ [0x1D9BB]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL TRIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BB,
+ },
+ [0x1D9BC]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE TRIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BC,
+ },
+ [0x1D9BD]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BD,
+ },
+ [0x1D9BE]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BE,
+ },
+ [0x1D9BF]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9BF,
+ },
+ [0x1D9C0]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C0,
+ },
+ [0x1D9C1]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C1,
+ },
+ [0x1D9C2]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C2,
+ },
+ [0x1D9C3]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING CEILING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C3,
+ },
+ [0x1D9C4]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING CEILING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C4,
+ },
+ [0x1D9C5]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING CEILING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C5,
+ },
+ [0x1D9C6]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C6,
+ },
+ [0x1D9C7]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C7,
+ },
+ [0x1D9C8]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C8,
+ },
+ [0x1D9C9]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR LARGE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9C9,
+ },
+ [0x1D9CA]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE SMALL TRIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CA,
+ },
+ [0x1D9CB]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE LARGE TRIPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CB,
+ },
+ [0x1D9CC]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CC,
+ },
+ [0x1D9CD]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CD,
+ },
+ [0x1D9CE]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CE,
+ },
+ [0x1D9CF]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9CF,
+ },
+ [0x1D9D0]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D0,
+ },
+ [0x1D9D1]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D1,
+ },
+ [0x1D9D2]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING FLOOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D2,
+ },
+ [0x1D9D3]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING FLOOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D3,
+ },
+ [0x1D9D4]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING FLOOR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D4,
+ },
+ [0x1D9D5]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D5,
+ },
+ [0x1D9D6]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE MEDIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D6,
+ },
+ [0x1D9D7]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D7,
+ },
+ [0x1D9D8]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGEST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D8,
+ },
+ [0x1D9D9]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE CURVE COMBINED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9D9,
+ },
+ [0x1D9DA]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE HUMP SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DA,
+ },
+ [0x1D9DB]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE LOOP SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DB,
+ },
+ [0x1D9DC]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE SNAKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DC,
+ },
+ [0x1D9DD]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DD,
+ },
+ [0x1D9DE]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WAVE LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DE,
+ },
+ [0x1D9DF]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9DF,
+ },
+ [0x1D9E0]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E0,
+ },
+ [0x1D9E1]={
+ category="so",
+ description="SIGNWRITING ROTATION-FLOORPLANE ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E1,
+ },
+ [0x1D9E2]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE SHAKING PARALLEL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E2,
+ },
+ [0x1D9E3]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E3,
+ },
+ [0x1D9E4]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E4,
+ },
+ [0x1D9E5]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E5,
+ },
+ [0x1D9E6]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E6,
+ },
+ [0x1D9E7]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E7,
+ },
+ [0x1D9E8]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E8,
+ },
+ [0x1D9E9]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9E9,
+ },
+ [0x1D9EA]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9EA,
+ },
+ [0x1D9EB]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9EB,
+ },
+ [0x1D9EC]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9EC,
+ },
+ [0x1D9ED]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9ED,
+ },
+ [0x1D9EE]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9EE,
+ },
+ [0x1D9EF]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9EF,
+ },
+ [0x1D9F0]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F0,
+ },
+ [0x1D9F1]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F1,
+ },
+ [0x1D9F2]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F2,
+ },
+ [0x1D9F3]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL SINGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F3,
+ },
+ [0x1D9F4]={
+ category="so",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL DOUBLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F4,
+ },
+ [0x1D9F5]={
+ category="so",
+ description="SIGNWRITING DYNAMIC ARROWHEAD SMALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F5,
+ },
+ [0x1D9F6]={
+ category="so",
+ description="SIGNWRITING DYNAMIC ARROWHEAD LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F6,
+ },
+ [0x1D9F7]={
+ category="so",
+ description="SIGNWRITING DYNAMIC FAST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F7,
+ },
+ [0x1D9F8]={
+ category="so",
+ description="SIGNWRITING DYNAMIC SLOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F8,
+ },
+ [0x1D9F9]={
+ category="so",
+ description="SIGNWRITING DYNAMIC TENSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9F9,
+ },
+ [0x1D9FA]={
+ category="so",
+ description="SIGNWRITING DYNAMIC RELAXED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FA,
+ },
+ [0x1D9FB]={
+ category="so",
+ description="SIGNWRITING DYNAMIC SIMULTANEOUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FB,
+ },
+ [0x1D9FC]={
+ category="so",
+ description="SIGNWRITING DYNAMIC SIMULTANEOUS ALTERNATING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FC,
+ },
+ [0x1D9FD]={
+ category="so",
+ description="SIGNWRITING DYNAMIC EVERY OTHER TIME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FD,
+ },
+ [0x1D9FE]={
+ category="so",
+ description="SIGNWRITING DYNAMIC GRADUAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FE,
+ },
+ [0x1D9FF]={
+ category="so",
+ description="SIGNWRITING HEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D9FF,
+ },
+ [0x1DA00]={
+ category="mn",
+ description="SIGNWRITING HEAD RIM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA00,
+ },
+ [0x1DA01]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT-WALLPLANE STRAIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA01,
+ },
+ [0x1DA02]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT-WALLPLANE TILT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA02,
+ },
+ [0x1DA03]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT-FLOORPLANE STRAIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA03,
+ },
+ [0x1DA04]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT-WALLPLANE CURVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA04,
+ },
+ [0x1DA05]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT-FLOORPLANE CURVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA05,
+ },
+ [0x1DA06]={
+ category="mn",
+ description="SIGNWRITING HEAD MOVEMENT CIRCLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA06,
+ },
+ [0x1DA07]={
+ category="mn",
+ description="SIGNWRITING FACE DIRECTION POSITION NOSE FORWARD TILTING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA07,
+ },
+ [0x1DA08]={
+ category="mn",
+ description="SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA08,
+ },
+ [0x1DA09]={
+ category="mn",
+ description="SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN TILTING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA09,
+ },
+ [0x1DA0A]={
+ category="mn",
+ description="SIGNWRITING EYEBROWS STRAIGHT UP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0A,
+ },
+ [0x1DA0B]={
+ category="mn",
+ description="SIGNWRITING EYEBROWS STRAIGHT NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0B,
+ },
+ [0x1DA0C]={
+ category="mn",
+ description="SIGNWRITING EYEBROWS STRAIGHT DOWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0C,
+ },
+ [0x1DA0D]={
+ category="mn",
+ description="SIGNWRITING DREAMY EYEBROWS NEUTRAL DOWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0D,
+ },
+ [0x1DA0E]={
+ category="mn",
+ description="SIGNWRITING DREAMY EYEBROWS DOWN NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0E,
+ },
+ [0x1DA0F]={
+ category="mn",
+ description="SIGNWRITING DREAMY EYEBROWS UP NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA0F,
+ },
+ [0x1DA10]={
+ category="mn",
+ description="SIGNWRITING DREAMY EYEBROWS NEUTRAL UP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA10,
+ },
+ [0x1DA11]={
+ category="mn",
+ description="SIGNWRITING FOREHEAD NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA11,
+ },
+ [0x1DA12]={
+ category="mn",
+ description="SIGNWRITING FOREHEAD CONTACT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA12,
+ },
+ [0x1DA13]={
+ category="mn",
+ description="SIGNWRITING FOREHEAD WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA13,
+ },
+ [0x1DA14]={
+ category="mn",
+ description="SIGNWRITING EYES OPEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA14,
+ },
+ [0x1DA15]={
+ category="mn",
+ description="SIGNWRITING EYES SQUEEZED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA15,
+ },
+ [0x1DA16]={
+ category="mn",
+ description="SIGNWRITING EYES CLOSED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA16,
+ },
+ [0x1DA17]={
+ category="mn",
+ description="SIGNWRITING EYE BLINK SINGLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA17,
+ },
+ [0x1DA18]={
+ category="mn",
+ description="SIGNWRITING EYE BLINK MULTIPLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA18,
+ },
+ [0x1DA19]={
+ category="mn",
+ description="SIGNWRITING EYES HALF OPEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA19,
+ },
+ [0x1DA1A]={
+ category="mn",
+ description="SIGNWRITING EYES WIDE OPEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1A,
+ },
+ [0x1DA1B]={
+ category="mn",
+ description="SIGNWRITING EYES HALF CLOSED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1B,
+ },
+ [0x1DA1C]={
+ category="mn",
+ description="SIGNWRITING EYES WIDENING MOVEMENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1C,
+ },
+ [0x1DA1D]={
+ category="mn",
+ description="SIGNWRITING EYE WINK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1D,
+ },
+ [0x1DA1E]={
+ category="mn",
+ description="SIGNWRITING EYELASHES UP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1E,
+ },
+ [0x1DA1F]={
+ category="mn",
+ description="SIGNWRITING EYELASHES DOWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA1F,
+ },
+ [0x1DA20]={
+ category="mn",
+ description="SIGNWRITING EYELASHES FLUTTERING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA20,
+ },
+ [0x1DA21]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA21,
+ },
+ [0x1DA22]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT DOUBLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA22,
+ },
+ [0x1DA23]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT ALTERNATING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA23,
+ },
+ [0x1DA24]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA24,
+ },
+ [0x1DA25]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT DOUBLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA25,
+ },
+ [0x1DA26]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT ALTERNATING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA26,
+ },
+ [0x1DA27]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-WALLPLANE CURVED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA27,
+ },
+ [0x1DA28]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-FLOORPLANE CURVED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA28,
+ },
+ [0x1DA29]={
+ category="mn",
+ description="SIGNWRITING EYEGAZE-WALLPLANE CIRCLING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA29,
+ },
+ [0x1DA2A]={
+ category="mn",
+ description="SIGNWRITING CHEEKS PUFFED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2A,
+ },
+ [0x1DA2B]={
+ category="mn",
+ description="SIGNWRITING CHEEKS NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2B,
+ },
+ [0x1DA2C]={
+ category="mn",
+ description="SIGNWRITING CHEEKS SUCKED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2C,
+ },
+ [0x1DA2D]={
+ category="mn",
+ description="SIGNWRITING TENSE CHEEKS HIGH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2D,
+ },
+ [0x1DA2E]={
+ category="mn",
+ description="SIGNWRITING TENSE CHEEKS MIDDLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2E,
+ },
+ [0x1DA2F]={
+ category="mn",
+ description="SIGNWRITING TENSE CHEEKS LOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA2F,
+ },
+ [0x1DA30]={
+ category="mn",
+ description="SIGNWRITING EARS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA30,
+ },
+ [0x1DA31]={
+ category="mn",
+ description="SIGNWRITING NOSE NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA31,
+ },
+ [0x1DA32]={
+ category="mn",
+ description="SIGNWRITING NOSE CONTACT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA32,
+ },
+ [0x1DA33]={
+ category="mn",
+ description="SIGNWRITING NOSE WRINKLES",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA33,
+ },
+ [0x1DA34]={
+ category="mn",
+ description="SIGNWRITING NOSE WIGGLES",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA34,
+ },
+ [0x1DA35]={
+ category="mn",
+ description="SIGNWRITING AIR BLOWING OUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA35,
+ },
+ [0x1DA36]={
+ category="mn",
+ description="SIGNWRITING AIR SUCKING IN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA36,
+ },
+ [0x1DA37]={
+ category="so",
+ description="SIGNWRITING AIR BLOW SMALL ROTATIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA37,
+ },
+ [0x1DA38]={
+ category="so",
+ description="SIGNWRITING AIR SUCK SMALL ROTATIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA38,
+ },
+ [0x1DA39]={
+ category="so",
+ description="SIGNWRITING BREATH INHALE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA39,
+ },
+ [0x1DA3A]={
+ category="so",
+ description="SIGNWRITING BREATH EXHALE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA3A,
+ },
+ [0x1DA3B]={
+ category="mn",
+ description="SIGNWRITING MOUTH CLOSED NEUTRAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA3B,
+ },
+ [0x1DA3C]={
+ category="mn",
+ description="SIGNWRITING MOUTH CLOSED FORWARD",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA3C,
+ },
+ [0x1DA3D]={
+ category="mn",
+ description="SIGNWRITING MOUTH CLOSED CONTACT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA3D,
+ },
+ [0x1DA3E]={
+ category="mn",
+ description="SIGNWRITING MOUTH SMILE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA3E,
+ },
+ [0x1DA3F]={
+ category="mn",
+ description="SIGNWRITING MOUTH SMILE WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA3F,
+ },
+ [0x1DA40]={
+ category="mn",
+ description="SIGNWRITING MOUTH SMILE OPEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA40,
+ },
+ [0x1DA41]={
+ category="mn",
+ description="SIGNWRITING MOUTH FROWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA41,
+ },
+ [0x1DA42]={
+ category="mn",
+ description="SIGNWRITING MOUTH FROWN WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA42,
+ },
+ [0x1DA43]={
+ category="mn",
+ description="SIGNWRITING MOUTH FROWN OPEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA43,
+ },
+ [0x1DA44]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN CIRCLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA44,
+ },
+ [0x1DA45]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN FORWARD",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA45,
+ },
+ [0x1DA46]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA46,
+ },
+ [0x1DA47]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN OVAL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA47,
+ },
+ [0x1DA48]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN OVAL WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA48,
+ },
+ [0x1DA49]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN OVAL YAWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA49,
+ },
+ [0x1DA4A]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN RECTANGLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4A,
+ },
+ [0x1DA4B]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN RECTANGLE WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4B,
+ },
+ [0x1DA4C]={
+ category="mn",
+ description="SIGNWRITING MOUTH OPEN RECTANGLE YAWN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4C,
+ },
+ [0x1DA4D]={
+ category="mn",
+ description="SIGNWRITING MOUTH KISS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4D,
+ },
+ [0x1DA4E]={
+ category="mn",
+ description="SIGNWRITING MOUTH KISS FORWARD",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4E,
+ },
+ [0x1DA4F]={
+ category="mn",
+ description="SIGNWRITING MOUTH KISS WRINKLED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA4F,
+ },
+ [0x1DA50]={
+ category="mn",
+ description="SIGNWRITING MOUTH TENSE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA50,
+ },
+ [0x1DA51]={
+ category="mn",
+ description="SIGNWRITING MOUTH TENSE FORWARD",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA51,
+ },
+ [0x1DA52]={
+ category="mn",
+ description="SIGNWRITING MOUTH TENSE SUCKED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA52,
+ },
+ [0x1DA53]={
+ category="mn",
+ description="SIGNWRITING LIPS PRESSED TOGETHER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA53,
+ },
+ [0x1DA54]={
+ category="mn",
+ description="SIGNWRITING LIP LOWER OVER UPPER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA54,
+ },
+ [0x1DA55]={
+ category="mn",
+ description="SIGNWRITING LIP UPPER OVER LOWER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA55,
+ },
+ [0x1DA56]={
+ category="mn",
+ description="SIGNWRITING MOUTH CORNERS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA56,
+ },
+ [0x1DA57]={
+ category="mn",
+ description="SIGNWRITING MOUTH WRINKLES SINGLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA57,
+ },
+ [0x1DA58]={
+ category="mn",
+ description="SIGNWRITING MOUTH WRINKLES DOUBLE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA58,
+ },
+ [0x1DA59]={
+ category="mn",
+ description="SIGNWRITING TONGUE STICKING OUT FAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA59,
+ },
+ [0x1DA5A]={
+ category="mn",
+ description="SIGNWRITING TONGUE LICKING LIPS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5A,
+ },
+ [0x1DA5B]={
+ category="mn",
+ description="SIGNWRITING TONGUE TIP BETWEEN LIPS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5B,
+ },
+ [0x1DA5C]={
+ category="mn",
+ description="SIGNWRITING TONGUE TIP TOUCHING INSIDE MOUTH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5C,
+ },
+ [0x1DA5D]={
+ category="mn",
+ description="SIGNWRITING TONGUE INSIDE MOUTH RELAXED",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5D,
+ },
+ [0x1DA5E]={
+ category="mn",
+ description="SIGNWRITING TONGUE MOVES AGAINST CHEEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5E,
+ },
+ [0x1DA5F]={
+ category="mn",
+ description="SIGNWRITING TONGUE CENTRE STICKING OUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA5F,
+ },
+ [0x1DA60]={
+ category="mn",
+ description="SIGNWRITING TONGUE CENTRE INSIDE MOUTH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA60,
+ },
+ [0x1DA61]={
+ category="mn",
+ description="SIGNWRITING TEETH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA61,
+ },
+ [0x1DA62]={
+ category="mn",
+ description="SIGNWRITING TEETH MOVEMENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA62,
+ },
+ [0x1DA63]={
+ category="mn",
+ description="SIGNWRITING TEETH ON TONGUE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA63,
+ },
+ [0x1DA64]={
+ category="mn",
+ description="SIGNWRITING TEETH ON TONGUE MOVEMENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA64,
+ },
+ [0x1DA65]={
+ category="mn",
+ description="SIGNWRITING TEETH ON LIPS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA65,
+ },
+ [0x1DA66]={
+ category="mn",
+ description="SIGNWRITING TEETH ON LIPS MOVEMENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA66,
+ },
+ [0x1DA67]={
+ category="mn",
+ description="SIGNWRITING TEETH BITE LIPS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA67,
+ },
+ [0x1DA68]={
+ category="mn",
+ description="SIGNWRITING MOVEMENT-WALLPLANE JAW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA68,
+ },
+ [0x1DA69]={
+ category="mn",
+ description="SIGNWRITING MOVEMENT-FLOORPLANE JAW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA69,
+ },
+ [0x1DA6A]={
+ category="mn",
+ description="SIGNWRITING NECK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA6A,
+ },
+ [0x1DA6B]={
+ category="mn",
+ description="SIGNWRITING HAIR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA6B,
+ },
+ [0x1DA6C]={
+ category="mn",
+ description="SIGNWRITING EXCITEMENT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA6C,
+ },
+ [0x1DA6D]={
+ category="so",
+ description="SIGNWRITING SHOULDER HIP SPINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA6D,
+ },
+ [0x1DA6E]={
+ category="so",
+ description="SIGNWRITING SHOULDER HIP POSITIONS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA6E,
+ },
+ [0x1DA6F]={
+ category="so",
+ description="SIGNWRITING WALLPLANE SHOULDER HIP MOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA6F,
+ },
+ [0x1DA70]={
+ category="so",
+ description="SIGNWRITING FLOORPLANE SHOULDER HIP MOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA70,
+ },
+ [0x1DA71]={
+ category="so",
+ description="SIGNWRITING SHOULDER TILTING FROM WAIST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA71,
+ },
+ [0x1DA72]={
+ category="so",
+ description="SIGNWRITING TORSO-WALLPLANE STRAIGHT STRETCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA72,
+ },
+ [0x1DA73]={
+ category="so",
+ description="SIGNWRITING TORSO-WALLPLANE CURVED BEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA73,
+ },
+ [0x1DA74]={
+ category="so",
+ description="SIGNWRITING TORSO-FLOORPLANE TWISTING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA74,
+ },
+ [0x1DA75]={
+ category="mn",
+ description="SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA75,
+ },
+ [0x1DA76]={
+ category="so",
+ description="SIGNWRITING LIMB COMBINATION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA76,
+ },
+ [0x1DA77]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA77,
+ },
+ [0x1DA78]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA78,
+ },
+ [0x1DA79]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA79,
+ },
+ [0x1DA7A]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7A,
+ },
+ [0x1DA7B]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7B,
+ },
+ [0x1DA7C]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7C,
+ },
+ [0x1DA7D]={
+ category="so",
+ description="SIGNWRITING LIMB LENGTH-7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7D,
+ },
+ [0x1DA7E]={
+ category="so",
+ description="SIGNWRITING FINGER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7E,
+ },
+ [0x1DA7F]={
+ category="so",
+ description="SIGNWRITING LOCATION-WALLPLANE SPACE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA7F,
+ },
+ [0x1DA80]={
+ category="so",
+ description="SIGNWRITING LOCATION-FLOORPLANE SPACE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA80,
+ },
+ [0x1DA81]={
+ category="so",
+ description="SIGNWRITING LOCATION HEIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA81,
+ },
+ [0x1DA82]={
+ category="so",
+ description="SIGNWRITING LOCATION WIDTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA82,
+ },
+ [0x1DA83]={
+ category="so",
+ description="SIGNWRITING LOCATION DEPTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA83,
+ },
+ [0x1DA84]={
+ category="mn",
+ description="SIGNWRITING LOCATION HEAD NECK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA84,
+ },
+ [0x1DA85]={
+ category="so",
+ description="SIGNWRITING LOCATION TORSO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA85,
+ },
+ [0x1DA86]={
+ category="so",
+ description="SIGNWRITING LOCATION LIMBS DIGITS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA86,
+ },
+ [0x1DA87]={
+ category="po",
+ description="SIGNWRITING COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1DA87,
+ },
+ [0x1DA88]={
+ category="po",
+ description="SIGNWRITING FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1DA88,
+ },
+ [0x1DA89]={
+ category="po",
+ description="SIGNWRITING SEMICOLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1DA89,
+ },
+ [0x1DA8A]={
+ category="po",
+ description="SIGNWRITING COLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1DA8A,
+ },
+ [0x1DA8B]={
+ category="po",
+ description="SIGNWRITING PARENTHESIS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1DA8B,
+ },
+ [0x1DA9B]={
+ category="mn",
+ description="SIGNWRITING FILL MODIFIER-2",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA9B,
+ },
+ [0x1DA9C]={
+ category="mn",
+ description="SIGNWRITING FILL MODIFIER-3",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA9C,
+ },
+ [0x1DA9D]={
+ category="mn",
+ description="SIGNWRITING FILL MODIFIER-4",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA9D,
+ },
+ [0x1DA9E]={
+ category="mn",
+ description="SIGNWRITING FILL MODIFIER-5",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA9E,
+ },
+ [0x1DA9F]={
+ category="mn",
+ description="SIGNWRITING FILL MODIFIER-6",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DA9F,
+ },
+ [0x1DAA1]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-2",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA1,
+ },
+ [0x1DAA2]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-3",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA2,
+ },
+ [0x1DAA3]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-4",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA3,
+ },
+ [0x1DAA4]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-5",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA4,
+ },
+ [0x1DAA5]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-6",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA5,
+ },
+ [0x1DAA6]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-7",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA6,
+ },
+ [0x1DAA7]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-8",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA7,
+ },
+ [0x1DAA8]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-9",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA8,
+ },
+ [0x1DAA9]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-10",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAA9,
+ },
+ [0x1DAAA]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-11",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAA,
+ },
+ [0x1DAAB]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-12",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAB,
+ },
+ [0x1DAAC]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-13",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAC,
+ },
+ [0x1DAAD]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-14",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAD,
+ },
+ [0x1DAAE]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-15",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAE,
+ },
+ [0x1DAAF]={
+ category="mn",
+ description="SIGNWRITING ROTATION MODIFIER-16",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DAAF,
+ },
+ [0x1E800]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M001 KI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E800,
+ },
+ [0x1E801]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M002 KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E801,
+ },
+ [0x1E802]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M003 KU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E802,
+ },
+ [0x1E803]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M065 KEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E803,
+ },
+ [0x1E804]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M095 KE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E804,
+ },
+ [0x1E805]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M076 KOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E805,
+ },
+ [0x1E806]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M048 KO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E806,
+ },
+ [0x1E807]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M179 KUA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E807,
+ },
+ [0x1E808]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M004 WI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E808,
+ },
+ [0x1E809]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M005 WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E809,
+ },
+ [0x1E80A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M006 WU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80A,
+ },
+ [0x1E80B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M126 WEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80B,
+ },
+ [0x1E80C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M118 WE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80C,
+ },
+ [0x1E80D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M114 WOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80D,
+ },
+ [0x1E80E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M045 WO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80E,
+ },
+ [0x1E80F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M194 WUI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E80F,
+ },
+ [0x1E810]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M143 WEI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E810,
+ },
+ [0x1E811]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M061 WVI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E811,
+ },
+ [0x1E812]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M049 WVA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E812,
+ },
+ [0x1E813]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M139 WVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E813,
+ },
+ [0x1E814]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M007 MIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E814,
+ },
+ [0x1E815]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M008 MAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E815,
+ },
+ [0x1E816]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M009 MUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E816,
+ },
+ [0x1E817]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M059 MEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E817,
+ },
+ [0x1E818]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M094 MON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E818,
+ },
+ [0x1E819]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M154 MUAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E819,
+ },
+ [0x1E81A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M189 MUEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81A,
+ },
+ [0x1E81B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M010 BI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81B,
+ },
+ [0x1E81C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M011 BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81C,
+ },
+ [0x1E81D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M012 BU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81D,
+ },
+ [0x1E81E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M150 BEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81E,
+ },
+ [0x1E81F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M097 BE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E81F,
+ },
+ [0x1E820]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M103 BOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E820,
+ },
+ [0x1E821]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M138 BO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E821,
+ },
+ [0x1E822]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M013 I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E822,
+ },
+ [0x1E823]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M014 A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E823,
+ },
+ [0x1E824]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M015 U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E824,
+ },
+ [0x1E825]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M163 EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E825,
+ },
+ [0x1E826]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M100 E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E826,
+ },
+ [0x1E827]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M165 OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E827,
+ },
+ [0x1E828]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M147 O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E828,
+ },
+ [0x1E829]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M137 EI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E829,
+ },
+ [0x1E82A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M131 IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82A,
+ },
+ [0x1E82B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M135 IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82B,
+ },
+ [0x1E82C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M195 AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82C,
+ },
+ [0x1E82D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M178 EN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82D,
+ },
+ [0x1E82E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M019 SI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82E,
+ },
+ [0x1E82F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M020 SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E82F,
+ },
+ [0x1E830]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M021 SU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E830,
+ },
+ [0x1E831]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M162 SEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E831,
+ },
+ [0x1E832]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M116 SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E832,
+ },
+ [0x1E833]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M136 SOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E833,
+ },
+ [0x1E834]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M079 SO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E834,
+ },
+ [0x1E835]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M196 SIA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E835,
+ },
+ [0x1E836]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M025 LI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E836,
+ },
+ [0x1E837]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M026 LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E837,
+ },
+ [0x1E838]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M027 LU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E838,
+ },
+ [0x1E839]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M084 LEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E839,
+ },
+ [0x1E83A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M073 LE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83A,
+ },
+ [0x1E83B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M054 LOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83B,
+ },
+ [0x1E83C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M153 LO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83C,
+ },
+ [0x1E83D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M110 LONG LE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83D,
+ },
+ [0x1E83E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M016 DI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83E,
+ },
+ [0x1E83F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M017 DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E83F,
+ },
+ [0x1E840]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M018 DU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E840,
+ },
+ [0x1E841]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M089 DEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E841,
+ },
+ [0x1E842]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M180 DOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E842,
+ },
+ [0x1E843]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M181 DO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E843,
+ },
+ [0x1E844]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M022 TI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E844,
+ },
+ [0x1E845]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M023 TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E845,
+ },
+ [0x1E846]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M024 TU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E846,
+ },
+ [0x1E847]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M091 TEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E847,
+ },
+ [0x1E848]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M055 TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E848,
+ },
+ [0x1E849]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M104 TOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E849,
+ },
+ [0x1E84A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M069 TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84A,
+ },
+ [0x1E84B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M028 JI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84B,
+ },
+ [0x1E84C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M029 JA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84C,
+ },
+ [0x1E84D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M030 JU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84D,
+ },
+ [0x1E84E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M157 JEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84E,
+ },
+ [0x1E84F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M113 JE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E84F,
+ },
+ [0x1E850]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M160 JOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E850,
+ },
+ [0x1E851]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M063 JO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E851,
+ },
+ [0x1E852]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M175 LONG JO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E852,
+ },
+ [0x1E853]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M031 YI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E853,
+ },
+ [0x1E854]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M032 YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E854,
+ },
+ [0x1E855]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M033 YU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E855,
+ },
+ [0x1E856]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M109 YEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E856,
+ },
+ [0x1E857]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M080 YE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E857,
+ },
+ [0x1E858]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M141 YOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E858,
+ },
+ [0x1E859]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M121 YO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E859,
+ },
+ [0x1E85A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M034 FI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85A,
+ },
+ [0x1E85B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M035 FA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85B,
+ },
+ [0x1E85C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M036 FU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85C,
+ },
+ [0x1E85D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M078 FEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85D,
+ },
+ [0x1E85E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M075 FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85E,
+ },
+ [0x1E85F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M133 FOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E85F,
+ },
+ [0x1E860]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M088 FO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E860,
+ },
+ [0x1E861]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M197 FUA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E861,
+ },
+ [0x1E862]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M101 FAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E862,
+ },
+ [0x1E863]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M037 NIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E863,
+ },
+ [0x1E864]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M038 NAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E864,
+ },
+ [0x1E865]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M039 NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E865,
+ },
+ [0x1E866]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M117 NEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E866,
+ },
+ [0x1E867]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M169 NON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E867,
+ },
+ [0x1E868]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M176 HI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E868,
+ },
+ [0x1E869]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M041 HA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E869,
+ },
+ [0x1E86A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M186 HU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86A,
+ },
+ [0x1E86B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M040 HEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86B,
+ },
+ [0x1E86C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M096 HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86C,
+ },
+ [0x1E86D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M042 HOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86D,
+ },
+ [0x1E86E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M140 HO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86E,
+ },
+ [0x1E86F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M083 HEEI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E86F,
+ },
+ [0x1E870]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M128 HOOU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E870,
+ },
+ [0x1E871]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M053 HIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E871,
+ },
+ [0x1E872]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M130 HAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E872,
+ },
+ [0x1E873]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M087 HUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E873,
+ },
+ [0x1E874]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M052 HEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E874,
+ },
+ [0x1E875]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M193 HON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E875,
+ },
+ [0x1E876]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M046 HUAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E876,
+ },
+ [0x1E877]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M090 NGGI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E877,
+ },
+ [0x1E878]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M043 NGGA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E878,
+ },
+ [0x1E879]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M082 NGGU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E879,
+ },
+ [0x1E87A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M115 NGGEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87A,
+ },
+ [0x1E87B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M146 NGGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87B,
+ },
+ [0x1E87C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M156 NGGOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87C,
+ },
+ [0x1E87D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M120 NGGO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87D,
+ },
+ [0x1E87E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M159 NGGAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87E,
+ },
+ [0x1E87F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M127 NGGUA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E87F,
+ },
+ [0x1E880]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M086 LONG NGGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E880,
+ },
+ [0x1E881]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M106 LONG NGGOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E881,
+ },
+ [0x1E882]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M183 LONG NGGO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E882,
+ },
+ [0x1E883]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M155 GI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E883,
+ },
+ [0x1E884]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M111 GA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E884,
+ },
+ [0x1E885]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M168 GU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E885,
+ },
+ [0x1E886]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M190 GEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E886,
+ },
+ [0x1E887]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M166 GUEI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E887,
+ },
+ [0x1E888]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M167 GUAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E888,
+ },
+ [0x1E889]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M184 NGEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E889,
+ },
+ [0x1E88A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M057 NGON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88A,
+ },
+ [0x1E88B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M177 NGUAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88B,
+ },
+ [0x1E88C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M068 PI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88C,
+ },
+ [0x1E88D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M099 PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88D,
+ },
+ [0x1E88E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M050 PU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88E,
+ },
+ [0x1E88F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M081 PEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E88F,
+ },
+ [0x1E890]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M051 PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E890,
+ },
+ [0x1E891]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M102 POO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E891,
+ },
+ [0x1E892]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M066 PO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E892,
+ },
+ [0x1E893]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M145 MBI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E893,
+ },
+ [0x1E894]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M062 MBA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E894,
+ },
+ [0x1E895]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M122 MBU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E895,
+ },
+ [0x1E896]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M047 MBEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E896,
+ },
+ [0x1E897]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M188 MBEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E897,
+ },
+ [0x1E898]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M072 MBE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E898,
+ },
+ [0x1E899]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M172 MBOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E899,
+ },
+ [0x1E89A]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M174 MBO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89A,
+ },
+ [0x1E89B]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M187 MBUU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89B,
+ },
+ [0x1E89C]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M161 LONG MBE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89C,
+ },
+ [0x1E89D]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M105 LONG MBOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89D,
+ },
+ [0x1E89E]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M142 LONG MBO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89E,
+ },
+ [0x1E89F]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M132 KPI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E89F,
+ },
+ [0x1E8A0]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M092 KPA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A0,
+ },
+ [0x1E8A1]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M074 KPU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A1,
+ },
+ [0x1E8A2]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M044 KPEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A2,
+ },
+ [0x1E8A3]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M108 KPE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A3,
+ },
+ [0x1E8A4]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M112 KPOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A4,
+ },
+ [0x1E8A5]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M158 KPO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A5,
+ },
+ [0x1E8A6]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M124 GBI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A6,
+ },
+ [0x1E8A7]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M056 GBA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A7,
+ },
+ [0x1E8A8]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M148 GBU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A8,
+ },
+ [0x1E8A9]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M093 GBEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8A9,
+ },
+ [0x1E8AA]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M107 GBE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AA,
+ },
+ [0x1E8AB]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M071 GBOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AB,
+ },
+ [0x1E8AC]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M070 GBO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AC,
+ },
+ [0x1E8AD]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M171 RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AD,
+ },
+ [0x1E8AE]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M123 NDI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AE,
+ },
+ [0x1E8AF]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M129 NDA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8AF,
+ },
+ [0x1E8B0]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M125 NDU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B0,
+ },
+ [0x1E8B1]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M191 NDEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B1,
+ },
+ [0x1E8B2]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M119 NDE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B2,
+ },
+ [0x1E8B3]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M067 NDOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B3,
+ },
+ [0x1E8B4]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M064 NDO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B4,
+ },
+ [0x1E8B5]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M152 NJA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B5,
+ },
+ [0x1E8B6]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M192 NJU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B6,
+ },
+ [0x1E8B7]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M149 NJEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B7,
+ },
+ [0x1E8B8]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M134 NJOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B8,
+ },
+ [0x1E8B9]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M182 VI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8B9,
+ },
+ [0x1E8BA]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M185 VA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BA,
+ },
+ [0x1E8BB]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M151 VU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BB,
+ },
+ [0x1E8BC]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M173 VEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BC,
+ },
+ [0x1E8BD]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M085 VE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BD,
+ },
+ [0x1E8BE]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M144 VOO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BE,
+ },
+ [0x1E8BF]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M077 VO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8BF,
+ },
+ [0x1E8C0]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M164 NYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C0,
+ },
+ [0x1E8C1]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M058 NYAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C1,
+ },
+ [0x1E8C2]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M170 NYUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C2,
+ },
+ [0x1E8C3]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M098 NYEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C3,
+ },
+ [0x1E8C4]={
+ category="lo",
+ description="MENDE KIKAKUI SYLLABLE M060 NYON",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C4,
+ },
+ [0x1E8C7]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C7,
+ },
+ [0x1E8C8]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C8,
+ },
+ [0x1E8C9]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8C9,
+ },
+ [0x1E8CA]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CA,
+ },
+ [0x1E8CB]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CB,
+ },
+ [0x1E8CC]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT SIX",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CC,
+ },
+ [0x1E8CD]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT SEVEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CD,
+ },
+ [0x1E8CE]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT EIGHT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CE,
+ },
+ [0x1E8CF]={
+ category="no",
+ description="MENDE KIKAKUI DIGIT NINE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1E8CF,
+ },
+ [0x1E8D0]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER TEENS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D0,
+ },
+ [0x1E8D1]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER TENS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D1,
+ },
+ [0x1E8D2]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER HUNDREDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D2,
+ },
+ [0x1E8D3]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER THOUSANDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D3,
+ },
+ [0x1E8D4]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D4,
+ },
+ [0x1E8D5]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D5,
+ },
+ [0x1E8D6]={
+ category="mn",
+ combining=0xDC,
+ description="MENDE KIKAKUI COMBINING NUMBER MILLIONS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1E8D6,
+ },
+ [0x1EE00]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ALEF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x627 },
+ unicodeslot=0x1EE00,
+ },
+ [0x1EE01]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x628 },
+ unicodeslot=0x1EE01,
+ },
+ [0x1EE02]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EE02,
+ },
+ [0x1EE03]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62F },
+ unicodeslot=0x1EE03,
+ },
+ [0x1EE05]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x648 },
+ unicodeslot=0x1EE05,
+ },
+ [0x1EE06]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x632 },
+ unicodeslot=0x1EE06,
+ },
+ [0x1EE07]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EE07,
+ },
+ [0x1EE08]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x637 },
+ unicodeslot=0x1EE08,
+ },
+ [0x1EE09]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EE09,
+ },
+ [0x1EE0A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x643 },
+ unicodeslot=0x1EE0A,
+ },
+ [0x1EE0B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x644 },
+ unicodeslot=0x1EE0B,
+ },
+ [0x1EE0C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x645 },
+ unicodeslot=0x1EE0C,
+ },
+ [0x1EE0D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EE0D,
+ },
+ [0x1EE0E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EE0E,
+ },
+ [0x1EE0F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EE0F,
+ },
+ [0x1EE10]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x641 },
+ unicodeslot=0x1EE10,
+ },
+ [0x1EE11]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EE11,
+ },
+ [0x1EE12]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EE12,
+ },
+ [0x1EE13]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x631 },
+ unicodeslot=0x1EE13,
+ },
+ [0x1EE14]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EE14,
+ },
+ [0x1EE15]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62A },
+ unicodeslot=0x1EE15,
+ },
+ [0x1EE16]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62B },
+ unicodeslot=0x1EE16,
+ },
+ [0x1EE17]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EE17,
+ },
+ [0x1EE18]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x630 },
+ unicodeslot=0x1EE18,
+ },
+ [0x1EE19]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EE19,
+ },
+ [0x1EE1A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x638 },
+ unicodeslot=0x1EE1A,
+ },
+ [0x1EE1B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EE1B,
+ },
+ [0x1EE1C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x66E },
+ unicodeslot=0x1EE1C,
+ },
+ [0x1EE1D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x6BA },
+ unicodeslot=0x1EE1D,
+ },
+ [0x1EE1E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x6A1 },
+ unicodeslot=0x1EE1E,
+ },
+ [0x1EE1F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x66F },
+ unicodeslot=0x1EE1F,
+ },
+ [0x1EE21]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x628 },
+ unicodeslot=0x1EE21,
+ },
+ [0x1EE22]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EE22,
+ },
+ [0x1EE24]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x647 },
+ unicodeslot=0x1EE24,
+ },
+ [0x1EE27]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EE27,
+ },
+ [0x1EE29]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EE29,
+ },
+ [0x1EE2A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x643 },
+ unicodeslot=0x1EE2A,
+ },
+ [0x1EE2B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x644 },
+ unicodeslot=0x1EE2B,
+ },
+ [0x1EE2C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x645 },
+ unicodeslot=0x1EE2C,
+ },
+ [0x1EE2D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EE2D,
+ },
+ [0x1EE2E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EE2E,
+ },
+ [0x1EE2F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EE2F,
+ },
+ [0x1EE30]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x641 },
+ unicodeslot=0x1EE30,
+ },
+ [0x1EE31]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EE31,
+ },
+ [0x1EE32]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EE32,
+ },
+ [0x1EE34]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EE34,
+ },
+ [0x1EE35]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62A },
+ unicodeslot=0x1EE35,
+ },
+ [0x1EE36]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62B },
+ unicodeslot=0x1EE36,
+ },
+ [0x1EE37]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EE37,
+ },
+ [0x1EE39]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EE39,
+ },
+ [0x1EE3B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EE3B,
+ },
+ [0x1EE42]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EE42,
+ },
+ [0x1EE47]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EE47,
+ },
+ [0x1EE49]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EE49,
+ },
+ [0x1EE4B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x644 },
+ unicodeslot=0x1EE4B,
+ },
+ [0x1EE4D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EE4D,
+ },
+ [0x1EE4E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EE4E,
+ },
+ [0x1EE4F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EE4F,
+ },
+ [0x1EE51]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EE51,
+ },
+ [0x1EE52]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EE52,
+ },
+ [0x1EE54]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EE54,
+ },
+ [0x1EE57]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EE57,
+ },
+ [0x1EE59]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EE59,
+ },
+ [0x1EE5B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EE5B,
+ },
+ [0x1EE5D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DOTLESS NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x6BA },
+ unicodeslot=0x1EE5D,
+ },
+ [0x1EE5F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DOTLESS QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x66F },
+ unicodeslot=0x1EE5F,
+ },
+ [0x1EE61]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x628 },
+ unicodeslot=0x1EE61,
+ },
+ [0x1EE62]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EE62,
+ },
+ [0x1EE64]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x647 },
+ unicodeslot=0x1EE64,
+ },
+ [0x1EE67]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EE67,
+ },
+ [0x1EE68]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x637 },
+ unicodeslot=0x1EE68,
+ },
+ [0x1EE69]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EE69,
+ },
+ [0x1EE6A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x643 },
+ unicodeslot=0x1EE6A,
+ },
+ [0x1EE6C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x645 },
+ unicodeslot=0x1EE6C,
+ },
+ [0x1EE6D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EE6D,
+ },
+ [0x1EE6E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EE6E,
+ },
+ [0x1EE6F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EE6F,
+ },
+ [0x1EE70]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x641 },
+ unicodeslot=0x1EE70,
+ },
+ [0x1EE71]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EE71,
+ },
+ [0x1EE72]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EE72,
+ },
+ [0x1EE74]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EE74,
+ },
+ [0x1EE75]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62A },
+ unicodeslot=0x1EE75,
+ },
+ [0x1EE76]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62B },
+ unicodeslot=0x1EE76,
+ },
+ [0x1EE77]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EE77,
+ },
+ [0x1EE79]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EE79,
+ },
+ [0x1EE7A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x638 },
+ unicodeslot=0x1EE7A,
+ },
+ [0x1EE7B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EE7B,
+ },
+ [0x1EE7C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DOTLESS BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x66E },
+ unicodeslot=0x1EE7C,
+ },
+ [0x1EE7E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DOTLESS FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x6A1 },
+ unicodeslot=0x1EE7E,
+ },
+ [0x1EE80]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ALEF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x627 },
+ unicodeslot=0x1EE80,
+ },
+ [0x1EE81]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x628 },
+ unicodeslot=0x1EE81,
+ },
+ [0x1EE82]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EE82,
+ },
+ [0x1EE83]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62F },
+ unicodeslot=0x1EE83,
+ },
+ [0x1EE84]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x647 },
+ unicodeslot=0x1EE84,
+ },
+ [0x1EE85]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x648 },
+ unicodeslot=0x1EE85,
+ },
+ [0x1EE86]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x632 },
+ unicodeslot=0x1EE86,
+ },
+ [0x1EE87]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EE87,
+ },
+ [0x1EE88]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x637 },
+ unicodeslot=0x1EE88,
+ },
+ [0x1EE89]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EE89,
+ },
+ [0x1EE8B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x644 },
+ unicodeslot=0x1EE8B,
+ },
+ [0x1EE8C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x645 },
+ unicodeslot=0x1EE8C,
+ },
+ [0x1EE8D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EE8D,
+ },
+ [0x1EE8E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EE8E,
+ },
+ [0x1EE8F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EE8F,
+ },
+ [0x1EE90]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x641 },
+ unicodeslot=0x1EE90,
+ },
+ [0x1EE91]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EE91,
+ },
+ [0x1EE92]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EE92,
+ },
+ [0x1EE93]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x631 },
+ unicodeslot=0x1EE93,
+ },
+ [0x1EE94]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EE94,
+ },
+ [0x1EE95]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62A },
+ unicodeslot=0x1EE95,
+ },
+ [0x1EE96]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62B },
+ unicodeslot=0x1EE96,
+ },
+ [0x1EE97]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EE97,
+ },
+ [0x1EE98]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x630 },
+ unicodeslot=0x1EE98,
+ },
+ [0x1EE99]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EE99,
+ },
+ [0x1EE9A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x638 },
+ unicodeslot=0x1EE9A,
+ },
+ [0x1EE9B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EE9B,
+ },
+ [0x1EEA1]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x628 },
+ unicodeslot=0x1EEA1,
+ },
+ [0x1EEA2]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62C },
+ unicodeslot=0x1EEA2,
+ },
+ [0x1EEA3]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62F },
+ unicodeslot=0x1EEA3,
+ },
+ [0x1EEA5]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x648 },
+ unicodeslot=0x1EEA5,
+ },
+ [0x1EEA6]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x632 },
+ unicodeslot=0x1EEA6,
+ },
+ [0x1EEA7]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62D },
+ unicodeslot=0x1EEA7,
+ },
+ [0x1EEA8]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x637 },
+ unicodeslot=0x1EEA8,
+ },
+ [0x1EEA9]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x64A },
+ unicodeslot=0x1EEA9,
+ },
+ [0x1EEAB]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x644 },
+ unicodeslot=0x1EEAB,
+ },
+ [0x1EEAC]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x645 },
+ unicodeslot=0x1EEAC,
+ },
+ [0x1EEAD]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x646 },
+ unicodeslot=0x1EEAD,
+ },
+ [0x1EEAE]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x633 },
+ unicodeslot=0x1EEAE,
+ },
+ [0x1EEAF]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x639 },
+ unicodeslot=0x1EEAF,
+ },
+ [0x1EEB0]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x641 },
+ unicodeslot=0x1EEB0,
+ },
+ [0x1EEB1]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x635 },
+ unicodeslot=0x1EEB1,
+ },
+ [0x1EEB2]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x642 },
+ unicodeslot=0x1EEB2,
+ },
+ [0x1EEB3]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x631 },
+ unicodeslot=0x1EEB3,
+ },
+ [0x1EEB4]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x634 },
+ unicodeslot=0x1EEB4,
+ },
+ [0x1EEB5]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62A },
+ unicodeslot=0x1EEB5,
+ },
+ [0x1EEB6]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62B },
+ unicodeslot=0x1EEB6,
+ },
+ [0x1EEB7]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x62E },
+ unicodeslot=0x1EEB7,
+ },
+ [0x1EEB8]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x630 },
+ unicodeslot=0x1EEB8,
+ },
+ [0x1EEB9]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x636 },
+ unicodeslot=0x1EEB9,
+ },
+ [0x1EEBA]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x638 },
+ unicodeslot=0x1EEBA,
+ },
+ [0x1EEBB]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x63A },
+ unicodeslot=0x1EEBB,
+ },
+ [0x1EEF0]={
+ category="sm",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1EEF0,
+ },
+ [0x1EEF1]={
+ category="sm",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL OPERATOR HAH WITH DAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1EEF1,
+ },
+ [0x1F000]={
+ category="so",
+ description="MAHJONG TILE EAST WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F000,
+ },
+ [0x1F001]={
+ category="so",
+ description="MAHJONG TILE SOUTH WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F001,
+ },
+ [0x1F002]={
+ category="so",
+ description="MAHJONG TILE WEST WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F002,
+ },
+ [0x1F003]={
+ category="so",
+ description="MAHJONG TILE NORTH WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F003,
+ },
+ [0x1F004]={
+ category="so",
+ description="MAHJONG TILE RED DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F004,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F005]={
+ category="so",
+ description="MAHJONG TILE GREEN DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F005,
+ },
+ [0x1F006]={
+ category="so",
+ description="MAHJONG TILE WHITE DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F006,
+ },
+ [0x1F007]={
+ category="so",
+ description="MAHJONG TILE ONE OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F007,
+ },
+ [0x1F008]={
+ category="so",
+ description="MAHJONG TILE TWO OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F008,
+ },
+ [0x1F009]={
+ category="so",
+ description="MAHJONG TILE THREE OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F009,
+ },
+ [0x1F00A]={
+ category="so",
+ description="MAHJONG TILE FOUR OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00A,
+ },
+ [0x1F00B]={
+ category="so",
+ description="MAHJONG TILE FIVE OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00B,
+ },
+ [0x1F00C]={
+ category="so",
+ description="MAHJONG TILE SIX OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00C,
+ },
+ [0x1F00D]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00D,
+ },
+ [0x1F00E]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00E,
+ },
+ [0x1F00F]={
+ category="so",
+ description="MAHJONG TILE NINE OF CHARACTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F00F,
+ },
+ [0x1F010]={
+ category="so",
+ description="MAHJONG TILE ONE OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F010,
+ },
+ [0x1F011]={
+ category="so",
+ description="MAHJONG TILE TWO OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F011,
+ },
+ [0x1F012]={
+ category="so",
+ description="MAHJONG TILE THREE OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F012,
+ },
+ [0x1F013]={
+ category="so",
+ description="MAHJONG TILE FOUR OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F013,
+ },
+ [0x1F014]={
+ category="so",
+ description="MAHJONG TILE FIVE OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F014,
+ },
+ [0x1F015]={
+ category="so",
+ description="MAHJONG TILE SIX OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F015,
+ },
+ [0x1F016]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F016,
+ },
+ [0x1F017]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F017,
+ },
+ [0x1F018]={
+ category="so",
+ description="MAHJONG TILE NINE OF BAMBOOS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F018,
+ },
+ [0x1F019]={
+ category="so",
+ description="MAHJONG TILE ONE OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F019,
+ },
+ [0x1F01A]={
+ category="so",
+ description="MAHJONG TILE TWO OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01A,
+ },
+ [0x1F01B]={
+ category="so",
+ description="MAHJONG TILE THREE OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01B,
+ },
+ [0x1F01C]={
+ category="so",
+ description="MAHJONG TILE FOUR OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01C,
+ },
+ [0x1F01D]={
+ category="so",
+ description="MAHJONG TILE FIVE OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01D,
+ },
+ [0x1F01E]={
+ category="so",
+ description="MAHJONG TILE SIX OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01E,
+ },
+ [0x1F01F]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F01F,
+ },
+ [0x1F020]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F020,
+ },
+ [0x1F021]={
+ category="so",
+ description="MAHJONG TILE NINE OF CIRCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F021,
+ },
+ [0x1F022]={
+ category="so",
+ description="MAHJONG TILE PLUM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F022,
+ },
+ [0x1F023]={
+ category="so",
+ description="MAHJONG TILE ORCHID",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F023,
+ },
+ [0x1F024]={
+ category="so",
+ description="MAHJONG TILE BAMBOO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F024,
+ },
+ [0x1F025]={
+ category="so",
+ description="MAHJONG TILE CHRYSANTHEMUM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F025,
+ },
+ [0x1F026]={
+ category="so",
+ description="MAHJONG TILE SPRING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F026,
+ },
+ [0x1F027]={
+ category="so",
+ description="MAHJONG TILE SUMMER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F027,
+ },
+ [0x1F028]={
+ category="so",
+ description="MAHJONG TILE AUTUMN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F028,
+ },
+ [0x1F029]={
+ category="so",
+ description="MAHJONG TILE WINTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F029,
+ },
+ [0x1F02A]={
+ category="so",
+ description="MAHJONG TILE JOKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F02A,
+ },
+ [0x1F02B]={
+ category="so",
+ description="MAHJONG TILE BACK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F02B,
+ },
+ [0x1F030]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL BACK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F030,
+ },
+ [0x1F031]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F031,
+ },
+ [0x1F032]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F032,
+ },
+ [0x1F033]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F033,
+ },
+ [0x1F034]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F034,
+ },
+ [0x1F035]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F035,
+ },
+ [0x1F036]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F036,
+ },
+ [0x1F037]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F037,
+ },
+ [0x1F038]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F038,
+ },
+ [0x1F039]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F039,
+ },
+ [0x1F03A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03A,
+ },
+ [0x1F03B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03B,
+ },
+ [0x1F03C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03C,
+ },
+ [0x1F03D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03D,
+ },
+ [0x1F03E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03E,
+ },
+ [0x1F03F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F03F,
+ },
+ [0x1F040]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F040,
+ },
+ [0x1F041]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F041,
+ },
+ [0x1F042]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F042,
+ },
+ [0x1F043]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F043,
+ },
+ [0x1F044]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F044,
+ },
+ [0x1F045]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F045,
+ },
+ [0x1F046]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F046,
+ },
+ [0x1F047]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F047,
+ },
+ [0x1F048]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F048,
+ },
+ [0x1F049]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F049,
+ },
+ [0x1F04A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04A,
+ },
+ [0x1F04B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04B,
+ },
+ [0x1F04C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04C,
+ },
+ [0x1F04D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04D,
+ },
+ [0x1F04E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04E,
+ },
+ [0x1F04F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F04F,
+ },
+ [0x1F050]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F050,
+ },
+ [0x1F051]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F051,
+ },
+ [0x1F052]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F052,
+ },
+ [0x1F053]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F053,
+ },
+ [0x1F054]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F054,
+ },
+ [0x1F055]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F055,
+ },
+ [0x1F056]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F056,
+ },
+ [0x1F057]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F057,
+ },
+ [0x1F058]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F058,
+ },
+ [0x1F059]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F059,
+ },
+ [0x1F05A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05A,
+ },
+ [0x1F05B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05B,
+ },
+ [0x1F05C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05C,
+ },
+ [0x1F05D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05D,
+ },
+ [0x1F05E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05E,
+ },
+ [0x1F05F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F05F,
+ },
+ [0x1F060]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F060,
+ },
+ [0x1F061]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F061,
+ },
+ [0x1F062]={
+ category="so",
+ description="DOMINO TILE VERTICAL BACK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F062,
+ },
+ [0x1F063]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F063,
+ },
+ [0x1F064]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F064,
+ },
+ [0x1F065]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F065,
+ },
+ [0x1F066]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F066,
+ },
+ [0x1F067]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F067,
+ },
+ [0x1F068]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F068,
+ },
+ [0x1F069]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F069,
+ },
+ [0x1F06A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06A,
+ },
+ [0x1F06B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06B,
+ },
+ [0x1F06C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06C,
+ },
+ [0x1F06D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06D,
+ },
+ [0x1F06E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06E,
+ },
+ [0x1F06F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F06F,
+ },
+ [0x1F070]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F070,
+ },
+ [0x1F071]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F071,
+ },
+ [0x1F072]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F072,
+ },
+ [0x1F073]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F073,
+ },
+ [0x1F074]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F074,
+ },
+ [0x1F075]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F075,
+ },
+ [0x1F076]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F076,
+ },
+ [0x1F077]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F077,
+ },
+ [0x1F078]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F078,
+ },
+ [0x1F079]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F079,
+ },
+ [0x1F07A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07A,
+ },
+ [0x1F07B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07B,
+ },
+ [0x1F07C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07C,
+ },
+ [0x1F07D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07D,
+ },
+ [0x1F07E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07E,
+ },
+ [0x1F07F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F07F,
+ },
+ [0x1F080]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F080,
+ },
+ [0x1F081]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F081,
+ },
+ [0x1F082]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F082,
+ },
+ [0x1F083]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F083,
+ },
+ [0x1F084]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F084,
+ },
+ [0x1F085]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F085,
+ },
+ [0x1F086]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F086,
+ },
+ [0x1F087]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F087,
+ },
+ [0x1F088]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F088,
+ },
+ [0x1F089]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F089,
+ },
+ [0x1F08A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08A,
+ },
+ [0x1F08B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08B,
+ },
+ [0x1F08C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08C,
+ },
+ [0x1F08D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-00",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08D,
+ },
+ [0x1F08E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-01",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08E,
+ },
+ [0x1F08F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-02",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F08F,
+ },
+ [0x1F090]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-03",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F090,
+ },
+ [0x1F091]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-04",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F091,
+ },
+ [0x1F092]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-05",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F092,
+ },
+ [0x1F093]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-06",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F093,
+ },
+ [0x1F0A0]={
+ category="so",
+ description="PLAYING CARD BACK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A0,
+ },
+ [0x1F0A1]={
+ category="so",
+ description="PLAYING CARD ACE OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A1,
+ },
+ [0x1F0A2]={
+ category="so",
+ description="PLAYING CARD TWO OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A2,
+ },
+ [0x1F0A3]={
+ category="so",
+ description="PLAYING CARD THREE OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A3,
+ },
+ [0x1F0A4]={
+ category="so",
+ description="PLAYING CARD FOUR OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A4,
+ },
+ [0x1F0A5]={
+ category="so",
+ description="PLAYING CARD FIVE OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A5,
+ },
+ [0x1F0A6]={
+ category="so",
+ description="PLAYING CARD SIX OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A6,
+ },
+ [0x1F0A7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A7,
+ },
+ [0x1F0A8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A8,
+ },
+ [0x1F0A9]={
+ category="so",
+ description="PLAYING CARD NINE OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0A9,
+ },
+ [0x1F0AA]={
+ category="so",
+ description="PLAYING CARD TEN OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0AA,
+ },
+ [0x1F0AB]={
+ category="so",
+ description="PLAYING CARD JACK OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0AB,
+ },
+ [0x1F0AC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0AC,
+ },
+ [0x1F0AD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0AD,
+ },
+ [0x1F0AE]={
+ category="so",
+ description="PLAYING CARD KING OF SPADES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0AE,
+ },
+ [0x1F0B1]={
+ category="so",
+ description="PLAYING CARD ACE OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B1,
+ },
+ [0x1F0B2]={
+ category="so",
+ description="PLAYING CARD TWO OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B2,
+ },
+ [0x1F0B3]={
+ category="so",
+ description="PLAYING CARD THREE OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B3,
+ },
+ [0x1F0B4]={
+ category="so",
+ description="PLAYING CARD FOUR OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B4,
+ },
+ [0x1F0B5]={
+ category="so",
+ description="PLAYING CARD FIVE OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B5,
+ },
+ [0x1F0B6]={
+ category="so",
+ description="PLAYING CARD SIX OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B6,
+ },
+ [0x1F0B7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B7,
+ },
+ [0x1F0B8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B8,
+ },
+ [0x1F0B9]={
+ category="so",
+ description="PLAYING CARD NINE OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0B9,
+ },
+ [0x1F0BA]={
+ category="so",
+ description="PLAYING CARD TEN OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BA,
+ },
+ [0x1F0BB]={
+ category="so",
+ description="PLAYING CARD JACK OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BB,
+ },
+ [0x1F0BC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BC,
+ },
+ [0x1F0BD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BD,
+ },
+ [0x1F0BE]={
+ category="so",
+ description="PLAYING CARD KING OF HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BE,
+ },
+ [0x1F0BF]={
+ category="so",
+ description="PLAYING CARD RED JOKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0BF,
+ },
+ [0x1F0C1]={
+ category="so",
+ description="PLAYING CARD ACE OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C1,
+ },
+ [0x1F0C2]={
+ category="so",
+ description="PLAYING CARD TWO OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C2,
+ },
+ [0x1F0C3]={
+ category="so",
+ description="PLAYING CARD THREE OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C3,
+ },
+ [0x1F0C4]={
+ category="so",
+ description="PLAYING CARD FOUR OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C4,
+ },
+ [0x1F0C5]={
+ category="so",
+ description="PLAYING CARD FIVE OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C5,
+ },
+ [0x1F0C6]={
+ category="so",
+ description="PLAYING CARD SIX OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C6,
+ },
+ [0x1F0C7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C7,
+ },
+ [0x1F0C8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C8,
+ },
+ [0x1F0C9]={
+ category="so",
+ description="PLAYING CARD NINE OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0C9,
+ },
+ [0x1F0CA]={
+ category="so",
+ description="PLAYING CARD TEN OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CA,
+ },
+ [0x1F0CB]={
+ category="so",
+ description="PLAYING CARD JACK OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CB,
+ },
+ [0x1F0CC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CC,
+ },
+ [0x1F0CD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CD,
+ },
+ [0x1F0CE]={
+ category="so",
+ description="PLAYING CARD KING OF DIAMONDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CE,
+ },
+ [0x1F0CF]={
+ category="so",
+ description="PLAYING CARD BLACK JOKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0CF,
+ },
+ [0x1F0D1]={
+ category="so",
+ description="PLAYING CARD ACE OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D1,
+ },
+ [0x1F0D2]={
+ category="so",
+ description="PLAYING CARD TWO OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D2,
+ },
+ [0x1F0D3]={
+ category="so",
+ description="PLAYING CARD THREE OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D3,
+ },
+ [0x1F0D4]={
+ category="so",
+ description="PLAYING CARD FOUR OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D4,
+ },
+ [0x1F0D5]={
+ category="so",
+ description="PLAYING CARD FIVE OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D5,
+ },
+ [0x1F0D6]={
+ category="so",
+ description="PLAYING CARD SIX OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D6,
+ },
+ [0x1F0D7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D7,
+ },
+ [0x1F0D8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D8,
+ },
+ [0x1F0D9]={
+ category="so",
+ description="PLAYING CARD NINE OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0D9,
+ },
+ [0x1F0DA]={
+ category="so",
+ description="PLAYING CARD TEN OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DA,
+ },
+ [0x1F0DB]={
+ category="so",
+ description="PLAYING CARD JACK OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DB,
+ },
+ [0x1F0DC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DC,
+ },
+ [0x1F0DD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DD,
+ },
+ [0x1F0DE]={
+ category="so",
+ description="PLAYING CARD KING OF CLUBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DE,
+ },
+ [0x1F0DF]={
+ category="so",
+ description="PLAYING CARD WHITE JOKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0DF,
+ },
+ [0x1F0E0]={
+ category="so",
+ description="PLAYING CARD FOOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E0,
+ },
+ [0x1F0E1]={
+ category="so",
+ description="PLAYING CARD TRUMP-1",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E1,
+ },
+ [0x1F0E2]={
+ category="so",
+ description="PLAYING CARD TRUMP-2",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E2,
+ },
+ [0x1F0E3]={
+ category="so",
+ description="PLAYING CARD TRUMP-3",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E3,
+ },
+ [0x1F0E4]={
+ category="so",
+ description="PLAYING CARD TRUMP-4",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E4,
+ },
+ [0x1F0E5]={
+ category="so",
+ description="PLAYING CARD TRUMP-5",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E5,
+ },
+ [0x1F0E6]={
+ category="so",
+ description="PLAYING CARD TRUMP-6",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E6,
+ },
+ [0x1F0E7]={
+ category="so",
+ description="PLAYING CARD TRUMP-7",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E7,
+ },
+ [0x1F0E8]={
+ category="so",
+ description="PLAYING CARD TRUMP-8",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E8,
+ },
+ [0x1F0E9]={
+ category="so",
+ description="PLAYING CARD TRUMP-9",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0E9,
+ },
+ [0x1F0EA]={
+ category="so",
+ description="PLAYING CARD TRUMP-10",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0EA,
+ },
+ [0x1F0EB]={
+ category="so",
+ description="PLAYING CARD TRUMP-11",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0EB,
+ },
+ [0x1F0EC]={
+ category="so",
+ description="PLAYING CARD TRUMP-12",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0EC,
+ },
+ [0x1F0ED]={
+ category="so",
+ description="PLAYING CARD TRUMP-13",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0ED,
+ },
+ [0x1F0EE]={
+ category="so",
+ description="PLAYING CARD TRUMP-14",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0EE,
+ },
+ [0x1F0EF]={
+ category="so",
+ description="PLAYING CARD TRUMP-15",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0EF,
+ },
+ [0x1F0F0]={
+ category="so",
+ description="PLAYING CARD TRUMP-16",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F0,
+ },
+ [0x1F0F1]={
+ category="so",
+ description="PLAYING CARD TRUMP-17",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F1,
+ },
+ [0x1F0F2]={
+ category="so",
+ description="PLAYING CARD TRUMP-18",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F2,
+ },
+ [0x1F0F3]={
+ category="so",
+ description="PLAYING CARD TRUMP-19",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F3,
+ },
+ [0x1F0F4]={
+ category="so",
+ description="PLAYING CARD TRUMP-20",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F4,
+ },
+ [0x1F0F5]={
+ category="so",
+ description="PLAYING CARD TRUMP-21",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F0F5,
+ },
+ [0x1F100]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ZERO FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x30, 0x2E },
+ unicodeslot=0x1F100,
+ },
+ [0x1F101]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ZERO COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x30, 0x2C },
+ unicodeslot=0x1F101,
+ },
+ [0x1F102]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ONE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x31, 0x2C },
+ unicodeslot=0x1F102,
+ },
+ [0x1F103]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT TWO COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x32, 0x2C },
+ unicodeslot=0x1F103,
+ },
+ [0x1F104]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT THREE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x33, 0x2C },
+ unicodeslot=0x1F104,
+ },
+ [0x1F105]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT FOUR COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x34, 0x2C },
+ unicodeslot=0x1F105,
+ },
+ [0x1F106]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT FIVE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x35, 0x2C },
+ unicodeslot=0x1F106,
+ },
+ [0x1F107]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT SIX COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x36, 0x2C },
+ unicodeslot=0x1F107,
+ },
+ [0x1F108]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT SEVEN COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x37, 0x2C },
+ unicodeslot=0x1F108,
+ },
+ [0x1F109]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT EIGHT COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x38, 0x2C },
+ unicodeslot=0x1F109,
+ },
+ [0x1F10A]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT NINE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x39, 0x2C },
+ unicodeslot=0x1F10A,
+ },
+ [0x1F10B]={
+ category="no",
+ description="DINGBAT CIRCLED SANS-SERIF DIGIT ZERO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x1F10B,
+ },
+ [0x1F10C]={
+ category="no",
+ description="DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x1F10C,
+ },
+ [0x1F110]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x41, 0x29 },
+ unicodeslot=0x1F110,
+ },
+ [0x1F111]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x42, 0x29 },
+ unicodeslot=0x1F111,
+ },
+ [0x1F112]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x43, 0x29 },
+ unicodeslot=0x1F112,
+ },
+ [0x1F113]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x44, 0x29 },
+ unicodeslot=0x1F113,
+ },
+ [0x1F114]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x45, 0x29 },
+ unicodeslot=0x1F114,
+ },
+ [0x1F115]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x46, 0x29 },
+ unicodeslot=0x1F115,
+ },
+ [0x1F116]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x47, 0x29 },
+ unicodeslot=0x1F116,
+ },
+ [0x1F117]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x48, 0x29 },
+ unicodeslot=0x1F117,
+ },
+ [0x1F118]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x49, 0x29 },
+ unicodeslot=0x1F118,
+ },
+ [0x1F119]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4A, 0x29 },
+ unicodeslot=0x1F119,
+ },
+ [0x1F11A]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4B, 0x29 },
+ unicodeslot=0x1F11A,
+ },
+ [0x1F11B]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4C, 0x29 },
+ unicodeslot=0x1F11B,
+ },
+ [0x1F11C]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4D, 0x29 },
+ unicodeslot=0x1F11C,
+ },
+ [0x1F11D]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4E, 0x29 },
+ unicodeslot=0x1F11D,
+ },
+ [0x1F11E]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x4F, 0x29 },
+ unicodeslot=0x1F11E,
+ },
+ [0x1F11F]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x50, 0x29 },
+ unicodeslot=0x1F11F,
+ },
+ [0x1F120]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x51, 0x29 },
+ unicodeslot=0x1F120,
+ },
+ [0x1F121]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x52, 0x29 },
+ unicodeslot=0x1F121,
+ },
+ [0x1F122]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x53, 0x29 },
+ unicodeslot=0x1F122,
+ },
+ [0x1F123]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x54, 0x29 },
+ unicodeslot=0x1F123,
+ },
+ [0x1F124]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x55, 0x29 },
+ unicodeslot=0x1F124,
+ },
+ [0x1F125]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x56, 0x29 },
+ unicodeslot=0x1F125,
+ },
+ [0x1F126]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x57, 0x29 },
+ unicodeslot=0x1F126,
+ },
+ [0x1F127]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x58, 0x29 },
+ unicodeslot=0x1F127,
+ },
+ [0x1F128]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x59, 0x29 },
+ unicodeslot=0x1F128,
+ },
+ [0x1F129]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x28, 0x5A, 0x29 },
+ unicodeslot=0x1F129,
+ },
+ [0x1F12A]={
+ category="so",
+ cjkwd="a",
+ description="TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x3014, 0x53, 0x3015 },
+ unicodeslot=0x1F12A,
+ },
+ [0x1F12B]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED ITALIC LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x43 },
+ unicodeslot=0x1F12B,
+ },
+ [0x1F12C]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED ITALIC LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x52 },
+ unicodeslot=0x1F12C,
+ },
+ [0x1F12D]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED CD",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x43, 0x44 },
+ unicodeslot=0x1F12D,
+ },
+ [0x1F12E]={
+ category="so",
+ description="CIRCLED WZ",
+ direction="l",
+ linebreak="al",
+ specials={ "circle", 0x57, 0x5A },
+ unicodeslot=0x1F12E,
+ },
+ [0x1F130]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x41 },
+ unicodeslot=0x1F130,
+ },
+ [0x1F131]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x42 },
+ unicodeslot=0x1F131,
+ },
+ [0x1F132]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x43 },
+ unicodeslot=0x1F132,
+ },
+ [0x1F133]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x44 },
+ unicodeslot=0x1F133,
+ },
+ [0x1F134]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x45 },
+ unicodeslot=0x1F134,
+ },
+ [0x1F135]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x46 },
+ unicodeslot=0x1F135,
+ },
+ [0x1F136]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x47 },
+ unicodeslot=0x1F136,
+ },
+ [0x1F137]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x48 },
+ unicodeslot=0x1F137,
+ },
+ [0x1F138]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x49 },
+ unicodeslot=0x1F138,
+ },
+ [0x1F139]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4A },
+ unicodeslot=0x1F139,
+ },
+ [0x1F13A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4B },
+ unicodeslot=0x1F13A,
+ },
+ [0x1F13B]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4C },
+ unicodeslot=0x1F13B,
+ },
+ [0x1F13C]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4D },
+ unicodeslot=0x1F13C,
+ },
+ [0x1F13D]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4E },
+ unicodeslot=0x1F13D,
+ },
+ [0x1F13E]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4F },
+ unicodeslot=0x1F13E,
+ },
+ [0x1F13F]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x50 },
+ unicodeslot=0x1F13F,
+ },
+ [0x1F140]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x51 },
+ unicodeslot=0x1F140,
+ },
+ [0x1F141]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x52 },
+ unicodeslot=0x1F141,
+ },
+ [0x1F142]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x53 },
+ unicodeslot=0x1F142,
+ },
+ [0x1F143]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x54 },
+ unicodeslot=0x1F143,
+ },
+ [0x1F144]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x55 },
+ unicodeslot=0x1F144,
+ },
+ [0x1F145]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x56 },
+ unicodeslot=0x1F145,
+ },
+ [0x1F146]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x57 },
+ unicodeslot=0x1F146,
+ },
+ [0x1F147]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x58 },
+ unicodeslot=0x1F147,
+ },
+ [0x1F148]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x59 },
+ unicodeslot=0x1F148,
+ },
+ [0x1F149]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x5A },
+ unicodeslot=0x1F149,
+ },
+ [0x1F14A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED HV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x48, 0x56 },
+ unicodeslot=0x1F14A,
+ },
+ [0x1F14B]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED MV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x4D, 0x56 },
+ unicodeslot=0x1F14B,
+ },
+ [0x1F14C]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SD",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x53, 0x44 },
+ unicodeslot=0x1F14C,
+ },
+ [0x1F14D]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SS",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x53, 0x53 },
+ unicodeslot=0x1F14D,
+ },
+ [0x1F14E]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED PPV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x50, 0x50, 0x56 },
+ unicodeslot=0x1F14E,
+ },
+ [0x1F14F]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED WC",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x57, 0x43 },
+ unicodeslot=0x1F14F,
+ },
+ [0x1F150]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F150,
+ },
+ [0x1F151]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F151,
+ },
+ [0x1F152]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F152,
+ },
+ [0x1F153]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F153,
+ },
+ [0x1F154]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F154,
+ },
+ [0x1F155]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F155,
+ },
+ [0x1F156]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F156,
+ },
+ [0x1F157]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F157,
+ },
+ [0x1F158]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F158,
+ },
+ [0x1F159]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F159,
+ },
+ [0x1F15A]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15A,
+ },
+ [0x1F15B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15B,
+ },
+ [0x1F15C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15C,
+ },
+ [0x1F15D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15D,
+ },
+ [0x1F15E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15E,
+ },
+ [0x1F15F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15F,
+ },
+ [0x1F160]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F160,
+ },
+ [0x1F161]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F161,
+ },
+ [0x1F162]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F162,
+ },
+ [0x1F163]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F163,
+ },
+ [0x1F164]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F164,
+ },
+ [0x1F165]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F165,
+ },
+ [0x1F166]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F166,
+ },
+ [0x1F167]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F167,
+ },
+ [0x1F168]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F168,
+ },
+ [0x1F169]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F169,
+ },
+ [0x1F16A]={
+ category="so",
+ description="RAISED MC SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x4D, 0x43 },
+ unicodeslot=0x1F16A,
+ },
+ [0x1F16B]={
+ category="so",
+ description="RAISED MD SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x4D, 0x44 },
+ unicodeslot=0x1F16B,
+ },
+ [0x1F170]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F170,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F171]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F171,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F172]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F172,
+ },
+ [0x1F173]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F173,
+ },
+ [0x1F174]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F174,
+ },
+ [0x1F175]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F175,
+ },
+ [0x1F176]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F176,
+ },
+ [0x1F177]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F177,
+ },
+ [0x1F178]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F178,
+ },
+ [0x1F179]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F179,
+ },
+ [0x1F17A]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17A,
+ },
+ [0x1F17B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17B,
+ },
+ [0x1F17C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17C,
+ },
+ [0x1F17D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17D,
+ },
+ [0x1F17E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17E,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F17F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F180]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F180,
+ },
+ [0x1F181]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F181,
+ },
+ [0x1F182]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F182,
+ },
+ [0x1F183]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F183,
+ },
+ [0x1F184]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F184,
+ },
+ [0x1F185]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F185,
+ },
+ [0x1F186]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F186,
+ },
+ [0x1F187]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F187,
+ },
+ [0x1F188]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F188,
+ },
+ [0x1F189]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F189,
+ },
+ [0x1F18A]={
+ category="so",
+ cjkwd="a",
+ description="CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18A,
+ },
+ [0x1F18B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED IC",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18B,
+ },
+ [0x1F18C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED PA",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18C,
+ },
+ [0x1F18D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED SA",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18D,
+ },
+ [0x1F18E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED AB",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18E,
+ },
+ [0x1F18F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED WC",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18F,
+ },
+ [0x1F190]={
+ category="so",
+ cjkwd="a",
+ description="SQUARE DJ",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x44, 0x4A },
+ unicodeslot=0x1F190,
+ },
+ [0x1F191]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED CL",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F191,
+ },
+ [0x1F192]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED COOL",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F192,
+ },
+ [0x1F193]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED FREE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F193,
+ },
+ [0x1F194]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED ID",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F194,
+ },
+ [0x1F195]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED NEW",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F195,
+ },
+ [0x1F196]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED NG",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F196,
+ },
+ [0x1F197]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED OK",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F197,
+ },
+ [0x1F198]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SOS",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F198,
+ },
+ [0x1F199]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED UP WITH EXCLAMATION MARK",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F199,
+ },
+ [0x1F19A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED VS",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F19A,
+ },
+ [0x1F1E6]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER A",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1E6,
+ },
+ [0x1F1E7]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER B",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1E7,
+ },
+ [0x1F1E8]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER C",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1E8,
+ },
+ [0x1F1E9]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER D",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1E9,
+ },
+ [0x1F1EA]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER E",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1EA,
+ },
+ [0x1F1EB]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER F",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1EB,
+ },
+ [0x1F1EC]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER G",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1EC,
+ },
+ [0x1F1ED]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER H",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1ED,
+ },
+ [0x1F1EE]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER I",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1EE,
+ },
+ [0x1F1EF]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER J",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1EF,
+ },
+ [0x1F1F0]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER K",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F0,
+ },
+ [0x1F1F1]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER L",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F1,
+ },
+ [0x1F1F2]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER M",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F2,
+ },
+ [0x1F1F3]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER N",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F3,
+ },
+ [0x1F1F4]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER O",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F4,
+ },
+ [0x1F1F5]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER P",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F5,
+ },
+ [0x1F1F6]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Q",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F6,
+ },
+ [0x1F1F7]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER R",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F7,
+ },
+ [0x1F1F8]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER S",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F8,
+ },
+ [0x1F1F9]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER T",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1F9,
+ },
+ [0x1F1FA]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER U",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FA,
+ },
+ [0x1F1FB]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER V",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FB,
+ },
+ [0x1F1FC]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER W",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FC,
+ },
+ [0x1F1FD]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER X",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FD,
+ },
+ [0x1F1FE]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Y",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FE,
+ },
+ [0x1F1FF]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Z",
+ direction="l",
+ linebreak="ri",
+ unicodeslot=0x1F1FF,
+ },
+ [0x1F200]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HIRAGANA HOKA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x307B, 0x304B },
+ unicodeslot=0x1F200,
+ },
+ [0x1F201]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA KOKO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B3, 0x30B3 },
+ unicodeslot=0x1F201,
+ },
+ [0x1F202]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA SA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B5 },
+ unicodeslot=0x1F202,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F210]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-624B",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x624B },
+ unicodeslot=0x1F210,
+ },
+ [0x1F211]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5B57",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5B57 },
+ unicodeslot=0x1F211,
+ },
+ [0x1F212]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-53CC",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x53CC },
+ unicodeslot=0x1F212,
+ },
+ [0x1F213]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA DE",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C7 },
+ unicodeslot=0x1F213,
+ },
+ [0x1F214]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E8C",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E8C },
+ unicodeslot=0x1F214,
+ },
+ [0x1F215]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-591A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x591A },
+ unicodeslot=0x1F215,
+ },
+ [0x1F216]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-89E3",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x89E3 },
+ unicodeslot=0x1F216,
+ },
+ [0x1F217]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5929",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5929 },
+ unicodeslot=0x1F217,
+ },
+ [0x1F218]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4EA4",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4EA4 },
+ unicodeslot=0x1F218,
+ },
+ [0x1F219]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6620",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6620 },
+ unicodeslot=0x1F219,
+ },
+ [0x1F21A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7121",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7121 },
+ unicodeslot=0x1F21A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F21B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6599",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6599 },
+ unicodeslot=0x1F21B,
+ },
+ [0x1F21C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-524D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x524D },
+ unicodeslot=0x1F21C,
+ },
+ [0x1F21D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5F8C",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5F8C },
+ unicodeslot=0x1F21D,
+ },
+ [0x1F21E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-518D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x518D },
+ unicodeslot=0x1F21E,
+ },
+ [0x1F21F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-65B0",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x65B0 },
+ unicodeslot=0x1F21F,
+ },
+ [0x1F220]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-521D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x521D },
+ unicodeslot=0x1F220,
+ },
+ [0x1F221]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7D42",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7D42 },
+ unicodeslot=0x1F221,
+ },
+ [0x1F222]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-751F",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x751F },
+ unicodeslot=0x1F222,
+ },
+ [0x1F223]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-8CA9",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x8CA9 },
+ unicodeslot=0x1F223,
+ },
+ [0x1F224]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-58F0",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x58F0 },
+ unicodeslot=0x1F224,
+ },
+ [0x1F225]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5439",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5439 },
+ unicodeslot=0x1F225,
+ },
+ [0x1F226]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6F14",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6F14 },
+ unicodeslot=0x1F226,
+ },
+ [0x1F227]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6295",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6295 },
+ unicodeslot=0x1F227,
+ },
+ [0x1F228]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6355",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6355 },
+ unicodeslot=0x1F228,
+ },
+ [0x1F229]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E00",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E00 },
+ unicodeslot=0x1F229,
+ },
+ [0x1F22A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E09",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E09 },
+ unicodeslot=0x1F22A,
+ },
+ [0x1F22B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-904A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x904A },
+ unicodeslot=0x1F22B,
+ },
+ [0x1F22C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5DE6",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5DE6 },
+ unicodeslot=0x1F22C,
+ },
+ [0x1F22D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E2D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E2D },
+ unicodeslot=0x1F22D,
+ },
+ [0x1F22E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-53F3",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x53F3 },
+ unicodeslot=0x1F22E,
+ },
+ [0x1F22F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6307",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6307 },
+ unicodeslot=0x1F22F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F230]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-8D70",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x8D70 },
+ unicodeslot=0x1F230,
+ },
+ [0x1F231]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6253",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6253 },
+ unicodeslot=0x1F231,
+ },
+ [0x1F232]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7981",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7981 },
+ unicodeslot=0x1F232,
+ },
+ [0x1F233]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7A7A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7A7A },
+ unicodeslot=0x1F233,
+ },
+ [0x1F234]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5408",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5408 },
+ unicodeslot=0x1F234,
+ },
+ [0x1F235]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6E80",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E80 },
+ unicodeslot=0x1F235,
+ },
+ [0x1F236]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6709",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6709 },
+ unicodeslot=0x1F236,
+ },
+ [0x1F237]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6708",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6708 },
+ unicodeslot=0x1F237,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
+ },
+ [0x1F238]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7533",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7533 },
+ unicodeslot=0x1F238,
+ },
+ [0x1F239]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5272",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5272 },
+ unicodeslot=0x1F239,
+ },
+ [0x1F23A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-55B6",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x55B6 },
+ unicodeslot=0x1F23A,
+ },
+ [0x1F240]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x672C, 0x3015 },
+ unicodeslot=0x1F240,
+ },
+ [0x1F241]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x4E09, 0x3015 },
+ unicodeslot=0x1F241,
+ },
+ [0x1F242]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x4E8C, 0x3015 },
+ unicodeslot=0x1F242,
+ },
+ [0x1F243]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x5B89, 0x3015 },
+ unicodeslot=0x1F243,
+ },
+ [0x1F244]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x70B9, 0x3015 },
+ unicodeslot=0x1F244,
+ },
+ [0x1F245]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x6253, 0x3015 },
+ unicodeslot=0x1F245,
+ },
+ [0x1F246]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x76D7, 0x3015 },
+ unicodeslot=0x1F246,
+ },
+ [0x1F247]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x52DD, 0x3015 },
+ unicodeslot=0x1F247,
+ },
+ [0x1F248]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x6557, 0x3015 },
+ unicodeslot=0x1F248,
+ },
+ [0x1F250]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ADVANTAGE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5F97 },
+ unicodeslot=0x1F250,
+ },
+ [0x1F251]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ACCEPT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x53EF },
+ unicodeslot=0x1F251,
+ },
+ [0x1F300]={
+ category="so",
+ description="CYCLONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F300,
+ },
+ [0x1F301]={
+ category="so",
+ description="FOGGY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F301,
+ },
+ [0x1F302]={
+ category="so",
+ description="CLOSED UMBRELLA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F302,
+ },
+ [0x1F303]={
+ category="so",
+ description="NIGHT WITH STARS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F303,
+ },
+ [0x1F304]={
+ category="so",
+ description="SUNRISE OVER MOUNTAINS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F304,
+ },
+ [0x1F305]={
+ category="so",
+ description="SUNRISE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F305,
+ },
+ [0x1F306]={
+ category="so",
+ description="CITYSCAPE AT DUSK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F306,
+ },
+ [0x1F307]={
+ category="so",
+ description="SUNSET OVER BUILDINGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F307,
+ },
+ [0x1F308]={
+ category="so",
+ description="RAINBOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F308,
+ },
+ [0x1F309]={
+ category="so",
+ description="BRIDGE AT NIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F309,
+ },
+ [0x1F30A]={
+ category="so",
+ description="WATER WAVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30A,
+ },
+ [0x1F30B]={
+ category="so",
+ description="VOLCANO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30B,
+ },
+ [0x1F30C]={
+ category="so",
+ description="MILKY WAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30C,
+ },
+ [0x1F30D]={
+ category="so",
+ description="EARTH GLOBE EUROPE-AFRICA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30D,
+ },
+ [0x1F30E]={
+ category="so",
+ description="EARTH GLOBE AMERICAS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30E,
+ },
+ [0x1F30F]={
+ category="so",
+ description="EARTH GLOBE ASIA-AUSTRALIA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F30F,
+ },
+ [0x1F310]={
+ category="so",
+ description="GLOBE WITH MERIDIANS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F310,
+ },
+ [0x1F311]={
+ category="so",
+ description="NEW MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F311,
+ },
+ [0x1F312]={
+ category="so",
+ description="WAXING CRESCENT MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F312,
+ },
+ [0x1F313]={
+ category="so",
+ description="FIRST QUARTER MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F313,
+ },
+ [0x1F314]={
+ category="so",
+ description="WAXING GIBBOUS MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F314,
+ },
+ [0x1F315]={
+ category="so",
+ description="FULL MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F315,
+ },
+ [0x1F316]={
+ category="so",
+ description="WANING GIBBOUS MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F316,
+ },
+ [0x1F317]={
+ category="so",
+ description="LAST QUARTER MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F317,
+ },
+ [0x1F318]={
+ category="so",
+ description="WANING CRESCENT MOON SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F318,
+ },
+ [0x1F319]={
+ category="so",
+ description="CRESCENT MOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F319,
+ },
+ [0x1F31A]={
+ category="so",
+ description="NEW MOON WITH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31A,
+ },
+ [0x1F31B]={
+ category="so",
+ description="FIRST QUARTER MOON WITH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31B,
+ },
+ [0x1F31C]={
+ category="so",
+ description="LAST QUARTER MOON WITH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31C,
+ },
+ [0x1F31D]={
+ category="so",
+ description="FULL MOON WITH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31D,
+ },
+ [0x1F31E]={
+ category="so",
+ description="SUN WITH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31E,
+ },
+ [0x1F31F]={
+ category="so",
+ description="GLOWING STAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F31F,
+ },
+ [0x1F320]={
+ category="so",
+ description="SHOOTING STAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F320,
+ },
+ [0x1F321]={
+ category="so",
+ description="THERMOMETER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F321,
+ },
+ [0x1F322]={
+ category="so",
+ description="BLACK DROPLET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F322,
+ },
+ [0x1F323]={
+ category="so",
+ description="WHITE SUN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F323,
+ },
+ [0x1F324]={
+ category="so",
+ description="WHITE SUN WITH SMALL CLOUD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F324,
+ },
+ [0x1F325]={
+ category="so",
+ description="WHITE SUN BEHIND CLOUD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F325,
+ },
+ [0x1F326]={
+ category="so",
+ description="WHITE SUN BEHIND CLOUD WITH RAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F326,
+ },
+ [0x1F327]={
+ category="so",
+ description="CLOUD WITH RAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F327,
+ },
+ [0x1F328]={
+ category="so",
+ description="CLOUD WITH SNOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F328,
+ },
+ [0x1F329]={
+ category="so",
+ description="CLOUD WITH LIGHTNING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F329,
+ },
+ [0x1F32A]={
+ category="so",
+ description="CLOUD WITH TORNADO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32A,
+ },
+ [0x1F32B]={
+ category="so",
+ description="FOG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32B,
+ },
+ [0x1F32C]={
+ category="so",
+ description="WIND BLOWING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32C,
+ },
+ [0x1F32D]={
+ category="so",
+ description="HOT DOG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32D,
+ },
+ [0x1F32E]={
+ category="so",
+ description="TACO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32E,
+ },
+ [0x1F32F]={
+ category="so",
+ description="BURRITO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F32F,
+ },
+ [0x1F330]={
+ category="so",
+ description="CHESTNUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F330,
+ },
+ [0x1F331]={
+ category="so",
+ description="SEEDLING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F331,
+ },
+ [0x1F332]={
+ category="so",
+ description="EVERGREEN TREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F332,
+ },
+ [0x1F333]={
+ category="so",
+ description="DECIDUOUS TREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F333,
+ },
+ [0x1F334]={
+ category="so",
+ description="PALM TREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F334,
+ },
+ [0x1F335]={
+ category="so",
+ description="CACTUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F335,
+ },
+ [0x1F336]={
+ category="so",
+ description="HOT PEPPER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F336,
+ },
+ [0x1F337]={
+ category="so",
+ description="TULIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F337,
+ },
+ [0x1F338]={
+ category="so",
+ description="CHERRY BLOSSOM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F338,
+ },
+ [0x1F339]={
+ category="so",
+ description="ROSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F339,
+ },
+ [0x1F33A]={
+ category="so",
+ description="HIBISCUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33A,
+ },
+ [0x1F33B]={
+ category="so",
+ description="SUNFLOWER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33B,
+ },
+ [0x1F33C]={
+ category="so",
+ description="BLOSSOM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33C,
+ },
+ [0x1F33D]={
+ category="so",
+ description="EAR OF MAIZE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33D,
+ },
+ [0x1F33E]={
+ category="so",
+ description="EAR OF RICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33E,
+ },
+ [0x1F33F]={
+ category="so",
+ description="HERB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F33F,
+ },
+ [0x1F340]={
+ category="so",
+ description="FOUR LEAF CLOVER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F340,
+ },
+ [0x1F341]={
+ category="so",
+ description="MAPLE LEAF",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F341,
+ },
+ [0x1F342]={
+ category="so",
+ description="FALLEN LEAF",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F342,
+ },
+ [0x1F343]={
+ category="so",
+ description="LEAF FLUTTERING IN WIND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F343,
+ },
+ [0x1F344]={
+ category="so",
+ description="MUSHROOM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F344,
+ },
+ [0x1F345]={
+ category="so",
+ description="TOMATO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F345,
+ },
+ [0x1F346]={
+ category="so",
+ description="AUBERGINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F346,
+ },
+ [0x1F347]={
+ category="so",
+ description="GRAPES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F347,
+ },
+ [0x1F348]={
+ category="so",
+ description="MELON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F348,
+ },
+ [0x1F349]={
+ category="so",
+ description="WATERMELON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F349,
+ },
+ [0x1F34A]={
+ category="so",
+ description="TANGERINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34A,
+ },
+ [0x1F34B]={
+ category="so",
+ description="LEMON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34B,
+ },
+ [0x1F34C]={
+ category="so",
+ description="BANANA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34C,
+ },
+ [0x1F34D]={
+ category="so",
+ description="PINEAPPLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34D,
+ },
+ [0x1F34E]={
+ category="so",
+ description="RED APPLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34E,
+ },
+ [0x1F34F]={
+ category="so",
+ description="GREEN APPLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F34F,
+ },
+ [0x1F350]={
+ category="so",
+ description="PEAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F350,
+ },
+ [0x1F351]={
+ category="so",
+ description="PEACH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F351,
+ },
+ [0x1F352]={
+ category="so",
+ description="CHERRIES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F352,
+ },
+ [0x1F353]={
+ category="so",
+ description="STRAWBERRY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F353,
+ },
+ [0x1F354]={
+ category="so",
+ description="HAMBURGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F354,
+ },
+ [0x1F355]={
+ category="so",
+ description="SLICE OF PIZZA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F355,
+ },
+ [0x1F356]={
+ category="so",
+ description="MEAT ON BONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F356,
+ },
+ [0x1F357]={
+ category="so",
+ description="POULTRY LEG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F357,
+ },
+ [0x1F358]={
+ category="so",
+ description="RICE CRACKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F358,
+ },
+ [0x1F359]={
+ category="so",
+ description="RICE BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F359,
+ },
+ [0x1F35A]={
+ category="so",
+ description="COOKED RICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35A,
+ },
+ [0x1F35B]={
+ category="so",
+ description="CURRY AND RICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35B,
+ },
+ [0x1F35C]={
+ category="so",
+ description="STEAMING BOWL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35C,
+ },
+ [0x1F35D]={
+ category="so",
+ description="SPAGHETTI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35D,
+ },
+ [0x1F35E]={
+ category="so",
+ description="BREAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35E,
+ },
+ [0x1F35F]={
+ category="so",
+ description="FRENCH FRIES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F35F,
+ },
+ [0x1F360]={
+ category="so",
+ description="ROASTED SWEET POTATO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F360,
+ },
+ [0x1F361]={
+ category="so",
+ description="DANGO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F361,
+ },
+ [0x1F362]={
+ category="so",
+ description="ODEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F362,
+ },
+ [0x1F363]={
+ category="so",
+ description="SUSHI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F363,
+ },
+ [0x1F364]={
+ category="so",
+ description="FRIED SHRIMP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F364,
+ },
+ [0x1F365]={
+ category="so",
+ description="FISH CAKE WITH SWIRL DESIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F365,
+ },
+ [0x1F366]={
+ category="so",
+ description="SOFT ICE CREAM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F366,
+ },
+ [0x1F367]={
+ category="so",
+ description="SHAVED ICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F367,
+ },
+ [0x1F368]={
+ category="so",
+ description="ICE CREAM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F368,
+ },
+ [0x1F369]={
+ category="so",
+ description="DOUGHNUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F369,
+ },
+ [0x1F36A]={
+ category="so",
+ description="COOKIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36A,
+ },
+ [0x1F36B]={
+ category="so",
+ description="CHOCOLATE BAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36B,
+ },
+ [0x1F36C]={
+ category="so",
+ description="CANDY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36C,
+ },
+ [0x1F36D]={
+ category="so",
+ description="LOLLIPOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36D,
+ },
+ [0x1F36E]={
+ category="so",
+ description="CUSTARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36E,
+ },
+ [0x1F36F]={
+ category="so",
+ description="HONEY POT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F36F,
+ },
+ [0x1F370]={
+ category="so",
+ description="SHORTCAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F370,
+ },
+ [0x1F371]={
+ category="so",
+ description="BENTO BOX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F371,
+ },
+ [0x1F372]={
+ category="so",
+ description="POT OF FOOD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F372,
+ },
+ [0x1F373]={
+ category="so",
+ description="COOKING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F373,
+ },
+ [0x1F374]={
+ category="so",
+ description="FORK AND KNIFE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F374,
+ },
+ [0x1F375]={
+ category="so",
+ description="TEACUP WITHOUT HANDLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F375,
+ },
+ [0x1F376]={
+ category="so",
+ description="SAKE BOTTLE AND CUP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F376,
+ },
+ [0x1F377]={
+ category="so",
+ description="WINE GLASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F377,
+ },
+ [0x1F378]={
+ category="so",
+ description="COCKTAIL GLASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F378,
+ },
+ [0x1F379]={
+ category="so",
+ description="TROPICAL DRINK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F379,
+ },
+ [0x1F37A]={
+ category="so",
+ description="BEER MUG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37A,
+ },
+ [0x1F37B]={
+ category="so",
+ description="CLINKING BEER MUGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37B,
+ },
+ [0x1F37C]={
+ category="so",
+ description="BABY BOTTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37C,
+ },
+ [0x1F37D]={
+ category="so",
+ description="FORK AND KNIFE WITH PLATE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37D,
+ },
+ [0x1F37E]={
+ category="so",
+ description="BOTTLE WITH POPPING CORK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37E,
+ },
+ [0x1F37F]={
+ category="so",
+ description="POPCORN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F37F,
+ },
+ [0x1F380]={
+ category="so",
+ description="RIBBON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F380,
+ },
+ [0x1F381]={
+ category="so",
+ description="WRAPPED PRESENT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F381,
+ },
+ [0x1F382]={
+ category="so",
+ description="BIRTHDAY CAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F382,
+ },
+ [0x1F383]={
+ category="so",
+ description="JACK-O-LANTERN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F383,
+ },
+ [0x1F384]={
+ category="so",
+ description="CHRISTMAS TREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F384,
+ },
+ [0x1F385]={
+ category="so",
+ description="FATHER CHRISTMAS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F385,
+ },
+ [0x1F386]={
+ category="so",
+ description="FIREWORKS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F386,
+ },
+ [0x1F387]={
+ category="so",
+ description="FIREWORK SPARKLER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F387,
+ },
+ [0x1F388]={
+ category="so",
+ description="BALLOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F388,
+ },
+ [0x1F389]={
+ category="so",
+ description="PARTY POPPER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F389,
+ },
+ [0x1F38A]={
+ category="so",
+ description="CONFETTI BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38A,
+ },
+ [0x1F38B]={
+ category="so",
+ description="TANABATA TREE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38B,
+ },
+ [0x1F38C]={
+ category="so",
+ description="CROSSED FLAGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38C,
+ },
+ [0x1F38D]={
+ category="so",
+ description="PINE DECORATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38D,
+ },
+ [0x1F38E]={
+ category="so",
+ description="JAPANESE DOLLS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38E,
+ },
+ [0x1F38F]={
+ category="so",
+ description="CARP STREAMER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F38F,
+ },
+ [0x1F390]={
+ category="so",
+ description="WIND CHIME",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F390,
+ },
+ [0x1F391]={
+ category="so",
+ description="MOON VIEWING CEREMONY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F391,
+ },
+ [0x1F392]={
+ category="so",
+ description="SCHOOL SATCHEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F392,
+ },
+ [0x1F393]={
+ category="so",
+ description="GRADUATION CAP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F393,
+ },
+ [0x1F394]={
+ category="so",
+ description="HEART WITH TIP ON THE LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F394,
+ },
+ [0x1F395]={
+ category="so",
+ description="BOUQUET OF FLOWERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F395,
+ },
+ [0x1F396]={
+ category="so",
+ description="MILITARY MEDAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F396,
+ },
+ [0x1F397]={
+ category="so",
+ description="REMINDER RIBBON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F397,
+ },
+ [0x1F398]={
+ category="so",
+ description="MUSICAL KEYBOARD WITH JACKS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F398,
+ },
+ [0x1F399]={
+ category="so",
+ description="STUDIO MICROPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F399,
+ },
+ [0x1F39A]={
+ category="so",
+ description="LEVEL SLIDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F39A,
+ },
+ [0x1F39B]={
+ category="so",
+ description="CONTROL KNOBS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F39B,
+ },
+ [0x1F39C]={
+ category="so",
+ description="BEAMED ASCENDING MUSICAL NOTES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F39C,
+ },
+ [0x1F39D]={
+ category="so",
+ description="BEAMED DESCENDING MUSICAL NOTES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F39D,
+ },
+ [0x1F39E]={
+ category="so",
+ description="FILM FRAMES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F39E,
+ },
+ [0x1F39F]={
+ category="so",
+ description="ADMISSION TICKETS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F39F,
+ },
+ [0x1F3A0]={
+ category="so",
+ description="CAROUSEL HORSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A0,
+ },
+ [0x1F3A1]={
+ category="so",
+ description="FERRIS WHEEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A1,
+ },
+ [0x1F3A2]={
+ category="so",
+ description="ROLLER COASTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A2,
+ },
+ [0x1F3A3]={
+ category="so",
+ description="FISHING POLE AND FISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A3,
+ },
+ [0x1F3A4]={
+ category="so",
+ description="MICROPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A4,
+ },
+ [0x1F3A5]={
+ category="so",
+ description="MOVIE CAMERA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A5,
+ },
+ [0x1F3A6]={
+ category="so",
+ description="CINEMA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A6,
+ },
+ [0x1F3A7]={
+ category="so",
+ description="HEADPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A7,
+ },
+ [0x1F3A8]={
+ category="so",
+ description="ARTIST PALETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A8,
+ },
+ [0x1F3A9]={
+ category="so",
+ description="TOP HAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3A9,
+ },
+ [0x1F3AA]={
+ category="so",
+ description="CIRCUS TENT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AA,
+ },
+ [0x1F3AB]={
+ category="so",
+ description="TICKET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AB,
+ },
+ [0x1F3AC]={
+ category="so",
+ description="CLAPPER BOARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AC,
+ },
+ [0x1F3AD]={
+ category="so",
+ description="PERFORMING ARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AD,
+ },
+ [0x1F3AE]={
+ category="so",
+ description="VIDEO GAME",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AE,
+ },
+ [0x1F3AF]={
+ category="so",
+ description="DIRECT HIT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3AF,
+ },
+ [0x1F3B0]={
+ category="so",
+ description="SLOT MACHINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B0,
+ },
+ [0x1F3B1]={
+ category="so",
+ description="BILLIARDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B1,
+ },
+ [0x1F3B2]={
+ category="so",
+ description="GAME DIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B2,
+ },
+ [0x1F3B3]={
+ category="so",
+ description="BOWLING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B3,
+ },
+ [0x1F3B4]={
+ category="so",
+ description="FLOWER PLAYING CARDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B4,
+ },
+ [0x1F3B5]={
+ category="so",
+ description="MUSICAL NOTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B5,
+ },
+ [0x1F3B6]={
+ category="so",
+ description="MULTIPLE MUSICAL NOTES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B6,
+ },
+ [0x1F3B7]={
+ category="so",
+ description="SAXOPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B7,
+ },
+ [0x1F3B8]={
+ category="so",
+ description="GUITAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B8,
+ },
+ [0x1F3B9]={
+ category="so",
+ description="MUSICAL KEYBOARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3B9,
+ },
+ [0x1F3BA]={
+ category="so",
+ description="TRUMPET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3BA,
+ },
+ [0x1F3BB]={
+ category="so",
+ description="VIOLIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3BB,
+ },
+ [0x1F3BC]={
+ category="so",
+ description="MUSICAL SCORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BC,
+ },
+ [0x1F3BD]={
+ category="so",
+ description="RUNNING SHIRT WITH SASH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3BD,
+ },
+ [0x1F3BE]={
+ category="so",
+ description="TENNIS RACQUET AND BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3BE,
+ },
+ [0x1F3BF]={
+ category="so",
+ description="SKI AND SKI BOOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3BF,
+ },
+ [0x1F3C0]={
+ category="so",
+ description="BASKETBALL AND HOOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C0,
+ },
+ [0x1F3C1]={
+ category="so",
+ description="CHEQUERED FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C1,
+ },
+ [0x1F3C2]={
+ category="so",
+ description="SNOWBOARDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C2,
+ },
+ [0x1F3C3]={
+ category="so",
+ description="RUNNER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C3,
+ },
+ [0x1F3C4]={
+ category="so",
+ description="SURFER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C4,
+ },
+ [0x1F3C5]={
+ category="so",
+ description="SPORTS MEDAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C5,
+ },
+ [0x1F3C6]={
+ category="so",
+ description="TROPHY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C6,
+ },
+ [0x1F3C7]={
+ category="so",
+ description="HORSE RACING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C7,
+ },
+ [0x1F3C8]={
+ category="so",
+ description="AMERICAN FOOTBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C8,
+ },
+ [0x1F3C9]={
+ category="so",
+ description="RUGBY FOOTBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3C9,
+ },
+ [0x1F3CA]={
+ category="so",
+ description="SWIMMER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CA,
+ },
+ [0x1F3CB]={
+ category="so",
+ description="WEIGHT LIFTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CB,
+ },
+ [0x1F3CC]={
+ category="so",
+ description="GOLFER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CC,
+ },
+ [0x1F3CD]={
+ category="so",
+ description="RACING MOTORCYCLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CD,
+ },
+ [0x1F3CE]={
+ category="so",
+ description="RACING CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CE,
+ },
+ [0x1F3CF]={
+ category="so",
+ description="CRICKET BAT AND BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3CF,
+ },
+ [0x1F3D0]={
+ category="so",
+ description="VOLLEYBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D0,
+ },
+ [0x1F3D1]={
+ category="so",
+ description="FIELD HOCKEY STICK AND BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D1,
+ },
+ [0x1F3D2]={
+ category="so",
+ description="ICE HOCKEY STICK AND PUCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D2,
+ },
+ [0x1F3D3]={
+ category="so",
+ description="TABLE TENNIS PADDLE AND BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D3,
+ },
+ [0x1F3D4]={
+ category="so",
+ description="SNOW CAPPED MOUNTAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D4,
+ },
+ [0x1F3D5]={
+ category="so",
+ description="CAMPING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D5,
+ },
+ [0x1F3D6]={
+ category="so",
+ description="BEACH WITH UMBRELLA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D6,
+ },
+ [0x1F3D7]={
+ category="so",
+ description="BUILDING CONSTRUCTION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D7,
+ },
+ [0x1F3D8]={
+ category="so",
+ description="HOUSE BUILDINGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D8,
+ },
+ [0x1F3D9]={
+ category="so",
+ description="CITYSCAPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3D9,
+ },
+ [0x1F3DA]={
+ category="so",
+ description="DERELICT HOUSE BUILDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DA,
+ },
+ [0x1F3DB]={
+ category="so",
+ description="CLASSICAL BUILDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DB,
+ },
+ [0x1F3DC]={
+ category="so",
+ description="DESERT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DC,
+ },
+ [0x1F3DD]={
+ category="so",
+ description="DESERT ISLAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DD,
+ },
+ [0x1F3DE]={
+ category="so",
+ description="NATIONAL PARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DE,
+ },
+ [0x1F3DF]={
+ category="so",
+ description="STADIUM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3DF,
+ },
+ [0x1F3E0]={
+ category="so",
+ description="HOUSE BUILDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E0,
+ },
+ [0x1F3E1]={
+ category="so",
+ description="HOUSE WITH GARDEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E1,
+ },
+ [0x1F3E2]={
+ category="so",
+ description="OFFICE BUILDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E2,
+ },
+ [0x1F3E3]={
+ category="so",
+ description="JAPANESE POST OFFICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E3,
+ },
+ [0x1F3E4]={
+ category="so",
+ description="EUROPEAN POST OFFICE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E4,
+ },
+ [0x1F3E5]={
+ category="so",
+ description="HOSPITAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E5,
+ },
+ [0x1F3E6]={
+ category="so",
+ description="BANK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E6,
+ },
+ [0x1F3E7]={
+ category="so",
+ description="AUTOMATED TELLER MACHINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E7,
+ },
+ [0x1F3E8]={
+ category="so",
+ description="HOTEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E8,
+ },
+ [0x1F3E9]={
+ category="so",
+ description="LOVE HOTEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3E9,
+ },
+ [0x1F3EA]={
+ category="so",
+ description="CONVENIENCE STORE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3EA,
+ },
+ [0x1F3EB]={
+ category="so",
+ description="SCHOOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3EB,
+ },
+ [0x1F3EC]={
+ category="so",
+ description="DEPARTMENT STORE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3EC,
+ },
+ [0x1F3ED]={
+ category="so",
+ description="FACTORY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3ED,
+ },
+ [0x1F3EE]={
+ category="so",
+ description="IZAKAYA LANTERN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3EE,
+ },
+ [0x1F3EF]={
+ category="so",
+ description="JAPANESE CASTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3EF,
+ },
+ [0x1F3F0]={
+ category="so",
+ description="EUROPEAN CASTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F0,
+ },
+ [0x1F3F1]={
+ category="so",
+ description="WHITE PENNANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F1,
+ },
+ [0x1F3F2]={
+ category="so",
+ description="BLACK PENNANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F2,
+ },
+ [0x1F3F3]={
+ category="so",
+ description="WAVING WHITE FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F3,
+ },
+ [0x1F3F4]={
+ category="so",
+ description="WAVING BLACK FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F4,
+ },
+ [0x1F3F5]={
+ category="so",
+ description="ROSETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F5,
+ },
+ [0x1F3F6]={
+ category="so",
+ description="BLACK ROSETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F6,
+ },
+ [0x1F3F7]={
+ category="so",
+ description="LABEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F7,
+ },
+ [0x1F3F8]={
+ category="so",
+ description="BADMINTON RACQUET AND SHUTTLECOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F8,
+ },
+ [0x1F3F9]={
+ category="so",
+ description="BOW AND ARROW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3F9,
+ },
+ [0x1F3FA]={
+ category="so",
+ description="AMPHORA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F3FA,
+ },
+ [0x1F3FB]={
+ category="sk",
+ description="EMOJI MODIFIER FITZPATRICK TYPE-1-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3FB,
+ },
+ [0x1F3FC]={
+ category="sk",
+ description="EMOJI MODIFIER FITZPATRICK TYPE-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3FC,
+ },
+ [0x1F3FD]={
+ category="sk",
+ description="EMOJI MODIFIER FITZPATRICK TYPE-4",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3FD,
+ },
+ [0x1F3FE]={
+ category="sk",
+ description="EMOJI MODIFIER FITZPATRICK TYPE-5",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3FE,
+ },
+ [0x1F3FF]={
+ category="sk",
+ description="EMOJI MODIFIER FITZPATRICK TYPE-6",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3FF,
+ },
+ [0x1F400]={
+ category="so",
+ description="RAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F400,
+ },
+ [0x1F401]={
+ category="so",
+ description="MOUSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F401,
+ },
+ [0x1F402]={
+ category="so",
+ description="OX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F402,
+ },
+ [0x1F403]={
+ category="so",
+ description="WATER BUFFALO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F403,
+ },
+ [0x1F404]={
+ category="so",
+ description="COW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F404,
+ },
+ [0x1F405]={
+ category="so",
+ description="TIGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F405,
+ },
+ [0x1F406]={
+ category="so",
+ description="LEOPARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F406,
+ },
+ [0x1F407]={
+ category="so",
+ description="RABBIT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F407,
+ },
+ [0x1F408]={
+ category="so",
+ description="CAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F408,
+ },
+ [0x1F409]={
+ category="so",
+ description="DRAGON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F409,
+ },
+ [0x1F40A]={
+ category="so",
+ description="CROCODILE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40A,
+ },
+ [0x1F40B]={
+ category="so",
+ description="WHALE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40B,
+ },
+ [0x1F40C]={
+ category="so",
+ description="SNAIL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40C,
+ },
+ [0x1F40D]={
+ category="so",
+ description="SNAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40D,
+ },
+ [0x1F40E]={
+ category="so",
+ description="HORSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40E,
+ },
+ [0x1F40F]={
+ category="so",
+ description="RAM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F40F,
+ },
+ [0x1F410]={
+ category="so",
+ description="GOAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F410,
+ },
+ [0x1F411]={
+ category="so",
+ description="SHEEP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F411,
+ },
+ [0x1F412]={
+ category="so",
+ description="MONKEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F412,
+ },
+ [0x1F413]={
+ category="so",
+ description="ROOSTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F413,
+ },
+ [0x1F414]={
+ category="so",
+ description="CHICKEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F414,
+ },
+ [0x1F415]={
+ category="so",
+ description="DOG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F415,
+ },
+ [0x1F416]={
+ category="so",
+ description="PIG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F416,
+ },
+ [0x1F417]={
+ category="so",
+ description="BOAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F417,
+ },
+ [0x1F418]={
+ category="so",
+ description="ELEPHANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F418,
+ },
+ [0x1F419]={
+ category="so",
+ description="OCTOPUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F419,
+ },
+ [0x1F41A]={
+ category="so",
+ description="SPIRAL SHELL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41A,
+ },
+ [0x1F41B]={
+ category="so",
+ description="BUG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41B,
+ },
+ [0x1F41C]={
+ category="so",
+ description="ANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41C,
+ },
+ [0x1F41D]={
+ category="so",
+ description="HONEYBEE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41D,
+ },
+ [0x1F41E]={
+ category="so",
+ description="LADY BEETLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41E,
+ },
+ [0x1F41F]={
+ category="so",
+ description="FISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F41F,
+ },
+ [0x1F420]={
+ category="so",
+ description="TROPICAL FISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F420,
+ },
+ [0x1F421]={
+ category="so",
+ description="BLOWFISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F421,
+ },
+ [0x1F422]={
+ category="so",
+ description="TURTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F422,
+ },
+ [0x1F423]={
+ category="so",
+ description="HATCHING CHICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F423,
+ },
+ [0x1F424]={
+ category="so",
+ description="BABY CHICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F424,
+ },
+ [0x1F425]={
+ category="so",
+ description="FRONT-FACING BABY CHICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F425,
+ },
+ [0x1F426]={
+ category="so",
+ description="BIRD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F426,
+ },
+ [0x1F427]={
+ category="so",
+ description="PENGUIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F427,
+ },
+ [0x1F428]={
+ category="so",
+ description="KOALA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F428,
+ },
+ [0x1F429]={
+ category="so",
+ description="POODLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F429,
+ },
+ [0x1F42A]={
+ category="so",
+ description="DROMEDARY CAMEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42A,
+ },
+ [0x1F42B]={
+ category="so",
+ description="BACTRIAN CAMEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42B,
+ },
+ [0x1F42C]={
+ category="so",
+ description="DOLPHIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42C,
+ },
+ [0x1F42D]={
+ category="so",
+ description="MOUSE FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42D,
+ },
+ [0x1F42E]={
+ category="so",
+ description="COW FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42E,
+ },
+ [0x1F42F]={
+ category="so",
+ description="TIGER FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F42F,
+ },
+ [0x1F430]={
+ category="so",
+ description="RABBIT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F430,
+ },
+ [0x1F431]={
+ category="so",
+ description="CAT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F431,
+ },
+ [0x1F432]={
+ category="so",
+ description="DRAGON FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F432,
+ },
+ [0x1F433]={
+ category="so",
+ description="SPOUTING WHALE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F433,
+ },
+ [0x1F434]={
+ category="so",
+ description="HORSE FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F434,
+ },
+ [0x1F435]={
+ category="so",
+ description="MONKEY FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F435,
+ },
+ [0x1F436]={
+ category="so",
+ description="DOG FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F436,
+ },
+ [0x1F437]={
+ category="so",
+ description="PIG FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F437,
+ },
+ [0x1F438]={
+ category="so",
+ description="FROG FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F438,
+ },
+ [0x1F439]={
+ category="so",
+ description="HAMSTER FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F439,
+ },
+ [0x1F43A]={
+ category="so",
+ description="WOLF FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43A,
+ },
+ [0x1F43B]={
+ category="so",
+ description="BEAR FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43B,
+ },
+ [0x1F43C]={
+ category="so",
+ description="PANDA FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43C,
+ },
+ [0x1F43D]={
+ category="so",
+ description="PIG NOSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43D,
+ },
+ [0x1F43E]={
+ category="so",
+ description="PAW PRINTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43E,
+ },
+ [0x1F43F]={
+ category="so",
+ description="CHIPMUNK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F43F,
+ },
+ [0x1F440]={
+ category="so",
+ description="EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F440,
+ },
+ [0x1F441]={
+ category="so",
+ description="EYE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F441,
+ },
+ [0x1F442]={
+ category="so",
+ description="EAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F442,
+ },
+ [0x1F443]={
+ category="so",
+ description="NOSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F443,
+ },
+ [0x1F444]={
+ category="so",
+ description="MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F444,
+ },
+ [0x1F445]={
+ category="so",
+ description="TONGUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F445,
+ },
+ [0x1F446]={
+ category="so",
+ description="WHITE UP POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F446,
+ },
+ [0x1F447]={
+ category="so",
+ description="WHITE DOWN POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F447,
+ },
+ [0x1F448]={
+ category="so",
+ description="WHITE LEFT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F448,
+ },
+ [0x1F449]={
+ category="so",
+ description="WHITE RIGHT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F449,
+ },
+ [0x1F44A]={
+ category="so",
+ description="FISTED HAND SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44A,
+ },
+ [0x1F44B]={
+ category="so",
+ description="WAVING HAND SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44B,
+ },
+ [0x1F44C]={
+ category="so",
+ description="OK HAND SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44C,
+ },
+ [0x1F44D]={
+ category="so",
+ description="THUMBS UP SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44D,
+ },
+ [0x1F44E]={
+ category="so",
+ description="THUMBS DOWN SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44E,
+ },
+ [0x1F44F]={
+ category="so",
+ description="CLAPPING HANDS SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F44F,
+ },
+ [0x1F450]={
+ category="so",
+ description="OPEN HANDS SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F450,
+ },
+ [0x1F451]={
+ category="so",
+ description="CROWN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F451,
+ },
+ [0x1F452]={
+ category="so",
+ description="WOMANS HAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F452,
+ },
+ [0x1F453]={
+ category="so",
+ description="EYEGLASSES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F453,
+ },
+ [0x1F454]={
+ category="so",
+ description="NECKTIE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F454,
+ },
+ [0x1F455]={
+ category="so",
+ description="T-SHIRT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F455,
+ },
+ [0x1F456]={
+ category="so",
+ description="JEANS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F456,
+ },
+ [0x1F457]={
+ category="so",
+ description="DRESS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F457,
+ },
+ [0x1F458]={
+ category="so",
+ description="KIMONO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F458,
+ },
+ [0x1F459]={
+ category="so",
+ description="BIKINI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F459,
+ },
+ [0x1F45A]={
+ category="so",
+ description="WOMANS CLOTHES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45A,
+ },
+ [0x1F45B]={
+ category="so",
+ description="PURSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45B,
+ },
+ [0x1F45C]={
+ category="so",
+ description="HANDBAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45C,
+ },
+ [0x1F45D]={
+ category="so",
+ description="POUCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45D,
+ },
+ [0x1F45E]={
+ category="so",
+ description="MANS SHOE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45E,
+ },
+ [0x1F45F]={
+ category="so",
+ description="ATHLETIC SHOE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F45F,
+ },
+ [0x1F460]={
+ category="so",
+ description="HIGH-HEELED SHOE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F460,
+ },
+ [0x1F461]={
+ category="so",
+ description="WOMANS SANDAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F461,
+ },
+ [0x1F462]={
+ category="so",
+ description="WOMANS BOOTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F462,
+ },
+ [0x1F463]={
+ category="so",
+ description="FOOTPRINTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F463,
+ },
+ [0x1F464]={
+ category="so",
+ description="BUST IN SILHOUETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F464,
+ },
+ [0x1F465]={
+ category="so",
+ description="BUSTS IN SILHOUETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F465,
+ },
+ [0x1F466]={
+ category="so",
+ description="BOY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F466,
+ },
+ [0x1F467]={
+ category="so",
+ description="GIRL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F467,
+ },
+ [0x1F468]={
+ category="so",
+ description="MAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F468,
+ },
+ [0x1F469]={
+ category="so",
+ description="WOMAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F469,
+ },
+ [0x1F46A]={
+ category="so",
+ description="FAMILY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46A,
+ },
+ [0x1F46B]={
+ category="so",
+ description="MAN AND WOMAN HOLDING HANDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46B,
+ },
+ [0x1F46C]={
+ category="so",
+ description="TWO MEN HOLDING HANDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46C,
+ },
+ [0x1F46D]={
+ category="so",
+ description="TWO WOMEN HOLDING HANDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46D,
+ },
+ [0x1F46E]={
+ category="so",
+ description="POLICE OFFICER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46E,
+ },
+ [0x1F46F]={
+ category="so",
+ description="WOMAN WITH BUNNY EARS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F46F,
+ },
+ [0x1F470]={
+ category="so",
+ description="BRIDE WITH VEIL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F470,
+ },
+ [0x1F471]={
+ category="so",
+ description="PERSON WITH BLOND HAIR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F471,
+ },
+ [0x1F472]={
+ category="so",
+ description="MAN WITH GUA PI MAO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F472,
+ },
+ [0x1F473]={
+ category="so",
+ description="MAN WITH TURBAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F473,
+ },
+ [0x1F474]={
+ category="so",
+ description="OLDER MAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F474,
+ },
+ [0x1F475]={
+ category="so",
+ description="OLDER WOMAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F475,
+ },
+ [0x1F476]={
+ category="so",
+ description="BABY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F476,
+ },
+ [0x1F477]={
+ category="so",
+ description="CONSTRUCTION WORKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F477,
+ },
+ [0x1F478]={
+ category="so",
+ description="PRINCESS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F478,
+ },
+ [0x1F479]={
+ category="so",
+ description="JAPANESE OGRE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F479,
+ },
+ [0x1F47A]={
+ category="so",
+ description="JAPANESE GOBLIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47A,
+ },
+ [0x1F47B]={
+ category="so",
+ description="GHOST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47B,
+ },
+ [0x1F47C]={
+ category="so",
+ description="BABY ANGEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47C,
+ },
+ [0x1F47D]={
+ category="so",
+ description="EXTRATERRESTRIAL ALIEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47D,
+ },
+ [0x1F47E]={
+ category="so",
+ description="ALIEN MONSTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47E,
+ },
+ [0x1F47F]={
+ category="so",
+ description="IMP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F47F,
+ },
+ [0x1F480]={
+ category="so",
+ description="SKULL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F480,
+ },
+ [0x1F481]={
+ category="so",
+ description="INFORMATION DESK PERSON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F481,
+ },
+ [0x1F482]={
+ category="so",
+ description="GUARDSMAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F482,
+ },
+ [0x1F483]={
+ category="so",
+ description="DANCER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F483,
+ },
+ [0x1F484]={
+ category="so",
+ description="LIPSTICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F484,
+ },
+ [0x1F485]={
+ category="so",
+ description="NAIL POLISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F485,
+ },
+ [0x1F486]={
+ category="so",
+ description="FACE MASSAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F486,
+ },
+ [0x1F487]={
+ category="so",
+ description="HAIRCUT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F487,
+ },
+ [0x1F488]={
+ category="so",
+ description="BARBER POLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F488,
+ },
+ [0x1F489]={
+ category="so",
+ description="SYRINGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F489,
+ },
+ [0x1F48A]={
+ category="so",
+ description="PILL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48A,
+ },
+ [0x1F48B]={
+ category="so",
+ description="KISS MARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48B,
+ },
+ [0x1F48C]={
+ category="so",
+ description="LOVE LETTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48C,
+ },
+ [0x1F48D]={
+ category="so",
+ description="RING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48D,
+ },
+ [0x1F48E]={
+ category="so",
+ description="GEM STONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48E,
+ },
+ [0x1F48F]={
+ category="so",
+ description="KISS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F48F,
+ },
+ [0x1F490]={
+ category="so",
+ description="BOUQUET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F490,
+ },
+ [0x1F491]={
+ category="so",
+ description="COUPLE WITH HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F491,
+ },
+ [0x1F492]={
+ category="so",
+ description="WEDDING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F492,
+ },
+ [0x1F493]={
+ category="so",
+ description="BEATING HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F493,
+ },
+ [0x1F494]={
+ category="so",
+ description="BROKEN HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F494,
+ },
+ [0x1F495]={
+ category="so",
+ description="TWO HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F495,
+ },
+ [0x1F496]={
+ category="so",
+ description="SPARKLING HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F496,
+ },
+ [0x1F497]={
+ category="so",
+ description="GROWING HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F497,
+ },
+ [0x1F498]={
+ category="so",
+ description="HEART WITH ARROW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F498,
+ },
+ [0x1F499]={
+ category="so",
+ description="BLUE HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F499,
+ },
+ [0x1F49A]={
+ category="so",
+ description="GREEN HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49A,
+ },
+ [0x1F49B]={
+ category="so",
+ description="YELLOW HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49B,
+ },
+ [0x1F49C]={
+ category="so",
+ description="PURPLE HEART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49C,
+ },
+ [0x1F49D]={
+ category="so",
+ description="HEART WITH RIBBON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49D,
+ },
+ [0x1F49E]={
+ category="so",
+ description="REVOLVING HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49E,
+ },
+ [0x1F49F]={
+ category="so",
+ description="HEART DECORATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F49F,
+ },
+ [0x1F4A0]={
+ category="so",
+ description="DIAMOND SHAPE WITH A DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A0,
+ },
+ [0x1F4A1]={
+ category="so",
+ description="ELECTRIC LIGHT BULB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A1,
+ },
+ [0x1F4A2]={
+ category="so",
+ description="ANGER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A2,
+ },
+ [0x1F4A3]={
+ category="so",
+ description="BOMB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A3,
+ },
+ [0x1F4A4]={
+ category="so",
+ description="SLEEPING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A4,
+ },
+ [0x1F4A5]={
+ category="so",
+ description="COLLISION SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A5,
+ },
+ [0x1F4A6]={
+ category="so",
+ description="SPLASHING SWEAT SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A6,
+ },
+ [0x1F4A7]={
+ category="so",
+ description="DROPLET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A7,
+ },
+ [0x1F4A8]={
+ category="so",
+ description="DASH SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A8,
+ },
+ [0x1F4A9]={
+ category="so",
+ description="PILE OF POO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4A9,
+ },
+ [0x1F4AA]={
+ category="so",
+ description="FLEXED BICEPS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4AA,
+ },
+ [0x1F4AB]={
+ category="so",
+ description="DIZZY SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4AB,
+ },
+ [0x1F4AC]={
+ category="so",
+ description="SPEECH BALLOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4AC,
+ },
+ [0x1F4AD]={
+ category="so",
+ description="THOUGHT BALLOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4AD,
+ },
+ [0x1F4AE]={
+ category="so",
+ description="WHITE FLOWER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4AE,
+ },
+ [0x1F4AF]={
+ category="so",
+ description="HUNDRED POINTS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AF,
+ },
+ [0x1F4B0]={
+ category="so",
+ description="MONEY BAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B0,
+ },
+ [0x1F4B1]={
+ category="so",
+ description="CURRENCY EXCHANGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B1,
+ },
+ [0x1F4B2]={
+ category="so",
+ description="HEAVY DOLLAR SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B2,
+ },
+ [0x1F4B3]={
+ category="so",
+ description="CREDIT CARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B3,
+ },
+ [0x1F4B4]={
+ category="so",
+ description="BANKNOTE WITH YEN SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B4,
+ },
+ [0x1F4B5]={
+ category="so",
+ description="BANKNOTE WITH DOLLAR SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B5,
+ },
+ [0x1F4B6]={
+ category="so",
+ description="BANKNOTE WITH EURO SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B6,
+ },
+ [0x1F4B7]={
+ category="so",
+ description="BANKNOTE WITH POUND SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B7,
+ },
+ [0x1F4B8]={
+ category="so",
+ description="MONEY WITH WINGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B8,
+ },
+ [0x1F4B9]={
+ category="so",
+ description="CHART WITH UPWARDS TREND AND YEN SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4B9,
+ },
+ [0x1F4BA]={
+ category="so",
+ description="SEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BA,
+ },
+ [0x1F4BB]={
+ category="so",
+ description="PERSONAL COMPUTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BB,
+ },
+ [0x1F4BC]={
+ category="so",
+ description="BRIEFCASE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BC,
+ },
+ [0x1F4BD]={
+ category="so",
+ description="MINIDISC",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BD,
+ },
+ [0x1F4BE]={
+ category="so",
+ description="FLOPPY DISK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BE,
+ },
+ [0x1F4BF]={
+ category="so",
+ description="OPTICAL DISC",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4BF,
+ },
+ [0x1F4C0]={
+ category="so",
+ description="DVD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C0,
+ },
+ [0x1F4C1]={
+ category="so",
+ description="FILE FOLDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C1,
+ },
+ [0x1F4C2]={
+ category="so",
+ description="OPEN FILE FOLDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C2,
+ },
+ [0x1F4C3]={
+ category="so",
+ description="PAGE WITH CURL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C3,
+ },
+ [0x1F4C4]={
+ category="so",
+ description="PAGE FACING UP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C4,
+ },
+ [0x1F4C5]={
+ category="so",
+ description="CALENDAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C5,
+ },
+ [0x1F4C6]={
+ category="so",
+ description="TEAR-OFF CALENDAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C6,
+ },
+ [0x1F4C7]={
+ category="so",
+ description="CARD INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C7,
+ },
+ [0x1F4C8]={
+ category="so",
+ description="CHART WITH UPWARDS TREND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C8,
+ },
+ [0x1F4C9]={
+ category="so",
+ description="CHART WITH DOWNWARDS TREND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4C9,
+ },
+ [0x1F4CA]={
+ category="so",
+ description="BAR CHART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CA,
+ },
+ [0x1F4CB]={
+ category="so",
+ description="CLIPBOARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CB,
+ },
+ [0x1F4CC]={
+ category="so",
+ description="PUSHPIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CC,
+ },
+ [0x1F4CD]={
+ category="so",
+ description="ROUND PUSHPIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CD,
+ },
+ [0x1F4CE]={
+ category="so",
+ description="PAPERCLIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CE,
+ },
+ [0x1F4CF]={
+ category="so",
+ description="STRAIGHT RULER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4CF,
+ },
+ [0x1F4D0]={
+ category="so",
+ description="TRIANGULAR RULER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D0,
+ },
+ [0x1F4D1]={
+ category="so",
+ description="BOOKMARK TABS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D1,
+ },
+ [0x1F4D2]={
+ category="so",
+ description="LEDGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D2,
+ },
+ [0x1F4D3]={
+ category="so",
+ description="NOTEBOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D3,
+ },
+ [0x1F4D4]={
+ category="so",
+ description="NOTEBOOK WITH DECORATIVE COVER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D4,
+ },
+ [0x1F4D5]={
+ category="so",
+ description="CLOSED BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D5,
+ },
+ [0x1F4D6]={
+ category="so",
+ description="OPEN BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D6,
+ },
+ [0x1F4D7]={
+ category="so",
+ description="GREEN BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D7,
+ },
+ [0x1F4D8]={
+ category="so",
+ description="BLUE BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D8,
+ },
+ [0x1F4D9]={
+ category="so",
+ description="ORANGE BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4D9,
+ },
+ [0x1F4DA]={
+ category="so",
+ description="BOOKS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DA,
+ },
+ [0x1F4DB]={
+ category="so",
+ description="NAME BADGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DB,
+ },
+ [0x1F4DC]={
+ category="so",
+ description="SCROLL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DC,
+ },
+ [0x1F4DD]={
+ category="so",
+ description="MEMO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DD,
+ },
+ [0x1F4DE]={
+ category="so",
+ description="TELEPHONE RECEIVER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DE,
+ },
+ [0x1F4DF]={
+ category="so",
+ description="PAGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4DF,
+ },
+ [0x1F4E0]={
+ category="so",
+ description="FAX MACHINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E0,
+ },
+ [0x1F4E1]={
+ category="so",
+ description="SATELLITE ANTENNA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E1,
+ },
+ [0x1F4E2]={
+ category="so",
+ description="PUBLIC ADDRESS LOUDSPEAKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E2,
+ },
+ [0x1F4E3]={
+ category="so",
+ description="CHEERING MEGAPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E3,
+ },
+ [0x1F4E4]={
+ category="so",
+ description="OUTBOX TRAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E4,
+ },
+ [0x1F4E5]={
+ category="so",
+ description="INBOX TRAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E5,
+ },
+ [0x1F4E6]={
+ category="so",
+ description="PACKAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E6,
+ },
+ [0x1F4E7]={
+ category="so",
+ description="E-MAIL SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E7,
+ },
+ [0x1F4E8]={
+ category="so",
+ description="INCOMING ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E8,
+ },
+ [0x1F4E9]={
+ category="so",
+ description="ENVELOPE WITH DOWNWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4E9,
+ },
+ [0x1F4EA]={
+ category="so",
+ description="CLOSED MAILBOX WITH LOWERED FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4EA,
+ },
+ [0x1F4EB]={
+ category="so",
+ description="CLOSED MAILBOX WITH RAISED FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4EB,
+ },
+ [0x1F4EC]={
+ category="so",
+ description="OPEN MAILBOX WITH RAISED FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4EC,
+ },
+ [0x1F4ED]={
+ category="so",
+ description="OPEN MAILBOX WITH LOWERED FLAG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4ED,
+ },
+ [0x1F4EE]={
+ category="so",
+ description="POSTBOX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4EE,
+ },
+ [0x1F4EF]={
+ category="so",
+ description="POSTAL HORN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4EF,
+ },
+ [0x1F4F0]={
+ category="so",
+ description="NEWSPAPER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F0,
+ },
+ [0x1F4F1]={
+ category="so",
+ description="MOBILE PHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F1,
+ },
+ [0x1F4F2]={
+ category="so",
+ description="MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F2,
+ },
+ [0x1F4F3]={
+ category="so",
+ description="VIBRATION MODE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F3,
+ },
+ [0x1F4F4]={
+ category="so",
+ description="MOBILE PHONE OFF",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F4,
+ },
+ [0x1F4F5]={
+ category="so",
+ description="NO MOBILE PHONES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F5,
+ },
+ [0x1F4F6]={
+ category="so",
+ description="ANTENNA WITH BARS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F6,
+ },
+ [0x1F4F7]={
+ category="so",
+ description="CAMERA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F7,
+ },
+ [0x1F4F8]={
+ category="so",
+ description="CAMERA WITH FLASH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F8,
+ },
+ [0x1F4F9]={
+ category="so",
+ description="VIDEO CAMERA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4F9,
+ },
+ [0x1F4FA]={
+ category="so",
+ description="TELEVISION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FA,
+ },
+ [0x1F4FB]={
+ category="so",
+ description="RADIO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FB,
+ },
+ [0x1F4FC]={
+ category="so",
+ description="VIDEOCASSETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FC,
+ },
+ [0x1F4FD]={
+ category="so",
+ description="FILM PROJECTOR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FD,
+ },
+ [0x1F4FE]={
+ category="so",
+ description="PORTABLE STEREO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FE,
+ },
+ [0x1F4FF]={
+ category="so",
+ description="PRAYER BEADS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F4FF,
+ },
+ [0x1F500]={
+ category="so",
+ description="TWISTED RIGHTWARDS ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F500,
+ },
+ [0x1F501]={
+ category="so",
+ description="CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F501,
+ },
+ [0x1F502]={
+ category="so",
+ description="CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F502,
+ },
+ [0x1F503]={
+ category="so",
+ description="CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F503,
+ },
+ [0x1F504]={
+ category="so",
+ description="ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F504,
+ },
+ [0x1F505]={
+ category="so",
+ description="LOW BRIGHTNESS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F505,
+ },
+ [0x1F506]={
+ category="so",
+ description="HIGH BRIGHTNESS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F506,
+ },
+ [0x1F507]={
+ category="so",
+ description="SPEAKER WITH CANCELLATION STROKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F507,
+ },
+ [0x1F508]={
+ category="so",
+ description="SPEAKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F508,
+ },
+ [0x1F509]={
+ category="so",
+ description="SPEAKER WITH ONE SOUND WAVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F509,
+ },
+ [0x1F50A]={
+ category="so",
+ description="SPEAKER WITH THREE SOUND WAVES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50A,
+ },
+ [0x1F50B]={
+ category="so",
+ description="BATTERY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50B,
+ },
+ [0x1F50C]={
+ category="so",
+ description="ELECTRIC PLUG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50C,
+ },
+ [0x1F50D]={
+ category="so",
+ description="LEFT-POINTING MAGNIFYING GLASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50D,
+ },
+ [0x1F50E]={
+ category="so",
+ description="RIGHT-POINTING MAGNIFYING GLASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50E,
+ },
+ [0x1F50F]={
+ category="so",
+ description="LOCK WITH INK PEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F50F,
+ },
+ [0x1F510]={
+ category="so",
+ description="CLOSED LOCK WITH KEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F510,
+ },
+ [0x1F511]={
+ category="so",
+ description="KEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F511,
+ },
+ [0x1F512]={
+ category="so",
+ description="LOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F512,
+ },
+ [0x1F513]={
+ category="so",
+ description="OPEN LOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F513,
+ },
+ [0x1F514]={
+ category="so",
+ description="BELL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F514,
+ },
+ [0x1F515]={
+ category="so",
+ description="BELL WITH CANCELLATION STROKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F515,
+ },
+ [0x1F516]={
+ category="so",
+ description="BOOKMARK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F516,
+ },
+ [0x1F517]={
+ category="so",
+ description="LINK SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F517,
+ },
+ [0x1F518]={
+ category="so",
+ description="RADIO BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F518,
+ },
+ [0x1F519]={
+ category="so",
+ description="BACK WITH LEFTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F519,
+ },
+ [0x1F51A]={
+ category="so",
+ description="END WITH LEFTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51A,
+ },
+ [0x1F51B]={
+ category="so",
+ description="ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51B,
+ },
+ [0x1F51C]={
+ category="so",
+ description="SOON WITH RIGHTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51C,
+ },
+ [0x1F51D]={
+ category="so",
+ description="TOP WITH UPWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51D,
+ },
+ [0x1F51E]={
+ category="so",
+ description="NO ONE UNDER EIGHTEEN SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51E,
+ },
+ [0x1F51F]={
+ category="so",
+ description="KEYCAP TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51F,
+ },
+ [0x1F520]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN CAPITAL LETTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F520,
+ },
+ [0x1F521]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN SMALL LETTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F521,
+ },
+ [0x1F522]={
+ category="so",
+ description="INPUT SYMBOL FOR NUMBERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F522,
+ },
+ [0x1F523]={
+ category="so",
+ description="INPUT SYMBOL FOR SYMBOLS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F523,
+ },
+ [0x1F524]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN LETTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F524,
+ },
+ [0x1F525]={
+ category="so",
+ description="FIRE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F525,
+ },
+ [0x1F526]={
+ category="so",
+ description="ELECTRIC TORCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F526,
+ },
+ [0x1F527]={
+ category="so",
+ description="WRENCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F527,
+ },
+ [0x1F528]={
+ category="so",
+ description="HAMMER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F528,
+ },
+ [0x1F529]={
+ category="so",
+ description="NUT AND BOLT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F529,
+ },
+ [0x1F52A]={
+ category="so",
+ description="HOCHO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52A,
+ },
+ [0x1F52B]={
+ category="so",
+ description="PISTOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52B,
+ },
+ [0x1F52C]={
+ category="so",
+ description="MICROSCOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52C,
+ },
+ [0x1F52D]={
+ category="so",
+ description="TELESCOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52D,
+ },
+ [0x1F52E]={
+ category="so",
+ description="CRYSTAL BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52E,
+ },
+ [0x1F52F]={
+ category="so",
+ description="SIX POINTED STAR WITH MIDDLE DOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F52F,
+ },
+ [0x1F530]={
+ category="so",
+ description="JAPANESE SYMBOL FOR BEGINNER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F530,
+ },
+ [0x1F531]={
+ category="so",
+ description="TRIDENT EMBLEM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F531,
+ },
+ [0x1F532]={
+ category="so",
+ description="BLACK SQUARE BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F532,
+ },
+ [0x1F533]={
+ category="so",
+ description="WHITE SQUARE BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F533,
+ },
+ [0x1F534]={
+ category="so",
+ description="LARGE RED CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F534,
+ },
+ [0x1F535]={
+ category="so",
+ description="LARGE BLUE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F535,
+ },
+ [0x1F536]={
+ category="so",
+ description="LARGE ORANGE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F536,
+ },
+ [0x1F537]={
+ category="so",
+ description="LARGE BLUE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F537,
+ },
+ [0x1F538]={
+ category="so",
+ description="SMALL ORANGE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F538,
+ },
+ [0x1F539]={
+ category="so",
+ description="SMALL BLUE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F539,
+ },
+ [0x1F53A]={
+ category="so",
+ description="UP-POINTING RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53A,
+ },
+ [0x1F53B]={
+ category="so",
+ description="DOWN-POINTING RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53B,
+ },
+ [0x1F53C]={
+ category="so",
+ description="UP-POINTING SMALL RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53C,
+ },
+ [0x1F53D]={
+ category="so",
+ description="DOWN-POINTING SMALL RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53D,
+ },
+ [0x1F53E]={
+ category="so",
+ description="LOWER RIGHT SHADOWED WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53E,
+ },
+ [0x1F53F]={
+ category="so",
+ description="UPPER RIGHT SHADOWED WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53F,
+ },
+ [0x1F540]={
+ category="so",
+ description="CIRCLED CROSS POMMEE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F540,
+ },
+ [0x1F541]={
+ category="so",
+ description="CROSS POMMEE WITH HALF-CIRCLE BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F541,
+ },
+ [0x1F542]={
+ category="so",
+ description="CROSS POMMEE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F542,
+ },
+ [0x1F543]={
+ category="so",
+ description="NOTCHED LEFT SEMICIRCLE WITH THREE DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F543,
+ },
+ [0x1F544]={
+ category="so",
+ description="NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F544,
+ },
+ [0x1F545]={
+ category="so",
+ description="SYMBOL FOR MARKS CHAPTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F545,
+ },
+ [0x1F546]={
+ category="so",
+ description="WHITE LATIN CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F546,
+ },
+ [0x1F547]={
+ category="so",
+ description="HEAVY LATIN CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F547,
+ },
+ [0x1F548]={
+ category="so",
+ description="CELTIC CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F548,
+ },
+ [0x1F549]={
+ category="so",
+ description="OM SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F549,
+ },
+ [0x1F54A]={
+ category="so",
+ description="DOVE OF PEACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54A,
+ },
+ [0x1F54B]={
+ category="so",
+ description="KAABA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54B,
+ },
+ [0x1F54C]={
+ category="so",
+ description="MOSQUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54C,
+ },
+ [0x1F54D]={
+ category="so",
+ description="SYNAGOGUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54D,
+ },
+ [0x1F54E]={
+ category="so",
+ description="MENORAH WITH NINE BRANCHES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54E,
+ },
+ [0x1F54F]={
+ category="so",
+ description="BOWL OF HYGIEIA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F54F,
+ },
+ [0x1F550]={
+ category="so",
+ description="CLOCK FACE ONE OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F550,
+ },
+ [0x1F551]={
+ category="so",
+ description="CLOCK FACE TWO OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F551,
+ },
+ [0x1F552]={
+ category="so",
+ description="CLOCK FACE THREE OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F552,
+ },
+ [0x1F553]={
+ category="so",
+ description="CLOCK FACE FOUR OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F553,
+ },
+ [0x1F554]={
+ category="so",
+ description="CLOCK FACE FIVE OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F554,
+ },
+ [0x1F555]={
+ category="so",
+ description="CLOCK FACE SIX OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F555,
+ },
+ [0x1F556]={
+ category="so",
+ description="CLOCK FACE SEVEN OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F556,
+ },
+ [0x1F557]={
+ category="so",
+ description="CLOCK FACE EIGHT OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F557,
+ },
+ [0x1F558]={
+ category="so",
+ description="CLOCK FACE NINE OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F558,
+ },
+ [0x1F559]={
+ category="so",
+ description="CLOCK FACE TEN OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F559,
+ },
+ [0x1F55A]={
+ category="so",
+ description="CLOCK FACE ELEVEN OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55A,
+ },
+ [0x1F55B]={
+ category="so",
+ description="CLOCK FACE TWELVE OCLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55B,
+ },
+ [0x1F55C]={
+ category="so",
+ description="CLOCK FACE ONE-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55C,
+ },
+ [0x1F55D]={
+ category="so",
+ description="CLOCK FACE TWO-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55D,
+ },
+ [0x1F55E]={
+ category="so",
+ description="CLOCK FACE THREE-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55E,
+ },
+ [0x1F55F]={
+ category="so",
+ description="CLOCK FACE FOUR-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F55F,
+ },
+ [0x1F560]={
+ category="so",
+ description="CLOCK FACE FIVE-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F560,
+ },
+ [0x1F561]={
+ category="so",
+ description="CLOCK FACE SIX-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F561,
+ },
+ [0x1F562]={
+ category="so",
+ description="CLOCK FACE SEVEN-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F562,
+ },
+ [0x1F563]={
+ category="so",
+ description="CLOCK FACE EIGHT-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F563,
+ },
+ [0x1F564]={
+ category="so",
+ description="CLOCK FACE NINE-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F564,
+ },
+ [0x1F565]={
+ category="so",
+ description="CLOCK FACE TEN-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F565,
+ },
+ [0x1F566]={
+ category="so",
+ description="CLOCK FACE ELEVEN-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F566,
+ },
+ [0x1F567]={
+ category="so",
+ description="CLOCK FACE TWELVE-THIRTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F567,
+ },
+ [0x1F568]={
+ category="so",
+ description="RIGHT SPEAKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F568,
+ },
+ [0x1F569]={
+ category="so",
+ description="RIGHT SPEAKER WITH ONE SOUND WAVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F569,
+ },
+ [0x1F56A]={
+ category="so",
+ description="RIGHT SPEAKER WITH THREE SOUND WAVES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56A,
+ },
+ [0x1F56B]={
+ category="so",
+ description="BULLHORN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56B,
+ },
+ [0x1F56C]={
+ category="so",
+ description="BULLHORN WITH SOUND WAVES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56C,
+ },
+ [0x1F56D]={
+ category="so",
+ description="RINGING BELL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56D,
+ },
+ [0x1F56E]={
+ category="so",
+ description="BOOK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56E,
+ },
+ [0x1F56F]={
+ category="so",
+ description="CANDLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F56F,
+ },
+ [0x1F570]={
+ category="so",
+ description="MANTELPIECE CLOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F570,
+ },
+ [0x1F571]={
+ category="so",
+ description="BLACK SKULL AND CROSSBONES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F571,
+ },
+ [0x1F572]={
+ category="so",
+ description="NO PIRACY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F572,
+ },
+ [0x1F573]={
+ category="so",
+ description="HOLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F573,
+ },
+ [0x1F574]={
+ category="so",
+ description="MAN IN BUSINESS SUIT LEVITATING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F574,
+ },
+ [0x1F575]={
+ category="so",
+ description="SLEUTH OR SPY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F575,
+ },
+ [0x1F576]={
+ category="so",
+ description="DARK SUNGLASSES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F576,
+ },
+ [0x1F577]={
+ category="so",
+ description="SPIDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F577,
+ },
+ [0x1F578]={
+ category="so",
+ description="SPIDER WEB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F578,
+ },
+ [0x1F579]={
+ category="so",
+ description="JOYSTICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F579,
+ },
+ [0x1F57B]={
+ category="so",
+ description="LEFT HAND TELEPHONE RECEIVER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F57B,
+ },
+ [0x1F57C]={
+ category="so",
+ description="TELEPHONE RECEIVER WITH PAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F57C,
+ },
+ [0x1F57D]={
+ category="so",
+ description="RIGHT HAND TELEPHONE RECEIVER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F57D,
+ },
+ [0x1F57E]={
+ category="so",
+ description="WHITE TOUCHTONE TELEPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F57E,
+ },
+ [0x1F57F]={
+ category="so",
+ description="BLACK TOUCHTONE TELEPHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F57F,
+ },
+ [0x1F580]={
+ category="so",
+ description="TELEPHONE ON TOP OF MODEM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F580,
+ },
+ [0x1F581]={
+ category="so",
+ description="CLAMSHELL MOBILE PHONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F581,
+ },
+ [0x1F582]={
+ category="so",
+ description="BACK OF ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F582,
+ },
+ [0x1F583]={
+ category="so",
+ description="STAMPED ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F583,
+ },
+ [0x1F584]={
+ category="so",
+ description="ENVELOPE WITH LIGHTNING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F584,
+ },
+ [0x1F585]={
+ category="so",
+ description="FLYING ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F585,
+ },
+ [0x1F586]={
+ category="so",
+ description="PEN OVER STAMPED ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F586,
+ },
+ [0x1F587]={
+ category="so",
+ description="LINKED PAPERCLIPS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F587,
+ },
+ [0x1F588]={
+ category="so",
+ description="BLACK PUSHPIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F588,
+ },
+ [0x1F589]={
+ category="so",
+ description="LOWER LEFT PENCIL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F589,
+ },
+ [0x1F58A]={
+ category="so",
+ description="LOWER LEFT BALLPOINT PEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58A,
+ },
+ [0x1F58B]={
+ category="so",
+ description="LOWER LEFT FOUNTAIN PEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58B,
+ },
+ [0x1F58C]={
+ category="so",
+ description="LOWER LEFT PAINTBRUSH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58C,
+ },
+ [0x1F58D]={
+ category="so",
+ description="LOWER LEFT CRAYON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58D,
+ },
+ [0x1F58E]={
+ category="so",
+ description="LEFT WRITING HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58E,
+ },
+ [0x1F58F]={
+ category="so",
+ description="TURNED OK HAND SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F58F,
+ },
+ [0x1F590]={
+ category="so",
+ description="RAISED HAND WITH FINGERS SPLAYED",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F590,
+ },
+ [0x1F591]={
+ category="so",
+ description="REVERSED RAISED HAND WITH FINGERS SPLAYED",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F591,
+ },
+ [0x1F592]={
+ category="so",
+ description="REVERSED THUMBS UP SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F592,
+ },
+ [0x1F593]={
+ category="so",
+ description="REVERSED THUMBS DOWN SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F593,
+ },
+ [0x1F594]={
+ category="so",
+ description="REVERSED VICTORY HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F594,
+ },
+ [0x1F595]={
+ category="so",
+ description="REVERSED HAND WITH MIDDLE FINGER EXTENDED",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F595,
+ },
+ [0x1F596]={
+ category="so",
+ description="RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F596,
+ },
+ [0x1F597]={
+ category="so",
+ description="WHITE DOWN POINTING LEFT HAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F597,
+ },
+ [0x1F598]={
+ category="so",
+ description="SIDEWAYS WHITE LEFT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F598,
+ },
+ [0x1F599]={
+ category="so",
+ description="SIDEWAYS WHITE RIGHT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F599,
+ },
+ [0x1F59A]={
+ category="so",
+ description="SIDEWAYS BLACK LEFT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59A,
+ },
+ [0x1F59B]={
+ category="so",
+ description="SIDEWAYS BLACK RIGHT POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59B,
+ },
+ [0x1F59C]={
+ category="so",
+ description="BLACK LEFT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59C,
+ },
+ [0x1F59D]={
+ category="so",
+ description="BLACK RIGHT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59D,
+ },
+ [0x1F59E]={
+ category="so",
+ description="SIDEWAYS WHITE UP POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59E,
+ },
+ [0x1F59F]={
+ category="so",
+ description="SIDEWAYS WHITE DOWN POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F59F,
+ },
+ [0x1F5A0]={
+ category="so",
+ description="SIDEWAYS BLACK UP POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A0,
+ },
+ [0x1F5A1]={
+ category="so",
+ description="SIDEWAYS BLACK DOWN POINTING INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A1,
+ },
+ [0x1F5A2]={
+ category="so",
+ description="BLACK UP POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A2,
+ },
+ [0x1F5A3]={
+ category="so",
+ description="BLACK DOWN POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A3,
+ },
+ [0x1F5A5]={
+ category="so",
+ description="DESKTOP COMPUTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A5,
+ },
+ [0x1F5A6]={
+ category="so",
+ description="KEYBOARD AND MOUSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A6,
+ },
+ [0x1F5A7]={
+ category="so",
+ description="THREE NETWORKED COMPUTERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A7,
+ },
+ [0x1F5A8]={
+ category="so",
+ description="PRINTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A8,
+ },
+ [0x1F5A9]={
+ category="so",
+ description="POCKET CALCULATOR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5A9,
+ },
+ [0x1F5AA]={
+ category="so",
+ description="BLACK HARD SHELL FLOPPY DISK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AA,
+ },
+ [0x1F5AB]={
+ category="so",
+ description="WHITE HARD SHELL FLOPPY DISK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AB,
+ },
+ [0x1F5AC]={
+ category="so",
+ description="SOFT SHELL FLOPPY DISK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AC,
+ },
+ [0x1F5AD]={
+ category="so",
+ description="TAPE CARTRIDGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AD,
+ },
+ [0x1F5AE]={
+ category="so",
+ description="WIRED KEYBOARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AE,
+ },
+ [0x1F5AF]={
+ category="so",
+ description="ONE BUTTON MOUSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5AF,
+ },
+ [0x1F5B0]={
+ category="so",
+ description="TWO BUTTON MOUSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B0,
+ },
+ [0x1F5B1]={
+ category="so",
+ description="THREE BUTTON MOUSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B1,
+ },
+ [0x1F5B2]={
+ category="so",
+ description="TRACKBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B2,
+ },
+ [0x1F5B3]={
+ category="so",
+ description="OLD PERSONAL COMPUTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B3,
+ },
+ [0x1F5B4]={
+ category="so",
+ description="HARD DISK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B4,
+ },
+ [0x1F5B5]={
+ category="so",
+ description="SCREEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B5,
+ },
+ [0x1F5B6]={
+ category="so",
+ description="PRINTER ICON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B6,
+ },
+ [0x1F5B7]={
+ category="so",
+ description="FAX ICON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B7,
+ },
+ [0x1F5B8]={
+ category="so",
+ description="OPTICAL DISC ICON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B8,
+ },
+ [0x1F5B9]={
+ category="so",
+ description="DOCUMENT WITH TEXT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5B9,
+ },
+ [0x1F5BA]={
+ category="so",
+ description="DOCUMENT WITH TEXT AND PICTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BA,
+ },
+ [0x1F5BB]={
+ category="so",
+ description="DOCUMENT WITH PICTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BB,
+ },
+ [0x1F5BC]={
+ category="so",
+ description="FRAME WITH PICTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BC,
+ },
+ [0x1F5BD]={
+ category="so",
+ description="FRAME WITH TILES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BD,
+ },
+ [0x1F5BE]={
+ category="so",
+ description="FRAME WITH AN X",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BE,
+ },
+ [0x1F5BF]={
+ category="so",
+ description="BLACK FOLDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5BF,
+ },
+ [0x1F5C0]={
+ category="so",
+ description="FOLDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C0,
+ },
+ [0x1F5C1]={
+ category="so",
+ description="OPEN FOLDER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C1,
+ },
+ [0x1F5C2]={
+ category="so",
+ description="CARD INDEX DIVIDERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C2,
+ },
+ [0x1F5C3]={
+ category="so",
+ description="CARD FILE BOX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C3,
+ },
+ [0x1F5C4]={
+ category="so",
+ description="FILE CABINET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C4,
+ },
+ [0x1F5C5]={
+ category="so",
+ description="EMPTY NOTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C5,
+ },
+ [0x1F5C6]={
+ category="so",
+ description="EMPTY NOTE PAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C6,
+ },
+ [0x1F5C7]={
+ category="so",
+ description="EMPTY NOTE PAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C7,
+ },
+ [0x1F5C8]={
+ category="so",
+ description="NOTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C8,
+ },
+ [0x1F5C9]={
+ category="so",
+ description="NOTE PAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5C9,
+ },
+ [0x1F5CA]={
+ category="so",
+ description="NOTE PAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CA,
+ },
+ [0x1F5CB]={
+ category="so",
+ description="EMPTY DOCUMENT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CB,
+ },
+ [0x1F5CC]={
+ category="so",
+ description="EMPTY PAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CC,
+ },
+ [0x1F5CD]={
+ category="so",
+ description="EMPTY PAGES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CD,
+ },
+ [0x1F5CE]={
+ category="so",
+ description="DOCUMENT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CE,
+ },
+ [0x1F5CF]={
+ category="so",
+ description="PAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5CF,
+ },
+ [0x1F5D0]={
+ category="so",
+ description="PAGES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5D0,
+ },
+ [0x1F5D1]={
+ category="so",
+ description="WASTEBASKET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5D1,
+ },
+ [0x1F5D2]={
+ category="so",
+ description="SPIRAL NOTE PAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5D2,
+ },
+ [0x1F5D3]={
+ category="so",
+ description="SPIRAL CALENDAR PAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5D3,
+ },
+ [0x1F5D4]={
+ category="so",
+ description="DESKTOP WINDOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D4,
+ },
+ [0x1F5D5]={
+ category="so",
+ description="MINIMIZE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D5,
+ },
+ [0x1F5D6]={
+ category="so",
+ description="MAXIMIZE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D6,
+ },
+ [0x1F5D7]={
+ category="so",
+ description="OVERLAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D7,
+ },
+ [0x1F5D8]={
+ category="so",
+ description="CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D8,
+ },
+ [0x1F5D9]={
+ category="so",
+ description="CANCELLATION X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5D9,
+ },
+ [0x1F5DA]={
+ category="so",
+ description="INCREASE FONT SIZE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5DA,
+ },
+ [0x1F5DB]={
+ category="so",
+ description="DECREASE FONT SIZE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5DB,
+ },
+ [0x1F5DC]={
+ category="so",
+ description="COMPRESSION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5DC,
+ },
+ [0x1F5DD]={
+ category="so",
+ description="OLD KEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5DD,
+ },
+ [0x1F5DE]={
+ category="so",
+ description="ROLLED-UP NEWSPAPER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5DE,
+ },
+ [0x1F5DF]={
+ category="so",
+ description="PAGE WITH CIRCLED TEXT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5DF,
+ },
+ [0x1F5E0]={
+ category="so",
+ description="STOCK CHART",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E0,
+ },
+ [0x1F5E1]={
+ category="so",
+ description="DAGGER KNIFE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E1,
+ },
+ [0x1F5E2]={
+ category="so",
+ description="LIPS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E2,
+ },
+ [0x1F5E3]={
+ category="so",
+ description="SPEAKING HEAD IN SILHOUETTE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E3,
+ },
+ [0x1F5E4]={
+ category="so",
+ description="THREE RAYS ABOVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E4,
+ },
+ [0x1F5E5]={
+ category="so",
+ description="THREE RAYS BELOW",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E5,
+ },
+ [0x1F5E6]={
+ category="so",
+ description="THREE RAYS LEFT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E6,
+ },
+ [0x1F5E7]={
+ category="so",
+ description="THREE RAYS RIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E7,
+ },
+ [0x1F5E8]={
+ category="so",
+ description="LEFT SPEECH BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E8,
+ },
+ [0x1F5E9]={
+ category="so",
+ description="RIGHT SPEECH BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5E9,
+ },
+ [0x1F5EA]={
+ category="so",
+ description="TWO SPEECH BUBBLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5EA,
+ },
+ [0x1F5EB]={
+ category="so",
+ description="THREE SPEECH BUBBLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5EB,
+ },
+ [0x1F5EC]={
+ category="so",
+ description="LEFT THOUGHT BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5EC,
+ },
+ [0x1F5ED]={
+ category="so",
+ description="RIGHT THOUGHT BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5ED,
+ },
+ [0x1F5EE]={
+ category="so",
+ description="LEFT ANGER BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5EE,
+ },
+ [0x1F5EF]={
+ category="so",
+ description="RIGHT ANGER BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5EF,
+ },
+ [0x1F5F0]={
+ category="so",
+ description="MOOD BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5F0,
+ },
+ [0x1F5F1]={
+ category="so",
+ description="LIGHTNING MOOD BUBBLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5F1,
+ },
+ [0x1F5F2]={
+ category="so",
+ description="LIGHTNING MOOD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5F2,
+ },
+ [0x1F5F3]={
+ category="so",
+ description="BALLOT BOX WITH BALLOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5F3,
+ },
+ [0x1F5F4]={
+ category="so",
+ description="BALLOT SCRIPT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F4,
+ },
+ [0x1F5F5]={
+ category="so",
+ description="BALLOT BOX WITH SCRIPT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F5,
+ },
+ [0x1F5F6]={
+ category="so",
+ description="BALLOT BOLD SCRIPT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F6,
+ },
+ [0x1F5F7]={
+ category="so",
+ description="BALLOT BOX WITH BOLD SCRIPT X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F7,
+ },
+ [0x1F5F8]={
+ category="so",
+ description="LIGHT CHECK MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F8,
+ },
+ [0x1F5F9]={
+ category="so",
+ description="BALLOT BOX WITH BOLD CHECK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5F9,
+ },
+ [0x1F5FA]={
+ category="so",
+ description="WORLD MAP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FA,
+ },
+ [0x1F5FB]={
+ category="so",
+ description="MOUNT FUJI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FB,
+ },
+ [0x1F5FC]={
+ category="so",
+ description="TOKYO TOWER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FC,
+ },
+ [0x1F5FD]={
+ category="so",
+ description="STATUE OF LIBERTY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FD,
+ },
+ [0x1F5FE]={
+ category="so",
+ description="SILHOUETTE OF JAPAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FE,
+ },
+ [0x1F5FF]={
+ category="so",
+ description="MOYAI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F5FF,
+ },
+ [0x1F600]={
+ category="so",
+ description="GRINNING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F600,
+ },
+ [0x1F601]={
+ category="so",
+ description="GRINNING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F601,
+ },
+ [0x1F602]={
+ category="so",
+ description="FACE WITH TEARS OF JOY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F602,
+ },
+ [0x1F603]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F603,
+ },
+ [0x1F604]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F604,
+ },
+ [0x1F605]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND COLD SWEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F605,
+ },
+ [0x1F606]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F606,
+ },
+ [0x1F607]={
+ category="so",
+ description="SMILING FACE WITH HALO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F607,
+ },
+ [0x1F608]={
+ category="so",
+ description="SMILING FACE WITH HORNS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F608,
+ },
+ [0x1F609]={
+ category="so",
+ description="WINKING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F609,
+ },
+ [0x1F60A]={
+ category="so",
+ description="SMILING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60A,
+ },
+ [0x1F60B]={
+ category="so",
+ description="FACE SAVOURING DELICIOUS FOOD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60B,
+ },
+ [0x1F60C]={
+ category="so",
+ description="RELIEVED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60C,
+ },
+ [0x1F60D]={
+ category="so",
+ description="SMILING FACE WITH HEART-SHAPED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60D,
+ },
+ [0x1F60E]={
+ category="so",
+ description="SMILING FACE WITH SUNGLASSES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60E,
+ },
+ [0x1F60F]={
+ category="so",
+ description="SMIRKING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F60F,
+ },
+ [0x1F610]={
+ category="so",
+ description="NEUTRAL FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F610,
+ },
+ [0x1F611]={
+ category="so",
+ description="EXPRESSIONLESS FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F611,
+ },
+ [0x1F612]={
+ category="so",
+ description="UNAMUSED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F612,
+ },
+ [0x1F613]={
+ category="so",
+ description="FACE WITH COLD SWEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F613,
+ },
+ [0x1F614]={
+ category="so",
+ description="PENSIVE FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F614,
+ },
+ [0x1F615]={
+ category="so",
+ description="CONFUSED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F615,
+ },
+ [0x1F616]={
+ category="so",
+ description="CONFOUNDED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F616,
+ },
+ [0x1F617]={
+ category="so",
+ description="KISSING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F617,
+ },
+ [0x1F618]={
+ category="so",
+ description="FACE THROWING A KISS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F618,
+ },
+ [0x1F619]={
+ category="so",
+ description="KISSING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F619,
+ },
+ [0x1F61A]={
+ category="so",
+ description="KISSING FACE WITH CLOSED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61A,
+ },
+ [0x1F61B]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61B,
+ },
+ [0x1F61C]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE AND WINKING EYE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61C,
+ },
+ [0x1F61D]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61D,
+ },
+ [0x1F61E]={
+ category="so",
+ description="DISAPPOINTED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61E,
+ },
+ [0x1F61F]={
+ category="so",
+ description="WORRIED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61F,
+ },
+ [0x1F620]={
+ category="so",
+ description="ANGRY FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F620,
+ },
+ [0x1F621]={
+ category="so",
+ description="POUTING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F621,
+ },
+ [0x1F622]={
+ category="so",
+ description="CRYING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F622,
+ },
+ [0x1F623]={
+ category="so",
+ description="PERSEVERING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F623,
+ },
+ [0x1F624]={
+ category="so",
+ description="FACE WITH LOOK OF TRIUMPH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F624,
+ },
+ [0x1F625]={
+ category="so",
+ description="DISAPPOINTED BUT RELIEVED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F625,
+ },
+ [0x1F626]={
+ category="so",
+ description="FROWNING FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F626,
+ },
+ [0x1F627]={
+ category="so",
+ description="ANGUISHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F627,
+ },
+ [0x1F628]={
+ category="so",
+ description="FEARFUL FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F628,
+ },
+ [0x1F629]={
+ category="so",
+ description="WEARY FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F629,
+ },
+ [0x1F62A]={
+ category="so",
+ description="SLEEPY FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62A,
+ },
+ [0x1F62B]={
+ category="so",
+ description="TIRED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62B,
+ },
+ [0x1F62C]={
+ category="so",
+ description="GRIMACING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62C,
+ },
+ [0x1F62D]={
+ category="so",
+ description="LOUDLY CRYING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62D,
+ },
+ [0x1F62E]={
+ category="so",
+ description="FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62E,
+ },
+ [0x1F62F]={
+ category="so",
+ description="HUSHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62F,
+ },
+ [0x1F630]={
+ category="so",
+ description="FACE WITH OPEN MOUTH AND COLD SWEAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F630,
+ },
+ [0x1F631]={
+ category="so",
+ description="FACE SCREAMING IN FEAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F631,
+ },
+ [0x1F632]={
+ category="so",
+ description="ASTONISHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F632,
+ },
+ [0x1F633]={
+ category="so",
+ description="FLUSHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F633,
+ },
+ [0x1F634]={
+ category="so",
+ description="SLEEPING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F634,
+ },
+ [0x1F635]={
+ category="so",
+ description="DIZZY FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F635,
+ },
+ [0x1F636]={
+ category="so",
+ description="FACE WITHOUT MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F636,
+ },
+ [0x1F637]={
+ category="so",
+ description="FACE WITH MEDICAL MASK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F637,
+ },
+ [0x1F638]={
+ category="so",
+ description="GRINNING CAT FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F638,
+ },
+ [0x1F639]={
+ category="so",
+ description="CAT FACE WITH TEARS OF JOY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F639,
+ },
+ [0x1F63A]={
+ category="so",
+ description="SMILING CAT FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63A,
+ },
+ [0x1F63B]={
+ category="so",
+ description="SMILING CAT FACE WITH HEART-SHAPED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63B,
+ },
+ [0x1F63C]={
+ category="so",
+ description="CAT FACE WITH WRY SMILE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63C,
+ },
+ [0x1F63D]={
+ category="so",
+ description="KISSING CAT FACE WITH CLOSED EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63D,
+ },
+ [0x1F63E]={
+ category="so",
+ description="POUTING CAT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63E,
+ },
+ [0x1F63F]={
+ category="so",
+ description="CRYING CAT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F63F,
+ },
+ [0x1F640]={
+ category="so",
+ description="WEARY CAT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F640,
+ },
+ [0x1F641]={
+ category="so",
+ description="SLIGHTLY FROWNING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F641,
+ },
+ [0x1F642]={
+ category="so",
+ description="SLIGHTLY SMILING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F642,
+ },
+ [0x1F643]={
+ category="so",
+ description="UPSIDE-DOWN FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F643,
+ },
+ [0x1F644]={
+ category="so",
+ description="FACE WITH ROLLING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F644,
+ },
+ [0x1F645]={
+ category="so",
+ description="FACE WITH NO GOOD GESTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F645,
+ },
+ [0x1F646]={
+ category="so",
+ description="FACE WITH OK GESTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F646,
+ },
+ [0x1F647]={
+ category="so",
+ description="PERSON BOWING DEEPLY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F647,
+ },
+ [0x1F648]={
+ category="so",
+ description="SEE-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F648,
+ },
+ [0x1F649]={
+ category="so",
+ description="HEAR-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F649,
+ },
+ [0x1F64A]={
+ category="so",
+ description="SPEAK-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64A,
+ },
+ [0x1F64B]={
+ category="so",
+ description="HAPPY PERSON RAISING ONE HAND",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64B,
+ },
+ [0x1F64C]={
+ category="so",
+ description="PERSON RAISING BOTH HANDS IN CELEBRATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64C,
+ },
+ [0x1F64D]={
+ category="so",
+ description="PERSON FROWNING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64D,
+ },
+ [0x1F64E]={
+ category="so",
+ description="PERSON WITH POUTING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64E,
+ },
+ [0x1F64F]={
+ category="so",
+ description="PERSON WITH FOLDED HANDS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F64F,
+ },
+ [0x1F650]={
+ category="so",
+ description="NORTH WEST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F650,
+ },
+ [0x1F651]={
+ category="so",
+ description="SOUTH WEST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F651,
+ },
+ [0x1F652]={
+ category="so",
+ description="NORTH EAST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F652,
+ },
+ [0x1F653]={
+ category="so",
+ description="SOUTH EAST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F653,
+ },
+ [0x1F654]={
+ category="so",
+ description="TURNED NORTH WEST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F654,
+ },
+ [0x1F655]={
+ category="so",
+ description="TURNED SOUTH WEST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F655,
+ },
+ [0x1F656]={
+ category="so",
+ description="TURNED NORTH EAST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F656,
+ },
+ [0x1F657]={
+ category="so",
+ description="TURNED SOUTH EAST POINTING LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F657,
+ },
+ [0x1F658]={
+ category="so",
+ description="NORTH WEST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F658,
+ },
+ [0x1F659]={
+ category="so",
+ description="SOUTH WEST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F659,
+ },
+ [0x1F65A]={
+ category="so",
+ description="NORTH EAST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65A,
+ },
+ [0x1F65B]={
+ category="so",
+ description="SOUTH EAST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65B,
+ },
+ [0x1F65C]={
+ category="so",
+ description="HEAVY NORTH WEST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65C,
+ },
+ [0x1F65D]={
+ category="so",
+ description="HEAVY SOUTH WEST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65D,
+ },
+ [0x1F65E]={
+ category="so",
+ description="HEAVY NORTH EAST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65E,
+ },
+ [0x1F65F]={
+ category="so",
+ description="HEAVY SOUTH EAST POINTING VINE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F65F,
+ },
+ [0x1F660]={
+ category="so",
+ description="NORTH WEST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F660,
+ },
+ [0x1F661]={
+ category="so",
+ description="SOUTH WEST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F661,
+ },
+ [0x1F662]={
+ category="so",
+ description="NORTH EAST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F662,
+ },
+ [0x1F663]={
+ category="so",
+ description="SOUTH EAST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F663,
+ },
+ [0x1F664]={
+ category="so",
+ description="HEAVY NORTH WEST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F664,
+ },
+ [0x1F665]={
+ category="so",
+ description="HEAVY SOUTH WEST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F665,
+ },
+ [0x1F666]={
+ category="so",
+ description="HEAVY NORTH EAST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F666,
+ },
+ [0x1F667]={
+ category="so",
+ description="HEAVY SOUTH EAST POINTING BUD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F667,
+ },
+ [0x1F668]={
+ category="so",
+ description="HOLLOW QUILT SQUARE ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F668,
+ },
+ [0x1F669]={
+ category="so",
+ description="HOLLOW QUILT SQUARE ORNAMENT IN BLACK SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F669,
+ },
+ [0x1F66A]={
+ category="so",
+ description="SOLID QUILT SQUARE ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66A,
+ },
+ [0x1F66B]={
+ category="so",
+ description="SOLID QUILT SQUARE ORNAMENT IN BLACK SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66B,
+ },
+ [0x1F66C]={
+ category="so",
+ description="LEFTWARDS ROCKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66C,
+ },
+ [0x1F66D]={
+ category="so",
+ description="UPWARDS ROCKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66D,
+ },
+ [0x1F66E]={
+ category="so",
+ description="RIGHTWARDS ROCKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66E,
+ },
+ [0x1F66F]={
+ category="so",
+ description="DOWNWARDS ROCKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F66F,
+ },
+ [0x1F670]={
+ category="so",
+ description="SCRIPT LIGATURE ET ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F670,
+ },
+ [0x1F671]={
+ category="so",
+ description="HEAVY SCRIPT LIGATURE ET ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F671,
+ },
+ [0x1F672]={
+ category="so",
+ description="LIGATURE OPEN ET ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F672,
+ },
+ [0x1F673]={
+ category="so",
+ description="HEAVY LIGATURE OPEN ET ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F673,
+ },
+ [0x1F674]={
+ category="so",
+ description="HEAVY AMPERSAND ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F674,
+ },
+ [0x1F675]={
+ category="so",
+ description="SWASH AMPERSAND ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F675,
+ },
+ [0x1F676]={
+ category="so",
+ description="SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x1F676,
+ },
+ [0x1F677]={
+ category="so",
+ description="SANS-SERIF HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x1F677,
+ },
+ [0x1F678]={
+ category="so",
+ description="SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="qu",
+ unicodeslot=0x1F678,
+ },
+ [0x1F679]={
+ category="so",
+ description="HEAVY INTERROBANG ORNAMENT",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x1F679,
+ },
+ [0x1F67A]={
+ category="so",
+ description="SANS-SERIF INTERROBANG ORNAMENT",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x1F67A,
+ },
+ [0x1F67B]={
+ category="so",
+ description="HEAVY SANS-SERIF INTERROBANG ORNAMENT",
+ direction="on",
+ linebreak="ns",
+ unicodeslot=0x1F67B,
+ },
+ [0x1F67C]={
+ category="so",
+ description="VERY HEAVY SOLIDUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F67C,
+ },
+ [0x1F67D]={
+ category="so",
+ description="VERY HEAVY REVERSE SOLIDUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F67D,
+ },
+ [0x1F67E]={
+ category="so",
+ description="CHECKER BOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F67E,
+ },
+ [0x1F67F]={
+ category="so",
+ description="REVERSE CHECKER BOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F67F,
+ },
+ [0x1F680]={
+ category="so",
+ description="ROCKET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F680,
+ },
+ [0x1F681]={
+ category="so",
+ description="HELICOPTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F681,
+ },
+ [0x1F682]={
+ category="so",
+ description="STEAM LOCOMOTIVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F682,
+ },
+ [0x1F683]={
+ category="so",
+ description="RAILWAY CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F683,
+ },
+ [0x1F684]={
+ category="so",
+ description="HIGH-SPEED TRAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F684,
+ },
+ [0x1F685]={
+ category="so",
+ description="HIGH-SPEED TRAIN WITH BULLET NOSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F685,
+ },
+ [0x1F686]={
+ category="so",
+ description="TRAIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F686,
+ },
+ [0x1F687]={
+ category="so",
+ description="METRO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F687,
+ },
+ [0x1F688]={
+ category="so",
+ description="LIGHT RAIL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F688,
+ },
+ [0x1F689]={
+ category="so",
+ description="STATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F689,
+ },
+ [0x1F68A]={
+ category="so",
+ description="TRAM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68A,
+ },
+ [0x1F68B]={
+ category="so",
+ description="TRAM CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68B,
+ },
+ [0x1F68C]={
+ category="so",
+ description="BUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68C,
+ },
+ [0x1F68D]={
+ category="so",
+ description="ONCOMING BUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68D,
+ },
+ [0x1F68E]={
+ category="so",
+ description="TROLLEYBUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68E,
+ },
+ [0x1F68F]={
+ category="so",
+ description="BUS STOP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F68F,
+ },
+ [0x1F690]={
+ category="so",
+ description="MINIBUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F690,
+ },
+ [0x1F691]={
+ category="so",
+ description="AMBULANCE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F691,
+ },
+ [0x1F692]={
+ category="so",
+ description="FIRE ENGINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F692,
+ },
+ [0x1F693]={
+ category="so",
+ description="POLICE CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F693,
+ },
+ [0x1F694]={
+ category="so",
+ description="ONCOMING POLICE CAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F694,
+ },
+ [0x1F695]={
+ category="so",
+ description="TAXI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F695,
+ },
+ [0x1F696]={
+ category="so",
+ description="ONCOMING TAXI",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F696,
+ },
+ [0x1F697]={
+ category="so",
+ description="AUTOMOBILE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F697,
+ },
+ [0x1F698]={
+ category="so",
+ description="ONCOMING AUTOMOBILE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F698,
+ },
+ [0x1F699]={
+ category="so",
+ description="RECREATIONAL VEHICLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F699,
+ },
+ [0x1F69A]={
+ category="so",
+ description="DELIVERY TRUCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69A,
+ },
+ [0x1F69B]={
+ category="so",
+ description="ARTICULATED LORRY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69B,
+ },
+ [0x1F69C]={
+ category="so",
+ description="TRACTOR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69C,
+ },
+ [0x1F69D]={
+ category="so",
+ description="MONORAIL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69D,
+ },
+ [0x1F69E]={
+ category="so",
+ description="MOUNTAIN RAILWAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69E,
+ },
+ [0x1F69F]={
+ category="so",
+ description="SUSPENSION RAILWAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F69F,
+ },
+ [0x1F6A0]={
+ category="so",
+ description="MOUNTAIN CABLEWAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A0,
+ },
+ [0x1F6A1]={
+ category="so",
+ description="AERIAL TRAMWAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A1,
+ },
+ [0x1F6A2]={
+ category="so",
+ description="SHIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A2,
+ },
+ [0x1F6A3]={
+ category="so",
+ description="ROWBOAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A3,
+ },
+ [0x1F6A4]={
+ category="so",
+ description="SPEEDBOAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A4,
+ },
+ [0x1F6A5]={
+ category="so",
+ description="HORIZONTAL TRAFFIC LIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A5,
+ },
+ [0x1F6A6]={
+ category="so",
+ description="VERTICAL TRAFFIC LIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A6,
+ },
+ [0x1F6A7]={
+ category="so",
+ description="CONSTRUCTION SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A7,
+ },
+ [0x1F6A8]={
+ category="so",
+ description="POLICE CARS REVOLVING LIGHT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A8,
+ },
+ [0x1F6A9]={
+ category="so",
+ description="TRIANGULAR FLAG ON POST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6A9,
+ },
+ [0x1F6AA]={
+ category="so",
+ description="DOOR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AA,
+ },
+ [0x1F6AB]={
+ category="so",
+ description="NO ENTRY SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AB,
+ },
+ [0x1F6AC]={
+ category="so",
+ description="SMOKING SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AC,
+ },
+ [0x1F6AD]={
+ category="so",
+ description="NO SMOKING SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AD,
+ },
+ [0x1F6AE]={
+ category="so",
+ description="PUT LITTER IN ITS PLACE SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AE,
+ },
+ [0x1F6AF]={
+ category="so",
+ description="DO NOT LITTER SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6AF,
+ },
+ [0x1F6B0]={
+ category="so",
+ description="POTABLE WATER SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B0,
+ },
+ [0x1F6B1]={
+ category="so",
+ description="NON-POTABLE WATER SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B1,
+ },
+ [0x1F6B2]={
+ category="so",
+ description="BICYCLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B2,
+ },
+ [0x1F6B3]={
+ category="so",
+ description="NO BICYCLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B3,
+ },
+ [0x1F6B4]={
+ category="so",
+ description="BICYCLIST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B4,
+ },
+ [0x1F6B5]={
+ category="so",
+ description="MOUNTAIN BICYCLIST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B5,
+ },
+ [0x1F6B6]={
+ category="so",
+ description="PEDESTRIAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B6,
+ },
+ [0x1F6B7]={
+ category="so",
+ description="NO PEDESTRIANS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B7,
+ },
+ [0x1F6B8]={
+ category="so",
+ description="CHILDREN CROSSING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B8,
+ },
+ [0x1F6B9]={
+ category="so",
+ description="MENS SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6B9,
+ },
+ [0x1F6BA]={
+ category="so",
+ description="WOMENS SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BA,
+ },
+ [0x1F6BB]={
+ category="so",
+ description="RESTROOM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BB,
+ },
+ [0x1F6BC]={
+ category="so",
+ description="BABY SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BC,
+ },
+ [0x1F6BD]={
+ category="so",
+ description="TOILET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BD,
+ },
+ [0x1F6BE]={
+ category="so",
+ description="WATER CLOSET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BE,
+ },
+ [0x1F6BF]={
+ category="so",
+ description="SHOWER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6BF,
+ },
+ [0x1F6C0]={
+ category="so",
+ description="BATH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C0,
+ },
+ [0x1F6C1]={
+ category="so",
+ description="BATHTUB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C1,
+ },
+ [0x1F6C2]={
+ category="so",
+ description="PASSPORT CONTROL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C2,
+ },
+ [0x1F6C3]={
+ category="so",
+ description="CUSTOMS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C3,
+ },
+ [0x1F6C4]={
+ category="so",
+ description="BAGGAGE CLAIM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C4,
+ },
+ [0x1F6C5]={
+ category="so",
+ description="LEFT LUGGAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C5,
+ },
+ [0x1F6C6]={
+ category="so",
+ description="TRIANGLE WITH ROUNDED CORNERS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C6,
+ },
+ [0x1F6C7]={
+ category="so",
+ description="PROHIBITED SIGN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C7,
+ },
+ [0x1F6C8]={
+ category="so",
+ description="CIRCLED INFORMATION SOURCE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C8,
+ },
+ [0x1F6C9]={
+ category="so",
+ description="BOYS SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6C9,
+ },
+ [0x1F6CA]={
+ category="so",
+ description="GIRLS SYMBOL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CA,
+ },
+ [0x1F6CB]={
+ category="so",
+ description="COUCH AND LAMP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CB,
+ },
+ [0x1F6CC]={
+ category="so",
+ description="SLEEPING ACCOMMODATION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CC,
+ },
+ [0x1F6CD]={
+ category="so",
+ description="SHOPPING BAGS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CD,
+ },
+ [0x1F6CE]={
+ category="so",
+ description="BELLHOP BELL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CE,
+ },
+ [0x1F6CF]={
+ category="so",
+ description="BED",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6CF,
+ },
+ [0x1F6D0]={
+ category="so",
+ description="PLACE OF WORSHIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6D0,
+ },
+ [0x1F6E0]={
+ category="so",
+ description="HAMMER AND WRENCH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E0,
+ },
+ [0x1F6E1]={
+ category="so",
+ description="SHIELD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E1,
+ },
+ [0x1F6E2]={
+ category="so",
+ description="OIL DRUM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E2,
+ },
+ [0x1F6E3]={
+ category="so",
+ description="MOTORWAY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E3,
+ },
+ [0x1F6E4]={
+ category="so",
+ description="RAILWAY TRACK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E4,
+ },
+ [0x1F6E5]={
+ category="so",
+ description="MOTOR BOAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E5,
+ },
+ [0x1F6E6]={
+ category="so",
+ description="UP-POINTING MILITARY AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E6,
+ },
+ [0x1F6E7]={
+ category="so",
+ description="UP-POINTING AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E7,
+ },
+ [0x1F6E8]={
+ category="so",
+ description="UP-POINTING SMALL AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E8,
+ },
+ [0x1F6E9]={
+ category="so",
+ description="SMALL AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6E9,
+ },
+ [0x1F6EA]={
+ category="so",
+ description="NORTHEAST-POINTING AIRPLANE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6EA,
+ },
+ [0x1F6EB]={
+ category="so",
+ description="AIRPLANE DEPARTURE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6EB,
+ },
+ [0x1F6EC]={
+ category="so",
+ description="AIRPLANE ARRIVING",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6EC,
+ },
+ [0x1F6F0]={
+ category="so",
+ description="SATELLITE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6F0,
+ },
+ [0x1F6F1]={
+ category="so",
+ description="ONCOMING FIRE ENGINE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6F1,
+ },
+ [0x1F6F2]={
+ category="so",
+ description="DIESEL LOCOMOTIVE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6F2,
+ },
+ [0x1F6F3]={
+ category="so",
+ description="PASSENGER SHIP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6F3,
+ },
+ [0x1F700]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR QUINTESSENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F700,
+ },
+ [0x1F701]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AIR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F701,
+ },
+ [0x1F702]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR FIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F702,
+ },
+ [0x1F703]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F703,
+ },
+ [0x1F704]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR WATER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F704,
+ },
+ [0x1F705]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUAFORTIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F705,
+ },
+ [0x1F706]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA REGIA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F706,
+ },
+ [0x1F707]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA REGIA-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F707,
+ },
+ [0x1F708]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA VITAE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F708,
+ },
+ [0x1F709]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA VITAE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F709,
+ },
+ [0x1F70A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70A,
+ },
+ [0x1F70B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70B,
+ },
+ [0x1F70C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70C,
+ },
+ [0x1F70D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70D,
+ },
+ [0x1F70E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70E,
+ },
+ [0x1F70F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BLACK SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70F,
+ },
+ [0x1F710]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F710,
+ },
+ [0x1F711]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F711,
+ },
+ [0x1F712]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F712,
+ },
+ [0x1F713]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CINNABAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F713,
+ },
+ [0x1F714]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F714,
+ },
+ [0x1F715]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR NITRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F715,
+ },
+ [0x1F716]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VITRIOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F716,
+ },
+ [0x1F717]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VITRIOL-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F717,
+ },
+ [0x1F718]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ROCK SALT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F718,
+ },
+ [0x1F719]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ROCK SALT-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F719,
+ },
+ [0x1F71A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR GOLD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71A,
+ },
+ [0x1F71B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SILVER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71B,
+ },
+ [0x1F71C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71C,
+ },
+ [0x1F71D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON ORE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71D,
+ },
+ [0x1F71E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF IRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71E,
+ },
+ [0x1F71F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF IRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71F,
+ },
+ [0x1F720]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR COPPER ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F720,
+ },
+ [0x1F721]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON-COPPER ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F721,
+ },
+ [0x1F722]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F722,
+ },
+ [0x1F723]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F723,
+ },
+ [0x1F724]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F724,
+ },
+ [0x1F725]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F725,
+ },
+ [0x1F726]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F726,
+ },
+ [0x1F727]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F727,
+ },
+ [0x1F728]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VERDIGRIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F728,
+ },
+ [0x1F729]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TIN ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F729,
+ },
+ [0x1F72A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR LEAD ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72A,
+ },
+ [0x1F72B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ANTIMONY ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72B,
+ },
+ [0x1F72C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72C,
+ },
+ [0x1F72D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72D,
+ },
+ [0x1F72E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72E,
+ },
+ [0x1F72F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72F,
+ },
+ [0x1F730]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F730,
+ },
+ [0x1F731]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F731,
+ },
+ [0x1F732]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F732,
+ },
+ [0x1F733]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F733,
+ },
+ [0x1F734]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F734,
+ },
+ [0x1F735]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-4",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F735,
+ },
+ [0x1F736]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALKALI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F736,
+ },
+ [0x1F737]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALKALI-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F737,
+ },
+ [0x1F738]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MARCASITE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F738,
+ },
+ [0x1F739]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SAL-AMMONIAC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F739,
+ },
+ [0x1F73A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ARSENIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73A,
+ },
+ [0x1F73B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REALGAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73B,
+ },
+ [0x1F73C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REALGAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73C,
+ },
+ [0x1F73D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AURIPIGMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73D,
+ },
+ [0x1F73E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BISMUTH ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73E,
+ },
+ [0x1F73F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TARTAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73F,
+ },
+ [0x1F740]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TARTAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F740,
+ },
+ [0x1F741]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR QUICK LIME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F741,
+ },
+ [0x1F742]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F742,
+ },
+ [0x1F743]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F743,
+ },
+ [0x1F744]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F744,
+ },
+ [0x1F745]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F745,
+ },
+ [0x1F746]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR OIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F746,
+ },
+ [0x1F747]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SPIRIT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F747,
+ },
+ [0x1F748]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TINCTURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F748,
+ },
+ [0x1F749]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR GUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F749,
+ },
+ [0x1F74A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR WAX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74A,
+ },
+ [0x1F74B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POWDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74B,
+ },
+ [0x1F74C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CALX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74C,
+ },
+ [0x1F74D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TUTTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74D,
+ },
+ [0x1F74E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CAPUT MORTUUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74E,
+ },
+ [0x1F74F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74F,
+ },
+ [0x1F750]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CADUCEUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F750,
+ },
+ [0x1F751]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TRIDENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F751,
+ },
+ [0x1F752]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STARRED TRIDENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F752,
+ },
+ [0x1F753]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR LODESTONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F753,
+ },
+ [0x1F754]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SOAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F754,
+ },
+ [0x1F755]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR URINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F755,
+ },
+ [0x1F756]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HORSE DUNG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F756,
+ },
+ [0x1F757]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ASHES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F757,
+ },
+ [0x1F758]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POT ASHES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F758,
+ },
+ [0x1F759]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BRICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F759,
+ },
+ [0x1F75A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POWDERED BRICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75A,
+ },
+ [0x1F75B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AMALGAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75B,
+ },
+ [0x1F75C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75C,
+ },
+ [0x1F75D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75D,
+ },
+ [0x1F75E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75E,
+ },
+ [0x1F75F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PRECIPITATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75F,
+ },
+ [0x1F760]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISTILL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F760,
+ },
+ [0x1F761]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISSOLVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F761,
+ },
+ [0x1F762]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISSOLVE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F762,
+ },
+ [0x1F763]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PURIFY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F763,
+ },
+ [0x1F764]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PUTREFACTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F764,
+ },
+ [0x1F765]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F765,
+ },
+ [0x1F766]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F766,
+ },
+ [0x1F767]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F767,
+ },
+ [0x1F768]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-4",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F768,
+ },
+ [0x1F769]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-5",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F769,
+ },
+ [0x1F76A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALEMBIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76A,
+ },
+ [0x1F76B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BATH OF MARY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76B,
+ },
+ [0x1F76C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BATH OF VAPOURS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76C,
+ },
+ [0x1F76D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR RETORT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76D,
+ },
+ [0x1F76E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76E,
+ },
+ [0x1F76F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR NIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76F,
+ },
+ [0x1F770]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DAY-NIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F770,
+ },
+ [0x1F771]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MONTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F771,
+ },
+ [0x1F772]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HALF DRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F772,
+ },
+ [0x1F773]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HALF OUNCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F773,
+ },
+ [0x1F780]={
+ category="so",
+ description="BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F780,
+ },
+ [0x1F781]={
+ category="so",
+ description="BLACK UP-POINTING ISOSCELES RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F781,
+ },
+ [0x1F782]={
+ category="so",
+ description="BLACK RIGHT-POINTING ISOSCELES RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F782,
+ },
+ [0x1F783]={
+ category="so",
+ description="BLACK DOWN-POINTING ISOSCELES RIGHT TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F783,
+ },
+ [0x1F784]={
+ category="so",
+ description="BLACK SLIGHTLY SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F784,
+ },
+ [0x1F785]={
+ category="so",
+ description="MEDIUM BOLD WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F785,
+ },
+ [0x1F786]={
+ category="so",
+ description="BOLD WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F786,
+ },
+ [0x1F787]={
+ category="so",
+ description="HEAVY WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F787,
+ },
+ [0x1F788]={
+ category="so",
+ description="VERY HEAVY WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F788,
+ },
+ [0x1F789]={
+ category="so",
+ description="EXTREMELY HEAVY WHITE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F789,
+ },
+ [0x1F78A]={
+ category="so",
+ description="WHITE CIRCLE CONTAINING BLACK SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78A,
+ },
+ [0x1F78B]={
+ category="so",
+ description="ROUND TARGET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78B,
+ },
+ [0x1F78C]={
+ category="so",
+ description="BLACK TINY SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78C,
+ },
+ [0x1F78D]={
+ category="so",
+ description="BLACK SLIGHTLY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78D,
+ },
+ [0x1F78E]={
+ category="so",
+ description="LIGHT WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78E,
+ },
+ [0x1F78F]={
+ category="so",
+ description="MEDIUM WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F78F,
+ },
+ [0x1F790]={
+ category="so",
+ description="BOLD WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F790,
+ },
+ [0x1F791]={
+ category="so",
+ description="HEAVY WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F791,
+ },
+ [0x1F792]={
+ category="so",
+ description="VERY HEAVY WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F792,
+ },
+ [0x1F793]={
+ category="so",
+ description="EXTREMELY HEAVY WHITE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F793,
+ },
+ [0x1F794]={
+ category="so",
+ description="WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F794,
+ },
+ [0x1F795]={
+ category="so",
+ description="WHITE SQUARE CONTAINING BLACK MEDIUM SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F795,
+ },
+ [0x1F796]={
+ category="so",
+ description="SQUARE TARGET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F796,
+ },
+ [0x1F797]={
+ category="so",
+ description="BLACK TINY DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F797,
+ },
+ [0x1F798]={
+ category="so",
+ description="BLACK VERY SMALL DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F798,
+ },
+ [0x1F799]={
+ category="so",
+ description="BLACK MEDIUM SMALL DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F799,
+ },
+ [0x1F79A]={
+ category="so",
+ description="WHITE DIAMOND CONTAINING BLACK VERY SMALL DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79A,
+ },
+ [0x1F79B]={
+ category="so",
+ description="WHITE DIAMOND CONTAINING BLACK MEDIUM DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79B,
+ },
+ [0x1F79C]={
+ category="so",
+ description="DIAMOND TARGET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79C,
+ },
+ [0x1F79D]={
+ category="so",
+ description="BLACK TINY LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79D,
+ },
+ [0x1F79E]={
+ category="so",
+ description="BLACK VERY SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79E,
+ },
+ [0x1F79F]={
+ category="so",
+ description="BLACK MEDIUM SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F79F,
+ },
+ [0x1F7A0]={
+ category="so",
+ description="WHITE LOZENGE CONTAINING BLACK SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A0,
+ },
+ [0x1F7A1]={
+ category="so",
+ description="THIN GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A1,
+ },
+ [0x1F7A2]={
+ category="so",
+ description="LIGHT GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A2,
+ },
+ [0x1F7A3]={
+ category="so",
+ description="MEDIUM GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A3,
+ },
+ [0x1F7A4]={
+ category="so",
+ description="BOLD GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A4,
+ },
+ [0x1F7A5]={
+ category="so",
+ description="VERY BOLD GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A5,
+ },
+ [0x1F7A6]={
+ category="so",
+ description="VERY HEAVY GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A6,
+ },
+ [0x1F7A7]={
+ category="so",
+ description="EXTREMELY HEAVY GREEK CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A7,
+ },
+ [0x1F7A8]={
+ category="so",
+ description="THIN SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A8,
+ },
+ [0x1F7A9]={
+ category="so",
+ description="LIGHT SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7A9,
+ },
+ [0x1F7AA]={
+ category="so",
+ description="MEDIUM SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AA,
+ },
+ [0x1F7AB]={
+ category="so",
+ description="BOLD SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AB,
+ },
+ [0x1F7AC]={
+ category="so",
+ description="HEAVY SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AC,
+ },
+ [0x1F7AD]={
+ category="so",
+ description="VERY HEAVY SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AD,
+ },
+ [0x1F7AE]={
+ category="so",
+ description="EXTREMELY HEAVY SALTIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AE,
+ },
+ [0x1F7AF]={
+ category="so",
+ description="LIGHT FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7AF,
+ },
+ [0x1F7B0]={
+ category="so",
+ description="MEDIUM FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B0,
+ },
+ [0x1F7B1]={
+ category="so",
+ description="BOLD FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B1,
+ },
+ [0x1F7B2]={
+ category="so",
+ description="HEAVY FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B2,
+ },
+ [0x1F7B3]={
+ category="so",
+ description="VERY HEAVY FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B3,
+ },
+ [0x1F7B4]={
+ category="so",
+ description="EXTREMELY HEAVY FIVE SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B4,
+ },
+ [0x1F7B5]={
+ category="so",
+ description="LIGHT SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B5,
+ },
+ [0x1F7B6]={
+ category="so",
+ description="MEDIUM SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B6,
+ },
+ [0x1F7B7]={
+ category="so",
+ description="BOLD SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B7,
+ },
+ [0x1F7B8]={
+ category="so",
+ description="HEAVY SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B8,
+ },
+ [0x1F7B9]={
+ category="so",
+ description="VERY HEAVY SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7B9,
+ },
+ [0x1F7BA]={
+ category="so",
+ description="EXTREMELY HEAVY SIX SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BA,
+ },
+ [0x1F7BB]={
+ category="so",
+ description="LIGHT EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BB,
+ },
+ [0x1F7BC]={
+ category="so",
+ description="MEDIUM EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BC,
+ },
+ [0x1F7BD]={
+ category="so",
+ description="BOLD EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BD,
+ },
+ [0x1F7BE]={
+ category="so",
+ description="HEAVY EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BE,
+ },
+ [0x1F7BF]={
+ category="so",
+ description="VERY HEAVY EIGHT SPOKED ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7BF,
+ },
+ [0x1F7C0]={
+ category="so",
+ description="LIGHT THREE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C0,
+ },
+ [0x1F7C1]={
+ category="so",
+ description="MEDIUM THREE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C1,
+ },
+ [0x1F7C2]={
+ category="so",
+ description="THREE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C2,
+ },
+ [0x1F7C3]={
+ category="so",
+ description="MEDIUM THREE POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C3,
+ },
+ [0x1F7C4]={
+ category="so",
+ description="LIGHT FOUR POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C4,
+ },
+ [0x1F7C5]={
+ category="so",
+ description="MEDIUM FOUR POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C5,
+ },
+ [0x1F7C6]={
+ category="so",
+ description="FOUR POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C6,
+ },
+ [0x1F7C7]={
+ category="so",
+ description="MEDIUM FOUR POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C7,
+ },
+ [0x1F7C8]={
+ category="so",
+ description="REVERSE LIGHT FOUR POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C8,
+ },
+ [0x1F7C9]={
+ category="so",
+ description="LIGHT FIVE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7C9,
+ },
+ [0x1F7CA]={
+ category="so",
+ description="HEAVY FIVE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CA,
+ },
+ [0x1F7CB]={
+ category="so",
+ description="MEDIUM SIX POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CB,
+ },
+ [0x1F7CC]={
+ category="so",
+ description="HEAVY SIX POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CC,
+ },
+ [0x1F7CD]={
+ category="so",
+ description="SIX POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CD,
+ },
+ [0x1F7CE]={
+ category="so",
+ description="MEDIUM EIGHT POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CE,
+ },
+ [0x1F7CF]={
+ category="so",
+ description="HEAVY EIGHT POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7CF,
+ },
+ [0x1F7D0]={
+ category="so",
+ description="VERY HEAVY EIGHT POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7D0,
+ },
+ [0x1F7D1]={
+ category="so",
+ description="HEAVY EIGHT POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7D1,
+ },
+ [0x1F7D2]={
+ category="so",
+ description="LIGHT TWELVE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7D2,
+ },
+ [0x1F7D3]={
+ category="so",
+ description="HEAVY TWELVE POINTED BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7D3,
+ },
+ [0x1F7D4]={
+ category="so",
+ description="HEAVY TWELVE POINTED PINWHEEL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F7D4,
+ },
+ [0x1F800]={
+ category="so",
+ description="LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F800,
+ },
+ [0x1F801]={
+ category="so",
+ description="UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F801,
+ },
+ [0x1F802]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F802,
+ },
+ [0x1F803]={
+ category="so",
+ description="DOWNWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F803,
+ },
+ [0x1F804]={
+ category="so",
+ description="LEFTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F804,
+ },
+ [0x1F805]={
+ category="so",
+ description="UPWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F805,
+ },
+ [0x1F806]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F806,
+ },
+ [0x1F807]={
+ category="so",
+ description="DOWNWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F807,
+ },
+ [0x1F808]={
+ category="so",
+ description="LEFTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F808,
+ },
+ [0x1F809]={
+ category="so",
+ description="UPWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F809,
+ },
+ [0x1F80A]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F80A,
+ },
+ [0x1F80B]={
+ category="so",
+ description="DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F80B,
+ },
+ [0x1F810]={
+ category="so",
+ description="LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F810,
+ },
+ [0x1F811]={
+ category="so",
+ description="UPWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F811,
+ },
+ [0x1F812]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F812,
+ },
+ [0x1F813]={
+ category="so",
+ description="DOWNWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F813,
+ },
+ [0x1F814]={
+ category="so",
+ description="LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F814,
+ },
+ [0x1F815]={
+ category="so",
+ description="UPWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F815,
+ },
+ [0x1F816]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F816,
+ },
+ [0x1F817]={
+ category="so",
+ description="DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F817,
+ },
+ [0x1F818]={
+ category="so",
+ description="HEAVY LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F818,
+ },
+ [0x1F819]={
+ category="so",
+ description="HEAVY UPWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F819,
+ },
+ [0x1F81A]={
+ category="so",
+ description="HEAVY RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81A,
+ },
+ [0x1F81B]={
+ category="so",
+ description="HEAVY DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81B,
+ },
+ [0x1F81C]={
+ category="so",
+ description="HEAVY LEFTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81C,
+ },
+ [0x1F81D]={
+ category="so",
+ description="HEAVY UPWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81D,
+ },
+ [0x1F81E]={
+ category="so",
+ description="HEAVY RIGHTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81E,
+ },
+ [0x1F81F]={
+ category="so",
+ description="HEAVY DOWNWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F81F,
+ },
+ [0x1F820]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F820,
+ },
+ [0x1F821]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F821,
+ },
+ [0x1F822]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F822,
+ },
+ [0x1F823]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F823,
+ },
+ [0x1F824]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F824,
+ },
+ [0x1F825]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F825,
+ },
+ [0x1F826]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F826,
+ },
+ [0x1F827]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F827,
+ },
+ [0x1F828]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F828,
+ },
+ [0x1F829]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F829,
+ },
+ [0x1F82A]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82A,
+ },
+ [0x1F82B]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82B,
+ },
+ [0x1F82C]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82C,
+ },
+ [0x1F82D]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82D,
+ },
+ [0x1F82E]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82E,
+ },
+ [0x1F82F]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F82F,
+ },
+ [0x1F830]={
+ category="so",
+ description="LEFTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F830,
+ },
+ [0x1F831]={
+ category="so",
+ description="UPWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F831,
+ },
+ [0x1F832]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F832,
+ },
+ [0x1F833]={
+ category="so",
+ description="DOWNWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F833,
+ },
+ [0x1F834]={
+ category="so",
+ description="LEFTWARDS FINGER-POST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F834,
+ },
+ [0x1F835]={
+ category="so",
+ description="UPWARDS FINGER-POST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F835,
+ },
+ [0x1F836]={
+ category="so",
+ description="RIGHTWARDS FINGER-POST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F836,
+ },
+ [0x1F837]={
+ category="so",
+ description="DOWNWARDS FINGER-POST ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F837,
+ },
+ [0x1F838]={
+ category="so",
+ description="LEFTWARDS SQUARED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F838,
+ },
+ [0x1F839]={
+ category="so",
+ description="UPWARDS SQUARED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F839,
+ },
+ [0x1F83A]={
+ category="so",
+ description="RIGHTWARDS SQUARED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83A,
+ },
+ [0x1F83B]={
+ category="so",
+ description="DOWNWARDS SQUARED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83B,
+ },
+ [0x1F83C]={
+ category="so",
+ description="LEFTWARDS COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83C,
+ },
+ [0x1F83D]={
+ category="so",
+ description="UPWARDS COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83D,
+ },
+ [0x1F83E]={
+ category="so",
+ description="RIGHTWARDS COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83E,
+ },
+ [0x1F83F]={
+ category="so",
+ description="DOWNWARDS COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F83F,
+ },
+ [0x1F840]={
+ category="so",
+ description="LEFTWARDS HEAVY COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F840,
+ },
+ [0x1F841]={
+ category="so",
+ description="UPWARDS HEAVY COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F841,
+ },
+ [0x1F842]={
+ category="so",
+ description="RIGHTWARDS HEAVY COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F842,
+ },
+ [0x1F843]={
+ category="so",
+ description="DOWNWARDS HEAVY COMPRESSED ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F843,
+ },
+ [0x1F844]={
+ category="so",
+ description="LEFTWARDS HEAVY ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F844,
+ },
+ [0x1F845]={
+ category="so",
+ description="UPWARDS HEAVY ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F845,
+ },
+ [0x1F846]={
+ category="so",
+ description="RIGHTWARDS HEAVY ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F846,
+ },
+ [0x1F847]={
+ category="so",
+ description="DOWNWARDS HEAVY ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F847,
+ },
+ [0x1F850]={
+ category="so",
+ description="LEFTWARDS SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F850,
+ },
+ [0x1F851]={
+ category="so",
+ description="UPWARDS SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F851,
+ },
+ [0x1F852]={
+ category="so",
+ description="RIGHTWARDS SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F852,
+ },
+ [0x1F853]={
+ category="so",
+ description="DOWNWARDS SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F853,
+ },
+ [0x1F854]={
+ category="so",
+ description="NORTH WEST SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F854,
+ },
+ [0x1F855]={
+ category="so",
+ description="NORTH EAST SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F855,
+ },
+ [0x1F856]={
+ category="so",
+ description="SOUTH EAST SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F856,
+ },
+ [0x1F857]={
+ category="so",
+ description="SOUTH WEST SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F857,
+ },
+ [0x1F858]={
+ category="so",
+ description="LEFT RIGHT SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F858,
+ },
+ [0x1F859]={
+ category="so",
+ description="UP DOWN SANS-SERIF ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F859,
+ },
+ [0x1F860]={
+ category="so",
+ description="WIDE-HEADED LEFTWARDS LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F860,
+ },
+ [0x1F861]={
+ category="so",
+ description="WIDE-HEADED UPWARDS LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F861,
+ },
+ [0x1F862]={
+ category="so",
+ description="WIDE-HEADED RIGHTWARDS LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F862,
+ },
+ [0x1F863]={
+ category="so",
+ description="WIDE-HEADED DOWNWARDS LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F863,
+ },
+ [0x1F864]={
+ category="so",
+ description="WIDE-HEADED NORTH WEST LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F864,
+ },
+ [0x1F865]={
+ category="so",
+ description="WIDE-HEADED NORTH EAST LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F865,
+ },
+ [0x1F866]={
+ category="so",
+ description="WIDE-HEADED SOUTH EAST LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F866,
+ },
+ [0x1F867]={
+ category="so",
+ description="WIDE-HEADED SOUTH WEST LIGHT BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F867,
+ },
+ [0x1F868]={
+ category="so",
+ description="WIDE-HEADED LEFTWARDS BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F868,
+ },
+ [0x1F869]={
+ category="so",
+ description="WIDE-HEADED UPWARDS BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F869,
+ },
+ [0x1F86A]={
+ category="so",
+ description="WIDE-HEADED RIGHTWARDS BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86A,
+ },
+ [0x1F86B]={
+ category="so",
+ description="WIDE-HEADED DOWNWARDS BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86B,
+ },
+ [0x1F86C]={
+ category="so",
+ description="WIDE-HEADED NORTH WEST BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86C,
+ },
+ [0x1F86D]={
+ category="so",
+ description="WIDE-HEADED NORTH EAST BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86D,
+ },
+ [0x1F86E]={
+ category="so",
+ description="WIDE-HEADED SOUTH EAST BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86E,
+ },
+ [0x1F86F]={
+ category="so",
+ description="WIDE-HEADED SOUTH WEST BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F86F,
+ },
+ [0x1F870]={
+ category="so",
+ description="WIDE-HEADED LEFTWARDS MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F870,
+ },
+ [0x1F871]={
+ category="so",
+ description="WIDE-HEADED UPWARDS MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F871,
+ },
+ [0x1F872]={
+ category="so",
+ description="WIDE-HEADED RIGHTWARDS MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F872,
+ },
+ [0x1F873]={
+ category="so",
+ description="WIDE-HEADED DOWNWARDS MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F873,
+ },
+ [0x1F874]={
+ category="so",
+ description="WIDE-HEADED NORTH WEST MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F874,
+ },
+ [0x1F875]={
+ category="so",
+ description="WIDE-HEADED NORTH EAST MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F875,
+ },
+ [0x1F876]={
+ category="so",
+ description="WIDE-HEADED SOUTH EAST MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F876,
+ },
+ [0x1F877]={
+ category="so",
+ description="WIDE-HEADED SOUTH WEST MEDIUM BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F877,
+ },
+ [0x1F878]={
+ category="so",
+ description="WIDE-HEADED LEFTWARDS HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F878,
+ },
+ [0x1F879]={
+ category="so",
+ description="WIDE-HEADED UPWARDS HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F879,
+ },
+ [0x1F87A]={
+ category="so",
+ description="WIDE-HEADED RIGHTWARDS HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87A,
+ },
+ [0x1F87B]={
+ category="so",
+ description="WIDE-HEADED DOWNWARDS HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87B,
+ },
+ [0x1F87C]={
+ category="so",
+ description="WIDE-HEADED NORTH WEST HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87C,
+ },
+ [0x1F87D]={
+ category="so",
+ description="WIDE-HEADED NORTH EAST HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87D,
+ },
+ [0x1F87E]={
+ category="so",
+ description="WIDE-HEADED SOUTH EAST HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87E,
+ },
+ [0x1F87F]={
+ category="so",
+ description="WIDE-HEADED SOUTH WEST HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F87F,
+ },
+ [0x1F880]={
+ category="so",
+ description="WIDE-HEADED LEFTWARDS VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F880,
+ },
+ [0x1F881]={
+ category="so",
+ description="WIDE-HEADED UPWARDS VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F881,
+ },
+ [0x1F882]={
+ category="so",
+ description="WIDE-HEADED RIGHTWARDS VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F882,
+ },
+ [0x1F883]={
+ category="so",
+ description="WIDE-HEADED DOWNWARDS VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F883,
+ },
+ [0x1F884]={
+ category="so",
+ description="WIDE-HEADED NORTH WEST VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F884,
+ },
+ [0x1F885]={
+ category="so",
+ description="WIDE-HEADED NORTH EAST VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F885,
+ },
+ [0x1F886]={
+ category="so",
+ description="WIDE-HEADED SOUTH EAST VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F886,
+ },
+ [0x1F887]={
+ category="so",
+ description="WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F887,
+ },
+ [0x1F890]={
+ category="so",
+ description="LEFTWARDS TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F890,
+ },
+ [0x1F891]={
+ category="so",
+ description="UPWARDS TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F891,
+ },
+ [0x1F892]={
+ category="so",
+ description="RIGHTWARDS TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F892,
+ },
+ [0x1F893]={
+ category="so",
+ description="DOWNWARDS TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F893,
+ },
+ [0x1F894]={
+ category="so",
+ description="LEFTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F894,
+ },
+ [0x1F895]={
+ category="so",
+ description="UPWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F895,
+ },
+ [0x1F896]={
+ category="so",
+ description="RIGHTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F896,
+ },
+ [0x1F897]={
+ category="so",
+ description="DOWNWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F897,
+ },
+ [0x1F898]={
+ category="so",
+ description="LEFTWARDS ARROW WITH NOTCHED TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F898,
+ },
+ [0x1F899]={
+ category="so",
+ description="UPWARDS ARROW WITH NOTCHED TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F899,
+ },
+ [0x1F89A]={
+ category="so",
+ description="RIGHTWARDS ARROW WITH NOTCHED TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89A,
+ },
+ [0x1F89B]={
+ category="so",
+ description="DOWNWARDS ARROW WITH NOTCHED TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89B,
+ },
+ [0x1F89C]={
+ category="so",
+ description="HEAVY ARROW SHAFT WIDTH ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89C,
+ },
+ [0x1F89D]={
+ category="so",
+ description="HEAVY ARROW SHAFT WIDTH TWO THIRDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89D,
+ },
+ [0x1F89E]={
+ category="so",
+ description="HEAVY ARROW SHAFT WIDTH ONE HALF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89E,
+ },
+ [0x1F89F]={
+ category="so",
+ description="HEAVY ARROW SHAFT WIDTH ONE THIRD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F89F,
+ },
+ [0x1F8A0]={
+ category="so",
+ description="LEFTWARDS BOTTOM-SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A0,
+ },
+ [0x1F8A1]={
+ category="so",
+ description="RIGHTWARDS BOTTOM SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A1,
+ },
+ [0x1F8A2]={
+ category="so",
+ description="LEFTWARDS TOP SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A2,
+ },
+ [0x1F8A3]={
+ category="so",
+ description="RIGHTWARDS TOP SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A3,
+ },
+ [0x1F8A4]={
+ category="so",
+ description="LEFTWARDS LEFT-SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A4,
+ },
+ [0x1F8A5]={
+ category="so",
+ description="RIGHTWARDS RIGHT-SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A5,
+ },
+ [0x1F8A6]={
+ category="so",
+ description="LEFTWARDS RIGHT-SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A6,
+ },
+ [0x1F8A7]={
+ category="so",
+ description="RIGHTWARDS LEFT-SHADED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A7,
+ },
+ [0x1F8A8]={
+ category="so",
+ description="LEFTWARDS BACK-TILTED SHADOWED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A8,
+ },
+ [0x1F8A9]={
+ category="so",
+ description="RIGHTWARDS BACK-TILTED SHADOWED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8A9,
+ },
+ [0x1F8AA]={
+ category="so",
+ description="LEFTWARDS FRONT-TILTED SHADOWED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8AA,
+ },
+ [0x1F8AB]={
+ category="so",
+ description="RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8AB,
+ },
+ [0x1F8AC]={
+ category="so",
+ description="WHITE ARROW SHAFT WIDTH ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8AC,
+ },
+ [0x1F8AD]={
+ category="so",
+ description="WHITE ARROW SHAFT WIDTH TWO THIRDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F8AD,
+ },
+ [0x1F910]={
+ category="so",
+ description="ZIPPER-MOUTH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F910,
+ },
+ [0x1F911]={
+ category="so",
+ description="MONEY-MOUTH FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F911,
+ },
+ [0x1F912]={
+ category="so",
+ description="FACE WITH THERMOMETER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F912,
+ },
+ [0x1F913]={
+ category="so",
+ description="NERD FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F913,
+ },
+ [0x1F914]={
+ category="so",
+ description="THINKING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F914,
+ },
+ [0x1F915]={
+ category="so",
+ description="FACE WITH HEAD-BANDAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F915,
+ },
+ [0x1F916]={
+ category="so",
+ description="ROBOT FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F916,
+ },
+ [0x1F917]={
+ category="so",
+ description="HUGGING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F917,
+ },
+ [0x1F918]={
+ category="so",
+ description="SIGN OF THE HORNS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F918,
+ },
+ [0x1F980]={
+ category="so",
+ description="CRAB",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F980,
+ },
+ [0x1F981]={
+ category="so",
+ description="LION FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F981,
+ },
+ [0x1F982]={
+ category="so",
+ description="SCORPION",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F982,
+ },
+ [0x1F983]={
+ category="so",
+ description="TURKEY",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F983,
+ },
+ [0x1F984]={
+ category="so",
+ description="UNICORN FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F984,
+ },
+ [0x1F9C0]={
+ category="so",
+ description="CHEESE WEDGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9C0,
+ },
+ [0x2F800]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0320",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E3D },
+ unicodeslot=0x2F800,
+ },
+ [0x2F801]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0321",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E38 },
+ unicodeslot=0x2F801,
+ },
+ [0x2F802]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0322",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4E41 },
+ unicodeslot=0x2F802,
+ },
+ [0x2F803]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0323",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x20122 },
+ unicodeslot=0x2F803,
+ },
+ [0x2F804]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0324",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4F60 },
+ unicodeslot=0x2F804,
+ },
+ [0x2F805]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0325",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4FAE },
+ unicodeslot=0x2F805,
+ },
+ [0x2F806]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0326",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4FBB },
+ unicodeslot=0x2F806,
+ },
+ [0x2F807]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0327",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5002 },
+ unicodeslot=0x2F807,
+ },
+ [0x2F808]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0328",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x507A },
+ unicodeslot=0x2F808,
+ },
+ [0x2F809]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0329",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5099 },
+ unicodeslot=0x2F809,
+ },
+ [0x2F80A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x50E7 },
+ unicodeslot=0x2F80A,
+ },
+ [0x2F80B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x50CF },
+ unicodeslot=0x2F80B,
+ },
+ [0x2F80C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x349E },
+ unicodeslot=0x2F80C,
+ },
+ [0x2F80D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2063A },
+ unicodeslot=0x2F80D,
+ },
+ [0x2F80E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x514D },
+ unicodeslot=0x2F80E,
+ },
+ [0x2F80F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0050F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5154 },
+ unicodeslot=0x2F80F,
+ },
+ [0x2F810]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5164 },
+ unicodeslot=0x2F810,
+ },
+ [0x2F811]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5177 },
+ unicodeslot=0x2F811,
+ },
+ [0x2F812]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2051C },
+ unicodeslot=0x2F812,
+ },
+ [0x2F813]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x34B9 },
+ unicodeslot=0x2F813,
+ },
+ [0x2F814]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5167 },
+ unicodeslot=0x2F814,
+ },
+ [0x2F815]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x032F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x518D },
+ unicodeslot=0x2F815,
+ },
+ [0x2F816]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0330",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2054B },
+ unicodeslot=0x2F816,
+ },
+ [0x2F817]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0331",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5197 },
+ unicodeslot=0x2F817,
+ },
+ [0x2F818]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0332",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51A4 },
+ unicodeslot=0x2F818,
+ },
+ [0x2F819]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0333",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4ECC },
+ unicodeslot=0x2F819,
+ },
+ [0x2F81A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51AC },
+ unicodeslot=0x2F81A,
+ },
+ [0x2F81B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51B5 },
+ unicodeslot=0x2F81B,
+ },
+ [0x2F81C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x291DF },
+ unicodeslot=0x2F81C,
+ },
+ [0x2F81D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x51F5 },
+ unicodeslot=0x2F81D,
+ },
+ [0x2F81E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5203 },
+ unicodeslot=0x2F81E,
+ },
+ [0x2F81F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0051F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x34DF },
+ unicodeslot=0x2F81F,
+ },
+ [0x2F820]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0334",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x523B },
+ unicodeslot=0x2F820,
+ },
+ [0x2F821]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0335",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5246 },
+ unicodeslot=0x2F821,
+ },
+ [0x2F822]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0336",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5272 },
+ unicodeslot=0x2F822,
+ },
+ [0x2F823]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0337",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5277 },
+ unicodeslot=0x2F823,
+ },
+ [0x2F824]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0338",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3515 },
+ unicodeslot=0x2F824,
+ },
+ [0x2F825]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0339",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52C7 },
+ unicodeslot=0x2F825,
+ },
+ [0x2F826]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52C9 },
+ unicodeslot=0x2F826,
+ },
+ [0x2F827]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52E4 },
+ unicodeslot=0x2F827,
+ },
+ [0x2F828]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52FA },
+ unicodeslot=0x2F828,
+ },
+ [0x2F829]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5305 },
+ unicodeslot=0x2F829,
+ },
+ [0x2F82A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5306 },
+ unicodeslot=0x2F82A,
+ },
+ [0x2F82B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5317 },
+ unicodeslot=0x2F82B,
+ },
+ [0x2F82C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5349 },
+ unicodeslot=0x2F82C,
+ },
+ [0x2F82D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5351 },
+ unicodeslot=0x2F82D,
+ },
+ [0x2F82E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x535A },
+ unicodeslot=0x2F82E,
+ },
+ [0x2F82F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0052F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5373 },
+ unicodeslot=0x2F82F,
+ },
+ [0x2F830]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x537D },
+ unicodeslot=0x2F830,
+ },
+ [0x2F831]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x033F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x537F },
+ unicodeslot=0x2F831,
+ },
+ [0x2F832]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0340",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x537F },
+ unicodeslot=0x2F832,
+ },
+ [0x2F833]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0341",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x537F },
+ unicodeslot=0x2F833,
+ },
+ [0x2F834]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0342",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x20A2C },
+ unicodeslot=0x2F834,
+ },
+ [0x2F835]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0343",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7070 },
+ unicodeslot=0x2F835,
+ },
+ [0x2F836]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0344",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53CA },
+ unicodeslot=0x2F836,
+ },
+ [0x2F837]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0345",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53DF },
+ unicodeslot=0x2F837,
+ },
+ [0x2F838]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0346",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x20B63 },
+ unicodeslot=0x2F838,
+ },
+ [0x2F839]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0347",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53EB },
+ unicodeslot=0x2F839,
+ },
+ [0x2F83A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x53F1 },
+ unicodeslot=0x2F83A,
+ },
+ [0x2F83B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5406 },
+ unicodeslot=0x2F83B,
+ },
+ [0x2F83C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x549E },
+ unicodeslot=0x2F83C,
+ },
+ [0x2F83D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5438 },
+ unicodeslot=0x2F83D,
+ },
+ [0x2F83E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5448 },
+ unicodeslot=0x2F83E,
+ },
+ [0x2F83F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0053F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5468 },
+ unicodeslot=0x2F83F,
+ },
+ [0x2F840]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0348",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x54A2 },
+ unicodeslot=0x2F840,
+ },
+ [0x2F841]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0349",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x54F6 },
+ unicodeslot=0x2F841,
+ },
+ [0x2F842]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5510 },
+ unicodeslot=0x2F842,
+ },
+ [0x2F843]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5553 },
+ unicodeslot=0x2F843,
+ },
+ [0x2F844]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5563 },
+ unicodeslot=0x2F844,
+ },
+ [0x2F845]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5584 },
+ unicodeslot=0x2F845,
+ },
+ [0x2F846]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5584 },
+ unicodeslot=0x2F846,
+ },
+ [0x2F847]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x034F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5599 },
+ unicodeslot=0x2F847,
+ },
+ [0x2F848]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0350",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x55AB },
+ unicodeslot=0x2F848,
+ },
+ [0x2F849]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0351",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x55B3 },
+ unicodeslot=0x2F849,
+ },
+ [0x2F84A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x55C2 },
+ unicodeslot=0x2F84A,
+ },
+ [0x2F84B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5716 },
+ unicodeslot=0x2F84B,
+ },
+ [0x2F84C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5606 },
+ unicodeslot=0x2F84C,
+ },
+ [0x2F84D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5717 },
+ unicodeslot=0x2F84D,
+ },
+ [0x2F84E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5651 },
+ unicodeslot=0x2F84E,
+ },
+ [0x2F84F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0054F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5674 },
+ unicodeslot=0x2F84F,
+ },
+ [0x2F850]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0352",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5207 },
+ unicodeslot=0x2F850,
+ },
+ [0x2F851]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0353",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58EE },
+ unicodeslot=0x2F851,
+ },
+ [0x2F852]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0354",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x57CE },
+ unicodeslot=0x2F852,
+ },
+ [0x2F853]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0355",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x57F4 },
+ unicodeslot=0x2F853,
+ },
+ [0x2F854]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0356",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x580D },
+ unicodeslot=0x2F854,
+ },
+ [0x2F855]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0357",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x578B },
+ unicodeslot=0x2F855,
+ },
+ [0x2F856]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0358",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5832 },
+ unicodeslot=0x2F856,
+ },
+ [0x2F857]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0359",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5831 },
+ unicodeslot=0x2F857,
+ },
+ [0x2F858]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58AC },
+ unicodeslot=0x2F858,
+ },
+ [0x2F859]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x214E4 },
+ unicodeslot=0x2F859,
+ },
+ [0x2F85A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58F2 },
+ unicodeslot=0x2F85A,
+ },
+ [0x2F85B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x58F7 },
+ unicodeslot=0x2F85B,
+ },
+ [0x2F85C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5906 },
+ unicodeslot=0x2F85C,
+ },
+ [0x2F85D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x591A },
+ unicodeslot=0x2F85D,
+ },
+ [0x2F85E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5922 },
+ unicodeslot=0x2F85E,
+ },
+ [0x2F85F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0055F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5962 },
+ unicodeslot=0x2F85F,
+ },
+ [0x2F860]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x216A8 },
+ unicodeslot=0x2F860,
+ },
+ [0x2F861]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x216EA },
+ unicodeslot=0x2F861,
+ },
+ [0x2F862]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x59EC },
+ unicodeslot=0x2F862,
+ },
+ [0x2F863]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x035F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5A1B },
+ unicodeslot=0x2F863,
+ },
+ [0x2F864]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0360",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5A27 },
+ unicodeslot=0x2F864,
+ },
+ [0x2F865]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0361",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x59D8 },
+ unicodeslot=0x2F865,
+ },
+ [0x2F866]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0362",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5A66 },
+ unicodeslot=0x2F866,
+ },
+ [0x2F867]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0363",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x36EE },
+ unicodeslot=0x2F867,
+ },
+ [0x2F868]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0364",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x36FC },
+ unicodeslot=0x2F868,
+ },
+ [0x2F869]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0365",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5B08 },
+ unicodeslot=0x2F869,
+ },
+ [0x2F86A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5B3E },
+ unicodeslot=0x2F86A,
+ },
+ [0x2F86B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5B3E },
+ unicodeslot=0x2F86B,
+ },
+ [0x2F86C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x219C8 },
+ unicodeslot=0x2F86C,
+ },
+ [0x2F86D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BC3 },
+ unicodeslot=0x2F86D,
+ },
+ [0x2F86E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BD8 },
+ unicodeslot=0x2F86E,
+ },
+ [0x2F86F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0056F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BE7 },
+ unicodeslot=0x2F86F,
+ },
+ [0x2F870]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0366",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BF3 },
+ unicodeslot=0x2F870,
+ },
+ [0x2F871]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0367",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x21B18 },
+ unicodeslot=0x2F871,
+ },
+ [0x2F872]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0368",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5BFF },
+ unicodeslot=0x2F872,
+ },
+ [0x2F873]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0369",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C06 },
+ unicodeslot=0x2F873,
+ },
+ [0x2F874]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F53 },
+ unicodeslot=0x2F874,
+ },
+ [0x2F875]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C22 },
+ unicodeslot=0x2F875,
+ },
+ [0x2F876]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3781 },
+ unicodeslot=0x2F876,
+ },
+ [0x2F877]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C60 },
+ unicodeslot=0x2F877,
+ },
+ [0x2F878]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C6E },
+ unicodeslot=0x2F878,
+ },
+ [0x2F879]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x036F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5CC0 },
+ unicodeslot=0x2F879,
+ },
+ [0x2F87A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5C8D },
+ unicodeslot=0x2F87A,
+ },
+ [0x2F87B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x21DE4 },
+ unicodeslot=0x2F87B,
+ },
+ [0x2F87C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D43 },
+ unicodeslot=0x2F87C,
+ },
+ [0x2F87D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x21DE6 },
+ unicodeslot=0x2F87D,
+ },
+ [0x2F87E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D6E },
+ unicodeslot=0x2F87E,
+ },
+ [0x2F87F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0057F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D6B },
+ unicodeslot=0x2F87F,
+ },
+ [0x2F880]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0370",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5D7C },
+ unicodeslot=0x2F880,
+ },
+ [0x2F881]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0371",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5DE1 },
+ unicodeslot=0x2F881,
+ },
+ [0x2F882]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0372",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5DE2 },
+ unicodeslot=0x2F882,
+ },
+ [0x2F883]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0373",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x382F },
+ unicodeslot=0x2F883,
+ },
+ [0x2F884]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0374",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5DFD },
+ unicodeslot=0x2F884,
+ },
+ [0x2F885]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0375",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5E28 },
+ unicodeslot=0x2F885,
+ },
+ [0x2F886]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0376",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5E3D },
+ unicodeslot=0x2F886,
+ },
+ [0x2F887]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0377",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5E69 },
+ unicodeslot=0x2F887,
+ },
+ [0x2F888]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0378",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3862 },
+ unicodeslot=0x2F888,
+ },
+ [0x2F889]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0379",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22183 },
+ unicodeslot=0x2F889,
+ },
+ [0x2F88A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x387C },
+ unicodeslot=0x2F88A,
+ },
+ [0x2F88B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EB0 },
+ unicodeslot=0x2F88B,
+ },
+ [0x2F88C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EB3 },
+ unicodeslot=0x2F88C,
+ },
+ [0x2F88D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EB6 },
+ unicodeslot=0x2F88D,
+ },
+ [0x2F88E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5ECA },
+ unicodeslot=0x2F88E,
+ },
+ [0x2F88F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0058F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A392 },
+ unicodeslot=0x2F88F,
+ },
+ [0x2F890]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5EFE },
+ unicodeslot=0x2F890,
+ },
+ [0x2F891]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22331 },
+ unicodeslot=0x2F891,
+ },
+ [0x2F892]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22331 },
+ unicodeslot=0x2F892,
+ },
+ [0x2F893]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8201 },
+ unicodeslot=0x2F893,
+ },
+ [0x2F894]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F22 },
+ unicodeslot=0x2F894,
+ },
+ [0x2F895]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x037F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F22 },
+ unicodeslot=0x2F895,
+ },
+ [0x2F896]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0380",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x38C7 },
+ unicodeslot=0x2F896,
+ },
+ [0x2F897]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0381",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x232B8 },
+ unicodeslot=0x2F897,
+ },
+ [0x2F898]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0382",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x261DA },
+ unicodeslot=0x2F898,
+ },
+ [0x2F899]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0383",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F62 },
+ unicodeslot=0x2F899,
+ },
+ [0x2F89A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F6B },
+ unicodeslot=0x2F89A,
+ },
+ [0x2F89B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x38E3 },
+ unicodeslot=0x2F89B,
+ },
+ [0x2F89C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5F9A },
+ unicodeslot=0x2F89C,
+ },
+ [0x2F89D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FCD },
+ unicodeslot=0x2F89D,
+ },
+ [0x2F89E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FD7 },
+ unicodeslot=0x2F89E,
+ },
+ [0x2F89F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0059F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5FF9 },
+ unicodeslot=0x2F89F,
+ },
+ [0x2F8A0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6081 },
+ unicodeslot=0x2F8A0,
+ },
+ [0x2F8A1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x393A },
+ unicodeslot=0x2F8A1,
+ },
+ [0x2F8A2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x391C },
+ unicodeslot=0x2F8A2,
+ },
+ [0x2F8A3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6094 },
+ unicodeslot=0x2F8A3,
+ },
+ [0x2F8A4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x226D4 },
+ unicodeslot=0x2F8A4,
+ },
+ [0x2F8A5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x60C7 },
+ unicodeslot=0x2F8A5,
+ },
+ [0x2F8A6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6148 },
+ unicodeslot=0x2F8A6,
+ },
+ [0x2F8A7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x614C },
+ unicodeslot=0x2F8A7,
+ },
+ [0x2F8A8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x614E },
+ unicodeslot=0x2F8A8,
+ },
+ [0x2F8A9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008A0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x614C },
+ unicodeslot=0x2F8A9,
+ },
+ [0x2F8AA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x617A },
+ unicodeslot=0x2F8AA,
+ },
+ [0x2F8AB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x618E },
+ unicodeslot=0x2F8AB,
+ },
+ [0x2F8AC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61B2 },
+ unicodeslot=0x2F8AC,
+ },
+ [0x2F8AD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61A4 },
+ unicodeslot=0x2F8AD,
+ },
+ [0x2F8AE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61AF },
+ unicodeslot=0x2F8AE,
+ },
+ [0x2F8AF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61DE },
+ unicodeslot=0x2F8AF,
+ },
+ [0x2F8B0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61F2 },
+ unicodeslot=0x2F8B0,
+ },
+ [0x2F8B1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x61F6 },
+ unicodeslot=0x2F8B1,
+ },
+ [0x2F8B2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6210 },
+ unicodeslot=0x2F8B2,
+ },
+ [0x2F8B3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x621B },
+ unicodeslot=0x2F8B3,
+ },
+ [0x2F8B4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x625D },
+ unicodeslot=0x2F8B4,
+ },
+ [0x2F8B5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62B1 },
+ unicodeslot=0x2F8B5,
+ },
+ [0x2F8B6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62D4 },
+ unicodeslot=0x2F8B6,
+ },
+ [0x2F8B7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6350 },
+ unicodeslot=0x2F8B7,
+ },
+ [0x2F8B8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22B0C },
+ unicodeslot=0x2F8B8,
+ },
+ [0x2F8B9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008B0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x633D },
+ unicodeslot=0x2F8B9,
+ },
+ [0x2F8BA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x62FC },
+ unicodeslot=0x2F8BA,
+ },
+ [0x2F8BB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6368 },
+ unicodeslot=0x2F8BB,
+ },
+ [0x2F8BC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6383 },
+ unicodeslot=0x2F8BC,
+ },
+ [0x2F8BD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x63E4 },
+ unicodeslot=0x2F8BD,
+ },
+ [0x2F8BE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x22BF1 },
+ unicodeslot=0x2F8BE,
+ },
+ [0x2F8BF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6422 },
+ unicodeslot=0x2F8BF,
+ },
+ [0x2F8C0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x63C5 },
+ unicodeslot=0x2F8C0,
+ },
+ [0x2F8C1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x63A9 },
+ unicodeslot=0x2F8C1,
+ },
+ [0x2F8C2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3A2E },
+ unicodeslot=0x2F8C2,
+ },
+ [0x2F8C3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6469 },
+ unicodeslot=0x2F8C3,
+ },
+ [0x2F8C4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x647E },
+ unicodeslot=0x2F8C4,
+ },
+ [0x2F8C5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x649D },
+ unicodeslot=0x2F8C5,
+ },
+ [0x2F8C6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6477 },
+ unicodeslot=0x2F8C6,
+ },
+ [0x2F8C7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3A6C },
+ unicodeslot=0x2F8C7,
+ },
+ [0x2F8C8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x654F },
+ unicodeslot=0x2F8C8,
+ },
+ [0x2F8C9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008C0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x656C },
+ unicodeslot=0x2F8C9,
+ },
+ [0x2F8CA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2300A },
+ unicodeslot=0x2F8CA,
+ },
+ [0x2F8CB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x65E3 },
+ unicodeslot=0x2F8CB,
+ },
+ [0x2F8CC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x66F8 },
+ unicodeslot=0x2F8CC,
+ },
+ [0x2F8CD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6649 },
+ unicodeslot=0x2F8CD,
+ },
+ [0x2F8CE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3B19 },
+ unicodeslot=0x2F8CE,
+ },
+ [0x2F8CF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6691 },
+ unicodeslot=0x2F8CF,
+ },
+ [0x2F8D0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3B08 },
+ unicodeslot=0x2F8D0,
+ },
+ [0x2F8D1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3AE4 },
+ unicodeslot=0x2F8D1,
+ },
+ [0x2F8D2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5192 },
+ unicodeslot=0x2F8D2,
+ },
+ [0x2F8D3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5195 },
+ unicodeslot=0x2F8D3,
+ },
+ [0x2F8D4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6700 },
+ unicodeslot=0x2F8D4,
+ },
+ [0x2F8D5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x669C },
+ unicodeslot=0x2F8D5,
+ },
+ [0x2F8D6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x80AD },
+ unicodeslot=0x2F8D6,
+ },
+ [0x2F8D7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x43D9 },
+ unicodeslot=0x2F8D7,
+ },
+ [0x2F8D8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6717 },
+ unicodeslot=0x2F8D8,
+ },
+ [0x2F8D9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008D0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x671B },
+ unicodeslot=0x2F8D9,
+ },
+ [0x2F8DA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6721 },
+ unicodeslot=0x2F8DA,
+ },
+ [0x2F8DB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x675E },
+ unicodeslot=0x2F8DB,
+ },
+ [0x2F8DC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6753 },
+ unicodeslot=0x2F8DC,
+ },
+ [0x2F8DD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x233C3 },
+ unicodeslot=0x2F8DD,
+ },
+ [0x2F8DE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3B49 },
+ unicodeslot=0x2F8DE,
+ },
+ [0x2F8DF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x67FA },
+ unicodeslot=0x2F8DF,
+ },
+ [0x2F8E0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6785 },
+ unicodeslot=0x2F8E0,
+ },
+ [0x2F8E1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6852 },
+ unicodeslot=0x2F8E1,
+ },
+ [0x2F8E2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6885 },
+ unicodeslot=0x2F8E2,
+ },
+ [0x2F8E3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2346D },
+ unicodeslot=0x2F8E3,
+ },
+ [0x2F8E4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x688E },
+ unicodeslot=0x2F8E4,
+ },
+ [0x2F8E5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x681F },
+ unicodeslot=0x2F8E5,
+ },
+ [0x2F8E6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6914 },
+ unicodeslot=0x2F8E6,
+ },
+ [0x2F8E7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3B9D },
+ unicodeslot=0x2F8E7,
+ },
+ [0x2F8E8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6942 },
+ unicodeslot=0x2F8E8,
+ },
+ [0x2F8E9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008E0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x69A3 },
+ unicodeslot=0x2F8E9,
+ },
+ [0x2F8EA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008EA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x69EA },
+ unicodeslot=0x2F8EA,
+ },
+ [0x2F8EB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008EB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6AA8 },
+ unicodeslot=0x2F8EB,
+ },
+ [0x2F8EC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008EC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x236A3 },
+ unicodeslot=0x2F8EC,
+ },
+ [0x2F8ED]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008ED",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6ADB },
+ unicodeslot=0x2F8ED,
+ },
+ [0x2F8EE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008EE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3C18 },
+ unicodeslot=0x2F8EE,
+ },
+ [0x2F8EF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008EF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B21 },
+ unicodeslot=0x2F8EF,
+ },
+ [0x2F8F0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x238A7 },
+ unicodeslot=0x2F8F0,
+ },
+ [0x2F8F1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B54 },
+ unicodeslot=0x2F8F1,
+ },
+ [0x2F8F2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3C4E },
+ unicodeslot=0x2F8F2,
+ },
+ [0x2F8F3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B72 },
+ unicodeslot=0x2F8F3,
+ },
+ [0x2F8F4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6B9F },
+ unicodeslot=0x2F8F4,
+ },
+ [0x2F8F5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6BBA },
+ unicodeslot=0x2F8F5,
+ },
+ [0x2F8F6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6BBB },
+ unicodeslot=0x2F8F6,
+ },
+ [0x2F8F7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23A8D },
+ unicodeslot=0x2F8F7,
+ },
+ [0x2F8F8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x21D0B },
+ unicodeslot=0x2F8F8,
+ },
+ [0x2F8F9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008F0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23AFA },
+ unicodeslot=0x2F8F9,
+ },
+ [0x2F8FA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6C4E },
+ unicodeslot=0x2F8FA,
+ },
+ [0x2F8FB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23CBC },
+ unicodeslot=0x2F8FB,
+ },
+ [0x2F8FC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6CBF },
+ unicodeslot=0x2F8FC,
+ },
+ [0x2F8FD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6CCD },
+ unicodeslot=0x2F8FD,
+ },
+ [0x2F8FE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6C67 },
+ unicodeslot=0x2F8FE,
+ },
+ [0x2F8FF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0008FF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D16 },
+ unicodeslot=0x2F8FF,
+ },
+ [0x2F900]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0384",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D3E },
+ unicodeslot=0x2F900,
+ },
+ [0x2F901]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0385",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D77 },
+ unicodeslot=0x2F901,
+ },
+ [0x2F902]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0386",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D41 },
+ unicodeslot=0x2F902,
+ },
+ [0x2F903]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0387",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D69 },
+ unicodeslot=0x2F903,
+ },
+ [0x2F904]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0388",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D78 },
+ unicodeslot=0x2F904,
+ },
+ [0x2F905]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0389",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D85 },
+ unicodeslot=0x2F905,
+ },
+ [0x2F906]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23D1E },
+ unicodeslot=0x2F906,
+ },
+ [0x2F907]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6D34 },
+ unicodeslot=0x2F907,
+ },
+ [0x2F908]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6E2F },
+ unicodeslot=0x2F908,
+ },
+ [0x2F909]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6E6E },
+ unicodeslot=0x2F909,
+ },
+ [0x2F90A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3D33 },
+ unicodeslot=0x2F90A,
+ },
+ [0x2F90B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6ECB },
+ unicodeslot=0x2F90B,
+ },
+ [0x2F90C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6EC7 },
+ unicodeslot=0x2F90C,
+ },
+ [0x2F90D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23ED1 },
+ unicodeslot=0x2F90D,
+ },
+ [0x2F90E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6DF9 },
+ unicodeslot=0x2F90E,
+ },
+ [0x2F90F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6F6E },
+ unicodeslot=0x2F90F,
+ },
+ [0x2F910]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23F5E },
+ unicodeslot=0x2F910,
+ },
+ [0x2F911]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x038F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23F8E },
+ unicodeslot=0x2F911,
+ },
+ [0x2F912]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0390",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6FC6 },
+ unicodeslot=0x2F912,
+ },
+ [0x2F913]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0391",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7039 },
+ unicodeslot=0x2F913,
+ },
+ [0x2F914]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0392",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x701E },
+ unicodeslot=0x2F914,
+ },
+ [0x2F915]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0393",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x701B },
+ unicodeslot=0x2F915,
+ },
+ [0x2F916]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0394",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3D96 },
+ unicodeslot=0x2F916,
+ },
+ [0x2F917]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0395",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x704A },
+ unicodeslot=0x2F917,
+ },
+ [0x2F918]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0396",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x707D },
+ unicodeslot=0x2F918,
+ },
+ [0x2F919]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0397",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7077 },
+ unicodeslot=0x2F919,
+ },
+ [0x2F91A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x70AD },
+ unicodeslot=0x2F91A,
+ },
+ [0x2F91B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x20525 },
+ unicodeslot=0x2F91B,
+ },
+ [0x2F91C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7145 },
+ unicodeslot=0x2F91C,
+ },
+ [0x2F91D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24263 },
+ unicodeslot=0x2F91D,
+ },
+ [0x2F91E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x719C },
+ unicodeslot=0x2F91E,
+ },
+ [0x2F91F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x243AB },
+ unicodeslot=0x2F91F,
+ },
+ [0x2F920]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0398",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7228 },
+ unicodeslot=0x2F920,
+ },
+ [0x2F921]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0399",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7235 },
+ unicodeslot=0x2F921,
+ },
+ [0x2F922]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7250 },
+ unicodeslot=0x2F922,
+ },
+ [0x2F923]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24608 },
+ unicodeslot=0x2F923,
+ },
+ [0x2F924]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7280 },
+ unicodeslot=0x2F924,
+ },
+ [0x2F925]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7295 },
+ unicodeslot=0x2F925,
+ },
+ [0x2F926]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24735 },
+ unicodeslot=0x2F926,
+ },
+ [0x2F927]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x039F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24814 },
+ unicodeslot=0x2F927,
+ },
+ [0x2F928]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x737A },
+ unicodeslot=0x2F928,
+ },
+ [0x2F929]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x738B },
+ unicodeslot=0x2F929,
+ },
+ [0x2F92A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3EAC },
+ unicodeslot=0x2F92A,
+ },
+ [0x2F92B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x73A5 },
+ unicodeslot=0x2F92B,
+ },
+ [0x2F92C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3EB8 },
+ unicodeslot=0x2F92C,
+ },
+ [0x2F92D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3EB8 },
+ unicodeslot=0x2F92D,
+ },
+ [0x2F92E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7447 },
+ unicodeslot=0x2F92E,
+ },
+ [0x2F92F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x745C },
+ unicodeslot=0x2F92F,
+ },
+ [0x2F930]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7471 },
+ unicodeslot=0x2F930,
+ },
+ [0x2F931]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7485 },
+ unicodeslot=0x2F931,
+ },
+ [0x2F932]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x74CA },
+ unicodeslot=0x2F932,
+ },
+ [0x2F933]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3F1B },
+ unicodeslot=0x2F933,
+ },
+ [0x2F934]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7524 },
+ unicodeslot=0x2F934,
+ },
+ [0x2F935]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24C36 },
+ unicodeslot=0x2F935,
+ },
+ [0x2F936]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x753E },
+ unicodeslot=0x2F936,
+ },
+ [0x2F937]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03A9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24C92 },
+ unicodeslot=0x2F937,
+ },
+ [0x2F938]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7570 },
+ unicodeslot=0x2F938,
+ },
+ [0x2F939]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2219F },
+ unicodeslot=0x2F939,
+ },
+ [0x2F93A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7610 },
+ unicodeslot=0x2F93A,
+ },
+ [0x2F93B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24FA1 },
+ unicodeslot=0x2F93B,
+ },
+ [0x2F93C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x24FB8 },
+ unicodeslot=0x2F93C,
+ },
+ [0x2F93D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25044 },
+ unicodeslot=0x2F93D,
+ },
+ [0x2F93E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x3FFC },
+ unicodeslot=0x2F93E,
+ },
+ [0x2F93F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4008 },
+ unicodeslot=0x2F93F,
+ },
+ [0x2F940]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x76F4 },
+ unicodeslot=0x2F940,
+ },
+ [0x2F941]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x250F3 },
+ unicodeslot=0x2F941,
+ },
+ [0x2F942]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x250F2 },
+ unicodeslot=0x2F942,
+ },
+ [0x2F943]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25119 },
+ unicodeslot=0x2F943,
+ },
+ [0x2F944]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25133 },
+ unicodeslot=0x2F944,
+ },
+ [0x2F945]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x771E },
+ unicodeslot=0x2F945,
+ },
+ [0x2F946]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x771F },
+ unicodeslot=0x2F946,
+ },
+ [0x2F947]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x771F },
+ unicodeslot=0x2F947,
+ },
+ [0x2F948]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x774A },
+ unicodeslot=0x2F948,
+ },
+ [0x2F949]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4039 },
+ unicodeslot=0x2F949,
+ },
+ [0x2F94A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005EA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x778B },
+ unicodeslot=0x2F94A,
+ },
+ [0x2F94B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005EB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4046 },
+ unicodeslot=0x2F94B,
+ },
+ [0x2F94C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005EC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4096 },
+ unicodeslot=0x2F94C,
+ },
+ [0x2F94D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005ED",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2541D },
+ unicodeslot=0x2F94D,
+ },
+ [0x2F94E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005EE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x784E },
+ unicodeslot=0x2F94E,
+ },
+ [0x2F94F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005EF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x788C },
+ unicodeslot=0x2F94F,
+ },
+ [0x2F950]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x78CC },
+ unicodeslot=0x2F950,
+ },
+ [0x2F951]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x40E3 },
+ unicodeslot=0x2F951,
+ },
+ [0x2F952]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25626 },
+ unicodeslot=0x2F952,
+ },
+ [0x2F953]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03B9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7956 },
+ unicodeslot=0x2F953,
+ },
+ [0x2F954]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2569A },
+ unicodeslot=0x2F954,
+ },
+ [0x2F955]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x256C5 },
+ unicodeslot=0x2F955,
+ },
+ [0x2F956]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x798F },
+ unicodeslot=0x2F956,
+ },
+ [0x2F957]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x79EB },
+ unicodeslot=0x2F957,
+ },
+ [0x2F958]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x412F },
+ unicodeslot=0x2F958,
+ },
+ [0x2F959]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A40 },
+ unicodeslot=0x2F959,
+ },
+ [0x2F95A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A4A },
+ unicodeslot=0x2F95A,
+ },
+ [0x2F95B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7A4F },
+ unicodeslot=0x2F95B,
+ },
+ [0x2F95C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2597C },
+ unicodeslot=0x2F95C,
+ },
+ [0x2F95D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25AA7 },
+ unicodeslot=0x2F95D,
+ },
+ [0x2F95E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25AA7 },
+ unicodeslot=0x2F95E,
+ },
+ [0x2F95F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x005FF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7AEE },
+ unicodeslot=0x2F95F,
+ },
+ [0x2F960]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4202 },
+ unicodeslot=0x2F960,
+ },
+ [0x2F961]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25BAB },
+ unicodeslot=0x2F961,
+ },
+ [0x2F962]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7BC6 },
+ unicodeslot=0x2F962,
+ },
+ [0x2F963]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7BC9 },
+ unicodeslot=0x2F963,
+ },
+ [0x2F964]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4227 },
+ unicodeslot=0x2F964,
+ },
+ [0x2F965]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25C80 },
+ unicodeslot=0x2F965,
+ },
+ [0x2F966]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CD2 },
+ unicodeslot=0x2F966,
+ },
+ [0x2F967]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x42A0 },
+ unicodeslot=0x2F967,
+ },
+ [0x2F968]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CE8 },
+ unicodeslot=0x2F968,
+ },
+ [0x2F969]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03C9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7CE3 },
+ unicodeslot=0x2F969,
+ },
+ [0x2F96A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D00 },
+ unicodeslot=0x2F96A,
+ },
+ [0x2F96B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x25F86 },
+ unicodeslot=0x2F96B,
+ },
+ [0x2F96C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7D63 },
+ unicodeslot=0x2F96C,
+ },
+ [0x2F96D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4301 },
+ unicodeslot=0x2F96D,
+ },
+ [0x2F96E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7DC7 },
+ unicodeslot=0x2F96E,
+ },
+ [0x2F96F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0060F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7E02 },
+ unicodeslot=0x2F96F,
+ },
+ [0x2F970]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7E45 },
+ unicodeslot=0x2F970,
+ },
+ [0x2F971]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4334 },
+ unicodeslot=0x2F971,
+ },
+ [0x2F972]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26228 },
+ unicodeslot=0x2F972,
+ },
+ [0x2F973]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26247 },
+ unicodeslot=0x2F973,
+ },
+ [0x2F974]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4359 },
+ unicodeslot=0x2F974,
+ },
+ [0x2F975]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x262D9 },
+ unicodeslot=0x2F975,
+ },
+ [0x2F976]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F7A },
+ unicodeslot=0x2F976,
+ },
+ [0x2F977]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2633E },
+ unicodeslot=0x2F977,
+ },
+ [0x2F978]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7F95 },
+ unicodeslot=0x2F978,
+ },
+ [0x2F979]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x7FFA },
+ unicodeslot=0x2F979,
+ },
+ [0x2F97A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8005 },
+ unicodeslot=0x2F97A,
+ },
+ [0x2F97B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x264DA },
+ unicodeslot=0x2F97B,
+ },
+ [0x2F97C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26523 },
+ unicodeslot=0x2F97C,
+ },
+ [0x2F97D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8060 },
+ unicodeslot=0x2F97D,
+ },
+ [0x2F97E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x265A8 },
+ unicodeslot=0x2F97E,
+ },
+ [0x2F97F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0061F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8070 },
+ unicodeslot=0x2F97F,
+ },
+ [0x2F980]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2335F },
+ unicodeslot=0x2F980,
+ },
+ [0x2F981]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x43D5 },
+ unicodeslot=0x2F981,
+ },
+ [0x2F982]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x80B2 },
+ unicodeslot=0x2F982,
+ },
+ [0x2F983]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8103 },
+ unicodeslot=0x2F983,
+ },
+ [0x2F984]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D8",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x440B },
+ unicodeslot=0x2F984,
+ },
+ [0x2F985]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03D9",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x813E },
+ unicodeslot=0x2F985,
+ },
+ [0x2F986]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5AB5 },
+ unicodeslot=0x2F986,
+ },
+ [0x2F987]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x267A7 },
+ unicodeslot=0x2F987,
+ },
+ [0x2F988]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x267B5 },
+ unicodeslot=0x2F988,
+ },
+ [0x2F989]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x23393 },
+ unicodeslot=0x2F989,
+ },
+ [0x2F98A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2339C },
+ unicodeslot=0x2F98A,
+ },
+ [0x2F98B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8201 },
+ unicodeslot=0x2F98B,
+ },
+ [0x2F98C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8204 },
+ unicodeslot=0x2F98C,
+ },
+ [0x2F98D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F9E },
+ unicodeslot=0x2F98D,
+ },
+ [0x2F98E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x446B },
+ unicodeslot=0x2F98E,
+ },
+ [0x2F98F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0062F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8291 },
+ unicodeslot=0x2F98F,
+ },
+ [0x2F990]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x828B },
+ unicodeslot=0x2F990,
+ },
+ [0x2F991]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x829D },
+ unicodeslot=0x2F991,
+ },
+ [0x2F992]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E0",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x52B3 },
+ unicodeslot=0x2F992,
+ },
+ [0x2F993]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E1",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82B1 },
+ unicodeslot=0x2F993,
+ },
+ [0x2F994]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E2",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82B3 },
+ unicodeslot=0x2F994,
+ },
+ [0x2F995]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E3",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82BD },
+ unicodeslot=0x2F995,
+ },
+ [0x2F996]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E4",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82E6 },
+ unicodeslot=0x2F996,
+ },
+ [0x2F997]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E5",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26B3C },
+ unicodeslot=0x2F997,
+ },
+ [0x2F998]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E6",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x82E5 },
+ unicodeslot=0x2F998,
+ },
+ [0x2F999]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x03E7",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x831D },
+ unicodeslot=0x2F999,
+ },
+ [0x2F99A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8363 },
+ unicodeslot=0x2F99A,
+ },
+ [0x2F99B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83AD },
+ unicodeslot=0x2F99B,
+ },
+ [0x2F99C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8323 },
+ unicodeslot=0x2F99C,
+ },
+ [0x2F99D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83BD },
+ unicodeslot=0x2F99D,
+ },
+ [0x2F99E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83E7 },
+ unicodeslot=0x2F99E,
+ },
+ [0x2F99F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0063F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8457 },
+ unicodeslot=0x2F99F,
+ },
+ [0x2F9A0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8353 },
+ unicodeslot=0x2F9A0,
+ },
+ [0x2F9A1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83CA },
+ unicodeslot=0x2F9A1,
+ },
+ [0x2F9A2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83CC },
+ unicodeslot=0x2F9A2,
+ },
+ [0x2F9A3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x83DC },
+ unicodeslot=0x2F9A3,
+ },
+ [0x2F9A4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26C36 },
+ unicodeslot=0x2F9A4,
+ },
+ [0x2F9A5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26D6B },
+ unicodeslot=0x2F9A5,
+ },
+ [0x2F9A6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26CD5 },
+ unicodeslot=0x2F9A6,
+ },
+ [0x2F9A7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x452B },
+ unicodeslot=0x2F9A7,
+ },
+ [0x2F9A8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x84F1 },
+ unicodeslot=0x2F9A8,
+ },
+ [0x2F9A9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009A0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x84F3 },
+ unicodeslot=0x2F9A9,
+ },
+ [0x2F9AA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8516 },
+ unicodeslot=0x2F9AA,
+ },
+ [0x2F9AB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x273CA },
+ unicodeslot=0x2F9AB,
+ },
+ [0x2F9AC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8564 },
+ unicodeslot=0x2F9AC,
+ },
+ [0x2F9AD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26F2C },
+ unicodeslot=0x2F9AD,
+ },
+ [0x2F9AE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x455D },
+ unicodeslot=0x2F9AE,
+ },
+ [0x2F9AF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009AF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4561 },
+ unicodeslot=0x2F9AF,
+ },
+ [0x2F9B0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x26FB1 },
+ unicodeslot=0x2F9B0,
+ },
+ [0x2F9B1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x270D2 },
+ unicodeslot=0x2F9B1,
+ },
+ [0x2F9B2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x456B },
+ unicodeslot=0x2F9B2,
+ },
+ [0x2F9B3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8650 },
+ unicodeslot=0x2F9B3,
+ },
+ [0x2F9B4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x865C },
+ unicodeslot=0x2F9B4,
+ },
+ [0x2F9B5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8667 },
+ unicodeslot=0x2F9B5,
+ },
+ [0x2F9B6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8669 },
+ unicodeslot=0x2F9B6,
+ },
+ [0x2F9B7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x86A9 },
+ unicodeslot=0x2F9B7,
+ },
+ [0x2F9B8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8688 },
+ unicodeslot=0x2F9B8,
+ },
+ [0x2F9B9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009B0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x870E },
+ unicodeslot=0x2F9B9,
+ },
+ [0x2F9BA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x86E2 },
+ unicodeslot=0x2F9BA,
+ },
+ [0x2F9BB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8779 },
+ unicodeslot=0x2F9BB,
+ },
+ [0x2F9BC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8728 },
+ unicodeslot=0x2F9BC,
+ },
+ [0x2F9BD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x876B },
+ unicodeslot=0x2F9BD,
+ },
+ [0x2F9BE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8786 },
+ unicodeslot=0x2F9BE,
+ },
+ [0x2F9BF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009BF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x45D7 },
+ unicodeslot=0x2F9BF,
+ },
+ [0x2F9C0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x87E1 },
+ unicodeslot=0x2F9C0,
+ },
+ [0x2F9C1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8801 },
+ unicodeslot=0x2F9C1,
+ },
+ [0x2F9C2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x45F9 },
+ unicodeslot=0x2F9C2,
+ },
+ [0x2F9C3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8860 },
+ unicodeslot=0x2F9C3,
+ },
+ [0x2F9C4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8863 },
+ unicodeslot=0x2F9C4,
+ },
+ [0x2F9C5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x27667 },
+ unicodeslot=0x2F9C5,
+ },
+ [0x2F9C6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88D7 },
+ unicodeslot=0x2F9C6,
+ },
+ [0x2F9C7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88DE },
+ unicodeslot=0x2F9C7,
+ },
+ [0x2F9C8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4635 },
+ unicodeslot=0x2F9C8,
+ },
+ [0x2F9C9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009C0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x88FA },
+ unicodeslot=0x2F9C9,
+ },
+ [0x2F9CA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x34BB },
+ unicodeslot=0x2F9CA,
+ },
+ [0x2F9CB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x278AE },
+ unicodeslot=0x2F9CB,
+ },
+ [0x2F9CC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x27966 },
+ unicodeslot=0x2F9CC,
+ },
+ [0x2F9CD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x46BE },
+ unicodeslot=0x2F9CD,
+ },
+ [0x2F9CE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x46C7 },
+ unicodeslot=0x2F9CE,
+ },
+ [0x2F9CF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009CF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AA0 },
+ unicodeslot=0x2F9CF,
+ },
+ [0x2F9D0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8AED },
+ unicodeslot=0x2F9D0,
+ },
+ [0x2F9D1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8B8A },
+ unicodeslot=0x2F9D1,
+ },
+ [0x2F9D2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8C55 },
+ unicodeslot=0x2F9D2,
+ },
+ [0x2F9D3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x27CA8 },
+ unicodeslot=0x2F9D3,
+ },
+ [0x2F9D4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8CAB },
+ unicodeslot=0x2F9D4,
+ },
+ [0x2F9D5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8CC1 },
+ unicodeslot=0x2F9D5,
+ },
+ [0x2F9D6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8D1B },
+ unicodeslot=0x2F9D6,
+ },
+ [0x2F9D7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8D77 },
+ unicodeslot=0x2F9D7,
+ },
+ [0x2F9D8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x27F2F },
+ unicodeslot=0x2F9D8,
+ },
+ [0x2F9D9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009D0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x20804 },
+ unicodeslot=0x2F9D9,
+ },
+ [0x2F9DA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8DCB },
+ unicodeslot=0x2F9DA,
+ },
+ [0x2F9DB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8DBC },
+ unicodeslot=0x2F9DB,
+ },
+ [0x2F9DC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8DF0 },
+ unicodeslot=0x2F9DC,
+ },
+ [0x2F9DD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x208DE },
+ unicodeslot=0x2F9DD,
+ },
+ [0x2F9DE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8ED4 },
+ unicodeslot=0x2F9DE,
+ },
+ [0x2F9DF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009DF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8F38 },
+ unicodeslot=0x2F9DF,
+ },
+ [0x2F9E0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x285D2 },
+ unicodeslot=0x2F9E0,
+ },
+ [0x2F9E1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x285ED },
+ unicodeslot=0x2F9E1,
+ },
+ [0x2F9E2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9094 },
+ unicodeslot=0x2F9E2,
+ },
+ [0x2F9E3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x90F1 },
+ unicodeslot=0x2F9E3,
+ },
+ [0x2F9E4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9111 },
+ unicodeslot=0x2F9E4,
+ },
+ [0x2F9E5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2872E },
+ unicodeslot=0x2F9E5,
+ },
+ [0x2F9E6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x911B },
+ unicodeslot=0x2F9E6,
+ },
+ [0x2F9E7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9238 },
+ unicodeslot=0x2F9E7,
+ },
+ [0x2F9E8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x92D7 },
+ unicodeslot=0x2F9E8,
+ },
+ [0x2F9E9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009E0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x92D8 },
+ unicodeslot=0x2F9E9,
+ },
+ [0x2F9EA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009EA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x927C },
+ unicodeslot=0x2F9EA,
+ },
+ [0x2F9EB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009EB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x93F9 },
+ unicodeslot=0x2F9EB,
+ },
+ [0x2F9EC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009EC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9415 },
+ unicodeslot=0x2F9EC,
+ },
+ [0x2F9ED]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009ED",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x28BFA },
+ unicodeslot=0x2F9ED,
+ },
+ [0x2F9EE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009EE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x958B },
+ unicodeslot=0x2F9EE,
+ },
+ [0x2F9EF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009EF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4995 },
+ unicodeslot=0x2F9EF,
+ },
+ [0x2F9F0]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x95B7 },
+ unicodeslot=0x2F9F0,
+ },
+ [0x2F9F1]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x28D77 },
+ unicodeslot=0x2F9F1,
+ },
+ [0x2F9F2]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x49E6 },
+ unicodeslot=0x2F9F2,
+ },
+ [0x2F9F3]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96C3 },
+ unicodeslot=0x2F9F3,
+ },
+ [0x2F9F4]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x5DB2 },
+ unicodeslot=0x2F9F4,
+ },
+ [0x2F9F5]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9723 },
+ unicodeslot=0x2F9F5,
+ },
+ [0x2F9F6]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x29145 },
+ unicodeslot=0x2F9F6,
+ },
+ [0x2F9F7]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2921A },
+ unicodeslot=0x2F9F7,
+ },
+ [0x2F9F8]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4A6E },
+ unicodeslot=0x2F9F8,
+ },
+ [0x2F9F9]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009F0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4A76 },
+ unicodeslot=0x2F9F9,
+ },
+ [0x2F9FA]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FA",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x97E0 },
+ unicodeslot=0x2F9FA,
+ },
+ [0x2F9FB]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FB",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2940A },
+ unicodeslot=0x2F9FB,
+ },
+ [0x2F9FC]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FC",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4AB2 },
+ unicodeslot=0x2F9FC,
+ },
+ [0x2F9FD]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FD",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x29496 },
+ unicodeslot=0x2F9FD,
+ },
+ [0x2F9FE]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FE",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x980B },
+ unicodeslot=0x2F9FE,
+ },
+ [0x2F9FF]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002F0x0009FF",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x980B },
+ unicodeslot=0x2F9FF,
+ },
+ [0x2FA00]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9829 },
+ unicodeslot=0x2FA00,
+ },
+ [0x2FA01]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0001",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x295B6 },
+ unicodeslot=0x2FA01,
+ },
+ [0x2FA02]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0002",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x98E2 },
+ unicodeslot=0x2FA02,
+ },
+ [0x2FA03]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0003",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4B33 },
+ unicodeslot=0x2FA03,
+ },
+ [0x2FA04]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0004",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9929 },
+ unicodeslot=0x2FA04,
+ },
+ [0x2FA05]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0005",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x99A7 },
+ unicodeslot=0x2FA05,
+ },
+ [0x2FA06]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0006",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x99C2 },
+ unicodeslot=0x2FA06,
+ },
+ [0x2FA07]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0007",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x99FE },
+ unicodeslot=0x2FA07,
+ },
+ [0x2FA08]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0008",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4BCE },
+ unicodeslot=0x2FA08,
+ },
+ [0x2FA09]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0009",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x29B30 },
+ unicodeslot=0x2FA09,
+ },
+ [0x2FA0A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9B12 },
+ unicodeslot=0x2FA0A,
+ },
+ [0x2FA0B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9C40 },
+ unicodeslot=0x2FA0B,
+ },
+ [0x2FA0C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9CFD },
+ unicodeslot=0x2FA0C,
+ },
+ [0x2FA0D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4CCE },
+ unicodeslot=0x2FA0D,
+ },
+ [0x2FA0E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4CED },
+ unicodeslot=0x2FA0E,
+ },
+ [0x2FA0F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0000F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9D67 },
+ unicodeslot=0x2FA0F,
+ },
+ [0x2FA10]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A0CE },
+ unicodeslot=0x2FA10,
+ },
+ [0x2FA11]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4CF8 },
+ unicodeslot=0x2FA11,
+ },
+ [0x2FA12]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A105 },
+ unicodeslot=0x2FA12,
+ },
+ [0x2FA13]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A20E },
+ unicodeslot=0x2FA13,
+ },
+ [0x2FA14]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A291 },
+ unicodeslot=0x2FA14,
+ },
+ [0x2FA15]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x000F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9EBB },
+ unicodeslot=0x2FA15,
+ },
+ [0x2FA16]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0010",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x4D56 },
+ unicodeslot=0x2FA16,
+ },
+ [0x2FA17]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0011",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9EF9 },
+ unicodeslot=0x2FA17,
+ },
+ [0x2FA18]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0012",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9EFE },
+ unicodeslot=0x2FA18,
+ },
+ [0x2FA19]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0013",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F05 },
+ unicodeslot=0x2FA19,
+ },
+ [0x2FA1A]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0001A",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F0F },
+ unicodeslot=0x2FA1A,
+ },
+ [0x2FA1B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0001B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F16 },
+ unicodeslot=0x2FA1B,
+ },
+ [0x2FA1C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0001C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x9F3B },
+ unicodeslot=0x2FA1C,
+ },
+ [0x2FA1D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-0x0002FA0x0001D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x2A600 },
+ unicodeslot=0x2FA1D,
+ },
+ [0xE0001]={
+ category="cf",
+ description="LANGUAGE TAG",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0001,
+ },
+ [0xE0020]={
+ category="cf",
+ description="TAG SPACE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0020,
+ },
+ [0xE0021]={
+ category="cf",
+ description="TAG EXCLAMATION MARK",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0021,
+ },
+ [0xE0022]={
+ category="cf",
+ description="TAG QUOTATION MARK",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0022,
+ },
+ [0xE0023]={
+ category="cf",
+ description="TAG NUMBER SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0023,
+ },
+ [0xE0024]={
+ category="cf",
+ description="TAG DOLLAR SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0024,
+ },
+ [0xE0025]={
+ category="cf",
+ description="TAG PERCENT SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0025,
+ },
+ [0xE0026]={
+ category="cf",
+ description="TAG AMPERSAND",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0026,
+ },
+ [0xE0027]={
+ category="cf",
+ description="TAG APOSTROPHE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0027,
+ },
+ [0xE0028]={
+ category="cf",
+ description="TAG LEFT PARENTHESIS",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0028,
+ },
+ [0xE0029]={
+ category="cf",
+ description="TAG RIGHT PARENTHESIS",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0029,
+ },
+ [0xE002A]={
+ category="cf",
+ description="TAG ASTERISK",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002A,
+ },
+ [0xE002B]={
+ category="cf",
+ description="TAG PLUS SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002B,
+ },
+ [0xE002C]={
+ category="cf",
+ description="TAG COMMA",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002C,
+ },
+ [0xE002D]={
+ category="cf",
+ description="TAG HYPHEN-MINUS",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002D,
+ },
+ [0xE002E]={
+ category="cf",
+ description="TAG FULL STOP",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002E,
+ },
+ [0xE002F]={
+ category="cf",
+ description="TAG SOLIDUS",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE002F,
+ },
+ [0xE0030]={
+ category="cf",
+ description="TAG DIGIT ZERO",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0030,
+ },
+ [0xE0031]={
+ category="cf",
+ description="TAG DIGIT ONE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0031,
+ },
+ [0xE0032]={
+ category="cf",
+ description="TAG DIGIT TWO",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0032,
+ },
+ [0xE0033]={
+ category="cf",
+ description="TAG DIGIT THREE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0033,
+ },
+ [0xE0034]={
+ category="cf",
+ description="TAG DIGIT FOUR",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0034,
+ },
+ [0xE0035]={
+ category="cf",
+ description="TAG DIGIT FIVE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0035,
+ },
+ [0xE0036]={
+ category="cf",
+ description="TAG DIGIT SIX",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0036,
+ },
+ [0xE0037]={
+ category="cf",
+ description="TAG DIGIT SEVEN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0037,
+ },
+ [0xE0038]={
+ category="cf",
+ description="TAG DIGIT EIGHT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0038,
+ },
+ [0xE0039]={
+ category="cf",
+ description="TAG DIGIT NINE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0039,
+ },
+ [0xE003A]={
+ category="cf",
+ description="TAG COLON",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003A,
+ },
+ [0xE003B]={
+ category="cf",
+ description="TAG SEMICOLON",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003B,
+ },
+ [0xE003C]={
+ category="cf",
+ description="TAG LESS-THAN SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003C,
+ },
+ [0xE003D]={
+ category="cf",
+ description="TAG EQUALS SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003D,
+ },
+ [0xE003E]={
+ category="cf",
+ description="TAG GREATER-THAN SIGN",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003E,
+ },
+ [0xE003F]={
+ category="cf",
+ description="TAG QUESTION MARK",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE003F,
+ },
+ [0xE0040]={
+ category="cf",
+ description="TAG COMMERCIAL AT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0040,
+ },
+ [0xE0041]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER A",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0041,
+ },
+ [0xE0042]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER B",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0042,
+ },
+ [0xE0043]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER C",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0043,
+ },
+ [0xE0044]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER D",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0044,
+ },
+ [0xE0045]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER E",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0045,
+ },
+ [0xE0046]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER F",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0046,
+ },
+ [0xE0047]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER G",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0047,
+ },
+ [0xE0048]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER H",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0048,
+ },
+ [0xE0049]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER I",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0049,
+ },
+ [0xE004A]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER J",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004A,
+ },
+ [0xE004B]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER K",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004B,
+ },
+ [0xE004C]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER L",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004C,
+ },
+ [0xE004D]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER M",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004D,
+ },
+ [0xE004E]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER N",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004E,
+ },
+ [0xE004F]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER O",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE004F,
+ },
+ [0xE0050]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER P",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0050,
+ },
+ [0xE0051]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER Q",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0051,
+ },
+ [0xE0052]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER R",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0052,
+ },
+ [0xE0053]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER S",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0053,
+ },
+ [0xE0054]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER T",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0054,
+ },
+ [0xE0055]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER U",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0055,
+ },
+ [0xE0056]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER V",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0056,
+ },
+ [0xE0057]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER W",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0057,
+ },
+ [0xE0058]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER X",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0058,
+ },
+ [0xE0059]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER Y",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0059,
+ },
+ [0xE005A]={
+ category="cf",
+ description="TAG LATIN CAPITAL LETTER Z",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005A,
+ },
+ [0xE005B]={
+ category="cf",
+ description="TAG LEFT SQUARE BRACKET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005B,
+ },
+ [0xE005C]={
+ category="cf",
+ description="TAG REVERSE SOLIDUS",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005C,
+ },
+ [0xE005D]={
+ category="cf",
+ description="TAG RIGHT SQUARE BRACKET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005D,
+ },
+ [0xE005E]={
+ category="cf",
+ description="TAG CIRCUMFLEX ACCENT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005E,
+ },
+ [0xE005F]={
+ category="cf",
+ description="TAG LOW LINE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE005F,
+ },
+ [0xE0060]={
+ category="cf",
+ description="TAG GRAVE ACCENT",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0060,
+ },
+ [0xE0061]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER A",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0061,
+ },
+ [0xE0062]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER B",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0062,
+ },
+ [0xE0063]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER C",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0063,
+ },
+ [0xE0064]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER D",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0064,
+ },
+ [0xE0065]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER E",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0065,
+ },
+ [0xE0066]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER F",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0066,
+ },
+ [0xE0067]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER G",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0067,
+ },
+ [0xE0068]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER H",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0068,
+ },
+ [0xE0069]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER I",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0069,
+ },
+ [0xE006A]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER J",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006A,
+ },
+ [0xE006B]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER K",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006B,
+ },
+ [0xE006C]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER L",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006C,
+ },
+ [0xE006D]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER M",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006D,
+ },
+ [0xE006E]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER N",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006E,
+ },
+ [0xE006F]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER O",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE006F,
+ },
+ [0xE0070]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER P",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0070,
+ },
+ [0xE0071]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER Q",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0071,
+ },
+ [0xE0072]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER R",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0072,
+ },
+ [0xE0073]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER S",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0073,
+ },
+ [0xE0074]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER T",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0074,
+ },
+ [0xE0075]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER U",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0075,
+ },
+ [0xE0076]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER V",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0076,
+ },
+ [0xE0077]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER W",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0077,
+ },
+ [0xE0078]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER X",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0078,
+ },
+ [0xE0079]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER Y",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE0079,
+ },
+ [0xE007A]={
+ category="cf",
+ description="TAG LATIN SMALL LETTER Z",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007A,
+ },
+ [0xE007B]={
+ category="cf",
+ description="TAG LEFT CURLY BRACKET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007B,
+ },
+ [0xE007C]={
+ category="cf",
+ description="TAG VERTICAL LINE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007C,
+ },
+ [0xE007D]={
+ category="cf",
+ description="TAG RIGHT CURLY BRACKET",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007D,
+ },
+ [0xE007E]={
+ category="cf",
+ description="TAG TILDE",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007E,
+ },
+ [0xE007F]={
+ category="cf",
+ description="CANCEL TAG",
+ direction="bn",
+ linebreak="cm",
+ unicodeslot=0xE007F,
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-enc.lua b/Master/texmf-dist/tex/context/base/mkiv/char-enc.lua
new file mode 100644
index 00000000000..c2061891ad4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-enc.lua
@@ -0,0 +1,193 @@
+if not modules then modules = { } end modules ['char-enc'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+ -- dataonly = true,
+}
+
+-- Thanks to tex4ht for these mappings.
+
+local next = next
+
+local allocate, setinitializer = utilities.storage.allocate, utilities.storage.setinitializer
+
+characters = characters or { }
+local characters = characters
+
+characters.synonyms = allocate { -- afm mess
+ angle = 0x2220,
+ anticlockwise = 0x21BA,
+ arrowaxisleft = 0x2190,
+ arrowaxisright = 0x2192,
+ arrowparrleftright = 0x21C6,
+ arrowparrrightleft = 0x21C4,
+ arrowtailleft = 0x21A2,
+ arrowtailright = 0x21A3,
+ arrowtripleleft = 0x21DA,
+ arrowtripleright = 0x21DB,
+ axisshort = 0x2212,
+ because = 0x2235,
+ between = 0x226C,
+ check = 0x2713,
+ circleasteris = 0x229B,
+ circleequal = 0x2257,
+ circleminus = 0x229D,
+ circleR = 0x24C7,
+ circlering = 0x229A,
+ circleS = 0x24C8,
+ clockwise = 0x21BB,
+ complement = 0x2201,
+ curlyleft = 0x21AB,
+ curlyright = 0x21AC,
+ dblarrowdwn = 0x21CA,
+ dblarrowheadleft = 0x219E,
+ dblarrowheadright = 0x21A0,
+ dblarrowleft = 0x21C7,
+ dblarrowright = 0x21C9,
+ dblarrowup = 0x21C8,
+ defines = 0x225C,
+ diamond = 0x2662,
+ diamondsolid = 0x2666,
+ difference = 0x224F,
+ dotplus = 0x2214,
+ downfall = 0x22CE,
+ equaldotleftright = 0x2252,
+ equaldotrightleft = 0x2253,
+ equalorfollows = 0x22DF,
+ equalorgreater = 0x22DD,
+ equalorless = 0x22DC,
+ equalorprecedes = 0x22DE,
+ equalsdots = 0x2251,
+ followsorcurly = 0x227D,
+ followsorequal = 0x227F,
+ forces = 0x22A9,
+ forcesbar = 0x22AA,
+ fork = 0x22D4,
+ frown = 0x2322,
+ geomequivalent = 0x224E,
+ greaterdbleqlless = 0x22Da,
+ greaterdblequal = 0x2267,
+ greaterlessequal = 0x22DA,
+ greaterorapproxeql = 0x227F,
+ greaterorequalslant= 0x2265,
+ greaterorless = 0x2277,
+ greaterorsimilar = 0x2273,
+ harpoondownleft = 0x21C3,
+ harpoondownright = 0x21C2,
+ harpoonleftright = 0x21CC,
+ harpoonrightleft = 0x21CB,
+ harpoonupleft = 0x21BF,
+ harpoonupright = 0x21BE,
+ intercal = 0x22BA,
+ intersectiondbl = 0x22D2,
+ lessdbleqlgreater = 0x22DB,
+ lessdblequal = 0x2266,
+ lessequalgreater = 0x22DB,
+ lessorapproxeql = 0x227E,
+ lessorequalslant = 0x2264,
+ lessorgreater = 0x2276,
+ lessorsimilar = 0x2272,
+ maltesecross = 0xFFFD,
+ measuredangle = 0x2221,
+ muchgreater = 0x22D9,
+ muchless = 0x22D8,
+ multimap = 0x22B8,
+ multiopenleft = 0x22CB,
+ multiopenright = 0x22CC,
+ nand = 0x22BC,
+ orunderscore = 0x22BB,
+ perpcorrespond = 0x2259,
+ precedesorcurly = 0x227C,
+ precedesorequal = 0x227E,
+ primereverse = 0x2035,
+ proportional = 0x221D,
+ revasymptequal = 0x2243,
+ revsimilar = 0x223D,
+ rightanglene = 0x231D,
+ rightanglenw = 0x231C,
+ rightanglese = 0x231F,
+ rightanglesw = 0x231E,
+ ringinequal = 0x2256,
+ satisfies = 0x22A8,
+ shiftleft = 0x21B0,
+ shiftright = 0x21B1,
+ smile = 0x2323,
+ sphericalangle = 0x2222,
+ square = 0x25A1,
+ squaredot = 0x22A1,
+ squareimage = 0x228F,
+ squareminus = 0x229F,
+ squaremultiply = 0x22A0,
+ squareoriginal = 0x2290,
+ squareplus = 0x229E,
+ squaresmallsolid = 0x25AA,
+ squaresolid = 0x25A0,
+ squiggleleftright = 0x21AD,
+ squiggleright = 0x21DD,
+ star = 0x22C6,
+ subsetdbl = 0x22D0,
+ subsetdblequal = 0x2286,
+ supersetdbl = 0x22D1,
+ supersetdblequa = 0x2287,
+ therefore = 0x2234,
+ triangle = 0x25B5,
+ triangledownsld = 0x25BE,
+ triangleinv = 0x25BF,
+ triangleleft = 0x25C3,
+ triangleleftequal = 0x22B4,
+ triangleleftsld = 0x25C2,
+ triangleright = 0x25B9,
+ trianglerightequal = 0x22B5,
+ trianglerightsld = 0x25B8,
+ trianglesolid = 0x25B4,
+ uniondbl = 0x22D3,
+ uprise = 0x22CF,
+ Yen = 0x00A5,
+}
+
+-- if not characters.enccodes then
+--
+-- local enccodes = { } characters.enccodes = enccodes
+--
+-- for unicode, data in next, characters.data do
+-- local encname = data.adobename or data.contextname
+-- if encname then
+-- enccodes[encname] = unicode
+-- end
+-- end
+--
+-- for name, unicode in next, characters.synonyms do
+-- if not enccodes[name] then enccodes[name] = unicode end
+-- end
+--
+--
+-- end
+--
+-- storage.register("characters.enccodes", characters.enccodes, "characters.enccodes")
+
+-- As this table is seldom used, we can delay its definition. Beware, this means
+-- that table.print would not work on this file unless it is accessed once. This
+-- why the serializer does a dummy access.
+
+local enccodes = allocate()
+characters.enccodes = enccodes
+
+ -- maybe omit context name -> then same as encodings.make_unicode_vector
+
+local function initialize()
+ for unicode, data in next, characters.data do
+ local encname = data.adobename or data.contextname
+ if encname then
+ enccodes[encname] = unicode
+ end
+ end
+ for name, unicode in next, characters.synonyms do
+ if not enccodes[name] then
+ enccodes[name] = unicode
+ end
+ end
+end
+
+setinitializer(enccodes,initialize)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-enc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-enc.mkiv
new file mode 100644
index 00000000000..86ab2591a41
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-enc.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=char-enc,
+%D version=2006.08.20,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Encodings,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Character Support / Encodings}
+
+\registerctxluafile{char-enc}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ent.lua b/Master/texmf-dist/tex/context/base/mkiv/char-ent.lua
new file mode 100644
index 00000000000..e48856a8440
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-ent.lua
@@ -0,0 +1,2259 @@
+if not modules then modules = { } end modules ['char-ent'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "derived from the mathml 2.0 specification",
+ dataonly = true,
+}
+
+-- http://www.w3.org/2003/entities/2007/w3centities-f.ent
+-- http://www.w3.org/2003/entities/2007/htmlmathml-f.ent
+
+local entities = utilities.storage.allocate {
+ ["AElig"] = "Æ", -- U+000C6
+ ["AMP"] = "&", -- U+00026
+ ["Aacgr"] = "Ά", -- U+00386
+ ["Aacute"] = "Á", -- U+000C1
+ ["Abreve"] = "Ă", -- U+00102
+ ["Acirc"] = "Â", -- U+000C2
+ ["Acy"] = "А", -- U+00410
+ ["Afr"] = "𝔄", -- U+1D504
+ ["Agr"] = "Α", -- U+00391
+ ["Agrave"] = "À", -- U+000C0
+ ["Alpha"] = "Α", -- U+00391
+ ["Amacr"] = "Ā", -- U+00100
+ ["And"] = "⩓", -- U+02A53
+ ["Aogon"] = "Ą", -- U+00104
+ ["Aopf"] = "𝔸", -- U+1D538
+ ["ApplyFunction"] = "⁡", -- U+02061
+ ["Aring"] = "Å", -- U+000C5
+ ["Ascr"] = "𝒜", -- U+1D49C
+ ["Assign"] = "≔", -- U+02254
+ ["Atilde"] = "Ã", -- U+000C3
+ ["Auml"] = "Ä", -- U+000C4
+ ["Backslash"] = "∖", -- U+02216
+ ["Barv"] = "⫧", -- U+02AE7
+ ["Barwed"] = "⌆", -- U+02306
+ ["Bcy"] = "Б", -- U+00411
+ ["Because"] = "∵", -- U+02235
+ ["Bernoullis"] = "ℬ", -- U+0212C
+ ["Beta"] = "Β", -- U+00392
+ ["Bfr"] = "𝔅", -- U+1D505
+ ["Bgr"] = "Β", -- U+00392
+ ["Bopf"] = "𝔹", -- U+1D539
+ ["Breve"] = "˘", -- U+002D8
+ ["Bscr"] = "ℬ", -- U+0212C
+ ["Bumpeq"] = "≎", -- U+0224E
+ ["CHcy"] = "Ч", -- U+00427
+ ["COPY"] = "©", -- U+000A9
+ ["Cacute"] = "Ć", -- U+00106
+ ["Cap"] = "⋒", -- U+022D2
+ ["CapitalDifferentialD"] = "ⅅ", -- U+02145
+ ["Cayleys"] = "ℭ", -- U+0212D
+ ["Ccaron"] = "Č", -- U+0010C
+ ["Ccedil"] = "Ç", -- U+000C7
+ ["Ccirc"] = "Ĉ", -- U+00108
+ ["Cconint"] = "∰", -- U+02230
+ ["Cdot"] = "Ċ", -- U+0010A
+ ["Cedilla"] = "¸", -- U+000B8
+ ["CenterDot"] = "·", -- U+000B7
+ ["Cfr"] = "ℭ", -- U+0212D
+ ["Chi"] = "Χ", -- U+003A7
+ ["CircleDot"] = "⊙", -- U+02299
+ ["CircleMinus"] = "⊖", -- U+02296
+ ["CirclePlus"] = "⊕", -- U+02295
+ ["CircleTimes"] = "⊗", -- U+02297
+ ["ClockwiseContourIntegral"] = "∲", -- U+02232
+ ["CloseCurlyDoubleQuote"] = "”", -- U+0201D
+ ["CloseCurlyQuote"] = "’", -- U+02019
+ ["Colon"] = "∷", -- U+02237
+ ["Colone"] = "⩴", -- U+02A74
+ ["Congruent"] = "≡", -- U+02261
+ ["Conint"] = "∯", -- U+0222F
+ ["ContourIntegral"] = "∮", -- U+0222E
+ ["Copf"] = "ℂ", -- U+02102
+ ["Coproduct"] = "∐", -- U+02210
+ ["CounterClockwiseContourIntegral"] = "∳", -- U+02233
+ ["Cross"] = "⨯", -- U+02A2F
+ ["Cscr"] = "𝒞", -- U+1D49E
+ ["Cup"] = "⋓", -- U+022D3
+ ["CupCap"] = "≍", -- U+0224D
+ ["DD"] = "ⅅ", -- U+02145
+ ["DDotrahd"] = "⤑", -- U+02911
+ ["DJcy"] = "Ђ", -- U+00402
+ ["DScy"] = "Ѕ", -- U+00405
+ ["DZcy"] = "Џ", -- U+0040F
+ ["Dagger"] = "‡", -- U+02021
+ ["Darr"] = "↡", -- U+021A1
+ ["Dashv"] = "⫤", -- U+02AE4
+ ["Dcaron"] = "Ď", -- U+0010E
+ ["Dcy"] = "Д", -- U+00414
+ ["Del"] = "∇", -- U+02207
+ ["Delta"] = "Δ", -- U+00394
+ ["Dfr"] = "𝔇", -- U+1D507
+ ["Dgr"] = "Δ", -- U+00394
+ ["DiacriticalAcute"] = "´", -- U+000B4
+ ["DiacriticalDot"] = "˙", -- U+002D9
+ ["DiacriticalDoubleAcute"] = "˝", -- U+002DD
+ ["DiacriticalGrave"] = "`", -- U+00060
+ ["DiacriticalTilde"] = "˜", -- U+002DC
+ ["Diamond"] = "⋄", -- U+022C4
+ ["DifferentialD"] = "ⅆ", -- U+02146
+ ["Dopf"] = "𝔻", -- U+1D53B
+ ["Dot"] = "¨", -- U+000A8
+ ["DotDot"] = "⃜", -- U+020DC
+ ["DotEqual"] = "≐", -- U+02250
+ ["DoubleContourIntegral"] = "∯", -- U+0222F
+ ["DoubleDot"] = "¨", -- U+000A8
+ ["DoubleDownArrow"] = "⇓", -- U+021D3
+ ["DoubleLeftArrow"] = "⇐", -- U+021D0
+ ["DoubleLeftRightArrow"] = "⇔", -- U+021D4
+ ["DoubleLeftTee"] = "⫤", -- U+02AE4
+ ["DoubleLongLeftArrow"] = "⟸", -- U+027F8
+ ["DoubleLongLeftRightArrow"] = "⟺", -- U+027FA
+ ["DoubleLongRightArrow"] = "⟹", -- U+027F9
+ ["DoubleRightArrow"] = "⇒", -- U+021D2
+ ["DoubleRightTee"] = "⊨", -- U+022A8
+ ["DoubleUpArrow"] = "⇑", -- U+021D1
+ ["DoubleUpDownArrow"] = "⇕", -- U+021D5
+ ["DoubleVerticalBar"] = "∥", -- U+02225
+ ["DownArrow"] = "↓", -- U+02193
+ ["DownArrowBar"] = "⤓", -- U+02913
+ ["DownArrowUpArrow"] = "⇵", -- U+021F5
+ ["DownBreve"] = "̑", -- U+00311
+ ["DownLeftRightVector"] = "⥐", -- U+02950
+ ["DownLeftTeeVector"] = "⥞", -- U+0295E
+ ["DownLeftVector"] = "↽", -- U+021BD
+ ["DownLeftVectorBar"] = "⥖", -- U+02956
+ ["DownRightTeeVector"] = "⥟", -- U+0295F
+ ["DownRightVector"] = "⇁", -- U+021C1
+ ["DownRightVectorBar"] = "⥗", -- U+02957
+ ["DownTee"] = "⊤", -- U+022A4
+ ["DownTeeArrow"] = "↧", -- U+021A7
+ ["Downarrow"] = "⇓", -- U+021D3
+ ["Dscr"] = "𝒟", -- U+1D49F
+ ["Dstrok"] = "Đ", -- U+00110
+ ["EEacgr"] = "Ή", -- U+00389
+ ["EEgr"] = "Η", -- U+00397
+ ["ENG"] = "Ŋ", -- U+0014A
+ ["ETH"] = "Ð", -- U+000D0
+ ["Eacgr"] = "Έ", -- U+00388
+ ["Eacute"] = "É", -- U+000C9
+ ["Ecaron"] = "Ě", -- U+0011A
+ ["Ecirc"] = "Ê", -- U+000CA
+ ["Ecy"] = "Э", -- U+0042D
+ ["Edot"] = "Ė", -- U+00116
+ ["Efr"] = "𝔈", -- U+1D508
+ ["Egr"] = "Ε", -- U+00395
+ ["Egrave"] = "È", -- U+000C8
+ ["Element"] = "∈", -- U+02208
+ ["Emacr"] = "Ē", -- U+00112
+ ["EmptySmallSquare"] = "◻", -- U+025FB
+ ["EmptyVerySmallSquare"] = "▫", -- U+025AB
+ ["Eogon"] = "Ę", -- U+00118
+ ["Eopf"] = "𝔼", -- U+1D53C
+ ["Epsilon"] = "Ε", -- U+00395
+ ["Equal"] = "⩵", -- U+02A75
+ ["EqualTilde"] = "≂", -- U+02242
+ ["Equilibrium"] = "⇌", -- U+021CC
+ ["Escr"] = "ℰ", -- U+02130
+ ["Esim"] = "⩳", -- U+02A73
+ ["Eta"] = "Η", -- U+00397
+ ["Euml"] = "Ë", -- U+000CB
+ ["Exists"] = "∃", -- U+02203
+ ["ExponentialE"] = "ⅇ", -- U+02147
+ ["Fcy"] = "Ф", -- U+00424
+ ["Ffr"] = "𝔉", -- U+1D509
+ ["FilledSmallSquare"] = "◼", -- U+025FC
+ ["FilledVerySmallSquare"] = "▪", -- U+025AA
+ ["Fopf"] = "𝔽", -- U+1D53D
+ ["ForAll"] = "∀", -- U+02200
+ ["Fouriertrf"] = "ℱ", -- U+02131
+ ["Fscr"] = "ℱ", -- U+02131
+ ["GJcy"] = "Ѓ", -- U+00403
+ ["GT"] = ">", -- U+0003E
+ ["Gamma"] = "Γ", -- U+00393
+ ["Gammad"] = "Ϝ", -- U+003DC
+ ["Gbreve"] = "Ğ", -- U+0011E
+ ["Gcedil"] = "Ģ", -- U+00122
+ ["Gcirc"] = "Ĝ", -- U+0011C
+ ["Gcy"] = "Г", -- U+00413
+ ["Gdot"] = "Ġ", -- U+00120
+ ["Gfr"] = "𝔊", -- U+1D50A
+ ["Gg"] = "⋙", -- U+022D9
+ ["Ggr"] = "Γ", -- U+00393
+ ["Gopf"] = "𝔾", -- U+1D53E
+ ["GreaterEqual"] = "≥", -- U+02265
+ ["GreaterEqualLess"] = "⋛", -- U+022DB
+ ["GreaterFullEqual"] = "≧", -- U+02267
+ ["GreaterGreater"] = "⪢", -- U+02AA2
+ ["GreaterLess"] = "≷", -- U+02277
+ ["GreaterSlantEqual"] = "⩾", -- U+02A7E
+ ["GreaterTilde"] = "≳", -- U+02273
+ ["Gscr"] = "𝒢", -- U+1D4A2
+ ["Gt"] = "≫", -- U+0226B
+ ["HARDcy"] = "Ъ", -- U+0042A
+ ["Hacek"] = "ˇ", -- U+002C7
+ ["Hat"] = "^", -- U+0005E
+ ["Hcirc"] = "Ĥ", -- U+00124
+ ["Hfr"] = "ℌ", -- U+0210C
+ ["HilbertSpace"] = "ℋ", -- U+0210B
+ ["Hopf"] = "ℍ", -- U+0210D
+ ["HorizontalLine"] = "─", -- U+02500
+ ["Hscr"] = "ℋ", -- U+0210B
+ ["Hstrok"] = "Ħ", -- U+00126
+ ["HumpDownHump"] = "≎", -- U+0224E
+ ["HumpEqual"] = "≏", -- U+0224F
+ ["IEcy"] = "Е", -- U+00415
+ ["IJlig"] = "IJ", -- U+00132
+ ["IOcy"] = "Ё", -- U+00401
+ ["Iacgr"] = "Ί", -- U+0038A
+ ["Iacute"] = "Í", -- U+000CD
+ ["Icirc"] = "Î", -- U+000CE
+ ["Icy"] = "И", -- U+00418
+ ["Idigr"] = "Ϊ", -- U+003AA
+ ["Idot"] = "İ", -- U+00130
+ ["Ifr"] = "ℑ", -- U+02111
+ ["Igr"] = "Ι", -- U+00399
+ ["Igrave"] = "Ì", -- U+000CC
+ ["Im"] = "ℑ", -- U+02111
+ ["Imacr"] = "Ī", -- U+0012A
+ ["ImaginaryI"] = "ⅈ", -- U+02148
+ ["Implies"] = "⇒", -- U+021D2
+ ["Int"] = "∬", -- U+0222C
+ ["Integral"] = "∫", -- U+0222B
+ ["Intersection"] = "⋂", -- U+022C2
+ ["InvisibleComma"] = "⁣", -- U+02063
+ ["InvisibleTimes"] = "⁢", -- U+02062
+ ["Iogon"] = "Į", -- U+0012E
+ ["Iopf"] = "𝕀", -- U+1D540
+ ["Iota"] = "Ι", -- U+00399
+ ["Iscr"] = "ℐ", -- U+02110
+ ["Itilde"] = "Ĩ", -- U+00128
+ ["Iukcy"] = "І", -- U+00406
+ ["Iuml"] = "Ï", -- U+000CF
+ ["Jcirc"] = "Ĵ", -- U+00134
+ ["Jcy"] = "Й", -- U+00419
+ ["Jfr"] = "𝔍", -- U+1D50D
+ ["Jopf"] = "𝕁", -- U+1D541
+ ["Jscr"] = "𝒥", -- U+1D4A5
+ ["Jsercy"] = "Ј", -- U+00408
+ ["Jukcy"] = "Є", -- U+00404
+ ["KHcy"] = "Х", -- U+00425
+ ["KHgr"] = "Χ", -- U+003A7
+ ["KJcy"] = "Ќ", -- U+0040C
+ ["Kappa"] = "Κ", -- U+0039A
+ ["Kcedil"] = "Ķ", -- U+00136
+ ["Kcy"] = "К", -- U+0041A
+ ["Kfr"] = "𝔎", -- U+1D50E
+ ["Kgr"] = "Κ", -- U+0039A
+ ["Kopf"] = "𝕂", -- U+1D542
+ ["Kscr"] = "𝒦", -- U+1D4A6
+ ["LJcy"] = "Љ", -- U+00409
+ ["LT"] = "<", -- U+00026
+ ["Lacute"] = "Ĺ", -- U+00139
+ ["Lambda"] = "Λ", -- U+0039B
+ ["Lang"] = "⟪", -- U+027EA
+ ["Laplacetrf"] = "ℒ", -- U+02112
+ ["Larr"] = "↞", -- U+0219E
+ ["Lcaron"] = "Ľ", -- U+0013D
+ ["Lcedil"] = "Ļ", -- U+0013B
+ ["Lcy"] = "Л", -- U+0041B
+ ["LeftAngleBracket"] = "⟨", -- U+027E8
+ ["LeftArrow"] = "←", -- U+02190
+ ["LeftArrowBar"] = "⇤", -- U+021E4
+ ["LeftArrowRightArrow"] = "⇆", -- U+021C6
+ ["LeftCeiling"] = "⌈", -- U+02308
+ ["LeftDoubleBracket"] = "⟦", -- U+027E6
+ ["LeftDownTeeVector"] = "⥡", -- U+02961
+ ["LeftDownVector"] = "⇃", -- U+021C3
+ ["LeftDownVectorBar"] = "⥙", -- U+02959
+ ["LeftFloor"] = "⌊", -- U+0230A
+ ["LeftRightArrow"] = "↔", -- U+02194
+ ["LeftRightVector"] = "⥎", -- U+0294E
+ ["LeftTee"] = "⊣", -- U+022A3
+ ["LeftTeeArrow"] = "↤", -- U+021A4
+ ["LeftTeeVector"] = "⥚", -- U+0295A
+ ["LeftTriangle"] = "⊲", -- U+022B2
+ ["LeftTriangleBar"] = "⧏", -- U+029CF
+ ["LeftTriangleEqual"] = "⊴", -- U+022B4
+ ["LeftUpDownVector"] = "⥑", -- U+02951
+ ["LeftUpTeeVector"] = "⥠", -- U+02960
+ ["LeftUpVector"] = "↿", -- U+021BF
+ ["LeftUpVectorBar"] = "⥘", -- U+02958
+ ["LeftVector"] = "↼", -- U+021BC
+ ["LeftVectorBar"] = "⥒", -- U+02952
+ ["Leftarrow"] = "⇐", -- U+021D0
+ ["Leftrightarrow"] = "⇔", -- U+021D4
+ ["LessEqualGreater"] = "⋚", -- U+022DA
+ ["LessFullEqual"] = "≦", -- U+02266
+ ["LessGreater"] = "≶", -- U+02276
+ ["LessLess"] = "⪡", -- U+02AA1
+ ["LessSlantEqual"] = "⩽", -- U+02A7D
+ ["LessTilde"] = "≲", -- U+02272
+ ["Lfr"] = "𝔏", -- U+1D50F
+ ["Lgr"] = "Λ", -- U+0039B
+ ["Ll"] = "⋘", -- U+022D8
+ ["Lleftarrow"] = "⇚", -- U+021DA
+ ["Lmidot"] = "Ŀ", -- U+0013F
+ ["LongLeftArrow"] = "⟵", -- U+027F5
+ ["LongLeftRightArrow"] = "⟷", -- U+027F7
+ ["LongRightArrow"] = "⟶", -- U+027F6
+ ["Longleftarrow"] = "⟸", -- U+027F8
+ ["Longleftrightarrow"] = "⟺", -- U+027FA
+ ["Longrightarrow"] = "⟹", -- U+027F9
+ ["Lopf"] = "𝕃", -- U+1D543
+ ["LowerLeftArrow"] = "↙", -- U+02199
+ ["LowerRightArrow"] = "↘", -- U+02198
+ ["Lscr"] = "ℒ", -- U+02112
+ ["Lsh"] = "↰", -- U+021B0
+ ["Lstrok"] = "Ł", -- U+00141
+ ["Lt"] = "≪", -- U+0226A
+ ["Map"] = "⤅", -- U+02905
+ ["Mcy"] = "М", -- U+0041C
+ ["MediumSpace"] = " ", -- U+0205F
+ ["Mellintrf"] = "ℳ", -- U+02133
+ ["Mfr"] = "𝔐", -- U+1D510
+ ["Mgr"] = "Μ", -- U+0039C
+ ["MinusPlus"] = "∓", -- U+02213
+ ["Mopf"] = "𝕄", -- U+1D544
+ ["Mscr"] = "ℳ", -- U+02133
+ ["Mu"] = "Μ", -- U+0039C
+ ["NJcy"] = "Њ", -- U+0040A
+ ["Nacute"] = "Ń", -- U+00143
+ ["Ncaron"] = "Ň", -- U+00147
+ ["Ncedil"] = "Ņ", -- U+00145
+ ["Ncy"] = "Н", -- U+0041D
+ ["NegativeMediumSpace"] = "​", -- U+0200B
+ ["NegativeThickSpace"] = "​", -- U+0200B
+ ["NegativeThinSpace"] = "​", -- U+0200B
+ ["NegativeVeryThinSpace"] = "​", -- U+0200B
+ ["NestedGreaterGreater"] = "≫", -- U+0226B
+ ["NestedLessLess"] = "≪", -- U+0226A
+ ["Nfr"] = "𝔑", -- U+1D511
+ ["Ngr"] = "Ν", -- U+0039D
+ ["NoBreak"] = "⁠", -- U+02060
+ ["NonBreakingSpace"] = " ", -- U+000A0
+ ["Nopf"] = "ℕ", -- U+02115
+ ["Not"] = "⫬", -- U+02AEC
+ ["NotCongruent"] = "≢", -- U+02262
+ ["NotCupCap"] = "≭", -- U+0226D
+ ["NotDoubleVerticalBar"] = "∦", -- U+02226
+ ["NotElement"] = "∉", -- U+02209
+ ["NotEqual"] = "≠", -- U+02260
+ ["NotEqualTilde"] = "≂̸", -- U+02242 00338
+ ["NotExists"] = "∄", -- U+02204
+ ["NotGreater"] = "≯", -- U+0226F
+ ["NotGreaterEqual"] = "≱", -- U+02271
+ ["NotGreaterFullEqual"] = "≧̸", -- U+02267 00338
+ ["NotGreaterGreater"] = "≫̸", -- U+0226B 00338
+ ["NotGreaterLess"] = "≹", -- U+02279
+ ["NotGreaterSlantEqual"] = "⩾̸", -- U+02A7E 00338
+ ["NotGreaterTilde"] = "≵", -- U+02275
+ ["NotHumpDownHump"] = "≎̸", -- U+0224E 00338
+ ["NotHumpEqual"] = "≏̸", -- U+0224F 00338
+ ["NotLeftTriangle"] = "⋪", -- U+022EA
+ ["NotLeftTriangleBar"] = "⧏̸", -- U+029CF 00338
+ ["NotLeftTriangleEqual"] = "⋬", -- U+022EC
+ ["NotLess"] = "≮", -- U+0226E
+ ["NotLessEqual"] = "≰", -- U+02270
+ ["NotLessGreater"] = "≸", -- U+02278
+ ["NotLessLess"] = "≪̸", -- U+0226A 00338
+ ["NotLessSlantEqual"] = "⩽̸", -- U+02A7D 00338
+ ["NotLessTilde"] = "≴", -- U+02274
+ ["NotNestedGreaterGreater"] = "⪢̸", -- U+02AA2 00338
+ ["NotNestedLessLess"] = "⪡̸", -- U+02AA1 00338
+ ["NotPrecedes"] = "⊀", -- U+02280
+ ["NotPrecedesEqual"] = "⪯̸", -- U+02AAF 00338
+ ["NotPrecedesSlantEqual"] = "⋠", -- U+022E0
+ ["NotReverseElement"] = "∌", -- U+0220C
+ ["NotRightTriangle"] = "⋫", -- U+022EB
+ ["NotRightTriangleBar"] = "⧐̸", -- U+029D0 00338
+ ["NotRightTriangleEqual"] = "⋭", -- U+022ED
+ ["NotSquareSubset"] = "⊏̸", -- U+0228F 00338
+ ["NotSquareSubsetEqual"] = "⋢", -- U+022E2
+ ["NotSquareSuperset"] = "⊐̸", -- U+02290 00338
+ ["NotSquareSupersetEqual"] = "⋣", -- U+022E3
+ ["NotSubset"] = "⊂⃒", -- U+02282 020D2
+ ["NotSubsetEqual"] = "⊈", -- U+02288
+ ["NotSucceeds"] = "⊁", -- U+02281
+ ["NotSucceedsEqual"] = "⪰̸", -- U+02AB0 00338
+ ["NotSucceedsSlantEqual"] = "⋡", -- U+022E1
+ ["NotSucceedsTilde"] = "≿̸", -- U+0227F 00338
+ ["NotSuperset"] = "⊃⃒", -- U+02283 020D2
+ ["NotSupersetEqual"] = "⊉", -- U+02289
+ ["NotTilde"] = "≁", -- U+02241
+ ["NotTildeEqual"] = "≄", -- U+02244
+ ["NotTildeFullEqual"] = "≇", -- U+02247
+ ["NotTildeTilde"] = "≉", -- U+02249
+ ["NotVerticalBar"] = "∤", -- U+02224
+ ["Nscr"] = "𝒩", -- U+1D4A9
+ ["Ntilde"] = "Ñ", -- U+000D1
+ ["Nu"] = "Ν", -- U+0039D
+ ["OElig"] = "Œ", -- U+00152
+ ["OHacgr"] = "Ώ", -- U+0038F
+ ["OHgr"] = "Ω", -- U+003A9
+ ["Oacgr"] = "Ό", -- U+0038C
+ ["Oacute"] = "Ó", -- U+000D3
+ ["Ocirc"] = "Ô", -- U+000D4
+ ["Ocy"] = "О", -- U+0041E
+ ["Odblac"] = "Ő", -- U+00150
+ ["Ofr"] = "𝔒", -- U+1D512
+ ["Ogr"] = "Ο", -- U+0039F
+ ["Ograve"] = "Ò", -- U+000D2
+ ["Omacr"] = "Ō", -- U+0014C
+ ["Omega"] = "Ω", -- U+003A9
+ ["Omicron"] = "Ο", -- U+0039F
+ ["Oopf"] = "𝕆", -- U+1D546
+ ["OpenCurlyDoubleQuote"] = "“", -- U+0201C
+ ["OpenCurlyQuote"] = "‘", -- U+02018
+ ["Or"] = "⩔", -- U+02A54
+ ["Oscr"] = "𝒪", -- U+1D4AA
+ ["Oslash"] = "Ø", -- U+000D8
+ ["Otilde"] = "Õ", -- U+000D5
+ ["Otimes"] = "⨷", -- U+02A37
+ ["Ouml"] = "Ö", -- U+000D6
+ ["OverBar"] = "‾", -- U+0203E
+ ["OverBrace"] = "⏞", -- U+023DE
+ ["OverBracket"] = "⎴", -- U+023B4
+ ["OverParenthesis"] = "⏜", -- U+023DC
+ ["PHgr"] = "Φ", -- U+003A6
+ ["PSgr"] = "Ψ", -- U+003A8
+ ["PartialD"] = "∂", -- U+02202
+ ["Pcy"] = "П", -- U+0041F
+ ["Pfr"] = "𝔓", -- U+1D513
+ ["Pgr"] = "Π", -- U+003A0
+ ["Phi"] = "Φ", -- U+003A6
+ ["Pi"] = "Π", -- U+003A0
+ ["PlusMinus"] = "±", -- U+000B1
+ ["Poincareplane"] = "ℌ", -- U+0210C
+ ["Popf"] = "ℙ", -- U+02119
+ ["Pr"] = "⪻", -- U+02ABB
+ ["Precedes"] = "≺", -- U+0227A
+ ["PrecedesEqual"] = "⪯", -- U+02AAF
+ ["PrecedesSlantEqual"] = "≼", -- U+0227C
+ ["PrecedesTilde"] = "≾", -- U+0227E
+ ["Prime"] = "″", -- U+02033
+ ["Product"] = "∏", -- U+0220F
+ ["Proportion"] = "∷", -- U+02237
+ ["Proportional"] = "∝", -- U+0221D
+ ["Pscr"] = "𝒫", -- U+1D4AB
+ ["Psi"] = "Ψ", -- U+003A8
+ ["QUOT"] = "\"", -- U+00022
+ ["Qfr"] = "𝔔", -- U+1D514
+ ["Qopf"] = "ℚ", -- U+0211A
+ ["Qscr"] = "𝒬", -- U+1D4AC
+ ["RBarr"] = "⤐", -- U+02910
+ ["REG"] = "®", -- U+000AE
+ ["Racute"] = "Ŕ", -- U+00154
+ ["Rang"] = "⟫", -- U+027EB
+ ["Rarr"] = "↠", -- U+021A0
+ ["Rarrtl"] = "⤖", -- U+02916
+ ["Rcaron"] = "Ř", -- U+00158
+ ["Rcedil"] = "Ŗ", -- U+00156
+ ["Rcy"] = "Р", -- U+00420
+ ["Re"] = "ℜ", -- U+0211C
+ ["ReverseElement"] = "∋", -- U+0220B
+ ["ReverseEquilibrium"] = "⇋", -- U+021CB
+ ["ReverseUpEquilibrium"] = "⥯", -- U+0296F
+ ["Rfr"] = "ℜ", -- U+0211C
+ ["Rgr"] = "Ρ", -- U+003A1
+ ["Rho"] = "Ρ", -- U+003A1
+ ["RightAngleBracket"] = "⟩", -- U+027E9
+ ["RightArrow"] = "→", -- U+02192
+ ["RightArrowBar"] = "⇥", -- U+021E5
+ ["RightArrowLeftArrow"] = "⇄", -- U+021C4
+ ["RightCeiling"] = "⌉", -- U+02309
+ ["RightDoubleBracket"] = "⟧", -- U+027E7
+ ["RightDownTeeVector"] = "⥝", -- U+0295D
+ ["RightDownVector"] = "⇂", -- U+021C2
+ ["RightDownVectorBar"] = "⥕", -- U+02955
+ ["RightFloor"] = "⌋", -- U+0230B
+ ["RightTee"] = "⊢", -- U+022A2
+ ["RightTeeArrow"] = "↦", -- U+021A6
+ ["RightTeeVector"] = "⥛", -- U+0295B
+ ["RightTriangle"] = "⊳", -- U+022B3
+ ["RightTriangleBar"] = "⧐", -- U+029D0
+ ["RightTriangleEqual"] = "⊵", -- U+022B5
+ ["RightUpDownVector"] = "⥏", -- U+0294F
+ ["RightUpTeeVector"] = "⥜", -- U+0295C
+ ["RightUpVector"] = "↾", -- U+021BE
+ ["RightUpVectorBar"] = "⥔", -- U+02954
+ ["RightVector"] = "⇀", -- U+021C0
+ ["RightVectorBar"] = "⥓", -- U+02953
+ ["Rightarrow"] = "⇒", -- U+021D2
+ ["Ropf"] = "ℝ", -- U+0211D
+ ["RoundImplies"] = "⥰", -- U+02970
+ ["Rrightarrow"] = "⇛", -- U+021DB
+ ["Rscr"] = "ℛ", -- U+0211B
+ ["Rsh"] = "↱", -- U+021B1
+ ["RuleDelayed"] = "⧴", -- U+029F4
+ ["SHCHcy"] = "Щ", -- U+00429
+ ["SHcy"] = "Ш", -- U+00428
+ ["SOFTcy"] = "Ь", -- U+0042C
+ ["Sacute"] = "Ś", -- U+0015A
+ ["Sc"] = "⪼", -- U+02ABC
+ ["Scaron"] = "Š", -- U+00160
+ ["Scedil"] = "Ş", -- U+0015E
+ ["Scirc"] = "Ŝ", -- U+0015C
+ ["Scy"] = "С", -- U+00421
+ ["Sfr"] = "𝔖", -- U+1D516
+ ["Sgr"] = "Σ", -- U+003A3
+ ["ShortDownArrow"] = "↓", -- U+02193
+ ["ShortLeftArrow"] = "←", -- U+02190
+ ["ShortRightArrow"] = "→", -- U+02192
+ ["ShortUpArrow"] = "↑", -- U+02191
+ ["Sigma"] = "Σ", -- U+003A3
+ ["SmallCircle"] = "∘", -- U+02218
+ ["Sopf"] = "𝕊", -- U+1D54A
+ ["Sqrt"] = "√", -- U+0221A
+ ["Square"] = "□", -- U+025A1
+ ["SquareIntersection"] = "⊓", -- U+02293
+ ["SquareSubset"] = "⊏", -- U+0228F
+ ["SquareSubsetEqual"] = "⊑", -- U+02291
+ ["SquareSuperset"] = "⊐", -- U+02290
+ ["SquareSupersetEqual"] = "⊒", -- U+02292
+ ["SquareUnion"] = "⊔", -- U+02294
+ ["Sscr"] = "𝒮", -- U+1D4AE
+ ["Star"] = "⋆", -- U+022C6
+ ["Sub"] = "⋐", -- U+022D0
+ ["Subset"] = "⋐", -- U+022D0
+ ["SubsetEqual"] = "⊆", -- U+02286
+ ["Succeeds"] = "≻", -- U+0227B
+ ["SucceedsEqual"] = "⪰", -- U+02AB0
+ ["SucceedsSlantEqual"] = "≽", -- U+0227D
+ ["SucceedsTilde"] = "≿", -- U+0227F
+ ["SuchThat"] = "∋", -- U+0220B
+ ["Sum"] = "∑", -- U+02211
+ ["Sup"] = "⋑", -- U+022D1
+ ["Superset"] = "⊃", -- U+02283
+ ["SupersetEqual"] = "⊇", -- U+02287
+ ["Supset"] = "⋑", -- U+022D1
+ ["THORN"] = "Þ", -- U+000DE
+ ["THgr"] = "Θ", -- U+00398
+ ["TRADE"] = "™", -- U+02122
+ ["TSHcy"] = "Ћ", -- U+0040B
+ ["TScy"] = "Ц", -- U+00426
+ ["Tab"] = "\9", -- U+00009
+ ["Tau"] = "Τ", -- U+003A4
+ ["Tcaron"] = "Ť", -- U+00164
+ ["Tcedil"] = "Ţ", -- U+00162
+ ["Tcy"] = "Т", -- U+00422
+ ["Tfr"] = "𝔗", -- U+1D517
+ ["Tgr"] = "Τ", -- U+003A4
+ ["Therefore"] = "∴", -- U+02234
+ ["Theta"] = "Θ", -- U+00398
+ ["ThickSpace"] = "  ", -- U+0205F 0200A
+ ["ThinSpace"] = " ", -- U+02009
+ ["Tilde"] = "∼", -- U+0223C
+ ["TildeEqual"] = "≃", -- U+02243
+ ["TildeFullEqual"] = "≅", -- U+02245
+ ["TildeTilde"] = "≈", -- U+02248
+ ["Topf"] = "𝕋", -- U+1D54B
+ ["TripleDot"] = "⃛", -- U+020DB
+ ["Tscr"] = "𝒯", -- U+1D4AF
+ ["Tstrok"] = "Ŧ", -- U+00166
+ ["Uacgr"] = "Ύ", -- U+0038E
+ ["Uacute"] = "Ú", -- U+000DA
+ ["Uarr"] = "↟", -- U+0219F
+ ["Uarrocir"] = "⥉", -- U+02949
+ ["Ubrcy"] = "Ў", -- U+0040E
+ ["Ubreve"] = "Ŭ", -- U+0016C
+ ["Ucirc"] = "Û", -- U+000DB
+ ["Ucy"] = "У", -- U+00423
+ ["Udblac"] = "Ű", -- U+00170
+ ["Udigr"] = "Ϋ", -- U+003AB
+ ["Ufr"] = "𝔘", -- U+1D518
+ ["Ugr"] = "Υ", -- U+003A5
+ ["Ugrave"] = "Ù", -- U+000D9
+ ["Umacr"] = "Ū", -- U+0016A
+ -- ["UnderBar"] = "_", -- U+0005F
+ ["UnderBar"] = "‾", -- U+0203E
+ ["UnderBrace"] = "⏟", -- U+023DF
+ ["UnderBracket"] = "⎵", -- U+023B5
+ ["UnderParenthesis"] = "⏝", -- U+023DD
+ ["Union"] = "⋃", -- U+022C3
+ ["UnionPlus"] = "⊎", -- U+0228E
+ ["Uogon"] = "Ų", -- U+00172
+ ["Uopf"] = "𝕌", -- U+1D54C
+ ["UpArrow"] = "↑", -- U+02191
+ ["UpArrowBar"] = "⤒", -- U+02912
+ ["UpArrowDownArrow"] = "⇅", -- U+021C5
+ ["UpDownArrow"] = "↕", -- U+02195
+ ["UpEquilibrium"] = "⥮", -- U+0296E
+ ["UpTee"] = "⊥", -- U+022A5
+ ["UpTeeArrow"] = "↥", -- U+021A5
+ ["Uparrow"] = "⇑", -- U+021D1
+ ["Updownarrow"] = "⇕", -- U+021D5
+ ["UpperLeftArrow"] = "↖", -- U+02196
+ ["UpperRightArrow"] = "↗", -- U+02197
+ ["Upsi"] = "ϒ", -- U+003D2
+ ["Upsilon"] = "Υ", -- U+003A5
+ ["Uring"] = "Ů", -- U+0016E
+ ["Uscr"] = "𝒰", -- U+1D4B0
+ ["Utilde"] = "Ũ", -- U+00168
+ ["Uuml"] = "Ü", -- U+000DC
+ ["VDash"] = "⊫", -- U+022AB
+ ["Vbar"] = "⫫", -- U+02AEB
+ ["Vcy"] = "В", -- U+00412
+ ["Vdash"] = "⊩", -- U+022A9
+ ["Vdashl"] = "⫦", -- U+02AE6
+ ["Vee"] = "⋁", -- U+022C1
+ ["Verbar"] = "‖", -- U+02016
+ ["Vert"] = "‖", -- U+02016
+ ["VerticalBar"] = "∣", -- U+02223
+ ["VerticalLine"] = "|", -- U+0007C
+ ["VerticalSeparator"] = "❘", -- U+02758
+ ["VerticalTilde"] = "≀", -- U+02240
+ ["VeryThinSpace"] = " ", -- U+0200A
+ ["Vfr"] = "𝔙", -- U+1D519
+ ["Vopf"] = "𝕍", -- U+1D54D
+ ["Vscr"] = "𝒱", -- U+1D4B1
+ ["Vvdash"] = "⊪", -- U+022AA
+ ["Wcirc"] = "Ŵ", -- U+00174
+ ["Wedge"] = "⋀", -- U+022C0
+ ["Wfr"] = "𝔚", -- U+1D51A
+ ["Wopf"] = "𝕎", -- U+1D54E
+ ["Wscr"] = "𝒲", -- U+1D4B2
+ ["Xfr"] = "𝔛", -- U+1D51B
+ ["Xgr"] = "Ξ", -- U+0039E
+ ["Xi"] = "Ξ", -- U+0039E
+ ["Xopf"] = "𝕏", -- U+1D54F
+ ["Xscr"] = "𝒳", -- U+1D4B3
+ ["YAcy"] = "Я", -- U+0042F
+ ["YIcy"] = "Ї", -- U+00407
+ ["YUcy"] = "Ю", -- U+0042E
+ ["Yacute"] = "Ý", -- U+000DD
+ ["Ycirc"] = "Ŷ", -- U+00176
+ ["Ycy"] = "Ы", -- U+0042B
+ ["Yfr"] = "𝔜", -- U+1D51C
+ ["Yopf"] = "𝕐", -- U+1D550
+ ["Yscr"] = "𝒴", -- U+1D4B4
+ ["Yuml"] = "Ÿ", -- U+00178
+ ["ZHcy"] = "Ж", -- U+00416
+ ["Zacute"] = "Ź", -- U+00179
+ ["Zcaron"] = "Ž", -- U+0017D
+ ["Zcy"] = "З", -- U+00417
+ ["Zdot"] = "Ż", -- U+0017B
+ ["ZeroWidthSpace"] = "​", -- U+0200B
+ ["Zeta"] = "Ζ", -- U+00396
+ ["Zfr"] = "ℨ", -- U+02128
+ ["Zgr"] = "Ζ", -- U+00396
+ ["Zopf"] = "ℤ", -- U+02124
+ ["Zscr"] = "𝒵", -- U+1D4B5
+ ["aacgr"] = "ά", -- U+003AC
+ ["aacute"] = "á", -- U+000E1
+ ["abreve"] = "ă", -- U+00103
+ ["ac"] = "∾", -- U+0223E
+ ["acE"] = "∾̳", -- U+0223E 00333
+ ["acd"] = "∿", -- U+0223F
+ ["acirc"] = "â", -- U+000E2
+ ["acute"] = "´", -- U+000B4
+ ["acy"] = "а", -- U+00430
+ ["aelig"] = "æ", -- U+000E6
+ ["af"] = "⁡", -- U+02061
+ ["afr"] = "𝔞", -- U+1D51E
+ ["agr"] = "α", -- U+003B1
+ ["agrave"] = "à", -- U+000E0
+ ["alefsym"] = "ℵ", -- U+02135
+ ["aleph"] = "ℵ", -- U+02135
+ ["alpha"] = "α", -- U+003B1
+ ["amacr"] = "ā", -- U+00101
+ ["amalg"] = "⨿", -- U+02A3F
+ ["amp"] = "&", -- U+00026
+ ["and"] = "∧", -- U+02227
+ ["andand"] = "⩕", -- U+02A55
+ ["andd"] = "⩜", -- U+02A5C
+ ["andslope"] = "⩘", -- U+02A58
+ ["andv"] = "⩚", -- U+02A5A
+ ["ang"] = "∠", -- U+02220
+ ["ange"] = "⦤", -- U+029A4
+ ["angle"] = "∠", -- U+02220
+ ["angmsd"] = "∡", -- U+02221
+ ["angmsdaa"] = "⦨", -- U+029A8
+ ["angmsdab"] = "⦩", -- U+029A9
+ ["angmsdac"] = "⦪", -- U+029AA
+ ["angmsdad"] = "⦫", -- U+029AB
+ ["angmsdae"] = "⦬", -- U+029AC
+ ["angmsdaf"] = "⦭", -- U+029AD
+ ["angmsdag"] = "⦮", -- U+029AE
+ ["angmsdah"] = "⦯", -- U+029AF
+ ["angrt"] = "∟", -- U+0221F
+ ["angrtvb"] = "⊾", -- U+022BE
+ ["angrtvbd"] = "⦝", -- U+0299D
+ ["angsph"] = "∢", -- U+02222
+ ["angst"] = "Å", -- U+000C5
+ ["angzarr"] = "⍼", -- U+0237C
+ ["aogon"] = "ą", -- U+00105
+ ["aopf"] = "𝕒", -- U+1D552
+ ["ap"] = "≈", -- U+02248
+ ["apE"] = "⩰", -- U+02A70
+ ["apacir"] = "⩯", -- U+02A6F
+ ["ape"] = "≊", -- U+0224A
+ ["apid"] = "≋", -- U+0224B
+ ["apos"] = "'", -- U+00027
+ ["approx"] = "≈", -- U+02248
+ ["approxeq"] = "≊", -- U+0224A
+ ["aring"] = "å", -- U+000E5
+ ["ascr"] = "𝒶", -- U+1D4B6
+ ["ast"] = "*", -- U+0002A
+ ["asymp"] = "≈", -- U+02248
+ ["asympeq"] = "≍", -- U+0224D
+ ["atilde"] = "ã", -- U+000E3
+ ["auml"] = "ä", -- U+000E4
+ ["awconint"] = "∳", -- U+02233
+ ["awint"] = "⨑", -- U+02A11
+ ["b.Delta"] = "𝚫", -- U+1D6AB
+ ["b.Gamma"] = "𝚪", -- U+1D6AA
+ ["b.Gammad"] = "𝟊", -- U+1D7CA
+ ["b.Lambda"] = "𝚲", -- U+1D6B2
+ ["b.Omega"] = "𝛀", -- U+1D6C0
+ ["b.Phi"] = "𝚽", -- U+1D6BD
+ ["b.Pi"] = "𝚷", -- U+1D6B7
+ ["b.Psi"] = "𝚿", -- U+1D6BF
+ ["b.Sigma"] = "𝚺", -- U+1D6BA
+ ["b.Theta"] = "𝚯", -- U+1D6AF
+ ["b.Upsi"] = "𝚼", -- U+1D6BC
+ ["b.Xi"] = "𝚵", -- U+1D6B5
+ ["b.alpha"] = "𝛂", -- U+1D6C2
+ ["b.beta"] = "𝛃", -- U+1D6C3
+ ["b.chi"] = "𝛘", -- U+1D6D8
+ ["b.delta"] = "𝛅", -- U+1D6C5
+ ["b.epsi"] = "𝛆", -- U+1D6C6
+ ["b.epsiv"] = "𝛜", -- U+1D6DC
+ ["b.eta"] = "𝛈", -- U+1D6C8
+ ["b.gamma"] = "𝛄", -- U+1D6C4
+ ["b.gammad"] = "𝟋", -- U+1D7CB
+ ["b.iota"] = "𝛊", -- U+1D6CA
+ ["b.kappa"] = "𝛋", -- U+1D6CB
+ ["b.kappav"] = "𝛞", -- U+1D6DE
+ ["b.lambda"] = "𝛌", -- U+1D6CC
+ ["b.mu"] = "𝛍", -- U+1D6CD
+ ["b.nu"] = "𝛎", -- U+1D6CE
+ ["b.omega"] = "𝛚", -- U+1D6DA
+ ["b.phi"] = "𝛗", -- U+1D6D7
+ ["b.phiv"] = "𝛟", -- U+1D6DF
+ ["b.pi"] = "𝛑", -- U+1D6D1
+ ["b.piv"] = "𝛡", -- U+1D6E1
+ ["b.psi"] = "𝛙", -- U+1D6D9
+ ["b.rho"] = "𝛒", -- U+1D6D2
+ ["b.rhov"] = "𝛠", -- U+1D6E0
+ ["b.sigma"] = "𝛔", -- U+1D6D4
+ ["b.sigmav"] = "𝛓", -- U+1D6D3
+ ["b.tau"] = "𝛕", -- U+1D6D5
+ ["b.thetas"] = "𝛉", -- U+1D6C9
+ ["b.thetav"] = "𝛝", -- U+1D6DD
+ ["b.upsi"] = "𝛖", -- U+1D6D6
+ ["b.xi"] = "𝛏", -- U+1D6CF
+ ["b.zeta"] = "𝛇", -- U+1D6C7
+ ["bNot"] = "⫭", -- U+02AED
+ ["backcong"] = "≌", -- U+0224C
+ ["backepsilon"] = "϶", -- U+003F6
+ ["backprime"] = "‵", -- U+02035
+ ["backsim"] = "∽", -- U+0223D
+ ["backsimeq"] = "⋍", -- U+022CD
+ ["barvee"] = "⊽", -- U+022BD
+ ["barwed"] = "⌅", -- U+02305
+ ["barwedge"] = "⌅", -- U+02305
+ ["bbrk"] = "⎵", -- U+023B5
+ ["bbrktbrk"] = "⎶", -- U+023B6
+ ["bcong"] = "≌", -- U+0224C
+ ["bcy"] = "б", -- U+00431
+ ["bdquo"] = "„", -- U+0201E
+ ["becaus"] = "∵", -- U+02235
+ ["because"] = "∵", -- U+02235
+ ["bemptyv"] = "⦰", -- U+029B0
+ ["bepsi"] = "϶", -- U+003F6
+ ["bernou"] = "ℬ", -- U+0212C
+ ["beta"] = "β", -- U+003B2
+ ["beth"] = "ℶ", -- U+02136
+ ["between"] = "≬", -- U+0226C
+ ["bfr"] = "𝔟", -- U+1D51F
+ ["bgr"] = "β", -- U+003B2
+ ["bigcap"] = "⋂", -- U+022C2
+ ["bigcirc"] = "◯", -- U+025EF
+ ["bigcup"] = "⋃", -- U+022C3
+ ["bigodot"] = "⨀", -- U+02A00
+ ["bigoplus"] = "⨁", -- U+02A01
+ ["bigotimes"] = "⨂", -- U+02A02
+ ["bigsqcup"] = "⨆", -- U+02A06
+ ["bigstar"] = "★", -- U+02605
+ ["bigtriangledown"] = "▽", -- U+025BD
+ ["bigtriangleup"] = "△", -- U+025B3
+ ["biguplus"] = "⨄", -- U+02A04
+ ["bigvee"] = "⋁", -- U+022C1
+ ["bigwedge"] = "⋀", -- U+022C0
+ ["bkarow"] = "⤍", -- U+0290D
+ ["blacklozenge"] = "⧫", -- U+029EB
+ ["blacksquare"] = "▪", -- U+025AA
+ ["blacktriangle"] = "▴", -- U+025B4
+ ["blacktriangledown"] = "▾", -- U+025BE
+ ["blacktriangleleft"] = "◂", -- U+025C2
+ ["blacktriangleright"] = "▸", -- U+025B8
+ ["blank"] = "␣", -- U+02423
+ ["blk12"] = "▒", -- U+02592
+ ["blk14"] = "░", -- U+02591
+ ["blk34"] = "▓", -- U+02593
+ ["block"] = "█", -- U+02588
+ ["bne"] = "=⃥", -- U+0003D 020E5
+ ["bnequiv"] = "≡⃥", -- U+02261 020E5
+ ["bnot"] = "⌐", -- U+02310
+ ["bopf"] = "𝕓", -- U+1D553
+ ["bot"] = "⊥", -- U+022A5
+ ["bottom"] = "⊥", -- U+022A5
+ ["bowtie"] = "⋈", -- U+022C8
+ ["boxDL"] = "╗", -- U+02557
+ ["boxDR"] = "╔", -- U+02554
+ ["boxDl"] = "╖", -- U+02556
+ ["boxDr"] = "╓", -- U+02553
+ ["boxH"] = "═", -- U+02550
+ ["boxHD"] = "╦", -- U+02566
+ ["boxHU"] = "╩", -- U+02569
+ ["boxHd"] = "╤", -- U+02564
+ ["boxHu"] = "╧", -- U+02567
+ ["boxUL"] = "╝", -- U+0255D
+ ["boxUR"] = "╚", -- U+0255A
+ ["boxUl"] = "╜", -- U+0255C
+ ["boxUr"] = "╙", -- U+02559
+ ["boxV"] = "║", -- U+02551
+ ["boxVH"] = "╬", -- U+0256C
+ ["boxVL"] = "╣", -- U+02563
+ ["boxVR"] = "╠", -- U+02560
+ ["boxVh"] = "╫", -- U+0256B
+ ["boxVl"] = "╢", -- U+02562
+ ["boxVr"] = "╟", -- U+0255F
+ ["boxbox"] = "⧉", -- U+029C9
+ ["boxdL"] = "╕", -- U+02555
+ ["boxdR"] = "╒", -- U+02552
+ ["boxdl"] = "┐", -- U+02510
+ ["boxdr"] = "┌", -- U+0250C
+ ["boxh"] = "─", -- U+02500
+ ["boxhD"] = "╥", -- U+02565
+ ["boxhU"] = "╨", -- U+02568
+ ["boxhd"] = "┬", -- U+0252C
+ ["boxhu"] = "┴", -- U+02534
+ ["boxminus"] = "⊟", -- U+0229F
+ ["boxplus"] = "⊞", -- U+0229E
+ ["boxtimes"] = "⊠", -- U+022A0
+ ["boxuL"] = "╛", -- U+0255B
+ ["boxuR"] = "╘", -- U+02558
+ ["boxul"] = "┘", -- U+02518
+ ["boxur"] = "└", -- U+02514
+ ["boxv"] = "│", -- U+02502
+ ["boxvH"] = "╪", -- U+0256A
+ ["boxvL"] = "╡", -- U+02561
+ ["boxvR"] = "╞", -- U+0255E
+ ["boxvh"] = "┼", -- U+0253C
+ ["boxvl"] = "┤", -- U+02524
+ ["boxvr"] = "├", -- U+0251C
+ ["bprime"] = "‵", -- U+02035
+ ["breve"] = "˘", -- U+002D8
+ ["brvbar"] = "¦", -- U+000A6
+ ["bscr"] = "𝒷", -- U+1D4B7
+ ["bsemi"] = "⁏", -- U+0204F
+ ["bsim"] = "∽", -- U+0223D
+ ["bsime"] = "⋍", -- U+022CD
+ ["bsol"] = "\\", -- U+0005C
+ ["bsolb"] = "⧅", -- U+029C5
+ ["bsolhsub"] = "⟈", -- U+027C8
+ ["bull"] = "•", -- U+02022
+ ["bullet"] = "•", -- U+02022
+ ["bump"] = "≎", -- U+0224E
+ ["bumpE"] = "⪮", -- U+02AAE
+ ["bumpe"] = "≏", -- U+0224F
+ ["bumpeq"] = "≏", -- U+0224F
+ ["cacute"] = "ć", -- U+00107
+ ["cap"] = "∩", -- U+02229
+ ["capand"] = "⩄", -- U+02A44
+ ["capbrcup"] = "⩉", -- U+02A49
+ ["capcap"] = "⩋", -- U+02A4B
+ ["capcup"] = "⩇", -- U+02A47
+ ["capdot"] = "⩀", -- U+02A40
+ ["caps"] = "∩︀", -- U+02229 0FE00
+ ["caret"] = "⁁", -- U+02041
+ ["caron"] = "ˇ", -- U+002C7
+ ["ccaps"] = "⩍", -- U+02A4D
+ ["ccaron"] = "č", -- U+0010D
+ ["ccedil"] = "ç", -- U+000E7
+ ["ccirc"] = "ĉ", -- U+00109
+ ["ccups"] = "⩌", -- U+02A4C
+ ["ccupssm"] = "⩐", -- U+02A50
+ ["cdot"] = "ċ", -- U+0010B
+ ["cedil"] = "¸", -- U+000B8
+ ["cemptyv"] = "⦲", -- U+029B2
+ ["cent"] = "¢", -- U+000A2
+ ["centerdot"] = "·", -- U+000B7
+ ["cfr"] = "𝔠", -- U+1D520
+ ["chcy"] = "ч", -- U+00447
+ ["check"] = "✓", -- U+02713
+ ["checkmark"] = "✓", -- U+02713
+ ["chi"] = "χ", -- U+003C7
+ ["cir"] = "○", -- U+025CB
+ ["cirE"] = "⧃", -- U+029C3
+ ["circ"] = "ˆ", -- U+002C6
+ ["circeq"] = "≗", -- U+02257
+ ["circlearrowleft"] = "↺", -- U+021BA
+ ["circlearrowright"] = "↻", -- U+021BB
+ ["circledR"] = "®", -- U+000AE
+ ["circledS"] = "Ⓢ", -- U+024C8
+ ["circledast"] = "⊛", -- U+0229B
+ ["circledcirc"] = "⊚", -- U+0229A
+ ["circleddash"] = "⊝", -- U+0229D
+ ["cire"] = "≗", -- U+02257
+ ["cirfnint"] = "⨐", -- U+02A10
+ ["cirmid"] = "⫯", -- U+02AEF
+ ["cirscir"] = "⧂", -- U+029C2
+ ["clubs"] = "♣", -- U+02663
+ ["clubsuit"] = "♣", -- U+02663
+ ["colon"] = ":", -- U+0003A
+ ["colone"] = "≔", -- U+02254
+ ["coloneq"] = "≔", -- U+02254
+ ["comma"] = ",", -- U+0002C
+ ["commat"] = "@", -- U+00040
+ ["comp"] = "∁", -- U+02201
+ ["compfn"] = "∘", -- U+02218
+ ["complement"] = "∁", -- U+02201
+ ["complexes"] = "ℂ", -- U+02102
+ ["cong"] = "≅", -- U+02245
+ ["congdot"] = "⩭", -- U+02A6D
+ ["conint"] = "∮", -- U+0222E
+ ["copf"] = "𝕔", -- U+1D554
+ ["coprod"] = "∐", -- U+02210
+ ["copy"] = "©", -- U+000A9
+ ["copysr"] = "℗", -- U+02117
+ ["crarr"] = "↵", -- U+021B5
+ ["cross"] = "✗", -- U+02717
+ ["cscr"] = "𝒸", -- U+1D4B8
+ ["csub"] = "⫏", -- U+02ACF
+ ["csube"] = "⫑", -- U+02AD1
+ ["csup"] = "⫐", -- U+02AD0
+ ["csupe"] = "⫒", -- U+02AD2
+ ["ctdot"] = "⋯", -- U+022EF
+ ["cudarrl"] = "⤸", -- U+02938
+ ["cudarrr"] = "⤵", -- U+02935
+ ["cuepr"] = "⋞", -- U+022DE
+ ["cuesc"] = "⋟", -- U+022DF
+ ["cularr"] = "↶", -- U+021B6
+ ["cularrp"] = "⤽", -- U+0293D
+ ["cup"] = "∪", -- U+0222A
+ ["cupbrcap"] = "⩈", -- U+02A48
+ ["cupcap"] = "⩆", -- U+02A46
+ ["cupcup"] = "⩊", -- U+02A4A
+ ["cupdot"] = "⊍", -- U+0228D
+ ["cupor"] = "⩅", -- U+02A45
+ ["cups"] = "∪︀", -- U+0222A 0FE00
+ ["curarr"] = "↷", -- U+021B7
+ ["curarrm"] = "⤼", -- U+0293C
+ ["curlyeqprec"] = "⋞", -- U+022DE
+ ["curlyeqsucc"] = "⋟", -- U+022DF
+ ["curlyvee"] = "⋎", -- U+022CE
+ ["curlywedge"] = "⋏", -- U+022CF
+ ["curren"] = "¤", -- U+000A4
+ ["curvearrowleft"] = "↶", -- U+021B6
+ ["curvearrowright"] = "↷", -- U+021B7
+ ["cuvee"] = "⋎", -- U+022CE
+ ["cuwed"] = "⋏", -- U+022CF
+ ["cwconint"] = "∲", -- U+02232
+ ["cwint"] = "∱", -- U+02231
+ ["cylcty"] = "⌭", -- U+0232D
+ ["dArr"] = "⇓", -- U+021D3
+ ["dHar"] = "⥥", -- U+02965
+ ["dagger"] = "†", -- U+02020
+ ["daleth"] = "ℸ", -- U+02138
+ ["darr"] = "↓", -- U+02193
+ ["dash"] = "‐", -- U+02010
+ ["dashv"] = "⊣", -- U+022A3
+ ["dbkarow"] = "⤏", -- U+0290F
+ ["dblac"] = "˝", -- U+002DD
+ ["dcaron"] = "ď", -- U+0010F
+ ["dcy"] = "д", -- U+00434
+ ["dd"] = "ⅆ", -- U+02146
+ ["ddagger"] = "‡", -- U+02021
+ ["ddarr"] = "⇊", -- U+021CA
+ ["ddotseq"] = "⩷", -- U+02A77
+ ["deg"] = "°", -- U+000B0
+ ["delta"] = "δ", -- U+003B4
+ ["demptyv"] = "⦱", -- U+029B1
+ ["dfisht"] = "⥿", -- U+0297F
+ ["dfr"] = "𝔡", -- U+1D521
+ ["dgr"] = "δ", -- U+003B4
+ ["dharl"] = "⇃", -- U+021C3
+ ["dharr"] = "⇂", -- U+021C2
+ ["diam"] = "⋄", -- U+022C4
+ ["diamond"] = "⋄", -- U+022C4
+ ["diamondsuit"] = "♦", -- U+02666
+ ["diams"] = "♦", -- U+02666
+ ["die"] = "¨", -- U+000A8
+ ["digamma"] = "ϝ", -- U+003DD
+ ["disin"] = "⋲", -- U+022F2
+ ["div"] = "÷", -- U+000F7
+ ["divide"] = "÷", -- U+000F7
+ ["divideontimes"] = "⋇", -- U+022C7
+ ["divonx"] = "⋇", -- U+022C7
+ ["djcy"] = "ђ", -- U+00452
+ ["dlcorn"] = "⌞", -- U+0231E
+ ["dlcrop"] = "⌍", -- U+0230D
+ ["dollar"] = "$", -- U+00024
+ ["dopf"] = "𝕕", -- U+1D555
+ ["dot"] = "˙", -- U+002D9
+ ["doteq"] = "≐", -- U+02250
+ ["doteqdot"] = "≑", -- U+02251
+ ["dotminus"] = "∸", -- U+02238
+ ["dotplus"] = "∔", -- U+02214
+ ["dotsquare"] = "⊡", -- U+022A1
+ ["doublebarwedge"] = "⌆", -- U+02306
+ ["downarrow"] = "↓", -- U+02193
+ ["downdownarrows"] = "⇊", -- U+021CA
+ ["downharpoonleft"] = "⇃", -- U+021C3
+ ["downharpoonright"] = "⇂", -- U+021C2
+ ["drbkarow"] = "⤐", -- U+02910
+ ["drcorn"] = "⌟", -- U+0231F
+ ["drcrop"] = "⌌", -- U+0230C
+ ["dscr"] = "𝒹", -- U+1D4B9
+ ["dscy"] = "ѕ", -- U+00455
+ ["dsol"] = "⧶", -- U+029F6
+ ["dstrok"] = "đ", -- U+00111
+ ["dtdot"] = "⋱", -- U+022F1
+ ["dtri"] = "▿", -- U+025BF
+ ["dtrif"] = "▾", -- U+025BE
+ ["duarr"] = "⇵", -- U+021F5
+ ["duhar"] = "⥯", -- U+0296F
+ ["dwangle"] = "⦦", -- U+029A6
+ ["dzcy"] = "џ", -- U+0045F
+ ["dzigrarr"] = "⟿", -- U+027FF
+ ["eDDot"] = "⩷", -- U+02A77
+ ["eDot"] = "≑", -- U+02251
+ ["eacgr"] = "έ", -- U+003AD
+ ["eacute"] = "é", -- U+000E9
+ ["easter"] = "⩮", -- U+02A6E
+ ["ecaron"] = "ě", -- U+0011B
+ ["ecir"] = "≖", -- U+02256
+ ["ecirc"] = "ê", -- U+000EA
+ ["ecolon"] = "≕", -- U+02255
+ ["ecy"] = "э", -- U+0044D
+ ["edot"] = "ė", -- U+00117
+ ["ee"] = "ⅇ", -- U+02147
+ ["eeacgr"] = "ή", -- U+003AE
+ ["eegr"] = "η", -- U+003B7
+ ["efDot"] = "≒", -- U+02252
+ ["efr"] = "𝔢", -- U+1D522
+ ["eg"] = "⪚", -- U+02A9A
+ ["egr"] = "ε", -- U+003B5
+ ["egrave"] = "è", -- U+000E8
+ ["egs"] = "⪖", -- U+02A96
+ ["egsdot"] = "⪘", -- U+02A98
+ ["el"] = "⪙", -- U+02A99
+ ["elinters"] = "⏧", -- U+023E7
+ ["ell"] = "ℓ", -- U+02113
+ ["els"] = "⪕", -- U+02A95
+ ["elsdot"] = "⪗", -- U+02A97
+ ["emacr"] = "ē", -- U+00113
+ ["empty"] = "∅", -- U+02205
+ ["emptyset"] = "∅", -- U+02205
+ ["emptyv"] = "∅", -- U+02205
+ ["emsp"] = " ", -- U+02003
+ ["emsp13"] = " ", -- U+02004
+ ["emsp14"] = " ", -- U+02005
+ ["eng"] = "ŋ", -- U+0014B
+ ["ensp"] = " ", -- U+02002
+ ["eogon"] = "ę", -- U+00119
+ ["eopf"] = "𝕖", -- U+1D556
+ ["epar"] = "⋕", -- U+022D5
+ ["eparsl"] = "⧣", -- U+029E3
+ ["eplus"] = "⩱", -- U+02A71
+ ["epsi"] = "ε", -- U+003B5
+ ["epsilon"] = "ε", -- U+003B5
+ ["epsiv"] = "ϵ", -- U+003F5
+ ["eqcirc"] = "≖", -- U+02256
+ ["eqcolon"] = "≕", -- U+02255
+ ["eqsim"] = "≂", -- U+02242
+ ["eqslantgtr"] = "⪖", -- U+02A96
+ ["eqslantless"] = "⪕", -- U+02A95
+ ["equals"] = "=", -- U+0003D
+ ["equest"] = "≟", -- U+0225F
+ ["equiv"] = "≡", -- U+02261
+ ["equivDD"] = "⩸", -- U+02A78
+ ["eqvparsl"] = "⧥", -- U+029E5
+ ["erDot"] = "≓", -- U+02253
+ ["erarr"] = "⥱", -- U+02971
+ ["escr"] = "ℯ", -- U+0212F
+ ["esdot"] = "≐", -- U+02250
+ ["esim"] = "≂", -- U+02242
+ ["eta"] = "η", -- U+003B7
+ ["eth"] = "ð", -- U+000F0
+ ["euml"] = "ë", -- U+000EB
+ ["euro"] = "€", -- U+020AC
+ ["excl"] = "!", -- U+00021
+ ["exist"] = "∃", -- U+02203
+ ["expectation"] = "ℰ", -- U+02130
+ ["exponentiale"] = "ⅇ", -- U+02147
+ ["fallingdotseq"] = "≒", -- U+02252
+ ["fcy"] = "ф", -- U+00444
+ ["female"] = "♀", -- U+02640
+ ["ffilig"] = "ffi", -- U+0FB03
+ ["fflig"] = "ff", -- U+0FB00
+ ["ffllig"] = "ffl", -- U+0FB04
+ ["ffr"] = "𝔣", -- U+1D523
+ ["filig"] = "fi", -- U+0FB01
+ ["fjlig"] = "fj", -- U+00066 0006A
+ ["flat"] = "♭", -- U+0266D
+ ["fllig"] = "fl", -- U+0FB02
+ ["fltns"] = "▱", -- U+025B1
+ ["fnof"] = "ƒ", -- U+00192
+ ["fopf"] = "𝕗", -- U+1D557
+ ["forall"] = "∀", -- U+02200
+ ["fork"] = "⋔", -- U+022D4
+ ["forkv"] = "⫙", -- U+02AD9
+ ["fpartint"] = "⨍", -- U+02A0D
+ ["frac12"] = "½", -- U+000BD
+ ["frac13"] = "⅓", -- U+02153
+ ["frac14"] = "¼", -- U+000BC
+ ["frac15"] = "⅕", -- U+02155
+ ["frac16"] = "⅙", -- U+02159
+ ["frac18"] = "⅛", -- U+0215B
+ ["frac23"] = "⅔", -- U+02154
+ ["frac25"] = "⅖", -- U+02156
+ ["frac34"] = "¾", -- U+000BE
+ ["frac35"] = "⅗", -- U+02157
+ ["frac38"] = "⅜", -- U+0215C
+ ["frac45"] = "⅘", -- U+02158
+ ["frac56"] = "⅚", -- U+0215A
+ ["frac58"] = "⅝", -- U+0215D
+ ["frac78"] = "⅞", -- U+0215E
+ ["frasl"] = "⁄", -- U+02044
+ ["frown"] = "⌢", -- U+02322
+ ["fscr"] = "𝒻", -- U+1D4BB
+ ["gE"] = "≧", -- U+02267
+ ["gEl"] = "⪌", -- U+02A8C
+ ["gacute"] = "ǵ", -- U+001F5
+ ["gamma"] = "γ", -- U+003B3
+ ["gammad"] = "ϝ", -- U+003DD
+ ["gap"] = "⪆", -- U+02A86
+ ["gbreve"] = "ğ", -- U+0011F
+ ["gcirc"] = "ĝ", -- U+0011D
+ ["gcy"] = "г", -- U+00433
+ ["gdot"] = "ġ", -- U+00121
+ ["ge"] = "≥", -- U+02265
+ ["gel"] = "⋛", -- U+022DB
+ ["geq"] = "≥", -- U+02265
+ ["geqq"] = "≧", -- U+02267
+ ["geqslant"] = "⩾", -- U+02A7E
+ ["ges"] = "⩾", -- U+02A7E
+ ["gescc"] = "⪩", -- U+02AA9
+ ["gesdot"] = "⪀", -- U+02A80
+ ["gesdoto"] = "⪂", -- U+02A82
+ ["gesdotol"] = "⪄", -- U+02A84
+ ["gesl"] = "⋛︀", -- U+022DB 0FE00
+ ["gesles"] = "⪔", -- U+02A94
+ ["gfr"] = "𝔤", -- U+1D524
+ ["gg"] = "≫", -- U+0226B
+ ["ggg"] = "⋙", -- U+022D9
+ ["ggr"] = "γ", -- U+003B3
+ ["gimel"] = "ℷ", -- U+02137
+ ["gjcy"] = "ѓ", -- U+00453
+ ["gl"] = "≷", -- U+02277
+ ["glE"] = "⪒", -- U+02A92
+ ["gla"] = "⪥", -- U+02AA5
+ ["glj"] = "⪤", -- U+02AA4
+ ["gnE"] = "≩", -- U+02269
+ ["gnap"] = "⪊", -- U+02A8A
+ ["gnapprox"] = "⪊", -- U+02A8A
+ ["gne"] = "⪈", -- U+02A88
+ ["gneq"] = "⪈", -- U+02A88
+ ["gneqq"] = "≩", -- U+02269
+ ["gnsim"] = "⋧", -- U+022E7
+ ["gopf"] = "𝕘", -- U+1D558
+ ["grave"] = "`", -- U+00060
+ ["gscr"] = "ℊ", -- U+0210A
+ ["gsim"] = "≳", -- U+02273
+ ["gsime"] = "⪎", -- U+02A8E
+ ["gsiml"] = "⪐", -- U+02A90
+ ["gt"] = ">", -- U+0003E
+ ["gtcc"] = "⪧", -- U+02AA7
+ ["gtcir"] = "⩺", -- U+02A7A
+ ["gtdot"] = "⋗", -- U+022D7
+ ["gtlPar"] = "⦕", -- U+02995
+ ["gtquest"] = "⩼", -- U+02A7C
+ ["gtrapprox"] = "⪆", -- U+02A86
+ ["gtrarr"] = "⥸", -- U+02978
+ ["gtrdot"] = "⋗", -- U+022D7
+ ["gtreqless"] = "⋛", -- U+022DB
+ ["gtreqqless"] = "⪌", -- U+02A8C
+ ["gtrless"] = "≷", -- U+02277
+ ["gtrsim"] = "≳", -- U+02273
+ ["gvertneqq"] = "≩︀", -- U+02269 0FE00
+ ["gvnE"] = "≩︀", -- U+02269 0FE00
+ ["hArr"] = "⇔", -- U+021D4
+ ["hairsp"] = " ", -- U+0200A
+ ["half"] = "½", -- U+000BD
+ ["hamilt"] = "ℋ", -- U+0210B
+ ["hardcy"] = "ъ", -- U+0044A
+ ["harr"] = "↔", -- U+02194
+ ["harrcir"] = "⥈", -- U+02948
+ ["harrw"] = "↭", -- U+021AD
+ ["hbar"] = "ℏ", -- U+0210F
+ ["hcirc"] = "ĥ", -- U+00125
+ ["hearts"] = "♥", -- U+02665
+ ["heartsuit"] = "♥", -- U+02665
+ ["hellip"] = "…", -- U+02026
+ ["hercon"] = "⊹", -- U+022B9
+ ["hfr"] = "𝔥", -- U+1D525
+ ["hksearow"] = "⤥", -- U+02925
+ ["hkswarow"] = "⤦", -- U+02926
+ ["hoarr"] = "⇿", -- U+021FF
+ ["homtht"] = "∻", -- U+0223B
+ ["hookleftarrow"] = "↩", -- U+021A9
+ ["hookrightarrow"] = "↪", -- U+021AA
+ ["hopf"] = "𝕙", -- U+1D559
+ ["horbar"] = "―", -- U+02015
+ ["hscr"] = "𝒽", -- U+1D4BD
+ ["hslash"] = "ℏ", -- U+0210F
+ ["hstrok"] = "ħ", -- U+00127
+ ["hybull"] = "⁃", -- U+02043
+ ["hyphen"] = "‐", -- U+02010
+ ["iacgr"] = "ί", -- U+003AF
+ ["iacute"] = "í", -- U+000ED
+ ["ic"] = "⁣", -- U+02063
+ ["icirc"] = "î", -- U+000EE
+ ["icy"] = "и", -- U+00438
+ ["idiagr"] = "ΐ", -- U+00390
+ ["idigr"] = "ϊ", -- U+003CA
+ ["iecy"] = "е", -- U+00435
+ ["iexcl"] = "¡", -- U+000A1
+ ["iff"] = "⇔", -- U+021D4
+ ["ifr"] = "𝔦", -- U+1D526
+ ["igr"] = "ι", -- U+003B9
+ ["igrave"] = "ì", -- U+000EC
+ ["ii"] = "ⅈ", -- U+02148
+ ["iiiint"] = "⨌", -- U+02A0C
+ ["iiint"] = "∭", -- U+0222D
+ ["iinfin"] = "⧜", -- U+029DC
+ ["iiota"] = "℩", -- U+02129
+ ["ijlig"] = "ij", -- U+00133
+ ["imacr"] = "ī", -- U+0012B
+ ["image"] = "ℑ", -- U+02111
+ ["imagline"] = "ℐ", -- U+02110
+ ["imagpart"] = "ℑ", -- U+02111
+ ["imath"] = "ı", -- U+00131
+ ["imof"] = "⊷", -- U+022B7
+ ["imped"] = "Ƶ", -- U+001B5
+ ["in"] = "∈", -- U+02208
+ ["incare"] = "℅", -- U+02105
+ ["infin"] = "∞", -- U+0221E
+ ["infintie"] = "⧝", -- U+029DD
+ ["inodot"] = "ı", -- U+00131
+ ["int"] = "∫", -- U+0222B
+ ["intcal"] = "⊺", -- U+022BA
+ ["integers"] = "ℤ", -- U+02124
+ ["intercal"] = "⊺", -- U+022BA
+ ["intlarhk"] = "⨗", -- U+02A17
+ ["intprod"] = "⨼", -- U+02A3C
+ ["iocy"] = "ё", -- U+00451
+ ["iogon"] = "į", -- U+0012F
+ ["iopf"] = "𝕚", -- U+1D55A
+ ["iota"] = "ι", -- U+003B9
+ ["iprod"] = "⨼", -- U+02A3C
+ ["iquest"] = "¿", -- U+000BF
+ ["iscr"] = "𝒾", -- U+1D4BE
+ ["isin"] = "∈", -- U+02208
+ ["isinE"] = "⋹", -- U+022F9
+ ["isindot"] = "⋵", -- U+022F5
+ ["isins"] = "⋴", -- U+022F4
+ ["isinsv"] = "⋳", -- U+022F3
+ ["isinv"] = "∈", -- U+02208
+ ["it"] = "⁢", -- U+02062
+ ["itilde"] = "ĩ", -- U+00129
+ ["iukcy"] = "і", -- U+00456
+ ["iuml"] = "ï", -- U+000EF
+ ["jcirc"] = "ĵ", -- U+00135
+ ["jcy"] = "й", -- U+00439
+ ["jfr"] = "𝔧", -- U+1D527
+ ["jmath"] = "ȷ", -- U+00237
+ ["jopf"] = "𝕛", -- U+1D55B
+ ["jscr"] = "𝒿", -- U+1D4BF
+ ["jsercy"] = "ј", -- U+00458
+ ["jukcy"] = "є", -- U+00454
+ ["kappa"] = "κ", -- U+003BA
+ ["kappav"] = "ϰ", -- U+003F0
+ ["kcedil"] = "ķ", -- U+00137
+ ["kcy"] = "к", -- U+0043A
+ ["kfr"] = "𝔨", -- U+1D528
+ ["kgr"] = "κ", -- U+003BA
+ ["kgreen"] = "ĸ", -- U+00138
+ ["khcy"] = "х", -- U+00445
+ ["khgr"] = "χ", -- U+003C7
+ ["kjcy"] = "ќ", -- U+0045C
+ ["kopf"] = "𝕜", -- U+1D55C
+ ["kscr"] = "𝓀", -- U+1D4C0
+ ["lAarr"] = "⇚", -- U+021DA
+ ["lArr"] = "⇐", -- U+021D0
+ ["lAtail"] = "⤛", -- U+0291B
+ ["lBarr"] = "⤎", -- U+0290E
+ ["lE"] = "≦", -- U+02266
+ ["lEg"] = "⪋", -- U+02A8B
+ ["lHar"] = "⥢", -- U+02962
+ ["lacute"] = "ĺ", -- U+0013A
+ ["laemptyv"] = "⦴", -- U+029B4
+ ["lagran"] = "ℒ", -- U+02112
+ ["lambda"] = "λ", -- U+003BB
+ ["lang"] = "⟨", -- U+027E8
+ ["langd"] = "⦑", -- U+02991
+ ["langle"] = "⟨", -- U+027E8
+ ["lap"] = "⪅", -- U+02A85
+ ["laquo"] = "«", -- U+000AB
+ ["larr"] = "←", -- U+02190
+ ["larrb"] = "⇤", -- U+021E4
+ ["larrbfs"] = "⤟", -- U+0291F
+ ["larrfs"] = "⤝", -- U+0291D
+ ["larrhk"] = "↩", -- U+021A9
+ ["larrlp"] = "↫", -- U+021AB
+ ["larrpl"] = "⤹", -- U+02939
+ ["larrsim"] = "⥳", -- U+02973
+ ["larrtl"] = "↢", -- U+021A2
+ ["lat"] = "⪫", -- U+02AAB
+ ["latail"] = "⤙", -- U+02919
+ ["late"] = "⪭", -- U+02AAD
+ ["lates"] = "⪭︀", -- U+02AAD 0FE00
+ ["lbarr"] = "⤌", -- U+0290C
+ ["lbbrk"] = "❲", -- U+02772
+ ["lbrace"] = "{", -- U+0007B
+ ["lbrack"] = "[", -- U+0005B
+ ["lbrke"] = "⦋", -- U+0298B
+ ["lbrksld"] = "⦏", -- U+0298F
+ ["lbrkslu"] = "⦍", -- U+0298D
+ ["lcaron"] = "ľ", -- U+0013E
+ ["lcedil"] = "ļ", -- U+0013C
+ ["lceil"] = "⌈", -- U+02308
+ ["lcub"] = "{", -- U+0007B
+ ["lcy"] = "л", -- U+0043B
+ ["ldca"] = "⤶", -- U+02936
+ ["ldquo"] = "“", -- U+0201C
+ ["ldquor"] = "„", -- U+0201E
+ ["ldrdhar"] = "⥧", -- U+02967
+ ["ldrushar"] = "⥋", -- U+0294B
+ ["ldsh"] = "↲", -- U+021B2
+ ["le"] = "≤", -- U+02264
+ ["leftarrow"] = "←", -- U+02190
+ ["leftarrowtail"] = "↢", -- U+021A2
+ ["leftharpoondown"] = "↽", -- U+021BD
+ ["leftharpoonup"] = "↼", -- U+021BC
+ ["leftleftarrows"] = "⇇", -- U+021C7
+ ["leftrightarrow"] = "↔", -- U+02194
+ ["leftrightarrows"] = "⇆", -- U+021C6
+ ["leftrightharpoons"] = "⇋", -- U+021CB
+ ["leftrightsquigarrow"] = "↭", -- U+021AD
+ ["leftthreetimes"] = "⋋", -- U+022CB
+ ["leg"] = "⋚", -- U+022DA
+ ["leq"] = "≤", -- U+02264
+ ["leqq"] = "≦", -- U+02266
+ ["leqslant"] = "⩽", -- U+02A7D
+ ["les"] = "⩽", -- U+02A7D
+ ["lescc"] = "⪨", -- U+02AA8
+ ["lesdot"] = "⩿", -- U+02A7F
+ ["lesdoto"] = "⪁", -- U+02A81
+ ["lesdotor"] = "⪃", -- U+02A83
+ ["lesg"] = "⋚︀", -- U+022DA 0FE00
+ ["lesges"] = "⪓", -- U+02A93
+ ["lessapprox"] = "⪅", -- U+02A85
+ ["lessdot"] = "⋖", -- U+022D6
+ ["lesseqgtr"] = "⋚", -- U+022DA
+ ["lesseqqgtr"] = "⪋", -- U+02A8B
+ ["lessgtr"] = "≶", -- U+02276
+ ["lesssim"] = "≲", -- U+02272
+ ["lfisht"] = "⥼", -- U+0297C
+ ["lfloor"] = "⌊", -- U+0230A
+ ["lfr"] = "𝔩", -- U+1D529
+ ["lg"] = "≶", -- U+02276
+ ["lgE"] = "⪑", -- U+02A91
+ ["lgr"] = "λ", -- U+003BB
+ ["lhard"] = "↽", -- U+021BD
+ ["lharu"] = "↼", -- U+021BC
+ ["lharul"] = "⥪", -- U+0296A
+ ["lhblk"] = "▄", -- U+02584
+ ["ljcy"] = "љ", -- U+00459
+ ["ll"] = "≪", -- U+0226A
+ ["llarr"] = "⇇", -- U+021C7
+ ["llcorner"] = "⌞", -- U+0231E
+ ["llhard"] = "⥫", -- U+0296B
+ ["lltri"] = "◺", -- U+025FA
+ ["lmidot"] = "ŀ", -- U+00140
+ ["lmoust"] = "⎰", -- U+023B0
+ ["lmoustache"] = "⎰", -- U+023B0
+ ["lnE"] = "≨", -- U+02268
+ ["lnap"] = "⪉", -- U+02A89
+ ["lnapprox"] = "⪉", -- U+02A89
+ ["lne"] = "⪇", -- U+02A87
+ ["lneq"] = "⪇", -- U+02A87
+ ["lneqq"] = "≨", -- U+02268
+ ["lnsim"] = "⋦", -- U+022E6
+ ["loang"] = "⟬", -- U+027EC
+ ["loarr"] = "⇽", -- U+021FD
+ ["lobrk"] = "⟦", -- U+027E6
+ ["longleftarrow"] = "⟵", -- U+027F5
+ ["longleftrightarrow"] = "⟷", -- U+027F7
+ ["longmapsto"] = "⟼", -- U+027FC
+ ["longrightarrow"] = "⟶", -- U+027F6
+ ["looparrowleft"] = "↫", -- U+021AB
+ ["looparrowright"] = "↬", -- U+021AC
+ ["lopar"] = "⦅", -- U+02985
+ ["lopf"] = "𝕝", -- U+1D55D
+ ["loplus"] = "⨭", -- U+02A2D
+ ["lotimes"] = "⨴", -- U+02A34
+ ["lowast"] = "∗", -- U+02217
+ ["lowbar"] = "_", -- U+0005F
+ ["loz"] = "◊", -- U+025CA
+ ["lozenge"] = "◊", -- U+025CA
+ ["lozf"] = "⧫", -- U+029EB
+ ["lpar"] = "(", -- U+00028
+ ["lparlt"] = "⦓", -- U+02993
+ ["lrarr"] = "⇆", -- U+021C6
+ ["lrcorner"] = "⌟", -- U+0231F
+ ["lrhar"] = "⇋", -- U+021CB
+ ["lrhard"] = "⥭", -- U+0296D
+ ["lrm"] = "‎", -- U+0200E
+ ["lrtri"] = "⊿", -- U+022BF
+ ["lsaquo"] = "‹", -- U+02039
+ ["lscr"] = "𝓁", -- U+1D4C1
+ ["lsh"] = "↰", -- U+021B0
+ ["lsim"] = "≲", -- U+02272
+ ["lsime"] = "⪍", -- U+02A8D
+ ["lsimg"] = "⪏", -- U+02A8F
+ ["lsqb"] = "[", -- U+0005B
+ ["lsquo"] = "‘", -- U+02018
+ ["lsquor"] = "‚", -- U+0201A
+ ["lstrok"] = "ł", -- U+00142
+ ["lt"] = "<", -- U+00026
+ ["ltcc"] = "⪦", -- U+02AA6
+ ["ltcir"] = "⩹", -- U+02A79
+ ["ltdot"] = "⋖", -- U+022D6
+ ["lthree"] = "⋋", -- U+022CB
+ ["ltimes"] = "⋉", -- U+022C9
+ ["ltlarr"] = "⥶", -- U+02976
+ ["ltquest"] = "⩻", -- U+02A7B
+ ["ltrPar"] = "⦖", -- U+02996
+ ["ltri"] = "◃", -- U+025C3
+ ["ltrie"] = "⊴", -- U+022B4
+ ["ltrif"] = "◂", -- U+025C2
+ ["lurdshar"] = "⥊", -- U+0294A
+ ["luruhar"] = "⥦", -- U+02966
+ ["lvertneqq"] = "≨︀", -- U+02268 0FE00
+ ["lvnE"] = "≨︀", -- U+02268 0FE00
+ ["mDDot"] = "∺", -- U+0223A
+ ["macr"] = "¯", -- U+000AF
+ ["male"] = "♂", -- U+02642
+ ["malt"] = "✠", -- U+02720
+ ["maltese"] = "✠", -- U+02720
+ ["map"] = "↦", -- U+021A6
+ ["mapsto"] = "↦", -- U+021A6
+ ["mapstodown"] = "↧", -- U+021A7
+ ["mapstoleft"] = "↤", -- U+021A4
+ ["mapstoup"] = "↥", -- U+021A5
+ ["marker"] = "▮", -- U+025AE
+ ["mcomma"] = "⨩", -- U+02A29
+ ["mcy"] = "м", -- U+0043C
+ ["mdash"] = "—", -- U+02014
+ ["measuredangle"] = "∡", -- U+02221
+ ["mfr"] = "𝔪", -- U+1D52A
+ ["mgr"] = "μ", -- U+003BC
+ ["mho"] = "℧", -- U+02127
+ ["micro"] = "µ", -- U+000B5
+ ["mid"] = "∣", -- U+02223
+ ["midast"] = "*", -- U+0002A
+ ["midcir"] = "⫰", -- U+02AF0
+ ["middot"] = "·", -- U+000B7
+ ["minus"] = "−", -- U+02212
+ ["minusb"] = "⊟", -- U+0229F
+ ["minusd"] = "∸", -- U+02238
+ ["minusdu"] = "⨪", -- U+02A2A
+ ["mlcp"] = "⫛", -- U+02ADB
+ ["mldr"] = "…", -- U+02026
+ ["mnplus"] = "∓", -- U+02213
+ ["models"] = "⊧", -- U+022A7
+ ["mopf"] = "𝕞", -- U+1D55E
+ ["mp"] = "∓", -- U+02213
+ ["mscr"] = "𝓂", -- U+1D4C2
+ ["mstpos"] = "∾", -- U+0223E
+ ["mu"] = "μ", -- U+003BC
+ ["multimap"] = "⊸", -- U+022B8
+ ["mumap"] = "⊸", -- U+022B8
+ ["nGg"] = "⋙̸", -- U+022D9 00338
+ ["nGt"] = "≫⃒", -- U+0226B 020D2
+ ["nGtv"] = "≫̸", -- U+0226B 00338
+ ["nLeftarrow"] = "⇍", -- U+021CD
+ ["nLeftrightarrow"] = "⇎", -- U+021CE
+ ["nLl"] = "⋘̸", -- U+022D8 00338
+ ["nLt"] = "≪⃒", -- U+0226A 020D2
+ ["nLtv"] = "≪̸", -- U+0226A 00338
+ ["nRightarrow"] = "⇏", -- U+021CF
+ ["nVDash"] = "⊯", -- U+022AF
+ ["nVdash"] = "⊮", -- U+022AE
+ ["nabla"] = "∇", -- U+02207
+ ["nacute"] = "ń", -- U+00144
+ ["nang"] = "∠⃒", -- U+02220 020D2
+ ["nap"] = "≉", -- U+02249
+ ["napE"] = "⩰̸", -- U+02A70 00338
+ ["napid"] = "≋̸", -- U+0224B 00338
+ ["napos"] = "ʼn", -- U+00149
+ ["napprox"] = "≉", -- U+02249
+ ["natur"] = "♮", -- U+0266E
+ ["natural"] = "♮", -- U+0266E
+ ["naturals"] = "ℕ", -- U+02115
+ ["nbsp"] = " ", -- U+000A0
+ ["nbump"] = "≎̸", -- U+0224E 00338
+ ["nbumpe"] = "≏̸", -- U+0224F 00338
+ ["ncap"] = "⩃", -- U+02A43
+ ["ncaron"] = "ň", -- U+00148
+ ["ncedil"] = "ņ", -- U+00146
+ ["ncong"] = "≇", -- U+02247
+ ["ncongdot"] = "⩭̸", -- U+02A6D 00338
+ ["ncup"] = "⩂", -- U+02A42
+ ["ncy"] = "н", -- U+0043D
+ ["ndash"] = "–", -- U+02013
+ ["ne"] = "≠", -- U+02260
+ ["neArr"] = "⇗", -- U+021D7
+ ["nearhk"] = "⤤", -- U+02924
+ ["nearr"] = "↗", -- U+02197
+ ["nearrow"] = "↗", -- U+02197
+ ["nedot"] = "≐̸", -- U+02250 00338
+ ["nequiv"] = "≢", -- U+02262
+ ["nesear"] = "⤨", -- U+02928
+ ["nesim"] = "≂̸", -- U+02242 00338
+ ["nexist"] = "∄", -- U+02204
+ ["nexists"] = "∄", -- U+02204
+ ["nfr"] = "𝔫", -- U+1D52B
+ ["ngE"] = "≧̸", -- U+02267 00338
+ ["nge"] = "≱", -- U+02271
+ ["ngeq"] = "≱", -- U+02271
+ ["ngeqq"] = "≧̸", -- U+02267 00338
+ ["ngeqslant"] = "⩾̸", -- U+02A7E 00338
+ ["nges"] = "⩾̸", -- U+02A7E 00338
+ ["ngr"] = "ν", -- U+003BD
+ ["ngsim"] = "≵", -- U+02275
+ ["ngt"] = "≯", -- U+0226F
+ ["ngtr"] = "≯", -- U+0226F
+ ["nhArr"] = "⇎", -- U+021CE
+ ["nharr"] = "↮", -- U+021AE
+ ["nhpar"] = "⫲", -- U+02AF2
+ ["ni"] = "∋", -- U+0220B
+ ["nis"] = "⋼", -- U+022FC
+ ["nisd"] = "⋺", -- U+022FA
+ ["niv"] = "∋", -- U+0220B
+ ["njcy"] = "њ", -- U+0045A
+ ["nlArr"] = "⇍", -- U+021CD
+ ["nlE"] = "≦̸", -- U+02266 00338
+ ["nlarr"] = "↚", -- U+0219A
+ ["nldr"] = "‥", -- U+02025
+ ["nle"] = "≰", -- U+02270
+ ["nleftarrow"] = "↚", -- U+0219A
+ ["nleftrightarrow"] = "↮", -- U+021AE
+ ["nleq"] = "≰", -- U+02270
+ ["nleqq"] = "≦̸", -- U+02266 00338
+ ["nleqslant"] = "⩽̸", -- U+02A7D 00338
+ ["nles"] = "⩽̸", -- U+02A7D 00338
+ ["nless"] = "≮", -- U+0226E
+ ["nlsim"] = "≴", -- U+02274
+ ["nlt"] = "≮", -- U+0226E
+ ["nltri"] = "⋪", -- U+022EA
+ ["nltrie"] = "⋬", -- U+022EC
+ ["nmid"] = "∤", -- U+02224
+ ["nopf"] = "𝕟", -- U+1D55F
+ ["not"] = "¬", -- U+000AC
+ ["notin"] = "∉", -- U+02209
+ ["notinE"] = "⋹̸", -- U+022F9 00338
+ ["notindot"] = "⋵̸", -- U+022F5 00338
+ ["notinva"] = "∉", -- U+02209
+ ["notinvb"] = "⋷", -- U+022F7
+ ["notinvc"] = "⋶", -- U+022F6
+ ["notni"] = "∌", -- U+0220C
+ ["notniva"] = "∌", -- U+0220C
+ ["notnivb"] = "⋾", -- U+022FE
+ ["notnivc"] = "⋽", -- U+022FD
+ ["npar"] = "∦", -- U+02226
+ ["nparallel"] = "∦", -- U+02226
+ ["nparsl"] = "⫽⃥", -- U+02AFD 020E5
+ ["npart"] = "∂̸", -- U+02202 00338
+ ["npolint"] = "⨔", -- U+02A14
+ ["npr"] = "⊀", -- U+02280
+ ["nprcue"] = "⋠", -- U+022E0
+ ["npre"] = "⪯̸", -- U+02AAF 00338
+ ["nprec"] = "⊀", -- U+02280
+ ["npreceq"] = "⪯̸", -- U+02AAF 00338
+ ["nrArr"] = "⇏", -- U+021CF
+ ["nrarr"] = "↛", -- U+0219B
+ ["nrarrc"] = "⤳̸", -- U+02933 00338
+ ["nrarrw"] = "↝̸", -- U+0219D 00338
+ ["nrightarrow"] = "↛", -- U+0219B
+ ["nrtri"] = "⋫", -- U+022EB
+ ["nrtrie"] = "⋭", -- U+022ED
+ ["nsc"] = "⊁", -- U+02281
+ ["nsccue"] = "⋡", -- U+022E1
+ ["nsce"] = "⪰̸", -- U+02AB0 00338
+ ["nscr"] = "𝓃", -- U+1D4C3
+ ["nshortmid"] = "∤", -- U+02224
+ ["nshortparallel"] = "∦", -- U+02226
+ ["nsim"] = "≁", -- U+02241
+ ["nsime"] = "≄", -- U+02244
+ ["nsimeq"] = "≄", -- U+02244
+ ["nsmid"] = "∤", -- U+02224
+ ["nspar"] = "∦", -- U+02226
+ ["nsqsube"] = "⋢", -- U+022E2
+ ["nsqsupe"] = "⋣", -- U+022E3
+ ["nsub"] = "⊄", -- U+02284
+ ["nsubE"] = "⫅̸", -- U+02AC5 00338
+ ["nsube"] = "⊈", -- U+02288
+ ["nsubset"] = "⊂⃒", -- U+02282 020D2
+ ["nsubseteq"] = "⊈", -- U+02288
+ ["nsubseteqq"] = "⫅̸", -- U+02AC5 00338
+ ["nsucc"] = "⊁", -- U+02281
+ ["nsucceq"] = "⪰̸", -- U+02AB0 00338
+ ["nsup"] = "⊅", -- U+02285
+ ["nsupE"] = "⫆̸", -- U+02AC6 00338
+ ["nsupe"] = "⊉", -- U+02289
+ ["nsupset"] = "⊃⃒", -- U+02283 020D2
+ ["nsupseteq"] = "⊉", -- U+02289
+ ["nsupseteqq"] = "⫆̸", -- U+02AC6 00338
+ ["ntgl"] = "≹", -- U+02279
+ ["ntilde"] = "ñ", -- U+000F1
+ ["ntlg"] = "≸", -- U+02278
+ ["ntriangleleft"] = "⋪", -- U+022EA
+ ["ntrianglelefteq"] = "⋬", -- U+022EC
+ ["ntriangleright"] = "⋫", -- U+022EB
+ ["ntrianglerighteq"] = "⋭", -- U+022ED
+ ["nu"] = "ν", -- U+003BD
+ ["num"] = "#", -- U+00023
+ ["numero"] = "№", -- U+02116
+ ["numsp"] = " ", -- U+02007
+ ["nvDash"] = "⊭", -- U+022AD
+ ["nvHarr"] = "⤄", -- U+02904
+ ["nvap"] = "≍⃒", -- U+0224D 020D2
+ ["nvdash"] = "⊬", -- U+022AC
+ ["nvge"] = "≥⃒", -- U+02265 020D2
+ ["nvgt"] = ">⃒", -- U+0003E 020D2
+ ["nvinfin"] = "⧞", -- U+029DE
+ ["nvlArr"] = "⤂", -- U+02902
+ ["nvle"] = "≤⃒", -- U+02264 020D2
+ ["nvlt"] = "&⃒", -- U+00026 020D2
+ ["nvltrie"] = "⊴⃒", -- U+022B4 020D2
+ ["nvrArr"] = "⤃", -- U+02903
+ ["nvrtrie"] = "⊵⃒", -- U+022B5 020D2
+ ["nvsim"] = "∼⃒", -- U+0223C 020D2
+ ["nwArr"] = "⇖", -- U+021D6
+ ["nwarhk"] = "⤣", -- U+02923
+ ["nwarr"] = "↖", -- U+02196
+ ["nwarrow"] = "↖", -- U+02196
+ ["nwnear"] = "⤧", -- U+02927
+ ["oS"] = "Ⓢ", -- U+024C8
+ ["oacgr"] = "ό", -- U+003CC
+ ["oacute"] = "ó", -- U+000F3
+ ["oast"] = "⊛", -- U+0229B
+ ["ocir"] = "⊚", -- U+0229A
+ ["ocirc"] = "ô", -- U+000F4
+ ["ocy"] = "о", -- U+0043E
+ ["odash"] = "⊝", -- U+0229D
+ ["odblac"] = "ő", -- U+00151
+ ["odiv"] = "⨸", -- U+02A38
+ ["odot"] = "⊙", -- U+02299
+ ["odsold"] = "⦼", -- U+029BC
+ ["oelig"] = "œ", -- U+00153
+ ["ofcir"] = "⦿", -- U+029BF
+ ["ofr"] = "𝔬", -- U+1D52C
+ ["ogon"] = "˛", -- U+002DB
+ ["ogr"] = "ο", -- U+003BF
+ ["ograve"] = "ò", -- U+000F2
+ ["ogt"] = "⧁", -- U+029C1
+ ["ohacgr"] = "ώ", -- U+003CE
+ ["ohbar"] = "⦵", -- U+029B5
+ ["ohgr"] = "ω", -- U+003C9
+ ["ohm"] = "Ω", -- U+003A9
+ ["oint"] = "∮", -- U+0222E
+ ["olarr"] = "↺", -- U+021BA
+ ["olcir"] = "⦾", -- U+029BE
+ ["olcross"] = "⦻", -- U+029BB
+ ["oline"] = "‾", -- U+0203E
+ ["olt"] = "⧀", -- U+029C0
+ ["omacr"] = "ō", -- U+0014D
+ ["omega"] = "ω", -- U+003C9
+ ["omicron"] = "ο", -- U+003BF
+ ["omid"] = "⦶", -- U+029B6
+ ["ominus"] = "⊖", -- U+02296
+ ["oopf"] = "𝕠", -- U+1D560
+ ["opar"] = "⦷", -- U+029B7
+ ["operp"] = "⦹", -- U+029B9
+ ["oplus"] = "⊕", -- U+02295
+ ["or"] = "∨", -- U+02228
+ ["orarr"] = "↻", -- U+021BB
+ ["ord"] = "⩝", -- U+02A5D
+ ["order"] = "ℴ", -- U+02134
+ ["orderof"] = "ℴ", -- U+02134
+ ["ordf"] = "ª", -- U+000AA
+ ["ordm"] = "º", -- U+000BA
+ ["origof"] = "⊶", -- U+022B6
+ ["oror"] = "⩖", -- U+02A56
+ ["orslope"] = "⩗", -- U+02A57
+ ["orv"] = "⩛", -- U+02A5B
+ ["oscr"] = "ℴ", -- U+02134
+ ["oslash"] = "ø", -- U+000F8
+ ["osol"] = "⊘", -- U+02298
+ ["otilde"] = "õ", -- U+000F5
+ ["otimes"] = "⊗", -- U+02297
+ ["otimesas"] = "⨶", -- U+02A36
+ ["ouml"] = "ö", -- U+000F6
+ ["ovbar"] = "⌽", -- U+0233D
+ ["par"] = "∥", -- U+02225
+ ["para"] = "¶", -- U+000B6
+ ["parallel"] = "∥", -- U+02225
+ ["parsim"] = "⫳", -- U+02AF3
+ ["parsl"] = "⫽", -- U+02AFD
+ ["part"] = "∂", -- U+02202
+ ["pcy"] = "п", -- U+0043F
+ ["percnt"] = "%", -- U+00025
+ ["period"] = ".", -- U+0002E
+ ["permil"] = "‰", -- U+02030
+ ["perp"] = "⊥", -- U+022A5
+ ["pertenk"] = "‱", -- U+02031
+ ["pfr"] = "𝔭", -- U+1D52D
+ ["pgr"] = "π", -- U+003C0
+ ["phgr"] = "φ", -- U+003C6
+ ["phi"] = "φ", -- U+003C6
+ ["phiv"] = "ϕ", -- U+003D5
+ ["phmmat"] = "ℳ", -- U+02133
+ ["phone"] = "☎", -- U+0260E
+ ["pi"] = "π", -- U+003C0
+ ["pitchfork"] = "⋔", -- U+022D4
+ ["piv"] = "ϖ", -- U+003D6
+ ["planck"] = "ℏ", -- U+0210F
+ ["planckh"] = "ℎ", -- U+0210E
+ ["plankv"] = "ℏ", -- U+0210F
+ ["plus"] = "+", -- U+0002B
+ ["plusacir"] = "⨣", -- U+02A23
+ ["plusb"] = "⊞", -- U+0229E
+ ["pluscir"] = "⨢", -- U+02A22
+ ["plusdo"] = "∔", -- U+02214
+ ["plusdu"] = "⨥", -- U+02A25
+ ["pluse"] = "⩲", -- U+02A72
+ ["plusmn"] = "±", -- U+000B1
+ ["plussim"] = "⨦", -- U+02A26
+ ["plustwo"] = "⨧", -- U+02A27
+ ["pm"] = "±", -- U+000B1
+ ["pointint"] = "⨕", -- U+02A15
+ ["popf"] = "𝕡", -- U+1D561
+ ["pound"] = "£", -- U+000A3
+ ["pr"] = "≺", -- U+0227A
+ ["prE"] = "⪳", -- U+02AB3
+ ["prap"] = "⪷", -- U+02AB7
+ ["prcue"] = "≼", -- U+0227C
+ ["pre"] = "⪯", -- U+02AAF
+ ["prec"] = "≺", -- U+0227A
+ ["precapprox"] = "⪷", -- U+02AB7
+ ["preccurlyeq"] = "≼", -- U+0227C
+ ["preceq"] = "⪯", -- U+02AAF
+ ["precnapprox"] = "⪹", -- U+02AB9
+ ["precneqq"] = "⪵", -- U+02AB5
+ ["precnsim"] = "⋨", -- U+022E8
+ ["precsim"] = "≾", -- U+0227E
+ ["prime"] = "′", -- U+02032
+ ["primes"] = "ℙ", -- U+02119
+ ["prnE"] = "⪵", -- U+02AB5
+ ["prnap"] = "⪹", -- U+02AB9
+ ["prnsim"] = "⋨", -- U+022E8
+ ["prod"] = "∏", -- U+0220F
+ ["profalar"] = "⌮", -- U+0232E
+ ["profline"] = "⌒", -- U+02312
+ ["profsurf"] = "⌓", -- U+02313
+ ["prop"] = "∝", -- U+0221D
+ ["propto"] = "∝", -- U+0221D
+ ["prsim"] = "≾", -- U+0227E
+ ["prurel"] = "⊰", -- U+022B0
+ ["pscr"] = "𝓅", -- U+1D4C5
+ ["psgr"] = "ψ", -- U+003C8
+ ["psi"] = "ψ", -- U+003C8
+ ["puncsp"] = " ", -- U+02008
+ ["qfr"] = "𝔮", -- U+1D52E
+ ["qint"] = "⨌", -- U+02A0C
+ ["qopf"] = "𝕢", -- U+1D562
+ ["qprime"] = "⁗", -- U+02057
+ ["qscr"] = "𝓆", -- U+1D4C6
+ ["quaternions"] = "ℍ", -- U+0210D
+ ["quatint"] = "⨖", -- U+02A16
+ ["quest"] = "?", -- U+0003F
+ ["questeq"] = "≟", -- U+0225F
+ ["quot"] = "\"", -- U+00022
+ ["rAarr"] = "⇛", -- U+021DB
+ ["rArr"] = "⇒", -- U+021D2
+ ["rAtail"] = "⤜", -- U+0291C
+ ["rBarr"] = "⤏", -- U+0290F
+ ["rHar"] = "⥤", -- U+02964
+ ["race"] = "∽̱", -- U+0223D 00331
+ ["racute"] = "ŕ", -- U+00155
+ ["radic"] = "√", -- U+0221A
+ ["raemptyv"] = "⦳", -- U+029B3
+ ["rang"] = "⟩", -- U+027E9
+ ["rangd"] = "⦒", -- U+02992
+ ["range"] = "⦥", -- U+029A5
+ ["rangle"] = "⟩", -- U+027E9
+ ["raquo"] = "»", -- U+000BB
+ ["rarr"] = "→", -- U+02192
+ ["rarrap"] = "⥵", -- U+02975
+ ["rarrb"] = "⇥", -- U+021E5
+ ["rarrbfs"] = "⤠", -- U+02920
+ ["rarrc"] = "⤳", -- U+02933
+ ["rarrfs"] = "⤞", -- U+0291E
+ ["rarrhk"] = "↪", -- U+021AA
+ ["rarrlp"] = "↬", -- U+021AC
+ ["rarrpl"] = "⥅", -- U+02945
+ ["rarrsim"] = "⥴", -- U+02974
+ ["rarrtl"] = "↣", -- U+021A3
+ ["rarrw"] = "↝", -- U+0219D
+ ["ratail"] = "⤚", -- U+0291A
+ ["ratio"] = "∶", -- U+02236
+ ["rationals"] = "ℚ", -- U+0211A
+ ["rbarr"] = "⤍", -- U+0290D
+ ["rbbrk"] = "❳", -- U+02773
+ ["rbrace"] = "}", -- U+0007D
+ ["rbrack"] = "]", -- U+0005D
+ ["rbrke"] = "⦌", -- U+0298C
+ ["rbrksld"] = "⦎", -- U+0298E
+ ["rbrkslu"] = "⦐", -- U+02990
+ ["rcaron"] = "ř", -- U+00159
+ ["rcedil"] = "ŗ", -- U+00157
+ ["rceil"] = "⌉", -- U+02309
+ ["rcub"] = "}", -- U+0007D
+ ["rcy"] = "р", -- U+00440
+ ["rdca"] = "⤷", -- U+02937
+ ["rdldhar"] = "⥩", -- U+02969
+ ["rdquo"] = "”", -- U+0201D
+ ["rdquor"] = "”", -- U+0201D
+ ["rdsh"] = "↳", -- U+021B3
+ ["real"] = "ℜ", -- U+0211C
+ ["realine"] = "ℛ", -- U+0211B
+ ["realpart"] = "ℜ", -- U+0211C
+ ["reals"] = "ℝ", -- U+0211D
+ ["rect"] = "▭", -- U+025AD
+ ["reg"] = "®", -- U+000AE
+ ["rfisht"] = "⥽", -- U+0297D
+ ["rfloor"] = "⌋", -- U+0230B
+ ["rfr"] = "𝔯", -- U+1D52F
+ ["rgr"] = "ρ", -- U+003C1
+ ["rhard"] = "⇁", -- U+021C1
+ ["rharu"] = "⇀", -- U+021C0
+ ["rharul"] = "⥬", -- U+0296C
+ ["rho"] = "ρ", -- U+003C1
+ ["rhov"] = "ϱ", -- U+003F1
+ ["rightarrow"] = "→", -- U+02192
+ ["rightarrowtail"] = "↣", -- U+021A3
+ ["rightharpoondown"] = "⇁", -- U+021C1
+ ["rightharpoonup"] = "⇀", -- U+021C0
+ ["rightleftarrows"] = "⇄", -- U+021C4
+ ["rightleftharpoons"] = "⇌", -- U+021CC
+ ["rightrightarrows"] = "⇉", -- U+021C9
+ ["rightsquigarrow"] = "↝", -- U+0219D
+ ["rightthreetimes"] = "⋌", -- U+022CC
+ ["ring"] = "˚", -- U+002DA
+ ["risingdotseq"] = "≓", -- U+02253
+ ["rlarr"] = "⇄", -- U+021C4
+ ["rlhar"] = "⇌", -- U+021CC
+ ["rlm"] = "‏", -- U+0200F
+ ["rmoust"] = "⎱", -- U+023B1
+ ["rmoustache"] = "⎱", -- U+023B1
+ ["rnmid"] = "⫮", -- U+02AEE
+ ["roang"] = "⟭", -- U+027ED
+ ["roarr"] = "⇾", -- U+021FE
+ ["robrk"] = "⟧", -- U+027E7
+ ["ropar"] = "⦆", -- U+02986
+ ["ropf"] = "𝕣", -- U+1D563
+ ["roplus"] = "⨮", -- U+02A2E
+ ["rotimes"] = "⨵", -- U+02A35
+ ["rpar"] = ")", -- U+00029
+ ["rpargt"] = "⦔", -- U+02994
+ ["rppolint"] = "⨒", -- U+02A12
+ ["rrarr"] = "⇉", -- U+021C9
+ ["rsaquo"] = "›", -- U+0203A
+ ["rscr"] = "𝓇", -- U+1D4C7
+ ["rsh"] = "↱", -- U+021B1
+ ["rsqb"] = "]", -- U+0005D
+ ["rsquo"] = "’", -- U+02019
+ ["rsquor"] = "’", -- U+02019
+ ["rthree"] = "⋌", -- U+022CC
+ ["rtimes"] = "⋊", -- U+022CA
+ ["rtri"] = "▹", -- U+025B9
+ ["rtrie"] = "⊵", -- U+022B5
+ ["rtrif"] = "▸", -- U+025B8
+ ["rtriltri"] = "⧎", -- U+029CE
+ ["ruluhar"] = "⥨", -- U+02968
+ ["rx"] = "℞", -- U+0211E
+ ["sacute"] = "ś", -- U+0015B
+ ["sbquo"] = "‚", -- U+0201A
+ ["sc"] = "≻", -- U+0227B
+ ["scE"] = "⪴", -- U+02AB4
+ ["scap"] = "⪸", -- U+02AB8
+ ["scaron"] = "š", -- U+00161
+ ["sccue"] = "≽", -- U+0227D
+ ["sce"] = "⪰", -- U+02AB0
+ ["scedil"] = "ş", -- U+0015F
+ ["scirc"] = "ŝ", -- U+0015D
+ ["scnE"] = "⪶", -- U+02AB6
+ ["scnap"] = "⪺", -- U+02ABA
+ ["scnsim"] = "⋩", -- U+022E9
+ ["scpolint"] = "⨓", -- U+02A13
+ ["scsim"] = "≿", -- U+0227F
+ ["scy"] = "с", -- U+00441
+ ["sdot"] = "⋅", -- U+022C5
+ ["sdotb"] = "⊡", -- U+022A1
+ ["sdote"] = "⩦", -- U+02A66
+ ["seArr"] = "⇘", -- U+021D8
+ ["searhk"] = "⤥", -- U+02925
+ ["searr"] = "↘", -- U+02198
+ ["searrow"] = "↘", -- U+02198
+ ["sect"] = "§", -- U+000A7
+ ["semi"] = ";", -- U+0003B
+ ["seswar"] = "⤩", -- U+02929
+ ["setminus"] = "∖", -- U+02216
+ ["setmn"] = "∖", -- U+02216
+ ["sext"] = "✶", -- U+02736
+ ["sfgr"] = "ς", -- U+003C2
+ ["sfr"] = "𝔰", -- U+1D530
+ ["sfrown"] = "⌢", -- U+02322
+ ["sgr"] = "σ", -- U+003C3
+ ["sharp"] = "♯", -- U+0266F
+ ["shchcy"] = "щ", -- U+00449
+ ["shcy"] = "ш", -- U+00448
+ ["shortmid"] = "∣", -- U+02223
+ ["shortparallel"] = "∥", -- U+02225
+ ["shy"] = "­", -- U+000AD
+ ["sigma"] = "σ", -- U+003C3
+ ["sigmaf"] = "ς", -- U+003C2
+ ["sigmav"] = "ς", -- U+003C2
+ ["sim"] = "∼", -- U+0223C
+ ["simdot"] = "⩪", -- U+02A6A
+ ["sime"] = "≃", -- U+02243
+ ["simeq"] = "≃", -- U+02243
+ ["simg"] = "⪞", -- U+02A9E
+ ["simgE"] = "⪠", -- U+02AA0
+ ["siml"] = "⪝", -- U+02A9D
+ ["simlE"] = "⪟", -- U+02A9F
+ ["simne"] = "≆", -- U+02246
+ ["simplus"] = "⨤", -- U+02A24
+ ["simrarr"] = "⥲", -- U+02972
+ ["slarr"] = "←", -- U+02190
+ ["smallsetminus"] = "∖", -- U+02216
+ ["smashp"] = "⨳", -- U+02A33
+ ["smeparsl"] = "⧤", -- U+029E4
+ ["smid"] = "∣", -- U+02223
+ ["smile"] = "⌣", -- U+02323
+ ["smt"] = "⪪", -- U+02AAA
+ ["smte"] = "⪬", -- U+02AAC
+ ["smtes"] = "⪬︀", -- U+02AAC 0FE00
+ ["softcy"] = "ь", -- U+0044C
+ ["sol"] = "/", -- U+0002F
+ ["solb"] = "⧄", -- U+029C4
+ ["solbar"] = "⌿", -- U+0233F
+ ["sopf"] = "𝕤", -- U+1D564
+ ["spades"] = "♠", -- U+02660
+ ["spadesuit"] = "♠", -- U+02660
+ ["spar"] = "∥", -- U+02225
+ ["sqcap"] = "⊓", -- U+02293
+ ["sqcaps"] = "⊓︀", -- U+02293 0FE00
+ ["sqcup"] = "⊔", -- U+02294
+ ["sqcups"] = "⊔︀", -- U+02294 0FE00
+ ["sqsub"] = "⊏", -- U+0228F
+ ["sqsube"] = "⊑", -- U+02291
+ ["sqsubset"] = "⊏", -- U+0228F
+ ["sqsubseteq"] = "⊑", -- U+02291
+ ["sqsup"] = "⊐", -- U+02290
+ ["sqsupe"] = "⊒", -- U+02292
+ ["sqsupset"] = "⊐", -- U+02290
+ ["sqsupseteq"] = "⊒", -- U+02292
+ ["squ"] = "□", -- U+025A1
+ ["square"] = "□", -- U+025A1
+ ["squarf"] = "▪", -- U+025AA
+ ["squf"] = "▪", -- U+025AA
+ ["srarr"] = "→", -- U+02192
+ ["sscr"] = "𝓈", -- U+1D4C8
+ ["ssetmn"] = "∖", -- U+02216
+ ["ssmile"] = "⌣", -- U+02323
+ ["sstarf"] = "⋆", -- U+022C6
+ ["star"] = "☆", -- U+02606
+ ["starf"] = "★", -- U+02605
+ ["straightepsilon"] = "ϵ", -- U+003F5
+ ["straightphi"] = "ϕ", -- U+003D5
+ ["strns"] = "¯", -- U+000AF
+ ["sub"] = "⊂", -- U+02282
+ ["subE"] = "⫅", -- U+02AC5
+ ["subdot"] = "⪽", -- U+02ABD
+ ["sube"] = "⊆", -- U+02286
+ ["subedot"] = "⫃", -- U+02AC3
+ ["submult"] = "⫁", -- U+02AC1
+ ["subnE"] = "⫋", -- U+02ACB
+ ["subne"] = "⊊", -- U+0228A
+ ["subplus"] = "⪿", -- U+02ABF
+ ["subrarr"] = "⥹", -- U+02979
+ ["subset"] = "⊂", -- U+02282
+ ["subseteq"] = "⊆", -- U+02286
+ ["subseteqq"] = "⫅", -- U+02AC5
+ ["subsetneq"] = "⊊", -- U+0228A
+ ["subsetneqq"] = "⫋", -- U+02ACB
+ ["subsim"] = "⫇", -- U+02AC7
+ ["subsub"] = "⫕", -- U+02AD5
+ ["subsup"] = "⫓", -- U+02AD3
+ ["succ"] = "≻", -- U+0227B
+ ["succapprox"] = "⪸", -- U+02AB8
+ ["succcurlyeq"] = "≽", -- U+0227D
+ ["succeq"] = "⪰", -- U+02AB0
+ ["succnapprox"] = "⪺", -- U+02ABA
+ ["succneqq"] = "⪶", -- U+02AB6
+ ["succnsim"] = "⋩", -- U+022E9
+ ["succsim"] = "≿", -- U+0227F
+ ["sum"] = "∑", -- U+02211
+ ["sung"] = "♪", -- U+0266A
+ ["sup"] = "⊃", -- U+02283
+ ["sup1"] = "¹", -- U+000B9
+ ["sup2"] = "²", -- U+000B2
+ ["sup3"] = "³", -- U+000B3
+ ["supE"] = "⫆", -- U+02AC6
+ ["supdot"] = "⪾", -- U+02ABE
+ ["supdsub"] = "⫘", -- U+02AD8
+ ["supe"] = "⊇", -- U+02287
+ ["supedot"] = "⫄", -- U+02AC4
+ ["suphsol"] = "⟉", -- U+027C9
+ ["suphsub"] = "⫗", -- U+02AD7
+ ["suplarr"] = "⥻", -- U+0297B
+ ["supmult"] = "⫂", -- U+02AC2
+ ["supnE"] = "⫌", -- U+02ACC
+ ["supne"] = "⊋", -- U+0228B
+ ["supplus"] = "⫀", -- U+02AC0
+ ["supset"] = "⊃", -- U+02283
+ ["supseteq"] = "⊇", -- U+02287
+ ["supseteqq"] = "⫆", -- U+02AC6
+ ["supsetneq"] = "⊋", -- U+0228B
+ ["supsetneqq"] = "⫌", -- U+02ACC
+ ["supsim"] = "⫈", -- U+02AC8
+ ["supsub"] = "⫔", -- U+02AD4
+ ["supsup"] = "⫖", -- U+02AD6
+ ["swArr"] = "⇙", -- U+021D9
+ ["swarhk"] = "⤦", -- U+02926
+ ["swarr"] = "↙", -- U+02199
+ ["swarrow"] = "↙", -- U+02199
+ ["swnwar"] = "⤪", -- U+0292A
+ ["szlig"] = "ß", -- U+000DF
+ ["target"] = "⌖", -- U+02316
+ ["tau"] = "τ", -- U+003C4
+ ["tbrk"] = "⎴", -- U+023B4
+ ["tcaron"] = "ť", -- U+00165
+ ["tcedil"] = "ţ", -- U+00163
+ ["tcy"] = "т", -- U+00442
+ ["tdot"] = "⃛", -- U+020DB
+ ["telrec"] = "⌕", -- U+02315
+ ["tfr"] = "𝔱", -- U+1D531
+ ["tgr"] = "τ", -- U+003C4
+ ["there4"] = "∴", -- U+02234
+ ["therefore"] = "∴", -- U+02234
+ ["theta"] = "θ", -- U+003B8
+ ["thetasym"] = "ϑ", -- U+003D1
+ ["thetav"] = "ϑ", -- U+003D1
+ ["thgr"] = "θ", -- U+003B8
+ ["thickapprox"] = "≈", -- U+02248
+ ["thicksim"] = "∼", -- U+0223C
+ ["thinsp"] = " ", -- U+02009
+ ["thkap"] = "≈", -- U+02248
+ ["thksim"] = "∼", -- U+0223C
+ ["thorn"] = "þ", -- U+000FE
+ ["tilde"] = "˜", -- U+002DC
+ ["times"] = "×", -- U+000D7
+ ["timesb"] = "⊠", -- U+022A0
+ ["timesbar"] = "⨱", -- U+02A31
+ ["timesd"] = "⨰", -- U+02A30
+ ["tint"] = "∭", -- U+0222D
+ ["toea"] = "⤨", -- U+02928
+ ["top"] = "⊤", -- U+022A4
+ ["topbot"] = "⌶", -- U+02336
+ ["topcir"] = "⫱", -- U+02AF1
+ ["topf"] = "𝕥", -- U+1D565
+ ["topfork"] = "⫚", -- U+02ADA
+ ["tosa"] = "⤩", -- U+02929
+ ["tprime"] = "‴", -- U+02034
+ ["trade"] = "™", -- U+02122
+ ["triangle"] = "▵", -- U+025B5
+ ["triangledown"] = "▿", -- U+025BF
+ ["triangleleft"] = "◃", -- U+025C3
+ ["trianglelefteq"] = "⊴", -- U+022B4
+ ["triangleq"] = "≜", -- U+0225C
+ ["triangleright"] = "▹", -- U+025B9
+ ["trianglerighteq"] = "⊵", -- U+022B5
+ ["tridot"] = "◬", -- U+025EC
+ ["trie"] = "≜", -- U+0225C
+ ["triminus"] = "⨺", -- U+02A3A
+ ["triplus"] = "⨹", -- U+02A39
+ ["trisb"] = "⧍", -- U+029CD
+ ["tritime"] = "⨻", -- U+02A3B
+ ["trpezium"] = "⏢", -- U+023E2
+ ["tscr"] = "𝓉", -- U+1D4C9
+ ["tscy"] = "ц", -- U+00446
+ ["tshcy"] = "ћ", -- U+0045B
+ ["tstrok"] = "ŧ", -- U+00167
+ ["twixt"] = "≬", -- U+0226C
+ ["twoheadleftarrow"] = "↞", -- U+0219E
+ ["twoheadrightarrow"] = "↠", -- U+021A0
+ ["uArr"] = "⇑", -- U+021D1
+ ["uHar"] = "⥣", -- U+02963
+ ["uacgr"] = "ύ", -- U+003CD
+ ["uacute"] = "ú", -- U+000FA
+ ["uarr"] = "↑", -- U+02191
+ ["ubrcy"] = "ў", -- U+0045E
+ ["ubreve"] = "ŭ", -- U+0016D
+ ["ucirc"] = "û", -- U+000FB
+ ["ucy"] = "у", -- U+00443
+ ["udarr"] = "⇅", -- U+021C5
+ ["udblac"] = "ű", -- U+00171
+ ["udhar"] = "⥮", -- U+0296E
+ ["udiagr"] = "ΰ", -- U+003B0
+ ["udigr"] = "ϋ", -- U+003CB
+ ["ufisht"] = "⥾", -- U+0297E
+ ["ufr"] = "𝔲", -- U+1D532
+ ["ugr"] = "υ", -- U+003C5
+ ["ugrave"] = "ù", -- U+000F9
+ ["uharl"] = "↿", -- U+021BF
+ ["uharr"] = "↾", -- U+021BE
+ ["uhblk"] = "▀", -- U+02580
+ ["ulcorn"] = "⌜", -- U+0231C
+ ["ulcorner"] = "⌜", -- U+0231C
+ ["ulcrop"] = "⌏", -- U+0230F
+ ["ultri"] = "◸", -- U+025F8
+ ["umacr"] = "ū", -- U+0016B
+ ["uml"] = "¨", -- U+000A8
+ ["uogon"] = "ų", -- U+00173
+ ["uopf"] = "𝕦", -- U+1D566
+ ["uparrow"] = "↑", -- U+02191
+ ["updownarrow"] = "↕", -- U+02195
+ ["upharpoonleft"] = "↿", -- U+021BF
+ ["upharpoonright"] = "↾", -- U+021BE
+ ["uplus"] = "⊎", -- U+0228E
+ ["upsi"] = "υ", -- U+003C5
+ ["upsih"] = "ϒ", -- U+003D2
+ ["upsilon"] = "υ", -- U+003C5
+ ["upuparrows"] = "⇈", -- U+021C8
+ ["urcorn"] = "⌝", -- U+0231D
+ ["urcorner"] = "⌝", -- U+0231D
+ ["urcrop"] = "⌎", -- U+0230E
+ ["uring"] = "ů", -- U+0016F
+ ["urtri"] = "◹", -- U+025F9
+ ["uscr"] = "𝓊", -- U+1D4CA
+ ["utdot"] = "⋰", -- U+022F0
+ ["utilde"] = "ũ", -- U+00169
+ ["utri"] = "▵", -- U+025B5
+ ["utrif"] = "▴", -- U+025B4
+ ["uuarr"] = "⇈", -- U+021C8
+ ["uuml"] = "ü", -- U+000FC
+ ["uwangle"] = "⦧", -- U+029A7
+ ["vArr"] = "⇕", -- U+021D5
+ ["vBar"] = "⫨", -- U+02AE8
+ ["vBarv"] = "⫩", -- U+02AE9
+ ["vDash"] = "⊨", -- U+022A8
+ ["vangrt"] = "⦜", -- U+0299C
+ ["varepsilon"] = "ϵ", -- U+003F5
+ ["varkappa"] = "ϰ", -- U+003F0
+ ["varnothing"] = "∅", -- U+02205
+ ["varphi"] = "ϕ", -- U+003D5
+ ["varpi"] = "ϖ", -- U+003D6
+ ["varpropto"] = "∝", -- U+0221D
+ ["varr"] = "↕", -- U+02195
+ ["varrho"] = "ϱ", -- U+003F1
+ ["varsigma"] = "ς", -- U+003C2
+ ["varsubsetneq"] = "⊊︀", -- U+0228A 0FE00
+ ["varsubsetneqq"] = "⫋︀", -- U+02ACB 0FE00
+ ["varsupsetneq"] = "⊋︀", -- U+0228B 0FE00
+ ["varsupsetneqq"] = "⫌︀", -- U+02ACC 0FE00
+ ["vartheta"] = "ϑ", -- U+003D1
+ ["vartriangleleft"] = "⊲", -- U+022B2
+ ["vartriangleright"] = "⊳", -- U+022B3
+ ["vcy"] = "в", -- U+00432
+ ["vdash"] = "⊢", -- U+022A2
+ ["vee"] = "∨", -- U+02228
+ ["veebar"] = "⊻", -- U+022BB
+ ["veeeq"] = "≚", -- U+0225A
+ ["vellip"] = "⋮", -- U+022EE
+ ["verbar"] = "|", -- U+0007C
+ ["vert"] = "|", -- U+0007C
+ ["vfr"] = "𝔳", -- U+1D533
+ ["vltri"] = "⊲", -- U+022B2
+ ["vnsub"] = "⊂⃒", -- U+02282 020D2
+ ["vnsup"] = "⊃⃒", -- U+02283 020D2
+ ["vopf"] = "𝕧", -- U+1D567
+ ["vprop"] = "∝", -- U+0221D
+ ["vrtri"] = "⊳", -- U+022B3
+ ["vscr"] = "𝓋", -- U+1D4CB
+ ["vsubnE"] = "⫋︀", -- U+02ACB 0FE00
+ ["vsubne"] = "⊊︀", -- U+0228A 0FE00
+ ["vsupnE"] = "⫌︀", -- U+02ACC 0FE00
+ ["vsupne"] = "⊋︀", -- U+0228B 0FE00
+ ["vzigzag"] = "⦚", -- U+0299A
+ ["wcirc"] = "ŵ", -- U+00175
+ ["wedbar"] = "⩟", -- U+02A5F
+ ["wedge"] = "∧", -- U+02227
+ ["wedgeq"] = "≙", -- U+02259
+ ["weierp"] = "℘", -- U+02118
+ ["wfr"] = "𝔴", -- U+1D534
+ ["wopf"] = "𝕨", -- U+1D568
+ ["wp"] = "℘", -- U+02118
+ ["wr"] = "≀", -- U+02240
+ ["wreath"] = "≀", -- U+02240
+ ["wscr"] = "𝓌", -- U+1D4CC
+ ["xcap"] = "⋂", -- U+022C2
+ ["xcirc"] = "◯", -- U+025EF
+ ["xcup"] = "⋃", -- U+022C3
+ ["xdtri"] = "▽", -- U+025BD
+ ["xfr"] = "𝔵", -- U+1D535
+ ["xgr"] = "ξ", -- U+003BE
+ ["xhArr"] = "⟺", -- U+027FA
+ ["xharr"] = "⟷", -- U+027F7
+ ["xi"] = "ξ", -- U+003BE
+ ["xlArr"] = "⟸", -- U+027F8
+ ["xlarr"] = "⟵", -- U+027F5
+ ["xmap"] = "⟼", -- U+027FC
+ ["xnis"] = "⋻", -- U+022FB
+ ["xodot"] = "⨀", -- U+02A00
+ ["xopf"] = "𝕩", -- U+1D569
+ ["xoplus"] = "⨁", -- U+02A01
+ ["xotime"] = "⨂", -- U+02A02
+ ["xrArr"] = "⟹", -- U+027F9
+ ["xrarr"] = "⟶", -- U+027F6
+ ["xscr"] = "𝓍", -- U+1D4CD
+ ["xsqcup"] = "⨆", -- U+02A06
+ ["xuplus"] = "⨄", -- U+02A04
+ ["xutri"] = "△", -- U+025B3
+ ["xvee"] = "⋁", -- U+022C1
+ ["xwedge"] = "⋀", -- U+022C0
+ ["yacute"] = "ý", -- U+000FD
+ ["yacy"] = "я", -- U+0044F
+ ["ycirc"] = "ŷ", -- U+00177
+ ["ycy"] = "ы", -- U+0044B
+ ["yen"] = "¥", -- U+000A5
+ ["yfr"] = "𝔶", -- U+1D536
+ ["yicy"] = "ї", -- U+00457
+ ["yopf"] = "𝕪", -- U+1D56A
+ ["yscr"] = "𝓎", -- U+1D4CE
+ ["yucy"] = "ю", -- U+0044E
+ ["yuml"] = "ÿ", -- U+000FF
+ ["zacute"] = "ź", -- U+0017A
+ ["zcaron"] = "ž", -- U+0017E
+ ["zcy"] = "з", -- U+00437
+ ["zdot"] = "ż", -- U+0017C
+ ["zeetrf"] = "ℨ", -- U+02128
+ ["zeta"] = "ζ", -- U+003B6
+ ["zfr"] = "𝔷", -- U+1D537
+ ["zgr"] = "ζ", -- U+003B6
+ ["zhcy"] = "ж", -- U+00436
+ ["zigrarr"] = "⇝", -- U+021DD
+ ["zopf"] = "𝕫", -- U+1D56B
+ ["zscr"] = "𝓏", -- U+1D4CF
+ ["zwj"] = "‍", -- U+0200D
+ ["zwnj"] = "‌", -- U+0200C
+}
+
+characters = characters or { }
+characters.entities = entities
+
+entities.plusminus = "±" -- U+000B1
+entities.minusplus = "∓" -- U+02213
+entities.Hat = "ˆ" -- U+002C6 -- better as this will stretch
+entities.cdots = "⋯" -- U+022EF
+entities.dots = "…" -- U+02026
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-fio.lua b/Master/texmf-dist/tex/context/base/mkiv/char-fio.lua
new file mode 100644
index 00000000000..ab255593575
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-fio.lua
@@ -0,0 +1,94 @@
+if not modules then modules = { } end modules ['char-fio'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- % directives="filters.utf.reorder=false"
+
+
+local next = next
+
+-- --
+
+local sequencers = utilities.sequencers
+local appendaction = sequencers.appendaction
+local enableaction = sequencers.enableaction
+local disableaction = sequencers.disableaction
+
+local utffilters = characters.filters.utf
+
+local textfileactions = resolvers.openers.helpers.textfileactions
+local textlineactions = resolvers.openers.helpers.textlineactions
+
+appendaction (textfileactions,"system","characters.filters.utf.reorder")
+disableaction(textfileactions, "characters.filters.utf.reorder")
+
+appendaction (textlineactions,"system","characters.filters.utf.reorder")
+disableaction(textlineactions, "characters.filters.utf.reorder")
+
+appendaction (textfileactions,"system","characters.filters.utf.collapse")
+disableaction(textfileactions, "characters.filters.utf.collapse")
+
+appendaction (textfileactions,"system","characters.filters.utf.decompose")
+disableaction(textfileactions, "characters.filters.utf.decompose")
+
+local report = logs.reporter("unicode filter")
+local reporting = "no"
+
+-- this is messy as for performance reasons i don't want this to happen
+-- per line by default
+
+local enforced = {
+ ["characters.filters.utf.reorder"] = true,
+ ["characters.filters.utf.collapse"] = true,
+ ["characters.filters.utf.decompose"] = true,
+}
+
+function utffilters.enable()
+ for k, v in next, enforced do
+ if v then
+ if reporting == "yes" then
+ report("%a enabled",k)
+ end
+ enableaction(textfileactions,v)
+ else
+ if reporting == "yes" then
+ report("%a not enabled",k)
+ end
+ end
+ end
+ reporting = "never"
+end
+
+local function configure(what,v)
+ if v == "line" then
+ disableaction(textfileactions,what)
+ enableaction (textlineactions,what)
+ elseif not toboolean(v) then
+ if reporting ~= "never" then
+ report("%a disabled",k)
+ reporting = "yes"
+ end
+ enforced[what] = false
+ disableaction(textfileactions,what)
+ disableaction(textlineactions,what)
+ else -- true or text
+ enableaction (textfileactions,what)
+ disableaction(textlineactions,what)
+ end
+end
+
+directives.register("filters.utf.reorder", function(v) configure("characters.filters.utf.reorder", v) end)
+directives.register("filters.utf.collapse", function(v) configure("characters.filters.utf.collapse", v) end)
+directives.register("filters.utf.decompose", function(v) configure("characters.filters.utf.decompose",v) end)
+
+utffilters.setskippable { "mkiv", "mkvi", "mkix", "mkxi" }
+
+interfaces.implement {
+ name = "enableutf",
+ onlyonce = true,
+ actions = utffilters.enable
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua
new file mode 100644
index 00000000000..ad53cae8f34
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua
@@ -0,0 +1,1357 @@
+if not modules then modules = { } end modules ['char-ini'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: make two files, one for format generation, one for format use
+-- todo: move some to char-utf
+
+-- we can remove the tag range starting at 0xE0000 (special applications)
+
+local utfchar, utfbyte, utfvalues, ustring, utotable = utf.char, utf.byte, utf.values, utf.ustring, utf.totable
+local concat, unpack, tohash, insert = table.concat, table.unpack, table.tohash, table.insert
+local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
+local format, lower, gsub = string.format, string.lower, string.gsub
+local P, R, S, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs
+
+if not characters then require("char-def") end
+
+local lpegpatterns = lpeg.patterns
+local lpegmatch = lpeg.match
+local utf8byte = lpegpatterns.utf8byte
+local utf8character = lpegpatterns.utf8character
+
+local utfchartabletopattern = lpeg.utfchartabletopattern
+
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+
+local setmetatableindex = table.setmetatableindex
+
+local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end)
+
+local report_defining = logs.reporter("characters")
+
+--[[ldx--
+<p>This module implements some methods and creates additional datastructured
+from the big character table that we use for all kind of purposes:
+<type>char-def.lua</type>.</p>
+
+<p>We assume that at this point <type>characters.data</type> is already
+loaded!</p>
+--ldx]]--
+
+-- todo: in 'char-def.lua' assume defaults:
+--
+-- directtions = l
+-- cjkwd = a
+-- linebreak = al
+
+characters = characters or { }
+local characters = characters
+local data = characters.data
+
+if data then
+ mark(data) -- why does this fail
+else
+ report_defining("fatal error: 'char-def.lua' is not loaded")
+ os.exit()
+end
+
+--[[ldx--
+<p>This converts a string (if given) into a number.</p>
+--ldx]]--
+
+local pattern = (P("0x") + P("U+")) * ((R("09","AF")^1 * P(-1)) / function(s) return tonumber(s,16) end)
+
+lpegpatterns.chartonumber = pattern
+
+local function chartonumber(k)
+ if type(k) == "string" then
+ local u = lpegmatch(pattern,k)
+ if u then
+ return utfbyte(u)
+ else
+ return utfbyte(k) or 0
+ end
+ else
+ return k or 0
+ end
+end
+
+local function charfromnumber(k)
+ if type(k) == "number" then
+ return utfchar(k) or ""
+ else
+ local u = lpegmatch(pattern,k)
+ if u then
+ return utfchar(u)
+ else
+ return k
+ end
+ end
+end
+
+--~ print(chartonumber(97), chartonumber("a"), chartonumber("0x61"), chartonumber("U+61"))
+
+characters.tonumber = chartonumber
+characters.fromnumber = charfromnumber
+
+local private = {
+ description = "PRIVATE SLOT",
+}
+
+local ranges = allocate()
+characters.ranges = ranges
+
+setmetatableindex(data, function(t,k)
+ local tk = type(k)
+ if tk == "string" then
+ k = lpegmatch(pattern,k) or utfbyte(k)
+ if k then
+ local v = rawget(t,k)
+ if v then
+ return v
+ else
+ tk = "number" -- fall through to range
+ end
+ else
+ return private
+ end
+ end
+ if tk == "number" and k < 0xF0000 then
+ for r=1,#ranges do
+ local rr = ranges[r]
+ if k >= rr.first and k <= rr.last then
+ local extender = rr.extender
+ if extender then
+ local v = extender(k)
+ t[k] = v
+ return v
+ end
+ end
+ end
+ end
+ return private -- handy for when we loop over characters in fonts and check for a property
+end)
+
+local variant_selector_metatable = {
+ category = "mn",
+ cjkwd = "a",
+ direction = "nsm",
+ linebreak = "cm",
+}
+
+-- This saves a bit of memory and also serves as example.
+
+local f_variant = string.formatters["VARIATION SELECTOR-0x%04X"]
+
+insert(characters.ranges,{
+ first = 0xFE00,
+ last = 0xFE0F,
+ name = "variant selector",
+ extender = function(k)
+ local t = {
+ description = f_variant(k - 0xFE00 + 0x0001),
+ unicodeslot = k,
+ }
+ setmetatable(t,variant_selector_metatable)
+ return t
+ end,
+})
+
+insert(characters.ranges,{
+ first = 0xE0100,
+ last = 0xE01EF,
+ name = "variant selector extension",
+ extender = function(k)
+ local t = {
+ description = f_variant(k - 0xE0100 + 0x0011),
+ unicodeslot = k,
+ }
+ setmetatable(t,variant_selector_metatable)
+ return t
+ end,
+})
+
+local blocks = allocate {
+ ["aegeannumbers"] = { first = 0x10100, last = 0x1013F, description = "Aegean Numbers" },
+ ["ahom"] = { first = 0x11700, last = 0x1173F, description = "Ahom" },
+ ["alchemicalsymbols"] = { first = 0x1F700, last = 0x1F77F, description = "Alchemical Symbols" },
+ ["alphabeticpresentationforms"] = { first = 0x0FB00, last = 0x0FB4F, otf="latn", description = "Alphabetic Presentation Forms" },
+ ["anatolianhieroglyphs"] = { first = 0x14400, last = 0x1467F, description = "Anatolian Hieroglyphs" },
+ ["ancientgreekmusicalnotation"] = { first = 0x1D200, last = 0x1D24F, otf="grek", description = "Ancient Greek Musical Notation" },
+ ["ancientgreeknumbers"] = { first = 0x10140, last = 0x1018F, otf="grek", description = "Ancient Greek Numbers" },
+ ["ancientsymbols"] = { first = 0x10190, last = 0x101CF, otf="grek", description = "Ancient Symbols" },
+ ["arabic"] = { first = 0x00600, last = 0x006FF, otf="arab", description = "Arabic" },
+ ["arabicextendeda"] = { first = 0x008A0, last = 0x008FF, description = "Arabic Extended-A" },
+ ["arabicmathematicalalphabeticsymbols"] = { first = 0x1EE00, last = 0x1EEFF, description = "Arabic Mathematical Alphabetic Symbols" },
+ ["arabicpresentationformsa"] = { first = 0x0FB50, last = 0x0FDFF, otf="arab", description = "Arabic Presentation Forms-A" },
+ ["arabicpresentationformsb"] = { first = 0x0FE70, last = 0x0FEFF, otf="arab", description = "Arabic Presentation Forms-B" },
+ ["arabicsupplement"] = { first = 0x00750, last = 0x0077F, otf="arab", description = "Arabic Supplement" },
+ ["armenian"] = { first = 0x00530, last = 0x0058F, otf="armn", description = "Armenian" },
+ ["arrows"] = { first = 0x02190, last = 0x021FF, description = "Arrows" },
+ ["avestan"] = { first = 0x10B00, last = 0x10B3F, description = "Avestan" },
+ ["balinese"] = { first = 0x01B00, last = 0x01B7F, otf="bali", description = "Balinese" },
+ ["bamum"] = { first = 0x0A6A0, last = 0x0A6FF, description = "Bamum" },
+ ["bamumsupplement"] = { first = 0x16800, last = 0x16A3F, description = "Bamum Supplement" },
+ ["basiclatin"] = { first = 0x00000, last = 0x0007F, otf="latn", description = "Basic Latin" },
+ ["bassavah"] = { first = 0x16AD0, last = 0x16AFF, description = "Bassa Vah" },
+ ["batak"] = { first = 0x01BC0, last = 0x01BFF, description = "Batak" },
+ ["bengali"] = { first = 0x00980, last = 0x009FF, otf="beng", description = "Bengali" },
+ ["blockelements"] = { first = 0x02580, last = 0x0259F, otf="bopo", description = "Block Elements" },
+ ["bopomofo"] = { first = 0x03100, last = 0x0312F, otf="bopo", description = "Bopomofo" },
+ ["bopomofoextended"] = { first = 0x031A0, last = 0x031BF, otf="bopo", description = "Bopomofo Extended" },
+ ["boxdrawing"] = { first = 0x02500, last = 0x0257F, description = "Box Drawing" },
+ ["brahmi"] = { first = 0x11000, last = 0x1107F, description = "Brahmi" },
+ ["braillepatterns"] = { first = 0x02800, last = 0x028FF, otf="brai", description = "Braille Patterns" },
+ ["buginese"] = { first = 0x01A00, last = 0x01A1F, otf="bugi", description = "Buginese" },
+ ["buhid"] = { first = 0x01740, last = 0x0175F, otf="buhd", description = "Buhid" },
+ ["byzantinemusicalsymbols"] = { first = 0x1D000, last = 0x1D0FF, otf="byzm", description = "Byzantine Musical Symbols" },
+ ["carian"] = { first = 0x102A0, last = 0x102DF, description = "Carian" },
+ ["caucasianalbanian"] = { first = 0x10530, last = 0x1056F, description = "Caucasian Albanian" },
+ ["chakma"] = { first = 0x11100, last = 0x1114F, description = "Chakma" },
+ ["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" },
+ ["cherokee"] = { first = 0x013A0, last = 0x013FF, otf="cher", description = "Cherokee" },
+ ["cherokeesupplement"] = { first = 0x0AB70, last = 0x0ABBF, description = "Cherokee Supplement" },
+ ["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" },
+ ["cjkcompatibilityideographssupplement"] = { first = 0x2F800, last = 0x2FA1F, otf="hang", description = "CJK Compatibility Ideographs Supplement" },
+ ["cjkradicalssupplement"] = { first = 0x02E80, last = 0x02EFF, otf="hang", description = "CJK Radicals Supplement" },
+ ["cjkstrokes"] = { first = 0x031C0, last = 0x031EF, otf="hang", description = "CJK Strokes" },
+ ["cjksymbolsandpunctuation"] = { first = 0x03000, last = 0x0303F, otf="hang", description = "CJK Symbols and Punctuation" },
+ ["cjkunifiedideographs"] = { first = 0x04E00, last = 0x09FFF, otf="hang", description = "CJK Unified Ideographs", catcode = "letter" },
+ ["cjkunifiedideographsextensiona"] = { first = 0x03400, last = 0x04DBF, otf="hang", description = "CJK Unified Ideographs Extension A" },
+ ["cjkunifiedideographsextensionb"] = { first = 0x20000, last = 0x2A6DF, otf="hang", description = "CJK Unified Ideographs Extension B" },
+ ["cjkunifiedideographsextensionc"] = { first = 0x2A700, last = 0x2B73F, description = "CJK Unified Ideographs Extension C" },
+ ["cjkunifiedideographsextensiond"] = { first = 0x2B740, last = 0x2B81F, description = "CJK Unified Ideographs Extension D" },
+ ["cjkunifiedideographsextensione"] = { first = 0x2B820, last = 0x2CEAF, description = "CJK Unified Ideographs Extension E" },
+ ["combiningdiacriticalmarks"] = { first = 0x00300, last = 0x0036F, description = "Combining Diacritical Marks" },
+ ["combiningdiacriticalmarksextended"] = { first = 0x01AB0, last = 0x01AFF, description = "Combining Diacritical Marks Extended" },
+ ["combiningdiacriticalmarksforsymbols"] = { first = 0x020D0, last = 0x020FF, description = "Combining Diacritical Marks for Symbols" },
+ ["combiningdiacriticalmarkssupplement"] = { first = 0x01DC0, last = 0x01DFF, description = "Combining Diacritical Marks Supplement" },
+ ["combininghalfmarks"] = { first = 0x0FE20, last = 0x0FE2F, description = "Combining Half Marks" },
+ ["commonindicnumberforms"] = { first = 0x0A830, last = 0x0A83F, description = "Common Indic Number Forms" },
+ ["controlpictures"] = { first = 0x02400, last = 0x0243F, description = "Control Pictures" },
+ ["coptic"] = { first = 0x02C80, last = 0x02CFF, otf="copt", description = "Coptic" },
+ ["copticepactnumbers"] = { first = 0x102E0, last = 0x102FF, description = "Coptic Epact Numbers" },
+ ["countingrodnumerals"] = { first = 0x1D360, last = 0x1D37F, description = "Counting Rod Numerals" },
+ ["cuneiform"] = { first = 0x12000, last = 0x123FF, otf="xsux", description = "Cuneiform" },
+ ["cuneiformnumbersandpunctuation"] = { first = 0x12400, last = 0x1247F, otf="xsux", description = "Cuneiform Numbers and Punctuation" },
+ ["currencysymbols"] = { first = 0x020A0, last = 0x020CF, description = "Currency Symbols" },
+ ["cypriotsyllabary"] = { first = 0x10800, last = 0x1083F, otf="cprt", description = "Cypriot Syllabary" },
+ ["cyrillic"] = { first = 0x00400, last = 0x004FF, otf="cyrl", description = "Cyrillic" },
+ ["cyrillicextendeda"] = { first = 0x02DE0, last = 0x02DFF, otf="cyrl", description = "Cyrillic Extended-A" },
+ ["cyrillicextendedb"] = { first = 0x0A640, last = 0x0A69F, otf="cyrl", description = "Cyrillic Extended-B" },
+ ["cyrillicsupplement"] = { first = 0x00500, last = 0x0052F, otf="cyrl", description = "Cyrillic Supplement" },
+ ["deseret"] = { first = 0x10400, last = 0x1044F, otf="dsrt", description = "Deseret" },
+ ["devanagari"] = { first = 0x00900, last = 0x0097F, otf="deva", description = "Devanagari" },
+ ["devanagariextended"] = { first = 0x0A8E0, last = 0x0A8FF, description = "Devanagari Extended" },
+ ["digitsarabicindic"] = { first = 0x00660, last = 0x00669, math = true },
+ -- ["digitsbengali"] = { first = 0x009E6, last = 0x009EF, math = true },
+ ["digitsbold"] = { first = 0x1D7CE, last = 0x1D7D8, math = true },
+ -- ["digitsdevanagari"] = { first = 0x00966, last = 0x0096F, math = true },
+ ["digitsdoublestruck"] = { first = 0x1D7D8, last = 0x1D7E2, math = true },
+ -- ["digitsethiopic"] = { first = 0x01369, last = 0x01371, math = true },
+ ["digitsextendedarabicindic"] = { first = 0x006F0, last = 0x006F9, math = true },
+ -- ["digitsgujarati"] = { first = 0x00AE6, last = 0x00AEF, math = true },
+ -- ["digitsgurmukhi"] = { first = 0x00A66, last = 0x00A6F, math = true },
+ -- ["digitskannada"] = { first = 0x00CE6, last = 0x00CEF, math = true },
+ -- ["digitskhmer"] = { first = 0x017E0, last = 0x017E9, math = true },
+ -- ["digitslao"] = { first = 0x00ED0, last = 0x00ED9, math = true },
+ ["digitslatin"] = { first = 0x00030, last = 0x00039, math = true },
+ -- ["digitsmalayalam"] = { first = 0x00D66, last = 0x00D6F, math = true },
+ -- ["digitsmongolian"] = { first = 0x01810, last = 0x01809, math = true },
+ ["digitsmonospace"] = { first = 0x1D7F6, last = 0x1D80F, math = true },
+ -- ["digitsmyanmar"] = { first = 0x01040, last = 0x01049, math = true },
+ ["digitsnormal"] = { first = 0x00030, last = 0x00039, math = true },
+ -- ["digitsoriya"] = { first = 0x00B66, last = 0x00B6F, math = true },
+ ["digitssansserifbold"] = { first = 0x1D7EC, last = 0x1D805, math = true },
+ ["digitssansserifnormal"] = { first = 0x1D7E2, last = 0x1D7EC, math = true },
+ -- ["digitstamil"] = { first = 0x00030, last = 0x00039, math = true }, -- no zero
+ -- ["digitstelugu"] = { first = 0x00C66, last = 0x00C6F, math = true },
+ -- ["digitsthai"] = { first = 0x00E50, last = 0x00E59, math = true },
+ -- ["digitstibetan"] = { first = 0x00F20, last = 0x00F29, math = true },
+ ["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" },
+ ["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" },
+ ["duployan"] = { first = 0x1BC00, last = 0x1BC9F, description = "Duployan" },
+ ["earlydynasticcuneiform"] = { first = 0x12480, last = 0x1254F, description = "Early Dynastic Cuneiform" },
+ ["egyptianhieroglyphs"] = { first = 0x13000, last = 0x1342F, description = "Egyptian Hieroglyphs" },
+ ["elbasan"] = { first = 0x10500, last = 0x1052F, description = "Elbasan" },
+ ["emoticons"] = { first = 0x1F600, last = 0x1F64F, description = "Emoticons" },
+ ["enclosedalphanumerics"] = { first = 0x02460, last = 0x024FF, description = "Enclosed Alphanumerics" },
+ ["enclosedalphanumericsupplement"] = { first = 0x1F100, last = 0x1F1FF, description = "Enclosed Alphanumeric Supplement" },
+ ["enclosedcjklettersandmonths"] = { first = 0x03200, last = 0x032FF, description = "Enclosed CJK Letters and Months" },
+ ["enclosedideographicsupplement"] = { first = 0x1F200, last = 0x1F2FF, description = "Enclosed Ideographic Supplement" },
+ ["ethiopic"] = { first = 0x01200, last = 0x0137F, otf="ethi", description = "Ethiopic" },
+ ["ethiopicextended"] = { first = 0x02D80, last = 0x02DDF, otf="ethi", description = "Ethiopic Extended" },
+ ["ethiopicextendeda"] = { first = 0x0AB00, last = 0x0AB2F, description = "Ethiopic Extended-A" },
+ ["ethiopicsupplement"] = { first = 0x01380, last = 0x0139F, otf="ethi", description = "Ethiopic Supplement" },
+ ["generalpunctuation"] = { first = 0x02000, last = 0x0206F, description = "General Punctuation" },
+ ["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" },
+ ["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, otf="geor", description = "Georgian Supplement" },
+ ["glagolitic"] = { first = 0x02C00, last = 0x02C5F, otf="glag", description = "Glagolitic" },
+ ["gothic"] = { first = 0x10330, last = 0x1034F, otf="goth", description = "Gothic" },
+ ["grantha"] = { first = 0x11300, last = 0x1137F, description = "Grantha" },
+ ["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" },
+ ["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" },
+ ["hanguljamo"] = { first = 0x01100, last = 0x011FF, otf="jamo", description = "Hangul Jamo" },
+ ["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" },
+ ["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" },
+ ["highprivateusesurrogates"] = { first = 0x0DB80, last = 0x0DBFF, description = "High Private Use Surrogates" },
+ ["highsurrogates"] = { first = 0x0D800, last = 0x0DB7F, description = "High Surrogates" },
+ ["hiragana"] = { first = 0x03040, last = 0x0309F, otf="kana", description = "Hiragana" },
+ ["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" },
+ ["imperialaramaic"] = { first = 0x10840, last = 0x1085F, description = "Imperial Aramaic" },
+ ["inscriptionalpahlavi"] = { first = 0x10B60, last = 0x10B7F, description = "Inscriptional Pahlavi" },
+ ["inscriptionalparthian"] = { first = 0x10B40, last = 0x10B5F, description = "Inscriptional Parthian" },
+ ["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" },
+ ["javanese"] = { first = 0x0A980, last = 0x0A9DF, description = "Javanese" },
+ ["kaithi"] = { first = 0x11080, last = 0x110CF, description = "Kaithi" },
+ ["kanasupplement"] = { first = 0x1B000, last = 0x1B0FF, description = "Kana Supplement" },
+ ["kanbun"] = { first = 0x03190, last = 0x0319F, description = "Kanbun" },
+ ["kangxiradicals"] = { first = 0x02F00, last = 0x02FDF, description = "Kangxi Radicals" },
+ ["kannada"] = { first = 0x00C80, last = 0x00CFF, otf="knda", description = "Kannada" },
+ ["katakana"] = { first = 0x030A0, last = 0x030FF, otf="kana", description = "Katakana" },
+ ["katakanaphoneticextensions"] = { first = 0x031F0, last = 0x031FF, otf="kana", description = "Katakana Phonetic Extensions" },
+ ["kayahli"] = { first = 0x0A900, last = 0x0A92F, description = "Kayah Li" },
+ ["kharoshthi"] = { first = 0x10A00, last = 0x10A5F, otf="khar", description = "Kharoshthi" },
+ ["khmer"] = { first = 0x01780, last = 0x017FF, otf="khmr", description = "Khmer" },
+ ["khmersymbols"] = { first = 0x019E0, last = 0x019FF, otf="khmr", description = "Khmer Symbols" },
+ ["khojki"] = { first = 0x11200, last = 0x1124F, description = "Khojki" },
+ ["khudawadi"] = { first = 0x112B0, last = 0x112FF, description = "Khudawadi" },
+ ["lao"] = { first = 0x00E80, last = 0x00EFF, otf="lao", description = "Lao" },
+ ["latinextendeda"] = { first = 0x00100, last = 0x0017F, otf="latn", description = "Latin Extended-A" },
+ ["latinextendedadditional"] = { first = 0x01E00, last = 0x01EFF, otf="latn", description = "Latin Extended Additional" },
+ ["latinextendedb"] = { first = 0x00180, last = 0x0024F, otf="latn", description = "Latin Extended-B" },
+ ["latinextendedc"] = { first = 0x02C60, last = 0x02C7F, otf="latn", description = "Latin Extended-C" },
+ ["latinextendedd"] = { first = 0x0A720, last = 0x0A7FF, otf="latn", description = "Latin Extended-D" },
+ ["latinextendede"] = { first = 0x0AB30, last = 0x0AB6F, description = "Latin Extended-E" },
+ ["latinsupplement"] = { first = 0x00080, last = 0x000FF, otf="latn", description = "Latin-1 Supplement" },
+ ["lepcha"] = { first = 0x01C00, last = 0x01C4F, description = "Lepcha" },
+ ["letterlikesymbols"] = { first = 0x02100, last = 0x0214F, math = true, description = "Letterlike Symbols" },
+ ["limbu"] = { first = 0x01900, last = 0x0194F, otf="limb", description = "Limbu" },
+ ["lineara"] = { first = 0x10600, last = 0x1077F, description = "Linear A" },
+ ["linearbideograms"] = { first = 0x10080, last = 0x100FF, otf="linb", description = "Linear B Ideograms" },
+ ["linearbsyllabary"] = { first = 0x10000, last = 0x1007F, otf="linb", description = "Linear B Syllabary" },
+ ["lisu"] = { first = 0x0A4D0, last = 0x0A4FF, description = "Lisu" },
+ ["lowercasebold"] = { first = 0x1D41A, last = 0x1D433, math = true },
+ ["lowercaseboldfraktur"] = { first = 0x1D586, last = 0x1D59F, math = true },
+ ["lowercasebolditalic"] = { first = 0x1D482, last = 0x1D49B, math = true },
+ ["lowercaseboldscript"] = { first = 0x1D4EA, last = 0x1D503, math = true },
+ ["lowercasedoublestruck"] = { first = 0x1D552, last = 0x1D56B, math = true },
+ ["lowercasefraktur"] = { first = 0x1D51E, last = 0x1D537, math = true },
+ ["lowercasegreekbold"] = { first = 0x1D6C2, last = 0x1D6DB, math = true },
+ ["lowercasegreekbolditalic"] = { first = 0x1D736, last = 0x1D74F, math = true },
+ ["lowercasegreekitalic"] = { first = 0x1D6FC, last = 0x1D715, math = true },
+ ["lowercasegreeknormal"] = { first = 0x003B1, last = 0x003CA, math = true },
+ ["lowercasegreeksansserifbold"] = { first = 0x1D770, last = 0x1D789, math = true },
+ ["lowercasegreeksansserifbolditalic"] = { first = 0x1D7AA, last = 0x1D7C3, math = true },
+ ["lowercaseitalic"] = { first = 0x1D44E, last = 0x1D467, math = true },
+ ["lowercasemonospace"] = { first = 0x1D68A, last = 0x1D6A3, math = true },
+ ["lowercasenormal"] = { first = 0x00061, last = 0x0007A, math = true },
+ ["lowercasesansserifbold"] = { first = 0x1D5EE, last = 0x1D607, math = true },
+ ["lowercasesansserifbolditalic"] = { first = 0x1D656, last = 0x1D66F, math = true },
+ ["lowercasesansserifitalic"] = { first = 0x1D622, last = 0x1D63B, math = true },
+ ["lowercasesansserifnormal"] = { first = 0x1D5BA, last = 0x1D5D3, math = true },
+ ["lowercasescript"] = { first = 0x1D4B6, last = 0x1D4CF, math = true },
+ ["lowsurrogates"] = { first = 0x0DC00, last = 0x0DFFF, description = "Low Surrogates" },
+ ["lycian"] = { first = 0x10280, last = 0x1029F, description = "Lycian" },
+ ["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" },
+ ["mahajani"] = { first = 0x11150, last = 0x1117F, description = "Mahajani" },
+ ["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" },
+ ["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" },
+ ["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, math = true, description = "Mathematical Alphanumeric Symbols" },
+ ["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, math = true, description = "Mathematical Operators" },
+ ["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" },
+ ["meroiticcursive"] = { first = 0x109A0, last = 0x109FF, description = "Meroitic Cursive" },
+ ["meroitichieroglyphs"] = { first = 0x10980, last = 0x1099F, description = "Meroitic Hieroglyphs" },
+ ["miao"] = { first = 0x16F00, last = 0x16F9F, description = "Miao" },
+ ["miscellaneousmathematicalsymbolsa"] = { first = 0x027C0, last = 0x027EF, math = true, description = "Miscellaneous Mathematical Symbols-A" },
+ ["miscellaneousmathematicalsymbolsb"] = { first = 0x02980, last = 0x029FF, math = true, description = "Miscellaneous Mathematical Symbols-B" },
+ ["miscellaneoussymbols"] = { first = 0x02600, last = 0x026FF, math = true, description = "Miscellaneous Symbols" },
+ ["miscellaneoussymbolsandarrows"] = { first = 0x02B00, last = 0x02BFF, math = true, description = "Miscellaneous Symbols and Arrows" },
+ ["miscellaneoussymbolsandpictographs"] = { first = 0x1F300, last = 0x1F5FF, description = "Miscellaneous Symbols and Pictographs" },
+ ["miscellaneoustechnical"] = { first = 0x02300, last = 0x023FF, math = true, description = "Miscellaneous Technical" },
+ ["modi"] = { first = 0x11600, last = 0x1165F, description = "Modi" },
+ ["modifiertoneletters"] = { first = 0x0A700, last = 0x0A71F, description = "Modifier Tone Letters" },
+ ["mongolian"] = { first = 0x01800, last = 0x018AF, otf="mong", description = "Mongolian" },
+ ["mro"] = { first = 0x16A40, last = 0x16A6F, description = "Mro" },
+ ["multani"] = { first = 0x11280, last = 0x112AF, description = "Multani" },
+ ["musicalsymbols"] = { first = 0x1D100, last = 0x1D1FF, otf="musc", description = "Musical Symbols" },
+ ["myanmar"] = { first = 0x01000, last = 0x0109F, otf="mymr", description = "Myanmar" },
+ ["myanmarextendeda"] = { first = 0x0AA60, last = 0x0AA7F, description = "Myanmar Extended-A" },
+ ["myanmarextendedb"] = { first = 0x0A9E0, last = 0x0A9FF, description = "Myanmar Extended-B" },
+ ["nabataean"] = { first = 0x10880, last = 0x108AF, description = "Nabataean" },
+ ["newtailue"] = { first = 0x01980, last = 0x019DF, description = "New Tai Lue" },
+ ["nko"] = { first = 0x007C0, last = 0x007FF, otf="nko", description = "NKo" },
+ ["numberforms"] = { first = 0x02150, last = 0x0218F, description = "Number Forms" },
+ ["ogham"] = { first = 0x01680, last = 0x0169F, otf="ogam", description = "Ogham" },
+ ["olchiki"] = { first = 0x01C50, last = 0x01C7F, description = "Ol Chiki" },
+ ["oldhungarian"] = { first = 0x10C80, last = 0x10CFF, description = "Old Hungarian" },
+ ["olditalic"] = { first = 0x10300, last = 0x1032F, otf="ital", description = "Old Italic" },
+ ["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" },
+ ["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" },
+ ["oriya"] = { first = 0x00B00, last = 0x00B7F, otf="orya", description = "Oriya" },
+ ["ornamentaldingbats"] = { first = 0x1F650, last = 0x1F67F, description = "Ornamental Dingbats" },
+ ["osmanya"] = { first = 0x10480, last = 0x104AF, otf="osma", description = "Osmanya" },
+ ["pahawhhmong"] = { first = 0x16B00, last = 0x16B8F, description = "Pahawh Hmong" },
+ ["palmyrene"] = { first = 0x10860, last = 0x1087F, description = "Palmyrene" },
+ ["paucinhau"] = { first = 0x11AC0, last = 0x11AFF, description = "Pau Cin Hau" },
+ ["phagspa"] = { first = 0x0A840, last = 0x0A87F, otf="phag", description = "Phags-pa" },
+ ["phaistosdisc"] = { first = 0x101D0, last = 0x101FF, description = "Phaistos Disc" },
+ ["phoenician"] = { first = 0x10900, last = 0x1091F, otf="phnx", description = "Phoenician" },
+ ["phoneticextensions"] = { first = 0x01D00, last = 0x01D7F, description = "Phonetic Extensions" },
+ ["phoneticextensionssupplement"] = { first = 0x01D80, last = 0x01DBF, description = "Phonetic Extensions Supplement" },
+ ["playingcards"] = { first = 0x1F0A0, last = 0x1F0FF, description = "Playing Cards" },
+ ["privateusearea"] = { first = 0x0E000, last = 0x0F8FF, description = "Private Use Area" },
+ ["psalterpahlavi"] = { first = 0x10B80, last = 0x10BAF, description = "Psalter Pahlavi" },
+ ["rejang"] = { first = 0x0A930, last = 0x0A95F, description = "Rejang" },
+ ["ruminumeralsymbols"] = { first = 0x10E60, last = 0x10E7F, description = "Rumi Numeral Symbols" },
+ ["runic"] = { first = 0x016A0, last = 0x016FF, otf="runr", description = "Runic" },
+ ["samaritan"] = { first = 0x00800, last = 0x0083F, description = "Samaritan" },
+ ["saurashtra"] = { first = 0x0A880, last = 0x0A8DF, description = "Saurashtra" },
+ ["sharada"] = { first = 0x11180, last = 0x111DF, description = "Sharada" },
+ ["shavian"] = { first = 0x10450, last = 0x1047F, otf="shaw", description = "Shavian" },
+ ["shorthandformatcontrols"] = { first = 0x1BCA0, last = 0x1BCAF, description = "Shorthand Format Controls" },
+ ["siddham"] = { first = 0x11580, last = 0x115FF, description = "Siddham" },
+ ["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" },
+ ["sorasompeng"] = { first = 0x110D0, last = 0x110FF, description = "Sora Sompeng" },
+ ["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" },
+ ["specials"] = { first = 0x0FFF0, last = 0x0FFFF, description = "Specials" },
+ ["sundanese"] = { first = 0x01B80, last = 0x01BBF, description = "Sundanese" },
+ ["sundanesesupplement"] = { first = 0x01CC0, last = 0x01CCF, description = "Sundanese Supplement" },
+ ["superscriptsandsubscripts"] = { first = 0x02070, last = 0x0209F, description = "Superscripts and Subscripts" },
+ ["supplementalarrowsa"] = { first = 0x027F0, last = 0x027FF, math = true, description = "Supplemental Arrows-A" },
+ ["supplementalarrowsb"] = { first = 0x02900, last = 0x0297F, math = true, description = "Supplemental Arrows-B" },
+ ["supplementalarrowsc"] = { first = 0x1F800, last = 0x1F8FF, math = true, description = "Supplemental Arrows-C" },
+ ["supplementalmathematicaloperators"] = { first = 0x02A00, last = 0x02AFF, math = true, description = "Supplemental Mathematical Operators" },
+ ["supplementalpunctuation"] = { first = 0x02E00, last = 0x02E7F, description = "Supplemental Punctuation" },
+ ["supplementalsymbolsandpictographs"] = { first = 0x1F900, last = 0x1F9FF, description = "Supplemental Symbols and Pictographs" },
+ ["supplementaryprivateuseareaa"] = { first = 0xF0000, last = 0xFFFFF, description = "Supplementary Private Use Area-A" },
+ ["supplementaryprivateuseareab"] = { first = 0x100000,last = 0x10FFFF, description = "Supplementary Private Use Area-B" },
+ ["suttonsignwriting"] = { first = 0x1D800, last = 0x1DAAF, description = "Sutton SignWriting" },
+ ["sylotinagri"] = { first = 0x0A800, last = 0x0A82F, otf="sylo", description = "Syloti Nagri" },
+ ["syriac"] = { first = 0x00700, last = 0x0074F, otf="syrc", description = "Syriac" },
+ ["tagalog"] = { first = 0x01700, last = 0x0171F, otf="tglg", description = "Tagalog" },
+ ["tagbanwa"] = { first = 0x01760, last = 0x0177F, otf="tagb", description = "Tagbanwa" },
+ ["tags"] = { first = 0xE0000, last = 0xE007F, description = "Tags" },
+ ["taile"] = { first = 0x01950, last = 0x0197F, otf="tale", description = "Tai Le" },
+ ["taitham"] = { first = 0x01A20, last = 0x01AAF, description = "Tai Tham" },
+ ["taiviet"] = { first = 0x0AA80, last = 0x0AADF, description = "Tai Viet" },
+ ["taixuanjingsymbols"] = { first = 0x1D300, last = 0x1D35F, description = "Tai Xuan Jing Symbols" },
+ ["takri"] = { first = 0x11680, last = 0x116CF, description = "Takri" },
+ ["tamil"] = { first = 0x00B80, last = 0x00BFF, otf="taml", description = "Tamil" },
+ ["telugu"] = { first = 0x00C00, last = 0x00C7F, otf="telu", description = "Telugu" },
+ ["thaana"] = { first = 0x00780, last = 0x007BF, otf="thaa", description = "Thaana" },
+ ["thai"] = { first = 0x00E00, last = 0x00E7F, otf="thai", description = "Thai" },
+ ["tibetan"] = { first = 0x00F00, last = 0x00FFF, otf="tibt", description = "Tibetan" },
+ ["tifinagh"] = { first = 0x02D30, last = 0x02D7F, otf="tfng", description = "Tifinagh" },
+ ["tirhuta"] = { first = 0x11480, last = 0x114DF, description = "Tirhuta" },
+ ["transportandmapsymbols"] = { first = 0x1F680, last = 0x1F6FF, description = "Transport and Map Symbols" },
+ ["ugaritic"] = { first = 0x10380, last = 0x1039F, otf="ugar", description = "Ugaritic" },
+ ["unifiedcanadianaboriginalsyllabics"] = { first = 0x01400, last = 0x0167F, otf="cans", description = "Unified Canadian Aboriginal Syllabics" },
+ ["unifiedcanadianaboriginalsyllabicsextended"] = { first = 0x018B0, last = 0x018FF, description = "Unified Canadian Aboriginal Syllabics Extended" },
+ ["uppercasebold"] = { first = 0x1D400, last = 0x1D419, math = true },
+ ["uppercaseboldfraktur"] = { first = 0x1D56C, last = 0x1D585, math = true },
+ ["uppercasebolditalic"] = { first = 0x1D468, last = 0x1D481, math = true },
+ ["uppercaseboldscript"] = { first = 0x1D4D0, last = 0x1D4E9, math = true },
+ ["uppercasedoublestruck"] = { first = 0x1D538, last = 0x1D551, math = true },
+ ["uppercasefraktur"] = { first = 0x1D504, last = 0x1D51D, math = true },
+ ["uppercasegreekbold"] = { first = 0x1D6A8, last = 0x1D6C1, math = true },
+ ["uppercasegreekbolditalic"] = { first = 0x1D71C, last = 0x1D735, math = true },
+ ["uppercasegreekitalic"] = { first = 0x1D6E2, last = 0x1D6FB, math = true },
+ ["uppercasegreeknormal"] = { first = 0x00391, last = 0x003AA, math = true },
+ ["uppercasegreeksansserifbold"] = { first = 0x1D756, last = 0x1D76F, math = true },
+ ["uppercasegreeksansserifbolditalic"] = { first = 0x1D790, last = 0x1D7A9, math = true },
+ ["uppercaseitalic"] = { first = 0x1D434, last = 0x1D44D, math = true },
+ ["uppercasemonospace"] = { first = 0x1D670, last = 0x1D689, math = true },
+ ["uppercasenormal"] = { first = 0x00041, last = 0x0005A, math = true },
+ ["uppercasesansserifbold"] = { first = 0x1D5D4, last = 0x1D5ED, math = true },
+ ["uppercasesansserifbolditalic"] = { first = 0x1D63C, last = 0x1D655, math = true },
+ ["uppercasesansserifitalic"] = { first = 0x1D608, last = 0x1D621, math = true },
+ ["uppercasesansserifnormal"] = { first = 0x1D5A0, last = 0x1D5B9, math = true },
+ ["uppercasescript"] = { first = 0x1D49C, last = 0x1D4B5, math = true },
+ ["vai"] = { first = 0x0A500, last = 0x0A63F, description = "Vai" },
+ ["variationselectors"] = { first = 0x0FE00, last = 0x0FE0F, description = "Variation Selectors" },
+ ["variationselectorssupplement"] = { first = 0xE0100, last = 0xE01EF, description = "Variation Selectors Supplement" },
+ ["vedicextensions"] = { first = 0x01CD0, last = 0x01CFF, description = "Vedic Extensions" },
+ ["verticalforms"] = { first = 0x0FE10, last = 0x0FE1F, description = "Vertical Forms" },
+ ["warangciti"] = { first = 0x118A0, last = 0x118FF, description = "Warang Citi" },
+ ["yijinghexagramsymbols"] = { first = 0x04DC0, last = 0x04DFF, otf="yi", description = "Yijing Hexagram Symbols" },
+ ["yiradicals"] = { first = 0x0A490, last = 0x0A4CF, otf="yi", description = "Yi Radicals" },
+ ["yisyllables"] = { first = 0x0A000, last = 0x0A48F, otf="yi", description = "Yi Syllables" },
+}
+
+characters.blocks = blocks
+
+function characters.blockrange(name)
+ local b = blocks[name]
+ if b then
+ return b.first, b.last
+ else
+ return 0, 0
+ end
+end
+
+setmetatableindex(blocks, function(t,k) -- we could use an intermediate table if called often
+ return k and rawget(t,lower(gsub(k,"[^a-zA-Z]","")))
+end)
+
+local otfscripts = utilities.storage.allocate()
+characters.otfscripts = otfscripts
+
+setmetatableindex(otfscripts,function(t,unicode)
+ for k, v in next, blocks do
+ local first, last = v.first, v.last
+ if unicode >= first and unicode <= last then
+ local script = v.otf or "dflt"
+ for u=first,last do
+ t[u] = script
+ end
+ return script
+ end
+ end
+ -- pretty slow when we're here
+ t[unicode] = "dflt"
+ return "dflt"
+end)
+
+local splitter = lpeg.splitat(S(":-"))
+
+function characters.getrange(name) -- used in font fallback definitions (name or range)
+ local range = blocks[name]
+ if range then
+ return range.first, range.last, range.description, range.gaps
+ end
+ name = gsub(name,'"',"0x") -- goodie: tex hex notation
+ local start, stop = lpegmatch(splitter,name)
+ if start and stop then
+ start, stop = tonumber(start,16) or tonumber(start), tonumber(stop,16) or tonumber(stop)
+ if start and stop then
+ return start, stop, nil
+ end
+ end
+ local slot = tonumber(name,16) or tonumber(name)
+ return slot, slot, nil
+end
+
+local categorytags = allocate {
+ lu = "Letter Uppercase",
+ ll = "Letter Lowercase",
+ lt = "Letter Titlecase",
+ lm = "Letter Modifier",
+ lo = "Letter Other",
+ mn = "Mark Nonspacing",
+ mc = "Mark Spacing Combining",
+ me = "Mark Enclosing",
+ nd = "Number Decimal Digit",
+ nl = "Number Letter",
+ no = "Number Other",
+ pc = "Punctuation Connector",
+ pd = "Punctuation Dash",
+ ps = "Punctuation Open",
+ pe = "Punctuation Close",
+ pi = "Punctuation Initial Quote",
+ pf = "Punctuation Final Quote",
+ po = "Punctuation Other",
+ sm = "Symbol Math",
+ sc = "Symbol Currency",
+ sk = "Symbol Modifier",
+ so = "Symbol Other",
+ zs = "Separator Space",
+ zl = "Separator Line",
+ zp = "Separator Paragraph",
+ cc = "Other Control",
+ cf = "Other Format",
+ cs = "Other Surrogate",
+ co = "Other Private Use",
+ cn = "Other Not Assigned",
+}
+
+local detailtags = allocate {
+ sl = "small letter",
+ bl = "big letter",
+ im = "iteration mark",
+ pm = "prolonged sound mark"
+}
+
+characters.categorytags = categorytags
+characters.detailtags = detailtags
+
+-- sounds : voiced unvoiced semivoiced
+
+--~ special : cf (softhyphen) zs (emspace)
+--~ characters: ll lm lo lt lu mn nl no pc pd pe pf pi po ps sc sk sm so
+
+local is_character = allocate ( tohash {
+ "lu","ll","lt","lm","lo",
+ "nd","nl","no",
+ "mn",
+ "nl","no",
+ "pc","pd","ps","pe","pi","pf","po",
+ "sm","sc","sk","so"
+} )
+
+local is_letter = allocate ( tohash {
+ "ll","lm","lo","lt","lu"
+} )
+
+local is_command = allocate ( tohash {
+ "cf","zs"
+} )
+
+local is_spacing = allocate ( tohash {
+ "zs", "zl","zp",
+} )
+
+local is_mark = allocate ( tohash {
+ "mn", "ms",
+} )
+
+local is_punctuation = allocate ( tohash {
+ "pc","pd","ps","pe","pi","pf","po",
+} )
+
+-- to be redone: store checked characters
+
+characters.is_character = is_character
+characters.is_letter = is_letter
+characters.is_command = is_command
+characters.is_spacing = is_spacing
+characters.is_mark = is_mark
+characters.is_punctuation = is_punctuation
+
+local mti = function(t,k)
+ if type(k) == "number" then
+ local c = data[k].category
+ return c and rawget(t,c)
+ else
+ -- avoid auto conversion in data.characters lookups
+ end
+end
+
+setmetatableindex(characters.is_character, mti)
+setmetatableindex(characters.is_letter, mti)
+setmetatableindex(characters.is_command, mti)
+setmetatableindex(characters.is_spacing, mti)
+setmetatableindex(characters.is_punctuation,mti)
+
+-- todo: also define callers for the above
+
+-- linebreak: todo: hash
+--
+-- normative : BK CR LF CM SG GL CB SP ZW NL WJ JL JV JT H2 H3
+-- informative : XX OP CL CP QU NS EX SY IS PR PO NU AL ID IN HY BB BA SA AI B2 HL CJ RI
+--
+-- comments taken from standard:
+
+characters.linebreaks = {
+
+ -- non-tailorable line breaking classes
+
+ ["bk"] = "mandatory break", -- nl, ps : cause a line break (after)
+ ["cr"] = "carriage return", -- cr : cause a line break (after), except between cr and lf
+ ["lf"] = "line feed", -- lf : cause a line break (after)
+ ["cm"] = "combining mark", -- combining marks, control codes : prohibit a line break between the character and the preceding character
+ ["nl"] = "next line", -- nel : cause a line break (after)
+ ["sg"] = "surrogate", -- surrogates :do not occur in well-formed text
+ ["wj"] = "word joiner", -- wj : prohibit line breaks before and after
+ ["zw"] = "zero width space", -- zwsp : provide a break opportunity
+ ["gl"] = "non-breaking (glue)", -- cgj, nbsp, zwnbsp : prohibit line breaks before and after
+ ["sp"] = "space", -- space : enable indirect line breaks
+
+ -- break opportunities
+
+ ["b2"] = "break opportunity before and after", -- em dash : provide a line break opportunity before and after the character
+ ["ba"] = "break after", -- spaces, hyphens : generally provide a line break opportunity after the character
+ ["bb"] = "break before", -- punctuation used in dictionaries : generally provide a line break opportunity before the character
+ ["hy"] = "hyphen", -- hyphen-minus : provide a line break opportunity after the character, except in numeric context
+ ["cb"] = "contingent break opportunity", -- inline objects : provide a line break opportunity contingent on additional information
+
+ -- characters prohibiting certain breaks
+
+ ["cl"] = "close punctuation", -- “}”, “❳”, “⟫” etc. : prohibit line breaks before
+ ["cp"] = "close parenthesis", -- “)”, “]” : prohibit line breaks before
+ ["ex"] = "exclamation/interrogation", -- “!”, “?”, etc. : prohibit line breaks before
+ ["in"] = "inseparable", -- leaders : allow only indirect line breaks between pairs
+ ["ns"] = "nonstarter", -- “‼”, “‽”, “⁇”, “⁉”, etc. : allow only indirect line breaks before
+ ["op"] = "open punctuation", -- “(“, “[“, “{“, etc. : prohibit line breaks after
+ ["qu"] = "quotation", -- quotation marks : act like they are both opening and closing
+
+ -- numeric context
+
+ ["is"] = "infix numeric separator", -- . , : prevent breaks after any and before numeric
+ ["nu"] = "numeric", -- digits : form numeric expressions for line breaking purposes
+ ["po"] = "postfix numeric", -- %, ¢ : do not break following a numeric expression
+ ["pr"] = "prefix numeric", -- $, £, ¥, etc. : do not break in front of a numeric expression
+ ["sy"] = "symbols allowing break after", -- / : prevent a break before, and allow a break after
+
+ -- other characters
+
+ ["ai"] = "ambiguous (alphabetic or ideographic)", -- characters with ambiguous east asian width : act like al when the resolved eaw is n; otherwise, act as id
+ ["al"] = "alphabetic", -- alphabets and regular symbols : are alphabetic characters or symbols that are used with alphabetic characters
+ ["cj"] = "conditional japanese starter", -- small kana : treat as ns or id for strict or normal breaking.
+ ["h2"] = "hangul lv syllable", -- hangul : form korean syllable blocks
+ ["h3"] = "hangul lvt syllable", -- hangul : form korean syllable blocks
+ ["hl"] = "hebrew letter", -- hebrew : do not break around a following hyphen; otherwise act as alphabetic
+ ["id"] = "ideographic", -- ideographs : break before or after, except in some numeric context
+ ["jl"] = "hangul l jamo", -- conjoining jamo : form korean syllable blocks
+ ["jv"] = "hangul v jamo", -- conjoining jamo : form korean syllable blocks
+ ["jt"] = "hangul t jamo", -- conjoining jamo : form korean syllable blocks
+ ["ri"] = "regional indicator", -- regional indicator symbol letter a .. z : keep together, break before and after from others
+ ["sa"] = "complex context dependent (south east asian)", -- south east asian: thai, lao, khmer : provide a line break opportunity contingent on additional, language-specific context analysis
+ ["xx"] = "unknown", -- most unassigned, private-use : have as yet unknown line breaking behavior or unassigned code positions
+
+}
+
+-- east asian width:
+--
+-- N A H W F Na
+
+characters.bidi = allocate {
+ l = "Left-to-Right",
+ lre = "Left-to-Right Embedding",
+ lro = "Left-to-Right Override",
+ r = "Right-to-Left",
+ al = "Right-to-Left Arabic",
+ rle = "Right-to-Left Embedding",
+ rlo = "Right-to-Left Override",
+ pdf = "Pop Directional Format",
+ en = "European Number",
+ es = "European Number Separator",
+ et = "European Number Terminator",
+ an = "Arabic Number",
+ cs = "Common Number Separator",
+ nsm = "Non-Spacing Mark",
+ bn = "Boundary Neutral",
+ b = "Paragraph Separator",
+ s = "Segment Separator",
+ ws = "Whitespace",
+ on = "Other Neutrals",
+}
+
+--[[ldx--
+<p>At this point we assume that the big data table is loaded. From this
+table we derive a few more.</p>
+--ldx]]--
+
+if not characters.fallbacks then
+
+ characters.fallbacks = {
+ [0x0308] = 0x00A8, [0x00A8] = 0x0308, -- dieresiscmb dieresis
+ [0x0304] = 0x00AF, [0x00AF] = 0x0304, -- macroncmb macron
+ [0x0301] = 0x00B4, [0x00B4] = 0x0301, -- acutecomb acute
+ [0x0327] = 0x00B8, [0x00B8] = 0x0327, -- cedillacmb cedilla
+ [0x0302] = 0x02C6, [0x02C6] = 0x0302, -- circumflexcmb circumflex
+ [0x030C] = 0x02C7, [0x02C7] = 0x030C, -- caroncmb caron
+ [0x0306] = 0x02D8, [0x02D8] = 0x0306, -- brevecmb breve
+ [0x0307] = 0x02D9, [0x02D9] = 0x0307, -- dotaccentcmb dotaccent
+ [0x030A] = 0x02DA, [0x02DA] = 0x030A, -- ringcmb ring
+ [0x0328] = 0x02DB, [0x02DB] = 0x0328, -- ogonekcmb ogonek
+ [0x0303] = 0x02DC, [0x02DC] = 0x0303, -- tildecomb tilde
+ [0x030B] = 0x02DD, [0x02DD] = 0x030B, -- hungarumlautcmb hungarumlaut
+ [0x0305] = 0x203E, [0x203E] = 0x0305, -- overlinecmb overline
+ [0x0300] = 0x0060, [0x0060] = 0x0333, -- gravecomb grave
+ }
+
+ -- not done (would mess up mapping):
+ --
+ -- 0X0301/0X0384 0X0314/0X1FFE 0X0313/0X1FBD 0X0313/0X1FBF 0X0342/0X1FC0
+ -- 0X3099/0X309B 0X309A/0X309C 0X0333/0X2017 0X0345/0X037A
+
+end
+
+if storage then
+ storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
+end
+
+characters.directions = { }
+
+setmetatableindex(characters.directions,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.direction
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false -- maybe 'l'
+ return v
+end)
+
+characters.mirrors = { }
+
+setmetatableindex(characters.mirrors,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.mirror
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false
+ return v
+end)
+
+characters.textclasses = { }
+
+setmetatableindex(characters.textclasses,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.textclass
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false
+ return v
+end)
+
+--[[ldx--
+<p>Next comes a whole series of helper methods. These are (will be) part
+of the official <l n='api'/>.</p>
+--ldx]]--
+
+-- we could make them virtual: characters.contextnames[n]
+
+function characters.contextname(n) return data[n] and data[n].contextname or "" end
+function characters.adobename (n) return data[n] and data[n].adobename or "" end
+function characters.description(n) return data[n] and data[n].description or "" end
+-------- characters.category (n) return data[n] and data[n].category or "" end
+
+function characters.category(n,verbose)
+ local c = data[n].category
+ if not c then
+ return ""
+ elseif verbose then
+ return categorytags[c]
+ else
+ return c
+ end
+end
+
+-- -- some day we will make a table .. not that many calls to utfchar
+--
+-- local utfchar = utf.char
+-- local utfbyte = utf.byte
+-- local utfbytes = { }
+-- local utfchars = { }
+--
+-- table.setmetatableindex(utfbytes,function(t,k) local v = utfchar(k) t[k] = v return v end)
+-- table.setmetatableindex(utfchars,function(t,k) local v = utfbyte(k) t[k] = v return v end)
+
+local function toutfstring(s)
+ if type(s) == "table" then
+ return utfchar(unpack(s)) -- concat { utfchar( unpack(s) ) }
+ else
+ return utfchar(s)
+ end
+end
+
+utf.tostring = toutfstring
+
+local categories = allocate() characters.categories = categories -- lazy table
+
+setmetatableindex(categories, function(t,u) if u then local c = data[u] c = c and c.category or u t[u] = c return c end end)
+
+-- todo: overloads (these register directly in the tables as number and string) e.g. for greek
+-- todo: for string do a numeric lookup in the table itself
+
+local lccodes = allocate() characters.lccodes = lccodes -- lazy table
+local uccodes = allocate() characters.uccodes = uccodes -- lazy table
+local shcodes = allocate() characters.shcodes = shcodes -- lazy table
+local fscodes = allocate() characters.fscodes = fscodes -- lazy table
+
+setmetatableindex(lccodes, function(t,u) if u then local c = data[u] c = c and c.lccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(uccodes, function(t,u) if u then local c = data[u] c = c and c.uccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(shcodes, function(t,u) if u then local c = data[u] c = c and c.shcode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(fscodes, function(t,u) if u then local c = data[u] c = c and c.fscode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+
+local lcchars = allocate() characters.lcchars = lcchars -- lazy table
+local ucchars = allocate() characters.ucchars = ucchars -- lazy table
+local shchars = allocate() characters.shchars = shchars -- lazy table
+local fschars = allocate() characters.fschars = fschars -- lazy table
+
+setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+
+local decomposed = allocate() characters.decomposed = decomposed -- lazy table
+local specials = allocate() characters.specials = specials -- lazy table
+
+setmetatableindex(decomposed, function(t,u) -- either a table or false
+ if u then
+ local c = data[u]
+ local s = c and c.decomposed or false -- could fall back to specials
+ t[u] = s
+ return s
+ end
+end)
+
+setmetatableindex(specials, function(t,u) -- either a table or false
+ if u then
+ local c = data[u]
+ local s = c and c.specials or false
+ t[u] = s
+ return s
+ end
+end)
+
+local specialchars = allocate() characters.specialchars = specialchars -- lazy table
+local descriptions = allocate() characters.descriptions = descriptions -- lazy table
+
+setmetatableindex(specialchars, function(t,u)
+ if u then
+ local c = data[u]
+ local s = c and c.specials
+ if s then
+ local tt, ttn = { }, 0
+ for i=2,#s do
+ local si = s[i]
+ local c = data[si]
+ if is_letter[c.category] then
+ ttn = ttn + 1
+ tt[ttn] = utfchar(si)
+ end
+ end
+ c = concat(tt)
+ t[u] = c
+ return c
+ else
+ if type(u) == "number" then
+ u = utfchar(u)
+ end
+ t[u] = u
+ return u
+ end
+ end
+end)
+
+setmetatableindex(descriptions, function(t,k)
+ -- 0.05 - 0.10 sec
+ for u, c in next, data do
+ local d = c.description
+ if d then
+ d = gsub(d," ","")
+ d = lower(d)
+ t[d] = u
+ end
+ end
+ local d = rawget(t,k)
+ if not d then
+ t[k] = k
+ end
+ return d
+end)
+
+function characters.unicodechar(asked)
+ local n = tonumber(asked)
+ if n then
+ return n
+ elseif type(asked) == "string" then
+ return descriptions[asked] or descriptions[gsub(asked," ","")]
+ end
+end
+
+-- function characters.lower(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = lcchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.upper(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = ucchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.shaped(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = shchars[u]
+-- end
+-- return concat(new)
+-- end
+
+----- tolower = Cs((utf8byte/lcchars)^0)
+----- toupper = Cs((utf8byte/ucchars)^0)
+----- toshape = Cs((utf8byte/shchars)^0)
+
+local tolower = Cs((utf8character/lcchars)^0) -- no need to check spacing
+local toupper = Cs((utf8character/ucchars)^0) -- no need to check spacing
+local toshape = Cs((utf8character/shchars)^0) -- no need to check spacing
+
+lpegpatterns.tolower = tolower -- old ones ... will be overloaded
+lpegpatterns.toupper = toupper -- old ones ... will be overloaded
+lpegpatterns.toshape = toshape -- old ones ... will be overloaded
+
+-- function characters.lower (str) return lpegmatch(tolower,str) end
+-- function characters.upper (str) return lpegmatch(toupper,str) end
+-- function characters.shaped(str) return lpegmatch(toshape,str) end
+
+-- local superscripts = allocate() characters.superscripts = superscripts
+-- local subscripts = allocate() characters.subscripts = subscripts
+
+-- if storage then
+-- storage.register("characters/superscripts", superscripts, "characters.superscripts")
+-- storage.register("characters/subscripts", subscripts, "characters.subscripts")
+-- end
+
+-- end
+
+if not characters.splits then
+
+ local char = allocate()
+ local compat = allocate()
+
+ local splits = {
+ char = char,
+ compat = compat,
+ }
+
+ characters.splits = splits
+
+ -- [0x013F] = { 0x004C, 0x00B7 }
+ -- [0x0140] = { 0x006C, 0x00B7 }
+
+ for unicode, data in next, characters.data do
+ local specials = data.specials
+ if specials and #specials > 2 then
+ local kind = specials[1]
+ if kind == "compat" then
+ compat[unicode] = { unpack(specials,2) }
+ elseif kind == "char" then
+ char [unicode] = { unpack(specials,2) }
+ end
+ end
+ end
+
+ if storage then
+ storage.register("characters/splits", splits, "characters.splits")
+ end
+
+end
+
+if not characters.lhash then
+
+ local lhash = allocate() characters.lhash = lhash -- nil if no conversion
+ local uhash = allocate() characters.uhash = uhash -- nil if no conversion
+ local shash = allocate() characters.shash = shash -- nil if no conversion
+
+ for k, v in next, characters.data do
+ -- if k < 0x11000 then
+ local l = v.lccode
+ if l then
+ -- we have an uppercase
+ if type(l) == "number" then
+ lhash[utfchar(k)] = utfchar(l)
+ elseif #l == 2 then
+ lhash[utfchar(k)] = utfchar(l[1]) .. utfchar(l[2])
+ else
+ inspect(v)
+ end
+ else
+ local u = v.uccode
+ if u then
+ -- we have an lowercase
+ if type(u) == "number" then
+ uhash[utfchar(k)] = utfchar(u)
+ elseif #u == 2 then
+ uhash[utfchar(k)] = utfchar(u[1]) .. utfchar(u[2])
+ else
+ inspect(v)
+ end
+ end
+ end
+ local s = v.shcode
+ if s then
+ if type(s) == "number" then
+ shash[utfchar(k)] = utfchar(s)
+ elseif #s == 2 then
+ shash[utfchar(k)] = utfchar(s[1]) .. utfchar(s[2])
+ else
+ inspect(v)
+ end
+ end
+ -- end
+ end
+
+ if storage then
+ storage.register("characters/lhash", lhash, "characters.lhash")
+ storage.register("characters/uhash", uhash, "characters.uhash")
+ storage.register("characters/shash", shash, "characters.shash")
+ end
+
+end
+
+local lhash = characters.lhash mark(lhash)
+local uhash = characters.uhash mark(uhash)
+local shash = characters.shash mark(shash)
+
+local utf8lowercharacter = utfchartabletopattern(lhash) / lhash
+local utf8uppercharacter = utfchartabletopattern(uhash) / uhash
+local utf8shapecharacter = utfchartabletopattern(shash) / shash
+
+local utf8lower = Cs((utf8lowercharacter + utf8character)^0)
+local utf8upper = Cs((utf8uppercharacter + utf8character)^0)
+local utf8shape = Cs((utf8shapecharacter + utf8character)^0)
+
+lpegpatterns.utf8lowercharacter = utf8lowercharacter -- one character
+lpegpatterns.utf8uppercharacter = utf8uppercharacter -- one character
+lpegpatterns.utf8shapecharacter = utf8shapecharacter -- one character
+
+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
+
+-- local str = [[
+-- ÀÁÂÃÄÅàáâãäå àáâãäåàáâãäå ÀÁÂÃÄÅÀÁÂÃÄÅ AAAAAAaaaaaa
+-- ÆÇæç æçæç ÆÇÆÇ AECaec
+-- ÈÉÊËèéêë èéêëèéêë ÈÉÊËÈÉÊË EEEEeeee
+-- ÌÍÎÏÞìíîïþ ìíîïþìíîïþ ÌÍÎÏÞÌÍÎÏÞ IIIIÞiiiiþ
+-- Ðð ðð ÐÐ Ðð
+-- Ññ ññ ÑÑ Nn
+-- ÒÓÔÕÖòóôõö òóôõöòóôõö ÒÓÔÕÖÒÓÔÕÖ OOOOOooooo
+-- Øø øø ØØ Oo
+-- ÙÚÛÜùúûü ùúûüùúûü ÙÚÛÜÙÚÛÜ UUUUuuuu
+-- Ýýÿ ýýÿ ÝÝŸ Yyy
+-- ß ß SS ss
+-- Ţţ ţţ ŢŢ Tt
+-- ]]
+--
+-- local lower = characters.lower print(lower(str))
+-- local upper = characters.upper print(upper(str))
+-- local shaped = characters.shaped print(shaped(str))
+--
+-- local c, n = os.clock(), 10000
+-- for i=1,n do lower(str) upper(str) shaped(str) end -- 2.08 => 0.77
+-- print(os.clock()-c,n*#str*3)
+
+-- maybe: (twice as fast when much ascii)
+--
+-- local tolower = lpeg.patterns.tolower
+-- local lower = string.lower
+--
+-- local allascii = R("\000\127")^1 * P(-1)
+--
+-- function characters.checkedlower(str)
+-- return lpegmatch(allascii,str) and lower(str) or lpegmatch(tolower,str) or str
+-- end
+
+function characters.lettered(str,spacing)
+ local new, n = { }, 0
+ if spacing then
+ local done = false
+ for u in utfvalues(str) do
+ local c = data[u].category
+ if is_letter[c] then
+ if done and n > 1 then
+ n = n + 1
+ new[n] = " "
+ done = false
+ end
+ n = n + 1
+ new[n] = utfchar(u)
+ elseif spacing and is_spacing[c] then
+ done = true
+ end
+ end
+ else
+ for u in utfvalues(str) do
+ if is_letter[data[u].category] then
+ n = n + 1
+ new[n] = utfchar(u)
+ end
+ end
+ end
+ return concat(new)
+end
+
+--[[ldx--
+<p>Requesting lower and uppercase codes:</p>
+--ldx]]--
+
+function characters.uccode(n) return uccodes[n] end -- obsolete
+function characters.lccode(n) return lccodes[n] end -- obsolete
+
+function characters.shape(n)
+ local shcode = shcodes[n]
+ if not shcode then
+ return n, nil
+ elseif type(shcode) == "table" then
+ return shcode[1], shcode[#shcode]
+ else
+ return shcode, nil
+ end
+end
+
+-- -- some day we might go this route, but it does not really save that much
+-- -- so not now (we can generate a lot using mtx-unicode that operates on the
+-- -- database)
+--
+-- -- category cjkwd direction linebreak
+--
+-- -- adobename comment contextcommand contextname description fallback lccode
+-- -- mathclass mathfiller mathname mathspec mathstretch mathsymbol mirror
+-- -- range shcode specials uccode uccodes unicodeslot
+--
+-- local data = {
+-- ['one']={
+-- common = {
+-- category="cc",
+-- direction="bn",
+-- linebreak="cm",
+-- },
+-- vector = {
+-- [0x0000] = {
+-- description="NULL",
+-- group='one',
+-- unicodeslot=0x0000,
+-- },
+-- {
+-- description="START OF HEADING",
+-- group='one',
+-- unicodeslot=0x0001,
+-- },
+-- }
+-- }
+-- }
+--
+-- local chardata, groupdata = { }, { }
+--
+-- for group, gdata in next, data do
+-- local common, vector = { __index = gdata.common }, gdata.vector
+-- for character, cdata in next, vector do
+-- chardata[character] = cdata
+-- setmetatable(cdata,common)
+-- end
+-- groupdata[group] = gdata
+-- end
+
+-- characters.data, characters.groups = chardata, groupdata
+
+-- [0xF0000]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x000F Private Use, First>",
+-- direction="l",
+-- unicodeslot=0xF0000,
+-- },
+-- [0xFFFFD]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x000F Private Use, Last>",
+-- direction="l",
+-- unicodeslot=0xFFFFD,
+-- },
+-- [0x100000]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x0010 Private Use, First>",
+-- direction="l",
+-- unicodeslot=0x100000,
+-- },
+-- [0x10FFFD]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x0010 Private Use, Last>",
+-- direction="l",
+-- unicodeslot=0x10FFFD,
+-- },
+
+if not characters.superscripts then
+
+ local superscripts = allocate() characters.superscripts = superscripts
+ local subscripts = allocate() characters.subscripts = subscripts
+ local fractions = allocate() characters.fractions = fractions
+
+ -- skipping U+02120 (service mark) U+02122 (trademark)
+
+ for k, v in next, data do
+ local specials = v.specials
+ if specials then
+ local what = specials[1]
+ if what == "super" then
+ if #specials == 2 then
+ superscripts[k] = specials[2]
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","superscript",ustring(k),k,v.description)
+ end
+ elseif what == "sub" then
+ if #specials == 2 then
+ subscripts[k] = specials[2]
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","subscript",ustring(k),k,v.description)
+ end
+ elseif what == "fraction" then
+ if #specials > 1 then
+ fractions[k] = { unpack(specials,2) }
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","fraction",ustring(k),k,v.description)
+ end
+ end
+ end
+ end
+
+ -- print(table.serialize(superscripts, "superscripts", { hexify = true }))
+ -- print(table.serialize(subscripts, "subscripts", { hexify = true }))
+ -- print(table.serialize(fractions, "fractions", { hexify = true }))
+
+ if storage then
+ storage.register("characters/superscripts", superscripts, "characters.superscripts")
+ storage.register("characters/subscripts", subscripts, "characters.subscripts")
+ storage.register("characters/fractions", fractions, "characters.fractions")
+ end
+
+end
+
+function characters.showstring(str)
+ local list = utotable(str)
+ for i=1,#list do
+ report_defining("split % 3i : %C",i,list[i])
+ end
+end
+
+-- code moved to char-tex.lua
+
+return characters
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv
new file mode 100644
index 00000000000..8f5a8da8fc8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=char-ini,
+%D version=2006.08.20,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Character Support / Initialization}
+
+\registerctxluafile{char-fio}{1.001}
+\registerctxluafile{char-map}{1.001} % maybe we will load this someplace else
+\registerctxluafile{char-tex}{1.001}
+\registerctxluafile{char-ent}{1.001}
+
+\unprotect
+
+% ¨äëïöüÿ
+% ´áćéíĺńóŕśúýź
+% ˙ċėġiż
+% ¯āēīōū
+% ˝őű
+% ˆâĉêĝĥîĵôŝûŵŷ
+% `àèìòùỳ
+% ¸çķļņŗşţ
+% ˛ąęįų
+% ˚åů
+% ˘ăĕğĭŏŭ
+% ˇčďěľňřšťž
+% ˜ãĩñõũ
+
+% \def\checkedchar#1% #2%
+% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
+%
+% impossible in math mode so there always fallback (till we have gyre):
+%
+% use \normalUchar when possible .. the next one is nice for documents and it also accepts
+% 0x prefixed numbers
+
+\def\utfchar #1{\clf_utfchar \numexpr#1\relax}
+\def\safechar#1{\clf_safechar\numexpr#1\relax}
+
+\unexpanded\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml
+ \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml
+
+\unexpanded\def\expandUx{\let\Ux\eUx}
+
+\def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2
+\def\checkedmathchar#1#2{#2}
+%def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
+
+\unexpanded\def\checkedtextchar#1% #2%
+ {\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2}
+
+\unexpanded\def\textormathchar#1%
+ {\relax\ifmmode
+ \char#1\relax
+ \else\iffontchar\font#1\relax
+ \char#1\relax
+ \else
+ \normalstartimath\char#1\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.
+
+% \def\setcclcuc#1#2#3{\global\catcode#1=\lettercatcode\global\lccode#1=#2\global\uccode#1=#3\relax}
+% \def\setcclcucself#1{\global\catcode#1=\lettercatcode\global\lccode#1=#1\global\uccode#1=#1\relax }
+
+% Is setting up vrb tpa and tpb needed?
+
+% move to lua side
+
+%clf_setcharactercodes
+
+\clf_setlettercatcodes\texcatcodes
+\clf_setlettercatcodes\ctxcatcodes
+\clf_setlettercatcodes\notcatcodes
+%clf_setlettercatcodes\mthcatcodes
+\clf_setlettercatcodes\vrbcatcodes
+\clf_setlettercatcodes\prtcatcodes
+\clf_setlettercatcodes\tpacatcodes
+\clf_setlettercatcodes\tpbcatcodes
+\clf_setlettercatcodes\txtcatcodes
+
+\clf_setactivecatcodes\ctxcatcodes
+\clf_setactivecatcodes\notcatcodes
+\clf_setactivecatcodes\prtcatcodes
+
+\def\chardescription#1{\clf_chardescription#1\relax}
+
+% experiment (watch out: this is global and very font dependent when used with
+% casing mechanisms)
+%
+% \overloaduppercase{0xDF}{0x1E9E}}
+% \overloaduppercase{0xDF}{0x53,0x53}
+
+\unexpanded\def\overloaduppercase{\clf_overloaduppercase}
+\unexpanded\def\overloadlowercase{\clf_overloadlowercase}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-map.lua b/Master/texmf-dist/tex/context/base/mkiv/char-map.lua
new file mode 100644
index 00000000000..749da5289bd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-map.lua
@@ -0,0 +1,1072 @@
+if not modules then modules = { } end modules ['char-map'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen & Arthur Reutenauer",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+-- not yet used
+
+characters = characters or { }
+
+characters.casemap={
+ [0x0049]={
+ ["az"]={
+ ["not_before_dot"]={
+ ["lower"]={ 0x0131 },
+ ["title"]={ 0x0049 },
+ ["upper"]={ 0x0049 },
+ },
+ },
+ ["lt"]={
+ ["more_above"]={
+ ["lower"]={ 0x0069, 0x0307 },
+ ["title"]={ 0x0049 },
+ ["upper"]={ 0x0049 },
+ },
+ },
+ ["tr"]={
+ ["not_before_dot"]={
+ ["lower"]={ 0x0131 },
+ ["title"]={ 0x0049 },
+ ["upper"]={ 0x0049 },
+ },
+ },
+ },
+ [0x004A]={
+ ["lt"]={
+ ["more_above"]={
+ ["lower"]={ 0x006A, 0x0307 },
+ ["title"]={ 0x004A },
+ ["upper"]={ 0x004A },
+ },
+ },
+ },
+ [0x0069]={
+ ["az"]={
+ ["all"]={
+ ["lower"]={ 0x0069 },
+ ["title"]={ 0x0130 },
+ ["upper"]={ 0x0130 },
+ },
+ },
+ ["tr"]={
+ ["all"]={
+ ["lower"]={ 0x0069 },
+ ["title"]={ 0x0130 },
+ ["upper"]={ 0x0130 },
+ },
+ },
+ },
+ [0x00CC]={
+ ["lt"]={
+ ["all"]={
+ ["lower"]={ 0x0069, 0x0307, 0x0300 },
+ ["title"]={ 0x00CC },
+ ["upper"]={ 0x00CC },
+ },
+ },
+ },
+ [0x00CD]={
+ ["lt"]={
+ ["all"]={
+ ["lower"]={ 0x0069, 0x0307, 0x0301 },
+ ["title"]={ 0x00CD },
+ ["upper"]={ 0x00CD },
+ },
+ },
+ },
+ [0x00DF]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x00DF },
+ ["title"]={ 0x0053, 0x0073 },
+ ["upper"]={ 0x0053, 0x0053 },
+ },
+ },
+ },
+ [0x0128]={
+ ["lt"]={
+ ["all"]={
+ ["lower"]={ 0x0069, 0x0307, 0x0303 },
+ ["title"]={ 0x0128 },
+ ["upper"]={ 0x0128 },
+ },
+ },
+ },
+ [0x012E]={
+ ["lt"]={
+ ["more_above"]={
+ ["lower"]={ 0x012F, 0x0307 },
+ ["title"]={ 0x012E },
+ ["upper"]={ 0x012E },
+ },
+ },
+ },
+ [0x0130]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x0069, 0x0307 },
+ ["title"]={ 0x0130 },
+ ["upper"]={ 0x0130 },
+ },
+ },
+ ["az"]={
+ ["all"]={
+ ["lower"]={ 0x0069 },
+ ["title"]={ 0x0130 },
+ ["upper"]={ 0x0130 },
+ },
+ },
+ ["tr"]={
+ ["all"]={
+ ["lower"]={ 0x0069 },
+ ["title"]={ 0x0130 },
+ ["upper"]={ 0x0130 },
+ },
+ },
+ },
+ [0x0149]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x0149 },
+ ["title"]={ 0x02BC, 0x004E },
+ ["upper"]={ 0x02BC, 0x004E },
+ },
+ },
+ },
+ [0x01F0]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x01F0 },
+ ["title"]={ 0x004A, 0x030C },
+ ["upper"]={ 0x004A, 0x030C },
+ },
+ },
+ },
+ [0x0307]={
+ ["az"]={
+ ["after_i"]={
+ ["lower"]={},
+ ["title"]={ 0x0307 },
+ ["upper"]={ 0x0307 },
+ },
+ },
+ ["lt"]={
+ ["after_soft_dotted"]={
+ ["lower"]={ 0x0307 },
+ ["title"]={},
+ ["upper"]={},
+ },
+ },
+ ["tr"]={
+ ["after_i"]={
+ ["lower"]={},
+ ["title"]={ 0x0307 },
+ ["upper"]={ 0x0307 },
+ },
+ },
+ },
+ [0x0390]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x0390 },
+ ["title"]={ 0x0399, 0x0308, 0x0301 },
+ ["upper"]={ 0x0399, 0x0308, 0x0301 },
+ },
+ },
+ },
+ [0x03A3]={
+ ["final_sigma"]={
+ ["all"]={
+ ["lower"]={ 0x03C2 },
+ ["title"]={ 0x03A3 },
+ ["upper"]={ 0x03A3 },
+ },
+ },
+ },
+ [0x03B0]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x03B0 },
+ ["title"]={ 0x03A5, 0x0308, 0x0301 },
+ ["upper"]={ 0x03A5, 0x0308, 0x0301 },
+ },
+ },
+ },
+ [0x0587]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x0587 },
+ ["title"]={ 0x0535, 0x0582 },
+ ["upper"]={ 0x0535, 0x0552 },
+ },
+ },
+ },
+ [0x1E96]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1E96 },
+ ["title"]={ 0x0048, 0x0331 },
+ ["upper"]={ 0x0048, 0x0331 },
+ },
+ },
+ },
+ [0x1E97]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1E97 },
+ ["title"]={ 0x0054, 0x0308 },
+ ["upper"]={ 0x0054, 0x0308 },
+ },
+ },
+ },
+ [0x1E98]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1E98 },
+ ["title"]={ 0x0057, 0x030A },
+ ["upper"]={ 0x0057, 0x030A },
+ },
+ },
+ },
+ [0x1E99]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1E99 },
+ ["title"]={ 0x0059, 0x030A },
+ ["upper"]={ 0x0059, 0x030A },
+ },
+ },
+ },
+ [0x1E9A]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1E9A },
+ ["title"]={ 0x0041, 0x02BE },
+ ["upper"]={ 0x0041, 0x02BE },
+ },
+ },
+ },
+ [0x1F50]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F50 },
+ ["title"]={ 0x03A5, 0x0313 },
+ ["upper"]={ 0x03A5, 0x0313 },
+ },
+ },
+ },
+ [0x1F52]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F52 },
+ ["title"]={ 0x03A5, 0x0313, 0x0300 },
+ ["upper"]={ 0x03A5, 0x0313, 0x0300 },
+ },
+ },
+ },
+ [0x1F54]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F54 },
+ ["title"]={ 0x03A5, 0x0313, 0x0301 },
+ ["upper"]={ 0x03A5, 0x0313, 0x0301 },
+ },
+ },
+ },
+ [0x1F56]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F56 },
+ ["title"]={ 0x03A5, 0x0313, 0x0342 },
+ ["upper"]={ 0x03A5, 0x0313, 0x0342 },
+ },
+ },
+ },
+ [0x1F80]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F80 },
+ ["title"]={ 0x1F88 },
+ ["upper"]={ 0x1F08, 0x0399 },
+ },
+ },
+ },
+ [0x1F81]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F81 },
+ ["title"]={ 0x1F89 },
+ ["upper"]={ 0x1F09, 0x0399 },
+ },
+ },
+ },
+ [0x1F82]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F82 },
+ ["title"]={ 0x1F8A },
+ ["upper"]={ 0x1F0A, 0x0399 },
+ },
+ },
+ },
+ [0x1F83]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F83 },
+ ["title"]={ 0x1F8B },
+ ["upper"]={ 0x1F0B, 0x0399 },
+ },
+ },
+ },
+ [0x1F84]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F84 },
+ ["title"]={ 0x1F8C },
+ ["upper"]={ 0x1F0C, 0x0399 },
+ },
+ },
+ },
+ [0x1F85]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F85 },
+ ["title"]={ 0x1F8D },
+ ["upper"]={ 0x1F0D, 0x0399 },
+ },
+ },
+ },
+ [0x1F86]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F86 },
+ ["title"]={ 0x1F8E },
+ ["upper"]={ 0x1F0E, 0x0399 },
+ },
+ },
+ },
+ [0x1F87]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F87 },
+ ["title"]={ 0x1F8F },
+ ["upper"]={ 0x1F0F, 0x0399 },
+ },
+ },
+ },
+ [0x1F88]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F80 },
+ ["title"]={ 0x1F88 },
+ ["upper"]={ 0x1F08, 0x0399 },
+ },
+ },
+ },
+ [0x1F89]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F81 },
+ ["title"]={ 0x1F89 },
+ ["upper"]={ 0x1F09, 0x0399 },
+ },
+ },
+ },
+ [0x1F8A]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F82 },
+ ["title"]={ 0x1F8A },
+ ["upper"]={ 0x1F0A, 0x0399 },
+ },
+ },
+ },
+ [0x1F8B]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F83 },
+ ["title"]={ 0x1F8B },
+ ["upper"]={ 0x1F0B, 0x0399 },
+ },
+ },
+ },
+ [0x1F8C]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F84 },
+ ["title"]={ 0x1F8C },
+ ["upper"]={ 0x1F0C, 0x0399 },
+ },
+ },
+ },
+ [0x1F8D]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F85 },
+ ["title"]={ 0x1F8D },
+ ["upper"]={ 0x1F0D, 0x0399 },
+ },
+ },
+ },
+ [0x1F8E]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F86 },
+ ["title"]={ 0x1F8E },
+ ["upper"]={ 0x1F0E, 0x0399 },
+ },
+ },
+ },
+ [0x1F8F]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F87 },
+ ["title"]={ 0x1F8F },
+ ["upper"]={ 0x1F0F, 0x0399 },
+ },
+ },
+ },
+ [0x1F90]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F90 },
+ ["title"]={ 0x1F98 },
+ ["upper"]={ 0x1F28, 0x0399 },
+ },
+ },
+ },
+ [0x1F91]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F91 },
+ ["title"]={ 0x1F99 },
+ ["upper"]={ 0x1F29, 0x0399 },
+ },
+ },
+ },
+ [0x1F92]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F92 },
+ ["title"]={ 0x1F9A },
+ ["upper"]={ 0x1F2A, 0x0399 },
+ },
+ },
+ },
+ [0x1F93]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F93 },
+ ["title"]={ 0x1F9B },
+ ["upper"]={ 0x1F2B, 0x0399 },
+ },
+ },
+ },
+ [0x1F94]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F94 },
+ ["title"]={ 0x1F9C },
+ ["upper"]={ 0x1F2C, 0x0399 },
+ },
+ },
+ },
+ [0x1F95]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F95 },
+ ["title"]={ 0x1F9D },
+ ["upper"]={ 0x1F2D, 0x0399 },
+ },
+ },
+ },
+ [0x1F96]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F96 },
+ ["title"]={ 0x1F9E },
+ ["upper"]={ 0x1F2E, 0x0399 },
+ },
+ },
+ },
+ [0x1F97]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F97 },
+ ["title"]={ 0x1F9F },
+ ["upper"]={ 0x1F2F, 0x0399 },
+ },
+ },
+ },
+ [0x1F98]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F90 },
+ ["title"]={ 0x1F98 },
+ ["upper"]={ 0x1F28, 0x0399 },
+ },
+ },
+ },
+ [0x1F99]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F91 },
+ ["title"]={ 0x1F99 },
+ ["upper"]={ 0x1F29, 0x0399 },
+ },
+ },
+ },
+ [0x1F9A]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F92 },
+ ["title"]={ 0x1F9A },
+ ["upper"]={ 0x1F2A, 0x0399 },
+ },
+ },
+ },
+ [0x1F9B]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F93 },
+ ["title"]={ 0x1F9B },
+ ["upper"]={ 0x1F2B, 0x0399 },
+ },
+ },
+ },
+ [0x1F9C]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F94 },
+ ["title"]={ 0x1F9C },
+ ["upper"]={ 0x1F2C, 0x0399 },
+ },
+ },
+ },
+ [0x1F9D]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F95 },
+ ["title"]={ 0x1F9D },
+ ["upper"]={ 0x1F2D, 0x0399 },
+ },
+ },
+ },
+ [0x1F9E]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F96 },
+ ["title"]={ 0x1F9E },
+ ["upper"]={ 0x1F2E, 0x0399 },
+ },
+ },
+ },
+ [0x1F9F]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1F97 },
+ ["title"]={ 0x1F9F },
+ ["upper"]={ 0x1F2F, 0x0399 },
+ },
+ },
+ },
+ [0x1FA0]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA0 },
+ ["title"]={ 0x1FA8 },
+ ["upper"]={ 0x1F68, 0x0399 },
+ },
+ },
+ },
+ [0x1FA1]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA1 },
+ ["title"]={ 0x1FA9 },
+ ["upper"]={ 0x1F69, 0x0399 },
+ },
+ },
+ },
+ [0x1FA2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA2 },
+ ["title"]={ 0x1FAA },
+ ["upper"]={ 0x1F6A, 0x0399 },
+ },
+ },
+ },
+ [0x1FA3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA3 },
+ ["title"]={ 0x1FAB },
+ ["upper"]={ 0x1F6B, 0x0399 },
+ },
+ },
+ },
+ [0x1FA4]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA4 },
+ ["title"]={ 0x1FAC },
+ ["upper"]={ 0x1F6C, 0x0399 },
+ },
+ },
+ },
+ [0x1FA5]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA5 },
+ ["title"]={ 0x1FAD },
+ ["upper"]={ 0x1F6D, 0x0399 },
+ },
+ },
+ },
+ [0x1FA6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA6 },
+ ["title"]={ 0x1FAE },
+ ["upper"]={ 0x1F6E, 0x0399 },
+ },
+ },
+ },
+ [0x1FA7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA7 },
+ ["title"]={ 0x1FAF },
+ ["upper"]={ 0x1F6F, 0x0399 },
+ },
+ },
+ },
+ [0x1FA8]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA0 },
+ ["title"]={ 0x1FA8 },
+ ["upper"]={ 0x1F68, 0x0399 },
+ },
+ },
+ },
+ [0x1FA9]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA1 },
+ ["title"]={ 0x1FA9 },
+ ["upper"]={ 0x1F69, 0x0399 },
+ },
+ },
+ },
+ [0x1FAA]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA2 },
+ ["title"]={ 0x1FAA },
+ ["upper"]={ 0x1F6A, 0x0399 },
+ },
+ },
+ },
+ [0x1FAB]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA3 },
+ ["title"]={ 0x1FAB },
+ ["upper"]={ 0x1F6B, 0x0399 },
+ },
+ },
+ },
+ [0x1FAC]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA4 },
+ ["title"]={ 0x1FAC },
+ ["upper"]={ 0x1F6C, 0x0399 },
+ },
+ },
+ },
+ [0x1FAD]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA5 },
+ ["title"]={ 0x1FAD },
+ ["upper"]={ 0x1F6D, 0x0399 },
+ },
+ },
+ },
+ [0x1FAE]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA6 },
+ ["title"]={ 0x1FAE },
+ ["upper"]={ 0x1F6E, 0x0399 },
+ },
+ },
+ },
+ [0x1FAF]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FA7 },
+ ["title"]={ 0x1FAF },
+ ["upper"]={ 0x1F6F, 0x0399 },
+ },
+ },
+ },
+ [0x1FB2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB2 },
+ ["title"]={ 0x1FBA, 0x0345 },
+ ["upper"]={ 0x1FBA, 0x0399 },
+ },
+ },
+ },
+ [0x1FB3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB3 },
+ ["title"]={ 0x1FBC },
+ ["upper"]={ 0x0391, 0x0399 },
+ },
+ },
+ },
+ [0x1FB4]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB4 },
+ ["title"]={ 0x0386, 0x0345 },
+ ["upper"]={ 0x0386, 0x0399 },
+ },
+ },
+ },
+ [0x1FB6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB6 },
+ ["title"]={ 0x0391, 0x0342 },
+ ["upper"]={ 0x0391, 0x0342 },
+ },
+ },
+ },
+ [0x1FB7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB7 },
+ ["title"]={ 0x0391, 0x0342, 0x0345 },
+ ["upper"]={ 0x0391, 0x0342, 0x0399 },
+ },
+ },
+ },
+ [0x1FBC]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FB3 },
+ ["title"]={ 0x1FBC },
+ ["upper"]={ 0x0391, 0x0399 },
+ },
+ },
+ },
+ [0x1FC2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC2 },
+ ["title"]={ 0x1FCA, 0x0345 },
+ ["upper"]={ 0x1FCA, 0x0399 },
+ },
+ },
+ },
+ [0x1FC3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC3 },
+ ["title"]={ 0x1FCC },
+ ["upper"]={ 0x0397, 0x0399 },
+ },
+ },
+ },
+ [0x1FC4]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC4 },
+ ["title"]={ 0x0389, 0x0345 },
+ ["upper"]={ 0x0389, 0x0399 },
+ },
+ },
+ },
+ [0x1FC6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC6 },
+ ["title"]={ 0x0397, 0x0342 },
+ ["upper"]={ 0x0397, 0x0342 },
+ },
+ },
+ },
+ [0x1FC7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC7 },
+ ["title"]={ 0x0397, 0x0342, 0x0345 },
+ ["upper"]={ 0x0397, 0x0342, 0x0399 },
+ },
+ },
+ },
+ [0x1FCC]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FC3 },
+ ["title"]={ 0x1FCC },
+ ["upper"]={ 0x0397, 0x0399 },
+ },
+ },
+ },
+ [0x1FD2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FD2 },
+ ["title"]={ 0x0399, 0x0308, 0x0300 },
+ ["upper"]={ 0x0399, 0x0308, 0x0300 },
+ },
+ },
+ },
+ [0x1FD3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FD3 },
+ ["title"]={ 0x0399, 0x0308, 0x0301 },
+ ["upper"]={ 0x0399, 0x0308, 0x0301 },
+ },
+ },
+ },
+ [0x1FD6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FD6 },
+ ["title"]={ 0x0399, 0x0342 },
+ ["upper"]={ 0x0399, 0x0342 },
+ },
+ },
+ },
+ [0x1FD7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FD7 },
+ ["title"]={ 0x0399, 0x0308, 0x0342 },
+ ["upper"]={ 0x0399, 0x0308, 0x0342 },
+ },
+ },
+ },
+ [0x1FE2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FE2 },
+ ["title"]={ 0x03A5, 0x0308, 0x0300 },
+ ["upper"]={ 0x03A5, 0x0308, 0x0300 },
+ },
+ },
+ },
+ [0x1FE3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FE3 },
+ ["title"]={ 0x03A5, 0x0308, 0x0301 },
+ ["upper"]={ 0x03A5, 0x0308, 0x0301 },
+ },
+ },
+ },
+ [0x1FE4]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FE4 },
+ ["title"]={ 0x03A1, 0x0313 },
+ ["upper"]={ 0x03A1, 0x0313 },
+ },
+ },
+ },
+ [0x1FE6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FE6 },
+ ["title"]={ 0x03A5, 0x0342 },
+ ["upper"]={ 0x03A5, 0x0342 },
+ },
+ },
+ },
+ [0x1FE7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FE7 },
+ ["title"]={ 0x03A5, 0x0308, 0x0342 },
+ ["upper"]={ 0x03A5, 0x0308, 0x0342 },
+ },
+ },
+ },
+ [0x1FF2]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF2 },
+ ["title"]={ 0x1FFA, 0x0345 },
+ ["upper"]={ 0x1FFA, 0x0399 },
+ },
+ },
+ },
+ [0x1FF3]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF3 },
+ ["title"]={ 0x1FFC },
+ ["upper"]={ 0x03A9, 0x0399 },
+ },
+ },
+ },
+ [0x1FF4]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF4 },
+ ["title"]={ 0x038F, 0x0345 },
+ ["upper"]={ 0x038F, 0x0399 },
+ },
+ },
+ },
+ [0x1FF6]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF6 },
+ ["title"]={ 0x03A9, 0x0342 },
+ ["upper"]={ 0x03A9, 0x0342 },
+ },
+ },
+ },
+ [0x1FF7]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF7 },
+ ["title"]={ 0x03A9, 0x0342, 0x0345 },
+ ["upper"]={ 0x03A9, 0x0342, 0x0399 },
+ },
+ },
+ },
+ [0x1FFC]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0x1FF3 },
+ ["title"]={ 0x1FFC },
+ ["upper"]={ 0x03A9, 0x0399 },
+ },
+ },
+ },
+ [0xFB00]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB00 },
+ ["title"]={ 0x0046, 0x0066 },
+ ["upper"]={ 0x0046, 0x0046 },
+ },
+ },
+ },
+ [0xFB01]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB01 },
+ ["title"]={ 0x0046, 0x0069 },
+ ["upper"]={ 0x0046, 0x0049 },
+ },
+ },
+ },
+ [0xFB02]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB02 },
+ ["title"]={ 0x0046, 0x006C },
+ ["upper"]={ 0x0046, 0x004C },
+ },
+ },
+ },
+ [0xFB03]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB03 },
+ ["title"]={ 0x0046, 0x0066, 0x0069 },
+ ["upper"]={ 0x0046, 0x0046, 0x0049 },
+ },
+ },
+ },
+ [0xFB04]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB04 },
+ ["title"]={ 0x0046, 0x0066, 0x006C },
+ ["upper"]={ 0x0046, 0x0046, 0x004C },
+ },
+ },
+ },
+ [0xFB05]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB05 },
+ ["title"]={ 0x0053, 0x0074 },
+ ["upper"]={ 0x0053, 0x0054 },
+ },
+ },
+ },
+ [0xFB06]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB06 },
+ ["title"]={ 0x0053, 0x0074 },
+ ["upper"]={ 0x0053, 0x0054 },
+ },
+ },
+ },
+ [0xFB13]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB13 },
+ ["title"]={ 0x0544, 0x0576 },
+ ["upper"]={ 0x0544, 0x0546 },
+ },
+ },
+ },
+ [0xFB14]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB14 },
+ ["title"]={ 0x0544, 0x0565 },
+ ["upper"]={ 0x0544, 0x0535 },
+ },
+ },
+ },
+ [0xFB15]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB15 },
+ ["title"]={ 0x0544, 0x056B },
+ ["upper"]={ 0x0544, 0x053B },
+ },
+ },
+ },
+ [0xFB16]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB16 },
+ ["title"]={ 0x054E, 0x0576 },
+ ["upper"]={ 0x054E, 0x0546 },
+ },
+ },
+ },
+ [0xFB17]={
+ [""]={
+ ["all"]={
+ ["lower"]={ 0xFB17 },
+ ["title"]={ 0x0544, 0x056D },
+ ["upper"]={ 0x0544, 0x053D },
+ },
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua
new file mode 100644
index 00000000000..60f324be2b2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua
@@ -0,0 +1,822 @@
+if not modules then modules = { } end modules ['char-tex'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+local lpeg = lpeg
+local next, type = next, type
+local format, find, gmatch = string.format, string.find, string.gmatch
+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
+
+local lpegpatterns = lpeg.patterns
+local lpegmatch = lpeg.match
+local utfchartabletopattern = lpeg.utfchartabletopattern
+
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+
+local context = context
+local commands = commands
+
+local characters = characters
+local texcharacters = { }
+characters.tex = texcharacters
+local utffilters = characters.filters.utf
+
+local is_character = characters.is_character
+local is_letter = characters.is_letter
+local is_command = characters.is_command
+local is_spacing = characters.is_spacing
+local is_mark = characters.is_mark
+local is_punctuation = characters.is_punctuation
+
+local data = characters.data if not data then return end
+local blocks = characters.blocks
+
+local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end)
+
+local report_defining = logs.reporter("characters")
+
+--[[ldx--
+<p>In order to deal with 8-bit output, we need to find a way to go from <l n='utf'/> to
+8-bit. This is handled in the <l n='luatex'/> engine itself.</p>
+
+<p>This leaves us problems with characters that are specific to <l n='tex'/> like
+<type>{}</type>, <type>$</type> and alike. We can remap some chars that tex input files
+are sensitive for to a private area (while writing to a utility file) and revert then
+to their original slot when we read in such a file. Instead of reverting, we can (when
+we resolve characters to glyphs) map them to their right glyph there. For this purpose
+we can use the private planes 0x0F0000 and 0x100000.</p>
+--ldx]]--
+
+local low = allocate()
+local high = allocate()
+local escapes = allocate()
+local special = "~#$%^&_{}\\|" -- "~#$%{}\\|"
+
+local private = {
+ low = low,
+ high = high,
+ escapes = escapes,
+}
+
+utffilters.private = private
+
+for ch in gmatch(special,".") do
+ local cb
+ if type(ch) == "number" then
+ cb, ch = ch, utfchar(ch)
+ else
+ cb = utfbyte(ch)
+ end
+ if cb < 256 then
+ escapes[ch] = "\\" .. ch
+ low[ch] = utfchar(0x0F0000 + cb)
+ if ch == "%" then
+ ch = "%%" -- nasty, but we need this as in replacements (also in lpeg) % is interpreted
+ end
+ high[utfchar(0x0F0000 + cb)] = ch
+ end
+end
+
+local tohigh = lpeg.replacer(low) -- frozen, only for basic tex
+local tolow = lpeg.replacer(high) -- frozen, only for basic tex
+
+lpegpatterns.utftohigh = tohigh
+lpegpatterns.utftolow = tolow
+
+function utffilters.harden(str)
+ return lpegmatch(tohigh,str)
+end
+
+function utffilters.soften(str)
+ return lpegmatch(tolow,str)
+end
+
+private.escape = utf.remapper(escapes) -- maybe: ,"dynamic"
+private.replace = utf.remapper(low) -- maybe: ,"dynamic"
+private.revert = utf.remapper(high) -- maybe: ,"dynamic"
+
+--[[ldx--
+<p>We get a more efficient variant of this when we integrate
+replacements in collapser. This more or less renders the previous
+private code redundant. The following code is equivalent but the
+first snippet uses the relocated dollars.</p>
+
+<typing>
+[󰀤x󰀤] [$x$]
+</typing>
+--ldx]]--
+
+-- using the tree-lpeg-mapper would be nice but we also need to deal with end-of-string
+-- cases: "\"\i" and don't want "\relax" to be seen as \r e lax" (for which we need to mess
+-- with spaces
+
+local accentmapping = allocate {
+ ['"'] = { [""] = "¨",
+ A = "Ä", a = "ä",
+ E = "Ë", e = "ë",
+ I = "Ï", i = "ï", ["ı"] = "ï", ["\\i"] = "ï",
+ O = "Ö", o = "ö",
+ U = "Ü", u = "ü",
+ Y = "Ÿ", y = "ÿ",
+ },
+ ["'"] = { [""] = "´",
+ A = "Á", a = "á",
+ C = "Ć", c = "ć",
+ E = "É", e = "é",
+ I = "Í", i = "í", ["ı"] = "í", ["\\i"] = "í",
+ L = "Ĺ", l = "ĺ",
+ N = "Ń", n = "ń",
+ O = "Ó", o = "ó",
+ R = "Ŕ", r = "ŕ",
+ S = "Ś", s = "ś",
+ U = "Ú", u = "ú",
+ Y = "Ý", y = "ý",
+ Z = "Ź", z = "ź",
+ },
+ ["."] = { [""] = "˙",
+ C = "Ċ", c = "ċ",
+ E = "Ė", e = "ė",
+ G = "Ġ", g = "ġ",
+ I = "İ", i = "i", ["ı"] = "i", ["\\i"] = "i",
+ Z = "Ż", z = "ż",
+ },
+ ["="] = { [""] = "¯",
+ A = "Ā", a = "ā",
+ E = "Ē", e = "ē",
+ I = "Ī", i = "ī", ["ı"] = "ī", ["\\i"] = "ī",
+ O = "Ō", o = "ō",
+ U = "Ū", u = "ū",
+ },
+ ["H"] = { [""] = "˝",
+ O = "Ő", o = "ő",
+ U = "Ű", u = "ű",
+ },
+ ["^"] = { [""] = "ˆ",
+ A = "Â", a = "â",
+ C = "Ĉ", c = "ĉ",
+ E = "Ê", e = "ê",
+ G = "Ĝ", g = "ĝ",
+ H = "Ĥ", h = "ĥ",
+ I = "Î", i = "î", ["ı"] = "î", ["\\i"] = "î",
+ J = "Ĵ", j = "ĵ",
+ O = "Ô", o = "ô",
+ S = "Ŝ", s = "ŝ",
+ U = "Û", u = "û",
+ W = "Ŵ", w = "ŵ",
+ Y = "Ŷ", y = "ŷ",
+ },
+ ["`"] = { [""] = "`",
+ A = "À", a = "à",
+ E = "È", e = "è",
+ I = "Ì", i = "ì", ["ı"] = "ì", ["\\i"] = "ì",
+ O = "Ò", o = "ò",
+ U = "Ù", u = "ù",
+ Y = "Ỳ", y = "ỳ",
+ },
+ ["c"] = { [""] = "¸",
+ C = "Ç", c = "ç",
+ K = "Ķ", k = "ķ",
+ L = "Ļ", l = "ļ",
+ N = "Ņ", n = "ņ",
+ R = "Ŗ", r = "ŗ",
+ S = "Ş", s = "ş",
+ T = "Ţ", t = "ţ",
+ },
+ ["k"] = { [""] = "˛",
+ A = "Ą", a = "ą",
+ E = "Ę", e = "ę",
+ I = "Į", i = "į",
+ U = "Ų", u = "ų",
+ },
+ ["r"] = { [""] = "˚",
+ A = "Å", a = "å",
+ U = "Ů", u = "ů",
+ },
+ ["u"] = { [""] = "˘",
+ A = "Ă", a = "ă",
+ E = "Ĕ", e = "ĕ",
+ G = "Ğ", g = "ğ",
+ I = "Ĭ", i = "ĭ", ["ı"] = "ĭ", ["\\i"] = "ĭ",
+ O = "Ŏ", o = "ŏ",
+ U = "Ŭ", u = "ŭ",
+ },
+ ["v"] = { [""] = "ˇ",
+ C = "Č", c = "č",
+ D = "Ď", d = "ď",
+ E = "Ě", e = "ě",
+ L = "Ľ", l = "ľ",
+ N = "Ň", n = "ň",
+ R = "Ř", r = "ř",
+ S = "Š", s = "š",
+ T = "Ť", t = "ť",
+ Z = "Ž", z = "ž",
+ },
+ ["~"] = { [""] = "˜",
+ A = "Ã", a = "ã",
+ I = "Ĩ", i = "ĩ", ["ı"] = "ĩ", ["\\i"] = "ĩ",
+ N = "Ñ", n = "ñ",
+ O = "Õ", o = "õ",
+ U = "Ũ", u = "ũ",
+ },
+}
+
+texcharacters.accentmapping = accentmapping
+
+local accent_map = allocate { -- incomplete
+ ['~'] = "̃" , -- ̃ Ẽ
+ ['"'] = "̈" , -- ̈ Ë
+ ["`"] = "̀" , -- ̀ È
+ ["'"] = "́" , -- ́ É
+ ["^"] = "̂" , -- ̂ Ê
+ -- ̄ Ē
+ -- ̆ Ĕ
+ -- ̇ Ė
+ -- ̉ Ẻ
+ -- ̌ Ě
+ -- ̏ Ȅ
+ -- ̑ Ȇ
+ -- ̣ Ẹ
+ -- ̧ Ȩ
+ -- ̨ Ę
+ -- ̭ Ḙ
+ -- ̰ Ḛ
+}
+
+-- local accents = concat(table.keys(accentmapping)) -- was _map
+
+local function remap_accent(a,c,braced)
+ local m = accentmapping[a]
+ if m then
+ local n = m[c]
+ if n then
+ return n
+ end
+ end
+-- local m = accent_map[a]
+-- if m then
+-- return c .. m
+-- elseif braced then -- or #c > 0
+ if braced then -- or #c > 0
+ return "\\" .. a .. "{" .. c .. "}"
+ else
+ return "\\" .. a .. " " .. c
+ end
+end
+
+local commandmapping = allocate {
+ ["aa"] = "å", ["AA"] = "Å",
+ ["ae"] = "æ", ["AE"] = "Æ",
+ ["cc"] = "ç", ["CC"] = "Ç",
+ ["i"] = "ı", ["j"] = "ȷ",
+ ["ij"] = "ij", ["IJ"] = "IJ",
+ ["l"] = "ł", ["L"] = "Ł",
+ ["o"] = "ø", ["O"] = "Ø",
+ ["oe"] = "œ", ["OE"] = "Œ",
+ ["sz"] = "ß", ["SZ"] = "SZ", ["ss"] = "ß", ["SS"] = "ß", -- uppercase: ẞ
+}
+
+texcharacters.commandmapping = commandmapping
+
+local ligaturemapping = allocate {
+ ["''"] = "”",
+ ["``"] = "“",
+ ["--"] = "–",
+ ["---"] = "—",
+}
+
+-- local achar = R("az","AZ") + P("ı") + P("\\i")
+--
+-- local spaces = P(" ")^0
+-- local no_l = P("{") / ""
+-- local no_r = P("}") / ""
+-- local no_b = P('\\') / ""
+--
+-- local lUr = P("{") * C(achar) * P("}")
+--
+-- local accents_1 = [["'.=^`~]]
+-- local accents_2 = [[Hckruv]]
+--
+-- local accent = P('\\') * (
+-- C(S(accents_1)) * (lUr * Cc(true) + C(achar) * Cc(false)) + -- we need achar for ı etc, could be sped up
+-- C(S(accents_2)) * lUr * Cc(true)
+-- ) / remap_accent
+--
+-- local csname = P('\\') * C(R("az","AZ")^1)
+--
+-- local command = (
+-- csname +
+-- P("{") * csname * spaces * P("}")
+-- ) / commandmapping -- remap_commands
+--
+-- local both_1 = Cs { "run",
+-- accent = accent,
+-- command = command,
+-- run = (V("accent") + no_l * V("accent") * no_r + V("command") + P(1))^0,
+-- }
+--
+-- local both_2 = Cs { "run",
+-- accent = accent,
+-- command = command,
+-- run = (V("accent") + V("command") + no_l * ( V("accent") + V("command") ) * no_r + P(1))^0,
+-- }
+--
+-- function texcharacters.toutf(str,strip)
+-- if not find(str,"\\") then
+-- return str
+-- elseif strip then
+-- return lpegmatch(both_1,str)
+-- else
+-- return lpegmatch(both_2,str)
+-- end
+-- end
+
+local untex
+
+local function toutfpattern()
+ if not untex then
+ local hash = { }
+ for k, v in next, accentmapping do
+ for kk, vv in next, v do
+ if (k >= "a" and k <= "z") or (k >= "A" and k <= "Z") then
+ hash[ "\\"..k.." "..kk ] = vv
+ hash["{\\"..k.." "..kk.."}"] = vv
+ else
+ hash["\\" ..k ..kk ] = vv
+ hash["{\\"..k ..kk.."}"] = vv
+ end
+ hash["\\" ..k.."{"..kk.."}" ] = vv
+ hash["{\\"..k.."{"..kk.."}}"] = vv
+ end
+ end
+ for k, v in next, commandmapping do
+ hash["\\"..k.." "] = v
+ hash["{\\"..k.."}"] = v
+ hash["{\\"..k.." }"] = v
+ end
+ for k, v in next, ligaturemapping do
+ hash[k] = v
+ end
+ untex = utfchartabletopattern(hash) / hash
+ end
+ return untex
+end
+
+texcharacters.toutfpattern = toutfpattern
+
+local pattern = nil
+
+local function prepare()
+ pattern = Cs((toutfpattern() + P(1))^0)
+ return pattern
+end
+
+function texcharacters.toutf(str,strip)
+ if str == "" then
+ return str
+ elseif not find(str,"\\") then
+ return str
+ -- elseif strip then
+ else
+ return lpegmatch(pattern or prepare(),str)
+ end
+end
+
+-- print(texcharacters.toutf([[\~{Z}]],true))
+-- print(texcharacters.toutf([[\'\i]],true))
+-- print(texcharacters.toutf([[\'{\i}]],true))
+-- print(texcharacters.toutf([[\"{e}]],true))
+-- print(texcharacters.toutf([[\" {e}]],true))
+-- print(texcharacters.toutf([[{\"{e}}]],true))
+-- print(texcharacters.toutf([[{\" {e}}]],true))
+-- print(texcharacters.toutf([[{\l}]],true))
+-- print(texcharacters.toutf([[{\l }]],true))
+-- print(texcharacters.toutf([[\v{r}]],true))
+-- print(texcharacters.toutf([[fo{\"o}{\ss}ar]],true))
+-- print(texcharacters.toutf([[H{\'a}n Th\^e\llap{\raise 0.5ex\hbox{\'{\relax}}} Th{\'a}nh]],true))
+
+function texcharacters.safechar(n) -- was characters.safechar
+ local c = data[n]
+ if c and c.contextname then
+ return "\\" .. c.contextname
+ else
+ return utfchar(n)
+ end
+end
+
+if not context or not commands then
+ -- used in e.g. mtx-bibtex
+ return
+end
+
+-- all kind of initializations
+
+if not interfaces then return end
+
+local implement = interfaces.implement
+
+local tex = tex
+local texsetlccode = tex.setlccode
+local texsetuccode = tex.setuccode
+local texsetsfcode = tex.setsfcode
+local texsetcatcode = tex.setcatcode
+
+local contextsprint = context.sprint
+local ctxcatcodes = catcodes.numbers.ctxcatcodes
+
+function texcharacters.defineaccents()
+ local ctx_dodefineaccentcommand = context.dodefineaccentcommand
+ local ctx_dodefineaccent = context.dodefineaccent
+ local ctx_dodefinecommand = context.dodefinecommand
+ for accent, group in next, accentmapping do
+ ctx_dodefineaccentcommand(accent)
+ for character, mapping in next, group do
+ ctx_dodefineaccent(accent,character,mapping)
+ end
+ end
+ for command, mapping in next, commandmapping do
+ ctx_dodefinecommand(command,mapping)
+ end
+end
+
+implement { -- a waste of scanner but consistent
+ name = "defineaccents",
+ actions = texcharacters.defineaccents
+}
+
+--[[ldx--
+<p>Instead of using a <l n='tex'/> file to define the named glyphs, we
+use the table. After all, we have this information available anyway.</p>
+--ldx]]--
+
+function commands.makeactive(n,name) -- not used
+ contextsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
+ -- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)
+end
+
+implement {
+ name = "utfchar",
+ actions = { utfchar, contextsprint },
+ arguments = "integer"
+}
+
+implement {
+ name = "safechar",
+ actions = { texcharacters.safechar, contextsprint },
+ arguments = "integer"
+}
+
+implement {
+ name = "uchar",
+ arguments = { "integer", "integer" },
+ actions = function(h,l)
+ context(utfchar(h*256+l))
+ end
+}
+
+tex.uprint = commands.utfchar
+
+-- in contect we don't use lc and uc codes (in fact in luatex we should have a hf code)
+-- so at some point we might drop this
+
+local forbidden = tohash { -- at least now
+ 0x00A0,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D,
+ 0x202F,
+ 0x205F,
+ -- 0xFEFF,
+}
+
+local csletters = characters.csletters -- also a signal that we have initialized
+local activated = { }
+local sfmode = "unset" -- unset, traditional, normal
+local block_too = false
+
+directives.register("characters.blockstoo",function(v) block_too = v end)
+
+-- If this is something that is not documentwide and used a lot, then we
+-- need a more clever approach (trivial but not now).
+
+local function setuppersfcodes(v,n)
+ if sfstate ~= "unset" then
+ report_defining("setting uppercase sf codes to %a",n)
+ for u, chr in next, data do
+ if chr.category == "lu" then
+ texsetsfcode(u,n)
+ end
+ end
+ end
+ sfstate = v
+end
+
+directives.register("characters.spaceafteruppercase",function(v)
+ if v == "traditional" then
+ setuppersfcodes(v,999)
+ elseif v == "normal" then
+ setuppersfcodes(v,1000)
+ end
+end)
+
+if not csletters then
+
+ csletters = allocate()
+ characters.csletters = csletters
+
+ report_defining("setting up character related codes and commands")
+
+ if sfstate == "unset" then
+ sfstate = "traditional"
+ end
+
+ local traditional = sfstate == "traditional"
+
+ for u, chr in next, data do -- will move up
+ local fallback = chr.fallback
+ if fallback then
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}")
+ activated[#activated+1] = u
+ else
+ local contextname = chr.contextname
+ local category = chr.category
+ local isletter = is_letter[category]
+ if contextname then
+ if is_character[category] then
+ if chr.unicodeslot < 128 then
+ if isletter then
+ -- setmacro
+ local c = utfchar(u)
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,c)) -- has no s
+ csletters[c] = u
+ else
+ -- setchar
+ contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u)) -- has no s
+ end
+ else
+ -- setmacro
+ local c = utfchar(u)
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,c)) -- has no s
+ if isletter and u >= 32 and u <= 65536 then
+ csletters[c] = u
+ end
+ end
+ --
+ if isletter then
+ local lc, uc = chr.lccode, chr.uccode
+ if not lc then
+ chr.lccode, lc = u, u
+ elseif type(lc) == "table" then
+ lc = u
+ end
+ if not uc then
+ chr.uccode, uc = u, u
+ elseif type(uc) == "table" then
+ uc = u
+ end
+ texsetlccode(u,lc,uc)
+ if traditional and category == "lu" then
+ texsetsfcode(code,999)
+ end
+ end
+ --
+ elseif is_command[category] and not forbidden[u] then
+ -- set
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}")
+ activated[#activated+1] = u
+ elseif is_mark[category] then
+ texsetlccode(u,u,u) -- for hyphenation
+ end
+ elseif isletter and u >= 32 and u <= 65536 then
+ csletters[utfchar(u)] = u
+ --
+ local lc, uc = chr.lccode, chr.uccode
+ if not lc then
+ chr.lccode, lc = u, u
+ elseif type(lc) == "table" then
+ lc = u
+ end
+ if not uc then
+ chr.uccode, uc = u, u
+ elseif type(uc) == "table" then
+ uc = u
+ end
+ texsetlccode(u,lc,uc)
+ if traditional and category == "lu" then
+ texsetsfcode(code,999)
+ end
+ --
+ elseif is_mark[category] then
+ --
+ texsetlccode(u,u,u) -- for hyphenation
+ --
+ end
+ end
+ end
+
+ if blocks_too then
+ -- this slows down format generation by over 10 percent
+ for k, v in next, blocks do
+ if v.catcode == "letter" then
+ for u=v.first,v.last do
+ csletters[utfchar(u)] = u
+ --
+ -- texsetlccode(u,u,u) -- self self
+ --
+ end
+ end
+ end
+ end
+
+ if storage then
+ storage.register("characters/csletters", csletters, "characters.csletters")
+ end
+
+else
+ mark(csletters)
+
+end
+
+lpegpatterns.csletter = utfchartabletopattern(csletters)
+
+-- todo: get rid of activated
+-- todo: move first loop out ,merge with above
+
+function characters.setlettercatcodes(cct)
+ if trace_defining then
+ report_defining("assigning letter catcodes to catcode table %a",cct)
+ end
+ local saved = tex.catcodetable
+ tex.catcodetable = cct
+ texsetcatcode(0x200C,11) -- non-joiner
+ texsetcatcode(0x200D,11) -- joiner
+ for c, u in next, csletters do
+ texsetcatcode(u,11)
+ end
+ -- for u, chr in next, data do
+ -- if not chr.fallback and is_letter[chr.category] and u >= 32 and u <= 65536 then
+ -- texsetcatcode(u,11)
+ -- end
+ -- local range = chr.range
+ -- if range then
+ -- for i=1,range.first,range.last do -- tricky as not all are letters
+ -- texsetcatcode(i,11)
+ -- end
+ -- end
+ -- end
+ -- for k, v in next, blocks do
+ -- if v.catcode == "letter" then
+ -- for u=v.first,v.last do
+ -- texsetcatcode(u,11)
+ -- end
+ -- end
+ -- end
+ tex.catcodetable = saved
+end
+
+function characters.setactivecatcodes(cct)
+ local saved = tex.catcodetable
+ tex.catcodetable = cct
+ for i=1,#activated do
+ local u = activated[i]
+ texsetcatcode(u,13)
+ if trace_defining then
+ report_defining("character %U (%s) is active in set %a",u,data[u].description,cct)
+ end
+ end
+ tex.catcodetable = saved
+end
+
+--[[ldx--
+<p>Setting the lccodes is also done in a loop over the data table.</p>
+--ldx]]--
+
+-- function characters.setcodes() -- we could loop over csletters
+-- if trace_defining then
+-- report_defining("defining lc and uc codes")
+-- end
+-- local traditional = sfstate == "traditional" or sfstate == "unset"
+-- for code, chr in next, data do
+-- local cc = chr.category
+-- if is_letter[cc] then
+-- local range = chr.range
+-- if range then
+-- for i=range.first,range.last do
+-- texsetlccode(i,i,i) -- self self
+-- end
+-- else
+-- local lc, uc = chr.lccode, chr.uccode
+-- if not lc then
+-- chr.lccode, lc = code, code
+-- elseif type(lc) == "table" then
+-- lc = code
+-- end
+-- if not uc then
+-- chr.uccode, uc = code, code
+-- elseif type(uc) == "table" then
+-- uc = code
+-- end
+-- texsetlccode(code,lc,uc)
+-- if traditional and cc == "lu" then
+-- texsetsfcode(code,999)
+-- end
+-- end
+-- elseif is_mark[cc] then
+-- texsetlccode(code,code,code) -- for hyphenation
+-- end
+-- end
+-- if traditional then
+-- sfstate = "traditional"
+-- end
+-- end
+
+-- tex
+
+implement {
+ name = "chardescription",
+ arguments = "integer",
+ actions = function(slot)
+ local d = data[slot]
+ if d then
+ context(d.description)
+ end
+ end,
+}
+
+-- xml
+
+characters.activeoffset = 0x10000 -- there will be remapped in that byte range
+
+function commands.remapentity(chr,slot) -- not used
+ contextsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
+end
+
+-- xml.entities = xml.entities or { }
+--
+-- storage.register("xml/entities",xml.entities,"xml.entities") -- this will move to lxml
+--
+-- function characters.setmkiventities()
+-- local entities = xml.entities
+-- entities.lt = "<"
+-- entities.amp = "&"
+-- entities.gt = ">"
+-- end
+--
+-- function characters.setmkiientities()
+-- local entities = xml.entities
+-- entities.lt = utfchar(characters.activeoffset + utfbyte("<"))
+-- entities.amp = utfchar(characters.activeoffset + utfbyte("&"))
+-- entities.gt = utfchar(characters.activeoffset + utfbyte(">"))
+-- end
+
+implement { name = "setlettercatcodes", scope = "private", actions = characters.setlettercatcodes, arguments = "integer" }
+implement { name = "setactivecatcodes", scope = "private", actions = characters.setactivecatcodes, arguments = "integer" }
+--------- { name = "setcharactercodes", scope = "private", actions = characters.setcodes }
+
+-- experiment (some can move to char-ini.lua)
+
+local function overload(c,u,code,codes)
+ local c = tonumber(c)
+ if not c then
+ return
+ end
+ local u = utilities.parsers.settings_to_array(u)
+ local n = #u
+ if n == 0 then
+ return
+ end
+ local t = nil
+ if n == 1 then
+ t = tonumber(u[1])
+ else
+ t = { }
+ for i=1,n do
+ t[#t+1] = tonumber(u[i])
+ end
+ end
+ if t then
+ data[c][code] = t
+ characters[codes][c] = nil
+ end
+end
+
+interfaces.implement {
+ name = "overloaduppercase",
+ arguments = { "string", "string" },
+ actions = function(c,u)
+ overload(c,u,"uccode","uccodes")
+ end
+}
+
+interfaces.implement {
+ name = "overloadlowercase",
+ arguments = { "string", "string" },
+ actions = function(c,u)
+ overload(c,u,"lccode","lccodes")
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua b/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua
new file mode 100644
index 00000000000..327529c32b6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua
@@ -0,0 +1,657 @@
+if not modules then modules = { } end modules ['char-utf'] = {
+ version = 1.001,
+ comment = "companion to char-utf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>When a sequence of <l n='utf'/> characters enters the application, it may be
+neccessary to collapse subsequences into their composed variant.</p>
+
+<p>This module implements methods for collapsing and expanding <l n='utf'/>
+sequences. We also provide means to deal with characters that are special to
+<l n='tex'/> as well as 8-bit characters that need to end up in special kinds
+of output (for instance <l n='pdf'/>).</p>
+
+<p>We implement these manipulations as filters. One can run multiple filters
+over a string.</p>
+--ldx]]--
+
+local gsub, find = string.gsub, string.find
+local concat, sortedhash, keys, sort = table.concat, table.sortedhash, table.keys, table.sort
+local utfchar, utfbyte, utfcharacters, utfvalues = utf.char, utf.byte, utf.characters, utf.values
+local P, Cs, Cmt, Ct = lpeg.P, lpeg.Cs, lpeg.Cmt, lpeg.Ct
+
+if not characters then require("char-def") end
+if not characters.blocks then require("char-ini") end
+
+local lpegmatch = lpeg.match
+local lpegpatterns = lpeg.patterns
+local p_utf8character = lpegpatterns.utf8character
+local p_utf8byte = lpegpatterns.utf8byte
+local utfchartabletopattern = lpeg.utfchartabletopattern
+
+local formatters = string.formatters
+
+local allocate = utilities.storage.allocate or function() return { } end
+
+local charfromnumber = characters.fromnumber
+
+characters = characters or { }
+local characters = characters
+
+local graphemes = allocate()
+characters.graphemes = graphemes
+
+local collapsed = allocate()
+characters.collapsed = collapsed
+
+local combined = allocate()
+characters.combined = combined
+
+local decomposed = allocate()
+characters.decomposed = decomposed
+
+local mathpairs = allocate()
+characters.mathpairs = mathpairs
+
+local filters = allocate()
+characters.filters = filters
+
+local utffilters = { }
+characters.filters.utf = utffilters
+
+local data = characters.data
+
+-- is characters.combined cached?
+
+--[[ldx--
+<p>It only makes sense to collapse at runtime, since we don't expect source code
+to depend on collapsing.</p>
+--ldx]]--
+
+-- for the moment, will be entries in char-def.lua .. this is just a subset that for
+-- typographic (font) reasons we want to have split ... if we decompose all, we get
+-- problems with fonts
+
+local decomposed = allocate {
+ ["IJ"] = "IJ",
+ ["ij"] = "ij",
+ ["և"] = "եւ",
+ ["ff"] = "ff",
+ ["fi"] = "fi",
+ ["fl"] = "fl",
+ ["ffi"] = "ffi",
+ ["ffl"] = "ffl",
+ ["ſt"] = "ſt",
+ ["st"] = "st",
+ ["ﬓ"] = "մն",
+ ["ﬔ"] = "մե",
+ ["ﬕ"] = "մի",
+ ["ﬖ"] = "վն",
+ ["ﬗ"] = "մխ",
+}
+
+characters.decomposed = decomposed
+
+-- local function initialize() -- maybe only 'mn'
+-- local data = characters.data
+-- for unicode, v in next, data do
+-- -- using vs and first testing for length is faster (.02->.01 s)
+-- local vs = v.specials
+-- if vs and #vs == 3 then
+-- local vc = vs[1]
+-- if vc == "char" then
+-- local one, two = vs[2], vs[3]
+-- if data[two].category == "mn" then
+-- local cgf = combined[one]
+-- if not cgf then
+-- cgf = { [two] = unicode }
+-- combined[one] = cgf
+-- else
+-- cgf[two] = unicode
+-- end
+-- end
+-- local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
+-- local cgf = graphemes[first]
+-- if not cgf then
+-- cgf = { [second] = combination }
+-- graphemes[first] = cgf
+-- else
+-- cgf[second] = combination
+-- end
+-- if v.mathclass or v.mathspec then
+-- local mps = mathpairs[two]
+-- if not mps then
+-- mps = { [one] = unicode }
+-- mathpairs[two] = mps
+-- else
+-- mps[one] = unicode -- here unicode
+-- end
+-- local mps = mathpairs[second]
+-- if not mps then
+-- mps = { [first] = combination }
+-- mathpairs[second] = mps
+-- else
+-- mps[first] = combination
+-- end
+-- end
+-- -- elseif vc == "compat" then
+-- -- else
+-- -- local description = v.description
+-- -- if find(description,"LIGATURE") then
+-- -- if vs then
+-- -- local t = { }
+-- -- for i=2,#vs do
+-- -- t[#t+1] = utfchar(vs[i])
+-- -- end
+-- -- decomposed[utfchar(unicode)] = concat(t)
+-- -- else
+-- -- local vs = v.shcode
+-- -- if vs then
+-- -- local t = { }
+-- -- for i=1,#vs do
+-- -- t[i] = utfchar(vs[i])
+-- -- end
+-- -- decomposed[utfchar(unicode)] = concat(t)
+-- -- end
+-- -- end
+-- -- end
+-- end
+-- end
+-- end
+-- initialize = false
+-- characters.initialize = function() end -- when used outside tex
+-- end
+
+local function initialize() -- maybe in tex mode store in format !
+ local data = characters.data
+ 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
+ collapsed[first..second] = target
+ backtrack(data[one],second,target)
+ end
+ end
+ local function setpair(one,two,unicode,first,second,combination)
+ local mps = mathpairs[one]
+ if not mps then
+ mps = { [two] = unicode }
+ mathpairs[one] = mps
+ else
+ mps[two] = unicode
+ end
+ local mps = mathpairs[first]
+ if not mps then
+ mps = { [second] = combination }
+ mathpairs[first] = mps
+ else
+ mps[second] = combination
+ end
+ end
+ for unicode, v in next, data do
+ local vs = v.specials
+ if vs and #vs == 3 and vs[1] == "char" then
+ --
+ local one, two = vs[2], vs[3]
+ local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
+ --
+ collapsed[first..second] = combination
+ backtrack(data[one],second,combination)
+ -- sort of obsolete:
+ local cgf = graphemes[first]
+ if not cgf then
+ cgf = { [second] = combination }
+ graphemes[first] = cgf
+ else
+ cgf[second] = combination
+ end
+ --
+ if v.mathclass or v.mathspec then
+ setpair(two,one,unicode,second,first,combination) -- watch order
+ end
+ end
+ local mp = v.mathpair
+ if mp then
+ local one, two = mp[1], mp[2]
+ local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
+ setpair(one,two,unicode,first,second,combination)
+ end
+ end
+ initialize = false
+ characters.initialize = function() end
+end
+
+characters.initialize = initialize
+
+--[[ldx--
+<p>The next variant has lazy token collecting, on a 140 page mk.tex this saves
+about .25 seconds, which is understandable because we have no graphemes and
+not collecting tokens is not only faster but also saves garbage collecting.
+</p>
+--ldx]]--
+
+local skippable = { }
+local filesuffix = file.suffix
+
+function utffilters.setskippable(suffix,value)
+ if value == nil then
+ value = true
+ end
+ if type(suffix) == "table" then
+ for i=1,#suffix do
+ skippable[suffix[i]] = value
+ end
+ else
+ skippable[suffix] = value
+ end
+end
+
+-- function utffilters.collapse(str,filename) -- we can make high a seperate pass (never needed with collapse)
+-- if skippable[filesuffix(filename)] then
+-- return str
+-- -- elseif find(filename,"^virtual://") then
+-- -- return str
+-- -- else
+-- -- -- print("\n"..filename)
+-- end
+-- if str and str ~= "" then
+-- local nstr = #str
+-- if nstr > 1 then
+-- if initialize then -- saves a call
+-- initialize()
+-- end
+-- local tokens, t, first, done, n = { }, 0, false, false, 0
+-- for second in utfcharacters(str) do
+-- if done then
+-- if first then
+-- if second == " " then
+-- t = t + 1
+-- tokens[t] = first
+-- first = second
+-- else
+-- -- local crs = high[second]
+-- -- if crs then
+-- -- t = t + 1
+-- -- tokens[t] = first
+-- -- first = crs
+-- -- else
+-- local cgf = graphemes[first]
+-- if cgf and cgf[second] then
+-- first = cgf[second]
+-- else
+-- t = t + 1
+-- tokens[t] = first
+-- first = second
+-- end
+-- -- end
+-- end
+-- elseif second == " " then
+-- first = second
+-- else
+-- -- local crs = high[second]
+-- -- if crs then
+-- -- first = crs
+-- -- else
+-- first = second
+-- -- end
+-- end
+-- elseif second == " " then
+-- first = nil
+-- n = n + 1
+-- else
+-- -- local crs = high[second]
+-- -- if crs then
+-- -- for s in utfcharacters(str) do
+-- -- if n == 1 then
+-- -- break
+-- -- else
+-- -- t = t + 1
+-- -- tokens[t] = s
+-- -- n = n - 1
+-- -- end
+-- -- end
+-- -- if first then
+-- -- t = t + 1
+-- -- tokens[t] = first
+-- -- end
+-- -- first = crs
+-- -- done = true
+-- -- else
+-- local cgf = graphemes[first]
+-- if cgf and cgf[second] then
+-- for s in utfcharacters(str) do
+-- if n == 1 then
+-- break
+-- else
+-- t = t + 1
+-- tokens[t] = s
+-- n = n - 1
+-- end
+-- end
+-- first = cgf[second]
+-- done = true
+-- else
+-- first = second
+-- n = n + 1
+-- end
+-- -- end
+-- end
+-- end
+-- if done then
+-- if first then
+-- t = t + 1
+-- tokens[t] = first
+-- end
+-- return concat(tokens) -- seldom called
+-- end
+-- elseif nstr > 0 then
+-- return high[str] or str -- this will go from here
+-- end
+-- end
+-- return str
+-- end
+
+-- this is about twice as fast
+
+local p_collapse = nil -- so we can reset if needed
+
+local function prepare()
+ if initialize then
+ initialize()
+ end
+ local tree = utfchartabletopattern(collapsed)
+ p_collapse = Cs((tree/collapsed + p_utf8character)^0 * P(-1)) -- the P(1) is needed in order to accept non utf
+end
+
+function utffilters.collapse(str,filename)
+ if not p_collapse then
+ prepare()
+ end
+ if not str or #str == "" or #str == 1 then
+ return str
+ elseif filename and skippable[filesuffix(filename)] then -- we could hash the collapsables or do a quicker test
+ return str
+ else
+ return lpegmatch(p_collapse,str) or str
+ end
+end
+
+-- function utffilters.decompose(str)
+-- if str and str ~= "" then
+-- local nstr = #str
+-- if nstr > 1 then
+-- -- if initialize then -- saves a call
+-- -- initialize()
+-- -- end
+-- local tokens, t, done, n = { }, 0, false, 0
+-- for s in utfcharacters(str) do
+-- local dec = decomposed[s]
+-- if dec then
+-- if not done then
+-- if n > 0 then
+-- for s in utfcharacters(str) do
+-- if n == 0 then
+-- break
+-- else
+-- t = t + 1
+-- tokens[t] = s
+-- n = n - 1
+-- end
+-- end
+-- end
+-- done = true
+-- end
+-- t = t + 1
+-- tokens[t] = dec
+-- elseif done then
+-- t = t + 1
+-- tokens[t] = s
+-- else
+-- n = n + 1
+-- end
+-- end
+-- if done then
+-- return concat(tokens) -- seldom called
+-- end
+-- end
+-- end
+-- return str
+-- end
+
+-- local replacer = nil
+-- local finder = nil
+--
+-- function utffilters.decompose(str) -- 3 to 4 times faster than the above
+-- if not replacer then
+-- if initialize then
+-- initialize()
+-- end
+-- local tree = utfchartabletopattern(decomposed)
+-- finder = lpeg.finder(tree,false,true)
+-- replacer = lpeg.replacer(tree,decomposed,false,true)
+-- end
+-- if str and str ~= "" and #str > 1 and lpegmatch(finder,str) then
+-- return lpegmatch(replacer,str)
+-- end
+-- return str
+-- end
+
+local p_decompose = nil
+
+local function prepare()
+ if initialize then
+ initialize()
+ end
+ local tree = utfchartabletopattern(decomposed)
+ p_decompose = Cs((tree/decomposed + p_utf8character)^0 * P(-1))
+end
+
+function utffilters.decompose(str,filename) -- 3 to 4 times faster than the above
+ if not p_decompose then
+ prepare()
+ end
+ if str and str ~= "" and #str > 1 then
+ return lpegmatch(p_decompose,str)
+ end
+ if not str or #str == "" or #str < 2 then
+ return str
+ elseif filename and skippable[filesuffix(filename)] then
+ return str
+ else
+ return lpegmatch(p_decompose,str) or str
+ end
+ return str
+end
+
+-- utffilters.addgrapheme(utfchar(318),'l','\string~')
+-- utffilters.addgrapheme('c','a','b')
+
+function utffilters.addgrapheme(result,first,second) -- can be U+ 0x string or utf or number
+ local result = charfromnumber(result)
+ local first = charfromnumber(first)
+ local second = charfromnumber(second)
+ if not graphemes[first] then
+ graphemes[first] = { [second] = result }
+ else
+ graphemes[first][second] = result
+ end
+ local pair = first .. second
+ if not composed[pair] then
+ composed[pair] = result
+ p_composed = nil
+ end
+end
+
+if interfaces then -- eventually this goes to char-ctx.lua
+
+ interfaces.implement {
+ name = "addgrapheme",
+ actions = utffilters.addgrapheme,
+ arguments = { "string", "string", "string" }
+ }
+
+end
+
+-- --
+
+local p_reorder = nil
+
+-- local sorter = function(a,b) return b[2] < a[2] end
+--
+-- local function swapper(s,p,t)
+-- local old = { }
+-- for i=1,#t do
+-- old[i] = t[i][1]
+-- end
+-- old = concat(old)
+-- sort(t,sorter)
+-- for i=1,#t do
+-- t[i] = t[i][1]
+-- end
+-- local new = concat(t)
+-- if old ~= new then
+-- print("reordered",old,"->",new)
+-- end
+-- return p, new
+-- end
+
+-- -- the next one isnto stable for similar weights
+
+local sorter = function(a,b)
+ return b[2] < a[2]
+end
+
+local function swapper(s,p,t)
+ sort(t,sorter)
+ for i=1,#t do
+ t[i] = t[i][1]
+ end
+ return p, concat(t)
+end
+
+-- -- the next one keeps similar weights in the original order
+--
+-- local sorter = function(a,b)
+-- local b2, a2 = b[2], a[2]
+-- if a2 == b2 then
+-- return b[3] > a[3]
+-- else
+-- return b2 < a2
+-- end
+-- end
+--
+-- local function swapper(s,p,t)
+-- for i=1,#t do
+-- t[i][3] = i
+-- end
+-- sort(t,sorter)
+-- for i=1,#t do
+-- t[i] = t[i][1]
+-- end
+-- return p, concat(t)
+-- end
+
+-- at some point exceptions will become an option, for now it's an experiment
+-- to overcome bugs (that have become features) in unicode .. or we might decide
+-- for an extra ordering key in char-def that takes precedence over combining
+
+local exceptions = {
+ -- frozen unicode bug
+ ["َّ"] = "َّ", -- U+64E .. U+651 => U+651 .. U+64E
+}
+
+local function prepare()
+ local hash = { }
+ for k, v in sortedhash(characters.data) do
+ local combining = v.combining -- v.ordering or v.combining
+ if combining then
+ hash[utfchar(k)] = { utfchar(k), combining, 0 } -- slot 3 can be used in sort
+ end
+ end
+ local e = utfchartabletopattern(exceptions)
+ local p = utfchartabletopattern(hash)
+ p_reorder = Cs((e/exceptions + Cmt(Ct((p/hash)^2),swapper) + p_utf8character)^0) * P(-1)
+end
+
+function utffilters.reorder(str,filename)
+ if not p_reorder then
+ prepare()
+ end
+ if not str or #str == "" or #str < 2 then
+ return str
+ elseif filename and skippable[filesuffix(filename)] then
+ return str
+ else
+ return lpegmatch(p_reorder,str) or str
+ end
+ return str
+end
+
+-- local collapse = utffilters.collapse
+-- local decompose = utffilters.decompose
+-- local preprocess = utffilters.preprocess
+--
+-- local c1, c2, c3 = "a", "̂", "̃"
+-- local r2, r3 = "â", "ẫ"
+-- local l1 = "ffl"
+--
+-- local str = c1..c2..c3 .. " " .. c1..c2 .. " " .. l1
+-- local res = r3 .. " " .. r2 .. " " .. "ffl"
+--
+-- local text = io.loaddata("t:/sources/tufte.tex")
+--
+-- local function test(n)
+-- local data = text .. string.rep(str,100) .. text
+-- local okay = text .. string.rep(res,100) .. text
+-- local t = os.clock()
+-- for i=1,10000 do
+-- collapse(data)
+-- decompose(data)
+-- -- preprocess(data)
+-- end
+-- print(os.clock()-t,decompose(collapse(data))==okay,decompose(collapse(str)))
+-- end
+--
+-- test(050)
+-- test(150)
+--
+-- local old = "foo" .. string.char(0xE1) .. "bar"
+-- local new = collapse(old)
+-- print(old,new)
+
+-- local one_old = "فَأَصَّدَّقَ دَّ" local one_new = utffilters.reorder(one_old)
+-- local two_old = "فَأَصَّدَّقَ دَّ" local two_new = utffilters.reorder(two_old)
+--
+-- print(one_old,two_old,one_old==two_old,false)
+-- print(one_new,two_new,one_new==two_new,true)
+--
+-- local test = "foo" .. utf.reverse("ؚ" .. "ً" .. "ٌ" .. "ٍ" .. "َ" .. "ُ" .. "ِ" .. "ّ" .. "ْ" ) .. "bar"
+-- local done = utffilters.reorder(test)
+--
+-- print(test,done,test==done,false)
+
+local f_default = formatters["[%U] "]
+local f_description = formatters["[%s] "]
+
+local function convert(n)
+ local d = data[n]
+ d = d and d.description
+ if d then
+ return f_description(d)
+ else
+ return f_default(n)
+ end
+end
+
+local pattern = Cs((p_utf8byte / convert)^1)
+
+function utffilters.verbose(data)
+ return data and lpegmatch(pattern,data) or ""
+end
+
+return characters
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-utf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-utf.mkiv
new file mode 100644
index 00000000000..fe9f402ef23
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-utf.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=char-utf,
+%D version=2006.12.05,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Unicode UTF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Character Support / Unicode UTF}
+
+%D After a bit of experimenting we reached a clean state where \UTF\
+%D 8, 16 and 32 were supported as well as collapsing (combining
+%D sequences). Writing the code was a relaxed experience, not in the
+%D last place because it was accompanied by listening to those nice
+%D Vienna Teng cd's (who decided that making music was more fun than
+%D programming, but then, she may not know \TEX\ and \LUA).
+
+\unprotect
+
+\registerctxluafile{char-def}{1.001}
+\registerctxluafile{char-ini}{1.001}
+\registerctxluafile{char-utf}{1.001}
+\registerctxluafile{char-cjk}{1.001}
+
+%D We enable collapsing (combining characters) by default, but
+%D since the source files are rather simple, we postpone the
+%D initialization till runtime.
+
+\appendtoks
+ \clf_enableutf % not needed when we create a format so we do it now
+\to \everyjob
+
+%D The next one influences input parsing.
+%D
+%D \starttyping
+%D \definecomposedutf 318 108 126 % lcaron
+%D \stoptyping
+
+\unexpanded\def\definecomposedutf#1 #2 #3 %
+ {\clf_addgrapheme{#1}{#2}{#3}}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/chem-ini.lua
new file mode 100644
index 00000000000..f7d10ffa272
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/chem-ini.lua
@@ -0,0 +1,62 @@
+if not modules then modules = { } end modules ['chem-ini'] = {
+ version = 1.001,
+ comment = "companion to chem-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+
+local trace_molecules = false trackers.register("chemistry.molecules", function(v) trace_molecules = v end)
+
+local report_chemistry = logs.reporter("chemistry")
+
+local context = context
+local cpatterns = patterns.context
+
+chemistry = chemistry or { }
+local chemistry = chemistry
+
+--[[
+<p>The next code started out as adaptation of code from Wolfgang Schuster as
+posted on the mailing list. The current version supports nested braces and
+unbraced integers as scripts.</p>
+]]--
+
+local moleculeparser = cpatterns.scripted
+chemistry.moleculeparser = moleculeparser
+
+function chemistry.molecule(str)
+ return lpegmatch(moleculeparser,str)
+end
+
+interfaces.implement {
+ name = "molecule",
+ arguments = "string",
+ actions = function(str)
+ if trace_molecules then
+ local rep = lpegmatch(moleculeparser,str)
+ report_chemistry("molecule %a becomes %a",str,rep)
+ context(rep)
+ else
+ context(lpegmatch(moleculeparser,str))
+ end
+ end,
+}
+
+-- interfaces.implement {
+-- name = "molecule",
+-- scope = "private",
+-- action = function()
+-- local str = scanstring()
+-- if trace_molecules then
+-- local rep = lpegmatch(moleculeparser,str)
+-- report_chemistry("molecule %a becomes %a",str,rep)
+-- context(rep)
+-- else
+-- context(lpegmatch(moleculeparser,str))
+-- end
+-- end,
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/chem-ini.mkiv
new file mode 100644
index 00000000000..d18ba47a10a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/chem-ini.mkiv
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=chem-ini,
+%D version=2008.03.06,
+%D subtitle=Chemistry,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: \mathscriptsmode
+
+\writestatus{loading}{ConTeXt Chemistry Macros / Initialization} % might become Inline
+
+\registerctxluafile{chem-ini}{1.001}
+
+\unprotect
+
+% todo: use \mathscriptsmode if needed
+
+%D \macros
+%D {molecule}
+%D
+%D Quick and dirty:
+%D
+%D \starttyping
+%D \unexpanded\def\molecule#1%
+%D {$\enablesupersub\tf#1$}
+%D \stoptyping
+%D
+%D Using \LUA:
+%D
+%D \startbuffer
+%D \molecule{H_2SO_4^-2}
+%D \molecule{H_2SO_4^{-2}}
+%D \molecule{H_2SO_4^{-2{x}}}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\molecule#1%
+ {\clf_molecule{#1}}
+
+%D For old times sake:
+
+\unexpanded\def\chem#1#2#3%
+ {\dontleavehmode\begingroup#1\lohi{#2}{#3}\endgroup}
+
+\protect \endinput
+
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua b/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua
new file mode 100644
index 00000000000..e90464ad2ed
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua
@@ -0,0 +1,888 @@
+if not modules then modules = { } end modules ['chem-str'] = {
+ version = 1.001,
+ comment = "companion to chem-str.mkiv",
+ author = "Hans Hagen and Alan Braslau",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+-- the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+-- \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+-- but better implementation, later versions might provide more.
+--
+-- Well, the later version has arrived as Alan took it upon him to make the code
+-- deviate even further from the original implementation. The original (early \MKII)
+-- variant operated within the boundaries of \PICTEX\ and as it supported MetaPost as
+-- alternative output. As a consequence it still used a stepwise graphic construction
+-- approach. As we used \TEX\ for parsing, the syntax was more rigid than it is now.
+-- This new variant uses a more mathematical and metapostisch approach. In the process
+-- more rendering variants have been added and alignment has been automated. As a result
+-- the current user interface is slightly different from the old one but hopefully users
+-- will like the added value.
+
+-- directive_strictorder: one might set this to off when associated texts are disordered too
+
+local trace_structure = false trackers .register("chemistry.structure", function(v) trace_structure = v end)
+local trace_metapost = false trackers .register("chemistry.metapost", function(v) trace_metapost = v end)
+local trace_boundingbox = false trackers .register("chemistry.boundingbox", function(v) trace_boundingbox = v end)
+local trace_textstack = false trackers .register("chemistry.textstack", function(v) trace_textstack = v end)
+local directive_strictorder = true directives.register("chemistry.strictorder", function(v) directive_strictorder = v end)
+local directive_strictindex = false directives.register("chemistry.strictindex", function(v) directive_strictindex = v end)
+
+local report_chemistry = logs.reporter("chemistry")
+
+local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
+local concat, insert, remove, unique, sorted = table.concat, table.insert, table.remove, table.unique, table.sorted
+local processor_tostring = typesetters and typesetters.processors.tostring
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_array_with_repeat = utilities.parsers.settings_to_array_with_repeat
+
+local lpegmatch = lpeg.match
+local P, R, S, C, Cs, Ct, Cc, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cmt
+
+local variables = interfaces and interfaces.variables
+local commands = commands
+local context = context
+local implement = interfaces.implement
+
+local formatters = string.formatters
+local texgetcount = tex.getcount
+
+local v_default = variables.default
+local v_small = variables.small
+local v_medium = variables.medium
+local v_big = variables.big
+local v_normal = variables.normal
+local v_fit = variables.fit
+local v_on = variables.on
+local v_none = variables.none
+
+local mpnamedcolor = attributes.colors.mpnamedcolor
+local topoints = number.topoints
+local todimen = string.todimen
+
+local trialtypesetting = context.trialtypesetting
+
+chemistry = chemistry or { }
+local chemistry = chemistry
+
+chemistry.instance = "chemistry"
+chemistry.format = "metafun"
+chemistry.method = "double"
+chemistry.structures = 0
+
+local common_keys = {
+ b = "line",
+ r = "line",
+ sb = "line",
+ sr = "line",
+ rd = "line",
+ rh = "line",
+ rb = "line",
+ rbd = "line",
+ cc = "line",
+ ccd = "line",
+ line = "line",
+ dash = "line",
+ arrow = "line",
+ c = "fixed",
+ cd = "fixed",
+ z = "text",
+ zt = "text",
+ zlt = "text",
+ zrt = "text",
+ rz = "text",
+ rt = "text",
+ lrt = "text",
+ rrt = "text",
+ label = "text",
+ zln = "number",
+ zrn = "number",
+ rn = "number",
+ lrn = "number",
+ rrn = "number",
+ zn = "number",
+ number = "number",
+ mov = "transform",
+ mark = "transform",
+ move = "transform",
+ diff = "transform",
+ off = "transform",
+ adj = "transform",
+ sub = "transform",
+}
+
+local front_keys = {
+ bb = "line",
+ eb = "line",
+ rr = "line",
+ lr = "line",
+ lsr = "line",
+ rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ lrb = "line",
+ rrb = "line",
+ lrz = "text",
+ rrz = "text",
+ lsub = "transform",
+ rsub = "transform",
+}
+
+local one_keys = {
+ db = "line",
+ tb = "line",
+ bb = "line",
+ dr = "line",
+ hb = "line",
+ bd = "line",
+ bw = "line",
+ oe = "line",
+ sd = "line",
+ rdb = "line",
+ ldb = "line",
+ ldd = "line",
+ rdd = "line",
+ ep = "line",
+ es = "line",
+ ed = "line",
+ et = "line",
+ au = "line",
+ ad = "line",
+ cz = "text",
+ rot = "transform",
+ dir = "transform",
+ rm = "transform",
+ mir = "transform",
+}
+
+local ring_keys = {
+ db = "line",
+ hb = "line",
+ br = "line",
+ lr = "line",
+ rr = "line",
+ lsr = "line",
+ rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrb = "line",
+ rrb = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ dr = "line",
+ eb = "line",
+ er = "line",
+ ed = "line",
+ au = "line",
+ ad = "line",
+ s = "line",
+ ss = "line",
+ mid = "line",
+ mids = "line",
+ midz = "text",
+ lrz = "text",
+ rrz = "text",
+ crz = "text",
+ rot = "transform",
+ mir = "transform",
+ adj = "transform",
+ lsub = "transform",
+ rsub = "transform",
+ rm = "transform",
+}
+
+-- table.setmetatableindex(front_keys,common_keys)
+-- table.setmetatableindex(one_keys,common_keys)
+-- table.setmetatableindex(ring_keys,common_keys)
+
+-- or (faster but not needed here):
+
+front_keys = table.merged(front_keys,common_keys)
+one_keys = table.merged(one_keys,common_keys)
+ring_keys = table.merged(ring_keys,common_keys)
+
+local syntax = {
+ carbon = { max = 4, keys = one_keys, },
+ alkyl = { max = 4, keys = one_keys, },
+ newmanstagger = { max = 6, keys = one_keys, },
+ newmaneclipsed = { max = 6, keys = one_keys, },
+ one = { max = 8, keys = one_keys, },
+ three = { max = 3, keys = ring_keys, },
+ four = { max = 4, keys = ring_keys, },
+ five = { max = 5, keys = ring_keys, },
+ six = { max = 6, keys = ring_keys, },
+ seven = { max = 7, keys = ring_keys, },
+ eight = { max = 8, keys = ring_keys, },
+ nine = { max = 9, keys = ring_keys, },
+ fivefront = { max = 5, keys = front_keys, },
+ sixfront = { max = 6, keys = front_keys, },
+ chair = { max = 6, keys = front_keys, },
+ boat = { max = 6, keys = front_keys, },
+ pb = { direct = 'chem_pb;' },
+ pe = { direct = 'chem_pe;' },
+ save = { direct = 'chem_save;' },
+ restore = { direct = 'chem_restore;' },
+ chem = { direct = formatters['chem_symbol("\\chemicaltext{%s}");'], arguments = 1 },
+ space = { direct = 'chem_symbol("\\chemicalsymbol[space]");' },
+ plus = { direct = 'chem_symbol("\\chemicalsymbol[plus]");' },
+ minus = { direct = 'chem_symbol("\\chemicalsymbol[minus]");' },
+ equals = { direct = 'chem_symbol("\\chemicalsymbol[equals]");' },
+ gives = { direct = formatters['chem_symbol("\\chemicalsymbol[gives]{%s}{%s}");'], arguments = 2 },
+ equilibrium = { direct = formatters['chem_symbol("\\chemicalsymbol[equilibrium]{%s}{%s}");'], arguments = 2 },
+ mesomeric = { direct = formatters['chem_symbol("\\chemicalsymbol[mesomeric]{%s}{%s}");'], arguments = 2 },
+ opencomplex = { direct = 'chem_symbol("\\chemicalsymbol[opencomplex]");' },
+ closecomplex = { direct = 'chem_symbol("\\chemicalsymbol[closecomplex]");' },
+ reset = { direct = 'chem_reset;' },
+ mp = { direct = formatters['%s'], arguments = 1 }, -- backdoor MP code - dangerous!
+}
+
+chemistry.definitions = chemistry.definitions or { }
+local definitions = chemistry.definitions
+
+storage.register("chemistry/definitions",definitions,"chemistry.definitions")
+
+function chemistry.undefine(name)
+ definitions[lower(name)] = nil
+end
+
+function chemistry.define(name,spec,text)
+ name = lower(name)
+ local dn = definitions[name]
+ if not dn then
+ dn = { }
+ definitions[name] = dn
+ end
+ dn[#dn+1] = {
+ spec = settings_to_array_with_repeat(spec,true),
+ text = settings_to_array_with_repeat(text,true),
+ }
+end
+
+local metacode, variant, keys, max, txt, pstack, sstack, align
+local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...)
+
+local function fetch(txt)
+ local st = stack[txt]
+ local t = st.text[st.n]
+ while not t and txt > 1 do
+ txt = txt - 1
+ st = stack[txt]
+ t = st.text[st.n]
+ end
+ if t then
+ if trace_textstack then
+ report_chemistry("fetching from stack %a, slot %a, data %a",txt,st.n,t)
+ end
+ st.n = st.n + 1
+ end
+ return txt, t
+end
+
+local remapper = {
+ ["+"] = "p",
+ ["-"] = "m",
+}
+
+local dchrs = R("09")
+local sign = S("+-")
+local digit = dchrs / tonumber
+local amount = (sign^-1 * (dchrs^0 * P('.'))^-1 * dchrs^1) / tonumber
+local single = digit
+local range = digit * P("..") * digit
+local set = Ct(digit^2)
+local colon = P(":")
+local equal = P("=")
+local other = 1 - digit - colon - equal
+local remapped = sign / remapper
+local operation = Cs(other^1)
+local special = (colon * C(other^1)) + Cc("")
+local text = (equal * C(P(1)^0)) + Cc(false)
+
+local pattern =
+ (amount + Cc(1))
+ * (remapped + Cc(""))
+ * Cs(operation/lower)
+ * Cs(special/lower) * (
+ range * Cc(false) * text +
+ Cc(false) * Cc(false) * set * text +
+ single * Cc(false) * Cc(false) * text +
+ Cc(false) * Cc(false) * Cc(false) * text
+ )
+
+-- local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
+
+-- print(lpegmatch(pattern,"RZ=x")) -- 1 RZ false false false x
+-- print(lpegmatch(pattern,"RZ1=x")) -- 1 RZ 1 false false x
+-- print(lpegmatch(pattern,"RZ1..3=x")) -- 1 RZ 1 3 false x
+-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x
+
+local f_initialize = 'if unknown context_chem : input mp-chem.mpiv ; fi ;'
+local f_start_structure = formatters['chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);']
+local f_set_trace_bounds = formatters['chem_trace_boundingbox := %l ;']
+local f_stop_structure = 'chem_stop_structure;'
+local f_start_component = 'chem_start_component;'
+local f_stop_component = 'chem_stop_component;'
+local f_line = formatters['chem_%s%s(%s,%s,%s,%s,%s);']
+local f_set = formatters['chem_set(%s);']
+local f_number = formatters['chem_%s%s(%s,%s,"\\chemicaltext{%s}");']
+local f_text = f_number
+local f_empty_normal = formatters['chem_%s(%s,%s,"");']
+local f_empty_center = formatters['chem_c%s(%s,%s,"");']
+local f_transform = formatters['chem_%s(%s,%s,%s);']
+
+local prepareMPvariable = commands and commands.prepareMPvariable
+
+local function process(level,spec,text,n,rulethickness,rulecolor,offset,default_variant)
+ insert(stack,{ spec = spec, text = text, n = n })
+ local txt = #stack
+ local m = #metacode
+ local saved_rulethickness = rulethickness
+ local saved_rulecolor = rulecolor
+ local saved_align = align
+ local current_variant = default_variant or "six"
+ for i=1,#spec do
+ local step = spec[i]
+ local s = lower(step)
+ local n = current_variant .. ":" .. s
+ local d = definitions[n]
+ if not d then
+ n = s
+ d = definitions[n]
+ end
+ if d then
+ if trace_structure then
+ report_chemistry("level %a, step %a, definition %a, snippets %a",level,step,n,#d)
+ end
+ for i=1,#d do
+ local di = d[i]
+ current_variant = process(level+1,di.spec,di.text,1,rulethickness,rulecolor,offset,current_variant) -- offset?
+ end
+ else
+ local factor, osign, operation, special, index, upto, set, text = lpegmatch(pattern,step)
+ if trace_structure then
+ local set = set and concat(set," ") or "-"
+ report_chemistry("level %a, step %a, factor %a, osign %a, operation %a, special %a, index %a, upto %a, set %a, text %a",
+ level,step,factor,osign,operation,special,index,upto,set,text)
+ end
+ if operation == "rulecolor" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == "" then
+ rulecolor = saved_rulecolor
+ elseif t then
+ rulecolor = mpnamedcolor(t)
+ end
+ elseif operation == "rulethickness" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == t_medium or t == "" then
+ rulethickness = saved_rulethickness
+ elseif t == v_small then
+ rulethickness = topoints(1/1.2 * todimen(saved_rulethickness))
+ elseif t == v_big then
+ rulethickness = topoints(1.2 * todimen(saved_rulethickness))
+ elseif t then
+ -- rulethickness = topoints(todimen(t)) -- mp can't handle sp
+ rulethickness = topoints(tonumber(t) * todimen(saved_rulethickness))
+ end
+ elseif operation == "symalign" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal then
+ align = saved_align
+ elseif t and t ~= "" then
+ align = "." .. t
+ end
+ elseif operation == "pb" then
+ insert(pstack,variant)
+ m = m + 1 ; metacode[m] = syntax.pb.direct
+ if keys[special] == "text" and index then
+ if keys["c"..special] == "text" then -- can be option: auto ...
+ m = m + 1 ; metacode[m] = f_empty_center(special,variant,index)
+ else
+ m = m + 1 ; metacode[m] = f_empty_normal(special,variant,index)
+ end
+ end
+ elseif operation == "pe" then
+ variant = remove(pstack)
+ local ss = syntax[variant]
+ keys, max = ss.keys, ss.max
+ m = m + 1 ; metacode[m] = syntax.pe.direct
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
+ elseif operation == "save" then
+ insert(sstack,variant)
+ m = m + 1 ; metacode[m] = syntax.save.direct
+ elseif operation == "restore" then
+ if #sstack > 0 then
+ variant = remove(sstack)
+ else
+ report_chemistry("restore without save")
+ end
+ local ss = syntax[variant]
+ keys, max = ss.keys, ss.max
+ m = m + 1 ; metacode[m] = syntax.restore.direct
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
+ elseif operation then
+ local ss = syntax[operation]
+ local what = keys[operation]
+ local ns = 0
+ if set then
+ local sv = syntax[current_variant]
+ local ms = sv and sv.max
+ set = unique(set)
+ ns = #set
+ if directive_strictorder then
+ if what == "line" then
+ set = sorted(set)
+ end
+ if directive_strictindex and ms then
+ for i=ns,1,-1 do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("level %a, operation %a, max nofsteps %a, ignoring %a",level,operation,ms,si)
+ set[i] = nil
+ ns = ns - 1
+ else
+ break
+ end
+ end
+ end
+ else
+ if directive_strictindex and ms then
+ local t, nt = { }, 0
+ for i=1,ns do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("level %a, operation %a, max nofsteps %a, ignoring %a",level,operation,ms,si)
+ set[i] = nil
+ else
+ nt = nt + 1
+ t[nt] = si
+ end
+ end
+ ns = nt
+ set = t
+ end
+ end
+ end
+ if ss then
+ local ds = ss.direct
+ if ds then
+ local sa = ss.arguments
+ if sa == 1 then
+ local one ; txt, one = fetch(txt)
+ m = m + 1 ; metacode[m] = ds(one or "")
+ elseif sa == 2 then
+ local one ; txt, one = fetch(txt)
+ local two ; txt, two = fetch(txt)
+ m = m + 1 ; metacode[m] = ds(one or "",two or "")
+ else
+ m = m + 1 ; metacode[m] = ds
+ end
+ elseif ss.keys then
+ variant, keys, max = s, ss.keys, ss.max
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
+ end
+ elseif what == "line" then
+ local s = osign
+ if s ~= "" then
+ s = "." .. s
+ end
+ if set then
+ -- condense consecutive numbers in a set to a range
+ local sf, st = set[1]
+ for i=1,ns do
+ if i > 1 and set[i] ~= set[i-1]+1 then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,sf,st,rulethickness,rulecolor)
+ sf = set[i]
+ end
+ st = set[i]
+ end
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,sf,st,rulethickness,rulecolor)
+ elseif upto then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,index,upto,rulethickness,rulecolor)
+ elseif index then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,index,index,rulethickness,rulecolor)
+ else
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,1,max,rulethickness,rulecolor)
+ end
+ elseif what == "number" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,si,si)
+ end
+ elseif upto then
+ for i=index,upto do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,si,si)
+ end
+ elseif index then
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,index,index)
+ else
+ for i=1,max do
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,i,i)
+ end
+ end
+ elseif what == "text" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+-- local p, t = processors.split(t)
+-- m = m + 1 ; metacode[m] = f_text(operation,p or align,variant,si,t)
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,si,t)
+ end
+ end
+ elseif upto then
+ for i=index,upto do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,i,t)
+ end
+ end
+ elseif index == 0 then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,index,t)
+ end
+ elseif index then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,index,t)
+ end
+ else
+ for i=1,max do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,i,t)
+ end
+ end
+ end
+ elseif what == "transform" then
+ if osign == "m" then
+ factor = -factor
+ end
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,si,factor)
+ end
+ elseif upto then
+ for i=index,upto do
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,i,factor)
+ end
+ else
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,index or 1,factor)
+ end
+ elseif what == "fixed" then
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,rulethickness,rulecolor)
+ elseif trace_structure then
+ report_chemistry("level %a, ignoring undefined operation %s",level,operation)
+ end
+ end
+ end
+ end
+ remove(stack)
+ return current_variant
+end
+
+-- the size related values are somewhat special but we want to be
+-- compatible
+--
+-- rulethickness in points
+
+local function checked(d,bondlength,unit,scale)
+ if d == v_none then
+ return 0
+ end
+ local n = tonumber(d)
+ if not n then
+ -- assume dimen
+ elseif n >= 10 or n <= -10 then
+ return bondlength * unit * n / 1000
+ else
+ return bondlength * unit * n
+ end
+ local n = todimen(d)
+ if n then
+ return scale * n
+ else
+ return v_fit
+ end
+end
+
+local function calculated(height,bottom,top,bondlength,unit,scale)
+ local scaled = 0
+ if height == v_none then
+ -- this always wins
+ height = "0pt"
+ bottom = "0pt"
+ top = "0pt"
+ elseif height == v_fit then
+ height = "true"
+ bottom = bottom == v_fit and "true" or topoints(checked(bottom,bondlength,unit,scale))
+ top = top == v_fit and "true" or topoints(checked(top, bondlength,unit,scale))
+ else
+ height = checked(height,bondlength,unit,scale)
+ if bottom == v_fit then
+ if top == v_fit then
+ bottom = height / 2
+ top = bottom
+ else
+ top = checked(top,bondlength,unit,scale)
+ bottom = height - top
+ end
+ elseif top == v_fit then
+ bottom = checked(bottom,bondlength,unit,scale)
+ top = height - bottom
+ else
+ bottom = checked(bottom,bondlength,unit,scale)
+ top = checked(top, bondlength,unit,scale)
+ local ratio = height / (bottom+top)
+ bottom = bottom * ratio
+ top = top * ratio
+ end
+ scaled = height
+ top = topoints(top)
+ bottom = topoints(bottom)
+ height = topoints(height)
+ end
+ return height, bottom, top, scaled
+end
+
+function chemistry.start(settings)
+ --
+ local width = settings.width or v_fit
+ local height = settings.height or v_fit
+ local unit = settings.unit or 655360
+ local bondlength = settings.factor or 3
+ local rulethickness = settings.rulethickness or 65536
+ local rulecolor = settings.rulecolor or ""
+ local axiscolor = settings.framecolor or ""
+ local scale = settings.scale or "normal"
+ local rotation = settings.rotation or 0
+ local offset = settings.offset or 0
+ local left = settings.left or v_fit
+ local right = settings.right or v_fit
+ local top = settings.top or v_fit
+ local bottom = settings.bottom or v_fit
+ --
+ align = settings.symalign or "auto"
+ if trace_structure then
+ report_chemistry("unit %p, bondlength %s, symalign %s",unit,bondlength,align)
+ end
+ if align ~= "" then
+ align = "." .. align
+ end
+ if trace_structure then
+ report_chemistry("%s scale %a, rotation %a, width %s, height %s, left %s, right %s, top %s, bottom %s","asked",scale,rotation,width,height,left,right,top,bottom)
+ end
+ if scale == v_small then
+ scale = 1/1.2
+ elseif scale == v_normal or scale == v_medium or scale == 0 then
+ scale = 1
+ elseif scale == v_big then
+ scale = 1.2
+ else
+ scale = tonumber(scale)
+ if not scale or scale == 0 then
+ scale = 1
+ elseif scale >= 10 then
+ scale = scale / 1000
+ elseif scale < .01 then
+ scale = .01
+ end
+ end
+ --
+ unit = scale * unit
+ --
+ local sp_width = 0
+ local sp_height = 0
+ --
+ width, left, right, sp_width = calculated(width, left, right,bondlength,unit,scale)
+ height, bottom, top, sp_height = calculated(height,bottom,top, bondlength,unit,scale)
+ --
+ if width ~= "true" and height ~= "true" and trialtypesetting() then
+ if trace_structure then
+ report_chemistry("skipping trial run")
+ end
+ context.hrule(sp_width,sp_height,0) -- maybe depth
+ return
+ end
+ --
+ chemistry.structures = chemistry.structures + 1
+ --
+ rotation = tonumber(rotation) or 0
+ --
+ metacode = { }
+ --
+ if trace_structure then
+ report_chemistry("%s scale %a, rotation %a, width %s, height %s, left %s, right %s, top %s, bottom %s","used",scale,rotation,width,height,left,right,top,bottom)
+ end
+ metacode[#metacode+1] = f_start_structure(
+ chemistry.structures,
+ left, right, top, bottom,
+ rotation, topoints(unit), bondlength, scale, topoints(offset),
+ tostring(settings.axis == v_on), topoints(rulethickness), tostring(axiscolor)
+ )
+ metacode[#metacode+1] = f_set_trace_bounds(trace_boundingbox) ;
+ --
+ variant, keys, stack, pstack, sstack = "one", { }, { }, { }, { }
+end
+
+function chemistry.stop()
+ if metacode then
+ metacode[#metacode+1] = f_stop_structure
+ local mpcode = concat(metacode,"\n")
+ 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,
+ method = chemistry.method,
+ data = mpcode,
+ definitions = f_initialize,
+ }
+ t_initialize = ""
+ metacode = nil
+ end
+end
+
+function chemistry.component(spec,text,rulethickness,rulecolor)
+ if metacode then
+ local spec = settings_to_array_with_repeat(spec,true) -- no lower?
+ local text = settings_to_array_with_repeat(text,true)
+ metacode[#metacode+1] = f_start_component
+ process(1,spec,text,1,rulethickness,rulecolor)
+ metacode[#metacode+1] = f_stop_component
+ end
+end
+
+statistics.register("chemical formulas", function()
+ if chemistry.structures > 0 then
+ return format("%s chemical structure formulas",chemistry.structures) -- no timing needed, part of metapost
+ end
+end)
+
+-- interfaces
+
+implement {
+ name = "undefinechemical",
+ actions = chemistry.undefine,
+ arguments = "string"
+}
+
+implement {
+ name = "definechemical",
+ actions = chemistry.define,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "startchemical",
+ actions = chemistry.start,
+ arguments = {
+ {
+ { "width" },
+ { "height" },
+ { "left" },
+ { "right" },
+ { "top" },
+ { "bottom" },
+ { "scale" },
+ { "rotation" },
+ { "symalign" },
+ { "axis" },
+ { "framecolor" },
+ { "rulethickness" },
+ { "offset" },
+ { "unit" },
+ { "factor" }
+ }
+ }
+}
+
+implement {
+ name = "stopchemical",
+ actions = chemistry.stop,
+}
+
+implement {
+ name = "chemicalcomponent",
+ actions = chemistry.component,
+ arguments = { "string", "string", "string", "string" }
+}
+
+-- todo: top / bottom
+-- note that "<->" here differs from ppchtex
+
+local inline = {
+ ["single"] = "\\chemicalsinglebond", ["-"] = "\\chemicalsinglebond",
+ ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond",
+ ["="] = "\\chemicaldoublebond",
+ ["triple"] = "\\chemicaltriplebond", ["---"] = "\\chemicaltriplebond",
+ ["≡"] = "\\chemicaltriplebond",
+ ["gives"] = "\\chemicalgives", ["->"] = "\\chemicalgives",
+ ["equilibrium"] = "\\chemicalequilibrium", ["<-->"] = "\\chemicalequilibrium",
+ ["<=>"] = "\\chemicalequilibrium",
+ ["mesomeric"] = "\\chemicalmesomeric", ["<>"] = "\\chemicalmesomeric",
+ ["<->"] = "\\chemicalmesomeric",
+ ["plus"] = "\\chemicalplus", ["+"] = "\\chemicalplus",
+ ["minus"] = "\\chemicalminus",
+ ["equals"] = "\\chemicalequals",
+ ["space"] = "\\chemicalspace",
+}
+
+local ctx_chemicalinline = context.chemicalinline
+
+function chemistry.inlinechemical(spec)
+ local spec = settings_to_array_with_repeat(spec,true)
+ for i=1,#spec do
+ local s = spec[i]
+ local inl = inline[lower(s)]
+ if inl then
+ context(inl) -- could be a fast context.sprint
+ else
+ ctx_chemicalinline(molecule(s))
+ end
+ end
+end
+
+implement {
+ name = "inlinechemical",
+ actions = chemistry.inlinechemical,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv b/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv
new file mode 100644
index 00000000000..a0b0a932734
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv
@@ -0,0 +1,759 @@
+%D \module
+%D [ file=chem-ini,
+%D version=2009.05.13,
+%D subtitle=Chemistry,
+%D author=Hans Hagen \& Alan Braslau,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+%D but better implementation, later versions might provide more,
+
+\writestatus{loading}{ConTeXt Chemistry Macros / Structure}
+
+\registerctxluafile{chem-str}{1.001}
+
+% We have a slightly different interface. This is unchanged:
+%
+% \startchemical[axis=on]
+% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1]
+% \stopchemical
+%
+% Here we use chemicalformula instead, so no longer a mix:
+%
+% \startchemicalformula
+% \chemical{2H_2}{top}{bottom}
+% \chemical{PLUS}{top}{bottom}
+% \chemical{O_2}{top}{bottom}
+% \chemical{GIVES}{top}{bottom}
+% \chemical{2H_2O}{top}{bottom}
+% \stopchemicalformula
+%
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+%
+% The inline variant has only one argument:
+%
+% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O}
+
+\unprotect
+
+\installcorenamespace{chemical}
+\installcorenamespace{chemicalsymbol}
+\installcorenamespace{chemicalframed}
+\installcorenamespace{chemicalsize}
+
+% \installsimplecommandhandler \??chemical {chemical} \??chemical % no \define...
+\installcommandhandler \??chemical {chemical} \??chemical % no \define...
+
+\let\setupchemicals \setupchemical
+\let\definechemicals\definechemical
+
+%D We use a dedicated framed macro instead of inheriting one. This is both
+%D a historical and practical reason (like shared keys with different meaning
+%D that could clash, e.g.\ align).
+
+\defineMPinstance % not really needed as we set in lua
+ [chemistry]
+ [\s!format=metafun,
+ %\s!extensions=\v!yes, % Should we add extensions and initializations?
+ %\s!initializations=\v!yes, % Would this give EmWidth, etc.?
+ \c!method=\s!double]
+
+\startMPdefinitions{chemistry}
+ input mp-chem.mpiv ;
+\stopMPdefinitions
+
+\defineframed
+ [\??chemicalframed]
+ [\c!align=\v!normal,
+ \c!strut=\v!no]
+
+\unexpanded\def\setupchemicalframed
+ {\setupframed[\??chemicalframed]}
+
+\unexpanded\def\definechemical % is global (so we don't use the commandhandler)
+ {\dosingleargument\chem_define}
+
+\def\chem_define[#1]#2%
+ {\startnointerference
+ \edef\currentdefinedchemical{#1}%
+ \let\chemical\chem_chemical_nested
+ \clf_undefinechemical{#1}%
+ #2% flush
+ \stopnointerference}
+
+\unexpanded\def\chem_chemical_nested
+ {\dodoubleempty\chem_chemical_nested_indeed}
+
+\def\chem_chemical_nested_indeed[#1][#2]%
+ {\clf_definechemical{\currentdefinedchemical}{#1}{\detokenize{#2}}}
+
+% chemical symbols
+
+\unexpanded\def\definechemicalsymbol
+ {\dodoubleempty\chem_symbol_define}
+
+\def\chem_symbol_define[#1][#2]%
+ {\setvalue{\??chemicalsymbol#1}{#2}}
+
+\unexpanded\def\chemicalsymbol[#1]%
+ {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname}
+
+\definechemicalsymbol[\s!unknown][] % \char"FFFD empty
+
+% size (small medium big)
+
+\edef\chemicaltoplocation{t}
+\edef\chemicalbotlocation{b}
+
+\unexpanded\def\chemicaltext#1%
+ {\mathematics
+ {\usechemicalstyleandcolor\c!style\c!color
+ \strut
+ \ifcase\currentxfontsize\or\scriptstyle\or\scriptscriptstyle\fi
+ #1}}
+
+\setvalue{\??chemicalsize\v!small }{\txx}
+\setvalue{\??chemicalsize\v!medium}{\tx}
+\setvalue{\??chemicalsize\v!big }{}
+
+\newtoks \everychemical
+\newtoks \everystructurechemical
+\newconditional\indisplaychemical
+
+\newtoks \t_chem_every_box
+\newbox \b_chem_result
+\newconditional\c_chem_some_text
+\newdimen \d_chem_width
+\newdimen \d_chem_height
+\newdimen \d_chem_depth
+
+\unexpanded\def\startchemical
+ {\dodoubleempty\chem_start}
+
+\def\chem_start[#1][#2]%
+ {\ifmmode\vcenter\else\vbox\fi % vpack ?
+ \bgroup
+ \synchronizestrut{\chemicalparameter\c!strut}%
+ \dontcomplain
+ \settrue\indisplaychemical
+ \forgetall
+ \ifsecondargument
+ \doifelseassignment{#1}
+ {\setupcurrentchemical[#1]}% same as \currentchemical
+ {\edef\currentchemical{#1}%
+ \setupcurrentchemical[#2]}%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\setupcurrentchemical[#1]}% same as \currentchemical
+ {\edef\currentchemical{#1}}%
+ \fi\fi
+ \the\everystructurechemical
+ \setbox\b_chem_result\hpack\bgroup
+ \clf_startchemical
+ width {\chemicalparameter\c!width}%
+ height {\chemicalparameter\c!height}%
+ left {\chemicalparameter\c!left}%
+ right {\chemicalparameter\c!right}%
+ top {\chemicalparameter\c!top}%
+ bottom {\chemicalparameter\c!bottom}%
+ scale {\chemicalparameter\c!scale}%
+ rotation {\chemicalparameter\c!rotation}%
+ symalign {\chemicalparameter\c!symalign}%
+ axis {\chemicalparameter\c!axis}%
+ framecolor {\MPcolor{\chemicalparameter\c!framecolor}}%
+ rulethickness {\number\dimexpr\chemicalparameter\c!rulethickness}%
+ offset {\number\dimexpr\chemicalparameter\c!offset}%
+ unit {\number\dimexpr\chemicalparameter\c!unit}%
+ factor {\number\chemicalparameter\c!factor}%
+ \relax
+ \startnointerference}
+
+\unexpanded\def\stopchemical
+ {\stopnointerference
+ \clf_stopchemical
+ \egroup
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+ \the\t_chem_every_box
+ \doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes
+ \egroup}
+
+\unexpanded\def\chem_framed_yes
+ {\localframedwithsettings
+ [\??chemicalframed]%
+ [\c!frame=\chemicalparameter\c!frame,
+ \c!rulethickness=\chemicalparameter\c!rulethickness,
+ \c!framecolor=\chemicalparameter\c!framecolor]%
+ {\vpack{\box\b_chem_result\vss}}} % remove depth
+
+\unexpanded\def\chem_framed_nop
+ {\directlocalframed
+ [\??chemicalframed]%
+ {\vpack{\box\b_chem_result\vss}}} % remove depth
+
+\let\startstructurechemical\startchemical
+\let\stopstructurechemical \stopchemical
+
+\unexpanded\def\structurechemical
+ {\dotripleempty\strc_chem_indeed}
+
+\appendtoks
+ \let\chemical\structurechemical
+\to\everystructurechemical
+
+\def\strc_chem_indeed
+ {\ifthirdargument
+ \expandafter\strc_chem_indeed_three
+ \else
+ \expandafter\strc_chem_indeed_two
+ \fi}
+
+\def\strc_chem_indeed_three[#1][#2][#3]%
+ {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored
+ \clf_chemicalcomponent
+ {#2}%
+ {\detokenize{#3}}%
+ {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points
+ {\MPcolor{\chemicalparameter\c!rulecolor}}% % we can precalculate this for speedup
+ \relax
+ \ignorespaces}
+
+\def\strc_chem_indeed_two[#1][#2]%
+ {\clf_chemicalcomponent
+ {#1}%
+ {\detokenize{#2}}%
+ {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points
+ {\MPcolor{\chemicalparameter\c!rulecolor}}% % we can precalculate this for speedup
+ \relax
+ \ignorespaces}
+
+\appendtoks
+ \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}%
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+\to \t_chem_every_box
+
+% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize)
+
+\appendtoks
+ \edef\chemicalbodyfont{\chemicalparameter\c!bodyfont}% public?
+ \ifx\chemicalbodyfont\empty
+ \switchtobodyfont[\chemicalbodyfont]%
+ \fi
+ \getvalue{\??chemicalsize\chemicalparameter\c!size}%
+% \to \everystructurechemical
+\to \everychemical
+
+\def\chemicaltoptext#1{\global\settrue\c_chem_some_text\gdef\m_chem_top_text{#1}\ignorespaces}
+\def\chemicalbottext#1{\global\settrue\c_chem_some_text\gdef\m_chem_bot_text{#1}\ignorespaces}
+\def\chemicalmidtext#1{\global\settrue\c_chem_some_text\gdef\m_chem_mid_text{#1}\ignorespaces}
+
+\appendtoks
+ \let\toptext\chemicaltoptext \glet\m_chem_top_text\empty
+ \let\bottext\chemicalbottext \glet\m_chem_bot_text\empty
+ \let\midtext\chemicalmidtext \glet\m_chem_mid_text\empty
+ \global\setfalse\c_chem_some_text
+\to \everystructurechemical
+
+\def\chem_add_texts
+ {\setbox2\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}%
+ \setbox4\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}%
+ \setbox6\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}%
+ \setbox\b_chem_result\hpack \bgroup
+ \box\b_chem_result
+ \hskip-\d_chem_width
+ \raise\d_chem_height\hpack{\lower\ht4\box4}%
+ \hskip-\d_chem_width
+ \lower.5\dimexpr\ht2-\dp2\relax\box2%
+ \hskip-\d_chem_width
+ \lower\d_chem_depth \hpack{\raise\dp6\box6}%
+ \hss
+ \egroup} % text on top of chemicals
+
+\appendtoks
+ \ifconditional\c_chem_some_text
+ \chem_add_texts
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+ \fi
+\to \t_chem_every_box
+
+% todo: enspace or emspace
+
+\definechemicalsymbol[space] [\enspace\quad\enspace]
+\definechemicalsymbol[plus] [\enspace+\enspace]
+\definechemicalsymbol[minus] [\enspace-\enspace]
+\definechemicalsymbol[gives] [\chem_arrow_construct\xrightarrow]
+\definechemicalsymbol[equilibrium] [\chem_arrow_construct\xrightoverleftarrow]
+\definechemicalsymbol[mesomeric] [\chem_arrow_construct\xleftrightarrow]
+\definechemicalsymbol[opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[SPACE] [{\chemicalsymbol[space]}]
+\definechemicalsymbol[PLUS] [{\chemicalsymbol[plus]}]
+\definechemicalsymbol[MINUS] [{\chemicalsymbol[minus]}]
+\definechemicalsymbol[GIVES] [{\chemicalsymbol[gives]}]
+\definechemicalsymbol[EQUILIBRIUM] [{\chemicalsymbol[equilibrium]}]
+\definechemicalsymbol[MESOMERIC] [{\chemicalsymbol[mesomeric]}]
+\definechemicalsymbol[OPENCOMPLEX] [{\chemicalsymbol[opencomplex]}]
+\definechemicalsymbol[CLOSECOMPLEX][{\chemicalsymbol[closecomplex]}]
+
+\def\chem_arrow_construct#1#2#3%
+ {\enspace
+ \mathematics{#1%
+ {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#3}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#2}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}%
+ \enspace}
+
+% special macros (probably needs some more work)
+
+\let\chem_box_normal_yes\hbox
+\let\chem_box_visual_yes\hbox
+\let\chem_box_visual_nop\relax
+
+\installtextracker
+ {chemistry.boxes}
+ {\let\chem_box_visual_yes\ruledhbox \let\chem_box_visual_nop\ruledhbox}
+ {\let\chem_box_visual_yes\hbox \let\chem_box_visual_nop\relax }
+
+\def\chem_top_construct#1#2#3#4%
+ {\hpack\bgroup
+ \setstrut
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\raise\dimexpr\dp\scratchboxone+\ht\scratchboxtwo\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \smashbox\scratchboxone
+ \box\scratchboxone
+ \box\scratchboxtwo
+ \egroup}
+
+\def\chem_bottom_construct#1#2#3#4%
+ {\hpack\bgroup
+ \setstrut
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\lower\dimexpr\dp\scratchboxtwo+\ht\scratchboxone\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \smashbox\scratchboxone
+ \box\scratchboxone
+ \box\scratchboxtwo
+ \egroup}
+
+\unexpanded\def\chemicalleft#1#2% redundant boxes thanks to visual
+ {\hbox\bgroup % hpack ?
+ \setstrut
+ \llap{\chem_box_visual_nop{\strut#1}}%
+ \chem_box_visual_nop{\strut#2}%
+ \egroup}
+
+\unexpanded\def\chemicalright#1#2% redundant boxes thanks to visual
+ {\hbox\bgroup % hpack ?
+ \setstrut
+ \chem_box_visual_yes{\strut#2}%
+ \rlap{\chem_box_visual_nop{\strut#1}}%
+ \egroup}
+
+\unexpanded\def\chemicaltop {\chem_top_construct \hss \hss }
+\unexpanded\def\chemicallefttop {\chem_top_construct \relax \hss }
+\unexpanded\def\chemicalrighttop {\chem_top_construct \hss \relax}
+\unexpanded\def\chemicalbottom {\chem_bottom_construct \hss \hss }
+\unexpanded\def\chemicalleftbottom {\chem_bottom_construct \relax \hss }
+\unexpanded\def\chemicalrightbottom {\chem_bottom_construct \hss \relax}
+
+\unexpanded\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}}
+\unexpanded\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}}
+\unexpanded\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}}
+\unexpanded\def\chemicalbottomright #1{\chemicalright{\chemicalleftbottom {#1}{}}}
+
+% \unexpanded\def\chemicalcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1\hss}}
+% \unexpanded\def\chemicalleftcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut #1\hss}}
+% \unexpanded\def\chemicalrightcentered#1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1}}
+
+% \let\chemicalsmashedmiddle\chemicalcentered
+% \let\chemicalsmashedleft \chemicalleftcentered
+% \let\chemicalsmashedright \chemicalrightcentered
+
+\unexpanded\def\chemicalalignedtext
+ {\ifmmode
+ \expandafter\chem_aligned_text_math
+ \else
+ \expandafter\chem_aligned_text_text
+ \fi}
+
+\let\chemicaltighttext\relax % maybe smaller strut
+
+\def\chem_aligned_text_text#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \usechemicalstyleandcolor\c!style\c!color
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
+ \setstrut\strut
+ #1\molecule{#3}#2%
+ \egroup
+ \endgroup}
+
+\def\chem_aligned_text_math#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
+ \setstrut\strut
+ #1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2%
+ \egroup
+ \endgroup}
+
+\unexpanded\def\chemicalcentered {\chemicalalignedtext\hss \hss }
+\unexpanded\def\chemicalleftcentered {\chemicalalignedtext\relax\hss }
+\unexpanded\def\chemicalrightcentered{\chemicalalignedtext\hss \relax}
+
+\let\chemicalsmashedmiddle\chemicalcentered
+\let\chemicalsmashedleft \chemicalleftcentered
+\let\chemicalsmashedright \chemicalrightcentered
+
+\unexpanded\def\chemicaloxidation#1#2#3%
+ {\chemicaltop{\txx\ifcase#2\relax0\else#1\convertnumber{I}{#2}\fi}{#3}}
+
+\unexpanded\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed!
+\unexpanded\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed!
+\unexpanded\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed!
+\unexpanded\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed!
+\unexpanded\def\chemicaloxidationone {\chemicaloxidation\relax1}
+\unexpanded\def\chemicaloxidationtwo {\chemicaloxidation\relax2}
+\unexpanded\def\chemicaloxidationthree{\chemicaloxidation\relax3}
+\unexpanded\def\chemicaloxidationfour {\chemicaloxidation\relax4}
+\unexpanded\def\chemicaloxidationfive {\chemicaloxidation\relax5}
+\unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6}
+\unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7}
+
+\unexpanded\def\chemicalbar
+ {\hpack \s!spread .5\emwidth \bgroup
+ \hss
+ \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight
+ \hss
+ \egroup}
+
+\appendtoks
+ \let|\chemicalbar % \SR{N|NH}
+ \let \+\chemicaloxidationplus
+ \let \-\chemicaloxidationminus
+ \let \[\chemicalforeveropen
+ \let \]\chemicalforeverclose
+ \let \1\chemicaloxidationone
+ \let \2\chemicaloxidationtwo
+ \let \3\chemicaloxidationthree
+ \let \4\chemicaloxidationfour
+ \let \5\chemicaloxidationfive
+ \let \6\chemicaloxidationsix
+ \let \7\chemicaloxidationseven
+ \let \X\chemicaltighttext
+ \let \T\chemicaltop
+ \let \B\chemicalbottom
+ \let \L\chemicalleft
+ \let\LC\chemicalleftcentered
+ \let \R\chemicalright
+ \let\RC\chemicalrightcentered
+ \let\TL\chemicaltopleft
+ \let\BL\chemicalbottomleft
+ \let\TR\chemicaltopright
+ \let\BR\chemicalbottomright
+ \let\LT\chemicallefttop
+ \let\LB\chemicalleftbottom
+ \let\RT\chemicalrighttop
+ \let\RB\chemicalrightbottom
+ \let\SL\chemicalsmashedleft
+ \let\SM\chemicalsmashedmiddle
+ \let\SR\chemicalsmashedright
+\to \everychemical
+
+% Should these also be defined in lower case, so as to be case independent?
+
+\appendtoks
+ \the\everychemical
+\to \everystructurechemical
+
+% inline
+
+% \unexpanded\def\chemical
+% {\ifinformula
+% \expandafter\displaychemical
+% \else
+% \expandafter\inlinechemical
+% \fi}
+
+\unexpanded\def\chemical
+ {\ifinformula
+ \expandafter\indisplaychemical
+ \else
+ \expandafter\inlinechemical
+ \fi}
+
+\unexpanded\def\indisplaychemical
+ {\mathstylecommand\displaychemical\inlinechemical\inlinechemical}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\clf_inlinechemical{#1}}}%
+ \endgroup}
+
+\unexpanded\def\displaychemical
+ {\dotriplegroupempty\chem_display}
+
+\def\chem_display#1#2#3%
+ {\the\everychemical
+ \everychemical\emptytoks
+ \quad
+ \vcenter\bgroup
+ \usechemicalstyleandcolor\c!style\c!color
+ \ifthirdargument
+ \ifsecondargument
+ \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
+ \else
+ \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}%
+ \fi
+ \else
+ \hbox{\molecule{#1}}%
+ \fi
+ \egroup
+ \quad}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}}
+
+\unexpanded\def\chemicalbondrule
+ {\hpack{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
+
+\definechemicalsymbol[i:space] [\enspace\quad\enspace]
+\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace]
+\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace]
+\definechemicalsymbol[i:equals] [\enspace\mathematics{=}\enspace]
+\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace]
+\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:single] [\chemicalbondrule]
+\definechemicalsymbol[i:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+
+\unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]}
+\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:triple]}
+\unexpanded\def\chemicalgives {\chemicalsymbol[i:gives]}
+\unexpanded\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]}
+\unexpanded\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]}
+\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]}
+\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]}
+\unexpanded\def\chemicalequals {\chemicalsymbol[i:equals]}
+\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]}
+\unexpanded\def\chemicalinline #1{#1}
+
+% display
+
+\newconditional\c_chem_has_top
+\newconditional\c_chem_has_bot
+
+\newtoks\t_chem_top
+\newtoks\t_chem_mid
+\newtoks\t_chem_bot
+
+\newif\ifinchemicalformula
+
+\unexpanded\def\startchemicalformula
+ {\mathortext\vcenter\vbox\bgroup
+ \forgetall
+ \inchemicalformulatrue
+ \the\everychemical
+ \everychemical\emptytoks
+ \t_chem_top\emptytoks % not needed
+ \t_chem_mid\emptytoks % not needed
+ \t_chem_bot\emptytoks % not needed
+ \let\chemical\formulachemical
+ \setfalse\c_chem_has_top
+ \setfalse\c_chem_has_bot}
+
+\unexpanded\def\stopchemicalformula
+ {\tabskip\emwidth\relax
+ \nointerlineskip
+ \ifconditional\c_chem_has_top
+ \ifconditional\c_chem_has_bot
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \else
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
+ \fi
+ \else
+ \ifconditional\c_chem_has_bot
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \else
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr}%
+ \fi
+ \fi
+ \egroup}
+
+% for the moment we have a special set
+
+\definechemicalsymbol[d:space] [\enspace\quad\enspace]
+\definechemicalsymbol[d:plus] [\enspace+\enspace]
+\definechemicalsymbol[d:minus] [\enspace-\enspace]
+\definechemicalsymbol[d:equals] [\enspace=\enspace]
+\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow
+\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow
+\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow
+\definechemicalsymbol[d:single] [\chemicalbondrule]
+\definechemicalsymbol[d:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[d:SPACE] [{\chemicalsymbol[d:space]}]
+\definechemicalsymbol[d:PLUS] [{\chemicalsymbol[d:plus]}]
+\definechemicalsymbol[d:MINUS] [{\chemicalsymbol[d:minus]}]
+\definechemicalsymbol[d:EQUALS] [{\chemicalsymbol[d:equals]}]
+\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}]
+\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}]
+\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}]
+\definechemicalsymbol[d:SINGLE] [{\chemicalsymbol[d:single]}]
+\definechemicalsymbol[d:DOUBLE] [{\chemicalsymbol[d:double]}]
+\definechemicalsymbol[d:TRIPLE] [{\chemicalsymbol[d:triple]}]
+\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}]
+\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}]
+
+\unexpanded\def\formulachemical
+ {\relax\dotriplegroupempty\chem_formula}
+
+\def\chem_formula#1#2#3% we could do hboxes and measure
+ {\ifthirdargument
+ \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
+ \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
+ \else\ifsecondargument
+ \chem_formula_top_nop
+ \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
+ \else
+ \chem_formula_top_nop
+ \chem_formula_bot_nop
+ \fi\fi
+ \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname
+ \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}%
+ \else
+ \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}%
+ \fi}
+
+\def\chem_formula_mid#1%
+ {\csname\??chemicalsymbol\detokenize{#1}\endcsname}
+
+\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top\aligntab}}
+\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot\aligntab}}
+\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top}
+\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot}
+
+\def\chem_formula_top_indeed#1{\strut#1}
+\def\chem_formula_bot_indeed#1{\strut#1}
+
+% Experimental: defaults might change.
+
+\definefloat
+ [\v!chemical]
+ [\v!chemicals]
+
+\setuplabeltext
+ [\v!chemical=]
+
+\setupfloat
+ [\v!chemical]
+ [\c!location=\v!here,
+ \c!inner=\hsize.8\textwidth\dontleavehmode, % brr
+ \c!align={\v!flushleft,\v!lohi}]
+
+\setupcaption
+ [\v!chemical]
+ [\c!location=\v!right,
+ \c!distance=\zeropoint,
+ \c!width=.2\textwidth,
+ \c!align=\v!flushright]
+
+% Can be used as for displayed math: \startplaceformula... to display a chemical formula
+% or a chemical structure:
+%
+% \startplacechemical
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+% \stopplacechemical
+
+% gone: state option resolution offset (now frame offset) alternative
+
+\setupchemicalframed
+ [\c!align=\v!normal,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\definecolor % private color
+ [chemicalframecolor]
+ [r=.75,g=.85,b=.95]
+
+\setupchemical
+ [\c!frame=,
+ \c!width=\v!fit, % or unitless number, multiplies scale*unit
+ \c!height=\v!fit, % or unitless number, multiplies scale*unit
+ \c!left=\v!fit, % or unitless number, multiplies scale*unit
+ \c!right=\v!fit, % or unitless number, multiplies scale*unit
+ \c!top=\v!fit, % or unitless number, multiplies scale*unit
+ \c!bottom=\v!fit, % or unitless number, multiplies scale*unit
+ \c!bodyfont=,
+ \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies unit)
+ \c!size=\v!medium,
+ \c!textsize=\v!big, % how is textsize used??
+ \c!axis=\v!off,
+ \c!style=\rm,
+ \c!rotation=0, % unitless number (interpreted as degrees)
+ \c!symalign=\v!auto,
+ \c!location=, % not yet used (was interaction related in mkii)
+ \c!offset=.25\emwidth,
+ \c!unit=\emwidth,
+ \c!factor=3,
+ \c!color=,
+ \c!strut=\v!yes,
+ \c!framecolor=chemicalframecolor,
+ \c!rulethickness=0.6pt, %1.5\linewidth,
+ \c!rulecolor=]
+
+%D Compatibility:
+
+\definechemical[+R] {\chemical[RR]}
+\definechemical[-R] {\chemical[LR]}
+
+\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]}
+\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]}
+
+\definechemical[NEWMAN] {\chemical[]}
+\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]}
+\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]}
+\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]}
+\definechemical[SIX:FRONT] {\chemical[SIXFRONT]}
+\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua
new file mode 100644
index 00000000000..1067a17d57e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua
@@ -0,0 +1,190 @@
+if not modules then modules = { } end modules ['cldf-bas'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- -- speedtest needed:
+--
+-- local flush, writer = context.getlogger()
+--
+-- trackers.register("context.trace",function(v)
+-- flush, writer = context.getlogger()
+-- end)
+--
+-- function context.bgroup()
+-- flush(ctxcatcodes,"{")
+-- end
+--
+-- function context.egroup()
+-- flush(ctxcatcodes,"}")
+-- end
+
+-- maybe use context.generics
+
+local type = type
+local format = string.format
+local utfchar = utf.char
+local concat = table.concat
+
+local context = context
+local generics = context.generics
+local variables = interfaces.variables
+
+local nodepool = nodes.pool
+local new_rule = nodepool.rule
+local new_glyph = nodepool.glyph
+
+local current_font = font.current
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
+function context.char(k) -- used as escape too, so don't change to utf
+ if type(k) == "table" then
+ local n = #k
+ if n == 1 then
+ context([[\char%s\relax]],k[1])
+ elseif n > 0 then
+ context([[\char%s\relax]],concat(k,[[\relax\char]]))
+ end
+ else
+ if type(k) == "string" then
+ k = tonumber(k)
+ end
+ if type(k) == "number" then
+ context([[\char%s\relax]],k)
+ end
+ end
+end
+
+function context.utfchar(k)
+ if type(k) == "string" then
+ k = tonumber(k)
+ end
+ if type(k) == "number" then
+ context(utfchar(k))
+ end
+end
+
+-- plain variants
+
+function context.chardef(cs,u)
+ context([[\chardef\%s=%s\relax]],k)
+end
+
+function context.par()
+ context([[\par]]) -- no need to add {} there
+end
+
+function context.bgroup()
+ context("{")
+end
+
+function context.egroup()
+ context("}")
+end
+
+function context.space()
+ context("\\space") -- no " " as that gets intercepted
+end
+
+function context.hrule(w,h,d,dir)
+ if type(w) == "table" then
+ context(new_rule(w.width,w.height,w.depth,w.dir))
+ else
+ context(new_rule(w,h,d,dir))
+ end
+end
+
+function context.glyph(id,k)
+ if id then
+ if not k then
+ id, k = current_font(), id
+ end
+ context(new_glyph(id,k))
+ end
+end
+
+context.vrule = context.hrule
+
+--~ local hbox, bgroup, egroup = context.hbox, context.bgroup, context.egroup
+
+--~ function context.hbox(a,...)
+--~ if type(a) == "table" then
+--~ local s = { }
+--~ if a.width then
+--~ s[#s+1] = "to " .. a.width -- todo: check for number
+--~ elseif a.spread then
+--~ s[#s+1] = "spread " .. a.spread -- todo: check for number
+--~ end
+--~ -- todo: dir, attr etc
+--~ hbox(false,table.concat(s," "))
+--~ bgroup()
+--~ context(string.format(...))
+--~ egroup()
+--~ else
+--~ hbox(a,...)
+--~ end
+--~ end
+
+-- not yet used ... but will get variant at the tex end as well
+
+function context.sethboxregister(n) context([[\setbox %s\hbox]],n) end
+function context.setvboxregister(n) context([[\setbox %s\vbox]],n) end
+
+function context.starthboxregister(n)
+ if type(n) == "number" then
+ context([[\setbox%s\hbox{]],n)
+ else
+ context([[\setbox\%s\hbox{]],n)
+ end
+end
+
+function context.startvboxregister(n)
+ if type(n) == "number" then
+ context([[\setbox%s\vbox{]],n)
+ else
+ context([[\setbox\%s\vbox{]],n)
+ end
+end
+
+context.stophboxregister = context.egroup
+context.stopvboxregister = context.egroup
+
+function context.flushboxregister(n)
+ if type(n) == "number" then
+ context([[\box%s ]],n)
+ else
+ context([[\box\%s]],n)
+ end
+end
+
+function context.beginvbox()
+ context([[\vbox{]]) -- we can do \bvbox ... \evbox (less tokens)
+end
+
+function context.beginhbox()
+ context([[\hbox{]]) -- todo: use fast one
+end
+
+context.endvbox = context.egroup
+context.endhbox = context.egroup
+
+local function allocate(name,what,cmd)
+ local a = format("c_syst_last_allocated_%s",what)
+ local n = texgetcount(a) + 1
+ if n <= texgetcount("c_syst_max_allocated_register") then
+ texsetcount(a,n)
+ end
+ context("\\global\\expandafter\\%sdef\\csname %s\\endcsname %s\\relax",cmd or what,name,n)
+ return n
+end
+
+function context.newdimen (name) return allocate(name,"dimen") end
+function context.newskip (name) return allocate(name,"skip") end
+function context.newcount (name) return allocate(name,"count") end
+function context.newmuskip(name) return allocate(name,"muskip") end
+function context.newtoks (name) return allocate(name,"toks") end
+function context.newbox (name) return allocate(name,"box","mathchar") end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.mkiv
new file mode 100644
index 00000000000..f8b5b5d6a3c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.mkiv
@@ -0,0 +1,19 @@
+%D \module
+%D [ file=cldf-bas,
+%D version=2010.10.19,,
+%D title=\CONTEXT\ \LUA\ Document Functions,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Lua Documents / Basics}
+
+\registerctxluafile{cldf-bas}{1.001}
+\registerctxluafile{cldf-prs}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-com.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-com.lua
new file mode 100644
index 00000000000..bd357b712b2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-com.lua
@@ -0,0 +1,38 @@
+if not modules then modules = { } end modules ['cldf-com'] = {
+ version = 1.001,
+ comment = "companion to cldf-com.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo ... needs more thinking ... a special table toolkit
+
+local tostring = tostring
+local context = context
+local generics = context.generics -- needs documentation
+local variables = interfaces.variables
+
+generics.starttabulate = "starttabulate" -- "start" .. variables.tabulate -- todo: e!start
+generics.stoptabulate = "stoptabulate" -- "stop" .. variables.tabulate -- todo: e!stop
+
+local NC, NR = context.NC, context.NR
+
+local function tabulaterow(how,...)
+ for i=1,select("#",...) do
+ local ti = tostring(select(i,...))
+ NC()
+ if how then
+ context[how](ti)
+ else
+ context(ti)
+ end
+ end
+ NC()
+ NR()
+end
+
+function context.tabulaterow (...) tabulaterow(false, ...) end
+function context.tabulaterowbold(...) tabulaterow("bold",...) end
+function context.tabulaterowtype(...) tabulaterow("type",...) end
+function context.tabulaterowtyp (...) tabulaterow("typ", ...) end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-com.mkiv
new file mode 100644
index 00000000000..49190988893
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-com.mkiv
@@ -0,0 +1,19 @@
+%D \module
+%D [ file=cldf-com,
+%D version=2010.10.19,,
+%D title=\CONTEXT\ \LUA\ Document Functions,
+%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 Lua Documents / Functions}
+
+\registerctxluafile{cldf-com}{1.001}
+\registerctxluafile{cldf-ver}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua
new file mode 100644
index 00000000000..0c39f72f55d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua
@@ -0,0 +1,1934 @@
+if not modules then modules = { } end modules ['cldf-ini'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- also see cldf-tod.* !
+-- old code moved to cldf-old.lua
+
+-- maybe:
+--
+-- 0.528 local foo = tex.ctxcatcodes
+-- 0.651 local foo = getcount("ctxcatcodes")
+-- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes")
+
+-- This started as an experiment: generating context code at the lua end. After all
+-- it is surprisingly simple to implement due to metatables. I was wondering if
+-- there was a more natural way to deal with commands at the lua end. Of course it's
+-- a bit slower but often more readable when mixed with lua code. It can also be handy
+-- when generating documents from databases or when constructing large tables or so.
+--
+-- maybe optional checking against interface
+-- currently no coroutine trickery
+-- we could always use prtcatcodes (context.a_b_c) but then we loose protection
+-- tflush needs checking ... sort of weird that it's not a table
+-- __flushlines is an experiment and rather ugly so it will go away
+--
+-- tex.print == line with endlinechar appended
+
+-- 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
+-- 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.
+
+-- context(lpeg.match(lpeg.patterns.texescape,"${}"))
+-- context(string.formatters["%!tex!"]("${}"))
+-- context("%!tex!","${}")
+
+local format, stripstring = string.format, string.strip
+local next, type, tostring, tonumber, setmetatable, unpack, select, rawset = next, type, tostring, tonumber, setmetatable, unpack, select, rawset
+local insert, remove, concat = table.insert, table.remove, table.concat
+local lpegmatch, lpegC, lpegS, lpegP, lpegV, lpegCc, lpegCs, patterns = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.V, lpeg.Cc, lpeg.Cs, lpeg.patterns
+local formatters = string.formatters -- using formatters is slower in this case
+
+context = context or { }
+commands = commands or { }
+interfaces = interfaces or { }
+
+local context = context
+local commands = commands
+local interfaces = interfaces
+
+local loaddata = io.loaddata
+
+local tex = tex
+local texsprint = tex.sprint -- just appended (no space,eol treatment)
+local texprint = tex.print -- each arg a separate line (not last in directlua)
+----- texwrite = tex.write -- all 'space' and 'character'
+local texgetcount = tex.getcount
+
+-- local function texsprint(...) print("sprint",...) tex.sprint(...) end
+-- local function texprint (...) print("print", ...) tex.print (...) end
+
+local isnode = node.is_node
+local writenode = node.write
+local copynodelist = node.copy_list
+
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local prtcatcodes = catcodenumbers.prtcatcodes
+local texcatcodes = catcodenumbers.texcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+local xmlcatcodes = catcodenumbers.xmlcatcodes
+
+local flush = texsprint -- snippets
+local flushdirect = texprint -- lines
+----- flushraw = texwrite
+
+local report_context = logs.reporter("cld","tex")
+local report_cld = logs.reporter("cld","stack")
+
+local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end)
+
+-- In earlier experiments a function tables was referred to as lua.calls and the
+-- primitive \luafunctions was \luacall.
+
+local luafunctions = lua.get_functions_table and lua.get_functions_table()
+local usedstack = nil
+local showstackusage = false
+
+-- luafunctions = false
+
+trackers.register("context.stack",function(v) showstackusage = v end)
+
+local storefunction, flushfunction
+local storenode, flushnode
+local registerfunction, unregisterfunction, reservefunction, knownfunctions, callfunctiononce
+
+-- if luafunctions then
+
+ local freed, nofused, noffreed = { }, 0, 0 -- maybe use the number of @@trialtypesetting
+
+ usedstack = function()
+ return nofused, noffreed
+ end
+
+ flushfunction = function(slot,arg)
+ if arg() then
+ -- keep
+ elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+ noffreed = noffreed + 1
+ freed[noffreed] = slot
+ luafunctions[slot] = false
+ else
+ -- keep
+ end
+ end
+
+ storefunction = function(arg)
+ local f = function(slot) flushfunction(slot,arg) end
+ if noffreed > 0 then
+ local n = freed[noffreed]
+ freed[noffreed] = nil
+ noffreed = noffreed - 1
+ luafunctions[n] = f
+ return n
+ else
+ nofused = nofused + 1
+ luafunctions[nofused] = f
+ return nofused
+ end
+ end
+
+ flushnode = function(slot,arg)
+ if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+ writenode(arg)
+ noffreed = noffreed + 1
+ freed[noffreed] = slot
+ luafunctions[slot] = false
+ else
+ writenode(copynodelist(arg))
+ end
+ end
+
+ storenode = function(arg)
+ local f = function(slot) flushnode(slot,arg) end
+ if noffreed > 0 then
+ local n = freed[noffreed]
+ freed[noffreed] = nil
+ noffreed = noffreed - 1
+ luafunctions[n] = f
+ return n
+ else
+ nofused = nofused + 1
+ luafunctions[nofused] = f
+ return nofused
+ end
+ end
+
+ -- registerfunction = function(f)
+ -- if type(f) == "string" then
+ -- f = loadstring(f)
+ -- end
+ -- if type(f) ~= "function" then
+ -- f = function() report_cld("invalid function %A",f) end
+ -- end
+ -- if noffreed > 0 then
+ -- local n = freed[noffreed]
+ -- freed[noffreed] = nil
+ -- noffreed = noffreed - 1
+ -- luafunctions[n] = f
+ -- return n
+ -- else
+ -- nofused = nofused + 1
+ -- luafunctions[nofused] = f
+ -- return nofused
+ -- end
+ -- end
+
+ storage.storedfunctions = storage.storedfunctions or { }
+ local storedfunctions = storage.storedfunctions
+ local initex = environment.initex
+
+ storage.register("storage/storedfunctions", storedfunctions, "storage.storedfunctions")
+
+ 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
+ end
+
+ local function expose(slot,f,...) -- so we can register yet undefined functions
+ local func = resolvestoredfunction(f)
+ if not func then
+ func = function() report_cld("beware: unknown function %i called: %s",slot,f) end
+ end
+ luafunctions[slot] = func
+ return func(...)
+ end
+
+ if initex then
+ -- todo: log stored functions
+ else
+ local slots = table.sortedkeys(storedfunctions)
+ local last = #slots
+ if last > 0 then
+ -- we restore the references
+ for i=1,last do
+ local slot = slots[i]
+ local data = storedfunctions[slot]
+ luafunctions[slot] = function(...)
+ -- print(data) -- could be trace
+ return expose(slot,data,...)
+ end
+ end
+ -- we now know how many are defined
+ nofused = slots[last]
+ -- normally there are no holes in the list yet
+ for i=1,nofused do
+ if not luafunctions[i] then
+ noffreed = noffreed + 1
+ freed[noffreed] = i
+ end
+ end
+ -- report_cld("%s registered functions, %s freed slots",last,noffreed)
+ end
+ end
+
+ registerfunction = function(f,direct) -- either f=code or f=namespace,direct=name
+ local slot, func
+ if noffreed > 0 then
+ slot = freed[noffreed]
+ freed[noffreed] = nil
+ noffreed = noffreed - 1
+ else
+ nofused = nofused + 1
+ slot = nofused
+ end
+ if direct then
+ if initex then
+ func = function(...)
+ expose(slot,f,...)
+ end
+ if initex then
+ storedfunctions[slot] = f
+ end
+ else
+ func = resolvestoredfunction(f)
+ end
+ if type(func) ~= "function" then
+ func = function() report_cld("invalid resolve %A",f) end
+ end
+ elseif type(f) == "string" then
+ func = loadstring(f)
+ if type(func) ~= "function" then
+ func = function() report_cld("invalid code %A",f) end
+ end
+ elseif type(f) == "function" then
+ func = f
+ else
+ func = function() report_cld("invalid function %A",f) end
+ end
+ luafunctions[slot] = func
+ return slot
+ end
+
+ -- do
+ -- commands.test = function(str) report_cld("test function: %s", str) end
+ -- if initex then
+ -- registerfunction("commands.test") -- number 1
+ -- end
+ -- luafunctions[1]("okay")
+ -- end
+
+ unregisterfunction = function(slot)
+ if luafunctions[slot] then
+ noffreed = noffreed + 1
+ freed[noffreed] = slot
+ luafunctions[slot] = false
+ else
+ report_cld("invalid function slot %A",slot)
+ end
+ end
+
+ reservefunction = function()
+ if noffreed > 0 then
+ local n = freed[noffreed]
+ freed[noffreed] = nil
+ noffreed = noffreed - 1
+ return n
+ else
+ nofused = nofused + 1
+ return nofused
+ end
+ end
+
+ callfunctiononce = function(slot)
+ luafunctions[slot](slot)
+ noffreed = noffreed + 1
+ freed[noffreed] = slot
+ luafunctions[slot] = false
+ end
+
+ table.setmetatablecall(luafunctions,function(t,n) return luafunctions[n](n) end)
+
+ knownfunctions = luafunctions
+
+ -- The next hack is a convenient way to define scanners at the Lua end and
+ -- get them available at the TeX end. There is some dirty magic needed to
+ -- prevent overload during format loading.
+
+ -- interfaces.scanners.foo = function() context("[%s]",tokens.scanners.string()) end : \scan_foo
+
+ interfaces.storedscanners = interfaces.storedscanners or { }
+ local storedscanners = interfaces.storedscanners
+
+ storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners")
+
+ local interfacescanners = table.setmetatablenewindex(function(t,k,v)
+ if storedscanners[k] then
+ -- report_cld("warning: scanner %a is already set",k)
+ -- os.exit()
+ -- \scan_<k> is already in the format
+ -- report_cld("using interface scanner: %s",k)
+ else
+ -- todo: allocate slot here and pass it
+ storedscanners[k] = true
+ -- report_cld("installing interface scanner: %s",k)
+ context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k)
+ end
+ rawset(t,k,v)
+ end)
+
+ interfaces.scanners = interfacescanners
+
+-- else -- by now this is obsolete
+--
+-- local luafunctions, noffunctions = { }, 0
+-- local luanodes, nofnodes = { }, 0
+--
+-- usedstack = function()
+-- return noffunctions + nofnodes, 0
+-- end
+--
+-- flushfunction = function(n)
+-- local sn = luafunctions[n]
+-- if not sn then
+-- report_cld("data with id %a cannot be found on stack",n)
+-- elseif not sn() and texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+-- luafunctions[n] = nil
+-- end
+-- end
+--
+-- storefunction = function(ti)
+-- noffunctions = noffunctions + 1
+-- luafunctions[noffunctions] = ti
+-- return noffunctions
+-- end
+--
+-- -- freefunction = function(n)
+-- -- luafunctions[n] = nil
+-- -- end
+--
+-- flushnode = function(n)
+-- local sn = luanodes[n]
+-- if not sn then
+-- report_cld("data with id %a cannot be found on stack",n)
+-- elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+-- writenode(sn)
+-- luanodes[n] = nil
+-- else
+-- writenode(copynodelist(sn))
+-- end
+-- end
+--
+-- storenode = function(ti)
+-- nofnodes = nofnodes + 1
+-- luanodes[nofnodes] = ti
+-- return nofnodes
+-- end
+--
+-- _cldf_ = flushfunction -- global
+-- _cldn_ = flushnode -- global
+-- -- _cldl_ = function(n) return luafunctions[n]() end -- luafunctions(n)
+-- _cldl_ = luafunctions
+--
+-- registerfunction = function(f)
+-- if type(f) == "string" then
+-- f = loadstring(f)
+-- end
+-- if type(f) ~= "function" then
+-- f = function() report_cld("invalid function %A",f) end
+-- end
+-- noffunctions = noffunctions + 1
+-- luafunctions[noffunctions] = f
+-- return noffunctions
+-- end
+--
+-- unregisterfunction = function(slot)
+-- if luafunctions[slot] then
+-- luafunctions[slot] = nil
+-- else
+-- report_cld("invalid function slot %A",slot)
+-- end
+-- end
+--
+-- reservefunction = function()
+-- noffunctions = noffunctions + 1
+-- return noffunctions
+-- end
+--
+-- callfunctiononce = function(slot)
+-- luafunctions[slot](slot)
+-- luafunctions[slot] = nil
+-- end
+--
+-- table.setmetatablecall(luafunctions,function(t,n) return luafunctions[n](n) end)
+--
+-- knownfunctions = luafunctions
+--
+-- end
+
+context.registerfunction = registerfunction
+context.unregisterfunction = unregisterfunction
+context.reservefunction = reservefunction
+context.knownfunctions = knownfunctions
+context.callfunctiononce = callfunctiononce _cldo_ = callfunctiononce
+context.storenode = storenode -- private helper
+
+function commands.ctxfunction(code,namespace)
+ context(registerfunction(code,namespace))
+end
+
+function commands.ctxscanner(name,code,namespace)
+ local n = registerfunction(code,namespace)
+ if storedscanners[name] then
+ storedscanners[name] = n
+ end
+ context(n)
+end
+
+local function dummy() end
+
+function commands.ctxresetter(name)
+ return function()
+ if storedscanners[name] then
+ rawset(interfacescanners,name,dummy)
+ context.resetctxscanner("clf_" .. name)
+ end
+ end
+end
+
+function context.trialtypesetting()
+ return texgetcount("@@trialtypesetting") ~= 0
+end
+
+-- local f_cldo = formatters["_cldo_(%i)"]
+-- local latelua_node = nodes.pool.latelua
+--
+-- function context.lateluafunctionnnode(f)
+-- return latelua_node(f_cldo(registerfunction(f)))
+-- end
+
+-- Should we keep the catcodes with the function?
+
+local catcodestack = { }
+local currentcatcodes = ctxcatcodes
+local contentcatcodes = ctxcatcodes
+
+local catcodes = {
+ ctx = ctxcatcodes, ctxcatcodes = ctxcatcodes, context = ctxcatcodes,
+ prt = prtcatcodes, prtcatcodes = prtcatcodes, protect = prtcatcodes,
+ tex = texcatcodes, texcatcodes = texcatcodes, plain = texcatcodes,
+ txt = txtcatcodes, txtcatcodes = txtcatcodes, text = txtcatcodes,
+ vrb = vrbcatcodes, vrbcatcodes = vrbcatcodes, verbatim = vrbcatcodes,
+ xml = xmlcatcodes, xmlcatcodes = xmlcatcodes,
+}
+
+-- maybe just increment / decrement
+
+-- local function pushcatcodes(c)
+-- insert(catcodestack,currentcatcodes)
+-- currentcatcodes = (c and catcodes[c] or tonumber(c)) or currentcatcodes
+-- contentcatcodes = currentcatcodes
+-- end
+--
+-- local function popcatcodes()
+-- currentcatcodes = remove(catcodestack) or currentcatcodes
+-- contentcatcodes = currentcatcodes
+-- end
+
+local catcodelevel = 0
+
+local function pushcatcodes(c)
+ catcodelevel = catcodelevel + 1
+ catcodestack[catcodelevel] = currentcatcodes
+ currentcatcodes = (c and catcodes[c] or tonumber(c)) or currentcatcodes
+ contentcatcodes = currentcatcodes
+end
+
+local function popcatcodes()
+ if catcodelevel > 0 then
+ currentcatcodes = catcodestack[catcodelevel] or currentcatcodes
+ catcodelevel = catcodelevel - 1
+ end
+ contentcatcodes = currentcatcodes
+end
+
+context.catcodes = catcodes
+context.pushcatcodes = pushcatcodes
+context.popcatcodes = popcatcodes
+
+-- -- --
+
+local newline = patterns.newline
+local space = patterns.spacer
+local spacing = newline * space^0
+local content = lpegC((1-spacing)^1) -- texsprint
+local emptyline = space^0 * newline^2 -- texprint("")
+local endofline = space^0 * newline * space^0 -- texsprint(" ")
+local simpleline = endofline * lpegP(-1) --
+
+local verbose = lpegC((1-space-newline)^1)
+local beginstripper = (lpegS(" \t")^1 * newline^1) / ""
+local endstripper = beginstripper * lpegP(-1)
+
+local justaspace = space * lpegCc("")
+local justanewline = newline * lpegCc("")
+
+local function n_content(s)
+ flush(contentcatcodes,s)
+end
+
+local function n_verbose(s)
+ flush(vrbcatcodes,s)
+end
+
+local function n_endofline()
+ flush(currentcatcodes," \r")
+end
+
+local function n_emptyline()
+ flushdirect(currentcatcodes,"\r")
+end
+
+local function n_simpleline()
+ flush(currentcatcodes," \r")
+end
+
+local n_exception = ""
+
+-- better a table specification
+
+function context.newtexthandler(specification) -- can also be used for verbose
+ specification = specification or { }
+ --
+ local s_catcodes = specification.catcodes
+ --
+ local f_before = specification.before
+ local f_after = specification.after
+ --
+ local f_endofline = specification.endofline or n_endofline
+ local f_emptyline = specification.emptyline or n_emptyline
+ local f_simpleline = specification.simpleline or n_simpleline
+ local f_content = specification.content or n_content
+ local f_space = specification.space
+ --
+ local p_exception = specification.exception
+ --
+ if s_catcodes then
+ f_content = function(s)
+ flush(s_catcodes,s)
+ end
+ end
+ --
+ local pattern
+ if f_space then
+ if p_exception then
+ local content = lpegC((1-spacing-p_exception)^1)
+ pattern =
+ (
+ justaspace / f_space
+ + justanewline / f_endofline
+ + p_exception
+ + content / f_content
+ )^0
+ else
+ local content = lpegC((1-space-endofline)^1)
+ pattern =
+ (
+ justaspace / f_space
+ + justanewline / f_endofline
+ + content / f_content
+ )^0
+ end
+ else
+ if p_exception then
+ local content = lpegC((1-spacing-p_exception)^1)
+ pattern =
+ simpleline / f_simpleline
+ +
+ (
+ emptyline / f_emptyline
+ + endofline / f_endofline
+ + p_exception
+ + content / f_content
+ )^0
+ else
+ local content = lpegC((1-spacing)^1)
+ pattern =
+ simpleline / f_simpleline
+ +
+ (
+ emptyline / f_emptyline
+ + endofline / f_endofline
+ + content / f_content
+ )^0
+ end
+ end
+ --
+ if f_before then
+ pattern = (P(true) / f_before) * pattern
+ end
+ --
+ if f_after then
+ pattern = pattern * (P(true) / f_after)
+ end
+ --
+ return function(str) return lpegmatch(pattern,str) end, pattern
+end
+
+function context.newverbosehandler(specification) -- a special variant for e.g. cdata in lxml-tex
+ specification = specification or { }
+ --
+ local f_line = specification.line or function() flushdirect("\r") end
+ local f_space = specification.space or function() flush(" ") end
+ local f_content = specification.content or n_verbose
+ local f_before = specification.before
+ local f_after = specification.after
+ --
+ local pattern =
+ justanewline / f_line -- so we get call{}
+ + verbose / f_content
+ + justaspace / f_space -- so we get call{}
+ --
+ if specification.strip then
+ pattern = beginstripper^0 * (endstripper + pattern)^0
+ else
+ pattern = pattern^0
+ end
+ --
+ if f_before then
+ pattern = (lpegP(true) / f_before) * pattern
+ end
+ --
+ if f_after then
+ pattern = pattern * (lpegP(true) / f_after)
+ end
+ --
+ return function(str) return lpegmatch(pattern,str) end, pattern
+end
+
+local flushlines = context.newtexthandler {
+ content = n_content,
+ endofline = n_endofline,
+ emptyline = n_emptyline,
+ simpleline = n_simpleline,
+}
+
+context.__flushlines = flushlines -- maybe context.helpers.flushtexlines
+context.__flush = flush
+context.__flushdirect = flushdirect
+
+-- The next variant is only used in rare cases (buffer to mp):
+
+local printlines_ctx = (
+ (newline) / function() texprint("") end +
+ (1-newline)^1 / function(s) texprint(ctxcatcodes,s) end * newline^-1
+)^0
+
+local printlines_raw = (
+ (newline) / function() texprint("") end +
+ (1-newline)^1 / function(s) texprint(s) end * newline^-1
+)^0
+
+function context.printlines(str,raw) -- todo: see if via file is useable
+ if raw then
+ lpegmatch(printlines_raw,str)
+ else
+ lpegmatch(printlines_ctx,str)
+ end
+end
+
+-- -- -- "{" .. ti .. "}" is somewhat slower in a cld-mkiv run than "{",ti,"}"
+
+local containseol = patterns.containseol
+
+local writer = nil
+local prtwriter = nil
+
+-- if luafunctions then
+
+ writer = function (parent,command,...) -- already optimized before call
+ flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
+ local direct = false
+ -- local t = { ... }
+ -- for i=1,#t do
+ -- local ti = t[i]
+ for i=1,select("#",...) do
+ local ti = (select(i,...))
+ if direct then
+ local typ = type(ti)
+ if typ == "string" or typ == "number" then
+ flush(currentcatcodes,ti)
+ else -- node.write
+ report_context("error: invalid use of direct in %a, only strings and numbers can be flushed directly, not %a",command,typ)
+ end
+ direct = false
+ elseif ti == nil then
+ -- nothing
+ elseif ti == "" then
+ flush(currentcatcodes,"{}")
+ else
+ local typ = type(ti)
+ if typ == "string" then
+ -- is processlines seen ?
+ if processlines and lpegmatch(containseol,ti) then
+ flush(currentcatcodes,"{")
+ local flushlines = parent.__flushlines or flushlines
+ flushlines(ti)
+ flush(currentcatcodes,"}")
+ elseif currentcatcodes == contentcatcodes then
+ flush(currentcatcodes,"{",ti,"}")
+ else
+ flush(currentcatcodes,"{")
+ flush(contentcatcodes,ti)
+ flush(currentcatcodes,"}")
+ end
+ elseif typ == "number" then
+ -- numbers never have funny catcodes
+ flush(currentcatcodes,"{",ti,"}")
+ elseif typ == "table" then
+ local tn = #ti
+ if tn == 0 then
+ local done = false
+ for k, v in next, ti do
+ if done then
+ if v == "" then
+ flush(currentcatcodes,",",k,'=')
+ else
+ flush(currentcatcodes,",",k,"={",v,"}")
+ end
+ else
+ if v == "" then
+ flush(currentcatcodes,"[",k,"=")
+ else
+ flush(currentcatcodes,"[",k,"={",v,"}")
+ end
+ done = true
+ end
+ end
+ if done then
+ flush(currentcatcodes,"]")
+ else
+ flush(currentcatcodes,"[]")
+ end
+ elseif tn == 1 then -- some 20% faster than the next loop
+ local tj = ti[1]
+ if type(tj) == "function" then
+ flush(currentcatcodes,"[\\cldl",storefunction(tj),"]")
+ -- flush(currentcatcodes,"[",storefunction(tj),"]")
+ else
+ flush(currentcatcodes,"[",tj,"]")
+ end
+ else -- is concat really faster than flushes here? probably needed anyway (print artifacts)
+ flush(currentcatcodes,"[")
+ for j=1,tn do
+ local tj = ti[j]
+ if type(tj) == "function" then
+ if j == tn then
+ flush(currentcatcodes,"\\cldl",storefunction(tj),"]")
+ -- flush(currentcatcodes,"",storefunction(tj),"]")
+ else
+ flush(currentcatcodes,"\\cldl",storefunction(tj),",")
+ -- flush(currentcatcodes,"",storefunction(tj),",")
+ end
+ else
+ if j == tn then
+ flush(currentcatcodes,tj,"]")
+ else
+ flush(currentcatcodes,tj,",")
+ end
+ end
+ end
+ end
+ elseif typ == "function" then
+ flush(currentcatcodes,"{\\cldl ",storefunction(ti),"}") -- todo: ctx|prt|texcatcodes
+ -- flush(currentcatcodes,"{",storefunction(ti),"}") -- todo: ctx|prt|texcatcodes
+ elseif typ == "boolean" then
+ if ti then
+ flushdirect(currentcatcodes,"\r")
+ else
+ direct = true
+ end
+ elseif typ == "thread" then
+ report_context("coroutines not supported as we cannot yield across boundaries")
+ elseif isnode(ti) then -- slow
+ flush(currentcatcodes,"{\\cldl",storenode(ti),"}")
+ -- flush(currentcatcodes,"{",storenode(ti),"}")
+ else
+ report_context("error: %a gets a weird argument %a",command,ti)
+ end
+ end
+ end
+ end
+
+ -- if performance really matters we can consider a compiler but it will never
+ -- pay off
+
+ prtwriter = function (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,"{\\cldl ",storefunction(ti),"}")
+ -- flush(currentcatcodes,"{",storefunction(ti),"}") -- todo: ctx|prt|texcatcodes
+ elseif isnode(ti) then
+ flush(prtcatcodes,"{\\cldl",storenode(ti),"}")
+ -- flush(currentcatcodes,"{",storenode(ti),"}")
+ else
+ report_context("fatal error: prt %a gets a weird argument %a",command,ti)
+ end
+ end
+ end
+ end
+
+-- else
+--
+-- writer = function (parent,command,first,...) -- already optimized before call
+-- local t = { first, ... }
+-- flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
+-- local direct = false
+-- for i=1,#t do
+-- local ti = t[i]
+-- local typ = type(ti)
+-- if direct then
+-- if typ == "string" or typ == "number" then
+-- flush(currentcatcodes,ti)
+-- else -- node.write
+-- report_context("error: invalid use of direct in %a, only strings and numbers can be flushed directly, not %a",command,typ)
+-- end
+-- direct = false
+-- elseif ti == nil then
+-- -- nothing
+-- elseif ti == "" then
+-- flush(currentcatcodes,"{}")
+-- elseif typ == "string" then
+-- -- is processelines seen ?
+-- if processlines and lpegmatch(containseol,ti) then
+-- flush(currentcatcodes,"{")
+-- local flushlines = parent.__flushlines or flushlines
+-- flushlines(ti)
+-- flush(currentcatcodes,"}")
+-- elseif currentcatcodes == contentcatcodes then
+-- flush(currentcatcodes,"{",ti,"}")
+-- else
+-- flush(currentcatcodes,"{")
+-- flush(contentcatcodes,ti)
+-- flush(currentcatcodes,"}")
+-- end
+-- elseif typ == "number" then
+-- -- numbers never have funny catcodes
+-- flush(currentcatcodes,"{",ti,"}")
+-- elseif typ == "table" then
+-- local tn = #ti
+-- if tn == 0 then
+-- local done = false
+-- for k, v in next, ti do
+-- if done then
+-- if v == "" then
+-- flush(currentcatcodes,",",k,'=')
+-- else
+-- flush(currentcatcodes,",",k,"={",v,"}")
+-- end
+-- else
+-- if v == "" then
+-- flush(currentcatcodes,"[",k,"=")
+-- else
+-- flush(currentcatcodes,"[",k,"={",v,"}")
+-- end
+-- done = true
+-- end
+-- end
+-- if done then
+-- flush(currentcatcodes,"]")
+-- else
+-- flush(currentcatcodes,"[]")
+-- end
+-- elseif tn == 1 then -- some 20% faster than the next loop
+-- local tj = ti[1]
+-- if type(tj) == "function" then
+-- flush(currentcatcodes,"[\\cldf{",storefunction(tj),"}]")
+-- else
+-- flush(currentcatcodes,"[",tj,"]")
+-- end
+-- else -- is concat really faster than flushes here? probably needed anyway (print artifacts)
+-- for j=1,tn do
+-- local tj = ti[j]
+-- if type(tj) == "function" then
+-- ti[j] = "\\cldf{" .. storefunction(tj) .. "}"
+-- end
+-- end
+-- flush(currentcatcodes,"[",concat(ti,","),"]")
+-- end
+-- elseif typ == "function" then
+-- flush(currentcatcodes,"{\\cldf{",storefunction(ti),"}}") -- todo: ctx|prt|texcatcodes
+-- elseif typ == "boolean" then
+-- if ti then
+-- flushdirect(currentcatcodes,"\r")
+-- else
+-- direct = true
+-- end
+-- elseif typ == "thread" then
+-- report_context("coroutines not supported as we cannot yield across boundaries")
+-- elseif isnode(ti) then -- slow
+-- flush(currentcatcodes,"{\\cldn{",storenode(ti),"}}")
+-- else
+-- report_context("error: %a gets a weird argument %a",command,ti)
+-- end
+-- end
+-- end
+--
+-- end
+
+local generics = { } context.generics = generics
+local indexer = nil
+local prtindexer = nil
+
+-- if environment.initex then
+
+ indexer = function(parent,k)
+ if type(k) == "string" then
+ local c = "\\" .. tostring(generics[k] or k)
+ local f = function(first,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ else
+ return writer(parent,c,first,...)
+ end
+ end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
+ end
+ end
+
+-- else
+--
+-- local create = token.create
+-- local twrite = token.write
+-- local setmacro = token.set_macro
+--
+-- indexer = function(parent,k)
+-- if type(k) == "string" then
+-- local s = tostring(generics[k] or k)
+-- local t = create(s)
+-- if t.cmdname == "undefined_cs" then
+-- report_cld("macro \\%s is not yet defined",s)
+-- token.set_macro(s,"")
+-- t = create(s)
+-- end
+-- local i = t.id
+-- local f = function(first,...)
+-- twrite(t.tok) --= we need to keep t uncollected
+-- if first ~= nil then
+-- return writer(parent,first,...)
+-- end
+-- end
+-- parent[k] = f
+-- return f
+-- else
+-- return context -- catch
+-- end
+-- end
+--
+-- end
+
+-- Potential optimization: after the first call we know if there will be an
+-- argument. Of course there is the side effect that for instance abuse like
+-- context.NC(str) fails as well as optional arguments. So, we don't do this
+-- in practice. We just keep the next trick commented. The gain on some
+-- 100000 calls is not that large: 0.100 => 0.95 which is neglectable.
+--
+-- local function constructor(parent,k,c,first,...)
+-- if first == nil then
+-- local f = function()
+-- flush(currentcatcodes,c)
+-- end
+-- parent[k] = f
+-- return f()
+-- else
+-- local f = function(...)
+-- return writer(parent,c,...)
+-- end
+-- parent[k] = f
+-- return f(first,...)
+-- end
+-- end
+--
+-- local function indexer(parent,k)
+-- local c = "\\" .. tostring(generics[k] or k)
+-- local f = function(...)
+-- return constructor(parent,k,c,...)
+-- end
+-- parent[k] = f
+-- return f
+-- end
+
+-- only for internal usage:
+
+do
+
+ function context.constructcsonly(k) -- not much faster than the next but more mem efficient
+ local c = "\\" .. tostring(generics[k] or k)
+ local v = function()
+ flush(prtcatcodes,c)
+ end
+ rawset(context,k,v) -- context namespace
+ return v
+ end
+
+ function context.constructcs(k)
+ local c = "\\" .. tostring(generics[k] or k)
+ local v = function(first,...)
+ if first == nil then
+ flush(prtcatcodes,c)
+ else
+ return prtwriter(c,first,...)
+ end
+ end
+ rawset(context,k,v) -- context namespace
+ return v
+ end
+
+ local function prtindexer(t,k)
+ local c = "\\" .. tostring(generics[k] or k)
+ local v = function(first,...)
+ if first == nil then
+ flush(prtcatcodes,c)
+ else
+ return prtwriter(c,first,...)
+ end
+ end
+ rawset(t,k,v) -- protected namespace
+ return v
+ end
+
+ context.protected = { } -- we could check for _ in the context namespace
+
+ setmetatable(context.protected, { __index = prtindexer, __call = prtwriter } )
+
+end
+
+-- local splitformatters = utilities.strings.formatters.new(true) -- not faster (yet)
+
+local caller
+
+-- if luafunctions then
+
+ caller = function(parent,f,a,...)
+ if not parent then
+ -- so we don't need to test in the calling (slower but often no issue)
+ elseif f ~= nil then
+ local typ = type(f)
+ if typ == "string" then
+ if f == "" then
+ -- new, can save a bit sometimes
+ -- if trace_context then
+ -- report_context("empty argument to context()")
+ -- end
+ elseif a then
+ flush(contentcatcodes,formatters[f](a,...)) -- was currentcatcodes
+ -- flush(contentcatcodes,splitformatters[f](a,...)) -- was currentcatcodes
+ elseif processlines and lpegmatch(containseol,f) then
+ local flushlines = parent.__flushlines or flushlines
+ flushlines(f)
+ else
+ flush(contentcatcodes,f)
+ end
+ elseif typ == "number" then
+ if a then
+ flush(currentcatcodes,f,a,...)
+ else
+ flush(currentcatcodes,f)
+ end
+ elseif typ == "function" then
+ -- ignored: a ...
+ flush(currentcatcodes,"{\\cldl",storefunction(f),"}") -- todo: ctx|prt|texcatcodes
+ -- flush(currentcatcodes,"{",storefunction(f),"}") -- todo: ctx|prt|texcatcodes
+ elseif typ == "boolean" then
+ if f then
+ if a ~= nil then
+ local flushlines = parent.__flushlines or flushlines
+ flushlines(a)
+ else
+ flushdirect(currentcatcodes,"\n") -- no \r, else issues with \startlines ... use context.par() otherwise
+ end
+ else
+ if a ~= nil then
+ -- no command, same as context(a,...)
+ writer(parent,"",a,...)
+ else
+ -- ignored
+ end
+ end
+ 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)," ")
+ else
+ report_context("error: %a gets a weird argument %a","context",f)
+ end
+ end
+ end
+
+ function context.flushnode(n)
+ flush(currentcatcodes,"\\cldl",storenode(n)," ")
+ -- flush(currentcatcodes,"",storenode(n)," ")
+ end
+
+-- else
+--
+-- caller = function(parent,f,a,...)
+-- if not parent then
+-- -- so we don't need to test in the calling (slower but often no issue)
+-- elseif f ~= nil then
+-- local typ = type(f)
+-- if typ == "string" then
+-- if f == "" then
+-- -- new, can save a bit sometimes
+-- -- if trace_context then
+-- -- report_context("empty argument to context()")
+-- -- end
+-- elseif a then
+-- flush(contentcatcodes,formatters[f](a,...)) -- was currentcatcodes
+-- -- flush(contentcatcodes,splitformatters[f](a,...)) -- was currentcatcodes
+-- elseif processlines and lpegmatch(containseol,f) then
+-- local flushlines = parent.__flushlines or flushlines
+-- flushlines(f)
+-- else
+-- flush(contentcatcodes,f)
+-- end
+-- elseif typ == "number" then
+-- if a then
+-- flush(currentcatcodes,f,a,...)
+-- else
+-- flush(currentcatcodes,f)
+-- end
+-- elseif typ == "function" then
+-- -- ignored: a ...
+-- flush(currentcatcodes,"{\\cldf{",storefunction(f),"}}") -- todo: ctx|prt|texcatcodes
+-- elseif typ == "boolean" then
+-- if f then
+-- if a ~= nil then
+-- local flushlines = parent.__flushlines or flushlines
+-- flushlines(a)
+-- else
+-- flushdirect(currentcatcodes,"\n") -- no \r, else issues with \startlines ... use context.par() otherwise
+-- end
+-- else
+-- if a ~= nil then
+-- -- no command, same as context(a,...)
+-- writer(parent,"",a,...)
+-- else
+-- -- ignored
+-- end
+-- end
+-- elseif typ == "thread" then
+-- report_context("coroutines not supported as we cannot yield across boundaries")
+-- elseif isnode(f) then -- slow
+-- -- writenode(f)
+-- flush(currentcatcodes,"\\cldn{",storenode(f),"}")
+-- else
+-- report_context("error: %a gets a weird argument %a","context",f)
+-- end
+-- end
+-- end
+--
+-- function context.flushnode(n)
+-- flush(currentcatcodes,"\\cldn{",storenode(n),"}")
+-- end
+--
+-- end
+
+local defaultcaller = caller
+
+setmetatable(context, { __index = indexer, __call = caller } )
+
+-- now we tweak unprotect and protect
+
+function context.unprotect()
+ -- at the lua end
+ insert(catcodestack,currentcatcodes)
+ currentcatcodes = prtcatcodes
+ contentcatcodes = currentcatcodes
+ -- at the tex end
+ flush("\\unprotect")
+end
+
+function context.protect()
+ -- at the tex end
+ flush("\\protect")
+ -- at the lua end
+ currentcatcodes = remove(catcodestack) or currentcatcodes
+ contentcatcodes = currentcatcodes
+end
+
+function context.sprint(...) -- takes catcodes as first argument
+ flush(...)
+end
+
+function context.fprint(catcodes,fmt,first,...)
+ if type(catcodes) == "number" then
+ if first then
+ flush(catcodes,formatters[fmt](first,...))
+ else
+ flush(catcodes,fmt)
+ end
+ else
+ if fmt then
+ flush(formatters[catcodes](fmt,first,...))
+ else
+ flush(catcodes)
+ end
+ end
+end
+
+function tex.fprint(fmt,first,...) -- goodie
+ if first then
+ flush(currentcatcodes,formatters[fmt](first,...))
+ else
+ flush(currentcatcodes,fmt)
+ end
+end
+
+-- logging
+
+local trace_stack = { }
+
+local normalflush = flush
+local normalflushdirect = flushdirect
+----- normalflushraw = flushraw
+local normalwriter = writer
+local currenttrace = nil
+local nofwriters = 0
+local nofflushes = 0
+
+local tracingpermitted = true
+
+local visualizer = lpeg.replacer {
+ { "\n","<<newline>>" },
+ { "\r","<<par>>" },
+}
+
+statistics.register("traced context", function()
+ local used, freed = usedstack()
+ local unreachable = used - freed
+ if nofwriters > 0 or nofflushes > 0 then
+ return format("writers: %s, flushes: %s, maxstack: %s",nofwriters,nofflushes,used,freed,unreachable)
+ elseif showstackusage or unreachable > 0 then
+ return format("maxstack: %s, freed: %s, unreachable: %s",used,freed,unreachable)
+ end
+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 traced = function(catcodes,...) -- todo: check for catcodes
+ local s = concat({...})
+ s = lpegmatch(visualizer,s)
+ n = n + 1
+ t[n] = s
+ end
+ flush = function(...)
+ normalflush(...)
+ if tracingpermitted then
+ traced(...)
+ end
+ end
+ flushdirect = function(...)
+ normalflushdirect(...)
+ if tracingpermitted then
+ traced(...)
+ end
+ end
+ normalwriter(parent,...)
+ flush = savedflush
+ flushdirect = savedflushdirect
+ currenttrace(concat(t))
+end
+
+-- we could reuse collapsed
+
+local traced = function(one,two,...)
+ if two ~= nil then
+ -- only catcodes if 'one' is number
+ local catcodes = type(one) == "number" and one
+ local arguments = catcodes and { two, ... } or { one, two, ... }
+ local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1
+ for i=1,#arguments do
+ local argument = arguments[i]
+ local argtype = type(argument)
+ c = c + 1
+ if argtype == "string" then
+ collapsed[c] = lpegmatch(visualizer,argument)
+ elseif argtype == "number" then
+ collapsed[c] = argument
+ else
+ collapsed[c] = formatters["<<%S>>"](argument)
+ end
+ end
+ currenttrace(concat(collapsed))
+ elseif one ~= nil then
+ -- no catcodes
+ local argtype = type(one)
+ if argtype == "string" then
+ currenttrace(formatters["f : - : %s"](lpegmatch(visualizer,one)))
+ elseif argtype == "number" then
+ currenttrace(formatters["f : - : %s"](one))
+ else
+ currenttrace(formatters["f : - : <<%S>>"](one))
+ end
+ end
+end
+
+local tracedflush = function(one,two,...)
+ nofflushes = nofflushes + 1
+ if two ~= nil then
+ normalflush(one,two,...)
+ else
+ normalflush(one)
+ end
+ if tracingpermitted then
+ traced(one,two,...)
+ end
+end
+
+local tracedflushdirect = function(one,two,...)
+ nofflushes = nofflushes + 1
+ if two ~= nil then
+ normalflushdirect(one,two,...)
+ else
+ normalflushdirect(one)
+ end
+ if tracingpermitted then
+ traced(one,two,...)
+ end
+end
+
+local function pushlogger(trace)
+ trace = trace or report_context
+ insert(trace_stack,currenttrace)
+ currenttrace = trace
+ --
+ flush = tracedflush
+ flushdirect = tracedflushdirect
+ writer = tracedwriter
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
+ --
+ return flush, writer, flushdirect
+end
+
+local function poplogger()
+ currenttrace = remove(trace_stack)
+ if not currenttrace then
+ flush = normalflush
+ flushdirect = normalflushdirect
+ writer = normalwriter
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
+ end
+ return flush, writer, flushdirect
+end
+
+local function settracing(v)
+ if v then
+ return pushlogger(report_context)
+ else
+ return poplogger()
+ end
+end
+
+-- todo: share flushers so that we can define in other files
+
+trackers.register("context.trace",settracing)
+
+context.pushlogger = pushlogger
+context.poplogger = poplogger
+context.settracing = settracing
+
+-- -- untested, no time now:
+--
+-- local tracestack, tracestacktop = { }, false
+--
+-- function context.pushtracing(v)
+-- insert(tracestack,tracestacktop)
+-- if type(v) == "function" then
+-- pushlogger(v)
+-- v = true
+-- else
+-- pushlogger()
+-- end
+-- tracestacktop = v
+-- settracing(v)
+-- end
+--
+-- function context.poptracing()
+-- poplogger()
+-- tracestacktop = remove(tracestack) or false
+-- settracing(tracestacktop)
+-- end
+
+function context.getlogger()
+ return flush, writer, flush_direct
+end
+
+local trace_cld = false trackers.register("context.files", function(v) trace_cld = v end)
+
+do
+
+ -- This is the most reliable way to deal with nested buffers and other
+ -- catcode sensitive data.
+
+ local resolve = resolvers.savers.byscheme
+ local validstring = string.valid
+ local input = context.input
+
+ local function viafile(data,tag)
+ if data and data ~= "" then
+ local filename = resolve("virtual",validstring(tag,"viafile"),data)
+ -- context.startregime { "utf" }
+ input(filename)
+ -- context.stopregime()
+ end
+ end
+
+ context.viafile = viafile
+
+ -- experiment for xtables, don't use it elsewhere yet
+
+ local collected = nil
+ local nofcollected = 0
+ 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
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = (select(i,...))
+ 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
+
+ -- doesn't work well with tracing do we need to avoid that when
+ -- collecting stuff
+
+ function context.startcollecting()
+ if level == 0 then
+ collected = { }
+ nofcollected = 0
+ --
+ flush = collect
+ flushdirect = collectdirect
+ permitted = tracingpermitted
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
+ end
+ level = level + 1
+ end
+
+ function context.stopcollecting()
+ level = level - 1
+ if level < 1 then
+ flush = normalflush
+ flushdirect = normalflushdirect
+ tracingpermitted = permitted
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
+ --
+ viafile(concat(collected,sentinel))
+ --
+ collected = nil
+ nofcollected = 0
+ level = 0
+ end
+ end
+
+end
+
+--
+
+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)
+ 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
+ else
+ report_context("unknown file %a",filename)
+ end
+end
+
+function context.loadfile(filename)
+ context(stripstring(loaddata(resolvers.findfile(filename))))
+end
+
+-- some functions
+
+function context.direct(first,...)
+ if first ~= nil then
+ return writer(context,"",first,...)
+ end
+end
+
+-- context.delayed (todo: lines)
+
+local delayed = { } context.delayed = delayed -- creates function (maybe also store them)
+
+local function indexer(parent,k)
+ local f = function(...)
+ local a = { ... }
+ return function()
+ return context[k](unpack(a))
+ end
+ end
+ parent[k] = f
+ return f
+end
+
+local function caller(parent,...) -- todo: nodes
+ local a = { ... }
+ return function()
+ return context(unpack(a))
+ end
+end
+
+-- local function indexer(parent,k)
+-- local f = function(a,...)
+-- if not a then
+-- return function()
+-- return context[k]()
+-- end
+-- elseif select("#",...) == 0 then
+-- return function()
+-- return context[k](a)
+-- end
+-- elseif a then
+-- local t = { ... }
+-- return function()
+-- return context[k](a,unpack(t))
+-- end
+-- end
+-- end
+-- parent[k] = f
+-- return f
+-- end
+--
+-- local function caller(parent,a,...) -- todo: nodes
+-- if not a then
+-- return function()
+-- return context()
+-- end
+-- elseif select("#",...) == 0 then
+-- return function()
+-- return context(a)
+-- end
+-- elseif a then
+-- local t = { ... }
+-- return function()
+-- return context(a,unpack(t))
+-- end
+-- end
+-- end
+
+setmetatable(delayed, { __index = indexer, __call = caller } )
+
+-- context.nested (todo: lines)
+
+local nested = { } context.nested = nested -- creates strings
+
+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](...)
+ 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(...)
+ flush = savedflush
+ return concat(t)
+end
+
+setmetatable(nested, { __index = indexer, __call = caller } )
+
+-- verbatim
+
+function context.newindexer(catcodes)
+ local handler = { }
+
+ local function indexer(parent,k)
+ local command = context[k]
+ local f = function(...)
+ local savedcatcodes = contentcatcodes
+ contentcatcodes = catcodes
+ command(...)
+ contentcatcodes = savedcatcodes
+ end
+ parent[k] = f
+ return f
+ end
+
+ local function caller(parent,...)
+ local savedcatcodes = contentcatcodes
+ contentcatcodes = catcodes
+ defaultcaller(parent,...)
+ contentcatcodes = savedcatcodes
+ end
+
+ setmetatable(handler, { __index = indexer, __call = caller } )
+
+ return handler
+end
+
+context.verbatim = context.newindexer(vrbcatcodes)
+context.puretext = context.newindexer(txtcatcodes)
+-------.protected = context.newindexer(prtcatcodes)
+
+-- formatted
+
+local formatted = { } context.formatted = formatted
+
+-- local function indexer(parent,k)
+-- local command = context[k]
+-- local f = function(fmt,...)
+-- command(formatters[fmt](...))
+-- end
+-- parent[k] = f
+-- return f
+-- end
+
+local function indexer(parent,k)
+ if type(k) == "string" then
+ local c = "\\" .. tostring(generics[k] or k)
+ local f = function(first,second,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ elseif second then
+ return writer(parent,c,formatters[first](second,...))
+ else
+ return writer(parent,c,first)
+ end
+ end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
+ end
+end
+
+-- local function caller(parent,...)
+-- context.fprint(...)
+-- end
+
+local function caller(parent,catcodes,fmt,first,...)
+ if type(catcodes) == "number" then
+ if first then
+ flush(catcodes,formatters[fmt](first,...))
+ else
+ flush(catcodes,fmt)
+ end
+ else
+ if fmt then
+ flush(formatters[catcodes](fmt,first,...))
+ else
+ flush(catcodes)
+ end
+ end
+end
+
+setmetatable(formatted, { __index = indexer, __call = caller } )
+
+-- metafun (this will move to another file)
+
+local metafun = { } context.metafun = metafun
+
+local mpdrawing = "\\MPdrawing"
+
+local function caller(parent,f,a,...)
+ if not parent then
+ -- skip
+ elseif f then
+ local typ = type(f)
+ if typ == "string" then
+ if a then
+ flush(currentcatcodes,mpdrawing,"{",formatters[f](a,...),"}")
+ else
+ flush(currentcatcodes,mpdrawing,"{",f,"}")
+ end
+ elseif typ == "number" then
+ if a then
+ flush(currentcatcodes,mpdrawing,"{",f,a,...,"}")
+ else
+ flush(currentcatcodes,mpdrawing,"{",f,"}")
+ end
+ elseif typ == "function" then
+ -- ignored: a ...
+ flush(currentcatcodes,mpdrawing,"{\\cldl",store_(f),"}")
+ -- flush(currentcatcodes,mpdrawing,"{",store_(f),"}")
+ elseif typ == "boolean" then
+ -- ignored: a ...
+ if f then
+ flush(currentcatcodes,mpdrawing,"{^^M}")
+ else
+ report_context("warning: %a gets argument 'false' which is currently unsupported","metafun")
+ end
+ else
+ report_context("error: %a gets a weird argument %a","metafun",tostring(f))
+ end
+ end
+end
+
+setmetatable(metafun, { __call = caller } )
+
+function metafun.start()
+ context.resetMPdrawing()
+end
+
+function metafun.stop()
+ context.MPdrawingdonetrue()
+ context.getMPdrawing()
+end
+
+function metafun.color(name)
+ return formatters[ [[\MPcolor{%s}]] ](name)
+end
+
+-- metafun.delayed
+
+local delayed = { } metafun.delayed = delayed
+
+local function indexer(parent,k)
+ local f = function(...)
+ local a = { ... }
+ return function()
+ return metafun[k](unpack(a))
+ end
+ end
+ parent[k] = f
+ return f
+end
+
+
+local function caller(parent,...)
+ local a = { ... }
+ return function()
+ return metafun(unpack(a))
+ end
+end
+
+setmetatable(delayed, { __index = indexer, __call = caller } )
+
+-- helpers:
+
+function context.concat(...)
+ context(concat(...))
+end
+
+local p_texescape = patterns.texescape
+
+function context.escaped(s)
+ return lpegmatch(p_texescape,s) or s
+end
+
+-- templates
+
+local single = lpegP("%")
+local double = lpegP("%%")
+local lquoted = lpegP("%[")
+local rquoted = lpegP("]%")
+
+local start = [[
+local texescape = lpeg.patterns.texescape
+local lpegmatch = lpeg.match
+return function(variables) return
+]]
+
+local stop = [[
+end
+]]
+
+local replacer = lpegP { "parser",
+ parser = lpegCs(lpegCc(start) * lpegV("step") * (lpegCc("..") * lpegV("step"))^0 * lpegCc(stop)),
+ unquoted = (lquoted/'') * ((lpegC((1-rquoted)^1)) / "lpegmatch(texescape,variables['%0'] or '')" ) * (rquoted/''),
+ escape = double/'%%',
+ key = (single/'') * ((lpegC((1-single)^1)) / "(variables['%0'] or '')" ) * (single/''),
+ step = lpegV("unquoted")
+ + lpegV("escape")
+ + lpegV("key")
+ + lpegCc("\n[===[") * (1 - lpegV("unquoted") - lpegV("escape") - lpegV("key"))^1 * lpegCc("]===]\n"),
+}
+
+local templates = { }
+
+local function indexer(parent,k)
+ local v = lpegmatch(replacer,k)
+ if not v then
+ v = "error: no valid template (1)"
+ else
+ v = loadstring(v)
+ if type(v) ~= "function" then
+ v = "error: no valid template (2)"
+ else
+ v = v()
+ if not v then
+ v = "error: no valid template (3)"
+ end
+ end
+ end
+ if type(v) == "function" then
+ local f = function(first,second)
+ if second then
+ pushcatcodes(first)
+ flushlines(v(second))
+ popcatcodes()
+ else
+ flushlines(v(first))
+ end
+ end
+ parent[k] = f
+ return f
+ else
+ return function()
+ flush(v)
+ end
+ end
+
+end
+
+local function caller(parent,k,...)
+ return parent[k](...)
+end
+
+setmetatable(templates, { __index = indexer, __call = caller } )
+
+function context.template(template,...)
+ context(templates[template](...))
+end
+
+context.templates = templates
+
+-- The above is a bit over the top as we could also stick to a simple context.replace
+-- which is fast enough anyway, but the above fits in nicer, also with the catcodes.
+--
+-- local replace = utilities.templates.replace
+--
+-- function context.template(template,variables)
+-- context(replace(template,variables))
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv
new file mode 100644
index 00000000000..a985f204ed6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv
@@ -0,0 +1,56 @@
+%D \module
+%D [ file=cldf-ini,
+%D version=2010.10.19,,
+%D title=\CONTEXT\ \LUA\ Document Functions,
+%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 Lua Documents / Initialization}
+
+\registerctxluafile{cldf-ini}{1.001}
+
+%D With each new update of \MKIV\ we can join Within Temptation in
+%D singing:
+%D
+%D \startbuffer
+%D \startluacode
+%D context("I go faster%s",string.rep(" and faster",6))
+%D \stopluacode
+%D
+%D \cldcontext{"I go faster\letterpercent s",
+%D string.rep(" and faster",6)}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Anyway \unknown\ the following are {\em not} user commands:
+
+% \zerocount removes as it's the default
+
+% \def\cldf#1{\directlua{_cldf_(#1)}} % global (functions)
+% \def\cldn#1{\directlua{_cldn_(#1)}} % global (nodes)
+%
+% \ifx\luafunction\undefined
+% \def\luafunction#1{\directlua{_cldl_(#1)}}
+% \fi
+
+\let\cldl\luafunction
+
+% \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
+
+\normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}}
+ \def\cldloadfile #1{\directlua{context.loadfile("#1")}}
+ \def\cldcontext #1{\directlua{context(#1)}}
+ \def\cldcommand #1{\directlua{context.#1}}
+ % \def\cldverbatim #1{\directlua{context.verbatim.#1}} % maybe make verbatim global
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua
new file mode 100644
index 00000000000..2743e49243b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua
@@ -0,0 +1,222 @@
+if not modules then modules = { } end modules ['cldf-int'] = {
+ version = 1.001,
+ comment = "companion to mult-clm.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- another experiment
+-- needs upgrading
+-- needs checking
+-- todo: multilingual
+
+local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat
+local unpack = unpack or table.unpack
+
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+
+local context = context
+local contextsprint = context.sprint
+
+local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
+
+interfaces = interfaces or { }
+
+_clmh_ = utilities.parsers.settings_to_array
+_clma_ = utilities.parsers.settings_to_array
+
+local starters, stoppers, macros, stack = { }, { }, { }, { }
+
+local checkers = {
+ [0] = "",
+ "\\dosingleempty",
+ "\\dodoubleempty",
+ "\\dotripleempty",
+ "\\doquadrupleempty",
+ "\\doquintupleempty",
+ "\\dosixtupleempty",
+}
+
+function _clmm_(name,...)
+ macros[name](...)
+end
+
+function _clmb_(name,...)
+ local sn = stack[name]
+ insert(sn,{...})
+ starters[name](...)
+end
+
+function _clme_(name)
+ local sn = stack[name]
+ local sv = remove(sn)
+ if sv then
+ stoppers[name](unpack(sv))
+ else
+ -- nesting error
+ end
+end
+
+_clmn_ = tonumber
+
+local estart = interfaces.elements.start
+local estop = interfaces.elements.stop
+
+function interfaces.definecommand(name,specification) -- name is optional
+ if type(name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if name and specification then
+ local arguments = specification.arguments
+ local na = (arguments and #arguments) or 0
+ local environment = specification.environment
+ if na == 0 then
+ if environment then
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}")
+ end
+ else
+ -- we could flush immediate but tracing is bad then
+ stack[name] = { }
+ local opt, done = 0, false
+ local snippets = { } -- we can reuse it
+ local mkivdo = "\\mkivdo" .. name -- maybe clddo
+ snippets[#snippets+1] = "\\def"
+ snippets[#snippets+1] = mkivdo
+ for i=1,na do
+ local a = arguments[i]
+ local variant = a[1]
+ if variant == "option" then
+ snippets[#snippets+1] = "[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]"
+ if not done then
+ opt = opt + 1
+ end
+ else
+ done = true -- no more optional checking after this
+ snippets[#snippets+1] = "#"
+ snippets[#snippets+1] = i
+ end
+ end
+ if environment then
+ snippets[#snippets+1] = "{\\ctxlua{_clmb_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
+ else
+ snippets[#snippets+1] = "{\\ctxlua{_clmm_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
+ end
+ for i=1,na do
+ local a = arguments[i]
+ local variant = a[2]
+ if variant == "list" then
+ snippets[#snippets+1] = ",_clma_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
+ elseif variant == "hash" then
+ snippets[#snippets+1] = ",_clmh_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
+ elseif variant == "number" then
+ snippets[#snippets+1] = ",_clmn_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
+ else
+ snippets[#snippets+1] = ",[[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]]"
+ end
+ end
+ snippets[#snippets+1] = ")}}"
+ contextsprint(ctxcatcodes,unpack(snippets))
+ if environment then
+ -- needs checking
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}")
+ end
+ end
+ if environment then
+ starters[name] = specification.starter
+ stoppers[name] = specification.stopper
+ else
+ macros[name] = specification.macro
+ end
+ end
+end
+
+function interfaces.tolist(t)
+ local r = { }
+ for i=1,#t do
+ r[i] = t[i]
+ end
+ local n = #r
+ for k,v in table.sortedhash(t) do
+ if type(k) ~= "number" then
+ n = n + 1
+ r[n] = k .. "=" .. v
+ end
+ end
+ return concat(r,", ")
+end
+
+--~ \startluacode
+--~ function test(opt_1, opt_2, arg_1)
+--~ context.startnarrower()
+--~ context("options 1: %s",interfaces.tolist(opt_1))
+--~ context.par()
+--~ context("options 2: %s",interfaces.tolist(opt_2))
+--~ context.par()
+--~ context("argument 1: %s",arg_1)
+--~ context.stopnarrower()
+--~ end
+
+--~ interfaces.definecommand {
+--~ name = "test",
+--~ arguments = {
+--~ { "option", "list" },
+--~ { "option", "hash" },
+--~ { "content", "string" },
+--~ },
+--~ macro = test,
+--~ }
+--~ \stopluacode
+
+--~ test: \test[1][a=3]{whatever}
+
+--~ \startluacode
+--~ local function startmore(opt_1)
+--~ context.startnarrower()
+--~ context("start more, options: %s",interfaces.tolist(opt_1))
+--~ context.startnarrower()
+--~ end
+
+--~ local function stopmore(opt_1)
+--~ context.stopnarrower()
+--~ context("stop more, options: %s",interfaces.tolist(opt_1))
+--~ context.stopnarrower()
+--~ end
+
+--~ interfaces.definecommand ( "more", {
+--~ environment = true,
+--~ arguments = {
+--~ { "option", "list" },
+--~ },
+--~ starter = startmore,
+--~ stopper = stopmore,
+--~ } )
+--~ \stopluacode
+
+--~ more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-int.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.mkiv
new file mode 100644
index 00000000000..da684694aee
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.mkiv
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Lua}
+
+\registerctxluafile{cldf-int}{1.001}
+
+\unprotect
+
+% now done directly
+%
+% \unexpanded\def\clmb#1{\unexpanded\expandafter\def\csname\e!start#1\endcsname}
+% \unexpanded\def\clme#1{\unexpanded\expandafter\def\csname\e!stop #1\endcsname}
+% \unexpanded\def\clmm#1{\unexpanded\expandafter\def\csname #1\endcsname}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-prs.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-prs.lua
new file mode 100644
index 00000000000..3c3836a3ee8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-prs.lua
@@ -0,0 +1,72 @@
+if not modules then modules = { } end modules ['cldf-bas'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- used in chem-ini.lua
+
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs
+local format = string.format
+
+local cpatterns = patterns.context or { }
+patterns.context = cpatterns
+
+local utf8character = patterns.utf8character
+local cardinal = patterns.cardinal
+
+local leftbrace = P("{")
+local rightbrace = P("}")
+local backslash = P("\\")
+local csname = backslash * P(1) * (1-backslash-leftbrace)^0 * P(" ")^0
+local sign = P("+") / "\\textplus "
+ + P("-") / "\\textminus "
+local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace }
+local subscript = P("_")
+local superscript = P("^")
+
+-- local scripts = P { "start",
+-- start = V("csname") + V("lowfirst") + V("highfirst"),
+-- csname = csname,
+-- content = Cs(V("csname") + nested + sign^-1 * (cardinal + utf8character)),
+-- lowfirst = subscript * ( Cc("\\lohi{%s}{%s}") * V("content") * superscript + Cc("\\low{%s}" ) ) * V("content") / format,
+-- highfirst = superscript * ( Cc("\\hilo{%s}{%s}") * V("content") * subscript + Cc("\\high{%s}") ) * V("content") / format,
+-- }
+
+-- local scripts = P { "start",
+-- start = (V("csname") + V("lowfirst") + V("highfirst"))^1,
+-- csname = csname,
+-- content = Cs(V("csname") + nested + sign^-1 * (cardinal + utf8character)),
+-- lowfirst = (subscript /"") * ( Cc("\\lohi{") * V("content") * Cc("}{") * (superscript/"") + Cc("\\low{" ) ) * V("content") * Cc("}"),
+-- highfirst = (superscript/"") * ( Cc("\\hilo{") * V("content") * Cc("}{") * (subscript /"") + Cc("\\high{") ) * V("content") * Cc("}"),
+-- }
+
+local scripted = Cs { "start",
+ start = (V("csname") + V("nested") + V("lowfirst") + V("highfirst") + V("character"))^1,
+ rest = V("csname") + V("nested") + V("lowfirst") + V("highfirst"),
+ csname = csname,
+ character = utf8character,
+ -- nested = leftbrace * (V("rest") + (V("character")-rightbrace))^0 * rightbrace,
+ nested = leftbrace * (V("start") -rightbrace)^0 * rightbrace,
+ -- content = Cs(V("nested") + sign^-1 * (cardinal + V("character"))),
+ content = V("nested") + sign^-1 * (cardinal + V("character")) + sign,
+ lowfirst = (subscript /"") * ( Cc("\\lohi{") * V("content") * Cc("}{") * (superscript/"") + Cc("\\low{" ) ) * V("content") * Cc("}"),
+ highfirst = (superscript/"") * ( Cc("\\hilo{") * V("content") * Cc("}{") * (subscript /"") + Cc("\\high{") ) * V("content") * Cc("}"),
+ }
+
+cpatterns.csname = csname
+cpatterns.scripted = scripted
+cpatterns.nested = nested
+
+-- print(lpegmatch(scripted,"10^-3_x"))
+-- print(lpegmatch(scripted,"\\L {C_5}"))
+-- print(lpegmatch(scripted,"\\SL{}"))
+-- print(lpegmatch(scripted,"\\SL{C_5}"))
+-- print(lpegmatch(scripted,"\\SL{C_5}"))
+-- print(lpegmatch(scripted,"{C_5}"))
+-- print(lpegmatch(scripted,"{\\C_5}"))
+-- print(lpegmatch(scripted,"10^-a"))
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua
new file mode 100644
index 00000000000..755d7fed7b3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua
@@ -0,0 +1,165 @@
+if not modules then modules = { } end modules ['cldf-scn'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local load, type = load, type
+
+local formatters = string.formatters
+local char = string.char
+local concat = table.concat
+
+local lpegmatch = lpeg.match
+local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted)
+
+local f_action_f = formatters["action%s(%s)"]
+local f_action_s = formatters["local action%s = action[%s]"]
+local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"]
+
+local interfaces = interfaces
+local commands = commands
+local scanners = interfaces.scanners
+
+local compile = tokens.compile or function() end
+
+local dummy = function() end
+
+local report = logs.reporter("interfaces","implementor")
+
+function interfaces.implement(specification)
+ local actions = specification.actions
+ local name = specification.name
+ local arguments = specification.arguments
+ local private = specification.scope == "private"
+ local onlyonce = specification.onlyonce
+ if not actions then
+ if name then
+ report("error: no actions for %a",name)
+ else
+ report("error: no actions and no name")
+ end
+ return
+ end
+ if name == "" then
+ name = nil
+ end
+ local scanner
+ local resetter = onlyonce and name and commands.ctxresetter(name)
+ if resetter then
+ local scan = compile(specification)
+ if private then
+ scanner = function()
+ resetter()
+ return scan()
+ end
+ else
+ scanner = function()
+ commands[name] = dummy
+ resetter()
+ return scan()
+ end
+ end
+ else
+ scanner = compile(specification)
+ end
+ if not name then
+ return scanner
+ end
+ if scanners[name] and not specification.overload then
+ report("warning: 'scanners.%s' is redefined",name)
+ end
+ scanners[name] = scanner
+ if private then
+ return
+ end
+ local command
+ if onlyonce then
+ if type(actions) == "function" then
+ actions = { actions }
+ elseif #actions == 1 then
+ actions = { actions[1] }
+ end
+ end
+ if type(actions) == "function" then
+ command = actions
+ elseif #actions == 1 then
+ command = actions[1]
+ else
+ -- this one is not yet complete .. compare tokens
+ tokens._action = actions
+ local f = { }
+ local args
+ if not arguments then
+ args = ""
+ elseif type(arguments) == "table" then
+ local a = { }
+ for i=1,#arguments do
+ local v = arguments[i]
+ local t = type(v)
+ if t == "boolean" then
+ a[i] = tostring(v)
+ elseif t == "number" then
+ a[i] = tostring(v)
+ elseif t == "string" then
+ local s = lpegmatch(p_unquoted,v)
+ if s and v ~= s then
+ a[i] = v -- a string, given as "'foo'" or '"foo"'
+ else
+ a[i] = char(96+i)
+ end
+ else
+ -- nothing special for tables
+ a[i] = char(96+i)
+ end
+ end
+ args = concat(a,",")
+ else
+ args = "a"
+ end
+ command = args
+ for i=1,#actions do
+ command = f_action_f(i,command)
+ f[#f+1] = f_action_s(i,i)
+ end
+ command = f_command(f,args,command)
+ command = load(command)
+ if command then
+ if resetter then
+ local cmd = command()
+ command = function()
+ commands[name] = dummy
+ resetter()
+ cmd()
+ end
+ else
+ command = command()
+ end
+ end
+ tokens._action = nil
+ end
+ if commands[name] and not specification.overload then
+ report("warning: 'commands.%s' is redefined",name)
+ end
+ commands[name] = command
+ -- return scanner, command
+end
+
+-- it's convenient to have copies here:
+
+interfaces.defined = tokens.defined
+
+interfaces.setmacro = tokens.setters.macro
+interfaces.setcount = tokens.setters.count
+interfaces.setdimen = tokens.setters.dimen
+
+interfaces.strings = table.setmetatableindex(function(t,k)
+ local v = { }
+ for i=1,k do
+ v[i] = "string"
+ end
+ t[k] = v
+ return v
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-stp.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-stp.lua
new file mode 100644
index 00000000000..7b5225dd353
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-stp.lua
@@ -0,0 +1,69 @@
+if not modules then modules = { } end modules ['cldf-stp'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- limitation: input levels
+
+-- context.stepwise (function()
+-- ...
+-- context.step(nil|...)
+-- ...
+-- context.step(nil|...)
+-- ...
+-- context.stepwise (function()
+-- ...
+-- context.step(nil|...)
+-- ...
+-- context.step(nil|...)
+-- ...
+-- end)
+-- ...
+-- context.step(nil|...)
+-- ...
+-- context.step(nil|...)
+-- ...
+-- end)
+
+local create = coroutine.create
+local yield = coroutine.yield
+local resume = coroutine.resume
+local status = coroutine.status
+
+local stepper = nil
+local stack = { } -- will never be deep so no gc needed
+local depth = 0
+
+local nextstep = function()
+ if status(stepper) == "dead" then
+ stepper = stack[depth]
+ depth = depth - 1
+ stack[depth] = false
+ end
+ resume(stepper)
+end
+
+interfaces.implement {
+ name = "step",
+ actions = nextstep,
+}
+
+local cldresume = context.constructcsonly("clf_step")
+
+function context.step(first,...)
+ if first ~= nil then
+ context(first,...)
+ end
+ cldresume()
+ yield()
+end
+
+function context.stepwise(f)
+ depth = depth + 1
+ stack[depth] = stepper
+ stepper = create(f)
+ resume(stepper)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua
new file mode 100644
index 00000000000..66432eb1c8c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua
@@ -0,0 +1,77 @@
+if not modules then modules = { } end modules ['cldf-ver'] = {
+ version = 1.001,
+ comment = "companion to cldf-ver.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We have better verbatim: context.verbatim so that needs to be looked
+-- into. We can also directly store in buffers although this variant works
+-- better when used mixed with other code (synchronization issue).
+
+local concat, tohandle = table.concat, table.tohandle
+local find, splitlines = string.find, string.splitlines
+local tostring, type = tostring, type
+
+local context = context
+
+local function flush(...)
+ context(concat{...,"\r"}) -- was \n
+end
+
+local function t_tocontext(...)
+ context.starttyping { "typing" } -- else [1] is intercepted
+ context.pushcatcodes("verbatim")
+ tohandle(flush,...) -- ok?
+ context.stoptyping()
+ context.popcatcodes()
+end
+
+local function s_tocontext(...) -- we need to catch {\}
+ context.type()
+ context("{")
+ context.pushcatcodes("verbatim")
+ context(concat({...}," "))
+ context.popcatcodes()
+ context("}")
+end
+
+local function b_tocontext(b)
+ s_tocontext(tostring(b))
+end
+
+table .tocontext = t_tocontext
+string .tocontext = s_tocontext
+boolean.tocontext = b_tocontext
+
+function context.tocontext(first,...)
+ local t = type(first)
+ if t == "string" then
+ s_tocontext(first,...)
+ elseif t == "table" then
+ t_tocontext(first,...)
+ elseif t == "boolean" then
+ b_tocontext(first,...)
+ end
+end
+
+-- function context.tobuffer(name,str)
+-- context.startbuffer { name }
+-- context.pushcatcodes("verbatim")
+-- local lines = (type(str) == "string" and find(str,"[\n\r]") and splitlines(str)) or str
+-- for i=1,#lines do
+-- context(lines[i] .. " ")
+-- end
+-- context.stopbuffer()
+-- context.popcatcodes()
+-- end
+
+context.tobuffer = buffers.assign -- (name,str,catcodes)
+
+function context.tolines(str)
+ local lines = type(str) == "string" and splitlines(str) or str
+ for i=1,#lines do
+ context(lines[i] .. " ")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.mkiv
new file mode 100644
index 00000000000..8e009035d2d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=cldf-com,
+%D version=2010.10.19,
+%D title=\CONTEXT\ \LUA\ Document Functions,
+%D subtitle=Verbatim,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Lua Documents / Verbatim}
+
+\registerctxluafile{cldf-ver}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-ext.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-ext.mkiv
new file mode 100644
index 00000000000..74ce2d3e5d4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-ext.mkiv
@@ -0,0 +1,100 @@
+%D \module
+%D [ file=colo-ext, % mostof thsi code used to be in colo-ini.tex
+%D version=1997.04.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Extras,
+%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 Color Macros / Extras}
+
+\unprotect
+
+%D \macros
+%D {negatecolorcomponent, negativecolorbox}
+%D
+%D Sometimes, especially when we deal with typesetting
+%D devices, we want to reverse the color scheme. Instead of
+%D recalculating all those colors, we use a quick and dirty
+%D approach:
+%D
+%D \starttyping
+%D \negativecolorbox0
+%D \stoptyping
+%D
+%D will negate the colors in box zero.
+
+\unexpanded\def\negatecolorbox#1% or just set attr of #1
+ {\setbox#1\hpack to \wd#1%
+ {\scratchdimen\wd#1\relax
+ \startnegative % might change
+ \blackrule[\c!color=\s!white,\c!height=\ht#1,\c!depth=\dp#1,\c!width=\scratchdimen]%
+ \hskip-\scratchdimen
+ \leaders\box#1\hfill% this triggers application to the box .. a real dirty hack!
+ \stopnegative}}
+
+%D There are in principle two ways to handle overprint: bound to colors
+%D or independent. For the moment we only support independent overprint
+%D handling. Here we deal with a per-document setting.
+
+%D We can move the stack and attribute setting to the \LUA\ end.
+
+\installcorenamespace{colorintent}
+
+\unexpanded\def\registercolorintent#1#2%
+ {\setevalue{\??colorintent#1}{\attribute\colorintentattribute\clf_registercolorintent{#2}}}
+
+\unexpanded\def\colo_intents_set
+ {\clf_enablecolorintents
+ \unexpanded\gdef\colo_intents_set##1{\csname\??colorintent##1\endcsname}%
+ \colo_intents_set}
+
+\registercolorintent{knockout} {knockout}
+\registercolorintent{overprint}{overprint}
+
+\installattributestack\colorintentattribute
+
+\setevalue{\??colorintent\v!none}{\attribute\colorintentattribute\attributeunsetvalue} % or reset? used at all?
+
+\unexpanded\def\startcolorintent[#1]%
+ {\pushattribute\colorintentattribute
+ \colo_intents_set{#1}}
+
+\unexpanded\def\stopcolorintent
+ {\popattribute\colorintentattribute}
+
+\unexpanded\def\startoverprint{\startcolorintent[\v!overprint]}
+\unexpanded\def\startknockout {\startcolorintent[\v!knockout ]}
+
+\let\stopoverprint\stopcolorintent
+\let\stopknockout \stopcolorintent
+
+\let\starttextcolorintent\relax
+\let\stoptextcolorintent \relax
+
+\appendtoks
+ \colo_intents_set_text
+\to \everysetupcolors
+
+\let\p_colo_intent\empty
+
+\def\colo_intents_set_text
+ {\edef\p_colo_intent{\colorsparameter\c!intent}%
+ \ifx\p_colo_intent\v!none \else
+ \unexpanded\xdef\starttextcolorintent{\colo_intents_set{\p_colo_intent}}%
+ \glet\colo_intents_set_text\relax
+ \colo_intents_set\p_colo_intent
+ \fi}
+
+\appendtoks \starttextcolorintent \to \everystarttextproperties
+\appendtoks \stoptextcolorintent \to \everystoptextproperties
+
+\setupcolors
+ [\c!intent=\v!none]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-grp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-grp.mkiv
new file mode 100644
index 00000000000..e296bbc33d9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-grp.mkiv
@@ -0,0 +1,168 @@
+%D \module
+%D [ file=colo-grp,
+%D version=2011.12.27, % moved from colo-ini
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Groups,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Regular colors and palets are used most, contrary to groups
+%D which is why we define their support in a separate module.
+
+\writestatus{loading}{ConTeXt Color Macros / Groups}
+
+\unprotect
+
+%D \macros
+%D {definecolorgroup}
+%D
+%D The naming of the colors in this palet suggests some
+%D ordening, which in turn is suported by color grouping.
+%D
+%D \starttyping
+%D \definecolorgroup
+%D [red]
+%D [1.00:0.90:0.90,
+%D 1.00:0.80:0.80,
+%D 1.00:0.70:0.70,
+%D 1.00:0.55:0.55,
+%D 1.00:0.40:0.40,
+%D 1.00:0.25:0.25,
+%D 1.00:0.15:0.15,
+%D 0.90:0.00:0.00]
+%D \stoptyping
+%D
+%D In such a color group colors are numbered from~$1$ to~$n$.
+%D
+%D \showsetup{definecolorgroup}
+%D
+%D This kind of specification is not only more compact than
+%D defining each color separate, it also loads faster and takes
+%D less bytes.
+
+\installcorenamespace{colorgroup}
+\installcorenamespace{colorgroupsetter}
+
+\newcount\c_colo_groups_n % scratch counter
+
+\unexpanded\def\definecolorgroup % sort of obsolete, just use palets directly
+ {\dotripleempty\colo_groups_define}
+
+\def\colo_groups_define
+ {\ifthirdargument
+ \expandafter\colo_groups_define_normal
+ \else
+ \expandafter\colo_groups_define_checked
+ \fi}
+
+\def\colo_groups_define_normal[#1][#2][#3]%
+ {\c_colo_groups_n\zerocount
+ \processcommalist[#3]{\colo_groups_define_entry{#1}{#2}}}
+
+\def\colo_groups_define_checked[#1][#2][#3]%
+ {\doifelseinstring{:}{#2}
+ {\colo_groups_define_normal[#1][\v!rgb][#2]}
+ {\doloop % inherited
+ {\ifcsname\??colorgroup#2:\recurselevel\endcsname
+ \setevalue{\??colorgroup#1:\recurselevel}{\csname\??colorgroup#2:\recurselevel\endcsname}%
+ \else
+ \exitloop
+ \fi}}}
+
+\def\colo_groups_define_entry#1#2#3% name mode specification
+ {\advance\c_colo_groups_n\plusone
+ \csname\??colorgroupsetter\ifcsname\??colorgroupsetter#2\endcsname#2\else\s!rgb\fi\endcsname[#1:\the\c_colo_groups_n][#3:0:0:0:0]}
+
+\setvalue{\??colorgroupsetter\s!gray}[#1][#2:#3]{\definecolor[#1][s=#2]}
+\setvalue{\??colorgroupsetter\s!rgb }[#1][#2:#3:#4:#5]{\definecolor[#1][r=#2,g=#3,b=#4]}
+\setvalue{\??colorgroupsetter\s!cmyk}[#1][#2:#3:#4:#5:#6]{\definecolor[#1][c=#2,m=#3=,y=#4,k=#5]}
+\setvalue{\??colorgroupsetter\s!spot}[#1][#2:#3:#4]{\definespotcolor[#1][#2][p=#3]}
+
+%D \macros
+%D {showcolorgroup}
+%D
+%D We can show the group by:
+%D
+%D \startbuffer
+%D \showcolorgroup [blue] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or in color:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D which uses:
+%D
+%D \showsetup{showcolorgroup}
+
+\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}
+
+%D There are ten predefined color groups, like
+%D \color[green]{\em groen}, \color[red]{\em rood},
+%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
+%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\hss
+%D \showcolorgroup [red] [vertical,name,number]\hss
+%D \showcolorgroup [green] [vertical,name]\hss
+%D \showcolorgroup [blue] [vertical,name]\hss
+%D \showcolorgroup [cyan] [vertical,name]\hss
+%D \showcolorgroup [magenta][vertical,name]\hss
+%D \showcolorgroup [yellow] [vertical,name]\hss}
+%D \stoplinecorrection
+%D
+%D These groups are used to define palets {\em alfa} upto {\em
+%D zeta}. As long as we don't use colors from the same row, we
+%D get ourselves distinctive palets. By activating such a palet
+%D one gains access to its members {\em top} to {\em charm} (of
+%D course one should use more suitable names than these).
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\showpalet [alfa] [vertical,name,number]\hss
+%D \showpalet [beta] [vertical,name]\hss
+%D \showpalet [gamma] [vertical,name]\hss
+%D \showpalet [delta] [vertical,name]\hss
+%D \showpalet [epsilon] [vertical,name]\hss
+%D \showpalet [zeta] [vertical,name]}
+%D \stoplinecorrection
+%D
+%D By using the keyword \type {value} the individual color
+%D components are shown too. When printed in color, these
+%D showcases show both the colors and the gray value.
+
+%D \macros
+%D {comparecolorgroup}
+%D
+%D The similar command:
+%D
+%D \startbuffer
+%D \comparecolorgroup [blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows color groups:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D this commands are defined as:
+%D
+%D \showsetup{comparecolorgroup}
+
+\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-icc.lua b/Master/texmf-dist/tex/context/base/mkiv/colo-icc.lua
new file mode 100644
index 00000000000..f7ed561c1bf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-icc.lua
@@ -0,0 +1,120 @@
+if not modules then modules = { } end modules ['colo-icc'] = {
+ version = 1.000,
+ comment = "companion to colo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local char, byte, gsub, match, format, strip = string.char, string.byte, string.gsub, string.match, string.format, string.strip
+local readstring, readnumber = io.readstring, io.readnumber
+local formatters = string.formatters
+
+local colors = attributes and attributes.colors or { } -- when used in mtxrun
+
+local report_colors = logs.reporter("colors","icc")
+
+local R, Cs, lpegmatch = lpeg.R, lpeg.Cs, lpeg.match
+
+local invalid = R(char(0)..char(31))
+local cleaned = invalid^0 * Cs((1-invalid)^0)
+
+function colors.iccprofile(filename,verbose)
+ local fullname = resolvers.findfile(filename,"icc") or ""
+ if fullname == "" then
+ local locate = resolvers.finders.byscheme -- not in mtxrun
+ if locate then
+ fullname = locate("loc",filename)
+ end
+ end
+ if fullname == "" then
+ report_colors("profile %a cannot be found",filename)
+ return nil, false
+ end
+ local f = io.open(fullname,"rb")
+ if not f then
+ report_colors("profile %a cannot be loaded",fullname)
+ return nil, false
+ end
+ local header = {
+ size = readnumber(f,4),
+ cmmtype = readnumber(f,4),
+ version = readnumber(f,4),
+ deviceclass = strip(readstring(f,4)),
+ colorspace = strip(readstring(f,4)),
+ connectionspace = strip(readstring(f,4)),
+ datetime = {
+ year = readnumber(f,2),
+ month = readnumber(f,2),
+ day = readnumber(f,2),
+ hour = readnumber(f,2),
+ minutes = readnumber(f,2),
+ seconds = readnumber(f,2),
+ },
+ filesignature = strip(readstring(f,4)),
+ platformsignature = strip(readstring(f,4)),
+ options = readnumber(f,4),
+ devicemanufacturer = strip(readstring(f,4)),
+ devicemodel = strip(readstring(f,4)),
+ deviceattributes = readnumber(f,4),
+ renderingintent = readnumber(f,4),
+ illuminantxyz = {
+ x = readnumber(f,4),
+ y = readnumber(f,4),
+ z = readnumber(f,4),
+ },
+ profilecreator = readnumber(f,4),
+ id = strip(readstring(f,16)),
+ }
+ local tags = { }
+ for i=1,readnumber(f,128,4) do
+ tags[readstring(f,4)] = {
+ offset = readnumber(f,4),
+ length = readnumber(f,4),
+ }
+ end
+ local o = header.options
+ header.options =
+ o == 0 and "embedded" or
+ o == 1 and "dependent" or "unknown"
+ local d = header.deviceattributes
+ header.deviceattributes = {
+ [number.hasbit(d,1) and "transparency" or "reflective"] = true,
+ [number.hasbit(d,2) and "mate" or "glossy" ] = true,
+ [number.hasbit(d,3) and "negative" or "positive" ] = true,
+ [number.hasbit(d,4) and "bw" or "color" ] = true,
+ }
+ local r = header.renderingintent
+ header.renderingintent =
+ r == 0 and "perceptual" or
+ r == 1 and "relative" or
+ r == 2 and "saturation" or
+ r == 3 and "absolute" or "unknown"
+ for tag, spec in next, tags do
+ if tag then
+ local offset, length = spec.offset, spec.length
+ local variant = readstring(f,offset,4)
+ if variant == "text" or variant == "desc" then
+ local str = readstring(f,length-4)
+ tags[tag] = {
+ data = str,
+ cleaned = lpegmatch(cleaned,str),
+ }
+ else
+ if verbose then
+ report_colors("ignoring tag %a or type %a in profile %a",tag,variant,fullname)
+ end
+ tags[tag] = nil
+ end
+ end
+ end
+ f:close()
+ local profile = {
+ filename = filename,
+ fullname = fullname,
+ header = header,
+ tags = tags,
+ }
+ report_colors("profile %a loaded",fullname)
+ return profile, true
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv
new file mode 100644
index 00000000000..dbae02d5a2a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv
@@ -0,0 +1,254 @@
+%D \module
+%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
+%C details.
+
+%D Crayola (Binney & Smith) crayon colors.
+
+\startprotectedcolors
+
+\definecolor [Red] [h=ED0A3F] % produced 1903–present
+\definecolor [Maroon] [h=C32148] % produced 1949–present, known as "dark red", 1949–1958.
+\definecolor [Scarlet] [h=FD0E35] % produced 1998–present, known as "torch red", 1998.
+\definecolor [BrickRed] [h=C62D42] % produced 1958–present
+\definecolor [EnglishVermilion] [h=CC474B] % also spelled "vermillion", produced 1903–1935.
+\definecolor [MadderLake] [h=CC3336] % produced 1903–1935
+\definecolor [PermanentGeraniumLake] [h=E12C2C] % produced 1903–circa 1910
+\definecolor [MaximumRed] [h=D92121] % part of the munsell line, 1926–1944
+\definecolor [IndianRed] [h=B94E48] % produced 1903–present, known as "chestnut" since 1999.
+\definecolor [OrangeRed] [h=FF5349] % produced 1958–1990
+\definecolor [SunsetOrange] [h=FE4C40] % produced 1997–present
+\definecolor [Bittersweet] [h=FE6F5E] % produced 1958–present
+\definecolor [DarkVenetianRed] [h=B33B24] % "venetian red, dark" on labels, produced 1903–circa 1910.
+\definecolor [VenetianRed] [h=CC553D] % produced 1903–1944
+\definecolor [LightVenetianRed] [h=E6735C] % "venetian red, light" on labels, produced 1903–circa 1910.
+\definecolor [VividTangerine] [h=FF9980] % produced 1990–present
+\definecolor [MiddleRed] [h=E58E73] % part of the munsell line, 1926–1944.
+\definecolor [BurntOrange] [h=FF7F49] % produced 1958–present
+\definecolor [RedOrange] [h=FF681F] % produced 1930–present
+\definecolor [Orange] [h=FF8833] % produced 1903–present
+\definecolor [MacaroniandCheese] [h=FFB97B] % produced 1993–present, also found as "macaroni & cheese" and "macaroni-n-cheese".
+\definecolor [MiddleYellowRed] [h=ECB176] % part of the munsell line, 1926–1944, same color as "medium orange" (1949–1958).
+\definecolor [MangoTango] [h=E77200] % produced 2003–present
+\definecolor [YellowOrange] [h=FFAE42] % produced 1930–present
+\definecolor [MaximumYellowRed] [h=F2BA49] % part of the munsell line, 1926–1944.
+\definecolor [BananaMania] [h=FBE7B2] % produced 1998–present
+\definecolor [Maize] [h=F2C649] % produced 1903–1990, known as "gold ochre", 1903–1958, "golden ochre" on some labels.
+\definecolor [OrangeYellow] [h=F8D568] % produced 1958–1990.
+\definecolor [Goldenrod] [h=FCD667] % produced 1903–present, known as "medium chrome yellow" (1903–?) and "medium yellow" (1903–1958).
+\definecolor [Dandelion] [h=FED85D] % produced 1990–present
+\definecolor [Yellow] [h=FBE870] % produced 1903–present
+\definecolor [GreenYellow] [h=F1E788] % produced 1958–present
+\definecolor [MiddleYellow] [h=FFEB00] % part of the munsell line, 1926–1944.
+\definecolor [OliveGreen] [h=B5B35C] % produced 1903–present
+\definecolor [SpringGreen] [h=ECEBBD] % produced 1958–present
+\definecolor [MaximumYellow] [h=FAFA37] % part of the munsell line, 1926–1944.
+\definecolor [Canary] [h=FFFF99] % produced 1998–present
+\definecolor [LemonYellow] [h=FFFF9F] % produced 1903–1990, also known as "light chrome yellow" (on labels "chrome yellow, light") or "light yellow", 1903–1958, on labels "chrome yellow, light."
+\definecolor [MaximumGreenYellow] [h=D9E650] % part of the munsell line, 1926–1944.
+\definecolor [MiddleGreenYellow] [h=ACBF60] % part of the munsell line, 1926–1944.
+\definecolor [Inchworm] [h=AFE313] % produced 1993–present
+\definecolor [LightChromeGreen] [h=BEE64B] % "chrome green, light" on labels, produced 1903–1935, same color as "light green" (1903–1935).
+\definecolor [YellowGreen] [h=C5E17A] % produced 1930–present
+\definecolor [MaximumGreen] [h=5E8C31] % part of the munsell line, 1926–1944.
+\definecolor [Asparagus] [h=7BA05B] % produced 1993–present
+\definecolor [GrannySmithApple] [h=9DE093] % produced 1993–present
+\definecolor [Fern] [h=63B76C] % produced 1998–present
+\definecolor [MiddleGreen] [h=4D8C57] % part of the munsell line, 1926–1944.
+\definecolor [Green] [h=3AA655] % produced 1903–present
+\definecolor [MediumChromeGreen] [h=6CA67C] % "chrome green, medium" on labels, produced 1903–1939, same color as "medium green" (1903–1939).
+\definecolor [ForestGreen] [h=5FA777] % produced 1949–present, known as "dark green", 1949–1958.
+\definecolor [SeaGreen] [h=93DFB8] % produced 1949–present, known as "light green", 1949–1958.
+\definecolor [Shamrock] [h=33CC99] % produced 1993–present
+\definecolor [MountainMeadow] [h=1AB385] % produced 1998–present
+\definecolor [JungleGreen] [h=29AB87] % produced 1990–present
+\definecolor [CaribbeanGreen] [h=00CC99] % produced 1997–present
+\definecolor [TropicalRainForest] [h=00755E] % produced 1993–present
+\definecolor [MiddleBlueGreen] [h=8DD9CC] % part of the munsell line, 1926–1944.
+\definecolor [PineGreen] [h=01786F] % produced 1903–1949, 1958–present, known as "dark chrome green" ("chrome green, dark" on labels) or "dark green", 1903–1949.
+\definecolor [MaximumBlueGreen] [h=30BFBF] % part of the munsell line, 1926–1944.
+\definecolor [RobinsEggBlue] [h=00CCCC] % produced 1993–present
+\definecolor [TealBlue] [h=008080] % produced 1990–2003.
+\definecolor [LightBlue] [h=8FD8D8] % produced only in 1958.
+\definecolor [Aquamarine] [h=95E0E8] % produced 1949–present, known as "light turquoise blue", 1949–1958.
+\definecolor [TurquoiseBlue] [h=6CDAE7] % produced 1935–present, available only in bulk, 1935–1949.
+\definecolor [OuterSpace] [h=2D383A] % produced 1998–present
+\definecolor [SkyBlue] [h=76D7EA] % produced 1958–present
+\definecolor [MiddleBlue] [h=7ED4E6] % part of the munsell line, 1926–1944.
+\definecolor [BlueGreen] [h=0095B7] % produced 1949–present, known as "middle blue-green", 1949–1958.
+\definecolor [PacificBlue] [h=009DC4] % produced 1993–present
+\definecolor [Cerulean] [h=02A4D3] % produced 1990–present
+\definecolor [MaximumBlue] [h=47ABCC] % produced 1926–1958, part of the munsell line, 1926–1944, also known as "blue-green", 1930–1958.
+\definecolor [BlueI] [h=4997D0] % produced 1903–1958, known as "celestial blue", 1935–1949, and "azure blue", 1949–1958.
+\definecolor [CeruleanBlue] [h=339ACC] % produced 1949–1958.
+\definecolor [Cornflower] [h=93CCEA] % produced 1958–present
+\definecolor [GreenBlue] [h=2887C8] % produced 1958–1990.
+\definecolor [MidnightBlue] [h=00468C] % produced 1903–present, known as "prussian blue", 1903–1958.
+\definecolor [NavyBlue] [h=0066CC] % produced 1958–present
+\definecolor [Denim] [h=1560BD] % produced 1993–present
+\definecolor [BlueIII] [h=0066FF] % produced 1949–present
+\definecolor [CadetBlue] [h=A9B2C3] % produced 1958–present
+\definecolor [Periwinkle] [h=C3CDE6] % produced 1958–present
+\definecolor [BlueII] [h=4570E6] % produced 1935–1958, known as "medium blue", 1949–1958.
+\definecolor [WildBlueYonder] [h=7A89B8] % produced 2003–present
+\definecolor [Indigo] [h=4F69C6] % produced 1999–present
+\definecolor [Manatee] [h=8D90A1] % produced 1998–present
+\definecolor [CobaltBlue] [h=8C90C8] % produced 1903–1958.
+\definecolor [CelestialBlue] [h=7070CC] % produced 1903–circa 1910.
+\definecolor [BlueBell] [h=9999CC] % produced 1998–present
+\definecolor [MaximumBluePurple] [h=ACACE6] % part of the munsell line, 1926–1944.
+\definecolor [VioletBlue] [h=766EC8] % produced 1930–1990, known as blue-violet, 1930–1958.
+\definecolor [BlueViolet] [h=6456B7] % produced 1949–present, known as "violet" 1949–1958.
+\definecolor [UltramarineBlue] [h=3F26BF] % produced 1903–1944.
+\definecolor [MiddleBluePurple] [h=8B72BE] % part of the munsell line, 1926–1944.
+\definecolor [PurpleHeart] [h=652DC1] % produced 1998–present
+\definecolor [RoyalPurple] [h=6B3FA0] % produced 1990–present
+\definecolor [VioletII] [h=8359A3] % produced 1930–1949, 1958–present, on labels "violet (purple)".
+\definecolor [MediumViolet] [h=8F47B3] % produced 1949–1958.
+\definecolor [Wisteria] [h=C9A0DC] % produced 1993–present
+\definecolor [LavenderI] [h=BF8FCC] % produced 1949–1958.
+\definecolor [VividViolet] [h=803790] % produced 1997–present
+\definecolor [MaximumPurple] [h=733380] % part of the munsell line, 1926–1944.
+\definecolor [PurpleMountainsMajesty] [h=D6AEDD] % produced 1993–present, also found as "purple mountain majesty" and "purple mountain's majesty."
+\definecolor [Fuchsia] [h=C154C1] % produced 1990–present
+\definecolor [PinkFlamingo] [h=FC74FD] % produced 1997–present
+\definecolor [VioletI] [h=732E6C] % produced 1903–1930, also known as "purple" (1903–circa 1914).
+\definecolor [BrilliantRose] [h=E667CE] % produced 1949–1958.
+\definecolor [Orchid] [h=E29CD2] % produced 1949–present, known as "medium red-violet", 1949–1958.
+\definecolor [Plum] [h=8E3179] % produced 1958–present
+\definecolor [MediumRose] [h=D96CBE] % produced 1949–1958.
+\definecolor [Thistle] [h=EBB0D7] % produced 1949–1999, known as "light magenta", 1949–1958.
+\definecolor [Mulberry] [h=C8509B] % produced 1958–2003.
+\definecolor [RedViolet] [h=BB3385] % produced 1930–present
+\definecolor [MiddlePurple] [h=D982B5] % part of the munsell line, 1926–1944.
+\definecolor [MaximumRedPurple] [h=A63A79] % part of the munsell line, 1926–1944.
+\definecolor [JazzberryJam] [h=A50B5E] % produced 2003–present
+\definecolor [Eggplant] [h=614051] % produced 1998–present
+\definecolor [Magenta] [h=F653A6] % produced 1903–present, same color as "permanent magenta" (1903–?).
+\definecolor [Cerise] [h=DA3287] % produced 1993–present
+\definecolor [WildStrawberry] [h=FF3399] % produced 1990–present
+\definecolor [LavenderII] [h=FBAED2] % produced 1958–present
+\definecolor [CottonCandy] [h=FFB7D5] % produced 1998–present
+\definecolor [CarnationPink] [h=FFA6C9] % produced 1903–present, known as "rose pink" (1903–1958) and "pink" (1903–1917).
+\definecolor [VioletRed] [h=F7468A] % produced 1958–present
+\definecolor [Razzmatazz] [h=E30B5C] % produced 1993–present
+\definecolor [PigPink] [h=FDD7E4] % produced 1998–present, also called "piggy pink."
+\definecolor [Carmine] [h=E62E6B] % produced 1935–1958, known as "carmine red", 1949–1958.
+\definecolor [Blush] [h=DB5079] % produced 1998–present, known as "cranberry", 1998–2005.
+\definecolor [TickleMePink] [h=FC80A5] % produced 1993–present
+\definecolor [Mauvelous] [h=F091A9] % produced 1993–present
+\definecolor [Salmon] [h=FF91A4] % produced 1949–present
+\definecolor [MiddleRedPurple] [h=A55353] % part of the munsell line, 1926–1944.
+\definecolor [Mahogany] [h=CA3435] % produced 1949–present
+\definecolor [Melon] [h=FEBAAD] % produced 1958–present
+\definecolor [PinkSherbert] [h=F7A38E] % produced 1998–present, known as "brink pink", 1998–2005.
+\definecolor [BurntSienna] [h=E97451] % produced 1903–present
+\definecolor [Brown] [h=AF593E] % produced 1935–present
+\definecolor [Sepia] [h=9E5B40] % produced 1935–1944, 1958–present, available only in bulk, 1935–1939.
+\definecolor [FuzzyWuzzy] [h=87421F] % produced 1998–present, known as "fuzzy wuzzy brown", 1998–2005.
+\definecolor [Beaver] [h=926F5B] % produced 1998–present
+\definecolor [Tumbleweed] [h=DEA681] % produced 1993–present
+\definecolor [RawSienna] [h=D27D46] % produced 1958–present
+\definecolor [VanDykeBrown] [h=664228] % produced 1903–1935, same color as "brown" (1903–1935)
+\definecolor [Tan] [h=D99A6C] % produced 1958–present
+\definecolor [DesertSand] [h=EDC9AF] % produced 1998–present
+\definecolor [Peach] [h=FFCBA4] % produced 1903–present, known as "flesh tint" (1903–1949), "flesh" (1949–1956, 1958–1962), and "pink beige" (1956–1958)
+\definecolor [BurntUmber] [h=805533] % produced 1903–1944
+\definecolor [Apricot] [h=FDD5B1] % produced 1958–present
+\definecolor [Almond] [h=EED9C4] % produced 1998–present
+\definecolor [RawUmber] [h=665233] % produced 1903–1990
+\definecolor [Shadow] [h=837050] % produced 1998–present
+\definecolor [RawSiennaI] [h=E6BC5C] % produced 1903–circa 1910
+\definecolor [Timberwolf] [h=D9D6CF] % produced 1993–present
+\definecolor [GoldI] [h=92926E] % metallic, swatch represents nominal hue only, produced 1903–1944, available only in bulk after 1915
+\definecolor [GoldII] [h=E6BE8A] % metallic, swatch represents nominal hue only, produced 1953–present, available only in bulk, 1953–1956
+\definecolor [Silver] [h=C9C0BB] % metallic, swatch represents nominal hue only, produced 1903–present, available only in bulk, 1915–1944
+\definecolor [Copper] [h=DA8A67] % metallic, swatch represents nominal hue only, produced 1903–1915, 1958–present
+\definecolor [AntiqueBrass] [h=C88A65] % metallic, swatch represents nominal hue only, produced 1998–present
+\definecolor [Black] [h=000000] % produced 1903–present
+\definecolor [CharcoalGray] [h=736A62] % produced 1903–1910
+\definecolor [Gray] [h=8B8680] % as "middle grey", part of the munsell line, 1926–1944, spelled "grey" on labels, but "gray" on boxes, also called "neutral grey", 1930–1956
+\definecolor [BlueGray] [h=C8C8CD] % produced 1958–1990
+\definecolor [White] [h=FFFFFF] % produced 1903–present
+\definecolor [RadicalRed] [h=FF355E] % introduced in 1990
+\definecolor [WildWatermelon] [h=FD5B78] % same color as "ultra red" (1972–1990)
+\definecolor [OutrageousOrange] [h=FF6037] % same color as "ultra orange" (1972–1990)
+\definecolor [AtomicTangerine] [h=FF9966] % same color as "ultra yellow" (1972–1990)
+\definecolor [NeonCarrot] [h=FF9933] % introduced in 1990
+\definecolor [Sunglow] [h=FFCC33] % introduced in 1990
+\definecolor [LaserLemon] [h=FFFF66] % same color as "chartreuse" (1972–1990)
+\definecolor [UnmellowYellow] [h=FFFF66] % introduced in 1990
+\definecolor [ElectricLime] [h=CCFF00] % introduced in 1990
+\definecolor [ScreaminGreen] [h=66FF66] % same color as "ultra green" (1972–1990)
+\definecolor [MagicMint] [h=AAF0D1] % produced 1990–2003
+\definecolor [BlizzardBlue] [h=50BFE6] % same color as "ultra blue" (1972–1990), discontinued in 2003
+\definecolor [ShockingPink] [h=FF6EFF] % same color as "ultra pink" (1972–1990)
+\definecolor [RazzleDazzleRose] [h=EE34D2] % same color as "hot magenta" (1972–1990)
+\definecolor [HotMagenta] [h=FF00CC] % introduced in 1990
+\definecolor [PurplePizzazz] [h=FF00CC] % introduced in 1990
+\definecolor [AztecGold] [h=C39953]
+\definecolor [BurnishedBrown] [h=A17A74]
+\definecolor [CeruleanFrost] [h=6D9BC3]
+\definecolor [CinnamonSatin] [h=CD607E]
+\definecolor [CopperPenny] [h=AD6F69]
+\definecolor [CosmicCobalt] [h=2E2D88]
+\definecolor [GlossyGrape] [h=AB92B3]
+\definecolor [GraniteGray] [h=676767]
+\definecolor [GreenSheen] [h=6EAEA1]
+\definecolor [LilacLuster] [h=AE98AA]
+\definecolor [MistyMoss] [h=BBB477]
+\definecolor [MysticMaroon] [h=AD4379]
+\definecolor [PearlyPurple] [h=B768A2]
+\definecolor [PewterBlue] [h=8BA8B7]
+\definecolor [PolishedPine] [h=5DA493]
+\definecolor [QuickSilver] [h=A6A6A6]
+\definecolor [RoseDust] [h=9E5E6F]
+\definecolor [RustyRed] [h=DA2C43]
+\definecolor [ShadowBlue] [h=778BA5]
+\definecolor [ShinyShamrock] [h=5FA778]
+\definecolor [SteelTeal] [h=5F8A8B]
+\definecolor [SugarPlum] [h=914E75]
+\definecolor [TwilightLavender] [h=8A496B]
+\definecolor [WintergreenDream] [h=56887D]
+\definecolor [Amethyst] [h=64609A]
+\definecolor [Citrine] [h=933709]
+\definecolor [Emerald] [h=14A989]
+\definecolor [Jade] [h=469A84]
+\definecolor [Jasper] [h=D05340]
+\definecolor [LapisLazuli] [h=436CB9]
+\definecolor [Malachite] [h=469496]
+\definecolor [Moonstone] [h=3AA8C1]
+\definecolor [Onyx] [h=353839]
+\definecolor [Peridot] [h=ABAD48]
+\definecolor [PinkPearl] [h=B07080]
+\definecolor [RoseQuartz] [h=BD559C]
+\definecolor [Ruby] [h=AA4069]
+\definecolor [Sapphire] [h=2D5DA1]
+\definecolor [SmokeyTopaz] [h=832A0D]
+\definecolor [TigersEye] [h=B56917]
+\definecolor [AquaPearl] [h=5FBED7]
+\definecolor [BlackCoralPearl] [h=54626F]
+\definecolor [CaribbeanGreenPearl] [h=6ADA8E]
+\definecolor [CulturedPearl] [h=F5F5F5]
+\definecolor [KeyLimePearl] [h=E8F48C]
+\definecolor [MandarinPearl] [h=F37A48]
+\definecolor [MidnightPearl] [h=702670]
+\definecolor [MysticPearl] [h=D65282]
+\definecolor [OceanBluePearl] [h=4F42B5]
+\definecolor [OceanGreenPearl] [h=48BF91]
+\definecolor [OrchidPearl] [h=7B4259]
+\definecolor [RosePearl] [h=F03865]
+\definecolor [SalmonPearl] [h=F1444A]
+\definecolor [SunnyPearl] [h=F2F27A]
+\definecolor [SunsetPearl] [h=F1CC79]
+\definecolor [TurquoisePearl] [h=3BBCD0]
+
+\stopprotectedcolors
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-dem.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-dem.mkiv
new file mode 100644
index 00000000000..7744a216ef9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-dem.mkiv
@@ -0,0 +1,275 @@
+%D \module
+%D [ file=colo-dem, % moved from colo-rgb,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Demo Palets and Groups,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Like colors, we first define the english colorgroups. These colorgroups are
+%D tuned for distinctive gray scale printing. The yellow range is not really
+%D all yellow but is at least visible.
+
+\definecolorgroup
+ [gray]
+ [0.95:0.95:0.95,
+ 0.90:0.90:0.90,
+ 0.80:0.80:0.80,
+ 0.70:0.70:0.70,
+ 0.60:0.60:0.60,
+ 0.50:0.50:0.50,
+ 0.40:0.40:0.40,
+ 0.30:0.30:0.30,
+ 0.20:0.20:0.20,
+ 0.10:0.10:0.10,
+ 0.00:0.00:0.00]
+
+\definecolorgroup
+ [red]
+ [1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.55:0.55,
+ 1.00:0.40:0.40,
+ 1.00:0.25:0.25,
+ 1.00:0.15:0.15,
+ 0.90:0.00:0.00]
+
+\definecolorgroup
+ [green]
+ [0.90:1.00:0.90,
+ 0.70:1.00:0.70,
+ 0.50:1.00:0.50,
+ 0.30:1.00:0.30,
+ 0.15:0.90:0.15,
+ 0.00:0.80:0.00,
+ 0.00:0.65:0.00,
+ 0.00:0.50:0.00]
+
+\definecolorgroup
+ [blue]
+ [0.90:0.95:1.00,
+ 0.80:0.90:1.00,
+ 0.55:0.85:1.00,
+ 0.30:0.80:1.00,
+ 0.15:0.75:1.00,
+ 0.00:0.70:1.00,
+ 0.00:0.55:1.00,
+ 0.00:0.40:1.00]
+
+\definecolorgroup
+ [cyan]
+ [0.80:1.00:1.00,
+ 0.60:1.00:1.00,
+ 0.30:1.00:1.00,
+ 0.00:0.95:0.95,
+ 0.00:0.85:0.85,
+ 0.00:0.75:0.75,
+ 0.00:0.60:0.60,
+ 0.00:0.50:0.50]
+
+\definecolorgroup
+ [magenta]
+ [1.00:0.90:1.00,
+ 1.00:0.80:1.00,
+ 1.00:0.65:1.00,
+ 1.00:0.50:1.00,
+ 1.00:0.35:1.00,
+ 1.00:0.15:1.00,
+ 0.90:0.05:0.90,
+ 0.80:0.00:0.80]
+
+\definecolorgroup
+ [yellow]
+ [1.00:1.00:0.70,
+ 1.00:1.00:0.00,
+ 1.00:0.85:0.05,
+ 1.00:0.70:0.00,
+ 1.00:0.55:0.00,
+ 0.95:0.40:0.00,
+ 0.80:0.30:0.00,
+ 0.60:0.30:0.00]
+
+\definecolorgroup
+ [red*]
+ [1.00:0.95:0.95,
+ 1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.60:0.60,
+ 1.00:0.50:0.50,
+ 1.00:0.40:0.40,
+ 1.00:0.30:0.30]
+
+\definecolorgroup
+ [green*]
+ [0.95:1.00:0.95,
+ 0.90:1.00:0.90,
+ 0.80:1.00:0.80,
+ 0.70:1.00:0.70,
+ 0.60:1.00:0.60,
+ 0.50:1.00:0.50,
+ 0.40:1.00:0.40,
+ 0.30:1.00:0.30]
+
+\definecolorgroup
+ [blue*]
+ [0.95:0.95:1.00,
+ 0.90:0.90:1.00,
+ 0.80:0.80:1.00,
+ 0.70:0.70:1.00,
+ 0.60:0.60:1.00,
+ 0.50:0.50:1.00,
+ 0.40:0.40:1.00,
+ 0.30:0.30:1.00]
+
+\definecolorgroup
+ [yellow*]
+ [1.00:1.00:0.10,
+ 1.00:1.00:0.00,
+ 0.90:0.90:0.00,
+ 0.80:0.80:0.00,
+ 0.70:0.70:0.00,
+ 0.60:0.60:0.00,
+ 0.50:0.50:0.00,
+ 0.40:0.40:0.00]
+
+%D For the sake of implementing interface dependant color
+%D groups we support colorgroup duplication.
+
+\startinterface dutch
+ \definecolorgroup [grijs] [gray]
+ \definecolorgroup [rood] [red]
+ \definecolorgroup [groen] [green]
+ \definecolorgroup [blauw] [blue]
+ \definecolorgroup [cyaan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [geel] [yellow]
+ \definecolorgroup [rood*] [red*]
+ \definecolorgroup [groen*] [green*]
+ \definecolorgroup [blauw*] [blue*]
+ \definecolorgroup [geel*] [yellow*]
+\stopinterface
+
+\startinterface german
+ \definecolorgroup [grau] [gray]
+ \definecolorgroup [rot] [red]
+ \definecolorgroup [gruen] [green]
+ \definecolorgroup [blau] [blue]
+ \definecolorgroup [cyan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [gelb] [yellow]
+ \definecolorgroup [rot*] [red*]
+ \definecolorgroup [gruen*] [green*]
+ \definecolorgroup [blau*] [blue*]
+ \definecolorgroup [gelb*] [yellow*]
+\stopinterface
+
+\startinterface czech
+ \definecolorgroup [seda] [gray]
+ \definecolorgroup [cervena] [red]
+ \definecolorgroup [zelena] [green]
+ \definecolorgroup [modra] [blue]
+ \definecolorgroup [azurova] [cyan]
+ \definecolorgroup [fialova] [magenta]
+ \definecolorgroup [zluta] [yellow]
+ \definecolorgroup [cervena*] [red*]
+ \definecolorgroup [zelena*] [green*]
+ \definecolorgroup [modra*] [blue*]
+ \definecolorgroup [zluta*] [yellow*]
+\stopinterface
+
+\startinterface italian
+ \definecolorgroup [grigio] [gray]
+ \definecolorgroup [rosso] [red]
+ \definecolorgroup [verde] [green]
+ \definecolorgroup [blu] [blue]
+ \definecolorgroup [ciano] [cyan]
+ \definecolorgroup [azzurro] [cyan]
+ \definecolorgroup [turchino][cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [cremisi] [magenta]
+ \definecolorgroup [giallo] [yellow]
+ \definecolorgroup [rosso*] [red*]
+ \definecolorgroup [verde*] [green*]
+ \definecolorgroup [blu*] [blue*]
+ \definecolorgroup [giallo*] [yellow*]
+\stopinterface
+
+\startinterface french
+ \definecolorgroup [gris] [gray]
+ \definecolorgroup [rouge] [red]
+ \definecolorgroup [vert] [green]
+ \definecolorgroup [bleu] [blue]
+ \definecolorgroup [cyan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [jaune] [yellow]
+ \definecolorgroup [rouge*] [red*]
+ \definecolorgroup [vert*] [green*]
+ \definecolorgroup [bleu*] [blue*]
+ \definecolorgroup [jaune*] [yellow*]
+\stopinterface
+
+%D The next set of color palets is quite language independant.
+%D These palets are meant as examples.
+
+\definepalet
+ [alfa]
+ [ top=red:7,
+ bottom=green:6,
+ up=blue:5,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+\definepalet
+ [beta]
+ [ top=red:7,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:2,
+ charm=yellow:1]
+
+\definepalet
+ [gamma]
+ [ top=red:2,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:7,
+ charm=yellow:4]
+
+\definepalet
+ [delta]
+ [ top=yellow*:5,
+ bottom=yellow*:3,
+ up=yellow*:2,
+ down=magenta:6,
+ strange=blue:4,
+ charm=blue:1]
+
+\definepalet
+ [epsilon]
+ [ top=cyan:7,
+ bottom=cyan:5,
+ up=blue:3,
+ down=yellow:6,
+ strange=yellow:4,
+ charm=yellow:2]
+
+\definepalet
+ [zeta]
+ [ top=red:6,
+ bottom=green:5,
+ up=blue:7,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ema.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ema.mkiv
new file mode 100644
index 00000000000..ff1db60fb55
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ema.mkiv
@@ -0,0 +1,500 @@
+%D \module
+%D [ file=colo-ema,
+%D version=2003.03.20,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Emacs Colors,
+%D author=Peter Rolf,
+%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.
+
+% author : Peter Rolf <peter.rolf@arcor.de>
+% last change : 17 march 2003
+% origin : /emacs/etc/rgb.txt
+%
+% USAGE:
+%
+% - select emacs menu: Edit -> Text Properties -> Display
+% Colors, if you don't know what I'm talking about
+% - copy this file to your /texmf/tex/context/user directory
+% and add "\input colo-emacs" to your tex-file
+%
+% IMPORTANT NOTES:
+%
+% - all color names are written as ONE word in lowercase
+% letters (no redundancy as in rgb.txt) so if you want to
+% use the color "Light Sky Blue"/"light sky blue" it's new
+% name is lightskyblue
+% - the grayX values [X=0..100] can only be used with \color
+% [grayX]
+% - use it at your own risk :)
+%
+% HINT:
+%
+% I only include this file (\showcolor [ema]) until I've
+% found the colors I want. Copy and paste the color
+% definitions to a seperate file, to decrease compilation
+% time (540 color definitions).
+
+\startprotectedcolors
+
+\definecolor [snow] [r=1,g=.980392,b=.980392]
+\definecolor [ghostwhite] [r=.972549,g=.972549,b=1]
+\definecolor [whitesmoke] [s=.960784]
+\definecolor [gainsboro] [s=.862745]
+\definecolor [floralwhite] [r=1,g=.980392,b=.941176]
+\definecolor [oldlace] [r=.992157,g=.960784,b=.901961]
+\definecolor [linen] [r=.980392,g=.941176,b=.901961]
+\definecolor [antiquewhite] [r=.980392,g=.921569,b=.843137]
+\definecolor [papayawhip] [r=1,g=.937255,b=.835294]
+\definecolor [blanchedalmond] [r=1,g=.921569,b=.803922]
+\definecolor [bisque] [r=1,g=.894118,b=.768627]
+\definecolor [peachpuff] [r=1,g=.854902,b=.72549]
+\definecolor [navajowhite] [r=1,g=.870588,b=.678431]
+\definecolor [moccasin] [r=1,g=.894118,b=.709804]
+\definecolor [cornsilk] [r=1,g=.972549,b=.862745]
+\definecolor [ivory] [r=1,g=1,b=.941176]
+\definecolor [lemonchiffon] [r=1,g=.980392,b=.803922]
+\definecolor [seashell] [r=1,g=.960784,b=.933333]
+\definecolor [honeydew] [r=.941176,g=1,b=.941176]
+\definecolor [mintcream] [r=.960784,g=1,b=.980392]
+\definecolor [azure] [r=.941176,g=1,b=1]
+\definecolor [aliceblue] [r=.941176,g=.972549,b=1]
+\definecolor [lavender] [r=.901961,g=.901961,b=.980392]
+\definecolor [lavenderblush] [r=1,g=.941176,b=.960784]
+\definecolor [mistyrose] [r=1,g=.894118,b=.882353]
+%definecolor[white] [s=1]
+%definecolor[black] [s=0]
+\definecolor [darkslategray] [r=.184314,g=.309804,b=.309804]
+\definecolor [dimgray] [s=.411765]
+\definecolor [slategray] [r=.439216,g=.501961,b=.564706]
+\definecolor [lightslategray] [r=.466667,g=.533333,b=.6]
+\definecolor [gray] [s=.745098]
+\definecolor [lightgray] [s=.827451]
+\definecolor [midnightblue] [r=.098039,g=.098039,b=.439216]
+\definecolor [navy] [b=.501961]
+\definecolor [navyblue] [navy]
+\definecolor [cornflowerblue] [r=.392157,g=.584314,b=.929412]
+\definecolor [darkslateblue] [r=.282353,g=.239216,b=.545098]
+\definecolor [slateblue] [r=.415686,g=.352941,b=.803922]
+\definecolor [mediumslateblue] [r=.482353,g=.407843,b=.933333]
+\definecolor [lightslateblue] [r=.517647,g=.439216,b=1]
+\definecolor [mediumblue] [b=.803922]
+\definecolor [royalblue] [r=.254902,g=.411765,b=.882353]
+%definecolor[blue] [b=1]
+\definecolor [dodgerblue] [r=.117647,g=.564706,b=1]
+\definecolor [deepskyblue] [g=.74902,b=1]
+\definecolor [skyblue] [r=.529412,g=.807843,b=.921569]
+\definecolor [lightskyblue] [r=.529412,g=.807843,b=.980392]
+\definecolor [steelblue] [r=.27451,g=.509804,b=.705882]
+\definecolor [lightsteelblue] [r=.690196,g=.768627,b=.870588]
+\definecolor [lightblue] [r=.678431,g=.847059,b=.901961]
+\definecolor [powderblue] [r=.690196,g=.878431,b=.901961]
+\definecolor [paleturquoise] [r=.686275,g=.933333,b=.933333]
+\definecolor [darkturquoise] [g=.807843,b=.819608]
+\definecolor [mediumturquoise] [r=.282353,g=.819608,b=.8]
+\definecolor [turquoise] [r=.25098,g=.878431,b=.815686]
+%definecolor[cyan] [g=1,b=1]
+\definecolor [lightcyan] [r=.878431,g=1,b=1]
+\definecolor [cadetblue] [r=.372549,g=.619608,b=.627451]
+\definecolor [mediumaquamarine] [r=.4,g=.803922,b=.666667]
+\definecolor [aquamarine] [r=.498039,g=1,b=.831373]
+\definecolor [darkgreen] [g=.392157]
+\definecolor [darkolivegreen] [r=.333333,g=.419608,b=.184314]
+\definecolor [darkseagreen] [r=.560784,g=.737255,b=.560784]
+\definecolor [seagreen] [r=.180392,g=.545098,b=.341176]
+\definecolor [mediumseagreen] [r=.235294,g=.701961,b=.443137]
+\definecolor [lightseagreen] [r=.12549,g=.698039,b=.666667]
+\definecolor [palegreen] [r=.596078,g=.984314,b=.596078]
+\definecolor [springgreen] [g=1,b=.498039]
+\definecolor [lawngreen] [r=.486275,g=.988235]
+%definecolor[green] [g=1]
+\definecolor [chartreuse] [r=.498039,g=1]
+\definecolor [mediumspringgreen] [g=.980392,b=.603922]
+\definecolor [greenyellow] [r=.678431,g=1,b=.184314]
+\definecolor [limegreen] [r=.196078,g=.803922,b=.196078]
+\definecolor [yellowgreen] [r=.603922,g=.803922,b=.196078]
+\definecolor [forestgreen] [r=.133333,g=.545098,b=.133333]
+\definecolor [olivedrab] [r=.419608,g=.556863,b=.137255]
+\definecolor [darkkhaki] [r=.741176,g=.717647,b=.419608]
+\definecolor [khaki] [r=.941176,g=.901961,b=.54902]
+\definecolor [palegoldenrod] [r=.933333,g=.909804,b=.666667]
+\definecolor [lightgoldenrodyellow] [r=.980392,g=.980392,b=.823529]
+\definecolor [lightyellow] [r=1,g=1,b=.878431]
+%definecolor[yellow] [r=1,g=1]
+\definecolor [gold] [r=1,g=.843137]
+\definecolor [lightgoldenrod] [r=.933333,g=.866667,b=.509804]
+\definecolor [goldenrod] [r=.854902,g=.647059,b=.12549]
+\definecolor [darkgoldenrod] [r=.721569,g=.52549,b=.043137]
+\definecolor [rosybrown] [r=.737255,g=.560784,b=.560784]
+\definecolor [indianred] [r=.803922,g=.360784,b=.360784]
+\definecolor [saddlebrown] [r=.545098,g=.270588,b=.07451]
+\definecolor [sienna] [r=.627451,g=.321569,b=.176471]
+\definecolor [peru] [r=.803922,g=.521569,b=.247059]
+\definecolor [burlywood] [r=.870588,g=.721569,b=.529412]
+\definecolor [beige] [r=.960784,g=.960784,b=.862745]
+\definecolor [wheat] [r=.960784,g=.870588,b=.701961]
+\definecolor [sandybrown] [r=.956863,g=.643137,b=.376471]
+\definecolor [tan] [r=.823529,g=.705882,b=.54902]
+\definecolor [chocolate] [r=.823529,g=.411765,b=.117647]
+\definecolor [firebrick] [r=.698039,g=.133333,b=.133333]
+\definecolor [brown] [r=.647059,g=.164706,b=.164706]
+\definecolor [darksalmon] [r=.913725,g=.588235,b=.478431]
+\definecolor [salmon] [r=.980392,g=.501961,b=.447059]
+\definecolor [lightsalmon] [r=1,g=.627451,b=.478431]
+\definecolor [orange] [r=1,g=.647059]
+\definecolor [darkorange] [r=1,g=.54902]
+\definecolor [coral] [r=1,g=.498039,b=.313725]
+\definecolor [lightcoral] [r=.941176,g=.501961,b=.501961]
+\definecolor [tomato] [r=1,g=.388235,b=.278431]
+\definecolor [orangered] [r=1,g=.270588]
+%definecolor[red] [r=1]
+\definecolor [hotpink] [r=1,g=.411765,b=.705882]
+\definecolor [deeppink] [r=1,g=.078431,b=.576471]
+\definecolor [pink] [r=1,g=.752941,b=.796078]
+\definecolor [lightpink] [r=1,g=.713725,b=.756863]
+\definecolor [palevioletred] [r=.858824,g=.439216,b=.576471]
+\definecolor [maroon] [r=.690196,g=.188235,b=.376471]
+\definecolor [mediumvioletred] [r=.780392,g=.082353,b=.521569]
+\definecolor [violetred] [r=.815686,g=.12549,b=.564706]
+%definecolor[magenta] [r=1,b=1]
+\definecolor [violet] [r=.933333,g=.509804,b=.933333]
+\definecolor [plum] [r=.866667,g=.627451,b=.866667]
+\definecolor [orchid] [r=.854902,g=.439216,b=.839216]
+\definecolor [mediumorchid] [r=.729412,g=.333333,b=.827451]
+\definecolor [darkorchid] [r=.6,g=.196078,b=.8]
+\definecolor [darkviolet] [r=.580392,b=.827451]
+\definecolor [blueviolet] [r=.541176,g=.168627,b=.886275]
+\definecolor [purple] [r=.627451,g=.12549,b=.941176]
+\definecolor [mediumpurple] [r=.576471,g=.439216,b=.858824]
+\definecolor [thistle] [r=.847059,g=.74902,b=.847059]
+\definecolor [snow1] [r=1,g=.980392,b=.980392]
+\definecolor [snow2] [r=.933333,g=.913725,b=.913725]
+\definecolor [snow3] [r=.803922,g=.788235,b=.788235]
+\definecolor [snow4] [r=.545098,g=.537255,b=.537255]
+\definecolor [seashell1] [r=1,g=.960784,b=.933333]
+\definecolor [seashell2] [r=.933333,g=.898039,b=.870588]
+\definecolor [seashell3] [r=.803922,g=.772549,b=.74902]
+\definecolor [seashell4] [r=.545098,g=.52549,b=.509804]
+\definecolor [antiquewhite1] [r=1,g=.937255,b=.858824]
+\definecolor [antiquewhite2] [r=.933333,g=.87451,b=.8]
+\definecolor [antiquewhite3] [r=.803922,g=.752941,b=.690196]
+\definecolor [antiquewhite4] [r=.545098,g=.513725,b=.470588]
+\definecolor [bisque1] [r=1,g=.894118,b=.768627]
+\definecolor [bisque2] [r=.933333,g=.835294,b=.717647]
+\definecolor [bisque3] [r=.803922,g=.717647,b=.619608]
+\definecolor [bisque4] [r=.545098,g=.490196,b=.419608]
+\definecolor [peachpuff1] [r=1,g=.854902,b=.72549]
+\definecolor [peachpuff2] [r=.933333,g=.796078,b=.678431]
+\definecolor [peachpuff3] [r=.803922,g=.686275,b=.584314]
+\definecolor [peachpuff4] [r=.545098,g=.466667,b=.396078]
+\definecolor [navajowhite1] [r=1,g=.870588,b=.678431]
+\definecolor [navajowhite2] [r=.933333,g=.811765,b=.631373]
+\definecolor [navajowhite3] [r=.803922,g=.701961,b=.545098]
+\definecolor [navajowhite4] [r=.545098,g=.47451,b=.368627]
+\definecolor [lemonchiffon1] [r=1,g=.980392,b=.803922]
+\definecolor [lemonchiffon2] [r=.933333,g=.913725,b=.74902]
+\definecolor [lemonchiffon3] [r=.803922,g=.788235,b=.647059]
+\definecolor [lemonchiffon4] [r=.545098,g=.537255,b=.439216]
+\definecolor [cornsilk1] [r=1,g=.972549,b=.862745]
+\definecolor [cornsilk2] [r=.933333,g=.909804,b=.803922]
+\definecolor [cornsilk3] [r=.803922,g=.784314,b=.694118]
+\definecolor [cornsilk4] [r=.545098,g=.533333,b=.470588]
+\definecolor [ivory1] [r=1,g=1,b=.941176]
+\definecolor [ivory2] [r=.933333,g=.933333,b=.878431]
+\definecolor [ivory3] [r=.803922,g=.803922,b=.756863]
+\definecolor [ivory4] [r=.545098,g=.545098,b=.513725]
+\definecolor [honeydew1] [r=.941176,g=1,b=.941176]
+\definecolor [honeydew2] [r=.878431,g=.933333,b=.878431]
+\definecolor [honeydew3] [r=.756863,g=.803922,b=.756863]
+\definecolor [honeydew4] [r=.513725,g=.545098,b=.513725]
+\definecolor [lavenderblush1] [r=1,g=.941176,b=.960784]
+\definecolor [lavenderblush2] [r=.933333,g=.878431,b=.898039]
+\definecolor [lavenderblush3] [r=.803922,g=.756863,b=.772549]
+\definecolor [lavenderblush4] [r=.545098,g=.513725,b=.52549]
+\definecolor [mistyrose1] [r=1,g=.894118,b=.882353]
+\definecolor [mistyrose2] [r=.933333,g=.835294,b=.823529]
+\definecolor [mistyrose3] [r=.803922,g=.717647,b=.709804]
+\definecolor [mistyrose4] [r=.545098,g=.490196,b=.482353]
+\definecolor [azure1] [r=.941176,g=1,b=1]
+\definecolor [azure2] [r=.878431,g=.933333,b=.933333]
+\definecolor [azure3] [r=.756863,g=.803922,b=.803922]
+\definecolor [azure4] [r=.513725,g=.545098,b=.545098]
+\definecolor [slateblue1] [r=.513725,g=.435294,b=1]
+\definecolor [slateblue2] [r=.478431,g=.403922,b=.933333]
+\definecolor [slateblue3] [r=.411765,g=.34902,b=.803922]
+\definecolor [slateblue4] [r=.278431,g=.235294,b=.545098]
+\definecolor [royalblue1] [r=.282353,g=.462745,b=1]
+\definecolor [royalblue2] [r=.262745,g=.431373,b=.933333]
+\definecolor [royalblue3] [r=.227451,g=.372549,b=.803922]
+\definecolor [royalblue4] [r=.152941,g=.25098,b=.545098]
+\definecolor [blue1] [blue]
+\definecolor [blue2] [b=.933333]
+\definecolor [blue3] [b=.803922]
+\definecolor [blue4] [b=.545098]
+\definecolor [dodgerblue1] [r=.117647,g=.564706,b=1]
+\definecolor [dodgerblue2] [r=.109804,g=.52549,b=.933333]
+\definecolor [dodgerblue3] [r=.094118,g=.454902,b=.803922]
+\definecolor [dodgerblue4] [r=.062745,g=.305882,b=.545098]
+\definecolor [steelblue1] [r=.388235,g=.721569,b=1]
+\definecolor [steelblue2] [r=.360784,g=.67451,b=.933333]
+\definecolor [steelblue3] [r=.309804,g=.580392,b=.803922]
+\definecolor [steelblue4] [r=.211765,g=.392157,b=.545098]
+\definecolor [deepskyblue1] [g=.74902,b=1]
+\definecolor [deepskyblue2] [g=.698039,b=.933333]
+\definecolor [deepskyblue3] [g=.603922,b=.803922]
+\definecolor [deepskyblue4] [g=.407843,b=.545098]
+\definecolor [skyblue1] [r=.529412,g=.807843,b=1]
+\definecolor [skyblue2] [r=.494118,g=.752941,b=.933333]
+\definecolor [skyblue3] [r=.423529,g=.65098,b=.803922]
+\definecolor [skyblue4] [r=.290196,g=.439216,b=.545098]
+\definecolor [lightskyblue1] [r=.690196,g=.886275,b=1]
+\definecolor [lightskyblue2] [r=.643137,g=.827451,b=.933333]
+\definecolor [lightskyblue3] [r=.552941,g=.713725,b=.803922]
+\definecolor [lightskyblue4] [r=.376471,g=.482353,b=.545098]
+\definecolor [slategray1] [r=.776471,g=.886275,b=1]
+\definecolor [slategray2] [r=.72549,g=.827451,b=.933333]
+\definecolor [slategray3] [r=.623529,g=.713725,b=.803922]
+\definecolor [slategray4] [r=.423529,g=.482353,b=.545098]
+\definecolor [lightsteelblue1] [r=.792157,g=.882353,b=1]
+\definecolor [lightsteelblue2] [r=.737255,g=.823529,b=.933333]
+\definecolor [lightsteelblue3] [r=.635294,g=.709804,b=.803922]
+\definecolor [lightsteelblue4] [r=.431373,g=.482353,b=.545098]
+\definecolor [lightblue1] [r=.74902,g=.937255,b=1]
+\definecolor [lightblue2] [r=.698039,g=.87451,b=.933333]
+\definecolor [lightblue3] [r=.603922,g=.752941,b=.803922]
+\definecolor [lightblue4] [r=.407843,g=.513725,b=.545098]
+\definecolor [lightcyan1] [r=.878431,g=1,b=1]
+\definecolor [lightcyan2] [r=.819608,g=.933333,b=.933333]
+\definecolor [lightcyan3] [r=.705882,g=.803922,b=.803922]
+\definecolor [lightcyan4] [r=.478431,g=.545098,b=.545098]
+\definecolor [paleturquoise1] [r=.733333,g=1,b=1]
+\definecolor [paleturquoise2] [r=.682353,g=.933333,b=.933333]
+\definecolor [paleturquoise3] [r=.588235,g=.803922,b=.803922]
+\definecolor [paleturquoise4] [r=.4,g=.545098,b=.545098]
+\definecolor [cadetblue1] [r=.596078,g=.960784,b=1]
+\definecolor [cadetblue2] [r=.556863,g=.898039,b=.933333]
+\definecolor [cadetblue3] [r=.478431,g=.772549,b=.803922]
+\definecolor [cadetblue4] [r=.32549,g=.52549,b=.545098]
+\definecolor [turquoise1] [g=.960784,b=1]
+\definecolor [turquoise2] [g=.898039,b=.933333]
+\definecolor [turquoise3] [g=.772549,b=.803922]
+\definecolor [turquoise4] [g=.52549,b=.545098]
+\definecolor [cyan1] [cyan]
+\definecolor [cyan2] [g=.933333,b=.933333]
+\definecolor [cyan3] [g=.803922,b=.803922]
+\definecolor [cyan4] [g=.545098,b=.545098]
+\definecolor [darkslategray1] [r=.592157,g=1,b=1]
+\definecolor [darkslategray2] [r=.552941,g=.933333,b=.933333]
+\definecolor [darkslategray3] [r=.47451,g=.803922,b=.803922]
+\definecolor [darkslategray4] [r=.321569,g=.545098,b=.545098]
+\definecolor [aquamarine1] [r=.498039,g=1,b=.831373]
+\definecolor [aquamarine2] [r=.462745,g=.933333,b=.776471]
+\definecolor [aquamarine3] [r=.4,g=.803922,b=.666667]
+\definecolor [aquamarine4] [r=.270588,g=.545098,b=.454902]
+\definecolor [darkseagreen1] [r=.756863,g=1,b=.756863]
+\definecolor [darkseagreen2] [r=.705882,g=.933333,b=.705882]
+\definecolor [darkseagreen3] [r=.607843,g=.803922,b=.607843]
+\definecolor [darkseagreen4] [r=.411765,g=.545098,b=.411765]
+\definecolor [seagreen1] [r=.329412,g=1,b=.623529]
+\definecolor [seagreen2] [r=.305882,g=.933333,b=.580392]
+\definecolor [seagreen3] [r=.262745,g=.803922,b=.501961]
+\definecolor [seagreen4] [r=.180392,g=.545098,b=.341176]
+\definecolor [palegreen1] [r=.603922,g=1,b=.603922]
+\definecolor [palegreen2] [r=.564706,g=.933333,b=.564706]
+\definecolor [palegreen3] [r=.486275,g=.803922,b=.486275]
+\definecolor [palegreen4] [r=.329412,g=.545098,b=.329412]
+\definecolor [springgreen1] [g=1,b=.498039]
+\definecolor [springgreen2] [g=.933333,b=.462745]
+\definecolor [springgreen3] [g=.803922,b=.4]
+\definecolor [springgreen4] [g=.545098,b=.270588]
+\definecolor [green1] [green]
+\definecolor [green2] [g=.933333]
+\definecolor [green3] [g=.803922]
+\definecolor [green4] [g=.545098]
+\definecolor [chartreuse1] [r=.498039,g=1]
+\definecolor [chartreuse2] [r=.462745,g=.933333]
+\definecolor [chartreuse3] [r=.4,g=.803922]
+\definecolor [chartreuse4] [r=.270588,g=.545098]
+\definecolor [olivedrab1] [r=.752941,g=1,b=.243137]
+\definecolor [olivedrab2] [r=.701961,g=.933333,b=.227451]
+\definecolor [olivedrab3] [r=.603922,g=.803922,b=.196078]
+\definecolor [olivedrab4] [r=.411765,g=.545098,b=.133333]
+\definecolor [darkolivegreen1] [r=.792157,g=1,b=.439216]
+\definecolor [darkolivegreen2] [r=.737255,g=.933333,b=.407843]
+\definecolor [darkolivegreen3] [r=.635294,g=.803922,b=.352941]
+\definecolor [darkolivegreen4] [r=.431373,g=.545098,b=.239216]
+\definecolor [khaki1] [r=1,g=.964706,b=.560784]
+\definecolor [khaki2] [r=.933333,g=.901961,b=.521569]
+\definecolor [khaki3] [r=.803922,g=.776471,b=.45098]
+\definecolor [khaki4] [r=.545098,g=.52549,b=.305882]
+\definecolor [lightgoldenrod1] [r=1,g=.92549,b=.545098]
+\definecolor [lightgoldenrod2] [r=.933333,g=.862745,b=.509804]
+\definecolor [lightgoldenrod3] [r=.803922,g=.745098,b=.439216]
+\definecolor [lightgoldenrod4] [r=.545098,g=.505882,b=.298039]
+\definecolor [lightyellow1] [r=1,g=1,b=.878431]
+\definecolor [lightyellow2] [r=.933333,g=.933333,b=.819608]
+\definecolor [lightyellow3] [r=.803922,g=.803922,b=.705882]
+\definecolor [lightyellow4] [r=.545098,g=.545098,b=.478431]
+\definecolor [yellow1] [yellow]
+\definecolor [yellow2] [r=.933333,g=.933333]
+\definecolor [yellow3] [r=.803922,g=.803922]
+\definecolor [yellow4] [r=.545098,g=.545098]
+\definecolor [gold1] [r=1,g=.843137]
+\definecolor [gold2] [r=.933333,g=.788235]
+\definecolor [gold3] [r=.803922,g=.678431]
+\definecolor [gold4] [r=.545098,g=.458824]
+\definecolor [goldenrod1] [r=1,g=.756863,b=.145098]
+\definecolor [goldenrod2] [r=.933333,g=.705882,b=.133333]
+\definecolor [goldenrod3] [r=.803922,g=.607843,b=.113725]
+\definecolor [goldenrod4] [r=.545098,g=.411765,b=.078431]
+\definecolor [darkgoldenrod1] [r=1,g=.72549,b=.058824]
+\definecolor [darkgoldenrod2] [r=.933333,g=.678431,b=.054902]
+\definecolor [darkgoldenrod3] [r=.803922,g=.584314,b=.047059]
+\definecolor [darkgoldenrod4] [r=.545098,g=.396078,b=.031373]
+\definecolor [rosybrown1] [r=1,g=.756863,b=.756863]
+\definecolor [rosybrown2] [r=.933333,g=.705882,b=.705882]
+\definecolor [rosybrown3] [r=.803922,g=.607843,b=.607843]
+\definecolor [rosybrown4] [r=.545098,g=.411765,b=.411765]
+\definecolor [indianred1] [r=1,g=.415686,b=.415686]
+\definecolor [indianred2] [r=.933333,g=.388235,b=.388235]
+\definecolor [indianred3] [r=.803922,g=.333333,b=.333333]
+\definecolor [indianred4] [r=.545098,g=.227451,b=.227451]
+\definecolor [sienna1] [r=1,g=.509804,b=.278431]
+\definecolor [sienna2] [r=.933333,g=.47451,b=.258824]
+\definecolor [sienna3] [r=.803922,g=.407843,b=.223529]
+\definecolor [sienna4] [r=.545098,g=.278431,b=.14902]
+\definecolor [burlywood1] [r=1,g=.827451,b=.607843]
+\definecolor [burlywood2] [r=.933333,g=.772549,b=.568627]
+\definecolor [burlywood3] [r=.803922,g=.666667,b=.490196]
+\definecolor [burlywood4] [r=.545098,g=.45098,b=.333333]
+\definecolor [wheat1] [r=1,g=.905882,b=.729412]
+\definecolor [wheat2] [r=.933333,g=.847059,b=.682353]
+\definecolor [wheat3] [r=.803922,g=.729412,b=.588235]
+\definecolor [wheat4] [r=.545098,g=.494118,b=.4]
+\definecolor [tan1] [r=1,g=.647059,b=.309804]
+\definecolor [tan2] [r=.933333,g=.603922,b=.286275]
+\definecolor [tan3] [r=.803922,g=.521569,b=.247059]
+\definecolor [tan4] [r=.545098,g=.352941,b=.168627]
+\definecolor [chocolate1] [r=1,g=.498039,b=.141176]
+\definecolor [chocolate2] [r=.933333,g=.462745,b=.129412]
+\definecolor [chocolate3] [r=.803922,g=.4,b=.113725]
+\definecolor [chocolate4] [r=.545098,g=.270588,b=.07451]
+\definecolor [firebrick1] [r=1,g=.188235,b=.188235]
+\definecolor [firebrick2] [r=.933333,g=.172549,b=.172549]
+\definecolor [firebrick3] [r=.803922,g=.14902,b=.14902]
+\definecolor [firebrick4] [r=.545098,g=.101961,b=.101961]
+\definecolor [brown1] [r=1,g=.25098,b=.25098]
+\definecolor [brown2] [r=.933333,g=.231373,b=.231373]
+\definecolor [brown3] [r=.803922,g=.2,b=.2]
+\definecolor [brown4] [r=.545098,g=.137255,b=.137255]
+\definecolor [salmon1] [r=1,g=.54902,b=.411765]
+\definecolor [salmon2] [r=.933333,g=.509804,b=.384314]
+\definecolor [salmon3] [r=.803922,g=.439216,b=.329412]
+\definecolor [salmon4] [r=.545098,g=.298039,b=.223529]
+\definecolor [lightsalmon1] [r=1,g=.627451,b=.478431]
+\definecolor [lightsalmon2] [r=.933333,g=.584314,b=.447059]
+\definecolor [lightsalmon3] [r=.803922,g=.505882,b=.384314]
+\definecolor [lightsalmon4] [r=.545098,g=.341176,b=.258824]
+\definecolor [orange1] [r=1,g=.647059]
+\definecolor [orange2] [r=.933333,g=.603922]
+\definecolor [orange3] [r=.803922,g=.521569]
+\definecolor [orange4] [r=.545098,g=.352941]
+\definecolor [darkorange1] [r=1,g=.498039]
+\definecolor [darkorange2] [r=.933333,g=.462745]
+\definecolor [darkorange3] [r=.803922,g=.4]
+\definecolor [darkorange4] [r=.545098,g=.270588]
+\definecolor [coral1] [r=1,g=.447059,b=.337255]
+\definecolor [coral2] [r=.933333,g=.415686,b=.313725]
+\definecolor [coral3] [r=.803922,g=.356863,b=.270588]
+\definecolor [coral4] [r=.545098,g=.243137,b=.184314]
+\definecolor [tomato1] [r=1,g=.388235,b=.278431]
+\definecolor [tomato2] [r=.933333,g=.360784,b=.258824]
+\definecolor [tomato3] [r=.803922,g=.309804,b=.223529]
+\definecolor [tomato4] [r=.545098,g=.211765,b=.14902]
+\definecolor [orangered1] [r=1,g=.270588]
+\definecolor [orangered2] [r=.933333,g=.25098]
+\definecolor [orangered3] [r=.803922,g=.215686]
+\definecolor [orangered4] [r=.545098,g=.145098]
+\definecolor [red1] [red]
+\definecolor [red2] [r=.933333]
+\definecolor [red3] [r=.803922]
+\definecolor [red4] [r=.545098]
+\definecolor [deeppink1] [r=1,g=.078431,b=.576471]
+\definecolor [deeppink2] [r=.933333,g=.070588,b=.537255]
+\definecolor [deeppink3] [r=.803922,g=.062745,b=.462745]
+\definecolor [deeppink4] [r=.545098,g=.039216,b=.313725]
+\definecolor [hotpink1] [r=1,g=.431373,b=.705882]
+\definecolor [hotpink2] [r=.933333,g=.415686,b=.654902]
+\definecolor [hotpink3] [r=.803922,g=.376471,b=.564706]
+\definecolor [hotpink4] [r=.545098,g=.227451,b=.384314]
+\definecolor [pink1] [r=1,g=.709804,b=.772549]
+\definecolor [pink2] [r=.933333,g=.662745,b=.721569]
+\definecolor [pink3] [r=.803922,g=.568627,b=.619608]
+\definecolor [pink4] [r=.545098,g=.388235,b=.423529]
+\definecolor [lightpink1] [r=1,g=.682353,b=.72549]
+\definecolor [lightpink2] [r=.933333,g=.635294,b=.678431]
+\definecolor [lightpink3] [r=.803922,g=.54902,b=.584314]
+\definecolor [lightpink4] [r=.545098,g=.372549,b=.396078]
+\definecolor [palevioletred1] [r=1,g=.509804,b=.670588]
+\definecolor [palevioletred2] [r=.933333,g=.47451,b=.623529]
+\definecolor [palevioletred3] [r=.803922,g=.407843,b=.537255]
+\definecolor [palevioletred4] [r=.545098,g=.278431,b=.364706]
+\definecolor [maroon1] [r=1,g=.203922,b=.701961]
+\definecolor [maroon2] [r=.933333,g=.188235,b=.654902]
+\definecolor [maroon3] [r=.803922,g=.160784,b=.564706]
+\definecolor [maroon4] [r=.545098,g=.109804,b=.384314]
+\definecolor [violetred1] [r=1,g=.243137,b=.588235]
+\definecolor [violetred2] [r=.933333,g=.227451,b=.54902]
+\definecolor [violetred3] [r=.803922,g=.196078,b=.470588]
+\definecolor [violetred4] [r=.545098,g=.133333,b=.321569]
+\definecolor [magenta1] [magenta]
+\definecolor [magenta2] [r=.933333,b=.933333]
+\definecolor [magenta3] [r=.803922,b=.803922]
+\definecolor [magenta4] [r=.545098,b=.545098]
+\definecolor [orchid1] [r=1,g=.513725,b=.980392]
+\definecolor [orchid2] [r=.933333,g=.478431,b=.913725]
+\definecolor [orchid3] [r=.803922,g=.411765,b=.788235]
+\definecolor [orchid4] [r=.545098,g=.278431,b=.537255]
+\definecolor [plum1] [r=1,g=.733333,b=1]
+\definecolor [plum2] [r=.933333,g=.682353,b=.933333]
+\definecolor [plum3] [r=.803922,g=.588235,b=.803922]
+\definecolor [plum4] [r=.545098,g=.4,b=.545098]
+\definecolor [mediumorchid1] [r=.878431,g=.4,b=1]
+\definecolor [mediumorchid2] [r=.819608,g=.372549,b=.933333]
+\definecolor [mediumorchid3] [r=.705882,g=.321569,b=.803922]
+\definecolor [mediumorchid4] [r=.478431,g=.215686,b=.545098]
+\definecolor [darkorchid1] [r=.74902,g=.243137,b=1]
+\definecolor [darkorchid2] [r=.698039,g=.227451,b=.933333]
+\definecolor [darkorchid3] [r=.603922,g=.196078,b=.803922]
+\definecolor [darkorchid4] [r=.407843,g=.133333,b=.545098]
+\definecolor [purple1] [r=.607843,g=.188235,b=1]
+\definecolor [purple2] [r=.568627,g=.172549,b=.933333]
+\definecolor [purple3] [r=.490196,g=.14902,b=.803922]
+\definecolor [purple4] [r=.333333,g=.101961,b=.545098]
+\definecolor [mediumpurple1] [r=.670588,g=.509804,b=1]
+\definecolor [mediumpurple2] [r=.623529,g=.47451,b=.933333]
+\definecolor [mediumpurple3] [r=.537255,g=.407843,b=.803922]
+\definecolor [mediumpurple4] [r=.364706,g=.278431,b=.545098]
+\definecolor [thistle1] [r=1,g=.882353,b=1]
+\definecolor [thistle2] [r=.933333,g=.823529,b=.933333]
+\definecolor [thistle3] [r=.803922,g=.709804,b=.803922]
+\definecolor [thistle4] [r=.545098,g=.482353,b=.545098]
+
+\dorecurse{100}{
+ \definecolor [gray#1] [s=\cldcontext{#1/100}]
+}
+
+\definecolor [darkgray] [s=.662745]
+\definecolor [darkblue] [b=.545098]
+\definecolor [darkcyan] [g=.545098,b=.545098]
+\definecolor [darkmagenta] [r=.545098,b=.545098]
+\definecolor [darkred] [r=.545098]
+\definecolor [lightgreen] [r=.564706,g=.933333,b=.564706]
+
+\stopprotectedcolors
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ral.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ral.mkiv
new file mode 100644
index 00000000000..e7b1a2408f4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-ral.mkiv
@@ -0,0 +1,239 @@
+%D \module
+%D [ file=colo-imp-ral,
+%D version=2009.11.13,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=RAL,
+%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
+%C details.
+
+%D RAL color system (Deutsches Institut für Gütesicherung und Kennzeichnung)
+%D approximate RGB colors (from \goto {ralcolor.com} [url(http://www.ralcolor.com)];
+%D see also \goto {ralcolors.com} [url(http://www.ralcolors.com)]). These could be
+%D good candidates for use as spot colors.
+
+\startprotectedcolors
+
+ % Deutsch English Français Español Italiano Nederlands
+
+\definecolor [RAL1000] [h=BEBD7F] % Grünbeige Green beige Beige vert Beige verdoso Beige verdastro Groenbeige
+\definecolor [RAL1001] [h=C2B078] % Beige Beige Beige Beige Beige Beige
+\definecolor [RAL1002] [h=C6A664] % Sandgelb Sand yellow Jaune sable Amarillo arena Giallo sabbia Zandgeel
+\definecolor [RAL1003] [h=E5BE01] % Signalgelb Signal yellow Jaune de sécurité Amarillo señales Giallo segnale Signaalgeel
+\definecolor [RAL1004] [h=CDA434] % Goldgelb Golden yellow Jaune or Amarillo oro Giallo oro Goudgeel
+\definecolor [RAL1005] [h=A98307] % Honiggelb Honey yellow Jaune miel Amarillo miel Giallo miele Honinggeel
+\definecolor [RAL1006] [h=E4A010] % Maisgelb Maize yellow Jaune maïs Amarillo maiz Giallo polenta Maisgeel
+\definecolor [RAL1007] [h=DC9D00] % Narzissengelb Daffodil yellow Jaune narcisse Amarillo narciso Giallo narciso Narcissengeel
+\definecolor [RAL1011] [h=8A6642] % Braunbeige Brown beige Beige brun Beige pardo Beige marrone Bruinbeige
+\definecolor [RAL1012] [h=C7B446] % Zitronengelb Lemon yellow Jaune citron Amarillo limón Giallo limone Citroengeel
+\definecolor [RAL1013] [h=EAE6CA] % Perlweiß Oyster white Blanc perlé Blanco perla Bianco perla Parelwit
+\definecolor [RAL1014] [h=E1CC4F] % Elfenbein Ivory Ivoire Marfil Avorio Ivoorkleurig
+\definecolor [RAL1015] [h=E6D690] % Hellelfenbein Light ivory Ivoire clair Marfil claro Avorio chiaro Licht ivoorkleurig
+\definecolor [RAL1016] [h=EDFF21] % Schwefelgelb Sulfur yellow Jaune soufre Amarillo azufre Giallo zolfo Zwavelgeel
+\definecolor [RAL1017] [h=F5D033] % Safrangelb Saffron yellow Jaune safran Amarillo azafrán Giallo zafferano Saffraangeel
+\definecolor [RAL1018] [h=F8F32B] % Zinkgelb Zinc yellow Jaune zinc Amarillo de zinc Giallo zinco Zinkgeel
+\definecolor [RAL1019] [h=9E9764] % Graubeige Grey beige Beige gris Beige agrisado Beige grigiastro Grijsbeige
+\definecolor [RAL1020] [h=999950] % Olivgelb Olive yellow Jaune olive Amarillo oliva Giallo olivastro Olijfgeel
+\definecolor [RAL1021] [h=F3DA0B] % Rapsgelb Rape yellow Jaune colza Amarillo colza Giallo navone Koolzaadgeel
+\definecolor [RAL1023] [h=FAD201] % Verkehrsgelb Traffic yellow Jaune signalisation Amarillo tráfico Giallo traffico Verkeersgeel
+\definecolor [RAL1024] [h=AEA04B] % Ockergelb Ochre yellow Jaune ocre Amarillo ocre Giallo ocra Okergeel
+\definecolor [RAL1026] [h=FFFF00] % Leuchtgelb Luminous yellow Jaune brillant Amarillo brillante Giallo brillante Briljantgeel
+\definecolor [RAL1027] [h=9D9101] % Currygelb Curry Jaune curry Amarillo curry Giallo curry Kerriegeel
+\definecolor [RAL1028] [h=F4A900] % Melonengelb Melon yellow Jaune melon Amarillo melón Giallo melone Meloengeel
+\definecolor [RAL1032] [h=D6AE01] % Ginstergelb Broom yellow Jaune genêt Amarillo retama Giallo scopa Bremgeel
+\definecolor [RAL1033] [h=F3A505] % Dahliengelb Dahlia yellow Jaune dahlia Amarillo dalia Giallo dahlien Dahliageel
+\definecolor [RAL1034] [h=EFA94A] % Pastellgelb Pastel yellow Jaune pastel Amarillo pastel Giallo pastello Pastelgeel
+\definecolor [RAL1035] [h=6A5D4D] % Perlbeige Pearl beige Beige nacré Beige perlado Beige perlato Parelmoergrijs
+\definecolor [RAL1036] [h=705335] % Perlgold Pearl gold Or nacré Oro perlado Oro perlato Parelmoergoud
+\definecolor [RAL1037] [h=F39F18] % Sonnengelb Sun yellow Jaune soleil Amarillo sol Giallo sole Zonnegeel
+\definecolor [RAL2000] [h=ED760E] % Gelborange Yellow orange Orangé jaune Amarillo naranja Arancio giallastro Geeloranje
+\definecolor [RAL2001] [h=C93C20] % Rotorange Red orange Orangé rouge Rojo anaranjado Arancio rossastro Roodoranje
+\definecolor [RAL2002] [h=CB2821] % Blutorange Vermilion Orangé sang Naranja sanguineo Arancio sanguigno Vermiljoen
+\definecolor [RAL2003] [h=FF7514] % Pastellorange Pastel orange Orangé pastel Naranja pálido Arancio pastello Pasteloranje
+\definecolor [RAL2004] [h=F44611] % Reinorange Pure orange Orangé pur Naranja puro Arancio puro Zuiver oranje
+\definecolor [RAL2005] [h=FF2301] % Leuchtorange Luminous orange Orangé brillant Naranja brillante Arancio brillante Briljant oranje
+\definecolor [RAL2007] [h=FFA420] % Leuchthellorange Luminous bright orange Orangé clair rillant Naranja claro brillante Arancio chiaro brillante Briljant lichtoranje
+\definecolor [RAL2008] [h=F75E25] % Hellrotorange Bright red orange Orangé rouge clair Rojo claro anaranjado Rosso arancio chiaro Licht roodoranje
+\definecolor [RAL2009] [h=F54021] % Verkehrsorange Traffic orange Orangé signalisation Naranja tráfico Arancio traffico Verkeersoranje
+\definecolor [RAL2010] [h=D84B20] % Signalorange Signal orange Orangé de sécurité Naranja señales Arancio segnale Signaaloranje
+\definecolor [RAL2011] [h=EC7C26] % Tieforange Deep orange Orangé foncé Naranja intenso Arancio profondo Dieporanje
+\definecolor [RAL2012] [h=E55137] % Lachsorange Salmon range Orangé saumon Naranja salmón Arancio salmone Zalmoranje
+\definecolor [RAL2013] [h=C35831] % Perlorange Pearl orange Orangé nacré Naranja perlado Arancio perlato Parelmoeroranje
+\definecolor [RAL3000] [h=AF2B1E] % Feuerrot Flame red Rouge feu Rojo vivo Rosso fuoco Vuurrood
+\definecolor [RAL3001] [h=A52019] % Signalrot Signal red Rouge de sécurité Rojo señales Rosso segnale Signaalrood
+\definecolor [RAL3002] [h=A2231D] % Karminrot Carmine red Rouge carmin Rojo carmin Rosso carminio Karmijnrood
+\definecolor [RAL3003] [h=9B111E] % Rubinrot Ruby red Rouge rubis Rojo rubí Rosso rubino Robijnrood
+\definecolor [RAL3004] [h=75151E] % Purpurrot Purple red Rouge pourpre Rojo purpura Rosso porpora Purperrood
+\definecolor [RAL3005] [h=5E2129] % Weinrot Wine red Rouge vin Rojo vino Rosso vino Wijnrood
+\definecolor [RAL3007] [h=412227] % Schwarzrot Black red Rouge noir Rojo negruzco Rosso nerastro Zwartrood
+\definecolor [RAL3009] [h=642424] % Oxidrot Oxide red Rouge oxyde Rojo óxido Rosso ossido Oxyderood
+\definecolor [RAL3011] [h=781F19] % Braunrot Brown red Rouge brun Rojo pardo Rosso marrone Bruinrood
+\definecolor [RAL3012] [h=C1876B] % Beigerot Beige red Rouge beige Rojo beige Rosso beige Beigerood
+\definecolor [RAL3013] [h=A12312] % Tomatenrot Tomato red Rouge tomate Rojo tomate Rosso pomodoro Tomaatrood
+\definecolor [RAL3014] [h=D36E70] % Altrosa Antique pink Vieux rose Rojo viejo Rosa antico Oudroze
+\definecolor [RAL3015] [h=EA899A] % Hellrosa Light pink Rose clair Rosa claro Rosa chiaro Lichtroze
+\definecolor [RAL3016] [h=B32821] % Korallenrot Coral red Rouge corail Rojo coral Rosso corallo Koraalrood
+\definecolor [RAL3017] [h=E63244] % Rosé Rose Rosé Rosa Rosato Bleekrood
+\definecolor [RAL3018] [h=D53032] % Erdbeerrot Strawberry red Rouge fraise Rojo fresa Rosso fragola Aardbeirood
+\definecolor [RAL3020] [h=CC0605] % Verkehrsrot Traffic red Rouge signalisation Rojo tráfico Rosso traffico Verkeersrood
+\definecolor [RAL3022] [h=D95030] % Lachsrot Salmon pink Rouge saumon Rojo salmón Rosso salmone Zalmrood
+\definecolor [RAL3024] [h=F80000] % Leuchtrot Luminous red Rouge brillant Rojo brillante Rosso brillante Briljantrood
+\definecolor [RAL3026] [h=FE0000] % Leuchthellrot Luminous bright red Rouge clair brillant Rojo claro brillante Rosso chiaro brillante
+\definecolor [RAL3027] [h=C51D34] % Himbeerrot Raspberry red Rouge framboise Rojo frambuesa Rosso lampone Framboosrood
+\definecolor [RAL3028] [h=CB3234] % Reinrot Pure red Rouge puro Rojo puro Rosso puro Zuiverrood
+\definecolor [RAL3031] [h=B32428] % Orientrot Orient red Rouge oriental Rojo oriente Rosso oriente Oriëntrood
+\definecolor [RAL3032] [h=721422] % Perlrubinrot Pearl ruby red Rouge rubis nacré Rojo rubí perlado Rosso rubino perlato Parelmoer donkerrood
+\definecolor [RAL3033] [h=B44C43] % Perlrosa Pearl pink Rose nacré Rosa perlado Rosa perlato Parelmoer lichtrood
+\definecolor [RAL4001] [h=6D3F5B] % Rotlila Red lilac Lilas rouge Rojo lila Lilla rossastro Roodlila
+\definecolor [RAL4002] [h=922B3E] % Rotviolett Red violet Violet rouge Rojo violeta Viola rossastro Roodpaars
+\definecolor [RAL4003] [h=DE4C8A] % Erikaviolett Heather violet Violet bruyère Violeta érica Viola erica Heidepaars
+\definecolor [RAL4004] [h=641C34] % Bordeauxviolett Claret violet Violet bordeaux Burdeos Viola bordeaux Bordeauxpaars
+\definecolor [RAL4005] [h=6C4675] % Blaulila Blue lilac Lilas bleu Lila azulado Lilla bluastro Blauwlila
+\definecolor [RAL4006] [h=A03472] % Verkehrspurpur Traffic purple Pourpre signalisation Púrpurá tráfico Porpora traffico Verkeerspurper
+\definecolor [RAL4007] [h=4A192C] % Purpurviolett Purple violet Violet pourpre Violeta púrpura Porpora violetto Purperviolet
+\definecolor [RAL4008] [h=924E7D] % Signalviolett Signal violet Violet de sécurité Violeta señales Violetto segnale Signaalviolet
+\definecolor [RAL4009] [h=A18594] % Pastellviolett Pastel violet Violet pastel Violeta pastel Violetto pastello Pastelviolet
+\definecolor [RAL4010] [h=CF3476] % Telemagenta Telemagenta Telemagenta Magenta tele Tele Magenta Telemagenta
+\definecolor [RAL4011] [h=8673A1] % Perlviolett Pearl violet Violet nacré Violeta perlado Violetto perlato Parelmoer donkerviolet
+\definecolor [RAL4012] [h=6C6874] % Perlbrombeer Pearl black berry Mûre nacré Morado perlado Mora perlato Parelmoer lichtviolet
+\definecolor [RAL5000] [h=354D73] % Violettblau Violet blue Bleu violet Azul violeta Blu violaceo Paarsblauw
+\definecolor [RAL5001] [h=1F3438] % Grünblau Green blue Bleu vert Azul verdoso Blu verdastro Groenblauw
+\definecolor [RAL5002] [h=20214F] % Ultramarinblau Ultramarine blue Bleu outremer Azul ultramar Blu oltremare Ultramarijnblauw
+\definecolor [RAL5003] [h=1D1E33] % Saphirblau Saphire blue Bleu saphir Azul zafiro Blu zaffiro Saffierblauw
+\definecolor [RAL5004] [h=18171C] % Schwarzblau Black blue Bleu noir Azul negruzco Blu nerastro Zwartblauw
+\definecolor [RAL5005] [h=1E2460] % Signalblau Signal blue Bleu de sécurité Azul señales Blu segnale Signaalblauw
+\definecolor [RAL5007] [h=3E5F8A] % Brillantblau Brillant blue Bleu brillant Azul brillante Blu brillante Briljantblauw
+\definecolor [RAL5008] [h=26252D] % Graublau Grey blue Bleu gris Azul grisáceo Blu grigiastro Grijsblauw
+\definecolor [RAL5009] [h=025669] % Azurblau Azure blue Bleu azur Azul azur Blu azzurro Azuurblauw
+\definecolor [RAL5010] [h=0E294B] % Enzianblau Gentian blue Bleu gentiane Azul genciana Blu genziana Gentiaanblauw
+\definecolor [RAL5011] [h=231A24] % Stahlblau Steel blue Bleu acier Azul acero Blu acciaio Staalblauw
+\definecolor [RAL5012] [h=3B83BD] % Lichtblau Light blue Bleu clair Azul luminoso Blu luce Lichtblauw
+\definecolor [RAL5013] [h=1E213D] % Kobaltblau Cobalt blue Bleu cobalt Azul cobalto Blu cobalto Kobaltblauw
+\definecolor [RAL5014] [h=606E8C] % Taubenblau Pigeon blue Bleu pigeon Azul olombino Blu colomba Duifblauw
+\definecolor [RAL5015] [h=2271B3] % Himmelblau Sky blue Bleu ciel Azul celeste Blu cielo Hemelsblauw
+\definecolor [RAL5017] [h=063971] % Verkehrsblau Traffic blue Bleu signalisation Azul tráfico Blu traffico Verkeersblauw
+\definecolor [RAL5018] [h=3F888F] % Türkisblau Turquoise blue Bleu turquoise Azul turquesa Blu turchese Turkooisblauw
+\definecolor [RAL5019] [h=1B5583] % Capriblau Capri blue Bleu capri Azul capri Blu capri Capriblauw
+\definecolor [RAL5020] [h=1D334A] % Ozeanblau Ocean blue Bleu océan Azul oceano Blu oceano Oceaanblauw
+\definecolor [RAL5021] [h=256D7B] % Wasserblau Water blue Bleu d’eau Azul agua Blu acqua Waterblauw
+\definecolor [RAL5022] [h=252850] % Nachtblau Night blue Bleu nocturne Azul noche Blu notte Nachtblauw
+\definecolor [RAL5023] [h=49678D] % Fernblau Distant blue Bleu distant Azul lejanía Blu distante Verblauw
+\definecolor [RAL5024] [h=5D9B9B] % Pastellblau Pastel blue Bleu pastel Azul pastel Blu pastello Pastelblauw
+\definecolor [RAL5025] [h=2A6478] % Perlenzian Pearl gentian blue Gentiane nacré Gencian perlado Blu genziana perlato Parelmoerblauw
+\definecolor [RAL5026] [h=102C54] % Perlnachtblau Pearl night blue Bleu nuit nacré Azul noche perlado Blu notte perlato Parelmoer nachtblauw
+\definecolor [RAL6000] [h=316650] % Patinagrün Patina green Vert patine Verde patina Verde patina Patinagroen
+\definecolor [RAL6001] [h=287233] % Smaragdgrün Emerald green Vert émeraude Verde esmeralda Verde smeraldo Smaragdgroen
+\definecolor [RAL6002] [h=2D572C] % Laubgrün Leaf green Vert feuillage Verde hoja Verde foglia Loofgroen
+\definecolor [RAL6003] [h=424632] % Olivgrün Olive green Vert olive Verde oliva Verde oliva Olijfgroen
+\definecolor [RAL6004] [h=1F3A3D] % Blaugrün Blue green Vert bleu Verde azulado Verde bluastro Blauwgroen
+\definecolor [RAL6005] [h=2F4538] % Moosgrün Moss green Vert mousse Verde musgo Verde muschio Mosgroen
+\definecolor [RAL6006] [h=3E3B32] % Grauoliv Grey olive Olive gris Oliva grisáceo Oliva grigiastro Grijs olijfgroen
+\definecolor [RAL6007] [h=343B29] % Flaschengrün Bottle green Vert bouteille Verde botella Verde bottiglia Flessegroen
+\definecolor [RAL6008] [h=39352A] % Braungrün Brown green Vert brun Verde parduzco Verde brunastro Bruingroen
+\definecolor [RAL6009] [h=31372B] % Tannengrün Fir green Vert sapin Verde abeto Verde abete Dennegroen
+\definecolor [RAL6010] [h=35682D] % Grasgrün Grass green Vert herbe Verde hierba Verde erba Grasgroen
+\definecolor [RAL6011] [h=587246] % Resedagrün Reseda green Vert réséda Verde reseda Verde reseda Resedagroen
+\definecolor [RAL6012] [h=343E40] % Schwarzgrün Black green Vert noir Verde negruzco Verde nerastro Zwartgroen
+\definecolor [RAL6013] [h=6C7156] % Schilfgrün Reed green Vert jonc Verde caña Verde canna Rietgroen
+\definecolor [RAL6014] [h=47402E] % Gelboliv Yellow olive Olive jaune Amarillo oliva Oliva giallastro Geel olijfgroen
+\definecolor [RAL6015] [h=3B3C36] % Schwarzoliv Black olive Olive noir Oliva negruzco Oliva nerastro Zwart olijfgroen
+\definecolor [RAL6016] [h=1E5945] % Türkisgrün Turquoise green Vert turquoise Verde turquesa Verde turchese Turkooisgroen
+\definecolor [RAL6017] [h=4C9141] % Maigrün May green Vert mai Verde mayo Verde maggio Meigroen
+\definecolor [RAL6018] [h=57A639] % Gelbgrün Yellow green Vert jaune Verde amarillento Verde giallastro Geelgroen
+\definecolor [RAL6019] [h=BDECB6] % Weißgrün Pastel green Vert blanc Verde lanquecino Verde biancastro Witgroen
+\definecolor [RAL6020] [h=2E3A23] % Chromoxidgrün Chrome green Vert oxyde chromique Verde cromo Verde cromo Chroomoxyde groen
+\definecolor [RAL6021] [h=89AC76] % Blassgrün Pale green Vert pâle Verde pálido Verde pallido Bleekgroen
+\definecolor [RAL6022] [h=25221B] % Braunoliv Olive drab Olive brun Oliva parduzco Oliva brunastro Bruin olijfgroen
+\definecolor [RAL6024] [h=308446] % Verkehrsgrün Traffic green Vert signalisation Verde tráfico Verde traffico Verkeersgroen
+\definecolor [RAL6025] [h=3D642D] % Farngrün Fern green Vert fougère Verde helecho Verde felce Varengroen
+\definecolor [RAL6026] [h=015D52] % Opalgrün Opal green Vert opale Verde opalo Verde opale Opaalgroen
+\definecolor [RAL6027] [h=84C3BE] % Lichtgrün Light green Vert clair Verde luminoso Verde chiaro Lichtgroen
+\definecolor [RAL6028] [h=2C5545] % Kieferngrün Pine green Vert pin Verde pino Verde pino Pijnboomgroen
+\definecolor [RAL6029] [h=20603D] % Minzgrün Mint green Vert menthe Verde menta Verde menta Mintgroen
+\definecolor [RAL6032] [h=317F43] % Signalgrün Signal green Vert de sécurité Verde señales Verde segnale Signaalgroen
+\definecolor [RAL6033] [h=497E76] % Minttürkis Mint turquoise Turquoise menthe Turquesa menta Turchese menta Mintturquoise
+\definecolor [RAL6034] [h=7FB5B5] % Pastelltürkis Pastel turquoise Turquoise pastel Turquesa pastel Turchese pastello Pastelturquoise
+\definecolor [RAL6035] [h=1C542D] % Perlgrün Pearl green Vert nacré Verde perlado Verde perlato Parelmoer donkergroen
+\definecolor [RAL6036] [h=193737] % Perlopalgrün Pearl opal green Vert opal nacré Verde ópalo perlado Verde opalo perlato Parelmoer lichtgroen
+\definecolor [RAL6037] [h=008F39] % Reingrün Pure green Vert pur Verde puro Verde puro Zuivergroen
+\definecolor [RAL6038] [h=00BB2D] % Leuchtgrün Luminous green Vert brillant Verde brillante Verde brillante Briljantgroen
+\definecolor [RAL7000] [h=78858B] % Fehgrau Squirrel grey Gris petit-gris Gris ardilla Grigio vaio Pelsgrijs
+\definecolor [RAL7001] [h=8A9597] % Silbergrau Silver grey Gris argent Gris plata Grigio argento Zilvergrijs
+\definecolor [RAL7002] [h=7E7B52] % Olivgrau Olive grey Gris olive Gris oliva Grigio olivastro Olijfgrijs
+\definecolor [RAL7003] [h=6C7059] % Moosgrau Moss grey Gris mousse Gris musgo Grigio muschio Mosgrijs
+\definecolor [RAL7004] [h=969992] % Signalgrau Signal grey Gris de sécurité Gris señales Grigio segnale Signaalgrijs
+\definecolor [RAL7005] [h=646B63] % Mausgrau Mouse grey Gris souris Gris ratón Grigio topo Muisgrijs
+\definecolor [RAL7006] [h=6D6552] % Beigegrau Beige grey Gris beige Gris beige Grigio beige Beigegrijs
+\definecolor [RAL7008] [h=6A5F31] % Khakigrau Khaki grey Gris kaki Gris caqui Grigio kaki Kakigrijs
+\definecolor [RAL7009] [h=4D5645] % Grüngrau Green grey Gris vert Gris verdoso Grigio verdastro Groengrijs
+\definecolor [RAL7010] [h=4C514A] % Zeltgrau Tarpaulin grey Gris tente Gris lona Grigio tenda Zeildoekgrijs
+\definecolor [RAL7011] [h=434B4D] % Eisengrau Iron grey Gris fer Gris hierro Grigio ferro IJzergrijs
+\definecolor [RAL7012] [h=4E5754] % Basaltgrau Basalt grey Gris basalte Gris basalto Grigio basalto Bazaltgrijs
+\definecolor [RAL7013] [h=464531] % Braungrau Brown grey Gris brun Gris parduzco Grigio brunastro Bruingrijs
+\definecolor [RAL7015] [h=434750] % Schiefergrau Slate grey Gris ardoise Gris pizarra Grigio ardesia Leigrijs
+\definecolor [RAL7016] [h=293133] % Anthrazitgrau Anthracite grey Gris anthracite Gris antracita Grigio antracite Antracietgrijs
+\definecolor [RAL7021] [h=23282B] % Schwarzgrau Black grey Gris noir Gris negruzco Grigio nerastro Zwartgrijs
+\definecolor [RAL7022] [h=332F2C] % Umbragrau Umbra grey Gris terre d’ombre Gris sombra Grigio ombra Ombergrijs
+\definecolor [RAL7023] [h=686C5E] % Betongrau Concrete grey Gris béton Gris hormigón Grigio calcestruzzo Betongrijs
+\definecolor [RAL7024] [h=474A51] % Graphitgrau Graphite grey Gris graphite Gris grafita Grigio grafite Grafietgrijs
+\definecolor [RAL7026] [h=2F353B] % Granitgrau Granite grey Gris granit Gris granito Grigio granito Granietgrijs
+\definecolor [RAL7030] [h=8B8C7A] % Steingrau Stone grey Gris pierre Gris piedra Grigio pietra Steengrijs
+\definecolor [RAL7031] [h=474B4E] % Blaugrau Blue grey Gris bleu Gris azulado Grigio bluastro Blauwgrijs
+\definecolor [RAL7032] [h=B8B799] % Kieselgrau Pebble grey Gris silex Gris guijarro Grigio ghiaia Kiezelgrijs
+\definecolor [RAL7033] [h=7D8471] % Zementgrau Cement grey Gris ciment Gris cemento Grigio cemento Cementgrijs
+\definecolor [RAL7034] [h=8F8B66] % Gelbgrau Yellow grey Gris jaune Gris amarillento Grigio giallastro Geelgrijs
+\definecolor [RAL7035] [h=D7D7D7] % Lichtgrau Light grey Gris clair Gris luminoso Grigio luce Lichtgrijs
+\definecolor [RAL7036] [h=7F7679] % Platingrau Platinum grey Gris platine Gris platino Grigio platino Platinagrijs
+\definecolor [RAL7037] [h=7D7F7D] % Staubgrau Dusty grey Gris poussière Gris polvo Grigio polvere Stofgrijs
+\definecolor [RAL7038] [h=B5B8B1] % Achatgrau Agate grey Gris agate Gris ágata Grigio agata Agaatgrijs
+\definecolor [RAL7039] [h=6C6960] % Quarzgrau Quartz grey Gris quartz Gris cuarzo Grigio quarzo Kwartsgrijs
+\definecolor [RAL7040] [h=9DA1AA] % Fenstergrau Window grey Gris fenêtre Gris ventana Grigio finestra Venstergrijs
+\definecolor [RAL7042] [h=8D948D] % Verkehrsgrau A Traffic grey A Gris signalisation A Gris tráfico A Grigio traffico A Verkeesgrijs A
+\definecolor [RAL7043] [h=4E5452] % Verkehrsgrau B Traffic grey B Gris signalisation B Gris tráfico B Grigio traffico B Verkeersgrijs B
+\definecolor [RAL7044] [h=CAC4B0] % Seidengrau Silk grey Gris soie Gris seda Grigio seta Zijdegrijs
+\definecolor [RAL7045] [h=909090] % Telegrau 1 Telegrey 1 Telegris 1 Gris tele 1 Tele grigio 1 Telegrijs 1
+\definecolor [RAL7046] [h=82898F] % Telegrau 2 Telegrey 2 Telegris 2 Gris tele 2 Tele grigio 2 Telegrijs 2
+\definecolor [RAL7047] [h=D0D0D0] % Telegrau 4 Telegrey 4 Telegris 4 Gris tele 4 Tele grigio 4 Telegrijs 4
+\definecolor [RAL7048] [h=898176] % Perlmausgrau Pearl mouse grey Gris souris nacré Gris musgo perlado Grigio topo perlato Parelmoer-muisgrijs
+\definecolor [RAL8000] [h=826C34] % Grünbraun Green brown Brun vert Pardo verdoso Marrone verdastro Groenbruin
+\definecolor [RAL8001] [h=955F20] % Ockerbraun Ochre brown Brun terre de Sienne Pardo ocre Marrone ocra Okerbruin
+\definecolor [RAL8002] [h=6C3B2A] % Signalbraun Signal brown Brun de sécurité Marrón señales Marrone segnale Signaalbruin
+\definecolor [RAL8003] [h=734222] % Lehmbraun Clay brown Brun argile Pardo arcilla Marrone fango Leembruin
+\definecolor [RAL8004] [h=8E402A] % Kupferbraun Copper brown Brun cuivré Pardo cobre Marrone rame Koperbruin
+\definecolor [RAL8007] [h=59351F] % Rehbraun Fawn brown Brun fauve Pardo corzo Marrone capriolo Reebruin
+\definecolor [RAL8008] [h=6F4F28] % Olivbraun Olive brown Brun olive Pardo oliva Marrone oliva Olijfbruin
+\definecolor [RAL8011] [h=5B3A29] % Nussbraun Nut brown Brun noisette Pardo nuez Marrone noce Notebruin
+\definecolor [RAL8012] [h=592321] % Rotbraun Red brown Brun rouge Pardo rojo Marrone rossiccio Roodbruin
+\definecolor [RAL8014] [h=382C1E] % Sepiabraun Sepia brown Brun sépia Sepia Marrone seppia Sepiabruin
+\definecolor [RAL8015] [h=633A34] % Kastanienbraun Chestnut brown Marron Castaño Marrone castagna Kastanjebruin
+\definecolor [RAL8016] [h=4C2F27] % Mahagonibraun Mahogany brown Brun acajou Caoba Marrone mogano Mahoniebruin
+\definecolor [RAL8017] [h=45322E] % Schokoladenbraun Chocolate brown Brun chocolat Chocolate Marrone cioccolata Chocoladebruin
+\definecolor [RAL8019] [h=403A3A] % Graubraun Grey brown Brun gris Pardo grisáceo Marrone grigiastro Grijsbruin
+\definecolor [RAL8022] [h=212121] % Schwarzbraun Black brown Brun noir Pardo negruzco Marrone nerastro Zwartbruin
+\definecolor [RAL8023] [h=A65E2E] % Orangebraun Orange brown Brun orangé Pardo anaranjado Marrone arancio Oranjebruin
+\definecolor [RAL8024] [h=79553D] % Beigebraun Beige brown Brun beige Pardo beige Marrone beige Beigebruin
+\definecolor [RAL8025] [h=755C48] % Blassbraun Pale brown Brun pâle Pardo pálido Marrone pallido Bleekbruin
+\definecolor [RAL8028] [h=4E3B31] % Terrabraun Terra brown Brun terre Marrón tierra Marrone terra Terrabruin
+\definecolor [RAL8029] [h=763C28] % Perlkupfer Pearl copper Cuivre nacré Cobre perlado Rame perlato Parelmoerkoper
+\definecolor [RAL9001] [h=FDF4E3] % Cremeweiß Cream Blanc crème Blanco crema Bianco crema Crèmewit
+\definecolor [RAL9002] [h=E7EBDA] % Grauweiß Grey white Blanc gris Blanco grisáceo Bianco grigiastro Grijswit
+\definecolor [RAL9003] [h=F4F4F4] % Signalweiß Signal white Blanc de sécurité Blanco señales Bianco segnale Signaalwit
+\definecolor [RAL9004] [h=282828] % Signalschwarz Signal black Noir de sécurité Negro señales Nero segnale Signaalzwart
+\definecolor [RAL9005] [h=0A0A0A] % Tiefschwarz Jet black Noir foncé Negro intenso Nero intenso Gitzwart
+\definecolor [RAL9006] [h=A5A5A5] % Weißaluminium White aluminium Aluminium blanc Aluminio blanco Aluminio brillante Blank aluminiumkleurig
+\definecolor [RAL9007] [h=8F8F8F] % Graualuminium Grey aluminium Aluminium gris Aluminio gris Aluminio grigiastro Grijs aluminiumkleurig
+\definecolor [RAL9010] [h=FFFFFF] % Reinweiß Pure white Blanc pur Blanco puro Bianco puro Zuiverwit
+\definecolor [RAL9011] [h=1C1C1C] % Graphitschwarz Graphite black Noir graphite Negro grafito Nero grafite Grafietzwart
+\definecolor [RAL9016] [h=F6F6F6] % Verkehrsweiß Traffic white Blanc signalisation Blanco tráfico Bianco traffico Verkeerswit
+\definecolor [RAL9017] [h=1E1E1E] % Verkehrsschwarz Traffic black Noir signalisation Negro tráfico Nero traffico Verkeerszwart
+\definecolor [RAL9018] [h=D7D7D7] % Papyrusweiß Papyrus white Blanc papyrus Blanco papiro Bianco papiro Papyruswit
+\definecolor [RAL9022] [h=9C9C9C] % Perlhellgrau Pearl light grey Gris clair nacré Gris claro perlado Grigio chiaro perlato Parelmoer lichtgrijs
+\definecolor [RAL9023] [h=828282] % Perldunkelgrau Pearl dark grey Gris fonçé nacré Gris oscuro perlado Grigio scuro perlato Parelmoer donkergrijs
+
+\stopprotectedcolors
+
+\endinput
+
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-rgb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-rgb.mkiv
new file mode 100644
index 00000000000..58b2ca42c2a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-rgb.mkiv
@@ -0,0 +1,337 @@
+%D \module
+%D [ file=colo-rgb,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=RGB,
+%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 Just to give users a start we define some colors. While
+%D switching fonts is as international as can be, thanks to the
+%D mnemonics, naming colors is very interface dependant. To
+%D support international setups, we define both english and
+%D interface dependant colors. We use the color inheritance
+%D mechanisms to implement the interface dependant ones.
+
+%D For historic reasons all colors are defined in \RGB\ color
+%D space and there is no reason to change this.
+
+\definecolor [red] [r=1, g=0, b=0]
+\definecolor [green] [r=0, g=1, b=0]
+\definecolor [blue] [r=0, g=0, b=1]
+
+\definecolor [cyan] [r=0, g=1, b=1]
+\definecolor [magenta] [r=1, g=0, b=1]
+\definecolor [yellow] [r=1, g=1, b=0]
+
+\definecolor [white] [s=1] % [r=1, g=1, b=1]
+\definecolor [black] [s=0]
+\definecolor [gray] [s=.9]
+
+% adapted per 2011.10.28
+
+\definecolor [lightred] [r=1, g=0, b=0]
+\definecolor [lightgreen] [r=0, g=1, b=0]
+\definecolor [lightblue] [r=0, g=0, b=1]
+\definecolor [lightcyan] [r=0, g=1, b=1]
+\definecolor [lightmagenta] [r=1, g=0, b=1]
+\definecolor [lightyellow] [r=1, g=1, b=0]
+
+\definecolor [middlered] [r=.8, g=0, b=0]
+\definecolor [middlegreen] [r=0, g=.8, b=0]
+\definecolor [middleblue] [r=0, g=0, b=.8]
+\definecolor [middlecyan] [r=0, g=.6, b=.6]
+\definecolor [middlemagenta] [r=.6, g=0, b=.6]
+\definecolor [middleyellow] [r=.6, g=.6, b=.0]
+
+\definecolor [darkred] [r=.6, g=0, b=0]
+\definecolor [darkgreen] [r=0, g=.6, b=0]
+\definecolor [darkblue] [r=0, g=0, b=.6]
+\definecolor [darkcyan] [r=0, g=.4, b=.4]
+\definecolor [darkmagenta] [r=.4, g=0, b=.4]
+\definecolor [darkyellow] [r=.4, g=.4, b=0]
+
+\definecolor [darkgray] [s=.40]
+\definecolor [middlegray] [s=.625]
+\definecolor [lightgray] [s=.85]
+
+%D These colors are mapped to interface dependant colornames.
+
+\startinterface dutch
+
+ \definecolor [rood] [red]
+ \definecolor [groen] [green]
+ \definecolor [blauw] [blue]
+
+ \definecolor [cyaan] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [geel] [yellow]
+
+ \definecolor [wit] [white]
+ \definecolor [grijs] [gray]
+ \definecolor [zwart] [black]
+
+ \definecolor [donkerrood] [darkred]
+ \definecolor [middelrood] [middlered]
+ \definecolor [lichtrood] [lightred]
+
+ \definecolor [donkergroen] [darkgreen]
+ \definecolor [middelgroen] [middlegreen]
+ \definecolor [lichtgroen] [lightgreen]
+
+ \definecolor [donkerblauw] [darkblue]
+ \definecolor [middelblauw] [middleblue]
+ \definecolor [lichtblauw] [lightblue]
+
+ \definecolor [donkercyaan] [darkcyan]
+ \definecolor [middelcyaan] [middlecyan]
+ \definecolor [lichtcyaan] [lightcyan]
+
+ \definecolor [donkermagenta] [darkmagenta]
+ \definecolor [middelmagenta] [middlemagenta]
+ \definecolor [lichtmagenta] [lightmagenta]
+
+ \definecolor [donkergeel] [darkyellow]
+ \definecolor [middelgeel] [middleyellow]
+ \definecolor [lichtgeel] [lightyellow]
+
+ \definecolor [donkergrijs] [darkgray]
+ \definecolor [middengrijs] [middlegray]
+ \definecolor [lichtgrijs] [lightgray]
+
+\stopinterface
+
+\startinterface german
+
+ \definecolor [rot] [red]
+ \definecolor [gruen] [green]
+ \definecolor [blau] [blue]
+
+ \definecolor [cyan] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [gelb] [yellow]
+
+ \definecolor [weiss] [white]
+ \definecolor [grau] [gray]
+ \definecolor [schwarz] [black]
+
+ \definecolor [dunkelrot] [darkred]
+ \definecolor [mittelrot] [middlered]
+ \definecolor [hellrot] [lightred]
+
+ \definecolor [dunkelgruen] [darkgreen]
+ \definecolor [mittelgruen] [middlegreen]
+ \definecolor [hellgruen] [lightgreen]
+
+ \definecolor [dunkelblau] [darkblue]
+ \definecolor [mittelblau] [middleblue]
+ \definecolor [hellblau] [lightblue]
+
+ \definecolor [dunkelcyan] [darkcyan]
+ \definecolor [mittelcyan] [middlecyan]
+ \definecolor [hellcyan] [lightcyan]
+
+ \definecolor [dunkelmagenta] [darkmagenta]
+ \definecolor [mittelmagenta] [middlemagenta]
+ \definecolor [hellmagenta] [lightmagenta]
+
+ \definecolor [dunkelgelb] [darkyellow]
+ \definecolor [mittelgelb] [middleyellow]
+ \definecolor [hellgelb] [lightyellow]
+
+ \definecolor [dunkelgrau] [darkgray]
+ \definecolor [mittelgrau] [middlegray]
+ \definecolor [hellgrau] [lightgray]
+
+\stopinterface
+
+\startinterface czech
+
+ \definecolor [cervena] [red]
+ \definecolor [zelena] [green]
+ \definecolor [modra] [blue]
+
+ \definecolor [azurova] [cyan]
+ \definecolor [fialova] [magenta]
+ \definecolor [zluta] [yellow]
+
+ \definecolor [bila] [white]
+ \definecolor [cerna] [black]
+
+ \definecolor [tmavecervena] [darkred]
+ \definecolor [strednecervena] [middlered]
+ \definecolor [svetlecervena] [lightred]
+
+ \definecolor [tmavezelena] [darkgreen]
+ \definecolor [strednezelena] [middlegreen]
+ \definecolor [svetlezelena] [lightgreen]
+
+ \definecolor [tmavemodra] [darkblue]
+ \definecolor [strednemodra] [middleblue]
+ \definecolor [svetlemodra] [lightblue]
+
+ \definecolor [tmaveazurova] [darkcyan]
+ \definecolor [stredneazurova] [middlecyan]
+ \definecolor [svelteazurova] [lightcyan]
+
+ \definecolor [tmavefialova] [darkmagenta]
+ \definecolor [strednefialova] [middlemagenta]
+ \definecolor [sveltefialova] [lightmagenta]
+
+ \definecolor [tmavezluta] [darkyellow]
+ \definecolor [strednezluta] [middleyellow]
+ \definecolor [sveltezluta] [lightyellow]
+
+ \definecolor [tmaveseda] [darkgray]
+ \definecolor [stredneseda] [middlegray]
+ \definecolor [svetleseda] [lightgray]
+
+\stopinterface
+
+\startinterface italian
+
+ \definecolor [rosso] [red]
+ \definecolor [verde] [green]
+ \definecolor [blu] [blue]
+
+ \definecolor [azzurro] [cyan]
+ \definecolor [turchino] [cyan]
+ \definecolor [ciano] [cyan]
+ \definecolor [cremisi] [magenta]
+ \definecolor [giallo] [yellow]
+
+ \definecolor [bianco] [white]
+ \definecolor [grigio] [gray]
+ \definecolor [nero] [black]
+
+ \definecolor [rossoscuro] [darkred]
+ \definecolor [rossomedio] [middlered]
+ \definecolor [rossochiaro] [lightred]
+
+ \definecolor [verdescuro] [darkgreen]
+ \definecolor [verdemedio] [middlegreen]
+ \definecolor [verdechiaro] [lightgreen]
+
+ \definecolor [bluscuro] [darkblue]
+ \definecolor [blumedio] [middleblue]
+ \definecolor [bluchiaro] [lightblue]
+
+ \definecolor [azzurroscuro] [darkcyan]
+ \definecolor [azzurromedio] [middlecyan]
+ \definecolor [azzurrochiaro] [lightcyan]
+
+ \definecolor [cremisiscuro] [darkmagenta]
+ \definecolor [cremisimedio] [middlemagenta]
+ \definecolor [cremisichiaro] [lightmagenta]
+
+ \definecolor [gialloscuro] [darkyellow]
+ \definecolor [giallomedio] [middleyellow]
+ \definecolor [giallochiaro] [lightyellow]
+
+ \definecolor [grigioscuro] [darkgray]
+ \definecolor [grigiomedio] [middlegray]
+ \definecolor [grigiochiaro] [lightgray]
+
+\stopinterface
+
+\startinterface french
+
+ \definecolor [rouge] [red]
+ \definecolor [vert] [green]
+ \definecolor [bleu] [blue]
+
+ \definecolor [cyan] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [jaune] [yellow]
+
+ \definecolor [blanche] [white]
+ \definecolor [gris] [gray]
+ \definecolor [noir] [black]
+
+ \definecolor [rougefoncé] [darkred]
+ \definecolor [rougemoyen] [middlered]
+ \definecolor [rougeclair] [lightred]
+
+ \definecolor [vertfoncé] [darkgreen]
+ \definecolor [vertmoyen] [middlegreen]
+ \definecolor [vertclair] [lightgreen]
+
+ \definecolor [bleufoncé] [darkblue]
+ \definecolor [bleumoyen] [middleblue]
+ \definecolor [bleuclair] [lightblue]
+
+ \definecolor [cyanfoncé] [darkcyan]
+ \definecolor [cyanmoyen] [middlecyan]
+ \definecolor [cyanclair] [lightcyan]
+
+ \definecolor [magentafoncé] [darkmagenta]
+ \definecolor [magentamoyen] [middlemagenta]
+ \definecolor [magentaclair] [lightmagenta]
+
+ \definecolor [jaunefoncé] [darkyellow]
+ \definecolor [jaunemoyen] [middleyellow]
+ \definecolor [jauneclair] [lightyellow]
+
+ \definecolor [grisfoncé] [darkgray]
+ \definecolor [grismoyen] [middlegray]
+ \definecolor [grisclair] [lightgray]
+
+\stopinterface
+
+\startinterface romanian
+
+ \definecolor [rosu] [red]
+ \definecolor [verde] [green]
+ \definecolor [albastru] [blue]
+
+ \definecolor [cian] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [galben] [yellow]
+
+ \definecolor [alb] [white]
+ \definecolor [gri] [gray]
+ \definecolor [negru] [black]
+
+ \definecolor [rosuinchis] [darkred]
+ \definecolor [rosumediu] [middlered]
+ \definecolor [rosudeschis] [lightred]
+
+ \definecolor [verdeinchis] [darkgreen]
+ \definecolor [verdemediu] [middlegreen]
+ \definecolor [verdedeschis] [lightgreen]
+
+ \definecolor [albastruinchis] [darkblue]
+ \definecolor [albastrumediu] [middleblue]
+ \definecolor [albastrudeschis] [lightblue]
+
+ \definecolor [cianinchis] [darkcyan]
+ \definecolor [cianmediu] [middlecyan]
+ \definecolor [ciandeschis] [lightcyan]
+
+ \definecolor [magentainchis] [darkmagenta]
+ \definecolor [magentamediu] [middlemagenta]
+ \definecolor [magentadeschis] [lightmagenta]
+
+ \definecolor [galbeninchis] [darkyellow]
+ \definecolor [galbenmediu] [middleyellow]
+ \definecolor [galbendeschis] [lightyellow]
+
+ \definecolor [griinchis] [darkgray]
+ \definecolor [grimediu] [middlegray]
+ \definecolor [grideschis] [lightgray]
+
+\stopinterface
+
+%D Bonus (needed for FO test):
+
+\definecolor [orange] [r=1, g=.5]
+\definecolor [lightorange] [r=1, g=.5]
+\definecolor [middleorange] [r=.6,g=.3]
+\definecolor [darkorange] [r=.4,g=.2]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-x11.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-x11.mkiv
new file mode 100644
index 00000000000..98a71354d2f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-x11.mkiv
@@ -0,0 +1,478 @@
+%D \module
+%D [ file=colo-imp-x11,
+%D version=2009.11.13,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=X11,
+%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
+%C details.
+
+%D Standard X11 rgb colors (from, e.g. \type {/usr/share/X11/rgb.txt}).
+%D Note that we have dropped the \quote{grey} spelling variants.
+
+\startprotectedcolors
+
+\definecolor [snow] [h=fffafa]
+\definecolor [ghostwhite] [h=f8f8ff]
+\definecolor [whitesmoke] [s=0.96]
+\definecolor [gainsboro] [s=0.86]
+\definecolor [floralwhite] [h=fffaf0]
+\definecolor [oldlace] [h=fdf5e6]
+\definecolor [linen] [h=faf0e6]
+\definecolor [antiquewhite] [h=faebd7]
+\definecolor [papayawhip] [h=ffefd5]
+\definecolor [blanchedalmond] [h=ffebcd]
+\definecolor [bisque] [h=ffe4c4]
+\definecolor [peachpuff] [h=ffdab9]
+\definecolor [navajowhite] [h=ffdead]
+\definecolor [moccasin] [h=ffe4b5]
+\definecolor [cornsilk] [h=fff8dc]
+\definecolor [ivory] [h=fffff0]
+\definecolor [lemonchiffon] [h=fffacd]
+\definecolor [seashell] [h=fff5ee]
+\definecolor [honeydew] [h=f0fff0]
+\definecolor [mintcream] [h=f5fffa]
+\definecolor [azure] [h=f0ffff]
+\definecolor [aliceblue] [h=f0f8ff]
+\definecolor [lavender] [h=e6e6fa]
+\definecolor [lavenderblush] [h=fff0f5]
+\definecolor [mistyrose] [h=ffe4e1]
+\definecolor [white] [s=1]
+\definecolor [black] [s=0]
+\definecolor [darkslategray] [h=2f4f4f]
+\definecolor [dimgray] [s=0.41]
+\definecolor [slategray] [h=708090]
+\definecolor [lightslategray] [h=778899]
+\definecolor [gray] [s=0.75]
+\definecolor [lightgray] [s=0.83]
+\definecolor [midnightblue] [h=191970]
+\definecolor [navy] [h=000080]
+\definecolor [navyblue] [h=000080]
+\definecolor [cornflowerblue] [h=6495ed]
+\definecolor [darkslateblue] [h=483d8b]
+\definecolor [slateblue] [h=6a5acd]
+\definecolor [mediumslateblue] [h=7b68ee]
+\definecolor [lightslateblue] [h=8470ff]
+\definecolor [mediumblue] [h=0000cd]
+\definecolor [royalblue] [h=4169e1]
+\definecolor [blue] [h=0000ff]
+\definecolor [dodgerblue] [h=1e90ff]
+\definecolor [deepskyblue] [h=00bfff]
+\definecolor [skyblue] [h=87ceeb]
+\definecolor [lightskyblue] [h=87cefa]
+\definecolor [steelblue] [h=4682b4]
+\definecolor [lightsteelblue] [h=b0c4de]
+\definecolor [lightblue] [h=add8e6]
+\definecolor [powderblue] [h=b0e0e6]
+\definecolor [paleturquoise] [h=afeeee]
+\definecolor [darkturquoise] [h=00ced1]
+\definecolor [mediumturquoise] [h=48d1cc]
+\definecolor [turquoise] [h=40e0d0]
+\definecolor [cyan] [h=00ffff]
+\definecolor [lightcyan] [h=e0ffff]
+\definecolor [cadetblue] [h=5f9ea0]
+\definecolor [mediumaquamarine] [h=66cdaa]
+\definecolor [aquamarine] [h=7fffd4]
+\definecolor [darkgreen] [h=006400]
+\definecolor [darkolivegreen] [h=556b2f]
+\definecolor [darkseagreen] [h=8fbc8f]
+\definecolor [seagreen] [h=2e8b57]
+\definecolor [mediumseagreen] [h=3cb371]
+\definecolor [lightseagreen] [h=20b2aa]
+\definecolor [palegreen] [h=98fb98]
+\definecolor [springgreen] [h=00ff7f]
+\definecolor [lawngreen] [h=7cfc00]
+\definecolor [green] [h=00ff00]
+\definecolor [chartreuse] [h=7fff00]
+\definecolor [mediumspringgreen] [h=00fa9a]
+\definecolor [greenyellow] [h=adff2f]
+\definecolor [limegreen] [h=32cd32]
+\definecolor [yellowgreen] [h=9acd32]
+\definecolor [forestgreen] [h=228b22]
+\definecolor [olivedrab] [h=6b8e23]
+\definecolor [darkkhaki] [h=bdb76b]
+\definecolor [khaki] [h=f0e68c]
+\definecolor [palegoldenrod] [h=eee8aa]
+\definecolor [lightgoldenrodyellow] [h=fafad2]
+\definecolor [lightyellow] [h=ffffe0]
+\definecolor [yellow] [h=ffff00]
+\definecolor [gold] [h=ffd700]
+\definecolor [lightgoldenrod] [h=eedd82]
+\definecolor [goldenrod] [h=daa520]
+\definecolor [darkgoldenrod] [h=b8860b]
+\definecolor [rosybrown] [h=bc8f8f]
+\definecolor [indianred] [h=cd5c5c]
+\definecolor [saddlebrown] [h=8b4513]
+\definecolor [sienna] [h=a0522d]
+\definecolor [peru] [h=cd853f]
+\definecolor [burlywood] [h=deb887]
+\definecolor [beige] [h=f5f5dc]
+\definecolor [wheat] [h=f5deb3]
+\definecolor [sandybrown] [h=f4a460]
+\definecolor [tan] [h=d2b48c]
+\definecolor [chocolate] [h=d2691e]
+\definecolor [firebrick] [h=b22222]
+\definecolor [brown] [h=a52a2a]
+\definecolor [darksalmon] [h=e9967a]
+\definecolor [salmon] [h=fa8072]
+\definecolor [lightsalmon] [h=ffa07a]
+\definecolor [orange] [h=ffa500]
+\definecolor [darkorange] [h=ff8c00]
+\definecolor [coral] [h=ff7f50]
+\definecolor [lightcoral] [h=f08080]
+\definecolor [tomato] [h=ff6347]
+\definecolor [orangered] [h=ff4500]
+\definecolor [red] [h=ff0000]
+\definecolor [hotpink] [h=ff69b4]
+\definecolor [deeppink] [h=ff1493]
+\definecolor [pink] [h=ffc0cb]
+\definecolor [lightpink] [h=ffb6c1]
+\definecolor [palevioletred] [h=db7093]
+\definecolor [maroon] [h=b03060]
+\definecolor [mediumvioletred] [h=c71585]
+\definecolor [violetred] [h=d02090]
+\definecolor [magenta] [h=ff00ff]
+\definecolor [violet] [h=ee82ee]
+\definecolor [plum] [h=dda0dd]
+\definecolor [orchid] [h=da70d6]
+\definecolor [mediumorchid] [h=ba55d3]
+\definecolor [darkorchid] [h=9932cc]
+\definecolor [darkviolet] [h=9400d3]
+\definecolor [blueviolet] [h=8a2be2]
+\definecolor [purple] [h=a020f0]
+\definecolor [mediumpurple] [h=9370db]
+\definecolor [thistle] [h=d8bfd8]
+\definecolor [snow1] [h=fffafa]
+\definecolor [snow2] [h=eee9e9]
+\definecolor [snow3] [h=cdc9c9]
+\definecolor [snow4] [h=8b8989]
+\definecolor [seashell1] [h=fff5ee]
+\definecolor [seashell2] [h=eee5de]
+\definecolor [seashell3] [h=cdc5bf]
+\definecolor [seashell4] [h=8b8682]
+\definecolor [antiquewhite1] [h=ffefdb]
+\definecolor [antiquewhite2] [h=eedfcc]
+\definecolor [antiquewhite3] [h=cdc0b0]
+\definecolor [antiquewhite4] [h=8b8378]
+\definecolor [bisque1] [h=ffe4c4]
+\definecolor [bisque2] [h=eed5b7]
+\definecolor [bisque3] [h=cdb79e]
+\definecolor [bisque4] [h=8b7d6b]
+\definecolor [peachpuff1] [h=ffdab9]
+\definecolor [peachpuff2] [h=eecbad]
+\definecolor [peachpuff3] [h=cdaf95]
+\definecolor [peachpuff4] [h=8b7765]
+\definecolor [navajowhite1] [h=ffdead]
+\definecolor [navajowhite2] [h=eecfa1]
+\definecolor [navajowhite3] [h=cdb38b]
+\definecolor [navajowhite4] [h=8b795e]
+\definecolor [lemonchiffon1] [h=fffacd]
+\definecolor [lemonchiffon2] [h=eee9bf]
+\definecolor [lemonchiffon3] [h=cdc9a5]
+\definecolor [lemonchiffon4] [h=8b8970]
+\definecolor [cornsilk1] [h=fff8dc]
+\definecolor [cornsilk2] [h=eee8cd]
+\definecolor [cornsilk3] [h=cdc8b1]
+\definecolor [cornsilk4] [h=8b8878]
+\definecolor [ivory1] [h=fffff0]
+\definecolor [ivory2] [h=eeeee0]
+\definecolor [ivory3] [h=cdcdc1]
+\definecolor [ivory4] [h=8b8b83]
+\definecolor [honeydew1] [h=f0fff0]
+\definecolor [honeydew2] [h=e0eee0]
+\definecolor [honeydew3] [h=c1cdc1]
+\definecolor [honeydew4] [h=838b83]
+\definecolor [lavenderblush1] [h=fff0f5]
+\definecolor [lavenderblush2] [h=eee0e5]
+\definecolor [lavenderblush3] [h=cdc1c5]
+\definecolor [lavenderblush4] [h=8b8386]
+\definecolor [mistyrose1] [h=ffe4e1]
+\definecolor [mistyrose2] [h=eed5d2]
+\definecolor [mistyrose3] [h=cdb7b5]
+\definecolor [mistyrose4] [h=8b7d7b]
+\definecolor [azure1] [h=f0ffff]
+\definecolor [azure2] [h=e0eeee]
+\definecolor [azure3] [h=c1cdcd]
+\definecolor [azure4] [h=838b8b]
+\definecolor [slateblue1] [h=836fff]
+\definecolor [slateblue2] [h=7a67ee]
+\definecolor [slateblue3] [h=6959cd]
+\definecolor [slateblue4] [h=473c8b]
+\definecolor [royalblue1] [h=4876ff]
+\definecolor [royalblue2] [h=436eee]
+\definecolor [royalblue3] [h=3a5fcd]
+\definecolor [royalblue4] [h=27408b]
+\definecolor [blue1] [h=0000ff]
+\definecolor [blue2] [h=0000ee]
+\definecolor [blue3] [h=0000cd]
+\definecolor [blue4] [h=00008b]
+\definecolor [dodgerblue1] [h=1e90ff]
+\definecolor [dodgerblue2] [h=1c86ee]
+\definecolor [dodgerblue3] [h=1874cd]
+\definecolor [dodgerblue4] [h=104e8b]
+\definecolor [steelblue1] [h=63b8ff]
+\definecolor [steelblue2] [h=5cacee]
+\definecolor [steelblue3] [h=4f94cd]
+\definecolor [steelblue4] [h=36648b]
+\definecolor [deepskyblue1] [h=00bfff]
+\definecolor [deepskyblue2] [h=00b2ee]
+\definecolor [deepskyblue3] [h=009acd]
+\definecolor [deepskyblue4] [h=00688b]
+\definecolor [skyblue1] [h=87ceff]
+\definecolor [skyblue2] [h=7ec0ee]
+\definecolor [skyblue3] [h=6ca6cd]
+\definecolor [skyblue4] [h=4a708b]
+\definecolor [lightskyblue1] [h=b0e2ff]
+\definecolor [lightskyblue2] [h=a4d3ee]
+\definecolor [lightskyblue3] [h=8db6cd]
+\definecolor [lightskyblue4] [h=607b8b]
+\definecolor [slategray1] [h=c6e2ff]
+\definecolor [slategray2] [h=b9d3ee]
+\definecolor [slategray3] [h=9fb6cd]
+\definecolor [slategray4] [h=6c7b8b]
+\definecolor [lightsteelblue1] [h=cae1ff]
+\definecolor [lightsteelblue2] [h=bcd2ee]
+\definecolor [lightsteelblue3] [h=a2b5cd]
+\definecolor [lightsteelblue4] [h=6e7b8b]
+\definecolor [lightblue1] [h=bfefff]
+\definecolor [lightblue2] [h=b2dfee]
+\definecolor [lightblue3] [h=9ac0cd]
+\definecolor [lightblue4] [h=68838b]
+\definecolor [lightcyan1] [h=e0ffff]
+\definecolor [lightcyan2] [h=d1eeee]
+\definecolor [lightcyan3] [h=b4cdcd]
+\definecolor [lightcyan4] [h=7a8b8b]
+\definecolor [paleturquoise1] [h=bbffff]
+\definecolor [paleturquoise2] [h=aeeeee]
+\definecolor [paleturquoise3] [h=96cdcd]
+\definecolor [paleturquoise4] [h=668b8b]
+\definecolor [cadetblue1] [h=98f5ff]
+\definecolor [cadetblue2] [h=8ee5ee]
+\definecolor [cadetblue3] [h=7ac5cd]
+\definecolor [cadetblue4] [h=53868b]
+\definecolor [turquoise1] [h=00f5ff]
+\definecolor [turquoise2] [h=00e5ee]
+\definecolor [turquoise3] [h=00c5cd]
+\definecolor [turquoise4] [h=00868b]
+\definecolor [cyan1] [h=00ffff]
+\definecolor [cyan2] [h=00eeee]
+\definecolor [cyan3] [h=00cdcd]
+\definecolor [cyan4] [h=008b8b]
+\definecolor [darkslategray1] [h=97ffff]
+\definecolor [darkslategray2] [h=8deeee]
+\definecolor [darkslategray3] [h=79cdcd]
+\definecolor [darkslategray4] [h=528b8b]
+\definecolor [aquamarine1] [h=7fffd4]
+\definecolor [aquamarine2] [h=76eec6]
+\definecolor [aquamarine3] [h=66cdaa]
+\definecolor [aquamarine4] [h=458b74]
+\definecolor [darkseagreen1] [h=c1ffc1]
+\definecolor [darkseagreen2] [h=b4eeb4]
+\definecolor [darkseagreen3] [h=9bcd9b]
+\definecolor [darkseagreen4] [h=698b69]
+\definecolor [seagreen1] [h=54ff9f]
+\definecolor [seagreen2] [h=4eee94]
+\definecolor [seagreen3] [h=43cd80]
+\definecolor [seagreen4] [h=2e8b57]
+\definecolor [palegreen1] [h=9aff9a]
+\definecolor [palegreen2] [h=90ee90]
+\definecolor [palegreen3] [h=7ccd7c]
+\definecolor [palegreen4] [h=548b54]
+\definecolor [springgreen1] [h=00ff7f]
+\definecolor [springgreen2] [h=00ee76]
+\definecolor [springgreen3] [h=00cd66]
+\definecolor [springgreen4] [h=008b45]
+\definecolor [green1] [h=00ff00]
+\definecolor [green2] [h=00ee00]
+\definecolor [green3] [h=00cd00]
+\definecolor [green4] [h=008b00]
+\definecolor [chartreuse1] [h=7fff00]
+\definecolor [chartreuse2] [h=76ee00]
+\definecolor [chartreuse3] [h=66cd00]
+\definecolor [chartreuse4] [h=458b00]
+\definecolor [olivedrab1] [h=c0ff3e]
+\definecolor [olivedrab2] [h=b3ee3a]
+\definecolor [olivedrab3] [h=9acd32]
+\definecolor [olivedrab4] [h=698b22]
+\definecolor [darkolivegreen1] [h=caff70]
+\definecolor [darkolivegreen2] [h=bcee68]
+\definecolor [darkolivegreen3] [h=a2cd5a]
+\definecolor [darkolivegreen4] [h=6e8b3d]
+\definecolor [khaki1] [h=fff68f]
+\definecolor [khaki2] [h=eee685]
+\definecolor [khaki3] [h=cdc673]
+\definecolor [khaki4] [h=8b864e]
+\definecolor [lightgoldenrod1] [h=ffec8b]
+\definecolor [lightgoldenrod2] [h=eedc82]
+\definecolor [lightgoldenrod3] [h=cdbe70]
+\definecolor [lightgoldenrod4] [h=8b814c]
+\definecolor [lightyellow1] [h=ffffe0]
+\definecolor [lightyellow2] [h=eeeed1]
+\definecolor [lightyellow3] [h=cdcdb4]
+\definecolor [lightyellow4] [h=8b8b7a]
+\definecolor [yellow1] [h=ffff00]
+\definecolor [yellow2] [h=eeee00]
+\definecolor [yellow3] [h=cdcd00]
+\definecolor [yellow4] [h=8b8b00]
+\definecolor [gold1] [h=ffd700]
+\definecolor [gold2] [h=eec900]
+\definecolor [gold3] [h=cdad00]
+\definecolor [gold4] [h=8b7500]
+\definecolor [goldenrod1] [h=ffc125]
+\definecolor [goldenrod2] [h=eeb422]
+\definecolor [goldenrod3] [h=cd9b1d]
+\definecolor [goldenrod4] [h=8b6914]
+\definecolor [darkgoldenrod1] [h=ffb90f]
+\definecolor [darkgoldenrod2] [h=eead0e]
+\definecolor [darkgoldenrod3] [h=cd950c]
+\definecolor [darkgoldenrod4] [h=8b6508]
+\definecolor [rosybrown1] [h=ffc1c1]
+\definecolor [rosybrown2] [h=eeb4b4]
+\definecolor [rosybrown3] [h=cd9b9b]
+\definecolor [rosybrown4] [h=8b6969]
+\definecolor [indianred1] [h=ff6a6a]
+\definecolor [indianred2] [h=ee6363]
+\definecolor [indianred3] [h=cd5555]
+\definecolor [indianred4] [h=8b3a3a]
+\definecolor [sienna1] [h=ff8247]
+\definecolor [sienna2] [h=ee7942]
+\definecolor [sienna3] [h=cd6839]
+\definecolor [sienna4] [h=8b4726]
+\definecolor [burlywood1] [h=ffd39b]
+\definecolor [burlywood2] [h=eec591]
+\definecolor [burlywood3] [h=cdaa7d]
+\definecolor [burlywood4] [h=8b7355]
+\definecolor [wheat1] [h=ffe7ba]
+\definecolor [wheat2] [h=eed8ae]
+\definecolor [wheat3] [h=cdba96]
+\definecolor [wheat4] [h=8b7e66]
+\definecolor [tan1] [h=ffa54f]
+\definecolor [tan2] [h=ee9a49]
+\definecolor [tan3] [h=cd853f]
+\definecolor [tan4] [h=8b5a2b]
+\definecolor [chocolate1] [h=ff7f24]
+\definecolor [chocolate2] [h=ee7621]
+\definecolor [chocolate3] [h=cd661d]
+\definecolor [chocolate4] [h=8b4513]
+\definecolor [firebrick1] [h=ff3030]
+\definecolor [firebrick2] [h=ee2c2c]
+\definecolor [firebrick3] [h=cd2626]
+\definecolor [firebrick4] [h=8b1a1a]
+\definecolor [brown1] [h=ff4040]
+\definecolor [brown2] [h=ee3b3b]
+\definecolor [brown3] [h=cd3333]
+\definecolor [brown4] [h=8b2323]
+\definecolor [salmon1] [h=ff8c69]
+\definecolor [salmon2] [h=ee8262]
+\definecolor [salmon3] [h=cd7054]
+\definecolor [salmon4] [h=8b4c39]
+\definecolor [lightsalmon1] [h=ffa07a]
+\definecolor [lightsalmon2] [h=ee9572]
+\definecolor [lightsalmon3] [h=cd8162]
+\definecolor [lightsalmon4] [h=8b5742]
+\definecolor [orange1] [h=ffa500]
+\definecolor [orange2] [h=ee9a00]
+\definecolor [orange3] [h=cd8500]
+\definecolor [orange4] [h=8b5a00]
+\definecolor [darkorange1] [h=ff7f00]
+\definecolor [darkorange2] [h=ee7600]
+\definecolor [darkorange3] [h=cd6600]
+\definecolor [darkorange4] [h=8b4500]
+\definecolor [coral1] [h=ff7256]
+\definecolor [coral2] [h=ee6a50]
+\definecolor [coral3] [h=cd5b45]
+\definecolor [coral4] [h=8b3e2f]
+\definecolor [tomato1] [h=ff6347]
+\definecolor [tomato2] [h=ee5c42]
+\definecolor [tomato3] [h=cd4f39]
+\definecolor [tomato4] [h=8b3626]
+\definecolor [orangered1] [h=ff4500]
+\definecolor [orangered2] [h=ee4000]
+\definecolor [orangered3] [h=cd3700]
+\definecolor [orangered4] [h=8b2500]
+\definecolor [red1] [h=ff0000]
+\definecolor [red2] [h=ee0000]
+\definecolor [red3] [h=cd0000]
+\definecolor [red4] [h=8b0000]
+\definecolor [debianred] [h=d70751]
+\definecolor [deeppink1] [h=ff1493]
+\definecolor [deeppink2] [h=ee1289]
+\definecolor [deeppink3] [h=cd1076]
+\definecolor [deeppink4] [h=8b0a50]
+\definecolor [hotpink1] [h=ff6eb4]
+\definecolor [hotpink2] [h=ee6aa7]
+\definecolor [hotpink3] [h=cd6090]
+\definecolor [hotpink4] [h=8b3a62]
+\definecolor [pink1] [h=ffb5c5]
+\definecolor [pink2] [h=eea9b8]
+\definecolor [pink3] [h=cd919e]
+\definecolor [pink4] [h=8b636c]
+\definecolor [lightpink1] [h=ffaeb9]
+\definecolor [lightpink2] [h=eea2ad]
+\definecolor [lightpink3] [h=cd8c95]
+\definecolor [lightpink4] [h=8b5f65]
+\definecolor [palevioletred1] [h=ff82ab]
+\definecolor [palevioletred2] [h=ee799f]
+\definecolor [palevioletred3] [h=cd6889]
+\definecolor [palevioletred4] [h=8b475d]
+\definecolor [maroon1] [h=ff34b3]
+\definecolor [maroon2] [h=ee30a7]
+\definecolor [maroon3] [h=cd2990]
+\definecolor [maroon4] [h=8b1c62]
+\definecolor [violetred1] [h=ff3e96]
+\definecolor [violetred2] [h=ee3a8c]
+\definecolor [violetred3] [h=cd3278]
+\definecolor [violetred4] [h=8b2252]
+\definecolor [magenta1] [h=ff00ff]
+\definecolor [magenta2] [h=ee00ee]
+\definecolor [magenta3] [h=cd00cd]
+\definecolor [magenta4] [h=8b008b]
+\definecolor [orchid1] [h=ff83fa]
+\definecolor [orchid2] [h=ee7ae9]
+\definecolor [orchid3] [h=cd69c9]
+\definecolor [orchid4] [h=8b4789]
+\definecolor [plum1] [h=ffbbff]
+\definecolor [plum2] [h=eeaeee]
+\definecolor [plum3] [h=cd96cd]
+\definecolor [plum4] [h=8b668b]
+\definecolor [mediumorchid1] [h=e066ff]
+\definecolor [mediumorchid2] [h=d15fee]
+\definecolor [mediumorchid3] [h=b452cd]
+\definecolor [mediumorchid4] [h=7a378b]
+\definecolor [darkorchid1] [h=bf3eff]
+\definecolor [darkorchid2] [h=b23aee]
+\definecolor [darkorchid3] [h=9a32cd]
+\definecolor [darkorchid4] [h=68228b]
+\definecolor [purple1] [h=9b30ff]
+\definecolor [purple2] [h=912cee]
+\definecolor [purple3] [h=7d26cd]
+\definecolor [purple4] [h=551a8b]
+\definecolor [mediumpurple1] [h=ab82ff]
+\definecolor [mediumpurple2] [h=9f79ee]
+\definecolor [mediumpurple3] [h=8968cd]
+\definecolor [mediumpurple4] [h=5d478b]
+\definecolor [thistle1] [h=ffe1ff]
+\definecolor [thistle2] [h=eed2ee]
+\definecolor [thistle3] [h=cdb5cd]
+\definecolor [thistle4] [h=8b7b8b]
+
+% A lot of useless grays (since one can always specify \color[s=.XX]:
+
+\dostepwiserecurse{0}{100}{1}{
+ \definecolor [gray#1] [s=\cldcontext{#1/100}]
+}
+
+% These were missing in the original specification, but were added later:
+
+\definecolor [darkgray] [s=0.66]
+\definecolor [darkblue] [h=00008b]
+\definecolor [darkcyan] [h=008b8b]
+\definecolor [darkmagenta] [h=8b008b]
+\definecolor [darkred] [h=8b0000]
+\definecolor [lightgreen] [h=90ee90]
+
+\stopprotectedcolors
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-xwi.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-xwi.mkiv
new file mode 100644
index 00000000000..57fe7965b7e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-xwi.mkiv
@@ -0,0 +1,146 @@
+%D \module
+%D [ file=colo-xwi,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=X Windows,
+%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 I've forgotten where I got these definitions from, but maybe
+%D they can be of use.
+
+\startprotectedcolors
+
+\definecolor [aliceblue] [r=0.94,g=0.97,b=1.00]
+\definecolor [antiquewhite] [r=0.98,g=0.92,b=0.84]
+\definecolor [aquamarine] [r=0.50,g=1.00,b=0.83]
+\definecolor [azure] [r=0.94,g=1.00,b=1.00]
+\definecolor [beige] [r=0.96,g=0.96,b=0.86]
+\definecolor [bisque] [r=1.00,g=0.89,b=0.77]
+\definecolor [black] [s=0] % [r=0.00,g=0.00,b=0.00]
+\definecolor [blanchedalmond] [r=1.00,g=0.92,b=0.80]
+\definecolor [blue] [r=0.00,g=0.00,b=1.00]
+\definecolor [blueviolet] [r=0.54,g=0.17,b=0.89]
+\definecolor [brown] [r=0.65,g=0.16,b=0.16]
+\definecolor [burlywood] [r=0.87,g=0.72,b=0.53]
+\definecolor [cadetblue] [r=0.37,g=0.62,b=0.63]
+\definecolor [chartreuse] [r=0.50,g=1.00,b=0.00]
+\definecolor [chocolate] [r=0.82,g=0.41,b=0.12]
+\definecolor [coral] [r=1.00,g=0.50,b=0.31]
+\definecolor [cornflowerblue] [r=0.39,g=0.58,b=0.93]
+\definecolor [cornsilk] [r=1.00,g=0.97,b=0.86]
+\definecolor [cyan] [r=0.00,g=1.00,b=1.00]
+\definecolor [darkgoldenrod] [r=0.72,g=0.53,b=0.04]
+\definecolor [darkgreen] [r=0.00,g=0.39,b=0.00]
+\definecolor [darkkhaki] [r=0.74,g=0.72,b=0.42]
+\definecolor [darkolivegreen] [r=0.33,g=0.42,b=0.18]
+\definecolor [darkorange] [r=1.00,g=0.55,b=0.00]
+\definecolor [darkorchid] [r=0.60,g=0.20,b=0.80]
+\definecolor [darksalmon] [r=0.91,g=0.59,b=0.48]
+\definecolor [darkseagreen] [r=0.56,g=0.74,b=0.56]
+\definecolor [darkslateblue] [r=0.28,g=0.24,b=0.55]
+\definecolor [darkturquoise] [r=0.00,g=0.81,b=0.82]
+\definecolor [darkviolet] [r=0.58,g=0.00,b=0.83]
+\definecolor [deeppink] [r=1.00,g=0.08,b=0.58]
+\definecolor [deepskyblue] [r=0.00,g=0.75,b=1.00]
+\definecolor [dodgerblue] [r=0.12,g=0.56,b=1.00]
+\definecolor [firebrick] [r=0.70,g=0.13,b=0.13]
+\definecolor [floralwhite] [r=1.00,g=0.98,b=0.94]
+\definecolor [forestgreen] [r=0.13,g=0.55,b=0.13]
+\definecolor [gainsboro] [r=0.86,g=0.86,b=0.86]
+\definecolor [ghostwhite] [r=0.97,g=0.97,b=1.00]
+\definecolor [gold] [r=1.00,g=0.84,b=0.00]
+\definecolor [goldenrod] [r=0.85,g=0.65,b=0.13]
+\definecolor [green] [r=0.00,g=1.00,b=0.00]
+\definecolor [greenyellow] [r=0.68,g=1.00,b=0.18]
+\definecolor [honeydew] [r=0.94,g=1.00,b=0.94]
+\definecolor [hotpink] [r=1.00,g=0.41,b=0.71]
+\definecolor [indianred] [r=0.80,g=0.36,b=0.36]
+\definecolor [ivory] [r=1.00,g=1.00,b=0.94]
+\definecolor [khaki] [r=0.94,g=0.90,b=0.55]
+\definecolor [lavender] [r=0.90,g=0.90,b=0.98]
+\definecolor [lavenderblush] [r=1.00,g=0.94,b=0.96]
+\definecolor [lawngreen] [r=0.49,g=0.99,b=0.00]
+\definecolor [lemonchiffon] [r=1.00,g=0.98,b=0.80]
+\definecolor [lightblue] [r=0.68,g=0.85,b=0.90]
+\definecolor [lightcoral] [r=0.94,g=0.50,b=0.50]
+\definecolor [lightcyan] [r=0.88,g=1.00,b=1.00]
+\definecolor [lightgoldenrod] [r=0.93,g=0.87,b=0.51]
+\definecolor [lightgoldenrodyellow] [r=0.98,g=0.98,b=0.82]
+\definecolor [lightpink] [r=1.00,g=0.71,b=0.76]
+\definecolor [lightsalmon] [r=1.00,g=0.63,b=0.48]
+\definecolor [lightseagreen] [r=0.13,g=0.70,b=0.67]
+\definecolor [lightskyblue] [r=0.53,g=0.81,b=0.98]
+\definecolor [lightslateblue] [r=0.52,g=0.44,b=1.00]
+\definecolor [lightsteelblue] [r=0.69,g=0.77,b=0.87]
+\definecolor [lightyellow] [r=1.00,g=1.00,b=0.88]
+\definecolor [limegreen] [r=0.20,g=0.80,b=0.20]
+\definecolor [linen] [r=0.98,g=0.94,b=0.90]
+\definecolor [magenta] [r=1.00,g=0.00,b=1.00]
+\definecolor [maroon] [r=0.69,g=0.19,b=0.38]
+\definecolor [mediumaquamarine] [r=0.40,g=0.80,b=0.67]
+\definecolor [mediumblue] [r=0.00,g=0.00,b=0.80]
+\definecolor [mediumorchid] [r=0.73,g=0.33,b=0.83]
+\definecolor [mediumpurple] [r=0.58,g=0.44,b=0.86]
+\definecolor [mediumseagreen] [r=0.24,g=0.70,b=0.44]
+\definecolor [mediumslateblue] [r=0.48,g=0.41,b=0.93]
+\definecolor [mediumspringgreen] [r=0.00,g=0.98,b=0.60]
+\definecolor [mediumturquoise] [r=0.28,g=0.82,b=0.80]
+\definecolor [mediumvioletred] [r=0.78,g=0.08,b=0.52]
+\definecolor [midnightblue] [r=0.10,g=0.10,b=0.44]
+\definecolor [mintcream] [r=0.96,g=1.00,b=0.98]
+\definecolor [mistyrose] [r=1.00,g=0.89,b=0.88]
+\definecolor [moccasin] [r=1.00,g=0.89,b=0.71]
+\definecolor [navajowhite] [r=1.00,g=0.87,b=0.68]
+\definecolor [navy] [r=0.00,g=0.00,b=0.50]
+\definecolor [navyblue] [r=0.00,g=0.00,b=0.50]
+\definecolor [oldlace] [r=0.99,g=0.96,b=0.90]
+\definecolor [olivedrab] [r=0.42,g=0.56,b=0.14]
+\definecolor [orange] [r=1.00,g=0.65,b=0.00]
+\definecolor [orangered] [r=1.00,g=0.27,b=0.00]
+\definecolor [orchid] [r=0.85,g=0.44,b=0.84]
+\definecolor [palegoldenrod] [r=0.93,g=0.91,b=0.67]
+\definecolor [palegreen] [r=0.60,g=0.98,b=0.60]
+\definecolor [paleturquoise] [r=0.69,g=0.93,b=0.93]
+\definecolor [palevioletred] [r=0.86,g=0.44,b=0.58]
+\definecolor [papayawhip] [r=1.00,g=0.94,b=0.84]
+\definecolor [peachpuff] [r=1.00,g=0.85,b=0.73]
+\definecolor [peru] [r=0.80,g=0.52,b=0.25]
+\definecolor [pink] [r=1.00,g=0.75,b=0.80]
+\definecolor [plum] [r=0.87,g=0.63,b=0.87]
+\definecolor [powderblue] [r=0.69,g=0.88,b=0.90]
+\definecolor [purple] [r=0.63,g=0.13,b=0.94]
+\definecolor [red ] [r=1.00,g=0.00,b=0.00]
+\definecolor [rosybrown] [r=0.74,g=0.56,b=0.56]
+\definecolor [royalblue] [r=0.25,g=0.41,b=0.88]
+\definecolor [saddlebrown] [r=0.55,g=0.27,b=0.07]
+\definecolor [salmon] [r=0.98,g=0.50,b=0.45]
+\definecolor [sandybrown] [r=0.96,g=0.64,b=0.38]
+\definecolor [seagreen] [r=0.18,g=0.55,b=0.34]
+\definecolor [seashell] [r=1.00,g=0.96,b=0.93]
+\definecolor [sienna] [r=0.63,g=0.32,b=0.18]
+\definecolor [skyblue] [r=0.53,g=0.81,b=0.92]
+\definecolor [slateblue] [r=0.42,g=0.35,b=0.80]
+\definecolor [snow] [r=1.00,g=0.98,b=0.98]
+\definecolor [springgreen] [r=0.00,g=1.00,b=0.50]
+\definecolor [steelblue] [r=0.27,g=0.51,b=0.71]
+\definecolor [x11tan] [r=0.82,g=0.71,b=0.55]
+\definecolor [thistle] [r=0.85,g=0.75,b=0.85]
+\definecolor [tomato] [r=1.00,g=0.39,b=0.28]
+\definecolor [turquoise] [r=0.25,g=0.88,b=0.82]
+\definecolor [violet] [r=0.93,g=0.51,b=0.93]
+\definecolor [violetred] [r=0.82,g=0.13,b=0.56]
+\definecolor [wheat] [r=0.96,g=0.87,b=0.70]
+\definecolor [white] [r=1.00,g=1.00,b=1.00]
+\definecolor [whitesmoke] [s=0.96] % [r=0.96,g=0.96,b=0.96]
+\definecolor [yellow] [r=1.00,g=1.00,b=0.00]
+\definecolor [yellowgreen] [r=0.60,g=0.80,b=0.20]
+
+\stopprotectedcolors
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua
new file mode 100644
index 00000000000..1a055242b18
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua
@@ -0,0 +1,1050 @@
+if not modules then modules = { } end modules ['colo-ini'] = {
+ version = 1.000,
+ comment = "companion to colo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tonumber = type, tonumber
+local concat, insert, remove = table.concat, table.insert, table.remove
+local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find
+local P, R, C, Cc = lpeg.P, lpeg.R, lpeg.C, lpeg.Cc
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local formatters = string.formatters
+
+local trace_define = false trackers.register("colors.define",function(v) trace_define = v end)
+local trace_pgf = false trackers.register("colors.pgf", function(v) trace_pgf = v end)
+
+local report_colors = logs.reporter("colors","defining")
+local report_pgf = logs.reporter("colors","pgf")
+
+local attributes = attributes
+local backends = backends
+local storage = storage
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local settings_to_hash_strict = utilities.parsers.settings_to_hash_strict
+
+local colors = attributes.colors
+local transparencies = attributes.transparencies
+local colorintents = attributes.colorintents
+local registrations = backends.registrations
+local texsetattribute = tex.setattribute
+local texgetattribute = tex.getattribute
+
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local register_color = colors.register
+local attributes_list = attributes.list
+
+local colorvalues = colors.values
+local transparencyvalues = transparencies.values
+
+colors.sets = colors.sets or { } -- sets are mostly used for
+local colorsets = colors.sets -- showing lists of defined
+local colorset = { } -- colors
+colorsets.default = colorset
+
+storage.register("attributes/colors/sets",colorsets,"attributes.colors.sets")
+
+local stack = { }
+
+local function pushset(name)
+ insert(stack,colorset)
+ colorset = colorsets[name]
+ if not colorset then
+ colorset = { }
+ colorsets[name] = colorset
+ end
+end
+
+local function popset()
+ colorset = remove(stack)
+end
+
+local function setlist(name)
+ return table.sortedkeys(name and name ~= "" and colorsets[name] or colorsets.default or {})
+end
+
+colors.pushset = pushset
+colors.popset = popset
+colors.setlist = setlist
+
+local context_colordefagc = context.colordefagc
+local context_colordefagt = context.colordefagt
+local context_colordefalc = context.colordefalc
+local context_colordefalt = context.colordefalt
+local context_colordeffgc = context.colordeffgc
+local context_colordeffgt = context.colordeffgt
+local context_colordefflc = context.colordefflc
+local context_colordefflt = context.colordefflt
+local context_colordefrgc = context.colordefrgc
+local context_colordefrgt = context.colordefrgt
+local context_colordefrlc = context.colordefrlc
+local context_colordefrlt = context.colordefrlt
+
+local function definecolor(name, ca, global)
+ if ca and ca > 0 then
+ if global then
+ if trace_define then
+ report_colors("define global color %a with attribute %a",name,ca)
+ end
+ context_colordefagc(name,ca)
+ else
+ if trace_define then
+ report_colors("define local color %a with attribute %a",name,ca)
+ end
+ context_colordefalc(name,ca)
+ end
+ else
+ if global then
+ context_colordefrgc(name)
+ else
+ context_colordefrlc(name)
+ end
+ end
+ colorset[name] = true-- maybe we can store more
+end
+
+local function inheritcolor(name, ca, global)
+ if ca and ca ~= "" then
+ if global then
+ if trace_define then
+ report_colors("inherit global color %a with attribute %a",name,ca)
+ end
+ context_colordeffgc(name,ca) -- some day we will set the macro directly
+ else
+ if trace_define then
+ report_colors("inherit local color %a with attribute %a",name,ca)
+ end
+ context_colordefflc(name,ca)
+ end
+ else
+ if global then
+ context_colordefrgc(name)
+ else
+ context_colordefrlc(name)
+ end
+ end
+ colorset[name] = true-- maybe we can store more
+end
+
+local function definetransparent(name, ta, global)
+ if ta and ta > 0 then
+ if global then
+ if trace_define then
+ report_colors("define global transparency %a with attribute %a",name,ta)
+ end
+ context_colordefagt(name,ta)
+ else
+ if trace_define then
+ report_colors("define local transparency %a with attribute %a",name,ta)
+ end
+ context_colordefalt(name,ta)
+ end
+ else
+ if global then
+ context_colordefrgt(name)
+ else
+ context_colordefrlt(name)
+ end
+ end
+end
+
+local function inherittransparent(name, ta, global)
+ if ta and ta ~= "" then
+ if global then
+ if trace_define then
+ report_colors("inherit global transparency %a with attribute %a",name,ta)
+ end
+ context_colordeffgt(name,ta)
+ else
+ if trace_define then
+ report_colors("inherit local transparency %a with attribute %a",name,ta)
+ end
+ context_colordefflt(name,ta)
+ end
+ else
+ if global then
+ context_colordefrgt(name)
+ else
+ context_colordefrlt(name)
+ end
+ end
+end
+
+local transparent = {
+ none = 0,
+ normal = 1,
+ multiply = 2,
+ screen = 3,
+ overlay = 4,
+ softlight = 5,
+ hardlight = 6,
+ colordodge = 7,
+ colorburn = 8,
+ darken = 9,
+ lighten = 10,
+ difference = 11,
+ exclusion = 12,
+ hue = 13,
+ saturation = 14,
+ color = 15,
+ luminosity = 16,
+}
+
+local gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = true, true, true, true, true, false
+
+function colors.forcesupport(gray,rgb,cmyk,spot,multichannel) -- pdfx driven
+ gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = gray, rgb, cmyk, spot, multichannel, true
+ report_colors("supported models: gray %a, rgb %a, cmyk %a, spot %a",gray,rgb,cmyk,spot) -- multichannel=%l multichannel
+end
+
+local function forcedmodel(model) -- delayed till the backend but mp directly
+ if not forced then
+ return model
+ elseif model == 2 then -- gray
+ if gray_okay then
+ -- okay
+ elseif cmyk_okay then
+ return 4
+ elseif rgb_okay then
+ return 3
+ end
+ elseif model == 3 then -- rgb
+ if rgb_okay then
+ -- okay
+ elseif cmyk_okay then
+ return 4
+ elseif gray_okay then
+ return 2
+ end
+ elseif model == 4 then -- cmyk
+ if cmyk_okay then
+ -- okay
+ elseif rgb_okay then
+ return 3
+ elseif gray_okay then
+ return 2
+ end
+ elseif model == 5 then -- spot
+ if cmyk_okay then
+ return 4
+ elseif rgb_okay then
+ return 3
+ elseif gray_okay then
+ return 2
+ end
+ end
+ return model
+end
+
+colors.forcedmodel = forcedmodel
+
+-- By coupling we are downward compatible. When we decouple we need to do more tricky
+-- housekeeping (e.g. persist color independent transparencies when color bound ones
+-- are nil.)
+
+colors.couple = true
+
+local function definetransparency(name,n)
+ transparent[name] = n
+end
+
+colors.definetransparency = definetransparency
+
+local registered = { }
+
+local function do_registerspotcolor(parent,parentnumber,e,f,d,p)
+ if not registered[parent] then
+ local v = colorvalues[parentnumber]
+ if v then
+ local model = colors.default -- else problems with shading etc
+ if model == 1 then
+ model = v[1]
+ end
+ if e and e ~= "" then
+ registrations.spotcolorname(parent,e) -- before registration of the color
+ end
+ if model == 2 then -- name noffractions names p's r g b
+ registrations.grayspotcolor(parent,f,d,p,v[2])
+ elseif model == 3 then
+ registrations.rgbspotcolor (parent,f,d,p,v[3],v[4],v[5])
+ elseif model == 4 then
+ registrations.cmykspotcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
+ end
+ end
+ registered[parent] = true
+ end
+end
+
+-- local function do_registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
+-- if not registered[parent] then
+-- local v = colorvalues[parentnumber]
+-- if v then
+-- local model = colors.default -- else problems with shading etc
+-- if model == 1 then
+-- model = v[1]
+-- end
+-- if model == 2 then
+-- registrations.grayindexcolor(parent,f,d,p,v[2])
+-- elseif model == 3 then
+-- registrations.rgbindexcolor (parent,f,d,p,v[3],v[4],v[5])
+-- elseif model == 4 then
+-- registrations.cmykindexcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
+-- end
+-- end
+-- registered[parent] = true
+-- end
+-- end
+
+function colors.definesimplegray(name,s)
+ return register_color(name,'gray',s) -- we still need to get rid of 'color'
+end
+
+local hexdigit = R("09","AF","af")
+local hexnumber = hexdigit * hexdigit / function(s) return tonumber(s,16)/255 end + Cc(0)
+local hexpattern = hexnumber^-3 * P(-1)
+local hexcolor = Cc("H") * P("#") * hexpattern
+
+local left = P("(")
+local right = P(")")
+local comma = P(",")
+local mixnumber = lpegpatterns.number / tonumber
+ + P("-") / function() return -1 end
+local mixname = C(P(1-left-right-comma)^1)
+----- mixcolor = Cc("M") * mixnumber * left * mixname * (comma * mixname)^-1 * right * P(-1)
+local mixcolor = Cc("M") * mixnumber * left * mixname * (comma * mixname)^0 * right * P(-1) -- one is also ok
+
+local exclamation = P("!")
+local pgfnumber = lpegpatterns.digit^0 / function(s) return tonumber(s)/100 end
+local pgfname = C(P(1-exclamation)^1)
+local pgfcolor = Cc("P") * pgfname * exclamation * pgfnumber * (exclamation * pgfname)^-1 * P(-1)
+
+local specialcolor = hexcolor + mixcolor
+
+local l_color = attributes.list[a_color]
+local l_transparency = attributes.list[a_transparency]
+
+directives.register("colors.pgf",function(v)
+ if v then
+ specialcolor = hexcolor + mixcolor + pgfcolor
+ else
+ specialcolor = hexcolor + mixcolor
+ end
+end)
+
+local defineintermediatecolor
+
+local function defineprocesscolor(name,str,global,freeze) -- still inconsistent color vs transparent
+ local what, one, two, three = lpegmatch(specialcolor,str)
+ if what == "H" then
+ -- for old times sake (if we need to feed from xml or so)
+ definecolor(name, register_color(name,'rgb',one,two,three),global)
+ elseif what == "M" then
+ -- intermediate
+ return defineintermediatecolor(name,one,l_color[two],l_color[three],l_transparency[two],l_transparency[three],"",global,freeze)
+ elseif what == "P" then
+ -- pgf for tikz
+ return defineintermediatecolor(name,two,l_color[one],l_color[three],l_transparency[one],l_transparency[three],"",global,freeze)
+ else
+ local settings = settings_to_hash_strict(str)
+ if settings then
+ local r, g, b = settings.r, settings.g, 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
+ 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
+ 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)
+ else
+ local x = settings.x or h
+ if x then
+ r, g, b = lpegmatch(hexpattern,x) -- can be inlined
+ definecolor(name, register_color(name,'rgb',r,g,b), global)
+ else
+ definecolor(name, register_color(name,'gray',tonumber(s) or 0), global)
+ end
+ end
+ end
+ end
+ local a, t = settings.a, 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
+ -- definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ elseif freeze then
+ local ca = attributes_list[a_color] [str]
+ local ta = attributes_list[a_transparency][str]
+ if ca then
+ definecolor(name, ca, global)
+ end
+ if ta then
+ definetransparent(name, ta, global)
+ end
+ else
+ inheritcolor(name, str, global)
+ inherittransparent(name, str, global)
+ -- if global and str ~= "" then -- For Peter Rolf who wants access to the numbers in Lua. (Currently only global is supported.)
+ -- attributes_list[a_color] [name] = attributes_list[a_color] [str] or attributes.unsetvalue -- reset
+ -- attributes_list[a_transparency][name] = attributes_list[a_transparency][str] or attributes.unsetvalue
+ -- end
+ end
+ end
+ colorset[name] = true-- maybe we can store more
+end
+
+local function isblack(ca) -- maybe commands
+ local cv = ca > 0 and colorvalues[ca]
+ return (cv and cv[2] == 0) or false
+end
+
+colors.isblack = isblack
+
+local function definespotcolor(name,parent,str,global)
+ if parent == "" or find(parent,"=",1,true) then
+ colors.registerspotcolor(name, parent) -- does that work? no attr
+ elseif name ~= parent then
+ local cp = attributes_list[a_color][parent]
+ if cp then
+ local t = settings_to_hash_strict(str)
+ if t then
+ local tp = tonumber(t.p) or 1
+ 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
+ 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
+ --~ definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ end
+ end
+ end
+ end
+ colorset[name] = true-- maybe we can store more
+end
+
+function colors.registerspotcolor(parent, str)
+ local cp = attributes_list[a_color][parent]
+ if cp then
+ local e = ""
+ if str then
+ local t = settings_to_hash_strict(str)
+ e = (t and t.e) or ""
+ end
+ do_registerspotcolor(parent, cp, e, 1, "", 1) -- p not really needed, only diagnostics
+ end
+end
+
+local function f(i,colors,fraction)
+ local otf = 0
+ for c=1,#colors do
+ otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i]
+ end
+ if otf > 1 then
+ otf = 1
+ end
+ return otf
+end
+
+local function definemixcolor(makename,name,fractions,cs,global,freeze)
+ local values = { }
+ for i=1,#cs do -- do fraction in here
+ local v = colorvalues[cs[i]]
+ if not v then
+ return
+ end
+ values[i] = v
+ end
+ if #values > 0 then
+ csone = values[1][1]
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',f(2,values,fractions))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb', f(3,values,fractions),
+ f(4,values,fractions),
+ f(5,values,fractions))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',f(6,values,fractions),
+ f(7,values,fractions),
+ f(8,values,fractions),
+ f(9,values,fractions))
+ else
+ ca = register_color(name,'gray',f(2,values,fractions))
+ end
+ definecolor(name,ca,global,freeze)
+ else
+ report_colors("invalid specification of components for color %a",makename)
+ end
+end
+
+local function definemultitonecolor(name,multispec,colorspec,selfspec)
+ local dd, pp, nn, max = { }, { }, { }, 0
+ for k,v in gmatch(multispec,"([^=,]+)=([^%,]*)") do -- use settings_to_array
+ max = max + 1
+ dd[max] = k
+ pp[max] = v
+ nn[max] = formatters["%s_%1.3g"](k,tonumber(v) or 0) -- 0 can't happen
+ end
+ if max > 0 then
+ nn = concat(nn,'_')
+ local parent = gsub(lower(nn),"[^%d%a%.]+","_")
+ if not colorspec or colorspec == "" then
+ local cc = { } for i=1,max do cc[i] = l_color[dd[i]] end
+ definemixcolor(name,parent,pp,cc,global,freeze) -- can become local
+ else
+ if selfspec ~= "" then
+ colorspec = colorspec .. "," .. selfspec
+ end
+ defineprocesscolor(parent,colorspec,true,true)
+ end
+ local cp = attributes_list[a_color][parent]
+ dd, pp = concat(dd,','), concat(pp,',')
+ if cp then
+ do_registerspotcolor(parent, cp, "", max, dd, pp)
+ definecolor(name, register_color(name, 'spot', parent, max, dd, pp), true)
+ local t = settings_to_hash_strict(selfspec)
+ if t and t.a and t.t then
+ definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
+ elseif colors.couple then
+ -- definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ end
+ end
+ colorset[name] = true-- maybe we can store more
+end
+
+colors.defineprocesscolor = defineprocesscolor
+colors.definespotcolor = definespotcolor
+colors.definemultitonecolor = definemultitonecolor
+
+-- will move to mlib-col as colors in mp are somewhat messy due to the fact
+-- 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 cv = colorvalues[ca]
+ if cv then
+ local tv = transparencyvalues[ta]
+ if model == 1 then
+ model = cv[1]
+ end
+ model = forcedmodel(model)
+ 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])
+ 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])
+ 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
+ else
+ if model == 2 then
+ return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
+ 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])
+ 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])
+ else -- see ** in meta-ini.mkiv: return formatters["%s"]((cv[2]))
+ return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
+ end
+ end
+ end
+ local tv = transparencyvalues[ta]
+ if tv then
+ return formatters["(%s,%s)"](tv[1],tv[2])
+ end
+ default = default or 0 -- rgb !
+ return formatters["(%s,%s,%s)"](default,default,default)
+end
+
+local function mpnamedcolor(name)
+ return mpcolor(texgetattribute(a_colorspace),l_color[name] or l_color.black)
+end
+
+local function mpoptions(model,ca,ta,default) -- will move to mlib-col
+ return formatters["withcolor %s"](mpcolor(model,ca,ta,default))
+end
+
+colors.mpcolor = mpcolor
+colors.mpnamedcolor = mpnamedcolor
+colors.mpoptions = mpoptions
+
+-- local function formatcolor(ca,separator)
+-- local cv = colorvalues[ca]
+-- if cv then
+-- local c, cn, f, t, model = { }, 0, 13, 13, cv[1]
+-- if model == 2 then
+-- return c[2]
+-- elseif model == 3 then
+-- return concat(c,separator,3,5)
+-- elseif model == 4 then
+-- return concat(c,separator,6,9)
+-- end
+-- else
+-- return 0
+-- end
+-- end
+
+local function formatcolor(ca,separator)
+ local cv = colorvalues[ca]
+ if cv then
+ local c, cn, f, t, model = { }, 0, 13, 13, cv[1]
+ if model == 2 then
+ f, t = 2, 2
+ elseif model == 3 then
+ f, t = 3, 5
+ elseif model == 4 then
+ f, t = 6, 9
+ end
+ for i=f,t do
+ cn = cn + 1
+ c[cn] = format("%0.3f",cv[i])
+ end
+ return concat(c,separator)
+ else
+ return format("%0.3f",0)
+ end
+end
+
+local function formatgray(ca,separator)
+ local cv = colorvalues[ca]
+ return format("%0.3f",(cv and cv[2]) or 0)
+end
+
+colors.formatcolor = formatcolor
+colors.formatgray = formatgray
+
+local f_gray = formatters["s=%1.3f"]
+local f_rgb = formatters["r=%1.3f%sg=%1.3f%sb=%1.3f"]
+local f_cmyk = formatters["c=%1.3f%sm=%1.3f%sy=%1.3f%sk=%1.3f"]
+local f_spot_name = formatters["p=%s"]
+local f_spot_value = formatters["p=%1.3f"]
+local f_transparency = formatters["a=%1.3f%st=%1.3f"]
+local f_both = formatters["%s%s%s"]
+
+local function colorcomponents(ca,separator) -- return list
+ local cv = colorvalues[ca]
+ if cv then
+ local model = cv[1]
+ if model == 2 then
+ return f_gray(cv[2])
+ elseif model == 3 then
+ return f_rgb(cv[3],separator or " ",cv[4],separator or " ",cv[5])
+ elseif model == 4 then
+ return f_cmyk(cv[6],separator or " ",cv[7],separator or " ",cv[8],separator or " ",cv[9])
+ elseif type(cv[13]) == "string" then
+ return f_spot_name(cv[13])
+ else
+ return f_spot_value(cv[13])
+ end
+ else
+ return ""
+ end
+end
+
+local function transparencycomponents(ta,separator)
+ local tv = transparencyvalues[ta]
+ if tv then
+ return f_transparency(tv[1],separator or " ",tv[2])
+ else
+ return ""
+ end
+end
+
+local function processcolorcomponents(ca,separator)
+ local cs = colorcomponents(ca,separator)
+ local ts = transparencycomponents(ca,separator)
+ if cs == "" then
+ return ts
+ elseif ts == "" then
+ return cs
+ else
+ return f_both(cs,separator or " ",ts)
+ end
+end
+
+local function spotcolorname(ca,default)
+ local cv, v = colorvalues[ca], "unknown"
+ if cv and cv[1] == 5 then
+ v = cv[10]
+ end
+ return tostring(v)
+end
+
+local function spotcolorparent(ca,default)
+ local cv, v = colorvalues[ca], "unknown"
+ if cv and cv[1] == 5 then
+ v = cv[12]
+ if v == "" then
+ v = cv[10]
+ end
+ end
+ return tostring(v)
+end
+
+local function spotcolorvalue(ca,default)
+ local cv, v = colorvalues[ca], 0
+ if cv and cv[1] == 5 then
+ v = cv[13]
+ end
+ return tostring(v)
+end
+
+colors.colorcomponents = colorcomponents
+colors.transparencycomponents = transparencycomponents
+colors.processcolorcomponents = processcolorcomponents
+colors.spotcolorname = spotcolorname
+colors.spotcolorparent = spotcolorparent
+colors.spotcolorvalue = spotcolorvalue
+
+-- experiment (a bit of a hack, as we need to get the attribute number)
+
+local min = math.min
+
+-- a[b,c] -> b+a*(c-b)
+
+local function inbetween(one,two,i,fraction)
+ local o, t = one[i], two[i]
+ local otf = o + fraction * (t - o)
+ if otf > 1 then
+ otf = 1
+ end
+ return otf
+end
+
+local function justone(one,fraction,i)
+ local otf = fraction * one[i]
+ if otf > 1 then
+ otf = 1
+ end
+ return otf
+end
+
+local function complement(one,fraction,i)
+ local otf = - fraction * (1 - one[i])
+ if otf > 1 then
+ otf = 1
+ end
+ return otf
+end
+
+defineintermediatecolor = function(name,fraction,c_one,c_two,a_one,a_two,specs,global,freeze)
+ fraction = tonumber(fraction) or 1
+ local one, two = colorvalues[c_one], colorvalues[c_two]
+ if one then
+ if two then
+ local csone, cstwo = one[1], two[1]
+ -- if csone == cstwo then
+ -- actually we can set all 8 values at once here but this is cleaner as we avoid
+ -- problems with weighted gray conversions and work with original values
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',inbetween(one,two,2,fraction))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb', inbetween(one,two,3,fraction),
+ inbetween(one,two,4,fraction),
+ inbetween(one,two,5,fraction))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',inbetween(one,two,6,fraction),
+ inbetween(one,two,7,fraction),
+ inbetween(one,two,8,fraction),
+ inbetween(one,two,9,fraction))
+ else
+ ca = register_color(name,'gray',inbetween(one,two,2,fraction))
+ end
+ definecolor(name,ca,global,freeze)
+ -- end
+ else
+ local inbetween = fraction < 0 and complement or justone
+ local csone = one[1]
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',inbetween(one,fraction,2))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb', inbetween(one,fraction,3),
+ inbetween(one,fraction,4),
+ inbetween(one,fraction,5))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',inbetween(one,fraction,6),
+ inbetween(one,fraction,7),
+ inbetween(one,fraction,8),
+ inbetween(one,fraction,9))
+ else
+ ca = register_color(name,'gray',inbetween(one,fraction,2))
+ end
+ definecolor(name,ca,global,freeze)
+ end
+ end
+ local one, two = transparencyvalues[a_one], transparencyvalues[a_two]
+ local t = settings_to_hash_strict(specs)
+ local ta = tonumber((t and t.a) or (one and one[1]) or (two and two[1]))
+ local tt = tonumber((t and t.t) or (one and two and f(one,two,2,fraction)))
+ if ta and tt then
+ definetransparent(name,transparencies.register(name,ta,tt),global)
+ end
+end
+
+colors.defineintermediatecolor = defineintermediatecolor
+
+-- for the moment downward compatible
+
+local patterns = {
+ "colo-imp-%s.mkiv",
+ "colo-imp-%s.tex",
+ -- obsolete:
+ "colo-%s.mkiv",
+ "colo-%s.tex"
+}
+
+local function action(name,foundname)
+ -- could be one command
+ context.startreadingfile()
+ context.startcolorset { name }
+ context.input(foundname)
+ context.showmessage("colors",4,name)
+ context.stopcolorset()
+ context.stopreadingfile()
+end
+
+local function failure(name)
+ -- context.showmessage("colors",5,name)
+ report_colors("unknown library %a",name)
+end
+
+local function usecolors(name)
+ commands.uselibrary {
+ category = "color definition",
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+end
+
+colors.usecolors = usecolors
+
+-- backend magic
+
+local currentpagecolormodel
+
+function colors.setpagecolormodel(model)
+ currentpagecolormodel = model
+end
+
+function colors.getpagecolormodel()
+ return currentpagecolormodel
+end
+
+-- interface
+
+local setcolormodel = colors.setmodel
+
+implement {
+ name = "setcolormodel",
+ arguments = { "string", "boolean" },
+ actions = function(model,weight)
+ texsetattribute(a_colorspace,setcolormodel(model,weight))
+ end
+}
+
+implement {
+ name = "setpagecolormodel",
+ actions = colors.setpagecolormodel,
+ arguments = { "string" },
+}
+
+implement {
+ name = "defineprocesscolorlocal",
+ actions = defineprocesscolor,
+ arguments = { "string", "string", false, "boolean" }
+}
+
+implement {
+ name = "defineprocesscolorglobal",
+ actions = defineprocesscolor,
+ arguments = { "string", "string", true, "boolean" }
+}
+
+implement {
+ name = "defineprocesscolordummy",
+ actions = defineprocesscolor,
+ arguments = { "'d_u_m_m_y'", "string", false, false }
+}
+
+implement {
+ name = "definespotcolorglobal",
+ actions = definespotcolor,
+ arguments = { "string", "string", "string", true }
+}
+
+implement {
+ name = "definemultitonecolorglobal",
+ actions = definemultitonecolor,
+ arguments = { "string", "string", "string", "string", true }
+}
+
+implement {
+ name = "registermaintextcolor",
+ actions = function(main)
+ colors.main = main
+ end,
+ arguments = { "integer" }
+}
+
+implement {
+ name = "definetransparency",
+ actions = definetransparency,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "defineintermediatecolor",
+ actions = defineintermediatecolor,
+ arguments = { "string", "string", "integer", "integer", "integer", "integer", "string", false, "boolean" }
+}
+
+implement { name = "spotcolorname", actions = { spotcolorname, context }, arguments = "integer" }
+implement { name = "spotcolorparent", actions = { spotcolorparent, context }, arguments = "integer" }
+implement { name = "spotcolorvalue", actions = { spotcolorvalue, context }, arguments = "integer" }
+implement { name = "colorcomponents", actions = { colorcomponents, context }, arguments = "integer" }
+implement { name = "transparencycomponents", actions = { transparencycomponents, context }, arguments = "integer" }
+implement { name = "processcolorcomponents", actions = { processcolorcomponents, context }, arguments = "integer" }
+implement { name = "formatcolor", actions = { formatcolor, context }, arguments = { "integer", "string" } }
+implement { name = "formatgray", actions = { formatgray, context }, arguments = { "integer", "string" } }
+
+implement {
+ name = "mpcolor",
+ actions = { mpcolor, context },
+ arguments = { "integer", "integer", "integer" }
+}
+
+implement {
+ name = "mpoptions",
+ actions = { mpoptions, context },
+ arguments = { "integer", "integer", "integer" }
+}
+
+local ctx_doifelse = commands.doifelse
+
+implement {
+ name = "doifelsedrawingblack",
+ actions = function() ctx_doifelse(isblack(texgetattribute(a_color))) end
+}
+
+implement {
+ name = "doifelseblack",
+ actions = { isblack, ctx_doifelse },
+ arguments = "integer"
+}
+
+-- function commands.withcolorsinset(name,command)
+-- local set
+-- if name and name ~= "" then
+-- set = colorsets[name]
+-- else
+-- set = colorsets.default
+-- end
+-- if set then
+-- if command then
+-- for name in table.sortedhash(set) do
+-- context[command](name)
+-- end
+-- else
+-- context(concat(table.sortedkeys(set),","))
+-- end
+-- end
+-- end
+
+implement { name = "startcolorset", actions = pushset, arguments = "string" }
+implement { name = "stopcolorset", actions = popset }
+implement { name = "usecolors", actions = usecolors, arguments = "string" }
+
+-- bonus
+
+do
+
+ local function pgfxcolorspec(model,ca) -- {}{}{colorspace}{list}
+ -- local cv = attributes.colors.values[ca]
+ local cv = colorvalues[ca]
+ local str
+ if cv then
+ if model and model ~= 0 then
+ model = model
+ else
+ model = forcedmodel(texgetattribute(a_colorspace))
+ if model == 1 then
+ model = cv[1]
+ end
+ end
+ if model == 3 then
+ str = formatters["{rgb}{%1.3f,%1.3f,%1.3f}"](cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ str = formatters["{cmyk}{%1.3f,%1.3f,%1.3f,%1.3f}"](cv[6],cv[7],cv[8],cv[9])
+ else -- there is no real gray
+ str = formatters["{rgb}{%1.3f,%1.3f,%1.3f}"](cv[2],cv[2],cv[2])
+ end
+ else
+ str = "{rgb}{0,0,0}"
+ end
+ if trace_pgf then
+ report_pgf("model %a, string %a",model,str)
+ end
+ return str
+ end
+
+ implement {
+ name = "pgfxcolorspec",
+ actions = { pgfxcolorspec, context },
+ arguments = { "integer", "integer" }
+ }
+
+end
+
+-- handy
+
+local models = storage.allocate { "all", "gray", "rgb", "cmyk", "spot" }
+
+colors.models = models -- check for usage elsewhere
+
+function colors.spec(name)
+ local l = attributes_list[a_color]
+ local t = colorvalues[l[name]] or colorvalues[l.black]
+ return {
+ model = models[t[1]] or models[1],
+ s = t[2],
+ r = t[3], g = t[4], b = t[5],
+ c = t[6], m = t[7], y = t[8], k = t[9],
+ }
+end
+
+-- inspect(attributes.colors.spec("red"))
+-- inspect(attributes.colors.spec("red socks"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv
new file mode 100644
index 00000000000..26208edd448
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv
@@ -0,0 +1,1268 @@
+%D \module
+%D [ file=colo-ini,
+%D version=2007.08.08,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We need to clean this up further but first we have to make sure that mkiv
+%D code works ok.
+
+\writestatus{loading}{ConTeXt Color Macros / Initialization}
+
+%D Todo: move color space in color attribute (last two bits)
+
+%D This module implements color. Since \MKII\ and \MKIV\ use a completely
+%D different approach, this module only implements a few generic mechanisms.
+
+\registerctxluafile{colo-ini}{1.000}
+\registerctxluafile{colo-icc}{1.000}
+
+\unprotect
+
+%D In \MKIV\ we have independent color, colorspace and transparency
+%D but I'm still not sure if I keep it that way as it's probably more
+%D efficient to combine them (less attributes and finalizing). If
+%D it becomes a bottleneck we can set up a more complex system
+%D with one shared attribute for colorspace, color and transparency.
+%D
+%D When typesetting for paper, we prefer using the \CMYK\ color space,
+%D but for on||screen viewing we prefer \RGB\ (the previous
+%D implementation supported only this scheme). Independant of such
+%D specifications, we support some automatic conversions:
+%D
+%D \startitemize[packed]
+%D \item convert all colors to \RGB
+%D \item convert all colors to \CMYK
+%D \item convert all colors to gray scales
+%D \stopitemize
+%D
+%D These options are communicated by means of:
+
+\newconditional\c_colo_rgb_supported
+\newconditional\c_colo_cmyk_supported
+\newconditional\c_colo_spot_supported % backend driven
+\newconditional\c_colo_weight_gray \settrue\c_colo_weight_gray
+\newconditional\c_colo_convert_gray \settrue\c_colo_convert_gray
+\newconditional\c_colo_enabled
+\newconditional\c_colo_expanded
+
+\let\currentcolormodel \empty
+\let\currentcolorname \empty
+\let\currentcolorpalet \empty
+\let\currentcolorprefix\empty % \currentcolorpalet:
+
+\installcorenamespace{color}
+\installcorenamespace{colorattribute}
+\installcorenamespace{transparencyattribute}
+\installcorenamespace{colorsetter}
+\installcorenamespace{transparencysetter}
+\installcorenamespace{colorpaletspecification}
+\installcorenamespace{colorpalet}
+\installcorenamespace{colorstack}
+\installcorenamespace{colorconversions}
+
+%D \macros
+%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor,
+%D definetransparency}
+%D
+%D \starttyping
+%D \definecolor [blue] [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
+%D \definecolor [yellow] [c=0,m=.28,y=1,k=.06] % pantone pms 124 uncoated m
+%D
+%D \definespotcolor [blue-100] [blue] [p=1]
+%D \definespotcolor [yellow-100] [yellow] [p=1]
+%D
+%D \definemultitonecolor [pdftoolscolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
+%D
+%D \defineprocesscolor[myred][r=.5]
+%D \defineprocesscolor[myredish][red][a=1,t=.5]
+%D
+%D \blackrule[color=myred,width=\hsize,height=1cm] \par
+%D \blackrule[color=myredish,width=\hsize,height=1cm]
+%D
+%D \useexternalfigure[demofig][mill.png][object=no]
+%D
+%D \startcombination[4*1]
+%D {\externalfigure[demofig]} {no color}
+%D {\externalfigure[demofig][color=pdftoolscolor]} {indexed duotone}
+%D {\externalfigure[demofig][color=blue-100]} {spot color}
+%D {\externalfigure[demofig][color=yellow-100]} {spot color}
+%D \stopcombination
+%D \stoptyping
+
+\unexpanded\def\definecolor {\dodoubleargument\colo_basics_define}
+\unexpanded\def\defineglobalcolor {\dodoubleargument\colo_basics_define_global}
+\unexpanded\def\defineprocesscolor {\dotripleargument\colo_basics_define_process}
+\unexpanded\def\definenamedcolor {\dodoubleargument\colo_basics_define_named}
+\unexpanded\def\definespotcolor {\dotripleargument\colo_basics_define_spot}
+\unexpanded\def\definemultitonecolor{\doquadrupleempty\colo_basics_define_multitone}
+\unexpanded\def\definetransparency {\dodoubleargument\colo_basics_define_transpancy}
+
+%D \macros
+%D {startcolor,stopcolor,color,graycolor}
+%D
+%D The local and global commands are here just for compatibility
+%D with \MKII.
+%D
+%D \showsetup{startcolor}
+%D
+%D The simple color commands are:
+%D
+%D \showsetup{color}
+%D \showsetup{graycolor}
+
+%D We expect sane behaviour in \MKIV\ so we don't used grouped command any
+%D longer.
+
+% \testfeatureonce{100000}{\color[red]{}} % 1.046 => 0.541
+
+\let\g_color\empty
+\let\g_style\empty
+
+\unexpanded\def\switchtocolor[#1]{\csname#1\endcsname}
+
+\unexpanded\def\color [#1]{\bgroup
+ \def\g_color{\colo_helpers_activate{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
+
+\unexpanded\def\graycolor [#1]{\bgroup
+ \def\g_color{\colo_helpers_set_model\s!gray\colo_helpers_activate{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
+
+\unexpanded\def\startcolor [#1]{\begingroup
+ \colo_helpers_activate{#1}}
+
+\unexpanded\def\stopcolor {\endgroup}
+
+\unexpanded\def\colored [#1]{\bgroup
+ \def\g_color{\colo_basics_defined_and_activated{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
+
+\unexpanded\def\fastcolored[#1]#2{\begingroup % is this command still needed?
+ \colo_basics_defined_and_activated{#1}%
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolored[#1]{\colo_basics_defined_and_activated{#1}}
+
+\unexpanded\def\fastcolor [#1]#2{\begingroup % is this command still needed?
+ \colo_helpers_activate{#1}%
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolor [#1]{\colo_helpers_activate{#1}}
+
+
+%D The following command is obsolete:
+
+\unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
+\unexpanded\def\stopcolorpage {\stopcolor}
+
+\unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
+ {\begingroup
+ \colo_helpers_activate{#1}%
+ \normalexpanded{\endgroup\edef\noexpand#2%
+ {\ifnum\attribute\colorattribute=\attributeunsetvalue\else\number\attribute\colorattribute\fi}}}
+
+\let\grey\graycolor % these macros are only used in tracing
+
+%D \macros
+%D {startcurrentcolor,stopcurrentcolor}
+
+\unexpanded\def\startcurrentcolor{\startcolor[\outercolorname]}
+\unexpanded\def\stopcurrentcolor {\stopcolor}
+
+%D \macros
+%D {setupcolor}
+%D
+%D Color definitions can be grouped in files with the name:
+%D
+%D \starttyping
+%D colo-imp-tag.tex
+%D \stoptyping
+%D
+%D Loading such a file is done by:
+%D
+%D \showsetup{usecolors}
+%D
+%D Some default colors are specified in \type {colo-imp-rgb},
+%D which is loaded into the format by default.
+%D
+%D Some demo palets and groups are defined in \type {colo-imp-dem}
+%D which can be loaded with:
+%D
+%D \starttyping
+%D \usecolors[dem]
+%D \stoptyping
+
+\unexpanded\def\startcolorset[#1]{\clf_startcolorset{#1}}
+\unexpanded\def\stopcolorset {\clf_stopcolorset}
+\unexpanded\def\usecolors [#1]{\clf_usecolors{#1}}
+
+\let\setupcolor\usecolors
+
+\installsetuponlycommandhandler \??color {colors}
+
+\let\colo_helpers_show_message\gobblethreearguments
+
+% \newtoks\everysetupcolors
+
+\let\v_colo_freeze_state\s!false
+\let\v_colo_weight_state\s!false
+
+\setvalue{\??colorconversions\v!yes}%
+ {\settrue \c_colo_convert_gray}
+
+\setvalue{\??colorconversions\v!always}%
+ {\settrue \c_colo_convert_gray
+ \setfalse\c_colo_rgb_supported
+ \setfalse\c_colo_cmyk_supported}
+
+\appendtoks
+ %
+ \doifelse{\directcolorsparameter\c!spot }\v!yes \settrue \setfalse\c_colo_spot_supported
+ \doifelse{\directcolorsparameter\c!expansion}\v!yes \settrue \setfalse\c_colo_expanded
+ \doifelse{\directcolorsparameter\c!factor }\v!no \setfalse\settrue \c_colo_weight_gray
+ \doifelse{\directcolorsparameter\c!rgb }\v!yes \settrue \setfalse\c_colo_rgb_supported
+ \doifelse{\directcolorsparameter\c!cmyk }\v!yes \settrue \setfalse\c_colo_cmyk_supported
+ \doifelse{\directcolorsparameter\c!state }\v!start\settrue \setfalse\c_colo_enabled
+ %
+ \ifconditional\c_colo_weight_gray
+ \let\v_colo_weight_state\s!true
+ \else
+ \let\v_colo_weight_state\s!false
+ \fi
+ %
+ \ifconditional\c_colo_expanded
+ \let\v_colo_freeze_state\s!true
+ \else
+ \let\v_colo_freeze_state\s!false
+ \fi
+ %
+ \setfalse\c_colo_convert_gray
+ \begincsname\??colorconversions\directcolorsparameter\c!conversion\endcsname
+ % too often:
+ \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
+ \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
+ \colo_helpers_set_current_model
+ \ifproductionrun
+ \edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
+ \clf_setpagecolormodel{\ifx\p_pagecolormodel\v!auto\currentcolormodel\else\p_pagecolormodel\fi}%
+ \fi
+\to \everysetupcolors
+
+\appendtoks
+ \setupcolors[\c!state=\v!start]%
+ \clf_enablecolor % this can as well happen when
+ \clf_enabletransparency % the handler is defined in lua
+ \let\colo_helpers_show_message\showmessage
+\to \everyjob
+
+%D We provide stacking independent of grouping.
+
+\newcount\c_colo_nesting
+
+\unexpanded\def\pushcolor[#1]%
+ {\global\advance\c_colo_nesting\plusone
+ \expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname
+ {\attribute\colormodelattribute \the\attribute\colormodelattribute
+ \attribute\colorattribute \the\attribute\colorattribute
+ \attribute\transparencyattribute\the\attribute\transparencyattribute
+ \relax}% stack
+ \colo_helpers_activate{#1}}
+
+\unexpanded\def\popcolor
+ {\csname\??colorstack\number\c_colo_nesting\endcsname
+ \global\advance\c_colo_nesting\minusone}
+
+% a simple one: assumes grouping
+
+\newcount\c_colo_saved_attribute_color
+\newcount\c_colo_saved_attribute_transparency
+
+\unexpanded\def\savecolor
+ {\c_colo_saved_attribute_color \attribute\colorattribute
+ \c_colo_saved_attribute_transparency\attribute\transparencyattribute}
+
+\unexpanded\def\restorecolor
+ {\attribute\colorattribute \c_colo_saved_attribute_color
+ \attribute\transparencyattribute\c_colo_saved_attribute_transparency}
+
+%D In this documentation we will not go into too much details
+%D on palets. Curious users can find more information on this
+%D topic in \from[use of color].
+%D
+%D At the moment we implemented color in \CONTEXT\ color
+%D printing was not yet on the desktop. In spite of this lack our
+%D graphics designer made colorfull illustrations. When printed
+%D on a black and white printer, distinctive colors can come
+%D out equally gray. We therefore decided to use only colors
+%D that were distinctive in colors as well as in black and
+%D white print.
+%D
+%D Although none of the graphic packages we used supported
+%D logical colors and global color redefition, we build this
+%D support into \CONTEXT. This enabled us to experiment and
+%D also prepared us for the future.
+
+%D \macros
+%D {definepalet}
+%D
+%D Colors are grouped in palets. The colors in such a palet can
+%D have colorful names, but best is to use names that specify
+%D their use, like {\em important} or {\em danger}. As a sort
+%D of example \CONTEXT\ has some palets predefined,
+%D like:\footnote{At the time I wrote the palet support, I was
+%D reading 'A hort history of time' of S.~Hawkins, so that's
+%D why we stuck to quarks.}
+%D
+%D \starttyping
+%D \definepalet
+%D [alfa]
+%D [ top=rood:7,
+%D bottom=groen:6,
+%D up=blauw:5,
+%D down=cyaan:4,
+%D strange=magenta:3,
+%D charm=geel:2]
+%D \stoptyping
+%D
+%D It's formal definition is:
+%D
+%D \showsetup{definepalet}
+%D
+%D Visualized, such a palet looks like:
+%D
+%D \startbuffer[palet]
+%D \showpalet [alfa] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \startlinecorrection
+%D \getbuffer[palet]
+%D \stoplinecorrection
+%D
+%D This bar shows both the color and gray alternatives of the
+%D palet components (not visible in black and white print).
+%D
+%D When needed, one can copy a palet by saying:
+%D
+%D \starttyping
+%D \definepalet [TEXcolorpretty] [colorpretty]
+%D \stoptyping
+%D
+%D This saves us some typing in for instance the modules that
+%D deal with pretty verbatim typesetting.
+
+\installcorenamespace{paletlist}
+\installcorenamespace{paletsize}
+
+\let\m_colo_palet\relax
+\let\c_colo_palet\relax
+
+\def\colo_palet_allocate#1%
+ {\expandafter\let \csname\??paletlist#1\endcsname\empty
+ \expandafter\newcount\csname\??paletsize#1\endcsname}
+
+\def\colo_palet_prepare#1%
+ {\edef\colo_palet_name{#1}%
+ \ifcsname\??paletlist\colo_palet_name\endcsname\else
+ \colo_palet_allocate\colo_palet_name
+ \fi
+ \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}%
+ \expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname}
+
+\def\colo_palet_extend#1%
+ {\addtocommalist{#1}\m_colo_palet
+ \expandafter\let\csname\??paletlist\colo_palet_name\endcsname\m_colo_palet
+ \advance\c_colo_palet\plusone}
+
+\unexpanded\def\doifelsecolorpalet#1%
+ {\ifcsname\??paletlist#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\paletlist\empty
+\let\paletsize\!!zerocount
+
+\unexpanded\def\getpaletlist[#1]%
+ {\edef\paletlist{\begincsname\??paletlist#1\endcsname}}
+
+\unexpanded\def\getpaletsize[#1]%
+ {\ifcsname\??paletsize#1\endcsname
+ \edef\paletsize{\the\lastnamedcs}%
+ \else
+ \let\paletsize\!!zerocount
+ \fi}
+
+\unexpanded\def\definepalet
+ {\dotripleempty\colo_palets_define}
+
+\def\colo_palets_define
+ {\ifthirdargument
+ \expandafter\colo_palets_define_b
+ \else
+ \expandafter\colo_palets_define_a
+ \fi}
+
+\unexpanded\def\colo_palets_define_a[#1][#2][#3]%
+ {\colo_palet_prepare{#1}%
+ \doifelseassignment{#2}
+ {\setevalue{\??colorpaletspecification#1}{#2}%
+ \processcommalist[#2]{\colo_palets_define_one{#1}}}
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \normalexpanded{\colo_palets_define[#1][\lastnamedcs]}%
+ \fi}}
+
+\unexpanded\def\colo_palets_define_b[#1][#2][#3]%
+ {\colo_palet_prepare{#1}%
+ \setevalue{\??colorpaletspecification#1}{#2}%
+ \colo_palet_extend{#2}%
+ \colo_palets_define_assign{#1}{#2}{#3}}
+
+\def\colo_palets_define_one#1#2% get rid of { }
+ {\doifelseassignment{#2} % catch empty entries
+ {\colo_palets_define_two{#1}[#2]}
+ {\colo_palets_define_three{#1}{#2}}}
+
+\def\colo_palets_define_two#1[#2=#3]%
+ {\colo_palet_extend{#2}%
+ \colo_palets_define_set{#1}{#2}{#3}}%
+
+\def\colo_palets_define_three#1#2%
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \processcommacommand[\lastnamedcs]{\colo_palets_define_one{#1}}%
+ \fi}
+
+%D Instead of refering to colors, one can also directly specify
+%D a color:
+%D
+%D \starttyping
+%D \definepalet[test][xx=green]
+%D \definepalet[test][xx={y=.4}]
+%D \stoptyping
+
+%D \macros
+%D {setuppalet}
+%D
+%D Colors are taken from the current palet, if defined.
+%D Setting the current palet is done by:
+%D
+%D \showsetup{setuppalet}
+
+\newtoks\everysetuppalet
+
+\unexpanded\def\setuppalet
+ {\dosingleempty\colo_palets_setup}
+
+\def\colo_palets_setup[#1]%
+ {\edef\currentcolorpalet{#1}%
+ \ifx\currentcolorpalet\empty
+ % seems to be a reset
+ \let\currentcolorprefix\empty
+ \else\ifcsname\??paletlist\currentcolorpalet\endcsname
+ \edef\currentcolorprefix{#1:}%
+ \else
+ \colo_helpers_show_message\m!colors7\currentcolorpalet
+ \let\currentcolorpalet\empty
+ \let\currentcolorprefix\empty
+ \fi\fi
+ \the\everysetuppalet
+ \colo_helpers_initialize_maintextcolor}
+
+%D \macros
+%D {showpalet}
+%D
+%D The previous visualization was typeset with:
+%D
+%D \typebuffer[palet]
+%D
+%D This commands is defined as:
+%D
+%D \showsetup{showpalet}
+
+\fetchruntimecommand \showpalet {\f!colorprefix\s!run}
+
+%D \macros
+%D {showcolorcomponents}
+%D
+%D \starttyping
+%D \showcolorcomponents[color-1,color-2]
+%D \stoptyping
+
+\fetchruntimecommand \showcolorcomponents {\f!colorprefix\s!run}
+
+%D \macros
+%D {comparepalet}
+%D
+%D There are some more testing macros available:
+%D
+%D \startbuffer
+%D \comparepalet [alfa]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows the palet colors against a background:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D The formal definition is:
+%D
+%D \showsetup{comparepalet}
+
+\fetchruntimecommand \comparepalet {\f!colorprefix\s!run}
+
+%D \macros
+%D {showcolor}
+%D
+%D But let's not forget that we also have the more traditional
+%D non||related colors. These show up after:
+%D
+%D \starttyping
+%D \showcolor [name]
+%D \stoptyping
+%D
+%D Where \type{name} for instance can be \type{rgb}.
+%D
+%D \showsetup{showcolor}
+
+\fetchruntimecommand \showcolor {\f!colorprefix\s!run}
+
+%D It would make sense to put the following code in \type
+%D {colo-mps}, but it it rather low level.
+
+%D \macros
+%D {negatecolorcomponent,negatedcolorcomponent}
+%D
+%D These speak for themselves. See \type {colo-ext} for usage.
+
+\unexpanded\def\negatecolorcomponent#1% #1 = \macro
+ {\scratchdimen\onepoint\advance\scratchdimen-#1\onepoint
+ \ifdim\scratchdimen<\zeropoint\scratchdimen\zeropoint\fi
+ \edef#1{\withoutpt\the\scratchdimen}}
+
+\def\negatedcolorcomponent#1%
+ {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint
+ \!!zerocount
+ \else
+ \expandafter\withoutpt\the\dimexpr\onepoint-#1\onepoint\relax
+ \fi}
+
+\unexpanded\def\negatecolorcomponent#1% #1 = \macro
+ {\edef#1{\negatedcolorcomponent{#1}}}
+
+%D \macros
+%D {MPcolor}
+%D
+%D A very special macro is \type{\MPcolor}. This one can be
+%D used to pass a \CONTEXT\ color to \METAPOST.
+%D
+%D \starttyping
+%D \MPcolor{my own red}
+%D \stoptyping
+%D
+%D This macro returns \METAPOST\ code that represents the
+%D color.
+%D
+%D For the moment we keep the next downward compatibility
+%D switch, i.e.\ expanded colors. However, predefined colors
+%D and palets are no longer expanded (which is what I wanted
+%D in the first place).
+%D
+%D In \MKIV\ we don't support color separation as we might now
+%D assume that printing houses have the right programs to do
+%D it themselves. If it's ever needed in \MKIV\ It is relatively
+%D easy to support it in the backend code.
+
+% todo: palets in definecolor
+% todo: {\red xx} vs \red{xx}
+
+% \def\mptexcolor#1{"\dogetattributeid\s!color \somecolorattribute{#1} A"}
+%
+% \startMPpage
+% fill fullcircle scaled 10cm ;
+% fill fullcircle scaled 5cm withprescript \mptexcolor{red} withpostscript \mptexcolor{black} ;
+% fill fullcircle scaled 3cm ;
+% draw btex test etex withprescript \mptexcolor{blue} ;
+% \stopMPpage
+
+\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
+ {\colo_helpers_set_model{#1}} % only for local usage
+
+\def\colo_helpers_set_model#1% direct
+ {\edef\currentcolormodel{#1}%
+ \clf_setcolormodel{\currentcolormodel}\v_colo_weight_state\relax} % sets attribute at lua end
+
+\colo_helpers_set_model\s!all
+
+\def\colo_helpers_set_current_model
+ {\ifconditional\c_colo_enabled
+ \ifconditional\c_colo_rgb_supported
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!all
+ \else
+ \colo_helpers_set_model\s!rgb
+ \fi
+ \else
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!cmyk
+ \else
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
+ \else
+ \colo_helpers_set_model\s!none
+ \fi
+ \fi
+ \fi
+ \else
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
+ \else
+ \colo_helpers_set_model\s!none
+ \fi
+ \fi}
+
+% Currently in mkiv transparency is implemented independent of color. This costs
+% a bit more processing time but gives the possibility to apply transparency
+% independently in the future. Is this useful? If not we may as well combine them
+% again in the future. By coupling we are downward compatible. When we decouple we
+% need to do more tricky housekeeping (e.g. persist color independent transparencies
+% when color bound ones are nil.
+
+% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
+
+\def\v_colo_dummy_name{d_u_m_m_y}
+
+\letvalue{\??colorsetter -}\empty % used?
+\letvalue{\??transparencysetter-}\empty % used?
+
+% new: expandable (see tbl)
+
+\def\colo_helpers_fast_activate
+ {\ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_fast_activate_nop
+ \else
+ \expandafter\colo_helpers_fast_activate_yes
+ \fi}
+
+\def\colo_helpers_fast_activate_yes#1%
+ {\ifcsname\??colorsetter\currentcolorprefix#1\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorprefix#1\endcsname
+ \else\ifcsname\??colorsetter#1\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter#1\endcsname
+ \fi\fi}
+
+\def\colo_helpers_fast_activate_nop#1%
+ {\ifcsname\??colorsetter#1\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter#1\endcsname
+ \fi}
+
+\let\dofastcoloractivation\colo_helpers_fast_activate
+
+% so far
+
+\def\colo_helpers_activate % two-step is not that much faster but less tracing
+ {\ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_activate_nop
+ \else
+ \expandafter\colo_helpers_activate_yes
+ \fi}
+
+\def\colo_helpers_activate_yes#1%
+ {\edef\currentcolorname{#1}%
+ \ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname
+ \else\ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorname\endcsname
+ \fi\fi}
+
+\def\colo_helpers_activate_nop#1%
+ {\edef\currentcolorname{#1}%
+ \ifcsname\??colorsetter\currentcolorname\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorname\endcsname
+ \fi}
+
+\def\colo_helpers_activate_dummy
+ {\csname\??colorsetter \v_colo_dummy_name\endcsname
+ \csname\??transparencysetter\v_colo_dummy_name\endcsname}
+
+\let\dousecolorparameter\colo_helpers_activate
+
+\unexpanded\def\dousecolorhashparameter#1#2%
+ {\ifcsname#1#2\endcsname
+ \expandafter\dousecolorparameter\csname#1#2\endcsname
+ \fi}
+
+\unexpanded\def\dousecurrentcolorparameter
+ {\let\currentcolorname\currentcolorparameter % maybe only when success
+ \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname
+ \else\ifcsname\??colorsetter\currentcolorparameter\endcsname
+ \lastnamedcs
+ \csname\??transparencysetter\currentcolorparameter\endcsname
+ \fi\fi}
+
+\let\dosetcolorattribute\dousecolorhashparameter % for a while
+
+\unexpanded\def\deactivatecolor % sort of public but a bad name
+ {\let\currentcolorname\s!black
+ \attribute\colorattribute\attributeunsetvalue
+ \attribute\transparencyattribute\attributeunsetvalue}
+
+% todo: check if color is overloading a non-color command
+
+\newcount\c_colo_protection
+
+\unexpanded\def\startprotectedcolors
+ {\advance\c_colo_protection\plusone}
+
+\unexpanded\def\stopprotectedcolors
+ {\advance\c_colo_protection\minusone}
+
+\def\colo_basics_define[#1][#2]%
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_global[#1][#2]%
+ {\clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_named[#1][#2]% currently same as define
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change)
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_defined_and_activated#1%
+ {\clf_defineprocesscolordummy{#1}%
+ \colo_helpers_activate_dummy}
+
+\def\colo_basics_define_process
+ {\ifthirdargument
+ \expandafter\colo_basics_define_process_yes
+ \else
+ \expandafter\colo_basics_define_process_nop
+ \fi}
+
+\def\colo_basics_define_process_yes[#1][#2][#3]%
+ {\clf_defineprocesscolorlocal{#1}{\processcolorcomponents{#2},#3}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_process_nop[#1][#2][#3]%
+ {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
+ \ifcase\c_colo_protection
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+% Spotcolors used setxvalue but that messes up currentcolor
+% and probably no global is needed either but they are global
+% at the lua end (true argument) so we keep that if only because
+% spot colors often are a document wide property
+
+\def\colo_basics_define_spot[#1][#2][#3]%
+ {\clf_definespotcolorglobal{#1}{#2}{#3}%
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+\def\colo_basics_define_multitone[#1][#2][#3][#4]%
+ {\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}%
+ \ifcase\c_colo_protection
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \fi}
+
+%D Transparencies (only):
+
+\def\colo_basics_define_transpancy[#1][#2]%
+ {\clf_definetransparency{#1}#2\relax}
+
+% A goodie that replaces the startMPcolor hackery
+
+% \definecolor[red-t] [r=1,t=0.5,a=1]
+% \definecolor[green-t][g=1,t=0.5,a=1]
+%
+% \defineintermediatecolor[mycolora][0.5,red,green]
+% \defineintermediatecolor[mycolorb][0.5,red-t,green-t]
+%
+% \definecolor[mycolorc][.5(blue,red)]
+% \definecolor[mycolord][.5(blue)]
+% \definecolor[mycolord][-.5(blue,red)] % complement
+% \definecolor[mycolord][-(blue)] % complement
+%
+% \enabledirectives[colors.pgf]
+% \definecolor[mycolorx][magenta!50!yellow]
+%
+% \starttext
+% test {\mycolora OEPS} test
+% test {\mycolorb OEPS} test
+% test {\mycolorc OEPS} test
+% test {\mycolord OEPS} test
+% test {\mycolorx OEPS} test
+% \stoptext
+%
+% Beware: if we say:
+%
+% \definecolor[one][two]
+%
+% only color one is actually defined and two is not seen at the
+% \LUA\ end. This means that this doesn't work:
+%
+% \definecolor[ColorA][red]
+% \definecolor[ColorB][.5(ColorA)]
+% \definecolor[ColorC][.5(ColorB,white)]
+%
+% But this does work:
+%
+% \definecolor[ColorA][1.0(red)]
+% \definecolor[ColorB][0.5(ColorA)]
+% \definecolor[ColorC][0.5(ColorB,white)]
+%
+% because the fractional definition results in a new definition.
+
+\unexpanded\def\defineintermediatecolor
+ {\dotripleempty\colo_basics_define_intermediate}
+
+\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside []
+ {\colo_basics_define_intermediate_indeed[#1][#2][#3]}
+
+\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]%
+ {\clf_defineintermediatecolor % not global
+ {#1}{#2}%
+ \thecolorattribute{#3} %
+ \thecolorattribute{#4} %
+ \thetransparencyattribute{#3} %
+ \thetransparencyattribute{#4} %
+ {#5}%
+ \v_colo_freeze_state
+ \relax
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
+
+%D Here is a more efficient helper for pgf:
+%D
+%D \starttying
+%D \startluacode
+%D function commands.pgfxcolorspec(ca) -- {}{}{colorspace}{list}
+%D local cv = attributes.colors.values[ca]
+%D if cv then
+%D local model = cv[1]
+%D if model == 2 then
+%D context("{}{}{gray}{%1.3f}",cv[2])
+%D elseif model == 3 then
+%D context("{}{}{rgb}{%1.3f,%1.3f,%1.3f}",cv[3],cv[4],cv[5])
+%D elseif model == 4 then
+%D context("{}{}{cmyk}{%1.3f,%1.3f,%1.3f,%1.3f}",cv[6],cv[7],cv[8],cv[9])
+%D else
+%D context("{}{}{gray}{%1.3f}",cv[2])
+%D end
+%D else
+%D context("{}{}{gray}{0}")
+%D end
+%D end
+%D \stopluacode
+%D
+%D \def\pgfutil@registercolor#1%
+%D {\setevalue{\string\color@#1}{\noexpand\xcolor@\ctxcommand{pgfxcolorspec(\thecolorattribute{#1})}}}
+%D
+%D \definecolor [darkblue] [r=0,g=0,b=0.5]
+%D
+%D \starttikzpicture
+%D \fill [blue] (0,0) circle(1);
+%D \fill [darkblue] (0,0) circle(1);
+%D \stoptikzpicture
+%D \stoptyping
+%D
+%D \stopmode
+
+\def\pgf@context@registercolor#1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\zerocount\thecolorattribute{#1}}}
+\def\pgf@context@registergray #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plustwo \thecolorattribute{#1}}}
+\def\pgf@context@registerrgb #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plusthree\thecolorattribute{#1}}}
+\def\pgf@context@registercmyk #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plusfour \thecolorattribute{#1}}}
+
+%D \starttyping
+%D \ifdefined\pgf@context@registercolor
+%D \let\pgfutil@registercolor\pgf@context@registercolor
+%D \fi
+%D \stoptyping
+
+%D \macros
+%D {doifcolorelse, doifcolor}
+%D
+%D Switching to a color is done by means of the following
+%D command. Later on we will explain the use of palets. We
+%D define ourselves a color conditional first.
+
+\def\doifelsecolor#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??colorattribute#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\let\doifcolorelse\doifelsecolor
+
+\def\doifcolor#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstofoneargument
+ \else\ifcsname\??colorattribute#1\endcsname
+ \doubleexpandafter\firstofoneargument
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+%D \macros
+%D {startregistercolor,stopregistercolor,permitcolormode}
+%D
+%D If you only want to register a color, the switch \type
+%D {\ifpermitcolormode} can be used. That way the nested
+%D colors know where to go back to.
+%D
+%D We use these macros for implementing text colors
+%D (actually, the first application was in foreground
+%D colors).
+%D
+%D \starttyping
+%D \starttextcolor[red]
+%D \dorecurse{10}{\input tufte \color[green]{oeps} \par}
+%D \stoptextcolor
+%D \stoptyping
+%D
+%D This is more efficient than the alternative:
+%D
+%D \starttyping
+%D \setupbackgrounds[text][foregroundcolor=red]
+%D \startregistercolor[red]
+%D \dorecurse{10}{\input tufte \color[green]{oeps} \par}
+%D \stopregistercolor
+%D \stoptyping
+
+\let\maintextcolor \empty
+\def\defaulttextcolor {black}
+\def\s!themaintextcolor{themaintextcolor}
+
+\unexpanded\def\inheritmaintextcolor
+ {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}
+
+\unexpanded\def\onlyinheritmaintextcolor
+ {\ifx\maintextcolor\empty
+ \deactivatecolor
+ \else
+ \colo_helpers_activate\maintextcolor
+ \fi}
+
+\appendtoks
+ \deactivatecolor % public?
+ \inheritmaintextcolor
+\to \everybeforeoutput
+
+\def\colo_helpers_switch_to_maintextcolor#1%
+ {\let\maintextcolor\s!themaintextcolor
+ \definecolor[\maintextcolor][#1]% can be fast one
+ \colo_helpers_activate\maintextcolor
+ \clf_registermaintextcolor\thecolorattribute\maintextcolor\relax}
+
+\unexpanded\def\starttextcolor[#1]%
+ {\doifsomething{#1}
+ {\colo_helpers_switch_to_maintextcolor{#1}}}
+
+\let\stoptextcolor\relax
+
+\let\p_colo_textcolor\empty
+
+\def\colo_helpers_initialize_maintextcolor
+ {\edef\p_colo_textcolor{\directcolorsparameter\c!textcolor}%
+ \ifx\p_colo_textcolor\empty
+ \colo_helpers_switch_to_maintextcolor\defaulttextcolor
+ \else
+ \colo_helpers_switch_to_maintextcolor\p_colo_textcolor
+ \fi}
+
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everyjob
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everysetupcolors
+
+\letvalue{\??colorsetter }\empty \letvalue{\??colorattribute }\!!zerocount
+\letvalue{\??transparencysetter}\empty \letvalue{\??transparencyattribute}\!!zerocount
+
+%def\colo_helpers_inherited_direct_cs#1{\csname\??colorsetter \ifcsname\??colorsetter #1\endcsname#1\fi\endcsname}
+%def\colo_helpers_inherited_direct_ca#1{\csname\??colorattribute \ifcsname\??colorattribute #1\endcsname#1\fi\endcsname}
+%def\colo_helpers_inherited_direct_ts#1{\csname\??transparencysetter \ifcsname\??transparencysetter #1\endcsname#1\fi\endcsname}
+%def\colo_helpers_inherited_direct_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute#1\endcsname#1\fi\endcsname}
+
+\def\colo_helpers_inherited_direct_cs#1{\ifcsname\??colorsetter #1\endcsname\lastnamedcs\fi}
+\def\colo_helpers_inherited_direct_ca#1{\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi}
+\def\colo_helpers_inherited_direct_ts#1{\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi}
+\def\colo_helpers_inherited_direct_ta#1{\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi}
+
+% %def\colo_helpers_inherited_palet_cs#1#2{\csname\??colorsetter \ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ca#1#2{\csname\??colorattribute \ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ts#1#2{\csname\??transparencysetter \ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+% %def\colo_helpers_inherited_palet_ta#1#2{\csname\??transparencyattribute\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
+%
+% \def\colo_helpers_inherited_palet_cs#1#2{\ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\lastnamedcs\fi}
+% \def\colo_helpers_inherited_palet_ca#1#2{\ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
+% \def\colo_helpers_inherited_palet_ts#1#2{\ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\lastnamedcs}
+% \def\colo_helpers_inherited_palet_ta#1#2{\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
+
+\let\colo_helpers_set_value\setvalue
+
+\appendtoks
+ \ifconditional\c_colo_expanded
+ \let\colo_helpers_set_value\setevalue
+ \else
+ \let\colo_helpers_set_value\setvalue
+ \fi
+\to \everysetupcolors
+
+% \def\colo_palets_define_set#1#2#3%
+% {\doifelseassignment{#3}% \definepalet[test][xx={y=.4}]
+% {\definecolor[\??colorpalet#1:#2][#3]%
+% \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_palet_ca{#1}{#2}}%
+% \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_palet_cs{#1}{#2}}%
+% \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_palet_ta{#1}{#2}}%
+% \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_palet_ts{#1}{#2}}}
+% {\ifcsname\??colorsetter#3\endcsname % \definepalet[test][xx=green]
+% \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{#3}}%
+% \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{#3}}%
+% \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{#3}}%
+% \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{#3}}%
+% \else
+% % not entered when making format
+% \localundefine{\??colorsetter #1:#2}%
+% \localundefine{\??colorattribute #1:#2}%
+% \localundefine{\??transparencysetter #1:#2}%
+% \localundefine{\??transparencyattribute#1:#2}%
+% \fi}}
+
+\def\colo_palets_define_set#1#2#3%
+ {\doifelseassignment{#3}% \definepalet[test][xx={y=.4}]
+ {\colo_palets_define_assign}%
+ {\ifcsname\??colorsetter#3\endcsname
+ % \definepalet[test][xx=green]
+ \expandafter\colo_palets_define_inherit
+ \else
+ % not entered when making format
+ \expandafter\colo_palets_define_undefine
+ \fi}%
+ {#1}{#2}{#3}}
+
+\def\colo_palets_define_inherit#1#2#3%
+ {\colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{#3}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{#3}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{#3}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{#3}}}
+
+\def\colo_palets_define_undefine#1#2#3%
+ {\localundefine{\??colorsetter #1:#2}%
+ \localundefine{\??colorattribute #1:#2}%
+ \localundefine{\??transparencysetter #1:#2}%
+ \localundefine{\??transparencyattribute#1:#2}}
+
+\def\colo_palets_define_assign#1#2#3%
+ {\definecolor[\??colorpalet#1:#2][#3]%
+ \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{\??colorpalet#1:#2}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{\??colorpalet#1:#2}}}
+
+\setvalue{\??colorattribute currentcolor}{\the\attribute\colorattribute} % for mpcolor
+\setvalue{\??transparencyattribute currentcolor}{\the\attribute\transparencyattribute} % for mpcolor
+
+%def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter \ifcsname\??colorsetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter \ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter #1\endcsname#1\fi\fi\endcsname}
+
+\def\colo_helpers_inherited_current_ca#1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_cs#1{\ifcsname\??colorsetter \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorsetter #1\endcsname\lastnamedcs\else\fi\fi}
+\def\colo_helpers_inherited_current_ta#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_ts#1{\ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\else\fi\fi}
+
+%D Low level defs:
+
+\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\attribute\colorattribute #2 }}
+\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\attribute\colorattribute #2 }} % was not g
+\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
+\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
+
+\unexpanded\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\unexpanded\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\unexpanded\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+\unexpanded\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+
+\unexpanded\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}}
+\unexpanded\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}}
+\unexpanded\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}}
+\unexpanded\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}}
+
+%D \macros
+%D {colorvalue, grayvalue}
+%D
+%D We can typeset the color components using \type{\colorvalue} and
+%D \type{\grayvalue}. The commands:
+%D
+%D \startbuffer
+%D color value of SomeKindOfRed: \colorvalue{SomeKindOfRed} \crlf
+%D gray value of SomeKindOfRed: \grayvalue{SomeKindOfRed}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D show us:
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+
+\let\currentcolorname\s!black % todo
+\let\outercolorname \s!black % todo
+
+\let\colorformatseparator\space
+
+\def\MPcolor#1%
+ {\clf_mpcolor
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \colo_helpers_inherited_current_ta{#1} }
+
+\def\MPcoloronly#1%
+ {\clf_mpcolor
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \zerocount}
+
+\def\MPtransparency#1%
+ {\clf_mpcolor
+ \zerocount
+ \zerocount
+ \colo_helpers_inherited_current_ta{#1} }
+
+\def\MPoptions#1%
+ {\clf_mpoptions
+ \attribute\colormodelattribute
+ \colo_helpers_inherited_current_ca{#1} %
+ \colo_helpers_inherited_current_ta{#1} }
+
+
+\def\thecolormodelattribute {\the\attribute\colormodelattribute}
+
+%def\thecolorattribute #1{\number\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+%def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+
+\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi\fi}
+\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi\fi}
+\def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} }
+\def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} }
+\def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} }
+
+\def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} }
+\def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} }
+\def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} }
+
+\def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}}
+\def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}}
+
+\def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} }
+\def\doifelsedrawingblack {\clf_doifelsedrawingblack}
+
+\let\doifblackelse \doifelseblack
+\let\doifdrawingblackelse \doifelsedrawingblack
+
+\let\doifblackelse \doifelseblack
+\let\doifdrawingblackelse\doifelsedrawingblack
+
+%D \macros
+%D {forcecolorhack}
+%D
+%D We can out this in front of (for instance) a special and so force color
+%D to be applied (only glyphs, rules and leaders are handled).
+%D
+%D \startbuffer
+%D \framed
+%D [background=color,backgroundcolor=yellow,framecolor=red,corner=round]
+%D {test}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% ignores in attribute handler
+%
+% \def\forcecolorhack{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
+
+% \normal added else fails in metafun manual (leaders do a hard scan)
+
+\unexpanded\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed !
+
+%D We default to the colors defined in \type {colo-imp-rgb} and
+%D support both \RGB\ and \CMYK\ output. Transparencies are defined
+%D here:
+
+\definecolor[black][s=0]
+\definecolor[white][s=1]
+
+\definetransparency [none] [0]
+\definetransparency [normal] [1]
+\definetransparency [multiply] [2]
+\definetransparency [screen] [3]
+\definetransparency [overlay] [4]
+\definetransparency [softlight] [5]
+\definetransparency [hardlight] [6]
+\definetransparency [colordodge] [7]
+\definetransparency [colorburn] [8]
+\definetransparency [darken] [9]
+\definetransparency [lighten] [10]
+\definetransparency [difference] [11]
+\definetransparency [exclusion] [12]
+\definetransparency [hue] [13]
+\definetransparency [saturation] [14]
+\definetransparency [color] [15]
+\definetransparency [luminosity] [16]
+
+\setupcolors
+ [\c!state=\v!stop, % color will be enabled later on
+ \c!conversion=\v!yes,
+ \c!rgb=\v!yes,
+ \c!cmyk=\v!yes,
+ \c!spot=\v!yes,
+ \c!pagecolormodel=\v!none,
+ \c!expansion=\v!no,
+ \c!textcolor=,
+ \c!factor=\v!yes]
+
+\setupcolor
+ [\v!rgb]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua b/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua
new file mode 100644
index 00000000000..6368b330716
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua
@@ -0,0 +1,74 @@
+if not modules then modules = { } end modules ['colo-run'] = {
+ version = 1.000,
+ comment = "companion to colo-run.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- For historic reasons the core has a couple of tracing features. Nowadays
+-- these would end up in modules.
+
+local colors, commands, context, utilities = colors, commands, context, utilities
+
+local colors = attributes.colors
+
+local private = table.tohash { "d_u_m_m_y", "maintextcolor", "themaintextcolor" }
+
+function commands.showcolorset(name)
+ local set = colors.setlist(name)
+ context.starttabulate { "|l|l|l|l|l|l|l|" }
+ for i=1,#set do
+ local s = set[i]
+ if not private[s] then
+ local r = { width = "4em", height = "max", depth = "max", color = s }
+ context.NC()
+ context.setcolormodel { "gray" }
+ context.blackrule(r)
+ context.NC()
+ context.blackrule(r)
+ context.NC()
+ context.grayvalue(s)
+ context.NC()
+ context.colorvalue(s)
+ context.NC()
+ context(s)
+ context.NC()
+ context.NR()
+ end
+ end
+ context.stoptabulate()
+end
+
+function commands.showcolorcomponents(list)
+ local set = utilities.parsers.settings_to_array(list)
+ context.starttabulate { "|lT|lT|lT|lT|" }
+ context.NC()
+ context("color")
+ context.NC()
+ context("name")
+ context.NC()
+ context("transparency")
+ context.NC()
+ context("specification ")
+ context.NC()
+ context.NR()
+ context.TB()
+ for i=1,#set do
+ local s = set[i]
+ if not private[s] then
+ context.NC()
+ context.showcolorbar { s }
+ context.NC()
+ context(s)
+ context.NC()
+ context.transparencycomponents(s)
+ context.NC()
+ context.colorcomponents(s)
+ context.NC()
+ context.NR()
+ end
+ end
+ context.stoptabulate()
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-run.mkiv
new file mode 100644
index 00000000000..37a9de19017
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/colo-run.mkiv
@@ -0,0 +1,255 @@
+%D \module
+%D [ file=colo-run,
+%D version=1997.04.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Runtime loaded commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{colo-run}{1.000}
+
+\unprotect
+
+%D Colors
+
+% These are nicer in \LUA\ code than in \TEX\ code but not more
+% efficient.
+
+\unexpanded\gdef\showcolorbar[#1]%
+ {\backgroundline[#1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}
+
+\unexpanded\gdef\showcolor {\dosingleempty\colo_basics_show}
+\unexpanded\gdef\showcolorset {\dosingleempty\colo_basics_show_set}
+\unexpanded\gdef\showcolorcomponents{\dosingleempty\colo_basics_show_components}
+
+\gdef\colo_basics_show_set [#1]{\ctxcommand{showcolorset("#1")}}
+\gdef\colo_basics_show_components[#1]{\ctxcommand{showcolorcomponents("#1")}}
+
+\gdef\colo_basics_show[#1]% % we do this at the tex end as loading happens
+ {\usecolors [#1]% % delayed and we can only ask for the set if
+ \showcolorset[#1]} % loading has happened
+
+% The rest might also be done in \LUA\ although there is not much
+% beauty to gain here (too much typesetting specific). Also, these
+% macros are pretty old and hardly used so best keep them as they
+% are.
+
+%D Palets
+
+\unexpanded\gdef\showpalet
+ {\dodoubleargument\colo_show_palet}
+
+\gdef\colo_show_palet[#1][#2]%
+ {\doifelsecolorpalet{#1}
+ {\doifelseinset\v!vertical{#2} \colo_palets_show_vertical \colo_palets_show_horizontal {#1}{#2}}%
+ {}}
+
+\gdef\colo_palets_show_vertical#1#2%
+ {\begingroup
+ \forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet[#1]
+ \tabskip\zeropoint
+ \def\colo_palets_show_palet##1%
+ {\doifelseinset\v!number{#2}{##1\hskip.5\emwidth}{}%
+ \aligntab
+ \color [##1]{\vrule\s!width3\emwidth\s!height\strutht\s!depth\strutdp}%
+ \graycolor[##1]{\vrule\s!width3\emwidth\s!height\strutht\s!depth\strutdp}%
+ \aligntab
+ \doifinset\v!value{#2}{\hskip.5\emwidth\colorvalue{##1}}%
+ \crcr}
+ \halign
+ {\hss\alignmark\alignmark\aligntab\hss\alignmark\alignmark\hss\aligntab\alignmark\alignmark\cr
+ \aligntab\doifinset\v!name{#2}{\strut#1}\aligntab\cr
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr}%
+ \endgroup}
+
+\gdef\colo_palets_show_horizontal#1#2% todo: bTABLE etc
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet[#1]
+ \tabskip\zeropoint
+ \scratchwidth\zeropoint
+ \doifinset\v!number{#2}
+ {\def\colo_palets_show_palet##1%
+ {\setbox\scratchbox\hbox{##1}%
+ \ifdim\scratchwidth<\wd\scratchbox
+ \scratchwidth\wd\scratchbox
+ \fi}%
+ \colo_palets_process[#1]\colo_palets_show_palet}%
+ \advance\scratchwidth\emwidth
+ \ifdim\scratchwidth<5\emwidth
+ \scratchwidth5\emwidth
+ \fi
+ \halign
+ {\alignmark\alignmark\aligntab\aligntab\hbox to \scratchwidth{\hss\alignmark\alignmark\hss}\cr
+ \doifinset\v!number{#2}
+ {\def\colo_palets_show_palet##1{\aligntab\strut##1}%
+ \colo_palets_process[#1]\colo_palets_show_palet}\cr
+ \doifinset\v!name{#2}{#1\hskip.5\emwidth}%
+ \def\colo_palets_show_palet##1%
+ {\aligntab\strut\color[##1]{\vrule\s!width\scratchwidth\s!height\strutht\s!depth\zeropoint}}%
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr
+ \noalign{\vskip-\strutdepth}%
+ \def\colo_palets_show_palet##1%
+ {\aligntab\graycolor[##1]{\vrule\s!width\scratchwidth\s!height\zeropoint\s!depth\strutdp}}%
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr
+ \doifinset\v!value{#2}
+ {\def\colo_palets_show_palet##1%
+ {\aligntab\vbox
+ {\hsize\scratchwidth
+ \vskip.25\exheight
+ \everypar{\strut}
+ \veryraggedcenter
+ \let\colorformatseparator\endgraf
+ \colorvalue{##1}}}%
+ \colo_palets_process[#1]\colo_palets_show_palet}%
+ \crcr}}}
+
+\gdef\colo_palets_process[#1]%
+ {\getpaletlist[#1]%
+ \normalexpanded{\globalprocesscommalist[\paletlist]}}
+
+\unexpanded\gdef\comparepalet
+ {\dosingleargument\colo_palets_compare}
+
+\gdef\colo_palets_compare[#1]%
+ {\doifelsecolorpalet{#1}%
+ {\hbox
+ {\colo_palets_compare_indeed\color{#1}%
+ \quad
+ \colo_palets_compare_indeed\graycolor{#1}}}%
+ {}}
+
+\gdef\colo_palets_compare_indeed#1#2%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet[#2]
+ \getpaletsize[#2]%
+ \getpaletlist[#2]%
+ \scratchwidth2\emwidth\relax
+ \hsize\paletsize\scratchwidth
+ \def\colo_palets_compare##1%
+ {\hbox
+ {\setbox0\hbox
+ {#1[##1]{\vrule\s!width\hsize\s!height3ex}}%
+ \wd0\zeropoint
+ \box0
+ \hbox to \hsize
+ {\def\colo_palets_compare####1%
+ {\hbox to \scratchwidth
+ {\hss#1[####1]{\vrule\s!width.5\scratchwidth\s!height2.25\exheight\s!depth-.75\exheight}\hss}}%
+ \processcommacommand[\paletlist]\colo_palets_compare}}
+ \endgraf}
+ \processcommacommand[\paletlist]\colo_palets_compare}}
+
+%D Groups
+
+\unexpanded\gdef\showcolorgroup
+ {\dodoubleargument\colo_groups_show}
+
+\gdef\colo_groups_show[#1][#2]%
+ {\doifcolor{#1:1}
+ {\doifelseinset\v!vertical{#2}
+ \colo_groups_show_vertical
+ \colo_groups_show_horizontal
+ [#1][#2]}}
+
+\gdef\colo_groups_show_horizontal[#1][#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet
+ \tabskip\zeropoint
+ \def\colorformatseparator{\strut\cr}
+ \def\colo_groups_show_group##1%
+ {\doifcolor{#1:##1}{\vbox
+ {\halign
+ {\hss\alignmark\alignmark\alignmark\alignmark\hss\cr
+ \doifinset\v!number{#2}{\strut##1}\cr
+ \color [#1:##1]{\vrule\s!width4\emwidth\s!height\strutht \s!depth\zeropoint}\cr
+ \graycolor[#1:##1]{\vrule\s!width4\emwidth\s!height\zeropoint\s!depth\strutdp }\cr
+ \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}}}%
+ \hbox
+ {\doifinset\v!name{#2}
+ {\strut
+ \doifelseinset\v!value{#2}
+ {\raise3\lineheight\hbox{#1\hskip.5\emwidth}}
+ {#1}%
+ \hskip.5\emwidth}%
+ \colo_groups_show_group1\colo_groups_show_group2\colo_groups_show_group3\colo_groups_show_group4%
+ \colo_groups_show_group5\colo_groups_show_group6\colo_groups_show_group7\colo_groups_show_group8}}}
+
+\gdef\colo_groups_show_vertical[#1][#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet
+ \tabskip\zeropoint
+ \def\colo_groups_show_group##1%
+ {\doifcolor{#1:##1}
+ {\doifinset\v!number{#2}
+ {##1\hskip.5\emwidth}%
+ \aligntab
+ \color [#1:##1]{\vrule\s!width2.5\emwidth\s!height\strutht\s!depth\strutdp}%
+ \graycolor[#1:##1]{\vrule\s!width2.5\emwidth\s!height\strutht\s!depth\strutdp}
+ \aligntab
+ \doifinset\v!value{#2}{\hskip.5\emwidth\colorvalue{#1:##1}}%
+ \crcr}}%
+ \halign
+ {\hss\alignmark\alignmark\aligntab\hss\alignmark\alignmark\hss\aligntab\alignmark\alignmark\hss\cr
+ \aligntab\doifinset\v!name{#2}{\strut#1}\aligntab\crcr
+ \colo_groups_show_group1\colo_groups_show_group2\colo_groups_show_group3\colo_groups_show_group4%
+ \colo_groups_show_group5\colo_groups_show_group6\colo_groups_show_group7\colo_groups_show_group8}}}
+
+\unexpanded\gdef\comparecolorgroup
+ {\dosingleargument\colo_groups_compare}
+
+\gdef\colo_groups_compare[#1]%
+ {\doifcolor{#1:1}
+ {\hbox
+ {\colo_groups_compare_indeed\color [#1]\quad
+ \colo_groups_compare_indeed\graycolor[#1]}}}
+
+\gdef\colo_groups_compare_indeed#1[#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \scratchcounter\zerocount
+ \dorecurse{15}{\doifcolor{#2:\recurselevel}{\advance\scratchcounter\plusone}}
+ \scratchwidth2\emwidth\relax
+ \hsize\scratchcounter\scratchwidth
+ \dorecurse\scratchcounter{\colo_groups_compare_step{#1}{#2}\recurselevel}}}
+
+\def\colo_groups_compare_step#1#2#3%
+ {\hbox to \hsize
+ {\setbox\scratchbox\hbox
+ {#1[#2:#3]{\vrule\s!width\hsize\s!height3\exheight}}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox
+ \hbox to \hsize
+ {\hss
+ \dorecurse\scratchcounter
+ {#1[#2:\recurselevel]{\vrule\s!width.5\scratchwidth\s!height2.25\exheight\s!depth-.75\exheight}%
+ \hss}}}
+ \endgraf}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-cs.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-cs.mkiv
new file mode 100644
index 00000000000..75e30fe6985
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-cs.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-cs,
+%D version=1998.12.02,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Czech 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {czech}
+\def\defaultlanguagetag{cs}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-de.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-de.mkiv
new file mode 100644
index 00000000000..998f76466da
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-de.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-de,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ German 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {german}
+\def\defaultlanguagetag{de}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-en.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-en.mkiv
new file mode 100644
index 00000000000..f25ab69cbd1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-en.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-en,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {english}
+\def\defaultlanguagetag{en}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-fil.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-fil.mkiv
new file mode 100644
index 00000000000..19c1c93ac06
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-fil.mkiv
@@ -0,0 +1,126 @@
+%D \module
+%D [ file=cont-fil,
+%D version=1997.11.15,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=File Synonyms,
+%D author=J. Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: use full names and remove calls at the tex end (now integrated in
+% lua library code
+
+\writestatus{loading}{ConTeXt File Synonyms}
+
+\definefilesynonym [chemics] [chemic]
+
+\definefilesynonym [unit] [units]
+
+\definefilesynonym [pstric] [pstricks]
+\definefilesynonym [pstrick] [pstricks]
+
+\definefilesynonym [finance] [financ]
+
+\definefilesynonym [dir-make] [dir-01]
+\definefilesynonym [dir-identify] [dir-05]
+
+\definefilesynonym [int-load] [set-11]
+\definefilesynonym [int-make] [set-12]
+
+ \definefilesynonym [fig-base] [fig-00]
+ \definefilesynonym [fig-make] [fig-01]
+ \definefilesynonym [fig-fake] [fig-02]
+ \definefilesynonym [fig-missing] [fig-06]
+
+\definefilesynonym [exi-interface] [exi-21]
+
+ \definefilesynonym [res-make] [res-01]
+ \definefilesynonym [res-base] [res-04]
+ \definefilesynonym [res-crop] [res-07]
+ \definefilesynonym [res-trace] [res-08]
+ \definefilesynonym [res-log] [res-09]
+ \definefilesynonym [res-identify] [res-12]
+
+\definefilesynonym [med-show] [res-50]
+
+\definefilesynonym [pre-general] [pre-00]
+
+\definefilesynonym [pre-original] [pre-01]
+\definefilesynonym [pre-green] [pre-02]
+\definefilesynonym [pre-funny] [pre-03]
+\definefilesynonym [pre-colorful] [pre-04]
+\definefilesynonym [pre-fuzzy] [pre-05]
+\definefilesynonym [pre-polish] [pre-06]
+\definefilesynonym [pre-spider] [pre-07]
+\definefilesynonym [pre-wonder] [pre-08]
+\definefilesynonym [pre-windows] [pre-09]
+\definefilesynonym [pre-grow] [pre-10]
+\definefilesynonym [pre-stack] [pre-11]
+\definefilesynonym [pre-arrows] [pre-12]
+\definefilesynonym [pre-writing] [pre-13]
+\definefilesynonym [pre-split] [pre-14]
+\definefilesynonym [pre-balls] [pre-15]
+\definefilesynonym [pre-knot] [pre-16]
+\definefilesynonym [pre-weird] [pre-17]
+\definefilesynonym [pre-shade] [pre-18]
+\definefilesynonym [pre-organic] [pre-19]
+\definefilesynonym [pre-speckle] [pre-20]
+\definefilesynonym [pre-zoom] [pre-21]
+\definefilesynonym [pre-cycle] [pre-22]
+\definefilesynonym [pre-super] [pre-23]
+
+%definefilesynonym [pre-more] [pre-24]
+%definefilesynonym [pre-more] [pre-25]
+\definefilesynonym [pre-more] [pre-26]
+%definefilesynonym [pre-more] [pre-27]
+%definefilesynonym [pre-more] [pre-28]
+%definefilesynonym [pre-more] [pre-29]
+%definefilesynonym [pre-more] [pre-30]
+
+\definefilesynonym [pre-tiles] [pre-41]
+
+\definefilesynonym [pre-stepwise] [pre-60]
+\definefilesynonym [pre-stepper] [pre-61]
+
+\definefilesynonym [pre-punk] [pre-70]
+\definefilesynonym [pre-random] [pre-71]
+
+\definefilesynonym [abr-pseudocaps] [abr-01]
+\definefilesynonym [abr-smallcaps] [abr-02]
+
+\definefilesynonym [pracjourn] [ptj-01]
+\definefilesynonym [maps] [map-10]
+
+\definefilesynonym [mml] [mathml]
+\definefilesynonym [cml] [chemml]
+
+\definefilesynonym [letter] [cor-01]
+\definefilesynonym [memo] [cor-02]
+\definefilesynonym [resume] [cor-03]
+
+% downward compatible mapping:
+
+\definefilesynonym [pre-41] [present-tiles]
+\definefilesynonym [fnt-29] [fonts-shapes]
+\definefilesynonym [fnt-33] [math-coverage]
+\definefilesynonym [mat-12] [math-parameters]
+\definefilesynonym [mat-20] [math-parameters]
+\definefilesynonym [fnt-25] [math-characters]
+\definefilesynonym [fnt-28] [fonts-goodies]
+\definefilesynonym [fnt-31] [fonts-coverage]
+\definefilesynonym [mat-10] [math-characters]
+\definefilesynonym [mat-11] [math-characters]
+\definefilesynonym [fnt-11] [fonts-system]
+\definefilesynonym [fnt-23] [fonts-shapes]
+\definefilesynonym [syn-01] [syntax]
+
+\definefilesynonym [set-11] [setups-basics]
+\definefilesynonym [set-12] [setups-overview]
+%definefilesynonym [set-13] [setups-proofing]
+%definefilesynonym [set-15] [setups-generate]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-fr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-fr.mkiv
new file mode 100644
index 00000000000..f45ec88c3f7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-fr.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-de,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ French 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {french}
+\def\defaultlanguagetag{fr}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-gb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-gb.mkiv
new file mode 100644
index 00000000000..f6dd4ba9ebc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-gb.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-uk,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {english}
+\def\defaultlanguagetag{gb}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-it.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-it.mkiv
new file mode 100644
index 00000000000..483eb858955
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-it.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-it,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Italian 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {italian}
+\def\defaultlanguagetag{it}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv
new file mode 100644
index 00000000000..b8eb0679f3b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv
@@ -0,0 +1,326 @@
+%D \module
+%D [ file=cont-log,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=\TEX\ Logos,
+%D author=J. 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 TeX Logos}
+
+%D The system that is used to typeset this text is called \TEX, typeset with an
+%D lowered~E. From te beginning of \TEX, authors of macro packages adapted this
+%D raising and lowering style. In this module we define some of those logos.
+
+\unprotect
+
+\unexpanded\def\TeX
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{M}%
+ T%
+ \kern-.1667\wd\scratchbox
+ \lower.5\exheight\hbox{E}%
+ \kern-.125\wd\scratchbox
+ X%
+ \endgroup}
+
+\unexpanded\def\ConTeXt
+ {\dontleavehmode
+ \begingroup
+ Con%
+ \setbox\scratchboxone\hbox{T\kern\zeropoint e}%
+ \setbox\scratchboxtwo\hbox{Te}%
+ \discretionary{-}{}{\kern\dimexpr\wd\scratchboxtwo-\wd\scratchboxone\relax}%
+ \TeX
+ t%
+ \endgroup}
+
+\unexpanded\def\PPCHTeX{ppch\TeX}
+\unexpanded\def\PRAGMA {Pragma ADE}
+
+\unexpanded\def\LaTeX % requested by erik frambach
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{L}%
+ \scratchdimen\ht\scratchbox
+ \setbox\scratchbox\hbox{\txx A}%
+ L\kern-.55\wd\scratchbox
+ \raise\scratchdimen\hbox{\lower\ht\scratchbox\copy\scratchbox}%
+ \kern-.2\wd\scratchbox\TeX
+ \endgroup}
+
+\unexpanded\def\TaBlE
+ {T%
+ \kern-.27\emwidth\lower.5\exheight\hbox{A}%
+ \kern-.18\emwidth B%
+ \kern-.1\emwidth\lower.5\exheight\hbox{L}%
+ \kern-.075\emwidth E}
+
+\unexpanded\def\PiCTeX
+ {P%
+ \kern-.12\emwidth\lower.5\exheight\hbox{I}%
+ \kern-.075\emwidth C%
+ \kern-.11\emwidth\TeX}
+
+\def\syst_logos_ams_script#1%
+ {\normalstartimath
+ \cal\ifdim\bodyfontsize>1.1\emwidth\scriptstyle\fi#1%
+ \normalstopimath}
+
+\unexpanded\def\AmSTeX
+ {\dontleavehmode
+ \syst_logos_ams_script A%
+ \kern-.1667\emwidth\lower.5\exheight\hbox{\syst_logos_ams_script M}%
+ \kern-.125\emwidth\syst_logos_ams_script S%
+ -\TeX}
+
+\unexpanded\def\LamSTeX
+ {L%
+ \kern-.4\emwidth\raise.3\exheight\hbox{\syst_logos_ams_script A}%
+ \kern-.25\emwidth\lower.4\exheight\hbox{\syst_logos_ams_script M}%
+ \kern-.1\emwidth{\syst_logos_ams_script S}%
+ -\TeX}
+
+% \unexpanded\def\AmSLaTeX
+% {\dontleavehmode
+% \syst_logos_ams_script A%
+% \kern-.1667\emwidth\lower.5\exheight\hbox{\syst_logos_ams_script M}%
+% \kern-.125\emwidth{\syst_logos_ams_script S}%
+% -\LaTeX}
+
+%D Alternative \CONTEXT\ logo, first Idris S.~Hamid's version:
+%D
+%D \def\Context
+%D {{\sc C\kern -.0667emo\kern -.0667emn\kern -.0549emt\kern
+%D -.1667em\lower.5ex\hbox {e}\kern -.125emx\kern -.0549emt}}
+%D
+%D I changed this into one that adapts itself:
+
+\unexpanded\def\Context % wrong usage of \getscaledglyph
+ {\dontleavehmode
+ \begingroup
+ C%
+ \kern -.0667\emwidth
+ \getscaledglyph{.8}\empty{%
+ O\kern-.0667\emwidth
+ N%
+ \discretionary{-}{}{\kern-.0549\emwidth}%
+ T%
+ \doifelseitalic
+ {\kern-.1\emwidth}%
+ {\kern-.1667\emwidth}%
+ \lower.5\exheight\hbox{E}%
+ \doifelseitalic
+ \empty
+ {\kern-.11em}%
+ X%
+ \kern-.055\emwidth
+ T%
+ }%
+ \endgroup}
+
+%D The \METAFONT\ and \METAPOST\ logos adapt themselves to the current fontsize, an
+%D ugly but usefull hack.
+
+\let\logofont\nullfont
+
+\loadmapfile[original-base.map] % stil needed? not if we assume afm
+
+\unexpanded\def\setMFPfont% more sensitive for low level changes
+ {\font\logofont=logo%
+ \ifx\fontalternative\s!bf\s!bf\else
+ \ifx\fontalternative\s!it\s!sl\else
+ \ifx\fontalternative\s!sl\s!sl\else
+ \ifx\fontalternative\s!bi\s!bf\else
+ \ifx\fontalternative\s!bs\s!bf\else
+ \fi\fi\fi\fi\fi
+ 10 at \currentfontscale\bodyfontsize % there is no afm in the minimals yet
+ \logofont}
+
+\def\syst_logos_meta_hyphen % there is no hyphenchar in this font
+ {\discretionary{\vrule\s!height.33\emwidth\s!depth-.27\emwidth\s!width.33\emwidth}{}{}}
+
+\unexpanded\def\MetaFont
+ {\dontleavehmode
+ \begingroup
+ \setMFPfont META\syst_logos_meta_hyphen FONT%
+ \endgroup}
+
+% \unexpanded\def\MetaPost
+% {\dontleavehmode
+% \begingroup
+% \setMFPfont META\syst_logos_meta_hyphen POST%
+% \endgroup}
+%
+% As decided on the ConText Meeting 2013 the logo has been simplified:
+
+\unexpanded\def\MetaPost
+ {MetaPost}
+
+\unexpanded\def\MetaFun
+ {MetaFun}
+
+%D \macros
+%D {TEX, METAFONT, METAPOST, METAFUN,
+%D PICTEX, TABLE,
+%D CONTEXT, PPCHTEX,
+%D AMSTEX, LATEX, LAMSTEX}
+%D
+%D We define the funny written ones as well as the less error prone upper case names
+%D (in \CONTEXT\ we tend to write all user defined commands, like abbreviations, in
+%D uppercase.)
+
+\unexpanded\def\METAFONT {\MetaFont}
+\unexpanded\def\METAPOST {\MetaPost}
+\unexpanded\def\PPCHTEX {\PPCHTeX}
+\unexpanded\def\CONTEXT {\ConTeXt}
+\unexpanded\def\METAFUN {\MetaFun}
+
+\unexpanded\def\TEX {\TeX}
+\unexpanded\def\LATEX {\LaTeX}
+\unexpanded\def\PICTEX {\PiCTeX}
+\unexpanded\def\TABLE {\TaBlE}
+\unexpanded\def\AMSTEX {\AmSTeX}
+\unexpanded\def\LAMSTEX {\LamSTeX}
+\unexpanded\def\INRSTEX {inrs\TeX}
+
+%D And this is how they show up: \TeX, \MetaFont, \MetaPost, \PiCTeX, \TaBlE, \ConTeXt,
+%D \PPCHTeX, \AmSTeX, \LaTeX, \LamSTeX.
+
+%D Some placeholders:
+
+\unexpanded\def\eTeX {\mathematics{\varepsilon}-\TeX}
+\unexpanded\def\pdfTeX {pdf\TeX}
+\unexpanded\def\pdfeTeX {pdfe-\TeX}
+\unexpanded\def\luaTeX {lua\TeX}
+\unexpanded\def\luajitTeX{luajit\TeX}
+\unexpanded\def\metaTeX {meta\TeX}
+\unexpanded\def\XeTeX {X\lower.5\exheight\hbox{\kern-.15\emwidth\mirror{E}}\kern-.1667\emwidth\TeX}
+
+% Adapted from a patch by Mojca:
+
+\def\syst_logos_xetex_e
+ {\setbox\scratchbox\hbox{E}%
+ \raise\dimexpr\ht\scratchbox+\dp\scratchbox\relax\hbox{\rotate[\c!rotation=180]{\box\scratchbox}}}
+
+\unexpanded\def\XeTeX
+ {X\lower.5\exheight
+ \hbox
+ {\kern-.15\emwidth
+ \iffontchar\font"018E\relax
+ \char"018E%
+ \else
+ \ifx\fontalternative\s!bf \mirror{E}\else
+ \ifx\fontalternative\s!it\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!sl\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!bi\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!bs\syst_logos_xetex_e\else
+ \mirror{E}\fi\fi\fi\fi\fi
+ \fi}%
+ \kern-.1667\emwidth\TeX}
+
+\let\ETEX \eTeX
+\let\PDFTEX \pdfTeX
+\let\PDFETEX \pdfeTeX
+\let\LUATEX \luaTeX
+\let\LUAJITTEX\luajitTeX
+\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
+ Lua%
+ % hope for kerning, try aT
+ \setbox0\hbox{aT}%
+ \setbox2\hbox{a\kern\zeropoint T}%
+ \ifdim\wd0=\wd2 % kerns can go two ways
+ % no aT kerning, try oT as a is not symmetrical
+ \setbox0\hbox{oT}%
+ \setbox2\hbox{o\kern\zeropoint T}%
+ \ifdim\wd0=\wd2 % kerns can go two ways
+ % no aT and oT kerning, try To
+ \setbox0\hbox{To}%
+ \setbox2\hbox{T\kern\zeropoint o}%
+ % maybe we need to compensate for the angle (sl/it/bs/bi)
+ \fi
+ \ifdim\wd0=\wd2\else
+ \kern\dimexpr\wd0-\wd2\relax
+ \fi
+ \fi
+ \TeX
+ \endgroup}
+
+\unexpanded\def\LuajitTeX
+ {\dontleavehmode
+ \begingroup
+ % at this moment there is no real need for kerning tT
+ Luajit\kern\zeropoint\TeX
+ \endgroup}
+
+\let\luaTeX \LuaTeX
+\let\luajitTeX\LuajitTeX
+\let\LUATEX \LuaTeX
+\let\LUAJITTEX\LuajitTeX
+
+\unexpanded\def\MKII{MkII}
+\unexpanded\def\MKIV{MkIV}
+\unexpanded\def\MKVI{MkVI}
+\unexpanded\def\MKIX{MkIX}
+\unexpanded\def\MKXI{MkXI}
+
+\unexpanded\def\MPII{MpII}
+\unexpanded\def\MPIV{MpIV}
+\unexpanded\def\MPVI{MpVI}
+
+\appendtoks
+ \def\ConTeXt {ConTeXt}%
+ \def\MetaPost {MetaPost}%
+ \def\MetaFont {MetaFont}%
+ \def\MetaFun {MetaFun}%
+ \def\TeX {TeX}%
+ \def\LuaTeX {LuaTeX}%
+ \def\LuajitTeX{LuajitTeX}%
+\to \everysimplifycommands
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv
new file mode 100644
index 00000000000..caa9c31df7d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv
@@ -0,0 +1,141 @@
+%D \module
+%D [ file=cont-new,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=New Macros,
+%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.
+
+\newcontextversion{2016.04.21 19:35}
+
+%D This file is loaded at runtime, thereby providing an excellent place for
+%D hacks, patches, extensions and new features.
+
+% \usemodule[newotf]
+% \usemodule[oldotf]
+
+\unprotect
+
+% \writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
+
+% \attribute152\zerocount : marks ... lots of sweeps so best early in list
+
+%D Maybe:
+
+% \appendtoks
+% \inheritmaintextcolor
+% \to \everybeforenoteinsert
+
+% \appendtoks
+% \inheritmaintextcolor
+% \to \everymargindatacontent
+
+% This is experimental; if this changes we need to adapt the mb-mp style too. It's
+% not in the core yet.
+%
+% \def\ActionY{\blank\inleftmargin{\shownofparlines}}
+% \def\ActionN{\inleftmargin{\shownofparlines}}
+%
+% \saveparnumber
+% ...
+% \checknofparlines
+% \ifnum\nofparlines<2
+% \ActionY
+% \else
+% \ActionN
+% \fi
+% ...
+
+\newcount\c_typo_par_current
+\newcount\c_typo_par_saved
+\newcount\c_typo_par_lines
+\newcount\c_typo_par_temp
+
+\appendtoks
+ \advance\c_typo_par_current\plusone % local
+ %\llap{\infofont[\the\c_typo_par_saved:\the\c_typo_par_current]\quad}%
+\to \everypar
+
+\unexpanded\def\saveparnumber % the upcoming number
+ {\c_typo_par_saved\c_typo_par_current} % local
+
+\def\savedparnumber {\number\c_typo_par_saved}
+\def\currentparnumber{\number\c_typo_par_current}
+\def\nofparlines {\number\c_typo_par_lines}
+\let\savedparstate \empty
+
+\unexpanded\def\shownofparlines
+ {\dontleavehmode\hbox\bgroup
+ \infofont[\savedparstate]%
+ \egroup}
+
+\unexpanded\def\checknofparlines
+ {\c_typo_par_temp\numexpr\c_typo_par_saved+\plusone\relax
+ \ifhmode
+ \c_typo_par_lines\zerocount
+ \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space-}%
+ \else\ifnum\c_typo_par_current=\c_typo_par_temp
+ \c_typo_par_lines\prevgraf
+ \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space\number\prevgraf}%
+ \else\ifnum\c_typo_par_temp>\c_typo_par_current
+ \c_typo_par_lines\zerocount
+ \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space-}%
+ \else
+ \c_typo_par_lines\maxdimen
+ \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space+}%
+ \fi\fi\fi}
+
+%D Maybe:
+
+\unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
+\unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
+
+%D Needs some work:
+
+\unexpanded\def\startgridcorrection
+ {\dosingleempty\spac_grid_correction_start}
+
+\def\spac_grid_correction_start[#1]%
+ {\ifgridsnapping
+ \snaptogrid[#1]\vbox\bgroup
+ \else
+ \startbaselinecorrection
+ \fi}
+
+\unexpanded\def\stopgridcorrection
+ {\ifgridsnapping
+ \egroup
+ \else
+ \stopbaselinecorrection
+ \fi}
+
+\unexpanded\def\checkgridsnapping
+ {\lineskip\ifgridsnapping\zeropoint\else\normallineskip\fi}
+
+%D Probably obsolete:
+
+\unexpanded\def\startcolumnmakeup % don't change
+ {\bgroup
+ \getrawnoflines\textheight % raw as we cna have topskip
+ \setbox\scratchbox\vbox to \dimexpr\noflines\lineheight-\lineheight+\topskip\relax
+ \bgroup
+ \forgetall}
+
+\unexpanded\def\stopcolumnmakeup
+ {\egroup
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\textwidth
+ \box\scratchbox
+ \egroup
+ \page_otr_command_synchronize_hsize}
+
+%D Till we fixed all styles:
+
+\let\\=\crlf
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-nl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-nl.mkiv
new file mode 100644
index 00000000000..890ad8ca594
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-nl.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-nl,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Dutch 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {dutch}
+\def\defaultlanguagetag{nl}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-nop.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-nop.mkiv
new file mode 100644
index 00000000000..c8188503e85
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-nop.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-nop,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Dummy,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\writestatus\m!system{loading dummy replacement for jobname}
+
+\protect
+
+\finishjob
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-pe.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-pe.mkiv
new file mode 100644
index 00000000000..4f7efe959d5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-pe.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-en,
+%D version=1997.08.19,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ English 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {persian}
+\def\messageinterface {english}
+\def\defaultlanguagetag{pe}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-ro.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-ro.mkiv
new file mode 100644
index 00000000000..ac6f159f539
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-ro.mkiv
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=cont-ro,
+%D version=2000.01.09,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Romanian 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.
+
+\catcode`\{=1 \catcode`\}=2
+
+\def\defaultinterface {romanian}
+\def\defaultlanguagetag{ro}
+
+\input context.mkiv
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua b/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua
new file mode 100644
index 00000000000..0420ed01c7b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua
@@ -0,0 +1,252 @@
+if not modules then modules = { } end modules ['cont-run'] = {
+ version = 1.001,
+ comment = "companion to cont-yes.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- When a style is loaded there is a good change that we never enter
+-- this code.
+
+local report = logs.reporter("system")
+
+local type, tostring = type, tostring
+
+local report = logs.reporter("sandbox","call")
+local fastserialize = table.fastserialize
+local quoted = string.quoted
+local possiblepath = sandbox.possiblepath
+
+local context = context
+local implement = interfaces.implement
+
+local qualified = { }
+local writeable = { }
+local readable = { }
+local blocked = { }
+local trace_files = false
+local trace_calls = false
+local nofcalls = 0
+local nofrejected = 0
+local logfilename = "sandbox.log"
+
+local function registerstats()
+ statistics.register("sandboxing", function()
+ if trace_files then
+ return string.format("%s calls, %s rejected, logdata in '%s'",nofcalls,nofrejected,logfilename)
+ else
+ return string.format("%s calls, %s rejected",nofcalls,nofrejected)
+ end
+ end)
+ registerstats = false
+end
+
+local function logsandbox(details)
+ local comment = details.comment
+ local result = details.result
+ local arguments = details.arguments
+ for i=1,#arguments do
+ local argument = arguments[i]
+ local t = type(argument)
+ if t == "string" then
+ arguments[i] = quoted(argument)
+ if trace_files and possiblepath(argument) then
+ local q = qualified[argument]
+ if q then
+ local c = q[comment]
+ if c then
+ local r = c[result]
+ if r then
+ c[result] = r + 1
+ else
+ c[result] = r
+ end
+ else
+ q[comment] = {
+ [result] = 1
+ }
+ end
+ else
+ qualified[argument] = {
+ [comment] = {
+ [result] = 1
+ }
+ }
+ end
+ end
+ elseif t == "table" then
+ arguments[i] = fastserialize(argument)
+ else
+ arguments[i] = tostring(argument)
+ end
+ end
+ if trace_calls then
+ report("%s(%,t) => %l",details.comment,arguments,result)
+ end
+ nofcalls = nofcalls + 1
+ if not result then
+ nofrejected = nofrejected + 1
+ end
+end
+
+local ioopen = sandbox.original(io.open)
+
+local function logsandboxfiles(name,what,asked,okay)
+ -- we're only interested in permitted access
+ if not okay then
+ blocked [asked] = blocked [asked] or 0 + 1
+ elseif what == "*" or what == "w" then
+ writeable[asked] = writeable[asked] or 0 + 1
+ else
+ readable [asked] = readable [asked] or 0 + 1
+ end
+end
+
+function sandbox.logcalls()
+ if not trace_calls then
+ trace_calls = true
+ sandbox.setlogger(logsandbox)
+ if registerstats then
+ registerstats()
+ end
+ end
+end
+
+function sandbox.logfiles()
+ if not trace_files then
+ trace_files = true
+ sandbox.setlogger(logsandbox)
+ sandbox.setfilenamelogger(logsandboxfiles)
+ luatex.registerstopactions(function()
+ table.save(logfilename,{
+ calls = {
+ nofcalls = nofcalls,
+ nofrejected = nofrejected,
+ filenames = qualified,
+ },
+ checkednames = {
+ readable = readable,
+ writeable = writeable,
+ blocked = blocked,
+ },
+ })
+ end)
+ if registerstats then
+ registerstats()
+ end
+ end
+end
+
+trackers.register("sandbox.tracecalls",sandbox.logcalls)
+trackers.register("sandbox.tracefiles",sandbox.logfiles)
+
+local sandboxing = environment.arguments.sandbox
+
+if sandboxing then
+
+ report("enabling sandbox")
+
+ sandbox.enable()
+
+ if type(sandboxing) == "string" then
+ sandboxing = utilities.parsers.settings_to_hash(sandboxing)
+ if sandboxing.calls then
+ sandbox.logcalls()
+ end
+ if sandboxing.files then
+ sandbox.logfiles()
+ end
+ end
+
+ -- Nicer would be if we could just disable write 18 and keep os.execute
+ -- which in fact we can do by defining write18 as macro instead of
+ -- primitive ... todo.
+
+ -- We block some potential escapes from protection.
+
+ context [[
+ \let\primitive \relax
+ \let\normalprimitive\relax
+ \let\normalwrite \relax
+ ]]
+
+end
+
+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 !
+
+ if not filename or filename == "" then
+ -- skip
+ elseif suffix == "xml" or arguments.forcexml then
+
+ -- Maybe we should move the preamble parsing here as it
+ -- can be part of (any) loaded (sub) file. The \starttext
+ -- wrapping might go away.
+
+ report("processing as xml: %s",filename)
+
+ context.starttext()
+ context.xmlprocess("main",filename,"")
+ context.stoptext()
+
+ elseif suffix == "cld" or arguments.forcecld then
+
+ report("processing as cld: %s",filename)
+
+ context.runfile(filename)
+
+ elseif suffix == "lua" or arguments.forcelua then
+
+ -- The wrapping might go away. Why is is it there in the
+ -- first place.
+
+ report("processing as lua: %s",filename)
+
+ context.starttext()
+ context.ctxlua(string.format('dofile("%s")',filename))
+ context.stoptext()
+
+ elseif suffix == "mp" or arguments.forcemp then
+
+ report("processing as metapost: %s",filename)
+
+ context.starttext()
+ context.processMPfigurefile(filename)
+ context.stoptext()
+
+ -- elseif suffix == "prep" then
+ --
+ -- -- Why do we wrap here. Because it can be xml? Let's get rid
+ -- -- of prepping in general.
+ --
+ -- context.starttext()
+ -- context.input(filename)
+ -- context.stoptext()
+
+ else
+
+ -- \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.*" }
+
+ end
+
+ context.finishjob()
+
+end
+
+implement {
+ name = "processjob",
+ onlyonce = true,
+ actions = processjob,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv
new file mode 100644
index 00000000000..fcca7b58133
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=cont-run,
+%D version=2014.12.26,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Runner,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Runner}
+
+\unprotect
+
+\registerctxluafile{cont-run}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-yes.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-yes.mkiv
new file mode 100644
index 00000000000..0b7f3231baf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-yes.mkiv
@@ -0,0 +1,99 @@
+%D \module
+%D [ file=cont-yes,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Stub,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% At some point I will reconsider the \starttext .. \stoptext
+% wraping as we can assume proper styling. It's a left-over from
+% mkii that we need to get rid of.
+
+% now moved to cont-run.lua
+%
+% \startluacode
+%
+% -- When a style is loaded there is a good change that we never enter
+% -- this code.
+%
+% local report = logs.reporter("system")
+%
+% 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 !
+%
+% if suffix == "xml" or arguments.forcexml then
+%
+% -- Maybe we should move the preamble parsing here as it
+% -- can be part of (any) loaded (sub) file. The \starttext
+% -- wrapping might go away.
+%
+% report("processing as xml: %s",filename)
+%
+% context.starttext()
+% context.xmlprocess("main",filename,"")
+% context.stoptext()
+%
+% elseif suffix == "cld" or arguments.forcecld then
+%
+% report("processing as cld: %s",filename)
+%
+% context.runfile(filename)
+%
+% elseif suffix == "lua" or arguments.forcelua then
+%
+% -- The wrapping might go away. Why is is it there in the
+% -- first place.
+%
+% report("processing as lua: %s",filename)
+%
+% context.starttext()
+% context.ctxlua(string.format('dofile("%s")',filename))
+% context.stoptext()
+%
+% elseif suffix == "mp" or arguments.forcemp then
+%
+% report("processing as metapost: %s",filename)
+%
+% context.starttext()
+% context.processMPfigurefile(filename)
+% context.stoptext()
+%
+% -- elseif suffix == "prep" then
+% --
+% -- -- Why do we wrap here. Because it can be xml? Let's get rid
+% -- -- of prepping in general.
+% --
+% -- context.starttext()
+% -- context.input(filename)
+% -- context.stoptext()
+%
+% else
+%
+% -- \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.*" }
+%
+% end
+%
+% context.finishjob()
+%
+% \stopluacode
+
+% We don't want to be in protected mode!
+
+\getvalue{clf_processjob} % from cont-run.lua
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-base.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-base.lmx
new file mode 100644
index 00000000000..482d43e8866
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-base.lmx
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+ filename : context-base.xml
+ comment : companion to mtx-server-ctx-startup.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <title><?lua inject(variables.title) ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <?lua if variables.refreshtime and (tonumber(variables.refreshtime) or 0) > 0 and variables.refreshurl then ?>
+ <meta http-equiv='refresh' content="<?lua inject(variables.refreshtime) ?>; <?lua inject(variables.refreshurl) ?>"/>
+ <?lua end ?>
+ <style type="text/css">
+ <?lmx-include context.css strip ?>
+ </style>
+ <style type="text/css">
+ <?lua inject(variables.cssdata) ?>
+ </style>
+ <?lua if variables.styles then for k, v in ipairs(variables.styles) do ?>
+ <link rel="StyleSheet" href="<?lua inject(v) ?>" type="text/css" />
+ <?lua end end ?>
+ </head>
+ <?lua if variables.refreshtime and (tonumber(variables.refreshtime) or 0) > 0 and variables.refreshurl then ?>
+ <!--[if IE]>
+ <script type="text/javascript">
+ setTimeout("document.location='<?lua inject(variables.refreshurl) ?>'", 1000*<?lua inject(variables.refreshtime) ?>);
+ </script>
+ <![endif]-->
+ <?lua end ?>
+ <?lua if variables.action then ?>
+ <form action="<?lua inject(variables.action) ?>" enctype="multi-part/form-data" method="post">
+ <?lua end ?>
+ <body>
+ <div id="top"><?lua if variables.title then ?>
+ <div id="top-one">
+ <div id="top-two"><?lua
+ inject(variables.title)
+ ?> </div>
+ </div>
+ <?lua end ?></div>
+ <div id="bottom"><?lua if variables.bottomtext then ?>
+ <div id="bottom-one">
+ <div id="bottom-two"><?lua
+ inject(variables.bottomtext)
+ ?></div>
+ </div>
+ <?lua end ?></div>
+ <div id="left"><?lua if variables.lefttext then ?>
+ <div id="left-one">
+ <div id="left-two"><?lua
+ inject(variables.lefttext)
+ ?></div>
+ </div>
+ <?lua end ?></div>
+ <div id="right"><?lua if variables.righttext then ?>
+ <div id="right-safari">
+ <div id="right-one">
+ <div id="right-two">
+ <div id="right-three">
+ <div id="right-four">
+ <div id="right-five"><?lua
+ inject(variables.righttext)
+ ?></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <?lua end ?></div>
+ <div id="main">
+ <div id='main-settings'>
+ <?lua inject(variables.maintext) ?>
+ </div>
+ </div>
+ </body>
+ <?lua if variables.action then ?>
+ </form>
+ <?lua end ?>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-characters.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-characters.lmx
new file mode 100644
index 00000000000..f018e412ba9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-characters.lmx
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : context-characters.lmx
+ comment : companion to context.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus();
+ -->
+ </script>
+ <title><?lua pv('title') ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <style type="text/css">
+ <!--
+ <?lmx-include context.css ?>
+ #type {
+ text-align: center ;
+ }
+ #variable {
+ width: 10em ;
+ text-align: right ;
+ margin-right: 1em ;
+ }
+ #value {
+ text-align: left ;
+ }
+ -->
+ </style>
+ </head>
+ <body> <!-- onclick="location.reload()" -->
+ <div id="top"><div id="top-one"><div id="top-two">
+ <?lua pv('title') ?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+ <!-- empty -->
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+ <!-- empty -->
+ </div></div></div></div></div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five"></div></div></div></div></div></div></div>
+ <div id="main"><div id='main-settings'>
+ <?lmx-define-begin chr-head ?>
+ <tr>
+ <th><div id="value">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th colspan='2'><div id="value">characters&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th colspan='2'><div id="value">unicodes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th colspan='2'><div id="value">indices&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th colspan='1'><div id="value">fonts&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ </tr>
+ <tr>
+ <th><div id="value">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">before utf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">after utf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">before hex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">after hex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">after hex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">after dec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ <th><div id="value">filename&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></th>
+ </tr>
+ <?lmx-define-end ?>
+ <?lmx-define-begin chr-body ?>
+ <tr>
+ <td valign="top"><div id="value"><?lua t((nodes.tracers.characters.equal(v.before,v.after) and "=") or "!") ?></div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.string(v.before)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.string(v.after)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.unicodes(v.before)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.unicodes(v.after)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.indices(v.after)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.indices(v.after,true)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ <td valign="top"><div id="value"><?lua t(nodes.tracers.characters.fonts(v.after)) ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>
+ </tr>
+ <?lmx-define-end ?>
+ <?lmx-define-begin chr-none ?>
+ <tr>
+ <td><br/></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <?lmx-define-end ?>
+ <?lua if tracers.knownlist('characters') then ?>
+ <h1>Processed Words</h1>
+ <table>
+ <?lmx-resolve chr-head ?>
+ <?lua for k,v in pairs(tracers.list['characters']) do if v.before and v.after then ?>
+ <?lmx-resolve chr-body ?>
+ <?lua else ?>
+ <?lmx-resolve chr-none ?>
+ <?lua end end ?>
+ </table>
+ <br/>
+ <?lua end ?>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+ Job Name: <?lua p(environment.jobname) ?> &nbsp;&nbsp;&nbsp;
+ ConTeXt Version: <?lua p(environment.version) ?> &nbsp;&nbsp;&nbsp;
+ </div></div></div>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-debug.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-debug.lmx
new file mode 100644
index 00000000000..51b18c83729
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-debug.lmx
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : context-debug.lmx
+ comment : companion to context.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus();
+ -->
+ </script>
+ <title><?lua pv('title') ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <style type="text/css">
+ <!--
+ <?lmx-include context.css ?>
+ #type {
+ text-align: center ;
+ }
+ #variable {
+ width: 10em ;
+ text-align: right ;
+ margin-right: 1em ;
+ }
+ #value {
+ text-align: left ;
+ }
+ -->
+ </style>
+ </head>
+ <body>
+ <div id="top"><div id="top-one"><div id="top-two">
+ <?lua pv('title') ?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+ <!-- empty -->
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+ <!-- empty -->
+ </div></div></div></div></div></div></div>
+ <div id="main"><div id='main-settings'>
+ <?lua if tracers.knownlist('scratch') then ?>
+ <h1>Scratch Variables</h1>
+ <table>
+ <tr>
+ <th align='middle'>index</th>
+ <th align='middle'>&nbsp;&nbsp;&nbsp;dimen</th>
+ <th align='middle'>&nbsp;&nbsp;&nbsp;count</th>
+ <th align='left' >&nbsp;&nbsp;&nbsp;toks</th>
+ </tr>
+ <?lua for k,v in pairs(tracers.list['scratch']) do ?>
+ <tr>
+ <th align='middle'><?lua t(v) ?></th>
+ <th align='middle'>&nbsp;&nbsp;&nbsp;<?lua t(tracers.dimen(v)) ?></th>
+ <th align='middle'>&nbsp;&nbsp;&nbsp;<?lua t(tracers.count(v)) ?></th>
+ <th align='left' >&nbsp;&nbsp;&nbsp;<?lua t(tracers.toks (v)) ?></th>
+ </tr>
+ <?lua end ?>
+ </table>
+ <br/>
+ <?lua end ?>
+ <?lmx-define-begin tvv-head ?>
+ <tr>
+ <th><div id="type" >type </div></th>
+ <th><div id="variable">variable</div></th>
+ <th><div id="value" >value </div></th>
+ </tr>
+ <?lmx-define-end ?>
+ <?lmx-define-begin tvv-body ?>
+ <tr>
+ <th><div id="type" ><?lua t(tracers.type(v)) ?></div></th>
+ <th><div id="variable"><?lua t(tracers.name(v)) ?></div></th>
+ <th><div id="value" ><?lua t(tracers.cs(v)) ?></div></th>
+ </tr>
+ <?lmx-define-end ?>
+ <?lua if tracers.knownlist('internals') then ?>
+ <h1>Internal Variables</h1>
+ <table>
+ <?lmx-resolve tvv-head ?>
+ <?lua for k,v in pairs(tracers.list['internals']) do ?>
+ <?lmx-resolve tvv-body ?>
+ <?lua end ?>
+ </table>
+ <br/>
+ <?lua end ?>
+ <?lua if tracers.knownlist('context') then ?>
+ <h1>ConTeXt Variables</h1>
+ <table>
+ <?lmx-resolve tvv-head ?>
+ <?lua for k,v in pairs(tracers.list['context']) do ?>
+ <?lmx-resolve tvv-body ?>
+ <?lua end ?>
+ </table>
+ <br/>
+ <?lua end ?>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+ Job Name: <?lua p(environment.jobname) ?> &nbsp;&nbsp;&nbsp;
+ ConTeXt Version: <?lua p(environment.version) ?> &nbsp;&nbsp;&nbsp;
+ Real Page: <?lua p(tracers.cs('c:realpageno')) ?> &nbsp;&nbsp;&nbsp;
+ Page: <?lua p(tracers.cs('c:pageno')) ?> &nbsp;&nbsp;&nbsp;
+ </div></div></div>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-error.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-error.lmx
new file mode 100644
index 00000000000..b82b552f88f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-error.lmx
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : context-error.lmx
+ comment : companion to context.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus();
+ -->
+ </script>
+ <title><?lua pv('title')?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <style type="text/css">
+ <!--
+ <?lmx-include context.css ?>
+ -->
+ </style>
+ </head>
+ <body>
+ <div id="top"><div id="top-one"><div id="top-two">
+ <?lua pv('title')?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+ <!-- empty -->
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+ <!-- empty -->
+ <br/>
+ <a href="<?lua pv('filename')?>">edit</a>
+ <br/>
+ </div></div></div></div></div></div></div>
+ <div id="main"><div id="main-settings">
+ <table>
+ <tr><td>Error</td><td>&nbsp;&nbsp;&nbsp;<?lua tv('errormessage')?></td></tr>
+ <tr><td>File </td><td>&nbsp;&nbsp;&nbsp;<?lua tv('filename') ?></td></tr>
+ <tr><td>Line </td><td>&nbsp;&nbsp;&nbsp;<?lua tv('linenumber') ?></td></tr>
+ </table>
+ <br/>
+ <pre>
+ <?lua pv('errorcontext')?>
+ </pre>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+ Job Name: <?lua p(environment.jobname) ?> &nbsp;&nbsp;&nbsp;
+ ConTeXt Version: <?lua p(environment.version) ?> &nbsp;&nbsp;&nbsp;
+ Real Page: <?lua p(tracers.cs('c:realpageno')) ?> &nbsp;&nbsp;&nbsp;
+ Page: <?lua p(tracers.cs('c:pageno')) ?> &nbsp;&nbsp;&nbsp;
+ </div></div></div>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-fonttest.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-fonttest.lmx
new file mode 100644
index 00000000000..fddb8196b38
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-fonttest.lmx
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : context-fonttest.lmx
+ comment : companion to mtx-server-ctx-fonttest.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus() ;
+ <?lua pv('javascripts')?> ;
+ <?lua pv('javascriptdata')?> ;
+ -->
+ </script>
+ <title><?lua pv('title')?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <style type="text/css">
+ <?lmx-include context.css ?>
+ </style>
+ </head>
+ <body onLoad="<?lua pv('javascriptinit')?>">
+ <form action="<?lua pv('formaction')?>" name="main-form">
+ <div id="top"><div id="top-one"><div id="top-two">
+ <?lua pv('title')?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+ <?lua pv('status')?>
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+ <!-- empty -->
+ </div></div></div></div></div></div></div>
+ <div id="main"><div id="main-settings">
+ <?lua pv('maintext')?>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+ <?lua pv('menu')?>
+ </div></div></div>
+ </form>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-help.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-help.lmx
new file mode 100644
index 00000000000..7c8f5006d17
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-help.lmx
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : comm-deb.xml
+ comment : companion to comm-xml.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<html>
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus();
+ -->
+ </script>
+ <title><?lua pv('title') ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <!-- <base target="context-help" /> -->
+ <style type="text/css">
+ <?lmx-include context.css ?>
+ </style>
+ <style type="text/css">
+ #main-left {
+ position: absolute;
+ left: 0% ;
+ top: 0% ;
+ right: 0% ;
+ bottom: 0% ;
+ z-index: 2 ;
+ width: 75% ;
+ height: 100% ;
+ padding: 0% ;
+ margin: 0% ;
+ overflow: auto ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-main-left')?> ;
+ }
+ #main-right {
+ position: absolute;
+ left: 75% ;
+ top: 0% ;
+ right: 0% ;
+ bottom: 0% ;
+ z-index: 2 ;
+ width: 25% ;
+ height: 100% ;
+ padding: 0% ;
+ margin: 0% ;
+ overflow: auto ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-main-right')?> ;
+ }
+ #main-common-settings {
+ padding: 1em ;
+ }
+ </style>
+ <style type="text/css">
+ #main-left {
+ background-color: #C0C0C0 ;
+ color: black;
+ }
+ a.setupmenuurl {
+ color: #FFFFFF ;
+ text-decoration: none ;
+ font-weight: bold ;
+ }
+ a.setupmenucmd {
+ color: #FFFFFF ;
+ text-decoration: underline ;
+ font-weight: bold ;
+ }
+ a.setuplisturl {
+ color: #000000 ;
+ text-decoration: none ;
+ font-weight: bold ;
+ }
+ .setupmenugroup {
+ text-decoration: none ;
+ }
+ .setupinstances {
+ margin-top: 3ex ;
+ }
+ .setupmenucategory {
+ font-weight: bold ;
+ font-size: 2.5ex ;
+ margin-bottom: 1ex ;
+ }
+ <?lua
+ if utilities and utilities.scite and utilities.scite.css then
+p(utilities.scite.css())
+ end
+ ?>
+ </style>
+ </head>
+ <body>
+ <div id="top"><div id="top-one"><div id="top-two">
+<?lua pv('title') ?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+<!-- empty -->
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+<?lua pv('interfaces') ?>
+ </div></div></div></div></div></div></div>
+ <div id="main"><div id='main-settings'>
+ <div id="main-left"><div id="main-common-settings">
+<h1><?lua pv('maintitle') ?></h1>
+<?lua pv('maintext') ?>
+ </div></div>
+ <div id="main-right"><div id="main-common-settings">
+<?lua pv('names') ?>
+<script type='text/javascript'>
+ <!--
+ document.getElementById("#current").scrollIntoView();
+ -->
+</script>
+ </div></div>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+<?lua pv('extra') ?>
+ </div></div></div>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-performance.tex b/Master/texmf-dist/tex/context/base/mkiv/context-performance.tex
new file mode 100644
index 00000000000..dd376866496
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-performance.tex
@@ -0,0 +1,66 @@
+% language=uk
+
+\usemodule[art-01,abr-01]
+
+\starttext
+
+\subject {About performance}
+
+If you use \PDFTEX, \XETEX\ and \LUATEX\ you will notice a difference in speed.
+Don't draw conclusions too easily from simple tests like:
+
+\starttyping
+\dorecurse{1000}{test\page}
+\stoptyping
+
+or (also tests the file system):
+
+\starttyping
+\dorecurse{1000}{\input tufte\blank}
+\stoptyping
+
+The wide engines \XETEX\ and \LUATEX\ have more work to do than \PDFTEX, because
+the input is \UTF\ and \UNICODE\ fonts are used. Of course running \PDFTEX\ on
+extensive \UTF\ input will compensate it a bit.
+
+Comparing \XETEX\ and \PDFTEX\ (using \MKII) and \LUATEX\ (using \MKIV) is kind
+of useless anyway because the \LUATEX\ with \MKIV\ combination is not only doing
+more advanced things, which costs time, but at the other hand has more efficient
+alternatives, like for instance using \MPLIB, which gains a lot.
+
+So, it's best to compare speeds with a mixed content document: multiple fonts,
+text and math, images, \METAPOST\ graphics, structural components, tables, etc.
+
+On the average \PDFTEX\ is the fastest, but offering less functionality, while
+\LUATEX\ with \MKIV\ is often faster than \XETEX\ with \MKII. On complex products
+like the \METAFUN\ manual or when processing complex \XML\ files a \LUATEX\ is
+much faster than a \PDFTEX\ run.
+
+There is some startup time involved which is normally not that much, and initial
+font loading is also not really a burden, but of course for a few page document
+it brings down the number of pages processed per second. Normalizing the input
+takes a bit but applying \OPENTYPE\ font features takes much more. If you find
+unacceptable bottlenecks just let me know (but better first check performance in
+the other engines). Of course inefficient coding of styles (massive font switches
+where a simple one could do) are no reason for a complaint. Keep in mind:
+flexibility comes at a price.
+
+A lot of time went into making sure that \CONTEXT\ runs efficiently on \LUATEX\
+and we keep improving the performance. This is not so much an engine issue but
+more one of the macro package. Of course what is true for \CONTEXT\ \MKIV\ can be
+different for other macro packages but comparing with them makes no sense because
+the differences in functionality.
+
+There are many features in \CONTEXT\ \MKIV\ that demand analysis of the text
+stream and when a spot is found where that feature has to be applied some actions
+takes place. Most such features don't have an impact on overall performance (due
+to the analysis) unless they are used. Of course font processing has the largest
+impact, but they are also the most flexible and extensible feature, especially
+when you use dynamic features. And font processing is always enabled. Speed has
+been improved over time and we're currently at a point that further speedup makes
+not much sense and would only make the code more complex. This is not to say that
+we cannot improve performance in the future.
+
+Hans Hagen \crlf Hasselt NL
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-timing.lmx b/Master/texmf-dist/tex/context/base/mkiv/context-timing.lmx
new file mode 100644
index 00000000000..57b5879bad8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-timing.lmx
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ filename : context-timing.xml
+ comment : companion to mtx-timing.tex
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright: PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+-->
+
+<!--
+ beware: xhtml, so no comment around css
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <script type='text/javascript'>
+ <!--
+ window.focus();
+ -->
+ </script>
+ <title><?lua pv('title')?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <style type="text/css">
+ <?lmx-include context.css ?>
+ </style>
+ </head>
+ <body>
+ <div id="top"><div id="top-one"><div id="top-two">
+ <?lua pv('title')?>
+ </div></div></div>
+ <div id="left"><div id="left-one"><div id="left-two">
+ <!-- empty -->
+ </div></div></div>
+ <div id="right"><div id="right-safari"><div id="right-one"><div id="right-two"><div id="right-three"><div id="right-four"><div id="right-five">
+ <!-- empty -->
+ </div></div></div></div></div></div></div>
+ <div id="main"><div id="main-settings">
+ <?lua pv('graphics')?>
+ </div></div>
+ <div id="bottom"><div id="bottom-one"><div id="bottom-two">
+ <small>
+ <br/> <br/>
+ <?lua pv('parametersmenu')?>
+ <br/>
+ <?lua pv('nodesmenu')?>
+ </small>
+ </div></div></div>
+ </body>
+</html>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex b/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex
new file mode 100644
index 00000000000..b9591e8e06e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex
@@ -0,0 +1,57 @@
+% language=uk
+
+\usemodule[art-01,abr-01]
+
+\starttext
+
+\subject {On the agenda}
+
+\subsubject{\LUATEX}
+
+\startitemize
+ \startitem
+ head||tail cleanup in disc nodes (get rid of temp i.e.\ delay till linebreak)
+ \stopitem
+ \startitem
+ optimize some callback resolution (more direct)
+ \stopitem
+ \startitem
+ add \type {--output-filename} for \PDF\ filename
+ \stopitem
+\stopitemize
+
+\subsubject{\CONTEXT}
+
+\startitemize
+ \startitem
+ play with par callback and properties
+ \stopitem
+ \startitem
+ play with box attributes
+ \stopitem
+ \startitem
+ redo some of the spacing (adapt to improvements in engine)
+ \stopitem
+ \startitem
+ use \type {\matheqnogapstep}, \type {\Ustack}, \type {\mathscriptsmode}
+ and other new math primitives
+ \stopitem
+\stopitemize
+
+\vfill {\em Feel free to suggest additions.}
+
+\stoptext
+
+% new:
+
+<cd:command name="showgrid" file="page-grd.mkiv">
+ ...
+ <cd:constant type="columns" default="yes"/>
+ ...
+</cd:command>
+
+<cd:command name="itemtag" variant="itemgroup" file="strc-itm.mkvi">
+ <cd:arguments>
+ <cd:resolve name="keyword-reference-list-optional"/>
+ </cd:arguments>
+</cd:command>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.css b/Master/texmf-dist/tex/context/base/mkiv/context.css
new file mode 100644
index 00000000000..be1dad79610
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context.css
@@ -0,0 +1,261 @@
+body {
+ color: #FFFFFF ;
+ background-color: <?lua pv('color-background-body')?> ;
+ font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans ;
+ font-size: 12px ;
+ line-height: 18px ;
+}
+a:link, a:active, a:visited {
+ color: #FFFFFF ;
+}
+a.dir-view:link, a.dir-view:active, a.dir-view:visited {
+ color: #FFFFFF ;
+ text-decoration: underline ;
+}
+.valid {
+ color: #00FF00 ;
+}
+.invalid {
+ color: #FF0000 ;
+}
+button, .commonlink, .smallbutton {
+ font-weight: bold ;
+ font-size: 12px ;
+ text-decoration: none ;
+ color: #000000 ;
+ border-color: #7F7F7F ;
+ border-style: solid ;
+ border-width: .125ex ;
+ background-color: #FFFFFF ;
+ padding: .5ex ;
+}
+.smallbutton {
+ width: 1em ;
+}
+a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited {
+ font-weight: bold ;
+ font-size: 12px ;
+ text-decoration: none ;
+ color: #000000 ;
+}
+h1, .title {
+ font-style: normal ;
+ font-weight: normal ;
+ font-size: 18px ;
+ line-height: 18px ;
+ margin-bottom: 20px ;
+}
+h2, .subtitle {
+ font-style: normal ;
+ font-weight: normal ;
+ font-size: 12px ;
+ margin-top: 18px ;
+ margin-bottom: 18px ;
+}
+table {
+ line-height: 18px ;
+ font-size: 12px ;
+ margin: 0 ;
+}
+th {
+ font-weight: bold ;
+ text-align: left ;
+ padding-bottom: 6px ;
+}
+.tc {
+ font-weight: bold ;
+ text-align: left ;
+}
+p, li {
+ max-width: 60em ;
+}
+.empty-line {
+ margin-top: 4px ;
+}
+.more-room {
+ margin-right: 1.5em ;
+}
+.much-more-room {
+ margin-right: 3em ;
+}
+#main {
+ position: absolute;
+ left: 10% ;
+ top: 10% ;
+ right: 10% ;
+ bottom: 10% ;
+ z-index: 2 ;
+ width: 80% ;
+ height: 80% ;
+ padding: 0% ;
+ margin: 0% ;
+ overflow: auto ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-main')?> ;
+}
+#main-settings {
+ margin: 12px ;
+ x_max-width: 60em ;
+ line-height: 18px ;
+ font-size: 12px ;
+}
+#left {
+ position: absolute;
+ top : 10% ;
+ left: 0% ;
+ bottom: 0%;
+ right: 90% ;
+ z-index: 1 ;
+ width: 10% ;
+ height: 90% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-one')?> ;
+}
+#right {
+ position: absolute;
+ top : 0% ;
+ left: 90% ;
+ bottom: 10% ;
+ right: 0% ;
+ z-index: 1 ;
+ width: 10% ;
+ height: 90% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-three')?> ;
+ _margin-left: -15px ;
+}
+#bottom {
+ position: absolute ;
+ left: 10% ;
+ right: 0% ;
+ top: 90% ;
+ bottom: 0% ;
+ z-index: 1 ;
+ width: 90% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-two')?> ;
+}
+#top {
+ position: absolute ;
+ left: 0% ;
+ right: 10% ;
+ top: 0% ;
+ bottom: 90% ;
+ z-index: 1 ;
+ width: 90% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: <?lua pv('color-background-four')?> ;
+}
+#top-one {
+ position: absolute ;
+ bottom: 50% ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#top-two {
+ position: relative ;
+ margin-bottom: -9px ;
+ margin-left: 12px ;
+ margin-right: 12px ;
+ line-height: 18px ;
+ text-align: right ;
+ vertical-align: middle ;
+}
+#bottom-one {
+ position: absolute ;
+ bottom: 50% ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#bottom-two {
+ position: relative ;
+ margin-bottom: -9px ;
+ margin-left: 12px ;
+ margin-right: 12px ;
+ line-height: 18px ;
+ text-align: left ;
+ vertical-align: middle ;
+}
+#left-one {
+ position: absolute ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#left-two {
+ position: relative ;
+ margin-top: 12px ;
+ line-height: 18px ;
+ text-align: center ;
+ vertical-align: top ;
+}
+#right-one {
+ display: table ;
+ height: 100% ;
+ width: 100% ;
+}
+#right-two {
+ display: table-row ;
+ height: 100% ;
+ width: 100% ;
+}
+#right-three {
+ display: table-cell ;
+ width: 100% ;
+ vertical-align: bottom ;
+ _position: absolute ;
+ _top: 100% ;
+}
+#right-four {
+ text-align: center ;
+ margin-bottom: 2ex ;
+ _position: relative ;
+ _top: -100% ;
+}
+#more-top {
+ position: absolute;
+ top: 0% ;
+ left: 90% ;
+ bottom: 90%;
+ right: 0% ;
+ z-index: 3 ;
+ width: 10% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ border-style: none ;
+ border-width: 0 ;
+}
+#more-top-settings {
+ text-align: center ;
+}
+#more-right-settings {
+ margin-right: 12px ;
+ margin-left: 12px ;
+ line-height: 18px ;
+ font-size: 10px ;
+ text-align: center ;
+}
+#right-safari {
+ _display: table ;
+ width: 100% ;
+ height: 100% ;
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.lus b/Master/texmf-dist/tex/context/base/mkiv/context.lus
new file mode 100644
index 00000000000..960e96adf7c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context.lus
@@ -0,0 +1,71 @@
+if not modules then modules = { } end modules ['context'] = {
+ version = 1.001,
+ comment = "companion to context.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[<p>This table specifies what stub files are needed in order to create
+the format. These files are loaded before the format is made so that we
+bypass kpse. When the format itself is used, another stub is used (with
+suffix lui). The current format builder is to a large part determined by
+the way luatex evolved and the process will probaby change.</p>]]--
+
+local method = 3
+
+local stubfiles = {
+
+ 'luat-cod.lua',
+
+ -- Here follows a list of trac, luat and data files, but we don't
+ -- it this way any more so there is no need to keep this updated.
+
+}
+
+-- This method will trigger the creation of a stub file with all neccessary
+-- libraries merged. This is how we originally did it.
+
+if method == 1 then
+
+ return stubfiles
+
+end
+
+-- This method will use this file as stub file so no merge is needed.
+
+if method == 2 then
+
+ if resolvers then
+ -- we're loading this file in mtxrun
+ else
+
+ local sourcepath = string.gsub(arg and arg[1] or "","/[^/]+$","")
+ local targetpath = "."
+
+ if sourcepath == "" then sourcepath = targetpath end
+
+ for i=1,#stubfiles do
+ local filename = sourcepath .. "/" .. stubfiles[i]
+ texio.write_nl("preloading " .. filename)
+ dofile(filename)
+ end
+ texio.write_nl("\n")
+
+ end
+
+ return "context.lus"
+
+end
+
+-- Only a simple stub:
+
+if method == 3 then
+
+ return "luat-cod.lua"
+
+end
+
+-- The last resort.
+
+return stubfiles
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv
new file mode 100644
index 00000000000..9f4ef2327a1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv
@@ -0,0 +1,577 @@
+%D \module
+%D [ file=context,
+%D version=2008.28.10, % 1995.10.10,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Format Generation,
+%D author=Hans Hagen, % ɦɑns ɦɑˈχən
+%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.
+
+% Here is some timing (2015-04-01) luajittex format generation:
+%
+% 2.6 sec : normal make
+% 2.0 sec : with terminal output piped to file
+% 0.2 sec : format dumped
+% 0.2 sec : char-def/char-ini (no bytecode)
+%
+% So a format still saves some 1.5 seconds (with luajjitex) startup and
+% on network shares cq. when no files are cached by the os it's of course
+% much worse. A zero run is .27 sec with luajittex.
+
+% Welcome to context, pronounced as kontekst (rather dutch) and not as
+% conτεχt.
+
+\catcode`\{=1 \catcode`\}=2 \catcode`\#=6
+
+%D From the next string (which is set by the script that assembles the
+%D distribution) later on we will calculate a number that can be used
+%D by use modules to identify the feature level. Starting with version
+%D 2004.8.30 the low level interface is english. Watch out and adapt
+%D your styles an modules.
+
+% \everypar{\writestatus{!!!!}{some spurious input in line \the\inputlineno}\wait}
+
+%D The order of loading will change when all modules have been cleaned
+%D up and the dependencies are more consistent.
+
+\edef\contextformat {\jobname}
+\edef\contextversion{2016.04.21 19:35}
+\edef\contextkind {beta}
+
+%D For those who want to use this:
+
+\let\fmtname \contextformat
+\let\fmtversion\contextversion
+
+%D Loading:
+
+\edef\mksuffix {mkiv}
+\edef\contextmark{MKIV}
+
+\ifx\normalinput\undefined \let\normalinput\input \fi
+
+\def\loadcorefile#1{\normalinput#1\relax}
+\def\loadmarkfile#1{\normalinput#1.\mksuffix\relax}
+\def\loadmkiifile#1{}
+\def\loadmkivfile#1{\normalinput#1.mkiv\relax}
+\def\loadmkvifile#1{\normalinput#1.mkvi\relax}
+
+%D First we load the system modules. These implement a lot of
+%D manipulation macros. We start with setting up some basic \TEX\
+%D machinery.
+
+\loadmarkfile{syst-ini}
+
+%D Some checking (more primitives are now defined):
+
+\ifdefined\defaultinterface \else \def\defaultinterface {english} \fi
+%ifdefined\messageinterface \else \let\messageinterface \defaultinterface \fi
+\ifdefined\defaultlanguagetag \else \def\defaultlanguagetag{en} \fi
+
+%D We just quit if new functionality is expected.
+
+\ifnum\luatexversion<70 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.70!}
+ \expandafter\end
+\fi
+
+%D There is only this way to pass the version info to \LUA\ (currently). Hm, we could
+%D now put it into the environment.
+
+\newtoks\contextversiontoks \contextversiontoks\expandafter{\contextversion}
+\newtoks\contextkindtoks \contextkindtoks \expandafter{\contextkind}
+
+% \normaleverypar{\wait} % uncomment for test of funny injections
+
+%D Now the more fundamental code gets defined.
+
+\loadmarkfile{norm-ctx}
+\loadmarkfile{syst-pln}
+\loadmarkfile{syst-mes}
+
+\loadmarkfile{luat-cod}
+\loadmarkfile{luat-bas}
+\loadmarkfile{luat-lib}
+
+\loadmarkfile{catc-ini}
+\loadmarkfile{catc-act}
+\loadmarkfile{catc-def}
+\loadmarkfile{catc-ctx}
+\loadmarkfile{catc-sym}
+
+\loadmarkfile{cldf-ini}
+
+% \tracecatcodetables
+
+% From here on we have \unexpanded being \normalprotected, as we already had
+% \unexpanded long before etex came around.
+
+\loadmarkfile{luat-ini}
+\loadmarkfile{toks-ini}
+
+\loadmarkfile{syst-aux}
+\loadmarkfile{syst-lua}
+\loadmarkfile{syst-con}
+
+\loadmarkfile{syst-fnt}
+\loadmarkfile{syst-rtp}
+
+\loadmarkfile{luat-usr}
+
+% \loadmarkfile{luat-ini} % moved up
+% \loadmarkfile{toks-ini} % moved up
+
+\loadmkvifile{file-ini}
+\loadmkvifile{file-res}
+\loadmkvifile{file-lib}
+
+\loadmarkfile{supp-dir}
+
+\loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini
+\loadmarkfile{char-ini} % tex / context specific
+\loadmarkfile{char-act} % even more specific
+
+\loadmarkfile{mult-ini}
+\loadmarkfile{mult-sys}
+\loadmarkfile{mult-aux}
+\loadmarkfile{mult-def}
+\loadmarkfile{mult-chk}
+%loadmarkfile{mult-aux} % moved up
+\loadmkvifile{mult-dim}
+
+\loadmarkfile{cldf-int} % interface
+
+% \loadmarkfile{luat-ini}
+
+\loadmarkfile{toks-tra}
+%loadmarkfile{toks-map} % obsolete, never used
+
+\loadmarkfile{attr-ini}
+
+\loadmarkfile{core-ini}
+\loadmarkfile{core-env}
+
+\loadmarkfile{layo-ini}
+
+\loadmarkfile{node-ini}
+
+\loadmarkfile{cldf-bas} % basics / depends on nodes
+
+\loadmarkfile{node-fin}
+\loadmarkfile{node-mig}
+%loadmarkfile{node-pag}
+
+\loadmarkfile{back-ini}
+
+\loadmarkfile{attr-col}
+\loadmarkfile{attr-lay}
+\loadmarkfile{attr-neg}
+\loadmarkfile{attr-eff}
+\loadmarkfile{attr-mkr}
+
+\loadmarkfile{trac-tex}
+\loadmarkfile{trac-deb} % will move up
+\loadmarkfile{trac-ctx} % maybe move up
+
+%loadmarkfile{blob-ini} % not to be used, we only use a helper
+
+\loadmarkfile{supp-box}
+
+%loadmarkfile{supp-vis} % replaced by trac-vis
+%loadmarkfile{supp-fun} % mostly replaced
+
+\loadmarkfile{supp-ran}
+\loadmarkfile{supp-mat}
+%loadmarkfile{spac-cha} % obsolete
+%loadmarkfile{supp-num} % obsolete
+
+\loadmarkfile{core-uti}
+\loadmkvifile{file-job}
+
+\loadmarkfile{anch-pos}
+
+\loadmarkfile{typo-ini}
+\loadmarkfile{typo-lin}
+\loadmarkfile{typo-bld} % par builders
+
+\loadmarkfile{typo-inj}
+
+\loadmkvifile{file-syn}
+\loadmkvifile{file-mod}
+
+\loadmarkfile{core-con}
+
+\loadmarkfile{cont-fil}
+
+\loadmarkfile{regi-ini}
+\loadmarkfile{enco-ini}
+\loadmarkfile{hand-ini}
+
+\loadmarkfile{lang-ini}
+\loadmarkfile{lang-hyp} % also loads dis
+\loadmarkfile{lang-lab}
+
+\loadmarkfile{unic-ini}
+
+% \loadmarkfile{core-uti}
+\loadmarkfile{core-two}
+\loadmarkfile{core-dat}
+
+\loadmarkfile{colo-ini}
+\loadmarkfile{colo-grp} % optional
+\loadmarkfile{colo-ext}
+
+\loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented)
+
+\loadmarkfile{pack-cut} % leftovers from trac-vis
+
+\loadmarkfile{lang-mis}
+\loadmarkfile{lang-url}
+\loadmarkfile{lang-def}
+
+% \loadmkvifile{file-job} % why so late?
+
+\loadmarkfile{symb-ini} % brrr depends on fonts
+
+\loadmarkfile{sort-ini}
+
+\loadmkvifile{pack-mis}
+\loadmarkfile{pack-rul}
+\loadmarkfile{pack-mrl}
+\loadmkvifile{pack-bck}
+\loadmarkfile{pack-fen}
+
+\loadmarkfile{lxml-ini}
+\loadmarkfile{lxml-sor}
+
+\loadmkvifile{typo-prc}
+
+% \loadmarkfile{anch-pos}
+
+\loadmkvifile{strc-ini}
+\loadmarkfile{strc-tag}
+\loadmarkfile{strc-doc}
+\loadmarkfile{strc-num}
+\loadmarkfile{strc-mar}
+\loadmarkfile{strc-sbe}
+\loadmkvifile{strc-lst}
+\loadmarkfile{strc-sec}
+\loadmarkfile{strc-pag} % hm, depends on core-num
+\loadmarkfile{strc-ren}
+\loadmarkfile{strc-xml}
+\loadmarkfile{strc-def} % might happen later
+\loadmkvifile{strc-ref}
+%loadmarkfile{strc-reg}
+\loadmkvifile{strc-lev} % experiment
+
+\loadmarkfile{spac-hor}
+\loadmarkfile{spac-ali}
+\loadmarkfile{spac-flr}
+\loadmarkfile{spac-ver}
+\loadmarkfile{spac-lin}
+\loadmarkfile{spac-pag}
+\loadmarkfile{spac-par}
+%loadmarkfile{spac-adj} % no longer needed
+\loadmarkfile{spac-def}
+\loadmkvifile{spac-prf}
+\loadmarkfile{spac-grd}
+
+%loadmarkfile{anch-pos}
+
+\loadmkvifile{scrn-ini}
+\loadmkvifile{scrn-ref}
+
+\loadmarkfile{pack-obj}
+
+\loadmkvifile{strc-itm}
+
+\loadmkvifile{strc-con}
+\loadmkvifile{strc-des}
+\loadmkvifile{strc-enu}
+
+\loadmarkfile{strc-ind}
+\loadmarkfile{strc-lab}
+\loadmarkfile{strc-syn}
+
+\loadmarkfile{core-sys}
+
+\loadmarkfile{page-var}
+\loadmkvifile{page-otr}
+\loadmarkfile{page-ini}
+\loadmarkfile{page-ins}
+\loadmarkfile{page-fac}
+\loadmarkfile{page-brk}
+\loadmarkfile{page-col}
+\loadmarkfile{page-inf}
+\loadmarkfile{page-grd}
+\loadmarkfile{page-flt}
+\loadmarkfile{page-bck}
+\loadmarkfile{page-not}
+\loadmarkfile{page-one}
+\loadmarkfile{page-lay}
+\loadmkvifile{page-box}
+\loadmkvifile{page-txt}
+\loadmarkfile{page-sid} % when
+
+\loadmkvifile{strc-flt}
+
+\loadmarkfile{page-pst}
+\loadmkvifile{page-mbk}
+\loadmarkfile{page-mul} % partly overloaded
+\loadmarkfile{page-mix} % new
+\loadmarkfile{page-set}
+\loadmarkfile{pack-lyr}
+\loadmarkfile{pack-pos}
+\loadmkvifile{page-mak}
+
+\loadmarkfile{strc-reg} % uses mixed columns
+
+\loadmkvifile{page-lin}
+\loadmarkfile{page-par}
+\loadmarkfile{typo-pag}
+\loadmarkfile{typo-mar}
+\loadmarkfile{typo-itm}
+
+\loadmarkfile{buff-ini}
+\loadmarkfile{buff-ver}
+\loadmkvifile{buff-par}
+
+\loadmarkfile{buff-imp-tex} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-mp} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-lua} % optional as also runtime if not loaded
+\loadmarkfile{buff-imp-xml} % optional as also runtime if not loaded
+
+\loadmarkfile{buff-imp-parsed-xml} % optional
+%loadmarkfile{buff-imp-parsed-lua} % optional
+
+\loadmarkfile{strc-blk}
+
+\loadmarkfile{page-imp}
+\loadmkvifile{page-sel} % optional
+\loadmkvifile{page-inj} % optional
+
+\loadmkvifile{scrn-pag}
+\loadmkvifile{scrn-wid}
+\loadmkvifile{scrn-but}
+\loadmkvifile{scrn-bar}
+
+\loadmarkfile{page-com} % optional (after scrn-pag)
+
+\loadmarkfile{strc-bkm} % bookmarks
+
+\loadmarkfile{java-ini}
+
+\loadmkvifile{scrn-fld}
+\loadmkvifile{scrn-hlp}
+
+\loadmarkfile{char-enc} % will move up
+
+\loadmkvifile{font-lib} % way too late but after language
+\loadmkvifile{font-fil}
+\loadmkvifile{font-var}
+\loadmkvifile{font-fea}
+\loadmkvifile{font-mat}
+\loadmkvifile{font-ini}
+\loadmkvifile{font-sym}
+\loadmkvifile{font-sty}
+\loadmkvifile{font-set}
+\loadmkvifile{font-emp}
+\loadmarkfile{font-pre}
+\loadmarkfile{font-unk}
+\loadmarkfile{font-tra}
+\loadmarkfile{font-chk}
+\loadmarkfile{font-uni}
+\loadmkvifile{font-col}
+\loadmkvifile{font-gds}
+\loadmkvifile{font-aux}
+\loadmkvifile{font-sel}
+
+\loadmarkfile{typo-tal}
+\loadmarkfile{typo-par} % par builders (uses fonts)
+
+\loadmarkfile{tabl-com}
+\loadmarkfile{tabl-pln}
+
+\loadmarkfile{tabl-tab} % thrd-tab stripped and merged
+
+\loadmarkfile{tabl-tbl}
+\loadmarkfile{tabl-ntb}
+\loadmarkfile{tabl-nte}
+\loadmarkfile{tabl-ltb}
+\loadmarkfile{tabl-tsp}
+\loadmkvifile{tabl-xtb}
+\loadmarkfile{tabl-mis}
+
+\loadmarkfile{typo-lan}
+
+\loadmarkfile{lxml-css}
+
+\loadmarkfile{spac-chr} % depends on fonts
+
+\loadmarkfile{blob-ini} % not to be used, we only use a helper
+
+\loadmarkfile{trac-vis}
+\loadmarkfile{trac-jus}
+
+\loadmarkfile{typo-cln}
+\loadmarkfile{typo-wrp}
+\loadmarkfile{typo-spa}
+\loadmarkfile{typo-krn}
+\loadmkvifile{typo-itc}
+\loadmarkfile{typo-dir}
+\loadmarkfile{typo-brk}
+\loadmarkfile{typo-cap}
+\loadmarkfile{typo-dig}
+\loadmarkfile{typo-rep}
+\loadmkvifile{typo-txt}
+\loadmarkfile{typo-drp}
+\loadmarkfile{typo-fln}
+\loadmarkfile{typo-sus}
+\loadmarkfile{typo-lig}
+\loadmarkfile{typo-chr}
+
+\loadmkvifile{type-ini}
+\loadmarkfile{type-set}
+
+\loadmarkfile{scrp-ini}
+
+\loadmarkfile{lang-wrd} % can be optional (discussion with mm sideeffect)
+\loadmarkfile{lang-rep} % can be optional (bt 2013 side effect)
+
+\loadmarkfile{prop-ini} % only for downward compatibility
+
+\loadmarkfile{mlib-ctx} % messy order
+
+\loadmarkfile{meta-ini}
+\loadmarkfile{meta-tex}
+\loadmarkfile{meta-fun}
+\loadmarkfile{meta-pag}
+\loadmarkfile{meta-grd}
+\loadmarkfile{meta-fnt}
+
+\loadmarkfile{page-mrk} % depends on mp
+
+\loadmarkfile{page-flw}
+\loadmarkfile{page-spr}
+\loadmarkfile{page-plg}
+\loadmarkfile{page-str}
+
+\loadmarkfile{anch-pgr} % can be moved up (nicer for dependencies)
+\loadmkvifile{anch-bck}
+\loadmarkfile{anch-tab} % overloads tabl-tbl
+\loadmarkfile{anch-bar}
+%loadmarkfile{anch-snc} % when needed this one will be redone
+
+\loadmarkfile{math-ini} % way after font-pre !
+\loadmarkfile{math-pln}
+\loadmarkfile{math-for}
+\loadmarkfile{math-def} % also saves some meanings
+\loadmarkfile{math-ali}
+%loadmarkfile{math-arr}
+\loadmkvifile{math-stc}
+\loadmarkfile{math-frc}
+\loadmarkfile{math-mis}
+\loadmarkfile{math-scr}
+\loadmarkfile{math-int}
+\loadmarkfile{math-del}
+\loadmarkfile{math-fen}
+\loadmkvifile{math-acc}
+\loadmkvifile{math-rad}
+\loadmarkfile{math-inl}
+\loadmarkfile{math-dis}
+%loadmarkfile{math-lan}
+
+%loadmarkfile{phys-dim} % moved to after typo-scr
+
+\loadmarkfile{strc-mat}
+
+\loadmarkfile{chem-ini}
+\loadmarkfile{chem-str}
+
+\loadmarkfile{typo-scr}
+\loadmarkfile{phys-dim}
+
+\loadmarkfile{node-rul}
+\loadmkvifile{font-sol} % font solutions
+
+\loadmkvifile{strc-not}
+\loadmkvifile{strc-lnt}
+
+\loadmarkfile{pack-com}
+\loadmarkfile{typo-del}
+
+\loadmarkfile{grph-trf}
+\loadmarkfile{grph-inc}
+\loadmarkfile{grph-fig}
+\loadmarkfile{grph-raw}
+\loadmarkfile{grph-rul}
+
+\loadmarkfile{pack-box}
+\loadmarkfile{pack-bar}
+\loadmarkfile{page-app}
+\loadmarkfile{meta-fig}
+
+\loadmarkfile{lang-spa} % will become obsolete
+
+% old bibtex support: (will be m-oldbibtex.mkiv)
+
+% \loadmarkfile{bibl-bib}
+% \loadmarkfile{bibl-tra}
+
+% new bibtex support:
+
+\loadmarkfile{publ-ini}
+\loadmarkfile{publ-tra}
+\loadmarkfile{publ-xml}
+\loadmarkfile{publ-old}
+
+%loadmarkfile{x-xtag} % no longer preloaded
+
+\loadmarkfile{meta-xml}
+
+\loadmarkfile{cont-log}
+
+\loadmarkfile{task-ini}
+
+\loadmarkfile{cldf-ver} % verbatim, this can come late
+\loadmarkfile{cldf-com} % commands, this can come late
+
+\loadmarkfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace
+
+\loadmarkfile{core-def}
+
+%usemodule[x][res-04] % xml resource libraries
+%usemodule[x][res-08] % rlx runtime conversion
+%usemodule[x][res-12] % rli external indentification
+
+% now we hook in backend code (needs checking)
+
+\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{grph-epd}
+
+\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
+
+\setupcurrentlanguage[\defaultlanguagetag]
+
+\prependtoks
+ \ctxlua{statistics.starttiming(statistics)}%
+\to \everyjob
+
+\appendtoks
+ \ctxlua{statistics.stoptiming(statistics)}%
+\to \everyjob
+
+\appendtoks
+ \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkiv","\contextkind")}% can become automatic
+\to \everydump
+
+\errorstopmode \dump \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.lua b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua
new file mode 100644
index 00000000000..bfe5357a6ec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua
@@ -0,0 +1,1357 @@
+if not modules then modules = { } end modules ['core-con'] = {
+ version = 1.001,
+ comment = "companion to core-con.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: split into char-lan.lua and core-con.lua
+
+--[[ldx--
+<p>This module implements a bunch of conversions. Some are more
+efficient than their <l n='tex'/> counterpart, some are even
+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 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 = tonumber, tostring
+local P, C, Cs, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.match
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local settings_to_array = utilities.parsers.settings_to_array
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local variables = interfaces.variables
+local constants = interfaces.constants
+
+converters = converters or { }
+local converters = converters
+
+languages = languages or { }
+local languages = languages
+
+converters.number = tonumber
+converters.numbers = tonumber
+
+implement { name = "number", actions = context }
+implement { name = "numbers", actions = context }
+
+-- to be reconsidered ... languages namespace here, might become local plus a register command
+
+local counters = allocate {
+ ['default'] = { -- no metatable as we do a test on keys
+ 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
+ 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
+ 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
+ 0x007A
+ },
+ ['slovenian'] = {
+ 0x0061, 0x0062, 0x0063, 0x010D, 0x0064,
+ 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x006E,
+ 0x006F, 0x0070, 0x0072, 0x0073, 0x0161,
+ 0x0074, 0x0075, 0x0076, 0x007A, 0x017E
+ },
+ ['spanish'] = {
+ 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
+ 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
+ 0x006B, 0x006C, 0x006D, 0x006E, 0x00F1,
+ 0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
+ 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007A
+ },
+ ['greek'] = { -- this should be the lowercase table
+ -- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
+ -- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
+ -- 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ -- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
+ -- 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
+ 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
+ 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5,
+ 0x03C6, 0x03C7, 0x03C8, 0x03C9,
+ },
+ ['arabic'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x0643, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['persian'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x06A9, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['thai'] = {
+ 0xE050, 0xE051, 0xE052, 0xE053, 0xE054,
+ 0xE055, 0xE056, 0xE057, 0xE058, 0xE059
+ },
+ ['devangari'] = {
+ 0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
+ 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
+ },
+ ['gurmurkhi'] = {
+ 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
+ 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
+ },
+ ['gujarati'] = {
+ 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
+ 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
+ },
+ ['tibetan'] = {
+ 0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24,
+ 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
+ },
+ ['korean'] = {
+ 0x3131, 0x3134, 0x3137, 0x3139, 0x3141,
+ 0x3142, 0x3145, 0x3147, 0x3148, 0x314A,
+ 0x314B, 0x314C, 0x314D, 0x314E
+ },
+ ['korean-parenthesis'] = { --
+ 0x3200, 0x3201, 0x3202, 0x3203, 0x3204,
+ 0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
+ 0x320A, 0x320B, 0x320C, 0x320D
+ },
+ ['korean-circle'] = { -- circled
+ 0x3260, 0x3261, 0x3262, 0x3263, 0x3264,
+ 0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
+ 0x326A, 0x326B, 0x326C, 0x326D
+ },
+}
+
+languages.counters = counters
+
+counters['ar'] = counters['arabic']
+counters['gr'] = counters['greek']
+counters['g'] = counters['greek']
+counters['sl'] = counters['slovenian']
+counters['es'] = counters['spanish']
+counters['kr'] = counters['korean']
+counters['kr-p'] = counters['korean-parenthesis']
+counters['kr-c'] = counters['korean-circle']
+
+counters['thainumerals'] = counters['thai']
+counters['devanagarinumerals'] = counters['devanagari']
+counters['gurmurkhinumerals'] = counters['gurmurkhi']
+counters['gujaratinumerals'] = counters['gujarati']
+counters['tibetannumerals'] = counters['tibetan']
+counters['greeknumerals'] = counters['greek']
+counters['arabicnumerals'] = counters['arabic']
+counters['persiannumerals'] = counters['persian']
+counters['arabicexnumerals'] = counters['persian']
+counters['koreannumerals'] = counters['korean']
+counters['koreanparenthesisnumerals'] = counters['korean-parenthesis']
+counters['koreancirclenumerals'] = counters['korean-circle']
+
+counters['sloveniannumerals'] = counters['slovenian']
+counters['spanishnumerals'] = counters['spanish']
+
+local decimals = allocate {
+ ['arabic'] = {
+ ["0"] = "٠", ["1"] = "١", ["2"] = "٢", ["3"] = "٣", ["4"] = "٤",
+ ["5"] = "٥", ["6"] = "٦", ["7"] = "٧", ["8"] = "٨", ["9"] = "٩",
+ },
+ ['persian'] = {
+ ["0"] = "۰", ["1"] = "۱", ["2"] = "۲", ["3"] = "۳", ["4"] = "۴",
+ ["5"] = "۵", ["6"] = "۶", ["7"] = "۷", ["8"] = "۸", ["9"] = "۹",
+ }
+}
+
+languages.decimals = decimals
+
+local fallback = utfbyte('0')
+
+local function chr(n,m)
+ return (n > 0 and n < 27 and utfchar(n+m)) or ""
+end
+
+local function chrs(n,m,t)
+ if not t then
+ t = { }
+ end
+ if n > 26 then
+ chrs(floor((n-1)/26),m,t)
+ n = (n-1)%26 + 1
+ end
+ if n ~= 0 then
+ t[#t+1] = utfchar(n+m)
+ end
+ if n <= 26 then
+ return concat(t)
+ end
+end
+
+local function maxchrs(n,m,cmd,t)
+ if not t then
+ t = { }
+ end
+ if n > m then
+ maxchrs(floor((n-1)/m),m,cmd)
+ n = (n-1)%m + 1
+ end
+ t[#t+1] = formatters["%s{%s}"](cmd,n)
+ if n <= m then
+ return concat(t)
+ end
+end
+
+converters.chr = chr
+converters.chrs = chrs
+converters.maxchrs = maxchrs
+
+local lowercharacter = characters.lcchars
+local uppercharacter = characters.ucchars
+
+local defaultcounter = counters.default
+
+local function do_alphabetic(n,mapping,mapper,t) -- todo: make zero based variant (initial n + 1)
+ if not t then
+ t = { }
+ end
+ local max = #mapping
+ if n > max then
+ do_alphabetic(floor((n-1)/max),mapping,mapper,t)
+ n = (n-1) % max + 1
+ end
+ local chr = mapping[n] or fallback
+ t[#t+1] = mapper and mapper[chr] or chr
+ if n <= max then
+ return concat(t)
+ end
+end
+
+local function alphabetic(n,code)
+ return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,lowercharacter)
+end
+
+local function Alphabetic(n,code)
+ return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,uppercharacter)
+end
+
+converters.alphabetic = alphabetic
+converters.Alphabetic = Alphabetic
+
+-- we could make a replacer
+
+local function todecimals(n,name)
+ local stream = tostring(n)
+ local mapping = decimals[name]
+ return mapping and gsub(stream,".",mapping) or stream
+end
+
+converters.decimals = todecimals
+
+local lower_offset = 96
+local upper_offset = 64
+
+function converters.character (n) return chr (n,lower_offset) end
+function converters.Character (n) return chr (n,upper_offset) end
+function converters.characters(n) return chrs(n,lower_offset) end
+function converters.Characters(n) return chrs(n,upper_offset) end
+
+implement { name = "alphabetic", actions = { alphabetic, context }, arguments = { "integer", "string" } }
+implement { name = "Alphabetic", actions = { Alphabetic, context }, arguments = { "integer", "string" } }
+
+implement { name = "character", actions = { chr, context }, arguments = { "integer", lower_offset } }
+implement { name = "Character", actions = { chr, context }, arguments = { "integer", upper_offset } }
+implement { name = "characters", actions = { chrs, context }, arguments = { "integer", lower_offset } }
+implement { name = "Characters", actions = { chrs, context }, arguments = { "integer", upper_offset } }
+
+implement { name = "decimals", actions = { todecimals, context }, arguments = { "integer", "string" } }
+
+local weekday = os.weekday -- moved to l-os
+local isleapyear = os.isleapyear -- moved to l-os
+local nofdays = os.nofdays -- moved to l-os
+
+local function leapyear(year)
+ return isleapyear(year) and 1 or 0
+end
+
+local function textime()
+ return tonumber(date("%H")) * 60 + tonumber(date("%M"))
+end
+
+function converters.year () return date("%Y") end
+function converters.month () return date("%m") end
+function converters.hour () return date("%H") end
+function converters.minute() return date("%M") end
+function converters.second() return date("%S") end
+
+converters.weekday = weekday
+converters.isleapyear = isleapyear
+converters.leapyear = leapyear
+converters.nofdays = nofdays
+converters.textime = textime
+
+implement { name = "weekday", actions = { weekday, context }, arguments = { "integer", "integer", "integer" } }
+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 = "textime", actions = { textime, context } }
+
+implement {
+ name = "doifelseleapyear",
+ actions = { isleapyear, commands.doifelse },
+ arguments = "integer"
+}
+
+local roman = {
+ { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
+ { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
+ { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
+}
+
+local function toroman(n)
+ if n >= 4000 then
+ return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
+ else
+ return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n%10)/1)]
+ end
+end
+
+converters.toroman = toroman
+converters.Romannumerals = toroman
+converters.romannumerals = function(n) return lower(toroman(n)) end
+
+converters['i'] = converters.romannumerals
+converters['I'] = converters.Romannumerals
+converters['r'] = converters.romannumerals
+converters['R'] = converters.Romannumerals
+converters['KR'] = converters.Romannumerals
+converters['RK'] = converters.Romannumerals
+
+implement {
+ name = "romannumerals",
+ actions = { toroman, lower, context },
+ arguments = "integer",
+}
+
+implement {
+ name = "Romannumerals",
+ actions = { toroman, context },
+ arguments = "integer",
+}
+
+--~ local small = {
+--~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631
+--~ }
+
+--~ local large = {
+--~ { 0x0627, 0x0628, 0x062C, 0x062F, 0x0647, 0x0648, 0x0632, 0x062D, 0x0637, },
+--~ { 0x064A, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639, 0x0641, 0x0635, },
+--~ { 0x0642, 0x0631, 0x0634, 0x062A, 0x062B, 0x062E, 0x0630, 0x0636, 0x0638, },
+--~ { 0x063A },
+--~ }
+
+local small = {
+ "ا", "ٮ", "ح", "د", "ه", "و", "ر",
+}
+
+local medium = {
+ "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" ,
+ "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" ,
+ "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" ,
+ "غ" ,
+}
+
+local large = {
+ { "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" },
+ { "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" },
+ { "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" },
+ { "غ" },
+}
+
+local function toabjad(n,what)
+ if n <= 0 or n >= 2000 then
+ return tostring(n)
+ elseif what == 2 and n <= 7 then
+ return small[n]
+ elseif what == 3 and n <= 28 then
+ return medium[n]
+ else
+ local a, b, c, d
+ a, n = floor(n/1000), n % 1000 -- mod(n,1000)
+ b, n = floor(n/ 100), n % 100 -- mod(n, 100)
+ c, n = floor(n/ 10), n % 10 -- mod(n, 10)
+ d, n = floor(n/ 1), n % 1 -- mod(n, 1)
+ return (large[4][a] or "") .. (large[3][b] or "") .. (large[2][c] or "") .. (large[1][d] or "")
+ end
+end
+
+converters.toabjad = toabjad
+
+function converters.abjadnumerals (n) return toabjad(n,false) end
+function converters.abjadnodotnumerals(n) return toabjad(n,true ) end
+
+implement {
+ name = "abjadnumerals",
+ actions = { toabjad, context },
+ arguments = { "integer", false }
+}
+
+implement {
+ name = "abjadnodotnumerals",
+ actions = { toabjad, context },
+ arguments = { "integer", true }
+}
+
+local vector = {
+ normal = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ },
+ cap = {
+ [0] = "零",
+ [1] = "壹",
+ [2] = "贰",
+ [3] = "叁",
+ [4] = "肆",
+ [5] = "伍",
+ [6] = "陆",
+ [7] = "柒",
+ [8] = "捌",
+ [9] = "玖",
+ [10] = "拾",
+ [100] = "佰",
+ [1000] = "仟",
+ [10000] = "萬",
+ [100000000] = "亿",
+ },
+ all = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [20] = "廿",
+ [30] = "卅",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ }
+}
+
+local function tochinese(n,name) -- normal, caps, all
+ -- improved version by Li Yanrui
+ local result, r = { }, 0
+ local vector = vector[name] or vector.normal
+ while true do
+ if n == 0 then
+ break
+ elseif n >= 100000000 then
+ local m = floor(n/100000000)
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[100000000]
+ local z = n - m * 100000000
+ if z > 0 and z < 10000000 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 100000000
+ elseif n >= 10000000 then
+ local m = floor(n/10000)
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000000 then
+ local m = floor(n/10000)
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 10000
+ elseif n >= 100000 then
+ local m = floor(n/10000)
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 10000
+ elseif n >= 10000 then
+ local m = floor(n/10000)
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000 then
+ local m = floor(n/1000)
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[1000]
+ local z = n - m * 1000
+ if z > 0 and z < 100 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 1000
+ elseif n >= 100 then
+ local m = floor(n/100)
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[100]
+ local z = n - m * 100
+ if z > 0 and z < 10 then r = r + 1 ; result[r] = vector[0] end
+ n = n % 100
+ elseif n >= 10 then
+ local m = floor(n/10)
+ if m > 1 and vector[m*10] then
+ r = r + 1 ; result[r] = vector[m*10]
+ else
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[10]
+ end
+ n = n % 10
+ else
+ r = r + 1 ; result[r] = vector[n]
+ break
+ end
+ end
+ if (result[1] == vector[1] and result[2] == vector[10]) then
+ result[1] = ""
+ end
+ return concat(result)
+end
+
+-- local t = { 1,10,15,25,35,45,11,100,111,1111,10000,11111,100000,111111,1111111,11111111,111111111,100000000,1111111111,11111111111,111111111111,1111111111111 }
+-- for k=1,#t do
+-- local v = t[k]
+-- print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap"))
+-- end
+
+converters.tochinese = tochinese
+
+function converters.chinesenumerals (n,how) return tochinese(n,how or "normal") end
+function converters.chinesecapnumerals(n) return tochinese(n,"cap") end
+function converters.chineseallnumerals(n) return tochinese(n,"all") end
+
+converters['cn'] = converters.chinesenumerals
+converters['cn-c'] = converters.chinesecapnumerals
+converters['cn-a'] = converters.chineseallnumerals
+
+implement {
+ name = "chinesenumerals",
+ actions = { tochinese, context },
+ arguments = { "integer", "string" }
+}
+
+-- this is a temporary solution: we need a better solution when we have
+-- more languages
+
+converters['a'] = converters.characters
+converters['A'] = converters.Characters
+converters['AK'] = converters.Characters -- obsolete
+converters['KA'] = converters.Characters -- obsolete
+
+function converters.spanishnumerals(n) return alphabetic(n,"es") end
+function converters.Spanishnumerals(n) return Alphabetic(n,"es") end
+function converters.sloviannumerals(n) return alphabetic(n,"sl") end
+function converters.Sloviannumerals(n) return Alphabetic(n,"sl") end
+
+converters['alphabetic:es'] = converters.spanishnumerals
+converters['alphabetic:sl'] = converters.sloveniannumerals
+
+converters['Alphabetic:es'] = converters.Spanishnumerals
+converters['Alphabetic:sl'] = converters.Sloveniannumerals
+
+-- bonus
+
+converters['a:es'] = converters.spanishnumerals
+converters['a:sl'] = converters.sloveniannumerals
+converters['A:es'] = converters.Spanishnumerals
+converters['A:sl'] = converters.Sloveniannumerals
+
+-- end of bonus
+
+converters.sequences = converters.sequences or { }
+local sequences = converters.sequences
+
+storage.register("converters/sequences", sequences, "converters.sequences")
+
+function converters.define(name,set) -- ,language)
+ -- if language then
+ -- name = name .. ":" .. language
+ -- end
+ sequences[name] = settings_to_array(set)
+end
+
+function converters.max(name)
+ local s = sequences[name]
+ return s and #s or 0
+end
+
+implement {
+ name = "defineconversion",
+ actions = converters.define,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "nofconversions",
+ actions = { converters.max, context },
+ arguments = "string",
+}
+
+local function convert(method,n,language)
+ local converter = language and converters[method..":"..language] or converters[method]
+ if converter then
+ return converter(n)
+ else
+ local lowermethod = lower(method)
+ local linguistic = counters[lowermethod]
+ if linguistic then
+ return do_alphabetic(n,linguistic,lowermethod == method and lowercharacter or uppercharacter)
+ end
+ local sequence = sequences[method]
+ if sequence then
+ local max = #sequence
+ if n > max then
+ return sequence[(n-1) % max + 1]
+ else
+ return sequence[n]
+ end
+ end
+ return n
+ end
+end
+
+converters.convert = convert
+
+local function valid(method,language)
+ return converters[method..":"..language] or converters[method] or sequences[method]
+end
+
+implement {
+ name = "doifelseconverter",
+ actions = { valid, commands.doifelse },
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "checkedconversion",
+ actions = { convert, context },
+ arguments = { "string", "integer" }
+}
+
+-- Well, since the one asking for this didn't test it the following code is not
+-- enabled.
+--
+-- -- This Lua version is based on a Javascript by Behdad Esfahbod which in turn
+-- -- is based on GPL'd code by Roozbeh Pournader of the The FarsiWeb Project
+-- -- Group: http://www.farsiweb.info/jalali/jalali.js.
+-- --
+-- -- We start tables at one, I kept it zero based in order to stay close to
+-- -- the original.
+-- --
+-- -- Conversion by Hans Hagen
+--
+-- local g_days_in_month = { [0]=31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+-- local j_days_in_month = { [0]=31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 }
+--
+-- local function div(a,b)
+-- return math.floor(a/b)
+-- end
+--
+-- local function remainder(a,b)
+-- return a - div(a,b)*b
+-- end
+--
+-- function gregorian_to_jalali(gy,gm,gd)
+-- local jy, jm, jd, g_day_no, j_day_no, j_np, i
+-- gy, gm, gd = gy - 1600, gm - 1, gd - 1
+-- g_day_no = 365*gy + div((gy+3),4) - div((gy+99),100) + div((gy+399),400)
+-- i = 0
+-- while i < gm do
+-- g_day_no = g_day_no + g_days_in_month[i]
+-- i = i + 1
+-- end
+-- if (gm>1 and ((gy%4==0 and gy%100~=0) or (gy%400==0))) then
+-- g_day_no = g_day_no + 1
+-- end
+-- g_day_no = g_day_no + gd
+-- j_day_no = g_day_no - 79
+-- j_np = div(j_day_no,12053)
+-- j_day_no = remainder(j_day_no,12053)
+-- jy = 979 + 33*j_np + 4*div(j_day_no,1461)
+-- j_day_no = remainder(j_day_no,1461)
+-- if j_day_no >= 366 then
+-- jy = jy + div((j_day_no-1),365)
+-- j_day_no = remainder((j_day_no-1),365)
+-- end
+-- i = 0
+-- while i < 11 and j_day_no >= j_days_in_month[i] do
+-- j_day_no = j_day_no - j_days_in_month[i]
+-- i = i + 1
+-- end
+-- jm = i + 1
+-- jd = j_day_no + 1
+-- return jy, jm, jd
+-- end
+--
+-- function jalali_to_gregorian(jy,jm,jd)
+-- local gy, gm, gd, g_day_no, j_day_no, leap, i
+-- jy, jm, jd = jy - 979, jm - 1, jd - 1
+-- j_day_no = 365*jy + div(jy,33)*8 + div((remainder(jy,33)+3),4)
+-- i = 0
+-- while i < jm do
+-- j_day_no = j_day_no + j_days_in_month[i]
+-- i = i + 1
+-- end
+-- j_day_no = j_day_no + jd
+-- g_day_no = j_day_no + 79
+-- gy = 1600 + 400*div(g_day_no,146097)
+-- g_day_no = remainder (g_day_no, 146097)
+-- leap = 1
+-- if g_day_no >= 36525 then
+-- g_day_no = g_day_no - 1
+-- gy = gy + 100*div(g_day_no,36524)
+-- g_day_no = remainder (g_day_no, 36524)
+-- if g_day_no >= 365 then
+-- g_day_no = g_day_no + 1
+-- else
+-- leap = 0
+-- end
+-- end
+-- gy = gy + 4*div(g_day_no,1461)
+-- g_day_no = remainder (g_day_no, 1461)
+-- if g_day_no >= 366 then
+-- leap = 0
+-- g_day_no = g_day_no - 1
+-- gy = gy + div(g_day_no, 365)
+-- g_day_no = remainder(g_day_no, 365)
+-- end
+-- i = 0
+-- while g_day_no >= g_days_in_month[i] + ((i == 1 and leap) or 0) do
+-- g_day_no = g_day_no - g_days_in_month[i] + ((i == 1 and leap) or 0)
+-- i = i + 1
+-- end
+-- gm = i + 1
+-- gd = g_day_no + 1
+-- return gy, gm, gd
+-- end
+--
+-- print(gregorian_to_jalali(2009,02,24))
+-- print(jalali_to_gregorian(1387,12,06))
+
+-- -- more efficient but needs testing
+
+-- local escapes = characters.filters.utf.private.escapes
+
+-- local function do_alphabetic(n,mapping,chr)
+-- local max = #mapping
+-- if n > max then
+-- do_alphabetic(floor((n-1)/max),mapping,chr)
+-- n = (n-1)%max+1
+-- end
+-- n = chr(n,mapping)
+-- context(escapes[n] or utfchar(n))
+-- end
+
+-- local lccodes, uccodes, safechar = characters.lccode, characters.uccode, commands.safechar
+
+-- local function do_alphabetic(n,mapping,chr)
+-- local max = #mapping
+-- if n > max then
+-- do_alphabetic(floor((n-1)/max),mapping,chr)
+-- n = (n-1)%max+1
+-- end
+-- safechar(chr(n,mapping))
+-- end
+
+-- local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
+-- local function uppercased(n,mapping) return characters.uccode(mapping[n] or fallback) end
+
+-- function converters.alphabetic(n,code)
+-- do_alphabetic(n,counters[code] or counters.default,lowercased) -- lccode catches wrong tables
+-- end
+
+-- function converters.Alphabetic(n,code)
+-- do_alphabetic(n,counters[code] or counters.default,uppercased)
+-- end
+
+local ordinals = {
+ english = function(n)
+ local two = n % 100
+ if two == 11 or two == 12 or two == 13 then
+ return "th"
+ else
+ local one = n % 10
+ if one == 1 then
+ return "st"
+ elseif one == 2 then
+ return "nd"
+ elseif one == 3 then
+ return "rd"
+ else
+ return "th"
+ end
+ end
+ end,
+ dutch = function(n)
+ return "e"
+ end,
+ french = function(n)
+ if n == 1 then
+ return "er"
+ end
+ end,
+}
+
+ordinals.en = ordinals.english
+ordinals.nl = ordinals.dutch
+ordinals.fr = ordinals.french
+
+function converters.ordinal(n,language)
+ local t = language and ordinals[language]
+ return t and t(n)
+end
+
+local function ctxordinal(n,language)
+ local t = language and ordinals[language]
+ local o = t and t(n)
+ context(n)
+ if o then
+ context.highordinalstr(o)
+ end
+end
+
+implement {
+ name = "ordinal",
+ actions = ctxordinal,
+ arguments = { "integer", "string" }
+}
+
+-- verbose numbers
+
+local data = allocate()
+local verbose = { data = data }
+converters.verbose = verbose
+
+-- verbose english
+
+local words = {
+ [0] = "zero",
+ [1] = "one",
+ [2] = "two",
+ [3] = "three",
+ [4] = "four",
+ [5] = "five",
+ [6] = "six",
+ [7] = "seven",
+ [8] = "eight",
+ [9] = "nine",
+ [10] = "ten",
+ [11] = "eleven",
+ [12] = "twelve",
+ [13] = "thirteen",
+ [14] = "fourteen",
+ [15] = "fifteen",
+ [16] = "sixteen",
+ [17] = "seventeen",
+ [18] = "eighteen",
+ [19] = "nineteen",
+ [20] = "twenty",
+ [30] = "thirty",
+ [40] = "forty",
+ [50] = "fifty",
+ [60] = "sixty",
+ [70] = "seventy",
+ [80] = "eighty",
+ [90] = "ninety",
+ [100] = "hundred",
+ [1000] = "thousand",
+ [1000^2] = "million",
+ [1000^3] = "billion",
+ [1000^4] = "trillion",
+}
+
+local function translate(n)
+ local w = words[n]
+ if w then
+ return w
+ end
+ local t = { }
+ local function compose_one(n)
+ local w = words[n]
+ if w then
+ t[#t+1] = w
+ return
+ end
+ local a, b = floor(n/100), n % 100
+ if a == 10 then
+ t[#t+1] = words[1]
+ t[#t+1] = words[1000]
+ elseif a > 0 then
+ t[#t+1] = words[a]
+ t[#t+1] = words[100]
+ -- don't say 'nine hundred zero'
+ if b == 0 then
+ return
+ end
+ end
+ if words[b] then
+ t[#t+1] = words[b]
+ else
+ a, b = floor(b/10), n % 10
+ t[#t+1] = words[a*10]
+ t[#t+1] = words[b]
+ end
+ end
+ local function compose_two(n,m)
+ if n > (m-1) then
+ local a, b = floor(n/m), n % m
+ if a > 0 then
+ compose_one(a)
+ end
+ t[#t+1] = words[m]
+ n = b
+ end
+ return n
+ end
+ n = compose_two(n,1000^4)
+ n = compose_two(n,1000^3)
+ n = compose_two(n,1000^2)
+ n = compose_two(n,1000^1)
+ if n > 0 then
+ compose_one(n)
+ end
+ return #t > 0 and concat(t," ") or tostring(n)
+end
+
+data.english = {
+ words = words,
+ translate = translate,
+}
+
+data.en = data.english
+
+-- print(translate(11111111))
+-- print(translate(2221101))
+-- print(translate(1111))
+-- print(translate(1218))
+-- print(translate(1234))
+-- print(translate(12345))
+-- print(translate(12345678900000))
+
+-- verbose spanish (unchecked)
+
+local words = {
+ [1] = "uno",
+ [2] = "dos",
+ [3] = "tres",
+ [4] = "cuatro",
+ [5] = "cinco",
+ [6] = "seis",
+ [7] = "siete",
+ [8] = "ocho",
+ [9] = "nueve",
+ [10] = "diez",
+ [11] = "once",
+ [12] = "doce",
+ [13] = "trece",
+ [14] = "catorce",
+ [15] = "quince",
+ [16] = "dieciséis",
+ [17] = "diecisiete",
+ [18] = "dieciocho",
+ [19] = "diecinueve",
+ [20] = "veinte",
+ [21] = "veintiuno",
+ [22] = "veintidós",
+ [23] = "veintitrés",
+ [24] = "veinticuatro",
+ [25] = "veinticinco",
+ [26] = "veintiséis",
+ [27] = "veintisiete",
+ [28] = "veintiocho",
+ [29] = "veintinueve",
+ [30] = "treinta",
+ [40] = "cuarenta",
+ [50] = "cincuenta",
+ [60] = "sesenta",
+ [70] = "setenta",
+ [80] = "ochenta",
+ [90] = "noventa",
+ [100] = "ciento",
+ [200] = "doscientos",
+ [300] = "trescientos",
+ [400] = "cuatrocientos",
+ [500] = "quinientos",
+ [600] = "seiscientos",
+ [700] = "setecientos",
+ [800] = "ochocientos",
+ [900] = "novecientos",
+ [1000] = "mil",
+ [1000^2] = "millón",
+ [1000^3] = "mil millones",
+ [1000^4] = "billón",
+}
+
+local function translate(n)
+ local w = words[n]
+ if w then
+ return w
+ end
+ local t = { }
+ local function compose_one(n)
+ local w = words[n]
+ if w then
+ t[#t+1] = w
+ return
+ end
+ -- a, b = hundreds, remainder
+ local a, b = floor(n/100), n % 100
+ -- one thousand
+ if a == 10 then
+ t[#t+1] = words[1]
+ t[#t+1] = words[1000]
+ -- x hundred (n.b. this will not give thirteen hundred because
+ -- compose_one(n) is only called after
+ -- `n = compose(two(n, 1000^1))`.
+ elseif a > 0 then
+ t[#t+1] = words[a*100]
+ end
+ -- the remainder
+ if words[b] then
+ t[#t+1] = words[b]
+ else
+ -- a, b = tens, remainder
+ a, b = floor(b/10), n % 10
+ t[#t+1] = words[a*10]
+ t[#t+1] = "y"
+ t[#t+1] = words[b]
+ end
+ end
+ -- compose_two handles x billion, ... x thousand. When 1000 or less is
+ -- left, compose_one takes over.
+ local function compose_two(n,m)
+ if n > (m-1) then
+ local a, b = floor(n/m), n % m
+ if a > 0 then
+ compose_one(a)
+ end
+ t[#t+1] = words[m]
+ n = b
+ end
+ return n
+ end
+ n = compose_two(n,1000^4)
+ n = compose_two(n,1000^3)
+ n = compose_two(n,1000^2)
+ n = compose_two(n,1000^1)
+ if n > 0 then
+ compose_one(n)
+ end
+ return #t > 0 and concat(t," ") or tostring(n)
+end
+
+data.spanish = {
+ words = words,
+ translate = translate,
+}
+
+data.es = data.spanish
+
+-- print(translate(31))
+-- print(translate(101))
+-- print(translate(199))
+
+-- verbose handler:
+
+function converters.verbose.translate(n,language)
+ local t = language and data[language]
+ return t and t.translate(n) or n
+end
+
+local function verbose(n,language)
+ local t = language and data[language]
+ context(t and t.translate(n) or n)
+end
+
+implement {
+ name = "verbose",
+ actions = verbose,
+ arguments = { "integer", "string" }
+}
+
+-- These are just helpers but not really for the tex end. Do we have to
+-- use translate here?
+
+local whitespace = lpeg.patterns.whitespace
+local word = lpeg.patterns.utf8uppercharacter^-1 * (1-whitespace)^1
+local pattern_one = Cs( whitespace^0 * word^-1 * P(1)^0)
+local pattern_all = Cs((whitespace^1 + word)^1)
+
+function converters.word (s) return s end -- dummies for typos
+function converters.words(s) return s end -- dummies for typos
+function converters.Word (s) return lpegmatch(pattern_one,s) or s end
+function converters.Words(s) return lpegmatch(pattern_all,s) or s end
+
+converters.upper = characters.upper
+converters.lower = characters.lower
+
+-- print(converters.Word("foo bar"))
+-- print(converters.Word(" foo bar"))
+-- print(converters.Word("123 foo bar"))
+-- print(converters.Word(" 123 foo bar"))
+
+-- print(converters.Words("foo bar"))
+-- print(converters.Words(" foo bar"))
+-- print(converters.Words("123 foo bar"))
+-- print(converters.Words(" 123 foo bar"))
+
+-- --
+
+local v_day = variables.day
+local v_year = variables.year
+local v_month = variables.month
+local v_weekday = variables.weekday
+local v_referral = variables.referral
+local v_space = variables.space
+
+local v_MONTH = upper(v_month)
+local v_WEEKDAY = upper(v_weekday)
+
+local convert = converters.convert
+
+local days = { -- not variables
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
+}
+
+local months = { -- not variables
+ "january",
+ "february",
+ "march",
+ "april",
+ "may",
+ "june",
+ "july",
+ "august",
+ "september",
+ "october",
+ "november",
+ "december",
+}
+
+local monthmnems = { -- not variables
+ -- virtual table
+}
+
+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
+
+local function weekdayname(day,month,year)
+ return days[weekday(day,month,year)]
+end
+
+local function monthname(n)
+ return months[n]
+end
+
+local function monthmnem(n)
+ return monthmnems[n]
+end
+
+implement {
+ name = "dayname",
+ actions = { dayname, context.labeltext },
+ arguments = "integer",
+}
+
+implement {
+ name = "weekdayname",
+ actions = { weekdayname, context.labeltext },
+ arguments = { "integer", "integer", "integer" }
+}
+
+implement {
+ name = "monthname",
+ actions = { monthname, context.labeltext },
+ arguments = { "integer" }
+}
+
+implement {
+ name = "monthmnem",
+ actions = { monthmnem, context.labeltext },
+ arguments = { "integer" }
+}
+
+-- a prelude to a function that we can use at the lua end
+
+-- day:ord month:mmem
+-- j and jj obsolete
+
+local spaced = {
+ [v_year] = true,
+ [v_month] = true,
+ [v_MONTH] = true,
+ [v_day] = true,
+ [v_weekday] = true,
+ [v_WEEKDAY] = true,
+ [v_day] = true,
+}
+
+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 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
+ end
+ if not auto and spaced[tag] then
+ context.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(months[month])
+ elseif mnemonic then
+ context.labeltext(variables[monthmnems[month]])
+ else
+ context.labeltext(variables[months[month]])
+ end
+ elseif tag == v_MONTH then
+ if currentlanguage == false then
+ context.WORD(variables[months[month]])
+ elseif mnemonic then
+ context.LABELTEXT(variables[monthmnems[month]])
+ else
+ context.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(days[day])
+ else
+ context.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)
+ whatordinal = day
+ elseif tag == v_weekday or tag == "w" then
+ local wd = weekday(day,month,year)
+ if currentlanguage == false then
+ context(days[wd])
+ else
+ context.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
+ context.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
+ context.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))
+ end
+ end
+ end
+end
+
+implement {
+ name = "currentdate",
+ actions = currentdate,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "rawdate",
+ actions = currentdate,
+ arguments = { "string", false }
+}
+
+implement {
+ name = "unihex",
+ actions = { formatters["U+%05X"], context },
+ arguments = "integer"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv
new file mode 100644
index 00000000000..1f6dc54d5e6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv
@@ -0,0 +1,859 @@
+%D \module
+%D [ file=core-con,
+%D version=1997.26.08,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Conversion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Conversion}
+
+\registerctxluafile{core-con}{1.001}
+
+% todo: iso date ranges (from/to)
+
+\unprotect
+
+\ifdefined\currentlanguage \else \let\currentlanguage\empty \fi
+\ifdefined\labeltext \else \let\labeltext \firstofoneargument \fi
+
+%D This module deals with all kind of conversions from numbers and dates. I
+%D considered splitting this module in a support one and a core one, but to keep
+%D things simple as well as preserve the overview, I decided against splitting.
+
+\let\spr\firstofoneargument % separator
+\let\stp\firstofoneargument % stopper
+
+% needed for arab:
+
+\unexpanded\def\isolateseparators % even works with list separator overloading
+ {\def\spr##1{{##1}}% % we can probably best mess around with zwj
+ \def\stp##1{{##1}}} % and friends
+
+%D \macros
+%D {numbers}
+%D
+%D First we deal with the dummy conversion of numbers using the \TEX\ primitive
+%D \type{\number}. The uppercase alternative is only there for compatibility with
+%D the other conversion macros. We could do without \type{#1} but this way we get
+%D rid of unwanted braces. For the savety we also define a non||sence uppercase
+%D alternative.
+%D
+%D \showsetup{numbers}
+%D
+%D \starttyping
+%D \def\numbers#1{\number#1}
+%D \def\Numbers#1{\number#1}
+%D \stoptyping
+%D
+%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear,
+%D unless we use:
+
+\def\numbers#1{\purenumber{#1}}
+\def\Numbers#1{\purenumber{#1}}
+
+%D \macros
+%D {romannumerals,Romannumerals}
+%D
+%D \TEX\ the program uses a rather tricky conversion from numbers to their roman
+%D counterparts. This conversion could of course be programmed in \TEX\ itself, but
+%D I guess Knuth found the programming trick worth presenting.
+%D
+%D \showsetup{romannumerals}
+%D \showsetup{Romannumerals}
+
+\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax}
+\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax}
+
+%D Arabic etc:
+
+\def\abjadnumerals #1{\clf_abjadnumerals \numexpr#1\relax}
+\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax}
+\def\abjadnaivenumerals#1{\clf_alphabetic \numexpr#1\relax{arabic}} % okay?
+
+\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new
+\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new
+
+\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}}
+\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}}
+
+\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}}
+\def\devanagarinumerals#1{\clf_alphabetic\numexpr#1\relax{devanagari}}
+\def\gurmurkhinumerals #1{\clf_alphabetic\numexpr#1\relax{gurmurkhi}}
+\def\gujaratinumerals #1{\clf_alphabetic\numexpr#1\relax{gujarati}}
+\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}}
+\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}}
+\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}}
+\def\arabicnumerals #1{\clf_alphabetic\numexpr#1\relax{arabic}}
+\def\persiannumerals #1{\clf_alphabetic\numexpr#1\relax{persian}}
+\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}}
+\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}}
+
+\let\arabicexnumerals \persiannumerals
+
+\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}}
+\def\koreannumeralsp #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}}
+\def\koreannumeralsc #1{\clf_alphabetic\numexpr#1\relax{korean-circle}}
+
+\let\koreanparentnumerals \koreannumeralsp
+\let\koreanparenthesisnumerals\koreannumeralsp
+\let\koreancirclenumerals \koreannumeralsc
+
+\def\chinesenumerals #1{\clf_chinesenumerals\numexpr#1\relax{normal}}
+\def\chinesecapnumerals#1{\clf_chinesenumerals\numexpr#1\relax{cap}}
+\def\chineseallnumerals#1{\clf_chinesenumerals\numexpr#1\relax{all}}
+
+%D \macros
+%D {character,Character}
+%D
+%D Converting a number into a character can of course only be done with numbers
+%D less or equal to~26. At the cost of much more macros a faster conversion is
+%D possible, using:
+%D
+%D \starttyping
+%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
+%D \stoptyping
+%D
+%D But we prefer a simpel \type{\case}.
+%D
+%D \showsetup{character}
+%D \showsetup{Character}
+
+\def\unknowncharacter{-} % else in lists \relax
+
+\def\character#1{\clf_character\numexpr#1\relax}
+\def\Character#1{\clf_Character\numexpr#1\relax}
+
+%D \macros
+%D {characters,Characters}
+%D
+%D Converting large numbers is supported by the next two macros. This time we
+%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$.
+%D
+%D \showsetup{characters}
+%D \showsetup{Characters}
+
+\def\characters#1{\clf_characters\numexpr#1\relax}
+\def\Characters#1{\clf_Characters\numexpr#1\relax}
+
+%D \macros
+%D {greeknumerals,Greeknumerals}
+%D
+%D Why should we only honour the romans, and not the greek?
+
+% \let\greeknumerals\gobbleoneargument
+% \let\Greeknumerals\gobbleoneargument
+
+%D \macros
+%D {oldstylenumerals,oldstyleromannumerals}
+%D
+%D These conversions are dedicated to Frans Goddijn.
+
+\unexpanded\def\oldstylenumerals#1%
+ {\begingroup
+ \os\number#1%
+ \endgroup}
+
+\unexpanded\def\oldstyleromannumerals#1% will become obsolete
+ {\dontleavehmode
+ \hbox\bgroup
+ \ss\txx
+ \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}%
+ \scratchwidth \wd\scratchbox
+ \scratchheight\ht\scratchbox
+ \scratchdimen .1\exheight
+ \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax
+ \hskip-\scratchwidth
+ \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen
+ \hskip-\scratchwidth
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {protectconversion}
+%D
+%D The previous two commands are not robust enough to be passed to \type
+%D {\write} en \type{\message}. That's why we introduce:
+
+\unexpanded\def\protectconversion
+ {\let\doconvertcharacters\firstofoneargument}
+
+%D \macros
+%D {normaltime,normalyear,normalmonth,normalday}
+%D
+%D The last part of this module is dedicated to converting dates. Because we
+%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
+
+%D \macros
+%D {month,MONTH}
+%D
+%D Converting the month number into a month name is done using a case statement,
+%D abstact values and the label mechanism. This way users can easily redefine a
+%D label from for instance german into austrian.
+%D
+%D \starttyping
+%D \setuplabeltext [de] [january=J\"anner]
+%D \stoptyping
+%D
+%D Anyhow, the conversion looks like:
+
+\unexpanded\def\monthlong #1{\clf_monthname\numexpr#1\relax}
+\unexpanded\def\monthshort#1{\clf_monthmnem\numexpr#1\relax}
+
+\let\convertmonth\monthlong % for old times sake
+
+%D We redefine the \TEX\ primitive \type{\month} as:
+%D
+%D \showsetup{month}
+%D \showsetup{MONTH}
+
+\let\month \monthlong
+
+\unexpanded\def\MONTH #1{\WORD{\month {#1}}}
+\unexpanded\def\MONTHLONG #1{\WORD{\monthlong {#1}}}
+\unexpanded\def\MONTHSHORT#1{\WORD{\monthshort{#1}}}
+
+%D We never explicitly needed this, but Tobias Burnus pointed out that it would be
+%D handy to convert to the day of the week. In doing so, we have to calculate the
+%D total number of days, taking leapyears into account. For those who are curious:
+%D
+%D \startitemize[packed]
+%D \item years that can be divided by 4 are leapyears
+%D \item exept years that can be divided by 100
+%D \item unless years can be divided by 400
+%D \stopitemize
+
+%D \macros
+%D {weekday,WEEKDAY}
+%D
+%D The first one is sort of redundant. It takes the day number argument.
+%D
+%D \showsetup{weekday}
+%D \showsetup{WEEKDAY}
+
+\unexpanded\def\weekday#1{\clf_dayname\numexpr#1\relax}
+\unexpanded\def\WEEKDAY#1{\WORD{\clf_dayname\numexpr#1\relax}}
+
+%D \macros
+%D {getdayoftheweek, dayoftheweek}
+
+\newcount\normalweekday
+
+ \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax,\numexpr#3\relax} % name
+\unexpanded\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax,\numexpr#3\relax\relax} % number
+
+%D Using this macro in
+%D
+%D \startbuffer
+%D monday: \dayoftheweek {4} {5} {1992}
+%D friday: \dayoftheweek {16} {6} {1995}
+%D monday: \dayoftheweek {25} {8} {1997}
+%D saturday: \dayoftheweek {30} {8} {1997}
+%D tuesday: \dayoftheweek {2} {1} {1996}
+%D tuesday: \dayoftheweek {7} {1} {1997}
+%D tuesday: \dayoftheweek {13} {1} {1998}
+%D friday: \dayoftheweek {1} {1} {2000}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The macro \type {\getdayoftheweek} can be used to calculate the number
+%D \type {\normalweekday}.
+
+%D \macros
+%D {doifleapyearelse,
+%D getdayspermonth}
+%D
+%D Sometimes we need to know if we're dealing with a leapyear, so here is a
+%D testmacro:
+%D
+%D \starttyping
+%D \doifleapyearelse{year}{yes}{no}
+%D \stoptyping
+%D
+%D An example of its use can be seen in the macro
+%D
+%D \starttyping
+%D \getdayspermonth{year}{month}
+%D \stoptyping
+%D
+%D The number of days is available in the macro \type {\numberofdays}.
+
+\def\doifelseleapyear#1% expandable check
+ {\clf_doifelseleapyear\numexpr#1\relax}
+
+\let\doifleapyearelse\doifelseleapyear
+
+\unexpanded\def\getdayspermonth#1#2%
+ {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}}
+
+\def\dayspermonth#1#2%
+ {\clf_nofdays\numexpr#1\relax\numexpr#2\relax}
+
+% \dayoftheweek{2006}{9}{15}
+% \doifleapyearelse{2000}{OK}{NOT OK}
+% \doifleapyearelse{2100}{NOT OK}{OK}
+% \doifleapyearelse{2004}{OK}{NOT OK}
+% \doifleapyearelse{2003}{NOT OK}{OK}
+% \dayspermonth{2000}{2}
+% [\the\normaltime=\the\time]
+
+%D \macros
+%D {currentdate, rawdate, date}
+%D
+%D We use these conversion macros in the date formatting macro:
+%D
+%D \showsetup{currentdate}
+%D
+%D This macro takes care of proper spacing and delivers for instance:
+%D
+%D \startbuffer
+%D \currentdate[weekday,day,month,year]
+%D \currentdate[WEEKDAY,day,MONTH,year]
+%D \stopbuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D depending of course on the keywords. Here we gave:
+%D
+%D \typebuffer
+%D
+%D If needed one can also add non||keywords, like in
+%D
+%D \startbuffer
+%D \currentdate[dd,--,mm,--,yy]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or typeset: \getbuffer.
+%D
+%D When no argument is passed, the current date is given as specified per
+%D language (using \type{\installlanguage}).
+%D
+%D \showsetup{currentdate}
+%D
+%D \startbuffer
+%D \date
+%D \date[d=12,m=12,y=1998][weekday]
+%D \date[d=12,m=12,y=1998]
+%D \stopbuffer
+%D
+%D We can also typeset arbitrary dates, using the previous
+%D command.
+%D
+%D \typebuffer
+%D
+%D The date is specified by one character keys. When no date is given, we
+%D get the current date.
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+%D \starttabulate[|l|l|]
+%D \HL
+%D \NC year \NC (\currentdate[year]) \NC\NR
+%D \NC yy \NC (\currentdate[yy]) \NC\NR
+%D \NC y \NC (\currentdate[y]) \NC\NR
+%D \NC Y \NC (\currentdate[Y]) \NC\NR
+%D \HL
+%D \NC month \NC (\currentdate[month]) \NC\NR
+%D \NC mm \NC (\currentdate[mm]) \NC\NR
+%D \NC m \NC (\currentdate[m]) \NC\NR
+%D \NC M \NC (\currentdate[M]) \NC\NR
+%D \HL
+%D \NC day \NC (\currentdate[day]) \NC\NR
+%D \NC dd \NC (\currentdate[dd]) \NC\NR
+%D \NC d \NC (\currentdate[d]) \NC\NR
+%D \NC D \NC (\currentdate[D]) \NC\NR
+%D \HL
+%D \NC weekday \NC (\currentdate[weekday]) \NC\NR
+%D \NC w \NC (\currentdate[w]) \NC\NR
+%D \NC W \NC (\currentdate[W]) \NC\NR
+%D \HL
+%D \NC referral \NC (\currentdate[referral]) \NC\NR
+%D \HL
+%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR
+%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR
+%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR
+%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR
+%D \HL
+%D \stoptabulate
+%D
+%D \startbuffer
+%D (\currentdate[D,.,M,.,Y])
+%D (\currentdate[day,month,year])
+%D (\currentdate[day,+,month,+,year])
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\newtoks \everycurrentdate
+
+\unexpanded\def\currentdate
+ {\dosingleempty\syst_converters_current_date}
+
+\def\syst_converters_current_date[#1]%
+ {\begingroup
+ \the\everycurrentdate
+ \doifsomething{#1}{\edef\currentdatespecification{#1}}%
+ \clf_currentdate{\currentdatespecification}{\labellanguage}%
+ \endgroup}
+
+\unexpanded\def\date
+ {\dodoubleempty\syst_converters_date}
+
+\def\syst_converters_date[#1][#2]%
+ {\begingroup
+ \iffirstargument
+ \letdummyparameter\c!d\normalday
+ \letdummyparameter\c!m\normalmonth
+ \letdummyparameter\c!y\normalyear
+ \getdummyparameters[#1]%
+ \normalday \directdummyparameter\c!d\relax
+ \normalmonth\directdummyparameter\c!m\relax
+ \normalyear \directdummyparameter\c!y\relax
+ \fi
+ \syst_converters_current_date[#2]%
+ \endgroup}
+
+\def\rawdate[#1]% expandable and no labels
+ {\clf_rawdate{\currentdatespecification}}
+
+%D \macros
+%D {currenttime}
+%D
+%D The currenttime is actually the jobtime. You can specify a pattern similar
+%D to the previous date macro using the keys \type {h}, \type {m} and a separator.
+
+\unexpanded\def\calculatecurrenttime
+ {\edef\currenthour {\clf_hour }%
+ \edef\currentminute{\clf_minute}%
+ \edef\currentsecond{\clf_second}}
+
+\let\currenthour \!!plusone
+\let\currentminute\!!plusone
+\let\currentsecond\!!plusone
+
+\def\currenttimespecification{h,:,m}
+
+\unexpanded\def\currenttime
+ {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop}
+
+\unexpanded\def\syst_converters_current_time_yes[#1]%
+ {\calculatecurrenttime
+ \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
+
+\unexpanded\def\syst_converters_current_time_nop
+ {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}}
+
+%D Because we're dealing with dates, we also introduce a few day loops:
+%D
+%D \starttyping
+%D \processmonth{year}{month}{command}
+%D \processyear{year}{command}{before}{after}
+%D \stoptyping
+%D
+%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday}
+%D can be used for for date manipulations.
+
+\unexpanded\def\processmonth#1#2#3% year month command
+ {\begingroup
+ \getdayspermonth{#1}{#2}%
+ \dostepwiserecurse\plusone\numberofdays\plusone
+ {\normalyear #1\relax
+ \normalmonth#2\relax
+ \normalday \recurselevel\relax
+ #3}%
+ \endgroup}
+
+\def\lastmonth{12} % can be set to e.g. 1 when testing
+
+\unexpanded\def\processyear#1#2#3#4% year command before after
+ {\begingroup
+ \dorecurse\lastmonth
+ {\normalyear #1\relax
+ \normalmonth\recurselevel\relax
+ #3\processmonth\normalyear\normalmonth{#2}#4}%
+ \endgroup}
+
+%D \macros
+%D {defineconversion, convertnumber}
+%D
+%D Conversion involves the macros that we implemented earlier in this module.
+%D
+%D \showsetup{defineconversion}
+%D \showsetup{convertnumber}
+%D
+%D We can feed this command with conversion macros as well as a set of conversion
+%D symbols. Both need a bit different treatment.
+%D
+%D \starttyping
+%D \defineconversion [roman] [\romannumerals]
+%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
+%D \stoptyping
+%D
+%D You can define a language dependent conversion with:
+%D
+%D \starttyping
+%D \defineconversion [en] [whatever] [\something]
+%D \stoptyping
+
+\installcorenamespace {conversion}
+\installcorenamespace {conversionarguments}
+\installcorenamespace {conversionwords}
+
+%D It might be better to move more to lua as we also need conversion there
+%D and doublicating logic doesn't make things cleaner. It means that all
+%D conversions will get a language argument too. However, we permit definitions
+%D at the \TEX\ end so we have to provide some hybrid method.
+
+% checkedconversion(method,n,language)
+
+\unexpanded\def\defineconversion
+ {\dotripleempty\syst_converters_define_conversion}
+
+\def\syst_converters_define_conversion[#1][#2][#3]% from now on global (maybe local again some day)
+ {\ifthirdargument
+ \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}%
+ \else
+ \syst_converters_define_conversion_indeed{#1}{#1}{#2}%
+ \fi}
+
+\def\syst_converters_define_conversion_indeed#1#2#3%
+ {\doifelseinstring{,}{\detokenize{#3}}
+ {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols
+ \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}}
+ {\setgvalue{\??conversion#1}{#3}}}
+
+\def\syst_converters_checked_conversion#1#2%
+ {\clf_checkedconversion{#1}\numexpr#2\relax}
+
+%D If a conversion is just a font switch then we need to make sure that the
+%D number is indeed ends up as number in the input, so we need to handle the
+%D second argument.
+
+\def\convertnumber#1#2% expandable
+ {\csname\??conversionarguments
+ \ifcsname\??conversion\currentlanguage#1\endcsname1\else
+ \ifcsname\??conversion #1\endcsname2\else
+ 3\fi\fi
+ \endcsname{#1}{\number#2}}
+
+\unexpanded\def\uconvertnumber % unexpandable
+ {\convertnumber}
+
+\setvalue{\??conversionarguments1}#1{\csname\??conversion\currentlanguage#1\endcsname}
+\setvalue{\??conversionarguments2}#1{\csname\??conversion #1\endcsname}
+\letvalue{\??conversionarguments3}\syst_converters_checked_conversion
+
+% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check
+% if we have definitions that are not matched at the lua end .. eventually we might do
+% that when more shows up
+
+\def\doifelseconversiondefined#1% expandable
+ {\ifcsname\??conversion\currentlanguage#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??conversion#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\def\doifelseconversionnumber#1#2% expandable
+ {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifconversiondefinedelse\doifelseconversiondefined
+\let\doifconversionnumberelse \doifelseconversionnumber
+
+%D Handy.
+
+\setvalue{\??conversionwords\v!one }{1}
+\setvalue{\??conversionwords\v!two }{2}
+\setvalue{\??conversionwords\v!three}{3}
+\setvalue{\??conversionwords\v!four }{4}
+\setvalue{\??conversionwords\v!five }{5}
+
+%def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
+\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi}
+
+% \defineconversion[ctx][c,o,n,t,e,x,t]
+%
+% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
+
+%D \macros
+%D {ordinalnumber, highordinalstr, ordinalstr}
+%D
+%D Efficient general ordinal number converters are sometimes difficult to
+%D implement. Fortunately dates never exceed the number~31.
+
+\def\highordinalstr #1{\high{\notsmallcapped{#1}}}
+\def\ordinalstr #1{\notsmallcapped{#1}}
+\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}}
+\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}}
+
+\def\verbosenumber #1{\clf_verbose\numexpr#1\relax{\currentlanguage}}
+\def\VerboseNumber #1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}}}
+
+%D As longs as symbols are linked to levels or numbers, we can also use the
+%D conversion mechanism, but in for instance the itemization macros, we prefer
+%D symbols because they can more easier be (partially) redefined. Symbols are
+%D implemented in another module.
+
+\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}}
+\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}}
+
+\defineconversion [] [\numbers] % the default conversion
+\defineconversion [\v!empty] [\gobbleoneargument]
+\defineconversion [\v!none] [\numbers]
+\defineconversion [\s!default] [\numbers]
+
+\defineconversion [month] [\monthlong]
+\defineconversion [month:mnem] [\monthshort]
+
+\defineconversion [\v!character] [\character]
+\defineconversion [\v!Character] [\Character]
+
+\defineconversion [\v!characters] [\characters]
+\defineconversion [\v!Characters] [\Characters]
+
+\defineconversion [a] [\alphabeticnumerals]
+\defineconversion [A] [\Alphabeticnumerals]
+\defineconversion [AK] [\smallcappedcharacters]
+\defineconversion [KA] [\smallcappedcharacters]
+
+\defineconversion [\v!alphabetic] [\alphabeticnumerals]
+\defineconversion [\v!Alphabetic] [\Alphabeticnumerals]
+
+\defineconversion [\v!number] [\numbers]
+\defineconversion [\v!numbers] [\numbers]
+\defineconversion [\v!Numbers] [\Numbers]
+\defineconversion [\v!mediaeval] [\mediaeval]
+
+\defineconversion [\v!word] [\verbosenumber]
+\defineconversion [\v!words] [\verbosenumber]
+
+\defineconversion [\v!Word] [\VerboseNumber]
+\defineconversion [\v!Words] [\VerboseNumber]
+
+\defineconversion[\v!ordinal] [\ordinalnumber]
+\defineconversion[\v!Ordinal] [\Ordinalnumber]
+
+\defineconversion [n] [\numbers]
+\defineconversion [N] [\Numbers]
+\defineconversion [m] [\mediaeval]
+\defineconversion [o] [\oldstylenumerals]
+\defineconversion [O] [\oldstylenumerals]
+\defineconversion [or] [\oldstyleromannumerals]
+
+\defineconversion [\v!romannumerals] [\romannumerals]
+\defineconversion [\v!Romannumerals] [\Romannumerals]
+
+\defineconversion [i] [\romannumerals]
+\defineconversion [I] [\Romannumerals]
+\defineconversion [r] [\romannumerals]
+\defineconversion [R] [\Romannumerals]
+
+\defineconversion [KR] [\smallcappedromannumerals]
+\defineconversion [RK] [\smallcappedromannumerals]
+
+\defineconversion [\v!greek] [\greeknumerals]
+\defineconversion [\v!Greek] [\Greeknumerals]
+
+\defineconversion [g] [\greeknumerals]
+\defineconversion [G] [\Greeknumerals]
+
+%defineconversion [ñ] [\spanishnumerals]
+%defineconversion [Ñ] [\Spanishnumerals]
+
+\defineconversion [abjadnumerals] [\abjadnumerals]
+\defineconversion [abjadnodotnumerals] [\abjadnodotnumerals]
+\defineconversion [abjadnaivenumerals] [\abjadnaivenumerals]
+
+\defineconversion [thainumerals] [\thainumerals]
+\defineconversion [devanagarinumerals] [\devanagarinumerals]
+\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals]
+\defineconversion [gujaratinumerals] [\gujaratinumerals]
+\defineconversion [tibetannumerals] [\tibetannumerals]
+\defineconversion [greeknumerals] [\greeknumerals]
+\defineconversion [Greeknumerals] [\Greeknumerals]
+\defineconversion [arabicnumerals] [\arabicnumerals]
+\defineconversion [persiannumerals] [\persiannumerals]
+\defineconversion [arabicexnumerals] [\arabicexnumerals]
+\defineconversion [arabicdecimals] [\arabicdecimals]
+\defineconversion [persiandecimals] [\persiandecimals]
+
+\defineconversion [koreannumerals] [\koreannumerals]
+\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while)
+\defineconversion [koreanparenthesisnumerals]
+ [\koreanparenthesisnumerals]
+\defineconversion [koreancirclenumerals] [\koreancirclenumerals]
+
+\defineconversion [kr] [\koreannumerals]
+\defineconversion [kr-p] [\koreanparentnumerals]
+\defineconversion [kr-c] [\koreancirclenumerals]
+
+\defineconversion [chinesenumerals] [\chinesenumerals]
+\defineconversion [chinesecapnumerals] [\chinesecapnumerals]
+\defineconversion [chineseallnumerals] [\chineseallnumerals]
+
+\defineconversion [cn] [\chinesenumerals]
+\defineconversion [cn-c] [\chinesecapnumerals]
+\defineconversion [cn-a] [\chineseallnumerals]
+
+%D Moved from lang-def.mkiv:
+%D
+%D Define these as the general character enumeration when language is Slovenian. If
+%D you feel uncomfortable with this, mail Mojca, since she promised to to take the
+%D heat. Pablo was next to request this. We changed characters to numerals for this
+%D feature. We do need these definitions for mechanisms like itemize that check
+%D for converters.
+
+\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}}
+\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}}
+
+\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}}
+\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}}
+
+%defineconversion [\s!sl] [character] [\sloveniannumerals]
+%defineconversion [\s!sl] [Character] [\slovenianNumerals]
+%defineconversion [\s!sl] [characters] [\sloveniannumerals]
+%defineconversion [\s!sl] [Characters] [\slovenianNumerals]
+
+\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals]
+\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals]
+
+\defineconversion [\s!sl] [a] [\sloveniannumerals]
+\defineconversion [\s!sl] [A] [\slovenianNumerals]
+\defineconversion [\s!sl] [AK] [\smallcapped\sloveniannumerals]
+\defineconversion [\s!sl] [KA] [\smallcapped\sloveniannumerals]
+
+%defineconversion [\s!es] [character] [\spanishnumerals]
+%defineconversion [\s!es] [Character] [\spanishNumerals]
+%defineconversion [\s!es] [characters] [\spanishnumerals]
+%defineconversion [\s!es] [Characters] [\spanishNumerals]
+
+\defineconversion [\s!es] [alphabetic] [\spanishnumerals]
+\defineconversion [\s!es] [Alphabetic] [\spanishNumerals]
+
+\defineconversion [\s!es] [a] [\spanishnumerals]
+\defineconversion [\s!es] [A] [\spanishNumerals]
+\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals]
+\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals]
+
+\defineconversion [sloveniannumerals] [\sloveniannumerals]
+\defineconversion [slovenianNumerals] [\slovenianNumerals]
+
+\defineconversion [spanishnumerals] [\spanishnumerals]
+\defineconversion [spanishNumerals] [\spanishNumerals]
+
+%D In case a font has no greek (WS):
+
+\defineconversion [mathgreek]
+ [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ},
+ \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ},
+ \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ},
+ \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}]
+
+%D Handy too (expanded!):
+
+\def\unihex#1{\clf_unihex\numexpr#1\relax}
+
+%D Symbol sets:
+
+\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo
+
+\defineconversion
+ [set 0]
+ [{\symbol[bullet]},
+ {\symbol[dash]},
+ {\symbol[star]},
+ {\symbol[triangle]},
+ {\symbol[circle]},
+ {\symbol[medcircle]},
+ {\symbol[bigcircle]},
+ {\symbol[square]}]
+
+\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{*},
+ \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}]
+
+\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}]
+
+%D Iteration of suggestion by WS on mailinglist 2010.12.22:
+%D
+%D \starttyping
+%D \setupfloatsplitting[conversion=continued]
+%D \stoptyping
+
+\unexpanded\def\continuednumber#1%
+ {\labeltext{\ifcase#1\or\else\v!continued\fi}}
+
+\defineconversion
+ [\v!continued]
+ [\continuednumber]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-ctx.ctx b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.ctx
new file mode 100644
index 00000000000..5126ad2d2bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.ctx
@@ -0,0 +1,23 @@
+<?xml version='1.0' standalone='yes'?>
+
+<ctx:job>
+ <ctx:message>demo file</ctx:message>
+ <ctx:preprocess suffix='prep'>
+ <ctx:processors>
+ <ctx:processor name='step-1' suffix='one' >dummy-prep-command-1 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor>
+ <ctx:processor name='step-2' suffix='prep'>dummy-prep-command-2 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor>
+ </ctx:processors>
+ <ctx:files>
+ <ctx:file processor='step-1' >one*.xml</ctx:file>
+ <ctx:file processor='step-2' >two*.xml</ctx:file>
+ <ctx:file processor='step-1,step-2'>all*.xml</ctx:file>
+ </ctx:files>
+ </ctx:preprocess>
+ <ctx:process>
+ <ctx:resources>
+ <ctx:environment>step-1-step-2.tex</ctx:environment>
+ </ctx:resources>
+ </ctx:process>
+ <ctx:postprocess>
+ </ctx:postprocess>
+</ctx:job>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua
new file mode 100644
index 00000000000..c20691cd7be
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua
@@ -0,0 +1,367 @@
+if not modules then modules = { } end modules ['core-ctx'] = {
+ version = 1.001,
+ comment = "companion to core-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+Job control files aka ctx files are rather old and date from the mkii times.
+They were handled in texexec and mtx-context and deals with modes, modules,
+environments and preprocessing in projects where one such file drives the
+processing of lots of files without the need to provide command line
+arguments.
+
+In mkiv this concept was of course supported as well. The first implementation
+of mtx-context took much of the approach of texexec, but by now we have gotten
+rid of the option file (for passing modes, modules and environments), the stubs
+(for directly processing cld and xml) as well as the preprocessing component
+of the ctx files. Special helper features, like typesetting listings, were
+already moved to the extras (a direct side effect of the ability to pass along
+command line arguments.) All this made mtx-context more simple than its ancestor
+texexec.
+
+Because some of the modes might affect the mtx-context end, the ctx file is
+still loaded there but only for getting the modes. The file is loaded again
+during the run but as loading and basic processing takes less than a
+millisecond it's not that much of a burden.
+--]]
+
+-- the ctxrunner tabel might either become private or move to the job namespace
+-- which also affects the loading order
+
+local trace_prepfiles = false trackers.register("system.prepfiles", function(v) trace_prepfiles = v end)
+
+local gsub, find, match, validstring = string.gsub, string.find, string.match, string.valid
+local concat = table.concat
+local xmltext = xml.text
+
+local report_prepfiles = logs.reporter("system","prepfiles")
+
+local commands = commands
+local implement = interfaces.implement
+
+ctxrunner = ctxrunner or { }
+
+ctxrunner.prepfiles = utilities.storage.allocate()
+
+local function dontpreparefile(t,k)
+ return k -- we only store when we have a prepper
+end
+
+table.setmetatableindex(ctxrunner.prepfiles,dontpreparefile)
+
+local function filtered(str,method) -- in resolvers?
+ str = tostring(str)
+ if method == 'name' then str = file.nameonly(str)
+ elseif method == 'path' then str = file.dirname(str)
+ elseif method == 'suffix' then str = file.suffix(str)
+ elseif method == 'nosuffix' then str = file.removesuffix(str)
+ elseif method == 'nopath' then str = file.basename(str)
+ elseif method == 'base' then str = file.basename(str)
+-- elseif method == 'full' then
+-- elseif method == 'complete' then
+-- elseif method == 'expand' then -- str = file.expandpath(str)
+ end
+ return (gsub(str,"\\","/"))
+end
+
+-- local function substitute(e,str)
+-- local attributes = e.at
+-- if str and attributes then
+-- if attributes['method'] then
+-- str = filtered(str,attributes['method'])
+-- end
+-- if str == "" and attributes['default'] then
+-- str = attributes['default']
+-- end
+-- end
+-- return str
+-- end
+
+local function substitute(str)
+ return str
+end
+
+local function justtext(str)
+ str = xml.unescaped(tostring(str))
+ str = xml.cleansed(str)
+ str = gsub(str,"\\+",'/')
+ str = gsub(str,"%s+",' ')
+ return str
+end
+
+function ctxrunner.load(ctxname)
+
+ local xmldata = xml.load(ctxname)
+
+ local jobname = tex.jobname -- todo
+
+ local variables = { job = jobname }
+ local commands = { }
+ local flags = { }
+ local paths = { } -- todo
+ local treatments = { }
+ local suffix = "prep"
+
+ xml.include(xmldata,'ctx:include','name', {'.', file.dirname(ctxname), "..", "../.." })
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
+ local flag = xmltext(e)
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ environment.setargument(key,value)
+ else
+ environment.setargument(flag,true)
+ end
+ end
+
+ -- add to document.options.ctxfile[...]
+
+ local ctxfile = document.options.ctxfile
+
+ local modes = ctxfile.modes
+ local modules = ctxfile.modules
+ local environments = ctxfile.environments
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode") do
+ modes[#modes+1] = xmltext(e)
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module") do
+ modules[#modules+1] = xmltext(e)
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do
+ environments[#environments+1] = xmltext(e)
+ end
+
+ for e in xml.collected(xmldata,"ctx:message") do
+ report_prepfiles("ctx comment: %s", xmltext(e))
+ end
+
+ for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do
+ d[k] = variables['job'] or ""
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
+ local name = e.at and e.at['name'] or "unknown"
+ local suffix = e.at and e.at['suffix'] or "prep"
+ for r, d, k in xml.elements(command,"ctx:old") do
+ d[k] = "%old%"
+ end
+ for r, d, k in xml.elements(e,"ctx:new") do
+ d[k] = "%new%"
+ end
+ for r, d, k in xml.elements(e,"ctx:value") do
+ local tag = d[k].at['name']
+ if tag then
+ d[k] = "%" .. tag .. "%"
+ end
+ end
+ local runner = xml.textonly(e)
+ if runner and runner ~= "" then
+ commands[name] = {
+ suffix = suffix,
+ runner = runner,
+ }
+ end
+ end
+
+ local suffix = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/attribute('suffix')") or suffix
+ local runlocal = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
+
+ runlocal = toboolean(runlocal)
+
+ -- todo: only collect, then plug into file handler
+
+ local inputfile = validstring(environment.arguments.input) or jobname
+
+ variables.old = inputfile
+
+ for files in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
+ for pattern in xml.collected(files,"ctx:file") do
+ local preprocessor = pattern.at['processor'] or ""
+ for r, d, k in xml.elements(pattern,"/ctx:old") do
+ d[k] = jobname
+ end
+ for r, d, k in xml.elements(pattern,"/ctx:value[@name='old'") do
+ d[k] = jobname
+ end
+ pattern =justtext(xml.tostring(pattern))
+ if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then
+ local noftreatments = #treatments + 1
+ local findpattern = string.topattern(pattern)
+ local preprocessors = utilities.parsers.settings_to_array(preprocessor)
+ treatments[noftreatments] = {
+ pattern = findpattern,
+ preprocessors = preprocessors,
+ }
+ report_prepfiles("step %s, pattern %a, preprocessor: %a",noftreatments,findpattern,preprocessors)
+ end
+ end
+ end
+
+ local function needstreatment(oldfile)
+ for i=1,#treatments do
+ local treatment = treatments[i]
+ local pattern = treatment.pattern
+ if find(oldfile,pattern) then
+ return treatment
+ end
+ end
+ end
+
+ local preparefile = #treatments > 0 and function(prepfiles,filename)
+
+ local treatment = needstreatment(filename)
+ local oldfile = filename
+ local newfile = false
+ if treatment then
+ local preprocessors = treatment.preprocessors
+ local runners = { }
+ for i=1,#preprocessors do
+ local preprocessor = preprocessors[i]
+ local command = commands[preprocessor]
+ if command then
+ local runner = command.runner
+ local suffix = command.suffix
+ local result = filename .. "." .. suffix
+ if runlocal then
+ result = file.basename(result)
+ end
+ variables.old = oldfile
+ variables.new = result
+ runner = utilities.templates.replace(runner,variables)
+ if runner and runner ~= "" then
+ runners[#runners+1] = runner
+ oldfile = result
+ if runlocal then
+ oldfile = file.basename(oldfile)
+ end
+ newfile = oldfile
+ end
+ end
+ end
+ if not newfile then
+ newfile = filename
+ elseif file.needsupdating(filename,newfile) then
+ for i=1,#runners do
+ report_prepfiles("step %i: %s",i,runners[i])
+ end
+ --
+ for i=1,#runners do
+ local command = runners[i]
+ report_prepfiles("command: %s",command)
+ local result = os.execute(command) or 0
+ -- if result > 0 then
+ -- report_prepfiles("error, return code: %s",result)
+ -- end
+ end
+ if lfs.isfile(newfile) then
+ file.syncmtimes(filename,newfile)
+ report_prepfiles("%a is converted to %a",filename,newfile)
+ else
+ report_prepfiles("%a is not converted to %a",filename,newfile)
+ newfile = filename
+ end
+ elseif lfs.isfile(newfile) then
+ report_prepfiles("%a is already converted to %a",filename,newfile)
+ end
+ else
+ newfile = filename
+ end
+ prepfiles[filename] = newfile
+ -- in case we ask twice (with the prepped name) ... todo: avoid this mess
+ prepfiles[newfile] = newfile
+ return newfile
+ end
+
+ table.setmetatableindex(ctxrunner.prepfiles,preparefile or dontpreparefile)
+
+ -- we need to deal with the input filename as it has already be resolved
+
+end
+
+-- print("\n")
+-- document = {
+-- options = {
+-- ctxfile = {
+-- modes = { },
+-- modules = { },
+-- environments = { },
+-- }
+-- }
+-- }
+-- environment.arguments.input = "test.tex"
+-- ctxrunner.load("x-ldx.ctx")
+
+local function resolve(name) -- used a few times later on
+ return ctxrunner.prepfiles[file.collapsepath(name)] or false
+end
+
+function ctxrunner.preparedfile(name)
+ return resolve(name) or name
+end
+
+local processfile = commands.processfile
+local doifelseinputfile = commands.doifelseinputfile
+
+implement {
+ name = "processfile",
+ overload = true,
+ arguments = { "string", "integer" },
+ actions = function(name,maxreadlevel) -- overloaded
+ local prepname = resolve(name)
+ if prepname then
+ return processfile(prepname,0)
+ end
+ return processfile(name,maxreadlevel)
+ end
+}
+
+implement {
+ name = "doifelseinputfile",
+ overload = true,
+ arguments = { "string", "integer" },
+ actions = function(name,depth)
+ local prepname = resolve(name)
+ if prepname then
+ return doifelseinputfile(prepname,0)
+ end
+ return doifelseinputfile(name,depth)
+ end
+}
+
+-- implement {
+-- name = "preparedfile", -- not used
+-- arguments = "string",
+-- actions = { ctxrunner.preparedfile, context }
+-- }
+
+implement {
+ name = "setdocumentctxfile",
+ onlyonce = true,
+ actions = function()
+ local ctxfile = document.arguments.ctx or ""
+ if ctxfile ~= "" then
+ ctxrunner.load(ctxfile) -- do we need to locate it?
+ end
+ end
+}
+
+function ctxrunner.resolve(name) -- used a few times later on
+ local collapsedname = file.collapsepath(name,".")
+ return ctxrunner.prepfiles[collapsedname] or collapsedname
+end
+
+-- ctxrunner.load("t:/sources/core-ctx.ctx")
+
+-- context(ctxrunner.prepfiles["one-a.xml"]) context.par()
+-- context(ctxrunner.prepfiles["one-b.xml"]) context.par()
+-- context(ctxrunner.prepfiles["two-c.xml"]) context.par()
+-- context(ctxrunner.prepfiles["two-d.xml"]) context.par()
+-- context(ctxrunner.prepfiles["all-x.xml"]) context.par()
+
+-- inspect(ctxrunner.prepfiles)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.mkiv
new file mode 100644
index 00000000000..e6372d0996a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.mkiv
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=core-ctx,
+%D version=2006.08.16, % old stuff
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Control,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Job Control}
+
+\registerctxluafile{core-ctx}{1.000}
+
+\unprotect
+
+% called directly in core-def.mkiv
+%
+% \unexpanded\def\job_options_get_commandline {\clf_setdocumentcommandline}
+% \unexpanded\def\job_options_get_ctxfile {\clf_setdocumentctxfile}
+% \unexpanded\def\job_options_set_modes {\clf_setdocumentmodes}
+% \unexpanded\def\job_options_set_modules {\clf_setdocumentmodules}
+% \unexpanded\def\job_options_set_environments{\clf_setdocumentenvironments}
+% \unexpanded\def\job_options_set_filenames {\clf_setdocumentfilenames}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua b/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua
new file mode 100644
index 00000000000..c3b00a7c098
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua
@@ -0,0 +1,315 @@
+if not modules then modules = { } end modules ['core-dat'] = {
+ version = 1.001,
+ comment = "companion to core-dat.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>This module provides a (multipass) container for arbitrary data. It
+replaces the twopass data mechanism.</p>
+--ldx]]--
+
+local tonumber, tostring, type = tonumber, tostring, type
+
+local context = context
+local commands = commands
+
+local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
+local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end)
+
+local report_dataset = logs.reporter("dataset")
+local report_pagestate = logs.reporter("pagestate")
+
+local allocate = utilities.storage.allocate
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
+local formatters = string.formatters
+
+local v_yes = interfaces.variables.yes
+
+local new_latelua = nodes.pool.latelua
+
+local implement = interfaces.implement
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local datasets = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.datasets = datasets
+
+local function initializer()
+ collected = datasets.collected
+ tobesaved = datasets.tobesaved
+end
+
+job.register('job.datasets.collected', tobesaved, initializer, nil)
+
+local sets = { }
+
+table.setmetatableindex(tobesaved, function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end)
+
+table.setmetatableindex(sets, function(t,k)
+ local v = {
+ index = 0,
+ order = 0,
+ }
+ t[k] = v
+ return v
+end)
+
+local function setdata(settings)
+ local name = settings.name
+ local tag = settings.tag
+ local data = settings.data
+ local list = tobesaved[name]
+ if settings.convert and type(data) == "string" then
+ data = settings_to_hash(data)
+ end
+ if type(data) ~= "table" then
+ data = { data = data }
+ end
+ if not tag then
+ tag = #list + 1
+ else
+ tag = tonumber(tag) or tag -- autonumber saves keys
+ end
+ list[tag] = data
+ if settings.delay == v_yes then
+ local set = sets[name]
+ local index = set.index + 1
+ set.index = index
+ data.index = index
+ data.order = index
+ data.realpage = texgetcount("realpageno")
+ if trace_datasets then
+ report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index)
+ end
+ elseif trace_datasets then
+ report_dataset("action %a, name %a, tag %a","assign immediate",name,tag)
+ end
+ return name, tag, data
+end
+
+datasets.setdata = setdata
+
+function datasets.extend(name,tag)
+ local set = sets[name]
+ local order = set.order + 1
+ local realpage = texgetcount("realpageno")
+ set.order = order
+ local t = tobesaved[name][tag]
+ t.realpage = realpage
+ t.order = order
+ if trace_datasets then
+ report_dataset("action %a, name %a, tag %a, page %a, index %a","flush by order",name,tag,t.index or 0,order,realpage)
+ end
+end
+
+function datasets.getdata(name,tag,key,default)
+ local t = collected[name]
+ if t == nil then
+ if trace_datasets then
+ report_dataset("error: unknown dataset, name %a",name)
+ end
+ elseif type(t) ~= "table" then
+ return t
+ else
+ t = t[tag] or t[tonumber(tag)]
+ if not t then
+ if trace_datasets then
+ report_dataset("error: unknown dataset, name %a, tag %a",name,tag)
+ end
+ elseif key then
+ return t[key] or default
+ else
+ return t
+ end
+ end
+ return default
+end
+
+local function setdataset(settings)
+ settings.convert = true
+ 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)))
+ end
+end
+
+local function datasetvariable(name,tag,key)
+ local t = collected[name]
+ if t == nil then
+ if trace_datasets then
+ report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name) -- no tag
+ end
+ elseif type(t) ~= "table" then
+ context(tostring(t))
+ else
+ t = t and (t[tag] or t[tonumber(tag)])
+ if not t then
+ if trace_datasets then
+ report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
+ end
+ elseif type(t) == "table" then
+ local s = t[key]
+ if type(s) ~= "table" then
+ context(tostring(s))
+ elseif trace_datasets then
+ report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
+ end
+ end
+ end
+end
+
+implement {
+ name = "setdataset",
+ actions = setdataset,
+ arguments = {
+ {
+ { "name" },
+ { "tag" },
+ { "delay" },
+ { "data" },
+ }
+ }
+}
+
+implement {
+ name = "datasetvariable",
+ actions = datasetvariable,
+ arguments = { "string", "string", "string" }
+}
+
+--[[ldx--
+<p>We also provide an efficient variant for page states.</p>
+--ldx]]--
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local pagestates = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.pagestates = pagestates
+
+local function initializer()
+ collected = pagestates.collected
+ tobesaved = pagestates.tobesaved
+end
+
+job.register('job.pagestates.collected', tobesaved, initializer, nil)
+
+table.setmetatableindex(tobesaved, function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end)
+
+local function setstate(settings)
+ local name = settings.name
+ local tag = settings.tag
+ local list = tobesaved[name]
+ if not tag then
+ tag = #list + 1
+ else
+ tag = tonumber(tag) or tag -- autonumber saves keys
+ end
+ local realpage = texgetcount("realpageno")
+ local data = realpage
+ list[tag] = data
+ if trace_pagestates then
+ report_pagestate("action %a, name %a, tag %a, preset %a","set",name,tag,realpage)
+ end
+ return name, tag, data
+end
+
+pagestates.setstate = setstate
+
+function pagestates.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)
+ end
+ tobesaved[name][tag] = realpage
+end
+
+function pagestates.realpage(name,tag,default)
+ local t = collected[name]
+ if t then
+ t = t[tag] or t[tonumber(tag)]
+ if t then
+ return tonumber(t or default)
+ elseif trace_pagestates then
+ report_pagestate("error: unknown dataset, name %a, tag %a",name,tag)
+ end
+ elseif trace_pagestates then
+ report_pagestate("error: unknown dataset, name %a, tag %a",name) -- nil
+ end
+ 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 t = collected[name]
+ t = t and (t[tag] or t[tonumber(tag)])
+ if t then
+ context(t)
+ end
+end
+
+local function setpagestaterealpageno(name,tag)
+ local t = collected[name]
+ t = t and (t[tag] or t[tonumber(tag)])
+ texsetcount("realpagestateno",t or texgetcount("realpageno"))
+end
+
+implement {
+ name = "setpagestate",
+ actions = setpagestate,
+ arguments = {
+ {
+ { "name" },
+ { "tag" },
+ { "delay" },
+ }
+ }
+}
+
+implement {
+ name = "pagestaterealpage",
+ actions = pagestaterealpage,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setpagestaterealpageno",
+ actions = setpagestaterealpageno,
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv
new file mode 100644
index 00000000000..26b1f14b5c0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv
@@ -0,0 +1,101 @@
+%D \module
+%D [ file=core-dat,
+%D version=20122.04.17, % replaces core-two from 1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Multipass Datasets,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Multipass Datasets}
+
+%D \starttyping
+%D \definedataset[test-1]
+%D \definedataset[test-2][delay=yes]
+%D
+%D \startlines
+%D set 1: \setdataset[test-1][whatever=this-or-that-1]
+%D set 2: \setdataset[test-2][whatever=this-or-that-2]
+%D set 3: \setdataset[test-2][whatever=this-or-that-3]
+%D \stoplines
+%D
+%D \startlines
+%D get 1: \datasetvariable{test-1}{1}{whatever} / \datasetvariable{test-1}{1}{realpage}
+%D get 2: \datasetvariable{test-2}{1}{whatever} / \datasetvariable{test-2}{1}{realpage}
+%D get 3: \datasetvariable{test-2}{2}{whatever} / \datasetvariable{test-2}{2}{realpage}
+%D \stoplines
+%D \stoptyping
+
+\unprotect
+
+\registerctxluafile{core-dat}{1.001}
+
+\installcorenamespace{dataset}
+
+\installcommandhandler \??dataset {dataset} \??dataset
+
+\unexpanded\def\setdataset
+ {\dotripleempty\syst_datasets_set}
+
+\def\syst_datasets_set
+ {\ifthirdargument
+ \expandafter\syst_datasets_set_named
+ \else
+ \expandafter\syst_datasets_set_indexed
+ \fi}
+
+\def\syst_datasets_set_named[#1][#2][#3]%
+ {\begingroup
+ \edef\currentdataset{#1}%
+ \clf_setdataset
+ name {\currentdataset}%
+ tag {#2}%
+ delay {\datasetparameter\c!delay}%
+ data {#3}%
+ \relax
+ \endgroup}
+
+\def\syst_datasets_set_indexed[#1][#2][#3]%
+ {\begingroup
+ \edef\currentdataset{#1}%
+ \clf_setdataset
+ name {\currentdataset}%
+ delay {\datasetparameter\c!delay}%
+ data {#2}%
+ \relax
+ \endgroup}
+
+\def\datasetvariable#1#2#3%
+ {\clf_datasetvariable{#1}{#2}{#3}}
+
+\installcorenamespace{pagestate}
+
+\installcommandhandler \??pagestate {pagestate} \??pagestate
+
+\setuppagestate
+ [\c!delay=\v!yes]
+
+\unexpanded\def\setpagestate
+ {\dodoubleempty\syst_pagestates_set}
+
+\def\syst_pagestates_set[#1][#2]%
+ {\begingroup
+ \edef\currentpagestate{#1}%
+ \clf_setpagestate
+ name {\currentpagestate}%
+ tag {#2}%
+ delay {\pagestateparameter\c!delay}%
+ \relax
+ \endgroup}
+
+\def\pagestaterealpage#1#2%
+ {\clf_pagestaterealpage{#1}{#2}}
+
+\def\setpagestaterealpageno#1#2%
+ {\clf_setpagestaterealpageno{#1}{#2}}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv
new file mode 100644
index 00000000000..acd411faccb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv
@@ -0,0 +1,170 @@
+%D \module
+%D [ file=core-def,
+%D version=2002.05.07,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Defaults}
+
+%D Here we collect settings that cannot be done earlier due to
+%D depedencies. More code will moved to this module later.
+
+\unprotect
+
+\usesymbols[mis,nav] % no longer mvs preloaded
+
+\setupsymbolset[navigation 1]
+
+\setupinteraction[\c!symbolset=navigation 1]
+
+% what a mess
+
+\everypar \emptytoks
+\neverypar \emptytoks
+
+\appendtoks
+ % \flushnotes
+ \page_otr_command_synchronize_side_floats % an otr specific command
+ \checkindentation
+ \showparagraphnumber
+ \restoreinterlinepenalty
+ % \flushmargincontents
+ % \flushcommentanchors
+ \flushnotes
+ \synchronizenotes
+ \OTRSETshowstatus
+ \registerparoptions
+ % \flushsyncpositions
+ \flushpostponednodedata
+ \typo_delimited_repeat
+ \insertparagraphintro
+ \typo_initial_handle
+ \typo_firstline_handle
+\to \everypar
+
+\appendtoks
+ \flushnotes
+\to \everydisplay
+
+\appendtoks
+ \adjustsidefloatdisplaylines
+\to \everydisplay
+
+% \appendtoks
+% \flushpostponednodedata
+% \to \neverypar
+
+% \appendtoks
+% \flushsyncpositions
+% \to \everyheadstart
+
+% \appendtoks
+% \flushsyncresets
+% \to \everyendoftextbody
+
+\appendtoks
+ \ignorespaces
+\to \everybeginofpar
+
+\appendtoks
+ \removeunwantedspaces
+ % \strut % option ?
+ % \flushsyncresets
+ % \setlastlinewidth % gone, will be done in lua
+ \endgraf
+\to \everyendofpar
+
+% initialization order:
+
+\ifdefined\font_preloads_at_every_job \else \let\font_preloads_at_every_job \relax \fi
+\ifdefined\font_preloads_at_start_text \else \let\font_preloads_at_start_text\relax \fi
+\ifdefined\font_preloads_at_stop_text \else \let\font_preloads_at_stop_text \relax \fi
+
+\appendtoks
+ \font_preloads_at_start_text
+\to \everystarttext
+
+\appendtoks
+ \font_preloads_at_stop_text
+\to \everystoptext
+
+% We made \loadoptionfile obsolete: we pass options via the command line to
+% luatex now and handle them directly instead of via a file. This also makes
+% the next obsolete:
+%
+% \directsetup{*runtime:options}
+% \directsetup{*runtime:modules}
+
+\appendtoks
+ \showcontextbanner
+ \initializenewlinechar
+ \calculatecurrenttime
+ \syst_files_load
+ \clf_setdocumentcommandline
+ \clf_setdocumentctxfile
+ \clf_setdocumentfilenames
+ \font_preloads_at_every_job
+ \settopskip % brrr
+ \initializemainlanguage
+ \initializepagebackgrounds
+ \initializepagecounters
+ \clf_setdocumentmodes
+ \clf_setdocumentmodules
+ \clf_setdocumentenvironments
+\to \everyjob
+
+\appendtoks
+ \ifarrangingpages\poparrangedpages\fi
+\to \everybye
+
+\prependtoks
+ \resetallattributes
+\to \everybeforeoutput
+
+\appendtoks
+ \the\everybackendshipout
+\to \everyshipout
+
+\prependtoks
+ \the\everylastbackendshipout
+\to \everylastshipout
+
+\prependtoks
+ \lefttoright
+\to \everybeforeoutput
+
+% temporary here:
+
+\unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg}
+
+% might move to \everydump or even disappear:
+
+\nonknuthmode
+
+% brrr
+
+\appendtoks
+ \synchronizegloballinespecs
+ \synchronizelocallinespecs
+\to \everysetupbodyfont
+
+\appendtoks
+ \synchronizelocallinespecs
+\to \everyswitchtobodyfont
+
+% who knows
+
+% \appendtoks
+% \resetcharacterspacing
+% \to \everyhyphenatedurl
+
+% \setbreakpoints[compound]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-env.lua b/Master/texmf-dist/tex/context/base/mkiv/core-env.lua
new file mode 100644
index 00000000000..06c9708d6eb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-env.lua
@@ -0,0 +1,274 @@
+if not modules then modules = { } end modules ['core-env'] = {
+ version = 1.001,
+ comment = "companion to core-env.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- maybe this will move to the context name space although the
+-- plurals are unlikely to clash with future tex primitives
+--
+-- if tex.modes['xxxx'] then .... else .... end
+
+local P, C, S, Cc, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.match, lpeg.patterns
+
+local context = context
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local setmetatablecall = table.setmetatablecall
+
+local createtoken = token.create
+
+tex.modes = allocate { }
+tex.systemmodes = allocate { }
+tex.constants = allocate { }
+tex.conditionals = allocate { }
+tex.ifs = allocate { }
+tex.isdefined = allocate { }
+
+local modes = { }
+local systemmodes = { }
+
+-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching
+-- at the lua en dis not that bad (and we need more anyway)
+
+-- undefined: mode == 0 or cmdname = "undefined_cs"
+
+
+local cache = table.setmetatableindex(function(t,k)
+ local v = createtoken(k)
+ t[k] = v
+ return v
+end)
+
+-- we can have a modes cache too
+
+local iftrue = cache["iftrue"].mode
+local undefined = cache["*undefined*crap*"].mode -- is this ok?
+
+setmetatableindex(tex.modes, function(t,k)
+ local m = modes[k]
+ if m then
+ return m()
+ else
+ local n = "mode>" .. k
+ if cache[n].mode == 0 then
+ return false
+ else
+ modes[k] = function() return texgetcount(n) == 1 end
+ return texgetcount(n) == 1 -- 2 is prevented
+ end
+ end
+end)
+
+setmetatableindex(tex.systemmodes, function(t,k)
+ local m = systemmodes[k]
+ if m then
+ return m()
+ else
+ local n = "mode>*" .. k
+ if cache[n].mode == 0 then
+ return false
+ else
+ systemmodes[k] = function() return texgetcount(n) == 1 end
+ return texgetcount(n) == 1 -- 2 is prevented
+ end
+ end
+end)
+
+setmetatableindex(tex.constants, function(t,k)
+ return cache[k].mode ~= 0 and texgetcount(k) or 0
+end)
+
+setmetatableindex(tex.conditionals, function(t,k) -- 0 == true
+ return cache[k].mode ~= 0 and texgetcount(k) == 0
+end)
+
+table.setmetatableindex(tex.ifs, function(t,k)
+ -- local mode = cache[k].mode
+ -- if mode == 0 then
+ -- return nil
+ -- else
+ -- return mode == iftrue
+ -- end
+ return cache[k].mode == iftrue
+end)
+
+setmetatableindex(tex.isdefined, function(t,k)
+ return k and cache[k].mode ~= 0
+end)
+
+setmetatablecall(tex.isdefined, function(t,k)
+ return k and cache[k].mode ~= 0
+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",
+}
+
+function tex.isdimen(name)
+ local hit = cache[name]
+ return hit.command == dimencode and hit.index or true
+end
+
+function tex.iscount(name)
+ local hit = cache[name]
+ return hit.command == countcode and hit.index or true
+end
+
+function tex.istoken(name)
+ local hit = cache[name]
+ return hit.command == tokencode and hit.index or true
+end
+
+function tex.isskip(name)
+ local hit = cache[name]
+ return hit.command == skipcode and hit.index or true
+end
+
+function tex.ismuskip(name)
+ local hit = cache[name]
+ return hit.command == muskipcode and hit.index or true
+end
+
+function tex.type(name)
+ return types[cache[name].command] or "macro"
+end
+
+-- -- old token code
+--
+-- local csname_id = token.csname_id
+-- local create = token.create
+--
+-- local undefined = csname_id("*undefined*crap*")
+-- local iftrue = create("iftrue")[2] -- inefficient hack
+--
+-- setmetatableindex(tex.modes, function(t,k)
+-- local m = modes[k]
+-- if m then
+-- return m()
+-- else
+-- local n = "mode>" .. k
+-- if csname_id(n) == undefined then
+-- return false
+-- else
+-- modes[k] = function() return texgetcount(n) == 1 end
+-- return texgetcount(n) == 1 -- 2 is prevented
+-- end
+-- end
+-- end)
+--
+-- setmetatableindex(tex.systemmodes, function(t,k)
+-- local m = systemmodes[k]
+-- if m then
+-- return m()
+-- else
+-- local n = "mode>*" .. k
+-- if csname_id(n) == undefined then
+-- return false
+-- else
+-- systemmodes[k] = function() return texgetcount(n) == 1 end
+-- return texgetcount(n) == 1 -- 2 is prevented
+-- end
+-- end
+-- end)
+--
+-- setmetatableindex(tex.constants, function(t,k)
+-- return csname_id(k) ~= undefined and texgetcount(k) or 0
+-- end)
+--
+-- setmetatableindex(tex.conditionals, function(t,k) -- 0 == true
+-- return csname_id(k) ~= undefined and texgetcount(k) == 0
+-- end)
+--
+-- setmetatableindex(tex.ifs, function(t,k)
+-- -- k = "if" .. k -- better not
+-- return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper
+-- end)
+--
+-- setmetatableindex(tex.isdefined, function(t,k)
+-- return k and csname_id(k) ~= undefined
+-- end)
+-- setmetatablecall(tex.isdefined, function(t,k)
+-- return k and csname_id(k) ~= undefined
+-- end)
+--
+-- local lookuptoken = token.lookup
+--
+-- local dimencode = lookuptoken("scratchdimen" )[1]
+-- local countcode = lookuptoken("scratchcounter")[1]
+-- local tokencode = lookuptoken("scratchtoken" )[1]
+-- local skipcode = lookuptoken("scratchskip" )[1]
+--
+-- local types = {
+-- [dimencode] = "dimen",
+-- [countcode] = "count",
+-- [tokencode] = "token",
+-- [skipcode ] = "skip",
+-- }
+--
+-- function tex.isdimen(name)
+-- return lookuptoken(name)[1] == dimencode
+-- end
+--
+-- function tex.iscount(name)
+-- return lookuptoken(name)[1] == countcode
+-- end
+--
+-- function tex.istoken(name)
+-- return lookuptoken(name)[1] == tokencode
+-- end
+--
+-- function tex.isskip(name)
+-- return lookuptoken(name)[1] == skipcode
+-- end
+--
+-- function tex.type(name)
+-- return types[lookuptoken(name)[1]] or "macro"
+-- end
+
+function context.setconditional(name,value)
+ if value then
+ context.settruevalue(name)
+ else
+ context.setfalsevalue(name)
+ end
+end
+
+---- arg = P("{") * C(patterns.nested) * P("}") + Cc("")
+
+local sep = S("), ")
+local str = C((1-sep)^1)
+local tag = P("(") * C((1-S(")" ))^1) * P(")")
+local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")")
+
+local pattern = (
+ P("lua") * tag / context.luasetup
+ + P("xml") * arg / context.setupwithargument -- or xmlw as xmlsetup has swapped arguments
+ + (P("tex") * tag + str) / context.texsetup
+ + sep^1
+)^1
+
+interfaces.implement {
+ name = "autosetups",
+ actions = function(str) lpegmatch(pattern,str) end,
+ arguments = "string"
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv
new file mode 100644
index 00000000000..e876dc80d94
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv
@@ -0,0 +1,847 @@
+%D \module
+%D [ file=core-env, % was core-new
+%D version=1995.01.01, % wrong
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=New ones,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Environments}
+
+\registerctxluafile{core-env}{1.001}
+
+\unprotect
+
+%D Modes:
+%D
+%D \starttyping
+%D \enablemode[screen,paper,bound]
+%D
+%D \doifmodeelse {paper} {this} {that}
+%D \doifmode {paper,screen} {this}
+%D \doifnotmode {paper,bound} {that}
+%D
+%D \startmode [list]
+%D \stopmode
+%D
+%D \startnotmode [list]
+%D \stopnotmode
+%D \stoptyping
+%D
+%D system modes have a * as prefix
+%D
+%D Sometimes, we want to prevent a mode for being set. Think
+%D of situations where a style enables a mode, but an outer
+%D level style does not want that. Preventing can be
+%D considered a permanent disabling on forehand.
+
+\def\systemmodeprefix{*}
+
+% we will have \installcorenamespace{mode} but need some hackery at the lua end then
+
+\installcorenamespace{modestack}
+
+\setnewconstant\disabledmode \zerocount
+\setnewconstant\enabledmode \plusone
+\setnewconstant\preventedmode\plustwo
+
+% fast internal ones
+
+\def\??mode{mode>} % special namespace, also used at lua end
+
+\def\syst_modes_new#1%
+ {\expandafter\newcount\csname\??mode#1\endcsname}
+
+\unexpanded\def\newmode#1% so, no change of already set modes !
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi}
+
+\unexpanded\def\setmode#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \lastnamedcs\enabledmode}
+
+\unexpanded\def\resetmode#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \lastnamedcs\disabledmode}
+
+\unexpanded\def\newsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
+
+\unexpanded\def\setsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \lastnamedcs\enabledmode}
+
+\unexpanded\def\resetsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \lastnamedcs\disabledmode}
+
+% \def\dosetsystemmode#1%
+% {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
+%
+% \def\doresetsystemmode#1%
+% {\csname\??mode\systemmodeprefix#1\endcsname\disabledmode}
+
+% demo: trialtypesetting is a systemmode as well as an if
+
+\newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end)
+
+\expandafter\let\expandafter\@@trialtypesetting\csname\??mode\systemmodeprefix trialtypesetting\endcsname % private !
+
+\appendtoks
+ \@@trialtypesetting\enabledmode
+\to \everysettrialtypesetting
+
+\appendtoks
+ \@@trialtypesetting\disabledmode
+\to \everyresettrialtypesetting
+
+% user ones
+
+\let\syst_mode_prefix\relax
+
+\unexpanded\def\preventmode{\unprotect\syst_modes_prevent}
+\unexpanded\def\enablemode {\unprotect\syst_modes_enable }
+\unexpanded\def\disablemode{\unprotect\syst_modes_disable}
+
+\unexpanded\def\globalpreventmode{\let\syst_mode_prefix\global\unprotect\syst_modes_prevent}
+\unexpanded\def\globalenablemode {\let\syst_mode_prefix\global\unprotect\syst_modes_enable }
+\unexpanded\def\globaldisablemode{\let\syst_mode_prefix\global\unprotect\syst_modes_disable}
+
+\def\syst_modes_prevent[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_prevent_indeed\let\syst_mode_prefix\relax}
+\def\syst_modes_enable [#1]{\protect\rawprocesscommacommand[#1]\syst_modes_enable_indeed \let\syst_mode_prefix\relax}
+\def\syst_modes_disable[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_disable_indeed\let\syst_mode_prefix\relax}
+
+\def\syst_modes_prevent_indeed#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \syst_mode_prefix\lastnamedcs\preventedmode}
+
+\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\??mode#1\endcsname=\preventedmode \else
+ \syst_mode_prefix\lastnamedcs\enabledmode
+ \fi}
+
+\def\syst_modes_disable_indeed#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\??mode#1\endcsname=\preventedmode \else
+ \syst_mode_prefix\lastnamedcs\disabledmode
+ \fi}
+
+%D If you do a lot of mode testing, it makes sense to define modes (or disable them
+%D explicitly if unset. This makes testing twice as fast. Often one enables modes
+%D beforehand, in which case \type {\definemode} would reset the mode. The optional
+%D second argument \type {keep} will prevent changing the already set mode but defines
+%D it when undefined.
+
+\unexpanded\def\definemode
+ {\unprotect
+ \dodoubleempty\syst_modes_define}
+
+\def\syst_modes_define[#1][#2]%
+ {\protect
+ \edef\m_modes_asked{#2}%
+ \rawprocesscommacommand[#1]\syst_modes_define_indeed}
+
+\def\syst_modes_define_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ % already set
+ \else
+ \syst_modes_new{#1}
+ \fi
+ \ifx\m_modes_asked\v!keep
+ % not changes, disabled when undefined
+ \else
+ \csname\??mode#1\endcsname\ifx\m_modes_asked\v!yes\enabledmode\else\disabledmode\fi
+ \fi}
+
+% handy for mp
+
+\def\booleanmodevalue#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs
+ \s!false
+ \or
+ \s!true
+ \else
+ \s!false
+ \fi
+ \else
+ \s!false
+ \fi}
+
+% check macros
+
+\newconditional\c_checked_mode
+
+% one
+
+\def\syst_modes_check_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs\else
+ \let\syst_modes_check_step\gobbleoneargument
+ \fi
+ \fi}
+
+\def\syst_modes_check_nop#1#2#3%
+ {\let\syst_modes_check_step\syst_modes_check_indeed
+ \rawprocesscommacommand[#3]\syst_modes_check_step
+ \ifx\syst_modes_check_step\gobbleoneargument
+ \expandafter#1%
+ \else
+ \expandafter#2%
+ \fi}
+
+\def\syst_modes_check_yes#1#2#3%
+ {\ifcase\lastnamedcs
+ \expandafter#2%
+ \or
+ \expandafter#1%
+ \else
+ \expandafter#2%
+ \fi}
+
+\def\syst_modes_check_lr#1#2#3%
+ {\ifcsname\??mode#3\endcsname
+ \expandafter\syst_modes_check_yes
+ \else
+ \expandafter\syst_modes_check_nop
+ \fi#1#2{#3}}
+
+\def\syst_modes_check_ss#1#2[#3]%
+ {\ifcsname\??mode#3\endcsname
+ \expandafter\syst_modes_check_yes
+ \else
+ \expandafter\syst_modes_check_nop
+ \fi#1#2{#3}}
+
+% all
+
+\def\syst_modes_check_all_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \or
+ % enabled
+ \else
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi
+ \else
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi}
+
+\def\syst_modes_check_all_lr#1#2#3%
+ {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+ \rawprocesscommacommand[#3]\syst_modes_check_all_step
+ \ifx\syst_modes_check_all_step\gobbleoneargument
+ \expandafter#2%
+ \else
+ \expandafter#1%
+ \fi}
+
+\def\syst_modes_check_all_ss#1#2[#3]%
+ {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+ \rawprocesscommacommand[#3]\syst_modes_check_all_step
+ \ifx\syst_modes_check_all_step\gobbleoneargument
+ \expandafter#2%
+ \else
+ \expandafter#1%
+ \fi}
+
+\unexpanded\def\doifelsemode {\syst_modes_check_lr\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifmode {\syst_modes_check_lr\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotmode {\syst_modes_check_lr\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startmode {\syst_modes_check_ss\donothing\syst_modes_stop_yes}
+\unexpanded\def\startnotmode {\syst_modes_check_ss\syst_modes_stop_nop\donothing}
+\unexpanded\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallmodes {\syst_modes_check_all_lr\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startallmodes {\syst_modes_check_all_ss\donothing\syst_modes_stop_all_yes}
+\unexpanded\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing}
+
+\let\doifmodeelse \doifelsemode
+\let\doifallmodeselse \doifelseallmodes
+
+\unexpanded\def\stopmode {} % no relax
+\unexpanded\def\stopnotmode {} % no relax
+\unexpanded\def\stopallmodes {} % no relax
+\unexpanded\def\stopnotallmodes {} % no relax
+
+\def\syst_modes_stop_yes #1\stopmode {}
+\def\syst_modes_stop_nop #1\stopnotmode {}
+\def\syst_modes_stop_all_yes#1\stopallmodes {}
+\def\syst_modes_stop_all_nop#1\stopnotallmodes{}
+
+%D Pushing/popping:
+
+% \unexpanded\def\pushmode[#1]%
+% {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+% \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\??mode#1\endcsname}%
+% \expandafter\pushmacro\csname\??modestack#1\endcsname}
+%
+% \unexpanded\def\popmode[#1]%
+% {\ifcsname\??modestack#1\endcsname
+% \expandafter\popmacro\csname\??modestack#1\endcsname
+% \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax
+% \fi}
+%
+% \def\pushsystemmode#1%
+% {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+% \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\??mode\systemmodeprefix#1\endcsname}%
+% \expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname}
+%
+% \def\popsystemmode#1%
+% {\ifcsname\??modestack\systemmodeprefix#1\endcsname
+% \expandafter\popmacro\csname\??modestack\systemmodeprefix#1\endcsname
+% \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
+% \fi}
+
+\unexpanded\def\pushmode[#1]%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \expandafter\edef\csname\??modestack#1\expandafter\endcsname\expandafter{\number\lastnamedcs}%
+ \expandafter\pushmacro\lastnamedcs}
+
+\unexpanded\def\popmode[#1]%
+ {\ifcsname\??modestack#1\endcsname
+ \expandafter\popmacro\lastnamedcs
+ \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax
+ \fi}
+
+\def\pushsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \expandafter\edef\csname\??modestack\systemmodeprefix#1\expandafter\endcsname\expandafter{\number\lastnamedcs}%
+ \expandafter\pushmacro\lastnamedcs}
+
+\def\popsystemmode#1%
+ {\ifcsname\??modestack\systemmodeprefix#1\endcsname
+ \expandafter\popmacro\lastnamedcs
+ \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
+ \fi}
+
+%D Here is a relatively new variant of mode checking:
+%D
+%D \starttyping
+%D \enablemode[two]
+%D
+%D \startmodeset
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodeset
+%D
+%D \startmodeset
+%D [one] {1}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodeset
+%D
+%D \startmodeset
+%D [one] {
+%D \input tufte
+%D }
+%D [two] {
+%D \startmodes
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodes
+%D }
+%D [three] {
+%D \input zapf
+%D }
+%D [default] {
+%D \input ward
+%D }
+%D \stopmodeset
+%D \stoptyping
+
+\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped
+
+\unexpanded\def\startmodeset
+ {\pushmacro\c_syst_modes_set_done
+ \setfalse\c_syst_modes_set_done
+ \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\def\syst_modes_set_start[#1]%
+ {\edef\m_mode_case{#1}%
+ \ifx\m_mode_case\s!default
+ \ifconditional\c_syst_modes_set_done
+ \doubleexpandafter\syst_modes_set_quit
+ \else
+ \doubleexpandafter\syst_modes_set_yes
+ \fi
+ \else
+ \singleexpandafter\syst_modes_set_check
+ \fi}
+
+\def\syst_modes_set_check
+ {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case}
+
+\def\syst_modes_set_yes#1%
+ {\settrue\c_syst_modes_set_done
+ #1%
+ \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\def\syst_modes_set_nop#1%
+ {\doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\def\syst_modes_set_quit#1\stopmodeset
+ {\popmacro\c_syst_modes_set_done}
+
+\let\stopmodeset\relax
+
+%D Lets now set a mode:
+
+\enablemode[mkiv] \newsystemmode{mkiv} \setsystemmode{mkiv}
+
+%D Setups:
+
+\installcorenamespace{setup} % we can probably get rid of some :'s later on
+
+\unexpanded\def\startsetups{} % to please dep checker
+\unexpanded\def\stopsetups {} % to please dep checker
+
+% \expanded % will become obsolete
+% {\def\expandafter\noexpand\csname\e!start\v!setups\endcsname
+% {\begingroup\noexpand\doifnextoptionalcselse
+% {\noexpand\dostartsetupsA\expandafter\noexpand\csname\e!stop\v!setups\endcsname}
+% {\noexpand\dostartsetupsB\expandafter\noexpand\csname\e!stop\v!setups\endcsname}}}
+%
+% \letvalue{\e!stop\v!setups}\relax
+
+\unexpanded\def\setups{\doifelsenextbgroup\syst_setups_a\syst_setups_b} % {..} or [..]
+\unexpanded\def\setup {\doifelsenextbgroup\syst_setups \syst_setups_c} % {..} or [..]
+
+\def\syst_setups_a #1{\processcommacommand[#1]\syst_setups} % {..}
+\def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..]
+\def\syst_setups_c[#1]{\syst_setups{#1}} % [..]
+
+\letvalue{\??setup:\??empty}\gobbleoneargument
+
+\def\syst_setups#1% the grid option will be extended to other main modes
+ {\csname\??setup
+ \ifgridsnapping
+ \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\??empty\fi\fi
+ \else
+ :\ifcsname\??setup:#1\endcsname#1\else\??empty\fi
+ \fi
+ \endcsname\empty} % takes one argument
+
+% no checking and we assume it being defined:
+
+\def\fastsetup #1{\csname\??setup:#1\endcsname\empty}
+\def\fastsetupwithargument #1{\csname\??setup:#1\endcsname} % swapped per 2015-08-30
+\def\fastsetupwithargumentswapped#1#2{\csname\??setup:#2\endcsname{#1}}% swapped per 2015-09-05
+
+% the next one is meant for \c!setups situations, hence the check for
+% a shortcut
+
+\let\m_syst_setups_asked\empty
+
+\def\doprocesslocalsetups#1% sort of public, fast local variant
+ {\edef\m_syst_setups_asked{#1}%
+ \ifx\m_syst_setups_asked\empty\else
+ \expandafter\syst_setups_process_local
+ \fi}
+
+\unexpanded\def\usesetupsparameter#1%
+ {\edef\m_syst_setups_asked{#1\c!setups}%
+ \ifx\m_syst_setups_asked\empty\else
+ \expandafter\syst_setups_process_local
+ \fi}
+
+% \def\syst_setups_process_local
+% {\expandafter\processcommalist\expandafter[\m_syst_setups_asked]\syst_setups}
+
+% setups=S1
+% setups=lua(S2)
+% setups=S3
+% setups={S1,lua(S2),xml(test{123}),S3}
+
+\def\syst_setups_process_local
+ {\clf_autosetups{\m_syst_setups_asked}%
+ \relax} % let's prevent lookahead
+
+\def\autosetups#1%
+ {\clf_autosetups{#1}}
+
+\edef\setupwithargument#1% saves a few expansions
+ {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname}
+
+\edef\setupwithargumentswapped#1#2% saves a few expansions (can be \let)
+ {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#2\endcsname#2\noexpand\else\??empty\noexpand\fi\endcsname{#1}}
+
+\let\directsetup\syst_setups
+\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup
+
+\unexpanded\def\doifelsesetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifsetupselse\doifelsesetups
+
+\unexpanded\def\doifsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+% maybe some day:
+%
+% \unexpanded\def\fastsetupfallback#1#2%
+% {\ifcsname\??setup:#1\endcsname
+% \expandafter\lastnamedcs
+% \else
+% \csname\??setup:#2\expandafter\endcsname
+% \fi}
+%
+% or
+%
+% \unexpanded\def\fastsetupfallback#1#2#3% prefix preferred fallback
+% {\ifcsname\??setup:#1#2\endcsname
+% \expandafter\lastnamedcs
+% \else
+% \csname\??setup:#1#3\expandafter\endcsname
+% \fi}
+
+% \startluasetups oeps
+% context("DONE")
+% a = 1
+% b = 1
+% \stopluasetups
+%
+% \luasetup{oeps}
+%
+% \startsetups xxx
+% ziezo
+% \stopsetups
+%
+% \directsetup{xxx}
+%
+% \startxmlsetups zzz
+% [[#1]]
+% \stopxmlsetups
+%
+% \xmlsetup{123}{zzz}
+%
+% \startbuffer[what]
+% context("DONE")
+% \stopbuffer
+%
+% \startbuffer
+% context("MORE")
+% \stopbuffer
+%
+% \ctxluabuffer[what]
+%
+% \ctxluabuffer
+
+\newtoks\t_syst_setups_tex \appendtoks
+ \catcode\endoflineasciicode \ignorecatcode
+\to \t_syst_setups_tex
+
+\newtoks\t_syst_setups_loc \appendtoks
+ \catcode\endoflineasciicode \ignorecatcode
+\to \t_syst_setups_loc
+
+\newtoks\t_syst_setups_raw \appendtoks
+ % nothing
+\to \t_syst_setups_raw
+
+\newtoks\t_syst_setups_xml \appendtoks
+ \catcode\endoflineasciicode\ignorecatcode
+ \catcode\barasciicode \othercatcode
+\to \t_syst_setups_xml
+
+\newtoks\t_syst_setups_lua \appendtoks
+ \obeylualines
+ \obeyluatokens
+\to \t_syst_setups_lua
+
+% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete.
+
+\unexpanded\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_a\syst_setups_start_lua_b} \let\stopluasetups \relax
+\unexpanded\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_a\syst_setups_start_xml_b} \let\stopxmlsetups \relax
+\unexpanded\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_a\syst_setups_start_raw_b} \let\stoprawsetups \relax
+\unexpanded\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_a\syst_setups_start_loc_b} \let\stoplocalsetups \relax
+\unexpanded\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_a\syst_setups_start_tex_b} \let\stopsetups \relax
+
+\def\syst_setups_start_lua_indeed#1#2#3\stopluasetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+\def\syst_setups_start_xml_indeed#1#2#3\stopxmlsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+\def\syst_setups_start_raw_indeed#1#2#3\stoprawsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+\def\syst_setups_start_loc_indeed#1#2#3\stoplocalsetups{\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+\def\syst_setups_start_tex_indeed#1#2#3\stopsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+
+\def\syst_setups_start_lua{\ifsecondargument\expandafter\syst_setups_start_lua_c\else\expandafter\syst_setups_start_lua_d\fi}
+\def\syst_setups_start_xml{\ifsecondargument\expandafter\syst_setups_start_xml_c\else\expandafter\syst_setups_start_xml_d\fi}
+\def\syst_setups_start_raw{\ifsecondargument\expandafter\syst_setups_start_raw_c\else\expandafter\syst_setups_start_raw_d\fi}
+\def\syst_setups_start_loc{\ifsecondargument\expandafter\syst_setups_start_loc_c\else\expandafter\syst_setups_start_loc_d\fi}
+\def\syst_setups_start_tex{\ifsecondargument\expandafter\syst_setups_start_tex_c\else\expandafter\syst_setups_start_tex_d\fi}
+
+\def\syst_setups_start_lua_a{\the\t_syst_setups_lua\dodoubleempty\syst_setups_start_lua} % [ ] delimited
+\def\syst_setups_start_xml_a{\the\t_syst_setups_xml\dodoubleempty\syst_setups_start_xml} % [ ] delimited
+\def\syst_setups_start_raw_a{\the\t_syst_setups_raw\dodoubleempty\syst_setups_start_raw} % [ ] delimited
+\def\syst_setups_start_loc_a{\the\t_syst_setups_loc\dodoubleempty\syst_setups_start_loc} % [ ] delimited
+\def\syst_setups_start_tex_a{\the\t_syst_setups_tex\dodoubleempty\syst_setups_start_tex} % [ ] delimited
+
+% empty preserves inner {} (is removed by the \expandafter{#3})
+
+\def\syst_setups_start_lua_b#1 {\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % space delimited
+\def\syst_setups_start_xml_b#1 {\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % space delimited
+\def\syst_setups_start_raw_b#1 {\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % space delimited
+\def\syst_setups_start_loc_b#1 {\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % space delimited
+\def\syst_setups_start_tex_b#1 {\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % space delimited
+
+\def\syst_setups_start_lua_c[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed{#1}{#2}\empty} % [..] [..]
+\def\syst_setups_start_xml_c[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed{#1}{#2}\empty} % [..] [..]
+\def\syst_setups_start_raw_c[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed{#1}{#2}\empty} % [..] [..]
+\def\syst_setups_start_loc_c[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed{#1}{#2}\empty} % [..] [..]
+\def\syst_setups_start_tex_c[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed{#1}{#2}\empty} % [..] [..]
+
+\def\syst_setups_start_lua_d[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % [..]
+\def\syst_setups_start_xml_d[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % [..]
+\def\syst_setups_start_raw_d[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % [..]
+\def\syst_setups_start_loc_d[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % [..]
+\def\syst_setups_start_tex_d[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % [..]
+
+\def\luasetup#1{\ctxlua{\syst_setups{#1}}}
+
+% % % %
+
+\def\systemsetupsprefix{*}
+
+\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}}
+
+\unexpanded\def\resetsetups[#1]% see x-fo for usage
+ {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname
+ \dodoglobal\undefinevalue{\??setup\ifgridsnapping\v!grid\fi:#1}%
+ \else
+ \dodoglobal\undefinevalue{\??setup:#1}%
+ \fi}
+
+\unexpanded\def\showsetupsdefinition[#1]%
+ {\showvalue{\??setup:#1}} % temp hack for debugging
+
+%D \macros
+%D {setvariables,getvariable,getvariabledefault}
+%D
+%D \starttyping
+%D \setvariables[xx][title=]
+%D \setvariables[xx][title=test test]
+%D \setvariables[xx][title=test $x=1$ test] % fatal error reported
+%D \setvariables[xx][title=test {$x=1$} test]
+%D \setvariables[xx][title] % fatal error reported
+%D \setvariables[xx][titletitel=e]
+%D \stoptyping
+
+\installcorenamespace{variables}
+
+\unexpanded\def\setvariables {\dotripleargument\syst_variables_set[\getrawparameters ]}
+\unexpanded\def\setevariables{\dotripleargument\syst_variables_set[\getraweparameters]}
+\unexpanded\def\setgvariables{\dotripleargument\syst_variables_set[\getrawgparameters]}
+\unexpanded\def\setxvariables{\dotripleargument\syst_variables_set[\getrawxparameters]}
+
+\unexpanded\def\globalsetvariables % obsolete
+ {\dotripleargument\syst_variables_set[\globalgetrawparameters]}
+
+\def\syst_variables_set[#1][#2][#3]% tricky, test on s-pre-60
+ {\errorisfataltrue
+ \doifelse{#2}\currentvariableclass
+ {#1[\??variables#2:][#3]}%
+ {\pushmacro\currentvariableclass
+ \def\currentvariableclass{#2}%
+ \getvariable{#2}\s!reset
+ #1[\??variables#2:][#3]%
+ \getvariable{#2}\s!set
+ \popmacro\currentvariableclass}%
+ \errorisfatalfalse}
+
+\unexpanded\def\setvariable #1#2#3{\expandafter\def \csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setevariable#1#2#3{\expandafter\edef\csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setgvariable#1#2#3{\expandafter\gdef\csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setxvariable#1#2#3{\expandafter\xdef\csname\??variables#1:#2\endcsname{#3}}
+
+% \def\getvariable#1#2%
+% {\csname
+% \ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi
+% \endcsname}
+
+\def\getvariable#1#2%
+ {\begincsname\??variables#1:#2\endcsname}
+
+\def\showvariable#1#2%
+ {\showvalue{\begincsname\??variables#1:#2\endcsname}}
+
+\let\currentvariableclass\empty
+
+%D \macros
+%D {checkvariables}
+%D
+%D I'll probably forget that this on exists.
+
+\let\m_syst_variables_temp\empty
+
+\def\checkvariables
+ {\dodoubleargument\syst_variables_check}
+
+\def\syst_variables_check
+ {\dogetparameters\syst_variables_check_value}
+
+\def\syst_variables_check_value#1#2#3%
+ {\ifcsname\??variables#1:#2\endcsname
+ %\edef\m_syst_variables_temp{\csname\??variables#1:#2\endcsname}%
+ \edef\m_syst_variables_temp{\lastnamedcs}%
+ \ifx\m_syst_variables_temp\empty
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
+ \fi
+ \else
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
+ \fi}
+
+%D \macros
+%D {doifelsevariable,doifvariable,doifnotvariable}
+%D
+%D A few trivial macros:
+
+\unexpanded\def\doifelsevariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifvariableelse\doifelsevariable
+
+\unexpanded\def\doifvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D A few more (we could use a public test variable so that we only need
+%D to expand once, assuming expandable variables):
+
+\letvalue{\??variables:}\empty
+
+\unexpanded\def\doifelseemptyvariable#1#2%
+ %{\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
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifemptyvariableelse\doifelseemptyvariable
+
+\unexpanded\def\doifemptyvariable#1#2%
+ %{\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\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotemptyvariable#1#2%
+ %{\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\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\getvariabledefault#1#2% #3% can be command
+ %{\executeifdefined{\??variables#1:#2}}% {#3}
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\setupenv
+ {\dotripleargument\syst_variables_set[\getrawparameters][\s!environment]}
+
+\unexpanded\def\doifelseenv{\doifelsevariable \s!environment}
+\unexpanded\def\doifenv {\doifvariable \s!environment}
+\unexpanded\def\doifnotenv {\doifnotvariable \s!environment}
+\def\env {\getvariable \s!environment}
+\def\envvar {\getvariabledefault\s!environment}
+
+\let\doifenvelse\doifelseenv
+
+%D \macros
+%D {defineselector,setupselector,select,directselect}
+%D
+%D \starttyping
+%D \defineselector[caption][max=2,n=2]
+%D
+%D \start
+%D \setupselector[caption][n=1]
+%D \placelist[figure][criterium=all]
+%D \stop
+%D
+%D \starttext
+%D \placefigure
+%D {\select{caption}{zapf}{\input zapf \relax}}
+%D {}
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{selector}
+
+\unexpanded\def\defineselector{\dodoubleargument\syst_selectors_define}
+\unexpanded\def\setupselector {\dodoubleargument\syst_selectors_setup}
+
+% \def\syst_selectors_define[#1][#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]}
+% \def\syst_selectors_setup [#1][#2]{\getparameters[\??selector#1][#2]}
+
+\def\syst_selectors_define[#1][{\getparameters[\??selector#1][\c!max=\plustwo,\c!n=\plusone,}
+\def\syst_selectors_setup [#1][{\getparameters[\??selector#1][}
+
+\unexpanded\def\select % unexpandable
+ {\directselect}
+
+% \def\directselect#1% expandable
+% {\filterfromnext % maybe add an \expanded
+% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}%
+% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}}
+%
+% this is more efficient when the arguments are used a few times (or passed along):
+
+\def\directselect#1% expandable
+ {\expandafter\filterfromnext
+ \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname
+ \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}
+
+\letvalue{\??selector\c!max}\plusone
+\letvalue{\??selector\c!n }\plusone
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-ini.mkiv
new file mode 100644
index 00000000000..0407409a39d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-ini.mkiv
@@ -0,0 +1,221 @@
+%D \module
+%D [ file=core-ini,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Additional 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 Core Macros / Additional Initialization}
+
+\unprotect
+
+%D We introduce a couple of variables that are used all over \CONTEXT. Alternatively
+%D we could define them in each module but as they are part of the bigger picture we
+%D prefer to do it here. Ideally we should hav ea proper dependency tree but it might
+%D be that we want to make versions with a smaller footprints in which case one would
+%D still need to define the token list registers (unless we could do that runtime).
+
+%D \macros
+%D {every...}
+%D
+%D A few every's.
+
+%D Output routine:
+
+\newtoks \everybeforeoutput
+\newtoks \everyafteroutput
+
+%D Shipout:
+
+\newtoks \everyshipout
+\newtoks \everybeforeshipout
+\newtoks \everyaftershipout
+\newtoks \everyfirstshipout
+\newtoks \everylastshipout
+
+%D End of run:
+
+\newtoks \everybye
+\newtoks \everygoodbye
+\newtoks \everynotabene
+
+%D Document:
+
+\newtoks \everysetupdocument
+\newtoks \everyendoftextbody
+
+\newtoks \everystarttext
+\newtoks \everystoptext
+
+%D Purity:
+
+\newtoks \everyforgetall
+\newtoks \everycleanupfeatures
+\newtoks \everysimplifycommands
+\newtoks \everypreroll
+
+\let\simplifiedcommands\everysimplifycommands % backward compatible, will stay as it's used in styles
+
+\newconditional\simplifyingcommands % public
+
+\unexpanded\def\forgetall {\the\everyforgetall}
+\unexpanded\def\cleanupfeatures {\the\everycleanupfeatures}
+\unexpanded\def\simplifycommands{\the\everysimplifycommands}
+
+\appendtoks
+ \settrue\simplifyingcommands
+\to \everysimplifycommands
+
+\appendtoks
+ \everypar\emptytoks % pretty important
+\to \everyforgetall
+
+%D Page building:
+
+\newtoks \everybeforepagebody
+\newtoks \everyafterpagebody
+
+\let\everypagebody\everybeforepagebody % backward compatible, will become obsolete
+
+%D Floats:
+
+\newtoks \everyinsidefloat
+
+%D Sectioning:
+
+%newtoks \everyheadstart
+
+%D Par building (experimental, used in xml <p> .. </p>)
+
+\newtoks \everybeginofpar
+\newtoks \everyendofpar
+%newtoks \everyparflush
+
+\unexpanded\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar
+\unexpanded\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar
+
+%D Lists:
+
+\newtoks \everylistentry
+\newtoks \everysavesortkeys
+
+%D Marks:
+
+%newtoks \everymarking
+
+%D Fonts:
+
+\newtoks \everyfont
+\newtoks \everyglobalbodyfont
+\newtoks \everydefinedfont
+
+\newtoks \everybodyfont
+\newtoks \everyfontswitch
+
+\newtoks \everysetupbodyfont
+\newtoks \everyswitchtobodyfont
+
+%D Math:
+
+\newtoks \everybeforedisplayformula
+\newtoks \everymathematics
+
+\prependtoks \the\everymathematics \to \everymath
+\prependtoks \the\everymathematics \to \everydisplay
+
+%D Tables:
+
+%newtoks \everytable % we need to disstinguish kinds
+
+%D State mess:
+
+\newtoks \everypushsomestate
+\newtoks \everypopsomestate
+
+\unexpanded\def\pushsomestates{\the\everypushsomestate}
+\unexpanded\def\popsomestates {\the\everypopsomestate }
+
+%D More generic (used to be pushcolor etc)
+
+\newtoks\everystarttextproperties
+\newtoks\everystoptextproperties
+
+\unexpanded\def\starttextproperties{\the\everystarttextproperties}
+\unexpanded\def\stoptextproperties {\the\everystoptextproperties}
+
+%D \macros
+%D {trialtypesetting}
+%D
+%D We disable trial typesetting in the output routine,
+%D just to be sure.
+
+\prependtoks
+ \resettrialtypesetting
+\to \everybeforepagebody
+
+%D \macros
+%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided}
+%D
+%D These will become system modes and conditionals
+
+\newif \ifinpagebody
+\newif \ifinsidecolumns
+\newif \ifdoublesided \doublesidedfalse
+\newif \ifsinglesided \singlesidedtrue
+\newif \ifinsidefloat
+\newif \ifdoingblocks
+\newif \ifgridsnapping
+
+\newconstant\pageduplexmode % 0 single 1 double 2 mix
+\newconstant\pagebodymode % 0 not 1 normal pagebody 2 spread
+
+%D \macros
+%D {ifproductionrun}
+%D
+%D This boolean can be used to bypass certain initializations.
+
+\newif\ifproductionrun
+
+\appendtoks
+ \productionruntrue
+\to \everydump
+
+%D \macros
+%D {everyboxedcontent, ifboxedcontent,
+%D startboxedcontent, stopboxedcontent}
+%D
+%D This one is relatively new and will be used as a more robust test for inner
+%D situations.
+
+\newif \ifboxedcontent
+\newtoks\everyboxedcontent
+
+\appendtoks
+ \boxedcontenttrue
+\to \everyboxedcontent
+
+\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent}
+
+\let\stopboxedcontent\egroup
+
+%D We store some original meanings, maybe in \type {math-ini}.
+
+\let\normalat \at
+\let\normalin \in
+\let\normalfrom \from
+%let\normalover \over
+\let\normalabout\about
+
+%D This will be implemented way later:
+
+\let\setlayoutcomponentattribute \gobbleoneargument
+\let\resetlayoutcomponentattribute\relax
+\let\layoutcomponentboxattribute \empty
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua b/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua
new file mode 100644
index 00000000000..3e39fa9da92
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua
@@ -0,0 +1,90 @@
+if not modules then modules = { } end modules ['core-sys'] = {
+ version = 1.001,
+ comment = "companion to core-sys.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lower, format, gsub = string.lower, string.format, string.gsub
+local suffixonly, basename, removesuffix = file.suffix, file.basename, file.removesuffix
+
+local environment = environment
+local context = context
+local implement = interfaces.implement
+
+local report_files = logs.reporter("system","files")
+
+function environment.initializefilenames()
+
+ local arguments = environment.arguments
+
+ local jobname = arguments.jobname or tex.jobname
+ local fulljobname = arguments.fulljobname or jobname
+ local inputfilename = arguments.input or fulljobname
+ local outputfilename = arguments.result or removesuffix(jobname)
+
+ local inputfilename = suffixonly(inputfilename) == "tex" and removesuffix(inputfilename) or inputfilename or ""
+
+ local filename = fulljobname
+ local suffix = suffixonly(filename)
+
+ local filename = ctxrunner.resolve(filename) -- in case we're prepped
+
+ local jobfilename = jobname or inputfilename or tex.jobname or ""
+ local inputfilename = inputfilename or ""
+
+ local jobfilebase = basename(jobfilename)
+ local inputfilebase = basename(inputfilename)
+
+ -- jobfilename = gsub(jobfilename, "^./","")
+ -- inputfilename = gsub(inputfilename,"^./","")
+
+ environment.jobfilename = jobfilebase
+ environment.jobfilesuffix = lower(suffixonly(jobfilebase))
+
+ environment.inputfilename = inputfilename -- so here we keep e.g. ./ or explicit paths
+ environment.inputfilebarename = removesuffix(inputfilebase)
+ environment.inputfilesuffix = lower(suffixonly(inputfilebase))
+
+ environment.outputfilename = outputfilename or environment.inputfilebarename or ""
+
+ environment.filename = filename
+ environment.suffix = suffix
+
+ report_files("jobname %a, input %a, result %a",jobfilename,inputfilename,outputfilename)
+
+ function environment.initializefilenames() end
+end
+
+-- we could set a macro (but will that work when we're expanding? needs testing!)
+
+implement { name = "operatingsystem", actions = function() context(os.platform) end }
+implement { name = "jobfilename", actions = function() context(environment.jobfilename) end }
+implement { name = "jobfilesuffix", actions = function() context(environment.jobfilesuffix) end }
+implement { name = "inputfilebarename", actions = function() context(environment.inputfilebarename) end }
+implement { name = "inputfilerealsuffix", actions = function() context(environment.inputfilerealsuffix) end }
+implement { name = "inputfilesuffix", actions = function() context(environment.inputfilesuffix) end }
+implement { name = "inputfilename", actions = function() context(environment.inputfilename) end }
+implement { name = "outputfilename", actions = function() context(environment.outputfilename) end }
+
+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
+ return format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf",
+ pdf.getcompresslevel(),
+ pdf.getobjcompresslevel()
+ )
+ else
+ return format("%s.%s",outputfilename,"dvi") -- hard to imagine
+ end
+end)
+
+implement {
+ name = "systemlog",
+ arguments = { "string", "string", "string" },
+ actions = function(whereto,category,text)
+ logs.system(whereto,"context",tex.jobname,category,text)
+ end,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-sys.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-sys.mkiv
new file mode 100644
index 00000000000..cc9dafdd2f8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-sys.mkiv
@@ -0,0 +1,459 @@
+%D \module
+%D [ file=core-sys, % moved from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% we need to mkiv-ize this file !
+
+\writestatus{loading}{ConTeXt Core Macros / System}
+
+\registerctxluafile{core-sys}{1.001}
+
+\unprotect
+
+%D Version checking:
+
+\unexpanded\def\newcontextversion#1%
+ {\doifelse{#1}\contextversion
+ {\let\newcontextversion\gobbleoneargument}
+ {\writeline
+ \writestatus{Fatal Error}{Your format does not match the base files!}%
+ \writeline
+ \writestatus{Format Version}{\contextversion\space\contextmark}%
+ \writestatus{Files Version}{#1}%
+ \batchmode
+ \normalend}}
+
+%D End of lines to the output. \TEX\ will map this onto the platform specific
+%D line ending. I hate this mess.
+
+\let\operatingsystem\clf_operatingsystem
+
+%D The jobname is what gets loaded by the cont-yes stub file. This name
+%D also determines the name of tuc etc files.
+
+\let\jobfilename \clf_jobfilename
+\let\jobfilesuffix\clf_jobfilesuffix
+
+%D However, that one can itself load another file.
+
+\let\inputfilebarename \clf_inputfilebarename
+\let\inputfilerealsuffix\clf_inputfilerealsuffix
+\let\inputfilesuffix \clf_inputfilesuffix
+\let\inputfilename \clf_inputfilename
+
+%D The output name is only used for some checking.
+
+\let\outputfilename\clf_outputfilename
+
+\installcorenamespace{system}
+
+\installdirectcommandhandler \??system {system}
+
+\appendtoks
+% \edef\outputfilename {\directsystemparameter\c!file }%
+% \edef\inputfilename {\directsystemparameter\c!inputfile }%
+\to \everysetupsystem
+
+\appendtoks
+ \ifcase\directsystemparameter\c!n\relax
+ % % 0 : unknown
+ \or
+ \setsystemmode\v!first % 1 : first run
+ \or
+ % % 2 : successive run
+ \or
+ \setsystemmode\v!first % 3 : first and only run
+ \or
+ \setsystemmode\v!last % 4 : (extra) last run
+ \fi
+\to \everysetupsystem
+
+\let\m_system_job_suffix\s!unknown
+
+\appendtoks
+ \resetsystemmode{suffix-\m_system_job_suffix}%
+ \edef\m_system_job_suffix{\jobsuffix}%
+ \setsystemmode{suffix-\m_system_job_suffix}%
+\to \everysetupsystem
+
+% \appendtoks
+% \ctxcommand{updatefilenames("\jobame","\inputfilename","\outputfilename")}%
+% \to \everysetupsystem
+
+\newconditional\prerollrun % when true it means that we have a forced number of runs
+
+% Some mechanisms (see x-res-01) use either \jobfilename or
+% \jobfilename.somesuffix, in which case we need to use the
+% full name if given or a default (like \jobfilename.xml);
+% this comes down to replacing the default tex suffix.
+
+\def\jobfullname{\jobfilename.\jobfilesuffix}
+
+\unexpanded\def\setjobfullname#1% #1 = default if not given
+ {\doifelsenothing\jobfilename
+ {\let\jobfullname\empty}
+ {\doif\jobfilesuffix\c!tex{\edef\jobfullname{\jobfilename.#1}}}}
+
+%D There are a couple of system states avaiable:
+%D
+%D \starttabulate [|T|T|]
+%D \NC \type{\jobname} \NC \jobname \NC \NR
+%D \NC \type{\jobfilename} \NC \jobfilename \NC \NR
+%D \NC \type{\jobfilesuffix} \NC \jobfilesuffix \NC \NR
+%D \NC \type{\inputfilename} \NC \inputfilename \NC \NR
+%D \NC \type{\inputfilebarename} \NC \inputfilebarename \NC \NR
+%D \NC \type{\inputfilesuffix} \NC \inputfilesuffix \NC \NR
+%D \NC \type{\outputfilename} \NC \outputfilename \NC \NR
+%D \NC \type{\operatingsystem} \NC \operatingsystem \NC \NR
+%D \stoptabulate
+
+\appendtoks
+ \edef\outputresolution{\directsystemparameter\c!resolution}%
+\to \everysetupsystem
+
+%D The system modes set by the setup command can be used in
+%D situations like:
+%D
+%D \starttyping
+%D \startmode[*first]
+%D \executesystemcommand{cleanupxml text.xml clean-text.xml}
+%D \stopmode
+%D
+%D \starttext
+%D \typefile{clean-text.xml}
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\setuprandomize[#1]%
+ {\doifsomething{#1}
+ {\begingroup
+ % tex's time is in minutes
+ \scratchcounter\normaltime
+ \processaction
+ [#1]
+ [ \v!small=>\divide\scratchcounter 15, % 900,
+ \v!medium=>\divide\scratchcounter 30, % 1800,
+ \v!big=>\divide\scratchcounter 60, % 3600,
+ \v!normal=>\getnewrandomseed\scratchcounter,
+ \s!default=>\getnewrandomseed\scratchcounter,
+ \s!unknown=>\scratchcounter#1]%
+ \expanded{\setrandomseed{\the\scratchcounter}}%
+ % \writestatus\m!system{randomseed: \the\scratchcounter}%
+ \endgroup}}
+
+\setupsystem
+ [\c!directory=,
+ \c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run
+ \c!resolution=600,% in dpi, no unit in mkiv
+ % \c!random=, % obsolete here
+ % \c!file=\jobname,
+ % \c!inputfile=\outputfilename,
+ \c!type=unix, % windows is normally less sensitive to handle
+ \c!bodyfont=\normalizedlocalbodyfontsize] % of iets anders
+
+%D Remark: windows programs normally handle \type {cr|lf|crlf} but unix
+%D is more picky, so we default to the \type {cr}. I never understood why
+%D \type {crlf} was not used in all systems, since it makes most sense.
+%D But anyway, in \MKIV\ we avoid most of the complications anyway as we
+%D deal with much at the \LUA\ end.
+
+\unexpanded\def\start
+ {\dosingleempty\syst_start}
+
+\def\syst_start
+ {\bgroup
+ \iffirstargument
+ \expandafter\syst_start_yes
+ \else
+ \expandafter\syst_start_nop
+ \fi}
+
+\def\syst_start_yes[#1]%
+ {\edef\m_syst_start_stop{#1}%
+ \ifx\m_syst_start_stop\empty
+ \let\syst_stop_indeed\donothing
+ \else\ifcsname\e!start\m_syst_start_stop\endcsname
+ \expandafter\let\expandafter\syst_stop_indeed\csname\e!stop\m_syst_start_stop\endcsname
+ \csname\e!start\m_syst_start_stop\expandafter\expandafter\expandafter\endcsname
+ \else
+ \let\syst_stop_indeed\donothing
+ \fi\fi}
+
+\def\syst_start_nop[#1]%
+ {\let\syst_stop_indeed\donothing}
+
+\unexpanded\def\stop
+ {\syst_stop_indeed
+ \egroup}
+
+% \c!before \c!after \c!inbetween \c!commands \c!style \c!color
+
+\installcorenamespace{startstop}
+
+\installcommandhandler \??startstop {startstop} \??startstop
+
+\appendtoks
+ \setuevalue{\e!start\currentstartstop}{\syst_startstop_start {\currentstartstop}}%
+ \setuevalue{\e!stop \currentstartstop}{\syst_startstop_stop {\currentstartstop}}%
+ \setuevalue {\currentstartstop}{\syst_startstop_indeed{\currentstartstop}}%
+\to \everydefinestartstop
+
+\unexpanded\def\syst_startstop_start#1%
+ {\namedstartstopparameter{#1}\c!before\relax
+ \bgroup
+ \def\currentstartstop{#1}%
+ % we will keep this for a while:
+ \startstopparameter\c!commands\relax % obsolete
+ % this is the new method:
+ \usesetupsparameter\startstopparameter\relax % only in the display version
+ \dostarttagged\t!construct\currentstartstop
+ \usestartstopstyleandcolor\c!style\c!color}
+
+\unexpanded\def\syst_startstop_stop#1%
+ {\dostoptagged
+ \egroup
+ \namedstartstopparameter{#1}\c!after\relax}
+
+\unexpanded\def\syst_startstop_indeed#1%
+ {\groupedcommand
+ {\def\currentstartstop{#1}%
+ \startstopparameter\c!commands\relax % better: setups so that will show op soon
+ \dostarttagged\t!construct\currentstartstop
+ \usestartstopstyleandcolor\c!style\c!color
+ \startstopparameter\c!left\relax}
+ {\def\currentstartstop{#1}% safeguard, nto really needed
+ \startstopparameter\c!right\relax
+ \dostoptagged
+ \startstopparameter\c!inbetween\relax}}
+
+% \definestartstop[tracing][\c!style=\tt]
+
+% \unexpanded\def\ignorestartstop[#1]%
+% {\unexpanded\expandafter\def\csname\e!start#1\expandafter\endcsname\expandafter
+% {\expandafter\gobbleuntil\csname\e!stop#1\endcsname}}
+%
+% \ignorestartstop[bagger]
+
+\installcorenamespace{highlight}
+
+\installcommandhandler \??highlight {highlight} \??highlight % we could do with less
+
+\setuphighlight
+ [\c!command=\v!yes]
+
+\appendtoks
+ \edef\p_command{\highlightparameter\c!command}%
+ \ifx\p_command\v!yes
+ \setuevalue\currenthighlight{\typo_highlights_indeed{\currenthighlight}}%
+ \fi
+\to \everydefinehighlight
+
+\ifdefined\dotaghighlight \else \let\dotaghighlight\relax \fi
+
+\unexpanded\def\typo_highlights_indeed#1% inline style/color switch
+ {\dontleavehmode\groupedcommand % otherwise wrong par number in tags
+ {\def\currenthighlight{#1}%
+ \dostarttagged\t!highlight\currenthighlight
+ \usehighlightstyleandcolor\c!style\c!color
+ \dotaghighlight}
+ {\dostoptagged}}
+
+\unexpanded\def\highlight[#1]%
+ {\typo_highlights_indeed{#1}}
+
+\unexpanded\def\starthighlight[#1]%
+ {\begingroup
+ \def\currenthighlight{#1}%
+ \dostarttagged\t!highlight\currenthighlight
+ \usehighlightstyleandcolor\c!style\c!color
+ \dotaghighlight}
+
+\unexpanded\def\stophighlight
+ {\dostoptagged
+ \endgroup}
+
+\let\directhighlight\typo_highlights_indeed
+
+\unexpanded\def\defineexpandable
+ {\doifelsenextoptional
+ {\syst_basics_define_yes\def}%
+ {\syst_basics_define_nop\def}}
+
+\unexpanded\def\define
+ {\doifelsenextoptional
+ {\syst_basics_define_yes{\unexpanded\def}}%
+ {\syst_basics_define_nop{\unexpanded\def}}}
+
+\unexpanded\def\syst_basics_define_yes#1[#2]#3#4%
+ {\ifdefined#3%
+ \showmessage\m!system4{\string#3}%
+ \fi
+ \ifcase0#2\relax
+ #1#3{#4}\or
+ #1#3##1{#4}\or
+ #1#3##1##2{#4}\or
+ #1#3##1##2##3{#4}\or
+ #1#3##1##2##3##4{#4}\or
+ #1#3##1##2##3##4##5{#4}\or
+ #1#3##1##2##3##4##5##6{#4}\or
+ #1#3##1##2##3##4##5##6##7{#4}\or
+ #1#3##1##2##3##4##5##6##7##8{#4}\or
+ #1#3##1##2##3##4##5##6##7##8##9{#4}\else
+ #1#3{#4}\fi}
+
+\unexpanded\def\syst_basics_define_nop#1#2#3%
+ {\ifdefined#2%
+ \showmessage\m!system4{\string#2}%
+ \fi
+ #1#2{#3}}
+
+% new:
+%
+% \checked\def \whatever#alpha#beta{#alpha + #beta}
+% \checked\edef\whatever#alpha#beta{#alpha + #beta}
+
+\unexpanded\def\unique#1#2%
+ {\ifdefined#2%
+ \showmessage\m!system4{\string#2}%
+ \expandafter#1\expandafter\gobbleddefinition
+ \else
+ \expandafter#1%
+ \fi#2}
+
+\unexpanded\def\checked#1#2%
+ {\ifdefined#2%
+ \showmessage\m!system4{\string#2}%
+ \fi
+ #1#2}
+
+% \startluacode
+% local formatters = string.formatters
+% local contextsprint, ctxcatcodes, prtcatcodes = context.sprint, tex.ctxcatcodes, tex.prtcatcodes
+% local match, gmatch, rep = string.match, string.gmatch, string.rep
+% local empty = {
+% "single",
+% "double",
+% "triple",
+% "quadruple",
+% "quintuple",
+% }
+% local check = {
+% "first",
+% "second",
+% "third",
+% "fourth",
+% "fifth",
+% }
+% function commands.define(str)
+% -- we could store the defaults in lua and call lua instead but why bother
+% local arg, cmd = match(str,"(.*)\\(.-)$")
+% local a = { }
+% for s in gmatch(arg,"%[(.-)%]") do
+% a[#a+1] = s
+% end
+% local n = tonumber(a[#a])
+% if n then
+% a[#a] = nil
+% else
+% n = 0
+% end
+% contextsprint(ctxcatcodes,formatters["\\unexpanded\\def\\%s"](cmd))
+% if #a > 0 then
+% contextsprint(prtcatcodes,formatters["{\\do%sempty\\user_defined_%s}"](empty[#a],cmd))
+% contextsprint(prtcatcodes,formatters["\\def\\user_defined_%s"](cmd))
+% for i=1,#a do
+% contextsprint(ctxcatcodes,formatters["[#%s]"](i))
+% end
+% contextsprint(ctxcatcodes,"{")
+% for i=#a,1,-1 do
+% contextsprint(ctxcatcodes,formatters["\\if%sargument"](check[i]))
+% contextsprint(prtcatcodes,formatters["\\def\\next{\\user_defined_indeed_%s"](cmd))
+% for j=1,#a-i do
+% contextsprint(ctxcatcodes,formatters["[%s]"](a[j]))
+% end
+% for j=1,i do
+% contextsprint(ctxcatcodes,formatters["[#%s]"](j))
+% end
+% contextsprint(ctxcatcodes,"}")
+% if i == 1 then
+% contextsprint(ctxcatcodes,rep("\\fi",#a))
+% else
+% contextsprint(ctxcatcodes,"\\else")
+% end
+% end
+% contextsprint(ctxcatcodes,"\\next}")
+% contextsprint(prtcatcodes,formatters["\\def\\user_defined_indeed_%s"](cmd))
+% for i=1,#a do
+% contextsprint(ctxcatcodes,formatters["[#%s]"](i))
+% end
+% end
+% for i=1,n do
+% contextsprint(ctxcatcodes,formatters["#%s"](#a+i))
+% end
+% end
+% \stopluacode
+%
+% \unexpanded\def\define#1#{\ctxcommand{define([[\detokenize{#1}]])}}
+%
+% \starttext
+% \define[2]\whatevera{#1+#2}
+% \whatevera{A}{B}
+% \define[me][too][2]\whateverb{#1+#2+#3+#4}
+% \whateverb[A]{B}{C}
+% \whateverb[A][B]{C}{D}
+% \define[alpha][beta][gamma][delta]\whateverc{#1+#2+#3+#4}
+% \whateverc[P][Q]
+% \stoptext
+
+%D This is a checked variant of \type {\getvalue}.
+
+\unexpanded\def\macroname#1% brrr
+% {\csname\ifcsname#1\endcsname#1\else\s!empty\fi\endcsname}
+ {\begincsname#1\endcsname}
+
+% %D A weird one that I probably needed once, so it might as well become
+% %D obsolete.
+%
+% \unexpanded\def\usecommands#1%
+% {\begingroup
+% \def\docommand##1{\setbox\scratchbox\hbox{\csname\string##1\endcsname##1}}%
+% \processcommalist[#1]\docommand
+% \endgroup}
+
+\unexpanded\def\syst_log_indeed#1#2#3%
+ {\ctxcommand{systemlog("#1","#2",\!!bs#3\!!es)}}
+
+\let\systemlog\syst_log_indeed
+
+\unexpanded\def\systemlogfirst
+ {\ifcase\directsystemparameter\c!n\relax
+ \expandafter\syst_log_indeed
+ \or
+ \expandafter\syst_log_indeed
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+\unexpanded\def\systemloglast
+ {\ifcase\directsystemparameter\c!n\relax
+ \expandafter\syst_log_indeed
+ \or
+ \expandafter\gobblethreearguments
+ \or
+ \expandafter\gobblethreearguments
+ \or
+ \expandafter\gobblethreearguments
+ \or
+ \expandafter\syst_log_indeed
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-two.lua b/Master/texmf-dist/tex/context/base/mkiv/core-two.lua
new file mode 100644
index 00000000000..bb1afa7db2f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-two.lua
@@ -0,0 +1,179 @@
+if not modules then modules = { } end modules ['core-two'] = {
+ version = 1.001,
+ comment = "companion to core-two.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local remove, concat = table.remove, table.concat
+local allocate = utilities.storage.allocate
+
+--[[ldx--
+<p>We save multi-pass information in the main utility table. This is a
+bit of a mess because we support old and new methods.</p>
+--ldx]]--
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local jobpasses = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.passes = jobpasses
+
+local function initializer()
+ collected = jobpasses.collected
+ tobesaved = jobpasses.tobesaved
+end
+
+job.register('job.passes.collected', tobesaved, initializer, nil)
+
+local function allocate(id)
+ local p = tobesaved[id]
+ if not p then
+ p = { }
+ tobesaved[id] = p
+ end
+ return p
+end
+
+jobpasses.define = allocate
+
+function jobpasses.save(id,str,index)
+ local jti = allocate(id)
+ if index then
+ jti[index] = str
+ else
+ jti[#jti+1] = str
+ end
+end
+
+function jobpasses.savetagged(id,tag,str)
+ local jti = allocate(id)
+ jti[tag] = str
+end
+
+function jobpasses.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 jti = collected[id]
+ jti = jti and jti[index]
+ local value = jti and jti[tag]
+ return value ~= "" and value or default or ""
+end
+
+function jobpasses.getcollected(id)
+ return collected[id] or { }
+end
+
+function jobpasses.gettobesaved(id)
+ return allocate(id)
+end
+
+local function get(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ return remove(jti,1)
+ end
+end
+
+local function first(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ return jti[1]
+ end
+end
+
+local function last(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ return jti[#jti]
+ end
+end
+
+local function find(id,n)
+ local jti = collected[id]
+ if jti and jti[n] then
+ return jti[n]
+ end
+end
+
+local function count(id)
+ local jti = collected[id]
+ return jti and #jti or 0
+end
+
+local function list(id)
+ local jti = collected[id]
+ if jti then
+ return concat(jti,',')
+ end
+end
+
+local function inlist(id,str)
+ local jti = collected[id]
+ if jti then
+ for _, v in next, jti do
+ if v == str then
+ return true
+ end
+ end
+ end
+ return false
+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
+
+-- interface
+
+local implement = interfaces.implement
+
+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 = { "string", "string" } }
+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,
+ arguments = "string"
+}
+
+implement {
+ name = "savetwopassdata",
+ actions = jobpasses.save,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "savetaggedtwopassdata",
+ actions = jobpasses.savetagged,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "doifelseintwopassdata",
+ actions = { inlist, commands.doifelse },
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv
new file mode 100644
index 00000000000..5a791dea2f7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv
@@ -0,0 +1,122 @@
+%D \module
+%D [ file=core-two, % moved from core-uti
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Two Pass Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Two Pass Data}
+
+%D This is a rather old mechanism which has not changed much over
+%D time, apart from adding a few more selectors. This code used
+%D to be part of \type {core-uti}. The following examples demonstrate
+%D the interface.
+%D
+%D \startbuffer
+%D \definetwopasslist{test-1}
+%D
+%D \gettwopassdatalist{test-1} [\twopassdatalist=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D
+%D \definetwopasslist{test-2}
+%D
+%D \lazysavetwopassdata{test-2}{1}{x}
+%D \lazysavetwopassdata{test-2}{2}{y}
+%D \lazysavetwopassdata{test-2}{3}{z}
+%D
+%D \gettwopassdatalist{test-2} [\twopassdatalist=x,y,z]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=y]
+%D \gettwopassdata {test-2} [\twopassdata=z]
+%D \gettwopassdata {test-2} [\twopassdata=]
+%D
+%D \definetwopasslist{test-3}
+%D
+%D \lazysavetaggedtwopassdata{test-3}{1}{x}{a}
+%D \lazysavetaggedtwopassdata{test-3}{2}{y}{b}
+%D \lazysavetaggedtwopassdata{test-3}{3}{z}{c}
+%D
+%D \findtwopassdata{test-3}{x} [\twopassdata=a]
+%D \findtwopassdata{test-3}{y} [\twopassdata=b]
+%D \findtwopassdata{test-3}{z} [\twopassdata=c]
+%D \findtwopassdata{test-3}{w} [\twopassdata=]
+%D
+%D \definetwopasslist{test-4}
+%D
+%D \lazysavetwopassdata{test-4}{1}{A}
+%D \lazysavetwopassdata{test-4}{2}{B}
+%D \lazysavetwopassdata{test-4}{3}{C}
+%D
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{1} [\twopassdata=A]
+%D \getfromtwopassdata {test-4}{3} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{2} [\twopassdata=B]
+%D \stopbuffer
+%D
+%D \getbuffer \typebuffer
+
+\unprotect
+
+\registerctxluafile{core-two}{1.001}
+
+\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")}}}
+
+% temp hack: needs a proper \starteverytimeluacode
+
+\setfalse\twopassdatafound
+\let \twopassdata \empty
+\let \twopassdatalist \empty
+
+\newif \iftwopassdatafound % obsolete, will go
+
+\def\syst_twopass_check % can be delegated to lua once obsolete is gone
+ {\ifx\twopassdata\empty
+ \twopassdatafoundfalse % obsolete
+ \setfalse\twopassdatafound
+ \else
+ \twopassdatafoundtrue % obsolete
+ \settrue\twopassdatafound
+ \fi}
+
+\def\syst_twopass_set_not_found
+ {\twopassdatafoundfalse % obsolete
+ \setfalse\twopassdatafound}
+
+\def\syst_twopass_set_found
+ {\twopassdatafoundtrue % obsolete
+ \settrue\twopassdatafound}
+
+\unexpanded\def\definetwopasslist #1{\clf_definetwopasslist{#1}}
+\unexpanded\def\gettwopassdata #1{\edef\twopassdata {\clf_gettwopassdata {#1}}\syst_twopass_check}
+\unexpanded\def\checktwopassdata #1{\edef\twopassdata {\clf_checktwopassdata {#1}}\syst_twopass_check}
+\unexpanded\def\findtwopassdata #1#2{\edef\twopassdata {\clf_findtwopassdata {#1}{#2}}\syst_twopass_check}
+\unexpanded\def\getfirsttwopassdata #1{\edef\twopassdata {\clf_getfirsttwopassdata {#1}}\syst_twopass_check}
+\unexpanded\def\getlasttwopassdata #1{\edef\twopassdata {\clf_getlasttwopassdata {#1}}%
+ \edef\noftwopassitems{\clf_counttwopassdata {#1}}\syst_twopass_check}
+\unexpanded\def\getnamedtwopassdatalist#1#2{\edef #1{\clf_gettwopassdatalist {#2}}}
+\unexpanded\def\gettwopassdatalist #1{\edef\twopassdatalist{\clf_gettwopassdatalist {#1}}}
+
+\unexpanded\def\doifelseintwopassdata #1#2{\clf_doifelseintwopassdata{#1}{#2}}
+
+ \let\doifintwopassdataelse \doifelseintwopassdata
+ \let\getfromtwopassdata \findtwopassdata
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua b/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua
new file mode 100644
index 00000000000..23057872ffe
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua
@@ -0,0 +1,438 @@
+if not modules then modules = { } end modules ['core-uti'] = {
+ version = 1.001,
+ comment = "companion to core-uti.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: keep track of changes here (hm, track access, and only true when
+-- accessed and changed)
+
+--[[ldx--
+<p>A utility file has always been part of <l n='context'/> and with
+the move to <l n='luatex'/> we also moved a lot of multi-pass info
+to a <l n='lua'/> table. Instead of loading a <l n='tex'/> based
+utility file under different setups, we now load a table once. This
+saves much runtime but at the cost of more memory usage.</p>
+--ldx]]--
+
+local math = math
+local format, match = string.format, string.match
+local next, type, tostring = next, type, tostring
+local concat = table.concat
+
+local definetable = utilities.tables.definetable
+local accesstable = utilities.tables.accesstable
+local migratetable = utilities.tables.migratetable
+local serialize = table.serialize
+local packers = utilities.packers
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+
+local implement = interfaces.implement
+
+local texgetcount = tex.getcount
+
+local report_passes = logs.reporter("job","passes")
+
+job = job or { }
+local job = job
+
+job.version = 1.30
+job.packversion = 1.02
+
+-- some day we will implement loading of other jobs and then we need
+-- job.jobs
+
+--[[ldx--
+<p>Variables are saved using in the previously defined table and passed
+onto <l n='tex'/> using the following method. Of course one can also
+directly access the variable using a <l n='lua'/> call.</p>
+--ldx]]--
+
+local savelist, comment = { }, { }
+
+function job.comment(key,value)
+ if type(key) == "table" then
+ for k, v in next, key do
+ comment[k] = v
+ end
+ else
+ comment[key] = value
+ end
+end
+
+job.comment("version",job.version)
+
+local enabled = true
+local initialized = false
+
+directives.register("job.save",function(v) enabled = v end)
+----------.register("job.keep",function(v) kept = v end)
+
+function job.disablesave() -- can be command
+ enabled = false
+end
+
+function job.initialize(loadname,savename)
+ if not initialized then
+ if not loadname or loadname == "" then
+ loadname = tex.jobname .. ".tuc"
+ end
+ if not savename or savename == "" then
+ savename = tex.jobname .. ".tua"
+ end
+ job.load(loadname) -- has to come after structure is defined !
+ luatex.registerstopactions(function()
+ if enabled and not status.lasterrorstring or status.lasterrorstring == "" then
+ -- if kept then
+ -- job.keep(loadname) -- could move to mtx-context instead
+ -- end
+ job.save(savename)
+ end
+ end)
+ initialized = true
+ end
+end
+
+function job.register(collected, tobesaved, initializer, finalizer, serializer)
+ savelist[#savelist+1] = { collected, tobesaved, initializer, finalizer, serializer }
+end
+
+-- as an example we implement variables
+
+local tobesaved, collected, checksums = allocate(), allocate(), allocate()
+
+local jobvariables = {
+ collected = collected,
+ tobesaved = tobesaved,
+ checksums = checksums,
+}
+
+-- if not checksums.old then checksums.old = md5.HEX("old") end -- used in experiment
+-- if not checksums.new then checksums.new = md5.HEX("new") end -- used in experiment
+
+job.variables = jobvariables
+
+local function initializer()
+ checksums = jobvariables.checksums
+end
+
+job.register('job.variables.checksums', 'job.variables.checksums', initializer)
+
+local rmethod, rvalue
+local collectedmacros, tobesavedmacros
+
+local ctx_setxvalue = context.setxvalue
+
+local function initializer()
+ tobesaved = jobvariables.tobesaved
+ collected = jobvariables.collected
+ --
+ rvalue = collected.randomseed
+ if not rvalue then
+ rvalue = math.random()
+ math.setrandomseedi(rvalue,"initialize")
+ rmethod = "initialized"
+ else
+ math.setrandomseedi(rvalue,"previous run")
+ rmethod = "resumed"
+ end
+ tobesaved.randomseed = rvalue
+ --
+ collectedmacros = collected.macros
+ tobesavedmacros = tobesaved.macros
+ if not collectedmacros then
+ collectedmacros = { }
+ collected.macros = collectedmacros
+ end
+ if not tobesavedmacros then
+ tobesavedmacros = { }
+ tobesaved.macros = tobesavedmacros
+ end
+ -- will become collected.macros
+ for cs, value in next, collectedmacros do
+ if type(value) == "string" then -- safeguard
+ ctx_setxvalue(cs,value)
+ end
+ end
+end
+
+job.register('job.variables.collected', tobesaved, initializer)
+
+function jobvariables.save(cs,value)
+ tobesavedmacros[cs] = value
+end
+
+function jobvariables.restore(cs)
+ return collectedmacros[cs] or tobesavedmacros[cs]
+end
+
+-- checksums
+
+function jobvariables.getchecksum(tag)
+ return checksums[tag] -- no default
+end
+
+function jobvariables.makechecksum(data)
+ return data and md5.HEX(data) -- no default
+end
+
+function jobvariables.setchecksum(tag,checksum)
+ checksums[tag] = checksum
+end
+
+--
+
+local packlist = {
+ "numbers",
+ "metadata",
+ "sectiondata",
+ "prefixdata",
+ "numberdata",
+ "pagedata",
+ "directives",
+ "specification",
+ "processors", -- might become key under directives or metadata
+-- "references", -- we need to rename of them as only one packs (not structures.lists.references)
+}
+
+local skiplist = {
+ "datasets",
+ "userdata",
+}
+
+-- not ok as we can have arbitrary keys in userdata and dataset so some day we
+-- might need a bit more granularity, like skippers
+
+local jobpacker = packers.new(packlist,job.packversion,skiplist) -- jump number when changs in hash
+
+job.pack = true
+-- job.pack = false
+
+directives.register("job.pack",function(v) job.pack = v end)
+
+local _save_, _load_, _others_ = { }, { }, { } -- registers timing
+
+function job.save(filename) -- we could return a table but it can get pretty large
+ statistics.starttiming(_save_)
+ local f = io.open(filename,'w')
+ if f then
+ f:write("local utilitydata = { }\n\n")
+ f:write(serialize(comment,"utilitydata.comment",true),"\n\n")
+ for l=1,#savelist do
+ -- f:write("do\n\n") -- no solution for the jit limitatione either
+ local list = savelist[l]
+ local target = format("utilitydata.%s",list[1])
+ local data = list[2]
+ local finalizer = list[4]
+ local serializer = list[5]
+ if type(data) == "string" then
+ data = utilities.tables.accesstable(data)
+ end
+ if type(finalizer) == "function" then
+ finalizer()
+ end
+ if job.pack then
+ packers.pack(data,jobpacker,true)
+ end
+ local definer, name = definetable(target,true,true) -- no first and no last
+ if serializer then
+ f:write(definer,"\n\n",serializer(data,name,true),"\n\n")
+ else
+ f:write(definer,"\n\n",serialize(data,name,true),"\n\n")
+ end
+ -- f:write("end\n\n")
+ end
+ if job.pack then
+ packers.strip(jobpacker)
+ -- f:write("do\n\n")
+ f:write(serialize(jobpacker,"utilitydata.job.packed",true),"\n\n")
+ -- f:write("end\n\n")
+ end
+ f:write("return utilitydata")
+ f:close()
+ end
+ statistics.stoptiming(_save_)
+end
+
+local function load(filename)
+ if lfs.isfile(filename) then
+ local okay, data = pcall(dofile,filename)
+ if okay and type(data) == "table" then
+ local jobversion = job.version
+ local datacomment = data.comment
+ local dataversion = datacomment and datacomment.version or "?"
+ if dataversion ~= jobversion then
+ report_passes("version mismatch: %s <> %s",dataversion,jobversion)
+ else
+ return data
+ end
+ else
+ os.remove(filename) -- probably a bad file (or luajit overflow as it cannot handle large tables well)
+ report_passes("removing stale job data file %a, restart job, message: %s%s",filename,tostring(data),
+ jit and " (try luatex instead of luajittex)" or "")
+ os.exit(true) -- trigger second run
+ end
+ end
+end
+
+function job.load(filename)
+ statistics.starttiming(_load_)
+ local utilitydata = load(filename)
+ if utilitydata then
+ local jobpacker = utilitydata.job.packed
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target = list[1]
+ local initializer = list[3]
+ local result = accesstable(target,utilitydata)
+ local done = packers.unpack(result,jobpacker,true)
+ if done then
+ migratetable(target,mark(result))
+ if type(initializer) == "function" then
+ initializer(result)
+ end
+ else
+ report_passes("pack version mismatch")
+ end
+ end
+ end
+ statistics.stoptiming(_load_)
+end
+
+function job.loadother(filename)
+ statistics.starttiming(_load_)
+ _others_[#_others_+1] = file.nameonly(filename)
+ local utilitydata = load(filename)
+ if utilitydata then
+ local jobpacker = utilitydata.job.packed
+ local unpacked = { }
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target = list[1]
+ local result = accesstable(target,utilitydata)
+ local done = packers.unpack(result,jobpacker,true)
+ if done then
+ migratetable(target,result,unpacked)
+ end
+ end
+ unpacked.job.packed = nil -- nicer in inspecting
+ return unpacked
+ end
+ statistics.stoptiming(_load_)
+end
+
+-- function job.keep(filename)
+-- local suffix = file.suffix(filename)
+-- local base = file.removesuffix(filename)
+-- if suffix == "" then
+-- suffix = "tuc"
+-- end
+-- for i=1,10 do
+-- local tmpname = format("%s-%s-%02d.tmp",base,suffix,i)
+-- if lfs.isfile(tmpname) then
+-- os.remove(tmpname)
+-- report_passes("removing %a",tmpname)
+-- end
+-- end
+-- if lfs.isfile(filename) then
+-- local tmpname = format("%s-%s-%02d.tmp",base,suffix,environment.currentrun or 1)
+-- report_passes("copying %a into %a",filename,tmpname)
+-- file.copy(filename,tmpname)
+-- else
+-- report_passes("no file %a, nothing kept",filename)
+-- end
+-- end
+
+-- eventually this will end up in strc-ini
+
+statistics.register("startup time", function()
+ return statistics.elapsedseconds(statistics,"including runtime option file processing")
+end)
+
+statistics.register("jobdata time",function()
+ if enabled then
+ if #_others_ > 0 then
+ return format("%s seconds saving, %s seconds loading, other files: %s",statistics.elapsedtime(_save_),statistics.elapsedtime(_load_),concat(_others_," "))
+ else
+ return format("%s seconds saving, %s seconds loading",statistics.elapsedtime(_save_),statistics.elapsedtime(_load_))
+ end
+ else
+ if #_others_ > 0 then
+ return format("nothing saved, %s seconds loading, other files: %s",statistics.elapsedtime(_load_),concat(_others_," "))
+ else
+ return format("nothing saved, %s seconds loading",statistics.elapsedtime(_load_))
+ end
+ end
+end)
+
+statistics.register("callbacks", function()
+ local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
+ local pages = texgetcount('realpageno') - 1
+ if pages > 1 then
+ return format("direct: %s, indirect: %s, total: %s (%i per page)", total-indirect, indirect, total, total/pages)
+ else
+ return format("direct: %s, indirect: %s, total: %s", total-indirect, indirect, total)
+ end
+end)
+
+statistics.register("randomizer", function()
+ if rmethod and rvalue then
+ return format("%s with value %s",rmethod,rvalue)
+ end
+end)
+
+-- a sort of joke (for ctx meeting)
+
+local kg_per_watt_per_second = 1 / 15000000
+local watts_per_core = 50
+local speedup_by_other_engine = 1.2
+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
+ local shipped = texgetcount('nofshipouts')
+ local pages = texgetcount('realpageno')
+ if pages > shipped then
+ pages = shipped
+ end
+ if shipped > 0 or pages > 0 then
+ local persecond = shipped / runtime
+ if pages == 0 then pages = shipped end
+ -- if jit 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
+ else
+ return format("%s seconds",runtime)
+ end
+ end
+end
+
+implement {
+ name = "savevariable",
+ actions = job.variables.save,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setjobcomment",
+ actions = job.comment,
+ arguments = { { "*" } }
+}
+
+implement {
+ name = "initializejob",
+ actions = job.initialize
+}
+
+implement {
+ name = "disablejobsave",
+ actions = job.disablesave
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-uti.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-uti.mkiv
new file mode 100644
index 00000000000..de9a893ee8e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/core-uti.mkiv
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=core-uti,
+%D version=1997.03.31, % 2006.09.19 mkiv
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Utility File Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Utility File Handling}
+
+\unprotect
+
+\registerctxluafile{core-uti}{1.001}
+
+\def\savecurrentvalue#1#2% immediate, so not \unexpanded
+ {\clf_savevariable{\csstring#1}{#2}}
+
+\appendtoks
+ \clf_setjobcomment
+ file {tex.jobname}%
+ format {\contextformat}%
+ stamp {\contextversion}%
+ escape {\!!bs\space...\space\!!es}%
+ \relax
+\to \everystarttext
+
+\appendtoks
+ \clf_initializejob
+\to \everyjob
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua
new file mode 100644
index 00000000000..dae96ce6200
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua
@@ -0,0 +1,63 @@
+if not modules then modules = { } end modules ['data-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find = string.find
+local type, next = type, next
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local resolvers = resolvers
+
+local report_scripts = logs.reporter("resolvers","scripts")
+
+function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per se a suffix
+ -- local scriptpath = "scripts/context/lua"
+ local scriptpath = "context/lua"
+ newname = file.addsuffix(newname,"lua")
+ local oldscript = resolvers.cleanpath(oldname)
+ if trace_locating then
+ report_scripts("to be replaced old script %a", oldscript)
+ end
+ local newscripts = resolvers.findfiles(newname) or { }
+ if #newscripts == 0 then
+ if trace_locating then
+ report_scripts("unable to locate new script")
+ end
+ else
+ for i=1,#newscripts do
+ local newscript = resolvers.cleanpath(newscripts[i])
+ if trace_locating then
+ report_scripts("checking new script %a", newscript)
+ end
+ if oldscript == newscript then
+ if trace_locating then
+ report_scripts("old and new script are the same")
+ end
+ elseif not find(newscript,scriptpath) then
+ if trace_locating then
+ report_scripts("new script should come from %a",scriptpath)
+ end
+ elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
+ if trace_locating then
+ report_scripts("invalid new script name")
+ end
+ else
+ local newdata = io.loaddata(newscript)
+ if newdata then
+ if trace_locating then
+ report_scripts("old script content replaced by new content")
+ end
+ io.savedata(oldscript,newdata)
+ break
+ elseif trace_locating then
+ report_scripts("unable to load new script")
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-bin.lua b/Master/texmf-dist/tex/context/base/mkiv/data-bin.lua
new file mode 100644
index 00000000000..1d1e8b74959
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-bin.lua
@@ -0,0 +1,27 @@
+if not modules then modules = { } end modules ['data-bin'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local resolvers = resolvers
+local methodhandler = resolvers.methodhandler
+
+function resolvers.findbinfile(filename,filetype)
+ return methodhandler('finders',filename,filetype)
+end
+
+function resolvers.openbinfile(filename)
+ return methodhandler('loaders',filename) -- a bit weird: load
+end
+
+function resolvers.loadbinfile(filename,filetype)
+ local fname = methodhandler('finders',filename,filetype)
+ if fname and fname ~= "" then
+ return resolvers.openbinfile(fname) -- a bit weird: open
+ else
+ return resolvers.loaders.notfound()
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-con.lua b/Master/texmf-dist/tex/context/base/mkiv/data-con.lua
new file mode 100644
index 00000000000..240538df2db
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-con.lua
@@ -0,0 +1,138 @@
+if not modules then modules = { } end modules ['data-con'] = {
+ version = 1.100,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, lower, gsub = string.format, string.lower, string.gsub
+
+local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
+local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
+local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
+
+--[[ldx--
+<p>Once we found ourselves defining similar cache constructs
+several times, containers were introduced. Containers are used
+to collect tables in memory and reuse them when possible based
+on (unique) hashes (to be provided by the calling function).</p>
+
+<p>Caching to disk is disabled by default. Version numbers are
+stored in the saved table which makes it possible to change the
+table structures without bothering about the disk cache.</p>
+
+<p>Examples of usage can be found in the font related code.</p>
+--ldx]]--
+
+containers = containers or { }
+local containers = containers
+containers.usecache = true
+
+local report_containers = logs.reporter("resolvers","containers")
+
+local allocated = { }
+
+local mt = {
+ __index = function(t,k)
+ if k == "writable" then
+ local writable = caches.getwritablepath(t.category,t.subcategory) or { "." }
+ t.writable = writable
+ return writable
+ elseif k == "readables" then
+ local readables = caches.getreadablepaths(t.category,t.subcategory) or { "." }
+ t.readables = readables
+ return readables
+ end
+ end,
+ __storage__ = true
+}
+
+function containers.define(category, subcategory, version, enabled)
+ if category and subcategory then
+ local c = allocated[category]
+ if not c then
+ c = { }
+ allocated[category] = c
+ end
+ local s = c[subcategory]
+ if not s then
+ s = {
+ category = category,
+ subcategory = subcategory,
+ storage = { },
+ enabled = enabled,
+ version = version or math.pi, -- after all, this is TeX
+ trace = false,
+ -- writable = caches.getwritablepath and caches.getwritablepath (category,subcategory) or { "." },
+ -- readables = caches.getreadablepaths and caches.getreadablepaths(category,subcategory) or { "." },
+ }
+ setmetatable(s,mt)
+ c[subcategory] = s
+ end
+ return s
+ end
+end
+
+function containers.is_usable(container,name)
+ return container.enabled and caches and caches.is_writable(container.writable, name)
+end
+
+function containers.is_valid(container,name)
+ if name and name ~= "" then
+ local storage = container.storage[name]
+ return storage and storage.cache_version == container.version
+ else
+ return false
+ end
+end
+
+function containers.read(container,name)
+ local storage = container.storage
+ local stored = storage[name]
+ if not stored and container.enabled and caches and containers.usecache then
+ stored = caches.loaddata(container.readables,name)
+ if stored and stored.cache_version == container.version then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+ end
+ else
+ stored = nil
+ end
+ storage[name] = stored
+ elseif stored then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+ end
+ end
+ return stored
+end
+
+function containers.write(container, name, data)
+ if data then
+ data.cache_version = container.version
+ if container.enabled and caches then
+ local unique, shared = data.unique, data.shared
+ data.unique, data.shared = nil, nil
+ caches.savedata(container.writable, name, data)
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+ end
+ data.unique, data.shared = unique, shared
+ end
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+ end
+ container.storage[name] = data
+ end
+ return data
+end
+
+function containers.content(container,name)
+ return container.storage[name]
+end
+
+function containers.cleanname(name)
+ -- return (gsub(lower(name),"[^%w]+","-"))
+ return (gsub(lower(name),"[^%w\128-\255]+","-")) -- more utf friendly
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-crl.lua b/Master/texmf-dist/tex/context/base/mkiv/data-crl.lua
new file mode 100644
index 00000000000..fba5a62305b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-crl.lua
@@ -0,0 +1,61 @@
+if not modules then modules = { } end modules ['data-crl'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this one is replaced by data-sch.lua --
+
+local gsub = string.gsub
+
+local resolvers = resolvers
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+resolvers.curl = resolvers.curl or { }
+local curl = resolvers.curl
+
+local cached = { }
+
+local function runcurl(specification)
+ local original = specification.original
+ -- local scheme = specification.scheme
+ local cleanname = gsub(original,"[^%a%d%.]+","-")
+ local cachename = caches.setfirstwritablefile(cleanname,"curl")
+ if not cached[original] then
+ if not io.exists(cachename) then
+ cached[original] = cachename
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
+ os.execute(command)
+ end
+ if io.exists(cachename) then
+ cached[original] = cachename
+ else
+ cached[original] = ""
+ end
+ end
+ return cached[original]
+end
+
+-- old code: we could be cleaner using specification (see schemes)
+
+local function finder(specification,filetype)
+ return resolvers.methodhandler("finders",runcurl(specification),filetype)
+end
+
+local opener = openers.file
+local loader = loaders.file
+
+local function install(scheme)
+ finders[scheme] = finder
+ openers[scheme] = opener
+ loaders[scheme] = loader
+end
+
+resolvers.curl.install = install
+
+install('http')
+install('https')
+install('ftp')
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/data-ctx.lua
new file mode 100644
index 00000000000..345e9c7411a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-ctx.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['data-ctx'] = {
+ 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"
+}
+
+-- empty
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-env.lua b/Master/texmf-dist/tex/context/base/mkiv/data-env.lua
new file mode 100644
index 00000000000..8bb25036de1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-env.lua
@@ -0,0 +1,307 @@
+if not modules then modules = { } end modules ['data-env'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lower, gsub = string.lower, string.gsub
+
+local resolvers = resolvers
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local suffixonly = file.suffixonly
+
+local formats = allocate()
+local suffixes = allocate()
+local dangerous = allocate()
+local suffixmap = allocate()
+local usertypes = allocate()
+
+resolvers.formats = formats
+resolvers.suffixes = suffixes
+resolvers.dangerous = dangerous
+resolvers.suffixmap = suffixmap
+resolvers.usertypes = usertypes
+
+local luasuffixes = utilities.lua.suffixes
+
+local relations = allocate { -- todo: handlers also here
+ core = {
+ ofm = { -- will become obsolete
+ names = { "ofm", "omega font metric", "omega font metrics" },
+ variable = 'OFMFONTS',
+ suffixes = { 'ofm', 'tfm' },
+ },
+ ovf = { -- will become obsolete
+ names = { "ovf", "omega virtual font", "omega virtual fonts" },
+ variable = 'OVFFONTS',
+ suffixes = { 'ovf', 'vf' },
+ },
+ tfm = {
+ names = { "tfm", "tex font metric", "tex font metrics" },
+ variable = 'TFMFONTS',
+ suffixes = { 'tfm' },
+ },
+ vf = {
+ names = { "vf", "virtual font", "virtual fonts" },
+ variable = 'VFFONTS',
+ suffixes = { 'vf' },
+ },
+ otf = {
+ names = { "otf", "opentype", "opentype font", "opentype fonts"},
+ variable = 'OPENTYPEFONTS',
+ suffixes = { 'otf' },
+ },
+ ttf = {
+ names = { "ttf", "truetype", "truetype font", "truetype fonts", "truetype collection", "truetype collections", "truetype dictionary", "truetype dictionaries" },
+ variable = 'TTFONTS',
+ suffixes = { 'ttf', 'ttc', 'dfont' },
+ },
+ afm = {
+ names = { "afm", "adobe font metric", "adobe font metrics" },
+ variable = "AFMFONTS",
+ suffixes = { "afm" },
+ },
+ pfb = {
+ names = { "pfb", "type1", "type 1", "type1 font", "type 1 font", "type1 fonts", "type 1 fonts" },
+ variable = 'T1FONTS',
+ suffixes = { 'pfb', 'pfa' },
+ },
+ fea = {
+ names = { "fea", "font feature", "font features", "font feature file", "font feature files" },
+ variable = 'FONTFEATURES',
+ suffixes = { 'fea' },
+ },
+ cid = {
+ names = { "cid", "cid map", "cid maps", "cid file", "cid files" },
+ variable = 'FONTCIDMAPS',
+ suffixes = { 'cid', 'cidmap' },
+ },
+ fmt = {
+ names = { "fmt", "format", "tex format" },
+ variable = 'TEXFORMATS',
+ suffixes = { 'fmt' },
+ },
+ mem = { -- will become obsolete
+ names = { 'mem', "metapost format" },
+ variable = 'MPMEMS',
+ suffixes = { 'mem' },
+ },
+ mp = {
+ names = { "mp" },
+ variable = 'MPINPUTS',
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
+ usertype = true,
+ },
+ tex = {
+ names = { "tex" },
+ variable = 'TEXINPUTS',
+ suffixes = { "tex", "mkvi", "mkiv", "mkii", "cld", "lfg", "xml" }, -- known suffixes have less lookups
+ usertype = true,
+ },
+ icc = {
+ names = { "icc", "icc profile", "icc profiles" },
+ variable = 'ICCPROFILES',
+ suffixes = { 'icc' },
+ },
+ texmfscripts = {
+ names = { "texmfscript", "texmfscripts", "script", "scripts" },
+ variable = 'TEXMFSCRIPTS',
+ suffixes = { 'lua', 'rb', 'pl', 'py' },
+ },
+ lua = {
+ names = { "lua" },
+ variable = 'LUAINPUTS',
+ suffixes = { luasuffixes.lua, luasuffixes.luc, luasuffixes.tma, luasuffixes.tmc },
+ usertype = true,
+ },
+ lib = {
+ names = { "lib" },
+ variable = 'CLUAINPUTS',
+ suffixes = os.libsuffix and { os.libsuffix } or { 'dll', 'so' },
+ },
+ bib = {
+ names = { 'bib' },
+ variable = 'BIBINPUTS',
+ suffixes = { 'bib' },
+ usertype = true,
+ },
+ bst = {
+ names = { 'bst' },
+ variable = 'BSTINPUTS',
+ suffixes = { 'bst' },
+ usertype = true,
+ },
+ fontconfig = {
+ names = { 'fontconfig', 'fontconfig file', 'fontconfig files' },
+ variable = 'FONTCONFIG_PATH',
+ },
+ pk = {
+ names = { "pk" },
+ variable = 'PKFONTS',
+ suffixes = { 'pk' },
+ },
+ },
+ obsolete = {
+ enc = {
+ names = { "enc", "enc files", "enc file", "encoding files", "encoding file" },
+ variable = 'ENCFONTS',
+ suffixes = { 'enc' },
+ },
+ map = {
+ names = { "map", "map files", "map file" },
+ variable = 'TEXFONTMAPS',
+ suffixes = { 'map' },
+ },
+ lig = {
+ names = { "lig files", "lig file", "ligature file", "ligature files" },
+ variable = 'LIGFONTS',
+ suffixes = { 'lig' },
+ },
+ opl = {
+ names = { "opl" },
+ variable = 'OPLFONTS',
+ suffixes = { 'opl' },
+ },
+ ovp = {
+ names = { "ovp" },
+ variable = 'OVPFONTS',
+ suffixes = { 'ovp' },
+ },
+ },
+ kpse = { -- subset
+ base = {
+ names = { 'base', "metafont format" },
+ variable = 'MFBASES',
+ suffixes = { 'base', 'bas' },
+ },
+ cmap = {
+ names = { 'cmap', 'cmap files', 'cmap file' },
+ variable = 'CMAPFONTS',
+ suffixes = { 'cmap' },
+ },
+ cnf = {
+ names = { 'cnf' },
+ suffixes = { 'cnf' },
+ },
+ web = {
+ names = { 'web' },
+ suffixes = { 'web', 'ch' }
+ },
+ cweb = {
+ names = { 'cweb' },
+ suffixes = { 'w', 'web', 'ch' },
+ },
+ gf = {
+ names = { 'gf' },
+ suffixes = { '<resolution>gf' },
+ },
+ mf = {
+ names = { 'mf' },
+ variable = 'MFINPUTS',
+ suffixes = { 'mf' },
+ },
+ mft = {
+ names = { 'mft' },
+ suffixes = { 'mft' },
+ },
+ pk = {
+ names = { 'pk' },
+ suffixes = { '<resolution>pk' },
+ },
+ },
+}
+
+resolvers.relations = relations
+
+-- formats: maps a format onto a variable
+
+function resolvers.updaterelations()
+ for category, categories in next, relations do
+ for name, relation in next, categories do
+ local rn = relation.names
+ local rv = relation.variable
+ if rn and rv then
+ local rs = relation.suffixes
+ local ru = relation.usertype
+ for i=1,#rn do
+ local rni = lower(gsub(rn[i]," ",""))
+ formats[rni] = rv
+ if rs then
+ suffixes[rni] = rs
+ for i=1,#rs do
+ local rsi = rs[i]
+ suffixmap[rsi] = rni
+ end
+ end
+ end
+ if ru then
+ usertypes[name] = true
+ end
+ end
+ end
+ end
+end
+
+resolvers.updaterelations() -- push this in the metatable -> newindex
+
+local function simplified(t,k)
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
+end
+
+setmetatableindex(formats, simplified)
+setmetatableindex(suffixes, simplified)
+setmetatableindex(suffixmap, simplified)
+
+-- A few accessors, mostly for command line tool.
+
+function resolvers.suffixofformat(str)
+ local s = suffixes[str]
+ return s and s[1] or ""
+end
+
+function resolvers.suffixofformat(str)
+ return suffixes[str] or { }
+end
+
+for name, format in next, formats do
+ dangerous[name] = true -- still needed ?
+end
+
+-- because vf searching is somewhat dangerous, we want to prevent
+-- too liberal searching esp because we do a lookup on the current
+-- path anyway; only tex (or any) is safe
+
+dangerous.tex = nil
+
+--~ print(table.serialize(dangerous))
+
+-- more helpers
+
+function resolvers.formatofvariable(str)
+ return formats[str] or ''
+end
+
+function resolvers.formatofsuffix(str) -- of file
+ return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
+end
+
+function resolvers.variableofformat(str)
+ return formats[str] or ''
+end
+
+function resolvers.variableofformatorsuffix(str)
+ local v = formats[str]
+ if v then
+ return v
+ end
+ v = suffixmap[suffixonly(str)]
+ if v then
+ return formats[v]
+ end
+ return ''
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-exp.lua b/Master/texmf-dist/tex/context/base/mkiv/data-exp.lua
new file mode 100644
index 00000000000..19ceb90c342
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-exp.lua
@@ -0,0 +1,552 @@
+if not modules then modules = { } end modules ['data-exp'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
+local concat, sort = table.concat, table.sort
+local sortedkeys = table.sortedkeys
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local Ct, Cs, Cc, Carg, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.P, lpeg.C, lpeg.S
+local type, next = type, next
+local isdir = lfs.isdir
+
+local ostype = os.type
+local collapsepath, joinpath, basename = file.collapsepath, file.join, file.basename
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
+local trace_globbing = true trackers.register("resolvers.globbing", function(v) trace_globbing = v end)
+
+local report_expansions = logs.reporter("resolvers","expansions")
+local report_globbing = logs.reporter("resolvers","globbing")
+
+local resolvers = resolvers
+local resolveprefix = resolvers.resolve
+
+-- As this bit of code is somewhat special it gets its own module. After
+-- all, when working on the main resolver code, I don't want to scroll
+-- past this every time. See data-obs.lua for the gsub variant.
+
+-- local function f_first(a,b)
+-- local t, n = { }, 0
+-- for s in gmatch(b,"[^,]+") do
+-- n = n + 1 ; t[n] = a .. s
+-- end
+-- return concat(t,",")
+-- end
+--
+-- local function f_second(a,b)
+-- local t, n = { }, 0
+-- for s in gmatch(a,"[^,]+") do
+-- n = n + 1 ; t[n] = s .. b
+-- end
+-- return concat(t,",")
+-- end
+
+-- kpsewhich --expand-braces '{a,b}{c,d}'
+-- ac:bc:ad:bd
+
+-- old {a,b}{c,d} => ac ad bc bd
+--
+-- local function f_both(a,b)
+-- local t, n = { }, 0
+-- for sa in gmatch(a,"[^,]+") do
+-- for sb in gmatch(b,"[^,]+") do
+-- n = n + 1 ; t[n] = sa .. sb
+-- end
+-- end
+-- return concat(t,",")
+-- end
+--
+-- new {a,b}{c,d} => ac bc ad bd
+
+local function f_both(a,b)
+ local t, n = { }, 0
+ for sb in gmatch(b,"[^,]+") do -- and not sa
+ for sa in gmatch(a,"[^,]+") do -- sb
+ n = n + 1 ; t[n] = sa .. sb
+ end
+ end
+ return concat(t,",")
+end
+
+local comma = P(",")
+local nocomma = (1-comma)^1
+local docomma = comma^1/","
+local before = Cs((nocomma * Carg(1) + docomma)^0)
+local after = Cs((Carg(1) * nocomma + docomma)^0)
+local both = Cs(((C(nocomma) * Carg(1))/function(a,b) return lpegmatch(before,b,1,a) end + docomma)^0)
+
+local function f_first (a,b) return lpegmatch(after, b,1,a) end
+local function f_second(a,b) return lpegmatch(before,a,1,b) end
+local function f_both (a,b) return lpegmatch(both, b,1,a) end
+
+-- print(f_first ("a", "x,y,z"))
+-- print(f_second("a,b,c","x"))
+-- print(f_both ("a,b,c","x,y,z"))
+
+local left = P("{")
+local right = P("}")
+local var = P((1 - S("{}" ))^0)
+local set = P((1 - S("{},"))^0)
+local other = P(1)
+
+local l_first = Cs( ( Cc("{") * (C(set) * left * C(var) * right / f_first) * Cc("}") + other )^0 )
+local l_second = Cs( ( Cc("{") * (left * C(var) * right * C(set) / f_second) * Cc("}") + other )^0 )
+local l_both = Cs( ( Cc("{") * (left * C(var) * right * left * C(var) * right / f_both) * Cc("}") + other )^0 )
+local l_rest = Cs( ( left * var * (left/"") * var * (right/"") * var * right + other )^0 )
+
+local stripper_1 = lpeg.stripper ("{}@")
+local replacer_1 = lpeg.replacer { { ",}", ",@}" }, { "{,", "{@," }, }
+
+local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpegging it (nice exercise).
+ if trace_expansions then
+ report_expansions("expanding variable %a",str)
+ end
+ local t, ok, done = newlist or { }, false, false
+ local n = #t
+ str = lpegmatch(replacer_1,str)
+ repeat
+ local old = str
+ repeat
+ local old = str
+ str = lpegmatch(l_first, str)
+ until old == str
+ repeat
+ local old = str
+ str = lpegmatch(l_second,str)
+ until old == str
+ repeat
+ local old = str
+ str = lpegmatch(l_both, str)
+ until old == str
+ repeat
+ local old = str
+ str = lpegmatch(l_rest, str)
+ until old == str
+ until old == str -- or not find(str,"{",1,true)
+ str = lpegmatch(stripper_1,str)
+ if validate then
+ for s in gmatch(str,"[^,]+") do
+ s = validate(s)
+ if s then
+ n = n + 1
+ t[n] = s
+ end
+ end
+ else
+ for s in gmatch(str,"[^,]+") do
+ n = n + 1
+ t[n] = s
+ end
+ end
+ if trace_expansions then
+ for k=1,#t do
+ report_expansions("% 4i: %s",k,t[k])
+ end
+ end
+ return t
+end
+
+-- We could make the previous one public.
+
+local function validate(s)
+ s = collapsepath(s) -- already keeps the trailing / and //
+ return s ~= "" and not find(s,"^!*unset/*$") and s
+end
+
+resolvers.validatedpath = validate -- keeps the trailing //
+
+function resolvers.expandedpathfromlist(pathlist)
+ local newlist = { }
+ for k=1,#pathlist do
+ splitpathexpr(pathlist[k],newlist,validate)
+ end
+ return newlist
+end
+
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
+local usedhomedir = nil
+local donegation = (P("!") /"" )^0
+local doslashes = (P("\\")/"/" + 1)^0
+
+local function expandedhome()
+ if not usedhomedir then
+ usedhomedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if usedhomedir == "~" or usedhomedir == "" or not isdir(usedhomedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent path using current path")
+ end
+ usedhomedir = "."
+ end
+ end
+ return usedhomedir
+end
+
+local dohome = ((P("~")+P("$HOME")+P("%HOME%"))/expandedhome)^0
+local cleanup = Cs(donegation * dohome * doslashes)
+
+resolvers.cleanpath = function(str)
+ return str and lpegmatch(cleanup,str) or ""
+end
+
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
+-- This one strips quotes and funny tokens.
+
+-- we have several options here:
+--
+-- expandhome = P("~") / "$HOME" : relocateble
+-- expandhome = P("~") / "home:" : relocateble
+-- expandhome = P("~") / environment.homedir : frozen but unexpanded
+-- expandhome = P("~") = dohome : frozen and expanded
+
+local expandhome = P("~") / "$HOME"
+
+local dodouble = P('"') / "" * (expandhome + (1 - P('"')))^0 * P('"') / ""
+local dosingle = P("'") / "" * (expandhome + (1 - P("'")))^0 * P("'") / ""
+local dostring = (expandhome + 1 )^0
+
+local stripper = Cs(
+ lpegpatterns.unspacer * (dosingle + dodouble + dostring) * lpegpatterns.unspacer
+)
+
+function resolvers.checkedvariable(str) -- assumes str is a string
+ return type(str) == "string" and lpegmatch(stripper,str) or str
+end
+
+-- The path splitter:
+
+-- A config (optionally) has the paths split in tables. Internally
+-- we join them and split them after the expansion has taken place. This
+-- is more convenient.
+
+local cache = { }
+
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
+
+local backslashswapper = lpeg.replacer("\\","/")
+
+local function splitconfigurationpath(str) -- beware, this can be either a path or a { specification }
+ if str then
+ local found = cache[str]
+ if not found then
+ if str == "" then
+ found = { }
+ else
+ local split = lpegmatch(splitter,lpegmatch(backslashswapper,str)) -- can be combined
+ found = { }
+ local noffound = 0
+ for i=1,#split do
+ local s = split[i]
+ if not find(s,"^{*unset}*") then
+ noffound = noffound + 1
+ found[noffound] = s
+ end
+ end
+ if trace_expansions then
+ report_expansions("splitting path specification %a",str)
+ for k=1,noffound do
+ report_expansions("% 4i: %s",k,found[k])
+ end
+ end
+ cache[str] = found
+ end
+ end
+ return found
+ end
+end
+
+resolvers.splitconfigurationpath = splitconfigurationpath
+
+function resolvers.splitpath(str)
+ if type(str) == 'table' then
+ return str
+ else
+ return splitconfigurationpath(str)
+ end
+end
+
+function resolvers.joinpath(str)
+ if type(str) == 'table' then
+ return joinpath(str)
+ else
+ return str
+ end
+end
+
+-- The next function scans directories and returns a hash where the
+-- entries are either strings or tables.
+--
+-- starting with . or .. etc or funny char
+--
+-- local l_forbidden = S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t")
+-- local l_confusing = P(" ")
+-- local l_character = lpegpatterns.utf8
+-- local l_dangerous = P(".")
+--
+-- local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * P(-1)
+-- ----- l_normal = l_normal * Cc(true) + Cc(false)
+--
+-- local function test(str)
+-- print(str,lpegmatch(l_normal,str))
+-- end
+-- test("ヒラギノ明朝 Pro W3")
+-- test("..ヒラギノ明朝 Pro W3")
+-- test(":ヒラギノ明朝 Pro W3;")
+-- test("ヒラギノ明朝 /Pro W3;")
+-- test("ヒラギノ明朝 Pro W3")
+
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
+
+local attributes, directory = lfs.attributes, lfs.dir
+
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local lessweird = P(".")^1 + lpeg.anywhere(S("~`#$%^&*:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+local fullcache = { }
+----- simplecache = { }
+local nofsharedscans = 0
+
+-- So, we assume either a lowercase name or a mixed case one but only one such case
+-- as having Foo fOo foo FoO FOo etc on the system is braindead in any sane project.
+
+local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
+ local full = path == "" and spec or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ local pattern = tolerant and lessweird or weird
+ for name in directory(full) do
+ if not lpegmatch(pattern,name) then
+ local mode = attributes(full..name,"mode")
+ if mode == "file" then
+ n = n + 1
+ local lower = lower(name)
+ local paths = files[lower]
+ if paths then
+ if onlyone then
+ -- forget about it
+ else
+ if type(paths) == "string" then
+ files[lower] = { paths, path }
+ else
+ paths[#paths+1] = path
+ end
+ if name ~= lower then
+ local rl = remap[lower]
+ if not rl then
+ remap[lower] = name
+ r = r + 1
+ elseif trace_globbing and rl ~= name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
+ end
+ end
+ else -- probably unique anyway
+ files[lower] = path
+ if name ~= lower then
+ local rl = remap[lower]
+ if not rl then
+ remap[lower] = name
+ r = r + 1
+ elseif trace_globbing and rl ~= name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
+ end
+ end
+ elseif mode == "directory" then
+ m = m + 1
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path .. "/" .. name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files, remap, n, m, r = scan(files,remap,spec,dirs[i],n,m,r,onlyonce,tolerant)
+ end
+ end
+ scancache[sub(full,1,-2)] = files
+ return files, remap, n, m, r
+end
+
+function resolvers.scanfiles(path,branch,usecache,onlyonce,tolerant)
+ local realpath = resolveprefix(path)
+ if usecache then
+ local content = fullcache[realpath]
+ if content then
+ if trace_locating then
+ report_expansions("using cached scan of path %a, branch %a",path,branch or path)
+ end
+ nofsharedscans = nofsharedscans + 1
+ return content
+ end
+ end
+ --
+ statistics.starttiming(timer)
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local content
+ if isdir(realpath) then
+ local files, remap, n, m, r = scan({ },{ },realpath .. '/',"",0,0,0,onlyonce,tolerant)
+ content = {
+ metadata = {
+ path = path, -- can be selfautoparent:texmf-whatever
+ files = n,
+ directories = m,
+ remappings = r,
+ },
+ files = files,
+ remap = remap,
+ }
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
+ end
+ else
+ content = {
+ metadata = {
+ path = path, -- can be selfautoparent:texmf-whatever
+ files = 0,
+ directories = 0,
+ remappings = 0,
+ },
+ files = { },
+ remap = { },
+ }
+ if trace_locating then
+ report_expansions("invalid path %a",realpath)
+ end
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = content
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return content
+end
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ return resolvers.scanfiles(path,branch,usecache,true,true) -- onlyonce
+end
+
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
+function resolvers.get_from_content(content,path,name) -- or (content,name)
+ if not content then
+ return
+ end
+ local files = content.files
+ if not files then
+ return
+ end
+ local remap = content.remap
+ if not remap then
+ return
+ end
+ if name then
+ -- this one resolves a remapped name
+ local used = lower(name)
+ return path, remap[used] or used
+ else
+ -- this one does a lookup and resolves a remapped name
+ local name = path
+ local used = lower(name)
+ local path = files[used]
+ if path then
+ return path, remap[used] or used
+ end
+ end
+end
+
+local nothing = function() end
+
+-- function resolvers.filtered_from_content(content,pattern)
+-- if content and type(pattern) == "string" then
+-- local pattern = lower(pattern)
+-- local files = content.files
+-- local remap = content.remap
+-- if files and remap then
+-- local n = next(files)
+-- local function iterator()
+-- while n do
+-- local k = n
+-- n = next(files,k)
+-- if find(k,pattern) then
+-- return files[k], remap and remap[k] or k
+-- end
+-- end
+-- end
+-- return iterator
+-- end
+-- end
+-- return nothing
+-- end
+
+function resolvers.filtered_from_content(content,pattern)
+ if content and type(pattern) == "string" then
+ local pattern = lower(pattern)
+ local files = content.files -- we could store the sorted list
+ local remap = content.remap
+ if files and remap then
+ local f = sortedkeys(files)
+ local n = #f
+ local i = 0
+ local function iterator()
+ while i < n do
+ i = i + 1
+ local k = f[i]
+ if find(k,pattern) then
+ return files[k], remap and remap[k] or k
+ end
+ end
+ end
+ return iterator
+ end
+ end
+ return nothing
+end
+
+-- inspect(resolvers.simplescanfiles("e:/temporary/mb-mp"))
+-- inspect(resolvers.scanfiles("e:/temporary/mb-mp"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-fil.lua b/Master/texmf-dist/tex/context/base/mkiv/data-fil.lua
new file mode 100644
index 00000000000..b699fc9e38f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-fil.lua
@@ -0,0 +1,113 @@
+if not modules then modules = { } end modules ['data-fil'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_files = logs.reporter("resolvers","files")
+
+local resolvers = resolvers
+local resolveprefix = resolvers.resolve
+
+local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
+local locators, hashers, generators, concatinators = resolvers.locators, resolvers.hashers, resolvers.generators, resolvers.concatinators
+
+local checkgarbage = utilities.garbagecollector and utilities.garbagecollector.check
+
+function locators.file(specification)
+ local filename = specification.filename
+ local realname = resolveprefix(filename) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
+ if trace_locating then
+ report_files("file locator %a found as %a",filename,realname)
+ end
+ resolvers.appendhash('file',filename,true) -- cache
+ elseif trace_locating then
+ report_files("file locator %a not found",filename)
+ end
+end
+
+function hashers.file(specification)
+ local pathname = specification.filename
+ local content = caches.loadcontent(pathname,'files')
+ resolvers.registerfilehash(pathname,content,content==nil)
+end
+
+function generators.file(specification)
+ local pathname = specification.filename
+ local content = resolvers.scanfiles(pathname,false,true) -- scan once
+ resolvers.registerfilehash(pathname,content,true)
+end
+
+concatinators.file = file.join
+
+function finders.file(specification,filetype)
+ local filename = specification.filename
+ local foundname = resolvers.findfile(filename,filetype)
+ if foundname and foundname ~= "" then
+ if trace_locating then
+ report_files("file finder: %a found",filename)
+ end
+ return foundname
+ else
+ if trace_locating then
+ report_files("file finder: %a not found",filename)
+ end
+ return finders.notfound()
+ end
+end
+
+-- The default textopener will be overloaded later on.
+
+function openers.helpers.textopener(tag,filename,f)
+ return {
+ reader = function() return f:read () end,
+ close = function() logs.show_close(filename) return f:close() end,
+ }
+end
+
+function openers.file(specification,filetype)
+ local filename = specification.filename
+ if filename and filename ~= "" then
+ local f = io.open(filename,"r")
+ if f then
+ if trace_locating then
+ report_files("file opener: %a opened",filename)
+ end
+ return openers.helpers.textopener("file",filename,f)
+ end
+ end
+ if trace_locating then
+ report_files("file opener: %a not found",filename)
+ end
+ return openers.notfound()
+end
+
+function loaders.file(specification,filetype)
+ local filename = specification.filename
+ if filename and filename ~= "" then
+ local f = io.open(filename,"rb")
+ if f then
+ logs.show_load(filename)
+ if trace_locating then
+ report_files("file loader: %a loaded",filename)
+ end
+ local s = f:read("*a") -- io.readall(f) is faster but we never have large files here
+ if checkgarbage then
+ checkgarbage(#s)
+ end
+ f:close()
+ if s then
+ return true, s, #s
+ end
+ end
+ end
+ if trace_locating then
+ report_files("file loader: %a not found",filename)
+ end
+ return loaders.notfound()
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-gen.lua b/Master/texmf-dist/tex/context/base/mkiv/data-gen.lua
new file mode 100644
index 00000000000..5a07558315b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-gen.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['data-gen'] = {
+ 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"
+}
+
+-- move generators here
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua
new file mode 100644
index 00000000000..c74ff2e04b2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua
@@ -0,0 +1,360 @@
+if not modules then modules = { } end modules ['data-ini'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local next, type, getmetatable, rawset = next, type, getmetatable, rawset
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
+local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
+local ostype, osname, osuname, ossetenv, osgetenv = os.type, os.name, os.uname, os.setenv, os.getenv
+
+local P, S, R, C, Cs, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.match
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
+local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
+
+local report_initialization = logs.reporter("resolvers","initialization")
+
+-- The code here used to be part of a data-res but for convenience we now split it over multiple
+-- files. As this file is now the starting point we introduce resolvers here. We also put some
+-- helpers here that later can be reimplemented of extended.
+
+resolvers = resolvers or { }
+local resolvers = resolvers
+
+-- We don't want the kpse library to kick in. Also, we want to be able to
+-- execute programs. Control over execution is implemented later.
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+
+if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then
+ local default_texmfcnf = kpse.default_texmfcnf()
+ -- looks more like context:
+ default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
+ default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
+ default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
+ default_texmfcnf = gsub(default_texmfcnf,"$HOME","home:")
+ --
+ environment.default_texmfcnf = default_texmfcnf
+end
+
+kpse = { original = kpse }
+
+setmetatable(kpse, {
+ __index = function(kp,name)
+ report_initialization("fatal error: kpse library is accessed (key: %s)",name)
+ os.exit()
+ end
+} )
+
+-- First we check a couple of environment variables. Some might be
+-- set already but we need then later on. We start with the system
+-- font path.
+
+do
+
+ local osfontdir = osgetenv("OSFONTDIR")
+
+ if osfontdir and osfontdir ~= "" then
+ -- ok
+ elseif osname == "windows" then
+ ossetenv("OSFONTDIR","c:/windows/fonts//")
+ elseif osname == "macosx" then
+ ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ end
+
+end
+
+-- Next comes the user's home path. We need this as later on we have
+-- to replace ~ with its value.
+
+do
+
+ local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
+
+ if not homedir or homedir == "" then
+ homedir = char(127) -- we need a value, later we wil trigger on it
+ end
+
+ homedir = file.collapsepath(homedir)
+
+ ossetenv("HOME", homedir) -- can be used in unix cnf files
+ ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
+
+ environment.homedir = homedir
+
+end
+
+-- The following code sets the name of the own binary and its
+-- path. This is fallback code as we have os.selfdir now.
+
+do
+
+ local args = environment.originalarguments or arg -- this needs a cleanup
+
+ if not environment.ownmain then
+ environment.ownmain = status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+
+ local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+ local ownpath = environment.ownpath or os.selfdir
+
+ ownbin = file.collapsepath(ownbin)
+ ownpath = file.collapsepath(ownpath)
+
+ if not ownpath or ownpath == "" or ownpath == "unset" then
+ ownpath = args[-1] or arg[-1]
+ ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
+ if not ownpath or ownpath == "" then
+ ownpath = args[-0] or arg[-0]
+ ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
+ end
+ local binary = ownbin
+ if not ownpath or ownpath == "" then
+ ownpath = ownpath and filedirname(binary)
+ end
+ if not ownpath or ownpath == "" then
+ if os.binsuffix ~= "" then
+ binary = file.replacesuffix(binary,os.binsuffix)
+ end
+ local path = osgetenv("PATH")
+ if path then
+ for p in gmatch(path,"[^"..io.pathseparator.."]+") do
+ local b = filejoin(p,binary)
+ if lfs.isfile(b) then
+ -- we assume that after changing to the path the currentdir function
+ -- resolves to the real location and use this side effect here; this
+ -- trick is needed because on the mac installations use symlinks in the
+ -- path instead of real locations
+ local olddir = lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp = lfs.currentdir()
+ if trace_locating and p ~= pp then
+ report_initialization("following symlink %a to %a",p,pp)
+ end
+ ownpath = pp
+ lfs.chdir(olddir)
+ else
+ if trace_locating then
+ report_initialization("unable to check path %a",p)
+ end
+ ownpath = p
+ end
+ break
+ end
+ end
+ end
+ end
+ if not ownpath or ownpath == "" then
+ ownpath = "."
+ report_initialization("forcing fallback to ownpath %a",ownpath)
+ elseif trace_locating then
+ report_initialization("using ownpath %a",ownpath)
+ end
+ end
+
+ environment.ownbin = ownbin
+ environment.ownpath = ownpath
+
+end
+
+resolvers.ownpath = environment.ownpath
+
+function resolvers.getownpath()
+ return environment.ownpath
+end
+
+-- The self variables permit us to use only a few (or even no)
+-- environment variables.
+
+do
+
+ local ownpath = environment.ownpath or dir.current()
+
+ if ownpath then
+ ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
+ ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
+ else
+ report_initialization("error: unable to locate ownpath")
+ os.exit()
+ end
+
+end
+
+-- The running os:
+
+-- todo: check is context sits here os.platform is more trustworthy
+-- that the bin check as mtx-update runs from another path
+
+local texos = environment.texos or osgetenv("TEXOS")
+local texmfos = environment.texmfos or osgetenv('SELFAUTODIR')
+
+if not texos or texos == "" then
+ texos = file.basename(texmfos)
+end
+
+ossetenv('TEXMFOS', texmfos) -- full bin path
+ossetenv('TEXOS', texos) -- partial bin parent
+ossetenv('SELFAUTOSYSTEM',os.platform) -- bonus
+
+environment.texos = texos
+environment.texmfos = texmfos
+
+-- The current root:
+
+local texroot = environment.texroot or osgetenv("TEXROOT")
+
+if not texroot or texroot == "" then
+ texroot = osgetenv('SELFAUTOPARENT')
+ ossetenv('TEXROOT',texroot)
+end
+
+environment.texroot = file.collapsepath(texroot)
+
+if type(profiler) == "table" and not jit then
+ directives.register("system.profile",function()
+ profiler.start("luatex-profile.log")
+ end)
+end
+
+-- a forward definition
+
+-- Because we use resolvers.resolve a lot later on, we will implement the basics here and
+-- add more later.
+
+local prefixes = utilities.storage.allocate()
+resolvers.prefixes = prefixes
+
+local resolved = { }
+local abstract = { }
+local dynamic = { }
+
+function resolvers.resetresolve(str)
+ resolved, abstract = { }, { }
+end
+
+function resolvers.allprefixes(separator)
+ local all = table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i] = all[i] .. ":"
+ end
+ end
+ return all
+end
+
+local function _resolve_(method,target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method .. ":" .. target
+ end
+end
+
+function resolvers.unresolve(str)
+ return abstract[str] or str
+end
+
+function resolvers.setdynamic(str)
+ dynamic[str] = true
+end
+
+-- home:xx;selfautoparent:xx;
+
+local pattern = Cs((C(R("az")^2) * P(":") * C((1-S(" \"\';,"))^1) / _resolve_ + P(1))^0)
+
+local prefix = C(R("az")^2) * P(":")
+local target = C((1-S(" \"\';,"))^1)
+local notarget = (#S(";,") + P(-1)) * Cc("")
+
+local p_resolve = Cs(((prefix * (target + notarget)) / _resolve_ + P(1))^0)
+local p_simple = prefix * P(-1)
+
+local function resolve(str) -- use schemes, this one is then for the commandline only
+ if type(str) == "table" then
+ local res = { }
+ for i=1,#str do
+ res[i] = resolve(str[i])
+ end
+ return res
+ end
+ -- already resolved
+ local res = resolved[str]
+ if res then
+ return res
+ end
+ -- simple resolving of (dynamic) methods
+ local simple = lpegmatch(p_simple,str)
+ local action = prefixes[simple]
+ if action then
+ local res = action(res)
+ if not dynamic[simple] then
+ resolved[simple] = res
+ abstract[res] = simple
+ end
+ return res
+ end
+ -- more extensive resolving (multiple too)
+ res = lpegmatch(p_resolve,str)
+ resolved[str] = res
+ abstract[res] = str
+ return res
+end
+
+resolvers.resolve = resolve
+
+if type(osuname) == "function" then
+
+ for k, v in next, osuname() do
+ if not prefixes[k] then
+ prefixes[k] = function() return v end
+ end
+ end
+
+end
+
+if ostype == "unix" then
+
+ -- We need to distringuish between a prefix and something else : so we
+ -- have a special repath variant for linux. Also, when a new prefix is
+ -- defined, we need to remake the matcher.
+
+ local pattern
+
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon = P(":")
+ for k, v in table.sortedpairs(prefixes) do
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ pattern = Cs((p * colon + colon/";" + P(1))^0)
+ end
+
+ makepattern()
+
+ table.setmetatablenewindex(prefixes,makepattern)
+
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+
+else -- already the default:
+
+ function resolvers.repath(str)
+ return str
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-inp.lua b/Master/texmf-dist/tex/context/base/mkiv/data-inp.lua
new file mode 100644
index 00000000000..97fb8904b91
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-inp.lua
@@ -0,0 +1,25 @@
+if not modules then modules = { } end modules ['data-inp'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local allocate = utilities.storage.allocate
+local resolvers = resolvers
+
+local methodhandler = resolvers.methodhandler
+local registermethod = resolvers.registermethod
+
+local finders = allocate { helpers = { }, notfound = function() end }
+local openers = allocate { helpers = { }, notfound = function() end }
+local loaders = allocate { helpers = { }, notfound = function() return false, nil, 0 end }
+
+registermethod("finders", finders, "uri")
+registermethod("openers", openers, "uri")
+registermethod("loaders", loaders, "uri")
+
+resolvers.finders = finders
+resolvers.openers = openers
+resolvers.loaders = loaders
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-lst.lua b/Master/texmf-dist/tex/context/base/mkiv/data-lst.lua
new file mode 100644
index 00000000000..e4621a6e16d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-lst.lua
@@ -0,0 +1,81 @@
+if not modules then modules = { } end modules ['data-lst'] = {
+ 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"
+}
+
+-- used in mtxrun, can be loaded later .. todo
+
+local rawget, type, next = rawget, type, next
+
+local find, concat, upper = string.find, table.concat, string.upper
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
+
+local resolvers = resolvers
+local listers = resolvers.listers or { }
+resolvers.listers = listers
+
+local resolveprefix = resolvers.resolve
+
+local report_lists = logs.reporter("resolvers","lists")
+
+local function tabstr(str)
+ if type(str) == 'table' then
+ return concat(str," | ")
+ else
+ return str
+ end
+end
+
+function listers.variables(pattern)
+ local instance = resolvers.instance
+ local environment = instance.environment
+ local variables = instance.variables
+ local expansions = instance.expansions
+ local pattern = upper(pattern or "")
+ local configured = { }
+ local order = instance.order
+ for i=1,#order do
+ for k, v in next, order[i] do
+ if v ~= nil and configured[k] == nil then
+ configured[k] = v
+ end
+ end
+ end
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
+ if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
+ report_lists(key)
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolveprefix(expansions[key])) or "unset")
+ end
+ end
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
+end
+
+local report_resolved = logs.reporter("system","resolved")
+
+function listers.configurations()
+ local configurations = resolvers.instance.specification
+ for i=1,#configurations do
+ report_resolved("file : %s",resolveprefix(configurations[i]))
+ end
+ report_resolved("")
+ local list = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
+ for i=1,#list do
+ local li = resolveprefix(list[i])
+ if lfs.isdir(li) then
+ report_resolved("path - %s",li)
+ else
+ report_resolved("path + %s",li)
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/data-lua.lua
new file mode 100644
index 00000000000..7c12a5940f5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-lua.lua
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['data-lua'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is now a plug in into l-lua (as we also use the extra paths elsewhere).
+
+local package, lpeg = package, lpeg
+
+local gsub = string.gsub
+local concat = table.concat
+local addsuffix = file.addsuffix
+
+local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match
+
+local luasuffixes = { 'tex', 'lua' }
+local libsuffixes = { 'lib' }
+local luaformats = { 'TEXINPUTS', 'LUAINPUTS' }
+local libformats = { 'CLUAINPUTS' }
+local helpers = package.helpers or { }
+local methods = helpers.methods or { }
+
+local resolvers = resolvers
+local resolveprefix = resolvers.resolve
+
+helpers.report = logs.reporter("resolvers","libraries")
+
+trackers.register("resolvers.libraries", function(v) helpers.trace = v end)
+trackers.register("resolvers.locating", function(v) helpers.trace = v end)
+
+helpers.sequence = {
+ "already loaded",
+ "preload table",
+ "lua variable format",
+ "lib variable format",
+ "lua extra list",
+ "lib extra list",
+ "path specification",
+ "cpath specification",
+ "all in one fallback",
+ "not loaded",
+}
+
+local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0)
+
+function helpers.cleanpath(path) -- hm, don't we have a helper for this?
+ return resolveprefix(lpegmatch(pattern,path))
+end
+
+local loadedaslib = helpers.loadedaslib
+local getextraluapaths = package.extraluapaths
+local getextralibpaths = package.extralibpaths
+local registerpath = helpers.registerpath
+local lualibfile = helpers.lualibfile
+
+local luaformatpaths
+local libformatpaths
+
+local function getluaformatpaths()
+ if not luaformatpaths then
+ luaformatpaths = { }
+ for i=1,#luaformats do
+ registerpath("lua format","lua",luaformatpaths,resolvers.expandedpathlistfromvariable(luaformats[i]))
+ end
+ end
+ return luaformatpaths
+end
+
+local function getlibformatpaths()
+ if not libformatpaths then
+ libformatpaths = { }
+ for i=1,#libformats do
+ registerpath("lib format","lib",libformatpaths,resolvers.expandedpathlistfromvariable(libformats[i]))
+ end
+ end
+ return libformatpaths
+end
+
+local function loadedbyformat(name,rawname,suffixes,islib,what)
+ local trace = helpers.trace
+ local report = helpers.report
+ for i=1,#suffixes do -- so we use findfile and not a lookup loop
+ local format = suffixes[i]
+ local resolved = resolvers.findfile(name,format) or ""
+ if trace then
+ report("%s format, identifying %a using format %a",what,name,format)
+ end
+ if resolved ~= "" then
+ if trace then
+ report("%s format, %a found on %a",what,name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
+ end
+ end
+ end
+end
+
+helpers.loadedbyformat = loadedbyformat
+
+-- print(lualibfile("bar"))
+-- print(lualibfile("foo.bar"))
+-- print(lualibfile("crap/foo...bar"))
+-- print(lualibfile("crap//foo.bar"))
+-- print(lualibfile("crap/../foo.bar"))
+-- print(lualibfile("crap/.././foo.bar"))
+
+-- alternatively we could split in path and base and temporary set the libpath to path
+
+-- we could build a list of relevant paths but for tracing it's better to have the
+-- whole lot (ok, we could skip the duplicates)
+
+methods["lua variable format"] = function(name)
+ if helpers.trace then
+ helpers.report("%s format, checking %s paths","lua",#getluaformatpaths()) -- call triggers building
+ end
+ return loadedbyformat(addsuffix(lualibfile(name),"lua"),name,luasuffixes,false,"lua")
+end
+
+methods["lib variable format"] = function(name)
+ if helpers.trace then
+ helpers.report("%s format, checking %s paths","lib",#getlibformatpaths()) -- call triggers building
+ end
+ return loadedbyformat(addsuffix(lualibfile(name),os.libsuffix),name,libsuffixes,true,"lib")
+end
+
+-- package.extraclibpath(environment.ownpath)
+
+resolvers.loadlualib = require -- hm
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-met.lua b/Master/texmf-dist/tex/context/base/mkiv/data-met.lua
new file mode 100644
index 00000000000..4e8a48f50e1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-met.lua
@@ -0,0 +1,141 @@
+if not modules then modules = { } end modules ['data-met'] = {
+ version = 1.100,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find, format = string.find, string.format
+local sequenced = table.sequenced
+local addurlscheme, urlhashed = url.addscheme, url.hashed
+local getcurrentdir = lfs.currentdir
+
+local trace_locating = false
+local trace_methods = false
+
+trackers.register("resolvers.locating", function(v) trace_methods = v end)
+trackers.register("resolvers.methods", function(v) trace_methods = v end)
+
+--~ trace_methods = true
+
+local report_methods = logs.reporter("resolvers","methods")
+
+local allocate = utilities.storage.allocate
+
+local resolvers = resolvers
+
+local registered = { }
+
+local function splitmethod(filename) -- todo: filetype in specification
+ if not filename then
+ return { scheme = "unknown", original = filename }
+ end
+ if type(filename) == "table" then
+ return filename -- already split
+ end
+ filename = file.collapsepath(filename,".") -- hm, we should keep ./ in some cases
+
+ if not find(filename,"://",1,true) then
+ return { scheme = "file", path = filename, original = filename, filename = filename }
+ end
+ local specification = url.hashed(filename)
+ if not specification.scheme or specification.scheme == "" then
+ return { scheme = "file", path = filename, original = filename, filename = filename }
+ else
+ return specification
+ end
+end
+
+-- local function splitmethod(filename) -- todo: filetype in specification
+-- if not filename then
+-- return { scheme = "unknown", original = filename }
+-- end
+-- if type(filename) == "table" then
+-- return filename -- already split
+-- end
+-- return url.hashed(filename)
+-- end
+
+resolvers.splitmethod = splitmethod -- bad name but ok
+
+-- the second argument is always analyzed (saves time later on) and the original
+-- gets passed as original but also as argument
+
+local function methodhandler(what,first,...) -- filename can be nil or false
+ local method = registered[what]
+ if method then
+ local how, namespace = method.how, method.namespace
+ if how == "uri" or how == "url" then
+ local specification = splitmethod(first)
+ local scheme = specification.scheme
+ local resolver = namespace and namespace[scheme]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
+ end
+ return resolver(specification,...)
+ else
+ resolver = namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
+ end
+ return resolver(specification,...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
+ end
+ end
+ elseif how == "tag" then
+ local resolver = namespace and namespace[first]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,first)
+ end
+ return resolver(...)
+ else
+ resolver = namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
+ end
+ return resolver(...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
+ end
+ end
+ end
+ else
+ report_methods("resolving, invalid method %a")
+ end
+end
+
+resolvers.methodhandler = methodhandler
+
+function resolvers.registermethod(name,namespace,how)
+ registered[name] = { how = how or "tag", namespace = namespace }
+ namespace["byscheme"] = function(scheme,filename,...)
+ if scheme == "file" then
+ return methodhandler(name,filename,...)
+ else
+ return methodhandler(name,addurlscheme(filename,scheme),...)
+ end
+ end
+end
+
+local concatinators = allocate { notfound = file.join } -- concatinate paths
+local locators = allocate { notfound = function() end } -- locate databases
+local hashers = allocate { notfound = function() end } -- load databases
+local generators = allocate { notfound = function() end } -- generate databases
+
+resolvers.concatinators = concatinators
+resolvers.locators = locators
+resolvers.hashers = hashers
+resolvers.generators = generators
+
+local registermethod = resolvers.registermethod
+
+registermethod("concatinators",concatinators,"tag")
+registermethod("locators", locators, "uri")
+registermethod("hashers", hashers, "uri")
+registermethod("generators", generators, "uri")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-out.lua b/Master/texmf-dist/tex/context/base/mkiv/data-out.lua
new file mode 100644
index 00000000000..11304c2ced3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-out.lua
@@ -0,0 +1,18 @@
+if not modules then modules = { } end modules ['data-out'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local allocate = utilities.storage.allocate
+local resolvers = resolvers
+
+local registermethod = resolvers.registermethod
+
+local savers = allocate { helpers = { } }
+
+resolvers.savers = savers
+
+registermethod("savers", savers, "uri")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua b/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua
new file mode 100644
index 00000000000..1c5016f8644
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua
@@ -0,0 +1,142 @@
+if not modules then modules = { } end modules ['data-pre'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local resolvers = resolvers
+local prefixes = resolvers.prefixes
+
+local cleanpath = resolvers.cleanpath
+local findgivenfile = resolvers.findgivenfile
+local expansion = resolvers.expansion
+local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
+
+local basename = file.basename
+local dirname = file.dirname
+local joinpath = file.join
+
+local isfile = lfs.isfile
+
+prefixes.environment = function(str)
+ return cleanpath(expansion(str))
+end
+
+local function relative(str,n)
+ if not isfile(str) then
+ local pstr = "./" .. str
+ if isfile(pstr) then
+ str = pstr
+ else
+ local p = "../"
+ for i=1,n or 2 do
+ local pstr = p .. str
+ if isfile(pstr) then
+ str = pstr
+ break
+ else
+ p = p .. "../"
+ end
+ end
+ end
+ end
+ return cleanpath(str)
+end
+
+local function locate(str)
+ local fullname = findgivenfile(str) or ""
+ return cleanpath(fullname ~= "" and fullname or str)
+end
+
+prefixes.relative = relative
+prefixes.locate = locate
+
+prefixes.auto = function(str)
+ local fullname = relative(str)
+ if not isfile(fullname) then
+ fullname = locate(str)
+ end
+ return fullname
+end
+
+prefixes.filename = function(str)
+ local fullname = findgivenfile(str) or ""
+ return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+end
+
+prefixes.pathname = function(str)
+ local fullname = findgivenfile(str) or ""
+ return cleanpath(dirname((fullname ~= "" and fullname) or str))
+end
+
+prefixes.selfautoloc = function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
+end
+
+prefixes.selfautoparent = function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
+end
+
+prefixes.selfautodir = function(str)
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
+end
+
+prefixes.home = function(str)
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+
+prefixes.env = prefixes.environment
+prefixes.rel = prefixes.relative
+prefixes.loc = prefixes.locate
+prefixes.kpse = prefixes.locate
+prefixes.full = prefixes.locate
+prefixes.file = prefixes.filename
+prefixes.path = prefixes.pathname
+
+-- This one assumes that inputstack is set (used in the tex loader). It is a momentary resolve
+-- as the top of the input stack changes.
+
+local function toppath()
+ local inputstack = resolvers.inputstack -- dependency, actually the code should move but it's
+ if not inputstack then -- more convenient to keep it here
+ return "."
+ end
+ local pathname = dirname(inputstack[#inputstack] or "")
+ if pathname == "" then
+ return "."
+ else
+ return pathname
+ end
+end
+
+-- The next variant is similar but bound to explicitly registered paths. Practice should
+-- show if that gives the same results as the previous one. It is meant for a project
+-- stucture.
+
+local function jobpath()
+ local path = resolvers.stackpath()
+ if not path or path == "" then
+ return "."
+ else
+ return path
+ end
+end
+
+resolvers.toppath = toppath
+resolvers.jobpath = jobpath
+
+-- This hook sit into the resolver:
+
+prefixes.toppath = function(str) return cleanpath(joinpath(toppath(),str)) end -- str can be nil or empty
+prefixes.jobpath = function(str) return cleanpath(joinpath(jobpath(),str)) end -- str can be nil or empty
+
+resolvers.setdynamic("toppath")
+resolvers.setdynamic("jobpath")
+
+-- for a while (obsolete):
+
+prefixes.jobfile = prefixes.jobpath
+
+resolvers.setdynamic("jobfile")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-res.lua b/Master/texmf-dist/tex/context/base/mkiv/data-res.lua
new file mode 100644
index 00000000000..831ad881c2b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-res.lua
@@ -0,0 +1,1885 @@
+if not modules then modules = { } end modules ['data-res'] = {
+ 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",
+}
+
+-- In practice we will work within one tds tree, but i want to keep
+-- the option open to build tools that look at multiple trees, which is
+-- why we keep the tree specific data in a table. We used to pass the
+-- instance but for practical purposes we now avoid this and use a
+-- instance variable. We always have one instance active (sort of global).
+
+-- I will reimplement this module ... way too fuzzy now and we can work
+-- with some sensible constraints as it is only is used for context.
+
+-- 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 next, type, rawget = next, type, rawget
+local os = os
+
+local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+local formatters = string.formatters
+local filedirname = file.dirname
+local filebasename = file.basename
+local suffixonly = file.suffixonly
+local addsuffix = file.addsuffix
+local removesuffix = file.removesuffix
+local filejoin = file.join
+local collapsepath = file.collapsepath
+local joinpath = file.joinpath
+local is_qualified_path = file.is_qualified_path
+
+local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
+
+local getcurrentdir = lfs.currentdir
+local isfile = lfs.isfile
+local isdir = lfs.isdir
+
+local setmetatableindex = table.setmetatableindex
+local luasuffixes = utilities.lua.suffixes
+
+local trace_locating = false trackers .register("resolvers.locating", function(v) trace_locating = v end)
+local trace_detail = false trackers .register("resolvers.details", function(v) trace_detail = v end)
+local trace_expansions = false trackers .register("resolvers.expansions", function(v) trace_expansions = v end)
+local trace_paths = false trackers .register("resolvers.paths", function(v) trace_paths = v end)
+local resolve_otherwise = true directives.register("resolvers.otherwise", function(v) resolve_otherwise = v end)
+
+local report_resolving = logs.reporter("resolvers","resolving")
+
+local resolvers = resolvers
+
+local expandedpathfromlist = resolvers.expandedpathfromlist
+local checkedvariable = resolvers.checkedvariable
+local splitconfigurationpath = resolvers.splitconfigurationpath
+local methodhandler = resolvers.methodhandler
+local filtered = resolvers.filtered_from_content
+local lookup = resolvers.get_from_content
+local cleanpath = resolvers.cleanpath
+local resolveprefix = resolvers.resolve
+
+local initializesetter = utilities.setters.initialize
+
+local ostype, osname, osenv, ossetenv, osgetenv = os.type, os.name, os.env, os.setenv, os.getenv
+
+resolvers.cacheversion = "1.100"
+resolvers.configbanner = ""
+resolvers.homedir = environment.homedir
+resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
+resolvers.luacnfname = "texmfcnf.lua"
+resolvers.luacnfstate = "unknown"
+
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead (for instance) use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautoloc:
+-- selfautoloc:/share/texmf-local/web2c
+-- selfautoloc:/share/texmf-dist/web2c
+-- selfautoloc:/share/texmf/web2c
+-- selfautoloc:/texmf-local/web2c
+-- selfautoloc:/texmf-dist/web2c
+-- selfautoloc:/texmf/web2c
+-- selfautodir:
+-- selfautodir:/share/texmf-local/web2c
+-- selfautodir:/share/texmf-dist/web2c
+-- selfautodir:/share/texmf/web2c
+-- selfautodir:/texmf-local/web2c
+-- selfautodir:/texmf-dist/web2c
+-- selfautodir:/texmf/web2c
+-- selfautoparent:/../texmf-local/web2c
+-- selfautoparent:
+-- selfautoparent:/share/texmf-local/web2c
+-- selfautoparent:/share/texmf-dist/web2c
+-- selfautoparent:/share/texmf/web2c
+-- selfautoparent:/texmf-local/web2c
+-- selfautoparent:/texmf-dist/web2c
+-- selfautoparent:/texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+-- This is a real mess: you don't want to know what creepy paths end up in the default
+-- configuration spec, for instance nested texmf- paths. I'd rather get away from it and
+-- specify a proper search sequence but alas ... it is not permitted in texlive and there
+-- is no way to check if we run a minimals as texmf-context is not in that spec. It's a
+-- compiled-in permutation of historics with the selfautoloc, selfautodir, selfautoparent
+-- resulting in weird combinations. So, when we eventually check the 30 something paths
+-- we also report weird ones, with weird being: (1) duplicate /texmf or (2) no /web2c in
+-- the names.
+
+if environment.default_texmfcnf then
+ resolvers.luacnfspec = "home:texmf/web2c;" .. environment.default_texmfcnf -- texlive + home: for taco etc
+else
+ resolvers.luacnfspec = concat ( {
+ "home:texmf/web2c",
+ "selfautoparent:/texmf-local/web2c",
+ "selfautoparent:/texmf-context/web2c",
+ "selfautoparent:/texmf-dist/web2c",
+ "selfautoparent:/texmf/web2c",
+ }, ";")
+end
+
+local unset_variable = "unset"
+
+local formats = resolvers.formats
+local suffixes = resolvers.suffixes
+local usertypes = resolvers.usertypes
+local dangerous = resolvers.dangerous
+local suffixmap = resolvers.suffixmap
+
+resolvers.defaultsuffixes = { "tex" } -- "mkiv", "cld" -- too tricky
+
+resolvers.instance = resolvers.instance or nil -- the current one (slow access)
+local instance = resolvers.instance or nil -- the current one (fast access)
+
+-- An instance has an environment (coming from the outside, kept raw), variables
+-- (coming from the configuration file), and expansions (variables with nested
+-- variables replaced). One can push something into the outer environment and
+-- its internal copy, but only the later one will be the raw unprefixed variant.
+
+function resolvers.setenv(key,value,raw)
+ if instance then
+ -- this one will be consulted first when we stay inside
+ -- the current environment (prefixes are not resolved here)
+ instance.environment[key] = value
+ -- we feed back into the environment, and as this is used
+ -- by other applications (via os.execute) we need to make
+ -- sure that prefixes are resolve
+ ossetenv(key,raw and value or resolveprefix(value))
+ end
+end
+
+-- Beware we don't want empty here as this one can be called early on
+-- and therefore we use rawget.
+
+local function getenv(key)
+ local value = rawget(instance.environment,key)
+ if value and value ~= "" then
+ return value
+ else
+ local e = osgetenv(key)
+ return e ~= nil and e ~= "" and checkedvariable(e) or ""
+ end
+end
+
+resolvers.getenv = getenv
+resolvers.env = getenv
+
+-- We are going to use some metatable trickery where we backtrack from
+-- expansion to variable to environment.
+
+local function resolvevariable(k)
+ return instance.expansions[k]
+end
+
+local dollarstripper = lpeg.stripper("$")
+local inhibitstripper = P("!")^0 * Cs(P(1)^0)
+local backslashswapper = lpeg.replacer("\\","/")
+
+local somevariable = P("$") / ""
+local somekey = C(R("az","AZ","09","__","--")^1)
+local somethingelse = P(";") * ((1-S("!{}/\\"))^1 * P(";") / "")
+ + P(";") * (P(";") / "")
+ + P(1)
+local variableexpander = Cs( (somevariable * (somekey/resolvevariable) + somethingelse)^1 )
+
+local cleaner = P("\\") / "/" + P(";") * S("!{}/\\")^0 * P(";")^1 / ";"
+local variablecleaner = Cs((cleaner + P(1))^0)
+
+local somevariable = R("az","AZ","09","__","--")^1 / resolvevariable
+local variable = (P("$")/"") * (somevariable + (P("{")/"") * somevariable * (P("}")/""))
+local variableresolver = Cs((variable + P(1))^0)
+
+local function expandedvariable(var)
+ return lpegmatch(variableexpander,var) or var
+end
+
+function resolvers.newinstance() -- todo: all vars will become lowercase and alphanum only
+
+ -- normally we only need one instance but for special cases we can (re)load one so
+ -- we stick to this model.
+
+ if trace_locating then
+ report_resolving("creating instance")
+ end
+
+ local environment, variables, expansions, order = allocate(), allocate(), allocate(), allocate()
+
+ local newinstance = {
+ environment = environment,
+ variables = variables,
+ expansions = expansions,
+ order = order,
+ files = allocate(),
+ setups = allocate(),
+ found = allocate(),
+ foundintrees = allocate(),
+ hashes = allocate(),
+ hashed = allocate(),
+ pathlists = false,-- delayed
+ specification = allocate(),
+ lists = allocate(),
+ data = allocate(), -- only for loading
+ fakepaths = allocate(),
+ remember = true,
+ diskcache = true,
+ renewcache = false,
+ renewtree = false,
+ loaderror = false,
+ savelists = true,
+ pattern = nil, -- lists
+ force_suffixes = true,
+ pathstack = { },
+ }
+
+ setmetatableindex(variables,function(t,k)
+ local v
+ for i=1,#order do
+ v = order[i][k]
+ if v ~= nil then
+ t[k] = v
+ return v
+ end
+ end
+ if v == nil then
+ v = ""
+ end
+ t[k] = v
+ return v
+ end)
+
+ setmetatableindex(environment, function(t,k)
+ local v = osgetenv(k)
+ if v == nil then
+ v = variables[k]
+ end
+ if v ~= nil then
+ v = checkedvariable(v) or ""
+ end
+ v = resolvers.repath(v) -- for taco who has a : separated osfontdir
+ t[k] = v
+ return v
+ end)
+
+ setmetatableindex(expansions, function(t,k)
+ local v = environment[k]
+ if type(v) == "string" then
+ v = lpegmatch(variableresolver,v)
+ v = lpegmatch(variablecleaner,v)
+ end
+ t[k] = v
+ return v
+ end)
+
+ return newinstance
+
+end
+
+function resolvers.setinstance(someinstance) -- only one instance is active
+ instance = someinstance
+ resolvers.instance = someinstance
+ return someinstance
+end
+
+function resolvers.reset()
+ return resolvers.setinstance(resolvers.newinstance())
+end
+
+local function reset_hashes()
+ instance.lists = { }
+ instance.pathlists = false
+ instance.found = { }
+end
+
+local function reset_caches()
+ instance.lists = { }
+ instance.pathlists = false
+end
+
+local slash = P("/")
+
+local pathexpressionpattern = Cs ( -- create lpeg instead (2013/2014)
+ Cc("^") * (
+ Cc("%") * S(".-")
+ + slash^2 * P(-1) / "/.*"
+ -- + slash^2 / "/.-/"
+ -- + slash^2 / "/[^/]*/*" -- too general
+ + slash^2 / "/"
+ + (1-slash) * P(-1) * Cc("/")
+ + P(1)
+ )^1 * Cc("$") -- yes or no $
+)
+
+local cache = { }
+
+local function makepathexpression(str)
+ if str == "." then
+ return "^%./$"
+ else
+ local c = cache[str]
+ if not c then
+ c = lpegmatch(pathexpressionpattern,str)
+ cache[str] = c
+ end
+ return c
+ end
+end
+
+local function reportcriticalvariables(cnfspec)
+ if trace_locating then
+ for i=1,#resolvers.criticalvars do
+ local k = resolvers.criticalvars[i]
+ local v = resolvers.getenv(k) or "unknown" -- this one will not resolve !
+ report_resolving("variable %a set to %a",k,v)
+ end
+ report_resolving()
+ if cnfspec then
+ report_resolving("using configuration specification %a",type(cnfspec) == "table" and concat(cnfspec,",") or cnfspec)
+ end
+ report_resolving()
+ end
+ reportcriticalvariables = function() end
+end
+
+local function identify_configuration_files()
+ local specification = instance.specification
+ if #specification == 0 then
+ local cnfspec = getenv("TEXMFCNF")
+ if cnfspec == "" then
+ cnfspec = resolvers.luacnfspec
+ resolvers.luacnfstate = "default"
+ else
+ resolvers.luacnfstate = "environment"
+ end
+ reportcriticalvariables(cnfspec)
+ local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
+ local luacnfname = resolvers.luacnfname
+ for i=1,#cnfpaths do
+ local filepath = cnfpaths[i]
+ local filename = collapsepath(filejoin(filepath,luacnfname))
+ local realname = resolveprefix(filename) -- can still have "//" ... needs checking
+ -- todo: environment.skipweirdcnfpaths directive
+ if trace_locating then
+ local fullpath = gsub(resolveprefix(collapsepath(filepath)),"//","/")
+ local weirdpath = find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
+ report_resolving("looking for %a on %s path %a from specification %a",luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
+ end
+ if isfile(realname) then
+ specification[#specification+1] = filename -- unresolved as we use it in matching, relocatable
+ if trace_locating then
+ report_resolving("found configuration file %a",realname)
+ end
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("configuration files already identified")
+ end
+end
+
+local function load_configuration_files()
+ local specification = instance.specification
+ if #specification > 0 then
+ local luacnfname = resolvers.luacnfname
+ for i=1,#specification do
+ local filename = specification[i]
+ local pathname = filedirname(filename)
+ local filename = filejoin(pathname,luacnfname)
+ local realname = resolveprefix(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local setups = instance.setups
+ local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolveprefix(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file %a",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
+ data = data and data.content
+ if data then
+ if trace_locating then
+ report_resolving("loading configuration file %a",filename)
+ report_resolving()
+ end
+ local variables = data.variables or { }
+ local warning = false
+ for k, v in next, data do
+ local variant = type(v)
+ if variant == "table" then
+ initializesetter(filename,k,v)
+ elseif variables[k] == nil then
+ if trace_locating and not warning then
+ report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
+ k,resolveprefix(filename))
+ warning = true
+ end
+ variables[k] = v
+ end
+ end
+ setups[pathname] = variables
+ if resolvers.luacnfstate == "default" then
+ -- the following code is not tested
+ local cnfspec = variables["TEXMFCNF"]
+ if cnfspec then
+ if trace_locating then
+ report_resolving("reloading configuration due to TEXMF redefinition")
+ end
+ -- we push the value into the main environment (osenv) so
+ -- that it takes precedence over the default one and therefore
+ -- also over following definitions
+ resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes
+ -- we now identify and load the specified configuration files
+ instance.specification = { }
+ identify_configuration_files()
+ load_configuration_files()
+ -- we prevent further overload of the configuration variable
+ resolvers.luacnfstate = "configuration"
+ -- we quit the outer loop
+ break
+ end
+ end
+
+ else
+ if trace_locating then
+ report_resolving("skipping configuration file %a (no content)",filename)
+ end
+ setups[pathname] = { }
+ instance.loaderror = true
+ end
+ elseif trace_locating then
+ report_resolving("skipping configuration file %a (no valid format)",filename)
+ end
+ instance.order[#instance.order+1] = instance.setups[pathname]
+ if instance.loaderror then
+ break
+ end
+ end
+ elseif trace_locating then
+ report_resolving("warning: no lua configuration files found")
+ end
+end
+
+-- scheme magic ... database loading
+
+local function load_file_databases()
+ instance.loaderror, instance.files = false, allocate()
+ if not instance.renewcache then
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ resolvers.hashers.byscheme(hash.type,hash.name)
+ if instance.loaderror then break end
+ end
+ end
+end
+
+local function locate_file_databases()
+ -- todo: cache:// and tree:// (runtime)
+ local texmfpaths = resolvers.expandedpathlist("TEXMF")
+ if #texmfpaths > 0 then
+ for i=1,#texmfpaths do
+ local path = collapsepath(texmfpaths[i])
+ path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing /
+ local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
+ if stripped ~= "" then
+ local runtime = stripped == path
+ path = cleanpath(path)
+ local spec = resolvers.splitmethod(stripped)
+ if runtime and (spec.noscheme or spec.scheme == "file") then
+ stripped = "tree:///" .. stripped
+ elseif spec.scheme == "cache" or spec.scheme == "file" then
+ stripped = spec.path
+ end
+ if trace_locating then
+ if runtime then
+ report_resolving("locating list of %a (runtime) (%s)",path,stripped)
+ else
+ report_resolving("locating list of %a (cached)",path)
+ end
+ end
+ methodhandler('locators',stripped)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("no texmf paths are defined (using TEXMF)")
+ end
+end
+
+local function generate_file_databases()
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ methodhandler('generators',hash.name)
+ end
+ if trace_locating then
+ report_resolving()
+ end
+end
+
+local function save_file_databases() -- will become cachers
+ for i=1,#instance.hashes do
+ local hash = instance.hashes[i]
+ local cachename = hash.name
+ if hash.cache then
+ local content = instance.files[cachename]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",cachename)
+ end
+ caches.savecontent(cachename,"files",content)
+ elseif trace_locating then
+ report_resolving("not saving runtime tree %a",cachename)
+ end
+ end
+end
+
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree %a from %a",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree %a",hashname)
+ end
+ end
+ local realpath = resolveprefix(hashname)
+ if isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path %a",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path %a",realpath)
+ end
+ end
+end
+
+local function load_databases()
+ locate_file_databases()
+ if instance.diskcache and not instance.renewcache then
+ load_file_databases()
+ if instance.loaderror then
+ generate_file_databases()
+ save_file_databases()
+ end
+ else
+ generate_file_databases()
+ if instance.renewcache then
+ save_file_databases()
+ end
+ end
+end
+
+function resolvers.appendhash(type,name,cache)
+ -- safeguard ... tricky as it's actually a bug when seen twice
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a appended",name)
+ end
+ insert(instance.hashes, { type = type, name = name, cache = cache } )
+ instance.hashed[name] = cache
+ end
+end
+
+function resolvers.prependhash(type,name,cache)
+ -- safeguard ... tricky as it's actually a bug when seen twice
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a prepended",name)
+ end
+ insert(instance.hashes, 1, { type = type, name = name, cache = cache } )
+ instance.hashed[name] = cache
+ end
+end
+
+function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
+ local t = resolvers.splitpath(getenv("TEXMF")) -- okay?
+ insert(t,1,specification)
+ local newspec = concat(t,",") -- not ;
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"] = newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"] = newspec
+ else
+ -- weird
+ end
+ reset_hashes()
+end
+
+function resolvers.splitexpansions()
+ local ie = instance.expansions
+ for k,v in next, ie do
+ local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
+ for kk=1,#p do
+ local vv = p[kk]
+ if vv ~= "" and not h[vv] then
+ tn = tn + 1
+ t[tn] = vv
+ h[vv] = true
+ end
+ end
+ if #t > 1 then
+ ie[k] = t
+ else
+ ie[k] = t[1]
+ end
+ end
+end
+
+-- end of split/join code
+
+-- we used to have 'files' and 'configurations' so therefore the following
+-- shared function
+
+function resolvers.datastate()
+ return caches.contentstate()
+end
+
+function resolvers.variable(name)
+ local name = name and lpegmatch(dollarstripper,name)
+ local result = name and instance.variables[name]
+ return result ~= nil and result or ""
+end
+
+function resolvers.expansion(name)
+ local name = name and lpegmatch(dollarstripper,name)
+ local result = name and instance.expansions[name]
+ return result ~= nil and result or ""
+end
+
+function resolvers.unexpandedpathlist(str)
+ local pth = resolvers.variable(str)
+ local lst = resolvers.splitpath(pth)
+ return expandedpathfromlist(lst)
+end
+
+function resolvers.unexpandedpath(str)
+ return joinpath(resolvers.unexpandedpathlist(str))
+end
+
+function resolvers.pushpath(name)
+ local pathstack = instance.pathstack
+ local lastpath = pathstack[#pathstack]
+ local pluspath = filedirname(name)
+ if lastpath then
+ lastpath = collapsepath(filejoin(lastpath,pluspath))
+ else
+ lastpath = collapsepath(pluspath)
+ end
+ insert(pathstack,lastpath)
+ if trace_paths then
+ report_resolving("pushing path %a",lastpath)
+ end
+end
+
+function resolvers.poppath()
+ local pathstack = instance.pathstack
+ if trace_paths and #pathstack > 0 then
+ report_resolving("popping path %a",pathstack[#pathstack])
+ end
+ remove(pathstack)
+end
+
+function resolvers.stackpath()
+ local pathstack = instance.pathstack
+ local currentpath = pathstack[#pathstack]
+ return currentpath ~= "" and currentpath or nil
+end
+
+local done = { }
+
+function resolvers.resetextrapath()
+ local ep = instance.extra_paths
+ if not ep then
+ done = { }
+ instance.extra_paths = { }
+ elseif #ep > 0 then
+ done = { }
+ reset_caches()
+ end
+end
+
+function resolvers.registerextrapath(paths,subpaths)
+ if not subpaths or subpaths == "" then
+ if not paths or path == "" then
+ return -- invalid spec
+ elseif done[paths] then
+ return -- already done
+ end
+ end
+ local paths = settings_to_array(paths)
+ local subpaths = settings_to_array(subpaths)
+ local ep = instance.extra_paths or { }
+ local oldn = #ep
+ local newn = oldn
+ local nofpaths = #paths
+ local nofsubpaths = #subpaths
+ if nofpaths > 0 then
+ if nofsubpaths > 0 then
+ for i=1,nofpaths do
+ local p = paths[i]
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
+ local ps = p .. "/" .. s
+ if not done[ps] then
+ newn = newn + 1
+ ep[newn] = cleanpath(ps)
+ done[ps] = true
+ end
+ end
+ end
+ else
+ for i=1,nofpaths do
+ local p = paths[i]
+ if not done[p] then
+ newn = newn + 1
+ ep[newn] = cleanpath(p)
+ done[p] = true
+ end
+ end
+ end
+ elseif nofsubpaths > 0 then
+ for i=1,oldn do
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
+ local ps = ep[i] .. "/" .. s
+ if not done[ps] then
+ newn = newn + 1
+ ep[newn] = cleanpath(ps)
+ done[ps] = true
+ end
+ end
+ end
+ end
+ if newn > 0 then
+ instance.extra_paths = ep -- register paths
+ end
+ if newn ~= oldn then
+ reset_caches()
+ end
+end
+
+function resolvers.pushextrapath(path)
+ local paths = settings_to_array(path)
+ if instance.extra_stack then
+ insert(instance.extra_stack,1,paths)
+ else
+ instance.extra_stack = { paths }
+ end
+ reset_caches()
+end
+
+function resolvers.popextrapath()
+ if instance.extra_stack then
+ reset_caches()
+ return remove(instance.extra_stack,1)
+ end
+end
+
+local function made_list(instance,list,extra_too)
+ local done = { }
+ local new = { }
+ local newn = 0
+ -- a helper
+ local function add(p)
+ for k=1,#p do
+ local v = p[k]
+ if not done[v] then
+ done[v] = true
+ newn = newn + 1
+ new[newn] = v
+ end
+ end
+ end
+ -- honour . .. ../.. but only when at the start
+ for k=1,#list do
+ local v = list[k]
+ if done[v] then
+ -- skip
+ elseif find(v,"^[%.%/]$") then
+ done[v] = true
+ newn = newn + 1
+ new[newn] = v
+ else
+ break
+ end
+ end
+ if extra_too then
+ -- first the stacked paths
+ local es = instance.extra_stack
+ if es and #es > 0 then
+ for k=1,#es do
+ add(es[k])
+ end
+ end
+ -- then the extra paths
+ local ep = instance.extra_paths
+ if ep and #ep > 0 then
+ add(ep)
+ end
+ end
+ -- last the formal paths
+ add(list)
+ return new
+end
+
+function resolvers.cleanpathlist(str)
+ local t = resolvers.expandedpathlist(str)
+ if t then
+ for i=1,#t do
+ t[i] = collapsepath(cleanpath(t[i]))
+ end
+ end
+ return t
+end
+
+function resolvers.expandpath(str)
+ return joinpath(resolvers.expandedpathlist(str))
+end
+
+function resolvers.expandedpathlist(str,extra_too)
+ if not str then
+ return { }
+ elseif instance.savelists then -- hm, what if two cases, with and without extra_too
+ str = lpegmatch(dollarstripper,str)
+ local lists = instance.lists
+ local lst = lists[str]
+ if not lst then
+ local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
+ lst = expandedpathfromlist(l)
+ lists[str] = lst
+ end
+ return lst
+ else
+ local lst = resolvers.splitpath(resolvers.expansion(str))
+ return made_list(instance,expandedpathfromlist(lst),extra_too)
+ end
+end
+
+function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ //
+ str = lpegmatch(dollarstripper,str)
+ local tmp = resolvers.variableofformatorsuffix(str)
+ return resolvers.expandedpathlist(tmp ~= "" and tmp or str)
+end
+
+function resolvers.expandpathfromvariable(str)
+ return joinpath(resolvers.expandedpathlistfromvariable(str))
+end
+
+function resolvers.cleanedpathlist(v) -- can be cached if needed
+ local t = resolvers.expandedpathlist(v)
+ for i=1,#t do
+ t[i] = resolvers.resolve(resolvers.cleanpath(t[i]))
+ end
+ return t
+end
+
+function resolvers.expandbraces(str) -- output variable and brace expansion of STRING
+-- local ori = resolvers.variable(str)
+-- if ori == "" then
+ local ori = str
+-- end
+ local pth = expandedpathfromlist(resolvers.splitpath(ori))
+ return joinpath(pth)
+end
+
+function resolvers.registerfilehash(name,content,someerror)
+ if content then
+ instance.files[name] = content
+ else
+ instance.files[name] = { }
+ if somerror == true then -- can be unset
+ instance.loaderror = someerror
+ end
+ end
+end
+
+local function isreadable(name)
+ local readable = isfile(name) -- not file.is_readable(name) asit can be a dir
+ if trace_detail then
+ if readable then
+ report_resolving("file %a is readable",name)
+ else
+ report_resolving("file %a is not readable", name)
+ end
+ end
+ return readable
+end
+
+-- name | name/name
+
+local function collect_files(names) -- potential files .. sort of too much when asking for just one file
+ local filelist = { } -- but we need it for pattern matching later on
+ local noffiles = 0
+ local function check(hash,root,pathname,path,name)
+ if not pathname or find(path,pathname) then
+ local variant = hash.type
+ local search = filejoin(root,path,name) -- funny no concatinator
+ local result = methodhandler('concatinators',variant,root,path,name)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles = noffiles + 1
+ filelist[noffiles] = { variant, search, result }
+ end
+ end
+ for k=1,#names do
+ local filename = names[k]
+ if trace_detail then
+ report_resolving("checking name %a",filename)
+ end
+ local basename = filebasename(filename)
+ local pathname = filedirname(filename)
+ if pathname == "" or find(pathname,"^%.") then
+ pathname = false
+ else
+ pathname = gsub(pathname,"%*",".*")
+ pathname = "/" .. pathname .. "$"
+ end
+ local hashes = instance.hashes
+ for h=1,#hashes do
+ local hash = hashes[h]
+ local hashname = hash.name
+ local content = hashname and instance.files[hashname]
+ if content then
+ if trace_detail then
+ report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
+ end
+ local path, name = lookup(content,basename)
+ if path then
+ local metadata = content.metadata
+ local realroot = metadata and metadata.path or hashname
+ if type(path) == "string" then
+ check(hash,realroot,pathname,path,name)
+ else
+ for i=1,#path do
+ check(hash,realroot,pathname,path[i],name)
+ end
+ end
+ end
+ elseif trace_locating then
+ report_resolving("no match in %a (%s)",hashname,basename)
+ end
+ end
+ end
+ return noffiles > 0 and filelist or nil
+end
+
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
+ end
+end
+
+-- split the next one up for readability (but this module needs a cleanup anyway)
+
+local function can_be_dir(name) -- can become local
+ local fakepaths = instance.fakepaths
+ if not fakepaths[name] then
+ if isdir(name) then
+ fakepaths[name] = 1 -- directory
+ else
+ fakepaths[name] = 2 -- no directory
+ end
+ end
+ return fakepaths[name] == 1
+end
+
+local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
+
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
+
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, suffixonly(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ local formatofsuffix = resolvers.formatofsuffix
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype %a",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
+ if trace_locating then
+ report_resolving("using suffix based filetype %a",filetype)
+ end
+ end
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
+ end
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype %a",filetype)
+ end
+ end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file %a found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
+ if find(filename,'*',1,true) then
+ if trace_locating then
+ report_resolving("checking wildcard %a", filename)
+ end
+ local result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
+ end
+ end
+end
+
+local function find_qualified(filename,allresults,askedformat,alsostripped) -- this one will be split too
+ if not is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name %a", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file %a found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file %a", filename)
+ end
+ local forcedname, suffix = "", suffixonly(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
+ if trace_locating then
+ report_resolving("no suffix, forcing format filetype %a", s)
+ end
+ return "qualified", { forcedname }
+ end
+ end
+ end
+ end
+ if alsostripped and suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ -- is this really what we want? basename if we have an explicit path?
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
+ end
+ end
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
+ end
+ end
+ if #result > 0 then
+ return "qualified", result
+ end
+ end
+ end
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found %a by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+-- this caching is not really needed (seldom accessed) but more readable
+-- we could probably move some to a higher level but then we need to adapt
+-- more code ... maybe some day
+
+local function makepathlist(list,filetype)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec,filetype and usertypes[filetype]) -- only extra path with user files
+ local entry = { }
+ if pathlist and #pathlist > 0 then
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local prescanned = find(path,'^!!')
+ local resursive = find(path,'//$')
+ local pathname = lpegmatch(inhibitstripper,path)
+ local expression = makepathexpression(pathname)
+ local barename = gsub(pathname,"/+$","")
+ barename = resolveprefix(barename)
+ local scheme = url.hasscheme(barename)
+ local schemename = gsub(barename,"%.%*$",'') -- after scheme
+ -- local prescanned = path ~= pathname -- ^!!
+ -- local resursive = find(pathname,'//$')
+ entry[k] = {
+ path = path,
+ pathname = pathname,
+ prescanned = prescanned,
+ recursive = recursive,
+ expression = expression,
+ barename = barename,
+ scheme = scheme,
+ schemename = schemename,
+ }
+ end
+ entry.typespec = typespec
+ list[filetype] = entry
+ else
+ list[filetype] = false
+ end
+ return entry
+end
+
+-- pathlist : resolved
+-- dirlist : unresolved or resolved
+-- filelist : unresolved
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local pathlists = instance.pathlists
+ if not pathlists then
+ pathlists = setmetatableindex(allocate(),makepathlist)
+ instance.pathlists = pathlists
+ end
+ local pathlist = pathlists[filetype]
+ if pathlist then
+ -- list search
+ local method = "intree"
+ local filelist = collect_files(wantedfiles) -- okay, a bit over the top when we just look relative to the current path
+ local dirlist = { }
+ local result = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
+ end
+ end
+ if trace_detail then
+ report_resolving("checking filename %a in tree",filename)
+ end
+ for k=1,#pathlist do
+ local entry = pathlist[k]
+ local path = entry.path
+ local pathname = entry.pathname
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = entry.expression
+ if trace_detail then
+ report_resolving("using pattern %a for path %a",expression,pathname)
+ end
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ -- resolve is new:
+ if find(d,expression) or find(resolveprefix(d),expression) then
+ -- todo, test for readable
+ result[#result+1] = resolveprefix(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
+ end
+ else
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
+ end
+ break
+ end
+ elseif trace_detail then
+ report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+ end
+ end
+ end
+ if done then
+ method = "database"
+ else
+ -- beware: we don't honor allresults here in a next attempt (done false)
+ -- but that is kind of special anyway
+ method = "filesystem" -- bonus, even when !! is specified
+ local scheme = entry.scheme
+ if not scheme or scheme == "file" then
+ local pname = entry.schemename
+ if not find(pname,"*",1,true) then
+ if can_be_dir(pname) then
+ -- hm, rather useless as we don't go deeper and if we would we could also
+ -- auto generate the file database .. however, we need this for extra paths
+ -- that are not hashed (like sources on my machine) .. so, this is slightly
+ -- out of order but at least fast (and we seldom end up here, only when a file
+ -- is not already found
+-- inspect(entry)
+ if not done and not entry.prescanned then
+ if trace_detail then
+ report_resolving("quick root scan for %a",pname)
+ end
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and entry.recursive then -- maybe also when allresults
+ -- collect files in path (and cache the result)
+ if trace_detail then
+ report_resolving("scanning filesystem for %a",pname)
+ end
+ local files = resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
+ end
+ else
+ -- we can have extra_paths that are urls
+ for k=1,#wantedfiles do
+ -- independent url scanner
+ local pname = entry.barename
+ local fname = methodhandler('finders',pname .. "/" .. wantedfiles[k])
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
+ end
+ end
+ if #result > 0 then
+ return method, result
+ end
+ end
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
+ end
+ if #result > 0 then
+ return "onpath", result
+ end
+end
+
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolveprefix(fl[3]) } -- filename
+ end
+end
+
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze .. todo: use url split
+
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ if not filename or filename == "" then
+ return { }
+ end
+ askedformat = askedformat or ""
+ filename = collapsepath(filename,".")
+
+ filename = gsub(filename,"^%./",getcurrentdir().."/") -- we will merge dir.expandname and collapse some day
+
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true,askedformat) }, -- we can add ,true if we want to find dups
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = formatters["%-10s: %s"](method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ if askedformat == "" then
+ stamp = formatters["%s::%s"](suffixonly(filename),filename)
+ else
+ stamp = formatters["%s::%s"](askedformat,filename)
+ end
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file %a",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename,false,askedformat)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if resolve_otherwise and not result then
+ -- this will search everywhere in the tree
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file %a using hash %a",filename,stamp)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
+
+-- -- -- end of main file search routing -- -- --
+
+local function findfiles(filename,filetype,allresults)
+ if not filename or filename == "" then
+ return { }
+ end
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
+ local lowered = lower(filename)
+ if filename ~= lowered then
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
+ end
+ end
+ return result or { }, status
+end
+
+function resolvers.findfiles(filename,filetype)
+ if not filename or filename == "" then
+ -- weird ... why called then
+ return ""
+ else
+ return findfiles(filename,filetype,true)
+ end
+end
+
+function resolvers.findfile(filename,filetype)
+ if not filename or filename == "" then
+ -- weird ... why called then
+ return ""
+ else
+ return findfiles(filename,filetype,false)[1] or ""
+ end
+end
+
+function resolvers.findpath(filename,filetype)
+ return filedirname(findfiles(filename,filetype,false)[1] or "")
+end
+
+local function findgivenfiles(filename,allresults)
+ local base = filebasename(filename)
+ local result = { }
+ local hashes = instance.hashes
+ --
+ local function okay(hash,path,name)
+ local found = methodhandler('concatinators',hash.type,hash.name,path,name)
+ if found and found ~= "" then
+ result[#result+1] = resolveprefix(found)
+ return not allresults
+ end
+ end
+ --
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local content = instance.files[hash.name]
+ if content then
+ local path, name = lookup(content,base)
+ if not path then
+ -- no match
+ elseif type(path) == "string" then
+ if okay(hash,path,name) then
+ return result
+ end
+ else
+ for i=1,#path do
+ if okay(hash,path[i],name) then
+ return result
+ end
+ end
+ end
+ end
+ end
+ --
+ return result
+end
+
+function resolvers.findgivenfiles(filename)
+ return findgivenfiles(filename,true)
+end
+
+function resolvers.findgivenfile(filename)
+ return findgivenfiles(filename,false)[1] or ""
+end
+
+local makewildcard = Cs(
+ (P("^")^0 * P("/") * P(-1) + P(-1)) /".*"
+ + (P("^")^0 * P("/") / "")^0 * (P("*")/".*" + P("-")/"%%-" + P(".")/"%%." + P("?")/"."+ P("\\")/"/" + P(1))^0
+)
+
+function resolvers.wildcardpattern(pattern)
+ return lpegmatch(makewildcard,pattern) or pattern
+end
+
+-- we use more function calls than before but we also have smaller trees so
+-- why bother
+
+local function findwildcardfiles(filename,allresults,result)
+ local result = result or { }
+ local base = filebasename(filename)
+ local dirn = filedirname(filename)
+ local path = lower(lpegmatch(makewildcard,dirn) or dirn)
+ local name = lower(lpegmatch(makewildcard,base) or base)
+ local files = instance.files
+ --
+ if find(name,"*",1,true) then
+ local hashes = instance.hashes
+ local function okay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full = methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full ~= "" then
+ result[#result+1] = resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local hashname = hash.name
+ local hashtype = hash.type
+ if hashname and hashtype then
+ for found, base in filtered(files[hashname],name) do
+ if type(found) == 'string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ local function okayokay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full = methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full ~= "" then
+ result[#result+1] = resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
+ --
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local hashname = hash.name
+ local hashtype = hash.type
+ if hashname and hashtype then
+ local found, base = lookup(content,base)
+ if not found then
+ -- nothing
+ elseif type(found) == 'string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
+ return result
+end
+
+function resolvers.findwildcardfiles(filename,result)
+ return findwildcardfiles(filename,true,result)
+end
+
+function resolvers.findwildcardfile(filename)
+ return findwildcardfiles(filename,false)[1] or ""
+end
+
+-- main user functions
+
+function resolvers.automount()
+ -- implemented later
+end
+
+function resolvers.load(option)
+ statistics.starttiming(instance)
+ identify_configuration_files()
+ load_configuration_files()
+ if option ~= "nofiles" then
+ load_databases()
+ resolvers.automount()
+ end
+ statistics.stoptiming(instance)
+ local files = instance.files
+ return files and next(files) and true
+end
+
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
+local function report(str)
+ if trace_locating then
+ report_resolving(str) -- has already verbose
+ else
+ print(str)
+ end
+end
+
+function resolvers.dowithfilesandreport(command, files, ...) -- will move
+ if files and #files > 0 then
+ if trace_locating then
+ report('') -- ?
+ end
+ if type(files) == "string" then
+ files = { files }
+ end
+ for f=1,#files do
+ local file = files[f]
+ local result = command(file,...)
+ if type(result) == 'string' then
+ report(result)
+ else
+ for i=1,#result do
+ report(result[i]) -- could be unpack
+ end
+ end
+ end
+ end
+end
+
+-- obsolete
+
+-- resolvers.varvalue = resolvers.variable -- output the value of variable $STRING.
+-- resolvers.expandvar = resolvers.expansion -- output variable expansion of STRING.
+
+function resolvers.showpath(str) -- output search path for file type NAME
+ return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
+end
+
+function resolvers.registerfile(files, name, path)
+ if files[name] then
+ if type(files[name]) == 'string' then
+ files[name] = { files[name], path }
+ else
+ files[name] = path
+ end
+ else
+ files[name] = path
+ end
+end
+
+function resolvers.dowithpath(name,func)
+ local pathlist = resolvers.expandedpathlist(name)
+ for i=1,#pathlist do
+ func("^"..cleanpath(pathlist[i]))
+ end
+end
+
+function resolvers.dowithvariable(name,func)
+ func(expandedvariable(name))
+end
+
+function resolvers.locateformat(name)
+ local engine = environment.ownmain or "luatex"
+ local barename = removesuffix(name)
+ local fullname = addsuffix(barename,"fmt")
+ local fmtname = caches.getfirstreadablefile(fullname,"formats",engine) or ""
+ if fmtname == "" then
+ fmtname = resolvers.findfile(fullname)
+ fmtname = cleanpath(fmtname)
+ end
+ if fmtname ~= "" then
+ local barename = removesuffix(fmtname)
+ local luaname = addsuffix(barename,luasuffixes.lua)
+ local lucname = addsuffix(barename,luasuffixes.luc)
+ local luiname = addsuffix(barename,luasuffixes.lui)
+ if isfile(luiname) then
+ return barename, luiname
+ elseif isfile(lucname) then
+ return barename, lucname
+ elseif isfile(luaname) then
+ return barename, luaname
+ end
+ end
+ return nil, nil
+end
+
+function resolvers.booleanvariable(str,default)
+ local b = resolvers.expansion(str)
+ if b == "" then
+ return default
+ else
+ b = toboolean(b)
+ return (b == nil and default) or b
+ end
+end
+
+function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead
+ local instance = resolvers.instance
+ local hashes = instance.hashes
+ for i=1,#hashes do
+ local hash = hashes[i]
+ local blobtype = hash.type
+ local blobpath = hash.name
+ if blobtype and blobpath then
+ local total = 0
+ local checked = 0
+ local done = 0
+ if before then
+ before(blobtype,blobpath,pattern)
+ end
+ for path, name in filtered(instance.files[blobpath],pattern) do
+ if type(path) == "string" then
+ checked = checked + 1
+ if handle(blobtype,blobpath,path,name) then
+ done = done + 1
+ end
+ else
+ checked = checked + #path
+ for i=1,#path do
+ if handle(blobtype,blobpath,path[i],name) then
+ done = done + 1
+ end
+ end
+ end
+ end
+ if after then
+ after(blobtype,blobpath,pattern,total,checked,done)
+ end
+ end
+ end
+end
+
+local obsolete = resolvers.obsolete or { }
+resolvers.obsolete = obsolete
+
+resolvers.find_file = resolvers.findfile obsolete.find_file = resolvers.findfile
+resolvers.find_files = resolvers.findfiles obsolete.find_files = resolvers.findfiles
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-sch.lua b/Master/texmf-dist/tex/context/base/mkiv/data-sch.lua
new file mode 100644
index 00000000000..d79e0c7ef59
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-sch.lua
@@ -0,0 +1,210 @@
+if not modules then modules = { } end modules ['data-sch'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local load = load
+local gsub, concat, format = string.gsub, table.concat, string.format
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
+local report_schemes = logs.reporter("resolvers","schemes")
+
+local http = require("socket.http")
+local ltn12 = require("ltn12")
+
+local resolvers = resolvers
+local schemes = resolvers.schemes or { }
+resolvers.schemes = schemes
+
+local cleaners = { }
+schemes.cleaners = cleaners
+
+local threshold = 24 * 60 * 60
+
+directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end)
+
+function cleaners.none(specification)
+ return specification.original
+end
+
+-- function cleaners.strip(specification)
+-- -- todo: only keep suffix periods, so after the last
+-- return (gsub(specification.original,"[^%a%d%.]+","-")) -- so we keep periods
+-- end
+
+function cleaners.strip(specification) -- keep suffixes
+ local path, name = file.splitbase(specification.original)
+ if path == "" then
+ return (gsub(name,"[^%a%d%.]+","-"))
+ else
+ return (gsub((gsub(path,"%.","-") .. "-" .. name),"[^%a%d%.]+","-"))
+ end
+end
+
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+
+local cleaner = cleaners.strip
+
+directives.register("schemes.cleanmethod", function(v) cleaner = cleaners[v] or cleaners.strip end)
+
+function resolvers.schemes.cleanname(specification)
+ local hash = cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %a to %a",specification.original,hash)
+ end
+ return hash
+end
+
+local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
+
+local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
+ local command = "curl --silent --insecure --create-dirs --output " .. cachename .. " " .. name
+ os.execute(command)
+end
+
+local function fetch(specification)
+ local original = specification.original
+ local scheme = specification.scheme
+ local cleanname = schemes.cleanname(specification)
+ local cachename = caches.setfirstwritablefile(cleanname,"schemes")
+ if not cached[original] then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then
+ cached[original] = cachename
+ local handler = handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in")
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl")
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
+ end
+ if io.exists(cachename) then
+ cached[original] = cachename
+ if trace_schemes then
+ report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename)
+ end
+ else
+ cached[original] = ""
+ if trace_schemes then
+ report_schemes("using missing %a, protocol %a",original,scheme)
+ end
+ end
+ loaded[scheme] = loaded[scheme] + 1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing %a, protocol %a",original,scheme)
+ end
+ reused[scheme] = reused[scheme] + 1
+ end
+ return cached[original]
+end
+
+local function finder(specification,filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
+end
+
+local opener = openers.file
+local loader = loaders.file
+
+local function install(scheme,handler,newthreshold)
+ handlers [scheme] = handler
+ loaded [scheme] = 0
+ reused [scheme] = 0
+ finders [scheme] = finder
+ openers [scheme] = opener
+ loaders [scheme] = loader
+ thresholds[scheme] = newthreshold or threshold
+end
+
+schemes.install = install
+
+local function http_handler(specification,cachename)
+ local tempname = cachename .. ".tmp"
+ local f = io.open(tempname,"wb")
+ local status, message = http.request {
+ url = specification.original,
+ sink = ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
+
+install('http',http_handler)
+install('https') -- see pod
+install('ftp')
+
+statistics.register("scheme handling time", function()
+ local l, r, nl, nr = { }, { }, 0, 0
+ for k, v in table.sortedhash(loaded) do
+ if v > 0 then
+ nl = nl + 1
+ l[nl] = k .. ":" .. v
+ end
+ end
+ for k, v in table.sortedhash(reused) do
+ if v > 0 then
+ nr = nr + 1
+ r[nr] = k .. ":" .. v
+ end
+ end
+ local n = nl + nr
+ if n > 0 then
+ l = nl > 0 and concat(l) or "none"
+ r = nr > 0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes), n, threshold, l, r)
+ else
+ return nil
+ end
+end)
+
+-- We provide a few more helpers:
+
+----- http = require("socket.http")
+local httprequest = http.request
+local toquery = url.toquery
+
+-- local function httprequest(url)
+-- return os.resultof(format("curl --silent %q", url))
+-- end
+
+local function fetchstring(url,data)
+ local q = data and toquery(data)
+ if q then
+ url = url .. "?" .. q
+ end
+ local reply = httprequest(url)
+ return reply -- just one argument
+end
+
+schemes.fetchstring = fetchstring
+
+function schemes.fetchtable(url,data)
+ local reply = fetchstring(url,data)
+ if reply then
+ local s = load("return " .. reply)
+ if s then
+ return s()
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua
new file mode 100644
index 00000000000..b6b97a0a989
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua
@@ -0,0 +1,193 @@
+if not modules then modules = { } end modules ['data-tex'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local char, find = string.char, string.find
+local insert, remove = table.insert, table.remove
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_tex = logs.reporter("resolvers","tex")
+
+local resolvers = resolvers
+
+local sequencers = utilities.sequencers
+local methodhandler = resolvers.methodhandler
+local splitlines = string.splitlines
+local utffiletype = utf.filetype
+local setmetatableindex = table.setmetatableindex
+
+-- local fileprocessor = nil
+-- local lineprocessor = nil
+
+local textfileactions = sequencers.new {
+ arguments = "str,filename,coding",
+ returnvalues = "str",
+ results = "str",
+}
+
+local textlineactions = sequencers.new {
+ arguments = "str,filename,linenumber,noflines,coding",
+ returnvalues = "str",
+ results = "str",
+}
+
+local helpers = resolvers.openers.helpers
+local appendgroup = sequencers.appendgroup
+
+helpers.textfileactions = textfileactions
+helpers.textlineactions = textlineactions
+
+appendgroup(textfileactions,"before") -- user
+appendgroup(textfileactions,"system") -- private
+appendgroup(textfileactions,"after" ) -- user
+
+appendgroup(textlineactions,"before") -- user
+appendgroup(textlineactions,"system") -- private
+appendgroup(textlineactions,"after" ) -- user
+
+local ctrl_d = char( 4) -- unix
+local ctrl_z = char(26) -- windows
+
+resolvers.inputstack = resolvers.inputstack or { }
+
+local inputstack = resolvers.inputstack
+
+function helpers.textopener(tag,filename,filehandle,coding)
+ local lines
+ local t_filehandle = type(filehandle)
+ if not filehandle then
+ lines = io.loaddata(filename)
+ elseif t_filehandle == "string" then
+ lines = filehandle
+ elseif t_filehandle == "table" then
+ lines = filehandle
+ else
+ lines = filehandle:read("*a") -- io.readall(filehandle) ... but never that large files anyway
+ -- lines = io.readall(filehandle)
+ filehandle:close()
+ end
+ if type(lines) == "string" then
+ local coding = coding or utffiletype(lines) -- so we can signal no regime
+ if trace_locating then
+ report_tex("%a opener: %a opened using method %a",tag,filename,coding)
+ end
+ if coding == "utf-16-be" then
+ lines = utf.utf16_to_utf8_be_t(lines)
+ elseif coding == "utf-16-le" then
+ lines = utf.utf16_to_utf8_le_t(lines)
+ elseif coding == "utf-32-be" then
+ lines = utf.utf32_to_utf8_be_t(lines)
+ elseif coding == "utf-32-le" then
+ lines = utf.utf32_to_utf8_le_t(lines)
+ else -- utf8 or unknown (could be a mkvi file)
+ local runner = textfileactions.runner
+ if runner then
+ lines = runner(lines,filename,coding) or lines
+ end
+ lines = splitlines(lines)
+ end
+ elseif trace_locating then
+ report_tex("%a opener: %a opened",tag,filename)
+ end
+ local noflines = #lines
+ if lines[noflines] == "" then -- maybe some special check is needed
+ lines[noflines] = nil
+ end
+ logs.show_open(filename)
+ insert(inputstack,filename)
+ local currentline, noflines = 0, noflines
+ local t = {
+ filename = filename,
+ noflines = noflines,
+ -- currentline = 0,
+ close = function()
+ if trace_locating then
+ report_tex("%a closer: %a closed",tag,filename)
+ end
+ logs.show_close(filename)
+ remove(inputstack)
+ t = nil
+ end,
+ reader = function(self)
+ self = self or t
+ -- local currentline, noflines = self.currentline, self.noflines
+ if currentline >= noflines then
+ return nil
+ else
+ currentline = currentline + 1
+ -- self.currentline = currentline
+ local content = lines[currentline]
+ if not content then
+ return nil
+ elseif content == "" then
+ return ""
+ -- elseif content == ctrl_d or ctrl_z then
+ -- return nil -- we need this as \endinput does not work in prints
+ else
+ local runner = textlineactions.runner
+ if runner then
+ return runner(content,filename,currentline,noflines,coding) or content
+ else
+ return content
+ end
+ end
+ end
+ end
+ }
+ setmetatableindex(t,function(t,k)
+ if k == "currentline" then
+ return currentline
+ else
+ -- no such key
+ end
+ end)
+ return t
+end
+
+function resolvers.findtexfile(filename,filetype)
+ return methodhandler('finders',filename,filetype)
+end
+
+function resolvers.opentexfile(filename)
+ return methodhandler('openers',filename)
+end
+
+function resolvers.openfile(filename)
+ local fullname = methodhandler('finders',filename)
+ return fullname and fullname ~= "" and methodhandler('openers',fullname) or nil
+end
+
+function resolvers.loadtexfile(filename,filetype)
+ -- todo: optionally apply filters
+ local ok, data, size = resolvers.loadbinfile(filename, filetype)
+ return data or ""
+end
+
+resolvers.texdatablob = resolvers.loadtexfile
+
+local function installhandler(namespace,what,where,func)
+ if not func then
+ where, func = "after", where
+ end
+ if where == "before" or where == "after" then
+ sequencers.appendaction(namespace,where,func)
+ else
+ report_tex("installing input %a handlers in %a is not possible",what,tostring(where))
+ end
+end
+
+function resolvers.installinputlinehandler(...) installhandler(helpers.textlineactions,"line",...) end
+function resolvers.installinputfilehandler(...) installhandler(helpers.textfileactions,"file",...) end
+
+-- local basename = file.basename
+-- resolvers.installinputlinehandler(function(str,filename,linenumber,noflines)
+-- report_tex("[lc] file %a, line %a of %a, length %a",basename(filename),linenumber,noflines,#str)
+-- end)
+-- resolvers.installinputfilehandler(function(str,filename)
+-- report_tex("[fc] file %a, length %a",basename(filename),#str)
+-- end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tmf.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tmf.lua
new file mode 100644
index 00000000000..e0ccac257a1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-tmf.lua
@@ -0,0 +1,73 @@
+if not modules then modules = { } end modules ['data-tmf'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local resolvers = resolvers
+
+local report_tds = logs.reporter("resolvers","tds")
+
+-- = <<
+-- ? ??
+-- < +=
+-- > =+
+
+function resolvers.load_tree(tree,resolve)
+ if type(tree) == "string" and tree ~= "" then
+
+ local getenv, setenv = resolvers.getenv, resolvers.setenv
+
+ -- later might listen to the raw osenv var as well
+ local texos = "texmf-" .. os.platform
+
+ local oldroot = environment.texroot
+ local newroot = file.collapsepath(tree)
+
+ local newtree = file.join(newroot,texos)
+ local newpath = file.join(newtree,"bin")
+
+ if not lfs.isdir(newtree) then
+ report_tds("no %a under tree %a",texos,tree)
+ os.exit()
+ end
+ if not lfs.isdir(newpath) then
+ report_tds("no '%s/bin' under tree %a",texos,tree)
+ os.exit()
+ end
+
+ local texmfos = newtree
+
+ environment.texroot = newroot
+ environment.texos = texos
+ environment.texmfos = texmfos
+
+ -- Beware, we need to obey the relocatable autoparent so we
+ -- set TEXMFCNF to its raw value. This is somewhat tricky when
+ -- we run a mkii job from within. Therefore, in mtxrun, there
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ -- resolvers.luacnfspec = resolvers.joinpath(resolvers.resolve(resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))))
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
+
+ setenv('SELFAUTOPARENT', newroot)
+ setenv('SELFAUTODIR', newtree)
+ setenv('SELFAUTOLOC', newpath)
+ setenv('TEXROOT', newroot)
+ setenv('TEXOS', texos)
+ setenv('TEXMFOS', texmfos)
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
+
+ report_tds("changing from root %a to %a",oldroot,newroot)
+ report_tds("prepending %a to PATH",newpath)
+ report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec)
+ report_tds()
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tmp.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tmp.lua
new file mode 100644
index 00000000000..9e1515a2650
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-tmp.lua
@@ -0,0 +1,448 @@
+if not modules then modules = { } end modules ['data-tmp'] = {
+ version = 1.100,
+ 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"
+}
+
+--[[ldx--
+<p>This module deals with caching data. It sets up the paths and
+implements loaders and savers for tables. Best is to set the
+following variable. When not set, the usual paths will be
+checked. Personally I prefer the (users) temporary path.</p>
+
+</code>
+TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
+</code>
+
+<p>Currently we do no locking when we write files. This is no real
+problem because most caching involves fonts and the chance of them
+being written at the same time is small. We also need to extend
+luatools with a recache feature.</p>
+--ldx]]--
+
+local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+----- serialize, serializetofile = table.serialize, table.tofile -- overloaded so no local
+local concat = table.concat
+local mkdirs, isdir, isfile = dir.mkdirs, lfs.isdir, lfs.isfile
+local addsuffix, is_writable, is_readable = file.addsuffix, file.is_writable, file.is_readable
+local formatters = string.formatters
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
+
+local report_caches = logs.reporter("resolvers","caches")
+local report_resolvers = logs.reporter("resolvers","caching")
+
+local resolvers = resolvers
+local cleanpath = resolvers.cleanpath
+
+-- intermezzo
+
+local directive_cleanup = false directives.register("system.compile.cleanup", function(v) directive_cleanup = v end)
+local directive_strip = false directives.register("system.compile.strip", function(v) directive_strip = v end)
+
+local compile = utilities.lua.compile
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip)
+ if cleanup == nil then cleanup = directive_cleanup end
+ if strip == nil then strip = directive_strip end
+ return compile(luafile,lucfile,cleanup,strip)
+end
+
+-- end of intermezzo
+
+caches = caches or { }
+local caches = caches
+
+local luasuffixes = utilities.lua.suffixes
+
+caches.base = caches.base or "luatex-cache"
+caches.more = caches.more or "context"
+caches.direct = false -- true is faster but may need huge amounts of memory
+caches.tree = false
+caches.force = true
+caches.ask = false
+caches.relocate = false
+caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
+
+local writable, readables, usedreadables = nil, { }, { }
+
+-- we could use a metatable for writable and readable but not yet
+
+local function identify()
+ -- Combining the loops makes it messy. First we check the format cache path
+ -- and when the last component is not present we try to create it.
+ local texmfcaches = resolvers.cleanpathlist("TEXMFCACHE") -- forward ref
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath = texmfcaches[k]
+ if cachepath ~= "" then
+ cachepath = resolvers.resolve(cachepath)
+ cachepath = resolvers.cleanpath(cachepath)
+ cachepath = file.collapsepath(cachepath)
+ local valid = isdir(cachepath)
+ if valid then
+ if is_readable(cachepath) then
+ readables[#readables+1] = cachepath
+ if not writable and is_writable(cachepath) then
+ writable = cachepath
+ end
+ end
+ elseif not writable and caches.force then
+ local cacheparent = file.dirname(cachepath)
+ if is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
+ if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
+ mkdirs(cachepath)
+ if isdir(cachepath) and is_writable(cachepath) then
+ report_caches("path %a created",cachepath)
+ writable = cachepath
+ readables[#readables+1] = cachepath
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- As a last resort we check some temporary paths but this time we don't
+ -- create them.
+ local texmfcaches = caches.defaults
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath = texmfcaches[k]
+ cachepath = resolvers.expansion(cachepath) -- was getenv
+ if cachepath ~= "" then
+ cachepath = resolvers.resolve(cachepath)
+ cachepath = resolvers.cleanpath(cachepath)
+ local valid = isdir(cachepath)
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
+ readables[#readables+1] = cachepath
+ writable = cachepath
+ break
+ end
+ end
+ end
+ end
+ end
+ -- Some extra checking. If we have no writable or readable path then we simply
+ -- quit.
+ if not writable then
+ report_caches("fatal error: there is no valid writable cache path defined")
+ os.exit()
+ elseif #readables == 0 then
+ report_caches("fatal error: there is no valid readable cache path defined")
+ os.exit()
+ end
+ -- why here
+ writable = dir.expandname(resolvers.cleanpath(writable)) -- just in case
+ -- moved here
+ local base, more, tree = caches.base, caches.more, caches.tree or caches.treehash() -- we have only one writable tree
+ if tree then
+ caches.tree = tree
+ writable = mkdirs(writable,base,more,tree)
+ for i=1,#readables do
+ readables[i] = file.join(readables[i],base,more,tree)
+ end
+ else
+ writable = mkdirs(writable,base,more)
+ for i=1,#readables do
+ readables[i] = file.join(readables[i],base,more)
+ end
+ end
+ -- end
+ if trace_cache then
+ for i=1,#readables do
+ report_caches("using readable path %a (order %s)",readables[i],i)
+ end
+ report_caches("using writable path %a",writable)
+ end
+ identify = function()
+ return writable, readables
+ end
+ return writable, readables
+end
+
+function caches.usedpaths(separator)
+ local writable, readables = identify()
+ if #readables > 1 then
+ local result = { }
+ local done = { }
+ for i=1,#readables do
+ local readable = readables[i]
+ if readable == writable then
+ done[readable] = true
+ result[#result+1] = formatters["readable+writable: %a"](readable)
+ elseif usedreadables[i] then
+ done[readable] = true
+ result[#result+1] = formatters["readable: %a"](readable)
+ end
+ end
+ if not done[writable] then
+ result[#result+1] = formatters["writable: %a"](writable)
+ end
+ return concat(result,separator or " | ")
+ else
+ return writable or "?"
+ end
+end
+
+function caches.configfiles()
+ return concat(resolvers.instance.specification,";")
+end
+
+function caches.hashed(tree)
+ tree = gsub(tree,"[\\/]+$","")
+ tree = lower(tree)
+ local hash = md5.hex(tree)
+ if trace_cache or trace_locating then
+ report_caches("hashing tree %a, hash %a",tree,hash)
+ end
+ return hash
+end
+
+function caches.treehash()
+ local tree = caches.configfiles()
+ if not tree or tree == "" then
+ return false
+ else
+ return caches.hashed(tree)
+ end
+end
+
+local r_cache, w_cache = { }, { } -- normally w in in r but who cares
+
+local function getreadablepaths(...)
+ local tags = { ... }
+ local hash = concat(tags,"/")
+ local done = r_cache[hash]
+ if not done then
+ local writable, readables = identify() -- exit if not found
+ if #tags > 0 then
+ done = { }
+ for i=1,#readables do
+ done[i] = file.join(readables[i],...)
+ end
+ else
+ done = readables
+ end
+ r_cache[hash] = done
+ end
+ return done
+end
+
+local function getwritablepath(...)
+ local tags = { ... }
+ local hash = concat(tags,"/")
+ local done = w_cache[hash]
+ if not done then
+ local writable, readables = identify() -- exit if not found
+ if #tags > 0 then
+ done = mkdirs(writable,...)
+ else
+ done = writable
+ end
+ w_cache[hash] = done
+ end
+ return done
+end
+
+caches.getreadablepaths = getreadablepaths
+caches.getwritablepath = getwritablepath
+
+-- this can be tricky as we can have a pre-generated format while at the same time
+-- use e.g. a home path where we have updated file databases and so maybe we need
+-- to check first if we do have a writable one
+
+function caches.getfirstreadablefile(filename,...)
+ local rd = getreadablepaths(...)
+ for i=1,#rd do
+ local path = rd[i]
+ local fullname = file.join(path,filename)
+ if is_readable(fullname) then
+ usedreadables[i] = true
+ return fullname, path
+ end
+ end
+ return caches.setfirstwritablefile(filename,...)
+end
+
+-- next time we have an issue, we can test this instead:
+
+function caches.getfirstreadablefile_TEST_ME_FIRST(filename,...)
+ -- check if we have already written once
+ local fullname, path = caches.setfirstwritablefile(filename,...)
+ if is_readable(fullname) then
+ return fullname, path -- , true
+ end
+ -- otherwise search for pregenerated
+ local rd = getreadablepaths(...)
+ for i=1,#rd do
+ local path = rd[i]
+ local fullname = file.join(path,filename)
+ if is_readable(fullname) then
+ usedreadables[i] = true
+ return fullname, path -- , false
+ end
+ end
+ -- else assume new written
+ return fullname, path -- , true
+end
+
+function caches.setfirstwritablefile(filename,...)
+ local wr = getwritablepath(...)
+ local fullname = file.join(wr,filename)
+ return fullname, wr
+end
+
+function caches.define(category,subcategory) -- for old times sake
+ return function()
+ return getwritablepath(category,subcategory)
+ end
+end
+
+function caches.setluanames(path,name)
+ return format("%s/%s.%s",path,name,luasuffixes.tma), format("%s/%s.%s",path,name,luasuffixes.tmc)
+end
+
+function caches.loaddata(readables,name)
+ if type(readables) == "string" then
+ readables = { readables }
+ end
+ for i=1,#readables do
+ local path = readables[i]
+ local tmaname, tmcname = caches.setluanames(path,name)
+ local loader = false
+ if isfile(tmcname) then
+ loader = loadfile(tmcname)
+ end
+ if not loader and isfile(tmaname) then
+ -- in case we have a different engine
+ utilities.lua.compile(tmaname,tmcname)
+ if isfile(tmcname) then
+ loader = loadfile(tmcname)
+ end
+ if not loader then
+ loader = loadfile(tmaname)
+ end
+ end
+ if loader then
+ loader = loader()
+ collectgarbage("step")
+ return loader
+ end
+ end
+ return false
+end
+
+function caches.is_writable(filepath,filename)
+ local tmaname, tmcname = caches.setluanames(filepath,filename)
+ return is_writable(tmaname)
+end
+
+local saveoptions = { compact = true }
+
+-- add some point we will only use the internal bytecode compiler and
+-- then we can flag success in the tma so that it can trigger a compile
+-- if the other engine
+
+function caches.savedata(filepath,filename,data,raw)
+ local tmaname, tmcname = caches.setluanames(filepath,filename)
+ data.cache_uuid = os.uuid()
+ if caches.direct then
+ file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ else
+ table.tofile(tmaname,data,true,saveoptions)
+ end
+ utilities.lua.compile(tmaname,tmcname)
+end
+
+-- moved from data-res:
+
+local content_state = { }
+
+function caches.contentstate()
+ return content_state or { }
+end
+
+function caches.loadcontent(cachename,dataname,filename)
+ if not filename then
+ local name = caches.hashed(cachename)
+ local full, path = caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename = file.join(path,name)
+ end
+ local blob = loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
+ if blob then
+ local data = blob()
+ if data and data.content then
+ if data.type == dataname then
+ if data.version == resolvers.cacheversion then
+ content_state[#content_state+1] = data.uuid
+ if trace_locating then
+ report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
+ end
+ return data.content
+ else
+ report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
+ end
+ else
+ report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
+ end
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
+ end
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+ end
+end
+
+function caches.collapsecontent(content)
+ for k, v in next, content do
+ if type(v) == "table" and #v == 1 then
+ content[k] = v[1]
+ end
+ end
+end
+
+function caches.savecontent(cachename,dataname,content,filename)
+ if not filename then
+ local name = caches.hashed(cachename)
+ local full, path = caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename = file.join(path,name) -- is full
+ end
+ local luaname = addsuffix(filename,luasuffixes.lua)
+ local lucname = addsuffix(filename,luasuffixes.luc)
+ if trace_locating then
+ report_resolvers("preparing %a for %a",dataname,cachename)
+ end
+ local data = {
+ type = dataname,
+ root = cachename,
+ version = resolvers.cacheversion,
+ date = os.date("%Y-%m-%d"),
+ time = os.date("%H:%M:%S"),
+ content = content,
+ uuid = os.uuid(),
+ }
+ local ok = io.savedata(luaname,table.serialize(data,true))
+ if ok then
+ if trace_locating then
+ report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
+ end
+ if utilities.lua.compile(luaname,lucname) then
+ if trace_locating then
+ report_resolvers("%a compiled to %a",dataname,lucname)
+ end
+ return true
+ else
+ if trace_locating then
+ report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
+ end
+ os.remove(lucname)
+ end
+ elseif trace_locating then
+ report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua
new file mode 100644
index 00000000000..4388731f98c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua
@@ -0,0 +1,233 @@
+if not modules then modules = { } end modules ['data-tre'] = {
+ 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"
+}
+
+-- tree://e:/temporary/mb-mp/**/drawing.jpg
+-- tree://e:/temporary/mb-mp/**/Drawing.jpg
+-- tree://t:./**/tufte.tex
+-- tree://t:/./**/tufte.tex
+-- tree://t:/**/tufte.tex
+-- dirlist://e:/temporary/mb-mp/**/drawing.jpg
+-- dirlist://e:/temporary/mb-mp/**/Drawing.jpg
+-- dirlist://e:/temporary/mb-mp/**/just/some/place/drawing.jpg
+-- dirlist://e:/temporary/mb-mp/**/images/drawing.jpg
+-- dirlist://e:/temporary/mb-mp/**/images/drawing.jpg?option=fileonly
+-- dirlist://///storage-2/resources/mb-mp/**/drawing.jpg
+-- dirlist://e:/**/drawing.jpg
+
+local find, gsub, lower = string.find, string.gsub, string.lower
+local basename, dirname, joinname = file.basename, file.dirname, file .join
+local globdir, isdir, isfile = dir.glob, lfs.isdir, lfs.isfile
+local P, lpegmatch = lpeg.P, lpeg.match
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_trees = logs.reporter("resolvers","trees")
+
+local resolvers = resolvers
+local resolveprefix = resolvers.resolve
+local notfound = resolvers.finders.notfound
+local lookup = resolvers.get_from_content
+
+-- A tree search is rather dumb ... there is some basic caching of searched trees
+-- but nothing is cached over runs ... it's also a wildcard one so we cannot use
+-- the normal scanner.
+
+local collectors = { }
+local found = { }
+
+function resolvers.finders.tree(specification) -- to be adapted to new formats
+ local spec = specification.filename
+ local okay = found[spec]
+ if okay == nil then
+ if spec ~= "" then
+ local path = dirname(spec)
+ local name = basename(spec)
+ if path == "" then
+ path = "."
+ end
+ local names = collectors[path]
+ if not names then
+ local pattern = find(path,"/%*+$") and path or (path .. "/*")
+ names = globdir(pattern)
+ collectors[path] = names
+ end
+ local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$"
+ for i=1,#names do
+ local fullname = names[i]
+ if find(fullname,pattern) then
+ found[spec] = fullname
+ return fullname
+ end
+ end
+ -- let's be nice:
+ local pattern = lower(pattern)
+ for i=1,#names do
+ local fullname = lower(names[i])
+ if find(fullname,pattern) then
+ if isfile(fullname) then
+ found[spec] = fullname
+ return fullname
+ else
+ -- no os name mapping
+ break
+ end
+ end
+ end
+ end
+ okay = notfound() -- false
+ found[spec] = okay
+ end
+ return okay
+end
+
+function resolvers.locators.tree(specification)
+ local name = specification.filename
+ local realname = resolveprefix(name) -- no shortcut
+ if realname and realname ~= '' and isdir(realname) then
+ if trace_locating then
+ report_trees("locator %a found",realname)
+ end
+ resolvers.appendhash('tree',name,false) -- don't cache
+ elseif trace_locating then
+ report_trees("locator %a not found",name)
+ end
+end
+
+function resolvers.hashers.tree(specification)
+ local name = specification.filename
+ -- if trace_locating then
+ report_trees("analyzing %a",name)
+ -- end
+ resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
+end
+
+-- This is a variation on tree lookups but this time we do cache in the given
+-- root. We use a similar hasher as the resolvers because we have to deal with
+-- for instance trees with 50K xml files plus a similar amount of resources to
+-- deal and we don't want too much overhead.
+
+local collectors = { }
+local splitter = lpeg.splitat("/**/")
+local stripper = lpeg.replacer { [P("/") * P("*")^1 * P(-1)] = "" }
+
+table.setmetatableindex(collectors, function(t,k)
+ local rootname = lpegmatch(stripper,k)
+ local dataname = joinname(rootname,"dirlist")
+ local content = caches.loadcontent(dataname,"files",dataname)
+ if not content then
+ -- path branch usecache onlyonce tolerant
+ content = resolvers.scanfiles(rootname,nil,nil,false,true) -- so we accept crap
+ caches.savecontent(dataname,"files",content,dataname)
+ end
+ t[k] = content
+ return content
+end)
+
+
+local function checked(root,p,n)
+ if p then
+ if type(p) == "table" then
+ for i=1,#p do
+ local fullname = joinname(root,p[i],n)
+ if isfile(fullname) then -- safeguard
+ return fullname
+ end
+ end
+ else
+ local fullname = joinname(root,p,n)
+ if isfile(fullname) then -- safeguard
+ return fullname
+ end
+ end
+ end
+ return notfound()
+end
+
+-- no funny characters in path but in filename permitted .. sigh
+
+local function resolve(specification) -- can be called directly too
+ local filename = specification.filename
+ -- inspect(specification)
+ if filename ~= "" then
+ local root, rest = lpegmatch(splitter,filename)
+ if root and rest then
+ local path, name = dirname(rest), basename(rest)
+ if name ~= rest then
+ local content = collectors[root]
+ local p, n = lookup(content,name)
+ if not p then
+ return notfound()
+ end
+ local pattern = ".*/" .. path .. "$"
+ local istable = type(p) == "table"
+ if istable then
+ for i=1,#p do
+ local pi = p[i]
+ if pi == path or find(pi,pattern) then
+ local fullname = joinname(root,pi,n)
+ if isfile(fullname) then -- safeguard
+ return fullname
+ end
+ end
+ end
+ elseif p == path or find(p,pattern) then
+ local fullname = joinname(root,p,n)
+ if isfile(fullname) then -- safeguard
+ return fullname
+ end
+ end
+ local queries = specification.queries
+ if queries and queries.option == "fileonly" then
+ return checked(root,p,n)
+ else
+ return notfound()
+ end
+ end
+ end
+ local path, name = dirname(filename), basename(filename)
+ local root = lpegmatch(stripper,path)
+ local content = collectors[path]
+ local p, n = lookup(content,name)
+ if p then
+ return checked(root,p,n)
+ end
+ end
+ return notfound()
+end
+
+resolvers.finders .dirlist = resolve
+resolvers.locators .dirlist = resolvers.locators .tree
+resolvers.hashers .dirlist = resolvers.hashers .tree
+resolvers.generators.dirlist = resolvers.generators.file
+resolvers.openers .dirlist = resolvers.openers .file
+resolvers.loaders .dirlist = resolvers.loaders .file
+
+function resolvers.finders.dirfile(specification)
+ local queries = specification.queries
+ if queries then
+ queries.option = "fileonly"
+ else
+ specification.queries = { option = "fileonly" }
+ end
+ return resolve(specification)
+end
+
+resolvers.locators .dirfile = resolvers.locators .dirlist
+resolvers.hashers .dirfile = resolvers.hashers .dirlist
+resolvers.generators.dirfile = resolvers.generators.dirlist
+resolvers.openers .dirfile = resolvers.openers .dirlist
+resolvers.loaders .dirfile = resolvers.loaders .dirlist
+
+-- local locate = collectors[ [[E:\temporary\mb-mp]] ]
+-- local locate = collectors( [[\\storage-2\resources\mb-mp]] )
+
+-- print(resolvers.findtexfile("tree://e:/temporary/mb-mp/**/VB_wmf_03_vw_01d_ant.jpg"))
+-- print(resolvers.findtexfile("tree://t:/**/tufte.tex"))
+-- print(resolvers.findtexfile("dirlist://e:/temporary/mb-mp/**/VB_wmf_03_vw_01d_ant.jpg"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-use.lua b/Master/texmf-dist/tex/context/base/mkiv/data-use.lua
new file mode 100644
index 00000000000..7598506e459
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-use.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['data-use'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, lower, gsub, find = string.format, string.lower, string.gsub, string.find
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_mounts = logs.reporter("resolvers","mounts")
+
+local resolvers = resolvers
+
+-- we will make a better format, maybe something xml or just text or lua
+
+resolvers.automounted = resolvers.automounted or { }
+
+function resolvers.automount(usecache)
+ local mountpaths = resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
+ if (not mountpaths or #mountpaths == 0) and usecache then
+ mountpaths = caches.getreadablepaths("mount")
+ end
+ if mountpaths and #mountpaths > 0 then
+ statistics.starttiming(resolvers.instance)
+ for k=1,#mountpaths do
+ local root = mountpaths[k]
+ local f = io.open(root.."/url.tmi")
+ if f then
+ for line in f:lines() do
+ if line then
+ if find(line,"^[%%#%-]") then -- or %W
+ -- skip
+ elseif find(line,"^zip://") then
+ if trace_locating then
+ report_mounts("mounting %a",line)
+ end
+ table.insert(resolvers.automounted,line)
+ resolvers.usezipfile(line)
+ end
+ end
+ end
+ f:close()
+ end
+ end
+ statistics.stoptiming(resolvers.instance)
+ end
+end
+
+-- status info
+
+statistics.register("used config file", function() return caches.configfiles() end)
+statistics.register("used cache path", function() return caches.usedpaths() end)
+
+-- experiment (code will move)
+
+function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
+ local enginebanner = status.banner
+ if formatbanner and enginebanner and sourcefile then
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
+ local luvdata = {
+ enginebanner = enginebanner,
+ formatbanner = formatbanner,
+ sourcehash = md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
+ sourcefile = sourcefile,
+ }
+ io.savedata(luvname,table.serialize(luvdata,true))
+ end
+end
+
+-- todo: check this at startup and return (say) 999 as signal that the run
+-- was aborted due to a wrong format in which case mtx-context can trigger
+-- a remake
+
+function statistics.checkfmtstatus(texname)
+ local enginebanner = status.banner
+ if enginebanner and texname then
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
+ if lfs.isfile(luvname) then
+ local luv = dofile(luvname)
+ if luv and luv.sourcefile then
+ local sourcehash = md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
+ local luvbanner = luv.enginebanner or "?"
+ if luvbanner ~= enginebanner then
+ return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
+ end
+ local luvhash = luv.sourcehash or "?"
+ if luvhash ~= sourcehash then
+ return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
+ end
+ else
+ return "invalid status file"
+ end
+ else
+ return "missing status file"
+ end
+ end
+ return true
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-vir.lua b/Master/texmf-dist/tex/context/base/mkiv/data-vir.lua
new file mode 100644
index 00000000000..7e25c822d07
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-vir.lua
@@ -0,0 +1,85 @@
+if not modules then modules = { } end modules ['data-vir'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local formatters, validstrings = string.formatters, string.valid
+
+local trace_virtual = false
+local report_virtual = logs.reporter("resolvers","virtual")
+
+trackers.register("resolvers.locating", function(v) trace_virtual = v end)
+trackers.register("resolvers.virtual", function(v) trace_virtual = v end)
+
+local resolvers = resolvers
+
+local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
+
+local data = { }
+local n = 0 -- hm, number can be query
+local f_virtual = formatters["virtual://%s.%s"]
+
+function savers.virtual(specification,content)
+ n = n + 1 -- one number for all namespaces
+ local path = specification.path
+ local filename = f_virtual(path ~= "" and path or "virtualfile",n)
+ if trace_virtual then
+ report_virtual("saver: file %a saved",filename)
+ end
+ data[filename] = content
+ return filename
+end
+
+function finders.virtual(specification)
+ local original = specification.original
+ local d = data[original]
+ if d then
+ if trace_virtual then
+ report_virtual("finder: file %a found",original)
+ end
+ return original
+ else
+ if trace_virtual then
+ report_virtual("finder: unknown file %a",original)
+ end
+ return finders.notfound()
+ end
+end
+
+function openers.virtual(specification)
+ local original = specification.original
+ local d = data[original]
+ if d then
+ if trace_virtual then
+ report_virtual("opener: file %a opened",original)
+ end
+ data[original] = nil -- when we comment this we can have error messages
+ -- With utf-8 we signal that no regime is to be applied!
+ -- characters.showstring(d)
+ return openers.helpers.textopener("virtual",original,d,"utf-8")
+ else
+ if trace_virtual then
+ report_virtual("opener: file %a not found",original)
+ end
+ return openers.notfound()
+ end
+end
+
+function loaders.virtual(specification)
+ local original = specification.original
+ local d = data[original]
+ if d then
+ if trace_virtual then
+ report_virtual("loader: file %a loaded",original)
+ end
+ data[original] = nil
+ return true, d, #d
+ end
+ if trace_virtual then
+ report_virtual("loader: file %a not loaded",original)
+ end
+ return loaders.notfound()
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua b/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua
new file mode 100644
index 00000000000..2be88e0fc1c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua
@@ -0,0 +1,264 @@
+if not modules then modules = { } end modules ['data-zip'] = {
+ 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"
+}
+
+-- real old code ... partly redone .. needs testing due to changes as well as a decent overhaul
+
+local format, find, match = string.format, string.find, string.match
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_zip = logs.reporter("resolvers","zip")
+
+--[[ldx--
+<p>We use a url syntax for accessing the zip file itself and file in it:</p>
+
+<typing>
+zip:///oeps.zip?name=bla/bla.tex
+zip:///oeps.zip?tree=tex/texmf-local
+zip:///texmf.zip?tree=/tex/texmf
+zip:///texmf.zip?tree=/tex/texmf-local
+zip:///texmf-mine.zip?tree=/tex/texmf-projects
+</typing>
+--ldx]]--
+
+local resolvers = resolvers
+
+zip = zip or { }
+local zip = zip
+
+zip.archives = zip.archives or { }
+local archives = zip.archives
+
+zip.registeredfiles = zip.registeredfiles or { }
+local registeredfiles = zip.registeredfiles
+
+local function validzip(str) -- todo: use url splitter
+ if not find(str,"^zip://") then
+ return "zip:///" .. str
+ else
+ return str
+ end
+end
+
+function zip.openarchive(name)
+ if not name or name == "" then
+ return nil
+ else
+ local arch = archives[name]
+ if not arch then
+ local full = resolvers.findfile(name) or ""
+ arch = full ~= "" and zip.open(full) or false
+ archives[name] = arch
+ end
+ return arch
+ end
+end
+
+function zip.closearchive(name)
+ if not name or (name == "" and archives[name]) then
+ zip.close(archives[name])
+ archives[name] = nil
+ end
+end
+
+function resolvers.locators.zip(specification)
+ local archive = specification.filename
+ local zipfile = archive and archive ~= "" and zip.openarchive(archive) -- tricky, could be in to be initialized tree
+ if trace_locating then
+ if zipfile then
+ report_zip("locator: archive %a found",archive)
+ else
+ report_zip("locator: archive %a not found",archive)
+ end
+ end
+end
+
+function resolvers.hashers.zip(specification)
+ local archive = specification.filename
+ if trace_locating then
+ report_zip("loading file %a",archive)
+ end
+ resolvers.usezipfile(specification.original)
+end
+
+function resolvers.concatinators.zip(zipfile,path,name) -- ok ?
+ if not path or path == "" then
+ return format('%s?name=%s',zipfile,name)
+ else
+ return format('%s?name=%s/%s',zipfile,path,name)
+ end
+end
+
+function resolvers.finders.zip(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = url.query(specification.query)
+ local queryname = query.name
+ if queryname then
+ local zfile = zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("finder: archive %a found",archive)
+ end
+ local dfile = zfile:open(queryname)
+ if dfile then
+ dfile = zfile:close()
+ if trace_locating then
+ report_zip("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_zip("finder: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_zip("finder: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_zip("finder: %a not found",original)
+ end
+ return resolvers.finders.notfound()
+end
+
+function resolvers.openers.zip(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = url.query(specification.query)
+ local queryname = query.name
+ if queryname then
+ local zfile = zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("opener; archive %a opened",archive)
+ end
+ local dfile = zfile:open(queryname)
+ if dfile then
+ if trace_locating then
+ report_zip("opener: file %a found",queryname)
+ end
+ return resolvers.openers.helpers.textopener('zip',original,dfile)
+ elseif trace_locating then
+ report_zip("opener: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_zip("opener: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_zip("opener: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+
+function resolvers.loaders.zip(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = url.query(specification.query)
+ local queryname = query.name
+ if queryname then
+ local zfile = zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("loader: archive %a opened",archive)
+ end
+ local dfile = zfile:open(queryname)
+ if dfile then
+ logs.show_load(original)
+ if trace_locating then
+ report_zip("loader; file %a loaded",original)
+ end
+ local s = dfile:read("*all")
+ dfile:close()
+ return true, s, #s
+ elseif trace_locating then
+ report_zip("loader: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_zip("loader; unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_zip("loader: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+
+-- zip:///somefile.zip
+-- zip:///somefile.zip?tree=texmf-local -> mount
+
+function resolvers.usezipfile(archive)
+ local specification = resolvers.splitmethod(archive) -- to be sure
+ local archive = specification.filename
+ if archive and not registeredfiles[archive] then
+ local z = zip.openarchive(archive)
+ if z then
+ local instance = resolvers.instance
+ local tree = url.query(specification.query).tree or ""
+ if trace_locating then
+ report_zip("registering: archive %a",archive)
+ end
+ statistics.starttiming(instance)
+ resolvers.prependhash('zip',archive)
+ resolvers.extendtexmfvariable(archive) -- resets hashes too
+ registeredfiles[archive] = z
+ instance.files[archive] = resolvers.registerzipfile(z,tree)
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ report_zip("registering: unknown archive %a",archive)
+ end
+ elseif trace_locating then
+ report_zip("registering: archive %a not found",archive)
+ end
+end
+
+function resolvers.registerzipfile(z,tree)
+ local names = { }
+ local files = { } -- somewhat overkill .. todo
+ local remap = { } -- somewhat overkill .. todo
+ local n = 0
+ local filter = tree == "" and "^(.+)/(.-)$" or format("^%s/(.+)/(.-)$",tree)
+ local register = resolvers.registerfile
+ if trace_locating then
+ report_zip("registering: using filter %a",filter)
+ end
+ for i in z:files() do
+ local filename = i.filename
+ local path, name = match(filename,filter)
+ if not path then
+ n = n + 1
+ register(names,filename,"")
+ local usedname = lower(filename)
+ files[usedname] = ""
+ if usedname ~= filename then
+ remap[usedname] = filename
+ end
+ elseif name and name ~= "" then
+ n = n + 1
+ register(names,name,path)
+ local usedname = lower(name)
+ files[usedname] = path
+ if usedname ~= name then
+ remap[usedname] = name
+ end
+ else
+ -- directory
+ end
+ end
+ report_zip("registering: %s files registered",n)
+ return {
+ -- metadata = { },
+ files = files,
+ remap = remap,
+ }
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/enco-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/enco-ini.mkiv
new file mode 100644
index 00000000000..835ee61f575
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/enco-ini.mkiv
@@ -0,0 +1,546 @@
+%D \module
+%D [ file=enco-ini,
+%D version=2007.02.19, % 2000.12.27, % 1998.12.03,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is stripped down version of th eoriginal enco-ini.tex
+%D file. For more details you might want to study the \MKII\ file
+%D but since \LUATEX\ is unicode inside we need less code.
+
+% When dealing with characters we have four cases to take into account
+% when moving from mkii to mkiv:
+
+% 1. <byte 200> => ref to slot 200 in current font
+% 2. \char 200 => ref to slot 200 in current font
+% 3. <active 200> => can (e.g.) map to another slot in current font
+% 4. \namedglyph => can map to some slot in some font
+
+% Using case 2 for special characters is doomed to fail because we are not going
+% to intercept these on the fly as happens automatically with traditional font
+% encoding handling. We could do that in a node pass but it's not worth the effort
+% because we seldom use this case in a document source.
+
+% We can consider using utf as internal format for mkii. The main reason for not
+% doing this before was that it was slow. On the other hand, it would make dealing
+% with utility files easier. However, we've now kind of frozen mkii.
+
+\writestatus{loading}{ConTeXt Encoding Macros / Initialization}
+
+\unprotect
+
+%D Obsolete (but sometimes used in styles)
+
+\let\defaultencoding\s!default
+
+%D \macros
+%D {defineaccent, definecharacter, definecommand}
+
+\installcorenamespace{accents}
+
+\unexpanded\def\defineaccent#1 #2 #3 %
+ {\enco_define_accent_command{#1}%
+ \enco_define_accent{#1}{#2}{#3}}
+
+\unexpanded\def\enco_define_accent_command#1%
+ {\setevalue{\string#1}{\noexpand\enco_handle_accent{\string#1}}}
+
+\unexpanded\def\enco_define_accent#1#2#3% no spaces, used low level
+ {\setvalue{\??accents\string#1\string#2\empty}{#3}}
+
+% the following dirty trick is needed to catch \asciimath{\^{1/5}log}:
+
+\def\enco_handle_accent#1#2% expandable because we want them in the tuc file
+ {\csname\??accents
+ \ifcsname\??accents\string#1#2\empty\endcsname
+ \string#1#2\empty
+ \else\ifcsname\??accents\string#1\string#2\empty\endcsname
+ \string#1\string#2\empty
+ \else
+ \endcsname#2\csname\??accents % very dirty trick: ignore accent but keep char
+ \fi\fi
+ \endcsname}
+
+\letvalue{\??accents}\empty
+
+\unexpanded\def\enco_define_command#1#2%
+ {\setuvalue{\string#1}{#2}}
+
+\let\dohandleaccent \enco_handle_accent % maybe useful
+\let\dodefineaccent \enco_define_accent % used at the lua end
+\let\dodefineaccentcommand\enco_define_accent_command % used at the lua end
+\let\dodefinecommand \enco_define_command % used at the lua end
+
+\unexpanded\def\definecharacter#1 #2 %
+ {\doifelsenumber{\string#2}
+ {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax}
+ {\setuvalue{\string#1}{#2}}}
+
+\unexpanded\def\definecommand#1 #2 %
+ {\setuvalue{\string#1}{#2}}
+
+%D \macros
+%D {everyuppercase, everylowercase, everysanitize}
+
+\newtoks \everyuppercase
+\newtoks \everylowercase
+\newtoks \everysanitize
+
+%D Accent handling (try to avoid this):
+
+% \buildtextaccent\greekdasia\greekalphamacron
+% \buildtextaccent\textacute q
+
+\newbox\b_enco_accent
+
+\def\buildmathaccent#1%
+ {\mathaccent#1 }
+
+% \unexpanded\def\buildtextaccent#1#2% we could do all at the lua end
+% {\begingroup % but that's no fun (yet)
+% \setbox\b_enco_accent\hbox{#1}%
+% \scratchcounter\cldcontext{nodes.firstcharinbox(\number\b_enco_accent)}\relax
+% \ifcase\scratchcounter\else\accent\scratchcounter\fi
+% \relax#2%
+% \endgroup}
+
+% \unexpanded\def\buildtextaccent#1#2% we could do all at the lua end
+% {\begingroup % but that's no fun (yet)
+% \setbox\b_enco_accent\hbox{#1}%
+% \clf_buildtextaccent\b_enco_accent#2%
+% \endgroup}
+%
+% This one can handle font collections too. The accent command is a scanner
+% and the same font and otherwise discards the character (imo it could
+% better drop the accent).
+
+\unexpanded\def\buildtextaccent#1#2% we could do all at the lua end
+ {\dontleavehmode\begingroup % but that's no fun (yet)
+ \setbox\scratchboxone\hbox{#1}% accent
+ \setbox\scratchboxtwo\hbox{#2}% character
+ \scratchheight\dimexpr\ht\scratchboxtwo-\ht\scratchboxone\relax
+ \scratchdepth \dimexpr\dp\scratchboxtwo-\dp\scratchboxone\relax
+ \scratchwidth \wd\scratchboxtwo
+ \hbox to \wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi\bgroup
+ \hss\box\scratchboxtwo\hss
+ \hskip-\scratchwidth
+ \hss
+ \ifdim\ht\scratchboxone>\exheight
+ % top accent
+ \raise\dimexpr\scratchheight+\exheight/3\relax
+ \else
+ \lower-\dimexpr\scratchdepth+\exheight/3\relax
+ \fi
+ \box\scratchboxone
+ \hss
+ \egroup
+ \endgroup}
+
+\unexpanded\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode % why this align mess
+ \vtop
+ {\forgetall
+ \baselineskip\zeropoint
+ \lineskip#1%
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \lineskiplimit\zeropoint
+ \setbox0\hbox{#4}%
+ \halign
+ {##\crcr\hbox{#5}\crcr
+ \hidewidth
+ \hskip#2\wd0
+ \hskip-#3\slantperpoint % in plain 1ex * dimenless value
+ \vpack to .2\exheight{\box0\vss}\hidewidth
+ \crcr}}}
+
+\unexpanded\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}}
+\unexpanded\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}}
+\unexpanded\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}}
+\unexpanded\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}}
+\unexpanded\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}}
+
+\let\d\buildtextbottomdot
+
+\unexpanded\def\topaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode
+ \bgroup
+ \setbox0\hbox{#4}%
+ \setbox2\hbox{#5}%
+ \hbox to \wd2 \bgroup
+ \hss\copy2\hss
+ \hskip-\wd2
+ \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss
+ \egroup
+ \egroup}
+
+\unexpanded\def\buildtextgrave
+ {\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
+
+\unexpanded\def\definemathaccent#1 #2%
+ {\setvalue{#1}{\mathaccent#2 }}
+
+%D Math (will move):
+
+\definemathaccent acute \mathacute
+\definemathaccent grave \mathgrave
+\definemathaccent ddot \mathddot
+\definemathaccent tilde \mathtilde
+\definemathaccent bar \mathbar
+\definemathaccent breve \mathbreve
+\definemathaccent check \mathcheck
+\definemathaccent hat \mathhat
+\definemathaccent vec \mathvec
+\definemathaccent dot \mathdot
+% \definemathaccent widetilde \mathwidetilde
+% \definemathaccent widehat \mathwidehat
+
+% from enco-com:
+
+\def\AA{Å} \def\aa{å}
+\def\AE{Æ} \def\ae{æ}
+\def\CC{Ç} \def\cc{ç}
+\def \L{Ł} \def \l{ł}
+\def \O{Ø} \def \o{ø}
+\def\OE{Œ} \def\oe{œ}
+\def\SZ{SS} \def\sz{ß} \def\SS{ß}
+\def\IJ{IJ} \def\ij{ij}
+
+% from enco-def:
+
+\def\i{ı}
+\def\j{ȷ}
+
+\def\S{§} \def\textS {§} % obsolete (surfaced in bibliographic files)
+\def\P{¶} \def\textP {¶} % obsolete (surfaced in bibliographic files)
+
+\def\eszett {ß} \def\Eszett {SS} \def\Ssharp{SS}
+\def\lslash {ł} \def\Lslash {Ł}
+\def\dslash {đ} \def\Dslash {Đ}
+\def\oslash {ø} \def\Oslash {Ø}
+\def\dcroat {đ} \def\Dcroat {Đ}
+\def\kcedilla{ķ} \def\Kcedilla{Ķ}
+\def\lcedilla{ļ} \def\Lcedilla{Ļ}
+\def\ncedilla{ņ} \def\Ncedilla{Ņ}
+\def\rcedilla{ŗ} \def\Rcedilla{Ŗ}
+\def\aumlaut {ä} \def\Aumlaut {Ä}
+\def\eumlaut {ë} \def\Eumlaut {Ë}
+\def\iumlaut {ï} \def\Iumlaut {Ï}
+\def\oumlaut {ö} \def\Oumlaut {Ö}
+\def\uumlaut {ü} \def\Uumlaut {Ü}
+
+% for old times sake (obsolete)
+
+\def\textflorin{ƒ} \def\florin {ƒ}
+\def\pound {£} \def\sterling{£}
+\def\promille {‰} \def\permille{‰}
+
+% tex specific
+
+\ifdefined\textpercent
+ \let\percent \textpercent
+ \let\procent \textpercent
+ \let\ampersand \textampersand
+ \let\dollar \textdollar
+ \let\hash \texthash
+\else
+ \def\percent {\textpercent}
+ \def\procent {\textpercent}
+ \def\ampersand {\textampersand}
+ \def\dollar {\textdollar}
+ \def\hash {\texthash}
+\fi
+
+% from enco-mis:
+
+\unexpanded\def\fakepercent
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}}
+
+\unexpanded\def\fakeperthousand
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}}
+
+\unexpanded\def\fakepermine
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox
+ {\mathematics{+}}%
+ \hbox to \wd\scratchbox
+ {\hss
+ \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}%
+ \hss}%
+ \egroup}
+
+\def\permine{\fakepermine}
+
+% some more
+
+\ifdefined\softhyphen \else
+ \let\softhyphen\-
+\fi
+
+\def\hyphen {\softhyphen}
+\def\compoundwordmark {\hyphen}
+\def\cwm {\hyphen}
+\def\nonbreakinghyphen{\hyphen}
+\def\breakinghyphen {\hyphen\prewordbreak}
+
+% quotes
+
+\def\lowerleftsingleninequote {\quotesinglebase}
+\def\lowerleftdoubleninequote {\quotedblbase}
+\def\lowerrightsingleninequote {\quotesinglebase}
+\def\lowerrightdoubleninequote {\quotedblbase}
+
+\def\upperleftsingleninequote {\quoteright}
+\def\upperleftdoubleninequote {\quotedblright}
+\def\upperrightsingleninequote {\quoteright}
+\def\upperrightdoubleninequote {\quotedblright}
+
+\def\upperleftsinglesixquote {\quoteleft}
+\def\upperleftdoublesixquote {\quotedblleft}
+\def\upperrightsinglesixquote {\quoteleft}
+\def\upperrightdoublesixquote {\quotedblleft}
+
+\def\leftsubguillemot {\guilsingleleft}
+\def\rightsubguillemot {\guilsingleright}
+
+% left-overs (some day in private unicode space, so that we can roundtrip)
+
+\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}}
+\unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
+\unexpanded\def\schwagrave {\buildtextgrave\schwa}
+
+\chardef\textcontrolspace"2423
+
+\installcorenamespace{controlspace}
+
+% \unexpanded\def\fallbackcontrolspace % beware: non-matching widths
+% {\hbox to \interwordspace{\hss\getglyph{LMTypewriter-Regular}\textcontrolspace\hss}%
+
+\unexpanded\def\fallbackcontrolspace % beware, current font, we also need to honor color
+ {\hbox to \interwordspace \bgroup
+ \hss
+ \ifcsname\??controlspace\number\interwordspace\endcsname
+ \csname\??controlspace\number\interwordspace\endcsname
+ \else
+ \enco_fast_control_space_define % only regular
+ \fi
+ \textcontrolspace
+ \hss
+ \egroup}
+
+\unexpanded\def\enco_fast_control_space_define
+ {\scratchdimen\interwordspace
+ \definedfont[LMTypewriter-Regular at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody]% see font-sym.mkiv
+ \expandafter\glet\csname\??controlspace\number\scratchdimen\endcsname\lastrawfontcall}
+
+\unexpanded\def\normalcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \textcontrolspace
+ \else
+ \fallbackcontrolspace
+ \fi}
+
+\let\textvisiblespace\normalcontrolspace
+
+\unexpanded\def\optionalcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \textcontrolspace
+ \else
+ \asciispacechar % used for export !
+ \fi}
+
+% \unexpanded\def\fastcontrolspace % no glyph resolving after first (use grouped)
+% {\enco_fast_control_space}
+%
+% \def\enco_fast_control_space
+% {\iffontchar\font\textcontrolspace
+% \enco_fast_control_space_nop
+% \else
+% \enco_fast_control_space_yes
+% \fi
+% \enco_fast_control_space}
+%
+% \newbox\b_enco_control_space
+%
+% \def\enco_fast_control_space_nop
+% {\let\enco_fast_control_space\textcontrolspace}
+%
+% \def\enco_fast_control_space_yes
+% {\setbox\b_enco_control_space\fallbackcontrolspace
+% \let\enco_fast_control_space\flushcontrolspacebox}
+%
+% \def\flushcontrolspacebox
+% {\copy\b_enco_control_space}
+
+% a few defaults (\<whatever>{}), we really need the verbose \empty as it will be
+% stringified .. anyhow, we define this at the lua end now but keep it here as a
+% reference
+%
+% \defineaccent ^ {\empty} {\textcircumflex}
+% \defineaccent ` {\empty} {\textgrave}
+% \defineaccent ~ {\empty} {\texttilde}
+% \defineaccent " {\empty} {\textdiaeresis}
+% \defineaccent ' {\empty} {\textacute}
+% \defineaccent . {\empty} {\textdotaccent}
+% \defineaccent = {\empty} {\textmacron}
+% \defineaccent c {\empty} {\textcedilla}
+% \defineaccent H {\empty} {\texthungarumlaut}
+% \defineaccent k {\empty} {\textogonek}
+% \defineaccent r {\empty} {\textring}
+% \defineaccent u {\empty} {\textbreve}
+% \defineaccent v {\empty} {\textcaron}
+
+\clf_defineaccents % one time
+
+%D A smaller and bolder variant, more like the math and monospaced ones.
+
+\unexpanded\def\fakeunderscore
+ {\relax\ifmmode
+ \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax
+ \else
+ \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}%
+ \fi}
+
+\unexpanded\def\fakeunderscores{\let\_\fakeunderscore}
+\unexpanded\def\textunderscores{\let\_\textunderscore}
+
+\textunderscores
+
+\ifdefined\mathunderscore \else \let\mathunderscore\fakeunderscore \fi
+\ifdefined\textunderscore \else \let\textunderscore\fakeunderscore \fi
+
+\unexpanded\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi}
+
+\let\_\normalunderscore
+
+%D To be sorted out:
+
+\unexpanded\def\textminus
+ {\char \iffontchar\font"2012 "2012 % figuredash
+ \else\iffontchar\font"2013 "2013 % endash
+ \else\iffontchar\font"2212 "2212 % math minus
+ "002D % hyphen
+ \fi\fi\fi}
+
+\unexpanded\def\textplus
+ {\char"002B } % plus
+
+%D Moved from core-mis:
+
+\unexpanded\def\celsius #1{#1\mathematics{^\circ}C}
+\unexpanded\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
+\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}
+
+% \def\periodswidth {.5em}
+% \def\periodsdefault{3} % was 5, but now it's like \unknown
+%
+% \unexpanded\def\periods
+% {\dosingleempty\enco_periods}
+%
+% \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
+% {\dontleavehmode
+% \begingroup
+% \scratchdimen\periodswidth
+% \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen
+% {\leaders\hbox to \scratchdimen{\hss\periodsymbol\hss}\hss}%
+% \endgroup}
+%
+% better for export:
+%
+% \unexpanded\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2
+% {\dontleavehmode
+% \hbox\bgroup
+% \setbox\scratchbox\hbox to \periodswidth{\hss\periodsymbol\hss}%
+% \dorecurse{\iffirstargument#1\else\periodsdefault\fi}{\copy\scratchbox}%
+% \egroup}
+%
+% \unexpanded\def\unknown
+% {\periods\relax} % relax prevents lookahead for []
+%
+% per request:
+
+%D \startbuffer
+%D \startlines
+%D x\periods x
+%D x\periods[10]x
+%D x\periods[n=10,symbol={,}]x
+%D x\periods[n=4,symbol={!!},width=1em]x
+%D x\periods[n=4,symbol={!!},width=fit]x
+%D x\periods[n=4,symbol={!!},width=fit,distance=1em]x
+%D x\unknown x
+%D \stoplines
+%D \stopbuffer
+%D
+%D \typbuffer \getbuffer
+
+\def\periodswidth {.5\emwidth} % downward compatible
+\def\periodsdefault{3} % downward compatible
+
+\installcorenamespace {periods}
+
+\installsetuponlycommandhandler \??periods {periods}
+
+\setupperiods
+ [\c!n=\periodsdefault,
+ \c!width=\periodswidth, % can also be \v!fit
+ \c!distance=.25\emwidth,
+ \c!symbol=.]
+
+\unexpanded\def\periods
+ {\dontleavehmode
+ \hbox\bgroup
+ \doifelsenextoptional\enco_periods_yes\enco_periods_nop}
+
+\unexpanded\def\enco_periods_yes[#1]%
+ {\doifelseassignment{#1}
+ {\setupcurrentperiods[#1]%
+ \scratchcounter\periodsparameter\c!n}
+ {\doifelsenothing{#1}
+ {\scratchcounter\periodsparameter\c!n}%
+ {\scratchcounter#1}}%
+ \enco_periods_finish}
+
+\unexpanded\def\enco_periods_nop
+ {\scratchcounter\periodsparameter\c!n
+ \enco_periods_finish}
+
+\unexpanded\def\enco_periods_finish
+ {\edef\p_width{\periodsparameter\c!width}%
+ \ifx\p_width\v!fit
+ \enco_periods_finish_fit
+ \else
+ \enco_periods_finish_width
+ \fi
+ \egroup}
+
+\unexpanded\def\enco_periods_finish_width
+ {\setbox\scratchbox\hbox to \p_width
+ {\hss\periodsparameter\c!symbol\hss}%
+ \dorecurse\scratchcounter{\copy\scratchbox}}
+
+\unexpanded\def\enco_periods_finish_fit
+ {\edef\p_symbol{\periodsparameter\c!symbol}%
+ \scratchdistance\periodsparameter\c!distance
+ \hskip\scratchdistance
+ \dorecurse\scratchcounter{\p_symbol\hskip\scratchdistance}}
+
+\unexpanded\def\unknown
+ {\dontleavehmode
+ \hbox\bgroup
+ \enco_periods_nop}
+
+%D Left-overs:
+
+\appendtoks
+ \let\buildtextaccent\secondoftwoarguments
+\to \everysimplifycommands
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/export-example.css b/Master/texmf-dist/tex/context/base/mkiv/export-example.css
new file mode 100644
index 00000000000..8c7ae3bfc67
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/export-example.css
@@ -0,0 +1,864 @@
+/*
+
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright : PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+ comment : companion to context.mkiv
+
+*/
+
+/*
+
+ Because empty div elements are not seen we put a comment in them so that empty
+ table cells etc work ok.
+
+ We can style individual elements in several ways and we support in this css file
+ meaningful elements as well as divs. If needed you can use the chain field as well
+ as chain elements in the div class for styling groups.
+
+ \definefloat[myfloata]
+ \definefloat[myfloatb][myfloatbs][figure]
+
+ context|div.float.myfloata { } float[detail='myfloata'] { }
+ context|div.float.myfloatb { } float[detail='myfloatb'] { }
+ context|div.float.figure { } float[detail='figure'] { }
+ context|div.float.figure.myfloatb { } float[chain~='figure'][detail='myfloata'] { }
+ context|div.myfloata { } *[detail='myfloata'] { }
+ context|div.myfloatb { } *[detail='myfloatb'] { }
+ context|div.figure { } *[chain~='figure'] { }
+ context|div.figure.myfloatb { } *[chain~='figure'][detail='myfloatb'] { }
+
+*/
+
+@namespace context url('http://www.pragma-ade.com/context/export') ;
+
+/* ignore : mixed */
+/* metadata: display */
+
+ignore, context|div.ignore {
+ display : none ;
+}
+
+ignore, context|div.private {
+ display : none ;
+}
+
+xmetadata, context|div.xmetadata {
+ display : none ;
+}
+
+xmetavariable, context|div.xmetavariable {
+ display : none ;
+}
+
+/* document : display */
+
+document:before, context|div.document:before {
+ content : attr(title) ;
+ font-size : 44pt ;
+ font-weight : bold ;
+ margin-bottom : 1em ;
+}
+
+document, context|div.document {
+ font-family : "DejaVu Serif", "Lucida Bright", serif ;
+ font-size : 12pt ;
+ line-height : 14.4pt;
+ max-width : 50em ;
+ padding : 1em ;
+ /* text-align : justify ; */
+ text-align : justify ;
+ /* hyphens : manual ; */
+ /* text-justify : inter-word ; */
+}
+
+document>metadata, context|div.document context|div.metadata {
+ font-family : "DejaVu Sans Mono", "Lucida Console", monospace ;
+ margin-bottom : 2em ;
+}
+
+document>metadata>metavariable[name="title"]:before,
+ context|div.document context|div.metadata context|div.metavariable.name-title:before {
+ content : "title\00A0\00A0\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="author"]:before,
+ context|div.document context|div.metadata context|div.metavariable.name-author:before {
+ content : "author\00A0\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="version"]:before,
+ context|div.document context|div.metadata context|div.metavariable.name-version:before {
+ content : "version\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="title"], document>metadata>metavariable[name="author"], document>metadata>metavariable[name="version"],
+ context|div.document context|div.metadata context|div.metavariable.name-title, context|div.document context|div.metadata context|div.metavariable.name-author, context|div.document context|div.metadata context|div.metavariable.name-version {
+ display : block ;
+}
+
+/* paragraph : mixed */
+/* p : mixed */
+
+paragraph, p, context|div.paragraph, context|div.p {
+ display : block ;
+ margin-top : 0.5em ;
+ margin-bottom : 0.5em ;
+}
+
+/* break : display */
+
+break, context|div.break {
+ display : block ;
+ margin-bottom : 0.5em ;
+}
+
+/* construct : inline */
+/* highlight : inline */
+
+construct, context|div.construct {
+}
+
+construct[detail="important"], context|div.construct.important {
+ font-weight : bold ;
+}
+
+highlight, context|div.highlight { /* todo: style and color */
+ display : inline ;
+}
+
+/* section : display */
+/* sectiontitle : mixed */
+/* sectionnumber : mixed */
+/* sectioncontent : display */
+
+section, context|div.section {
+ display : block ;
+}
+
+sectioncontent, context|div.sectioncontent {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+}
+
+section[detail="chapter"], section[detail="title"],
+ context|div.section.chapter, context|div.section.title {
+ page-break-before : always ;
+ page-break-after : avoid ;
+ margin-top : 3em ;
+ margin-bottom : 2em ;
+}
+
+section[detail="section"], section[detail="subject"],
+ context|div.section.section, context|div.section.subject {
+ page-break-after : avoid ;
+ margin-top : 2.5em ;
+ margin-bottom : 2.5em ;
+}
+
+section[detail="subsection"], section[detail="subsubject"],
+ context|div.section.subsection, context|div.section.subsubject {
+ page-break-after : avoid ;
+ margin-top : 2em ;
+ margin-bottom : 2em ;
+}
+
+section[detail="subsubsection"], section[detail="subsubsubject"],
+ context|div.section.subsubsection, context|div.section.subsubsubject {
+ page-break-after : avoid ;
+ margin-top : 1em ;
+ margin-bottom : 0em ;
+}
+
+section[detail="summary"], section[detail="subsummary"],
+ context|div.section.summary, context|div.section.subsummary {
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+}
+
+section[detail="chapter"]>sectionnumber,
+ context|div.section.chapter context|div.sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 3em ;
+ font-weight : bold ;
+}
+
+section[detail="chapter"]>sectiontitle, section[detail="title"]>sectiontitle,
+ context|div.section.chapter context|div.sectiontitle, context|div.section.title context|div.sectiontitle {
+ display : inline-block ;
+ font-size : 3em ;
+ font-weight : bold ;
+}
+
+section[detail="section"]>sectiontitle, section[detail="subject"]>sectiontitle,
+ context|div.section.section context|div.sectiontitle, context|div.section.subject context|div.sectiontitle {
+ display : inline-block ;
+ font-size : 2.5em ;
+ font-weight : bold ;
+}
+
+section[detail="subsection"]>sectiontitle, section[detail="subsubject"]>sectiontitle,
+ context|div.section.subsection context|div.sectiontitle, context|div.section.subsubject context|div.sectiontitle {
+ display : inline-block ;
+ font-size : 2em ;
+ font-weight : bold ;
+}
+
+section[detail="subsubsection"]>sectiontitle, section[detail="subsubsubject"]>sectiontitle,
+ context|div.section.subsubsection context|div.sectiontitle, context|div.section.subsubsubject context|div.sectiontitle {
+ display : inline-block ;
+ font-size : 1em ;
+ font-weight : bold ;
+}
+
+section[detail="section"]>sectionnumber, context|div.section.section context|div.sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 2.5em ;
+ font-weight : bold ;
+}
+
+section[detail="summary"]>sectiontitle, context|div.section.summary context|div.sectiontitle {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ font-weight : bold ;
+ border-bottom-style : solid ;
+ border-color : rgb(50%,50%,100%) ;
+ border-width : .15em;
+}
+
+section[detail="subsection"]>sectionnumber, context|div.section.subsection context|div.sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 1em ;
+ font-weight : bold ;
+}
+
+section[detail="subsummary"]>sectiontitle, context|div.section.subsummary context|div.sectiontitle {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ font-weight : bold ;
+ border-color : rgb(50%,50%,100%) ;
+ border-bottom-style : dotted ;
+ border-width : .15em ;
+}
+
+/* itemgroup : display */
+/* item : display */
+/* itemtag : mixed */
+/* itemcontent : mixed */
+
+/* type : alphabetic ; */
+/* suffix : '.' ; */
+
+@counter-style lower-greek { /* css 3 */
+ type : non-repeating ;
+ glyphs : 'α' 'β' 'γ' 'δ' 'ε' 'ζ' 'η' 'θ' 'ι' 'κ' 'λ' 'μ' 'ν' 'ξ' 'ο' 'π' 'ρ' 'σ' 'τ' 'υ' 'φ' 'χ' 'ψ' 'ω' ;
+}
+
+@counter-style upper-greek { /* css 3 */
+ type : non-repeating ;
+ glyphs : 'Α' 'B' 'Γ' 'Δ' 'Ε' 'Ζ' 'Η' 'Θ' 'Ι' 'Κ' 'Λ' 'Μ' 'Ν' 'Ξ' 'Ο' 'Π' 'Ρ' 'Σ' 'Τ' 'Υ' 'Φ' 'Χ' 'Ψ' 'Ω' ;
+}
+
+itemgroup, context|div.itemgroup {
+ display : block ;
+ margin-bottom : 0.5em ;
+ margin-top : 0.5em ;
+}
+
+itemgroup[symbol="1"], context|div.itemgroup.symbol-1 { list-style-type : disc ; }
+itemgroup[symbol="2"], context|div.itemgroup.symbol-2 { list-style-type : square ; }
+itemgroup[symbol="3"], context|div.itemgroup.symbol-3 { list-style-type : square ; }
+itemgroup[symbol="4"], context|div.itemgroup.symbol-4 { list-style-type : square ; }
+itemgroup[symbol="5"], context|div.itemgroup.symbol-5 { list-style-type : circ ; }
+itemgroup[symbol="a"], context|div.itemgroup.symbol-a { list-style-type : lower-alpha ; }
+itemgroup[symbol="A"], context|div.itemgroup.symbol-A { list-style-type : alpha ; }
+itemgroup[symbol="r"], context|div.itemgroup.symbol-r { list-style-type : lower-roman ; }
+itemgroup[symbol="R"], context|div.itemgroup.symbol-R { list-style-type : upper-roman ; }
+itemgroup[symbol="n"], context|div.itemgroup.symbol-n { list-style-type : decimal ; }
+itemgroup[symbol="g"], context|div.itemgroup.symbol-g { list-style-type : lower-greek ; }
+itemgroup[symbol="G"], context|div.itemgroup.symbol-G { list-style-type : upper-greek ; }
+
+item, context|div.item {
+ display : list-item ;
+ margin-left : 1em ;
+ margin-bottom : 0.5em ;
+ margin-top : 0.5em ;
+}
+
+itemtag, context|div.item {
+ display: none ;
+}
+
+itemcontent, context|div.itemcontent {
+}
+
+/* description : display */
+/* descriptiontag : mixed */
+/* descriptioncontent : mixed */
+/* descriptionsymbol : inline */
+
+description, context|div.description {
+ display : block ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+}
+
+descriptiontag, context|div.descriptiontag {
+ display : inline ;
+ float : left ;
+ clear : left ;
+ margin-right : 1em ;
+ text-align : left ;
+ font-weight : bold ;
+}
+
+descriptioncontent, context|div.descriptioncontent {
+}
+
+descriptionsymbol, context|div.descriptionsymbol {
+ display : inline ;
+}
+
+/* verbatimblock : display */
+/* verbatimlines : display */
+/* verbatimline : mixed */
+/* verbatim : inline */
+
+verbatimblock, context|div.verbatimblock {
+ background-color : rgb(50%,50%,100%) ;
+ display : block ;
+ padding : 1em ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+ font-family : "DejaVu Sans Mono", "Lucida Console", monospace ;
+}
+
+verbatimlines+verbatimlines, context|div.verbatimlines+context|div.verbatimlines {
+ display : block ;
+ margin-top : 1em ;
+}
+
+verbatimline, context|div.verbatimline {
+ display : block ;
+ white-space : pre-wrap ;
+}
+
+verbatim, context|div.verbatim {
+ display : inline ;
+ white-space : pre-wrap ;
+ color : rgb(60%,60%,0%) ;
+ font-family : "DejaVu Sans Mono", "Lucida Console", monospace ;
+}
+
+/* lines : display */
+/* line : mixed */
+
+lines, context|div.lines {
+ display : block ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+}
+
+lines+lines, context|div.lines+context|div.lines {
+ display : block ;
+ margin-top : 1em ;
+}
+
+line, context|div.line {
+ display : block ;
+ white-space : pre-wrap ;
+}
+
+/* synonym : inline */
+/* sorting : inline */
+
+sorting, synonym, context|div.sorting, context|div.synonym {
+ display : inline ;
+ font-variant : small-caps ;
+}
+
+/* register : display */
+/* registersection : display */
+/* registertag : mixed */
+/* registerentries : display */
+/* registerentry : mixed */
+/* registersee : mixed */
+/* registerpages : mixed */
+/* registerpage : inline */
+/* registerpagerange : mixed */
+
+register, context|div.register {
+ display: none ;
+}
+
+registerlocation, context|div.registerlocation {
+ display: inline ;
+}
+
+registerlocation:after, context|div.registerlocation:after {
+ content : "\25B6\00A0\00A0" ;
+ color : rgb(40%,40%,40%) ;
+ font-size : x-small ;
+ line-height : 0 ;
+ padding-top : 0.5ex ;
+ vertical-align : top ;
+}
+
+/* table : display */
+/* tablerow : display */
+/* tablecell : mixed */
+
+table, context|div.table {
+ display : table ;
+}
+
+tablerow, context|div.tablerow {
+ display : table-row ;
+}
+
+tablecell[align="middle"], context|div.tablecell.align-middle {
+ display : table-cell ;
+ text-align : center ;
+ padding : .1em ;
+}
+
+tablecell[align="flushleft"], context|div.tablecell.align-flushleft {
+ display : table-cell ;
+ text-align : left ;
+ padding : .1em ;
+}
+
+tablecell[align="flushright"], context|div.tablecell.align-flushright {
+ display : table-cell ;
+ text-align : right ;
+ padding : .1em ;
+}
+
+tablecell, context|div.tablecell {
+ display : table-cell ;
+ text-align : left ;
+ padding : .1em ;
+}
+
+/* tabulate : display */
+/* tabulaterow : display */
+/* tabulatecell : mixed */
+
+tabulate, context|div.tabulate {
+ display : table ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+floatcontent>tabulate, context|div.floatcontent context|div.tabulate {
+ margin-left : 0em ;
+}
+
+tabulaterow, context|div.tabulaterow {
+ display : table-row ;
+}
+
+tabulatecell[align="middle"], context|div.tabulatecell.align-middle {
+ display : table-cell ;
+ text-align : center ;
+ padding-right : 1em ;
+}
+
+tabulatecell[align="flushleft"], context|div.tabulatecell.align-flushleft {
+ display : table-cell ;
+ text-align : left ;
+ padding-right : 1em ;
+}
+
+tabulatecell[align="flushright"], context|div.tabulatecell.align-flushright {
+ display : table-cell ;
+ text-align : right ;
+ padding-right : 1em ;
+}
+
+tabulatecell, context|div.tabulatecell {
+ display : table-cell ;
+ text-align : left ;
+ padding-right : 1em ;
+}
+
+/* combination : display */
+/* combinationpair : display */
+/* combinationcontent : mixed */
+/* combinationcaption : mixed */
+
+combination, context|div.combination {
+ display : table ;
+ margin-top : 0em ;
+ margin-bottom : 0em ;
+}
+
+combinationpair, context|div.combinationpair {
+ display : table-cell ;
+ padding-right : 1em ;
+}
+
+combinationcontent, context|div.combinationcontent {
+ display : table-row ;
+ text-align : center ;
+}
+
+combinationcaption, context|div.combinationcaption {
+ display : table-row ;
+ padding-top : 1ex ;
+ text-align : center ;
+}
+
+
+/* list : display */
+/* listitem : display */
+/* listtag : mixed */
+/* listcontent : mixed */
+/* listdata : mixed */
+/* listpage : mixed */
+
+list, context|div.list {
+ display : block ;
+}
+
+listitem[detail="chapter"], context|div.listitem.chapter {
+ display : block ;
+ margin-top : 1em ;
+ font-weight : bold ;
+}
+
+listitem[detail="section"], context|div.listitem.section {
+ display : block ;
+}
+
+listitem[detail="subsection"], context|div.listitem.subsection {
+ display : block ;
+ display : inline-block ;
+}
+
+listtag, context|div.listtag {
+ display : inline-block ;
+ width : 5em ;
+}
+
+listcontent, context|div.listcontent {
+ display : inline-block ;
+}
+
+listdata, context|div.listdata {
+ display : inline-block ;
+}
+
+listpage, context|div.listpage {
+ display : none ;
+}
+
+/* delimitedblock : display */
+/* delimited : inline */
+/* delimitedsymbol : inline */
+/* delimitedcontent : inline */
+/* subsentence : inline */
+/* subsentencesymbol : inline */
+/* subsentencecontent : inline */
+
+/* :lang(en) */
+
+delimited[detail="quotation"]:before, delimitedblock[detail="quotation"]:before,
+ context|div.delimited.quotation:before, context|div.delimitedblock.quotation:before {
+ /* content : "\201C" ; */
+ font-style : italic ;
+}
+
+delimited[detail="quotation"]:after, delimitedblock[detail="quotation"]:after,
+ context|div.delimited.quotation:after, context|div.delimitedblock.quotation:after {
+ /* content : "\201D" ; */
+ font-style : italic ;
+}
+
+delimited[detail="quote"]:before, delimitedblock[detail="quote"]:before,
+ context|div.delimited.quote:before, context|div.delimitedblock.quote:before {
+ /* content : "\2018" ; */
+ font-style : italic ;
+}
+
+delimited[detail="quote"]:after, delimitedblock[detail="quote"]:after,
+ context|div.delimited.quote:after, context|div.delimitedblock.quote:after {
+ /* content : "\2019" ; */
+ font-style : italic ;
+}
+
+delimited, context|div.delimited {
+ display : inline
+}
+
+delimitedcontent, context|div.delimitedcontent {
+ display : inline
+}
+
+delimitedsymbol, context|div.delimitedsymbol {
+ display : inline
+}
+
+delimitedblock, context|div.delimitedblock {
+ display : block
+}
+
+subsentence:before, subsentence:after, context|div.subsentence:before, context|div.subsentence:after {
+ content : "\2014" ;
+}
+
+subsentence, context|div.subsentence {
+ display : inline
+}
+
+subsentencecontent, context|div.subsentencecontent {
+ display : inline
+}
+
+subsentencesymbol, context|div.subsentencesymbol {
+ display : inline
+}
+
+/* label : mixed */
+/* number : mixed */
+
+/* float : display */
+/* floatcaption : mixed */
+/* floatlabel : inline */
+/* floatnumber : inline */
+/* floattext : mixed */
+/* floatcontent : mixed */
+
+float, context|div.float {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+floatcaption, context|div.floatcaption {
+ display : block ;
+ margin-top : 0.5em ;
+ color : rgb(60%,60%,0%) ;
+}
+
+floatlabel, context|div.floatlabel {
+ display : inline-block ;
+ font-weight : bold ;
+ margin-right : 0.25em ;
+}
+
+floatnumber, context|div.floatnumber {
+ display : inline ;
+ font-weight : bold ;
+ margin-right : 0.25em ;
+}
+
+floattext, context|div.floattext {
+ display : inline ;
+}
+
+floatcontent, context|div.floatcontent {
+}
+
+/* image : mixed */
+/* mpgraphic : mixed */
+
+/* image {
+ display : block ;
+ background : url(hacker.jpg) ;
+ background-size : 100% auto ;
+ width : 8.992cm ;
+ height : 5.994cm ;
+} */
+
+mpgraphic:before, context|div.mpgraphic:before { /* does not work with empty element */
+ content : "[runtime metapost graphic]" ;
+}
+
+mpgraphic, context|div.mpgraphic {
+ display : inline ;
+}
+
+/* formula : display */
+/* subformula : display */
+/* formulaset : display */
+/* formulacaption : mixed */
+/* formulalabel : mixed */
+/* formulanumber : mixed */
+/* formulacontent : display */
+
+formula, context|div.formula {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+subformula, context|div.subformula { /* todo */
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+formulaset, context|div.formulaset { /* todo */
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+formulacaption, context|div.formulacaption { /* todo */
+ display : block ;
+ margin-top : 0.5em ;
+ color : rgb(60%,60%,0%) ;
+}
+
+formulalabel, context|div.formulalabel {
+ display : inline ;
+ font-weight : bold ;
+ margin-right : .25em ;
+}
+
+formulanumber, context|div.formulanumber {
+ display : inline ;
+ font-weight : bold ;
+}
+
+formulacontent, context|div.formulacontent {
+ display : block ;
+}
+
+link, context|div.link {
+ display : inline ;
+}
+
+/* margintextblock : inline */
+/* margintext : inline */
+
+margintext, context|div.margintext {
+ display : block ;
+ font-weight : bold ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+}
+
+margintext:before, context|div.margintext:before {
+ content : "\25B6\00A0\00A0" ;
+ color : rgb(40%,40%,40%) ;
+}
+
+/* math : inline | display */
+/* mn : mixed */
+/* mi : mixed */
+/* mo : mixed */
+/* ms : mixed */
+/* mrow : display */
+/* msubsup : display */
+/* msub : display */
+/* msup : display */
+/* merror : mixed */
+/* munderover : display */
+/* munder : display */
+/* mover : display */
+/* mtext : mixed */
+/* mfrac : display */
+/* mroot : display */
+/* msqrt : display */
+/* mfenced : display */
+/* maction : display */
+/* mtable : display */
+/* mtr : display */
+/* mtd : display */
+
+context|div.math-inline {
+ display : inline ;
+ vertical-align : 0 ; /* this will be set directly */
+}
+
+context|div.math-display {
+ display : block ;
+ margin : 1ex 0ex 1em 3em ;
+}
+
+/* quantity : inline */
+/* unit : inline */
+/* number : inline */
+
+quantity, context|div.quantity {
+ display : inline-block ;
+}
+
+quantity>unit, context|div.quantity>context|div.unit {
+ display : inline ;
+}
+
+quantity>number, context|div.quantity>context|div.number {
+ display : inline ;
+}
+
+/* sub : inline */
+/* sup : inline */
+/* subsup : inline */
+
+sup, context|div.sup {
+ display : inline-block ;
+ font-size : xx-small ;
+ vertical-align : super ;
+}
+
+sub, context|div.sub {
+ display : inline-block ;
+ font-size : xx-small ;
+ vertical-align : sub ;
+}
+
+subsup>sup, context|div.subsup>context|div.sup {
+ display : inline ;
+ vertical-align : top ;
+}
+
+subsup>sub, context|div.subsup>context|div.sub {
+ display : inline ;
+ vertical-align : bottom ;
+}
+
+/* links */
+
+context|div[href]:hover {
+ color : rgb(50%,0%,0%) ;
+ background-color : rgb(85%,85%,85%) ;
+}
+
+/* setups */
+
+setup, context|div.setup {
+ display : block ;
+}
+
+comment, context|div.comment {
+ background-color : rgb(50%,75%,100%) ;
+ display : block ;
+ padding : 1em ;
+ margin-bottom : 2ex ;
+ margin-top : 2ex ;
+ font-family : "DejaVu Sans Mono", "Lucida Console", monospace ;
+}
+
+/* special */
+
+c, context|div.c {
+ display : inline ;
+}
+
+warning, context|div.warning {
+ display : none ;
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/export-example.rng b/Master/texmf-dist/tex/context/base/mkiv/export-example.rng
new file mode 100644
index 00000000000..93b21ba50bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/export-example.rng
@@ -0,0 +1,377 @@
+# author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+# copyright : PRAGMA ADE / ConTeXt Development Team
+# license : see context related readme files
+# comment : companion to context.mkiv
+
+# todo: check all content (not yet ok but a bit boring job)
+# todo: add attributes
+# todo: we need more | and less ,
+#
+# validate with "rnv -c export-example.rng"
+
+namespace m = "http://www.w3.org/1998/Math/MathML"
+
+start = e_document
+
+# Because users can typeset anything the content is somewhat
+# unpredictable so this is just an indication of what to expect.
+
+c_everything =
+ text
+ | c_inline
+ | e_verbatimblock
+ | e_lines
+ | e_itemgroup
+ | e_table
+ | e_tabulate
+ | e_register
+ | e_list
+ | e_section
+ | e_float
+ | e_formula
+ | e_combination
+
+c_inline =
+ text
+ | e_ignore
+ | e_metadata
+ | e_construct
+ | e_highlight
+ | e_verbatim
+ | e_description
+ | e_descriptionsymbol
+ | e_sorting
+ | e_synonym
+ | e_image
+ | e_mpgraphic
+ | e_math
+ | e_sub
+ | e_sup
+ | e_subsup
+ | e_link
+ | e_margintext
+ | e_margintextblock
+
+# We pass some relevant information via attributes. The detail attribute
+# is common and provides information about the class or environment used.
+
+a_detail = attribute detail {
+ text
+}
+
+# The document element is the root of all.
+
+e_document = element document {
+ c_everything *
+}
+
+e_ignore = element ignore {
+ c_everything *
+}
+
+e_metadata = element metadata {
+ element metavariable {
+ attribute name { text } ?
+ , text
+ } *
+}
+
+e_section = element section {
+ a_detail ?
+ | (
+ element sectiontitle {
+ c_inline *
+ }
+ , element sectionnumber {
+ c_inline *
+ } *
+ , element sectioncontent {
+ c_everything *
+ }
+ )
+}
+
+e_paragraph = element paragraph {
+ c_inline *
+}
+
+e_p = element p {
+ c_inline *
+}
+
+e_break = element break {
+ empty
+}
+
+e_construct = element construct {
+ c_everything*
+}
+
+e_highlight = element highlight {
+ c_inline*
+}
+
+e_itemgroup = element itemgroup {
+ element item {
+ element itemtag {
+ c_inline *
+ }
+ } ,
+ element itemcontent {
+ c_everything *
+ }
+}
+
+e_combination = element combination {
+ element combinationpair {
+ element combinationcontent {
+ inline*
+ } ,
+ element combinationcaption {
+ inline*
+ }
+ }
+}
+
+e_description = element description {
+ element descriptiontag {
+ c_inline*
+ } ,
+ element descriptioncontent {
+ c_inline*
+ } ,
+ element descriptionsymbol {
+ c_inline*
+ }
+}
+
+e_descriptionsymbol = element descriptionsymbol {
+ c_inline*
+}
+
+e_verbatimblock = element verbatimblock {
+ element verbatimlines {
+ element verbatimline {
+ text
+ } *
+ } *
+}
+
+e_verbatim = element verbatim {
+ text
+}
+
+e_lines = element lines {
+ element line {
+ text
+ } *
+}
+
+e_synonym = element synonym {
+ text
+}
+
+e_sorting = element sorting {
+ text
+}
+
+e_register = element register {
+ element registersection {
+ element registertag {
+ text
+ } ?
+ ,
+ element registerentries {
+ (
+ element registerentry {
+ text
+ } |
+ element registersee {
+ text
+ }
+ ),
+ (
+ element registerpages {
+ element registerpage {
+ text
+ } *
+ } |
+ element registerpage {
+ text
+ } |
+ element registerpagerange {
+ element registerpage {
+ text
+ } ,
+ element registerpage {
+ text
+ }
+ }
+ )
+ } ?
+ } *
+}
+
+e_table = element table {
+ element tablerow {
+ element tablecell {
+ c_inline *
+ } *
+ } *
+}
+
+e_tabulate = element tabulate {
+ element tabulaterow {
+ element tabulatecell {
+ c_inline *
+ } *
+ } *
+}
+
+e_list = element list {
+ element listitem {
+ element listtag {
+ text
+ } ? ,
+ element listcontent {
+ text
+ } ? ,
+ element listdata {
+ text
+ } ? ,
+ element listpage {
+ text
+ } ?
+ }
+}
+
+e_delimitedblock = element delimitedblock {
+ c_everything*
+}
+
+e_delimited = element delimited {
+ c_inline
+}
+
+e_subsentence = element subsentence {
+ c_inline
+}
+
+e_float = element float {
+ element floatcaption {
+ element floatlabel {
+ text
+ } ,
+ element floatnumber {
+ text
+ } ,
+ element floattext {
+ c_inline
+ }
+ } ,
+ element floatcontent {
+ c_inline
+ }
+}
+
+e_image = element image {
+ empty
+}
+
+e_mpgraphic = element mpgraphic {
+ empty
+}
+
+e_formula = element formula {
+ element subformula {
+ element formulacontent {
+ e_math*
+ }
+ } ,
+ element formulaset {
+ element formulacontent {
+ e_math*
+ }
+ } ,
+ element formulacaption {
+ element formulalabel {
+ text
+ } ,
+ element formulanumber {
+ text
+ }
+ } ,
+ element formulacontent {
+ e_math*
+ }
+}
+
+e_link = element link {
+ c_inline
+}
+
+e_margintextblock = element margintextblock {
+ c_inline
+}
+
+e_margintext = element margintext {
+ c_inline
+}
+
+e_quantity = element quantity {
+ element unit {
+ text
+ } ,
+ element number {
+ text
+ }
+}
+
+e_unit = element unit {
+ text |
+ e_math
+}
+
+e_sub = element sub {
+ c_inline
+}
+
+e_sup = element sup {
+ c_inline
+}
+
+e_subsup = element subsup {
+ c_inline,
+ c_inline
+}
+
+# There are enough mathml dtd's out there so this is just a
+# simplified placeholder.
+
+e_math_basics =
+ element m:mn | m:mi | m:mo | m:ms | m:merror | m:mtext {
+ text
+ } |
+ element m:mrow | m:msub | m:msup | m:msqrt | m:mfenced | m:maction {
+ e_math_basics *
+ } |
+ element m:msubsup | m:munder | m:mover | m:mfrac | m:mroot {
+ e_math_basics,
+ e_math_basics
+ } |
+ element m:munderover {
+ e_math_basics,
+ e_math_basics,
+ e_math_basics
+ } |
+ element m:mtable {
+ element m:mtr {
+ element m:mtd {
+ e_math_basics *
+ } *
+ } *
+ }
+
+e_math = element m:math {
+ e_math_basics *
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/export-example.tex b/Master/texmf-dist/tex/context/base/mkiv/export-example.tex
new file mode 100644
index 00000000000..32cb79c5ea2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/export-example.tex
@@ -0,0 +1,118 @@
+% language=uk
+
+\usemodule[abr-01]
+
+\setupexport
+ [%bodyfont=16pt,
+ width=650pt,
+ %align=flushleft,
+ hyphen=yes]
+
+\setupbackend
+ [export=yes]
+
+% \setupalign
+% [flushleft]
+
+\settaggedmetadata
+ [title=Export Example,
+ author=Hans Hagen,
+ version=0.1]
+
+\setupbodyfont
+ [dejavu]
+
+\setupinteraction
+ [state=start]
+
+\setuplayout
+ [width=middle]
+
+\setupwhitespace
+ [big]
+
+\definedescription
+ [description]
+
+\enabledirectives[export.css.hyphens=yes]
+\enabledirectives[export.css.textwidth=100em]
+
+\definehighlight[interesting][style=bold,color=red]
+
+\starttext
+
+\startchapter[title=Example]
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\startparagraph
+ Watching a \interesting {movie} after reading a review on \goto{my favourite movie
+ reviews site}[url(http://outlawvern.com/)] is much more fun. \footnote {Just a note.}
+\stopparagraph
+
+\placefigure
+ {}
+ {\startcombination[3*1]
+ {\externalfigure[hacker.jpg][width=3cm]} {first}
+ {\externalfigure[hacker.jpg][width=4cm]} {second}
+ {\externalfigure[hacker.jpg][width=2cm]} {third}
+ \stopcombination}
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\placefigure
+ {}
+ {\externalfigure[mill.png]}
+
+\startparagraph \input tufte (Tufte) \stopparagraph
+
+\placefigure
+ {}
+ {\externalfigure[cow.pdf]}
+
+\startparagraph \input tufte (Tufte) \stopparagraph
+
+\startitemize[1]
+ \startitem \input ward (Ward) \stopitem
+ \startitem \input knuth (Knuth) \stopitem
+\stopitemize
+
+\startitemize[2,packed]
+ \startitem \input zapf (Zapf) \stopitem
+ \startitem \input tufte (Tufte) \stopitem
+\stopitemize
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\startdescription {Ward} \input ward \stopdescription
+
+\startdescription {Tufte} \input tufte \stopdescription
+
+\startparagraph \input knuth (Knuth) \stopparagraph
+
+\startformula
+e = mc^2
+\stopformula
+
+\startparagraph
+Okay, it's somewhat boring to always use the same formula, so how about
+$\sqrt{4} = 2$ or travelling at \unit{120 km/h} instead of $\unit{110 km/h}$.
+\stopparagraph
+
+\bTABLE
+\bTR \bTD test \eTD \bTD test \eTD \eTR
+\bTR \bTD[nx=2] test \eTD \eTR
+\eTABLE
+
+\starttabulate[|l|r|p|]
+\NC left \NC right \NC \input ward \NC \NR
+\NC l \NC r \NC \input ward \NC \NR
+\stoptabulate
+
+It looks like we're using \CONTEXT\ to produce some kind of \XML\ output.
+
+\typefile{export-example.tex}
+
+\stopchapter
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/file-ini.lua
new file mode 100644
index 00000000000..2a0271a9d80
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-ini.lua
@@ -0,0 +1,52 @@
+if not modules then modules = { } end modules ['file-ini'] = {
+ version = 1.001,
+ comment = "companion to file-ini.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>It's more convenient to manipulate filenames (paths) in <l n='lua'/> than in
+<l n='tex'/>. These methods have counterparts at the <l n='tex'/> end.</p>
+--ldx]]--
+
+
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+local setcount = interfaces.setcount
+
+resolvers.jobs = resolvers.jobs or { }
+
+local filenametotable = file.nametotable
+local findtexfile = resolvers.findtexfile
+
+local commands_doifelse = commands.doifelse
+
+local function splitfilename(full)
+ local split = filenametotable(full)
+ local path = split.path
+ setcount("splitoffkind",(path == "" and 0) or (path == '.' and 1) or 2)
+ setmacro("splitofffull",full or "")
+ setmacro("splitoffpath",path or "")
+ setmacro("splitoffname",split.name or "")
+ setmacro("splitoffbase",split.base or "")
+ setmacro("splitofftype",split.suffix or "")
+end
+
+local function isparentfile(name)
+ return
+ name == environment.jobname
+ or name == environment.jobname .. '.tex'
+ or name == environment.outputfilename
+end
+
+local function istexfile(name)
+ local name = name and findtexfile(name)
+ return name ~= "" and name
+end
+
+implement { name = "splitfilename", actions = splitfilename, arguments = "string" }
+implement { name = "doifelseparentfile", actions = { isparentfile, commands_doifelse }, arguments = "string" }
+implement { name = "doifelsepathexist", actions = { lfs.isdir, commands_doifelse }, arguments = "string" }
+implement { name = "doifelsefileexist", actions = { istexfile, commands_doifelse }, arguments = "string" }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-ini.mkvi
new file mode 100644
index 00000000000..9f12e9a3ba2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-ini.mkvi
@@ -0,0 +1,239 @@
+%D \module
+%D [ file=file-ini, % was supp-fil,
+%D version=20110701, % 1995.10.10,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Helpers,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D \TEX\ operates on files, so one wouldn't wonder that there
+%D is a separate module for file commands. In \CONTEXT\ files
+%D are used for several purposes:
+%D
+%D \startitemize[packed]
+%D \item general textual input
+%D \item logging status information
+%D \item saving registers, lists and references
+%D \item buffering defered textual input
+%D \stopitemize
+%D
+%D When dealing with files we can load them as a whole, using
+%D the \type{\input} primitive or load them on a line||by||line
+%D basis, using \type{\read}. Writing is always done line by
+%D line, using \type{\write}.
+
+\writestatus{loading}{ConTeXt File Macros / Helpers}
+
+\registerctxluafile{file-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {scratchread, scratchwrite}
+%D
+%D We define a scratch file for reading. Keep in mind that
+%D the number of files is limited to~16, so use this one when
+%D possible. We also define a scratch output file.
+
+\ifdefined\scratchread \else \newread \scratchread \fi
+\ifdefined\scratchwrite \else \newwrite\scratchwrite \fi
+
+%D Seldom needed:
+
+\def\openinputfile #handle#name{\immediate\openin #handle={#name}\relax}
+\def\openoutputfile #handle#name{\immediate\openout#handle={#name}\relax}
+
+\def\closeinputfile #handle{\immediate\closein #handle\relax}
+\def\closeoutputfile#handle{\immediate\closeout#handle\relax}
+
+%D \macros
+%D {writeln}
+%D
+%D This saves a few tokens:
+
+\def\writeln#handle{\write#handle{}}
+
+%D \macros
+%D {pushendofline,popendofline}
+%D
+%D When we are loading files in the middle of the typesetting
+%D process, for instance when we load references, we have to be
+%D sure that the reading process does not generate so called
+%D 'spurious spaces'. This can be prevented by assigning the
+%D line ending character the \CATCODE\ comment. This is
+%D accomplished by
+%D
+%D \starttyping
+%D \pushendofline
+%D ... reading ...
+%D \popendofline
+%D \stoptyping
+
+\installsystemnamespace{eolstack}
+
+\newcount\c_system_files_eol_level
+
+\unexpanded\def\pushendofline
+ {\advance\c_system_files_eol_level\plusone
+ \expandafter\chardef\csname\??eolstack\number\c_system_files_eol_level\endcsname\catcode\endoflineasciicode
+ \catcode\endoflineasciicode\commentcatcode}
+
+\unexpanded\def\popendofline
+ {\catcode\endoflineasciicode\csname\??eolstack\number\c_system_files_eol_level\endcsname
+ \advance\c_system_files_eol_level\minusone}
+
+\unexpanded\def\restoreendofline
+ {\catcode\endoflineasciicode\endoflinecatcode}
+
+%D \macros
+%D {startreadingfile,stopreadingfile}
+%D
+%D A low level capsule:
+
+\newcount\readingfilelevel % no longer needed
+\newtoks \everystartreadingfile
+\newtoks \everystopreadingfile
+
+\unexpanded\def\startreadingfile% beter een every en \setnormalcatcodes
+ {\global\advance\readingfilelevel\plusone
+ \the\everystartreadingfile
+ \pushcatcodetable % saveguard
+ \setcatcodetable\ctxcatcodes
+ \clf_pushregime}% temporarily this way
+
+\unexpanded\def\stopreadingfile
+ {\popcatcodetable % saveguard
+ \clf_popregime % temporarily this way
+ \the\everystopreadingfile
+ \global\advance\readingfilelevel\minusone}
+
+%D \macros
+%D {input, normalinput}
+%D
+%D Sometimes we run into troubles when \type {\input} wants to get
+%D expanded, e.g. in a \type {\write} (which happens in the metafun
+%D manual when we permit long MP lines). So, instead of fixing that,
+%D we go for a redefinition of \type {\input}. Of course it's better
+%D to use \type {\readfile} or \type {\processfile}.
+
+\unexpanded\def\input{\normalinput}
+
+\def\inputgivenfile#name{\normalinput{#name}}
+
+%D \macros
+%D {doifelsefile}
+%D
+%D The next alternative only looks if a file is present. No
+%D loading is done. This one obeys the standard \TEX\ lookup.
+%D
+%D \starttyping
+%D \doiffileelse {filename} {found} {not found}
+%D \stoptyping
+
+\unexpanded\def\doifelsefile {\clf_doifelsefileexist}
+\unexpanded\def\doifelsepath {\clf_doifelsepathexist}
+\unexpanded\def\doiffile #name{\clf_doifelsefileexist{#name}\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotfile #name{\clf_doifelsefileexist{#name}\gobbleoneargument\firstofoneargument}
+
+\let\doiffileelse\doifelsefile
+\let\doifpathelse\doifelsepath
+
+\let\doifelsefileexists\doifelsefile
+\let\doifelsepathexists\doifelsepath
+
+\let\doiffileexistselse\doifelsefileexists
+\let\doifpathexistselse\doifelsepathexists
+
+%D \macros
+%D {doifparentfileelse}
+%D
+%D \starttyping
+%D \doifparentfileelse{filename}{yes}{no}
+%D \stoptyping
+
+\ifx\outputfilename\undefined \def\outputfilename{\jobname} \fi
+
+\unexpanded\def\doifelseparentfile{\clf_doifelseparentfile}
+
+\let\doifparentfileelse\doifelseparentfile
+
+%D \macros
+%D {splitfilename}
+%D
+%D \startbuffer
+%D \def\showfilesplit
+%D {\bgroup \tttf
+%D \hbox{(full: \splitofffull)}\space
+%D \hbox{(path: \splitoffpath)}\space
+%D \hbox{(base: \splitoffbase)}\space
+%D \hbox{(name: \splitoffname)}\space
+%D \hbox{(type: \splitofftype)}\space
+%D \egroup}
+%D
+%D \splitfilename{c:/aa/bb/cc/dd.ee.ff} \showfilesplit \endgraf
+%D \splitfilename{c:/aa/bb/cc/dd.ee} \showfilesplit \endgraf
+%D \splitfilename{c:/aa/bb/cc/dd} \showfilesplit \endgraf
+%D
+%D \splitfilename{dd.ee.ff} \showfilesplit \endgraf
+%D \splitfilename{dd.ee} \showfilesplit \endgraf
+%D \splitfilename{dd} \showfilesplit \endgraf
+%D \stopbuffer
+%D
+%D \start \typebuffer \getbuffer \stop
+
+\newconstant\kindoffile % 0=normal 1=full path spec (or http) / set at the lua end
+
+\def\splitoffroot{.} \newconstant\splitoffkind
+
+\let\splitofffull\empty
+\let\splitoffpath\empty
+\let\splitoffbase\empty
+\let\splitoffname\empty
+\let\splitofftype\empty
+
+\unexpanded\def\splitfilename{\clf_splitfilename}
+
+%D \macros
+%D {doonlyonce, doinputonce, doendinputonce}
+%D
+%D Especially macropackages need only be loaded once.
+%D Repetitive loading not only costs time, relocating registers
+%D often leads to abortion of the processing because \TEX's
+%D capacity is limited. One can prevent multiple execution and
+%D loading by using one of both:
+%D
+%D \starttyping
+%D \doonlyonce{actions}
+%D \doinputonce{filename}
+%D \doendinputonce{filename}
+%D \stoptyping
+%D
+%D This command obeys the standard method for locating files. We could
+%D move this function to the \LUA\ end.
+
+\installsystemnamespace {fileonce}
+
+\unexpanded\def\doonlyonce#whatever%
+ {\ifcsname\??fileonce#whatever\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \letgvalue{\??fileonce#whatever}\relax
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doinputonce#name%
+ {\doonlyonce{#name}{\doifelsefile{#name}{\inputgivenfile{#name}}\donothing}}
+
+\unexpanded\def\doendinputonce#name%
+ {\ifcsname\??fileonce#name\endcsname
+ \expandafter\endinput
+ \fi}
+
+\unexpanded\def\forgetdoingonce#whatever%
+ {\global\undefinevalue{\??fileonce#whatever}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-job.lua b/Master/texmf-dist/tex/context/base/mkiv/file-job.lua
new file mode 100644
index 00000000000..602c41a118c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-job.lua
@@ -0,0 +1,1225 @@
+if not modules then modules = { } end modules ['file-job'] = {
+ version = 1.001,
+ comment = "companion to file-job.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- in retrospect dealing it's not that bad to deal with the nesting
+-- and push/poppign at the tex end
+
+local rawget = rawget
+local gsub, match, find = string.gsub, string.match, string.find
+local insert, remove, concat = table.insert, table.remove, table.concat
+local validstring, formatters = string.valid, string.formatters
+local sortedhash = table.sortedhash
+
+local commands = commands
+local resolvers = resolvers
+local context = context
+
+local ctx_doifelse = commands.doifelse
+
+local implement = interfaces.implement
+
+local trace_jobfiles = false trackers.register("system.jobfiles", function(v) trace_jobfiles = v end)
+
+local report_jobfiles = logs.reporter("system","jobfiles")
+local report_functions = logs.reporter("system","functions")
+
+local texsetcount = tex.setcount
+local elements = interfaces.elements
+local constants = interfaces.constants
+local variables = interfaces.variables
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+local settings_to_array = utilities.parsers.settings_to_array
+local allocate = utilities.storage.allocate
+
+local nameonly = file.nameonly
+local suffixonly = file.suffix
+local basename = file.basename
+local addsuffix = file.addsuffix
+local removesuffix = file.removesuffix
+local dirname = file.dirname
+local joinpath = file.join
+local is_qualified_path = file.is_qualified_path
+
+local cleanpath = resolvers.cleanpath
+local inputstack = resolvers.inputstack
+local resolveprefix = resolvers.resolve
+
+local hasscheme = url.hasscheme
+
+local jobresolvers = resolvers.jobs
+
+local registerextrapath = resolvers.registerextrapath
+local resetextrapath = resolvers.resetextrapath
+local pushextrapath = resolvers.pushextrapath
+local popextrapath = resolvers.popextrapath
+
+local v_outer = variables.outer
+local v_text = variables.text
+local v_project = variables.project
+local v_environment = variables.environment
+local v_product = variables.product
+local v_component = variables.component
+local v_yes = variables.yes
+
+-- main code .. there is some overlap .. here we have loc://
+
+local function findctxfile(name) -- loc ? any ?
+ if is_qualified_path(name) then -- maybe when no suffix do some test for tex
+ return name
+ elseif not hasscheme(name) then
+ return resolvers.finders.byscheme("loc",name) or ""
+ else
+ return resolvers.findtexfile(name) or ""
+ end
+end
+
+resolvers.findctxfile = findctxfile
+
+implement {
+ name = "processfile",
+ arguments = "string",
+ actions = function(name)
+ name = findctxfile(name)
+ if name ~= "" then
+ context.input(name)
+ end
+ end
+}
+
+implement {
+ name = "doifelseinputfile",
+ arguments = "string",
+ actions = function(name)
+ ctx_doifelse(findctxfile(name) ~= "")
+ end
+}
+
+implement {
+ name = "locatefilepath",
+ arguments = "string",
+ actions = function(name)
+ context(dirname(findctxfile(name)))
+ end
+}
+
+implement {
+ name = "usepath",
+ arguments = "string",
+ actions = function(paths)
+ report_jobfiles("using path: %s",paths)
+ registerextrapath(paths)
+ end
+}
+
+implement {
+ name = "pushpath",
+ arguments = "string",
+ actions = function(paths)
+ report_jobfiles("pushing path: %s",paths)
+ pushextrapath(paths)
+ end
+}
+
+implement {
+ name = "poppath",
+ actions = function(paths)
+ popextrapath()
+ report_jobfiles("popping path")
+ end
+}
+
+implement {
+ name = "usesubpath",
+ arguments = "string",
+ actions = function(subpaths)
+ report_jobfiles("using subpath: %s",subpaths)
+ registerextrapath(nil,subpaths)
+ end
+}
+
+implement {
+ name = "resetpath",
+ actions = function()
+ report_jobfiles("resetting path")
+ resetextrapath()
+ end
+}
+
+implement {
+ name = "allinputpaths",
+ actions = function()
+ context(concat(resolvers.instance.extra_paths or { },","))
+ end
+}
+
+implement {
+ name = "usezipfile",
+ arguments = { "string", "string" },
+ actions = function(name,tree)
+ if tree and tree ~= "" then
+ resolvers.usezipfile(formatters["zip:///%s?tree=%s"](name,tree))
+ else
+ resolvers.usezipfile(formatters["zip:///%s"](name))
+ end
+ end
+}
+
+local report_system = logs.reporter("system")
+
+-- moved from tex to lua:
+
+local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
+local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua" }
+local cldpatterns = { "%s.cld" }
+local xmlpatterns = { "%s.xml" }
+
+local uselibrary = resolvers.uselibrary
+local input = context.input
+
+-- status
+--
+-- these need to be synced with input stream:
+
+local processstack = { }
+local processedfile = ""
+local processedfiles = { }
+
+implement {
+ name = "processedfile",
+ actions = function()
+ context(processedfile)
+ end
+}
+
+implement {
+ name = "processedfiles",
+ actions = function()
+ context(concat(processedfiles,","))
+ end
+}
+
+implement {
+ name = "dostarttextfile",
+ arguments = "string",
+ actions = function(name)
+ insert(processstack,name)
+ processedfile = name
+ insert(processedfiles,name)
+ end
+}
+
+implement {
+ name = "dostoptextfile",
+ actions = function()
+ processedfile = remove(processstack) or ""
+ end
+}
+
+local function startprocessing(name,notext)
+ if not notext then
+ -- report_system("begin file %a at line %a",name,status.linenumber or 0)
+ context.dostarttextfile(name)
+ end
+end
+
+local function stopprocessing(notext)
+ if not notext then
+ context.dostoptextfile()
+ -- report_system("end file %a at line %a",name,status.linenumber or 0)
+ end
+end
+
+--
+
+local typestack = { }
+local currenttype = v_text
+
+--
+
+local action = function(name,foundname) input(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","tex",name) end
+
+local function usetexfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = texpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","lua",name) end
+
+local function useluafile(name,onlyonce,notext)
+ uselibrary {
+ name = name,
+ patterns = luapatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","cld",name) end
+
+local function usecldfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = cldpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) context.xmlprocess(foundname,"main","") end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","xml",name) end
+
+local function usexmlfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = xmlpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local suffixes = {
+ mkvi = usetexfile,
+ mkiv = usetexfile,
+ tex = usetexfile,
+ luc = useluafile,
+ lua = useluafile,
+ cld = usecldfile,
+ xml = usexmlfile,
+ [""] = usetexfile,
+}
+
+local function useanyfile(name,onlyonce)
+ local s = suffixes[suffixonly(name)]
+ context(function() resolvers.pushpath(name) end)
+ if s then
+ -- s(removesuffix(name),onlyonce)
+ s(name,onlyonce) -- so, first with suffix, then without
+ else
+ usetexfile(name,onlyonce) -- e.g. ctx file
+ -- resolvers.readfilename(name)
+ end
+ context(resolvers.poppath)
+end
+
+implement { name = "usetexfile", actions = usetexfile, arguments = "string" }
+implement { name = "useluafile", actions = useluafile, arguments = "string" }
+implement { name = "usecldfile", actions = usecldfile, arguments = "string" }
+implement { name = "usexmlfile", actions = usexmlfile, arguments = "string" }
+
+implement { name = "usetexfileonce", actions = usetexfile, arguments = { "string", true } }
+implement { name = "useluafileonce", actions = useluafile, arguments = { "string", true } }
+implement { name = "usecldfileonce", actions = usecldfile, arguments = { "string", true } }
+implement { name = "usexmlfileonce", actions = usexmlfile, arguments = { "string", true } }
+
+implement { name = "useanyfile", actions = useanyfile, arguments = "string" }
+implement { name = "useanyfileonce", actions = useanyfile, arguments = { "string", true } }
+
+function jobresolvers.usefile(name,onlyonce,notext)
+ local s = suffixes[suffixonly(name)]
+ if s then
+ -- s(removesuffix(name),onlyonce,notext)
+ s(name,onlyonce,notext) -- so, first with suffix, then without
+ end
+end
+
+-- document structure
+
+local textlevel = 0 -- inaccessible for user, we need to define counter textlevel at the tex end
+
+local function dummyfunction() end
+
+local function startstoperror()
+ report_system("invalid \\%s%s ... \\%s%s structure",elements.start,v_text,elements.stop,v_text)
+ startstoperror = dummyfunction
+end
+
+local stopped
+
+local function starttext()
+ if textlevel == 0 then
+ if trace_jobfiles then
+ report_jobfiles("starting text")
+ end
+ -- registerfileinfo[begin]jobfilename
+ context.dostarttext()
+ end
+ textlevel = textlevel + 1
+ texsetcount("global","textlevel",textlevel)
+end
+
+local function stoptext()
+ if not stopped then
+ if textlevel == 0 then
+ startstoperror()
+ elseif textlevel > 0 then
+ textlevel = textlevel - 1
+ end
+ texsetcount("global","textlevel",textlevel)
+ if textlevel <= 0 then
+ if trace_jobfiles then
+ report_jobfiles("stopping text")
+ end
+ context.dostoptext()
+ -- registerfileinfo[end]jobfilename
+ context.finalend()
+ stopped = true
+ end
+ end
+end
+
+implement { name = "starttext", actions = starttext }
+implement { name = "stoptext", actions = stoptext }
+
+implement {
+ name = "forcequitjob",
+ arguments = "string",
+ actions = function(reason)
+ if reason then
+ report_system("forcing quit: %s",reason)
+ else
+ report_system("forcing quit")
+ end
+ context.batchmode()
+ while textlevel >= 0 do
+ context.stoptext()
+ end
+ end
+}
+
+implement {
+ name = "forceendjob",
+ actions = function()
+ report_system([[don't use \end to finish a document]])
+ context.stoptext()
+ end
+}
+
+implement {
+ name = "autostarttext",
+ actions = function()
+ if textlevel == 0 then
+ report_system([[auto \starttext ... \stoptext]])
+ end
+ context.starttext()
+ end
+}
+
+implement {
+ name = "autostoptext",
+ actions = stoptext
+}
+
+-- project structure
+
+implement {
+ name = "processfilemany",
+ arguments = { "string", false },
+ actions = useanyfile
+}
+
+implement {
+ name = "processfileonce",
+ arguments = { "string", true },
+ actions = useanyfile
+}
+
+implement {
+ name = "processfilenone",
+ arguments = "string",
+ actions = dummyfunction,
+}
+
+local tree = { type = "text", name = "", branches = { } }
+local treestack = { }
+local top = tree.branches
+local root = tree
+
+local project_stack = { }
+local product_stack = { }
+local component_stack = { }
+local environment_stack = { }
+
+local stacks = {
+ [v_project ] = project_stack,
+ [v_product ] = product_stack,
+ [v_component ] = component_stack,
+ [v_environment] = environment_stack,
+}
+
+--
+
+local report_structures = logs.reporter("system","structure")
+local report_structure = logs.reporter("used structure")
+
+local function pushtree(what,name)
+ local t = { }
+ top[#top+1] = { type = what, name = name, branches = t }
+ insert(treestack,top)
+ top = t
+end
+
+local function poptree()
+ top = remove(treestack)
+ -- inspect(top)
+end
+
+local function log_tree(top,depth)
+ report_structure("%s%s: %s",depth,top.type,top.name)
+ local branches = top.branches
+ if #branches > 0 then
+ depth = depth .. " "
+ for i=1,#branches do
+ log_tree(branches[i],depth)
+ end
+ end
+end
+
+luatex.registerstopactions(function()
+ logspushtarget("logfile")
+ logsnewline()
+ report_structures("start used structure")
+ logsnewline()
+ root.name = environment.jobname
+ log_tree(root,"")
+ logsnewline()
+ report_structures("stop used structure")
+ logsnewline()
+ logspoptarget()
+end)
+
+local jobstructure = job.structure or { }
+job.structure = jobstructure
+jobstructure.collected = jobstructure.collected or { }
+jobstructure.tobesaved = root
+jobstructure.components = { }
+
+local function initialize()
+ local function collect(root,result)
+ local branches = root.branches
+ if branches then
+ for i=1,#branches do
+ local branch = branches[i]
+ if branch.type == "component" then
+ result[#result+1] = branch.name
+ end
+ collect(branch,result)
+ end
+ end
+ return result
+ end
+ jobstructure.components = collect(jobstructure.collected,{})
+end
+
+job.register('job.structure.collected',root,initialize)
+
+-- component: small unit, either or not components itself
+-- product : combination of components
+
+local context_processfilemany = context.processfilemany
+local context_processfileonce = context.processfileonce
+local context_processfilenone = context.processfilenone
+
+-- we need a plug in the nested loaded, push pop pseudo current dir
+
+local function processfilecommon(name,action)
+ -- experiment, might go away
+-- if not hasscheme(name) then
+-- local path = dirname(name)
+-- if path ~= "" then
+-- registerextrapath(path)
+-- report_jobfiles("adding search path %a",path)
+-- end
+-- end
+ -- till here
+ action(name)
+end
+
+local function processfilemany(name) processfilecommon(name,context_processfilemany) end
+local function processfileonce(name) processfilecommon(name,context_processfileonce) end
+local function processfilenone(name) processfilecommon(name,context_processfilenone) end
+
+local processors = utilities.storage.allocate {
+ -- [v_outer] = {
+ -- [v_text] = { "many", processfilemany },
+ -- [v_project] = { "once", processfileonce },
+ -- [v_environment] = { "once", processfileonce },
+ -- [v_product] = { "once", processfileonce },
+ -- [v_component] = { "many", processfilemany },
+ -- },
+ [v_text] = {
+ [v_text] = { "many", processfilemany },
+ [v_project] = { "once", processfileonce }, -- dubious
+ [v_environment] = { "once", processfileonce },
+ [v_product] = { "many", processfilemany }, -- dubious
+ [v_component] = { "many", processfilemany },
+ },
+ [v_project] = {
+ [v_text] = { "many", processfilemany },
+ [v_project] = { "none", processfilenone },
+ [v_environment] = { "once", processfileonce },
+ [v_product] = { "none", processfilenone },
+ [v_component] = { "none", processfilenone },
+ },
+ [v_environment] = {
+ [v_text] = { "many", processfilemany },
+ [v_project] = { "none", processfilenone },
+ [v_environment] = { "once", processfileonce },
+ [v_product] = { "none", processfilenone },
+ [v_component] = { "none", processfilenone },
+ },
+ [v_product] = {
+ [v_text] = { "many", processfilemany },
+ [v_project] = { "once", processfileonce },
+ [v_environment] = { "once", processfileonce },
+ [v_product] = { "many", processfilemany },
+ [v_component] = { "many", processfilemany },
+ },
+ [v_component] = {
+ [v_text] = { "many", processfilemany },
+ [v_project] = { "once", processfileonce },
+ [v_environment] = { "once", processfileonce },
+ [v_product] = { "none", processfilenone },
+ [v_component] = { "many", processfilemany },
+ }
+}
+
+local start = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.startreadingfile,
+ [v_product] = context.starttext,
+ [v_component] = context.starttext,
+}
+
+local stop = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.stopreadingfile,
+ [v_product] = context.stoptext,
+ [v_component] = context.stoptext,
+}
+
+jobresolvers.processors = processors
+
+local function topofstack(what)
+ local stack = stacks[what]
+ return stack and stack[#stack] or environment.jobname
+end
+
+local function productcomponent() -- only when in product
+ local product = product_stack[#product_stack]
+ if product and product ~= "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+local function justacomponent()
+ local product = product_stack[#product_stack]
+ if not product or product == "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+jobresolvers.productcomponent = productcomponent
+jobresolvers.justacomponent = justacomponent
+
+function jobresolvers.currentproject () return topofstack(v_project ) end
+function jobresolvers.currentproduct () return topofstack(v_product ) end
+function jobresolvers.currentcomponent () return topofstack(v_component ) end
+function jobresolvers.currentenvironment() return topofstack(v_environment) end
+
+local done = { }
+local tolerant = false -- too messy, mkii user with the wrong structure should adapt
+
+local function process(what,name)
+ local depth = #typestack
+ local process
+ --
+ name = resolveprefix(name)
+ --
+-- if not tolerant then
+ -- okay, would be best but not compatible with mkii
+ process = processors[currenttype][what]
+-- elseif depth == 0 then
+-- -- could be a component, product or (brr) project
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 1)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- elseif depth == 1 and typestack[1] == v_text then
+-- -- we're still not doing a component or product
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 2)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- else
+-- process = processors[currenttype][what]
+-- end
+ if process then
+ local method = process[1]
+ if method == "none" then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"ignoring",what,name,currenttype,topofstack(currenttype))
+ end
+ elseif method == "once" and done[name] then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"skipping",what,name,currenttype,topofstack(currenttype))
+ end
+ else
+ -- keep in mind that we also handle "once" at the file level
+ -- so there is a double catch
+ done[name] = true
+ local before = start[what]
+ local after = stop [what]
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"processing",what,name,currenttype,topofstack(currenttype))
+ end
+ if before then
+ before()
+ end
+ process[2](name)
+ if after then
+ after()
+ end
+ end
+ else
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,"none","ignoring",what,name,currenttype,topofstack(currenttype))
+ end
+ end
+end
+
+implement { name = "useproject", actions = function(name) process(v_project, name) end, arguments = "string" }
+implement { name = "useenvironment", actions = function(name) process(v_environment,name) end, arguments = "string" }
+implement { name = "useproduct", actions = function(name) process(v_product, name) end, arguments = "string" } -- will be overloaded
+implement { name = "usecomponent", actions = function(name) process(v_component, name) end, arguments = "string" }
+
+-- todo: setsystemmode to currenttype
+-- todo: make start/stop commands at the tex end
+
+local start = {
+ [v_project] = context.startprojectindeed,
+ [v_product] = context.startproductindeed,
+ [v_component] = context.startcomponentindeed,
+ [v_environment] = context.startenvironmentindeed,
+}
+
+local stop = {
+ [v_project] = context.stopprojectindeed,
+ [v_product] = context.stopproductindeed,
+ [v_component] = context.stopcomponentindeed,
+ [v_environment] = context.stopenvironmentindeed,
+}
+
+local function gotonextlevel(what,name) -- todo: something with suffix name
+ insert(stacks[what],name)
+ insert(typestack,currenttype)
+ currenttype = what
+ pushtree(what,name)
+ if start[what] then
+ start[what]()
+ end
+end
+
+local function gotopreviouslevel(what)
+ if stop[what] then
+ stop[what]()
+ end
+ poptree()
+ currenttype = remove(typestack) or v_text
+ remove(stacks[what]) -- not currenttype ... weak recovery
+ -- context.endinput() -- does not work
+ context.signalendofinput(what)
+end
+
+local function autoname(name)
+ if name == "*" then
+ name = nameonly(inputstack[#inputstack] or name)
+ end
+ return name
+end
+
+implement { name = "startproject", actions = function(name) gotonextlevel(v_project, autoname(name)) end, arguments = "string" }
+implement { name = "startproduct", actions = function(name) gotonextlevel(v_product, autoname(name)) end, arguments = "string" }
+implement { name = "startcomponent", actions = function(name) gotonextlevel(v_component, autoname(name)) end, arguments = "string" }
+implement { name = "startenvironment", actions = function(name) gotonextlevel(v_environment,autoname(name)) end, arguments = "string" }
+
+implement { name = "stopproject", actions = function() gotopreviouslevel(v_project ) end }
+implement { name = "stopproduct", actions = function() gotopreviouslevel(v_product ) end }
+implement { name = "stopcomponent", actions = function() gotopreviouslevel(v_component ) end }
+implement { name = "stopenvironment", actions = function() gotopreviouslevel(v_environment) end }
+
+implement { name = "currentproject", actions = function() context(topofstack(v_project )) end }
+implement { name = "currentproduct", actions = function() context(topofstack(v_product )) end }
+implement { name = "currentcomponent", actions = function() context(topofstack(v_component )) end }
+implement { name = "currentenvironment", actions = function() context(topofstack(v_environment)) end }
+
+-- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+--
+-- <?xml version='1.0' standalone='yes'?>
+-- <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
+-- <exa:variable label='mode:pragma'>nee</exa:variable>
+-- <exa:variable label='mode:variant'>standaard</exa:variable>
+-- </exa:variables>
+--
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+local report_examodes = logs.reporter("system","examodes")
+
+local function convertexamodes(str)
+ local x = xml.convert(str)
+ for e in xml.collected(x,"exa:variable") do
+ local label = e.at and e.at.label
+ if label and label ~= "" then
+ local data = xml.text(e)
+ local mode = match(label,"^mode:(.+)$")
+ if mode then
+ context.enablemode { formatters["%s:%s"](mode,data) }
+ end
+ context.setvariable("exa:variables",label,(gsub(data,"([{}])","\\%1")))
+ end
+ end
+end
+
+function environment.loadexamodes(filename)
+ if not filename or filename == "" then
+ filename = removesuffix(tex.jobname)
+ end
+ filename = resolvers.findfile(addsuffix(filename,'ctm')) or ""
+ if filename ~= "" then
+ report_examodes("loading %a",filename) -- todo: message system
+ convertexamodes(io.loaddata(filename))
+ else
+ report_examodes("no mode file %a",filename) -- todo: message system
+ end
+end
+
+implement {
+ name = "loadexamodes",
+ actions = environment.loadexamodes,
+ arguments = "string"
+}
+
+-- changed in mtx-context
+-- code moved from luat-ini
+
+-- todo: locals when mtx-context is changed
+
+document = document or {
+ arguments = allocate(),
+ files = allocate(),
+ variables = allocate(), -- for templates
+ options = {
+ commandline = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ ctxfile = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ },
+ functions = table.setmetatablenewindex(function(t,k,v)
+ if rawget(t,k) then
+ report_functions("overloading document function %a",k)
+ end
+ rawset(t,k,v)
+ return v
+ end),
+}
+
+function document.setargument(key,value)
+ document.arguments[key] = value
+end
+
+function document.setdefaultargument(key,default)
+ local v = document.arguments[key]
+ if v == nil or v == "" then
+ document.arguments[key] = default
+ end
+end
+
+function document.setfilename(i,name)
+ if name then
+ document.files[tonumber(i)] = name
+ else
+ document.files[#document.files+1] = tostring(i)
+ end
+end
+
+function document.getargument(key,default)
+ local v = document.arguments[key]
+ if type(v) == "boolean" then
+ v = (v and "yes") or "no"
+ document.arguments[key] = v
+ end
+ return v or default or ""
+end
+
+function document.getfilename(i)
+ return document.files[tonumber(i)] or ""
+end
+
+implement {
+ name = "setdocumentargument",
+ actions = document.setargument,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setdocumentdefaultargument",
+ actions = document.setdefaultargument,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setdocumentfilename",
+ actions = document.setfilename,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "getdocumentargument",
+ actions = { document.getargument, context },
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "getdocumentfilename",
+ actions = { document.getfilename, context },
+ arguments = "integer"
+}
+
+function document.setcommandline() -- has to happen at the tex end in order to expand
+
+ -- the document[arguments|files] tables are copies
+
+ local arguments = document.arguments
+ local files = document.files
+ local options = document.options
+
+ for k, v in next, environment.arguments do
+ k = gsub(k,"^c:","") -- already done, but better be safe than sorry
+ if arguments[k] == nil then
+ arguments[k] = v
+ end
+ end
+
+ -- in the new mtx=context approach we always pass a stub file so we need to
+ -- to trick the files table which actually only has one entry in a tex job
+
+ if arguments.timing then
+ context.usemodule("timing")
+ end
+
+ if arguments.batchmode then
+ context.batchmode(false)
+ end
+
+ if arguments.nonstopmode then
+ context.nonstopmode(false)
+ end
+
+ if arguments.nostatistics then
+ directives.enable("system.nostatistics")
+ end
+
+ if arguments.paranoid then
+ context.setvalue("maxreadlevel",1)
+ end
+
+ if validstring(arguments.path) then
+ context.usepath { arguments.path }
+ end
+
+ if arguments.export then
+ context.setupbackend { export = v_yes }
+ end
+
+ local inputfile = validstring(arguments.input)
+
+ if inputfile and dirname(inputfile) == "." and lfs.isfile(inputfile) then
+ -- nicer in checks
+ inputfile = basename(inputfile)
+ end
+
+ local forcedruns = arguments.forcedruns
+ local kindofrun = arguments.kindofrun
+ local currentrun = arguments.currentrun
+ local maxnofruns = arguments.maxnofruns or arguments.runs
+
+ -- context.setupsystem {
+ -- [constants.directory] = validstring(arguments.setuppath),
+ -- [constants.inputfile] = inputfile,
+ -- [constants.file] = validstring(arguments.result),
+ -- [constants.random] = validstring(arguments.randomseed),
+ -- -- old:
+ -- [constants.n] = validstring(kindofrun),
+ -- [constants.m] = validstring(currentrun),
+ -- }
+
+ context.setupsystem {
+ directory = validstring(arguments.setuppath),
+ inputfile = inputfile,
+ file = validstring(arguments.result),
+ random = validstring(arguments.randomseed),
+ -- old:
+ n = validstring(kindofrun),
+ m = validstring(currentrun),
+ }
+
+ forcedruns = tonumber(forcedruns) or 0
+ kindofrun = tonumber(kindofrun) or 0
+ maxnofruns = tonumber(maxnofruns) or 0
+ currentrun = tonumber(currentrun) or 0
+
+ local prerollrun = forcedruns > 0 and currentrun > 0 and currentrun < forcedruns
+
+ environment.forcedruns = forcedruns
+ environment.kindofrun = kindofrun
+ environment.maxnofruns = maxnofruns
+ environment.currentrun = currentrun
+ environment.prerollrun = prerollrun
+
+ context.setconditional("prerollrun",prerollrun)
+
+ if validstring(arguments.arguments) then
+ context.setupenv { arguments.arguments }
+ end
+
+ if arguments.once then
+ directives.enable("system.runonce")
+ end
+
+ if arguments.noarrange then
+ context.setuparranging { variables.disable }
+ end
+
+ --
+
+ local commandline = options.commandline
+
+ commandline.environments = table.append(commandline.environments,settings_to_array(validstring(arguments.environment)))
+ commandline.modules = table.append(commandline.modules, settings_to_array(validstring(arguments.usemodule)))
+ commandline.modes = table.append(commandline.modes, settings_to_array(validstring(arguments.mode)))
+
+ --
+
+ if #files == 0 then
+ local list = settings_to_array(validstring(arguments.files))
+ if list and #list > 0 then
+ files = list
+ end
+ end
+
+ if #files == 0 then
+ files = { validstring(arguments.input) }
+ end
+
+ --
+
+ document.arguments = arguments
+ document.files = files
+
+end
+
+-- commandline wins over ctxfile
+
+local function apply(list,action)
+ if list then
+ for i=1,#list do
+ action { list[i] }
+ end
+ end
+end
+
+function document.setmodes() -- was setup: *runtime:modes
+ apply(document.options.ctxfile .modes,context.enablemode)
+ apply(document.options.commandline.modes,context.enablemode)
+end
+
+function document.setmodules() -- was setup: *runtime:modules
+ apply(document.options.ctxfile .modules,context.usemodule)
+ apply(document.options.commandline.modules,context.usemodule)
+end
+
+function document.setenvironments() -- was setup: *runtime:environments
+ apply(document.options.ctxfile .environments,context.environment)
+ apply(document.options.commandline.environments,context.environment)
+end
+
+function document.setfilenames()
+ local initialize = environment.initializefilenames
+ if initialize then
+ initialize()
+ else
+ -- fatal error
+ end
+end
+
+implement { name = "setdocumentcommandline", actions = document.setcommandline, onlyonce = true }
+implement { name = "setdocumentmodes", actions = document.setmodes, onlyonce = true }
+implement { name = "setdocumentmodules", actions = document.setmodules, onlyonce = true }
+implement { name = "setdocumentenvironments", actions = document.setenvironments, onlyonce = true }
+implement { name = "setdocumentfilenames", actions = document.setfilenames, onlyonce = true }
+
+local report_files = logs.reporter("system","files")
+local report_options = logs.reporter("system","options")
+local report_file = logs.reporter("used file")
+local report_option = logs.reporter("used option")
+
+luatex.registerstopactions(function()
+ local foundintrees = resolvers.instance.foundintrees
+ if #foundintrees > 0 then
+ logspushtarget("logfile")
+ logsnewline()
+ report_files("start used files")
+ logsnewline()
+ for i=1,#foundintrees do
+ report_file("%4i: % T",i,foundintrees[i])
+ end
+ logsnewline()
+ report_files("stop used files")
+ logsnewline()
+ logspoptarget()
+ end
+end)
+
+luatex.registerstopactions(function()
+ local files = document.files -- or environment.files
+ local arguments = document.arguments -- or environment.arguments
+ --
+ logspushtarget("logfile")
+ logsnewline()
+ report_options("start commandline options")
+ logsnewline()
+ if arguments and next(arguments) then
+ for argument, value in sortedhash(arguments) do
+ report_option("%s=%A",argument,value)
+ end
+ else
+ report_file("no arguments")
+ end
+ logsnewline()
+ report_options("stop commandline options")
+ logsnewline()
+ report_options("start commandline files")
+ logsnewline()
+ if files and #files > 0 then
+ for i=1,#files do
+ report_file("% 4i: %s",i,files[i])
+ end
+ else
+ report_file("no files")
+ end
+ logsnewline()
+ report_options("stop commandline files")
+ logsnewline()
+ logspoptarget()
+end)
+
+if environment.initex then
+
+ local report_storage = logs.reporter("system","storage")
+ local report_table = logs.reporter("stored table")
+ local report_module = logs.reporter("stored module")
+ local report_attribute = logs.reporter("stored attribute")
+ local report_catcodetable = logs.reporter("stored catcodetable")
+ local report_corenamespace = logs.reporter("stored corenamespace")
+
+ luatex.registerstopactions(function()
+ logspushtarget("logfile")
+ logsnewline()
+ report_storage("start stored tables")
+ logsnewline()
+ for k,v in sortedhash(storage.data) do
+ report_table("%03i %s",k,v[1])
+ end
+ logsnewline()
+ report_storage("stop stored tables")
+ logsnewline()
+ report_storage("start stored modules")
+ logsnewline()
+ for k,v in sortedhash(lua.bytedata) do
+ report_module("%03i %s %s",k,v[2],v[1])
+ end
+ logsnewline()
+ report_storage("stop stored modules")
+ logsnewline()
+ report_storage("start stored attributes")
+ logsnewline()
+ for k,v in sortedhash(attributes.names) do
+ report_attribute("%03i %s",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored attributes")
+ logsnewline()
+ report_storage("start stored catcodetables")
+ logsnewline()
+ for k,v in sortedhash(catcodes.names) do
+ report_catcodetable("%03i % t",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored catcodetables")
+ logsnewline()
+ report_storage("start stored corenamespaces")
+ for k,v in sortedhash(interfaces.corenamespaces) do
+ report_corenamespace("%03i %s",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored corenamespaces")
+ logsnewline()
+ logspoptarget()
+ end)
+
+end
+
+implement {
+ name = "doifelsecontinuewithfile",
+ arguments = "string",
+ actions = function(inpname,basetoo)
+ local inpnamefull = addsuffix(inpname,"tex")
+ local inpfilefull = addsuffix(environment.inputfilename,"tex")
+ local continue = inpnamefull == inpfilefull
+ -- if basetoo and not continue then
+ if not continue then
+ continue = inpnamefull == basename(inpfilefull)
+ end
+ if continue then
+ report_system("continuing input file %a",inpname)
+ end
+ ctx_doifelse(continue)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi
new file mode 100644
index 00000000000..7814aba3f62
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi
@@ -0,0 +1,331 @@
+%D \module
+%D [ file=file-job, % copied from main-001, later core-job
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is still to be split and documented.
+
+\writestatus{loading}{ConTeXt File Macros / Job Handling}
+
+\unprotect
+
+\registerctxluafile{file-job}{1.001}
+
+% processing
+
+\unexpanded\def\doifelseinputfile#name%
+ {\clf_doifelseinputfile{#name}}
+
+\let\doifinputfileelse\doifelseinputfile
+
+\unexpanded\def\processfile#name%
+ {\clf_processfile{#name}}
+
+% path control
+
+%D In the following example the lookup order is \type {.}, {/foo}, \type
+%D {foo/bar} as one can always explicitly prefix a wanted file.
+%D
+%D \starttyping
+%D \pushpath[foo]
+%D \pushpath[foo/bar]
+%D \input test
+%D \poppath
+%D \poppath
+%D \stoptyping
+
+\unexpanded\def\usepath[#path]%
+ {\clf_usepath{#path}}
+
+\unexpanded\def\usesubpath[#path]%
+ {\clf_usesubpath{#path}}
+
+\unexpanded\def\pushpath[#path]%
+ {\clf_pushpath{#path}}
+
+\unexpanded\def\poppath
+ {\clf_poppath}
+
+\unexpanded\def\resetpath % not the pushed paths
+ {\clf_resetpath}
+
+\def\allinputpaths
+ {\clf_allinputpaths}
+
+% helper (not really needed nowadays)
+
+\let\locatedfilepath\empty
+
+\unexpanded\def\locatefilepath#name% no [] ?
+ {\edef\locatedfilepath{\clf_locatefilepath{#name}}}
+
+% % maybe:
+%
+% % \dirlist{c:/data/temporary/foo}{images/bar.jpg}
+% % \dirfile{c:/data/temporary/foo}{images/bar.jpg}
+%
+% \def\dirlist#1#2{dirlist://#1/**/#2}
+% \def\dirfile#1#2{dirlist://#1/**/#2?option=fileonly}
+
+% zip files are tree'd
+
+\unexpanded\def\usezipfile
+ {\dodoubleempty\syst_files_use_zip_file}
+
+\def\syst_files_use_zip_file[#zipname][#subtree]%
+ {\clf_usezipfile{#zipname}{#subtree}}
+
+% exa stuff might become obsolete:
+
+\unexpanded\def\loadexamodes
+ {\dosingleempty\syst_files_load_exa_modes}
+
+\def\syst_files_load_exa_modes[#name]%
+ {\clf_loadexamodes{#name}}
+
+% runtime files (maybe also do this in lua?)
+
+% \def\doloadsystemfile#1% only mkiv files
+% {\readfile{sys:///#1.\mksuffix}{\showmessage\m!system2{#1.\mksuffix}}\donothing}
+
+\unexpanded\def\syst_files_load
+ {\syst_files_load_indeed\f!newfilename % new code, to be integrated at some point, plus fixes posted on the list
+ \syst_files_load_indeed\f!locfilename % new code, somewhat experimental, not distributed (outside the dev group)
+ \syst_files_load_indeed\f!expfilename % new code, very experimental, can be engine specific, mostly for me only
+ \syst_files_load_indeed\f!sysfilename % local settings, but probably not that good an idea to use
+ %\syst_files_load_indeed\f!fntfilename % maybe some day, can load goodies and patches
+ }
+
+\def\syst_files_load_indeed#name% from now on we assume a suffix to be part of the name
+ {\readsysfile{#name}{\showmessage\m!system2{#name}}\donothing}
+
+% document structure
+
+\ifdefined\textlevel \else \newcount\textlevel \fi % might go away
+\ifdefined\strc_pagenumbers_flush_final_page \else \let\strc_pagenumbers_flush_final_page\relax \fi % ugly
+
+\unexpanded\def\dostarttext
+ {\glet\dostarttext\relax
+ \the\everystarttext
+ \global\everystarttext\emptytoks}
+
+\unexpanded\def\dostoptext
+ {\glet\dostoptext\relax
+ \strc_pagenumbers_flush_final_page
+ \page % hm, bonus
+ \the\everystoptext
+ \global\everystoptext\emptytoks
+ \the\everybye
+ \global\everybye\emptytoks
+ \the\everygoodbye
+ \global\everygoodbye\emptytoks
+ \doifelsesometoks\everynotabene{\writeline\the\everynotabene\writeline}\donothing
+ \normalend} % tex's \end
+
+\unexpanded\def\starttext {\clf_starttext}
+\unexpanded\def\stoptext {\clf_stoptext}
+\unexpanded\def\forcequitjob {\clf_forcequitjob}
+\unexpanded\def\end {\clf_forceendjob}
+\unexpanded\def\autostarttext{\clf_autostarttext}
+\unexpanded\def\autostoptext {\clf_autostoptext}
+
+\unexpanded\def\finishjob{\stoptext} % nicer in luatex call commandline
+
+\newtoks\everystartnotext
+\newtoks\everystopnotext
+
+\unexpanded\def\startnotext {\the\everystartnotext}
+\unexpanded\def\stopnotext {\the\everystopnotext \normalend}
+
+% protect structure
+
+\unexpanded\def\processfilemany#name{\clf_processfilemany{#name}}
+\unexpanded\def\processfileonce#name{\clf_processfileonce{#name}}
+\unexpanded\def\processfilenone#name{\clf_processfilenone{#name}}
+
+\unexpanded\def\project {\doifelsenextoptionalcs\useproject \syst_structure_arg_project}
+\unexpanded\def\product {\doifelsenextoptionalcs\useproduct \syst_structure_arg_product}
+\unexpanded\def\component {\doifelsenextoptionalcs\usecomponent \syst_structure_arg_component}
+\unexpanded\def\environment{\doifelsenextoptionalcs\useenvironment\syst_structure_arg_environment}
+
+\def\syst_structure_arg_project #name {\clf_useproject {#name}}
+\def\syst_structure_arg_product #name {\clf_useproduct {#name}}
+\def\syst_structure_arg_component #name {\clf_usecomponent {#name}}
+\def\syst_structure_arg_environment#name {\clf_useenvironment{#name}}
+
+\unexpanded\def\startproject {\doifelsenextoptionalcs\syst_structure_start_opt_project \syst_structure_start_arg_project }
+\unexpanded\def\startproduct {\doifelsenextoptionalcs\syst_structure_start_opt_product \syst_structure_start_arg_product }
+\unexpanded\def\startcomponent {\doifelsenextoptionalcs\syst_structure_start_opt_component \syst_structure_start_arg_component }
+\unexpanded\def\startenvironment{\doifelsenextoptionalcs\syst_structure_start_opt_environment\syst_structure_start_arg_environment}
+
+\def\syst_structure_start_arg_project #name {\clf_startproject {#name}}
+\def\syst_structure_start_arg_product #name {\clf_startproduct {#name}}
+\def\syst_structure_start_arg_component #name {\clf_startcomponent {#name}}
+\def\syst_structure_start_arg_environment#name {\clf_startenvironment{#name}}
+
+\unexpanded\def\useproject [#name]{\clf_useproject {#name}}
+\unexpanded\def\useproduct [#name]{\clf_useproduct {#name}}
+\unexpanded\def\usecomponent [#name]{\clf_usecomponent {#name}}
+\unexpanded\def\useenvironment[#name]{\clf_useenvironment{#name}}
+
+\unexpanded\def\syst_structure_start_opt_project [#name]{\clf_startproject {#name}}
+\unexpanded\def\syst_structure_start_opt_product [#name]{\clf_startproduct {#name}}
+\unexpanded\def\syst_structure_start_opt_component [#name]{\clf_startcomponent {#name}}
+\unexpanded\def\syst_structure_start_opt_environment[#name]{\clf_startenvironment{#name}}
+
+\newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua
+
+\unexpanded\def\signalendofinput#1% argument just for tracing
+ {\global\settrue\endofinput}
+
+\unexpanded\def\honorendofinput
+ {\ifconditional\endofinput
+ \global\setfalse\endofinput
+ \endinput
+ \fi}
+
+\unexpanded\def\stopproject {\clf_stopproject \honorendofinput}
+\unexpanded\def\stopproduct {\clf_stopproduct \honorendofinput}
+\unexpanded\def\stopcomponent {\clf_stopcomponent \honorendofinput}
+\unexpanded\def\stopenvironment {\clf_stopenvironment\honorendofinput}
+
+ \let\currentproject \clf_currentproject
+ \let\currentproduct \clf_currentproduct
+ \let\currentcomponent \clf_currentcomponent
+ \let\currentenvironment \clf_currentenvironment
+ \let\processedfile \clf_processedfile
+ \let\processedfiles \clf_processedfiles
+
+\unexpanded\def\dostarttextfile #name{\clf_dostarttextfile{name}}
+\unexpanded\def\dostoptextfile {\clf_dostoptextfile}
+
+\unexpanded\def\loadtexfile [#name]{\clf_usetexfile{#name}}
+\unexpanded\def\loadluafile [#name]{\clf_useluafile{#name}}
+\unexpanded\def\loadcldfile [#name]{\clf_usecldfile{#name}}
+\unexpanded\def\loadanyfile [#name]{\clf_useanyfile{#name}}
+
+\unexpanded\def\loadtexfileonce [#name]{\clf_usetexfileonce{#name}}
+\unexpanded\def\loadluafileonce [#name]{\clf_useluafileonce{#name}}
+\unexpanded\def\loadcldfileonce [#name]{\clf_usecldfileonce{#name}}
+\unexpanded\def\loadanyfileonce [#name]{\clf_useanyfileonce{#name}}
+
+%D Handy for modules that have a test/demo appended (true added).
+
+\unexpanded\def\continueifinputfile#name%
+ {\clf_doifelsecontinuewithfile{#name}\relax\endinput} % we cannot do \endinput via lua
+
+% \startproject test
+% 1: \startmode[*project] project \stopmode \endgraf
+% 2: \startmode[*product] product \stopmode \endgraf
+% \stopproject
+
+% replaced by modes:
+%
+% \setvalue{\e!start\v!localenvironment}[#1]%
+% {\let\loadedlocalenvironments\empty
+% \def\docommand##1%
+% {\beforesplitstring##1\at.\to\someevironment
+% \addtocommalist\someevironment\loadedlocalenvironments}%
+% \processcommalist[#1]\docommand
+% \doifcommonelse{\currentproject,\currentproduct,\currentcomponent,\currentenvironment}\loadedlocalenvironments
+% {\letvalue{\e!stop\v!localenvironment}\relax}
+% {\grabuntil{\e!stop\v!localenvironment}\gobbleoneargument}}
+%
+% \setvalue{\v!localenvironment}{\doifnextoptionalcselse\uselocalenvironment\redolocalenvironment}
+%
+% \def\redolocalenvironment#1 {\uselocalenvironment[#1]}
+% \def\uselocalenvironment[#1]{\doexecutefileonce{#1}}
+
+% weird place:
+
+\neverypar\emptytoks
+
+%D Wrappers (the signal is a synchronization with lua hack):
+
+\newsystemmode\v!project
+\newsystemmode\v!product
+\newsystemmode\v!component
+\newsystemmode\v!environment
+
+\unexpanded\def\startprojectindeed
+ {%starttext
+ \pushsystemmode\v!project
+ \setsystemmode\v!project}
+
+\unexpanded\def\stopprojectindeed
+ {\popsystemmode\v!project
+ %stoptext
+ \signalendofinput\v!project}
+
+\unexpanded\def\startproductindeed
+ {\starttext
+ \pushsystemmode\v!product
+ \setsystemmode\v!product}
+
+\unexpanded\def\stopproductindeed
+ {\popsystemmode\v!product
+ \stoptext
+ \signalendofinput\v!product}
+
+\unexpanded\def\startcomponentindeed
+ {\starttext
+ \pushreferenceprefix\currentcomponent
+ \pushsystemmode\v!component
+ \setsystemmode\v!component}
+
+\unexpanded\def\stopcomponentindeed
+ {\popsystemmode\v!component
+ \popreferenceprefix
+ \stoptext
+ \signalendofinput\v!component}
+
+\unexpanded\def\startenvironmentindeed
+ {\pushsystemmode\v!environment
+ \setsystemmode\v!environment}
+
+\unexpanded\def\stopenvironmentindeed
+ {\popsystemmode\v!environment
+ \signalendofinput\v!environment}
+
+%D Relatively new (might move as it depends on setups):
+
+%newtoks\everysetupdocument
+
+\unexpanded\def\startdocument % todo: dostarttagged\t!document
+ {\dosingleargument\syst_structure_document_start}
+
+\unexpanded\def\syst_structure_document_start[#settings]%
+ {\setvariables[\s!document][#settings]%
+ \the\everysetupdocument\relax
+ \starttext
+ \documentvariable\c!before}
+
+\unexpanded\def\stopdocument % todo: dostoptagged\t!document
+ {\documentvariable\c!after
+ \stoptext}
+
+\def\documentvariable#name%
+ {\getvariable\s!document{#name}}
+
+\unexpanded\def\setupdocument[#settings]%
+ {\setvariables[\s!document][#settings]%
+ \the\everysetupdocument\relax}
+
+% metadata:author metadata:title metadata:subject
+
+\setvariables
+ [document]
+ [\c!before=\directsetup{\s!document:start},
+ \c!after=\directsetup{\s!document:stop}]
+
+%S The document: namespace will be used elsewhere too.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-lib.lua b/Master/texmf-dist/tex/context/base/mkiv/file-lib.lua
new file mode 100644
index 00000000000..361608ea3cf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-lib.lua
@@ -0,0 +1,90 @@
+if not modules then modules = { } end modules ['file-lib'] = {
+ version = 1.001,
+ comment = "companion to file-lib.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: check all usage of truefilename at the tex end and remove
+-- files there (and replace definitions by full names)
+
+local format, gsub = string.format, string.gsub
+
+local trace_libraries = false trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+----- trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end)
+
+local report_library = logs.reporter("files","library")
+----- report_files = logs.reporter("files","readfile")
+
+local suffixonly = file.suffix
+local removesuffix = file.removesuffix
+
+local getreadfilename = resolvers.getreadfilename
+
+local loaded = { }
+local defaultpatterns = { "%s" }
+
+local function defaultaction(name,foundname)
+ report_files("asked name %a, found name %a",name,foundname)
+end
+
+local function defaultfailure(name)
+ report_files("asked name %a, not found",name)
+end
+
+function resolvers.uselibrary(specification) -- todo: reporter
+ local name = specification.name
+ if name and name ~= "" then
+ local patterns = specification.patterns or defaultpatterns
+ local action = specification.action or defaultaction
+ local failure = specification.failure or defaultfailure
+ local onlyonce = specification.onlyonce
+ local files = utilities.parsers.settings_to_array(name)
+ local truename = environment.truefilename
+ local function found(filename)
+ local somename = truename and truename(filename) or filename
+ local foundname = getreadfilename("any",".",somename) -- maybe some day also an option not to backtrack .. and ../.. (or block global)
+ return foundname ~= "" and foundname
+ end
+ for i=1,#files do
+ local filename = files[i]
+ if loaded[filename] then
+ -- next one
+ else
+ if onlyonce then
+ loaded[filename] = true -- todo: base this on return value
+ end
+ local foundname = nil
+ local barename = removesuffix(filename)
+ -- direct search (we have an explicit suffix)
+ if barename ~= filename then
+ foundname = found(filename)
+ if trace_libraries then
+ report_library("checking %a: %s",filename,foundname or "not found")
+ end
+ end
+ if not foundname then
+ -- pattern based search
+ for i=1,#patterns do
+ local wanted = format(patterns[i],barename)
+ foundname = found(wanted)
+ if trace_libraries then
+ report_library("checking %a as %a: %s",filename,wanted,foundname or "not found")
+ end
+ if foundname then
+ break
+ end
+ end
+ end
+ if foundname then
+ action(name,foundname)
+ elseif failure then
+ failure(name)
+ end
+ end
+ end
+ end
+end
+
+commands.uselibrary = resolvers.uselibrary -- for the moment
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-lib.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-lib.mkvi
new file mode 100644
index 00000000000..76137ce15b9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-lib.mkvi
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=file-lib, % was core-fil,
+%D version=20110701, % 1997.11.15,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Module Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt File Macros / Libraries}
+
+\unprotect
+
+\registerctxluafile{file-lib}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-mod.lua b/Master/texmf-dist/tex/context/base/mkiv/file-mod.lua
new file mode 100644
index 00000000000..7f3763c5ded
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-mod.lua
@@ -0,0 +1,242 @@
+if not modules then modules = { } end modules ['file-mod'] = {
+ version = 1.001,
+ comment = "companion to file-mod.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module will be redone! For instance, the prefixes will move to data-*
+-- as they arr sort of generic along with home:// etc/.
+
+-- context is not defined yet! todo! (we need to load tupp-fil after cld)
+-- todo: move startreadingfile to lua and push regime there
+
+--[[ldx--
+<p>It's more convenient to manipulate filenames (paths) in
+<l n='lua'/> than in <l n='tex'/>. These methods have counterparts
+at the <l n='tex'/> side.</p>
+--ldx]]--
+
+local format, find, concat, tonumber = string.format, string.find, table.concat, tonumber
+
+local trace_modules = false trackers .register("modules.loading", function(v) trace_modules = v end)
+local permit_unprefixed = false directives.register("modules.permitunprefixed", function(v) permit_unprefixed = v end)
+
+local report_modules = logs.reporter("resolvers","modules")
+
+local commands = commands
+local context = context
+local implement = interfaces.implement
+
+local findbyscheme = resolvers.finders.byscheme -- use different one
+local iterator = utilities.parsers.iterator
+
+-- modules can have a specific suffix or can specify one
+
+local prefixes = {
+ "m", -- module, extends functionality
+ "p", -- private code
+ "s", -- styles
+ "x", -- xml specific modules
+ -- "v", -- an old internal one for examples
+ "t", -- third party extensions
+}
+
+-- the order might change and how about cld
+
+local suffixes = {
+ "mkvi", -- proprocessed mkiv files
+ "mkiv", -- mkiv files
+ "tex", -- normally source code files
+ "cld", -- context lua documents (often stand alone)
+ "lua", -- lua files
+}
+
+local modstatus = { }
+
+local function usemodule(name,hasscheme)
+ local foundname
+ if hasscheme then
+ -- no auto suffix as http will return a home page or error page
+ -- so we only add one if missing
+ local fullname = file.addsuffix(name,"tex")
+ if trace_modules then
+ report_modules("checking url %a",fullname)
+ end
+ foundname = resolvers.findtexfile(fullname) or ""
+ elseif file.suffix(name) ~= "" then
+ if trace_modules then
+ report_modules("checking file %a",name)
+ end
+ foundname = findbyscheme("any",name) or ""
+ else
+ for i=1,#suffixes do
+ local fullname = file.addsuffix(name,suffixes[i])
+ if trace_modules then
+ report_modules("checking file %a",fullname)
+ end
+ foundname = findbyscheme("any",fullname) or ""
+ if foundname ~= "" then
+ break
+ end
+ end
+ end
+ if foundname ~= "" then
+ if trace_modules then
+ report_modules("loading file %a",foundname)
+ end
+ context.startreadingfile()
+ resolvers.jobs.usefile(foundname,true) -- once, notext
+ -- context.input(foundname)
+ context.stopreadingfile()
+ return true
+ else
+ return false
+ end
+end
+
+function environment.usemodules(prefix,askedname,truename)
+ local truename = truename or environment.truefilename(askedname)
+ local hasprefix = prefix and prefix ~= ""
+ local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
+ local status = modstatus[hashname] or false -- yet unset
+ if status == 0 then
+ -- not found
+ elseif status == 1 then
+ status = status + 1
+ else
+ if trace_modules then
+ report_modules("locating, prefix %a, askedname %a, truename %a",prefix,askedname,truename)
+ end
+ local hasscheme = url.hasscheme(truename)
+ if hasscheme then
+ -- no prefix and suffix done
+ if usemodule(truename,true) then
+ status = 1
+ else
+ status = 0
+ end
+ elseif hasprefix then
+ if usemodule(prefix .. "-" .. truename) then
+ status = 1
+ else
+ status = 0
+ end
+ else
+ for i=1,#prefixes do
+ -- todo: reconstruct name i.e. basename
+ local thename = prefixes[i] .. "-" .. truename
+ if usemodule(thename) then
+ status = 1
+ break
+ end
+ end
+ if status then
+ -- ok, don't change
+ elseif find(truename,"%-") and usemodule(truename) then
+ -- assume a user namespace
+ report_modules("using user prefixed file %a",truename)
+ status = 1
+ elseif permit_unprefixed and usemodule(truename) then
+ report_modules("using unprefixed file %a",truename)
+ status = 1
+ else
+ status = 0
+ end
+ end
+ end
+ if status == 0 then
+ report_modules("%a is not found",askedname)
+ elseif status == 1 then
+ report_modules("%a is loaded",trace_modules and truename or askedname)
+ else
+ report_modules("%a is already loaded",trace_modules and truename or askedname)
+ end
+ modstatus[hashname] = status
+end
+
+statistics.register("loaded tex modules", function()
+ if next(modstatus) then
+ local t, f, nt, nf = { }, { }, 0, 0
+ for k, v in table.sortedhash(modstatus) do
+ k = file.basename(k)
+ if v == 0 then
+ nf = nf + 1
+ f[nf] = k
+ else
+ nt = nt + 1
+ t[nt] = k
+ end
+ end
+ if nf == 0 then
+ return format("%s requested, all found (%s)",nt,concat(t," "))
+ elseif nt == 0 then
+ return format("%s requested, all missing (%s)",nf,concat(f," "))
+ else
+ return format("%s requested, %s found (%s), %s missing (%s)",nt+nf,nt,concat(t," "),nf,concat(f," "))
+ end
+ else
+ return nil
+ end
+end)
+
+-- moved from syst-lua.lua:
+
+local lpegmatch = lpeg.match
+local splitter = lpeg.tsplitter(lpeg.S(". "),tonumber)
+
+function environment.comparedversion(one,two) -- one >= two
+ if not two or two == "" then
+ one, two = environment.version, one
+ elseif one == "" then
+ one = environment.version
+ end
+ one = lpegmatch(splitter,one)
+ two = lpegmatch(splitter,two)
+ one = (one[1] or 0) * 10000 + (one[2] or 0) * 100 + (one[3] or 0)
+ two = (two[1] or 0) * 10000 + (two[2] or 0) * 100 + (two[3] or 0)
+ if one < two then
+ return -1
+ elseif one > two then
+ return 1
+ else
+ return 0
+ end
+end
+
+environment.comparedversion = comparedversion
+
+
+function environment.useluamodule(list)
+ for filename in iterator(list) do
+ environment.loadluafile(filename)
+ end
+end
+
+local strings = interfaces.strings
+
+implement {
+ name = "usemodules",
+ actions = environment.usemodules,
+ arguments = strings[2]
+}
+
+implement {
+ name = "doifelseolderversion",
+ actions = function(one,two) commands.doifelse(comparedversion(one,two) >= 0) end,
+ arguments = strings[2]
+}
+
+implement {
+ name = "useluamodule",
+ actions = environment.useluamodule,
+ arguments = "string"
+}
+
+implement {
+ name = "loadluamodule",
+ actions = function(name) dofile(resolvers.findctxfile(name)) end, -- hack
+ arguments = "string"
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi
new file mode 100644
index 00000000000..ebd741d42af
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi
@@ -0,0 +1,293 @@
+%D \module
+%D [ file=file-mod, % was core-fil,
+%D version=20110701, % 1997.11.15,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Module Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt File Macros / Modules}
+
+\unprotect
+
+\registerctxluafile{file-mod}{1.001}
+
+%D \macros
+%D {usemodule}
+%D
+%D Most of \CONTEXT is preloaded in the format file. Some very domain specific
+%D typesetting topics are however dealt with in separate modules, e.g. typesetting
+%D of chemical structure formulas. These modules are loaded by:
+%D
+%D \showsetup{usemodule}
+%D
+%D More information on the specific modules can be found in their dedicated manuals.
+%D We use \type {\next} so that we can \type {\end} in modules.
+
+\unexpanded\def\usemodules
+ {\dotripleempty\strc_modules_use}
+
+\let\usemodule \usemodules
+\let\usetexmodule\usemodules
+
+\def\strc_modules_use[#category][#name][#parameters]% category=t|m|x|p|...
+ {\pushmacro\currentmodule
+ \pushmacro\currentmodulecategory
+ \pushmacro\currentmoduleparameters
+ \ifthirdargument
+ \edef\currentmodulecategory {#category}%
+ \edef\currentmodule {#name}%
+ \def \currentmoduleparameters{#parameters}%
+ \else\ifsecondargument
+ \doifelseassignment{#name}
+ {\let\currentmodulecategory \empty
+ \edef\currentmodule {#category}%
+ \edef\currentmoduleparameters{#name}}
+ {\edef\currentmodulecategory {#category}%
+ \edef\currentmodule {#name}%
+ \let \currentmoduleparameters\empty}%
+ \else
+ \let \currentmodulecategory \empty
+ \edef\currentmodule {#category}%
+ \let \currentmoduleparameters\empty
+ \fi\fi
+ \processcommacommand[\currentmodule]{\strc_modules_use_indeed\currentmodulecategory}%
+ \popmacro\currentmoduleparameters
+ \popmacro\currentmodulecategory
+ \popmacro\currentmodule}
+
+\def\strc_modules_use_indeed#category#name%
+ {\ifx\currentmoduleparameters\empty\else
+ \scratchtoks\expandafter{\currentmoduleparameters}%
+ \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}%
+ \fi
+ \clf_usemodules{#category}{#name}}
+
+\installcorenamespace{module}
+
+\let\currentmoduleparameters\empty
+\let\currentmodule \s!unknown
+
+\newtoks\everysetupmodule
+
+\unexpanded\def\startmodule
+ {\doifelsenextoptionalcs\syst_modules_start_yes\syst_modules_start_nop}
+
+\def\syst_modules_start_yes[#name]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \def\currentmodule{#name}}
+
+\def\syst_modules_start_nop#name %
+ {\syst_modules_start_yes[#name]}
+
+\unexpanded\def\stopmodule
+ {\popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\unexpanded\def\setupmodule
+ {\dodoubleempty\syst_modules_setup}
+
+\def\syst_modules_setup
+ {\ifx\currentmoduleparameters\empty
+ \expandafter\syst_modules_setup_nop
+ \else
+ \expandafter\syst_modules_setup_yes
+ \fi}
+
+\def\syst_modules_setup_nop[#name][#parameters]%
+ {\ifsecondargument
+ \getparameters[\??module#name:][#parameters]% internal (defaults)
+ \else\iffirstargument
+ \doifassignmentelse{#name}{\getparameters[\??module\currentmodule:][#name]}\donothing
+ \fi\fi
+ \the\everysetupmodule}
+
+\def\syst_modules_setup_yes[#name][#parameters]%
+ {\scratchtoks\expandafter{\currentmoduleparameters}%
+ \ifsecondargument
+ \getparameters[\??module#name:][#parameters]% internal (defaults)
+ \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% loadtime (user)
+ \else\iffirstargument
+ \doifassignmentelse{#name}
+ {\getparameters[\??module\currentmodule:][#name]% internal (defaults)
+ \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}}% loadtime (user)
+ {\normalexpanded{\getparameters[\??module#1:][\the\scratchtoks]}}% loadtime (user)
+ \else
+ \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}%
+ \fi\fi
+ \let\currentmoduleparameters\empty
+ \the\everysetupmodule}
+
+% to be tested:
+%
+% \def\syst_modules_setup[#name][#parameters]%
+% {\ifsecondargument
+% \getparameters[\??module#name:][#parameters]% internal (defaults)
+% \normalexpanded{\getparameters[\??module#name:][\normalunexpanded\expandafter{\currentmoduleparameters}]}% loadtime (user)
+% \else
+% \getparameters[\??module\currentmodule:][#name]% internal (defaults)
+% \normalexpanded{\getparameters[\??module\currentmodule:][\normalunexpanded\expandafter{\currentmoduleparameters}]}% loadtime (user)
+% \fi
+% \let\currentmoduleparameters\empty}
+
+\def\moduleparameter#name#parameter% should have been \namedmoduleparameter
+ {\begincsname\??module#name:#parameter\endcsname}
+
+\letvalue\??module\empty % so we default to empty as with all parameters
+
+\def\currentmoduleparameter{\moduleparameter\currentmodule} % no need for inlining
+
+\unexpanded\def\useluamodule [#name]{\clf_loadluamodule{#1}} % why not use useluamodule
+\unexpanded\def\luaenvironment #name {\clf_loadluamodule{#1}}
+
+% \usemodule[newmml]
+% \usemodule[newmml][a=b]
+% \usemodule[x][newmml]
+% \usemodule[x][newmml][a=b]
+%
+% \startmodule [mathml]
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars will be set afterwards
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars are now forgotten
+% \stopmodule
+
+% one can introduce test sections with:
+%
+% \enablemode[newmml:test:\currentmoduleparameter{test}]
+% \startmode[newmml:test:yes} ... \stopmode
+%
+% these will be ignored unless test=yes
+%
+% however, a better way is:
+
+\unexpanded\def\startmoduletestsection
+ {\begingroup
+ \setupmodule % we need to make sure that the vars are set
+ \doifelse{\currentmoduleparameter\v!test}\v!yes
+ {\endgroup
+ \writestatus\currentmodule{loading experimental code}}
+ {\endgroup
+ \writestatus\currentmodule{skipping experimental code}%
+ \gobbleuntil\stopmoduletestsection}}
+
+\let\stopmoduletestsection\donothing
+
+% will become file-run
+
+%D To save memory, we implement some seldomly used commands in a lazy way. Nota
+%D bene: such runtime definitions are to be defined global.
+%D
+%D \starttyping
+%D \fetchruntimecommand\showaccents{\f!colorprefix ...}
+%D \stoptyping
+
+\installcorenamespace{runtimeloaded}
+
+\unexpanded\def\fetchruntimecommand#1#2%
+ {\unexpanded\def#1{\dofetchruntimecommand#1{#2}}}
+
+\def\dofetchruntimecommand#1#2% actually a test on #1 being define would be ok as well
+ {\ifcsname\??runtimeloaded#2\endcsname
+ % already loaded
+ \else
+ \global\let#1\undefined
+ \startreadingfile
+ \startnointerference % \bgroup
+ \cleanupfeatures % better \setnormalcatcodes / test first
+ \readfile{#2.\mksuffix}\donothing\donothing
+ \stopnointerference % \egroup
+ \stopreadingfile
+ \letgvalue{\??runtimeloaded#2}\empty
+ \fi
+ \ifx#1\undefined
+ \writestatus\m!system{command \string#1 not found in file #2}%
+ \unexpanded\gdef#1{{\infofont[unknown command \string#1]}}%
+ \fi
+ #1}
+
+%D \macros
+%D {doifolderversionelse}
+%D
+%D We start with a macro specially for Aditya who wants to be able
+%D to use development versions of \MKIV\ for real documents.
+%D
+%D \starttyping
+%D \doifolderversionelse\contextversion{1010.10.10} {OLDER} {OKAY} => OLDER
+%D \doifolderversionelse\contextversion{2020.20.20} {OLDER} {OKAY} => OKAY
+%D \doifolderversionelse\contextversion{2020} {OLDER} {OKAY} => OKAY
+%D \stoptyping
+%D
+%D The version pattern is \type {yyyy.mm.dd} (with mm and dd being optional).
+
+\unexpanded\def\doifelseolderversion#parent#child{\clf_doifelseolderversion{#parent}{#child}}
+\unexpanded\def\doifelseoldercontext #child{\clf_doifelseolderversion{#child}{}}
+
+\let\doifolderversionelse\doifelseolderversion
+\let\doifoldercontextelse\doifelseoldercontext
+
+%D Relatively new (no need for a speedup here):
+
+\unexpanded\def\syst_modules_direct_lua#1#2%
+ {\edef\m_module_command_command {#1}%
+ \edef\m_module_command_function{#2}%
+ \directsetup{module:\m_module_command_command:start}%
+ \ctxlua{\m_module_command_function()}%
+ \directsetup{module:\m_module_command_command:stop}}
+
+\unexpanded\def\syst_modules_single_lua#1#2%
+ {\edef\m_module_command_command {#1}%
+ \edef\m_module_command_function{#2}%
+ \dosingleempty\syst_modules_single_lua_indeed}
+
+\unexpanded\def\syst_modules_single_lua_indeed[#1]%
+ {\directsetup{module:\m_module_command_command:start}%
+ \ctxlua{\m_module_command_function(\!!bs#1\!!es)}%
+ \directsetup{module:\m_module_command_command:stop}}
+
+\unexpanded\def\syst_modules_double_lua#1#2%
+ {\edef\m_module_command_command {#1}%
+ \edef\m_module_command_function{#2}%
+ \dodoubleempty\syst_modules_double_lua_indeed}
+
+\unexpanded\def\syst_modules_double_lua_indeed[#1][#2]%
+ {\directsetup{module:\m_module_command_command:start}%
+ \ctxlua{\m_module_command_function(\!!bs#1\!!es,\!!bs#2\!!es)}%
+ \directsetup{module:\m_module_command_command:stop}}
+
+\def\installmodulecommandlua #1#2{\unexpanded\def#1{\normalexpanded{\syst_modules_direct_lua{\strippedcsname#1}{#2}}}}
+\def\installmodulecommandluasingle#1#2{\unexpanded\def#1{\normalexpanded{\syst_modules_single_lua{\strippedcsname#1}{#2}}}}
+\def\installmodulecommandluadouble#1#2{\unexpanded\def#1{\normalexpanded{\syst_modules_double_lua{\strippedcsname#1}{#2}}}}
+
+\unexpanded\def\syst_modules_one_lua#1#2#3%
+ {\directsetup{module:#1:start}%
+ \ctxlua{#2(\!!bs#3\!!es)}%
+ \directsetup{module:#1:stop}}
+
+\unexpanded\def\syst_modules_two_lua#1#2#3#4%
+ {\directsetup{module:#1:start}%
+ \ctxlua{#2(\!!bs#3\!!es,\!!bs#4\!!es)}%
+ \directsetup{module:#1:stop}}
+
+\def\installmodulecommandluaone#1#2{\unexpanded\def#1{\normalexpanded{\syst_modules_one_lua{\strippedcsname#1}{#2}}}}
+\def\installmodulecommandluatwo#1#2{\unexpanded\def#1{\normalexpanded{\syst_modules_two_lua{\strippedcsname#1}{#2}}}}
+
+% obsolete
+%
+% \def\documentresources{\@@erurl}
+%
+% \unexpanded\def\setupexternalresources
+% {\dodoubleargument\getparameters[\??er]}
+%
+% \setupexternalresources
+% [url=]
+
+% new:
+
+\unexpanded\def\useluamodule[#1]{\clf_useluamodule{#1}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-res.lua b/Master/texmf-dist/tex/context/base/mkiv/file-res.lua
new file mode 100644
index 00000000000..08a3e22af8f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-res.lua
@@ -0,0 +1,172 @@
+if not modules then modules = { } end modules ['file-res'] = {
+ version = 1.001,
+ comment = "companion to supp-fil.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find = string.format, string.find
+local isfile = lfs.isfile
+local is_qualified_path = file.is_qualified_path
+local hasscheme, urlescape = url.hasscheme, url.escape
+
+local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end)
+local trace_details = false trackers.register("resolvers.readfile.details", function(v) trace_details = v end)
+local report_files = logs.reporter("files","readfile")
+
+resolvers.maxreadlevel = 2
+
+directives.register("resolvers.maxreadlevel", function(v)
+ -- resolvers.maxreadlevel = (v == false and 0) or (v == true and 2) or tonumber(v) or 2
+ resolvers.maxreadlevel = v == false and 0 or tonumber(v) or 2
+end)
+
+local finders, loaders, openers = resolvers.finders, resolvers.loaders, resolvers.openers
+
+local found = { } -- can best be done in the resolver itself
+
+local function readfilename(specification,backtrack,treetoo)
+ if trace_details then
+ report_files(table.serialize(specification,"specification"))
+ end
+ local name = specification.filename
+ local fnd = name and found[name]
+ if not fnd then
+ local names
+ local suffix = file.suffix(name)
+ if suffix ~= "" then
+ names = { name }
+ else
+ local defaultsuffixes = resolvers.defaultsuffixes
+ names = { }
+ for i=1,#defaultsuffixes do
+ names[i] = name .. "." .. defaultsuffixes[i]
+ end
+ if trace_files then
+ report_files("locating: %s, using default suffixes: %a",name,defaultsuffixes)
+ end
+ end
+ for i=1,#names do
+ local fname = names[i]
+ if isfile(fname) then
+ if trace_files then
+ report_files("found local: %s",name)
+ end
+ fnd = fname
+ break
+ end
+ end
+ if not fnd and backtrack then
+ for i=1,#names do
+ local fname = names[i]
+ for i=1,backtrack,1 do
+ fname = "../" .. fname
+ if isfile(fname) then
+ if trace_files then
+ report_files("found by backtracking: %s",fname)
+ end
+ fnd = fname
+ break
+ elseif trace_files then
+ report_files("not found by backtracking: %s",fname)
+ end
+ end
+ if fnd then
+ break
+ end
+ end
+ end
+ if not fnd then
+ local paths = resolvers.instance.extra_paths
+ if paths then
+ for i=1,#paths do
+ for i=1,#names do
+ local fname = paths[i] .. "/" .. names[i]
+ if isfile(fname) then
+ if trace_files then
+ report_files("found on extra path: %s",fname)
+ end
+ fnd = fname
+ break
+ end
+ end
+ if fnd then
+ break
+ end
+ end
+ end
+ end
+ if not fnd and treetoo then
+ fnd = resolvers.findtexfile(name) or ""
+ if trace_files then
+ if fnd ~= "" then
+ report_files("found by tree lookup: %s",fnd)
+ else
+ report_files("not found by tree lookup: %s",name)
+ end
+ end
+ end
+ found[name] = fnd
+ elseif trace_files then
+ if fnd ~= "" then
+ report_files("already found: %s",fnd)
+ else
+ report_files("already not found: %s",name)
+ end
+ end
+ return fnd or ""
+end
+
+--~ resolvers.readfilename = readfilename -- bonus use getreadfilename instead
+
+function finders.job(specification) return readfilename(specification,false, false) end -- current path, no backtracking
+function finders.loc(specification) return readfilename(specification,resolvers.maxreadlevel,false) end -- current path, backtracking
+function finders.sys(specification) return readfilename(specification,false, true ) end -- current path, obeys tex search
+function finders.fix(specification) return readfilename(specification,resolvers.maxreadlevel,false) end -- specified path, backtracking
+function finders.set(specification) return readfilename(specification,false, false) end -- specified path, no backtracking
+function finders.any(specification) return readfilename(specification,resolvers.maxreadlevel,true ) end -- loc job sys
+
+openers.job = openers.file loaders.job = loaders.file -- default anyway
+openers.loc = openers.file loaders.loc = loaders.file
+openers.sys = openers.file loaders.sys = loaders.file
+openers.fix = openers.file loaders.fix = loaders.file
+openers.set = openers.file loaders.set = loaders.file
+openers.any = openers.file loaders.any = loaders.file
+
+local function getreadfilename(scheme,path,name) -- better do a split and then pass table
+ local fullname
+ if hasscheme(name) or is_qualified_path(name) then
+ fullname = name
+ else
+ if not find(name,"%",1,true) then
+ name = urlescape(name) -- if no % in names
+ end
+ fullname = ((path == "") and format("%s:///%s",scheme,name)) or format("%s:///%s/%s",scheme,path,name)
+ end
+ return resolvers.findtexfile(fullname) or "" -- can be more direct
+end
+
+resolvers.getreadfilename = getreadfilename
+
+-- a name belonging to the run but also honoring qualified
+
+local implement = interfaces.implement
+
+implement {
+ name = "getreadfilename",
+ actions = { getreadfilename, context },
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "locfilename",
+ actions = { getreadfilename, context },
+ arguments = { "'loc'","'.'", "string" },
+}
+
+implement {
+ name = "doifelselocfile",
+ actions = { getreadfilename, isfile, commands.doifelse },
+ arguments = { "'loc'","'.'", "string" },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-res.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-res.mkvi
new file mode 100644
index 00000000000..17f4cf44c5c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-res.mkvi
@@ -0,0 +1,153 @@
+%D \module
+%D [ file=file-mod, % was supp-fil,
+%D version=20110701, % 1995.10.10,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Resolvers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt File Macros / Resolvers}
+
+\unprotect
+
+\registerctxluafile{file-res}{1.001}
+
+%D \macros
+%D {readfile,ReadFile}
+%D
+%D One cannot be sure if a file exists. When no file can be
+%D found, the \type{\input} primitive gives an error message
+%D and switches to interactive mode. The macro \type{\readfile}
+%D takes care of non||existing files. This macro has two faces.
+%D
+%D \starttyping
+%D \ReadFile {filename}
+%D \readfile {filename} {before loading} {not found}
+%D \stoptyping
+%D
+%D Many \TEX\ implementations have laid out some strategy for
+%D locating files. This can lead to unexpected results,
+%D especially when one loads files that are not found in the
+%D current directory. Let's give an example of this. In
+%D \CONTEXT\ illustrations can be defined in an external file.
+%D The resizing macro first looks if an illustration is defined
+%D in the local definitions file. When no such file is found,
+%D it searches for a global file and when this file is not
+%D found either, the illustration itself is scanned for
+%D dimensions. One can imagine what happens if an adapted,
+%D localy stored illustration, is scaled according to
+%D dimensions stored somewhere else.
+%D
+%D When some \TEX\ implementation starts looking for a file, it
+%D normally first looks in the current directory. When no file
+%D is found, \TEX\ starts searching on the path where format
+%D and|/|or style files are stored. Depending on the implementation
+%D this can considerably slow down processing speed.
+%D
+%D In \CONTEXT, we support a project||wise ordening of files.
+%D In such an approach it seems feasible to store common files
+%D in a lower directory. When for instance searching for a
+%D general layout file, we therefore have to backtrack.
+%D
+%D These three considerations have lead to a more advanced
+%D approach for loading files.
+%D
+%D We first present an earlier implementation of
+%D \type{\readfile}. This command backtracks parent
+%D directories, upto a predefined level. Users can change this
+%D level (on the commandline using a directive); we default to~3.
+%D
+%D We use \type{\normalinput} instead of \type{\input}
+%D because we want to be able to redefine the original
+%D \type{\input} when needed, for instance when loading third
+%D party libraries.
+
+\let\readfilename\empty
+
+\def\syst_files_read_file#protocol#path#name% #true #false
+ {\edef\readfilename{\clf_getreadfilename{#protocol}{#path}{#name}}%
+ \ifx\readfilename\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\syst_files_read_file_indeed
+ \fi}
+
+\def\syst_files_read_file_indeed#true#false%
+ {#true%
+ \relax
+ \normalinput{\readfilename}%
+ \relax}
+
+%D \macros
+%D {readjobfile,readlocfile,readsysfile,
+%D readfixfile,readsetfile}
+%D
+%D This implementation honnors the third situation, but we
+%D still can get unwanted files loaded and/or can get involved
+%D in extensive searching.
+%D
+%D Due to different needs, we decided to offer four alternative
+%D loading commands. With \type{\readjobfile} we load a local
+%D file and do no backtracking, while \type{\readlocfile}
+%D backtracks~\number\maxreadlevel\ directories, including the current
+%D one.
+%D
+%D System files can be anywhere and therefore
+%D \type{\readsysfile} is not bound to the current directory
+%D and obeys the \TEX\ implementation.
+%D
+%D Of the last two, \type{\readfixfile} searches on the
+%D directory specified and backtracks too, while
+%D \type{\readsetfile} does only search on the specified path.
+%D
+%D The most liberal is \type {\readfile}.
+
+\unexpanded\def\readjobfile #name{\syst_files_read_file{job} {.}{#name}} % current path, no backtracking
+\unexpanded\def\readlocfile #name{\syst_files_read_file{loc} {.}{#name}} % current path, backtracking
+\unexpanded\def\readsysfile #name{\syst_files_read_file{sys} {.}{#name}} % current path, obeys tex search
+\unexpanded\def\readfixfile#path#name{\syst_files_read_file{fix}{#path}{#name}} % specified path, backtracking
+\unexpanded\def\readsetfile#path#name{\syst_files_read_file{set}{#path}{#name}} % specified path, no backtracking
+\unexpanded\def\readfile #name{\syst_files_read_file{any} {.}{#name}}
+\unexpanded\def\ReadFile #name{\syst_files_read_file{any} {.}{#name}\donothing\donothing}
+
+%D So now we've got ourselves five file loading commands:
+%D
+%D \starttyping
+%D \readfile {filename} {before loading} {not found}
+%D
+%D \readjobfile {filename} {before loading} {not found}
+%D \readlocfile {filename} {before loading} {not found}
+%D \readfixfile {filename} {before loading} {not found}
+%D \readsysfile {directory} {filename} {before loading} {not found}
+%D \stoptyping
+
+\unexpanded\def\readtexfile#name#true#false%
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes
+ \readfile{#name}{#true}{#false}%
+ \popcatcodetable}
+
+\unexpanded\def\readxmlfile#name#true#false%
+ {\pushcatcodetable
+ \catcodetable\xmlcatcodes
+ \readfile{#name}{#true}{#false}%
+ \popcatcodetable}
+
+%D \macros
+%D {doiflocfileelse,locfilename}
+%D
+%D \starttyping
+%D \doiflocfileelse {filename} {before loading} {not found}
+%D \stoptyping
+
+\unexpanded\def\doifelselocfile#name{\clf_doifelselocfile{#name}}
+ \def\locfilename #name{\clf_locfilename {#name}}
+
+\let\doiflocfileelse\doifelselocfile
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-syn.lua b/Master/texmf-dist/tex/context/base/mkiv/file-syn.lua
new file mode 100644
index 00000000000..b6ad27c8325
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-syn.lua
@@ -0,0 +1,72 @@
+if not modules then modules = { } end modules ['file-syn'] = {
+ version = 1.001,
+ comment = "companion to file-syn.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+environment.filesynonyms = environment.filesynonyms or { }
+local filesynonyms = environment.filesynonyms
+
+local settings_to_array = utilities.parsers.settings_to_array
+local findfile = resolvers.findfile
+
+local implement = interfaces.implement
+
+local report_files = logs.reporter("files")
+
+storage.register("environment/filesynonyms", filesynonyms, "environment.filesynonyms")
+
+local function truefilename(name)
+ local realname = filesynonyms[name] or name
+ if realname ~= name then
+ return truefilename(realname)
+ else
+ return realname
+ end
+end
+
+environment.truefilename = truefilename
+
+function environment.definefilesynonym(name,realname)
+ local names = settings_to_array(name)
+ for i=1,#names do
+ local name = names[i]
+ local synonym = filesynonyms[name]
+ if synonym then
+ interfaces.showmessage("files",1,{ name or "?", realname or "?", synonym or "?" })
+ end
+ filesynonyms[name] = realname
+ end
+end
+
+function environment.definefilefallback(name,alternatives)
+ local names = settings_to_array(alternatives)
+ for i=1,#names do
+ local realname = findfile(names[i])
+ if realname ~= "" then
+ filesynonyms[name] = realname
+ break
+ end
+ end
+end
+
+implement {
+ name = "truefilename",
+ actions = { truefilename, context },
+ arguments = "string"
+}
+
+implement {
+ name = "definefilesynonym",
+ actions = environment.definefilesynonym,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "definefilefallback",
+ actions = environment,definefilefallback,
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-syn.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-syn.mkvi
new file mode 100644
index 00000000000..52ecd0d71e3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/file-syn.mkvi
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=file-syn, % was core-fil,
+%D version=20110701, % 1997.11.15,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Module Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt File Macros / Synonyms}
+
+\unprotect
+
+\registerctxluafile{file-syn}{1.001}
+
+%D \macros
+%D {definefilesynonym,definefilefallback}
+%D
+%D One of the problems with loading files is that their names
+%D can depend on the interface language. We therefore need a
+%D method to define filesynonyms. The actual synonyms are
+%D defined elsewhere, but look like:
+%D
+%D \starttyping
+%D \definefilesynonym [chemic] [chemie]
+%D \definefilesynonym [einheit] [unit]
+%D \definefilesynonym [unit] [unit]
+%D \stoptyping
+%D
+%D So we can say in english:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemic,unit]
+%D \stoptyping
+%D
+%D and in dutch:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemie,unit]
+%D \stoptyping
+
+\unexpanded\def\definefilesynonym {\dodoubleempty \syst_files_define_synonym }
+\unexpanded\def\definefilefallback{\dodoubleargument\syst_files_define_fallback} % still used?
+
+\def\syst_files_define_synonym [#name][#realname]{\clf_definefilesynonym {#name}{#realname}}
+\def\syst_files_define_fallback[#name][#alternatives]{\clf_definefilefallback{#name}{#alternatives}}
+
+%D \macros
+%D {truefilename}
+%D
+%D At the system level such a filename can be called upon by
+%D saying:
+%D
+%D \starttyping
+%D \truefilename{filename/filesynonym}
+%D \stoptyping
+%D
+%D The implementation shows that nesting is supported.
+
+\def\truefilename#1{\clf_truefilename{#1}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-afk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-afk.lua
new file mode 100644
index 00000000000..8b65b063184
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-afk.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['font-afk'] = {
+ version = 1.001,
+ comment = "companion to font-afm.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+--[[ldx--
+<p>For ligatures, only characters with a code smaller than 128 make sense,
+anything larger is encoding dependent. An interesting complication is that a
+character can be in an encoding twice but is hashed once.</p>
+--ldx]]--
+
+local allocate = utilities.storage.allocate
+
+fonts.handlers.afm.helpdata = {
+ ligatures = allocate { -- okay, nowadays we could parse the name but type 1 fonts
+ ['f'] = { -- don't have that many ligatures anyway
+ { 'f', 'ff' },
+ { 'i', 'fi' },
+ { 'l', 'fl' },
+ },
+ ['ff'] = {
+ { 'i', 'ffi' }
+ },
+ ['fi'] = {
+ { 'i', 'fii' }
+ },
+ ['fl'] = {
+ { 'i', 'fli' }
+ },
+ ['s'] = {
+ { 't', 'st' }
+ },
+ ['i'] = {
+ { 'j', 'ij' }
+ },
+ },
+ texligatures = allocate {
+ -- ['space'] = {
+ -- { 'L', 'Lslash' },
+ -- { 'l', 'lslash' }
+ -- },
+ -- ['question'] = {
+ -- { 'quoteleft', 'questiondown' }
+ -- },
+ -- ['exclam'] = {
+ -- { 'quoteleft', 'exclamdown' }
+ -- },
+ ['quoteleft'] = {
+ { 'quoteleft', 'quotedblleft' }
+ },
+ ['quoteright'] = {
+ { 'quoteright', 'quotedblright' }
+ },
+ ['hyphen'] = {
+ { 'hyphen', 'endash' }
+ },
+ ['endash'] = {
+ { 'hyphen', 'emdash' }
+ }
+ },
+ leftkerned = allocate {
+ AEligature = "A", aeligature = "a",
+ OEligature = "O", oeligature = "o",
+ IJligature = "I", ijligature = "i",
+ AE = "A", ae = "a",
+ OE = "O", oe = "o",
+ IJ = "I", ij = "i",
+ Ssharp = "S", ssharp = "s",
+ },
+ rightkerned = allocate {
+ AEligature = "E", aeligature = "e",
+ OEligature = "E", oeligature = "e",
+ IJligature = "J", ijligature = "j",
+ AE = "E", ae = "e",
+ OE = "E", oe = "e",
+ IJ = "J", ij = "j",
+ Ssharp = "S", ssharp = "s",
+ },
+ bothkerned = allocate {
+ Acircumflex = "A", acircumflex = "a",
+ Ccircumflex = "C", ccircumflex = "c",
+ Ecircumflex = "E", ecircumflex = "e",
+ Gcircumflex = "G", gcircumflex = "g",
+ Hcircumflex = "H", hcircumflex = "h",
+ Icircumflex = "I", icircumflex = "i",
+ Jcircumflex = "J", jcircumflex = "j",
+ Ocircumflex = "O", ocircumflex = "o",
+ Scircumflex = "S", scircumflex = "s",
+ Ucircumflex = "U", ucircumflex = "u",
+ Wcircumflex = "W", wcircumflex = "w",
+ Ycircumflex = "Y", ycircumflex = "y",
+
+ Agrave = "A", agrave = "a",
+ Egrave = "E", egrave = "e",
+ Igrave = "I", igrave = "i",
+ Ograve = "O", ograve = "o",
+ Ugrave = "U", ugrave = "u",
+ Ygrave = "Y", ygrave = "y",
+
+ Atilde = "A", atilde = "a",
+ Itilde = "I", itilde = "i",
+ Otilde = "O", otilde = "o",
+ Utilde = "U", utilde = "u",
+ Ntilde = "N", ntilde = "n",
+
+ Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a",
+ Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e",
+ Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i",
+ Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o",
+ Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u",
+ Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y",
+
+ Aacute = "A", aacute = "a",
+ Cacute = "C", cacute = "c",
+ Eacute = "E", eacute = "e",
+ Iacute = "I", iacute = "i",
+ Lacute = "L", lacute = "l",
+ Nacute = "N", nacute = "n",
+ Oacute = "O", oacute = "o",
+ Racute = "R", racute = "r",
+ Sacute = "S", sacute = "s",
+ Uacute = "U", uacute = "u",
+ Yacute = "Y", yacute = "y",
+ Zacute = "Z", zacute = "z",
+
+ Dstroke = "D", dstroke = "d",
+ Hstroke = "H", hstroke = "h",
+ Tstroke = "T", tstroke = "t",
+
+ Cdotaccent = "C", cdotaccent = "c",
+ Edotaccent = "E", edotaccent = "e",
+ Gdotaccent = "G", gdotaccent = "g",
+ Idotaccent = "I", idotaccent = "i",
+ Zdotaccent = "Z", zdotaccent = "z",
+
+ Amacron = "A", amacron = "a",
+ Emacron = "E", emacron = "e",
+ Imacron = "I", imacron = "i",
+ Omacron = "O", omacron = "o",
+ Umacron = "U", umacron = "u",
+
+ Ccedilla = "C", ccedilla = "c",
+ Kcedilla = "K", kcedilla = "k",
+ Lcedilla = "L", lcedilla = "l",
+ Ncedilla = "N", ncedilla = "n",
+ Rcedilla = "R", rcedilla = "r",
+ Scedilla = "S", scedilla = "s",
+ Tcedilla = "T", tcedilla = "t",
+
+ Ohungarumlaut = "O", ohungarumlaut = "o",
+ Uhungarumlaut = "U", uhungarumlaut = "u",
+
+ Aogonek = "A", aogonek = "a",
+ Eogonek = "E", eogonek = "e",
+ Iogonek = "I", iogonek = "i",
+ Uogonek = "U", uogonek = "u",
+
+ Aring = "A", aring = "a",
+ Uring = "U", uring = "u",
+
+ Abreve = "A", abreve = "a",
+ Ebreve = "E", ebreve = "e",
+ Gbreve = "G", gbreve = "g",
+ Ibreve = "I", ibreve = "i",
+ Obreve = "O", obreve = "o",
+ Ubreve = "U", ubreve = "u",
+
+ Ccaron = "C", ccaron = "c",
+ Dcaron = "D", dcaron = "d",
+ Ecaron = "E", ecaron = "e",
+ Lcaron = "L", lcaron = "l",
+ Ncaron = "N", ncaron = "n",
+ Rcaron = "R", rcaron = "r",
+ Scaron = "S", scaron = "s",
+ Tcaron = "T", tcaron = "t",
+ Zcaron = "Z", zcaron = "z",
+
+ dotlessI = "I", dotlessi = "i",
+ dotlessJ = "J", dotlessj = "j",
+
+ AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae",
+ OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe",
+ IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij",
+
+ Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l",
+ Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o",
+
+ Ssharp = "SS", ssharp = "ss",
+
+ Aumlaut = "A", aumlaut = "a",
+ Eumlaut = "E", eumlaut = "e",
+ Iumlaut = "I", iumlaut = "i",
+ Oumlaut = "O", oumlaut = "o",
+ Uumlaut = "U", uumlaut = "u",
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-afm.lua b/Master/texmf-dist/tex/context/base/mkiv/font-afm.lua
new file mode 100644
index 00000000000..3dedf12e1da
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-afm.lua
@@ -0,0 +1,1197 @@
+if not modules then modules = { } end modules ['font-afm'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Some code may look a bit obscure but this has to do with the
+fact that we also use this code for testing and much code evolved
+in the transition from <l n='tfm'/> to <l n='afm'/> to <l
+n='otf'/>.</p>
+
+<p>The following code still has traces of intermediate font support
+where we handles font encodings. Eventually font encoding goes
+away.</p>
+
+<p>The embedding of a font involves creating temporary files and
+depending on your system setup that can fail. It took more than a
+day to figure out why sometimes embedding failed in mingw luatex
+where running on a real path like c:\... failed while running on
+say e:\... being a link worked well. The native windows binaries
+don't have this issue.</p>
+
+--ldx]]--
+
+local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
+
+local next, type, tonumber = next, type, tonumber
+local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find
+local char, byte, sub = string.char, string.byte, string.sub
+local abs, mod = math.abs, math.mod
+local bxor, rshift = bit32.bxor, bit32.rshift
+local P, S, R, Cmt, C, Ct, Cs, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns
+local derivetable = table.derive
+
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+local report_afm = logs.reporter("fonts","afm loading")
+
+local setmetatableindex = table.setmetatableindex
+
+local findbinfile = resolvers.findbinfile
+
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local afm = constructors.newhandler("afm")
+local pfb = constructors.newhandler("pfb")
+
+local afmfeatures = constructors.newfeatures("afm")
+local registerafmfeature = afmfeatures.register
+
+afm.version = 1.500 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "afm", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
+afm.addligatures = true -- best leave this set to true
+afm.addtexligatures = true -- best leave this set to true
+afm.addkerns = true -- best leave this set to true
+
+local overloads = fonts.mappings.overloads
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+local function setmode(tfmdata,value)
+ if value then
+ tfmdata.properties.mode = lower(value)
+ end
+end
+
+registerafmfeature {
+ name = "mode",
+ description = "mode",
+ initializers = {
+ base = setmode,
+ node = setmode,
+ }
+}
+
+--[[ldx--
+<p>We start with the basic reader which we give a name similar to the
+built in <l n='tfm'/> and <l n='otf'/> reader.</p>
+--ldx]]--
+
+--~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
+--~ Comment CODINGSCHEME TEX MATH SYMBOLS
+--~ Comment DESIGNSIZE 10.0 pt
+--~ Comment CHECKSUM O 4261307036
+--~ Comment SPACE 0 plus 0 minus 0
+--~ Comment QUAD 1000
+--~ Comment EXTRASPACE 0
+--~ Comment NUM 676.508 393.732 443.731
+--~ Comment DENOM 685.951 344.841
+--~ Comment SUP 412.892 362.892 288.889
+--~ Comment SUB 150 247.217
+--~ Comment SUPDROP 386.108
+--~ Comment SUBDROP 50
+--~ Comment DELIM 2390 1010
+--~ Comment AXISHEIGHT 250
+
+local comment = P("Comment")
+local spacing = patterns.spacer -- S(" \t")^1
+local lineend = patterns.newline -- S("\n\r")
+local words = C((1 - lineend)^1)
+local number = C((R("09") + S("."))^1) / tonumber * spacing^0
+local data = lpeg.Carg(1)
+
+local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
+ comment * spacing *
+ (
+ data * (
+ ("CODINGSCHEME" * spacing * words ) / function(fd,a) end +
+ ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end +
+ ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end +
+ ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
+ ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end +
+ ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end +
+ ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
+ ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end +
+ ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
+ ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end +
+ ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end +
+ ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end +
+ ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end +
+ ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end
+ )
+ + (1-lineend)^0
+ )
+ + (1-comment)^1
+)^0
+
+local function scan_comment(str)
+ local fd = { }
+ lpegmatch(pattern,str,1,fd)
+ return fd
+end
+
+-- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader
+-- as in now supports afm/pfb loading but it's not too bad to have different methods
+-- for testing approaches.
+
+local keys = { }
+
+function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
+ data.metadata.fullname = strip (line) end
+function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end
+function keys.IsFixedPitch(data,line) data.metadata.monospaced = toboolean(line,true) end
+function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end
+function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end
+function keys.Descender (data,line) data.metadata.descender = tonumber (line) end
+function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
+function keys.Comment (data,line)
+ -- Comment DesignSize 12 (pts)
+ -- Comment TFM designsize: 12 (in points)
+ line = lower(line)
+ local designsize = match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize = tonumber(designsize) end
+end
+
+local function get_charmetrics(data,charmetrics,vector)
+ local characters = data.characters
+ local chr, ind = { }, 0
+ for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
+ if k == 'C' then
+ v = tonumber(v)
+ if v < 0 then
+ ind = ind + 1 -- ?
+ else
+ ind = v
+ end
+ chr = {
+ index = ind
+ }
+ elseif k == 'WX' then
+ chr.width = tonumber(v)
+ elseif k == 'N' then
+ characters[v] = chr
+ elseif k == 'B' then
+ local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
+ chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
+ elseif k == 'L' then
+ local plus, becomes = match(v,"^(.-) +(.-)$")
+ local ligatures = chr.ligatures
+ if ligatures then
+ ligatures[plus] = becomes
+ else
+ chr.ligatures = { [plus] = becomes }
+ end
+ end
+ end
+end
+
+local function get_kernpairs(data,kernpairs)
+ local characters = data.characters
+ for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
+ local chr = characters[one]
+ if chr then
+ local kerns = chr.kerns
+ if kerns then
+ kerns[two] = tonumber(value)
+ else
+ chr.kerns = { [two] = tonumber(value) }
+ end
+ end
+ end
+end
+
+local function get_variables(data,fontmetrics)
+ for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
+ local keyhandler = keys[key]
+ if keyhandler then
+ keyhandler(data,rest)
+ end
+ end
+end
+
+local get_indexes
+
+do
+
+ -- old font loader
+
+ local fontloader = fontloader
+
+ if fontloader then
+
+ local font_to_table = fontloader.to_table
+ local open_font = fontloader.open
+ local close_font = fontloader.close
+
+ local function get_indexes_old(data,pfbname)
+ local pfbblob = open_font(pfbname)
+ if pfbblob then
+ local characters = data.characters
+ local pfbdata = font_to_table(pfbblob)
+ if pfbdata then
+ local glyphs = pfbdata.glyphs
+ if glyphs then
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index, glyph in next, glyphs do
+ local name = glyph.name
+ if name then
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ elseif trace_loading then
+ report_afm("no glyph data in pfb file %a",pfbname)
+ end
+ elseif trace_loading then
+ report_afm("no data in pfb file %a",pfbname)
+ end
+ close_font(pfbblob)
+ elseif trace_loading then
+ report_afm("invalid pfb file %a",pfbname)
+ end
+ end
+
+ end
+
+ -- new (unfinished) font loader but i see no differences between
+ -- old and new (one bad vector with old)
+
+ local n, m
+
+ local progress = function(str,position,name,size)
+ local forward = position + tonumber(size) + 3 + 2
+ n = n + 1
+ if n >= m then
+ return #str, name
+ elseif forward < #str then
+ return forward, name
+ else
+ return #str, name
+ end
+ end
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = tonumber(size)
+ return position + 1
+ end
+
+ local charstrings = P("/CharStrings")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size = C(R("09")^1)
+ local spaces = P(" ")^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
+ * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
+ )
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local decrypt
+
+ do
+
+ local r, c1, c2, n = 0, 0, 0, 0
+
+ local function step(c)
+ local cipher = byte(c)
+ local plain = bxor(cipher,rshift(r,8))
+ r = mod((cipher + r) * c1 + c2,65536)
+ return char(plain)
+ end
+
+ decrypt = function(binary)
+ r, c1, c2, n = 55665, 52845, 22719, 4
+ binary = gsub(binary,".",step)
+ return sub(binary,n+1)
+ end
+
+ -- local pattern = Cs((P(1) / step)^1)
+ --
+ -- decrypt = function(binary)
+ -- r, c1, c2, n = 55665, 52845, 22719, 4
+ -- binary = lpegmatch(pattern,binary)
+ -- return sub(binary,n+1)
+ -- end
+
+ end
+
+ local function loadpfbvector(filename)
+ -- for the moment limited to encoding only
+
+ local data = io.loaddata(resolvers.findfile(filename))
+
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
+
+ if not data then
+ print("no data",filename)
+ return
+ end
+
+ local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
+
+ if not binary then
+ print("no binary",filename)
+ return
+ end
+
+ binary = decrypt(binary,4)
+
+ local vector = lpegmatch(p_filternames,binary)
+
+ vector[0] = table.remove(vector,1)
+
+ if not vector then
+ print("no vector",filename)
+ return
+ end
+
+ return vector
+
+ end
+
+ get_indexes = function(data,pfbname)
+ local vector = loadpfbvector(pfbname)
+ if vector then
+ local characters = data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index=1,#vector do
+ local name = vector[index]
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ end
+
+ if fontloader then
+
+ afm.use_new_indexer = true
+ get_indexes_new = get_indexes
+
+ get_indexes = function(data,pfbname)
+ if afm.use_new_indexer then
+ return get_indexes_new(data,pfbname)
+ else
+ return get_indexes_old(data,pfbname)
+ end
+ end
+
+ end
+
+end
+
+local function readafm(filename)
+ local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
+ if ok and afmblob then
+ local data = {
+ resources = {
+ filename = resolvers.unresolve(filename),
+ version = afm.version,
+ creator = "context mkiv",
+ },
+ properties = {
+ hasitalics = false,
+ },
+ goodies = {
+ },
+ metadata = {
+ filename = file.removesuffix(file.basename(filename))
+ },
+ characters = {
+ -- a temporary store
+ },
+ descriptions = {
+ -- the final store
+ },
+ }
+ afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
+ if trace_loading then
+ report_afm("loading char metrics")
+ end
+ get_charmetrics(data,charmetrics,vector)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
+ if trace_loading then
+ report_afm("loading kern pairs")
+ end
+ get_kernpairs(data,kernpairs)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
+ if trace_loading then
+ report_afm("loading variables")
+ end
+ data.afmversion = version
+ get_variables(data,fontmetrics)
+ data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
+ return ""
+ end)
+ return data
+ else
+ if trace_loading then
+ report_afm("no valid afm file %a",filename)
+ end
+ return nil
+ end
+end
+
+--[[ldx--
+<p>We cache files. Caching is taken care of in the loader. We cheat a bit
+by adding ligatures and kern information to the afm derived data. That
+way we can set them faster when defining a font.</p>
+--ldx]]--
+
+local addkerns, addligatures, addtexligatures, unify, normalize, fixnames -- we will implement these later
+
+function afm.load(filename)
+ -- hm, for some reasons not resolved yet
+ filename = resolvers.findfile(filename,'afm') or ""
+ if filename ~= "" and not fonts.names.ignoredfile(filename) then
+ 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 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
+ if pfbname ~= "" then
+ local attr = lfs.attributes(pfbname)
+ pfbsize = attr.size or 0
+ pfbtime = attr.modification or 0
+ end
+ if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
+ report_afm("reading %a",filename)
+ data = readafm(filename)
+ if data then
+ if pfbname ~= "" then
+ data.resources.filename = resolvers.unresolve(pfbname)
+ get_indexes(data,pfbname)
+ elseif trace_loading then
+ report_afm("no pfb file for %a",filename)
+ -- data.resources.filename = "unset" -- better than loading the afm file
+ end
+ report_afm("unifying %a",filename)
+ unify(data,filename)
+ if afm.addligatures then
+ report_afm("add ligatures")
+ addligatures(data)
+ end
+ if afm.addtexligatures then
+ report_afm("add tex ligatures")
+ addtexligatures(data)
+ end
+ if afm.addkerns then
+ report_afm("add extra kerns")
+ addkerns(data)
+ end
+ normalize(data)
+ fixnames(data)
+ report_afm("add tounicode data")
+ fonts.mappings.addtounicode(data,filename)
+ data.size = size
+ data.time = time
+ data.pfbsize = pfbsize
+ data.pfbtime = pfbtime
+ report_afm("saving %a in cache",name)
+ data.resources.unicodes = nil -- consistent with otf but here we save not much
+ data = containers.write(afm.cache, name, data)
+ data = containers.read(afm.cache,name)
+ end
+ if applyruntimefixes and data then
+ applyruntimefixes(filename,data)
+ end
+ end
+ return data
+ else
+ return nil
+ end
+end
+
+local uparser = fonts.mappings.makenameparser()
+
+unify = function(data, filename)
+ local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
+ local unicodes, names = { }, { }
+ local private = constructors.privateoffset
+ local descriptions = data.descriptions
+ for name, blob in next, data.characters do
+ local code = unicodevector[name] -- or characters.name_to_unicode[name]
+ if not code then
+ code = lpegmatch(uparser,name)
+ if not code then
+ code = private
+ private = private + 1
+ report_afm("assigning private slot %U for unknown glyph name %a",code,name)
+ end
+ end
+ local index = blob.index
+ unicodes[name] = code
+ names[name] = index
+ blob.name = name
+ descriptions[code] = {
+ boundingbox = blob.boundingbox,
+ width = blob.width,
+ kerns = blob.kerns,
+ index = index,
+ name = name,
+ }
+ end
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local krn = { }
+ for name, kern in next, kerns do
+ local unicode = unicodes[name]
+ if unicode then
+ krn[unicode] = kern
+ else
+ -- print(unicode,name)
+ end
+ end
+ description.kerns = krn
+ end
+ end
+ data.characters = nil
+ local resources = data.resources
+ local filename = resources.filename or file.removesuffix(file.basename(filename))
+ resources.filename = resolvers.unresolve(filename) -- no shortcut
+ resources.unicodes = unicodes -- name to unicode
+ resources.marks = { } -- todo
+ -- resources.names = names -- name to index
+ resources.private = private
+end
+
+normalize = function(data)
+end
+
+fixnames = function(data)
+ for k, v in next, data.descriptions do
+ local n = v.name
+ local r = overloads[n]
+ if r then
+ local name = r.name
+ if trace_indexing then
+ report_afm("renaming characters %a to %a",n,name)
+ end
+ v.name = name
+ v.unicode = r.unicode
+ end
+ end
+end
+
+
+--[[ldx--
+<p>These helpers extend the basic table with extra ligatures, texligatures
+and extra kerns. This saves quite some lookups later.</p>
+--ldx]]--
+
+local addthem = function(rawdata,ligatures)
+ if ligatures then
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ -- local names = resources.names
+ for ligname, ligdata in next, ligatures do
+ local one = descriptions[unicodes[ligname]]
+ if one then
+ for _, pair in next, ligdata do
+ local two, three = unicodes[pair[1]], unicodes[pair[2]]
+ if two and three then
+ local ol = one.ligatures
+ if ol then
+ if not ol[two] then
+ ol[two] = three
+ end
+ else
+ one.ligatures = { [two] = three }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
+addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
+
+--[[ldx--
+<p>We keep the extra kerns in separate kerning tables so that we can use
+them selectively.</p>
+--ldx]]--
+
+-- This is rather old code (from the beginning when we had only tfm). If
+-- we unify the afm data (now we have names all over the place) then
+-- we can use shcodes but there will be many more looping then. But we
+-- could get rid of the tables in char-cmp then. Als, in the generic version
+-- we don't use the character database. (Ok, we can have a context specific
+-- variant).
+
+addkerns = function(rawdata) -- using shcodes is not robust here
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local function do_it_left(what)
+ if what then
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local extrakerns
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local ks = kerns[simple]
+ if ks and not kerns[complex] then
+ if extrakerns then
+ extrakerns[complex] = ks
+ else
+ extrakerns = { [complex] = ks }
+ end
+ end
+ end
+ end
+ if extrakerns then
+ description.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ local function do_it_copy(what)
+ if what then
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local complexdescription = descriptions[complex]
+ if complexdescription then -- optional
+ local simpledescription = descriptions[complex]
+ if simpledescription then
+ local extrakerns
+ local kerns = simpledescription.kerns
+ if kerns then
+ for unicode, kern in next, kerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ local extrakerns = simpledescription.extrakerns
+ if extrakerns then
+ for unicode, kern in next, extrakerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ if extrakerns then
+ complexdescription.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- add complex with values of simplified when present
+ do_it_left(afm.helpdata.leftkerned)
+ do_it_left(afm.helpdata.bothkerned)
+ -- copy kerns from simple char to complex char unless set
+ do_it_copy(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.rightkerned)
+end
+
+--[[ldx--
+<p>The copying routine looks messy (and is indeed a bit messy).</p>
+--ldx]]--
+
+local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
+ if data then
+ for unicode, description in next, data.descriptions do
+ local bb = description.boundingbox
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- no need to set it and no negative heights, nil == 0
+ else
+ description.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- no negative depths and no negative depths, nil == 0
+ else
+ description.depth = dp
+ end
+ end
+ end
+ end
+end
+
+local function copytotfm(data)
+ if data and data.descriptions then
+ local metadata = data.metadata
+ local resources = data.resources
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { }
+ local parameters = { }
+ local unicodes = resources.unicodes
+ --
+ for unicode, description in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ --
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname or metadata.fullname
+ local fullname = metadata.fullname or metadata.fontname
+ local endash = 0x0020 -- space
+ local emdash = 0x2014
+ local spacer = "space"
+ local spaceunits = 500
+ --
+ local monospaced = metadata.monospaced
+ local charwidth = metadata.charwidth
+ local italicangle = metadata.italicangle
+ local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
+ properties.monospaced = monospaced
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ -- same as otf
+ if properties.monospaced then
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ else
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits)
+ if spaceunits < 200 then
+ -- todo: warning
+ end
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits
+ parameters.space_stretch = 500
+ parameters.space_shrink = 333
+ parameters.x_height = 400
+ parameters.quad = 1000
+ --
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif afm.syncspace then
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink
+ if charxheight then
+ parameters.x_height = charxheight
+ else
+ -- same as otf
+ local x = 0x0078 -- x
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ --
+ end
+ local fd = data.fontdimens
+ if fd and fd[8] and fd[9] and fd[10] then -- math
+ for k,v in next, fd do
+ parameters[k] = v
+ end
+ end
+ --
+ parameters.designsize = (metadata.designsize or 10)*65536
+ parameters.ascender = abs(metadata.ascender or 0)
+ parameters.descender = abs(metadata.descender or 0)
+ parameters.units = 1000
+ --
+ properties.spacer = spacer
+ properties.encodingbytes = 2
+ properties.format = fonts.formats[filename] or "type1"
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = fullname
+ properties.name = filename or fullname or fontname
+ --
+ if next(characters) then
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ }
+ end
+ end
+ return nil
+end
+
+--[[ldx--
+<p>Originally we had features kind of hard coded for <l n='afm'/>
+files but since I expect to support more font formats, I decided
+to treat this fontformat like any other and handle features in a
+more configurable way.</p>
+--ldx]]--
+
+function afm.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
+ if okay then
+ return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
+ else
+ return { } -- will become false
+ end
+end
+
+local function addtables(data)
+ local resources = data.resources
+ local lookuptags = resources.lookuptags
+ local unicodes = resources.unicodes
+ if not lookuptags then
+ lookuptags = { }
+ resources.lookuptags = lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v = type(k) == "number" and ("lookup " .. k) or k
+ t[k] = v
+ return v
+ end)
+ if not unicodes then
+ unicodes = { }
+ resources.unicodes = unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u, d in next, data.descriptions do
+ local n = d.name
+ if n then
+ t[n] = u
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes) -- do we really need this?
+end
+
+local function afmtotfm(specification)
+ local afmname = specification.filename or specification.name
+ if specification.forced == "afm" or specification.format == "afm" then -- move this one up
+ if trace_loading then
+ report_afm("forcing afm format for %a",afmname)
+ end
+ else
+ local tfmname = findbinfile(afmname,"ofm") or ""
+ if tfmname ~= "" then
+ if trace_loading then
+ report_afm("fallback from afm to tfm for %a",afmname)
+ end
+ return -- just that
+ end
+ end
+ if afmname ~= "" then
+ -- weird, isn't this already done then?
+ local features = constructors.checkedfeatures("afm",specification.features.normal)
+ specification.features.normal = features
+ constructors.hashinstance(specification,true) -- also weird here
+ --
+ specification = definers.resolve(specification) -- new, was forgotten
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied
+ if not tfmdata then
+ local rawdata = afm.load(afmname)
+ if rawdata and next(rawdata) then
+ addtables(rawdata)
+ adddimensions(rawdata)
+ tfmdata = copytotfm(rawdata)
+ if tfmdata and next(tfmdata) then
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ shared.features = features
+ shared.processes = afm.setfeatures(tfmdata,features)
+ end
+ elseif trace_loading then
+ report_afm("no (valid) afm file found with name %a",afmname)
+ end
+ tfmdata = containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+ end
+end
+
+--[[ldx--
+<p>As soon as we could intercept the <l n='tfm'/> reader, I implemented an
+<l n='afm'/> reader. Since traditional <l n='pdftex'/> could use <l n='opentype'/>
+fonts with <l n='afm'/> companions, the following method also could handle
+those cases, but now that we can handle <l n='opentype'/> directly we no longer
+need this features.</p>
+--ldx]]--
+
+local function read_from_afm(specification)
+ local tfmdata = afmtotfm(specification)
+ if tfmdata then
+ tfmdata.properties.name = specification.name
+ tfmdata = constructors.scale(tfmdata, specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
+ fonts.loggers.register(tfmdata,'afm',specification)
+ end
+ return tfmdata
+end
+
+--[[ldx--
+<p>Here comes the implementation of a few features. We only implement
+those that make sense for this format.</p>
+--ldx]]--
+
+local function prepareligatures(tfmdata,ligatures,value)
+ if value then
+ local descriptions = tfmdata.descriptions
+ local hasligatures = false
+ for unicode, character in next, tfmdata.characters do
+ local description = descriptions[unicode]
+ local dligatures = description.ligatures
+ if dligatures then
+ local cligatures = character.ligatures
+ if not cligatures then
+ cligatures = { }
+ character.ligatures = cligatures
+ end
+ for unicode, ligature in next, dligatures do
+ cligatures[unicode] = {
+ char = ligature,
+ type = 0
+ }
+ end
+ hasligatures = true
+ end
+ end
+ tfmdata.properties.hasligatures = hasligatures
+ end
+end
+
+local function preparekerns(tfmdata,kerns,value)
+ if value then
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local descriptions = tfmdata.descriptions
+ local haskerns = false
+ for u, chr in next, tfmdata.characters do
+ local d = descriptions[u]
+ local newkerns = d[kerns]
+ if newkerns then
+ local kerns = chr.kerns
+ if not kerns then
+ kerns = { }
+ chr.kerns = kerns
+ end
+ for k,v in next, newkerns do
+ local uk = unicodes[k]
+ if uk then
+ kerns[uk] = v
+ end
+ end
+ haskerns = true
+ end
+ end
+ tfmdata.properties.haskerns = haskerns
+ end
+end
+
+local list = {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+}
+
+local function texreplacements(tfmdata,value)
+ local descriptions = tfmdata.descriptions
+ local characters = tfmdata.characters
+ for k, v in next, list do
+ characters [k] = characters [v] -- we forget about kerns
+ descriptions[k] = descriptions[v] -- we forget about kerns
+ end
+end
+
+local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end
+local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
+local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end
+local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end
+
+registerafmfeature {
+ name = "liga",
+ description = "traditional ligatures",
+ initializers = {
+ base = ligatures,
+ node = ligatures,
+ }
+}
+
+registerafmfeature {
+ name = "kern",
+ description = "intercharacter kerning",
+ initializers = {
+ base = kerns,
+ node = kerns,
+ }
+}
+
+registerafmfeature {
+ name = "extrakerns",
+ description = "additional intercharacter kerning",
+ initializers = {
+ base = extrakerns,
+ node = extrakerns,
+ }
+}
+
+registerafmfeature {
+ name = 'tlig',
+ description = 'tex ligatures',
+ initializers = {
+ base = texligatures,
+ node = texligatures,
+ }
+}
+
+registerafmfeature {
+ name = 'trep',
+ description = 'tex replacements',
+ initializers = {
+ base = texreplacements,
+ node = texreplacements,
+ }
+}
+
+-- readers
+
+local check_tfm = readers.check_tfm
+
+fonts.formats.afm = "type1"
+fonts.formats.pfb = "type1"
+
+local function check_afm(specification,fullname)
+ local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"afm") or ""
+ end
+ if foundname == "" and afm.autoprefixed then
+ local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if encoding and shortname and fonts.encodings.known[encoding] then
+ shortname = findbinfile(shortname,'afm') or "" -- just to be sure
+ if shortname ~= "" then
+ foundname = shortname
+ if trace_defining then
+ report_afm("stripping encoding prefix from filename %a",afmname)
+ end
+ end
+ end
+ end
+ if foundname ~= "" then
+ specification.filename = foundname
+ specification.format = "afm"
+ return read_from_afm(specification)
+ end
+end
+
+function readers.afm(specification,method)
+ local fullname, tfmdata = specification.filename or "", nil
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmdata = check_afm(specification,specification.name .. "." .. forced)
+ end
+ if not tfmdata then
+ method = method or definers.method or "afm or tfm"
+ if method == "tfm" then
+ tfmdata = check_tfm(specification,specification.name)
+ elseif method == "afm" then
+ tfmdata = check_afm(specification,specification.name)
+ elseif method == "tfm or afm" then
+ tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
+ else -- method == "afm or tfm" or method == "" then
+ tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
+ end
+ end
+ else
+ tfmdata = check_afm(specification,fullname)
+ end
+ return tfmdata
+end
+
+function readers.pfb(specification,method) -- only called when forced
+ local original = specification.specification
+ if trace_defining then
+ report_afm("using afm reader for %a",original)
+ end
+ specification.specification = gsub(original,"%.pfb",".afm")
+ specification.forced = "afm"
+ return readers.afm(specification,method)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-age.lua b/Master/texmf-dist/tex/context/base/mkiv/font-age.lua
new file mode 100644
index 00000000000..bb6883a7470
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-age.lua
@@ -0,0 +1,4115 @@
+if not modules then modules = { } end modules ['font-age'] = {
+ version = 1.001,
+ comment = "companion to luatex-fonts.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "derived from http://www.adobe.com/devnet/opentype/archives/glyphlist.txt",
+ original = "Adobe Glyph List, version 2.0, September 20, 2002",
+ dataonly = true,
+}
+
+if context then
+ logs.report("fatal error","this module is not for context")
+ os.exit()
+end
+
+return { -- generated: inspect(fonts.encodings.agl.unicodes)
+ ["A"]=65,
+ ["AE"]=198,
+ ["AEacute"]=508,
+ ["AEmacron"]=482,
+ ["Aacute"]=193,
+ ["Abreve"]=258,
+ ["Abreveacute"]=7854,
+ ["Abrevecyrillic"]=1232,
+ ["Abrevedotbelow"]=7862,
+ ["Abrevegrave"]=7856,
+ ["Abrevehookabove"]=7858,
+ ["Abrevetilde"]=7860,
+ ["Acaron"]=461,
+ ["Acircle"]=9398,
+ ["Acircumflex"]=194,
+ ["Acircumflexacute"]=7844,
+ ["Acircumflexdotbelow"]=7852,
+ ["Acircumflexgrave"]=7846,
+ ["Acircumflexhookabove"]=7848,
+ ["Acircumflextilde"]=7850,
+ ["Acyrillic"]=1040,
+ ["Adblgrave"]=512,
+ ["Adieresis"]=196,
+ ["Adieresiscyrillic"]=1234,
+ ["Adieresismacron"]=478,
+ ["Adotbelow"]=7840,
+ ["Adotmacron"]=480,
+ ["Agrave"]=192,
+ ["Ahookabove"]=7842,
+ ["Aiecyrillic"]=1236,
+ ["Ainvertedbreve"]=514,
+ ["Alpha"]=913,
+ ["Alphatonos"]=902,
+ ["Amacron"]=256,
+ ["Amonospace"]=65313,
+ ["Aogonek"]=260,
+ ["Aring"]=197,
+ ["Aringacute"]=506,
+ ["Aringbelow"]=7680,
+ ["Atilde"]=195,
+ ["Aybarmenian"]=1329,
+ ["B"]=66,
+ ["Bcircle"]=9399,
+ ["Bdotaccent"]=7682,
+ ["Bdotbelow"]=7684,
+ ["Becyrillic"]=1041,
+ ["Benarmenian"]=1330,
+ ["Beta"]=914,
+ ["Bhook"]=385,
+ ["Blinebelow"]=7686,
+ ["Bmonospace"]=65314,
+ ["Btopbar"]=386,
+ ["C"]=67,
+ ["Caarmenian"]=1342,
+ ["Cacute"]=262,
+ ["Ccaron"]=268,
+ ["Ccedilla"]=199,
+ ["Ccedillaacute"]=7688,
+ ["Ccircle"]=9400,
+ ["Ccircumflex"]=264,
+ ["Cdot"]=266,
+ ["Cdotaccent"]=266,
+ ["Chaarmenian"]=1353,
+ ["Cheabkhasiancyrillic"]=1212,
+ ["Checyrillic"]=1063,
+ ["Chedescenderabkhasiancyrillic"]=1214,
+ ["Chedescendercyrillic"]=1206,
+ ["Chedieresiscyrillic"]=1268,
+ ["Cheharmenian"]=1347,
+ ["Chekhakassiancyrillic"]=1227,
+ ["Cheverticalstrokecyrillic"]=1208,
+ ["Chi"]=935,
+ ["Chook"]=391,
+ ["Cmonospace"]=65315,
+ ["Coarmenian"]=1361,
+ ["D"]=68,
+ ["DZ"]=497,
+ ["DZcaron"]=452,
+ ["Daarmenian"]=1332,
+ ["Dafrican"]=393,
+ ["Dcaron"]=270,
+ ["Dcedilla"]=7696,
+ ["Dcircle"]=9401,
+ ["Dcircumflexbelow"]=7698,
+ ["Dcroat"]=272,
+ ["Ddotaccent"]=7690,
+ ["Ddotbelow"]=7692,
+ ["Decyrillic"]=1044,
+ ["Deicoptic"]=1006,
+ ["Delta"]=8710,
+ ["Deltagreek"]=916,
+ ["Dhook"]=394,
+ ["Digammagreek"]=988,
+ ["Djecyrillic"]=1026,
+ ["Dlinebelow"]=7694,
+ ["Dmonospace"]=65316,
+ ["Dslash"]=272,
+ ["Dtopbar"]=395,
+ ["Dz"]=498,
+ ["Dzcaron"]=453,
+ ["Dzeabkhasiancyrillic"]=1248,
+ ["Dzecyrillic"]=1029,
+ ["Dzhecyrillic"]=1039,
+ ["E"]=69,
+ ["Eacute"]=201,
+ ["Ebreve"]=276,
+ ["Ecaron"]=282,
+ ["Ecedillabreve"]=7708,
+ ["Echarmenian"]=1333,
+ ["Ecircle"]=9402,
+ ["Ecircumflex"]=202,
+ ["Ecircumflexacute"]=7870,
+ ["Ecircumflexbelow"]=7704,
+ ["Ecircumflexdotbelow"]=7878,
+ ["Ecircumflexgrave"]=7872,
+ ["Ecircumflexhookabove"]=7874,
+ ["Ecircumflextilde"]=7876,
+ ["Ecyrillic"]=1028,
+ ["Edblgrave"]=516,
+ ["Edieresis"]=203,
+ ["Edot"]=278,
+ ["Edotaccent"]=278,
+ ["Edotbelow"]=7864,
+ ["Efcyrillic"]=1060,
+ ["Egrave"]=200,
+ ["Eharmenian"]=1335,
+ ["Ehookabove"]=7866,
+ ["Eightroman"]=8551,
+ ["Einvertedbreve"]=518,
+ ["Eiotifiedcyrillic"]=1124,
+ ["Elcyrillic"]=1051,
+ ["Elevenroman"]=8554,
+ ["Emacron"]=274,
+ ["Emacronacute"]=7702,
+ ["Emacrongrave"]=7700,
+ ["Emcyrillic"]=1052,
+ ["Emonospace"]=65317,
+ ["Encyrillic"]=1053,
+ ["Endescendercyrillic"]=1186,
+ ["Eng"]=330,
+ ["Enghecyrillic"]=1188,
+ ["Enhookcyrillic"]=1223,
+ ["Eogonek"]=280,
+ ["Eopen"]=400,
+ ["Epsilon"]=917,
+ ["Epsilontonos"]=904,
+ ["Ercyrillic"]=1056,
+ ["Ereversed"]=398,
+ ["Ereversedcyrillic"]=1069,
+ ["Escyrillic"]=1057,
+ ["Esdescendercyrillic"]=1194,
+ ["Esh"]=425,
+ ["Eta"]=919,
+ ["Etarmenian"]=1336,
+ ["Etatonos"]=905,
+ ["Eth"]=208,
+ ["Etilde"]=7868,
+ ["Etildebelow"]=7706,
+ ["Euro"]=8364,
+ ["Ezh"]=439,
+ ["Ezhcaron"]=494,
+ ["Ezhreversed"]=440,
+ ["F"]=70,
+ ["Fcircle"]=9403,
+ ["Fdotaccent"]=7710,
+ ["Feharmenian"]=1366,
+ ["Feicoptic"]=996,
+ ["Fhook"]=401,
+ ["Fitacyrillic"]=1138,
+ ["Fiveroman"]=8548,
+ ["Fmonospace"]=65318,
+ ["Fourroman"]=8547,
+ ["G"]=71,
+ ["GBsquare"]=13191,
+ ["Gacute"]=500,
+ ["Gamma"]=915,
+ ["Gammaafrican"]=404,
+ ["Gangiacoptic"]=1002,
+ ["Gbreve"]=286,
+ ["Gcaron"]=486,
+ ["Gcedilla"]=290,
+ ["Gcircle"]=9404,
+ ["Gcircumflex"]=284,
+ ["Gcommaaccent"]=290,
+ ["Gdot"]=288,
+ ["Gdotaccent"]=288,
+ ["Gecyrillic"]=1043,
+ ["Ghadarmenian"]=1346,
+ ["Ghemiddlehookcyrillic"]=1172,
+ ["Ghestrokecyrillic"]=1170,
+ ["Gheupturncyrillic"]=1168,
+ ["Ghook"]=403,
+ ["Gimarmenian"]=1331,
+ ["Gjecyrillic"]=1027,
+ ["Gmacron"]=7712,
+ ["Gmonospace"]=65319,
+ ["Gsmallhook"]=667,
+ ["Gstroke"]=484,
+ ["H"]=72,
+ ["H18533"]=9679,
+ ["H18543"]=9642,
+ ["H18551"]=9643,
+ ["H22073"]=9633,
+ ["HPsquare"]=13259,
+ ["Haabkhasiancyrillic"]=1192,
+ ["Hadescendercyrillic"]=1202,
+ ["Hardsigncyrillic"]=1066,
+ ["Hbar"]=294,
+ ["Hbrevebelow"]=7722,
+ ["Hcedilla"]=7720,
+ ["Hcircle"]=9405,
+ ["Hcircumflex"]=292,
+ ["Hdieresis"]=7718,
+ ["Hdotaccent"]=7714,
+ ["Hdotbelow"]=7716,
+ ["Hmonospace"]=65320,
+ ["Hoarmenian"]=1344,
+ ["Horicoptic"]=1000,
+ ["Hzsquare"]=13200,
+ ["I"]=73,
+ ["IAcyrillic"]=1071,
+ ["IJ"]=306,
+ ["IUcyrillic"]=1070,
+ ["Iacute"]=205,
+ ["Ibreve"]=300,
+ ["Icaron"]=463,
+ ["Icircle"]=9406,
+ ["Icircumflex"]=206,
+ ["Icyrillic"]=1030,
+ ["Idblgrave"]=520,
+ ["Idieresis"]=207,
+ ["Idieresisacute"]=7726,
+ ["Idieresiscyrillic"]=1252,
+ ["Idot"]=304,
+ ["Idotaccent"]=304,
+ ["Idotbelow"]=7882,
+ ["Iebrevecyrillic"]=1238,
+ ["Iecyrillic"]=1045,
+ ["Ifraktur"]=8465,
+ ["Igrave"]=204,
+ ["Ihookabove"]=7880,
+ ["Iicyrillic"]=1048,
+ ["Iinvertedbreve"]=522,
+ ["Iishortcyrillic"]=1049,
+ ["Imacron"]=298,
+ ["Imacroncyrillic"]=1250,
+ ["Imonospace"]=65321,
+ ["Iniarmenian"]=1339,
+ ["Iocyrillic"]=1025,
+ ["Iogonek"]=302,
+ ["Iota"]=921,
+ ["Iotaafrican"]=406,
+ ["Iotadieresis"]=938,
+ ["Iotatonos"]=906,
+ ["Istroke"]=407,
+ ["Itilde"]=296,
+ ["Itildebelow"]=7724,
+ ["Izhitsacyrillic"]=1140,
+ ["Izhitsadblgravecyrillic"]=1142,
+ ["J"]=74,
+ ["Jaarmenian"]=1345,
+ ["Jcircle"]=9407,
+ ["Jcircumflex"]=308,
+ ["Jecyrillic"]=1032,
+ ["Jheharmenian"]=1355,
+ ["Jmonospace"]=65322,
+ ["K"]=75,
+ ["KBsquare"]=13189,
+ ["KKsquare"]=13261,
+ ["Kabashkircyrillic"]=1184,
+ ["Kacute"]=7728,
+ ["Kacyrillic"]=1050,
+ ["Kadescendercyrillic"]=1178,
+ ["Kahookcyrillic"]=1219,
+ ["Kappa"]=922,
+ ["Kastrokecyrillic"]=1182,
+ ["Kaverticalstrokecyrillic"]=1180,
+ ["Kcaron"]=488,
+ ["Kcedilla"]=310,
+ ["Kcircle"]=9408,
+ ["Kcommaaccent"]=310,
+ ["Kdotbelow"]=7730,
+ ["Keharmenian"]=1364,
+ ["Kenarmenian"]=1343,
+ ["Khacyrillic"]=1061,
+ ["Kheicoptic"]=998,
+ ["Khook"]=408,
+ ["Kjecyrillic"]=1036,
+ ["Klinebelow"]=7732,
+ ["Kmonospace"]=65323,
+ ["Koppacyrillic"]=1152,
+ ["Koppagreek"]=990,
+ ["Ksicyrillic"]=1134,
+ ["L"]=76,
+ ["LJ"]=455,
+ ["Lacute"]=313,
+ ["Lambda"]=923,
+ ["Lcaron"]=317,
+ ["Lcedilla"]=315,
+ ["Lcircle"]=9409,
+ ["Lcircumflexbelow"]=7740,
+ ["Lcommaaccent"]=315,
+ ["Ldot"]=319,
+ ["Ldotaccent"]=319,
+ ["Ldotbelow"]=7734,
+ ["Ldotbelowmacron"]=7736,
+ ["Liwnarmenian"]=1340,
+ ["Lj"]=456,
+ ["Ljecyrillic"]=1033,
+ ["Llinebelow"]=7738,
+ ["Lmonospace"]=65324,
+ ["Lslash"]=321,
+ ["M"]=77,
+ ["MBsquare"]=13190,
+ ["Macute"]=7742,
+ ["Mcircle"]=9410,
+ ["Mdotaccent"]=7744,
+ ["Mdotbelow"]=7746,
+ ["Menarmenian"]=1348,
+ ["Mmonospace"]=65325,
+ ["Mturned"]=412,
+ ["Mu"]=924,
+ ["N"]=78,
+ ["NJ"]=458,
+ ["Nacute"]=323,
+ ["Ncaron"]=327,
+ ["Ncedilla"]=325,
+ ["Ncircle"]=9411,
+ ["Ncircumflexbelow"]=7754,
+ ["Ncommaaccent"]=325,
+ ["Ndotaccent"]=7748,
+ ["Ndotbelow"]=7750,
+ ["Nhookleft"]=413,
+ ["Nineroman"]=8552,
+ ["Nj"]=459,
+ ["Njecyrillic"]=1034,
+ ["Nlinebelow"]=7752,
+ ["Nmonospace"]=65326,
+ ["Nowarmenian"]=1350,
+ ["Ntilde"]=209,
+ ["Nu"]=925,
+ ["O"]=79,
+ ["OE"]=338,
+ ["Oacute"]=211,
+ ["Obarredcyrillic"]=1256,
+ ["Obarreddieresiscyrillic"]=1258,
+ ["Obreve"]=334,
+ ["Ocaron"]=465,
+ ["Ocenteredtilde"]=415,
+ ["Ocircle"]=9412,
+ ["Ocircumflex"]=212,
+ ["Ocircumflexacute"]=7888,
+ ["Ocircumflexdotbelow"]=7896,
+ ["Ocircumflexgrave"]=7890,
+ ["Ocircumflexhookabove"]=7892,
+ ["Ocircumflextilde"]=7894,
+ ["Ocyrillic"]=1054,
+ ["Odblacute"]=336,
+ ["Odblgrave"]=524,
+ ["Odieresis"]=214,
+ ["Odieresiscyrillic"]=1254,
+ ["Odotbelow"]=7884,
+ ["Ograve"]=210,
+ ["Oharmenian"]=1365,
+ ["Ohm"]=8486,
+ ["Ohookabove"]=7886,
+ ["Ohorn"]=416,
+ ["Ohornacute"]=7898,
+ ["Ohorndotbelow"]=7906,
+ ["Ohorngrave"]=7900,
+ ["Ohornhookabove"]=7902,
+ ["Ohorntilde"]=7904,
+ ["Ohungarumlaut"]=336,
+ ["Oi"]=418,
+ ["Oinvertedbreve"]=526,
+ ["Omacron"]=332,
+ ["Omacronacute"]=7762,
+ ["Omacrongrave"]=7760,
+ ["Omega"]=8486,
+ ["Omegacyrillic"]=1120,
+ ["Omegagreek"]=937,
+ ["Omegaroundcyrillic"]=1146,
+ ["Omegatitlocyrillic"]=1148,
+ ["Omegatonos"]=911,
+ ["Omicron"]=927,
+ ["Omicrontonos"]=908,
+ ["Omonospace"]=65327,
+ ["Oneroman"]=8544,
+ ["Oogonek"]=490,
+ ["Oogonekmacron"]=492,
+ ["Oopen"]=390,
+ ["Oslash"]=216,
+ ["Oslashacute"]=510,
+ ["Ostrokeacute"]=510,
+ ["Otcyrillic"]=1150,
+ ["Otilde"]=213,
+ ["Otildeacute"]=7756,
+ ["Otildedieresis"]=7758,
+ ["P"]=80,
+ ["Pacute"]=7764,
+ ["Pcircle"]=9413,
+ ["Pdotaccent"]=7766,
+ ["Pecyrillic"]=1055,
+ ["Peharmenian"]=1354,
+ ["Pemiddlehookcyrillic"]=1190,
+ ["Phi"]=934,
+ ["Phook"]=420,
+ ["Pi"]=928,
+ ["Piwrarmenian"]=1363,
+ ["Pmonospace"]=65328,
+ ["Psi"]=936,
+ ["Psicyrillic"]=1136,
+ ["Q"]=81,
+ ["Qcircle"]=9414,
+ ["Qmonospace"]=65329,
+ ["R"]=82,
+ ["Raarmenian"]=1356,
+ ["Racute"]=340,
+ ["Rcaron"]=344,
+ ["Rcedilla"]=342,
+ ["Rcircle"]=9415,
+ ["Rcommaaccent"]=342,
+ ["Rdblgrave"]=528,
+ ["Rdotaccent"]=7768,
+ ["Rdotbelow"]=7770,
+ ["Rdotbelowmacron"]=7772,
+ ["Reharmenian"]=1360,
+ ["Rfraktur"]=8476,
+ ["Rho"]=929,
+ ["Rinvertedbreve"]=530,
+ ["Rlinebelow"]=7774,
+ ["Rmonospace"]=65330,
+ ["Rsmallinverted"]=641,
+ ["Rsmallinvertedsuperior"]=694,
+ ["S"]=83,
+ ["SF010000"]=9484,
+ ["SF020000"]=9492,
+ ["SF030000"]=9488,
+ ["SF040000"]=9496,
+ ["SF050000"]=9532,
+ ["SF060000"]=9516,
+ ["SF070000"]=9524,
+ ["SF080000"]=9500,
+ ["SF090000"]=9508,
+ ["SF10000"]=9484,
+ ["SF100000"]=9472,
+ ["SF110000"]=9474,
+ ["SF190000"]=9569,
+ ["SF20000"]=9492,
+ ["SF200000"]=9570,
+ ["SF210000"]=9558,
+ ["SF220000"]=9557,
+ ["SF230000"]=9571,
+ ["SF240000"]=9553,
+ ["SF250000"]=9559,
+ ["SF260000"]=9565,
+ ["SF270000"]=9564,
+ ["SF280000"]=9563,
+ ["SF30000"]=9488,
+ ["SF360000"]=9566,
+ ["SF370000"]=9567,
+ ["SF380000"]=9562,
+ ["SF390000"]=9556,
+ ["SF40000"]=9496,
+ ["SF400000"]=9577,
+ ["SF410000"]=9574,
+ ["SF420000"]=9568,
+ ["SF430000"]=9552,
+ ["SF440000"]=9580,
+ ["SF450000"]=9575,
+ ["SF460000"]=9576,
+ ["SF470000"]=9572,
+ ["SF480000"]=9573,
+ ["SF490000"]=9561,
+ ["SF50000"]=9532,
+ ["SF500000"]=9560,
+ ["SF510000"]=9554,
+ ["SF520000"]=9555,
+ ["SF530000"]=9579,
+ ["SF540000"]=9578,
+ ["SF60000"]=9516,
+ ["SF70000"]=9524,
+ ["SF80000"]=9500,
+ ["SF90000"]=9508,
+ ["Sacute"]=346,
+ ["Sacutedotaccent"]=7780,
+ ["Sampigreek"]=992,
+ ["Scaron"]=352,
+ ["Scarondotaccent"]=7782,
+ ["Scedilla"]=350,
+ ["Schwa"]=399,
+ ["Schwacyrillic"]=1240,
+ ["Schwadieresiscyrillic"]=1242,
+ ["Scircle"]=9416,
+ ["Scircumflex"]=348,
+ ["Scommaaccent"]=536,
+ ["Sdotaccent"]=7776,
+ ["Sdotbelow"]=7778,
+ ["Sdotbelowdotaccent"]=7784,
+ ["Seharmenian"]=1357,
+ ["Sevenroman"]=8550,
+ ["Shaarmenian"]=1351,
+ ["Shacyrillic"]=1064,
+ ["Shchacyrillic"]=1065,
+ ["Sheicoptic"]=994,
+ ["Shhacyrillic"]=1210,
+ ["Shimacoptic"]=1004,
+ ["Sigma"]=931,
+ ["Sixroman"]=8549,
+ ["Smonospace"]=65331,
+ ["Softsigncyrillic"]=1068,
+ ["Stigmagreek"]=986,
+ ["T"]=84,
+ ["Tau"]=932,
+ ["Tbar"]=358,
+ ["Tcaron"]=356,
+ ["Tcedilla"]=354,
+ ["Tcircle"]=9417,
+ ["Tcircumflexbelow"]=7792,
+ ["Tcommaaccent"]=354,
+ ["Tdotaccent"]=7786,
+ ["Tdotbelow"]=7788,
+ ["Tecyrillic"]=1058,
+ ["Tedescendercyrillic"]=1196,
+ ["Tenroman"]=8553,
+ ["Tetsecyrillic"]=1204,
+ ["Theta"]=920,
+ ["Thook"]=428,
+ ["Thorn"]=222,
+ ["Threeroman"]=8546,
+ ["Tiwnarmenian"]=1359,
+ ["Tlinebelow"]=7790,
+ ["Tmonospace"]=65332,
+ ["Toarmenian"]=1337,
+ ["Tonefive"]=444,
+ ["Tonesix"]=388,
+ ["Tonetwo"]=423,
+ ["Tretroflexhook"]=430,
+ ["Tsecyrillic"]=1062,
+ ["Tshecyrillic"]=1035,
+ ["Twelveroman"]=8555,
+ ["Tworoman"]=8545,
+ ["U"]=85,
+ ["Uacute"]=218,
+ ["Ubreve"]=364,
+ ["Ucaron"]=467,
+ ["Ucircle"]=9418,
+ ["Ucircumflex"]=219,
+ ["Ucircumflexbelow"]=7798,
+ ["Ucyrillic"]=1059,
+ ["Udblacute"]=368,
+ ["Udblgrave"]=532,
+ ["Udieresis"]=220,
+ ["Udieresisacute"]=471,
+ ["Udieresisbelow"]=7794,
+ ["Udieresiscaron"]=473,
+ ["Udieresiscyrillic"]=1264,
+ ["Udieresisgrave"]=475,
+ ["Udieresismacron"]=469,
+ ["Udotbelow"]=7908,
+ ["Ugrave"]=217,
+ ["Uhookabove"]=7910,
+ ["Uhorn"]=431,
+ ["Uhornacute"]=7912,
+ ["Uhorndotbelow"]=7920,
+ ["Uhorngrave"]=7914,
+ ["Uhornhookabove"]=7916,
+ ["Uhorntilde"]=7918,
+ ["Uhungarumlaut"]=368,
+ ["Uhungarumlautcyrillic"]=1266,
+ ["Uinvertedbreve"]=534,
+ ["Ukcyrillic"]=1144,
+ ["Umacron"]=362,
+ ["Umacroncyrillic"]=1262,
+ ["Umacrondieresis"]=7802,
+ ["Umonospace"]=65333,
+ ["Uogonek"]=370,
+ ["Upsilon"]=933,
+ ["Upsilon1"]=978,
+ ["Upsilonacutehooksymbolgreek"]=979,
+ ["Upsilonafrican"]=433,
+ ["Upsilondieresis"]=939,
+ ["Upsilondieresishooksymbolgreek"]=980,
+ ["Upsilonhooksymbol"]=978,
+ ["Upsilontonos"]=910,
+ ["Uring"]=366,
+ ["Ushortcyrillic"]=1038,
+ ["Ustraightcyrillic"]=1198,
+ ["Ustraightstrokecyrillic"]=1200,
+ ["Utilde"]=360,
+ ["Utildeacute"]=7800,
+ ["Utildebelow"]=7796,
+ ["V"]=86,
+ ["Vcircle"]=9419,
+ ["Vdotbelow"]=7806,
+ ["Vecyrillic"]=1042,
+ ["Vewarmenian"]=1358,
+ ["Vhook"]=434,
+ ["Vmonospace"]=65334,
+ ["Voarmenian"]=1352,
+ ["Vtilde"]=7804,
+ ["W"]=87,
+ ["Wacute"]=7810,
+ ["Wcircle"]=9420,
+ ["Wcircumflex"]=372,
+ ["Wdieresis"]=7812,
+ ["Wdotaccent"]=7814,
+ ["Wdotbelow"]=7816,
+ ["Wgrave"]=7808,
+ ["Wmonospace"]=65335,
+ ["X"]=88,
+ ["Xcircle"]=9421,
+ ["Xdieresis"]=7820,
+ ["Xdotaccent"]=7818,
+ ["Xeharmenian"]=1341,
+ ["Xi"]=926,
+ ["Xmonospace"]=65336,
+ ["Y"]=89,
+ ["Yacute"]=221,
+ ["Yatcyrillic"]=1122,
+ ["Ycircle"]=9422,
+ ["Ycircumflex"]=374,
+ ["Ydieresis"]=376,
+ ["Ydotaccent"]=7822,
+ ["Ydotbelow"]=7924,
+ ["Yericyrillic"]=1067,
+ ["Yerudieresiscyrillic"]=1272,
+ ["Ygrave"]=7922,
+ ["Yhook"]=435,
+ ["Yhookabove"]=7926,
+ ["Yiarmenian"]=1349,
+ ["Yicyrillic"]=1031,
+ ["Yiwnarmenian"]=1362,
+ ["Ymonospace"]=65337,
+ ["Ytilde"]=7928,
+ ["Yusbigcyrillic"]=1130,
+ ["Yusbigiotifiedcyrillic"]=1132,
+ ["Yuslittlecyrillic"]=1126,
+ ["Yuslittleiotifiedcyrillic"]=1128,
+ ["Z"]=90,
+ ["Zaarmenian"]=1334,
+ ["Zacute"]=377,
+ ["Zcaron"]=381,
+ ["Zcircle"]=9423,
+ ["Zcircumflex"]=7824,
+ ["Zdot"]=379,
+ ["Zdotaccent"]=379,
+ ["Zdotbelow"]=7826,
+ ["Zecyrillic"]=1047,
+ ["Zedescendercyrillic"]=1176,
+ ["Zedieresiscyrillic"]=1246,
+ ["Zeta"]=918,
+ ["Zhearmenian"]=1338,
+ ["Zhebrevecyrillic"]=1217,
+ ["Zhecyrillic"]=1046,
+ ["Zhedescendercyrillic"]=1174,
+ ["Zhedieresiscyrillic"]=1244,
+ ["Zlinebelow"]=7828,
+ ["Zmonospace"]=65338,
+ ["Zstroke"]=437,
+ ["a"]=97,
+ ["aabengali"]=2438,
+ ["aacute"]=225,
+ ["aadeva"]=2310,
+ ["aagujarati"]=2694,
+ ["aagurmukhi"]=2566,
+ ["aamatragurmukhi"]=2622,
+ ["aarusquare"]=13059,
+ ["aavowelsignbengali"]=2494,
+ ["aavowelsigndeva"]=2366,
+ ["aavowelsigngujarati"]=2750,
+ ["abbreviationmarkarmenian"]=1375,
+ ["abbreviationsigndeva"]=2416,
+ ["abengali"]=2437,
+ ["abopomofo"]=12570,
+ ["abreve"]=259,
+ ["abreveacute"]=7855,
+ ["abrevecyrillic"]=1233,
+ ["abrevedotbelow"]=7863,
+ ["abrevegrave"]=7857,
+ ["abrevehookabove"]=7859,
+ ["abrevetilde"]=7861,
+ ["acaron"]=462,
+ ["acircle"]=9424,
+ ["acircumflex"]=226,
+ ["acircumflexacute"]=7845,
+ ["acircumflexdotbelow"]=7853,
+ ["acircumflexgrave"]=7847,
+ ["acircumflexhookabove"]=7849,
+ ["acircumflextilde"]=7851,
+ ["acute"]=180,
+ ["acutebelowcmb"]=791,
+ ["acutecmb"]=769,
+ ["acutecomb"]=769,
+ ["acutedeva"]=2388,
+ ["acutelowmod"]=719,
+ ["acutetonecmb"]=833,
+ ["acyrillic"]=1072,
+ ["adblgrave"]=513,
+ ["addakgurmukhi"]=2673,
+ ["adeva"]=2309,
+ ["adieresis"]=228,
+ ["adieresiscyrillic"]=1235,
+ ["adieresismacron"]=479,
+ ["adotbelow"]=7841,
+ ["adotmacron"]=481,
+ ["ae"]=230,
+ ["aeacute"]=509,
+ ["aekorean"]=12624,
+ ["aemacron"]=483,
+ ["afii00208"]=8213,
+ ["afii08941"]=8356,
+ ["afii10017"]=1040,
+ ["afii10018"]=1041,
+ ["afii10019"]=1042,
+ ["afii10020"]=1043,
+ ["afii10021"]=1044,
+ ["afii10022"]=1045,
+ ["afii10023"]=1025,
+ ["afii10024"]=1046,
+ ["afii10025"]=1047,
+ ["afii10026"]=1048,
+ ["afii10027"]=1049,
+ ["afii10028"]=1050,
+ ["afii10029"]=1051,
+ ["afii10030"]=1052,
+ ["afii10031"]=1053,
+ ["afii10032"]=1054,
+ ["afii10033"]=1055,
+ ["afii10034"]=1056,
+ ["afii10035"]=1057,
+ ["afii10036"]=1058,
+ ["afii10037"]=1059,
+ ["afii10038"]=1060,
+ ["afii10039"]=1061,
+ ["afii10040"]=1062,
+ ["afii10041"]=1063,
+ ["afii10042"]=1064,
+ ["afii10043"]=1065,
+ ["afii10044"]=1066,
+ ["afii10045"]=1067,
+ ["afii10046"]=1068,
+ ["afii10047"]=1069,
+ ["afii10048"]=1070,
+ ["afii10049"]=1071,
+ ["afii10050"]=1168,
+ ["afii10051"]=1026,
+ ["afii10052"]=1027,
+ ["afii10053"]=1028,
+ ["afii10054"]=1029,
+ ["afii10055"]=1030,
+ ["afii10056"]=1031,
+ ["afii10057"]=1032,
+ ["afii10058"]=1033,
+ ["afii10059"]=1034,
+ ["afii10060"]=1035,
+ ["afii10061"]=1036,
+ ["afii10062"]=1038,
+ ["afii10065"]=1072,
+ ["afii10066"]=1073,
+ ["afii10067"]=1074,
+ ["afii10068"]=1075,
+ ["afii10069"]=1076,
+ ["afii10070"]=1077,
+ ["afii10071"]=1105,
+ ["afii10072"]=1078,
+ ["afii10073"]=1079,
+ ["afii10074"]=1080,
+ ["afii10075"]=1081,
+ ["afii10076"]=1082,
+ ["afii10077"]=1083,
+ ["afii10078"]=1084,
+ ["afii10079"]=1085,
+ ["afii10080"]=1086,
+ ["afii10081"]=1087,
+ ["afii10082"]=1088,
+ ["afii10083"]=1089,
+ ["afii10084"]=1090,
+ ["afii10085"]=1091,
+ ["afii10086"]=1092,
+ ["afii10087"]=1093,
+ ["afii10088"]=1094,
+ ["afii10089"]=1095,
+ ["afii10090"]=1096,
+ ["afii10091"]=1097,
+ ["afii10092"]=1098,
+ ["afii10093"]=1099,
+ ["afii10094"]=1100,
+ ["afii10095"]=1101,
+ ["afii10096"]=1102,
+ ["afii10097"]=1103,
+ ["afii10098"]=1169,
+ ["afii10099"]=1106,
+ ["afii10100"]=1107,
+ ["afii10101"]=1108,
+ ["afii10102"]=1109,
+ ["afii10103"]=1110,
+ ["afii10104"]=1111,
+ ["afii10105"]=1112,
+ ["afii10106"]=1113,
+ ["afii10107"]=1114,
+ ["afii10108"]=1115,
+ ["afii10109"]=1116,
+ ["afii10110"]=1118,
+ ["afii10145"]=1039,
+ ["afii10146"]=1122,
+ ["afii10147"]=1138,
+ ["afii10148"]=1140,
+ ["afii10193"]=1119,
+ ["afii10194"]=1123,
+ ["afii10195"]=1139,
+ ["afii10196"]=1141,
+ ["afii10846"]=1241,
+ ["afii208"]=8213,
+ ["afii299"]=8206,
+ ["afii300"]=8207,
+ ["afii301"]=8205,
+ ["afii57381"]=1642,
+ ["afii57388"]=1548,
+ ["afii57392"]=1632,
+ ["afii57393"]=1633,
+ ["afii57394"]=1634,
+ ["afii57395"]=1635,
+ ["afii57396"]=1636,
+ ["afii57397"]=1637,
+ ["afii57398"]=1638,
+ ["afii57399"]=1639,
+ ["afii57400"]=1640,
+ ["afii57401"]=1641,
+ ["afii57403"]=1563,
+ ["afii57407"]=1567,
+ ["afii57409"]=1569,
+ ["afii57410"]=1570,
+ ["afii57411"]=1571,
+ ["afii57412"]=1572,
+ ["afii57413"]=1573,
+ ["afii57414"]=1574,
+ ["afii57415"]=1575,
+ ["afii57416"]=1576,
+ ["afii57417"]=1577,
+ ["afii57418"]=1578,
+ ["afii57419"]=1579,
+ ["afii57420"]=1580,
+ ["afii57421"]=1581,
+ ["afii57422"]=1582,
+ ["afii57423"]=1583,
+ ["afii57424"]=1584,
+ ["afii57425"]=1585,
+ ["afii57426"]=1586,
+ ["afii57427"]=1587,
+ ["afii57428"]=1588,
+ ["afii57429"]=1589,
+ ["afii57430"]=1590,
+ ["afii57431"]=1591,
+ ["afii57432"]=1592,
+ ["afii57433"]=1593,
+ ["afii57434"]=1594,
+ ["afii57440"]=1600,
+ ["afii57441"]=1601,
+ ["afii57442"]=1602,
+ ["afii57443"]=1603,
+ ["afii57444"]=1604,
+ ["afii57445"]=1605,
+ ["afii57446"]=1606,
+ ["afii57448"]=1608,
+ ["afii57449"]=1609,
+ ["afii57450"]=1610,
+ ["afii57451"]=1611,
+ ["afii57452"]=1612,
+ ["afii57453"]=1613,
+ ["afii57454"]=1614,
+ ["afii57455"]=1615,
+ ["afii57456"]=1616,
+ ["afii57457"]=1617,
+ ["afii57458"]=1618,
+ ["afii57470"]=1607,
+ ["afii57505"]=1700,
+ ["afii57506"]=1662,
+ ["afii57507"]=1670,
+ ["afii57508"]=1688,
+ ["afii57509"]=1711,
+ ["afii57511"]=1657,
+ ["afii57512"]=1672,
+ ["afii57513"]=1681,
+ ["afii57514"]=1722,
+ ["afii57519"]=1746,
+ ["afii57534"]=1749,
+ ["afii57636"]=8362,
+ ["afii57645"]=1470,
+ ["afii57658"]=1475,
+ ["afii57664"]=1488,
+ ["afii57665"]=1489,
+ ["afii57666"]=1490,
+ ["afii57667"]=1491,
+ ["afii57668"]=1492,
+ ["afii57669"]=1493,
+ ["afii57670"]=1494,
+ ["afii57671"]=1495,
+ ["afii57672"]=1496,
+ ["afii57673"]=1497,
+ ["afii57674"]=1498,
+ ["afii57675"]=1499,
+ ["afii57676"]=1500,
+ ["afii57677"]=1501,
+ ["afii57678"]=1502,
+ ["afii57679"]=1503,
+ ["afii57680"]=1504,
+ ["afii57681"]=1505,
+ ["afii57682"]=1506,
+ ["afii57683"]=1507,
+ ["afii57684"]=1508,
+ ["afii57685"]=1509,
+ ["afii57686"]=1510,
+ ["afii57687"]=1511,
+ ["afii57688"]=1512,
+ ["afii57689"]=1513,
+ ["afii57690"]=1514,
+ ["afii57694"]=64298,
+ ["afii57695"]=64299,
+ ["afii57700"]=64331,
+ ["afii57705"]=64287,
+ ["afii57716"]=1520,
+ ["afii57717"]=1521,
+ ["afii57718"]=1522,
+ ["afii57723"]=64309,
+ ["afii57793"]=1460,
+ ["afii57794"]=1461,
+ ["afii57795"]=1462,
+ ["afii57796"]=1467,
+ ["afii57797"]=1464,
+ ["afii57798"]=1463,
+ ["afii57799"]=1456,
+ ["afii57800"]=1458,
+ ["afii57801"]=1457,
+ ["afii57802"]=1459,
+ ["afii57803"]=1474,
+ ["afii57804"]=1473,
+ ["afii57806"]=1465,
+ ["afii57807"]=1468,
+ ["afii57839"]=1469,
+ ["afii57841"]=1471,
+ ["afii57842"]=1472,
+ ["afii57929"]=700,
+ ["afii61248"]=8453,
+ ["afii61289"]=8467,
+ ["afii61352"]=8470,
+ ["afii61573"]=8236,
+ ["afii61574"]=8237,
+ ["afii61575"]=8238,
+ ["afii61664"]=8204,
+ ["afii63167"]=1645,
+ ["afii64937"]=701,
+ ["agrave"]=224,
+ ["agujarati"]=2693,
+ ["agurmukhi"]=2565,
+ ["ahiragana"]=12354,
+ ["ahookabove"]=7843,
+ ["aibengali"]=2448,
+ ["aibopomofo"]=12574,
+ ["aideva"]=2320,
+ ["aiecyrillic"]=1237,
+ ["aigujarati"]=2704,
+ ["aigurmukhi"]=2576,
+ ["aimatragurmukhi"]=2632,
+ ["ainarabic"]=1593,
+ ["ainfinalarabic"]=65226,
+ ["aininitialarabic"]=65227,
+ ["ainmedialarabic"]=65228,
+ ["ainvertedbreve"]=515,
+ ["aivowelsignbengali"]=2504,
+ ["aivowelsigndeva"]=2376,
+ ["aivowelsigngujarati"]=2760,
+ ["akatakana"]=12450,
+ ["akatakanahalfwidth"]=65393,
+ ["akorean"]=12623,
+ ["alef"]=1488,
+ ["alefarabic"]=1575,
+ ["alefdageshhebrew"]=64304,
+ ["aleffinalarabic"]=65166,
+ ["alefhamzaabovearabic"]=1571,
+ ["alefhamzaabovefinalarabic"]=65156,
+ ["alefhamzabelowarabic"]=1573,
+ ["alefhamzabelowfinalarabic"]=65160,
+ ["alefhebrew"]=1488,
+ ["aleflamedhebrew"]=64335,
+ ["alefmaddaabovearabic"]=1570,
+ ["alefmaddaabovefinalarabic"]=65154,
+ ["alefmaksuraarabic"]=1609,
+ ["alefmaksurafinalarabic"]=65264,
+ ["alefmaksurainitialarabic"]=65267,
+ ["alefmaksuramedialarabic"]=65268,
+ ["alefpatahhebrew"]=64302,
+ ["alefqamatshebrew"]=64303,
+ ["aleph"]=8501,
+ ["allequal"]=8780,
+ ["alpha"]=945,
+ ["alphatonos"]=940,
+ ["amacron"]=257,
+ ["amonospace"]=65345,
+ ["ampersand"]=38,
+ ["ampersandmonospace"]=65286,
+ ["amsquare"]=13250,
+ ["anbopomofo"]=12578,
+ ["angbopomofo"]=12580,
+ ["angkhankhuthai"]=3674,
+ ["angle"]=8736,
+ ["anglebracketleft"]=12296,
+ ["anglebracketleftvertical"]=65087,
+ ["anglebracketright"]=12297,
+ ["anglebracketrightvertical"]=65088,
+ ["angleleft"]=9001,
+ ["angleright"]=9002,
+ ["angstrom"]=8491,
+ ["anoteleia"]=903,
+ ["anudattadeva"]=2386,
+ ["anusvarabengali"]=2434,
+ ["anusvaradeva"]=2306,
+ ["anusvaragujarati"]=2690,
+ ["aogonek"]=261,
+ ["apaatosquare"]=13056,
+ ["aparen"]=9372,
+ ["apostrophearmenian"]=1370,
+ ["apostrophemod"]=700,
+ ["apple"]=63743,
+ ["approaches"]=8784,
+ ["approxequal"]=8776,
+ ["approxequalorimage"]=8786,
+ ["approximatelyequal"]=8773,
+ ["araeaekorean"]=12686,
+ ["araeakorean"]=12685,
+ ["arc"]=8978,
+ ["arighthalfring"]=7834,
+ ["aring"]=229,
+ ["aringacute"]=507,
+ ["aringbelow"]=7681,
+ ["arrowboth"]=8596,
+ ["arrowdashdown"]=8675,
+ ["arrowdashleft"]=8672,
+ ["arrowdashright"]=8674,
+ ["arrowdashup"]=8673,
+ ["arrowdblboth"]=8660,
+ ["arrowdbldown"]=8659,
+ ["arrowdblleft"]=8656,
+ ["arrowdblright"]=8658,
+ ["arrowdblup"]=8657,
+ ["arrowdown"]=8595,
+ ["arrowdownleft"]=8601,
+ ["arrowdownright"]=8600,
+ ["arrowdownwhite"]=8681,
+ ["arrowheaddownmod"]=709,
+ ["arrowheadleftmod"]=706,
+ ["arrowheadrightmod"]=707,
+ ["arrowheadupmod"]=708,
+ ["arrowleft"]=8592,
+ ["arrowleftdbl"]=8656,
+ ["arrowleftdblstroke"]=8653,
+ ["arrowleftoverright"]=8646,
+ ["arrowleftwhite"]=8678,
+ ["arrowright"]=8594,
+ ["arrowrightdblstroke"]=8655,
+ ["arrowrightheavy"]=10142,
+ ["arrowrightoverleft"]=8644,
+ ["arrowrightwhite"]=8680,
+ ["arrowtableft"]=8676,
+ ["arrowtabright"]=8677,
+ ["arrowup"]=8593,
+ ["arrowupdn"]=8597,
+ ["arrowupdnbse"]=8616,
+ ["arrowupdownbase"]=8616,
+ ["arrowupleft"]=8598,
+ ["arrowupleftofdown"]=8645,
+ ["arrowupright"]=8599,
+ ["arrowupwhite"]=8679,
+ ["asciicircum"]=94,
+ ["asciicircummonospace"]=65342,
+ ["asciitilde"]=126,
+ ["asciitildemonospace"]=65374,
+ ["ascript"]=593,
+ ["ascriptturned"]=594,
+ ["asmallhiragana"]=12353,
+ ["asmallkatakana"]=12449,
+ ["asmallkatakanahalfwidth"]=65383,
+ ["asterisk"]=42,
+ ["asteriskaltonearabic"]=1645,
+ ["asteriskarabic"]=1645,
+ ["asteriskmath"]=8727,
+ ["asteriskmonospace"]=65290,
+ ["asterisksmall"]=65121,
+ ["asterism"]=8258,
+ ["asymptoticallyequal"]=8771,
+ ["at"]=64,
+ ["atilde"]=227,
+ ["atmonospace"]=65312,
+ ["atsmall"]=65131,
+ ["aturned"]=592,
+ ["aubengali"]=2452,
+ ["aubopomofo"]=12576,
+ ["audeva"]=2324,
+ ["augujarati"]=2708,
+ ["augurmukhi"]=2580,
+ ["aulengthmarkbengali"]=2519,
+ ["aumatragurmukhi"]=2636,
+ ["auvowelsignbengali"]=2508,
+ ["auvowelsigndeva"]=2380,
+ ["auvowelsigngujarati"]=2764,
+ ["avagrahadeva"]=2365,
+ ["aybarmenian"]=1377,
+ ["ayin"]=1506,
+ ["ayinaltonehebrew"]=64288,
+ ["ayinhebrew"]=1506,
+ ["b"]=98,
+ ["babengali"]=2476,
+ ["backslash"]=92,
+ ["backslashmonospace"]=65340,
+ ["badeva"]=2348,
+ ["bagujarati"]=2732,
+ ["bagurmukhi"]=2604,
+ ["bahiragana"]=12400,
+ ["bahtthai"]=3647,
+ ["bakatakana"]=12496,
+ ["bar"]=124,
+ ["barmonospace"]=65372,
+ ["bbopomofo"]=12549,
+ ["bcircle"]=9425,
+ ["bdotaccent"]=7683,
+ ["bdotbelow"]=7685,
+ ["beamedsixteenthnotes"]=9836,
+ ["because"]=8757,
+ ["becyrillic"]=1073,
+ ["beharabic"]=1576,
+ ["behfinalarabic"]=65168,
+ ["behinitialarabic"]=65169,
+ ["behiragana"]=12409,
+ ["behmedialarabic"]=65170,
+ ["behmeeminitialarabic"]=64671,
+ ["behmeemisolatedarabic"]=64520,
+ ["behnoonfinalarabic"]=64621,
+ ["bekatakana"]=12505,
+ ["benarmenian"]=1378,
+ ["bet"]=1489,
+ ["beta"]=946,
+ ["betasymbolgreek"]=976,
+ ["betdagesh"]=64305,
+ ["betdageshhebrew"]=64305,
+ ["bethebrew"]=1489,
+ ["betrafehebrew"]=64332,
+ ["bhabengali"]=2477,
+ ["bhadeva"]=2349,
+ ["bhagujarati"]=2733,
+ ["bhagurmukhi"]=2605,
+ ["bhook"]=595,
+ ["bihiragana"]=12403,
+ ["bikatakana"]=12499,
+ ["bilabialclick"]=664,
+ ["bindigurmukhi"]=2562,
+ ["birusquare"]=13105,
+ ["blackcircle"]=9679,
+ ["blackdiamond"]=9670,
+ ["blackdownpointingtriangle"]=9660,
+ ["blackleftpointingpointer"]=9668,
+ ["blackleftpointingtriangle"]=9664,
+ ["blacklenticularbracketleft"]=12304,
+ ["blacklenticularbracketleftvertical"]=65083,
+ ["blacklenticularbracketright"]=12305,
+ ["blacklenticularbracketrightvertical"]=65084,
+ ["blacklowerlefttriangle"]=9699,
+ ["blacklowerrighttriangle"]=9698,
+ ["blackrectangle"]=9644,
+ ["blackrightpointingpointer"]=9658,
+ ["blackrightpointingtriangle"]=9654,
+ ["blacksmallsquare"]=9642,
+ ["blacksmilingface"]=9787,
+ ["blacksquare"]=9632,
+ ["blackstar"]=9733,
+ ["blackupperlefttriangle"]=9700,
+ ["blackupperrighttriangle"]=9701,
+ ["blackuppointingsmalltriangle"]=9652,
+ ["blackuppointingtriangle"]=9650,
+ ["blank"]=9251,
+ ["blinebelow"]=7687,
+ ["block"]=9608,
+ ["bmonospace"]=65346,
+ ["bobaimaithai"]=3610,
+ ["bohiragana"]=12412,
+ ["bokatakana"]=12508,
+ ["bparen"]=9373,
+ ["bqsquare"]=13251,
+ ["braceleft"]=123,
+ ["braceleftmonospace"]=65371,
+ ["braceleftsmall"]=65115,
+ ["braceleftvertical"]=65079,
+ ["braceright"]=125,
+ ["bracerightmonospace"]=65373,
+ ["bracerightsmall"]=65116,
+ ["bracerightvertical"]=65080,
+ ["bracketleft"]=91,
+ ["bracketleftmonospace"]=65339,
+ ["bracketright"]=93,
+ ["bracketrightmonospace"]=65341,
+ ["breve"]=728,
+ ["brevebelowcmb"]=814,
+ ["brevecmb"]=774,
+ ["breveinvertedbelowcmb"]=815,
+ ["breveinvertedcmb"]=785,
+ ["breveinverteddoublecmb"]=865,
+ ["bridgebelowcmb"]=810,
+ ["bridgeinvertedbelowcmb"]=826,
+ ["brokenbar"]=166,
+ ["bstroke"]=384,
+ ["btopbar"]=387,
+ ["buhiragana"]=12406,
+ ["bukatakana"]=12502,
+ ["bullet"]=8226,
+ ["bulletinverse"]=9688,
+ ["bulletoperator"]=8729,
+ ["bullseye"]=9678,
+ ["c"]=99,
+ ["caarmenian"]=1390,
+ ["cabengali"]=2458,
+ ["cacute"]=263,
+ ["cadeva"]=2330,
+ ["cagujarati"]=2714,
+ ["cagurmukhi"]=2586,
+ ["calsquare"]=13192,
+ ["candrabindubengali"]=2433,
+ ["candrabinducmb"]=784,
+ ["candrabindudeva"]=2305,
+ ["candrabindugujarati"]=2689,
+ ["capslock"]=8682,
+ ["careof"]=8453,
+ ["caron"]=711,
+ ["caronbelowcmb"]=812,
+ ["caroncmb"]=780,
+ ["carriagereturn"]=8629,
+ ["cbopomofo"]=12568,
+ ["ccaron"]=269,
+ ["ccedilla"]=231,
+ ["ccedillaacute"]=7689,
+ ["ccircle"]=9426,
+ ["ccircumflex"]=265,
+ ["ccurl"]=597,
+ ["cdot"]=267,
+ ["cdotaccent"]=267,
+ ["cdsquare"]=13253,
+ ["cedilla"]=184,
+ ["cedillacmb"]=807,
+ ["cent"]=162,
+ ["centigrade"]=8451,
+ ["centmonospace"]=65504,
+ ["chaarmenian"]=1401,
+ ["chabengali"]=2459,
+ ["chadeva"]=2331,
+ ["chagujarati"]=2715,
+ ["chagurmukhi"]=2587,
+ ["chbopomofo"]=12564,
+ ["cheabkhasiancyrillic"]=1213,
+ ["checkmark"]=10003,
+ ["checyrillic"]=1095,
+ ["chedescenderabkhasiancyrillic"]=1215,
+ ["chedescendercyrillic"]=1207,
+ ["chedieresiscyrillic"]=1269,
+ ["cheharmenian"]=1395,
+ ["chekhakassiancyrillic"]=1228,
+ ["cheverticalstrokecyrillic"]=1209,
+ ["chi"]=967,
+ ["chieuchacirclekorean"]=12919,
+ ["chieuchaparenkorean"]=12823,
+ ["chieuchcirclekorean"]=12905,
+ ["chieuchkorean"]=12618,
+ ["chieuchparenkorean"]=12809,
+ ["chochangthai"]=3594,
+ ["chochanthai"]=3592,
+ ["chochingthai"]=3593,
+ ["chochoethai"]=3596,
+ ["chook"]=392,
+ ["cieucacirclekorean"]=12918,
+ ["cieucaparenkorean"]=12822,
+ ["cieuccirclekorean"]=12904,
+ ["cieuckorean"]=12616,
+ ["cieucparenkorean"]=12808,
+ ["cieucuparenkorean"]=12828,
+ ["circle"]=9675,
+ ["circlemultiply"]=8855,
+ ["circleot"]=8857,
+ ["circleplus"]=8853,
+ ["circlepostalmark"]=12342,
+ ["circlewithlefthalfblack"]=9680,
+ ["circlewithrighthalfblack"]=9681,
+ ["circumflex"]=710,
+ ["circumflexbelowcmb"]=813,
+ ["circumflexcmb"]=770,
+ ["clear"]=8999,
+ ["clickalveolar"]=450,
+ ["clickdental"]=448,
+ ["clicklateral"]=449,
+ ["clickretroflex"]=451,
+ ["club"]=9827,
+ ["clubsuitblack"]=9827,
+ ["clubsuitwhite"]=9831,
+ ["cmcubedsquare"]=13220,
+ ["cmonospace"]=65347,
+ ["cmsquaredsquare"]=13216,
+ ["coarmenian"]=1409,
+ ["colon"]=58,
+ ["colonmonetary"]=8353,
+ ["colonmonospace"]=65306,
+ ["colonsign"]=8353,
+ ["colonsmall"]=65109,
+ ["colontriangularhalfmod"]=721,
+ ["colontriangularmod"]=720,
+ ["comma"]=44,
+ ["commaabovecmb"]=787,
+ ["commaaboverightcmb"]=789,
+ ["commaarabic"]=1548,
+ ["commaarmenian"]=1373,
+ ["commamonospace"]=65292,
+ ["commareversedabovecmb"]=788,
+ ["commareversedmod"]=701,
+ ["commasmall"]=65104,
+ ["commaturnedabovecmb"]=786,
+ ["commaturnedmod"]=699,
+ ["compass"]=9788,
+ ["congruent"]=8773,
+ ["contourintegral"]=8750,
+ ["control"]=8963,
+ ["controlACK"]=6,
+ ["controlBEL"]=7,
+ ["controlBS"]=8,
+ ["controlCAN"]=24,
+ ["controlCR"]=13,
+ ["controlDC1"]=17,
+ ["controlDC2"]=18,
+ ["controlDC3"]=19,
+ ["controlDC4"]=20,
+ ["controlDEL"]=127,
+ ["controlDLE"]=16,
+ ["controlEM"]=25,
+ ["controlENQ"]=5,
+ ["controlEOT"]=4,
+ ["controlESC"]=27,
+ ["controlETB"]=23,
+ ["controlETX"]=3,
+ ["controlFF"]=12,
+ ["controlFS"]=28,
+ ["controlGS"]=29,
+ ["controlHT"]=9,
+ ["controlLF"]=10,
+ ["controlNAK"]=21,
+ ["controlRS"]=30,
+ ["controlSI"]=15,
+ ["controlSO"]=14,
+ ["controlSOT"]=2,
+ ["controlSTX"]=1,
+ ["controlSUB"]=26,
+ ["controlSYN"]=22,
+ ["controlUS"]=31,
+ ["controlVT"]=11,
+ ["copyright"]=169,
+ ["cornerbracketleft"]=12300,
+ ["cornerbracketlefthalfwidth"]=65378,
+ ["cornerbracketleftvertical"]=65089,
+ ["cornerbracketright"]=12301,
+ ["cornerbracketrighthalfwidth"]=65379,
+ ["cornerbracketrightvertical"]=65090,
+ ["corporationsquare"]=13183,
+ ["cosquare"]=13255,
+ ["coverkgsquare"]=13254,
+ ["cparen"]=9374,
+ ["cruzeiro"]=8354,
+ ["cstretched"]=663,
+ ["curlyand"]=8911,
+ ["curlyor"]=8910,
+ ["currency"]=164,
+ ["d"]=100,
+ ["daarmenian"]=1380,
+ ["dabengali"]=2470,
+ ["dadarabic"]=1590,
+ ["dadeva"]=2342,
+ ["dadfinalarabic"]=65214,
+ ["dadinitialarabic"]=65215,
+ ["dadmedialarabic"]=65216,
+ ["dagesh"]=1468,
+ ["dageshhebrew"]=1468,
+ ["dagger"]=8224,
+ ["daggerdbl"]=8225,
+ ["dagujarati"]=2726,
+ ["dagurmukhi"]=2598,
+ ["dahiragana"]=12384,
+ ["dakatakana"]=12480,
+ ["dalarabic"]=1583,
+ ["dalet"]=1491,
+ ["daletdagesh"]=64307,
+ ["daletdageshhebrew"]=64307,
+ ["dalethatafpatah"]=1491,
+ ["dalethatafpatahhebrew"]=1491,
+ ["dalethatafsegol"]=1491,
+ ["dalethatafsegolhebrew"]=1491,
+ ["dalethebrew"]=1491,
+ ["dalethiriq"]=1491,
+ ["dalethiriqhebrew"]=1491,
+ ["daletholam"]=1491,
+ ["daletholamhebrew"]=1491,
+ ["daletpatah"]=1491,
+ ["daletpatahhebrew"]=1491,
+ ["daletqamats"]=1491,
+ ["daletqamatshebrew"]=1491,
+ ["daletqubuts"]=1491,
+ ["daletqubutshebrew"]=1491,
+ ["daletsegol"]=1491,
+ ["daletsegolhebrew"]=1491,
+ ["daletsheva"]=1491,
+ ["daletshevahebrew"]=1491,
+ ["dalettsere"]=1491,
+ ["dalettserehebrew"]=1491,
+ ["dalfinalarabic"]=65194,
+ ["dammaarabic"]=1615,
+ ["dammalowarabic"]=1615,
+ ["dammatanaltonearabic"]=1612,
+ ["dammatanarabic"]=1612,
+ ["danda"]=2404,
+ ["dargahebrew"]=1447,
+ ["dargalefthebrew"]=1447,
+ ["dasiapneumatacyrilliccmb"]=1157,
+ ["dblanglebracketleft"]=12298,
+ ["dblanglebracketleftvertical"]=65085,
+ ["dblanglebracketright"]=12299,
+ ["dblanglebracketrightvertical"]=65086,
+ ["dblarchinvertedbelowcmb"]=811,
+ ["dblarrowleft"]=8660,
+ ["dblarrowright"]=8658,
+ ["dbldanda"]=2405,
+ ["dblgravecmb"]=783,
+ ["dblintegral"]=8748,
+ ["dbllowline"]=8215,
+ ["dbllowlinecmb"]=819,
+ ["dbloverlinecmb"]=831,
+ ["dblprimemod"]=698,
+ ["dblverticalbar"]=8214,
+ ["dblverticallineabovecmb"]=782,
+ ["dbopomofo"]=12553,
+ ["dbsquare"]=13256,
+ ["dcaron"]=271,
+ ["dcedilla"]=7697,
+ ["dcircle"]=9427,
+ ["dcircumflexbelow"]=7699,
+ ["dcroat"]=273,
+ ["ddabengali"]=2465,
+ ["ddadeva"]=2337,
+ ["ddagujarati"]=2721,
+ ["ddagurmukhi"]=2593,
+ ["ddalarabic"]=1672,
+ ["ddalfinalarabic"]=64393,
+ ["dddhadeva"]=2396,
+ ["ddhabengali"]=2466,
+ ["ddhadeva"]=2338,
+ ["ddhagujarati"]=2722,
+ ["ddhagurmukhi"]=2594,
+ ["ddotaccent"]=7691,
+ ["ddotbelow"]=7693,
+ ["decimalseparatorarabic"]=1643,
+ ["decimalseparatorpersian"]=1643,
+ ["decyrillic"]=1076,
+ ["degree"]=176,
+ ["dehihebrew"]=1453,
+ ["dehiragana"]=12391,
+ ["deicoptic"]=1007,
+ ["dekatakana"]=12487,
+ ["deleteleft"]=9003,
+ ["deleteright"]=8998,
+ ["delta"]=948,
+ ["deltaturned"]=397,
+ ["denominatorminusonenumeratorbengali"]=2552,
+ ["dezh"]=676,
+ ["dhabengali"]=2471,
+ ["dhadeva"]=2343,
+ ["dhagujarati"]=2727,
+ ["dhagurmukhi"]=2599,
+ ["dhook"]=599,
+ ["dialytikatonos"]=901,
+ ["dialytikatonoscmb"]=836,
+ ["diamond"]=9830,
+ ["diamondsuitwhite"]=9826,
+ ["dieresis"]=168,
+ ["dieresisbelowcmb"]=804,
+ ["dieresiscmb"]=776,
+ ["dieresistonos"]=901,
+ ["dihiragana"]=12386,
+ ["dikatakana"]=12482,
+ ["dittomark"]=12291,
+ ["divide"]=247,
+ ["divides"]=8739,
+ ["divisionslash"]=8725,
+ ["djecyrillic"]=1106,
+ ["dkshade"]=9619,
+ ["dlinebelow"]=7695,
+ ["dlsquare"]=13207,
+ ["dmacron"]=273,
+ ["dmonospace"]=65348,
+ ["dnblock"]=9604,
+ ["dochadathai"]=3598,
+ ["dodekthai"]=3604,
+ ["dohiragana"]=12393,
+ ["dokatakana"]=12489,
+ ["dollar"]=36,
+ ["dollarmonospace"]=65284,
+ ["dollarsmall"]=65129,
+ ["dong"]=8363,
+ ["dorusquare"]=13094,
+ ["dotaccent"]=729,
+ ["dotaccentcmb"]=775,
+ ["dotbelowcmb"]=803,
+ ["dotbelowcomb"]=803,
+ ["dotkatakana"]=12539,
+ ["dotlessi"]=305,
+ ["dotlessjstrokehook"]=644,
+ ["dotmath"]=8901,
+ ["dottedcircle"]=9676,
+ ["doubleyodpatah"]=64287,
+ ["doubleyodpatahhebrew"]=64287,
+ ["downtackbelowcmb"]=798,
+ ["downtackmod"]=725,
+ ["dparen"]=9375,
+ ["dtail"]=598,
+ ["dtopbar"]=396,
+ ["duhiragana"]=12389,
+ ["dukatakana"]=12485,
+ ["dz"]=499,
+ ["dzaltone"]=675,
+ ["dzcaron"]=454,
+ ["dzcurl"]=677,
+ ["dzeabkhasiancyrillic"]=1249,
+ ["dzecyrillic"]=1109,
+ ["dzhecyrillic"]=1119,
+ ["e"]=101,
+ ["eacute"]=233,
+ ["earth"]=9793,
+ ["ebengali"]=2447,
+ ["ebopomofo"]=12572,
+ ["ebreve"]=277,
+ ["ecandradeva"]=2317,
+ ["ecandragujarati"]=2701,
+ ["ecandravowelsigndeva"]=2373,
+ ["ecandravowelsigngujarati"]=2757,
+ ["ecaron"]=283,
+ ["ecedillabreve"]=7709,
+ ["echarmenian"]=1381,
+ ["echyiwnarmenian"]=1415,
+ ["ecircle"]=9428,
+ ["ecircumflex"]=234,
+ ["ecircumflexacute"]=7871,
+ ["ecircumflexbelow"]=7705,
+ ["ecircumflexdotbelow"]=7879,
+ ["ecircumflexgrave"]=7873,
+ ["ecircumflexhookabove"]=7875,
+ ["ecircumflextilde"]=7877,
+ ["ecyrillic"]=1108,
+ ["edblgrave"]=517,
+ ["edeva"]=2319,
+ ["edieresis"]=235,
+ ["edot"]=279,
+ ["edotaccent"]=279,
+ ["edotbelow"]=7865,
+ ["eegurmukhi"]=2575,
+ ["eematragurmukhi"]=2631,
+ ["efcyrillic"]=1092,
+ ["egrave"]=232,
+ ["egujarati"]=2703,
+ ["eharmenian"]=1383,
+ ["ehbopomofo"]=12573,
+ ["ehiragana"]=12360,
+ ["ehookabove"]=7867,
+ ["eibopomofo"]=12575,
+ ["eight"]=56,
+ ["eightarabic"]=1640,
+ ["eightbengali"]=2542,
+ ["eightcircle"]=9319,
+ ["eightcircleinversesansserif"]=10129,
+ ["eightdeva"]=2414,
+ ["eighteencircle"]=9329,
+ ["eighteenparen"]=9349,
+ ["eighteenperiod"]=9369,
+ ["eightgujarati"]=2798,
+ ["eightgurmukhi"]=2670,
+ ["eighthackarabic"]=1640,
+ ["eighthangzhou"]=12328,
+ ["eighthnotebeamed"]=9835,
+ ["eightideographicparen"]=12839,
+ ["eightinferior"]=8328,
+ ["eightmonospace"]=65304,
+ ["eightparen"]=9339,
+ ["eightperiod"]=9359,
+ ["eightpersian"]=1784,
+ ["eightroman"]=8567,
+ ["eightsuperior"]=8312,
+ ["eightthai"]=3672,
+ ["einvertedbreve"]=519,
+ ["eiotifiedcyrillic"]=1125,
+ ["ekatakana"]=12456,
+ ["ekatakanahalfwidth"]=65396,
+ ["ekonkargurmukhi"]=2676,
+ ["ekorean"]=12628,
+ ["elcyrillic"]=1083,
+ ["element"]=8712,
+ ["elevencircle"]=9322,
+ ["elevenparen"]=9342,
+ ["elevenperiod"]=9362,
+ ["elevenroman"]=8570,
+ ["ellipsis"]=8230,
+ ["ellipsisvertical"]=8942,
+ ["emacron"]=275,
+ ["emacronacute"]=7703,
+ ["emacrongrave"]=7701,
+ ["emcyrillic"]=1084,
+ ["emdash"]=8212,
+ ["emdashvertical"]=65073,
+ ["emonospace"]=65349,
+ ["emphasismarkarmenian"]=1371,
+ ["emptyset"]=8709,
+ ["enbopomofo"]=12579,
+ ["encyrillic"]=1085,
+ ["endash"]=8211,
+ ["endashvertical"]=65074,
+ ["endescendercyrillic"]=1187,
+ ["eng"]=331,
+ ["engbopomofo"]=12581,
+ ["enghecyrillic"]=1189,
+ ["enhookcyrillic"]=1224,
+ ["enspace"]=8194,
+ ["eogonek"]=281,
+ ["eokorean"]=12627,
+ ["eopen"]=603,
+ ["eopenclosed"]=666,
+ ["eopenreversed"]=604,
+ ["eopenreversedclosed"]=606,
+ ["eopenreversedhook"]=605,
+ ["eparen"]=9376,
+ ["epsilon"]=949,
+ ["epsilontonos"]=941,
+ ["equal"]=61,
+ ["equalmonospace"]=65309,
+ ["equalsmall"]=65126,
+ ["equalsuperior"]=8316,
+ ["equivalence"]=8801,
+ ["erbopomofo"]=12582,
+ ["ercyrillic"]=1088,
+ ["ereversed"]=600,
+ ["ereversedcyrillic"]=1101,
+ ["escyrillic"]=1089,
+ ["esdescendercyrillic"]=1195,
+ ["esh"]=643,
+ ["eshcurl"]=646,
+ ["eshortdeva"]=2318,
+ ["eshortvowelsigndeva"]=2374,
+ ["eshreversedloop"]=426,
+ ["eshsquatreversed"]=645,
+ ["esmallhiragana"]=12359,
+ ["esmallkatakana"]=12455,
+ ["esmallkatakanahalfwidth"]=65386,
+ ["estimated"]=8494,
+ ["eta"]=951,
+ ["etarmenian"]=1384,
+ ["etatonos"]=942,
+ ["eth"]=240,
+ ["etilde"]=7869,
+ ["etildebelow"]=7707,
+ ["etnahtafoukhhebrew"]=1425,
+ ["etnahtafoukhlefthebrew"]=1425,
+ ["etnahtahebrew"]=1425,
+ ["etnahtalefthebrew"]=1425,
+ ["eturned"]=477,
+ ["eukorean"]=12641,
+ ["euro"]=8364,
+ ["evowelsignbengali"]=2503,
+ ["evowelsigndeva"]=2375,
+ ["evowelsigngujarati"]=2759,
+ ["exclam"]=33,
+ ["exclamarmenian"]=1372,
+ ["exclamdbl"]=8252,
+ ["exclamdown"]=161,
+ ["exclammonospace"]=65281,
+ ["existential"]=8707,
+ ["ezh"]=658,
+ ["ezhcaron"]=495,
+ ["ezhcurl"]=659,
+ ["ezhreversed"]=441,
+ ["ezhtail"]=442,
+ ["f"]=102,
+ ["fadeva"]=2398,
+ ["fagurmukhi"]=2654,
+ ["fahrenheit"]=8457,
+ ["fathaarabic"]=1614,
+ ["fathalowarabic"]=1614,
+ ["fathatanarabic"]=1611,
+ ["fbopomofo"]=12552,
+ ["fcircle"]=9429,
+ ["fdotaccent"]=7711,
+ ["feharabic"]=1601,
+ ["feharmenian"]=1414,
+ ["fehfinalarabic"]=65234,
+ ["fehinitialarabic"]=65235,
+ ["fehmedialarabic"]=65236,
+ ["feicoptic"]=997,
+ ["female"]=9792,
+ ["ff"]=64256,
+ ["ffi"]=64259,
+ ["ffl"]=64260,
+ ["fi"]=64257,
+ ["fifteencircle"]=9326,
+ ["fifteenparen"]=9346,
+ ["fifteenperiod"]=9366,
+ ["figuredash"]=8210,
+ ["filledbox"]=9632,
+ ["filledrect"]=9644,
+ ["finalkaf"]=1498,
+ ["finalkafdagesh"]=64314,
+ ["finalkafdageshhebrew"]=64314,
+ ["finalkafhebrew"]=1498,
+ ["finalkafqamats"]=1498,
+ ["finalkafqamatshebrew"]=1498,
+ ["finalkafsheva"]=1498,
+ ["finalkafshevahebrew"]=1498,
+ ["finalmem"]=1501,
+ ["finalmemhebrew"]=1501,
+ ["finalnun"]=1503,
+ ["finalnunhebrew"]=1503,
+ ["finalpe"]=1507,
+ ["finalpehebrew"]=1507,
+ ["finaltsadi"]=1509,
+ ["finaltsadihebrew"]=1509,
+ ["firsttonechinese"]=713,
+ ["fisheye"]=9673,
+ ["fitacyrillic"]=1139,
+ ["five"]=53,
+ ["fivearabic"]=1637,
+ ["fivebengali"]=2539,
+ ["fivecircle"]=9316,
+ ["fivecircleinversesansserif"]=10126,
+ ["fivedeva"]=2411,
+ ["fiveeighths"]=8541,
+ ["fivegujarati"]=2795,
+ ["fivegurmukhi"]=2667,
+ ["fivehackarabic"]=1637,
+ ["fivehangzhou"]=12325,
+ ["fiveideographicparen"]=12836,
+ ["fiveinferior"]=8325,
+ ["fivemonospace"]=65301,
+ ["fiveparen"]=9336,
+ ["fiveperiod"]=9356,
+ ["fivepersian"]=1781,
+ ["fiveroman"]=8564,
+ ["fivesuperior"]=8309,
+ ["fivethai"]=3669,
+ ["fl"]=64258,
+ ["florin"]=402,
+ ["fmonospace"]=65350,
+ ["fmsquare"]=13209,
+ ["fofanthai"]=3615,
+ ["fofathai"]=3613,
+ ["fongmanthai"]=3663,
+ ["forall"]=8704,
+ ["four"]=52,
+ ["fourarabic"]=1636,
+ ["fourbengali"]=2538,
+ ["fourcircle"]=9315,
+ ["fourcircleinversesansserif"]=10125,
+ ["fourdeva"]=2410,
+ ["fourgujarati"]=2794,
+ ["fourgurmukhi"]=2666,
+ ["fourhackarabic"]=1636,
+ ["fourhangzhou"]=12324,
+ ["fourideographicparen"]=12835,
+ ["fourinferior"]=8324,
+ ["fourmonospace"]=65300,
+ ["fournumeratorbengali"]=2551,
+ ["fourparen"]=9335,
+ ["fourperiod"]=9355,
+ ["fourpersian"]=1780,
+ ["fourroman"]=8563,
+ ["foursuperior"]=8308,
+ ["fourteencircle"]=9325,
+ ["fourteenparen"]=9345,
+ ["fourteenperiod"]=9365,
+ ["fourthai"]=3668,
+ ["fourthtonechinese"]=715,
+ ["fparen"]=9377,
+ ["fraction"]=8260,
+ ["franc"]=8355,
+ ["g"]=103,
+ ["gabengali"]=2455,
+ ["gacute"]=501,
+ ["gadeva"]=2327,
+ ["gafarabic"]=1711,
+ ["gaffinalarabic"]=64403,
+ ["gafinitialarabic"]=64404,
+ ["gafmedialarabic"]=64405,
+ ["gagujarati"]=2711,
+ ["gagurmukhi"]=2583,
+ ["gahiragana"]=12364,
+ ["gakatakana"]=12460,
+ ["gamma"]=947,
+ ["gammalatinsmall"]=611,
+ ["gammasuperior"]=736,
+ ["gangiacoptic"]=1003,
+ ["gbopomofo"]=12557,
+ ["gbreve"]=287,
+ ["gcaron"]=487,
+ ["gcedilla"]=291,
+ ["gcircle"]=9430,
+ ["gcircumflex"]=285,
+ ["gcommaaccent"]=291,
+ ["gdot"]=289,
+ ["gdotaccent"]=289,
+ ["gecyrillic"]=1075,
+ ["gehiragana"]=12370,
+ ["gekatakana"]=12466,
+ ["geometricallyequal"]=8785,
+ ["gereshaccenthebrew"]=1436,
+ ["gereshhebrew"]=1523,
+ ["gereshmuqdamhebrew"]=1437,
+ ["germandbls"]=223,
+ ["gershayimaccenthebrew"]=1438,
+ ["gershayimhebrew"]=1524,
+ ["getamark"]=12307,
+ ["ghabengali"]=2456,
+ ["ghadarmenian"]=1394,
+ ["ghadeva"]=2328,
+ ["ghagujarati"]=2712,
+ ["ghagurmukhi"]=2584,
+ ["ghainarabic"]=1594,
+ ["ghainfinalarabic"]=65230,
+ ["ghaininitialarabic"]=65231,
+ ["ghainmedialarabic"]=65232,
+ ["ghemiddlehookcyrillic"]=1173,
+ ["ghestrokecyrillic"]=1171,
+ ["gheupturncyrillic"]=1169,
+ ["ghhadeva"]=2394,
+ ["ghhagurmukhi"]=2650,
+ ["ghook"]=608,
+ ["ghzsquare"]=13203,
+ ["gihiragana"]=12366,
+ ["gikatakana"]=12462,
+ ["gimarmenian"]=1379,
+ ["gimel"]=1490,
+ ["gimeldagesh"]=64306,
+ ["gimeldageshhebrew"]=64306,
+ ["gimelhebrew"]=1490,
+ ["gjecyrillic"]=1107,
+ ["glottalinvertedstroke"]=446,
+ ["glottalstop"]=660,
+ ["glottalstopinverted"]=662,
+ ["glottalstopmod"]=704,
+ ["glottalstopreversed"]=661,
+ ["glottalstopreversedmod"]=705,
+ ["glottalstopreversedsuperior"]=740,
+ ["glottalstopstroke"]=673,
+ ["glottalstopstrokereversed"]=674,
+ ["gmacron"]=7713,
+ ["gmonospace"]=65351,
+ ["gohiragana"]=12372,
+ ["gokatakana"]=12468,
+ ["gparen"]=9378,
+ ["gpasquare"]=13228,
+ ["gradient"]=8711,
+ ["grave"]=96,
+ ["gravebelowcmb"]=790,
+ ["gravecmb"]=768,
+ ["gravecomb"]=768,
+ ["gravedeva"]=2387,
+ ["gravelowmod"]=718,
+ ["gravemonospace"]=65344,
+ ["gravetonecmb"]=832,
+ ["greater"]=62,
+ ["greaterequal"]=8805,
+ ["greaterequalorless"]=8923,
+ ["greatermonospace"]=65310,
+ ["greaterorequivalent"]=8819,
+ ["greaterorless"]=8823,
+ ["greateroverequal"]=8807,
+ ["greatersmall"]=65125,
+ ["gscript"]=609,
+ ["gstroke"]=485,
+ ["guhiragana"]=12368,
+ ["guillemotleft"]=171,
+ ["guillemotright"]=187,
+ ["guilsinglleft"]=8249,
+ ["guilsinglright"]=8250,
+ ["gukatakana"]=12464,
+ ["guramusquare"]=13080,
+ ["gysquare"]=13257,
+ ["h"]=104,
+ ["haabkhasiancyrillic"]=1193,
+ ["haaltonearabic"]=1729,
+ ["habengali"]=2489,
+ ["hadescendercyrillic"]=1203,
+ ["hadeva"]=2361,
+ ["hagujarati"]=2745,
+ ["hagurmukhi"]=2617,
+ ["haharabic"]=1581,
+ ["hahfinalarabic"]=65186,
+ ["hahinitialarabic"]=65187,
+ ["hahiragana"]=12399,
+ ["hahmedialarabic"]=65188,
+ ["haitusquare"]=13098,
+ ["hakatakana"]=12495,
+ ["hakatakanahalfwidth"]=65418,
+ ["halantgurmukhi"]=2637,
+ ["hamzaarabic"]=1569,
+ ["hamzadammaarabic"]=1569,
+ ["hamzadammatanarabic"]=1569,
+ ["hamzafathaarabic"]=1569,
+ ["hamzafathatanarabic"]=1569,
+ ["hamzalowarabic"]=1569,
+ ["hamzalowkasraarabic"]=1569,
+ ["hamzalowkasratanarabic"]=1569,
+ ["hamzasukunarabic"]=1569,
+ ["hangulfiller"]=12644,
+ ["hardsigncyrillic"]=1098,
+ ["harpoonleftbarbup"]=8636,
+ ["harpoonrightbarbup"]=8640,
+ ["hasquare"]=13258,
+ ["hatafpatah"]=1458,
+ ["hatafpatah16"]=1458,
+ ["hatafpatah23"]=1458,
+ ["hatafpatah2f"]=1458,
+ ["hatafpatahhebrew"]=1458,
+ ["hatafpatahnarrowhebrew"]=1458,
+ ["hatafpatahquarterhebrew"]=1458,
+ ["hatafpatahwidehebrew"]=1458,
+ ["hatafqamats"]=1459,
+ ["hatafqamats1b"]=1459,
+ ["hatafqamats28"]=1459,
+ ["hatafqamats34"]=1459,
+ ["hatafqamatshebrew"]=1459,
+ ["hatafqamatsnarrowhebrew"]=1459,
+ ["hatafqamatsquarterhebrew"]=1459,
+ ["hatafqamatswidehebrew"]=1459,
+ ["hatafsegol"]=1457,
+ ["hatafsegol17"]=1457,
+ ["hatafsegol24"]=1457,
+ ["hatafsegol30"]=1457,
+ ["hatafsegolhebrew"]=1457,
+ ["hatafsegolnarrowhebrew"]=1457,
+ ["hatafsegolquarterhebrew"]=1457,
+ ["hatafsegolwidehebrew"]=1457,
+ ["hbar"]=295,
+ ["hbopomofo"]=12559,
+ ["hbrevebelow"]=7723,
+ ["hcedilla"]=7721,
+ ["hcircle"]=9431,
+ ["hcircumflex"]=293,
+ ["hdieresis"]=7719,
+ ["hdotaccent"]=7715,
+ ["hdotbelow"]=7717,
+ ["he"]=1492,
+ ["heart"]=9829,
+ ["heartsuitblack"]=9829,
+ ["heartsuitwhite"]=9825,
+ ["hedagesh"]=64308,
+ ["hedageshhebrew"]=64308,
+ ["hehaltonearabic"]=1729,
+ ["heharabic"]=1607,
+ ["hehebrew"]=1492,
+ ["hehfinalaltonearabic"]=64423,
+ ["hehfinalalttwoarabic"]=65258,
+ ["hehfinalarabic"]=65258,
+ ["hehhamzaabovefinalarabic"]=64421,
+ ["hehhamzaaboveisolatedarabic"]=64420,
+ ["hehinitialaltonearabic"]=64424,
+ ["hehinitialarabic"]=65259,
+ ["hehiragana"]=12408,
+ ["hehmedialaltonearabic"]=64425,
+ ["hehmedialarabic"]=65260,
+ ["heiseierasquare"]=13179,
+ ["hekatakana"]=12504,
+ ["hekatakanahalfwidth"]=65421,
+ ["hekutaarusquare"]=13110,
+ ["henghook"]=615,
+ ["herutusquare"]=13113,
+ ["het"]=1495,
+ ["hethebrew"]=1495,
+ ["hhook"]=614,
+ ["hhooksuperior"]=689,
+ ["hieuhacirclekorean"]=12923,
+ ["hieuhaparenkorean"]=12827,
+ ["hieuhcirclekorean"]=12909,
+ ["hieuhkorean"]=12622,
+ ["hieuhparenkorean"]=12813,
+ ["hihiragana"]=12402,
+ ["hikatakana"]=12498,
+ ["hikatakanahalfwidth"]=65419,
+ ["hiriq"]=1460,
+ ["hiriq14"]=1460,
+ ["hiriq21"]=1460,
+ ["hiriq2d"]=1460,
+ ["hiriqhebrew"]=1460,
+ ["hiriqnarrowhebrew"]=1460,
+ ["hiriqquarterhebrew"]=1460,
+ ["hiriqwidehebrew"]=1460,
+ ["hlinebelow"]=7830,
+ ["hmonospace"]=65352,
+ ["hoarmenian"]=1392,
+ ["hohipthai"]=3627,
+ ["hohiragana"]=12411,
+ ["hokatakana"]=12507,
+ ["hokatakanahalfwidth"]=65422,
+ ["holam"]=1465,
+ ["holam19"]=1465,
+ ["holam26"]=1465,
+ ["holam32"]=1465,
+ ["holamhebrew"]=1465,
+ ["holamnarrowhebrew"]=1465,
+ ["holamquarterhebrew"]=1465,
+ ["holamwidehebrew"]=1465,
+ ["honokhukthai"]=3630,
+ ["hookabovecomb"]=777,
+ ["hookcmb"]=777,
+ ["hookpalatalizedbelowcmb"]=801,
+ ["hookretroflexbelowcmb"]=802,
+ ["hoonsquare"]=13122,
+ ["horicoptic"]=1001,
+ ["horizontalbar"]=8213,
+ ["horncmb"]=795,
+ ["hotsprings"]=9832,
+ ["house"]=8962,
+ ["hparen"]=9379,
+ ["hsuperior"]=688,
+ ["hturned"]=613,
+ ["huhiragana"]=12405,
+ ["huiitosquare"]=13107,
+ ["hukatakana"]=12501,
+ ["hukatakanahalfwidth"]=65420,
+ ["hungarumlaut"]=733,
+ ["hungarumlautcmb"]=779,
+ ["hv"]=405,
+ ["hyphen"]=45,
+ ["hyphenmonospace"]=65293,
+ ["hyphensmall"]=65123,
+ ["hyphentwo"]=8208,
+ ["i"]=105,
+ ["iacute"]=237,
+ ["iacyrillic"]=1103,
+ ["ibengali"]=2439,
+ ["ibopomofo"]=12583,
+ ["ibreve"]=301,
+ ["icaron"]=464,
+ ["icircle"]=9432,
+ ["icircumflex"]=238,
+ ["icyrillic"]=1110,
+ ["idblgrave"]=521,
+ ["ideographearthcircle"]=12943,
+ ["ideographfirecircle"]=12939,
+ ["ideographicallianceparen"]=12863,
+ ["ideographiccallparen"]=12858,
+ ["ideographiccentrecircle"]=12965,
+ ["ideographicclose"]=12294,
+ ["ideographiccomma"]=12289,
+ ["ideographiccommaleft"]=65380,
+ ["ideographiccongratulationparen"]=12855,
+ ["ideographiccorrectcircle"]=12963,
+ ["ideographicearthparen"]=12847,
+ ["ideographicenterpriseparen"]=12861,
+ ["ideographicexcellentcircle"]=12957,
+ ["ideographicfestivalparen"]=12864,
+ ["ideographicfinancialcircle"]=12950,
+ ["ideographicfinancialparen"]=12854,
+ ["ideographicfireparen"]=12843,
+ ["ideographichaveparen"]=12850,
+ ["ideographichighcircle"]=12964,
+ ["ideographiciterationmark"]=12293,
+ ["ideographiclaborcircle"]=12952,
+ ["ideographiclaborparen"]=12856,
+ ["ideographicleftcircle"]=12967,
+ ["ideographiclowcircle"]=12966,
+ ["ideographicmedicinecircle"]=12969,
+ ["ideographicmetalparen"]=12846,
+ ["ideographicmoonparen"]=12842,
+ ["ideographicnameparen"]=12852,
+ ["ideographicperiod"]=12290,
+ ["ideographicprintcircle"]=12958,
+ ["ideographicreachparen"]=12867,
+ ["ideographicrepresentparen"]=12857,
+ ["ideographicresourceparen"]=12862,
+ ["ideographicrightcircle"]=12968,
+ ["ideographicsecretcircle"]=12953,
+ ["ideographicselfparen"]=12866,
+ ["ideographicsocietyparen"]=12851,
+ ["ideographicspace"]=12288,
+ ["ideographicspecialparen"]=12853,
+ ["ideographicstockparen"]=12849,
+ ["ideographicstudyparen"]=12859,
+ ["ideographicsunparen"]=12848,
+ ["ideographicsuperviseparen"]=12860,
+ ["ideographicwaterparen"]=12844,
+ ["ideographicwoodparen"]=12845,
+ ["ideographiczero"]=12295,
+ ["ideographmetalcircle"]=12942,
+ ["ideographmooncircle"]=12938,
+ ["ideographnamecircle"]=12948,
+ ["ideographsuncircle"]=12944,
+ ["ideographwatercircle"]=12940,
+ ["ideographwoodcircle"]=12941,
+ ["ideva"]=2311,
+ ["idieresis"]=239,
+ ["idieresisacute"]=7727,
+ ["idieresiscyrillic"]=1253,
+ ["idotbelow"]=7883,
+ ["iebrevecyrillic"]=1239,
+ ["iecyrillic"]=1077,
+ ["ieungacirclekorean"]=12917,
+ ["ieungaparenkorean"]=12821,
+ ["ieungcirclekorean"]=12903,
+ ["ieungkorean"]=12615,
+ ["ieungparenkorean"]=12807,
+ ["igrave"]=236,
+ ["igujarati"]=2695,
+ ["igurmukhi"]=2567,
+ ["ihiragana"]=12356,
+ ["ihookabove"]=7881,
+ ["iibengali"]=2440,
+ ["iicyrillic"]=1080,
+ ["iideva"]=2312,
+ ["iigujarati"]=2696,
+ ["iigurmukhi"]=2568,
+ ["iimatragurmukhi"]=2624,
+ ["iinvertedbreve"]=523,
+ ["iishortcyrillic"]=1081,
+ ["iivowelsignbengali"]=2496,
+ ["iivowelsigndeva"]=2368,
+ ["iivowelsigngujarati"]=2752,
+ ["ij"]=307,
+ ["ikatakana"]=12452,
+ ["ikatakanahalfwidth"]=65394,
+ ["ikorean"]=12643,
+ ["ilde"]=732,
+ ["iluyhebrew"]=1452,
+ ["imacron"]=299,
+ ["imacroncyrillic"]=1251,
+ ["imageorapproximatelyequal"]=8787,
+ ["imatragurmukhi"]=2623,
+ ["imonospace"]=65353,
+ ["increment"]=8710,
+ ["infinity"]=8734,
+ ["iniarmenian"]=1387,
+ ["integral"]=8747,
+ ["integralbottom"]=8993,
+ ["integralbt"]=8993,
+ ["integraltop"]=8992,
+ ["integraltp"]=8992,
+ ["intersection"]=8745,
+ ["intisquare"]=13061,
+ ["invbullet"]=9688,
+ ["invcircle"]=9689,
+ ["invsmileface"]=9787,
+ ["iocyrillic"]=1105,
+ ["iogonek"]=303,
+ ["iota"]=953,
+ ["iotadieresis"]=970,
+ ["iotadieresistonos"]=912,
+ ["iotalatin"]=617,
+ ["iotatonos"]=943,
+ ["iparen"]=9380,
+ ["irigurmukhi"]=2674,
+ ["ismallhiragana"]=12355,
+ ["ismallkatakana"]=12451,
+ ["ismallkatakanahalfwidth"]=65384,
+ ["issharbengali"]=2554,
+ ["istroke"]=616,
+ ["iterationhiragana"]=12445,
+ ["iterationkatakana"]=12541,
+ ["itilde"]=297,
+ ["itildebelow"]=7725,
+ ["iubopomofo"]=12585,
+ ["iucyrillic"]=1102,
+ ["ivowelsignbengali"]=2495,
+ ["ivowelsigndeva"]=2367,
+ ["ivowelsigngujarati"]=2751,
+ ["izhitsacyrillic"]=1141,
+ ["izhitsadblgravecyrillic"]=1143,
+ ["j"]=106,
+ ["jaarmenian"]=1393,
+ ["jabengali"]=2460,
+ ["jadeva"]=2332,
+ ["jagujarati"]=2716,
+ ["jagurmukhi"]=2588,
+ ["jbopomofo"]=12560,
+ ["jcaron"]=496,
+ ["jcircle"]=9433,
+ ["jcircumflex"]=309,
+ ["jcrossedtail"]=669,
+ ["jdotlessstroke"]=607,
+ ["jecyrillic"]=1112,
+ ["jeemarabic"]=1580,
+ ["jeemfinalarabic"]=65182,
+ ["jeeminitialarabic"]=65183,
+ ["jeemmedialarabic"]=65184,
+ ["jeharabic"]=1688,
+ ["jehfinalarabic"]=64395,
+ ["jhabengali"]=2461,
+ ["jhadeva"]=2333,
+ ["jhagujarati"]=2717,
+ ["jhagurmukhi"]=2589,
+ ["jheharmenian"]=1403,
+ ["jis"]=12292,
+ ["jmonospace"]=65354,
+ ["jparen"]=9381,
+ ["jsuperior"]=690,
+ ["k"]=107,
+ ["kabashkircyrillic"]=1185,
+ ["kabengali"]=2453,
+ ["kacute"]=7729,
+ ["kacyrillic"]=1082,
+ ["kadescendercyrillic"]=1179,
+ ["kadeva"]=2325,
+ ["kaf"]=1499,
+ ["kafarabic"]=1603,
+ ["kafdagesh"]=64315,
+ ["kafdageshhebrew"]=64315,
+ ["kaffinalarabic"]=65242,
+ ["kafhebrew"]=1499,
+ ["kafinitialarabic"]=65243,
+ ["kafmedialarabic"]=65244,
+ ["kafrafehebrew"]=64333,
+ ["kagujarati"]=2709,
+ ["kagurmukhi"]=2581,
+ ["kahiragana"]=12363,
+ ["kahookcyrillic"]=1220,
+ ["kakatakana"]=12459,
+ ["kakatakanahalfwidth"]=65398,
+ ["kappa"]=954,
+ ["kappasymbolgreek"]=1008,
+ ["kapyeounmieumkorean"]=12657,
+ ["kapyeounphieuphkorean"]=12676,
+ ["kapyeounpieupkorean"]=12664,
+ ["kapyeounssangpieupkorean"]=12665,
+ ["karoriisquare"]=13069,
+ ["kashidaautoarabic"]=1600,
+ ["kashidaautonosidebearingarabic"]=1600,
+ ["kasmallkatakana"]=12533,
+ ["kasquare"]=13188,
+ ["kasraarabic"]=1616,
+ ["kasratanarabic"]=1613,
+ ["kastrokecyrillic"]=1183,
+ ["katahiraprolongmarkhalfwidth"]=65392,
+ ["kaverticalstrokecyrillic"]=1181,
+ ["kbopomofo"]=12558,
+ ["kcalsquare"]=13193,
+ ["kcaron"]=489,
+ ["kcedilla"]=311,
+ ["kcircle"]=9434,
+ ["kcommaaccent"]=311,
+ ["kdotbelow"]=7731,
+ ["keharmenian"]=1412,
+ ["kehiragana"]=12369,
+ ["kekatakana"]=12465,
+ ["kekatakanahalfwidth"]=65401,
+ ["kenarmenian"]=1391,
+ ["kesmallkatakana"]=12534,
+ ["kgreenlandic"]=312,
+ ["khabengali"]=2454,
+ ["khacyrillic"]=1093,
+ ["khadeva"]=2326,
+ ["khagujarati"]=2710,
+ ["khagurmukhi"]=2582,
+ ["khaharabic"]=1582,
+ ["khahfinalarabic"]=65190,
+ ["khahinitialarabic"]=65191,
+ ["khahmedialarabic"]=65192,
+ ["kheicoptic"]=999,
+ ["khhadeva"]=2393,
+ ["khhagurmukhi"]=2649,
+ ["khieukhacirclekorean"]=12920,
+ ["khieukhaparenkorean"]=12824,
+ ["khieukhcirclekorean"]=12906,
+ ["khieukhkorean"]=12619,
+ ["khieukhparenkorean"]=12810,
+ ["khokhaithai"]=3586,
+ ["khokhonthai"]=3589,
+ ["khokhuatthai"]=3587,
+ ["khokhwaithai"]=3588,
+ ["khomutthai"]=3675,
+ ["khook"]=409,
+ ["khorakhangthai"]=3590,
+ ["khzsquare"]=13201,
+ ["kihiragana"]=12365,
+ ["kikatakana"]=12461,
+ ["kikatakanahalfwidth"]=65399,
+ ["kiroguramusquare"]=13077,
+ ["kiromeetorusquare"]=13078,
+ ["kirosquare"]=13076,
+ ["kiyeokacirclekorean"]=12910,
+ ["kiyeokaparenkorean"]=12814,
+ ["kiyeokcirclekorean"]=12896,
+ ["kiyeokkorean"]=12593,
+ ["kiyeokparenkorean"]=12800,
+ ["kiyeoksioskorean"]=12595,
+ ["kjecyrillic"]=1116,
+ ["klinebelow"]=7733,
+ ["klsquare"]=13208,
+ ["kmcubedsquare"]=13222,
+ ["kmonospace"]=65355,
+ ["kmsquaredsquare"]=13218,
+ ["kohiragana"]=12371,
+ ["kohmsquare"]=13248,
+ ["kokaithai"]=3585,
+ ["kokatakana"]=12467,
+ ["kokatakanahalfwidth"]=65402,
+ ["kooposquare"]=13086,
+ ["koppacyrillic"]=1153,
+ ["koreanstandardsymbol"]=12927,
+ ["koroniscmb"]=835,
+ ["kparen"]=9382,
+ ["kpasquare"]=13226,
+ ["ksicyrillic"]=1135,
+ ["ktsquare"]=13263,
+ ["kturned"]=670,
+ ["kuhiragana"]=12367,
+ ["kukatakana"]=12463,
+ ["kukatakanahalfwidth"]=65400,
+ ["kvsquare"]=13240,
+ ["kwsquare"]=13246,
+ ["l"]=108,
+ ["labengali"]=2482,
+ ["lacute"]=314,
+ ["ladeva"]=2354,
+ ["lagujarati"]=2738,
+ ["lagurmukhi"]=2610,
+ ["lakkhangyaothai"]=3653,
+ ["lamaleffinalarabic"]=65276,
+ ["lamalefhamzaabovefinalarabic"]=65272,
+ ["lamalefhamzaaboveisolatedarabic"]=65271,
+ ["lamalefhamzabelowfinalarabic"]=65274,
+ ["lamalefhamzabelowisolatedarabic"]=65273,
+ ["lamalefisolatedarabic"]=65275,
+ ["lamalefmaddaabovefinalarabic"]=65270,
+ ["lamalefmaddaaboveisolatedarabic"]=65269,
+ ["lamarabic"]=1604,
+ ["lambda"]=955,
+ ["lambdastroke"]=411,
+ ["lamed"]=1500,
+ ["lameddagesh"]=64316,
+ ["lameddageshhebrew"]=64316,
+ ["lamedhebrew"]=1500,
+ ["lamedholam"]=1500,
+ ["lamedholamdagesh"]=1500,
+ ["lamedholamdageshhebrew"]=1500,
+ ["lamedholamhebrew"]=1500,
+ ["lamfinalarabic"]=65246,
+ ["lamhahinitialarabic"]=64714,
+ ["laminitialarabic"]=65247,
+ ["lamjeeminitialarabic"]=64713,
+ ["lamkhahinitialarabic"]=64715,
+ ["lamlamhehisolatedarabic"]=65010,
+ ["lammedialarabic"]=65248,
+ ["lammeemhahinitialarabic"]=64904,
+ ["lammeeminitialarabic"]=64716,
+ ["lammeemjeeminitialarabic"]=65247,
+ ["lammeemkhahinitialarabic"]=65247,
+ ["largecircle"]=9711,
+ ["lbar"]=410,
+ ["lbelt"]=620,
+ ["lbopomofo"]=12556,
+ ["lcaron"]=318,
+ ["lcedilla"]=316,
+ ["lcircle"]=9435,
+ ["lcircumflexbelow"]=7741,
+ ["lcommaaccent"]=316,
+ ["ldot"]=320,
+ ["ldotaccent"]=320,
+ ["ldotbelow"]=7735,
+ ["ldotbelowmacron"]=7737,
+ ["leftangleabovecmb"]=794,
+ ["lefttackbelowcmb"]=792,
+ ["less"]=60,
+ ["lessequal"]=8804,
+ ["lessequalorgreater"]=8922,
+ ["lessmonospace"]=65308,
+ ["lessorequivalent"]=8818,
+ ["lessorgreater"]=8822,
+ ["lessoverequal"]=8806,
+ ["lesssmall"]=65124,
+ ["lezh"]=622,
+ ["lfblock"]=9612,
+ ["lhookretroflex"]=621,
+ ["lira"]=8356,
+ ["liwnarmenian"]=1388,
+ ["lj"]=457,
+ ["ljecyrillic"]=1113,
+ ["lladeva"]=2355,
+ ["llagujarati"]=2739,
+ ["llinebelow"]=7739,
+ ["llladeva"]=2356,
+ ["llvocalicbengali"]=2529,
+ ["llvocalicdeva"]=2401,
+ ["llvocalicvowelsignbengali"]=2531,
+ ["llvocalicvowelsigndeva"]=2403,
+ ["lmiddletilde"]=619,
+ ["lmonospace"]=65356,
+ ["lmsquare"]=13264,
+ ["lochulathai"]=3628,
+ ["logicaland"]=8743,
+ ["logicalnot"]=172,
+ ["logicalnotreversed"]=8976,
+ ["logicalor"]=8744,
+ ["lolingthai"]=3621,
+ ["longs"]=383,
+ ["lowlinecenterline"]=65102,
+ ["lowlinecmb"]=818,
+ ["lowlinedashed"]=65101,
+ ["lozenge"]=9674,
+ ["lparen"]=9383,
+ ["lslash"]=322,
+ ["lsquare"]=8467,
+ ["ltshade"]=9617,
+ ["luthai"]=3622,
+ ["lvocalicbengali"]=2444,
+ ["lvocalicdeva"]=2316,
+ ["lvocalicvowelsignbengali"]=2530,
+ ["lvocalicvowelsigndeva"]=2402,
+ ["lxsquare"]=13267,
+ ["m"]=109,
+ ["mabengali"]=2478,
+ ["macron"]=175,
+ ["macronbelowcmb"]=817,
+ ["macroncmb"]=772,
+ ["macronlowmod"]=717,
+ ["macronmonospace"]=65507,
+ ["macute"]=7743,
+ ["madeva"]=2350,
+ ["magujarati"]=2734,
+ ["magurmukhi"]=2606,
+ ["mahapakhhebrew"]=1444,
+ ["mahapakhlefthebrew"]=1444,
+ ["mahiragana"]=12414,
+ ["maichattawathai"]=3659,
+ ["maiekthai"]=3656,
+ ["maihanakatthai"]=3633,
+ ["maitaikhuthai"]=3655,
+ ["maithothai"]=3657,
+ ["maitrithai"]=3658,
+ ["maiyamokthai"]=3654,
+ ["makatakana"]=12510,
+ ["makatakanahalfwidth"]=65423,
+ ["male"]=9794,
+ ["mansyonsquare"]=13127,
+ ["maqafhebrew"]=1470,
+ ["mars"]=9794,
+ ["masoracirclehebrew"]=1455,
+ ["masquare"]=13187,
+ ["mbopomofo"]=12551,
+ ["mbsquare"]=13268,
+ ["mcircle"]=9436,
+ ["mcubedsquare"]=13221,
+ ["mdotaccent"]=7745,
+ ["mdotbelow"]=7747,
+ ["meemarabic"]=1605,
+ ["meemfinalarabic"]=65250,
+ ["meeminitialarabic"]=65251,
+ ["meemmedialarabic"]=65252,
+ ["meemmeeminitialarabic"]=64721,
+ ["meemmeemisolatedarabic"]=64584,
+ ["meetorusquare"]=13133,
+ ["mehiragana"]=12417,
+ ["meizierasquare"]=13182,
+ ["mekatakana"]=12513,
+ ["mekatakanahalfwidth"]=65426,
+ ["mem"]=1502,
+ ["memdagesh"]=64318,
+ ["memdageshhebrew"]=64318,
+ ["memhebrew"]=1502,
+ ["menarmenian"]=1396,
+ ["merkhahebrew"]=1445,
+ ["merkhakefulahebrew"]=1446,
+ ["merkhakefulalefthebrew"]=1446,
+ ["merkhalefthebrew"]=1445,
+ ["mhook"]=625,
+ ["mhzsquare"]=13202,
+ ["middledotkatakanahalfwidth"]=65381,
+ ["middot"]=183,
+ ["mieumacirclekorean"]=12914,
+ ["mieumaparenkorean"]=12818,
+ ["mieumcirclekorean"]=12900,
+ ["mieumkorean"]=12609,
+ ["mieumpansioskorean"]=12656,
+ ["mieumparenkorean"]=12804,
+ ["mieumpieupkorean"]=12654,
+ ["mieumsioskorean"]=12655,
+ ["mihiragana"]=12415,
+ ["mikatakana"]=12511,
+ ["mikatakanahalfwidth"]=65424,
+ ["minus"]=8722,
+ ["minusbelowcmb"]=800,
+ ["minuscircle"]=8854,
+ ["minusmod"]=727,
+ ["minusplus"]=8723,
+ ["minute"]=8242,
+ ["miribaarusquare"]=13130,
+ ["mirisquare"]=13129,
+ ["mlonglegturned"]=624,
+ ["mlsquare"]=13206,
+ ["mmcubedsquare"]=13219,
+ ["mmonospace"]=65357,
+ ["mmsquaredsquare"]=13215,
+ ["mohiragana"]=12418,
+ ["mohmsquare"]=13249,
+ ["mokatakana"]=12514,
+ ["mokatakanahalfwidth"]=65427,
+ ["molsquare"]=13270,
+ ["momathai"]=3617,
+ ["moverssquare"]=13223,
+ ["moverssquaredsquare"]=13224,
+ ["mparen"]=9384,
+ ["mpasquare"]=13227,
+ ["mssquare"]=13235,
+ ["mturned"]=623,
+ ["mu"]=181,
+ ["mu1"]=181,
+ ["muasquare"]=13186,
+ ["muchgreater"]=8811,
+ ["muchless"]=8810,
+ ["mufsquare"]=13196,
+ ["mugreek"]=956,
+ ["mugsquare"]=13197,
+ ["muhiragana"]=12416,
+ ["mukatakana"]=12512,
+ ["mukatakanahalfwidth"]=65425,
+ ["mulsquare"]=13205,
+ ["multiply"]=215,
+ ["mumsquare"]=13211,
+ ["munahhebrew"]=1443,
+ ["munahlefthebrew"]=1443,
+ ["musicalnote"]=9834,
+ ["musicalnotedbl"]=9835,
+ ["musicflatsign"]=9837,
+ ["musicsharpsign"]=9839,
+ ["mussquare"]=13234,
+ ["muvsquare"]=13238,
+ ["muwsquare"]=13244,
+ ["mvmegasquare"]=13241,
+ ["mvsquare"]=13239,
+ ["mwmegasquare"]=13247,
+ ["mwsquare"]=13245,
+ ["n"]=110,
+ ["nabengali"]=2472,
+ ["nabla"]=8711,
+ ["nacute"]=324,
+ ["nadeva"]=2344,
+ ["nagujarati"]=2728,
+ ["nagurmukhi"]=2600,
+ ["nahiragana"]=12394,
+ ["nakatakana"]=12490,
+ ["nakatakanahalfwidth"]=65413,
+ ["napostrophe"]=329,
+ ["nasquare"]=13185,
+ ["nbopomofo"]=12555,
+ ["nbspace"]=160,
+ ["ncaron"]=328,
+ ["ncedilla"]=326,
+ ["ncircle"]=9437,
+ ["ncircumflexbelow"]=7755,
+ ["ncommaaccent"]=326,
+ ["ndotaccent"]=7749,
+ ["ndotbelow"]=7751,
+ ["nehiragana"]=12397,
+ ["nekatakana"]=12493,
+ ["nekatakanahalfwidth"]=65416,
+ ["newsheqelsign"]=8362,
+ ["nfsquare"]=13195,
+ ["ngabengali"]=2457,
+ ["ngadeva"]=2329,
+ ["ngagujarati"]=2713,
+ ["ngagurmukhi"]=2585,
+ ["ngonguthai"]=3591,
+ ["nhiragana"]=12435,
+ ["nhookleft"]=626,
+ ["nhookretroflex"]=627,
+ ["nieunacirclekorean"]=12911,
+ ["nieunaparenkorean"]=12815,
+ ["nieuncieuckorean"]=12597,
+ ["nieuncirclekorean"]=12897,
+ ["nieunhieuhkorean"]=12598,
+ ["nieunkorean"]=12596,
+ ["nieunpansioskorean"]=12648,
+ ["nieunparenkorean"]=12801,
+ ["nieunsioskorean"]=12647,
+ ["nieuntikeutkorean"]=12646,
+ ["nihiragana"]=12395,
+ ["nikatakana"]=12491,
+ ["nikatakanahalfwidth"]=65414,
+ ["nikhahitthai"]=3661,
+ ["nine"]=57,
+ ["ninearabic"]=1641,
+ ["ninebengali"]=2543,
+ ["ninecircle"]=9320,
+ ["ninecircleinversesansserif"]=10130,
+ ["ninedeva"]=2415,
+ ["ninegujarati"]=2799,
+ ["ninegurmukhi"]=2671,
+ ["ninehackarabic"]=1641,
+ ["ninehangzhou"]=12329,
+ ["nineideographicparen"]=12840,
+ ["nineinferior"]=8329,
+ ["ninemonospace"]=65305,
+ ["nineparen"]=9340,
+ ["nineperiod"]=9360,
+ ["ninepersian"]=1785,
+ ["nineroman"]=8568,
+ ["ninesuperior"]=8313,
+ ["nineteencircle"]=9330,
+ ["nineteenparen"]=9350,
+ ["nineteenperiod"]=9370,
+ ["ninethai"]=3673,
+ ["nj"]=460,
+ ["njecyrillic"]=1114,
+ ["nkatakana"]=12531,
+ ["nkatakanahalfwidth"]=65437,
+ ["nlegrightlong"]=414,
+ ["nlinebelow"]=7753,
+ ["nmonospace"]=65358,
+ ["nmsquare"]=13210,
+ ["nnabengali"]=2467,
+ ["nnadeva"]=2339,
+ ["nnagujarati"]=2723,
+ ["nnagurmukhi"]=2595,
+ ["nnnadeva"]=2345,
+ ["nohiragana"]=12398,
+ ["nokatakana"]=12494,
+ ["nokatakanahalfwidth"]=65417,
+ ["nonbreakingspace"]=160,
+ ["nonenthai"]=3603,
+ ["nonuthai"]=3609,
+ ["noonarabic"]=1606,
+ ["noonfinalarabic"]=65254,
+ ["noonghunnaarabic"]=1722,
+ ["noonghunnafinalarabic"]=64415,
+ ["noonhehinitialarabic"]=65255,
+ ["nooninitialarabic"]=65255,
+ ["noonjeeminitialarabic"]=64722,
+ ["noonjeemisolatedarabic"]=64587,
+ ["noonmedialarabic"]=65256,
+ ["noonmeeminitialarabic"]=64725,
+ ["noonmeemisolatedarabic"]=64590,
+ ["noonnoonfinalarabic"]=64653,
+ ["notcontains"]=8716,
+ ["notelement"]=8713,
+ ["notelementof"]=8713,
+ ["notequal"]=8800,
+ ["notgreater"]=8815,
+ ["notgreaternorequal"]=8817,
+ ["notgreaternorless"]=8825,
+ ["notidentical"]=8802,
+ ["notless"]=8814,
+ ["notlessnorequal"]=8816,
+ ["notparallel"]=8742,
+ ["notprecedes"]=8832,
+ ["notsubset"]=8836,
+ ["notsucceeds"]=8833,
+ ["notsuperset"]=8837,
+ ["nowarmenian"]=1398,
+ ["nparen"]=9385,
+ ["nssquare"]=13233,
+ ["nsuperior"]=8319,
+ ["ntilde"]=241,
+ ["nu"]=957,
+ ["nuhiragana"]=12396,
+ ["nukatakana"]=12492,
+ ["nukatakanahalfwidth"]=65415,
+ ["nuktabengali"]=2492,
+ ["nuktadeva"]=2364,
+ ["nuktagujarati"]=2748,
+ ["nuktagurmukhi"]=2620,
+ ["numbersign"]=35,
+ ["numbersignmonospace"]=65283,
+ ["numbersignsmall"]=65119,
+ ["numeralsigngreek"]=884,
+ ["numeralsignlowergreek"]=885,
+ ["numero"]=8470,
+ ["nun"]=1504,
+ ["nundagesh"]=64320,
+ ["nundageshhebrew"]=64320,
+ ["nunhebrew"]=1504,
+ ["nvsquare"]=13237,
+ ["nwsquare"]=13243,
+ ["nyabengali"]=2462,
+ ["nyadeva"]=2334,
+ ["nyagujarati"]=2718,
+ ["nyagurmukhi"]=2590,
+ ["o"]=111,
+ ["oacute"]=243,
+ ["oangthai"]=3629,
+ ["obarred"]=629,
+ ["obarredcyrillic"]=1257,
+ ["obarreddieresiscyrillic"]=1259,
+ ["obengali"]=2451,
+ ["obopomofo"]=12571,
+ ["obreve"]=335,
+ ["ocandradeva"]=2321,
+ ["ocandragujarati"]=2705,
+ ["ocandravowelsigndeva"]=2377,
+ ["ocandravowelsigngujarati"]=2761,
+ ["ocaron"]=466,
+ ["ocircle"]=9438,
+ ["ocircumflex"]=244,
+ ["ocircumflexacute"]=7889,
+ ["ocircumflexdotbelow"]=7897,
+ ["ocircumflexgrave"]=7891,
+ ["ocircumflexhookabove"]=7893,
+ ["ocircumflextilde"]=7895,
+ ["ocyrillic"]=1086,
+ ["odblacute"]=337,
+ ["odblgrave"]=525,
+ ["odeva"]=2323,
+ ["odieresis"]=246,
+ ["odieresiscyrillic"]=1255,
+ ["odotbelow"]=7885,
+ ["oe"]=339,
+ ["oekorean"]=12634,
+ ["ogonek"]=731,
+ ["ogonekcmb"]=808,
+ ["ograve"]=242,
+ ["ogujarati"]=2707,
+ ["oharmenian"]=1413,
+ ["ohiragana"]=12362,
+ ["ohookabove"]=7887,
+ ["ohorn"]=417,
+ ["ohornacute"]=7899,
+ ["ohorndotbelow"]=7907,
+ ["ohorngrave"]=7901,
+ ["ohornhookabove"]=7903,
+ ["ohorntilde"]=7905,
+ ["ohungarumlaut"]=337,
+ ["oi"]=419,
+ ["oinvertedbreve"]=527,
+ ["okatakana"]=12458,
+ ["okatakanahalfwidth"]=65397,
+ ["okorean"]=12631,
+ ["olehebrew"]=1451,
+ ["omacron"]=333,
+ ["omacronacute"]=7763,
+ ["omacrongrave"]=7761,
+ ["omdeva"]=2384,
+ ["omega"]=969,
+ ["omega1"]=982,
+ ["omegacyrillic"]=1121,
+ ["omegalatinclosed"]=631,
+ ["omegaroundcyrillic"]=1147,
+ ["omegatitlocyrillic"]=1149,
+ ["omegatonos"]=974,
+ ["omgujarati"]=2768,
+ ["omicron"]=959,
+ ["omicrontonos"]=972,
+ ["omonospace"]=65359,
+ ["one"]=49,
+ ["onearabic"]=1633,
+ ["onebengali"]=2535,
+ ["onecircle"]=9312,
+ ["onecircleinversesansserif"]=10122,
+ ["onedeva"]=2407,
+ ["onedotenleader"]=8228,
+ ["oneeighth"]=8539,
+ ["onegujarati"]=2791,
+ ["onegurmukhi"]=2663,
+ ["onehackarabic"]=1633,
+ ["onehalf"]=189,
+ ["onehangzhou"]=12321,
+ ["oneideographicparen"]=12832,
+ ["oneinferior"]=8321,
+ ["onemonospace"]=65297,
+ ["onenumeratorbengali"]=2548,
+ ["oneparen"]=9332,
+ ["oneperiod"]=9352,
+ ["onepersian"]=1777,
+ ["onequarter"]=188,
+ ["oneroman"]=8560,
+ ["onesuperior"]=185,
+ ["onethai"]=3665,
+ ["onethird"]=8531,
+ ["oogonek"]=491,
+ ["oogonekmacron"]=493,
+ ["oogurmukhi"]=2579,
+ ["oomatragurmukhi"]=2635,
+ ["oopen"]=596,
+ ["oparen"]=9386,
+ ["openbullet"]=9702,
+ ["option"]=8997,
+ ["ordfeminine"]=170,
+ ["ordmasculine"]=186,
+ ["orthogonal"]=8735,
+ ["oshortdeva"]=2322,
+ ["oshortvowelsigndeva"]=2378,
+ ["oslash"]=248,
+ ["oslashacute"]=511,
+ ["osmallhiragana"]=12361,
+ ["osmallkatakana"]=12457,
+ ["osmallkatakanahalfwidth"]=65387,
+ ["ostrokeacute"]=511,
+ ["otcyrillic"]=1151,
+ ["otilde"]=245,
+ ["otildeacute"]=7757,
+ ["otildedieresis"]=7759,
+ ["oubopomofo"]=12577,
+ ["overline"]=8254,
+ ["overlinecenterline"]=65098,
+ ["overlinecmb"]=773,
+ ["overlinedashed"]=65097,
+ ["overlinedblwavy"]=65100,
+ ["overlinewavy"]=65099,
+ ["overscore"]=175,
+ ["ovowelsignbengali"]=2507,
+ ["ovowelsigndeva"]=2379,
+ ["ovowelsigngujarati"]=2763,
+ ["p"]=112,
+ ["paampssquare"]=13184,
+ ["paasentosquare"]=13099,
+ ["pabengali"]=2474,
+ ["pacute"]=7765,
+ ["padeva"]=2346,
+ ["pagedown"]=8671,
+ ["pageup"]=8670,
+ ["pagujarati"]=2730,
+ ["pagurmukhi"]=2602,
+ ["pahiragana"]=12401,
+ ["paiyannoithai"]=3631,
+ ["pakatakana"]=12497,
+ ["palatalizationcyrilliccmb"]=1156,
+ ["palochkacyrillic"]=1216,
+ ["pansioskorean"]=12671,
+ ["paragraph"]=182,
+ ["parallel"]=8741,
+ ["parenleft"]=40,
+ ["parenleftaltonearabic"]=64830,
+ ["parenleftinferior"]=8333,
+ ["parenleftmonospace"]=65288,
+ ["parenleftsmall"]=65113,
+ ["parenleftsuperior"]=8317,
+ ["parenleftvertical"]=65077,
+ ["parenright"]=41,
+ ["parenrightaltonearabic"]=64831,
+ ["parenrightinferior"]=8334,
+ ["parenrightmonospace"]=65289,
+ ["parenrightsmall"]=65114,
+ ["parenrightsuperior"]=8318,
+ ["parenrightvertical"]=65078,
+ ["partialdiff"]=8706,
+ ["paseqhebrew"]=1472,
+ ["pashtahebrew"]=1433,
+ ["pasquare"]=13225,
+ ["patah"]=1463,
+ ["patah11"]=1463,
+ ["patah1d"]=1463,
+ ["patah2a"]=1463,
+ ["patahhebrew"]=1463,
+ ["patahnarrowhebrew"]=1463,
+ ["patahquarterhebrew"]=1463,
+ ["patahwidehebrew"]=1463,
+ ["pazerhebrew"]=1441,
+ ["pbopomofo"]=12550,
+ ["pcircle"]=9439,
+ ["pdotaccent"]=7767,
+ ["pe"]=1508,
+ ["pecyrillic"]=1087,
+ ["pedagesh"]=64324,
+ ["pedageshhebrew"]=64324,
+ ["peezisquare"]=13115,
+ ["pefinaldageshhebrew"]=64323,
+ ["peharabic"]=1662,
+ ["peharmenian"]=1402,
+ ["pehebrew"]=1508,
+ ["pehfinalarabic"]=64343,
+ ["pehinitialarabic"]=64344,
+ ["pehiragana"]=12410,
+ ["pehmedialarabic"]=64345,
+ ["pekatakana"]=12506,
+ ["pemiddlehookcyrillic"]=1191,
+ ["perafehebrew"]=64334,
+ ["percent"]=37,
+ ["percentarabic"]=1642,
+ ["percentmonospace"]=65285,
+ ["percentsmall"]=65130,
+ ["period"]=46,
+ ["periodarmenian"]=1417,
+ ["periodcentered"]=183,
+ ["periodhalfwidth"]=65377,
+ ["periodmonospace"]=65294,
+ ["periodsmall"]=65106,
+ ["perispomenigreekcmb"]=834,
+ ["perpendicular"]=8869,
+ ["perthousand"]=8240,
+ ["peseta"]=8359,
+ ["pfsquare"]=13194,
+ ["phabengali"]=2475,
+ ["phadeva"]=2347,
+ ["phagujarati"]=2731,
+ ["phagurmukhi"]=2603,
+ ["phi"]=966,
+ ["phi1"]=981,
+ ["phieuphacirclekorean"]=12922,
+ ["phieuphaparenkorean"]=12826,
+ ["phieuphcirclekorean"]=12908,
+ ["phieuphkorean"]=12621,
+ ["phieuphparenkorean"]=12812,
+ ["philatin"]=632,
+ ["phinthuthai"]=3642,
+ ["phisymbolgreek"]=981,
+ ["phook"]=421,
+ ["phophanthai"]=3614,
+ ["phophungthai"]=3612,
+ ["phosamphaothai"]=3616,
+ ["pi"]=960,
+ ["pieupacirclekorean"]=12915,
+ ["pieupaparenkorean"]=12819,
+ ["pieupcieuckorean"]=12662,
+ ["pieupcirclekorean"]=12901,
+ ["pieupkiyeokkorean"]=12658,
+ ["pieupkorean"]=12610,
+ ["pieupparenkorean"]=12805,
+ ["pieupsioskiyeokkorean"]=12660,
+ ["pieupsioskorean"]=12612,
+ ["pieupsiostikeutkorean"]=12661,
+ ["pieupthieuthkorean"]=12663,
+ ["pieuptikeutkorean"]=12659,
+ ["pihiragana"]=12404,
+ ["pikatakana"]=12500,
+ ["pisymbolgreek"]=982,
+ ["piwrarmenian"]=1411,
+ ["plus"]=43,
+ ["plusbelowcmb"]=799,
+ ["pluscircle"]=8853,
+ ["plusminus"]=177,
+ ["plusmod"]=726,
+ ["plusmonospace"]=65291,
+ ["plussmall"]=65122,
+ ["plussuperior"]=8314,
+ ["pmonospace"]=65360,
+ ["pmsquare"]=13272,
+ ["pohiragana"]=12413,
+ ["pointingindexdownwhite"]=9759,
+ ["pointingindexleftwhite"]=9756,
+ ["pointingindexrightwhite"]=9758,
+ ["pointingindexupwhite"]=9757,
+ ["pokatakana"]=12509,
+ ["poplathai"]=3611,
+ ["postalmark"]=12306,
+ ["postalmarkface"]=12320,
+ ["pparen"]=9387,
+ ["precedes"]=8826,
+ ["prescription"]=8478,
+ ["primemod"]=697,
+ ["primereversed"]=8245,
+ ["product"]=8719,
+ ["projective"]=8965,
+ ["prolongedkana"]=12540,
+ ["propellor"]=8984,
+ ["propersubset"]=8834,
+ ["propersuperset"]=8835,
+ ["proportion"]=8759,
+ ["proportional"]=8733,
+ ["psi"]=968,
+ ["psicyrillic"]=1137,
+ ["psilipneumatacyrilliccmb"]=1158,
+ ["pssquare"]=13232,
+ ["puhiragana"]=12407,
+ ["pukatakana"]=12503,
+ ["pvsquare"]=13236,
+ ["pwsquare"]=13242,
+ ["q"]=113,
+ ["qadeva"]=2392,
+ ["qadmahebrew"]=1448,
+ ["qafarabic"]=1602,
+ ["qaffinalarabic"]=65238,
+ ["qafinitialarabic"]=65239,
+ ["qafmedialarabic"]=65240,
+ ["qamats"]=1464,
+ ["qamats10"]=1464,
+ ["qamats1a"]=1464,
+ ["qamats1c"]=1464,
+ ["qamats27"]=1464,
+ ["qamats29"]=1464,
+ ["qamats33"]=1464,
+ ["qamatsde"]=1464,
+ ["qamatshebrew"]=1464,
+ ["qamatsnarrowhebrew"]=1464,
+ ["qamatsqatanhebrew"]=1464,
+ ["qamatsqatannarrowhebrew"]=1464,
+ ["qamatsqatanquarterhebrew"]=1464,
+ ["qamatsqatanwidehebrew"]=1464,
+ ["qamatsquarterhebrew"]=1464,
+ ["qamatswidehebrew"]=1464,
+ ["qarneyparahebrew"]=1439,
+ ["qbopomofo"]=12561,
+ ["qcircle"]=9440,
+ ["qhook"]=672,
+ ["qmonospace"]=65361,
+ ["qof"]=1511,
+ ["qofdagesh"]=64327,
+ ["qofdageshhebrew"]=64327,
+ ["qofhatafpatah"]=1511,
+ ["qofhatafpatahhebrew"]=1511,
+ ["qofhatafsegol"]=1511,
+ ["qofhatafsegolhebrew"]=1511,
+ ["qofhebrew"]=1511,
+ ["qofhiriq"]=1511,
+ ["qofhiriqhebrew"]=1511,
+ ["qofholam"]=1511,
+ ["qofholamhebrew"]=1511,
+ ["qofpatah"]=1511,
+ ["qofpatahhebrew"]=1511,
+ ["qofqamats"]=1511,
+ ["qofqamatshebrew"]=1511,
+ ["qofqubuts"]=1511,
+ ["qofqubutshebrew"]=1511,
+ ["qofsegol"]=1511,
+ ["qofsegolhebrew"]=1511,
+ ["qofsheva"]=1511,
+ ["qofshevahebrew"]=1511,
+ ["qoftsere"]=1511,
+ ["qoftserehebrew"]=1511,
+ ["qparen"]=9388,
+ ["quarternote"]=9833,
+ ["qubuts"]=1467,
+ ["qubuts18"]=1467,
+ ["qubuts25"]=1467,
+ ["qubuts31"]=1467,
+ ["qubutshebrew"]=1467,
+ ["qubutsnarrowhebrew"]=1467,
+ ["qubutsquarterhebrew"]=1467,
+ ["qubutswidehebrew"]=1467,
+ ["question"]=63,
+ ["questionarabic"]=1567,
+ ["questionarmenian"]=1374,
+ ["questiondown"]=191,
+ ["questiongreek"]=894,
+ ["questionmonospace"]=65311,
+ ["quotedbl"]=34,
+ ["quotedblbase"]=8222,
+ ["quotedblleft"]=8220,
+ ["quotedblmonospace"]=65282,
+ ["quotedblprime"]=12318,
+ ["quotedblprimereversed"]=12317,
+ ["quotedblright"]=8221,
+ ["quoteleft"]=8216,
+ ["quoteleftreversed"]=8219,
+ ["quotereversed"]=8219,
+ ["quoteright"]=8217,
+ ["quoterightn"]=329,
+ ["quotesinglbase"]=8218,
+ ["quotesingle"]=39,
+ ["quotesinglemonospace"]=65287,
+ ["r"]=114,
+ ["raarmenian"]=1404,
+ ["rabengali"]=2480,
+ ["racute"]=341,
+ ["radeva"]=2352,
+ ["radical"]=8730,
+ ["radoverssquare"]=13230,
+ ["radoverssquaredsquare"]=13231,
+ ["radsquare"]=13229,
+ ["rafe"]=1471,
+ ["rafehebrew"]=1471,
+ ["ragujarati"]=2736,
+ ["ragurmukhi"]=2608,
+ ["rahiragana"]=12425,
+ ["rakatakana"]=12521,
+ ["rakatakanahalfwidth"]=65431,
+ ["ralowerdiagonalbengali"]=2545,
+ ["ramiddlediagonalbengali"]=2544,
+ ["ramshorn"]=612,
+ ["ratio"]=8758,
+ ["rbopomofo"]=12566,
+ ["rcaron"]=345,
+ ["rcedilla"]=343,
+ ["rcircle"]=9441,
+ ["rcommaaccent"]=343,
+ ["rdblgrave"]=529,
+ ["rdotaccent"]=7769,
+ ["rdotbelow"]=7771,
+ ["rdotbelowmacron"]=7773,
+ ["referencemark"]=8251,
+ ["reflexsubset"]=8838,
+ ["reflexsuperset"]=8839,
+ ["registered"]=174,
+ ["reharabic"]=1585,
+ ["reharmenian"]=1408,
+ ["rehfinalarabic"]=65198,
+ ["rehiragana"]=12428,
+ ["rehyehaleflamarabic"]=1585,
+ ["rekatakana"]=12524,
+ ["rekatakanahalfwidth"]=65434,
+ ["resh"]=1512,
+ ["reshdageshhebrew"]=64328,
+ ["reshhatafpatah"]=1512,
+ ["reshhatafpatahhebrew"]=1512,
+ ["reshhatafsegol"]=1512,
+ ["reshhatafsegolhebrew"]=1512,
+ ["reshhebrew"]=1512,
+ ["reshhiriq"]=1512,
+ ["reshhiriqhebrew"]=1512,
+ ["reshholam"]=1512,
+ ["reshholamhebrew"]=1512,
+ ["reshpatah"]=1512,
+ ["reshpatahhebrew"]=1512,
+ ["reshqamats"]=1512,
+ ["reshqamatshebrew"]=1512,
+ ["reshqubuts"]=1512,
+ ["reshqubutshebrew"]=1512,
+ ["reshsegol"]=1512,
+ ["reshsegolhebrew"]=1512,
+ ["reshsheva"]=1512,
+ ["reshshevahebrew"]=1512,
+ ["reshtsere"]=1512,
+ ["reshtserehebrew"]=1512,
+ ["reversedtilde"]=8765,
+ ["reviahebrew"]=1431,
+ ["reviamugrashhebrew"]=1431,
+ ["revlogicalnot"]=8976,
+ ["rfishhook"]=638,
+ ["rfishhookreversed"]=639,
+ ["rhabengali"]=2525,
+ ["rhadeva"]=2397,
+ ["rho"]=961,
+ ["rhook"]=637,
+ ["rhookturned"]=635,
+ ["rhookturnedsuperior"]=693,
+ ["rhosymbolgreek"]=1009,
+ ["rhotichookmod"]=734,
+ ["rieulacirclekorean"]=12913,
+ ["rieulaparenkorean"]=12817,
+ ["rieulcirclekorean"]=12899,
+ ["rieulhieuhkorean"]=12608,
+ ["rieulkiyeokkorean"]=12602,
+ ["rieulkiyeoksioskorean"]=12649,
+ ["rieulkorean"]=12601,
+ ["rieulmieumkorean"]=12603,
+ ["rieulpansioskorean"]=12652,
+ ["rieulparenkorean"]=12803,
+ ["rieulphieuphkorean"]=12607,
+ ["rieulpieupkorean"]=12604,
+ ["rieulpieupsioskorean"]=12651,
+ ["rieulsioskorean"]=12605,
+ ["rieulthieuthkorean"]=12606,
+ ["rieultikeutkorean"]=12650,
+ ["rieulyeorinhieuhkorean"]=12653,
+ ["rightangle"]=8735,
+ ["righttackbelowcmb"]=793,
+ ["righttriangle"]=8895,
+ ["rihiragana"]=12426,
+ ["rikatakana"]=12522,
+ ["rikatakanahalfwidth"]=65432,
+ ["ring"]=730,
+ ["ringbelowcmb"]=805,
+ ["ringcmb"]=778,
+ ["ringhalfleft"]=703,
+ ["ringhalfleftarmenian"]=1369,
+ ["ringhalfleftbelowcmb"]=796,
+ ["ringhalfleftcentered"]=723,
+ ["ringhalfright"]=702,
+ ["ringhalfrightbelowcmb"]=825,
+ ["ringhalfrightcentered"]=722,
+ ["rinvertedbreve"]=531,
+ ["rittorusquare"]=13137,
+ ["rlinebelow"]=7775,
+ ["rlongleg"]=636,
+ ["rlonglegturned"]=634,
+ ["rmonospace"]=65362,
+ ["rohiragana"]=12429,
+ ["rokatakana"]=12525,
+ ["rokatakanahalfwidth"]=65435,
+ ["roruathai"]=3619,
+ ["rparen"]=9389,
+ ["rrabengali"]=2524,
+ ["rradeva"]=2353,
+ ["rragurmukhi"]=2652,
+ ["rreharabic"]=1681,
+ ["rrehfinalarabic"]=64397,
+ ["rrvocalicbengali"]=2528,
+ ["rrvocalicdeva"]=2400,
+ ["rrvocalicgujarati"]=2784,
+ ["rrvocalicvowelsignbengali"]=2500,
+ ["rrvocalicvowelsigndeva"]=2372,
+ ["rrvocalicvowelsigngujarati"]=2756,
+ ["rtblock"]=9616,
+ ["rturned"]=633,
+ ["rturnedsuperior"]=692,
+ ["ruhiragana"]=12427,
+ ["rukatakana"]=12523,
+ ["rukatakanahalfwidth"]=65433,
+ ["rupeemarkbengali"]=2546,
+ ["rupeesignbengali"]=2547,
+ ["ruthai"]=3620,
+ ["rvocalicbengali"]=2443,
+ ["rvocalicdeva"]=2315,
+ ["rvocalicgujarati"]=2699,
+ ["rvocalicvowelsignbengali"]=2499,
+ ["rvocalicvowelsigndeva"]=2371,
+ ["rvocalicvowelsigngujarati"]=2755,
+ ["s"]=115,
+ ["sabengali"]=2488,
+ ["sacute"]=347,
+ ["sacutedotaccent"]=7781,
+ ["sadarabic"]=1589,
+ ["sadeva"]=2360,
+ ["sadfinalarabic"]=65210,
+ ["sadinitialarabic"]=65211,
+ ["sadmedialarabic"]=65212,
+ ["sagujarati"]=2744,
+ ["sagurmukhi"]=2616,
+ ["sahiragana"]=12373,
+ ["sakatakana"]=12469,
+ ["sakatakanahalfwidth"]=65403,
+ ["sallallahoualayhewasallamarabic"]=65018,
+ ["samekh"]=1505,
+ ["samekhdagesh"]=64321,
+ ["samekhdageshhebrew"]=64321,
+ ["samekhhebrew"]=1505,
+ ["saraaathai"]=3634,
+ ["saraaethai"]=3649,
+ ["saraaimaimalaithai"]=3652,
+ ["saraaimaimuanthai"]=3651,
+ ["saraamthai"]=3635,
+ ["saraathai"]=3632,
+ ["saraethai"]=3648,
+ ["saraiithai"]=3637,
+ ["saraithai"]=3636,
+ ["saraothai"]=3650,
+ ["saraueethai"]=3639,
+ ["sarauethai"]=3638,
+ ["sarauthai"]=3640,
+ ["sarauuthai"]=3641,
+ ["sbopomofo"]=12569,
+ ["scaron"]=353,
+ ["scarondotaccent"]=7783,
+ ["scedilla"]=351,
+ ["schwa"]=601,
+ ["schwacyrillic"]=1241,
+ ["schwadieresiscyrillic"]=1243,
+ ["schwahook"]=602,
+ ["scircle"]=9442,
+ ["scircumflex"]=349,
+ ["scommaaccent"]=537,
+ ["sdotaccent"]=7777,
+ ["sdotbelow"]=7779,
+ ["sdotbelowdotaccent"]=7785,
+ ["seagullbelowcmb"]=828,
+ ["second"]=8243,
+ ["secondtonechinese"]=714,
+ ["section"]=167,
+ ["seenarabic"]=1587,
+ ["seenfinalarabic"]=65202,
+ ["seeninitialarabic"]=65203,
+ ["seenmedialarabic"]=65204,
+ ["segol"]=1462,
+ ["segol13"]=1462,
+ ["segol1f"]=1462,
+ ["segol2c"]=1462,
+ ["segolhebrew"]=1462,
+ ["segolnarrowhebrew"]=1462,
+ ["segolquarterhebrew"]=1462,
+ ["segoltahebrew"]=1426,
+ ["segolwidehebrew"]=1462,
+ ["seharmenian"]=1405,
+ ["sehiragana"]=12379,
+ ["sekatakana"]=12475,
+ ["sekatakanahalfwidth"]=65406,
+ ["semicolon"]=59,
+ ["semicolonarabic"]=1563,
+ ["semicolonmonospace"]=65307,
+ ["semicolonsmall"]=65108,
+ ["semivoicedmarkkana"]=12444,
+ ["semivoicedmarkkanahalfwidth"]=65439,
+ ["sentisquare"]=13090,
+ ["sentosquare"]=13091,
+ ["seven"]=55,
+ ["sevenarabic"]=1639,
+ ["sevenbengali"]=2541,
+ ["sevencircle"]=9318,
+ ["sevencircleinversesansserif"]=10128,
+ ["sevendeva"]=2413,
+ ["seveneighths"]=8542,
+ ["sevengujarati"]=2797,
+ ["sevengurmukhi"]=2669,
+ ["sevenhackarabic"]=1639,
+ ["sevenhangzhou"]=12327,
+ ["sevenideographicparen"]=12838,
+ ["seveninferior"]=8327,
+ ["sevenmonospace"]=65303,
+ ["sevenparen"]=9338,
+ ["sevenperiod"]=9358,
+ ["sevenpersian"]=1783,
+ ["sevenroman"]=8566,
+ ["sevensuperior"]=8311,
+ ["seventeencircle"]=9328,
+ ["seventeenparen"]=9348,
+ ["seventeenperiod"]=9368,
+ ["seventhai"]=3671,
+ ["sfthyphen"]=173,
+ ["shaarmenian"]=1399,
+ ["shabengali"]=2486,
+ ["shacyrillic"]=1096,
+ ["shaddaarabic"]=1617,
+ ["shaddadammaarabic"]=64609,
+ ["shaddadammatanarabic"]=64606,
+ ["shaddafathaarabic"]=64608,
+ ["shaddafathatanarabic"]=1617,
+ ["shaddakasraarabic"]=64610,
+ ["shaddakasratanarabic"]=64607,
+ ["shade"]=9618,
+ ["shadedark"]=9619,
+ ["shadelight"]=9617,
+ ["shademedium"]=9618,
+ ["shadeva"]=2358,
+ ["shagujarati"]=2742,
+ ["shagurmukhi"]=2614,
+ ["shalshelethebrew"]=1427,
+ ["shbopomofo"]=12565,
+ ["shchacyrillic"]=1097,
+ ["sheenarabic"]=1588,
+ ["sheenfinalarabic"]=65206,
+ ["sheeninitialarabic"]=65207,
+ ["sheenmedialarabic"]=65208,
+ ["sheicoptic"]=995,
+ ["sheqel"]=8362,
+ ["sheqelhebrew"]=8362,
+ ["sheva"]=1456,
+ ["sheva115"]=1456,
+ ["sheva15"]=1456,
+ ["sheva22"]=1456,
+ ["sheva2e"]=1456,
+ ["shevahebrew"]=1456,
+ ["shevanarrowhebrew"]=1456,
+ ["shevaquarterhebrew"]=1456,
+ ["shevawidehebrew"]=1456,
+ ["shhacyrillic"]=1211,
+ ["shimacoptic"]=1005,
+ ["shin"]=1513,
+ ["shindagesh"]=64329,
+ ["shindageshhebrew"]=64329,
+ ["shindageshshindot"]=64300,
+ ["shindageshshindothebrew"]=64300,
+ ["shindageshsindot"]=64301,
+ ["shindageshsindothebrew"]=64301,
+ ["shindothebrew"]=1473,
+ ["shinhebrew"]=1513,
+ ["shinshindot"]=64298,
+ ["shinshindothebrew"]=64298,
+ ["shinsindot"]=64299,
+ ["shinsindothebrew"]=64299,
+ ["shook"]=642,
+ ["sigma"]=963,
+ ["sigma1"]=962,
+ ["sigmafinal"]=962,
+ ["sigmalunatesymbolgreek"]=1010,
+ ["sihiragana"]=12375,
+ ["sikatakana"]=12471,
+ ["sikatakanahalfwidth"]=65404,
+ ["siluqhebrew"]=1469,
+ ["siluqlefthebrew"]=1469,
+ ["similar"]=8764,
+ ["sindothebrew"]=1474,
+ ["siosacirclekorean"]=12916,
+ ["siosaparenkorean"]=12820,
+ ["sioscieuckorean"]=12670,
+ ["sioscirclekorean"]=12902,
+ ["sioskiyeokkorean"]=12666,
+ ["sioskorean"]=12613,
+ ["siosnieunkorean"]=12667,
+ ["siosparenkorean"]=12806,
+ ["siospieupkorean"]=12669,
+ ["siostikeutkorean"]=12668,
+ ["six"]=54,
+ ["sixarabic"]=1638,
+ ["sixbengali"]=2540,
+ ["sixcircle"]=9317,
+ ["sixcircleinversesansserif"]=10127,
+ ["sixdeva"]=2412,
+ ["sixgujarati"]=2796,
+ ["sixgurmukhi"]=2668,
+ ["sixhackarabic"]=1638,
+ ["sixhangzhou"]=12326,
+ ["sixideographicparen"]=12837,
+ ["sixinferior"]=8326,
+ ["sixmonospace"]=65302,
+ ["sixparen"]=9337,
+ ["sixperiod"]=9357,
+ ["sixpersian"]=1782,
+ ["sixroman"]=8565,
+ ["sixsuperior"]=8310,
+ ["sixteencircle"]=9327,
+ ["sixteencurrencydenominatorbengali"]=2553,
+ ["sixteenparen"]=9347,
+ ["sixteenperiod"]=9367,
+ ["sixthai"]=3670,
+ ["slash"]=47,
+ ["slashmonospace"]=65295,
+ ["slong"]=383,
+ ["slongdotaccent"]=7835,
+ ["smileface"]=9786,
+ ["smonospace"]=65363,
+ ["sofpasuqhebrew"]=1475,
+ ["softhyphen"]=173,
+ ["softsigncyrillic"]=1100,
+ ["sohiragana"]=12381,
+ ["sokatakana"]=12477,
+ ["sokatakanahalfwidth"]=65407,
+ ["soliduslongoverlaycmb"]=824,
+ ["solidusshortoverlaycmb"]=823,
+ ["sorusithai"]=3625,
+ ["sosalathai"]=3624,
+ ["sosothai"]=3595,
+ ["sosuathai"]=3626,
+ ["space"]=32,
+ ["spacehackarabic"]=32,
+ ["spade"]=9824,
+ ["spadesuitblack"]=9824,
+ ["spadesuitwhite"]=9828,
+ ["sparen"]=9390,
+ ["squarebelowcmb"]=827,
+ ["squarecc"]=13252,
+ ["squarecm"]=13213,
+ ["squarediagonalcrosshatchfill"]=9641,
+ ["squarehorizontalfill"]=9636,
+ ["squarekg"]=13199,
+ ["squarekm"]=13214,
+ ["squarekmcapital"]=13262,
+ ["squareln"]=13265,
+ ["squarelog"]=13266,
+ ["squaremg"]=13198,
+ ["squaremil"]=13269,
+ ["squaremm"]=13212,
+ ["squaremsquared"]=13217,
+ ["squareorthogonalcrosshatchfill"]=9638,
+ ["squareupperlefttolowerrightfill"]=9639,
+ ["squareupperrighttolowerleftfill"]=9640,
+ ["squareverticalfill"]=9637,
+ ["squarewhitewithsmallblack"]=9635,
+ ["srsquare"]=13275,
+ ["ssabengali"]=2487,
+ ["ssadeva"]=2359,
+ ["ssagujarati"]=2743,
+ ["ssangcieuckorean"]=12617,
+ ["ssanghieuhkorean"]=12677,
+ ["ssangieungkorean"]=12672,
+ ["ssangkiyeokkorean"]=12594,
+ ["ssangnieunkorean"]=12645,
+ ["ssangpieupkorean"]=12611,
+ ["ssangsioskorean"]=12614,
+ ["ssangtikeutkorean"]=12600,
+ ["sterling"]=163,
+ ["sterlingmonospace"]=65505,
+ ["strokelongoverlaycmb"]=822,
+ ["strokeshortoverlaycmb"]=821,
+ ["subset"]=8834,
+ ["subsetnotequal"]=8842,
+ ["subsetorequal"]=8838,
+ ["succeeds"]=8827,
+ ["suchthat"]=8715,
+ ["suhiragana"]=12377,
+ ["sukatakana"]=12473,
+ ["sukatakanahalfwidth"]=65405,
+ ["sukunarabic"]=1618,
+ ["summation"]=8721,
+ ["sun"]=9788,
+ ["superset"]=8835,
+ ["supersetnotequal"]=8843,
+ ["supersetorequal"]=8839,
+ ["svsquare"]=13276,
+ ["syouwaerasquare"]=13180,
+ ["t"]=116,
+ ["tabengali"]=2468,
+ ["tackdown"]=8868,
+ ["tackleft"]=8867,
+ ["tadeva"]=2340,
+ ["tagujarati"]=2724,
+ ["tagurmukhi"]=2596,
+ ["taharabic"]=1591,
+ ["tahfinalarabic"]=65218,
+ ["tahinitialarabic"]=65219,
+ ["tahiragana"]=12383,
+ ["tahmedialarabic"]=65220,
+ ["taisyouerasquare"]=13181,
+ ["takatakana"]=12479,
+ ["takatakanahalfwidth"]=65408,
+ ["tatweelarabic"]=1600,
+ ["tau"]=964,
+ ["tav"]=1514,
+ ["tavdages"]=64330,
+ ["tavdagesh"]=64330,
+ ["tavdageshhebrew"]=64330,
+ ["tavhebrew"]=1514,
+ ["tbar"]=359,
+ ["tbopomofo"]=12554,
+ ["tcaron"]=357,
+ ["tccurl"]=680,
+ ["tcedilla"]=355,
+ ["tcheharabic"]=1670,
+ ["tchehfinalarabic"]=64379,
+ ["tchehinitialarabic"]=64380,
+ ["tchehmedialarabic"]=64381,
+ ["tchehmeeminitialarabic"]=64380,
+ ["tcircle"]=9443,
+ ["tcircumflexbelow"]=7793,
+ ["tcommaaccent"]=355,
+ ["tdieresis"]=7831,
+ ["tdotaccent"]=7787,
+ ["tdotbelow"]=7789,
+ ["tecyrillic"]=1090,
+ ["tedescendercyrillic"]=1197,
+ ["teharabic"]=1578,
+ ["tehfinalarabic"]=65174,
+ ["tehhahinitialarabic"]=64674,
+ ["tehhahisolatedarabic"]=64524,
+ ["tehinitialarabic"]=65175,
+ ["tehiragana"]=12390,
+ ["tehjeeminitialarabic"]=64673,
+ ["tehjeemisolatedarabic"]=64523,
+ ["tehmarbutaarabic"]=1577,
+ ["tehmarbutafinalarabic"]=65172,
+ ["tehmedialarabic"]=65176,
+ ["tehmeeminitialarabic"]=64676,
+ ["tehmeemisolatedarabic"]=64526,
+ ["tehnoonfinalarabic"]=64627,
+ ["tekatakana"]=12486,
+ ["tekatakanahalfwidth"]=65411,
+ ["telephone"]=8481,
+ ["telephoneblack"]=9742,
+ ["telishagedolahebrew"]=1440,
+ ["telishaqetanahebrew"]=1449,
+ ["tencircle"]=9321,
+ ["tenideographicparen"]=12841,
+ ["tenparen"]=9341,
+ ["tenperiod"]=9361,
+ ["tenroman"]=8569,
+ ["tesh"]=679,
+ ["tet"]=1496,
+ ["tetdagesh"]=64312,
+ ["tetdageshhebrew"]=64312,
+ ["tethebrew"]=1496,
+ ["tetsecyrillic"]=1205,
+ ["tevirhebrew"]=1435,
+ ["tevirlefthebrew"]=1435,
+ ["thabengali"]=2469,
+ ["thadeva"]=2341,
+ ["thagujarati"]=2725,
+ ["thagurmukhi"]=2597,
+ ["thalarabic"]=1584,
+ ["thalfinalarabic"]=65196,
+ ["thanthakhatthai"]=3660,
+ ["theharabic"]=1579,
+ ["thehfinalarabic"]=65178,
+ ["thehinitialarabic"]=65179,
+ ["thehmedialarabic"]=65180,
+ ["thereexists"]=8707,
+ ["therefore"]=8756,
+ ["theta"]=952,
+ ["theta1"]=977,
+ ["thetasymbolgreek"]=977,
+ ["thieuthacirclekorean"]=12921,
+ ["thieuthaparenkorean"]=12825,
+ ["thieuthcirclekorean"]=12907,
+ ["thieuthkorean"]=12620,
+ ["thieuthparenkorean"]=12811,
+ ["thirteencircle"]=9324,
+ ["thirteenparen"]=9344,
+ ["thirteenperiod"]=9364,
+ ["thonangmonthothai"]=3601,
+ ["thook"]=429,
+ ["thophuthaothai"]=3602,
+ ["thorn"]=254,
+ ["thothahanthai"]=3607,
+ ["thothanthai"]=3600,
+ ["thothongthai"]=3608,
+ ["thothungthai"]=3606,
+ ["thousandcyrillic"]=1154,
+ ["thousandsseparatorarabic"]=1644,
+ ["thousandsseparatorpersian"]=1644,
+ ["three"]=51,
+ ["threearabic"]=1635,
+ ["threebengali"]=2537,
+ ["threecircle"]=9314,
+ ["threecircleinversesansserif"]=10124,
+ ["threedeva"]=2409,
+ ["threeeighths"]=8540,
+ ["threegujarati"]=2793,
+ ["threegurmukhi"]=2665,
+ ["threehackarabic"]=1635,
+ ["threehangzhou"]=12323,
+ ["threeideographicparen"]=12834,
+ ["threeinferior"]=8323,
+ ["threemonospace"]=65299,
+ ["threenumeratorbengali"]=2550,
+ ["threeparen"]=9334,
+ ["threeperiod"]=9354,
+ ["threepersian"]=1779,
+ ["threequarters"]=190,
+ ["threeroman"]=8562,
+ ["threesuperior"]=179,
+ ["threethai"]=3667,
+ ["thzsquare"]=13204,
+ ["tihiragana"]=12385,
+ ["tikatakana"]=12481,
+ ["tikatakanahalfwidth"]=65409,
+ ["tikeutacirclekorean"]=12912,
+ ["tikeutaparenkorean"]=12816,
+ ["tikeutcirclekorean"]=12898,
+ ["tikeutkorean"]=12599,
+ ["tikeutparenkorean"]=12802,
+ ["tilde"]=732,
+ ["tildebelowcmb"]=816,
+ ["tildecmb"]=771,
+ ["tildecomb"]=771,
+ ["tildedoublecmb"]=864,
+ ["tildeoperator"]=8764,
+ ["tildeoverlaycmb"]=820,
+ ["tildeverticalcmb"]=830,
+ ["timescircle"]=8855,
+ ["tipehahebrew"]=1430,
+ ["tipehalefthebrew"]=1430,
+ ["tippigurmukhi"]=2672,
+ ["titlocyrilliccmb"]=1155,
+ ["tiwnarmenian"]=1407,
+ ["tlinebelow"]=7791,
+ ["tmonospace"]=65364,
+ ["toarmenian"]=1385,
+ ["tohiragana"]=12392,
+ ["tokatakana"]=12488,
+ ["tokatakanahalfwidth"]=65412,
+ ["tonebarextrahighmod"]=741,
+ ["tonebarextralowmod"]=745,
+ ["tonebarhighmod"]=742,
+ ["tonebarlowmod"]=744,
+ ["tonebarmidmod"]=743,
+ ["tonefive"]=445,
+ ["tonesix"]=389,
+ ["tonetwo"]=424,
+ ["tonos"]=900,
+ ["tonsquare"]=13095,
+ ["topatakthai"]=3599,
+ ["tortoiseshellbracketleft"]=12308,
+ ["tortoiseshellbracketleftsmall"]=65117,
+ ["tortoiseshellbracketleftvertical"]=65081,
+ ["tortoiseshellbracketright"]=12309,
+ ["tortoiseshellbracketrightsmall"]=65118,
+ ["tortoiseshellbracketrightvertical"]=65082,
+ ["totaothai"]=3605,
+ ["tpalatalhook"]=427,
+ ["tparen"]=9391,
+ ["trademark"]=8482,
+ ["tretroflexhook"]=648,
+ ["triagdn"]=9660,
+ ["triaglf"]=9668,
+ ["triagrt"]=9658,
+ ["triagup"]=9650,
+ ["ts"]=678,
+ ["tsadi"]=1510,
+ ["tsadidagesh"]=64326,
+ ["tsadidageshhebrew"]=64326,
+ ["tsadihebrew"]=1510,
+ ["tsecyrillic"]=1094,
+ ["tsere"]=1461,
+ ["tsere12"]=1461,
+ ["tsere1e"]=1461,
+ ["tsere2b"]=1461,
+ ["tserehebrew"]=1461,
+ ["tserenarrowhebrew"]=1461,
+ ["tserequarterhebrew"]=1461,
+ ["tserewidehebrew"]=1461,
+ ["tshecyrillic"]=1115,
+ ["ttabengali"]=2463,
+ ["ttadeva"]=2335,
+ ["ttagujarati"]=2719,
+ ["ttagurmukhi"]=2591,
+ ["tteharabic"]=1657,
+ ["ttehfinalarabic"]=64359,
+ ["ttehinitialarabic"]=64360,
+ ["ttehmedialarabic"]=64361,
+ ["tthabengali"]=2464,
+ ["tthadeva"]=2336,
+ ["tthagujarati"]=2720,
+ ["tthagurmukhi"]=2592,
+ ["tturned"]=647,
+ ["tuhiragana"]=12388,
+ ["tukatakana"]=12484,
+ ["tukatakanahalfwidth"]=65410,
+ ["tusmallhiragana"]=12387,
+ ["tusmallkatakana"]=12483,
+ ["tusmallkatakanahalfwidth"]=65391,
+ ["twelvecircle"]=9323,
+ ["twelveparen"]=9343,
+ ["twelveperiod"]=9363,
+ ["twelveroman"]=8571,
+ ["twentycircle"]=9331,
+ ["twentyparen"]=9351,
+ ["twentyperiod"]=9371,
+ ["two"]=50,
+ ["twoarabic"]=1634,
+ ["twobengali"]=2536,
+ ["twocircle"]=9313,
+ ["twocircleinversesansserif"]=10123,
+ ["twodeva"]=2408,
+ ["twodotenleader"]=8229,
+ ["twodotleader"]=8229,
+ ["twodotleadervertical"]=65072,
+ ["twogujarati"]=2792,
+ ["twogurmukhi"]=2664,
+ ["twohackarabic"]=1634,
+ ["twohangzhou"]=12322,
+ ["twoideographicparen"]=12833,
+ ["twoinferior"]=8322,
+ ["twomonospace"]=65298,
+ ["twonumeratorbengali"]=2549,
+ ["twoparen"]=9333,
+ ["twoperiod"]=9353,
+ ["twopersian"]=1778,
+ ["tworoman"]=8561,
+ ["twostroke"]=443,
+ ["twosuperior"]=178,
+ ["twothai"]=3666,
+ ["twothirds"]=8532,
+ ["u"]=117,
+ ["uacute"]=250,
+ ["ubar"]=649,
+ ["ubengali"]=2441,
+ ["ubopomofo"]=12584,
+ ["ubreve"]=365,
+ ["ucaron"]=468,
+ ["ucircle"]=9444,
+ ["ucircumflex"]=251,
+ ["ucircumflexbelow"]=7799,
+ ["ucyrillic"]=1091,
+ ["udattadeva"]=2385,
+ ["udblacute"]=369,
+ ["udblgrave"]=533,
+ ["udeva"]=2313,
+ ["udieresis"]=252,
+ ["udieresisacute"]=472,
+ ["udieresisbelow"]=7795,
+ ["udieresiscaron"]=474,
+ ["udieresiscyrillic"]=1265,
+ ["udieresisgrave"]=476,
+ ["udieresismacron"]=470,
+ ["udotbelow"]=7909,
+ ["ugrave"]=249,
+ ["ugujarati"]=2697,
+ ["ugurmukhi"]=2569,
+ ["uhiragana"]=12358,
+ ["uhookabove"]=7911,
+ ["uhorn"]=432,
+ ["uhornacute"]=7913,
+ ["uhorndotbelow"]=7921,
+ ["uhorngrave"]=7915,
+ ["uhornhookabove"]=7917,
+ ["uhorntilde"]=7919,
+ ["uhungarumlaut"]=369,
+ ["uhungarumlautcyrillic"]=1267,
+ ["uinvertedbreve"]=535,
+ ["ukatakana"]=12454,
+ ["ukatakanahalfwidth"]=65395,
+ ["ukcyrillic"]=1145,
+ ["ukorean"]=12636,
+ ["umacron"]=363,
+ ["umacroncyrillic"]=1263,
+ ["umacrondieresis"]=7803,
+ ["umatragurmukhi"]=2625,
+ ["umonospace"]=65365,
+ ["underscore"]=95,
+ ["underscoredbl"]=8215,
+ ["underscoremonospace"]=65343,
+ ["underscorevertical"]=65075,
+ ["underscorewavy"]=65103,
+ ["union"]=8746,
+ ["universal"]=8704,
+ ["uogonek"]=371,
+ ["uparen"]=9392,
+ ["upblock"]=9600,
+ ["upperdothebrew"]=1476,
+ ["upsilon"]=965,
+ ["upsilondieresis"]=971,
+ ["upsilondieresistonos"]=944,
+ ["upsilonlatin"]=650,
+ ["upsilontonos"]=973,
+ ["uptackbelowcmb"]=797,
+ ["uptackmod"]=724,
+ ["uragurmukhi"]=2675,
+ ["uring"]=367,
+ ["ushortcyrillic"]=1118,
+ ["usmallhiragana"]=12357,
+ ["usmallkatakana"]=12453,
+ ["usmallkatakanahalfwidth"]=65385,
+ ["ustraightcyrillic"]=1199,
+ ["ustraightstrokecyrillic"]=1201,
+ ["utilde"]=361,
+ ["utildeacute"]=7801,
+ ["utildebelow"]=7797,
+ ["uubengali"]=2442,
+ ["uudeva"]=2314,
+ ["uugujarati"]=2698,
+ ["uugurmukhi"]=2570,
+ ["uumatragurmukhi"]=2626,
+ ["uuvowelsignbengali"]=2498,
+ ["uuvowelsigndeva"]=2370,
+ ["uuvowelsigngujarati"]=2754,
+ ["uvowelsignbengali"]=2497,
+ ["uvowelsigndeva"]=2369,
+ ["uvowelsigngujarati"]=2753,
+ ["v"]=118,
+ ["vadeva"]=2357,
+ ["vagujarati"]=2741,
+ ["vagurmukhi"]=2613,
+ ["vakatakana"]=12535,
+ ["vav"]=1493,
+ ["vavdagesh"]=64309,
+ ["vavdagesh65"]=64309,
+ ["vavdageshhebrew"]=64309,
+ ["vavhebrew"]=1493,
+ ["vavholam"]=64331,
+ ["vavholamhebrew"]=64331,
+ ["vavvavhebrew"]=1520,
+ ["vavyodhebrew"]=1521,
+ ["vcircle"]=9445,
+ ["vdotbelow"]=7807,
+ ["vecyrillic"]=1074,
+ ["veharabic"]=1700,
+ ["vehfinalarabic"]=64363,
+ ["vehinitialarabic"]=64364,
+ ["vehmedialarabic"]=64365,
+ ["vekatakana"]=12537,
+ ["venus"]=9792,
+ ["verticalbar"]=124,
+ ["verticallineabovecmb"]=781,
+ ["verticallinebelowcmb"]=809,
+ ["verticallinelowmod"]=716,
+ ["verticallinemod"]=712,
+ ["vewarmenian"]=1406,
+ ["vhook"]=651,
+ ["vikatakana"]=12536,
+ ["viramabengali"]=2509,
+ ["viramadeva"]=2381,
+ ["viramagujarati"]=2765,
+ ["visargabengali"]=2435,
+ ["visargadeva"]=2307,
+ ["visargagujarati"]=2691,
+ ["vmonospace"]=65366,
+ ["voarmenian"]=1400,
+ ["voicediterationhiragana"]=12446,
+ ["voicediterationkatakana"]=12542,
+ ["voicedmarkkana"]=12443,
+ ["voicedmarkkanahalfwidth"]=65438,
+ ["vokatakana"]=12538,
+ ["vparen"]=9393,
+ ["vtilde"]=7805,
+ ["vturned"]=652,
+ ["vuhiragana"]=12436,
+ ["vukatakana"]=12532,
+ ["w"]=119,
+ ["wacute"]=7811,
+ ["waekorean"]=12633,
+ ["wahiragana"]=12431,
+ ["wakatakana"]=12527,
+ ["wakatakanahalfwidth"]=65436,
+ ["wakorean"]=12632,
+ ["wasmallhiragana"]=12430,
+ ["wasmallkatakana"]=12526,
+ ["wattosquare"]=13143,
+ ["wavedash"]=12316,
+ ["wavyunderscorevertical"]=65076,
+ ["wawarabic"]=1608,
+ ["wawfinalarabic"]=65262,
+ ["wawhamzaabovearabic"]=1572,
+ ["wawhamzaabovefinalarabic"]=65158,
+ ["wbsquare"]=13277,
+ ["wcircle"]=9446,
+ ["wcircumflex"]=373,
+ ["wdieresis"]=7813,
+ ["wdotaccent"]=7815,
+ ["wdotbelow"]=7817,
+ ["wehiragana"]=12433,
+ ["weierstrass"]=8472,
+ ["wekatakana"]=12529,
+ ["wekorean"]=12638,
+ ["weokorean"]=12637,
+ ["wgrave"]=7809,
+ ["whitebullet"]=9702,
+ ["whitecircle"]=9675,
+ ["whitecircleinverse"]=9689,
+ ["whitecornerbracketleft"]=12302,
+ ["whitecornerbracketleftvertical"]=65091,
+ ["whitecornerbracketright"]=12303,
+ ["whitecornerbracketrightvertical"]=65092,
+ ["whitediamond"]=9671,
+ ["whitediamondcontainingblacksmalldiamond"]=9672,
+ ["whitedownpointingsmalltriangle"]=9663,
+ ["whitedownpointingtriangle"]=9661,
+ ["whiteleftpointingsmalltriangle"]=9667,
+ ["whiteleftpointingtriangle"]=9665,
+ ["whitelenticularbracketleft"]=12310,
+ ["whitelenticularbracketright"]=12311,
+ ["whiterightpointingsmalltriangle"]=9657,
+ ["whiterightpointingtriangle"]=9655,
+ ["whitesmallsquare"]=9643,
+ ["whitesmilingface"]=9786,
+ ["whitesquare"]=9633,
+ ["whitestar"]=9734,
+ ["whitetelephone"]=9743,
+ ["whitetortoiseshellbracketleft"]=12312,
+ ["whitetortoiseshellbracketright"]=12313,
+ ["whiteuppointingsmalltriangle"]=9653,
+ ["whiteuppointingtriangle"]=9651,
+ ["wihiragana"]=12432,
+ ["wikatakana"]=12528,
+ ["wikorean"]=12639,
+ ["wmonospace"]=65367,
+ ["wohiragana"]=12434,
+ ["wokatakana"]=12530,
+ ["wokatakanahalfwidth"]=65382,
+ ["won"]=8361,
+ ["wonmonospace"]=65510,
+ ["wowaenthai"]=3623,
+ ["wparen"]=9394,
+ ["wring"]=7832,
+ ["wsuperior"]=695,
+ ["wturned"]=653,
+ ["wynn"]=447,
+ ["x"]=120,
+ ["xabovecmb"]=829,
+ ["xbopomofo"]=12562,
+ ["xcircle"]=9447,
+ ["xdieresis"]=7821,
+ ["xdotaccent"]=7819,
+ ["xeharmenian"]=1389,
+ ["xi"]=958,
+ ["xmonospace"]=65368,
+ ["xparen"]=9395,
+ ["xsuperior"]=739,
+ ["y"]=121,
+ ["yaadosquare"]=13134,
+ ["yabengali"]=2479,
+ ["yacute"]=253,
+ ["yadeva"]=2351,
+ ["yaekorean"]=12626,
+ ["yagujarati"]=2735,
+ ["yagurmukhi"]=2607,
+ ["yahiragana"]=12420,
+ ["yakatakana"]=12516,
+ ["yakatakanahalfwidth"]=65428,
+ ["yakorean"]=12625,
+ ["yamakkanthai"]=3662,
+ ["yasmallhiragana"]=12419,
+ ["yasmallkatakana"]=12515,
+ ["yasmallkatakanahalfwidth"]=65388,
+ ["yatcyrillic"]=1123,
+ ["ycircle"]=9448,
+ ["ycircumflex"]=375,
+ ["ydieresis"]=255,
+ ["ydotaccent"]=7823,
+ ["ydotbelow"]=7925,
+ ["yeharabic"]=1610,
+ ["yehbarreearabic"]=1746,
+ ["yehbarreefinalarabic"]=64431,
+ ["yehfinalarabic"]=65266,
+ ["yehhamzaabovearabic"]=1574,
+ ["yehhamzaabovefinalarabic"]=65162,
+ ["yehhamzaaboveinitialarabic"]=65163,
+ ["yehhamzaabovemedialarabic"]=65164,
+ ["yehinitialarabic"]=65267,
+ ["yehmedialarabic"]=65268,
+ ["yehmeeminitialarabic"]=64733,
+ ["yehmeemisolatedarabic"]=64600,
+ ["yehnoonfinalarabic"]=64660,
+ ["yehthreedotsbelowarabic"]=1745,
+ ["yekorean"]=12630,
+ ["yen"]=165,
+ ["yenmonospace"]=65509,
+ ["yeokorean"]=12629,
+ ["yeorinhieuhkorean"]=12678,
+ ["yerahbenyomohebrew"]=1450,
+ ["yerahbenyomolefthebrew"]=1450,
+ ["yericyrillic"]=1099,
+ ["yerudieresiscyrillic"]=1273,
+ ["yesieungkorean"]=12673,
+ ["yesieungpansioskorean"]=12675,
+ ["yesieungsioskorean"]=12674,
+ ["yetivhebrew"]=1434,
+ ["ygrave"]=7923,
+ ["yhook"]=436,
+ ["yhookabove"]=7927,
+ ["yiarmenian"]=1397,
+ ["yicyrillic"]=1111,
+ ["yikorean"]=12642,
+ ["yinyang"]=9775,
+ ["yiwnarmenian"]=1410,
+ ["ymonospace"]=65369,
+ ["yod"]=1497,
+ ["yoddagesh"]=64313,
+ ["yoddageshhebrew"]=64313,
+ ["yodhebrew"]=1497,
+ ["yodyodhebrew"]=1522,
+ ["yodyodpatahhebrew"]=64287,
+ ["yohiragana"]=12424,
+ ["yoikorean"]=12681,
+ ["yokatakana"]=12520,
+ ["yokatakanahalfwidth"]=65430,
+ ["yokorean"]=12635,
+ ["yosmallhiragana"]=12423,
+ ["yosmallkatakana"]=12519,
+ ["yosmallkatakanahalfwidth"]=65390,
+ ["yotgreek"]=1011,
+ ["yoyaekorean"]=12680,
+ ["yoyakorean"]=12679,
+ ["yoyakthai"]=3618,
+ ["yoyingthai"]=3597,
+ ["yparen"]=9396,
+ ["ypogegrammeni"]=890,
+ ["ypogegrammenigreekcmb"]=837,
+ ["yr"]=422,
+ ["yring"]=7833,
+ ["ysuperior"]=696,
+ ["ytilde"]=7929,
+ ["yturned"]=654,
+ ["yuhiragana"]=12422,
+ ["yuikorean"]=12684,
+ ["yukatakana"]=12518,
+ ["yukatakanahalfwidth"]=65429,
+ ["yukorean"]=12640,
+ ["yusbigcyrillic"]=1131,
+ ["yusbigiotifiedcyrillic"]=1133,
+ ["yuslittlecyrillic"]=1127,
+ ["yuslittleiotifiedcyrillic"]=1129,
+ ["yusmallhiragana"]=12421,
+ ["yusmallkatakana"]=12517,
+ ["yusmallkatakanahalfwidth"]=65389,
+ ["yuyekorean"]=12683,
+ ["yuyeokorean"]=12682,
+ ["yyabengali"]=2527,
+ ["yyadeva"]=2399,
+ ["z"]=122,
+ ["zaarmenian"]=1382,
+ ["zacute"]=378,
+ ["zadeva"]=2395,
+ ["zagurmukhi"]=2651,
+ ["zaharabic"]=1592,
+ ["zahfinalarabic"]=65222,
+ ["zahinitialarabic"]=65223,
+ ["zahiragana"]=12374,
+ ["zahmedialarabic"]=65224,
+ ["zainarabic"]=1586,
+ ["zainfinalarabic"]=65200,
+ ["zakatakana"]=12470,
+ ["zaqefgadolhebrew"]=1429,
+ ["zaqefqatanhebrew"]=1428,
+ ["zarqahebrew"]=1432,
+ ["zayin"]=1494,
+ ["zayindagesh"]=64310,
+ ["zayindageshhebrew"]=64310,
+ ["zayinhebrew"]=1494,
+ ["zbopomofo"]=12567,
+ ["zcaron"]=382,
+ ["zcircle"]=9449,
+ ["zcircumflex"]=7825,
+ ["zcurl"]=657,
+ ["zdot"]=380,
+ ["zdotaccent"]=380,
+ ["zdotbelow"]=7827,
+ ["zecyrillic"]=1079,
+ ["zedescendercyrillic"]=1177,
+ ["zedieresiscyrillic"]=1247,
+ ["zehiragana"]=12380,
+ ["zekatakana"]=12476,
+ ["zero"]=48,
+ ["zeroarabic"]=1632,
+ ["zerobengali"]=2534,
+ ["zerodeva"]=2406,
+ ["zerogujarati"]=2790,
+ ["zerogurmukhi"]=2662,
+ ["zerohackarabic"]=1632,
+ ["zeroinferior"]=8320,
+ ["zeromonospace"]=65296,
+ ["zeropersian"]=1776,
+ ["zerosuperior"]=8304,
+ ["zerothai"]=3664,
+ ["zerowidthjoiner"]=65279,
+ ["zerowidthnonjoiner"]=8204,
+ ["zerowidthspace"]=8203,
+ ["zeta"]=950,
+ ["zhbopomofo"]=12563,
+ ["zhearmenian"]=1386,
+ ["zhebrevecyrillic"]=1218,
+ ["zhecyrillic"]=1078,
+ ["zhedescendercyrillic"]=1175,
+ ["zhedieresiscyrillic"]=1245,
+ ["zihiragana"]=12376,
+ ["zikatakana"]=12472,
+ ["zinorhebrew"]=1454,
+ ["zlinebelow"]=7829,
+ ["zmonospace"]=65370,
+ ["zohiragana"]=12382,
+ ["zokatakana"]=12478,
+ ["zparen"]=9397,
+ ["zretroflexhook"]=656,
+ ["zstroke"]=438,
+ ["zuhiragana"]=12378,
+ ["zukatakana"]=12474,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-agl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-agl.lua
new file mode 100644
index 00000000000..dd349052335
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-agl.lua
@@ -0,0 +1,692 @@
+if not modules then modules = { } end modules ['font-agl'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "derived from http://www.adobe.com/devnet/opentype/archives/glyphlist.txt",
+ original = "Adobe Glyph List, version 2.0, September 20, 2002",
+}
+
+local allocate = utilities.storage.allocate
+
+fonts = fonts or { }
+local encodings = fonts.encodings or { }
+fonts.encodings = encodings
+local agl = fonts.encodings.agl or { }
+fonts.encodings.agl = agl
+
+table.setmetatableindex(agl,nil) -- prevent recursive lookups otherwise when autoloaded
+
+local synonyms = {
+ Acyrillic = 0x0410,
+ Becyrillic = 0x0411,
+ Cdot = 0x010A,
+ Checyrillic = 0x0427,
+ Decyrillic = 0x0414,
+ Djecyrillic = 0x0402,
+ Dzecyrillic = 0x0405,
+ Dzhecyrillic = 0x040F,
+ Ecyrillic = 0x0404,
+ Edot = 0x0116,
+ Efcyrillic = 0x0424,
+ Elcyrillic = 0x041B,
+ Emcyrillic = 0x041C,
+ Encyrillic = 0x041D,
+ Ercyrillic = 0x0420,
+ Ereversedcyrillic = 0x042D,
+ Escyrillic = 0x0421,
+ Fitacyrillic = 0x0472,
+ Gcedilla = 0x0122,
+ Gdot = 0x0120,
+ Gecyrillic = 0x0413,
+ Gheupturncyrillic = 0x0490,
+ Gjecyrillic = 0x0403,
+ Hardsigncyrillic = 0x042A,
+ IAcyrillic = 0x042F,
+ IUcyrillic = 0x042E,
+ Icyrillic = 0x0406,
+ Idot = 0x0130,
+ Iecyrillic = 0x0415,
+ Iicyrillic = 0x0418,
+ Iishortcyrillic = 0x0419,
+ Iocyrillic = 0x0401,
+ Izhitsacyrillic = 0x0474,
+ Jecyrillic = 0x0408,
+ Kacyrillic = 0x041A,
+ Kcedilla = 0x0136,
+ Khacyrillic = 0x0425,
+ Kjecyrillic = 0x040C,
+ Lcedilla = 0x013B,
+ Ljecyrillic = 0x0409,
+ Ncedilla = 0x0145,
+ Njecyrillic = 0x040A,
+ Ocyrillic = 0x041E,
+ Odblacute = 0x0150,
+ Ohm = 0x2126,
+ Pecyrillic = 0x041F,
+ Rcedilla = 0x0156,
+ Shacyrillic = 0x0428,
+ Shchacyrillic = 0x0429,
+ Softsigncyrillic = 0x042C,
+ Tcedilla = 0x0162,
+ Tecyrillic = 0x0422,
+ Tsecyrillic = 0x0426,
+ Tshecyrillic = 0x040B,
+ Ucyrillic = 0x0423,
+ Udblacute = 0x0170,
+ Ushortcyrillic = 0x040E,
+ Vecyrillic = 0x0412,
+ Yatcyrillic = 0x0462,
+ Yericyrillic = 0x042B,
+ Yicyrillic = 0x0407,
+ Zdot = 0x017B,
+ Zecyrillic = 0x0417,
+ Zhecyrillic = 0x0416,
+ acutecmb = 0x0301,
+ acyrillic = 0x0430,
+ afii00208 = 0x2015,
+ afii08941 = 0x20A4,
+ afii57694 = 0xFB2A,
+ afii57695 = 0xFB2B,
+ afii57700 = 0xFB4B,
+ afii57705 = 0xFB1F,
+ afii57723 = 0xFB35,
+ alef = 0x05D0,
+ alefmaksurainitialarabic = 0xFEF3,
+ alefmaksuramedialarabic = 0xFEF4,
+ approximatelyequal = 0x2245,
+ asteriskaltonearabic = 0x066D,
+ ayin = 0x05E2,
+ bet = 0x05D1,
+ betdagesh = 0xFB31,
+ blackdownpointingtriangle = 0x25BC,
+ blackleftpointingpointer = 0x25C4,
+ blackrectangle = 0x25AC,
+ blackrightpointingpointer = 0x25BA,
+ blacksmilingface = 0x263B,
+ blacksquare = 0x25A0,
+ blackuppointingtriangle = 0x25B2,
+ bulletinverse = 0x25D8,
+ cdot = 0x010B,
+ compass = 0x263C,
+ dagesh = 0x05BC,
+ dalet = 0x05D3,
+ daletdagesh = 0xFB33,
+ dalethatafpatah = 0x05D3,
+ dalethatafpatahhebrew = 0x05D3,
+ dalethatafsegol = 0x05D3,
+ dalethatafsegolhebrew = 0x05D3,
+ dalethebrew = 0x05D3,
+ dalethiriq = 0x05D3,
+ dalethiriqhebrew = 0x05D3,
+ daletholam = 0x05D3,
+ daletholamhebrew = 0x05D3,
+ daletpatah = 0x05D3,
+ daletpatahhebrew = 0x05D3,
+ daletqamats = 0x05D3,
+ daletqamatshebrew = 0x05D3,
+ daletqubuts = 0x05D3,
+ daletqubutshebrew = 0x05D3,
+ daletsegol = 0x05D3,
+ daletsegolhebrew = 0x05D3,
+ daletsheva = 0x05D3,
+ daletshevahebrew = 0x05D3,
+ dalettsere = 0x05D3,
+ dammaarabic = 0x064F,
+ dammatanaltonearabic = 0x064C,
+ dargahebrew = 0x05A7,
+ dbllowline = 0x2017,
+ decimalseparatorarabic = 0x066B,
+ dialytikatonos = 0x0385,
+ dotbelowcmb = 0x0323,
+ doubleyodpatah = 0xFB1F,
+ doubleyodpatahhebrew = 0xFB1F,
+ edot = 0x0117,
+ eightarabic = 0x0668,
+ eighthnotebeamed = 0x266B,
+ etnahtafoukhhebrew = 0x0591,
+ etnahtafoukhlefthebrew = 0x0591,
+ etnahtahebrew = 0x0591,
+ fathaarabic = 0x064E,
+ finalkaf = 0x05DA,
+ finalkafdagesh = 0xFB3A,
+ finalkafhebrew = 0x05DA,
+ finalkafqamats = 0x05DA,
+ finalkafqamatshebrew = 0x05DA,
+ finalkafsheva = 0x05DA,
+ finalmem = 0x05DD,
+ finalnun = 0x05DF,
+ finalpe = 0x05E3,
+ finaltsadi = 0x05E5,
+ fivearabic = 0x0665,
+ forall = 0x2200,
+ fourarabic = 0x0664,
+ gcedilla = 0x0123,
+ gdot = 0x0121,
+ gimel = 0x05D2,
+ gimeldagesh = 0xFB32,
+ gravecmb = 0x0300,
+ haaltonearabic = 0x06C1,
+ hamzaarabic = 0x0621,
+ hamzadammaarabic = 0x0621,
+ hamzadammatanarabic = 0x0621,
+ hamzafathaarabic = 0x0621,
+ hamzafathatanarabic = 0x0621,
+ hamzalowarabic = 0x0621,
+ hamzalowkasraarabic = 0x0621,
+ hamzalowkasratanarabic = 0x0621,
+ hatafpatah = 0x05B2,
+ hatafpatah16 = 0x05B2,
+ hatafpatah23 = 0x05B2,
+ hatafpatah2f = 0x05B2,
+ hatafpatahhebrew = 0x05B2,
+ hatafpatahnarrowhebrew = 0x05B2,
+ hatafpatahquarterhebrew = 0x05B2,
+ hatafqamats = 0x05B3,
+ hatafqamats1b = 0x05B3,
+ hatafqamats28 = 0x05B3,
+ hatafqamats34 = 0x05B3,
+ hatafqamatshebrew = 0x05B3,
+ hatafqamatsnarrowhebrew = 0x05B3,
+ hatafqamatsquarterhebrew = 0x05B3,
+ hatafsegol = 0x05B1,
+ hatafsegol17 = 0x05B1,
+ hatafsegol24 = 0x05B1,
+ hatafsegol30 = 0x05B1,
+ hatafsegolhebrew = 0x05B1,
+ hatafsegolnarrowhebrew = 0x05B1,
+ hatafsegolquarterhebrew = 0x05B1,
+ he = 0x05D4,
+ hedagesh = 0xFB34,
+ hehfinalalttwoarabic = 0xFEEA,
+ het = 0x05D7,
+ hiriq = 0x05B4,
+ hiriq14 = 0x05B4,
+ hiriq21 = 0x05B4,
+ hiriq2d = 0x05B4,
+ hiriqhebrew = 0x05B4,
+ hiriqnarrowhebrew = 0x05B4,
+ hiriqquarterhebrew = 0x05B4,
+ holam = 0x05B9,
+ holam19 = 0x05B9,
+ holam26 = 0x05B9,
+ holam32 = 0x05B9,
+ holamhebrew = 0x05B9,
+ holamnarrowhebrew = 0x05B9,
+ holamquarterhebrew = 0x05B9,
+ ilde = 0x02DC,
+ integralbottom = 0x2321,
+ integraltop = 0x2320,
+ kaf = 0x05DB,
+ kafdagesh = 0xFB3B,
+ kashidaautoarabic = 0x0640,
+ kashidaautonosidebearingarabic = 0x0640,
+ kcedilla = 0x0137,
+ lamed = 0x05DC,
+ lameddagesh = 0xFB3C,
+ lamedhebrew = 0x05DC,
+ lamedholam = 0x05DC,
+ lamedholamdagesh = 0x05DC,
+ lamedholamdageshhebrew = 0x05DC,
+ laminitialarabic = 0xFEDF,
+ lammeemjeeminitialarabic = 0xFEDF,
+ lcedilla = 0x013C,
+ logicalnotreversed = 0x2310,
+ mahapakhhebrew = 0x05A4,
+ mem = 0x05DE,
+ memdagesh = 0xFB3E,
+ merkhahebrew = 0x05A5,
+ merkhakefulahebrew = 0x05A6,
+ middot = 0x00B7,
+ munahhebrew = 0x05A3,
+ nbspace = 0x00A0,
+ ncedilla = 0x0146,
+ newsheqelsign = 0x20AA,
+ ninearabic = 0x0669,
+ noonhehinitialarabic = 0xFEE7,
+ nun = 0x05E0,
+ nundagesh = 0xFB40,
+ odblacute = 0x0151,
+ onearabic = 0x0661,
+ overscore = 0x00AF,
+ patah = 0x05B7,
+ patah11 = 0x05B7,
+ patah1d = 0x05B7,
+ patah2a = 0x05B7,
+ patahhebrew = 0x05B7,
+ patahnarrowhebrew = 0x05B7,
+ patahquarterhebrew = 0x05B7,
+ pe = 0x05E4,
+ pedagesh = 0xFB44,
+ qamats = 0x05B8,
+ qamats10 = 0x05B8,
+ qamats1a = 0x05B8,
+ qamats1c = 0x05B8,
+ qamats27 = 0x05B8,
+ qamats29 = 0x05B8,
+ qamats33 = 0x05B8,
+ qamatsde = 0x05B8,
+ qamatshebrew = 0x05B8,
+ qamatsnarrowhebrew = 0x05B8,
+ qamatsqatanhebrew = 0x05B8,
+ qamatsqatannarrowhebrew = 0x05B8,
+ qamatsqatanquarterhebrew = 0x05B8,
+ qamatsqatanwidehebrew = 0x05B8,
+ qamatsquarterhebrew = 0x05B8,
+ qof = 0x05E7,
+ qofdagesh = 0xFB47,
+ qofhatafpatah = 0x05E7,
+ qofhatafpatahhebrew = 0x05E7,
+ qofhatafsegol = 0x05E7,
+ qofhatafsegolhebrew = 0x05E7,
+ qofhebrew = 0x05E7,
+ qofhiriq = 0x05E7,
+ qofhiriqhebrew = 0x05E7,
+ qofholam = 0x05E7,
+ qofholamhebrew = 0x05E7,
+ qofpatah = 0x05E7,
+ qofpatahhebrew = 0x05E7,
+ qofqamats = 0x05E7,
+ qofqamatshebrew = 0x05E7,
+ qofqubuts = 0x05E7,
+ qofqubutshebrew = 0x05E7,
+ qofsegol = 0x05E7,
+ qofsegolhebrew = 0x05E7,
+ qofsheva = 0x05E7,
+ qofshevahebrew = 0x05E7,
+ qoftsere = 0x05E7,
+ qubuts = 0x05BB,
+ qubuts18 = 0x05BB,
+ qubuts25 = 0x05BB,
+ qubuts31 = 0x05BB,
+ qubutshebrew = 0x05BB,
+ qubutsnarrowhebrew = 0x05BB,
+ qubutsquarterhebrew = 0x05BB,
+ quoteleftreversed = 0x201B,
+ rafe = 0x05BF,
+ rcedilla = 0x0157,
+ reharabic = 0x0631,
+ resh = 0x05E8,
+ reshhatafpatah = 0x05E8,
+ reshhatafpatahhebrew = 0x05E8,
+ reshhatafsegol = 0x05E8,
+ reshhatafsegolhebrew = 0x05E8,
+ reshhebrew = 0x05E8,
+ reshhiriq = 0x05E8,
+ reshhiriqhebrew = 0x05E8,
+ reshholam = 0x05E8,
+ reshholamhebrew = 0x05E8,
+ reshpatah = 0x05E8,
+ reshpatahhebrew = 0x05E8,
+ reshqamats = 0x05E8,
+ reshqamatshebrew = 0x05E8,
+ reshqubuts = 0x05E8,
+ reshqubutshebrew = 0x05E8,
+ reshsegol = 0x05E8,
+ reshsegolhebrew = 0x05E8,
+ reshsheva = 0x05E8,
+ reshshevahebrew = 0x05E8,
+ reshtsere = 0x05E8,
+ reviahebrew = 0x0597,
+ samekh = 0x05E1,
+ samekhdagesh = 0xFB41,
+ segol = 0x05B6,
+ segol13 = 0x05B6,
+ segol1f = 0x05B6,
+ segol2c = 0x05B6,
+ segolhebrew = 0x05B6,
+ segolnarrowhebrew = 0x05B6,
+ segolquarterhebrew = 0x05B6,
+ sevenarabic = 0x0667,
+ sfthyphen = 0x00AD,
+ shaddaarabic = 0x0651,
+ sheqel = 0x20AA,
+ sheva = 0x05B0,
+ sheva115 = 0x05B0,
+ sheva15 = 0x05B0,
+ sheva22 = 0x05B0,
+ sheva2e = 0x05B0,
+ shevahebrew = 0x05B0,
+ shevanarrowhebrew = 0x05B0,
+ shevaquarterhebrew = 0x05B0,
+ shin = 0x05E9,
+ shindagesh = 0xFB49,
+ shindageshshindot = 0xFB2C,
+ shindageshsindot = 0xFB2D,
+ shinshindot = 0xFB2A,
+ shinsindot = 0xFB2B,
+ siluqhebrew = 0x05BD,
+ sixarabic = 0x0666,
+ tav = 0x05EA,
+ tavdages = 0xFB4A,
+ tavdagesh = 0xFB4A,
+ tcedilla = 0x0163,
+ tchehinitialarabic = 0xFB7C,
+ tet = 0x05D8,
+ tetdagesh = 0xFB38,
+ tevirhebrew = 0x059B,
+ thousandsseparatorarabic = 0x066C,
+ threearabic = 0x0663,
+ tildecmb = 0x0303,
+ tipehahebrew = 0x0596,
+ tsadi = 0x05E6,
+ tsadidagesh = 0xFB46,
+ tsere = 0x05B5,
+ tsere12 = 0x05B5,
+ tsere1e = 0x05B5,
+ tsere2b = 0x05B5,
+ tserehebrew = 0x05B5,
+ tserenarrowhebrew = 0x05B5,
+ tserequarterhebrew = 0x05B5,
+ twoarabic = 0x0662,
+ udblacute = 0x0171,
+ vav = 0x05D5,
+ vavdagesh = 0xFB35,
+ vavdagesh65 = 0xFB35,
+ vavholam = 0xFB4B,
+ yerahbenyomohebrew = 0x05AA,
+ yod = 0x05D9,
+ yoddagesh = 0xFB39,
+ zayin = 0x05D6,
+ zayindagesh = 0xFB36,
+ zdot = 0x017C,
+ zeroarabic = 0x0660,
+}
+
+local extras = allocate { -- private extensions
+ Dcroat = 0x0110,
+ Delta = 0x2206,
+ Euro = 0x20AC,
+ H18533 = 0x25CF,
+ H18543 = 0x25AA,
+ H18551 = 0x25AB,
+ H22073 = 0x25A1,
+ Ldot = 0x013F,
+ Oslashacute = 0x01FE,
+ SF10000 = 0x250C,
+ SF20000 = 0x2514,
+ SF30000 = 0x2510,
+ SF40000 = 0x2518,
+ SF50000 = 0x253C,
+ SF60000 = 0x252C,
+ SF70000 = 0x2534,
+ SF80000 = 0x251C,
+ SF90000 = 0x2524,
+ Upsilon1 = 0x03D2,
+ afii10066 = 0x0431,
+ afii10067 = 0x0432,
+ afii10068 = 0x0433,
+ afii10069 = 0x0434,
+ afii10070 = 0x0435,
+ afii10071 = 0x0451,
+ afii10072 = 0x0436,
+ afii10073 = 0x0437,
+ afii10074 = 0x0438,
+ afii10075 = 0x0439,
+ afii10076 = 0x043A,
+ afii10077 = 0x043B,
+ afii10078 = 0x043C,
+ afii10079 = 0x043D,
+ afii10080 = 0x043E,
+ afii10081 = 0x043F,
+ afii10082 = 0x0440,
+ afii10083 = 0x0441,
+ afii10084 = 0x0442,
+ afii10085 = 0x0443,
+ afii10086 = 0x0444,
+ afii10087 = 0x0445,
+ afii10088 = 0x0446,
+ afii10089 = 0x0447,
+ afii10090 = 0x0448,
+ afii10091 = 0x0449,
+ afii10092 = 0x044A,
+ afii10093 = 0x044B,
+ afii10094 = 0x044C,
+ afii10095 = 0x044D,
+ afii10096 = 0x044E,
+ afii10097 = 0x044F,
+ afii10098 = 0x0491,
+ afii10099 = 0x0452,
+ afii10100 = 0x0453,
+ afii10101 = 0x0454,
+ afii10102 = 0x0455,
+ afii10103 = 0x0456,
+ afii10104 = 0x0457,
+ afii10105 = 0x0458,
+ afii10106 = 0x0459,
+ afii10107 = 0x045A,
+ afii10108 = 0x045B,
+ afii10109 = 0x045C,
+ afii10110 = 0x045E,
+ afii10193 = 0x045F,
+ afii10194 = 0x0463,
+ afii10195 = 0x0473,
+ afii10196 = 0x0475,
+ afii10846 = 0x04D9,
+ afii208 = 0x2015,
+ afii57381 = 0x066A,
+ afii57388 = 0x060C,
+ afii57392 = 0x0660,
+ afii57393 = 0x0661,
+ afii57394 = 0x0662,
+ afii57395 = 0x0663,
+ afii57396 = 0x0664,
+ afii57397 = 0x0665,
+ afii57398 = 0x0666,
+ afii57399 = 0x0667,
+ afii57400 = 0x0668,
+ afii57401 = 0x0669,
+ afii57403 = 0x061B,
+ afii57407 = 0x061F,
+ afii57409 = 0x0621,
+ afii57410 = 0x0622,
+ afii57411 = 0x0623,
+ afii57412 = 0x0624,
+ afii57413 = 0x0625,
+ afii57414 = 0x0626,
+ afii57415 = 0x0627,
+ afii57416 = 0x0628,
+ afii57417 = 0x0629,
+ afii57418 = 0x062A,
+ afii57419 = 0x062B,
+ afii57420 = 0x062C,
+ afii57421 = 0x062D,
+ afii57422 = 0x062E,
+ afii57423 = 0x062F,
+ afii57424 = 0x0630,
+ afii57425 = 0x0631,
+ afii57426 = 0x0632,
+ afii57427 = 0x0633,
+ afii57428 = 0x0634,
+ afii57429 = 0x0635,
+ afii57430 = 0x0636,
+ afii57431 = 0x0637,
+ afii57432 = 0x0638,
+ afii57433 = 0x0639,
+ afii57434 = 0x063A,
+ afii57440 = 0x0640,
+ afii57441 = 0x0641,
+ afii57442 = 0x0642,
+ afii57443 = 0x0643,
+ afii57444 = 0x0644,
+ afii57445 = 0x0645,
+ afii57446 = 0x0646,
+ afii57448 = 0x0648,
+ afii57449 = 0x0649,
+ afii57450 = 0x064A,
+ afii57451 = 0x064B,
+ afii57452 = 0x064C,
+ afii57453 = 0x064D,
+ afii57454 = 0x064E,
+ afii57455 = 0x064F,
+ afii57456 = 0x0650,
+ afii57457 = 0x0651,
+ afii57458 = 0x0652,
+ afii57470 = 0x0647,
+ afii57505 = 0x06A4,
+ afii57506 = 0x067E,
+ afii57507 = 0x0686,
+ afii57508 = 0x0698,
+ afii57509 = 0x06AF,
+ afii57511 = 0x0679,
+ afii57512 = 0x0688,
+ afii57513 = 0x0691,
+ afii57514 = 0x06BA,
+ afii57519 = 0x06D2,
+ afii57636 = 0x20AA,
+ afii57645 = 0x05BE,
+ afii57658 = 0x05C3,
+ afii57664 = 0x05D0,
+ afii57665 = 0x05D1,
+ afii57666 = 0x05D2,
+ afii57667 = 0x05D3,
+ afii57668 = 0x05D4,
+ afii57669 = 0x05D5,
+ afii57670 = 0x05D6,
+ afii57671 = 0x05D7,
+ afii57672 = 0x05D8,
+ afii57673 = 0x05D9,
+ afii57674 = 0x05DA,
+ afii57675 = 0x05DB,
+ afii57676 = 0x05DC,
+ afii57677 = 0x05DD,
+ afii57678 = 0x05DE,
+ afii57679 = 0x05DF,
+ afii57680 = 0x05E0,
+ afii57681 = 0x05E1,
+ afii57682 = 0x05E2,
+ afii57683 = 0x05E3,
+ afii57684 = 0x05E4,
+ afii57685 = 0x05E5,
+ afii57686 = 0x05E6,
+ afii57687 = 0x05E7,
+ afii57688 = 0x05E8,
+ afii57689 = 0x05E9,
+ afii57690 = 0x05EA,
+ afii57716 = 0x05F0,
+ afii57717 = 0x05F1,
+ afii57718 = 0x05F2,
+ afii57793 = 0x05B4,
+ afii57794 = 0x05B5,
+ afii57795 = 0x05B6,
+ afii57796 = 0x05BB,
+ afii57797 = 0x05B8,
+ afii57798 = 0x05B7,
+ afii57799 = 0x05B0,
+ afii57800 = 0x05B2,
+ afii57801 = 0x05B1,
+ afii57802 = 0x05B3,
+ afii57803 = 0x05C2,
+ afii57804 = 0x05C1,
+ afii57806 = 0x05B9,
+ afii57807 = 0x05BC,
+ afii57839 = 0x05BD,
+ afii57841 = 0x05BF,
+ afii57842 = 0x05C0,
+ afii57929 = 0x02BC,
+ afii61248 = 0x2105,
+ afii61289 = 0x2113,
+ afii61352 = 0x2116,
+ afii61664 = 0x200C,
+ afii63167 = 0x066D,
+ afii64937 = 0x02BD,
+ arrowdblboth = 0x21D4,
+ arrowdblleft = 0x21D0,
+ arrowdblright = 0x21D2,
+ arrowupdnbse = 0x21A8,
+ bar = 0x007C,
+ circle = 0x25CB,
+ circlemultiply = 0x2297,
+ circleplus = 0x2295,
+ club = 0x2663,
+ colonmonetary = 0x20A1,
+ dcroat = 0x0111,
+ dkshade = 0x2593,
+ existential = 0x2203,
+ female = 0x2640,
+ gradient = 0x2207,
+ heart = 0x2665,
+ hookabovecomb = 0x0309,
+ invcircle = 0x25D9,
+ ldot = 0x0140,
+ longs = 0x017F,
+ ltshade = 0x2591,
+ male = 0x2642,
+ mu = 0x00B5,
+ napostrophe = 0x0149,
+ notelement = 0x2209,
+ omega1 = 0x03D6,
+ openbullet = 0x25E6,
+ orthogonal = 0x221F,
+ oslashacute = 0x01FF,
+ phi1 = 0x03D5,
+ propersubset = 0x2282,
+ propersuperset = 0x2283,
+ reflexsubset = 0x2286,
+ reflexsuperset = 0x2287,
+ shade = 0x2592,
+ sigma1 = 0x03C2,
+ similar = 0x223C,
+ smileface = 0x263A,
+ spacehackarabic = 0x0020,
+ spade = 0x2660,
+ theta1 = 0x03D1,
+ twodotenleader = 0x2025,
+}
+
+-- We load this table only when needed. We could use a loading mechanism
+-- return the table but there are no more vectors like this so why bother.
+--
+-- Well, we currently have this table preloaded anyway.
+
+local names = agl.names
+local unicodes = agl.unicodes
+local ctxcodes = agl.ctxcodes
+
+if not names then
+
+ names = allocate { } -- filled from char-def.lua
+ unicodes = allocate { }
+ ctxcodes = allocate { }
+
+ for u, c in next, characters.data do
+ local a = c.adobename
+ if a then
+ unicodes[a] = u
+ names [u] = a
+ end
+ local n = c.contextname
+ if n then
+ ctxcodes[n] = u
+ -- names [u] = a
+ end
+ end
+
+ for a, u in next, extras do
+ unicodes[a] = u
+ if not names[u] then
+ names[u] = a
+ end
+ end
+
+ for s, u in next, synonyms do
+ unicodes[s] = u
+ if not names[u] then
+ names[u] = s
+ end
+ end
+
+ if storage then
+ storage.register("encodings/names", names, "fonts.encodings.names")
+ storage.register("encodings/unicodes", unicodes, "fonts.encodings.unicodes")
+ storage.register("encodings/ctxcodes", ctxcodes, "fonts.encodings.ctxcodes")
+ end
+
+end
+
+agl.names = names -- unicode -> name
+agl.unicodes = unicodes -- name -> unicode
+agl.ctxcodes = ctxcodes -- name -> unicode
+agl.synonyms = synonyms -- merged into the other two
+agl.extras = extras -- merged into the other two
+
+return agl
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua
new file mode 100644
index 00000000000..fc6c90bc177
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua
@@ -0,0 +1,241 @@
+if not modules then modules = { } end modules ['font-aux'] = {
+ 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 tonumber, type = tonumber, type
+----- wrap, yield = coroutine.wrap, coroutine.yield
+
+local fonts, font = fonts, font
+
+local fonts = fonts
+local handlers = fonts.handlers
+local otf = handlers.otf -- brrr
+local afm = handlers.afm -- brrr
+
+local iterators = { }
+fonts.iterators = iterators
+
+local currentfont = font.current
+local identifiers = fonts.hashes.identifiers
+local sortedkeys = table.sortedkeys
+
+-- for unicode, character in fonts.iterators.characters () do print(unicode) end
+-- for unicode, description in fonts.iterators.descriptions() do print(unicode) end
+-- for index, glyph in fonts.iterators.glyphs () do print(index ) end
+
+local function dummy() end
+
+local function checkeddata(data) -- beware, nullfont is the fallback in identifiers
+ local t = type(data)
+ if t == "table" then
+ return data
+ elseif t ~= "number" then
+ data = currentfont()
+ end
+ return identifiers[data] -- has nullfont as fallback
+end
+
+local function getindices(data)
+ data = checkeddata(data)
+ local indices = { }
+ local characters = data.characters
+ if characters then
+ for unicode, character in next, characters do
+ indices[character.index or unicode] = unicode
+ end
+ end
+ return indices
+end
+
+-- function iterators.characters(data)
+-- data = checkeddata(data)
+-- local characters = data.characters
+-- if characters then
+-- local collected = sortedkeys(characters)
+-- return wrap(function()
+-- for c=1,#collected do
+-- local cc = collected[c]
+-- local dc = characters[cc]
+-- if dc then
+-- yield(cc,dc)
+-- end
+-- end
+-- end)
+-- else
+-- return wrap(function() end)
+-- end
+-- end
+
+-- function iterators.descriptions(data)
+-- data = checkeddata(data)
+-- local characters = data.characters
+-- local descriptions = data.descriptions
+-- if characters and descriptions then
+-- local collected = sortedkeys(characters)
+-- return wrap(function()
+-- for c=1,#collected do
+-- local cc = collected[c]
+-- local dc = descriptions[cc]
+-- if dc then
+-- yield(cc,dc)
+-- end
+-- end
+-- end)
+-- else
+-- return wrap(function() end)
+-- end
+-- end
+
+-- function iterators.glyphs(data)
+-- data = checkeddata(data)
+-- local descriptions = data.descriptions
+-- if descriptions then
+-- local indices = getindices(data)
+-- local collected = sortedkeys(indices)
+-- return wrap(function()
+-- for c=1,#collected do
+-- local cc = collected[c]
+-- local dc = descriptions[indices[cc]]
+-- if dc then
+-- yield(cc,dc)
+-- end
+-- end
+-- end)
+-- else
+-- return wrap(function() end)
+-- end
+-- end
+
+function iterators.characters(data)
+ data = checkeddata(data)
+ local characters = data.characters
+ if characters then
+ local collected = sortedkeys(characters)
+ local n, i = #collected, 0
+ return function()
+ i = i + 1
+ if i <= n then
+ local cc = collected[i]
+ local dc = characters[cc]
+ return cc, dc or { }
+ end
+ end
+ else
+ return dummy
+ end
+end
+
+function iterators.descriptions(data)
+ data = checkeddata(data)
+ local characters = data.characters
+ local descriptions = data.descriptions
+ if characters and descriptions then
+ local collected = sortedkeys(characters)
+ local n, i = #collected, 0
+ return function()
+ i = i + 1
+ if i <= n then
+ local cc = collected[i]
+ local dc = descriptions[cc]
+ return cc, dc or { }
+ end
+ end
+ else
+ return dummy
+ end
+end
+
+function iterators.glyphs(data)
+ data = checkeddata(data)
+ local descriptions = data.descriptions
+ if descriptions then
+ local indices = getindices(data)
+ local collected = sortedkeys(indices)
+ local n, i = #collected, 0
+ return function()
+ i = i + 1
+ if i <= n then
+ local cc = collected[i]
+ local dc = descriptions[indices[cc]]
+ return cc, dc or { }
+ end
+ end
+ else
+ return dummy
+ end
+end
+
+-- for the moment here, it might move to some other file later
+
+function afm.getkern(tfmdata,left,right)
+ local c = tfmdata.characters[left]
+ if c then
+ local kerns = c.kerns
+ if kerns then
+ return kerns[right] -- already scaled
+ end
+ end
+ return 0
+end
+
+local getters = { -- maybe better getters[format][...]
+ kern = {
+ ["type1"] = afm.getkern,
+ ["opentype"] = otf.getkern,
+ },
+ substitution = {
+ ["opentype"] = otf.getsubstitution,
+ },
+ alternate = {
+ ["opentype"] = otf.getalternate,
+ },
+ multiple = {
+ ["opentype"] = otf.getmultiple,
+ }
+}
+
+fonts.getters = getters
+
+function fonts.getkern(tfmdata,left,right)
+ local format = tfmdata.properties.format
+ local getter = getters.kern[format]
+ if getter then
+ return getter(tfmdata,left,right)
+ else
+ return 0
+ end
+end
+
+function fonts.getsubstitution(tfmdata,k,kind)
+ local format = tfmdata.properties.format
+ local getter = getters.substitution[format]
+ if getter then
+ return getter(tfmdata,k,kind,value)
+ else
+ return 0
+ end
+end
+
+function fonts.getalternate(tfmdata,k,kind,value)
+ local format = tfmdata.properties.format
+ local getter = getters.substitution[format]
+ if getter then
+ return getter(tfmdata,k,kind,value)
+ else
+ return 0
+ end
+end
+
+function fonts.getmultiple(tfmdata,k,kind)
+ local format = tfmdata.properties.format
+ local getter = getters.substitution[format]
+ if getter then
+ return getter(tfmdata,k,kind,value)
+ else
+ return 0
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-aux.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-aux.mkvi
new file mode 100644
index 00000000000..bd655e41c60
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-aux.mkvi
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=font-gds,
+%D version=2012.06.26,
+%D title=\CONTEXT\ Font Support,
+%D subtitle=Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Support / Helpers}
+
+%D Here we collect code moved from other files, like some of the
+%D support modules.
+
+\unprotect
+
+%D Leftovers:
+
+\unexpanded\def\xbox {\bgroup\aftergroup\egroup\hbox\bgroup\tx \let\next=}
+\unexpanded\def\xxbox{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
new file mode 100644
index 00000000000..8c57b473ef8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua
@@ -0,0 +1,1698 @@
+if not modules then modules = { } end modules ['font-cff'] = {
+ 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: option.outlines
+-- todo: option.boundingbox
+-- per charstring (less memory)
+
+-- This is a heavy one as it is a rather packed format. We don't need al the information
+-- now but we might need it later (who know what magic we can do with metapost). So at
+-- some point this might become a module. We just follow Adobe Technical Notes #5176 and
+-- #5177. In case of doubt I looked in the fontforge code that comes with LuaTeX.
+
+-- For now we save the segments in a list of segments with the operator last in an entry
+-- because that reflects the original. But it might make more sense to use a single array
+-- per segment. For pdf a simple concat works ok, but for other purposes a operator first
+-- flush is nicer.
+
+local next, type, tonumber = next, type, tonumber
+local byte = string.byte
+local concat, remove = table.concat, table.remove
+local floor, abs, round, ceil = math.floor, math.abs, math.round, math.ceil
+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 readers = fonts.handlers.otf.readers
+local streamreader = readers.streamreader
+
+local readbytes = streamreader.readbytes
+local readstring = streamreader.readstring
+local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer
+local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local setposition = streamreader.setposition
+local getposition = streamreader.getposition
+
+local setmetatableindex = table.setmetatableindex
+
+local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end)
+local report = logs.reporter("otf reader","cff")
+
+local parsedictionaries
+local parsecharstring
+local parsecharstrings
+local resetcharstrings
+local parseprivates
+
+local defaultstrings = { [0] = -- taken from ff
+ ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H",
+ "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
+ "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
+ "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent",
+ "sterling", "fraction", "yen", "florin", "section", "currency",
+ "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
+ "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl",
+ "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase",
+ "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown",
+ "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
+ "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash",
+ "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae",
+ "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior",
+ "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn",
+ "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters",
+ "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior",
+ "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring",
+ "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave",
+ "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute",
+ "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute",
+ "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
+ "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde",
+ "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute",
+ "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex",
+ "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex",
+ "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
+ "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall",
+ "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+ "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
+ "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
+ "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+ "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
+ "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
+ "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior",
+ "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall",
+ "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall",
+ "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
+ "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall",
+ "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah",
+ "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall",
+ "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall",
+ "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior",
+ "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth",
+ "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds",
+ "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
+ "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior",
+ "oneinferior", "twoinferior", "threeinferior", "fourinferior",
+ "fiveinferior", "sixinferior", "seveninferior", "eightinferior",
+ "nineinferior", "centinferior", "dollarinferior", "periodinferior",
+ "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
+ "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
+ "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall",
+ "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall",
+ "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall",
+ "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall",
+ "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall",
+ "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003",
+ "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold",
+}
+
+local cffreaders = {
+ readbyte,
+ readushort,
+ readuint,
+ readulong,
+}
+
+-- The header contains information about its own size.
+
+local function readheader(f)
+ local offset = getposition(f)
+ local header = {
+ offset = offset,
+ major = readbyte(f),
+ minor = readbyte(f),
+ size = readbyte(f), -- headersize
+ osize = readbyte(f), -- for offsets to start
+ }
+ setposition(f,offset+header.size)
+ return header
+end
+
+-- The indexes all look the same, so we share a loader. We could pass a handler
+-- and run over the array but why bother, we only have a few uses.
+
+local function readlengths(f)
+ local count = readushort(f)
+ if count == 0 then
+ return { }
+ end
+ local osize = readbyte(f)
+ local read = cffreaders[osize]
+ if not read then
+ report("bad offset size: %i",osize)
+ return { }
+ end
+ local lengths = { }
+ local previous = read(f)
+ for i=1,count do
+ local offset = read(f)
+ lengths[i] = offset - previous
+ previous = offset
+ end
+ return lengths
+end
+
+-- There can be subfonts so names is an array. However, in our case it's always
+-- one font. The same is true for the top dictionaries. Watch how we only load
+-- the dictionary string as for interpretation we need to have the strings loaded
+-- as well.
+
+local function readfontnames(f)
+ local names = readlengths(f)
+ for i=1,#names do
+ names[i] = readstring(f,names[i])
+ end
+ return names
+end
+
+local function readtopdictionaries(f)
+ local dictionaries = readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i] = readstring(f,dictionaries[i])
+ end
+ return dictionaries
+end
+
+-- Strings are added to a list of standard strings so we start the font specific
+-- one with an offset. Strings are shared so we have one table.
+
+local function readstrings(f)
+ local lengths = readlengths(f)
+ local strings = setmetatableindex({ }, defaultstrings)
+ local index = #defaultstrings
+ for i=1,#lengths do
+ index = index + 1
+ strings[index] = readstring(f,lengths[i])
+ end
+ return strings
+end
+
+-- Parsing the dictionaries is delayed till we have the strings loaded. The parser
+-- is stack based so the operands come before the operator (like in postscript).
+
+-- local function delta(t)
+-- local n = #t
+-- if n > 1 then
+-- local p = t[1]
+-- for i=2,n do
+-- local c = t[i]
+-- t[i] = c + p
+-- p = c
+-- end
+-- end
+-- end
+
+do
+
+ -- We use a closure so that we don't need to pass too much around.
+
+ local stack = { }
+ local top = 0
+ local result = { }
+ local strings = { }
+
+ local p_single =
+ P("\00") / function()
+ result.version = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\01") / function()
+ result.notice = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\02") / function()
+ result.fullname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\03") / function()
+ result.familyname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\04") / function()
+ result.weight = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\05") / function()
+ 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("\13") / function()
+ result.uniqueid = stack[top]
+ top = 0
+ end
+ + P("\14") / function()
+ result.xuid = concat(stack,"",1,top)
+ top = 0
+ end
+ + P("\15") / function()
+ result.charset = stack[top]
+ top = 0
+ end
+ + P("\16") / function()
+ result.encoding = stack[top]
+ top = 0
+ end
+ + P("\17") / function()
+ result.charstrings = stack[top]
+ top = 0
+ end
+ + P("\18") / function()
+ result.private = {
+ size = stack[top-1],
+ offset = stack[top],
+ }
+ top = 0
+ end
+ + P("\19") / function()
+ result.subroutines = stack[top]
+ end
+ + P("\20") / function()
+ result.defaultwidthx = stack[top]
+ end
+ + P("\21") / function()
+ result.nominalwidthx = stack[top]
+ end
+ -- + P("\22") / function() end -- reserved
+ -- + P("\23") / function() end -- reserved
+ -- + P("\24") / function() end -- reserved
+ -- + P("\25") / function() end -- reserved
+ -- + P("\26") / function() end -- reserved
+ -- + P("\27") / function() end -- reserved
+
+ local p_double = P("\12") * (
+ P("\00") / function()
+ result.copyright = stack[top]
+ top = 0
+ end
+ + P("\01") / function()
+ result.monospaced = stack[top] == 1 and true or false -- isfixedpitch
+ top = 0
+ end
+ + P("\02") / function()
+ result.italicangle = stack[top]
+ top = 0
+ end
+ + P("\03") / function()
+ result.underlineposition = stack[top]
+ top = 0
+ end
+ + P("\04") / function()
+ result.underlinethickness = stack[top]
+ top = 0
+ end
+ + P("\05") / function()
+ result.painttype = stack[top]
+ top = 0
+ end
+ + P("\06") / function()
+ result.charstringtype = stack[top]
+ top = 0
+ end
+ + P("\07") / function()
+ result.fontmatrix = { unpack(stack,1,6) }
+ top = 0
+ end
+ + P("\08") / function()
+ result.strokewidth = stack[top]
+ top = 0
+ end
+ + P("\20") / function()
+ result.syntheticbase = stack[top]
+ top = 0
+ end
+ + P("\21") / function()
+ result.postscript = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\22") / function()
+ result.basefontname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\21") / function()
+ result.basefontblend = stack[top]
+ top = 0
+ end
+ + P("\30") / function()
+ result.cid.registry = strings[stack[top-2]] or "unset"
+ result.cid.ordering = strings[stack[top-1]] or "unset"
+ result.cid.supplement = stack[top]
+ top = 0
+ end
+ + P("\31") / function()
+ result.cid.fontversion = stack[top]
+ top = 0
+ end
+ + P("\32") / function()
+ result.cid.fontrevision= stack[top]
+ top = 0
+ end
+ + P("\33") / function()
+ result.cid.fonttype = stack[top]
+ top = 0
+ end
+ + P("\34") / function()
+ result.cid.count = stack[top]
+ top = 0
+ end
+ + P("\35") / function()
+ result.cid.uidbase = stack[top]
+ top = 0
+ end
+ + P("\36") / function()
+ result.cid.fdarray = stack[top]
+ top = 0
+ end
+ + P("\37") / function()
+ result.cid.fdselect = stack[top]
+ top = 0
+ end
+ + P("\38") / function()
+ result.cid.fontname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ )
+
+ -- Some lpeg fun ... a first variant split the byte and made a new string but
+ -- 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",
+ ["\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)
+ -- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish
+ top = top + 1
+ stack[top] = tonumber(n) or 0
+ end
+
+ local p_byte = C(R("\32\246")) / function(b0)
+ -- -107 .. +107
+ top = top + 1
+ stack[top] = byte(b0) - 139
+ end
+
+ local p_positive = C(R("\247\250")) * C(1) / function(b0,b1)
+ -- +108 .. +1131
+ top = top + 1
+ stack[top] = (byte(b0)-247)*256 + byte(b1) + 108
+ end
+
+ local p_negative = C(R("\251\254")) * C(1) / function(b0,b1)
+ -- -1131 .. -108
+ top = top + 1
+ stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108
+ end
+
+ local p_short = P("\28") * C(1) * C(1) / function(b1,b2)
+ -- -32768 .. +32767 : b1<<8 | b2
+ top = top + 1
+ local n = 0x100 * byte(b1) + byte(b2)
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1
+ else
+ stack[top] = n
+ end
+ end
+
+ local p_long = P("\29") * C(1) * C(1) * C(1) * C(1) / function(b1,b2,b3,b4)
+ -- -2^31 .. +2^31-1 : b1<<24 | b2<<16 | b3<<8 | b4
+ top = top + 1
+ local n = 0x1000000 * byte(b1) + 0x10000 * byte(b2) + 0x100 * byte(b3) + byte(b4)
+ if n >= 0x8000000 then
+ stack[top] = n - 0xFFFFFFFF - 1
+ else
+ stack[top] = n
+ end
+ end
+
+ local p_unsupported = P(1) / function(detail)
+ top = 0
+ end
+
+ local p_dictionary = (
+ p_byte
+ + p_positive
+ + p_negative
+ + p_short
+ + p_long
+ + p_nibbles
+ + p_single
+ + p_double
+ + p_unsupported
+ )^1
+
+ parsedictionaries = function(data,dictionaries)
+ stack = { }
+ strings = data.strings
+ for i=1,#dictionaries do
+ top = 0
+ result = {
+ monospaced = false,
+ italicangle = 0,
+ underlineposition = -100,
+ underlinethickness = 50,
+ painttype = 0,
+ charstringtype = 2,
+ fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 },
+ fontbbox = { 0, 0, 0, 0 },
+ strokewidth = 0,
+ charset = 0,
+ encoding = 0,
+ cid = {
+ fontversion = 0,
+ fontrevision = 0,
+ fonttype = 0,
+ count = 8720,
+ }
+ }
+ lpegmatch(p_dictionary,dictionaries[i])
+ dictionaries[i] = result
+ end
+ --
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+ parseprivates = function(data,dictionaries)
+ stack = { }
+ strings = data.strings
+ for i=1,#dictionaries do
+ local private = dictionaries[i].private
+ if private and private.data then
+ top = 0
+ result = {
+ forcebold = false,
+ languagegroup = 0,
+ expansionfactor = 0.06,
+ initialrandomseed = 0,
+ subroutines = 0,
+ defaultwidthx = 0,
+ nominalwidthx = 0,
+ cid = {
+ -- actually an error
+ },
+ }
+ lpegmatch(p_dictionary,private.data)
+ private.data = result
+ end
+ end
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+ -- All bezier curves have 6 points with successive pairs relative to
+ -- the previous pair. Some can be left out and are then copied or zero
+ -- (optimization).
+ --
+ -- We are not really interested in all the details of a glyph because we
+ -- only need to calculate the boundingbox. So, todo: a quick no result but
+ -- calculate only variant.
+ --
+ -- The conversion is straightforward and the specification os clear once
+ -- you understand that the x and y needs to be updates each step. It's also
+ -- quite easy to test because in mp a shape will look bad when a few variables
+ -- are swapped. But still there might be bugs down here because not all
+ -- variants are seen in a font so far. We are less compact that the ff code
+ -- because there quite some variants are done in one helper with a lot of
+ -- testing for states.
+
+ local x = 0
+ local y = 0
+ local width = false
+ local r = 0
+ local stems = 0
+ local globalbias = 0
+ local localbias = 0
+ local globals = false
+ local locals = false
+ local depth = 1
+ local xmin = 0
+ local xmax = 0
+ local ymin = 0
+ local ymax = 0
+ local checked = false
+ local keepcurve = false
+
+ local function showstate(where)
+ report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
+ end
+
+ local function showvalue(where,value,showstack)
+ if showstack then
+ report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top)
+ else
+ report("%w%-10s : %s",depth*2,where,tostring(value))
+ end
+ end
+
+ -- All these indirect calls make this run slower but it's cleaner this way
+ -- and we cache the result. As we moved the boundingbox code inline we gain
+ -- some back.
+
+ local function moveto(x,y)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x, y, "m" }
+ end
+ if checked then
+ 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
+ else
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
+ checked = true
+ end
+ end
+
+ local function lineto(x,y)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x, y, "l" }
+ end
+ if checked then
+ 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
+ else
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
+ checked = true
+ end
+ end
+
+ local function curveto(x1,y1,x2,y2,x3,y3)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x1, y1, x2, y2, x3, y3, "c" }
+ end
+ if checked 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
+ else
+ xmin = x1
+ ymin = y1
+ xmax = x1
+ ymax = y1
+ checked = true
+ end
+ if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end
+ if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end
+ if x3 < xmin then xmin = x3 elseif x3 > xmax then xmax = x3 end
+ if y3 < ymin then ymin = y3 elseif y3 > ymax then ymax = y3 end
+ end
+
+ local function rmoveto()
+ if top > 2 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("rmoveto")
+ end
+ x = x + stack[top-1] -- dx1
+ y = y + stack[top] -- dy1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function hmoveto()
+ if top > 1 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("hmoveto")
+ end
+ x = x + stack[top] -- dx1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function vmoveto()
+ if top > 1 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("vmoveto")
+ end
+ y = y + stack[top] -- dy1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function rlineto()
+ if trace_charstrings then
+ showstate("rlineto")
+ end
+ for i=1,top,2 do
+ x = x + stack[i] -- dxa
+ y = y + stack[i+1] -- dya
+ lineto(x,y)
+ end
+ top = 0
+ end
+
+ local function xlineto(swap) -- x (y,x)+ | (x,y)+
+ for i=1,top do
+ if swap then
+ x = x + stack[i]
+ swap = false
+ else
+ y = y + stack[i]
+ swap = true
+ end
+ lineto(x,y)
+ end
+ top = 0
+ end
+
+ local function hlineto() -- x (y,x)+ | (x,y)+
+ if trace_charstrings then
+ showstate("hlineto")
+ end
+ xlineto(true)
+ end
+
+ local function vlineto() -- y (x,y)+ | (y,x)+
+ if trace_charstrings then
+ showstate("vlineto")
+ end
+ xlineto(false)
+ end
+
+ local function rrcurveto()
+ if trace_charstrings then
+ showstate("rrcurveto")
+ end
+ for i=1,top,6 do
+ local ax = x + stack[i] -- dxa
+ local ay = y + stack[i+1] -- dya
+ local bx = ax + stack[i+2] -- dxb
+ local by = ay + stack[i+3] -- dyb
+ x = bx + stack[i+4] -- dxc
+ y = by + stack[i+5] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function hhcurveto()
+ if trace_charstrings then
+ showstate("hhcurveto")
+ end
+ local s = 1
+ if top % 2 ~= 0 then
+ y = y + stack[1] -- dy1
+ s = 2
+ end
+ for i=s,top,4 do
+ local ax = x + stack[i] -- dxa
+ local ay = y
+ local bx = ax + stack[i+1] -- dxb
+ local by = ay + stack[i+2] -- dyb
+ x = bx + stack[i+3] -- dxc
+ y = by
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function vvcurveto()
+ if trace_charstrings then
+ showstate("vvcurveto")
+ end
+ local s = 1
+ local d = 0
+ if top % 2 ~= 0 then
+ d = stack[1] -- dx1
+ s = 2
+ end
+ for i=s,top,4 do
+ local ax = x + d
+ local ay = y + stack[i] -- dya
+ local bx = ax + stack[i+1] -- dxb
+ local by = ay + stack[i+2] -- dyb
+ x = bx
+ y = by + stack[i+3] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ d = 0
+ end
+ top = 0
+ end
+
+ local function xxcurveto(swap)
+ local last = top % 4 ~= 0 and stack[top]
+ if last then
+ top = top - 1
+ end
+ local sw = swap
+ for i=1,top,4 do
+ local ax, ay, bx, by
+ if swap then
+ ax = x + stack[i]
+ ay = y
+ bx = ax + stack[i+1]
+ by = ay + stack[i+2]
+ y = by + stack[i+3]
+ if last and i+3 == top then
+ x = bx + last
+ else
+ x = bx
+ end
+ swap = false
+ else
+ ax = x
+ ay = y + stack[i]
+ bx = ax + stack[i+1]
+ by = ay + stack[i+2]
+ x = bx + stack[i+3]
+ if last and i+3 == top then
+ y = by + last
+ else
+ y = by
+ end
+ swap = true
+ end
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function hvcurveto()
+ if trace_charstrings then
+ showstate("hvcurveto")
+ end
+ xxcurveto(true)
+ end
+
+ local function vhcurveto()
+ if trace_charstrings then
+ showstate("vhcurveto")
+ end
+ xxcurveto(false)
+ end
+
+ local function rcurveline()
+ if trace_charstrings then
+ showstate("rcurveline")
+ end
+ for i=1,top-2,6 do
+ local ax = x + stack[i] -- dxa
+ local ay = y + stack[i+1] -- dya
+ local bx = ax + stack[i+2] -- dxb
+ local by = ay + stack[i+3] -- dyb
+ x = bx + stack[i+4] -- dxc
+ y = by + stack[i+5] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ end
+ x = x + stack[top-1] -- dxc
+ y = y + stack[top] -- dyc
+ lineto(x,y)
+ top = 0
+ end
+
+ local function rlinecurve()
+ if trace_charstrings then
+ showstate("rlinecurve")
+ end
+ if top > 6 then
+ for i=1,top-6,2 do
+ x = x + stack[i]
+ y = y + stack[i+1]
+ lineto(x,y)
+ end
+ end
+ local ax = x + stack[top-5]
+ local ay = y + stack[top-4]
+ local bx = ax + stack[top-3]
+ local by = ay + stack[top-2]
+ x = bx + stack[top-1]
+ y = by + stack[top]
+ curveto(ax,ay,bx,by,x,y)
+ top = 0
+ end
+
+ -- flex is not yet tested! no loop
+
+ local function flex() -- fd not used
+ if trace_charstrings then
+ showstate("flex")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y + stack[2] -- dy1
+ local bx = ax + stack[3] -- dx2
+ local by = ay + stack[4] -- dy2
+ local cx = bx + stack[5] -- dx3
+ local cy = by + stack[6] -- dy3
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[7] -- dx4
+ local dy = cy + stack[8] -- dy4
+ local ex = dx + stack[9] -- dx5
+ local ey = dy + stack[10] -- dy5
+ x = ex + stack[11] -- dx6
+ y = ey + stack[12] -- dy6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function hflex()
+ if trace_charstrings then
+ showstate("hflex")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y
+ local bx = ax + stack[2] -- dx2
+ local by = ay + stack[3] -- dy2
+ local cx = bx + stack[4] -- dx3
+ local cy = by
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[5] -- dx4
+ local dy = by
+ local ex = dx + stack[6] -- dx5
+ local ey = y
+ x = ex + stack[7] -- dx6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function hflex1()
+ if trace_charstrings then
+ showstate("hflex1")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y + stack[2] -- dy1
+ local bx = ax + stack[3] -- dx2
+ local by = ay + stack[4] -- dy2
+ local cx = bx + stack[5] -- dx3
+ local cy = by
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[6] -- dx4
+ local dy = by
+ local ex = dx + stack[7] -- dx5
+ local ey = dy + stack[8] -- dy5
+ x = ex + stack[9] -- dx6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function flex1()
+ if trace_charstrings then
+ showstate("flex1")
+ end
+ local ax = x + stack[1] --dx1
+ local ay = y + stack[2] --dy1
+ local bx = ax + stack[3] --dx2
+ local by = ay + stack[4] --dy2
+ local cx = bx + stack[5] --dx3
+ local cy = by + stack[6] --dy3
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[7] --dx4
+ local dy = cy + stack[8] --dy4
+ local ex = dx + stack[9] --dx5
+ local ey = dy + stack[10] --dy5
+ if abs(ex - x) > abs(ey - y) then -- spec: abs(dx) > abs(dy)
+ x = ex + stack[11]
+ else
+ y = ey + stack[11]
+ end
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function getstem()
+ if top == 0 then
+ -- bad
+ elseif top % 2 ~= 0 then
+ if width then
+ remove(stack,1)
+ else
+ width = remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top = top - 1
+ end
+ if trace_charstrings then
+ showstate("stem")
+ end
+ stems = stems + top/2
+ top = 0
+ end
+
+ local function getmask()
+ if top == 0 then
+ -- bad
+ elseif top % 2 ~= 0 then
+ if width then
+ remove(stack,1)
+ else
+ width = remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top = top - 1
+ end
+ if trace_charstrings then
+ showstate(operator == 19 and "hintmark" or "cntrmask")
+ end
+ stems = stems + top/2
+ top = 0
+ if stems == 0 then
+ -- forget about it
+ elseif stems <= 8 then
+ return 1
+ else
+ return floor((stems+7)/8)
+ end
+ end
+
+ local function unsupported()
+ if trace_charstrings then
+ showstate("unsupported")
+ end
+ top = 0
+ end
+
+ -- Bah, we cannot use a fast lpeg because a hint has an unknown size and a
+ -- runtime capture cannot handle that well.
+
+ local actions = { [0] =
+ unsupported, -- 0
+ getstem, -- 1 -- hstem
+ unsupported, -- 2
+ getstem, -- 3 -- vstem
+ vmoveto, -- 4
+ rlineto, -- 5
+ hlineto, -- 6
+ vlineto, -- 7
+ rrcurveto, -- 8
+ unsupported, -- 9 -- closepath
+ unsupported, -- 10 -- calllocal,
+ unsupported, -- 11 -- callreturn,
+ unsupported, -- 12 -- elsewhere
+ unsupported, -- 13 -- hsbw
+ unsupported, -- 14 -- endchar,
+ unsupported, -- 15
+ unsupported, -- 16
+ unsupported, -- 17
+ getstem, -- 18 -- hstemhm
+ getmask, -- 19 -- hintmask
+ getmask, -- 20 -- cntrmask
+ rmoveto, -- 21
+ hmoveto, -- 22
+ getstem, -- 23 -- vstemhm
+ rcurveline, -- 24
+ rlinecurve, -- 25
+ vvcurveto, -- 26
+ hhcurveto, -- 27
+ unsupported, -- 28 -- elsewhere
+ unsupported, -- 29 -- elsewhere
+ vhcurveto, -- 30
+ hvcurveto, -- 31
+ }
+
+ local subactions = {
+ [034] = hflex,
+ [035] = flex,
+ [036] = hflex1,
+ [037] = flex1,
+ }
+
+ local p_bytes = Ct((P(1)/byte)^0)
+
+ local function call(scope,list,bias,process)
+ local index = stack[top] + bias
+ top = top - 1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local str = list[index]
+ if str then
+ if type(str) == "string" then
+ str = lpegmatch(p_bytes,str)
+ list[index] = str
+ end
+ depth = depth + 1
+ process(str)
+ depth = depth - 1
+ else
+ report("unknown %s %i",scope,index)
+ end
+ end
+
+ local function process(tab)
+ local i = 1
+ local n = #tab
+ while i <= n do
+ local t = tab[i]
+ if t >= 32 and t<=246 then
+ -- -107 .. +107
+ top = top + 1
+ stack[top] = t - 139
+ i = i + 1
+ elseif t >= 247 and t <= 250 then
+ -- +108 .. +1131
+ top = top + 1
+ stack[top] = (t-247)*256 + tab[i+1] + 108
+ i = i + 2
+ elseif t >= 251 and t <= 254 then
+ -- -1131 .. -108
+ top = top + 1
+ stack[top] = -(t-251)*256 - tab[i+1] - 108
+ i = i + 2
+ elseif t == 28 then
+ -- -32768 .. +32767 : b1<<8 | b2
+ top = top + 1
+ local n = 0x100 * tab[i+1] + tab[i+2]
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1
+ else
+ stack[top] = n
+ end
+ i = i + 3
+ elseif t == 255 then
+ local n = 0x100 * tab[i+1] + tab[i+2]
+ top = top + 1
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ else
+ stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ end
+ i = i + 5
+ elseif t == 11 then
+ if trace_charstrings then
+ showstate("return")
+ end
+ return
+ elseif t == 10 then
+ call("local",locals,localbias,process)
+ i = i + 1
+ elseif t == 14 then -- endchar
+ if width then
+ -- okay
+ elseif top > 0 then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ else
+ width = true
+ end
+ if trace_charstrings then
+ showstate("endchar")
+ end
+ return
+ elseif t == 29 then
+ call("global",globals,globalbias,process)
+ i = i + 1
+ elseif t == 12 then
+ i = i + 1
+ local t = tab[i]
+ local a = subactions[t]
+ if a then
+ a()
+ else
+ if trace_charstrings then
+ showvalue("<subaction>",t)
+ end
+ top = 0
+ end
+ i = i + 1
+ else
+ local a = actions[t]
+ if a then
+ local s = a()
+ if s then
+ i = i + s
+ end
+ else
+ if trace_charstrings then
+ showvalue("<action>",t)
+ end
+ top = 0
+ end
+ i = i + 1
+ end
+ end
+ end
+
+ -- local function calculatebounds(segments,x,y)
+ -- local nofsegments = #segments
+ -- if nofsegments == 0 then
+ -- return { x, y, x, y }
+ -- else
+ -- local xmin = 10000
+ -- local xmax = -10000
+ -- local ymin = 10000
+ -- local ymax = -10000
+ -- if x < xmin then xmin = x end
+ -- if x > xmax then xmax = x end
+ -- if y < ymin then ymin = y end
+ -- if y > ymax then ymax = y end
+ -- -- we now have a reasonable start so we could
+ -- -- simplyfy the next checks
+ -- for i=1,nofsegments do
+ -- local s = segments[i]
+ -- local x = s[1]
+ -- local y = s[2]
+ -- if x < xmin then xmin = x end
+ -- if x > xmax then xmax = x end
+ -- if y < ymin then ymin = y end
+ -- if y > ymax then ymax = y end
+ -- if s[#s] == "c" then -- "curveto"
+ -- local x = s[3]
+ -- local y = s[4]
+ -- 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
+ -- local x = s[5]
+ -- local y = s[6]
+ -- 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
+ -- end
+ -- end
+ -- return { round(xmin), round(ymin), round(xmax), round(ymax) } -- doesn't make ceil more sense
+ -- end
+ -- end
+
+ parsecharstrings = function(data,glyphs,doshapes)
+ -- for all charstrings
+ local dictionary = data.dictionaries[1]
+ local charstrings = dictionary.charstrings
+ local charset = dictionary.charset
+ keepcurve = doshapes
+ stack = { }
+ glyphs = glyphs or { }
+ strings = data.strings
+ locals = dictionary.subroutines
+ globals = data.routines
+ globalbias = #globals
+ localbias = #locals
+ globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
+ localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
+ local nominalwidth = dictionary.private.data.nominalwidthx or 0
+ local defaultwidth = dictionary.private.data.defaultwidthx or 0
+
+ for i=1,#charstrings do
+ local str = charstrings[i]
+ local tab = lpegmatch(p_bytes,str)
+ local index = i - 1
+ x = 0
+ y = 0
+ width = false
+ r = 0
+ top = 0
+ stems = 0
+ result = { }
+ --
+ xmin = 0
+ xmax = 0
+ ymin = 0
+ ymax = 0
+ checked = false
+ --
+ if trace_charstrings then
+ report("glyph: %i",index)
+ report("data: % t",tab)
+ end
+ --
+ process(tab)
+ --
+ local boundingbox = { round(xmin), round(ymin), round(xmax), round(ymax) }
+ --
+ if width == true or width == false then
+ width = defaultwidth
+ else
+ width = nominalwidth + width
+ end
+ --
+ -- trace_charstrings = index == 3078 -- todo: make tracker
+ local glyph = glyphs[index] -- can be autodefined in otr
+ if not glyph then
+ glyphs[index] = {
+ segments = doshapes ~= false and result or nil, -- optional
+ boundingbox = boundingbox,
+ width = width,
+ name = charset[index],
+ -- sidebearing = 0,
+ }
+ else
+ glyph.segments = doshapes ~= false and result or nil
+ glyph.boundingbox = boundingbox
+ if not glyph.width then
+ glyph.width = width
+ end
+ if charset and not glyph.name then
+ glyph.name = charset[index]
+ end
+ -- glyph.sidebearing = 0 -- todo
+ end
+ if trace_charstrings then
+ report("width: %s",tostring(width))
+ report("boundingbox: % t",boundingbox)
+ end
+ charstrings[i] = nil -- free memory
+ end
+ return glyphs
+ end
+
+ parsecharstring = function(data,dictionary,charstring,glyphs,index,doshapes)
+ local private = dictionary.private
+ keepcurve = doshapes
+ strings = data.strings -- or in dict?
+ locals = dictionary.subroutines or { }
+ globals = data.routines or { }
+ globalbias = #globals
+ localbias = #locals
+ globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
+ localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
+ local nominalwidth = private and private.data.nominalwidthx or 0
+ local defaultwidth = private and private.data.defaultwidthx or 0
+ --
+ local tab = lpegmatch(p_bytes,charstring)
+ x = 0
+ y = 0
+ width = false
+ r = 0
+ top = 0
+ stems = 0
+ result = { }
+ --
+ xmin = 0
+ xmax = 0
+ ymin = 0
+ ymax = 0
+ checked = false
+ --
+ if trace_charstrings then
+ report("glyph: %i",index)
+ report("data: % t",tab)
+ end
+ --
+ process(tab)
+ --
+ local boundingbox = { xmin, ymin, xmax, ymax }
+ --
+ if width == true or width == false then
+ width = defaultwidth
+ else
+ width = nominalwidth + width
+ end
+ --
+index = index - 1
+ local glyph = glyphs[index] -- can be autodefined in otr
+ if not glyph then
+ glyphs[index] = {
+ segments = doshapes ~= false and result or nil, -- optional
+ boundingbox = boundingbox,
+ width = width,
+ name = charset[index],
+ -- sidebearing = 0,
+ }
+ else
+ glyph.segments = doshapes ~= false and result or nil
+ glyph.boundingbox = boundingbox
+ if not glyph.width then
+ glyph.width = width
+ end
+ if charset and not glyph.name then
+ glyph.name = charset[index]
+ end
+ -- glyph.sidebearing = 0 -- todo
+ end
+ --
+ if trace_charstrings then
+ report("width: %s",tostring(width))
+ report("boundingbox: % t",boundingbox)
+ end
+ --
+ return charstring
+ end
+
+ resetcharstrings = function()
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+end
+
+local function readglobals(f,data)
+ local routines = readlengths(f)
+ for i=1,#routines do
+ routines[i] = readstring(f,routines[i])
+ end
+ data.routines = routines
+end
+
+local function readencodings(f,data)
+ data.encodings = { }
+end
+
+local function readcharsets(f,data,dictionary)
+ local header = data.header
+ local strings = data.strings
+ local nofglyphs = data.nofglyphs
+ local charsetoffset = dictionary.charset
+
+ if charsetoffset ~= 0 then
+ setposition(f,header.offset+charsetoffset)
+ local format = readbyte(f)
+ local charset = { [0] = ".notdef" }
+ dictionary.charset = charset
+ if format == 0 then
+ for i=1,nofglyphs do
+ charset[i] = strings[readushort(f)]
+ end
+ elseif format == 1 or format == 2 then
+ local readcount = format == 1 and readbyte or readushort
+ local i = 1
+ while i <= nofglyphs do
+ local sid = readushort(f)
+ local n = readcount(f)
+ for s=sid,sid+n do
+ charset[i] = strings[s]
+ i = i + 1
+ if i > nofglyphs then
+ break
+ end
+ end
+ end
+ else
+ report("cff parser: unsupported charset format %a",format)
+ end
+ end
+end
+
+local function readprivates(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local private = dictionaries[1].private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data = readstring(f,private.size)
+ end
+end
+
+local function readlocals(f,data,dictionary)
+ local header = data.header
+ local private = dictionary.private
+ if private then
+ local subroutineoffset = private.data.subroutines
+ if subroutineoffset ~= 0 then
+ setposition(f,header.offset+private.offset+subroutineoffset)
+ local subroutines = readlengths(f)
+ for i=1,#subroutines do
+ subroutines[i] = readstring(f,subroutines[i])
+ end
+ dictionary.subroutines = subroutines
+ private.data.subroutines = nil
+ else
+ dictionary.subroutines = { }
+ end
+ else
+ dictionary.subroutines = { }
+ end
+end
+
+-- These charstrings are little programs and described in: Technical Note #5177. A truetype
+-- font has only one dictionary.
+
+local function readcharstrings(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ local type = dictionary.charstringtype
+ local offset = dictionary.charstrings
+ if type == 2 then
+ setposition(f,header.offset+offset)
+ -- could be a metatable .. delayed loading
+ local charstrings = readlengths(f)
+ local nofglyphs = #charstrings
+ for i=1,nofglyphs do
+ charstrings[i] = readstring(f,charstrings[i])
+ end
+ data.nofglyphs = nofglyphs
+ dictionary.charstrings = charstrings
+ else
+ report("unsupported charstr type %i",type)
+ data.nofglyphs = 0
+ dictionary.charstrings = { }
+ end
+end
+
+-- cid (maybe do this stepwise so less mem) -- share with above
+
+local function readcidprivates(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries[1].cid.dictionaries
+ for i=1,#dictionaries do
+ local dictionary = dictionaries[i]
+ local private = dictionary.private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data = readstring(f,private.size)
+ end
+ end
+ parseprivates(data,dictionaries)
+end
+
+local function readnoselect(f,data,glyphs,doshapes)
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ readglobals(f,data)
+ readcharstrings(f,data)
+ readencodings(f,data)
+ readcharsets(f,data,dictionary)
+ readprivates(f,data)
+ parseprivates(data,data.dictionaries)
+ readlocals(f,data,dictionary)
+ parsecharstrings(data,glyphs,doshapes)
+ resetcharstrings()
+end
+
+local function readfdselect(f,data,glyphs,doshapes)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ local cid = dictionary.cid
+ local cidselect = cid and cid.fdselect
+ readglobals(f,data)
+ readcharstrings(f,data)
+ readencodings(f,data)
+ local charstrings = dictionary.charstrings
+ local fdindex = { }
+ local nofglyphs = data.nofglyphs
+ local maxindex = -1
+ setposition(f,header.offset+cidselect)
+ local format = readbyte(f)
+ if format == 1 then
+ for i=0,nofglyphs do -- notdef included (needs checking)
+ local index = readbyte(i)
+ fdindex[i] = index
+ if index > maxindex then
+ maxindex = index
+ end
+ end
+ elseif format == 3 then
+ local nofranges = readushort(f)
+ local first = readushort(f)
+ local index = readbyte(f)
+ while true do
+ local last = readushort(f)
+ if index > maxindex then
+ maxindex = index
+ end
+ for i=first,last do
+ fdindex[i] = index
+ end
+ if last >= nofglyphs then
+ break
+ else
+ first = last + 1
+ index = readbyte(f)
+ end
+ end
+ else
+ -- unsupported format
+ end
+ 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
+ for i=1,#charstrings do
+ parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes)
+ end
+ resetcharstrings()
+ end
+end
+
+function readers.cff(f,fontdata,specification)
+-- if specification.glyphs then
+ if specification.details then
+ local datatable = fontdata.tables.cff
+ if datatable then
+ local offset = datatable.offset
+ local glyphs = fontdata.glyphs
+ if not f then
+ report("invalid filehandle")
+ return
+ end
+ if offset then
+ setposition(f,offset)
+ end
+ local header = readheader(f)
+ if header.major > 1 then
+ report("version mismatch")
+ return
+ end
+ local names = readfontnames(f)
+ local dictionaries = readtopdictionaries(f)
+ local strings = readstrings(f)
+ local data = {
+ header = header,
+ names = names,
+ dictionaries = dictionaries,
+ strings = strings,
+ nofglyphs = fontdata.nofglyphs,
+ }
+ --
+ parsedictionaries(data,data.dictionaries)
+ --
+ local d = dictionaries[1]
+ local c = d.cid
+ fontdata.cffinfo = {
+ familynamename = d.familyname,
+ fullname = d.fullname,
+ boundingbox = d.boundingbox,
+ weight = d.weight,
+ italicangle = d.italicangle,
+ underlineposition = d.underlineposition,
+ underlinethickness = d.underlinethickness,
+ monospaced = d.monospaced,
+ }
+ fontdata.cidinfo = c and {
+ registry = c.registry,
+ ordering = c.ordering,
+ supplement = c.supplement,
+ }
+ --
+ if not specification.glyphs then
+ -- we only want some metadata
+ else
+ local cid = d.cid
+ if cid and cid.fdselect then
+ readfdselect(f,data,glyphs,specification.shapes or false)
+ else
+ readnoselect(f,data,glyphs,specification.shapes or false)
+ end
+ end
+ --
+ -- cleanup (probably more can go)
+ --
+ -- for i=1,#dictionaries do
+ -- local d = dictionaries[i]
+ -- d.subroutines = nil
+ -- end
+ -- data.strings = nil
+ -- if data then
+ -- data.charstrings = nil
+ -- data.routines = nil
+ -- end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua
new file mode 100644
index 00000000000..5b1ad992070
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua
@@ -0,0 +1,462 @@
+if not modules then modules = { } end modules ['font-chk'] = {
+ 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"
+}
+
+-- possible optimization: delayed initialization of vectors
+-- move to the nodes namespace
+
+local next = next
+
+local formatters = string.formatters
+local bpfactor = number.dimenfactors.bp
+local fastcopy = table.fastcopy
+
+local report_fonts = logs.reporter("fonts","checking")
+
+local allocate = utilities.storage.allocate
+
+local fonts = fonts
+
+fonts.checkers = fonts.checkers or { }
+local checkers = fonts.checkers
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+
+local helpers = fonts.helpers
+
+local addprivate = helpers.addprivate
+local hasprivate = helpers.hasprivate
+local getprivatenode = helpers.getprivatenode
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+local afmfeatures = fonts.constructors.newfeatures("afm")
+local registerafmfeature = afmfeatures.register
+
+local is_character = characters.is_character
+local chardata = characters.data
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
+
+local implement = interfaces.implement
+
+local glyph_code = nodes.nodecodes.glyph
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+
+local setfield = nuts.setfield
+local setchar = nuts.setchar
+
+local traverse_id = nuts.traverse_id
+local remove_node = nuts.remove
+local insert_node_after = nuts.insert_after
+
+-- maybe in fonts namespace
+-- deletion can be option
+
+local action = false
+
+-- to tfmdata.properties ?
+
+local function onetimemessage(font,char,message) -- char == false returns table
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared
+ local messages = shared.messages
+ if not messages then
+ messages = { }
+ shared.messages = messages
+ end
+ local category = messages[message]
+ if not category then
+ category = { }
+ messages[message] = category
+ end
+ if char == false then
+ return table.sortedkeys(category)
+ elseif not category[char] then
+ report_fonts("char %C in font %a with id %a: %s",char,tfmdata.properties.fullname,font,message)
+ category[char] = true
+ end
+end
+
+fonts.loggers.onetimemessage = onetimemessage
+
+local mapping = allocate { -- this is just an experiment to illustrate some principles elsewhere
+ lu = "placeholder uppercase red",
+ ll = "placeholder lowercase red",
+ lt = "placeholder uppercase red",
+ lm = "placeholder lowercase red",
+ lo = "placeholder lowercase red",
+ mn = "placeholder mark green",
+ mc = "placeholder mark green",
+ me = "placeholder mark green",
+ nd = "placeholder lowercase blue",
+ nl = "placeholder lowercase blue",
+ no = "placeholder lowercase blue",
+ pc = "placeholder punctuation cyan",
+ pd = "placeholder punctuation cyan",
+ ps = "placeholder punctuation cyan",
+ pe = "placeholder punctuation cyan",
+ pi = "placeholder punctuation cyan",
+ pf = "placeholder punctuation cyan",
+ po = "placeholder punctuation cyan",
+ sm = "placeholder lowercase magenta",
+ sc = "placeholder lowercase yellow",
+ sk = "placeholder lowercase yellow",
+ so = "placeholder lowercase yellow",
+}
+
+table.setmetatableindex(mapping,
+ function(t,k)
+ v = "placeholder unknown gray"
+ t[k] = v
+ return v
+ end
+)
+
+local fakes = allocate {
+ {
+ name = "lowercase",
+ code = ".025 -.175 m .425 -.175 l .425 .525 l .025 .525 l .025 -.175 l .025 0 l .425 0 l .025 -.175 m h S",
+ width = .45,
+ height = .55,
+ depth = .20,
+ },
+ {
+ name = "uppercase",
+ code = ".025 -.225 m .625 -.225 l .625 .675 l .025 .675 l .025 -.225 l .025 0 l .625 0 l .025 -.225 m h S",
+ width = .65,
+ height = .70,
+ depth = .25,
+ },
+ {
+ name = "mark",
+ code = ".025 .475 m .125 .475 l .125 .675 l .025 .675 l .025 .475 l h B",
+ width = .15,
+ height = .70,
+ depth = -.50,
+ },
+ {
+ name = "punctuation",
+ code = ".025 -.175 m .125 -.175 l .125 .525 l .025 .525 l .025 -.175 l h B",
+ width = .15,
+ height = .55,
+ depth = .20,
+ },
+ {
+ name = "unknown",
+ code = ".025 0 m .425 0 l .425 .175 l .025 .175 l .025 0 l h B",
+ width = .45,
+ height = .20,
+ depth = 0,
+ },
+}
+
+local variants = allocate {
+ { tag = "gray", r = .6, g = .6, b = .6 },
+ { tag = "red", r = .6, g = 0, b = 0 },
+ { tag = "green", r = 0, g = .6, b = 0 },
+ { tag = "blue", r = 0, g = 0, b = .6 },
+ { tag = "cyan", r = 0, g = .6, b = .6 },
+ { tag = "magenta", r = .6, g = 0, b = .6 },
+ { tag = "yellow", r = .6, g = .6, b = 0 },
+}
+
+local pdf_blob = "pdf: q %0.6F 0 0 %0.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+
+local cache = { } -- saves some tables but not that impressive
+
+local function addmissingsymbols(tfmdata) -- we can have an alternative with rules
+ local characters = tfmdata.characters
+ local size = tfmdata.parameters.size
+ local privates = tfmdata.properties.privates
+ local scale = size * bpfactor
+ for i=1,#variants do
+ local v = variants[i]
+ local tag, r, g, b = v.tag, v.r, v.g, v.b
+ for i =1, #fakes do
+ local fake = fakes[i]
+ local name = fake.name
+ local privatename = formatters["placeholder %s %s"](name,tag)
+ if not hasprivate(tfmdata,privatename) then
+ local hash = formatters["%s_%s_%s_%s_%s_%s"](name,tag,r,g,b,size)
+ local char = cache[hash]
+ if not char then
+ char = {
+ width = size*fake.width,
+ height = size*fake.height,
+ depth = size*fake.depth,
+ -- 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) } }
+ }
+ cache[hash] = char
+ end
+ addprivate(tfmdata, privatename, char)
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "missing",
+ description = "missing symbols",
+ manipulators = {
+ base = addmissingsymbols,
+ node = addmissingsymbols,
+ }
+}
+
+fonts.loggers.add_placeholders = function(id) addmissingsymbols(fontdata[id or true]) end
+fonts.loggers.category_to_placeholder = mapping
+
+function commands.getplaceholderchar(name)
+ local id = font.current()
+ addmissingsymbols(fontdata[id])
+ context(helpers.getprivatenode(fontdata[id],name))
+end
+
+local function placeholder(font,char)
+ local tfmdata = fontdata[font]
+ local properties = tfmdata.properties
+ local privates = properties.privates
+ local category = chardata[char].category
+ local fakechar = mapping[category]
+ local p = privates and privates[fakechar]
+ if not p then
+ addmissingsymbols(tfmdata)
+ p = properties.privates[fakechar]
+ end
+ if properties.lateprivates then
+ -- frozen already
+ return "node", getprivatenode(tfmdata,fakechar)
+ else
+ -- good, we have \definefontfeature[default][default][missing=yes]
+ return "char", p
+ end
+end
+
+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)
+ if font ~= lastfont then
+ characters = fontcharacters[font]
+ lastfont = font
+ end
+ if not characters[char] and is_character[chardata[char].category] then
+ if action == "remove" then
+ onetimemessage(font,char,"missing (will be deleted)")
+ elseif action == "replace" then
+ onetimemessage(font,char,"missing (will be flagged)")
+ else
+ onetimemessage(font,char,"missing")
+ end
+ if not found then
+ found = { n }
+ else
+ found[#found+1] = n
+ end
+ end
+ end
+ if not found then
+ -- all well
+ elseif action == "remove" then
+ for i=1,#found do
+ head = remove_node(head,found[i],true)
+ end
+ elseif action == "replace" then
+ for i=1,#found do
+ local node = found[i]
+ local kind, char = placeholder(getfont(node),getchar(node))
+ if kind == "node" then
+ insert_node_after(head,node,tonut(char))
+ head = remove_node(head,node,true)
+ elseif kind == "char" then
+ setchar(node,char)
+ else
+ -- error
+ end
+ end
+ else
+ -- maye write a report to the log
+ end
+ return tonode(head), false
+end
+
+local relevant = {
+ "missing (will be deleted)",
+ "missing (will be flagged)",
+ "missing"
+}
+
+local function getmissing(id)
+ if id then
+ local list = getmissing(font.current())
+ if list then
+ local _, list = next(getmissing(font.current()))
+ return list
+ else
+ return { }
+ end
+ else
+ local t = { }
+ for id, d in next, fontdata do
+ local shared = d.shared
+ local messages = shared.messages
+ if messages then
+ local tf = t[d.properties.filename] or { }
+ for i=1,#relevant do
+ local tm = messages[relevant[i]]
+ if tm then
+ tf = table.merged(tf,tm)
+ end
+ end
+ if next(tf) then
+ t[d.properties.filename] = tf
+ end
+ end
+ end
+ for k, v in next, t do
+ t[k] = table.sortedkeys(v)
+ end
+ return t
+ end
+end
+
+checkers.getmissing = getmissing
+
+local tracked = false
+
+trackers.register("fonts.missing", function(v)
+ if v then
+ enableaction("processors","fonts.checkers.missing")
+ tracked = true
+ else
+ disableaction("processors","fonts.checkers.missing")
+ end
+ if v == "replace" then
+ otffeatures.defaults.missing = true
+ end
+ action = v
+end)
+
+local report_characters = logs.reporter("fonts","characters")
+local report_character = logs.reporter("missing")
+
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+
+luatex.registerstopactions(function()
+ if tracked then
+ local collected = checkers.getmissing()
+ if next(collected) then
+ logspushtarget("logfile")
+ for filename, list in table.sortedhash(collected) do
+ logsnewline()
+ report_characters("start missing characters: %s",filename)
+ logsnewline()
+ for i=1,#list do
+ local u = list[i]
+ report_character("%U %c %s",u,u,chardata[u].description)
+ end
+ logsnewline()
+ report_characters("stop missing characters")
+ logsnewline()
+ end
+ logspoptarget()
+ end
+ end
+end)
+
+-- for the moment here
+
+local function expandglyph(characters,index,done)
+ done = done or { }
+ if not done[index] then
+ local data = characters[index]
+ if data then
+ done[index] = true
+ local d = fastcopy(data)
+ local n = d.next
+ if n then
+ d.next = expandglyph(characters,n,done)
+ end
+ local h = d.horiz_variants
+ if h then
+ for i=1,#h do
+ h[i].glyph = expandglyph(characters,h[i].glyph,done)
+ end
+ end
+ local v = d.vert_variants
+ if v then
+ for i=1,#v do
+ v[i].glyph = expandglyph(characters,v[i].glyph,done)
+ end
+ end
+ return d
+ end
+ end
+end
+
+helpers.expandglyph = expandglyph
+
+-- should not be needed as we add .notdef in the engine
+
+local dummyzero = {
+ -- width = 0,
+ -- height = 0,
+ -- depth = 0,
+ commands = { { "special", "" } },
+}
+
+local function adddummysymbols(tfmdata,...)
+ local characters = tfmdata.characters
+ if not characters[0] then
+ characters[0] = dummyzero
+ end
+ -- if not characters[1] then
+ -- characters[1] = dummyzero -- test only
+ -- end
+end
+
+registerotffeature {
+ name = "dummies",
+ description = "dummy symbols",
+ default = true,
+ manipulators = {
+ base = adddummysymbols,
+ node = adddummysymbols,
+ }
+}
+
+registerafmfeature {
+ name = "dummies",
+ description = "dummy symbols",
+ default = true,
+ manipulators = {
+ base = adddummysymbols,
+ node = adddummysymbols,
+ }
+}
+
+-- callback.register("char_exists",function(f,c) -- to slow anyway as called often so we should flag in tfmdata
+-- return true
+-- end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-chk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-chk.mkiv
new file mode 100644
index 00000000000..4c8967532e8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-chk.mkiv
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=font-chk,
+%D version=2009.01.02, % moved from font-tra
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Checking}
+
+\registerctxluafile{font-chk}{1.001}
+
+\tracinglostchars\zerocount
+
+% Use this instead:
+%
+% \definefontfeature[default][default][missing=yes]
+% \enabletrackers[fonts.missing=replace]
+
+\unexpanded\def\checkcharactersinfont {\enabletrackers[fonts.missing]}
+\unexpanded\def\removemissingcharacters {\enabletrackers[fonts.missing=remove]}
+\unexpanded\def\replacemissingcharacters{\enabletrackers[fonts.missing=replace]}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-cid.lua b/Master/texmf-dist/tex/context/base/mkiv/font-cid.lua
new file mode 100644
index 00000000000..0eaacdfbd54
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-cid.lua
@@ -0,0 +1,177 @@
+if not modules then modules = { } end modules ['font-cid'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (cidmaps)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, match, lower = string.format, string.match, string.lower
+local tonumber = tonumber
+local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match
+
+local fonts, logs, trackers = fonts, logs, trackers
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+local cid = { }
+fonts.cid = cid
+
+local cidmap = { }
+local cidmax = 10
+
+-- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
+--
+-- 18964 18964 (leader)
+-- 0 /.notdef
+-- 1..95 0020
+-- 99 3000
+
+local number = C(R("09","af","AF")^1)
+local space = S(" \n\r\t")
+local spaces = space^0
+local period = P(".")
+local periods = period * period
+local name = P("/") * C((1-space)^1)
+
+local unicodes, names = { }, { } -- we could use Carg now
+
+local function do_one(a,b)
+ unicodes[tonumber(a)] = tonumber(b,16)
+end
+
+local function do_range(a,b,c)
+ c = tonumber(c,16)
+ for i=tonumber(a),tonumber(b) do
+ unicodes[i] = c
+ c = c + 1
+ end
+end
+
+local function do_name(a,b)
+ names[tonumber(a)] = b
+end
+
+local grammar = P { "start",
+ start = number * spaces * number * V("series"),
+ series = (spaces * (V("one") + V("range") + V("named")))^1,
+ one = (number * spaces * number) / do_one,
+ range = (number * periods * number * spaces * number) / do_range,
+ named = (number * spaces * name) / do_name
+}
+
+local function loadcidfile(filename)
+ local data = io.loaddata(filename)
+ if data then
+ unicodes, names = { }, { }
+ lpegmatch(grammar,data)
+ local supplement, registry, ordering = match(filename,"^(.-)%-(.-)%-()%.(.-)$")
+ return {
+ supplement = supplement,
+ registry = registry,
+ ordering = ordering,
+ filename = filename,
+ unicodes = unicodes,
+ names = names,
+ }
+ end
+end
+
+cid.loadfile = loadcidfile -- we use the frozen variant
+local template = "%s-%s-%s.cidmap"
+
+local function locate(registry,ordering,supplement)
+ local filename = format(template,registry,ordering,supplement)
+ local hashname = lower(filename)
+ local found = cidmap[hashname]
+ if not found then
+ if trace_loading then
+ report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
+ end
+ local fullname = resolvers.findfile(filename,'cid') or ""
+ if fullname ~= "" then
+ found = loadcidfile(fullname)
+ if found then
+ if trace_loading then
+ report_otf("using cidmap file %a",filename)
+ end
+ cidmap[hashname] = found
+ found.usedname = file.basename(filename)
+ end
+ end
+ end
+ return found
+end
+
+-- cf Arthur R. we can safely scan upwards since cids are downward compatible
+
+function cid.getmap(specification)
+ if not specification then
+ report_otf("invalid cidinfo specification, table expected")
+ return
+ end
+ local registry = specification.registry
+ local ordering = specification.ordering
+ local supplement = specification.supplement
+ local filename = format(registry,ordering,supplement)
+ local lowername = lower(filename)
+ local found = cidmap[lowername]
+ if found then
+ return found
+ end
+ if ordering == "Identity" then
+ local found = {
+ supplement = supplement,
+ registry = registry,
+ ordering = ordering,
+ filename = filename,
+ unicodes = { },
+ names = { },
+ }
+ cidmap[lowername] = found
+ return found
+ end
+ -- check for already loaded file
+ if trace_loading then
+ report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
+ end
+ found = locate(registry,ordering,supplement)
+ if not found then
+ local supnum = tonumber(supplement)
+ local cidnum = nil
+ -- next highest (alternatively we could start high)
+ if supnum < cidmax then
+ for s=supnum+1,cidmax do
+ local c = locate(registry,ordering,s)
+ if c then
+ found, cidnum = c, s
+ break
+ end
+ end
+ end
+ -- next lowest (least worse fit)
+ if not found and supnum > 0 then
+ for s=supnum-1,0,-1 do
+ local c = locate(registry,ordering,s)
+ if c then
+ found, cidnum = c, s
+ break
+ end
+ end
+ end
+ -- prevent further lookups -- somewhat tricky
+ registry = lower(registry)
+ ordering = lower(ordering)
+ if found and cidnum > 0 then
+ for s=0,cidnum-1 do
+ local filename = format(template,registry,ordering,s)
+ if not cidmap[filename] then
+ cidmap[filename] = found
+ end
+ end
+ end
+ end
+ return found
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-col.lua b/Master/texmf-dist/tex/context/base/mkiv/font-col.lua
new file mode 100644
index 00000000000..cf1b60bb93e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-col.lua
@@ -0,0 +1,348 @@
+if not modules then modules = { } end modules ['font-col'] = {
+ 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"
+}
+
+-- possible optimization: delayed initialization of vectors
+-- we should also share equal vectors (math)
+
+local context, commands, trackers, logs = context, commands, trackers, logs
+local node, nodes, fonts, characters = node, nodes, fonts, characters
+local file, lpeg, table, string = file, lpeg, table, string
+
+local type, next, toboolean = type, next, toboolean
+local gmatch = string.gmatch
+local fastcopy = table.fastcopy
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+
+local setfield = nuts.setfield
+local setchar = nuts.setchar
+
+local traverse_id = nuts.traverse_id
+local traverse_char = nuts.traverse_char
+
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end)
+
+local report_fonts = logs.reporter("fonts","collections")
+
+local collections = fonts.collections or { }
+fonts.collections = collections
+
+local definitions = collections.definitions or { }
+collections.definitions = definitions
+
+local vectors = collections.vectors or { }
+collections.vectors = vectors
+
+local fontdata = fonts.hashes.identifiers
+local chardata = fonts.hashes.characters
+local glyph_code = nodes.nodecodes.glyph
+local currentfont = font.current
+
+local fontpatternhassize = fonts.helpers.fontpatternhassize
+
+local implement = interfaces.implement
+
+local list = { }
+local current = 0
+local enabled = false
+
+local function checkenabled()
+ -- a bit ugly but nicer than a fuzzy state while defining math
+ if next(vectors) then
+ if not enabled then
+ nodes.tasks.enableaction("processors","fonts.collections.process")
+ enabled = true
+ end
+ else
+ if enabled then
+ nodes.tasks.disableaction("processors","fonts.collections.process")
+ enabled = false
+ end
+ end
+end
+
+collections.checkenabled = checkenabled
+
+function collections.reset(name,font)
+ if font and font ~= "" then
+ local d = definitions[name]
+ if d then
+ d[font] = nil
+ if not next(d) then
+ definitions[name] = nil
+ end
+ end
+ else
+ definitions[name] = nil
+ end
+end
+
+function collections.define(name,font,ranges,details)
+ -- todo: details -> method=force|conditional rscale=
+ -- todo: remap=name
+ local d = definitions[name]
+ if not d then
+ d = { }
+ definitions[name] = d
+ end
+ if name and trace_collecting then
+ report_fonts("extending collection %a using %a",name,font)
+ end
+ details = settings_to_hash(details)
+ -- todo, combine per font start/stop as arrays
+ for s in gmatch(ranges,"[^, ]+") do
+ local start, stop, description, gaps = characters.getrange(s)
+ if start and stop then
+ if trace_collecting then
+ if description then
+ report_fonts("using range %a, slots %U - %U, description %a)",s,start,stop,description)
+ end
+ for i=1,#d do
+ local di = d[i]
+ if (start >= di.start and start <= di.stop) or (stop >= di.start and stop <= di.stop) then
+ report_fonts("overlapping ranges %U - %U and %U - %U",start,stop,di.start,di.stop)
+ end
+ end
+ end
+ local offset = details.offset
+ if type(offset) == "string" then
+ local start = characters.getrange(offset)
+ 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),
+ }
+ end
+ end
+end
+
+-- todo: provide a lua variant (like with definefont)
+
+function collections.registermain(name)
+ local last = currentfont()
+ if trace_collecting then
+ report_fonts("registering font %a with name %a",last,name)
+ end
+ list[#list+1] = last
+end
+
+-- check: when true, only set when present in font
+-- force: when false, then not set when already set
+
+function collections.clonevector(name)
+ statistics.starttiming(fonts)
+ if trace_collecting then
+ report_fonts("processing collection %a",name)
+ end
+ local definitions = definitions[name]
+ local vector = { }
+ vectors[current] = vector
+ for i=1,#definitions do
+ local definition = definitions[i]
+ local name = definition.font
+ local start = definition.start
+ local stop = definition.stop
+ local check = definition.check
+ local force = definition.force
+ local offset = definition.offset or start
+ local remap = definition.remap
+ local cloneid = list[i]
+ local oldchars = fontdata[current].characters
+ local newchars = fontdata[cloneid].characters
+ if trace_collecting then
+ report_fonts("remapping font %a to %a for range %U - %U",current,cloneid,start,stop)
+ 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
+ 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
+ vector[unic] = { cloneid, remap[unicode] }
+ else
+ vector[unic] = cloneid
+ end
+ end
+ end
+ end
+ end
+ if trace_collecting then
+ report_fonts("activating collection %a for font %a",name,current)
+ end
+ checkenabled()
+ statistics.stoptiming(fonts)
+end
+
+-- we already have this parser
+--
+-- local spec = (P("sa") + P("at") + P("scaled") + P("at") + P("mo")) * P(" ")^1 * (1-P(" "))^1 * P(" ")^0 * -1
+-- local okay = ((1-spec)^1 * spec * Cc(true)) + Cc(false)
+--
+-- if lpegmatch(okay,name) then
+
+function collections.prepare(name) -- we can do this in lua now .. todo
+ current = currentfont()
+ if vectors[current] then
+ return
+ end
+ if fontdata[current].mathparameters then
+ return
+ end
+ local d = definitions[name]
+ if d then
+ if trace_collecting then
+ local filename = file.basename(fontdata[current].properties.filename or "?")
+ report_fonts("applying collection %a to %a, file %a",name,current,filename)
+ end
+ list = { }
+ context.pushcatcodes("prt") -- context.unprotect()
+ context.font_fallbacks_start_cloning()
+ for i=1,#d do
+ local f = d[i]
+ local name = f.font
+ local scale = f.rscale or 1
+ if fontpatternhassize(name) then
+ context.font_fallbacks_clone_unique(name,scale)
+ else
+ context.font_fallbacks_clone_inherited(name,scale)
+ end
+ context.font_fallbacks_register_main(name)
+ end
+ context.font_fallbacks_prepare_clone_vectors(name)
+ context.font_fallbacks_stop_cloning()
+ context.popcatcodes() -- context.protect()
+ elseif trace_collecting then
+ local filename = file.basename(fontdata[current].properties.filename or "?")
+ report_fonts("error while applying collection %a to %a, file %a",name,current,filename)
+ end
+end
+
+function collections.report(message)
+ if trace_collecting then
+ report_fonts("tex: %s",message)
+ end
+end
+
+function collections.process(head) -- this way we keep feature processing
+ local done = false
+ -- for n in traverse_id(glyph_code,tonut(head)) do
+ for n in traverse_char(tonut(head)) do
+ local font = getfont(n)
+ local vector = vectors[font]
+ if vector then
+ local char = getchar(n)
+ local vect = vector[char]
+ if not vect then
+ -- keep it
+ elseif type(vect) == "table" then
+ local newfont = vect[1]
+ local newchar = vect[2]
+ if trace_collecting then
+ report_fonts("remapping character %C in font %a to character %C in font %a%s",
+ char,font,newchar,newfont,not chardata[newfont][newchar] and " (missing)" or ""
+ )
+ end
+ setfield(n,"font",newfont)
+ setchar(n,newchar)
+ done = true
+ else
+ if trace_collecting then
+ report_fonts("remapping font %a to %a for character %C%s",
+ font,vect,char,not chardata[vect][char] and " (missing)" or ""
+ )
+ end
+ setfield(n,"font",vect)
+ done = true
+ end
+ end
+ end
+ return head, done
+end
+
+function collections.found(font,char) -- this way we keep feature processing
+ if not char then
+ font, char = currentfont(), font
+ end
+ if chardata[font][char] then
+ return true -- in normal font
+ else
+ local v = vectors[font]
+ return v and v[char] and true or false
+ end
+end
+
+-- interface
+
+implement {
+ name = "fontcollectiondefine",
+ actions = collections.define,
+ arguments = { "string", "string", "string", "string" }
+}
+
+implement {
+ name = "fontcollectionreset",
+ actions = collections.reset,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "fontcollectionprepare",
+ actions = collections.prepare,
+ arguments = "string"
+}
+
+implement {
+ name = "fontcollectionreport",
+ actions = collections.report,
+ arguments = "string"
+}
+
+implement {
+ name = "fontcollectionregister",
+ actions = collections.registermain,
+ arguments = "string"
+}
+
+implement {
+ name = "fontcollectionclone",
+ actions = collections.clonevector,
+ arguments = "string"
+}
+
+implement {
+ name = "doifelsecharinfont",
+ actions = { collections.found, commands.doifelse },
+ arguments = { "integer" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi
new file mode 100644
index 00000000000..bc8e8151ed1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi
@@ -0,0 +1,138 @@
+%D \module
+%D [ file=font-col,
+%D version=2008.06.11,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Fallbacks (collections),
+%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.
+
+% ! EXPERIMENTAL ! code will be made more nice
+%
+% actually we can now do more at the lua end
+
+% todo : missing only, force always, multiple fallbacks with test, scale
+% beware : only english key/values
+%
+% \resetfontfallback [whatever]
+%
+% \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]
+
+\writestatus{loading}{ConTeXt Font Macros / Collections}
+
+\registerctxluafile{font-col}{1.001}
+
+\unprotect
+
+\unexpanded\def\definefontfallback{\doquadrupleempty\font_fallbacks_define}
+\unexpanded\def\resetfontfallback {\dodoubleempty \font_fallbacks_reset }
+
+\def\font_fallbacks_define[#name][#font][#ranges][#settings]%
+ {\clf_fontcollectiondefine{#name}{#font}{#ranges}{#settings}}
+
+\def\font_fallbacks_reset[#name][#font]%
+ {\clf_fontcollectionreset{#name}{#font}}
+
+\def\font_fallbacks_prepare#name%
+ {\clf_fontcollectionprepare{#name}} % add fallbacks to last font
+
+% we might as well move the handling to lua but then we need to pass the
+% fallbacks, skewchar etc.
+
+\newconditional\c_font_fallbacks_in_progress
+
+\def\font_fallbacks_prepare_indeed#fallbacks%
+ {\begingroup
+ \settrue\c_font_fallbacks_in_progress
+ \lastrawfontcall % sets current font id
+ \font_fallbacks_prepare#fallbacks%
+ \endgroup}
+
+\let\m_font_fallbacks\empty % set in the font-ini
+
+\appendtoks
+ \ifconditional\c_font_fallbacks_in_progress\else
+ \ifx\m_font_fallbacks\empty
+ \ifx\m_font_class_fallbacks\empty
+ \else
+ \font_fallbacks_prepare_indeed\m_font_class_fallbacks
+ \fi
+ \else
+ \font_fallbacks_prepare_indeed\m_font_fallbacks
+ \fi
+ \fi
+\to\everydefinefont
+
+\def\font_fallbacks_start_cloning
+ {\begingroup
+ \let\savedfontspec\somefontspec}
+
+\def\font_fallbacks_stop_cloning
+ {\endgroup}
+
+\def\font_fallbacks_clone_unique#specification#scale% kind of dododefinefont
+ {\clf_fontcollectionreport{defining #specification (relative scale: #scale)}% brrr
+ \setfalse\c_font_auto_size
+ \let\lastfontidentifier\s!dummy
+ \def\v_font_size_relative{#scale}%
+ \let\v_font_size_absolute\fontbody
+ \font_helpers_low_level_define{#specification}\v_font_identifier_basic
+ \csname\v_font_identifier_basic\endcsname
+ \setfalse\c_font_auto_size} % no \setfontcharacteristics and \the\everyfontswitch needed
+
+\def\font_fallbacks_clone_inherited#font% also a second argument
+ {\font_fallbacks_clone_unique{#font \savedfontspec}}
+
+\def\font_fallbacks_register_main #name{\clf_fontcollectionregister{#name}}
+\def\font_fallbacks_prepare_clone_vectors#name{\clf_fontcollectionclone{#name}}
+
+% check : only replace when present in replacement font (default: no)
+% force : force replacent even when basefont has glyph (default: yes)
+
+% \definefontfallback [whatever] [Slanted] [0x0060-0x007F] [force=yes]
+% \definefontfallback [whatever] [Bold] [0x0080:0x00FF,0x00A0:0x00AF] [rscale=2.0]
+% \definefontfallback [whatever] [BoldSlanted] ["00C0-"00C7] [check=yes,force=yes]
+% \definefontfallback [whatever] [Mono] [latinextendeda] [force=yes] % 0x0100:0x017F
+% \definefontfallback [whatever] [Mono] [latin extended a] [force=yes] % 0x0100:0x017F
+%
+% \definefontsynonym[SerifPlus][Serif][fallbacks=whatever]
+%
+% \showfont[SerifPlus][all]
+
+% \definefontfeature[zh][mode=node,script=hang,lang=zhs]
+% \definefontfallback[serifwhatever] [lmroman10-regular] [0x0000-0x0400][force=yes]
+% \definefontfallback[serifboldwhatever] [lmroman10-bold] [0x0000-0x0400][force=yes]
+% \definefontfallback[serifitalicwhatever] [lmroman10-italic] [0x0000-0x0400][force=yes]
+% \definefontfallback[serifbolditalicwhatever][lmroman10-bolditalic][0x0000-0x0400][force=yes]
+%
+% \starttypescript [serif] [zhfont]
+% \definefontsynonym [zhserif] [AdobeSongStd-Light] [features=zh,fallbacks=serifwhatever]
+% \definefontsynonym [zhserifbold] [AdobeHeitiStd-Regular][features=zh,fallbacks=serifboldwhatever]
+% \definefontsynonym [zhserifitalic] [AdobeKaitiStd-Regular][features=zh,fallbacks=serifitalicwhatever]
+% \definefontsynonym [zhserifbolditalic][AdobeHeitiStd-Regular][features=zh,fallbacks=serifbolditalicwhatever]
+% \stoptypescript
+%
+% \starttypescript [serif][zhfont][name]
+% \definefontsynonym[Serif] [zhserif] % [fallbacks=serifwhatever]
+% \definefontsynonym[SerifBold] [zhserifbold] % [fallbacks=serifboldwhatever]
+% \definefontsynonym[SerifItalic] [zhserifitalic] % [fallbacks=serifitalicwhatever]
+% \definefontsynonym[SerifBoldItalic] [zhserifbolditalic] % [fallbacks=serifbolditalicwhatever]
+% \stoptypescript
+%
+% \starttypescript[myfont]
+% \definetypeface[myfont][rm][serif][zhfont]
+% \stoptypescript
+%
+% \usetypescript[myfont] \setupbodyfont[myfont,rm,12pt]
+%
+% \starttext
+% fonts {\bf fonts} {\bi fonts} {\it fonts}
+% \stoptext
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-con.lua b/Master/texmf-dist/tex/context/base/mkiv/font-con.lua
new file mode 100644
index 00000000000..b11853533b4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-con.lua
@@ -0,0 +1,1454 @@
+if not modules then modules = { } end modules ['font-con'] = {
+ 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"
+}
+
+-- some names of table entries will be changed (no _)
+
+local next, tostring, rawget = next, tostring, rawget
+local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
+local utfbyte = utf.byte
+local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
+local derivetable = table.derive
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
+
+local report_defining = logs.reporter("fonts","defining")
+
+-- watch out: no negative depths and negative eights permitted in regular fonts
+
+--[[ldx--
+<p>Here we only implement a few helper functions.</p>
+--ldx]]--
+
+local fonts = fonts
+local constructors = fonts.constructors or { }
+fonts.constructors = constructors
+local handlers = fonts.handlers or { } -- can have preloaded tables
+fonts.handlers = handlers
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+-- will be directives
+
+constructors.dontembed = allocate()
+constructors.autocleanup = true
+constructors.namemode = "fullpath" -- will be a function
+
+constructors.version = 1.01
+constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+
+constructors.privateoffset = 0xF0000 -- 0x10FFFF
+
+constructors.cacheintex = true -- so we see the original table in fonts.font
+
+-- Some experimental helpers (handy for tracing):
+--
+-- todo: extra:
+--
+-- extra_space => space.extra
+-- space => space.width
+-- space_stretch => space.stretch
+-- space_shrink => space.shrink
+
+-- We do keep the x-height, extra_space, space_shrink and space_stretch
+-- around as these are low level official names.
+
+constructors.keys = {
+ properties = {
+ encodingbytes = "number",
+ embedding = "number",
+ cidinfo = { },
+ format = "string",
+ fontname = "string",
+ fullname = "string",
+ filename = "filename",
+ psname = "string",
+ name = "string",
+ virtualized = "boolean",
+ hasitalics = "boolean",
+ autoitalicamount = "basepoints",
+ nostackmath = "boolean",
+ noglyphnames = "boolean",
+ mode = "string",
+ hasmath = "boolean",
+ mathitalics = "boolean",
+ textitalics = "boolean",
+ finalized = "boolean",
+ },
+ parameters = {
+ mathsize = "number",
+ scriptpercentage = "float",
+ scriptscriptpercentage = "float",
+ units = "cardinal",
+ designsize = "scaledpoints",
+ expansion = {
+ stretch = "integerscale", -- might become float
+ shrink = "integerscale", -- might become float
+ step = "integerscale", -- might become float
+ auto = "boolean",
+ },
+ protrusion = {
+ auto = "boolean",
+ },
+ slantfactor = "float",
+ extendfactor = "float",
+ factor = "float",
+ hfactor = "float",
+ vfactor = "float",
+ size = "scaledpoints",
+ units = "scaledpoints",
+ scaledpoints = "scaledpoints",
+ slantperpoint = "scaledpoints",
+ spacing = {
+ width = "scaledpoints",
+ stretch = "scaledpoints",
+ shrink = "scaledpoints",
+ extra = "scaledpoints",
+ },
+ xheight = "scaledpoints",
+ quad = "scaledpoints",
+ ascender = "scaledpoints",
+ descender = "scaledpoints",
+ synonyms = {
+ space = "spacing.width",
+ spacestretch = "spacing.stretch",
+ spaceshrink = "spacing.shrink",
+ extraspace = "spacing.extra",
+ x_height = "xheight",
+ space_stretch = "spacing.stretch",
+ space_shrink = "spacing.shrink",
+ extra_space = "spacing.extra",
+ em = "quad",
+ ex = "xheight",
+ slant = "slantperpoint",
+ },
+ },
+ description = {
+ width = "basepoints",
+ height = "basepoints",
+ depth = "basepoints",
+ boundingbox = { },
+ },
+ character = {
+ width = "scaledpoints",
+ height = "scaledpoints",
+ depth = "scaledpoints",
+ italic = "scaledpoints",
+ },
+}
+
+-- This might become an interface:
+
+local designsizes = allocate()
+constructors.designsizes = designsizes
+local loadedfonts = allocate()
+constructors.loadedfonts = loadedfonts
+
+--[[ldx--
+<p>We need to normalize the scale factor (in scaled points). This has to
+do with the fact that <l n='tex'/> uses a negative multiple of 1000 as
+a signal for a font scaled based on the design size.</p>
+--ldx]]--
+
+local factors = {
+ pt = 65536.0,
+ bp = 65781.8,
+}
+
+function constructors.setfactor(f)
+ constructors.factor = factors[f or 'pt'] or factors.pt
+end
+
+constructors.setfactor()
+
+function constructors.scaled(scaledpoints, designsize) -- handles designsize in sp as well
+ if scaledpoints < 0 then
+ local factor = constructors.factor
+ if designsize then
+ if designsize > factor then -- or just 1000 / when? mp?
+ return (- scaledpoints/1000) * designsize -- sp's
+ else
+ return (- scaledpoints/1000) * designsize * factor
+ end
+ else
+ return (- scaledpoints/1000) * 10 * factor
+ end
+ else
+ return scaledpoints
+ 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
+excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p>
+--ldx]]--
+
+-- The scaler is only used for otf and afm and virtual fonts. If a virtual font has italic
+-- correction make sure to set the hasitalics flag. Some more flags will be added in the
+-- future.
+
+--[[ldx--
+<p>The reason why the scaler was originally split, is that for a while we experimented
+with a helper function. However, in practice the <l n='api'/> calls are too slow to
+make this profitable and the <l n='lua'/> based variant was just faster. A days
+wasted day but an experience richer.</p>
+--ldx]]--
+
+-- we can get rid of the tfm instance when we have fast access to the
+-- scaled character dimensions at the tex end, e.g. a fontobject.width
+-- actually we already have some of that now as virtual keys in glyphs
+--
+-- flushing the kern and ligature tables from memory saves a lot (only
+-- base mode) but it complicates vf building where the new characters
+-- demand this data .. solution: functions that access them
+
+function constructors.cleanuptable(tfmdata)
+ if constructors.autocleanup and tfmdata.properties.virtualized then
+ for k, v in next, tfmdata.characters do
+ if v.commands then v.commands = nil end
+ -- if v.kerns then v.kerns = nil end
+ end
+ end
+end
+
+-- experimental, sharing kerns (unscaled and scaled) saves memory
+-- local sharedkerns, basekerns = constructors.check_base_kerns(tfmdata)
+-- loop over descriptions (afm and otf have descriptions, tfm not)
+-- there is no need (yet) to assign a value to chr.tonunicode
+
+-- constructors.prepare_base_kerns(tfmdata) -- optimalization
+
+-- we have target.name=metricfile and target.fullname=RealName and target.filename=diskfilename
+-- when collapsing fonts, luatex looks as both target.name and target.fullname as ttc files
+-- can have multiple subfonts
+
+function constructors.calculatescale(tfmdata,scaledpoints)
+ local parameters = tfmdata.parameters
+ if scaledpoints < 0 then
+ scaledpoints = (- scaledpoints/1000) * (tfmdata.designsize or parameters.designsize) -- already in sp
+ end
+ return scaledpoints, scaledpoints / (parameters.units or 1000) -- delta
+end
+
+local unscaled = {
+ ScriptPercentScaleDown = true,
+ ScriptScriptPercentScaleDown = true,
+ RadicalDegreeBottomRaisePercent = true
+}
+
+function constructors.assignmathparameters(target,original) -- simple variant, not used in context
+ -- when a tfm file is loaded, it has already been scaled
+ -- and it never enters the scaled so this is otf only and
+ -- even then we do some extra in the context math plugins
+ local mathparameters = original.mathparameters
+ if mathparameters and next(mathparameters) then
+ local targetparameters = target.parameters
+ local targetproperties = target.properties
+ local targetmathparameters = { }
+ local factor = targetproperties.math_is_scaled and 1 or targetparameters.factor
+ for name, value in next, mathparameters do
+ if unscaled[name] then
+ targetmathparameters[name] = value
+ else
+ targetmathparameters[name] = value * factor
+ end
+ end
+ if not targetmathparameters.FractionDelimiterSize then
+ targetmathparameters.FractionDelimiterSize = 1.01 * targetparameters.size
+ end
+ if not mathparameters.FractionDelimiterDisplayStyleSize then
+ targetmathparameters.FractionDelimiterDisplayStyleSize = 2.40 * targetparameters.size
+ end
+ target.mathparameters = targetmathparameters
+ end
+end
+
+function constructors.beforecopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.aftercopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+-- It's probably ok to hash just the indices because there is not that much
+-- chance that one will shift slots and leave the others unset then. Anyway,
+-- there is of course some overhead here, but it might as well get compensated
+-- by less time spent on including the font resource twice. For the moment
+-- we default to false, so a macro package has to enable it explicitly. In
+-- LuaTeX the fullname is used to identify a font as being unique.
+
+constructors.sharefonts = false
+constructors.nofsharedfonts = 0
+local sharednames = { }
+
+function constructors.trytosharefont(target,tfmdata)
+ if constructors.sharefonts then -- not robust !
+ local characters = target.characters
+ local n = 1
+ local t = { target.psname }
+ local u = sortedkeys(characters)
+ for i=1,#u do
+ local k = u[i]
+ n = n + 1 ; t[n] = k
+ n = n + 1 ; t[n] = characters[k].index or k
+ end
+ local h = md5.HEX(concat(t," "))
+ local s = sharednames[h]
+ if s then
+ if trace_defining then
+ report_defining("font %a uses backend resources of font %a",target.fullname,s)
+ end
+ target.fullname = s
+ constructors.nofsharedfonts = constructors.nofsharedfonts + 1
+ target.properties.sharedwith = s
+ else
+ sharednames[h] = target.fullname
+ end
+ end
+end
+
+function constructors.enhanceparameters(parameters)
+ local xheight = parameters.x_height
+ local quad = parameters.quad
+ local space = parameters.space
+ local stretch = parameters.space_stretch
+ local shrink = parameters.space_shrink
+ local extra = parameters.extra_space
+ local slant = parameters.slant
+ parameters.xheight = xheight
+ parameters.spacestretch = stretch
+ parameters.spaceshrink = shrink
+ parameters.extraspace = extra
+ parameters.em = quad
+ parameters.ex = xheight
+ parameters.slantperpoint = slant
+ parameters.spacing = {
+ width = space,
+ stretch = stretch,
+ shrink = shrink,
+ extra = extra,
+ }
+end
+
+function constructors.scale(tfmdata,specification)
+ local target = { } -- the new table
+ --
+ if tonumber(specification) then
+ specification = { size = specification }
+ end
+ target.specification = specification
+ --
+ local scaledpoints = specification.size
+ local relativeid = specification.relativeid
+ --
+ local properties = tfmdata.properties or { }
+ local goodies = tfmdata.goodies or { }
+ local resources = tfmdata.resources or { }
+ local descriptions = tfmdata.descriptions or { } -- bad news if empty
+ local characters = tfmdata.characters or { } -- bad news if empty
+ local changed = tfmdata.changed or { } -- for base mode
+ local shared = tfmdata.shared or { }
+ local parameters = tfmdata.parameters or { }
+ local mathparameters = tfmdata.mathparameters or { }
+ --
+ local targetcharacters = { }
+ local targetdescriptions = derivetable(descriptions)
+ local targetparameters = derivetable(parameters)
+ local targetproperties = derivetable(properties)
+ local targetgoodies = goodies -- we need to loop so no metatable
+ target.characters = targetcharacters
+ target.descriptions = targetdescriptions
+ target.parameters = targetparameters
+ -- target.mathparameters = targetmathparameters -- happens elsewhere
+ target.properties = targetproperties
+ target.goodies = targetgoodies
+ target.shared = shared
+ target.resources = resources
+ target.unscaled = tfmdata -- the original unscaled one
+ --
+ -- specification.mathsize : 1=text 2=script 3=scriptscript
+ -- specification.textsize : natural (text)size
+ -- parameters.mathsize : 1=text 2=script 3=scriptscript >1000 enforced size (feature value other than yes)
+ --
+ local mathsize = tonumber(specification.mathsize) or 0
+ local textsize = tonumber(specification.textsize) or scaledpoints
+ local forcedsize = tonumber(parameters.mathsize ) or 0
+ local extrafactor = tonumber(specification.factor ) or 1
+ if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then
+ scaledpoints = parameters.scriptpercentage * textsize / 100
+ elseif (mathsize == 3 or forcedsize == 3) and parameters.scriptscriptpercentage then
+ scaledpoints = parameters.scriptscriptpercentage * textsize / 100
+ elseif forcedsize > 1000 then -- safeguard
+ scaledpoints = forcedsize
+ end
+ targetparameters.mathsize = mathsize -- context specific
+ targetparameters.textsize = textsize -- context specific
+ targetparameters.forcedsize = forcedsize -- context specific
+ targetparameters.extrafactor = extrafactor -- context specific
+ --
+ local tounicode = fonts.mappings.tounicode
+ --
+ local defaultwidth = resources.defaultwidth or 0
+ local defaultheight = resources.defaultheight or 0
+ local defaultdepth = resources.defaultdepth or 0
+ local units = parameters.units or 1000
+ --
+ if target.fonts then
+ target.fonts = fastcopy(target.fonts) -- maybe we virtualize more afterwards
+ end
+ --
+ -- boundary keys are no longer needed as we now have a string 'right_boundary'
+ -- that can be used in relevant tables (kerns and ligatures) ... not that I ever
+ -- used them
+ --
+ -- boundarychar_label = 0, -- not needed
+ -- boundarychar = 65536, -- there is now a string 'right_boundary'
+ -- false_boundarychar = 65536, -- produces invalid tfm in luatex
+ --
+ targetproperties.language = properties.language or "dflt" -- inherited
+ targetproperties.script = properties.script or "dflt" -- inherited
+ targetproperties.mode = properties.mode or "base" -- inherited
+ --
+ local askedscaledpoints = scaledpoints
+ local scaledpoints, delta = constructors.calculatescale(tfmdata,scaledpoints,nil,specification) -- no shortcut, dan be redefined
+ --
+ local hdelta = delta
+ local vdelta = delta
+ --
+ target.designsize = parameters.designsize -- not really needed so it might become obsolete
+ target.units = units
+ target.units_per_em = units -- just a trigger for the backend
+ --
+ local direction = properties.direction or tfmdata.direction or 0 -- pointless, as we don't use omf fonts at all
+ target.direction = direction
+ properties.direction = direction
+ --
+ target.size = scaledpoints
+ --
+ target.encodingbytes = properties.encodingbytes or 1
+ target.embedding = properties.embedding or "subset"
+ target.tounicode = 1
+ target.cidinfo = properties.cidinfo
+ target.format = properties.format
+ target.cache = constructors.cacheintex and "yes" or "renew"
+ --
+ local fontname = properties.fontname or tfmdata.fontname -- for the moment we fall back on
+ local fullname = properties.fullname or tfmdata.fullname -- names in the tfmdata although
+ local filename = properties.filename or tfmdata.filename -- that is not the right place to
+ local psname = properties.psname or tfmdata.psname -- pass them
+ local name = properties.name or tfmdata.name
+ --
+ if not psname or psname == "" then
+ -- name used in pdf file as well as for selecting subfont in ttc/dfont
+ psname = fontname or (fullname and fonts.names.cleanname(fullname))
+ end
+ target.fontname = fontname
+ target.fullname = fullname
+ target.filename = filename
+ target.psname = psname
+ target.name = name
+ --
+ --
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.filename = filename
+ properties.psname = psname
+ properties.name = name
+ -- expansion (hz)
+ local expansion = parameters.expansion
+ if expansion then
+ target.stretch = expansion.stretch
+ target.shrink = expansion.shrink
+ target.step = expansion.step
+ target.auto_expand = expansion.auto
+ end
+ -- protrusion
+ local protrusion = parameters.protrusion
+ if protrusion then
+ target.auto_protrude = protrusion.auto
+ end
+ -- widening
+ local extendfactor = parameters.extendfactor or 0
+ if extendfactor ~= 0 and extendfactor ~= 1 then
+ hdelta = hdelta * extendfactor
+ target.extend = extendfactor * 1000 -- extent ?
+ else
+ target.extend = 1000 -- extent ?
+ end
+ -- slanting
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
+ else
+ target.slant = 0
+ end
+ --
+ targetparameters.factor = delta
+ targetparameters.hfactor = hdelta
+ targetparameters.vfactor = vdelta
+ targetparameters.size = scaledpoints
+ targetparameters.units = units
+ targetparameters.scaledpoints = askedscaledpoints
+ --
+ local isvirtual = properties.virtualized or tfmdata.type == "virtual"
+ local hasquality = target.auto_expand or target.auto_protrude
+ local hasitalics = properties.hasitalics
+ local autoitalicamount = properties.autoitalicamount
+ local stackmath = not properties.nostackmath
+ local nonames = properties.noglyphnames
+ local haskerns = properties.haskerns or properties.mode == "base" -- we can have afm in node mode
+ local hasligatures = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode
+ local realdimensions = properties.realdimensions
+ --
+ if changed and not next(changed) then
+ changed = false
+ end
+ --
+ target.type = isvirtual and "virtual" or "real"
+ --
+ target.postprocessors = tfmdata.postprocessors
+ --
+ local targetslant = (parameters.slant or parameters[1] or 0) * factors.pt -- per point
+ local targetspace = (parameters.space or parameters[2] or 0) * hdelta
+ local targetspace_stretch = (parameters.space_stretch or parameters[3] or 0) * hdelta
+ local targetspace_shrink = (parameters.space_shrink or parameters[4] or 0) * hdelta
+ local targetx_height = (parameters.x_height or parameters[5] or 0) * vdelta
+ local targetquad = (parameters.quad or parameters[6] or 0) * hdelta
+ local targetextra_space = (parameters.extra_space or parameters[7] or 0) * hdelta
+ --
+ targetparameters.slant = targetslant -- slantperpoint
+ targetparameters.space = targetspace
+ targetparameters.space_stretch = targetspace_stretch
+ targetparameters.space_shrink = targetspace_shrink
+ targetparameters.x_height = targetx_height
+ targetparameters.quad = targetquad
+ targetparameters.extra_space = targetextra_space
+ --
+ local ascender = parameters.ascender
+ if ascender then
+ targetparameters.ascender = delta * ascender
+ end
+ local descender = parameters.descender
+ if descender then
+ targetparameters.descender = delta * descender
+ end
+ --
+ constructors.enhanceparameters(targetparameters) -- official copies for us
+ --
+ local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0
+ local scaledwidth = defaultwidth * hdelta
+ local scaledheight = defaultheight * vdelta
+ local scaleddepth = defaultdepth * vdelta
+ --
+ local hasmath = (properties.hasmath or next(mathparameters)) and true
+ --
+ if hasmath then
+ constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed
+ properties.hasmath = true
+ target.nomath = false
+ target.MathConstants = target.mathparameters
+ else
+ properties.hasmath = false
+ target.nomath = true
+ target.mathparameters = nil -- nop
+ end
+ --
+ -- Here we support some context specific trickery (this might move to a plugin). During the
+ -- transition to opentype the engine had troubles with italics so we had some additional code
+ -- for fixing that. In node mode (text) we don't care much if italics gets passed because
+ -- the engine does nothign with them then.
+ --
+ if hasmath then
+ local mathitalics = properties.mathitalics
+ if mathitalics == false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics = false
+ autoitalicamount = false
+ end
+ else
+ local textitalics = properties.textitalics
+ if textitalics == false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics = false
+ autoitalicamount = false
+ end
+ end
+ --
+ -- end of context specific trickery
+ --
+ if trace_defining then
+ report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+ end
+ --
+ constructors.beforecopyingcharacters(target,tfmdata)
+ --
+ local sharedkerns = { }
+ --
+ -- we can have a dumb mode (basemode without math etc) that skips most
+ --
+ for unicode, character in next, characters do
+ local chr, description, index
+ if changed then
+ local c = changed[unicode]
+ if c then
+ description = descriptions[c] or descriptions[unicode] or character
+ character = characters[c] or character
+ index = description.index or c
+ else
+ description = descriptions[unicode] or character
+ index = description.index or unicode
+ end
+ else
+ description = descriptions[unicode] or character
+ index = description.index or unicode
+ end
+ local width = description.width
+ local height = description.height
+ local depth = description.depth
+ if realdimensions then
+ -- this is mostly for checking issues
+ if not height or height == 0 then
+ local bb = description.boundingbox
+ local ht = bb[4]
+ if ht ~= 0 then
+ height = ht
+ end
+ if not depth or depth == 0 then
+ local dp = -bb[2]
+ if dp ~= 0 then
+ depth = dp
+ end
+ end
+ elseif not depth or depth == 0 then
+ local dp = -description.boundingbox[2]
+ if dp ~= 0 then
+ depth = dp
+ end
+ end
+ end
+ if width then width = hdelta*width else width = scaledwidth end
+ if height then height = vdelta*height else height = scaledheight end
+ -- if depth then depth = vdelta*depth else depth = scaleddepth end
+ if depth and depth ~= 0 then
+ depth = delta*depth
+ if nonames then
+ chr = {
+ index = index,
+ height = height,
+ depth = depth,
+ width = width,
+ }
+ else
+ chr = {
+ name = description.name,
+ index = index,
+ height = height,
+ depth = depth,
+ width = width,
+ }
+ end
+ else
+ -- this saves a little bit of memory time and memory, esp for big cjk fonts
+ if nonames then
+ chr = {
+ index = index,
+ height = height,
+ width = width,
+ }
+ else
+ chr = {
+ name = description.name,
+ index = index,
+ height = height,
+ width = width,
+ }
+ 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
+ end
+ if hasquality then
+ -- we could move these calculations elsewhere (saves calculations)
+ local ve = character.expansion_factor
+ if ve then
+ chr.expansion_factor = ve*1000 -- expansionfactor, hm, can happen elsewhere
+ end
+ local vl = character.left_protruding
+ if vl then
+ chr.left_protruding = protrusionfactor*width*vl
+ end
+ local vr = character.right_protruding
+ if vr then
+ chr.right_protruding = protrusionfactor*width*vr
+ end
+ end
+ --
+ if hasmath then
+ --
+ -- todo, just operate on descriptions.math
+ local vn = character.next
+ if vn then
+ chr.next = vn
+ else
+ local vv = character.vert_variants
+ if vv then
+ 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"],
+ }
+ end
+ chr.vert_variants = t
+ else
+ local hv = character.horiz_variants
+ if hv then
+ 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"],
+ }
+ end
+ chr.horiz_variants = t
+ end
+ end
+ -- todo also check mathitalics (or that one can go away)
+ end
+ local vi = character.vert_italic
+ if vi and vi ~= 0 then
+ chr.vert_italic = vi*hdelta
+ end
+ local va = character.accent
+ if va then
+ chr.top_accent = vdelta*va
+ end
+ if stackmath then
+ local mk = character.mathkerns -- not in math ?
+ if mk then
+ local kerns = { }
+ local v = mk.top_right if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.top_right = k end
+ local v = mk.top_left if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.top_left = k end
+ local v = mk.bottom_left if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.bottom_left = k end
+ local v = mk.bottom_right if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.bottom_right = k end
+ chr.mathkern = kerns -- singular -> should be patched in luatex !
+ end
+ end
+ if hasitalics then
+ local vi = character.italic
+ if vi and vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ end
+ elseif autoitalicamount then -- itlc feature
+ local vi = description.italic
+ if not vi then
+ local bb = description.boundingbox
+ if bb then
+ local vi = bb[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr.italic = vi*hdelta
+ end
+ else
+ -- report_defining("no boundingbox for character %C in font %a, fullname %a, filename %a",unicode,name,fullname,filename)
+ end
+ elseif vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ elseif hasitalics then -- unlikely
+ local vi = character.italic
+ if vi and vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ end
+ if haskerns then
+ local vk = character.kerns
+ if vk then
+ local s = sharedkerns[vk]
+ if not s then
+ s = { }
+ for k,v in next, vk do s[k] = v*hdelta end
+ sharedkerns[vk] = s
+ end
+ chr.kerns = s
+ end
+ end
+ if hasligatures then
+ local vl = character.ligatures
+ if vl then
+ if true then
+ chr.ligatures = vl -- shared
+ else
+ local tt = { }
+ for i, l in next, vl do
+ tt[i] = l
+ end
+ chr.ligatures = tt
+ end
+ end
+ end
+ if isvirtual then
+ local vc = character.commands
+ if vc then
+ -- we assume non scaled commands here
+ -- tricky .. we need to scale pseudo math glyphs too
+ -- which is why we deal with rules too
+ local ok = false
+ for i=1,#vc do
+ local key = vc[i][1]
+ if key == "right" or key == "down" then
+ ok = true
+ break
+ end
+ end
+ if ok then
+ local tt = { }
+ for i=1,#vc do
+ local ivc = vc[i]
+ local key = ivc[1]
+ if key == "right" then
+ tt[i] = { key, ivc[2]*hdelta }
+ elseif key == "down" then
+ tt[i] = { key, ivc[2]*vdelta }
+ elseif key == "rule" then
+ tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
+ else -- not comment
+ tt[i] = ivc -- shared since in cache and untouched
+ end
+ end
+ chr.commands = tt
+ else
+ chr.commands = vc
+ end
+ chr.index = nil
+ end
+ end
+ targetcharacters[unicode] = chr
+ end
+ --
+ properties.setitalics = hasitalics -- for postprocessing
+ --
+ constructors.aftercopyingcharacters(target,tfmdata)
+ --
+ constructors.trytosharefont(target,tfmdata)
+ --
+ return target
+end
+
+function constructors.finalize(tfmdata)
+ if tfmdata.properties and tfmdata.properties.finalized then
+ return
+ end
+ --
+ if not tfmdata.characters then
+ return nil
+ end
+ --
+ if not tfmdata.goodies then
+ tfmdata.goodies = { } -- context specific
+ end
+ --
+ local parameters = tfmdata.parameters
+ if not parameters then
+ return nil
+ end
+ --
+ if not parameters.expansion then
+ parameters.expansion = {
+ stretch = tfmdata.stretch or 0,
+ shrink = tfmdata.shrink or 0,
+ step = tfmdata.step or 0,
+ auto = tfmdata.auto_expand or false,
+ }
+ end
+ --
+ if not parameters.protrusion then
+ parameters.protrusion = {
+ auto = auto_protrude
+ }
+ end
+ --
+ if not parameters.size then
+ parameters.size = tfmdata.size
+ end
+ --
+ if not parameters.extendfactor then
+ parameters.extendfactor = tfmdata.extend or 0
+ end
+ --
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
+ end
+ --
+ local designsize = parameters.designsize
+ if designsize then
+ parameters.minsize = tfmdata.minsize or designsize
+ parameters.maxsize = tfmdata.maxsize or designsize
+ else
+ designsize = factors.pt * 10
+ parameters.designsize = designsize
+ parameters.minsize = designsize
+ parameters.maxsize = designsize
+ end
+ parameters.minsize = tfmdata.minsize or parameters.designsize
+ parameters.maxsize = tfmdata.maxsize or parameters.designsize
+ --
+ if not parameters.units then
+ parameters.units = tfmdata.units or tfmdata.units_per_em or 1000
+ end
+ --
+ if not tfmdata.descriptions then
+ local descriptions = { } -- yes or no
+ setmetatableindex(descriptions, function(t,k) local v = { } t[k] = v return v end)
+ tfmdata.descriptions = descriptions
+ end
+ --
+ local properties = tfmdata.properties
+ if not properties then
+ properties = { }
+ tfmdata.properties = properties
+ end
+ --
+ if not properties.virtualized then
+ 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,
+ }
+ end
+ if not tfmdata.resources then
+ tfmdata.resources = { }
+ end
+ if not tfmdata.shared then
+ tfmdata.shared = { }
+ end
+ --
+ -- tfmdata.fonts
+ -- tfmdata.unscaled
+ --
+ if not properties.hasmath then
+ properties.hasmath = not tfmdata.nomath
+ end
+ --
+ tfmdata.MathConstants = nil
+ tfmdata.postprocessors = nil
+ --
+ tfmdata.fontname = nil
+ tfmdata.filename = nil
+ tfmdata.fullname = nil
+ tfmdata.name = nil -- most tricky part
+ tfmdata.psname = nil
+ --
+ tfmdata.encodingbytes = nil
+ tfmdata.embedding = nil
+ tfmdata.tounicode = nil
+ tfmdata.cidinfo = nil
+ tfmdata.format = nil
+ tfmdata.direction = nil
+ tfmdata.type = nil
+ tfmdata.nomath = nil
+ tfmdata.designsize = nil
+ --
+ tfmdata.size = nil
+ tfmdata.stretch = nil
+ tfmdata.shrink = nil
+ tfmdata.step = nil
+ tfmdata.auto_expand = nil
+ tfmdata.auto_protrude = nil
+ tfmdata.extend = nil
+ tfmdata.slant = nil
+ tfmdata.units = nil
+ tfmdata.units_per_em = nil
+ --
+ tfmdata.cache = nil
+ --
+ properties.finalized = true
+ --
+ return tfmdata
+end
+
+--[[ldx--
+<p>A unique hash value is generated by:</p>
+--ldx]]--
+
+local hashmethods = { }
+constructors.hashmethods = hashmethods
+
+function constructors.hashfeatures(specification) -- will be overloaded
+ local features = specification.features
+ if features then
+ local t, tn = { }, 0
+ for category, list in next, features do
+ if next(list) then
+ local hasher = hashmethods[category]
+ if hasher then
+ local hash = hasher(list)
+ if hash then
+ tn = tn + 1
+ t[tn] = category .. ":" .. hash
+ end
+ end
+ end
+ end
+ if tn > 0 then
+ return concat(t," & ")
+ end
+ end
+ return "unknown"
+end
+
+hashmethods.normal = function(list)
+ local s = { }
+ local n = 0
+ for k, v in next, list do
+ if not k then
+ -- no need to add to hash
+ elseif k == "number" or k == "features" then
+ -- no need to add to hash (maybe we need a skip list)
+ else
+ n = n + 1
+ s[n] = k
+ end
+ end
+ if n > 0 then
+ sort(s)
+ for i=1,n do
+ local k = s[i]
+ s[i] = k .. '=' .. tostring(list[k])
+ end
+ return concat(s,"+")
+ end
+end
+
+--[[ldx--
+<p>In principle we can share tfm tables when we are in node for a font, but then
+we need to define a font switch as an id/attr switch which is no fun, so in that
+case users can best use dynamic features ... so, we will not use that speedup. Okay,
+when we get rid of base mode we can optimize even further by sharing, but then we
+loose our testcases for <l n='luatex'/>.</p>
+--ldx]]--
+
+function constructors.hashinstance(specification,force)
+ local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
+ if force or not hash then
+ hash = constructors.hashfeatures(specification)
+ specification.hash = hash
+ end
+ if size < 1000 and designsizes[hash] then
+ size = math.round(constructors.scaled(size,designsizes[hash]))
+ specification.size = size
+ end
+ if fallbacks then
+ return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks
+ else
+ return hash .. ' @ ' .. tostring(size)
+ end
+end
+
+function constructors.setname(tfmdata,specification) -- todo: get specification from tfmdata
+ if constructors.namemode == "specification" then
+ -- not to be used in context !
+ local specname = specification.specification
+ if specname then
+ tfmdata.properties.name = specname
+ if trace_defining then
+ report_otf("overloaded fontname %a",specname)
+ end
+ end
+ end
+end
+
+function constructors.checkedfilename(data)
+ local foundfilename = data.foundfilename
+ if not foundfilename then
+ local askedfilename = data.filename or ""
+ if askedfilename ~= "" then
+ askedfilename = resolvers.resolve(askedfilename) -- no shortcut
+ foundfilename = resolvers.findbinfile(askedfilename,"") or ""
+ if foundfilename == "" then
+ report_defining("source file %a is not found",askedfilename)
+ foundfilename = resolvers.findbinfile(file.basename(askedfilename),"") or ""
+ if foundfilename ~= "" then
+ report_defining("using source file %a due to cache mismatch",foundfilename)
+ end
+ end
+ end
+ data.foundfilename = foundfilename
+ end
+ return foundfilename
+end
+
+local formats = allocate()
+fonts.formats = formats
+
+setmetatableindex(formats, function(t,k)
+ local l = lower(k)
+ if rawget(t,k) then
+ t[k] = l
+ return l
+ end
+ return rawget(t,file.suffix(l))
+end)
+
+local locations = { }
+
+local function setindeed(mode,target,group,name,action,position)
+ local t = target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ -- todo: remove existing
+ insert(t, position, { name = name, action = action })
+ else
+ for i=1,#t do
+ local ti = t[i]
+ if ti.name == name then
+ ti.action = action
+ return
+ end
+ end
+ insert(t, { name = name, action = action })
+ end
+end
+
+local function set(group,name,target,source)
+ target = target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local source = source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local node = source.node
+ local base = source.base
+ local position = source.position
+ if node then
+ setindeed("node",target,group,name,node,position)
+ end
+ if base then
+ setindeed("base",target,group,name,base,position)
+ end
+end
+
+local function register(where,specification)
+ local name = specification.name
+ if name and name ~= "" then
+ local default = specification.default
+ local description = specification.description
+ local initializers = specification.initializers
+ local processors = specification.processors
+ local manipulators = specification.manipulators
+ local modechecker = specification.modechecker
+ if default then
+ where.defaults[name] = default
+ end
+ if description and description ~= "" then
+ where.descriptions[name] = description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors', name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker = modechecker
+ end
+ end
+end
+
+constructors.registerfeature = register
+
+function constructors.getfeatureaction(what,where,mode,name)
+ what = handlers[what].features
+ if what then
+ where = what[where]
+ if where then
+ mode = where[mode]
+ if mode then
+ for i=1,#mode do
+ local m = mode[i]
+ if m.name == name then
+ return m.action
+ end
+ end
+ end
+ end
+ end
+end
+
+function constructors.newhandler(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ if not handler then
+ handler = { }
+ handlers[what] = handler
+ end
+ return handler
+end
+
+function constructors.newfeatures(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ local features = handler.features
+ if not features then
+ local tables = handler.tables -- can be preloaded
+ local statistics = handler.statistics -- can be preloaded
+ features = allocate {
+ defaults = { },
+ descriptions = tables and tables.features or { },
+ used = statistics and statistics.usedfeatures or { },
+ initializers = { base = { }, node = { } },
+ processors = { base = { }, node = { } },
+ manipulators = { base = { }, node = { } },
+ }
+ features.register = function(specification) return register(features,specification) end
+ handler.features = features -- will also become hidden
+ end
+ return features
+end
+
+--[[ldx--
+<p>We need to check for default features. For this we provide
+a helper function.</p>
+--ldx]]--
+
+function constructors.checkedfeatures(what,features)
+ local defaults = handlers[what].features.defaults
+ if features and next(features) then
+ features = fastcopy(features) -- can be inherited (mt) but then no loops possible
+ for key, value in next, defaults do
+ if features[key] == nil then
+ features[key] = value
+ end
+ end
+ return features
+ else
+ return fastcopy(defaults) -- we can change features in place
+ end
+end
+
+-- before scaling
+
+function constructors.initializefeatures(what,tfmdata,features,trace,report)
+ if features and next(features) then
+ local properties = tfmdata.properties or { } -- brrr
+ local whathandler = handlers[what]
+ local whatfeatures = whathandler.features
+ local whatinitializers = whatfeatures.initializers
+ local whatmodechecker = whatfeatures.modechecker
+ -- properties.mode can be enforces (for instance in font-otd)
+ local mode = properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
+ properties.mode = mode -- also status
+ features.mode = mode -- both properties.mode or features.mode can be changed
+ --
+ local done = { }
+ while true do
+ local redo = false
+ local initializers = whatfeatures.initializers[mode]
+ if initializers then
+ for i=1,#initializers do
+ local step = initializers[i]
+ local feature = step.name
+-- we could intercept mode here .. needs a rewrite of this whole loop then but it's cleaner that way
+ local value = features[feature]
+ if not value then
+ -- disabled
+ elseif done[feature] then
+ -- already done
+ else
+ local action = step.action
+ if trace then
+ report("initializing feature %a to %a for mode %a for font %a",feature,
+ value,mode,tfmdata.properties.fullname)
+ end
+ action(tfmdata,value,features) -- can set mode (e.g. goodies) so it can trigger a restart
+ if mode ~= properties.mode or mode ~= features.mode then
+ if whatmodechecker then
+ properties.mode = whatmodechecker(tfmdata,features,properties.mode) -- force checking
+ features.mode = properties.mode
+ end
+ if mode ~= properties.mode then
+ mode = properties.mode
+ redo = true
+ end
+ end
+ done[feature] = true
+ end
+ if redo then
+ break
+ end
+ end
+ if not redo then
+ break
+ end
+ else
+ break
+ end
+ end
+ properties.mode = mode -- to be sure
+ return true
+ else
+ return false
+ end
+end
+
+-- while typesetting
+
+function constructors.collectprocessors(what,tfmdata,features,trace,report)
+ local processes, nofprocesses = { }, 0
+ if features and next(features) then
+ local properties = tfmdata.properties
+ local whathandler = handlers[what]
+ local whatfeatures = whathandler.features
+ local whatprocessors = whatfeatures.processors
+ local mode = properties.mode
+ local processors = whatprocessors[mode]
+ if processors then
+ for i=1,#processors do
+ local step = processors[i]
+ local feature = step.name
+ if features[feature] then
+ local action = step.action
+ if trace then
+ report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+ end
+ if action then
+ nofprocesses = nofprocesses + 1
+ processes[nofprocesses] = action
+ end
+ end
+ end
+ elseif trace then
+ report("no feature processors for mode %a for font %a",mode,properties.fullname)
+ end
+ end
+ return processes
+end
+
+-- after scaling
+
+function constructors.applymanipulators(what,tfmdata,features,trace,report)
+ if features and next(features) then
+ local properties = tfmdata.properties
+ local whathandler = handlers[what]
+ local whatfeatures = whathandler.features
+ local whatmanipulators = whatfeatures.manipulators
+ local mode = properties.mode
+ local manipulators = whatmanipulators[mode]
+ if manipulators then
+ for i=1,#manipulators do
+ local step = manipulators[i]
+ local feature = step.name
+ local value = features[feature]
+ if value then
+ local action = step.action
+ if trace then
+ report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname)
+ end
+ if action then
+ action(tfmdata,feature,value)
+ end
+ end
+ end
+ end
+ end
+end
+
+function constructors.addcoreunicodes(unicodes) -- maybe make this a metatable if used at all
+ if not unicodes then
+ unicodes = { }
+ end
+ unicodes.space = 0x0020
+ unicodes.hyphen = 0x002D
+ unicodes.zwj = 0x200D
+ unicodes.zwnj = 0x200C
+ return unicodes
+end
+
+-- -- keep for a while: old tounicode code
+--
+-- if changed then
+-- -- basemode hack (we try to catch missing tounicodes, e.g. needed for ssty in math cambria)
+-- local c = changed[unicode]
+-- if c then
+-- -- local ligatures = character.ligatures -- the original ligatures (as we cannot rely on remapping)
+-- description = descriptions[c] or descriptions[unicode] or character
+-- character = characters[c] or character
+-- index = description.index or c
+-- if tounicode then
+-- touni = tounicode[index] -- nb: index!
+-- if not touni then -- goodie
+-- local d = descriptions[unicode] or characters[unicode]
+-- local i = d.index or unicode
+-- touni = tounicode[i] -- nb: index!
+-- end
+-- end
+-- -- if ligatures and not character.ligatures then
+-- -- character.ligatures = ligatures -- the original targets (for now at least.. see libertine smallcaps)
+-- -- end
+-- else
+-- description = descriptions[unicode] or character
+-- index = description.index or unicode
+-- if tounicode then
+-- touni = tounicode[index] -- nb: index!
+-- end
+-- end
+-- else
+-- description = descriptions[unicode] or character
+-- index = description.index or unicode
+-- if tounicode then
+-- touni = tounicode[index] -- nb: index!
+-- end
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua
new file mode 100644
index 00000000000..be233e5702d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua
@@ -0,0 +1,2498 @@
+if not modules then modules = { } end modules ['font-ctx'] = {
+ 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"
+}
+
+-- At some point I will clean up the code here so that at the tex end
+-- the table interface is used.
+--
+-- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true'
+-- in virtual fonts indices is implemented.
+
+local context, commands = context, commands
+
+local format, gmatch, match, find, lower, gsub, byte = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte
+local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged
+local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced
+local settings_to_hash, hash_to_string = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string
+local formatcolumns = utilities.formatters.formatcolumns
+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 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)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_designsize = false trackers.register("fonts.designsize", function(v) trace_designsize = v end)
+local trace_usage = false trackers.register("fonts.usage", function(v) trace_usage = v end)
+local trace_mapfiles = false trackers.register("fonts.mapfiles", function(v) trace_mapfiles = v end)
+local trace_automode = false trackers.register("fonts.automode", function(v) trace_automode = v end)
+local trace_merge = false trackers.register("fonts.merge", function(v) trace_merge = v end)
+
+local report_features = logs.reporter("fonts","features")
+local report_cummulative = logs.reporter("fonts","cummulative")
+local report_defining = logs.reporter("fonts","defining")
+local report_status = logs.reporter("fonts","status")
+local report_mapfiles = logs.reporter("fonts","mapfiles")
+
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+
+local fonts = fonts
+local handlers = fonts.handlers
+local otf = handlers.otf -- brrr
+local afm = handlers.afm -- brrr
+local tfm = handlers.tfm -- brrr
+local names = fonts.names
+local definers = fonts.definers
+local specifiers = fonts.specifiers
+local constructors = fonts.constructors
+local loggers = fonts.loggers
+local fontgoodies = fonts.goodies
+local helpers = fonts.helpers
+local hashes = fonts.hashes
+local currentfont = font.current
+local definefont = font.define
+
+local encodings = fonts.encodings
+----- aglunicodes = encodings.agl.unicodes
+local aglunicodes = nil -- delayed loading
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+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
+local texsetattribute = tex.setattribute
+local texgetdimen = tex.getdimen
+local texsetcount = tex.setcount
+local texget = tex.get
+
+local texdefinefont = tex.definefont
+local texsp = tex.sp
+
+local fontdata = hashes.identifiers
+local characters = hashes.characters
+local descriptions = hashes.descriptions
+local properties = hashes.properties
+local resources = hashes.resources
+local unicodes = hashes.unicodes
+local csnames = hashes.csnames
+local lastmathids = hashes.lastmathids
+local exheights = hashes.exheights
+local emwidths = hashes.emwidths
+local parameters = hashes.parameters
+
+local designsizefilename = fontgoodies.designsizes.filename
+
+local context_char = context.char
+local context_getvalue = context.getvalue
+
+local otffeatures = otf.features
+local otftables = otf.tables
+
+local registerotffeature = otffeatures.register
+local baseprocessors = otffeatures.processors.base
+local baseinitializers = otffeatures.initializers.base
+
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+
+specifiers.contextsetups = specifiers.contextsetups or { }
+specifiers.contextnumbers = specifiers.contextnumbers or { }
+specifiers.contextmerged = specifiers.contextmerged or { }
+specifiers.synonyms = specifiers.synonyms or { }
+
+local setups = specifiers.contextsetups
+local numbers = specifiers.contextnumbers
+local merged = specifiers.contextmerged
+local synonyms = specifiers.synonyms
+
+storage.register("fonts/setups" , setups , "fonts.specifiers.contextsetups" )
+storage.register("fonts/numbers", numbers, "fonts.specifiers.contextnumbers")
+storage.register("fonts/merged", merged, "fonts.specifiers.contextmerged")
+storage.register("fonts/synonyms", synonyms, "fonts.specifiers.synonyms")
+
+-- inspect(setups)
+
+if environment.initex then
+ setmetatableindex(setups,function(t,k)
+ return type(k) == "number" and rawget(t,numbers[k]) or nil
+ end)
+else
+ setmetatableindex(setups,function(t,k)
+ local v = type(k) == "number" and rawget(t,numbers[k])
+ if v then
+ t[k] = v
+ return v
+ end
+ end)
+end
+
+-- this will move elsewhere ...
+
+local function getfontname(tfmdata)
+ return basename(type(tfmdata) == "number" and properties[tfmdata].name or tfmdata.properties.name)
+end
+
+fonts.helpers.name = getfontname
+
+if _LUAVERSION < 5.2 then
+
+ utilities.strings.formatters.add(formatters,"font:name", [["'"..fontname(%s).."'"]], "local fontname = fonts.helpers.name")
+ utilities.strings.formatters.add(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],"local sequenced = table.sequenced")
+
+else
+
+ utilities.strings.formatters.add(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = fonts.helpers.name })
+ utilities.strings.formatters.add(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],{ sequenced = table.sequenced })
+
+end
+
+-- ... like font-sfm or so
+
+constructors.resolvevirtualtoo = true -- context specific (due to resolver)
+
+constructors.sharefonts = true -- experimental
+constructors.nofsharedhashes = 0
+constructors.nofsharedvectors = 0
+constructors.noffontsloaded = 0
+
+local shares = { }
+local hashes = { }
+
+function constructors.trytosharefont(target,tfmdata)
+ constructors.noffontsloaded = constructors.noffontsloaded + 1
+ if constructors.sharefonts then
+ local fonthash = target.specification.hash
+ if fonthash then
+ local properties = target.properties
+ local fullname = target.fullname
+ local sharedname = hashes[fonthash]
+ if sharedname then
+ -- this is ok for context as we know that only features can mess with font definitions
+ -- so a similar hash means that the fonts are similar too
+ if trace_defining then
+ report_defining("font %a uses backend resources of font %a (%s)",target.fullname,sharedname,"common hash")
+ end
+ target.fullname = sharedname
+ properties.sharedwith = sharedname
+ constructors.nofsharedfonts = constructors.nofsharedfonts + 1
+ constructors.nofsharedhashes = constructors.nofsharedhashes + 1
+ else
+ -- the one takes more time (in the worst case of many cjk fonts) but it also saves
+ -- embedding time
+ local characters = target.characters
+ local n = 1
+ local t = { target.psname }
+ local u = sortedkeys(characters)
+ for i=1,#u do
+ local k = u[i]
+ n = n + 1 ; t[n] = k
+ n = n + 1 ; t[n] = characters[k].index or k
+ end
+ local checksum = md5.HEX(concat(t," "))
+ local sharedname = shares[checksum]
+ local fullname = target.fullname
+ if sharedname then
+ if trace_defining then
+ report_defining("font %a uses backend resources of font %a (%s)",fullname,sharedname,"common vector")
+ end
+ fullname = sharedname
+ properties.sharedwith= sharedname
+ constructors.nofsharedfonts = constructors.nofsharedfonts + 1
+ constructors.nofsharedvectors = constructors.nofsharedvectors + 1
+ else
+ shares[checksum] = fullname
+ end
+ target.fullname = fullname
+ hashes[fonthash] = fullname
+ end
+ end
+ end
+end
+
+directives.register("fonts.checksharing",function(v)
+ if not v then
+ report_defining("font sharing in backend is disabled")
+ end
+ constructors.sharefonts = v
+end)
+
+function definers.resetnullfont()
+ -- resetting is needed because tikz misuses nullfont
+ local parameters = fonts.nulldata.parameters
+ --
+ parameters.slant = 0 -- 1
+ parameters.space = 0 -- 2
+ parameters.space_stretch = 0 -- 3
+ parameters.space_shrink = 0 -- 4
+ parameters.x_height = 0 -- 5
+ parameters.quad = 0 -- 6
+ parameters.extra_space = 0 -- 7
+ --
+ constructors.enhanceparameters(parameters) -- official copies for us
+ --
+ definers.resetnullfont = function() end
+end
+
+implement {
+ name = "resetnullfont",
+ onlyonce = true,
+ actions = function()
+ for i=1,7 do
+ -- we have no direct method yet
+ context([[\fontdimen%s\nullfont\zeropoint]],i)
+ end
+ definers.resetnullfont()
+ end
+}
+
+-- this cannot be a feature initializer as there is no auto namespace
+-- so we never enter the loop then; we can store the defaults in the tma
+-- file (features.gpos.mkmk = 1 etc)
+
+local needsnodemode = { -- we will have node mode by default anyway
+ -- gsub_single = true,
+ gsub_multiple = true,
+ -- gsub_alternate = true,
+ -- gsub_ligature = true,
+ gsub_context = true,
+ gsub_contextchain = true,
+ gsub_reversecontextchain = true,
+ -- chainsub = true,
+ -- reversesub = true,
+ gpos_mark2base = true,
+ gpos_mark2ligature = true,
+ gpos_mark2mark = true,
+ gpos_cursive = true,
+ -- gpos_single = true,
+ -- gpos_pair = true,
+ gpos_context = true,
+ gpos_contextchain = true,
+}
+
+otftables.scripts.auto = "automatic fallback to latn when no dflt present"
+
+-- setmetatableindex(otffeatures.descriptions,otftables.features)
+
+local privatefeatures = {
+ tlig = true,
+ trep = true,
+ anum = true,
+}
+
+local function checkedscript(tfmdata,resources,features)
+ local latn = false
+ local script = false
+ if resources.features then
+ for g, list in next, resources.features do
+ for f, scripts in next, list do
+ if privatefeatures[f] then
+ -- skip
+ elseif scripts.dflt then
+ script = "dflt"
+ break
+ elseif scripts.latn then
+ latn = true
+ end
+ end
+ end
+ end
+ if not script then
+ script = latn and "latn" or "dflt"
+ end
+ if trace_automode then
+ report_defining("auto script mode, using script %a in font %!font:name!",script,tfmdata)
+ end
+ features.script = script
+ return script
+end
+
+-- basemode combined with dynamics is somewhat tricky
+
+local function checkedmode(tfmdata,resources,features)
+ local sequences = resources.sequences
+ if sequences and #sequences > 0 then
+ local script = features.script or "dflt"
+ local language = features.language or "dflt"
+ for feature, value in next, features do
+ if value then
+ local found = false
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local features = sequence.features
+ if features then
+ local scripts = features[feature]
+ if scripts then
+ local languages = scripts[script]
+ if languages and languages[language] then
+ if found then
+ -- more than one lookup
+ if trace_automode then
+ report_defining("forcing mode %a, font %!font:name!, feature %a, script %a, language %a, %s",
+ "node",tfmdata,feature,script,language,"multiple lookups")
+ end
+ features.mode = "node"
+ return "node"
+ elseif needsnodemode[sequence.type] then
+ if trace_automode then
+ report_defining("forcing mode %a, font %!font:name!, feature %a, script %a, language %a, %s",
+ "node",tfmdata,feature,script,language,"no base support")
+ end
+ features.mode = "node"
+ return "node"
+ else
+ -- at least one lookup
+ found = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if trace_automode then
+ report_defining("forcing mode base, font %!font:name!",tfmdata)
+ end
+ features.mode = "base" -- new, or is this wrong?
+ return "base"
+end
+
+definers.checkedscript = checkedscript
+definers.checkedmode = checkedmode
+
+local function modechecker(tfmdata,features,mode) -- we cannot adapt features as they are shared!
+ if trace_features then
+ report_features("fontname %!font:name!, features %!font:features!",tfmdata,features)
+ end
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata and rawdata.resources
+ local script = features.script
+ if resources then
+ if script == "auto" then
+ script = checkedscript(tfmdata,resources,features)
+ end
+ if mode == "auto" then
+ mode = checkedmode(tfmdata,resources,features)
+ end
+ else
+ report_features("missing resources for font %!font:name!",tfmdata)
+ end
+ return mode
+end
+
+registerotffeature {
+ -- we only set the checker and leave other settings of the mode
+ -- feature as they are
+ name = "mode",
+ modechecker = modechecker,
+}
+
+-- -- default = true anyway
+--
+-- local normalinitializer = constructors.getfeatureaction("otf","initializers","node","analyze")
+--
+-- local function analyzeinitializer(tfmdata,value,features) -- attr
+-- if value == "auto" and features then
+-- value = features.init or features.medi or features.fina or features.isol or false
+-- end
+-- return normalinitializer(tfmdata,value,features)
+-- end
+--
+-- registerotffeature {
+-- name = "analyze",
+-- initializers = {
+-- node = analyzeinitializer,
+-- },
+-- }
+
+local beforecopyingcharacters = sequencers.new {
+ name = "beforecopyingcharacters",
+ arguments = "target,original",
+}
+
+appendgroup(beforecopyingcharacters,"before") -- user
+appendgroup(beforecopyingcharacters,"system") -- private
+appendgroup(beforecopyingcharacters,"after" ) -- user
+
+function constructors.beforecopyingcharacters(original,target)
+ local runner = beforecopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
+local aftercopyingcharacters = sequencers.new {
+ name = "aftercopyingcharacters",
+ arguments = "target,original",
+}
+
+appendgroup(aftercopyingcharacters,"before") -- user
+appendgroup(aftercopyingcharacters,"system") -- private
+appendgroup(aftercopyingcharacters,"after" ) -- user
+
+function constructors.aftercopyingcharacters(original,target)
+ local runner = aftercopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
+--[[ldx--
+<p>So far we haven't really dealt with features (or whatever we want
+to pass along with the font definition. We distinguish the following
+situations:</p>
+situations:</p>
+
+<code>
+name:xetex like specs
+name@virtual font spec
+name*context specification
+</code>
+--ldx]]--
+
+-- currently fonts are scaled while constructing the font, so we
+-- have to do scaling of commands in the vf at that point using e.g.
+-- "local scale = g.parameters.factor or 1" after all, we need to
+-- work with copies anyway and scaling needs to be done at some point;
+-- however, when virtual tricks are used as feature (makes more
+-- sense) we scale the commands in fonts.constructors.scale (and set the
+-- factor there)
+
+local loadfont = definers.loadfont
+
+function definers.loadfont(specification,size,id) -- overloads the one in font-def
+ local variants = definers.methods.variants
+ local virtualfeatures = specification.features.virtual
+ if virtualfeatures and virtualfeatures.preset then
+ local variant = variants[virtualfeatures.preset]
+ if variant then
+ return variant(specification,size,id)
+ end
+ else
+ local tfmdata = loadfont(specification,size,id)
+ -- constructors.checkvirtualid(tfmdata,id)
+ return tfmdata
+ end
+end
+
+local function predefined(specification)
+ local variants = definers.methods.variants
+ local detail = specification.detail
+ if detail ~= "" and variants[detail] then
+ specification.features.virtual = { preset = detail }
+ end
+ return specification
+end
+
+definers.registersplit("@", predefined,"virtual")
+
+local normalize_features = otffeatures.normalize -- should be general
+
+local function definecontext(name,t) -- can be shared
+ local number = setups[name] and setups[name].number or 0 -- hm, numbers[name]
+ if number == 0 then
+ number = #numbers + 1
+ numbers[number] = name
+ end
+ t.number = number
+ setups[name] = t
+ return number, t
+end
+
+local function presetcontext(name,parent,features) -- will go to con and shared
+ if features == "" and find(parent,"=",1,true) then
+ features = parent
+ parent = ""
+ end
+ if not features or features == "" then
+ features = { }
+ elseif type(features) == "string" then
+ features = normalize_features(settings_to_hash(features))
+ else
+ features = normalize_features(features)
+ end
+ -- todo: synonyms, and not otf bound
+ if parent ~= "" then
+ for p in gmatch(parent,"[^, ]+") do
+ local s = setups[p]
+ if s then
+ for k,v in next, s do
+ if features[k] == nil then
+ features[k] = v
+ end
+ end
+ else
+ -- just ignore an undefined one .. i.e. we can refer to not yet defined
+ end
+ end
+ end
+ -- these are auto set so in order to prevent redundant definitions
+ -- we need to preset them (we hash the features and adding a default
+ -- setting during initialization may result in a different hash)
+ --
+ -- for k,v in next, triggers do
+ -- if features[v] == nil then -- not false !
+ -- local vv = default_features[v]
+ -- if vv then features[v] = vv end
+ -- end
+ -- end
+ --
+ for feature,value in next, features do
+ if value == nil then -- not false !
+ local default = default_features[feature]
+ if default ~= nil then
+ features[feature] = default
+ end
+ end
+ end
+ -- sparse 'm so that we get a better hash and less test (experimental
+ -- optimization)
+ local t = { } -- can we avoid t ?
+ for k,v in next, features do
+-- if v then t[k] = v end
+ t[k] = v
+ end
+ -- needed for dynamic features
+ -- maybe number should always be renewed as we can redefine features
+ local number = setups[name] and setups[name].number or 0 -- hm, numbers[name]
+ if number == 0 then
+ number = #numbers + 1
+ numbers[number] = name
+ end
+ t.number = number
+ setups[name] = t
+ return number, t
+end
+
+local function contextnumber(name) -- will be replaced
+ local t = setups[name]
+ if not t then
+ return 0
+ elseif t.auto then
+ local lng = tonumber(tex.language)
+ local tag = name .. ":" .. lng
+ local s = setups[tag]
+ if s then
+ return s.number or 0
+ else
+ local script, language = languages.association(lng)
+ if t.script ~= script or t.language ~= language then
+ local s = fastcopy(t)
+ local n = #numbers + 1
+ setups[tag] = s
+ numbers[n] = tag
+ s.number = n
+ s.script = script
+ s.language = language
+ return n
+ else
+ setups[tag] = t
+ return t.number or 0
+ end
+ end
+ else
+ return t.number or 0
+ end
+end
+
+local function mergecontext(currentnumber,extraname,option) -- number string number (used in scrp-ini
+ local extra = setups[extraname]
+ if extra then
+ local current = setups[numbers[currentnumber]]
+ local mergedfeatures, mergedname = { }, nil
+ if option < 0 then
+ if current then
+ for k, v in next, current do
+ if not extra[k] then
+ mergedfeatures[k] = v
+ end
+ end
+ end
+ mergedname = currentnumber .. "-" .. extraname
+ else
+ if current then
+ for k, v in next, current do
+ mergedfeatures[k] = v
+ end
+ end
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ mergedname = currentnumber .. "+" .. extraname
+ end
+ local number = #numbers + 1
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = option
+ setups[mergedname] = mergedfeatures
+ return number -- contextnumber(mergedname)
+ else
+ return currentnumber
+ end
+end
+
+local extrasets = { }
+
+setmetatableindex(extrasets,function(t,k)
+ local v = mergehashes(setups,k)
+ t[k] = v
+ return v
+end)
+
+local function mergecontextfeatures(currentname,extraname,how,mergedname) -- string string
+ local extra = setups[extraname] or extrasets[extraname]
+ if extra then
+ local current = setups[currentname]
+ local mergedfeatures = { }
+ if how == "+" then
+ if current then
+ for k, v in next, current do
+ mergedfeatures[k] = v
+ end
+ end
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ if trace_merge then
+ report_features("merge %a, method %a, current %|T, extra %|T, result %|T",mergedname,"add",current or { },extra,mergedfeatures)
+ end
+ elseif how == "-" then
+ if current then
+ for k, v in next, current do
+ mergedfeatures[k] = v
+ end
+ end
+ for k, v in next, extra do
+ -- only boolean features
+ if v == true then
+ mergedfeatures[k] = false
+ end
+ end
+ if trace_merge then
+ report_features("merge %a, method %a, current %|T, extra %|T, result %|T",mergedname,"subtract",current or { },extra,mergedfeatures)
+ end
+ else -- =
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ if trace_merge then
+ report_features("merge %a, method %a, result %|T",mergedname,"replace",mergedfeatures)
+ end
+ end
+ local number = #numbers + 1
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = option
+ setups[mergedname] = mergedfeatures
+ return number
+ else
+ return numbers[currentname] or 0
+ end
+end
+
+local function registercontext(fontnumber,extraname,option)
+ local extra = setups[extraname]
+ if extra then
+ local mergedfeatures, mergedname = { }, nil
+ if option < 0 then
+ mergedname = fontnumber .. "-" .. extraname
+ else
+ mergedname = fontnumber .. "+" .. extraname
+ end
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ local number = #numbers + 1
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = option
+ setups[mergedname] = mergedfeatures
+ return number -- contextnumber(mergedname)
+ else
+ return 0
+ end
+end
+
+local function registercontextfeature(mergedname,extraname,how)
+ local extra = setups[extraname]
+ if extra then
+ local mergedfeatures = { }
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ local number = #numbers + 1 -- we somehow end up with steps of 2
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = how == "=" and 1 or 2 -- 1=replace, 2=combine
+ setups[mergedname] = mergedfeatures
+ return number -- contextnumber(mergedname)
+ else
+ report_features("unknown feature %a cannot be merged into %a using method %a",extraname,mergedname,how)
+ return 0
+ end
+end
+
+specifiers.presetcontext = presetcontext
+specifiers.contextnumber = contextnumber
+specifiers.mergecontext = mergecontext
+specifiers.registercontext = registercontext
+specifiers.definecontext = definecontext
+
+-- we extend the hasher:
+
+-- constructors.hashmethods.virtual = function(list)
+-- local s = { }
+-- local n = 0
+-- for k, v in next, list do
+-- n = n + 1
+-- s[n] = k -- no checking on k
+-- end
+-- if n > 0 then
+-- sort(s)
+-- for i=1,n do
+-- local k = s[i]
+-- s[i] = k .. '=' .. tostring(list[k])
+-- end
+-- return concat(s,"+")
+-- end
+-- end
+
+constructors.hashmethods.virtual = function(list)
+ local s = { }
+ local n = 0
+ for k, v in next, list do
+ n = n + 1
+ -- if v == true then
+ -- s[n] = k .. '=true'
+ -- elseif v == false then
+ -- s[n] = k .. '=false'
+ -- else
+ -- s[n] = k .. "=" .. v
+ -- end
+ s[n] = k .. "=" .. tostring(v)
+ end
+ if n > 0 then
+ sort(s)
+ return concat(s,"+")
+ end
+end
+
+-- end of redefine
+
+-- local withcache = { } -- concat might be less efficient than nested tables
+--
+-- local function withset(name,what)
+-- local zero = texgetattribute(0)
+-- local hash = zero .. "+" .. name .. "*" .. what
+-- local done = withcache[hash]
+-- if not done then
+-- done = mergecontext(zero,name,what)
+-- withcache[hash] = done
+-- end
+-- texsetattribute(0,done)
+-- end
+--
+-- local function withfnt(name,what,font)
+-- local font = font or currentfont()
+-- local hash = font .. "*" .. name .. "*" .. what
+-- local done = withcache[hash]
+-- if not done then
+-- done = registercontext(font,name,what)
+-- withcache[hash] = done
+-- end
+-- texsetattribute(0,done)
+-- end
+
+function specifiers.showcontext(name)
+ return setups[name] or setups[numbers[name]] or setups[numbers[tonumber(name)]] or { }
+end
+
+-- we need a copy as we will add (fontclass) goodies to the features and
+-- that is bad for a shared table
+
+-- local function splitcontext(features) -- presetcontext creates dummy here
+-- return fastcopy(setups[features] or (presetcontext(features,"","") and setups[features]))
+-- end
+
+local function splitcontext(features) -- presetcontext creates dummy here
+ local sf = setups[features]
+ if not sf then
+ local n -- number
+ if find(features,",",a,true) then
+ -- let's assume a combination which is not yet defined but just specified (as in math)
+ n, sf = presetcontext(features,features,"")
+ else
+ -- we've run into an unknown feature and or a direct spec so we create a dummy
+ n, sf = presetcontext(features,"","")
+ end
+ end
+ return fastcopy(sf)
+end
+
+-- local splitter = lpeg.splitat("=")
+--
+-- local function splitcontext(features)
+-- local setup = setups[features]
+-- if setup then
+-- return setup
+-- elseif find(features,",",1,true) then
+-- -- This is not that efficient but handy anyway for quick and dirty tests
+-- -- beware, due to the way of caching setups you can get the wrong results
+-- -- when components change. A safeguard is to nil the cache.
+-- local merge = nil
+-- for feature in gmatch(features,"[^, ]+") do
+-- if find(feature,"=",1,true) then
+-- local k, v = lpegmatch(splitter,feature)
+-- if k and v then
+-- if not merge then
+-- merge = { k = v }
+-- else
+-- merge[k] = v
+-- end
+-- end
+-- else
+-- local s = setups[feature]
+-- if not s then
+-- -- skip
+-- elseif not merge then
+-- merge = s
+-- else
+-- for k, v in next, s do
+-- merge[k] = v
+-- end
+-- end
+-- end
+-- end
+-- setup = merge and presetcontext(features,"",merge) and setups[features]
+-- -- actually we have to nil setups[features] in order to permit redefinitions
+-- setups[features] = nil
+-- end
+-- return setup or (presetcontext(features,"","") and setups[features]) -- creates dummy
+-- end
+
+specifiers.splitcontext = splitcontext
+
+function specifiers.contexttostring(name,kind,separator,yes,no,strict,omit) -- not used
+ return hash_to_string(
+ mergedtable(handlers[kind].features.defaults or {},setups[name] or {}),
+ separator, yes, no, strict, omit or { "number" }
+ )
+end
+
+local function starred(features) -- no longer fallbacks here
+ local detail = features.detail
+ if detail and detail ~= "" then
+ features.features.normal = splitcontext(detail)
+ else
+ features.features.normal = { }
+ end
+ return features
+end
+
+definers.registersplit('*',starred,"featureset")
+
+-- sort of xetex mode, but without [] and / as we have file: and name: etc
+
+local space = P(" ")
+local spaces = space^0
+local separator = S(";,")
+local equal = P("=")
+local sometext = C((1-equal-space-separator)^1)
+local truevalue = P("+") * spaces * sometext * Cc(true)
+local falsevalue = P("-") * spaces * sometext * Cc(false)
+local somevalue = sometext * spaces * Cc(true)
+local keyvalue = sometext * spaces * equal * spaces * sometext
+local pattern = Cf(Ct("") * (space + separator + Cg(falsevalue + truevalue + keyvalue + somevalue))^0, rawset)
+
+local function colonized(specification)
+ specification.features.normal = normalize_features(lpegmatch(pattern,specification.detail))
+ return specification
+end
+
+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") * 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
+
+function helpers.splitfontpattern(str)
+ local name, size = lpegmatch(splitpattern,str)
+ local kind, size = lpegmatch(sizepattern,size)
+ return name, kind, size
+end
+
+function helpers.fontpatternhassize(str)
+ local name, size = lpegmatch(splitpattern,str)
+ local kind, size = lpegmatch(sizepattern,size)
+ return size or false
+end
+
+local specification -- still needed as local ?
+
+local getspecification = definers.getspecification
+
+-- we can make helper macros which saves parsing (but normaly not
+-- that many calls, e.g. in mk a couple of 100 and in metafun 3500)
+
+do -- else too many locals
+
+ ----- ctx_setdefaultfontname = context.fntsetdefname
+ ----- ctx_setsomefontname = context.fntsetsomename
+ ----- ctx_setemptyfontsize = context.fntsetnopsize
+ ----- ctx_setsomefontsize = context.fntsetsomesize
+ ----- ctx_letvaluerelax = context.letvaluerelax
+
+ local starttiming = statistics.starttiming
+ local stoptiming = statistics.stoptiming
+
+ local scanners = tokens.scanners
+ local scanstring = scanners.string
+ local scaninteger = scanners.integer
+ local scanboolean = scanners.boolean
+
+ local setmacro = tokens.setters.macro
+
+ local scanners = interfaces.scanners
+
+ -- function commands.definefont_one(str)
+
+ scanners.definefont_one = function()
+ local str = scanstring()
+
+ starttiming(fonts)
+ if trace_defining then
+ report_defining("memory usage before: %s",statistics.memused())
+ report_defining("start stage one: %s",str)
+ end
+ local fullname, size = lpegmatch(splitpattern,str)
+ local lookup, name, sub, method, detail = getspecification(fullname)
+ if not name then
+ report_defining("strange definition %a",str)
+ -- ctx_setdefaultfontname()
+ elseif name == "unknown" then
+ -- ctx_setdefaultfontname()
+ else
+ -- ctx_setsomefontname(name)
+ setmacro("somefontname",name,"global")
+ end
+ -- we can also use a count for the size
+ if size and size ~= "" then
+ local mode, size = lpegmatch(sizepattern,size)
+ if size and mode then
+ texsetcount("scaledfontmode",mode)
+ -- ctx_setsomefontsize(size)
+ setmacro("somefontsize",size)
+ else
+ texsetcount("scaledfontmode",0)
+ -- ctx_setemptyfontsize()
+ end
+ elseif true then
+ -- so we don't need to check in tex
+ texsetcount("scaledfontmode",2)
+ -- ctx_setemptyfontsize()
+ else
+ texsetcount("scaledfontmode",0)
+ -- ctx_setemptyfontsize()
+ end
+ specification = definers.makespecification(str,lookup,name,sub,method,detail,size)
+ if trace_defining then
+ report_defining("stop stage one")
+ end
+ end
+
+ local n = 0
+
+ -- we can also move rscale to here (more consistent)
+ -- the argument list will become a table
+
+ local function nice_cs(cs)
+ return (gsub(cs,".->", ""))
+ end
+
+ -- function commands.definefont_two(global,cs,str,size,inheritancemode,classfeatures,fontfeatures,classfallbacks,fontfallbacks,
+ -- mathsize,textsize,relativeid,classgoodies,goodies,classdesignsize,fontdesignsize,scaledfontmode)
+
+ scanners.definefont_two = function()
+
+ local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
+ local cs = scanstring () -- {#csname}%
+ local str = scanstring () -- \somefontfile
+ local size = scaninteger() -- \d_font_scaled_font_size
+ local inheritancemode = scaninteger() -- \c_font_feature_inheritance_mode
+ local classfeatures = scanstring () -- \m_font_class_features
+ local fontfeatures = scanstring () -- \m_font_features
+ local classfallbacks = scanstring () -- \m_font_class_fallbacks
+ local fontfallbacks = scanstring () -- \m_font_fallbacks
+ local mathsize = scaninteger() -- \fontface
+ local textsize = scaninteger() -- \d_font_scaled_text_face
+ local relativeid = scaninteger() -- \relativefontid
+ local classgoodies = scanstring () -- \m_font_class_goodies
+ local goodies = scanstring () -- \m_font_goodies
+ local classdesignsize = scanstring () -- \m_font_class_designsize
+ local fontdesignsize = scanstring () -- \m_font_designsize
+ local scaledfontmode = scaninteger() -- \scaledfontmode
+
+ if trace_defining then
+ report_defining("start stage two: %s (size %s)",str,size)
+ end
+ -- name is now resolved and size is scaled cf sa/mo
+ local lookup, name, sub, method, detail = getspecification(str or "")
+ -- new (todo: inheritancemode)
+ local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or ""
+ local designname = designsizefilename(name,designsize,size)
+ if designname and designname ~= "" then
+ if trace_defining or trace_designsize then
+ report_defining("remapping name %a, specification %a, size %a, designsize %a",name,designsize,size,designname)
+ end
+ -- we don't catch detail here
+ local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname)
+ if o_lookup and o_lookup ~= "" then lookup = o_lookup end
+ if o_method and o_method ~= "" then method = o_method end
+ if o_detail and o_detail ~= "" then detail = o_detail end
+ name = o_name
+ sub = o_sub
+ end
+ -- so far
+ -- some settings can have been overloaded
+ if lookup and lookup ~= "" then
+ specification.lookup = lookup
+ end
+ if relativeid and relativeid ~= "" then -- experimental hook
+ local id = tonumber(relativeid) or 0
+ specification.relativeid = id > 0 and id
+ end
+ --
+ specification.name = name
+ specification.size = size
+ specification.sub = (sub and sub ~= "" and sub) or specification.sub
+ specification.mathsize = mathsize
+ specification.textsize = textsize
+ specification.goodies = goodies
+ specification.cs = cs
+ specification.global = global
+ specification.scalemode = scaledfontmode -- context specific
+ if detail and detail ~= "" then
+ specification.method = method or "*"
+ specification.detail = detail
+ elseif specification.detail and specification.detail ~= "" then
+ -- already set
+ elseif inheritancemode == 0 then
+ -- nothing
+ elseif inheritancemode == 1 then
+ -- fontonly
+ if fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = fontfeatures
+ end
+ if fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ end
+ elseif inheritancemode == 2 then
+ -- classonly
+ if classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ end
+ if classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ end
+ elseif inheritancemode == 3 then
+ -- fontfirst
+ if fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = fontfeatures
+ elseif classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ end
+ if fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ elseif classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ end
+ elseif inheritancemode == 4 then
+ -- classfirst
+ if classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ elseif fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = fontfeatures
+ end
+ if classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ elseif fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ end
+ end
+ local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
+ --
+ local lastfontid = 0
+ if not tfmdata then
+ report_defining("unable to define %a as %a",name,nice_cs(cs))
+ lastfontid = -1
+ texsetcount("scaledfontsize",0)
+ -- ctx_letvaluerelax(cs) -- otherwise the current definition takes the previous one
+ elseif type(tfmdata) == "number" then
+ if trace_defining then
+ report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a",
+ name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize)
+ end
+ csnames[tfmdata] = specification.cs
+ texdefinefont(global,cs,tfmdata)
+ -- resolved (when designsize is used):
+ local size = fontdata[tfmdata].parameters.size or 0
+ -- ctx_setsomefontsize(size .. "sp")
+ setmacro("somefontsize",size.."sp")
+ texsetcount("scaledfontsize",size)
+ lastfontid = tfmdata
+ else
+ -- setting the extra characters will move elsewhere
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
+ characters[0] = nil
+ -- characters[0x00A0] = { width = parameters.space }
+ -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
+ -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
+ --
+ constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
+ local id = definefont(tfmdata)
+ csnames[id] = specification.cs
+ tfmdata.properties.id = id
+ definers.register(tfmdata,id) -- to be sure, normally already done
+ texdefinefont(global,cs,id)
+ constructors.cleanuptable(tfmdata)
+ constructors.finalize(tfmdata)
+ if trace_defining then
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ end
+ -- resolved (when designsize is used):
+ local size = tfmdata.parameters.size or 655360
+ setmacro("somefontsize",size.."sp")
+ -- ctx_setsomefontsize(size .. "sp")
+ texsetcount("scaledfontsize",size)
+ lastfontid = id
+ end
+ if trace_defining then
+ report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
+ end
+ --
+ texsetcount("global","lastfontid",lastfontid)
+ if not mathsize then
+ -- forget about it
+ elseif mathsize == 0 then
+ lastmathids[1] = lastfontid
+ else
+ lastmathids[mathsize] = lastfontid
+ end
+ --
+ stoptiming(fonts)
+ end
+
+ --
+
+ function definers.define(specification)
+ --
+ local name = specification.name
+ if not name or name == "" then
+ return -1
+ else
+ starttiming(fonts)
+ --
+ -- following calls expect a few properties to be set:
+ --
+ local lookup, name, sub, method, detail = getspecification(name or "")
+ --
+ specification.name = (name ~= "" and name) or specification.name
+ --
+ specification.lookup = specification.lookup or (lookup ~= "" and lookup) or "file"
+ specification.size = specification.size or 655260
+ specification.sub = specification.sub or (sub ~= "" and sub) or ""
+ specification.method = specification.method or (method ~= "" and method) or "*"
+ specification.detail = specification.detail or (detail ~= "" and detail) or ""
+ --
+ if type(specification.size) == "string" then
+ specification.size = texsp(specification.size) or 655260
+ end
+ --
+ specification.specification = "" -- not used
+ specification.resolved = ""
+ specification.forced = ""
+ specification.features = { } -- via detail, maybe some day
+ --
+ -- we don't care about mathsize textsize goodies fallbacks
+ --
+ local cs = specification.cs
+ if cs == "" then
+ cs = nil
+ specification.cs = nil
+ specification.global = false
+ elseif specification.global == nil then
+ specification.global = false
+ end
+ --
+ local tfmdata = definers.read(specification,specification.size)
+ if not tfmdata then
+ return -1, nil
+ elseif type(tfmdata) == "number" then
+ if cs then
+ texdefinefont(specification.global,cs,tfmdata)
+ csnames[tfmdata] = cs
+ end
+ return tfmdata, fontdata[tfmdata]
+ else
+ constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
+ local id = definefont(tfmdata)
+ tfmdata.properties.id = id
+ definers.register(tfmdata,id)
+ if cs then
+ texdefinefont(specification.global,cs,id)
+ csnames[id] = cs
+ end
+ constructors.cleanuptable(tfmdata)
+ constructors.finalize(tfmdata)
+ return id, tfmdata
+ end
+ stoptiming(fonts)
+ end
+ end
+
+ -- local id, cs = fonts.definers.internal { }
+ -- local id, cs = fonts.definers.internal { number = 2 }
+ -- local id, cs = fonts.definers.internal { name = "dejavusans" }
+
+ local n = 0
+
+ function definers.internal(specification,cs)
+ specification = specification or { }
+ local name = specification.name
+ local size = tonumber(specification.size)
+ local number = tonumber(specification.number)
+ local id = nil
+ if not size then
+ size = texgetdimen("bodyfontsize")
+ end
+ if number then
+ id = number
+ elseif name and name ~= "" then
+ local cs = cs or specification.cs
+ if not cs then
+ n = n + 1 -- beware ... there can be many and they are often used once
+ -- cs = formatters["internal font %s"](n)
+ cs = "internal font " .. n
+ else
+ specification.cs = cs
+ end
+ id = definers.define {
+ name = name,
+ size = size,
+ cs = cs,
+ }
+ end
+ if not id then
+ id = currentfont()
+ end
+ return id, csnames[id]
+ end
+
+ -- here
+
+ local infofont = 0
+
+ function fonts.infofont()
+ if infofont == 0 then
+ infofont = definers.define { name = "dejavusansmono", size = tex.sp("6pt") }
+ end
+ return infofont
+ end
+
+end
+
+local enable_auto_r_scale = false
+
+experiments.register("fonts.autorscale", function(v)
+ enable_auto_r_scale = v
+end)
+
+-- Not ok, we can best use a database for this. The problem is that we
+-- have delayed definitions and so we never know what style is taken
+-- as start.
+
+local calculatescale = constructors.calculatescale
+
+function constructors.calculatescale(tfmdata,scaledpoints,relativeid,specification)
+ if specification then
+ local scalemode = specification.scalemode
+ local special = scalemode and specialscale[scalemode]
+ if special then
+ -- we also have available specification.textsize
+ local parameters = tfmdata.parameters
+ -- local designsize = parameters.designsize
+ if special == "ht" then
+ local height = parameters.ascender / parameters.units
+ scaledpoints = scaledpoints / height
+ elseif special == "cp" then
+ local glyph = tfmdata.descriptions[utfbyte("X")]
+ local height = (glyph and glyph.height or parameters.ascender) / parameters.units
+ scaledpoints = scaledpoints / height
+ end
+ end
+ end
+ local scaledpoints, delta = calculatescale(tfmdata,scaledpoints)
+ -- if enable_auto_r_scale and relativeid then -- for the moment this is rather context specific (we need to hash rscale then)
+ -- local relativedata = fontdata[relativeid]
+ -- local rfmdata = relativedata and relativedata.unscaled and relativedata.unscaled
+ -- local id_x_height = rfmdata and rfmdata.parameters and rfmdata.parameters.x_height
+ -- local tf_x_height = tfmdata and tfmdata.parameters and tfmdata.parameters.x_height
+ -- if id_x_height and tf_x_height then
+ -- local rscale = id_x_height/tf_x_height
+ -- delta = rscale * delta
+ -- scaledpoints = rscale * scaledpoints
+ -- end
+ -- end
+ return scaledpoints, delta
+end
+
+local designsizes = constructors.designsizes
+
+function constructors.hashinstance(specification,force)
+ local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
+ if force or not hash then
+ hash = constructors.hashfeatures(specification)
+ specification.hash = hash
+ end
+ if size < 1000 and designsizes[hash] then
+ size = math.round(constructors.scaled(size,designsizes[hash]))
+ specification.size = size
+ end
+ if fallbacks then
+ return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks
+ else
+ local scalemode = specification.scalemode
+ local special = scalemode and specialscale[scalemode]
+ if special then
+ return hash .. ' @ ' .. tostring(size) .. ' @ ' .. special
+ else
+ return hash .. ' @ ' .. tostring(size)
+ end
+ end
+end
+
+-- We overload the (generic) resolver:
+
+local resolvers = definers.resolvers
+local hashfeatures = constructors.hashfeatures
+
+function definers.resolve(specification) -- overload function in font-con.lua
+ if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash
+ local r = resolvers[specification.lookup]
+ if r then
+ r(specification)
+ end
+ end
+ if specification.forced == "" then
+ specification.forced = nil
+ else
+ specification.forced = specification.forced
+ end
+ -- goodies are a context specific thing and not always defined
+ -- as feature, so we need to make sure we add them here before
+ -- hashing because otherwise we get funny goodies applied
+ local goodies = specification.goodies
+ if goodies and goodies ~= "" then
+ -- this adapts the features table so it has best be a copy
+ local normal = specification.features.normal
+ if not normal then
+ specification.features.normal = { goodies = goodies }
+ elseif not normal.goodies then
+ local g = normal.goodies
+ if g and g ~= "" then
+ normal.goodies = formatters["%s,%s"](g,goodies)
+ else
+ normal.goodies = goodies
+ end
+ end
+ end
+ -- so far for goodie hacks
+ specification.hash = lower(specification.name .. ' @ ' .. hashfeatures(specification))
+ if specification.sub and specification.sub ~= "" then
+ specification.hash = specification.sub .. ' @ ' .. specification.hash
+ end
+ return specification
+end
+
+
+-- soon to be obsolete:
+
+local mappings = fonts.mappings
+
+local loaded = { -- prevent loading (happens in cont-sys files)
+ -- ["original-base.map" ] = true,
+ -- ["original-ams-base.map" ] = true,
+ -- ["original-ams-euler.map"] = true,
+ -- ["original-public-lm.map"] = true,
+}
+
+function mappings.loadfile(name)
+ name = file.addsuffix(name,"map")
+ if not loaded[name] then
+ if trace_mapfiles then
+ report_mapfiles("loading map file %a",name)
+ end
+ pdf.mapfile(name)
+ loaded[name] = true
+ end
+end
+
+local loaded = { -- prevent double loading
+}
+
+function mappings.loadline(how,line)
+ if line then
+ how = how .. " " .. line
+ elseif how == "" then
+ how = "= " .. line
+ end
+ if not loaded[how] then
+ if trace_mapfiles then
+ report_mapfiles("processing map line %a",line)
+ end
+ pdf.mapline(how)
+ loaded[how] = true
+ end
+end
+
+function mappings.reset()
+ pdf.mapfile("")
+end
+
+mappings.reset() -- resets the default file
+
+implement {
+ name = "loadmapfile",
+ actions = mappings.loadfile,
+ arguments = "string"
+}
+
+implement {
+ name = "loadmapline",
+ actions = mappings.loadline,
+ arguments = "string"
+}
+
+implement {
+ name = "resetmapfiles",
+ actions = mappings.reset,
+ arguments = "string"
+}
+
+-- we need an 'do after the banner hook'
+
+-- => commands
+
+local function nametoslot(name)
+ local t = type(name)
+ local s = nil
+ if t == "string" then
+ local slot = unicodes[true][name]
+ if slot then
+ return slot
+ end
+ if not aglunicodes then
+ aglunicodes = encodings.agl.unicodes
+ end
+ slot = aglunicodes[name]
+ if characters[true][slot] then
+ return slot
+ else
+ -- not in font
+ end
+ elseif t == "number" then
+ if characters[true][name] then
+ return slot
+ else
+ -- not in font
+ end
+ end
+end
+
+local function indextoslot(index)
+ local r = resources[true]
+ if r then
+ local indices = r.indices
+ if not indices then
+ indices = { }
+ local c = characters[true]
+ for unicode, data in next, c do
+ local di = data.index
+ if di then
+ indices[di] = unicode
+ end
+ end
+ r.indices = indices
+ end
+ return indices[tonumber(index)]
+ end
+end
+
+do -- else too many locals
+
+ local entities = characters.entities
+ local lowered = { } -- delayed initialization
+
+ setmetatableindex(lowered,function(t,k)
+ for k, v in next, entities do
+ local l = lower(k)
+ if not entities[l] then
+ lowered[l] = v
+ end
+ end
+ setmetatableindex(lowered,nil)
+ return lowered[k]
+ end)
+
+ local methods = {
+ -- entity
+ e = function(name)
+ return entities[name] or lowered[name] or name
+ end,
+ -- hexadecimal unicode
+ x = function(name)
+ local n = tonumber(name,16)
+ return n and utfchar(n) or name
+ end,
+ -- decimal unicode
+ d = function(name)
+ local n = tonumber(name)
+ return n and utfchar(n) or name
+ end,
+ -- hexadecimal index (slot)
+ s = function(name)
+ local n = tonumber(name,16)
+ local n = n and indextoslot(n)
+ return n and utfchar(n) or name
+ end,
+ -- decimal index
+ i = function(name)
+ local n = tonumber(name)
+ local n = n and indextoslot(n)
+ return n and utfchar(n) or name
+ end,
+ -- name
+ n = function(name)
+ local n = nametoslot(name)
+ return n and utfchar(n) or name
+ end,
+ -- char
+ c = function(name)
+ return name
+ end,
+ }
+
+ -- -- nicer:
+ --
+ -- setmetatableindex(methods,function(t,k) return methods.c end)
+ --
+ -- local splitter = (C(1) * P(":") + Cc("c")) * C(P(1)^1) / function(method,name)
+ -- return methods[method](name)
+ -- end
+ --
+ -- -- more efficient:
+
+ local splitter = C(1) * P(":") * C(P(1)^1) / function(method,name)
+ local action = methods[method]
+ return action and action(name) or name
+ end
+
+ local function tochar(str)
+ local t = type(str)
+ if t == "number" then
+ return utfchar(str)
+ elseif t == "string" then
+ return lpegmatch(splitter,str) or str
+ else
+ return str
+ end
+ end
+
+ helpers.nametoslot = nametoslot
+ helpers.indextoslot = indextoslot
+ helpers.tochar = tochar
+
+ -- interfaces:
+
+ implement {
+ name = "fontchar",
+ actions = { nametoslot, context_char },
+ arguments = "string",
+ }
+
+ implement {
+ name = "fontcharbyindex",
+ actions = { indextoslot, context_char },
+ arguments = "integer",
+ }
+
+ implement {
+ name = "tochar",
+ actions = { tochar, context },
+ arguments = "string",
+ }
+
+end
+
+-- this will change ...
+
+function loggers.reportdefinedfonts()
+ if trace_usage then
+ local t, tn = { }, 0
+ for id, data in sortedhash(fontdata) do
+ local properties = data.properties or { }
+ local parameters = data.parameters or { }
+ tn = tn + 1
+ t[tn] = {
+ format("%03i",id or 0),
+ format("%09i",parameters.size or 0),
+ properties.type or "real",
+ properties.format or "unknown",
+ properties.name or "",
+ properties.psname or "",
+ properties.fullname or "",
+ properties.sharedwith or "",
+ }
+ report_status("%s: % t",properties.name,sortedkeys(data))
+ end
+ formatcolumns(t," ")
+ report_status()
+ report_status("defined fonts:")
+ report_status()
+ for k=1,tn do
+ report_status(t[k])
+ end
+ end
+end
+
+luatex.registerstopactions(loggers.reportdefinedfonts)
+
+function loggers.reportusedfeatures()
+ -- numbers, setups, merged
+ if trace_usage then
+ local t, n = { }, #numbers
+ for i=1,n do
+ local name = numbers[i]
+ local setup = setups[name]
+ local n = setup.number
+ setup.number = nil -- we have no reason to show this
+ t[i] = { i, name, sequenced(setup,false,true) } -- simple mode
+ setup.number = n -- restore it (normally not needed as we're done anyway)
+ end
+ formatcolumns(t," ")
+ report_status()
+ report_status("defined featuresets:")
+ report_status()
+ for k=1,n do
+ report_status(t[k])
+ end
+ end
+end
+
+luatex.registerstopactions(loggers.reportusedfeatures)
+
+-- maybe move this to font-log.lua:
+
+statistics.register("font engine", function()
+ local elapsed = statistics.elapsedseconds(fonts)
+ local nofshared = constructors.nofsharedfonts or 0
+ local nofloaded = constructors.noffontsloaded or 0
+ if nofshared > 0 then
+ return format("otf %0.3f, afm %0.3f, tfm %0.3f, %s instances, %s shared in backend, %s common vectors, %s common hashes, load time %s",
+ otf.version,afm.version,tfm.version,nofloaded,
+ nofshared,constructors.nofsharedvectors,constructors.nofsharedhashes,
+ elapsed)
+ elseif nofloaded > 0 and elapsed then
+ return format("otf %0.3f, afm %0.3f, tfm %0.3f, %s instances, load time %s",
+ otf.version,afm.version,tfm.version,nofloaded,
+ elapsed)
+ else
+ return format("otf %0.3f, afm %0.3f, tfm %0.3f",
+ otf.version,afm.version,tfm.version)
+ end
+end)
+
+-- experimental mechanism for Mojca:
+--
+-- fonts.definetypeface {
+-- name = "mainbodyfont-light",
+-- preset = "antykwapoltawskiego-light",
+-- }
+--
+-- fonts.definetypeface {
+-- name = "mojcasfavourite",
+-- preset = "antykwapoltawskiego",
+-- normalweight = "light",
+-- boldweight = "bold",
+-- width = "condensed",
+-- }
+
+local Shapes = {
+ serif = "Serif",
+ sans = "Sans",
+ mono = "Mono",
+}
+
+local ctx_startfontclass = context.startfontclass
+local ctx_stopfontclass = context.stopfontclass
+local ctx_definefontsynonym = context.definefontsynonym
+local ctx_dofastdefinetypeface = context.dofastdefinetypeface
+
+function fonts.definetypeface(name,t)
+ if type(name) == "table" then
+ -- {name=abc,k=v,...}
+ t = name
+ elseif t then
+ if type(t) == "string" then
+ -- "abc", "k=v,..."
+ t = settings_to_hash(name)
+ else
+ -- "abc", {k=v,...}
+ end
+ t.name = t.name or name
+ else
+ -- "name=abc,k=v,..."
+ t = settings_to_hash(name)
+ end
+ local p = t.preset and fonts.typefaces[t.preset] or { }
+ local name = t.name or "unknowntypeface"
+ local shortcut = t.shortcut or p.shortcut or "rm"
+ local size = t.size or p.size or "default"
+ local shape = t.shape or p.shape or "serif"
+ local fontname = t.fontname or p.fontname or "unknown"
+ local normalweight = t.normalweight or t.weight or p.normalweight or p.weight or "normal"
+ local boldweight = t.boldweight or t.weight or p.boldweight or p.weight or "normal"
+ local normalwidth = t.normalwidth or t.width or p.normalwidth or p.width or "normal"
+ local boldwidth = t.boldwidth or t.width or p.boldwidth or p.width or "normal"
+ Shape = Shapes[shape] or "Serif"
+ ctx_startfontclass { name }
+ ctx_definefontsynonym( { formatters["%s"] (Shape) }, { formatters["spec:%s-%s-regular-%s"] (fontname, normalweight, normalwidth) } )
+ ctx_definefontsynonym( { formatters["%sBold"] (Shape) }, { formatters["spec:%s-%s-regular-%s"] (fontname, boldweight, boldwidth ) } )
+ ctx_definefontsynonym( { formatters["%sBoldItalic"](Shape) }, { formatters["spec:%s-%s-italic-%s"] (fontname, boldweight, boldwidth ) } )
+ ctx_definefontsynonym( { formatters["%sItalic"] (Shape) }, { formatters["spec:%s-%s-italic-%s"] (fontname, normalweight, normalwidth) } )
+ ctx_stopfontclass()
+ local settings = sequenced({ features= t.features },",")
+ ctx_dofastdefinetypeface(name, shortcut, shape, size, settings)
+end
+
+implement {
+ name = "definetypeface",
+ actions = fonts.definetypeface,
+ arguments = { "string", "string" }
+}
+
+function fonts.current() -- todo: also handle name
+ return fontdata[currentfont()] or fontdata[0]
+end
+
+function fonts.currentid()
+ return currentfont() or 0
+end
+
+-- for the moment here, this will become a chain of extras that is
+-- hooked into the ctx registration (or scaler or ...)
+
+local dimenfactors = number.dimenfactors
+
+function helpers.dimenfactor(unit,id)
+ if unit == "ex" then
+ return id and exheights[id] or 282460 -- lm 10pt
+ elseif unit == "em" then
+ return id and emwidths [id] or 655360 -- lm 10pt
+ else
+ local du = dimenfactors[unit]
+ return du and 1/du or tonumber(unit) or 1
+ end
+end
+
+local function digitwidth(font) -- max(quad/2,wd(0..9))
+ local tfmdata = fontdata[font]
+ local parameters = tfmdata.parameters
+ local width = parameters.digitwidth
+ if not width then
+ width = round(parameters.quad/2) -- maybe tex.scale
+ local characters = tfmdata.characters
+ for i=48,57 do
+ local wd = round(characters[i].width)
+ if wd > width then
+ width = wd
+ end
+ end
+ parameters.digitwidth = width
+ end
+ return width
+end
+
+helpers.getdigitwidth = digitwidth
+helpers.setdigitwidth = digitwidth
+
+--
+
+function helpers.getparameters(tfmdata)
+ local p = { }
+ local m = p
+ local parameters = tfmdata.parameters
+ while true do
+ for k, v in next, parameters do
+ m[k] = v
+ end
+ parameters = getmetatable(parameters)
+ parameters = parameters and parameters.__index
+ if type(parameters) == "table" then
+ m = { }
+ p.metatable = m
+ else
+ break
+ end
+ end
+ return p
+end
+
+if environment.initex then
+
+ local function names(t)
+ local nt = #t
+ if nt > 0 then
+ local n = { }
+ for i=1,nt do
+ n[i] = t[i].name
+ end
+ return concat(n," ")
+ else
+ return "-"
+ end
+ end
+
+ statistics.register("font processing", function()
+ local l = { }
+ for what, handler in table.sortedpairs(handlers) do
+ local features = handler.features
+ if features then
+ l[#l+1] = format("[%s (base initializers: %s) (base processors: %s) (base manipulators: %s) (node initializers: %s) (node processors: %s) (node manipulators: %s)]",
+ what,
+ names(features.initializers.base),
+ names(features.processors .base),
+ names(features.manipulators.base),
+ names(features.initializers.node),
+ names(features.processors .node),
+ names(features.manipulators.node)
+ )
+ end
+ end
+ return concat(l, " | ")
+ end)
+
+end
+
+-- redefinition
+
+-- local hashes = fonts.hashes
+-- local emwidths = hashes.emwidths
+-- local exheights = hashes.exheights
+
+setmetatableindex(dimenfactors, function(t,k)
+ if k == "ex" then
+ return 1/exheights[currentfont()]
+ elseif k == "em" then
+ return 1/emwidths[currentfont()]
+ elseif k == "pct" or k == "%" then
+ return 1/(texget("hsize")/100)
+ else
+ -- error("wrong dimension: " .. (s or "?")) -- better a message
+ return false
+ end
+end)
+
+dimenfactors.ex = nil
+dimenfactors.em = nil
+dimenfactors["%"] = nil
+dimenfactors.pct = nil
+
+--[[ldx--
+<p>Before a font is passed to <l n='tex'/> we scale it. Here we also need
+to scale virtual characters.</p>
+--ldx]]--
+
+-- in versions > 0.82 0 is supported as equivalent of self
+
+function constructors.checkvirtualids(tfmdata)
+ -- begin of experiment: we can use { "slot", 0, number } in virtual fonts
+ local fonts = tfmdata.fonts
+ local selfid = font.nextid()
+ if fonts and #fonts > 0 then
+ for i=1,#fonts do
+ local fi = fonts[i]
+ if fi[2] == 0 then
+ fi[2] = selfid
+ elseif fi.id == 0 then
+ fi.id = selfid
+ end
+ end
+ else
+ -- tfmdata.fonts = { "id", selfid } -- conflicts with other next id's (vf math), too late anyway
+ end
+ -- end of experiment
+end
+
+-- function constructors.getvirtualid(tfmdata)
+-- -- since we don't know the id yet, we use 0 as signal
+-- local tf = tfmdata.fonts
+-- if not tf then
+-- local properties = tfmdata.properties
+-- if properties then
+-- properties.virtualized = true
+-- else
+-- tfmdata.properties = { virtualized = true }
+-- end
+-- tf = { }
+-- tfmdata.fonts = tf
+-- end
+-- local ntf = #tf + 1
+-- tf[ntf] = { id = 0 }
+-- return ntf
+-- end
+--
+-- function constructors.checkvirtualid(tfmdata, id) -- will go
+-- local properties = tfmdata.properties
+-- if tfmdata and tfmdata.type == "virtual" or (properties and properties.virtualized) then
+-- local vfonts = tfmdata.fonts
+-- if not vffonts or #vfonts == 0 then
+-- if properties then
+-- properties.virtualized = false
+-- end
+-- tfmdata.fonts = nil
+-- else
+-- for f=1,#vfonts do
+-- local fnt = vfonts[f]
+-- if fnt.id and fnt.id == 0 then
+-- fnt.id = id
+-- end
+-- end
+-- end
+-- end
+-- end
+
+do
+
+ -- local scanners = tokens.scanners
+ -- local scanstring = scanners.string
+ -- local scaninteger = scanners.integer
+ -- local scandimen = scanners.dimen
+ -- local scanboolean = scanners.boolean
+
+ -- local scanners = interfaces.scanners
+
+ local setmacro = tokens.setters.macro
+
+ function constructors.currentfonthasfeature(n)
+ local f = fontdata[currentfont()]
+ if not f then return end f = f.shared
+ if not f then return end f = f.rawdata
+ if not f then return end f = f.resources
+ if not f then return end f = f.features
+ return f and (f.gpos[n] or f.gsub[n])
+ end
+
+ implement {
+ name = "doifelsecurrentfonthasfeature",
+ actions = { constructors.currentfonthasfeature, commands.doifelse },
+ arguments = "string"
+ }
+
+ -- local p, f = 1, formatters["%0.1fpt"] -- normally this value is changed only once
+ --
+ -- local stripper = lpeg.patterns.stripzeros
+ --
+ -- function commands.nbfs(amount,precision)
+ -- if precision ~= p then
+ -- p = precision
+ -- f = formatters["%0." .. p .. "fpt"]
+ -- end
+ -- context(lpegmatch(stripper,f(amount/65536)))
+ -- end
+
+ local f_strip = formatters["%0.2fpt"] -- normally this value is changed only once
+ local stripper = lpeg.patterns.stripzeros
+
+ -- scanners.nbfs = function()
+ -- context(lpegmatch(stripper,f_strip(scandimen()/65536)))
+ -- end
+
+ implement {
+ name = "nbfs",
+ arguments = "dimen",
+ actions = function(d)
+ context(lpegmatch(stripper,f_strip(d/65536)))
+ end
+ }
+
+ -- commands.featureattribute = function(tag) context(contextnumber(tag)) end
+ -- commands.setfontfeature = function(tag) texsetattribute(0,contextnumber(tag)) end
+ -- commands.resetfontfeature = function() texsetattribute(0,0) end
+ -- commands.setfontofid = function(id) context_getvalue(csnames[id]) end
+ -- commands.definefontfeature = presetcontext
+
+ -- scanners.featureattribute = function() context(contextnumber(scanstring())) end
+ -- scanners.setfontfeature = function() texsetattribute(0,contextnumber(scanstring())) end
+ -- scanners.resetfontfeature = function() texsetattribute(0,0) end
+ -- scanners.setfontofid = function() context_getvalue(csnames[scaninteger()]) end
+ -- scanners.definefontfeature = function() presetcontext(scanstring(),scanstring(),scanstring()) end
+
+ implement {
+ name = "featureattribute",
+ arguments = "string",
+ actions = { contextnumber, context }
+ }
+
+ implement {
+ name = "setfontfeature",
+ arguments = "string",
+ actions = function(tag) texsetattribute(0,contextnumber(tag)) end
+ }
+
+ implement {
+ name = "resetfontfeature",
+ arguments = { 0, 0 },
+ actions = texsetattribute,
+ }
+
+ implement {
+ name = "setfontofid",
+ arguments = "integer",
+ actions = function(id)
+ context_getvalue(csnames[id])
+ end
+ }
+
+ implement {
+ name = "definefontfeature",
+ arguments = { "string", "string", "string" },
+ actions = presetcontext
+ }
+
+ local cache = { }
+
+ local hows = {
+ ["+"] = "add",
+ ["-"] = "subtract",
+ ["="] = "replace",
+ }
+
+ local function setfeature(how,parent,name,font) -- 0/1 test temporary for testing
+ if not how or how == 0 then
+ if trace_features and texgetattribute(0) ~= 0 then
+ report_cummulative("font %!font:name!, reset",fontdata[font or true])
+ end
+ texsetattribute(0,0)
+ elseif how == true or how == 1 then
+ local hash = "feature > " .. parent
+ local done = cache[hash]
+ if trace_features and done then
+ report_cummulative("font %!font:name!, revive %a : %!font:features!",fontdata[font or true],parent,setups[numbers[done]])
+ end
+ texsetattribute(0,done or 0)
+ else
+ local full = parent .. how .. name
+ local hash = "feature > " .. full
+ local done = cache[hash]
+ if not done then
+ local n = setups[full]
+ if n then
+ -- already defined
+ else
+ n = mergecontextfeatures(parent,name,how,full)
+ end
+ done = registercontextfeature(hash,full,how)
+ cache[hash] = done
+ if trace_features then
+ report_cummulative("font %!font:name!, %s %a : %!font:features!",fontdata[font or true],hows[how],full,setups[numbers[done]])
+ end
+ end
+ texsetattribute(0,done)
+ end
+ end
+
+ local function resetfeature()
+ if trace_features and texgetattribute(0) ~= 0 then
+ report_cummulative("font %!font:name!, reset",fontdata[true])
+ end
+ texsetattribute(0,0)
+ end
+
+ local function registerlanguagefeatures()
+ local specifications = languages.data.specifications
+ for i=1,#specifications do
+ local specification = specifications[i]
+ local language = specification.opentype
+ if language then
+ local script = specification.opentypescript or specification.script
+ if script then
+ local context = specification.context
+ if type(context) == "table" then
+ for i=1,#context do
+ definecontext(context[i], { language = language, script = script})
+ end
+ elseif type(context) == "string" then
+ definecontext(context, { language = language, script = script})
+ end
+ end
+ end
+ end
+ end
+
+ implement { name = "resetfeature", actions = resetfeature }
+ implement { name = "addfeature", actions = setfeature, arguments = { "'+'", "string", "string" } }
+ implement { name = "subtractfeature", actions = setfeature, arguments = { "'-'", "string", "string" } }
+ implement { name = "replacefeature", actions = setfeature, arguments = { "'='", "string", "string" } }
+ implement { name = "revivefeature", actions = setfeature, arguments = { true, "string" } }
+
+ implement {
+ name = "featurelist",
+ actions = { fonts.specifiers.contexttostring, context },
+ arguments = { "string", "'otf'", "string", "'yes'", "'no'", true }
+ }
+
+ implement {
+ name = "registerlanguagefeatures",
+ actions = registerlanguagefeatures,
+ }
+
+end
+
+-- a fontkern plug:
+
+do
+
+ local kerncodes = nodes.kerncodes
+ local copy_node = nuts.copy
+ local kern = nuts.pool.register(nuts.pool.kern())
+
+ setattr(kern,attributes.private('fontkern'),1)
+
+ nodes.injections.installnewkern(function(k)
+ local c = copy_node(kern)
+ setfield(c,"kern",k)
+ return c
+ end)
+
+ directives.register("fonts.injections.fontkern", function(v)
+ setsubtype(kern,v and kerncodes.fontkern or kerncodes.userkern)
+ end)
+
+end
+
+do
+
+ local report = logs.reporter("otf","variants")
+
+ local function replace(tfmdata,feature,value)
+ local characters = tfmdata.characters
+ local variants = tfmdata.resources.variants
+ if variants then
+ local t = { }
+ for k, v in sortedhash(variants) do
+ t[#t+1] = formatters["0x%X (%i)"](k,k)
+ end
+ value = tonumber(value) or 0xFE00 -- 917762
+ report("fontname : %s",tfmdata.properties.fontname)
+ report("available: % t",t)
+ local v = variants[value]
+ if v then
+ report("using : %X (%i)",value,value)
+ for k, v in next, v do
+ local c = characters[v]
+ if c then
+ characters[k] = c
+ end
+ end
+ else
+ report("unknown : %X (%i)",value,value)
+ end
+ end
+ end
+
+ registerotffeature {
+ name = 'variant',
+ description = 'unicode variant',
+ manipulators = {
+ base = replace,
+ node = replace,
+ }
+ }
+
+end
+
+-- here (todo: closure)
+
+-- make a closure (200 limit):
+
+local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+
+local analyzers = fonts.analyzers
+local methods = analyzers.methods
+
+local unsetvalue = attributes.unsetvalue
+
+local traverse_id = nuts.traverse_id
+
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local a_state = attributes.private('state')
+local m_color = attributes.list[a_color] or { }
+
+local glyph_code = nodes.nodecodes.glyph
+
+local states = analyzers.states
+
+local colornames = {
+ [states.init] = "font:1",
+ [states.medi] = "font:2",
+ [states.fina] = "font:3",
+ [states.isol] = "font:4",
+ [states.mark] = "font:5",
+ [states.rest] = "font:6",
+ [states.rphf] = "font:1",
+ [states.half] = "font:2",
+ [states.pref] = "font:3",
+ [states.blwf] = "font:4",
+ [states.pstf] = "font:5",
+}
+
+local function markstates(head)
+ if head then
+ head = tonut(head)
+ local model = getattr(head,a_colormodel) or 1
+ for glyph in traverse_id(glyph_code,head) do
+ local a = getprop(glyph,a_state)
+ if a then
+ local name = colornames[a]
+ if name then
+ local color = m_color[name]
+ if color then
+ setattr(glyph,a_colormodel,model)
+ setattr(glyph,a_color,color)
+ end
+ end
+ end
+ end
+ end
+end
+
+local function analyzeprocessor(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
+ local action = methods[script]
+ if not action then
+ return head, false
+ end
+ if type(action) == "function" then
+ local head, done = action(head,font,attr)
+ if done and trace_analyzing then
+ markstates(head)
+ end
+ return head, done
+ end
+ action = action[language]
+ if action then
+ local head, done = action(head,font,attr)
+ if done and trace_analyzing then
+ markstates(head)
+ end
+ return head, done
+ else
+ return head, false
+ end
+end
+
+registerotffeature { -- adapts
+ name = "analyze",
+ processors = {
+ node = analyzeprocessor,
+ }
+}
+
+function methods.nocolor(head,font,attr)
+ for n in traverse_id(glyph_code,head) do
+ if not font or getfont(n) == font then
+ setattr(n,a_color,unsetvalue)
+ end
+ end
+ return head, true
+end
+
+local function purefontname(name)
+ if type(name) == "number" then
+ name = getfontname(name)
+ end
+ if type(name) == "string" then
+ return basename(name)
+ end
+end
+
+implement {
+ name = "purefontname",
+ actions = { purefontname, context },
+ arguments = "string",
+}
+
+local list = storage.shared.bodyfontsizes or { }
+storage.shared.bodyfontsizes = list
+
+implement {
+ name = "registerbodyfontsize",
+ arguments = "string",
+ actions = function(size)
+ list[size] = true
+ end
+}
+
+implement {
+ name = "getbodyfontsizes",
+ arguments = "string",
+ actions = function(separator)
+ context(concat(sortedkeys(list),separator))
+ end
+}
+
+implement {
+ name = "processbodyfontsizes",
+ arguments = "string",
+ actions = function(command)
+ local keys = sortedkeys(list)
+ if command then
+ local action = context[command]
+ for i=1,#keys do
+ action(keys[i])
+ end
+ else
+ context(concat(keys,","))
+ end
+ end
+}
+
+implement {
+ name = "cleanfontname",
+ actions = { names.cleanname, context },
+ arguments = "string"
+}
+
+implement {
+ name = "fontlookupinitialize",
+ actions = names.lookup,
+ arguments = "string",
+}
+
+implement {
+ name = "fontlookupnoffound",
+ actions = { names.noflookups, context },
+}
+
+implement {
+ name = "fontlookupgetkeyofindex",
+ actions = { names.getlookupkey, context },
+ arguments = { "string", "integer"}
+}
+
+implement {
+ name = "fontlookupgetkey",
+ actions = { names.getlookupkey, context },
+ arguments = "string"
+}
+
+-- this might move to a runtime module:
+
+function commands.showchardata(n)
+ local tfmdata = fontdata[currentfont()]
+ if tfmdata then
+ if type(n) == "string" then
+ n = utfbyte(n)
+ end
+ local chr = tfmdata.characters[n]
+ if chr then
+ report_status("%s @ %s => %U => %c => %s",tfmdata.properties.fullname,tfmdata.parameters.size,n,n,serialize(chr,false))
+ end
+ end
+end
+
+function commands.showfontparameters(tfmdata)
+ -- this will become more clever
+ local tfmdata = tfmdata or fontdata[currentfont()]
+ if tfmdata then
+ local parameters = tfmdata.parameters
+ local mathparameters = tfmdata.mathparameters
+ local properties = tfmdata.properties
+ local hasparameters = parameters and next(parameters)
+ local hasmathparameters = mathparameters and next(mathparameters)
+ if hasparameters then
+ report_status("%s @ %s => text parameters => %s",properties.fullname,parameters.size,serialize(parameters,false))
+ end
+ if hasmathparameters then
+ report_status("%s @ %s => math parameters => %s",properties.fullname,parameters.size,serialize(mathparameters,false))
+ end
+ if not hasparameters and not hasmathparameters then
+ report_status("%s @ %s => no text parameters and/or math parameters",properties.fullname,parameters.size)
+ end
+ end
+end
+
+implement {
+ name = "currentdesignsize",
+ actions = function()
+ context(parameters[currentfont()].designsize)
+ end
+}
+
+implement {
+ name = "doifelsefontpresent",
+ actions = { names.exists, commands.doifelse },
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-def.lua b/Master/texmf-dist/tex/context/base/mkiv/font-def.lua
new file mode 100644
index 00000000000..add42ee3828
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-def.lua
@@ -0,0 +1,454 @@
+if not modules then modules = { } end modules ['font-def'] = {
+ 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"
+}
+
+-- We can overload some of the definers.functions so we don't local them.
+
+local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
+local tostring, next = tostring, next
+local lpegmatch = lpeg.match
+local suffixonly, removesuffix = file.suffix, file.removesuffix
+
+local allocate = utilities.storage.allocate
+
+local trace_defining = false trackers .register("fonts.defining", function(v) trace_defining = v end)
+local directive_embedall = false directives.register("fonts.embedall", function(v) directive_embedall = v end)
+
+trackers.register("fonts.loading", "fonts.defining", "otf.loading", "afm.loading", "tfm.loading")
+trackers.register("fonts.all", "fonts.*", "otf.*", "afm.*", "tfm.*")
+
+local report_defining = logs.reporter("fonts","defining")
+
+--[[ldx--
+<p>Here we deal with defining fonts. We do so by intercepting the
+default loader that only handles <l n='tfm'/>.</p>
+--ldx]]--
+
+local fonts = fonts
+local fontdata = fonts.hashes.identifiers
+local readers = fonts.readers
+local definers = fonts.definers
+local specifiers = fonts.specifiers
+local constructors = fonts.constructors
+local fontgoodies = fonts.goodies
+
+readers.sequence = allocate { 'otf', 'ttf', 'afm', 'tfm', 'lua' } -- dfont ttc
+
+local variants = allocate()
+specifiers.variants = variants
+
+definers.methods = definers.methods or { }
+
+local internalized = allocate() -- internal tex numbers (private)
+local lastdefined = nil -- we don't want this one to end up in s-tra-02
+
+local loadedfonts = constructors.loadedfonts
+local designsizes = constructors.designsizes
+
+-- not in generic (some day I'll make two defs, one for context, one for generic)
+
+local resolvefile = fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end
+
+--[[ldx--
+<p>We hardly gain anything when we cache the final (pre scaled)
+<l n='tfm'/> table. But it can be handy for debugging, so we no
+longer carry this code along. Also, we now have quite some reference
+to other tables so we would end up with lots of catches.</p>
+--ldx]]--
+
+--[[ldx--
+<p>We can prefix a font specification by <type>name:</type> or
+<type>file:</type>. The first case will result in a lookup in the
+synonym table.</p>
+
+<typing>
+[ name: | file: ] identifier [ separator [ specification ] ]
+</typing>
+
+<p>The following function split the font specification into components
+and prepares a table that will move along as we proceed.</p>
+--ldx]]--
+
+-- beware, we discard additional specs
+--
+-- method:name method:name(sub) method:name(sub)*spec method:name*spec
+-- 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
+ lookup = definers.defaultlookup
+ end
+ if trace_defining then
+ report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a",
+ specification, lookup, name, sub, method, detail)
+ end
+ local t = {
+ lookup = lookup, -- forced type
+ specification = specification, -- full specification
+ size = size, -- size in scaled points or -1000*n
+ name = name, -- font or filename
+ sub = sub, -- subfont (eg in ttc)
+ method = method, -- specification method
+ detail = detail, -- specification
+ resolved = "", -- resolved font name
+ forced = "", -- forced loader
+ features = { }, -- preprocessed features
+ }
+ 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)
+end
+
+--[[ldx--
+<p>We can resolve the filename using the next function:</p>
+--ldx]]--
+
+definers.resolvers = definers.resolvers or { }
+local resolvers = definers.resolvers
+
+-- todo: reporter
+
+function resolvers.file(specification)
+ local name = resolvefile(specification.name) -- catch for renames
+ local suffix = lower(suffixonly(name))
+ if fonts.formats[suffix] then
+ specification.forced = suffix
+ specification.forcedname = name
+ specification.name = removesuffix(name)
+ else
+ specification.name = name -- can be resolved
+ end
+end
+
+function resolvers.name(specification)
+ local resolve = fonts.names.resolve
+ if resolve then
+ local resolved, sub, subindex = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
+ specification.subindex = subindex
+ local suffix = lower(suffixonly(resolved))
+ if fonts.formats[suffix] then
+ specification.forced = suffix
+ specification.forcedname = resolved
+ specification.name = removesuffix(resolved)
+ else
+ specification.name = resolved
+ end
+ end
+ else
+ resolvers.file(specification)
+ end
+end
+
+function resolvers.spec(specification)
+ local resolvespec = fonts.names.resolvespec
+ if resolvespec then
+ local resolved, sub, subindex = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
+ specification.subindex = subindex
+ specification.forced = lower(suffixonly(resolved))
+ specification.forcedname = resolved
+ specification.name = removesuffix(resolved)
+ end
+ else
+ resolvers.name(specification)
+ end
+end
+
+function definers.resolve(specification)
+ if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash
+ local r = resolvers[specification.lookup]
+ if r then
+ r(specification)
+ end
+ end
+ if specification.forced == "" then
+ specification.forced = nil
+ specification.forcedname = nil
+ end
+ specification.hash = lower(specification.name .. ' @ ' .. constructors.hashfeatures(specification))
+ if specification.sub and specification.sub ~= "" then
+ specification.hash = specification.sub .. ' @ ' .. specification.hash
+ end
+ return specification
+end
+
+--[[ldx--
+<p>The main read function either uses a forced reader (as determined by
+a lookup) or tries to resolve the name using the list of readers.</p>
+
+<p>We need to cache when possible. We do cache raw tfm data (from <l
+n='tfm'/>, <l n='afm'/> or <l n='otf'/>). After that we can cache based
+on specificstion (name) and size, that is, <l n='tex'/> only needs a number
+for an already loaded fonts. However, it may make sense to cache fonts
+before they're scaled as well (store <l n='tfm'/>'s with applied methods
+and features). However, there may be a relation between the size and
+features (esp in virtual fonts) so let's not do that now.</p>
+
+<p>Watch out, here we do load a font, but we don't prepare the
+specification yet.</p>
+--ldx]]--
+
+-- very experimental:
+
+function definers.applypostprocessors(tfmdata)
+ local postprocessors = tfmdata.postprocessors
+ if postprocessors then
+ local properties = tfmdata.properties
+ for i=1,#postprocessors do
+ local extrahash = postprocessors[i](tfmdata) -- after scaling etc
+ if type(extrahash) == "string" and extrahash ~= "" then
+ -- e.g. a reencoding needs this
+ extrahash = gsub(lower(extrahash),"[^a-z]","-")
+ properties.fullname = format("%s-%s",properties.fullname,extrahash)
+ end
+ end
+ end
+ return tfmdata
+end
+
+-- function definers.applypostprocessors(tfmdata)
+-- return tfmdata
+-- end
+
+local function checkembedding(tfmdata)
+ local properties = tfmdata.properties
+ local embedding
+ if directive_embedall then
+ embedding = "full"
+ elseif properties and properties.filename and constructors.dontembed[properties.filename] then
+ embedding = "no"
+ else
+ embedding = "subset"
+ end
+ if properties then
+ properties.embedding = embedding
+ else
+ tfmdata.properties = { embedding = embedding }
+ end
+ tfmdata.embedding = embedding
+end
+
+function definers.loadfont(specification)
+ local hash = constructors.hashinstance(specification)
+ local tfmdata = loadedfonts[hash] -- hashes by size !
+ if not tfmdata then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ local reader = readers[lower(forced)] -- normally forced is already lowered
+ tfmdata = reader and reader(specification)
+ if not tfmdata then
+ report_defining("forced type %a of %a not found",forced,specification.name)
+ end
+ else
+ local sequence = readers.sequence -- can be overloaded so only a shortcut here
+ for s=1,#sequence do
+ local reader = sequence[s]
+ if readers[reader] then -- we skip not loaded readers
+ if trace_defining then
+ report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename)
+ end
+ tfmdata = readers[reader](specification)
+ if tfmdata then
+ break
+ else
+ specification.filename = nil
+ end
+ end
+ end
+ end
+ if tfmdata then
+ tfmdata = definers.applypostprocessors(tfmdata)
+ checkembedding(tfmdata) -- todo: general postprocessor
+ loadedfonts[hash] = tfmdata
+ designsizes[specification.hash] = tfmdata.parameters.designsize
+ end
+ end
+ if not tfmdata then
+ report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup)
+ end
+ return tfmdata
+end
+
+function constructors.checkvirtualids()
+ -- dummy in plain version
+end
+
+function constructors.readanddefine(name,size) -- no id -- maybe a dummy first
+ local specification = definers.analyze(name,size)
+ local method = specification.method
+ if method and variants[method] then
+ specification = variants[method](specification)
+ end
+ specification = definers.resolve(specification)
+ local hash = constructors.hashinstance(specification)
+ local id = definers.registered(hash)
+ if not id then
+ local tfmdata = definers.loadfont(specification)
+ if tfmdata then
+ tfmdata.properties.hash = hash
+ constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
+ id = font.define(tfmdata)
+ definers.register(tfmdata,id)
+ else
+ id = 0 -- signal
+ end
+ end
+ return fontdata[id], id
+end
+
+--[[ldx--
+<p>So far the specifiers. Now comes the real definer. Here we cache
+based on id's. Here we also intercept the virtual font handler. Since
+it evolved stepwise I may rewrite this bit (combine code).</p>
+
+In the previously defined reader (the one resulting in a <l n='tfm'/>
+table) we cached the (scaled) instances. Here we cache them again, but
+this time based on id. We could combine this in one cache but this does
+not gain much. By the way, passing id's back to in the callback was
+introduced later in the development.</p>
+--ldx]]--
+
+function definers.current() -- or maybe current
+ return lastdefined
+end
+
+function definers.registered(hash)
+ local id = internalized[hash]
+ return id, id and fontdata[id]
+end
+
+function definers.register(tfmdata,id)
+ if tfmdata and id then
+ local hash = tfmdata.properties.hash
+ if not hash then
+ report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?")
+ elseif not internalized[hash] then
+ internalized[hash] = id
+ if trace_defining then
+ report_defining("registering font, id %s, hash %a",id,hash)
+ end
+ fontdata[id] = tfmdata
+ end
+ end
+end
+
+function definers.read(specification,size,id) -- id can be optional, name can already be table
+ statistics.starttiming(fonts)
+ if type(specification) == "string" then
+ specification = definers.analyze(specification,size)
+ end
+ local method = specification.method
+ if method and variants[method] then
+ specification = variants[method](specification)
+ end
+ specification = definers.resolve(specification)
+ local hash = constructors.hashinstance(specification)
+ local tfmdata = definers.registered(hash) -- id
+ if tfmdata then
+ if trace_defining then
+ report_defining("already hashed: %s",hash)
+ end
+ else
+ tfmdata = definers.loadfont(specification) -- can be overloaded
+ if tfmdata then
+ if trace_defining then
+ report_defining("loaded and hashed: %s",hash)
+ end
+ tfmdata.properties.hash = hash
+ if id then
+ definers.register(tfmdata,id)
+ end
+ else
+ if trace_defining then
+ report_defining("not loaded and hashed: %s",hash)
+ end
+ end
+ end
+ lastdefined = tfmdata or id -- todo ! ! ! ! !
+ if not tfmdata then -- or id?
+ report_defining( "unknown font %a, loading aborted",specification.name)
+ elseif trace_defining and type(tfmdata) == "table" then
+ local properties = tfmdata.properties or { }
+ local parameters = tfmdata.parameters or { }
+ report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
+ properties.format or "unknown", id, properties.name, parameters.size, properties.encodingbytes,
+ properties.encodingname, properties.fullname, file.basename(properties.filename))
+ end
+ statistics.stoptiming(fonts)
+ return tfmdata
+end
+
+function font.getfont(id)
+ return fontdata[id] -- otherwise issues
+end
+
+--[[ldx--
+<p>We overload the <l n='tfm'/> reader.</p>
+--ldx]]--
+
+callbacks.register('define_font', definers.read, "definition of fonts (tfmdata preparation)")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua b/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua
new file mode 100644
index 00000000000..14e816d5e4d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua
@@ -0,0 +1,2200 @@
+if not modules then modules = { } end modules ['font-dsp'] = {
+ 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"
+}
+
+-- many 0,0 entry/exit
+
+-- This loader went through a few iterations. First I made a ff compatible one so
+-- that we could do some basic checking. Also some verbosity was added (named
+-- glyphs). Eventually all that was dropped for a context friendly format, simply
+-- because keeping the different table models in sync too to much time. I have the
+-- old file somewhere. A positive side effect is that we get an (upto) much smaller
+-- smaller tma/tmc file. In the end the loader will be not much slower than the
+-- c based ff one.
+
+-- Being binary encoded, an opentype is rather compact. When expanded into a Lua table
+-- quite some memory can be used. This is very noticeable in the ff loader, which for
+-- a good reason uses a verbose format. However, when we use that data we create a couple
+-- of hashes. In the Lua loader we create these hashes directly, which save quite some
+-- memory.
+--
+-- We convert a font file only once and then cache it. Before creating the cached instance
+-- packing takes place: common tables get shared. After (re)loading and unpacking we then
+-- get a rather efficient internal representation of the font. In the new loader there is a
+-- pitfall. Because we use some common coverage magic we put a bit more information in
+-- the mark and cursive coverage tables than strickly needed: a reference to the coverage
+-- itself. This permits a fast lookup of the second glyph involved. In the marks we
+-- expand the class indicator to a class hash, in the cursive we use a placeholder that gets
+-- a self reference. This means that we cannot pack these subtables unless we add a unique
+-- id per entry (the same one per coverage) and that makes the tables larger. Because only a
+-- few fonts benefit from this, I decided to not do this. Experiments demonstrated that it
+-- only gives a few percent gain (on for instance husayni we can go from 845K to 828K
+-- bytecode). Better stay conceptually clean than messy compact.
+
+-- When we can reduce all basic lookups to one step we might safe a bit in the processing
+-- so then only chains are multiple.
+
+-- I used to flatten kerns here but that has been moved elsewhere because it polutes the code
+-- here and can be done fast afterwards. One can even wonder if it makes sense to do it as we
+-- pack anyway. In a similar fashion the unique placeholders in anchors in marks have been
+-- removed because packing doesn't save much there anyway.
+
+-- Although we have a bit more efficient tables in the cached files, the internals are still
+-- pretty similar. And although we have a slightly more direct coverage access the processing
+-- of node lists is not noticeable faster for latin texts, but for arabic we gain some 10%
+-- (and could probably gain a bit more).
+
+local next, type = next, type
+local bittest = bit32.btest
+local rshift = bit32.rshift
+local concat = table.concat
+local lower = string.lower
+local sub = string.sub
+local strip = string.strip
+local tohash = table.tohash
+local reversed = table.reversed
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local sortedkeys = table.sortedkeys
+local sortedhash = table.sortedhash
+
+local report = logs.reporter("otf reader")
+
+local readers = fonts.handlers.otf.readers
+local streamreader = readers.streamreader
+
+local setposition = streamreader.setposition
+local skipbytes = streamreader.skip
+local skipshort = streamreader.skipshort
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local readshort = streamreader.readinteger2 -- 16-bit signed integer
+local readfword = readshort
+local readstring = streamreader.readstring
+local readtag = streamreader.readtag
+
+local gsubhandlers = { }
+local gposhandlers = { }
+
+local lookupidoffset = -1 -- will become 1 when we migrate (only -1 for comparign with old)
+
+local classes = {
+ "base",
+ "ligature",
+ "mark",
+ "component",
+}
+
+local gsubtypes = {
+ "single",
+ "multiple",
+ "alternate",
+ "ligature",
+ "context",
+ "chainedcontext",
+ "extension",
+ "reversechainedcontextsingle",
+}
+
+local gpostypes = {
+ "single",
+ "pair",
+ "cursive",
+ "marktobase",
+ "marktoligature",
+ "marktomark",
+ "context",
+ "chainedcontext",
+ "extension",
+}
+
+local chaindirections = {
+ context = 0,
+ chainedcontext = 1,
+ reversechainedcontextsingle = -1,
+}
+
+-- 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.
+
+-- chainsub
+-- reversesub
+
+local lookupnames = {
+ gsub = {
+ single = "gsub_single",
+ multiple = "gsub_multiple",
+ alternate = "gsub_alternate",
+ ligature = "gsub_ligature",
+ context = "gsub_context",
+ chainedcontext = "gsub_contextchain",
+ reversechainedcontextsingle = "gsub_reversecontextchain", -- reversesub
+ },
+ gpos = {
+ single = "gpos_single",
+ pair = "gpos_pair",
+ cursive = "gpos_cursive",
+ marktobase = "gpos_mark2base",
+ marktoligature = "gpos_mark2ligature",
+ marktomark = "gpos_mark2mark",
+ context = "gpos_context",
+ chainedcontext = "gpos_contextchain",
+ }
+}
+
+-- keep this as reference:
+--
+-- local lookupbits = {
+-- [0x0001] = "righttoleft",
+-- [0x0002] = "ignorebaseglyphs",
+-- [0x0004] = "ignoreligatures",
+-- [0x0008] = "ignoremarks",
+-- [0x0010] = "usemarkfilteringset",
+-- [0x00E0] = "reserved",
+-- [0xFF00] = "markattachmenttype",
+-- }
+--
+-- local lookupstate = setmetatableindex(function(t,k)
+-- local v = { }
+-- for kk, vv in next, lookupbits do
+-- if bittest(k,kk) then
+-- v[vv] = true
+-- end
+-- end
+-- t[k] = v
+-- return v
+-- end)
+
+local lookupflags = setmetatableindex(function(t,k)
+ local v = {
+ bittest(k,0x0008) and true or false, -- ignoremarks
+ bittest(k,0x0004) and true or false, -- ignoreligatures
+ bittest(k,0x0002) and true or false, -- ignorebaseglyphs
+ bittest(k,0x0001) and true or false, -- r2l
+ }
+ t[k] = v
+ return v
+end)
+
+-- Beware: only use the simple variant if we don't set keys/values (otherwise too many entries). We
+-- could also have a variant that applies a function but there is no real benefit in this.
+
+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)
+ end
+ else
+ for i=0,nofcoverage-1 do
+ coverage[readushort(f)] = i -- index in record
+ end
+ end
+ elseif coverageformat == 2 then
+ local nofranges = readushort(f)
+ local n = simple and 1 or 0 -- needs checking
+ for i=1,nofranges do
+ local firstindex = readushort(f)
+ local lastindex = readushort(f)
+ local coverindex = readushort(f)
+ if simple then
+ for i=firstindex,lastindex do
+ coverage[n] = i
+ n = n + 1
+ end
+ else
+ for i=firstindex,lastindex do
+ coverage[i] = n
+ n = n + 1
+ end
+ end
+ end
+ else
+ report("unknown coverage format %a ",coverageformat)
+ end
+ return coverage
+end
+
+local function readclassdef(f,offset)
+ setposition(f,offset)
+ local classdefformat = readushort(f)
+ local classdef = { }
+ if classdefformat == 1 then
+ local index = readushort(f)
+ local nofclassdef = readushort(f)
+ for i=1,nofclassdef do
+ classdef[index] = readushort(f) + 1
+ index = index + 1
+ end
+ elseif classdefformat == 2 then
+ local nofranges = readushort(f)
+ local n = 0
+ for i=1,nofranges do
+ local firstindex = readushort(f)
+ local lastindex = readushort(f)
+ local class = readushort(f) + 1
+ for i=firstindex,lastindex do
+ classdef[i] = class
+ end
+ end
+ else
+ report("unknown classdef format %a ",classdefformat)
+ end
+ return classdef
+end
+
+local function classtocoverage(defs)
+ if defs then
+ local list = { }
+ for index, class in next, defs do
+ local c = list[class]
+ if c then
+ c[#c+1] = index
+ else
+ list[class] = { index }
+ end
+ end
+ return list
+ end
+end
+
+-- extra readers
+
+local function readposition(f,format)
+ if format == 0 then
+ return nil
+ end
+ -- maybe fast test on 0x0001 + 0x0002 + 0x0004 + 0x0008 (profile first)
+ local x = bittest(format,0x0001) and readshort(f) or 0 -- placement
+ local y = bittest(format,0x0002) and readshort(f) or 0 -- placement
+ local h = bittest(format,0x0004) and readshort(f) or 0 -- advance
+ local v = bittest(format,0x0008) and readshort(f) or 0 -- advance
+ if x == 0 and y == 0 and h == 0 and v == 0 then
+ return nil
+ else
+ return { x, y, h, v }
+ end
+end
+
+local function readanchor(f,offset)
+ if not offset or offset == 0 then
+ return nil -- false
+ end
+ setposition(f,offset)
+ local format = readshort(f)
+ if format == 0 then
+ report("invalid anchor format %i @ position %i",format,offset)
+ return false
+ elseif format > 3 then
+ report("unsupported anchor format %i @ position %i",format,offset)
+ return false
+ end
+ return { readshort(f), readshort(f) }
+end
+
+-- common handlers: inlining can be faster but we cache anyway
+-- so we don't bother too much about speed here
+
+local function readfirst(f,offset)
+ if offset then
+ setposition(f,offset)
+ end
+ return { readushort(f) }
+end
+
+local function readarray(f,offset,first)
+ 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
+ elseif n > 0 then
+ local t = { }
+ for i=1,n do
+ t[i] = readushort(f)
+ end
+ return t, n
+ end
+end
+
+local function readcoveragearray(f,offset,t,simple)
+ if not t then
+ return nil
+ end
+ local n = #t
+ if n == 0 then
+ return nil
+ end
+ for i=1,n do
+ t[i] = readcoverage(f,offset+t[i],simple)
+ end
+ return t
+end
+
+local function covered(subset,all)
+ local used, u
+ for i=1,#subset do
+ local s = subset[i]
+ if all[s] then
+ if used then
+ u = u + 1
+ used[u] = s
+ else
+ u = 1
+ used = { s }
+ end
+ end
+ end
+ return used
+end
+
+-- We generalize the chained lookups so that we can do with only one handler
+-- when processing them.
+
+local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local subclasssets = readarray(f)
+ local rules = { }
+ if subclasssets then
+ coverage = readcoverage(f,tableoffset+coverage,true)
+ for i=1,#subclasssets do
+ local offset = subclasssets[i]
+ if offset > 0 then
+ local firstcoverage = coverage[i]
+ local rulesoffset = tableoffset + offset
+ local subclassrules = readarray(f,rulesoffset)
+ for rule=1,#subclassrules do
+ setposition(f,rulesoffset + subclassrules[rule])
+ local nofcurrent = readushort(f)
+ local noflookups = readushort(f)
+ local current = { { firstcoverage } }
+ for i=2,nofcurrent do
+ current[i] = { readushort(f) }
+ end
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ rules[#rules+1] = {
+ current = current,
+ lookups = lookups
+ }
+ end
+ end
+ end
+ else
+ report("empty subclassset in %a subtype %i","unchainedcontext",subtype)
+ end
+ return {
+ format = "glyphs",
+ rules = rules,
+ }
+ elseif subtype == 2 then
+ -- We expand the classes as later on we do a pack over the whole table so then we get
+ -- back efficiency. This way we can also apply the coverage to the first current.
+ local coverage = readushort(f)
+ local currentclassdef = readushort(f)
+ local subclasssets = readarray(f)
+ local rules = { }
+ if subclasssets then
+ coverage = readcoverage(f,tableoffset + coverage)
+ currentclassdef = readclassdef(f,tableoffset + currentclassdef)
+ local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs)
+ for class=1,#subclasssets do
+ local offset = subclasssets[class]
+ if offset > 0 then
+ local firstcoverage = currentclasses[class]
+ if firstcoverage then
+ firstcoverage = covered(firstcoverage,coverage) -- bonus
+ if firstcoverage then
+ local rulesoffset = tableoffset + offset
+ local subclassrules = readarray(f,rulesoffset)
+ for rule=1,#subclassrules do
+ setposition(f,rulesoffset + subclassrules[rule])
+ local nofcurrent = readushort(f)
+ local noflookups = readushort(f)
+ local current = { firstcoverage }
+ for i=2,nofcurrent do
+ current[i] = currentclasses[readushort(f) + 1]
+ end
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ rules[#rules+1] = {
+ current = current,
+ lookups = lookups
+ }
+ end
+ else
+ report("no coverage")
+ end
+ else
+ report("no coverage class")
+ end
+ end
+ end
+ else
+ report("empty subclassset in %a subtype %i","unchainedcontext",subtype)
+ end
+ return {
+ format = "class",
+ rules = rules,
+ }
+ elseif subtype == 3 then
+ local current = readarray(f)
+ local noflookups = readushort(f)
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ current = readcoveragearray(f,tableoffset,current,true)
+ return {
+ format = "coverage",
+ rules = {
+ {
+ current = current,
+ lookups = lookups,
+ }
+ }
+ }
+ else
+ report("unsupported subtype %a in %a %s",subtype,"unchainedcontext",what)
+ end
+end
+
+-- todo: optimize for n=1 ?
+
+-- class index needs checking, probably no need for +1
+
+local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local subclasssets = readarray(f)
+ local rules = { }
+ if subclasssets then
+ coverage = readcoverage(f,tableoffset+coverage,true)
+ for i=1,#subclasssets do
+ local offset = subclasssets[i]
+ if offset > 0 then
+ local firstcoverage = coverage[i]
+ local rulesoffset = tableoffset + offset
+ local subclassrules = readarray(f,rulesoffset)
+ for rule=1,#subclassrules do
+ setposition(f,rulesoffset + subclassrules[rule])
+ local nofbefore = readushort(f)
+ local before
+ if nofbefore > 0 then
+ before = { }
+ for i=1,nofbefore do
+ before[i] = { readushort(f) }
+ end
+ end
+ local nofcurrent = readushort(f)
+ local current = { { firstcoverage } }
+ for i=2,nofcurrent do
+ current[i] = { readushort(f) }
+ end
+ local nofafter = readushort(f)
+ local after
+ if nofafter > 0 then
+ after = { }
+ for i=1,nofafter do
+ after[i] = { readushort(f) }
+ end
+ end
+ local noflookups = readushort(f)
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ rules[#rules+1] = {
+ before = before,
+ current = current,
+ after = after,
+ lookups = lookups,
+ }
+ end
+ end
+ end
+ else
+ report("empty subclassset in %a subtype %i","chainedcontext",subtype)
+ end
+ return {
+ format = "glyphs",
+ rules = rules,
+ }
+ elseif subtype == 2 then
+ local coverage = readushort(f)
+ local beforeclassdef = readushort(f)
+ local currentclassdef = readushort(f)
+ local afterclassdef = readushort(f)
+ local subclasssets = readarray(f)
+ local rules = { }
+ if subclasssets then
+ local coverage = readcoverage(f,tableoffset + coverage)
+ local beforeclassdef = readclassdef(f,tableoffset + beforeclassdef)
+ local currentclassdef = readclassdef(f,tableoffset + currentclassdef)
+ local afterclassdef = readclassdef(f,tableoffset + afterclassdef)
+ local beforeclasses = classtocoverage(beforeclassdef,fontdata.glyphs)
+ local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs)
+ local afterclasses = classtocoverage(afterclassdef,fontdata.glyphs)
+ for class=1,#subclasssets do
+ local offset = subclasssets[class]
+ if offset > 0 then
+ local firstcoverage = currentclasses[class]
+ if firstcoverage then
+ firstcoverage = covered(firstcoverage,coverage) -- bonus
+ if firstcoverage then
+ local rulesoffset = tableoffset + offset
+ local subclassrules = readarray(f,rulesoffset)
+ for rule=1,#subclassrules do
+ -- watch out, in context we first get the counts and then the arrays while
+ -- here we get them mixed
+ setposition(f,rulesoffset + subclassrules[rule])
+ local nofbefore = readushort(f)
+ local before
+ if nofbefore > 0 then
+ before = { }
+ for i=1,nofbefore do
+ before[i] = beforeclasses[readushort(f) + 1]
+ end
+ end
+ local nofcurrent = readushort(f)
+ local current = { firstcoverage }
+ for i=2,nofcurrent do
+ current[i] = currentclasses[readushort(f)+ 1]
+ end
+ local nofafter = readushort(f)
+ local after
+ if nofafter > 0 then
+ after = { }
+ for i=1,nofafter do
+ after[i] = afterclasses[readushort(f) + 1]
+ end
+ end
+ -- no sequence index here (so why in context as it saves nothing)
+ local noflookups = readushort(f)
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ rules[#rules+1] = {
+ before = before,
+ current = current,
+ after = after,
+ lookups = lookups,
+ }
+ end
+ else
+ report("no coverage")
+ end
+ else
+ report("class is not covered")
+ end
+ end
+ end
+ else
+ report("empty subclassset in %a subtype %i","chainedcontext",subtype)
+ end
+ return {
+ format = "class",
+ rules = rules,
+ }
+ elseif subtype == 3 then
+ local before = readarray(f)
+ local current = readarray(f)
+ local after = readarray(f)
+ local noflookups = readushort(f)
+ local lookups = { }
+ for i=1,noflookups do
+ lookups[readushort(f)+1] = readushort(f) + 1
+ end
+ before = readcoveragearray(f,tableoffset,before,true)
+ current = readcoveragearray(f,tableoffset,current,true)
+ after = readcoveragearray(f,tableoffset,after,true)
+ return {
+ format = "coverage",
+ rules = {
+ {
+ before = before,
+ current = current,
+ after = after,
+ lookups = lookups,
+ }
+ }
+ }
+ else
+ report("unsupported subtype %a in %a %s",subtype,"chainedcontext",what)
+ end
+end
+
+local function extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,types,handlers,what)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local lookuptype = types[readushort(f)]
+ local faroffset = readulong(f)
+ local handler = handlers[lookuptype]
+ if handler then
+ -- maybe we can just pass one offset (or tableoffset first)
+ return handler(f,fontdata,lookupid,tableoffset + faroffset,0,glyphs,nofglyphs), lookuptype
+ else
+ report("no handler for lookuptype %a subtype %a in %s %s",lookuptype,subtype,what,"extension")
+ end
+ else
+ report("unsupported subtype %a in %s %s",subtype,what,"extension")
+ end
+end
+
+-- gsub handlers
+
+function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ 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
+ 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
+ else
+ coverage[index] = newindex
+ end
+ end
+ return {
+ coverage = coverage
+ }
+ 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 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
+ 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
+ else
+ coverage[index] = replacements[newindex]
+ end
+ end
+ return {
+ coverage = coverage
+ }
+ else
+ report("unsupported subtype %a in %a substitution",subtype,"single")
+ end
+end
+
+local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local nofsequence = readushort(f)
+ local sequences = { }
+ for i=1,nofsequence do
+ sequences[i] = readushort(f)
+ end
+ 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
+ end
+ local coverage = readcoverage(f,tableoffset + coverage)
+ for index, newindex in next, coverage do
+ newindex = newindex + 1
+ if index > nofglyphs or newindex > nofglyphs then
+ report("invalid index in %s format %i: %i -> %i (max %i)",what,subtype,index,newindex,nofglyphs)
+ coverage[index] = nil
+ else
+ coverage[index] = sequences[newindex]
+ end
+ end
+ return {
+ coverage = coverage
+ }
+ else
+ report("unsupported subtype %a in %a substitution",subtype,what)
+ end
+end
+
+function gsubhandlers.multiple(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"multiple")
+end
+
+function gsubhandlers.alternate(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"alternate")
+end
+
+function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local nofsets = readushort(f)
+ local ligatures = { }
+ for i=1,nofsets do
+ ligatures[i] = readushort(f)
+ end
+ 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)
+ end
+ ligatures[i] = l
+ end
+ local coverage = readcoverage(f,tableoffset + coverage)
+ for index, newindex in next, coverage do
+ local hash = { }
+ local ligatures = ligatures[newindex+1]
+ for i=1,#ligatures do
+ local offset = ligatures[i]
+ setposition(f,offset)
+ local lig = readushort(f)
+ local cnt = readushort(f)
+ local hsh = hash
+ for i=2,cnt do
+ local c = readushort(f)
+ local h = hsh[c]
+ if not h then
+ h = { }
+ hsh[c] = h
+ end
+ hsh = h
+ end
+ hsh.ligature = lig
+ end
+ coverage[index] = hash
+ end
+ return {
+ coverage = coverage
+ }
+ else
+ report("unsupported subtype %a in %a substitution",subtype,"ligature")
+ end
+end
+
+function gsubhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"), "context"
+end
+
+function gsubhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"), "chainedcontext"
+end
+
+function gsubhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gsubtypes,gsubhandlers,"substitution")
+end
+
+function gsubhandlers.reversechainedcontextsingle(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then -- NEEDS CHECKING
+ local current = readfirst(f)
+ local before = readarray(f)
+ local after = readarray(f)
+ local replacements = readarray(f)
+ current = readcoveragearray(f,tableoffset,current,true)
+ before = readcoveragearray(f,tableoffset,before,true)
+ after = readcoveragearray(f,tableoffset,after,true)
+ return {
+ coverage = {
+ format = "reversecoverage", -- reversesub
+ before = before,
+ current = current,
+ after = after,
+ replacements = replacements,
+ }
+ }, "reversechainedcontextsingle"
+ else
+ report("unsupported subtype %a in %a substitution",subtype,"reversechainedcontextsingle")
+ end
+end
+
+-- gpos handlers
+
+local function readpairsets(f,tableoffset,sets,format1,format2)
+ local done = { }
+ for i=1,#sets do
+ local offset = sets[i]
+ local reused = done[offset]
+ if not reused then
+ setposition(f,tableoffset + offset)
+ local n = readushort(f)
+ reused = { }
+ for i=1,n do
+ reused[i] = {
+ readushort(f), -- second glyph id
+ readposition(f,format1),
+ readposition(f,format2)
+ }
+ end
+ done[offset] = reused
+ end
+ sets[i] = reused
+ end
+ return sets
+end
+
+local function readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
+ local classlist1 = { }
+ for i=1,nofclasses1 do
+ local classlist2 = { }
+ classlist1[i] = classlist2
+ for j=1,nofclasses2 do
+ local one = readposition(f,format1)
+ local two = readposition(f,format2)
+ if one or two then
+ classlist2[j] = { one, two }
+ else
+ classlist2[j] = false
+ end
+ end
+ end
+ return classlist1
+end
+
+-- no real gain in kerns as we pack
+
+function gposhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local format = readushort(f)
+ local value = readposition(f,format)
+ local coverage = readcoverage(f,tableoffset+coverage)
+ for index, newindex in next, coverage do
+ coverage[index] = value
+ end
+ return {
+ format = "pair",
+ coverage = coverage
+ }
+ elseif subtype == 2 then
+ local coverage = readushort(f)
+ local format = readushort(f)
+ local values = { }
+ local nofvalues = readushort(f)
+ for i=1,nofvalues do
+ values[i] = readposition(f,format)
+ end
+ local coverage = readcoverage(f,tableoffset+coverage)
+ for index, newindex in next, coverage do
+ coverage[index] = values[newindex+1]
+ end
+ return {
+ format = "pair",
+ coverage = coverage
+ }
+ else
+ report("unsupported subtype %a in %a positioning",subtype,"single")
+ end
+end
+
+-- this needs checking! if no second pair then another advance over the list
+
+-- ValueFormat1 applies to the ValueRecord of the first glyph in each pair. ValueRecords for all first glyphs must use ValueFormat1. If ValueFormat1 is set to zero (0), the corresponding glyph has no ValueRecord and, therefore, should not be repositioned.
+-- ValueFormat2 applies to the ValueRecord of the second glyph in each pair. ValueRecords for all second glyphs must use ValueFormat2. If ValueFormat2 is set to null, then the second glyph of the pair is the “next” glyph for which a lookup should be performed.
+
+-- !!!!! this needs checking: when both false, we have no hit so then we might need to fall through
+
+function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = readushort(f)
+ local format1 = readushort(f)
+ local format2 = readushort(f)
+ local sets = readarray(f)
+ sets = readpairsets(f,tableoffset,sets,format1,format2)
+ coverage = readcoverage(f,tableoffset + coverage)
+ for index, newindex in next, coverage do
+ local set = sets[newindex+1]
+ local hash = { }
+ for i=1,#set do
+ local value = set[i]
+ if value then
+ local other = value[1]
+ local first = value[2]
+ local second = value[3]
+ if first or second then
+ hash[other] = { first, second } -- needs checking
+ else
+ hash[other] = nil
+ end
+ end
+ end
+ coverage[index] = hash
+ end
+ return {
+ format = "pair",
+ coverage = coverage
+ }
+ elseif subtype == 2 then
+ local coverage = readushort(f)
+ local format1 = readushort(f)
+ local format2 = readushort(f)
+ local classdef1 = readushort(f)
+ local classdef2 = readushort(f)
+ local nofclasses1 = readushort(f) -- incl class 0
+ local nofclasses2 = readushort(f) -- incl class 0
+ local classlist = readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
+ coverage = readcoverage(f,tableoffset+coverage)
+ classdef1 = readclassdef(f,tableoffset+classdef1)
+ classdef2 = readclassdef(f,tableoffset+classdef2)
+ local usedcoverage = { }
+ for g1, c1 in next, classdef1 do
+ if coverage[g1] then
+ local l1 = classlist[c1]
+ if l1 then
+ local hash = { }
+ for paired, class in next, classdef2 do
+ local offsets = l1[class]
+ if offsets then
+ local first = offsets[1]
+ local second = offsets[2]
+ if first or second then
+ hash[paired] = { first, second }
+ else
+ -- upto the next lookup for this combination
+ end
+ end
+ end
+ usedcoverage[g1] = hash
+ end
+ end
+ end
+ return {
+ format = "pair",
+ coverage = usedcoverage
+ }
+ elseif subtype == 3 then
+ report("yet unsupported subtype %a in %a positioning",subtype,"pair")
+ else
+ report("unsupported subtype %a in %a positioning",subtype,"pair")
+ end
+end
+
+function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ local coverage = tableoffset + readushort(f)
+ local nofrecords = readushort(f)
+ local records = { }
+ for i=1,nofrecords do
+ local entry = readushort(f)
+ local exit = readushort(f)
+ records[i] = {
+ entry = entry ~= 0 and (tableoffset + entry) or false,
+ exit = exit ~= 0 and (tableoffset + exit ) or false,
+ }
+ end
+ coverage = readcoverage(f,coverage)
+ for i=1,nofrecords do
+ local r = records[i]
+ records[i] = {
+ 1, -- will become hash after loading (must be unique per lookup when packed)
+ readanchor(f,r.entry) or nil,
+ readanchor(f,r.exit ) or nil,
+ }
+ end
+ for index, newindex in next, coverage do
+ coverage[index] = records[newindex+1]
+ end
+ return {
+ coverage = coverage
+ }
+ else
+ report("unsupported subtype %a in %a positioning",subtype,"cursive")
+ end
+end
+
+local function handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,ligature)
+ local tableoffset = lookupoffset + offset
+ setposition(f,tableoffset)
+ local subtype = readushort(f)
+ if subtype == 1 then
+ -- we are one based, not zero
+ local markcoverage = tableoffset + readushort(f)
+ local basecoverage = tableoffset + readushort(f)
+ local nofclasses = readushort(f)
+ local markoffset = tableoffset + readushort(f)
+ local baseoffset = tableoffset + readushort(f)
+ --
+ local markcoverage = readcoverage(f,markcoverage)
+ local basecoverage = readcoverage(f,basecoverage,true) -- TO BE CHECKED: true
+ --
+ setposition(f,markoffset)
+ local markclasses = { }
+ local nofmarkclasses = readushort(f)
+ --
+ local lastanchor = fontdata.lastanchor or 0
+ local usedanchors = { }
+ --
+-- local placeholder = (fontdata.markcount or 0) + 1
+-- fontdata.markcount = placeholder
+-- placeholder = "m" .. placeholder
+ --
+ for i=1,nofmarkclasses do
+ local class = readushort(f) + 1
+ local offset = readushort(f)
+ if offset == 0 then
+ markclasses[i] = false
+ else
+-- markclasses[i] = { placeholder, class, markoffset + offset }
+ markclasses[i] = { class, markoffset + offset }
+ end
+ usedanchors[class] = true
+ end
+ for i=1,nofmarkclasses do
+ local mc = markclasses[i]
+ if mc then
+-- mc[3] = readanchor(f,mc[3])
+ mc[2] = readanchor(f,mc[2])
+ end
+ end
+ --
+ setposition(f,baseoffset)
+ local nofbaserecords = readushort(f)
+ local baserecords = { }
+ --
+ if ligature then
+ -- 3 components
+ -- 1 : class .. nofclasses -- NULL when empty
+ -- 2 : class .. nofclasses -- NULL when empty
+ -- 3 : class .. nofclasses -- NULL when empty
+ for i=1,nofbaserecords do -- here i is the class
+ local offset = readushort(f)
+ if offset == 0 then
+ baserecords[i] = false
+ else
+ baserecords[i] = baseoffset + offset
+ end
+ end
+ for i=1,nofbaserecords do
+ local recordoffset = baserecords[i]
+ if recordoffset then
+ setposition(f,recordoffset)
+ local nofcomponents = readushort(f)
+ local components = { }
+ for i=1,nofcomponents do
+ local classes = { }
+ for i=1,nofclasses do
+ local offset = readushort(f)
+ if offset ~= 0 then
+ classes[i] = recordoffset + offset
+ else
+ classes[i] = false
+ end
+ end
+ components[i] = classes
+ end
+ baserecords[i] = components
+ end
+ end
+ local baseclasses = { } -- setmetatableindex("table")
+ for i=1,nofclasses do
+ baseclasses[i] = { }
+ end
+ for i=1,nofbaserecords do
+ local components = baserecords[i]
+ local b = basecoverage[i]
+ if components then
+ for c=1,#components do
+ local classes = components[c]
+ if classes then
+ for i=1,nofclasses do
+ local anchor = readanchor(f,classes[i])
+ local bclass = baseclasses[i]
+ local bentry = bclass[b]
+ if bentry then
+ bentry[c] = anchor
+ else
+ bclass[b]= { [c] = anchor }
+ end
+ end
+ end
+ components[i] = classes
+ end
+ end
+ end
+ for index, newindex in next, markcoverage do
+ markcoverage[index] = markclasses[newindex+1] or nil
+ end
+ return {
+ format = "ligature",
+ baseclasses = baseclasses,
+ coverage = markcoverage,
+ }
+ else
+ for i=1,nofbaserecords do
+ local r = { }
+ for j=1,nofclasses do
+ local offset = readushort(f)
+ if offset == 0 then
+ r[j] = false
+ else
+ r[j] = baseoffset + offset
+ end
+ end
+ baserecords[i] = r
+ end
+ local baseclasses = { } -- setmetatableindex("table")
+ for i=1,nofclasses do
+ baseclasses[i] = { }
+ end
+ for i=1,nofbaserecords do
+ local r = baserecords[i]
+ local b = basecoverage[i]
+ for j=1,nofclasses do
+ baseclasses[j][b] = readanchor(f,r[j])
+ end
+ end
+ for index, newindex in next, markcoverage do
+ markcoverage[index] = markclasses[newindex+1] or nil
+ end
+ -- we could actually already calculate the displacement if we want
+ return {
+ format = "base",
+ baseclasses = baseclasses,
+ coverage = markcoverage,
+ }
+ end
+ else
+ report("unsupported subtype %a in",subtype)
+ end
+
+end
+
+function gposhandlers.marktobase(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+end
+
+function gposhandlers.marktoligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,true)
+end
+
+function gposhandlers.marktomark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+end
+
+function gposhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"), "context"
+end
+
+function gposhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"), "chainedcontext"
+end
+
+function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
+ return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gpostypes,gposhandlers,"positioning")
+end
+
+-- main loader
+
+do
+
+ local plugins = { }
+
+ function plugins.size(f,fontdata,tableoffset,parameters)
+ if not fontdata.designsize then
+ setposition(f,tableoffset+parameters)
+ local designsize = readushort(f)
+ if designsize > 0 then
+ fontdata.designsize = designsize
+ skipshort(f,2)
+ fontdata.minsize = readushort(f)
+ fontdata.maxsize = readushort(f)
+ end
+ end
+ end
+
+ -- feature order needs checking ... as we loop over a hash
+
+ local function reorderfeatures(fontdata,scripts,features)
+ local scriptlangs = { }
+ local featurehash = { }
+ local featureorder = { }
+ for script, languages in next, scripts do
+ for language, record in next, languages do
+ local hash = { }
+ local list = record.featureindices
+ for k=1,#list do
+ local index = list[k]
+ local feature = features[index]
+ local lookups = feature.lookups
+ local tag = feature.tag
+ if tag then
+ hash[tag] = true
+ end
+ if lookups then
+ for i=1,#lookups do
+ local lookup = lookups[i]
+ local o = featureorder[lookup]
+ if o then
+ local okay = true
+ for i=1,#o do
+ if o[i] == tag then
+ okay = false
+ break
+ end
+ end
+ if okay then
+ o[#o+1] = tag
+ end
+ else
+ featureorder[lookup] = { tag }
+ end
+ local f = featurehash[lookup]
+ if f then
+ local h = f[tag]
+ if h then
+ local s = h[script]
+ if s then
+ s[language] = true
+ else
+ h[script] = { [language] = true }
+ end
+ else
+ f[tag] = { [script] = { [language] = true } }
+ end
+ else
+ featurehash[lookup] = { [tag] = { [script] = { [language] = true } } }
+ end
+ --
+ local h = scriptlangs[tag]
+ if h then
+ local s = h[script]
+ if s then
+ s[language] = true
+ else
+ h[script] = { [language] = true }
+ end
+ else
+ scriptlangs[tag] = { [script] = { [language] = true } }
+ end
+ end
+ end
+ end
+ end
+ end
+ return scriptlangs, featurehash, featureorder
+ end
+
+ local function readscriplan(f,fontdata,scriptoffset)
+ setposition(f,scriptoffset)
+ local nofscripts = readushort(f)
+ local scripts = { }
+ for i=1,nofscripts do
+ scripts[readtag(f)] = scriptoffset + readushort(f)
+ end
+ -- script list -> language system info
+ local languagesystems = setmetatableindex("table")
+ for script, offset in next, scripts do
+ setposition(f,offset)
+ local defaultoffset = readushort(f)
+ local noflanguages = readushort(f)
+ local languages = { }
+ if defaultoffset > 0 then
+ languages.dflt = languagesystems[offset + defaultoffset]
+ end
+ for i=1,noflanguages do
+ local language = readtag(f)
+ local offset = offset + readushort(f)
+ languages[language] = languagesystems[offset]
+ end
+ scripts[script] = languages
+ end
+ -- script list -> language system info -> feature list
+ for offset, usedfeatures in next, languagesystems do
+ if offset > 0 then
+ setposition(f,offset)
+ local featureindices = { }
+ usedfeatures.featureindices = featureindices
+ usedfeatures.lookuporder = readushort(f) -- reserved, not used (yet)
+ usedfeatures.requiredindex = readushort(f) -- relates to required (can be 0xFFFF)
+ local noffeatures = readushort(f)
+ for i=1,noffeatures do
+ featureindices[i] = readushort(f) + 1
+ end
+ end
+ end
+ return scripts
+ end
+
+ local function readfeatures(f,fontdata,featureoffset)
+ setposition(f,featureoffset)
+ local features = { }
+ local noffeatures = readushort(f)
+ for i=1,noffeatures do
+ -- also shared?
+ features[i] = {
+ tag = readtag(f),
+ offset = readushort(f)
+ }
+ end
+ --
+ for i=1,noffeatures do
+ local feature = features[i]
+ local offset = featureoffset+feature.offset
+ setposition(f,offset)
+ local parameters = readushort(f) -- feature.parameters
+ local noflookups = readushort(f)
+ if noflookups > 0 then
+ local lookups = { }
+ feature.lookups = lookups
+ for j=1,noflookups do
+ lookups[j] = readushort(f) + 1
+ end
+ end
+ if parameters > 0 then
+ feature.parameters = parameters
+ local plugin = plugins[feature.tag]
+ if plugin then
+ plugin(f,fontdata,offset,parameters)
+ end
+ end
+ end
+ return features
+ end
+
+ 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
+ for lookupid=1,noflookups do
+ local index = lookups[lookupid]
+ setposition(f,lookupoffset+index)
+ local subtables = { }
+ local typebits = readushort(f)
+ local flagbits = readushort(f)
+ local lookuptype = lookuptypes[typebits]
+ local lookupflags = lookupflags[flagbits]
+ local nofsubtables = readushort(f)
+ for j=1,nofsubtables do
+ local offset = readushort(f)
+ subtables[j] = offset + index -- we can probably put lookupoffset here
+ end
+ -- which one wins?
+ local markclass = bittest(flagbits,0x0010) -- usemarkfilteringset
+ if markclass then
+ markclass = readushort(f) -- + 1
+ end
+ local markset = rshift(flagbits,8)
+ if markset > 0 then
+ markclass = markset -- + 1
+ end
+ lookups[lookupid] = {
+ type = lookuptype,
+ -- chain = chaindirections[lookuptype] or nil,
+ flags = lookupflags,
+ name = lookupid,
+ subtables = subtables,
+ markclass = markclass,
+ features = featurehash[lookupid], -- not if extension
+ order = featureorder[lookupid],
+ }
+ end
+ return lookups
+ end
+
+ local function readscriptoffsets(f,fontdata,tableoffset)
+ if not tableoffset then
+ return
+ end
+ setposition(f,tableoffset)
+ local version = readulong(f)
+ if version ~= 0x00010000 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ return
+ end
+ --
+ return tableoffset + readushort(f), tableoffset + readushort(f), tableoffset + readushort(f)
+ end
+
+ local f_lookupname = formatters["%s_%s_%s"]
+
+ local function resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what)
+
+ local sequences = fontdata.sequences or { }
+ local sublookuplist = fontdata.sublookups or { }
+ fontdata.sequences = sequences
+ fontdata.sublookups = sublookuplist
+ local nofsublookups = #sublookuplist
+ local nofsequences = #sequences -- 0
+ local lastsublookup = nofsublookups
+ local lastsequence = nofsequences
+ local lookupnames = lookupnames[what]
+ local sublookuphash = { }
+ local sublookupcheck = { }
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs or #glyphs
+ local noflookups = #lookups
+ local lookupprefix = sub(what,2,2) -- g[s|p][ub|os]
+ --
+ for lookupid=1,noflookups do
+ local lookup = lookups[lookupid]
+ local lookuptype = lookup.type
+ local subtables = lookup.subtables
+ local features = lookup.features
+ local handler = lookuphandlers[lookuptype]
+ if handler then
+ local nofsubtables = #subtables
+ local order = lookup.order
+ local flags = lookup.flags
+ -- this is expected in th efont handler (faster checking)
+ if flags[1] then flags[1] = "mark" end
+ if flags[2] then flags[2] = "ligature" end
+ if flags[3] then flags[3] = "base" end
+ --
+ local markclass = lookup.markclass
+ -- local chain = lookup.chain
+ if nofsubtables > 0 then
+ local steps = { }
+ local nofsteps = 0
+ local oldtype = nil
+ for s=1,nofsubtables do
+ local step, lt = handler(f,fontdata,lookupid,lookupoffset,subtables[s],glyphs,nofglyphs)
+ if lt then
+ lookuptype = lt
+ if oldtype and lt ~= oldtype then
+ report("messy %s lookup type %a and %a",what,lookuptype,oldtype)
+ end
+ oldtype = lookuptype
+ end
+ if not step then
+ report("unsupported %s lookup type %a",what,lookuptype)
+ else
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = step
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local before = rule.before
+ local current = rule.current
+ local after = rule.after
+ if before then
+ for i=1,#before do
+ before[i] = tohash(before[i])
+ end
+ -- as with original ctx ff loader
+ rule.before = reversed(before)
+ end
+ if current then
+ for i=1,#current do
+ current[i] = tohash(current[i])
+ end
+ end
+ if after then
+ for i=1,#after do
+ after[i] = tohash(after[i])
+ end
+ end
+ end
+ end
+ end
+ end
+ if nofsteps ~= nofsubtables then
+ report("bogus subtables removed in %s lookup type %a",what,lookuptype)
+ end
+ lookuptype = lookupnames[lookuptype] or lookuptype
+ if features then
+ nofsequences = nofsequences + 1
+ -- report("registering %i as sequence step %i",lookupid,nofsequences)
+ local l = {
+ index = nofsequences,
+ name = f_lookupname(lookupprefix,"s",lookupid+lookupidoffset),
+ steps = steps,
+ nofsteps = nofsteps,
+ type = lookuptype,
+ markclass = markclass or nil,
+ flags = flags,
+ -- chain = chain,
+ order = order,
+ features = features,
+ }
+ sequences[nofsequences] = l
+ lookup.done = l
+ else
+ nofsublookups = nofsublookups + 1
+ -- report("registering %i as sublookup %i",lookupid,nofsublookups)
+ local l = {
+ index = nofsublookups,
+ name = f_lookupname(lookupprefix,"l",lookupid+lookupidoffset),
+ steps = steps,
+ nofsteps = nofsteps,
+ type = lookuptype,
+ markclass = markclass or nil,
+ flags = flags,
+ -- chain = chain,
+ }
+ sublookuplist[nofsublookups] = l
+ sublookuphash[lookupid] = nofsublookups
+ sublookupcheck[lookupid] = 0
+ lookup.done = l
+ end
+ else
+ report("no subtables for lookup %a",lookupid)
+ end
+ else
+ report("no handler for lookup %a with type %a",lookupid,lookuptype)
+ end
+ end
+
+ -- When we have a context, we have sublookups that resolve into lookups for which we need to
+ -- know the type. We split the main lookuptable in two parts: sequences (the main lookups)
+ -- and subtable lookups (simple specs with no features). We could keep them merged and might do
+ -- that once we only use this loader. Then we can also move the simple specs into the sequence.
+ -- After all, we pack afterwards.
+
+ local reported = { }
+
+ for i=lastsequence+1,nofsequences do
+ local sequence = sequences[i]
+ local steps = sequence.steps
+ for i=1,#steps do
+ local step = steps[i]
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local rlookups = rule.lookups
+ if not rlookups then
+ local name = sequence.name
+ if not reported[name] then
+ report("rule %i in %s lookup %a has %s lookups",i,what,name,"no")
+ reported[name] = true
+ end
+ elseif not next(rlookups) then
+ local name = sequence.name
+ if not reported[name] then
+ -- can be ok as it aborts a chain sequence
+ report("rule %i in %s lookup %a has %s lookups",i,what,name,"empty")
+ reported[name] = true
+ end
+ rule.lookups = nil
+ else
+ for index, lookupid in sortedhash(rlookups) do -- nicer
+ local h = sublookuphash[lookupid]
+ if not h then
+ -- here we have a lookup that is used independent as well
+ -- as in another one
+ nofsublookups = nofsublookups + 1
+ -- report("registering %i as sublookup %i",lookupid,nofsublookups)
+ local d = lookups[lookupid].done
+ h = {
+ index = nofsublookups, -- handy for tracing
+ name = f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
+ derived = true, -- handy for tracing
+ steps = d.steps,
+ nofsteps = d.nofsteps,
+ type = d.lookuptype,
+ markclass = d.markclass or nil,
+ flags = d.flags,
+ -- chain = d.chain,
+ }
+ sublookuplist[nofsublookups] = h
+ sublookuphash[lookupid] = nofsublookups
+ sublookupcheck[lookupid] = 1
+ else
+ sublookupcheck[lookupid] = sublookupcheck[lookupid] + 1
+ end
+ rlookups[index] = h
+ end
+ end
+ end
+ end
+ end
+ end
+
+ for i, n in sortedhash(sublookupcheck) do
+ local l = lookups[i]
+ local t = l.type
+ if n == 0 and t ~= "extension" then
+ local d = l.done
+ report("%s lookup %s of type %a is not used",what,d and d.name or l.name,t)
+ -- inspect(l)
+ end
+ end
+
+ end
+
+ local function readscripts(f,fontdata,what,lookuptypes,lookuphandlers,lookupstoo)
+ local datatable = fontdata.tables[what]
+ if not datatable then
+ return
+ end
+ local tableoffset = datatable.offset
+ if not tableoffset then
+ return
+ end
+ local scriptoffset, featureoffset, lookupoffset = readscriptoffsets(f,fontdata,tableoffset)
+ if not scriptoffset then
+ return
+ end
+ --
+ local scripts = readscriplan(f,fontdata,scriptoffset)
+ local features = readfeatures(f,fontdata,featureoffset)
+ --
+ local scriptlangs, featurehash, featureorder = reorderfeatures(fontdata,scripts,features)
+ --
+ if fontdata.features then
+ fontdata.features[what] = scriptlangs
+ else
+ fontdata.features = { [what] = scriptlangs }
+ end
+ --
+ if not lookupstoo then
+ return
+ end
+ --
+ local lookups = readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder)
+ --
+ if lookups then
+ resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what)
+ end
+ end
+
+ local function checkkerns(f,fontdata,specification)
+ local datatable = fontdata.tables.kern
+ if not datatable then
+ return -- no kerns
+ end
+ local features = fontdata.features
+ local gposfeatures = features and features.gpos
+ local name
+ if not gposfeatures or not gposfeatures.kern then
+ name = "kern"
+ elseif specification.globalkerns then
+ name = "globalkern"
+ else
+ report("ignoring global kern table using gpos kern feature")
+ return
+ end
+ report("adding global kern table as gpos feature %a",name)
+ setposition(f,datatable.offset)
+ local version = readushort(f)
+ local noftables = readushort(f)
+ local kerns = setmetatableindex("table")
+ for i=1,noftables do
+ local version = readushort(f)
+ local length = readushort(f)
+ local coverage = readushort(f)
+ -- bit 8-15 of coverage: format 0 or 2
+ local format = bit32.rshift(coverage,8) -- is this ok?
+ if format == 0 then
+ local nofpairs = readushort(f)
+ local searchrange = readushort(f)
+ local entryselector = readushort(f)
+ local rangeshift = readushort(f)
+ for i=1,nofpairs do
+ kerns[readushort(f)][readushort(f)] = readfword(f)
+ end
+ elseif format == 2 then
+ -- apple specific so let's ignore it
+ else
+ -- not supported by ms
+ end
+ end
+ local feature = { dflt = { dflt = true } }
+ if not features then
+ fontdata.features = { gpos = { [name] = feature } }
+ elseif not gposfeatures then
+ fontdata.features.gpos = { [name] = feature }
+ else
+ gposfeatures[name] = feature
+ end
+ local sequences = fontdata.sequences
+ if not sequences then
+ sequences = { }
+ fontdata.sequences = sequences
+ end
+ local nofsequences = #sequences + 1
+ sequences[nofsequences] = {
+ index = nofsequences,
+ name = name,
+ steps = {
+ {
+ coverage = kerns,
+ format = "kern",
+ },
+ },
+ nofsteps = 1,
+ type = "gpos_pair",
+ -- type = "gpos_single", -- maybe better
+ flags = { false, false, false, false },
+ order = { name },
+ features = { [name] = feature },
+ }
+ end
+
+ function readers.gsub(f,fontdata,specification)
+ if specification.details then
+ readscripts(f,fontdata,"gsub",gsubtypes,gsubhandlers,specification.lookups)
+ end
+ end
+
+ function readers.gpos(f,fontdata,specification)
+ if specification.details then
+ readscripts(f,fontdata,"gpos",gpostypes,gposhandlers,specification.lookups)
+ if specification.lookups then
+ checkkerns(f,fontdata,specification)
+ end
+ end
+ end
+
+end
+
+function readers.gdef(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.gdef
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readulong(f)
+ local classoffset = tableoffset + readushort(f)
+ local attachmentoffset = tableoffset + readushort(f) -- used for bitmaps
+ local ligaturecarets = tableoffset + readushort(f) -- used in editors (maybe nice for tracing)
+ local markclassoffset = tableoffset + readushort(f)
+ local marksetsoffset = version == 0x00010002 and (tableoffset + readushort(f))
+ local glyphs = fontdata.glyphs
+ local marks = { }
+ local markclasses = setmetatableindex("table")
+ local marksets = setmetatableindex("table")
+ fontdata.marks = marks
+ fontdata.markclasses = markclasses
+ fontdata.marksets = marksets
+ -- class definitions
+ setposition(f,classoffset)
+ local classformat = readushort(f)
+ if classformat == 1 then
+ local firstindex = readushort(f)
+ local lastindex = firstindex + readushort(f) - 1
+ for index=firstindex,lastindex do
+ local class = classes[readushort(f)]
+ if class == "mark" then
+ marks[index] = true
+ end
+ glyphs[index].class = class
+ end
+ elseif classformat == 2 then
+ local nofranges = readushort(f)
+ for i=1,nofranges do
+ local firstindex = readushort(f)
+ local lastindex = readushort(f)
+ local class = classes[readushort(f)]
+ if class then
+ for index=firstindex,lastindex do
+ glyphs[index].class = class
+ if class == "mark" then
+ marks[index] = true
+ end
+ end
+ end
+ end
+ end
+ -- mark classes
+ setposition(f,markclassoffset)
+ local classformat = readushort(f)
+ if classformat == 1 then
+ local firstindex = readushort(f)
+ local lastindex = firstindex + readushort(f) - 1
+ for index=firstindex,lastindex do
+ markclasses[readushort(f)][index] = true
+ end
+ elseif classformat == 2 then
+ local nofranges = readushort(f)
+ for i=1,nofranges do
+ local firstindex = readushort(f)
+ local lastindex = readushort(f)
+ local class = markclasses[readushort(f)]
+ for index=firstindex,lastindex do
+ class[index] = true
+ end
+ end
+ end
+ -- mark sets : todo: just make the same as class sets above
+ if marksetsoffset then
+ setposition(f,marksetsoffset)
+ local format = readushort(f)
+ if format == 1 then
+ local nofsets = readushort(f)
+ local sets = { }
+ for i=1,nofsets do
+ sets[i] = readulong(f)
+ end
+ -- somehow this fails on e.g. notosansethiopic-bold.ttf
+ for i=1,nofsets do
+ local offset = sets[i]
+ if offset ~= 0 then
+ marksets[i] = readcoverage(f,marksetsoffset+offset)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- We keep this code here instead of font-otm.lua because we need coverage
+-- helpers. Okay, these helpers could go to the main reader file some day.
+
+local function readmathvalue(f)
+ local v = readshort(f)
+ skipshort(f,1) -- offset to device table
+ return v
+end
+
+local function readmathconstants(f,fontdata,offset)
+ setposition(f,offset)
+ fontdata.mathconstants = {
+ ScriptPercentScaleDown = readshort(f),
+ ScriptScriptPercentScaleDown = readshort(f),
+ DelimitedSubFormulaMinHeight = readushort(f),
+ DisplayOperatorMinHeight = readushort(f),
+ MathLeading = readmathvalue(f),
+ AxisHeight = readmathvalue(f),
+ AccentBaseHeight = readmathvalue(f),
+ FlattenedAccentBaseHeight = readmathvalue(f),
+ SubscriptShiftDown = readmathvalue(f),
+ SubscriptTopMax = readmathvalue(f),
+ SubscriptBaselineDropMin = readmathvalue(f),
+ SuperscriptShiftUp = readmathvalue(f),
+ SuperscriptShiftUpCramped = readmathvalue(f),
+ SuperscriptBottomMin = readmathvalue(f),
+ SuperscriptBaselineDropMax = readmathvalue(f),
+ SubSuperscriptGapMin = readmathvalue(f),
+ SuperscriptBottomMaxWithSubscript = readmathvalue(f),
+ SpaceAfterScript = readmathvalue(f),
+ UpperLimitGapMin = readmathvalue(f),
+ UpperLimitBaselineRiseMin = readmathvalue(f),
+ LowerLimitGapMin = readmathvalue(f),
+ LowerLimitBaselineDropMin = readmathvalue(f),
+ StackTopShiftUp = readmathvalue(f),
+ StackTopDisplayStyleShiftUp = readmathvalue(f),
+ StackBottomShiftDown = readmathvalue(f),
+ StackBottomDisplayStyleShiftDown = readmathvalue(f),
+ StackGapMin = readmathvalue(f),
+ StackDisplayStyleGapMin = readmathvalue(f),
+ StretchStackTopShiftUp = readmathvalue(f),
+ StretchStackBottomShiftDown = readmathvalue(f),
+ StretchStackGapAboveMin = readmathvalue(f),
+ StretchStackGapBelowMin = readmathvalue(f),
+ FractionNumeratorShiftUp = readmathvalue(f),
+ FractionNumeratorDisplayStyleShiftUp = readmathvalue(f),
+ FractionDenominatorShiftDown = readmathvalue(f),
+ FractionDenominatorDisplayStyleShiftDown = readmathvalue(f),
+ FractionNumeratorGapMin = readmathvalue(f),
+ FractionNumeratorDisplayStyleGapMin = readmathvalue(f),
+ FractionRuleThickness = readmathvalue(f),
+ FractionDenominatorGapMin = readmathvalue(f),
+ FractionDenominatorDisplayStyleGapMin = readmathvalue(f),
+ SkewedFractionHorizontalGap = readmathvalue(f),
+ SkewedFractionVerticalGap = readmathvalue(f),
+ OverbarVerticalGap = readmathvalue(f),
+ OverbarRuleThickness = readmathvalue(f),
+ OverbarExtraAscender = readmathvalue(f),
+ UnderbarVerticalGap = readmathvalue(f),
+ UnderbarRuleThickness = readmathvalue(f),
+ UnderbarExtraDescender = readmathvalue(f),
+ RadicalVerticalGap = readmathvalue(f),
+ RadicalDisplayStyleVerticalGap = readmathvalue(f),
+ RadicalRuleThickness = readmathvalue(f),
+ RadicalExtraAscender = readmathvalue(f),
+ RadicalKernBeforeDegree = readmathvalue(f),
+ RadicalKernAfterDegree = readmathvalue(f),
+ RadicalDegreeBottomRaisePercent = readshort(f),
+ }
+end
+
+local function readmathglyphinfo(f,fontdata,offset)
+ setposition(f,offset)
+ local italics = readushort(f)
+ local accents = readushort(f)
+ local extensions = readushort(f)
+ local kerns = readushort(f)
+ local glyphs = fontdata.glyphs
+ if italics ~= 0 then
+ setposition(f,offset+italics)
+ local coverage = readushort(f)
+ local nofglyphs = readushort(f)
+ coverage = readcoverage(f,offset+italics+coverage,true)
+ setposition(f,offset+italics+4)
+ for i=1,nofglyphs do
+ local italic = readmathvalue(f)
+ if italic ~= 0 then
+ local glyph = glyphs[coverage[i]]
+ local math = glyph.math
+ if not math then
+ glyph.math = { italic = italic }
+ else
+ math.italic = italic
+ end
+ end
+ end
+ fontdata.hasitalics = true
+ end
+ if accents ~= 0 then
+ setposition(f,offset+accents)
+ local coverage = readushort(f)
+ local nofglyphs = readushort(f)
+ coverage = readcoverage(f,offset+accents+coverage,true)
+ setposition(f,offset+accents+4)
+ for i=1,nofglyphs do
+ local accent = readmathvalue(f)
+ if accent ~= 0 then
+ local glyph = glyphs[coverage[i]]
+ local math = glyph.math
+ if not math then
+ glyph.math = { accent = accent }
+ else
+ math.accent = accent
+ end
+ end
+ end
+ end
+ if extensions ~= 0 then
+ setposition(f,offset+extensions)
+ end
+ if kerns ~= 0 then
+ local kernoffset = offset + kerns
+ setposition(f,kernoffset)
+ local coverage = readushort(f)
+ local nofglyphs = readushort(f)
+ if nofglyphs > 0 then
+ local function get(offset)
+ setposition(f,kernoffset+offset)
+ local n = readushort(f)
+ if n > 0 then
+ local l = { }
+ -- for i=1,n do
+ -- l[i] = { readushort(f), 0 } -- height, kern
+ -- skipshort(f)
+ -- end
+ -- for i=1,n do
+ -- l[i][2] = readushort(f)
+ -- skipshort(f)
+ -- end
+ for i=1,n do
+ l[i] = { height = readmathvalue(f) }
+ end
+ for i=1,n do
+ l[i].kern = readmathvalue(f)
+ end
+ l[n+1] = { kern = readmathvalue(f) }
+ return l
+ end
+ end
+ local kernsets = { }
+ for i=1,nofglyphs do
+ local topright = readushort(f)
+ local topleft = readushort(f)
+ local bottomright = readushort(f)
+ local bottomleft = readushort(f)
+ kernsets[i] = {
+ topright = topright ~= 0 and topright or nil,
+ topleft = topleft ~= 0 and topleft or nil,
+ bottomright = bottomright ~= 0 and bottomright or nil,
+ bottomleft = bottomleft ~= 0 and bottomleft or nil,
+ }
+ end
+ coverage = readcoverage(f,kernoffset+coverage,true)
+ for i=1,nofglyphs do
+ local kernset = kernsets[i]
+ if next(kernset) then
+ local k = kernset.topright if k then kernset.topright = get(k) end
+ local k = kernset.topleft if k then kernset.topleft = get(k) end
+ local k = kernset.bottomright if k then kernset.bottomright = get(k) end
+ local k = kernset.bottomleft if k then kernset.bottomleft = get(k) end
+ if next(kernset) then
+ local glyph = glyphs[coverage[i]]
+ local math = glyph.math
+ if not math then
+ glyph.math = { kerns = kernset }
+ else
+ math.kerns = kernset
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local function readmathvariants(f,fontdata,offset)
+ setposition(f,offset)
+ local glyphs = fontdata.glyphs
+ local minoverlap = readushort(f)
+ local vcoverage = readushort(f)
+ 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
+
+ fontdata.mathconstants.MinConnectorOverlap = minoverlap
+
+ -- variants[i] = {
+ -- glyph = readushort(f),
+ -- advance = readushort(f),
+ -- }
+
+ local function get(offset,coverage,nofglyphs,construction,kvariants,kparts,kitalic)
+ if coverage ~= 0 and nofglyphs > 0 then
+ local coverage = readcoverage(f,offset+coverage,true)
+ for i=1,nofglyphs do
+ local c = construction[i]
+ if c ~= 0 then
+ local index = coverage[i]
+ local glyph = glyphs[index]
+ local math = glyph.math
+ setposition(f,offset+c)
+ local assembly = readushort(f)
+ local nofvariants = readushort(f)
+ if nofvariants > 0 then
+ local variants, v = nil, 0
+ for i=1,nofvariants do
+ local variant = readushort(f)
+ if variant == index then
+ -- ignore
+ elseif variants then
+ v = v + 1
+ variants[v] = variant
+ else
+ v = 1
+ variants = { variant }
+ end
+ skipshort(f)
+ end
+ if not variants then
+ -- only self
+ elseif not math then
+ math = { [kvariants] = variants }
+ glyph.math = math
+ else
+ math[kvariants] = variants
+ end
+ end
+ if assembly ~= 0 then
+ setposition(f,offset + c + assembly)
+ local italic = readmathvalue(f)
+ local nofparts = readushort(f)
+ local parts = { }
+ for i=1,nofparts do
+ local p = {
+ glyph = readushort(f),
+ start = readushort(f),
+ ["end"] = readushort(f),
+ advance = readushort(f),
+ }
+ local flags = readushort(f)
+ if bittest(flags,0x0001) then
+ p.extender = 1 -- true
+ end
+ parts[i] = p
+ end
+ if not math then
+ math = {
+ [kparts] = parts
+ }
+ glyph.math = math
+ else
+ math[kparts] = parts
+ end
+ if italic and italic ~= 0 then
+ math[kitalic] = italic
+ end
+ end
+ end
+ end
+ end
+ end
+
+ get(offset,vcoverage,vnofglyphs,vconstruction,"vvariants","vparts","vitalic")
+ get(offset,hcoverage,hnofglyphs,hconstruction,"hvariants","hparts","hitalic")
+end
+
+function readers.math(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.math
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readulong(f)
+ if version ~= 0x00010000 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ return
+ end
+ local constants = readushort(f)
+ local glyphinfo = readushort(f)
+ local variants = readushort(f)
+ if constants == 0 then
+ report("the math table of %a has no constants",fontdata.filename)
+ else
+ readmathconstants(f,fontdata,tableoffset+constants)
+ end
+ if glyphinfo ~= 0 then
+ readmathglyphinfo(f,fontdata,tableoffset+glyphinfo)
+ end
+ if variants ~= 0 then
+ readmathvariants(f,fontdata,tableoffset+variants)
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi
new file mode 100644
index 00000000000..8f87ff7a199
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi
@@ -0,0 +1,237 @@
+%D \module
+%D [ file=font-emp,
+%D version=20120106, % (moved from font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Emphasis,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Emphasis}
+
+\unprotect
+
+%D \macros
+%D {em,emphasistypeface,emphasisboldface}
+%D
+%D The next macro started as a copy of Donald Arseneau's
+%D \type{\em} (\TUGNEWS\ Vol.~3, no.~1, 1994). His
+%D implementation was a bit more sophisticated version of the
+%D standard \LATEX\ one. We further enhanced the macro, so now
+%D it also adapts itself to boldface mode. Because we favor
+%D {\sl slanted} type over {\it italic}, we made the emphasis
+%D adaptable, for instance:
+%D
+%D \starttyping
+%D \def\emphasistypeface {\it}
+%D \def\emphasisboldface {\bi}
+%D \stoptyping
+%D
+%D But we prefer:
+%D
+%D \starttyping
+%D \unexpanded\def\emphasistypeface{\sl}
+%D \unexpanded\def\emphasisboldface{\bs}
+%D \stoptyping
+%D
+%D or even better:
+
+\let\m_font_emphasized_typeface\empty
+
+\def\font_emphasis_checked_typeface#slanted#italic%
+ {\edef\m_font_emphasized_typeface{\font_bodyfontvariable\s!em}%
+ \ifx\m_font_emphasized_typeface\v!slanted
+ #slanted%
+ \else\ifx\m_font_emphasized_typeface\v!italic
+ #italic%
+ \else\ifx\m_font_emphasized_typeface\empty
+ #slanted%
+ \else
+ \csname\m_font_emphasized_typeface\endcsname
+ \fi\fi\fi}
+
+\unexpanded\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
+\unexpanded\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
+
+\unexpanded\def\normalboldface % public
+ {\relax\ifx\fontalternative\s!it\bi
+ \else \ifx\fontalternative\s!sl\bs
+ \else \bf\fi\fi}
+
+\unexpanded\def\normaltypeface % public
+ {\relax
+ \ifx\fontalternative\s!bi \it \else
+ \ifx\fontalternative\s!bs \sl \else
+ \tf \fi\fi}
+
+\unexpanded\def\swaptypeface % public
+ {\relax
+ \ifx\fontalternative\s!it \tf \else
+ \ifx\fontalternative\s!sl \tf \else
+ \ifx\fontalternative\s!bf \emphasisboldface \else
+ \ifx\fontalternative\s!bs \bf \else
+ \ifx\fontalternative\s!bi \bf \else
+ \emphasistypeface \fi\fi\fi\fi\fi}
+
+\let\typeface\normaltypeface % public
+\let\boldface\normalboldface % public
+\let\swapface\swaptypeface % public
+
+%D To be set with the default body font environment: \type
+%D {em} being \type {slanted} or \type {italic}.
+
+% maybe a \csname...\fontalternative\endcsname
+
+\newconditional\c_font_emphasis_needed
+
+\unexpanded\def\em
+ {\relax
+ \ifdim\slantperpoint>\zeropoint
+ \settrue\c_font_emphasis_needed
+ \else
+ \setfalse\c_font_emphasis_needed
+ \fi
+ \font_emphasis_set_emphasis_boldface % new
+ \ifx\fontalternative\s!it
+ \unexpanded\def\emphasistypeface{\it}\tf
+ \else\ifx\fontalternative\s!sl
+ \unexpanded\def\emphasistypeface{\sl}\tf
+ \else\ifx\fontalternative\s!bf
+ \emphasisboldface
+ \else\ifx\fontalternative\s!bs
+ \unexpanded\def\emphasisboldface{\bs}\bf
+ \else\ifx\fontalternative\s!bi
+ \unexpanded\def\emphasisboldface{\bi}\bf
+ \else
+ \emphasistypeface
+ \fi\fi\fi\fi\fi
+ \ifconditional\c_font_emphasis_needed\else
+ \expandafter\aftergroup
+ \fi
+ \emphasiscorrection}
+
+%D The next feature was not present in previous versions. It
+%D takes care of \type {\em \bf ...} situations.
+
+\let\font_emphasis_saved_emphasis_boldface\relax
+
+\def\font_emphasis_set_emphasis_boldface
+ {\let\font_emphasis_saved_emphasis_boldface\bf
+ \let\font_emphasis_set_emphasis_boldface\relax
+ \let\bf\font_emphasis_bold_bold}
+
+\unexpanded\def\font_emphasis_bold_bold
+ {%\relax
+ \let\bf\relax % new
+ \ifx\fontalternative\s!it
+ \bi
+ \else\ifx\fontalternative\s!sl
+ \bs
+ \else
+ \font_emphasis_saved_emphasis_boldface
+ \fi\fi
+ \let\bf\font_emphasis_saved_emphasis_boldface}
+
+%D Donald's (adapted) macros take the next character into
+%D account when placing italic correction. As a bonus we also
+%D look for something that looks like a dash, in which case we
+%D don't correct.
+
+\let\italiccorrection=\/ % tex primitive
+
+\def\emphasiscorrection % public, not in raw alignment groups, else omit problem
+ {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else
+ \expandafter\expandafter\expandafter\font_emphasis_look
+ \fi\fi}
+
+\def\font_emphasis_look
+ {\begingroup
+ \futurelet\nexttoken\font_emphasis_test}
+
+\def\font_emphasis_test
+ {\ifcat\noexpand\nexttoken,% still ok?
+ \expandafter\font_emphasis_a
+ \else
+ \expandafter\font_emphasis_b
+ \fi}
+
+\def\font_emphasis_a
+ {\futurelet\nexttoken\font_emphasis_correction}
+
+\def\font_emphasis_correction
+ {\setbox\scratchbox\hbox{\nexttoken}% tricky as next can be a macro
+ \ifdim\ht\scratchbox=\zeropoint % probably a space
+ \expandafter\font_emphasis_b
+ \else\ifdim\ht\scratchbox<.3\exheight
+ \expandafter\expandafter\expandafter\endgroup
+ \else
+ \expandafter\expandafter\expandafter\font_emphasis_b
+ \fi\fi}
+
+\def\font_emphasis_b
+ {\scratchskip\lastskip
+ \ifdim\scratchskip=\zeropoint\relax % == \ifzeropt\scratchskip
+ \italiccorrection\relax
+ \else
+ \unskip\italiccorrection\hskip\scratchskip
+ \fi
+ \endgroup}
+
+%D We end with some examples which show the behavior when
+%D some punctuation is met. We also show how the mechanism
+%D adapts itself to bold, italic and slanted typing.
+%D
+%D \startbuffer
+%D test {test}test \par
+%D test {\sl test}test \par
+%D test {\em test}test \par
+%D test {\em test}--test \par
+%D
+%D test {test}, test \par
+%D test {\em test}, test \par
+%D
+%D test {\em test {\em test {\em test} test} test} test \par
+%D test {\bf test {\em test {\em test} test} test} test \par
+%D test {\sl test {\em test {\em test} test} test} test \par
+%D test {\it test {\em test {\em test} test} test} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+%D \macros
+%D {emphbf,emphit,emphsl,emphtf}
+%D
+%D The next emphasis alternatives are for \THANH. They adapt
+%D their style as good as possible. These macros are obsolete
+%D in \MKIV.
+
+\unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+\unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+\unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+\unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+
+\unexpanded\def\emph {\groupedcommand{\em}{}}
+
+\unexpanded\def\emphasized{\bgroup\em\let\nexttoken}
+
+%D \startbuffer
+%D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT
+%D TEXT \emphbf{text \emphit{text} \emphtf{text} \emphsl{text}} TEXT
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-enc.lua b/Master/texmf-dist/tex/context/base/mkiv/font-enc.lua
new file mode 100644
index 00000000000..2e8b722de39
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-enc.lua
@@ -0,0 +1,153 @@
+if not modules then modules = { } end modules ['font-enc'] = {
+ 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"
+}
+
+-- this module is obsolete
+
+local next = next
+local match, gmatch, gsub = string.match, string.gmatch, string.gsub
+
+local setmetatableindex = table.setmetatableindex
+
+--[[ldx--
+<p>Because encodings are going to disappear, we don't bother defining
+them in tables. But we may do so some day, for consistency.</p>
+--ldx]]--
+
+local report_encoding = logs.reporter("fonts","encoding")
+
+local encodings = { }
+fonts.encodings = encodings
+
+encodings.version = 1.03
+encodings.cache = containers.define("fonts", "enc", fonts.encodings.version, true)
+encodings.known = utilities.storage.allocate { -- sort of obsolete
+ texnansi = true,
+ ec = true,
+ qx = true,
+ t5 = true,
+ t2a = true,
+ t2b = true,
+ t2c = true,
+ unicode = true,
+}
+
+function encodings.is_known(encoding)
+ return containers.is_valid(encodings.cache,encoding)
+end
+
+--[[ldx--
+<p>An encoding file looks like this:</p>
+
+<typing>
+/TeXnANSIEncoding [
+/.notdef
+/Euro
+...
+/ydieresis
+] def
+</typing>
+
+<p>Beware! The generic encoding files don't always apply to the ones that
+ship with fonts. This has to do with the fact that names follow (slightly)
+different standards. However, the fonts where this applies to (for instance
+Latin Modern or <l n='tex'> Gyre) come in OpenType variants too, so these
+will be used.</p>
+--ldx]]--
+
+local enccodes = characters.enccodes or { }
+
+function encodings.load(filename)
+ local name = file.removesuffix(filename)
+ local data = containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ if name == "unicode" then
+ data = encodings.make_unicode_vector() -- special case, no tex file for this
+ end
+ if data then
+ return data
+ end
+ local vector, tag, hash, unicodes = { }, "", { }, { }
+ local foundname = resolvers.findfile(filename,'enc')
+ if foundname and foundname ~= "" then
+ local ok, encoding, size = resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding = gsub(encoding,"%%(.-)\n","")
+ local tag, vec = match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i = 0
+ for ch in gmatch(vec,"/([%a%d%.]+)") do
+ if ch ~= ".notdef" then
+ vector[i] = ch
+ if not hash[ch] then
+ hash[ch] = i
+ else
+ -- duplicate, play safe for tex ligs and take first
+ end
+ if enccodes[ch] then
+ unicodes[enccodes[ch]] = i
+ end
+ end
+ i = i + 1
+ end
+ end
+ end
+ local data = {
+ name = name,
+ tag = tag,
+ vector = vector,
+ hash = hash,
+ unicodes = unicodes
+ }
+ return containers.write(encodings.cache, name, data)
+end
+
+--[[ldx--
+<p>There is no unicode encoding but for practical purposes we define
+one.</p>
+--ldx]]--
+
+-- maybe make this a function:
+
+function encodings.make_unicode_vector()
+ local vector, hash = { }, { }
+ for code, v in next, characters.data do
+ local name = v.adobename
+ if name then
+ vector[code] = name
+ hash[name] = code
+ else
+ vector[code] = '.notdef'
+ end
+ end
+ for name, code in next, characters.synonyms do
+ if not vector[code] then
+ vector[code] = name
+ end
+ if not hash[name] then
+ hash[name] = code
+ end
+ end
+ return containers.write(encodings.cache, 'unicode', { name='unicode', tag='unicode', vector=vector, hash=hash })
+end
+
+if not encodings.agl then
+
+ -- We delay delay loading this rather big vector that is only needed when a
+ -- font is loaded for caching. Once we're further along the route we can also
+ -- delay it in the generic version (which doesn't use this file).
+
+ encodings.agl = { }
+
+ setmetatableindex(encodings.agl, function(t,k)
+ report_encoding("loading (extended) adobe glyph list")
+ dofile(resolvers.findfile("font-agl.lua"))
+ return rawget(encodings.agl,k)
+ end)
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua
new file mode 100644
index 00000000000..3439a434ab4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['font-enh'] = {
+ 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 trace_unicoding = false
+
+trackers.register("fonts.defining", function(v) trace_unicoding = v end)
+trackers.register("fonts.unicoding", function(v) trace_unicoding = v end)
+
+local report_unicoding = logs.reporter("fonts","unicoding")
+
+local fonts = fonts
+local constructors = fonts.constructors
+
+local tfmfeatures = constructors.newfeatures("tfm")
+local registertfmfeature = tfmfeatures.register
+
+local afmfeatures = fonts.constructors.newfeatures("afm")
+local registerafmfeature = afmfeatures.register
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+-- -- these will become goodies (when needed at all)
+--
+-- local fontencodings = fonts.encodings
+-- fontencodings.remappings = fontencodings.remappings or { }
+--
+-- local function reencode(tfmdata,encoding)
+-- if encoding and fontencodings.known[encoding] then
+-- local data = fontencodings.load(encoding)
+-- if data then
+-- tfmdata.properties.encoding = encoding
+-- local characters = tfmdata.characters
+-- local original = { }
+-- local vector = data.vector
+-- for unicode, character in next, characters do
+-- character.name = vector[unicode]
+-- character.index = unicode, character
+-- original[unicode] = character
+-- end
+-- for newcode, oldcode in next, data.unicodes do
+-- if newcode ~= oldcode then
+-- if trace_unicoding then
+-- report_unicoding("reencoding %U to %U",oldcode,newcode)
+-- end
+-- characters[newcode] = original[oldcode]
+-- end
+-- end
+-- end
+-- end
+-- end
+--
+-- registertfmfeature {
+-- name = "reencode",
+-- description = "reencode",
+-- manipulators = {
+-- base = reencode,
+-- node = reencode,
+-- }
+-- }
+--
+-- local function remap(tfmdata,remapping)
+-- local vector = remapping and fontencodings.remappings[remapping]
+-- if vector then
+-- local characters, original = tfmdata.characters, { }
+-- for k, v in next, characters do
+-- original[k], characters[k] = v, nil
+-- end
+-- for k,v in next, vector do
+-- if k ~= v then
+-- if trace_unicoding then
+-- report_unicoding("remapping %U to %U",k,v)
+-- end
+-- local c = original[k]
+-- characters[v] = c
+-- c.index = k
+-- end
+-- end
+-- local properties = tfmdata.properties
+-- if not properties then
+-- properties = { }
+-- tfmdata.properties = properties
+-- else
+-- properties.encodingbytes = 2
+-- properties.format = properties.format or 'type1'
+-- end
+-- end
+-- end
+--
+-- registertfmfeature {
+-- name = "remap",
+-- description = "remap",
+-- manipulators = {
+-- base = remap,
+-- node = remap,
+-- }
+-- }
+
+-- \definefontfeature[dingbats][goodies=dingbats,unicoding=yes]
+
+-- we only add and don't replace
+-- we could also add kerns but we asssume symbols
+-- todo: complain if not basemode
+
+-- remapping = {
+-- tounicode = true,
+-- unicodes = {
+-- a1 = 0x2701,
+
+----- tosixteen = fonts.mappings.tounicode16
+
+local function initializeunicoding(tfmdata)
+ local goodies = tfmdata.goodies
+ local newcoding = nil
+ -- local tounicode = false
+ for i=1,#goodies do
+ local remapping = goodies[i].remapping
+ if remapping and remapping.unicodes then
+ newcoding = remapping.unicodes -- names to unicodes
+ -- tounicode = remapping.tounicode -- not used
+ end
+ end
+ if newcoding then
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local oldcoding = tfmdata.resources.unicodes
+ -- local tounicodes = tfmdata.resources.tounicode -- index to unicode
+ local originals = { }
+ for name, newcode in next, newcoding do
+ local oldcode = oldcoding[name]
+ if characters[newcode] and not originals[newcode] then
+ originals[newcode] = {
+ character = characters [newcode],
+ description = descriptions[newcode],
+ }
+ end
+ if oldcode then
+ local original = originals[oldcode]
+ if original then
+ characters [newcode] = original.character
+ descriptions[newcode] = original.description
+ else
+ characters [newcode] = characters [oldcode]
+ descriptions[newcode] = descriptions[oldcode]
+ end
+ else
+ oldcoding[name] = newcode
+ end
+ -- if tounicode then
+ -- local description = descriptions[newcode]
+ -- if description then
+ -- local index = description.index
+ -- if not tounicodes[index] then
+ -- tounicodes[index] = tosixteen(newcode) -- shared (we could have a metatable)
+ -- end
+ -- end
+ -- end
+ if trace_unicoding then
+ if oldcode then
+ report_unicoding("aliasing glyph %a from %U to %U",name,oldcode,newcode)
+ else
+ report_unicoding("aliasing glyph %a to %U",name,newcode)
+ end
+ end
+ end
+ end
+end
+
+registerafmfeature {
+ name = "unicoding",
+ description = "adapt unicode table",
+ initializers = {
+ base = initializeunicoding,
+ node = initializeunicoding,
+ },
+ -- manipulators = {
+ -- base = finalizeunicoding,
+ -- node = finalizeunicoding,
+ -- }
+}
+
+registerotffeature {
+ name = "unicoding",
+ description = "adapt unicode table",
+ initializers = {
+ base = initializeunicoding,
+ node = initializeunicoding,
+ },
+ -- manipulators = {
+ -- base = finalizeunicoding,
+ -- node = finalizeunicoding,
+ -- }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua
new file mode 100644
index 00000000000..79144aa70e3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua
@@ -0,0 +1,1039 @@
+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, byte = next, type, string.byte
+local utfbyte = utf.byte
+
+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")
+local report_opbd = logs.reporter("fonts","otf opbd")
+
+--[[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 registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local fontdata = hashes.identifiers
+
+local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
+local getparameters = utilities.parsers.getparameters
+
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+
+-- -- -- -- -- --
+-- 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
+
+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,
+ auto = true,
+ }
+ 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
+
+registerotffeature {
+ name = "expansion",
+ description = "apply hz optimization",
+ initializers = {
+ base = initializeexpansion,
+ node = initializeexpansion,
+ }
+}
+
+registerafmfeature {
+ name = "expansion",
+ description = "apply hz optimization",
+ initializers = {
+ base = initializeexpansion,
+ node = initializeexpansion,
+ }
+}
+
+fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
+
+implement {
+ name = "setupfontexpansion",
+ arguments = { "string", "string" },
+ 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 data = lookuphash[lookup]
+ if data then
+ if trace_protrusion then
+ report_protrusions("setting left using lfbd lookup %a",lookuptags[lookup])
+ end
+ for k, v in next, data 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 -> %s -> %C -> %0.03f (% t)",lookuptags[lookup],k,p,v)
+ 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 data = lookuphash[lookup]
+ if data then
+ if trace_protrusion then
+ report_protrusions("setting right using rtbd lookup %a",lookuptags[lookup])
+ end
+ for k, v in next, data 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 -> %s -> %C -> %0.03f (% t)",lookuptags[lookup],k,p,v)
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+ local parameters = tfmdata.parameters
+ local protrusion = tfmdata.protrusion
+ if not protrusion then
+ parameters.protrusion = {
+ auto = true
+ }
+ else
+ protrusion.auto = true
+ 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,
+ auto = true,
+ }
+ 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
+
+registerotffeature {
+ name = "protrusion",
+ description = "l/r margin character protrusion",
+ initializers = {
+ base = initializeprotrusion,
+ node = initializeprotrusion,
+ }
+}
+
+registerafmfeature {
+ name = "protrusion",
+ description = "shift characters into the left and or right margin",
+ initializers = {
+ base = initializeprotrusion,
+ node = initializeprotrusion,
+ }
+}
+
+fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
+
+implement {
+ name = "setupfontprotrusion",
+ arguments = { "string", "string" },
+ 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
+
+registerotffeature {
+ name = "itlc",
+ description = "italic correction",
+ initializers = {
+ base = initializeitlc,
+ node = initializeitlc,
+ }
+}
+
+registerafmfeature {
+ name = "itlc",
+ description = "italic correction",
+ initializers = {
+ base = initializeitlc,
+ node = initializeitlc,
+ }
+}
+
+local function initializetextitalics(tfmdata,value) -- yes no delay
+ tfmdata.properties.textitalics = toboolean(value)
+end
+
+registerotffeature {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initializetextitalics,
+ node = initializetextitalics,
+ }
+}
+
+registerafmfeature {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initializetextitalics,
+ node = initializetextitalics,
+ }
+}
+
+local function initializemathitalics(tfmdata,value) -- yes no delay
+ tfmdata.properties.mathitalics = toboolean(value)
+end
+
+registerotffeature {
+ name = "mathitalics",
+ description = "use alternative math italic correction",
+ initializers = {
+ base = initializemathitalics,
+ node = initializemathitalics,
+ }
+}
+
+registerafmfeature {
+ name = "mathitalics",
+ description = "use alternative math italic correction",
+ initializers = {
+ base = initializemathitalics,
+ node = initializemathitalics,
+ }
+}
+
+-- 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
+
+registerotffeature {
+ name = "slant",
+ description = "slant glyphs",
+ initializers = {
+ base = initializeslant,
+ node = initializeslant,
+ }
+}
+
+registerafmfeature {
+ name = "slant",
+ description = "slant glyphs",
+ initializers = {
+ base = initializeslant,
+ node = initializeslant,
+ }
+}
+
+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
+
+registerotffeature {
+ name = "extend",
+ description = "scale glyphs horizontally",
+ initializers = {
+ base = initializeextend,
+ node = initializeextend,
+ }
+}
+
+registerafmfeature {
+ name = "extend",
+ description = "scale glyphs horizontally",
+ initializers = {
+ base = initializeextend,
+ node = initializeextend,
+ }
+}
+
+-- For Wolfgang Schuster:
+--
+-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
+-- \definedfont[file:kozminpr6nregular*thisway]
+--
+-- For the moment we don't mess with the descriptions.
+
+local function manipulatedimensions(tfmdata,key,value)
+ if type(value) == "string" and value ~= "" then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local emwidth = parameters.quad
+ local exheight = parameters.xheight
+ local spec = settings_to_array(value)
+ local width = (spec[1] or 0) * emwidth
+ local height = (spec[2] or 0) * exheight
+ local depth = (spec[3] or 0) * exheight
+ if width > 0 then
+ local resources = tfmdata.resources
+ local additions = { }
+ local private = resources.private
+ for unicode, old_c in next, characters do
+ local oldwidth = old_c.width
+ if oldwidth ~= width then
+ -- Defining the tables in one step is more efficient
+ -- than adding fields later.
+ private = private + 1
+ local new_c
+ local commands = {
+ { "right", (width - oldwidth) / 2 },
+ { "slot", 1, private },
+ }
+ if height > 0 then
+ if depth > 0 then
+ new_c = {
+ width = width,
+ height = height,
+ depth = depth,
+ commands = commands,
+ }
+ else
+ new_c = {
+ width = width,
+ height = height,
+ commands = commands,
+ }
+ end
+ else
+ if depth > 0 then
+ new_c = {
+ width = width,
+ depth = depth,
+ commands = commands,
+ }
+ else
+ new_c = {
+ width = width,
+ commands = commands,
+ }
+ end
+ end
+ setmetatableindex(new_c,old_c)
+ characters[unicode] = new_c
+ additions[private] = old_c
+ end
+ end
+ for k, v in next, additions do
+ characters[k] = v
+ end
+ resources.private = private
+ elseif height > 0 and depth > 0 then
+ for unicode, old_c in next, characters do
+ old_c.height = height
+ old_c.depth = depth
+ end
+ elseif height > 0 then
+ for unicode, old_c in next, characters do
+ old_c.height = height
+ end
+ elseif depth > 0 then
+ for unicode, old_c in next, characters do
+ old_c.depth = depth
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "dimensions",
+ description = "force dimensions",
+ manipulators = {
+ base = manipulatedimensions,
+ node = manipulatedimensions,
+ }
+}
+
+-- for zhichu chen (see mailing list archive): we might add a few more variants
+-- in due time
+--
+-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
+--
+-- maybe:
+--
+-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
+--
+-- local gray = { "special", "pdf: /Tr1 gs .75 g" }
+-- local black = { "special", "pdf: /Tr0 gs 0 g" }
+
+-- sort of obsolete as we now have \showglyphs
+
+local push = { "push" }
+local pop = { "pop" }
+local gray = { "special", "pdf: .75 g" }
+local black = { "special", "pdf: 0 g" }
+
+local downcache = { } -- handy for huge cjk fonts
+local rulecache = { } -- handy for huge cjk fonts
+
+setmetatableindex(downcache,function(t,d)
+ local v = { "down", d }
+ t[d] = v
+ return v
+end)
+
+setmetatableindex(rulecache,function(t,h)
+ local v = { }
+ t[h] = v
+ setmetatableindex(v,function(t,w)
+ local v = { "rule", h, w }
+ t[w] = v
+ return v
+ end)
+ return v
+end)
+
+local function showboundingbox(tfmdata,key,value)
+ if value then
+ local vfspecials = backends.pdf.tables.vfspecials
+ local gray = vfspecials and (vfspecials.rulecolors[value] or vfspecials.rulecolors.palegray) or gray
+ local characters = tfmdata.characters
+ local resources = tfmdata.resources
+ local additions = { }
+ local private = resources.private
+ for unicode, old_c in next, characters do
+ private = private + 1
+ local width = old_c.width or 0
+ local height = old_c.height or 0
+ local depth = old_c.depth or 0
+ local new_c
+ if depth == 0 then
+ new_c = {
+ width = width,
+ height = height,
+ commands = {
+ push,
+ gray,
+ rulecache[height][width],
+ black,
+ pop,
+ { "slot", 1, private },
+ }
+ }
+ else
+ new_c = {
+ width = width,
+ height = height,
+ depth = depth,
+ commands = {
+ push,
+ downcache[depth],
+ gray,
+ rulecache[height+depth][width],
+ black,
+ pop,
+ { "slot", 1, private },
+ }
+ }
+ end
+ setmetatableindex(new_c,old_c)
+ characters[unicode] = new_c
+ additions[private] = old_c
+ end
+ for k, v in next, additions do
+ characters[k] = v
+ end
+ resources.private = private
+ end
+end
+
+registerotffeature {
+ name = "boundingbox",
+ description = "show boundingbox",
+ manipulators = {
+ base = showboundingbox,
+ node = showboundingbox,
+ }
+}
+
+-- -- for notosans but not general
+--
+-- do
+--
+-- 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,
+-- }
+-- }
+--
+-- 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,
+-- }
+-- }
+
+-- a handy helper (might change or be moved to another namespace)
+
+local nodepool = nodes.pool
+
+local new_special = nodepool.special
+local new_glyph = nodepool.glyph
+local new_rule = nodepool.rule
+local hpack_node = node.hpack
+
+local helpers = fonts.helpers
+local currentfont = font.current
+
+function helpers.addprivate(tfmdata,name,characterdata)
+ local properties = tfmdata.properties
+ local privates = properties.privates
+ local lastprivate = properties.lastprivate
+ if lastprivate then
+ lastprivate = lastprivate + 1
+ else
+ lastprivate = 0xE000
+ end
+ if not privates then
+ privates = { }
+ properties.privates = privates
+ end
+ if name then
+ privates[name] = lastprivate
+ end
+ properties.lastprivate = lastprivate
+ tfmdata.characters[lastprivate] = characterdata
+ if properties.finalized then
+ properties.lateprivates = true
+ end
+ return lastprivate
+end
+
+local function getprivatenode(tfmdata,name)
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ if privates then
+ local p = privates[name]
+ if p then
+ local char = tfmdata.characters[p]
+ local commands = char.commands
+ if commands then
+ local fake = hpack_node(new_special(commands[1][2]))
+ fake.width = char.width
+ fake.height = char.height
+ fake.depth = char.depth
+ return fake
+ else
+ -- todo: set current attribibutes
+ return new_glyph(properties.id,p)
+ end
+ end
+ end
+end
+
+helpers.getprivatenode = getprivatenode
+
+function helpers.hasprivate(tfmdata,name)
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ return privates and privates[name] or false
+end
+
+implement {
+ name = "getprivatechar",
+ arguments = "string",
+ actions = function(name)
+ context(getprivatenode(fontdata[currentfont()],name))
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua
new file mode 100644
index 00000000000..9ef0706d235
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua
@@ -0,0 +1,340 @@
+if not modules then modules = { } end modules ['font-fbk'] = {
+ 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 cos, tan, rad, format = math.cos, math.tan, math.rad, string.format
+local utfbyte, utfchar = utf.byte, utf.char
+
+--[[ldx--
+<p>This is very experimental code!</p>
+--ldx]]--
+
+local trace_combining_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)
+
+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 allocate = utilities.storage.allocate
+
+local fonts = fonts
+local handlers = fonts.handlers
+local constructors = fonts.constructors
+
+local otf = handlers.otf
+local afm = handlers.afm
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local unicodecharacters = characters.data
+local unicodefallbacks = characters.fallbacks
+
+local vf = handlers.vf
+local commands = vf.combiner.commands
+local push = vf.predefined.push
+local pop = vf.predefined.pop
+
+local force_composed = false
+local cache = { } -- we could make these weak
+local fraction = 0.15 -- 30 units for lucida
+
+-- 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
+
+local function composecharacters(tfmdata)
+ -- this assumes that slot 1 is self, there will be a proper self some day
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ local Xdesc = descriptions[utfbyte("X")]
+ local xdesc = descriptions[utfbyte("x")]
+ if Xdesc and xdesc then
+ local scale = parameters.factor or 1
+ local deltaxheight = scale * (Xdesc.boundingbox[4] - xdesc.boundingbox[4])
+ local extraxheight = fraction * deltaxheight -- maybe use compose value
+ local italicfactor = parameters.italicfactor or 0
+ local vfspecials = backends.tables.vfspecials --brr
+ local red, green, blue, black
+ if trace_combining_visualize then
+ red = vfspecials.red
+ green = vfspecials.green
+ blue = vfspecials.blue
+ black = vfspecials.black
+ end
+ local compose = fonts.goodies.getcompositions(tfmdata)
+ if compose and trace_combining_visualize then
+ report_combining("using compose information from goodies file")
+ end
+ local done = false
+ for i, c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory
+ if force_combining or not characters[i] then
+ local s = c.specials
+ if s and s[1] == 'char' then
+ local chr = s[2]
+ local charschr = characters[chr]
+ if charschr then
+ local cc = c.category
+ if cc == 'll' or cc == 'lu' or cc == 'lt' then -- characters.is_letter[cc]
+ local acc = s[3]
+ local t = { }
+ for k, v in next, charschr do
+ if k ~= "commands" then
+ t[k] = v
+ end
+ end
+ local charsacc = characters[acc]
+ -- local ca = charsacc.category
+ -- if ca == "mn" then
+ -- -- mark nonspacing
+ -- elseif ca == "ms" then
+ -- -- mark spacing combining
+ -- elseif ca == "me" then
+ -- -- mark enclosing
+ -- else
+ if not charsacc then -- fallback accents
+ acc = unicodefallbacks[acc]
+ charsacc = acc and characters[acc]
+ end
+ local chr_t = cache[chr]
+ if not chr_t then
+ chr_t = { "slot", 1, chr }
+ -- will be: chr_t = { "slot", 0, chr }
+ cache[chr] = chr_t
+ end
+ 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 }
+ -- will be: acc_t = { "slot", 0, acc }
+ cache[acc] = acc_t
+ end
+ 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
+ if compose then
+ local i_compose = compose[i]
+ local i_anchored = i_compose and i_compose.anchored
+ if i_anchored then
+ local c_compose = compose[chr]
+ local a_compose = compose[acc]
+ local c_anchors = c_compose and c_compose.anchors
+ local a_anchors = a_compose and a_compose.anchors
+ if c_anchors and a_anchors then
+ local c_anchor = c_anchors[i_anchored]
+ local a_anchor = a_anchors[i_anchored]
+ if c_anchor and a_anchor then
+ local cx = c_anchor.x or 0
+ local cy = c_anchor.y or 0
+ local ax = a_anchor.x or 0
+ local ay = a_anchor.y or 0
+ local dx = cx - ax
+ local dy = cy - ay
+ if trace_combining_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)
+ 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
+ -- }
+ else
+ t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, acc_t, pop, chr_t }
+ end
+ done = true
+ end
+ end
+ end
+ end
+ if not done then
+ -- can be sped up for scale == 1
+ local dx = (c_urx - a_urx - a_llx + c_llx)/2
+ local dd = (c_urx - c_llx)*italicfactor
+ if a_ury < 0 then
+ if trace_combining_visualize then
+ t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t }
+ else
+ t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t }
+ end
+ elseif c_ury > a_lly then -- messy test
+ local dy
+ if compose then
+ -- experimental: we could use sx but all that testing
+ -- takes time and code
+ dy = compose[i]
+ if dy then
+ dy = dy.dy
+ end
+ if not dy then
+ dy = compose[acc]
+ if dy then
+ dy = dy and dy.dy
+ end
+ end
+ if not dy then
+ dy = compose.dy
+ end
+ if not dy then
+ dy = - deltaxheight + extraxheight
+ elseif dy > -1.5 and dy < 1.5 then
+ -- we assume a fraction of (percentage)
+ dy = - dy * deltaxheight
+ else
+ -- we assume fontunits (value smaller than 2 make no sense)
+ dy = - dy * scale
+ end
+ else
+ dy = - deltaxheight + extraxheight
+ end
+ if trace_combining_visualize then
+ t.commands = { push, {"right", dx+dd}, {"down", dy}, green, acc_t, black, pop, chr_t }
+ else
+ t.commands = { push, {"right", dx+dd}, {"down", dy}, acc_t, pop, chr_t }
+ end
+ else
+ if trace_combining_visualize then
+ t.commands = { push, {"right", dx+dd}, blue, acc_t, black, pop, chr_t }
+ else
+ t.commands = { push, {"right", dx+dd}, acc_t, pop, chr_t }
+ end
+ end
+ end
+ else
+ t.commands = { chr_t } -- else index mess
+ end
+ else
+ if trace_combining_define then
+ report_combining("%C becomes simplified %C",i,chr)
+ end
+ t.commands = { chr_t } -- else index mess
+ end
+ done = true
+ characters[i] = t
+ local d = { }
+ for k, v in next, descriptions[chr] do
+ d[k] = v
+ end
+ descriptions[i] = d
+ end
+ end
+ end
+ end
+ end
+ if done then
+ properties.virtualized = true
+ end
+ end
+end
+
+registerotffeature {
+ name = "compose",
+ description = "additional composed characters",
+ manipulators = {
+ base = composecharacters,
+ node = composecharacters,
+ }
+}
+
+registerafmfeature {
+ name = "compose",
+ description = "additional composed characters",
+ manipulators = {
+ base = composecharacters,
+ node = composecharacters,
+ }
+}
+
+vf.helpers.composecharacters = composecharacters
+
+-- This installs the builder into the regular virtual font builder,
+-- which only makes sense as demo.
+
+commands["compose.trace.enable"] = function()
+ trace_combining_visualize = true
+end
+
+commands["compose.trace.disable"] = function()
+ trace_combining_visualize = false
+end
+
+commands["compose.force.enable"] = function()
+ force_combining = true
+end
+
+commands["compose.force.disable"] = function()
+ force_combining = false
+end
+
+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
+
+-- vf builder
+
+-- {'special', 'pdf: q ' .. s .. ' 0 0 '.. s .. ' 0 0 cm'},
+-- {'special', 'pdf: q 1 0 0 1 ' .. -w .. ' ' .. -h .. ' cm'},
+-- {'special', 'pdf: /Fm\XX\space Do'},
+-- {'special', 'pdf: Q'},
+-- {'special', 'pdf: Q'},
+
+-- new and experimental
+
+local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+local noflags = { }
+
+local char_specification = {
+ type = "ligature",
+ features = everywhere,
+ data = characters.splits.char,
+ order = { "char-ligatures" },
+ flags = noflags,
+ prepend = true,
+}
+
+local compat_specification = {
+ type = "ligature",
+ features = everywhere,
+ data = characters.splits.compat,
+ order = { "compat-ligatures" },
+ flags = noflags,
+ prepend = true,
+}
+
+otf.addfeature("char-ligatures", char_specification) -- xlig (extra)
+otf.addfeature("compat-ligatures",compat_specification) -- plig (pseudo)
+
+registerotffeature { name = 'char-ligatures', description = 'unicode char specials to ligatures' }
+registerotffeature { name = 'compat-ligatures', description = 'unicode compat specials to ligatures' }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi
new file mode 100644
index 00000000000..dade7049488
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi
@@ -0,0 +1,356 @@
+%D \module
+%D [ file=font-sty,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=features,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Features}
+
+\unprotect
+
+%D Feature management.
+%D
+%D \starttyping
+%D \definefontfeature[smallcaps][smcp=yes,script=latn]
+%D \definefontfeature[smallcaps][SmallCapitals=yes,script=latn]
+%D \definefontfeature[smallcaps][Small Capitals=yes,script=latn]
+%D \definefontfeature[smallcaps][small capitals=yes,script=latn]
+%D \definefontfeature[smallcaps][smallcapitals=yes,script=latn]
+%D
+%D \definedfont[cambria*smallcaps] test
+%D
+%D \starttext
+%D \definefontfeature[basekerned][default][mode=base]
+%D \definefontfeature[nodekerned][default][mode=node]
+%D \definefontfeature[nonekerned][default][mode=base,kern=no]
+%D \setupcolors[state=start]
+%D \startoverlay
+%D {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }}
+%D {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }}
+%D {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }}
+%D \stopoverlay
+%D \stoptext
+%D
+%D \enabletrackers[otf.kerns]
+%D
+%D \definefontfeature[withkern][default][mode=node]
+%D \definefontfeature[nokern] [default][mode=node,kern=no]
+%D \definefontfeature[single] [default][mode=node,cpsp=yes]
+%D \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no]
+%D
+%D {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D \stoptyping
+
+% \definefontfeature[slanted] [default][slant=.25]
+% \definefontfeature[stretched][default][stretch=2]
+%
+% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop
+% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop
+%
+% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes]
+% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn]
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular][features=default]
+% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif
+% \stoptypescript
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular*default]
+% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps]
+% \stoptypescript
+%
+% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface]
+%
+% \starttext
+% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl
+% \stoptext
+%
+% \definefontfeature
+% [default-base]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes]
+% \definefontfeature
+% [default-node]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node]
+% \definefontfeature
+% [default-none]
+% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes]
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \definefontfeature[superdefault][default][compose=yes]
+%
+% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683}
+% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683}
+
+\unexpanded\def\definefontfeature
+ {\dotripleargument\font_basics_define_font_feature}
+
+\def\font_basics_define_font_feature[#featureset][#parent][#settings]%
+ {\clf_definefontfeature{#featureset}{#parent}{#settings}}
+
+\unexpanded\def\fontfeatureslist
+ {\dodoubleargument\font_basics_features_list}
+
+\def\font_basics_features_list[#name][#separator]% todo: arg voor type
+ {\clf_featurelist{#name}{\detokenize{#separator}}}
+
+\attribute\zerocount\zerocount % first in list, so fast match
+
+% beware: these are global features on top of existing font features
+
+\let\currentfeature \s!current
+\let\m_font_feature_list \s!current
+\let\m_font_feature_asked\empty
+
+\newconstant\c_font_feature_state
+
+% hashing at this end is slower
+
+\unexpanded\def\addfeature {\doifelsenextoptionalcs\font_feature_add_yes \font_feature_add_nop }
+\unexpanded\def\subtractfeature {\doifelsenextoptionalcs\font_feature_subtract_yes \font_feature_subtract_nop }
+\unexpanded\def\replacefeature {\doifelsenextoptionalcs\font_feature_replace_yes \font_feature_replace_nop }
+\unexpanded\def\resetandaddfeature{\doifelsenextoptionalcs\font_feature_reset_add_yes\font_feature_reset_add_nop}
+\unexpanded\def\feature {\doifelsenextoptionalcs\font_feature_yes \font_feature_nop }
+
+\unexpanded\def\font_feature_add_yes [#feature]{\edef\m_font_feature_asked{#feature}\font_feature_add}
+\unexpanded\def\font_feature_add_nop #feature{\edef\m_font_feature_asked{#feature}\font_feature_add}
+
+\unexpanded\def\font_feature_subtract_yes [#feature]{\edef\m_font_feature_asked{#feature}\font_feature_subtract}
+\unexpanded\def\font_feature_subtract_nop #feature{\edef\m_font_feature_asked{#feature}\font_feature_subtract}
+
+\unexpanded\def\font_feature_replace_yes [#feature]{\edef\m_font_feature_asked{#feature}\font_feature_replace}
+\unexpanded\def\font_feature_replace_nop #feature{\edef\m_font_feature_asked{#feature}\font_feature_replace}
+
+\unexpanded\def\font_feature_reset_add_yes[#feature]{\edef\m_font_feature_asked{#feature}\font_feature_reset_add}
+\unexpanded\def\font_feature_reset_add_nop #feature{\edef\m_font_feature_asked{#feature}\font_feature_reset_add}
+
+\let\doaddfeature \font_feature_add_nop % low level faster ones
+\let\dosubtractfeature \font_feature_subtract_nop
+\let\doreplacefeature \font_feature_replace_nop
+\let\doresetandaddfeature\font_feature_reset_add_nop
+
+\unexpanded\def\font_feature_add
+ {\ifnum\c_font_feature_state=\plusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_add_indeed
+ \fi
+ \else
+ \font_feature_add_indeed
+ \fi}
+
+\unexpanded\def\font_feature_add_indeed
+ {\clf_addfeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list+\m_font_feature_asked}% also + at the lua end
+ \c_font_feature_state\plusone
+ \let\currentfeature\m_font_feature_asked}
+
+\unexpanded\def\font_feature_subtract
+ {\ifnum\c_font_feature_state=\minusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_subtract_indeed
+ \fi
+ \else
+ \font_feature_subtract_indeed
+ \fi}
+
+\unexpanded\def\font_feature_subtract_indeed
+ {\clf_subtractfeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list-\m_font_feature_asked}% also - at the lua end
+ \c_font_feature_state\minusone
+ \let\currentfeature\m_font_feature_asked}
+
+\unexpanded\def\font_feature_replace
+ {\ifnum\c_font_feature_state=\zerocount
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_replace_indeed
+ \fi
+ \else
+ \font_feature_replace_indeed
+ \fi}
+
+\unexpanded\def\font_feature_replace_indeed
+ {\clf_replacefeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list=\m_font_feature_asked}% also = at the lua end
+ \c_font_feature_state\zerocount
+ \let\currentfeature\m_font_feature_asked}
+
+\unexpanded\def\resetfeature
+ {\ifx\currentfeature\s!current \else
+ \font_feature_reset_indeed
+ \fi}
+
+\unexpanded\def\font_feature_reset_indeed
+ {\let\m_font_feature_asked\empty
+ \let\currentfeature \s!current
+ \let\m_font_feature_list \s!current
+ \clf_resetfeature}
+
+\unexpanded\def\revivefeature
+ {\ifx\currentfeature\s!current \else
+ \font_feature_revive_indeed
+ \fi}
+
+\unexpanded\def\font_feature_revive_indeed
+ {\clf_revivefeature{\m_font_feature_list}}
+
+\unexpanded\def\font_feature_reset_add
+ {\ifnum\c_font_feature_state=\plusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_reset_add_indeed
+ \fi
+ \else
+ \font_feature_reset_add_indeed
+ \fi}
+
+\unexpanded\def\font_feature_reset_add_indeed
+ {\clf_addfeature{\s!current}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\s!current+\m_font_feature_asked}% also + at the lua end
+ \c_font_feature_state\plusone
+ \let\currentfeature\m_font_feature_asked}
+
+\installcorenamespace{featureyes}
+\installcorenamespace{featurenop}
+
+%\unexpanded\def\font_feature_yes[#method]{\csname\??featureyes\ifcsname\??featureyes#method\endcsname#method\else\s!unknown\fi\endcsname}
+%\unexpanded\def\font_feature_nop #method{\csname\??featurenop\ifcsname\??featurenop#method\endcsname#method\else\s!unknown\fi\endcsname}
+
+\unexpanded\def\font_feature_yes[#method]{\begincsname\??featureyes#method\endcsname}
+\unexpanded\def\font_feature_nop #method{\begincsname\??featurenop#method\endcsname}
+
+\letvalue{\??featureyes +}\addfeature
+\letvalue{\??featurenop +}\addfeature
+\letvalue{\??featureyes -}\subtractfeature
+\letvalue{\??featurenop -}\subtractfeature
+\letvalue{\??featureyes =}\replacefeature
+\letvalue{\??featurenop =}\replacefeature
+\letvalue{\??featureyes !}\resetandaddfeature
+\letvalue{\??featurenop !}\resetandaddfeature
+\letvalue{\??featureyes >}\revivefeature
+\letvalue{\??featurenop >}\revivefeature
+\letvalue{\??featureyes <}\resetfeature
+\letvalue{\??featurenop <}\resetfeature
+
+\letvalue{\??featureyes\v!more }\addfeature % add set to previous set and combine with font set
+\letvalue{\??featurenop\v!more }\addfeature
+\letvalue{\??featureyes\v!less }\subtractfeature % subtract set from previous set and combine with font set
+\letvalue{\??featurenop\v!less }\subtractfeature
+\letvalue{\??featureyes\v!new }\replacefeature % replace font set
+\letvalue{\??featurenop\v!new }\replacefeature
+\letvalue{\??featureyes\v!reset }\resetfeature % forget sets and revert to font set
+\letvalue{\??featurenop\v!reset }\resetfeature
+\letvalue{\??featureyes\v!default}\revivefeature % make sure the current set is used on top of the font set
+\letvalue{\??featurenop\v!default}\revivefeature
+\letvalue{\??featureyes\v!old }\revivefeature
+\letvalue{\??featurenop\v!old }\revivefeature
+\letvalue{\??featureyes\v!local }\resetandaddfeature
+\letvalue{\??featurenop\v!local }\resetandaddfeature
+\letvalue{\??featureyes\s!unknown}\empty
+\letvalue{\??featurenop\s!unknown}\empty
+
+% just for old times sake:
+
+\unexpanded\def\featureattribute#feature%
+ {\clf_featureattribute{#feature}}
+
+\unexpanded\def\setfontfeature#feature%
+ {\edef\currentfeature{#feature}%
+ \let\m_font_feature_list\currentfeature
+ \clf_setfontfeature{\currentfeature}}
+
+\let\resetfontfeature\resetfeature
+
+% these are obsolete (don't use them any longer)
+
+\let\addfontfeaturetoset \font_feature_add_nop
+\let\subtractfontfeaturefromset \font_feature_subtract_nop
+\let\addfontfeaturetofont \font_feature_add_nop
+\let\subtractfontfeaturefromfont\font_feature_subtract_nop
+
+\let\setff\setfontfeature
+\let\addfs\addfontfeaturetoset
+\let\subfs\subtractfontfeaturefromset
+\let\addff\addfontfeaturetofont
+\let\subff\subtractfontfeaturefromfont
+
+%D \macros
+%D {os}
+%D
+%D In good old \TEX, the old style numerals were often taken
+%D from the math fonts. No longer.
+
+\definefontfeature
+ [just-os]
+ [mode=node,onum=yes]
+
+%unexpanded\def\sc{\setfontfeature{smallcaps}}
+\unexpanded\def\os{\setfontfeature{just-os}}
+
+% \doifelsecurrentfonthasfeature{smcp}{YES}{NO}
+% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
+% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
+
+\def\doifelsecurrentfonthasfeature#feature%
+ {\clf_doifelsecurrentfonthasfeature{#feature}}
+
+\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature
+
+% new:
+
+\clf_registerlanguagefeatures
+
+% also new
+
+\unexpanded\def\useaddfontfeatureparameter#namespace% faster local variant
+ {\edef\m_font_feature_asked{#namespace\c!features}%
+ \ifx\m_font_feature_asked\empty\else
+ \font_feature_add
+ \fi}
+
+% let's put this here:
+
+\unexpanded\def\slashedzero
+ {\dontleavehmode
+ \begingroup
+ %\addff{zero}
+ \font_feature_add_nop{zero}%
+ 0%
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi
new file mode 100644
index 00000000000..0bfc07b6c74
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi
@@ -0,0 +1,454 @@
+%D \module
+%D [ file=font-fil,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Classes and Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Classes and Files}
+
+\unprotect
+
+%D Personally I think that using \TEX\ macro packages is
+%D complicated by the way fonts are handled. Apart from the
+%D many encodings, we also deal with different naming schemes.
+%D Confronted with this problem, I decided to change the
+%D definitions into:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm] [tf=Times-Roman at 12pt]
+%D \stoptyping
+%D
+%D combined with for instance:
+%D
+%D \starttyping
+%D \definefontsynonym [Times-Roman] [tir]
+%D \stoptyping
+
+% \definetypeface[palatino][rm][serif][palatino,allbold][default]
+%
+% \startfontclass[palatino]
+% \definefontsynonym [Serif] [SerifBold]
+% \definefontsynonym [SerifItalic] [SerifBoldItalic]
+% \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
+% \definefontsynonym [SerifCaps] [SerifBold]
+% \stopfontclass
+%
+% \setupbodyfont[palatino]
+
+\let\fontclass\empty
+
+\unexpanded\def\startfontclass
+ {\dosingleempty\font_basics_start_font_class}
+
+\def\font_basics_start_font_class[#class]%
+ {\pushmacro\fontclass
+ \doifelse{#class}\v!each
+ {\let\fontclass\empty}
+ {\doifsomething{#class}{\def\fontclass{#class}}}}
+
+\unexpanded\def\stopfontclass
+ {\popmacro\fontclass}
+
+\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
+
+%D \macros
+%D {definefontsynonym, doifelsefontsynonym,
+%D expandfontsynonym, truefontname, truefontdata}
+%D
+%D While looking for fonts, fontsynonyms are used for accessing
+%D the files!
+%D
+%D \starttyping
+%D \definefontsynonym[Serif][Lucida-Bright]
+%D \definefontsynonym[Lucida-Bright][lbr][encoding=texnansi]
+%D \stoptyping
+
+\installcorenamespace {fontfile} % file synonyms
+
+\let\m_font_name\empty
+\let\m_font_file\empty
+
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+
+\unexpanded\def\definefontsynonym[#name]#crap[#file]%
+ {\edef\m_font_name{#name}%
+ \edef\m_font_file{#file}%
+ \ifx\fontclass\empty
+ \expandafter\font_basics_define_font_synonym_nop
+ \else
+ \expandafter\font_basics_define_font_synonym_yes
+ \fi}
+
+\def\font_basics_define_font_synonym_nop
+ {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
+ \doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil}
+
+\def\font_basics_define_font_synonym_yes
+ {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
+ \doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil}
+
+\def\font_basics_define_font_synonym_nop_opt[#specification]%
+ {\let\p_features \undefined
+ \let\p_fallbacks \undefined
+ \let\p_goodies \undefined
+ \let\p_designsize\undefined
+ \expandafter\font_basics_get_font_parameter_nop#specification,]=,}
+
+\def\font_basics_define_font_synonym_yes_opt[#specification]%
+ {\let\p_features \undefined
+ \let\p_fallbacks \undefined
+ \let\p_goodies \undefined
+ \let\p_designsize\undefined
+ \expandafter\font_basics_get_font_parameter_yes#specification,]=,}
+
+\def\font_basics_get_font_parameter_nop#key=#value,%
+ {\if]#key%
+ \font_basics_get_font_parameter_nop_finish
+ \else
+ \expandafter\normaldef\csname p_#key\endcsname{#value}%
+ \expandafter\font_basics_get_font_parameter_nop
+ \fi}
+
+\def\font_basics_get_font_parameter_yes#key=#value,%
+ {\if]#key%
+ \font_basics_get_font_parameter_yes_finish
+ \else
+ \expandafter\normaldef\csname p_#key\endcsname{#value}%
+ \expandafter\font_basics_get_font_parameter_yes
+ \fi}
+
+% helpers, some day these will be toks and counts
+
+% \def\fntsetdefname {\global\let\somefontname\defaultfontfile}
+% \def\fntsetsomename{\gdef\somefontname} % takes argument
+% \def\fntsetnopsize {\let\somefontsize\empty}
+% \def\fntsetsomesize{\def\somefontsize} % takes argument
+
+% happens later, else mkvi parsing gets into troubles
+
+% end of helpers
+
+% we could collect them in one macro (but no expansion)
+
+\def\font_basics_define_font_synonym_nop_nil
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_define_font_synonym_yes_nil
+ {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_get_font_parameter_nop_finish
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\p_features
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\p_goodies
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize}
+
+\def\font_basics_get_font_parameter_yes_finish
+ {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize}
+
+%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
+%
+%\defineclassfontsynonym [KopFont] [officina] [SerifBold]
+
+\unexpanded\def\defineclassfontsynonym
+ {\dotripleargument\font_basics_define_class_font_synonym}
+
+%\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]}
+
+\def\font_basics_define_class_font_synonym[#tag][#class][#fileortag]% needs testing
+ {\expandafter\normaldef\csname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}%
+ \font_basics_define_font_synonym_yes_nil}
+
+\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
+
+\unexpanded\def\setupfontsynonym
+ {\dodoubleempty\dosetupfontsynonym}
+
+\def\dosetupfontsynonym[#name][#settings]% not yet supported, will do when needed
+ {}
+
+% todo: replace * by ... less messy with features
+
+\def\truefontname#name%
+ {\expandafter\font_helpers_true_fontname#name*\empty*\relax}
+
+\def\font_helpers_true_fontname#name*#first#rest*#crap\relax
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \else\ifcsname\??fontfile#name\endcsname
+ \ifx#first\empty
+ %\expandafter\truefontname\csname\??fontfile#name\endcsname
+ \expandafter\truefontname\lastnamedcs
+ \else
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname*#first#rest%
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
+ \fi
+ \else
+ #name\ifx#first\empty\else*#first#rest\fi
+ \fi\fi\fi}
+
+\def\font_helpers_true_fontname_check#name%
+ {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax}
+
+\def\font_helpers_true_fontname_check_indeed#name*#crap\relax
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \else\ifcsname\??fontfile#name\endcsname
+ %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\lastnamedcs
+ \else
+ #name%
+ \fi\fi\fi}
+
+\def\expandfontsynonym#command#name% one level expansion
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\fontclass#name\endcsname}%
+ \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
+ \else\ifcsname\??fontfile\defaultfontclass#2\endcsname
+ %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\defaultfontclass#name\endcsname}%
+ \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
+ \fi\fi}
+
+\def\doifelsefontsynonym#name%
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \singleexpandafter\firstoftwoarguments
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\let\doiffontsynonymelse\doifelsefontsynonym
+
+%D \macros
+%D {tracedfontname}
+%D
+%D A goody:
+
+\def\tracedfontname#name%
+ {#name\ifcsname\??fontfile\fontclass#name\endcsname
+ %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
+ \expandafter\tracedfontname\lastnamedcs
+ \else\ifcsname\??fontfile#name\endcsname
+ %\expandafter\tracedfontname\csname\??fontfile#name\endcsname
+ \expandafter\tracedfontname\lastnamedcs
+ \fi\fi}
+
+%D \macros
+%D {fontclass, defaultfontclass}
+%D
+%D The fontclass model was introduced a while after we implement
+%D the basic font model and at that time we still defaulted to
+%D no model at all. Nowadays we default to the \type {modern}
+%D fontclass.
+
+\let\fontclass \empty
+\let\defaultfontclass\empty
+
+\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting
+ {\ifcsname\??fontfile#class#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}%
+ \else\ifcsname\??fontfile#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#name\endcsname}%
+ \else
+ #2%
+ \fi\fi}
+
+%D Files or names can have properties and these need to be consulted
+%D at some point. They can inherit them.
+
+% Why these expanded and rscale not ... maybe not worth the trouble (delayed
+% expansion actually would be better i.e. macros in feature specs). Test
+% without pre-expansion.
+
+\def\font_helpers_update_font_class_parameters
+ {\edef\m_font_class_direction {\begincsname\??fontclass\fontclass\fontstyle\s!direction \endcsname}%
+ \edef\m_font_class_features {\begincsname\??fontclass\fontclass\fontstyle\s!features \endcsname}%
+ \edef\m_font_class_fallbacks {\begincsname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname}%
+ \edef\m_font_class_goodies {\begincsname\??fontclass\fontclass\fontstyle\s!goodies \endcsname}%
+ \edef\m_font_class_designsize{\begincsname\??fontclass\fontclass\fontstyle\s!designsize\endcsname}}
+
+% resolve
+
+% \def\font_helpers_set_features_yes#name%
+% {\ifcsname\??fontfile\fontclass#name\s!features \endcsname \edef\m_font_features % class + symbolic_name
+% {\csname\??fontfile\fontclass#name\s!features \endcsname}\else
+% \ifcsname\??fontfile #name\s!features \endcsname \edef\m_font_features % symbolic_name
+% {\csname\??fontfile #name\s!features \endcsname}\else
+% \ifcsname\??fontfile\fontclass #name\endcsname\expandafter\font_helpers_set_features_yes % class + parent_name
+% \csname\??fontfile\fontclass #name\endcsname \else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_yes % parent_name
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_features\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_fallbacks_yes#name%
+% {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks
+% {\csname\??fontfile\fontclass#name\s!fallbacks\endcsname}\else
+% \ifcsname\??fontfile #name\s!fallbacks\endcsname \edef\m_font_fallbacks
+% {\csname\??fontfile #name\s!fallbacks\endcsname}\else
+% \ifcsname\??fontfile\fontclass #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
+% \csname\??fontfile\fontclass #name\endcsname \else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_fallbacks\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_goodies_yes#name%
+% {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname \edef\m_font_goodies
+% {\csname\??fontfile\fontclass#name\s!goodies \endcsname}\else
+% \ifcsname\??fontfile #name\s!goodies \endcsname \edef\m_font_goodies
+% {\csname\??fontfile #name\s!goodies \endcsname}\else
+% \ifcsname\??fontfile\fontclass #name\endcsname \expandafter\font_helpers_set_goodies_yes
+% \csname\??fontfile\fontclass #name\endcsname \else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_yes
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_goodies\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_designsize_yes#name%
+% {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize
+% {\csname\??fontfile\fontclass#name\s!designsize\endcsname}\else
+% \ifcsname\??fontfile #name\s!designsize\endcsname \edef\m_font_designsize
+% {\csname\??fontfile #name\s!designsize\endcsname}\else
+% \ifcsname\??fontfile\fontclass #name\endcsname \expandafter\font_helpers_set_designsize_yes
+% \csname\??fontfile\fontclass #name\endcsname \else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_yes
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_designsize\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_features_nop#name%
+% {\ifcsname\??fontfile#name\s!features \endcsname \edef\m_font_features
+% {\csname\??fontfile#name\s!features \endcsname}\else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_nop
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_features\empty\fi\fi}
+%
+% \def\font_helpers_set_fallbacks_nop#name%
+% {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks
+% {\csname\??fontfile#name\s!fallbacks\endcsname}\else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_nop
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_fallbacks\empty\fi\fi}
+%
+% \def\font_helpers_set_goodies_nop#name%
+% {\ifcsname\??fontfile#name\s!goodies \endcsname \edef\m_font_goodies
+% {\csname\??fontfile#name\s!goodies \endcsname}\else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_nop
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_goodies\empty\fi\fi}
+%
+% \def\font_helpers_set_designsize_nop#name%
+% {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize
+% {\csname\??fontfile#name\s!designsize\endcsname}\else
+% \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_nop
+% \csname\??fontfile #name\endcsname \else
+% \let\m_font_designsize\empty\fi\fi}
+
+\def\font_helpers_set_features_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else % class + symbolic_name
+ \ifcsname\??fontfile #name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else % symbolic_name
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % class + parent_name
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % parent_name
+ \let\m_font_features\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_fallbacks_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+ \ifcsname\??fontfile #name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else
+ \let\m_font_fallbacks\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_goodies_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\else
+ \ifcsname\??fontfile #name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\else
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else
+ \let\m_font_goodies\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_designsize_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+ \ifcsname\??fontfile #name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+ \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else
+ \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else
+ \let\m_font_designsize\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_features_nop#name%
+ {\ifcsname\??fontfile#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_features_nop\lastnamedcs \else
+ \let\m_font_features\empty\fi\fi}
+
+\def\font_helpers_set_fallbacks_nop#name%
+ {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_fallbacks_nop\lastnamedcs \else
+ \let\m_font_fallbacks\empty\fi\fi}
+
+\def\font_helpers_set_goodies_nop#name%
+ {\ifcsname\??fontfile#name\s!goodies\endcsname \edef\m_font_goodies{\lastnamedcs}\else
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_goodies_nop\lastnamedcs \else
+ \let\m_font_goodies\empty\fi\fi}
+
+\def\font_helpers_set_designsize_nop#name%
+ {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+ \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_designsize_nop\lastnamedcs \else
+ \let\m_font_designsize\empty\fi\fi}
+
+\def\font_helpers_update_font_parameters_yes
+ {\font_helpers_set_features_yes \somefontname
+ \font_helpers_set_fallbacks_yes \somefontname
+ \font_helpers_set_goodies_yes \somefontname
+ \font_helpers_set_designsize_yes\somefontname}
+
+\def\font_helpers_update_font_parameters_nop
+ {\font_helpers_set_features_nop \somefontname
+ \font_helpers_set_fallbacks_nop \somefontname
+ \font_helpers_set_goodies_nop \somefontname
+ \font_helpers_set_designsize_nop\somefontname}
+
+\def\font_helpers_update_font_parameters
+ {\ifx\fontclass\empty\font_helpers_update_font_parameters_nop\else\font_helpers_update_font_parameters_yes\fi}
+
+\installcorenamespace{fontclass}
+
+% we can pack them
+
+\unexpanded\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction%
+ {\setxvalue{\??fontclass\fontclass#style\s!rscale }{#rscale}%
+ \setxvalue{\??fontclass\fontclass#style\s!features }{#features}%
+ \setxvalue{\??fontclass\fontclass#style\s!fallbacks }{#fallbacks}%
+ \setxvalue{\??fontclass\fontclass#style\s!goodies }{#goodies}%
+ \setxvalue{\??fontclass\fontclass#style\s!designsize}{#designsize}%
+ \setxvalue{\??fontclass\fontclass#style\s!direction }{#direction}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua
new file mode 100644
index 00000000000..daa072b4bc2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua
@@ -0,0 +1,255 @@
+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 fonts = fonts
+local nodes = nodes
+
+local nuts = nodes.nuts -- context abstraction of direct nodes
+
+local traverse_id = nuts.traverse_id
+local remove_node = nuts.remove
+local free_node = nuts.free
+
+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
+
+function nodes.handlers.nodepass(head)
+ 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
+ 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
+ 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)
+ if not redundant then
+ redundant = { n }
+ else
+ redundant[#redundant+1] = n
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ 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 b > 0 then
+ for i=1,b 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
+ free_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
+ 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) or head
+ end
+ end
+ end
+ if basemodepass and #basefonts > 0 then
+ for i=1,#basefonts 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 not 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)
+ if head then
+ head = nodepass(head)
+ 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/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua b/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua
new file mode 100644
index 00000000000..23bbad42f63
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua
@@ -0,0 +1,917 @@
+if not modules then modules = { } end modules ['font-gds'] = {
+ version = 1.000,
+ comment = "companion to font-gds.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- depends on ctx
+
+local type, next, tonumber = type, next, tonumber
+local gmatch, lower, find, splitup = string.gmatch, string.lower, string.find, string.splitup
+
+local fonts = fonts
+local nodes = nodes
+local attributes = attributes
+local node = node
+
+local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+local report_goodies = logs.reporter("fonts","goodies")
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+
+local texsp = tex.sp
+local formatters = string.formatters
+
+local otf = fonts.handlers.otf
+local afm = fonts.handlers.afm
+local tfm = fonts.handlers.tfm
+
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+local registertfmfeature = tfm.features.register
+
+local fontgoodies = fonts.goodies or { }
+fonts.goodies = fontgoodies
+
+local typefaces = fonts.typefaces or allocate()
+fonts.typefaces = typefaces
+
+local data = fontgoodies.data or allocate()
+fontgoodies.data = data
+
+local list = fontgoodies.list or { }
+fontgoodies.list = list -- no allocate as we want to see what is there
+
+local addotffeature = otf.enhancers.addfeature
+
+local findfile = resolvers.findfile
+
+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
+
+function fontgoodies.report(what,trace,goodies)
+ if trace_goodies or trace then
+ local whatever = goodies[what]
+ if whatever then
+ report_goodies("goodie %a found in %a",what,goodies.name)
+ end
+ end
+end
+
+local function loadgoodies(filename) -- maybe a merge is better
+ local goodies = data[filename] -- we assume no suffix is given
+ if goodies ~= nil then
+ -- found or tagged unfound
+ elseif type(filename) == "string" then
+ local fullname = findfile(file.addsuffix(filename,"lfg")) or "" -- prefered suffix
+ if fullname == "" then
+ fullname = findfile(file.addsuffix(filename,"lua")) or "" -- fallback suffix
+ end
+ if fullname == "" then
+ report_goodies("goodie file '%s.lfg' is not found",filename)
+ data[filename] = false -- signal for not found
+ else
+ goodies = dofile(fullname) or false
+ if not goodies then
+ report_goodies("goodie file %a is invalid",fullname)
+ return nil
+ elseif trace_goodies then
+ report_goodies("goodie file %a is loaded",fullname)
+ end
+ goodies.name = goodies.name or "no name"
+ for name, fnc in next, list do
+ if trace_goodies then
+ report_goodies("handling goodie %a",name)
+ end
+ fnc(goodies)
+ end
+ goodies.initialized = true
+ data[filename] = goodies
+ end
+ end
+ return goodies
+end
+
+function fontgoodies.register(name,fnc) -- will be a proper sequencer
+ list[name] = fnc
+end
+
+fontgoodies.load = loadgoodies
+
+-- register goodies file
+
+local function setgoodies(tfmdata,value)
+ local goodies = tfmdata.goodies
+ if not goodies then -- actually an error
+ goodies = { }
+ tfmdata.goodies = goodies
+ end
+ for filename in gmatch(value,"[^, ]+") do
+ -- we need to check for duplicates
+ local ok = loadgoodies(filename)
+ if ok then
+ if trace_goodies then
+ report_goodies("assigning goodie %a",filename)
+ end
+ goodies[#goodies+1] = ok
+ end
+ end
+end
+
+-- this will be split into good-* files and this file might become good-ini.lua
+
+-- featuresets
+
+local function flattenedfeatures(t,tt)
+ -- first set value dominates
+ local tt = tt or { }
+ for i=1,#t do
+ local ti = t[i]
+ if type(ti) == "table" then
+ flattenedfeatures(ti,tt)
+ elseif tt[ti] == nil then
+ tt[ti] = true
+ end
+ end
+ for k, v in next, t do
+ if type(k) ~= "number" then -- not tonumber(k)
+ if type(v) == "table" then
+ flattenedfeatures(v,tt)
+ elseif tt[k] == nil then
+ tt[k] = v
+ end
+ end
+ end
+ return tt
+end
+
+-- fonts.features.flattened = flattenedfeatures
+
+local function prepare_features(goodies,name,set)
+ if set then
+ local ff = flattenedfeatures(set)
+ local fullname = goodies.name .. "::" .. name
+ local n, s = fonts.specifiers.presetcontext(fullname,"",ff)
+ goodies.featuresets[name] = s -- set
+ if trace_goodies then
+ report_goodies("feature set %a gets number %a and name %a",name,n,fullname)
+ end
+ return n
+ end
+end
+
+fontgoodies.prepare_features = prepare_features
+
+local function initialize(goodies,tfmdata)
+ local featuresets = goodies.featuresets
+ local goodiesname = goodies.name
+ if featuresets then
+ if trace_goodies then
+ report_goodies("checking featuresets in %a",goodies.name)
+ end
+ for name, set in next, featuresets do
+ prepare_features(goodies,name,set)
+ end
+ end
+end
+
+fontgoodies.register("featureset",initialize)
+
+local function setfeatureset(tfmdata,set,features)
+ local goodies = tfmdata.goodies -- shared ?
+ if goodies then
+ local properties = tfmdata.properties
+ local what
+ for i=1,#goodies do
+ -- last one wins
+ local g = goodies[i]
+ what = g.featuresets and g.featuresets[set] or what
+ end
+ if what then
+ for feature, value in next, what do
+ if features[feature] == nil then
+ features[feature] = value
+ end
+ end
+ properties.mode = what.mode or properties.mode
+ end
+ end
+end
+
+-- postprocessors (we could hash processor and share code)
+
+function fontgoodies.registerpostprocessor(tfmdata,f,prepend)
+ local postprocessors = tfmdata.postprocessors
+ if not postprocessors then
+ tfmdata.postprocessors = { f }
+ elseif prepend then
+ table.insert(postprocessors,f,1)
+ else
+ table.insert(postprocessors,f)
+ end
+end
+
+local function setpostprocessor(tfmdata,processor)
+ local goodies = tfmdata.goodies
+ if goodies and type(processor) == "string" then
+ local found = { }
+ local asked = utilities.parsers.settings_to_array(processor)
+ for i=1,#goodies do
+ local g = goodies[i]
+ local p = g.postprocessors
+ if p then
+ for i=1,#asked do
+ local a = asked[i]
+ local f = p[a]
+ if type(f) == "function" then
+ found[a] = f
+ end
+ end
+ end
+ end
+ local postprocessors = tfmdata.postprocessors or { }
+ for i=1,#asked do
+ local a = asked[i]
+ local f = found[a]
+ if f then
+ postprocessors[#postprocessors+1] = f
+ end
+ end
+ if #postprocessors > 0 then
+ tfmdata.postprocessors = postprocessors
+ end
+ end
+end
+
+-- colorschemes
+
+local colorschemes = fontgoodies.colorschemes or allocate { }
+fontgoodies.colorschemes = colorschemes
+colorschemes.data = colorschemes.data or { }
+
+local function setcolorscheme(tfmdata,scheme)
+ if type(scheme) == "string" then
+ local goodies = tfmdata.goodies
+ -- todo : check for already defined in shared
+ if goodies then
+ local what
+ for i=1,#goodies do
+ -- last one counts
+ local g = goodies[i]
+ what = g.colorschemes and g.colorschemes[scheme] or what
+ end
+ if type(what) == "table" then
+ -- this is font bound but we can share them if needed
+ -- just as we could hash the conversions (per font)
+ local hash = tfmdata.resources.unicodes
+ local reverse = { }
+ local characters = tfmdata.characters
+ for i=1,#what do
+ local w = what[i]
+ for j=1,#w do
+ local name = w[j]
+ if name == "*" then
+ -- inefficient but only used for tracing anyway
+ for _, unicode in next, hash do
+ reverse[unicode] = i
+ end
+ elseif type(name) == "number" then
+ reverse[name] = i
+ elseif find(name,":",1,true) then
+ local start, stop = splitup(name,":")
+ start = tonumber(start)
+ stop = tonumber(stop)
+ if start and stop then
+ -- limited usage: we only deal with non reassigned
+ -- maybe some day I'll also support the ones with a
+ -- tounicode in this range
+ for unicode=start,stop do
+ if characters[unicode] then
+ reverse[unicode] = i
+ end
+ end
+ end
+ else
+ local unicode = hash[name]
+ if unicode then
+ reverse[unicode] = i
+ end
+ end
+ end
+ end
+ tfmdata.properties.colorscheme = reverse
+ return
+ end
+ end
+ end
+ tfmdata.properties.colorscheme = false
+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
+
+setmetatableindex(cache,function(t,a)
+ local v = { }
+ setmetatableindex(v,function(t,c)
+ local v = "colorscheme:" .. a .. ":" .. c
+ t[c] = v
+ return v
+ end)
+ t[a]= v
+ return v
+end)
+
+function colorschemes.coloring(head)
+ local lastfont = nil
+ local lastattr = nil
+ local lastcache = nil
+ local lastscheme = nil
+ local done = nil
+ 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
+ lastfont = f
+ lastscheme = fontproperties[f].colorscheme
+ end
+ if a ~= lastattr then
+ lastattr = a
+ lastcache = cache[a]
+ end
+ if lastscheme then
+ local sc = lastscheme[getchar(n)]
+ if sc then
+ setnodecolor(n,lastcache[sc]) -- we could inline this one
+ done = true
+ end
+ end
+ end
+ end
+ return head, done
+end
+
+function colorschemes.enable()
+ nodes.tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring")
+ function colorschemes.enable() end
+end
+
+local function setextrafeatures(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ for i=1,#goodies do
+ local g = goodies[i]
+ local f = g.features
+ if f then
+ for feature, specification in next, f do
+ addotffeature(tfmdata.shared.rawdata,feature,specification)
+ registerotffeature {
+ name = feature,
+ description = formatters["extra: %s"](feature)
+ }
+ end
+ end
+ end
+ end
+end
+
+local function setextensions(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ for i=1,#goodies do
+ local g = goodies[i]
+ local e = g.extensions
+ if e then
+ local goodie = g.name or "unknown"
+ for i=1,#e do
+ local name = "extension-" .. i
+ -- report_goodies("adding extension %s from %s",name,goodie)
+ otf.enhancers.addfeature(tfmdata.shared.rawdata,name,e[i])
+ end
+ end
+ end
+ end
+end
+
+-- installation (collected to keep the overview) -- also for type 1
+
+registerotffeature {
+ name = "goodies",
+ description = "goodies on top of built in features",
+ initializers = {
+ position = 1,
+ base = setgoodies,
+ node = setgoodies,
+ }
+}
+
+registerotffeature {
+ name = "extrafeatures",
+ description = "extra features",
+ default = true,
+ initializers = {
+ position = 2,
+ base = setextrafeatures,
+ node = setextrafeatures,
+ }
+}
+
+registerotffeature {
+ name = "extensions",
+ description = "extensions to features",
+ default = true,
+ initializers = {
+ position = 2,
+ base = setextensions,
+ node = setextensions,
+ }
+}
+
+registerotffeature {
+ name = "featureset",
+ description = "goodie feature set",
+ initializers = {
+ position = 3,
+ base = setfeatureset,
+ node = setfeatureset,
+ }
+}
+
+registerotffeature {
+ name = "colorscheme",
+ description = "goodie color scheme",
+ initializers = {
+ base = setcolorscheme,
+ node = setcolorscheme,
+ }
+}
+
+registerotffeature {
+ name = "postprocessor",
+ description = "goodie postprocessor",
+ initializers = {
+ base = setpostprocessor,
+ node = setpostprocessor,
+ }
+}
+
+-- afm
+
+registerafmfeature {
+ name = "goodies",
+ description = "goodies on top of built in features",
+ initializers = {
+ position = 1,
+ base = setgoodies,
+ node = setgoodies,
+ }
+}
+
+-- tfm
+
+registertfmfeature {
+ name = "goodies",
+ description = "goodies on top of built in features",
+ initializers = {
+ position = 1,
+ base = setgoodies,
+ node = setgoodies,
+ }
+}
+
+-- experiment, we have to load the definitions immediately as they precede
+-- the definition so they need to be initialized in the typescript
+
+local function initialize(goodies)
+ local mathgoodies = goodies.mathematics
+ if mathgoodies then
+ local virtuals = mathgoodies.virtuals
+ local mapfiles = mathgoodies.mapfiles
+ local maplines = mathgoodies.maplines
+ if virtuals then
+ for name, specification in next, virtuals do
+ -- beware, they are all constructed
+ mathematics.makefont(name,specification,goodies)
+ end
+ end
+ if mapfiles then
+ for i=1,#mapfiles do
+ fonts.mappings.loadfile(mapfiles[i]) -- todo: backend function
+ end
+ end
+ if maplines then
+ for i=1,#maplines do
+ fonts.mappings.loadline(maplines[i]) -- todo: backend function
+ end
+ end
+ end
+end
+
+fontgoodies.register("mathematics", initialize)
+
+-- the following takes care of explicit file specifications
+--
+-- files = {
+-- name = "antykwapoltawskiego",
+-- list = {
+-- ["AntPoltLtCond-Regular.otf"] = {
+-- -- name = "antykwapoltawskiego",
+-- style = "regular",
+-- weight = "light",
+-- width = "condensed",
+-- },
+-- },
+-- }
+
+-- math italics (not rteally needed)
+--
+-- it would be nice to have a \noitalics\font option
+
+local function initialize(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ local shared = tfmdata.shared
+ for i=1,#goodies do
+ local mathgoodies = goodies[i].mathematics
+ local mathitalics = mathgoodies and mathgoodies.italics
+ if mathitalics then
+ local properties = tfmdata.properties
+ if properties.setitalics then
+ mathitalics = mathitalics[file.nameonly(properties.name)] or mathitalics
+ if mathitalics then
+ if trace_goodies then
+ report_goodies("loading mathitalics for font %a",properties.name)
+ end
+ local corrections = mathitalics.corrections
+ local defaultfactor = mathitalics.defaultfactor
+ -- properties.mathitalic_defaultfactor = defaultfactor -- we inherit outer one anyway (name will change)
+ if corrections then
+ fontgoodies.registerpostprocessor(tfmdata, function(tfmdata) -- this is another tfmdata (a copy)
+ -- better make a helper so that we have less code being defined
+ local properties = tfmdata.properties
+ local parameters = tfmdata.parameters
+ local characters = tfmdata.characters
+ properties.mathitalic_defaultfactor = defaultfactor
+ properties.mathitalic_defaultvalue = defaultfactor * parameters.quad
+ if trace_goodies then
+ report_goodies("assigning mathitalics for font %a",properties.name)
+ end
+ local quad = parameters.quad
+ local hfactor = parameters.hfactor
+ for k, v in next, corrections do
+ local c = characters[k]
+ if c then
+ if v > -1 and v < 1 then
+ c.italic = v * quad
+ else
+ c.italic = v * hfactor
+ end
+ else
+ report_goodies("invalid mathitalics entry %U for font %a",k,properties.name)
+ end
+ end
+ end)
+ end
+ return -- maybe not as these can accumulate
+ end
+ end
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathitalics",
+ description = "additional math italic corrections",
+ -- default = true,
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+-- fontgoodies.register("mathitalics", initialize)
+
+-- files
+
+local function initialize(goodies)
+ local files = goodies.files
+ if files then
+ fonts.names.register(files)
+ end
+end
+
+fontgoodies.register("files", initialize)
+
+-- some day we will have a define command and then we can also do some
+-- proper tracing
+--
+-- fonts.typefaces["antykwapoltawskiego-condensed"] = {
+-- shortcut = "rm",
+-- shape = "serif",
+-- fontname = "antykwapoltawskiego",
+-- normalweight = "light",
+-- boldweight = "medium",
+-- width = "condensed",
+-- size = "default",
+-- features = "default",
+-- }
+
+local function initialize(goodies)
+ local typefaces = goodies.typefaces
+ if typefaces then
+ local ft = fonts.typefaces
+ for k, v in next, typefaces do
+ ft[k] = v
+ end
+ end
+end
+
+fontgoodies.register("typefaces", initialize)
+
+local compositions = { }
+
+function fontgoodies.getcompositions(tfmdata)
+ return compositions[file.nameonly(tfmdata.properties.filename or "")]
+end
+
+local function initialize(goodies)
+ local gc = goodies.compositions
+ if gc then
+ for k, v in next, gc do
+ compositions[k] = v
+ end
+ end
+end
+
+fontgoodies.register("compositions", initialize)
+
+-- extra treatments (on top of defaults): \loadfontgoodies[mytreatments]
+
+local treatmentdata = fonts.treatments.data
+
+local function initialize(goodies)
+ local treatments = goodies.treatments
+ if treatments then
+ for name, data in next, treatments do
+ treatmentdata[name] = data -- always wins
+ end
+ end
+end
+
+fontgoodies.register("treatments", initialize)
+
+local filenames = fontgoodies.filenames or allocate()
+fontgoodies.filenames = filenames
+
+local filedata = filenames.data or allocate()
+filenames.data = filedata
+
+local function initialize(goodies) -- design sizes are registered global
+ local fn = goodies.filenames
+ if fn then
+ for usedname, alternativenames in next, fn do
+ filedata[usedname] = alternativenames
+ end
+ end
+end
+
+fontgoodies.register("filenames", initialize)
+
+function fontgoodies.filenames.resolve(name)
+ local fd = filedata[name]
+ if fd and findfile(name) == "" then
+ for i=1,#fd do
+ local fn = fd[i]
+ if findfile(fn) ~= "" then
+ return fn
+ end
+ end
+ else
+ -- no lookup, just use the regular mechanism
+ end
+ return name
+end
+
+local designsizes = fontgoodies.designsizes or allocate()
+fontgoodies.designsizes = designsizes
+
+local designdata = designsizes.data or allocate()
+designsizes.data = designdata
+
+local function initialize(goodies) -- design sizes are registered global
+ local gd = goodies.designsizes
+ if gd then
+ for name, data in next, gd do
+ local ranges = { }
+ for size, file in next, data do
+ if size ~= "default" then
+ ranges[#ranges+1] = { texsp(size), file } -- also lower(file)
+ end
+ end
+ table.sort(ranges,function(a,b) return a[1] < b[1] end)
+ designdata[lower(name)] = { -- overloads, doesn't merge!
+ default = data.default,
+ ranges = ranges,
+ }
+ end
+ end
+end
+
+fontgoodies.register("designsizes", initialize)
+
+function fontgoodies.designsizes.register(name,size,specification)
+ local d = designdata[name]
+ if not d then
+ d = {
+ ranges = { },
+ default = nil, -- so we have no default set
+ }
+ designdata[name] = d
+ end
+ if size == "default" then
+ d.default = specification
+ else
+ if type(size) == "string" then
+ size = texsp(size) -- hm
+ end
+ local ranges = d.ranges
+ ranges[#ranges+1] = { size, specification }
+ end
+end
+
+function fontgoodies.designsizes.filename(name,spec,size) -- returns nil of no match
+ local data = designdata[lower(name)]
+ if data then
+ if not spec or spec == "" or spec == "default" then
+ return data.default
+ elseif spec == "auto" then
+ local ranges = data.ranges
+ if ranges then
+ for i=1,#ranges do
+ local r = ranges[i]
+ if r[1] >= size then -- todo: rounding so maybe size - 100
+ return r[2]
+ end
+ end
+ end
+ return data.default or (ranges and ranges[#ranges][2])
+ end
+ end
+end
+
+-- The following file (husayni.lfg) is the experimental setup that we used
+-- for Idris font. For the moment we don't store this in the cache and quite
+-- probably these files sit in one of the paths:
+--
+-- tex/context/fonts/goodies
+-- tex/fonts/goodies/context
+-- tex/fonts/data/foundry/collection
+--
+-- see lfg files in distribution
+
+-- interface
+
+implement {
+ name = "loadfontgoodies",
+ actions = fontgoodies.load,
+ arguments = "string",
+ overload = true, -- for now, permits new font loader
+}
+
+implement {
+ name = "enablefontcolorschemes",
+ onlyonce = true,
+ actions = colorschemes.enable,
+ overload = true, -- for now, permits new font loader
+}
+
+-- weird place ... depends on math
+
+local function finalize(tfmdata,feature,value)
+ mathematics.overloaddimensions(tfmdata,tfmdata,value)
+end
+
+registerotffeature {
+ name = "mathdimensions",
+ description = "manipulate math dimensions",
+ -- default = true,
+ manipulators = {
+ base = finalize,
+ node = finalize,
+ }
+}
+
+-- kern hackery:
+--
+-- yes : use goodies table
+-- auto : assume features to be set (often ccmp only)
+
+local function setkeepligatures(tfmdata,value)
+ if not tfmdata.properties.keptligatures then
+ local goodies = tfmdata.goodies
+ if goodies then
+ for i=1,#goodies do
+ local g = goodies[i]
+ local letterspacing = g.letterspacing
+ if letterspacing then
+ local keptligatures = letterspacing.keptligatures
+ if keptligatures then
+ local unicodes = tfmdata.resources.unicodes -- so we accept names
+ local hash = { }
+ for k, v in next, keptligatures do
+ local u = unicodes[k]
+ if u then
+ hash[u] = true
+ else
+ -- error: unknown name
+ end
+ end
+ tfmdata.properties.keptligatures = hash
+ end
+ end
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "keepligatures",
+ description = "keep ligatures in letterspacing",
+ initializers = {
+ base = setkeepligatures,
+ node = setkeepligatures,
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi
new file mode 100644
index 00000000000..e9c34e807af
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi
@@ -0,0 +1,91 @@
+%D \module
+%D [ file=font-gds,
+%D version=2009.10.14,
+%D title=\CONTEXT\ Font Support,
+%D subtitle=Colorschemes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Support / Colorschemes}
+
+%registerctxluafile{font-gds}{1.001}
+
+\unprotect
+
+% this will become colorgroups and move to font-col or so
+
+\definecolor[colorscheme:1:1][s=.75]
+\definecolor[colorscheme:1:2][r=.75]
+\definecolor[colorscheme:1:3][g=.75]
+\definecolor[colorscheme:1:4][b=.75]
+\definecolor[colorscheme:1:5][c=.75]
+\definecolor[colorscheme:1:6][m=.75]
+\definecolor[colorscheme:1:7][y=.75]
+
+\definecolor[colorscheme:2:7][s=.75]
+\definecolor[colorscheme:2:6][r=.75]
+\definecolor[colorscheme:2:5][g=.75]
+\definecolor[colorscheme:2:4][b=.75]
+\definecolor[colorscheme:2:3][c=.75]
+\definecolor[colorscheme:2:2][m=.75]
+\definecolor[colorscheme:2:1][y=.75]
+
+\definecolor[colorscheme:3:1][r=.75]
+\definecolor[colorscheme:3:2][g=.75]
+\definecolor[colorscheme:3:3][b=.75]
+\definecolor[colorscheme:3:4][g=.75,b=.75]
+\definecolor[colorscheme:3:5][r=.75,b=.75]
+\definecolor[colorscheme:3:6][r=.75,g=.75]
+\definecolor[colorscheme:3:7][g=.75]
+
+\definesystemattribute[colorscheme][public]
+
+\unexpanded\def\loadfontgoodies[#filename]%
+ {\clf_loadfontgoodies{#filename}}
+
+\unexpanded\def\setfontcolorscheme % will move to the lua end
+ {\clf_enablefontcolorschemes
+ \unexpanded\xdef\setfontcolorscheme[##1]{\attribute\colorschemeattribute##1\relax}%
+ \setfontcolorscheme}
+
+\unexpanded\def\resetfontcolorscheme
+ {\attribute\colorschemeattribute\attributeunsetvalue}
+
+\protect \endinput
+
+% \definefontfeature[husayni-colored][goodies=husayni,colorscheme=default,featureset=default]
+%
+% \definedfont[husayni*husayni-colored at 36pt]
+%
+% \starttext \pardir TRT \textdir TRT
+%
+% \setfontcolorscheme[1]
+%
+% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \setfontcolorscheme[2]
+%
+% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \resetfontcolorscheme
+%
+% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua b/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua
new file mode 100644
index 00000000000..efd042fe162
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua
@@ -0,0 +1,349 @@
+if not modules then modules = { } end modules ['font-hsh'] = {
+ 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 rawget = rawget
+
+local setmetatableindex = table.setmetatableindex
+local currentfont = font.current
+local allocate = utilities.storage.allocate
+
+local fonts = fonts
+local hashes = fonts.hashes or allocate()
+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 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.italics = italics
+hashes.lastmathids = lastmathids
+hashes.dynamics = dynamics
+hashes.unicodes = unicodes
+hashes.originals = originals
+hashes.modes = modes
+hashes.variants = variants
+
+local nodepool = nodes.pool
+local dummyglyph = nodepool.register(nodepool.glyph())
+
+local nulldata = allocate {
+ name = "nullfont",
+ characters = { },
+ descriptions = { },
+ properties = { },
+ parameters = { -- lmromanregular @ 12pt
+ slantperpoint = 0,
+ spacing = {
+ width = 256377,
+ stretch = 128188,
+ shrink = 85459,
+ extra = 85459,
+ },
+ quad = 786432,
+ xheight = 338952,
+ -- compatibility:
+ slant = 0, -- 1
+ space = 256377, -- 2
+ space_stretch = 128188, -- 3
+ space_shrink = 85459, -- 4
+ x_height = 338952, -- 5
+ quad = 786432, -- 6
+ extra_space = 85459, -- 7
+ },
+}
+
+fonts.nulldata = nulldata
+
+fonts.constructors.enhanceparameters(nulldata.parameters) -- official copies for us
+
+setmetatableindex(identifiers, function(t,k)
+ return k == true and identifiers[currentfont()] or nulldata
+end)
+
+do
+
+ -- to be used
+
+ local define = font.define
+ local setfont = font.setfont
+ local frozen = font.frozen
+
+ function fonts.reserveid(fontdata)
+ return define(fontdata or nulldata)
+ end
+
+ function fonts.enhanceid(id,fontdata)
+ if not frozen(id) then
+ setfont(id,fontdata)
+ end
+ end
+
+end
+
+setmetatableindex(characters, function(t,k)
+ if k == true then
+ return characters[currentfont()]
+ else
+ local characters = identifiers[k].characters
+ t[k] = characters
+ return characters
+ end
+end)
+
+setmetatableindex(descriptions, function(t,k)
+ if k == true then
+ return descriptions[currentfont()]
+ else
+ local descriptions = identifiers[k].descriptions
+ t[k] = descriptions
+ return descriptions
+ end
+end)
+
+setmetatableindex(parameters, function(t,k)
+ if k == true then
+ return parameters[currentfont()]
+ else
+ local parameters = identifiers[k].parameters
+ t[k] = parameters
+ return parameters
+ end
+end)
+
+setmetatableindex(properties, function(t,k)
+ if k == true then
+ return properties[currentfont()]
+ else
+ local properties = identifiers[k].properties
+ t[k] = properties
+ return properties
+ end
+end)
+
+setmetatableindex(resources, function(t,k)
+ if k == true then
+ return resources[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local rawdata = shared and shared.rawdata
+ local resources = rawdata and rawdata.resources
+ t[k] = resources or false -- better than resolving each time
+ return resources
+ end
+end)
+
+setmetatableindex(features, function(t,k)
+ if k == true then
+ return features[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local features = shared and shared.features or { }
+ t[k] = features
+ return features
+ end
+end)
+
+local nospacing = {
+ width = 0,
+ stretch = 0,
+ shrink = 0,
+ extra = 0,
+}
+
+setmetatableindex(spacings, function(t,k)
+ if k == true then
+ return spacings[currentfont()]
+ else
+ local parameters = parameters[k]
+ local spacing = parameters and parameters.spacing or nospacing
+ t[k] = spacing
+ return spacing
+ end
+end)
+
+setmetatableindex(spaces, function(t,k)
+ if k == true then
+ return spaces[currentfont()]
+ else
+ local space = spacings[k].width
+ t[k] = space
+ return space
+ end
+end)
+
+setmetatableindex(marks, function(t,k)
+ if k == true then
+ return marks[currentfont()]
+ else
+ local resources = identifiers[k].resources or { }
+ local marks = resources.marks or { }
+ t[k] = marks
+ return marks
+ end
+end)
+
+setmetatableindex(quads, function(t,k)
+ if k == true then
+ return quads[currentfont()]
+ else
+ local parameters = rawget(parameters,k)
+ local quad
+ if parameters then
+ quad = parameters.quad
+ else
+ dummyglyph.font = k
+ dummyglyph.char = 0x2014 -- emdash
+ quad = dummyglyph.width -- dirty trick
+ end
+ if not quad or quad == 0 then
+ quad = 655360 -- lm 10pt
+ end
+ t[k] = quad
+ return quad
+ end
+end)
+
+setmetatableindex(xheights, function(t,k)
+ if k == true then
+ return xheights[currentfont()]
+ else
+ local parameters = rawget(parameters,k)
+ local xheight
+ if parameters then
+ xheight = parameters.xheight
+ else
+ dummyglyph.font = k
+ dummyglyph.char = 0x78 -- x
+ xheight = dummyglyph.height -- dirty trick
+ end
+ if not xheight or xheight == 0 then
+ xheight = 282460 -- lm 10pt
+ end
+ t[k] = xheight
+ return xheight
+ end
+end)
+
+setmetatableindex(italics, function(t,k) -- is test !
+ if k == true then
+ return italics[currentfont()]
+ else
+ local properties = identifiers[k].properties
+ local hasitalics = properties and properties.hasitalics
+ if hasitalics then
+ hasitalics = characters[k] -- convenient return
+ else
+ hasitalics = false
+ end
+ t[k] = hasitalics
+ return hasitalics
+ end
+end)
+
+setmetatableindex(dynamics, function(t,k)
+ if k == true then
+ return dynamics[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local dynamics = shared and shared.dynamics or false
+ t[k] = dynamics
+ return dynamics
+ end
+end)
+
+setmetatableindex(unicodes, function(t,k) -- always a unicode
+ if k == true then
+ return unicodes[currentfont()]
+ else
+ local resources = resources[k]
+ local unicodes = resources and resources.unicodes or { }
+ t[k] = unicodes
+ return unicodes
+ end
+end)
+
+setmetatableindex(originals, function(t,k) -- always a unicode
+ if k == true then
+ return originals[currentfont()]
+ else
+ local resolved = { }
+ setmetatableindex(resolved,function(t,name)
+ local u = unicodes[k][name]
+ local d = u and descriptions[k][u]
+ local v = d and d.unicode or u or 0 -- so we return notdef (at least for the moment)
+ t[name] = u
+ return v
+ end)
+ t[k] = resolved
+ return resolved
+ end
+end)
+
+setmetatableindex(modes, function(t,k)
+ if k == true then
+ return modes[currentfont()]
+ else
+ local mode = properties[k].mode or "base"
+ t[k] = mode
+ return mode
+ end
+end)
+
+setmetatableindex(variants, function(t,k)
+ if k == true then
+ return variants[currentfont()]
+ else
+ local resources = resources[k]
+ if resources then
+ local variants = resources.variants
+ if variants and next(variants) then
+ t[k] = variants
+ return variants
+ end
+ end
+ t[k] = false
+ return false
+ end
+end)
+
+function font.getfont(id)
+ return identifiers[id]
+end
+
+font.setfont = currentfont -- bah, no native 'setfont' as name
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua
new file mode 100644
index 00000000000..c547f89acf9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua
@@ -0,0 +1,32 @@
+if not modules then modules = { } end modules ['font-ini'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Not much is happening here.</p>
+--ldx]]--
+
+local allocate = utilities.storage.allocate
+
+local report_defining = logs.reporter("fonts","defining")
+
+fonts = fonts or { }
+local fonts = fonts
+
+fonts.hashes = { identifiers = allocate() }
+
+fonts.tables = fonts.tables or { }
+fonts.helpers = fonts.helpers or { }
+fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata
+fonts.specifiers = fonts.specifiers or { } -- in format !
+
+fonts.analyzers = { } -- not needed here
+fonts.readers = { }
+fonts.definers = { methods = { } }
+fonts.loggers = { register = function() end }
+
+fontloader.totable = fontloader.to_table -- not used
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi
new file mode 100644
index 00000000000..7e5851b2601
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi
@@ -0,0 +1,2608 @@
+%D \module
+%D [ file=font-ini,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: < 3 pt => 3pt
+% todo: check where more class usage
+% todo: split font-nam (style/alternative/size)
+% todo: split font-dim (scales etc)
+% todo: reconsider defaultfontclass
+%
+
+%D Watch out: as we define inside macros in sometimes special ways,
+%D an occasional \type {\normaldef} is used in order to please the
+%D \MKVI\ parser.
+
+%D Beware, we use a special set of parameters here:
+%D
+%D \starttabulate[|l|l|]
+%D \NC system variable (fixed) \NC \type {\s!text} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!script} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!scriptscript} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!x} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!xx} \NC \NR
+%D \NC variable (value) \NC \type {\v!big} \NC \NR
+%D \NC variable (value) \NC \type {\v!small} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!interlinespace} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!em} \NC \NR
+%D \stoptabulate
+%D
+%D The math related ones are similar to the ones used in \TEX\ itself,
+%D the size related ones show up as keywords in the user interface
+%D when switching sizes, and the two constants are used in key|/|value
+%D situations.
+
+%D We should consider design sizes ... maybe kick 'm out which removes
+%D the size code and simplifies things considerably. After all, there
+%D will be no latin modern math in sizes.
+
+\writestatus{loading}{ConTeXt Font Macros / Initialization}
+
+%D Documentation is somewhat messy as it contains bits and pieces of
+%D previous versions.
+
+\unprotect
+
+%D There are several ways to specify a font. Three of them are
+%D pure \TeX\ ones, the fourth one is new:
+%D
+%D \starttyping
+%D \font\name=cmr12
+%D \font\name=cmr12 at 10pt
+%D \font\name=cmr12 scaled 2
+%D \font\name=cmr12 sa 1.440
+%D \stoptyping
+%D
+%D The non||\TEX\ alternative \type{sa} stands for {\em scaled
+%D at}. This means as much as: scale the bodyfontsize with this
+%D factor. The scaled option is not that useful as one needs to
+%D know the design size.
+%D
+%D Because \type {sa} (scaled at) and \type {mo} (mapped on)
+%D are not low level \TEX\ supported alternatives, we have to
+%D test for it ourselves. In doing so, we need an auxiliary
+%D \DIMENSION. We cannot use \type{\scratchdimen} because font
+%D loading can happen at any moment due to postponed loading.
+%D We could instead have used dirty grouping tricks, but this
+%D one works too.
+
+% \enableexperiments[fonts.autorscale]
+%
+% \starttypescript[mscore]
+% \definetypeface [mscore] [rm] [serif] [mscoretimes] [default]
+% \definetypeface [mscore] [ss] [sans] [mscorearial] [default] [rscale=auto] % 0.860]
+% \definetypeface [mscore] [tt] [mono] [mscorecourier] [default] [rscale=auto] % 1.065]
+% \definetypeface [mscore] [mm] [math] [times] [default] [rscale=auto] % 1.020]
+% \stoptypescript
+%
+% \starttext
+% \setupbodyfont[mscore,12pt]
+% \startTEXpage
+% test \ss test \tt test
+% \stopTEXpage
+% \stoptext
+
+% \definetypeface[one][rm][serif][computer-roman][default]
+% \definetypeface[two][rm][serif][computer-roman][default][rscale=.9]
+%
+% {\one \bf test \two test}
+% {\one \bf test \pushcurrentfont \two \popcurrentfont test}
+
+%D \macros
+%D {rm,ss,tt,hw,cg}
+%D
+%D Fonts are defined in separate files. When we define a font,
+%D we distinguish between several styles. In most cases we will
+%D use:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC roman regular serif \NC \type{\rm} \NC\FR
+%D \NC sansserif sans support \NC \type{\ss} \NC\MR
+%D \NC type teletype mono \NC \type{\tt} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D The number of styles is not limited to these three. When
+%D using Lucida Bright we can for instance also define:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC handwritten \NC \type{\hw} \NC\FR
+%D \NC calligraphic \NC \type{\cg} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Within such a font set (\type{cmr}) and style (\type{\rm})
+%D we can define a number of text font alternatives:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC typeface \NC \type{\tf} \NC\FR
+%D \NC boldface \NC \type{\bf} \NC\MR
+%D \NC slanted \NC \type{\sl} \NC\MR
+%D \NC italic \NC \type{\it} \NC\MR
+%D \NC boldslanted \NC \type{\bs} \NC\MR
+%D \NC bolditalic \NC \type{\bi} \NC\MR
+%D \NC smallcaps \NC \type{\sc} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Internally fonts are stored as combination of size, style
+%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}.
+%D Users are not confronted with sizes, but use the style or
+%D style+alternative to activate them.
+%D
+%D During the definition of a bodyfont one can also declare the
+%D available larger alternatives:
+%D
+%D \starttyping
+%D \tf \tfa \tfb \tfc ...
+%D \bf \bfa \bfb \bfc ...
+%D \sl \sla \slb \slc ...
+%D \stoptyping
+%D
+%D The smaller ones are automatically supplied and derived from
+%D the the bodyfont environment.
+%D
+%D \starttyping
+%D \tfx \tfxx
+%D \bfx \bfxx
+%D \slx \slxx
+%D \stoptyping
+%D
+%D There are only two smaller alternatives per style. The
+%D larger alternatives on the other hand have no limitations.
+%D
+%D These larger alternatives are mostly used in chapter and
+%D section titles or on title pages. When one switches to a
+%D larger alternative, the bold an other ones automatically
+%D adapt themselves:
+%D
+%D \startbuffer
+%D \tfd Hi \bf there\sl, here \tfb I \bf am
+%D \stopbuffer
+%D
+%S \startnarrower
+%D \typebuffer
+%S \stopnarrower
+%D
+%D therefore becomes:
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D Maybe this mechanism isn't always as logic, but as said
+%D before, we tried to make it as intuitive as possible.
+%D
+%D So a specific kind of glyph can be characterized by:
+%D
+%D \startnarrower
+%D family (cmr) + bodyfont (12pt) + style (rm) + alternative (bf) + size (a)
+%D \stopnarrower
+%D
+%D The last component (the size) is optional.
+%D
+%D We introduced \type{\tf} as command to call for the current
+%D normally sized typeface. This commands results in roman,
+%D sans serif, teletype or whatever style is in charge. Such
+%D rather massive switches of style sometimes take more
+%D processing time than comfortable. Of course there is a
+%D workaround for this: we can call fonts directly by means of
+%D commands like:
+%D
+%D \starttyping
+%D \rmtf \sssl \tttf \rmbsa
+%D \stoptyping
+%D
+%D One should realize that this fast calls have limitations,
+%D they lack for instance automatic super- and subscript
+%D support.
+%D
+%D This leaves us two more commands: \type{\tx} and
+%D \type{\txx}. These activate a smaller and even more smaller
+%D font than the current one and adapt themselves to the
+%D current alternative, so when \type{\bf} is active,
+%D \type{\tx} gives a smaller boldface, which in turn can be
+%D called directly by \type{\bfx}.
+%D
+%D These two smaller alternatives are specified by the bodyfont
+%D environment and therefore not necessarily have similar sizes
+%D as \type{\scriptsize} and \type{\scriptscriptsize}. The main
+%D reason for this incompatibility (which can easily be undone)
+%D lays in the fact that we often want a bit bigger characters
+%D than in math mode. In \CONTEXT\ for instance the \type{\tx}
+%D and \type{\txx} commands are used for surrogate
+%D \cap{smallcaps} which support both nesting and alternatives,
+%D like in {\bf\cap{a \cap{small} world}}, which was typeset by
+%D
+%D \starttyping
+%D \bf\cap{a \cap{small} world}
+%D \stoptyping
+%D
+%D And compare $\rm \scriptstyle THIS$ with the slightly larger
+%D \cap{THIS}: \ruledhbox{$\rm \scriptstyle scriptstyle: THIS$}
+%D or \ruledhbox{\cap{x style: THIS}} makes a big difference.
+%D
+%D The \type{x..d} sizes should be used grouped. If you
+%D don't group them, i.e. call them in a row, \CONTEXT\ will
+%D not be able to sort out your intention (\type {x} inside
+%D \type {d} inside \type {x}. etc.). The following table
+%D demonstrates this:
+%D
+%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf grouped} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \NC \type{\tf} \NC \tf \FontState \NC \tf \tx \FontState \NC \tf \txx \FontState \NC \NR
+%D \NC \type{\tfa} \NC \tfa \FontState \NC \tfa \tx \FontState \NC \tfa \txx \FontState \NC \NR
+%D \NC \type{\tfb} \NC \tfb \FontState \NC \tfb \tx \FontState \NC \tfb \txx \FontState \NC \NR
+%D \NC \type{\tfc} \NC \tfc \FontState \NC \tfc \tx \FontState \NC \tfc \txx \FontState \NC \NR
+%D \NC \type{\tfd} \NC \tfd \FontState \NC \tfd \tx \FontState \NC \tfd \txx \FontState \NC \NR
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \HL
+%D \stoptabulate
+%D
+%D \blank
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf stacked} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx}
+%D \NC \tfx \FontState
+%D \NC \tfx \tx \FontState
+%D \NC \tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx \FontState
+%D \NC \tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tf}
+%D \NC \tfx\tfxx\tf \FontState
+%D \NC \tfx\tfxx\tf \tx \FontState
+%D \NC \tfx\tfxx\tf \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfa}
+%D \NC \tfx\tfxx\tf\tfa \FontState
+%D \NC \tfx\tfxx\tf\tfa \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfb}
+%D \NC \tfx\tfxx\tf\tfa\tfb \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfc}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfd}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \HL
+%D \stoptabulate
+
+\fontslantperpoint \nullfont 0\scaledpoint
+\fontinterwordspace \nullfont 256377\scaledpoint
+\fontinterwordstretch\nullfont 128188\scaledpoint
+\fontinterwordshrink \nullfont 85459\scaledpoint
+\fontexheight \nullfont 338952\scaledpoint
+\fontemwidth \nullfont 786432\scaledpoint
+\fontextraspace \nullfont 85459\scaledpoint
+
+%D Tracing
+
+\newtoks\t_font_tracers_definitions
+
+\unexpanded\def\tracefontdefinitions
+ {\the\t_font_tracers_definitions}
+
+%D Some housekeeping macros:
+
+\unexpanded\def\setfontparameters
+ {\setfalse\c_font_synchronize
+ \the\everybodyfont
+ \settrue\c_font_synchronize}
+
+\unexpanded\def\savefont
+ {\edef\savedfont{\the\font}% gives \csname
+ \pushmacro\savedfont}
+
+\unexpanded\def\restorefont
+ {\popmacro\savedfont
+ \savedfont}
+
+\unexpanded\def\pushcurrentfont
+ {\edef\popcurrentfont
+ {\def\noexpand\fontbody {\fontbody}%
+ \def\noexpand\fontstyle {\fontstyle}%
+ \def\noexpand\fontalternative{\fontalternative}%
+ \def\noexpand\fontsize {\fontsize}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}}
+
+%D \macros{definedfont}
+
+\let\thedefinedfont\relax % not to be confused with \everydefinefont
+
+\unexpanded\def\definedfont
+ {\doifelsenextoptionalcs\font_basics_defined_font_yes\font_basics_defined_font_nop}
+
+\def\font_basics_defined_font_yes[#specification]%
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \thedefinedfont
+ \the\everydefinedfont}
+
+\def\font_basics_defined_font_nop
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \thedefinedfont
+ \the\everydefinedfont}
+
+%D \macros{startfont}
+
+\unexpanded\def\startfont{\begingroup\definedfont}
+\unexpanded\def\stopfont {\endgroup}
+
+%D \macros
+%D {everybodyfont,everyglobalbodyfont}
+%D
+%D Every change in bodyfont size has conseqences for the baseline
+%D distance and skips between paragraphs. These are initialized
+%D in other modules. Here we only provide the hooks that
+%D garantees their handling.
+%D
+%D At the system level one can initialize thing like:
+%D
+%D \starttyping
+%D \appendtoks \setupspacing \to \everybodyfont
+%D \stoptyping
+
+%D \macros
+%D {globalbodyfontsize,localbodyfontsize,bodyfontsize}
+
+%D Here we have to distinguish between the global (overal) bodyfont
+%D size and the local (sometimes in the textflow) size. We store
+%D these dimensions in two \DIMENSION\ registers. These registers are
+%D not to be misused in calculations.
+
+\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
+\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
+\ifdefined\bodyfontsize \else \newdimen\bodyfontsize \fi \bodyfontsize =\globalbodyfontsize
+
+%D When we assign for instance 12pt to a \DIMENSION\ register the \type
+%D {\the}'d value comes out as 12.0pt, which is often not the way users
+%D specify the bodyfont size. Therefore we use normalized values. They
+%D are cached to save overhead in \LUA\ calls.
+
+% \setnewconstant\fontdigits\plustwo % from now on always 2
+
+\installcorenamespace{fontnormalizedbody}
+
+% \def\normalizebodyfontsize#macro#body%
+% {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname
+% \ifx#macro\relax
+% \normalizebodyfontsize_indeed#macro{#body}%
+% \fi}
+%
+% \def\normalizebodyfontsize_indeed#macro#body%
+% {\edef#macro{\ctxcommand{nbfs(\number\dimexpr#body,\number\fontdigits)}}%
+% \global\expandafter\let\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro}
+%
+% \def\thenormalizedbodyfontsize#body%
+% {\ctxcommand{nbfs(\number\dimexpr#body\relax,\number\fontdigits)}}
+%
+% caching is less relevant now
+
+\def\normalizebodyfontsize#macro#body%
+ {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\dimexpr#body\endcsname
+ \ifx#macro\relax
+ \normalizebodyfontsize_indeed#macro{#body}%
+ \fi}
+
+\def\normalizebodyfontsize_indeed#macro#body%
+ {\edef#macro{\clf_nbfs\dimexpr#body\relax}%
+ \global\expandafter\let\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro}
+
+\def\thenormalizedbodyfontsize#body%
+ {\clf_nbfs\dimexpr#body\relax}
+
+\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+
+%D \macros
+%D {mapfontsize}
+%D
+%D For special purposes, like in math, you may want to use
+%D slightly different sizes than the ones given. This happens
+%D for instance with the Math Times fonts. Mapped font sizes
+%D can be specified by using the \type {mo} key instead of
+%D \type {sa} in font definitions.
+%D
+%D \startbuffer
+%D \mapfontsize[10pt][11pt]
+%D \mapfontsize[11pt][12pt]
+%D \mapfontsize[12pt][13pt]
+%D
+%D \definefont[test][Serif]\test TEST \par
+%D \definefont[test][Serif sa 5]\test TEST \par
+%D \definefont[test][Serif mo 5]\test TEST \par
+%D \definefont[test][Serif sa d]\test TEST \par
+%D \definefont[test][Serif at 60pt]\test TEST \par
+%D \definefont[test][Serif scaled 6000]\test TEST \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+\installcorenamespace{mappedfontsize}
+
+\unexpanded\def\mapfontsize
+ {\dodoubleargument\font_basics_map_fontsize}
+
+\def\font_basics_map_fontsize[#from][#to]%
+ {\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}}
+
+\def\font_basics_set_mapped_fontsize#from%
+ {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname
+ \lastnamedcs\else#from%
+ \fi}
+
+\installcorenamespace{fontbodyknown}
+\installcorenamespace{fontclassyes} % fontclass
+\installcorenamespace{fontclassnop} % nofontclass
+
+\def\font_helpers_process_relative_size_list#command% could be a toks
+ {#command\v!big
+ #command\v!small}
+
+\let\v_font_size_relative \plusone
+\def\v_font_size_absolute {\fontbody}
+
+\let\v_font_rscale_default\!!plusone
+\let\p_font_rscale \v_font_rscale_default
+
+\def\font_helpers_check_relative_font_id % can be plugged in later
+ {\let\p_font_rscale\minusone
+ \let\p_font_rscale\v_font_rscale_default}
+
+\def\font_helpers_check_relative_font_size#style%
+ {\edef\p_font_rscale
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \lastnamedcs
+ \else\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi\fi}%
+ % move elsewhere
+ \ifx\p_font_rscale\v!auto
+ \let\p_font_rscale\plusone
+ \font_helpers_check_relative_font_id
+ \else
+ \let\relativefontid\minusone
+ \fi}
+
+\def\font_rscale_xx#style%
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_rscale_mm
+ {\ifcsname\??fontclass\fontclass\s!mm\s!rscale\endcsname
+ \lastnamedcs
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_helpers_register_fontbody#body%
+ {\expandafter\let\csname\??fontbodyknown#body\endcsname\empty}
+
+%D \macros
+%D {definefontstyle,definefontsize,definefontalternative}
+%D
+%D When setting of switching the overall style we can use the
+%D short identifier like rm and ss, but when defined we can
+%D also use more verbose names like roman or sansserif. Such
+%D names are defined by:
+%D
+%D \starttyping
+%D \definefontstyle [serif,rm] [rm]
+%D \definefontstyle [sansserif,ss] [ss]
+%D \stoptyping
+
+\installcorenamespace{fontstyle} % full style prefix (roman etc)
+\installcorenamespace{fontshortstyle} % short style prefix (rm etc)
+
+\installcorenamespace{fontstyleknown}
+\installcorenamespace{fontalternativeknown}
+\installcorenamespace{fontsizeknown}
+
+\newtoks\t_font_style_commands
+\newtoks\t_font_size_commands
+\newtoks\t_font_alternative_commands
+
+\setnewmacro\m_font_style_command \gobbleoneargument
+\setnewmacro\m_font_size_command \gobbleoneargument
+\setnewmacro\m_font_alternative_command\gobbleoneargument
+
+\def\font_helpers_process_style_list #command{\def\m_font_style_command {#command}\the\t_font_style_commands}
+\def\font_helpers_process_size_list #command{\def\m_font_size_command {#command}\the\t_font_size_commands}
+\def\font_helpers_process_alternative_list#command{\def\m_font_alternative_command{#command}\the\t_font_alternative_commands}
+
+\def\font_helpers_register_style #style{\expandafter\let\csname\??fontstyleknown #style\endcsname\empty}
+\def\font_helpers_register_size #size{\expandafter\let\csname\??fontsizeknown #size\endcsname\empty}
+\def\font_helpers_register_alternative#alternative{\expandafter\let\csname\??fontalternativeknown#alternative\endcsname\empty}
+
+\unexpanded\def\definefontstyle
+ {\dodoubleargument\font_basics_define_fontstyle}
+
+\def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ...
+ {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
+ \font_helpers_register_style{#style}%
+ % todo: apptoks
+ \t_font_style_commands\expandafter{\the\t_font_style_commands\m_font_style_command{#style}}%
+ \fi
+ \processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}}
+
+\def\font_basics_define_fontstyle_indeed#style#command%
+ {\setvalue{\??fontshortstyle#command}{#style}%
+ \setvalue{\??fontstyle #command}{\csname#style\endcsname}}
+
+\unexpanded\def\definefontsize[#size]%
+ {\ifcsname\??fontsizeknown#size\endcsname \else
+ \font_helpers_register_size{#size}%
+ \t_font_size_commands\expandafter{\the\t_font_size_commands
+ \m_font_size_command{#size}}%
+ \fi
+ \font_helpers_check_fontname_combinations}
+
+\unexpanded\def\definefontalternative[#alternative]%
+ {\ifcsname\??fontalternativeknown#alternative\endcsname \else
+ \font_helpers_register_alternative{#alternative}%
+ % todo: apptoks
+ \t_font_alternative_commands\expandafter{\the\t_font_alternative_commands
+ \m_font_alternative_command{#alternative}}%
+ \fi
+ \font_helpers_check_fontname_combinations}
+
+\unexpanded\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb)
+ {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s}
+
+\def\font_helpers_check_fontname_combinations_s#style%
+ {\font_helpers_process_alternative_list{\font_helpers_check_fontname_combinations_indeed_s_a{#style}}}
+
+\def\font_helpers_check_fontname_combinations_indeed_s_a#style#alternative%
+ {\font_helpers_process_size_list{\font_basics_check_fontname_combination{#style}{#alternative}}}
+
+\definefontstyle [\s!mm] [\s!mm]
+\definefontstyle [\s!rm] [\s!rm]
+\definefontstyle [\s!ss] [\s!ss]
+\definefontstyle [\s!tt] [\s!tt]
+
+%D We define all the font switching commands globally. After all they are part
+%D of the formal font interface once defined. The size can be empty (so
+%D checking is needed as \type {\bf} is already defined)
+
+%D The \type {\normal..} variants are available as extras for cases where
+%D the \type {..} is overloaded.
+
+\newmacro\m_font_mm
+
+\def\font_basics_check_fontname_combination#style% alternative size
+ {\edef\m_font_mm{#style}%
+ \ifx\m_font_mm\s!mm % prevents \max and alike (re)defs
+ \expandafter\font_basics_check_math_bodyfont
+ \else
+ \expandafter\font_basics_check_text_bodyfont
+ \fi{#style}} % no \m_font_mm, not expanded later on
+
+% \def\font_basics_check_math_bodyfont#style#alternative#size%
+% {%setugvalue{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \mr \mb
+% \setugvalue{#style}{\font_helpers_set_current_font_style{#style}}}% \mm
+
+\def\font_basics_check_math_bodyfont#style#alternative#size%
+ {}
+
+\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined)
+ {\setugvalue{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma
+ \setugvalue{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla
+ \setugvalue{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla
+ \ifcsname\s!normal#style\endcsname % text/math check
+ \expandafter\let\csname#style\expandafter\endcsname\csname\s!normal#style\endcsname
+ \else
+ \setugvalue{#style}{\font_helpers_set_current_font_style{#style}}% \rm
+ \fi
+ \ifcsname\s!normal#alternative\endcsname % text/math check
+ \expandafter\let\csname#alternative\expandafter\endcsname\csname\s!normal#alternative\endcsname
+ \else
+ \setugvalue{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl
+ \fi
+ \setugvalue{#style\s!x}{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx
+ \setugvalue{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx
+ \setugvalue{#alternative\s!x}{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx
+ \setugvalue{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx
+ \setugvalue{#style#alternative}{\font_helpers_set_current_font_style_alternative{#style}{#alternative}}}% \rmsl
+
+%D Scaling macros:
+%D
+%D This system is somewhat complicated by two (possible conflicting)
+%D demands:
+%D
+%D \startitemize
+%D \item We support wildcards like \type {sa *} which will adapt
+%D to the current size. This is also the default specification.
+%D \item We support named scales like \type {sa d}; beware: \type
+%D {x} and \type {xx} are valid scales but they are not alway
+%D the same as the ones used in for instance \type {\bfx} because
+%D there the sized come from the bodyfont environment. In the
+%D future there maybe a switch that also honors the environment
+%D in named scales.
+%D \stopitemize
+%D
+%D Keep in mind that the smaller sizes are just for text super and
+%D subscripts while larger sizes can be used in titles where for
+%D instance math follows the size.
+
+% b:x{\definedfont[SerifBold sa b]x}{\bfb x $x^x$}\par
+% 1:x{\definedfont[SerifBold sa 1]x}{\bf x $x^x$}\par
+% x:x{\definedfont[SerifBold sa x]x}{\bfx x $x^x$}\par
+% xx:x{\definedfont[SerifBold sa xx]x}{\bfxx x $x^x$}\par
+%
+% *:x{\definedfont[Serif sa *]x}\par
+% 1:x{\definedfont[Serif sa 1]x}\par
+% 2:x{\definedfont[Serif sa 2]x}\par
+% 3:x{\definedfont[Serif sa 3]x}\par
+% 4:x{\definedfont[Serif sa 4]x}\par
+% 5:x{\definedfont[Serif sa 5]x}\par
+
+\def\safontscale{\number\dimexpr\v_font_size_absolute\relax}
+\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax}
+
+\let\somefontname\s!unknown
+\let\somefontspec\s!unknown
+\let\somefontsize\zerocount
+
+\newcount\scaledfontmode % also used at the lua end
+\newcount\scaledfontsize % also used at the lua end
+\newcount\lastfontid % also used at the lua end / tex end
+\newtoks \everydefinefont
+
+\let\relativefontid\minusone % todo, not yet used
+
+\let\c_font_feature_inheritance_fontnone \zerocount % none
+\let\c_font_feature_inheritance_fontonly \plusone % fontonly
+\let\c_font_feature_inheritance_classonly \plustwo % classonly
+\let\c_font_feature_inheritance_fontfirst \plusthree % fontfirst
+\let\c_font_feature_inheritance_classfirst\plusfour % classfirst
+
+\let\c_font_feature_inheritance_default \c_font_feature_inheritance_fontfirst
+
+\setnewconstant\c_font_feature_inheritance_mode \c_font_feature_inheritance_default
+
+\newdimen \d_font_scaled_text_face
+\newdimen \d_font_scaled_font_size
+\newconditional\c_font_body_scale
+\newfraction \f_font_body_scale
+
+\unexpanded\def\font_helpers_low_level_define#specification#csname%
+ {% we can now set more at the lua end
+ \global\let\somefontname\defaultfontfile
+ \let\somefontsize\empty
+ \clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen
+ % sets \scaledfontmode and \somefontname and \somefontsize
+ \ifcase\fontface\relax
+ % \let\v_font_size_absolute\textface % fontbody
+ \or
+ \let\v_font_size_absolute\textface
+ \or
+ \let\v_font_size_absolute\scriptface
+ \or
+ \let\v_font_size_absolute\scriptscriptface
+ \or
+ \let\v_font_size_absolute\xtextface
+ \or
+ \let\v_font_size_absolute\xxtextface
+ \fi
+ %
+ \ifcase\scaledfontmode\relax
+ % none, avoid the designsize if possible
+ \d_font_scaled_font_size-\plusthousand\scaledpoint
+ \or
+ % at
+ \d_font_scaled_font_size\somefontsize
+ \or
+ % sa
+ \d_font_scaled_font_size\v_font_size_absolute\relax
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size % uses \somefontsize set by lua
+ \or
+ % mo
+ \d_font_scaled_font_size\font_basics_set_mapped_fontsize\v_font_size_absolute
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size
+ \or
+ % scaled, don't use this one as it's unpredictable
+ \d_font_scaled_font_size-\somefontsize\scaledpoint
+ \else % ht cp
+ % experiment, yet undocumented
+ \d_font_scaled_font_size\somefontsize
+ \fi
+ \relax
+ \d_font_scaled_font_size\v_font_size_relative\d_font_scaled_font_size
+ \ifconditional\c_font_auto_size
+ \font_helpers_check_body_scale\fontsize
+ \ifconditional\c_font_body_scale
+ \d_font_scaled_font_size\f_font_body_scale\d_font_scaled_font_size
+ \d_font_scaled_text_face\f_font_body_scale\dimexpr\textface\relax
+ \else
+ \d_font_scaled_font_size\f_font_body_scale
+ \d_font_scaled_text_face\textface
+ \fi
+ \else
+ \d_font_scaled_text_face\textface
+ \fi
+ \edef\somefontspec{at \number\d_font_scaled_font_size sp}%
+ \edef\somefontfile{\truefontname\somefontname}%
+ \ifx\somefontfile\s!unknown
+ \edef\somefontfile{\defaultfontfile}%
+ \fi
+ \font_helpers_update_font_parameters
+ \font_helpers_update_font_class_parameters
+ % \writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}%
+ \clf_definefont_two
+ \ifx\fontclass\empty\s!false\else\s!true\fi
+ {#csname}%
+ {\somefontfile}%
+ \d_font_scaled_font_size
+ \c_font_feature_inheritance_mode
+ {\m_font_class_features}%
+ {\m_font_features}%
+ {\m_font_class_fallbacks}%
+ {\m_font_fallbacks}%
+ \fontface
+ \d_font_scaled_text_face
+ \relativefontid
+ {\m_font_class_goodies}%
+ {\m_font_goodies}%
+ {\m_font_class_designsize}%
+ {\m_font_designsize}%
+ \scaledfontmode
+ \relax
+ \ifcase\scaledfontsize
+ %\scaledfontsize\plusone
+ \let\somefontspec\empty
+ \let\lastrawfontcall\relax
+ \expandafter\let\csname#csname\endcsname\relax
+ \else
+ \edef\somefontspec{at \number\scaledfontsize sp}% we need the resolved designsize (for fallbacks)
+ \expandafter\let\expandafter\lastrawfontcall\csname#csname\endcsname
+ \the\everydefinefont
+ \fi
+ \c_font_feature_inheritance_mode\c_font_feature_inheritance_default}
+
+% \def\font_helpers_check_body_scale#fontsize% gets character (x xx a etc)
+% {\ifcsname\??fontenvironments\fontclass\fontbody #fontsize\endcsname \setfalse\c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments\fontclass\fontbody #fontsize\endcsname \else
+% \ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments\fontclass\s!default#fontsize\endcsname \else
+% \ifcsname\??fontenvironments \fontbody #fontsize\endcsname \setfalse\c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments \fontbody #fontsize\endcsname \else
+% \ifcsname\??fontenvironments \s!default#fontsize\endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments \s!default#fontsize\endcsname \else
+% \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments\fontclass\s!default\s!text \endcsname \else
+% \ifcsname\??fontenvironments \s!default\s!text \endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+% \csname\??fontenvironments \s!default\s!text \endcsname
+% \else
+% \settrue \c_font_body_scale
+% \let\f_font_body_scale\plusone
+% \fi\fi\fi\fi\fi\fi}
+
+\def\font_helpers_check_body_scale#fontsize% gets character (x xx a etc)
+ {\ifcsname\??fontenvironments\fontclass\fontbody#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \setfalse\c_font_body_scale % !
+ \else\ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \else\ifcsname\??fontenvironments\fontbody#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \setfalse\c_font_body_scale % !
+ \else\ifcsname\??fontenvironments\s!default#fontsize\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \else\ifcsname\??fontenvironments\fontclass\s!default\s!text\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \else\ifcsname\??fontenvironments\s!default\s!text\endcsname
+ \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
+ \settrue\c_font_body_scale
+ \else
+ \let\f_font_body_scale\plusone
+ \settrue\c_font_body_scale
+ \fi\fi\fi\fi\fi\fi}
+
+%D The following macros are used at the \LUA\ end. Watch the \type {\normal}
+%D hackery: this makes the mkvi parser happy.
+
+% \normaldef\fntsetdefname {\global\let\somefontname\defaultfontfile} % do before calling
+% \normaldef\fntsetnopsize {\let\somefontsize\empty} % do before calling
+% \normaldef\fntsetsomename{\normalgdef\somefontname} % takes argument
+% \normaldef\fntsetsomesize{\normaldef\somefontsize} % takes argument
+
+\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
+
+%D When fontclasses are used, we define the font global, since namespaces are
+%D used. Otherwise we parse the specs each time.
+
+\let\fontfile\s!unknown
+
+%D \macros
+%D {everyfont,everyfontswitch}
+
+\ifdefined\everyfont \else \newtoks\everyfont \fi
+\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi
+
+\def\setfontcharacteristics{\the\everyfont}
+
+%D \macros
+%D {definefont}
+%D
+%D We also accept \type{sa a}||\type{sa d} as specification.
+%D
+%D Before we implement the main definition macro, we first show
+%D one for local use:
+%D
+%D \starttyping
+%D \definefont[Some][LucidaBright at 100pt] \Some some
+%D \definefont[More][LucidaBright scaled 3000] \More more
+%D \definefont[Nice][LucidaBright mo 2] \Nice nice
+%D \definefont[Text][LucidaBright sa 5.4] \Text last
+%D \stoptyping
+%D
+%D The implementation looks as follows:
+
+\unexpanded\def\definefont % [name][spec][1.6 | line=10pt | setup_id]
+ {\dotripleempty\font_basics_define_font}
+
+\def\font_basics_define_font
+ {\ifthirdargument
+ \expandafter\font_basics_define_font_a
+ \else
+ \expandafter\font_basics_define_font_b
+ \fi}
+
+\def\font_basics_define_font_a[#name][#specification][#settings]% [name][spec][1.6 | line=10pt | setup_id]
+ {\doifelsesetups{#settings}%
+ {\setuvalue{#name}{\font_basics_define_font_with_setups {#name}{#specification}{#settings}}}
+ {\setuvalue{#name}{\font_basics_define_font_with_parameters{#name}{#specification}{#settings}}}}
+
+\def\font_basics_define_font_b[#name][#specification][#dummy]%
+ {\setuvalue{#name}{\font_basics_define_font_without_parameters{#name}{#specification}}}
+
+\def\font_basics_define_font_with_parameters#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setuplocalinterlinespace[#settings]%
+ \setupspacing\relax} % is this really needed ?
+
+\def\font_basics_define_font_with_setups#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setups[#settings]}
+
+%D Beware, in the frozen variants no settings are supported yet, but that might happen
+%D some day.
+
+\unexpanded\def\definefrozenfont
+ {\dotripleempty\font_basics_define_frozen_font}
+
+% \def\font_basics_define_frozen_font[#name][#specification][#settings]%
+% {\begingroup
+% \font_basics_define_font[#name][#specification][#settings]%
+% \csname#name\endcsname
+% \expandafter\expandafter\expandafter\endgroup\expandafter\let\csname#name\endcsname\lastrawfontcall}
+
+\def\font_basics_define_frozen_font[#name][#specification][#settings]%
+ {\begingroup
+ \font_basics_define_font[#name][#specification][#settings]%
+ \csname#name\endcsname
+ \global\let\lastglobalrawfontcall\lastrawfontcall
+ \endgroup
+ \expandafter\let\csname#name\endcsname\lastglobalrawfontcall}
+
+%D The instance namespace protection makes the switch local so that we can redefine a
+%D logical name and/or change the size in between.
+
+% todo: now mathsize twice in name (so it can go here)
+% todo: check when mathsize is needed
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+\newconditional\c_font_auto_size \settrue\c_font_auto_size
+
+\let\lastfontidentifier\empty
+
+\def\v_font_identifier_basic{\??fontinstancebasic \lastfontidentifier-\fontsize-\fontface}
+\def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontsize-\fontface}
+
+\let\v_font_identifier_basic_saved\v_font_identifier_basic
+\let\v_font_identifier_class_saved\v_font_identifier_class
+
+% \def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontstyle-\fontsize} % no \fontface
+
+\def\font_basics_define_font_without_parameters#identifier#2%
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \edef\lastfontidentifier{#identifier}%
+ \let\v_font_size_relative\v_font_rscale_default
+ \let\v_font_size_absolute\fontbody
+ \font_helpers_low_level_define{#2}\v_font_identifier_basic
+ \csname\v_font_identifier_basic\endcsname
+ \setfalse\c_font_auto_size
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \let\v_font_identifier_basic\v_font_identifier_basic_saved}
+
+\unexpanded\def\font_helpers_trigger#identifier% make a traced variant
+ {\edef\lastfontidentifier{#identifier}%
+ \ifcsname\v_font_identifier_class\endcsname
+ % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}%
+ \expandafter\font_helpers_trigger_reuse
+ \else
+ % \writestatus{fonts}{trigger: defining \v_font_identifier_class}%
+ \expandafter\font_helpers_trigger_define
+ \fi}
+
+\def\font_helpers_trigger_define#relative#absolute#specification%
+ {\def\v_font_size_relative{#relative}%
+ \def\v_font_size_absolute{#absolute}%
+ \font_helpers_low_level_define{#specification}\v_font_identifier_class
+ \csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+\def\font_helpers_trigger_reuse#relative#absolute#specification%
+ {\csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+%D \macros
+%D {currentfontbodyscale}
+%D
+%D Sometimes we need to have access to the font scale
+%D including the \type{a}||\type{d} sizes. The next macro
+%D returns the current scaling factor. Take a look at
+%D \type {cont-log.tex} for an example of its use.
+
+\installcorenamespace{fontenvironments}
+
+% \def\currentfontbodysize
+% {\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+% \csname\??fontenvironments\s!default\somefontsize\endcsname
+% \else
+% \somefontsize
+% \fi}
+%
+% \def\currentfontbodyscale
+% {\csname\??fontenvironments\s!default
+% \ifcsname\??fontenvironments\s!default\fontsize\endcsname \fontsize \else
+% \ifcsname\??fontenvironments\s!default\s!text \endcsname \s!text \fi\fi
+% \endcsname}
+
+% \def\currentfontbodysize % gets number (the normal sa 1 etc)
+% {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+% \csname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+% \else\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+% \csname\??fontenvironments\s!default\somefontsize\endcsname
+% \else
+% \somefontsize
+% \fi\fi}
+
+\def\currentfontbodysize % gets number (the normal sa 1 etc)
+ {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+ \lastnamedcs
+ \else\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+ \lastnamedcs
+ \else
+ \somefontsize
+ \fi\fi}
+
+\def\currentfontbodyscale % gets character (x xx a etc)
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\else
+ \ifcsname\??fontenvironments \s!default\fontsize\endcsname \s!default\fontsize\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi\fi\fi\fi
+ \endcsname}
+
+\def\font_currentfontbodyscale % gets character (x xx a etc)
+ {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments \s!default\fontsize\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else
+ \csname\??fontenvironments \s!default \endcsname \fi\fi\fi\fi}
+
+\def\currentfontscale % used in default definition
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\else
+ \ifcsname\??fontenvironments \s!default\xfontsize\endcsname \s!default\fontsize\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi\fi\fi\fi
+ \endcsname}
+
+\def\font_currentfontscale % used in default definition
+ {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments \s!default\xfontsize\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else
+ \csname\??fontenvironments \s!default \endcsname \fi\fi\fi\fi}
+
+\setvalue{\??fontenvironments\s!default}{1}
+
+%D In the following macros we use \type{\currentxfontsize} to
+%D hold the current x||size of the font. This enables us to
+%D support for instance \type{\sl} inside a \type{\tx} switch.
+
+\newconstant\currentxfontsize
+
+\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi}
+
+%D Now we enter the area of font switching. The switching
+%D mechanism has to take care of several situations, like:
+%D
+%D \startitemize[packed]
+%D \item changing the overal document fonts (including margins,
+%D headers and footers)
+%D \item changing local fonts (only the running text)
+%D \item smaller and even more smaller alternatives (super-
+%D and subscripts)
+%D \stopitemize
+%D
+%D \TEX\ offers a powerfull family mechanism for super- and
+%D subscripts in math mode. In text mode however, we don't use
+%D families for the smaller alternatives, and therefore have
+%D to take care of it otherwise.
+
+%D \macros
+%D {definebodyfontenvironment,setupbodyfontenvironment}
+%D
+%D The relationship between the several sizes of a font, is
+%D defined by:
+%D
+%D \showsetup{definebodyfontenvironment}
+%D
+%D Later on we will see how these parameters are used, so for
+%D the moment we stick with an example:
+%D
+%D \starttyping
+%D \definebodyfontenvironment
+%D [12pt]
+%D [ text=12pt,
+%D script=9pt,
+%D scriptscript=7pt,
+%D x=10pt,
+%D xx=8pt,
+%D big=12pt,
+%D small=10pt]
+%D \stoptyping
+%D
+%D The first argument specifies the bodyfont size to which the
+%D settings apply. All second parameters are specified in
+%D dimensions and tell us more about related sizes.
+%D
+%D Afterwards, one can change values with
+%D
+%D \showsetup{setupbodyfontenvironment}
+%D
+%D When instead of a size the keyword \type{unknown} is
+%D passed, fractions (relations) are used instead of fixed
+%D sizes.
+
+%D {\bf Remark:} We need to cover the following cases, otherwise users can
+%D get confused:
+%D
+%D \starttyping
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \definebodyfont[23pt][rm,ss,tt][default]
+%D \setupbodyfont[23pt]
+%D \stoptyping
+%D
+%D Beware: while some font defs can be global, the bodyfont
+%D environment checks local. This means that multiple local
+%D checks resulting in definitions are not that efficient.
+%D So, apart from an occasional switch, one should define an
+%D environment at the outer level.
+
+% \definebodyfontenvironment[33pt]
+% \definebodyfontenvironment[dejavu][default][1=.5]
+% \definebodyfontenvironment[dejavu][default][x=1.2]
+% \definebodyfontenvironment[dejavu][default][a=5]
+% \definebodyfontenvironment[dejavu][33pt][x=100pt]
+
+% the lookup order is:
+%
+% [class] [dimension] [parameters]
+% [class] [default] [parameters] % factors
+% [dimension] [parameters]
+% [default] [parameters] % factors
+%
+% with defaults providing factors
+
+% todo: class:size
+% todo: make assignments global
+
+\letvalue\??fontenvironments\empty % so we default to empty
+
+\def\bodyfontvariable#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\else
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \normalizedbodyfontsize#parameter\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi\fi\fi\fi
+ \endcsname}
+
+\def\font_bodyfontvariable#parameter%
+ {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi\fi\fi\fi}
+
+\def\bodyfontsizevariable#size#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\else
+ \ifcsname\??fontenvironments #size#parameter\endcsname #size#parameter\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi\fi\fi\fi
+ \endcsname}
+
+\def\font_bodyfontsizevariable#size#parameter%
+ {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments #size#parameter\endcsname\lastnamedcs\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi\fi\fi\fi}
+
+\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere
+
+% \def\bodyfontdimension#class#size#parameter#body%
+% {\the\dimexpr
+% \ifcsname\??fontenvironments #class#size#parameter\endcsname
+% \csname\??fontenvironments #class#size#parameter\endcsname \else
+% \ifcsname\??fontenvironments#class\s!default#parameter\endcsname
+% \csname\??fontenvironments#class\s!default#parameter\endcsname\dimexpr#body\relax\else % factor
+% \ifcsname\??fontenvironments #size#parameter\endcsname
+% \csname\??fontenvironments #size#parameter\endcsname \else
+% \csname\??fontenvironments \s!default#parameter\endcsname\dimexpr#body\relax\fi\fi\fi % factor
+% \relax}
+
+\def\bodyfontdimension#class#size#parameter#body%
+ {\the\dimexpr
+ \ifcsname\??fontenvironments #class#size#parameter\endcsname \lastnamedcs \else
+ \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\else % factor
+ \ifcsname\??fontenvironments #size#parameter\endcsname \lastnamedcs \else
+ \lastnamedcs\dimexpr#body\relax\fi\fi\fi % factor
+ \relax}
+
+\unexpanded\def\definebodyfontenvironment
+ {\dotripleempty\font_basics_define_body_font_environment}
+
+\let\setupbodyfontenvironment\definebodyfontenvironment
+
+\installcorenamespace{fontenvironmentknown}
+
+\def\font_helpers_register_environment#class#body%
+ {\expandafter\let\csname\??fontenvironmentknown#class#body\endcsname\empty}
+
+\newmacro\m_font_body
+\newmacro\m_font_body_normalized
+
+\def\font_basics_define_body_font_environment
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_environment_class
+ \else\ifsecondargument
+ \doubleexpandafter\font_basics_define_body_font_environment_empty
+ \else
+ \doubleexpandafter\font_basics_define_body_font_environment_unset
+ \fi\fi}
+
+%D First we handle the class specific case. Beware: you can change values before
+%D a bodyfont is loaded but changing them afterwards can be sort of tricky as
+%D values are not consulted afterwards.
+
+\def\processbodyfontenvironmentlist#1% no \unexpanded as then we cannot use it in alignments
+ {\clf_processbodyfontsizes{\strippedcsname#1}}
+
+\def\bodyfontenvironmentlist
+ {\clf_getbodyfontsizes}
+
+\def\font_basics_define_body_font_environment_class[#class][#body][#settings]%
+ {\edef\m_font_body{#body}%
+ \ifx\m_font_body\s!default
+ % these are the last resort within a class
+ \getrawparameters[\??fontenvironments#class\s!default][#settings]%
+ \else
+ \normalizebodyfontsize\m_font_body_normalized\m_font_body
+ \font_basics_define_body_font_environment_size[#class][\m_font_body_normalized][#settings]%
+ \clf_registerbodyfontsize{\m_font_body_normalized}%
+ \fi}
+
+%D The empty case uses the same code but needs to ignore the current class
+%D settings (just to be sure, as it's not really needed).
+
+\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
+ {\pushmacro\fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][#settings]%
+ \popmacro\fontclass}
+
+\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]%
+ {\pushmacro\fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][]%
+ \popmacro\fontclass}
+
+%D We don't check too soon as we can refer to later definitions.
+
+\newconditional\c_font_defining_environment_state % controls messages
+
+\def\font_basics_define_body_font_environment_size[#class][#normalizedbody][#settings]% normalized body
+ {\getrawparameters[\??fontenvironments#class#normalizedbody][#settings]%
+ \ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname
+ % environment and size already defined
+ \else\ifproductionrun
+ \pushmacro\fontclass
+ \edef\fontclass{#class}%
+ \font_helpers_register_environment{#class}{#normalizedbody}%
+ \settrue\c_font_defining_environment_state
+ \font_helpers_define_unknown_font{#normalizedbody}% current class
+ \setfalse\c_font_defining_environment_state
+ \popmacro\fontclass
+ \fi\fi
+ \font_helpers_register_fontbody{#normalizedbody}}
+
+%D Checking
+
+\def\font_helpers_check_bodyfont_environment#normalizedbody#body%
+ {\ifcsname\??fontenvironmentknown\fontclass#normalizedbody\endcsname
+ % already defined
+ \else
+ \font_helpers_check_bodyfont_environment_indeed{#normalizedbody}{#body}%
+ \fi}
+
+\def\font_helpers_check_bodyfont_environment_indeed#normalizedbody#body%
+ {\font_helpers_register_environment\fontclass{#normalizedbody}%
+ \ifcsname\??fontbodyknown#normalizedbody\endcsname
+ \else
+ \font_helpers_define_unknown_font{#normalizedbody}%
+ \fi}
+
+%D We default all parameters to the main bodyfont size, so the next
+%D setup is valid too:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[24pt]
+%D \stoptyping
+%D
+%D All parameters can be redefined when needed, so one doesnot have to
+%D stick to the default ones.
+
+%D \macros
+%D {definebodyfont}
+%D
+%D The next step in defining a bodyfont involves the actual font
+%D files, which can be recognized by their extension
+%D \type{tfm}. Installing those file is often beyond the
+%D scope of the user and up to the system administrator.
+%D
+%D \showsetup{definebodyfont}
+%D
+%D This commands takes three arguments: a (series of) bodyfont
+%D size(s), the style group to which the definitions belong,
+%D and an alternative, as specified by the \TEX\ (math) families,
+%D extended with~a, b~\unknown.
+%D
+%D We show two examples, that show all the alternative
+%D scaling options. The \type{\tfa} alternatives can be
+%D extended with \type{\bfa}, \type{\slb}, etc. or even
+%D \type{e} and higher alternatives. The magic scaled
+%D values are derived from plain \TEX's \type {\magstep}:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm]
+%D [tf=cmr12,
+%D bf=cmbx12,
+%D it=cmti12,
+%D sl=cmsl12,
+%D bi=cmbxti10 at 12pt,
+%D bs=cmbxsl10 at 12pt,
+%D tfa=cmr12 scaled 1.200,
+%D tfb=cmr12 scaled 1.440,
+%D tfc=cmr12 scaled 1.728,
+%D tfd=cmr12 scaled 2.074,
+%D sc=cmcsc10 at 12pt]
+%D
+%D \definebodyfont [12pt,11pt,10pt,9pt,8pt] [rm]
+%D [tf=lbr sa 1,
+%D bf=lbd sa 1,
+%D it=lbi sa 1,
+%D sl=lbsl sa 1,
+%D bi=lbdi sa 1,
+%D bs=lbdi sa 1,
+%D tfa=lbr sa 1.200,
+%D tfb=lbr sa 1.440,
+%D tfc=lbr sa 1.728,
+%D tfd=lbr sa 2.074,
+%D sc=lbr sa 0.833]
+%D \stoptyping
+%D
+%D The second example shows that we can define more sizes at
+%D once. The main difference between these examples is that the
+%D Computer Modern Roman come in many design sizes. This means
+%D that there we cannot define them in bulk using \type{sa}.
+%D Instead of \type{rm} (roman) one can define \type{ss} (sans
+%D serif), \type{tt} (teletype), \type{hw} (hand written),
+%D \type{cg} (calygraphic) and whatever styles.
+%D
+%D The first argument may be a comma separated list. This,
+%D combined with specifications using \type{sa} can save a lot
+%D of typing. Although all arguments should be specified, we
+%D treat the second argument as optional.
+%D
+%D Defining a bodyfont involves two actions: defining the
+%D specific style related alternatives, like \type{\rma},
+%D \type{\bfa} and \type{\rmsla}, and storing the definitions
+%D of their bodyfont size related fonts. The first step is
+%D bodyfont independant but executed every time. This permits
+%D user definitions like \type{\tfw} or \type{\bfq} for real
+%D large alternatives.
+
+%D If we move design size info to the lfg file (after all only lm
+%D has design sizes) we can get rid of much code .. 2012 or so.
+
+\installcorenamespace{fontdefinitions}
+
+% [class] [name] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [name]
+
+% [class] [name] [settings] == [name] [rm] [settings]
+% [class] [10pt,11pt] [settings] == [name] [rm] [settings]
+% [class] [10pt,11pt] [name] == [10pt,11pt] [rm] [name]
+
+\unexpanded\def\definebodyfont
+ {\doquadrupleempty\font_basics_define_body_font}
+
+\def\font_basics_define_body_font[#1][#2][#3][#4]%
+ {\iffourthargument
+ \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}%
+ \else
+ \font_basics_define_body_font_class_known[#1][#2][#3]%
+ \fi}
+
+\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
+ {\pushmacro\fontclass
+ \doifelse{#4}\s!default
+ {\let\fontclass\empty}
+ {\def\fontclass{#4}}%
+ \definebodyfont[#1][#2][#3]%
+ \popmacro\fontclass}
+
+\def\font_basics_define_body_font_class_known
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_a
+ \else\ifsecondargument
+ \doubleexpandafter\font_basics_define_body_font_b
+ \else
+ \doubleexpandafter\font_basics_define_body_font_c
+ \fi\fi}
+
+\unexpanded\def\font_basics_define_body_font_b[#whatever][#specification][#dummy]% body|identifier defs|identifier
+ {\font_basics_define_body_font_a[#whatever][\s!rm][#specification]}
+
+\unexpanded\def\font_basics_define_body_font_c[#whatever][#dummya][#dummyb]% body|identifier
+ {\font_basics_define_body_font_a[#whatever][\s!rm][]}
+
+\unexpanded\def\font_basics_define_body_font_a[#whatever]%
+ {\doifelsenumber{#whatever}%
+ \font_basics_define_body_font_body
+ \font_basics_define_body_font_name
+ [#whatever]}
+
+\unexpanded\def\font_basics_define_body_font_body[#body][#style][#specification]%
+ {\doifelseassignment{#specification}
+ \font_basics_define_body_font_body_assignment
+ \font_basics_define_body_font_body_identifier
+ [#body][#style][#specification]}%
+
+\unexpanded\def\font_basics_define_body_font_name[#name][#style][#specification]%
+ {\doifelseassignment{#specification}
+ \font_basics_define_body_font_name_assignment
+ \font_basics_define_body_font_name_identifier
+ [#name][#style][#specification]}%
+
+\unexpanded\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]%
+ {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body%
+ {\normalizebodyfontsize\m_font_asked_body{#body}%
+ % normally we define quite a lot in advance, i.e global defs
+ \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
+ \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_body_assignment_b#assignments#style%
+ {\edef\m_font_asked_style{#style}%
+ \processcommalist[#assignments]\font_basics_define_body_font_defs}
+
+\unexpanded\def\font_basics_define_body_font_defs
+ {\ifx\fontclass\empty
+ \expandafter\font_basics_define_body_font_defs_nop
+ \else
+ \expandafter\font_basics_define_body_font_defs_yes
+ \fi}
+
+\unexpanded\def\font_basics_define_body_font_defs_yes_normal#assignment%
+ {\ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_yes_mm
+ \else
+ \expandafter\font_basics_define_body_font_yes_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_nop_normal#assignment%
+ {\ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_nop_mm
+ \else
+ \expandafter\font_basics_define_body_font_nop_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_yes_traced#assignment%
+ {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
+ \ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_yes_mm
+ \else
+ \expandafter\font_basics_define_body_font_yes_xx
+ \fi[#assignment]}
+
+\unexpanded\def\font_basics_define_body_font_defs_nop_traced#assignment%
+ {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
+ \ifx\m_font_asked_style\s!mm
+ \expandafter\font_basics_define_body_font_nop_mm
+ \else
+ \expandafter\font_basics_define_body_font_nop_xx
+ \fi[#assignment]}
+
+\let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_normal
+\let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_normal
+
+\appendtoks
+ \let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_traced
+ \let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_traced
+\to \t_font_tracers_definitions
+
+% We split into two characters (first part of spec) and the rest: the first two are the style and
+% the rest is a size, although in practice one will seldom define the size directly. We might even
+% drop that as it gives faster code.
+
+\unexpanded\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
+ {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+\unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
+ {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
+ \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space yes: {\expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}
+
+%D Here the rest concerns rl or lr so in this case it is not a size specifier but
+%D a directional one.
+
+\unexpanded\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local
+ {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
+ \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\noexpand\font_rscale_mm}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space nop: \expandafter\meaning\csname\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
+
+\unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
+ {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
+ \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
+ \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space yes: \expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
+
+\unexpanded\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]%
+ {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}}
+
+\unexpanded\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body%
+ {\normalizebodyfontsize\m_font_asked_body{#body}%
+ \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
+ \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}}
+
+\unexpanded\def\font_basics_define_body_font_body_identifier_b#name#style%
+ {\edef\m_font_asked_style{#style}%
+ %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}%
+ \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking
+
+\unexpanded\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]%
+ {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_name_assignment_a#name#assignments#style%
+ {%\writestatus\m!fonts{[#name:#style] => [#assignments]}%
+ \setevalue{\??fontdefinitions#name:#style}{\font_basics_define_body_font_default{#assignments}}}
+
+\unexpanded\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]%
+ {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}}
+
+\unexpanded\def\font_basics_define_body_font_name_identifier_a#name#identifier#style%
+ {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}%
+ \ifcsname\??fontdefinitions#name:#style\endcsname
+ \expandafter\let\csname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname
+ \else
+ \expandafter\def\csname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}%
+ \fi}
+
+%D The unknown:
+
+\newconditional\c_font_defining_unknown
+\newconditional\c_font_defining_state
+
+\unexpanded\def\font_helpers_define_unknown_font#body% one level only
+ {\font_helpers_register_fontbody{#body}% prevents loop, can go
+ \setfalse\c_font_defining_state
+ \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}%
+ \ifconditional\c_font_defining_state
+ \setfalse\c_font_defining_state
+ \font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
+ \ifconditional\c_font_defining_state
+ \ifconditional\c_font_defining_environment_state\else
+ \showmessage\m!fonts{14}{#body}% main
+ \fi
+ \setfalse\c_font_defining_state
+ \font_helpers_register_fontbody{#body}%
+ % needed ?
+ \ifconditional\c_font_defining_unknown
+ \else
+ \settrue\c_font_defining_unknown
+ \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}%
+ \setfalse\c_font_defining_unknown
+ \fi
+ \fi
+ \fi}
+
+% \def\font_helpers_define_unknown_check_sizes#body#relativesize%
+% {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
+% % 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}%
+ \settrue\c_font_defining_state
+ \fi}
+
+\def\font_helpers_define_unknown_check_definitions#body#style%
+ {\ifcsname\??fontdefinitions\s!default:#style\endcsname
+ \edef\m_font_asked_body{#body}%
+ \edef\m_font_asked_style{#style}%
+ \lastnamedcs
+ \settrue\c_font_defining_state
+ \fi}
+
+% \def\font_helpers_define_unknown_check_relatives#body#relativesize%
+% {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
+% % how \lastnamedcs here
+% \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
+% \settrue\c_font_defining_state
+% \fi}
+
+\def\font_helpers_define_unknown_check_relatives#body#relativesize%
+ {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
+ \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
+ \settrue\c_font_defining_state
+ \fi}
+
+\unexpanded\def\font_basics_define_body_font_default#assignments%
+ {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here?
+ \ifcsname\m_font_asked_style\endcsname\else
+ \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}%
+ \fi
+ \processcommalist[#assignments]\font_basics_define_body_font_defs
+ \let\p_font_rscale\v_font_rscale_default}
+
+%D These macros show that quite some definitions take place. Fonts are not loaded
+%D yet! This means that at format generation time, no font files are present.
+
+% \unexpanded\def\font_basics_switch_points#body%
+% {\ifcsname\??fontbodyknown#body\endcsname \else
+% % we need to check the relative sizes for this body
+% \font_helpers_define_unknown_font{#body}%
+% \fi%
+% \ifcsname\??fontbodyknown#body\endcsname % always true now
+% \font_basics_complete_switch{#body}%
+% \localbodyfontsize#body\relax
+% \normalizebodyfontsize\normalizedbodyfontsize\localbodyfontsize
+% \font_helpers_check_bodyfont_environment\normalizedbodyfontsize\normalizedbodyfontsize % !!
+% \else
+% \showmessage\m!fonts4{#body}%
+% \fi}
+
+\unexpanded\def\font_basics_switch_points#body%
+ {\ifcsname\??fontbodyknown#body\endcsname \else
+ % we need to check the relative sizes for this body
+ \font_helpers_define_unknown_font{#body}%
+ \fi%
+ \ifcsname\??fontbodyknown#body\endcsname % always true now
+ \font_basics_complete_switch{#body}%
+ \localbodyfontsize#body\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\localbodyfontsize
+ \font_helpers_check_bodyfont_environment\normalizedbodyfontsize\normalizedbodyfontsize % !!
+ \else
+ \showmessage\m!fonts4{#body}%
+ \fi}
+
+\unexpanded\def\font_basics_switch_style#style%
+ {\ifcsname\??fontstyle#style\endcsname
+ \lastnamedcs
+ \edef\fontstyle{#style}%
+ \ifmmode\mr\fi % in order to be compatible with \rm in math mode
+ % \the\everybodyfont % cleaner, in setting size as well as style
+ \else
+ \showmessage\m!fonts5{#style}%
+ \fi}
+
+%D Here comes the main font switching macros. These macros
+%D handle changes in size as well as returning to the global
+%D bodyfont size.
+
+\ifdefined\font_preloads_at_definition \else \let\font_preloads_at_definition\relax \fi
+
+\def\font_helpers_set_font#method#specification%
+ {\edef\m_font_specification{#specification}%
+ \ifx\m_font_specification\empty \else
+ \ifx\m_font_specification\v!global % we can have all kind of presets
+ \restoreglobalbodyfont
+ \else
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_check_size}%
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_set_font{#method}}%
+ \ifproductionrun
+ \font_preloads_at_definition
+ \font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \ifx\defaultfontclass\empty
+ \let\defaultfontclass\fontclass
+ \fi
+ \fi
+ \fi
+ \currentxfontsize\zerocount
+ \fi}
+
+\def\font_helpers_set_font_check_size#option%
+ {\doifelsenumber{#option}{\font_helpers_check_bodyfont_environment{#option}{#option}}\donothing}
+
+\def\font_helpers_set_font_set_font#method#option% method=1: set, method=2: switch
+ {\doifsomething{#option}{\font_helpers_set_font_set_font_option{#method}{#option}}}
+
+\def\font_helpers_set_font_set_font_option#method#option%
+ {\doifelsenumber{#option}%
+ \font_helpers_set_font_set_font_option_body
+ \font_helpers_set_font_set_font_option_keyword
+ {#method}{#option}{#option}}
+
+\newmacro\m_font_keyword
+
+\unexpanded\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
+ {\edef\m_font_keyword{#keyword}%
+ \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname
+ \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}%
+ \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}%
+ \else\ifx\m_font_keyword\v!reset
+ \let\fontstyle\empty % new 31/7/2006
+ \let\fontsize \empty
+ \else\ifcsname\??fontstyle\m_font_keyword\endcsname
+ \let\fontstyle\m_font_keyword
+ \else
+ \setcurrentfontclass\m_font_keyword
+ \ifcase#method\relax
+ \let\globalfontclass\globalfontclass % -)
+ \else
+ \let\globalfontclass\fontclass
+ \fi
+ \font_helpers_set_fontstyle_of_fontclass
+ \fi\fi\fi}
+
+\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later
+ {\let\fontstyle\s!rm}
+
+\unexpanded\def\font_helpers_set_font_set_font_option_body#method#body#message%
+ {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else
+ \font_helpers_define_unknown_font\normalizedsetfont
+ \fi
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname
+ \localbodyfontsize\normalizedsetfont
+ \let\normalizedbodyfontsize\normalizedsetfont
+ \else
+ \showmessage\m!fonts4{#message}%
+ %\font_helpers_set_font_set_font_option_body_fallbacks{#method}{#body}%
+ \fi}
+
+% we need to check the fontclass
+
+\def\registerfontclass#class%
+ {\letgvalue{\??fontclassyes#class}\v!yes} % global ?
+
+\def\setcurrentfontclass#class%
+ {\ifcsname\??fontclassyes#class\endcsname
+ \edef\fontclass{#class}%
+ \else\ifcsname\??fontclassnop#class\endcsname
+ % already tried
+ \else % too messy: \ifcase\currentgrouplevel % (unpredictable)
+ \trycurrentfontclass{#class}%
+ \fi\fi} % \fi}
+
+\ifdefined\trycurrentfontclass \else
+
+ \unexpanded\def\trycurrentfontclass#typeface%
+ {\letvalueempty{\??fontclassnop#typeface}}
+
+\fi
+
+\let\defaultfontstyle \s!rm
+\let\defaultfontalternative\s!tf
+\let\defaultfontsize \empty
+\let\defaultfontface \!!zerocount
+
+%D So far for synchronisation. (We can inline the following macros.)
+
+\unexpanded\def\setcurrentfont#body#style#alternative#size% not used
+ {\edef\fontbody {#body}%
+ \edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\setcurrentfontbody#body% % not used
+ {\edef\fontbody{#body}%
+ \font_helpers_synchronize_font}
+
+% For Taco: optional fall backs:
+
+\ifdefined\font_typescripts_inherit_check \else
+ \let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini
+\fi
+
+\unexpanded\def\font_helpers_set_current_font_style#style%
+ {\edef\fontstyle{#style}%
+ \font_typescripts_inherit_check\fontstyle
+ \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_xsize_alternative#xsize#alternative%
+ {\edef\fontface{#xsize}%
+ \edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative#alternative%
+ {\edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_size#size%
+ {\edef\fontsize{#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl
+ {\edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_size#style#size% \rma
+ {\edef\fontstyle{#style}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
+ {\edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla
+ {\edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization % double? better in everymath?
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
+ {\ifx\fontclass\empty
+ \applyfontstrategies
+ \else
+ \applyfontclassstrategies
+ \fi
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+%D This is the resolver for special cases (sizes) and in practice it is not called that often
+%D so further optimization makes no sense.
+
+\def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_b
+ \fi}
+
+\def\font_helpers_check_strategy_class_b % --- --- --- def % pt tt bf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_c
+ \fi}
+
+\def\font_helpers_check_strategy_class_c % --- --- def --- % pt tt tf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_d
+ \fi}
+
+\def\font_helpers_check_strategy_class_d % --- --- def def % pt tt tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_e
+ \fi}
+
+\def\font_helpers_check_strategy_class_e % --- def def def % pt rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_class_f
+ \fi}
+
+\def\font_helpers_check_strategy_class_f % def def def def % rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_a
+ \fi}
+
+% no class
+
+\def\font_helpers_check_strategy_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_b
+ \fi}
+
+\def\font_helpers_check_strategy_b % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_c
+ \fi}
+
+\def\font_helpers_check_strategy_c % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_d
+ \fi}
+
+\def\font_helpers_check_strategy_d % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_e
+ \fi}
+
+\def\font_helpers_check_strategy_e % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \lastnamedcs
+ \else
+ \expandafter\font_helpers_check_strategy_f
+ \fi}
+
+\def\font_helpers_check_strategy_f % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \lastnamedcs
+ \fi}
+
+\let\applyfontstrategies \font_helpers_check_strategy_a
+\let\applyfontclassstrategies\font_helpers_check_strategy_class_a
+
+%D Let's synchronize:
+
+\newconditional\c_font_synchronize \settrue\c_font_synchronize
+
+\prependtoks
+ \ifconditional\c_font_synchronize
+ \font_helpers_synchronize_math
+ \font_helpers_synchronize_font % problem: syncs last font
+ \fi
+\to \everybodyfont
+
+%D Setting the normal sizes as well as the x and xx smaller
+%D sizes is accomplished by the next set of macros. When in
+%D math mode, the commands \type{\tx} and \type{\txx} are
+%D just a switch to the script and double script styles, but
+%D in text mode the values defined by the bodyfontenvironment are
+%D used. Here we also set \type{\currentxfontsize}.
+
+\def\font_helpers_set_current_font_xxx_alternative#alternative#xsize#scriptstyle%
+ {\ifmmode
+ #scriptstyle%
+ \else
+ \font_helpers_set_current_xsize_alternative{#xsize}{#alternative}%
+ \fi}
+
+\def\font_helpers_set_current_font_x_alternative#alternative%
+ {\font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\def\font_helpers_set_current_font_xx_alternative#alternative%
+ {\font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
+ \currentxfontsize\plustwo
+ \let\tx\empty
+ \let\txx\empty}
+
+\def\font_helpers_reset_x_fontsize
+ {\ifcase\currentxfontsize\else
+ \currentxfontsize\zerocount
+ \let\tx\normaltx
+ \let\txx\normaltxx
+ \fi}
+
+\def\font_helpers_check_nested_x_fontsize % option
+% {\ifcase\currentxfontsize\else\ifx\fontsize\empty\else
+% \currentxfontsize\zerocount
+% \let\fontsize\empty
+% \let\tx\normaltx
+% \let\txx\normaltxx
+% \fi\fi}
+ {}
+
+\def\font_helpers_set_current_font_x_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\def\font_helpers_set_current_font_xx_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
+ \currentxfontsize\plustwo
+ \let\tx\empty
+ \let\txx\empty}
+
+% This alterative is not really needed, but for old time's sake
+% we keep it there. We can speed it up when needed.
+
+\def\font_helpers_set_current_font_x_style_alternative #alternative{\csname#alternative\endcsname\tx}
+\def\font_helpers_set_current_font_xx_style_alternative#alternative{\csname#alternative\endcsname\txx}
+
+%D These macros also show us that when we call for \type{\tx},
+%D this macro is redefined to be \type{\txx}. Therefore calls
+%D like:
+%D
+%D \startbuffer
+%D {small \tx is \tx beautiful}
+%D {small \tx is \txx beautiful}
+%D {small \txx is \tx beautiful}
+%D {small \txx is \txx beautiful}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D result in:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D Setting the main size involves the style list and therefore
+%D takes a bit more time. Keep in mind that the fontsize is
+%D represented by a character or empty.
+
+% \unexpanded\def\tx {\font_helpers_set_current_font_x_alternative \fontalternative}
+% \unexpanded\def\txx{\font_helpers_set_current_font_xx_alternative\fontalternative}
+
+\unexpanded\def\tx
+ {\ifmmode
+ \scriptstyle
+ \else
+ \let\fontface\!!plusfour
+ \let\fontalternative\fontalternative
+ \font_helpers_synchronize_font
+ \fi
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\unexpanded\def\txx
+ {\ifmmode
+ \scriptscriptstyle
+ \else
+ \let\fontface\!!plusfive
+ \let\fontalternative\fontalternative
+ \font_helpers_synchronize_font
+ \fi
+ \currentxfontsize\plustwo}
+
+\let\normaltx \tx
+\let\normaltxx\txx
+
+%D When asking for a complete font switch, for instance from 10
+%D to 12~points, the next macro does the job. First we
+%D normalize the size, next we define the current range of
+%D text, script and scriptscript sizes, then we set the text
+%D fonts and the math families and finally we activate the
+%D default typeface and also set the font specific parameters
+%D assigned to \type{\everybodyfont}
+
+\def\textface {\currentbodyfontdimension\s!text }
+\def\scriptface {\currentbodyfontdimension\s!script }
+\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript}
+\def\xtextface {\currentbodyfontdimension\s!x }
+\def\xxtextface {\currentbodyfontdimension\s!xx }
+
+% \unexpanded\def\font_basics_complete_switch#size%
+% {\bodyfontsize#size\relax
+% \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
+% \edef\textface {\currentbodyfontdimension\s!text }%
+% \edef\scriptface {\currentbodyfontdimension\s!script }%
+% \edef\scriptscriptface{\currentbodyfontdimension\s!scriptscript}}%
+
+\installcorenamespace{fontbodyfaces}
+
+\unexpanded\def\font_basics_complete_switch#size%
+ {\bodyfontsize#size\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
+ \expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname
+ \ifx\font_basics_set_faces\relax
+ \font_basics_set_faces_preset
+ \fi
+ \font_basics_set_faces}
+
+\def\font_basics_set_faces_preset
+ {\edef\font_basics_set_faces{% 0.2 sec on 10K \tfa
+ \noexpand\edef\noexpand\textface {\currentbodyfontdimension\s!text }%
+ \noexpand\edef\noexpand\scriptface {\currentbodyfontdimension\s!script }%
+ \noexpand\edef\noexpand\scriptscriptface{\currentbodyfontdimension\s!scriptscript}%
+ \noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }%
+ \noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }%
+ }%
+ \global\expandafter\let\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
+
+% \def\currentbodyfontdimension#parameter%
+% {\the\dimexpr
+% \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname
+% \csname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname \else
+% \ifcsname\??fontenvironments\fontclass\s!default #parameter\endcsname
+% \csname\??fontenvironments\fontclass\s!default #parameter\endcsname
+% \dimexpr\normalizedbodyfontsize\relax \else % factor
+% \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname
+% \csname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \else
+% \csname\??fontenvironments \s!default #parameter\endcsname
+% \dimexpr\normalizedbodyfontsize\relax \fi\fi\fi % factor
+% \relax}
+
+\def\currentbodyfontdimension#parameter% there can be factors here
+ {\the\dimexpr
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\??fontenvironments\fontclass\s!default#parameter\endcsname
+ \lastnamedcs
+ \dimexpr\normalizedbodyfontsize\relax
+ \else\ifcsname\??fontenvironments\normalizedbodyfontsize#parameter\endcsname
+ \lastnamedcs
+ \else
+ \csname\??fontenvironments\s!default#parameter\endcsname
+ \dimexpr\normalizedbodyfontsize\relax
+ \fi\fi\fi
+ \relax}
+
+%D \macros
+%D {setupbodyfont,switchtobodyfont}
+%D
+%D The next two macros are user ones. With \type{\setupbodyfont}
+%D one can set the document bodyfont size, font family, style
+%D and/or options defined in files, for example:
+%D
+%D \starttyping
+%D \setupbodyfont[modern,12pt,roman]
+%D \stoptyping
+%D
+%D This command affects the document as a whole: text, headers
+%D and footers. The second macro however affects only the text:
+%D
+%D \starttyping
+%D \switchtobodyfont[10pt]
+%D \stoptyping
+%D
+%D So we've got:
+%D
+%D \showsetup{setupbodyfont}
+%D \showsetup{switchtobodyfont}
+%D
+%D Both macros look alike. The second one also has to take
+%D all kind of keywords into account.
+
+\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
+\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
+
+% \newtoks \everysetupbodyfont
+% \newtoks \everyswitchtobodyfont
+
+\unexpanded\def\setupbodyfont
+ {\doifelsenextoptionalcs\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop}
+
+\def\font_basics_setupbodyfont_nop
+ {\restoreglobalbodyfont
+ \saveinterlinespace}
+
+\def\font_basics_setupbodyfont_yes[#specification]%
+ {\doifsomething{#specification}
+ {\font_helpers_set_font\plusone{#specification}%
+ \globalbodyfontsize\localbodyfontsize
+ \normalizebodyfontsize\normalizedglobalbodyfontsize\globalbodyfontsize
+ \let\globalfontstyle\fontstyle
+ \ifproductionrun
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \fi
+ \the\everysetupbodyfont}}
+
+\unexpanded\def\font_basics_switchtobodyfont#specification%
+ {\edef\m_font_step{\font_bodyfontvariable{#specification}}%
+ \ifx\m_font_step\empty
+ \font_helpers_set_font\zerocount{#specification}%
+ \else
+ \font_helpers_switch_bodyfont_step % so we have a fast [small] switch
+ \fi
+ \the\everybodyfont
+ \the\everyswitchtobodyfont}
+
+\unexpanded\def\switchtobodyfont[#specification]% could become an ifx
+ {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}}
+
+
+\unexpanded\def\usebodyfontparameter#1%
+ {\edef\m_font_bodyfont_asked{#1\c!bodyfont}%
+ \ifx\m_font_bodyfont_asked\empty\else
+ \font_basics_switchtobodyfont\m_font_bodyfont_asked
+ \fi}
+
+\def\font_helpers_switch_bodyfont_step
+ {\font_basics_switch_points\m_font_step
+ \font_basics_switch_style \fontstyle}
+
+%D The following alternative is meant for math||to||text
+%D switching and will be optimized.
+
+\unexpanded\def\fastswitchtobodyfont#name%
+ {\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
+ %\edef\futurebodyfontsize{\csname\??fontenvironments\normalizedbodyfontsize#name\endcsname}%
+ \edef\futurebodyfontsize{\lastnamedcs}%
+ \ifcsname\??fontbodyknown\futurebodyfontsize\endcsname
+ \font_basics_complete_switch\futurebodyfontsize
+ \localbodyfontsize\futurebodyfontsize\relax
+ \fi
+ \fi
+ \csname\??fontstyle\fontstyle\endcsname
+ \the\everybodyfont}
+
+%D \starttyping
+%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
+%D \stoptyping
+
+%D \macros
+%D {usebodyfont}
+%D
+%D This looks nicer then a switch in the preamble
+%D
+%D \starttyping
+%D \usebodyfont[pagella,10pt]
+%D \usebodyfont[termes,10pt]
+%D \usebodyfont[dejavu,10pt]
+%D
+%D \setupbodyfont[dejavu]
+%D
+%D \starttext
+%D test
+%D \stoptext
+%D \stoptyping
+
+% \unexpanded\def\usebodyfont[#1]%
+% {\pushmacro\fontclass
+% \switchtobodyfont[#1]%
+% \popmacro\fontclass
+% \ifx\fontclass\empty\else\setupbodyfont\relax\fi}
+
+\unexpanded\def\usebodyfont[#1]%
+ {\pushmacro\fontclass
+ \font_helpers_set_font\zerocount{#1}%
+ \popmacro\fontclass
+ \ifx\fontclass\empty \else
+ \font_basics_setupbodyfont_nop
+ \fi}
+
+%D Handy for manuals:
+
+
+%D The \type {\tochar} commmand takes a specification:
+%D
+%D \starttabulate[|l|l|l|]
+%D \NC e \NC entity \NC e:eacute \NC \NR
+%D \NC x \NC hexadecimal unicode \NC x:013D \NC \NR
+%D \NC d \NC decimal unicode \NC d:123 \NC \NR
+%D \NC s \NC hexadecimal index (slot) \NC s:210D \NC \NR
+%D \NC i \NC decimal index \NC i:456 \NC \NR
+%D \NC n \NC name \NC n:eight \NC \NR
+%D \NC c \NC name \NC c:x \NC \NR
+%D \stoptabulate
+%D
+%D This is an expandable command!
+
+\unexpanded\def\fontchar #character{\clf_fontchar{#character}}
+\unexpanded\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax}
+ \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef)
+
+%D The next auxilliary macro is an alternative to \type {\fontname}.
+
+\def\purefontname#font{\clf_purefontname{\fontname#font}}
+
+%D \macros
+%D {switchstyleonly}
+%D
+%D For switching a style but keeping the alternative, there
+%D is:
+%D
+%D \starttyping
+%D {\bf text \switchstyleonly\ss text}
+%D {\bf text \switchstyleonly[ss]text}
+%D {\sl text \switchstyleonly[sansserif]text}
+%D \stoptyping
+
+\unexpanded\def\switchstyleonly
+ {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg}
+
+\def\font_basics_switch_style_only_arg#name% stupid version
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle\checkedstrippedcsname#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+\def\font_basics_switch_style_only_opt[#name]% todo : check
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+%D \macros
+%D {definebodyfontswitch}
+%D
+%D \PLAIN\ \TEX\ defines some macro's like \type{\tenpoint}
+%D to switch to a specific bodyfontsize. Just for the sake of
+%D compatibility we can define them like:
+%D
+%D \starttyping
+%D \definebodyfontswitch [twelvepoint] [12pt]
+%D \stoptyping
+%D
+%D We don't support language specific synonyms here.
+
+\unexpanded\def\definebodyfontswitch
+ {\dodoubleargument\font_basics_define_bodyfont_switch}
+
+\def\font_basics_define_bodyfont_switch[#command][#specification]% no longer a commalist (not useful)
+ {\setvalue{#command}{\switchtobodyfont[#specification]}}%
+
+%D \macros
+%D {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
+%D
+%D When we're typesetting at for instance 10pt, we can call for
+%D the \type{small} as well as the \type{big} alternative,
+%D related to this main size, using \type{\switchtobodyfont[small]}.
+%D The three alternatives can be activated by the next three
+%D system calls and are defined by the bodyfontenvironment.
+
+\newmacro\m_font_step
+
+\def\font_helpers_set_bodyfont_step#step%
+ {\edef\m_font_step{\font_bodyfontvariable{#step}}% not always \cs
+ \font_basics_switch_points\m_font_step
+ \font_basics_switch_style \fontstyle}
+
+\unexpanded\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont}
+\unexpanded\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont}
+
+\unexpanded\def\setmainbodyfont
+ {\font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+%D \macros
+%D {restoreglobalbodyfont}
+%D
+%D Users can set whatever font available while typesetting text.
+%D Pagenumbers, footers, headers etc. however must be typeset
+%D in the main bodyfont and style of the document. Returning to
+%D the global state can be done with the next macro:
+%D
+%D This macro has to be called when entering the pagebody
+%D handling routine as well as the footnote insert routine.
+%D Users can access this feature |<|for instance when one wants
+%D to typeset tables and alike in the main bodyfont and style
+%D while the running text is temporary set to a smaller one|>|
+%D by saying \type{\switchtobodyfont[global]}.
+
+\let\globalfontstyle\s!rm
+
+\unexpanded\def\fullrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \let\fontface\defaultfontface
+ \currentxfontsize\zerocount
+ \let\fontclass\globalfontclass
+ \font_basics_switch_points\normalizedglobalbodyfontsize
+ \font_basics_switch_style\globalfontstyle
+ \redoconvertfont % just in case a pagebreak occurs
+ \tf
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+\unexpanded\def\partialrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \let\fontface\defaultfontface
+ \currentxfontsize\zerocount
+ \redoconvertfont
+ \tf
+ \the\everybodyfont % indeed needed
+ \the\everyglobalbodyfont % indeed needed
+ \saveinterlinespace}
+
+\unexpanded\def\restoreglobalbodyfont % ook style etc
+ {\ifx\fontclass\globalfontclass
+ \ifx\fontstyle\globalfontstyle
+ \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
+ \partialrestoreglobalbodyfont
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi}
+
+% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
+
+%D Here are some fast variants that can be used in cases where no font
+%D system is needed and where fonts are frozen:
+%D
+%D \starttyping
+%D \definefont [TestA][Serif at 10pt]
+%D \predefinefont[TestB][Serif at 20pt]
+%D
+%D \testfeatureonce{1000}{{\TestA}} % .312
+%D \testfeatureonce{1000}{{\TestB}} % < .016
+%D \testfeatureonce{1000}{{\definedfont[Serif at 30pt]}} % .312
+%D \testfeatureonce{1000}{{\predefinedfont[Serif at 40pt]}} % < .016
+%D \stoptyping
+
+\installcorenamespace{predefinedfont}
+
+\unexpanded\def\predefinefont[#1]#2[#3]% global !
+ {\setugvalue{#1}{\font_basics_predefine{#1}{#3}}}
+
+\unexpanded\def\predefinedfont[#1]% global !
+ {\ifcsname\??predefinedfont#1\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_predefined{#1}%
+ \fi}
+
+\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}
+
+\unexpanded\def\font_basics_predefined#1%
+ {\font_basics_predefine{\??predefinedfont#1}{#1}}
+
+%D Handy helper:
+
+\unexpanded\def\savedefinedfont[#1]%
+ {\bgroup
+ \definedfont[#1]%
+ \xdef\saveddefinedfontid {\number\fontid\font}%
+ \xdef\saveddefinedfontname{\fontname\font}%
+ \egroup}
+
+\def\saveddefinedfontid {\number\fontid\font}
+\def\saveddefinedfontname{\fontname\font}
+
+% yes or no:
+
+% \let\font_basics_check_text_bodyfont_slow\font_basics_check_text_bodyfont
+%
+% \unexpanded\def\font_basics_check_text_bodyfont
+% {\ifproductionrun
+% % not per se \s!..'s
+% \glet\font_basics_check_text_bodyfont \font_basics_check_text_bodyfont_slow
+% \glet\font_basics_check_text_bodyfont_fast\relax
+% \expandafter\font_basics_check_text_bodyfont
+% \else
+% \expandafter\font_basics_check_text_bodyfont_fast
+% \fi}
+%
+% \def\font_basics_check_text_bodyfont_fast#style#alternative#size% size can be empty (checking needed as \bf is already defined)
+% {\setugvalue{#style#size}% \rma
+% {\let\fontstyle#style%
+% \let\fontsize #size%
+% \font_helpers_check_big_math_synchronization % double? better in everymath?
+% \font_helpers_synchronize_font}%
+% \setugvalue{#alternative#size}% \sla
+% {\let\fontalternative#alternative%
+% \let\fontsize #size%
+% \font_helpers_check_big_math_synchronization % double? better in everymath?
+% \font_helpers_synchronize_font}%
+% \setugvalue{#style#alternative#size}% \rmsla
+% {\let\fontstyle #style%
+% \let\fontalternative#alternative%
+% \let\fontsize #size%
+% \font_helpers_check_big_math_synchronization % double? better in everymath?
+% \font_helpers_synchronize_font}%
+% \ifcsname\s!normal#style\endcsname % text/math check
+% \expandafter\let\csname#style\expandafter\endcsname\csname\s!normal#style\endcsname
+% \else
+% \setugvalue{#style}% \rm
+% {\let\fontstyle#style%
+% \font_typescripts_inherit_check\fontstyle
+% \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet
+% \font_helpers_synchronize_font}%
+% \fi
+% \ifcsname\s!normal#alternative\endcsname % text/math check
+% \expandafter\let\csname#alternative\expandafter\endcsname\csname\s!normal#alternative\endcsname
+% \else
+% \setugvalue{#alternative}% \sl
+% {\let\fontalternative#alternative%
+% \font_helpers_synchronize_font}%
+% \fi
+% \setugvalue{#style\s!x}% \rmx
+% {\csname#style\endcsname\tx}%
+% \setugvalue{#style\s!xx}% \rmxx
+% {\csname#style\endcsname\txx}%
+% \setugvalue{#alternative\s!x}% \slx
+% {\font_helpers_check_nested_x_fontsize
+% \ifmmode
+% \scriptstyle
+% \else
+% \let\fontface\!!plusfour
+% \let\fontalternative#alternative%
+% \font_helpers_synchronize_font
+% \fi
+% \currentxfontsize\plusone
+% \let\tx\txx}%
+% \setugvalue{#alternative\s!xx}% \slxx
+% {\font_helpers_check_nested_x_fontsize
+% \ifmmode
+% \scriptscriptstyle
+% \else
+% \let\fontface\!!plusfive
+% \let\fontalternative#alternative%
+% \font_helpers_synchronize_font
+% \fi
+% \currentxfontsize\plustwo
+% \let\tx\empty
+% \let\txx\empty}%
+% \setugvalue{#style#alternative}% \rmsl
+% {\let\fontstyle #style%
+% \let\fontalternative#alternative%
+% \font_helpers_synchronize_font}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-inj.lua b/Master/texmf-dist/tex/context/base/mkiv/font-inj.lua
new file mode 100644
index 00000000000..89370210d41
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-inj.lua
@@ -0,0 +1,1196 @@
+if not modules then modules = { } end modules ['font-inj'] = {
+ version = 1.001,
+ comment = "companion to font-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This property based variant is not faster but looks nicer than the attribute one. We
+-- need to use rawget (which is apbout 4 times slower than a direct access but we cannot
+-- get/set that one for our purpose! This version does a bit more with discretionaries
+-- (and Kai has tested it with his collection of weird fonts.)
+
+-- There is some duplicate code here (especially in the the pre/post/replace branches) but
+-- we go for speed. We could store a list of glyph and mark nodes when registering but it's
+-- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
+-- being too clever here is dangerous.
+
+-- The subtype test is not needed as there will be no (new) properties set, given that we
+-- reset the properties.
+
+if not nodes.properties then return end
+
+local next, rawget = next, rawget
+local utfchar = utf.char
+local fastcopy = table.fastcopy
+
+local trace_injections = false trackers.register("fonts.injections", function(v) trace_injections = v end)
+
+local report_injections = logs.reporter("fonts","injections")
+
+local attributes, nodes, node = attributes, nodes, node
+
+fonts = fonts
+local fontdata = fonts.hashes.identifiers
+
+nodes.injections = nodes.injections or { }
+local injections = nodes.injections
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local newkern = nodepool.kern
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+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 traverse_id = nuts.traverse_id
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local find_tail = nuts.tail
+
+local properties = nodes.properties.data
+
+function injections.installnewkern(nk)
+ newkern = nk or newkern
+end
+
+local nofregisteredkerns = 0
+local nofregisteredpairs = 0
+local nofregisteredmarks = 0
+local nofregisteredcursives = 0
+local keepregisteredcounts = false
+
+function injections.keepcounts()
+ keepregisteredcounts = true
+end
+
+function injections.resetcounts()
+ nofregisteredkerns = 0
+ nofregisteredpairs = 0
+ nofregisteredmarks = 0
+ nofregisteredcursives = 0
+ keepregisteredcounts = false
+end
+
+-- We need to make sure that a possible metatable will not kick in unexpectedly.
+
+-- function injections.reset(n)
+-- local p = rawget(properties,n)
+-- if p and rawget(p,"injections") then
+-- p.injections = nil
+-- end
+-- end
+
+-- function injections.copy(target,source)
+-- local sp = rawget(properties,source)
+-- if sp then
+-- local tp = rawget(properties,target)
+-- local si = rawget(sp,"injections")
+-- if si then
+-- si = fastcopy(si)
+-- if tp then
+-- tp.injections = si
+-- else
+-- propertydata[target] = {
+-- injections = si,
+-- }
+-- end
+-- else
+-- if tp then
+-- tp.injections = nil
+-- end
+-- end
+-- end
+-- end
+
+function injections.reset(n)
+ local p = rawget(properties,n)
+ if p then
+ p.injections = false -- { }
+ else
+ properties[n] = false -- { injections = { } }
+ end
+end
+
+function injections.copy(target,source)
+ local sp = rawget(properties,source)
+ if sp then
+ local tp = rawget(properties,target)
+ local si = rawget(sp,"injections")
+ if si then
+ si = fastcopy(si)
+ if tp then
+ tp.injections = si
+ else
+ propertydata[target] = {
+ injections = si,
+ }
+ end
+ elseif tp then
+ tp.injections = false -- { }
+ else
+ properties[target] = { injections = { } }
+ end
+ else
+ local tp = rawget(properties,target)
+ if tp then
+ tp.injections = false -- { }
+ else
+ properties[target] = false -- { injections = { } }
+ end
+ end
+end
+
+function injections.setligaindex(n,index)
+ local p = rawget(properties,n)
+ if p then
+ local i = rawget(p,"injections")
+ if i then
+ i.ligaindex = index
+ else
+ p.injections = {
+ ligaindex = index
+ }
+ end
+ else
+ properties[n] = {
+ injections = {
+ ligaindex = index
+ }
+ }
+ end
+end
+
+function injections.getligaindex(n,default)
+ local p = rawget(properties,n)
+ if p then
+ local i = rawget(p,"injections")
+ if i then
+ return i.ligaindex or default
+ end
+ end
+ return default
+end
+
+function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes
+ local dx = factor*(exit[1]-entry[1])
+ local dy = -factor*(exit[2]-entry[2])
+ local ws = tfmstart.width
+ local wn = tfmnext.width
+ nofregisteredcursives = nofregisteredcursives + 1
+ if rlmode < 0 then
+ dx = -(dx + wn)
+ else
+ dx = dx - ws
+ end
+ --
+ local p = rawget(properties,start)
+ if p then
+ local i = rawget(p,"injections")
+ if i then
+ i.cursiveanchor = true
+ else
+ p.injections = {
+ cursiveanchor = true,
+ }
+ end
+ else
+ properties[start] = {
+ injections = {
+ cursiveanchor = true,
+ },
+ }
+ end
+ local p = rawget(properties,nxt)
+ if p then
+ local i = rawget(p,"injections")
+ if i then
+ i.cursivex = dx
+ i.cursivey = dy
+ else
+ p.injections = {
+ cursivex = dx,
+ cursivey = dy,
+ }
+ end
+ else
+ properties[nxt] = {
+ injections = {
+ cursivex = dx,
+ cursivey = dy,
+ },
+ }
+ end
+ return dx, dy, nofregisteredcursives
+end
+
+function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
+ local x = factor*spec[1]
+ local y = factor*spec[2]
+ local w = factor*spec[3]
+ local h = factor*spec[4]
+ 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
+ local rightkern = w - x -- to normal kerns where we set only leftkern
+ if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then
+ nofregisteredpairs = nofregisteredpairs + 1
+ if rlmode and rlmode < 0 then
+ leftkern, rightkern = rightkern, leftkern
+ end
+ if not injection then
+ injection = "injections"
+ end
+ local p = rawget(properties,current)
+ if p then
+ local i = rawget(p,injection)
+ if i then
+ if leftkern ~= 0 then
+ i.leftkern = (i.leftkern or 0) + leftkern
+ end
+ if rightkern ~= 0 then
+ i.rightkern = (i.rightkern or 0) + rightkern
+ end
+ if yoffset ~= 0 then
+ i.yoffset = (i.yoffset or 0) + yoffset
+ end
+ elseif leftkern ~= 0 or rightkern ~= 0 then
+ p[injection] = {
+ leftkern = leftkern,
+ rightkern = rightkern,
+ yoffset = yoffset,
+ }
+ else
+ p[injection] = {
+ yoffset = yoffset,
+ }
+ end
+ elseif leftkern ~= 0 or rightkern ~= 0 then
+ properties[current] = {
+ [injection] = {
+ leftkern = leftkern,
+ rightkern = rightkern,
+ yoffset = yoffset,
+ },
+ }
+ else
+ properties[current] = {
+ [injection] = {
+ yoffset = yoffset,
+ },
+ }
+ end
+ return x, y, w, h, nofregisteredpairs
+ end
+ end
+ return x, y, w, h -- no bound
+end
+
+-- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between
+-- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in
+-- the previous case)
+
+function injections.setkern(current,factor,rlmode,x,injection)
+ local dx = factor * x
+ if dx ~= 0 then
+ nofregisteredkerns = nofregisteredkerns + 1
+ local p = rawget(properties,current)
+ if not injection then
+ injection = "injections"
+ end
+ if p then
+ local i = rawget(p,injection)
+ if i then
+ i.leftkern = dx + (i.leftkern or 0)
+ else
+ p[injection] = {
+ leftkern = dx,
+ }
+ end
+ else
+ properties[current] = {
+ [injection] = {
+ leftkern = dx,
+ },
+ }
+ end
+ return dx, nofregisteredkerns
+ else
+ return 0, 0
+ end
+end
+
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
+ local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
+ nofregisteredmarks = nofregisteredmarks + 1
+ -- markanchors[nofregisteredmarks] = base
+ if rlmode >= 0 then
+ dx = tfmbase.width - dx -- see later commented ox
+ end
+ local p = rawget(properties,start)
+ -- hm, dejavu serif does a sloppy mark2mark before mark2base
+ if p then
+ local i = rawget(p,"injections")
+ if i then
+ if i.markmark then
+ -- out of order mkmk: yes or no or option
+ else
+ i.markx = dx
+ i.marky = dy
+ i.markdir = rlmode or 0
+ i.markbase = nofregisteredmarks
+ i.markbasenode = base
+ i.markmark = mkmk
+ end
+ else
+ p.injections = {
+ markx = dx,
+ marky = dy,
+ markdir = rlmode or 0,
+ markbase = nofregisteredmarks,
+ markbasenode = base,
+ markmark = mkmk,
+ }
+ end
+ else
+ properties[start] = {
+ injections = {
+ markx = dx,
+ marky = dy,
+ markdir = rlmode or 0,
+ markbase = nofregisteredmarks,
+ markbasenode = base,
+ markmark = mkmk,
+ },
+ }
+ end
+ return dx, dy, nofregisteredmarks
+end
+
+local function dir(n)
+ return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
+end
+
+local function showchar(n,nested)
+ local char = getchar(n)
+ report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char)
+end
+
+local function show(n,what,nested,symbol)
+ if n then
+ local p = rawget(properties,n)
+ if p then
+ local i = rawget(p,what)
+ if i then
+ local leftkern = i.leftkern or 0
+ local rightkern = i.rightkern or 0
+ local yoffset = i.yoffset or 0
+ local markx = i.markx or 0
+ local marky = i.marky or 0
+ local markdir = i.markdir or 0
+ local markbase = i.markbase or 0
+ local cursivex = i.cursivex or 0
+ local cursivey = i.cursivey or 0
+ local ligaindex = i.ligaindex or 0
+ local cursbase = i.cursiveanchor
+ local margin = nested and 4 or 2
+ --
+ if rightkern ~= 0 or yoffset ~= 0 then
+ report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
+ elseif leftkern ~= 0 then
+ report_injections("%w%s kern: dx %p",margin,symbol,leftkern)
+ end
+ if markx ~= 0 or marky ~= 0 or markbase ~= 0 then
+ report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
+ end
+ if cursivex ~= 0 or cursivey ~= 0 then
+ if cursbase then
+ report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ else
+ report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ end
+ elseif cursbase then
+ report_injections("%w%s curs: base",margin,symbol)
+ end
+ if ligaindex ~= 0 then
+ report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
+ end
+ end
+ end
+ end
+end
+
+local function showsub(n,what,where)
+ report_injections("begin subrun: %s",where)
+ for n in traverse_id(glyph_code,n) do
+ showchar(n,where)
+ show(n,what,where," ")
+ end
+ report_injections("end subrun")
+end
+
+local function trace(head,where)
+ report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
+ where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
+ local n = head
+ while n do
+ local id = getid(n)
+ if id == glyph_code then
+ showchar(n)
+ show(n,"injections",false," ")
+ show(n,"preinjections",false,"<")
+ show(n,"postinjections",false,">")
+ show(n,"replaceinjections",false,"=")
+ elseif id == disc_code then
+ local pre = getfield(n,"pre")
+ local post = getfield(n,"post")
+ local replace = getfield(n,"replace")
+ if pre then
+ showsub(pre,"preinjections","pre")
+ end
+ if post then
+ showsub(post,"postinjections","post")
+ end
+ if replace then
+ showsub(replace,"replaceinjections","replace")
+ end
+ end
+ n = getnext(n)
+ end
+ report_injections("end run")
+end
+
+local function show_result(head)
+ local current = head
+ local skipping = false
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",
+ getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
+ skipping = false
+ elseif id == kern_code then
+ report_injections("kern: %p",getfield(current,"kern"))
+ skipping = false
+ elseif not skipping then
+ report_injections()
+ skipping = true
+ end
+ current = getnext(current)
+ end
+end
+
+local function collect_glyphs(head,offsets)
+ local glyphs, glyphi, nofglyphs = { }, { }, 0
+ local marks, marki, nofmarks = { }, { }, 0
+ local nf, tm = nil, nil
+ local n = head
+
+ local function identify(n,what)
+ local f = getfont(n)
+ if f ~= nf then
+ nf = f
+ -- other hash in ctx:
+ tm = fontdata[nf].resources
+ if tm then
+ tm = tm.marks
+ end
+ end
+ if tm and tm[getchar(n)] then
+ nofmarks = nofmarks + 1
+ marks[nofmarks] = n
+ marki[nofmarks] = "injections"
+ else
+ nofglyphs = nofglyphs + 1
+ glyphs[nofglyphs] = n
+ glyphi[nofglyphs] = what
+ end
+ if offsets then
+ -- yoffsets can influence curs steps
+ local p = rawget(properties,n)
+ if p then
+ local i = rawget(p,what)
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ end
+ end
+ end
+ end
+
+ while n do -- only needed for relevant fonts
+ local id = getid(n)
+ if id == glyph_code then
+ identify(n,"injections")
+ elseif id == disc_code then
+ local d = getfield(n,"pre")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"preinjections")
+ end
+ end
+ end
+ local d = getfield(n,"post")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"postinjections")
+ end
+ end
+ end
+ local d = getfield(n,"replace")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"replaceinjections")
+ end
+ end
+ end
+ end
+ n = getnext(n)
+ end
+
+ return glyphs, glyphi, nofglyphs, marks, marki, nofmarks
+end
+
+local function inject_marks(marks,marki,nofmarks)
+ for i=1,nofmarks do
+ local n = marks[i]
+ local pn = rawget(properties,n)
+ if pn then
+ local ni = marki[i]
+ local pn = rawget(pn,ni)
+ if pn then
+ local p = pn.markbasenode
+ if p then
+ local px = getfield(p,"xoffset")
+ local ox = 0
+ local rightkern = nil
+ local pp = rawget(properties,p)
+ if pp then
+ pp = rawget(pp,ni)
+ if pp then
+ rightkern = pp.rightkern
+ end
+ end
+ if rightkern then -- x and w ~= 0
+ if pn.markdir < 0 then
+ -- kern(w-x) glyph(p) kern(x) mark(n)
+ ox = px - pn.markx - rightkern
+ -- report_injections("r2l case 1: %p",ox)
+ else
+ -- kern(x) glyph(p) kern(w-x) mark(n)
+ -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
+ --
+ -- According to Kai we don't need to handle leftkern here but I'm
+ -- pretty sure I've run into a case where it was needed so maybe
+ -- some day we need something more clever here.
+ --
+ if false then
+ -- a mark with kerning
+ local leftkern = pp.leftkern
+ if leftkern then
+ ox = px - pn.markx - leftkern
+ else
+ ox = px - pn.markx
+ end
+ else
+ ox = px - pn.markx
+ end
+ end
+ else
+ -- we need to deal with fonts that have marks with width
+ -- if pn.markdir < 0 then
+ -- ox = px - pn.markx
+ -- -- report_injections("r2l case 3: %p",ox)
+ -- else
+ -- -- ox = px - getfield(p,"width") + pn.markx
+ ox = px - pn.markx
+ -- report_injections("l2r case 3: %p",ox)
+ -- end
+ local wn = getfield(n,"width") -- in arial marks have widths
+ if wn ~= 0 then
+ -- bad: we should center
+ -- insert_node_before(head,n,newkern(-wn/2))
+ -- insert_node_after(head,n,newkern(-wn/2))
+ pn.leftkern = -wn/2
+ pn.rightkern = -wn/2
+ -- wx[n] = { 0, -wn/2, 0, -wn }
+ end
+ -- so far
+ end
+ setfield(n,"xoffset",ox)
+ --
+ local py = getfield(p,"yoffset")
+-- local oy = 0
+-- if marks[p] then
+-- oy = py + pn.marky
+-- else
+-- oy = getfield(n,"yoffset") + py + pn.marky
+-- end
+ local oy = getfield(n,"yoffset") + py + pn.marky
+ setfield(n,"yoffset",oy)
+ else
+ -- normally this can't happen (only when in trace mode which is a special case anyway)
+ -- report_injections("missing mark anchor %i",pn.markbase or 0)
+ end
+ end
+ end
+ end
+end
+
+local function inject_cursives(glyphs,glyphi,nofglyphs)
+ local cursiveanchor, lastanchor = nil, nil
+ local minc, maxc, last = 0, 0, nil
+ for i=1,nofglyphs do
+ local n = glyphs[i]
+ local pn = rawget(properties,n)
+ if pn then
+ pn = rawget(pn,glyphi[i])
+ end
+ if pn then
+ local cursivex = pn.cursivex
+ if cursivex then
+ if cursiveanchor then
+ if cursivex ~= 0 then
+ pn.leftkern = (pn.leftkern or 0) + cursivex
+ end
+ if lastanchor then
+ if maxc == 0 then
+ minc = lastanchor
+ end
+ maxc = lastanchor
+ properties[cursiveanchor].cursivedy = pn.cursivey
+ end
+ last = n
+ else
+ maxc = 0
+ end
+ elseif maxc > 0 then
+ local ny = getfield(n,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ end
+ maxc = 0
+ end
+ if pn.cursiveanchor then
+ cursiveanchor = n
+ lastanchor = i
+ else
+ cursiveanchor = nil
+ lastanchor = nil
+ if maxc > 0 then
+ local ny = getfield(n,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ end
+ maxc = 0
+ end
+ end
+ elseif maxc > 0 then
+ local ny = getfield(n,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- ?
+ end
+ maxc = 0
+ cursiveanchor = nil
+ lastanchor = nil
+ end
+ -- if maxc > 0 and not cursiveanchor then
+ -- local ny = getfield(n,"yoffset")
+ -- for i=maxc,minc,-1 do
+ -- local ti = glyphs[i][1]
+ -- ny = ny + properties[ti].cursivedy
+ -- setfield(ti,"yoffset",ny) -- why not add ?
+ -- end
+ -- maxc = 0
+ -- end
+ end
+ if last and maxc > 0 then
+ local ny = getfield(last,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ end
+ end
+end
+
+-- G +D-pre G
+-- D-post+
+-- +D-replace+
+--
+-- G +D-pre +D-pre
+-- D-post +D-post
+-- +D-replace +D-replace
+
+local function inject_kerns(head,glist,ilist,length) -- not complete ! compare with inject_kerns_only (but unlikely disc here)
+ for i=1,length do
+ local n = glist[i]
+ local pn = rawget(properties,n)
+ if pn then
+ local dp = nil
+ local dr = nil
+ local ni = ilist[i]
+ local p = nil
+ if ni == "injections" then
+ p = getprev(n)
+ if p then
+ local id = getid(p)
+ if id == disc_code then
+ dp = getfield(p,"post")
+ dr = getfield(p,"replace")
+ end
+ end
+ end
+ if dp then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(dp)
+ insert_node_after(dp,t,newkern(leftkern))
+ setfield(p,"post",dp) -- currently we need to force a tail refresh
+ end
+ end
+ end
+ if dr then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(dr)
+ insert_node_after(dr,t,newkern(leftkern))
+ setfield(p,"replace",dr) -- currently we need to force a tail refresh
+ end
+ end
+ else
+ local i = rawget(pn,ni)
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,n,newkern(leftkern)) -- type 0/2
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern)) -- type 0/2
+ end
+ end
+ end
+ end
+ end
+end
+
+local function inject_everything(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"everything")
+ end
+ local glyphs, glyphi, nofglyphs, marks, marki, nofmarks = collect_glyphs(head,nofregisteredpairs > 0)
+ if nofglyphs > 0 then
+ if nofregisteredcursives > 0 then
+ inject_cursives(glyphs,glyphi,nofglyphs)
+ end
+ if nofregisteredmarks > 0 then -- and nofmarks > 0
+ inject_marks(marks,marki,nofmarks)
+ end
+ inject_kerns(head,glyphs,glyphi,nofglyphs)
+ end
+ if nofmarks > 0 then
+ inject_kerns(head,marks,marki,nofmarks)
+ end
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredkerns = 0
+ nofregisteredpairs = 0
+ nofregisteredmarks = 0
+ nofregisteredcursives = 0
+ end
+ return tonode(head), true
+end
+
+-- G +D-pre G
+-- D-post+
+-- +D-replace+
+--
+-- G +D-pre +D-pre
+-- D-post +D-post
+-- +D-replace +D-replace
+
+local function inject_kerns_only(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"kerns")
+ end
+ local n = head
+ local p = nil -- disc node when non-nil
+ while n do
+ local id = getid(n)
+ if id == glyph_code then
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ if p then
+ local d = getfield(p,"post")
+ if d then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(d)
+ insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d) -- currently we need to force a tail refresh
+ end
+ end
+ end
+ local d = getfield(p,"replace")
+ if d then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(d)
+ insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
+ end
+ end
+ else
+ local i = rawget(pn,"injections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(p,"replace",newkern(leftkern))
+ end
+ end
+ end
+ else
+ -- this is the most common case
+ local i = rawget(pn,"injections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ head = insert_node_before(head,n,newkern(leftkern))
+ end
+ end
+ end
+ end
+ end
+ p = nil
+ elseif id == disc_code then
+ local d = getfield(n,"pre")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"preinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"pre",h)
+ end
+ end
+ local d = getfield(n,"post")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"post",h)
+ end
+ end
+ local d = getfield(n,"replace")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"replace",h)
+ end
+ end
+ p = n
+ else
+ p = nil
+ end
+ n = getnext(n)
+ end
+ --
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredkerns = 0
+ end
+ return tonode(head), true
+end
+
+local function inject_pairs_only(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"pairs")
+ end
+ local n = head
+ local p = nil -- disc node when non-nil
+ while n do
+ local id = getid(n)
+ if id == glyph_code then
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ if p then
+ local d = getfield(p,"post")
+ if d then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(d)
+ insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d) -- currently we need to force a tail refresh
+ end
+ -- local rightkern = i.rightkern
+ -- if rightkern and rightkern ~= 0 then
+ -- insert_node_after(head,n,newkern(rightkern))
+ -- n = getnext(n) -- to be checked
+ -- end
+ end
+ end
+ local d = getfield(p,"replace")
+ if d then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(d)
+ insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
+ end
+ -- local rightkern = i.rightkern
+ -- if rightkern and rightkern ~= 0 then
+ -- insert_node_after(head,n,newkern(rightkern))
+ -- n = getnext(n) -- to be checked
+ -- end
+ end
+ else
+ local i = rawget(pn,"injections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(p,"replace",newkern(leftkern))
+ end
+ -- local rightkern = i.rightkern
+ -- if rightkern and rightkern ~= 0 then
+ -- insert_node_after(head,n,newkern(rightkern))
+ -- n = getnext(n) -- to be checked
+ -- end
+ end
+ end
+ else
+ -- this is the most common case
+ local i = rawget(pn,"injections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ head = insert_node_before(head,n,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern))
+ n = getnext(n) -- to be checked
+ end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ end
+ end
+ end
+ end
+ p = nil
+ elseif id == disc_code then
+ local d = getfield(n,"pre")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"preinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern))
+ n = getnext(n) -- to be checked
+ end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"pre",h)
+ end
+ end
+ local d = getfield(n,"post")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern))
+ n = getnext(n) -- to be checked
+ end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"post",h)
+ end
+ end
+ local d = getfield(n,"replace")
+ if d then
+ local h = d
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ h = insert_node_before(h,n,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern))
+ n = getnext(n) -- to be checked
+ end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ end
+ end
+ else
+ break
+ end
+ end
+ if h ~= d then
+ setfield(n,"replace",h)
+ end
+ end
+ p = n
+ else
+ p = nil
+ end
+ n = getnext(n)
+ end
+ --
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredpairs = 0
+ nofregisteredkerns = 0
+ end
+ return tonode(head), true
+end
+
+function injections.handler(head,where)
+ if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
+ return inject_everything(head,where)
+ elseif nofregisteredpairs > 0 then
+ return inject_pairs_only(head,where)
+ elseif nofregisteredkerns > 0 then
+ return inject_kerns_only(head,where)
+ else
+ return head, false
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ldr.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ldr.lua
new file mode 100644
index 00000000000..175b4d0cc50
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ldr.lua
@@ -0,0 +1,70 @@
+if not modules then modules = { } end modules ['font-ldr'] = {
+ 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"
+}
+
+-- This module provides an experimental replacement for fontloader.to_table
+-- but is not used that much.
+
+local fields = fontloader.fields
+
+if fields then
+
+ local glyphfields
+
+ local function get_glyphs(r)
+ local t = { }
+ local g = r.glyphs
+ for i=1,r.glyphmax-1 do
+ local gi = g[i]
+ if gi then
+ if not glyphfields then
+ glyphfields = fields(gi)
+ end
+ local h = { }
+ for i=1,#glyphfields do
+ local s = glyphfields[i]
+ h[s] = gi[s]
+ end
+ t[i] = h
+ end
+ end
+ return t
+ end
+
+ local function to_table(r)
+ local f = fields(r)
+ if f then
+ local t = { }
+ for i=1,#f do
+ local fi = f[i]
+ local ri = r[fi]
+ if not ri then
+ -- skip
+ elseif fi == "glyphs" then
+ t.glyphs = get_glyphs(r)
+ elseif fi == "subfonts" then
+ t[fi] = ri
+ ri.glyphs = get_glyphs(ri)
+ else
+ t[fi] = r[fi]
+ end
+ end
+ return t
+ end
+ end
+
+ -- currently glyphs, subfont-glyphs and the main table are userdata
+
+ function fonts.to_table(raw)
+ return to_table(raw)
+ end
+
+else
+
+ fonts.to_table = fontloader.to_table
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi
new file mode 100644
index 00000000000..7bb042a5943
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi
@@ -0,0 +1,112 @@
+%D \module
+%D [ file=font-lib,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Libraries,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Libraries}
+
+\unprotect
+
+\registerctxluafile{font-ini}{1.001}
+\registerctxluafile{font-log}{1.001}
+\registerctxluafile{font-con}{1.001}
+\registerctxluafile{font-enc}{1.001}
+\registerctxluafile{font-agl}{1.001} % if needed we can comment this and delay loading
+\registerctxluafile{font-cid}{1.001} % cid maps
+\registerctxluafile{font-map}{1.001}
+
+% the otf font loader:
+
+\registerctxluafile{font-otr}{1.001} % opentype fontloader
+\registerctxluafile{font-cff}{1.001} % quadratic outlines
+\registerctxluafile{font-ttf}{1.001} % cubic outlines
+%registerctxluafile{font-tmp}{1.001} % temporary placeholder
+\registerctxluafile{font-dsp}{1.001} % ... for this one
+\registerctxluafile{font-off}{1.001} % the old loader
+
+\registerctxluafile{font-syn}{1.001}
+
+\registerctxluafile{font-tfm}{1.001}
+
+\registerctxluafile{font-afm}{1.001}
+\registerctxluafile{font-afk}{1.001}
+
+\registerctxluafile{font-hsh}{1.001} % hashes used by context
+\registerctxluafile{font-nod}{1.001}
+
+\registerctxluafile{font-trt}{1.001}
+
+\registerctxluafile{font-oti}{1.001} % otf initialization
+\registerctxluafile{font-ott}{1.001} % otf tables (first)
+
+\registerctxluafile{font-otl}{1.001}
+\registerctxluafile{font-oto}{1.001}
+\registerctxluafile{font-otj}{1.001}
+\registerctxluafile{font-oup}{1.001}
+\registerctxluafile{font-ota}{1.001}
+\registerctxluafile{font-ots}{1.001}
+\registerctxluafile{font-otd}{1.001}
+\registerctxluafile{font-otc}{1.001}
+\registerctxluafile{font-oth}{1.001}
+\registerctxluafile{font-osd}{1.001}
+
+% so far
+
+\registerctxluafile{font-pat}{1.001} % patchers
+
+\registerctxluafile{node-fnt}{1.001} % here
+
+\registerctxluafile{font-mps}{1.001} % outline fun
+
+\registerctxluafile{font-lua}{1.001}
+
+\registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-enh}{1.001}
+
+\registerctxluafile{font-gds}{1.001}
+
+\registerctxluafile{font-def}{1.001}
+\registerctxluafile{font-ctx}{1.001} % after def as it overloads
+
+\registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-fbk}{1.001}
+
+\registerctxluafile{font-aux}{1.001}
+
+%D Some low level helpers
+%D
+%D \starttyping
+%D \def\TestLookup#specification%
+%D {\dolookupfontbyspec{#specification}
+%D pattern: #specification, found: \dolookupnoffound
+%D \blank
+%D \dorecurse {\dolookupnoffound} {%
+%D \recurselevel:~\dolookupgetkeyofindex{fontname}{\recurselevel}\quad
+%D }%
+%D \blank}
+%D
+%D \TestLookup{familyname=helveticaneue}
+%D \TestLookup{familyname=helveticaneue,weight=bold}
+%D \TestLookup{familyname=helveticaneue,weight=bold,style=italic}
+%D \stoptyping
+
+% we can also move the lookups to the fonts.namespace (of commands)
+% one can also directly use the clf calls when speed is needed
+
+ \def\dolookupfontbyspec #1{\clf_fontlookupinitialize{#1}}
+ \def\dolookupnoffound {\clf_fontlookupnoffound}
+ \def\dolookupgetkeyofindex#1#2{\clf_fontlookupgetkeyofindex{#1}\numexpr#2\relax}
+ \def\dolookupgetkey #1{\clf_fontlookupgetkey{#1}}
+ \def\cleanfontname #1{\clf_cleanfontname{#1}}
+\unexpanded\def\setfontofid #1{\clf_setfontofid\numexpr#1\relax}
+
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-log.lua b/Master/texmf-dist/tex/context/base/mkiv/font-log.lua
new file mode 100644
index 00000000000..092b5a62ea9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-log.lua
@@ -0,0 +1,88 @@
+if not modules then modules = { } end modules ['font-log'] = {
+ 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, format, lower, concat = next, string.format, string.lower, table.concat
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local report_defining = logs.reporter("fonts","defining")
+
+local basename = file.basename
+
+local fonts = fonts
+local loggers = { }
+fonts.loggers = loggers
+local usedfonts = utilities.storage.allocate()
+----- loadedfonts = utilities.storage.allocate()
+
+--[[ldx--
+<p>The following functions are used for reporting about the fonts
+used. The message itself is not that useful in regular runs but since
+we now have several readers it may be handy to know what reader is
+used for which font.</p>
+--ldx]]--
+
+function loggers.onetimemessage(font,char,message,reporter)
+ local tfmdata = fonts.hashes.identifiers[font]
+ local shared = tfmdata.shared
+ local messages = shared.messages
+ if not messages then
+ messages = { }
+ shared.messages = messages
+ end
+ local category = messages[message]
+ if not category then
+ category = { }
+ messages[message] = category
+ end
+ if not category[char] then
+ if not reporter then
+ reporter = report_defining
+ end
+ reporter("char %U in font %a with id %s: %s",char,tfmdata.properties.fullname,font,message)
+ category[char] = true
+ end
+end
+
+function loggers.register(tfmdata,source,specification) -- save file name in spec here ! ! ! ! ! !
+ if tfmdata and specification and specification.specification then
+ local name = lower(specification.name)
+ if trace_defining and not usedfonts[name] then
+ report_defining("registering %a as %a, used %a",file.basename(specification.name),source,file.basename(specification.filename))
+ end
+ specification.source = source
+ -- loadedfonts[lower(specification.specification)] = specification
+ usedfonts[lower(specification.filename or specification.name)] = source
+ end
+end
+
+function loggers.format(name) -- should be avoided
+ return usedfonts[name] or "unknown"
+end
+
+-- maybe move this to font-ctx.lua
+
+statistics.register("loaded fonts", function()
+ if next(usedfonts) then
+ local t, n = { }, 0
+ local treatmentdata = fonts.treatments.data
+ for name, used in table.sortedhash(usedfonts) do
+ n = n + 1
+ local base = basename(name)
+ if complete then
+ t[n] = format("%s -> %s",used,base)
+ else
+ t[n] = base
+ end
+ local treatment = treatmentdata[base]
+ if treatment and treatment.comment then
+ t[n] = format("%s (%s)",t[n],treatment.comment)
+ end
+ end
+ return n > 0 and format("%s files: %s",n,concat(t,", ")) or "none"
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/font-lua.lua
new file mode 100644
index 00000000000..6fbbcf17e4e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-lua.lua
@@ -0,0 +1,46 @@
+if not modules then modules = { } end modules ['font-lua'] = {
+ 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 trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+local report_lua = logs.reporter("fonts","lua loading")
+
+local fonts = fonts
+local readers = fonts.readers
+fonts.formats.lua = "lua"
+
+-- we could add support for features here
+
+local function check_lua(specification,fullname)
+ -- standard tex file lookup
+ local fullname = resolvers.findfile(fullname) or ""
+ if fullname ~= "" then
+ local loader = loadfile(fullname)
+ loader = loader and loader()
+ return loader and loader(specification)
+ end
+end
+
+readers.check_lua = check_lua
+
+function readers.lua(specification)
+ local original = specification.specification
+ if trace_defining then
+ report_lua("using lua reader for %a",original)
+ end
+ local fullname = specification.filename or ""
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ fullname = specification.name .. "." .. forced
+ else
+ fullname = specification.name
+ end
+ end
+ return check_lua(specification,fullname)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-map.lua b/Master/texmf-dist/tex/context/base/mkiv/font-map.lua
new file mode 100644
index 00000000000..509e7510710
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-map.lua
@@ -0,0 +1,517 @@
+if not modules then modules = { } end modules ['font-map'] = {
+ 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 tonumber, next, type = tonumber, next, type
+
+local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower
+local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match
+local utfbyte = utf.byte
+local floor = math.floor
+local formatters = string.formatters
+
+local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
+local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end)
+
+local report_fonts = logs.reporter("fonts","loading") -- not otf only
+
+local force_ligatures = false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures = v end)
+
+local fonts = fonts or { }
+local mappings = fonts.mappings or { }
+fonts.mappings = mappings
+
+local allocate = utilities.storage.allocate
+
+--[[ldx--
+<p>Eventually this code will disappear because map files are kind
+of obsolete. Some code may move to runtime or auxiliary modules.</p>
+<p>The name to unciode related code will stay of course.</p>
+--ldx]]--
+
+-- local function loadlumtable(filename) -- will move to font goodies
+-- local lumname = file.replacesuffix(file.basename(filename),"lum")
+-- local lumfile = resolvers.findfile(lumname,"map") or ""
+-- if lumfile ~= "" and lfs.isfile(lumfile) then
+-- if trace_loading or trace_mapping then
+-- report_fonts("loading map table %a",lumfile)
+-- end
+-- lumunic = dofile(lumfile)
+-- return lumunic, lumfile
+-- end
+-- end
+
+local hex = R("AF","09")
+----- hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+----- hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end
+local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end
+local dec = (R("09")^1) / tonumber
+local period = P(".")
+local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes
+local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended
+local index = P("index") * dec * Cc(false)
+
+local parser = unicode + ucode + index
+
+local parsers = { }
+
+local function makenameparser(str)
+ if not str or str == "" then
+ return parser
+ else
+ local p = parsers[str]
+ if not p then
+ p = P(str) * period * dec * Cc(false)
+ parsers[str] = p
+ end
+ return p
+ end
+end
+
+local f_single = formatters["%04X"]
+local f_double = formatters["%04X%04X"]
+
+-- 0.684 0.661 0,672 0.650 : cache at lua end (more mem)
+-- 0.682 0,672 0.698 0.657 : no cache (moderate mem i.e. lua strings)
+-- 0.644 0.647 0.655 0.645 : convert in c (less mem in theory)
+
+-- local tounicodes = table.setmetatableindex(function(t,unicode)
+-- local s
+-- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+-- s = f_single(unicode)
+-- else
+-- unicode = unicode - 0x10000
+-- s = f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
+-- end
+-- t[unicode] = s
+-- return s
+-- end)
+--
+-- local function tounicode16(unicode,name)
+-- local s = tounicodes[unicode]
+-- if s then
+-- return s
+-- else
+-- report_fonts("can't convert %a in %a into tounicode",unicode,name)
+-- end
+-- end
+--
+-- local function tounicode16sequence(unicodes,name)
+-- local t = { }
+-- for l=1,#unicodes do
+-- local u = unicodes[l]
+-- local s = tounicodes[u]
+-- if s then
+-- t[l] = s
+-- else
+-- report_fonts ("can't convert %a in %a into tounicode",u,name)
+-- return
+-- end
+-- end
+-- return concat(t)
+-- end
+--
+-- local function tounicode(unicode,name)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- local u = unicode[l]
+-- local s = tounicodes[u]
+-- if s then
+-- t[l] = s
+-- else
+-- report_fonts ("can't convert %a in %a into tounicode",u,name)
+-- return
+-- end
+-- end
+-- return concat(t)
+-- else
+-- local s = tounicodes[unicode]
+-- if s then
+-- return s
+-- else
+-- report_fonts("can't convert %a in %a into tounicode",unicode,name)
+-- end
+-- end
+-- end
+
+local function tounicode16(unicode,name)
+ if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+ return f_single(unicode)
+ else
+ unicode = unicode - 0x10000
+ return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
+ end
+end
+
+local function tounicode16sequence(unicodes,name)
+ local t = { }
+ for l=1,#unicodes do
+ local u = unicodes[l]
+ if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
+ t[l] = f_single(u)
+ else
+ u = u - 0x10000
+ t[l] = f_double(floor(u/1024)+0xD800,u%1024+0xDC00)
+ end
+ end
+ return concat(t)
+end
+
+local function tounicode(unicode,name)
+ 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(floor(u/1024)+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(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
+ end
+ end
+end
+
+local function fromunicode16(str)
+ if #str == 4 then
+ return tonumber(str,16)
+ else
+ local l, r = match(str,"(....)(....)")
+ -- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00
+ return 0x10000 + (tonumber(l,16)-0xD800)*0x400 + tonumber(r,16) - 0xDC00
+ end
+end
+
+-- Slightly slower:
+--
+-- local p = C(4) * (C(4)^-1) / function(l,r)
+-- if r then
+-- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00
+-- else
+-- return tonumber(l,16)
+-- end
+-- end
+--
+-- local function fromunicode16(str)
+-- return lpegmatch(p,str)
+-- end
+
+mappings.makenameparser = makenameparser
+mappings.tounicode = tounicode
+mappings.tounicode16 = tounicode16
+mappings.tounicode16sequence = tounicode16sequence
+mappings.fromunicode16 = fromunicode16
+
+local ligseparator = P("_")
+local varseparator = P(".")
+local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator * C((1 - ligseparator - varseparator)^1))^0)
+
+-- maybe: ff fi fl ffi ffl => f_f f_i f_l f_f_i f_f_l
+
+-- local function test(name)
+-- local split = lpegmatch(namesplitter,name)
+-- print(string.formatters["%s: [% t]"](name,split))
+-- end
+
+-- test("i.f_")
+-- test("this")
+-- test("this.that")
+-- test("japan1.123")
+-- test("such_so_more")
+-- test("such_so_more.that")
+
+-- to be completed .. for fonts that use unicodes for ligatures which
+-- is a actually a bad thing and should be avoided in the first place
+
+local overloads = allocate {
+ IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 },
+ ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 },
+ ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 },
+ fi = { name = "f_i", unicode = { 0x66, 0x69 }, mess = 0xFB01 },
+ fl = { name = "f_l", unicode = { 0x66, 0x6C }, mess = 0xFB02 },
+ ffi = { name = "f_f_i", unicode = { 0x66, 0x66, 0x69 }, mess = 0xFB03 },
+ ffl = { name = "f_f_l", unicode = { 0x66, 0x66, 0x6C }, mess = 0xFB04 },
+ fj = { name = "f_j", unicode = { 0x66, 0x6A } },
+ fk = { name = "f_k", unicode = { 0x66, 0x6B } },
+}
+
+for k, v in next, overloads do
+ local name = v.name
+ local mess = v.mess
+ if name then
+ overloads[name] = v
+ end
+ if mess then
+ overloads[mess] = v
+ end
+end
+
+mappings.overloads = overloads
+
+function mappings.addtounicode(data,filename,checklookups)
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ if not unicodes then
+ return
+ end
+ local properties = data.properties
+ local descriptions = data.descriptions
+ -- we need to move this code
+ unicodes['space'] = unicodes['space'] or 32
+ unicodes['hyphen'] = unicodes['hyphen'] or 45
+ unicodes['zwj'] = unicodes['zwj'] or 0x200D
+ unicodes['zwnj'] = unicodes['zwnj'] or 0x200C
+ --
+ local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+ local unicodevector = fonts.encodings.agl.unicodes or { } -- loaded runtime in context
+ local contextvector = fonts.encodings.agl.ctxcodes or { } -- loaded runtime in context
+ local missing = { }
+ local nofmissing = 0
+ local oparser = nil
+ local cidnames = nil
+ local cidcodes = nil
+ local cidinfo = properties.cidinfo
+ local usedmap = cidinfo and fonts.cid.getmap(cidinfo)
+ local uparser = makenameparser() -- hm, every time?
+ if usedmap then
+ oparser = usedmap and makenameparser(cidinfo.ordering)
+ cidnames = usedmap.names
+ cidcodes = usedmap.unicodes
+ end
+ local ns = 0
+ local nl = 0
+ --
+ for unic, glyph in next, descriptions do
+ local name = glyph.name
+ if name then
+ local index = glyph.index
+ local r = overloads[name]
+ if r then
+ -- get rid of weird ligatures
+ -- glyph.name = r.name
+ glyph.unicode = r.unicode
+ elseif not unic or unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
+ local unicode = unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ end
+ -- cidmap heuristics, beware, there is no guarantee for a match unless
+ -- the chain resolves
+ if (not unicode) and usedmap then
+ local foundindex = lpegmatch(oparser,name)
+ if foundindex then
+ unicode = cidcodes[foundindex] -- name to number
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ else
+ local reference = cidnames[foundindex] -- number to name
+ if reference then
+ local foundindex = lpegmatch(oparser,reference)
+ if foundindex then
+ unicode = cidcodes[foundindex]
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ end
+ end
+ if not unicode or unicode == "" then
+ local foundcodes, multiple = lpegmatch(uparser,reference)
+ if foundcodes then
+ glyph.unicode = foundcodes
+ if multiple then
+ nl = nl + 1
+ unicode = true
+ else
+ ns = ns + 1
+ unicode = foundcodes
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_
+ --
+ -- It is not trivial to find a solution that suits all fonts. We tried several alternatives
+ -- and this one seems to work reasonable also with fonts that use less standardized naming
+ -- schemes. The extra private test is tested by KE and seems to work okay with non-typical
+ -- fonts as well.
+ --
+ if not unicode or unicode == "" then
+ local split = lpegmatch(namesplitter,name)
+ local nsplit = split and #split or 0 -- add if
+ if nsplit == 0 then
+ -- skip
+ elseif nsplit == 1 then
+ local base = split[1]
+ local u = unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ -- skip
+ elseif type(u) == "table" then
+ -- unlikely
+ if u[1] < private then
+ unicode = u
+ glyph.unicode = unicode
+ end
+ elseif u < private then
+ unicode = u
+ glyph.unicode = unicode
+ end
+ else
+ local t, n = { }, 0
+ for l=1,nsplit do
+ local base = split[l]
+ local u = unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ break
+ elseif type(u) == "table" then
+ if u[1] >= private then
+ break
+ end
+ n = n + 1
+ t[n] = u[1]
+ else
+ if u >= private then
+ break
+ end
+ n = n + 1
+ t[n] = u
+ end
+ end
+ if n > 0 then
+ if n == 1 then
+ unicode = t[1]
+ else
+ unicode = t
+ end
+ glyph.unicode = unicode
+ end
+ end
+ nl = nl + 1
+ end
+ -- last resort (we might need to catch private here as well)
+ if not unicode or unicode == "" then
+ local foundcodes, multiple = lpegmatch(uparser,name)
+ if foundcodes then
+ glyph.unicode = foundcodes
+ if multiple then
+ nl = nl + 1
+ unicode = true
+ else
+ ns = ns + 1
+ unicode = foundcodes
+ end
+ end
+ end
+ -- check using substitutes and alternates
+ local r = overloads[unicode]
+ if r then
+ unicode = r.unicode
+ glyph.unicode = unicode
+ end
+ --
+ if not unicode then
+ missing[unic] = true
+ nofmissing = nofmissing + 1
+ end
+ end
+ else
+ -- no name
+ end
+ end
+ if type(checklookups) == "function" then
+ checklookups(data,missing,nofmissing)
+ end
+
+ -- todo: go lowercase
+
+ local collected = false
+ local unicoded = 0
+ for unicode, glyph in next, descriptions do
+ if glyph.class == "ligature" and (force_ligatures or not glyph.unicode) then
+ if not collected then
+ collected = fonts.handlers.otf.readers.getcomponents(data)
+ if not collected then
+ break
+ end
+ end
+ local u = collected[unicode] -- always tables
+ 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
+ glyph.unicode = u
+ else
+ glyph.unicode = u[1]
+ end
+ unicoded = unicoded + 1
+ end
+ end
+ end
+ end
+ if trace_mapping and unicoded > 0 then
+ report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
+ end
+
+ if trace_mapping then
+ for unic, glyph in table.sortedhash(descriptions) do
+ local name = glyph.name
+ local index = glyph.index
+ local unicode = glyph.unicode
+ if unicode then
+ if type(unicode) == "table" then
+ local unicodes = { }
+ for i=1,#unicode do
+ unicodes[i] = formatters("%U",unicode[i])
+ end
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,unic,unicodes)
+ else
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,unic,unicode)
+ end
+ else
+ report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
+ end
+ end
+ end
+ if trace_loading and (ns > 0 or nl > 0) then
+ report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns)
+ end
+end
+
+-- local parser = makenameparser("Japan1")
+-- local parser = makenameparser()
+-- local function test(str)
+-- local b, a = lpegmatch(parser,str)
+-- print((a and table.serialize(b)) or b)
+-- end
+-- test("a.sc")
+-- test("a")
+-- test("uni1234")
+-- test("uni1234.xx")
+-- test("uni12349876")
+-- test("u123400987600")
+-- test("index1234")
+-- test("Japan1.123")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi
new file mode 100644
index 00000000000..2e7c2080d67
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi
@@ -0,0 +1,511 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Math,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Math}
+
+\unprotect
+
+%D Be nice:
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+%D \macros
+%D {textonly}
+%D
+%D Traditionally math has a big impact on font definitions, mainly
+%D because we need to define alphabet variants using families and
+%D fonts. This means that one can easily get 10 fonts loaded per
+%D math size. In \MKIV\ we use a different approach: one family
+%D which has either a virtual font made of traditional fonts, or
+%D an \OPENTYPE\ font that has it all.
+%D
+%D We currently use only one math family but in the future we
+%D might consider using a second one for bold math. For the
+%D moment we keep the \MKII\ method of using a token register
+%D for definitions but we already dropped the text and symbols
+%D ones since they now live in the same family.
+
+\newtoks \t_font_math_strategies
+\newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts
+
+\unexpanded\def\font_helpers_synchronize_math % math stuff in mmode
+ {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi}
+
+\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
+
+%D The main math font definer. We have removed some optimized
+%D code simply because we now always have a fontclass. We could
+%D check for fontclass being default or empty and save a few
+%D tests but it does not help us when no math is defined.
+
+%D Because we want to keep mr=.. and mb=... settings (read: not
+%D break downward compatibility by enforcing mrlr etc) we need a
+%D bit more code that optimal.
+
+% todo: \c_font_fam_mr
+
+\let\c_font_fam_mr \zerocount % math regular
+\let\c_font_fam_mr_lr\plusone % math regular l2r
+\let\c_font_fam_mr_rl\plustwo % math regular r2l
+
+\let\c_font_fam_mb \plusthree % math bold
+\let\c_font_fam_mb_lr\plusfour % math bold l2r
+\let\c_font_fam_mb_rl\plusfive % math bold r2l
+
+\definesystemattribute[mathfamily][public]
+
+\newconditional\c_font_bidirectional_mathstrategy % can be default, not that much overhead: \settrue\c_font_bidirectional_mathstrategy
+\newconditional\c_font_complete_bold_mathstrategy \settrue\c_font_complete_bold_mathstrategy
+
+\def\mathtextsuffix {-text}
+\def\mathscriptsuffix {-script}
+\def\mathscriptscriptsuffix{-scriptscript}
+
+\def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
+
+% Beware: truefontname also does a fallback on defaultfontclass so there
+% can be some interference here, which is why we use a different method
+% for bold.
+
+% \def\font_helpers_set_math_family_a
+% {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+% \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+% \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+% \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \else
+% \font_helpers_set_math_family_b
+% \fi\fi}
+
+% \def\font_helpers_set_math_family_b
+% {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+% \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+% \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+% \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \else
+% \font_helpers_set_math_family_c
+% \fi\fi}
+
+% \def\font_helpers_set_math_family_c
+% {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+% \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+% \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+% \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \else
+% \settrue \c_font_auto_size
+% \fi\fi}
+
+\def\font_helpers_set_math_family_a
+ {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \else
+ \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \font_helpers_set_math_family_b
+ \fi\fi}
+
+\def\font_helpers_set_math_family_b
+ {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \else
+ \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \font_helpers_set_math_family_c
+ \fi\fi}
+
+\def\font_helpers_set_math_family_c
+ {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs \else
+ \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs \else
+ \settrue \c_font_auto_size
+ \fi\fi}
+
+\def\font_helpers_set_math_family_indeed#mrtag#family% \fontface etc are also used later on
+ {\let\savedfontbody\fontbody
+ \let\fontfamily#family%
+ % the order is important as we depend on known id's when completing fonts
+ \let\fontface\!!plusthree\font_helpers_set_math_family_a\scriptscriptfont#mrtag\font
+ \let\fontface\!!plustwo \font_helpers_set_math_family_a\scriptfont #mrtag\font
+ \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font
+ \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \setfalse\c_font_auto_size}
+
+% \def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
+% {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+% \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname #font#mbfam\font \else
+% \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+% \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname #font#mbfam\font \else
+% #font#mbfam#font#mrfam%
+% \fi\fi}
+
+\def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \lastnamedcs #font#mbfam\font \else
+ \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \lastnamedcs #font#mbfam\font \else
+ #font#mbfam#font#mrfam%
+ \fi\fi}
+
+\def\font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam% \c_font_fam_mb \s!mb \c_font_fam_mr
+ {\let\savedfontclass\defaultfontclass
+ \let\defaultfontclass\fontclass % else truefontname falls back on the wrong one
+ \let\savedfontbody\fontbody
+ \let\fontfamily#familytag%
+ \let\fontface\!!plusthree\font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam%
+ \let\fontface\!!plustwo \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam%
+ \let\fontface\!!plusone \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam%
+ \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \let\defaultfontclass\savedfontclass
+ \setfalse\c_font_auto_size}
+
+% optimized: math fonts are never changed (10K \bfa $x$: 3.2 => 2.5 (baseline 1.0))
+%
+% sort of tricky: we cannot reset in \everybeforedefinetypeface as we don't know
+% all sizes so we postpone the optimization to the first starttext
+%
+% pitfall: we should reset 'm when a fontclass name is reused
+
+\newconditional\optimizemathfontdefinitions \settrue\optimizemathfontdefinitions
+
+\def\font_helpers_set_math_family#mrfam#familytag%
+ {\ifconditional\optimizemathfontdefinitions
+ \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ % \writestatus{fonts}{math: reusing \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_preset_math_family_indeed#mrfam#familytag%
+ \else
+ % \writestatus{fonts}{math: defining \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi
+ \else
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi}
+
+\def\font_helpers_set_math_family_bold#mbfam#familytag#mrfam%
+ {\ifconditional\optimizemathfontdefinitions
+ %\ifcsname\??fontinstanceclass\fontclass-\textface-\s!mm-#familytag-\fontsize-1\endcsname
+ \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ \font_helpers_preset_math_family_indeed#mbfam#familytag%
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi}
+
+%D It can happen that we use a bodyfont with no math in which case
+%D we have a problem with setting the global bodyfont size in the
+%D page builder. For instance in:
+%D
+%D \starttext
+%D \definetypeface[test][rm][serif][pagella][default]
+%D \setupbodyfont[test]
+%D test
+%D \stoptext
+%D
+%D This is why we need the check. At the cost of some extra checking we gain a little
+%D in restoring global states and, what's more important, we get rid of large math parameter
+%D push/pop in tracingall when not needed.
+
+\def\font_helpers_preset_math_family_indeed#fam#familytag%
+ {\expandafter\let\expandafter\v_font_math_one\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ \ifx\v_font_math_one\relax
+ \font_helpers_preset_math_family_warning
+ \else\ifnum\fontid\textfont#fam=\fontid\v_font_math_one\else
+ \font_helpers_preset_math_family_indeed_changed#fam#familytag%
+ \fi\fi}
+
+\def\font_helpers_preset_math_family_warning
+ {\writestatus{fonts}{math: unset for global bodyfont \fontclass\space at \fontbody}}
+
+\def\font_helpers_preset_math_family_indeed_changed#fam#familytag%
+ {\scriptscriptfont#fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-3\endcsname
+ \scriptfont #fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-2\endcsname
+ \textfont #fam\v_font_math_one}
+
+\let\font_helpers_reset_fontclass_math_families\gobbleoneargument
+
+% It would be nice if characters could be defined in a neutral way (say fam 255) and
+% be mapped to a real family during noad list construction. However, this changes
+% tex in critical places so for the moment we simulate this using manipulation.
+
+% For tracing purposes we use three families but in l2r mode 1 and 2 are copies of 0
+% while in rl mode 0 is a copy of 1. There is no real overhead involved in this. This
+% also permits different font definitions for normal and mixed.
+
+\let\m_font_class_direction\empty
+\let\m_font_class_features \empty
+\let\m_font_class_fallbacks\empty
+\let\m_font_class_goodies \empty
+
+\let\m_font_direction\empty
+\let\m_font_features \empty
+\let\m_font_fallbacks\empty
+\let\m_font_goodies \empty
+
+\appendtoks % can be analyzed once
+ % why here ..
+ %\edef\m_font_class_direction{\ifcsname\??fontclass\fontclass\s!mm\s!direction\endcsname\csname\??fontclass\fontclass\s!mm\s!direction\endcsname\fi}%
+ \edef\m_font_class_direction{\begincsname\??fontclass\fontclass\s!mm\s!direction\endcsname}%
+ % ...
+ \ifx\m_font_class_direction\v!both
+ \settrue\c_font_bidirectional_mathstrategy
+ \else
+ \setfalse\c_font_bidirectional_mathstrategy
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_bidirectional_mathstrategy_yes
+ {\font_helpers_set_math_family\c_font_fam_mr_lr\s!mrlr
+ \font_helpers_set_math_family\c_font_fam_mr_rl\s!mrrl
+ \ifnum\fontid\textfont\c_font_fam_mr=\fontid\textfont\c_font_fam_mr_lr\else
+ \font_helpers_bidirectional_mathstrategy_yes_changed
+ \fi}
+
+\def\font_helpers_bidirectional_mathstrategy_yes_changed
+ {\textfont \c_font_fam_mr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mr\scriptscriptfont\c_font_fam_mr_lr}
+
+\def\font_helpers_bidirectional_mathstrategy_nop
+ {\font_helpers_set_math_family\c_font_fam_mr\s!mr
+ \ifnum\fontid\textfont\c_font_fam_mr_rl=\fontid\textfont\c_font_fam_mr\else
+ \font_helpers_bidirectional_mathstrategy_nop_changed
+ \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
+ \scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr}
+
+\appendtoks
+ \ifconditional\c_font_bidirectional_mathstrategy
+ \font_helpers_bidirectional_mathstrategy_yes
+ \else
+ \font_helpers_bidirectional_mathstrategy_nop
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_complete_bold_mathstrategy_yes_bidi
+ {\font_helpers_set_math_family_bold\c_font_fam_mb_lr\s!mblr\c_font_fam_mr_lr
+ \font_helpers_set_math_family_bold\c_font_fam_mb_rl\s!mbrl\c_font_fam_mr_rl
+ \ifnum\fontid\textfont\c_font_fam_mb=\fontid\textfont\c_font_fam_mb_lr\else
+ \font_helpers_complete_bold_mathstrategy_yes_bidi_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_yes_bidi_changed
+ {\textfont \c_font_fam_mb\textfont \c_font_fam_mb_lr
+ \scriptfont \c_font_fam_mb\scriptfont \c_font_fam_mb_lr
+ \scriptscriptfont\c_font_fam_mb\scriptscriptfont\c_font_fam_mb_lr}
+
+\def\font_helpers_complete_bold_mathstrategy_yes
+ {\font_helpers_set_math_family_bold\c_font_fam_mb\s!mb\c_font_fam_mr\relax
+ \ifnum\fontid\textfont\c_font_fam_mb_rl=\fontid\textfont\c_font_fam_mb\else
+ \font_helpers_complete_bold_mathstrategy_yes_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_yes_changed
+ {\textfont \c_font_fam_mb_rl\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mb
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mb}
+
+\def\font_helpers_complete_bold_mathstrategy_nop
+ {\ifnum\fontid\textfont\c_font_fam_mb=\fontid\textfont\c_font_fam_mr\else
+ \font_helpers_complete_bold_mathstrategy_nop_changed
+ \fi}
+
+\def\font_helpers_complete_bold_mathstrategy_nop_changed
+ {\textfont \c_font_fam_mb \textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr}
+
+\def\font_helpers_apply_complete_bold_mathstrategy
+ {\ifconditional\c_font_complete_bold_mathstrategy
+ \ifconditional\c_font_bidirectional_mathstrategy
+ \font_helpers_complete_bold_mathstrategy_yes_bidi
+ \else
+ \font_helpers_complete_bold_mathstrategy_yes
+ \fi
+ \else
+ \font_helpers_complete_bold_mathstrategy_nop
+ \fi}
+
+\appendtoks
+ \font_helpers_apply_complete_bold_mathstrategy
+\to \t_font_math_strategies
+
+\ifdefined\defaultmathfamily \else
+ \setnewconstant\defaultmathfamily\zerocount
+\fi
+
+\appendtoks
+ \fam\defaultmathfamily % all characters and symbols are in this family
+\to \everymathematics
+
+\unexpanded\def\font_helpers_synchronize_math_family_mr
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_mathstrategy
+ \ifconditional\c_math_right_to_left
+ \plustwo
+ \else
+ \plusone
+ \fi
+ \else
+ \zerocount
+ \fi}
+
+\unexpanded\def\font_helpers_synchronize_math_family_mb
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_mathstrategy
+ \ifconditional\c_math_right_to_left
+ \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plusseven\else\plusfour\fi
+ \fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plussix\else\plusthree\fi
+ \fi}
+
+\installcorenamespace{fontmathsynchronizer}
+\installcorenamespace{fontmathstoredstrategy}
+
+\letvalue{\??fontmathsynchronizer\s!tf }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!sl }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!it }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!bf }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bs }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bi }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\empty}\font_helpers_synchronize_math_family_mr
+
+% \def\font_helpers_synchronize_math_family
+% {\csname\??fontmathsynchronizer\ifcsname\??fontmathsynchronizer\fontalternative\endcsname\fontalternative\fi\endcsname}
+
+\def\font_helpers_synchronize_math_family
+ {\ifcsname\??fontmathsynchronizer\fontalternative\endcsname
+ \lastnamedcs
+ \else
+ \font_helpers_synchronize_math_family_mr
+ \fi}
+
+\ifdefined \fontid % we need to keep this test for a while
+ \appendtoks
+ \ifnum\fontid\textfont\zerocount=\fontid\textfont\plusthree
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\else
+ \appendtoks
+ \edef\currentmathfontmr{\fontname\textfont\zerocount}%
+ \edef\currentmathfontmb{\fontname\textfont\plusthree}%
+ \ifx\currentmathfontmr\currentmathfontmb
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\fi
+
+%def\font_helpers_synchronize_math_bold_strategy{\csname\??fontmathstoredstrategy\fontclass\endcsname}
+\def\font_helpers_synchronize_math_bold_strategy{\begincsname\??fontmathstoredstrategy\fontclass\endcsname}
+
+\newconditional\c_font_pseudo_bold_math_state
+
+\def\font_helpers_set_math_partial_bold_strategy{\settrue \c_font_pseudo_bold_math_state}
+\def\font_helpers_set_math_full_bold_strategy {\setfalse\c_font_pseudo_bold_math_state}
+
+\appendtoks
+ \font_helpers_synchronize_math_bold_strategy
+\to \everymathematics
+
+% Bold is somewhat special as we might want both full-bold-math mixed
+% regular-math, as well as automatic adaption to outer bold (in titles
+% and inline text bold) so we will need explicit switches as well as
+% an automatic one. (We will use lucida as an example.)
+
+\ifdefined\mathdefault \else \let\mathdefault\relax \fi
+
+\unexpanded\def\mr % math regular
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mr
+ \else
+ \font_helpers_set_current_font_alternative\s!mr
+ \fi
+ \mathdefault}
+
+\unexpanded\def\mb % math bold
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mb
+ \else
+ \font_helpers_set_current_font_alternative\s!mb
+ \fi
+ \mathdefault}
+
+\appendtoks
+ \font_helpers_synchronize_math_family % auto bold
+\to \everymathematics
+
+%D \macros
+%D {bigmath,nobigmath}
+%D
+%D We can inhibit this slow||downer with:
+
+% these can best be combined
+
+% 0=never 1=everymath 2=always
+
+\setnewconstant\synchronizebigmathflag\plusone
+
+\appendtoks
+ \ifcase\synchronizebigmathflag
+ % never
+ \or
+ \synchronizebigmath
+ \or
+ % always
+ \fi
+\to \everymathematics
+
+\unexpanded\def\nobigmath {\synchronizebigmathflag\zerocount}
+\unexpanded\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
+\unexpanded\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
+
+\let\bigmathfontsize\empty
+
+\unexpanded\def\synchronizebigmath
+ {\ifx\bigmathfontsize\fontsize
+ % already in sync
+ \else
+ \let\bigmathfontsize\fontsize
+ \font_helpers_synchronize_math
+ \fi}
+
+\unexpanded\def\font_helpers_check_big_math_synchronization
+ {\ifcase\synchronizebigmathflag
+ % never
+ \or
+ \ifmmode \synchronizebigmath \fi
+ \or
+ \synchronizebigmath
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua b/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua
new file mode 100644
index 00000000000..06bf2204928
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua
@@ -0,0 +1,51 @@
+if not modules then modules = { } end modules ['font-mis'] = {
+ version = 1.001,
+ comment = "companion to mtx-fonts",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+fonts = fonts or { }
+
+fonts.helpers = fonts.helpers or { }
+local helpers = fonts.helpers
+
+fonts.handlers = fonts.handlers or { }
+local handlers = fonts.handlers
+
+handlers.otf = handlers.otf or { }
+local otf = handlers.otf
+
+local readers = otf.readers
+
+if readers then
+
+ otf.version = otf.version or 3.018
+ otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true)
+
+ function fonts.helpers.getfeatures(name,save)
+ local filename = resolvers.findfile(name) or ""
+ if filename ~= "" then
+ local name = file.removesuffix(file.basename(filename))
+ local cleanname = containers.cleanname(name)
+ local data = containers.read(otf.cache,cleanname)
+ if data then
+ readers.unpack(data)
+ else
+ data = readers.loadfont(filename)
+ if data and save then
+ containers.write(otf.cache,cleanname,data)
+ end
+ end
+ return data and data.resources and data.resources.features
+ end
+ end
+
+else
+
+ function fonts.helpers.getfeatures(name)
+ -- not supported
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua b/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua
new file mode 100644
index 00000000000..7b7c859df77
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua
@@ -0,0 +1,450 @@
+if not modules then modules = { } end modules ['font-mps'] = {
+ 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 concat = table.concat
+local formatters = string.formatters
+
+-- QP0 [QP1] QP2 => CP0 [CP1 CP2] CP3
+
+-- CP0 = QP0
+-- CP3 = QP2
+--
+-- CP1 = QP0 + 2/3 *(QP1-QP0)
+-- CP2 = QP2 + 2/3 *(QP1-QP2)
+
+fonts = fonts or { }
+local metapost = fonts.metapost or { }
+fonts.metapost = metapost
+
+local trace_skips = false trackers.register("metapost.outlines.skips",function(v) trace_skips = v end)
+
+local f_moveto = formatters["(%.4F,%.4F)"]
+local f_lineto = formatters["--(%.4F,%.4F)"]
+local f_curveto = formatters["..controls(%.4F,%.4F)and(%.4F,%.4F)..(%.4F,%.4F)"]
+local s_cycle = "--cycle"
+
+local f_nofill = formatters["nofill %s;"]
+local f_dofill = formatters["fill %s;"]
+
+local f_draw_trace = formatters["drawpathonly %s;"]
+local f_draw = formatters["draw %s;"]
+
+local f_boundingbox = formatters["((%.4F,%.4F)--(%.4F,%.4F)--(%.4F,%.4F)--(%.4F,%.4F)--cycle)"]
+local f_vertical = formatters["((%.4F,%.4F)--(%.4F,%.4F))"]
+
+function metapost.boundingbox(d,factor)
+ local bounds = d.boundingbox
+ local factor = factor or 1
+ local llx = factor*bounds[1]
+ local lly = factor*bounds[2]
+ local urx = factor*bounds[3]
+ local ury = factor*bounds[4]
+ return f_boundingbox(llx,lly,urx,lly,urx,ury,llx,ury)
+end
+
+function metapost.widthline(d,factor)
+ local bounds = d.boundingbox
+ local factor = factor or 1
+ local lly = factor*bounds[2]
+ local ury = factor*bounds[4]
+ local width = factor*d.width
+ return f_vertical(width,lly,width,ury)
+end
+
+function metapost.zeroline(d,factor)
+ local bounds = d.boundingbox
+ local factor = factor or 1
+ local lly = factor*bounds[2]
+ local ury = factor*bounds[4]
+ return f_vertical(0,lly,0,ury)
+end
+
+function metapost.paths(d,xfactor,yfactor)
+ local sequence = d.sequence
+ local segments = d.segments
+ local list = { }
+ local path = { } -- recycled
+ local size = 0
+ local xfactor = xfactor or 1
+ local yfactor = yfactor or xfactor
+ if sequence then
+ local i = 1
+ local n = #sequence
+ while i < n do
+ local operator = sequence[i]
+ if operator == "m" then -- "moveto"
+ if size > 0 then
+ size = size + 1
+ path[size] = s_cycle
+ list[#list+1] = concat(path,"",1,size)
+ size = 1
+ else
+ size = size + 1
+ end
+ path[size] = f_moveto(xfactor*sequence[i+1],yfactor*sequence[i+2])
+ i = i + 3
+ elseif operator == "l" then -- "lineto"
+ size = size + 1
+ path[size] = f_lineto(xfactor*sequence[i+1],yfactor*sequence[i+2])
+ i = i + 3
+ elseif operator == "c" then -- "curveto"
+ size = size + 1
+ path[size] = f_curveto(xfactor*sequence[i+1],yfactor*sequence[i+2],xfactor*sequence[i+3],yfactor*sequence[i+4],xfactor*sequence[i+5],yfactor*sequence[i+6])
+ i = i + 7
+ 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]
+ path[size] = f_curveto (
+ l_x + 2/3 * (m_x-l_x),
+ l_y + 2/3 * (m_y-l_y),
+ r_x + 2/3 * (m_x-r_x),
+ r_y + 2/3 * (m_y-r_y),
+ r_x, r_y
+ )
+ i = i + 5
+ else
+ -- weird
+ i = i + 1
+ end
+ end
+ elseif segments then
+ for i=1,#segments do
+ local segment = segments[i]
+ local operator = segment[#segment]
+ if operator == "m" then -- "moveto"
+ if size > 0 then
+ size = size + 1
+ path[size] = s_cycle
+ list[#list+1] = concat(path,"",1,size)
+ size = 1
+ else
+ size = size + 1
+ end
+ path[size] = f_moveto(xfactor*segment[1],yfactor*segment[2])
+ elseif operator == "l" then -- "lineto"
+ size = size + 1
+ path[size] = f_lineto(xfactor*segment[1],yfactor*segment[2])
+ elseif operator == "c" then -- "curveto"
+ size = size + 1
+ path[size] = f_curveto(xfactor*segment[1],yfactor*segment[2],xfactor*segment[3],yfactor*segment[4],xfactor*segment[5],yfactor*segment[6])
+ elseif operator =="q" then -- "quadraticto"
+ 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]
+ path[size] = f_curveto (
+ l_x + 2/3 * (m_x-l_x),
+ l_y + 2/3 * (m_y-l_y),
+ r_x + 2/3 * (m_x-r_x),
+ r_y + 2/3 * (m_y-r_y),
+ r_x, r_y
+ )
+ else
+ -- weird
+ end
+ end
+ else
+ return
+ end
+ if size > 0 then
+ size = size + 1
+ path[size] = s_cycle
+ list[#list+1] = concat(path,"",1,size)
+ end
+ return list
+end
+
+function metapost.fill(paths)
+ local r = { }
+ local n = #paths
+ for i=1,n do
+ if i < n then
+ r[i] = f_nofill(paths[i])
+ else
+ r[i] = f_dofill(paths[i])
+ end
+ end
+ return concat(r)
+end
+
+function metapost.draw(paths,trace)
+ local r = { }
+ local n = #paths
+ for i=1,n do
+ if trace then
+ r[i] = f_draw_trace(paths[i])
+ else
+ r[i] = f_draw(paths[i])
+ end
+ end
+ return concat(r)
+end
+
+function metapost.maxbounds(data,index,factor)
+ local maxbounds = data.maxbounds
+ local factor = factor or 1
+ local glyphs = data.glyphs
+ local glyph = glyphs[index]
+ local boundingbox = glyph.boundingbox
+ local xmin, ymin, xmax, ymax
+ if not maxbounds then
+ xmin, ymin, xmax, ymax = 0, 0, 0, 0
+ for i=1,#glyphs do
+ local d = glyphs[i]
+ if d then
+ local b = d.boundingbox
+ if b then
+ if b[1] < xmin then xmin = b[1] end
+ if b[2] < ymin then ymin = b[2] end
+ if b[3] > xmax then xmax = b[3] end
+ if b[4] > ymax then ymax = b[4] end
+ end
+ end
+ end
+ maxbounds = { xmin, ymin, xmax, ymax }
+ data.maxbounds = maxbounds
+ else
+ xmin = maxbounds[1]
+ ymin = maxbounds[2]
+ xmax = maxbounds[3]
+ ymax = maxbounds[4]
+ end
+ local llx = boundingbox[1]
+ local lly = boundingbox[2]
+ local urx = boundingbox[3]
+ local ury = boundingbox[4]
+ local width = glyph.width
+ if llx > 0 then
+ llx = 0
+ end
+ if width > urx then
+ urx = width
+ end
+ return f_boundingbox(
+ factor*llx,factor*ymin,
+ factor*urx,factor*ymin,
+ factor*urx,factor*ymax,
+ factor*llx,factor*ymax
+ )
+end
+
+----- formatters = string.formatters
+----- concat = table.concat
+
+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 penalty_code = nodecodes.penalty
+
+local find_tail = nodes.tail
+
+----- metapost = fonts.glyphs.metapost
+
+local characters = fonts.hashes.characters
+local quaddata = fonts.hashes.emwidths
+local shapes = fonts.hashes.shapes
+local topaths = metapost.paths
+
+local f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.4F,%.4F)(%,t);"]
+local s_nothing = "(origin scaled 10)"
+local f_trace_rule = formatters["draw rule(%6F,%6F,%6F) shifted (%6F,%6F) withcolor .5white;"]
+local f_strut = formatters["strut(%6F,%6F);"]
+local f_hrule = formatters["draw rule(%6F,%6F,%6F);"]
+local f_vrule = formatters["draw rule(%6F,%6F,%6F) shifted (%6F,%6F);"]
+local f_bounds = formatters["checkbounds(%6F,%6F,%6F,%6F);"]
+
+local sc = 10
+local fc = number.dimenfactors.bp * sc / 10
+
+-- todo: make the next more efficient:
+
+function metapost.output(kind,font,char,advance,shift,ex)
+ local character = characters[font][char]
+ if character then
+ local index = character.index
+ if index then
+ local shapedata = shapes[font]
+ local glyphs = shapedata.glyphs -- todo: subfonts fonts.shapes.indexed(font,sub)
+ if glyphs then
+ local glyf = glyphs[index]
+ if glyf then
+ local units = shapedata.units or 1000
+ local yfactor = sc/units
+ local xfactor = yfactor
+ local shift = shift or 0
+ local advance = advance or 0
+ local exfactor = ex or 0
+ local wfactor = 1
+ if exfactor ~= 0 then
+ wfactor = (1+(ex/units)/1000)
+ xfactor = xfactor * wfactor
+ end
+ local paths = topaths(glyf,xfactor,yfactor)
+ local code = f_code(kind,#paths,advance,shift,paths)
+ return code, character.width * fc * wfactor
+ end
+ end
+ end
+ end
+ return s_nothing, 10 * sc/1000
+end
+
+-- not ok yet: leftoffset in framed not handled well
+
+local signal = -0x3FFFFFFF - 1
+
+function fonts.metapost.boxtomp(n,kind)
+
+ local result = { }
+ local advance = 0 -- in bp
+ local distance = 0
+
+ local llx, lly, urx, ury = 0, 0, 0, 0
+
+ local boxtomp
+
+ local function horizontal(current,shift,glue_sign,glue_set,glue_order,ht,dp)
+ shift = shift or 0
+ while current do
+ local id = current.id
+ if id == glyph_code then
+ local code, width = metapost.output(kind,current.font,current.char,advance,-shift*fc,current.expansion_factor)
+ result[#result+1] = code
+ advance = advance + width
+ elseif id == disc_code then
+ local replace = current.replace
+ if replace then
+ horizontal(replace,shift,glue_sign,glue_set,glue_order,ht,dp)
+ end
+ elseif id == kern_code then
+ local kern = current.kern * fc
+ if trace_skips then
+ result[#result+1] = f_trace_rule(kern,0.8*ht*fc,0.8*dp*fc,advance,-shift*fc)
+ end
+ advance = advance + kern
+ elseif id == glue_code then
+ local width = current.width
+ if glue_sign == 1 then
+ if current.stretch_order == glue_order then
+ width = (width + current.stretch * glue_set) * fc
+ else
+ width = width * fc
+ end
+ elseif glue_sign == 2 then
+ if current.shrink_order == glue_order then
+ width = (width - current.shrink * glue_set) * fc
+ else
+ width = width * fc
+ end
+ else
+ width = width * fc
+ end
+ if trace_skips then
+ result[#result+1] = f_trace_rule(width,0.1*ht*fc,0.1*dp*fc,advance,-shift*fc)
+ end
+ advance = advance + width
+ elseif id == hlist_code then
+ local a = advance
+ boxtomp(current,shift+current.shift,current.glue_sign,current.glue_set,current.glue_order)
+ advance = a + current.width * fc
+ elseif id == vlist_code then
+ boxtomp(current) -- ,distance + shift,current.glue_set*current.glue_sign)
+ advance = advance + current.width * fc
+ elseif id == rule_code then
+ local wd = current.width
+ local ht = current.height
+ local dp = current.depth
+ if not (ht == signal or dp == signal or wd == signal) then
+ ht = ht - shift
+ dp = dp - shift
+ if wd == 0 then
+ result[#result+1] = f_strut(ht*fc,-dp*fc)
+ else
+ result[#result+1] = f_hrule(wd*fc,ht*fc,-dp*fc)
+ end
+ end
+ if wd ~= signal then
+ advance = advance + wd * fc
+ end
+ end
+ current = current.next
+ end
+ end
+
+ local function vertical(current,shift)
+ shift = shift or 0
+ current = find_tail(current) -- otherwise bad bbox
+ while current do
+ local id = current.id
+ if id == hlist_code then
+ distance = distance - current.depth
+ boxtomp(current,distance + shift,current.glue_set*current.glue_sign)
+ distance = distance - current.height
+ elseif id == vlist_code then
+ print("vertical >>>")
+ vertical(current.list,0)
+ elseif id == kern_code then
+ distance = distance - current.kern
+ advance = 0
+ elseif id == glue_code then
+ distance = distance - current.width
+ advance = 0
+ elseif id == rule_code then
+ local wd = current.width
+ local ht = current.height
+ local dp = current.depth
+ if not (ht == signal or dp == signal or wd == signal) then
+ distance = distance - dp
+ if wd == 0 then
+ result[#result+1] = f_strut(ht*fc,-dp*fc)
+ else
+ result[#result+1] = f_vrule(wd*fc,ht*fc,-dp*fc,0,distance+shift)
+ end
+ distance = distance - ht
+ end
+ end
+ current = current.prev
+ end
+ end
+
+ boxtomp = function(list,shift)
+ local current = list.list
+ if current then
+ if list.id == hlist_code then
+ horizontal(current,shift,list.glue_sign,list.glue_set,list.glue_order,list.height,list.depth)
+ else
+ vertical(current,shift)
+ end
+ end
+ end
+
+ local box = tex.box[n]
+
+ boxtomp(box,box.shift,box.glue_sign,box.glue_set,box.glue_order)
+
+ local wd = box.width
+ local ht = box.height
+ local dp = box.depth
+ local sh = box.shift
+
+ result[#result+1] = f_bounds(0,-dp*fc,wd*fc,ht*fc)
+
+ return concat(result)
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua
new file mode 100644
index 00000000000..7f30b6d5cbd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua
@@ -0,0 +1,550 @@
+if not modules then modules = { } end modules ['font-nod'] = {
+ 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"
+}
+
+--[[ldx--
+<p>This is rather experimental. We need more control and some of this
+might become a runtime module instead. This module will be cleaned up!</p>
+--ldx]]--
+
+local tonumber, tostring, rawget = tonumber, tostring, rawget
+local utfchar = utf.char
+local concat, fastcopy = table.concat, table.fastcopy
+local match, rep = string.match, string.rep
+
+local report_nodes = logs.reporter("fonts","tracing")
+
+fonts = fonts or { }
+nodes = nodes or { }
+
+local fonts, nodes, node, context = fonts, nodes, node, context
+
+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 char_tracers = tracers.characters or { }
+tracers.characters = char_tracers
+
+local step_tracers = tracers.steppers or { }
+tracers.steppers = step_tracers
+
+local nodecodes = nodes.nodecodes
+
+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 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 isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setbox = nuts.setbox
+local setchar = nuts.setchar
+local setsubtype = nuts.setsubtype
+
+local copy_node_list = nuts.copy_list
+local hpack_node_list = nuts.hpack
+local free_node_list = nuts.flush_list
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+local protect_glyphs = nuts.protect_glyphs
+
+local nodepool = nuts.pool
+local new_glyph = nodepool.glyph
+
+local formatters = string.formatters
+local formatter = string.formatter
+
+local hashes = fonts.hashes
+
+local fontidentifiers = hashes.identifiers
+local fontdescriptions = hashes.descriptions
+local fontcharacters = hashes.characters
+local fontproperties = hashes.properties
+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)
+ -- report_nodes("freezing %s",where)
+ for n in traverse_nodes(tonut(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
+ -- local i = r.preinjections if i then p.preinjections = fastcopy(i) end
+ -- local i = r.postinjections if i then p.postinjections = fastcopy(i) end
+ -- local i = r.replaceinjections if i then p.replaceinjections = fastcopy(i) end
+ -- only injections
+ end
+ end
+end
+
+function char_tracers.collect(head,list,tag,n)
+ head = tonut(head)
+ n = n or 0
+ local ok, fn = false, nil
+ while head do
+ local c, id = isglyph(head)
+ if c then
+ local f = getfont(head)
+ if f ~= fn then
+ ok, fn = false, f
+ end
+ if not ok then
+ ok = true
+ n = n + 1
+ list[n] = list[n] or { }
+ list[n][tag] = { }
+ end
+ local l = list[n][tag]
+ -- l[#l+1] = { c, f, i }
+ l[#l+1] = { c, f }
+ elseif id == disc_code then
+ -- skip
+-- local pre, post, replace = getdisc(head)
+-- if replace then
+-- for n in traverse_id(glyph_code,replace) do
+-- l[#l+1] = { c, f }
+-- end
+-- end
+-- if pre then
+-- for n in traverse_id(glyph_code,pre) do
+-- l[#l+1] = { c, f }
+-- end
+-- end
+-- if post then
+-- for n in traverse_id(glyph_code,post) do
+-- l[#l+1] = { c, f }
+-- end
+-- end
+ else
+ ok = false
+ end
+ head = getnext(head)
+ end
+end
+
+function char_tracers.equal(ta, tb)
+ if #ta ~= #tb then
+ return false
+ else
+ for i=1,#ta do
+ local a, b = ta[i], 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
+ end
+ end
+ end
+ return true
+end
+
+function char_tracers.string(t)
+ local tt = { }
+ for i=1,#t do
+ tt[i] = utfchar(t[i][1])
+ end
+ return concat(tt,"")
+end
+
+local f_unicode = formatters["%U"]
+local f_badcode = formatters["{%i}"]
+
+function char_tracers.unicodes(t,decimal)
+ local tt = { }
+ for i=1,#t do
+ local n = t[i][1]
+ if n == 0 then
+ tt[i] = "-"
+ elseif decimal then
+ tt[i] = n
+ else
+ tt[i] = f_unicode(n)
+ end
+ end
+ return concat(tt," ")
+end
+
+-- function char_tracers.indices(t,decimal)
+-- local tt = { }
+-- for i=1,#t do
+-- local n = t[i][3]
+-- if n == 0 then
+-- tt[i] = "-"
+-- elseif decimal then
+-- tt[i] = n
+-- else
+-- tt[i] = f_unicode(n)
+-- end
+-- end
+-- return concat(tt," ")
+-- end
+
+function char_tracers.start()
+ local npc = handlers.characters -- should accept nuts too
+ local list = { }
+ function handlers.characters(head)
+ local n = #list
+ char_tracers.collect(head,list,'before',n)
+ local h, d = npc(tonode(head)) -- for the moment tonode
+ char_tracers.collect(head,list,'after',n)
+ if #list > n then
+ list[#list+1] = { }
+ end
+ return h, d
+ end
+ function char_tracers.stop()
+ tracers.list['characters'] = list
+ local variables = {
+ ['title'] = 'ConTeXt Character Processing Information',
+ ['color-background-one'] = lmx.get('color-background-yellow'),
+ ['color-background-two'] = lmx.get('color-background-purple'),
+ }
+ lmx.show('context-characters.lmx',variables)
+ handlers.characters = npc
+ tasks.restart("processors", "characters")
+ end
+ tasks.restart("processors", "characters")
+end
+
+local stack = { }
+
+function tracers.start(tag)
+ stack[#stack+1] = tag
+ local tracer = tracers[tag]
+ if tracer and tracer.start then
+ tracer.start()
+ end
+end
+function tracers.stop()
+ local tracer = stack[#stack]
+ if tracer and tracer.stop then
+ tracer.stop()
+ end
+ stack[#stack] = nil
+end
+
+-- experimental
+
+local collection, collecting, messages = { }, false, { }
+
+function step_tracers.start()
+ collecting = true
+end
+
+function step_tracers.stop()
+ collecting = false
+end
+
+function step_tracers.reset()
+ for i=1,#collection do
+ local c = collection[i]
+ if c then
+ free_node_list(c)
+ end
+ end
+ collection, messages = { }, { }
+end
+
+function step_tracers.nofsteps()
+ return context(#collection)
+end
+
+function step_tracers.glyphs(n,i)
+ local c = collection[i]
+ if c then
+ local c = copy_node_list(c)
+ local b = hpack_node_list(c) -- multiple arguments
+ setbox(n,b)
+ end
+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, t = fontidentifiers[getfont(f)], { }
+ for feature, value in table.sortedhash(tfmdata.shared.features) do
+ if feature == "number" or feature == "features" then
+ -- private
+ elseif type(value) == "boolean" then
+ if value then
+ t[#t+1] = formatters["%s=yes"](feature)
+ else
+ -- skip
+ end
+ else
+ t[#t+1] = formatters["%s=%s"](feature,value)
+ end
+ end
+ if #t > 0 then
+ context(concat(t,", "))
+ else
+ context("no features")
+ end
+ return
+ end
+ f = getnext(f)
+ end
+end
+
+function tracers.fontchar(font,char)
+ local n = new_glyph(font,char)
+ setsubtype(n,256)
+ context(tonode(n))
+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
+ else
+ c = getnext(c)
+ end
+ end
+end
+
+local colors = {
+ pre = { "darkred" },
+ post = { "darkgreen" },
+ replace = { "darkblue" },
+}
+
+function step_tracers.codes(i,command,space)
+ local c = collection[i]
+
+ local function showchar(c)
+ local f = getfont(c)
+ local c = getchar(c)
+ if command then
+ local d = fontdescriptions[f]
+ local d = d and d[c]
+ context[command](f,c,d and d.class or "")
+ else
+ context("[%s:U+%05X]",f,c)
+ end
+ end
+
+ local function showdisc(d,w,what)
+ if w then
+ context.startcolor(colors[what])
+ context("%s:",what)
+ for c in traverse_nodes(w) do
+ local id = getid(c)
+ if id == glyph_code then
+ showchar(c)
+ else
+ context("[%s]",nodecodes[id])
+ end
+ end
+ context[space]()
+ context.stopcolor()
+ end
+ 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]",getfield(c,"dir"))
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(c)
+ if pre or post or replace then
+ context("[")
+ context[space]()
+ showdisc(c,pre,"pre")
+ showdisc(c,post,"post")
+ showdisc(c,replace,"replace")
+ context[space]()
+ context("]")
+ else
+ context("[disc]")
+ end
+ else
+ context("[%s]",nodecodes[id])
+ end
+ c = getnext(c)
+ end
+end
+
+function step_tracers.messages(i,command,split)
+ local list = messages[i] -- or { "no messages" }
+ if list then
+ for i=1,#list do
+ local l = list[i]
+ if not command then
+ context("(%s)",l)
+ elseif split then
+ local a, b = match(l,"^(.-)%s*:%s*(.*)$")
+ context[command](a or l or "",b or "")
+ else
+ context[command](l)
+ end
+ end
+ end
+end
+
+-- hooks into the node list processor (see otf)
+
+function step_tracers.check(head)
+ if collecting then
+ step_tracers.reset()
+ local h = tonut(head)
+ local n = copy_node_list(h)
+ freeze(n,"check")
+ injections.keepcounts(n) -- one-time
+ injections.handler(n,"trace")
+ protect_glyphs(n)
+ collection[1] = n
+ end
+end
+
+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)
+ freeze(n,"register")
+ injections.keepcounts(n) -- one-time
+ injections.handler(n,"trace")
+ protect_glyphs(n)
+ collection[nc] = n
+ end
+ end
+end
+
+function step_tracers.message(str,...)
+ str = formatter(str,...)
+ if collecting then
+ local n = #collection + 1
+ local m = messages[n]
+ if not m then m = { } messages[n] = m end
+ m[#m+1] = str
+ end
+ return str -- saves an intermediate var in the caller
+end
+
+--
+
+local threshold = 65536
+
+local function toutf(list,result,nofresult,stopcriterium)
+ if list then
+ for n in traverse_nodes(tonut(list)) do
+ local c, id = isglyph(n)
+ if c then
+ local components = getfield(n,"components")
+ if components then
+ result, nofresult = toutf(components,result,nofresult)
+ elseif c > 0 then
+ local fc = fontcharacters[getfont(n)]
+ if fc then
+ local fcc = fc[c]
+ if fcc then
+ local u = fcc.unicode
+ if not u then
+ nofresult = nofresult + 1
+ result[nofresult] = utfchar(c)
+ elseif type(u) == "table" then
+ for i=1,#u do
+ nofresult = nofresult + 1
+ result[nofresult] = utfchar(u[i])
+ end
+ else
+ nofresult = nofresult + 1
+ result[nofresult] = utfchar(u)
+ end
+ else
+ nofresult = nofresult + 1
+ result[nofresult] = utfchar(c)
+ end
+ else
+ nofresult = nofresult + 1
+ result[nofresult] = f_unicode(c)
+ end
+ else
+ nofresult = nofresult + 1
+ result[nofresult] = f_badcode(c)
+ end
+ elseif id == disc_code then
+ result, nofresult = toutf(getfield(n,"replace"),result,nofresult) -- needed?
+ elseif id == hlist_code or id == vlist_code then
+ -- if nofresult > 0 and result[nofresult] ~= " " then
+ -- nofresult = nofresult + 1
+ -- result[nofresult] = " "
+ -- end
+ result, nofresult = toutf(getlist(n),result,nofresult)
+ elseif id == glue_code then
+ if nofresult > 0 and result[nofresult] ~= " " then
+ nofresult = nofresult + 1
+ result[nofresult] = " "
+ end
+ elseif id == kern_code and getfield(n,"kern") > threshold then
+ if nofresult > 0 and result[nofresult] ~= " " then
+ nofresult = nofresult + 1
+ result[nofresult] = " "
+ end
+ end
+ if n == stopcriterium then
+ break
+ end
+ end
+ end
+ if nofresult > 0 and result[nofresult] == " " then
+ result[nofresult] = nil
+ nofresult = nofresult - 1
+ end
+ return result, nofresult
+end
+
+function nodes.toutf(list,stopcriterium)
+ local result, nofresult = toutf(list,{},0,stopcriterium)
+ return concat(result)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-odk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-odk.lua
new file mode 100644
index 00000000000..c34efc1203e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-odk.lua
@@ -0,0 +1,904 @@
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+-- We keep the original around for a while so that we can check it --
+-- when the above code does it wrong (data tables are not included). --
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+-- author : Kai Eigner, TAT Zetwerk
+-- copyright : TAT Zetwerk
+-- comment : see font-odv.lua for current implementation
+
+-- local state = attributes.private('state')
+-- local sylnr = attributes.private('syllabe')
+--
+-- local function install_dev(tfmdata)
+-- local features = tfmdata.resources.features
+-- local sequences = tfmdata.resources.sequences
+--
+-- local insertpos = 1
+-- for s=1,#sequences do -- classify chars
+-- for k in pairs(basic_shaping_forms) do
+-- if sequences[s].features and ( sequences[s].features[k] or sequences[s].features.locl ) then insertpos = s + 1 end
+-- end
+-- end
+--
+-- features.gsub["dev2_reorder_matras"] = { ["dev2"] = { ["dflt"] = true } }
+-- features.gsub["dev2_reorder_reph"] = { ["dev2"] = { ["dflt"] = true } }
+-- features.gsub["dev2_reorder_pre_base_reordering_consonants"] = { ["dev2"] = { ["dflt"] = true } }
+-- features.gsub["remove_joiners"] = { ["deva"] = { ["dflt"] = true }, ["dev2"] = { ["dflt"] = true } }
+--
+-- local sequence_dev2_reorder_matras = {
+-- chain = 0,
+-- features = { dev2_reorder_matras = { dev2 = { dflt = true } } },
+-- flags = { false, false, false, false },
+-- name = "dev2_reorder_matras",
+-- subtables = { "dev2_reorder_matras" },
+-- type = "dev2_reorder_matras",
+-- }
+-- local sequence_dev2_reorder_reph = {
+-- chain = 0,
+-- features = { dev2_reorder_reph = { dev2 = { dflt = true } } },
+-- flags = { false, false, false, false },
+-- name = "dev2_reorder_reph",
+-- subtables = { "dev2_reorder_reph" },
+-- type = "dev2_reorder_reph",
+-- }
+-- local sequence_dev2_reorder_pre_base_reordering_consonants = {
+-- chain = 0,
+-- features = { dev2_reorder_pre_base_reordering_consonants = { dev2 = { dflt = true } } },
+-- flags = { false, false, false, false },
+-- name = "dev2_reorder_pre_base_reordering_consonants",
+-- subtables = { "dev2_reorder_pre_base_reordering_consonants" },
+-- type = "dev2_reorder_pre_base_reordering_consonants",
+-- }
+-- local sequence_remove_joiners = {
+-- chain = 0,
+-- features = { remove_joiners = { deva = { dflt = true }, dev2 = { dflt = true } } },
+-- flags = { false, false, false, false },
+-- name = "remove_joiners",
+-- subtables = { "remove_joiners" },
+-- type = "remove_joiners",
+-- }
+-- table.insert(sequences, insertpos, sequence_dev2_reorder_pre_base_reordering_consonants)
+-- table.insert(sequences, insertpos, sequence_dev2_reorder_reph)
+-- table.insert(sequences, insertpos, sequence_dev2_reorder_matras)
+-- table.insert(sequences, insertpos, sequence_remove_joiners)
+-- end
+--
+-- local function deva_reorder(head,start,stop,font,attr)
+-- local tfmdata = fontdata[font]
+-- local lookuphash = tfmdata.resources.lookuphash
+-- local sequences = tfmdata.resources.sequences
+--
+-- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features
+--
+-- local sharedfeatures = tfmdata.shared.features
+-- sharedfeatures["remove_joiners"] = true
+-- local datasets = otf.dataset(tfmdata,font,attr)
+--
+-- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true }
+--
+-- local current, n, base, firstcons, lastcons, basefound = start, start.next, nil, nil, nil, false
+-- local reph, vattu = false, false
+-- for s=1,#sequences do
+-- local dataset = datasets[s]
+-- featurevalue = dataset and dataset[1]
+-- if featurevalue and dataset[4] == "rphf" then reph = true end
+-- if featurevalue and dataset[4] == "blwf" then vattu = true end
+-- end
+-- if ra[start.char] and halant[n.char] and reph then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
+-- if n == stop then return head, stop end
+-- if zwj[n.next.char] then
+-- current = start
+-- else
+-- current = n.next
+-- set_attribute(start,state,5) -- rphf
+-- end
+-- end
+--
+-- if nbsp[current.char] then --Stand Alone cluster
+-- if current == stop then
+-- stop = stop.prev
+-- head = node.remove(head, current)
+-- node.free(current)
+-- return head, stop
+-- else
+-- base, firstcons, lastcons = current, current, current
+-- current = current.next
+-- if current ~= stop then
+-- if nukta[current.char] then current = current.next end
+-- if zwj[current.char] then
+-- if current ~= stop and current.next ~= stop and halant[current.next.char] then
+-- current = current.next
+-- local tmp = current.next.next
+-- local changestop = current.next == stop
+-- local tempcurrent = node.copy(current.next)
+-- tempcurrent.next = node.copy(current)
+-- tempcurrent.next.prev = tempcurrent
+-- set_attribute(tempcurrent,state,8) --blwf
+-- tempcurrent = nodes.handlers.characters(tempcurrent)
+-- unset_attribute(tempcurrent,state)
+-- if current.next.char == tempcurrent.char then
+-- node.flush_list(tempcurrent)
+-- local n = node.copy(current)
+-- current.char = dotted_circle
+-- head = node.insert_after(head, current, n)
+-- else
+-- current.char = tempcurrent.char -- (assumes that result of blwf consists of one node)
+-- local freenode = current.next
+-- current.next = tmp
+-- tmp.prev = current
+-- node.free(freenode)
+-- node.flush_list(tempcurrent)
+-- if changestop then stop = current end
+-- end
+-- end
+-- end
+-- end
+-- end
+-- end
+--
+-- while not basefound do -- find base consonant
+-- if consonant[current.char] then
+-- set_attribute(current, state, 6) -- half
+-- if not firstcons then firstcons = current end
+-- lastcons = current
+-- if not base then
+-- base = current
+-- else --check whether consonant has below-base (or post-base) form
+-- local baseform = true
+-- for s=1,#sequences do
+-- local sequence = sequences[s]
+-- local dataset = datasets[s]
+-- featurevalue = dataset and dataset[1]
+-- if featurevalue and dataset[4] == "blwf" then
+-- local subtables = sequence.subtables
+-- for i=1,#subtables do
+-- local lookupname = subtables[i]
+-- local lookupcache = lookuphash[lookupname]
+-- if lookupcache then
+-- local lookupmatch = lookupcache[current.char]
+-- if lookupmatch then
+-- set_attribute(current, state, 8) -- blwf
+-- baseform = false
+-- end
+-- end
+-- end
+-- end
+-- end
+-- if baseform then base = current end
+-- end
+-- end
+-- basefound = current == stop
+-- current = current.next
+-- end
+-- if base ~= lastcons then -- if base consonant is not last one then move halant from base consonant to last one
+-- n = base.next
+-- if nukta[n.char] then n = n.next end
+-- if halant[n.char] then
+-- if lastcons ~= stop then
+-- local ln = lastcons.next
+-- if nukta[ln.char] then lastcons = ln end
+-- end
+-- local np, nn, ln = n.prev, n.next, lastcons.next
+-- np.next = n.next
+-- nn.prev = n.prev
+-- lastcons.next = n
+-- if ln then ln.prev = n end
+-- n.next = ln
+-- n.prev = lastcons
+-- if lastcons == stop then stop = n end
+-- end
+-- end
+--
+-- n = start.next
+-- if ra[start.char] and halant[n.char] and not ( n ~= stop and ( zwj[n.next.char] or zwnj[n.next.char] ) ) then -- if syllable starts with Ra + H then move this combination so that it follows either: the post-base 'matra' (if any) or the base consonant
+-- local matra = base
+-- if base ~= stop and dependent_vowel[base.next.char] then matra = base.next end
+-- local sp, nn, mn = start.prev, n.next, matra.next
+-- if sp then sp.next = nn end
+-- nn.prev = sp
+-- matra.next = start
+-- start.prev = matra
+-- n.next = mn
+-- if mn then mn.prev = n end
+-- if head == start then head = nn end
+-- start = nn
+-- if matra == stop then stop = n end
+-- end
+--
+-- local current = start
+-- while current ~= stop do
+-- if halant[current.next.char] and current.next ~= stop and zwnj[current.next.next.char] then unset_attribute(current, state) end
+-- current = current.next
+-- end
+--
+-- if has_attribute(base, state) and base ~= stop and halant[base.next.char] and not ( base.next ~= stop and zwj[base.next.next.char] ) then unset_attribute(base, state) end
+--
+-- local current, allreordered, moved = start, false, { [base] = true }
+-- local a, b, p, bn = base, base, base, base.next
+-- if base ~= stop and nukta[bn.char] then a, b, p = bn, bn, bn end
+-- while not allreordered do
+-- local c, n, l = current, current.next, nil --current is always consonant
+-- if c ~= stop and nukta[n.char] then c = n n = n.next end
+-- if c ~= stop and halant[n.char] then c = n n = n.next end
+-- while c ~= stop and dependent_vowel[n.char] do c = n n = n.next end
+-- if c ~= stop and vowel_modifier[n.char] then c = n n = n.next end
+-- if c ~= stop and stress_tone_mark[n.char] then c = n n = n.next end
+-- local bp, cn = firstcons.prev, current.next
+-- while cn ~= c.next do -- move pre-base matras...
+-- if pre_mark[cn.char] then
+-- if bp then bp.next = cn end
+-- cn.prev.next = cn.next
+-- if cn.next then cn.next.prev = cn.prev end
+-- if cn == stop then stop = cn.prev end
+-- cn.prev = bp
+-- cn.next = firstcons
+-- firstcons.prev = cn
+-- if firstcons == start then
+-- if head == start then head = cn end
+-- start = cn
+-- end
+-- break
+-- end
+-- cn = cn.next
+-- end
+-- allreordered = c == stop
+-- current = c.next
+-- end
+--
+-- if reph or vattu then
+-- local current, cns = start, nil
+-- while current ~= stop do
+-- local c, n = current, current.next
+-- if ra[current.char] and halant[n.char] then
+-- c, n = n, n.next
+-- local b, bn = base, base
+-- while bn ~= stop do
+-- if dependent_vowel[bn.next.char] then b = bn.next end
+-- bn = bn.next
+-- end
+-- if has_attribute(current,state,attribute) == 5 then -- position Reph (Ra + H) after post-base 'matra' (if any) since these become marks on the 'matra', not on the base glyph
+-- if b ~= current then
+-- if current == start then
+-- if head == start then head = n end
+-- start = n
+-- end
+-- if b == stop then stop = c end
+-- if current.prev then current.prev.next = n end
+-- if n then n.prev = current.prev end
+-- c.next = b.next
+-- if b.next then b.next.prev = c end
+-- b.next = current
+-- current.prev = b
+-- end
+-- elseif cns and cns.next ~= current then -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants)
+-- local cp, cnsn = current.prev, cns.next
+-- if cp then cp.next = n end
+-- if n then n.prev = cp end
+-- cns.next = current
+-- current.prev = cns
+-- c.next = cnsn
+-- if cnsn then cnsn.prev = c end
+-- if c == stop then stop = cp break end
+-- current = n.prev
+-- end
+-- elseif consonant[current.char] or nbsp[current.char] then
+-- cns = current
+-- if halant[cns.next.char] then cns = cns.next end
+-- end
+-- current = current.next
+-- end
+-- end
+--
+-- if nbsp[base.char] then
+-- head = node.remove(head, base)
+-- node.free(base)
+-- end
+--
+-- return head, stop
+-- end
+--
+-- function dev2_reorder_matras(start,kind,lookupname,replacement)
+-- local current = start
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
+-- if halant[current.char] and not has_attribute(current, state) then
+-- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
+-- local sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- if current.next then current.next.prev = start end
+-- start.next = current.next
+-- current.next = start
+-- start.prev = current
+-- start = sn
+-- break
+-- end
+-- current = current.next
+-- end
+-- return start, true
+-- end
+--
+-- function dev2_reorder_reph(start,kind,lookupname,replacement)
+-- local current, sn = start.next, nil
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 2
+-- if halant[current.char] and not has_attribute(current, state) then
+-- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- if current.next then current.next.prev = start end
+-- start.next = current.next
+-- current.next = start
+-- start.prev = current
+-- start = sn
+-- break
+-- end
+-- current = current.next
+-- end
+-- if not sn then
+-- current = start.next
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 4
+-- if has_attribute(current, state) == 9 then --post-base
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- start.prev = current.prev
+-- current.prev.next = start
+-- start.next = current
+-- current.prev = start
+-- start = sn
+-- break
+-- end
+-- current = current.next
+-- end
+-- end
+-- if not sn then
+-- current = start.next
+-- local c = nil
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 5
+-- if not c and ( above_mark[current.char] or below_mark[current.char] or post_mark[current.char] ) and ReorderClass[current.char] ~= "after subscript" then c = current end
+-- current = current.next
+-- end
+-- if c then
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- start.prev = c.prev
+-- c.prev.next = start
+-- start.next = c
+-- c.prev = start
+-- start = sn
+-- end
+-- end
+-- if not sn then
+-- current = start
+-- while current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) do --step 6
+-- current = current.next
+-- end
+-- if start ~= current then
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- if current.next then current.next.prev = start end
+-- start.next = current.next
+-- current.next = start
+-- start.prev = current
+-- start = sn
+-- end
+-- end
+-- return start, true
+-- end
+--
+-- function dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
+-- local current, sn = start, nil
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
+-- if halant[current.char] and not has_attribute(current, state) then
+-- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- if current.next then current.next.prev = start end
+-- start.next = current.next
+-- current.next = start
+-- start.prev = current
+-- start = sn
+-- break
+-- end
+-- current = current.next
+-- end
+-- if not sn then
+-- current = start.next
+-- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
+-- if not consonant[current.char] and has_attribute(current, state) then --main
+-- sn = start.next
+-- start.next.prev = start.prev
+-- if start.prev then start.prev.next = start.next end
+-- start.prev = current.prev
+-- current.prev.next = start
+-- start.next = current
+-- current.prev = start
+-- start = sn
+-- break
+-- end
+-- current = current.next
+-- end
+-- end
+-- return start, true
+-- end
+--
+-- function remove_joiners(start,kind,lookupname,replacement)
+-- local stop = start.next
+-- while stop and stop.id == glyph and stop.subtype<256 and stop.font == start.font and (zwj[stop.char] or zwnj[stop.char]) do stop = stop.next end
+-- if stop then stop.prev.next = nil stop.prev = start.prev end
+-- if start.prev then start.prev.next = stop end
+-- node.flush_list(start)
+-- return stop, true
+-- end
+--
+-- local function dev2_reorder(head,start,stop,font,attr)
+-- local tfmdata = fontdata[font]
+-- local lookuphash = tfmdata.resources.lookuphash
+-- local sequences = tfmdata.resources.sequences
+--
+-- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features
+--
+-- local sharedfeatures = tfmdata.shared.features
+-- sharedfeatures["dev2_reorder_matras"] = true
+-- sharedfeatures["dev2_reorder_reph"] = true
+-- sharedfeatures["dev2_reorder_pre_base_reordering_consonants"] = true
+-- sharedfeatures["remove_joiners"] = true
+-- local datasets = otf.dataset(tfmdata,font,attr)
+--
+-- local reph, pre_base_reordering_consonants = false, nil
+-- local halfpos, basepos, subpos, postpos = nil, nil, nil, nil
+-- local locl = { }
+--
+-- for s=1,#sequences do -- classify chars
+-- local sequence = sequences[s]
+-- local dataset = datasets[s]
+-- featurevalue = dataset and dataset[1]
+-- if featurevalue and dataset[4] then
+-- local subtables = sequence.subtables
+-- for i=1,#subtables do
+-- local lookupname = subtables[i]
+-- local lookupcache = lookuphash[lookupname]
+-- if lookupcache then
+-- if dataset[4] == "rphf" then
+-- if dataset[3] ~= 0 then --rphf is result of of chain
+-- else
+-- reph = lookupcache[0x0930] and lookupcache[0x0930][0x094D] and lookupcache[0x0930][0x094D]["ligature"]
+-- end
+-- end
+-- if dataset[4] == "pref" and not pre_base_reordering_consonants then
+-- for k, v in pairs(lookupcache[0x094D]) do
+-- pre_base_reordering_consonants[k] = v and v["ligature"] --ToDo: reph might also be result of chain
+-- end
+-- end
+-- local current = start
+-- while current ~= stop.next do
+-- if dataset[4] == "locl" then locl[current] = lookupcache[current.char] end --ToDo: locl might also be result of chain
+-- if current ~= stop then
+-- local c, n = locl[current] or current.char, locl[current.next] or current.next.char
+-- if dataset[4] == "rphf" and lookupcache[c] and lookupcache[c][n] then --above-base: rphf Consonant + Halant
+-- if current.next ~= stop and ( zwj[current.next.next.char] or zwnj[current.next.next.char] ) then --ZWJ and ZWNJ prevent creation of reph
+-- current = current.next
+-- elseif current == start then
+-- set_attribute(current,state,5)
+-- end
+-- current = current.next
+-- end
+-- if dataset[4] == "half" and lookupcache[c] and lookupcache[c][n] then --half forms: half Consonant + Halant
+-- if current.next ~= stop and zwnj[current.next.next.char] then --ZWNJ prevent creation of half
+-- current = current.next
+-- else
+-- set_attribute(current,state,6)
+-- if not halfpos then halfpos = current end
+-- end
+-- current = current.next
+-- end
+-- if dataset[4] == "pref" and lookupcache[c] and lookupcache[c][n] then --pre-base: pref Halant + Consonant
+-- set_attribute(current,state,7)
+-- set_attribute(current.next,state,7)
+-- current = current.next
+-- end
+-- if dataset[4] == "blwf" and lookupcache[c] and lookupcache[c][n] then --below-base: blwf Halant + Consonant
+-- set_attribute(current,state,8)
+-- set_attribute(current.next,state,8)
+-- current = current.next
+-- subpos = current
+-- end
+-- if dataset[4] == "pstf" and lookupcache[c] and lookupcache[c][n] then --post-base: pstf Halant + Consonant
+-- set_attribute(current,state,9)
+-- set_attribute(current.next,state,9)
+-- current = current.next
+-- postpos = current
+-- end
+-- end
+-- current = current.next
+-- end
+-- end
+-- end
+-- end
+-- end
+--
+-- lookuphash["dev2_reorder_matras"] = pre_mark
+-- lookuphash["dev2_reorder_reph"] = { [reph] = true }
+-- lookuphash["dev2_reorder_pre_base_reordering_consonants"] = pre_base_reordering_consonants or { }
+-- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true }
+--
+-- local current, base, firstcons = start, nil, nil
+-- if has_attribute(start,state) == 5 then current = start.next.next end -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
+--
+-- if current ~= stop.next and nbsp[current.char] then --Stand Alone cluster
+-- if current == stop then
+-- stop = stop.prev
+-- head = node.remove(head, current)
+-- node.free(current)
+-- return head, stop
+-- else
+-- base = current
+-- current = current.next
+-- if current ~= stop then
+-- if nukta[current.char] then current = current.next end
+-- if zwj[current.char] then
+-- if current ~= stop and current.next ~= stop and halant[current.next.char] then
+-- current = current.next
+-- local tmp = current.next.next
+-- local changestop = current.next == stop
+-- current.next.next = nil
+-- set_attribute(current,state,7) --pref
+-- current = nodes.handlers.characters(current)
+-- set_attribute(current,state,8) --blwf
+-- current = nodes.handlers.characters(current)
+-- set_attribute(current,state,9) --pstf
+-- current = nodes.handlers.characters(current)
+-- unset_attribute(current,state)
+-- if halant[current.char] then
+-- current.next.next = tmp
+-- local nc = node.copy(current)
+-- current.char = dotted_circle
+-- head = node.insert_after(head, current, nc)
+-- else
+-- current.next = tmp -- (assumes that result of pref, blwf, or pstf consists of one node)
+-- if changestop then stop = current end
+-- end
+-- end
+-- end
+-- end
+-- end
+-- else --not Stand Alone cluster
+-- while current ~= stop.next do -- find base consonant
+-- if consonant[current.char] and not ( current ~= stop and halant[current.next.char] and current.next ~= stop and zwj[current.next.next.char] ) then
+-- if not firstcons then firstcons = current end
+-- if not ( has_attribute(current, state) == 7 or has_attribute(current, state) == 8 or has_attribute(current, state) == 9 ) then base = current end --check whether consonant has below-base or post-base form or is pre-base reordering Ra
+-- end
+-- current = current.next
+-- end
+-- if not base then
+-- base = firstcons
+-- end
+-- end
+--
+-- if not base then
+-- if has_attribute(start, state) == 5 then unset_attribute(start, state) end
+-- return head, stop
+-- else
+-- if has_attribute(base, state) then unset_attribute(base, state) end
+-- basepos = base
+-- end
+-- if not halfpos then halfpos = base end
+-- if not subpos then subpos = base end
+-- if not postpos then postpos = subpos or base end
+--
+-- --Matra characters are classified and reordered by which consonant in a conjunct they have affinity for
+-- local moved = { }
+-- current = start
+-- while current ~= stop.next do
+-- local char, target, cn = locl[current] or current.char, nil, current.next
+-- if not moved[current] and dependent_vowel[char] then
+-- if pre_mark[char] then -- Before first half form in the syllable
+-- moved[current] = true
+-- if current.prev then current.prev.next = current.next end
+-- if current.next then current.next.prev = current.prev end
+-- if current == stop then stop = current.prev end
+-- if halfpos == start then
+-- if head == start then head = current end
+-- start = current
+-- end
+-- if halfpos.prev then halfpos.prev.next = current end
+-- current.prev = halfpos.prev
+-- halfpos.prev = current
+-- current.next = halfpos
+-- halfpos = current
+-- elseif above_mark[char] then -- After main consonant
+-- target = basepos
+-- if subpos == basepos then subpos = current end
+-- if postpos == basepos then postpos = current end
+-- basepos = current
+-- elseif below_mark[char] then -- After subjoined consonants
+-- target = subpos
+-- if postpos == subpos then postpos = current end
+-- subpos = current
+-- elseif post_mark[char] then -- After post-form consonant
+-- target = postpos
+-- postpos = current
+-- end
+-- if ( above_mark[char] or below_mark[char] or post_mark[char] ) and current.prev ~= target then
+-- if current.prev then current.prev.next = current.next end
+-- if current.next then current.next.prev = current.prev end
+-- if current == stop then stop = current.prev end
+-- if target.next then target.next.prev = current end
+-- current.next = target.next
+-- target.next = current
+-- current.prev = target
+-- end
+-- end
+-- current = cn
+-- end
+--
+-- --Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first.
+-- local current, c = start, nil
+-- while current ~= stop do
+-- if halant[current.char] or stress_tone_mark[current.char] then
+-- if not c then c = current end
+-- else
+-- c = nil
+-- end
+-- if c and nukta[current.next.char] then
+-- if head == c then head = current.next end
+-- if stop == current.next then stop = current end
+-- if c.prev then c.prev.next = current.next end
+-- current.next.prev = c.prev
+-- current.next = current.next.next
+-- if current.next.next then current.next.next.prev = current end
+-- c.prev = current.next
+-- current.next.next = c
+-- end
+-- if stop == current then break end
+-- current = current.next
+-- end
+--
+-- if nbsp[base.char] then
+-- head = node.remove(head, base)
+-- node.free(base)
+-- end
+--
+-- return head, stop
+-- end
+--
+-- function fonts.analyzers.methods.deva(head,font,attr)
+-- local orighead = head
+-- local current, start, done = head, true, false
+-- while current do
+-- if current.id == glyph and current.subtype<256 and current.font == font then
+-- done = true
+-- local syllablestart, syllableend = current, nil
+--
+-- local c = current --Checking Stand Alone cluster (this behavior is copied from dev2)
+-- if ra[c.char] and c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] and c.next.next and c.next.next.id == glyph and c.next.next.subtype<256 and c.next.next.font == font then c = c.next.next end
+-- if nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or
+-- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and
+-- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] )
+-- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- local n = c.next
+-- if n and n.id == glyph and n.subtype<256 and n.font == font then
+-- local ni = n.next
+-- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end
+-- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end
+-- end
+-- while c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] do c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- current = c.next
+-- syllableend = c
+-- if syllablestart ~= syllableend then
+-- head, current = deva_reorder(head, syllablestart,syllableend,font,attr)
+-- current = current.next
+-- end
+-- elseif consonant[current.char] then -- syllable containing consonant
+-- prevc = true
+-- while prevc do
+-- prevc = false
+-- local n = current.next
+-- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end
+-- if n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] then
+-- local n = n.next
+-- if n and n.id == glyph and n.subtype<256 and n.font == font and ( zwj[n.char] or zwnj[n.char] ) then n = n.next end
+-- if n and n.id == glyph and n.subtype<256 and n.font == font and consonant[n.char] then
+-- prevc = true
+-- current = n
+-- end
+-- end
+-- end
+-- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and nukta[current.next.char] then current = current.next end -- nukta (not specified in Microsft Devanagari OpenType specification)
+-- syllableend = current
+-- current = current.next
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and halant[current.char] then -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H
+-- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
+-- syllableend = current
+-- current = current.next
+-- else -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM]
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and dependent_vowel[current.char] then
+-- syllableend = current
+-- current = current.next
+-- end
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then
+-- syllableend = current
+-- current = current.next
+-- end
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then
+-- syllableend = current
+-- current = current.next
+-- end
+-- end
+-- if syllablestart ~= syllableend then
+-- head, current = deva_reorder(head,syllablestart,syllableend,font,attr)
+-- current = current.next
+-- end
+-- elseif current.id == glyph and current.subtype<256 and current.font == font and independent_vowel[current.char] then -- syllable without consonants: VO + [VM] + [SM]
+-- syllableend = current
+-- current = current.next
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then
+-- syllableend = current
+-- current = current.next
+-- end
+-- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then
+-- syllableend = current
+-- current = current.next
+-- end
+-- else -- Syntax error
+-- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then
+-- local n = node.copy(current)
+-- if pre_mark[current.char] then
+-- n.char = dotted_circle
+-- else
+-- current.char = dotted_circle
+-- end
+-- head, current = node.insert_after(head, current, n)
+-- end
+-- current = current.next
+-- end
+-- else
+-- current = current.next
+-- end
+-- start = false
+-- end
+--
+-- return head, done
+-- end
+--
+-- function fonts.analyzers.methods.dev2(head,font,attr)
+-- local current, start, done, syl_nr = head, true, false, 0
+-- while current do
+-- local syllablestart, syllableend = nil, nil
+-- if current.id == glyph and current.subtype<256 and current.font == font then
+-- syllablestart = current
+-- done = true
+-- local c, n = current, current.next
+-- if ra[current.char] and n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] and n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font then c = n.next end
+-- if independent_vowel[c.char] then --Vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+-- n = c.next
+-- local ni, nii = nil, nil
+-- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end
+-- if n and n.id == glyph and n.subtype<256 and n.font == font then local ni = n.next end
+-- if ni and ni.id == glyph and ni.subtype<256 and ni.font == font and ni.next and ni.next.id == glyph and ni.next.subtype<256 and ni.next.font == font then
+-- nii = ni.next
+-- if zwj[ni.char] and consonant[nii.char] then
+-- c = nii
+-- elseif (zwj[ni.char] or zwnj[ni.char]) and halant[nii.char] and nii.next and nii.next.id == glyph and nii.next.subtype<256 and nii.next.font == font and consonant[nii.next.char] then
+-- c = nii.next
+-- end
+-- end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- current = c
+-- syllableend = c
+-- elseif nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or
+-- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and
+-- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] )
+-- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- n = c.next
+-- if n and n.id == glyph and n.subtype<256 and n.font == font then
+-- local ni = n.next
+-- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end
+-- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end
+-- end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- current = c
+-- syllableend = c
+-- elseif consonant[current.char] then --Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)]
+-- c = current
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- n = c
+-- while n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( halant[n.next.char] or zwnj[n.next.char] or zwj[n.next.char] ) do
+-- if halant[n.next.char] then
+-- n = n.next
+-- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( zwnj[n.next.char] or zwj[n.next.char] ) then n = n.next end
+-- else
+-- if n.next.next and n.next.next.id == glyph and n.next.next.subtype<256 and n.next.next.font == font and halant[n.next.next.char] then n = n.next.next end
+-- end
+-- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and consonant[n.next.char] then
+-- n = n.next
+-- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and nukta[n.next.char] then n = n.next end
+-- c = n
+-- else
+-- break
+-- end
+-- end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and anudatta[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then
+-- c = c.next
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and ( zwnj[c.next.char] or zwj[c.next.char] ) then c = c.next end
+-- else
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
+-- end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
+-- current = c
+-- syllableend = c
+-- end
+-- end
+--
+-- if syllableend then
+-- syl_nr = syl_nr + 1
+-- c = syllablestart
+-- while c ~= syllableend.next do
+-- set_attribute(c,sylnr,syl_nr)
+-- c = c.next
+-- end
+-- end
+-- if syllableend and syllablestart ~= syllableend then
+-- head, current = dev2_reorder(head,syllablestart,syllableend,font,attr)
+-- end
+--
+-- if not syllableend and not has_attribute(current, state) and current.id == glyph and current.subtype<256 and current.font == font then -- Syntax error
+-- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then
+-- local n = node.copy(current)
+-- if pre_mark[current.char] then
+-- n.char = dotted_circle
+-- else
+-- current.char = dotted_circle
+-- end
+-- head, current = node.insert_after(head, current, n)
+-- end
+-- end
+--
+-- start = false
+-- current = current.next
+-- end
+--
+-- return head, done
+-- end
+--
+-- function otf.handlers.dev2_reorder_matras(start,kind,lookupname,replacement)
+-- return dev2_reorder_matras(start,kind,lookupname,replacement)
+-- end
+--
+-- function otf.handlers.dev2_reorder_reph(start,kind,lookupname,replacement)
+-- return dev2_reorder_reph(start,kind,lookupname,replacement)
+-- end
+--
+-- function otf.handlers.dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
+-- return dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
+-- end
+--
+-- function otf.handlers.remove_joiners(start,kind,lookupname,replacement)
+-- return remove_joiners(start,kind,lookupname,replacement)
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-odv.lua b/Master/texmf-dist/tex/context/base/mkiv/font-odv.lua
new file mode 100644
index 00000000000..6b9a5a9e42a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-odv.lua
@@ -0,0 +1,2380 @@
+if not modules then modules = { } end modules ['font-odv'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE",
+ copyright = "TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- One day I'll speed this up ... char swapping and properties.
+
+-- A few remarks:
+--
+-- This code is a partial rewrite of the code that deals with devanagari. The data and logic
+-- is by Kai Eigner and based based on Microsoft's OpenType specifications for specific
+-- scripts, but with a few improvements. More information can be found at:
+--
+-- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx
+-- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx
+--
+-- Rajeesh Nambiar provided patches for the malayalam variant. Thansk to feedback from
+-- the mailing list some aspects could be improved.
+--
+-- As I touched nearly all code, reshuffled it, optimized a lot, etc. etc. (imagine how
+-- much can get messed up in over a week work) it could be that I introduced bugs. There
+-- is more to gain (esp in the functions applied to a range) but I'll do that when
+-- everything works as expected. Kai's original code is kept in font-odk.lua as a reference
+-- so blame me (HH) for bugs.
+--
+-- Interesting is that Kai managed to write this on top of the existing otf handler. Only a
+-- few extensions were needed, like a few more analyzing states and dealing with changed
+-- head nodes in the core scanner as that only happens here. There's a lot going on here
+-- and it's only because I touched nearly all code that I got a bit of a picture of what
+-- happens. For in-depth knowledge one needs to consult Kai.
+--
+-- The rewrite mostly deals with efficiency, both in terms of speed and code. We also made
+-- sure that it suits generic use as well as use in ConTeXt. I removed some buglets but can
+-- as well have messed up the logic by doing this. For this we keep the original around
+-- as that serves as reference. Due to the lots of reshuffling glyphs quite some leaks
+-- occur(red) but once I'm satisfied with the rewrite I'll weed them. I also integrated
+-- initialization etc into the regular mechanisms.
+--
+-- In the meantime, we're down from 25.5-3.5=22 seconds to 17.7-3.5=14.2 seconds for a 100
+-- page sample (mid 2012) with both variants so it's worth the effort. Some more speedup is
+-- to be expected. Due to the method chosen it will never be real fast. If I ever become a
+-- power user I'll have a go at some further speed up. I will rename some functions (and
+-- features) once we don't need to check the original code. We now use a special subset
+-- sequence for use inside the analyzer (after all we could can store this in the dataset
+-- and save redundant analysis).
+--
+-- I might go for an array approach with respect to attributes (and reshuffling). Easier.
+--
+-- Some data will move to char-def.lua (some day).
+--
+-- Hans Hagen, PRAGMA-ADE, Hasselt NL
+--
+-- We could have c_nukta, c_halant, c_ra is we know that they are never used mixed within
+-- one script .. yes or no?
+--
+-- Matras: according to Microsoft typography specifications "up to one of each type:
+-- pre-, above-, below- or post- base", but that does not seem to be right. It could
+-- become an option.
+--
+-- The next code looks weird anyway: the "and boolean" should move inside the if
+-- or we should check differently (case vs successive).
+--
+-- local function ms_matra(c)
+-- local prebase, abovebase, belowbase, postbase = true, true, true, true
+-- local n = getnext(c)
+-- while n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font do
+-- local char = getchar(n)
+-- if not dependent_vowel[char] then
+-- break
+-- elseif pre_mark[char] and prebase then
+-- prebase = false
+-- elseif above_mark[char] and abovebase then
+-- abovebase = false
+-- elseif below_mark[char] and belowbase then
+-- belowbase = false
+-- elseif post_mark[char] and postbase then
+-- postbase = false
+-- else
+-- return c
+-- end
+-- c = getnext(c)
+-- end
+-- return c
+-- end
+
+-- todo: first test for font then for subtype
+
+local insert, imerge = table.insert, table.imerge
+local next = next
+
+local report_devanagari = logs.reporter("otf","devanagari")
+
+fonts = fonts or { }
+fonts.analyzers = fonts.analyzers or { }
+fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
+
+local otf = fonts.handlers.otf
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local handlers = otf.handlers
+local methods = fonts.analyzers.methods
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local setnext = nuts.setnext
+local getprev = nuts.getprev
+local setprev = nuts.setprev
+local getid = nuts.getid
+local getchar = nuts.getchar
+local setchar = nuts.setchar
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getprop = nuts.getprop
+local setprop = nuts.setprop
+
+local insert_node_after = nuts.insert_after
+local copy_node = nuts.copy
+local free_node = nuts.free
+local remove_node = nuts.remove
+local flush_list = nuts.flush_list
+
+local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
+
+local unsetvalue = attributes.unsetvalue
+
+local fontdata = fonts.hashes.identifiers
+
+local a_state = attributes.private('state')
+local a_syllabe = attributes.private('syllabe')
+
+local dotted_circle = 0x25CC
+
+local states = fonts.analyzers.states -- not features
+
+local s_rphf = states.rphf
+local s_half = states.half
+local s_pref = states.pref
+local s_blwf = states.blwf
+local s_pstf = states.pstf
+
+local replace_all_nbsp = nil
+
+replace_all_nbsp = function(head) -- delayed definition
+ replace_all_nbsp = typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head)
+ return head
+ end
+ return replace_all_nbsp(head)
+end
+
+local xprocesscharacters = nil
+
+if context then
+ xprocesscharacters = function(head,font)
+ xprocesscharacters = nodes.handlers.characters
+ return xprocesscharacters(head,font)
+ end
+else
+ xprocesscharacters = function(head,font)
+ xprocesscharacters = nodes.handlers.nodepass -- generic
+ return xprocesscharacters(head,font)
+ end
+end
+
+local function processcharacters(head,font)
+ return tonut(xprocesscharacters(tonode(head)))
+end
+
+-- 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
+
+-- In due time there will be entries here for scripts like Bengali, Gujarati,
+-- Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu. Feel free to provide the
+-- code points.
+
+-- 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.
+
+-- new, to be checked:
+--
+-- U+00978 : DEVANAGARI LETTER MARWARI DDA
+-- U+00980 : BENGALI ANJI
+-- U+00C00 : TELUGU SIGN COMBINING CANDRABINDU ABOVE
+-- U+00C34 : TELUGU LETTER LLLA
+-- U+00C81 : KANNADA SIGN CANDRABINDU
+-- U+00D01 : MALAYALAM SIGN CANDRABINDU
+-- U+00DE6 : SINHALA LITH DIGIT ZERO
+-- U+00DE7 : SINHALA LITH DIGIT ONE
+-- U+00DE8 : SINHALA LITH DIGIT TWO
+-- U+00DE9 : SINHALA LITH DIGIT THREE
+-- U+00DEA : SINHALA LITH DIGIT FOUR
+-- U+00DEB : SINHALA LITH DIGIT FIVE
+-- U+00DEC : SINHALA LITH DIGIT SIX
+-- U+00DED : SINHALA LITH DIGIT SEVEN
+-- U+00DEE : SINHALA LITH DIGIT EIGHT
+-- U+00DEF : SINHALA LITH DIGIT NINE
+
+local consonant = {
+ -- devanagari
+ [0x0915] = true, [0x0916] = true, [0x0917] = true, [0x0918] = true,
+ [0x0919] = true, [0x091A] = true, [0x091B] = true, [0x091C] = true,
+ [0x091D] = true, [0x091E] = true, [0x091F] = true, [0x0920] = true,
+ [0x0921] = true, [0x0922] = true, [0x0923] = true, [0x0924] = true,
+ [0x0925] = true, [0x0926] = true, [0x0927] = true, [0x0928] = true,
+ [0x0929] = true, [0x092A] = true, [0x092B] = true, [0x092C] = true,
+ [0x092D] = true, [0x092E] = true, [0x092F] = true, [0x0930] = true,
+ [0x0931] = true, [0x0932] = true, [0x0933] = true, [0x0934] = true,
+ [0x0935] = true, [0x0936] = true, [0x0937] = true, [0x0938] = true,
+ [0x0939] = true, [0x0958] = true, [0x0959] = true, [0x095A] = true,
+ [0x095B] = true, [0x095C] = true, [0x095D] = true, [0x095E] = true,
+ [0x095F] = true, [0x0979] = true, [0x097A] = true,
+ -- kannada
+ [0x0C95] = true, [0x0C96] = true, [0x0C97] = true, [0x0C98] = true,
+ [0x0C99] = true, [0x0C9A] = true, [0x0C9B] = true, [0x0C9C] = true,
+ [0x0C9D] = true, [0x0C9E] = true, [0x0C9F] = true, [0x0CA0] = true,
+ [0x0CA1] = true, [0x0CA2] = true, [0x0CA3] = true, [0x0CA4] = true,
+ [0x0CA5] = true, [0x0CA6] = true, [0x0CA7] = true, [0x0CA8] = true,
+ [0x0CA9] = true, [0x0CAA] = true, [0x0CAB] = true, [0x0CAC] = true,
+ [0x0CAD] = true, [0x0CAE] = true, [0x0CAF] = true, [0x0CB0] = true,
+ [0x0CB1] = true, [0x0CB2] = true, [0x0CB3] = true, [0x0CB4] = true,
+ [0x0CB5] = true, [0x0CB6] = true, [0x0CB7] = true, [0x0CB8] = true,
+ [0x0CB9] = true,
+ [0x0CDE] = true, -- obsolete
+ -- malayalam
+ [0x0D15] = true, [0x0D16] = true, [0x0D17] = true, [0x0D18] = true,
+ [0x0D19] = true, [0x0D1A] = true, [0x0D1B] = true, [0x0D1C] = true,
+ [0x0D1D] = true, [0x0D1E] = true, [0x0D1F] = true, [0x0D20] = true,
+ [0x0D21] = true, [0x0D22] = true, [0x0D23] = true, [0x0D24] = true,
+ [0x0D25] = true, [0x0D26] = true, [0x0D27] = true, [0x0D28] = true,
+ [0x0D29] = true, [0x0D2A] = true, [0x0D2B] = true, [0x0D2C] = true,
+ [0x0D2D] = true, [0x0D2E] = true, [0x0D2F] = true, [0x0D30] = true,
+ [0x0D31] = true, [0x0D32] = true, [0x0D33] = true, [0x0D34] = true,
+ [0x0D35] = true, [0x0D36] = true, [0x0D37] = true, [0x0D38] = true,
+ [0x0D39] = true, [0x0D3A] = true,
+}
+
+local independent_vowel = {
+ -- devanagari
+ [0x0904] = true, [0x0905] = true, [0x0906] = true, [0x0907] = true,
+ [0x0908] = true, [0x0909] = true, [0x090A] = true, [0x090B] = true,
+ [0x090C] = true, [0x090D] = true, [0x090E] = true, [0x090F] = true,
+ [0x0910] = true, [0x0911] = true, [0x0912] = true, [0x0913] = true,
+ [0x0914] = true, [0x0960] = true, [0x0961] = true, [0x0972] = true,
+ [0x0973] = true, [0x0974] = true, [0x0975] = true, [0x0976] = true,
+ [0x0977] = true,
+ -- kannada
+ [0x0C85] = true, [0x0C86] = true, [0x0C87] = true, [0x0C88] = true,
+ [0x0C89] = true, [0x0C8A] = true, [0x0C8B] = true, [0x0C8C] = true,
+ [0x0C8D] = true, [0x0C8E] = true, [0x0C8F] = true, [0x0C90] = true,
+ [0x0C91] = true, [0x0C92] = true, [0x0C93] = true, [0x0C94] = true,
+ -- malayalam
+ [0x0D05] = true, [0x0D06] = true, [0x0D07] = true, [0x0D08] = true,
+ [0x0D09] = true, [0x0D0A] = true, [0x0D0B] = true, [0x0D0C] = true,
+ [0x0D0E] = true, [0x0D0F] = true, [0x0D10] = true, [0x0D12] = true,
+ [0x0D13] = true, [0x0D14] = true,
+}
+
+local dependent_vowel = { -- matra
+ -- devanagari
+ [0x093A] = true, [0x093B] = true, [0x093E] = true, [0x093F] = true,
+ [0x0940] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
+ [0x0944] = true, [0x0945] = true, [0x0946] = true, [0x0947] = true,
+ [0x0948] = true, [0x0949] = true, [0x094A] = true, [0x094B] = true,
+ [0x094C] = true, [0x094E] = true, [0x094F] = true, [0x0955] = true,
+ [0x0956] = true, [0x0957] = true, [0x0962] = true, [0x0963] = true,
+ -- kannada
+ [0x0CBE] = true, [0x0CBF] = true, [0x0CC0] = true, [0x0CC1] = true,
+ [0x0CC2] = true, [0x0CC3] = true, [0x0CC4] = true, [0x0CC5] = true,
+ [0x0CC6] = true, [0x0CC7] = true, [0x0CC8] = true, [0x0CC9] = true,
+ [0x0CCA] = true, [0x0CCB] = true, [0x0CCC] = true,
+ -- malayalam
+ [0x0D3E] = true, [0x0D3F] = true, [0x0D40] = true, [0x0D41] = true,
+ [0x0D42] = true, [0x0D43] = true, [0x0D44] = true, [0x0D46] = true,
+ [0x0D47] = true, [0x0D48] = true, [0x0D4A] = true, [0x0D4B] = true,
+ [0x0D4C] = true, [0x0D57] = true,
+}
+
+local vowel_modifier = {
+ -- devanagari
+ [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x0903] = true,
+ -- A8E0 - A8F1 are cantillation marks for the Samaveda and may not belong here.
+ [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
+ [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
+ [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
+ [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
+ [0xA8F0] = true, [0xA8F1] = true,
+ -- malayalam
+ [0x0D02] = true, [0x0D03] = true,
+}
+
+local stress_tone_mark = {
+ [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true,
+ -- kannada
+ [0x0CCD] = true,
+ -- malayalam
+ [0x0D4D] = true,
+}
+
+local nukta = {
+ -- devanagari
+ [0x093C] = true,
+ -- kannada:
+ [0x0CBC] = true,
+}
+
+local halant = {
+ -- devanagari
+ [0x094D] = true,
+ -- kannada
+ [0x0CCD] = true,
+ -- malayalam
+ [0x0D4D] = true,
+}
+
+local ra = {
+ -- devanagari
+ [0x0930] = true,
+ -- kannada
+ [0x0CB0] = true,
+ -- malayalam
+ [0x0D30] = true,
+}
+
+local c_anudatta = 0x0952 -- used to be tables
+local c_nbsp = 0x00A0 -- used to be tables
+local c_zwnj = 0x200C -- used to be tables
+local c_zwj = 0x200D -- used to be tables
+
+local zw_char = { -- could also be inlined
+ [0x200C] = true,
+ [0x200D] = true,
+}
+
+-- 0C82 anusvara
+-- 0C83 visarga
+-- 0CBD avagraha
+-- 0CD5 length mark
+-- 0CD6 ai length mark
+-- 0CE0 letter ll
+-- 0CE1 letter rr
+-- 0CE2 vowel sign l
+-- 0CE2 vowel sign ll
+-- 0CF1 sign
+-- 0CF2 sign
+-- OCE6 - OCEF digits
+
+local pre_mark = {
+ [0x093F] = true, [0x094E] = true,
+ -- malayalam
+ [0x0D46] = true, [0x0D47] = true, [0x0D48] = true,
+}
+
+local above_mark = {
+ [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x093A] = true,
+ [0x0945] = true, [0x0946] = true, [0x0947] = true, [0x0948] = true,
+ [0x0951] = true, [0x0953] = true, [0x0954] = true, [0x0955] = true,
+ [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
+ [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
+ [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
+ [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
+ [0xA8F0] = true, [0xA8F1] = true,
+ -- malayalam
+ [0x0D4E] = true,
+}
+
+local below_mark = {
+ [0x093C] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
+ [0x0944] = true, [0x094D] = true, [0x0952] = true, [0x0956] = true,
+ [0x0957] = true, [0x0962] = true, [0x0963] = true,
+}
+
+local post_mark = {
+ [0x0903] = true, [0x093B] = true, [0x093E] = true, [0x0940] = true,
+ [0x0949] = true, [0x094A] = true, [0x094B] = true, [0x094C] = true,
+ [0x094F] = true,
+}
+
+local twopart_mark = {
+ -- malayalam
+ [0x0D4A] = { 0x0D46, 0x0D3E, }, -- ൊ
+ [0x0D4B] = { 0x0D47, 0x0D3E, }, -- ോ
+ [0x0D4C] = { 0x0D46, 0x0D57, }, -- ൌ
+}
+
+local mark_four = { } -- As we access these frequently an extra hash is used.
+
+for k, v in next, pre_mark do mark_four[k] = pre_mark end
+for k, v in next, above_mark do mark_four[k] = above_mark end
+for k, v in next, below_mark do mark_four[k] = below_mark end
+for k, v in next, post_mark do mark_four[k] = post_mark end
+
+local mark_above_below_post = { }
+
+for k, v in next, above_mark do mark_above_below_post[k] = above_mark end
+for k, v in next, below_mark do mark_above_below_post[k] = below_mark end
+for k, v in next, post_mark do mark_above_below_post[k] = post_mark end
+
+-- Again, this table can be extended for other scripts than devanagari. Actually,
+-- for ConTeXt this kind of data is kept elsewhere so eventually we might move
+-- tables to someplace else.
+
+local reorder_class = {
+ -- devanagari
+ [0x0930] = "before postscript",
+ [0x093F] = "before half",
+ [0x0940] = "after subscript",
+ [0x0941] = "after subscript",
+ [0x0942] = "after subscript",
+ [0x0943] = "after subscript",
+ [0x0944] = "after subscript",
+ [0x0945] = "after subscript",
+ [0x0946] = "after subscript",
+ [0x0947] = "after subscript",
+ [0x0948] = "after subscript",
+ [0x0949] = "after subscript",
+ [0x094A] = "after subscript",
+ [0x094B] = "after subscript",
+ [0x094C] = "after subscript",
+ [0x0962] = "after subscript",
+ [0x0963] = "after subscript",
+ [0x093E] = "after subscript",
+ -- kannada:
+ [0x0CB0] = "after postscript", -- todo in code below
+ [0x0CBF] = "before subscript", -- todo in code below
+ [0x0CC6] = "before subscript", -- todo in code below
+ [0x0CCC] = "before subscript", -- todo in code below
+ [0x0CBE] = "before subscript", -- todo in code below
+ [0x0CE2] = "before subscript", -- todo in code below
+ [0x0CE3] = "before subscript", -- todo in code below
+ [0x0CC1] = "before subscript", -- todo in code below
+ [0x0CC2] = "before subscript", -- todo in code below
+ [0x0CC3] = "after subscript",
+ [0x0CC4] = "after subscript",
+ [0x0CD5] = "after subscript",
+ [0x0CD6] = "after subscript",
+ -- malayalam
+}
+
+-- We use some pseudo features as we need to manipulate the nodelist based
+-- on information in the font as well as already applied features.
+
+local dflt_true = {
+ dflt = true
+}
+
+local dev2_defaults = {
+ dev2 = dflt_true,
+}
+
+local deva_defaults = {
+ dev2 = dflt_true,
+ deva = dflt_true,
+}
+
+local false_flags = { false, false, false, false }
+
+local both_joiners_true = {
+ [0x200C] = true,
+ [0x200D] = true,
+}
+
+local sequence_reorder_matras = {
+ chain = 0,
+ features = { dv01 = dev2_defaults },
+ flags = false_flags,
+ name = "dv01_reorder_matras",
+ order = { "dv01" },
+ subtables = { "dv01_reorder_matras" },
+ type = "devanagari_reorder_matras",
+}
+
+local sequence_reorder_reph = {
+ chain = 0,
+ features = { dv02 = dev2_defaults },
+ flags = false_flags,
+ name = "dv02_reorder_reph",
+ order = { "dv02" },
+ subtables = { "dv02_reorder_reph" },
+ type = "devanagari_reorder_reph",
+}
+
+local sequence_reorder_pre_base_reordering_consonants = {
+ chain = 0,
+ features = { dv03 = dev2_defaults },
+ flags = false_flags,
+ name = "dv03_reorder_pre_base_reordering_consonants",
+ order = { "dv03" },
+ subtables = { "dv03_reorder_pre_base_reordering_consonants" },
+ type = "devanagari_reorder_pre_base_reordering_consonants",
+}
+
+local sequence_remove_joiners = {
+ chain = 0,
+ features = { dv04 = deva_defaults },
+ flags = false_flags,
+ name = "dv04_remove_joiners",
+ order = { "dv04" },
+ subtables = { "dv04_remove_joiners" },
+ type = "devanagari_remove_joiners",
+}
+
+-- Looping over feature twice as efficient as looping over basic forms (some
+-- 350 checks instead of 750 for one font). This is something to keep an eye on
+-- as it might depends on the font. Not that it's a bottleneck.
+
+local basic_shaping_forms = {
+ nukt = true,
+ akhn = true,
+ rphf = true,
+ pref = true,
+ rkrf = true,
+ blwf = true,
+ half = true,
+ pstf = true,
+ vatu = true,
+ cjct = true,
+}
+
+local function initializedevanagi(tfmdata)
+ local script, language = otf.scriptandlanguage(tfmdata,attr) -- todo: take fast variant
+ if script == "deva" or script == "dev2" or script =="mlym" or script == "mlm2" then
+ local resources = tfmdata.resources
+ local lookuphash = resources.lookuphash
+ if not lookuphash["dv01"] then
+ report_devanagari("adding devanagari features to font")
+ --
+ local features = resources.features
+ local gsubfeatures = features.gsub
+ local sequences = resources.sequences
+ local sharedfeatures = tfmdata.shared.features
+ --
+ local lastmatch = 0
+ for s=1,#sequences do -- classify chars
+ local features = sequences[s].features
+ if features then
+ for k, v in next, features do
+ if basic_shaping_forms[k] then
+ lastmatch = s
+ end
+ end
+ end
+ end
+ local insertindex = lastmatch + 1
+ --
+ lookuphash["dv04_remove_joiners"] = both_joiners_true
+ --
+ gsubfeatures["dv01"] = dev2_defaults -- reorder matras
+ gsubfeatures["dv02"] = dev2_defaults -- reorder reph
+ gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants
+ gsubfeatures["dv04"] = deva_defaults -- remove joiners
+ --
+ insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
+ insert(sequences,insertindex,sequence_reorder_reph)
+ insert(sequences,insertindex,sequence_reorder_matras)
+ insert(sequences,insertindex,sequence_remove_joiners)
+ --
+ if script == "deva" then
+ sharedfeatures["dv04"] = true -- dv04_remove_joiners
+ elseif script == "dev2" then
+ sharedfeatures["dv01"] = true -- dv01_reorder_matras
+ sharedfeatures["dv02"] = true -- dv02_reorder_reph
+ sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
+ sharedfeatures["dv04"] = true -- dv04_remove_joiners
+ elseif script == "mlym" then
+ sharedfeatures["pstf"] = true
+ elseif script == "mlm2" then
+ sharedfeatures["pstf"] = true
+ sharedfeatures["pref"] = true
+ sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
+ gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants
+ insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "devanagari",
+ description = "inject additional features",
+ default = true,
+ initializers = {
+ node = initializedevanagi,
+ },
+}
+
+-- hm, this is applied to one character:
+
+local function deva_initialize(font,attr)
+
+ local tfmdata = fontdata[font]
+ local resources = tfmdata.resources
+ local lookuphash = resources.lookuphash
+
+ local datasets = otf.dataset(tfmdata,font,attr)
+ local devanagaridata = datasets.devanagari
+
+ if devanagaridata then -- maybe also check for e.g. reph
+
+ return lookuphash, devanagaridata.reph, devanagaridata.vattu, devanagaridata.blwfcache
+
+ else
+
+ devanagaridata = { }
+ datasets.devanagari = devanagaridata
+
+ local reph = false
+ local vattu = false
+ local blwfcache = { }
+
+ local sequences = resources.sequences
+
+ for s=1,#sequences do -- triggers creation of dataset
+ -- local sequence = sequences[s]
+ local dataset = datasets[s]
+ if dataset and dataset[1] then -- value
+ local kind = dataset[4]
+ if kind == "rphf" then
+ -- deva
+ reph = true
+ elseif kind == "blwf" then
+ -- deva
+ vattu = true
+ -- dev2
+ local subtables = dataset[3].subtables
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ for k, v in next, lookupcache do
+ blwfcache[k] = blwfcache[k] or v
+ end
+ end
+ end
+ end
+ end
+ end
+
+ devanagaridata.reph = reph
+ devanagaridata.vattu = vattu
+ devanagaridata.blwfcache = blwfcache
+
+ return lookuphash, reph, vattu, blwfcache
+
+ end
+
+end
+
+local function deva_reorder(head,start,stop,font,attr,nbspaces)
+
+ local lookuphash, reph, vattu, blwfcache = deva_initialize(font,attr) -- could be inlines but ugly
+
+ local current = start
+ local n = getnext(start)
+ local base = nil
+ local firstcons = nil
+ local lastcons = nil
+ local basefound = false
+
+ if ra[getchar(start)] and halant[getchar(n)] and reph then
+ -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph
+ -- from candidates for base consonants
+ if n == stop then
+ return head, stop, nbspaces
+ end
+ if getchar(getnext(n)) == c_zwj then
+ current = start
+ else
+ current = getnext(n)
+ setprop(start,a_state,s_rphf)
+ end
+ end
+
+ if getchar(current) == c_nbsp then
+ -- Stand Alone cluster
+ if current == stop then
+ stop = getprev(stop)
+ head = remove_node(head,current)
+ free_node(current)
+ return head, stop, nbspaces
+ else
+ nbspaces = nbspaces + 1
+ base = current
+ firstcons = current
+ lastcons = current
+ current = getnext(current)
+ if current ~= stop then
+ if nukta[getchar(current)] then
+ current = getnext(current)
+ end
+ if getchar(current) == c_zwj then
+ if current ~= stop then
+ local next = getnext(current)
+ if next ~= stop and halant[getchar(next)] then
+ current = next
+ next = getnext(current)
+ local tmp = next and getnext(next) or nil -- needs checking
+ local changestop = next == stop
+ local tempcurrent = copy_node(next)
+ copyinjection(tempcurrent,next)
+ local nextcurrent = copy_node(current)
+ copyinjection(nextcurrent,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set
+ setnext(tempcurrent,nextcurrent)
+ setprev(nextcurrent,tempcurrent)
+ setprop(tempcurrent,a_state,s_blwf)
+ tempcurrent = processcharacters(tempcurrent,font)
+ 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)
+ else
+ setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
+ local freenode = getnext(current)
+ setnext(current,tmp)
+ if tmp then
+ setprev(tmp,current)
+ end
+ free_node(freenode)
+ flush_list(tempcurrent)
+ if changestop then
+ stop = current
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ while not basefound do
+ -- find base consonant
+ if consonant[getchar(current)] then
+ setprop(current,a_state,s_half)
+ if not firstcons then
+ firstcons = current
+ end
+ lastcons = current
+ if not base then
+ base = current
+ elseif blwfcache[getchar(current)] then
+ -- consonant has below-base (or post-base) form
+ setprop(current,a_state,s_blwf)
+ else
+ base = current
+ end
+ end
+ basefound = current == stop
+ current = getnext(current)
+ end
+
+ if base ~= lastcons then
+ -- if base consonant is not last one then move halant from base consonant to last one
+ local np = base
+ local n = getnext(base)
+ if nukta[getchar(n)] then
+ np = n
+ n = getnext(n)
+ end
+ if halant[getchar(n)] then
+ if lastcons ~= stop then
+ local ln = getnext(lastcons)
+ if nukta[getchar(ln)] then
+ lastcons = ln
+ end
+ end
+ -- local np = getprev(n)
+ local nn = getnext(n)
+ local ln = getnext(lastcons) -- what if lastcons is nn ?
+ setnext(np,nn)
+ setprev(nn,np)
+ setnext(lastcons,n)
+ if ln then
+ setprev(ln,n)
+ end
+ setnext(n,ln)
+ setprev(n,lastcons)
+ if lastcons == stop then
+ stop = n
+ end
+ end
+ end
+
+ n = getnext(start)
+ if n ~= stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
+ -- if syllable starts with Ra + H then move this combination so that it follows either:
+ -- the post-base 'matra' (if any) or the base consonant
+ local matra = base
+ if base ~= stop then
+ local next = getnext(base)
+ if dependent_vowel[getchar(next)] then
+ matra = next
+ end
+ end
+ -- [sp][start][n][nn] [matra|base][?]
+ -- [matra|base][start] [n][?] [sp][nn]
+ local sp = getprev(start)
+ local nn = getnext(n)
+ local mn = getnext(matra)
+ if sp then
+ setnext(sp,nn)
+ end
+ setprev(nn,sp)
+ setnext(matra,start)
+ setprev(start,matra)
+ setnext(n,mn)
+ if mn then
+ setprev(mn,n)
+ end
+ if head == start then
+ head = nn
+ end
+ start = nn
+ if matra == stop then
+ stop = n
+ end
+ end
+
+ local current = start
+ while current ~= stop do
+ local next = getnext(current)
+ if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then
+ setprop(current,a_state,unsetvalue)
+ end
+ current = next
+ end
+
+ if base ~= stop and getprop(base,a_state) then
+ local next = getnext(base)
+ if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then
+ setprop(base,a_state,unsetvalue)
+ end
+ end
+
+ -- ToDo: split two- or three-part matras into their parts. Then, move the left 'matra' part to the beginning of the syllable.
+ -- Not necessary for Devanagari. However it is necessay for other scripts, such as Tamil (e.g. TAMIL VOWEL SIGN O - 0BCA)
+
+ -- classify consonants and 'matra' parts as pre-base, above-base (Reph), below-base or post-base, and group elements of the syllable (consonants and 'matras') according to this classification
+
+ local current, allreordered, moved = start, false, { [base] = true }
+ local a, b, p, bn = base, base, base, getnext(base)
+ if base ~= stop and nukta[getchar(bn)] then
+ a, b, p = bn, bn, bn
+ end
+ while not allreordered do
+ -- current is always consonant
+ local c = current
+ local n = getnext(current)
+ local l = nil -- used ?
+ if c ~= stop then
+ if nukta[getchar(n)] then
+ c = n
+ n = getnext(n)
+ end
+ if c ~= stop then
+ if halant[getchar(n)] then
+ c = n
+ n = getnext(n)
+ end
+ while c ~= stop and dependent_vowel[getchar(n)] do
+ c = n
+ n = getnext(n)
+ end
+ if c ~= stop then
+ if vowel_modifier[getchar(n)] then
+ c = n
+ n = getnext(n)
+ end
+ if c ~= stop and stress_tone_mark[getchar(n)] then
+ c = n
+ n = getnext(n)
+ end
+ end
+ end
+ end
+ local bp = getprev(firstcons)
+ local cn = getnext(current)
+ local last = getnext(c)
+ while cn ~= last do
+ -- move pre-base matras...
+ if pre_mark[getchar(cn)] then
+ if bp then
+ setnext(bp,cn)
+ end
+ local next = getnext(cn)
+ local prev = getprev(cn)
+ if next then
+ setprev(next,prev)
+ end
+ setnext(prev,next)
+ if cn == stop then
+ stop = prev
+ end
+ setprev(cn,bp)
+ setnext(cn,firstcons)
+ setprev(firstcons,cn)
+ if firstcons == start then
+ if head == start then
+ head = cn
+ end
+ start = cn
+ end
+ break
+ end
+ cn = getnext(cn)
+ end
+ allreordered = c == stop
+ current = getnext(c)
+ end
+
+ if reph or vattu then
+ local current, cns = start, nil
+ while current ~= stop do
+ local c = current
+ local n = getnext(current)
+ if ra[getchar(current)] and halant[getchar(n)] then
+ c = n
+ n = getnext(n)
+ local b, bn = base, base
+ while bn ~= stop do
+ local next = getnext(bn)
+ if dependent_vowel[getchar(next)] then
+ b = next
+ end
+ bn = next
+ end
+ if getprop(current,a_state) == s_rphf then
+ -- position Reph (Ra + H) after post-base 'matra' (if any) since these
+ -- become marks on the 'matra', not on the base glyph
+ if b ~= current then
+ if current == start then
+ if head == start then
+ head = n
+ end
+ start = n
+ end
+ if b == stop then
+ stop = c
+ end
+ local prev = getprev(current)
+ if prev then
+ setnext(prev,n)
+ end
+ if n then
+ setprev(n,prev)
+ end
+ local next = getnext(b)
+ setnext(c,next)
+ if next then
+ setprev(next,c)
+ end
+ setnext(c,next)
+ setnext(b,current)
+ setprev(current,b)
+ end
+ elseif cns and getnext(cns) ~= current then -- todo: optimize next
+ -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants)
+ local cp, cnsn = getprev(current), getnext(cns)
+ if cp then
+ setnext(cp,n)
+ end
+ if n then
+ setprev(n,cp)
+ end
+ setnext(cns,current)
+ setprev(current,cns)
+ setnext(c,cnsn)
+ if cnsn then
+ setprev(cnsn,c)
+ end
+ if c == stop then
+ stop = cp
+ break
+ end
+ current = getprev(n)
+ end
+ else
+ local char = getchar(current)
+ if consonant[char] then
+ cns = current
+ local next = getnext(cns)
+ if halant[getchar(next)] then
+ cns = next
+ end
+ elseif char == c_nbsp then
+ nbspaces = nbspaces + 1
+ cns = current
+ local next = getnext(cns)
+ if halant[getchar(next)] then
+ cns = next
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ end
+
+ if getchar(base) == c_nbsp then
+ nbspaces = nbspaces - 1
+ head = remove_node(head,base)
+ free_node(base)
+ end
+
+ return head, stop, nbspaces
+end
+
+-- If a pre-base matra character had been reordered before applying basic features,
+-- the glyph can be moved closer to the main consonant based on whether half-forms had been formed.
+-- Actual position for the matra is defined as “after last standalone halant glyph,
+-- after initial matra position and before the main consonant”.
+-- If ZWJ or ZWNJ follow this halant, position is moved after it.
+
+-- so we break out ... this is only done for the first 'word' (if we feed words we can as
+-- well test for non glyph.
+
+function handlers.devanagari_reorder_matras(head,start,kind,lookupname,replacement) -- no leak
+ local current = start -- we could cache attributes here
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ -- can be fast loop
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and getprop(current,a_syllabe) == startattr do
+ local next = getnext(current)
+ if halant[getchar(current)] and not getprop(current,a_state) then
+ if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getprop(next,a_syllabe) == startattr and zw_char[getchar(next)] then
+ current = next
+ end
+ local startnext = getnext(start)
+ head = remove_node(head,start)
+ local next = getnext(current)
+ if next then
+ setprev(next,start)
+ end
+ setnext(start,next)
+ setnext(current,start)
+ setprev(start,current)
+ start = startnext
+ break
+ end
+ current = next
+ end
+ return head, start, true
+end
+
+-- todo: way more caching of attributes and font
+
+-- Reph’s original position is always at the beginning of the syllable, (i.e. it is not reordered at the character reordering stage).
+-- However, it will be reordered according to the basic-forms shaping results.
+-- Possible positions for reph, depending on the script, are; after main, before post-base consonant forms,
+-- and after post-base consonant forms.
+
+-- 1 If reph should be positioned after post-base consonant forms, proceed to step 5.
+-- 2 If the reph repositioning class is not after post-base: target position is after the first explicit halant glyph between
+-- the first post-reph consonant and last main consonant. If ZWJ or ZWNJ are following this halant, position is moved after it.
+-- If such position is found, this is the target position. Otherwise, proceed to the next step.
+-- Note: in old-implementation fonts, where classifications were fixed in shaping engine,
+-- there was no case where reph position will be found on this step.
+-- 3 If reph should be repositioned after the main consonant: from the first consonant not ligated with main,
+-- or find the first consonant that is not a potential pre-base reordering Ra.
+-- 4 If reph should be positioned before post-base consonant, find first post-base classified consonant not ligated with main.
+-- If no consonant is found, the target position should be before the first matra, syllable modifier sign or vedic sign.
+-- 5 If no consonant is found in steps 3 or 4, move reph to a position immediately before the first post-base matra,
+-- syllable modifier sign or vedic sign that has a reordering class after the intended reph position.
+-- For example, if the reordering position for reph is post-main, it will skip above-base matras that also have a post-main position.
+-- 6 Otherwise, reorder reph to the end of the syllable.
+
+-- hm, this only looks at the start of a nodelist ... is this supposed to be line based?
+
+function handlers.devanagari_reorder_reph(head,start,kind,lookupname,replacement)
+ -- since in Devanagari reph has reordering position 'before postscript' dev2 only follows step 2, 4, and 6,
+ -- the other steps are still ToDo (required for scripts other than dev2)
+ local current = getnext(start)
+ local startnext = nil
+ local startprev = nil
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 2
+ if halant[getchar(current)] and not getprop(current,a_state) then
+ local next = getnext(current)
+ if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getprop(next,a_syllabe) == startattr and zw_char[getchar(next)] then
+ current = next
+ end
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local next = getnext(current)
+ if next then
+ setprev(next,start)
+ end
+ setnext(start,next)
+ setnext(current,start)
+ setprev(start,current)
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ break
+ end
+ current = getnext(current)
+ end
+ if not startnext then
+ current = getnext(start)
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 4
+ if getprop(current,a_state) == s_pstf then --post-base
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local prev = getprev(current)
+ setprev(start,prev)
+ setnext(prev,start)
+ setnext(start,current)
+ setprev(current,start)
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ break
+ end
+ current = getnext(current)
+ end
+ end
+ -- ToDo: determine position for reph with reordering position other than 'before postscript'
+ -- (required for scripts other than dev2)
+ -- leaks
+ if not startnext then
+ current = getnext(start)
+ local c = nil
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 5
+ if not c then
+ local char = getchar(current)
+ -- todo: combine in one
+ if mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then
+ c = current
+ end
+ end
+ current = getnext(current)
+ end
+ -- here we can loose the old start node: maybe best split cases
+ if c then
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local prev = getprev(c)
+ setprev(start,prev)
+ setnext(prev,start)
+ setnext(start,c)
+ setprev(c,start)
+ -- end
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ end
+ end
+ -- leaks
+ if not startnext then
+ current = start
+ local next = getnext(current)
+ while next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getprop(next,a_syllabe) == startattr do --step 6
+ current = next
+ next = getnext(current)
+ end
+ if start ~= current then
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local next = getnext(current)
+ if next then
+ setprev(next,start)
+ end
+ setnext(star,next)
+ setnext(current,start)
+ setprev(start,current)
+ start = startnext
+ end
+ end
+ --
+ return head, start, true
+end
+
+-- we can cache some checking (v)
+
+-- If a pre-base reordering consonant is found, reorder it according to the following rules:
+--
+-- 1 Only reorder a glyph produced by substitution during application of the feature.
+-- (Note that a font may shape a Ra consonant with the feature generally but block it in certain contexts.)
+-- 2 Try to find a target position the same way as for pre-base matra. If it is found, reorder pre-base consonant glyph.
+-- 3 If position is not found, reorder immediately before main consonant.
+
+-- UNTESTED: NOT CALLED IN EXAMPLE
+
+function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start,kind,lookupname,replacement)
+ local current = start
+ local startnext = nil
+ local startprev = nil
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ -- can be fast for loop + caching state
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do
+ local next = getnext(current)
+ if halant[getchar(current)] and not getprop(current,a_state) then
+ if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getprop(next,a_syllabe) == startattr then
+ local char = getchar(next)
+ if char == c_zwnj or char == c_zwj then
+ current = next
+ end
+ end
+ startnext = getnext(start)
+ removenode(start,start)
+ local next = getnext(current)
+ if next then
+ setprev(next,start)
+ end
+ setnext(start,next)
+ setnext(current,start)
+ setprev(start,current)
+ start = startnext
+ break
+ end
+ current = next
+ end
+ if not startnext then
+ current = getnext(start)
+ startattr = getprop(start,a_syllabe)
+ while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do
+ if not consonant[getchar(current)] and getprop(current,a_state) then --main
+ startnext = getnext(start)
+ removenode(start,start)
+ local prev = getprev(current)
+ setprev(start,prev)
+ setnext(prev,start)
+ setnext(start,current)
+ setprev(current,start)
+ start = startnext
+ break
+ end
+ current = getnext(current)
+ end
+ end
+ return head, start, true
+end
+
+function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
+ local stop = getnext(start)
+ local startfont = getfont(start)
+ while stop and getid(stop) == glyph_code and getsubtype(stop) < 256 and getfont(stop) == startfont do
+ local char = getchar(stop)
+ if char == c_zwnj or char == c_zwj then
+ stop = getnext(stop)
+ else
+ break
+ end
+ end
+ if stop then
+ setnext(getprev(stop),nil)
+ setprev(stop,getprev(start))
+ end
+ local prev = getprev(start)
+ if prev then
+ setnext(prev,stop)
+ end
+ if head == start then
+ head = stop
+ end
+ flush_list(start)
+ return head, stop, true
+end
+
+local valid = {
+ akhn = true, -- malayalam
+ rphf = true,
+ pref = true,
+ half = true,
+ blwf = true,
+ pstf = true,
+ pres = true, -- malayalam
+ blws = true, -- malayalam
+ psts = true, -- malayalam
+}
+
+local function dev2_initialize(font,attr)
+
+ local tfmdata = fontdata[font]
+ local resources = tfmdata.resources
+ local lookuphash = resources.lookuphash
+
+ local datasets = otf.dataset(tfmdata,font,attr)
+ local devanagaridata = datasets.devanagari
+
+ if devanagaridata then -- maybe also check for e.g. seqsubset
+
+ return lookuphash, devanagaridata.seqsubset
+
+ else
+
+ devanagaridata = { }
+ datasets.devanagari = devanagaridata
+
+ local seqsubset = { }
+ devanagaridata.seqsubset = seqsubset
+
+ local sequences = resources.sequences
+
+ for s=1,#sequences do
+ -- local sequence = sequences[s]
+ local dataset = datasets[s]
+ if dataset and dataset[1] then -- featurevalue
+ local kind = dataset[4]
+ if kind and valid[kind] then
+ -- could become a function call
+ local subtables = dataset[3].subtables
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local reph = false
+ local chain = dataset[3]
+ if chain ~= 0 then --rphf is result of of chain
+ -- rphf might be result of other handler/chainproc
+ else
+ -- rphf acts on consonant + halant
+ for k, v in next, ra do
+ local r = lookupcache[k]
+ if r then
+ local h = false
+ for k, v in next, halant do
+ local h = r[k]
+ if h then
+ reph = h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
+ end
+ end
+ end
+ seqsubset[#seqsubset+1] = { kind, lookupcache, reph }
+ end
+ end
+ end
+ end
+ end
+
+ lookuphash["dv01_reorder_matras"] = pre_mark -- move to initializer ?
+
+ return lookuphash, seqsubset
+
+ end
+
+end
+
+-- this one will be merged into the caller: it saves a call, but we will then make function
+-- of the actions
+
+local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pass over (determine stop in sweep)
+
+ local lookuphash, seqsubset = dev2_initialize(font,attr)
+
+ local pre_base_reordering_consonants = { } -- was nil ... probably went unnoticed because never assigned
+
+ local reph = false -- was nil ... probably went unnoticed because never assigned
+ local halfpos = nil
+ local basepos = nil
+ local subpos = nil
+ local postpos = nil
+ local locl = { }
+
+ for i=1,#seqsubset do
+
+ -- maybe quit if start == stop
+
+ local subset = seqsubset[i]
+ local kind = subset[1]
+ local lookupcache = subset[2]
+ if kind == "rphf" then
+ for k, v in next, ra do
+ local r = lookupcache[k]
+ if r then
+ for k, v in next, halant do
+ local h = r[k]
+ if h then
+ reph = h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
+ end
+ end
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then --above-base: rphf Consonant + Halant
+ local afternext = next ~= stop and getnext(next)
+ if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph
+ current = next
+ current = getnext(current)
+ elseif current == start then
+ setprop(current,a_state,s_rphf)
+ current = next
+ else
+ current = next
+ end
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "pref" then
+ -- why not global? pretty ineffient this way
+ -- this will move to the initializer and we will store the hash in dataset
+ -- todo: reph might also be result of chain
+ for k, v in next, halant do
+ local h = lookupcache[k]
+ if h then
+ local found = false
+ for k, v in next, h do
+ found = v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k] = found
+ break
+ end
+ end
+ if found then
+ break
+ end
+ end
+ end
+ --
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pref)
+ setprop(next,a_state,s_pref)
+ current = next
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "half" then -- half forms: half / Consonant + Halant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half
+ current = next
+ else
+ setprop(current,a_state,s_half)
+ if not halfpos then
+ halfpos = current
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "blwf" then -- below-base: blwf / Halant + Consonant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_blwf)
+ setprop(next,a_state,s_blwf)
+ current = next
+ subpos = current
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "pstf" then -- post-base: pstf / Halant + Consonant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pstf)
+ setprop(next,a_state,s_pstf)
+ current = next
+ postpos = current
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ end
+
+ -- this one changes per word
+
+ lookuphash["dv02_reorder_reph"] = { [reph] = true }
+ lookuphash["dv03_reorder_pre_base_reordering_consonants"] = pre_base_reordering_consonants
+
+ local current, base, firstcons = start, nil, nil
+
+ if getprop(start,a_state) == s_rphf then
+ -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
+ current = getnext(getnext(start))
+ end
+
+ if current ~= getnext(stop) and getchar(current) == c_nbsp then
+ -- Stand Alone cluster
+ if current == stop then
+ stop = getprev(stop)
+ head = remove_node(head,current)
+ free_node(current)
+ return head, stop, nbspaces
+ else
+ nbspaces = nbspaces + 1
+ base = current
+ current = getnext(current)
+ if current ~= stop then
+ local char = getchar(current)
+ if nukta[char] then
+ current = getnext(current)
+ char = getchar(current)
+ end
+ if char == c_zwj then
+ local next = getnext(current)
+ if current ~= stop and next ~= stop and halant[getchar(next)] then
+ current = next
+ next = getnext(current)
+ local tmp = getnext(next)
+ local changestop = next == stop
+ setnext(next,nil)
+ setprop(current,a_state,s_pref)
+ current = processcharacters(current,font)
+ setprop(current,a_state,s_blwf)
+ current = processcharacters(current,font)
+ setprop(current,a_state,s_pstf)
+ current = processcharacters(current,font)
+ 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)
+ else
+ setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node
+ if changestop then
+ stop = current
+ end
+ end
+ end
+ end
+ end
+ end
+ else -- not Stand Alone cluster
+ local last = getnext(stop)
+ while current ~= last do -- find base consonant
+ local next = getnext(current)
+ if consonant[getchar(current)] then
+ if not (current ~= stop and next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwj) then
+ if not firstcons then
+ firstcons = current
+ end
+ -- check whether consonant has below-base or post-base form or is pre-base reordering Ra
+ local a = getprop(current,a_state)
+ if not (a == s_pref or a == s_blwf or a == s_pstf) then
+ base = current
+ end
+ end
+ end
+ current = next
+ end
+ if not base then
+ base = firstcons
+ end
+ end
+
+ if not base then
+ if getprop(start,a_state) == s_rphf then
+ setprop(start,a_state,unsetvalue)
+ end
+ return head, stop, nbspaces
+ else
+ if getprop(base,a_state) then
+ setprop(base,a_state,unsetvalue)
+ end
+ basepos = base
+ end
+ if not halfpos then
+ halfpos = base
+ end
+ if not subpos then
+ subpos = base
+ end
+ if not postpos then
+ postpos = subpos or base
+ end
+
+ -- Matra characters are classified and reordered by which consonant in a conjunct they have affinity for
+
+ local moved = { }
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ local char, target, cn = locl[current] or getchar(current), nil, getnext(current)
+-- not so efficient (needed for malayalam)
+local tpm = twopart_mark[char]
+if tpm then
+ local extra = copy_node(current)
+ copyinjection(extra,current)
+ char = tpm[1]
+ setchar(current,char)
+ setchar(extra,tpm[2])
+ head = insert_node_after(head,current,extra)
+end
+--
+ if not moved[current] and dependent_vowel[char] then
+ if pre_mark[char] then -- Before first half form in the syllable
+ moved[current] = true
+ local prev = getprev(current)
+ local next = getnext(current)
+ if prev then
+ setnext(prev,next)
+ end
+ if next then
+ setprev(next,prev)
+ end
+ if current == stop then
+ stop = getprev(current)
+ end
+ if halfpos == start then
+ if head == start then
+ head = current
+ end
+ start = current
+ end
+ local prev = getprev(halfpos)
+ if prev then
+ setnext(prev,current)
+ end
+ setprev(current,prev)
+ setprev(halfpos,current)
+ setnext(current,halfpos)
+ halfpos = current
+ elseif above_mark[char] then -- After main consonant
+ target = basepos
+ if subpos == basepos then
+ subpos = current
+ end
+ if postpos == basepos then
+ postpos = current
+ end
+ basepos = current
+ elseif below_mark[char] then -- After subjoined consonants
+ target = subpos
+ if postpos == subpos then
+ postpos = current
+ end
+ subpos = current
+ elseif post_mark[char] then -- After post-form consonant
+ target = postpos
+ postpos = current
+ end
+ if mark_above_below_post[char] then
+ local prev = getprev(current)
+ if prev ~= target then
+ local next = getnext(current)
+ if prev then -- not needed, already tested with target
+ setnext(prev,next)
+ end
+ if next then
+ setprev(next,prev)
+ end
+ if current == stop then
+ stop = prev
+ end
+ local next = getnext(target)
+ if next then
+ setprev(next,current)
+ end
+ setnext(current,next)
+ setnext(target,current)
+ setprev(current,target)
+ end
+ end
+ end
+ current = cn
+ end
+
+ -- Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first.
+
+ local current, c = start, nil
+ while current ~= stop do
+ local char = getchar(current)
+ if halant[char] or stress_tone_mark[char] then
+ if not c then
+ c = current
+ end
+ else
+ c = nil
+ end
+ local next = getnext(current)
+ if c and nukta[getchar(next)] then
+ if head == c then
+ head = next
+ end
+ if stop == next then
+ stop = current
+ end
+ local prev = getprev(c)
+ if prev then
+ setnext(prev,next)
+ end
+ setprev(next,prev)
+ local nextnext = getnext(next)
+ setnext(current,nextnext)
+ local nextnextnext = getnext(nextnext)
+ if nextnextnext then
+ setprev(nextnextnext,current)
+ end
+ setprev(c,nextnext)
+ setnext(nextnext,c)
+ end
+ if stop == current then break end
+ current = getnext(current)
+ end
+
+ if getchar(base) == c_nbsp then
+ nbspaces = nbspaces - 1
+ head = remove_node(head, base)
+ free_node(base)
+ end
+
+ return head, stop, nbspaces
+end
+
+-- cleaned up and optimized ... needs checking (local, check order, fixes, extra hash, etc)
+
+local separator = { }
+
+imerge(separator,consonant)
+imerge(separator,independent_vowel)
+imerge(separator,dependent_vowel)
+imerge(separator,vowel_modifier)
+imerge(separator,stress_tone_mark)
+
+for k, v in next, nukta do separator[k] = true end
+for k, v in next, halant do separator[k] = true end
+
+local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowel
+ -- why two variants ... the comment suggests that it's the same ruleset
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ if variant == 1 then
+ local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if v and nukta[getchar(n)] then
+ n = getnext(n)
+ if n then
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ end
+ end
+ if n and v then
+ local nn = getnext(n)
+ if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then
+ local nnn = getnext(nn)
+ if nnn and getid(nnn) == glyph_code and getsubtype(nnn) < 256 and getfont(nnn) == font then
+ local nnc = getchar(nn)
+ local nnnc = getchar(nnn)
+ if nnc == c_zwj and consonant[nnnc] then
+ c = nnn
+ elseif (nnc == c_zwnj or nnc == c_zwj) and halant[nnnc] then
+ local nnnn = getnext(nnn)
+ if nnnn and getid(nnnn) == glyph_code and consonant[getchar(nnnn)] and getsubtype(nnnn) < 256 and getfont(nnnn) == font then
+ c = nnnn
+ end
+ end
+ end
+ end
+ end
+ elseif variant == 2 then
+ if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ c = n
+ end
+ n = getnext(c)
+ if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
+ local nn = getnext(n)
+ if nn then
+ local nv = getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font
+ if nv and zw_char[getchar(n)] then
+ n = nn
+ nn = getnext(nn)
+ nv = nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font
+ end
+ if nv and halant[getchar(n)] and consonant[getchar(nn)] then
+ c = nn
+ end
+ end
+ end
+ end
+ -- c = ms_matra(c)
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ local char = getchar(n)
+ if dependent_vowel[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if nukta[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if halant[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if vowel_modifier[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if stress_tone_mark[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if stress_tone_mark[char] then
+ return n
+ else
+ return c
+ end
+end
+
+local function analyze_next_chars_two(c,font)
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ c = n
+ end
+ n = c
+ while true do
+ local nn = getnext(n)
+ if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then
+ local char = getchar(nn)
+ if halant[char] then
+ n = nn
+ local nnn = getnext(nn)
+ if nnn and getid(nnn) == glyph_code and zw_char[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
+ n = nnn
+ end
+ elseif char == c_zwnj or char == c_zwj then
+ -- n = nn -- not here (?)
+ local nnn = getnext(nn)
+ if nnn and getid(nnn) == glyph_code and halant[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
+ n = nnn
+ end
+ else
+ break
+ end
+ local nn = getnext(n)
+ if nn and getid(nn) == glyph_code and consonant[getchar(nn)] and getsubtype(nn) < 256 and getfont(nn) == font then
+ n = nn
+ local nnn = getnext(nn)
+ if nnn and getid(nnn) == glyph_code and nukta[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
+ n = nnn
+ end
+ c = n
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ --
+ if not c then
+ -- This shouldn't happen I guess.
+ return
+ end
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ local char = getchar(n)
+ if char == c_anudatta then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if halant[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ if char == c_zwnj or char == c_zwj then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ else
+ -- c = ms_matra(c)
+ -- same as one
+ if dependent_vowel[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if nukta[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if halant[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ end
+ -- same as one
+ if vowel_modifier[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if stress_tone_mark[char] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ return c
+ end
+ char = getchar(n)
+ end
+ if stress_tone_mark[char] then
+ return n
+ else
+ return c
+ end
+end
+
+local function inject_syntax_error(head,current,mark)
+ local signal = copy_node(current)
+ copyinjection(signal,current)
+ if mark == pre_mark 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.
+
+function methods.deva(head,font,attr)
+ head = tonut(head)
+ local current = head
+ local start = true
+ local done = false
+ local nbspaces = 0
+ while current do
+ if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then
+ done = true
+ local syllablestart = current
+ local syllableend = nil
+ local c = current
+ local n = getnext(c)
+ if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ local n = getnext(n)
+ if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
+ c = n
+ end
+ end
+ local standalone = getchar(c) == c_nbsp
+ if standalone then
+ local prev = getprev(current)
+ if not prev then
+ -- begin of paragraph or box
+ elseif getid(prev) ~= glyph_code or getsubtype(prev) >= 256 or getfont(prev) ~= font then
+ -- different font or language so quite certainly a different word
+ elseif not separator[getchar(prev)] then
+ -- something that separates words
+ else
+ standalone = false
+ end
+ end
+ if standalone then
+ -- stand alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ local syllableend = analyze_next_chars_one(c,font,2)
+ current = getnext(syllableend)
+ if syllablestart ~= syllableend then
+ head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current = getnext(current)
+ end
+ else
+ -- we can delay the getsubtype(n) and getfont(n) and test for say halant first
+ -- as an table access is faster than two function calls (subtype and font are
+ -- pseudo fields) but the code becomes messy (unless we make it a function)
+ local char = getchar(current)
+ if consonant[char] then
+ -- syllable containing consonant
+ local prevc = true
+ while prevc do
+ prevc = false
+ local n = getnext(current)
+ if not n then
+ break
+ end
+ local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ break
+ end
+ local c = getchar(n)
+ if nukta[c] then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ break
+ end
+ c = getchar(n)
+ end
+ if halant[c] then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ break
+ end
+ c = getchar(n)
+ if c == c_zwnj or c == c_zwj then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
+ if not v then
+ break
+ end
+ c = getchar(n)
+ end
+ if consonant[c] then
+ prevc = true
+ current = n
+ end
+ end
+ end
+ local n = getnext(current)
+ if n and getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ -- nukta (not specified in Microsft Devanagari OpenType specification)
+ current = n
+ n = getnext(current)
+ end
+ syllableend = current
+ current = n
+ if current then
+ local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
+ if v then
+ if halant[getchar(current)] then
+ -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H
+ local n = getnext(current)
+ if n and getid(n) == glyph_code and zw_char[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ -- code collapsed, probably needs checking with intention
+ syllableend = n
+ current = getnext(n)
+ else
+ syllableend = current
+ current = n
+ end
+ else
+ -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM]
+ local c = getchar(current)
+ if dependent_vowel[c] then
+ syllableend = current
+ current = getnext(current)
+ v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
+ if v then
+ c = getchar(current)
+ end
+ end
+ if v and vowel_modifier[c] then
+ syllableend = current
+ current = getnext(current)
+ v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
+ if v then
+ c = getchar(current)
+ end
+ end
+ if v and stress_tone_mark[c] then
+ syllableend = current
+ current = getnext(current)
+ end
+ end
+ end
+ end
+ if syllablestart ~= syllableend then
+ head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current = getnext(current)
+ end
+ elseif independent_vowel[char] then
+ -- syllable without consonants: VO + [VM] + [SM]
+ syllableend = current
+ current = getnext(current)
+ if current then
+ local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
+ if v then
+ local c = getchar(current)
+ if vowel_modifier[c] then
+ syllableend = current
+ current = getnext(current)
+ v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
+ if v then
+ c = getchar(current)
+ end
+ end
+ if v and stress_tone_mark[c] then
+ syllableend = current
+ current = getnext(current)
+ end
+ end
+ end
+ else
+ local mark = mark_four[char]
+ if mark then
+ head, current = inject_syntax_error(head,current,mark)
+ end
+ current = getnext(current)
+ end
+ end
+ else
+ current = getnext(current)
+ end
+ start = false
+ end
+
+ if nbspaces > 0 then
+ head = replace_all_nbsp(head)
+ end
+
+ head = tonode(head)
+
+ 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)
+
+-- handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+
+function methods.dev2(head,font,attr)
+ head = tonut(head)
+ local current = head
+ local start = true
+ local done = false
+ local syllabe = 0
+ local nbspaces = 0
+ while current do
+ local syllablestart, syllableend = nil, nil
+ if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then
+ done = true
+ syllablestart = current
+ local c = current
+ local n = getnext(current)
+ if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
+ local n = getnext(n)
+ if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
+ c = n
+ end
+ end
+ local char = getchar(c)
+ if independent_vowel[char] then
+ -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ current = analyze_next_chars_one(c,font,1)
+ syllableend = current
+ else
+ local standalone = char == c_nbsp
+ if standalone then
+ nbspaces = nbspaces + 1
+ local p = getprev(current)
+ if not p then
+ -- begin of paragraph or box
+ elseif getid(p) ~= glyph_code or getsubtype(p) >= 256 or getfont(p) ~= font then
+ -- different font or language so quite certainly a different word
+ elseif not separator[getchar(p)] then
+ -- something that separates words
+ else
+ standalone = false
+ end
+ end
+ if standalone then
+ -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ current = analyze_next_chars_one(c,font,2)
+ syllableend = current
+ elseif consonant[getchar(current)] then
+ -- WHY current INSTEAD OF c ?
+
+ -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)]
+ current = analyze_next_chars_two(current,font) -- not c !
+ syllableend = current
+ end
+ end
+ end
+ if syllableend then
+ syllabe = syllabe + 1
+ local c = syllablestart
+ local n = getnext(syllableend)
+ while c ~= n do
+ setprop(c,a_syllabe,syllabe)
+ c = getnext(c)
+ end
+ end
+ if syllableend and syllablestart ~= syllableend then
+ head, current, nbspaces = dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ end
+ if not syllableend and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and not getprop(current,a_state) then
+ local mark = mark_four[getchar(current)]
+ if mark then
+ head, current = inject_syntax_error(head,current,mark)
+ end
+ end
+ start = false
+ current = getnext(current)
+ end
+
+ if nbspaces > 0 then
+ head = replace_all_nbsp(head)
+ end
+
+ head = tonode(head)
+
+ return head, done
+end
+
+methods.mlym = methods.deva
+methods.mlm2 = methods.dev2
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-off.lua b/Master/texmf-dist/tex/context/base/mkiv/font-off.lua
new file mode 100644
index 00000000000..82426552ec0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-off.lua
@@ -0,0 +1,229 @@
+if not modules then modules = { } end modules ['font-off'] = {
+ 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 lower = string.lower
+local round = math.round
+local setmetatableindex = table.setmetatableindex
+
+local fontloader = fontloader
+local font_to_table = fontloader.to_table
+local open_font = fontloader.open
+local get_font_info = fontloader.info
+local close_font = fontloader.close
+local font_fields = fontloader.fields
+
+-- table={
+-- ["familyname"]="TeXGyrePagella",
+-- ["fontname"]="TeXGyrePagella-Regular",
+-- ["fullname"]="TeXGyrePagella-Regular",
+-- ["italicangle"]=0,
+-- ["names"]={
+-- {
+-- ["lang"]="English (US)",
+-- ["names"]={
+-- ["copyright"]="Copyright 2006, 2009 for TeX Gyre extensions by B. Jackowski and J.M. Nowacki (on behalf of TeX users groups). This work is released under the GUST Font License -- see http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt for details.",
+-- ["family"]="TeXGyrePagella",
+-- ["fullname"]="TeXGyrePagella-Regular",
+-- ["postscriptname"]="TeXGyrePagella-Regular",
+-- ["preffamilyname"]="TeX Gyre Pagella",
+-- ["subfamily"]="Regular",
+-- ["trademark"]="Please refer to the Copyright section for the font trademark attribution notices.",
+-- ["uniqueid"]="2.004;UKWN;TeXGyrePagella-Regular",
+-- ["version"]="Version 2.004;PS 2.004;hotconv 1.0.49;makeotf.lib2.0.14853",
+-- },
+-- },
+-- },
+-- ["pfminfo"]={
+-- ["avgwidth"]=528,
+-- ["codepages"]={ 536871315, 0 },
+-- ["firstchar"]=32,
+-- ["fstype"]=12,
+-- ["hhead_ascent"]=1098,
+-- ["hhead_descent"]=-283,
+-- ["hheadascent_add"]=0,
+-- ["hheaddescent_add"]=0,
+-- ["hheadset"]=1,
+-- ["lastchar"]=64260,
+-- ["linegap"]=0,
+-- ["os2_breakchar"]=32,
+-- ["os2_capheight"]=692,
+-- ["os2_defaultchar"]=0,
+-- ["os2_family_class"]=0,
+-- ["os2_strikeypos"]=269,
+-- ["os2_strikeysize"]=50,
+-- ["os2_subxoff"]=0,
+-- ["os2_subxsize"]=650,
+-- ["os2_subyoff"]=75,
+-- ["os2_subysize"]=600,
+-- ["os2_supxoff"]=0,
+-- ["os2_supxsize"]=650,
+-- ["os2_supyoff"]=350,
+-- ["os2_supysize"]=600,
+-- ["os2_typoascent"]=726,
+-- ["os2_typodescent"]=-274,
+-- ["os2_typolinegap"]=200,
+-- ["os2_vendor"]="UKWN",
+-- ["os2_winascent"]=1098,
+-- ["os2_windescent"]=283,
+-- ["os2_xheight"]=449,
+-- ["panose"]={
+-- ["armstyle"]="Any",
+-- ["contrast"]="Any",
+-- ["familytype"]="Any",
+-- ["letterform"]="Any",
+-- ["midline"]="Any",
+-- ["proportion"]="Any",
+-- ["serifstyle"]="Any",
+-- ["strokevariation"]="Any",
+-- ["weight"]="Book",
+-- ["xheight"]="Any",
+-- },
+-- ["panose_set"]=1,
+-- ["pfmfamily"]=81,
+-- ["pfmset"]=1,
+-- ["subsuper_set"]=1,
+-- ["typoascent_add"]=0,
+-- ["typodescent_add"]=0,
+-- ["unicoderanges"]={ 536871047, 0, 0, 0 },
+-- ["vheadset"]=0,
+-- ["vlinegap"]=0,
+-- ["weight"]=400,
+-- ["width"]=5,
+-- ["winascent_add"]=0,
+-- ["windescent_add"]=0,
+-- },
+-- ["units_per_em"]=1000,
+-- ["version"]="2.004;PS 2.004;hotconv 1.0.49;makeotf.lib2.0.14853",
+-- ["weight"]="Book",
+-- }
+
+-- We had this as temporary solution because we needed a bit more info but in the
+-- meantime it got an interesting side effect: currently luatex delays loading of e.g.
+-- glyphs so here we first load and then discard which is a waste. In the past it did
+-- free memory because a full load was done. One of these things that goes unnoticed.
+--
+-- local function get_full_info(...) -- check with taco what we get / could get
+-- local ff = open_font(...)
+-- if ff then
+-- local d = ff -- and font_to_table(ff)
+-- d.glyphs, d.subfonts, d.gpos, d.gsub, d.lookups = nil, nil, nil, nil, nil
+-- close_font(ff)
+-- return d
+-- else
+-- return nil, "error in loading font"
+-- end
+-- end
+
+-- Phillip suggested this faster variant but it's still a hack as fontloader.info should
+-- return these keys/values (and maybe some more) but at least we close the loader which
+-- might save some memory in the end.
+
+-- local function get_full_info(name)
+-- local ff = open_font(name)
+-- if ff then
+-- local fields = table.tohash(font_fields(ff),true) -- isn't that one stable
+-- local d = {
+-- names = fields.names and ff.names,
+-- familyname = fields.familyname and ff.familyname,
+-- fullname = fields.fullname and ff.fullname,
+-- fontname = fields.fontname and ff.fontname,
+-- weight = fields.weight and ff.weight,
+-- italicangle = fields.italicangle and ff.italicangle,
+-- units = fields.units_per_em and ff.units_per_em,
+-- designsize = fields.design_size and ff.design_size,
+-- minsize = fields.design_range_bottom and ff.design_range_bottom,
+-- maxsize = fields.design_range_top and ff.design_range_top,
+-- italicangle = fields.italicangle and ff.italicangle,
+-- pfmweight = pfminfo and pfminfo.weight or 400,
+-- pfmwidth = pfminfo and pfminfo.width or 5,
+-- }
+-- -- setmetatableindex(d,function(t,k)
+-- -- report_names("warning, trying to access field %a in font table of %a",k,name)
+-- -- end)
+-- close_font(ff)
+-- return d
+-- else
+-- return nil, "error in loading font"
+-- end
+-- end
+
+-- more efficient:
+
+local fields = nil
+
+local function check_names(names)
+ if names then
+ for i=1,#names do
+ local name = names[i]
+ if lower(name.lang) == "english (us)" then -- lower added
+ return name.names
+ end
+ end
+ end
+end
+
+local function get_full_info(name)
+ local ff = open_font(name)
+ if ff then
+ -- unfortunately luatex aborts when a field is not available but we just make
+ -- sure that we only access a few known ones
+ local pfminfo = ff.pfminfo or { }
+ local names = check_names(ff.names) or { }
+ local weight = names.weight or ff.weight
+ local width = names.width -- no: ff.width
+ local d = {
+ fontname = ff.fontname,
+ fullname = names.fullname or ff.fullname,
+ family = names.family,
+ subfamily = names.subfamily,
+ familyname = names.preffamilyname or names.family or ff.familyname,
+ subfamilyname = names.prefmodifiers or names.subfamily,
+ weight = weight and lower(weight),
+ width = width and lower(width),
+ italicangle = round(1000*(tonumber(ff.italicangle) or 0))/1000 or 0,
+ units = ff.units_per_em,
+ designsize = ff.design_size,
+ minsize = ff.design_range_bottom,
+ maxsize = ff.design_range_top,
+ pfmweight = pfminfo.weight or 400,
+ pfmwidth = pfminfo.width or 5,
+ monospaced = pfminfo.panose and pfminfo.panose.proportion == "Monospaced",
+ }
+ close_font(ff)
+ return d
+ else
+ return nil, "error in loading font"
+ end
+end
+
+-- As we have lazy loading anyway, this one still is full and with less code than
+-- the previous one. But this depends on the garbage collector to kick in and in the
+-- current version that somehow happens not that often (on my machine I end up with
+-- some 3 GB extra before that happens).
+
+-- local function get_full_info(...)
+-- local ff = open_font(...)
+-- if ff then
+-- local d = { } -- ff is userdata so [1] or # fails on it
+-- setmetatableindex(d,ff)
+-- return d -- garbage collection will do the close_font(ff)
+-- else
+-- return nil, "error in loading font"
+-- end
+-- end
+
+fonts = fonts or { }
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
+local otf = handlers.otf or { }
+handlers.otf = otf
+local readers = otf.readers or { }
+otf.readers = readers
+
+fontloader.fullinfo = get_full_info
+readers.getinfo = readers.getinfo or get_full_info
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua b/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua
new file mode 100644
index 00000000000..6ff2e38b65d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua
@@ -0,0 +1,2414 @@
+if not modules then modules = { } end modules ['font-osd'] = { -- script devanagari
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE",
+ copyright = "TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- I'll optimize this one with ischar (much faster) when I see a reason (read: I need a
+-- proper test case first).
+
+-- This is a version of font-odv.lua adapted to the new font loader and more
+-- direct hashing. The initialization code has been adapted (more efficient). One day
+-- I'll speed this up ... char swapping and properties.
+
+-- A few remarks:
+--
+-- This code is a partial rewrite of the code that deals with devanagari. The data and logic
+-- is by Kai Eigner and based based on Microsoft's OpenType specifications for specific
+-- scripts, but with a few improvements. More information can be found at:
+--
+-- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx
+-- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx
+--
+-- Rajeesh Nambiar provided patches for the malayalam variant. Thanks to feedback from
+-- the mailing list some aspects could be improved.
+--
+-- As I touched nearly all code, reshuffled it, optimized a lot, etc. etc. (imagine how
+-- much can get messed up in over a week work) it could be that I introduced bugs. There
+-- is more to gain (esp in the functions applied to a range) but I'll do that when
+-- everything works as expected. Kai's original code is kept in font-odk.lua as a reference
+-- so blame me (HH) for bugs.
+--
+-- Interesting is that Kai managed to write this on top of the existing otf handler. Only a
+-- few extensions were needed, like a few more analyzing states and dealing with changed
+-- head nodes in the core scanner as that only happens here. There's a lot going on here
+-- and it's only because I touched nearly all code that I got a bit of a picture of what
+-- happens. For in-depth knowledge one needs to consult Kai.
+--
+-- The rewrite mostly deals with efficiency, both in terms of speed and code. We also made
+-- sure that it suits generic use as well as use in ConTeXt. I removed some buglets but can
+-- as well have messed up the logic by doing this. For this we keep the original around
+-- as that serves as reference. Due to the lots of reshuffling glyphs quite some leaks
+-- occur(red) but once I'm satisfied with the rewrite I'll weed them. I also integrated
+-- initialization etc into the regular mechanisms.
+--
+-- In the meantime, we're down from 25.5-3.5=22 seconds to 17.7-3.5=14.2 seconds for a 100
+-- page sample (mid 2012) with both variants so it's worth the effort. Some more speedup is
+-- to be expected. Due to the method chosen it will never be real fast. If I ever become a
+-- power user I'll have a go at some further speed up. I will rename some functions (and
+-- features) once we don't need to check the original code. We now use a special subset
+-- sequence for use inside the analyzer (after all we could can store this in the dataset
+-- and save redundant analysis).
+--
+-- I might go for an array approach with respect to attributes (and reshuffling). Easier.
+--
+-- Some data will move to char-def.lua (some day).
+--
+-- By now we have yet another incremental improved version. In the end I might rewrite the
+-- code.
+
+-- Hans Hagen, PRAGMA-ADE, Hasselt NL
+--
+-- We could have c_nukta, c_halant, c_ra is we know that they are never used mixed within
+-- one script .. yes or no?
+--
+-- Matras: according to Microsoft typography specifications "up to one of each type:
+-- pre-, above-, below- or post- base", but that does not seem to be right. It could
+-- become an option.
+
+local insert, imerge, copy = table.insert, table.imerge, table.copy
+local next, type = next, type
+
+local report_devanagari = logs.reporter("otf","devanagari")
+
+fonts = fonts or { }
+fonts.analyzers = fonts.analyzers or { }
+fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
+
+local otf = fonts.handlers.otf
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local handlers = otf.handlers
+local methods = fonts.analyzers.methods
+
+local otffeatures = fonts.constructors.newfeatures("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
+local getboth = nuts.getboth
+local getid = nuts.getid
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setchar = nuts.setchar
+local getprop = nuts.getprop
+local setprop = nuts.setprop
+
+local ischar = nuts.is_char
+
+local insert_node_after = nuts.insert_after
+local copy_node = nuts.copy
+local free_node = nuts.free
+local remove_node = nuts.remove
+local flush_list = nuts.flush_list
+
+local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
+
+local unsetvalue = attributes.unsetvalue
+
+local fontdata = fonts.hashes.identifiers
+
+local a_state = attributes.private('state')
+local a_syllabe = attributes.private('syllabe')
+
+local dotted_circle = 0x25CC
+
+local states = fonts.analyzers.states -- not features
+
+local s_rphf = states.rphf
+local s_half = states.half
+local s_pref = states.pref
+local s_blwf = states.blwf
+local s_pstf = states.pstf
+
+local replace_all_nbsp = nil
+
+replace_all_nbsp = function(head) -- delayed definition
+ replace_all_nbsp = typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head)
+ return head
+ end
+ return replace_all_nbsp(head)
+end
+
+local xprocesscharacters = nil
+
+if context then
+ xprocesscharacters = function(head,font)
+ xprocesscharacters = nodes.handlers.characters
+ return xprocesscharacters(head,font)
+ end
+else
+ xprocesscharacters = function(head,font)
+ xprocesscharacters = nodes.handlers.nodepass -- generic
+ return xprocesscharacters(head,font)
+ end
+end
+
+local function processcharacters(head,font)
+ return tonut(xprocesscharacters(tonode(head))) -- can be more efficient in context, just direct call
+end
+
+-- 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
+
+-- In due time there will be entries here for scripts like Bengali, Gujarati,
+-- Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu. Feel free to provide the
+-- code points.
+
+-- 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.
+
+-- new, to be checked:
+--
+-- U+00978 : DEVANAGARI LETTER MARWARI DDA
+-- U+00980 : BENGALI ANJI
+-- U+00C00 : TELUGU SIGN COMBINING CANDRABINDU ABOVE
+-- U+00C34 : TELUGU LETTER LLLA
+-- U+00C81 : KANNADA SIGN CANDRABINDU
+-- U+00D01 : MALAYALAM SIGN CANDRABINDU
+-- U+00DE6 : SINHALA LITH DIGIT ZERO
+-- U+00DE7 : SINHALA LITH DIGIT ONE
+-- U+00DE8 : SINHALA LITH DIGIT TWO
+-- U+00DE9 : SINHALA LITH DIGIT THREE
+-- U+00DEA : SINHALA LITH DIGIT FOUR
+-- U+00DEB : SINHALA LITH DIGIT FIVE
+-- U+00DEC : SINHALA LITH DIGIT SIX
+-- U+00DED : SINHALA LITH DIGIT SEVEN
+-- U+00DEE : SINHALA LITH DIGIT EIGHT
+-- U+00DEF : SINHALA LITH DIGIT NINE
+
+local consonant = {
+ -- devanagari
+ [0x0915] = true, [0x0916] = true, [0x0917] = true, [0x0918] = true,
+ [0x0919] = true, [0x091A] = true, [0x091B] = true, [0x091C] = true,
+ [0x091D] = true, [0x091E] = true, [0x091F] = true, [0x0920] = true,
+ [0x0921] = true, [0x0922] = true, [0x0923] = true, [0x0924] = true,
+ [0x0925] = true, [0x0926] = true, [0x0927] = true, [0x0928] = true,
+ [0x0929] = true, [0x092A] = true, [0x092B] = true, [0x092C] = true,
+ [0x092D] = true, [0x092E] = true, [0x092F] = true, [0x0930] = true,
+ [0x0931] = true, [0x0932] = true, [0x0933] = true, [0x0934] = true,
+ [0x0935] = true, [0x0936] = true, [0x0937] = true, [0x0938] = true,
+ [0x0939] = true, [0x0958] = true, [0x0959] = true, [0x095A] = true,
+ [0x095B] = true, [0x095C] = true, [0x095D] = true, [0x095E] = true,
+ [0x095F] = true, [0x0979] = true, [0x097A] = true,
+ -- kannada
+ [0x0C95] = true, [0x0C96] = true, [0x0C97] = true, [0x0C98] = true,
+ [0x0C99] = true, [0x0C9A] = true, [0x0C9B] = true, [0x0C9C] = true,
+ [0x0C9D] = true, [0x0C9E] = true, [0x0C9F] = true, [0x0CA0] = true,
+ [0x0CA1] = true, [0x0CA2] = true, [0x0CA3] = true, [0x0CA4] = true,
+ [0x0CA5] = true, [0x0CA6] = true, [0x0CA7] = true, [0x0CA8] = true,
+ [0x0CA9] = true, [0x0CAA] = true, [0x0CAB] = true, [0x0CAC] = true,
+ [0x0CAD] = true, [0x0CAE] = true, [0x0CAF] = true, [0x0CB0] = true,
+ [0x0CB1] = true, [0x0CB2] = true, [0x0CB3] = true, [0x0CB4] = true,
+ [0x0CB5] = true, [0x0CB6] = true, [0x0CB7] = true, [0x0CB8] = true,
+ [0x0CB9] = true,
+ [0x0CDE] = true, -- obsolete
+ -- malayalam
+ [0x0D15] = true, [0x0D16] = true, [0x0D17] = true, [0x0D18] = true,
+ [0x0D19] = true, [0x0D1A] = true, [0x0D1B] = true, [0x0D1C] = true,
+ [0x0D1D] = true, [0x0D1E] = true, [0x0D1F] = true, [0x0D20] = true,
+ [0x0D21] = true, [0x0D22] = true, [0x0D23] = true, [0x0D24] = true,
+ [0x0D25] = true, [0x0D26] = true, [0x0D27] = true, [0x0D28] = true,
+ [0x0D29] = true, [0x0D2A] = true, [0x0D2B] = true, [0x0D2C] = true,
+ [0x0D2D] = true, [0x0D2E] = true, [0x0D2F] = true, [0x0D30] = true,
+ [0x0D31] = true, [0x0D32] = true, [0x0D33] = true, [0x0D34] = true,
+ [0x0D35] = true, [0x0D36] = true, [0x0D37] = true, [0x0D38] = true,
+ [0x0D39] = true, [0x0D3A] = true,
+}
+
+local independent_vowel = {
+ -- devanagari
+ [0x0904] = true, [0x0905] = true, [0x0906] = true, [0x0907] = true,
+ [0x0908] = true, [0x0909] = true, [0x090A] = true, [0x090B] = true,
+ [0x090C] = true, [0x090D] = true, [0x090E] = true, [0x090F] = true,
+ [0x0910] = true, [0x0911] = true, [0x0912] = true, [0x0913] = true,
+ [0x0914] = true, [0x0960] = true, [0x0961] = true, [0x0972] = true,
+ [0x0973] = true, [0x0974] = true, [0x0975] = true, [0x0976] = true,
+ [0x0977] = true,
+ -- kannada
+ [0x0C85] = true, [0x0C86] = true, [0x0C87] = true, [0x0C88] = true,
+ [0x0C89] = true, [0x0C8A] = true, [0x0C8B] = true, [0x0C8C] = true,
+ [0x0C8D] = true, [0x0C8E] = true, [0x0C8F] = true, [0x0C90] = true,
+ [0x0C91] = true, [0x0C92] = true, [0x0C93] = true, [0x0C94] = true,
+ -- malayalam
+ [0x0D05] = true, [0x0D06] = true, [0x0D07] = true, [0x0D08] = true,
+ [0x0D09] = true, [0x0D0A] = true, [0x0D0B] = true, [0x0D0C] = true,
+ [0x0D0E] = true, [0x0D0F] = true, [0x0D10] = true, [0x0D12] = true,
+ [0x0D13] = true, [0x0D14] = true,
+}
+
+local dependent_vowel = { -- matra
+ -- devanagari
+ [0x093A] = true, [0x093B] = true, [0x093E] = true, [0x093F] = true,
+ [0x0940] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
+ [0x0944] = true, [0x0945] = true, [0x0946] = true, [0x0947] = true,
+ [0x0948] = true, [0x0949] = true, [0x094A] = true, [0x094B] = true,
+ [0x094C] = true, [0x094E] = true, [0x094F] = true, [0x0955] = true,
+ [0x0956] = true, [0x0957] = true, [0x0962] = true, [0x0963] = true,
+ -- kannada
+ [0x0CBE] = true, [0x0CBF] = true, [0x0CC0] = true, [0x0CC1] = true,
+ [0x0CC2] = true, [0x0CC3] = true, [0x0CC4] = true, [0x0CC5] = true,
+ [0x0CC6] = true, [0x0CC7] = true, [0x0CC8] = true, [0x0CC9] = true,
+ [0x0CCA] = true, [0x0CCB] = true, [0x0CCC] = true,
+ -- malayalam
+ [0x0D3E] = true, [0x0D3F] = true, [0x0D40] = true, [0x0D41] = true,
+ [0x0D42] = true, [0x0D43] = true, [0x0D44] = true, [0x0D46] = true,
+ [0x0D47] = true, [0x0D48] = true, [0x0D4A] = true, [0x0D4B] = true,
+ [0x0D4C] = true, [0x0D57] = true,
+}
+
+local vowel_modifier = {
+ -- devanagari
+ [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x0903] = true,
+ -- A8E0 - A8F1 are cantillation marks for the Samaveda and may not belong here.
+ [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
+ [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
+ [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
+ [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
+ [0xA8F0] = true, [0xA8F1] = true,
+ -- malayalam
+ [0x0D02] = true, [0x0D03] = true,
+}
+
+local stress_tone_mark = {
+ [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true,
+ -- kannada
+ [0x0CCD] = true,
+ -- malayalam
+ [0x0D4D] = true,
+}
+
+local nukta = {
+ -- devanagari
+ [0x093C] = true,
+ -- kannada:
+ [0x0CBC] = true,
+}
+
+local halant = {
+ -- devanagari
+ [0x094D] = true,
+ -- kannada
+ [0x0CCD] = true,
+ -- malayalam
+ [0x0D4D] = true,
+}
+
+local ra = {
+ -- devanagari
+ [0x0930] = true,
+ -- kannada
+ [0x0CB0] = true,
+ -- malayalam
+ [0x0D30] = true,
+}
+
+local c_anudatta = 0x0952 -- used to be tables
+local c_nbsp = 0x00A0 -- used to be tables
+local c_zwnj = 0x200C -- used to be tables
+local c_zwj = 0x200D -- used to be tables
+
+local zw_char = { -- could also be inlined
+ [0x200C] = true,
+ [0x200D] = true,
+}
+
+-- 0C82 anusvara
+-- 0C83 visarga
+-- 0CBD avagraha
+-- 0CD5 length mark
+-- 0CD6 ai length mark
+-- 0CE0 letter ll
+-- 0CE1 letter rr
+-- 0CE2 vowel sign l
+-- 0CE2 vowel sign ll
+-- 0CF1 sign
+-- 0CF2 sign
+-- OCE6 - OCEF digits
+
+local pre_mark = {
+ [0x093F] = true, [0x094E] = true,
+ -- malayalam
+ [0x0D46] = true, [0x0D47] = true, [0x0D48] = true,
+}
+
+local above_mark = {
+ [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x093A] = true,
+ [0x0945] = true, [0x0946] = true, [0x0947] = true, [0x0948] = true,
+ [0x0951] = true, [0x0953] = true, [0x0954] = true, [0x0955] = true,
+ [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
+ [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
+ [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
+ [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
+ [0xA8F0] = true, [0xA8F1] = true,
+ -- malayalam
+ [0x0D4E] = true,
+}
+
+local below_mark = {
+ [0x093C] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
+ [0x0944] = true, [0x094D] = true, [0x0952] = true, [0x0956] = true,
+ [0x0957] = true, [0x0962] = true, [0x0963] = true,
+}
+
+local post_mark = {
+ [0x0903] = true, [0x093B] = true, [0x093E] = true, [0x0940] = true,
+ [0x0949] = true, [0x094A] = true, [0x094B] = true, [0x094C] = true,
+ [0x094F] = true,
+}
+
+local twopart_mark = {
+ -- malayalam
+ [0x0D4A] = { 0x0D46, 0x0D3E, }, -- ൊ
+ [0x0D4B] = { 0x0D47, 0x0D3E, }, -- ോ
+ [0x0D4C] = { 0x0D46, 0x0D57, }, -- ൌ
+}
+
+local mark_four = { } -- As we access these frequently an extra hash is used.
+
+for k, v in next, pre_mark do mark_four[k] = pre_mark end
+for k, v in next, above_mark do mark_four[k] = above_mark end
+for k, v in next, below_mark do mark_four[k] = below_mark end
+for k, v in next, post_mark do mark_four[k] = post_mark end
+
+local mark_above_below_post = { }
+
+for k, v in next, above_mark do mark_above_below_post[k] = above_mark end
+for k, v in next, below_mark do mark_above_below_post[k] = below_mark end
+for k, v in next, post_mark do mark_above_below_post[k] = post_mark end
+
+-- Again, this table can be extended for other scripts than devanagari. Actually,
+-- for ConTeXt this kind of data is kept elsewhere so eventually we might move
+-- tables to someplace else.
+
+local reorder_class = {
+ -- devanagari
+ [0x0930] = "before postscript",
+ [0x093F] = "before half",
+ [0x0940] = "after subscript",
+ [0x0941] = "after subscript",
+ [0x0942] = "after subscript",
+ [0x0943] = "after subscript",
+ [0x0944] = "after subscript",
+ [0x0945] = "after subscript",
+ [0x0946] = "after subscript",
+ [0x0947] = "after subscript",
+ [0x0948] = "after subscript",
+ [0x0949] = "after subscript",
+ [0x094A] = "after subscript",
+ [0x094B] = "after subscript",
+ [0x094C] = "after subscript",
+ [0x0962] = "after subscript",
+ [0x0963] = "after subscript",
+ [0x093E] = "after subscript",
+ -- kannada:
+ [0x0CB0] = "after postscript", -- todo in code below
+ [0x0CBF] = "before subscript", -- todo in code below
+ [0x0CC6] = "before subscript", -- todo in code below
+ [0x0CCC] = "before subscript", -- todo in code below
+ [0x0CBE] = "before subscript", -- todo in code below
+ [0x0CE2] = "before subscript", -- todo in code below
+ [0x0CE3] = "before subscript", -- todo in code below
+ [0x0CC1] = "before subscript", -- todo in code below
+ [0x0CC2] = "before subscript", -- todo in code below
+ [0x0CC3] = "after subscript",
+ [0x0CC4] = "after subscript",
+ [0x0CD5] = "after subscript",
+ [0x0CD6] = "after subscript",
+ -- malayalam
+}
+
+-- We use some pseudo features as we need to manipulate the nodelist based
+-- on information in the font as well as already applied features.
+
+local dflt_true = {
+ dflt = true
+}
+
+local dev2_defaults = {
+ dev2 = dflt_true,
+}
+
+local deva_defaults = {
+ dev2 = dflt_true,
+ deva = dflt_true,
+}
+
+local false_flags = { false, false, false, false }
+
+local both_joiners_true = {
+ [0x200C] = true,
+ [0x200D] = true,
+}
+
+local sequence_reorder_matras = {
+ features = { dv01 = dev2_defaults },
+ flags = false_flags,
+ name = "dv01_reorder_matras",
+ order = { "dv01" },
+ type = "devanagari_reorder_matras",
+ nofsteps = 1,
+ steps = {
+ {
+ osdstep = true,
+ coverage = pre_mark,
+ }
+ }
+}
+
+local sequence_reorder_reph = {
+ features = { dv02 = dev2_defaults },
+ flags = false_flags,
+ name = "dv02_reorder_reph",
+ order = { "dv02" },
+ type = "devanagari_reorder_reph",
+ nofsteps = 1,
+ steps = {
+ {
+ osdstep = true,
+ coverage = { },
+ }
+ }
+}
+
+local sequence_reorder_pre_base_reordering_consonants = {
+ features = { dv03 = dev2_defaults },
+ flags = false_flags,
+ name = "dv03_reorder_pre_base_reordering_consonants",
+ order = { "dv03" },
+ type = "devanagari_reorder_pre_base_reordering_consonants",
+ nofsteps = 1,
+ steps = {
+ {
+ osdstep = true,
+ coverage = { },
+ }
+ }
+}
+
+local sequence_remove_joiners = {
+ features = { dv04 = deva_defaults },
+ flags = false_flags,
+ name = "dv04_remove_joiners",
+ order = { "dv04" },
+ type = "devanagari_remove_joiners",
+ nofsteps = 1,
+ steps = {
+ { osdstep = true,
+ coverage = both_joiners_true,
+ },
+ }
+}
+
+-- Looping over feature twice as efficient as looping over basic forms (some
+-- 350 checks instead of 750 for one font). This is something to keep an eye on
+-- as it might depends on the font. Not that it's a bottleneck.
+
+local basic_shaping_forms = {
+ nukt = true,
+ akhn = true,
+ rphf = true,
+ pref = true,
+ rkrf = true,
+ blwf = true,
+ half = true,
+ pstf = true,
+ vatu = true,
+ cjct = true,
+}
+
+local valid = {
+ akhn = true, -- malayalam
+ rphf = true,
+ pref = true,
+ half = true,
+ blwf = true,
+ pstf = true,
+ pres = true, -- malayalam
+ blws = true, -- malayalam
+ psts = true, -- malayalam
+}
+
+local function initializedevanagi(tfmdata)
+ local script, language = otf.scriptandlanguage(tfmdata,attr) -- todo: take fast variant
+ if script == "deva" or script == "dev2" or script =="mlym" or script == "mlm2" then
+ local resources = tfmdata.resources
+ local devanagari = resources.devanagari
+ if not devanagari then
+ --
+ report_devanagari("adding devanagari features to font")
+ --
+ local gsubfeatures = resources.features.gsub
+ local sequences = resources.sequences
+ local sharedfeatures = tfmdata.shared.features
+ --
+ local lastmatch = 0
+ for s=1,#sequences do -- classify chars
+ local features = sequences[s].features
+ if features then
+ for k, v in next, features do
+ if basic_shaping_forms[k] then
+ lastmatch = s
+ end
+ end
+ end
+ end
+ local insertindex = lastmatch + 1
+ --
+ gsubfeatures["dv01"] = dev2_defaults -- reorder matras
+ gsubfeatures["dv02"] = dev2_defaults -- reorder reph
+ gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants
+ gsubfeatures["dv04"] = deva_defaults -- remove joiners
+ --
+ local reorder_pre_base_reordering_consonants = copy(sequence_reorder_pre_base_reordering_consonants)
+ local reorder_reph = copy(sequence_reorder_reph)
+ local reorder_matras = copy(sequence_reorder_matras)
+ local remove_joiners = copy(sequence_remove_joiners)
+ --
+ insert(sequences,insertindex,reorder_pre_base_reordering_consonants)
+ insert(sequences,insertindex,reorder_reph)
+ insert(sequences,insertindex,reorder_matras)
+ insert(sequences,insertindex,remove_joiners)
+ --
+ local blwfcache = { }
+ local seqsubset = { }
+ local rephstep = {
+ coverage = { } -- will be adapted each work
+ }
+ local devanagari = {
+ reph = false,
+ vattu = false,
+ blwfcache = blwfcache,
+ seqsubset = seqsubset,
+ reorderreph = rephstep,
+
+ }
+ --
+ reorder_reph.steps = { rephstep }
+ --
+ local pre_base_reordering_consonants = { }
+ reorder_pre_base_reordering_consonants.steps[1].coverage = pre_base_reordering_consonants
+ --
+ resources.devanagari = devanagari
+ --
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local steps = sequence.steps
+ local nofsteps = sequence.nofsteps
+ local features = sequence.features
+ if features["rphf"] then
+ -- deva
+ devanagari.reph = true
+ elseif features["blwf"] then
+ -- deva
+ devanagari.vattu = true
+ -- dev2
+ for i=1,nofsteps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, coverage do
+ if not blwfcache[k] then
+ blwfcache[k] = v
+ end
+ end
+ end
+ end
+ end
+ if valid[kind] then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ local reph = false
+ if step.osdstep then
+ -- rphf acts on consonant + halant
+ for k, v in next, ra do
+ local r = coverage[k]
+ if r then
+ local h = false
+ for k, v in next, halant do
+ local h = r[k]
+ if h then
+ reph = h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
+ end
+ end
+ else
+ -- rphf might be result of other handler/chainproc
+ end
+ seqsubset[#seqsubset+1] = { kind, coverage, reph }
+ end
+ end
+ end
+ if kind == "pref" then
+ local sequence = dataset[3] -- was [5]
+ local steps = sequence.steps
+ local nofsteps = sequence.nofsteps
+ for i=1,nofsteps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, halant do
+ local h = coverage[k]
+ if h then
+ local found = false
+ for k, v in next, h do
+ found = v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k] = found
+ break
+ end
+ end
+ if found then
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ if script == "deva" then
+ sharedfeatures["dv04"] = true -- dv04_remove_joiners
+ elseif script == "dev2" then
+ sharedfeatures["dv01"] = true -- dv01_reorder_matras
+ sharedfeatures["dv02"] = true -- dv02_reorder_reph
+ sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
+ sharedfeatures["dv04"] = true -- dv04_remove_joiners
+ elseif script == "mlym" then
+ sharedfeatures["pstf"] = true
+ elseif script == "mlm2" then
+ sharedfeatures["pstf"] = true
+ sharedfeatures["pref"] = true
+ sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
+ gsubfeatures ["dv03"] = dev2_defaults -- reorder pre base reordering consonants
+ insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "devanagari",
+ description = "inject additional features",
+ default = true,
+ initializers = {
+ node = initializedevanagi,
+ },
+}
+
+-- hm, this is applied to one character:
+
+local function deva_initialize(font,attr) -- we need a proper hook into the dataset initializer
+
+ local tfmdata = fontdata[font]
+ local datasets = otf.dataset(tfmdata,font,attr) -- don't we know this one?
+ local devanagaridata = datasets.devanagari
+
+ if not devanagaridata then
+
+ devanagaridata = {
+ reph = false,
+ vattu = false,
+ blwfcache = { },
+ }
+ datasets.devanagari = devanagaridata
+ local resources = tfmdata.resources
+ local devanagari = resources.devanagari
+
+ for s=1,#datasets do
+ local dataset = datasets[s]
+ if dataset and dataset[1] then -- value
+ local kind = dataset[4]
+ if kind == "rphf" then
+ -- deva
+ devanagaridata.reph = true
+ elseif kind == "blwf" then
+ -- deva
+ devanagaridata.vattu = true
+ -- dev2
+ devanagaridata.blwfcache = devanagari.blwfcache
+ end
+ end
+ end
+
+ end
+
+ return devanagaridata.reph, devanagaridata.vattu, devanagaridata.blwfcache
+
+end
+
+local function deva_reorder(head,start,stop,font,attr,nbspaces)
+
+ local reph, vattu, blwfcache = deva_initialize(font,attr) -- todo: a hash[font]
+
+ local current = start
+ local n = getnext(start)
+ local base = nil
+ local firstcons = nil
+ local lastcons = nil
+ local basefound = false
+
+ if reph and ra[getchar(start)] and halant[getchar(n)] then
+ -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph
+ -- from candidates for base consonants
+ if n == stop then
+ return head, stop, nbspaces
+ end
+ if getchar(getnext(n)) == c_zwj then
+ current = start
+ else
+ current = getnext(n)
+ setprop(start,a_state,s_rphf)
+ end
+ end
+
+ if getchar(current) == c_nbsp then
+ -- Stand Alone cluster
+ if current == stop then
+ stop = getprev(stop)
+ head = remove_node(head,current)
+ free_node(current)
+ return head, stop, nbspaces
+ else
+ nbspaces = nbspaces + 1
+ base = current
+ firstcons = current
+ lastcons = current
+ current = getnext(current)
+ if current ~= stop then
+ if nukta[getchar(current)] then
+ current = getnext(current)
+ end
+ if getchar(current) == c_zwj then
+ if current ~= stop then
+ local next = getnext(current)
+ if next ~= stop and halant[getchar(next)] then
+ current = next
+ next = getnext(current)
+ local tmp = next and getnext(next) or nil -- needs checking
+ local changestop = next == stop
+ local tempcurrent = copy_node(next)
+ copyinjection(tempcurrent,next)
+ local nextcurrent = copy_node(current)
+ copyinjection(nextcurrent,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set
+ setlink(tempcurrent,nextcurrent)
+ setprop(tempcurrent,a_state,s_blwf)
+ tempcurrent = processcharacters(tempcurrent,font)
+ 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)
+ else
+ setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
+ local freenode = getnext(current)
+ setlink(current,tmp)
+ free_node(freenode)
+ flush_list(tempcurrent)
+ if changestop then
+ stop = current
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ while not basefound do
+ -- find base consonant
+ local char = getchar(current)
+ if consonant[char] then
+ setprop(current,a_state,s_half)
+ if not firstcons then
+ firstcons = current
+ end
+ lastcons = current
+ if not base then
+ base = current
+ elseif blwfcache[char] then
+ -- consonant has below-base (or post-base) form
+ setprop(current,a_state,s_blwf)
+ else
+ base = current
+ end
+ end
+ basefound = current == stop
+ current = getnext(current)
+ end
+
+ if base ~= lastcons then
+ -- if base consonant is not last one then move halant from base consonant to last one
+ local np = base
+ local n = getnext(base)
+ local ch = getchar(n)
+ if nukta[ch] then
+ np = n
+ n = getnext(n)
+ ch = getchar(n)
+ end
+ if halant[ch] then
+ if lastcons ~= stop then
+ local ln = getnext(lastcons)
+ if nukta[getchar(ln)] then
+ lastcons = ln
+ end
+ end
+ -- local np = getprev(n)
+ local nn = getnext(n)
+ local ln = getnext(lastcons) -- what if lastcons is nn ?
+ setlink(np,nn)
+ setnext(lastcons,n)
+ if ln then
+ setprev(ln,n)
+ end
+ setnext(n,ln)
+ setprev(n,lastcons)
+ if lastcons == stop then
+ stop = n
+ end
+ end
+ end
+
+ n = getnext(start)
+ if n ~= stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
+ -- if syllable starts with Ra + H then move this combination so that it follows either:
+ -- the post-base 'matra' (if any) or the base consonant
+ local matra = base
+ if base ~= stop then
+ local next = getnext(base)
+ if dependent_vowel[getchar(next)] then
+ matra = next
+ end
+ end
+ -- [sp][start][n][nn] [matra|base][?]
+ -- [matra|base][start] [n][?] [sp][nn]
+ local sp = getprev(start)
+ local nn = getnext(n)
+ local mn = getnext(matra)
+ setlink(sp,nn)
+ setlink(matra,start)
+ setlink(n,mn)
+ if head == start then
+ head = nn
+ end
+ start = nn
+ if matra == stop then
+ stop = n
+ end
+ end
+
+ local current = start
+ while current ~= stop do
+ local next = getnext(current)
+ if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then
+ setprop(current,a_state,unsetvalue)
+ end
+ current = next
+ end
+
+ if base ~= stop and getprop(base,a_state) then
+ local next = getnext(base)
+ if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then
+ setprop(base,a_state,unsetvalue)
+ end
+ end
+
+ -- ToDo: split two- or three-part matras into their parts. Then, move the left 'matra' part to the beginning of the syllable.
+ -- Not necessary for Devanagari. However it is necessay for other scripts, such as Tamil (e.g. TAMIL VOWEL SIGN O - 0BCA)
+
+ -- classify consonants and 'matra' parts as pre-base, above-base (Reph), below-base or post-base, and group elements of the syllable (consonants and 'matras') according to this classification
+
+ local current, allreordered, moved = start, false, { [base] = true }
+ local a, b, p, bn = base, base, base, getnext(base)
+ if base ~= stop and nukta[getchar(bn)] then
+ a, b, p = bn, bn, bn
+ end
+ while not allreordered do
+ -- current is always consonant
+ local c = current
+ local n = getnext(current)
+ local l = nil -- used ?
+ if c ~= stop then
+ local ch = getchar(n)
+ if nukta[ch] then
+ c = n
+ n = getnext(n)
+ ch = getchar(n)
+ end
+ if c ~= stop then
+ if halant[ch] then
+ c = n
+ n = getnext(n)
+ ch = getchar(n)
+ end
+ while c ~= stop and dependent_vowel[ch] do
+ c = n
+ n = getnext(n)
+ ch = getchar(n)
+ end
+ if c ~= stop then
+ if vowel_modifier[ch] then
+ c = n
+ n = getnext(n)
+ ch = getchar(n)
+ end
+ if c ~= stop and stress_tone_mark[ch] then
+ c = n
+ n = getnext(n)
+ end
+ end
+ end
+ end
+ local bp = getprev(firstcons)
+ local cn = getnext(current)
+ local last = getnext(c)
+ while cn ~= last do
+ -- move pre-base matras...
+ if pre_mark[getchar(cn)] then
+ if bp then
+ setnext(bp,cn)
+ end
+ local prev, next = getboth(cn)
+ if next then
+ setprev(next,prev)
+ end
+ setnext(prev,next)
+ if cn == stop then
+ stop = prev
+ end
+ setprev(cn,bp)
+ setlink(cn,firstcons)
+ if firstcons == start then
+ if head == start then
+ head = cn
+ end
+ start = cn
+ end
+ break
+ end
+ cn = getnext(cn)
+ end
+ allreordered = c == stop
+ current = getnext(c)
+ end
+
+ if reph or vattu then
+ local current, cns = start, nil
+ while current ~= stop do
+ local c = current
+ local n = getnext(current)
+ if ra[getchar(current)] and halant[getchar(n)] then
+ c = n
+ n = getnext(n)
+ local b, bn = base, base
+ while bn ~= stop do
+ local next = getnext(bn)
+ if dependent_vowel[getchar(next)] then
+ b = next
+ end
+ bn = next
+ end
+ if getprop(current,a_state) == s_rphf then
+ -- position Reph (Ra + H) after post-base 'matra' (if any) since these
+ -- become marks on the 'matra', not on the base glyph
+ if b ~= current then
+ if current == start then
+ if head == start then
+ head = n
+ end
+ start = n
+ end
+ if b == stop then
+ stop = c
+ end
+ local prev = getprev(current)
+ setlink(prev,n)
+ local next = getnext(b)
+ setlink(c,next)
+ setlink(b,current)
+ end
+ elseif cns and getnext(cns) ~= current then -- todo: optimize next
+ -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants)
+ local cp = getprev(current)
+ local cnsn = getnext(cns)
+ setlink(cp,n)
+ setlink(cns,current)
+ setlink(c,cnsn)
+ if c == stop then
+ stop = cp
+ break
+ end
+ current = getprev(n)
+ end
+ else
+ local char = getchar(current)
+ if consonant[char] then
+ cns = current
+ local next = getnext(cns)
+ if halant[getchar(next)] then
+ cns = next
+ end
+ elseif char == c_nbsp then
+ nbspaces = nbspaces + 1
+ cns = current
+ local next = getnext(cns)
+ if halant[getchar(next)] then
+ cns = next
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ end
+
+ if getchar(base) == c_nbsp then
+ nbspaces = nbspaces - 1
+ head = remove_node(head,base)
+ free_node(base)
+ end
+
+ return head, stop, nbspaces
+end
+
+-- If a pre-base matra character had been reordered before applying basic features,
+-- the glyph can be moved closer to the main consonant based on whether half-forms had been formed.
+-- Actual position for the matra is defined as “after last standalone halant glyph,
+-- after initial matra position and before the main consonant”.
+-- If ZWJ or ZWNJ follow this halant, position is moved after it.
+
+-- so we break out ... this is only done for the first 'word' (if we feed words we can as
+-- well test for non glyph.
+
+function handlers.devanagari_reorder_matras(head,start) -- no leak
+ local current = start -- we could cache attributes here
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ while current do
+ local char = ischar(current,startfont)
+ local next = getnext(current)
+ if char and getprop(current,a_syllabe) == startattr then
+ if halant[char] and not getprop(current,a_state) then
+ if next then
+ local char = ischar(next,startfont)
+ if char and zw_char[char] and getprop(next,a_syllabe) == startattr then
+ current = next
+ next = getnext(current)
+ end
+ end
+ -- can be optimzied
+ local startnext = getnext(start)
+ head = remove_node(head,start)
+ setlink(start,next)
+ setlink(current,start)
+ start = startnext
+ break
+ end
+ end
+ current = next
+ end
+ return head, start, true
+end
+
+-- todo: way more caching of attributes and font
+
+-- Reph’s original position is always at the beginning of the syllable, (i.e. it is not reordered at the character reordering stage).
+-- However, it will be reordered according to the basic-forms shaping results.
+-- Possible positions for reph, depending on the script, are; after main, before post-base consonant forms,
+-- and after post-base consonant forms.
+
+-- 1 If reph should be positioned after post-base consonant forms, proceed to step 5.
+-- 2 If the reph repositioning class is not after post-base: target position is after the first explicit halant glyph between
+-- the first post-reph consonant and last main consonant. If ZWJ or ZWNJ are following this halant, position is moved after it.
+-- If such position is found, this is the target position. Otherwise, proceed to the next step.
+-- Note: in old-implementation fonts, where classifications were fixed in shaping engine,
+-- there was no case where reph position will be found on this step.
+-- 3 If reph should be repositioned after the main consonant: from the first consonant not ligated with main,
+-- or find the first consonant that is not a potential pre-base reordering Ra.
+-- 4 If reph should be positioned before post-base consonant, find first post-base classified consonant not ligated with main.
+-- If no consonant is found, the target position should be before the first matra, syllable modifier sign or vedic sign.
+-- 5 If no consonant is found in steps 3 or 4, move reph to a position immediately before the first post-base matra,
+-- syllable modifier sign or vedic sign that has a reordering class after the intended reph position.
+-- For example, if the reordering position for reph is post-main, it will skip above-base matras that also have a post-main position.
+-- 6 Otherwise, reorder reph to the end of the syllable.
+
+-- hm, this only looks at the start of a nodelist ... is this supposed to be line based?
+
+function handlers.devanagari_reorder_reph(head,start)
+ -- since in Devanagari reph has reordering position 'before postscript' dev2 only follows step 2, 4, and 6,
+ -- the other steps are still ToDo (required for scripts other than dev2)
+ local current = getnext(start)
+ local startnext = nil
+ local startprev = nil
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ while current do
+ local char = ischar(current,font)
+ if char and getprop(current,a_syllabe) == startattr then -- step 2
+ if halant[char] and not getprop(current,a_state) then
+ local next = getnext(current)
+ if next then
+ local nextchar = ischar(next,font)
+ if nextchar and zw_char[nextchar] and getprop(next,a_syllabe) == startattr then
+ current = next
+ next = getnext(current)
+ end
+ end
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ setlink(start,next)
+ setlink(current,start)
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ break
+ end
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if not startnext then
+ current = getnext(start)
+ while current do
+ local char = ischar(current,font)
+ if char and getprop(current,a_syllabe) == startattr then -- step 4
+ if getprop(current,a_state) == s_pstf then -- post-base
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local prev = getprev(current)
+ setlink(prev,start)
+ setlink(start,current)
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ break
+ end
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ end
+ -- todo: determine position for reph with reordering position other than 'before postscript'
+ -- (required for scripts other than dev2)
+ -- leaks
+ if not startnext then
+ current = getnext(start)
+ local c = nil
+ while current do
+ local char = ischar(current,font)
+ if char and getprop(current,a_syllabe) == startattr then -- step 5
+ if not c and mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then
+ c = current
+ end
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ -- here we can loose the old start node: maybe best split cases
+ if c then
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local prev = getprev(c)
+ setlink(prev,start)
+ setlink(start,c)
+ -- end
+ start = startnext
+ startattr = getprop(start,a_syllabe)
+ end
+ end
+ -- leaks
+ if not startnext then
+ current = start
+ local next = getnext(current)
+ while next do
+ local nextchar = ischar(next,font)
+ if nextchar and getprop(next,a_syllabe) == startattr then --step 6
+ current = next
+ next = getnext(current)
+ else
+ break
+ end
+ end
+ if start ~= current then
+ startnext = getnext(start)
+ head = remove_node(head,start)
+ local next = getnext(current)
+ setlink(start,next)
+ setlink(current,"next",start)
+ start = startnext
+ end
+ end
+ --
+ return head, start, true
+end
+
+-- we can cache some checking (v)
+
+-- If a pre-base reordering consonant is found, reorder it according to the following rules:
+--
+-- 1 Only reorder a glyph produced by substitution during application of the feature.
+-- (Note that a font may shape a Ra consonant with the feature generally but block it in certain contexts.)
+-- 2 Try to find a target position the same way as for pre-base matra. If it is found, reorder pre-base consonant glyph.
+-- 3 If position is not found, reorder immediately before main consonant.
+
+-- UNTESTED: NOT CALLED IN EXAMPLE
+
+function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
+ local current = start
+ local startnext = nil
+ local startprev = nil
+ local startfont = getfont(start)
+ local startattr = getprop(start,a_syllabe)
+ -- can be fast for loop + caching state
+ while current do
+ local char = ischar(current,font)
+ if char and getprop(current,a_syllabe) == startattr then
+ local next = getnext(current)
+ if halant[char] and not getprop(current,a_state) then
+ if next then
+ local nextchar = ischar(next,font)
+ if nextchar and getprop(next,a_syllabe) == startattr then
+ if nextchar == c_zwnj or nextchar == c_zwj then
+ current = next
+ next = getnext(current)
+ end
+ end
+ end
+ startnext = getnext(start)
+ removenode(start,start)
+ setlink(start,next)
+ setlink(current,start)
+ start = startnext
+ break
+ end
+ current = next
+ else
+ break
+ end
+ end
+ if not startnext then
+ current = getnext(start)
+ startattr = getprop(start,a_syllabe)
+ while current do
+ local char = ischar(current,font)
+ if char and getprop(current,a_syllabe) == startattr then
+ if not consonant[char] and getprop(current,a_state) then -- main
+ startnext = getnext(start)
+ removenode(start,start)
+ local prev = getprev(current)
+ setlink(start,prev)
+ setlink(start,current)
+ start = startnext
+ break
+ end
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ end
+ return head, start, true
+end
+
+-- function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
+-- local stop = getnext(start)
+-- local font = getfont(start)
+-- while stop do
+-- local char = ischar(stop)
+-- if char and (char == c_zwnj or char == c_zwj) then
+-- stop = getnext(stop)
+-- else
+-- break
+-- end
+-- end
+-- if stop then
+-- setnext(getprev(stop))
+-- setprev(stop,getprev(start))
+-- end
+-- local prev = getprev(start)
+-- if prev then
+-- setnext(prev,stop)
+-- end
+-- if head == start then
+-- head = stop
+-- end
+-- flush_list(start)
+-- return head, stop, true
+-- end
+
+function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
+ local stop = getnext(start)
+ local font = getfont(start)
+ local last = start
+ while stop do
+ local char = ischar(stop,font)
+ if char and (char == c_zwnj or char == c_zwj) then
+ last = stop
+ stop = getnext(stop)
+ else
+ break
+ end
+ end
+ local prev = getprev(start)
+ if stop then
+ setnext(last)
+ setlink(prev,stop)
+ elseif prev then
+ setnext(prev)
+ end
+ if head == start then
+ head = stop
+ end
+ flush_list(start)
+ return head, stop, true
+end
+
+local function dev2_initialize(font,attr)
+
+ local devanagari = fontdata[font].resources.devanagari
+
+ if devanagari then
+ return devanagari.seqsubset or { }, devanagari.reorderreph or { }
+ else
+ return { }, { }
+ end
+
+end
+
+-- this one will be merged into the caller: it saves a call, but we will then make function
+-- of the actions
+
+local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pass over (determine stop in sweep)
+
+ local seqsubset, reorderreph = dev2_initialize(font,attr)
+
+ local reph = false -- was nil ... probably went unnoticed because never assigned
+ local halfpos = nil
+ local basepos = nil
+ local subpos = nil
+ local postpos = nil
+ local locl = { }
+
+ for i=1,#seqsubset do
+
+ -- maybe quit if start == stop
+
+ local subset = seqsubset[i]
+ local kind = subset[1]
+ local lookupcache = subset[2]
+ if kind == "rphf" then
+ for k, v in next, ra do
+ local r = lookupcache[k]
+ if r then
+ for k, v in next, halant do
+ local h = r[k]
+ if h then
+ reph = h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
+ end
+ end
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then --above-base: rphf Consonant + Halant
+ local afternext = next ~= stop and getnext(next)
+ if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph
+ current = next
+ current = getnext(current)
+ elseif current == start then
+ setprop(current,a_state,s_rphf)
+ current = next
+ else
+ current = next
+ end
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "pref" then
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pref)
+ setprop(next,a_state,s_pref)
+ current = next
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "half" then -- half forms: half / Consonant + Halant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half
+ current = next
+ else
+ setprop(current,a_state,s_half)
+ if not halfpos then
+ halfpos = current
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "blwf" then -- below-base: blwf / Halant + Consonant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_blwf)
+ setprop(next,a_state,s_blwf)
+ current = next
+ subpos = current
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ elseif kind == "pstf" then -- post-base: pstf / Halant + Consonant
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ if current ~= stop then
+ local c = locl[current] or getchar(current)
+ local found = lookupcache[c]
+ if found then
+ local next = getnext(current)
+ local n = locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pstf)
+ setprop(next,a_state,s_pstf)
+ current = next
+ postpos = current
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ end
+
+ -- this one changes per word ...
+
+ reorderreph.coverage = { [reph] = true } -- neat
+
+ -- end of weird
+
+ local current, base, firstcons = start, nil, nil
+
+ if getprop(start,a_state) == s_rphf then
+ -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
+ current = getnext(getnext(start))
+ end
+
+ if current ~= getnext(stop) and getchar(current) == c_nbsp then
+ -- Stand Alone cluster
+ if current == stop then
+ stop = getprev(stop)
+ head = remove_node(head,current)
+ free_node(current)
+ return head, stop, nbspaces
+ else
+ nbspaces = nbspaces + 1
+ base = current
+ current = getnext(current)
+ if current ~= stop then
+ local char = getchar(current)
+ if nukta[char] then
+ current = getnext(current)
+ char = getchar(current)
+ end
+ if char == c_zwj then
+ local next = getnext(current)
+ if current ~= stop and next ~= stop and halant[getchar(next)] then
+ current = next
+ next = getnext(current)
+ local tmp = getnext(next)
+ local changestop = next == stop
+ setnext(next,nil)
+ setprop(current,a_state,s_pref)
+ current = processcharacters(current,font)
+ setprop(current,a_state,s_blwf)
+ current = processcharacters(current,font)
+ setprop(current,a_state,s_pstf)
+ current = processcharacters(current,font)
+ 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)
+ else
+ setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node
+ if changestop then
+ stop = current
+ end
+ end
+ end
+ end
+ end
+ end
+ else -- not Stand Alone cluster
+ local last = getnext(stop)
+ while current ~= last do -- find base consonant
+ local next = getnext(current)
+ if consonant[getchar(current)] then
+ if not (current ~= stop and next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwj) then
+ if not firstcons then
+ firstcons = current
+ end
+ -- check whether consonant has below-base or post-base form or is pre-base reordering Ra
+ local a = getprop(current,a_state)
+ if not (a == s_pref or a == s_blwf or a == s_pstf) then
+ base = current
+ end
+ end
+ end
+ current = next
+ end
+ if not base then
+ base = firstcons
+ end
+ end
+
+ if not base then
+ if getprop(start,a_state) == s_rphf then
+ setprop(start,a_state,unsetvalue)
+ end
+ return head, stop, nbspaces
+ else
+ if getprop(base,a_state) then
+ setprop(base,a_state,unsetvalue)
+ end
+ basepos = base
+ end
+ if not halfpos then
+ halfpos = base
+ end
+ if not subpos then
+ subpos = base
+ end
+ if not postpos then
+ postpos = subpos or base
+ end
+
+ -- Matra characters are classified and reordered by which consonant in a conjunct they have affinity for
+
+ local moved = { }
+ local current = start
+ local last = getnext(stop)
+ while current ~= last do
+ local char, target, cn = locl[current] or getchar(current), nil, getnext(current)
+ -- not so efficient (needed for malayalam)
+ local tpm = twopart_mark[char]
+ if tpm then
+ local extra = copy_node(current)
+ copyinjection(extra,current)
+ char = tpm[1]
+ setchar(current,char)
+ setchar(extra,tpm[2])
+ head = insert_node_after(head,current,extra)
+ end
+ --
+ if not moved[current] and dependent_vowel[char] then
+ if pre_mark[char] then -- Before first half form in the syllable
+ moved[current] = true
+ -- can be helper to remove one node
+ local prev, next = getboth(current)
+ setlink(prev,next)
+ if current == stop then
+ stop = getprev(current)
+ end
+ if halfpos == start then
+ if head == start then
+ head = current
+ end
+ start = current
+ end
+ local prev = getprev(halfpos)
+ setlink(prev,current)
+ setlink(current,halfpos)
+ halfpos = current
+ elseif above_mark[char] then -- After main consonant
+ target = basepos
+ if subpos == basepos then
+ subpos = current
+ end
+ if postpos == basepos then
+ postpos = current
+ end
+ basepos = current
+ elseif below_mark[char] then -- After subjoined consonants
+ target = subpos
+ if postpos == subpos then
+ postpos = current
+ end
+ subpos = current
+ elseif post_mark[char] then -- After post-form consonant
+ target = postpos
+ postpos = current
+ end
+ if mark_above_below_post[char] then
+ local prev = getprev(current)
+ if prev ~= target then
+ local next = getnext(current)
+ setlink(next,prev)
+ if current == stop then
+ stop = prev
+ end
+ local next = getnext(target)
+ setlink(current,next)
+ setlink(target,current)
+ end
+ end
+ end
+ current = cn
+ end
+
+ -- Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first.
+
+ local current, c = start, nil
+ while current ~= stop do
+ local char = getchar(current)
+ if halant[char] or stress_tone_mark[char] then
+ if not c then
+ c = current
+ end
+ else
+ c = nil
+ end
+ local next = getnext(current)
+ if c and nukta[getchar(next)] then
+ if head == c then
+ head = next
+ end
+ if stop == next then
+ stop = current
+ end
+ local prev = getprev(c)
+ setlink(next,prev)
+ local nextnext = getnext(next)
+ setnext(current,nextnext)
+ local nextnextnext = getnext(nextnext)
+ if nextnextnext then
+ setprev(nextnextnext,current)
+ end
+ setlink(nextnext,c)
+ end
+ if stop == current then break end
+ current = getnext(current)
+ end
+
+ if getchar(base) == c_nbsp then
+ nbspaces = nbspaces - 1
+ head = remove_node(head, base)
+ free_node(base)
+ end
+
+ return head, stop, nbspaces
+end
+
+-- cleaned up and optimized ... needs checking (local, check order, fixes, extra hash, etc)
+
+local separator = { }
+
+imerge(separator,consonant)
+imerge(separator,independent_vowel)
+imerge(separator,dependent_vowel)
+imerge(separator,vowel_modifier)
+imerge(separator,stress_tone_mark)
+
+for k, v in next, nukta do separator[k] = true end
+for k, v in next, halant do separator[k] = true end
+
+local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowel
+ -- why two variants ... the comment suggests that it's the same ruleset
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ if variant == 1 then
+ local v = ischar(n,font)
+ if v and nukta[v] then
+ n = getnext(n)
+ if n then
+ v = ischar(n,font)
+ end
+ end
+ if n and v then
+ local nn = getnext(n)
+ if nn then
+ local vv = ischar(nn,font)
+ if vv then
+ local nnn = getnext(nn)
+ if nnn then
+ local vvv = ischar(nnn,font)
+ if vvv then
+ if vv == c_zwj and consonant[vvv] then
+ c = nnn
+ elseif (vv == c_zwnj or vv == c_zwj) and halant[vvv] then
+ local nnnn = getnext(nnn)
+ if nnnn then
+ local vvvv = ischar(nnnn)
+ if vvvv and consonant[vvvv] then
+ c = nnnn
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif variant == 2 then
+ local v = ischar(n,font)
+ if v and nukta[v] then
+ c = n
+ end
+ n = getnext(c)
+ if n then
+ v = ischar(n,font)
+ if v then
+ local nn = getnext(n)
+ if nn then
+ local vv = ischar(nn,font)
+ if vv and zw_char[vv] then
+ n = nn
+ v = vv
+ nn = getnext(nn)
+ vv = nn and ischar(nn,font)
+ end
+ if vv and halant[v] and consonant[vv] then
+ c = nn
+ end
+ end
+ end
+ end
+ end
+ -- c = ms_matra(c)
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ local v = ischar(n,font)
+ if not v then
+ return c
+ end
+ if dependent_vowel[v] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if nukta[v] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if halant[v] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if vowel_modifier[v] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ c = getnext(c)
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ return n
+ else
+ return c
+ end
+end
+
+local function analyze_next_chars_two(c,font)
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ local v = ischar(n,font)
+ if v and nukta[v] then
+ c = n
+ end
+ n = c
+ while true do
+ local nn = getnext(n)
+ if nn then
+ local vv = ischar(nn,font)
+ if vv then
+ if halant[vv] then
+ n = nn
+ local nnn = getnext(nn)
+ if nnn then
+ local vvv = ischar(nnn,font)
+ if vvv and zw_char[vvv] then
+ n = nnn
+ end
+ end
+ elseif vv == c_zwnj or vv == c_zwj then
+ -- n = nn -- not here (?)
+ local nnn = getnext(nn)
+ if nnn then
+ local vvv = ischar(nnn,font)
+ if vvv and halant[vvv] then
+ n = nnn
+ end
+ end
+ else
+ break
+ end
+ local nn = getnext(n)
+ if nn then
+ local vv = ischar(nn,font)
+ if vv and consonant[vv] then
+ n = nn
+ local nnn = getnext(nn)
+ if nnn then
+ local vvv = ischar(nnn,font)
+ if vvv and nukta[vvv] then
+ n = nnn
+ end
+ end
+ c = n
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ --
+ if not c then
+ -- This shouldn't happen I guess.
+ return
+ end
+ local n = getnext(c)
+ if not n then
+ return c
+ end
+ local v = ischar(n,font)
+ if not v then
+ return c
+ end
+ if v == c_anudatta then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if halant[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ if v == c_zwnj or v == c_zwj then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ else
+ -- c = ms_matra(c)
+ -- same as one
+ if dependent_vowel[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if nukta[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if halant[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ end
+ -- same as one
+ if vowel_modifier[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ c = n
+ n = getnext(c)
+ if not n then
+ return c
+ end
+ v = ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ return n
+ else
+ return c
+ end
+end
+
+local function inject_syntax_error(head,current,mark)
+ local signal = copy_node(current)
+ copyinjection(signal,current)
+ if mark == pre_mark then -- THIS IS WRONG: pre_mark is a table
+ 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.
+
+function methods.deva(head,font,attr)
+ head = tonut(head)
+ local current = head
+ local start = true
+ local done = false
+ local nbspaces = 0
+ while current do
+ local char = ischar(current,font)
+ if char then
+ done = true
+ local syllablestart = current
+ local syllableend = nil
+ local c = current
+ local n = getnext(c)
+ local first = char
+ if n and ra[first] then
+ local second = ischar(n,font)
+ if second and halant[second] then
+ local n = getnext(n)
+ if n then
+ local third = ischar(n,font)
+ if third then
+ c = n
+ first = third
+ end
+ end
+ end
+ end
+ local standalone = first == c_nbsp
+ if standalone then
+ local prev = getprev(current)
+ if prev then
+ local prevchar = ischar(prev,font)
+ if not prevchar then
+ -- different font or language so quite certainly a different word
+ elseif not separator[prevchar] then
+ -- something that separates words
+ else
+ standalone = false
+ end
+ else
+ -- begin of paragraph or box
+ end
+ end
+ if standalone then
+ -- stand alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ local syllableend = analyze_next_chars_one(c,font,2)
+ current = getnext(syllableend)
+ if syllablestart ~= syllableend then
+ head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current = getnext(current)
+ end
+ else
+ -- we can delay the getsubtype(n) and getfont(n) and test for say halant first
+ -- as an table access is faster than two function calls (subtype and font are
+ -- pseudo fields) but the code becomes messy (unless we make it a function)
+ if consonant[char] then
+ -- syllable containing consonant
+ local prevc = true
+ while prevc do
+ prevc = false
+ local n = getnext(current)
+ if not n then
+ break
+ end
+ local v = ischar(n,font)
+ if not v then
+ break
+ end
+ if nukta[v] then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = ischar(n,font)
+ if not v then
+ break
+ end
+ end
+ if halant[v] then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = ischar(n,font)
+ if not v then
+ break
+ end
+ if v == c_zwnj or v == c_zwj then
+ n = getnext(n)
+ if not n then
+ break
+ end
+ v = ischar(n,font)
+ if not v then
+ break
+ end
+ end
+ if consonant[v] then
+ prevc = true
+ current = n
+ end
+ end
+ end
+ local n = getnext(current)
+ if n then
+ local v = ischar(n,font)
+ if v and nukta[v] then
+ -- nukta (not specified in Microsft Devanagari OpenType specification)
+ current = n
+ n = getnext(current)
+ end
+ end
+ syllableend = current
+ current = n
+ if current then
+ local v = ischar(current,font)
+ if not v then
+ -- skip
+ elseif halant[v] then
+ -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H
+ local n = getnext(current)
+ if n then
+ local v = ischar(n,font)
+ if v and zw_char[v] then
+ -- code collapsed, probably needs checking with intention
+ syllableend = n
+ current = getnext(n)
+ else
+ syllableend = current
+ current = n
+ end
+ else
+ syllableend = current
+ current = n
+ end
+ else
+ -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM]
+ if dependent_vowel[v] then
+ syllableend = current
+ current = getnext(current)
+ v = ischar(current,font)
+ end
+ if v and vowel_modifier[v] then
+ syllableend = current
+ current = getnext(current)
+ v = ischar(current,font)
+ end
+ if v and stress_tone_mark[v] then
+ syllableend = current
+ current = getnext(current)
+ end
+ end
+ end
+ if syllablestart ~= syllableend then
+ head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current = getnext(current)
+ end
+ elseif independent_vowel[char] then
+ -- syllable without consonants: VO + [VM] + [SM]
+ syllableend = current
+ current = getnext(current)
+ if current then
+ local v = ischar(current,font)
+ if v then
+ if vowel_modifier[v] then
+ syllableend = current
+ current = getnext(current)
+ v = ischar(current,font)
+ end
+ if v and stress_tone_mark[v] then
+ syllableend = current
+ current = getnext(current)
+ end
+ end
+ end
+ else
+ local mark = mark_four[char]
+ if mark then
+ head, current = inject_syntax_error(head,current,mark)
+ end
+ current = getnext(current)
+ end
+ end
+ else
+ current = getnext(current)
+ end
+ start = false
+ end
+
+ if nbspaces > 0 then
+ head = replace_all_nbsp(head)
+ end
+
+ head = tonode(head)
+
+ 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)
+
+function methods.dev2(head,font,attr)
+ head = tonut(head)
+ local current = head
+ local start = true
+ local done = false
+ local syllabe = 0
+ local nbspaces = 0
+ while current do
+ local syllablestart = nil
+ local syllableend = nil
+ local char = ischar(current,font)
+ if char then
+ done = true
+ syllablestart = current
+ local c = current
+ local n = getnext(current)
+ if n and ra[char] then
+ local nextchar = ischar(n,font)
+ if nextchar and halant[nextchar] then
+ local n = getnext(n)
+ if n then
+ local nextnextchar = ischar(n,font)
+ if nextnextchar then
+ c = n
+ char = nextnextchar
+ end
+ end
+ end
+ end
+ if independent_vowel[char] then
+ -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ current = analyze_next_chars_one(c,font,1)
+ syllableend = current
+ else
+ local standalone = char == c_nbsp
+ if standalone then
+ nbspaces = nbspaces + 1
+ local p = getprev(current)
+ if not p then
+ -- begin of paragraph or box
+ elseif ischar(p,font) then
+ -- different font or language so quite certainly a different word
+ elseif not separator[getchar(p)] then
+ -- something that separates words
+ else
+ standalone = false
+ end
+ end
+ if standalone then
+ -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
+ current = analyze_next_chars_one(c,font,2)
+ syllableend = current
+ elseif consonant[getchar(current)] then
+ -- WHY current INSTEAD OF c ?
+
+ -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)]
+ current = analyze_next_chars_two(current,font) -- not c !
+ syllableend = current
+ end
+ end
+ end
+ if syllableend then
+ syllabe = syllabe + 1
+ local c = syllablestart
+ local n = getnext(syllableend)
+ while c ~= n do
+ setprop(c,a_syllabe,syllabe)
+ c = getnext(c)
+ end
+ end
+ if syllableend and syllablestart ~= syllableend then
+ head, current, nbspaces = dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ end
+ if not syllableend then
+ local char = ischar(current,font)
+ if char and not getprop(current,a_state) then
+ local mark = mark_four[char]
+ if mark then
+ head, current = inject_syntax_error(head,current,mark)
+ end
+ end
+ end
+ start = false
+ current = getnext(current)
+ end
+
+ if nbspaces > 0 then
+ head = replace_all_nbsp(head)
+ end
+
+ head = tonode(head)
+
+ return head, done
+end
+
+methods.mlym = methods.deva
+methods.mlm2 = methods.dev2
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua
new file mode 100644
index 00000000000..6a3804a7425
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua
@@ -0,0 +1,442 @@
+if not modules then modules = { } end modules ['font-ota'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (analysing)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- context only
+
+local type = type
+
+if not trackers then trackers = { register = function() end } end
+
+----- trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+
+local fonts, nodes, node = fonts, nodes, node
+
+local allocate = utilities.storage.allocate
+
+local otf = fonts.handlers.otf
+
+local analyzers = fonts.analyzers
+local initializers = allocate()
+local methods = allocate()
+
+analyzers.initializers = initializers
+analyzers.methods = methods
+
+local a_state = attributes.private('state')
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+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 traverse_node_list = nuts.traverse
+local end_of_math = nuts.end_of_math
+
+local nodecodes = nodes.nodecodes
+----- glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+
+local fontdata = fonts.hashes.identifiers
+local categories = characters and characters.categories or { } -- sorry, only in context
+local chardata = characters and characters.data
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+--[[ldx--
+<p>Analyzers run per script and/or language and are needed in order to
+process features right.</p>
+--ldx]]--
+
+-- never use these numbers directly
+
+local s_init = 1 local s_rphf = 7
+local s_medi = 2 local s_half = 8
+local s_fina = 3 local s_pref = 9
+local s_isol = 4 local s_blwf = 10
+local s_mark = 5 local s_pstf = 11
+local s_rest = 6
+
+local states = {
+ init = s_init,
+ medi = s_medi,
+ med2 = s_medi,
+ fina = s_fina,
+ fin2 = s_fina,
+ fin3 = s_fina,
+ isol = s_isol,
+ mark = s_mark,
+ rest = s_rest,
+ rphf = s_rphf,
+ half = s_half,
+ pref = s_pref,
+ blwf = s_blwf,
+ pstf = s_pstf,
+}
+
+local features = {
+ init = s_init,
+ medi = s_medi,
+ med2 = s_medi,
+ fina = s_fina,
+ fin2 = s_fina,
+ fin3 = s_fina,
+ isol = s_isol,
+ -- mark = s_mark,
+ -- rest = s_rest,
+ rphf = s_rphf,
+ half = s_half,
+ pref = s_pref,
+ blwf = s_blwf,
+ pstf = s_pstf,
+}
+
+analyzers.states = states
+analyzers.features = features
+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
+
+function analyzers.setstate(head,font)
+ local useunicodemarks = analyzers.useunicodemarks
+ local tfmdata = fontdata[font]
+ local descriptions = tfmdata.descriptions
+ local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
+ current = tonut(current)
+ while current do
+ local char, id = ischar(current,font)
+ if char and not getprop(current,a_state) then
+ done = true
+ local d = descriptions[char]
+ if d then
+ if d.class == "mark" then
+ done = true
+ setprop(current,a_state,s_mark)
+ elseif useunicodemarks and categories[char] == "mn" then
+ done = true
+ setprop(current,a_state,s_mark)
+ elseif n == 0 then
+ first, last, n = current, current, 1
+ setprop(current,a_state,s_init)
+ else
+ last, n = current, n+1
+ setprop(current,a_state,s_medi)
+ end
+ else -- finish
+ if first and first == last then
+ setprop(last,a_state,s_isol)
+ elseif last then
+ setprop(last,a_state,s_fina)
+ end
+ first, last, n = nil, nil, 0
+ end
+ elseif char == false then
+ -- other font
+ if first and first == last then
+ setprop(last,a_state,s_isol)
+ elseif last then
+ setprop(last,a_state,s_fina)
+ end
+ first, last, n = nil, nil, 0
+ if id == math_code then
+ current = end_of_math(current)
+ end
+ elseif id == disc_code then
+ -- always in the middle .. it doesn't make much sense to assign a property
+ -- here ... we might at some point decide to flag the components when present
+ -- but even then it's kind of bogus
+ setprop(current,a_state,s_medi)
+ last = current
+ else -- finish
+ if first and first == last then
+ setprop(last,a_state,s_isol)
+ elseif last then
+ setprop(last,a_state,s_fina)
+ end
+ first, last, n = nil, nil, 0
+ if id == math_code then
+ current = end_of_math(current)
+ end
+ end
+ current = getnext(current)
+ end
+ if first and first == last then
+ setprop(last,a_state,s_isol)
+ elseif last then
+ setprop(last,a_state,s_fina)
+ end
+ return head, done
+end
+
+-- in the future we will use language/script attributes instead of the
+-- font related value, but then we also need dynamic features which is
+-- somewhat slower; and .. we need a chain of them
+
+local function analyzeinitializer(tfmdata,value) -- attr
+ local script, language = otf.scriptandlanguage(tfmdata) -- attr
+ local action = initializers[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(tfmdata,value)
+ else
+ local action = action[language]
+ if action then
+ return action(tfmdata,value)
+ end
+ end
+end
+
+local function analyzeprocessor(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
+ local action = methods[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(head,font,attr)
+ else
+ action = action[language]
+ if action then
+ return action(head,font,attr)
+ end
+ end
+ return head, false
+end
+
+registerotffeature {
+ name = "analyze",
+ description = "analysis of character classes",
+ default = true,
+ initializers = {
+ node = analyzeinitializer,
+ },
+ processors = {
+ position = 1,
+ node = analyzeprocessor,
+ }
+}
+
+-- latin
+
+methods.latn = analyzers.setstate
+-------.dflt = analyzers.setstate % can be an option or just the default
+
+local arab_warned = { }
+
+local function warning(current,what)
+ local char = getchar(current)
+ if not arab_warned[char] then
+ log.report("analyze","arab: character %C has no %a class",char,what)
+ arab_warned[char] = true
+ end
+end
+
+local mappers = {
+ l = s_init, -- left
+ d = s_medi, -- double
+ c = s_medi, -- joiner
+ r = s_fina, -- right
+ u = s_isol, -- nonjoiner
+}
+
+-- we can also use this trick for devanagari
+
+local classifiers = characters.classifiers
+
+if not classifiers then
+
+ local first_arabic, last_arabic = characters.blockrange("arabic")
+ local first_syriac, last_syriac = characters.blockrange("syriac")
+ local first_mandiac, last_mandiac = characters.blockrange("mandiac")
+ local first_nko, last_nko = characters.blockrange("nko")
+
+ classifiers = table.setmetatableindex(function(t,k)
+ local c = chardata[k]
+ local v = false
+ if c then
+ local arabic = c.arabic
+ if arabic then
+ v = mappers[arabic]
+ if not v then
+ log.report("analyze","error in mapping arabic %C",k)
+ -- error
+ v = false
+ end
+ elseif k >= first_arabic and k <= last_arabic or k >= first_syriac and k <= last_syriac or
+ k >= first_mandiac and k <= last_mandiac or k >= first_nko and k <= last_nko then
+ if categories[k] == "mn" then
+ v = s_mark
+ else
+ v = s_rest
+ end
+ end
+ end
+ t[k] = v
+ return v
+ end)
+
+end
+
+function methods.arab(head,font,attr)
+ local first, last = nil, nil
+ local c_first, c_last = nil, nil
+ local current, done = head, false
+ current = tonut(current)
+ while current do
+ local char, id = ischar(current,font)
+ if char and not getprop(current,a_state) then
+ done = true
+ local classifier = classifiers[char]
+ if not classifier then
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setprop(last,a_state,s_fina)
+ else
+ warning(last,"fina")
+ setprop(last,a_state,s_error)
+ end
+ first, last = nil, nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setprop(first,a_state,s_isol)
+ else
+ warning(first,"isol")
+ setprop(first,a_state,s_error)
+ end
+ first = nil
+ end
+ elseif classifier == s_mark then
+ setprop(current,a_state,s_mark)
+ elseif classifier == s_isol then
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setprop(last,a_state,s_fina)
+ else
+ warning(last,"fina")
+ setprop(last,a_state,s_error)
+ end
+ first, last = nil, nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setprop(first,a_state,s_isol)
+ else
+ warning(first,"isol")
+ setprop(first,a_state,s_error)
+ end
+ first = nil
+ end
+ setprop(current,a_state,s_isol)
+ elseif classifier == s_medi then
+ if first then
+ last = current
+ c_last = classifier
+ setprop(current,a_state,s_medi)
+ else
+ setprop(current,a_state,s_init)
+ first = current
+ c_first = classifier
+ end
+ elseif classifier == s_fina then
+ if last then
+ if getprop(last,a_state) ~= s_init then
+ setprop(last,a_state,s_medi)
+ end
+ setprop(current,a_state,s_fina)
+ first, last = nil, nil
+ elseif first then
+ -- if getprop(first,a_state) ~= s_init then
+ -- -- needs checking
+ -- setprop(first,a_state,s_medi)
+ -- end
+ setprop(current,a_state,s_fina)
+ first = nil
+ else
+ setprop(current,a_state,s_isol)
+ end
+ else -- classifier == s_rest
+ setprop(current,a_state,s_rest)
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setprop(last,a_state,s_fina)
+ else
+ warning(last,"fina")
+ setprop(last,a_state,s_error)
+ end
+ first, last = nil, nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setprop(first,a_state,s_isol)
+ else
+ warning(first,"isol")
+ setprop(first,a_state,s_error)
+ end
+ first = nil
+ end
+ end
+ else
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setprop(last,a_state,s_fina)
+ else
+ warning(last,"fina")
+ setprop(last,a_state,s_error)
+ end
+ first, last = nil, nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setprop(first,a_state,s_isol)
+ else
+ warning(first,"isol")
+ setprop(first,a_state,s_error)
+ end
+ first = nil
+ end
+ if id == math_code then -- a bit duplicate as we test for glyphs twice
+ current = end_of_math(current)
+ end
+ end
+ current = getnext(current)
+ end
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setprop(last,a_state,s_fina)
+ else
+ warning(last,"fina")
+ setprop(last,a_state,s_error)
+ end
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setprop(first,a_state,s_isol)
+ else
+ warning(first,"isol")
+ setprop(first,a_state,s_error)
+ end
+ end
+ return head, done
+end
+
+methods.syrc = methods.arab
+methods.mand = methods.arab
+methods.nko = methods.arab
+
+directives.register("otf.analyze.useunicodemarks",function(v)
+ analyzers.useunicodemarks = v
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otb.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otb.lua
new file mode 100644
index 00000000000..c9f5d4aca9b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otb.lua
@@ -0,0 +1,707 @@
+if not modules then modules = { } end modules ['font-otb'] = {
+ 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 concat = table.concat
+local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget
+local lpegmatch = lpeg.match
+local utfchar = utf.char
+
+local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
+local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+
+local report_prepare = logs.reporter("fonts","otf prepare")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
+
+otf.defaultbasealternate = "none" -- first last
+
+local wildcard = "*"
+local default = "dflt"
+
+local formatters = string.formatters
+local f_unicode = formatters["%U"]
+local f_uniname = formatters["%U (%s)"]
+local f_unilist = formatters["% t (% t)"]
+
+local function gref(descriptions,n)
+ if type(n) == "number" then
+ local name = descriptions[n].name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
+ end
+ elseif n then
+ local num, nam, j = { }, { }, 0
+ for i=1,#n do
+ local ni = n[i]
+ if tonumber(ni) then -- first is likely a key
+ j = j + 1
+ local di = descriptions[ni]
+ num[j] = f_unicode(ni)
+ nam[j] = di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in base mode tracing>"
+ end
+end
+
+local function cref(feature,lookuptags,lookupname)
+ if lookupname then
+ return formatters["feature %a, lookup %a"](feature,lookuptags[lookupname])
+ else
+ return formatters["feature %a"](feature)
+ end
+end
+
+local function report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,comment)
+ report_prepare("%s: base alternate %s => %s (%S => %S)",
+ cref(feature,lookuptags,lookupname),
+ gref(descriptions,unicode),
+ replacement and gref(descriptions,replacement),
+ value,
+ comment)
+end
+
+local function report_substitution(feature,lookuptags,lookupname,descriptions,unicode,substitution)
+ report_prepare("%s: base substitution %s => %S",
+ cref(feature,lookuptags,lookupname),
+ gref(descriptions,unicode),
+ gref(descriptions,substitution))
+end
+
+local function report_ligature(feature,lookuptags,lookupname,descriptions,unicode,ligature)
+ report_prepare("%s: base ligature %s => %S",
+ cref(feature,lookuptags,lookupname),
+ gref(descriptions,ligature),
+ gref(descriptions,unicode))
+end
+
+local function report_kern(feature,lookuptags,lookupname,descriptions,unicode,otherunicode,value)
+ report_prepare("%s: base kern %s + %s => %S",
+ cref(feature,lookuptags,lookupname),
+ gref(descriptions,unicode),
+ gref(descriptions,otherunicode),
+ value)
+end
+
+local basemethods = { }
+local basemethod = "<unset>"
+
+local function applybasemethod(what,...)
+ local m = basemethods[basemethod][what]
+ if m then
+ return m(...)
+ end
+end
+
+-- We need to make sure that luatex sees the difference between
+-- base fonts that have different glyphs in the same slots in fonts
+-- that have the same fullname (or filename). LuaTeX will merge fonts
+-- eventually (and subset later on). If needed we can use a more
+-- verbose name as long as we don't use <()<>[]{}/%> and the length
+-- is < 128.
+
+local basehash, basehashes, applied = { }, 1, { }
+
+local function registerbasehash(tfmdata)
+ local properties = tfmdata.properties
+ local hash = concat(applied," ")
+ local base = basehash[hash]
+ if not base then
+ basehashes = basehashes + 1
+ base = basehashes
+ basehash[hash] = base
+ end
+ properties.basehash = base
+ properties.fullname = properties.fullname .. "-" .. base
+ -- report_prepare("fullname base hash '%a, featureset %a",tfmdata.properties.fullname,hash)
+ applied = { }
+end
+
+local function registerbasefeature(feature,value)
+ applied[#applied+1] = feature .. "=" .. tostring(value)
+end
+
+-- The original basemode ligature builder used the names of components
+-- and did some expression juggling to get the chain right. The current
+-- variant starts with unicodes but still uses names to make the chain.
+-- This is needed because we have to create intermediates when needed
+-- but use predefined snippets when available. To some extend the
+-- current builder is more stupid but I don't worry that much about it
+-- as ligatures are rather predicatable.
+--
+-- Personally I think that an ff + i == ffi rule as used in for instance
+-- latin modern is pretty weird as no sane person will key that in and
+-- expect a glyph for that ligature plus the following character. Anyhow,
+-- as we need to deal with this, we do, but no guarantes are given.
+--
+-- latin modern dejavu
+--
+-- f+f 102 102 102 102
+-- f+i 102 105 102 105
+-- f+l 102 108 102 108
+-- f+f+i 102 102 105
+-- f+f+l 102 102 108 102 102 108
+-- ff+i 64256 105 64256 105
+-- ff+l 64256 108
+--
+-- As you can see here, latin modern is less complete than dejavu but
+-- in practice one will not notice it.
+--
+-- The while loop is needed because we need to resolve for instance
+-- pseudo names like hyphen_hyphen to endash so in practice we end
+-- up with a bit too many definitions but the overhead is neglectable.
+--
+-- We can have changed[first] or changed[second] but it quickly becomes
+-- messy if we need to take that into account.
+
+local trace = false
+
+local function finalize_ligatures(tfmdata,ligatures)
+ local nofligatures = #ligatures
+ if nofligatures > 0 then
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local unicodes = resources.unicodes -- we use rawget in order to avoid bulding the table
+ local private = resources.private
+ local alldone = false
+ while not alldone do
+ local done = 0
+ for i=1,nofligatures do
+ local ligature = ligatures[i]
+ if ligature then
+ local unicode, lookupdata = ligature[1], ligature[2]
+ if trace_ligatures_detail then
+ report_prepare("building % a into %a",lookupdata,unicode)
+ end
+ local size = #lookupdata
+ local firstcode = lookupdata[1] -- [2]
+ local firstdata = characters[firstcode]
+ local okay = false
+ if firstdata then
+ local firstname = "ctx_" .. firstcode
+ for i=1,size-1 do -- for i=2,size-1 do
+ local firstdata = characters[firstcode]
+ if not firstdata then
+ firstcode = private
+ if trace_ligatures_detail then
+ report_prepare("defining %a as %a",firstname,firstcode)
+ end
+ unicodes[firstname] = firstcode
+ firstdata = { intermediate = true, ligatures = { } }
+ characters[firstcode] = firstdata
+ descriptions[firstcode] = { name = firstname }
+ private = private + 1
+ end
+ local target
+ local secondcode = lookupdata[i+1]
+ local secondname = firstname .. "_" .. secondcode
+ if i == size - 1 then
+ target = unicode
+ if not rawget(unicodes,secondname) then
+ unicodes[secondname] = unicode -- map final ligature onto intermediates
+ end
+ okay = true
+ else
+ target = rawget(unicodes,secondname)
+ if not target then
+ break
+ end
+ end
+ if trace_ligatures_detail then
+ report_prepare("codes (%a,%a) + (%a,%a) -> %a",firstname,firstcode,secondname,secondcode,target)
+ end
+ local firstligs = firstdata.ligatures
+ if firstligs then
+ firstligs[secondcode] = { char = target }
+ else
+ firstdata.ligatures = { [secondcode] = { char = target } }
+ end
+ firstcode = target
+ firstname = secondname
+ end
+ elseif trace_ligatures_detail then
+ report_prepare("no glyph (%a,%a) for building %a",firstname,firstcode,target)
+ end
+ if okay then
+ ligatures[i] = false
+ done = done + 1
+ end
+ end
+ end
+ alldone = done == 0
+ end
+ if trace_ligatures_detail then
+ for k, v in table.sortedhash(characters) do
+ if v.ligatures then
+ table.print(v,k)
+ end
+ end
+ end
+ resources.private = private
+ return true
+ end
+end
+
+local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local properties = tfmdata.properties
+ local changed = tfmdata.changed
+ local lookuphash = resources.lookuphash
+ local lookuptypes = resources.lookuptypes
+ local lookuptags = resources.lookuptags
+
+ local ligatures = { }
+ local alternate = tonumber(value) or true and 1
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
+
+ local actions = {
+ substitution = function(lookupdata,lookuptags,lookupname,description,unicode)
+ if trace_singles then
+ report_substitution(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
+ end
+ changed[unicode] = lookupdata
+ end,
+ alternate = function(lookupdata,lookuptags,lookupname,description,unicode)
+ local replacement = lookupdata[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = lookupdata[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = lookupdata[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
+ end
+ end,
+ ligature = function(lookupdata,lookuptags,lookupname,description,unicode)
+ if trace_ligatures then
+ report_ligature(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
+ end
+ ligatures[#ligatures+1] = { unicode, lookupdata }
+ end,
+ }
+
+ for unicode, character in next, characters do
+ local description = descriptions[unicode]
+ local lookups = description.slookups
+ if lookups then
+ for l=1,#lookuplist do
+ local lookupname = lookuplist[l]
+ local lookupdata = lookups[lookupname]
+ if lookupdata then
+ local lookuptype = lookuptypes[lookupname]
+ local action = actions[lookuptype]
+ if action then
+ action(lookupdata,lookuptags,lookupname,description,unicode)
+ end
+ end
+ end
+ end
+ local lookups = description.mlookups
+ if lookups then
+ for l=1,#lookuplist do
+ local lookupname = lookuplist[l]
+ local lookuplist = lookups[lookupname]
+ if lookuplist then
+ local lookuptype = lookuptypes[lookupname]
+ local action = actions[lookuptype]
+ if action then
+ for i=1,#lookuplist do
+ action(lookuplist[i],lookuptags,lookupname,description,unicode)
+ end
+ end
+ end
+ end
+ end
+ end
+ properties.hasligatures = finalize_ligatures(tfmdata,ligatures)
+end
+
+local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) -- todo what kind of kerns, currently all
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local properties = tfmdata.properties
+ local lookuptags = resources.lookuptags
+ local sharedkerns = { }
+ local traceindeed = trace_baseinit and trace_kerns
+ local haskerns = false
+ for unicode, character in next, characters do
+ local description = descriptions[unicode]
+ local rawkerns = description.kerns -- shared
+ if rawkerns then
+ local s = sharedkerns[rawkerns]
+ if s == false then
+ -- skip
+ elseif s then
+ character.kerns = s
+ else
+ local newkerns = character.kerns
+ local done = false
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local kerns = rawkerns[lookup]
+ if kerns then
+ for otherunicode, value in next, kerns do
+ if value == 0 then
+ -- maybe no 0 test here
+ elseif not newkerns then
+ newkerns = { [otherunicode] = value }
+ done = true
+ if traceindeed then
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
+ end
+ elseif not newkerns[otherunicode] then -- first wins
+ newkerns[otherunicode] = value
+ done = true
+ if traceindeed then
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
+ end
+ end
+ end
+ end
+ end
+ if done then
+ sharedkerns[rawkerns] = newkerns
+ character.kerns = newkerns -- no empty assignments
+ haskerns = true
+ else
+ sharedkerns[rawkerns] = false
+ end
+ end
+ end
+ end
+ properties.haskerns = haskerns
+end
+
+basemethods.independent = {
+ preparesubstitutions = preparesubstitutions,
+ preparepositionings = preparepositionings,
+}
+
+local function makefake(tfmdata,name,present)
+ local resources = tfmdata.resources
+ local private = resources.private
+ local character = { intermediate = true, ligatures = { } }
+ resources.unicodes[name] = private
+ tfmdata.characters[private] = character
+ tfmdata.descriptions[private] = { name = name }
+ resources.private = private + 1
+ present[name] = private
+ return character
+end
+
+local function make_1(present,tree,name)
+ for k, v in next, tree do
+ if k == "ligature" then
+ present[name] = v
+ else
+ make_1(present,v,name .. "_" .. k)
+ end
+ end
+end
+
+local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookuptags,lookupname)
+ for k, v in next, tree do
+ if k == "ligature" then
+ local character = characters[preceding]
+ if not character then
+ if trace_baseinit then
+ report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookuptags[lookupname],v,preceding)
+ end
+ character = makefake(tfmdata,name,present)
+ end
+ local ligatures = character.ligatures
+ if ligatures then
+ ligatures[unicode] = { char = v }
+ else
+ character.ligatures = { [unicode] = { char = v } }
+ end
+ if done then
+ local d = done[lookupname]
+ if not d then
+ done[lookupname] = { "dummy", v }
+ else
+ d[#d+1] = v
+ end
+ end
+ else
+ local code = present[name] or unicode
+ local name = name .. "_" .. k
+ make_2(present,tfmdata,characters,v,name,code,k,done,lookuptags,lookupname)
+ end
+ end
+end
+
+local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local changed = tfmdata.changed
+ local lookuphash = resources.lookuphash
+ local lookuptypes = resources.lookuptypes
+ local lookuptags = resources.lookuptags
+
+ local ligatures = { }
+ local alternate = tonumber(value) or true and 1
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
+
+ for l=1,#lookuplist do
+ local lookupname = lookuplist[l]
+ local lookupdata = lookuphash[lookupname]
+ local lookuptype = lookuptypes[lookupname]
+ for unicode, data in next, lookupdata do
+ if lookuptype == "substitution" then
+ if trace_singles then
+ report_substitution(feature,lookuptags,lookupname,descriptions,unicode,data)
+ end
+ changed[unicode] = data
+ elseif lookuptype == "alternate" then
+ local replacement = data[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = data[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = data[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
+ end
+ elseif lookuptype == "ligature" then
+ ligatures[#ligatures+1] = { unicode, data, lookupname }
+ if trace_ligatures then
+ report_ligature(feature,lookuptags,lookupname,descriptions,unicode,data)
+ end
+ end
+ end
+ end
+
+ local nofligatures = #ligatures
+
+ if nofligatures > 0 then
+
+ local characters = tfmdata.characters
+ local present = { }
+ local done = trace_baseinit and trace_ligatures and { }
+
+ for i=1,nofligatures do
+ local ligature = ligatures[i]
+ local unicode, tree = ligature[1], 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]
+ make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookuptags,lookupname)
+ end
+
+ end
+
+end
+
+local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local properties = tfmdata.properties
+ local lookuphash = resources.lookuphash
+ local lookuptags = resources.lookuptags
+ local traceindeed = trace_baseinit and trace_kerns
+ -- check out this sharedkerns trickery
+ for l=1,#lookuplist do
+ local lookupname = lookuplist[l]
+ local lookupdata = lookuphash[lookupname]
+ for unicode, data in next, lookupdata do
+ local character = characters[unicode]
+ local kerns = character.kerns
+ if not kerns then
+ kerns = { }
+ character.kerns = kerns
+ end
+ if traceindeed then
+ for otherunicode, kern in next, data do
+ if not kerns[otherunicode] and kern ~= 0 then
+ kerns[otherunicode] = kern
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,kern)
+ end
+ end
+ else
+ for otherunicode, kern in next, data do
+ if not kerns[otherunicode] and kern ~= 0 then
+ kerns[otherunicode] = kern
+ end
+ end
+ end
+ end
+ end
+
+end
+
+local function initializehashes(tfmdata)
+ nodeinitializers.features(tfmdata)
+end
+
+basemethods.shared = {
+ initializehashes = initializehashes,
+ preparesubstitutions = preparesubstitutions,
+ preparepositionings = preparepositionings,
+}
+
+basemethod = "independent"
+
+local function featuresinitializer(tfmdata,value)
+ if true then -- value then
+ local starttime = trace_preparing and os.clock()
+ local features = tfmdata.shared.features
+ local fullname = tfmdata.properties.fullname or "?"
+ if features then
+ applybasemethod("initializehashes",tfmdata)
+ local collectlookups = otf.collectlookups
+ local rawdata = tfmdata.shared.rawdata
+ local properties = tfmdata.properties
+ local script = properties.script -- or "dflt" -- can be nil
+ local language = properties.language -- or "dflt" -- can be nil
+ local basesubstitutions = rawdata.resources.features.gsub
+ local basepositionings = rawdata.resources.features.gpos
+ --
+ -- if basesubstitutions then
+ -- for feature, data in next, basesubstitutions do
+ -- local value = features[feature]
+ -- if value then
+ -- local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
+ -- if validlookups then
+ -- applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
+ -- registerbasefeature(feature,value)
+ -- end
+ -- end
+ -- end
+ -- end
+ -- if basepositionings then
+ -- for feature, data in next, basepositionings do
+ -- local value = features[feature]
+ -- if value then
+ -- local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
+ -- if validlookups then
+ -- applybasemethod("preparepositionings",tfmdata,feature,features[feature],validlookups,lookuplist)
+ -- registerbasefeature(feature,value)
+ -- end
+ -- end
+ -- end
+ -- end
+ --
+ if basesubstitutions or basepositionings then
+ local sequences = tfmdata.resources.sequences
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local sfeatures = sequence.features
+ if sfeatures then
+ local order = sequence.order
+ if order then
+ for i=1,#order do --
+ local feature = order[i]
+ local value = features[feature]
+ if value then
+ local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
+ if not validlookups then
+ -- skip
+ elseif basesubstitutions and basesubstitutions[feature] then
+ if trace_preparing then
+ report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value)
+ end
+ applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
+ registerbasefeature(feature,value)
+ elseif basepositionings and basepositionings[feature] then
+ if trace_preparing then
+ report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value)
+ end
+ applybasemethod("preparepositionings",tfmdata,feature,value,validlookups,lookuplist)
+ registerbasefeature(feature,value)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ registerbasehash(tfmdata)
+ end
+ if trace_preparing then
+ report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname)
+ end
+ end
+end
+
+registerotffeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1
+ base = featuresinitializer,
+ }
+}
+
+-- independent : collect lookups independently (takes more runtime ... neglectable)
+-- shared : shares lookups with node mode (takes more memory unless also a node mode variant is used ... noticeable)
+
+directives.register("fonts.otf.loader.basemethod", function(v)
+ if basemethods[v] then
+ basemethod = v
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua
new file mode 100644
index 00000000000..d4c98d6fcc5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua
@@ -0,0 +1,747 @@
+if not modules then modules = { } end modules ['font-otc'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (context)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ 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 lpegmatch = lpeg.match
+local utfbyte = utf.byte
+
+-- we assume that the other otf stuff is loaded already
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local report_otf = logs.reporter("fonts","otf loading")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local setmetatableindex = table.setmetatableindex
+
+local normalized = {
+ substitution = "substitution",
+ single = "substitution",
+ ligature = "ligature",
+ alternate = "alternate",
+ multiple = "multiple",
+ kern = "kern",
+ pair = "pair",
+ chainsubstitution = "chainsubstitution",
+ chainposition = "chainposition",
+}
+
+local types = {
+ substitution = "gsub_single",
+ ligature = "gsub_ligature",
+ alternate = "gsub_alternate",
+ multiple = "gsub_multiple",
+ kern = "gpos_pair",
+ pair = "gpos_pair",
+ chainsubstitution = "gsub_contextchain",
+ chainposition = "gpos_contextchain",
+}
+
+setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key"
+
+local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+local noflags = { false, false, false, false }
+
+-- beware: shared, maybe we should copy the sequence
+
+local function addfeature(data,feature,specifications)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local features = resources.features
+ local sequences = resources.sequences
+ if not features or not sequences then
+ return
+ end
+ -- feature has to be unique but the name entry wins eventually
+
+ -- todo alse gpos
+
+ local fontfeatures = resources.features or everywhere
+ local unicodes = resources.unicodes
+ local splitter = lpeg.splitter(" ",unicodes)
+ local done = 0
+ local skip = 0
+ if not specifications[1] then
+ -- so we accept a one entry specification
+ specifications = { specifications }
+ end
+
+ local function tounicode(code)
+ if not code then
+ return
+ elseif type(code) == "number" then
+ return code
+ else
+ return unicodes[code] or utfbyte(code)
+ end
+ end
+
+ local coverup = otf.coverup
+ local coveractions = coverup.actions
+ local stepkey = coverup.stepkey
+ local register = coverup.register
+
+ local function prepare_substitution(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(replacement) == "table" then
+ replacement = replacement[1]
+ end
+ replacement = tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_alternate(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r = { }
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ r[i] = descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_multiple(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r, n = { }, 0
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ if descriptions[u] then
+ n = n + 1
+ r[n] = u
+ end
+ end
+ if n > 0 then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_ligature(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, ligature in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(ligature) == "string" then
+ ligature = { lpegmatch(splitter,ligature) }
+ end
+ local present = true
+ for i=1,#ligature do
+ local l = ligature[i]
+ local u = tounicode(l)
+ if descriptions[u] then
+ ligature[i] = u
+ else
+ present = false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_kern(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_pair(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_chain(list,featuretype,sublookups)
+ -- todo: coveractions
+ local rules = list.rules
+ local coverage = { }
+ if rules then
+ local rulehash = { }
+ local rulesize = 0
+ local sequence = { }
+ local nofsequences = 0
+ local lookuptype = types[featuretype]
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local current = rule.current
+ local before = rule.before
+ local after = rule.after
+ local replacements = rule.replacements or false
+ local sequence = { }
+ local nofsequences = 0
+ if before then
+ for n=1,#before do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = before[n]
+ end
+ end
+ local start = nofsequences + 1
+ for n=1,#current do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = current[n]
+ end
+ local stop = nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = after[n]
+ end
+ end
+ local lookups = rule.lookups or false
+ local subtype = nil
+ if lookups and sublookups then
+ for k, v in next, lookups do
+ local lookup = sublookups[v]
+ if lookup then
+ lookups[k] = lookup
+ if not subtype then
+ subtype = lookup.type
+ end
+ else
+ -- already expanded
+ end
+ end
+ end
+ if nofsequences > 0 then -- we merge coverage into one
+ -- we copy as we can have different fonts
+ local hashed = { }
+ for i=1,nofsequences do
+ local t = { }
+ local s = sequence[i]
+ for i=1,#s do
+ local u = tounicode(s[i])
+ if u then
+ t[u] = true
+ end
+ end
+ hashed[i] = t
+ end
+ sequence = hashed
+ -- now we create the rule
+ rulesize = rulesize + 1
+ rulehash[rulesize] = {
+ nofrules, -- 1
+ lookuptype, -- 2
+ sequence, -- 3
+ start, -- 4
+ stop, -- 5
+ lookups, -- 6 (6/7 also signal of what to do)
+ replacements, -- 7
+ subtype, -- 8
+ }
+ for unic in next, sequence[start] do
+ local cu = coverage[unic]
+ if not cu then
+ coverage[unic] = rulehash -- can now be done cleaner i think
+ end
+ end
+ end
+ end
+ end
+ return coverage
+ end
+
+ for s=1,#specifications do
+ local specification = specifications[s]
+ local valid = specification.valid
+ local feature = specification.name or feature
+ if not valid or valid(data,specification,feature) then
+ local initialize = specification.initialize
+ if initialize then
+ -- when false is returned we initialize only once
+ specification.initialize = initialize(specification,data) and initialize or nil
+ end
+ local askedfeatures = specification.features or everywhere
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local featureorder = specification.order or { feature }
+ local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
+ local nofsteps = 0
+ local steps = { }
+ local sublookups = specification.lookups
+ local category = nil
+ if sublookups then
+ local s = { }
+ for i=1,#sublookups do
+ local specification = sublookups[i]
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local nofsteps = 0
+ local steps = { }
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ coverage = prepare_substitution(list,featuretype)
+ elseif featuretype == "ligature" then
+ coverage = prepare_ligature(list,featuretype)
+ elseif featuretype == "alternate" then
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ coverage = prepare_multiple(list,featuretype)
+ elseif featuretype == "kern" then
+ format = "kern"
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ s[i] = {
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = types[featuretype],
+ }
+ end
+ sublookups = s
+ end
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ category = "gsub"
+ coverage = prepare_substitution(list,featuretype)
+ elseif featuretype == "ligature" then
+ category = "gsub"
+ coverage = prepare_ligature(list,featuretype)
+ elseif featuretype == "alternate" then
+ category = "gsub"
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ category = "gsub"
+ coverage = prepare_multiple(list,featuretype)
+ elseif featuretype == "kern" then
+ category = "gpos"
+ format = kern
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ category = "gpos"
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ elseif featuretype == "chainsubstitution" then
+ category = "gsub"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ elseif featuretype == "chainposition" then
+ category = "gpos"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if nofsteps > 0 then
+ -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
+ for k, v in next, askedfeatures do
+ if v[1] then
+ askedfeatures[k] = tohash(v)
+ end
+ end
+ if featureflags[1] then featureflags[1] = "mark" end
+ if featureflags[2] then featureflags[2] = "ligature" end
+ if featureflags[3] then featureflags[3] = "base" end
+ local sequence = {
+ chain = featurechain,
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = feature, -- redundant
+ order = featureorder,
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = types[featuretype],
+ }
+ -- todo : before|after|index
+ if specification.prepend then
+ insert(sequences,1,sequence)
+ else
+ insert(sequences,sequence)
+ end
+ -- register in metadata (merge as there can be a few)
+ local features = fontfeatures[category]
+ if not features then
+ features = { }
+ fontfeatures[category] = features
+ end
+ local k = features[feature]
+ if not k then
+ k = { }
+ features[feature] = k
+ end
+ --
+ for script, languages in next, askedfeatures do
+ local kk = k[script]
+ if not kk then
+ kk = { }
+ k[script] = kk
+ end
+ for language, value in next, languages do
+ kk[language] = value
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
+ end
+end
+
+otf.enhancers.addfeature = addfeature
+
+local extrafeatures = { }
+
+function otf.addfeature(name,specification)
+ if type(name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if type(name) == "string" then
+ extrafeatures[name] = specification
+ end
+end
+
+local function enhance(data,filename,raw)
+ for feature, specification in next, extrafeatures do
+ addfeature(data,feature,specification)
+ end
+end
+
+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 {
+ 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 {
+ name = 'trep',
+ description = 'tex replacements',
+}
+
+-- tcom
+
+if characters.combined then
+
+ local tcom = { }
+
+ local function initialize()
+ characters.initialize()
+ for first, seconds in next, characters.combined do
+ for second, combination in next, seconds do
+ tcom[combination] = { first, second }
+ end
+ end
+ -- return false
+ end
+
+ local tcom_specification = {
+ type = "ligature",
+ features = everywhere,
+ data = tcom,
+ 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 {
+ 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',
+-- }
+
+-- fonts.handlers.otf.addfeature {
+-- name = "stest",
+-- type = "substitution",
+-- data = {
+-- a = "X",
+-- b = "P",
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "atest",
+-- type = "alternate",
+-- data = {
+-- a = { "X", "Y" },
+-- b = { "P", "Q" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "mtest",
+-- type = "multiple",
+-- data = {
+-- a = { "X", "Y" },
+-- b = { "P", "Q" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "ltest",
+-- type = "ligature",
+-- data = {
+-- X = { "a", "b" },
+-- Y = { "d", "a" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "ktest",
+-- type = "kern",
+-- data = {
+-- a = { b = -500 },
+-- }
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otd.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otd.lua
new file mode 100644
index 00000000000..2257caa8ca5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otd.lua
@@ -0,0 +1,253 @@
+if not modules then modules = { } end modules ['font-otd'] = {
+ 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 type = type
+local match = string.match
+local sequenced = table.sequenced
+
+local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
+local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+local report_process = logs.reporter("fonts","otf process")
+
+local allocate = utilities.storage.allocate
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local hashes = fonts.hashes
+local definers = fonts.definers
+local constructors = fonts.constructors
+local specifiers = fonts.specifiers
+
+local fontidentifiers = hashes.identifiers
+local fontresources = hashes.resources
+local fontproperties = hashes.properties
+local fontdynamics = hashes.dynamics
+
+local contextsetups = specifiers.contextsetups
+local contextnumbers = specifiers.contextnumbers
+local contextmerged = specifiers.contextmerged
+
+local setmetatableindex = table.setmetatableindex
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local a_to_script = { }
+local a_to_language = { }
+
+-- we can have a scripts hash in fonts.hashes
+
+function otf.setdynamics(font,attribute)
+ -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
+ local features = contextsetups[attribute]
+ if features then
+ local dynamics = fontdynamics[font]
+ dynamic = contextmerged[attribute] or 0
+ local script, language
+ if dynamic == 2 then -- merge
+ language = features.language or fontproperties[font].language or "dflt"
+ script = features.script or fontproperties[font].script or "dflt"
+ else -- if dynamic == 1 then -- replace
+ language = features.language or "dflt"
+ script = features.script or "dflt"
+ end
+ if script == "auto" then
+ -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
+ script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
+ end
+ local ds = dynamics[script] -- can be metatable magic (less testing)
+-- or dynamics.dflt
+ if not ds then
+ ds = { }
+ dynamics[script] = ds
+ end
+ local dsl = ds[language]
+-- or ds.dflt
+ if not dsl then
+ dsl = { }
+ ds[language] = dsl
+ end
+ local dsla = dsl[attribute]
+ if not dsla then
+ local tfmdata = fontidentifiers[font]
+ a_to_script [attribute] = script
+ a_to_language[attribute] = language
+ -- we need to save some values .. quite messy
+ local properties = tfmdata.properties
+ local shared = tfmdata.shared
+ local s_script = properties.script
+ local s_language = properties.language
+ local s_mode = properties.mode
+ local s_features = shared.features
+ properties.mode = "node"
+ properties.language = language
+ properties.script = script
+ properties.dynamics = true -- handy for tracing
+ shared.features = { }
+ -- end of save
+ local set = constructors.checkedfeatures("otf",features)
+ set.mode = "node" -- really needed
+ dsla = otf.setfeatures(tfmdata,set)
+ if trace_dynamics then
+ report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set)
+ end
+ -- we need to restore some values
+ properties.script = s_script
+ properties.language = s_language
+ properties.mode = s_mode
+ shared.features = s_features
+ -- end of restore
+ dynamics[script][language][attribute] = dsla -- cache
+ elseif trace_dynamics then
+ -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
+ end
+ return dsla
+ end
+end
+
+function otf.scriptandlanguage(tfmdata,attr)
+ local properties = tfmdata.properties
+ if attr and attr > 0 then
+ return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt"
+ else
+ return properties.script or "dflt", properties.language or "dflt"
+ end
+end
+
+-- we reimplement the dataset resolver
+
+local autofeatures = fonts.analyzers.features
+local featuretypes = otf.tables.featuretypes
+local defaultscript = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
+
+local resolved = { } -- we only resolve a font,script,language,attribute pair once
+local wildcard = "*"
+
+-- what about analyze in local and not in font
+
+-- needs checking: some added features can pass twice
+
+local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
+ local features = sequence.features
+ if features then
+ local order = sequence.order
+ if order then
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do --
+ local kind = order[i] --
+ local e_e
+ local a_e = a_enabled and a_enabled[kind] -- the value (location)
+ if a_e ~= nil then
+ e_e = a_e
+ else
+ e_e = s_enabled and s_enabled[kind] -- the value (font)
+ end
+ if e_e then
+ local scripts = features[kind] --
+ local languages = scripts[script] or scripts[wildcard]
+ if not languages and autoscript then
+ langages = defaultscript(featuretype,autoscript,scripts)
+ end
+ if languages then
+ -- we need detailed control over default becase we want to trace
+ -- only first attribute match check, so we assume simple fina's
+ local valid = false
+ if languages[language] then
+ valid = e_e
+ elseif languages[wildcard] then
+ valid = e_e
+ elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
+ valid = e_e
+ end
+ if valid then
+ local attribute = autofeatures[kind] or false
+ if trace_applied then
+ report_process(
+ "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
+ font,attr or 0,dynamic,kind,script,language,sequence.name,valid)
+ end
+ ra[#ra+1] = { valid, attribute, sequence, kind }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- there is some fuzzy language/script state stuff in properties (temporary)
+
+function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
+
+ local script, language, s_enabled, a_enabled, dynamic
+
+ if attr and attr ~= 0 then
+ dynamic = contextmerged[attr] or 0
+ -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
+ local features = contextsetups[attr]
+ a_enabled = features -- location based
+ if dynamic == 1 then -- or dynamic == -1 then
+ -- replace
+ language = features.language or "dflt"
+ script = features.script or "dflt"
+ elseif dynamic == 2 then -- or dynamic == -2 then
+ -- merge
+ local properties = tfmdata.properties
+ s_enabled = tfmdata.shared.features -- font based
+ language = features.language or properties.language or "dflt"
+ script = features.script or properties.script or "dflt"
+ else
+ -- error
+ local properties = tfmdata.properties
+ language = properties.language or "dflt"
+ script = properties.script or "dflt"
+ end
+ else
+ local properties = tfmdata.properties
+ language = properties.language or "dflt"
+ script = properties.script or "dflt"
+ s_enabled = tfmdata.shared.features -- can be made local to the resolver
+ dynamic = 0
+ end
+
+ local res = resolved[font]
+ if not res then
+ res = { }
+ resolved[font] = res
+ end
+ local rs = res[script]
+ if not rs then
+ rs = { }
+ res[script] = rs
+ end
+ local rl = rs[language]
+ if not rl then
+ rl = { }
+ rs[language] = rl
+ end
+ local ra = rl[attr]
+ if ra == nil then -- attr can be false
+ ra = {
+ -- indexed but we can also add specific data by key in:
+ }
+ rl[attr] = ra
+ local sequences = tfmdata.resources.sequences
+ if sequences then
+ local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
+ local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
+ for s=1,#sequences do
+ initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
+ end
+ end
+ end
+ return ra
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otf.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otf.lua
new file mode 100644
index 00000000000..cbdc79678bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otf.lua
@@ -0,0 +1,3057 @@
+if not modules then modules = { } end modules ['font-otf'] = {
+ 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"
+}
+
+-- langs -> languages enz
+-- anchor_classes vs kernclasses
+-- modification/creationtime in subfont is runtime dus zinloos
+-- to_table -> totable
+-- ascent descent
+
+-- to be checked: combinations like:
+--
+-- current="ABCD" with [A]=nothing, [BC]=ligature, [D]=single (applied to result of BC so funny index)
+--
+-- unlikely but possible
+
+-- more checking against low level calls of functions
+
+local utfbyte = utf.byte
+local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local abs = math.abs
+local reversed, concat, insert, remove, sortedkeys = table.reversed, table.concat, table.insert, table.remove, table.sortedkeys
+local ioflush = io.flush
+local fastcopy, tohash, derivetable, copy = table.fastcopy, table.tohash, table.derive, table.copy
+local formatters = string.formatters
+local P, R, S, C, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.match
+
+local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local registertracker = trackers.register
+local registerdirective = directives.register
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local elapsedtime = statistics.elapsedtime
+local findbinfile = resolvers.findbinfile
+
+local trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+local trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
+local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
+local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
+local trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
+local trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
+local trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
+
+local compact_lookups = true registertracker("otf.compactlookups", function(v) compact_lookups = v end)
+local purge_names = true registertracker("otf.purgenames", function(v) purge_names = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+otf.glists = { "gsub", "gpos" }
+
+otf.version = 2.824 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otf", otf.version, true)
+
+local hashes = fonts.hashes
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local fontdata = hashes and hashes.identifiers
+local chardata = characters and characters.data -- not used
+
+local otffeatures = constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local enhancers = allocate()
+otf.enhancers = enhancers
+local patches = { }
+enhancers.patches = patches
+
+local forceload = false
+local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
+local packdata = true
+local syncspace = true
+local forcenotdef = false
+local includesubfonts = false
+local overloadkerns = false -- experiment
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+local wildcard = "*"
+local default = "dflt"
+
+local fontloader = fontloader
+local open_font = fontloader.open
+local close_font = fontloader.close
+local font_fields = fontloader.fields
+local apply_featurefile = fontloader.apply_featurefile
+
+local mainfields = nil
+local glyphfields = nil -- not used yet
+
+local formats = fonts.formats
+
+formats.otf = "opentype"
+formats.ttf = "truetype"
+formats.ttc = "truetype"
+formats.dfont = "truetype"
+
+registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
+registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
+registerdirective("fonts.otf.loader.pack", function(v) packdata = v end)
+registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+registerdirective("fonts.otf.loader.overloadkerns", function(v) overloadkerns = v end)
+-----------------("fonts.otf.loader.alldimensions", function(v) alldimensions = v end)
+
+function otf.fileformat(filename)
+ local leader = lower(io.loadchunk(filename,4))
+ local suffix = lower(file.suffix(filename))
+ if leader == "otto" then
+ return formats.otf, suffix == "otf"
+ elseif leader == "ttcf" then
+ return formats.ttc, suffix == "ttc"
+ -- elseif leader == "true" then
+ -- return formats.ttf, suffix == "ttf"
+ elseif suffix == "ttc" then
+ return formats.ttc, true
+ elseif suffix == "dfont" then
+ return formats.dfont, true
+ else
+ return formats.ttf, suffix == "ttf"
+ end
+end
+
+-- local function otf_format(filename)
+-- -- return formats[lower(file.suffix(filename))]
+-- end
+
+local function otf_format(filename)
+ local format, okay = otf.fileformat(filename)
+ if not okay then
+ report_otf("font %a is actually an %a file",filename,format)
+ end
+ return format
+end
+
+local function load_featurefile(raw,featurefile)
+ if featurefile and featurefile ~= "" then
+ if trace_loading then
+ report_otf("using featurefile %a", featurefile)
+ end
+ apply_featurefile(raw, featurefile)
+ end
+end
+
+local function showfeatureorder(rawdata,filename)
+ local sequences = rawdata.resources.sequences
+ if sequences and #sequences > 0 then
+ if trace_loading then
+ report_otf("font %a has %s sequences",filename,#sequences)
+ report_otf(" ")
+ end
+ for nos=1,#sequences do
+ local sequence = sequences[nos]
+ local typ = sequence.type or "no-type"
+ local name = sequence.name or "no-name"
+ local subtables = sequence.subtables or { "no-subtables" }
+ local features = sequence.features
+ if trace_loading then
+ report_otf("%3i %-15s %-20s [% t]",nos,name,typ,subtables)
+ end
+ if features then
+ for feature, scripts in next, features do
+ local tt = { }
+ if type(scripts) == "table" then
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = formatters["[%s: % t]"](script,ttt)
+ end
+ if trace_loading then
+ report_otf(" %s: % t",feature,tt)
+ end
+ else
+ if trace_loading then
+ report_otf(" %s: %S",feature,scripts)
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("\n")
+ end
+ elseif trace_loading then
+ report_otf("font %a has no sequences",filename)
+ end
+end
+
+--[[ldx--
+<p>We start with a lot of tables and related functions.</p>
+--ldx]]--
+
+local valid_fields = table.tohash {
+ -- "anchor_classes",
+ "ascent",
+ -- "cache_version",
+ "cidinfo",
+ "copyright",
+ -- "creationtime",
+ "descent",
+ "design_range_bottom",
+ "design_range_top",
+ "design_size",
+ "encodingchanged",
+ "extrema_bound",
+ "familyname",
+ "fontname",
+ "fontstyle_id",
+ "fontstyle_name",
+ "fullname",
+ -- "glyphs",
+ "hasvmetrics",
+ -- "head_optimized_for_cleartype",
+ "horiz_base",
+ "issans",
+ "isserif",
+ "italicangle",
+ -- "kerns",
+ -- "lookups",
+ "macstyle",
+ -- "modificationtime",
+ "notdef_loc",
+ "onlybitmaps",
+ "origname",
+ "os2_version",
+ "pfminfo",
+ -- "private",
+ "serifcheck",
+ "sfd_version",
+ -- "size",
+ "strokedfont",
+ "strokewidth",
+ -- "subfonts",
+ "table_version",
+ -- "tables",
+ -- "ttf_tab_saved",
+ "ttf_tables",
+ "uni_interp",
+ "uniqueid",
+ "units_per_em",
+ "upos",
+ "use_typo_metrics",
+ "uwidth",
+ "validation_state",
+ "version",
+ "vert_base",
+ "weight",
+ "weight_width_slope_only",
+ -- "xuid",
+ -- "truetype", -- maybe as check
+}
+
+local ordered_enhancers = {
+ "prepare tables",
+
+ "prepare glyphs",
+ "prepare lookups",
+
+ "analyze glyphs",
+ "analyze math",
+
+ -- "prepare tounicode",
+
+ "reorganize lookups",
+ "reorganize mark classes",
+ "reorganize anchor classes",
+
+ "reorganize glyph kerns",
+ "reorganize glyph lookups",
+ "reorganize glyph anchors",
+
+ "merge kern classes",
+
+ "reorganize features",
+ "reorganize subtables",
+
+ "check glyphs",
+ "check metadata",
+
+ "prepare tounicode",
+
+ "check encoding", -- moved
+ "add duplicates",
+
+ "expand lookups", -- a temp hack awaiting the lua loader
+
+ "check extra features", -- after metadata and duplicates
+
+ "cleanup tables",
+
+ "compact lookups",
+ "purge names",
+}
+
+--[[ldx--
+<p>Here we go.</p>
+--ldx]]--
+
+local actions = allocate()
+local before = allocate()
+local after = allocate()
+
+patches.before = before
+patches.after = after
+
+local function enhance(name,data,filename,raw)
+ local enhancer = actions[name]
+ if enhancer then
+ if trace_loading then
+ report_otf("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ -- no message as we can have private ones
+ end
+end
+
+function enhancers.apply(data,filename,raw)
+ local basename = file.basename(lower(filename))
+ if trace_loading then
+ report_otf("%s enhancing file %a","start",filename)
+ end
+ ioflush() -- we want instant messages
+ for e=1,#ordered_enhancers do
+ local enhancer = ordered_enhancers[e]
+ local b = before[enhancer]
+ if b then
+ for pattern, action in next, b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a = after[enhancer]
+ if a then
+ for pattern, action in next, a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush() -- we want instant messages
+ end
+ if trace_loading then
+ report_otf("%s enhancing file %a","stop",filename)
+ end
+ ioflush() -- we want instant messages
+end
+
+-- patches.register("before","migrate metadata","cambria",function() end)
+
+function patches.register(what,where,pattern,action)
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
+ end
+end
+
+function patches.report(fmt,...)
+ if trace_loading then
+ report_otf("patching: %s",formatters[fmt](...))
+ end
+end
+
+function enhancers.register(what,action) -- only already registered can be overloaded
+ actions[what] = action
+end
+
+function otf.load(filename,sub,featurefile) -- second argument (format) is gone !
+ local base = file.basename(file.removesuffix(filename))
+ local name = file.removesuffix(base)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ if featurefile then
+ name = name .. "@" .. file.removesuffix(file.basename(featurefile))
+ end
+ -- or: sub = tonumber(sub)
+ if sub == "" then
+ sub = false
+ end
+ local hash = name
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ hash = containers.cleanname(hash)
+ local featurefiles
+ if featurefile then
+ featurefiles = { }
+ for s in gmatch(featurefile,"[^,]+") do
+ local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
+ if name == "" then
+ report_otf("loading error, no featurefile %a",s)
+ else
+ local attr = lfs.attributes(name)
+ featurefiles[#featurefiles+1] = {
+ name = name,
+ size = attr and attr.size or 0,
+ time = attr and attr.modification or 0,
+ }
+ end
+ end
+ if #featurefiles == 0 then
+ featurefiles = nil
+ end
+ end
+ local data = containers.read(otf.cache,hash)
+ local reload = not data or data.size ~= size or data.time ~= time
+ if forceload then
+ report_otf("forced reload of %a due to hard coded flag",filename)
+ reload = true
+ end
+ if not reload then
+ local featuredata = data.featuredata
+ if featurefiles then
+ if not featuredata or #featuredata ~= #featurefiles then
+ reload = true
+ else
+ for i=1,#featurefiles do
+ local fi, fd = featurefiles[i], featuredata[i]
+ if fi.name ~= fd.name or fi.size ~= fd.size or fi.time ~= fd.time then
+ reload = true
+ break
+ end
+ end
+ end
+ elseif featuredata then
+ reload = true
+ end
+ if reload then
+ report_otf("loading: forced reload due to changed featurefile specification %a",featurefile)
+ end
+ end
+ if reload then
+ starttiming("fontloader")
+ report_otf("loading %a, hash %a",filename,hash)
+ local fontdata, messages
+ if sub then
+ fontdata, messages = open_font(filename,sub)
+ else
+ fontdata, messages = open_font(filename)
+ end
+ if fontdata then
+ mainfields = mainfields or (font_fields and font_fields(fontdata))
+ end
+ if trace_loading and messages and #messages > 0 then
+ if type(messages) == "string" then
+ report_otf("warning: %s",messages)
+ else
+ for m=1,#messages do
+ report_otf("warning: %S",messages[m])
+ end
+ end
+ else
+ report_otf("loading done")
+ end
+ if fontdata then
+ if featurefiles then
+ for i=1,#featurefiles do
+ load_featurefile(fontdata,featurefiles[i].name)
+ end
+ end
+ local unicodes = {
+ -- names to unicodes
+ }
+ local splitter = lpeg.splitter(" ",unicodes)
+ data = {
+ size = size,
+ time = time,
+ subfont = sub,
+ format = otf_format(filename),
+ featuredata = featurefiles,
+ resources = {
+ filename = resolvers.unresolve(filename), -- no shortcut
+ version = otf.version,
+ creator = "context mkiv",
+ unicodes = unicodes,
+ indices = {
+ -- index to unicodes
+ },
+ duplicates = {
+ -- alternative unicodes
+ },
+ variants = {
+ -- alternative unicodes (variants)
+ },
+ lookuptypes = {
+ },
+ },
+ warnings = {
+ },
+ metadata = {
+ -- raw metadata, not to be used
+ },
+ properties = {
+ -- normalized metadata
+ },
+ descriptions = {
+ },
+ goodies = {
+ },
+ helpers = { -- might go away
+ tounicodelist = splitter,
+ tounicodetable = Ct(splitter),
+ },
+ }
+ report_otf("file size: %s", size)
+ enhancers.apply(data,filename,fontdata)
+ local packtime = { }
+ if packdata then
+ if cleanup > 0 then
+ collectgarbage("collect")
+ end
+ starttiming(packtime)
+ enhance("pack",data,filename,nil)
+ stoptiming(packtime)
+ end
+ report_otf("saving %a in cache",filename)
+ data = containers.write(otf.cache, hash, data)
+ if cleanup > 1 then
+ collectgarbage("collect")
+ end
+ stoptiming("fontloader")
+ if elapsedtime then -- not in generic
+ report_otf("loading, optimizing, packing and caching time %s, pack time %s",
+ elapsedtime("fontloader"),packdata and elapsedtime(packtime) or 0)
+ end
+ close_font(fontdata) -- free memory
+ if cleanup > 3 then
+ collectgarbage("collect")
+ end
+ data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
+ if cleanup > 2 then
+ collectgarbage("collect")
+ end
+ else
+ stoptiming("fontloader")
+ data = nil
+ report_otf("loading failed due to read error")
+ end
+ end
+ if data then
+ if trace_defining then
+ report_otf("loading from cache using hash %a",hash)
+ end
+ enhance("unpack",data,filename,nil,false)
+ --
+ local resources = data.resources
+ local lookuptags = resources.lookuptags
+ local unicodes = resources.unicodes
+ if not lookuptags then
+ lookuptags = { }
+ resources.lookuptags = lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v = type(k) == "number" and ("lookup " .. k) or k
+ t[k] = v
+ return v
+ end)
+ if not unicodes then
+ unicodes = { }
+ resources.unicodes = unicodes
+ setmetatableindex(unicodes,function(t,k)
+ -- use rawget when no table has to be built
+ setmetatableindex(unicodes,nil)
+ for u, d in next, data.descriptions do
+ local n = d.name
+ if n then
+ t[n] = u
+ -- report_otf("accessing known name %a",k)
+ else
+ -- report_otf("accessing unknown name %a",k)
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes) -- do we really need this?
+ --
+ if applyruntimefixes then
+ applyruntimefixes(filename,data)
+ end
+ enhance("add dimensions",data,filename,nil,false)
+ if trace_sequences then
+ showfeatureorder(data,filename)
+ end
+ end
+ return data
+end
+
+local mt = {
+ __index = function(t,k) -- maybe set it
+ if k == "height" then
+ local ht = t.boundingbox[4]
+ return ht < 0 and 0 or ht
+ elseif k == "depth" then
+ local dp = -t.boundingbox[2]
+ return dp < 0 and 0 or dp
+ elseif k == "width" then
+ return 0
+ elseif k == "name" then -- or maybe uni*
+ return forcenotdef and ".notdef"
+ end
+ end
+}
+
+actions["prepare tables"] = function(data,filename,raw)
+ data.properties.hasitalics = false
+end
+
+actions["add dimensions"] = function(data,filename)
+ -- todo: forget about the width if it's the defaultwidth (saves mem)
+ -- we could also build the marks hash here (instead of storing it)
+ if data then
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local defaultwidth = resources.defaultwidth or 0
+ local defaultheight = resources.defaultheight or 0
+ local defaultdepth = resources.defaultdepth or 0
+ local basename = trace_markwidth and file.basename(filename)
+ for _, d in next, descriptions do
+ local bb, wd = d.boundingbox, d.width
+ if not wd then
+ -- or bb?
+ d.width = defaultwidth
+ elseif trace_markwidth and wd ~= 0 and d.class == "mark" then
+ report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
+ -- d.width = -wd
+ end
+ if bb then
+ local ht = bb[4]
+ local dp = -bb[2]
+ -- if alldimensions then
+ -- if ht ~= 0 then
+ -- d.height = ht
+ -- end
+ -- if dp ~= 0 then
+ -- d.depth = dp
+ -- end
+ -- else
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ -- end
+ end
+ end
+ end
+end
+
+local function somecopy(old) -- fast one
+ if old then
+ local new = { }
+ if type(old) == "table" then
+ for k, v in next, old do
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
+ else
+ new[k] = v
+ end
+ end
+ else
+ for i=1,#mainfields do
+ local k = mainfields[i]
+ local v = old[k]
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
+ else
+ new[k] = v
+ end
+ end
+ end
+ return new
+ else
+ return { }
+ end
+end
+
+-- not setting hasitalics and class (when nil) during table construction can save some mem
+
+actions["prepare glyphs"] = function(data,filename,raw)
+ local rawglyphs = raw.glyphs
+ local rawsubfonts = raw.subfonts
+ local rawcidinfo = raw.cidinfo
+ local criterium = constructors.privateoffset
+ local private = criterium
+ local resources = data.resources
+ local metadata = data.metadata
+ local properties = data.properties
+ local descriptions = data.descriptions
+ local unicodes = resources.unicodes -- name to unicode
+ local indices = resources.indices -- index to unicode
+ local duplicates = resources.duplicates
+ local variants = resources.variants
+ local notdefindex = -1
+
+ if rawsubfonts then
+
+ metadata.subfonts = includesubfonts and { }
+ properties.cidinfo = rawcidinfo
+
+ if rawcidinfo.registry then
+ local cidmap = fonts.cid.getmap(rawcidinfo)
+ if cidmap then
+ rawcidinfo.usedname = cidmap.usedname
+ local nofnames = 0
+ local nofunicodes = 0
+ local cidunicodes = cidmap.unicodes
+ local cidnames = cidmap.names
+ local cidtotal = 0
+ local unique = trace_subfonts and { }
+ for cidindex=1,#rawsubfonts do
+ local subfont = rawsubfonts[cidindex]
+ local cidglyphs = subfont.glyphs
+ if includesubfonts then
+ metadata.subfonts[cidindex] = somecopy(subfont)
+ end
+ local cidcnt = subfont.glyphcnt
+ local cidmin = subfont.glyphmin
+ local cidmax = subfont.glyphmax
+ local notdef = (tonumber(raw.table_version) or 0) > 0.4 and subfont.notdef_loc or -1
+ if notdeffound == -1 and notdef >= 0 then
+ notdeffound = notdef
+ end
+ if trace_subfonts then
+ local cidtot = cidmax - cidmin + 1
+ cidtotal = cidtotal + cidtot
+ report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+ end
+ if cidcnt > 0 then
+ for index=cidmin,cidmax do
+ local glyph = cidglyphs[index]
+ if glyph then
+ if trace_subfonts then
+ unique[index] = true
+ end
+ local unicode = glyph.unicode
+ if unicode >= 0x00E000 and unicode <= 0x00F8FF then
+ unicode = -1
+ elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
+ unicode = -1
+ elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
+ unicode = -1
+ end
+ local name = glyph.name or cidnames[index]
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ unicode = cidunicodes[index]
+ end
+ if unicode and descriptions[unicode] then
+ if trace_private then
+ report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ end
+ unicode = -1
+ end
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ if not name then
+ name = formatters["u%06X.ctx"](private)
+ end
+ unicode = private
+ unicodes[name] = private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private = private + 1
+ nofnames = nofnames + 1
+ else
+ -- if unicode > criterium then
+ -- local taken = descriptions[unicode]
+ -- if taken then
+ -- private = private + 1
+ -- descriptions[private] = taken
+ -- unicodes[taken.name] = private
+ -- indices[taken.index] = private
+ -- if trace_private then
+ -- report_otf("slot %U is moved to %U due to private in font",unicode)
+ -- end
+ -- end
+ -- end
+ if not name then
+ name = formatters["u%06X.ctx"](unicode)
+ end
+ unicodes[name] = unicode
+ nofunicodes = nofunicodes + 1
+ end
+ indices[index] = unicode -- each index is unique (at least now)
+ local description = {
+ -- width = glyph.width,
+ boundingbox = glyph.boundingbox,
+ -- name = glyph.name or name or "unknown", -- uniXXXX
+ name = name or "unknown", -- uniXXXX
+ -- cidindex = cidindex,
+ index = index,
+ glyph = glyph,
+ }
+ descriptions[unicode] = description
+ local altuni = glyph.altuni
+ if altuni then
+ -- local d
+ for i=1,#altuni do
+ local a = altuni[i]
+ local u = a.unicode
+ if u ~= unicode then
+ local v = a.variant
+ if v then
+ -- tricky: no addition to d? needs checking but in practice such dups are either very simple
+ -- shapes or e.g cjk with not that many features
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ -- elseif d then
+ -- d[#d+1] = u
+ -- else
+ -- d = { u }
+ end
+ end
+ end
+ -- if d then
+ -- duplicates[unicode] = d -- is this needed ?
+ -- end
+ end
+ end
+ end
+ else
+ report_otf("potential problem: no glyphs found in subfont %i",cidindex)
+ end
+ end
+ if trace_subfonts then
+ report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+ end
+ if trace_loading then
+ report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ end
+ elseif trace_loading then
+ report_otf("unable to remap cid font, missing cid file for %a",filename)
+ end
+ elseif trace_loading then
+ report_otf("font %a has no glyphs",filename)
+ end
+
+ else
+
+ local cnt = raw.glyphcnt or 0
+ local min = raw.glyphmin or 0
+ local max = raw.glyphmax or (raw.glyphcnt - 1)
+ notdeffound = (tonumber(raw.table_version) or 0) > 0.4 and raw.notdef_loc or -1
+ if cnt > 0 then
+ for index=min,max do
+ local glyph = rawglyphs[index]
+ if glyph then
+ local unicode = glyph.unicode
+ local name = glyph.name
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ unicode = private
+ unicodes[name] = private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private = private + 1
+ else
+ -- We have a font that uses and exposes the private area. As this is rather unreliable it's
+ -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
+ -- we need to move already moved entries and we also need to bump the next private to after
+ -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
+ if unicode > criterium then
+ -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
+ local taken = descriptions[unicode]
+ if taken then
+ if unicode >= private then
+ private = unicode + 1 -- restart private (so we can have mixed now)
+ else
+ private = private + 1 -- move on
+ end
+ descriptions[private] = taken
+ unicodes[taken.name] = private
+ indices[taken.index] = private
+ if trace_private then
+ report_otf("slot %U is moved to %U due to private in font",unicode)
+ end
+ else
+ if unicode >= private then
+ private = unicode + 1 -- restart (so we can have mixed now)
+ end
+ end
+ end
+ unicodes[name] = unicode
+ end
+ indices[index] = unicode
+ -- if not name then
+ -- name = formatters["u%06X"](unicode) -- u%06X.ctx
+ -- end
+ descriptions[unicode] = {
+ -- width = glyph.width,
+ boundingbox = glyph.boundingbox,
+ name = name,
+ index = index,
+ glyph = glyph,
+ }
+ local altuni = glyph.altuni
+ if altuni then
+ -- local d
+ for i=1,#altuni do
+ local a = altuni[i]
+ local u = a.unicode
+ if u ~= unicode then
+ local v = a.variant
+ if v then
+ -- tricky: no addition to d? needs checking but in practice such dups are either very simple
+ -- shapes or e.g cjk with not that many features
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ -- elseif d then
+ -- d[#d+1] = u
+ -- else
+ -- d = { u }
+ end
+ end
+ end
+ -- if d then
+ -- duplicates[unicode] = d -- is this needed ?
+ -- end
+ end
+ else
+ report_otf("potential problem: glyph %U is used but empty",index)
+ end
+ end
+ else
+ report_otf("potential problem: no glyphs found")
+ end
+
+ end
+
+ if notdeffound == -1 then
+ report_otf("warning: no .notdef found in %a",filename)
+ elseif notdeffound ~= 0 then
+ report_otf("warning: .notdef found at position %a in %a",notdeffound,filename)
+ end
+ metadata.notdef = notdeffound
+
+ resources.private = private
+
+end
+
+-- the next one is still messy but will get better when we have
+-- flattened map/enc tables in the font loader
+
+-- the next one is not using a valid base for unicode privates
+--
+-- PsuedoEncodeUnencoded(EncMap *map,struct ttfinfo *info)
+
+actions["check encoding"] = function(data,filename,raw)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local properties = data.properties
+ local unicodes = resources.unicodes -- name to unicode
+ local indices = resources.indices -- index to unicodes
+ local duplicates = resources.duplicates
+
+ -- begin of messy (not needed when cidmap)
+
+ local mapdata = raw.map or { }
+ local unicodetoindex = mapdata and mapdata.map or { }
+ local indextounicode = mapdata and mapdata.backmap or { }
+ -- local encname = lower(data.enc_name or raw.enc_name or mapdata.enc_name or "")
+ local encname = lower(data.enc_name or mapdata.enc_name or "")
+ local criterium = 0xFFFF -- for instance cambria has a lot of mess up there
+ local privateoffset = constructors.privateoffset
+
+ -- end of messy
+
+ if find(encname,"unicode") then -- unicodebmp, unicodefull, ...
+ if trace_loading then
+ report_otf("checking embedded unicode map %a",encname)
+ end
+ local reported = { }
+ -- we loop over the original unicode->index mapping but we
+ -- need to keep in mind that that one can have weird entries
+ -- so we need some extra checking
+ for maybeunicode, index in next, unicodetoindex do
+ if descriptions[maybeunicode] then
+ -- we ignore invalid unicodes (unicode = -1) (ff can map wrong to non private)
+ else
+ local unicode = indices[index]
+ if not unicode then
+ -- weird (cjk or so?)
+ elseif maybeunicode == unicode then
+ -- no need to add
+ elseif unicode > privateoffset then
+ -- we have a non-unicode
+ else
+ local d = descriptions[unicode]
+ if d then
+ local c = d.copies
+ if c then
+ c[maybeunicode] = true
+ else
+ d.copies = { [maybeunicode] = true }
+ end
+ elseif index and not reported[index] then
+ report_otf("missing index %i",index)
+ reported[index] = true
+ end
+ end
+ end
+ end
+ for unicode, data in next, descriptions do
+ local d = data.copies
+ if d then
+ duplicates[unicode] = sortedkeys(d)
+ data.copies = nil
+ end
+ end
+ elseif properties.cidinfo then
+ report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname)
+ else
+ report_otf("warning: non unicode map %a, only using glyph unicode data",encname or "whatever")
+ end
+
+ if mapdata then
+ mapdata.map = { } -- clear some memory (virtual and created each time anyway)
+ mapdata.backmap = { } -- clear some memory (virtual and created each time anyway)
+ end
+end
+
+-- for the moment we assume that a font with lookups will not use
+-- altuni so we stick to kerns only .. alternatively we can always
+-- do an indirect lookup uni_to_uni . but then we need that in
+-- all lookups
+
+actions["add duplicates"] = function(data,filename,raw)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local properties = data.properties
+ local unicodes = resources.unicodes -- name to unicode
+ local indices = resources.indices -- index to unicodes
+ local duplicates = resources.duplicates
+ -- for unicode, d in next, duplicates do
+ for unicode, d in table.sortedhash(duplicates) do -- nicer for log
+ local nofduplicates = #d
+ if nofduplicates > 4 then
+ if trace_loading then
+ report_otf("ignoring excessive duplicates of %U (n=%s)",unicode,nofduplicates)
+ end
+ else
+ -- local validduplicates = { }
+ for i=1,nofduplicates do
+ local u = d[i]
+ if not descriptions[u] then
+ local description = descriptions[unicode]
+ local n = 0
+ for _, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ for _, k in next, kerns do
+ local ku = k[unicode]
+ if ku then
+ k[u] = ku
+ n = n + 1
+ end
+ end
+ end
+ -- todo: lookups etc
+ end
+ if u > 0 then -- and
+ local duplicate = copy(description) -- else packing problem
+ duplicate.comment = formatters["copy of %U"](unicode)
+ descriptions[u] = duplicate
+ -- validduplicates[#validduplicates+1] = u
+ if trace_loading then
+ report_otf("duplicating %06U to %06U with index %H (%s kerns)",unicode,u,description.index,n)
+ end
+ end
+ end
+ end
+ -- duplicates[unicode] = #validduplicates > 0 and validduplicates or nil
+ end
+ end
+end
+
+-- class : nil base mark ligature component (maybe we don't need it in description)
+-- boundingbox: split into ht/dp takes more memory (larger tables and less sharing)
+
+actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this in the previous
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local metadata = data.metadata
+ local properties = data.properties
+ local hasitalics = false
+ local widths = { }
+ local marks = { } -- always present (saves checking)
+ for unicode, description in next, descriptions do
+ local glyph = description.glyph
+ local italic = glyph.italic_correction -- only in a math font (we also have vert/horiz)
+ if not italic then
+ -- skip
+ elseif italic == 0 then
+ -- skip
+ else
+ description.italic = italic
+ hasitalics = true
+ end
+ local width = glyph.width
+ widths[width] = (widths[width] or 0) + 1
+ local class = glyph.class
+ if class then
+ if class == "mark" then
+ marks[unicode] = true
+ end
+ description.class = class
+ end
+ end
+ -- flag italic
+ properties.hasitalics = hasitalics
+ -- flag marks
+ resources.marks = marks
+ -- share most common width for cjk fonts
+ local wd, most = 0, 1
+ for k,v in next, widths do
+ if v > most then
+ wd, most = k, v
+ end
+ end
+ if most > 1000 then -- maybe 500
+ if trace_loading then
+ report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
+ end
+ for unicode, description in next, descriptions do
+ if description.width == wd then
+ -- description.width = nil
+ else
+ description.width = description.glyph.width
+ end
+ end
+ resources.defaultwidth = wd
+ else
+ for unicode, description in next, descriptions do
+ description.width = description.glyph.width
+ end
+ end
+end
+
+actions["reorganize mark classes"] = function(data,filename,raw)
+ local mark_classes = raw.mark_classes
+ if mark_classes then
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ local markclasses = { }
+ resources.markclasses = markclasses -- reversed
+ for name, class in next, mark_classes do
+ local t = { }
+ for s in gmatch(class,"[^ ]+") do
+ t[unicodes[s]] = true
+ end
+ markclasses[name] = t
+ end
+ end
+end
+
+actions["reorganize features"] = function(data,filename,raw) -- combine with other
+ local features = { }
+ data.resources.features = features
+ for k=1,#otf.glists do
+ local what = otf.glists[k]
+ local dw = raw[what]
+ if dw then
+ local f = { }
+ features[what] = f
+ for i=1,#dw do
+ local d= dw[i]
+ local dfeatures = d.features
+ if dfeatures then
+ for i=1,#dfeatures do
+ local df = dfeatures[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag]
+ if not ft then
+ ft = { }
+ f[tag] = ft
+ end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+actions["reorganize anchor classes"] = function(data,filename,raw)
+ local resources = data.resources
+ local anchor_to_lookup = { }
+ local lookup_to_anchor = { }
+ resources.anchor_to_lookup = anchor_to_lookup
+ resources.lookup_to_anchor = lookup_to_anchor
+ local classes = raw.anchor_classes -- anchor classes not in final table
+ if classes then
+ for c=1,#classes do
+ local class = classes[c]
+ local anchor = class.name
+ local lookups = class.lookup
+ if type(lookups) ~= "table" then
+ lookups = { lookups }
+ end
+ local a = anchor_to_lookup[anchor]
+ if not a then
+ a = { }
+ anchor_to_lookup[anchor] = a
+ end
+ for l=1,#lookups do
+ local lookup = lookups[l]
+ local l = lookup_to_anchor[lookup]
+ if l then
+ l[anchor] = true
+ else
+ l = { [anchor] = true }
+ lookup_to_anchor[lookup] = l
+ end
+ a[lookup] = true
+ end
+ end
+ end
+end
+
+-- local function checklookups(data,missing,nofmissing)
+-- local resources = data.resources
+-- local unicodes = resources.unicodes
+-- local lookuptypes = resources.lookuptypes
+-- if not unicodes or not lookuptypes then
+-- return
+-- elseif nofmissing <= 0 then
+-- return
+-- end
+-- local descriptions = data.descriptions
+-- local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+-- --
+-- local ns, nl = 0, 0
+
+-- local guess = { }
+-- -- helper
+-- local function check(gname,code,unicode)
+-- local description = descriptions[code]
+-- -- no need to add a self reference
+-- local variant = description.name
+-- if variant == gname then
+-- return
+-- end
+-- -- the variant already has a unicode (normally that results in a default tounicode to self)
+-- local unic = unicodes[variant]
+-- if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
+-- -- no default mapping and therefore maybe no tounicode yet
+-- else
+-- return
+-- end
+-- -- the variant already has a tounicode
+-- if descriptions[code].unicode then
+-- return
+-- end
+-- -- add to the list
+-- local g = guess[variant]
+-- -- local r = overloads[unicode]
+-- -- if r then
+-- -- unicode = r.unicode
+-- -- end
+-- if g then
+-- g[gname] = unicode
+-- else
+-- guess[variant] = { [gname] = unicode }
+-- end
+-- end
+-- --
+-- for unicode, description in next, descriptions do
+-- local slookups = description.slookups
+-- if slookups then
+-- local gname = description.name
+-- for tag, data in next, slookups do
+-- local lookuptype = lookuptypes[tag]
+-- if lookuptype == "alternate" then
+-- for i=1,#data do
+-- check(gname,data[i],unicode)
+-- end
+-- elseif lookuptype == "substitution" then
+-- check(gname,data,unicode)
+-- end
+-- end
+-- end
+-- local mlookups = description.mlookups
+-- if mlookups then
+-- local gname = description.name
+-- for tag, list in next, mlookups do
+-- local lookuptype = lookuptypes[tag]
+-- if lookuptype == "alternate" then
+-- for i=1,#list do
+-- local data = list[i]
+-- for i=1,#data do
+-- check(gname,data[i],unicode)
+-- end
+-- end
+-- elseif lookuptype == "substitution" then
+-- for i=1,#list do
+-- check(gname,list[i],unicode)
+-- end
+-- end
+-- end
+-- end
+-- end
+-- -- resolve references
+-- local done = true
+-- while done do
+-- done = false
+-- for k, v in next, guess do
+-- if type(v) ~= "number" then
+-- for kk, vv in next, v do
+-- if vv == -1 or vv >= private or (vv >= 0xE000 and vv <= 0xF8FF) or vv == 0xFFFE or vv == 0xFFFF then
+-- local uu = guess[kk]
+-- if type(uu) == "number" then
+-- guess[k] = uu
+-- done = true
+-- end
+-- else
+-- guess[k] = vv
+-- done = true
+-- end
+-- end
+-- end
+-- end
+-- end
+-- -- wrap up
+-- local orphans = 0
+-- local guessed = 0
+-- for k, v in next, guess do
+-- if type(v) == "number" then
+-- descriptions[unicodes[k]].unicode = descriptions[v].unicode or v -- can also be a table
+-- guessed = guessed + 1
+-- else
+-- local t = nil
+-- local l = lower(k)
+-- local u = unicodes[l]
+-- if not u then
+-- orphans = orphans + 1
+-- elseif u == -1 or u >= private or (u >= 0xE000 and u <= 0xF8FF) or u == 0xFFFE or u == 0xFFFF then
+-- local unicode = descriptions[u].unicode
+-- if unicode then
+-- descriptions[unicodes[k]].unicode = unicode
+-- guessed = guessed + 1
+-- else
+-- orphans = orphans + 1
+-- end
+-- else
+-- orphans = orphans + 1
+-- end
+-- end
+-- end
+-- if trace_loading and orphans > 0 or guessed > 0 then
+-- report_otf("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
+-- end
+-- end
+
+actions["prepare tounicode"] = function(data,filename,raw)
+ fonts.mappings.addtounicode(data,filename)
+end
+
+local g_directions = {
+ gsub_contextchain = 1,
+ gpos_contextchain = 1,
+ -- gsub_context = 1,
+ -- gpos_context = 1,
+ gsub_reversecontextchain = -1,
+ gpos_reversecontextchain = -1,
+}
+-- The following is no longer needed as AAT is ignored per end October 2013.
+--
+-- -- Research by Khaled Hosny has demonstrated that the font loader merges
+-- -- regular and AAT features and that these can interfere (especially because
+-- -- we dropped checking for valid features elsewhere. So, we just check for
+-- -- the special flag and drop the feature if such a tag is found.
+--
+-- local function supported(features)
+-- for i=1,#features do
+-- if features[i].ismac then
+-- return false
+-- end
+-- end
+-- return true
+-- end
+
+actions["reorganize subtables"] = function(data,filename,raw)
+ local resources = data.resources
+ local sequences = { }
+ local lookups = { }
+ local chainedfeatures = { }
+ resources.sequences = sequences
+ resources.lookups = lookups -- we also have lookups in data itself
+ for k=1,#otf.glists do
+ local what = otf.glists[k]
+ local dw = raw[what]
+ if dw then
+ for k=1,#dw do
+ local gk = dw[k]
+ local features = gk.features
+ -- if not features or supported(features) then -- not always features !
+ local typ = gk.type
+ local chain = g_directions[typ] or 0
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ t[s] = subtables[s].name
+ end
+ subtables = t
+ end
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = resources.markclasses[markclass]
+ end
+ flags = t
+ end
+ --
+ local name = gk.name
+ --
+ if not name then
+ -- in fact an error
+ report_otf("skipping weird lookup number %s",k)
+ elseif features then
+ -- scripts, tag, ismac
+ local f = { }
+ local o = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag]
+ if not ft then
+ ft = { }
+ f[tag] = ft
+ o[#o+1] = tag
+ end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
+ end
+ end
+ end
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ order = o,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
+ end
+ -- end
+ end
+ end
+ end
+end
+
+actions["prepare lookups"] = function(data,filename,raw)
+ local lookups = raw.lookups
+ if lookups then
+ data.lookups = lookups
+ end
+end
+
+-- The reverse handler does a bit redundant splitting but it's seldom
+-- seen so we don't bother too much. We could store the replacement
+-- in the current list (value instead of true) but it makes other code
+-- uglier. Maybe some day.
+
+local function t_uncover(splitter,cache,covers)
+ local result = { }
+ for n=1,#covers do
+ local cover = covers[n]
+ local uncovered = cache[cover]
+ if not uncovered then
+ uncovered = lpegmatch(splitter,cover)
+ cache[cover] = uncovered
+ end
+ result[n] = uncovered
+ end
+ return result
+end
+
+local function s_uncover(splitter,cache,cover)
+ if cover == "" then
+ return nil
+ else
+ local uncovered = cache[cover]
+ if not uncovered then
+ uncovered = lpegmatch(splitter,cover)
+ -- for i=1,#uncovered do
+ -- uncovered[i] = { [uncovered[i]] = true }
+ -- end
+ cache[cover] = uncovered
+ end
+ return { uncovered }
+ end
+end
+
+local function t_hashed(t,cache)
+ if t then
+ local ht = { }
+ for i=1,#t do
+ local ti = t[i]
+ local tih = cache[ti]
+ if not tih then
+ local tn = #ti
+ if tn == 1 then
+ tih = { [ti[1]] = true }
+ else
+ tih = { }
+ for i=1,tn do
+ tih[ti[i]] = true
+ end
+ end
+ cache[ti] = tih
+ end
+ ht[i] = tih
+ end
+ return ht
+ else
+ return nil
+ end
+end
+
+-- local s_hashed = t_hashed
+
+local function s_hashed(t,cache)
+ if t then
+ local tf = t[1]
+ local nf = #tf
+ if nf == 1 then
+ return { [tf[1]] = true }
+ else
+ local ht = { }
+ for i=1,nf do
+ ht[i] = { [tf[i]] = true }
+ end
+ return ht
+ end
+ else
+ return nil
+ end
+end
+
+local function r_uncover(splitter,cache,cover,replacements)
+ if cover == "" then
+ return nil
+ else
+ -- we always have current as { } even in the case of one
+ local uncovered = cover[1]
+ local replaced = cache[replacements]
+ if not replaced then
+ replaced = lpegmatch(splitter,replacements)
+ cache[replacements] = replaced
+ end
+ local nu, nr = #uncovered, #replaced
+ local r = { }
+ if nu == nr then
+ for i=1,nu do
+ r[uncovered[i]] = replaced[i]
+ end
+ end
+ return r
+ end
+end
+
+actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
+ -- we prefer the before lookups in a normal order
+ if data.lookups then
+ local helpers = data.helpers
+ local duplicates = data.resources.duplicates
+ local splitter = helpers.tounicodetable
+ local t_u_cache = { }
+ local s_u_cache = t_u_cache -- string keys
+ local t_h_cache = { }
+ local s_h_cache = t_h_cache -- table keys (so we could use one cache)
+ local r_u_cache = { } -- maybe shared
+ helpers.matchcache = t_h_cache -- so that we can add duplicates
+ --
+ for _, lookup in next, data.lookups do
+ local rules = lookup.rules
+ if rules then
+ local format = lookup.format
+ if format == "class" then
+ local before_class = lookup.before_class
+ if before_class then
+ before_class = t_uncover(splitter,t_u_cache,reversed(before_class))
+ end
+ local current_class = lookup.current_class
+ if current_class then
+ current_class = t_uncover(splitter,t_u_cache,current_class)
+ end
+ local after_class = lookup.after_class
+ if after_class then
+ after_class = t_uncover(splitter,t_u_cache,after_class)
+ end
+ for i=1,#rules do
+ local rule = rules[i]
+ local class = rule.class
+ local before = class.before
+ if before then
+ for i=1,#before do
+ before[i] = before_class[before[i]] or { }
+ end
+ rule.before = t_hashed(before,t_h_cache)
+ end
+ local current = class.current
+ local lookups = rule.lookups
+ if current then
+ for i=1,#current do
+ current[i] = current_class[current[i]] or { }
+ -- let's not be sparse
+ if lookups and not lookups[i] then
+ lookups[i] = "" -- (was: false) e.g. we can have two lookups and one replacement
+ end
+ -- end of fix
+ end
+ rule.current = t_hashed(current,t_h_cache)
+ end
+ local after = class.after
+ if after then
+ for i=1,#after do
+ after[i] = after_class[after[i]] or { }
+ end
+ rule.after = t_hashed(after,t_h_cache)
+ end
+ rule.class = nil
+ end
+ lookup.before_class = nil
+ lookup.current_class = nil
+ lookup.after_class = nil
+ lookup.format = "coverage"
+ elseif format == "coverage" then
+ for i=1,#rules do
+ local rule = rules[i]
+ local coverage = rule.coverage
+ if coverage then
+ local before = coverage.before
+ if before then
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
+ end
+ local current = coverage.current
+ if current then
+ current = t_uncover(splitter,t_u_cache,current)
+ -- let's not be sparse
+ local lookups = rule.lookups
+ if lookups then
+ for i=1,#current do
+ if not lookups[i] then
+ lookups[i] = "" -- fix sparse array
+ end
+ end
+ end
+ --
+ rule.current = t_hashed(current,t_h_cache)
+ end
+ local after = coverage.after
+ if after then
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
+ end
+ rule.coverage = nil
+ end
+ end
+ elseif format == "reversecoverage" then -- special case, single substitution only
+ for i=1,#rules do
+ local rule = rules[i]
+ local reversecoverage = rule.reversecoverage
+ if reversecoverage then
+ local before = reversecoverage.before
+ if before then
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
+ end
+ local current = reversecoverage.current
+ if current then
+ current = t_uncover(splitter,t_u_cache,current)
+ rule.current = t_hashed(current,t_h_cache)
+ end
+ local after = reversecoverage.after
+ if after then
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
+ end
+ local replacements = reversecoverage.replacements
+ if replacements then
+ rule.replacements = r_uncover(splitter,r_u_cache,current,replacements)
+ end
+ rule.reversecoverage = nil
+ end
+ end
+ elseif format == "glyphs" then
+ -- I could store these more efficient (as not we use a nested tables for before,
+ -- after and current but this features happens so seldom that I don't bother
+ -- about it right now.
+ for i=1,#rules do
+ local rule = rules[i]
+ local glyphs = rule.glyphs
+ if glyphs then
+ local fore = glyphs.fore
+ if fore and fore ~= "" then
+ fore = s_uncover(splitter,s_u_cache,fore)
+ rule.after = s_hashed(fore,s_h_cache)
+ end
+ local back = glyphs.back
+ if back then
+ back = s_uncover(splitter,s_u_cache,back)
+ rule.before = s_hashed(back,s_h_cache)
+ end
+ local names = glyphs.names
+ if names then
+ names = s_uncover(splitter,s_u_cache,names)
+ rule.current = s_hashed(names,s_h_cache)
+ end
+ rule.glyphs = nil
+ local lookups = rule.lookups
+ if lookups then
+ for i=1,#names do
+ if not lookups[i] then
+ lookups[i] = "" -- fix sparse array
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+actions["expand lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
+ if data.lookups then
+ local cache = data.helpers.matchcache
+ if cache then
+ local duplicates = data.resources.duplicates
+ for key, hash in next, cache do
+ local done = nil
+ for key in next, hash do
+ local unicode = duplicates[key]
+ if not unicode then
+ -- no duplicate
+ elseif type(unicode) == "table" then
+ -- multiple duplicates
+ for i=1,#unicode do
+ local u = unicode[i]
+ if hash[u] then
+ -- already in set
+ elseif done then
+ done[u] = key
+ else
+ done = { [u] = key }
+ end
+ end
+ else
+ -- one duplicate
+ if hash[unicode] then
+ -- already in set
+ elseif done then
+ done[unicode] = key
+ else
+ done = { [unicode] = key }
+ end
+ end
+ end
+ if done then
+ for u in next, done do
+ hash[u] = true
+ end
+ end
+ end
+ end
+ end
+end
+
+local function check_variants(unicode,the_variants,splitter,unicodes)
+ local variants = the_variants.variants
+ if variants then -- use splitter
+ local glyphs = lpegmatch(splitter,variants)
+ local done = { [unicode] = true }
+ local n = 0
+ for i=1,#glyphs do
+ local g = glyphs[i]
+ if done[g] then
+ if i > 1 then
+ report_otf("skipping cyclic reference %U in math variant %U",g,unicode)
+ end
+ else
+ if n == 0 then
+ n = 1
+ variants = { g }
+ else
+ n = n + 1
+ variants[n] = g
+ end
+ done[g] = true
+ end
+ end
+ if n == 0 then
+ variants = nil
+ end
+ end
+ local parts = the_variants.parts
+ if parts then
+ local p = #parts
+ if p > 0 then
+ for i=1,p do
+ local pi = parts[i]
+ pi.glyph = unicodes[pi.component] or 0
+ pi.component = nil
+ end
+ else
+ parts = nil
+ end
+ end
+ local italic = the_variants.italic
+ if italic and italic == 0 then
+ italic = nil
+ end
+ return variants, parts, italic
+end
+
+actions["analyze math"] = function(data,filename,raw)
+ if raw.math then
+ data.metadata.math = raw.math
+ local unicodes = data.resources.unicodes
+ local splitter = data.helpers.tounicodetable
+ for unicode, description in next, data.descriptions do
+ local glyph = description.glyph
+ local mathkerns = glyph.mathkern -- singular
+ local hvariants = glyph.horiz_variants
+ local vvariants = glyph.vert_variants
+ local accent = glyph.top_accent
+ local italic = glyph.italic_correction
+ if mathkerns or hvariants or vvariants or accent or italic then
+ local math = { }
+ if accent then
+ math.accent = accent
+ end
+ if mathkerns then
+ for k, v in next, mathkerns do
+ if not next(v) then
+ mathkerns[k] = nil
+ else
+ for k, v in next, v do
+ if v == 0 then
+ k[v] = nil -- height / kern can be zero
+ end
+ end
+ end
+ end
+ math.kerns = mathkerns
+ end
+ if hvariants then
+ math.hvariants, math.hparts, math.hitalic = check_variants(unicode,hvariants,splitter,unicodes)
+ end
+ if vvariants then
+ math.vvariants, math.vparts, math.vitalic = check_variants(unicode,vvariants,splitter,unicodes)
+ end
+ if italic and italic ~= 0 then
+ math.italic = italic
+ end
+ description.math = math
+ end
+ end
+ end
+end
+
+actions["reorganize glyph kerns"] = function(data,filename,raw)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ for unicode, description in next, descriptions do
+ local kerns = description.glyph.kerns
+ if kerns then
+ local newkerns = { }
+ for k, kern in next, kerns do
+ local name = kern.char
+ local offset = kern.off
+ local lookup = kern.lookup
+ if name and offset and lookup then
+ local unicode = unicodes[name]
+ if unicode then
+ if type(lookup) == "table" then
+ for l=1,#lookup do
+ local lookup = lookup[l]
+ local lookupkerns = newkerns[lookup]
+ if lookupkerns then
+ lookupkerns[unicode] = offset
+ else
+ newkerns[lookup] = { [unicode] = offset }
+ end
+ end
+ else
+ local lookupkerns = newkerns[lookup]
+ if lookupkerns then
+ lookupkerns[unicode] = offset
+ else
+ newkerns[lookup] = { [unicode] = offset }
+ end
+ end
+ elseif trace_loading then
+ report_otf("problems with unicode %a of kern %a of glyph %U",name,k,unicode)
+ end
+ end
+ end
+ description.kerns = newkerns
+ end
+ end
+end
+
+actions["merge kern classes"] = function(data,filename,raw)
+ local gposlist = raw.gpos
+ if gposlist then
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ local splitter = data.helpers.tounicodetable
+ local ignored = 0
+ local blocked = 0
+ for gp=1,#gposlist do
+ local gpos = gposlist[gp]
+ local subtables = gpos.subtables
+ if subtables then
+ local first_done = { } -- could become an option so that we can deal with buggy fonts that don't get fixed
+ local split = { } -- saves time .. although probably not that much any more in the fixed luatex kernclass table
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
+ local lookup = subtable.lookup or subtable.name
+ if kernclass then -- the next one is quite slow
+ -- as fas as i can see the kernclass is a table with one entry and offsets
+ -- have no [1] so we could remov eon elevel (kernclass) and start offsets
+ -- at 1 but we're too far down the road now to fix that
+ if #kernclass > 0 then
+ kernclass = kernclass[1]
+ lookup = type(kernclass.lookup) == "string" and kernclass.lookup or lookup
+ report_otf("fixing kernclass table of lookup %a",lookup)
+ end
+ local firsts = kernclass.firsts
+ local seconds = kernclass.seconds
+ local offsets = kernclass.offsets
+ -- if offsets[1] == nil then
+ -- offsets[1] = "" -- defaults ?
+ -- end
+ for n, s in next, firsts do
+ split[s] = split[s] or lpegmatch(splitter,s)
+ end
+ local maxseconds = 0
+ for n, s in next, seconds do
+ if n > maxseconds then
+ maxseconds = n
+ end
+ split[s] = split[s] or lpegmatch(splitter,s)
+ end
+ for fk=1,#firsts do -- maxfirsts ?
+ local fv = firsts[fk]
+ local splt = split[fv]
+ if splt then
+ local extrakerns = { }
+ local baseoffset = (fk-1) * maxseconds
+ -- for sk, sv in next, seconds do
+ for sk=2,maxseconds do
+ local sv = seconds[sk]
+ if sv then
+ local splt = split[sv]
+ if splt then -- redundant test
+ local offset = offsets[baseoffset + sk]
+ if offset then
+ for i=1,#splt do
+ extrakerns[splt[i]] = offset
+ end
+ end
+ end
+ end
+ end
+ for i=1,#splt do
+ local first_unicode = splt[i]
+ if first_done[first_unicode] then
+ report_otf("lookup %a: ignoring further kerns of %C",lookup,first_unicode)
+ blocked = blocked + 1
+ else
+ first_done[first_unicode] = true
+ local description = descriptions[first_unicode]
+ if description then
+ local kerns = description.kerns
+ if not kerns then
+ kerns = { } -- unicode indexed !
+ description.kerns = kerns
+ end
+ local lookupkerns = kerns[lookup]
+ if not lookupkerns then
+ lookupkerns = { }
+ kerns[lookup] = lookupkerns
+ end
+ if overloadkerns then
+ for second_unicode, kern in next, extrakerns do
+ lookupkerns[second_unicode] = kern
+ end
+ else
+ for second_unicode, kern in next, extrakerns do
+ local k = lookupkerns[second_unicode]
+ if not k then
+ lookupkerns[second_unicode] = kern
+ elseif k ~= kern then
+ if trace_loading then
+ report_otf("lookup %a: ignoring overload of kern between %C and %C, rejecting %a, keeping %a",lookup,first_unicode,second_unicode,k,kern)
+ end
+ ignored = ignored + 1
+ end
+ end
+ end
+ elseif trace_loading then
+ report_otf("no glyph data for %U", first_unicode)
+ end
+ end
+ end
+ end
+ end
+ subtable.kernclass = { }
+ end
+ end
+ end
+ end
+ if ignored > 0 then
+ report_otf("%s kern overloads ignored",ignored)
+ end
+ if blocked > 0 then
+ report_otf("%s successive kerns blocked",blocked)
+ end
+ end
+end
+
+actions["check glyphs"] = function(data,filename,raw)
+ for unicode, description in next, data.descriptions do
+ description.glyph = nil
+ end
+end
+
+-- future versions will remove _
+
+local valid = (R("\x00\x7E") - S("(){}[]<>%/ \n\r\f\v"))^0 * P(-1)
+
+local function valid_ps_name(str)
+ return str and str ~= "" and #str < 64 and lpegmatch(valid,str) and true or false
+end
+
+actions["check metadata"] = function(data,filename,raw)
+ local metadata = data.metadata
+ for _, k in next, mainfields do
+ if valid_fields[k] then
+ local v = raw[k]
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ -- metadata.pfminfo = raw.pfminfo -- not already done?
+ local ttftables = metadata.ttf_tables
+ if ttftables then
+ for i=1,#ttftables do
+ ttftables[i].data = "deleted"
+ end
+ end
+ --
+ local state = metadata.validation_state
+ local names = raw.names
+ --
+ if state and table.contains(state,"bad_ps_fontname") then
+ -- the ff library does a bit too much (and wrong) checking ... so we need to catch this
+ -- at least for now
+ local function valid(what)
+ if names then
+ for i=1,#names do
+ local list = names[i]
+ local names = list.names
+ if names then
+ local name = names[what]
+ if name and valid_ps_name(name) then
+ return name
+ end
+ end
+ end
+ end
+ end
+ local function check(what)
+ local oldname = metadata[what]
+ if valid_ps_name(oldname) then
+ report_otf("ignoring warning %a because %s %a is proper ASCII","bad_ps_fontname",what,oldname)
+ else
+ local newname = valid(what)
+ if not newname then
+ newname = formatters["bad-%s-%s"](what,file.nameonly(filename))
+ end
+ local warning = formatters["overloading %s from invalid ASCII name %a to %a"](what,oldname,newname)
+ data.warnings[#data.warnings+1] = warning
+ report_otf(warning)
+ metadata[what] = newname
+ end
+ end
+ check("fontname")
+ check("fullname")
+ end
+ --
+ if names then
+ local psname = metadata.psname
+ if not psname or psname == "" then
+ for i=1,#names do
+ local name = names[i]
+ -- Currently we use the same restricted search as in the new context (specific) font loader
+ -- but we might add more lang checks (it worked ok in the new loaded so now we're in sync)
+ -- This check here is also because there are (esp) cjk fonts out there with psnames different
+ -- from fontnames (gives a bad lookup in backend).
+ if lower(name.lang) == "english (us)" then
+ local specification = name.names
+ if specification then
+ local postscriptname = specification.postscriptname
+ if postscriptname then
+ psname = postscriptname
+ end
+ end
+ end
+ break
+ end
+ end
+ if psname ~= metadata.fontname then
+ report_otf("fontname %a, fullname %a, psname %a",metadata.fontname,metadata.fullname,psname)
+ end
+ metadata.psname = psname
+ end
+ --
+ if state and table.contains(state,"bad_cmap_table") then
+ report_otf("fontfile %a has bad cmap tables",filename)
+ end
+end
+
+actions["cleanup tables"] = function(data,filename,raw)
+ local duplicates = data.resources.duplicates
+ if duplicates then
+ for k, v in next, duplicates do
+ if #v == 1 then
+ duplicates[k] = v[1]
+ end
+ end
+ end
+ data.resources.indices = nil -- not needed
+ data.resources.unicodes = nil -- delayed
+ data.helpers = nil -- tricky as we have no unicodes any more
+end
+
+-- kern: ttf has a table with kerns
+--
+-- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
+-- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
+-- unpredictable alternatively we could force an [1] if not set (maybe I will do that
+-- anyway).
+
+-- we can share { } as it is never set
+
+-- ligatures have an extra specification.char entry that we don't use
+
+-- mlookups only with pairs and ligatures
+
+actions["reorganize glyph lookups"] = function(data,filename,raw)
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ local descriptions = data.descriptions
+ local splitter = data.helpers.tounicodelist
+
+ local lookuptypes = resources.lookuptypes
+
+ for unicode, description in next, descriptions do
+ local lookups = description.glyph.lookups
+ if lookups then
+ for tag, lookuplist in next, lookups do
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local specification = lookup.specification
+ local lookuptype = lookup.type
+ local lt = lookuptypes[tag]
+ if not lt then
+ lookuptypes[tag] = lookuptype
+ elseif lt ~= lookuptype then
+ report_otf("conflicting lookuptypes, %a points to %a and %a",tag,lt,lookuptype)
+ end
+ if lookuptype == "ligature" then
+ lookuplist[l] = { lpegmatch(splitter,specification.components) }
+ elseif lookuptype == "alternate" then
+ lookuplist[l] = { lpegmatch(splitter,specification.components) }
+ elseif lookuptype == "substitution" then
+ lookuplist[l] = unicodes[specification.variant]
+ elseif lookuptype == "multiple" then
+ lookuplist[l] = { lpegmatch(splitter,specification.components) }
+ elseif lookuptype == "position" then
+ lookuplist[l] = {
+ specification.x or 0,
+ specification.y or 0,
+ specification.h or 0,
+ specification.v or 0
+ }
+ elseif lookuptype == "pair" then
+ local one = specification.offsets[1]
+ local two = specification.offsets[2]
+ local paired = unicodes[specification.paired]
+ if one then
+ if two then
+ lookuplist[l] = { paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
+ else
+ lookuplist[l] = { paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
+ end
+ else
+ if two then
+ lookuplist[l] = { paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
+ else
+ lookuplist[l] = { paired }
+ end
+ end
+ end
+ end
+ end
+ local slookups, mlookups
+ for tag, lookuplist in next, lookups do
+ if #lookuplist == 1 then
+ if slookups then
+ slookups[tag] = lookuplist[1]
+ else
+ slookups = { [tag] = lookuplist[1] }
+ end
+ else
+ if mlookups then
+ mlookups[tag] = lookuplist
+ else
+ mlookups = { [tag] = lookuplist }
+ end
+ end
+ end
+ if slookups then
+ description.slookups = slookups
+ end
+ if mlookups then
+ description.mlookups = mlookups
+ end
+ -- description.lookups = nil
+ end
+ end
+end
+
+local zero = { 0, 0 }
+
+actions["reorganize glyph anchors"] = function(data,filename,raw)
+ local descriptions = data.descriptions
+ for unicode, description in next, descriptions do
+ local anchors = description.glyph.anchors
+ if anchors then
+ for class, data in next, anchors do
+ if class == "baselig" then
+ for tag, specification in next, data do
+ -- for i=1,#specification do
+ -- local si = specification[i]
+ -- specification[i] = { si.x or 0, si.y or 0 }
+ -- end
+ -- can be sparse so we need to fill the holes
+ local n = 0
+ for k, v in next, specification do
+ if k > n then
+ n = k
+ end
+ local x, y = v.x, v.y
+ if x or y then
+ specification[k] = { x or 0, y or 0 }
+ else
+ specification[k] = zero
+ end
+ end
+ local t = { }
+ for i=1,n do
+ t[i] = specification[i] or zero
+ end
+ data[tag] = t -- so # is okay (nicer for packer)
+ end
+ else
+ for tag, specification in next, data do
+ local x, y = specification.x, specification.y
+ if x or y then
+ data[tag] = { x or 0, y or 0 }
+ else
+ data[tag] = zero
+ end
+ end
+ end
+ end
+ description.anchors = anchors
+ end
+ end
+end
+
+local bogusname = (P("uni") + P("u")) * R("AF","09")^4
+ + (P("index") + P("glyph") + S("Ii") * P("dentity") * P(".")^0) * R("09")^1
+local uselessname = (1-bogusname)^0 * bogusname
+
+actions["purge names"] = function(data,filename,raw) -- not used yet
+ if purge_names then
+ local n = 0
+ for u, d in next, data.descriptions do
+ if lpegmatch(uselessname,d.name) then
+ n = n + 1
+ d.name = nil
+ end
+ -- d.comment = nil
+ end
+ if n > 0 then
+ report_otf("%s bogus names removed",n)
+ end
+ end
+end
+
+actions["compact lookups"] = function(data,filename,raw)
+ if not compact_lookups then
+ report_otf("not compacting")
+ return
+ end
+ -- create keyhash
+ local last = 0
+ local tags = table.setmetatableindex({ },
+ function(t,k)
+ last = last + 1
+ t[k] = last
+ return last
+ end
+ )
+ --
+ local descriptions = data.descriptions
+ local resources = data.resources
+ --
+ for u, d in next, descriptions do
+ --
+ -- -- we can also compact anchors and cursives (basechar basemark baselig mark)
+ --
+ local slookups = d.slookups
+ if type(slookups) == "table" then
+ local s = { }
+ for k, v in next, slookups do
+ s[tags[k]] = v
+ end
+ d.slookups = s
+ end
+ --
+ local mlookups = d.mlookups
+ if type(mlookups) == "table" then
+ local m = { }
+ for k, v in next, mlookups do
+ m[tags[k]] = v
+ end
+ d.mlookups = m
+ end
+ --
+ local kerns = d.kerns
+ if type(kerns) == "table" then
+ local t = { }
+ for k, v in next, kerns do
+ t[tags[k]] = v
+ end
+ d.kerns = t
+ end
+ end
+ --
+ local lookups = data.lookups
+ if lookups then
+ local l = { }
+ for k, v in next, lookups do
+ local rules = v.rules
+ if rules then
+ for i=1,#rules do
+ local l = rules[i].lookups
+ if type(l) == "table" then
+ for i=1,#l do
+ l[i] = tags[l[i]]
+ end
+ end
+ end
+ end
+ l[tags[k]] = v
+ end
+ data.lookups = l
+ end
+ --
+ local lookups = resources.lookups
+ if lookups then
+ local l = { }
+ for k, v in next, lookups do
+ local s = v.subtables
+ if type(s) == "table" then
+ for i=1,#s do
+ s[i] = tags[s[i]]
+ end
+ end
+ l[tags[k]] = v
+ end
+ resources.lookups = l
+ end
+ --
+ local sequences = resources.sequences
+ if sequences then
+ for i=1,#sequences do
+ local s = sequences[i]
+ local n = s.name
+ if n then
+ s.name = tags[n]
+ end
+ local t = s.subtables
+ if type(t) == "table" then
+ for i=1,#t do
+ t[i] = tags[t[i]]
+ end
+ end
+ end
+ end
+ --
+ local lookuptypes = resources.lookuptypes
+ if lookuptypes then
+ local l = { }
+ for k, v in next, lookuptypes do
+ l[tags[k]] = v
+ end
+ resources.lookuptypes = l
+ end
+ --
+ local anchor_to_lookup = resources.anchor_to_lookup
+ if anchor_to_lookup then
+ for anchor, lookups in next, anchor_to_lookup do
+ local l = { }
+ for lookup, value in next, lookups do
+ l[tags[lookup]] = value
+ end
+ anchor_to_lookup[anchor] = l
+ end
+ end
+ --
+ local lookup_to_anchor = resources.lookup_to_anchor
+ if lookup_to_anchor then
+ local l = { }
+ for lookup, value in next, lookup_to_anchor do
+ l[tags[lookup]] = value
+ end
+ resources.lookup_to_anchor = l
+ end
+ --
+ tags = table.swapped(tags)
+ --
+ report_otf("%s lookup tags compacted",#tags)
+ --
+ resources.lookuptags = tags
+end
+
+-- modes: node, base, none
+
+function otf.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
+ if okay then
+ return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
+ else
+ return { } -- will become false
+ end
+end
+
+-- the first version made a top/mid/not extensible table, now we just
+-- pass on the variants data and deal with it in the tfm scaler (there
+-- is no longer an extensible table anyway)
+--
+-- we cannot share descriptions as virtual fonts might extend them (ok,
+-- we could use a cache with a hash
+--
+-- we already assign an empty tabel to characters as we can add for
+-- instance protruding info and loop over characters; one is not supposed
+-- to change descriptions and if one does so one should make a copy!
+
+local function copytotfm(data,cache_id)
+ if data then
+ local metadata = data.metadata
+ local warnings = data.warnings
+ local resources = data.resources
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { }
+ local parameters = { }
+ local mathparameters = { }
+ --
+ local pfminfo = metadata.pfminfo or { }
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ -- local mode = data.mode or "base"
+ local spaceunits = 500
+ local spacer = "space"
+ local designsize = metadata.designsize or metadata.design_size or 100
+ local minsize = metadata.minsize or metadata.design_range_bottom or designsize
+ local maxsize = metadata.maxsize or metadata.design_range_top or designsize
+ local mathspecs = metadata.math
+ --
+ if designsize == 0 then
+ designsize = 100
+ minsize = 100
+ maxsize = 100
+ end
+ if mathspecs then
+ for name, value in next, mathspecs do
+ mathparameters[name] = value
+ end
+ end
+ for unicode, _ in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ if mathspecs then
+ -- we could move this to the scaler but not that much is saved
+ -- and this is cleaner
+ for unicode, character in next, characters do
+ local d = descriptions[unicode]
+ local m = d.math
+ if m then
+ -- watch out: luatex uses horiz_variants for the parts
+ --
+ local italic = m.italic
+ local vitalic = m.vitalic
+ --
+ local variants = m.hvariants
+ local parts = m.hparts
+ -- local done = { [unicode] = true }
+ if variants then
+ local c = character
+ for i=1,#variants do
+ local un = variants[i]
+ -- if done[un] then
+ -- -- report_otf("skipping cyclic reference %U in math variant %U",un,unicode)
+ -- else
+ c.next = un
+ c = characters[un]
+ -- done[un] = true
+ -- end
+ end -- c is now last in chain
+ c.horiz_variants = parts
+ elseif parts then
+ character.horiz_variants = parts
+ italic = m.hitalic
+ end
+ --
+ local variants = m.vvariants
+ local parts = m.vparts
+ -- local done = { [unicode] = true }
+ if variants then
+ local c = character
+ for i=1,#variants do
+ local un = variants[i]
+ -- if done[un] then
+ -- -- report_otf("skipping cyclic reference %U in math variant %U",un,unicode)
+ -- else
+ c.next = un
+ c = characters[un]
+ -- done[un] = true
+ -- end
+ end -- c is now last in chain
+ c.vert_variants = parts
+ elseif parts then
+ character.vert_variants = parts
+ end
+ --
+ if italic and italic ~= 0 then
+ character.italic = italic -- overload
+ end
+ if vitalic and vitalic ~= 0 then
+ character.vert_italic = vitalic
+ end
+ --
+ local accent = m.accent
+ if accent then
+ character.accent = accent
+ end
+ --
+ local kerns = m.kerns
+ if kerns then
+ character.mathkerns = kerns
+ end
+ end
+ end
+ end
+ -- end math
+ -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't we use the basename then?)
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname
+ local fullname = metadata.fullname or fontname
+ local psname = metadata.psname or fontname or fullname
+ local units = metadata.units or metadata.units_per_em or 1000
+ --
+ if units == 0 then -- catch bugs in fonts
+ units = 1000 -- maybe 2000 when ttf
+ metadata.units = 1000
+ report_otf("changing %a units to %a",0,units)
+ end
+ --
+ local monospaced = metadata.monospaced or metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
+ local charwidth = pfminfo.avgwidth -- or unset
+ local charxheight = pfminfo.os2_xheight and pfminfo.os2_xheight > 0 and pfminfo.os2_xheight
+-- charwidth = charwidth * units/1000
+-- charxheight = charxheight * units/1000
+ local italicangle = metadata.italicangle
+ properties.monospaced = monospaced
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ --
+ local space = 0x0020
+ local emdash = 0x2014
+ if monospaced then
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ else
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width/2, "emdash/2"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits) or 500 -- brrr
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits -- 3.333 (cmr10)
+ parameters.space_stretch = units/2 -- 500 -- 1.666 (cmr10)
+ parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
+ parameters.x_height = 2*units/5 -- 400
+ parameters.quad = units -- 1000
+ if spaceunits < 2*units/5 then
+ -- todo: warning
+ end
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif syncspace then --
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink -- 1.111 (cmr10)
+ if charxheight then
+ parameters.x_height = charxheight
+ else
+ local x = 0x0078
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ end
+ --
+ parameters.designsize = (designsize/10)*65536
+ parameters.minsize = (minsize /10)*65536
+ parameters.maxsize = (maxsize /10)*65536
+ parameters.ascender = abs(metadata.ascender or metadata.ascent or 0)
+ parameters.descender = abs(metadata.descender or metadata.descent or 0)
+ parameters.units = units
+ --
+ properties.space = spacer
+ properties.encodingbytes = 2
+ properties.format = data.format or otf_format(filename) or formats.otf
+ properties.noglyphnames = true
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = psname
+ properties.name = filename or fullname
+ --
+ -- properties.name = specification.name
+ -- properties.sub = specification.sub
+ --
+ if warnings and #warnings > 0 then
+ report_otf("warnings for font: %s",filename)
+ report_otf()
+ for i=1,#warnings do
+ report_otf(" %s",warnings[i])
+ end
+ report_otf()
+ end
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ mathparameters = mathparameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ warnings = warnings,
+ }
+ end
+end
+
+local function otftotfm(specification)
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache,cache_id)
+ if not tfmdata then
+ local name = specification.name
+ local sub = specification.sub
+ local filename = specification.filename
+ -- local format = specification.format
+ local features = specification.features.normal
+ local rawdata = otf.load(filename,sub,features and features.featurefile)
+ if rawdata and next(rawdata) then
+ local descriptions = rawdata.descriptions
+ local duplicates = rawdata.resources.duplicates
+ if duplicates then
+ local nofduplicates, nofduplicated = 0, 0
+ for parent, list in next, duplicates do
+ if type(list) == "table" then
+ local n = #list
+ for i=1,n do
+ local unicode = list[i]
+ if not descriptions[unicode] then
+ descriptions[unicode] = descriptions[parent] -- or copy
+ nofduplicated = nofduplicated + 1
+ end
+ end
+ nofduplicates = nofduplicates + n
+ else
+ if not descriptions[list] then
+ descriptions[list] = descriptions[parent] -- or copy
+ nofduplicated = nofduplicated + 1
+ end
+ nofduplicates = nofduplicates + 1
+ end
+ end
+ if trace_otf and nofduplicated ~= nofduplicates then
+ report_otf("%i extra duplicates copied out of %i",nofduplicated,nofduplicates)
+ end
+ end
+ rawdata.lookuphash = { }
+ tfmdata = copytotfm(rawdata,cache_id)
+ if tfmdata and next(tfmdata) then
+ -- at this moment no characters are assigned yet, only empty slots
+ local features = constructors.checkedfeatures("otf",features)
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ -- shared.features = features -- default
+ shared.dynamics = { }
+ -- shared.processes = { }
+ tfmdata.changed = { }
+ shared.features = features
+ shared.processes = otf.setfeatures(tfmdata,features)
+ end
+ end
+ containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+end
+
+local function read_from_otf(specification)
+ local tfmdata = otftotfm(specification)
+ if tfmdata then
+ -- this late ? .. needs checking
+ tfmdata.properties.name = specification.name
+ tfmdata.properties.sub = specification.sub
+ --
+ tfmdata = constructors.scale(tfmdata,specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
+ constructors.setname(tfmdata,specification) -- only otf?
+ fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
+ end
+ return tfmdata
+end
+
+local function checkmathsize(tfmdata,mathsize)
+ local mathdata = tfmdata.shared.rawdata.metadata.math
+ local mathsize = tonumber(mathsize)
+ if mathdata then -- we cannot use mathparameters as luatex will complain
+ local parameters = tfmdata.parameters
+ parameters.scriptpercentage = mathdata.ScriptPercentScaleDown
+ parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown
+ parameters.mathsize = mathsize
+ end
+end
+
+registerotffeature {
+ name = "mathsize",
+ description = "apply mathsize specified in the font",
+ initializers = {
+ base = checkmathsize,
+ node = checkmathsize,
+ }
+}
+
+-- helpers
+
+function otf.collectlookups(rawdata,kind,script,language)
+ local sequences = rawdata.resources.sequences
+ if sequences then
+ local featuremap, featurelist = { }, { }
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local features = sequence.features
+ features = features and features[kind]
+ features = features and (features[script] or features[default] or features[wildcard])
+ features = features and (features[language] or features[default] or features[wildcard])
+ if features then
+ local subtables = sequence.subtables
+ if subtables then
+ for s=1,#subtables do
+ local ss = subtables[s]
+ if not featuremap[s] then
+ featuremap[ss] = true
+ featurelist[#featurelist+1] = ss
+ end
+ end
+ end
+ end
+ end
+ if #featurelist > 0 then
+ return featuremap, featurelist
+ end
+ end
+ return nil, nil
+end
+
+-- readers (a bit messy, this forced so I might redo that bit: foo.ttf FOO.ttf foo.TTF FOO.TTF)
+
+local function check_otf(forced,specification,suffix)
+ local name = specification.name
+ if forced then
+ name = specification.forcedname -- messy
+ end
+ local fullname = findbinfile(name,suffix) or ""
+ if fullname == "" then
+ fullname = fonts.names.getfilename(name,suffix) or ""
+ end
+ if fullname ~= "" and not fonts.names.ignoredfile(fullname) then
+ specification.filename = fullname
+ return read_from_otf(specification)
+ end
+end
+
+local function opentypereader(specification,suffix)
+ local forced = specification.forced or ""
+ if formats[forced] then
+ return check_otf(true,specification,forced)
+ else
+ return check_otf(false,specification,suffix)
+ end
+end
+
+readers.opentype = opentypereader -- kind of useless and obsolete
+
+function readers.otf (specification) return opentypereader(specification,"otf") end
+function readers.ttf (specification) return opentypereader(specification,"ttf") end
+function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.dfont(specification) return opentypereader(specification,"ttf") end
+
+-- this will be overloaded
+
+function otf.scriptandlanguage(tfmdata,attr)
+ local properties = tfmdata.properties
+ return properties.script or "dflt", properties.language or "dflt"
+end
+
+-- a little bit of abstraction
+
+local function justset(coverage,unicode,replacement)
+ coverage[unicode] = replacement
+end
+
+otf.coverup = {
+ stepkey = "subtables",
+ actions = {
+ substitution = justset,
+ alternate = justset,
+ multiple = justset,
+ ligature = justset,
+ kern = justset,
+ chainsubstitution = justset,
+ chainposition = justset,
+ },
+ register = function(coverage,lookuptype,format,feature,n,descriptions,resources)
+ local name = formatters["ctx_%s_%s_%s"](feature,lookuptype,n) -- we can have a mix of types
+ if lookuptype == "kern" then
+ resources.lookuptypes[name] = "position"
+ else
+ resources.lookuptypes[name] = lookuptype
+ end
+ for u, c in next, coverage do
+ local description = descriptions[u]
+ local slookups = description.slookups
+ if slookups then
+ slookups[name] = c
+ else
+ description.slookups = { [name] = c }
+ end
+ end
+ return name
+ end
+}
+
+-- moved from font-oth.lua
+
+local function getgsub(tfmdata,k,kind)
+ local description = tfmdata.descriptions[k]
+ if description then
+ local slookups = description.slookups -- we assume only slookups (we can always extend)
+ if slookups then
+ local shared = tfmdata.shared
+ local rawdata = shared and shared.rawdata
+ if rawdata then
+ local lookuptypes = rawdata.resources.lookuptypes
+ if lookuptypes then
+ local properties = tfmdata.properties
+ -- we could cache these
+ local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local found = slookups[lookup]
+ if found then
+ return found, lookuptypes[lookup]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.getgsub = getgsub -- returns value, gsub_kind
+
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if not found then
+ --
+ elseif kind == "substitution" then
+ return found
+ elseif kind == "alternate" then
+ local choice = tonumber(value) or 1 -- no random here (yet)
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+
+otf.getalternate = otf.getsubstitution
+
+function otf.getmultiple(tfmdata,k,kind)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if found and kind == "multiple" then
+ return found
+ end
+ return { k }
+end
+
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub
+ if kerns then
+ local found = kerns[right]
+ local kind = type(found)
+ if kind == "table" then
+ found = found[1][3] -- can be more clever
+ elseif kind ~= "number" then
+ found = false
+ end
+ if found then
+ return found * tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oth.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oth.lua
new file mode 100644
index 00000000000..28c543494fc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-oth.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['font-oth'] = {
+ version = 1.001,
+ comment = "companion to font-oth.lua (helpers)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- otf.getalternate is moved elsewhere (for now) but move back here some day
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oti.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oti.lua
new file mode 100644
index 00000000000..bacd001a5e8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-oti.lua
@@ -0,0 +1,158 @@
+if not modules then modules = { } end modules ['font-oti'] = {
+ 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 lower = string.lower
+
+local fonts = fonts
+local constructors = fonts.constructors
+
+local otf = constructors.newhandler("otf")
+local otffeatures = constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local otftables = otf.tables or { }
+otf.tables = otftables
+
+local allocate = utilities.storage.allocate
+
+registerotffeature {
+ name = "features",
+ description = "initialization of feature handler",
+ default = true,
+}
+
+-- these are later hooked into node and base initializaters
+
+local function setmode(tfmdata,value)
+ if value then
+ tfmdata.properties.mode = lower(value)
+ end
+end
+
+local function setlanguage(tfmdata,value)
+ if value then
+ local cleanvalue = lower(value)
+ local languages = otftables and otftables.languages
+ local properties = tfmdata.properties
+ if not languages then
+ properties.language = cleanvalue
+ elseif languages[value] then
+ properties.language = cleanvalue
+ else
+ properties.language = "dflt"
+ end
+ end
+end
+
+local function setscript(tfmdata,value)
+ if value then
+ local cleanvalue = lower(value)
+ local scripts = otftables and otftables.scripts
+ local properties = tfmdata.properties
+ if not scripts then
+ properties.script = cleanvalue
+ elseif scripts[value] then
+ properties.script = cleanvalue
+ else
+ properties.script = "dflt"
+ end
+ end
+end
+
+registerotffeature {
+ name = "mode",
+ description = "mode",
+ initializers = {
+ base = setmode,
+ node = setmode,
+ }
+}
+
+registerotffeature {
+ name = "language",
+ description = "language",
+ initializers = {
+ base = setlanguage,
+ node = setlanguage,
+ }
+}
+
+registerotffeature {
+ name = "script",
+ description = "script",
+ initializers = {
+ base = setscript,
+ node = setscript,
+ }
+}
+
+-- here (as also in generic
+
+otftables.featuretypes = allocate {
+ gpos_single = "position",
+ gpos_pair = "position",
+ gpos_cursive = "position",
+ gpos_mark2base = "position",
+ gpos_mark2ligature = "position",
+ gpos_mark2mark = "position",
+ gpos_context = "position",
+ gpos_contextchain = "position",
+ gsub_single = "substitution",
+ gsub_multiple = "substitution",
+ gsub_alternate = "substitution",
+ gsub_ligature = "substitution",
+ gsub_context = "substitution",
+ gsub_contextchain = "substitution",
+ gsub_reversecontextchain = "substitution",
+ gsub_reversesub = "substitution",
+}
+
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype == "position" then
+ local default = scripts.dflt
+ if default then
+ if autoscript == "position" or autoscript == true then
+ return default
+ else
+ report_otf("script feature %s not applied, enable default positioning")
+ end
+ else
+ -- no positioning at all
+ end
+ elseif featuretype == "substitution" then
+ local default = scripts.dflt
+ if default then
+ if autoscript == "substitution" or autoscript == true then
+ return default
+ end
+ end
+ end
+end
+
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype == "position" then
+ local default = languages.dflt
+ if default then
+ if autolanguage == "position" or autolanguage == true then
+ return default
+ else
+ report_otf("language feature %s not applied, enable default positioning")
+ end
+ else
+ -- no positioning at all
+ end
+ elseif featuretype == "substitution" then
+ local default = languages.dflt
+ if default then
+ if autolanguage == "substitution" or autolanguage == true then
+ return default
+ end
+ end
+ end
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua
new file mode 100644
index 00000000000..aae70d1f345
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua
@@ -0,0 +1,1532 @@
+if not modules then modules = { } end modules ['font-otj'] = {
+ version = 1.001,
+ comment = "companion to font-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This property based variant is not faster but looks nicer than the attribute one. We
+-- need to use rawget (which is apbout 4 times slower than a direct access but we cannot
+-- get/set that one for our purpose! This version does a bit more with discretionaries
+-- (and Kai has tested it with his collection of weird fonts.)
+
+-- There is some duplicate code here (especially in the the pre/post/replace branches) but
+-- we go for speed. We could store a list of glyph and mark nodes when registering but it's
+-- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
+-- being too clever here is dangerous.
+
+-- The subtype test is not needed as there will be no (new) properties set, given that we
+-- reset the properties.
+
+-- As we have a rawget on properties we don't need one on injections.
+
+-- The use_advance code is just a test and is meant for testing and manuals. There is no
+-- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now).
+
+if not nodes.properties then return end
+
+local next, rawget = next, rawget
+local utfchar = utf.char
+local fastcopy = table.fastcopy
+
+local registertracker = trackers.register
+
+local trace_injections = false registertracker("fonts.injections", function(v) trace_injections = v end)
+local trace_marks = false registertracker("fonts.injections.marks", function(v) trace_marks = v end)
+local trace_cursive = false registertracker("fonts.injections.cursive", function(v) trace_cursive = v end)
+local trace_spaces = false registertracker("otf.spaces", function(v) trace_spaces = v end)
+
+-- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous
+
+local use_advance = false directives.register("fonts.injections.advance", function(v) use_advance = v end)
+
+local report_injections = logs.reporter("fonts","injections")
+local report_spaces = logs.reporter("fonts","spaces")
+
+local attributes, nodes, node = attributes, nodes, node
+
+fonts = fonts
+local hashes = fonts.hashes
+local fontdata = hashes.identifiers
+local parameters = fonts.hashes.parameters
+local resources = fonts.hashes.resources
+
+nodes.injections = nodes.injections or { }
+local injections = nodes.injections
+
+local tracers = nodes.tracers
+local setcolor = tracers and tracers.colors.set
+local resetcolor = tracers and tracers.colors.reset
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local newkern = nodepool.kern
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+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 getboth = nuts.getboth
+
+local ischar = nuts.is_char
+
+local getdisc = nuts.getdisc
+local setdisc = nuts.setdisc
+
+local traverse_id = nuts.traverse_id
+local traverse_char = nuts.traverse_char
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local find_tail = nuts.tail
+
+local properties = nodes.properties.data
+
+function injections.installnewkern(nk)
+ newkern = nk or newkern
+end
+
+local nofregisteredkerns = 0
+local nofregisteredpairs = 0
+local nofregisteredmarks = 0
+local nofregisteredcursives = 0
+local keepregisteredcounts = false
+
+function injections.keepcounts()
+ keepregisteredcounts = true
+end
+
+function injections.resetcounts()
+ nofregisteredkerns = 0
+ nofregisteredpairs = 0
+ nofregisteredmarks = 0
+ nofregisteredcursives = 0
+ keepregisteredcounts = false
+end
+
+-- We need to make sure that a possible metatable will not kick in unexpectedly.
+
+-- function injections.reset(n)
+-- local p = rawget(properties,n)
+-- if p and rawget(p,"injections") then
+-- p.injections = nil
+-- end
+-- end
+
+-- function injections.copy(target,source)
+-- local sp = rawget(properties,source)
+-- if sp then
+-- local tp = rawget(properties,target)
+-- local si = rawget(sp,"injections")
+-- if si then
+-- si = fastcopy(si)
+-- if tp then
+-- tp.injections = si
+-- else
+-- propertydata[target] = {
+-- injections = si,
+-- }
+-- end
+-- else
+-- if tp then
+-- tp.injections = nil
+-- end
+-- end
+-- end
+-- end
+
+function injections.reset(n)
+ local p = rawget(properties,n)
+ if p then
+ p.injections = false -- { }
+ else
+ properties[n] = false -- { injections = { } }
+ end
+end
+
+function injections.copy(target,source)
+ local sp = rawget(properties,source)
+ if sp then
+ local tp = rawget(properties,target)
+ -- local si = rawget(sp,"injections")
+ local si = sp.injections
+ if si then
+ si = fastcopy(si)
+ if tp then
+ tp.injections = si
+ else
+ propertydata[target] = {
+ injections = si,
+ }
+ end
+ elseif tp then
+ tp.injections = false -- { }
+ else
+ properties[target] = { injections = { } }
+ end
+ else
+ local tp = rawget(properties,target)
+ if tp then
+ tp.injections = false -- { }
+ else
+ properties[target] = false -- { injections = { } }
+ end
+ end
+end
+
+function injections.setligaindex(n,index)
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ i.ligaindex = index
+ else
+ p.injections = {
+ ligaindex = index
+ }
+ end
+ else
+ properties[n] = {
+ injections = {
+ ligaindex = index
+ }
+ }
+ end
+end
+
+function injections.getligaindex(n,default)
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ return i.ligaindex or default
+ end
+ end
+ return default
+end
+
+function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes
+ local dx = factor*(exit[1]-entry[1])
+ local dy = -factor*(exit[2]-entry[2])
+ local ws = tfmstart.width
+ local wn = tfmnext.width
+ nofregisteredcursives = nofregisteredcursives + 1
+ if rlmode < 0 then
+ dx = -(dx + wn)
+ else
+ dx = dx - ws
+ end
+ if dx == 0 then
+ -- get rid of funny -0
+ dx = 0
+ end
+ --
+ local p = rawget(properties,start)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ i.cursiveanchor = true
+ else
+ p.injections = {
+ cursiveanchor = true,
+ }
+ end
+ else
+ properties[start] = {
+ injections = {
+ cursiveanchor = true,
+ },
+ }
+ end
+ local p = rawget(properties,nxt)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ i.cursivex = dx
+ i.cursivey = dy
+ else
+ p.injections = {
+ cursivex = dx,
+ cursivey = dy,
+ }
+ end
+ else
+ properties[nxt] = {
+ injections = {
+ cursivex = dx,
+ cursivey = dy,
+ },
+ }
+ end
+ return dx, dy, nofregisteredcursives
+end
+
+function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
+ local x = factor*spec[1]
+ local y = factor*spec[2]
+ local w = factor*spec[3]
+ local h = factor*spec[4]
+ 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
+ local rightkern = w - x -- to normal kerns where we set only leftkern
+ if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then
+ nofregisteredpairs = nofregisteredpairs + 1
+ if rlmode and rlmode < 0 then
+ leftkern, rightkern = rightkern, leftkern
+ end
+ if not injection then
+ injection = "injections"
+ end
+ local p = rawget(properties,current)
+ if p then
+ -- local i = p[injection]
+ local i = rawget(p,injection)
+ if i then
+ if leftkern ~= 0 then
+ i.leftkern = (i.leftkern or 0) + leftkern
+ end
+ if rightkern ~= 0 then
+ i.rightkern = (i.rightkern or 0) + rightkern
+ end
+ if yoffset ~= 0 then
+ i.yoffset = (i.yoffset or 0) + yoffset
+ end
+ elseif leftkern ~= 0 or rightkern ~= 0 then
+ p[injection] = {
+ leftkern = leftkern,
+ rightkern = rightkern,
+ yoffset = yoffset,
+ }
+ else
+ p[injection] = {
+ yoffset = yoffset,
+ }
+ end
+ elseif leftkern ~= 0 or rightkern ~= 0 then
+ properties[current] = {
+ [injection] = {
+ leftkern = leftkern,
+ rightkern = rightkern,
+ yoffset = yoffset,
+ },
+ }
+ else
+ properties[current] = {
+ [injection] = {
+ yoffset = yoffset,
+ },
+ }
+ end
+ return x, y, w, h, nofregisteredpairs
+ end
+ end
+ return x, y, w, h -- no bound
+end
+
+-- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between
+-- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in
+-- the previous case)
+
+function injections.setkern(current,factor,rlmode,x,injection)
+ local dx = factor * x
+ if dx ~= 0 then
+ nofregisteredkerns = nofregisteredkerns + 1
+ local p = rawget(properties,current)
+ if not injection then
+ injection = "injections"
+ end
+ if p then
+ -- local i = rawget(p,injection)
+ local i = rawget(p,injection)
+ if i then
+ i.leftkern = dx + (i.leftkern or 0)
+ else
+ p[injection] = {
+ leftkern = dx,
+ }
+ end
+ else
+ properties[current] = {
+ [injection] = {
+ leftkern = dx,
+ },
+ }
+ end
+ return dx, nofregisteredkerns
+ else
+ return 0, 0
+ end
+end
+
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
+ local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
+ nofregisteredmarks = nofregisteredmarks + 1
+ if rlmode >= 0 then
+ dx = tfmbase.width - dx -- see later commented ox
+ end
+ local p = rawget(properties,start)
+ -- hm, dejavu serif does a sloppy mark2mark before mark2base
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ if i.markmark then
+ -- out of order mkmk: yes or no or option
+ else
+ i.markx = dx
+ i.marky = dy
+ i.markdir = rlmode or 0
+ i.markbase = nofregisteredmarks
+ i.markbasenode = base
+ i.markmark = mkmk
+ end
+ else
+ p.injections = {
+ markx = dx,
+ marky = dy,
+ markdir = rlmode or 0,
+ markbase = nofregisteredmarks,
+ markbasenode = base,
+ markmark = mkmk,
+ }
+ end
+ else
+ properties[start] = {
+ injections = {
+ markx = dx,
+ marky = dy,
+ markdir = rlmode or 0,
+ markbase = nofregisteredmarks,
+ markbasenode = base,
+ markmark = mkmk,
+ },
+ }
+ end
+ return dx, dy, nofregisteredmarks
+end
+
+local function dir(n)
+ return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
+end
+
+local function showchar(n,nested)
+ local char = getchar(n)
+ report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char)
+end
+
+local function show(n,what,nested,symbol)
+ if n then
+ local p = rawget(properties,n)
+ if p then
+ local i = rawget(p,what)
+ if i then
+ local leftkern = i.leftkern or 0
+ local rightkern = i.rightkern or 0
+ local yoffset = i.yoffset or 0
+ local markx = i.markx or 0
+ local marky = i.marky or 0
+ local markdir = i.markdir or 0
+ local markbase = i.markbase or 0
+ local cursivex = i.cursivex or 0
+ local cursivey = i.cursivey or 0
+ local ligaindex = i.ligaindex or 0
+ local cursbase = i.cursiveanchor
+ local margin = nested and 4 or 2
+ --
+ if rightkern ~= 0 or yoffset ~= 0 then
+ report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
+ elseif leftkern ~= 0 then
+ report_injections("%w%s kern: dx %p",margin,symbol,leftkern)
+ end
+ if markx ~= 0 or marky ~= 0 or markbase ~= 0 then
+ report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
+ end
+ if cursivex ~= 0 or cursivey ~= 0 then
+ if cursbase then
+ report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ else
+ report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ end
+ elseif cursbase then
+ report_injections("%w%s curs: base",margin,symbol)
+ end
+ if ligaindex ~= 0 then
+ report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
+ end
+ end
+ end
+ end
+end
+
+local function showsub(n,what,where)
+ report_injections("begin subrun: %s",where)
+ for n in traverse_id(glyph_code,n) do
+ showchar(n,where)
+ show(n,what,where," ")
+ end
+ report_injections("end subrun")
+end
+
+local function trace(head,where)
+ report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
+ where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
+ local n = head
+ while n do
+ local id = getid(n)
+ if id == glyph_code then
+ showchar(n)
+ show(n,"injections",false," ")
+ show(n,"preinjections",false,"<")
+ show(n,"postinjections",false,">")
+ show(n,"replaceinjections",false,"=")
+ show(n,"emptyinjections",false,"*")
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(n)
+ if pre then
+ showsub(pre,"preinjections","pre")
+ end
+ if post then
+ showsub(post,"postinjections","post")
+ end
+ if replace then
+ showsub(replace,"replaceinjections","replace")
+ end
+ show(n,"emptyinjections",false,"*")
+ end
+ n = getnext(n)
+ end
+ report_injections("end run")
+end
+
+local function show_result(head)
+ local current = head
+ local skipping = false
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",
+ getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
+ skipping = false
+ elseif id == kern_code then
+ report_injections("kern: %p",getfield(current,"kern"))
+ skipping = false
+ elseif not skipping then
+ report_injections()
+ skipping = true
+ end
+ current = getnext(current)
+ end
+end
+
+-- G +D-pre G
+-- D-post+
+-- +D-replace+
+--
+-- G +D-pre +D-pre
+-- D-post +D-post
+-- +D-replace +D-replace
+
+local function inject_kerns_only(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"kerns")
+ end
+ local current = head
+ local prev = nil
+ local next = nil
+ local prevdisc = nil
+ local prevglyph = nil
+ local pre = nil -- saves a lookup
+ local post = nil -- saves a lookup
+ local replace = nil -- saves a lookup
+ local pretail = nil -- saves a lookup
+ local posttail = nil -- saves a lookup
+ local replacetail = nil -- saves a lookup
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ if id == glyph_code then
+ if getsubtype(current) < 256 then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ -- left|glyph|right
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(current,"xoffset",leftkern)
+ setfield(current,"xadvance",leftkern)
+ else
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ end
+ end
+ if prevdisc then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(post,"xadvance",leftkern)
+ else
+ insert_node_after(post,posttail,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(replace,"xadvance",leftkern)
+ else
+ insert_node_after(replace,replacetail,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ -- glyph|disc|glyph (special case)
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ end
+ end
+ end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
+ end
+ end
+ end
+ end
+ prevdisc = nil
+ prevglyph = current
+ elseif id == disc_code then
+ pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
+ local done = false
+ if pre then
+ -- left|pre glyphs|right
+ for n in traverse_char(pre) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+ local i = p.injections or p.preinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(pre,"xoffset",leftkern)
+ setfield(pre,"xadvance",leftkern)
+ else
+ pre = insert_node_before(pre,n,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ end
+ if post then
+ -- left|post glyphs|right
+ for n in traverse_char(post) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+ local i = p.injections or p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(post,"xoffset",leftkern)
+ setfield(post,"xadvance",leftkern)
+ else
+ post = insert_node_before(post,n,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ end
+ if replace then
+ -- left|replace glyphs|right
+ for n in traverse_char(replace) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+ local i = p.injections or p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ if use_advance then
+ setfield(replace,"xoffset",leftkern)
+ setfield(replace,"xadvance",leftkern)
+ else
+ replace = insert_node_before(replace,n,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ end
+ if done then
+ setdisc(current,pre,post,replace)
+ end
+ prevglyph = nil
+ prevdisc = current
+ else
+ prevglyph = nil
+ prevdisc = nil
+ end
+ prev = current
+ current = next
+ end
+ --
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredkerns = 0
+ end
+ return tonode(head), true
+end
+
+local function inject_pairs_only(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"pairs")
+ end
+ local current = head
+ local prev = nil
+ local next = nil
+ local prevdisc = nil
+ local prevglyph = nil
+ local pre = nil -- saves a lookup
+ local post = nil -- saves a lookup
+ local replace = nil -- saves a lookup
+ local pretail = nil -- saves a lookup
+ local posttail = nil -- saves a lookup
+ local replacetail = nil -- saves a lookup
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ if id == glyph_code then
+ if getsubtype(current) < 256 then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ -- left|glyph|right
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(current,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ -- glyph|disc|glyph (special case)
+-- is this okay?
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ if next and getid(next) == disc_code then
+ if replace then
+ -- error, we expect an empty one
+ else
+ setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
+ end
+ end
+ end
+ end
+ end
+ if prevdisc then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_after(post,posttail,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_after(replace,replacetail,newkern(leftkern))
+ done = true
+ end
+ end
+ else
+ local i = p.emptyinjections
+ if i then
+-- new .. okay?
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ end
+ end
+ end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
+ end
+ end
+ end
+ end
+ prevdisc = nil
+ prevglyph = current
+ elseif id == disc_code then
+ pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
+ local done = false
+ if pre then
+ -- left|pre glyphs|right
+ for n in traverse_char(pre) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+ local i = p.injections or p.preinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ pre = insert_node_before(pre,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(pre,n,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ if post then
+ -- left|post glyphs|right
+ for n in traverse_char(post) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+ local i = p.injections or p.postinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ post = insert_node_before(post,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(post,n,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ if replace then
+ -- left|replace glyphs|right
+ for n in traverse_char(replace) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+ local i = p.injections or p.replaceinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ replace = insert_node_before(replace,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(replace,n,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ if prevglyph then
+ if pre then
+ local p = rawget(properties,prevglyph)
+ if p then
+ -- local i = rawget(p,"preinjections")
+ local i = p.preinjections
+ if i then
+ -- glyph|pre glyphs
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ pre = insert_node_before(pre,pre,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ if replace then
+ local p = rawget(properties,prevglyph)
+ if p then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ -- glyph|replace glyphs
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ replace = insert_node_before(replace,replace,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ if done then
+ setdisc(current,pre,post,replace)
+ end
+ prevglyph = nil
+ prevdisc = current
+ else
+ prevglyph = nil
+ prevdisc = nil
+ end
+ prev = current
+ current = next
+ end
+ --
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredkerns = 0
+ end
+ return tonode(head), true
+end
+
+-- local function showoffset(n,flag)
+-- local ox = getfield(n,"xoffset")
+-- local oy = getfield(n,"yoffset")
+-- if flag then
+-- if ox == 0 then
+-- setcolor(n,oy == 0 and "darkgray" or "darkgreen")
+-- else
+-- setcolor(n,oy == 0 and "darkblue" or "darkred")
+-- end
+-- else
+-- if ox == 0 then
+-- setcolor(n,oy == 0 and "gray" or "green")
+-- else
+-- setcolor(n,oy == 0 and "blue" or "red")
+-- end
+-- end
+-- end
+
+local function showoffset(n,flag)
+ local o = getfield(n,"xoffset")
+ if o == 0 then
+ o = getfield(n,"yoffset")
+ end
+ if o ~= 0 then
+ setcolor(n,flag and "darkred" or "darkgreen")
+ else
+ resetcolor(n)
+ end
+end
+
+local function inject_everything(head,where)
+ head = tonut(head)
+ if trace_injections then
+ trace(head,"everything")
+ end
+ local hascursives = nofregisteredcursives > 0
+ local hasmarks = nofregisteredmarks > 0
+ --
+ local current = head
+ local last = nil
+ local font = font
+ local markdata = nil
+ local prev = nil
+ local next = nil
+ local prevdisc = nil
+ local prevglyph = nil
+ local pre = nil -- saves a lookup
+ local post = nil -- saves a lookup
+ local replace = nil -- saves a lookup
+ local pretail = nil -- saves a lookup
+ local posttail = nil -- saves a lookup
+ local replacetail = nil -- saves a lookup
+ --
+ local cursiveanchor = nil
+ local minc = 0
+ local maxc = 0
+ local glyphs = { }
+ local marks = { }
+ local nofmarks = 0
+ --
+ -- move out
+ --
+ local function processmark(p,n,pn) -- p = basenode
+ local px = getfield(p,"xoffset")
+ local ox = 0
+ local rightkern = nil
+ local pp = rawget(properties,p)
+ if pp then
+ -- pp = rawget(pp,"injections")
+ pp = pp.injections
+ if pp then
+ rightkern = pp.rightkern
+ end
+ end
+ if rightkern then -- x and w ~= 0
+ if pn.markdir < 0 then
+ -- kern(w-x) glyph(p) kern(x) mark(n)
+ ox = px - pn.markx - rightkern
+ -- report_injections("r2l case 1: %p",ox)
+ else
+ -- kern(x) glyph(p) kern(w-x) mark(n)
+ -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
+ --
+ -- According to Kai we don't need to handle leftkern here but I'm
+ -- pretty sure I've run into a case where it was needed so maybe
+ -- some day we need something more clever here.
+ --
+ if false then
+ -- a mark with kerning
+ local leftkern = pp.leftkern
+ if leftkern then
+ ox = px - pn.markx - leftkern
+ else
+ ox = px - pn.markx
+ end
+ else
+ ox = px - pn.markx
+ end
+ end
+ else
+ -- if pn.markdir < 0 then
+ -- ox = px - pn.markx
+ -- -- report_injections("r2l case 3: %p",ox)
+ -- else
+ -- -- ox = px - getfield(p,"width") + pn.markx
+ ox = px - pn.markx
+ -- report_injections("l2r case 3: %p",ox)
+ -- end
+ local wn = getfield(n,"width") -- in arial marks have widths
+ if wn ~= 0 then
+ -- bad: we should center
+ pn.leftkern = -wn/2
+ pn.rightkern = -wn/2
+ end
+ end
+ local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky
+ setfield(n,"xoffset",ox)
+ setfield(n,"yoffset",oy)
+ if trace_marks then
+ showoffset(n,true)
+ end
+ end
+ -- todo: marks in disc
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ if id == glyph_code then
+ if getsubtype(current) < 256 then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ local pm = i.markbasenode
+ if pm then
+ nofmarks = nofmarks + 1
+ marks[nofmarks] = current
+ else
+ if hascursives then
+ local cursivex = i.cursivex
+ if cursivex then
+ if cursiveanchor then
+ if cursivex ~= 0 then
+ i.leftkern = (i.leftkern or 0) + cursivex
+ end
+ if maxc == 0 then
+ minc = 1
+ maxc = 1
+ glyphs[1] = cursiveanchor
+ else
+ maxc = maxc + 1
+ glyphs[maxc] = cursiveanchor
+ end
+ properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops
+ last = current
+ else
+ maxc = 0
+ end
+ elseif maxc > 0 then
+ local ny = getfield(current,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ if trace_cursive then
+ showoffset(ti)
+ end
+ end
+ maxc = 0
+ cursiveanchor = nil
+ end
+ if i.cursiveanchor then
+ cursiveanchor = current -- no need for both now
+ else
+ if maxc > 0 then
+ local ny = getfield(current,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ if trace_cursive then
+ showoffset(ti)
+ end
+ end
+ maxc = 0
+ end
+ cursiveanchor = nil
+ end
+ end
+ -- left|glyph|right
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(current,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ -- glyph|disc|glyph (special case)
+-- okay?
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ if next and getid(next) == disc_code then
+ if replace then
+ -- error, we expect an empty one
+ else
+ setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
+ end
+ end
+ end
+ end
+ end
+ if prevdisc then
+ if p then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_after(post,posttail,newkern(leftkern))
+ done = true
+ end
+ end
+ end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_after(replace,replacetail,newkern(leftkern))
+ done = true
+ end
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ end
+ end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
+ end
+ end
+ end
+ else
+ -- cursive
+ if hascursives and maxc > 0 then
+ local ny = getfield(current,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- can be mark
+ end
+ maxc = 0
+ cursiveanchor = nil
+ end
+ end
+ end
+ prevdisc = nil
+ prevglyph = current
+ elseif id == disc_code then
+ pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
+ local done = false
+ if pre then
+ -- left|pre glyphs|right
+ for n in traverse_char(pre) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+ local i = p.injections or p.preinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ pre = insert_node_before(pre,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(pre,n,newkern(rightkern))
+ done = true
+ end
+ end
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
+ end
+ end
+ end
+ end
+ if post then
+ -- left|post glyphs|right
+ for n in traverse_char(post) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+ local i = p.injections or p.postinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ post = insert_node_before(post,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(post,n,newkern(rightkern))
+ done = true
+ end
+ end
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
+ end
+ end
+ end
+ end
+ if replace then
+ -- left|replace glyphs|right
+ for n in traverse_char(replace) do
+ local p = rawget(properties,n)
+ if p then
+ -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+ local i = p.injections or p.replaceinjections
+ if i then
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ replace = insert_node_before(replace,n,newkern(leftkern))
+ done = true
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(replace,n,newkern(rightkern))
+ done = true
+ end
+ end
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
+ end
+ end
+ end
+ end
+ if prevglyph then
+ if pre then
+ local p = rawget(properties,prevglyph)
+ if p then
+ -- local i = rawget(p,"preinjections")
+ local i = p.preinjections
+ if i then
+ -- glyph|pre glyphs
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ pre = insert_node_before(pre,pre,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ if replace then
+ local p = rawget(properties,prevglyph)
+ if p then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ -- glyph|replace glyphs
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ replace = insert_node_before(replace,replace,newkern(rightkern))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ if done then
+ setdisc(current,pre,post,replace)
+ end
+ prevglyph = nil
+ prevdisc = current
+ else
+ prevglyph = nil
+ prevdisc = nil
+ end
+ prev = current
+ current = next
+ end
+ -- cursive
+ if hascursives and maxc > 0 then
+ local ny = getfield(last,"yoffset")
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setfield(ti,"yoffset",ny) -- why not add ?
+ if trace_cursive then
+ showoffset(ti)
+ end
+ end
+ end
+ --
+ if nofmarks > 0 then
+ for i=1,nofmarks do
+ local m = marks[i]
+ local p = rawget(properties,m)
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ local b = i.markbasenode
+ processmark(b,m,i)
+ end
+ elseif hasmarks then
+ -- sometyhing bad happened
+ end
+ --
+ if keepregisteredcounts then
+ keepregisteredcounts = false
+ else
+ nofregisteredkerns = 0
+ nofregisteredpairs = 0
+ nofregisteredmarks = 0
+ nofregisteredcursives = 0
+ end
+ return tonode(head), true
+end
+
+-- space triggers
+
+local triggers = false
+
+function nodes.injections.setspacekerns(font,sequence)
+ if triggers then
+ triggers[font] = sequence
+ else
+ triggers = { [font] = sequence }
+ end
+end
+
+local function injectspaces(head)
+
+ if not triggers then
+ return head, false
+ end
+
+ local lastfont = nil
+ local spacekerns = nil
+ local leftkerns = nil
+ local rightkerns = nil
+ local factor = 0
+ local threshold = 0
+ local leftkern = false
+ local rightkern = false
+
+ local function updatefont(font,trig)
+ -- local resources = resources[font]
+ -- local spacekerns = resources.spacekerns
+ -- if spacekerns then
+ -- leftkerns = spacekerns.left
+ -- rightkerns = spacekerns.right
+ -- end
+ leftkerns = trig.left
+ rightkerns = trig.right
+ local par = parameters[font]
+ factor = par.factor
+ threshold = par.spacing.width - 1 -- get rid of rounding errors
+ lastfont = font
+ end
+
+ for n in traverse_id(glue_code,tonut(head)) do
+ local prev, next = getboth(n)
+ local prevchar = ischar(prev)
+ local nextchar = ischar(next)
+ if nextchar then
+ local font = getfont(next)
+ local trig = triggers[font]
+ if trig then
+ if lastfont ~= font then
+ updatefont(font,trig)
+ end
+ if rightkerns then
+ rightkern = rightkerns[nextchar]
+ end
+ end
+ end
+ if prevchar then
+ local font = getfont(next)
+ local trig = triggers[font]
+ if trig then
+ if lastfont ~= font then
+ updatefont(font,trig)
+ end
+ if leftkerns then
+ leftkern = leftkerns[prevchar]
+ end
+ end
+ end
+ if leftkern then
+ local old = getfield(n,"width")
+ if old >= threshold then
+ if rightkern then
+ local new = old + (leftkern + rightkern) * factor
+ if trace_spaces then
+ report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar)
+ end
+ setfield(n,"width",new)
+ leftkern = false
+ else
+ local new = old + leftkern * factor
+ if trace_spaces then
+ report_spaces("%C [%p -> %p]",prevchar,old,new)
+ end
+ setfield(n,"width",new)
+ end
+ end
+ leftkern = false
+ elseif rightkern then
+ local old = getfield(n,"width")
+ if old >= threshold then
+ local new = old + rightkern * factor
+ if trace_spaces then
+ report_spaces("[%p -> %p] %C",nextchar,old,new)
+ end
+ setfield(n,"width",new)
+ end
+ rightkern = false
+ end
+ end
+
+ triggers = false
+ return head, true
+end
+
+--
+
+function injections.handler(head,where)
+ if triggers then
+ head = injectspaces(head)
+ end
+ if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
+ return inject_everything(head,where)
+ elseif nofregisteredpairs > 0 then
+ return inject_pairs_only(head,where)
+ elseif nofregisteredkerns > 0 then
+ return inject_kerns_only(head,where)
+ else
+ return head, false
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua
new file mode 100644
index 00000000000..bcea2752015
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua
@@ -0,0 +1,839 @@
+if not modules then modules = { } end modules ['font-otl'] = {
+ 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",
+}
+
+-- After some experimenting with an alternative loader (one that is needed for
+-- getting outlines in mp) I decided not to be compatible with the old (built-in)
+-- one. The approach used in font-otn is as follows: we load the font in a compact
+-- format but still very compatible with the ff data structures. From there we
+-- create hashes to access the data efficiently. The implementation of feature
+-- processing is mostly based on looking at the data as organized in the glyphs and
+-- lookups as well as the specification. Keeping the lookup data in the glyphs is
+-- very instructive and handy for tracing. On the other hand hashing is what brings
+-- speed. So, the in the new approach (the old one will stay around too) we no
+-- longer keep data in the glyphs which saves us a (what in retrospect looks a bit
+-- like) a reconstruction step. It also means that the data format of the cached
+-- files changes. What method is used depends on that format. There is no fundamental
+-- change in processing, and not even in data organation. Most has to do with
+-- loading and storage.
+
+-- todo: less tounicodes
+
+local gmatch, find, match, lower, strip = string.gmatch, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack
+local abs = math.abs
+local ioflush = io.flush
+local derivetable = table.derive
+local formatters = string.formatters
+
+local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local registertracker = trackers.register
+local registerdirective = directives.register
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local elapsedtime = statistics.elapsedtime
+local findbinfile = resolvers.findbinfile
+
+----- trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+----- trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
+local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
+local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
+----- trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
+----- trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
+----- trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+otf.version = 3.018 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otl", otf.version, true)
+
+local otfreaders = otf.readers
+
+local hashes = fonts.hashes
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local otffeatures = constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local enhancers = allocate()
+otf.enhancers = enhancers
+local patches = { }
+enhancers.patches = patches
+
+local forceload = false
+local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
+local syncspace = true
+local forcenotdef = false
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+local wildcard = "*"
+local default = "dflt"
+
+local formats = fonts.formats
+
+formats.otf = "opentype"
+formats.ttf = "truetype"
+formats.ttc = "truetype"
+
+registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
+registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
+registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+
+-- local function load_featurefile(raw,featurefile)
+-- if featurefile and featurefile ~= "" then
+-- if trace_loading then
+-- report_otf("using featurefile %a", featurefile)
+-- end
+-- -- TODO: apply_featurefile(raw, featurefile)
+-- end
+-- end
+
+local ordered_enhancers = {
+ "check extra features",
+}
+
+local actions = allocate()
+local before = allocate()
+local after = allocate()
+
+patches.before = before
+patches.after = after
+
+local function enhance(name,data,filename,raw)
+ local enhancer = actions[name]
+ if enhancer then
+ if trace_loading then
+ report_otf("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ -- no message as we can have private ones
+ end
+end
+
+function enhancers.apply(data,filename,raw)
+ local basename = file.basename(lower(filename))
+ if trace_loading then
+ report_otf("%s enhancing file %a","start",filename)
+ end
+ ioflush() -- we want instant messages
+ for e=1,#ordered_enhancers do
+ local enhancer = ordered_enhancers[e]
+ local b = before[enhancer]
+ if b then
+ for pattern, action in next, b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a = after[enhancer]
+ if a then
+ for pattern, action in next, a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush() -- we want instant messages
+ end
+ if trace_loading then
+ report_otf("%s enhancing file %a","stop",filename)
+ end
+ ioflush() -- we want instant messages
+end
+
+-- patches.register("before","migrate metadata","cambria",function() end)
+
+function patches.register(what,where,pattern,action)
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
+ end
+end
+
+function patches.report(fmt,...)
+ if trace_loading then
+ report_otf("patching: %s",formatters[fmt](...))
+ end
+end
+
+function enhancers.register(what,action) -- only already registered can be overloaded
+ actions[what] = action
+end
+
+function otf.load(filename,sub,featurefile) -- second argument (format) is gone !
+ --
+ local featurefile = nil -- not supported (yet)
+ --
+ local base = file.basename(file.removesuffix(filename))
+ local name = file.removesuffix(base)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ if featurefile then
+ name = name .. "@" .. file.removesuffix(file.basename(featurefile))
+ end
+ -- sub can be number of string
+ if sub == "" then
+ sub = false
+ end
+ local hash = name
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ hash = containers.cleanname(hash)
+ local featurefiles
+ if featurefile then
+ featurefiles = { }
+ for s in gmatch(featurefile,"[^,]+") do
+ local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
+ if name == "" then
+ report_otf("loading error, no featurefile %a",s)
+ else
+ local attr = lfs.attributes(name)
+ featurefiles[#featurefiles+1] = {
+ name = name,
+ size = attr and attr.size or 0,
+ time = attr and attr.modification or 0,
+ }
+ end
+ end
+ if #featurefiles == 0 then
+ featurefiles = nil
+ end
+ end
+ local data = containers.read(otf.cache,hash)
+ local reload = not data or data.size ~= size or data.time ~= time or data.tableversion ~= otfreaders.tableversion
+ if forceload then
+ report_otf("forced reload of %a due to hard coded flag",filename)
+ reload = true
+ end
+ -- if not reload then
+ -- local featuredata = data.featuredata
+ -- if featurefiles then
+ -- if not featuredata or #featuredata ~= #featurefiles then
+ -- reload = true
+ -- else
+ -- for i=1,#featurefiles do
+ -- local fi, fd = featurefiles[i], featuredata[i]
+ -- if fi.name ~= fd.name or fi.size ~= fd.size or fi.time ~= fd.time then
+ -- reload = true
+ -- break
+ -- end
+ -- end
+ -- end
+ -- elseif featuredata then
+ -- reload = true
+ -- end
+ -- if reload then
+ -- report_otf("loading: forced reload due to changed featurefile specification %a",featurefile)
+ -- end
+ -- end
+ if reload then
+ report_otf("loading %a, hash %a",filename,hash)
+ --
+ starttiming(otfreaders)
+ data = otfreaders.loadfont(filename,sub or 1) -- we can pass the number instead (if it comes from a name search)
+ --
+ -- if featurefiles then
+ -- for i=1,#featurefiles do
+ -- load_featurefile(data,featurefiles[i].name)
+ -- end
+ -- end
+ --
+ --
+ if data then
+ otfreaders.compact(data)
+ otfreaders.rehash(data,"unicodes")
+ otfreaders.addunicodetable(data)
+ otfreaders.extend(data)
+ otfreaders.pack(data)
+ report_otf("loading done")
+ report_otf("saving %a in cache",filename)
+ data = containers.write(otf.cache, hash, data)
+ if cleanup > 1 then
+ collectgarbage("collect")
+ end
+ stoptiming(otfreaders)
+ if elapsedtime then -- not in generic
+ report_otf("loading, optimizing, packing and caching time %s", elapsedtime(otfreaders))
+ end
+ if cleanup > 3 then
+ collectgarbage("collect")
+ end
+ data = containers.read(otf.cache,hash) -- this frees the old table and load the sparse one
+ if cleanup > 2 then
+ collectgarbage("collect")
+ end
+ else
+ data = nil
+ report_otf("loading failed due to read error")
+ end
+ end
+ if data then
+ if trace_defining then
+ report_otf("loading from cache using hash %a",hash)
+ end
+ --
+ otfreaders.unpack(data)
+ otfreaders.expand(data) -- inline tables
+ otfreaders.addunicodetable(data) -- only when not done yet
+ --
+ enhancers.apply(data,filename,data)
+ --
+ constructors.addcoreunicodes(unicodes)
+ --
+ if applyruntimefixes then
+ applyruntimefixes(filename,data)
+ end
+ --
+ data.metadata.math = data.resources.mathconstants
+ end
+
+
+ return data
+end
+
+-- modes: node, base, none
+
+function otf.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
+ if okay then
+ return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
+ else
+ return { } -- will become false
+ end
+end
+
+-- the first version made a top/mid/not extensible table, now we just
+-- pass on the variants data and deal with it in the tfm scaler (there
+-- is no longer an extensible table anyway)
+--
+-- we cannot share descriptions as virtual fonts might extend them (ok,
+-- we could use a cache with a hash
+--
+-- we already assign an empty table to characters as we can add for
+-- instance protruding info and loop over characters; one is not supposed
+-- to change descriptions and if one does so one should make a copy!
+
+local function copytotfm(data,cache_id)
+ if data then
+ local metadata = data.metadata
+ local resources = data.resources
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { }
+ local parameters = { }
+ local mathparameters = { }
+ --
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ local spaceunits = 500
+ local spacer = "space"
+ local designsize = metadata.designsize or 100
+ local minsize = metadata.minsize or designsize
+ local maxsize = metadata.maxsize or designsize
+ local mathspecs = metadata.math
+ --
+ if designsize == 0 then
+ designsize = 100
+ minsize = 100
+ maxsize = 100
+ end
+ if mathspecs then
+ for name, value in next, mathspecs do
+ mathparameters[name] = value
+ end
+ end
+ for unicode in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ if mathspecs then
+ for unicode, character in next, characters do
+ local d = descriptions[unicode]
+ local m = d.math
+ if m then
+ -- watch out: luatex uses horiz_variants for the parts
+ --
+ local italic = m.italic
+ local vitalic = m.vitalic
+ --
+ local variants = m.hvariants
+ local parts = m.hparts
+ if variants then
+ local c = character
+ for i=1,#variants do
+ -- local un = variants[i].glyph
+ local un = variants[i]
+ c.next = un
+ c = characters[un]
+ end -- c is now last in chain
+ c.horiz_variants = parts
+ elseif parts then
+ character.horiz_variants = parts
+ italic = m.hitalic
+ end
+ --
+ local variants = m.vvariants
+ local parts = m.vparts
+ if variants then
+ local c = character
+ for i=1,#variants do
+ -- local un = variants[i].glyph
+ local un = variants[i]
+ c.next = un
+ c = characters[un]
+ end -- c is now last in chain
+ c.vert_variants = parts
+ elseif parts then
+ character.vert_variants = parts
+ end
+ --
+ if italic and italic ~= 0 then
+ character.italic = italic
+ end
+ --
+ if vitalic and vitalic ~= 0 then
+ character.vert_italic = vitalic
+ end
+ --
+ local accent = m.accent -- taccent?
+ if accent then
+ character.accent = accent
+ end
+ --
+ local kerns = m.kerns
+ if kerns then
+ character.mathkerns = kerns
+ end
+ end
+ end
+ end
+ -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't
+ -- we use the basename then?)
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname
+ local fullname = metadata.fullname or fontname
+ local psname = fontname or fullname
+ local units = metadata.units or 1000
+ --
+ if units == 0 then -- catch bugs in fonts
+ units = 1000 -- maybe 2000 when ttf
+ metadata.units = 1000
+ report_otf("changing %a units to %a",0,units)
+ end
+ --
+ local monospaced = metadata.monospaced
+ local charwidth = metadata.averagewidth -- or unset
+ local charxheight = metadata.xheight -- or unset
+ local italicangle = metadata.italicangle
+ local hasitalics = metadata.hasitalics
+ properties.monospaced = monospaced
+ properties.hasitalics = hasitalics
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ --
+ local space = 0x0020
+ local emdash = 0x2014
+ if monospaced then
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ else
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width/2, "emdash/2"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits) or 500 -- brrr
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits -- 3.333 (cmr10)
+ parameters.space_stretch = 1*units/2 -- 500 -- 1.666 (cmr10)
+ parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
+ parameters.x_height = 2*units/5 -- 400
+ parameters.quad = units -- 1000
+ if spaceunits < 2*units/5 then
+ -- todo: warning
+ end
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif syncspace then --
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink -- 1.111 (cmr10)
+ if charxheight then
+ parameters.x_height = charxheight
+ else
+ local x = 0x0078
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ end
+ --
+ parameters.designsize = (designsize/10)*65536
+ parameters.minsize = (minsize /10)*65536
+ parameters.maxsize = (maxsize /10)*65536
+ parameters.ascender = abs(metadata.ascender or 0)
+ parameters.descender = abs(metadata.descender or 0)
+ parameters.units = units
+ --
+ properties.space = spacer
+ properties.encodingbytes = 2
+ properties.format = data.format or formats.otf
+ properties.noglyphnames = true
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = psname
+ properties.name = filename or fullname
+ --
+ -- properties.name = specification.name
+ -- properties.sub = specification.sub
+ --
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ mathparameters = mathparameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ }
+ end
+end
+
+local function otftotfm(specification)
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache,cache_id)
+ if not tfmdata then
+ local name = specification.name
+ local sub = specification.sub
+ local subindex = specification.subindex
+ local filename = specification.filename
+ local features = specification.features.normal
+ local rawdata = otf.load(filename,sub,features and features.featurefile)
+ if rawdata and next(rawdata) then
+ local descriptions = rawdata.descriptions
+ rawdata.lookuphash = { } -- to be done
+ tfmdata = copytotfm(rawdata,cache_id)
+ if tfmdata and next(tfmdata) then
+ -- at this moment no characters are assigned yet, only empty slots
+ local features = constructors.checkedfeatures("otf",features)
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ -- shared.features = features -- default
+ shared.dynamics = { }
+ -- shared.processes = { }
+ tfmdata.changed = { }
+ shared.features = features
+ shared.processes = otf.setfeatures(tfmdata,features)
+ end
+ end
+ containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+end
+
+local function read_from_otf(specification)
+ local tfmdata = otftotfm(specification)
+ if tfmdata then
+ -- this late ? .. needs checking
+ tfmdata.properties.name = specification.name
+ tfmdata.properties.sub = specification.sub
+ --
+ tfmdata = constructors.scale(tfmdata,specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
+ constructors.setname(tfmdata,specification) -- only otf?
+ fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
+ end
+ return tfmdata
+end
+
+local function checkmathsize(tfmdata,mathsize)
+ local mathdata = tfmdata.shared.rawdata.metadata.math
+ local mathsize = tonumber(mathsize)
+ if mathdata then -- we cannot use mathparameters as luatex will complain
+ local parameters = tfmdata.parameters
+ parameters.scriptpercentage = mathdata.ScriptPercentScaleDown
+ parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown
+ parameters.mathsize = mathsize
+ end
+end
+
+registerotffeature {
+ name = "mathsize",
+ description = "apply mathsize specified in the font",
+ initializers = {
+ base = checkmathsize,
+ node = checkmathsize,
+ }
+}
+
+-- readers
+
+function otf.collectlookups(rawdata,kind,script,language)
+ if not kind then
+ return
+ end
+ if not script then
+ script = default
+ end
+ if not language then
+ language = default
+ end
+ local lookupcache = rawdata.lookupcache
+ if not lookupcache then
+ lookupcache = { }
+ rawdata.lookupcache = lookupcache
+ end
+ local kindlookup = lookupcache[kind]
+ if not kindlookup then
+ kindlookup = { }
+ lookupcache[kind] = kindlookup
+ end
+ local scriptlookup = kindlookup[script]
+ if not scriptlookup then
+ scriptlookup = { }
+ kindlookup[script] = scriptlookup
+ end
+ local languagelookup = scriptlookup[language]
+ if not languagelookup then
+ local sequences = rawdata.resources.sequences
+ local featuremap = { }
+ local featurelist = { }
+ if sequences then
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local features = sequence.features
+ if features then
+ features = features[kind]
+ if features then
+ -- features = features[script] or features[default] or features[wildcard]
+ features = features[script] or features[wildcard]
+ if features then
+ -- features = features[language] or features[default] or features[wildcard]
+ features = features[language] or features[wildcard]
+ if features then
+ if not featuremap[sequence] then
+ featuremap[sequence] = true
+ featurelist[#featurelist+1] = sequence
+ end
+ end
+ end
+ end
+ end
+ end
+ if #featurelist == 0 then
+ featuremap, featurelist = false, false
+ end
+ else
+ featuremap, featurelist = false, false
+ end
+ languagelookup = { featuremap, featurelist }
+ scriptlookup[language] = languagelookup
+ end
+ return unpack(languagelookup)
+end
+
+-- moved from font-oth.lua, todo: also afm
+
+local function getgsub(tfmdata,k,kind,value)
+ local shared = tfmdata.shared
+ local rawdata = shared and shared.rawdata
+ if rawdata then
+ local sequences = rawdata.resources.sequences
+ if sequences then
+ local properties = tfmdata.properties
+ local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ local choice = tonumber(value) or 1 -- no random here (yet)
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ for i=1,nofsteps do
+ local coverage = steps[i].coverage
+ if coverage then
+ local found = coverage[k]
+ if found then
+ return found, lookup.type
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.getgsub = getgsub -- returns value, gsub_kind
+
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if not found then
+ --
+ elseif kind == "gsub_single" then
+ return found
+ elseif kind == "gsub_alternate" then
+ local choice = tonumber(value) or 1 -- no random here (yet)
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+
+otf.getalternate = otf.getsubstitution
+
+function otf.getmultiple(tfmdata,k,kind)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if found and kind == "gsub_multiple" then
+ return found
+ end
+ return { k }
+end
+
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub
+ if kerns then
+ local found = kerns[right]
+ local kind = type(found)
+ if kind == "table" then
+ found = found[1][3] -- can be more clever
+ elseif kind ~= "number" then
+ found = false
+ end
+ if found then
+ return found * tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
+
+local function check_otf(forced,specification,suffix)
+ local name = specification.name
+ if forced then
+ name = specification.forcedname -- messy
+ end
+ local fullname = findbinfile(name,suffix) or ""
+ if fullname == "" then
+ fullname = fonts.names.getfilename(name,suffix) or ""
+ end
+ if fullname ~= "" and not fonts.names.ignoredfile(fullname) then
+ specification.filename = fullname
+ return read_from_otf(specification)
+ end
+end
+
+local function opentypereader(specification,suffix)
+ local forced = specification.forced or ""
+ if formats[forced] then
+ return check_otf(true,specification,forced)
+ else
+ return check_otf(false,specification,suffix)
+ end
+end
+
+readers.opentype = opentypereader -- kind of useless and obsolete
+
+function readers.otf (specification) return opentypereader(specification,"otf") end
+function readers.ttf (specification) return opentypereader(specification,"ttf") end
+function readers.ttc (specification) return opentypereader(specification,"ttf") end
+
+-- this will be overloaded
+
+function otf.scriptandlanguage(tfmdata,attr)
+ local properties = tfmdata.properties
+ return properties.script or "dflt", properties.language or "dflt"
+end
+
+-- a little bit of abstraction
+
+local function justset(coverage,unicode,replacement)
+ coverage[unicode] = replacement
+end
+
+otf.coverup = {
+ stepkey = "steps",
+ actions = {
+ chainsubstitution = justset,
+ chainposition = justset,
+ substitution = justset,
+ alternate = justset,
+ multiple = justset,
+ kern = justset,
+ pair = justset,
+ ligature = function(coverage,unicode,ligature)
+ local first = ligature[1]
+ local tree = coverage[first]
+ if not tree then
+ tree = { }
+ coverage[first] = tree
+ end
+ for i=2,#ligature do
+ local l = ligature[i]
+ local t = tree[l]
+ if not t then
+ t = { }
+ tree[l] = t
+ end
+ tree = t
+ end
+ tree.ligature = unicode
+ end,
+ },
+ register = function(coverage,featuretype,format)
+ return {
+ format = format,
+ coverage = coverage,
+ }
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otn.lua
new file mode 100644
index 00000000000..1c17e889de0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otn.lua
@@ -0,0 +1,3960 @@
+if not modules then modules = { } end modules ['font-otn'] = {
+ 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",
+}
+
+-- this is a context version which can contain experimental code, but when we
+-- have serious patches we also need to change the other two font-otn files
+
+-- at some point i might decide to convert the whole list into a table and then
+-- run over that instead (but it has some drawbacks as we also need to deal with
+-- attributes and such so we need to keep a lot of track - which is why i rejected
+-- that method - although it has become a bit easier in the meantime so it might
+-- become an alternative (by that time i probably have gone completely lua) .. the
+-- usual chicken-egg issues ... maybe mkix as it's no real tex any more then
+
+-- preprocessors = { "nodes" }
+
+-- anchor class : mark, mkmk, curs, mklg (todo)
+-- anchor type : mark, basechar, baselig, basemark, centry, cexit, max (todo)
+
+-- this is still somewhat preliminary and it will get better in due time;
+-- much functionality could only be implemented thanks to the husayni font
+-- of Idris Samawi Hamid to who we dedicate this module.
+
+-- in retrospect it always looks easy but believe it or not, it took a lot
+-- of work to get proper open type support done: buggy fonts, fuzzy specs,
+-- special made testfonts, many skype sessions between taco, idris and me,
+-- torture tests etc etc ... unfortunately the code does not show how much
+-- time it took ...
+
+-- todo:
+--
+-- extension infrastructure (for usage out of context)
+-- sorting features according to vendors/renderers
+-- alternative loop quitters
+-- check cursive and r2l
+-- find out where ignore-mark-classes went
+-- default features (per language, script)
+-- handle positions (we need example fonts)
+-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
+-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
+-- remove some optimizations (when I have a faster machine)
+--
+-- beware:
+--
+-- we do some disc jugling 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 needed
+--
+-- not possible:
+--
+-- \discretionary {alpha-} {betagammadelta}
+-- {\discretionary {alphabeta-} {gammadelta}
+-- {\discretionary {alphabetagamma-} {delta}
+-- {alphabetagammadelta}}}
+
+--[[ldx--
+<p>This module is a bit more split up that I'd like but since we also want to test
+with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/>
+and discussion about improvements and functionality mostly happens on the
+<l n='context'/> mailing list.</p>
+
+<p>The specification of OpenType is kind of vague. Apart from a lack of a proper
+free specifications there's also the problem that Microsoft and Adobe
+may have their own interpretation of how and in what order to apply features.
+In general the Microsoft website has more detailed specifications and is a
+better reference. There is also some information in the FontForge help files.</p>
+
+<p>Because there is so much possible, fonts might contain bugs and/or be made to
+work with certain rederers. These may evolve over time which may have the side
+effect that suddenly fonts behave differently.</p>
+
+<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another
+implementation. Of course all errors are mine and of course the code can be
+improved. There are quite some optimizations going on here and processing speed
+is currently acceptable. Not all functions are implemented yet, often because I
+lack the fonts for testing. Many scripts are not yet supported either, but I will
+look into them as soon as <l n='context'/> users ask for it.</p>
+
+<p>The specification leaves room for interpretation. In case of doubt the microsoft
+implementation is the reference as it is the most complete one. As they deal with
+lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
+their suggestions help improve the code. I'm aware that not all border cases can be
+taken care of, unless we accept excessive runtime, and even then the interference
+with other mechanisms (like hyphenation) are not trivial.</p>
+
+<p>Glyphs are indexed not by unicode but in their own way. This is because there is no
+relationship with unicode at all, apart from the fact that a font might cover certain
+ranges of characters. One character can have multiple shapes. However, at the
+<l n='tex'/> end we use unicode so and all extra glyphs are mapped into a private
+space. This is needed because we need to access them and <l n='tex'/> has to include
+then in the output eventually.</p>
+
+<p>The raw table as it coms from <l n='fontforge'/> gets reorganized in to fit out needs.
+In <l n='context'/> that table is packed (similar tables are shared) and cached on disk
+so that successive runs can use the optimized table (after loading the table is
+unpacked). The flattening code used later is a prelude to an even more compact table
+format (and as such it keeps evolving).</p>
+
+<p>This module is sparsely documented because it is a moving target. The table format
+of the reader changes and we experiment a lot with different methods for supporting
+features.</p>
+
+<p>As with the <l n='afm'/> code, we may decide to store more information in the
+<l n='otf'/> table.</p>
+
+<p>Incrementing the version number will force a re-cache. We jump the number by one
+when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that
+results in different tables.</p>
+--ldx]]--
+
+-- action handler chainproc
+--
+-- gsub_single ok ok
+-- gsub_multiple ok ok
+-- gsub_alternate ok ok
+-- gsub_ligature ok ok
+-- gsub_context ok --
+-- gsub_contextchain ok --
+-- gsub_reversecontextchain ok --
+-- chainsub -- ok
+-- reversesub -- ok
+-- gpos_mark2base ok ok
+-- gpos_mark2ligature ok ok
+-- gpos_mark2mark ok ok
+-- gpos_cursive ok untested
+-- gpos_single ok ok
+-- gpos_pair ok ok
+-- gpos_context ok --
+-- gpos_contextchain ok --
+--
+-- todo: contextpos
+--
+-- actions:
+--
+-- handler : actions triggered by lookup
+-- chainproc : actions triggered by contextual lookup
+-- chainmore : multiple substitutions triggered by contextual lookup (e.g. fij -> f + ij)
+--
+-- remark: the 'not implemented yet' variants will be done when we have fonts that use them
+
+-- We used to have independent hashes for lookups but as the tags are unique
+-- we now use only one hash. If needed we can have multiple again but in that
+-- case I will probably prefix (i.e. rename) the lookups in the cached font file.
+
+-- Todo: make plugin feature that operates on char/glyphnode arrays
+
+local type, next, tonumber = type, next, tonumber
+local random = math.random
+local formatters = string.formatters
+
+local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
+
+local registertracker = trackers.register
+local registerdirective = directives.register
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
+local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end)
+local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end)
+local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end)
+local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end)
+local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
+local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
+local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
+local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
+local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
+local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
+
+local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end)
+local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end)
+local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
+
+local quit_on_no_replacement = true -- maybe per font
+local zwnjruns = true
+
+registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
+
+local report_direct = logs.reporter("fonts","otf direct")
+local report_subchain = logs.reporter("fonts","otf subchain")
+local report_chain = logs.reporter("fonts","otf chain")
+local report_process = logs.reporter("fonts","otf process")
+local report_prepare = logs.reporter("fonts","otf prepare")
+local report_warning = logs.reporter("fonts","otf warning")
+local report_run = logs.reporter("fonts","otf run")
+
+registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
+registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
+
+registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
+registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
+registertracker("otf.actions","otf.replacements,otf.positions")
+registertracker("otf.injections","nodes.injections")
+
+registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local setnext = nuts.setnext
+local getprev = nuts.getprev
+local setprev = nuts.setprev
+local getid = nuts.getid
+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
+local setchar = nuts.setchar
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local delete_node = nuts.delete
+local remove_node = nuts.remove
+local copy_node = nuts.copy
+local copy_node_list = nuts.copy_list
+local find_node_tail = nuts.tail
+local flush_node_list = nuts.flush_list
+local free_node = nuts.free
+local end_of_math = nuts.end_of_math
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+
+local setmetatableindex = table.setmetatableindex
+
+local zwnj = 0x200C
+local zwj = 0x200D
+local wildcard = "*"
+local default = "dflt"
+
+local nodecodes = nodes.nodecodes
+local glyphcodes = nodes.glyphcodes
+local disccodes = nodes.disccodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+
+local discretionary_code = disccodes.discretionary
+local ligature_code = glyphcodes.ligature
+
+local privateattribute = attributes.private
+
+-- Something is messed up: we have two mark / ligature indices, one at the injection
+-- end and one here ... this is based on KE's patches but there is something fishy
+-- there as I'm pretty sure that for husayni we need some connection (as it's much
+-- more complex than an average font) but I need proper examples of all cases, not
+-- of only some.
+
+local a_state = privateattribute('state')
+local a_cursbase = privateattribute('cursbase') -- to be checked, probably can go
+
+local injections = nodes.injections
+local setmark = injections.setmark
+local setcursive = injections.setcursive
+local setkern = injections.setkern
+local setpair = injections.setpair
+local resetinjection = injections.reset
+local copyinjection = injections.copy
+local setligaindex = injections.setligaindex
+local getligaindex = injections.getligaindex
+
+local cursonce = true
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local onetimemessage = fonts.loggers.onetimemessage or function() end
+
+otf.defaultnodealternate = "none" -- first last
+
+-- we share some vars here, after all, we have no nested lookups and less code
+
+local tfmdata = false
+local characters = false
+local descriptions = false
+local resources = false
+local marks = false
+local currentfont = false
+local lookuptable = false
+local anchorlookups = false
+local lookuptypes = false
+local lookuptags = false
+local handlers = { }
+local rlmode = 0
+local featurevalue = false
+
+local sweephead = { }
+local sweepnode = nil
+local sweepprev = nil
+local sweepnext = nil
+
+local notmatchpre = { }
+local notmatchpost = { }
+local notmatchreplace = { }
+
+-- we use this for special testing and documentation
+
+local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
+local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
+local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_direct(...)
+end
+
+local function logwarning(...)
+ report_direct(...)
+end
+
+local f_unicode = formatters["%U"]
+local f_uniname = formatters["%U (%s)"]
+local f_unilist = formatters["% t (% t)"]
+
+local function gref(n) -- currently the same as in font-otb
+ if type(n) == "number" then
+ local description = descriptions[n]
+ local name = description and description.name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
+ end
+ elseif n then
+ local num, nam = { }, { }
+ for i=1,#n do
+ local ni = n[i]
+ if tonumber(ni) then -- later we will start at 2
+ local di = descriptions[ni]
+ num[i] = f_unicode(ni)
+ nam[i] = di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in node mode tracing>"
+ end
+end
+
+local function cref(kind,chainname,chainlookupname,lookupname,index) -- not in the mood to alias f_
+ if index then
+ return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookuptags[lookupname],index)
+ elseif lookupname then
+ return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookuptags[lookupname])
+ elseif chainlookupname then
+ return formatters["feature %a, chain %a, sub %a"](kind,lookuptags[chainname],lookuptags[chainlookupname])
+ elseif chainname then
+ return formatters["feature %a, chain %a"](kind,lookuptags[chainname])
+ else
+ return formatters["feature %a"](kind)
+ end
+end
+
+local function pref(kind,lookupname)
+ return formatters["feature %a, lookup %a"](kind,lookuptags[lookupname])
+end
+
+-- We can assume that languages that use marks are not hyphenated. We can also assume
+-- that at most one discretionary is present.
+
+-- We do need components in funny kerning mode but maybe I can better reconstruct then
+-- as we do have the font components info available; removing components makes the
+-- previous code much simpler. Also, later on copying and freeing becomes easier.
+-- However, for arabic we need to keep them around for the sake of mark placement
+-- and indices.
+
+local function copy_glyph(g) -- next and prev are untouched !
+ local components = getfield(g,"components")
+ if components then
+ setfield(g,"components",nil)
+ local n = copy_node(g)
+ copyinjection(n,g) -- we need to preserve the lig indices
+ setfield(g,"components",components)
+ return n
+ else
+ local n = copy_node(g)
+ copyinjection(n,g) -- we need to preserve the lig indices
+ return n
+ end
+end
+
+local function flattendisk(head,disc)
+ local replace = getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head == disc then
+ local next = getnext(disc)
+ if replace then
+ if next then
+ local tail = find_node_tail(replace)
+ setnext(tail,next)
+ setprev(next,tail)
+ end
+ return replace, replace
+ elseif next then
+ return next, next
+ else
+ return -- maybe warning
+ end
+ else
+ local next = getnext(disc)
+ local prev = getprev(disc)
+ if replace then
+ local tail = find_node_tail(replace)
+ if next then
+ setnext(tail,next)
+ setprev(next,tail)
+ end
+ setnext(prev,replace)
+ setprev(replace,prev)
+ return head, replace
+ else
+ if next then
+ setprev(next,prev)
+ end
+ setnext(prev,next)
+ return head, next
+ end
+ end
+end
+
+local function appenddisc(disc,list)
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
+ local phead = list
+ local rhead = copy_node_list(list)
+ local ptail = find_node_tail(post)
+ local rtail = find_node_tail(replace)
+ if post then
+ setnext(ptail,phead)
+ setprev(phead,ptail)
+ else
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setnext(rtail,rhead)
+ setprev(rhead,rtail)
+ else
+ setfield(disc,"replace",rhead)
+ end
+end
+
+-- start is a mark and we need to keep that one
+
+local function markstoligature(kind,lookupname,head,start,stop,char)
+ if start == stop and getchar(start) == char then
+ return head, start
+ else
+ local prev = getprev(start)
+ local next = getnext(stop)
+ setprev(start,nil)
+ setnext(stop,nil)
+ local base = copy_glyph(start)
+ if head == start then
+ head = base
+ end
+ resetinjection(base)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
+ setfield(base,"components",start)
+ if prev then
+ setnext(prev,base)
+ end
+ if next then
+ setprev(next,base)
+ end
+ setnext(base,next)
+ setprev(base,prev)
+ return head, base
+ end
+end
+
+-- The next code is somewhat complicated by the fact that some fonts can have ligatures made
+-- from ligatures that themselves have marks. This was identified by Kai in for instance
+-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
+-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
+-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
+-- third component.
+
+local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
+ if getid(start) ~= glyph_code then -- and then get rid of all components
+ return 0
+ elseif getsubtype(start) == ligature_code then
+ local i = 0
+ local components = getfield(start,"components")
+ while components do
+ i = i + getcomponentindex(components)
+ components = getnext(components)
+ end
+ return i
+ elseif not marks[getchar(start)] then
+ return 1
+ else
+ return 0
+ end
+end
+
+local a_noligature = attributes.private("noligature")
+
+local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
+ if getattr(start,a_noligature) == 1 then
+ -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+ return head, start
+ end
+ if start == stop and getchar(start) == char then
+ resetinjection(start)
+ setchar(start,char)
+ return head, start
+ end
+ -- needs testing (side effects):
+ local components = getfield(start,"components")
+ if components then
+ -- we get a double free .. needs checking
+ -- flush_node_list(components)
+ end
+ --
+ local prev = getprev(start)
+ local next = getnext(stop)
+ local comp = start
+ setprev(start,nil)
+ setnext(stop,nil)
+ local base = copy_glyph(start)
+ if start == head then
+ head = base
+ end
+ resetinjection(base)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
+ setfield(base,"components",comp) -- start can have components ... do we need to flush?
+ if prev then
+ setnext(prev,base)
+ end
+ if next then
+ setprev(next,base)
+ end
+ setprev(base,prev)
+ setnext(base,next)
+ if not discfound then
+ local deletemarks = markflag ~= "mark"
+ local components = start
+ local baseindex = 0
+ local componentindex = 0
+ local head = base
+ local current = base
+ -- first we loop over the glyphs in start .. stop
+ while start do
+ local char = getchar(start)
+ if not marks[char] then
+ baseindex = baseindex + componentindex
+ componentindex = getcomponentindex(start)
+ elseif not deletemarks then -- quite fishy
+ setligaindex(start,baseindex + getligaindex(start,componentindex))
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
+ end
+ local n = copy_node(start)
+ copyinjection(n,start)
+ head, current = insert_node_after(head,current,n) -- unlikely that mark has components
+ elseif trace_marks then
+ logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
+ end
+ start = getnext(start)
+ end
+ -- we can have one accent as part of a lookup and another following
+ -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
+ local start = getnext(current)
+ while start and getid(start) == glyph_code do
+ local char = getchar(start)
+ if marks[char] then
+ setligaindex(start,baseindex + getligaindex(start,componentindex))
+ if trace_marks then
+ logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
+ end
+ else
+ break
+ end
+ start = getnext(start)
+ end
+ else
+ -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
+ local discprev = getprev(discfound)
+ local discnext = getnext(discfound)
+ if discprev and discnext then
+ -- we assume normalization in context, and don't care about generic ... especially
+ -- \- can give problems as there we can have a negative char but that won't match
+ -- anyway
+ local pre = getfield(discfound,"pre")
+ local post = getfield(discfound,"post")
+ local replace = getfield(discfound,"replace")
+ if not replace then -- todo: signal simple hyphen
+ local prev = getprev(base)
+ local copied = copy_node_list(comp)
+ setprev(discnext,nil) -- also blocks funny assignments
+ setnext(discprev,nil) -- also blocks funny assignments
+ if pre then
+ setnext(discprev,pre)
+ setprev(pre,discprev)
+ end
+ pre = comp
+ if post then
+ local tail = find_node_tail(post)
+ setnext(tail,discnext)
+ setprev(discnext,tail)
+ setprev(post,nil)
+ else
+ post = discnext
+ end
+ setnext(prev,discfound)
+ setprev(discfound,prev)
+ setnext(discfound,next)
+ setprev(next,discfound)
+ setnext(base,nil)
+ setprev(base,nil)
+ setfield(base,"components",copied)
+ setfield(discfound,"pre",pre)
+ setfield(discfound,"post",post)
+ setfield(discfound,"replace",base)
+ setsubtype(discfound,discretionary_code)
+ base = prev -- restart
+ end
+ end
+ end
+ return head, base
+end
+
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples = #multiple
+ if nofmultiples > 0 then
+ resetinjection(start)
+ setchar(start,multiple[1])
+ if nofmultiples > 1 then
+ local sn = getnext(start)
+ for k=2,nofmultiples do -- todo: use insert_node
+-- untested:
+--
+-- while ignoremarks and marks[getchar(sn)] then
+-- local sn = getnext(sn)
+-- end
+ local n = copy_node(start) -- ignore components
+ resetinjection(n)
+ setchar(n,multiple[k])
+ setprev(n,start)
+ setnext(n,sn)
+ if sn then
+ setprev(sn,n)
+ end
+ setnext(start,n)
+ start = n
+ end
+ end
+ return head, start, true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head, start, false
+ end
+end
+
+local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
+ local n = #alternatives
+ if value == "random" then
+ local r = random(1,n)
+ return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
+ elseif value == "first" then
+ return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1)
+ elseif value == "last" then
+ return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n)
+ else
+ value = tonumber(value)
+ if type(value) ~= "number" then
+ return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
+ elseif value > n then
+ local defaultalt = otf.defaultnodealternate
+ if defaultalt == "first" then
+ return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
+ elseif defaultalt == "last" then
+ return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n)
+ else
+ return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
+ end
+ elseif value == 0 then
+ return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
+ elseif value < 1 then
+ return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
+ else
+ return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value)
+ end
+ end
+end
+
+-- handlers
+
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
+ end
+ resetinjection(start)
+ setchar(start,replacement)
+ return head, start, true
+end
+
+function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+ local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
+ end
+ resetinjection(start)
+ setchar(start,choice)
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
+ end
+ end
+ return head, start, true
+end
+
+function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
+ if trace_multiples then
+ logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
+ end
+ return multiple_glyphs(head,start,multiple,sequence.flags[1])
+end
+
+function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
+ local s, stop = getnext(start), nil
+ local startchar = getchar(start)
+ if marks[startchar] then
+ while s do
+ local id = getid(s)
+ if id == glyph_code and getfont(s) == currentfont and getsubtype(s)<256 then
+ local lg = ligature[getchar(s)]
+ if lg then
+ stop = s
+ ligature = lg
+ s = getnext(s)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if stop then
+ local lig = ligature.ligature
+ if lig then
+ if trace_ligatures then
+ local stopchar = getchar(stop)
+ head, start = markstoligature(kind,lookupname,head,start,stop,lig)
+ logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
+ else
+ head, start = markstoligature(kind,lookupname,head,start,stop,lig)
+ end
+ return head, start, true, false
+ else
+ -- ok, goto next lookup
+ end
+ end
+ else
+ local skipmark = sequence.flags[1]
+ local discfound = false
+ local lastdisc = nil
+ while s do
+ local id = getid(s)
+ if id == glyph_code and getsubtype(s)<256 then -- not needed
+ if getfont(s) == currentfont then -- also not needed only when mark
+ local char = getchar(s)
+ if skipmark and marks[char] then
+ s = getnext(s)
+ else -- ligature is a tree
+ local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
+ if lg then
+ if not discfound and lastdisc then
+ discfound = lastdisc
+ lastdisc = nil
+ end
+ stop = s -- needed for fake so outside then
+ ligature = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ else
+ break
+ end
+ elseif id == disc_code then
+ lastdisc = s
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ local lig = ligature.ligature -- can't we get rid of this .ligature?
+ if lig then
+ if stop then
+ if trace_ligatures then
+ local stopchar = getchar(stop)
+ head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
+ logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
+ else
+ head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
+ end
+ else
+ -- weird but happens (in some arabic font)
+ resetinjection(start)
+ setchar(start,lig)
+ if trace_ligatures then
+ logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
+ end
+ end
+ return head, start, true, discfound
+ else
+ -- weird but happens, pseudo ligatures ... just the components
+ end
+ end
+ return head, start, false, discfound
+end
+
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ local startchar = getchar(start)
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
+ end
+ return head, start, false
+end
+
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+ -- todo: kerns in components of ligatures
+ local snext = getnext(start)
+ if not snext then
+ return head, start, false
+ else
+ local prev = start
+ local done = false
+ local factor = tfmdata.parameters.factor
+ local lookuptype = lookuptypes[lookupname]
+ while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
+ local nextchar = getchar(snext)
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then -- probably not needed
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else -- wrong ... position has different entries
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ -- local a, b = krn[2], krn[6]
+ -- if a and a ~= 0 then
+ -- local k = setkern(snext,factor,rlmode,a)
+ -- if trace_kerns then
+ -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
+ -- end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) -- prev?
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+end
+
+--[[ldx--
+<p>We get hits on a mark, but we're not sure if the it has to be applied so
+we need to explicitly test for basechar, baselig and basemark entries.</p>
+--ldx]]--
+
+function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [start=mark]
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ local basechar = getchar(base)
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ basechar = getchar(base)
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+ end
+ end
+ end
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ end
+ if baseanchors then
+ local baseanchors = baseanchors['basechar']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s, no matching anchors for mark %s and base %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",pref(kind,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
+ -- check chainpos variant
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [optional marks] [start=mark]
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ local basechar = getchar(base)
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ basechar = getchar(base)
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+ end
+ end
+ end
+ local index = getligaindex(start)
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ if baseanchors then
+ local baseanchors = baseanchors['baselig']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor, ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar]) -- index
+ if trace_marks then
+ logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
+ else
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(kind,lookupname),gref(markchar),gref(basechar),index)
+ end
+ end
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",pref(kind,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [basemark] [start=mark]
+ local slc = getligaindex(start)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = getligaindex(base)
+ if blc and blc ~= slc then
+ base = getprev(base)
+ else
+ break
+ end
+ end
+ end
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
+ local basechar = getchar(base)
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ if baseanchors then
+ baseanchors = baseanchors['basemark']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked
+ local alreadydone = cursonce and getprop(start,a_cursbase)
+ if not alreadydone then
+ local done = false
+ local startchar = getchar(start)
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
+ end
+ else
+ local nxt = getnext(start)
+ while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
+ local nextchar = getchar(nxt)
+ if marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = getnext(nxt)
+ else
+ local entryanchors = descriptions[nextchar]
+ if entryanchors then
+ entryanchors = entryanchors.anchors
+ if entryanchors then
+ entryanchors = entryanchors['centry']
+ if entryanchors then
+ local al = anchorlookups[lookupname]
+ for anchor, entry in next, entryanchors do
+ if al[anchor] then
+ local exit = exitanchors[anchor]
+ if exit then
+ local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
+ end
+ done = true
+ break
+ end
+ end
+ end
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
+ onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
+ end
+ break
+ end
+ end
+ end
+ return head, start, done
+ else
+ if trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
+ end
+ return head, start, false
+ end
+end
+
+--[[ldx--
+<p>I will implement multiple chain replacements once I run into a font that uses
+it. It's not that complex to handle.</p>
+--ldx]]--
+
+local chainprocs = { }
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_subchain(...)
+end
+
+local logwarning = report_subchain
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_chain(...)
+end
+
+local logwarning = report_chain
+
+-- We could share functions but that would lead to extra function calls with many
+-- arguments, redundant tests and confusing messages.
+
+function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname)
+ logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
+ return head, start, false
+end
+
+-- The reversesub is a special case, which is why we need to store the replacements
+-- in a bit weird way. There is no lookup and the replacement comes from the lookup
+-- itself. It is meant mostly for dealing with Urdu.
+
+function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
+ local char = getchar(start)
+ local replacement = replacements[char]
+ if replacement then
+ if trace_singles then
+ logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
+ end
+ resetinjection(start)
+ setchar(start,replacement)
+ return head, start, true
+ else
+ return head, start, false
+ end
+end
+
+--[[ldx--
+<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be
+applied: single, alternate, multiple or ligature where ligature can be an invalid
+one in the sense that it will replace multiple by one but not neccessary one that
+looks like the combination (i.e. it is the counterpart of multiple then). For
+example, the following is valid:</p>
+
+<typing>
+<line>xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx</line>
+</typing>
+
+<p>Therefore we we don't really do the replacement here already unless we have the
+single lookup case. The efficiency of the replacements can be improved by deleting
+as less as needed but that would also make the code even more messy.</p>
+--ldx]]--
+
+-- local function delete_till_stop(head,start,stop,ignoremarks) -- keeps start
+-- local n = 1
+-- if start == stop then
+-- -- done
+-- elseif ignoremarks then
+-- repeat -- start x x m x x stop => start m
+-- local next = getnext(start)
+-- if not marks[getchar(next)] then
+-- local components = getnext(next,"components")
+-- if components then -- probably not needed
+-- flush_node_list(components)
+-- end
+-- head = delete_node(head,next)
+-- end
+-- n = n + 1
+-- until next == stop
+-- else -- start x x x stop => start
+-- repeat
+-- local next = getnext(start)
+-- local components = getfield(next,"components")
+-- if components then -- probably not needed
+-- flush_node_list(components)
+-- end
+-- head = delete_node(head,next)
+-- n = n + 1
+-- until next == stop
+-- end
+-- return head, n
+-- end
+
+--[[ldx--
+<p>Here we replace start by a single variant.</p>
+--ldx]]--
+
+function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
+ -- todo: marks ?
+ local current = start
+ local subtables = currentlookup.subtables
+ if #subtables > 1 then
+ logwarning("todo: check if we need to loop over the replacements: % t",subtables)
+ end
+ while current do
+ if getid(current) == glyph_code then
+ local currentchar = getchar(current)
+ local lookupname = subtables[1] -- only 1
+ local replacement = lookuphash[lookupname]
+ if not replacement then
+ if trace_bugs then
+ logwarning("%s: no single hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
+ end
+ else
+ replacement = replacement[currentchar]
+ if not replacement or replacement == "" then
+ if trace_bugs then
+ logwarning("%s: no single for %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar))
+ end
+ else
+ if trace_singles then
+ logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
+ end
+ resetinjection(current)
+ setchar(current,replacement)
+ end
+ end
+ return head, start, true
+ elseif current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>Here we replace start by a sequence of new glyphs.</p>
+--ldx]]--
+
+function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ -- local head, n = delete_till_stop(head,start,stop)
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local replacements = lookuphash[lookupname]
+ if not replacements then
+ if trace_bugs then
+ logwarning("%s: no multiple hits",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ else
+ replacements = replacements[startchar]
+ if not replacements or replacement == "" then
+ if trace_bugs then
+ logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar))
+ end
+ else
+ if trace_multiples then
+ logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements))
+ end
+ return multiple_glyphs(head,start,replacements,currentlookup.flags[1])
+ end
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
+--ldx]]--
+
+-- char_1 mark_1 -> char_x mark_1 (ignore marks)
+-- char_1 mark_1 -> char_x
+
+-- to be checked: do we always have just one glyph?
+-- we can also have alternates for marks
+-- marks come last anyway
+-- are there cases where we need to delete the mark
+
+function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ local current = start
+ local subtables = currentlookup.subtables
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+ while current do
+ if getid(current) == glyph_code then -- is this check needed?
+ local currentchar = getchar(current)
+ local lookupname = subtables[1]
+ local alternatives = lookuphash[lookupname]
+ if not alternatives then
+ if trace_bugs then
+ logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ else
+ alternatives = alternatives[currentchar]
+ if alternatives then
+ local choice, comment = get_alternative_glyph(current,alternatives,value,trace_alternatives)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
+ end
+ resetinjection(start)
+ setchar(start,choice)
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: no alternative for %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar),comment)
+ end
+ end
+ return head, start, true
+ elseif current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>When we replace ligatures we use a helper that handles the marks. I might change
+this function (move code inline and handle the marks by a separate function). We
+assume rather stupid ligatures (no complex disc nodes).</p>
+--ldx]]--
+
+function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local ligatures = lookuphash[lookupname]
+ if not ligatures then
+ if trace_bugs then
+ logwarning("%s: no ligature hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
+ end
+ else
+ ligatures = ligatures[startchar]
+ if not ligatures then
+ if trace_bugs then
+ logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
+ end
+ else
+ local s = getnext(start)
+ local discfound = false
+ local last = stop
+ local nofreplacements = 1
+ local skipmark = currentlookup.flags[1]
+ while s do
+ local id = getid(s)
+ if id == disc_code then
+ if not discfound then
+ discfound = s
+ end
+ if s == stop then
+ break -- okay? or before the disc
+ else
+ s = getnext(s)
+ end
+ else
+ local schar = getchar(s)
+ if skipmark and marks[schar] then -- marks
+ s = getnext(s)
+ else
+ local lg = ligatures[schar]
+ if lg then
+ ligatures, last, nofreplacements = lg, s, nofreplacements + 1
+ if s == stop then
+ break
+ else
+ s = getnext(s)
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+ local l2 = ligatures.ligature
+ if l2 then
+ if chainindex then
+ stop = last
+ end
+ if trace_ligatures then
+ if start == stop then
+ logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
+ else
+ logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
+ end
+ end
+ head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
+ return head, start, true, nofreplacements, discfound
+ elseif trace_bugs then
+ if start == stop then
+ logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
+ else
+ logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)))
+ end
+ end
+ end
+ end
+ return head, start, false, 0, false
+end
+
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ -- untested .. needs checking for the new model
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar] -- needed ?
+ if kerns then
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext = getnext(start)
+ if snext then
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar]
+ if kerns then
+ local lookuptype = lookuptypes[lookupname]
+ local prev, done = start, false
+ local factor = tfmdata.parameters.factor
+ while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
+ local nextchar = getchar(snext)
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b) -- ,characters[nextchar])
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ -- local a, b = krn[2], krn[6]
+ -- if a and a ~= 0 then
+ -- local k = setkern(snext,factor,rlmode,a)
+ -- if trace_kerns then
+ -- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
+ -- end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = lookuphash[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = getprev(start) -- [glyph] [start=mark]
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ local basechar = getchar(base)
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ basechar = getchar(base)
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return head, start, false
+ end
+ end
+ end
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ local baseanchors = baseanchors['basechar']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s, no matching anchors for mark %s and base %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = lookuphash[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = getprev(start) -- [glyph] [optional marks] [start=mark]
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ local basechar = getchar(base)
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
+ basechar = getchar(base)
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar)
+ end
+ return head, start, false
+ end
+ end
+ end
+ -- todo: like marks a ligatures hash
+ local index = getligaindex(start)
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ local baseanchors = baseanchors['baselig']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("feature %s, lookup %s: prev node is no char",kind,lookupname)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = lookuphash[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = getprev(start) -- [glyph] [basemark] [start=mark]
+ local slc = getligaindex(start)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = getligaindex(base)
+ if blc and blc ~= slc then
+ base = getprev(base)
+ else
+ break
+ end
+ end
+ end
+ if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
+ local basechar = getchar(base)
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ baseanchors = baseanchors['basemark']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+ local alreadydone = cursonce and getprop(start,a_cursbase)
+ if not alreadydone then
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local exitanchors = lookuphash[lookupname]
+ if exitanchors then
+ exitanchors = exitanchors[startchar]
+ end
+ if exitanchors then
+ local done = false
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
+ end
+ else
+ local nxt = getnext(start)
+ while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
+ local nextchar = getchar(nxt)
+ if marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = getnext(nxt)
+ else
+ local entryanchors = descriptions[nextchar]
+ if entryanchors then
+ entryanchors = entryanchors.anchors
+ if entryanchors then
+ entryanchors = entryanchors['centry']
+ if entryanchors then
+ local al = anchorlookups[lookupname]
+ for anchor, entry in next, entryanchors do
+ if al[anchor] then
+ local exit = exitanchors[anchor]
+ if exit then
+ local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
+ end
+ done = true
+ break
+ end
+ end
+ end
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
+ onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
+ end
+ break
+ end
+ end
+ end
+ return head, start, done
+ else
+ if trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
+ end
+ return head, start, false
+ end
+ end
+ return head, start, false
+end
+
+-- what pointer to return, spec says stop
+-- to be discussed ... is bidi changer a space?
+-- elseif char == zwnj and sequence[n][32] then -- brrr
+
+-- somehow l or f is global
+-- we don't need to pass the currentcontext, saves a bit
+-- make a slow variant then can be activated but with more tracing
+
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+
+-- A previous version had disc collapsing code in the (single sub) handler plus some
+-- checking in the main loop, but that left the pre/post sequences undone. The best
+-- solution is to add some checking there and backtrack when a replace/post matches
+-- but it takes a bit of work to figure out an efficient way (this is what the sweep*
+-- names refer to). I might look into that variant one day again as it can replace
+-- some other code too. In that approach we can have a special version for gub and pos
+-- which gains some speed. This method does the test and passes info to the handlers
+-- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
+-- main loop which also makes code elsewhere simpler (i.e. no need for the other special
+-- runners and disc code in ligature building). I also experimented with pushing preceding
+-- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
+-- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
+--
+-- In the meantime Kai had moved the code from the single chain into a more general handler
+-- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
+-- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
+-- complex approach is meant for fonts that implement (for instance) ligatures by character
+-- replacement which to some extend is not that suitable for hyphenation. I also use some
+-- helpers. This method passes some states but reparses the list. There is room for a bit of
+-- speed up but that will be done in the context version. (In fact a partial rewrite of all
+-- code can bring some more efficientry.)
+--
+-- I didn't test it with extremes but successive disc nodes still can give issues but in
+-- order to handle that we need more complex code which also slows down even more. The main
+-- loop variant could deal with that: test, collapse, backtrack.
+
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+
+ if not start then
+ return head, start, false
+ end
+
+ local startishead = start == head
+ local seq = ck[3]
+ local f = ck[4]
+ local l = ck[5]
+ local s = #seq
+ local done = false
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local sweepoverflow = false
+ local checkdisc = getprev(head) -- hm bad name head
+ local keepdisc = not sweepnode
+ local lookaheaddisc = nil
+ local backtrackdisc = nil
+ local current = start
+ local last = start
+ local prev = getprev(start)
+
+ -- fishy: so we can overflow and then go on in the sweep?
+
+ local i = f
+ while i <= l do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i <= l do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ last = current
+ current = getnext(c)
+ else
+ head, current = flattendisk(head,current)
+ end
+ else
+ last = current
+ current = getnext(current)
+ end
+ if current then
+ -- go on
+ elseif sweepoverflow then
+ -- we already are folling up on sweepnode
+ break
+ elseif sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ sweepoverflow = true
+ else
+ break
+ end
+ else
+ break -- added
+ end
+ end
+
+ if sweepoverflow then
+ local prev = current and getprev(current)
+ if not current or prev ~= sweepnode then
+ local head = getnext(sweepnode)
+ local tail = nil
+ if prev then
+ tail = prev
+ setprev(current,sweepnode)
+ else
+ tail = find_node_tail(head)
+ end
+ setnext(sweepnode,current)
+ setprev(head,nil)
+ setnext(tail,nil)
+ appenddisc(sweepnode,head)
+ end
+ end
+
+ if l < s then
+ local i = l
+ local t = sweeptype == "post" or sweeptype == "replace"
+ while current and i < s do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(c,"replace")
+ while replace and i < s do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ current = getnext(current)
+ elseif notmatchpre[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ else
+ current = getnext(current) -- HH
+ end
+ else
+ current = getnext(current)
+ end
+ if not current and t then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ end
+ end
+ end
+ end
+
+ if f > 1 then
+ local current = prev
+ local i = f
+ local t = sweeptype == "pre" or sweeptype == "replace"
+ if not current and t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ while current and i > 1 do -- missing getprev added / moved outside
+ local id = getid(current)
+ if id == glyph_code then
+ i = i - 1
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpost[current] ~= notmatchreplace[current] then
+ backtrackdisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i > 1 do
+ if getid(replace) == glyph_code then
+ i = i - 1
+ end
+ replace = getnext(replace)
+ end
+ elseif notmatchpost[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ end
+ end
+ current = getprev(current)
+ if t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ end
+ end
+
+ local ok = false
+ if lookaheaddisc then
+
+ local cf = start
+ local cl = getprev(lookaheaddisc)
+ local cprev = getprev(start)
+ local insertedmarks = 0
+
+ while cprev and getid(cf) == glyph_code and getfont(cf) == currentfont and getsubtype(cf) < 256 and marks[getchar(cf)] do
+ insertedmarks = insertedmarks + 1
+ cf = cprev
+ startishead = cf == head
+ cprev = getprev(cprev)
+ end
+
+ setprev(lookaheaddisc,cprev)
+ if cprev then
+ setnext(cprev,lookaheaddisc)
+ end
+ setprev(cf,nil)
+ setnext(cl,nil)
+ if startishead then
+ head = lookaheaddisc
+ end
+
+ local replace = getfield(lookaheaddisc,"replace")
+ local pre = getfield(lookaheaddisc,"pre")
+ local new = copy_node_list(cf)
+ local cnew = new
+ for i=1,insertedmarks do
+ cnew = getnext(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setnext(cl,pre)
+ setprev(pre,cl)
+ end
+ if replace then
+ local tail = find_node_tail(new)
+ setnext(tail,replace)
+ setprev(replace,tail)
+ end
+ setfield(lookaheaddisc,"pre",cf) -- also updates tail
+ setfield(lookaheaddisc,"replace",new) -- also updates tail
+
+ start = getprev(lookaheaddisc)
+ sweephead[cf] = getnext(clast)
+ sweephead[new] = getnext(last)
+
+ elseif backtrackdisc then
+
+ local cf = getnext(backtrackdisc)
+ local cl = start
+ local cnext = getnext(start)
+ local insertedmarks = 0
+
+ while cnext and getid(cnext) == glyph_code and getfont(cnext) == currentfont and getsubtype(cnext) < 256 and marks[getchar(cnext)] do
+ insertedmarks = insertedmarks + 1
+ cl = cnext
+ cnext = getnext(cnext)
+ end
+ if cnext then
+ setprev(cnext,backtrackdisc)
+ end
+ setnext(backtrackdisc,cnext)
+ setprev(cf,nil)
+ setnext(cl,nil)
+ local replace = getfield(backtrackdisc,"replace")
+ local post = getfield(backtrackdisc,"post")
+ local new = copy_node_list(cf)
+ local cnew = find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew = getprev(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail = find_node_tail(post)
+ setnext(tail,cf)
+ setprev(cf,tail)
+ else
+ post = cf
+ end
+ if replace then
+ local tail = find_node_tail(replace)
+ setnext(tail,new)
+ setprev(new,tail)
+ else
+ replace = new
+ end
+ setfield(backtrackdisc,"post",post) -- also updates tail
+ setfield(backtrackdisc,"replace",replace) -- also updates tail
+ start = getprev(backtrackdisc)
+ sweephead[post] = getnext(clast)
+ sweephead[replace] = getnext(last)
+
+ else
+
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+
+ end
+
+ return head, start, ok
+end
+
+local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local diskseen = false
+ local checkdisc = getprev(head)
+ local flags = sequence.flags
+ local done = false
+ local skipmark = flags[1]
+ local skipligature = flags[2]
+ local skipbase = flags[3]
+ local markclass = sequence.markclass
+ local skipped = false
+
+ for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
+ local match = true
+ local current = start
+ local last = start
+ local ck = contexts[k]
+ local seq = ck[3]
+ local s = #seq
+ -- f..l = mid string
+ if s == 1 then
+ -- never happens
+ match = getid(current) == glyph_code and getfont(current) == currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
+ else
+ -- maybe we need a better space check (maybe check for glue or category or combination)
+ -- we cannot optimize for n=2 because there can be disc nodes
+ local f = ck[4]
+ local l = ck[5]
+ -- current match
+ if f == 1 and f == l then -- current only
+ -- already a hit
+ -- match = true
+ else -- before/current/after | before/current | current/after
+ -- no need to test first hit (to be optimized)
+ if f == l then -- new, else last out of sync (f is > 1)
+ -- match = true
+ else
+ local discfound = nil
+ local n = f + 1
+ last = getnext(last)
+ while n <= l do
+ if not last and (sweeptype == "post" or sweeptype == "replace") then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
+ if last then
+ local id = getid(last)
+ if id == glyph_code then
+ if getfont(last) == currentfont and getsubtype(last)<256 then
+ local char = getchar(last)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class or "base"
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ last = getnext(last)
+ elseif seq[n][char] then
+ if n < l then
+ last = getnext(last)
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ elseif id == disc_code then
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre = getfield(last,"pre")
+ local replace = getfield(last,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > l then
+ break
+ end
+ else
+ notmatchpre[last] = true
+ break
+ end
+ end
+ if n <= l then
+ notmatchpre[last] = true
+ end
+ else
+ notmatchpre[last] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > l then
+ break
+ end
+ else
+ notmatchreplace[last] = true
+ match = not notmatchpre[last]
+ break
+ end
+ end
+ match = not notmatchpre[last]
+ end
+ last = getnext(last)
+ else
+ match = false
+ break
+ end
+ else
+ match = false
+ break
+ end
+ end
+ end
+ end
+ -- before
+ if match and f > 1 then
+ local prev = getprev(start)
+ if prev then
+ if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
+ prev = getprev(sweepnode)
+ -- sweeptype = nil
+ end
+ if prev then
+ local discfound = nil
+ local n = f - 1
+ while n >= 1 do
+ if prev then
+ local id = getid(prev)
+ if id == glyph_code then
+ if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
+ local char = getchar(prev)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n -1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ elseif id == disc_code then
+ -- the special case: f i where i becomes dottless i ..
+ diskseen = true
+ discfound = prev
+ notmatchpre[prev] = true
+ notmatchpost[prev] = nil
+ notmatchreplace[prev] = nil
+ local pre = getfield(prev,"pre")
+ local post = getfield(prev,"post")
+ local replace = getfield(prev,"replace")
+ if pre ~= start and post ~= start and replace ~= start then
+ if post then
+ local n = n
+ local posttail = find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n = n - 1
+ if posttail == post then
+ break
+ else
+ posttail = getprev(posttail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev] = true
+ break
+ end
+ end
+ if n >= 1 then
+ notmatchpost[prev] = true
+ end
+ else
+ notmatchpost[prev] = true
+ end
+ if replace then
+ -- we seldom enter this branch (e.g. on brill efficient)
+ local replacetail = find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n = n - 1
+ if replacetail == replace then
+ break
+ else
+ replacetail = getprev(replacetail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev] = true
+ match = not notmatchpost[prev]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ -- skip 'm
+ end
+ else
+ -- skip 'm
+ end
+ elseif seq[n][32] then
+ n = n -1
+ else
+ match = false
+ break
+ end
+ prev = getprev(prev)
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
+ n = n - 1
+ else
+ match = false
+ break
+ end
+ end
+ else
+ match = false
+ end
+ else
+ match = false
+ end
+ end
+ -- after
+ if match and s > l then
+ local current = last and getnext(last)
+ if not current then
+ if sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ -- sweeptype = nil
+ end
+ end
+ if current then
+ local discfound = nil
+ -- removed optimization for s-l == 1, we have to deal with marks anyway
+ local n = l + 1
+ while n <= s do
+ if current then
+ local id = getid(current)
+ if id == glyph_code then
+ if getfont(current) == currentfont and getsubtype(current)<256 then -- normal char
+ local char = getchar(current)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ elseif id == disc_code then
+ diskseen = true
+ discfound = current
+ notmatchpre[current] = nil
+ notmatchpost[current] = true
+ notmatchreplace[current] = nil
+ local pre = getfield(current,"pre")
+ local replace = getfield(current,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > s then
+ break
+ end
+ else
+ notmatchpre[current] = true
+ break
+ end
+ end
+ if n <= s then
+ notmatchpre[current] = true
+ end
+ else
+ notmatchpre[current] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > s then
+ break
+ end
+ else
+ notmatchreplace[current] = true
+ match = notmatchpre[current]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ -- skip 'm
+ end
+ elseif seq[n][32] then -- brrr
+ n = n + 1
+ else
+ match = false
+ break
+ end
+ current = getnext(current)
+ elseif seq[n][32] then
+ n = n + 1
+ else
+ match = false
+ break
+ end
+ end
+ else
+ match = false
+ end
+ end
+ end
+ if match then
+ -- can lookups be of a different type ?
+ local diskchain = diskseen or sweepnode
+ if trace_contexts then
+ local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
+ local char = getchar(start)
+ if ck[9] then
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
+ cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
+ else
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
+ cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype)
+ end
+ end
+ local chainlookups = ck[6]
+ if chainlookups then
+ local nofchainlookups = #chainlookups
+ -- we can speed this up if needed
+ if nofchainlookups == 1 then
+ local chainlookupname = chainlookups[1]
+ local chainlookup = lookuptable[chainlookupname]
+ if chainlookup then
+ local chainproc = chainprocs[chainlookup.type]
+ if chainproc then
+ local ok
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if ok then
+ done = true
+ end
+ else
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ end
+ else -- shouldn't happen
+ logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname))
+ end
+ else
+ local i = 1
+ while start and true do
+ if skipped then
+ while true do -- todo: use properties
+ local char = getchar(start)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class or "base"
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ start = getnext(start)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
+ local chainlookupname = chainlookups[i]
+ local chainlookup = lookuptable[chainlookupname]
+ if not chainlookup then
+ -- we just advance
+ i = i + 1
+ else
+ local chainproc = chainprocs[chainlookup.type]
+ if not chainproc then
+ -- actually an error
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ i = i + 1
+ else
+ local ok, n
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok, n = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
+ -- messy since last can be changed !
+ if ok then
+ done = true
+ if n and n > 1 then
+ -- we have a ligature (cf the spec we advance one but we really need to test it
+ -- as there are fonts out there that are fuzzy and have too many lookups:
+ --
+ -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
+ --
+ if i + n > nofchainlookups then
+ -- if trace_contexts then
+ -- logprocess("%s: quitting lookups",cref(kind,chainname))
+ -- end
+ break
+ else
+ -- we need to carry one
+ end
+ end
+ end
+ i = i + 1
+ end
+ end
+ if i > nofchainlookups or not start then
+ break
+ elseif start then
+ start = getnext(start)
+ end
+ end
+ end
+ else
+ local replacements = ck[7]
+ if replacements then
+ head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence
+ else
+ done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
+ if trace_contexts then
+ logprocess("%s: skipping match",cref(kind,chainname))
+ end
+ end
+ end
+ if done then
+ break -- out of contexts (new, needs checking)
+ end
+ end
+ end
+ if diskseen then -- maybe move up so that we can turn checking on/off
+ notmatchpre = { }
+ notmatchpost = { }
+ notmatchreplace = { }
+ end
+ return head, start, done
+end
+
+-- Because we want to keep this elsewhere (an because speed is less an issue) we
+-- pass the font id so that the verbose variant can access the relevant helper tables.
+
+local verbose_handle_contextchain = function(font,...)
+ logwarning("no verbose handler installed, reverting to 'normal'")
+ otf.setcontextchain()
+ return normal_handle_contextchain(...)
+end
+
+otf.chainhandlers = {
+ normal = normal_handle_contextchain,
+ verbose = verbose_handle_contextchain,
+}
+
+local handle_contextchain = nil
+
+-- normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+
+local function chained_contextchain(head,start,stop,...)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,...)
+end
+
+function otf.setcontextchain(method)
+ if not method or method == "normal" or not otf.chainhandlers[method] then
+ if handle_contextchain then -- no need for a message while making the format
+ logwarning("installing normal contextchain handler")
+ end
+ handle_contextchain = normal_handle_contextchain
+ else
+ logwarning("installing contextchain handler %a",method)
+ local handler = otf.chainhandlers[method]
+ handle_contextchain = function(...)
+ return handler(currentfont,...) -- hm, get rid of ...
+ end
+ end
+
+ handlers.gsub_context = handle_contextchain
+ handlers.gsub_contextchain = handle_contextchain
+ handlers.gsub_reversecontextchain = handle_contextchain
+ handlers.gpos_contextchain = handle_contextchain
+ handlers.gpos_context = handle_contextchain
+
+ handlers.contextchain = handle_contextchain
+
+end
+
+chainprocs.gsub_context = chained_contextchain
+chainprocs.gsub_contextchain = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain = chained_contextchain
+chainprocs.gpos_context = chained_contextchain
+
+otf.setcontextchain()
+
+local missing = { } -- we only report once
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_process(...)
+end
+
+local logwarning = report_process
+
+local function report_missing_cache(typ,lookup)
+ local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end
+ local t = f[typ] if not t then t = { } f[typ] = t end
+ if not t[lookup] then
+ t[lookup] = true
+ logwarning("missing cache for lookup %a, type %a, font %a, name %a",lookup,typ,currentfont,tfmdata.properties.fullname)
+ end
+end
+
+local resolved = { } -- we only resolve a font,script,language pair once
+
+-- todo: pass all these 'locals' in a table
+
+local lookuphashes = { }
+
+setmetatableindex(lookuphashes, function(t,font)
+ local lookuphash = fontdata[font].resources.lookuphash
+ if not lookuphash or not next(lookuphash) then
+ lookuphash = false
+ end
+ t[font] = lookuphash
+ return lookuphash
+end)
+
+-- fonts.hashes.lookups = lookuphashes
+
+local autofeatures = fonts.analyzers.features
+local featuretypes = otf.tables.featuretypes
+local defaultscript = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
+
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
+ local features = sequence.features
+ if features then
+ local order = sequence.order
+ if order then
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind = order[i]
+ local valid = enabled[kind]
+ if valid then
+ local scripts = features[kind]
+ local languages = scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled = languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
+ return { valid, autofeatures[kind] or false, sequence, kind }
+ end
+ end
+ end
+ else
+ -- can't happen
+ end
+ end
+ return false
+end
+
+function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
+ local shared = tfmdata.shared
+ local properties = tfmdata.properties
+ local language = properties.language or "dflt"
+ local script = properties.script or "dflt"
+ local enabled = shared.features
+ local autoscript = enabled and enabled.autoscript
+ local autolanguage = enabled and enabled.autolanguage
+ local res = resolved[font]
+ if not res then
+ res = { }
+ resolved[font] = res
+ end
+ local rs = res[script]
+ if not rs then
+ rs = { }
+ res[script] = rs
+ end
+ local rl = rs[language]
+ if not rl then
+ rl = {
+ -- indexed but we can also add specific data by key
+ }
+ rs[language] = rl
+ local sequences = tfmdata.resources.sequences
+ for s=1,#sequences do
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1] = v
+ end
+ end
+ end
+ return rl
+end
+
+-- assumptions:
+--
+-- * languages that use complex disc nodes
+
+local function kernrun(disc,run)
+ --
+ -- we catch <font 1><disc font 2>
+ --
+ if trace_kernruns then
+ report_run("kern") -- will be more detailed
+ end
+ --
+ local prev = getprev(disc) -- todo, keep these in the main loop
+ local next = getnext(disc) -- todo, keep these in the main loop
+ --
+ local pre = getfield(disc,"pre")
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
+ --
+ local prevmarks = prev
+ --
+ -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
+ -- has happened but then it should be in the disc so basically this test indicates an error)
+ --
+ while prevmarks and getid(prevmarks) == glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks) == currentfont and getsubtype(prevmarks) < 256 do
+ prevmarks = getprev(prevmarks)
+ end
+ --
+ if prev and (pre or replace) and not (getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
+ prev = false
+ end
+ if next and (post or replace) and not (getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
+ next = false
+ end
+ --
+ if not pre then
+ -- go on
+ elseif prev then
+ local nest = getprev(pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
+ run(prevmarks,"preinjections")
+ setprev(pre,nest)
+ setnext(prev,disc)
+ else
+ run(pre,"preinjections")
+ end
+ --
+ if not post then
+ -- go on
+ elseif next then
+ local tail = find_node_tail(post)
+ setnext(tail,next)
+ setprev(next,tail)
+ run(post,"postinjections",next)
+ setnext(tail,nil)
+ setprev(next,disc)
+ else
+ run(post,"postinjections")
+ end
+ --
+ if not replace and prev and next then
+ -- this should be already done by discfound
+ setnext(prev,next)
+ setprev(next,prev)
+ run(prevmarks,"injections",next)
+ setnext(prev,disc)
+ setprev(next,disc)
+ elseif prev and next then
+ local tail = find_node_tail(replace)
+ local nest = getprev(replace)
+ setprev(replace,prev)
+ setnext(prev,replace)
+ setnext(tail,next)
+ setprev(next,tail)
+ run(prevmarks,"replaceinjections",next)
+ setprev(replace,nest)
+ setnext(prev,disc)
+ setnext(tail,nil)
+ setprev(next,disc)
+ elseif prev then
+ local nest = getprev(replace)
+ setprev(replace,prev)
+ setnext(prev,replace)
+ run(prevmarks,"replaceinjections")
+ setprev(replace,nest)
+ setnext(prev,disc)
+ elseif next then
+ local tail = find_node_tail(replace)
+ setnext(tail,next)
+ setprev(next,tail)
+ run(replace,"replaceinjections",next)
+ setnext(tail,nil)
+ setprev(next,disc)
+ else
+ run(replace,"replaceinjections")
+ end
+end
+
+-- the if new test might be dangerous as luatex will check / set some tail stuff
+-- in a temp node
+
+local function comprun(disc,run)
+ if trace_compruns then
+ report_run("comp: %s",languages.serializediscretionary(disc))
+ end
+ --
+ local pre = getfield(disc,"pre")
+ if pre then
+ sweepnode = disc
+ sweeptype = "pre" -- in alternative code preinjections is used (also used then for proeprties, saves a variable)
+ local new, done = run(pre)
+ if done then
+ setfield(disc,"pre",new)
+ end
+ end
+ --
+ local post = getfield(disc,"post")
+ if post then
+ sweepnode = disc
+ sweeptype = "post"
+ local new, done = run(post)
+ if done then
+ setfield(disc,"post",new)
+ end
+ end
+ --
+ local replace = getfield(disc,"replace")
+ if replace then
+ sweepnode = disc
+ sweeptype = "replace"
+ local new, done = run(replace)
+ if done then
+ setfield(disc,"replace",new)
+ end
+ end
+ sweepnode = nil
+ sweeptype = nil
+end
+
+local function testrun(disc,trun,crun) -- use helper
+ local next = getnext(disc)
+ if next then
+ local replace = getfield(disc,"replace")
+ if replace then
+ local prev = getprev(disc)
+ if prev then
+ -- only look ahead
+ local tail = find_node_tail(replace)
+ -- local nest = getprev(replace)
+ setnext(tail,next)
+ setprev(next,tail)
+ if trun(replace,next) then
+ setfield(disc,"replace",nil) -- beware, side effects of nest so first
+ setnext(prev,replace)
+ setprev(replace,prev)
+ setprev(next,tail)
+ setnext(tail,next)
+ setprev(disc,nil)
+ setnext(disc,nil)
+ flush_node_list(disc)
+ return replace -- restart
+ else
+ setnext(tail,nil)
+ setprev(next,disc)
+ end
+ else
+ -- weird case
+ end
+ else
+ -- no need
+ end
+ else
+ -- weird case
+ end
+ comprun(disc,crun)
+ return next
+end
+
+local function discrun(disc,drun,krun)
+ local next = getnext(disc)
+ local prev = getprev(disc)
+ if trace_discruns then
+ report_run("disc") -- will be more detailed
+ end
+ if next and prev then
+ setnext(prev,next)
+ -- setprev(next,prev)
+ drun(prev)
+ setnext(prev,disc)
+ -- setprev(next,disc)
+ end
+ --
+ local pre = getfield(disc,"pre")
+ if not pre then
+ -- go on
+ elseif prev then
+ local nest = getprev(pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
+ krun(prev,"preinjections")
+ setprev(pre,nest)
+ setnext(prev,disc)
+ else
+ krun(pre,"preinjections")
+ end
+ return next
+end
+
+-- todo: maybe run lr and rl stretches
+
+local function featuresprocessor(head,font,attr)
+
+ local lookuphash = lookuphashes[font] -- we can also check sequences here
+
+ if not lookuphash then
+ return head, false
+ end
+
+ head = tonut(head)
+
+ if trace_steps then
+ checkstep(head)
+ end
+
+ tfmdata = fontdata[font]
+ descriptions = tfmdata.descriptions
+ characters = tfmdata.characters
+ resources = tfmdata.resources
+
+ marks = resources.marks
+ anchorlookups = resources.lookup_to_anchor
+ lookuptable = resources.lookups
+ lookuptypes = resources.lookuptypes
+ lookuptags = resources.lookuptags
+
+ currentfont = font
+ rlmode = 0
+ sweephead = { }
+
+ local sequences = resources.sequences
+ local done = false
+ local datasets = otf.dataset(tfmdata,font,attr)
+
+ local dirstack = { } -- could move outside function
+
+ -- We could work on sub start-stop ranges instead but I wonder if there is that
+ -- much speed gain (experiments showed that it made not much sense) and we need
+ -- to keep track of directions anyway. Also at some point I want to play with
+ -- font interactions and then we do need the full sweeps.
+
+ -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
+ -- so that multiple cases are also covered.)
+
+ -- We don't goto the next node of a disc node is created so that we can then treat
+ -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
+
+ -- there can be less subtype and attr checking in the comprun etc helpers
+
+ for s=1,#datasets do
+ local dataset = datasets[s]
+ featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ local attribute = dataset[2]
+ local sequence = dataset[3] -- sequences[s] -- also dataset[5]
+ local kind = dataset[4]
+ ----- chain = dataset[5] -- sequence.chain or 0
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local typ = sequence.type
+ local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- maybe all of them
+ local subtables = sequence.subtables
+ local handler = handlers[typ]
+ if typ == "gsub_reversecontextchain" then -- chain < 0
+ -- this is a limited case, no special treatments like 'init' etc
+ -- we need to get rid of this slide! probably no longer needed in latest luatex
+ local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
+ while start do
+ local id = getid(start)
+ if id == glyph_code then
+ if getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = a == attr
+ else
+ a = true
+ end
+ if a then
+ local char = getchar(start)
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- todo: disc?
+ head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if success then
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = getprev(start) end
+ else
+ start = getprev(start)
+ end
+ else
+ start = getprev(start)
+ end
+ else
+ start = getprev(start)
+ end
+ end
+ else
+ local ns = #subtables
+ local start = head -- local ?
+ rlmode = 0 -- to be checked ?
+ if ns == 1 then -- happens often
+ local lookupname = subtables[1]
+ local lookupcache = lookuphash[lookupname]
+ if not lookupcache then -- also check for empty cache
+ report_missing_cache(typ,lookupname)
+ else
+
+ local function c_run(head) -- no need to check for 256 and attr probably also the same
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
+ while start do
+ local id = getid(start)
+ if id ~= glyph_code then
+ -- very unlikely
+ start = getnext(start)
+ elseif getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(start)]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done = true
+ end
+ end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
+ end
+ else
+ return head, false
+ end
+ end
+ if done then
+ success = true -- needed in this subrun?
+ end
+ return head, done
+ end
+
+ local function t_run(start,stop)
+ while start ~= stop do
+ local id = getid(start)
+ if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(start)]
+ if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ while s do
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ end
+ start = getnext(start)
+ else
+ break
+ end
+ end
+ end
+
+ local function d_run(prev) -- we can assume that prev and next are glyphs
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(prev)]
+ if lookupmatch then
+ -- sequence kan weg
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done = true
+ success = true
+ end
+ end
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ -- sequence kan weg
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local id = getid(n)
+ if id == glyph_code then
+ local lookupmatch = lookupcache[getchar(n)]
+ if lookupmatch then
+ local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
+ if ok then
+ done = true
+ success = true
+ end
+ end
+ else
+ -- message
+ end
+ end
+ end
+ end
+
+ while start do
+ local id = getid(start)
+ if id == glyph_code then
+ if getfont(start) == font and getsubtype(start) < 256 then -- why a 256 test ...
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local char = getchar(start)
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ success = true
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
+ end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
+ end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif id == disc_code then
+ if gpossing then
+ kernrun(start,k_run)
+ start = getnext(start)
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start = getnext(start)
+ end
+ elseif id == math_code then
+ start = getnext(end_of_math(start))
+ elseif id == dir_code then
+ local dir = getfield(start,"dir")
+ if dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start = getnext(start)
+ elseif id == localpar_code then
+ local dir = getfield(start,"dir")
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ -- one might wonder if the par dir should be looked at, so we might as well drop the next line
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start = getnext(start)
+ else
+ start = getnext(start)
+ end
+ end
+ end
+
+ else
+
+ local function c_run(head)
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
+ while start do
+ local id = getid(start)
+ if id ~= glyph_code then
+ -- very unlikely
+ start = getnext(start)
+ elseif getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local char = getchar(start)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ 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,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
+ end
+ else
+ return head, false
+ end
+ end
+ if done then
+ success = true
+ end
+ return head, done
+ end
+
+ local function d_run(prev)
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ -- brr prev can be disc
+ local char = getchar(prev)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local id = getid(n)
+ if id == glyph_code then
+ local char = getchar(n)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
+ if ok then
+ done = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ else
+ -- message
+ end
+ end
+ end
+ end
+
+ local function t_run(start,stop)
+ while start ~= stop do
+ local id = getid(start)
+ if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local char = getchar(start)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ while s do
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ end
+ start = getnext(start)
+ else
+ break
+ end
+ end
+ end
+
+ while start do
+ local id = getid(start)
+ if id == glyph_code then
+ if getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local char = getchar(start)
+ 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,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ success = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
+ end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif id == disc_code then
+ if gpossing then
+ kernrun(start,k_run)
+ start = getnext(start)
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start = getnext(start)
+ end
+ elseif id == math_code then
+ start = getnext(end_of_math(start))
+ elseif id == dir_code then
+ local dir = getfield(start,"dir")
+ if dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start = getnext(start)
+ elseif id == localpar_code then
+ local dir = getfield(start,"dir")
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start = getnext(start)
+ else
+ start = getnext(start)
+ end
+ end
+ end
+ end
+ if success then
+ done = true
+ end
+ if trace_steps then -- ?
+ registerstep(head)
+ end
+
+ end
+
+ head = tonode(head)
+
+ return head, done
+end
+
+-- this might move to the loader
+
+local function generic(lookupdata,lookupname,unicode,lookuphash)
+ local target = lookuphash[lookupname]
+ if target then
+ target[unicode] = lookupdata
+ else
+ lookuphash[lookupname] = { [unicode] = lookupdata }
+ end
+end
+
+local function ligature(lookupdata,lookupname,unicode,lookuphash)
+ local target = lookuphash[lookupname]
+ if not target then
+ target = { }
+ lookuphash[lookupname] = target
+ end
+ for i=1,#lookupdata do
+ local li = lookupdata[i]
+ local tu = target[li]
+ if not tu then
+ tu = { }
+ target[li] = tu
+ end
+ target = tu
+ end
+ target.ligature = unicode
+end
+
+local function pair(lookupdata,lookupname,unicode,lookuphash)
+ local target = lookuphash[lookupname]
+ if not target then
+ target = { }
+ lookuphash[lookupname] = target
+ end
+ local others = target[unicode]
+ local paired = lookupdata[1]
+ if others then
+ others[paired] = lookupdata
+ else
+ others = { [paired] = lookupdata }
+ target[unicode] = others
+ end
+end
+
+local action = {
+ substitution = generic,
+ multiple = generic,
+ alternate = generic,
+ position = generic,
+ ligature = ligature,
+ pair = pair,
+ kern = pair,
+}
+
+local function prepare_lookups(tfmdata)
+
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata.resources
+ local lookuphash = resources.lookuphash
+ local anchor_to_lookup = resources.anchor_to_lookup
+ local lookup_to_anchor = resources.lookup_to_anchor
+ local lookuptypes = resources.lookuptypes
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local duplicates = resources.duplicates
+
+ -- we cannot free the entries in the descriptions as sometimes we access
+ -- then directly (for instance anchors) ... selectively freeing does save
+ -- much memory as it's only a reference to a table and the slot in the
+ -- description hash is not freed anyway
+
+ -- we can delay this using metatables so that we don't make the hashes for
+ -- features we don't use but then we need to loop over the characters
+ -- many times so we gain nothing
+
+ for unicode, character in next, characters do -- we cannot loop over descriptions !
+
+ local description = descriptions[unicode]
+
+ if description then
+
+ local lookups = description.slookups
+ if lookups then
+ for lookupname, lookupdata in next, lookups do
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
+ end
+ end
+
+ local lookups = description.mlookups
+ if lookups then
+ for lookupname, lookuplist in next, lookups do
+ local lookuptype = lookuptypes[lookupname]
+ for l=1,#lookuplist do
+ local lookupdata = lookuplist[l]
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
+ end
+ end
+ end
+
+ local list = description.kerns
+ if list then
+ for lookup, krn in next, list do -- ref to glyph, saves lookup
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = krn
+ else
+ lookuphash[lookup] = { [unicode] = krn }
+ end
+ end
+ end
+
+ local list = description.anchors
+ if list then
+ for typ, anchors in next, list do -- types
+ if typ == "mark" or typ == "cexit" then -- or entry?
+ for name, anchor in next, anchors do
+ local lookups = anchor_to_lookup[name]
+ if lookups then
+ for lookup in next, lookups do
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = anchors
+ else
+ lookuphash[lookup] = { [unicode] = anchors }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ end
+
+ end
+
+end
+
+-- so far
+
+local function split(replacement,original)
+ local result = { }
+ for i=1,#replacement do
+ result[original[i]] = replacement[i]
+ end
+ return result
+end
+
+local valid = { -- does contextpos work?
+ coverage = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
+ reversecoverage = { reversesub = true },
+ glyphs = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
+}
+
+local function prepare_contextchains(tfmdata)
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata.resources
+ local lookuphash = resources.lookuphash
+ local lookuptags = resources.lookuptags
+ local lookups = rawdata.lookups
+ if lookups then
+ for lookupname, lookupdata in next, rawdata.lookups do
+ local lookuptype = lookupdata.type
+ if lookuptype then
+ local rules = lookupdata.rules
+ if rules then
+ local format = lookupdata.format
+ local validformat = valid[format]
+ if not validformat then
+ report_prepare("unsupported format %a",format)
+ elseif not validformat[lookuptype] then
+ -- todo: dejavu-serif has one (but i need to see what use it has)
+ report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookuptags[lookupname])
+ else
+ local contexts = lookuphash[lookupname]
+ if not contexts then
+ contexts = { }
+ lookuphash[lookupname] = contexts
+ end
+ local t, nt = { }, 0
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local current = rule.current
+ local before = rule.before
+ local after = rule.after
+ local replacements = rule.replacements
+ local sequence = { }
+ local nofsequences = 0
+ -- Eventually we can store start, stop and sequence in the cached file
+ -- but then less sharing takes place so best not do that without a lot
+ -- of profiling so let's forget about it.
+ if before then
+ for n=1,#before do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = before[n]
+ end
+ end
+ local start = nofsequences + 1
+ for n=1,#current do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = current[n]
+ end
+ local stop = nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = after[n]
+ end
+ end
+ if sequence[1] then
+ -- Replacements only happen with reverse lookups as they are single only. We
+ -- could pack them into current (replacement value instead of true) and then
+ -- use sequence[start] instead but it's somewhat ugly.
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
+ for unic in next, sequence[start] do
+ local cu = contexts[unic]
+ if not cu then
+ contexts[unic] = t
+ end
+ end
+ end
+ end
+ end
+ else
+ -- no rules
+ end
+ else
+ report_prepare("missing lookuptype for lookupname %a",lookuptags[lookupname])
+ end
+ end
+ end
+end
+
+-- we can consider lookuphash == false (initialized but empty) vs lookuphash == table
+
+local function featuresinitializer(tfmdata,value)
+ if true then -- value then
+ -- beware we need to use the topmost properties table
+ local rawdata = tfmdata.shared.rawdata
+ local properties = rawdata.properties
+ if not properties.initialized then
+ local starttime = trace_preparing and os.clock()
+ local resources = rawdata.resources
+ resources.lookuphash = resources.lookuphash or { }
+ prepare_contextchains(tfmdata)
+ prepare_lookups(tfmdata)
+ properties.initialized = true
+ if trace_preparing then
+ report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname)
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ position = 1,
+ node = featuresinitializer,
+ },
+ processors = {
+ node = featuresprocessor,
+ }
+}
+
+-- This can be used for extra handlers, but should be used with care!
+
+otf.handlers = handlers
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua
new file mode 100644
index 00000000000..b7ee717c949
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua
@@ -0,0 +1,452 @@
+if not modules then modules = { } end modules ['font-oto'] = { -- original 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"
+}
+
+-- This is a version of font-otb adapted to the new fontloader code. We used to have two
+-- base initialization methods but now we have only one. This means that instead of the
+-- old default (independent) we now use the one more similar to node node (shared).
+
+local concat, unpack = table.concat, table.unpack
+local insert, remove = table.insert, table.remove
+local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget
+local lpegmatch = lpeg.match
+local utfchar = utf.char
+
+local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
+local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
+----- trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+
+local report_prepare = logs.reporter("fonts","otf prepare")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
+
+otf.defaultbasealternate = "none" -- first last
+
+local wildcard = "*"
+local default = "dflt"
+
+local formatters = string.formatters
+local f_unicode = formatters["%U"]
+local f_uniname = formatters["%U (%s)"]
+local f_unilist = formatters["% t (% t)"]
+
+local function gref(descriptions,n)
+ if type(n) == "number" then
+ local name = descriptions[n].name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
+ end
+ elseif n then
+ local num, nam, j = { }, { }, 0
+ for i=1,#n do
+ local ni = n[i]
+ if tonumber(ni) then -- first is likely a key
+ j = j + 1
+ local di = descriptions[ni]
+ num[j] = f_unicode(ni)
+ nam[j] = di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in base mode tracing>"
+ end
+end
+
+local function cref(feature,sequence)
+ return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name)
+end
+
+
+local function report_alternate(feature,sequence,descriptions,unicode,replacement,value,comment)
+ report_prepare("%s: base alternate %s => %s (%S => %S)",
+ cref(feature,sequence),
+ gref(descriptions,unicode),
+ replacement and gref(descriptions,replacement),
+ value,
+ comment)
+end
+
+local function report_substitution(feature,sequence,descriptions,unicode,substitution)
+ report_prepare("%s: base substitution %s => %S",
+ cref(feature,sequence),
+ gref(descriptions,unicode),
+ gref(descriptions,substitution))
+end
+
+local function report_ligature(feature,sequence,descriptions,unicode,ligature)
+ report_prepare("%s: base ligature %s => %S",
+ cref(feature,sequence),
+ gref(descriptions,ligature),
+ gref(descriptions,unicode))
+end
+
+local function report_kern(feature,sequence,descriptions,unicode,otherunicode,value)
+ report_prepare("%s: base kern %s + %s => %S",
+ cref(feature,sequence),
+ gref(descriptions,unicode),
+ gref(descriptions,otherunicode),
+ value)
+end
+
+-- We need to make sure that luatex sees the difference between base fonts that have
+-- different glyphs in the same slots in fonts that have the same fullname (or filename).
+-- LuaTeX will merge fonts eventually (and subset later on). If needed we can use a more
+-- verbose name as long as we don't use <()<>[]{}/%> and the length is < 128.
+
+local basehash, basehashes, applied = { }, 1, { }
+
+local function registerbasehash(tfmdata)
+ local properties = tfmdata.properties
+ local hash = concat(applied," ")
+ local base = basehash[hash]
+ if not base then
+ basehashes = basehashes + 1
+ base = basehashes
+ basehash[hash] = base
+ end
+ properties.basehash = base
+ properties.fullname = properties.fullname .. "-" .. base
+ -- report_prepare("fullname base hash '%a, featureset %a",tfmdata.properties.fullname,hash)
+ applied = { }
+end
+
+local function registerbasefeature(feature,value)
+ applied[#applied+1] = feature .. "=" .. tostring(value)
+end
+
+-- The original basemode ligature builder used the names of components and did some expression
+-- juggling to get the chain right. The current variant starts with unicodes but still uses
+-- names to make the chain. This is needed because we have to create intermediates when needed
+-- but use predefined snippets when available. To some extend the current builder is more stupid
+-- but I don't worry that much about it as ligatures are rather predicatable.
+--
+-- Personally I think that an ff + i == ffi rule as used in for instance latin modern is pretty
+-- weird as no sane person will key that in and expect a glyph for that ligature plus the following
+-- character. Anyhow, as we need to deal with this, we do, but no guarantes are given.
+--
+-- latin modern dejavu
+--
+-- f+f 102 102 102 102
+-- f+i 102 105 102 105
+-- f+l 102 108 102 108
+-- f+f+i 102 102 105
+-- f+f+l 102 102 108 102 102 108
+-- ff+i 64256 105 64256 105
+-- ff+l 64256 108
+--
+-- As you can see here, latin modern is less complete than dejavu but
+-- in practice one will not notice it.
+--
+-- The while loop is needed because we need to resolve for instance pseudo names like
+-- hyphen_hyphen to endash so in practice we end up with a bit too many definitions but the
+-- overhead is neglectable. We can have changed[first] or changed[second] but it quickly becomes
+-- messy if we need to take that into account.
+
+local function makefake(tfmdata,name,present)
+ local resources = tfmdata.resources
+ local private = resources.private
+ local character = { intermediate = true, ligatures = { } }
+ resources.unicodes[name] = private
+ tfmdata.characters[private] = character
+ tfmdata.descriptions[private] = { name = name }
+ resources.private = private + 1
+ present[name] = private
+ return character
+end
+
+local function make_1(present,tree,name)
+ for k, v in next, tree do
+ if k == "ligature" then
+ present[name] = v
+ else
+ make_1(present,v,name .. "_" .. k)
+ end
+ end
+end
+
+local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done)
+ for k, v in next, tree do
+ if k == "ligature" then
+ local character = characters[preceding]
+ if not character then
+ if trace_baseinit then
+ report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding)
+ end
+ character = makefake(tfmdata,name,present)
+ end
+ local ligatures = character.ligatures
+ if ligatures then
+ ligatures[unicode] = { char = v }
+ else
+ character.ligatures = { [unicode] = { char = v } }
+ end
+ if done then
+ local d = done[name]
+ if not d then
+ done[name] = { "dummy", v }
+ else
+ d[#d+1] = v
+ end
+ end
+ else
+ local code = present[name] or unicode
+ local name = name .. "_" .. k
+ make_2(present,tfmdata,characters,v,name,code,k,done)
+ end
+ end
+end
+
+local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local changed = tfmdata.changed
+
+ local ligatures = { }
+ local alternate = tonumber(value) or true and 1
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
+
+ for i=1,#lookuplist do
+ local sequence = lookuplist[i]
+ local steps = sequence.steps
+ local kind = sequence.type
+ if kind == "gsub_single" then
+ for i=1,#steps do
+ for unicode, data in next, steps[i].coverage do
+ if not changed[unicode] then
+ if trace_singles then
+ report_substitution(feature,sequence,descriptions,unicode,data)
+ end
+ changed[unicode] = data
+ end
+ end
+ end
+ elseif kind == "gsub_alternate" then
+ for i=1,#steps do
+ for unicode, data in next, steps[i].coverage do
+ if not changed[unicode] then
+ local replacement = data[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,sequence,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = data[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = data[#data]
+ if trace_alternatives then
+ report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,sequence,descriptions,unicode,replacement,value,"unknown")
+ end
+ end
+ end
+ end
+ end
+ elseif kind == "gsub_ligature" then
+ for i=1,#steps do
+ for unicode, data in next, steps[i].coverage do
+ ligatures[#ligatures+1] = { unicode, data, "" } -- lookupname }
+ if trace_ligatures then
+ report_ligature(feature,sequence,descriptions,unicode,data)
+ end
+ end
+ end
+ end
+ end
+
+ local nofligatures = #ligatures
+
+ if nofligatures > 0 then
+
+ local characters = tfmdata.characters
+ local present = { }
+ local done = trace_baseinit and trace_ligatures and { }
+
+ for i=1,nofligatures do
+ local ligature = ligatures[i]
+ local unicode, tree = ligature[1], 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]
+ make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence)
+ end
+
+ end
+
+end
+
+local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local properties = tfmdata.properties
+ local traceindeed = trace_baseinit and trace_kerns
+ -- check out this sharedkerns trickery
+ for i=1,#lookuplist do
+ local sequence = lookuplist[i]
+ local steps = sequence.steps
+ local kind = sequence.type
+ local format = sequence.format
+ if kind == "gpos_pair" then
+ for i=1,#steps do
+ local step = steps[i]
+ if step.format == "kern" then
+ for unicode, data in next, steps[i].coverage do
+ local character = characters[unicode]
+ local kerns = character.kerns
+ if not kerns then
+ kerns = { }
+ character.kerns = kerns
+ end
+ if traceindeed then
+ for otherunicode, kern in next, data do
+ if not kerns[otherunicode] and kern ~= 0 then
+ kerns[otherunicode] = kern
+ report_kern(feature,sequence,descriptions,unicode,otherunicode,kern)
+ end
+ end
+ else
+ for otherunicode, kern in next, data do
+ if not kerns[otherunicode] and kern ~= 0 then
+ kerns[otherunicode] = kern
+ end
+ end
+ end
+ end
+ else
+ for unicode, data in next, steps[i].coverage do
+ local character = characters[unicode]
+ local kerns = character.kerns
+ for otherunicode, kern in next, data do
+ if not kern[2] and not (kerns and kerns[otherunicode]) then
+ local kern = kern[1]
+ if kern[1] ~= 0 or kern[2] ~= 0 or kern[4] ~= 0 then
+ -- a complex pair not suitable for basemode
+ else
+ kern = kern[3]
+ if kern ~= 0 then
+ if kerns then
+ kerns[otherunicode] = kern
+ else
+ kerns = { [otherunicode] = kern }
+ character.kerns = kerns
+ end
+ if traceindeed then
+ report_kern(feature,sequence,descriptions,unicode,otherunicode,kern)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+end
+
+local function initializehashes(tfmdata)
+ -- already done
+end
+
+local function featuresinitializer(tfmdata,value)
+ if true then -- value then
+ local starttime = trace_preparing and os.clock()
+ local features = tfmdata.shared.features
+ local fullname = tfmdata.properties.fullname or "?"
+ if features then
+ initializehashes(tfmdata)
+ local collectlookups = otf.collectlookups
+ local rawdata = tfmdata.shared.rawdata
+ local properties = tfmdata.properties
+ local script = properties.script
+ local language = properties.language
+ local rawfeatures = rawdata.resources.features
+ local basesubstitutions = rawfeatures and rawfeatures.gsub
+ local basepositionings = rawfeatures and rawfeatures.gpos
+ --
+ if basesubstitutions or basepositionings then
+ local sequences = tfmdata.resources.sequences
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local sfeatures = sequence.features
+ if sfeatures then
+ local order = sequence.order
+ if order then
+ for i=1,#order do --
+ local feature = order[i]
+ local value = features[feature]
+ if value then
+ local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
+ if not validlookups then
+ -- skip
+ elseif basesubstitutions and basesubstitutions[feature] then
+ if trace_preparing then
+ report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value)
+ end
+ preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+ registerbasefeature(feature,value)
+ elseif basepositionings and basepositionings[feature] then
+ if trace_preparing then
+ report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value)
+ end
+ preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
+ registerbasefeature(feature,value)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ registerbasehash(tfmdata)
+ end
+ if trace_preparing then
+ report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname)
+ end
+ end
+end
+
+registerotffeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1
+ base = featuresinitializer,
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otp.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otp.lua
new file mode 100644
index 00000000000..91bd05b322f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otp.lua
@@ -0,0 +1,909 @@
+if not modules then modules = { } end modules ['font-otp'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (packing)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: pack math (but not that much to share)
+--
+-- pitfall 5.2: hashed tables can suddenly become indexed with nil slots
+--
+-- unless we sort all hashes we can get a different pack order (no big deal but size can differ)
+
+local next, type, tostring = next, type, tostring
+local sort, concat = table.sort, table.concat
+
+local trace_packing = false trackers.register("otf.packing", function(v) trace_packing = v end)
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+-- also used in other scripts so we need to check some tables:
+
+fonts = fonts or { }
+
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
+
+local otf = handlers.otf or { }
+handlers.otf = otf
+
+local enhancers = otf.enhancers or { }
+otf.enhancers = enhancers
+
+local glists = otf.glists or { "gsub", "gpos" }
+otf.glists = glists
+
+local criterium = 1
+local threshold = 0
+
+local function tabstr_normal(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ if type(v) == "table" then
+ s[n] = k .. ">" .. tabstr_normal(v)
+ elseif v == true then
+ s[n] = k .. "+" -- "=true"
+ elseif v then
+ s[n] = k .. "=" .. v
+ else
+ s[n] = k .. "-" -- "=false"
+ end
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+local function tabstr_flat(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ s[n] = k .. "=" .. v
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+local function tabstr_mixed(t) -- indexed
+ local s = { }
+ local n = #t
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ local k = t[1]
+ if k == true then
+ return "++" -- we need to distinguish from "true"
+ elseif k == false then
+ return "--" -- we need to distinguish from "false"
+ else
+ return tostring(k) -- number or string
+ end
+ else
+ for i=1,n do
+ local k = t[i]
+ if k == true then
+ s[i] = "++" -- we need to distinguish from "true"
+ elseif k == false then
+ s[i] = "--" -- we need to distinguish from "false"
+ else
+ s[i] = k -- number or string
+ end
+ end
+ return concat(s,",")
+ end
+end
+
+local function tabstr_boolean(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ if v then
+ s[n] = k .. "+"
+ else
+ s[n] = k .. "-"
+ end
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+-- tabstr_boolean_x = tabstr_boolean
+
+-- tabstr_boolean = function(t)
+-- local a = tabstr_normal(t)
+-- local b = tabstr_boolean_x(t)
+-- print(a)
+-- print(b)
+-- return b
+-- end
+
+-- beware: we cannot unpack and repack the same table because then sharing
+-- interferes (we could catch this if needed) .. so for now: save, reload
+-- and repack in such cases (never needed anyway) .. a tricky aspect is that
+-- we then need to sort more thanks to random hashing
+
+local function packdata(data)
+
+ if data then
+ -- stripdata(data)
+ local h, t, c = { }, { }, { }
+ local hh, tt, cc = { }, { }, { }
+ local nt, ntt = 0, 0
+ local function pack_normal(v)
+ local tag = tabstr_normal(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_flat(v)
+ local tag = tabstr_flat(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_boolean(v)
+ local tag = tabstr_boolean(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_indexed(v)
+ local tag = concat(v," ")
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_mixed(v)
+ local tag = tabstr_mixed(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_final(v)
+ -- v == number
+ if c[v] <= criterium then
+ return t[v]
+ else
+ -- compact hash
+ local hv = hh[v]
+ if hv then
+ return hv
+ else
+ ntt = ntt + 1
+ tt[ntt] = t[v]
+ hh[v] = ntt
+ cc[ntt] = c[v]
+ return ntt
+ end
+ end
+ end
+ local function success(stage,pass)
+ if nt == 0 then
+ if trace_loading or trace_packing then
+ report_otf("pack quality: nothing to pack")
+ end
+ return false
+ elseif nt >= threshold then
+ local one, two, rest = 0, 0, 0
+ if pass == 1 then
+ for k,v in next, c do
+ if v == 1 then
+ one = one + 1
+ elseif v == 2 then
+ two = two + 1
+ else
+ rest = rest + 1
+ end
+ end
+ else
+ for k,v in next, cc do
+ if v > 20 then
+ rest = rest + 1
+ elseif v > 10 then
+ two = two + 1
+ else
+ one = one + 1
+ end
+ end
+ data.tables = tt
+ end
+ if trace_loading or trace_packing then
+ report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium)
+ end
+ return true
+ else
+ if trace_loading or trace_packing then
+ report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, nt, threshold)
+ end
+ return false
+ end
+ end
+ local function packers(pass)
+ if pass == 1 then
+ return pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed
+ else
+ return pack_final, pack_final, pack_final, pack_final, pack_final
+ end
+ end
+ local resources = data.resources
+ local lookuptypes = resources.lookuptypes
+ for pass=1,2 do
+ if trace_packing then
+ report_otf("start packing: stage 1, pass %s",pass)
+ end
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ for unicode, description in next, data.descriptions do
+ local boundingbox = description.boundingbox
+ if boundingbox then
+ description.boundingbox = pack_indexed(boundingbox)
+ end
+ local slookups = description.slookups
+ if slookups then
+ for tag, slookup in next, slookups do
+ local what = lookuptypes[tag]
+ if what == "pair" then
+ local t = slookup[2] if t then slookup[2] = pack_indexed(t) end
+ local t = slookup[3] if t then slookup[3] = pack_indexed(t) end
+ elseif what ~= "substitution" then
+ slookups[tag] = pack_indexed(slookup) -- true is new
+ end
+ end
+ end
+ local mlookups = description.mlookups
+ if mlookups then
+ for tag, mlookup in next, mlookups do
+ local what = lookuptypes[tag]
+ if what == "pair" then
+ for i=1,#mlookup do
+ local lookup = mlookup[i]
+ local t = lookup[2] if t then lookup[2] = pack_indexed(t) end
+ local t = lookup[3] if t then lookup[3] = pack_indexed(t) end
+ end
+ elseif what ~= "substitution" then
+ for i=1,#mlookup do
+ mlookup[i] = pack_indexed(mlookup[i]) -- true is new
+ end
+ end
+ end
+ end
+ local kerns = description.kerns
+ if kerns then
+ for tag, kern in next, kerns do
+ kerns[tag] = pack_flat(kern)
+ end
+ end
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ for tag, kern in next, kerns do
+ kerns[tag] = pack_normal(kern)
+ end
+ end
+ end
+ local anchors = description.anchors
+ if anchors then
+ for what, anchor in next, anchors do
+ if what == "baselig" then
+ for _, a in next, anchor do
+ for k=1,#a do
+ a[k] = pack_indexed(a[k])
+ end
+ end
+ else
+ for k, v in next, anchor do
+ anchor[k] = pack_indexed(v)
+ end
+ end
+ end
+ end
+ local altuni = description.altuni
+ if altuni then
+ for i=1,#altuni do
+ altuni[i] = pack_flat(altuni[i])
+ end
+ end
+ end
+ local lookups = data.lookups
+ if lookups then
+ for _, lookup in next, lookups do
+ local rules = lookup.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local r = rule.before if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.after if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.current if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.replacements if r then rule.replacements = pack_flat (r) end -- can have holes
+ local r = rule.lookups if r then rule.lookups = pack_indexed(r) end -- can have ""
+ -- local r = rule.lookups if r then rule.lookups = pack_flat(r) end -- can have holes (already taken care of some cases)
+ end
+ end
+ end
+ end
+ local anchor_to_lookup = resources.anchor_to_lookup
+ if anchor_to_lookup then
+ for anchor, lookup in next, anchor_to_lookup do
+ anchor_to_lookup[anchor] = pack_normal(lookup)
+ end
+ end
+ local lookup_to_anchor = resources.lookup_to_anchor
+ if lookup_to_anchor then
+ for lookup, anchor in next, lookup_to_anchor do
+ lookup_to_anchor[lookup] = pack_normal(anchor)
+ end
+ end
+ local sequences = resources.sequences
+ if sequences then
+ for feature, sequence in next, sequences do
+ local flags = sequence.flags
+ if flags then
+ sequence.flags = pack_normal(flags)
+ end
+ local subtables = sequence.subtables
+ if subtables then
+ sequence.subtables = pack_normal(subtables)
+ end
+ local features = sequence.features
+ if features then
+ for script, feature in next, features do
+ features[script] = pack_normal(feature)
+ end
+ end
+ local order = sequence.order
+ if order then
+ sequence.order = pack_indexed(order)
+ end
+ local markclass = sequence.markclass
+ if markclass then
+ sequence.markclass = pack_boolean(markclass)
+ end
+ end
+ end
+ local lookups = resources.lookups
+ if lookups then
+ for name, lookup in next, lookups do
+ local flags = lookup.flags
+ if flags then
+ lookup.flags = pack_normal(flags)
+ end
+ local subtables = lookup.subtables
+ if subtables then
+ lookup.subtables = pack_normal(subtables)
+ end
+ end
+ end
+ local features = resources.features
+ if features then
+ for _, what in next, glists do
+ local list = features[what]
+ if list then
+ for feature, spec in next, list do
+ list[feature] = pack_normal(spec)
+ end
+ end
+ end
+ end
+ if not success(1,pass) then
+ return
+ end
+ end
+ if nt > 0 then
+ for pass=1,2 do
+ if trace_packing then
+ report_otf("start packing: stage 2, pass %s",pass)
+ end
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ for unicode, description in next, data.descriptions do
+ local kerns = description.kerns
+ if kerns then
+ description.kerns = pack_normal(kerns)
+ end
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ math.kerns = pack_normal(kerns)
+ end
+ end
+ local anchors = description.anchors
+ if anchors then
+ description.anchors = pack_normal(anchors)
+ end
+ local mlookups = description.mlookups
+ if mlookups then
+ for tag, mlookup in next, mlookups do
+ mlookups[tag] = pack_normal(mlookup)
+ end
+ end
+ local altuni = description.altuni
+ if altuni then
+ description.altuni = pack_normal(altuni)
+ end
+ end
+ local lookups = data.lookups
+ if lookups then
+ for _, lookup in next, lookups do
+ local rules = lookup.rules
+ if rules then
+ for i=1,#rules do -- was next loop
+ local rule = rules[i]
+ local r = rule.before if r then rule.before = pack_normal(r) end
+ local r = rule.after if r then rule.after = pack_normal(r) end
+ local r = rule.current if r then rule.current = pack_normal(r) end
+ end
+ end
+ end
+ end
+ local sequences = resources.sequences
+ if sequences then
+ for feature, sequence in next, sequences do
+ sequence.features = pack_normal(sequence.features)
+ end
+ end
+ if not success(2,pass) then
+ -- return
+ end
+ end
+
+ for pass=1,2 do
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ for unicode, description in next, data.descriptions do
+ local slookups = description.slookups
+ if slookups then
+ description.slookups = pack_normal(slookups)
+ end
+ local mlookups = description.mlookups
+ if mlookups then
+ description.mlookups = pack_normal(mlookups)
+ end
+ end
+ end
+
+ end
+ end
+end
+
+local unpacked_mt = {
+ __index =
+ function(t,k)
+ t[k] = false
+ return k -- next time true
+ end
+}
+
+local function unpackdata(data)
+
+ if data then
+ local tables = data.tables
+ if tables then
+ local resources = data.resources
+ local lookuptypes = resources.lookuptypes
+ local unpacked = { }
+ setmetatable(unpacked,unpacked_mt)
+ for unicode, description in next, data.descriptions do
+ local tv = tables[description.boundingbox]
+ if tv then
+ description.boundingbox = tv
+ end
+ local slookups = description.slookups
+ if slookups then
+ local tv = tables[slookups]
+ if tv then
+ description.slookups = tv
+ slookups = unpacked[tv]
+ end
+ if slookups then
+ for tag, lookup in next, slookups do
+ local what = lookuptypes[tag]
+ if what == "pair" then
+ local tv = tables[lookup[2]]
+ if tv then
+ lookup[2] = tv
+ end
+ local tv = tables[lookup[3]]
+ if tv then
+ lookup[3] = tv
+ end
+ elseif what ~= "substitution" then
+ local tv = tables[lookup]
+ if tv then
+ slookups[tag] = tv
+ end
+ end
+ end
+ end
+ end
+ local mlookups = description.mlookups
+ if mlookups then
+ local tv = tables[mlookups]
+ if tv then
+ description.mlookups = tv
+ mlookups = unpacked[tv]
+ end
+ if mlookups then
+ for tag, list in next, mlookups do
+ local tv = tables[list]
+ if tv then
+ mlookups[tag] = tv
+ list = unpacked[tv]
+ end
+ if list then
+ local what = lookuptypes[tag]
+ if what == "pair" then
+ for i=1,#list do
+ local lookup = list[i]
+ local tv = tables[lookup[2]]
+ if tv then
+ lookup[2] = tv
+ end
+ local tv = tables[lookup[3]]
+ if tv then
+ lookup[3] = tv
+ end
+ end
+ elseif what ~= "substitution" then
+ for i=1,#list do
+ local tv = tables[list[i]]
+ if tv then
+ list[i] = tv
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ local kerns = description.kerns
+ if kerns then
+ local tm = tables[kerns]
+ if tm then
+ description.kerns = tm
+ kerns = unpacked[tm]
+ end
+ if kerns then
+ for k, kern in next, kerns do
+ local tv = tables[kern]
+ if tv then
+ kerns[k] = tv
+ end
+ end
+ end
+ end
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ local tm = tables[kerns]
+ if tm then
+ math.kerns = tm
+ kerns = unpacked[tm]
+ end
+ if kerns then
+ for k, kern in next, kerns do
+ local tv = tables[kern]
+ if tv then
+ kerns[k] = tv
+ end
+ end
+ end
+ end
+ end
+ local anchors = description.anchors
+ if anchors then
+ local ta = tables[anchors]
+ if ta then
+ description.anchors = ta
+ anchors = unpacked[ta]
+ end
+ if anchors then
+ for tag, anchor in next, anchors do
+ if tag == "baselig" then
+ for _, list in next, anchor do
+ for i=1,#list do
+ local tv = tables[list[i]]
+ if tv then
+ list[i] = tv
+ end
+ end
+ end
+ else
+ for a, data in next, anchor do
+ local tv = tables[data]
+ if tv then
+ anchor[a] = tv
+ end
+ end
+ end
+ end
+ end
+ end
+ local altuni = description.altuni
+ if altuni then
+ local altuni = tables[altuni]
+ if altuni then
+ description.altuni = altuni
+ for i=1,#altuni do
+ local tv = tables[altuni[i]]
+ if tv then
+ altuni[i] = tv
+ end
+ end
+ end
+ end
+ end
+ local lookups = data.lookups
+ if lookups then
+ for _, lookup in next, lookups do
+ local rules = lookup.rules
+ if rules then
+ for i=1,#rules do -- was next loop
+ local rule = rules[i]
+ local before = rule.before
+ if before then
+ local tv = tables[before]
+ if tv then
+ rule.before = tv
+ before = unpacked[tv]
+ end
+ if before then
+ for i=1,#before do
+ local tv = tables[before[i]]
+ if tv then
+ before[i] = tv
+ end
+ end
+ end
+ end
+ local after = rule.after
+ if after then
+ local tv = tables[after]
+ if tv then
+ rule.after = tv
+ after = unpacked[tv]
+ end
+ if after then
+ for i=1,#after do
+ local tv = tables[after[i]]
+ if tv then
+ after[i] = tv
+ end
+ end
+ end
+ end
+ local current = rule.current
+ if current then
+ local tv = tables[current]
+ if tv then
+ rule.current = tv
+ current = unpacked[tv]
+ end
+ if current then
+ for i=1,#current do
+ local tv = tables[current[i]]
+ if tv then
+ current[i] = tv
+ end
+ end
+ end
+ end
+ local replacements = rule.replacements
+ if replacements then
+ local tv = tables[replacements]
+ if tv then
+ rule.replacements = tv
+ end
+ end
+ -- local fore = rule.fore
+ -- if fore then
+ -- local tv = tables[fore]
+ -- if tv then
+ -- rule.fore = tv
+ -- end
+ -- end
+ -- local back = rule.back
+ -- if back then
+ -- local tv = tables[back]
+ -- if tv then
+ -- rule.back = tv
+ -- end
+ -- end
+ -- local names = rule.names
+ -- if names then
+ -- local tv = tables[names]
+ -- if tv then
+ -- rule.names = tv
+ -- end
+ -- end
+ --
+ local lookups = rule.lookups
+ if lookups then
+ local tv = tables[lookups]
+ if tv then
+ rule.lookups = tv
+ end
+ end
+ end
+ end
+ end
+ end
+ local anchor_to_lookup = resources.anchor_to_lookup
+ if anchor_to_lookup then
+ for anchor, lookup in next, anchor_to_lookup do
+ local tv = tables[lookup]
+ if tv then
+ anchor_to_lookup[anchor] = tv
+ end
+ end
+ end
+ local lookup_to_anchor = resources.lookup_to_anchor
+ if lookup_to_anchor then
+ for lookup, anchor in next, lookup_to_anchor do
+ local tv = tables[anchor]
+ if tv then
+ lookup_to_anchor[lookup] = tv
+ end
+ end
+ end
+ local ls = resources.sequences
+ if ls then
+ for _, feature in next, ls do
+ local flags = feature.flags
+ if flags then
+ local tv = tables[flags]
+ if tv then
+ feature.flags = tv
+ end
+ end
+ local subtables = feature.subtables
+ if subtables then
+ local tv = tables[subtables]
+ if tv then
+ feature.subtables = tv
+ end
+ end
+ local features = feature.features
+ if features then
+ local tv = tables[features]
+ if tv then
+ feature.features = tv
+ features = unpacked[tv]
+ end
+ if features then
+ for script, data in next, features do
+ local tv = tables[data]
+ if tv then
+ features[script] = tv
+ end
+ end
+ end
+ end
+ local order = feature.order
+ if order then
+ local tv = tables[order]
+ if tv then
+ feature.order = tv
+ end
+ end
+ local markclass = feature.markclass
+ if markclass then
+ local tv = tables[markclass]
+ if tv then
+ feature.markclass = tv
+ end
+ end
+ end
+ end
+ local lookups = resources.lookups
+ if lookups then
+ for _, lookup in next, lookups do
+ local flags = lookup.flags
+ if flags then
+ local tv = tables[flags]
+ if tv then
+ lookup.flags = tv
+ end
+ end
+ local subtables = lookup.subtables
+ if subtables then
+ local tv = tables[subtables]
+ if tv then
+ lookup.subtables = tv
+ end
+ end
+ end
+ end
+ local features = resources.features
+ if features then
+ for _, what in next, glists do
+ local feature = features[what]
+ if feature then
+ for tag, spec in next, feature do
+ local tv = tables[spec]
+ if tv then
+ feature[tag] = tv
+ end
+ end
+ end
+ end
+ end
+ data.tables = nil
+ end
+ end
+end
+
+if otf.enhancers.register then
+
+ otf.enhancers.register( "pack", packdata)
+ otf.enhancers.register("unpack",unpackdata)
+
+-- todo: directive
+
+end
+
+otf.enhancers.unpack = unpackdata -- used elsewhere
+otf.enhancers.pack = packdata -- used elsewhere
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua
new file mode 100644
index 00000000000..a9ad73906c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua
@@ -0,0 +1,2335 @@
+if not modules then modules = { } end modules ['font-otr'] = {
+ 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"
+}
+
+-- When looking into a cid font relates issue in the ff library I wondered if
+-- it made sense to use Lua to filter the information from the otf and ttf
+-- files. Quite some ff code relates to special fonts and in practice we only
+-- use rather normal opentype fonts.
+--
+-- The code here is based on the documentation (and examples) at the microsoft
+-- website. The code will be extended and improved stepwise. After some experiments
+-- I decided to convert to a format more suitable for the context font handler
+-- because it makes no sense to rehash all those lookups again.
+--
+-- Currently we can use this code for getting basic info about the font, loading
+-- shapes and loading the extensive table. I'm not sure if I will provide a ff
+-- compatible output as well (We're not that far from it as currently I can load
+-- all data reasonable fast.)
+
+-- We can omit redundant glyphs names i.e. ones that match the agl or
+-- 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
+-- and the existing (old) code if okay.
+
+-- todo: more messages (only if really needed)
+--
+-- considered, in math:
+--
+-- start -> first (so we can skip the first same-size one)
+-- end -> last
+--
+-- Widths and weights are kind of messy: for instance lmmonolt has a pfmweight of
+-- 400 while it should be 300. So, for now we mostly stick to the old compromis.
+
+-- We don't really need all those language tables so they might be dropped some
+-- day.
+
+-- The new reader is faster on some aspects and slower on other. The memory footprint
+-- is lower. The string reader is a bit faster than the file reader. The new reader
+-- gives more efficient tables and has bit more analysis. In practice these times are
+-- not that relevant because we cache. The otf files take a it more time because we
+-- need to calculate the boundingboxes. In theory the processing of text should be
+-- somewhat faster especially for complex fonts with many lookups.
+--
+-- old new str reader
+-- lmroman12-regular.otf 0.103 0.203 0.195
+-- latinmodern-math.otf 0.454 0.768 0.712
+-- husayni.ttf 1.142 1.526 1.259
+--
+-- If there is demand I will consider making a ff compatible table dumper but it's
+-- probably more fun to provide a way to show features applied.
+
+-- I experimented a bit with f:readbyte(n) and f:readshort() and so and it is indeed
+-- faster but it might not be the real bottleneck as we still need to juggle data. It
+-- is probably more memory efficient as no intermediate strings are involved.
+
+-- if not characters then
+-- require("char-def")
+-- require("char-ini")
+-- end
+
+local next, type, unpack = next, type, unpack
+local byte, lower, char, strip, gsub = string.byte, string.lower, string.char, string.strip, string.gsub
+local bittest = bit32.btest
+local concat, remove, unpack, fastcopy = table.concat, table.remov, table.unpack, table.fastcopy
+local floor, mod, abs, sqrt, round = math.floor, math.mod, math.abs, math.sqrt, 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
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local sortedkeys = table.sortedkeys
+local sortedhash = table.sortedhash
+local stripstring = string.strip
+local utf16_to_utf8_be = utf.utf16_to_utf8_be
+
+local report = logs.reporter("otf reader")
+
+local trace_cmap = false -- only for checking issues
+
+fonts = fonts or { }
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
+local otf = handlers.otf or { }
+handlers.otf = otf
+local readers = otf.readers or { }
+otf.readers = readers
+
+----- streamreader = utilities.streams -- faster on big files
+local streamreader = utilities.files -- faster on identify
+
+readers.streamreader = streamreader
+
+local openfile = streamreader.open
+local closefile = streamreader.close
+local skipbytes = streamreader.skip
+local setposition = streamreader.setposition
+local skipshort = streamreader.skipshort
+local readbytes = streamreader.readbytes
+local readstring = streamreader.readstring
+local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readuint = streamreader.readcardinal3 -- 24-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 readlong = streamreader.readinteger4 -- 24-bit unsigned integer
+local readfixed = streamreader.readfixed4
+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 read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14)
+
+function streamreader.readtag(f)
+ return lower(strip(readstring(f,4)))
+end
+
+-- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a
+-- signed 64-bit integer
+
+local function readlongdatetime(f)
+ local a, b, c, d, e, f, g, h = readbytes(f,8)
+ return 0x100000000 * d + 0x1000000 * e + 0x10000 * f + 0x100 * g + h
+end
+
+local tableversion = 0.004
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+
+readers.tableversion = tableversion
+
+local reportedskipped = { }
+
+local function reportskippedtable(tag)
+ if not reportedskipped[tag] then
+ report("loading of table %a skipped (reported once only)",tag)
+ reportedskipped[tag] = true
+ end
+end
+
+-- We have quite some data tables. We are somewhat ff compatible with names but as I used
+-- the information from the microsoft site there can be differences. Eventually I might end
+-- up with a different ordering and naming.
+
+local reservednames = { [0] =
+ "copyright",
+ "family",
+ "subfamily",
+ "uniqueid",
+ "fullname",
+ "version",
+ "postscriptname",
+ "trademark",
+ "manufacturer",
+ "designer",
+ "description", -- descriptor in ff
+ "vendorurl",
+ "designerurl",
+ "license",
+ "licenseurl",
+ "reserved",
+ "typographicfamily", -- preffamilyname
+ "typographicsubfamily", -- prefmodifiers
+ "compatiblefullname", -- for mac
+ "sampletext",
+ "cidfindfontname",
+ "wwsfamily",
+ "wwssubfamily",
+ "lightbackgroundpalette",
+ "darkbackgroundpalette",
+}
+
+-- more at: https://www.microsoft.com/typography/otspec/name.htm
+
+-- setmetatableindex(reservednames,function(t,k)
+-- local v = "name_" .. k
+-- t[k] = v
+-- return v
+-- end)
+
+local platforms = { [0] =
+ "unicode",
+ "macintosh",
+ "iso",
+ "windows",
+ "custom",
+}
+
+local encodings = {
+ -- these stay:
+ unicode = { [0] =
+ "unicode 1.0 semantics",
+ "unicode 1.1 semantics",
+ "iso/iec 10646",
+ "unicode 2.0 bmp", -- cmap subtable formats 0, 4, 6
+ "unicode 2.0 full", -- cmap subtable formats 0, 4, 6, 10, 12
+ "unicode variation sequences", -- cmap subtable format 14).
+ "unicode full repertoire", -- cmap subtable formats 0, 4, 6, 10, 12, 13
+ },
+ -- these can go:
+ macintosh = { [0] =
+ "roman", "japanese", "chinese (traditional)", "korean", "arabic", "hebrew", "greek", "russian",
+ "rsymbol", "devanagari", "gurmukhi", "gujarati", "oriya", "bengali", "tamil", "telugu", "kannada",
+ "malayalam", "sinhalese", "burmese", "khmer", "thai", "laotian", "georgian", "armenian",
+ "chinese (simplified)", "tibetan", "mongolian", "geez", "slavic", "vietnamese", "sindhi",
+ "uninterpreted",
+ },
+ -- these stay:
+ iso = { [0] =
+ "7-bit ascii",
+ "iso 10646",
+ "iso 8859-1",
+ },
+ -- these stay:
+ windows = { [0] =
+ "symbol",
+ "unicode bmp", -- this is utf16
+ "shiftjis",
+ "prc",
+ "big5",
+ "wansung",
+ "johab",
+ "reserved 7",
+ "reserved 8",
+ "reserved 9",
+ "unicode ucs-4",
+ },
+ custom = {
+ --custom: 0-255 : otf windows nt compatibility mapping
+ }
+}
+
+local decoders = {
+ unicode = { },
+ macintosh = { },
+ iso = { },
+ windows = {
+ -- maybe always utf16
+ ["unicode semantics"] = utf16_to_utf8_be,
+ ["unicode bmp"] = utf16_to_utf8_be,
+ ["unicode full"] = utf16_to_utf8_be,
+ ["unicode 1.0 semantics"] = utf16_to_utf8_be,
+ ["unicode 1.1 semantics"] = utf16_to_utf8_be,
+ ["unicode 2.0 bmp"] = utf16_to_utf8_be,
+ ["unicode 2.0 full"] = utf16_to_utf8_be,
+ ["unicode variation sequences"] = utf16_to_utf8_be,
+ ["unicode full repertoire"] = utf16_to_utf8_be,
+ },
+ custom = { },
+}
+
+-- This is bit over the top as we can just look for either windows, unicode or macintosh
+-- names (in that order). A font with no english name is probably a weird one anyway.
+
+local languages = {
+ -- these stay:
+ unicode = {
+ [ 0] = "english",
+ },
+ -- english can stay:
+ macintosh = {
+ [ 0] = "english",
+ -- [ 1] = "french",
+ -- [ 2] = "german",
+ -- [ 3] = "italian",
+ -- [ 4] = "dutch",
+ -- [ 5] = "swedish",
+ -- [ 6] = "spanish",
+ -- [ 7] = "danish",
+ -- [ 8] = "portuguese",
+ -- [ 9] = "norwegian",
+ -- [ 10] = "hebrew",
+ -- [ 11] = "japanese",
+ -- [ 12] = "arabic",
+ -- [ 13] = "finnish",
+ -- [ 14] = "greek",
+ -- [ 15] = "icelandic",
+ -- [ 16] = "maltese",
+ -- [ 17] = "turkish",
+ -- [ 18] = "croatian",
+ -- [ 19] = "chinese (traditional)",
+ -- [ 20] = "urdu",
+ -- [ 21] = "hindi",
+ -- [ 22] = "thai",
+ -- [ 23] = "korean",
+ -- [ 24] = "lithuanian",
+ -- [ 25] = "polish",
+ -- [ 26] = "hungarian",
+ -- [ 27] = "estonian",
+ -- [ 28] = "latvian",
+ -- [ 29] = "sami",
+ -- [ 30] = "faroese",
+ -- [ 31] = "farsi/persian",
+ -- [ 32] = "russian",
+ -- [ 33] = "chinese (simplified)",
+ -- [ 34] = "flemish",
+ -- [ 35] = "irish gaelic",
+ -- [ 36] = "albanian",
+ -- [ 37] = "romanian",
+ -- [ 38] = "czech",
+ -- [ 39] = "slovak",
+ -- [ 40] = "slovenian",
+ -- [ 41] = "yiddish",
+ -- [ 42] = "serbian",
+ -- [ 43] = "macedonian",
+ -- [ 44] = "bulgarian",
+ -- [ 45] = "ukrainian",
+ -- [ 46] = "byelorussian",
+ -- [ 47] = "uzbek",
+ -- [ 48] = "kazakh",
+ -- [ 49] = "azerbaijani (cyrillic script)",
+ -- [ 50] = "azerbaijani (arabic script)",
+ -- [ 51] = "armenian",
+ -- [ 52] = "georgian",
+ -- [ 53] = "moldavian",
+ -- [ 54] = "kirghiz",
+ -- [ 55] = "tajiki",
+ -- [ 56] = "turkmen",
+ -- [ 57] = "mongolian (mongolian script)",
+ -- [ 58] = "mongolian (cyrillic script)",
+ -- [ 59] = "pashto",
+ -- [ 60] = "kurdish",
+ -- [ 61] = "kashmiri",
+ -- [ 62] = "sindhi",
+ -- [ 63] = "tibetan",
+ -- [ 64] = "nepali",
+ -- [ 65] = "sanskrit",
+ -- [ 66] = "marathi",
+ -- [ 67] = "bengali",
+ -- [ 68] = "assamese",
+ -- [ 69] = "gujarati",
+ -- [ 70] = "punjabi",
+ -- [ 71] = "oriya",
+ -- [ 72] = "malayalam",
+ -- [ 73] = "kannada",
+ -- [ 74] = "tamil",
+ -- [ 75] = "telugu",
+ -- [ 76] = "sinhalese",
+ -- [ 77] = "burmese",
+ -- [ 78] = "khmer",
+ -- [ 79] = "lao",
+ -- [ 80] = "vietnamese",
+ -- [ 81] = "indonesian",
+ -- [ 82] = "tagalong",
+ -- [ 83] = "malay (roman script)",
+ -- [ 84] = "malay (arabic script)",
+ -- [ 85] = "amharic",
+ -- [ 86] = "tigrinya",
+ -- [ 87] = "galla",
+ -- [ 88] = "somali",
+ -- [ 89] = "swahili",
+ -- [ 90] = "kinyarwanda/ruanda",
+ -- [ 91] = "rundi",
+ -- [ 92] = "nyanja/chewa",
+ -- [ 93] = "malagasy",
+ -- [ 94] = "esperanto",
+ -- [128] = "welsh",
+ -- [129] = "basque",
+ -- [130] = "catalan",
+ -- [131] = "latin",
+ -- [132] = "quenchua",
+ -- [133] = "guarani",
+ -- [134] = "aymara",
+ -- [135] = "tatar",
+ -- [136] = "uighur",
+ -- [137] = "dzongkha",
+ -- [138] = "javanese (roman script)",
+ -- [139] = "sundanese (roman script)",
+ -- [140] = "galician",
+ -- [141] = "afrikaans",
+ -- [142] = "breton",
+ -- [143] = "inuktitut",
+ -- [144] = "scottish gaelic",
+ -- [145] = "manx gaelic",
+ -- [146] = "irish gaelic (with dot above)",
+ -- [147] = "tongan",
+ -- [148] = "greek (polytonic)",
+ -- [149] = "greenlandic",
+ -- [150] = "azerbaijani (roman script)",
+ },
+ -- these can stay:
+ iso = {
+ },
+ -- english can stay:
+ windows = {
+ -- [0x0436] = "afrikaans - south africa",
+ -- [0x041c] = "albanian - albania",
+ -- [0x0484] = "alsatian - france",
+ -- [0x045e] = "amharic - ethiopia",
+ -- [0x1401] = "arabic - algeria",
+ -- [0x3c01] = "arabic - bahrain",
+ -- [0x0c01] = "arabic - egypt",
+ -- [0x0801] = "arabic - iraq",
+ -- [0x2c01] = "arabic - jordan",
+ -- [0x3401] = "arabic - kuwait",
+ -- [0x3001] = "arabic - lebanon",
+ -- [0x1001] = "arabic - libya",
+ -- [0x1801] = "arabic - morocco",
+ -- [0x2001] = "arabic - oman",
+ -- [0x4001] = "arabic - qatar",
+ -- [0x0401] = "arabic - saudi arabia",
+ -- [0x2801] = "arabic - syria",
+ -- [0x1c01] = "arabic - tunisia",
+ -- [0x3801] = "arabic - u.a.e.",
+ -- [0x2401] = "arabic - yemen",
+ -- [0x042b] = "armenian - armenia",
+ -- [0x044d] = "assamese - india",
+ -- [0x082c] = "azeri (cyrillic) - azerbaijan",
+ -- [0x042c] = "azeri (latin) - azerbaijan",
+ -- [0x046d] = "bashkir - russia",
+ -- [0x042d] = "basque - basque",
+ -- [0x0423] = "belarusian - belarus",
+ -- [0x0845] = "bengali - bangladesh",
+ -- [0x0445] = "bengali - india",
+ -- [0x201a] = "bosnian (cyrillic) - bosnia and herzegovina",
+ -- [0x141a] = "bosnian (latin) - bosnia and herzegovina",
+ -- [0x047e] = "breton - france",
+ -- [0x0402] = "bulgarian - bulgaria",
+ -- [0x0403] = "catalan - catalan",
+ -- [0x0c04] = "chinese - hong kong s.a.r.",
+ -- [0x1404] = "chinese - macao s.a.r.",
+ -- [0x0804] = "chinese - people's republic of china",
+ -- [0x1004] = "chinese - singapore",
+ -- [0x0404] = "chinese - taiwan",
+ -- [0x0483] = "corsican - france",
+ -- [0x041a] = "croatian - croatia",
+ -- [0x101a] = "croatian (latin) - bosnia and herzegovina",
+ -- [0x0405] = "czech - czech republic",
+ -- [0x0406] = "danish - denmark",
+ -- [0x048c] = "dari - afghanistan",
+ -- [0x0465] = "divehi - maldives",
+ -- [0x0813] = "dutch - belgium",
+ -- [0x0413] = "dutch - netherlands",
+ -- [0x0c09] = "english - australia",
+ -- [0x2809] = "english - belize",
+ -- [0x1009] = "english - canada",
+ -- [0x2409] = "english - caribbean",
+ -- [0x4009] = "english - india",
+ -- [0x1809] = "english - ireland",
+ -- [0x2009] = "english - jamaica",
+ -- [0x4409] = "english - malaysia",
+ -- [0x1409] = "english - new zealand",
+ -- [0x3409] = "english - republic of the philippines",
+ -- [0x4809] = "english - singapore",
+ -- [0x1c09] = "english - south africa",
+ -- [0x2c09] = "english - trinidad and tobago",
+ -- [0x0809] = "english - united kingdom",
+ [0x0409] = "english - united states",
+ -- [0x3009] = "english - zimbabwe",
+ -- [0x0425] = "estonian - estonia",
+ -- [0x0438] = "faroese - faroe islands",
+ -- [0x0464] = "filipino - philippines",
+ -- [0x040b] = "finnish - finland",
+ -- [0x080c] = "french - belgium",
+ -- [0x0c0c] = "french - canada",
+ -- [0x040c] = "french - france",
+ -- [0x140c] = "french - luxembourg",
+ -- [0x180c] = "french - principality of monoco",
+ -- [0x100c] = "french - switzerland",
+ -- [0x0462] = "frisian - netherlands",
+ -- [0x0456] = "galician - galician",
+ -- [0x0437] = "georgian -georgia",
+ -- [0x0c07] = "german - austria",
+ -- [0x0407] = "german - germany",
+ -- [0x1407] = "german - liechtenstein",
+ -- [0x1007] = "german - luxembourg",
+ -- [0x0807] = "german - switzerland",
+ -- [0x0408] = "greek - greece",
+ -- [0x046f] = "greenlandic - greenland",
+ -- [0x0447] = "gujarati - india",
+ -- [0x0468] = "hausa (latin) - nigeria",
+ -- [0x040d] = "hebrew - israel",
+ -- [0x0439] = "hindi - india",
+ -- [0x040e] = "hungarian - hungary",
+ -- [0x040f] = "icelandic - iceland",
+ -- [0x0470] = "igbo - nigeria",
+ -- [0x0421] = "indonesian - indonesia",
+ -- [0x045d] = "inuktitut - canada",
+ -- [0x085d] = "inuktitut (latin) - canada",
+ -- [0x083c] = "irish - ireland",
+ -- [0x0434] = "isixhosa - south africa",
+ -- [0x0435] = "isizulu - south africa",
+ -- [0x0410] = "italian - italy",
+ -- [0x0810] = "italian - switzerland",
+ -- [0x0411] = "japanese - japan",
+ -- [0x044b] = "kannada - india",
+ -- [0x043f] = "kazakh - kazakhstan",
+ -- [0x0453] = "khmer - cambodia",
+ -- [0x0486] = "k'iche - guatemala",
+ -- [0x0487] = "kinyarwanda - rwanda",
+ -- [0x0441] = "kiswahili - kenya",
+ -- [0x0457] = "konkani - india",
+ -- [0x0412] = "korean - korea",
+ -- [0x0440] = "kyrgyz - kyrgyzstan",
+ -- [0x0454] = "lao - lao p.d.r.",
+ -- [0x0426] = "latvian - latvia",
+ -- [0x0427] = "lithuanian - lithuania",
+ -- [0x082e] = "lower sorbian - germany",
+ -- [0x046e] = "luxembourgish - luxembourg",
+ -- [0x042f] = "macedonian (fyrom) - former yugoslav republic of macedonia",
+ -- [0x083e] = "malay - brunei darussalam",
+ -- [0x043e] = "malay - malaysia",
+ -- [0x044c] = "malayalam - india",
+ -- [0x043a] = "maltese - malta",
+ -- [0x0481] = "maori - new zealand",
+ -- [0x047a] = "mapudungun - chile",
+ -- [0x044e] = "marathi - india",
+ -- [0x047c] = "mohawk - mohawk",
+ -- [0x0450] = "mongolian (cyrillic) - mongolia",
+ -- [0x0850] = "mongolian (traditional) - people's republic of china",
+ -- [0x0461] = "nepali - nepal",
+ -- [0x0414] = "norwegian (bokmal) - norway",
+ -- [0x0814] = "norwegian (nynorsk) - norway",
+ -- [0x0482] = "occitan - france",
+ -- [0x0448] = "odia (formerly oriya) - india",
+ -- [0x0463] = "pashto - afghanistan",
+ -- [0x0415] = "polish - poland",
+ -- [0x0416] = "portuguese - brazil",
+ -- [0x0816] = "portuguese - portugal",
+ -- [0x0446] = "punjabi - india",
+ -- [0x046b] = "quechua - bolivia",
+ -- [0x086b] = "quechua - ecuador",
+ -- [0x0c6b] = "quechua - peru",
+ -- [0x0418] = "romanian - romania",
+ -- [0x0417] = "romansh - switzerland",
+ -- [0x0419] = "russian - russia",
+ -- [0x243b] = "sami (inari) - finland",
+ -- [0x103b] = "sami (lule) - norway",
+ -- [0x143b] = "sami (lule) - sweden",
+ -- [0x0c3b] = "sami (northern) - finland",
+ -- [0x043b] = "sami (northern) - norway",
+ -- [0x083b] = "sami (northern) - sweden",
+ -- [0x203b] = "sami (skolt) - finland",
+ -- [0x183b] = "sami (southern) - norway",
+ -- [0x1c3b] = "sami (southern) - sweden",
+ -- [0x044f] = "sanskrit - india",
+ -- [0x1c1a] = "serbian (cyrillic) - bosnia and herzegovina",
+ -- [0x0c1a] = "serbian (cyrillic) - serbia",
+ -- [0x181a] = "serbian (latin) - bosnia and herzegovina",
+ -- [0x081a] = "serbian (latin) - serbia",
+ -- [0x046c] = "sesotho sa leboa - south africa",
+ -- [0x0432] = "setswana - south africa",
+ -- [0x045b] = "sinhala - sri lanka",
+ -- [0x041b] = "slovak - slovakia",
+ -- [0x0424] = "slovenian - slovenia",
+ -- [0x2c0a] = "spanish - argentina",
+ -- [0x400a] = "spanish - bolivia",
+ -- [0x340a] = "spanish - chile",
+ -- [0x240a] = "spanish - colombia",
+ -- [0x140a] = "spanish - costa rica",
+ -- [0x1c0a] = "spanish - dominican republic",
+ -- [0x300a] = "spanish - ecuador",
+ -- [0x440a] = "spanish - el salvador",
+ -- [0x100a] = "spanish - guatemala",
+ -- [0x480a] = "spanish - honduras",
+ -- [0x080a] = "spanish - mexico",
+ -- [0x4c0a] = "spanish - nicaragua",
+ -- [0x180a] = "spanish - panama",
+ -- [0x3c0a] = "spanish - paraguay",
+ -- [0x280a] = "spanish - peru",
+ -- [0x500a] = "spanish - puerto rico",
+ -- [0x0c0a] = "spanish (modern sort) - spain",
+ -- [0x040a] = "spanish (traditional sort) - spain",
+ -- [0x540a] = "spanish - united states",
+ -- [0x380a] = "spanish - uruguay",
+ -- [0x200a] = "spanish - venezuela",
+ -- [0x081d] = "sweden - finland",
+ -- [0x041d] = "swedish - sweden",
+ -- [0x045a] = "syriac - syria",
+ -- [0x0428] = "tajik (cyrillic) - tajikistan",
+ -- [0x085f] = "tamazight (latin) - algeria",
+ -- [0x0449] = "tamil - india",
+ -- [0x0444] = "tatar - russia",
+ -- [0x044a] = "telugu - india",
+ -- [0x041e] = "thai - thailand",
+ -- [0x0451] = "tibetan - prc",
+ -- [0x041f] = "turkish - turkey",
+ -- [0x0442] = "turkmen - turkmenistan",
+ -- [0x0480] = "uighur - prc",
+ -- [0x0422] = "ukrainian - ukraine",
+ -- [0x042e] = "upper sorbian - germany",
+ -- [0x0420] = "urdu - islamic republic of pakistan",
+ -- [0x0843] = "uzbek (cyrillic) - uzbekistan",
+ -- [0x0443] = "uzbek (latin) - uzbekistan",
+ -- [0x042a] = "vietnamese - vietnam",
+ -- [0x0452] = "welsh - united kingdom",
+ -- [0x0488] = "wolof - senegal",
+ -- [0x0485] = "yakut - russia",
+ -- [0x0478] = "yi - prc",
+ -- [0x046a] = "yoruba - nigeria",
+ },
+ custom = {
+ },
+}
+
+local standardromanencoding = { [0] = -- taken from wikipedia
+ "notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl",
+ "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft",
+ "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
+ "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
+ "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b",
+ "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
+ "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
+ "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute",
+ "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex",
+ "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
+ "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
+ "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute",
+ "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
+ "section", "bullet", "paragraph", "germandbls", "registered", "copyright",
+ "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity",
+ "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff",
+ "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine",
+ "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+ "radical", "florin", "approxequal", "Delta", "guillemotleft",
+ "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
+ "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright",
+ "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis",
+ "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl",
+ "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase",
+ "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave",
+ "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
+ "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
+ "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla",
+ "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron",
+ "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn",
+ "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior",
+ "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+ "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron",
+ "dcroat",
+}
+
+local weights = {
+ [100] = "thin",
+ [200] = "extralight",
+ [300] = "light",
+ [400] = "normal",
+ [500] = "medium",
+ [600] = "semibold",
+ [700] = "bold",
+ [800] = "extrabold",
+ [900] = "black",
+}
+
+local widths = {
+ [1] = "ultracondensed",
+ [2] = "extracondensed",
+ [3] = "condensed",
+ [4] = "semicondensed",
+ [5] = "normal",
+ [6] = "semiexpanded",
+ [7] = "expanded",
+ [8] = "extraexpanded",
+ [9] = "ultraexpanded",
+}
+
+setmetatableindex(weights, function(t,k)
+ local r = floor((k + 50) / 100) * 100
+ local v = (r > 900 and "black") or rawget(t,r) or "normal"
+-- print("weight:",k,r,v)
+ return v
+end)
+
+setmetatableindex(widths,function(t,k)
+-- print("width:",k)
+ return "normal"
+end)
+
+local panoseweights = {
+ [ 0] = "normal",
+ [ 1] = "normal",
+ [ 2] = "verylight",
+ [ 3] = "light",
+ [ 4] = "thin",
+ [ 5] = "book",
+ [ 6] = "medium",
+ [ 7] = "demi",
+ [ 8] = "bold",
+ [ 9] = "heavy",
+ [10] = "black",
+}
+
+local panosewidths = {
+ [ 0] = "normal",
+ [ 1] = "normal",
+ [ 2] = "normal",
+ [ 3] = "normal",
+ [ 4] = "normal",
+ [ 5] = "expanded",
+ [ 6] = "condensed",
+ [ 7] = "veryexpanded",
+ [ 8] = "verycondensed",
+ [ 9] = "monospaced",
+}
+
+-- We implement a reader per table.
+
+-- The name table is probably the first one to load. After all this one provides
+-- useful information about what we deal with. The complication is that we need
+-- to filter the best one available.
+
+local platformnames = {
+ postscriptname = true,
+ fullname = true,
+ family = true,
+ subfamily = true,
+ typographicfamily = true,
+ typographicsubfamily = true,
+ compatiblefullname = true,
+}
+
+function readers.name(f,fontdata,specification)
+ local datatable = fontdata.tables.name
+ if datatable then
+ setposition(f,datatable.offset)
+ local format = readushort(f)
+ local nofnames = readushort(f)
+ local offset = readushort(f)
+ -- we can also provide a raw list as extra, todo as option
+ local start = datatable.offset + offset
+ local namelists = {
+ unicode = { },
+ windows = { },
+ macintosh = { },
+ -- iso = { },
+ -- windows = { },
+ }
+ for i=1,nofnames do
+ local platform = platforms[readushort(f)]
+ if platform then
+ local namelist = namelists[platform]
+ if namelist then
+ local encoding = readushort(f)
+ local language = readushort(f)
+ local encodings = encodings[platform]
+ local languages = languages[platform]
+ if encodings and languages then
+ local encoding = encodings[encoding]
+ local language = languages[language]
+ if encoding and language then
+ local name = reservednames[readushort(f)]
+ if name then
+ namelist[#namelist+1] = {
+ platform = platform,
+ encoding = encoding,
+ language = language,
+ name = name,
+ length = readushort(f),
+ offset = start + readushort(f),
+ }
+ else
+ skipshort(f,2)
+ end
+ else
+ skipshort(f,3)
+ end
+ else
+ skipshort(f,3)
+ end
+ else
+ skipshort(f,5)
+ end
+ else
+ skipshort(f,5)
+ end
+ end
+ -- if format == 1 then
+ -- local noftags = readushort(f)
+ -- for i=1,noftags do
+ -- local length = readushort(f)
+ -- local offset = readushort(f)
+ -- end
+ -- end
+ --
+ -- we need to choose one we like, for instance an unicode one
+ --
+ local names = { }
+ local done = { }
+ --
+ -- there is quite some logic in ff ... hard to follow so we start simple
+ -- and extend when we run into it (todo: proper reverse hash) .. we're only
+ -- interested in english anyway
+ --
+ local function filter(platform,e,l)
+ local namelist = namelists[platform]
+ for i=1,#namelist do
+ local name = namelist[i]
+ local nametag = name.name
+ if not done[nametag] then
+ local encoding = name.encoding
+ 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
+ names[nametag] = {
+ content = content,
+ platform = platform,
+ encoding = encoding,
+ language = language,
+ }
+ done[nametag] = true
+ end
+ end
+ end
+ end
+ --
+ filter("windows","unicode bmp","english - united states")
+ -- filter("unicode") -- which one ?
+ filter("macintosh","roman","english")
+ filter("windows")
+ filter("macintosh")
+ filter("unicode")
+ --
+ fontdata.names = names
+ --
+ if specification.platformnames then
+ local collected = { }
+ 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
+ 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
+ if filtered then
+ filtered[name] = content
+ else
+ filtered = { [name] = content }
+ end
+ end
+ end
+ if filtered then
+ collected[platform] = filtered
+ end
+ end
+ fontdata.platformnames = collected
+ end
+ else
+ fontdata.names = { }
+ end
+end
+
+----- validutf = lpeg.patterns.utf8character^0 * P(-1)
+local validutf = lpeg.patterns.validutf8
+
+local function getname(fontdata,key)
+ local names = fontdata.names
+ if names then
+ local value = names[key]
+ if value then
+ local content = value.content
+ return lpegmatch(validutf,content) and content or nil
+ end
+ end
+end
+
+-- This table is an original windows (with its precursor os/2) table. In ff this one is
+-- part of the pfminfo table but here we keep it separate (for now). We will create a
+-- properties table afterwards.
+
+readers["os/2"] = function(f,fontdata)
+ local datatable = fontdata.tables["os/2"]
+ if datatable then
+ setposition(f,datatable.offset)
+ local version = readushort(f)
+ local windowsmetrics = {
+ version = version,
+ averagewidth = readshort(f),
+ weightclass = readushort(f),
+ widthclass = readushort(f),
+ fstype = readushort(f),
+ subscriptxsize = readshort(f),
+ subscriptysize = readshort(f),
+ subscriptxoffset = readshort(f),
+ subscriptyoffset = readshort(f),
+ superscriptxsize = readshort(f),
+ superscriptysize = readshort(f),
+ superscriptxoffset = readshort(f),
+ superscriptyoffset = readshort(f),
+ strikeoutsize = readshort(f),
+ strikeoutpos = readshort(f),
+ familyclass = readshort(f),
+ panose = { readbytes(f,10) },
+ unicoderanges = { readulong(f), readulong(f), readulong(f), readulong(f) },
+ vendor = readstring(f,4),
+ fsselection = readushort(f),
+ firstcharindex = readushort(f),
+ lastcharindex = readushort(f),
+ typoascender = readshort(f),
+ typodescender = readshort(f),
+ typolinegap = readshort(f),
+ winascent = readushort(f),
+ windescent = readushort(f),
+ }
+ if version >= 1 then
+ windowsmetrics.codepageranges = { readulong(f), readulong(f) }
+ end
+ if version >= 3 then
+ windowsmetrics.xheight = readshort(f)
+ windowsmetrics.capheight = readshort(f)
+ windowsmetrics.defaultchar = readushort(f)
+ windowsmetrics.breakchar = readushort(f)
+ -- windowsmetrics.maxcontexts = readushort(f)
+ -- windowsmetrics.loweropticalpointsize = readushort(f)
+ -- windowsmetrics.upperopticalpointsize = readushort(f)
+ end
+ --
+ -- todo: unicoderanges
+ --
+ windowsmetrics.weight = windowsmetrics.weightclass and weights[windowsmetrics.weightclass]
+ windowsmetrics.width = windowsmetrics.widthclass and widths [windowsmetrics.widthclass]
+ --
+ windowsmetrics.panoseweight = panoseweights[windowsmetrics.panose[3]]
+ windowsmetrics.panosewidth = panosewidths [windowsmetrics.panose[4]]
+ --
+ fontdata.windowsmetrics = windowsmetrics
+ else
+ fontdata.windowsmetrics = { }
+ end
+end
+
+readers.head = function(f,fontdata)
+ local datatable = fontdata.tables.head
+ if datatable then
+ setposition(f,datatable.offset)
+ 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),
+ }
+ fontdata.fontheader = fontheader
+ else
+ fontdata.fontheader = { }
+ end
+ fontdata.nofglyphs = 0
+end
+
+-- This table is a rather simple one. No treatment of values is needed here. Most
+-- variables are not used but nofhmetrics is quite important.
+
+readers.hhea = function(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.hhea
+ if datatable then
+ setposition(f,datatable.offset)
+ fontdata.horizontalheader = {
+ version = readfixed(f),
+ ascender = readfword(f),
+ descender = readfword(f),
+ linegap = readfword(f),
+ maxadvancewidth = readufword(f),
+ minleftsidebearing = readfword(f),
+ minrightsidebearing = readfword(f),
+ maxextent = readfword(f),
+ caretsloperise = readshort(f),
+ caretsloperun = readshort(f),
+ caretoffset = readshort(f),
+ reserved_1 = readshort(f),
+ reserved_2 = readshort(f),
+ reserved_3 = readshort(f),
+ reserved_4 = readshort(f),
+ metricdataformat = readshort(f),
+ nofhmetrics = readushort(f),
+ }
+ else
+ fontdata.horizontalheader = {
+ nofhmetrics = 0,
+ }
+ end
+ end
+end
+
+-- We probably never need all these variables, but we do need the nofglyphs when loading other
+-- tables. Again we use the microsoft names but see no reason to have "max" in each name.
+
+-- fontdata.maximumprofile can be bad
+
+readers.maxp = function(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.maxp
+ if datatable then
+ setposition(f,datatable.offset)
+ local version = readfixed(f)
+ local nofglyphs = readushort(f)
+ fontdata.nofglyphs = nofglyphs
+ if version == 0.5 then
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = nofglyphs,
+ }
+ return
+ elseif version == 1.0 then
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = nofglyphs,
+ points = readushort(f),
+ contours = readushort(f),
+ compositepoints = readushort(f),
+ compositecontours = readushort(f),
+ zones = readushort(f),
+ twilightpoints = readushort(f),
+ storage = readushort(f),
+ functiondefs = readushort(f),
+ instructiondefs = readushort(f),
+ stackelements = readushort(f),
+ sizeofinstructions = readushort(f),
+ componentelements = readushort(f),
+ componentdepth = readushort(f),
+ }
+ return
+ end
+ end
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = 0,
+ }
+ end
+end
+
+-- Here we filter the (advance) widths (that can be different from the boundingbox width of
+-- course).
+
+readers.hmtx = function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.hmtx
+ if datatable then
+ setposition(f,datatable.offset)
+ local nofmetrics = fontdata.horizontalheader.nofhmetrics
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local width = 0 -- advance
+ local leftsidebearing = 0
+ for i=0,nofmetrics-1 do
+ local glyph = glyphs[i]
+ width = readshort(f)
+ leftsidebearing = readshort(f)
+ if width ~= 0 then
+ glyph.width = width
+ 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.
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph = glyphs[i]
+ if width ~= 0 then
+ glyph.width = width
+ end
+ -- if leftsidebearing ~= 0 then
+ -- glyph.lsb = leftsidebearing
+ -- end
+ end
+ end
+ end
+end
+
+-- The post table relates to postscript (printing) but has some relevant properties for other
+-- usage as well. We just use the names from the microsoft specification. The version 2.0
+-- description is somewhat fuzzy but it is a hybrid with overloads.
+
+readers.post = function(f,fontdata,specification)
+ local datatable = fontdata.tables.post
+ if datatable then
+ setposition(f,datatable.offset)
+ local version = readfixed(f)
+ fontdata.postscript = {
+ version = version,
+ italicangle = round(1000*readfixed(f))/1000,
+ underlineposition = readfword(f),
+ underlinethickness = readfword(f),
+ monospaced = readulong(f),
+ minmemtype42 = readulong(f),
+ maxmemtype42 = readulong(f),
+ minmemtype1 = readulong(f),
+ maxmemtype1 = readulong(f),
+ }
+ if not specification.glyphs then
+ -- enough done
+ elseif version == 1.0 then
+ -- mac encoding (258 glyphs)
+ for index=0,#standardromanencoding do
+ glyphs[index].name = standardromanencoding[index]
+ end
+ elseif version == 2.0 then
+ local glyphs = fontdata.glyphs
+ local nofglyphs = readushort(f)
+ local indices = { }
+ local names = { }
+ local maxnames = 0
+ for i=0,nofglyphs-1 do
+ local nameindex = readushort(f)
+ if nameindex >= 258 then
+ maxnames = maxnames + 1
+ nameindex = nameindex - 257
+ indices[nameindex] = i
+ else
+ glyphs[i].name = standardromanencoding[nameindex]
+ end
+ end
+ for i=1,maxnames do
+ local mapping = indices[i]
+ if not mapping then
+ report("quit post name fetching at %a of %a: %s",i,maxnames,"no index")
+ break
+ else
+ local length = readbyte(f)
+ if length > 0 then
+ glyphs[mapping].name = readstring(f,length)
+ else
+ report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow")
+ break
+ 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 = { }
+ end
+end
+
+readers.cff = function(f,fontdata,specification)
+ if specification.glyphs then
+ reportskippedtable("cff")
+ end
+end
+
+-- Not all cmaps make sense .. e.g. dfont is obsolete and probably more are not relevant. Let's see
+-- what we run into. There is some weird calculation going on here because we offset in a table
+-- being a blob of memory or file. Anyway, I can't stand lunatic formats like this esp when there
+-- is no real gain.
+
+local formatreaders = { }
+local duplicatestoo = true
+
+local sequence = {
+ { 3, 1, 4 },
+ { 3, 10, 12 },
+ { 0, 3, 4 },
+ { 0, 1, 4 },
+ -- { 0, 4, 12 },
+ { 0, 0, 6 },
+ { 3, 0, 6 },
+ -- variants
+ { 0, 5, 14 },
+ -- last resort ranges
+ { 3, 10, 13 },
+}
+
+-- local sequence = {
+-- { 0, 1, 4 },
+-- { 0, 4, 12 },
+-- { 0, 3, 4 },
+-- { 3, 1, 4 },
+-- { 3, 10, 12 },
+-- { 0, 0, 6 },
+-- { 3, 0, 6 },
+-- -- variants
+-- { 0, 5, 14 },
+-- }
+
+local supported = { }
+
+for i=1,#sequence do
+ local sp, se, sf = unpack(sequence[i])
+ local p = supported[sp]
+ if not p then
+ p = { }
+ supported[sp] = p
+ end
+ local e = p[se]
+ if not e then
+ e = { }
+ p[se] = e
+ end
+ e[sf] = true
+end
+
+formatreaders[4] = function(f,fontdata,offset)
+ setposition(f,offset+2) -- skip format
+ --
+ local length = readushort(f) -- in bytes of subtable
+ local language = readushort(f)
+ local nofsegments = readushort(f) / 2
+ --
+ 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
+ -- format length language nofsegments searchrange entryselector rangeshift 4-tables
+ local size = (length - 2 * 2 - 5 * 2 - 4 * nofsegments * 2) / 2
+ for i=1,size-1 do
+ indices[i] = readushort(f)
+ end
+ --
+ for segment=1,nofsegments do
+ local startchar = startchars[segment]
+ local endchar = endchars[segment]
+ local offset = offsets[segment]
+ local delta = deltas[segment]
+ if startchar == 0xFFFF and endchar == 0xFFFF then
+ -- break
+ elseif startchar == 0xFFFF and offset == 0 then
+ -- break
+ elseif offset == 0xFFFF then
+ -- bad encoding
+ elseif offset == 0 then
+ if trace_cmap then
+ report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,mod(startchar + delta,65536))
+ end
+ for unicode=startchar,endchar do
+ local index = mod(unicode + delta,65536)
+ if index and index > 0 then
+ local glyph = glyphs[index]
+ if glyph then
+ local gu = glyph.unicode
+ if not gu then
+ glyph.unicode = unicode
+ nofdone = nofdone + 1
+ elseif gu ~= unicode then
+ if duplicatestoo then
+ local d = duplicates[gu]
+ if d then
+ d[unicode] = true
+ else
+ duplicates[gu] = { [unicode] = true }
+ end
+ else
+ -- no duplicates ... weird side effects in lm
+ report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name)
+ end
+ end
+ if not mapping[index] then
+ mapping[index] = unicode
+ end
+ end
+ end
+ end
+ else
+ local shift = (segment-nofsegments+offset/2) - startchar
+ if trace_cmap then
+ report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,mod(startchar + delta,65536))
+ end
+ for unicode=startchar,endchar do
+ local slot = shift + unicode
+ local index = indices[slot]
+ if index and index > 0 then
+ index = mod(index + delta,65536)
+ local glyph = glyphs[index]
+ if glyph then
+ local gu = glyph.unicode
+ if not gu then
+ glyph.unicode = unicode
+ nofdone = nofdone + 1
+ elseif gu ~= unicode then
+ if duplicatestoo then
+ local d = duplicates[gu]
+ if d then
+ d[unicode] = true
+ else
+ duplicates[gu] = { [unicode] = true }
+ end
+ else
+ -- no duplicates ... weird side effects in lm
+ report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name)
+ end
+ end
+ if not mapping[index] then
+ mapping[index] = unicode
+ end
+ end
+ end
+ end
+ end
+ end
+ return nofdone
+end
+
+formatreaders[6] = function(f,fontdata,offset)
+ setposition(f,offset) -- + 2 + 2 + 2 -- skip format length language
+ local format = readushort(f)
+ local length = readushort(f)
+ local language = readushort(f)
+ local mapping = fontdata.mapping
+ local glyphs = fontdata.glyphs
+ local duplicates = fontdata.duplicates
+ local start = readushort(f)
+ local count = readushort(f)
+ local stop = start+count-1
+ local nofdone = 0
+ if trace_cmap then
+ report("format 6 from %C to %C",2,start,stop)
+ end
+ for unicode=start,stop do
+ local index = readushort(f)
+ if index > 0 then
+ local glyph = glyphs[index]
+ if glyph then
+ local gu = glyph.unicode
+ if not gu then
+ glyph.unicode = unicode
+ nofdone = nofdone + 1
+ elseif gu ~= unicode then
+ -- report("format 6 overloading %C to %C",gu,unicode)
+ -- glyph.unicode = unicode
+ -- no duplicates ... weird side effects in lm
+ end
+ if not mapping[index] then
+ mapping[index] = unicode
+ end
+ end
+ end
+ end
+ return nofdone
+end
+
+formatreaders[12] = function(f,fontdata,offset)
+ setposition(f,offset+2+2+4+4) -- skip format reserved length language
+ local mapping = fontdata.mapping
+ local glyphs = fontdata.glyphs
+ local duplicates = fontdata.duplicates
+ local nofgroups = readulong(f)
+ local nofdone = 0
+ for i=1,nofgroups do
+ local first = readulong(f)
+ local last = readulong(f)
+ local index = readulong(f)
+ if trace_cmap then
+ report("format 12 from %C to %C starts at index %i",first,last,index)
+ end
+ for unicode=first,last do
+ local glyph = glyphs[index]
+ if glyph then
+ local gu = glyph.unicode
+ if not gu then
+ glyph.unicode = unicode
+ nofdone = nofdone + 1
+ elseif gu ~= unicode then
+ -- e.g. sourcehan fonts need this
+ local d = duplicates[gu]
+ if d then
+ d[unicode] = true
+ else
+ duplicates[gu] = { [unicode] = true }
+ end
+ end
+ if not mapping[index] then
+ mapping[index] = unicode
+ end
+ end
+ index = index + 1
+ end
+ end
+ return nofdone
+end
+
+formatreaders[13] = function(f,fontdata,offset)
+ --
+ -- this fector is only used for simple fallback fonts
+ --
+ setposition(f,offset+2+2+4+4) -- skip format reserved length language
+ local mapping = fontdata.mapping
+ local glyphs = fontdata.glyphs
+ local duplicates = fontdata.duplicates
+ local nofgroups = readulong(f)
+ local nofdone = 0
+ for i=1,nofgroups do
+ local first = readulong(f)
+ local last = readulong(f)
+ local index = readulong(f)
+ if first < privateoffset then
+ if trace_cmap then
+ report("format 13 from %C to %C get index %i",first,last,index)
+ end
+ local glyph = glyphs[index]
+ local unicode = glyph.unicode
+ if not unicode then
+ unicode = first
+ glyph.unicode = unicode
+ first = first + 1
+ end
+ local list = duplicates[unicode]
+ mapping[index] = unicode
+ if not list then
+ list = { }
+ duplicates[unicode] = list
+ end
+ if last >= privateoffset then
+ local limit = privateoffset - 1
+ report("format 13 from %C to %C pruned to %C",first,last,limit)
+ last = limit
+ end
+ for unicode=first,last do
+ list[unicode] = true
+ end
+ nofdone = nofdone + last - first + 1
+ else
+ report("format 13 from %C to %C ignored",first,last)
+ end
+ end
+ return nofdone
+end
+
+formatreaders[14] = function(f,fontdata,offset)
+ if offset and offset ~= 0 then
+ setposition(f,offset)
+ local format = readushort(f)
+ local length = readulong(f)
+ local nofrecords = readulong(f)
+ local records = { }
+ local variants = { }
+ local nofdone = 0
+ fontdata.variants = variants
+ for i=1,nofrecords do
+ records[i] = {
+ selector = readuint(f),
+ default = readulong(f), -- default offset
+ other = readulong(f), -- non-default offset
+ }
+ end
+ for i=1,nofrecords do
+ local record = records[i]
+ local selector = record.selector
+ local default = record.default
+ local other = record.other
+ --
+ -- there is no need to map the defaults to themselves
+ --
+ -- if default ~= 0 then
+ -- setposition(f,offset+default)
+ -- local nofranges = readulong(f)
+ -- for i=1,nofranges do
+ -- local start = readuint(f)
+ -- local extra = readbyte(f)
+ -- for i=start,start+extra do
+ -- mapping[i] = i
+ -- end
+ -- end
+ -- end
+ local other = record.other
+ if other ~= 0 then
+ setposition(f,offset+other)
+ local mapping = { }
+ local count = readulong(f)
+ for i=1,count do
+ mapping[readuint(f)] = readushort(f)
+ end
+ nofdone = nofdone + count
+ variants[selector] = mapping
+ end
+ end
+ return nofdone
+ else
+ return 0
+ end
+end
+
+local function checkcmap(f,fontdata,records,platform,encoding,format)
+ local data = records[platform]
+ if not data then
+ return 0
+ end
+ data = data[encoding]
+ if not data then
+ return 0
+ end
+ data = data[format]
+ if not data then
+ return 0
+ end
+ local reader = formatreaders[format]
+ if not reader then
+ return 0
+ end
+ local p = platforms[platform]
+ local e = encodings[p]
+ local n = reader(f,fontdata,data) or 0
+ report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n)
+ return n
+end
+
+function readers.cmap(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.cmap
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ local noftables = readushort(f)
+ local records = { }
+ local unicodecid = false
+ local variantcid = false
+ local variants = { }
+ local duplicates = fontdata.duplicates or { }
+ fontdata.duplicates = duplicates
+ for i=1,noftables do
+ local platform = readushort(f)
+ local encoding = readushort(f)
+ local offset = readulong(f)
+ local record = records[platform]
+ if not record then
+ records[platform] = {
+ [encoding] = {
+ offsets = { offset },
+ formats = { },
+ }
+ }
+ else
+ local subtables = record[encoding]
+ if not subtables then
+ record[encoding] = {
+ offsets = { offset },
+ formats = { },
+ }
+ else
+ local offsets = subtables.offsets
+ offsets[#offsets+1] = offset
+ end
+ end
+ end
+ report("found cmaps:")
+ for platform, record in sortedhash(records) do
+ local p = platforms[platform]
+ local e = encodings[p]
+ local sp = supported[platform]
+ local ps = p or "?"
+ if sp then
+ report(" platform %i: %s",platform,ps)
+ else
+ report(" platform %i: %s (unsupported)",platform,ps)
+ end
+ for encoding, subtables in sortedhash(record) do
+ local se = sp and sp[encoding]
+ local es = e and e[encoding] or "?"
+ if se then
+ report(" encoding %i: %s",encoding,es)
+ else
+ report(" encoding %i: %s (unsupported)",encoding,es)
+ end
+ local offsets = subtables.offsets
+ local formats = subtables.formats
+ for i=1,#offsets do
+ local offset = tableoffset + offsets[i]
+ setposition(f,offset)
+ formats[readushort(f)] = offset
+ end
+ record[encoding] = formats
+ local list = sortedkeys(formats)
+ for i=1,#list do
+ if not (se and se[list[i]]) then
+ list[i] = list[i] .. " (unsupported)"
+ end
+ end
+ report(" formats: % t",list)
+ end
+ end
+ --
+ local ok = false
+ for i=1,#sequence do
+ local sp, se, sf = unpack(sequence[i])
+ if checkcmap(f,fontdata,records,sp,se,sf) > 0 then
+ ok = true
+ end
+ end
+ if not ok then
+ report("no useable unicode cmap found")
+ end
+ --
+ fontdata.cidmaps = {
+ version = version,
+ noftables = noftables,
+ records = records,
+ }
+ else
+ fontdata.cidmaps = { }
+ end
+ end
+end
+
+-- The glyf table depends on the loca table. We have one entry to much in the locations table (the
+-- last one is a dummy) because we need to calculate the size of a glyph blob from the delta,
+-- although we not need it in our usage (yet). We can remove the locations table when we're done.
+
+function readers.loca(f,fontdata,specification)
+ if specification.glyphs then
+ reportskippedtable("loca")
+ end
+end
+
+function readers.glyf(f,fontdata,specification) -- part goes to cff module
+ if specification.glyphs then
+ reportskippedtable("glyf")
+ end
+end
+
+-- Here we have a table that we really need for later processing although a more advanced gpos table
+-- can also be available. Todo: we need a 'fake' lookup for this (analogue to ff).
+
+function readers.kern(f,fontdata,specification)
+ if specification.kerns then
+ local datatable = fontdata.tables.kern
+ if datatable then
+ setposition(f,datatable.offset)
+ local version = readushort(f)
+ local noftables = readushort(f)
+ for i=1,noftables do
+ local version = readushort(f)
+ local length = readushort(f)
+ local coverage = readushort(f)
+ -- bit 8-15 of coverage: format 0 or 2
+ local format = bit32.rshift(coverage,8) -- is this ok?
+ if format == 0 then
+ local nofpairs = readushort(f)
+ local searchrange = readushort(f)
+ local entryselector = readushort(f)
+ local rangeshift = readushort(f)
+ local kerns = { }
+ local glyphs = fontdata.glyphs
+ for i=1,nofpairs do
+ local left = readushort(f)
+ local right = readushort(f)
+ local kern = readfword(f)
+ local glyph = glyphs[left]
+ local kerns = glyph.kerns
+ if kerns then
+ kerns[right] = kern
+ else
+ glyph.kerns = { [right] = kern }
+ end
+ end
+ elseif format == 2 then
+ report("todo: kern classes")
+ else
+ report("todo: kerns")
+ end
+ end
+ end
+ end
+end
+
+function readers.gdef(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("gdef")
+ end
+end
+
+function readers.gsub(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("gsub")
+ end
+end
+
+function readers.gpos(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("gpos")
+ end
+end
+
+function readers.math(f,fontdata,specification)
+ if specification.glyphs then
+ reportskippedtable("math")
+ end
+end
+
+-- Goodie. A sequence instead of segments costs a bit more memory, some 300K on a
+-- dejavu serif and about the same on a pagella regular.
+
+local function packoutlines(data,makesequence)
+ local subfonts = data.subfonts
+ if subfonts then
+ for i=1,#subfonts do
+ packoutlines(subfonts[i],makesequence)
+ end
+ return
+ end
+ local common = data.segments
+ if common then
+ return
+ end
+ local glyphs = data.glyphs
+ if not glyphs then
+ return
+ end
+ if makesequence then
+ for index=1,#glyphs do
+ local glyph = glyphs[index]
+ local segments = glyph.segments
+ if segments then
+ local sequence = { }
+ local nofsequence = 0
+ for i=1,#segments do
+ local segment = segments[i]
+ local nofsegment = #segment
+ nofsequence = nofsequence + 1
+ sequence[nofsequence] = segment[nofsegment]
+ for i=1,nofsegment-1 do
+ nofsequence = nofsequence + 1
+ sequence[nofsequence] = segment[i]
+ end
+ end
+ glyph.sequence = sequence
+ glyph.segments = nil
+ end
+ end
+ else
+ local hash = { }
+ local common = { }
+ local reverse = { }
+ local last = 0
+ for index=1,#glyphs do
+ local segments = glyphs[index].segments
+ if segments then
+ for i=1,#segments do
+ local h = concat(segments[i]," ")
+ hash[h] = (hash[h] or 0) + 1
+ end
+ end
+ end
+ for index=1,#glyphs do
+ local segments = glyphs[index].segments
+ if segments then
+ for i=1,#segments do
+ local segment = segments[i]
+ local h = concat(segment," ")
+ if hash[h] > 1 then -- minimal one shared in order to hash
+ local idx = reverse[h]
+ if not idx then
+ last = last + 1
+ reverse[h] = last
+ common[last] = segment
+ idx = last
+ end
+ segments[i] = idx
+ end
+ end
+ end
+ end
+ if last > 0 then
+ data.segments = common
+ end
+ end
+end
+
+local function unpackoutlines(data)
+ local subfonts = data.subfonts
+ if subfonts then
+ for i=1,#subfonts do
+ unpackoutlines(subfonts[i])
+ end
+ return
+ end
+ local common = data.segments
+ if not common then
+ return
+ end
+ local glyphs = data.glyphs
+ if not glyphs then
+ return
+ end
+ for index=1,#glyphs do
+ local segments = glyphs[index].segments
+ if segments then
+ for i=1,#segments do
+ local c = common[segments[i]]
+ if c then
+ segments[i] = c
+ end
+ end
+ end
+ end
+ data.segments = nil
+end
+
+otf.packoutlines = packoutlines
+otf.unpackoutlines = unpackoutlines
+
+-- Now comes the loader. The order of reading these matters as we need to know
+-- some properties in order to read following tables. When details is true we also
+-- initialize the glyphs data.
+
+local function getinfo(maindata,sub,platformnames,rawfamilynames)
+ local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata
+ local names = fontdata.names
+ local info = nil
+ if names then
+ local metrics = fontdata.windowsmetrics or { }
+ local postscript = fontdata.postscript or { }
+ local fontheader = fontdata.fontheader or { }
+ local cffinfo = fontdata.cffinfo or { }
+ local filename = fontdata.filename
+ local weight = getname(fontdata,"weight") or cffinfo.weight or metrics.weight
+ local width = getname(fontdata,"width") or cffinfo.width or metrics.width
+ local fontname = getname(fontdata,"postscriptname")
+ local fullname = getname(fontdata,"fullname")
+ local family = getname(fontdata,"family")
+ local subfamily = getname(fontdata,"subfamily")
+ local familyname = getname(fontdata,"typographicfamily")
+ local subfamilyname = getname(fontdata,"typographicsubfamily")
+ local compatiblename = getname(fontdata,"compatiblefullname") -- kind of useless
+ if rawfamilynames then
+ -- for PG (for now, as i need to check / adapt context to catch a no-fallback case)
+ else
+ if not familyname then familyname = family end
+ if not subfamilyname then subfamilyname = subfamily end
+ end
+ info = { -- we inherit some inconsistencies/choices from ff
+ subfontindex = fontdata.subfontindex or sub or 0,
+ -- filename = filename,
+ version = getname(fontdata,"version"),
+ -- format = fontdata.format,
+ fontname = fontname,
+ fullname = fullname,
+ family = family,
+ subfamily = subfamily,
+ familyname = familyname,
+ subfamilyname = subfamilyname,
+ compatiblename = compatiblename,
+ weight = weight and lower(weight),
+ width = width and lower(width),
+ pfmweight = metrics.weightclass or 400, -- will become weightclass
+ pfmwidth = metrics.widthclass or 5, -- will become widthclass
+ panosewidth = metrics.panosewidth,
+ panoseweight = metrics.panoseweight,
+ italicangle = postscript.italicangle or 0,
+ units = fontheader.units or 0,
+ designsize = fontdata.designsize,
+ minsize = fontdata.minsize,
+ maxsize = fontdata.maxsize,
+ 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
+ ascender = metrics.typoascender,
+ descender = metrics.typodescender,
+ platformnames = platformnames and fontdata.platformnames or nil,
+ }
+ elseif n then
+ info = {
+ filename = fontdata.filename,
+ comment = "there is no info for subfont " .. n,
+ }
+ else
+ info = {
+ filename = fontdata.filename,
+ comment = "there is no info",
+ }
+ end
+ -- inspect(info)
+ return info
+end
+
+local function loadtables(f,specification,offset)
+ if offset then
+ setposition(f,offset)
+ end
+ local tables = { }
+ local basename = file.basename(specification.filename)
+ local filesize = specification.filesize
+ local filetime = specification.filetime
+ local fontdata = { -- some can/will go
+ filename = basename,
+ filesize = filesize,
+ filetime = filetime,
+ version = readstring(f,4),
+ noftables = readushort(f),
+ searchrange = readushort(f), -- not needed
+ entryselector = readushort(f), -- not needed
+ rangeshift = readushort(f), -- not needed
+ tables = tables,
+ }
+ for i=1,fontdata.noftables do
+ local tag = lower(stripstring(readstring(f,4)))
+ local checksum = readulong(f) -- not used
+ local offset = readulong(f)
+ local length = readulong(f)
+ if offset + length > filesize then
+ report("bad %a table in file %a",tag,basename)
+ end
+ tables[tag] = {
+ checksum = checksum,
+ offset = offset,
+ length = length,
+ }
+ end
+ if tables.cff then
+ fontdata.format = "opentype"
+ else
+ fontdata.format = "truetype"
+ end
+ return fontdata
+end
+
+local function prepareglyps(fontdata)
+ local glyphs = setmetatableindex(function(t,k)
+ local v = {
+ -- maybe more defaults
+ index = k,
+ }
+ t[k] = v
+ return v
+ end)
+ fontdata.glyphs = glyphs
+ fontdata.mapping = { }
+end
+
+local function readdata(f,offset,specification)
+ local fontdata = loadtables(f,specification,offset)
+ if specification.glyphs then
+ prepareglyps(fontdata)
+ end
+ --
+ readers["name"](f,fontdata,specification)
+ --
+ local askedname = specification.askedname
+ if askedname then
+ local fullname = getname(fontdata,"fullname") or ""
+ local cleanname = gsub(askedname,"[^a-zA-Z0-9]","")
+ local foundname = gsub(fullname,"[^a-zA-Z0-9]","")
+ if lower(cleanname) ~= lower(foundname) then
+ return -- keep searching
+ end
+ end
+ --
+ --
+ readers["os/2"](f,fontdata,specification)
+ readers["head"](f,fontdata,specification)
+ readers["maxp"](f,fontdata,specification)
+ readers["hhea"](f,fontdata,specification)
+ readers["hmtx"](f,fontdata,specification)
+ readers["post"](f,fontdata,specification)
+ readers["cff" ](f,fontdata,specification)
+ readers["cmap"](f,fontdata,specification)
+ readers["loca"](f,fontdata,specification)
+ readers["glyf"](f,fontdata,specification)
+ readers["kern"](f,fontdata,specification)
+ readers["gdef"](f,fontdata,specification)
+ readers["gsub"](f,fontdata,specification)
+ readers["gpos"](f,fontdata,specification)
+ readers["math"](f,fontdata,specification)
+ --
+ fontdata.locations = nil
+ fontdata.tables = nil
+ fontdata.cidmaps = nil
+ fontdata.dictionaries = nil
+ -- fontdata.cff = nil
+ return fontdata
+end
+
+local function loadfontdata(specification)
+ local filename = specification.filename
+ local fileattr = lfs.attributes(filename)
+ local filesize = fileattr and fileattr.size or 0
+ local filetime = fileattr and fileattr.modification or 0
+ local f = openfile(filename,true) -- zero based
+ if not f then
+ report("unable to open %a",filename)
+ elseif filesize == 0 then
+ report("empty file %a",filename)
+ closefile(f)
+ else
+ specification.filesize = filesize
+ specification.filetime = filetime
+ local version = readstring(f,4)
+ local fontdata = nil
+ if version == "OTTO" or version == "true" or version == "\0\1\0\0" then
+ 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
+ if subfont then -- a number of not
+ if subfont >= 1 and subfont <= nofsubfonts then
+ fontdata = readdata(f,offsets[subfont],specification)
+ else
+ report("no subfont %a in file %a",subfont,filename)
+ end
+ else
+ subfont = specification.subfont
+ if type(subfont) == "string" and subfont ~= "" then
+ specification.askedname = subfont
+ for i=1,nofsubfonts do
+ fontdata = readdata(f,offsets[i],specification)
+ if fontdata then
+ fontdata.subfontindex = i
+ report("subfont named %a has index %a",subfont,i)
+ break
+ end
+ end
+ if not fontdata then
+ report("no subfont named %a",subfont)
+ end
+ else
+ local subfonts = { }
+ fontdata = {
+ filename = filename,
+ filesize = filesize,
+ filetime = filetime,
+ version = version,
+ subfonts = subfonts,
+ ttcversion = ttcversion,
+ nofsubfonts = nofsubfonts,
+ }
+ for i=1,nofsubfonts do
+ subfonts[i] = readdata(f,offsets[i],specification)
+ end
+ end
+ end
+ else
+ report("unknown version %a in file %a",version,filename)
+ end
+ closefile(f)
+ return fontdata or { }
+ end
+end
+
+local function loadfont(specification,n)
+ if type(specification) == "string" then
+ specification = {
+ filename = specification,
+ info = true, -- always true (for now)
+ details = true,
+ glyphs = true,
+ shapes = true,
+ kerns = true,
+ globalkerns = true,
+ lookups = true,
+ -- true or number:
+ subfont = n or true,
+ tounicode = false,
+ }
+ end
+ -- if shapes only then
+ if specification.shapes or specification.lookups or specification.kerns then
+ specification.glyphs = true
+ end
+ if specification.glyphs then
+ specification.details = true
+ end
+ if specification.details then
+ specification.info = true -- not really used any more
+ end
+ if specification.platformnames then
+ specification.platformnames = true -- not really used any more
+ end
+ local function message(str)
+ report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
+ end
+ local ok, result = xpcall(loadfontdata,message,specification)
+ if ok then
+ return result
+ end
+end
+
+-- we need even less, but we can have a 'detail' variant
+
+function readers.loadshapes(filename,n)
+ local fontdata = loadfont {
+ filename = filename,
+ shapes = true,
+ subfont = n,
+ }
+ return fontdata and {
+ -- version = 0.123 -- todo
+ filename = filename,
+ format = fontdata.format,
+ glyphs = fontdata.glyphs,
+ units = fontdata.fontheader.units,
+ } or {
+ filename = filename,
+ format = "unknown",
+ glyphs = { },
+ units = 0,
+ }
+end
+
+function readers.loadfont(filename,n)
+ local fontdata = loadfont {
+ filename = filename,
+ glyphs = true,
+ shapes = false,
+ lookups = true,
+ -- kerns = true,
+ -- globalkerns = true, -- only for testing, e.g. cambria has different gpos and kern
+ subfont = n,
+ }
+ if fontdata then
+ --
+ return {
+ tableversion = tableversion,
+ creator = "context mkiv",
+ size = fontdata.filesize,
+ time = fontdata.filetime,
+ glyphs = fontdata.glyphs,
+ descriptions = fontdata.descriptions,
+ format = fontdata.format,
+ goodies = { },
+ metadata = getinfo(fontdata,n), -- no platformnames here !
+ properties = {
+ hasitalics = fontdata.hasitalics or false,
+ },
+ resources = {
+ -- filename = fontdata.filename,
+ filename = filename,
+ private = privateoffset,
+ duplicates = fontdata.duplicates or { },
+ features = fontdata.features or { }, -- we need to add these in the loader
+ sublookups = fontdata.sublookups or { }, -- we need to add these in the loader
+ marks = fontdata.marks or { }, -- we need to add these in the loader
+ markclasses = fontdata.markclasses or { }, -- we need to add these in the loader
+ marksets = fontdata.marksets or { }, -- we need to add these in the loader
+ sequences = fontdata.sequences or { }, -- we need to add these in the loader
+ variants = fontdata.variants, -- variant -> unicode -> glyph
+ version = getname(fontdata,"version"),
+ cidinfo = fontdata.cidinfo,
+ mathconstants = fontdata.mathconstants,
+ },
+ }
+ end
+end
+
+function readers.getinfo(filename,specification) -- string, nil|number|table
+ -- platformnames is optional and not used by context (a too unpredictable mess
+ -- that only add to the confusion) .. so it's only for checking things
+ local subfont = nil
+ local platformnames = false
+ local rawfamilynames = false
+ if type(specification) == "table" then
+ subfont = tonumber(specification.subfont)
+ platformnames = specification.platformnames
+ rawfamilynames = specification.rawfamilynames
+ else
+ subfont = tonumber(specification)
+ end
+ local fontdata = loadfont {
+ filename = filename,
+ details = true,
+ platformnames = platformnames,
+ -- rawfamilynames = rawfamilynames,
+ }
+ if fontdata then
+ local subfonts = fontdata.subfonts
+ if not subfonts then
+ return getinfo(fontdata,nil,platformnames,rawfamilynames)
+ elseif not subfont then
+ local info = { }
+ for i=1,#subfonts do
+ info[i] = getinfo(fontdata,i,platformnames,rawfamilynames)
+ end
+ return info
+ elseif subfont >= 1 and subfont <= #subfonts then
+ return getinfo(fontdata,subfont,platformnames,rawfamilynames)
+ else
+ return {
+ filename = filename,
+ comment = "there is no subfont " .. subfont .. " in this file"
+ }
+ end
+ else
+ return {
+ filename = filename,
+ comment = "the file cannot be opened for reading",
+ }
+ end
+end
+
+function readers.rehash(fontdata,hashmethod)
+ report("the %a helper is not yet implemented","rehash")
+end
+
+function readers.checkhash(fontdata)
+ report("the %a helper is not yet implemented","checkhash")
+end
+
+function readers.pack(fontdata,hashmethod)
+ report("the %a helper is not yet implemented","pack")
+end
+
+function readers.unpack(fontdata)
+ report("the %a helper is not yet implemented","unpack")
+end
+
+function readers.expand(fontdata)
+ report("the %a helper is not yet implemented","unpack")
+end
+
+function readers.compact(fontdata)
+ report("the %a helper is not yet implemented","compact")
+end
+
+-- plug in
+
+local extenders = { }
+
+function readers.registerextender(extender)
+ extenders[#extenders+1] = extender
+end
+
+function readers.extend(fontdata)
+ for i=1,#extenders do
+ local extender = extenders[i]
+ local name = extender.name or "unknown"
+ local action = extender.action
+ if action then
+ action(fontdata)
+ end
+ end
+end
+
+-- for now .. this will move to a context specific file
+
+if fonts.hashes then
+
+ local identifiers = fonts.hashes.identifiers
+ local loadshapes = readers.loadshapes
+
+ readers.version = 0.006
+ readers.cache = containers.define("fonts", "shapes", readers.version, true)
+
+ -- todo: loaders per format
+
+ local function load(filename,sub)
+ local base = file.basename(filename)
+ local name = file.removesuffix(base)
+ local kind = file.suffix(filename)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ local sub = tonumber(sub)
+ if size > 0 and (kind == "otf" or kind == "ttf" or kind == "tcc") then
+ local hash = containers.cleanname(base) -- including suffix
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ data = containers.read(readers.cache,hash)
+ if not data or data.time ~= time or data.size ~= size then
+ data = loadshapes(filename,sub)
+ if data then
+ data.size = size
+ data.format = data.format or (kind == "otf" and "opentype") or "truetype"
+ data.time = time
+ packoutlines(data)
+ containers.write(readers.cache,hash,data)
+ data = containers.read(readers.cache,hash) -- frees old mem
+ end
+ end
+ unpackoutlines(data)
+ else
+ data = {
+ filename = filename,
+ size = 0,
+ time = time,
+ format = "unknown",
+ units = 1000,
+ glyphs = { }
+ }
+ end
+ return data
+ end
+
+ fonts.hashes.shapes = table.setmetatableindex(function(t,k)
+ local d = identifiers[k]
+ local v = load(d.properties.filename,d.subindex)
+ t[k] = v
+ return v
+ end)
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua
new file mode 100644
index 00000000000..69118725842
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua
@@ -0,0 +1,3765 @@
+if not modules then modules = { } end modules ['font-ots'] = { -- sequences
+ 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",
+}
+
+-- to be checked: discrun doesn't seem to do something useful now (except run the
+-- check again) so if we need it again we'll do a zwnjrun or so
+
+-- beware, on my development machine we test a slightly a more optimized version
+
+-- assumptions:
+--
+-- cursives don't cross discretionaries
+-- marks precede bases
+--
+-- pitfalls:
+--
+-- when we append to a dics field we need to set the field in order to update tail
+--
+-- This is a version of font-otn.lua adapted to the new font loader code. It
+-- is a context version which can contain experimental code, but when we
+-- have serious patches we will backport to the font-otn files. The plain
+-- loader that ships with context also uses this now.
+--
+-- todo: looks like we have a leak somewhere (probably in ligatures)
+-- todo: copy attributes to disc
+-- todo: get rid of components, better use the tounicode entry if needed (at all)
+--
+-- 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 needed
+--
+-- not possible:
+--
+-- \discretionary {alpha-} {betagammadelta}
+-- {\discretionary {alphabeta-} {gammadelta}
+-- {\discretionary {alphabetagamma-} {delta}
+-- {alphabetagammadelta}}}
+
+--[[ldx--
+<p>This module is a bit more split up that I'd like but since we also want to test
+with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/>
+and discussion about improvements and functionality mostly happens on the
+<l n='context'/> mailing list.</p>
+
+<p>The specification of OpenType is kind of vague. Apart from a lack of a proper
+free specifications there's also the problem that Microsoft and Adobe
+may have their own interpretation of how and in what order to apply features.
+In general the Microsoft website has more detailed specifications and is a
+better reference. There is also some information in the FontForge help files.</p>
+
+<p>Because there is so much possible, fonts might contain bugs and/or be made to
+work with certain rederers. These may evolve over time which may have the side
+effect that suddenly fonts behave differently.</p>
+
+<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another
+implementation. Of course all errors are mine and of course the code can be
+improved. There are quite some optimizations going on here and processing speed
+is currently acceptable. Not all functions are implemented yet, often because I
+lack the fonts for testing. Many scripts are not yet supported either, but I will
+look into them as soon as <l n='context'/> users ask for it.</p>
+
+<p>The specification leaves room for interpretation. In case of doubt the microsoft
+implementation is the reference as it is the most complete one. As they deal with
+lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
+their suggestions help improve the code. I'm aware that not all border cases can be
+taken care of, unless we accept excessive runtime, and even then the interference
+with other mechanisms (like hyphenation) are not trivial.</p>
+
+<p>Glyphs are indexed not by unicode but in their own way. This is because there is no
+relationship with unicode at all, apart from the fact that a font might cover certain
+ranges of characters. One character can have multiple shapes. However, at the
+<l n='tex'/> end we use unicode so and all extra glyphs are mapped into a private
+space. This is needed because we need to access them and <l n='tex'/> has to include
+then in the output eventually.</p>
+
+<p>The initial data table is rather close to the open type specification and also not
+that different from the one produced by <l n='fontforge'/> but we uses hashes instead.
+In <l n='context'/> that table is packed (similar tables are shared) and cached on disk
+so that successive runs can use the optimized table (after loading the table is
+unpacked). The flattening code used later is a prelude to an even more compact table
+format (and as such it keeps evolving).</p>
+
+<p>This module is sparsely documented because it is a moving target. The table format
+of the reader changes and we experiment a lot with different methods for supporting
+features.</p>
+
+<p>As with the <l n='afm'/> code, we may decide to store more information in the
+<l n='otf'/> table.</p>
+
+<p>Incrementing the version number will force a re-cache. We jump the number by one
+when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that
+results in different tables.</p>
+--ldx]]--
+
+local type, next, tonumber = type, next, tonumber
+local random = math.random
+local formatters = string.formatters
+local insert = table.insert
+
+local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
+
+local registertracker = trackers.register
+local registerdirective = directives.register
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
+local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end)
+local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end)
+local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end)
+local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end)
+local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
+local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
+local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
+local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
+local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
+local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
+
+local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end)
+local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end)
+local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
+local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end)
+
+local quit_on_no_replacement = true -- maybe per font
+local zwnjruns = true
+local optimizekerns = true
+
+registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
+
+local report_direct = logs.reporter("fonts","otf direct")
+local report_subchain = logs.reporter("fonts","otf subchain")
+local report_chain = logs.reporter("fonts","otf chain")
+local report_process = logs.reporter("fonts","otf process")
+----- report_prepare = logs.reporter("fonts","otf prepare")
+local report_warning = logs.reporter("fonts","otf warning")
+local report_run = logs.reporter("fonts","otf run")
+local report_check = logs.reporter("fonts","otf check")
+
+registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
+registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
+registertracker("otf.actions","otf.replacements,otf.positions")
+registertracker("otf.injections","nodes.injections")
+
+registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local setnext = nuts.setnext
+local getprev = nuts.getprev
+local setprev = nuts.setprev
+local getboth = nuts.getboth
+local setboth = nuts.setboth
+local getid = nuts.getid
+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
+local setchar = nuts.setchar
+local getdisc = nuts.getdisc
+local setdisc = nuts.setdisc
+local setlink = nuts.setlink
+
+local ischar = nuts.is_char
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local delete_node = nuts.delete
+local remove_node = nuts.remove
+local copy_node = nuts.copy
+local copy_node_list = nuts.copy_list
+local find_node_tail = nuts.tail
+local flush_node_list = nuts.flush_list
+local free_node = nuts.free
+local end_of_math = nuts.end_of_math
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+
+local setmetatableindex = table.setmetatableindex
+
+local zwnj = 0x200C
+local zwj = 0x200D
+local wildcard = "*"
+local default = "dflt"
+
+local nodecodes = nodes.nodecodes
+local glyphcodes = nodes.glyphcodes
+local disccodes = nodes.disccodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+
+local discretionary_code = disccodes.discretionary
+local ligature_code = glyphcodes.ligature
+
+local privateattribute = attributes.private
+
+-- Something is messed up: we have two mark / ligature indices, one at the injection
+-- end and one here ... this is based on KE's patches but there is something fishy
+-- there as I'm pretty sure that for husayni we need some connection (as it's much
+-- more complex than an average font) but I need proper examples of all cases, not
+-- of only some.
+
+local a_state = privateattribute('state')
+
+local injections = nodes.injections
+local setmark = injections.setmark
+local setcursive = injections.setcursive
+local setkern = injections.setkern
+local setpair = injections.setpair
+local resetinjection = injections.reset
+local copyinjection = injections.copy
+local setligaindex = injections.setligaindex
+local getligaindex = injections.getligaindex
+
+local cursonce = true
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local onetimemessage = fonts.loggers.onetimemessage or function() end
+
+otf.defaultnodealternate = "none" -- first last
+
+-- We use a few global variables. The handler can be called nested but this assumes that the
+-- same font is used. Nested calls are normally not needed (only for devanagari).
+
+local tfmdata = false
+local characters = false
+local descriptions = false
+local marks = false
+local currentfont = false
+local factor = 0
+local threshold = 0
+
+local sweepnode = nil
+local sweepprev = nil
+local sweepnext = nil
+local sweephead = { }
+
+local notmatchpre = { }
+local notmatchpost = { }
+local notmatchreplace = { }
+
+local handlers = { }
+
+-- helper
+
+local function isspace(n)
+ if getid(n) == glue_code then
+ local w = getfield(n,"width")
+ if w >= threshold then
+ return 32
+ end
+ end
+end
+
+-- we use this for special testing and documentation
+
+local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
+local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
+local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_direct(...)
+end
+
+local function logwarning(...)
+ report_direct(...)
+end
+
+local f_unicode = formatters["%U"]
+local f_uniname = formatters["%U (%s)"]
+local f_unilist = formatters["% t (% t)"]
+
+local function gref(n) -- currently the same as in font-otb
+ if type(n) == "number" then
+ local description = descriptions[n]
+ local name = description and description.name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
+ end
+ elseif n then
+ local num, nam = { }, { }
+ for i=1,#n do
+ local ni = n[i]
+ if tonumber(ni) then -- later we will start at 2
+ local di = descriptions[ni]
+ num[i] = f_unicode(ni)
+ nam[i] = di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in node mode tracing>"
+ end
+end
+
+local function cref(dataset,sequence,index)
+ if not dataset then
+ return "no valid dataset"
+ elseif index then
+ return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
+ else
+ return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
+ end
+end
+
+local function pref(dataset,sequence)
+ return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name)
+end
+
+local function mref(rlmode)
+ if not rlmode or rlmode == 0 then
+ return "---"
+ elseif rlmode == -1 or rlmode == "+TRT" then
+ return "r2l"
+ else
+ return "l2r"
+ end
+end
+
+-- We can assume that languages that use marks are not hyphenated. We can also assume
+-- that at most one discretionary is present.
+
+-- We do need components in funny kerning mode but maybe I can better reconstruct then
+-- as we do have the font components info available; removing components makes the
+-- previous code much simpler. Also, later on copying and freeing becomes easier.
+-- However, for arabic we need to keep them around for the sake of mark placement
+-- and indices.
+
+local function copy_glyph(g) -- next and prev are untouched !
+ local components = getfield(g,"components")
+ if components then
+ setfield(g,"components",nil)
+ local n = copy_node(g)
+ copyinjection(n,g) -- we need to preserve the lig indices
+ setfield(g,"components",components)
+ return n
+ else
+ local n = copy_node(g)
+ copyinjection(n,g) -- we need to preserve the lig indices
+ return n
+ end
+end
+
+local function flattendisk(head,disc)
+ local _, _, replace, _, _, replacetail = getdisc(disc,true)
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head == disc then
+ local next = getnext(disc)
+ if replace then
+ if next then
+ setlink(replacetail,next)
+ end
+ return replace, replace
+ elseif next then
+ return next, next
+ else
+ return -- maybe warning
+ end
+ else
+ local prev, next = getboth(disc)
+ if replace then
+ if next then
+ setlink(replacetail,next)
+ end
+ setlink(prev,replace)
+ return head, replace
+ else
+ setlink(prev,next) -- checks for next anyway
+ return head, next
+ end
+ end
+end
+
+local function appenddisc(disc,list)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ local posthead = list
+ local replacehead = copy_node_list(list)
+ if post then
+ setlink(posttail,posthead)
+ else
+ post = phead
+ end
+ if replace then
+ setlink(replacetail,replacehead)
+ else
+ replace = rhead
+ end
+ setdisc(disc,pre,post,replace)
+end
+
+-- start is a mark and we need to keep that one
+
+local function markstoligature(head,start,stop,char)
+ if start == stop and getchar(start) == char then
+ return head, start
+ else
+ local prev = getprev(start)
+ local next = getnext(stop)
+ setprev(start,nil)
+ setnext(stop,nil)
+ local base = copy_glyph(start)
+ if head == start then
+ head = base
+ end
+ resetinjection(base)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
+ setfield(base,"components",start)
+ setlink(prev,base)
+ setlink(base,next)
+ return head, base
+ end
+end
+
+-- The next code is somewhat complicated by the fact that some fonts can have ligatures made
+-- from ligatures that themselves have marks. This was identified by Kai in for instance
+-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
+-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
+-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
+-- third component.
+
+local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
+ if getid(start) ~= glyph_code then -- and then get rid of all components
+ return 0
+ elseif getsubtype(start) == ligature_code then
+ local i = 0
+ local components = getfield(start,"components")
+ while components do
+ i = i + getcomponentindex(components)
+ components = getnext(components)
+ end
+ return i
+ elseif not marks[getchar(start)] then
+ return 1
+ else
+ return 0
+ end
+end
+
+local a_noligature = attributes.private("noligature")
+
+local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) -- brr head
+ if getattr(start,a_noligature) == 1 then
+ -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+ return head, start
+ end
+ if start == stop and getchar(start) == char then
+ resetinjection(start)
+ setchar(start,char)
+ return head, start
+ end
+ -- needs testing (side effects):
+ local components = getfield(start,"components")
+ if components then
+ -- we get a double free .. needs checking
+ -- flush_node_list(components)
+ end
+ --
+ local prev = getprev(start)
+ local next = getnext(stop)
+ local comp = start
+ setprev(start,nil)
+ setnext(stop,nil)
+ local base = copy_glyph(start)
+ if start == head then
+ head = base
+ end
+ resetinjection(base)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
+ setfield(base,"components",comp) -- start can have components ... do we need to flush?
+ if prev then
+ setnext(prev,base)
+ end
+ if next then
+ setprev(next,base)
+ end
+ setboth(base,prev,next)
+ if not discfound then
+ local deletemarks = markflag ~= "mark"
+ local components = start
+ local baseindex = 0
+ local componentindex = 0
+ local head = base
+ local current = base
+ -- first we loop over the glyphs in start .. stop
+ while start do
+ local char = getchar(start)
+ if not marks[char] then
+ baseindex = baseindex + componentindex
+ componentindex = getcomponentindex(start)
+ elseif not deletemarks then -- quite fishy
+ setligaindex(start,baseindex + getligaindex(start,componentindex))
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
+ end
+ local n = copy_node(start)
+ copyinjection(n,start)
+ head, current = insert_node_after(head,current,n) -- unlikely that mark has components
+ elseif trace_marks then
+ logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char))
+ end
+ start = getnext(start)
+ end
+ -- we can have one accent as part of a lookup and another following
+ -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
+ local start = getnext(current)
+ while start do
+ local char = ischar(start)
+ if char then
+ if marks[char] then
+ setligaindex(start,baseindex + getligaindex(start,componentindex))
+ if trace_marks then
+ logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
+ end
+ start = getnext(start)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ else
+ -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
+ local discprev, discnext = getboth(discfound)
+ if discprev and discnext then
+ -- we assume normalization in context, and don't care about generic ... especially
+ -- \- can give problems as there we can have a negative char but that won't match
+ -- anyway
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
+ if not replace then -- todo: signal simple hyphen
+ local prev = getprev(base)
+ local copied = copy_node_list(comp)
+ setprev(discnext,nil) -- also blocks funny assignments
+ setnext(discprev,nil) -- also blocks funny assignments
+ if pre then
+ setlink(discprev,pre)
+ end
+ pre = comp
+ if post then
+ setlink(posttail,discnext)
+ setprev(post,nil)
+ else
+ post = discnext
+ end
+ setlink(prev,discfound)
+ setlink(discfound,next)
+ setboth(base,nil,nil)
+ setfield(base,"components",copied)
+ setdisc(discfound,pre,post,base,discretionary_code)
+ base = prev -- restart
+ end
+ end
+ end
+ return head, base
+end
+
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples = #multiple
+ if nofmultiples > 0 then
+ resetinjection(start)
+ setchar(start,multiple[1])
+ if nofmultiples > 1 then
+ local sn = getnext(start)
+ for k=2,nofmultiples do
+-- untested:
+--
+-- while ignoremarks and marks[getchar(sn)] then
+-- local sn = getnext(sn)
+-- end
+ local n = copy_node(start) -- ignore components
+ resetinjection(n)
+ setchar(n,multiple[k])
+ insert_node_after(head,start,n)
+ start = n
+ end
+ end
+ return head, start, true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head, start, false
+ end
+end
+
+local function get_alternative_glyph(start,alternatives,value)
+ local n = #alternatives
+ if value == "random" then
+ local r = random(1,n)
+ return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
+ elseif value == "first" then
+ return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1)
+ elseif value == "last" then
+ return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n)
+ end
+ value = value == true and 1 or tonumber(value)
+ if type(value) ~= "number" then
+ return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
+ end
+ -- local a = alternatives[value]
+ -- if a then
+ -- -- some kind of hash
+ -- return a, trace_alternatives and formatters["value %a, taking %a"](value,a)
+ -- end
+ if value > n then
+ local defaultalt = otf.defaultnodealternate
+ if defaultalt == "first" then
+ return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
+ elseif defaultalt == "last" then
+ return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n)
+ else
+ return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
+ end
+ elseif value == 0 then
+ return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
+ elseif value < 1 then
+ return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
+ else
+ return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value)
+ end
+end
+
+-- handlers
+
+function handlers.gsub_single(head,start,dataset,sequence,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(dataset,sequence),gref(getchar(start)),gref(replacement))
+ end
+ resetinjection(start)
+ setchar(start,replacement)
+ return head, start, true
+end
+
+function handlers.gsub_alternate(head,start,dataset,sequence,alternative)
+ local kind = dataset[4]
+ local what = dataset[1]
+ local value = what == true and tfmdata.shared.features[kind] or what
+ local choice, comment = get_alternative_glyph(start,alternative,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %a to %s, %s",pref(dataset,sequence),gref(getchar(start)),gref(choice),comment)
+ end
+ resetinjection(start)
+ setchar(start,choice)
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
+ end
+ end
+ return head, start, true
+end
+
+function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
+ if trace_multiples then
+ logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
+ end
+ return multiple_glyphs(head,start,multiple,sequence.flags[1])
+end
+
+function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
+ local current = getnext(start)
+ if not current then
+ return head, start, false, nil
+ end
+ local stop = nil
+ local startchar = getchar(start)
+ if marks[startchar] then
+ while current do
+ local char = ischar(current,currentfont)
+ if char then
+ local lg = ligature[char]
+ if lg then
+ stop = current
+ ligature = lg
+ current = getnext(current)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if stop then
+ local lig = ligature.ligature
+ if lig then
+ if trace_ligatures then
+ local stopchar = getchar(stop)
+ head, start = markstoligature(head,start,stop,lig)
+ logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start)))
+ else
+ head, start = markstoligature(head,start,stop,lig)
+ end
+ return head, start, true, false
+ else
+ -- ok, goto next lookup
+ end
+ end
+ else
+ local skipmark = sequence.flags[1]
+ local discfound = false
+ local lastdisc = nil
+ while current do
+ local char, id = ischar(current,currentfont)
+ if char then
+ if skipmark and marks[char] then
+ current = getnext(current)
+ else -- ligature is a tree
+ local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
+ if lg then
+ if not discfound and lastdisc then
+ discfound = lastdisc
+ lastdisc = nil
+ end
+ stop = current -- needed for fake so outside then
+ ligature = lg
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ elseif char == false then
+ -- kind of weird
+ break
+ elseif id == disc_code then
+ -- tricky .. we also need to do pre here
+ local replace = getfield(current,"replace")
+ 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
+ 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)
+ else
+ break
+ 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,skipmark,discfound)
+ 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,skipmark,discfound)
+ end
+ else
+ -- weird but happens (in some arabic font)
+ resetinjection(start)
+ setchar(start,lig)
+ if trace_ligatures then
+ 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
+ else
+ -- weird but happens, pseudo ligatures ... just the components
+ end
+ end
+ return head, start, false, discfound
+end
+
+function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,step,i,injection)
+ local startchar = getchar(start)
+ if step.format == "pair" then
+ local dx, dy, w, h = setpair(start,factor,rlmode,sequence.flags[4],kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(dataset,sequence),gref(startchar),dx,dy,w,h)
+ end
+ else
+ -- needs checking .. maybe no kerns format for single
+ local k = setkern(start,factor,rlmode,kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(startchar),k)
+ end
+ end
+ return head, start, false
+end
+
+function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,injection)
+ local snext = getnext(start)
+ if not snext then
+ return head, start, false
+ else
+ local prev = start
+ local done = false
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if nextchar then
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ elseif not krn then
+ break
+ elseif step.format == "pair" then
+ local a, b = krn[1], krn[2]
+ if optimizekerns then
+ -- this permits a mixed table, but we could also decide to optimize this
+ -- in the loader and use format 'kern'
+ if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
+ local k = setkern(snext,factor,rlmode,a[3],injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
+ end
+ done = true
+ break
+ end
+ end
+ if a and #a > 0 then
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ end
+ end
+ if b and #b > 0 then
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ if trace_kerns then
+ local startchar = getchar(snext)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ end
+ end
+ done = true
+ break
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
+ end
+ done = true
+ break
+ else -- can't happen
+ break
+ end
+ else
+ break
+ end
+ end
+ return head, start, done
+ end
+end
+
+--[[ldx--
+<p>We get hits on a mark, but we're not sure if the it has to be applied so
+we need to explicitly test for basechar, baselig and basemark entries.</p>
+--ldx]]--
+
+function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [start=mark]
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while base do
+ base = getprev(base)
+ if base then
+ basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
+ end
+ end
+ end
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ elseif trace_bugs then
+ logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1)
+ end
+ elseif trace_bugs then
+ logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlmode)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [optional marks] [start=mark]
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while base do
+ base = getprev(base)
+ if base then
+ basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
+ end
+ end
+ end
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local index = getligaindex(start)
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
+ if trace_marks then
+ logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
+ else
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
+ end
+ end
+ end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local base = getprev(start) -- [glyph] [basemark] [start=mark]
+ local slc = getligaindex(start)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = getligaindex(base)
+ if blc and blc ~= slc then
+ base = getprev(base)
+ else
+ break
+ end
+ end
+ end
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then -- subtype test can go
+ local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
+ if ba then
+ local ma = markanchors[2]
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i) -- to be checked
+ local done = false
+ local startchar = getchar(start)
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
+ end
+ else
+ local nxt = getnext(start)
+ while not done and nxt do
+ local nextchar = ischar(nxt,currentfont)
+ if not nextchar then
+ break
+ elseif marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = getnext(nxt)
+ else
+ local exit = exitanchors[3]
+ if exit then
+ local entry = exitanchors[1][nextchar]
+ if entry then
+ entry = entry[2]
+ if entry then
+ local dx, dy, bound = setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
+ end
+ done = true
+ end
+ end
+ end
+ break
+ end
+ end
+ end
+ return head, start, done
+end
+
+--[[ldx--
+<p>I will implement multiple chain replacements once I run into a font that uses
+it. It's not that complex to handle.</p>
+--ldx]]--
+
+local chainprocs = { }
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_subchain(...)
+end
+
+local logwarning = report_subchain
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_chain(...)
+end
+
+local logwarning = report_chain
+
+-- We could share functions but that would lead to extra function calls with many
+-- arguments, redundant tests and confusing messages.
+
+-- The reversesub is a special case, which is why we need to store the replacements
+-- in a bit weird way. There is no lookup and the replacement comes from the lookup
+-- itself. It is meant mostly for dealing with Urdu.
+
+local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode)
+ local char = getchar(start)
+ local replacement = replacements[char]
+ if replacement then
+ if trace_singles then
+ logprocess("%s: single reverse replacement of %s by %s",cref(dataset,sequence),gref(char),gref(replacement))
+ end
+ resetinjection(start)
+ setchar(start,replacement)
+ return head, start, true
+ else
+ return head, start, false
+ end
+end
+
+
+chainprocs.reversesub = reversesub
+
+--[[ldx--
+<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be
+applied: single, alternate, multiple or ligature where ligature can be an invalid
+one in the sense that it will replace multiple by one but not neccessary one that
+looks like the combination (i.e. it is the counterpart of multiple then). For
+example, the following is valid:</p>
+
+<typing>
+<line>xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx</line>
+</typing>
+
+<p>Therefore we we don't really do the replacement here already unless we have the
+single lookup case. The efficiency of the replacements can be improved by deleting
+as less as needed but that would also make the code even more messy.</p>
+--ldx]]--
+
+--[[ldx--
+<p>Here we replace start by a single variant.</p>
+--ldx]]--
+
+-- To be done (example needed): what if > 1 steps
+
+-- this is messy: do we need this disc checking also in alternaties?
+
+local function reportmoresteps(dataset,sequence)
+ logwarning("%s: more than 1 step",cref(dataset,sequence))
+end
+
+function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,chainindex)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local current = start
+ while current do
+ local currentchar = ischar(current)
+ if currentchar then
+ local replacement = steps[1].coverage[currentchar]
+ if not replacement or replacement == "" then
+ if trace_bugs then
+ logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar))
+ end
+ else
+ if trace_singles then
+ logprocess("%s: replacing single %s by %s",cref(dataset,sequence,chainindex),gref(currentchar),gref(replacement))
+ end
+ resetinjection(current)
+ setchar(current,replacement)
+ end
+ return head, start, true
+ elseif currentchar == false then
+ -- can't happen
+ break
+ elseif current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>Here we replace start by a sequence of new glyphs.</p>
+--ldx]]--
+
+function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local startchar = getchar(start)
+ local replacement = steps[1].coverage[startchar]
+ if not replacement or replacement == "" then
+ if trace_bugs then
+ logwarning("%s: no multiple for %s",cref(dataset,sequence),gref(startchar))
+ end
+ else
+ 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,currentlookup.flags[1]) -- not sequence.flags?
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
+--ldx]]--
+
+-- char_1 mark_1 -> char_x mark_1 (ignore marks)
+-- char_1 mark_1 -> char_x
+
+-- to be checked: do we always have just one glyph?
+-- we can also have alternates for marks
+-- marks come last anyway
+-- are there cases where we need to delete the mark
+
+function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlookup)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local kind = dataset[4]
+ local what = dataset[1]
+ local value = what == true and tfmdata.shared.features[kind] or what
+ local current = start
+ while current do
+ local currentchar = ischar(current)
+ if currentchar then
+ local alternatives = steps[1].coverage[currentchar]
+ if alternatives then
+ local choice, comment = get_alternative_glyph(current,alternatives,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %a to %s, %s",cref(dataset,sequence),gref(char),choice,gref(choice),comment)
+ end
+ resetinjection(start)
+ setchar(start,choice)
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %a for %s, %s",cref(dataset,sequence),value,gref(char),comment)
+ end
+ end
+ end
+ return head, start, true
+ elseif currentchar == false then
+ -- can't happen
+ break
+ elseif current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ return head, start, false
+end
+
+--[[ldx--
+<p>When we replace ligatures we use a helper that handles the marks. I might change
+this function (move code inline and handle the marks by a separate function). We
+assume rather stupid ligatures (no complex disc nodes).</p>
+--ldx]]--
+
+function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup,chainindex)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local startchar = getchar(start)
+ local ligatures = steps[1].coverage[startchar]
+ if not ligatures then
+ if trace_bugs then
+ logwarning("%s: no ligatures starting with %s",cref(dataset,sequence,chainindex),gref(startchar))
+ end
+ else
+ local current = getnext(start)
+ local discfound = false
+ local last = stop
+ local nofreplacements = 1
+ local skipmark = currentlookup.flags[1] -- sequence.flags?
+ while current do
+ -- todo: ischar ... can there really be disc nodes here?
+ local id = getid(current)
+ if id == disc_code then
+ if not discfound then
+ discfound = current
+ end
+ if current == stop then
+ break -- okay? or before the disc
+ else
+ current = getnext(current)
+ end
+ else
+ local schar = getchar(current)
+ if skipmark and marks[schar] then -- marks
+ -- if current == stop then -- maybe add this
+ -- break
+ -- else
+ current = getnext(current)
+ -- end
+ else
+ local lg = ligatures[schar]
+ if lg then
+ ligatures = lg
+ last = current
+ nofreplacements = nofreplacements + 1
+ if current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+ local ligature = ligatures.ligature
+ if ligature then
+ if chainindex then
+ stop = last
+ end
+ if trace_ligatures then
+ if start == stop then
+ logprocess("%s: replacing character %s by ligature %s case 3",cref(dataset,sequence,chainindex),gref(startchar),gref(ligature))
+ else
+ logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)),gref(ligature))
+ end
+ end
+ head, start = toligature(head,start,stop,ligature,dataset,sequence,skipmark,discfound)
+ return head, start, true, nofreplacements, discfound
+ elseif trace_bugs then
+ if start == stop then
+ logwarning("%s: replacing character %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar))
+ else
+ logwarning("%s: replacing character %s upto %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)))
+ end
+ end
+ end
+ return head, start, false, 0, false
+end
+
+function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local startchar = getchar(start)
+ local step = steps[1]
+ local kerns = step.coverage[startchar]
+ if not kerns then
+ -- skip
+ elseif step.format == "pair" then
+ local dx, dy, w, h = setpair(start,factor,rlmode,sequence.flags[4],kerns) -- currentlookup.flags ?
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),dx,dy,w,h)
+ end
+ else -- needs checking .. maybe no kerns format for single
+ local k = setkern(start,factor,rlmode,kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) -- todo: injections ?
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local snext = getnext(start)
+ if snext then
+ local startchar = getchar(start)
+ local step = steps[1]
+ local kerns = step.coverage[startchar] -- always 1 step
+ if kerns then
+ local prev = start
+ local done = false
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if not nextchar then
+ break
+ end
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ elseif not krn then
+ break
+ elseif step.format == "pair" then
+ local a, b = krn[1], krn[2]
+ if optimizekerns then
+ -- this permits a mixed table, but we could also decide to optimize this
+ -- in the loader and use format 'kern'
+ if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
+ local k = setkern(snext,factor,rlmode,a[3],"injections")
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
+ end
+ done = true
+ break
+ end
+ end
+ if a and #a > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,"injections") -- currentlookups flags?
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,"injections")
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ done = true
+ break
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done = true
+ break
+ else
+ break
+ end
+ end
+ return head, start, done
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local markanchors = steps[1].coverage[markchar] -- always 1 step
+ if markanchors then
+ local base = getprev(start) -- [glyph] [start=mark]
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while base do
+ base = getprev(base)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
+ end
+ end
+ end
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local markanchors = steps[1].coverage[markchar] -- always 1 step
+ if markanchors then
+ local base = getprev(start) -- [glyph] [optional marks] [start=mark]
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while base do
+ base = getprev(base)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2)
+ end
+ return head, start, false
+ end
+ end
+ end
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local index = getligaindex(start)
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1)
+ end
+ elseif trace_bugs then
+ logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2)
+ end
+ elseif trace_bugs then
+ logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s, mark %s is no mark",cref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local markchar = getchar(start)
+ if marks[markchar] then
+ local markanchors = steps[1].coverage[markchar] -- always 1 step
+ if markanchors then
+ local base = getprev(start) -- [glyph] [basemark] [start=mark]
+ local slc = getligaindex(start)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = getligaindex(base)
+ if blc and blc ~= slc then
+ base = getprev(base)
+ else
+ break
+ end
+ end
+ end
+ if base then -- subtype test can go
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1)
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar))
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ local startchar = getchar(start)
+ local exitanchors = steps[1].coverage[startchar] -- always 1 step
+ if exitanchors then
+ local done = false
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
+ end
+ else
+ local nxt = getnext(start)
+ while not done and nxt do
+ local nextchar = ischar(nxt,currentfont)
+ if not nextchar then
+ break
+ elseif marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = getnext(nxt)
+ else
+ local exit = exitanchors[3]
+ if exit then
+ local entry = exitanchors[1][nextchar]
+ if entry then
+ entry = entry[2]
+ if entry then
+ local dx, dy, bound = setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
+ end
+ done = true
+ break
+ end
+ end
+ elseif trace_bugs then
+ onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
+ end
+ break
+ end
+ end
+ end
+ return head, start, done
+ else
+ if trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
+ end
+ return head, start, false
+ end
+end
+
+-- what pointer to return, spec says stop
+-- to be discussed ... is bidi changer a space?
+-- elseif char == zwnj and sequence[n][32] then -- brrr
+
+local function show_skip(dataset,sequence,char,ck,class)
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2])
+end
+
+-- A previous version had disc collapsing code in the (single sub) handler plus some
+-- checking in the main loop, but that left the pre/post sequences undone. The best
+-- solution is to add some checking there and backtrack when a replace/post matches
+-- but it takes a bit of work to figure out an efficient way (this is what the sweep*
+-- names refer to). I might look into that variant one day again as it can replace
+-- some other code too. In that approach we can have a special version for gub and pos
+-- which gains some speed. This method does the test and passes info to the handlers
+-- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
+-- main loop which also makes code elsewhere simpler (i.e. no need for the other special
+-- runners and disc code in ligature building). I also experimented with pushing preceding
+-- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
+-- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
+--
+-- In the meantime Kai had moved the code from the single chain into a more general handler
+-- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
+-- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
+-- complex approach is meant for fonts that implement (for instance) ligatures by character
+-- replacement which to some extend is not that suitable for hyphenation. I also use some
+-- helpers. This method passes some states but reparses the list. There is room for a bit of
+-- speed up but that will be done in the context version. (In fact a partial rewrite of all
+-- code can bring some more efficientry.)
+--
+-- I didn't test it with extremes but successive disc nodes still can give issues but in
+-- order to handle that we need more complex code which also slows down even more. The main
+-- loop variant could deal with that: test, collapse, backtrack.
+
+local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
+
+ if not start then
+ return head, start, false
+ end
+
+ local startishead = start == head
+ local seq = ck[3]
+ local f = ck[4]
+ local l = ck[5]
+ local s = #seq
+ local done = false
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local sweepoverflow = false
+ local checkdisc = getprev(head) -- hm bad name head
+ local keepdisc = not sweepnode
+ local lookaheaddisc = nil
+ local backtrackdisc = nil
+ local current = start
+ local last = start
+ local prev = getprev(start)
+
+ -- fishy: so we can overflow and then go on in the sweep?
+
+ local i = f
+ while i <= l do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i <= l do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ last = current
+ current = getnext(c)
+ else
+ head, current = flattendisk(head,current)
+ end
+ else
+ last = current
+ current = getnext(current)
+ end
+ if current then
+ -- go on
+ elseif sweepoverflow then
+ -- we already are folling up on sweepnode
+ break
+ elseif sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ sweepoverflow = true
+ else
+ break
+ end
+ else
+ break -- added
+ end
+ end
+
+ if sweepoverflow then
+ local prev = current and getprev(current)
+ if not current or prev ~= sweepnode then
+ local head = getnext(sweepnode)
+ local tail = nil
+ if prev then
+ tail = prev
+ setprev(current,sweepnode)
+ else
+ tail = find_node_tail(head)
+ end
+ setnext(sweepnode,current)
+ setprev(head,nil)
+ setnext(tail,nil)
+ appenddisc(sweepnode,head)
+ end
+ end
+
+ if l < s then
+ local i = l
+ local t = sweeptype == "post" or sweeptype == "replace"
+ while current and i < s do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(c,"replace")
+ while replace and i < s do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ current = getnext(current)
+ elseif notmatchpre[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ else
+ current = getnext(current) -- HH
+ end
+ else
+ current = getnext(current)
+ end
+ if not current and t then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ end
+ end
+ end
+ end
+
+ if f > 1 then
+ local current = prev
+ local i = f
+ local t = sweeptype == "pre" or sweeptype == "replace"
+ if not current and t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ while current and i > 1 do -- missing getprev added / moved outside
+ local id = getid(current)
+ if id == glyph_code then
+ i = i - 1
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpost[current] ~= notmatchreplace[current] then
+ backtrackdisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i > 1 do
+ if getid(replace) == glyph_code then
+ i = i - 1
+ end
+ replace = getnext(replace)
+ end
+ elseif notmatchpost[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ end
+ end
+ current = getprev(current)
+ if t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ end
+ end
+
+ local ok = false
+ if lookaheaddisc then
+
+ local cf = start
+ local cl = getprev(lookaheaddisc)
+ local cprev = getprev(start)
+ local insertedmarks = 0
+
+ while cprev do
+ local char = ischar(cf,currentfont)
+ if char and marks[char] then
+ insertedmarks = insertedmarks + 1
+ cf = cprev
+ startishead = cf == head
+ cprev = getprev(cprev)
+ else
+ break
+ end
+ end
+
+ setprev(lookaheaddisc,cprev)
+ if cprev then
+ setnext(cprev,lookaheaddisc)
+ end
+ setprev(cf,nil)
+ setnext(cl,nil)
+ if startishead then
+ head = lookaheaddisc
+ end
+ local pre, post, replace = getdisc(lookaheaddisc)
+ local new = copy_node_list(cf)
+ local cnew = new
+ for i=1,insertedmarks do
+ cnew = getnext(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
+ end
+ if pre then
+ setlink(cl,pre)
+ end
+ if replace then
+ local tail = find_node_tail(new)
+ setlink(tail,replace)
+ end
+ setdisc(lookaheaddisc,cf,post,new)
+ start = getprev(lookaheaddisc)
+ sweephead[cf] = getnext(clast)
+ sweephead[new] = getnext(last)
+
+ elseif backtrackdisc then
+
+ local cf = getnext(backtrackdisc)
+ local cl = start
+ local cnext = getnext(start)
+ local insertedmarks = 0
+
+ while cnext do
+ local char = ischar(cnext,currentfont)
+ if char and marks[char] then
+ insertedmarks = insertedmarks + 1
+ cl = cnext
+ cnext = getnext(cnext)
+ else
+ break
+ end
+ end
+ if cnext then
+ setprev(cnext,backtrackdisc)
+ end
+ setnext(backtrackdisc,cnext)
+ setprev(cf,nil)
+ setnext(cl,nil)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(backtrackdisc,true)
+ local new = copy_node_list(cf)
+ local cnew = find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew = getprev(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
+ end
+ if post then
+ setlink(posttail,cf)
+ else
+ post = cf
+ end
+ if replace then
+ setlink(replacetail,new)
+ else
+ replace = new
+ end
+ setdisc(backtrackdisc,pre,post,replace)
+ start = getprev(backtrackdisc)
+ sweephead[post] = getnext(clast)
+ sweephead[replace] = getnext(last)
+
+ else
+
+ head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k)
+
+ end
+
+ return head, start, ok
+end
+
+-- helpers from elsewhere
+
+-- local function currentmatch(current,n,l)
+-- while current do
+-- if getid(current) ~= glyph_code then
+-- return false
+-- elseif seq[n][getchar(current)] then
+-- n = n + 1
+-- current = getnext(current)
+-- if not current then
+-- return true, n, current
+-- elseif n > l then
+-- -- match = false
+-- return true, n, current
+-- end
+-- else
+-- return false
+-- end
+-- end
+-- end
+--
+-- local function aftermatch(current,n,l)
+-- while current do
+-- if getid(current) ~= glyph_code then
+-- return false
+-- elseif seq[n][getchar(current)] then
+-- n = n + 1
+-- current = getnext(current)
+-- if not current then
+-- return true, n, current
+-- elseif n > l then
+-- -- match = false
+-- return true, n, current
+-- end
+-- else
+-- return false
+-- end
+-- end
+-- end
+--
+-- local function beforematch(current,n)
+-- local finish = getprev(current)
+-- local current = find_node_tail(current)
+-- while current do
+-- if getid(current) ~= glyph_code then
+-- return false
+-- elseif seq[n][getchar(current)] then
+-- n = n - 1
+-- current = getprev(current)
+-- if not current or current == finish then
+-- return true, n, current
+-- elseif n < 1 then
+-- -- match = false
+-- return true, n, current
+-- end
+-- else
+-- return false
+-- end
+-- end
+-- end
+
+local noflags = { false, false, false, false }
+
+local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local currentfont = currentfont
+ local diskseen = false
+ local checkdisc = getprev(head)
+ local flags = sequence.flags or noflags
+ local done = false
+ local skipmark = flags[1]
+ local skipligature = flags[2]
+ local skipbase = flags[3]
+ local markclass = sequence.markclass
+ local skipped = false
+ for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
+ local match = true
+ local current = start
+ local last = start
+ local ck = contexts[k]
+ local seq = ck[3]
+ local s = #seq
+ -- f..l = mid string
+ if s == 1 then
+ -- never happens
+ local char = ischar(current,currentfont)
+ if char then
+ match = seq[1][char]
+ end
+ else
+ -- maybe we need a better space check (maybe check for glue or category or combination)
+ -- we cannot optimize for n=2 because there can be disc nodes
+ local f = ck[4]
+ local l = ck[5]
+ -- current match
+ if f == 1 and f == l then -- current only
+ -- already a hit
+ -- match = true
+ else -- before/current/after | before/current | current/after
+ -- no need to test first hit (to be optimized)
+ if f == l then -- new, else last out of sync (f is > 1)
+ -- match = true
+ else
+ local discfound = nil
+ local n = f + 1
+ last = getnext(last)
+ while n <= l do
+ if not last and (sweeptype == "post" or sweeptype == "replace") then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
+ if last then
+ local char, id = ischar(last,currentfont)
+ if char then
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class or "base"
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ last = getnext(last)
+ elseif seq[n][char] then
+ if n < l then
+ last = getnext(last)
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ last = getnext(last)
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ elseif id == disc_code then
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre, post, replace = getdisc(last)
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > l then
+ break
+ end
+ else
+ notmatchpre[last] = true
+ break
+ end
+ end
+ if n <= l then
+ notmatchpre[last] = true
+ end
+ else
+ notmatchpre[last] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > l then
+ break
+ end
+ else
+ notmatchreplace[last] = true
+ match = not notmatchpre[last]
+ break
+ end
+ end
+ match = not notmatchpre[last]
+ end
+ last = getnext(last)
+ else
+ match = false
+ break
+ end
+ else
+ match = false
+ break
+ end
+ end
+ end
+ end
+ -- before
+ if match and f > 1 then
+ local prev = getprev(start)
+ if prev then
+ if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
+ prev = getprev(sweepnode)
+ -- sweeptype = nil
+ end
+ if prev then
+ local discfound = nil
+ local n = f - 1
+ while n >= 1 do
+ if prev then
+ local char, id = ischar(prev,currentfont)
+ if char then
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n -1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ prev = getprev(prev)
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
+ elseif id == disc_code then
+ -- the special case: f i where i becomes dottless i ..
+ diskseen = true
+ discfound = prev
+ notmatchpre[prev] = true
+ notmatchpost[prev] = nil
+ notmatchreplace[prev] = nil
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(prev,true)
+ if pre ~= start and post ~= start and replace ~= start then
+ if post then
+ local n = n
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n = n - 1
+ if posttail == post then
+ break
+ else
+ posttail = getprev(posttail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev] = true
+ break
+ end
+ end
+ if n >= 1 then
+ notmatchpost[prev] = true
+ end
+ else
+ notmatchpost[prev] = true
+ end
+ if replace then
+ -- we seldom enter this branch (e.g. on brill efficient)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n = n - 1
+ if replacetail == replace then
+ break
+ else
+ replacetail = getprev(replacetail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev] = true
+ match = not notmatchpost[prev]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ -- skip 'm
+ end
+ else
+ -- skip 'm
+ end
+ elseif seq[n][32] then
+ n = n - 1
+ else
+ match = false
+ break
+ end
+ prev = getprev(prev)
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
+ n = n - 1
+ else
+ match = false
+ break
+ end
+ end
+ else
+ match = false
+ end
+ else
+ match = false
+ end
+ end
+ -- after
+ if match and s > l then
+ local current = last and getnext(last)
+ if not current then
+ if sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ -- sweeptype = nil
+ end
+ end
+ if current then
+ local discfound = nil
+ -- removed optimization for s-l == 1, we have to deal with marks anyway
+ local n = l + 1
+ while n <= s do
+ if current then
+ local char, id = ischar(current,currentfont)
+ if char then
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ elseif id == disc_code then
+ diskseen = true
+ discfound = current
+ notmatchpre[current] = nil
+ notmatchpost[current] = true
+ notmatchreplace[current] = nil
+ local pre, post, replace = getdisc(current)
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > s then
+ break
+ end
+ else
+ notmatchpre[current] = true
+ break
+ end
+ end
+ if n <= s then
+ notmatchpre[current] = true
+ end
+ else
+ notmatchpre[current] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > s then
+ break
+ end
+ else
+ notmatchreplace[current] = true
+ match = notmatchpre[current]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ -- skip 'm
+ end
+ elseif seq[n][32] then -- brrr
+ n = n + 1
+ else
+ match = false
+ break
+ end
+ current = getnext(current)
+ elseif seq[n][32] then
+ n = n + 1
+current = getnext(current)
+ else
+ match = false
+ break
+ end
+ end
+ else
+ match = false
+ end
+ end
+ end
+ if match then
+ -- can lookups be of a different type ?
+ local diskchain = diskseen or sweepnode
+ if trace_contexts then
+ local rule = ck[1]
+ local lookuptype = ck[8] or ck[2]
+ local first = ck[4]
+ local last = ck[5]
+ local char = getchar(start)
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
+ cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype)
+ end
+ local chainlookups = ck[6]
+ if chainlookups then
+ local nofchainlookups = #chainlookups
+ -- we can speed this up if needed
+ if nofchainlookups == 1 then
+ local chainlookup = chainlookups[1]
+ local chainkind = chainlookup.type
+ local chainproc = chainprocs[chainkind]
+ if chainproc then
+ local ok
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc)
+ else
+ head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
+ end
+ if ok then
+ done = true
+ end
+ else
+ logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
+ end
+ else
+ local i = 1
+ while start and true do
+ if skipped then
+ while start do -- todo: use properties
+ local char = getchar(start)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class or "base"
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ start = getnext(start)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
+ local chainlookup = chainlookups[1] -- should be i when they can be different
+ if not chainlookup then
+ -- we just advance
+ i = i + 1 -- shouldn't that be #current
+ else
+ local chainkind = chainlookup.type
+ local chainproc = chainprocs[chainkind]
+ if chainproc then
+ local ok, n
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc)
+ else
+ head, start, ok, n = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
+ end
+ -- messy since last can be changed !
+ if ok then
+ done = true
+ if n and n > 1 then
+ -- we have a ligature (cf the spec we advance one but we really need to test it
+ -- as there are fonts out there that are fuzzy and have too many lookups:
+ --
+ -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
+ --
+ if i + n > nofchainlookups then
+ -- if trace_contexts then
+ -- logprocess("%s: quitting lookups",cref(dataset,sequence))
+ -- end
+ break
+ else
+ -- we need to carry one
+ end
+ end
+ end
+ else
+ -- actually an error
+ logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
+ end
+ i = i + 1
+ end
+ if i > nofchainlookups or not start then
+ break
+ elseif start then
+ start = getnext(start)
+ end
+ end
+ end
+ else
+ local replacements = ck[7]
+ if replacements then
+ head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
+ else
+ done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
+ if trace_contexts then
+ logprocess("%s: skipping match",cref(dataset,sequence))
+ end
+ end
+ end
+ if done then
+ break -- out of contexts (new, needs checking)
+ end
+ end
+ end
+ if diskseen then
+ notmatchpre = { }
+ notmatchpost = { }
+ notmatchreplace = { }
+ end
+ return head, start, done
+end
+
+handlers.gsub_context = handle_contextchain
+handlers.gsub_contextchain = handle_contextchain
+handlers.gsub_reversecontextchain = handle_contextchain
+handlers.gpos_contextchain = handle_contextchain
+handlers.gpos_context = handle_contextchain
+
+-- this needs testing
+
+local function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode)
+end
+
+chainprocs.gsub_context = chained_contextchain
+chainprocs.gsub_contextchain = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain = chained_contextchain
+chainprocs.gpos_context = chained_contextchain
+
+local missing = setmetatableindex("table")
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ report_process(...)
+end
+
+local logwarning = report_process
+
+local function report_missing_coverage(dataset,sequence)
+ local t = missing[currentfont]
+ if not t[sequence] then
+ t[sequence] = true
+ logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a",
+ dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname)
+ end
+end
+
+local resolved = { } -- we only resolve a font,script,language pair once
+
+-- todo: pass all these 'locals' in a table
+
+local sequencelists = setmetatableindex(function(t,font)
+ local sequences = fontdata[font].resources.sequences
+ if not sequences or not next(sequences) then
+ sequences = false
+ end
+ t[font] = sequences
+ return sequences
+end)
+
+-- fonts.hashes.sequences = sequencelists
+
+local autofeatures = fonts.analyzers.features
+local featuretypes = otf.tables.featuretypes
+local defaultscript = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
+
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
+ local features = sequence.features
+ if features then
+ local order = sequence.order
+ if order then
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind = order[i]
+ local valid = enabled[kind]
+ if valid then
+ local scripts = features[kind]
+ local languages = scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled = languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
+ return { valid, autofeatures[kind] or false, sequence, kind }
+ end
+ end
+ end
+ else
+ -- can't happen
+ end
+ end
+ return false
+end
+
+function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
+ local shared = tfmdata.shared
+ local properties = tfmdata.properties
+ local language = properties.language or "dflt"
+ local script = properties.script or "dflt"
+ local enabled = shared.features
+ local autoscript = enabled and enabled.autoscript
+ local autolanguage = enabled and enabled.autolanguage
+ local res = resolved[font]
+ if not res then
+ res = { }
+ resolved[font] = res
+ end
+ local rs = res[script]
+ if not rs then
+ rs = { }
+ res[script] = rs
+ end
+ local rl = rs[language]
+ if not rl then
+ rl = {
+ -- indexed but we can also add specific data by key
+ }
+ rs[language] = rl
+ local sequences = tfmdata.resources.sequences
+ for s=1,#sequences do
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1] = v
+ end
+ end
+ end
+ return rl
+end
+
+local function report_disc(what,n)
+ report_run("%s: %s > %s",what,n,languages.serializediscretionary(n))
+end
+
+local function kernrun(disc,k_run,font,attr,...)
+ --
+ -- we catch <font 1><disc font 2>
+ --
+ if trace_kernruns then
+ report_disc("kern",disc)
+ end
+ --
+ local prev, next = getboth(disc)
+ --
+ local nextstart = next
+ local done = false
+ --
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ --
+ local prevmarks = prev
+ --
+ -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
+ -- has happened but then it should be in the disc so basically this test indicates an error)
+ --
+ while prevmarks do
+ local char = ischar(prevmarks,font)
+ if char and marks[char] then
+ prevmarks = getprev(prevmarks)
+ else
+ break
+ end
+ end
+ --
+ if prev and (pre or replace) and not ischar(prev,font) then
+ prev = false
+ end
+ if next and (post or replace) and not ischar(next,font) then
+ next = false
+ end
+ --
+ -- we need to get rid of this nest mess some day .. has to be done otherwise
+ --
+ if pre then
+ if k_run(pre,"injections",nil,font,attr,...) then
+ done = true
+ end
+ if prev then
+ local nest = getprev(pre)
+ setlink(prev,pre)
+ if k_run(prevmarks,"preinjections",pre,font,attr,...) then -- or prev?
+ done = true
+ end
+ setprev(pre,nest)
+ setnext(prev,disc)
+ end
+ end
+ --
+ if post then
+ if k_run(post,"injections",nil,font,attr,...) then
+ done = true
+ end
+ if next then
+ setlink(posttail,next)
+ if k_run(posttail,"postinjections",next,font,attr,...) then
+ done = true
+ end
+ setnext(posttail,nil)
+ setprev(next,disc)
+ end
+ end
+ --
+ if replace then
+ if k_run(replace,"injections",nil,font,attr,...) then
+ done = true
+ end
+ if prev then
+ local nest = getprev(replace)
+ setlink(prev,replace)
+ if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then -- getnext(replace))
+ done = true
+ end
+ setprev(replace,nest)
+ setnext(prev,disc)
+ end
+ if next then
+ setlink(replacetail,next)
+ if k_run(replacetail,"replaceinjections",next,font,attr,...) then
+ done = true
+ end
+ setnext(replacetail,nil)
+ setprev(next,disc)
+ end
+ elseif prev and next then
+ setlink(prev,next)
+ if k_run(prevmarks,"emptyinjections",next,font,attr,...) then
+ done = true
+ end
+ setlink(prev,disc)
+ setlink(disc,next)
+ end
+ return nextstart, done
+end
+
+local function comprun(disc,c_run,...)
+ if trace_compruns then
+ report_disc("comp",disc)
+ end
+ --
+ local pre, post, replace = getdisc(disc)
+ local renewed = false
+ --
+ if pre then
+ sweepnode = disc
+ sweeptype = "pre" -- in alternative code preinjections is uc_c_sed (also used then for proeprties, saves a variable)
+ local new, done = c_run(pre,...)
+ if done then
+ pre = new
+ renewed = true
+ end
+ end
+ --
+ if post then
+ sweepnode = disc
+ sweeptype = "post"
+ local new, done = c_run(post,...)
+ if done then
+ post = new
+ renewed = true
+ end
+ end
+ --
+ if replace then
+ sweepnode = disc
+ sweeptype = "replace"
+ local new, done = c_run(replace,...)
+ if done then
+ replace = new
+ renewed = true
+ end
+ end
+ --
+ sweepnode = nil
+ sweeptype = nil
+ if renewed then
+ setdisc(disc,pre,post,replace)
+ end
+ --
+ return getnext(disc), renewed
+end
+
+local function testrun(disc,t_run,c_run,...)
+ if trace_testruns then
+ report_disc("test",disc)
+ end
+ local prev, next = getboth(disc)
+ if not next then
+ -- weird discretionary
+ return
+ end
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ local done = false
+ if replace and prev then
+ -- this is a bit strange as we only do replace here and not post
+ -- anyway, we only look ahead ... the idea is that we discard a
+ -- disc when there is a ligature crossing the replace boundary
+ setlink(replacetail,next)
+ local ok, overflow = t_run(replace,next,...)
+ if ok and overflow then
+ -- so, we can have crossed the boundary
+ setfield(disc,"replace",nil)
+ setlink(prev,replace)
+ -- setlink(replacetail,next)
+ setboth(disc)
+ flush_node_list(disc)
+ return replace, true -- restart .. tricky !
+ else
+ -- we stay inside the disc
+ setnext(replacetail)
+ setprev(next,disc)
+ end
+ -- pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ end
+ --
+ -- like comprun
+ --
+ local renewed = false
+ --
+ if pre then
+ sweepnode = disc
+ sweeptype = "pre"
+ local new, ok = c_run(pre,...)
+ if ok then
+ pre = new
+ renewed = true
+ end
+ end
+ --
+ if post then
+ sweepnode = disc
+ sweeptype = "post"
+ local new, ok = c_run(post,...)
+ if ok then
+ post = new
+ renewed = true
+ end
+ end
+ --
+ if replace then
+ sweepnode = disc
+ sweeptype = "replace"
+ local new, ok = c_run(replace,...)
+ if ok then
+ replace = new
+ renewed = true
+ end
+ end
+ --
+ sweepnode = nil
+ sweeptype = nil
+ if renewed then
+ setdisc(disc,pre,post,replace)
+ return next, true
+ else
+ return next, done
+ end
+end
+
+-- A discrun happens when we have a zwnj. We're gpossing so it is unlikely that
+-- there has been a match changing the character. Now, as we check again here
+-- the question is: why do we do this ... needs checking as drun seems useless
+-- ... maybe that code can go away
+
+-- local function discrun(disc,drun,krun)
+-- local prev, next = getboth(disc)
+-- if trace_discruns then
+-- report_disc("disc",disc)
+-- end
+-- if next and prev then
+-- setnext(prev,next)
+-- -- setprev(next,prev)
+-- drun(prev)
+-- setnext(prev,disc)
+-- -- setprev(next,disc)
+-- end
+-- --
+-- if krun then -- currently always false
+-- local pre = getfield(disc,"pre")
+-- if not pre then
+-- -- go on
+-- elseif prev then
+-- local nest = getprev(pre)
+-- setlink(prev,pre)
+-- krun(prev,"preinjections")
+-- setprev(pre,nest)
+-- setnext(prev,disc)
+-- else
+-- krun(pre,"preinjections")
+-- end
+-- end
+-- return next
+-- end
+
+-- We can make some assumptions with respect to discretionaries. First of all it is very
+-- unlikely that some of the analysis related attributes applies. Then we can also assume
+-- that the ConTeXt specific dynamic attribute is different, although we do use explicit
+-- discretionaries (maybe we need to tag those some day). So, at least for now, we don't
+-- have the following test in the sub runs:
+--
+-- -- local a = getattr(start,0)
+-- -- if a then
+-- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+-- -- else
+-- -- a = not attribute or getprop(start,a_state) == attribute
+-- -- end
+-- -- if a then
+--
+-- but use this instead:
+--
+-- -- local a = getattr(start,0)
+-- -- if not a or (a == attr) then
+--
+-- and even that one is probably not needed.
+
+local nesting = 0
+
+local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ local done = false
+ local sweep = sweephead[head]
+ if sweep then
+ start = sweep
+ sweephead[head] = nil
+ else
+ start = head
+ end
+ while start do
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if not a or (a == attr) then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
+ if ok then
+ done = true
+ end
+ end
+ if start then
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif char == false then
+ return head, done
+ elseif sweep then
+ -- else we loose the rest
+ return head, done
+ else
+ -- in disc component
+ start = getnext(start)
+ end
+ end
+ return head, done
+end
+
+local function t_run_single(start,stop,font,attr,lookupcache)
+ while start ~= stop do
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if not a or (a == attr) then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ local d = 0
+ while s do
+ if s == stop then
+ d = 1
+ elseif d > 0 then
+ d = d + 1
+ end
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true, d > 1
+ end
+ end
+ end
+ start = getnext(start)
+ else
+ break
+ end
+ end
+end
+
+-- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+-- local a = getattr(prev,0)
+-- if not a or (a == attr) then
+-- local char = ischar(prev) -- can be disc
+-- if char then
+-- local lookupmatch = lookupcache[char]
+-- if lookupmatch then
+-- local h, d, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
+-- if ok then
+-- done = true
+-- success = true
+-- end
+-- end
+-- end
+-- end
+-- end
+
+local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ local a = getattr(sub,0)
+ if not a or (a == attr) then
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local char = ischar(n)
+ if char then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(sub,n,dataset,sequence,lookupmatch,rlmode,step,1,injection)
+ if ok then
+ return true
+ end
+ end
+ end
+ end
+ end
+end
+
+local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ local done = false
+ local sweep = sweephead[head]
+ if sweep then
+ start = sweep
+ sweephead[head] = nil
+ else
+ start = head
+ end
+ while start do
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if not a or (a == attr) then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ 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,step,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ end
+ end
+ else
+ report_missing_coverage(dataset,sequence)
+ end
+ end
+ if start then
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif char == false then
+ -- whatever glyph
+ return head, done
+ elseif sweep then
+ -- else we loose the rest
+ return head, done
+ else
+ -- in disc component
+ start = getnext(start)
+ end
+ end
+ return head, done
+end
+
+local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
+ while start ~= stop do
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if not a or (a == attr) then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ local d = 0
+ while s do
+ if s == stop then
+ d = 1
+ elseif d > 0 then
+ d = d + 1
+ end
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true, d > 1
+ end
+ end
+ else
+ report_missing_coverage(dataset,sequence)
+ end
+ end
+ end
+ start = getnext(start)
+ else
+ break
+ end
+ end
+end
+
+-- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+-- local a = getattr(prev,0)
+-- if not a or (a == attr) then
+-- local char = ischar(prev) -- can be disc
+-- if char then
+-- for i=1,nofsteps do
+-- local step = steps[i]
+-- local lookupcache = step.coverage
+-- if lookupcache then
+-- local lookupmatch = lookupcache[char]
+-- if lookupmatch then
+-- -- we could move all code inline but that makes things even more unreadable
+-- local h, d, ok = handler(head,prev,dataset,sequence,lookupmatch,rlmode,step,i)
+-- if ok then
+-- done = true
+-- break
+-- end
+-- end
+-- else
+-- report_missing_coverage(dataset,sequence)
+-- end
+-- end
+-- end
+-- end
+-- end
+
+local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ local a = getattr(sub,0)
+ if not a or (a == attr) then
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local char = ischar(n)
+ if char then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection)
+ if ok then
+ return true
+ end
+ end
+ else
+ report_missing_coverage(dataset,sequence)
+ end
+ end
+ end
+ end
+ end
+end
+
+-- to be checkedL 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 = getfield(start,"dir")
+ 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
+ top = top - 1
+ if stack[top] == "+TRT" then
+ new = -1
+ end
+ else
+ new = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, level %a",dir,mref(rlparmode),mref(new),topstack)
+ end
+ return getnext(start), top, new
+end
+
+local function pardirstate(start)
+ local dir = getfield(start,"dir")
+ local new = 0
+ if dir == "TLT" then
+ new = 1
+ elseif dir == "TRT" then
+ new = -1
+ end
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a",dir,mref(new))
+ end
+ return getnext(start), new, new
+end
+
+local function featuresprocessor(head,font,attr)
+
+ local sequences = sequencelists[font] -- temp hack
+
+ if not sequencelists then
+ return head, false
+ end
+
+ nesting = nesting + 1
+
+ if nesting == 1 then
+
+ currentfont = font
+ tfmdata = fontdata[font]
+ descriptions = tfmdata.descriptions
+ characters = tfmdata.characters
+ marks = tfmdata.resources.marks
+ factor = tfmdata.parameters.factor
+ threshold = tfmdata.parameters.spacing.width or 65536*10
+
+ elseif currentfont ~= font then
+
+ report_warning("nested call with a different font, level %s, quitting",nesting)
+ nesting = nesting - 1
+ return head, false
+
+ end
+
+ head = tonut(head)
+
+ if trace_steps then
+ checkstep(head)
+ end
+
+ local rlmode = 0
+
+ local done = false
+ local datasets = otf.dataset(tfmdata,font,attr)
+
+ local dirstack = { } -- could move outside function btu we can have local runss
+
+ sweephead = { }
+
+ -- We could work on sub start-stop ranges instead but I wonder if there is that
+ -- much speed gain (experiments showed that it made not much sense) and we need
+ -- to keep track of directions anyway. Also at some point I want to play with
+ -- font interactions and then we do need the full sweeps.
+
+ -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
+ -- so that multiple cases are also covered.)
+
+ -- We don't goto the next node of a disc node is created so that we can then treat
+ -- the pre, post and replace. It's a bit of a hack but works out ok for most cases.
+
+ for s=1,#datasets do
+ local dataset = datasets[s]
+ ----- featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ local attribute = dataset[2]
+ local sequence = dataset[3] -- sequences[s] -- also dataset[5]
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local typ = sequence.type
+ local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset
+ local handler = handlers[typ]
+ local steps = sequence.steps
+ local nofsteps = sequence.nofsteps
+ if not steps then
+ -- this permits injection, watch the different arguments
+ local h, d, ok = handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr)
+ if ok then
+ success = true
+ if h then
+ head = h
+ end
+ if d then
+ start = d
+ end
+ end
+ elseif typ == "gsub_reversecontextchain" then
+ -- this is a limited case, no special treatments like 'init' etc
+ local start = find_node_tail(head)
+ while start do
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if not a or (a == attr) then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- todo: disc?
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ success = true
+ break
+ end
+ end
+ else
+ report_missing_coverage(dataset,sequence)
+ end
+ end
+ if start then
+ start = getprev(start)
+ end
+ else
+ start = getprev(start)
+ end
+ else
+ start = getprev(start)
+ end
+ end
+ else
+ local start = head -- local ?
+ rlmode = 0 -- to be checked ?
+ if nofsteps == 1 then -- happens often
+
+ local step = steps[1]
+ local lookupcache = step.coverage
+ if not lookupcache then
+ -- can't happen, no check in loop either
+ report_missing_coverage(dataset,sequence)
+ else
+
+ while start do
+ local char, id = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
+ if ok then
+ success = true
+ -- elseif gpossing and zwnjruns and char == zwnj then
+ -- discrun(start,d_run,font,attr,lookupcache)
+ end
+ -- elseif gpossing and zwnjruns and char == zwnj then
+ -- discrun(start,d_run,font,attr,lookupcache)
+ end
+ if start then
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif char == false then
+ -- whatever glyph
+ start = getnext(start)
+ elseif id == disc_code then
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success = true
+ 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)
+ else
+ start = getnext(start)
+ end
+ end
+ end
+
+ else
+
+ while start do
+ local char, id = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ 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,step,i)
+ if ok then
+ success = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ -- elseif gpossing and zwnjruns and char == zwnj then
+ -- discrun(start,d_run,font,attr,steps,nofsteps)
+ end
+ -- elseif gpossing and zwnjruns and char == zwnj then
+ -- discrun(start,d_run,font,attr,steps,nofsteps)
+ end
+ else
+ report_missing_coverage(dataset,sequence)
+ end
+ end
+ if start then
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif char == false then
+ start = getnext(start)
+ elseif id == disc_code then
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ else
+ start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success = true
+ 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)
+ else
+ start = getnext(start)
+ end
+ end
+ end
+ end
+
+ if success then
+ done = true
+ end
+ if trace_steps then -- ?
+ registerstep(head)
+ end
+
+ end
+
+ nesting = nesting - 1
+ head = tonode(head)
+
+ return head, done
+end
+
+-- so far
+
+local function featuresinitializer(tfmdata,value)
+ -- nothing done here any more
+end
+
+registerotffeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ position = 1,
+ node = featuresinitializer,
+ },
+ processors = {
+ node = featuresprocessor,
+ }
+}
+
+-- This can be used for extra handlers, but should be used with care!
+
+otf.handlers = handlers -- used in devanagari
+
+-- We implement one here:
+
+local setspacekerns = nodes.injections.setspacekerns if not setspacekerns then os.exit() end
+
+function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ -- if not setspacekerns then
+ -- setspacekerns = nodes.injections.setspacekerns
+ -- end
+ setspacekerns(font,sequence)
+ return head, start, true
+end
+
+local function hasspacekerns(data)
+ local sequences = data.resources.sequences
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local steps = sequence.steps
+ if steps and sequence.features.kern then
+ for i=1,#steps do
+ local coverage = steps[i].coverage
+ if not coverage then
+ -- maybe an issue
+ elseif coverage[32] then
+ return true
+ else
+ for k, v in next, coverage do
+ if v[32] then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+ return false
+end
+
+otf.readers.registerextender {
+ name = "spacekerns",
+ action = function(data)
+ data.properties.hasspacekerns = hasspacekerns(data)
+ end
+}
+
+local function spaceinitializer(tfmdata,value) -- attr
+ local resources = tfmdata.resources
+ local spacekerns = resources and resources.spacekerns
+ if spacekerns == nil then
+ local properties = tfmdata.properties
+ if properties and properties.hasspacekerns then
+ local sequences = resources.sequences
+ local left = { }
+ local right = { }
+ local last = 0
+ local feat = nil
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local steps = sequence.steps
+ if steps then
+ local kern = sequence.features.kern
+ if kern then
+ feat = feat or kern -- or maybe merge
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ local kerns = coverage[32]
+ if kerns then
+ for k, v in next, kerns do
+ if type(v) == "table" then
+ right[k] = v[3] -- needs checking
+ else
+ right[k] = v
+ end
+ end
+ end
+ for k, v in next, coverage do
+ local kern = v[32]
+ if kern then
+ if type(kern) == "table" then
+ left[k] = kern[3] -- needs checking
+ else
+ left[k] = kern
+ end
+ end
+ end
+ end
+ end
+ last = i
+ end
+ else
+ -- no steps ... needed for old one ... we could use the basekerns
+ -- instead
+ end
+ end
+ left = next(left) and left or false
+ right = next(right) and right or false
+ if left or right then
+ spacekerns = {
+ left = left,
+ right = right,
+ }
+ if last > 0 then
+ local triggersequence = {
+ features = { kern = feat or { dflt = { dflt = true, } } },
+ flags = noflags,
+ name = "trigger_space_kerns",
+ order = { "kern" },
+ type = "trigger_space_kerns",
+ left = left,
+ right = right,
+ }
+ insert(sequences,last,triggersequence)
+ end
+ else
+ spacekerns = false
+ end
+ else
+ spacekerns = false
+ end
+ resources.spacekerns = spacekerns
+ end
+ return spacekerns
+end
+
+registerotffeature {
+ name = "spacekern",
+ description = "space kern injection",
+ default = true,
+ initializers = {
+ node = spaceinitializer,
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua
new file mode 100644
index 00000000000..f8d74a317d0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua
@@ -0,0 +1,1130 @@
+if not modules then modules = { } end modules ['font-ott'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (tables)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ -- dataonly = true,
+}
+
+local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
+local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match
+local is_boolean = string.is_boolean
+
+local setmetatableindex = table.setmetatableindex
+local setmetatablenewindex = table.setmetatablenewindex
+local allocate = utilities.storage.allocate
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
+
+local tables = otf.tables or { }
+otf.tables = tables
+
+local statistics = otf.statistics or { }
+otf.statistics = statistics
+
+local scripts = allocate {
+ ['arab'] = 'arabic',
+ ['armi'] = 'imperial aramaic',
+ ['armn'] = 'armenian',
+ ['avst'] = 'avestan',
+ ['bali'] = 'balinese',
+ ['bamu'] = 'bamum',
+ ['batk'] = 'batak',
+ ['beng'] = 'bengali',
+ ['bng2'] = 'bengali variant 2',
+ ['bopo'] = 'bopomofo',
+ ['brah'] = 'brahmi',
+ ['brai'] = 'braille',
+ ['bugi'] = 'buginese',
+ ['buhd'] = 'buhid',
+ ['byzm'] = 'byzantine music',
+ ['cakm'] = 'chakma',
+ ['cans'] = 'canadian syllabics',
+ ['cari'] = 'carian',
+ ['cham'] = 'cham',
+ ['cher'] = 'cherokee',
+ ['copt'] = 'coptic',
+ ['cprt'] = 'cypriot syllabary',
+ ['cyrl'] = 'cyrillic',
+ ['deva'] = 'devanagari',
+ ['dev2'] = 'devanagari variant 2',
+ ['dsrt'] = 'deseret',
+ ['egyp'] = 'egyptian heiroglyphs',
+ ['ethi'] = 'ethiopic',
+ ['geor'] = 'georgian',
+ ['glag'] = 'glagolitic',
+ ['goth'] = 'gothic',
+ ['grek'] = 'greek',
+ ['gujr'] = 'gujarati',
+ ['gjr2'] = 'gujarati variant 2',
+ ['guru'] = 'gurmukhi',
+ ['gur2'] = 'gurmukhi variant 2',
+ ['hang'] = 'hangul',
+ ['hani'] = 'cjk ideographic',
+ ['hano'] = 'hanunoo',
+ ['hebr'] = 'hebrew',
+ ['ital'] = 'old italic',
+ ['jamo'] = 'hangul jamo',
+ ['java'] = 'javanese',
+ ['kali'] = 'kayah li',
+ ['kana'] = 'hiragana and katakana',
+ ['khar'] = 'kharosthi',
+ ['khmr'] = 'khmer',
+ ['knda'] = 'kannada',
+ ['knd2'] = 'kannada variant 2',
+ ['kthi'] = 'kaithi',
+ ['lana'] = 'tai tham',
+ ['lao' ] = 'lao',
+ ['latn'] = 'latin',
+ ['lepc'] = 'lepcha',
+ ['limb'] = 'limbu',
+ ['linb'] = 'linear b',
+ ['lisu'] = 'lisu',
+ ['lyci'] = 'lycian',
+ ['lydi'] = 'lydian',
+ ['mand'] = 'mandaic and mandaean',
+ ['math'] = 'mathematical alphanumeric symbols',
+ ['merc'] = 'meroitic cursive',
+ ['mero'] = 'meroitic hieroglyphs',
+ ['mlym'] = 'malayalam',
+ ['mlm2'] = 'malayalam variant 2',
+ ['mong'] = 'mongolian',
+ ['mtei'] = 'meitei Mayek',
+ ['musc'] = 'musical symbols',
+ ['mym2'] = 'myanmar variant 2',
+ ['mymr'] = 'myanmar',
+ ['nko' ] = "n'ko",
+ ['ogam'] = 'ogham',
+ ['olck'] = 'ol chiki',
+ ['orkh'] = 'old turkic and orkhon runic',
+ ['orya'] = 'oriya',
+ ['ory2'] = 'odia variant 2',
+ ['osma'] = 'osmanya',
+ ['phag'] = 'phags-pa',
+ ['phli'] = 'inscriptional pahlavi',
+ ['phnx'] = 'phoenician',
+ ['prti'] = 'inscriptional parthian',
+ ['rjng'] = 'rejang',
+ ['runr'] = 'runic',
+ ['samr'] = 'samaritan',
+ ['sarb'] = 'old south arabian',
+ ['saur'] = 'saurashtra',
+ ['shaw'] = 'shavian',
+ ['shrd'] = 'sharada',
+ ['sinh'] = 'sinhala',
+ ['sora'] = 'sora sompeng',
+ ['sund'] = 'sundanese',
+ ['sylo'] = 'syloti nagri',
+ ['syrc'] = 'syriac',
+ ['tagb'] = 'tagbanwa',
+ ['takr'] = 'takri',
+ ['tale'] = 'tai le',
+ ['talu'] = 'tai lu',
+ ['taml'] = 'tamil',
+ ['tavt'] = 'tai viet',
+ ['telu'] = 'telugu',
+ ['tel2'] = 'telugu variant 2',
+ ['tfng'] = 'tifinagh',
+ ['tglg'] = 'tagalog',
+ ['thaa'] = 'thaana',
+ ['thai'] = 'thai',
+ ['tibt'] = 'tibetan',
+ ['tml2'] = 'tamil variant 2',
+ ['ugar'] = 'ugaritic cuneiform',
+ ['vai' ] = 'vai',
+ ['xpeo'] = 'old persian cuneiform',
+ ['xsux'] = 'sumero-akkadian cuneiform',
+ ['yi' ] = 'yi',
+}
+
+local languages = allocate {
+ ["aba" ] = "abaza",
+ ["abk" ] = "abkhazian",
+ ["ach" ] = "acholi",
+ ["acr" ] = "achi",
+ ["ady" ] = "adyghe",
+ ["afk" ] = "afrikaans",
+ ["afr" ] = "afar",
+ ["agw" ] = "agaw",
+ ["aio" ] = "aiton",
+ ["aka" ] = "akan",
+ ["als" ] = "alsatian",
+ ["alt" ] = "altai",
+ ["amh" ] = "amharic",
+ ["ang" ] = "anglo-saxon",
+ ["apph"] = "phonetic transcription—americanist conventions",
+ ["ara" ] = "arabic",
+ ["arg" ] = "aragonese",
+ ["ari" ] = "aari",
+ ["ark" ] = "rakhine",
+ ["asm" ] = "assamese",
+ ["ast" ] = "asturian",
+ ["ath" ] = "athapaskan",
+ ["avr" ] = "avar",
+ ["awa" ] = "awadhi",
+ ["aym" ] = "aymara",
+ ["azb" ] = "torki",
+ ["aze" ] = "azerbaijani",
+ ["bad" ] = "badaga",
+ ["bad0"] = "banda",
+ ["bag" ] = "baghelkhandi",
+ ["bal" ] = "balkar",
+ ["ban" ] = "balinese",
+ ["bar" ] = "bavarian",
+ ["bau" ] = "baulé",
+ ["bbc" ] = "batak toba",
+ ["bbr" ] = "berber",
+ ["bch" ] = "bench",
+ ["bcr" ] = "bible cree",
+ ["bdy" ] = "bandjalang",
+ ["bel" ] = "belarussian",
+ ["bem" ] = "bemba",
+ ["ben" ] = "bengali",
+ ["bgc" ] = "haryanvi",
+ ["bgq" ] = "bagri",
+ ["bgr" ] = "bulgarian",
+ ["bhi" ] = "bhili",
+ ["bho" ] = "bhojpuri",
+ ["bik" ] = "bikol",
+ ["bil" ] = "bilen",
+ ["bis" ] = "bislama",
+ ["bjj" ] = "kanauji",
+ ["bkf" ] = "blackfoot",
+ ["bli" ] = "baluchi",
+ ["blk" ] = "pa'o karen",
+ ["bln" ] = "balante",
+ ["blt" ] = "balti",
+ ["bmb" ] = "bambara (bamanankan)",
+ ["bml" ] = "bamileke",
+ ["bos" ] = "bosnian",
+ ["bpy" ] = "bishnupriya manipuri",
+ ["bre" ] = "breton",
+ ["brh" ] = "brahui",
+ ["bri" ] = "braj bhasha",
+ ["brm" ] = "burmese",
+ ["brx" ] = "bodo",
+ ["bsh" ] = "bashkir",
+ ["bti" ] = "beti",
+ ["bts" ] = "batak simalungun",
+ ["bug" ] = "bugis",
+ ["cak" ] = "kaqchikel",
+ ["cat" ] = "catalan",
+ ["cbk" ] = "zamboanga chavacano",
+ ["ceb" ] = "cebuano",
+ ["cgg" ] = "chiga",
+ ["cha" ] = "chamorro",
+ ["che" ] = "chechen",
+ ["chg" ] = "chaha gurage",
+ ["chh" ] = "chattisgarhi",
+ ["chi" ] = "chichewa (chewa, nyanja)",
+ ["chk" ] = "chukchi",
+ ["chk0"] = "chuukese",
+ ["cho" ] = "choctaw",
+ ["chp" ] = "chipewyan",
+ ["chr" ] = "cherokee",
+ ["chu" ] = "chuvash",
+ ["chy" ] = "cheyenne",
+ ["cmr" ] = "comorian",
+ ["cop" ] = "coptic",
+ ["cor" ] = "cornish",
+ ["cos" ] = "corsican",
+ ["cpp" ] = "creoles",
+ ["cre" ] = "cree",
+ ["crr" ] = "carrier",
+ ["crt" ] = "crimean tatar",
+ ["csb" ] = "kashubian",
+ ["csl" ] = "church slavonic",
+ ["csy" ] = "czech",
+ ["ctg" ] = "chittagonian",
+ ["cuk" ] = "san blas kuna",
+ ["dan" ] = "danish",
+ ["dar" ] = "dargwa",
+ ["dax" ] = "dayi",
+ ["dcr" ] = "woods cree",
+ ["deu" ] = "german",
+ ["dgo" ] = "dogri",
+ ["dgr" ] = "dogri",
+ ["dhg" ] = "dhangu",
+ ["dhv" ] = "divehi (dhivehi, maldivian)",
+ ["diq" ] = "dimli",
+ ["div" ] = "divehi (dhivehi, maldivian)",
+ ["djr" ] = "zarma",
+ ["djr0"] = "djambarrpuyngu",
+ ["dng" ] = "dangme",
+ ["dnj" ] = "dan",
+ ["dnk" ] = "dinka",
+ ["dri" ] = "dari",
+ ["duj" ] = "dhuwal",
+ ["dun" ] = "dungan",
+ ["dzn" ] = "dzongkha",
+ ["ebi" ] = "ebira",
+ ["ecr" ] = "eastern cree",
+ ["edo" ] = "edo",
+ ["efi" ] = "efik",
+ ["ell" ] = "greek",
+ ["emk" ] = "eastern maninkakan",
+ ["eng" ] = "english",
+ ["erz" ] = "erzya",
+ ["esp" ] = "spanish",
+ ["esu" ] = "central yupik",
+ ["eti" ] = "estonian",
+ ["euq" ] = "basque",
+ ["evk" ] = "evenki",
+ ["evn" ] = "even",
+ ["ewe" ] = "ewe",
+ ["fan" ] = "french antillean",
+ ["fan0"] = " fang",
+ ["far" ] = "persian",
+ ["fat" ] = "fanti",
+ ["fin" ] = "finnish",
+ ["fji" ] = "fijian",
+ ["fle" ] = "dutch (flemish)",
+ ["fne" ] = "forest nenets",
+ ["fon" ] = "fon",
+ ["fos" ] = "faroese",
+ ["fra" ] = "french",
+ ["frc" ] = "cajun french",
+ ["fri" ] = "frisian",
+ ["frl" ] = "friulian",
+ ["frp" ] = "arpitan",
+ ["fta" ] = "futa",
+ ["ful" ] = "fulah",
+ ["fuv" ] = "nigerian fulfulde",
+ ["gad" ] = "ga",
+ ["gae" ] = "scottish gaelic (gaelic)",
+ ["gag" ] = "gagauz",
+ ["gal" ] = "galician",
+ ["gar" ] = "garshuni",
+ ["gaw" ] = "garhwali",
+ ["gez" ] = "ge'ez",
+ ["gih" ] = "githabul",
+ ["gil" ] = "gilyak",
+ ["gil0"] = " kiribati (gilbertese)",
+ ["gkp" ] = "kpelle (guinea)",
+ ["glk" ] = "gilaki",
+ ["gmz" ] = "gumuz",
+ ["gnn" ] = "gumatj",
+ ["gog" ] = "gogo",
+ ["gon" ] = "gondi",
+ ["grn" ] = "greenlandic",
+ ["gro" ] = "garo",
+ ["gua" ] = "guarani",
+ ["guc" ] = "wayuu",
+ ["guf" ] = "gupapuyngu",
+ ["guj" ] = "gujarati",
+ ["guz" ] = "gusii",
+ ["hai" ] = "haitian (haitian creole)",
+ ["hal" ] = "halam",
+ ["har" ] = "harauti",
+ ["hau" ] = "hausa",
+ ["haw" ] = "hawaiian",
+ ["hay" ] = "haya",
+ ["haz" ] = "hazaragi",
+ ["hbn" ] = "hammer-banna",
+ ["her" ] = "herero",
+ ["hil" ] = "hiligaynon",
+ ["hin" ] = "hindi",
+ ["hma" ] = "high mari",
+ ["hmn" ] = "hmong",
+ ["hmo" ] = "hiri motu",
+ ["hnd" ] = "hindko",
+ ["ho" ] = "ho",
+ ["hri" ] = "harari",
+ ["hrv" ] = "croatian",
+ ["hun" ] = "hungarian",
+ ["hye" ] = "armenian",
+ ["hye0"] = "armenian east",
+ ["iba" ] = "iban",
+ ["ibb" ] = "ibibio",
+ ["ibo" ] = "igbo",
+ ["ido" ] = "ido",
+ ["ijo" ] = "ijo languages",
+ ["ile" ] = "interlingue",
+ ["ilo" ] = "ilokano",
+ ["ina" ] = "interlingua",
+ ["ind" ] = "indonesian",
+ ["ing" ] = "ingush",
+ ["inu" ] = "inuktitut",
+ ["ipk" ] = "inupiat",
+ ["ipph"] = "phonetic transcription—ipa conventions",
+ ["iri" ] = "irish",
+ ["irt" ] = "irish traditional",
+ ["isl" ] = "icelandic",
+ ["ism" ] = "inari sami",
+ ["ita" ] = "italian",
+ ["iwr" ] = "hebrew",
+ ["jam" ] = "jamaican creole",
+ ["jan" ] = "japanese",
+ ["jav" ] = "javanese",
+ ["jbo" ] = "lojban",
+ ["jii" ] = "yiddish",
+ ["jud" ] = "ladino",
+ ["jul" ] = "jula",
+ ["kab" ] = "kabardian",
+ ["kab0"] = "kabyle",
+ ["kac" ] = "kachchi",
+ ["kal" ] = "kalenjin",
+ ["kan" ] = "kannada",
+ ["kar" ] = "karachay",
+ ["kat" ] = "georgian",
+ ["kaz" ] = "kazakh",
+ ["kde" ] = "makonde",
+ ["kea" ] = "kabuverdianu (crioulo)",
+ ["keb" ] = "kebena",
+ ["kek" ] = "kekchi",
+ ["kge" ] = "khutsuri georgian",
+ ["kha" ] = "khakass",
+ ["khk" ] = "khanty-kazim",
+ ["khm" ] = "khmer",
+ ["khs" ] = "khanty-shurishkar",
+ ["kht" ] = "khamti shan",
+ ["khv" ] = "khanty-vakhi",
+ ["khw" ] = "khowar",
+ ["kik" ] = "kikuyu (gikuyu)",
+ ["kir" ] = "kirghiz (kyrgyz)",
+ ["kis" ] = "kisii",
+ ["kiu" ] = "kirmanjki",
+ ["kjd" ] = "southern kiwai",
+ ["kjp" ] = "eastern pwo karen",
+ ["kkn" ] = "kokni",
+ ["klm" ] = "kalmyk",
+ ["kmb" ] = "kamba",
+ ["kmn" ] = "kumaoni",
+ ["kmo" ] = "komo",
+ ["kms" ] = "komso",
+ ["knr" ] = "kanuri",
+ ["kod" ] = "kodagu",
+ ["koh" ] = "korean old hangul",
+ ["kok" ] = "konkani",
+ ["kom" ] = "komi",
+ ["kon" ] = "kikongo",
+ ["kon0"] = "kongo",
+ ["kop" ] = "komi-permyak",
+ ["kor" ] = "korean",
+ ["kos" ] = "kosraean",
+ ["koz" ] = "komi-zyrian",
+ ["kpl" ] = "kpelle",
+ ["kri" ] = "krio",
+ ["krk" ] = "karakalpak",
+ ["krl" ] = "karelian",
+ ["krm" ] = "karaim",
+ ["krn" ] = "karen",
+ ["krt" ] = "koorete",
+ ["ksh" ] = "kashmiri",
+ ["ksh0"] = "ripuarian",
+ ["ksi" ] = "khasi",
+ ["ksm" ] = "kildin sami",
+ ["ksw" ] = "s’gaw karen",
+ ["kua" ] = "kuanyama",
+ ["kui" ] = "kui",
+ ["kul" ] = "kulvi",
+ ["kum" ] = "kumyk",
+ ["kur" ] = "kurdish",
+ ["kuu" ] = "kurukh",
+ ["kuy" ] = "kuy",
+ ["kyk" ] = "koryak",
+ ["kyu" ] = "western kayah",
+ ["lad" ] = "ladin",
+ ["lah" ] = "lahuli",
+ ["lak" ] = "lak",
+ ["lam" ] = "lambani",
+ ["lao" ] = "lao",
+ ["lat" ] = "latin",
+ ["laz" ] = "laz",
+ ["lcr" ] = "l-cree",
+ ["ldk" ] = "ladakhi",
+ ["lez" ] = "lezgi",
+ ["lij" ] = "ligurian",
+ ["lim" ] = "limburgish",
+ ["lin" ] = "lingala",
+ ["lis" ] = "lisu",
+ ["ljp" ] = "lampung",
+ ["lki" ] = "laki",
+ ["lma" ] = "low mari",
+ ["lmb" ] = "limbu",
+ ["lmo" ] = "lombard",
+ ["lmw" ] = "lomwe",
+ ["lom" ] = "loma",
+ ["lrc" ] = "luri",
+ ["lsb" ] = "lower sorbian",
+ ["lsm" ] = "lule sami",
+ ["lth" ] = "lithuanian",
+ ["ltz" ] = "luxembourgish",
+ ["lua" ] = "luba-lulua",
+ ["lub" ] = "luba-katanga",
+ ["lug" ] = "ganda",
+ ["luh" ] = "luyia",
+ ["luo" ] = "luo",
+ ["lvi" ] = "latvian",
+ ["mad" ] = "madura",
+ ["mag" ] = "magahi",
+ ["mah" ] = "marshallese",
+ ["maj" ] = "majang",
+ ["mak" ] = "makhuwa",
+ ["mal" ] = "malayalam reformed",
+ ["mam" ] = "mam",
+ ["man" ] = "mansi",
+ ["map" ] = "mapudungun",
+ ["mar" ] = "marathi",
+ ["maw" ] = "marwari",
+ ["mbn" ] = "mbundu",
+ ["mch" ] = "manchu",
+ ["mcr" ] = "moose cree",
+ ["mde" ] = "mende",
+ ["mdr" ] = "mandar",
+ ["men" ] = "me'en",
+ ["mer" ] = "meru",
+ ["mfe" ] = "morisyen",
+ ["min" ] = "minangkabau",
+ ["miz" ] = "mizo",
+ ["mkd" ] = "macedonian",
+ ["mkr" ] = "makasar",
+ ["mkw" ] = "kituba",
+ ["mle" ] = "male",
+ ["mlg" ] = "malagasy",
+ ["mln" ] = "malinke",
+ ["mly" ] = "malay",
+ ["mnd" ] = "mandinka",
+ ["mng" ] = "mongolian",
+ ["mni" ] = "manipuri",
+ ["mnk" ] = "maninka",
+ ["mnx" ] = "manx",
+ ["moh" ] = "mohawk",
+ ["mok" ] = "moksha",
+ ["mol" ] = "moldavian",
+ ["mon" ] = "mon",
+ ["mor" ] = "moroccan",
+ ["mos" ] = "mossi",
+ ["mri" ] = "maori",
+ ["mth" ] = "maithili",
+ ["mts" ] = "maltese",
+ ["mun" ] = "mundari",
+ ["mus" ] = "muscogee",
+ ["mwl" ] = "mirandese",
+ ["mww" ] = "hmong daw",
+ ["myn" ] = "mayan",
+ ["mzn" ] = "mazanderani",
+ ["nag" ] = "naga-assamese",
+ ["nah" ] = "nahuatl",
+ ["nan" ] = "nanai",
+ ["nap" ] = "neapolitan",
+ ["nas" ] = "naskapi",
+ ["nau" ] = "nauruan",
+ ["nav" ] = "navajo",
+ ["ncr" ] = "n-cree",
+ ["ndb" ] = "ndebele",
+ ["ndc" ] = "ndau",
+ ["ndg" ] = "ndonga",
+ ["nds" ] = "low saxon",
+ ["nep" ] = "nepali",
+ ["new" ] = "newari",
+ ["nga" ] = "ngbaka",
+ ["ngr" ] = "nagari",
+ ["nhc" ] = "norway house cree",
+ ["nis" ] = "nisi",
+ ["niu" ] = "niuean",
+ ["nkl" ] = "nyankole",
+ ["nko" ] = "n'ko",
+ ["nld" ] = "dutch",
+ ["noe" ] = "nimadi",
+ ["nog" ] = "nogai",
+ ["nor" ] = "norwegian",
+ ["nov" ] = "novial",
+ ["nsm" ] = "northern sami",
+ ["nso" ] = "sotho, northern",
+ ["nta" ] = "northern tai",
+ ["nto" ] = "esperanto",
+ ["nym" ] = "nyamwezi",
+ ["nyn" ] = "norwegian nynorsk",
+ ["oci" ] = "occitan",
+ ["ocr" ] = "oji-cree",
+ ["ojb" ] = "ojibway",
+ ["ori" ] = "odia",
+ ["oro" ] = "oromo",
+ ["oss" ] = "ossetian",
+ ["paa" ] = "palestinian aramaic",
+ ["pag" ] = "pangasinan",
+ ["pal" ] = "pali",
+ ["pam" ] = "pampangan",
+ ["pan" ] = "punjabi",
+ ["pap" ] = "palpa",
+ ["pap0"] = "papiamentu",
+ ["pas" ] = "pashto",
+ ["pau" ] = "palauan",
+ ["pcc" ] = "bouyei",
+ ["pcd" ] = "picard",
+ ["pdc" ] = "pennsylvania german",
+ ["pgr" ] = "polytonic greek",
+ ["phk" ] = "phake",
+ ["pih" ] = "norfolk",
+ ["pil" ] = "filipino",
+ ["plg" ] = "palaung",
+ ["plk" ] = "polish",
+ ["pms" ] = "piemontese",
+ ["pnb" ] = "western panjabi",
+ ["poh" ] = "pocomchi",
+ ["pon" ] = "pohnpeian",
+ ["pro" ] = "provencal",
+ ["ptg" ] = "portuguese",
+ ["pwo" ] = "western pwo karen",
+ ["qin" ] = "chin",
+ ["quc" ] = "k’iche’",
+ ["quh" ] = "quechua (bolivia)",
+ ["quz" ] = "quechua",
+ ["qvi" ] = "quechua (ecuador)",
+ ["qwh" ] = "quechua (peru)",
+ ["raj" ] = "rajasthani",
+ ["rar" ] = "rarotongan",
+ ["rbu" ] = "russian buriat",
+ ["rcr" ] = "r-cree",
+ ["rej" ] = "rejang",
+ ["ria" ] = "riang",
+ ["rif" ] = "tarifit",
+ ["rit" ] = "ritarungo",
+ ["rkw" ] = "arakwal",
+ ["rms" ] = "romansh",
+ ["rmy" ] = "vlax romani",
+ ["rom" ] = "romanian",
+ ["roy" ] = "romany",
+ ["rsy" ] = "rusyn",
+ ["rtm" ] = "rotuman",
+ ["rua" ] = "kinyarwanda",
+ ["run" ] = "rundi",
+ ["rup" ] = "aromanian",
+ ["rus" ] = "russian",
+ ["sad" ] = "sadri",
+ ["san" ] = "sanskrit",
+ ["sas" ] = "sasak",
+ ["sat" ] = "santali",
+ ["say" ] = "sayisi",
+ ["scn" ] = "sicilian",
+ ["sco" ] = "scots",
+ ["sek" ] = "sekota",
+ ["sel" ] = "selkup",
+ ["sga" ] = "old irish",
+ ["sgo" ] = "sango",
+ ["sgs" ] = "samogitian",
+ ["shi" ] = "tachelhit",
+ ["shn" ] = "shan",
+ ["sib" ] = "sibe",
+ ["sid" ] = "sidamo",
+ ["sig" ] = "silte gurage",
+ ["sks" ] = "skolt sami",
+ ["sky" ] = "slovak",
+ ["sla" ] = "slavey",
+ ["slv" ] = "slovenian",
+ ["sml" ] = "somali",
+ ["smo" ] = "samoan",
+ ["sna" ] = "sena",
+ ["sna0"] = "shona",
+ ["snd" ] = "sindhi",
+ ["snh" ] = "sinhala (sinhalese)",
+ ["snk" ] = "soninke",
+ ["sog" ] = "sodo gurage",
+ ["sop" ] = "songe",
+ ["sot" ] = "sotho, southern",
+ ["sqi" ] = "albanian",
+ ["srb" ] = "serbian",
+ ["srd" ] = "sardinian",
+ ["srk" ] = "saraiki",
+ ["srr" ] = "serer",
+ ["ssl" ] = "south slavey",
+ ["ssm" ] = "southern sami",
+ ["stq" ] = "saterland frisian",
+ ["suk" ] = "sukuma",
+ ["sun" ] = "sundanese",
+ ["sur" ] = "suri",
+ ["sva" ] = "svan",
+ ["sve" ] = "swedish",
+ ["swa" ] = "swadaya aramaic",
+ ["swk" ] = "swahili",
+ ["swz" ] = "swati",
+ ["sxt" ] = "sutu",
+ ["sxu" ] = "upper saxon",
+ ["syl" ] = "sylheti",
+ ["syr" ] = "syriac",
+ ["szl" ] = "silesian",
+ ["tab" ] = "tabasaran",
+ ["taj" ] = "tajiki",
+ ["tam" ] = "tamil",
+ ["tat" ] = "tatar",
+ ["tcr" ] = "th-cree",
+ ["tdd" ] = "dehong dai",
+ ["tel" ] = "telugu",
+ ["tet" ] = "tetum",
+ ["tgl" ] = "tagalog",
+ ["tgn" ] = "tongan",
+ ["tgr" ] = "tigre",
+ ["tgy" ] = "tigrinya",
+ ["tha" ] = "thai",
+ ["tht" ] = "tahitian",
+ ["tib" ] = "tibetan",
+ ["tiv" ] = "tiv",
+ ["tkm" ] = "turkmen",
+ ["tmh" ] = "tamashek",
+ ["tmn" ] = "temne",
+ ["tna" ] = "tswana",
+ ["tne" ] = "tundra nenets",
+ ["tng" ] = "tonga",
+ ["tod" ] = "todo",
+ ["tod0"] = "toma",
+ ["tpi" ] = "tok pisin",
+ ["trk" ] = "turkish",
+ ["tsg" ] = "tsonga",
+ ["tua" ] = "turoyo aramaic",
+ ["tul" ] = "tulu",
+ ["tuv" ] = "tuvin",
+ ["tvl" ] = "tuvalu",
+ ["twi" ] = "twi",
+ ["tyz" ] = "tày",
+ ["tzm" ] = "tamazight",
+ ["tzo" ] = "tzotzil",
+ ["udm" ] = "udmurt",
+ ["ukr" ] = "ukrainian",
+ ["umb" ] = "umbundu",
+ ["urd" ] = "urdu",
+ ["usb" ] = "upper sorbian",
+ ["uyg" ] = "uyghur",
+ ["uzb" ] = "uzbek",
+ ["vec" ] = "venetian",
+ ["ven" ] = "venda",
+ ["vit" ] = "vietnamese",
+ ["vol" ] = "volapük",
+ ["vro" ] = "võro",
+ ["wa" ] = "wa",
+ ["wag" ] = "wagdi",
+ ["war" ] = "waray-waray",
+ ["wcr" ] = "west-cree",
+ ["wel" ] = "welsh",
+ ["wlf" ] = "wolof",
+ ["wln" ] = "walloon",
+ ["xbd" ] = "lü",
+ ["xhs" ] = "xhosa",
+ ["xjb" ] = "minjangbal",
+ ["xog" ] = "soga",
+ ["xpe" ] = "kpelle (liberia)",
+ ["yak" ] = "sakha",
+ ["yao" ] = "yao",
+ ["yap" ] = "yapese",
+ ["yba" ] = "yoruba",
+ ["ycr" ] = "y-cree",
+ ["yic" ] = "yi classic",
+ ["yim" ] = "yi modern",
+ ["zea" ] = "zealandic",
+ ["zgh" ] = "standard morrocan tamazigh",
+ ["zha" ] = "zhuang",
+ ["zhh" ] = "chinese, hong kong sar",
+ ["zhp" ] = "chinese phonetic",
+ ["zhs" ] = "chinese simplified",
+ ["zht" ] = "chinese traditional",
+ ["znd" ] = "zande",
+ ["zul" ] = "zulu",
+ ["zza" ] = "zazaki",
+}
+
+local features = allocate {
+ ['aalt'] = 'access all alternates',
+ ['abvf'] = 'above-base forms',
+ ['abvm'] = 'above-base mark positioning',
+ ['abvs'] = 'above-base substitutions',
+ ['afrc'] = 'alternative fractions',
+ ['akhn'] = 'akhands',
+ ['blwf'] = 'below-base forms',
+ ['blwm'] = 'below-base mark positioning',
+ ['blws'] = 'below-base substitutions',
+ ['c2pc'] = 'petite capitals from capitals',
+ ['c2sc'] = 'small capitals from capitals',
+ ['calt'] = 'contextual alternates',
+ ['case'] = 'case-sensitive forms',
+ ['ccmp'] = 'glyph composition/decomposition',
+ ['cfar'] = 'conjunct form after ro',
+ ['cjct'] = 'conjunct forms',
+ ['clig'] = 'contextual ligatures',
+ ['cpct'] = 'centered cjk punctuation',
+ ['cpsp'] = 'capital spacing',
+ ['cswh'] = 'contextual swash',
+ ['curs'] = 'cursive positioning',
+ ['dflt'] = 'default processing',
+ ['dist'] = 'distances',
+ ['dlig'] = 'discretionary ligatures',
+ ['dnom'] = 'denominators',
+ ['dtls'] = 'dotless forms', -- math
+ ['expt'] = 'expert forms',
+ ['falt'] = 'final glyph alternates',
+ ['fin2'] = 'terminal forms #2',
+ ['fin3'] = 'terminal forms #3',
+ ['fina'] = 'terminal forms',
+ ['flac'] = 'flattened accents over capitals', -- math
+ ['frac'] = 'fractions',
+ ['fwid'] = 'full width',
+ ['half'] = 'half forms',
+ ['haln'] = 'halant forms',
+ ['halt'] = 'alternate half width',
+ ['hist'] = 'historical forms',
+ ['hkna'] = 'horizontal kana alternates',
+ ['hlig'] = 'historical ligatures',
+ ['hngl'] = 'hangul',
+ ['hojo'] = 'hojo kanji forms',
+ ['hwid'] = 'half width',
+ ['init'] = 'initial forms',
+ ['isol'] = 'isolated forms',
+ ['ital'] = 'italics',
+ ['jalt'] = 'justification alternatives',
+ ['jp04'] = 'jis2004 forms',
+ ['jp78'] = 'jis78 forms',
+ ['jp83'] = 'jis83 forms',
+ ['jp90'] = 'jis90 forms',
+ ['kern'] = 'kerning',
+ ['lfbd'] = 'left bounds',
+ ['liga'] = 'standard ligatures',
+ ['ljmo'] = 'leading jamo forms',
+ ['lnum'] = 'lining figures',
+ ['locl'] = 'localized forms',
+ ['ltra'] = 'left-to-right alternates',
+ ['ltrm'] = 'left-to-right mirrored forms',
+ ['mark'] = 'mark positioning',
+ ['med2'] = 'medial forms #2',
+ ['medi'] = 'medial forms',
+ ['mgrk'] = 'mathematical greek',
+ ['mkmk'] = 'mark to mark positioning',
+ ['mset'] = 'mark positioning via substitution',
+ ['nalt'] = 'alternate annotation forms',
+ ['nlck'] = 'nlc kanji forms',
+ ['nukt'] = 'nukta forms',
+ ['numr'] = 'numerators',
+ ['onum'] = 'old style figures',
+ ['opbd'] = 'optical bounds',
+ ['ordn'] = 'ordinals',
+ ['ornm'] = 'ornaments',
+ ['palt'] = 'proportional alternate width',
+ ['pcap'] = 'petite capitals',
+ ['pkna'] = 'proportional kana',
+ ['pnum'] = 'proportional figures',
+ ['pref'] = 'pre-base forms',
+ ['pres'] = 'pre-base substitutions',
+ ['pstf'] = 'post-base forms',
+ ['psts'] = 'post-base substitutions',
+ ['pwid'] = 'proportional widths',
+ ['qwid'] = 'quarter widths',
+ ['rand'] = 'randomize',
+ ['rclt'] = 'required contextual alternates',
+ ['rkrf'] = 'rakar forms',
+ ['rlig'] = 'required ligatures',
+ ['rphf'] = 'reph form',
+ ['rtbd'] = 'right bounds',
+ ['rtla'] = 'right-to-left alternates',
+ ['rtlm'] = 'right to left math', -- math
+ ['ruby'] = 'ruby notation forms',
+ ['salt'] = 'stylistic alternates',
+ ['sinf'] = 'scientific inferiors',
+ ['size'] = 'optical size',
+ ['smcp'] = 'small capitals',
+ ['smpl'] = 'simplified forms',
+ -- ['ss01'] = 'stylistic set 1',
+ -- ['ss02'] = 'stylistic set 2',
+ -- ['ss03'] = 'stylistic set 3',
+ -- ['ss04'] = 'stylistic set 4',
+ -- ['ss05'] = 'stylistic set 5',
+ -- ['ss06'] = 'stylistic set 6',
+ -- ['ss07'] = 'stylistic set 7',
+ -- ['ss08'] = 'stylistic set 8',
+ -- ['ss09'] = 'stylistic set 9',
+ -- ['ss10'] = 'stylistic set 10',
+ -- ['ss11'] = 'stylistic set 11',
+ -- ['ss12'] = 'stylistic set 12',
+ -- ['ss13'] = 'stylistic set 13',
+ -- ['ss14'] = 'stylistic set 14',
+ -- ['ss15'] = 'stylistic set 15',
+ -- ['ss16'] = 'stylistic set 16',
+ -- ['ss17'] = 'stylistic set 17',
+ -- ['ss18'] = 'stylistic set 18',
+ -- ['ss19'] = 'stylistic set 19',
+ -- ['ss20'] = 'stylistic set 20',
+ ['ssty'] = 'script style', -- math
+ ['stch'] = 'stretching glyph decomposition',
+ ['subs'] = 'subscript',
+ ['sups'] = 'superscript',
+ ['swsh'] = 'swash',
+ ['titl'] = 'titling',
+ ['tjmo'] = 'trailing jamo forms',
+ ['tnam'] = 'traditional name forms',
+ ['tnum'] = 'tabular figures',
+ ['trad'] = 'traditional forms',
+ ['twid'] = 'third widths',
+ ['unic'] = 'unicase',
+ ['valt'] = 'alternate vertical metrics',
+ ['vatu'] = 'vattu variants',
+ ['vert'] = 'vertical writing',
+ ['vhal'] = 'alternate vertical half metrics',
+ ['vjmo'] = 'vowel jamo forms',
+ ['vkna'] = 'vertical kana alternates',
+ ['vkrn'] = 'vertical kerning',
+ ['vpal'] = 'proportional alternate vertical metrics',
+ ['vrt2'] = 'vertical rotation',
+ ['zero'] = 'slashed zero',
+
+ ['trep'] = 'traditional tex replacements',
+ ['tlig'] = 'traditional tex ligatures',
+
+ ['ss..'] = 'stylistic set ..',
+ ['cv..'] = 'character variant ..',
+ ['js..'] = 'justification ..',
+
+ ["dv.."] = "devanagari ..",
+ ["ml.."] = "malayalam ..",
+}
+
+local baselines = allocate {
+ ['hang'] = 'hanging baseline',
+ ['icfb'] = 'ideographic character face bottom edge baseline',
+ ['icft'] = 'ideographic character face tope edige baseline',
+ ['ideo'] = 'ideographic em-box bottom edge baseline',
+ ['idtp'] = 'ideographic em-box top edge baseline',
+ ['math'] = 'mathematical centered baseline',
+ ['romn'] = 'roman baseline'
+}
+
+tables.scripts = scripts
+tables.languages = languages
+tables.features = features
+tables.baselines = baselines
+
+local acceptscripts = true directives.register("otf.acceptscripts", function(v) acceptscripts = v end)
+local acceptlanguages = true directives.register("otf.acceptlanguages", function(v) acceptlanguages = v end)
+
+local report_checks = logs.reporter("fonts","checks")
+
+-- hm, we overload the metatables
+
+if otffeatures.features then
+ for k, v in next, otffeatures.features do
+ features[k] = v
+ end
+ otffeatures.features = features
+end
+
+local function swapped(h)
+ local r = { }
+ for k, v in next, h do
+ r[gsub(v,"[^a-z0-9]","")] = k -- is already lower
+ end
+ return r
+end
+
+local verbosescripts = allocate(swapped(scripts ))
+local verboselanguages = allocate(swapped(languages))
+local verbosefeatures = allocate(swapped(features ))
+local verbosebaselines = allocate(swapped(baselines))
+
+-- lets forget about trailing spaces
+
+local function resolve(t,k)
+ if k then
+ k = gsub(lower(k),"[^a-z0-9]","")
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ end
+end
+
+setmetatableindex(verbosescripts, resolve)
+setmetatableindex(verboselanguages, resolve)
+setmetatableindex(verbosefeatures, resolve)
+setmetatableindex(verbosebaselines, resolve)
+
+-- We could optimize the next lookups by using an extra metatable and storing
+-- already found values but in practice there are not that many lookups so
+-- it's never a bottleneck.
+
+setmetatableindex(scripts, function(t,k)
+ if k then
+ k = lower(k)
+ if k == "dflt" then
+ return k
+ end
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ k = gsub(k," ","")
+ v = rawget(t,v)
+ if v then
+ return v
+ elseif acceptscripts then
+ report_checks("registering extra script %a",k)
+ rawset(t,k,k)
+ return k
+ end
+ end
+ return "dflt"
+end)
+
+setmetatableindex(languages, function(t,k)
+ if k then
+ k = lower(k)
+ if k == "dflt" then
+ return k
+ end
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ k = gsub(k," ","")
+ v = rawget(t,v)
+ if v then
+ return v
+ elseif acceptlanguages then
+ report_checks("registering extra language %a",k)
+ rawset(t,k,k)
+ return k
+ end
+ end
+ return "dflt"
+end)
+
+setmetatablenewindex(languages, "ignore")
+setmetatablenewindex(baselines, "ignore")
+setmetatablenewindex(baselines, "ignore")
+
+local function resolve(t,k)
+ if k then
+ k = lower(k)
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ k = gsub(k," ","")
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ local tag, dd = match(k,"(..)(%d+)")
+ if tag and dd then
+ local v = rawget(t,tag)
+ if v then
+ return v -- return format(v,tonumber(dd)) -- old way
+ else
+ local v = rawget(t,tag.."..") -- nicer in overview
+ if v then
+ return (gsub(v,"%.%.",tonumber(dd))) -- new way
+ end
+ end
+ end
+ end
+ return k -- "dflt"
+end
+
+setmetatableindex(features, resolve)
+
+local function assign(t,k,v)
+ if k and v then
+ v = lower(v)
+ rawset(t,k,v) -- rawset ?
+ -- rawset(features,gsub(v,"[^a-z0-9]",""),k) -- why ? old code
+ end
+end
+
+setmetatablenewindex(features, assign)
+
+local checkers = {
+ rand = function(v)
+ return v == true and "random" or v
+ end
+}
+
+-- Keep this:
+--
+-- function otf.features.normalize(features)
+-- if features then
+-- local h = { }
+-- for k, v in next, features do
+-- k = lower(k)
+-- if k == "language" then
+-- v = gsub(lower(v),"[^a-z0-9]","")
+-- h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds
+-- elseif k == "script" then
+-- v = gsub(lower(v),"[^a-z0-9]","")
+-- h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
+-- else
+-- if type(v) == "string" then
+-- local b = is_boolean(v)
+-- if type(b) == "nil" then
+-- v = tonumber(v) or lower(v)
+-- else
+-- v = b
+-- end
+-- end
+-- if not rawget(features,k) then
+-- k = rawget(verbosefeatures,k) or k
+-- end
+-- local c = checkers[k]
+-- h[k] = c and c(v) or v
+-- end
+-- end
+-- return h
+-- end
+-- end
+
+-- inspect(fonts.handlers.otf.statistics.usedfeatures)
+
+if not storage then
+ return
+end
+
+local usedfeatures = statistics.usedfeatures or { }
+statistics.usedfeatures = usedfeatures
+
+table.setmetatableindex(usedfeatures, function(t,k) if k then local v = { } t[k] = v return v end end) -- table.autotable
+
+storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.statistics.usedfeatures" )
+
+function otffeatures.normalize(features)
+ if features then
+ local h = { }
+ for key, value in next, features do
+ local k = lower(key)
+ if k == "language" then
+ local v = gsub(lower(value),"[^a-z0-9]","")
+ h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds
+ elseif k == "script" then
+ local v = gsub(lower(value),"[^a-z0-9]","")
+ h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
+ else
+ local uk = usedfeatures[key]
+ local uv = uk[value]
+ if uv then
+ -- report_checks("feature value %a first seen at %a",value,key)
+ else
+ uv = tonumber(value) -- before boolean as there we also handle 0/1
+ if uv then
+ -- we're okay
+ elseif type(value) == "string" then
+ local b = is_boolean(value)
+ if type(b) == "nil" then
+ uv = lower(value)
+ else
+ uv = b
+ end
+ else
+ uv = value
+ end
+ if not rawget(features,k) then
+ k = rawget(verbosefeatures,k) or k
+ end
+ local c = checkers[k]
+ if c then
+ uv = c(uv) or vc
+ end
+ uk[value] = uv
+ end
+ h[k] = uv
+ end
+ end
+ return h
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua
new file mode 100644
index 00000000000..3b6d8ea53c7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua
@@ -0,0 +1,2157 @@
+if not modules then modules = { } end modules ['font-oup'] = {
+ 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, type = next, type
+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 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 doduplicates = true -- can become an option (pseudo feature)
+
+local function replaced(list,index,replacement)
+ if type(list) == "number" then
+ return replacement
+ elseif type(replacement) == "table" then
+ local t = { }
+ local n = index-1
+ for i=1,n do
+ t[i] = list[i]
+ end
+ for i=1,#replacement do
+ n = n + 1
+ t[n] = replacement[i]
+ end
+ for i=index+1,#list do
+ n = n + 1
+ t[n] = list[i]
+ end
+ else
+ list[index] = replacement
+ return list
+ end
+end
+
+local function unifyresources(fontdata,indices)
+ local descriptions = fontdata.descriptions
+ local resources = fontdata.resources
+ if not descriptions or not resources then
+ return
+ end
+ --
+ local variants = fontdata.resources.variants
+ if variants then
+ for selector, unicodes in next, variants do
+ for unicode, index in next, unicodes do
+ unicodes[unicode] = indices[index]
+ end
+ end
+ end
+ --
+ local function remark(marks)
+ if marks then
+ local newmarks = { }
+ for k, v in next, marks do
+ local u = indices[k]
+ if u then
+ newmarks[u] = v
+ else
+ report("discarding mark %i",k)
+ end
+ end
+ return newmarks
+ end
+ end
+ --
+ local marks = resources.marks
+ if marks then
+ resources.marks = remark(marks)
+ end
+ --
+ local markclasses = resources.markclasses
+ if markclasses then
+ for class, marks in next, markclasses do
+ markclasses[class] = remark(marks)
+ end
+ end
+ --
+ local marksets = resources.marksets
+ if marksets then
+ for class, marks in next, marksets do
+ marksets[class] = remark(marks)
+ end
+ end
+ --
+ local done = { } -- we need to deal with shared !
+ --
+ local duplicates = doduplicates and resources.duplicates
+ if duplicates and not next(duplicates) then
+ duplicates = false
+ end
+ --
+ local function recover(cover) -- can be packed
+ for i=1,#cover do
+ local c = cover[i]
+ if not done[c] then
+ local t = { }
+ for k, v in next, c do
+ t[indices[k]] = v
+ end
+ cover[i] = t
+ done[c] = d
+ end
+ end
+ end
+ --
+ local function recursed(c) -- ligs are not packed
+ local t = { }
+ for g, d in next, c do
+ if type(d) == "table" then
+ t[indices[g]] = recursed(d)
+ else
+ t[g] = indices[d] -- ligature
+ end
+ end
+ return t
+ end
+ --
+ -- the duplicates need checking (probably only in cjk fonts): currently we only check
+ -- gsub_single, gsub_alternate, gsub_multiple, gpos_single and gpos_cursive
+ --
+ local function unifythem(sequences)
+ if not sequences then
+ return
+ end
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ local features = sequence.features
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gsub_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]
+ local ud1 = indices[d1]
+ t1[ug1] = ud1
+ --
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ for u in next, dg1 do
+ t1[u] = ud1
+ end
+ end
+ end
+ else
+ for g1, d1 in next, c do
+ t1[indices[g1]] = indices[d1]
+ end
+ end
+ done[c] = t1
+ end
+ step.coverage = t1
+ end
+ elseif kind == "gpos_pair" then
+ local c = step.coverage
+ if c then
+ local t1 = done[c]
+ 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
+ end
+ done[d1] = t2
+ end
+ t1[indices[g1]] = t2
+ end
+ done[c] = t1
+ end
+ step.coverage = t1
+ end
+ elseif kind == "gsub_ligature" then
+ local c = step.coverage
+ if c then
+ step.coverage = recursed(c)
+ end
+ elseif kind == "gsub_alternate" or kind == "gsub_multiple" 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
+ for i=1,#d1 do
+ d1[i] = indices[d1[i]]
+ 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)
+ end
+ end
+ end
+ else
+ for g1, d1 in next, c do
+ for i=1,#d1 do
+ d1[i] = indices[d1[i]]
+ end
+ t1[indices[g1]] = d1
+ 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
+ local t1 = done[c]
+ if not t1 then
+ t1 = { }
+ for g1, d1 in next, c do
+ t1[indices[g1]] = d1
+ end
+ done[c] = t1
+ end
+ step.coverage = t1
+ end
+ local c = step.baseclasses
+ if c then
+ local t1 = done[c]
+ if not t1 then
+ 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
+ end
+ done[d1] = t2
+ end
+ c[g1] = t2
+ end
+ done[c] = c
+ end
+ 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]
+ t1[ug1] = d1
+ --
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ for u in next, dg1 do
+ t1[u] = d1
+ end
+ 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
+ end
+ end
+ else
+ for g1, d1 in next, c do
+ t1[indices[g1]] = d1
+ end
+ end
+ done[c] = t1
+ end
+ step.coverage = t1
+ end
+ end
+ --
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ --
+ local before = rule.before if before then recover(before) end
+ local after = rule.after if after then recover(after) end
+ local current = rule.current if current then recover(current) end
+ --
+ local replacements = rule.replacements
+ if replacements then
+ if not done[replacements] then
+ local r = { }
+ for k, v in next, replacements do
+ r[indices[k]] = indices[v]
+ end
+ rule.replacements = r
+ done[replacements] = r
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ unifythem(resources.sequences)
+ unifythem(resources.sublookups)
+end
+
+local function copyduplicates(fontdata)
+ if doduplicates then
+ local descriptions = fontdata.descriptions
+ local resources = fontdata.resources
+ local duplicates = resources.duplicates
+ if duplicates then
+ for u, d in next, duplicates do
+ local du = descriptions[u]
+ if du then
+ local t = { f_character_y(u), "@", f_index(du.index), "->" }
+ local n = 0
+ local m = 25
+ for u in next, d do
+ if descriptions[u] then
+ if n < m then
+ t[n+4] = f_character_n(u)
+ end
+ else
+ local c = copy(du)
+ c.unicode = u -- better this way
+ descriptions[u] = c
+ if n < m then
+ t[n+4] = f_character_y(u)
+ end
+ end
+ n = n + 1
+ end
+ if n <= m then
+ report("duplicates: %i : % t",n,t)
+ else
+ report("duplicates: %i : % t ...",n,t)
+ end
+ else
+ -- what a mess
+ end
+ end
+ end
+ end
+end
+
+local ignore = { -- should we fix them?
+ ["notdef"] = true,
+ [".notdef"] = true,
+ ["null"] = true,
+ [".null"] = true,
+ ["nonmarkingreturn"] = true,
+}
+
+
+local function checklookups(fontdata,missing,nofmissing)
+ local descriptions = fontdata.descriptions
+ local resources = fontdata.resources
+ if missing and nofmissing and nofmissing <= 0 then
+ return
+ end
+ --
+ local singles = { }
+ local alternates = { }
+ local ligatures = { }
+
+ if not missing then
+ missing = { }
+ nofmissing = 0
+ for u, d in next, descriptions do
+ if not d.unicode then
+ nofmissing = nofmissing + 1
+ missing[u] = true
+ end
+ end
+ end
+
+ local function collectthem(sequences)
+ if not sequences then
+ return
+ end
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gsub_single" then
+ local c = step.coverage
+ if c then
+ singles[#singles+1] = c
+ end
+ elseif kind == "gsub_alternate" then
+ local c = step.coverage
+ if c then
+ alternates[#alternates+1] = c
+ end
+ elseif kind == "gsub_ligature" then
+ local c = step.coverage
+ if c then
+ ligatures[#ligatures+1] = c
+ end
+ end
+ end
+ end
+ end
+ end
+
+ collectthem(resources.sequences)
+ collectthem(resources.sublookups)
+
+ local loops = 0
+ while true do
+ loops = loops + 1
+ local old = nofmissing
+ for i=1,#singles do
+ local c = singles[i]
+ for g1, g2 in next, c do
+ if missing[g1] then
+ local u2 = descriptions[g2].unicode
+ if u2 then
+ missing[g1] = false
+ descriptions[g1].unicode = u2
+ nofmissing = nofmissing - 1
+ end
+ end
+ if missing[g2] then
+ local u1 = descriptions[g1].unicode
+ if u1 then
+ missing[g2] = false
+ descriptions[g2].unicode = u1
+ nofmissing = nofmissing - 1
+ end
+ end
+ end
+ end
+ for i=1,#alternates do
+ local c = alternates[i]
+ -- maybe first a g1 loop and then a g2
+ for g1, d1 in next, c do
+ if missing[g1] then
+ for i=1,#d1 do
+ local g2 = d1[i]
+ local u2 = descriptions[g2].unicode
+ if u2 then
+ missing[g1] = false
+ descriptions[g1].unicode = u2
+ nofmissing = nofmissing - 1
+ end
+ end
+ end
+ if not missing[g1] then
+ for i=1,#d1 do
+ local g2 = d1[i]
+ if missing[g2] then
+ local u1 = descriptions[g1].unicode
+ if u1 then
+ missing[g2] = false
+ descriptions[g2].unicode = u1
+ nofmissing = nofmissing - 1
+ end
+ end
+ end
+ end
+ end
+ end
+ if nofmissing <= 0 then
+ report("all done in %s loops",loops)
+ return
+ elseif old == nofmissing then
+ break
+ end
+ end
+
+ local t, n -- no need to insert/remove and allocate many times
+
+ local function recursed(c)
+ for g, d in next, c do
+ if g ~= "ligature" then
+ local u = descriptions[g].unicode
+ if u then
+ n = n + 1
+ t[n] = u
+ recursed(d)
+ n = n - 1
+ end
+ elseif missing[d] then
+ local l = { }
+ local m = 0
+ for i=1,n do
+ local u = t[i]
+ if type(u) == "table" then
+ for i=1,#u do
+ m = m + 1
+ l[m] = u[i]
+ end
+ else
+ m = m + 1
+ l[m] = u
+ end
+ end
+ missing[d] = false
+ descriptions[d].unicode = l
+ nofmissing = nofmissing - 1
+ end
+ end
+ end
+
+ if nofmissing > 0 then
+ t = { }
+ n = 0
+ local loops = 0
+ while true do
+ loops = loops + 1
+ local old = nofmissing
+ for i=1,#ligatures do
+ recursed(ligatures[i])
+ end
+ if nofmissing <= 0 then
+ report("all done in %s loops",loops)
+ return
+ elseif old == nofmissing then
+ break
+ end
+ end
+ t = nil
+ n = 0
+ end
+
+ if nofmissing > 0 then
+ local done = { }
+ for i, r in next, missing do
+ if r then
+ local name = descriptions[i].name or f_index(i)
+ if not ignore[name] then
+ done[name] = true
+ end
+ end
+ end
+ if next(done) then
+ report("not unicoded: % t",table.sortedkeys(done))
+ end
+ end
+end
+
+local function unifymissing(fontdata)
+ if not fonts.mappings then
+ require("font-map")
+ require("font-agl")
+ end
+ local unicodes = { }
+ local private = fontdata.private
+ local resources = fontdata.resources
+ resources.unicodes = unicodes
+ for unicode, d in next, fontdata.descriptions do
+ if unicode < privateoffset then
+ local name = d.name
+ if name then
+ unicodes[name] = unicode
+ end
+ end
+ end
+ fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
+ resources.unicodes = nil
+end
+
+local function unifyglyphs(fontdata,usenames)
+ local private = fontdata.private or privateoffset
+ local glyphs = fontdata.glyphs
+ local indices = { }
+ local descriptions = { }
+ local names = usenames and { }
+ local resources = fontdata.resources
+ local zero = glyphs[0]
+ local zerocode = zero.unicode
+ if not zerocode then
+ zerocode = private
+ zero.unicode = zerocode
+ private = private + 1
+ end
+ descriptions[zerocode] = zero
+ if names then
+ local name = glyphs[0].name or f_private(zerocode)
+ indices[0] = name
+ names[name] = zerocode
+ else
+ 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
+ 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
+ local name = glyph.name or f_private(unicode)
+ indices[index] = name
+ names[name] = unicode
+ 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
+ else
+ indices[index] = unicode
+ end
+ end
+ descriptions[unicode] = glyph
+ end
+ --
+ for index=1,#glyphs do
+ local math = glyphs[index].math
+ if math then
+ local list = math.vparts
+ if list then
+ for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end
+ end
+ local list = math.hparts
+ if list then
+ for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end
+ end
+ local list = math.vvariants
+ if list then
+ -- for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end
+ for i=1,#list do list[i] = indices[list[i]] end
+ end
+ local list = math.hvariants
+ if list then
+ -- for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end
+ for i=1,#list do list[i] = indices[list[i]] end
+ end
+ end
+ end
+ --
+ fontdata.private = private
+ fontdata.glyphs = nil
+ fontdata.names = names
+ fontdata.descriptions = descriptions
+ fontdata.hashmethod = hashmethod
+ --
+ 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 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
+ end
+ if d.class == "base" then
+ d.class = nil
+ c = c + 1
+ 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)
+ end
+ end
+end
+
+function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing
+ local resources = fontdata.resources
+ if resources then
+ local sequences = resources.sequences
+ if sequences then
+ local collected = { }
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ if sequence.type == "gsub_ligature" then
+ local steps = sequence.steps
+ if steps then
+ local l = { }
+ local function traverse(p,k,v)
+ if k == "ligature" then
+ collected[v] = { unpack(l) }
+ else
+ insert(l,k)
+ for k, vv in next, v do
+ traverse(p,k,vv)
+ end
+ remove(l)
+ end
+ 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
+ traverse(k,k,v)
+ end
+ end
+ end
+ end
+ end
+ end
+ if next(collected) then
+ -- remove self referring
+ -- for k, v in next, collected do
+ -- for i=1,#v do
+ -- local vi = v[i]
+ -- if vi == k then
+ -- -- report("removing self referring ligature @ slot %5X from collected (1)",k)
+ -- collected[k] = nil
+ -- end
+ -- end
+ -- end
+ while true do
+ local done = false
+ for k, v in next, collected do
+ for i=1,#v do
+ local vi = v[i]
+ if vi == k then
+ -- report("removing self referring ligature @ slot %5X from collected (2)",k)
+ collected[k] = nil
+ break
+ else
+ local c = collected[vi]
+ if c then
+ done = true
+ local t = { }
+ local n = i - 1
+ for j=1,n do
+ t[j] = v[j]
+ end
+ for j=1,#c do
+ n = n + 1
+ t[n] = c[j]
+ end
+ for j=i+1,#v do
+ n = n + 1
+ t[n] = v[j]
+ end
+ collected[k] = t
+ break
+ end
+ end
+ end
+ end
+ if not done then
+ break
+ end
+ end
+ return collected
+ end
+ end
+ end
+end
+
+function readers.rehash(fontdata,hashmethod) -- TODO: combine loops in one
+ if not (fontdata and fontdata.glyphs) then
+ return
+ end
+ if hashmethod == "indices" then
+ fontdata.hashmethod = "indices"
+ elseif hashmethod == "names" then
+ fontdata.hashmethod = "names"
+ local indices = unifyglyphs(fontdata,true)
+ unifyresources(fontdata,indices)
+ copyduplicates(fontdata)
+ unifymissing(fontdata)
+ -- stripredundant(fontdata)
+ else
+ fontdata.hashmethod = "unicode"
+ local indices = unifyglyphs(fontdata)
+ unifyresources(fontdata,indices)
+ copyduplicates(fontdata)
+ unifymissing(fontdata)
+ stripredundant(fontdata)
+ end
+ -- maybe here components
+end
+
+function readers.checkhash(fontdata)
+ local hashmethod = fontdata.hashmethod
+ if hashmethod == "unicodes" then
+ fontdata.names = nil -- just to be sure
+ elseif hashmethod == "names" and fontdata.names then
+ unifyresources(fontdata,fontdata.names)
+ copyduplicates(fontdata)
+ fontdata.hashmethod = "unicode"
+ fontdata.names = nil -- no need for it
+ else
+ readers.rehash(fontdata,"unicode")
+ end
+end
+
+function readers.addunicodetable(fontdata)
+ local resources = fontdata.resources
+ local unicodes = resources.unicodes
+ if not unicodes then
+ local descriptions = fontdata.descriptions
+ if descriptions then
+ unicodes = { }
+ resources.unicodes = unicodes
+ for u, d in next, descriptions do
+ local n = d.name
+ if n then
+ unicodes[n] = u
+ end
+ end
+ end
+ end
+end
+
+-- for the moment here:
+
+local concat, sort = table.concat, table.sort
+local next, type, tostring = next, type, tostring
+
+local criterium = 1
+local threshold = 0
+
+local trace_packing = false trackers.register("otf.packing", function(v) trace_packing = v end)
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+local function tabstr_normal(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ if type(v) == "table" then
+ s[n] = k .. ">" .. tabstr_normal(v)
+ elseif v == true then
+ s[n] = k .. "+" -- "=true"
+ elseif v then
+ s[n] = k .. "=" .. v
+ else
+ s[n] = k .. "-" -- "=false"
+ end
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+local function tabstr_flat(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ s[n] = k .. "=" .. v
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+local function tabstr_mixed(t) -- indexed
+ local s = { }
+ local n = #t
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ local k = t[1]
+ if k == true then
+ return "++" -- we need to distinguish from "true"
+ elseif k == false then
+ return "--" -- we need to distinguish from "false"
+ else
+ return tostring(k) -- number or string
+ end
+ else
+ for i=1,n do
+ local k = t[i]
+ if k == true then
+ s[i] = "++" -- we need to distinguish from "true"
+ elseif k == false then
+ s[i] = "--" -- we need to distinguish from "false"
+ else
+ s[i] = k -- number or string
+ end
+ end
+ return concat(s,",")
+ end
+end
+
+local function tabstr_boolean(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ if v then
+ s[n] = k .. "+"
+ else
+ s[n] = k .. "-"
+ end
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+-- beware: we cannot unpack and repack the same table because then sharing
+-- interferes (we could catch this if needed) .. so for now: save, reload
+-- and repack in such cases (never needed anyway) .. a tricky aspect is that
+-- we then need to sort more thanks to random hashing
+
+function readers.pack(data)
+
+ if data then
+
+ local h, t, c = { }, { }, { }
+ local hh, tt, cc = { }, { }, { }
+ local nt, ntt = 0, 0
+
+ local function pack_normal(v)
+ local tag = tabstr_normal(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ local function pack_flat(v)
+ local tag = tabstr_flat(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ local function pack_boolean(v)
+ local tag = tabstr_boolean(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ local function pack_indexed(v)
+ local tag = concat(v," ")
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ local function pack_mixed(v)
+ local tag = tabstr_mixed(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ local function pack_final(v)
+ -- v == number
+ if c[v] <= criterium then
+ return t[v]
+ else
+ -- compact hash
+ local hv = hh[v]
+ if hv then
+ return hv
+ else
+ ntt = ntt + 1
+ tt[ntt] = t[v]
+ hh[v] = ntt
+ cc[ntt] = c[v]
+ return ntt
+ end
+ end
+ end
+
+ local function success(stage,pass)
+ if nt == 0 then
+ if trace_loading or trace_packing then
+ report_otf("pack quality: nothing to pack")
+ end
+ return false
+ elseif nt >= threshold then
+ local one, two, rest = 0, 0, 0
+ if pass == 1 then
+ for k,v in next, c do
+ if v == 1 then
+ one = one + 1
+ elseif v == 2 then
+ two = two + 1
+ else
+ rest = rest + 1
+ end
+ end
+ else
+ for k,v in next, cc do
+ if v > 20 then
+ rest = rest + 1
+ elseif v > 10 then
+ two = two + 1
+ else
+ one = one + 1
+ end
+ end
+ data.tables = tt
+ end
+ if trace_loading or trace_packing then
+ report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)",
+ stage, pass, one+two+rest, one, two, rest, criterium)
+ end
+ return true
+ else
+ if trace_loading or trace_packing then
+ report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)",
+ stage, pass, nt, threshold)
+ end
+ return false
+ end
+ end
+
+ local function packers(pass)
+ if pass == 1 then
+ return pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed
+ else
+ return pack_final, pack_final, pack_final, pack_final, pack_final
+ end
+ end
+
+ local resources = data.resources
+ local sequences = resources.sequences
+ local sublookups = resources.sublookups
+ local features = resources.features
+
+ local chardata = characters and characters.data
+ local descriptions = data.descriptions or data.glyphs
+
+ if not descriptions then
+ return
+ end
+
+ --
+
+ for pass=1,2 do
+
+ if trace_packing then
+ report_otf("start packing: stage 1, pass %s",pass)
+ end
+
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+
+ for unicode, description in next, descriptions do
+ local boundingbox = description.boundingbox
+ if boundingbox then
+ description.boundingbox = pack_indexed(boundingbox)
+ end
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ for tag, kern in next, kerns do
+ kerns[tag] = pack_normal(kern)
+ end
+ end
+ end
+ end
+
+ local function packthem(sequences)
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ local order = sequence.order
+ local features = sequence.features
+ local flags = sequence.flags
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gpos_pair" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ for g1, d1 in next, c do
+ c[g1] = pack_normal(d1)
+ end
+ else
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ local f = d2[1] if f then d2[1] = pack_indexed(f) end
+ local s = d2[2] if s then d2[2] = pack_indexed(s) end
+ end
+ end
+ end
+ end
+ elseif kind == "gpos_single" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ step.coverage = pack_normal(c)
+ else
+ for g1, d1 in next, c do
+ c[g1] = pack_indexed(d1)
+ end
+ end
+ end
+ elseif kind == "gpos_cursive" then
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ local f = d1[2] if f then d1[2] = pack_indexed(f) end
+ local s = d1[3] if s then d1[3] = pack_indexed(s) end
+ end
+ end
+ elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" then
+ local c = step.baseclasses
+ if c then
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ d1[g2] = pack_indexed(d2)
+ end
+ end
+ end
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ d1[2] = pack_indexed(d1[2])
+ end
+ end
+ elseif kind == "gpos_mark2ligature" then
+ local c = step.baseclasses
+ if c then
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ for g3, d3 in next, d2 do
+ d2[g3] = pack_indexed(d3)
+ end
+ end
+ end
+ end
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ d1[2] = pack_indexed(d1[2])
+ end
+ end
+ end
+ -- if ... chain ...
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local r = rule.before if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.after if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.current if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.replacements if r then rule.replacements = pack_flat (r) end -- can have holes
+ end
+ end
+ end
+ end
+ if order then
+ sequence.order = pack_indexed(order)
+ end
+ if features then
+ for script, feature in next, features do
+ features[script] = pack_normal(feature)
+ end
+ end
+ if flags then
+ sequence.flags = pack_normal(flags)
+ end
+ end
+ end
+
+ if sequences then
+ packthem(sequences)
+ end
+
+ if sublookups then
+ packthem(sublookups)
+ end
+
+ if features then
+ for k, list in next, features do
+ for feature, spec in next, list do
+ list[feature] = pack_normal(spec)
+ end
+ end
+ end
+
+ if not success(1,pass) then
+ return
+ end
+
+ end
+
+ if nt > 0 then
+
+ for pass=1,2 do
+
+ if trace_packing then
+ report_otf("start packing: stage 2, pass %s",pass)
+ end
+
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+
+ for unicode, description in next, descriptions do
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ math.kerns = pack_normal(kerns)
+ end
+ end
+ end
+
+ local function packthem(sequences)
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ local features = sequence.features
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gpos_pair" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ -- todo !
+ else
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ d1[g2] = pack_normal(d2)
+ end
+ end
+ end
+ end
+-- elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then
+-- local c = step.baseclasses
+-- for k, v in next, c do
+-- c[k] = pack_normal(v)
+-- end
+ end
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local r = rule.before if r then rule.before = pack_normal(r) end
+ local r = rule.after if r then rule.after = pack_normal(r) end
+ local r = rule.current if r then rule.current = pack_normal(r) end
+ end
+ end
+ end
+ end
+ if features then
+ sequence.features = pack_normal(features)
+ end
+ end
+ end
+ if sequences then
+ packthem(sequences)
+ end
+ if sublookups then
+ packthem(sublookups)
+ end
+ -- features
+ if not success(2,pass) then
+ -- return
+ end
+ end
+
+ for pass=1,2 do
+ if trace_packing then
+ report_otf("start packing: stage 3, pass %s",pass)
+ end
+
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+
+ local function packthem(sequences)
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ local features = sequence.features
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gpos_pair" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ -- todo !
+ else
+ for g1, d1 in next, c do
+ c[g1] = pack_normal(d1)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ if sequences then
+ packthem(sequences)
+ end
+ if sublookups then
+ packthem(sublookups)
+ end
+
+ end
+
+ end
+
+ end
+end
+
+local unpacked_mt = {
+ __index =
+ function(t,k)
+ t[k] = false
+ return k -- next time true
+ end
+}
+
+function readers.unpack(data)
+
+ if data then
+ local tables = data.tables
+ if tables then
+ local resources = data.resources
+ local descriptions = data.descriptions or data.glyphs
+ local sequences = resources.sequences
+ local sublookups = resources.sublookups
+ local features = resources.features
+ local unpacked = { }
+ setmetatable(unpacked,unpacked_mt)
+ for unicode, description in next, descriptions do
+ local tv = tables[description.boundingbox]
+ if tv then
+ description.boundingbox = tv
+ end
+ local math = description.math
+ if math then
+ local kerns = math.kerns
+ if kerns then
+ local tm = tables[kerns]
+ if tm then
+ math.kerns = tm
+ kerns = unpacked[tm]
+ end
+ if kerns then
+ for k, kern in next, kerns do
+ local tv = tables[kern]
+ if tv then
+ kerns[k] = tv
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local function unpackthem(sequences)
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local kind = sequence.type
+ local steps = sequence.steps
+ local order = sequence.order
+ local features = sequence.features
+ local flags = sequence.flags
+ local markclass = sequence.markclass
+ if steps then
+ for i=1,#steps do
+ local step = steps[i]
+ if kind == "gpos_pair" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ for g1, d1 in next, c do
+ local tv = tables[d1]
+ if tv then
+ c[g1] = tv
+ end
+ end
+ else
+ for g1, d1 in next, c do
+ local tv = tables[d1]
+ if tv then
+ c[g1] = tv
+ d1 = tv
+ end
+ for g2, d2 in next, d1 do
+ local tv = tables[d2]
+ if tv then
+ d1[g2] = tv
+ d2 = tv
+ end
+ local f = tables[d2[1]] if f then d2[1] = f end
+ local s = tables[d2[2]] if s then d2[2] = s end
+ end
+ end
+ end
+ end
+ elseif kind == "gpos_single" then
+ local c = step.coverage
+ if c then
+ if step.format == "kern" then
+ local tv = tables[c]
+ if tv then
+ step.coverage = tv
+ end
+ else
+ for g1, d1 in next, c do
+ local tv = tables[d1]
+ if tv then
+ c[g1] = tv
+ end
+ end
+ end
+ end
+ elseif kind == "gpos_cursive" then
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ local f = tables[d1[2]] if f then d1[2] = f end
+ local s = tables[d1[3]] if s then d1[3] = s end
+ end
+ end
+ elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" then
+ local c = step.baseclasses
+ if c then
+-- for k, v in next, c do
+-- local tv = tables[v]
+-- if tv then
+-- c[k] = tv
+-- end
+-- end
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ local tv = tables[d2]
+ if tv then
+ d1[g2] = tv
+ end
+ end
+ end
+ end
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ local tv = tables[d1[2]]
+ if tv then
+ d1[2] = tv
+ end
+ end
+ end
+ elseif kind == "gpos_mark2ligature" then
+ local c = step.baseclasses
+ if c then
+-- for k, v in next, c do
+-- local tv = tables[v]
+-- if tv then
+-- c[k] = tv
+-- end
+-- end
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ for g3, d3 in next, d2 do
+ local tv = tables[d2[g3]]
+ if tv then
+ d2[g3] = tv
+ end
+ end
+ end
+ end
+ end
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ local tv = tables[d1[2]]
+ if tv then
+ d1[2] = tv
+ end
+ end
+ end
+ end
+ local rules = step.rules
+ if rules then
+ for i=1,#rules do
+ local rule = rules[i]
+ local before = rule.before
+ if before then
+ local tv = tables[before]
+ if tv then
+ rule.before = tv
+ before = tv
+ end
+ for i=1,#before do
+ local tv = tables[before[i]]
+ if tv then
+ before[i] = tv
+ end
+ end
+ end
+ local after = rule.after
+ if after then
+ local tv = tables[after]
+ if tv then
+ rule.after = tv
+ after = tv
+ end
+ for i=1,#after do
+ local tv = tables[after[i]]
+ if tv then
+ after[i] = tv
+ end
+ end
+ end
+ local current = rule.current
+ if current then
+ local tv = tables[current]
+ if tv then
+ rule.current = tv
+ current = tv
+ end
+ for i=1,#current do
+ local tv = tables[current[i]]
+ if tv then
+ current[i] = tv
+ end
+ end
+ end
+ local replacements = rule.replacements
+ if replacements then
+ local tv = tables[replace]
+ if tv then
+ rule.replacements = tv
+ end
+ end
+ end
+ end
+ end
+ end
+ if features then
+ local tv = tables[features]
+ if tv then
+ sequence.features = tv
+ features = tv
+ end
+ for script, feature in next, features do
+ local tv = tables[feature]
+ if tv then
+ features[script] = tv
+ end
+ end
+ end
+ if order then
+ local tv = tables[order]
+ if tv then
+ sequence.order = tv
+ end
+ end
+ if flags then
+ local tv = tables[flags]
+ if tv then
+ sequence.flags = tv
+ end
+ end
+ end
+ end
+
+ if sequences then
+ unpackthem(sequences)
+ end
+
+ if sublookups then
+ unpackthem(sublookups)
+ end
+
+ if features then
+ for k, list in next, features do
+ for feature, spec in next, list do
+ local tv = tables[spec]
+ if tv then
+ list[feature] = tv
+ end
+ end
+ end
+ end
+
+ data.tables = nil
+ end
+ end
+end
+
+local mt = {
+ __index = function(t,k) -- maybe set it
+ if k == "height" then
+ local ht = t.boundingbox[4]
+ return ht < 0 and 0 or ht
+ elseif k == "depth" then
+ local dp = -t.boundingbox[2]
+ return dp < 0 and 0 or dp
+ elseif k == "width" then
+ return 0
+ elseif k == "name" then -- or maybe uni*
+ return forcenotdef and ".notdef"
+ end
+ end
+}
+
+local function sameformat(sequence,steps,first,nofsteps,kind)
+ return true
+end
+
+local function mergesteps_1(lookup,strict)
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ local first = steps[1]
+ if strict then
+ 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)
+ return 0
+ end
+ end
+ end
+ report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ 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
+ end
+ end
+ end
+ lookup.nofsteps = 1
+ lookup.merged = true
+ lookup.steps = { first }
+ return nofsteps - 1
+end
+
+
+local function mergesteps_2(lookup,strict) -- pairs
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ local first = steps[1]
+ if strict then
+ 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)
+ return 0
+ end
+ end
+ end
+ report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ 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 k, v in next, v do
+ if not tk[k] then
+ tk[k] = v
+ end
+ end
+ else
+ target[k] = v
+ end
+ end
+ end
+ lookup.nofsteps = 1
+ lookup.steps = { first }
+ return nofsteps - 1
+end
+
+
+local function mergesteps_3(lookup,strict) -- marks
+ 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)
+ local baseclasses = { }
+ local coverage = { }
+ local used = { }
+ for i=1,nofsteps do
+ local offset = i*10
+ local step = steps[i]
+ for k, v in sortedhash(step.baseclasses) do
+ baseclasses[offset+k] = v
+ end
+ for k, v in next, step.coverage do
+ local tk = coverage[k]
+ if tk then
+ for k, v in next, v do
+ if not tk[k] then
+ tk[k] = v
+ local c = offset + v[1]
+ v[1] = c
+ if not used[c] then
+ used[c] = true
+ end
+ end
+ end
+ else
+ coverage[k] = v
+ local c = offset + v[1]
+ v[1] = c
+ if not used[c] then
+ used[c] = true
+ end
+ end
+ end
+ end
+ for k, v in next, baseclasses do
+ if not used[k] then
+ baseclasses[k] = nil
+ report("discarding not used baseclass %i",k)
+ end
+ end
+ first.baseclasses = baseclasses
+ first.coverage = coverage
+ lookup.nofsteps = 1
+ lookup.steps = { first }
+ return nofsteps - 1
+end
+
+local function nested(old,new)
+ for k, v in next, old do
+ if k == "ligature" then
+ if not new.ligature then
+ new.ligature = v
+ end
+ else
+ local n = new[k]
+ if n then
+ nested(v,n)
+ else
+ new[k] = v
+ end
+ end
+ end
+end
+
+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)
+ 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
+ end
+ end
+ end
+ lookup.nofsteps = 1
+ lookup.steps = { first }
+ return nofsteps - 1
+end
+
+local function checkkerns(lookup)
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ for i=1,nofsteps do
+ local step = steps[i]
+ if step.format == "pair" then
+ local coverage = step.coverage
+ local kerns = true
+ for g1, d1 in next, coverage do
+ if d1[1] ~= 0 or d1[2] ~= 0 or d1[4] ~= 0 then
+ kerns = false
+ break
+ end
+ end
+ if kerns then
+ report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ for g1, d1 in next, coverage do
+ coverage[g1] = d1[3]
+ end
+ step.format = "kern"
+ end
+ end
+ end
+end
+
+local function checkpairs(lookup)
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ local kerned = 0
+ for i=1,nofsteps do
+ local step = steps[i]
+ if step.format == "pair" then
+ local coverage = step.coverage
+ local kerns = true
+ for g1, d1 in next, coverage do
+ for g2, d2 in next, d1 do
+ if d2[2] then
+ kerns = false
+ break
+ else
+ local v = d2[1]
+ if v[1] ~= 0 or v[2] ~= 0 or v[4] ~= 0 then
+ kerns = false
+ break
+ end
+ end
+ end
+ end
+ if kerns then
+ report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ for g1, d1 in next, coverage do
+ for g2, d2 in next, d1 do
+ d1[g2] = d2[1][3]
+ end
+ end
+ step.format = "kern"
+ kerned = kerned + 1
+ end
+ end
+ end
+ return kerned
+end
+
+function readers.compact(data)
+ if not data or data.compacted then
+ return
+ else
+ data.compacted = true
+ end
+ local resources = data.resources
+ local merged = 0
+ local kerned = 0
+ local allsteps = 0
+ local function compact(what)
+ local lookups = resources[what]
+ if lookups then
+ for i=1,#lookups do
+ local lookup = lookups[i]
+ local nofsteps = lookup.nofsteps
+ allsteps = allsteps + nofsteps
+ if nofsteps > 1 then
+ local kind = lookup.type
+ if kind == "gsub_single" or kind == "gsub_alternate" or kind == "gsub_multiple" then
+ merged = merged + mergesteps_1(lookup)
+ elseif kind == "gsub_ligature" then
+ merged = merged + mergesteps_4(lookup)
+ elseif kind == "gpos_single" then
+ merged = merged + mergesteps_1(lookup,true)
+ checkkerns(lookup)
+ elseif kind == "gpos_pair" then
+ merged = merged + mergesteps_2(lookup,true)
+ kerned = kerned + checkpairs(lookup)
+ elseif kind == "gpos_cursive" then
+ merged = merged + mergesteps_2(lookup)
+ elseif kind == "gpos_mark2mark" or kind == "gpos_mark2base" or kind == "gpos_mark2ligature" then
+ merged = merged + mergesteps_3(lookup)
+ end
+ end
+ end
+ else
+ report("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)
+ end
+end
+
+function readers.expand(data)
+ if not data or data.expanded then
+ return
+ else
+ data.expanded = true
+ end
+ local resources = data.resources
+ local sublookups = resources.sublookups
+ local sequences = resources.sequences -- were one level up
+ local markclasses = resources.markclasses
+ local descriptions = data.descriptions
+ if descriptions then
+ local defaultwidth = resources.defaultwidth or 0
+ local defaultheight = resources.defaultheight or 0
+ local defaultdepth = resources.defaultdepth or 0
+ local basename = trace_markwidth and file.basename(resources.filename)
+ for u, d in next, descriptions do
+ local bb = d.boundingbox
+ local wd = d.width
+ if not wd then
+ -- 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)
+ end
+ if bb then
+ local ht = bb[4]
+ local dp = -bb[2]
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ end
+ end
+ end
+ local function expandlookups(sequences)
+ if sequences then
+ -- we also need to do sublookups
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local steps = sequence.steps
+ if steps then
+ local kind = sequence.type
+ local markclass = sequence.markclass
+ if markclass then
+ if not markclasses then
+ report_warning("missing markclasses")
+ sequence.markclass = false
+ else
+ sequence.markclass = markclasses[markclass]
+ end
+ end
+ for i=1,sequence.nofsteps do
+ local step = steps[i]
+ local baseclasses = step.baseclasses
+ if baseclasses then
+ local coverage = step.coverage
+ for k, v in next, coverage do
+ v[1] = baseclasses[v[1]] -- slot 1 is a placeholder
+ end
+ elseif kind == "gpos_cursive" then
+ local coverage = step.coverage
+ for k, v in next, coverage do
+ v[1] = coverage -- slot 1 is a placeholder
+ end
+ end
+ local rules = step.rules
+ if rules then
+ local rulehash = { }
+ local rulesize = 0
+ local coverage = { }
+ local lookuptype = sequence.type
+ step.coverage = coverage -- combined hits
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local current = rule.current
+ local before = rule.before
+ local after = rule.after
+ local replacements = rule.replacements or false
+ local sequence = { }
+ local nofsequences = 0
+ if before then
+ for n=1,#before do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = before[n]
+ end
+ end
+ local start = nofsequences + 1
+ for n=1,#current do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = current[n]
+ end
+ local stop = nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = after[n]
+ end
+ end
+ local lookups = rule.lookups or false
+ local subtype = nil
+ if lookups then
+ for k, v in next, lookups do
+ local lookup = sublookups[v]
+ if lookup then
+ lookups[k] = lookup
+ if not subtype then
+ subtype = lookup.type
+ end
+ else
+ -- already expanded
+ end
+ end
+ end
+ if sequence[1] then -- we merge coverage into one
+ rulesize = rulesize + 1
+ rulehash[rulesize] = {
+ nofrules, -- 1
+ lookuptype, -- 2
+ sequence, -- 3
+ start, -- 4
+ stop, -- 5
+ lookups, -- 6 (6/7 also signal of what to do)
+ replacements, -- 7
+ subtype, -- 8
+ }
+ for unic in next, sequence[start] do
+ local cu = coverage[unic]
+ if not cu then
+ coverage[unic] = rulehash -- can now be done cleaner i think
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ expandlookups(sequences)
+ expandlookups(sublookups)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-pat.lua b/Master/texmf-dist/tex/context/base/mkiv/font-pat.lua
new file mode 100644
index 00000000000..357b12ea0a0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-pat.lua
@@ -0,0 +1,92 @@
+if not modules then modules = { } end modules ['font-pat'] = {
+ 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"
+}
+
+-- This functiononality is nowadays provided via lfg files so what you see here
+-- is more an example.
+
+local match, lower = string.match, string.lower
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local patches = otf.enhancers.patches
+local register = patches.register
+local report = patches.report
+
+-- For some reason (either it's a bug in the font, or it's a problem in the
+-- library) the palatino arabic fonts don't have the mkmk features properly
+-- set up.
+
+register("after","rehash features","^palatino.*arabic", function (data,filename)
+ local gpos = data.gpos
+ if gpos then
+ for k=1,#gpos do
+ local v = gpos[k]
+ if not v.features and v.type == "gpos_mark2mark" then
+ report("mkmk feature, name %a", v.name)
+ v.features = {
+ {
+ scripts = {
+ arab = {
+ ["ara "] = true,
+ ["far "] = true,
+ ["urd "] = true,
+ ["dflt"] = true,
+ }
+ },
+ tag = "mkmk",
+ }
+ }
+ end
+ end
+ end
+end)
+
+-- -- this code is now in lm-math.lfg
+--
+-- local function patch(data,filename)
+-- local uni_to_ind = data.map.map
+-- if not uni_to_ind[0x391] then
+-- -- beware, this is a hack, features for latin often don't apply to greek
+-- -- but lm has not much features anyway (and only greek for math)
+-- report("adding 13 greek capitals")
+-- uni_to_ind[0x391] = uni_to_ind[0x41]
+-- uni_to_ind[0x392] = uni_to_ind[0x42]
+-- uni_to_ind[0x395] = uni_to_ind[0x45]
+-- uni_to_ind[0x397] = uni_to_ind[0x48]
+-- uni_to_ind[0x399] = uni_to_ind[0x49]
+-- uni_to_ind[0x39A] = uni_to_ind[0x4B]
+-- uni_to_ind[0x39C] = uni_to_ind[0x4D]
+-- uni_to_ind[0x39D] = uni_to_ind[0x4E]
+-- uni_to_ind[0x39F] = uni_to_ind[0x4F]
+-- uni_to_ind[0x3A1] = uni_to_ind[0x52]
+-- uni_to_ind[0x3A4] = uni_to_ind[0x54]
+-- uni_to_ind[0x3A7] = uni_to_ind[0x58]
+-- uni_to_ind[0x396] = uni_to_ind[0x5A]
+-- end
+-- end
+--
+-- register("after","prepare glyphs","^lmroman", patch)
+-- register("after","prepare glyphs","^lmsans", patch)
+-- register("after","prepare glyphs","^lmtypewriter",patch)
+--
+-- -- this code is now in cambria-math.lfg and asana-math.lfg
+--
+-- local function patch_domh(data,filename,threshold)
+-- local m = data.metadata.math
+-- if m then
+-- local d = m.DisplayOperatorMinHeight or 0
+-- if d < threshold then
+-- report("DisplayOperatorMinHeight(%s -> %s)",d,threshold)
+-- m.DisplayOperatorMinHeight = threshold
+-- end
+-- end
+-- end
+--
+-- register("after","check math parameters","cambria", function(data,filename) patch_domh(data,filename,2800) end)
+-- register("after","check math parameters","cambmath",function(data,filename) patch_domh(data,filename,2800) end)
+-- register("after","check math parameters","asana", function(data,filename) patch_domh(data,filename,1350) end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv
new file mode 100644
index 00000000000..3b3a76d9c0e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv
@@ -0,0 +1,772 @@
+%D \module
+%D [ file=font-pre,
+%D version=2012.01.04, % moved from font-ini
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Predefined,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Predefined}
+
+\unprotect
+
+%D A basic set of features is defined here.
+
+% beware, base mode + dynamics can give weird effects
+
+% rlig ccmp
+
+\definefontfeature
+ [always]
+ [mode=node, % we had 'auto', but let's try 'node' for a while and see what the impact is
+ script=auto, % on speed; 'base' just doesn't play well with dynamics; some day we can even
+ autoscript=position,
+ autolanguage=position,
+ kern=yes, % consider skipping the base passes when no base mode is used
+ mark=yes,
+ mkmk=yes,
+ curs=yes]
+
+\definefontfeature
+ [default]
+ [always]
+ [liga=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [smallcaps]
+ [always]
+ [smcp=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [oldstyle]
+ [always]
+ [onum=yes,
+ liga=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [inlinenumbers]
+ [pnum=yes,
+ tnum=no]
+
+\definefontfeature
+ [tabularnumbers]
+ [tnum=yes,
+ pnum=no]
+
+\definefontfeature
+ [oldstylenumbers]
+ [onum=yes]
+
+\definefontfeature
+ [zero]
+ [zero=yes]
+
+% \definefontfeature
+% [newstyle]
+% [onum=no]
+
+\definefontfeature % == default unless redefined
+ [ligatures]
+ [always]
+ [liga=yes,
+ tlig=yes,
+ trep=yes]
+
+\definefontfeature
+ [letterspacing]
+ [liga=no,
+ rlig=no,
+ clig=no,
+ dlig=no,
+ ccmp=yes,
+ keepligatures=auto]
+
+\definefontfeature % can be used for type1 fonts
+ [complete]
+ [always]
+ [compose=yes,
+ liga=yes,
+ tlig=yes,
+ trep=yes]
+
+\definefontfeature
+ [none]
+ [mode=none,
+ features=no]
+
+\definefontfeature
+ [semitic-complete]
+ [mode=node,analyze=yes,language=dflt,ccmp=yes,
+ autoscript=position,autolanguage=position,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes,
+ liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes]
+
+\definefontfeature
+ [semitic-simple]
+ [mode=node,analyze=yes,language=dflt,ccmp=yes,
+ autoscript=position,autolanguage=position,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes,
+ rlig=yes,calt=yes]
+
+\definefontfeature
+ [arabic]
+ [semitic-complete]
+ [script=arab]
+
+\definefontfeature
+ [hebrew]
+ [semitic-complete]
+ [script=hebr]
+
+\definefontfeature
+ [simplearabic]
+ [semitic-simple]
+ [script=arab]
+
+\definefontfeature
+ [simplehebrew]
+ [semitic-simple]
+ [script=hebr]
+
+% \definefont [DevaOne] [file:chandas.ttf*devanagari-one at 12pt]
+% \definefont [DevaTwo] [file:kokila.ttf*devanagari-two at 18pt]
+
+\definefontfeature
+ [devanagari-one]
+ [mode=node,
+ language=dflt,
+ script=deva,
+ nukt=yes,
+ akhn=yes,
+ rphf=yes,
+ blwf=yes,
+ half=yes,
+ vatu=yes,
+ pres=yes,
+ abvs=yes,
+ blws=yes,
+ psts=yes,
+ haln=yes,
+ abvm=yes,
+ blwm=yes,
+ dist=yes]
+
+\definefontfeature
+ [devanagari-two]
+ [devanagari-one]
+ [script=dev2,
+ locl=yes,
+ pref=yes,
+ rkrf=yes,
+ pstf=yes,
+ cjct=yes,
+ init=yes,
+ calt=yes,
+ kern=yes]
+
+\definefontfeature
+ [malayalam-one]
+ [mode=node,
+ language=dflt,
+ script=mlym,
+ akhn=yes,
+ blwf=yes,
+ half=yes,
+ pres=yes,
+ blws=yes,
+ psts=yes,
+ haln=no]
+
+\definefontfeature
+ [malayalam-two]
+ [malayalam-one]
+ [script=mlm2]
+
+\definefontfeature
+ [jamoforms]
+ [ljmo=yes,
+ tjmo=yes,
+ vjmo=yes]
+
+% cjk
+
+% \definefontfeature
+% [japanese]
+% [default]
+% [language=jan]
+
+% \definefontfeature
+% [simplified-chinese]
+% [default]
+% [language=zhs]
+
+% \definefontfeature
+% [traditional-chinese]
+% [default]
+% [language=zht]
+
+% \definefontfeature
+% [chinese]
+% [simplified-chinese]
+
+% \definefontfeature
+% [korean]
+% [default]
+% [language=kor]
+
+% symbols:
+
+\definefontfeature
+ [dingbats]
+ [mode=base,
+ goodies=dingbats,
+ unicoding=yes]
+
+% math:
+
+\definefontfeature
+ [mathematics]
+ [mode=base,
+ liga=yes,
+ kern=yes,
+ tlig=yes,
+ trep=yes,
+ mathalternates=yes,
+ mathitalics=yes, % we pass them
+ % mathgaps=yes,
+ language=dflt,
+ script=math]
+
+\definefontfeature
+ [mathematics-l2r]
+ [mathematics]
+ []
+
+% \definefontfeature
+% [mathematics-r2l]
+% [mathematics]
+% [language=ara,
+% rtlm=yes,
+% locl=yes]
+
+\definefontfeature
+ [mathematics-r2l]
+ [mathematics]
+ [rtlm=yes,
+ %dtls=yes,
+ locl=yes]
+
+\definefontfeature[virtualmath] [mathematics] % downward compatibility
+\definefontfeature[virtualmath-l2r] [mathematics-l2r] % downward compatibility
+\definefontfeature[virtualmath-r2l] [mathematics-r2l] % downward compatibility
+
+\definefontfeature[math-text] [mathematics] [ssty=no]
+\definefontfeature[math-script] [mathematics] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript] [mathematics] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-text-l2r] [mathematics-l2r] [ssty=no]
+\definefontfeature[math-script-l2r] [mathematics-l2r] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript-l2r] [mathematics-l2r] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-text-r2l] [mathematics-r2l] [ssty=no]
+\definefontfeature[math-script-r2l] [mathematics-r2l] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript-r2l] [mathematics-r2l] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-nostack-text] [math-text] [nostackmath=yes]
+\definefontfeature[math-nostack-script] [math-script] [nostackmath=yes]
+\definefontfeature[math-nostack-scriptscript][math-scriptscript][nostackmath=yes]
+
+% \definefontfeature[mathtext] [math-text]
+% \definefontfeature[mathscript] [math-script]
+% \definefontfeature[mathscriptscript] [math-scriptscript]
+
+\definefontfeature
+ [missing]
+ [missing=yes]
+
+%D Nice to have too:
+
+\definefontfeature
+ [quality]
+ [expansion=quality,
+ protrusion=quality]
+
+\definefontfeature
+ [slanted]
+ [slant=.2]
+
+\definefontfeature
+ [boldened]
+ [extend=1.2]
+
+%D We define some colors that are used in tracing (for instance \OPENTYPE\
+%D features). We cannot yet inherit because no colors are predefined.
+
+\definecolor[trace:0][s=.4]
+\definecolor[trace:1][r=.6]
+\definecolor[trace:2][g=.6]
+\definecolor[trace:3][b=.6]
+\definecolor[trace:4][r=.6,g=.6]
+\definecolor[trace:5][r=.6,b=.6]
+\definecolor[trace:6][g=.6,b=.6]
+\definecolor[trace:7][r=.8,g=.4]
+\definecolor[trace:8][r=.8,b=.4]
+\definecolor[trace:9][g=.4,b=.8]
+
+\definecolor[font:init][r=.75]
+\definecolor[font:medi][g=.75]
+\definecolor[font:fina][b=.75]
+\definecolor[font:isol][r=.75,g=.75] % [y=.75]
+\definecolor[font:mark][r=.75,b=.75] % [m=.75]
+\definecolor[font:rest][b=.75,g=.75] % [c=.75]
+
+\definecolor[trace:w][s=1]
+\definecolor[trace:r][r=.75,t=.5,a=1]
+\definecolor[trace:g][g=.75,t=.5,a=1]
+\definecolor[trace:b][b=.75,t=.5,a=1]
+\definecolor[trace:c][c=.75,t=.5,a=1]
+\definecolor[trace:m][m=.75,t=.5,a=1]
+\definecolor[trace:y][y=.75,t=.5,a=1]
+\definecolor[trace:s][s=.75,t=.5,a=1]
+\definecolor[trace:o][r=1,g=.6,b=.1,t=.5,a=1]
+
+\definecolor[trace:dw][s=1]
+\definecolor[trace:dr][r=.75,t=.75,a=1]
+\definecolor[trace:dg][g=.75,t=.75,a=1]
+\definecolor[trace:db][b=.75,t=.75,a=1]
+\definecolor[trace:dc][c=.75,t=.75,a=1]
+\definecolor[trace:dm][m=.75,t=.75,a=1]
+\definecolor[trace:dy][y=.75,t=.75,a=1]
+\definecolor[trace:ds][s=.75,t=.75,a=1]
+\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1]
+
+\definecolor[font:0] [s=1]
+\definecolor[font:1] [r=.75]
+\definecolor[font:2] [g=.75]
+\definecolor[font:3] [b=.75]
+\definecolor[font:4] [r=.75,g=.75]
+\definecolor[font:5] [r=.75,b=.75]
+\definecolor[font:6] [b=.75,g=.75]
+\definecolor[font:7] [r=.75]
+\definecolor[font:8] [g=.75]
+\definecolor[font:9] [b=.75]
+
+\definecolor[f:r:t][a=1,t=.25,r=1]
+\definecolor[f:g:t][a=1,t=.25,g=1]
+\definecolor[f:b:t][a=1,t=.25,b=1]
+\definecolor[f:c:t][a=1,t=.25,c=1]
+\definecolor[f:m:t][a=1,t=.25,m=1]
+\definecolor[f:y:t][a=1,t=.25,y=1]
+\definecolor[f:k:t][a=1,t=.25,s=0]
+\definecolor[f:s:t][a=1,t=.25,s=0]
+
+\definepalet % weird place
+ [layout]
+ [grid=trace:dr,
+ page=trace:dg,
+ profile=f:s:t,
+ one=f:y:t,
+ mix=f:b:t]
+
+%D Now we're up to some definitions.
+
+\definebodyfontenvironment
+ [\s!default]
+ [ \s!text=1.0,
+ \s!script=0.7,
+ \s!scriptscript=0.5,
+ \s!a=1.200,
+ \s!b=1.440,
+ \s!c=1.728,
+ \s!d=2.074,
+ *=\font_currentfontscale, % wildcard
+ \s!x=0.8,
+ \s!xx=0.6,
+ \v!big=1.2,
+ \v!small=0.8,
+ \c!interlinespace=,
+ \s!em=\v!slanted]
+
+\definebodyfontenvironment
+ [20.7pt]
+ [ \s!text=20.7pt,
+ \s!script=\!!fourteenpointfour,
+ \s!scriptscript=\!!twelvepoint,
+ \s!x=17.3pt,
+ \s!xx=\!!fourteenpointfour,
+ \v!big=20.7pt, % !!!!
+ \v!small=17.3pt]
+
+\definebodyfontenvironment
+ [17.3pt]
+ [ \s!text=17.3pt,
+ \s!script=\!!twelvepoint,
+ \s!scriptscript=\!!tenpoint,
+ \s!x=\!!fourteenpointfour,
+ \s!xx=\!!twelvepoint,
+ \v!big=20.7pt,
+ \v!small=\!!fourteenpointfour]
+
+\definebodyfontenvironment
+ [\!!fourteenpointfour]
+ [ \s!text=\!!fourteenpointfour,
+ \s!script=\!!elevenpoint,
+ \s!scriptscript=\!!ninepoint,
+ \s!x=\!!twelvepoint,
+ \s!xx=\!!tenpoint,
+ \v!big=17.3pt,
+ \v!small=\!!twelvepoint]
+
+\definebodyfontenvironment
+ [\!!twelvepoint]
+ [ \s!text=\!!twelvepoint,
+ \s!script=\!!ninepoint,
+ \s!scriptscript=\!!sevenpoint,
+ \s!x=\!!tenpoint,
+ \s!xx=\!!eightpoint,
+ \v!big=\!!fourteenpointfour,
+ \v!small=\!!tenpoint]
+
+\definebodyfontenvironment
+ [\!!elevenpoint]
+ [ \s!text=\!!elevenpoint,
+ \s!script=\!!eightpoint,
+ \s!scriptscript=\!!sixpoint,
+ \s!x=\!!ninepoint,
+ \s!xx=\!!sevenpoint,
+ \v!big=\!!twelvepoint,
+ \v!small=\!!ninepoint]
+
+\definebodyfontenvironment
+ [\!!tenpoint]
+ [ \s!text=\!!tenpoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!eightpoint,
+ \s!xx=\!!sixpoint,
+ \v!big=\!!twelvepoint,
+ \v!small=\!!eightpoint]
+
+\definebodyfontenvironment
+ [\!!ninepoint]
+ [ \s!text=\!!ninepoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sevenpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!elevenpoint,
+ \v!small=\!!sevenpoint]
+
+\definebodyfontenvironment
+ [\!!eightpoint]
+ [ \s!text=\!!eightpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sixpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!tenpoint,
+ \v!small=\!!sixpoint]
+
+\definebodyfontenvironment
+ [\!!sevenpoint]
+ [ \s!text=\!!sevenpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sixpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!ninepoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!sixpoint]
+ [ \s!text=\!!sixpoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!fivepoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!eightpoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fivepoint]
+ [ \s!text=\!!fivepoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!fivepoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!sevenpoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fourpoint]
+ [ \s!text=\!!fourpoint,
+ \s!script=\!!fourpoint,
+ \s!scriptscript=\!!fourpoint,
+ \s!x=\!!fourpoint,
+ \s!xx=\!!fourpoint,
+ \v!big=\!!sixpoint,
+ \v!small=\!!fourpoint]
+
+\definebodyfontswitch [fourteenpointfour] [\!!fourteenpointfour]
+\definebodyfontswitch [twelvepoint] [\!!twelvepoint]
+\definebodyfontswitch [elevenpoint] [\!!elevenpoint]
+\definebodyfontswitch [tenpoint] [\!!tenpoint]
+\definebodyfontswitch [ninepoint] [\!!ninepoint]
+\definebodyfontswitch [eightpoint] [\!!eightpoint]
+\definebodyfontswitch [sevenpoint] [\!!sevenpoint]
+\definebodyfontswitch [sixpoint] [\!!sixpoint]
+\definebodyfontswitch [fivepoint] [\!!fivepoint]
+\definebodyfontswitch [fourpoint] [\!!fourpoint]
+
+%D So far.
+
+\definefontstyle [\s!hw] [\s!hw]
+\definefontstyle [\s!cg] [\s!cg]
+
+\definefontstyle [\v!roman,\v!serif,\v!regular] [\s!rm]
+\definefontstyle [\v!sansserif,\v!sans,\v!support] [\s!ss]
+\definefontstyle [\v!teletype,\v!type,\v!mono] [\s!tt]
+\definefontstyle [\v!handwritten] [\s!hw]
+\definefontstyle [\v!calligraphic] [\s!cg]
+\definefontstyle [\v!math,\v!mathematics] [\s!mm]
+
+\definefontalternative[\s!tf]
+\definefontalternative[\s!bf]
+\definefontalternative[\s!it]
+\definefontalternative[\s!sl]
+\definefontalternative[\s!bs]
+\definefontalternative[\s!bi]
+\definefontalternative[\s!sc]
+
+\definefontsize[\s!a] \definefontsize[\s!b]
+\definefontsize[\s!c] \definefontsize[\s!d]
+
+\definealternativestyle [\v!mediaeval] [\os] []
+\definealternativestyle [\v!normal] [\tf] []
+\definealternativestyle [\v!bold] [\bf] []
+\definealternativestyle [\v!type] [\tt] []
+\definealternativestyle [\v!mono] [\tt] []
+\definealternativestyle [\v!slanted] [\sl] []
+\definealternativestyle [\v!italic] [\it] []
+\definealternativestyle [\v!boldslanted,\v!slantedbold] [\bs] []
+\definealternativestyle [\v!bolditalic,\v!italicbold] [\bi] []
+
+\definealternativestyle [\v!small,\v!smallnormal] [\setsmallbodyfont\tf] []
+\definealternativestyle [\v!smallbold] [\setsmallbodyfont\bf] []
+\definealternativestyle [\v!smalltype] [\setsmallbodyfont\tt] []
+\definealternativestyle [\v!smallitalic,\v!smallslanted] [\setsmallbodyfont\sl] []
+\definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\setsmallbodyfont\bs] []
+\definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\setsmallbodyfont\bi] []
+
+\definealternativestyle [\v!bigger] [\setbigbodyfont \tf] []
+\definealternativestyle [\v!smaller] [\setsmallbodyfont\tf] []
+
+\definealternativestyle [\v!sans,\v!sansserif] [\ss] []
+\definealternativestyle [\v!roman,\v!serif,\v!regular] [\rm]
+\definealternativestyle [\v!handwritten] [\hw]
+\definealternativestyle [\v!calligraphic] [\cg]
+
+\definealternativestyle [\v!sansnormal] [\ss\tf] []
+\definealternativestyle [\v!sansbold] [\ss\bf] []
+\definealternativestyle [\v!serifnormal] [\rm\tf] []
+\definealternativestyle [\v!serifbold] [\rm\bf] []
+\definealternativestyle [\v!mononormal] [\tt\tf] []
+\definealternativestyle [\v!monobold] [\tt\bf] []
+
+% For Alan:
+
+\definealternativestyle
+ [\v!camel]
+ [{\setcharactercasing[\v!camel]}]
+ [{\setcharactercasing[\v!camel]}]
+
+% % maybe we need interface neutral as well (for use in cld):
+%
+% \letcscsname\mediaeval \csname\v!mediaeval \endcsname
+% \letcscsname\normal \csname\v!normal \endcsname
+% \letcscsname\bold \csname\v!bold \endcsname
+% \letcscsname\mono \csname\v!mono \endcsname
+% \letcscsname\slanted \csname\v!slanted \endcsname
+% \letcscsname\italic \csname\v!italic \endcsname
+% \letcscsname\boldslanted \csname\v!boldslanted \endcsname
+% \letcscsname\slantedbold \csname\v!slantedbold \endcsname
+% \letcscsname\bolditalic \csname\v!bolditalic \endcsname
+% \letcscsname\italicbold \csname\v!italicbold \endcsname
+%
+% \letcscsname\small \csname\v!small \endcsname
+% \letcscsname\smallnormal \csname\v!smallnormal \endcsname
+% \letcscsname\smallbold \csname\v!smallbold \endcsname
+% \letcscsname\smalltype \csname\v!smalltype \endcsname
+% \letcscsname\smallslanted \csname\v!smallslanted \endcsname
+% \letcscsname\smallboldslanted\csname\v!smallboldslanted\endcsname
+% \letcscsname\smallslantedbold\csname\v!smallslantedbold\endcsname
+% \letcscsname\smallbolditalic \csname\v!smallbolditalic \endcsname
+% \letcscsname\smallitalicbold \csname\v!smallitalicbold \endcsname
+%
+% \letcscsname\bigger \csname\v!bigger \endcsname
+% \letcscsname\smaller \csname\v!smaller \endcsname
+%
+% \letcscsname\sans \csname\v!sans \endcsname
+% \letcscsname\sansserif \csname\v!sansserif \endcsname
+% \letcscsname\sansbold \csname\v!sansbold \endcsname
+
+%D We can go on and on and on:
+%D
+%D \starttyping
+%D \setupbodyfontenvironment[default][p=0.8,q=0.6]
+%D \definefontsize[p]
+%D \definefontsize[q]
+%D \stoptyping
+
+%D Slow but handy:
+
+\definealternativestyle [\v!smallbodyfont] [\setsmallbodyfont] []
+\definealternativestyle [\v!bigbodyfont] [\setbigbodyfont] []
+
+%D We treat {\sc Small Caps} and \cap {Pseudo Caps} a bit
+%D different. We also provide an \WORD {uppercase} style.
+
+\definealternativestyle [\v!WORD] [{\setcharactercasing[\v!WORD ]}] [{\setcharactercasing[\v!WORD ]}]
+\definealternativestyle [\v!word] [{\setcharactercasing[\v!word ]}] [{\setcharactercasing[\v!word ]}]
+\definealternativestyle [\v!Word] [{\setcharactercasing[\v!Word ]}] [{\setcharactercasing[\v!Word ]}]
+\definealternativestyle [\v!Words] [{\setcharactercasing[\v!Words ]}] [{\setcharactercasing[\v!Words ]}]
+\definealternativestyle [\v!capital] [{\setcharactercasing[\v!capital]}] [{\setcharactercasing[\v!capital]}]
+\definealternativestyle [\v!Capital] [{\setcharactercasing[\v!Capital]}] [{\setcharactercasing[\v!Capital]}]
+\definealternativestyle [\v!mixed] [{\setcharactercasing[\v!mixed ]}] [{\setcharactercasing[\v!mixed ]}]
+
+\definealternativestyle [\v!cap] [{\setcharactercasing[\v!cap ]}] [{\setcharactercasing[\v!cap ]}]
+\definealternativestyle [\v!Cap] [{\setcharactercasing[\v!Cap ]}] [{\setcharactercasing[\v!Cap ]}]
+
+%D From now (2013-03-17) on we have:
+
+\definefontfeature[f:smallcaps][smcp=yes]
+\definefontfeature[f:oldstyle] [onum=yes]
+\definefontfeature[f:tabular] [tnum=yes]
+\definefontfeature[f:superiors][sups=yes]
+
+\definealternativestyle [\v!smallcaps] [\setsmallcaps] [\setsmallcaps]
+\definealternativestyle [\v!oldstyle] [\setoldstyle ] [\setoldstyle ]
+
+\unexpanded\def\setsmallcaps{\doaddfeature{f:smallcaps}}
+\unexpanded\def\setoldstyle {\doaddfeature{f:oldstyle}}
+\unexpanded\def\settabular {\doaddfeature{f:tabular}}
+\unexpanded\def\setsuperiors{\doaddfeature{f:superiors}}
+
+%D \macros
+%D {tinyfont}
+%D
+%D By default we load the Computer Modern Roman fonts (but
+%D not yet at this moment) and activate the 12pt roman
+%D bodyfont. Sans serif and teletype are also available and
+%D can be called for by \type{\ss} and \type{\tt}. Loading
+%D takes place elsewhere.
+%D
+%D For tracing purposes we define:
+
+\definefont[tinyfont][dejavusansmono at 1ex]
+
+%D \macros
+%D {infofont}
+%D
+%D The second situation occurs when we enable the info mode,
+%D and put all kind of status information in the margin. We
+%D don't want huge switches to the main bodyfont and style, so
+%D here too we use a direct method.
+
+\let\infofont \relax % satisfy dep checker
+\let\infofontbold\relax % satisfy dep checker
+
+\definefont[infofont] [dejavusansmono at 6pt] % todo \the\everybodyfont
+\definefont[infofontbold][dejavusansmonobold at 6pt] % todo \the\everybodyfont
+
+%D Optimization (later we overload in math):
+
+\unexpanded\def\normaltf{\let\fontalternative\s!tf\font_helpers_synchronize_font}
+\unexpanded\def\normalbf{\let\fontalternative\s!bf\font_helpers_synchronize_font}
+\unexpanded\def\normalit{\let\fontalternative\s!it\font_helpers_synchronize_font}
+\unexpanded\def\normalsl{\let\fontalternative\s!sl\font_helpers_synchronize_font}
+\unexpanded\def\normalbi{\let\fontalternative\s!bi\font_helpers_synchronize_font}
+\unexpanded\def\normalbs{\let\fontalternative\s!bs\font_helpers_synchronize_font}
+
+\let\tf\normaltf
+\let\bf\normalbf
+\let\it\normalit
+\let\sl\normalsl
+\let\bi\normalbi
+\let\bs\normalbs
+
+\protect \endinput
+
+% LM math vs CM math (analysis by Taco):
+%
+% Computer Modern Roman : Donald Knuth
+% Latin Modern : LM Font Revision Team
+%
+% lmex10.tfm % identical
+% lmmi5.tfm % identical
+% lmmi6.tfm % identical
+% lmmi7.tfm % identical
+% lmmi8.tfm % identical
+% lmmi9.tfm % identical
+% lmmi10.tfm % identical
+% lmmi12.tfm % identical
+% lmmib10.tfm % identical
+% lmsy5.tfm % extra chars: 254,255 (octal)
+% lmsy6.tfm % extra chars: 254,255 (octal)
+% lmsy7.tfm % extra chars: 254,255 (octal)
+% lmsy8.tfm % extra chars: 254,255 (octal)
+% lmsy9.tfm % extra chars: 254,255 (octal)
+% lmsy10.tfm % extra chars: 254,255 (octal)
+% lmbsy10.tfm % extra chars: 254,255 (octal)
+%
+% From the 'AMS' set:
+%
+% lmmib5.tfm % identical
+% lmmib7.tfm % identical
+% lmbsy5.tfm % extra chars: 254,255 (octal)
+% lmbsy7.tfm % extra chars: 254,255 (octal)
+%
+% The two extra characters are:
+%
+% /lessorequalslant
+% /greaterorequalslant
+
+% \unprotect
+%
+% \definehighlight[\v!italic ][\c!command=\v!no,\c!style=\v!italic]
+% \definehighlight[\v!bold ][\c!command=\v!no,\c!style=\v!bold]
+% \definehighlight[\v!bolditalic][\c!command=\v!no,\c!style=\v!bolditalic]
+% \definehighlight[\v!mono] [\c!command=\v!no,\c!style=\v!mono]
+% \definehighlight[\v!monobold] [\c!command=\v!no,\c!style=\v!monobold]
+%
+% \definehighlight[important] [\c!command=\v!no,\c!style=\v!bold]
+% \definehighlight[unimportant] [\c!command=\v!no,\c!color=darkgray]
+% \definehighlight[warning] [\c!command=\v!no,\c!style=\v!bold,\c!color=darkblue]
+% \definehighlight[error] [\c!command=\v!no,\c!style=\v!bold,\c!color=darkred]
+%
+% \protect
+%
+% \starttext
+% \highlight[italic] {italic}
+% \highlight[bolditalic] {bolditalic}
+% \highlight[bold] {bold}
+% \highlight[mono] {mono}
+% \highlight[monobold] {monobold}
+% \highlight[important] {important}
+% \highlight[unimportant]{unimportant}
+% \highlight[warning] {warning}
+% \highlight[error] {error}
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-run.mkiv
new file mode 100644
index 00000000000..e9a6f9ddb7b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-run.mkiv
@@ -0,0 +1,403 @@
+%D \module
+%D [ file=font-run,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D [This code is hooked into the core macros and saves some format
+%D space. It needs a cleanup as it's real old derioved \MKII\ code]
+
+\unprotect
+
+\gdef\font_show_only_english#1%
+ {\blank{\tttf \type {#1} is only available in the english interface}\blank}
+
+\gdef\font_show_title#1%
+ {\tabskip\zeropoint
+ \parindent\zeropoint
+ \setlocalhsize
+ \doifelsenothing{#1}
+ {\def\title{[\the\bodyfontsize]}}
+ {\switchtobodyfont[#1]\def\title{[#1]}}
+ \doifsomething\fontclass
+ {\doifnot{[\fontclass]}\title
+ {\edef\title{[\fontclass]\space\title}}}}
+
+\unexpanded\gdef\showbodyfont
+ {\dosingleempty\font_show_bodyfont}
+
+\gdef\font_show_bodyfont[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\font_show_title{#1}%
+ \def\bigstrut##1##2%
+ {\hbox{\vrule
+ \s!height##1\strutht
+ \s!depth ##2\strutdp
+ \s!width \zeropoint}}
+ \def\next##1##2##3%
+ {&&##1&&##2\tf##3&&##2\sc##3%
+ &&##2\sl##3&&##2\it##3&&##2\bf##3&&##2\bs##3&&##2\bi##3%
+ &&##2\tfx##3&&##2\tfxx##3%
+ &&##2\tfa##3&&##2\tfb##3&&##2\tfc##3&&##2\tfd##3&\cr}%
+ \halign to \localhsize
+ {\bigstrut{1.5}{2}##&\vrule##
+ \tabskip\zeropoint \s!plus 1\s!fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule
+ \tabskip=\zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{29}{\vrule\hfil\tttf\strut\title\hfil
+ \llap{\string\mr\hpack to \emwidth{\hss:\hss}\normalstartimath\mr\languageparameter\c!text\normalstopimath\quad}\vrule}\cr
+ \noalign{\hrule}\next{}{\tt\string}{}
+ \noalign{\hrule}\next{\tt\string\rm}\rm{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\ss}\ss{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\tt}\tt{\languageparameter\c!text}
+ \noalign{\hrule}}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\unexpanded\gdef\showbodyfontenvironment
+ {\dosingleempty\font_show_bodyfont_environment}
+
+\gdef\font_show_bodyfont_environment[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\font_show_title{#1}%
+ \def\next##1%
+ {&&\bodyfontsizevariable{##1}\s!text
+ &&\bodyfontsizevariable{##1}\s!script
+ &&\bodyfontsizevariable{##1}\s!scriptscript
+ &&\bodyfontsizevariable{##1}\s!x
+ &&\bodyfontsizevariable{##1}\s!xx
+ &&\bodyfontsizevariable{##1}\v!small
+ &&\bodyfontsizevariable{##1}\v!big
+ &&\bodyfontsizevariable{##1}\c!interlinespace
+ &\cr
+ \noalign{\hrule}}
+ \halign to \localhsize
+ {##&\vrule##\strut
+ \tabskip=\zeropoint \s!plus 1\s!fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule
+ \tabskip\zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{17}{\vrule\hfil\tttf\strut\title\hfil}\vrule\cr
+ \noalign{\hrule}
+ &&\tttf\tx\s!text&&\tttf\tx\s!script&&\tttf\tx\s!scriptscript
+ &&\tttf\tx\s!x&&\tttf\tx\s!xx&&\tttf\tx\v!small&&\tttf\tx\v!big
+ &&\tttf\tx\c!interlinespace&\cr
+ \noalign{\hrule}%
+ \processbodyfontenvironmentlist\next}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\unexpanded\gdef\showfont
+ {\dodoubleempty\font_show_font}
+
+\gdef\font_show_font[#1][#2]% doing this in lua is much faster
+ {\bgroup
+ \iffirstargument
+ \definefont[\s!dummy][#1]\dummy
+ \fi
+ \doifelsenothing{#2}
+ {\font_show_font_indeed{#1}\zerocount}
+ {\doifelse{#2}\v!all
+ {\dostepwiserecurse\zerocount{255}\plusone
+ {\scratchcounterone \recurselevel
+ \scratchcountertwo \numexpr\scratchcounterone*256\relax
+ \scratchcounterthree\numexpr\scratchcountertwo+255\relax
+ \doloop
+ {\iffontchar\font\scratchcountertwo
+ \font_show_font_indeed{#1}\scratchcounterone
+ \exitloop
+ \else\ifnum\scratchcountertwo=\scratchcounterthree
+ \exitloop
+ \else
+ \advance\scratchcountertwo\plusone
+ \fi\fi}}}
+ {\processcommalist[#2]{\font_show_font_indeed{#1}}}}%
+ \egroup}
+
+\gdef\font_show_font_indeed#1#2% made some 50% faster but still slow
+ {\bgroup
+ \iffirstargument
+ % \definefont[\s!dummy][#1]\dummy
+ \else\ifdim2.5\emwidth>.05\hsize \tx
+ \ifdim2.5\emwidth>.05\hsize \txx
+ \fi\fi\fi
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox\bgroup
+ \scratchdimenone 2.5\emwidth
+ \scratchdimentwo 2.4\emwidth
+ \scratchdimenthree2.3\emwidth
+ \edef\charplane{\number#2}%
+ \forgetall
+ \startoverlay % easier in cld
+ {\vbox
+ {\tf
+ \setstrut
+ \dummy
+ \offinterlineskip
+ \unexpanded\def\wrapbox##1%
+ {\vpack to \scratchdimenone
+ {\vss
+ \hpack to \scratchdimenone
+ {\dummy
+ \ifdim\interwordspace=\zeropoint
+ \setbox##1\hpack
+ {\raise.5\dp##1\hpack
+ {\lower.5\ht##1\copy##1}}%
+ \ht##1\zeropoint
+ \dp##1\zeropoint
+ \else
+ \ht##1\strutht
+ \dp##1\strutdp
+ \strut
+ \fi
+ \hss\copy##1\hss}
+ \vss}}%
+ \unexpanded\def\textbox##1%
+ {\vpack to \scratchdimentwo
+ {\hsize\scratchdimenthree
+ ##1%
+ \par}}%
+ \unexpanded\def\scratchnum
+ {\blue
+ \tinyfont
+ \hfill
+ \number\scratchcounter
+ \vfill
+ \octnumber\scratchcounter
+ \hfill
+ \lchexnumbers\scratchcounter}%
+ \setbox\scratchboxone\hpack{\tf\textbox{}}%
+ \setbox\scratchboxtwo\hpack{\tf\gray\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight}%
+ \setbox\scratchboxtwo\wrapbox\scratchboxtwo
+ \setbox\scratchboxthree\hpack
+ {\startoverlay
+ {\box\scratchboxtwo}
+ {\box\scratchboxone}
+ \stopoverlay}%
+ \dostepwiserecurse\zerocount{15}\plusone
+ {\scratchcounterone\recurselevel
+ \hpack
+ {\dostepwiserecurse\zerocount{15}\plusone
+ {\scratchcountertwo \recurselevel
+ \scratchcounter \numexpr\scratchcounterone*16+\scratchcountertwo\relax
+ \scratchcounterthree\numexpr\charplane*256+\scratchcounter\relax
+ \iffontchar\font\scratchcounterthree
+ \setbox\scratchbox\ruledhpack{\char\scratchcounterthree}%
+ \tf
+ \startoverlay
+ {\wrapbox\scratchbox}
+ {\textbox\scratchnum}
+ \stopoverlay
+ \else
+ \copy\scratchboxthree
+ \fi}}}%
+ \par}}
+ {\tf\basegrid[\c!nx=16,\c!ny=16,\c!dx=2.5,\c!dy=2.5,\c!unit=em]}
+ \stopoverlay
+ \nointerlineskip
+ \vskip2\points
+ % the \noexpand before \blank is needed for non etex
+ \edef\theshowfontspecs{name: {\noexpand\black\fontname\font}\quad plane: \charplane\enspace"\hexnumber\charplane}%
+ \tf % also sets em
+ \hbox to 40\emwidth{\blue\hfill\tinyfont\setstrut\strut\theshowfontspecs}
+ \egroup
+ \ifinsidefloat\else\stopbaselinecorrection\fi
+ \egroup}
+
+% \showfontstyle[modern][rm][tf][all] % #2, #3 and #4 can be 'all'
+
+\unexpanded\gdef\showfontstyle {\dodoubleempty \font_show_style}
+\unexpanded\gdef\font_show_style_a{\dotripleempty \font_show_style_b}
+\unexpanded\gdef\font_show_style_c{\doquadrupleempty\font_show_style_d}
+
+% no lists any more, so no 'all' any longer
+
+\gdef\font_show_style[#1][#2]%
+ {\doifelsenothing{#2}
+ {\font_show_style_a[#1][\s!rm,\s!ss,\s!tt,\s!mm]}
+ {\font_show_style_a[#1][#2]}}
+
+\gdef\font_show_style_b[#1][#2][#3]%
+ {\doifelsenothing{#3}
+ {\font_show_style_c[#1][#2][\s!tf,\s!bf,\s!it,\s!sl,\s!bs,\s!bi]}
+ {\font_show_style_c[#1][#2][#3]}}
+
+\gdef\font_show_style_d[#1][#2][#3][#4]%
+ {\font_show_style_e[#1][#2][#3][#4]}
+
+% so far
+
+\gdef\font_show_style_e[#1][#2][#3][#4]%
+ {\bgroup
+ \raggedright
+ \switchtobodyfont[#1]
+ \def\dododocommand##1%
+ {\dostepwiserecurse\zerocount{255}\plusone
+ {\scratchcounter\numexpr##1*256+\recurselevel\relax
+ \iffontchar\font\scratchcounter\relax
+ \char\scratchcounter
+ \space
+ \fi}}%
+ \def\dodocommand##1##2%
+ {\starttextrule{\tttf #1 ##1 ##2}
+ \nobreak\getvalue{##2}%
+ \doifelsenothing{#4}
+ {\dododocommand\zerocount}
+ {\doifelse{#4}\v!all
+ {\dostepwiserecurse\zerocount{255}\plusone{\expanded{\dododocommand{\recurselevel}}}}
+ {\processcommalist[#4]{\dododocommand}}}%
+ \par \nobreak
+ \stoptextrule}
+ \def\docommand##1%
+ {\getvalue{##1}%
+ \processcommacommand[#3]{\dodocommand{##1}}}
+ \processcommalist[#2]\docommand
+ \egroup}
+
+\unexpanded\gdef\showligature#1%
+ {\hbox{\type{#1}\enspace\red\ruledhbox{\black#1}}}
+
+\unexpanded\gdef\showligatures[#1]% we keep it around for compatibility reasons
+ {\ifx\starttabulate\undefined
+ \font_show_only_english\showligatures
+ \else
+ \bgroup
+ \def\font_show_ligature##1{\hbox{\red\ruledhbox{\black##1}}}%
+ \definedfont[#1*default]%
+ %starttabulate[|*{9}{c|}]
+ \starttabulate[|*{7}{c|}]
+ \NC\type{ff}
+ \NC\type{fi}
+ \NC\type{fl}
+ \NC\type{ffi}
+ \NC\type{ffl}
+ %NC\type{``}
+ %NC\type{''}
+ \NC\type{--}
+ \NC\type{---}
+ \NC\NR
+ \NC\font_show_ligature{ff}
+ \NC\font_show_ligature{fi}
+ \NC\font_show_ligature{fl}
+ \NC\font_show_ligature{ffi}
+ \NC\font_show_ligature{ffl}
+ %NC\font_show_ligature{``}
+ %NC\font_show_ligature{''}
+ \NC\font_show_ligature{--}
+ \NC\font_show_ligature{---}
+ \NC\NR
+ \stoptabulate
+ \egroup
+ \fi}
+
+\unexpanded\gdef\showfontstrip
+ {\dosingleempty\font_show_strip}
+
+\gdef\font_show_strip[#1]%
+ {\ifx\starttabulate\undefined
+ \font_show_only_english\showfontstrip
+ \else
+ \bgroup
+ \def\font_show_strip_a##1##2%
+ {\tttf\string##1}
+ \def\font_show_strip_b##1##2%
+ {\ruledhbox{\switchtobodyfont[#1]##1{##2}}}
+ \def\font_show_strip_c##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\ht\scratchbox}%
+ \def\font_show_strip_d##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\wd\scratchbox}%
+ \def\font_show_strip_indeed##1##2##3%
+ {\NC##2\rm{##3}\NC
+ ##2\ss{##3}\NC
+ ##2\tt{##3}\NC
+ ##2\mathematics{##3}\NC
+ \tttf##1\NR}
+ \starttabulate[|c|c|c|c|c|]
+ \font_show_strip_indeed\relax\font_show_strip_a\empty
+ \TB
+ \font_show_strip_indeed\relax\font_show_strip_b{xxxx}
+ \font_show_strip_indeed\relax\font_show_strip_b{12345}
+ \font_show_strip_indeed\relax\font_show_strip_b{(Agw)}
+ \TB
+ \font_show_strip_indeed{(x height)}\font_show_strip_c{x}
+ \font_show_strip_indeed{(m width)}\font_show_strip_d{m}
+ \stoptabulate
+ \egroup
+ \fi}
+
+\ifdefined\databox \else \newbox\databox \fi
+
+\unexpanded\gdef\testminimalbaseline#1% to be used in a 10 column tabulate
+ {\setbox\databox\ruledhbox{#1}%
+ \scratchdimen\htdp\databox
+ \normalexpanded {
+ \NC \ruledhbox{#1}%
+ \NC ->
+ \NC \the\htdp\databox
+ \NC =
+ \NC \the\ht\databox
+ \NC +
+ \NC \the\dp\databox
+ \NC \ifdim\scratchdimen<\baselineskip <
+ \else\ifdim\scratchdimen=\baselineskip =
+ \else > \fi\fi
+ \NC \the\baselineskip
+ \NC (\ifdim\scratchdimen>\baselineskip not \fi ok)
+ \NC \NR}
+ }
+
+\unexpanded\gdef\showminimalbaseline
+ {\ifx\starttabulate\undefined
+ \font_show_only_english\showminimalbaseline
+ \else
+ \starttabulate[|l|T|T|T|T|T|T|T|T|T|]
+ \testminimalbaseline{\hbox to \emwidth{\hss\showstruts\strut\hss}}%
+ \testminimalbaseline{(/)}%
+ \testminimalbaseline{\normalstartimath\frac{1}{2}x\normalsuperscript2\normalsubscript3\normalstopimath}
+ \stoptabulate
+ \fi}
+
+\unexpanded\gdef\showkerning#1%
+ {\bgroup
+ \let\MPfshowcommand\ruledhbox
+ \setMPtext\s!dummy{#1}%
+ \startMPcode draw textext(\MPstring\s!dummy);\stopMPcode
+ \egroup}
+
+\unexpanded\gdef\showcharratio
+ {\dowithnextboxcontent
+ {\switchtobodyfont[10pt]}%
+ {(\withoutpt\the\nextboxht,\withoutpt\the\nextboxdp)}%
+ \hbox}
+
+\unexpanded\gdef\showfontparameters
+ {\starttabulate[|tl|l|]
+ \NC slantperpoint \NC \the\fontslantperpoint \font \NC\NR
+ \NC interwordspace \NC \the\fontinterwordspace \font \NC\NR
+ \NC interwordstretch\NC \the\fontinterwordstretch\font \NC\NR
+ \NC interwordshrink \NC \the\fontinterwordshrink \font \NC\NR
+ \NC exheight \NC \the\fontexheight \font \NC\NR
+ \NC emwidth \NC \the\fontemwidth \font \NC\NR
+ \NC extraspace \NC \the\fontextraspace \font \NC\NR
+ \stoptabulate}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua b/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua
new file mode 100644
index 00000000000..c3431a213ca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua
@@ -0,0 +1,770 @@
+if not modules then modules = { } end modules ['font-sel'] = {
+ version = 1.000,
+ comment = "companion to font-sel.mkvi",
+ author = "Wolfgang Schuster",
+ copyright = "Wolfgang Schuster",
+ license = "GNU General Public License"
+}
+
+local context = context
+local cleanname = fonts.names.cleanname
+local gsub, splitup, find = string.gsub, string.splitup, string.find
+local splitbase, removesuffix = file.splitbase, file.removesuffix
+local splitat, lpegmatch = lpeg.splitat, lpeg.match
+
+local formatters = string.formatters
+local settings_to_array = utilities.parsers.settings_to_array
+
+local v_yes = interfaces.variables.yes
+local v_simplefonts = interfaces.variables.simplefonts
+local v_selectfont = interfaces.variables.selectfont
+local v_default = interfaces.variables.default
+
+local implement = interfaces.implement
+
+local selectfont = fonts.select or { }
+fonts.select = selectfont
+
+local data = selectfont.data or { }
+selectfont.data = data
+
+local fallbacks = selectfont.fallbacks or { }
+selectfont.fallbacks = fallbacks
+
+local methods = selectfont.methods or { }
+selectfont.methods = methods
+
+local getlookups = fonts.names.getlookups
+local registerdesignsizes = fonts.goodies.designsizes.register
+
+local alternatives = {
+ ["tf"] = "regular",
+ ["it"] = "italic",
+ ["sl"] = "slanted",
+ ["bf"] = "bold",
+ ["bi"] = "bolditalic",
+ ["bs"] = "boldslanted",
+ ["sc"] = "smallcaps",
+}
+
+local styles = {
+ ["rm"] = "serif",
+ ["ss"] = "sans",
+ ["tt"] = "mono",
+ ["hw"] = "handwriting",
+ ["cg"] = "calligraphy",
+ ["mm"] = "math",
+}
+
+local sizes = {
+ ["default"] = {
+ { 40, "4pt" },
+ { 50, "5pt" },
+ { 60, "6pt" },
+ { 70, "7pt" },
+ { 80, "8pt" },
+ { 90, "9pt" },
+ { 100, "10pt" },
+ { 110, "11pt" },
+ { 120, "12pt" },
+ { 144, "14.4pt" },
+ { 173, "17.3pt" },
+ },
+ ["dtp"] = {
+ { 50, "5pt" },
+ { 60, "6pt" },
+ { 70, "7pt" },
+ { 80, "8pt" },
+ { 90, "9pt" },
+ { 100, "10pt" },
+ { 110, "11pt" },
+ { 120, "12pt" },
+ { 130, "13pt" },
+ { 140, "14pt" },
+ { 160, "16pt" },
+ { 180, "18pt" },
+ { 220, "22pt" },
+ { 280, "28pt" },
+ }
+}
+
+local synonyms = {
+ ["rm"] = {
+ ["tf"] = "Serif",
+ ["it"] = "SerifItalic",
+ ["sl"] = "SerifSlanted",
+ ["bf"] = "SerifBold",
+ ["bi"] = "SerifBoldItalic",
+ ["bs"] = "SerifBoldSlanted",
+ ["sc"] = "SerifCaps",
+ },
+ ["ss"] = {
+ ["tf"] = "Sans",
+ ["it"] = "SansItalic",
+ ["sl"] = "SansSlanted",
+ ["bf"] = "SansBold",
+ ["bi"] = "SansBoldItalic",
+ ["bs"] = "SansBoldSlanted",
+ ["sc"] = "SansCaps",
+ },
+ ["tt"] = {
+ ["tf"] = "Mono",
+ ["it"] = "MonoItalic",
+ ["sl"] = "MonoSlanted",
+ ["bf"] = "MonoBold",
+ ["bi"] = "MonoBoldItalic",
+ ["bs"] = "MonoBoldSlanted",
+ ["sc"] = "MonoCaps",
+ },
+ ["hw"] = {
+ ["tf"] = "Handwriting",
+ },
+ ["cg"] = {
+ ["tf"] = "Calligraphy",
+ },
+ ["mm"] = {
+ ["tf"] = "MathRoman",
+ ["bf"] = "MathBold",
+ }
+}
+
+local replacement = {
+ ["style"] = {
+ ["it"] = "tf",
+ ["sl"] = "it",
+ ["bf"] = "tf",
+ ["bi"] = "bf",
+ ["bs"] = "bi",
+ ["sc"] = "tf",
+ },
+ ["weight"] = {
+ ["it"] = "tf",
+ ["sl"] = "tf",
+ ["bf"] = "tf",
+ ["bi"] = "bf",
+ ["bs"] = "bf",
+ ["sc"] = "tf",
+ },
+}
+
+local names = {
+ ["selectfont"] = { -- weight, style, width, variant, italic
+ ["regular"] = { weight = "normal", style = "normal", width = "normal", variant = "normal", italic = false },
+ ["italic"] = { weight = "normal", style = "italic", width = "normal", variant = "normal", italic = true },
+ ["slanted"] = { weight = "normal", style = "slanted", width = "normal", variant = "normal", italic = true },
+ ["medium"] = { weight = "medium", style = "normal", width = "normal", variant = "normal", italic = false },
+ ["mediumitalic"] = { weight = "medium", style = "italic", width = "normal", variant = "normal", italic = true },
+ ["mediumcaps"] = { weight = "medium", style = "normal", width = "normal", variant = "smallcaps", italic = true },
+ ["bold"] = { weight = "bold", style = "normal", width = "normal", variant = "normal", italic = false },
+ ["bolditalic"] = { weight = "bold", style = "italic", width = "normal", variant = "normal", italic = true },
+ ["boldslanted"] = { weight = "bold", style = "slanted", width = "normal", variant = "normal", italic = true },
+ ["smallcaps"] = { weight = "normal", style = "normal", width = "normal", variant = "smallcaps", italic = false },
+ },
+ ["simplefonts"] = {
+ ["light"] = { "lightregular", "light" },
+ ["lightitalic"] = { "lightitalic", "lightit", "lightoblique" },
+ ["lightcaps"] = { "smallcapslight" },
+ ["regular"] = { "roman", "regular", "book", "" },
+ ["italic"] = { "italic", "it", "oblique", "kursiv", "bookitalic", "bookit" },
+ ["medium"] = { "mediumregular", "medregular", "medium" },
+ ["mediumitalic"] = { "mediumitalic", "meditalic" },
+ ["mediumcaps"] = { "mediumcaps" },
+ ["bold"] = { "bold", "bd", "kraeftig", "mediumregular", "semibold", "demi" },
+ ["bolditalic"] = { "bolditalic", "boldit", "bdit", "boldoblique", "mediumitalic", "semibolditalic", "demiitalic" },
+ ["smallcaps"] = { "smallcaps", "capitals", "sc" },
+ ["heavy"] = { "heavyregular", "heavy" },
+ ["heavyitalic"] = { "heavyitalic" },
+ },
+ ["default"] = { -- weight, width, italic
+ ["thin"] = { weight = { 100, 200, 300, 400, 500 }, width = 5, italic = false },
+ ["thinitalic"] = { weight = { 100, 200, 300, 400, 500 }, width = 5, italic = true },
+ ["extralight"] = { weight = { 200, 100, 300, 400, 500 }, width = 5, italic = false },
+ ["extralightitalic"] = { weight = { 200, 100, 300, 400, 500 }, width = 5, italic = true },
+ ["light"] = { weight = { 300, 200, 100, 400, 500 }, width = 5, italic = false },
+ ["lightitalic"] = { weight = { 300, 200, 100, 400, 500 }, width = 5, italic = true },
+ ["regular"] = { weight = { 400, 500, 300, 200, 100 }, width = 5, italic = false },
+ ["italic"] = { weight = { 400, 500, 300, 200, 100 }, width = 5, italic = true },
+ ["medium"] = { weight = { 500, 400, 300, 200, 100 }, width = 5, italic = false },
+ ["mediumitalic"] = { weight = { 500, 400, 300, 200, 100 }, width = 5, italic = true },
+ ["demibold"] = { weight = { 600, 700, 800, 900 }, width = 5, italic = false },
+ ["demibolditalic"] = { weight = { 600, 700, 800, 900 }, width = 5, italic = true },
+ ["bold"] = { weight = { 700, 600, 800, 900 }, width = 5, italic = false },
+ ["bolditalic"] = { weight = { 700, 600, 800, 900 }, width = 5, italic = true },
+ ["extrabold"] = { weight = { 800, 900, 700, 600 }, width = 5, italic = false },
+ ["extrabolditalic"] = { weight = { 800, 900, 700, 600 }, width = 5, italic = true },
+ ["heavy"] = { weight = { 900, 800, 700, 600 }, width = 5, italic = false },
+ ["heavyitalic"] = { weight = { 900, 800, 700, 600 }, width = 5, italic = true },
+ }
+}
+
+-- simplefonts synonyms
+
+names.simplefonts.slanted = names.simplefonts.italic
+names.simplefonts.boldslanted = names.simplefonts.bolditalic
+
+-- default synonyms
+
+names.default.ultralight = names.default.extralight
+names.default.semibold = names.default.demibold
+names.default.ultrabold = names.default.extrabold
+names.default.black = names.default.heavy
+
+names.default.ultralightitalic = names.default.extralightitalic
+names.default.semibolditalic = names.default.demibolditalic
+names.default.ultrabolditalic = names.default.extrabolditalic
+names.default.blackitalic = names.default.heavyitalic
+
+names.default.thinslanted = names.default.thinitalic
+names.default.extralightslanted = names.default.extralightitalic
+names.default.ultralightslanted = names.default.extralightitalic
+names.default.lightslanted = names.default.lightitalic
+names.default.slanted = names.default.italic
+names.default.demiboldslanted = names.default.demibolditalic
+names.default.semiboldslanted = names.default.demibolditalic
+names.default.boldslanted = names.default.bolditalic
+names.default.extraboldslanted = names.default.extrabolditalic
+names.default.ultraboldslanted = names.default.extrabolditalic
+names.default.heavyslanted = names.default.heavyitalic
+names.default.blackslanted = names.default.heavyitalic
+
+names.default.smallcaps = names.default.regular
+
+local mathsettings = {
+ ["asanamath"] = {
+ extras = "asana-math",
+ goodies = {
+ ["tf"] = "anana-math",
+ },
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["cambriamath"] = {
+ extras = "cambria-math",
+ goodies = {
+ ["tf"] = "cambria-math",
+ },
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["neoeuler"] = {
+ extras = "euler-math",
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["latinmodernmath"] = {
+ extras = "lm,lm-math",
+ goodies = {
+ ["tf"] = "lm",
+ },
+ features = {
+ ["tf"] = "math\\mathsizesuffix,lm-math",
+ },
+ },
+ ["lucidabrightmathot"] = {
+ extras = "lucida-opentype-math",
+ goodies = {
+ ["tf"] = "lucida-opentype-math",
+ },
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["texgyrepagellamath"] = {
+ extras = "texgyre",
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["texgyrebonummath"] = {
+ extras = "texgyre",
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["texgyretermesmath"] = {
+ extras = "texgyre",
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+ ["xitsmath"] = {
+ extras = "xits-math",
+ goodies = {
+ ["tf"] = "xits-math",
+ },
+ features = {
+ ["tf"] = "math\\mathsizesuffix",
+ },
+ },
+}
+
+function selectfont.define(settings)
+ local index = #data + 1
+ data[index] = settings
+ selectfont.searchfiles(index)
+ selectfont.filterinput(index)
+ return index
+end
+
+local function savefont(data,alternative,entries)
+ local f = data.fonts
+ if not f then
+ f = { }
+ data.fonts = f
+ end
+ f[alternative] = entries
+end
+
+local function savefeatures(data,alternative,entries)
+ local e = gsub(entries,"{(.*)}","%1")
+ local f = data.features
+ if not f then
+ f = { }
+ data.features = f
+ end
+ f[alternative] = e
+end
+
+local function savegoodies(data,alternative,entries)
+ local e = gsub(entries,"{(.*)}","%1")
+ local g = data.goodies
+ if not f then
+ g = { }
+ data.goodies = g
+ end
+ g[alternative] = e
+end
+
+methods[v_simplefonts] = function(data,alternative,style)
+ local family = data.metadata.family
+ local names = names["simplefonts"][style] or names["simplefonts"]["regular"]
+ for _, name in next, names do
+ local filename = cleanname(formatters["%s%s"](family,name))
+ local fullname = getlookups{ fullname = filename }
+ local fontname = getlookups{ fontname = filename }
+ local cleanfilename = getlookups{ cleanfilename = filename }
+ if #fullname > 0 then
+ savefont(data,alternative,fullname)
+ break
+ elseif #fontname > 0 then
+ savefont(data,alternative,fontname)
+ break
+ elseif #cleanfilename > 0 then
+ savefont(data,alternative,cleanfilename)
+ break
+ end
+ end
+end
+
+methods[v_default] = function(data,alternative,style)
+ local family = data.metadata.family
+ local spec = names["default"][style] or names["default"]["regular"]
+ local weights = spec["weight"]
+ for _, weight in next, weights do
+ local pattern = getlookups{
+ familyname = cleanname(family),
+ pfmweight = weight,
+ pfmwidth = spec["width"],
+ }
+ if #pattern > 0 then
+ local fontfiles = { }
+ for _, fontfile in next, pattern do
+ if (fontfile["angle"] and spec["italic"] == true) or (not fontfile["angle"] and spec["italic"] == false) then
+ fontfiles[#fontfiles + 1] = fontfile
+ end
+ end
+ savefont(data,alternative,fontfiles)
+ break
+ end
+ end
+end
+
+methods[v_selectfont] = function(data,alternative,style)
+ local family = data.metadata.family
+ local spec = names["selectfont"][style] or names["selectfont"]["regular"]
+ local pattern = getlookups{
+ familyname = cleanname(family),
+ weight = spec["weight"],
+ style = spec["style"],
+ width = spec["width"],
+ variant = spec["variant"]
+ }
+ if #pattern > 0 then
+ local fontfiles = { }
+ for _, fontfile in next, pattern do
+ if (fontfile["angle"] and spec["italic"] == true) or (not fontfile["angle"] and spec["italic"] == false) then
+ fontfiles[#fontfiles + 1] = fontfile
+ end
+ end
+ savefont(data,alternative,fontfiles)
+ end
+end
+
+methods["name"] = function(data,alternative,filename)
+ local data = data
+ local family = data.metadata.family
+ local filename = cleanname(gsub(filename,"*",family))
+ local fullname = getlookups{ fullname = filename }
+ local fontname = getlookups{ fontname = filename }
+ if #fullname > 0 then
+ savefont(data,alternative,fullname)
+ elseif #fontname > 0 then
+ savefont(data,alternative,fontname)
+ end
+end
+
+methods["file"] = function(data,alternative,filename)
+ local data = data
+ local family = data.metadata.family
+ local filename = gsub(removesuffix(filename),"*",family)
+ local filename = getlookups{ cleanfilename = cleanname(filename) }
+ if #filename > 0 then
+ savefont(data,alternative,filename)
+ end
+end
+
+methods["spec"] = function(data,alternative,filename)
+ local family = data.metadata.family
+ local weight, style, width, variant = splitup(filename,"-")
+ local pattern = getlookups{
+ familyname = cleanname(family),
+ weight = weight or "normal",
+ style = style or "normal",
+ width = width or "normal",
+ variant = variant or "normal",
+ }
+ if #pattern > 0 then
+ savefont(data,alternative,pattern)
+ end
+end
+
+methods["style"] = function(data,alternative,style)
+ local method = data.options.alternative or nil
+ (methods[method] or methods[v_default])(data,alternative,style)
+end
+
+methods["features"] = function(data,alternative,features)
+ savefeatures(data,alternative,features)
+end
+
+methods["goodies"] = function(data,alternative,goodies)
+ savegoodies(data,alternative,goodies)
+end
+
+function selectfont.searchfiles(index)
+ local data = data[index]
+ for alternative, _ in next, alternatives do
+ local filename = data.files[alternative]
+ local method = data.options.alternative
+ local family = data.metadata.family
+ local style = alternatives[alternative]
+ if filename == "" then
+ local pattern = getlookups{ familyname = cleanname(family) }
+ if #pattern == 1 and alternative == "tf" then -- needs to be improved
+ savefont(data,alternative,pattern)
+ else
+ (methods[method] or methods[v_default])(data,alternative,style)
+ end
+ else
+ method, filename = splitup(filename,":")
+ if not filename then
+ filename = method
+ method = "name"
+ end
+ (methods[method] or methods["name"])(data,alternative,filename)
+ end
+ end
+end
+
+function selectfont.filterinput(index)
+ local data = data[index]
+ local p = splitat(":",true)
+ for alternative, _ in next, alternatives do
+ local list = settings_to_array(data.alternatives[alternative])
+ for _, entry in next, list do
+ method, entries = lpegmatch(p,entry)
+ if not entries then
+ entries = method
+ method = "name"
+ end
+ (methods[method] or methods["name"])(data,alternative,entries)
+ end
+ end
+end
+
+local ctx_definefontsynonym = context.definefontsynonym
+local ctx_resetfontfallback = context.resetfontfallback
+local ctx_startfontclass = context.startfontclass
+local ctx_stopfontclass = context.stopfontclass
+local ctx_loadfontgoodies = context.loadfontgoodies
+local ctx_definefontfallback = context.definefontfallback
+local ctx_definetypeface = context.definetypeface
+
+local function definefontsynonym(data,alternative,index,fallback)
+ local fontdata = data.fonts and data.fonts[alternative]
+ local style = data.metadata.style
+ local typeface = data.metadata.typeface
+ local mathsettings = mathsettings[cleanname(data.metadata.family)]
+ local features = mathsettings and mathsettings["features"] and (mathsettings["features"][alternative] or mathsettings["features"]["tf"]) or data.features and data.features[alternative] or ""
+ local goodies = mathsettings and mathsettings["goodies"] and (mathsettings["goodies"] [alternative] or mathsettings["goodies"] ["tf"]) or data.goodies and data.goodies [alternative] or ""
+ local parent = replacement["style"][alternative] or ""
+ local fontname, fontfile, fontparent
+ if fallback then
+ fontname = formatters["%s-%s-%s-fallback-%s"](typeface, style, alternative, index)
+ fontfile = formatters["%s-%s-%s-%s"] (typeface, style, alternative, index)
+ fontparent = formatters["%s-%s-%s-fallback-%s"](typeface, style, parent, index)
+ else
+ fontname = synonyms[style][alternative]
+ fontfile = formatters["%s-%s-%s"](typeface, style, alternative)
+ fontparent = formatters["%s-%s-%s"](typeface, style, parent)
+ end
+ if fontdata and #fontdata > 0 then
+ for _, size in next, sizes["default"] do
+ for _, entry in next, fontdata do
+ if entry["minsize"] and entry["maxsize"] then
+ if size[1] > entry["minsize"] and size[1] <= entry["maxsize"] then
+ local filepath, filename = splitbase(entry["filename"])
+ registerdesignsizes( fontfile, size[2], filename )
+ end
+ end
+ end
+ end
+ for _, entry in next, fontdata do
+ local designsize = entry["designsize"] or 100
+ if designsize == 100 or designsize == 110 or designsize == 120 or designsize == 0 or #fontdata == 1 then
+ local filepath, filename = splitbase(entry["filename"])
+ if entry["format"] == "ttc" or entry["format"] == "dfont" then
+ filename = formatters["%s(%s)"](filename, entry["rawname"])
+ end
+ registerdesignsizes( fontfile, "default", filename )
+ break
+ end
+ end
+ if fallback then
+ -- can we use
+ ctx_definefontsynonym( { fontname }, { fontfile }, { features = features } )
+ else
+ ctx_definefontsynonym( { fontname }, { fontfile }, { features = features, fallbacks = fontfile, goodies = goodies } )
+ end
+ else
+ if fallback then
+ ctx_definefontsynonym( { fontname }, { fontparent }, { features = features } )
+ else
+ ctx_definefontsynonym( { fontname }, { fontparent }, { features = features, fallbacks = fontfile, goodies = goodies } )
+ end
+ end
+end
+
+local function definetypescript(index)
+ local data = data[index]
+ local entry = data.fonts
+ local mathsettings = mathsettings[cleanname(data.metadata.family)]
+ local goodies = mathsettings and mathsettings.extras or data.options.goodies
+ local typeface = data.metadata.typeface
+ local style = data.metadata.style
+ if entry and entry["tf"] then
+ ctx_startfontclass( { typeface } )
+ if goodies ~= "" then
+ goodies = utilities.parsers.settings_to_array(goodies)
+ for _, goodie in next, goodies do
+ ctx_loadfontgoodies( { goodie } )
+ end
+ end
+ for alternative, _ in next, alternatives do
+ if synonyms[style][alternative] then -- prevent unnecessary synonyms for handwriting, calligraphy and math
+ definefontsynonym(data,alternative)
+ end
+ end
+ ctx_stopfontclass()
+ else
+ -- regular style not available, loading aborted
+ end
+end
+
+function selectfont.registerfallback(typeface,style,index)
+ local t = fallbacks[typeface]
+ if not t then
+ fallbacks[typeface] = { [style] = { index } }
+ else
+ local s = t[style]
+ if not s then
+ fallbacks[typeface][style] = { index }
+ else
+ fallbacks[typeface][style][#s+1] = index
+ end
+ end
+end
+
+local function definetextfontfallback(data,alternative,index)
+ local typeface = data.metadata.typeface
+ local style = data.metadata.style
+ local features = data.features[alternative]
+ local range = data.options.range
+ local rscale = data.options.scale ~= "" and data.options.scale or 1
+ local check = data.options.check ~= "" and data.options.check or "yes"
+ local force = data.options.force ~= "" and data.options.force or "yes"
+ local synonym = formatters["%s-%s-%s-fallback-%s"](typeface, style, alternative, index)
+ local fallback = formatters["%s-%s-%s"] (typeface, style, alternative)
+ if index == 1 then
+ ctx_resetfontfallback( { fallback } )
+ end
+ ctx_definefontfallback( { fallback }, { synonym }, { range }, { rscale = rscale, check = check, force = force } )
+end
+
+local function definetextfallback(entry,index)
+ local data = data[index]
+ local typeface = data.metadata.typeface
+ ctx_startfontclass( { typeface } )
+ for alternative, _ in next, alternatives do
+ definefontsynonym (data,alternative,entry,true)
+ definetextfontfallback(data,alternative,entry)
+ end
+ ctx_stopfontclass()
+ -- inspect(data)
+end
+
+local function definemathfontfallback(data,alternative,index)
+ local typeface = data.metadata.typeface
+ local style = data.metadata.style
+ local range = data.options.range
+ local rscale = data.options.scale ~= "" and data.options.scale or 1
+ local check = data.options.check ~= "" and data.options.check or "yes"
+ local force = data.options.force ~= "" and data.options.force or "yes"
+ local offset = data.options.offset
+ local features = data.features[alternative]
+ local fontdata = data.fonts and data.fonts[alternative]
+ local fallback = formatters["%s-%s-%s"](typeface, style, alternative)
+ if index == 1 then
+ ctx_resetfontfallback( { fallback } )
+ end
+ if fontdata and #fontdata > 0 then
+ for _, entry in next, fontdata do
+ local filename = entry["filename"]
+ local designsize = entry["designsize"] or 100
+ if designsize == 100 or designsize == 110 or designsize == 120 or designsize == 0 or #fontdata == 1 then
+ ctx_definefontfallback( { fallback }, { formatters["file:%s*%s"](filename,features) }, { range }, { rscale = rscale, check = check, force = force, offset = offset } )
+ break
+ end
+ end
+ end
+end
+
+local function definemathfallback(entry,index)
+ local data = data[index]
+ local typeface = data.metadata.typeface
+ local style = data.metadata.style
+ ctx_startfontclass( { typeface } )
+ for alternative, _ in next, alternatives do
+ if synonyms[style][alternative] then
+ definemathfontfallback(data,alternative,entry)
+ end
+ end
+ ctx_stopfontclass()
+ -- inspect(data)
+end
+
+local function definefallbackfont(index)
+ local data = data[index]
+ local f = fallbacks[data.metadata.typeface]
+ if f then
+ local s = f[data.metadata.style]
+ if s then
+ for entry, fallback in next, s do
+ if data.metadata.style == "mm" then
+ definemathfallback(entry,fallback)
+ else
+ definetextfallback(entry,fallback)
+ end
+ end
+ end
+ end
+end
+
+local function definetextfont(index)
+ local data = data[index]
+ local fontclass = data.metadata.typeface
+ local shortstyle = data.metadata.style
+ local style = styles[data.metadata.style]
+ local designsize = data.options.opticals == v_yes and "auto" or "default"
+ local scale = data.options.scale ~= "" and data.options.scale or 1
+ ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { "" }, { "default" }, { designsize = designsize, rscale = scale } )
+end
+
+local function definemathfont(index)
+ local data = data[index]
+ local fontclass = data.metadata.typeface
+ local shortstyle = data.metadata.style
+ local style = styles[data.metadata.style]
+ local scale = data.options.scale ~= "" and data.options.scale or 1
+ local typescript = cleanname(data.metadata.family)
+ local entries = data.fonts
+ if entries then
+ ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { "" }, { "default" }, { rscale = scale } )
+ else
+ ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { typescript }, { "default" }, { rscale = scale } )
+ end
+end
+
+function selectfont.definetypeface(index)
+ local data = data[index]
+ if data.metadata.style == "mm" then
+ definefallbackfont(index)
+ definetypescript (index)
+ definemathfont (index)
+ else
+ definefallbackfont(index)
+ definetypescript (index)
+ definetextfont (index)
+ end
+ -- inspect(data)
+end
+
+local styles = {
+ { "tf" }, { "bf" }, { "it" }, { "sl" }, { "bi" }, { "bs" }, { "sc" },
+}
+
+implement {
+ name = "defineselectfont",
+ actions = { selectfont.define, context },
+ arguments = {
+ {
+ {
+ "metadata", {
+ { "typeface" },
+ { "style" },
+ { "family" },
+ }
+ },
+ {
+ "options", {
+ { "opticals" },
+ { "scale" },
+ { "goodies" },
+ { "alternative" },
+ { "range" },
+ { "offset" },
+ { "check" },
+ { "force" },
+ }
+ },
+ { "alternatives", styles },
+ { "files", styles },
+ { "features", styles },
+ }
+ }
+}
+
+implement {
+ name = "definefontfamily",
+ actions = selectfont.definetypeface,
+ arguments = "integer"
+}
+
+implement {
+ name = "definefallbackfamily",
+ actions = selectfont.registerfallback,
+ arguments = { "string", "string", "integer"}
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sel.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sel.mkvi
new file mode 100644
index 00000000000..eb45ea03386
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sel.mkvi
@@ -0,0 +1,429 @@
+%D \module
+%D [ file=font-sel,
+%D version=2014.07.27,
+%D title=\CONTEXT\ User Module,
+%D subtitle=Selectfont,
+%D author=Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright=Wolfgang Schuster,
+%D license=GNU General Public License]
+
+\writestatus{loading}{ConTeXt User Module / Selectfont}
+
+\registerctxluafile{font-sel}{1.000}
+
+\unprotect
+
+\installcorenamespace {selectfont}
+\installsimplecommandhandler \??selectfont {selectfont}
+
+\unexpanded\def\selectfont_setparameters[#settings]%
+ {\begingroup
+ \setupcurrentselectfont[#settings]%
+ \edef\p_selectfont_preset{\selectfontparameter\c!preset}%
+ \ifx\p_selectfont_preset\empty \else
+ \processcommacommand[\p_selectfont_preset]\selectfont_preset_process
+ \setupcurrentselectfont[#settings]%
+ \fi
+ \setexpandedselectfontparameter\c!style {\expandnamespaceparameter\??selectfontstyle \selectfontparameter\c!style \s!rm }%
+ \setexpandedselectfontparameter\c!alternative{\expandnamespaceparameter\??selectfontalternative\selectfontparameter\c!alternative\v!default}%
+ \xdef\selectfont_index{\clf_defineselectfont
+ metadata {%
+ typeface {\selectfontparameter\c!name}%
+ style {\selectfontparameter\c!style}%
+ family {\selectfontparameter\c!family}%
+ }
+ options {%
+ opticals {\selectfontparameter\c!opticalsize}%
+ scale {\selectfontparameter\c!scale}%
+ goodies {\selectfontparameter\c!goodies}%
+ alternative {\selectfontparameter\c!alternative}%
+ range {\selectfontparameter\c!range}% fallback only
+ offset {\selectfontparameter\c!offset}% fallback only
+ check {\selectfontparameter\c!check}% fallback only
+ force {\selectfontparameter\c!force}% fallback only
+ }
+ alternatives {%
+ tf {\selectfontparameter\s!tf}%
+ bf {\selectfontparameter\s!bf}%
+ it {\selectfontparameter\s!it}%
+ sl {\selectfontparameter\s!sl}%
+ bi {\selectfontparameter\s!bi}%
+ bs {\selectfontparameter\s!bs}%
+ sc {\selectfontparameter\s!sc}%
+ }
+ files {%
+ tf {\selectfontparameter\c!regularfont}%
+ bf {\selectfontparameter\c!boldfont}%
+ it {\selectfontparameter\c!italicfont}%
+ sl {\selectfontparameter\c!slantedfont}%
+ bi {\selectfontparameter\c!bolditalicfont}%
+ bs {\selectfontparameter\c!boldslantedfont}%
+ sc {\selectfontparameter\c!smallcapsfont}%
+ }
+ features {%
+ tf {\selectfontparameter\c!regularfeatures}%
+ bf {\selectfontparameter\c!boldfeatures}%
+ it {\selectfontparameter\c!italicfeatures}%
+ sl {\selectfontparameter\c!slantedfeatures}%
+ bi {\selectfontparameter\c!bolditalicfeatures}%
+ bs {\selectfontparameter\c!boldslantedfeatures}%
+ sc {\selectfontparameter\c!smallcapsfeatures}%
+ }}%
+ \endgroup}
+
+%D \macros
+%D {defineselectfontstyle}
+
+\installcorenamespace {selectfontstyle}
+
+\unexpanded\def\defineselectfontstyle
+ {\dodoubleargument\selectfont_style_define}
+
+\def\selectfont_style_define[#styles][#shortstyle]%
+ {\processcommalist[#styles]{\selectfont_style_define_indeed{#shortstyle}}}
+
+\def\selectfont_style_define_indeed#shortstyle#style%
+ {\setvalue{\??selectfontstyle#style}{#shortstyle}}
+
+\defineselectfontstyle [\s!rm,\s!serif] [\s!rm]
+\defineselectfontstyle [\s!ss,\s!sans] [\s!ss]
+\defineselectfontstyle [\s!tt,\s!mono] [\s!tt]
+\defineselectfontstyle [\s!hw,\s!handwriting] [\s!hw]
+\defineselectfontstyle [\s!cg,\s!calligraphy] [\s!cg]
+\defineselectfontstyle [\s!mm,\s!math] [\s!mm]
+
+%D \macros
+%D {definefontfamilypreset}
+
+\installcorenamespace {selectfontpreset}
+
+\unexpanded\def\definefontfamilypreset
+ {\dodoubleargument\selectfont_preset_define}
+
+\def\selectfont_preset_define[#name][#settings]%
+ {\doifelseassignment{#settings}
+ {\setvalue{\??selectfontpreset#name}{\setupcurrentselectfont[#settings]}}
+ {\setvalue{\??selectfontpreset#name}{\csname\??selectfontpreset#settings\endcsname}}}
+
+\def\selectfont_preset_process#name%
+ {\ifcsname\??selectfontpreset#name\endcsname
+ \lastnamedcs
+ \else
+ % unknown preset
+ \fi}
+
+\definefontfamilypreset
+ [range:chinese]
+ [\c!range={cjkcompatibilityforms,
+ cjkcompatibilityideographs,
+ cjkcompatibilityideographssupplement,
+ cjkradicalssupplement,
+ cjkstrokes,
+ cjksymbolsandpunctuation,
+ cjkunifiedideographs,
+ cjkunifiedideographsextensiona,
+ cjkunifiedideographsextensionb,
+ halfwidthandfullwidthforms,
+ verticalforms,
+ bopomofo,
+ bopomofoextended}]
+
+\definefontfamilypreset
+ [range:japanese]
+ [\crange={cjkcompatibilityforms,
+ cjkcompatibilityideographs,
+ cjkcompatibilityideographssupplement,
+ cjkradicalssupplement,
+ cjkstrokes,
+ cjksymbolsandpunctuation,
+ cjkunifiedideographs,
+ cjkunifiedideographsextensiona,
+ cjkunifiedideographsextensionb,
+ halfwidthandfullwidthforms,
+ verticalforms,
+ hiragana,
+ katakana}]
+
+\definefontfamilypreset
+ [range:korean]
+ [\c!range={cjkcompatibilityforms,
+ cjkcompatibilityideographs,
+ cjkcompatibilityideographssupplement,
+ cjkradicalssupplement,
+ cjkstrokes,
+ cjksymbolsandpunctuation,
+ cjkunifiedideographs,
+ cjkunifiedideographsextensiona,
+ cjkunifiedideographsextensionb,
+ halfwidthandfullwidthforms,
+ verticalforms,
+ hangulcompatibilityjamo,
+ hanguljamo,
+ hanguljamoextendeda,
+ hanguljamoextendedb,
+ hangulsyllables}]
+
+\definefontfamilypreset
+ [range:cyrillic]
+ [\c!range={cyrillic,
+ cyrillicextendeda,
+ cyrillicextendedb,
+ cyrillicsupplement}]
+
+\definefontfamilypreset
+ [range:greek]
+ [\c!range={greekandcoptic,
+ greekextended,
+ ancientgreeknumbers}]
+
+\definefontfamilypreset
+ [range:hebrew]
+ [\c!range={hebrew,
+ alphabeticpresentationforms}]
+
+\definefontfamilypreset [math:digitsnormal] [\c!range=digitsnormal]
+\definefontfamilypreset [math:digitsbold] [\c!range=digitsnormal,\c!offset=digitsbold,\s!tf=style:bold]
+
+\definefontfamilypreset [math:uppercasenormal] [\c!range=uppercasenormal]
+\definefontfamilypreset [math:uppercaseitalic] [\c!range=uppercasenormal,\c!offset=uppercaseitalic, \s!tf=style:italic]
+\definefontfamilypreset [math:uppercasebold] [\c!range=uppercasenormal,\c!offset=uppercasebold, \s!tf=style:bold]
+\definefontfamilypreset [math:uppercasebolditalic] [\c!range=uppercasenormal,\c!offset=uppercasebolditalic,\s!tf=style:bolditalic]
+
+\definefontfamilypreset [math:lowercasenormal] [\c!range=lowercasenormal]
+\definefontfamilypreset [math:lowercaseitalic] [\c!range=lowercasenormal,\c!offset=lowercaseitalic, \s!tf=style:italic]
+\definefontfamilypreset [math:lowercasebold] [\c!range=lowercasenormal,\c!offset=lowercasebold, \s!tf=style:bold]
+\definefontfamilypreset [math:lowercasebolditalic] [\c!range=lowercasenormal,\c!offset=lowercasebolditalic,\s!tf=style:bolditalic]
+
+\definefontfamilypreset [math:mathematicaloperators] [\c!range=mathematicaloperators]
+
+\definefontfamilypreset [math:lowercasegreeknormal] [\c!range=lowercasegreeknormal]
+\definefontfamilypreset [math:lowercasegreekitalic] [\c!range=lowercasegreeknormal,\c!offset=lowercasegreekitalic, \s!tf=style:italic]
+\definefontfamilypreset [math:lowercasegreekbold] [\c!range=lowercasegreeknormal,\c!offset=lowercasegreekbold, \s!tf=style:bold]
+\definefontfamilypreset [math:lowercasegreekbolditalic] [\c!range=lowercasegreeknormal,\c!offset=lowercasegreekbolditalic,\s!tf=style:bolditalic]
+
+\definefontfamilypreset [math:uppercasegreeknormal] [\c!range=uppercasegreeknormal]
+\definefontfamilypreset [math:uppercasegreekitalic] [\c!range=uppercasegreeknormal,\c!offset=uppercasegreekitalic, \s!tf=style:italic]
+\definefontfamilypreset [math:uppercasegreekbold] [\c!range=uppercasegreeknormal,\c!offset=uppercasegreekbold, \s!tf=style:bold]
+\definefontfamilypreset [math:uppercasegreekbolditalic] [\c!range=uppercasegreeknormal,\c!offset=uppercasegreekbolditalic,\s!tf=style:bolditalic]
+
+
+%D \macros
+%D {defineselectfontalternative}
+%D
+%D The results between the old {\em simplefonts} and the new {\em selectfont}
+%D can be different because simplefonts the name entries in the database to find
+%D the styles for a font while selectfont the newer spec-method to the find the
+%D files for each style.
+%D
+%D The used method depends on the command one uses to load a font but it is
+%D also possible to switch between them with the {\em alternative} key, possible
+%D values are:
+%D
+%D \startitemize[packed]
+%D \startitem selectfont and \stopitem
+%D \startitem simplefonts. \stopitem
+%D \stopitemize
+
+\installcorenamespace {selectfontalternative}
+
+\unexpanded\def\defineselectfontalternative
+ {\dodoubleargument\selectfont_alternative_define}
+
+\def\selectfont_alternative_define[#name][#alternative]%
+ {\setvalue{\??selectfontalternative#name}{#alternative}}
+
+\defineselectfontalternative [\v!selectfont ] [\v!selectfont ]
+\defineselectfontalternative [\v!simplefonts] [\v!simplefonts]
+\defineselectfontalternative [\v!default ] [\v!default ]
+
+%D \macros
+%D {definefontfamily,definefallbackfamily}
+%D
+%D The \tex{definefontfamily} creates like \tex{definetypeface} a collection of font
+%D with different styles which can be later called with the \tex{setupbodyfont} command.
+%D
+%D The command takes three mendatory commands which are (a) the name of the fontclass,
+%D (b) the styles of the font and (c) the name of the font.
+%D
+%D \starttyping
+%D \definefontfamily [dejavu] [serif] [DejaVu Serif]
+%D \definefontfamily [dejavu] [sans] [DejaVu Sans]
+%D \definefontfamily [dejavu] [mono] [DejaVu Sans Mono]
+%D \definefontfamily [dejavu] [math] [XITS Math] [scale=1.1]
+%D
+%D \definefontfamily [office] [serif] [Times New Roman]
+%D \definefontfamily [office] [sans] [Arial] [scale=0.9]
+%D \definefontfamily [office] [mono] [Courier]
+%D \definefontfamily [office] [math] [TeX Gyre Termes Math]
+%D
+%D \definefontfamily [linux] [serif] [Linux Libertine O]
+%D \definefontfamily [linux] [sans] [Linux Biolinum O]
+%D \definefontfamily [linux] [mono] [Latin Modern Mono]
+%D \definefontfamily [linux] [math] [TeX Gyre Pagella Math] [scale=0.9]
+%D
+%D \setupbodyfont[dejavu]
+%D
+%D \starttext
+%D
+%D \rm Serif \ss Sans \tt Mono \m{1+2=3}
+%D
+%D \switchtobodyfont[office]
+%D
+%D \rm Serif 123 \ss Sans \tt Mono \m{1+2=3}
+%D
+%D \switchtobodyfont[linux]
+%D
+%D \rm Serif 123 \ss Sans \tt Mono \m{1+2=3}
+%D
+%D \stoptext
+%D \stoptyping
+%D
+%D When a document contains different languages and the global font lacks some characters
+%D for one language, one could set a different font where these charcters are taken from.
+%D This fallback font (there can be more than one for a certain style) could be set with
+%D the \tex{definefallbackfamily} command which takes the same argument as
+%D the \tex{definefontfamily} command.
+%D
+%D \starttyping
+%D \definefallbackfamily [mainface] [serif] [DejaVu Serif] [range=cyrillic]
+%D \definefontfamily [mainface] [serif] [TeX Gyre Pagella]
+%D
+%D \setupbodyfont[mainface]
+%D
+%D \setuplanguage[en][patterns={us,ru}]
+%D
+%D \starttext
+%D
+%D \input knuth
+%D
+%D Традиционная систематика лишайников оказывается во многом условна и
+%D
+%D \stoptext
+%D \stoptyping
+%D
+%D Another feature of the module is the \type{opticalsize} key which allows one to enable
+%D optical sizes when they are a feature of the requested font.
+%D
+%D \starttyping
+%D \definefontfamily[mainface][serif][Latin Modern Roman][opticalsize=yes]
+%D
+%D \setupbodyfont[mainface]
+%D
+%D \starttext
+%D \scale[width=\textwidth]{\switchtobodyfont [6pt]\tf Regular, \it Italic \bf Bold and \bi BoldItalic}
+%D \scale[width=\textwidth]{\switchtobodyfont [8pt]\tf Regular, \it Italic \bf Bold and \bi BoldItalic}
+%D \scale[width=\textwidth]{\switchtobodyfont [10pt]\tf Regular, \it Italic \bf Bold and \bi BoldItalic}
+%D \scale[width=\textwidth]{\switchtobodyfont [12pt]\tf Regular, \it Italic \bf Bold and \bi BoldItalic}
+%D \scale[width=\textwidth]{\switchtobodyfont[17.3pt]\tf Regular, \it Italic \bf Bold and \bi BoldItalic}
+%D \stoptext
+%D \stoptyping
+
+% regularfont = … | * … | name:… | name:* … | file:… | file:* … | spec:…-…-… | style:medium
+
+\unexpanded\def\definefontfamily
+ {\doquadrupleempty\selectfont_family_define}
+
+\def\selectfont_family_define[#typeface][#style][#family][#settings]%
+ {\doifelseassignment{#settings}
+ {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},#settings]}
+ {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},\c!preset={#settings}]}%
+ \clf_definefontfamily\selectfont_index\relax}
+
+\unexpanded\def\definefallbackfamily
+ {\doquadrupleempty\selectfont_fallback_define}
+
+\def\selectfont_fallback_define[#typeface][#style][#family][#settings]%
+ {\doifelseassignment{#settings}
+ {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},#settings]}
+ {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},\c!preset={#settings}]}%
+ \edef\p_selectfont_style{\expandnamespacevalue\??selectfontstyle{#style}\s!rm}%
+ \clf_definefallbackfamily{#typeface}{\p_selectfont_style}\selectfont_index\relax}
+
+%D \macros
+%D {setupfontfamily,setupfallbackfamily}
+%D
+%D For simple documents which don’t need complex font settings one could use
+%D the \tex{setupfontfamily} command where the requested font is enabled immediately
+%D without the need to load it with \tex{setupbodyfont}. The downside of this method
+%D is that processing of the document takes longer with each additional font which
+%D is set with \tex{setupfontfamily}.
+%D
+%D \starttyping
+%D \setupfontfamily [serif] [DejaVu Serif]
+%D \setupfontfamily [sans] [DejaVu Sans]
+%D \setupfontfamily [mono] [DejaVu Sans Mono]
+%D \setupfontfamily [math] [XITS Math] [scale=1.1]
+%D
+%D \starttext
+%D
+%D \rm Serif 123 \ss Sans \tt Mono \m{1+2=3}
+%D
+%D \stoptext
+%D \stoptyping
+
+\newcount\c_selectfont_family
+\newtoks \t_selectfont_fallback
+\newtoks \t_selectfont_styles
+
+\unexpanded\def\setupfontfamily
+ {\dotripleempty\selectfont_family_setup}
+
+\def\selectfont_family_setup
+ {\ifsecondargument
+ \expandafter\selectfont_family_setup_yes
+ \else
+ \expandafter\selectfont_family_setup_nop
+ \fi}
+
+\def\selectfont_family_setup_yes[#style][#family][#settings]%
+ {\normalexpanded{\t_selectfont_styles{\selectfont_set_font_family[#style][#family][#settings]\the\t_selectfont_styles}}%
+ \selectfont_set_font_indeed}
+
+\def\selectfont_family_setup_nop[#settings][#dummya][#dummyb]%
+ {\setupselectfont[#settings]}
+
+\unexpanded\def\selectfont_set_default
+ {\selectfont_set_font_family[\v!serif][Latin Modern Roman][\c!opticalsize=\v!yes]%
+ \selectfont_set_font_family[\v!sans] [Latin Modern Sans] [\c!opticalsize=\v!yes]%
+ \selectfont_set_font_family[\v!mono] [Latin Modern Mono] [\c!opticalsize=\v!yes,\c!features=\s!none]%
+ \selectfont_set_font_family[\v!math] [Latin Modern Math] [\c!opticalsize=\v!yes]}
+
+\unexpanded\def\setupfallbackfamily
+ {\dotripleempty\selectfont_fallback_setup}
+
+\def\selectfont_fallback_setup[#style][#family][#settings]%
+ {\normalexpanded{\t_selectfont_fallback{\the\t_selectfont_fallback\selectfont_set_font_fallback[#style][#family][#settings]}}}
+
+\def\selectfont_set_font_indeed
+ {\global\advance\c_selectfont_family\plusone
+ \edef\m_selectfont_typeface{\v!selectfont-\number\c_selectfont_family}%
+ \the\t_selectfont_fallback
+ \the\t_selectfont_styles
+ \selectfont_set_default
+ \setupbodyfont[\m_selectfont_typeface,\rootselectfontparameter\c!style]}
+
+\unexpanded\def\selectfont_set_font_family[#style]#dummy[#family]#dummy[#settings]%
+ {\ifcsname\m_selectfont_typeface#style\endcsname \else
+ \expandafter\let\csname\m_selectfont_typeface#style\endcsname\relax
+ \selectfont_family_define[\m_selectfont_typeface][#style][#family][#settings]%
+ \fi}
+
+\unexpanded\def\selectfont_set_font_fallback[#style]#dummy[#family]#dummy[#settings]%
+ {\selectfont_fallback_define[\m_selectfont_typeface][#style][#family][#settings]}
+
+%D You can apply a different feature set to each style of a font but if nothing
+%D is set the global features are used.
+
+\setupselectfont
+ [ \c!features=\s!default,
+ \c!regularfeatures=\selectfontparameter\c!features,
+ \c!boldfeatures=\selectfontparameter\c!features,
+ \c!italicfeatures=\selectfontparameter\c!features,
+ \c!slantedfeatures=\selectfontparameter\c!features,
+ \c!bolditalicfeatures=\selectfontparameter\c!features,
+ \c!boldslantedfeatures=\selectfontparameter\c!features,
+ \c!smallcapsfeatures=\s!smallcaps,
+ \c!style=\s!rm]
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi
new file mode 100644
index 00000000000..b29545ace3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=font-set,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Initial Loading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Initial Loading}
+
+\unprotect
+
+%D Defining fonts using \type{\definebodyfont} takes time, so we
+%D prefer to predefine at least the Computer Modern Roman
+%D fonts. However, loading all those fonts at definition time
+%D would take both time and space. But even worse, once fonts
+%D are loaded into memory, their encoding vector is fixed,
+%D which is a handicap when we want to distribute the compact
+%D \type{fmt} files. So what we want to do is defining fonts in
+%D a way that postpones the loading. We accomplish this by only
+%D loading the fonts when we switch to another bodyfont size.
+%D Among the other alternatives, such as loading the font at
+%D the moment of activation and redefining the activation
+%D macro afterwards, this proved to be the most efficient
+%D alternative.
+%D
+%D The next few macros take care of the one exeption on this
+%D scheme. When at format generation time we load the default
+%D font file, the one that defines the Computer Modern Fonts,
+%D we don't want the fonts metrics to end up in the format
+%D file, so we temporary prohibit loading. This means that at
+%D runtime we have to load the default bodyfont size just before
+%D we start typesetting.
+
+% \enablemode[lmmath]
+
+\let\m_font_fallback_name\empty
+
+% keep as reference:
+%
+% \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}
+
+\def\font_preload_check_mode
+ {\doifelsemode{lmmath}
+ {\def\m_font_fallback_name{modern-designsize-virtual}}% this will stay
+ {\def\m_font_fallback_name{modern-designsize}}% % this might become 'modern'
+ \glet\font_preload_check_mode\relax}
+
+\def\font_preload_default_fonts
+ {\font_preloads_reset
+ \font_preload_check_mode
+ \setupbodyfont[\m_font_fallback_name,\fontstyle,\fontbody]%
+ \showmessage\m!fonts6{fallback \m_font_fallback_name\space \fontstyle\normalspace\normalizedbodyfontsize}}
+
+\def\font_preload_default_fonts_mm
+ {\font_preload_check_mode
+ \writestatus\m!fonts{preloading \m_font_fallback_name\space (math)}%
+ \definetypeface[\fontclass][\s!mm][\s!math][\m_font_fallback_name][\s!default]%
+ \showmessage\m!fonts6{fallback \m_font_fallback_name\space mm \normalizedbodyfontsize}}
+
+\def\font_preload_default_fonts_tt
+ {\font_preload_check_mode
+ \writestatus\m!fonts{preloading \m_font_fallback_name\space (mono)}%
+ \definetypeface[\fontclass][\s!tt][\s!mono][\m_font_fallback_name][\s!default]%
+ \showmessage\m!fonts6{fallback \m_font_fallback_name\space tt \normalizedbodyfontsize}}
+
+\def\font_preloads_reset
+ {\glet\font_preload_default_fonts \relax
+ %\glet\font_preload_default_fonts_tt\relax
+ %\glet\font_preload_default_fonts_mm\relax
+ \glet\font_preloads_zero_stage \relax
+ \glet\font_preloads_first_stage \relax
+ \glet\font_preloads_second_stage \relax
+ %\glet\font_preloads_third_stage \relax
+ \glet\fourthstagepreloadfonts \relax
+ \global\everyhbox\emptytoks
+ \global\everyvbox\emptytoks
+ % old: \font_preloads_reset_nullfont, new:
+ \clf_resetnullfont}
+
+\appendtoks
+ \font_preloads_reset
+\to \everystartnotext
+
+\def\font_preloads_reset_checked
+ {\glet\font_preload_default_fonts_tt\relax
+ \glet\font_preload_default_fonts_mm\relax
+ \glet\font_preloads_third_stage \relax
+% \glet\font_preloads_fourth_stage \relax
+ }
+
+\def\font_preloads_zero_stage_indeed
+ {\definedfont[\s!file:lmmono10-regular sa 1]}
+
+\unexpanded\def\font_preloads_zero_stage
+ {\writestatus\m!fonts{beware: no fonts are loaded yet, using 'lm mono' in box}%
+ \glet\font_preloads_zero_stage\font_preloads_zero_stage_indeed
+ \font_preloads_zero_stage}
+
+\unexpanded\def\font_preloads_first_stage % % *nofonts -> *preloadfonts
+ {\doifelsemode{*preloadfonts}
+ {\font_preload_default_fonts
+ \writestatus\m!fonts{preloading latin modern fonts (first stage)}}
+ {\writestatus\m!fonts{latin modern fonts are not preloaded}}}
+
+\unexpanded\def\font_preloads_second_stage
+ {\writestatus\m!fonts{preloading latin modern fonts (second stage)}%
+ \font_preload_default_fonts}
+
+\unexpanded\def\font_preloads_third_stage % always
+ {\ifx\fontclass\empty
+ \writestatus\m!fonts{preloading latin modern fonts (third stage)}%
+ \font_preload_default_fonts
+ \font_preloads_reset
+ \else
+ \font_preloads_reset
+ \pushmacro\fontstyle
+ \ifcsname\??fontclass\fontclass\s!mm\s!features\endcsname \else
+ \font_preload_default_fonts_mm
+ \fi
+ \ifcsname\??fontclass\fontclass\s!tt\s!features\endcsname \else
+ \font_preload_default_fonts_tt
+ \fi
+ \popmacro\fontstyle
+ \font_preloads_reset_checked % reset third, mm and tt
+ \setupbodyfont[\fontstyle]%
+ \fi}
+
+\unexpanded\def\font_preloads_fourth_stage
+ {\begingroup
+ %ifzeropt\fontcharwd\font\number`!\relax
+ \setbox\scratchbox\hbox{c o n t e x t}%
+ \ifzeropt\wd\scratchbox
+ \writeline
+ \writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}%
+ \writestatus\m!fonts{!! loaded (maybe due to a missing \string\starttext).}%
+ \writeline
+ \fi
+ \font_preloads_reset
+ \endgroup}
+
+\appendtoks
+ \everyhbox{\font_preloads_zero_stage}%
+ \everyvbox{\font_preloads_zero_stage}%
+\to \everydump
+
+\unexpanded\def\font_preloads_at_every_job {\font_preloads_first_stage }
+\unexpanded\def\font_preloads_at_start_text{\font_preloads_second_stage}
+\unexpanded\def\font_preloads_at_stop_text {\font_preloads_fourth_stage}
+\unexpanded\def\font_preloads_at_definition{\font_preloads_third_stage
+ \glet\font_preloads_at_definition\relax}
+
+% \unexpanded\def\checkpreloadedbodyfont % no \let here
+% {\font_preloads_at_start_text}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua b/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua
new file mode 100644
index 00000000000..8d45552a5e9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua
@@ -0,0 +1,956 @@
+if not modules then modules = { } end modules ['font-sol'] = { -- this was: node-spl
+ version = 1.001,
+ comment = "companion to font-sol.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module is dedicated to the oriental tex project and for
+-- the moment is too experimental to be publicly supported.
+--
+-- We could cache solutions: say that we store the featureset and
+-- all 'words' -> replacement ... so we create a large solution
+-- database (per font)
+--
+-- This module can be optimized by using a dedicated dynamics handler
+-- but I'll only do that when the rest of the code is stable.
+--
+-- Todo: bind setups to paragraph.
+
+local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove
+local next, tostring, tonumber = next, tostring, tonumber
+local insert, remove = table.insert, table.remove
+local utfchar = utf.char
+local random = math.random
+
+local utilities, logs, statistics, fonts, trackers = utilities, logs, statistics, fonts, trackers
+local interfaces, commands, attributes = interfaces, commands, attributes
+local nodes, node, tex = nodes, node, tex
+
+local trace_split = false trackers.register("builders.paragraphs.solutions.splitters.splitter", function(v) trace_split = v end)
+local trace_optimize = false trackers.register("builders.paragraphs.solutions.splitters.optimizer", function(v) trace_optimize = v end)
+local trace_colors = false trackers.register("builders.paragraphs.solutions.splitters.colors", function(v) trace_colors = v end)
+local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+
+local report_solutions = logs.reporter("fonts","solutions")
+local report_splitters = logs.reporter("fonts","splitters")
+local report_optimizers = logs.reporter("fonts","optimizers")
+
+local variables = interfaces.variables
+
+local v_normal = variables.normal
+local v_reverse = variables.reverse
+local v_preroll = variables.preroll
+local v_random = variables.random
+local v_split = variables.split
+
+local implement = interfaces.implement
+
+local settings_to_array = utilities.parsers.settings_to_array
+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
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setlist = nuts.setlist
+
+local find_node_tail = nuts.tail
+local free_node = nuts.free
+local free_nodelist = nuts.flush_list
+local copy_nodelist = 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 repack_hlist = nuts.repackhlist
+
+local nodes_to_utf = nodes.listtoutf
+
+----- protect_glyphs = nodes.handlers.protectglyphs
+
+local setnodecolor = nodes.tracers.colors.set
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local hlist_code = nodecodes.hlist
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+
+local whatsit_code = nodecodes.whatsit
+
+local fontkern_code = kerncodes.fontkern
+
+local userdefined_code = whatsitcodes.userdefined
+
+local nodepool = nuts.pool
+local usernodeids = nodepool.userids
+
+local new_textdir = nodepool.textdir
+local new_usernumber = nodepool.usernumber
+local new_glue = nodepool.glue
+local new_leftskip = nodepool.leftskip
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+----- process_characters = nodes.handlers.characters
+local inject_kerns = nodes.injections.handler
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local setfontdynamics = fonthashes.setdynamics
+local fontprocesses = fonthashes.processes
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local parbuilders = builders.paragraphs
+parbuilders.solutions = parbuilders.solutions or { }
+local parsolutions = parbuilders.solutions
+parsolutions.splitters = parsolutions.splitters or { }
+local splitters = parsolutions.splitters
+
+local solutions = { } -- attribute sets
+local registered = { } -- backmapping
+splitters.registered = registered
+
+local a_split = attributes.private('splitter')
+
+local preroll = true
+local criterium = 0
+local randomseed = nil
+local optimize = nil -- set later
+local variant = v_normal
+local splitwords = true
+
+local cache = { }
+local variants = { }
+local max_less = 0
+local max_more = 0
+
+local stack = { }
+
+local dummy = {
+ attribute = unsetvalue,
+ randomseed = 0,
+ criterium = 0,
+ preroll = false,
+ optimize = nil,
+ splitwords = false,
+ variant = v_normal,
+}
+
+local function checksettings(r,settings)
+ local s = r.settings
+ local method = settings_to_hash(settings.method or "")
+ local optimize, preroll, splitwords
+ for k, v in next, method do
+ if k == v_preroll then
+ preroll = true
+ elseif k == v_split then
+ splitwords = true
+ elseif variants[k] then
+ variant = k
+ optimize = variants[k] -- last one wins
+ end
+ end
+ r.randomseed = tonumber(settings.randomseed) or s.randomseed or r.randomseed or 0
+ r.criterium = tonumber(settings.criterium ) or s.criterium or r.criterium or 0
+ r.preroll = preroll or false
+ r.splitwords = splitwords or false
+ r.optimize = optimize or s.optimize or r.optimize or variants[v_normal]
+end
+
+local function pushsplitter(name,settings)
+ local r = name and registered[name]
+ if r then
+ if settings then
+ checksettings(r,settings)
+ end
+ else
+ r = dummy
+ end
+ insert(stack,r)
+ -- brr
+ randomseed = r.randomseed or 0
+ criterium = r.criterium or 0
+ preroll = r.preroll or false
+ optimize = r.optimize or nil
+ splitwords = r.splitwords or nil
+ --
+ texsetattribute(a_split,r.attribute)
+ return #stack
+end
+
+local function popsplitter()
+ remove(stack)
+ local n = #stack
+ local r = stack[n] or dummy
+ --
+ randomseed = r.randomseed or 0
+ criterium = r.criterium or 0
+ preroll = r.preroll or false
+ optimize = r.optimize or nil
+ --
+ texsetattribute(a_split,r.attribute)
+ return n
+end
+
+local contextsetups = fonts.specifiers.contextsetups
+
+local function convert(featuresets,name,list)
+ if list then
+ local numbers = { }
+ local nofnumbers = 0
+ for i=1,#list do
+ local feature = list[i]
+ local fs = featuresets[feature]
+ local fn = fs and fs.number
+ if not fn then
+ -- fall back on global features
+ fs = contextsetups[feature]
+ fn = fs and fs.number
+ end
+ if fn then
+ nofnumbers = nofnumbers + 1
+ numbers[nofnumbers] = fn
+ if trace_goodies or trace_optimize then
+ report_solutions("solution %a of %a uses feature %a with number %s",i,name,feature,fn)
+ end
+ else
+ report_solutions("solution %a of %a has an invalid feature reference %a",i,name,feature)
+ end
+ end
+ return nofnumbers > 0 and numbers
+ end
+end
+
+local function initialize(goodies)
+ local solutions = goodies.solutions
+ if solutions then
+ local featuresets = goodies.featuresets
+ local goodiesname = goodies.name
+ if trace_goodies or trace_optimize then
+ report_solutions("checking solutions in %a",goodiesname)
+ end
+ for name, set in next, solutions do
+ set.less = convert(featuresets,name,set.less)
+ set.more = convert(featuresets,name,set.more)
+ end
+ end
+end
+
+fonts.goodies.register("solutions",initialize)
+
+function splitters.define(name,settings)
+ local goodies = settings.goodies
+ local solution = settings.solution
+ local less = settings.less
+ local more = settings.more
+ local less_set, more_set
+ local l = less and settings_to_array(less)
+ local m = more and settings_to_array(more)
+ if goodies then
+ goodies = fonts.goodies.load(goodies) -- also in tfmdata
+ if goodies then
+ local featuresets = goodies.featuresets
+ local solution = solution and goodies.solutions[solution]
+ if l and #l > 0 then
+ less_set = convert(featuresets,name,less) -- take from settings
+ else
+ less_set = solution and solution.less -- take from goodies
+ end
+ if m and #m > 0 then
+ more_set = convert(featuresets,name,more) -- take from settings
+ else
+ more_set = solution and solution.more -- take from goodies
+ end
+ end
+ else
+ if l then
+ local n = #less_set
+ for i=1,#l do
+ local ss = contextsetups[l[i]]
+ if ss then
+ n = n + 1
+ less_set[n] = ss.number
+ end
+ end
+ end
+ if m then
+ local n = #more_set
+ for i=1,#m do
+ local ss = contextsetups[m[i]]
+ if ss then
+ n = n + 1
+ more_set[n] = ss.number
+ end
+ end
+ end
+ end
+ if trace_optimize then
+ report_solutions("defining solutions %a, less %a, more %a",name,concat(less_set or {}," "),concat(more_set or {}," "))
+ end
+ local nofsolutions = #solutions + 1
+ local t = {
+ solution = solution,
+ less = less_set or { },
+ more = more_set or { },
+ settings = settings, -- for tracing
+ attribute = nofsolutions,
+ }
+ solutions[nofsolutions] = t
+ registered[name] = t
+ return nofsolutions
+end
+
+local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0
+
+local splitter_one = usernodeids["splitters.one"]
+local splitter_two = usernodeids["splitters.two"]
+
+local a_word = attributes.private('word')
+local a_fontkern = attributes.private('fontkern')
+
+local encapsulate = false
+
+directives.register("builders.paragraphs.solutions.splitters.encapsulate", function(v)
+ encapsulate = v
+end)
+
+function splitters.split(head)
+ -- quite fast
+ head = tonut(head)
+ local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0
+ cache, max_less, max_more = { }, 0, 0
+ local function flush() -- we can move this
+ local font = getfont(start)
+ local last = getnext(stop)
+ local list = last and copy_nodelist(start,last) or copy_nodelist(start)
+ local n = #cache + 1
+ if encapsulate then
+ local user_one = new_usernumber(splitter_one,n)
+ local user_two = new_usernumber(splitter_two,n)
+ head, start = insert_node_before(head,start,user_one)
+ insert_node_after(head,stop,user_two)
+ else
+ local current = start
+ while true do
+ setattr(current,a_word,n)
+ if current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ end
+ if rlmode == "TRT" or rlmode == "+TRT" then
+ local dirnode = new_textdir("+TRT")
+ setlink(dirnode,list)
+ list = dirnode
+ end
+ local c = {
+ original = list,
+ attribute = attribute,
+ direction = rlmode,
+ font = font
+ }
+ if trace_split then
+ report_splitters("cached %4i: font %a, attribute %a, direction %a, word %a",
+ n, font, attribute, nodes_to_utf(list,true), rlmode and "r2l" or "l2r")
+ end
+ cache[n] = c
+ local solution = solutions[attribute]
+ local l, m = #solution.less, #solution.more
+ if l > max_less then max_less = l end
+ if m > max_more then max_more = m end
+ start, stop, done = nil, nil, true
+ end
+ while current do -- also nextid
+ local next = getnext(current)
+ local id = getid(current)
+ if id == glyph_code then
+ if getsubtype(current) < 256 then
+ local a = getattr(current,a_split)
+ if not a then
+ start, stop = nil, nil
+ elseif not start then
+ start, stop, attribute = current, current, a
+ elseif a ~= attribute then
+ start, stop = nil, nil
+ else
+ stop = current
+ end
+ end
+ elseif id == disc_code then
+ if splitwords then
+ if start then
+ flush()
+ end
+ elseif start and next and getid(next) == glyph_code and getsubtype(next) < 256 then
+ -- beware: we can cross future lines
+ stop = next
+ else
+ start, stop = nil, nil
+ end
+ elseif id == dir_code or id == localpar_code then
+ if start then
+ flush()
+ end
+ rlmode = getfield(current,"dir")
+ else
+ if start then
+ flush()
+ end
+ end
+ current = next
+ end
+ if start then
+ flush()
+ end
+ nofparagraphs = nofparagraphs + 1
+ nofwords = nofwords + #cache
+ return tonode(head), done
+end
+
+local function collect_words(list) -- can be made faster for attributes
+ local words, w, word = { }, 0, nil
+ if encapsulate then
+ for current in traverse_ids(whatsit_code,list) do
+ if 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
+ end
+ end
+ end
+ end
+ else
+ local current, first, last, index = list, nil, nil, nil
+ while current do
+ -- todo: disc and kern
+ local id = getid(current)
+ if id == glyph_code or id == disc_code then
+ local a = getattr(current,a_word)
+ if a then
+ if a == index then
+ -- same word
+ last = current
+ elseif index then
+ w = w + 1
+ words[w] = { index, first, last }
+ first = current
+ last = current
+ index = a
+ elseif first then
+ last = current
+ index = a
+ else
+ first = current
+ last = current
+ index = a
+ end
+ elseif index then
+ if first then
+ w = w + 1
+ words[w] = { index, first, last }
+ end
+ index = nil
+ first = nil
+ elseif trace_split then
+ if id == disc_code then
+ report_splitters("skipped: disc node")
+ else
+ report_splitters("skipped: %C",current.char)
+ end
+ end
+ elseif id == kern_code and (getsubtype(current) == fontkern_code or getattr(current,a_fontkern)) then
+ if first then
+ last = current
+ else
+ first = current
+ last = current
+ end
+ elseif index then
+ w = w + 1
+ words[w] = { index, first, last }
+ index = nil
+ first = nil
+ if id == disc_code then
+ if trace_split then
+ report_splitters("skipped: disc node")
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ if index then
+ w = w + 1
+ words[w] = { index, first, last }
+ end
+ if trace_split then
+ for i=1,#words do
+ local w = words[i]
+ local n, f, l = w[1], w[2], w[3]
+ local c = cache[n]
+ if c then
+ report_splitters("found %4i: word %a, cached %a",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true))
+ else
+ report_splitters("found %4i: word %a, not in cache",n,nodes_to_utf(f,true,true,l))
+ end
+ end
+ end
+ end
+ return words, list -- check for empty (elsewhere)
+end
+
+-- we could avoid a hpack but hpack is not that slow
+
+local function doit(word,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ local n = word[1]
+ local found = cache[n]
+ if found then
+ local h, t
+ if encapsulate then
+ h = getnext(word[2]) -- head of current word
+ t = getprev(word[3]) -- tail of current word
+ else
+ h = word[2]
+ t = word[3]
+ end
+ if splitwords then
+ -- there are no lines crossed in a word
+ else
+ local ok = false
+ local c = h
+ while c do
+ if c == t then
+ ok = true
+ break
+ else
+ c = getnext(c)
+ end
+ end
+ if not ok then
+ report_solutions("skipping hyphenated word (for now)")
+ -- todo: mark in words as skipped, saves a bit runtime
+ return false, changed
+ end
+ end
+ local original, attribute, direction = found.original, found.attribute, found.direction
+ local solution = solutions[attribute]
+ local features = solution and solution[set]
+ if features then
+ local featurenumber = features[best] -- not ok probably
+ if featurenumber then
+ noftries = noftries + 1
+ local first = copy_nodelist(original)
+ if not trace_colors then
+ for n in traverse_nodes(first) do -- maybe fast force so no attr needed
+ setattr(n,0,featurenumber) -- this forces dynamics
+ end
+ elseif set == "less" then
+ for n in traverse_nodes(first) do
+ setnodecolor(n,"font:isol") -- yellow
+ setattr(n,0,featurenumber)
+ end
+ else
+ for n in traverse_nodes(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
+ local processes = setdynamics[featurenumber]
+ for i=1,#processes do -- often more than 1
+ first = processes[i](first,font,featurenumber)
+ end
+ else
+ report_solutions("fatal error, no dynamics for font %a",font)
+ end
+ first = inject_kerns(first)
+first = tonut(first)
+ if getid(first) == whatsit_code then
+ local temp = first
+ first = getnext(first)
+ free_node(temp)
+ end
+ local last = find_node_tail(first)
+ -- replace [u]h->t by [u]first->last
+ local prev = getprev(h)
+ local next = getnext(t)
+ setlink(prev,first)
+ if next then
+ setlink(last,next)
+ end
+ -- check new pack
+ local temp, b = repack_hlist(list,width,'exactly',listdir)
+ if b > badness then
+ if trace_optimize then
+ report_optimizers("line %a, badness before %a, after %a, criterium %a, verdict %a",line,badness,b,criterium,"quit")
+ end
+ -- remove last insert
+ setlink(prev,h)
+ if next then
+ setlink(t,next)
+ else
+ setnext(t)
+ end
+ setnext(last)
+ free_nodelist(first)
+ else
+ if trace_optimize then
+ report_optimizers("line %a, badness before: %a, after %a, criterium %a, verdict %a",line,badness,b,criterium,"continue")
+ end
+ -- free old h->t
+ setnext(t)
+ free_nodelist(h) -- somhow fails
+ if not encapsulate then
+ word[2] = first
+ word[3] = last
+ end
+ changed, badness = changed + 1, b
+ end
+ if b <= criterium then
+ return true, changed
+ end
+ end
+ end
+ end
+ return false, changed
+end
+
+-- We repeat some code but adding yet another layer of indirectness is not
+-- making things better.
+
+variants[v_normal] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ for i=1,#words do
+ local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+variants[v_reverse] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ for i=#words,1,-1 do
+ local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+variants[v_random] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ while #words > 0 do
+ local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+local function show_quality(current,what,line)
+ local set = getfield(current,"glue_set")
+ local sign = getfield(current,"glue_sign")
+ local order = getfield(current,"glue_order")
+ local amount = set * ((sign == 2 and -1) or 1)
+ report_optimizers("line %a, category %a, amount %a, set %a, sign %a, how %a, order %a",line,what,amount,set,sign,how,order)
+end
+
+function splitters.optimize(head)
+ if not optimize then
+ report_optimizers("no optimizer set")
+ return
+ end
+ local nc = #cache
+ if nc == 0 then
+ return
+ end
+ starttiming(splitters)
+ local listdir = nil -- todo ! ! !
+ if randomseed then
+ math.setrandomseedi(randomseed)
+ randomseed = nil
+ end
+ local line = 0
+ local tex_hbadness = tex.hbadness
+ local tex_hfuzz = tex.hfuzz
+ tex.hbadness = 10000
+ tex.hfuzz = number.maxdimen
+ 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
+ line = line + 1
+ local sign = getfield(current,"glue_sign")
+ local dir = getfield(current,"dir")
+ local width = getfield(current,"width")
+ 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
+ if badness > 0 then
+ if sign == 0 then
+ if trace_optimize then
+ report_optimizers("line %a, badness %a, outcome %a, verdict %a",line,badness,"okay","okay")
+ end
+ else
+ local set, max
+ if sign == 1 then
+ if trace_optimize then
+ report_optimizers("line %a, badness %a, outcome %a, verdict %a",line,badness,"underfull","trying more")
+ end
+ set, max = "more", max_more
+ else
+ if trace_optimize then
+ report_optimizers("line %a, badness %a, outcome %a, verdict %a",line,badness,"overfull","trying less")
+ end
+ set, max = "less", max_less
+ end
+ -- we can keep the best variants
+ local lastbest, lastbadness = nil, badness
+ if preroll then
+ local bb, base
+ for i=1,max do
+ if base then
+ free_nodelist(base)
+ end
+ base = copy_nodelist(list)
+ local words = collect_words(base) -- beware: words is adapted
+ for j=i,max do
+ local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir)
+ base = temp
+ if trace_optimize then
+ report_optimizers("line %a, alternative %a.%a, changes %a, badness %a",line,i,j,changes,b)
+ end
+ bb = b
+ if b <= criterium then
+ break
+ end
+ -- if done then
+ -- break
+ -- end
+ end
+ if bb and bb > criterium then -- needs checking
+ if not lastbest then
+ lastbest, lastbadness = i, bb
+ elseif bb > lastbadness then
+ lastbest, lastbadness = i, bb
+ end
+ else
+ break
+ end
+ end
+ free_nodelist(base)
+ end
+ local words = collect_words(list)
+ for best=lastbest or 1,max do
+ local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir)
+ setlist(current,temp)
+ if trace_optimize then
+ report_optimizers("line %a, alternative %a, changes %a, badness %a",line,best,changes,b)
+ end
+ if done then
+ if b <= criterium then -- was == 0
+ protect_glyphs(list)
+ break
+ end
+ end
+ end
+ end
+ else
+ if trace_optimize then
+ report_optimizers("line %a, verdict %a",line,"not bad enough")
+ end
+ end
+ -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus
+ local list = hpack_nodes(getlist(current),width,'exactly',listdir)
+ setlist(current,list)
+ end
+ for i=1,nc do
+ local ci = cache[i]
+ free_nodelist(ci.original)
+ end
+ cache = { }
+ tex.hbadness = tex_hbadness
+ tex.hfuzz = tex_hfuzz
+ stoptiming(splitters)
+end
+
+statistics.register("optimizer statistics", function()
+ if nofwords > 0 then
+ local elapsed = statistics.elapsedtime(splitters)
+ local average = noftries/elapsed
+ return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second",
+ nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average)
+ end
+end)
+
+-- we could use a stack
+
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
+
+local function enable()
+ enableaction("processors", "builders.paragraphs.solutions.splitters.split")
+ enableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
+end
+
+local function disable()
+ disableaction("processors", "builders.paragraphs.solutions.splitters.split")
+ disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
+end
+
+function splitters.start(name,settings)
+ if pushsplitter(name,settings) == 1 then
+ enable()
+ end
+end
+
+function splitters.stop()
+ if popsplitter() == 0 then
+ disable()
+ end
+end
+
+function splitters.set(name,settings)
+ if #stack > 0 then
+ stack = { }
+ else
+ enable()
+ end
+ pushsplitter(name,settings) -- sets attribute etc
+end
+
+function splitters.reset()
+ if #stack > 0 then
+ stack = { }
+ popsplitter() -- resets attribute etc
+ disable()
+ end
+end
+
+-- interface
+
+implement {
+ name = "definefontsolution",
+ actions = splitters.define,
+ arguments = {
+ "string",
+ {
+ { "goodies" },
+ { "solution" },
+ { "less" },
+ { "more" },
+ }
+ }
+}
+
+implement {
+ name = "startfontsolution",
+ actions = splitters.start,
+ arguments = {
+ "string",
+ {
+ { "method" },
+ { "criterium" },
+ { "randomseed" },
+ }
+ }
+}
+
+implement {
+ name = "stopfontsolution",
+ actions = splitters.stop
+}
+
+implement {
+ name = "setfontsolution",
+ actions = splitters.set,
+ arguments = {
+ "string",
+ {
+ { "method" },
+ { "criterium" },
+ { "randomseed" },
+ }
+ }
+}
+
+implement {
+ name = "resetfontsolution",
+ actions = splitters.reset
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sol.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sol.mkvi
new file mode 100644
index 00000000000..d065b78ea55
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sol.mkvi
@@ -0,0 +1,129 @@
+%D \module
+%D [ file=font-sol,
+%D version=2009.05.19,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Solutions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Support / Splitters}
+
+% todo: pass color for tracing
+
+%D This module is specially made for the oriental \TEX\ project. The working is as
+%D follows (and tuned for fonts like Idris' Husayni. The following method came to
+%D my mind after a couple of Skype sessions with Idris while working on the rough
+%D edges of the Husayni font and playing with font dynamics.
+%D
+%D \startitemize[packed]
+%D
+%D \item We define a couple of features sets, some can have stylistics variants
+%D that result in the same words getting a different width. Normally this
+%D happens in a goodies file.
+%D
+%D \item We group such features in a solution set. A solutionset can be enabled
+%D by setting an attribute.
+%D
+%D \item For each paragraph we identify words that get this set applied. We replace
+%D these words by a user node that refers to the original.
+%D
+%D \item For each word we apply the features to a copy that we associate with this
+%D original word.
+%D
+%D \item At the end we have a paragraph (node list) with user nodes that point to a
+%D cache that has originals and processed variants.
+%D
+%D \item When the paragraph is broken into lines we optimize the spacing by
+%D substituting variants.
+%D
+%D \stopitemize
+%D
+%D This approach permits us to use a dedicated paragraph builder, one that treats
+%D the user nodes special and takes the alternatives into account.
+%D
+%D Currently we assume only one solution being active. Maybe some day I'll support
+%D a mixture. This is only one way of optimizing and after several experiments this
+%D one was chosen as testcase. It took quite some experiments (and time) to get thus
+%D far.
+%D
+%D The is experimental code for the Oriental \TEX\ project and aspects of it might
+%D change.
+%D
+%D \starttyping
+%D \setupfontsolutions[method={random,preroll},criterium=1,randomseed=101]
+%D
+%D \definefontsolution % actually only the last run needs to be done this way
+%D [FancyHusayni]
+%D [goodies=husayni,
+%D solution=experimental]
+%D
+%D \definedfont[husayni*husayni-default at 24pt]
+%D \setupinterlinespace[line=36pt]
+%D \righttoleft
+%D \enabletrackers[parbuilders.solutions.splitters.colors]
+%D \setfontsolution[FancyHusayni]
+%D alb alb alb \par
+%D \resetfontsolution
+%D \disabletrackers[parbuilders.solutions.splitters.colors]
+%D \stoptyping
+
+\registerctxluafile{font-sol}{1.001}
+
+\unprotect
+
+\definesystemattribute[splitter][public]
+
+\installcorenamespace{fontsolution}
+
+\installcommandhandler \??fontsolution {fontsolution} \??fontsolution
+
+\let\setupfontsolutions\setupfontsolution
+
+\appendtoks
+ \clf_definefontsolution
+ {\currentfontsolution}%
+ {% these are frozen
+ goodies {\fontsolutionparameter\s!goodies}%
+ solution {\fontsolutionparameter\c!solution}%
+ less {\fontsolutionparameter\c!less}%
+ more {\fontsolutionparameter\c!more}%
+ }%
+ \relax
+\to \everydefinefontsolution
+
+\unexpanded\def\setfontsolution[#solution]% just one
+ {\edef\currentfontsolution{#solution}%
+ \clf_setfontsolution
+ {\currentfontsolution}%
+ {%
+ method {\fontsolutionparameter\c!method}%
+ criterium {\fontsolutionparameter\c!criterium}%
+ % randomseed {\fontsolutionparameter\c!random}%
+ }%
+ \relax}
+
+\unexpanded\def\resetfontsolution % resets all
+ {\clf_resetfontsolution
+ \let\currentfontsolution\empty}
+
+\unexpanded\def\startfontsolution % [#1]
+ {\pushmacro\currentfontsolution
+ \setfontsolution}
+
+\unexpanded\def\stopfontsolution
+ {\ifhmode\par\fi
+ \clf_stopfontsolution
+ \popmacro\currentfontsolution}
+
+% We initialize this module at the \LUA\ end.
+%
+% \setupfontsolutions
+% [\c!method={\v!normal,preroll},
+% \c!criterium=0]
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi
new file mode 100644
index 00000000000..6b2c072e5ff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi
@@ -0,0 +1,412 @@
+%D \module
+%D [ file=font-sty,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Styles,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Styles}
+
+\unprotect
+
+%D \macros
+%D {definealternativestyle}
+%D
+%D In the main modules we are going to implement lots of
+%D parameterized commands and one of these parameters will
+%D concern the font to use. To suit consistent use of fonts we
+%D here implement a mechanism for defining the keywords that
+%D present a particular style or alternative.
+%D
+%D \starttyping
+%D \definealternativestyle [keywords] [\style] [\nostyle]
+%D \stoptyping
+%D
+%D The first command is used in the normal textflow, while the
+%D second command takes care of headings and alike. Consider
+%D the next two definitions:
+%D
+%D \starttyping
+%D \definealternativestyle [bold] [\bf] []
+%D \definealternativestyle [cap] [\cap] [\cap]
+%D \stoptyping
+%D
+%D A change \type{\bf} in a heading which is to be set in
+%D \type{\tfd} does not look that well, so therefore we leave
+%D the second argument of \type{\definealternativestyle} empty.
+%D When we capatalize characters using the pseudo small cap
+%D command \type{\cap}, we want this to take effect in both
+%D text and headings, which is accomplished by assigning both
+%D arguments.
+
+\installcorenamespace{alternativestyles}
+
+\setnewconstant \c_font_current_alternative_style_index \plusone
+
+\unexpanded\def\definealternativestyle
+ {\dotripleempty\font_basics_define_alternative_style}
+
+\def\font_basics_define_alternative_style[#commands][#variantone][#varianttwo]%
+ {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}}
+
+\let\definestyle\definealternativestyle % later redefined
+
+\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command%
+ {\ifcsname#command\endcsname
+ % no redefinition
+ \else
+ \setuvalue{#command}{\groupedcommand{#variantone}{}}%
+ \fi
+ \setvalue{\??alternativestyles#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}}%
+
+\def\font_helpers_apply_alternative_style
+ {\ifcase\c_font_current_alternative_style_index
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\firstoftwoarguments
+ \or
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\applyalternativestyle#name% public
+ {\begincsname\??alternativestyles#name\endcsname}
+
+%D Maybe too geneneric, but probably ok is the following. (Maybe one
+%D day we will use a dedicated grouped command for styles.)
+
+% \appendtoks
+% \let\groupedcommand\thirdofthreearguments
+% \to \everysimplifycommands
+
+%D This command also defines the keyword as command. This means
+%D that the example definition of \type{bold} we gave before,
+%D results in a command \type{\bold} which can be used as:
+%D
+%D \startbuffer
+%D He's a \bold{bold} man with a {\bold head}.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startexample
+%D \definealternativestyle[bold][\bf][]\getbuffer
+%D \stopexample
+%D
+%D Such definitions are of course unwanted for \type{\cap}
+%D because this would result in an endless recursive call.
+%D Therefore we check on the existance of both the command and
+%D the substitution. The latter is needed because for instance
+%D \type{\type} is an entirely diferent command. That command
+%D handles verbatim, while the style command would just switch
+%D to teletype font. This is just an example of a tricky
+%D naming coincidence.
+
+%D \macros
+%D {doconvertfont,noconvertfont,
+%D dontconvertfont,redoconvertfont}
+%D
+%D After having defined such keywords, we can call for them by
+%D using
+%D
+%D \starttyping
+%D \doconvertfont{keyword}{text}
+%D \stoptyping
+%D
+%D We deliberately pass an argument. This enables us to
+%D assign converters that handle one argument, like
+%D \type{\cap}.
+%D
+%D By default the first specification is used to set the style,
+%D exept when we say \type{\dontconvertfont}, after which the
+%D second specification is used. We can also directly call for
+%D \type{\noconvertfont}. In nested calls, we can restore the
+%D conversion by saying \type{\redoconvertfont}.
+
+%D These commands are not grouped! Grouping is most probably
+%D done by the calling macro's and would lead to unnecessary
+%D overhead.
+
+\let\m_current_convert_font \empty
+\let\m_current_convert_font_dt\empty
+
+\unexpanded\def\doconvertfont#specification% takes second argument / this command is obsolete
+ {\edef\m_current_convert_font{#specification}%
+ \ifx\m_current_convert_font\empty
+ %\expandafter\firstofoneargument
+ \else
+ \expandafter\font_helpers_do_convert_font
+ \fi}
+
+\def\font_helpers_do_convert_font
+ {\edef\m_current_convert_font_dt{\detokenize\expandafter{\m_current_convert_font}}%
+ \ifcsname\??alternativestyles\m_current_convert_font_dt\endcsname
+ \expandafter\lastnamedcs
+ \else\ifcsname\m_current_convert_font_dt\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\m_current_convert_font
+ \fi\fi}
+
+%D Low level switches (downward compatible, but we keep them as one can use
+%D them in styles):
+%D
+%D \starttyping
+%D \usemodule[abr-02]
+%D \setuphead[chapter][style=\bfb]
+%D \setupfooter[style=\dontconvertfont\bf]
+%D \chapter{This is \TEX}
+%D \stoptyping
+
+\unexpanded\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage
+\unexpanded\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage
+
+%D The new one:
+
+\setfalse\fontattributeisset
+
+\unexpanded\def\dousestyleparameter#value%
+ {\edef\currentstyleparameter{#value}%
+ \ifx\currentstyleparameter\empty\else
+ \expandafter\dousecurrentstyleparameter
+ \fi}
+
+\unexpanded\def\dousestylehashparameter#hash#parameter%
+ {\ifcsname#hash#parameter\endcsname
+ \expandafter\dousestyleparameter\lastnamedcs
+ \fi}
+
+\unexpanded\def\dousecurrentstyleparameter % empty check outside here
+ {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
+ \settrue\fontattributeisset % reset is done elsewhere
+ \ifcsname\??alternativestyles\detokenizedstyleparameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\detokenizedstyleparameter\endcsname
+ \lastnamedcs
+ \else
+ \currentstyleparameter
+ \fi\fi}
+
+\let\dosetfontattribute\dousestylehashparameter % for a while
+
+%D New commands (not yet interfaced):
+%D
+%D \startbuffer
+%D \definestyle[one][style=bold,color=darkblue]
+%D
+%D test \one{test} test
+%D test \style[one]{test} test
+%D test \style[color=red]{test} test
+%D test \style[Serif at 20pt]{test} test
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+% definitions .. no tagging here
+
+\installcorenamespace{style}
+\installcorenamespace{stylecheck}
+
+\installcommandhandler \??style {style} \??style
+
+\setupstyle
+ [%\c!style=,
+ %\c!color=,
+ \c!method=\v!command]
+
+\appendtoks
+ \letvalue{\??stylecheck\currentstyle}\relax
+ \edef\p_method{\styleparameter\c!method}%
+ \ifx\p_method\v!command
+ \setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}%
+ \setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}%
+ \setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here
+ \fi
+\to \everydefinestyle
+
+\unexpanded\def\font_styles_apply_start#name%
+ {\begingroup
+ \font_styles_use_defined{#name}}
+
+\unexpanded\def\font_styles_apply_stop
+ {\endgroup}
+
+\unexpanded\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup
+ {\bgroup
+ \def\g_style{\font_styles_use_defined{#name}}%
+ \afterassignment\g_style
+ \let\nexttoken}
+
+\unexpanded\def\font_styles_use_defined#name%
+ {\edef\currentstyle{#name}%
+ \usestylestyleandcolor\c!style\c!color}
+
+\unexpanded\def\font_styles_use_generic#specification%
+ {\let\currentstyle\s!unknown % reasonable generic tag
+ \letstyleparameter\c!style\empty
+ \letstyleparameter\c!color\empty
+ \setupcurrentstyle[#specification]%
+ \usestylestyleandcolor\c!style\c!color}
+
+% commands
+
+\installcorenamespace{styleargument}
+
+\unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand
+ {\csname\??styleargument
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \else\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi\fi
+ \endcsname{#name}}
+
+\setvalue{\??styleargument1}#name%
+ {\groupedcommand{\csname#name\endcsname}{}}
+
+\setvalue{\??styleargument2}#name%
+ {\groupedcommand{\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]}{}}
+
+% environments
+
+\installcorenamespace{styleenvironment}
+
+\unexpanded\def\startstyle[#name]%
+ {\begingroup
+ \csname\??styleenvironment
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \else\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi\fi
+ \endcsname{#name}}
+
+\unexpanded\def\stopstyle
+ {\endgroup
+ \autoinsertnextspace} % will be configurable, maybe also in \definestartstop
+
+\setvalue{\??styleenvironment1}#name%
+ {\csname#name\endcsname}
+
+\setvalue{\??styleenvironment2}#name%
+ {\font_styles_use_defined{#name}}
+
+\setvalue{\??styleenvironment3}#specification%
+ {\doifelseassignment{#specification}\font_styles_start_assignment\font_styles_start_direct{#specification}}
+
+\def\font_styles_start_assignment#specification{\font_styles_use_generic{#specification}}
+\def\font_styles_start_direct #specification{\definedfont[#specification]\relax}
+
+%D Still experimental (might even go away).
+
+% \definestylecollection[mine]
+
+% \definestyleinstance[mine][default][sorry]
+% \definestyleinstance[mine][tt][bs][ttbs:\rm\sl]
+% \definestyleinstance[mine][tt][bf][ttbf:\rm\sl]
+% \definestyleinstance[mine][bf][\sl]
+% \definestyleinstance[mine][sl][\tt]
+
+% {\bf test \mine test \sl test \mine test \bs oeps \mine oeps {\tt test \mine \bf test}}
+
+\installcorenamespace{stylecollection}
+
+\unexpanded\def\definestylecollection
+ {\dosingleargument\font_styles_define_style_collection}
+
+\def\font_styles_define_style_collection[#name]%
+ {\iffirstargument
+ \setuvalue{#name}{\styleinstance[#name]}%
+ \def\font_styles_define_style_collection_a#style%
+ {\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}%
+ \font_helpers_process_alternative_list\font_styles_define_style_collection_b
+ \font_styles_define_style_collection_b\s!default}%
+ \font_helpers_process_style_list\font_styles_define_style_collection_a
+ \font_styles_define_style_collection_a\s!default
+ \fi}
+
+\let\font_styles_define_style_collection_a\relax
+\let\font_styles_define_style_collection_b\relax
+
+\unexpanded\def\definestyleinstance
+ {\doquadrupleargument\font_styles_define_style_instance}
+
+\def\font_styles_define_style_instance[#instance][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
+ {\iffirstargument
+ \ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi
+ \fi
+ \iffourthargument
+ \setvalue{\??stylecollection#instance:#2:#3}{#4}%
+ \else\ifthirdargument
+ \setvalue{\??stylecollection#instance::#2}{#3}%
+ \else\ifsecondargument
+ \letvalueempty{\??stylecollection#instance::#2}%
+ \fi\fi\fi}
+
+% \unexpanded\def\styleinstance[#instance]% will be made faster
+% {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup
+% \executeifdefined{\??stylecollection#instance:\fontstyle:\fontalternative}%
+% {\executeifdefined{\??stylecollection#instance:\fontstyle:\s!default}%
+% {\executeifdefined{\??stylecollection#instance::\fontalternative}
+% {\getvalue {\??stylecollection#instance::\s!default}}}}}
+
+\unexpanded\def\styleinstance[#instance]% maybe \lastnamedcs here too
+ {\csname\??stylecollection#instance:%
+ \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname
+ \fontstyle:\fontalternative
+ \else\ifcsname\??stylecollection#instance:\fontstyle:\s!default\endcsname
+ \fontstyle:\s!default
+ \else\ifcsname\??stylecollection#instance::\fontalternative\endcsname
+ :\fontalternative
+ \else
+ :\s!default
+ \fi\fi\fi
+ \endcsname}
+
+%D Variant selectors
+%D
+%D \starttyping
+%D \mathematics {\vsone{\utfchar{0x2229}}}
+%D \mathematics {\utfchar{0x2229}\vsone{}}
+%D \stoptyping
+
+\unexpanded\edef\vsone#character{#character\normalUchar"FE00 } % used
+\unexpanded\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing
+
+%D For historic reasons we keep the following around but they are no longer
+%D that relevant for \MKIV.
+
+\unexpanded\def\doattributes#1#2#3#4%
+ {\begingroup % geen \bgroup, anders in mathmode lege \hbox
+ \dousestylehashparameter{#1}{#2}%
+ \dousecolorhashparameter{#1}{#3}%
+ #4%
+ \endgroup}
+
+\unexpanded\def\dostartattributes#1#2#3%
+ {\begingroup % geen \bgroup, anders in mathmode lege \hbox
+ \dousestylehashparameter{#1}{#2}%
+ \dousecolorhashparameter{#1}{#3}}
+
+\let\dostopattributes\endgroup
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi
new file mode 100644
index 00000000000..c1ffd6361ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Symbolic Access,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Symbolic Access}
+
+\unprotect
+
+%D \macros
+%D {getglyph, symbolicfont}
+%D
+%D Individual glyphs can be accessed by using
+%D
+%D \starttyping
+%D \getglyph{fontname}{character}
+%D \stoptyping
+%D
+%D This macro is used in for instance the symbol modules and
+%D as one can see, it does obey the small and even smaller
+%D sizes. The \type {\symbolicfont} macro can be used to
+%D switch to a font named \type {fontname} (see \type
+%D {cont-log} and \type {symb-eur} for examples of symbolic
+%D definitions.
+
+\def\v_font_string_a
+ {\ifx\fontstyle\s!rm \s!Serif \else
+ \ifx\fontstyle\s!ss \s!Sans \else
+ \ifx\fontstyle\s!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\def\v_font_string_b
+ {\ifx\fontstyle\s!rm \s!Regular \else
+ \ifx\fontstyle\s!ss \s!Support \else
+ \ifx\fontstyle\s!tt \s!Type \else
+ \s!Serif \fi\fi\fi}
+
+\def\v_font_string_c
+ {\ifx\fontalternative\s!bf \s!Bold \else
+ \ifx\fontalternative\s!sl \s!Slanted \else
+ \ifx\fontalternative\s!it \s!Italic \else
+ \ifx\fontalternative\s!bs \s!BoldSlanted \else
+ \ifx\fontalternative\s!bi \s!BoldItalic \fi\fi\fi\fi\fi}
+
+\let\v_font_string_d\s!Serif % default fontstyle (will be redefined in type-ini)
+
+\definefontsynonym
+ [CurrentFont]
+ [\noexpand\v_font_string_a\noexpand\v_font_string_c]
+
+% potential generalization:
+%
+% \letvalue{\??fontfile:t:\s!rm}\s!Serif
+% \letvalue{\??fontfile:t:\s!ss}\s!Sans
+% \letvalue{\??fontfile:t:\s!tt}\s!Mono
+%
+% \letvalue{\??fontfile:a:\s!rm}\s!Regular
+% \letvalue{\??fontfile:a:\s!ss}\s!Support
+% \letvalue{\??fontfile:a:\s!tt}\s!Type
+%
+% \letvalue{\??fontfile:s:\s!bf}\s!Bold
+% \letvalue{\??fontfile:s:\s!sl}\s!Slanted
+% \letvalue{\??fontfile:s:\s!it}\s!Italic
+% \letvalue{\??fontfile:s:\s!bs}\s!BoldSlanted
+% \letvalue{\??fontfile:s:\s!bi}\s!BoldItalic
+%
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_b{\executeifdefined{\??fontfile:a:\fontstyle}\s!Serif}
+% \def\v_font_string_c{\executeifdefined{\??fontfile:s:\fontstyle}\empty}
+% \def\v_font_string_d{\executeifdefined{\??fontfile:t:\csname\??typescriptdefaultstyles\fontclass\endcsname}\s!Serif}
+
+%D \macros
+%D {fontstylesuffix}
+%D
+%D The next macro is used to map non latin fontnames on fonts. See \type
+%D {font-uni} for an example of its use.
+
+\def\fontstylesuffix% why the \s!Regular ? see \getglyph
+ {\ifx\fontalternative\s!tf \s!Regular \else
+ \ifx\fontalternative\s!bf \s!Bold \else
+ \ifx\fontalternative\s!sl \s!Slanted \else
+ \ifx\fontalternative\s!it \s!Italic \else
+ \ifx\fontalternative\s!bs \s!BoldSlanted \else
+ \ifx\fontalternative\s!bi \s!BoldItalic \else
+ \ifx\fontalternative\s!sc \s!Caps \else
+ \s!Regular \fi\fi\fi\fi\fi\fi\fi}%
+
+\def\glyphfontfile#base% appends
+ {#base%
+ \ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname
+ \v_font_string_a\v_font_string_c
+ \else\ifcsname\??fontfile#base\v_font_string_b\v_font_string_c\endcsname
+ \v_font_string_b\v_font_string_c
+ \else\ifcsname\??fontfile#base\v_font_string_a\endcsname
+ \v_font_string_a
+ \else\ifcsname\??fontfile#base\v_font_string_b\endcsname
+ \v_font_string_b
+ \else\ifcsname\??fontfile#base\v_font_string_c\endcsname
+ \v_font_string_c
+ \fi\fi\fi\fi\fi}
+
+%D The next macro can be used to make decisions based on the shape:
+
+\def\doifelseitalic#yes#nop%
+ {\ifx\fontalternative\s!sl#yes\else
+ \ifx\fontalternative\s!it#yes\else
+ \ifx\fontalternative\s!bs#yes\else
+ \ifx\fontalternative\s!bi#yes\else#nop\fi\fi\fi\fi}
+
+\let\doifitalicelse\doifelseitalic
+
+%D For an example of usage of the following command,
+%D see \type {cont-log.tex}.
+%D
+%D \starttyping
+%D \def\symbolicfont#specification{\definedfont[\glyphfontfile{#specification} sa *]}
+%D \stoptyping
+%D
+%D Since we know what scaling it to be applied, we can
+%D implement a much faster alternative:
+
+\installcorenamespace{symbolfont}
+
+\let\thedefinedfont\relax
+
+\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setdirectsymbolicfont#fontname%
+ {\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \lastnamedcs
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\font_basics_define_symbolic_font
+ {\definefont[currentsymbolfont][\askedsymbolfont]%
+ \currentsymbolfont
+ \global\expandafter\let\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
+
+\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\unexpanded\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+\unexpanded\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+
+% this one is wrong:
+
+\unexpanded\def\getscaledglyph#scale#name#content%
+ {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}}
+
+\let\getglyph \getglyphstyled % old
+\let\getrawglyph \getglyphdirect % old
+\let\symbolicsizedfont\setscaledstyledsymbolicfont % old
+\let\symbolicfont \setstyledsymbolicfont % old
+
+\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
+\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
+
+%D The last implementation of \type {\getglyph} permits
+%D definitions like:
+%D
+%D \starttyping
+%D \definefontsynonym [EuroSans] [eurose]
+%D \definefontsynonym [EuroSansBold] [euroseb]
+%D \definefontsynonym [EuroSansItalic] [eurosei]
+%D \definefontsynonym [EuroSansSlanted] [eurosei]
+%D \definefontsynonym [EuroSansBoldItalic] [eurosebi]
+%D \definefontsynonym [EuroSansBoldSlanted] [eurosebi]
+%D
+%D \definesymbol [euro] [\getglyph{Euro}{\char160}]
+%D
+%D \def\euro{\symbol[euro]}
+%D \stoptyping
+%D
+%D These definitions guarantee that the next calls work okay:
+%D
+%D \starttyping
+%D \ss \tf\euro \bf\euro \sla\euro \itd\euro \bs\euro \bic\euro
+%D \stoptyping
+%D
+%D The shape as well as the size is adapted to the current
+%D environment.
+
+%D \macros
+%D {setfont}
+%D
+%D Every now and then we want to define a font directly, for
+%D instance when we typeset title pages. The next macro saves
+%D some typing:
+
+\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk
+ {\afterassignment\font_basics_set_font\font\nextfont=}
+
+\def\font_basics_set_font
+ {\nextfont\setupinterlinespace}% hm, we need to use \setuplocalinterlinespace
+
+%D One can call this macro as:
+%D
+%D \starttyping
+%D \setfont cmr10 at 60pt
+%D \stoptyping
+%D
+%D After which the font is active and the baselines and
+%D struts are set.
+
+%D \macros{doiffontcharelse}
+
+\unexpanded\def\doifelsefontchar#specification#unicode% this could be a direct lua call
+ {\begingroup
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \iffontchar\font#unicode\relax
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiffontcharelse\doifelsefontchar
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua
new file mode 100644
index 00000000000..f27995212bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua
@@ -0,0 +1,2090 @@
+if not modules then modules = { } end modules ['font-syn'] = {
+ 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: subs in lookups requests
+-- todo: see if the (experimental) lua reader (on my machine) be used (it's a bit slower so maybe wait till lua 5.3)
+
+-- identifying ttf/otf/ttc/afm : 2200 fonts:
+--
+-- old ff loader: 140 sec
+-- new lua loader: 5 sec
+
+local next, tonumber, type, tostring = next, tonumber, type, tostring
+local sub, gsub, match, find, lower, upper = string.sub, string.gsub, string.match, string.find, string.lower, string.upper
+local concat, sort = table.concat, table.sort
+local serialize, sortedhash = table.serialize, table.sortedhash
+local lpegmatch = lpeg.match
+local unpack = unpack or table.unpack
+local formatters, topattern = string.formatters, string.topattern
+local round = math.round
+local P, R, S, C, Cc, Ct, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cs
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+local allocate = utilities.storage.allocate
+local sparse = utilities.storage.sparse
+local setmetatableindex = table.setmetatableindex
+
+local removesuffix = file.removesuffix
+local splitbase = file.splitbase
+local splitname = file.splitname
+local basename = file.basename
+local nameonly = file.nameonly
+local pathpart = file.pathpart
+local filejoin = file.join
+local is_qualified_path = file.is_qualified_path
+local exists = io.exists
+
+local findfile = resolvers.findfile
+local cleanpath = resolvers.cleanpath
+local resolveprefix = resolvers.resolve
+
+----- fontloader = fontloader -- still needed for pfb (now)
+----- get_font_info = fontloader.info
+
+local settings_to_hash = utilities.parsers.settings_to_hash_tolerant
+
+local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end)
+local trace_warnings = false trackers.register("fonts.warnings", function(v) trace_warnings = v end)
+local trace_specifications = false trackers.register("fonts.specifications", function(v) trace_specifications = v end)
+local trace_rejections = false trackers.register("fonts.rejections", function(v) trace_rejections = v end)
+
+local report_names = logs.reporter("fonts","names")
+
+--[[ldx--
+<p>This module implements a name to filename resolver. Names are resolved
+using a table that has keys filtered from the font related files.</p>
+--ldx]]--
+
+fonts = fonts or { } -- also used elsewhere
+
+local names = fonts.names or allocate { }
+fonts.names = names
+
+local filters = names.filters or { }
+names.filters = filters
+
+local treatments = fonts.treatments or { }
+fonts.treatments = treatments
+
+names.data = names.data or allocate { }
+
+names.version = 1.131
+names.basename = "names"
+names.saved = false
+names.loaded = false
+names.be_clever = true
+names.enabled = true
+names.cache = containers.define("fonts","data",names.version,true)
+
+local usesystemfonts = true
+local autoreload = true
+
+directives.register("fonts.autoreload", function(v) autoreload = toboolean(v) end)
+directives.register("fonts.usesystemfonts", function(v) usesystemfonts = toboolean(v) end)
+
+--[[ldx--
+<p>A few helpers.</p>
+--ldx]]--
+
+-- -- what to do with these -- --
+--
+-- thin -> thin
+--
+-- regu -> regular -> normal
+-- norm -> normal -> normal
+-- stan -> standard -> normal
+-- medi -> medium
+-- ultr -> ultra
+-- ligh -> light
+-- heav -> heavy
+-- blac -> black
+-- thin
+-- book
+-- verylight
+--
+-- buch -> book
+-- buchschrift -> book
+-- halb -> demi
+-- halbfett -> demi
+-- mitt -> medium
+-- mittel -> medium
+-- fett -> bold
+-- mage -> light
+-- mager -> light
+-- nord -> normal
+-- gras -> normal
+
+local weights = Cs ( -- not extra
+ P("demibold")
+ + P("semibold")
+ + P("mediumbold")
+ + P("ultrabold")
+ + P("extrabold")
+ + P("ultralight")
+ + P("extralight")
+ + P("bold")
+ + P("demi")
+ + P("semi")
+ + P("light")
+ + P("medium")
+ + P("heavy")
+ + P("ultra")
+ + P("black")
+--+ P("bol") / "bold" -- blocks
+ + P("bol")
+ + P("regular") / "normal"
+)
+
+-- numeric_weights = {
+-- 200 = "extralight",
+-- 300 = "light",
+-- 400 = "book",
+-- 500 = "medium",
+-- 600 = "demi",
+-- 700 = "bold",
+-- 800 = "heavy",
+-- 900 = "black",
+-- }
+
+local normalized_weights = sparse {
+ regular = "normal",
+}
+
+local styles = Cs (
+ P("reverseoblique") / "reverseitalic"
+ + P("regular") / "normal"
+ + P("italic")
+ + P("oblique") / "italic"
+ + P("slanted")
+ + P("roman") / "normal"
+ + P("ital") / "italic" -- might be tricky
+ + P("ita") / "italic" -- might be tricky
+--+ P("obli") / "oblique"
+)
+
+local normalized_styles = sparse {
+ reverseoblique = "reverseitalic",
+ regular = "normal",
+ oblique = "italic",
+}
+
+local widths = Cs(
+ P("condensed")
+ + P("thin")
+ + P("expanded")
+ + P("cond") / "condensed"
+--+ P("expa") / "expanded"
+ + P("normal")
+ + P("book") / "normal"
+)
+
+local normalized_widths = sparse()
+
+local variants = Cs( -- fax casual
+ P("smallcaps")
+ + P("oldstyle")
+ + P("caps") / "smallcaps"
+)
+
+local normalized_variants = sparse()
+
+names.knownweights = {
+ "black",
+ "bold",
+ "demi",
+ "demibold",
+ "extrabold",
+ "heavy",
+ "light",
+ "medium",
+ "mediumbold",
+ "normal",
+ "regular",
+ "semi",
+ "semibold",
+ "ultra",
+ "ultrabold",
+ "ultralight",
+}
+
+names.knownstyles = {
+ "italic",
+ "normal",
+ "oblique",
+ "regular",
+ "reverseitalic",
+ "reverseoblique",
+ "roman",
+ "slanted",
+}
+
+names.knownwidths = {
+ "book",
+ "condensed",
+ "expanded",
+ "normal",
+ "thin",
+}
+
+names.knownvariants = {
+ "normal",
+ "oldstyle",
+ "smallcaps",
+}
+
+local remappedweights = {
+ [""] = "normal",
+ ["bol"] = "bold",
+}
+
+local remappedstyles = {
+ [""] = "normal",
+}
+
+local remappedwidths = {
+ [""] = "normal",
+}
+
+local remappedvariants = {
+ [""] = "normal",
+}
+
+names.remappedweights = remappedweights setmetatableindex(remappedweights ,"self")
+names.remappedstyles = remappedstyles setmetatableindex(remappedstyles ,"self")
+names.remappedwidths = remappedwidths setmetatableindex(remappedwidths ,"self")
+names.remappedvariants = remappedvariants setmetatableindex(remappedvariants,"self")
+
+local any = P(1)
+
+local analyzed_table
+
+local analyzer = Cs (
+ (
+ weights / function(s) analyzed_table[1] = s return "" end
+ + styles / function(s) analyzed_table[2] = s return "" end
+ + widths / function(s) analyzed_table[3] = s return "" end
+ + variants / function(s) analyzed_table[4] = s return "" end
+ + any
+ )^0
+)
+
+local splitter = lpeg.splitat("-")
+
+function names.splitspec(askedname)
+ local name, weight, style, width, variant = lpegmatch(splitter,askedname)
+ weight = weight and lpegmatch(weights, weight) or weight
+ style = style and lpegmatch(styles, style) or style
+ width = width and lpegmatch(widths, width) or width
+ variant = variant and lpegmatch(variants,variant) or variant
+ if trace_names then
+ report_names("requested name %a split in name %a, weight %a, style %a, width %a and variant %a",
+ askedname,name,weight,style,width,variant)
+ end
+ if not weight or not weight or not width or not variant then
+ weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal"
+ if trace_names then
+ report_names("request %a normalized to '%s-%s-%s-%s-%s'",
+ askedname,name,weight,style,width,variant)
+ end
+ end
+ return name or askedname, weight, style, width, variant
+end
+
+local function analyzespec(somename)
+ if somename then
+ analyzed_table = { }
+ local name = lpegmatch(analyzer,somename)
+ return name, analyzed_table[1], analyzed_table[2], analyzed_table[3], analyzed_table[4]
+ end
+end
+
+--[[ldx--
+<p>It would make sense to implement the filters in the related modules,
+but to keep the overview, we define them here.</p>
+--ldx]]--
+
+filters.otf = fonts.handlers.otf.readers.getinfo
+filters.ttf = filters.otf
+filters.ttc = filters.otf
+-------.ttx = filters.otf
+
+local function normalize(t) -- only for afm parsing
+ local boundingbox = t.fontbbox
+ if boundingbox then
+ for i=1,#boundingbox do
+ boundingbox[i] = tonumber(boundingbox[i])
+ end
+ else
+ boundingbox = { 0, 0, 0, 0 }
+ end
+ return {
+ copyright = t.copyright,
+ fontname = t.fontname,
+ fullname = t.fullname,
+ familyname = t.familyname,
+ weight = t.weight,
+ widtht = t.width,
+ italicangle = tonumber(t.italicangle) or 0,
+ monospaced = toboolean(t.isfixedpitch) or false,
+ boundingbox = boundingbox,
+ version = t.version, -- not used
+ capheight = tonumber(t.capheight),
+ xheight = tonumber(t.xheight),
+ ascender = tonumber(t.ascender),
+ descender = tonumber(t.descender),
+ }
+end
+
+local p_spaces = lpegpatterns.whitespace
+local p_number = (R("09")+S(".-+"))^1 / tonumber
+local p_boolean = P("false") * Cc(false)
+ + P("false") * Cc(false)
+local p_string = P("(") * C((lpegpatterns.nestedparents + 1 - P(")"))^1) * P(")")
+local p_array = P("[") * Ct((p_number + p_boolean + p_string + p_spaces^1)^1) * P("]")
+ + P("{") * Ct((p_number + p_boolean + p_string + p_spaces^1)^1) * P("}")
+
+local p_key = P("/") * C(R("AZ","az")^1)
+local p_value = p_string
+ + p_number
+ + p_boolean
+ + p_array
+
+local p_entry = p_key * p_spaces^0 * p_value
+
+function filters.afm(name)
+ -- we could parse the afm file as well, and then report an error but
+ -- it's not worth the trouble
+ local pfbname = findfile(removesuffix(name)..".pfb","pfb") or ""
+ if pfbname == "" then
+ pfbname = findfile(nameonly(name)..".pfb","pfb") or ""
+ end
+ if pfbname ~= "" then
+ local f = io.open(name)
+ if f then
+ local hash = { }
+ local okay = false
+ for line in f:lines() do -- slow but only a few lines at the beginning
+ if find(line,"StartCharMetrics",1,true) then
+ break
+ else
+ local key, value = match(line,"^(.+)%s+(.+)%s*$")
+ if key and #key > 0 then
+ hash[lower(key)] = value
+ end
+ end
+ end
+ f:close()
+ return normalize(hash)
+ end
+ end
+ return nil, "no matching pfb file"
+end
+
+function filters.pfb(name)
+ local f = io.open(name)
+ if f then
+ local hash = { }
+ local okay = false
+ for line in f:lines() do -- slow but only a few lines at the beginning
+ if find(line,"dict begin") then
+ okay = true
+ elseif not okay then
+ -- go on
+ elseif find(line,"currentdict end") then
+ break
+ else
+ local key, value = lpegmatch(p_entry,line)
+ if key and value then
+ hash[lower(key)] = value
+ end
+ end
+ end
+ f:close()
+ return normalize(hash)
+ end
+end
+
+--[[ldx--
+<p>The scanner loops over the filters using the information stored in
+the file databases. Watch how we check not only for the names, but also
+for combination with the weight of a font.</p>
+--ldx]]--
+
+filters.list = {
+ "otf", "ttf", "ttc", "afm", -- no longer dfont support (for now)
+}
+
+-- to be considered: loop over paths per list entry (so first all otf ttf etc)
+
+names.fontconfigfile = "fonts.conf" -- a bit weird format, bonus feature
+names.osfontdirvariable = "OSFONTDIR" -- the official way, in minimals etc
+
+filters.paths = { }
+filters.names = { }
+
+function names.getpaths(trace)
+ local hash, result, r = { }, { }, 0
+ local function collect(t,where)
+ for i=1,#t do
+ local v = cleanpath(t[i])
+ v = gsub(v,"/+$","") -- not needed any more
+ local key = lower(v)
+ report_names("%a specifies path %a",where,v)
+ if not hash[key] then
+ r = r + 1
+ result[r] = v
+ hash[key] = true
+ end
+ end
+ end
+ local path = names.osfontdirvariable or ""
+ if path ~= "" then
+ collect(resolvers.expandedpathlist(path),path)
+ end
+ if xml then
+ local confname = resolvers.expansion("FONTCONFIG_FILE") or ""
+ if confname == "" then
+ confname = names.fontconfigfile or ""
+ end
+ if confname ~= "" then
+ -- first look in the tex tree
+ local name = findfile(confname,"fontconfig files") or ""
+ if name == "" then
+ -- after all, fontconfig is a unix thing
+ name = filejoin("/etc",confname)
+ if not lfs.isfile(name) then
+ name = "" -- force quit
+ end
+ end
+ if name ~= "" and lfs.isfile(name) then
+ if trace_names then
+ report_names("%s fontconfig file %a","loading",name)
+ end
+ local xmldata = xml.load(name)
+ -- begin of untested mess
+ xml.include(xmldata,"include","",true,function(incname)
+ if not is_qualified_path(incname) then
+ local path = pathpart(name) -- main name
+ if path ~= "" then
+ incname = filejoin(path,incname)
+ end
+ end
+ if lfs.isfile(incname) then
+ if trace_names then
+ report_names("%s fontconfig file %a","merging included",incname)
+ end
+ return io.loaddata(incname)
+ elseif trace_names then
+ report_names("%s fontconfig file: %a","ignoring included",incname)
+ end
+ end)
+ -- end of untested mess
+ local fontdirs = xml.collect_texts(xmldata,"dir",true)
+ if trace_names then
+ report_names("%s dirs found in fontconfig",#fontdirs)
+ end
+ collect(fontdirs,"fontconfig file")
+ end
+ end
+ end
+ sort(result)
+ function names.getpaths()
+ return result
+ end
+ return result
+end
+
+local function cleanname(name)
+ return (gsub(lower(name),"[^%a%d]",""))
+end
+
+local function cleanfilename(fullname,defaultsuffix)
+ local path, name, suffix = splitname(fullname)
+ name = gsub(lower(name),"[^%a%d]","")
+ if suffix and suffix ~= "" then
+ return name .. ".".. suffix
+ elseif defaultsuffix and defaultsuffix ~= "" then
+ return name .. ".".. defaultsuffix
+ else
+ return name
+ end
+end
+
+local sorter = function(a,b)
+ return a > b -- to be checked
+end
+
+names.cleanname = cleanname
+names.cleanfilename = cleanfilename
+
+-- local function check_names(result)
+-- local names = result.names
+-- if names then
+-- for i=1,#names do
+-- local name = names[i]
+-- if name.lang == "English (US)" then
+-- return name.names
+-- end
+-- end
+-- end
+-- return result
+-- end
+
+local function walk_tree(pathlist,suffix,identify)
+ if pathlist then
+ for i=1,#pathlist do
+ local path = pathlist[i]
+ path = cleanpath(path .. "/")
+ path = gsub(path,"/+","/")
+ local pattern = path .. "**." .. suffix -- ** forces recurse
+ report_names("globbing path %a",pattern)
+ local t = dir.glob(pattern)
+ sort(t,sorter)
+ for j=1,#t do
+ local completename = t[j]
+ identify(completename,basename(completename),suffix,completename)
+ end
+ end
+ end
+end
+
+local function check_name(data,result,filename,modification,suffix,subfont)
+ -- shortcuts
+ local specifications = data.specifications
+ -- fetch
+ local fullname = result.fullname
+ local fontname = result.fontname
+ local family = result.family
+ local subfamily = result.subfamily
+ local familyname = result.familyname
+ local subfamilyname = result.subfamilyname
+ -- local compatiblename = result.compatiblename
+ local weight = result.weight
+ local italicangle = tonumber(result.italicangle)
+ local subfont = subfont
+ local rawname = fullname or fontname or familyname
+ local filebase = removesuffix(basename(filename))
+ local cleanfilename = cleanname(filebase) -- for WS
+ -- normalize
+ fullname = fullname and cleanname(fullname)
+ fontname = fontname and cleanname(fontname)
+ family = family and cleanname(family)
+ subfamily = subfamily and cleanname(subfamily)
+ familyname = familyname and cleanname(familyname)
+ subfamilyname = subfamilyname and cleanname(subfamilyname)
+ -- compatiblename = compatiblename and cleanname(compatiblename)
+ weight = weight and cleanname(weight)
+ italicangle = italicangle == 0 and nil
+ -- analyze
+ local a_name, a_weight, a_style, a_width, a_variant = analyzespec(fullname or fontname or familyname)
+ -- check
+ local width = a_width
+ local variant = a_variant
+ local style = subfamilyname or subfamily -- can re really trust subfamilyname?
+ if style then
+ style = gsub(style,"[^%a]","")
+ elseif italicangle then
+ style = "italic"
+ end
+ if not variant or variant == "" then
+ variant = "normal"
+ end
+ if not weight or weight == "" then
+ weight = a_weight
+ end
+ if not style or style == "" then
+ style = a_style
+ end
+ if not familyname then
+ familyname = a_name
+ end
+ fontname = fontname or fullname or familyname or filebase -- maybe cleanfilename
+ fullname = fullname or fontname
+ familyname = familyname or fontname
+ -- we do these sparse -- todo: check table type or change names in ff loader
+ local units = result.units or 1000 -- can be zero too
+ local designsize = result.designsize or 0
+ local minsize = result.minsize or 0
+ local maxsize = result.maxsize or 0
+ local angle = result.italicangle or 0
+ local pfmwidth = result.pfmwidth or 0
+ local pfmweight = result.pfmweight or 0
+ --
+ specifications[#specifications + 1] = {
+ filename = filename, -- unresolved
+ cleanfilename = cleanfilename,
+ -- subfontindex = subfont,
+ format = lower(suffix),
+ subfont = subfont,
+ rawname = rawname,
+ fullname = fullname,
+ fontname = fontname,
+ family = family,
+ subfamily = subfamily,
+ familyname = familyname,
+ subfamilyname = subfamilyname,
+ -- compatiblename = compatiblename, -- nor used / needed
+ weight = weight,
+ style = style,
+ width = width,
+ variant = variant,
+ units = units ~= 1000 and units or nil,
+ pfmwidth = pfmwidth ~= 0 and pfmwidth or nil,
+ pfmweight = pfmweight ~= 0 and pfmweight or nil,
+ angle = angle ~= 0 and angle or nil,
+ minsize = minsize ~= 0 and minsize or nil,
+ maxsize = maxsize ~= 0 and maxsize or nil,
+ designsize = designsize ~= 0 and designsize or nil,
+ modification = modification ~= 0 and modification or nil,
+ }
+end
+
+local function cleanupkeywords()
+ local data = names.data
+ local specifications = names.data.specifications
+ if specifications then
+ local weights = { }
+ local styles = { }
+ local widths = { }
+ local variants = { }
+ for i=1,#specifications do
+ local s = specifications[i]
+ -- fix (sofar styles are taken from the name, and widths from the specification)
+ local _, b_weight, b_style, b_width, b_variant = analyzespec(s.weight)
+ local _, c_weight, c_style, c_width, c_variant = analyzespec(s.style)
+ local _, d_weight, d_style, d_width, d_variant = analyzespec(s.width)
+ local _, e_weight, e_style, e_width, e_variant = analyzespec(s.variant)
+ local _, f_weight, f_style, f_width, f_variant = analyzespec(s.fullname or "")
+ local weight = b_weight or c_weight or d_weight or e_weight or f_weight or "normal"
+ local style = b_style or c_style or d_style or e_style or f_style or "normal"
+ local width = b_width or c_width or d_width or e_width or f_width or "normal"
+ local variant = b_variant or c_variant or d_variant or e_variant or f_variant or "normal"
+ weight = remappedweights [weight or ""]
+ style = remappedstyles [style or ""]
+ width = remappedwidths [width or ""]
+ variant = remappedvariants[variant or ""]
+ weights [weight ] = (weights [weight ] or 0) + 1
+ styles [style ] = (styles [style ] or 0) + 1
+ widths [width ] = (widths [width ] or 0) + 1
+ variants[variant] = (variants[variant] or 0) + 1
+ if weight ~= s.weight then
+ s.fontweight = s.weight
+ end
+ s.weight, s.style, s.width, s.variant = weight, style, width, variant
+ end
+ local statistics = data.statistics
+ statistics.used_weights = weights
+ statistics.used_styles = styles
+ statistics.used_widths = widths
+ statistics.used_variants = variants
+ end
+end
+
+local function collectstatistics(runtime)
+ local data = names.data
+ local specifications = data.specifications
+ local statistics = data.statistics
+ if specifications then
+ local f_w = formatters["%i"]
+ local f_a = formatters["%0.2f"]
+ -- normal stuff
+ local weights = { }
+ local styles = { }
+ local widths = { }
+ local variants = { }
+ -- weird stuff
+ local angles = { }
+ -- extra stuff
+ local pfmweights = { } setmetatableindex(pfmweights,"table")
+ local pfmwidths = { } setmetatableindex(pfmwidths, "table")
+ -- main loop
+ for i=1,#specifications do
+ local s = specifications[i]
+ -- normal stuff
+ local weight = s.weight
+ local style = s.style
+ local width = s.width
+ local variant = s.variant
+ if weight then weights [weight ] = (weights [weight ] or 0) + 1 end
+ if style then styles [style ] = (styles [style ] or 0) + 1 end
+ if width then widths [width ] = (widths [width ] or 0) + 1 end
+ if variant then variants[variant] = (variants[variant] or 0) + 1 end
+ -- weird stuff
+ local angle = f_a(tonumber(s.angle) or 0)
+ angles[angle] = (angles[angles] or 0) + 1
+ -- extra stuff
+ local pfmweight = f_w(s.pfmweight or 0)
+ local pfmwidth = f_w(s.pfmwidth or 0)
+ local tweights = pfmweights[pfmweight]
+ local twidths = pfmwidths [pfmwidth]
+ tweights[pfmweight] = (tweights[pfmweight] or 0) + 1
+ twidths[pfmwidth] = (twidths [pfmwidth] or 0) + 1
+ end
+ --
+ statistics.weights = weights
+ statistics.styles = styles
+ statistics.widths = widths
+ statistics.variants = variants
+ statistics.angles = angles
+ statistics.pfmweights = pfmweights
+ statistics.pfmwidths = pfmwidths
+ statistics.fonts = #specifications
+ --
+ setmetatableindex(pfmweights,nil)
+ setmetatableindex(pfmwidths, nil)
+ --
+ report_names("")
+ report_names("statistics: ")
+ report_names("")
+ report_names("weights")
+ report_names("")
+ report_names(formatters[" %T"](weights))
+ report_names("")
+ report_names("styles")
+ report_names("")
+ report_names(formatters[" %T"](styles))
+ report_names("")
+ report_names("widths")
+ report_names("")
+ report_names(formatters[" %T"](widths))
+ report_names("")
+ report_names("variants")
+ report_names("")
+ report_names(formatters[" %T"](variants))
+ report_names("")
+ report_names("angles")
+ report_names("")
+ report_names(formatters[" %T"](angles))
+ report_names("")
+ report_names("pfmweights")
+ report_names("")
+ for k, v in sortedhash(pfmweights) do
+ report_names(formatters[" %-10s: %T"](k,v))
+ end
+ report_names("")
+ report_names("pfmwidths")
+ report_names("")
+ for k, v in sortedhash(pfmwidths) do
+ report_names(formatters[" %-10s: %T"](k,v))
+ end
+ report_names("")
+ report_names("registered fonts : %i", statistics.fonts)
+ report_names("read files : %i", statistics.readfiles)
+ report_names("skipped files : %i", statistics.skippedfiles)
+ report_names("duplicate files : %i", statistics.duplicatefiles)
+ if runtime then
+ report_names("total scan time : %0.3f seconds",runtime)
+ end
+ end
+end
+
+local function collecthashes()
+ local data = names.data
+ local mappings = data.mappings
+ local fallbacks = data.fallbacks
+ local specifications = data.specifications
+ local nofmappings = 0
+ local noffallbacks = 0
+ if specifications then
+ -- maybe multiple passes
+ for index=1,#specifications do
+ local specification = specifications[index]
+ local format = specification.format
+ local fullname = specification.fullname
+ local fontname = specification.fontname
+ local familyname = specification.familyname or specification.family
+ local subfamilyname = specification.subfamilyname
+ local subfamily = specification.subfamily
+ local weight = specification.weight
+ local mapping = mappings[format]
+ local fallback = fallbacks[format]
+ if fullname and not mapping[fullname] then
+ mapping[fullname] = index
+ nofmappings = nofmappings + 1
+ end
+ if fontname and not mapping[fontname] then
+ mapping[fontname] = index
+ nofmappings = nofmappings + 1
+ end
+ if familyname then
+ if weight and weight ~= sub(familyname,#familyname-#weight+1,#familyname) then
+ local madename = familyname .. weight
+ if not mapping[madename] and not fallback[madename] then
+ fallback[madename] = index
+ noffallbacks = noffallbacks + 1
+ end
+ end
+ if subfamily and subfamily ~= sub(familyname,#familyname-#subfamily+1,#familyname) then
+ local extraname = familyname .. subfamily
+ if not mapping[extraname] and not fallback[extraname] then
+ fallback[extraname] = index
+ noffallbacks = noffallbacks + 1
+ end
+ end
+ if subfamilyname and subfamilyname ~= sub(familyname,#familyname-#subfamilyname+1,#familyname) then
+ local extraname = familyname .. subfamilyname
+ if not mapping[extraname] and not fallback[extraname] then
+ fallback[extraname] = index
+ noffallbacks = noffallbacks + 1
+ end
+ end
+ if not mapping[familyname] and not fallback[familyname] then
+ fallback[familyname] = index
+ noffallbacks = noffallbacks + 1
+ end
+ end
+ end
+ end
+ return nofmappings, noffallbacks
+end
+
+local function collectfamilies()
+ local data = names.data
+ local specifications = data.specifications
+ local families = data.families
+ for index=1,#specifications do
+ local familyname = specifications[index].familyname
+ local family = families[familyname]
+ if not family then
+ families[familyname] = { index }
+ else
+ family[#family+1] = index
+ end
+ end
+end
+
+local function checkduplicate(where) -- fails on "Romantik" but that's a border case anyway
+ local data = names.data
+ local mapping = data[where]
+ local specifications = data.specifications
+ local loaded = { }
+ if specifications and mapping then
+ -- was: for _, m in sortedhash(mapping) do
+ local order = filters.list
+ for i=1,#order do
+ local m = mapping[order[i]]
+ for k, v in sortedhash(m) do
+ local s = specifications[v]
+ local hash = formatters["%s-%s-%s-%s-%s"](s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*")
+ local h = loaded[hash]
+ if h then
+ local ok = true
+ local fn = s.filename
+ for i=1,#h do
+ local hn = s.filename
+ if h[i] == fn then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ h[#h+1] = fn
+ end
+ else
+ loaded[hash] = { s.filename }
+ end
+ end
+ end
+ end
+ local n = 0
+ for k, v in sortedhash(loaded) do
+ local nv = #v
+ if nv > 1 then
+ if trace_warnings then
+ report_names("lookup %a clashes with %a",k,v)
+ end
+ n = n + nv
+ end
+ end
+ report_names("%a double lookups in %a",n,where)
+end
+
+local function checkduplicates()
+ checkduplicate("mappings")
+ checkduplicate("fallbacks")
+end
+
+local function sorthashes()
+ local data = names.data
+ local list = filters.list
+ local mappings = data.mappings
+ local fallbacks = data.fallbacks
+ local sorted_mappings = { }
+ local sorted_fallbacks = { }
+ data.sorted_mappings = sorted_mappings
+ data.sorted_fallbacks = sorted_fallbacks
+ for i=1,#list do
+ local l = list[i]
+ sorted_mappings [l] = table.keys(mappings[l])
+ sorted_fallbacks[l] = table.keys(fallbacks[l])
+ sort(sorted_mappings [l],sorter)
+ sort(sorted_fallbacks[l],sorter)
+ end
+ data.sorted_families = table.keys(data.families)
+ sort(data.sorted_families,sorter)
+end
+
+local function unpackreferences()
+ local data = names.data
+ local specifications = data.specifications
+ if specifications then
+ for k, v in sortedhash(data.families) do
+ for i=1,#v do
+ v[i] = specifications[v[i]]
+ end
+ end
+ local mappings = data.mappings
+ if mappings then
+ for _, m in sortedhash(mappings) do
+ for k, v in sortedhash(m) do
+ m[k] = specifications[v]
+ end
+ end
+ end
+ local fallbacks = data.fallbacks
+ if fallbacks then
+ for _, f in sortedhash(fallbacks) do
+ for k, v in sortedhash(f) do
+ f[k] = specifications[v]
+ end
+ end
+ end
+ end
+end
+
+local function analyzefiles(olddata)
+ if not trace_warnings then
+ report_names("warnings are disabled (tracker 'fonts.warnings')")
+ end
+ local data = names.data
+ local done = { }
+ local totalnofread = 0
+ local totalnofskipped = 0
+ local totalnofduplicates = 0
+ local nofread = 0
+ local nofskipped = 0
+ local nofduplicates = 0
+ local skip_paths = filters.paths
+ local skip_names = filters.names
+ local specifications = data.specifications
+ local oldindices = olddata and olddata.indices or { }
+ local oldspecifications = olddata and olddata.specifications or { }
+ local oldrejected = olddata and olddata.rejected or { }
+ local treatmentdata = treatments.data or { } -- when used outside context
+
+ local function identify(completename,name,suffix,storedname)
+ local pathpart, basepart = splitbase(completename)
+ nofread = nofread + 1
+ local treatment = treatmentdata[completename] or treatmentdata[basepart]
+ if treatment and treatment.ignored then
+ if trace_names or trace_rejections then
+ report_names("%s font %a is ignored, reason %a",suffix,completename,treatment.comment or "unknown")
+ end
+ nofskipped = nofskipped + 1
+ elseif done[name] then
+ if lower(completename) ~= lower(done[name]) then
+ -- already done (avoid otf afm clash)
+ if trace_names or trace_rejections then
+ report_names("%s font %a already done as %a",suffix,completename,done[name])
+ end
+ nofduplicates = nofduplicates + 1
+ nofskipped = nofskipped + 1
+ end
+ elseif not exists(completename) then
+ -- weird error
+ if trace_names or trace_rejections then
+ report_names("%s font %a does not really exist",suffix,completename)
+ end
+ nofskipped = nofskipped + 1
+ elseif not is_qualified_path(completename) and findfile(completename,suffix) == "" then
+ -- not locatable by backend anyway
+ if trace_names or trace_rejections then
+ report_names("%s font %a cannot be found by backend",suffix,completename)
+ end
+ nofskipped = nofskipped + 1
+ else
+ if #skip_paths > 0 then
+ for i=1,#skip_paths do
+ if find(pathpart,skip_paths[i]) then
+ if trace_names or trace_rejections then
+ report_names("rejecting path of %s font %a",suffix,completename)
+ end
+ nofskipped = nofskipped + 1
+ return
+ end
+ end
+ end
+ if #skip_names > 0 then
+ for i=1,#skip_paths do
+ if find(basepart,skip_names[i]) then
+ done[name] = true
+ if trace_names or trace_rejections then
+ report_names("rejecting name of %s font %a",suffix,completename)
+ end
+ nofskipped = nofskipped + 1
+ return
+ end
+ end
+ end
+ if trace_names then
+ report_names("identifying %s font %a",suffix,completename)
+ end
+ -- needs checking with ttc / ttx : date not updated ?
+ local result = nil
+ local modification = lfs.attributes(completename,"modification")
+ if olddata and modification and modification > 0 then
+ local oldindex = oldindices[storedname] -- index into specifications
+ if oldindex then
+ local oldspecification = oldspecifications[oldindex]
+ if oldspecification and oldspecification.filename == storedname then -- double check for out of sync
+ local oldmodification = oldspecification.modification
+ if oldmodification == modification then
+ result = oldspecification
+ specifications[#specifications + 1] = result
+ else
+ -- ??
+ end
+ else
+ -- ??
+ end
+ elseif oldrejected[storedname] == modification then
+ result = false
+ end
+ end
+ if result == nil then
+ local lsuffix = lower(suffix)
+ local result, message = filters[lsuffix](completename)
+ if result then
+ if #result > 0 then
+ for r=1,#result do
+ local ok = check_name(data,result[r],storedname,modification,suffix,r) -- subfonts start at zero
+ -- if not ok then
+ -- nofskipped = nofskipped + 1
+ -- end
+ end
+ else
+ local ok = check_name(data,result,storedname,modification,suffix)
+ -- if not ok then
+ -- nofskipped = nofskipped + 1
+ -- end
+ end
+ if trace_warnings and message and message ~= "" then
+ report_names("warning when identifying %s font %a, %s",suffix,completename,message)
+ end
+ elseif trace_warnings then
+ nofskipped = nofskipped + 1
+ report_names("error when identifying %s font %a, %s",suffix,completename,message or "unknown")
+ end
+ end
+ done[name] = completename
+ end
+ logs.flush() -- a bit overkill for each font, maybe not needed here
+ end
+ local function traverse(what, method)
+ local list = filters.list
+ for n=1,#list do
+ local suffix = list[n]
+ local t = os.gettimeofday() -- use elapser
+ nofread, nofskipped, nofduplicates = 0, 0, 0
+ suffix = lower(suffix)
+ report_names("identifying %s font files with suffix %a",what,suffix)
+ method(suffix)
+ suffix = upper(suffix)
+ report_names("identifying %s font files with suffix %a",what,suffix)
+ method(suffix)
+ totalnofread, totalnofskipped, totalnofduplicates = totalnofread + nofread, totalnofskipped + nofskipped, totalnofduplicates + nofduplicates
+ local elapsed = os.gettimeofday() - t
+ report_names("%s %s files identified, %s skipped, %s duplicates, %s hash entries added, runtime %0.3f seconds",nofread,what,nofskipped,nofduplicates,nofread-nofskipped,elapsed)
+ end
+ logs.flush()
+ end
+ -- problem .. this will not take care of duplicates
+ local function withtree(suffix)
+ resolvers.dowithfilesintree(".*%." .. suffix .. "$", function(method,root,path,name)
+ if method == "file" or method == "tree" then
+ local completename = root .."/" .. path .. "/" .. name
+ completename = resolveprefix(completename) -- no shortcut
+ identify(completename,name,suffix,name)
+ return true
+ end
+ end, function(blobtype,blobpath,pattern)
+ blobpath = resolveprefix(blobpath) -- no shortcut
+ 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)
+ end)
+ end
+ local function withlsr(suffix) -- all trees
+ -- we do this only for a stupid names run, not used for context itself,
+ -- using the vars is too clumsy so we just stick to a full scan instead
+ local pathlist = resolvers.splitpath(resolvers.showpath("ls-R") or "")
+ walk_tree(pathlist,suffix,identify)
+ end
+ local function withsystem(suffix) -- OSFONTDIR cum suis
+ walk_tree(names.getpaths(trace),suffix,identify)
+ end
+ traverse("tree",withtree) -- TEXTREE only
+ if not usesystemfonts then
+ report_names("ignoring system fonts")
+ elseif texconfig.kpse_init then
+ traverse("lsr", withlsr)
+ else
+ traverse("system", withsystem)
+ end
+ data.statistics.readfiles = totalnofread
+ data.statistics.skippedfiles = totalnofskipped
+ data.statistics.duplicatefiles = totalnofduplicates
+end
+
+local function addfilenames()
+ local data = names.data
+ local specifications = data.specifications
+ local indices = { }
+ local files = { }
+ for i=1,#specifications do
+ local fullname = specifications[i].filename
+ files[cleanfilename(fullname)] = fullname
+ indices[fullname] = i
+ end
+ data.files = files
+ data.indices = indices
+end
+
+local function rejectclashes() -- just to be sure, so no explicit afm will be found then
+ local specifications = names.data.specifications
+ local used = { }
+ local okay = { }
+ local rejected = { } -- only keep modification
+ local o = 0
+ for i=1,#specifications do
+ local s = specifications[i]
+ local f = s.fontname
+ if f then
+ local fnd = used[f]
+ local fnm = s.filename
+ if fnd then
+ if trace_warnings then
+ report_names("fontname %a clashes, %a rejected in favor of %a",f,fnm,fnd)
+ end
+ rejected[f] = s.modification
+ else
+ used[f] = fnm
+ o = o + 1
+ okay[o] = s
+ end
+ else
+ o = o + 1
+ okay[o] = s
+ end
+ end
+ local d = #specifications - #okay
+ if d > 0 then
+ report_names("%s files rejected due to clashes",d)
+ end
+ names.data.specifications = okay
+ names.data.rejected = rejected
+end
+
+local function resetdata()
+ local mappings = { }
+ local fallbacks = { }
+ for _, k in next, filters.list do
+ mappings [k] = { }
+ fallbacks[k] = { }
+ end
+ names.data = {
+ version = names.version,
+ mappings = mappings,
+ fallbacks = fallbacks,
+ specifications = { },
+ families = { },
+ statistics = { },
+ names = { },
+ indices = { },
+ rejected = { },
+ datastate = resolvers.datastate(),
+ }
+end
+
+function names.identify(force)
+ local starttime = os.gettimeofday() -- use elapser
+ resetdata()
+ analyzefiles(not force and names.readdata(names.basename))
+ rejectclashes()
+ collectfamilies()
+ cleanupkeywords()
+ collecthashes()
+ checkduplicates()
+ addfilenames()
+ -- sorthashes() -- will be resorted when saved
+ collectstatistics(os.gettimeofday()-starttime)
+end
+
+function names.is_permitted(name)
+ return containers.is_usable(names.cache, name)
+end
+function names.writedata(name,data)
+ containers.write(names.cache,name,data)
+end
+function names.readdata(name)
+ return containers.read(names.cache,name)
+end
+
+function names.load(reload,force)
+ if not names.loaded then
+ if reload then
+ if names.is_permitted(names.basename) then
+ names.identify(force)
+ names.writedata(names.basename,names.data)
+ else
+ report_names("unable to access database cache")
+ end
+ names.saved = true
+ end
+ local data = names.readdata(names.basename)
+ names.data = data
+ if not names.saved then
+ if not data or not next(data) or not data.specifications or not next(data.specifications) then
+ names.load(true)
+ end
+ names.saved = true
+ end
+ if not data then
+ report_names("accessing the data table failed")
+ else
+ unpackreferences()
+ sorthashes()
+ end
+ names.loaded = true
+ end
+end
+
+local function list_them(mapping,sorted,pattern,t,all)
+ if mapping[pattern] then
+ t[pattern] = mapping[pattern]
+ else
+ for k=1,#sorted do
+ local v = sorted[k]
+ if not t[v] and find(v,pattern) then
+ t[v] = mapping[v]
+ if not all then
+ return
+ end
+ end
+ end
+ end
+end
+
+function names.list(pattern,reload,all) -- here?
+ names.load() -- todo reload
+ if names.loaded then
+ local t = { }
+ local data = names.data
+ if data then
+ local list = filters.list
+ local mappings = data.mappings
+ local sorted_mappings = data.sorted_mappings
+ local fallbacks = data.fallbacks
+ local sorted_fallbacks = data.sorted_fallbacks
+ for i=1,#list do
+ local format = list[i]
+ list_them(mappings[format],sorted_mappings[format],pattern,t,all)
+ if next(t) and not all then
+ return t
+ end
+ list_them(fallbacks[format],sorted_fallbacks[format],pattern,t,all)
+ if next(t) and not all then
+ return t
+ end
+ end
+ end
+ return t
+ end
+end
+
+local reloaded = false
+
+local function is_reloaded()
+ if not reloaded then
+ local data = names.data
+ if autoreload then
+ local c_status = serialize(resolvers.datastate())
+ local f_status = serialize(data.datastate)
+ if c_status == f_status then
+ if trace_names then
+ report_names("font database has matching configuration and file hashes")
+ end
+ return
+ else
+ report_names("font database has mismatching configuration and file hashes")
+ end
+ else
+ report_names("font database is regenerated (controlled by directive 'fonts.autoreload')")
+ end
+ names.loaded = false
+ reloaded = true
+ logs.flush()
+ names.load(true)
+ end
+end
+
+--[[ldx--
+<p>The resolver also checks if the cached names are loaded. Being clever
+here is for testing purposes only (it deals with names prefixed by an
+encoding name).</p>
+--ldx]]--
+
+local function fuzzy(mapping,sorted,name,sub)
+ local condensed = gsub(name,"[^%a%d]","")
+ for k=1,#sorted do
+ local v = sorted[k]
+ if find(v,condensed) then
+ return mapping[v], v
+ end
+ end
+end
+
+-- we could cache a lookup .. maybe some day ... (only when auto loaded!)
+
+local function foundname(name,sub) -- sub is not used currently
+ local data = names.data
+ local mappings = data.mappings
+ local sorted_mappings = data.sorted_mappings
+ local fallbacks = data.fallbacks
+ local sorted_fallbacks = data.sorted_fallbacks
+ local list = filters.list
+ -- dilemma: we lookup in the order otf ttf ttc ... afm but now an otf fallback
+ -- can come after an afm match ... well, one should provide nice names anyway
+ -- and having two lists is not an option
+ for i=1,#list do
+ local l = list[i]
+ local found = mappings[l][name]
+ if found then
+ if trace_names then
+ report_names("resolved via direct name match: %a",name)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found, fname = fuzzy(mappings[l],sorted_mappings[l],name,sub)
+ if found then
+ if trace_names then
+ report_names("resolved via fuzzy name match: %a onto %a",name,fname)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found = fallbacks[l][name]
+ if found then
+ if trace_names then
+ report_names("resolved via direct fallback match: %a",name)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found, fname = fuzzy(sorted_mappings[l],sorted_fallbacks[l],name,sub)
+ if found then
+ if trace_names then
+ report_names("resolved via fuzzy fallback match: %a onto %a",name,fname)
+ end
+ return found
+ end
+ end
+ if trace_names then
+ report_names("font with name %a cannot be found",name)
+ end
+end
+
+function names.resolvedspecification(askedname,sub)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = cleanname(askedname)
+ names.load()
+ local found = foundname(askedname,sub)
+ if not found and is_reloaded() then
+ found = foundname(askedname,sub)
+ end
+ return found
+ end
+end
+
+function names.resolve(askedname,sub)
+ local found = names.resolvedspecification(askedname,sub)
+ if found then
+ return found.filename, found.subfont and found.rawname, found.subfont
+ end
+end
+
+-- function names.getfilename(askedname,suffix) -- last resort, strip funny chars
+-- names.load()
+-- local files = names.data.files
+-- askedname = files and files[cleanfilename(askedname,suffix)] or ""
+-- if askedname == "" then
+-- return ""
+-- else -- never entered
+-- return resolvers.findbinfile(askedname,suffix) or ""
+-- end
+-- end
+
+function names.getfilename(askedname,suffix) -- last resort, strip funny chars
+ names.load()
+ local files = names.data.files
+ local cleanname = cleanfilename(askedname,suffix)
+ local found = files and files[cleanname] or ""
+ if found == "" and is_reloaded() then
+ files = names.data.files
+ found = files and files[cleanname] or ""
+ end
+ if found and found ~= "" then
+ return resolvers.findbinfile(found,suffix) or "" -- we still need to locate it
+ end
+end
+
+-- specified search
+
+local function s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family)
+ if family then
+ for i=1,#family do
+ local f = family[i]
+ if f and weight == f.weight and style == f.style and width == f.width and variant == f.variant then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and width == f.width and variant == f.variant and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight_style_width(found,done,all,weight,style,width,family)
+ if family then
+ for i=1,#family do
+ local f = family[i]
+ if f and weight == f.weight and style == f.style and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight_style(found,done,all,weight,style,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and weight == f.weight and style == f.style then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_style_width(found,done,all,style,width,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and style == f.style and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_style_width(found,done,all,style,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and style == f.style and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight(found,done,all,weight,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and weight == f.weight then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight(found,done,all,weight,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_style(found,done,all,style,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and style == f.style then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_style(found,done,all,style,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and style == f.style and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_width(found,done,all,width,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_width(found,done,all,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect(found,done,all,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect(found,done,all,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function collect(stage,found,done,name,weight,style,width,variant,all)
+ local data = names.data
+ local families = data.families
+ local sorted = data.sorted_families
+ local strictname = "^".. name -- to be checked
+ local family = families[name]
+ if trace_names then
+ report_names("resolving name %a, weight %a, style %a, width %a, variant %a",name,weight,style,width,variant)
+ end
+ if weight and weight ~= "" then
+ if style and style ~= "" then
+ if width and width ~= "" then
+ if variant and variant ~= "" then
+ if trace_names then
+ report_names("resolving stage %s, name %a, weight %a, style %a, width %a, variant %a",stage,name,weight,style,width,variant)
+ end
+ s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family)
+ m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname)
+ else
+ if trace_names then
+ report_names("resolving stage %s, name %a, weight %a, style %a, width %a",stage,name,weight,style,width)
+ end
+ s_collect_weight_style_width(found,done,all,weight,style,width,family)
+ m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname)
+ end
+ else
+ if trace_names then
+ report_names("resolving stage %s, name %a, weight %a, style %a",stage,name,weight,style)
+ end
+ s_collect_weight_style(found,done,all,weight,style,family)
+ m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname)
+ end
+ else
+ if trace_names then
+ report_names("resolving stage %s, name %a, weight %a",stage,name,weight)
+ end
+ s_collect_weight(found,done,all,weight,family)
+ m_collect_weight(found,done,all,weight,families,sorted,strictname)
+ end
+ elseif style and style ~= "" then
+ if width and width ~= "" then
+ if trace_names then
+ report_names("resolving stage %s, name %a, style %a, width %a",stage,name,style,width)
+ end
+ s_collect_style_width(found,done,all,style,width,family)
+ m_collect_style_width(found,done,all,style,width,families,sorted,strictname)
+ else
+ if trace_names then
+ report_names("resolving stage %s, name %a, style %a",stage,name,style)
+ end
+ s_collect_style(found,done,all,style,family)
+ m_collect_style(found,done,all,style,families,sorted,strictname)
+ end
+ elseif width and width ~= "" then
+ if trace_names then
+ report_names("resolving stage %s, name %a, width %a",stage,name,width)
+ end
+ s_collect_width(found,done,all,width,family)
+ m_collect_width(found,done,all,width,families,sorted,strictname)
+ else
+ if trace_names then
+ report_names("resolving stage %s, name %a",stage,name)
+ end
+ s_collect(found,done,all,family)
+ m_collect(found,done,all,families,sorted,strictname)
+ end
+end
+
+local function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks
+ local found, done = { }, { }
+--~ print(name,weight,style,width,variant)
+ weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal"
+ name = cleanname(name)
+ collect(1,found,done,name,weight,style,width,variant,all)
+ -- still needed ?
+ if #found == 0 and variant ~= "normal" then -- not weight
+ variant = "normal"
+ collect(4,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and width ~= "normal" then
+ width = "normal"
+ collect(2,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and weight ~= "normal" then -- not style
+ weight = "normal"
+ collect(3,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and style ~= "normal" then -- not weight
+ style = "normal"
+ collect(4,found,done,name,weight,style,width,variant,all)
+ end
+ --
+ local nf = #found
+ if trace_names then
+ if nf then
+ local t = { }
+ for i=1,nf do
+ t[i] = formatters["%a"](found[i].fontname)
+ end
+ report_names("name %a resolved to %s instances: % t",name,nf,t)
+ else
+ report_names("name %a unresolved",name)
+ end
+ end
+ if all then
+ return nf > 0 and found
+ else
+ return found[1]
+ end
+end
+
+function names.specification(askedname,weight,style,width,variant,reload,all)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = cleanname(askedname) -- or cleanname
+ names.load(reload)
+ local found = heuristic(askedname,weight,style,width,variant,all)
+ if not found and is_reloaded() then
+ found = heuristic(askedname,weight,style,width,variant,all)
+ if not filename then
+ found = foundname(askedname) -- old method
+ end
+ end
+ return found
+ end
+end
+
+function names.collect(askedname,weight,style,width,variant,reload,all)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = cleanname(askedname) -- or cleanname
+ names.load(reload)
+ local list = heuristic(askedname,weight,style,width,variant,true)
+ if not list or #list == 0 and is_reloaded() then
+ list = heuristic(askedname,weight,style,width,variant,true)
+ end
+ return list
+ end
+end
+
+function names.collectspec(askedname,reload,all)
+ local name, weight, style, width, variant = names.splitspec(askedname)
+ return names.collect(name,weight,style,width,variant,reload,all)
+end
+
+function names.resolvespec(askedname,sub) -- redefined later
+ local found = names.specification(names.splitspec(askedname))
+ if found then
+ return found.filename, found.subfont and found.rawname
+ end
+end
+
+function names.collectfiles(askedname,reload) -- no all
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = cleanname(askedname) -- or cleanname
+ names.load(reload)
+ local list = { }
+ local specifications = names.data.specifications
+ for i=1,#specifications do
+ local s = specifications[i]
+ if find(cleanname(basename(s.filename)),askedname) then
+ list[#list+1] = s
+ end
+ end
+ return list
+ end
+end
+
+-- todo:
+--
+-- blacklisted = {
+-- ["cmr10.ttf"] = "completely messed up",
+-- }
+
+function names.exists(name)
+ local found = false
+ local list = filters.list
+ for k=1,#list do
+ local v = list[k]
+ found = (findfile(name,v) or "") ~= ""
+ if found then
+ return found
+ end
+ end
+ return (findfile(name,"tfm") or "") ~= "" or (names.resolve(name) or "") ~= ""
+end
+
+local lastlookups, lastpattern = { }, ""
+
+-- function names.lookup(pattern,name,reload) -- todo: find
+-- if lastpattern ~= pattern then
+-- names.load(reload)
+-- local specifications = names.data.specifications
+-- local families = names.data.families
+-- local lookups = specifications
+-- if name then
+-- lookups = families[name]
+-- elseif not find(pattern,"=",1,true) then
+-- lookups = families[pattern]
+-- end
+-- if trace_names then
+-- report_names("starting with %s lookups for %a",#lookups,pattern)
+-- end
+-- if lookups then
+-- for key, value in gmatch(pattern,"([^=,]+)=([^=,]+)") do
+-- local t, n = { }, 0
+-- if find(value,"*",1,true) then
+-- value = topattern(value)
+-- for i=1,#lookups do
+-- local s = lookups[i]
+-- if find(s[key],value) then
+-- n = n + 1
+-- t[n] = lookups[i]
+-- end
+-- end
+-- else
+-- for i=1,#lookups do
+-- local s = lookups[i]
+-- if s[key] == value then
+-- n = n + 1
+-- t[n] = lookups[i]
+-- end
+-- end
+-- end
+-- if trace_names then
+-- report_names("%s matches for key %a with value %a",#t,key,value)
+-- end
+-- lookups = t
+-- end
+-- end
+-- lastpattern = pattern
+-- lastlookups = lookups or { }
+-- end
+-- return #lastlookups
+-- end
+
+local function look_them_up(lookups,specification)
+ for key, value in sortedhash(specification) do
+ local t, n = { }, 0
+ if find(value,"*",1,true) then
+ value = topattern(value)
+ for i=1,#lookups do
+ local s = lookups[i]
+ if find(s[key],value) then
+ n = n + 1
+ t[n] = lookups[i]
+ end
+ end
+ else
+ for i=1,#lookups do
+ local s = lookups[i]
+ if s[key] == value then
+ n = n + 1
+ t[n] = lookups[i]
+ end
+ end
+ end
+ if trace_names then
+ report_names("%s matches for key %a with value %a",#t,key,value)
+ end
+ lookups = t
+ end
+ return lookups
+end
+
+local function first_look(name,reload)
+ names.load(reload)
+ local data = names.data
+ local specifications = data.specifications
+ local families = data.families
+ if name then
+ return families[name]
+ else
+ return specifications
+ end
+end
+
+function names.lookup(pattern,name,reload) -- todo: find
+ names.load(reload)
+ local data = names.data
+ local specifications = data.specifications
+ local families = data.families
+ local lookups = specifications
+ if name then
+ name = cleanname(name)
+ end
+ if type(pattern) == "table" then
+ local familyname = pattern.familyname
+ if familyname then
+ familyname = cleanname(familyname)
+ pattern.familyname = familyname
+ end
+ local lookups = first_look(name or familyname,reload)
+ if lookups then
+ if trace_names then
+ report_names("starting with %s lookups for '%T'",#lookups,pattern)
+ end
+ lookups = look_them_up(lookups,pattern)
+ end
+ lastpattern = false
+ lastlookups = lookups or { }
+ elseif lastpattern ~= pattern then
+ local lookups = first_look(name or (not find(pattern,"=",1,true) and pattern),reload)
+ if lookups then
+ if trace_names then
+ report_names("starting with %s lookups for %a",#lookups,pattern)
+ end
+ local specification = settings_to_hash(pattern)
+ local familyname = specification.familyname
+ if familyname then
+ familyname = cleanname(familyname)
+ specification.familyname = familyname
+ end
+ lookups = look_them_up(lookups,specification)
+ end
+ lastpattern = pattern
+ lastlookups = lookups or { }
+ end
+ return #lastlookups
+end
+
+function names.getlookupkey(key,n)
+ local l = lastlookups[n or 1]
+ return (l and l[key]) or ""
+end
+
+function names.noflookups()
+ return #lastlookups
+end
+
+function names.getlookups(pattern,name,reload)
+ if pattern then
+ names.lookup(pattern,name,reload)
+ end
+ return lastlookups
+end
+
+-- The following is new ... watch the overload!
+
+local specifications = allocate()
+names.specifications = specifications
+
+-- files = {
+-- name = "antykwapoltawskiego",
+-- list = {
+-- ["AntPoltLtCond-Regular.otf"] = {
+-- -- name = "antykwapoltawskiego",
+-- style = "regular",
+-- weight = "light",
+-- width = "condensed",
+-- },
+-- },
+-- }
+
+function names.register(files)
+ if files then
+ local list, commonname = files.list, files.name
+ if list then
+ local n, m = 0, 0
+ for filename, filespec in sortedhash(list) do
+ local name = lower(filespec.name or commonname)
+ if name and name ~= "" then
+ local style = normalized_styles [lower(filespec.style or "normal")]
+ local width = normalized_widths [lower(filespec.width or "normal")]
+ local weight = normalized_weights [lower(filespec.weight or "normal")]
+ local variant = normalized_variants[lower(filespec.variant or "normal")]
+ local weights = specifications[name ] if not weights then weights = { } specifications[name ] = weights end
+ local styles = weights [weight] if not styles then styles = { } weights [weight] = styles end
+ local widths = styles [style ] if not widths then widths = { } styles [style ] = widths end
+ local variants = widths [width ] if not variants then variants = { } widths [width ] = variants end
+ variants[variant] = filename
+ n = n + 1
+ else
+ m = m + 1
+ end
+ end
+ if trace_specifications then
+ report_names("%s filenames registered, %s filenames rejected",n,m)
+ end
+ end
+ end
+end
+
+function names.registered(name,weight,style,width,variant)
+ local ok = specifications[name]
+ ok = ok and (ok[(weight and weight ~= "" and weight ) or "normal"] or ok.normal)
+ ok = ok and (ok[(style and style ~= "" and style ) or "normal"] or ok.normal)
+ ok = ok and (ok[(width and width ~= "" and width ) or "normal"] or ok.normal)
+ ok = ok and (ok[(variant and variant ~= "" and variant) or "normal"] or ok.normal)
+ --
+ -- todo: same fallbacks as with database
+ --
+ if ok then
+ return {
+ filename = ok,
+ subname = "",
+ -- rawname = nil,
+ }
+ end
+end
+
+function names.resolvespec(askedname,sub) -- overloads previous definition
+ local name, weight, style, width, variant = names.splitspec(askedname)
+ if trace_specifications then
+ report_names("resolving specification: %a to name=%s, weight=%s, style=%s, width=%s, variant=%s",askedname,name,weight,style,width,variant)
+ end
+ local found = names.registered(name,weight,style,width,variant)
+ if found and found.filename then
+ if trace_specifications then
+ report_names("resolved by registered names: %a to %s",askedname,found.filename)
+ end
+ return found.filename, found.subname, found.rawname
+ else
+ found = names.specification(name,weight,style,width,variant)
+ if found and found.filename then
+ if trace_specifications then
+ report_names("resolved by font database: %a to %s",askedname,found.filename)
+ end
+ return found.filename, found.subfont and found.rawname
+ end
+ end
+ if trace_specifications then
+ report_names("unresolved: %s",askedname)
+ end
+end
+
+function fonts.names.ignoredfile(filename) -- only supported in mkiv
+ return false -- will be overloaded
+end
+
+-- example made for luatex list (unlikely to be used):
+--
+-- local command = [[reg QUERY "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"]]
+-- local pattern = ".-[\n\r]+%s+(.-)%s%(([^%)]+)%)%s+REG_SZ%s+(%S+)%s+"
+--
+-- local function getnamesfromregistry()
+-- local data = os.resultof(command)
+-- local list = { }
+-- for name, format, filename in string.gmatch(data,pattern) do
+-- list[name] = filename
+-- end
+-- return list
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua
new file mode 100644
index 00000000000..8e92c4808a6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua
@@ -0,0 +1,201 @@
+if not modules then modules = { } end modules ['font-tfm'] = {
+ 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 match = string.match
+
+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)
+
+local report_defining = logs.reporter("fonts","defining")
+local report_tfm = logs.reporter("fonts","tfm loading")
+
+local findbinfile = resolvers.findbinfile
+
+local fonts = fonts
+local handlers = fonts.handlers
+local readers = fonts.readers
+local constructors = fonts.constructors
+local encodings = fonts.encodings
+
+local tfm = constructors.newhandler("tfm")
+tfm.version = 1.000
+tfm.maxnestingdepth = 5
+tfm.maxnestingsize = 65536*1024
+
+local tfmfeatures = constructors.newfeatures("tfm")
+local registertfmfeature = tfmfeatures.register
+
+constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
+
+fonts.formats.tfm = "type1" -- we need to have at least a value here
+fonts.formats.ofm = "type1" -- we need to have at least a value here
+
+--[[ldx--
+<p>The next function encapsulates the standard <l n='tfm'/> loader as
+supplied by <l n='luatex'/>.</p>
+--ldx]]--
+
+-- this might change: not scaling and then apply features and do scaling in the
+-- usual way with dummy descriptions but on the other hand .. we no longer use
+-- tfm so why bother
+
+-- ofm directive blocks local path search unless set; btw, in context we
+-- don't support ofm files anyway as this format is obsolete
+
+-- we need to deal with nested virtual fonts, but because we load in the
+-- frontend we also need to make sure we don't nest too deep (esp when sizes
+-- get large)
+--
+-- (VTITLE Example of a recursion)
+-- (MAPFONT D 0 (FONTNAME recurse)(FONTAT D 2))
+-- (CHARACTER C A (CHARWD D 1)(CHARHT D 1)(MAP (SETRULE D 1 D 1)))
+-- (CHARACTER C B (CHARWD D 2)(CHARHT D 2)(MAP (SETCHAR C A)))
+-- (CHARACTER C C (CHARWD D 4)(CHARHT D 4)(MAP (SETCHAR C B)))
+--
+-- we added the same checks as below to the luatex engine
+
+function tfm.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
+ if okay then
+ return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
+ else
+ return { } -- will become false
+ end
+end
+
+local depth = { } -- table.setmetatableindex("number")
+
+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 resources = tfmdata.resources or { }
+ local properties = tfmdata.properties or { }
+ local parameters = tfmdata.parameters or { }
+ local shared = tfmdata.shared or { }
+ properties.name = tfmdata.name
+ properties.fontname = tfmdata.fontname
+ properties.psname = tfmdata.psname
+ properties.filename = specification.filename
+ properties.format = fonts.formats.tfm -- better than nothing
+ parameters.size = size
+ --
+ tfmdata.properties = properties
+ tfmdata.resources = resources
+ tfmdata.parameters = parameters
+ tfmdata.shared = shared
+ --
+ shared.rawdata = { }
+ shared.features = features
+ shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
+ parameters.slant = parameters.slant or parameters[1] or 0
+ parameters.space = parameters.space or parameters[2] or 0
+ parameters.space_stretch = parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink = parameters.space_shrink or parameters[4] or 0
+ parameters.x_height = parameters.x_height or parameters[5] or 0
+ parameters.quad = parameters.quad or parameters[6] or 0
+ parameters.extra_space = parameters.extra_space or parameters[7] or 0
+ --
+ constructors.enhanceparameters(parameters) -- official copies for us
+ --
+ if constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.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
+ 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
+ end
+ end
+ end
+ end
+ --
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
+ if not features.encoding then
+ local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if filename and encoding and encodings.known and encodings.known[encoding] then
+ features.encoding = encoding
+ end
+ end
+ -- let's play safe:
+ 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)
+ end
+end
+
+readers.check_tfm = check_tfm
+
+function readers.tfm(specification)
+ local fullname = specification.filename or ""
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ fullname = specification.name .. "." .. forced
+ else
+ fullname = specification.name
+ end
+ end
+ return check_tfm(specification,fullname)
+end
+
+readers.ofm = readers.tfm
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tmp.lua b/Master/texmf-dist/tex/context/base/mkiv/font-tmp.lua
new file mode 100644
index 00000000000..8db5cff1436
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-tmp.lua
@@ -0,0 +1,118 @@
+if not modules then modules = { } end modules ['font-tmp'] = {
+ 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"
+}
+
+-- There is a complete feature loader but it needs a bit of testing, first so this
+-- one does design size only (as needed for identifying).
+
+local next, type = next, type
+
+local report = logs.reporter("otf reader")
+
+local readers = fonts.handlers.otf.readers
+local streamreader = readers.streamreader
+
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local readshort = streamreader.readinteger2 -- 16-bit signed integer
+local readtag = streamreader.readtag
+local skipshort = streamreader.skipshort
+local setposition = streamreader.setposition
+
+local plugins = { }
+
+function plugins.size(f,fontdata,tableoffset,parameters)
+ if not fontdata.designsize then
+ setposition(f,tableoffset+parameters)
+ local designsize = readushort(f)
+ if designsize > 0 then
+ fontdata.designsize = designsize
+ skipshort(f,2)
+ fontdata.minsize = readushort(f)
+ fontdata.maxsize = readushort(f)
+ end
+ end
+end
+
+local function readscripts(f,fontdata,what)
+ local datatable = fontdata.tables[what]
+ if not datatable then
+ return
+ end
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readulong(f)
+ if version ~= 0x00010000 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ return
+ end
+ --
+ local scriptoffset = tableoffset + readushort(f)
+ local featureoffset = tableoffset + readushort(f)
+ local lookupoffset = tableoffset + readushort(f)
+ --
+ setposition(f,scriptoffset)
+ local nofscripts = readushort(f)
+ local scripts = { }
+ for i=1,nofscripts do
+ scripts[readtag(f)] = scriptoffset + readushort(f)
+ end
+ local languagesystems = table.setmetatableindex("table") -- we share when possible
+ for script, offset in next, scripts do
+ setposition(f,offset)
+ local defaultoffset = readushort(f)
+ local noflanguages = readushort(f)
+ local languages = { }
+ if defaultoffset > 0 then
+ languages.dflt = languagesystems[offset + defaultoffset]
+ end
+ for i=1,noflanguages do
+ local language = readtag(f)
+ local offset = offset + readushort(f)
+ languages[language] = languagesystems[offset]
+ end
+ scripts[script] = languages
+ end
+ --
+ setposition(f,featureoffset)
+ local features = { }
+ local noffeatures = readushort(f)
+ for i=1,noffeatures do
+ features[i] = {
+ tag = readtag(f),
+ offset = readushort(f)
+ }
+ end
+ --
+ for i=1,noffeatures do
+ local feature = features[i]
+ local offset = featureoffset + feature.offset
+ setposition(f,offset)
+ local parameters = readushort(f) -- feature.parameters
+ local noflookups = readushort(f)
+ skipshort(f,noflookups+1)
+ if parameters > 0 then
+ feature.parameters = parameters
+ local plugin = plugins[feature.tag]
+ if plugin then
+ plugin(f,fontdata,offset,parameters)
+ end
+ end
+ end
+end
+
+function readers.gsub(f,fontdata,specification)
+ if specification.details then
+ readscripts(f,fontdata,"gsub")
+ end
+end
+
+function readers.gpos(f,fontdata,specification)
+ if specification.details then
+ readscripts(f,fontdata,"gpos")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv
new file mode 100644
index 00000000000..f5290d61463
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv
@@ -0,0 +1,290 @@
+%D \module
+%D [ file=font-tra,
+%D version=2009.01.02, % or so
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Tracing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\writestatus{loading}{ConTeXt Font Macros / Tracing}
+
+%D just use fontid
+
+%D \macros
+%D {showbodyfont}
+%D
+%D One can call for a rather simple overview of a bodyfont and the
+%D relations between its alternative fonts.
+%D
+%D \showsetup{showbodyfont}
+%D
+%D The current bodyfont (here we omitted the argument) looks like:
+%D
+%D \showbodyfont
+%D
+%D The implementation is rather straightforward in using
+%D \type{\halign}.
+
+\fetchruntimecommand \showbodyfont {\f!fontprefix\s!run}
+
+%D \macros
+%D {showfontstrip, testminimalbaseline, showminimalbaseline}
+%D
+%D The next command can come in handy when combining
+%D different fonts into a collection (typeface) and
+%D determining optimal baseline distances.
+%D
+%D \showfontstrip \blank \showminimalbaseline
+
+\fetchruntimecommand \showfontstrip {\f!fontprefix\s!run}
+\fetchruntimecommand \testminimalbaseline {\f!fontprefix\s!run}
+\fetchruntimecommand \showminimalbaseline {\f!fontprefix\s!run}
+
+%D \macros
+%D {showkerning}
+%D
+%D A goody is:
+%D
+%D \showkerning{Can you guess what kerning is?}
+
+\fetchruntimecommand \showkerning {\f!fontprefix\s!run}
+
+%D \macros
+%D {showbodyfontenvironment,showfont,showfontstyle,showligatures}
+%D
+%D The current bodyfontenvironment is:
+%D
+%D \showbodyfontenvironment
+%D
+%D This overview is generated using:
+%D
+%D \showsetup{showbodyfontenvironment}
+
+\fetchruntimecommand \showbodyfontenvironment {\f!fontprefix\s!run}
+
+%D
+%D The following command generates a fontmap:
+%D
+%D \startbuffer
+%D \showfont[SansBold at 12pt]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\fetchruntimecommand \showfont {\f!fontprefix\s!run}
+\fetchruntimecommand \showfontstyle {\f!fontprefix\s!run}
+\fetchruntimecommand \showligature {\f!fontprefix\s!run}
+\fetchruntimecommand \showligatures {\f!fontprefix\s!run}
+\fetchruntimecommand \showcharratio {\f!fontprefix\s!run}
+\fetchruntimecommand \showfontparameters {\f!fontprefix\s!run}
+
+\unexpanded\def\showchardata #1{\ctxcommand{showchardata("#1")}}
+\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}}
+
+%D \macros
+%D {doiffontpresentelse}
+%D
+%D \starttyping
+%D \doiffontpresentelse{texnansi-lmr10}{YES}{NO}
+%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO}
+%D \stoptyping
+
+\unexpanded\def\doifelsefontpresent#1{\clf_doifelsefontpresent{#1}}
+
+\let\doiffontpresentelse\doifelsefontpresent
+
+% experimental, maybe this becomes a module
+
+\newbox\otfcollector
+
+\unexpanded\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}}
+\unexpanded\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}}
+\unexpanded\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}}
+
+% Rather experimental:
+%
+% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page
+% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page
+
+\unexpanded\def\showotfstepglyphs#1%
+ {\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}%
+ \unhbox\otfcollector}
+
+\unexpanded\def\otfstepspace
+ {\removeunwantedspaces
+ \hskip.5\emwidth \s!plus .125\emwidth \s!minus .125\emwidth\relax}
+
+\unexpanded\def\otfstepcharcommand#1#2#3% font char class
+ {\otfstepspace
+ \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}%
+ \otfstepspace}
+
+\unexpanded\def\otfstepfontcommand#1#2#3% id font size
+ {\begingroup
+ \tttf #1: #2 @ \the\dimexpr#3\scaledpoint\relax
+ \endgroup}
+
+\unexpanded\def\otfstepmessagecommand#1#2%
+ {\begingroup
+ \tttf\language\minusone
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar
+ \hangindent\emwidth
+ \hangafter\plusone
+ \dontleavehmode\detokenize{#1}\removeunwantedspaces
+ \doifsomething{#2}{,\space\detokenize{#2}}\endgraf
+ \endgroup
+ \blank}
+
+\unexpanded\def\showotfstepfont
+ {\ctxlua{nodes.tracers.steppers.font("otfstepfontcommand")}}
+
+\unexpanded\def\showotfstepchars#1%
+ {\ctxlua{nodes.tracers.steppers.codes(#1,"otfstepcharcommand","otfstepspace")}}
+
+\unexpanded\def\showotfstepmessages#1%
+ {\ctxlua{nodes.tracers.steppers.messages(#1,"otfstepmessagecommand",true)}}
+
+\unexpanded\def\showotfstepfeatures
+ {\ctxlua{nodes.tracers.steppers.features()}}
+
+\unexpanded\def\otfnoffeaturesteps
+ {\ctxlua{nodes.tracers.steppers.nofsteps()}}
+
+% \unexpanded\def\showotfsteps
+% {\begingroup
+% \veryraggedright
+% \forgetparindent
+% \forgeteverypar
+% \dontleavehmode\bgroup\tttf \language\minusone features: \showotfstepfeatures\egroup
+% \blank
+% \dontleavehmode\bgroup\tttf result:\egroup
+% \blank
+% \startlinecorrection
+% \ruledhbox\bgroup\box\otfcompositionbox\egroup
+% \stoplinecorrection
+% \dorecurse\otfnoffeaturesteps
+% {\blank
+% \showotfstepmessages\recurselevel
+% \blank
+% \startlinecorrection
+% \dontleavehmode\bgroup\resetallattributes\pardir TLT\textdir TLT\relax\tttf\recurselevel: \showotfstepchars\recurselevel\egroup
+% \stoplinecorrection
+% \blank
+% \startlinecorrection
+% \ruledhbox % can be mode
+% \bgroup\resetallattributes\showotfstepglyphs\recurselevel\egroup % reset is new, we don't want additional processing
+% \stoplinecorrection
+% \blank}%
+% \endgroup}
+
+\unexpanded\def\showotfsteps
+ {\begingroup
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar
+ \tt
+ \lefttoright
+ \hbox to \hsize \bgroup
+ \hbox to 6\emwidth{\bf font\hss}%
+ \vtop \bgroup
+ \hsize\dimexpr\hsize-6\emwidth\relax
+ \language\minusone
+ \bf
+ \showotfstepfont
+ \egroup
+ \egroup
+ \blank
+ \hbox to \hsize \bgroup
+ \hbox to 6\emwidth{\bf features\hss}%
+ \vtop \bgroup
+ \hsize\dimexpr\hsize-6\emwidth\relax
+ \language\minusone
+ \showotfstepfeatures
+ \egroup
+ \egroup
+ \blank
+ \scratchcounter\otfnoffeaturesteps\relax
+ \dorecurse\scratchcounter
+ {\blank
+ \begingroup
+ \advance\leftskip6\emwidth
+ \showotfstepmessages\recurselevel
+ \par
+ \endgroup
+ \blank
+ \dontleavehmode
+ \hbox to \hsize \bgroup
+ \hbox to 6\emwidth \bgroup
+ \bf
+ \ifnum\recurselevel=\scratchcounter result\else step \recurselevel\fi
+ \hss
+ \egroup
+ \vtop \bgroup
+ \hsize\dimexpr\hsize-6\emwidth\relax
+ \resetallattributes
+ \pardir TLT\textdir TLT\relax
+ \dontleavehmode
+ \ifnum\recurselevel=\scratchcounter
+ \ruledhbox{\box\otfcompositionbox}%
+ \else
+ \ruledhbox{\showotfstepglyphs\recurselevel}%
+ \fi
+ \quad
+ \showotfstepchars\recurselevel
+ \hfill
+ \par
+ \egroup
+ \egroup
+ \blank}%
+ \endgroup}
+
+\unexpanded\def\startotfsample
+ {\enabletrackers[*otf.sample]% beware, kind of global
+ \startotfcollecting
+ \begingroup
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar}
+
+\unexpanded\def\stopotfsample
+ {\endgroup
+ \stopotfcollecting
+ \disabletrackers[*otf.sample]% beware, kind of global: otf.sample
+ \showotfsteps
+ \resetotfcollecting}
+
+\newbox\otfcompositionbox
+
+% this should go in spac-ali:
+
+\installcorenamespace{otfcompositiondir}
+
+\letvalue{\??otfcompositiondir -1}\righttoleft
+\letvalue{\??otfcompositiondir r2l}\righttoleft
+\letvalue{\??otfcompositiondir l2r}\lefttoright
+\letvalue{\??otfcompositiondir +1}\lefttoright
+\letvalue{\??otfcompositiondir 1}\lefttoright
+
+\unexpanded\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text
+ {\begingroup
+ \forgetparindent
+ \forgeteverypar
+ % \setupcolors[\c!state=\v!start]%
+ \setupalign[\v!verytolerant,\v!flushleft]%
+ \startotfsample
+ \nohyphens
+ \global\setbox\otfcompositionbox\hbox{\definedfont[#1]\relax\getvalue{\??otfcompositiondir#2}\relax#3}%
+ \stopotfsample
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-trt.lua b/Master/texmf-dist/tex/context/base/mkiv/font-trt.lua
new file mode 100644
index 00000000000..abc92ba5265
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-trt.lua
@@ -0,0 +1,116 @@
+if not modules then modules = { } end modules ['font-trt'] = {
+ 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 rawget, dofile, next, type = rawget, dofile, next, type
+
+local cleanfilename = fonts.names.cleanfilename
+local splitbase = file.splitbase
+local lower = string.lower
+
+--[[ldx--
+<p>We provide a simple treatment mechanism (mostly because I want to demonstrate
+something in a manual). It's one of the few places where an lfg file gets loaded
+outside the goodies manager.</p>
+--ldx]]--
+
+local treatments = fonts.treatments or { }
+fonts.treatments = treatments
+
+local treatmentdata = treatments.data or utilities.storage.allocate()
+treatments.data = treatmentdata
+
+treatments.filename = "treatments.lfg"
+
+local trace_treatments = false trackers.register("fonts.treatments", function(v) trace_treatments = v end)
+local report_treatment = logs.reporter("fonts","treatment")
+
+treatments.report = report_treatment
+
+function treatments.trace(...)
+ if trace_treatments then
+ report_treatment(...)
+ end
+end
+
+-- function treatments.load(name)
+-- local filename = resolvers.findfile(name)
+-- if filename and filename ~= "" then
+-- local goodies = dofile(filename)
+-- if goodies then
+-- local treatments = goodies.treatments
+-- if treatments then
+-- for name, data in next, treatments do
+-- treatmentdata[name] = data -- always wins
+-- end
+-- end
+-- end
+-- end
+-- end
+
+table.setmetatableindex(treatmentdata,function(t,k)
+ local files = resolvers.findfiles(treatments.filename)
+ if files then
+ for i=1,#files do
+ local goodies = dofile(files[i])
+ if goodies then
+ local treatments = goodies.treatments
+ if treatments then
+ for name, data in next, treatments do
+ if not rawget(t,name) then
+ t[name] = data
+ end
+ end
+ end
+ end
+ end
+ end
+ table.setmetatableindex(treatmentdata,nil)
+ return treatmentdata[k]
+end)
+
+local function applyfix(fix,filename,data,n)
+ if type(fix) == "function" then
+ -- we assume that when needed the fix reports something
+ -- if trace_treatments then
+ -- report_treatment("applying treatment %a to file %a",n,filename)
+ -- end
+ fix(data)
+ elseif trace_treatments then
+ report_treatment("invalid treatment %a for file %a",n,filename)
+ end
+end
+
+function treatments.applyfixes(filename,data)
+ local filename = cleanfilename(filename)
+ local pathpart, basepart = splitbase(filename)
+ local treatment = treatmentdata[filename] or treatmentdata[basepart]
+ if treatment then
+ local fixes = treatment.fixes
+ if not fixes then
+ -- nothing to fix
+ elseif type(fixes) == "table" then
+ for i=1,#fixes do
+ applyfix(fixes[i],filename,data,i)
+ end
+ else
+ applyfix(fixes,filename,data,1)
+ end
+ end
+end
+
+function treatments.ignoredfile(fullname)
+ local treatmentdata = treatments.data or { } -- when used outside context
+ local _, basepart = splitbase(fullname)
+ local treatment = treatmentdata[basepart] or treatmentdata[lower(basepart)]
+ if treatment and treatment.ignored then
+ report_treatment("font file %a resolved as %a is ignored, reason %a",basepart,fullname,treatment.comment or "unknown")
+ return true
+ end
+end
+
+fonts.names.ignoredfile = treatments.ignoredfile
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua
new file mode 100644
index 00000000000..6df339214b2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua
@@ -0,0 +1,480 @@
+if not modules then modules = { } end modules ['font-ttf'] = {
+ 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, type, unpack = next, type, unpack
+local bittest = bit32.btest
+local sqrt = math.sqrt
+
+local report = logs.reporter("otf reader","ttf")
+
+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 function mergecomposites(glyphs,shapes)
+
+ local function merge(index,shape,components)
+ local contours = { }
+ local nofcontours = 0
+ for i=1,#components do
+ local component = components[i]
+ local subindex = component.index
+ local subshape = shapes[subindex]
+ local subcontours = subshape.contours
+ if not subcontours then
+ local subcomponents = subshape.components
+ if subcomponents then
+ subcontours = merge(subindex,subshape,subcomponents)
+ end
+ end
+ if subcontours then
+ local matrix = component.matrix
+ local xscale = matrix[1]
+ local xrotate = matrix[2]
+ local yrotate = matrix[3]
+ local yscale = matrix[4]
+ local xoffset = matrix[5]
+ local yoffset = matrix[6]
+ for i=1,#subcontours do
+ local points = subcontours[i]
+ local result = { }
+ for i=1,#points do
+ local p = points[i]
+ local x = p[1]
+ local y = p[2]
+ result[i] = {
+ xscale * x + xrotate * y + xoffset,
+ yscale * y + yrotate * x + yoffset,
+ p[3]
+ }
+ end
+ nofcontours = nofcontours + 1
+ contours[nofcontours] = result
+ end
+ else
+ report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex)
+ end
+ end
+ shape.contours = contours
+ shape.components = nil
+ return contours
+ end
+
+ for index=1,#glyphs do
+ local shape = shapes[index]
+ local components = shape.components
+ if components then
+ merge(index,shape,components)
+ end
+ end
+
+end
+
+local function readnothing(f,nofcontours)
+ return {
+ type = "nothing",
+ }
+end
+
+-- begin of converter
+
+-- make paths: the ff code is quite complex but it looks like we need to deal
+-- with all kind of on curve border cases
+
+local function curveto(m_x,m_y,l_x,l_y,r_x,r_y) -- todo: inline this
+ return {
+ l_x + 2/3 *(m_x-l_x), l_y + 2/3 *(m_y-l_y),
+ r_x + 2/3 *(m_x-r_x), r_y + 2/3 *(m_y-r_y),
+ r_x, r_y, "c" -- "curveto"
+ }
+end
+
+-- We could omit the operator which saves some 10%:
+--
+-- #2=lineto #4=quadratic #6=cubic #3=moveto (with "m")
+--
+-- For the moment we keep the original outlines but that default might change
+-- in the future. In any case, a backend should support both.
+--
+-- The code is a bit messy. I looked at the ff code but it's messy too. It has
+-- to do with the fact that we need to look at points on the curve and control
+-- points in between. This also means that we start at point 2 and have to look at
+-- point 1 when we're at the end. We still use a ps like storage with the operator
+-- last in an entry. It's typical code that evolves stepwise till a point of no
+-- comprehension.
+
+local function contours2outlines(glyphs,shapes)
+ local quadratic = true
+ -- local quadratic = false
+ for index=1,#glyphs do
+ local glyph = glyphs[index]
+ local shape = shapes[index]
+ local contours = shape.contours
+ if contours then
+ local nofcontours = #contours
+ local segments = { }
+ local nofsegments = 0
+ glyph.segments = segments
+ if nofcontours > 0 then
+ for i=1,nofcontours do
+ local contour = contours[i]
+ local nofcontour = #contour
+ if nofcontour > 0 then
+ local first_pt = contour[1]
+ local first_on = first_pt[3]
+ -- todo no new tables but reuse lineto and quadratic
+ if nofcontour == 1 then
+ -- this can influence the boundingbox
+ first_pt[3] = "m" -- "moveto"
+ nofsegments = nofsegments + 1
+ segments[nofsegments] = first_pt
+ else -- maybe also treat n == 2 special
+ local first_on = first_pt[3]
+ local last_pt = contour[nofcontour]
+ local last_on = last_pt[3]
+ local start = 1
+ local control_pt = false
+ if first_on then
+ start = 2
+ else
+ if last_on then
+ first_pt = last_pt
+ else
+ first_pt = { (first_pt[1]+last_pt[1])/2, (first_pt[2]+last_pt[2])/2, false }
+ end
+ control_pt = first_pt
+ end
+ nofsegments = nofsegments + 1
+ segments[nofsegments] = { first_pt[1], first_pt[2], "m" } -- "moveto"
+ local previous_pt = first_pt
+ for i=start,nofcontour do
+ local current_pt = contour[i]
+ local current_on = current_pt[3]
+ local previous_on = previous_pt[3]
+ if previous_on then
+ if current_on then
+ -- both normal points
+ nofsegments = nofsegments + 1
+ segments[nofsegments] = { current_pt[1], current_pt[2], "l" } -- "lineto"
+ else
+ control_pt = current_pt
+ end
+ elseif current_on then
+ local ps = segments[nofsegments]
+ nofsegments = nofsegments + 1
+ if quadratic then
+ segments[nofsegments] = { control_pt[1], control_pt[2], current_pt[1], current_pt[2], "q" } -- "quadraticto"
+ else
+ local p = segments[nofsegments-1] local n = #p
+ segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],current_pt[1],current_pt[2])
+ end
+ control_pt = false
+ else
+ nofsegments = nofsegments + 1
+ local halfway_x = (previous_pt[1]+current_pt[1])/2
+ local halfway_y = (previous_pt[2]+current_pt[2])/2
+ if quadratic then
+ segments[nofsegments] = { control_pt[1], control_pt[2], halfway_x, halfway_y, "q" } -- "quadraticto"
+ else
+ local p = segments[nofsegments-1] local n = #p
+ segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],halfway_x,halfway_y)
+ end
+ control_pt = current_pt
+ end
+ previous_pt = current_pt
+ end
+ if first_pt == last_pt then
+ -- we're already done, probably a simple curve
+ else
+ nofsegments = nofsegments + 1
+ if not control_pt then
+ segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto"
+ elseif quadratic then
+ segments[nofsegments] = { control_pt[1], control_pt[2], first_pt[1], first_pt[2], "q" } -- "quadraticto"
+ else
+ local p = last_pt local n = #p
+ segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],first_pt[1],first_pt[2])
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- end of converter
+
+local function readglyph(f,nofcontours)
+ local points = { }
+ local endpoints = { }
+ local instructions = { }
+ local flags = { }
+ for i=1,nofcontours do
+ endpoints[i] = readshort(f) + 1
+ end
+ local nofpoints = endpoints[nofcontours]
+ local nofinstructions = readushort(f)
+-- f:seek("set",f:seek()+nofinstructions)
+ skipbytes(f,nofinstructions)
+ -- because flags can repeat we don't know the amount ... in fact this is
+ -- not that efficient (small files but more mem)
+ local i = 1
+ while i <= nofpoints do
+ local flag = readbyte(f)
+ flags[i] = flag
+ if bittest(flag,0x0008) then
+ for j=1,readbyte(f) do
+ i = i + 1
+ flags[i] = flag
+ end
+ end
+ i = i + 1
+ end
+ -- first come the x coordinates, and next the y coordinates and they
+ -- can be repeated
+ local x = 0
+ for i=1,nofpoints do
+ local flag = flags[i]
+ local short = bittest(flag,0x0002)
+ local same = bittest(flag,0x0010)
+ if short then
+ if same then
+ x = x + readbyte(f)
+ else
+ x = x - readbyte(f)
+ end
+ elseif same then
+ -- copy
+ else
+ x = x + readshort(f)
+ end
+ points[i] = { x, y, bittest(flag,0x0001) }
+ end
+ local y = 0
+ for i=1,nofpoints do
+ local flag = flags[i]
+ local short = bittest(flag,0x0004)
+ local same = bittest(flag,0x0020)
+ if short then
+ if same then
+ y = y + readbyte(f)
+ else
+ y = y - readbyte(f)
+ end
+ elseif same then
+ -- copy
+ else
+ y = y + readshort(f)
+ end
+ points[i][2] = y
+ end
+ -- we could integrate this if needed
+ local first = 1
+ for i=1,#endpoints do
+ local last = endpoints[i]
+ endpoints[i] = { unpack(points,first,last) }
+ first = last + 1
+ end
+ return {
+ type = "glyph",
+ -- points = points,
+ contours = endpoints,
+ }
+end
+
+local function readcomposite(f)
+ local components = { }
+ local nofcomponents = 0
+ local instructions = false
+ while true do
+ local flags = readushort(f)
+ local index = readushort(f)
+ ----- f_words = bittest(flags,0x0001)
+ local f_xyarg = bittest(flags,0x0002)
+ ----- f_round = bittest(flags,0x0004+0x0002)
+ ----- f_scale = bittest(flags,0x0008)
+ ----- f_reserved = bittest(flags,0x0010)
+ ----- f_more = bittest(flags,0x0020)
+ ----- f_xyscale = bittest(flags,0x0040)
+ ----- f_matrix = bittest(flags,0x0080)
+ ----- f_instruct = bittest(flags,0x0100)
+ ----- f_usemine = bittest(flags,0x0200)
+ ----- f_overlap = bittest(flags,0x0400)
+ local f_offset = bittest(flags,0x0800)
+ ----- f_uoffset = bittest(flags,0x1000)
+ local xscale = 1
+ local xrotate = 0
+ local yrotate = 0
+ local yscale = 1
+ local xoffset = 0
+ local yoffset = 0
+ local base = false
+ local reference = false
+ if f_xyarg then
+ if bittest(flags,0x0001) then -- f_words
+ xoffset = readshort(f)
+ yoffset = readshort(f)
+ else
+ xoffset = readchar(f) -- signed byte, stupid name
+ yoffset = readchar(f) -- signed byte, stupid name
+ end
+ else
+ if bittest(flags,0x0001) then -- f_words
+ base = readshort(f)
+ reference = readshort(f)
+ else
+ base = readchar(f) -- signed byte, stupid name
+ reference = readchar(f) -- signed byte, stupid name
+ end
+ end
+ if bittest(flags,0x0008) then -- f_scale
+ xscale = read2dot14(f)
+ yscale = xscale
+ if f_xyarg and f_offset then
+ xoffset = xoffset * xscale
+ yoffset = yoffset * yscale
+ end
+ elseif bittest(flags,0x0040) then -- f_xyscale
+ xscale = read2dot14(f)
+ yscale = read2dot14(f)
+ if f_xyarg and f_offset then
+ xoffset = xoffset * xscale
+ yoffset = yoffset * yscale
+ end
+ elseif bittest(flags,0x0080) then -- f_matrix
+ xscale = read2dot14(f)
+ xrotate = read2dot14(f)
+ yrotate = read2dot14(f)
+ yscale = read2dot14(f)
+ if f_xyarg and f_offset then
+ xoffset = xoffset * sqrt(xscale ^2 + xrotate^2)
+ yoffset = yoffset * sqrt(yrotate^2 + yscale ^2)
+ end
+ end
+ nofcomponents = nofcomponents + 1
+ components[nofcomponents] = {
+ index = index,
+ usemine = bittest(flags,0x0200), -- f_usemine
+ round = bittest(flags,0x0006), -- f_round,
+ base = base,
+ reference = reference,
+ matrix = { xscale, xrotate, yrotate, yscale, xoffset, yoffset },
+ }
+ if bittest(flags,0x0100) then
+ instructions = true
+ end
+ if not bittest(flags,0x0020) then -- f_more
+ break
+ end
+ end
+ return {
+ type = "composite",
+ components = components,
+ }
+end
+
+-- function readers.cff(f,offset,glyphs,doshapes) -- false == no shapes (nil or true otherwise)
+
+-- The glyf table depends on the loca table. We have one entry to much
+-- in the locations table (the last one is a dummy) because we need to
+-- calculate the size of a glyph blob from the delta, although we not
+-- need it in our usage (yet). We can remove the locations table when
+-- we're done (todo: cleanup finalizer).
+
+function readers.loca(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.loca
+ if datatable then
+ -- locations are relative to the glypdata table (glyf)
+ local offset = fontdata.tables.glyf.offset
+ local format = fontdata.fontheader.indextolocformat
+ local locations = { }
+ setposition(f,datatable.offset)
+ if format == 1 then
+ local nofglyphs = datatable.length/4 - 1
+ -1
+ for i=0,nofglyphs do
+ locations[i] = offset + readulong(f)
+ end
+ fontdata.nofglyphs = nofglyphs
+ else
+ local nofglyphs = datatable.length/2 - 1
+ -1
+ for i=0,nofglyphs do
+ locations[i] = offset + readushort(f) * 2
+ end
+ fontdata.nofglyphs = nofglyphs
+ end
+ fontdata.locations = locations
+ end
+ end
+end
+
+function readers.glyf(f,fontdata,specification) -- part goes to cff module
+ if specification.glyphs then
+ local datatable = fontdata.tables.glyf
+ if datatable then
+ local locations = fontdata.locations
+ if locations then
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local filesize = fontdata.filesize
+ local nothing = { 0, 0, 0, 0 }
+ local shapes = { }
+ local loadshapes = specification.shapes
+ for index=0,nofglyphs do
+ local location = locations[index]
+ 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
+ setposition(f,location)
+ local nofcontours = readshort(f)
+ glyphs[index].boundingbox = {
+ readshort(f), -- xmin
+ readshort(f), -- ymin
+ readshort(f), -- xmax
+ readshort(f), -- ymax
+ }
+ if not loadshapes then
+ -- save space
+ elseif nofcontours == 0 then
+ shapes[index] = readnothing(f,nofcontours)
+ elseif nofcontours > 0 then
+ shapes[index] = readglyph(f,nofcontours)
+ else
+ shapes[index] = readcomposite(f,nofcontours)
+ end
+ else
+ if loadshapes then
+ shapes[index] = { }
+ end
+ glyphs[index].boundingbox = nothing
+ end
+ end
+ if loadshapes then
+ mergecomposites(glyphs,shapes)
+ contours2outlines(glyphs,shapes)
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-uni.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-uni.mkiv
new file mode 100644
index 00000000000..91a488ff205
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-uni.mkiv
@@ -0,0 +1,27 @@
+%D \module
+%D [ file=font-uni,
+%D version=2008.11.03, % 1999.10.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=\UNICODE,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Unicode}
+
+%D In \MKIV\ we only provide the \type {\uchar} macro and implement it as just
+%D an \UTF\ converter. We expand it so best not use not use it for active
+%D characters. In practice this command is probably never used anyway but we keep
+%D if for old styles.
+
+\unprotect
+
+\def\uchar#1#2{\clf_uchar\numexpr#1\relax\numexpr#2\relax}
+
+\let\uc\uchar
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-unk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-unk.mkiv
new file mode 100644
index 00000000000..988e5df3d3c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-unk.mkiv
@@ -0,0 +1,150 @@
+%D \module
+%D [ file=font-unk,
+%D version=1998.09.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Unknown Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is rather important, because it enables us to
+%D define and call for not yet defined fonts in a way
+%D completely independant of real font names. First we map
+%D some meaningful names onto unknown filenames.
+
+\unprotect
+
+\definefontsynonym [Serif] [unknown]
+\definefontsynonym [SerifBold] [unknown]
+\definefontsynonym [SerifItalic] [unknown]
+\definefontsynonym [SerifSlanted] [unknown]
+\definefontsynonym [SerifBoldItalic] [unknown]
+\definefontsynonym [SerifBoldSlanted] [unknown]
+\definefontsynonym [SerifCaps] [unknown]
+
+\definefontsynonym [Sans] [unknown]
+\definefontsynonym [SansBold] [unknown]
+\definefontsynonym [SansItalic] [unknown]
+\definefontsynonym [SansSlanted] [unknown]
+\definefontsynonym [SansBoldItalic] [unknown]
+\definefontsynonym [SansBoldSlanted] [unknown]
+\definefontsynonym [SansCaps] [unknown]
+
+\definefontsynonym [Mono] [unknown]
+\definefontsynonym [MonoBold] [unknown]
+\definefontsynonym [MonoItalic] [unknown]
+\definefontsynonym [MonoSlanted] [unknown]
+\definefontsynonym [MonoBoldItalic] [unknown]
+\definefontsynonym [MonoBoldSlanted] [unknown]
+\definefontsynonym [MonoCaps] [unknown]
+
+\definefontsynonym [MathRoman] [unknown]
+\definefontsynonym [MathRomanL2R] [MathRoman]
+\definefontsynonym [MathRomanR2L] [MathRoman]
+\definefontsynonym [MathRomanBold] [MathRoman]
+\definefontsynonym [MathRomanBoldL2R] [MathRomanBold]
+\definefontsynonym [MathRomanBoldR2L] [MathRomanBold]
+
+\definefontsynonym [Handwriting] [unknown]
+\definefontsynonym [Calligraphic] [unknown]
+
+%D This permit us to define (use) fonts that refer to the default
+%D style (so, Bold may expand to SansBold or SerifBold, depending
+%D on the default style in the typeface).
+
+\definefontsynonym[\s!Normal] [\noexpand\v_font_string_d]
+\definefontsynonym[\s!Bold] [\noexpand\v_font_string_d\noexpand\s!Bold]
+\definefontsynonym[\s!Italic] [\noexpand\v_font_string_d\noexpand\s!Italic]
+\definefontsynonym[\s!Slanted] [\noexpand\v_font_string_d\noexpand\s!Slanted]
+\definefontsynonym[\s!BoldItalic] [\noexpand\v_font_string_d\noexpand\s!BoldItalic]
+\definefontsynonym[\s!BoldSlanted][\noexpand\v_font_string_d\noexpand\s!BoldSlanted]
+\definefontsynonym[\s!Caps] [\noexpand\v_font_string_d\noexpand\s!Caps]
+
+%D Also handy:
+
+\definefontsynonym [Regular] [Serif]
+\definefontsynonym [RegularBold] [SerifBold]
+\definefontsynonym [RegularItalic] [SerifItalic]
+\definefontsynonym [RegularSlanted] [SerifSlanted]
+\definefontsynonym [RegularBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RegularBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RegularCaps] [SerifCaps]
+
+\definefontsynonym [Support] [Sans]
+\definefontsynonym [SupportBold] [SansBold]
+\definefontsynonym [SupportItalic] [SansItalic]
+\definefontsynonym [SupportSlanted] [SansSlanted]
+\definefontsynonym [SupportBoldItalic] [SansBoldItalic]
+\definefontsynonym [SupportBoldSlanted] [SansBoldSlanted]
+\definefontsynonym [SupportCaps] [SansCaps]
+
+%D Well, not that good an idea:
+
+\definefontsynonym [Roman] [Serif]
+\definefontsynonym [RomanBold] [SerifBold]
+\definefontsynonym [RomanItalic] [SerifItalic]
+\definefontsynonym [RomanSlanted] [SerifSlanted]
+\definefontsynonym [RomanBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RomanBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RomanCaps] [SerifCaps]
+
+\definefontsynonym [Type] [Mono]
+\definefontsynonym [TypeBold] [MonoBold]
+\definefontsynonym [TypeItalic] [MonoItalic]
+\definefontsynonym [TypeSlanted] [MonoSlanted]
+\definefontsynonym [TypeBoldItalic] [MonoBoldItalic]
+\definefontsynonym [TypeBoldSlanted] [MonoBoldSlanted]
+\definefontsynonym [TypeCaps] [MonoCaps]
+
+%D Next we define roman, sans and monospaced font sets.
+
+\definebodyfont [default] [rm]
+ [\s!tf=Serif sa 1,
+ \s!bf=SerifBold sa 1,
+ \s!it=SerifItalic sa 1,
+ \s!sl=SerifSlanted sa 1,
+ \s!bi=SerifBoldItalic sa 1,
+ \s!bs=SerifBoldSlanted sa 1,
+ \s!sc=SerifCaps sa 1]
+
+\definebodyfont [default] [ss]
+ [\s!tf=Sans sa 1,
+ \s!bf=SansBold sa 1,
+ \s!it=SansItalic sa 1,
+ \s!sl=SansSlanted sa 1,
+ \s!bi=SansBoldItalic sa 1,
+ \s!bs=SansBoldSlanted sa 1,
+ \s!sc=SansCaps sa 1]
+
+\definebodyfont [default] [tt]
+ [\s!tf=Mono sa 1,
+ \s!bf=MonoBold sa 1,
+ \s!it=MonoItalic sa 1,
+ \s!sl=MonoSlanted sa 1,
+ \s!bi=MonoBoldItalic sa 1,
+ \s!bs=MonoBoldSlanted sa 1,
+ \s!sc=MonoCaps sa 1]
+
+\definebodyfont [default] [mm]
+ [\s!mr =MathRoman mo 1,
+ \s!mrlr=MathRomanL2R mo 1,
+ \s!mrrl=MathRomanR2L mo 1,
+ \s!mb =MathRomanBold mo 1,
+ \s!mblr=MathRomanBoldL2R mo 1,
+ \s!mbrl=MathRomanBoldR2L mo 1]
+
+\definebodyfont [default] [hw]
+ [\s!tf=Handwriting sa 1]
+
+\definebodyfont [default] [cg]
+ [\s!tf=Calligraphy sa 1]
+
+%D These definitions come into action as soon as names are
+%D mapped onto real file names (or names that themselves are
+%D mapped).
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi
new file mode 100644
index 00000000000..fb60b711cef
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi
@@ -0,0 +1,56 @@
+%D \module
+%D [ file=font-var,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Common Variables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Common Variables}
+
+\unprotect
+
+% some more will move here
+
+%D \macros
+%D {fontstyle,fontalternative,fontsize,fontbody}
+%D
+%D Within a bodyfont, fonts can come in different sizes. For instance
+%D \type {\tf} is accompanied by \type {\tfa}, \type {\tfb} etc. The
+%D first two characters denote the alternative, while the third
+%D character in these sequences represents the size. The actual size
+%D is saved in a macro. The styles, being roman (\type {\rm}), sans
+%D serif (\type {\ss}) etc. are also available in macros in \type {rm},
+%D \type {ss} etc. form.
+
+% fontclass % modern dejavu
+% fontbody % ... 10pt 11pt 12pt ...
+% fontstyle % rm ss tt mm hw cg ...
+% fontalternative % tf bf sl it bs bi sc ...
+% fontsize % a b c d ...
+% fontface % 0=normal 1=text 2=script 3=scriptscript 4=x 5=xx (math are temporary)
+
+\def\normalizedbodyfontsize{12pt}
+
+\def\defaultfontbody {\normalizedbodyfontsize}
+\let\defaultfontstyle \empty
+\let\defaultfontalternative \s!tf
+\let\defaultfontsize \empty
+
+\let\globalfontclass \empty
+\let\fontclass \empty
+\let\fontbody \defaultfontbody
+\let\fontstyle \defaultfontstyle
+\let\fontalternative \defaultfontalternative
+\let\fontsize \defaultfontsize
+\let\fontface \!!zerocount
+
+% 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 ...
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-vf.lua b/Master/texmf-dist/tex/context/base/mkiv/font-vf.lua
new file mode 100644
index 00000000000..7037c6c8be6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-vf.lua
@@ -0,0 +1,206 @@
+if not modules then modules = { } end modules ['font-vf'] = {
+ 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"
+}
+
+--[[ldx--
+<p>This is very experimental code! Not yet adapted to recent changes. This will change.</p>
+--ldx]]--
+
+-- present in the backend but unspecified:
+--
+-- 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 allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local fastcopy = table.fastcopy
+
+local fonts = fonts
+local constructors = fonts.constructors
+local vf = constructors.newhandler("vf")
+vf.version = 1.000 -- same as tfm
+
+--[[ldx--
+<p>We overload the <l n='vf'/> reader.</p>
+--ldx]]--
+
+-- general code / already frozen
+--
+-- function vf.find(name)
+-- name = file.removesuffix(file.basename(name))
+-- if constructors.resolvevirtualtoo then
+-- local format = fonts.loggers.format(name)
+-- if format == 'tfm' or format == 'ofm' then
+-- if trace_defining then
+-- report_defining("locating vf for %a",name)
+-- end
+-- return findbinfile(name,"ovf") or ""
+-- else
+-- if trace_defining then
+-- report_defining("vf for %a is already taken care of",name)
+-- end
+-- return ""
+-- end
+-- else
+-- if trace_defining then
+-- report_defining("locating vf for %a",name)
+-- end
+-- return findbinfile(name,"ovf") or ""
+-- end
+-- end
+--
+-- callbacks.register('find_vf_file', vf.find, "locating virtual fonts, insofar needed") -- not that relevant any more
+
+-- specific code (will move to other module)
+
+local definers = fonts.definers
+local methods = definers.methods
+
+local variants = allocate()
+local combinations = { }
+local combiner = { }
+local whatever = allocate()
+local helpers = allocate()
+local predefined = allocate {
+ dummy = { "comment" },
+ push = { "push" },
+ pop = { "pop" },
+}
+
+methods.variants = variants -- todo .. wrong namespace
+vf.combinations = combinations
+vf.combiner = combiner
+vf.whatever = whatever
+vf.helpers = helpers
+vf.predefined = predefined
+
+setmetatableindex(whatever, function(t,k) local v = { } t[k] = v return v end)
+
+local function checkparameters(g,f)
+ if f and g and not g.parameters and #g.fonts > 0 then
+ local p = { }
+ for k,v in next, f.parameters do
+ p[k] = v
+ end
+ g.parameters = p
+ setmetatable(p, getmetatable(f.parameters))
+ end
+end
+
+function methods.install(tag, rules)
+ vf.combinations[tag] = rules
+ variants[tag] = function(specification)
+ return vf.combine(specification,tag)
+ end
+end
+
+local function combine_load(g,name)
+ return constructors.readanddefine(name or g.specification.name,g.specification.size)
+end
+
+local function combine_assign(g, name, from, to, start, force)
+ local f, id = combine_load(g,name)
+ if f and id then
+ -- optimize for whole range, then just g = f
+ 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 hn = #g.fonts+1
+ g.fonts[hn] = { id = id } -- no need to be sparse
+ for i=from,to do
+ if fc[i] and (force or not gc[i]) then
+ gc[i] = fastcopy(fc[i],true) -- can be optimized
+ gc[i].commands = { { 'slot', hn, start } }
+ gd[i] = fd[i]
+ end
+ start = start + 1
+ end
+ checkparameters(g,f)
+ end
+end
+
+local function combine_process(g,list)
+ if list then
+ for _,v in next, list do
+ (combiner.commands[v[1]] or nop)(g,v)
+ end
+ end
+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
+ g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse
+ local hn = #g.fonts
+ for k, v in next, fc do
+ if force or not gc[k] then
+ gc[k] = fastcopy(v,true)
+ gc[k].commands = { { 'slot', hn, k } }
+ gd[i] = fd[i]
+ end
+ end
+ checkparameters(g,f)
+ end
+end
+
+local combine_feature = function(g,v)
+ local key, value = v[2], v[3]
+ if key then
+ if value == nil then
+ value = true
+ end
+ local specification = g.specification
+ if specification then
+ local normalfeatures = specification.features.normal
+ if normalfeatures then
+ normalfeatures[key] = value -- otf?
+ end
+ end
+ end
+end
+
+--~ combiner.load = combine_load
+--~ combiner.assign = combine_assign
+--~ combiner.process = combine_process
+--~ combiner.names = combine_names
+--~ combiner.feature = combine_feature
+
+combiner.commands = allocate {
+ ["initialize"] = function(g,v) combine_assign (g,g.properties.name) end,
+ ["include-method"] = function(g,v) combine_process (g,combinations[v[2]]) end, -- name
+ -- ["copy-parameters"] = function(g,v) combine_parameters(g,v[2]) end, -- name
+ ["copy-range"] = function(g,v) combine_assign (g,v[2],v[3],v[4],v[5],true) end, -- name, from-start, from-end, to-start
+ ["copy-char"] = function(g,v) combine_assign (g,v[2],v[3],v[3],v[4],true) end, -- name, from, to
+ ["fallback-range"] = function(g,v) combine_assign (g,v[2],v[3],v[4],v[5],false) end, -- name, from-start, from-end, to-start
+ ["fallback-char"] = function(g,v) combine_assign (g,v[2],v[3],v[3],v[4],false) end, -- name, from, to
+ ["copy-names"] = function(g,v) combine_names (g,v[2],true) end,
+ ["fallback-names"] = function(g,v) combine_names (g,v[2],false) end,
+ ["feature"] = combine_feature,
+}
+
+function vf.combine(specification,tag)
+ local g = {
+ name = specification.name,
+ properties = {
+ virtualized = true,
+ },
+ fonts = {
+ },
+ characters = {
+ },
+ descriptions = {
+ },
+ specification = fastcopy(specification),
+ }
+ combine_process(g,combinations[tag])
+ return g
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua b/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua
new file mode 100644
index 00000000000..494ac00a928
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua
@@ -0,0 +1,97 @@
+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/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua
new file mode 100644
index 00000000000..17f04d593da
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua
@@ -0,0 +1,34 @@
+if not modules then modules = { } end modules ['grph-epd'] = {
+ version = 1.001,
+ comment = "companion to grph-epd.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local variables = interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+-- todo: page, name, file, url
+
+local codeinjections = backends.codeinjections
+
+function figures.mergegoodies(optionlist)
+ local options = settings_to_hash(optionlist)
+ local all = options[variables.all] or options[variables.yes]
+ if all or options[variables.reference] then
+ codeinjections.mergereferences()
+ end
+ if all or options[variables.layer] then
+ codeinjections.mergeviewerlayers()
+ end
+ if all or options[variables.bookmark] then
+ codeinjections.mergebookmarks()
+ end
+end
+
+interfaces.implement {
+ name = "figure_mergegoodies",
+ actions = figures.mergegoodies,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-epd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.mkiv
new file mode 100644
index 00000000000..8152772aa48
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=grph-epd,
+%D version=2010.07.29,
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Merging Goodies,
+%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 Graphic Macros / Merging Goodies}
+
+\unprotect
+
+\registerctxluafile{grph-epd}{1.001}
+
+\def\figurereference{\clf_figurestatus{reference}{}} % might become private
+
+\defineoverlay[system:graphics:epdf][\directsetup{system:graphics:epdf}]
+
+\startsetups system:graphics:epdf
+ \clf_figure_mergegoodies{\externalfigureparameter\c!interaction}%
+ \reference[\figurereference]{}% todo: dest area
+\stopsetups
+
+\defineframed
+ [system_graphics_epdf]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!background={\v!foreground,system:graphics:epdf}]
+
+\unexpanded\def\grph_epdf_add_overlay
+ {\global\setbox\foundexternalfigure\vbox\bgroup % vpack ?
+ \system_graphics_epdf{\box\foundexternalfigure}%
+ \egroup}
+
+\appendtoks
+ \iflocation
+ \doif\figurefiletype{pdf}{\doifnot{\externalfigureparameter\c!interaction}\v!none\grph_epdf_add_overlay}%
+ \fi
+\to \externalfigurepostprocessors
+
+\protect \endinput
+
+% /Properties << /xxxx 22 0 R >>
+% 21 0 obj << /Type /OCG /Name (xxxx) >> endobj
+% 22 0 obj << /OCGs [ 21 0 R ] /Type /OCMD >> endobj
+
+% \def\setepdflayer#1#2#3#4#5#6% x y w h (in bp) 0/1 destination
+% {\setlayer
+% [epdflinks]
+% [\c!x=#1bp,\c!y=#1\s!bp,\c!preset=\v!leftbottom]
+% {\button
+% [\c!width=#3\s!bp,\c!height=#4\s!bp,\c!offset=\v!overlay,\c!frame=\ifnum#5=1 on\else\v!off]%
+% {}[#6]}}
+
+% \def\setepdflayer#1#2#3#4#5#6% x y w h (in bp) 0/1 destination
+% {\setlayer
+% [epdflinks]
+% [\c!x=#1bp,\c!y=#1\s!bp,\c!preset=\v!leftbottom]
+% {\gotowdhtbox{#3\s!bp}{#4\s!bp}[#6]}}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-fig.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-fig.mkiv
new file mode 100644
index 00000000000..80b094d83fa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-fig.mkiv
@@ -0,0 +1,391 @@
+%D \module
+%D [ file=grph-fig,
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure 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.
+
+\unprotect
+
+%D Used in the styledesign manual:
+%
+% beware in mkiv we don't have the typeset- prefix
+%
+% \setbuffer[typeset-b]\endbuffer
+% \setbuffer[typeset-a]\endbuffer
+%
+% todo:
+%
+% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext
+% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext
+
+% we could use \typesetbuffer[*] to access the last one
+
+\newconstant\c_grph_buffers_mode
+
+\let\lasttypesetbuffer\empty
+
+\unexpanded\def\typesetbuffer
+ {\bgroup
+ \setconstant\c_grph_buffers_mode\plusone
+ \dodoubleempty\grph_buffers_typeset}
+
+\unexpanded\def\typesetbufferonly
+ {\bgroup
+ \setconstant\c_grph_buffers_mode\zerocount
+ \dodoubleempty\grph_buffers_typeset}
+
+\def\grph_buffers_typeset[#1][#2]% beware: this will mix up the mp graphics
+ {\ifsecondargument
+ \grph_buffers_typeset_indeed[#1][#2]%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\grph_buffers_typeset_indeed[\jobname][#1]}%
+ {\grph_buffers_typeset_indeed[#1][]}%
+ \else
+ \grph_buffers_typeset_indeed[\jobname][]
+ \fi\fi}
+
+\def\grph_buffers_typeset_indeed[#1][#2]% we could use the via files
+ {\doifnot{#1}{*}{\xdef\lasttypesetbuffer{\clf_runbuffer{#1}}}%
+ \ifcase\c_grph_buffers_mode
+ % typesetonly
+ \or
+ \externalfigure[\lasttypesetbuffer][#2]%
+ \fi
+ \egroup}
+
+% For manuals and such:
+%
+% \definetypesetting [name] [options] [settings-a]
+%
+% \typesetfile [name] [file] [settings-b]
+% \typesetfile [file] [options] [settings-b]
+% \typesetfile [file] [settings-b]
+% \typesetfile [file]
+%
+% \enabletrackers[files.run]
+% \starttext
+% \typesetfile[oepsoeps.tex][width=10cm,frame=on]
+% \stoptext
+
+\installcorenamespace{typesettingfile}
+
+\unexpanded\def\definetypesetting{\dotripleempty\grph_typesetting_define}
+\unexpanded\def\typesetfile {\dotripleempty\grph_typesetting_process}
+
+\def\grph_typesetting_define[#1][#2][#3]% <name> options settings-a
+ {\doifsomething{#1}{\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}}}
+
+\def\grph_typesetting_process[#1][#2][#3]% <name> filename settings-b | filename options settings
+ {\ifcsname\??typesettingfile#1\endcsname
+ \lastnamedcs{#2}{#3}%
+ \else\ifthirdargument % filename options settings
+ \grph_typesetting_process_indeed{#2}{#3}{#1}{}%
+ \else\ifsecondargument % filename settings
+ \grph_typesetting_process_indeed{}{#2}{#1}{}%
+ \fi\fi\fi}
+
+\def\grph_typesetting_process_indeed#1#2#3#4% options settings-a filename settings-b
+ {\begingroup
+ \edef\m_typesetting_name{\clf_runcontextjob{#3}{#1}}%
+ \ifx\m_typesetting_name\empty \else
+ \expanded{\externalfigure[\m_typesetting_name]}[#2,#4]%
+ \fi
+ \endgroup}
+
+%D Whatever ... hardly used ... but historic ... needs checking ...
+%D will probably become m-fig-nn.mkiv .. or I will extend it cq. clean
+%D it up when I needed it. After all, it's documented in old manuals.
+
+\newcount\c_grph_steps_reference
+\newdimen\d_grph_steps_x
+\newdimen\d_grph_steps_y
+\newbox \b_grph_steps_colorbar
+
+\let\placestopfigure\relax
+
+\unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
+ {\hpack
+ {\setbox\scratchbox\hpack
+ {\useexternalfigure[\s!dummy][#2][#3,#5]%
+ \externalfigure[\s!dummy]}%
+ \grph_steps_calculate
+ \startpositioning
+ \let\referring\grph_steps_one_referring
+ \let\marking \grph_steps_one_marking
+ \let\remark \grph_steps_one_remark
+ \let\colorbar \grph_steps_one_colorbar
+ \position(0,0){\box\scratchbox}%
+ \linewidth\onepoint
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\d_grph_steps_x,
+ \c!yscale=\withoutpt\the\d_grph_steps_y,
+ \c!factor=1]%
+ \ignorespaces#4%
+ \let\referring\grph_steps_two_referring
+ \let\marking \grph_steps_two_marking
+ \let\remark \grph_steps_two_remark
+ \let\colorbar \grph_steps_two_colorbar
+ \ignorespaces#4%
+ \stoppositioning
+ \ifvoid\b_grph_steps_colorbar\else\box\b_grph_steps_colorbar\fi}} % not really needed
+
+\unexpanded\def\grph_steps_one_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {\position(#1,#2){\grph_steps_goto(#4,#5){\externalfigureparameter\c!frames}[#7]}}
+
+\unexpanded\def\grph_steps_one_marking(#1,#2)#3(#4,#5)#6[#7]%
+ {\position(#1,#2){\grph_steps_this_is(#4,#5){\externalfigureparameter\c!frames}[#7]}}
+
+\unexpanded\def\grph_steps_one_remark(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst}
+ {\def\grph_steps_no_comment_indeed[##1]##2{}%
+ \dosingleempty\grph_steps_no_comment_indeed}
+
+\unexpanded\def\grph_steps_one_colorbar#1[#2]%
+ {}
+
+\unexpanded\def\grph_steps_two_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {}
+
+\let\grph_steps_two_marking\grph_steps_two_referring
+
+\unexpanded\def\grph_steps_two_remark
+ {\grph_steps_comment\v!no}
+
+\unexpanded\def\grph_steps_two_colorbar#1[#2]
+ {\begingroup
+ \global\setbox\b_grph_steps_colorbar\vpack % \vbox ?
+ {\forgetall
+ \processcommalist[#2]\grph_colorbar_make_step}%
+ \global\setbox\b_grph_steps_colorbar\vpack
+ {\hskip2\emwidth\box\b_grph_steps_colorbar}%
+ \global\wd\b_grph_steps_colorbar\zeropoint
+ \endgroup}
+
+\unexpanded\def\grph_colorbar_make_step#1%
+ {\blackrule[\c!color=#1,\c!width=2\emwidth,\c!height=\exheight,\c!depth=\zeropoint]%
+ \endgraf}
+
+\unexpanded\def\startfigure % could be done nicer
+ {\grabuntil{\e!stop\v!figure}\grph_steps_figure_process}
+
+\let\stopfigure\relax
+
+\def\grph_steps_figure_process#1%
+ {\dotripleargument\grph_steps_figure_process_indeed#1\stopfigure}
+
+\def\grph_steps_figure_process_indeed[#1][#2][#3]#4\stopfigure
+ {\doifelse{\externalfigureparameter\c!option}\v!test
+ {\teststartfigure[#1][#2][#3]#4\teststopfigure
+ \letexternalfigureparameter\c!frames\v!on}
+ {\letexternalfigureparameter\c!frames\v!off}%
+ \setvalue{\??externalfigureinstance#1}%
+ {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}}
+
+\let\teststopfigure\relax
+
+\unexpanded\def\teststartfigure[#1][#2][#3]#4\teststopfigure
+ {\begingroup
+ \setbox\scratchbox\hpack
+ {\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]%
+ \externalfigure[\s!dummy]}%
+ \let\referring\grph_steps_three_referring
+ \let\marking \grph_steps_three_marking
+ \let\remark \grph_steps_three_remark
+ \let\colorbar \grph_steps_three_colorbar
+ \c_grph_steps_reference\zerocount
+ \setbox0\vpack
+ {\hsize240\points
+ \startpositioning
+ \grph_steps_calculate
+ \position(0,0)
+ {\box\scratchbox}%
+ \position(0,0)
+ {\basegrid
+ [\c!nx=\externalfigureparameter\c!xmax,
+ \c!dx=\withoutpt\the\d_grph_steps_x,
+ \c!ny=\externalfigureparameter\c!ymax,
+ \c!dy=\withoutpt\the\d_grph_steps_y,
+ \c!xstep=1,
+ \c!ystep=1,
+ \c!scale=1,
+ \c!offset=\v!no,
+ \c!unit=pt]}%
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\d_grph_steps_x,
+ \c!yscale=\withoutpt\the\d_grph_steps_y,
+ \c!factor=1]%
+ \linewidth\onepoint
+ \ignorespaces#4\relax
+ \stoppositioning
+ \vfill}%
+ \c_grph_steps_reference\zerocount
+ \let\referring\grph_steps_four_referring
+ \let\marking \grph_steps_four_marking
+ \let\remark \grph_steps_four_remark
+ \let\colorbar \grph_steps_four_colorbar
+ \setbox2\vbox % \vpack ?
+ {{\tfa\doifelsenothing{#1}{#2}{#1}}
+ \blank
+ \tfxx#4
+ \vfilll}%
+ \ifdim\ht0>\ht2
+ \ht2\ht0
+ \else
+ \ht0\ht2
+ \fi
+ \hpack
+ {\hskip3\emwidth
+ \tpack{\vskip12\points\box0\vskip6\points}%
+ \tpack{\vskip12\points\box2\vskip6\points}}%
+ \endgroup}
+
+\unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {\advance\c_grph_steps_reference\plusone
+ \position(#1,#2)
+ {\hbox{\the\c_grph_steps_reference}}%
+ \position(#1,#2)
+ {\gotosomeinternal\s!vwb{#7}\realfolio
+ {\grph_steps_marker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}}
+
+\unexpanded\def\grph_steps_three_remark
+ {\grph_steps_comment\v!yes}
+
+\let\grph_steps_three_marking \grph_steps_three_referring
+\let\grph_steps_three_colorbar\grph_steps_one_colorbar
+
+\unexpanded\def\grph_steps_four_referring
+ {\grph_steps_text{\normalstartimath\rightarrow\normalstopimath}}
+
+\unexpanded\def\grph_steps_four_marking
+ {\grph_steps_text{\normalstartimath\leftarrow\normalstopimath}}
+
+\let\grph_steps_four_remark \grph_steps_one_remark
+\let\grph_steps_four_colorbar\grph_steps_one_colorbar
+
+% Helpers:
+
+\def\grph_steps_calculate
+ {\ifnum0\externalfigureparameter\c!xmax=\zerocount
+ \ifnum0\externalfigureparameter\c!ymax=\zerocount
+ \setexternalfigureparameter\c!ymax{24}%
+ \fi
+ \d_grph_steps_y\figureheight
+ \divide\d_grph_steps_y \externalfigureparameter\c!ymax
+ \d_grph_steps_x\d_grph_steps_y
+ \scratchdimen\figurewidth
+ \advance\scratchdimen\d_grph_steps_y
+ \divide \scratchdimen\d_grph_steps_y
+ \setexternalfigureparameter\c!xmax{\number\scratchdimen}%
+ \else
+ \d_grph_steps_x\figurewidth \divide\d_grph_steps_x \externalfigureparameter\c!xmax\relax
+ \d_grph_steps_y\figureheight \divide\d_grph_steps_y \externalfigureparameter\c!ymax\relax
+ \fi}
+
+\def\grph_steps_comment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst}
+ {\def\grph_steps_comment_indeed[##1]##2%
+ {\position(#2,#3)%
+ {\setnostrut
+ \framed
+ [\c!width=#5\d_grph_steps_x,
+ \c!height=#6\d_grph_steps_y,
+ \c!offset=\v!none,
+ \c!frame=#1,
+ ##1]%
+ {##2}}}%
+ \dosingleempty\grph_steps_comment_indeed}
+
+% \def\grph_steps_figure#1%
+% {\position(0,0){\getvalue{#1}}}
+
+\def\grph_steps_goto(#1,#2)#3[#4]% (h,b)kader[ref]
+ {\gotobox{\vpack{\grph_steps_area(#1,#2)#3{}}}[#4]}
+
+\def\grph_steps_text#1(#2,#3)#4(#5,#6)#7[#8]%
+ {\advance\c_grph_steps_reference\plusone
+ \hbox % \hpack ?
+ {\quad
+ \thisissomeinternal\s!vwb
+ {#8}%
+ \gotosomeinternal\s!vwa{#8}\realfolio
+ {\hbox to 1.5em{\the\c_grph_steps_reference\presetgoto\hfill}}%
+ \quad#1 (#2,#3) (#5,#6) [#8]\hfill}%
+ \endgraf}
+
+\def\grph_steps_this_is(#1,#2)#3[#4]%
+ {\grph_steps_area(#1,#2){#3}{\dosetdirectpagereference{#4}}}
+
+\def\grph_steps_area(#1,#2)#3#4% (h,b){kader}{tekst}
+ {\bgroup
+ \setnostrut
+ \framed
+ [\c!width=#1\d_grph_steps_x,
+ \c!height=#2\d_grph_steps_y,
+ \c!offset=\zeropoint,
+ \c!frame=#3]
+ {#4}%
+ \egroup}
+
+\def\grph_steps_marker(#1,#2)#3#4% (h,b){kader}{tekst}
+ {\framed
+ [\c!width=#1\d_grph_steps_x,
+ \c!height=#2\d_grph_steps_y,
+ \c!offset=\v!none,
+ \c!frame=#3]%
+ {#4}}
+
+\protect \endinput
+
+% \startbuffer
+% \definecolor [blue] [c=1,m=.38,y=0,k=.64]
+% \definecolor [yellow] [c=0,m=.28,y=1,k=.06]
+%
+% \definespotcolor [blue-100] [blue] [p=1]
+% \definespotcolor [yellow-100] [yellow] [p=1]
+%
+% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
+%
+% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone
+% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone
+%
+% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth]
+% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth]
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-a][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-b][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=blue-100]} {spot color}
+% {\externalfigure[demo-a][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=blue-100]} {spot color}
+% {\externalfigure[demo-b][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+% \stopbuffer
+%
+% \getbuffer \typebuffer
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-fil.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-fil.lua
new file mode 100644
index 00000000000..e774d097e6e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-fil.lua
@@ -0,0 +1,93 @@
+if not modules then modules = { } end modules ['grph-fil'] = {
+ version = 1.001,
+ comment = "companion to grph-fig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type = type
+
+local trace_run = false trackers.register("graphic.runfile",function(v) trace_run = v end)
+local report_run = logs.reporter("graphics","run")
+
+local isfile = lfs.isfile
+local replacesuffix = file.replacesuffix
+local addsuffix = file.addsuffix
+local checksum = file.checksum
+
+-- Historically running files is part of graphics processing, so this is why it
+-- sits here but is part of the job namespace.
+
+local allocate = utilities.storage.allocate
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local jobfiles = {
+ collected = collected,
+ tobesaved = tobesaved,
+ forcerun = false, -- maybe a directive some day
+}
+
+job.files = jobfiles
+
+local inputsuffix = "tex"
+local resultsuffix = "pdf"
+
+local function initializer()
+ tobesaved = jobfiles.tobesaved
+ collected = jobfiles.collected
+end
+
+job.register('job.files.collected', tobesaved, initializer)
+
+function jobfiles.run(name,action)
+ local usedname = addsuffix(name,inputsuffix) -- we assume tex if not set
+ local oldchecksum = collected[usedname]
+ local newchecksum = checksum(usedname)
+ local resultfile = replacesuffix(usedname,resultsuffix)
+ if jobfiles.forcerun or not oldchecksum or oldchecksum ~= newchecksum or not isfile(resultfile) then
+ if trace_run then
+ report_run("processing file, changes in %a, processing forced",name)
+ end
+ local ta = type(action)
+ if ta == "function" then
+ action(name)
+ elseif ta == "string" and action ~= "" then
+ os.execute(action)
+ else
+ report_run("processing file, no action given for processing %a",name)
+ end
+ elseif trace_run then
+ report_run("processing file, no changes in %a, not processed",name)
+ end
+ tobesaved[name] = newchecksum
+end
+
+--
+
+local done = { }
+
+function jobfiles.context(name,options)
+ if type(name) == "table" then
+ local result = { }
+ for i=1,#name do
+ result[#result+1] = jobfiles.context(name[i],options)
+ end
+ return result
+ else
+ local result = replacesuffix(name,resultsuffix)
+ if not done[result] then
+ jobfiles.run(name,"context ".. (options or "") .. " " .. name)
+ done[result] = true
+ end
+ return result
+ end
+end
+
+interfaces.implement {
+ name = "runcontextjob",
+ arguments = { "string", "string" },
+ actions = { jobfiles.context, context }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua
new file mode 100644
index 00000000000..cf4a702697f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua
@@ -0,0 +1,2119 @@
+if not modules then modules = { } end modules ['grph-inc'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: files are sometimes located twice
+-- todo: empty filename or only suffix always false (not found)
+-- lowercase types
+-- mps tex tmp svg
+-- partly qualified
+-- dimensions
+-- use metatables
+-- figures.boxnumber can go as we now can use names
+-- avoid push
+-- move some to command namespace
+
+--[[
+The ConTeXt figure inclusion mechanisms are among the oldest code
+in ConTeXt and evolved into a complex whole. One reason is that we
+deal with backend in an abstract way. What complicates matters is
+that we deal with internal graphics as well: TeX code, MetaPost code,
+etc. Later on figure databases were introduced, which resulted in
+a plug in model for locating images. On top of that runs a conversion
+mechanism (with caching) and resource logging.
+
+Porting that to Lua is not that trivial because quite some
+status information is kept between al these stages. Of course, image
+reuse also has some price, and so I decided to implement the graphics
+inclusion in several layers: detection, loading, inclusion, etc.
+
+Object sharing and scaling can happen at each stage, depending on the
+way the resource is dealt with.
+
+The TeX-Lua mix is suboptimal. This has to do with the fact that we cannot
+run TeX code from within Lua. Some more functionality will move to Lua.
+]]--
+
+-- todo: store loaded pages per pdf file someplace
+
+local format, lower, find, match, gsub, gmatch = string.format, string.lower, string.find, string.match, string.gsub, string.gmatch
+local contains = table.contains
+local concat, insert, remove = table.concat, table.insert, table.remove
+local todimen = string.todimen
+local collapsepath = file.collapsepath
+local formatters = string.formatters
+local longtostring = string.longtostring
+local expandfilename = dir.expandname
+
+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
+
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local replacetemplate = utilities.templates.replace
+
+local images = img
+
+local hasscheme = url.hasscheme
+local urlhashed = url.hashed
+
+local resolveprefix = resolvers.resolve
+
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+
+local hpack = node.hpack
+
+local new_latelua = nodes.pool.latelua
+
+local context = context
+
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+local codeinjections = backends.codeinjections
+local nodeinjections = backends.nodeinjections
+
+local trace_figures = false trackers.register ("graphics.locating", function(v) trace_figures = v end)
+local trace_bases = false trackers.register ("graphics.bases", function(v) trace_bases = v end)
+local trace_programs = false trackers.register ("graphics.programs", function(v) trace_programs = v end)
+local trace_conversion = false trackers.register ("graphics.conversion", function(v) trace_conversion = v end)
+local trace_inclusion = false trackers.register ("graphics.inclusion", function(v) trace_inclusion = v end)
+
+local extra_check = false directives.register("graphics.extracheck", function(v) extra_check = v end)
+
+local report_inclusion = logs.reporter("graphics","inclusion")
+local report_figures = logs.reporter("system","graphics")
+local report_figure = logs.reporter("used graphic")
+
+local f_hash_part = formatters["%s->%s->%s"]
+local f_hash_full = formatters["%s->%s->%s->%s->%s->%s->%s"]
+
+local v_yes = variables.yes
+local v_low = variables.low
+local v_medium = variables.medium
+local v_high = variables.high
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_default = variables.default
+local v_auto = variables.auto
+
+local maxdimen = 2^30-1
+
+function images.check(figure)
+ if figure then
+ 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)
+ return false, "bad dimensions"
+ end
+ local xres = figure.xres
+ local yres = figure.yres
+ local changes = false
+ if height > width then
+ if height > maxdimen then
+ figure.height = maxdimen
+ figure.width = width * maxdimen/height
+ changed = true
+ end
+ elseif width > maxdimen then
+ figure.width = maxdimen
+ figure.height = height * maxdimen/width
+ changed = true
+ end
+ if changed then
+ report_inclusion("limiting natural dimensions of %a, old %p * %p, new %p * %p",
+ figure.filename,width,height,figure.width,figure.height)
+ end
+ if width >= maxdimen or height >= maxdimen then
+ report_inclusion("image %a is too large (%p,%p), discarding",
+ figure.filename,width,height)
+ return false, "dimensions too large"
+ end
+ return figure
+ end
+end
+
+--- some extra img functions --- can become luat-img.lua
+
+local allimagekeys = images.keys()
+
+local function imagetotable(imgtable)
+ local result = { }
+ for k=1,#allimagekeys do
+ local key = allimagekeys[k]
+ result[key] = imgtable[key]
+ end
+ return result
+end
+
+images.totable = imagetotable
+
+function images.serialize(i,...)
+ return table.serialize(imagetotable(i),...)
+end
+
+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())
+
+function images.checksize(size)
+ if size then
+ size = gsub(size,"box","")
+ return validsizes[size] and size or "crop"
+ else
+ return "crop"
+ end
+end
+
+local indexed = { }
+
+function images.ofindex(n)
+ return indexed[n]
+end
+
+--- we can consider an grph-ini file
+
+figures = figures or { }
+local figures = figures
+
+figures.images = images
+figures.boxnumber = figures.boxnumber or 0
+figures.defaultsearch = true
+figures.defaultwidth = 0
+figures.defaultheight = 0
+figures.defaultdepth = 0
+figures.nofprocessed = 0
+figures.preferquality = true -- quality over location
+
+local figures_loaded = allocate() figures.loaded = figures_loaded
+local figures_used = allocate() figures.used = figures_used
+local figures_found = allocate() figures.found = figures_found
+local figures_suffixes = allocate() figures.suffixes = figures_suffixes
+local figures_patterns = allocate() figures.patterns = figures_patterns
+local figures_resources = allocate() figures.resources = figures_resources
+
+local existers = allocate() figures.existers = existers
+local checkers = allocate() figures.checkers = checkers
+local includers = allocate() figures.includers = includers
+local converters = allocate() figures.converters = converters
+local identifiers = allocate() figures.identifiers = identifiers
+local programs = allocate() figures.programs = programs
+
+local defaultformat = "pdf"
+local defaultprefix = "m_k_i_v_"
+
+figures.localpaths = allocate {
+ ".", "..", "../.."
+}
+
+figures.cachepaths = allocate {
+ prefix = "",
+ path = ".",
+ subpath = ".",
+}
+
+local figure_paths = allocate(table.copy(figures.localpaths))
+figures.paths = figure_paths
+
+local figures_order = allocate {
+ "pdf", "mps", "jpg", "png", "jp2", "jbig", "svg", "eps", "tif", "gif", "mov", "buffer", "tex", "cld", "auto",
+}
+
+local figures_formats = allocate { -- magic and order will move here
+ ["pdf"] = { list = { "pdf" } },
+ ["mps"] = { patterns = { "mps", "%d+" } },
+ ["jpg"] = { list = { "jpg", "jpeg" } },
+ ["png"] = { list = { "png" } },
+ ["jp2"] = { list = { "jp2" } },
+ ["jbig"] = { list = { "jbig", "jbig2", "jb2" } },
+ ["svg"] = { list = { "svg", "svgz" } },
+ ["eps"] = { list = { "eps", "ai" } },
+ ["gif"] = { list = { "gif" } },
+ ["tif"] = { list = { "tif", "tiff" } },
+ ["mov"] = { list = { "mov", "flv", "mp4" } }, -- "avi" is not supported
+ ["buffer"] = { list = { "tmp", "buffer", "buf" } },
+ ["tex"] = { list = { "tex" } },
+ ["cld"] = { list = { "cld" } },
+ ["auto"] = { list = { "auto" } },
+}
+
+local figures_magics = allocate {
+ { format = "png", pattern = P("\137PNG\013\010\026\010") }, -- 89 50 4E 47 0D 0A 1A 0A,
+ { format = "jpg", pattern = P("\255\216\255") }, -- FF D8 FF
+ { format = "jp2", pattern = P("\000\000\000\012\106\080\032\032\013\010"), }, -- 00 00 00 0C 6A 50 20 20 0D 0A },
+ { format = "gif", pattern = P("GIF") },
+ { format = "pdf", pattern = (1 - P("%PDF"))^0 * P("%PDF") },
+}
+
+local figures_native = allocate {
+ pdf = true,
+ jpg = true,
+ jp2 = true,
+ png = true,
+}
+
+figures.formats = figures_formats -- frozen
+figures.magics = figures_magics -- frozen
+figures.order = figures_order -- frozen
+
+-- name checker
+
+local okay = P("m_k_i_v_")
+
+local pattern = (R("az","AZ") * P(":"))^-1 * ( -- a-z : | A-Z :
+ (okay + R("az","09") + S("_/") - P("_")^2)^1 * (P(".") * R("az")^1)^0 * P(-1) + -- a-z | single _ | /
+ (okay + R("az","09") + S("-/") - P("-")^2)^1 * (P(".") * R("az")^1)^0 * P(-1) + -- a-z | single - | /
+ (okay + R("AZ","09") + S("_/") - P("_")^2)^1 * (P(".") * R("AZ")^1)^0 * P(-1) + -- A-Z | single _ | /
+ (okay + R("AZ","09") + S("-/") - P("-")^2)^1 * (P(".") * R("AZ")^1)^0 * P(-1) -- A-Z | single - | /
+) * Cc(false) + Cc(true)
+
+function figures.badname(name)
+ if not name then
+ -- bad anyway
+ elseif not hasscheme(name) then
+ return lpegmatch(pattern,name)
+ else
+ return lpegmatch(pattern,file.basename(name))
+ end
+end
+
+local trace_names = false
+
+trackers.register("graphics.lognames", function(v)
+ if v and not trace_names then
+ luatex.registerstopactions(function()
+ if figures.nofprocessed > 0 then
+ local report_newline = logs.newline
+ logs.pushtarget("logfile")
+ report_newline()
+ report_figures("start names")
+ for _, data in table.sortedhash(figures_found) do
+ report_newline()
+ report_figure("asked : %s",data.askedname)
+ if data.found then
+ report_figure("format : %s",data.format)
+ report_figure("found : %s",data.foundname)
+ report_figure("used : %s",data.fullname)
+ if data.badname then
+ report_figure("comment : %s","bad name")
+ elseif data.comment then
+ report_figure("comment : %s",data.comment)
+ end
+ else
+ report_figure("comment : %s","not found")
+ end
+ end
+ report_newline()
+ report_figures("stop names")
+ report_newline()
+ logs.poptarget()
+ end
+ end)
+ trace_names = true
+ end
+end)
+
+-- We can set the order but only indirectly so that we can check for support.
+
+function figures.setorder(list) -- can be table or string
+ if type(list) == "string" then
+ list = settings_to_array(list)
+ end
+ if list and #list > 0 then
+ figures_order = allocate()
+ figures.order = figures_order
+ local done = { } -- just to be sure in case the list is generated
+ for i=1,#list do
+ local l = lower(list[i])
+ if figures_formats[l] and not done[l] then
+ figures_order[#figures_order+1] = l
+ done[l] = true
+ end
+ end
+ report_inclusion("lookup order % a",figures_order)
+ else
+ -- invalid list
+ end
+end
+
+function figures.guess(filename)
+ local f = io.open(filename,'rb')
+ if f then
+ local str = f:read(100)
+ f:close()
+ 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
+end
+
+local function setlookups() -- tobe redone .. just set locals
+ figures_suffixes = allocate()
+ figures_patterns = allocate()
+ for _, format in next, figures_order do
+ local data = figures_formats[format]
+ local list = data.list
+ if list then
+ for i=1,#list do
+ figures_suffixes[list[i]] = format -- hash
+ end
+ else
+ figures_suffixes[format] = format
+ end
+ local patterns = data.patterns
+ if patterns then
+ for i=1,#patterns do
+ figures_patterns[#figures_patterns+1] = { patterns[i], format } -- array
+ end
+ end
+ end
+ figures.suffixes = figures_suffixes
+ figures.patterns = figures_patterns
+end
+
+setlookups()
+
+figures.setlookups = setlookups
+
+function figures.registerresource(t)
+ local n = #figures_resources + 1
+ figures_resources[n] = t
+ return n
+end
+
+local function register(tag,what,target)
+ local data = figures_formats[target] -- resolver etc
+ if not data then
+ data = { }
+ figures_formats[target] = data
+ end
+ local d = data[tag] -- list or pattern
+ if d and not contains(d,what) then
+ d[#d+1] = what -- suffix or patternspec
+ else
+ data[tag] = { what }
+ end
+ if not contains(figures_order,target) then
+ figures_order[#figures_order+1] = target
+ end
+ setlookups()
+end
+
+function figures.registersuffix (suffix, target) register('list',suffix,target) end
+function figures.registerpattern(pattern,target) register('pattern',pattern,target) end
+
+implement { name = "registerfiguresuffix", actions = register, arguments = { "'list'", "string", "string" } }
+implement { name = "registerfigurepattern", actions = register, arguments = { "'pattern'", "string", "string" } }
+
+local last_locationset = last_locationset or nil
+local last_pathlist = last_pathlist or nil
+
+function figures.setpaths(locationset,pathlist)
+ if last_locationset == locationset and last_pathlist == pathlist then
+ -- this function can be called each graphic so we provide this optimization
+ return
+ end
+ local t, h = figure_paths, settings_to_hash(locationset)
+ if last_locationset ~= locationset then
+ -- change == reset (actually, a 'reset' would indeed reset
+ if h[v_local] then
+ t = table.fastcopy(figures.localpaths or { })
+ else
+ t = { }
+ end
+ figures.defaultsearch = h[v_default]
+ last_locationset = locationset
+ end
+ if h[v_global] then
+ local list = settings_to_array(pathlist)
+ for i=1,#list do
+ local s = list[i]
+ if not contains(t,s) then
+ t[#t+1] = s
+ end
+ end
+ end
+ figure_paths = t
+ last_pathlist = pathlist
+ figures.paths = figure_paths
+ if trace_figures then
+ report_inclusion("using locations %a",last_locationset)
+ report_inclusion("using paths % a",figure_paths)
+ end
+end
+
+implement { name = "setfigurepaths", actions = figures.setpaths, arguments = { "string", "string" } }
+
+-- check conversions and handle it here
+
+function figures.hash(data)
+ local status = data and data.status
+ return (status and status.hash or tostring(status.private)) or "nohash" -- the <img object>
+end
+
+-- interfacing to tex
+
+local function new() -- we could use metatables status -> used -> request but it needs testing
+ local request = {
+ name = false,
+ label = false,
+ format = false,
+ page = false,
+ width = false,
+ height = false,
+ preview = false,
+ ["repeat"] = false,
+ controls = false,
+ display = false,
+ mask = false,
+ conversion = false,
+ resolution = false,
+ cache = false,
+ prefix = false,
+ size = false,
+ }
+ local used = {
+ fullname = false,
+ format = false,
+ name = false,
+ path = false,
+ suffix = false,
+ width = false,
+ height = false,
+ }
+ local status = {
+ status = 0,
+ converted = false,
+ cached = false,
+ fullname = false,
+ format = false,
+ }
+ -- this needs checking because we might check for nil, the test case
+ -- is getfiguredimensions which then should return ~= 0
+ -- setmetatableindex(status, used)
+ -- setmetatableindex(used, request)
+ return {
+ request = request,
+ used = used,
+ status = status,
+ }
+end
+
+-- use table.insert|remove
+
+local lastfiguredata = nil -- will be topofstack or last so no { } (else problems with getfiguredimensions)
+local callstack = { }
+
+function figures.initialize(request)
+ local figuredata = new()
+ if request then
+ -- request.width/height are strings and are only used when no natural dimensions
+ -- can be determined; at some point the handlers might set them to numbers instead
+ local w = tonumber(request.width) or 0
+ local h = tonumber(request.height) or 0
+ request.width = w > 0 and w or nil
+ request.height = h > 0 and h or nil
+ --
+ request.page = math.max(tonumber(request.page) or 1,1)
+ request.size = images.checksize(request.size)
+ request.object = request.object == v_yes
+ request["repeat"] = request["repeat"] == v_yes
+ request.preview = request.preview == v_yes
+ request.cache = request.cache ~= "" and request.cache
+ request.prefix = request.prefix ~= "" and request.prefix
+ request.format = request.format ~= "" and request.format
+ table.merge(figuredata.request,request)
+ end
+ return figuredata
+end
+
+function figures.push(request)
+ statistics.starttiming(figures)
+ local figuredata = figures.initialize(request) -- we could use table.sparse but we set them later anyway
+ insert(callstack,figuredata)
+ lastfiguredata = figuredata
+ return figuredata
+end
+
+function figures.pop()
+ remove(callstack)
+ lastfiguredata = callstack[#callstack] or lastfiguredata
+ statistics.stoptiming(figures)
+end
+
+function figures.current()
+ return callstack[#callstack] or lastfiguredata
+end
+
+local function get(category,tag,default)
+ local value = lastfiguredata and lastfiguredata[category]
+ value = value and value[tag]
+ if not value or value == "" or value == true then
+ return default or ""
+ else
+ return value
+ end
+end
+
+local function setdimensions(box)
+ local status = lastfiguredata and lastfiguredata.status
+ local used = lastfiguredata and lastfiguredata.used
+ if status and used then
+ local b = texgetbox(box)
+ local w = b.width
+ local h = b.height + b.depth
+ status.width = w
+ status.height = h
+ used.width = w
+ used.height = h
+ status.status = 10
+ end
+end
+
+figures.get = get
+figures.set = setdimensions
+
+implement { name = "figurestatus", actions = { get, context }, arguments = { "'status'", "string", "string" } }
+implement { name = "figurerequest", actions = { get, context }, arguments = { "'request'", "string", "string" } }
+implement { name = "figureused", actions = { get, context }, arguments = { "'used'", "string", "string" } }
+
+implement { name = "figurefilepath", actions = { get, file.dirname, context }, arguments = { "'used'", "'fullname'" } }
+implement { name = "figurefilename", actions = { get, file.nameonly, context }, arguments = { "'used'", "'fullname'" } }
+implement { name = "figurefiletype", actions = { get, file.extname, context }, arguments = { "'used'", "'fullname'" } }
+
+implement { name = "figuresetdimensions", actions = setdimensions, arguments = { "integer" } }
+
+-- todo: local path or cache path
+
+local function forbiddenname(filename)
+ if not filename or filename == "" then
+ return false
+ end
+ local expandedfullname = collapsepath(filename,true)
+ local expandedinputname = collapsepath(file.addsuffix(environment.jobfilename,environment.jobfilesuffix),true)
+ if expandedfullname == expandedinputname then
+ report_inclusion("skipping graphic with same name as input filename %a, enforce suffix",expandedinputname)
+ return true
+ end
+ local expandedoutputname = collapsepath(codeinjections.getoutputfilename(),true)
+ if expandedfullname == expandedoutputname then
+ report_inclusion("skipping graphic with same name as output filename %a, enforce suffix",expandedoutputname)
+ return true
+ end
+end
+
+local function rejected(specification)
+ if extra_check then
+ local fullname = specification.fullname
+ if fullname and figures_native[file.suffix(fullname)] and not figures.guess(fullname) then
+ specification.comment = "probably a bad file"
+ specification.found = false
+ specification.error = true
+ report_inclusion("file %a looks bad",fullname)
+ return true
+ end
+ end
+end
+
+local function register(askedname,specification)
+ if not specification then
+ specification = { askedname = askedname, comment = "invalid specification" }
+ elseif forbiddenname(specification.fullname) then
+ specification = { askedname = askedname, comment = "forbidden name" }
+ elseif specification.internal then
+ -- no filecheck needed
+ specification.found = true
+ if trace_figures then
+ report_inclusion("format %a internally supported by engine",specification.format)
+ end
+ elseif not rejected(specification) then
+ local format = specification.format
+ if format then
+ local conversion = specification.conversion
+ local resolution = specification.resolution
+ if conversion == "" then
+ conversion = nil
+ end
+ if resolution == "" then
+ resolution = nil
+ end
+ local newformat = conversion
+ if not newformat or newformat == "" then
+ newformat = defaultformat
+ end
+ if trace_conversion then
+ report_inclusion("checking conversion of %a, fullname %a, old format %a, new format %a, conversion %a, resolution %a",
+ askedname,specification.fullname,format,newformat,conversion or "default",resolution or "default")
+ end
+ -- quick hack
+ local converter = (newformat ~= format or resolution) and converters[format]
+ if converter then
+ if converter[newformat] then
+ converter = converter[newformat]
+ else
+ newformat = defaultformat
+ if converter[newformat] then
+ converter = converter[newformat]
+ else
+ converter = nil
+ newformat = defaultformat
+ end
+ end
+ elseif trace_conversion then
+ report_inclusion("no converter for %a to %a",format,newformat)
+ end
+ if converter then
+ --
+ -- todo: outline as helper function
+ --
+ local oldname = specification.fullname
+ local newpath = file.dirname(oldname)
+ local oldbase = file.basename(oldname)
+ --
+ -- problem: we can have weird filenames, like a.b.c (no suffix) and a.b.c.gif
+ -- so we cannot safely remove a suffix (unless we do that for known suffixes)
+ --
+ -- local newbase = file.removesuffix(oldbase) -- assumes a known suffix
+ --
+ -- so we now have (also see *):
+ --
+ local newbase = oldbase
+ --
+ local fc = specification.cache or figures.cachepaths.path
+ if fc and fc ~= "" and fc ~= "." then
+ newpath = gsub(fc,"%*",newpath) -- so cachedir can be "/data/cache/*"
+ else
+ newbase = defaultprefix .. newbase
+ end
+ local subpath = specification.subpath or figures.cachepaths.subpath
+ if subpath and subpath ~= "" and subpath ~= "." then
+ newpath = newpath .. "/" .. subpath
+ end
+ if not lfs.isdir(newpath) then
+ dir.makedirs(newpath)
+ if not file.is_writable(newpath) then
+ if trace_conversion then
+ report_inclusion("path %a is not writable, forcing conversion path %a",newpath,".")
+ end
+ newpath = "."
+ end
+ end
+ local prefix = specification.prefix or figures.cachepaths.prefix
+ if prefix and prefix ~= "" then
+ newbase = prefix .. newbase
+ end
+ if resolution and resolution ~= "" then -- the order might change
+ newbase = newbase .. "_" .. resolution
+ end
+ --
+ -- see *, we had:
+ --
+ -- local newbase = file.addsuffix(newbase,newformat)
+ --
+ -- but now have (result of Aditya's web image testing):
+ --
+ -- as a side effect we can now have multiple fetches with different
+ -- original figures_formats, not that it matters much (apart from older conversions
+ -- sticking around)
+ --
+ local newbase = newbase .. "." .. newformat
+ --
+ local newname = file.join(newpath,newbase)
+ oldname = collapsepath(oldname)
+ newname = collapsepath(newname)
+ local oldtime = lfs.attributes(oldname,'modification') or 0
+ local newtime = lfs.attributes(newname,'modification') or 0
+ if newtime == 0 or oldtime > newtime then
+ if trace_conversion then
+ report_inclusion("converting %a (%a) from %a to %a",askedname,oldname,format,newformat)
+ end
+ converter(oldname,newname,resolution or "")
+ else
+ if trace_conversion then
+ report_inclusion("no need to convert %a (%a) from %a to %a",askedname,oldname,format,newformat)
+ end
+ end
+ if io.exists(newname) and io.size(newname) > 0 then
+ specification.foundname = oldname
+ specification.fullname = newname
+ specification.prefix = prefix
+ specification.subpath = subpath
+ specification.converted = true
+ format = newformat
+ if not figures_suffixes[format] then
+ -- maybe the new format is lowres.png (saves entry in suffixes)
+ -- so let's do this extra check
+ local suffix = file.suffix(newformat)
+ if figures_suffixes[suffix] then
+ if trace_figures then
+ report_inclusion("using suffix %a as format for %a",suffix,format)
+ end
+ format = suffix
+ end
+ end
+ elseif io.exists(oldname) then
+ report_inclusion("file %a is bugged",oldname)
+ if format and validtypes[format] then
+ specification.fullname = oldname
+ end
+ specification.converted = false
+ specification.bugged = true
+ end
+ end
+ end
+ if format then
+ local found = figures_suffixes[format] -- validtypes[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
+ specification.found = true
+ if trace_figures then
+ report_inclusion("format %a natively supported by backend",format)
+ end
+ else
+ specification.found = true -- else no foo.1 mps conversion
+ if trace_figures then
+ report_inclusion("format %a supported by output file format",format)
+ end
+ end
+ else
+ specification.askedname = askedname
+ specification.found = false
+ end
+ end
+ if specification.found then
+ specification.foundname = specification.foundname or specification.fullname
+ else
+ specification.foundname = nil
+ end
+ specification.badname = figures.badname(askedname)
+ local askedhash = f_hash_part(askedname,specification.conversion or "default",specification.resolution or "default")
+ figures_found[askedhash] = specification
+ return specification
+end
+
+local resolve_too = false -- true
+
+local internalschemes = {
+ file = true,
+ tree = true,
+ dirfile = true,
+ dirtree = true,
+}
+
+local function locate(request) -- name, format, cache
+ -- not resolvers.cleanpath(request.name) as it fails on a!b.pdf and b~c.pdf
+ -- todo: more restricted cleanpath
+ local askedname = request.name or ""
+ local askedhash = f_hash_part(askedname,request.conversion or "default",request.resolution or "default")
+ local foundname = figures_found[askedhash]
+ if foundname then
+ return foundname
+ end
+ --
+ local askedcache = request.cache
+ local askedconversion = request.conversion
+ local askedresolution = request.resolution
+ --
+ local askedformat = request.format
+ if not askedformat or askedformat == "" or askedformat == "unknown" then
+ askedformat = file.suffix(askedname) or ""
+ elseif askedformat == v_auto then
+ if trace_figures then
+ report_inclusion("ignoring suffix of %a",askedname)
+ end
+ askedformat = ""
+ askedname = file.removesuffix(askedname)
+ end
+ -- protocol check
+ local hashed = urlhashed(askedname)
+ if not hashed then
+ -- go on
+ elseif internalschemes[hashed.scheme] then
+ local path = hashed.path
+ if path and path ~= "" then
+ askedname = path
+ end
+ else
+ -- local fname = methodhandler('finders',pathname .. "/" .. wantedfiles[k])
+ local foundname = resolvers.findbinfile(askedname)
+ if not foundname or not lfs.isfile(foundname) then -- foundname can be dummy
+ if trace_figures then
+ report_inclusion("unknown url %a",askedname)
+ end
+ -- url not found
+ return register(askedname)
+ end
+ local guessedformat = figures.guess(foundname)
+ if askedformat ~= guessedformat then
+ if trace_figures then
+ report_inclusion("url %a has unknown format",askedname)
+ end
+ -- url found, but wrong format
+ return register(askedname)
+ else
+ if trace_figures then
+ report_inclusion("url %a is resolved to %a",askedname,foundname)
+ end
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ -- we could use the hashed data instead
+ local askedpath = file.is_rootbased_path(askedname)
+ local askedbase = file.basename(askedname)
+ if askedformat ~= "" then
+ askedformat = lower(askedformat)
+ if trace_figures then
+ report_inclusion("forcing format %a",askedformat)
+ end
+ local format = figures_suffixes[askedformat]
+ if not format then
+ for i=1,#figures_patterns do
+ local pattern = figures_patterns[i]
+ if find(askedformat,pattern[1]) then
+ format = pattern[2]
+ if trace_figures then
+ report_inclusion("asked format %a matches %a",askedformat,pattern[1])
+ end
+ break
+ end
+ end
+ end
+ if format then
+ local foundname, quitscanning, forcedformat, internal = figures.exists(askedname,format,resolve_too) -- not askedformat
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname, -- askedname,
+ format = forcedformat or format,
+ cache = askedcache,
+ -- foundname = foundname, -- no
+ conversion = askedconversion,
+ resolution = askedresolution,
+ internal = internal,
+ })
+ elseif quitscanning then
+ return register(askedname)
+ end
+ askedformat = format -- new per 2013-08-05
+ elseif trace_figures then
+ report_inclusion("unknown format %a",askedformat)
+ end
+ if askedpath then
+ -- path and type given, todo: strip pieces of path
+ local foundname, quitscanning, forcedformat = figures.exists(askedname,askedformat,resolve_too)
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname, -- askedname,
+ format = forcedformat or askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ else
+ -- type given
+ for i=1,#figure_paths do
+ local path = resolveprefix(figure_paths[i]) -- we resolve (e.g. jobfile:)
+ local check = path .. "/" .. askedname
+ -- we pass 'true' as it can be an url as well, as the type
+ -- is given we don't waste much time
+ local foundname, quitscanning, forcedformat = figures.exists(check,askedformat,resolve_too)
+ if foundname then
+ return register(check, {
+ askedname = askedname,
+ fullname = foundname, -- check,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ if figures.defaultsearch then
+ local check = resolvers.findfile(askedname)
+ if check and check ~= "" then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ end
+ elseif askedpath then
+ if trace_figures then
+ report_inclusion("using rootbased path")
+ end
+ for i=1,#figures_order do
+ local format = figures_order[i]
+ local list = figures_formats[format].list or { format }
+ for j=1,#list do
+ local suffix = list[j]
+ local check = file.addsuffix(askedname,suffix)
+ local foundname, quitscanning, forcedformat = figures.exists(check,format,resolve_too)
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname, -- check,
+ format = forcedformat or format,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ end
+ else
+ if figures.preferquality then
+ if trace_figures then
+ report_inclusion("unknown format, quality preferred")
+ end
+ for j=1,#figures_order do
+ local format = figures_order[j]
+ local list = figures_formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ -- local name = file.replacesuffix(askedbase,suffix)
+ local name = file.replacesuffix(askedname,suffix)
+ for i=1,#figure_paths do
+ local path = resolveprefix(figure_paths[i]) -- we resolve (e.g. jobfile:)
+ local check = path .. "/" .. name
+ local isfile = internalschemes[urlhashed(check).scheme]
+ if not isfile then
+ if trace_figures then
+ report_inclusion("warning: skipping path %a",path)
+ end
+ else
+ local foundname, quitscanning, forcedformat = figures.exists(check,format,resolve_too) -- true)
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname, -- check
+ format = forcedformat or format,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ end
+ end
+ end
+ else -- 'location'
+ if trace_figures then
+ report_inclusion("unknown format, using path strategy")
+ end
+ for i=1,#figure_paths do
+ local path = resolveprefix(figure_paths[i]) -- we resolve (e.g. jobfile:)
+ for j=1,#figures_order do
+ local format = figures_order[j]
+ local list = figures_formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ local check = path .. "/" .. file.replacesuffix(askedbase,suffix)
+ local foundname, quitscanning, forcedformat = figures.exists(check,format,resolve_too)
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foudname, -- check,
+ format = forcedformat or format,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ end
+ end
+ end
+ if figures.defaultsearch then
+ if trace_figures then
+ report_inclusion("using default tex path")
+ end
+ for j=1,#figures_order do
+ local format = figures_order[j]
+ local list = figures_formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ local check = resolvers.findfile(file.replacesuffix(askedname,suffix))
+ if check and check ~= "" then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
+ end
+ end
+ end
+ end
+ return register(askedname, { -- these two are needed for hashing 'found'
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+end
+
+-- -- -- plugins -- -- --
+
+function identifiers.default(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local l = locate(dr)
+ local foundname = l.foundname
+ local fullname = l.fullname or foundname
+ if fullname then
+ du.format = l.format or false
+ du.fullname = fullname -- can be cached
+ ds.fullname = foundname -- original
+ ds.format = l.format
+ ds.status = (l.bugged and 0) or (l.found and 10) or 0
+ end
+ return data
+end
+
+function figures.identify(data)
+ data = data or callstack[#callstack] or lastfiguredata
+ local list = identifiers.list -- defined at the end
+ for i=1,#list do
+ local identifier = list[i]
+ local data = identifier(data)
+ if data and (not data.status and data.status.status > 0) then
+ break
+ end
+ end
+ return data
+end
+
+function figures.exists(askedname,format,resolve)
+ return (existers[format] or existers.generic)(askedname,resolve)
+end
+
+function figures.check(data)
+ data = data or callstack[#callstack] or lastfiguredata
+ return (checkers[data.status.format] or checkers.generic)(data)
+end
+
+local trace_usage = false
+local used_images = { }
+
+trackers.register("graphics.usage", function(v)
+ if v and not trace_usage then
+ luatex.registerstopactions(function()
+ local found = { }
+ for _, t in table.sortedhash(figures_found) do
+ found[#found+1] = t
+ for k, v in next, t do
+ if v == false or v == "" then
+ t[k] = nil
+ end
+ end
+ end
+ for i=1,#used_images do
+ local u = used_images[i]
+ local s = u.status
+ if s then
+ s.status = nil -- doesn't say much here
+ if s.error then
+ u.used = { } -- better show that it's not used
+ end
+ end
+ for _, t in next, u do
+ for k, v in next, t do
+ if v == false or v == "" then
+ t[k] = nil
+ end
+ end
+ end
+ end
+ table.save(file.nameonly(environment.jobname) .. "-figures-usage.lua",{
+ found = found,
+ used = used_images,
+ } )
+ end)
+ trace_usage = true
+ end
+end)
+
+function figures.include(data)
+ data = data or callstack[#callstack] or lastfiguredata
+ if trace_usage then
+ used_images[#used_images+1] = data
+ end
+ return (includers[data.status.format] or includers.generic)(data)
+end
+
+function figures.scale(data) -- will become lua code
+ data = data or callstack[#callstack] or lastfiguredata
+ context.doscalefigure()
+ return data
+end
+
+function figures.done(data)
+ figures.nofprocessed = figures.nofprocessed + 1
+ data = data or callstack[#callstack] or lastfiguredata
+ local dr, du, ds, nr = data.request, data.used, data.status, figures.boxnumber
+ local box = texgetbox(nr)
+ ds.width = box.width
+ ds.height = box.height
+ ds.xscale = ds.width /(du.width or 1)
+ ds.yscale = ds.height/(du.height or 1)
+ ds.page = ds.page or du.page or dr.page -- sort of redundant but can be limited
+ return data
+end
+
+function figures.dummy(data)
+ data = data or callstack[#callstack] or lastfiguredata
+ local dr, du, nr = data.request, data.used, figures.boxnumber
+ local box = hpack(node.new("hlist")) -- we need to set the dir (luatex 0.60 buglet)
+ du.width = du.width or figures.defaultwidth
+ du.height = du.height or figures.defaultheight
+ du.depth = du.depth or figures.defaultdepth
+ -- box.dir = "TLT"
+ box.width = du.width
+ box.height = du.height
+ box.depth = du.depth
+ texsetbox(nr,box) -- hm, should be global (to be checked for consistency)
+end
+
+-- -- -- generic -- -- --
+
+function existers.generic(askedname,resolve)
+ -- not findbinfile
+ local result
+ if hasscheme(askedname) then
+ result = resolvers.findbinfile(askedname)
+ elseif lfs.isfile(askedname) then
+ result = askedname
+ elseif resolve then
+ result = resolvers.findbinfile(askedname)
+ end
+ if not result or result == "" then
+ result = false
+ end
+ if trace_figures then
+ if result then
+ report_inclusion("%a resolved to %a",askedname,result)
+ else
+ report_inclusion("%a cannot be resolved",askedname)
+ end
+ end
+ return result
+end
+
+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
+ if not conversion or conversion == "" then
+ conversion = "unknown"
+ end
+ if not resolution or resolution == "" then
+ resolution = "unknown"
+ end
+ local hash = f_hash_full(name,page,size,color,conversion,resolution,mask)
+ local figure = figures_loaded[hash]
+ if figure == nil then
+ figure = images.new {
+ filename = name,
+ page = page,
+ pagebox = dr.size,
+ -- visiblefilename = "", -- this prohibits the full filename ending up in the file
+ }
+ codeinjections.setfigurecolorspace(data,figure)
+ codeinjections.setfiguremask(data,figure)
+ if figure then
+ local f, comment = images.check(images.scan(figure))
+ if not f then
+ ds.comment = comment
+ ds.found = false
+ ds.error = true
+ end
+ figure = f
+ end
+ local f, d = codeinjections.setfigurealternative(data,figure)
+ figure = f or figure
+ data = d or data
+ figures_loaded[hash] = figure
+ if trace_conversion then
+ report_inclusion("new graphic, using hash %a",hash)
+ end
+ else
+ if trace_conversion then
+ report_inclusion("existing graphic, using hash %a",hash)
+ end
+ end
+ if figure then
+ du.width = figure.width
+ du.height = figure.height
+ du.pages = figure.pages
+ du.depth = figure.depth or 0
+ du.colordepth = figure.colordepth or 0
+ du.xresolution = figure.xres or 0
+ du.yresolution = figure.yres or 0
+ du.xsize = figure.xsize or 0
+ du.ysize = figure.ysize or 0
+ ds.private = figure
+ ds.hash = hash
+ end
+ return data
+end
+
+local nofimages = 0
+local pofimages = { }
+
+function figures.getrealpage(index)
+ return pofimages[index] or 0
+end
+
+function includers.generic(data)
+ local dr, du, ds = data.request, data.used, data.status
+ -- here we set the 'natural dimensions'
+ dr.width = du.width
+ dr.height = du.height
+ local hash = figures.hash(data)
+ local figure = figures_used[hash]
+ -- figures.registerresource {
+ -- filename = du.fullname,
+ -- width = dr.width,
+ -- height = dr.height,
+ -- }
+ if figure == nil then
+ figure = ds.private
+ if figure then
+ figure = images.copy(figure)
+ figure = figure and images.clone(figure,data.request) or false
+ end
+ figures_used[hash] = figure
+ end
+ if figure then
+ local nr = figures.boxnumber
+ nofimages = nofimages + 1
+ ds.pageindex = nofimages
+ local image = images.node(figure)
+ local pager = new_latelua(function()
+ pofimages[nofimages] = pofimages[nofimages] or tex.count.realpageno -- so when reused we register the first one only
+ end)
+ image.next = pager
+ pager.prev = image
+ local box = hpack(image) -- images.node(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)
+ texsetbox(nr,box)
+ ds.objectnumber = figure.objnum
+ context.relocateexternalfigure()
+ end
+ return data
+end
+
+-- -- -- nongeneric -- -- --
+
+local function checkers_nongeneric(data,command) -- todo: macros and context.*
+ local dr, du, ds = data.request, data.used, data.status
+ local name = du.fullname or "unknown nongeneric"
+ local hash = name
+ if dr.object then
+ -- hm, bugged ... waiting for an xform interface
+ if not objects.data["FIG"][hash] then
+ if type(command) == "function" then
+ command()
+ end
+ context.dosetfigureobject("FIG",hash)
+ end
+ context.doboxfigureobject("FIG",hash)
+ elseif type(command) == "function" then
+ command()
+ end
+ return data
+end
+
+local function includers_nongeneric(data)
+ return data
+end
+
+checkers.nongeneric = checkers_nongeneric
+includers.nongeneric = includers_nongeneric
+
+-- -- -- mov -- -- --
+
+function checkers.mov(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local width = todimen(dr.width or figures.defaultwidth)
+ local height = todimen(dr.height or figures.defaultheight)
+ local foundname = du.fullname
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ if trace_inclusion then
+ report_inclusion("including movie %a, width %p, height %p",foundname,width,height)
+ end
+ -- we need to push the node.write in between ... we could make a shared helper for this
+ context.startfoundexternalfigure(width .. "sp",height .. "sp")
+ context(function()
+ nodeinjections.insertmovie {
+ width = width,
+ height = height,
+ factor = number.dimenfactors.bp,
+ ["repeat"] = dr["repeat"],
+ controls = dr.controls,
+ preview = dr.preview,
+ label = dr.label,
+ foundname = foundname,
+ }
+ end)
+ context.stopfoundexternalfigure()
+ return data
+end
+
+includers.mov = includers.nongeneric
+
+-- -- -- mps -- -- --
+
+internalschemes.mprun = true
+
+-- mprun.foo.1 mprun.6 mprun:foo.2
+
+local function internal(askedname)
+ local spec, mprun, mpnum = match(lower(askedname),"mprun([:%.]?)(.-)%.(%d+)")
+ if spec ~= "" then
+ return mprun, mpnum
+ else
+ return "", mpnum
+ end
+end
+
+function existers.mps(askedname)
+ local mprun, mpnum = internal(askedname)
+ if mpnum then
+ return askedname, true, "mps", true
+ else
+ return existers.generic(askedname)
+ end
+end
+
+function checkers.mps(data)
+ local mprun, mpnum = internal(data.used.fullname)
+ if mpnum then
+ return checkers_nongeneric(data,function() context.docheckfiguremprun(mprun,mpnum) end)
+ else
+ return checkers_nongeneric(data,function() context.docheckfiguremps(data.used.fullname) end)
+ end
+end
+
+includers.mps = includers.nongeneric
+
+-- -- -- tex -- -- --
+
+function existers.tex(askedname)
+ askedname = resolvers.findfile(askedname)
+ return askedname ~= "" and askedname or false, true, "tex", true
+end
+
+function checkers.tex(data)
+ return checkers_nongeneric(data,function() context.docheckfiguretex(data.used.fullname) end)
+end
+
+includers.tex = includers.nongeneric
+
+-- -- -- buffer -- -- --
+
+function existers.buffer(askedname)
+ local name = file.nameonly(askedname)
+ local okay = buffers.exists(name)
+ return okay and name, true, "buffer", true -- always quit scanning
+end
+
+function checkers.buffer(data)
+ return checkers_nongeneric(data,function() context.docheckfigurebuffer(file.nameonly(data.used.fullname)) end)
+end
+
+includers.buffers = includers.nongeneric
+
+-- -- -- auto -- -- --
+
+function existers.auto(askedname)
+ local name = gsub(askedname, ".auto$", "")
+ local format = figures.guess(name)
+ -- if format then
+ -- report_inclusion("format guess %a for %a",format,name)
+ -- else
+ -- report_inclusion("format guess for %a is not possible",name)
+ -- end
+ return format and name, true, format
+end
+
+checkers.auto = checkers.generic
+includers.auto = includers.generic
+
+-- -- -- cld -- -- --
+
+function existers.cld(askedname)
+ askedname = resolvers.findfile(askedname)
+ return askedname ~= "" and askedname or false, true, "cld", true
+end
+
+function checkers.cld(data)
+ return checkers_nongeneric(data,function() context.docheckfigurecld(data.used.fullname) end)
+end
+
+includers.cld = includers.nongeneric
+
+-- -- -- converters -- -- --
+
+local function makeoptions(options)
+ local to = type(options)
+ return (to == "table" and concat(options," ")) or (to == "string" and options) or ""
+end
+
+-- programs.makeoptions = makeoptions
+
+local function runprogram(binary,argument,variables)
+ -- move this check to the runner code
+ local found = nil
+ if type(binary) == "table" then
+ for i=1,#binary do
+ local b = binary[i]
+ found = os.which(b)
+ if found then
+ binary = b
+ break
+ end
+ end
+ if not found then
+ binary = concat(binary, " | ")
+ end
+ elseif binary then
+ found = os.which(match(binary,"[%S]+"))
+ end
+ if type(argument) == "table" then
+ argument = concat(argument," ") -- for old times sake
+ end
+ if not found then
+ report_inclusion("program %a is not installed",binary or "?")
+ elseif not argument or argument == "" then
+ report_inclusion("nothing to run, no arguments for program %a",binary)
+ else
+ -- no need to use the full found filename (found) .. we also don't quote the program
+ -- name any longer as in luatex there is too much messing with these names
+ local command = format([[%s %s]],binary,replacetemplate(longtostring(argument),variables))
+ if trace_conversion or trace_programs then
+ report_inclusion("running command: %s",command)
+ end
+ os.execute(command)
+ end
+end
+
+programs.run = runprogram
+
+-- -- -- eps & pdf -- -- --
+--
+-- \externalfigure[cow.eps]
+-- \externalfigure[cow.pdf][conversion=stripped]
+
+local epsconverter = converters.eps or { }
+converters.eps = epsconverter
+converters.ps = epsconverter
+
+-- todo: colorspace
+
+local epstopdf = {
+ resolutions = {
+ [v_low] = "screen",
+ [v_medium] = "ebook",
+ [v_high] = "prepress",
+ },
+ command = os.type == "windows" and { "gswin64c", "gswin32c" } or "gs",
+ -- -dProcessDSCComments=false
+ argument = [[
+ -q
+ -sDEVICE=pdfwrite
+ -dNOPAUSE
+ -dNOCACHE
+ -dBATCH
+ -dAutoRotatePages=/None
+ -dPDFSETTINGS=/%presets%
+ -dEPSCrop
+ -dCompatibilityLevel=%level%
+ -sOutputFile="%newname%"
+ %colorspace%
+ "%oldname%"
+ -c quit
+ ]],
+}
+
+programs.epstopdf = epstopdf
+programs.gs = epstopdf
+
+local cleanups = { }
+local cleaners = { }
+
+local whitespace = lpeg.patterns.whitespace
+local quadruple = Ct((whitespace^0 * lpeg.patterns.number/tonumber * whitespace^0)^4)
+local betterbox = P("%%BoundingBox:") * quadruple
+ * P("%%HiResBoundingBox:") * quadruple
+ * P("%AI3_Cropmarks:") * quadruple
+ * P("%%CropBox:") * quadruple
+ / function(b,h,m,c)
+ return formatters["%%%%BoundingBox: %i %i %i %i\n%%%%HiResBoundingBox: %F %F %F %F\n%%%%CropBox: %F %F %F %F\n"](
+ m[1],m[2],m[3],m[4],
+ m[1],m[2],m[3],m[4],
+ m[1],m[2],m[3],m[4]
+ )
+ end
+local nocrap = P("%") / "" * (
+ (P("AI9_PrivateDataBegin") * P(1)^0) / "%%%%EOF"
+ + (P("%EOF") * whitespace^0 * P("%AI9_PrintingDataEnd") * P(1)^0) / "%%%%EOF"
+ + (P("AI7_Thumbnail") * (1-P("%%EndData"))^0 * P("%%EndData")) / ""
+ )
+local whatever = nocrap + P(1)
+local pattern = Cs((betterbox * whatever^1 + whatever)^1)
+
+directives.register("graphics.conversion.eps.cleanup.ai",function(v) cleanups.ai = v end)
+
+cleaners.ai = function(name)
+ local tmpname = name .. ".tmp"
+ io.savedata(tmpname,lpegmatch(pattern,io.loaddata(name) or ""))
+ return tmpname
+end
+
+function epsconverter.pdf(oldname,newname,resolution,colorspace) -- the resolution interface might change
+ local epstopdf = programs.epstopdf -- can be changed
+ local presets = epstopdf.resolutions[resolution or "high"] or epstopdf.resolutions.high
+ local level = codeinjections.getformatoption("pdf_level") or "1.3"
+ local tmpname = oldname
+ if not tmpname or tmpname == "" or not lfs.isfile(tmpname) then
+ return
+ end
+ if cleanups.ai then
+ tmpname = cleaners.ai(oldname)
+ end
+ if colorspace == "gray" then
+ colorspace = "-sColorConversionStrategy=Gray -sProcessColorModel=DeviceGray"
+ -- colorspace = "-sColorConversionStrategy=Gray"
+ else
+ colorspace = nil
+ end
+ runprogram(epstopdf.command, epstopdf.argument, {
+ newname = newname,
+ oldname = tmpname,
+ presets = presets,
+ level = tostring(level),
+ colorspace = colorspace,
+ } )
+ if tmpname ~= oldname then
+ os.remove(tmpname)
+ end
+end
+
+epsconverter["gray.pdf"] = function(oldname,newname,resolution) -- the resolution interface might change
+ epsconverter.pdf(oldname,newname,resolution,"gray")
+end
+
+epsconverter.default = epsconverter.pdf
+
+local pdfconverter = converters.pdf or { }
+converters.pdf = pdfconverter
+
+-- programs.pdftoeps = {
+-- command = "pdftops",
+-- argument = [[-eps "%oldname%" "%newname%"]],
+-- }
+--
+-- pdfconverter.stripped = function(oldname,newname)
+-- local pdftoeps = programs.pdftoeps -- can be changed
+-- local epstopdf = programs.epstopdf -- can be changed
+-- local presets = epstopdf.resolutions[resolution or ""] or epstopdf.resolutions.high
+-- local level = codeinjections.getformatoption("pdf_level") or "1.3"
+-- local tmpname = newname .. ".tmp"
+-- runprogram(pdftoeps.command, pdftoeps.argument, { oldname = oldname, newname = tmpname, presets = presets, level = level })
+-- runprogram(epstopdf.command, epstopdf.argument, { oldname = tmpname, newname = newname, presets = presets, level = level })
+-- os.remove(tmpname)
+-- end
+--
+-- figures.registersuffix("stripped","pdf")
+
+-- -- -- svg -- -- --
+
+local svgconverter = { }
+converters.svg = svgconverter
+converters.svgz = svgconverter
+
+-- inkscape on windows only works with complete paths
+
+programs.inkscape = {
+ command = "inkscape",
+ pdfargument = [[
+ "%oldname%"
+ --export-dpi=600
+ -A
+ "%newname%"
+ ]],
+ pngargument = [[
+ "%oldname%"
+ --export-dpi=600
+ --export-png="%newname%"
+ ]],
+}
+
+function svgconverter.pdf(oldname,newname)
+ local inkscape = programs.inkscape -- can be changed
+ runprogram(inkscape.command, inkscape.pdfargument, {
+ newname = expandfilename(newname),
+ oldname = expandfilename(oldname),
+ } )
+end
+
+function svgconverter.png(oldname,newname)
+ local inkscape = programs.inkscape
+ runprogram(inkscape.command, inkscape.pngargument, {
+ newname = expandfilename(newname),
+ oldname = expandfilename(oldname),
+ } )
+end
+
+svgconverter.default = svgconverter.pdf
+
+-- -- -- gif -- -- --
+-- -- -- tif -- -- --
+
+local gifconverter = converters.gif or { }
+local tifconverter = converters.tif or { }
+local bmpconverter = converters.bmp or { }
+
+converters.gif = gifconverter
+converters.tif = tifconverter
+converters.bmp = bmpconverter
+
+programs.convert = {
+ command = "gm", -- graphicmagick
+ argument = [[convert "%oldname%" "%newname%"]],
+}
+
+local function converter(oldname,newname)
+ local convert = programs.convert
+ runprogram(convert.command, convert.argument, {
+ newname = newname,
+ oldname = oldname,
+ } )
+end
+
+tifconverter.pdf = converter
+gifconverter.pdf = converter
+bmpconverter.pdf = converter
+
+gifconverter.default = converter
+tifconverter.default = converter
+bmpconverter.default = converter
+
+-- todo: lowres
+
+-- cmyk conversion
+
+-- ecirgb_v2.icc
+-- ecirgb_v2_iccv4.icc
+-- isocoated_v2_300_eci.icc
+-- isocoated_v2_eci.icc
+-- srgb.icc
+-- srgb_v4_icc_preference.icc
+
+-- [[convert %?colorspace: -colorspace "%colorspace%" ?%]]
+
+local rgbprofile = "srgb_v4_icc_preference.icc" -- srgb.icc
+local cmykprofile = "isocoated_v2_300_eci.icc" -- isocoated_v2_eci.icc
+
+directives.register("graphics.conversion.rgbprofile", function(v) rgbprofile = type(v) == "string" and v or rgbprofile end)
+directives.register("graphics.conversion.cmykprofile",function(v) cmykprofile = type(v) == "string" and v or cmykprofile end)
+
+local function profiles()
+ if not lfs.isfile(rgbprofile) then
+ local found = resolvers.findfile(rgbprofile)
+ if found and found ~= "" then
+ rgbprofile = found
+ else
+ report_figures("unknown profile %a",rgbprofile)
+ end
+ end
+ if not lfs.isfile(cmykprofile) then
+ local found = resolvers.findfile(cmykprofile)
+ if found and found ~= "" then
+ cmykprofile = found
+ else
+ report_figures("unknown profile %a",cmykprofile)
+ end
+ end
+ return rgbprofile, cmykprofile
+end
+
+programs.pngtocmykpdf = {
+ command = "gm",
+ argument = [[convert -compress Zip -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+}
+
+programs.jpgtocmykpdf = {
+ command = "gm",
+ argument = [[convert -compress JPEG -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+}
+
+programs.pngtograypdf = {
+ command = "gm",
+ argument = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+}
+
+programs.jpgtograypdf = {
+ command = "gm",
+ argument = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+}
+
+figures.converters.png = {
+ ["cmyk.pdf"] = function(oldname,newname,resolution)
+ local rgbprofile, cmykprofile = profiles()
+ runprogram(programs.pngtocmykpdf.command, programs.pngtocmykpdf.argument, {
+ -- runprogram(programs.pngtocmykpdf, {
+ rgbprofile = rgbprofile,
+ cmykprofile = cmykprofile,
+ oldname = oldname,
+ newname = newname,
+ } )
+ end,
+ ["gray.pdf"] = function(oldname,newname,resolution)
+ runprogram(programs.pngtograypdf.command, programs.pngtograypdf.argument, {
+ -- runprogram(programs.pngtograypdf, {
+ oldname = oldname,
+ newname = newname,
+ } )
+ end,
+}
+
+figures.converters.jpg = {
+ ["cmyk.pdf"] = function(oldname,newname,resolution)
+ local rgbprofile, cmykprofile = profiles()
+ runprogram(programs.jpgtocmykpdf.command, programs.jpgtocmykpdf.argument, {
+ -- runprogram(programs.jpgtocmykpdf, {
+ rgbprofile = rgbprofile,
+ cmykprofile = cmykprofile,
+ oldname = oldname,
+ newname = newname,
+ } )
+ end,
+ ["gray.pdf"] = function(oldname,newname,resolution)
+ runprogram(programs.jpgtograypdf.command, programs.jpgtograypdf.argument, {
+ -- runprogram(programs.jpgtograypdf, {
+ oldname = oldname,
+ newname = newname,
+ } )
+ end,
+}
+
+-- -- -- bases -- -- --
+
+local bases = allocate()
+figures.bases = bases
+
+local bases_list = nil -- index => { basename, fullname, xmlroot }
+local bases_used = nil -- [basename] => { basename, fullname, xmlroot } -- pointer to list
+local bases_found = nil
+local bases_enabled = false
+
+local function reset()
+ bases_list = allocate()
+ bases_used = allocate()
+ bases_found = allocate()
+ bases_enabled = false
+ bases.list = bases_list
+ bases.used = bases_used
+ bases.found = bases_found
+end
+
+reset()
+
+function bases.use(basename)
+ if basename == "reset" then
+ reset()
+ else
+ basename = file.addsuffix(basename,"xml")
+ if not bases_used[basename] then
+ local t = { basename, nil, nil }
+ bases_used[basename] = t
+ bases_list[#bases_list+1] = t
+ if not bases_enabled then
+ bases_enabled = true
+ xml.registerns("rlx","http://www.pragma-ade.com/schemas/rlx") -- we should be able to do this per xml file
+ end
+ if trace_bases then
+ report_inclusion("registering base %a",basename)
+ end
+ end
+ end
+end
+
+implement { name = "usefigurebase", actions = bases.use, arguments = "string" }
+
+local function bases_find(basename,askedlabel)
+ if trace_bases then
+ report_inclusion("checking for %a in base %a",askedlabel,basename)
+ end
+ basename = file.addsuffix(basename,"xml")
+ local t = bases_found[askedlabel]
+ if t == nil then
+ local base = bases_used[basename]
+ local page = 0
+ if base[2] == nil then
+ -- no yet located
+ for i=1,#figure_paths do
+ local path = resolveprefix(figure_paths[i]) -- we resolve (e.g. jobfile:)
+ local xmlfile = path .. "/" .. basename
+ if io.exists(xmlfile) then
+ base[2] = xmlfile
+ base[3] = xml.load(xmlfile)
+ if trace_bases then
+ report_inclusion("base %a loaded",xmlfile)
+ end
+ break
+ end
+ end
+ end
+ t = false
+ if base[2] and base[3] then -- rlx:library
+ for e in xml.collected(base[3],"/(*:library|figurelibrary)/*:figure/*:label") do
+ page = page + 1
+ if xml.text(e) == askedlabel then
+ t = {
+ base = file.replacesuffix(base[2],"pdf"),
+ format = "pdf",
+ name = xml.text(e,"../*:file"), -- to be checked
+ page = page,
+ }
+ bases_found[askedlabel] = t
+ if trace_bases then
+ report_inclusion("figure %a found in base %a",askedlabel,base[2])
+ end
+ return t
+ end
+ end
+ if trace_bases and not t then
+ report_inclusion("figure %a not found in base %a",askedlabel,base[2])
+ end
+ end
+ end
+ return t
+end
+
+-- we can access sequential or by name
+
+local function bases_locate(askedlabel)
+ for i=1,#bases_list do
+ local entry = bases_list[i]
+ local t = bases_find(entry[1],askedlabel)
+ if t then
+ return t
+ end
+ end
+ return false
+end
+
+function identifiers.base(data)
+ if bases_enabled then
+ local dr, du, ds = data.request, data.used, data.status
+ local fbl = bases_locate(dr.name or dr.label)
+ if fbl then
+ du.page = fbl.page
+ du.format = fbl.format
+ du.fullname = fbl.base
+ ds.fullname = fbl.name
+ ds.format = fbl.format
+ ds.page = fbl.page
+ ds.status = 10
+ end
+ end
+ return data
+end
+
+bases.locate = bases_locate
+bases.find = bases_find
+
+identifiers.list = {
+ identifiers.base,
+ identifiers.default
+}
+
+-- tracing
+
+statistics.register("graphics processing time", function()
+ local nofprocessed = figures.nofprocessed
+ if nofprocessed > 0 then
+ local nofnames, nofbadnames = 0, 0
+ for hash, data in next, figures_found do
+ nofnames = nofnames + 1
+ if data.badname then
+ nofbadnames = nofbadnames + 1
+ end
+ end
+ return format("%s seconds including tex, %s processed images, %s unique asked, %s bad names",
+ statistics.elapsedtime(figures),nofprocessed,nofnames,nofbadnames)
+ else
+ return nil
+ end
+end)
+
+-- helper
+
+function figures.applyratio(width,height,w,h) -- width and height are strings and w and h are numbers
+ if not width or width == "" then
+ if not height or height == "" then
+ return figures.defaultwidth, figures.defaultheight
+ else
+ height = todimen(height)
+ if w and h then
+ return height * w/h, height
+ else
+ return figures.defaultwidth, height
+ end
+ end
+ else
+ width = todimen(width)
+ if not height or height == "" then
+ if w and h then
+ return width, width * h/w
+ else
+ return width, figures.defaultheight
+ end
+ else
+ return width, todimen(height)
+ end
+ end
+end
+
+-- example of simple plugins:
+--
+-- figures.converters.png = {
+-- png = function(oldname,newname,resolution)
+-- local command = string.format('gm convert -depth 1 "%s" "%s"',oldname,newname)
+-- logs.report(string.format("running command %s",command))
+-- os.execute(command)
+-- end,
+-- }
+
+-- local fig = figures.push { name = pdffile }
+-- figures.identify()
+-- figures.check()
+-- local nofpages = fig.used.pages
+-- figures.pop()
+
+-- interfacing
+
+implement {
+ name = "figure_push",
+ scope = "private",
+ actions = figures.push,
+ arguments = {
+ {
+ { "name" },
+ { "label" },
+ { "page" },
+ { "size" },
+ { "object" },
+ { "prefix" },
+ { "cache" },
+ { "format" },
+ { "preset" },
+ { "controls" },
+ { "resources" },
+ { "preview" },
+ { "display" },
+ { "mask" },
+ { "conversion" },
+ { "resolution" },
+ { "color" },
+ { "repeat" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ }
+ }
+}
+
+-- beware, we get a number passed by default
+
+implement { name = "figure_pop", scope = "private", actions = figures.pop }
+implement { name = "figure_done", scope = "private", actions = figures.done }
+implement { name = "figure_dummy", scope = "private", actions = figures.dummy }
+implement { name = "figure_identify", scope = "private", actions = figures.identify }
+implement { name = "figure_scale", scope = "private", actions = figures.scale }
+implement { name = "figure_check", scope = "private", actions = figures.check }
+implement { name = "figure_include", scope = "private", actions = figures.include }
+
+implement {
+ name = "setfigurelookuporder",
+ actions = figures.setorder,
+ arguments = "string"
+}
+
+implement {
+ name = "figure_reset",
+ scope = "private",
+ arguments = { "integer", "dimen", "dimen" },
+ actions = function(box,width,height)
+ figures.boxnumber = box
+ figures.defaultwidth = width
+ figures.defaultheight = height
+ end
+}
+
+-- require("util-lib-imp-gm")
+--
+-- figures.converters.tif.pdf = function(oldname,newname,resolution)
+-- logs.report("graphics","using gm library to convert %a",oldname)
+-- utilities.graphicmagick.convert {
+-- inputname = oldname,
+-- outputname = newname,
+-- }
+-- end
+--
+-- \externalfigure[t:/sources/hakker1b.tiff]
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv
new file mode 100644
index 00000000000..deba82c583d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv
@@ -0,0 +1,797 @@
+%D \module
+%D [ file=grph-inc, % moved from core-fig
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure 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.
+
+% \enabledirectives[graphics.conversion.eps.cleanup.ai]
+
+% \setupexternalfigures[directory=dirfile://./test/**]
+% \externalfigure[crappname(2).eps][frame=on]
+
+% todo: messages
+
+\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion}
+
+\registerctxluafile{grph-inc}{1.001}
+\registerctxluafile{grph-fil}{1.001}
+\registerctxluafile{grph-u3d}{1.001} % this will change
+\registerctxluafile{grph-swf}{1.001} % this will change
+
+\unprotect
+
+%D Including graphics is complicated by the fact that we need to locate them first,
+%D optionally manipulate them and scale then next. Lookups are to be done as efficient
+%D as possible and inclusion of the data might happens only once. In \MKIV\ much of this
+%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's
+%D more powerful, flexible, pluggable and some of the extended functionality has been
+%D moved from modules to the core. The overall functionality is rather stable and has
+%D not changed much over the years.
+
+\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi
+
+\installcorenamespace{externalfigure}
+\installcorenamespace{externalfigureinstance}
+\installcorenamespace{externalfigurecollection}
+
+\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure
+
+\let\setupexternalfigures\setupexternalfigure
+
+\setupexternalfigures[% we really need the defaults
+ \c!method =,
+ \c!label =,
+ \c!size =,
+ \c!conversion =,
+ \c!resolution =,
+ \c!prefix =,
+ \c!cache =,
+ \c!page =\zerocount,
+ \c!display =,
+ \c!mask =,
+ \c!preset =\v!yes,
+ \c!split =,
+ \c!color =,
+ \c!symbol =\v!no,
+ \c!controls =\v!no,
+ \c!resources =,
+ \c!preview =\v!no
+ \c!repeat =\v!no
+ \c!foregroundcolor=,
+ \c!interaction =\v!none,
+ \c!hfactor =,
+ \c!wfactor =,
+ \c!factor =,
+ \c!maxwidth =\externalfigureparameter\c!width,
+ \c!maxheight =\externalfigureparameter\c!height,
+ \c!xscale =,
+ \c!yscale =,
+ \c!scale =,
+ \c!sx =\externalfigureparameter\c!s,
+ \c!sy =\externalfigureparameter\c!s,
+ \c!s =1,
+ \c!width =,
+ \c!height =,
+ \c!lines =,
+ \c!grid =,
+ \c!bodyfont =\bodyfontsize,
+ \c!object =\v!yes,
+ \c!corner =\v!rectangular,
+ \c!frame =\v!off,
+ \c!option =,
+ \c!reset =\v!no,
+ \c!directory =,
+ \c!radius =.5\bodyfontsize,
+ \c!background =,
+ \c!splitcolor =\s!white,
+ \c!order =,
+ \c!equalwidth =,
+ \c!equalheight =,
+ \c!location ={\v!local,\v!global},
+ \c!frames =\v!off,
+ \c!ymax =24,
+ \c!xmax =,
+ \c!align =\v!none, % New, for Tacos extremely large graphics.
+ ]
+
+%D Defining figures.
+
+\newcount\c_grph_include_nesting
+
+\newtoks \everyexternalfigureresets % for the moment still public
+\newtoks \everyexternalfigurechecks % for the moment still public
+
+% \useexternalfigure[alpha][koe]
+% \useexternalfigure[beta] [koe] [breedte=1cm]
+% \useexternalfigure[gamma][koe][alpha]
+% \useexternalfigure[delta][koe][alpha][breedte=2cm]
+%
+% volle breedte: \externalfigure[koe] \par
+% 3cm breed: \externalfigure[koe] [breedte=3cm] \par
+% volle breedte: \externalfigure[alpha] \par
+% 1cm breed: \externalfigure[beta] \par
+% volle breedte: \externalfigure[gamma] \par
+% 2cm breed: \externalfigure[delta] \par
+% 4cm breed: \externalfigure[beta] [breedte=4cm] \par
+% 5cm breed: \externalfigure[gamma][breedte=5cm] \par
+%
+% \defineexternalfigure[a][width=10cm]
+% \defineexternalfigure[b][width=5cm]
+% \externalfigure[cow][a]
+% \externalfigure[cow][b][height=8cm]
+%
+% \useexternalfigure[x][cow][width=10cm,height=1cm]
+% \externalfigure[x]
+% \externalfigure[x][width=3cm]
+%
+% [label] [filename]
+% [label] [filename] [parent]
+% [label] [filename] [parent] [settings]
+% [label] [filename] [settings]
+%
+% new: more convenient/efficient than
+%
+% \use..[a][a][setting] \externalfigure[b][a]
+%
+% is equivalent to:
+%
+% \def..[a][setting] \externalfigure[b][a]
+%
+% see x-res modules for usage:
+%
+% \defineexternalfigure[name][settings]
+
+%D Defining is persistent, i.e.\ when you redefine an instance,
+%D the already set parameters need to be set again or otherwise
+%D the old values will be used.
+
+%D New: \type {method=auto}: strips suffix and uses \quote {order} which is handy in
+%D some of four workflows where sources are used for web and print and where
+%D the web tools need a suffix (like gif) which we don't want as we want a high
+%D quality format.
+
+\newconditional\c_grph_include_trace_inheritance
+
+\installtextracker
+ {graphics.inheritance}
+ {\settrue \c_grph_include_trace_inheritance}
+ {\setfalse\c_grph_include_trace_inheritance}
+
+\installcorenamespace{externalfiguredefinition}
+
+% \unexpanded\def\defineexternalfigure
+% {\dodoubleargument\grph_include_define}
+%
+% \def\grph_include_define[#1][#2]%
+% {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}}
+
+\let\defineexternalfigures\defineexternalfigure
+
+\unexpanded\def\useexternalfigure
+ {\doquadrupleempty\grph_include_use}
+
+% label file parent settings
+% label file settings
+% label file parent
+
+\def\grph_include_use[#1][#2][#3][#4]%
+ {\doifelsenothing{#1}
+ {\doifsomething{#2}
+ {\doifelseassignment{#3}
+ {\grph_include_use_indeed{#2}{#2}{#3}{#4}}
+ {\grph_include_use_indeed{#2}{#2}\empty{#4}}}}
+ {\doifelsenothing{#2}
+ {\doifelseassignment{#3}
+ {\grph_include_use_indeed{#1}{#1}\empty{#3}}
+ {\grph_include_use_indeed{#1}{#1}{#3}{#4}}}
+ {\doifelseassignment{#3}
+ {\grph_include_use_indeed{#1}{#2}\empty{#3}}
+ {\grph_include_use_indeed{#1}{#2}{#3}{#4}}}}}
+
+\def\grph_include_use_indeed#1#2#3#4%
+ {\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}%
+ \grph_include_analyze_collection[#2][#4]}
+
+% inclusion
+
+\unexpanded\def\externalfigure
+ {\dotripleempty\grph_include_figure}
+
+\def\grph_include_figure[#1][#2][#3]%
+ {\docheckassignment{#2}%
+ \ifassignment
+ \grph_include_place[#1][][#2]%
+ \else
+ \grph_include_place[#1][#2][#3]%
+ \fi}
+
+% todo: chain them
+
+\def\grph_include_setup#1#2#3% name parent settings
+ {\edef\m_grph_include_name {#1}%
+ \edef\m_grph_include_parent{#2}%
+ \ifx\m_grph_include_name\empty \else
+ \let\p_grph_include_name\m_grph_include_name
+ \fi
+ \ifx\m_grph_include_parent\empty \else
+ \grph_include_inherit_from_parent\m_grph_include_parent
+ \fi
+ \setupcurrentexternalfigure[#3]}
+
+% \def\grph_include_inherit_from_parent#1%
+% {\ifcsname\??externalfiguredefinition#1\endcsname
+% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
+% \csname\??externalfiguredefinition#1\endcsname
+% \fi
+% \ifcsname\??externalfigureinstance#1\endcsname
+% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
+% \csname\??externalfigureinstance#1\endcsname
+% \fi}
+
+\def\grph_include_inherit_from_parent#1%
+ {%\ifcsname\??externalfiguredefinition#1\endcsname
+ % \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
+ % \csname\??externalfiguredefinition#1\endcsname
+ %\fi
+ \ifcsname\??externalfigure#1:\s!parent\endcsname
+ \let\currentexternalfigure#1%
+ \fi
+ \ifcsname\??externalfigureinstance#1\endcsname
+ \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
+ \csname\??externalfigureinstance#1\endcsname
+ \fi}
+
+\newtoks\t_grph_include_local_settings
+
+\appendtoks
+ \let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode (probably no longer needed)
+ %
+ \dontcomplain
+ \restorecatcodes
+ \forgetall
+\to \t_grph_include_local_settings
+
+\def\grph_include_place_inherit
+ {\ifconditional\c_grph_include_trace_inheritance
+ \writestatus\m!figures{label: \p_grph_include_label, name: \p_grph_include_name, parent: \p_grph_include_parent}%
+ \fi
+ \ifx\p_grph_include_parent\empty
+ % nothing to be done
+ \else\ifx\p_grph_include_parent\p_grph_include_label
+ % redundant
+ \else
+ \grph_include_inherit_from_parent\p_grph_include_parent
+ \fi\fi
+ \ifx\p_grph_include_label\empty
+ % nothing to be done
+ \else
+ \grph_include_inherit_from_parent\p_grph_include_label
+ \fi}
+
+\def\grph_include_place[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
+ {\bgroup
+ \advance\c_grph_include_nesting\plusone
+ \edef\currentexternalfigure{\the\c_grph_include_nesting}%
+ \checkexternalfigureparent % each inherits from the root
+ %
+ \the\everyexternalfigureresets
+ %
+ \edef\p_grph_include_label{#1}%
+ \let\p_grph_include_name\p_grph_include_label
+ \docheckassignment{#2}%
+ \ifassignment
+ % [label] [settings]
+ \let\p_grph_include_parent\p_grph_include_label
+ \grph_include_place_inherit
+ \setupcurrentexternalfigure[#2]%
+ \else
+ % [label] [parent] [settings]
+ \edef\p_grph_include_parent{#2}%
+ \ifx\p_grph_include_parent\empty
+ \let\p_grph_include_parent\p_grph_include_label
+ \fi
+ \grph_include_place_inherit
+ \setupcurrentexternalfigure[#3]%
+ \fi
+ %
+ \the\everyexternalfigurechecks
+ %
+ \the\t_grph_include_local_settings
+ %
+ \edef\p_width {\externalfigureparameter\c!width}%
+ \edef\p_height{\externalfigureparameter\c!height}%
+ \edef\p_label {\externalfigureparameter\c!label}%
+ %
+ \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}%
+ size {\externalfigureparameter\c!size}%
+ object {\externalfigureparameter\c!object}%
+ prefix {\externalfigureparameter\c!prefix}%
+ cache {\externalfigureparameter\c!cache}%
+ format {\externalfigureparameter\c!method}%
+ preset {\externalfigureparameter\c!prefix}%
+ controls {\externalfigureparameter\c!controls}%
+ resources {\externalfigureparameter\c!resources}%
+ preview {\externalfigureparameter\c!preview}%
+ display {\externalfigureparameter\c!display}%
+ mask {\externalfigureparameter\c!mask}%
+ conversion {\externalfigureparameter\c!conversion}%
+ resolution {\externalfigureparameter\c!resolution}%
+ color {\internalspotcolorparent{\externalfigureparameter\c!color}}% hack is needed
+ repeat {\externalfigureparameter\c!repeat}%
+ \ifx\p_width\empty \else
+ width \dimexpr\p_width\relax
+ \fi
+ \ifx\p_height\empty \else
+ height \dimexpr\p_height\relax
+ \fi
+ \relax
+ \clf_figure_identify
+ \relax
+ \ifconditional\c_grph_include_test_only
+ \ifcase\figurestatus \else
+ \clf_figure_check
+ \clf_figure_dummy
+ \clf_figure_scale
+ \clf_figure_done
+ \fi
+ \grph_include_set_mode
+ \else
+ \ifcase\figurestatus
+ \clf_figure_dummy
+ \clf_figure_scale
+ \else
+ \clf_figure_check
+ \clf_figure_include
+ \clf_figure_scale
+ \fi
+ \clf_figure_done
+ \grph_include_set_mode
+ \grph_include_finalize
+ \fi
+ \clf_figure_pop
+ \dotagfigure
+ \naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}%
+ \dostoptagged
+ \egroup}
+
+%D Scaling:
+
+\let\dowithfigure\relax % name might change (into a proper hook)
+
+\unexpanded\def\doscalefigure % used at lua end
+ {\global\setbox\foundexternalfigure\vpack{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}
+
+\definescale % some day we will inherit
+ [\v!figure]
+ [\c!hfactor =\externalfigureparameter\c!hfactor,
+ \c!wfactor =\externalfigureparameter\c!wfactor,
+ \c!factor =\externalfigureparameter\c!factor,
+ \c!maxwidth =\externalfigureparameter\c!maxwidth ,
+ \c!maxheight =\externalfigureparameter\c!maxheight,
+ \c!equalwidth =\externalfigureparameter\c!equalwidth ,
+ \c!equalheight=\externalfigureparameter\c!equalheight,
+ \c!xscale =\externalfigureparameter\c!xscale,
+ \c!yscale =\externalfigureparameter\c!yscale,
+ \c!scale =\externalfigureparameter\c!scale,
+ \c!sx =\externalfigureparameter\c!sx,
+ \c!sy =\externalfigureparameter\c!sy,
+ \c!s =\externalfigureparameter\c!s,
+ \c!width =\externalfigureparameter\c!width,
+ \c!height =\externalfigureparameter\c!height,
+ \c!lines =\externalfigureparameter\c!lines]
+
+% % this will become:
+%
+% \unexpanded\def\doscalefigure % used at lua end
+% {\global\setbox\foundexternalfigure\vbox\bgroup
+% \bgroup
+% \let\currentscale\currentexternalfigure
+% \let\scaleparameter\externalfigureparameter
+% \dowithnextboxcs\grph_scale_finish\hbox{\dowithfigure{\box\foundexternalfigure}}%
+% \egroup}
+%
+% % or even better:
+%
+% \def\grph_scale_inherited#1%
+% {\bgroup
+% \expandafter\let\expandafter\currentscale \csname current#1\endcsname
+% \expandafter\let\expandafter\scaleparameter\csname #1parameter\endcsname
+% \dowithnextboxcs\grph_scale_finish\hbox}
+%
+% \unexpanded\def\doscalefigure % used at lua end
+% {\global\setbox\foundexternalfigure\vbox\bgroup
+% \grph_scale_inherited{externalfigure}{\dowithfigure{\box\foundexternalfigure}}%
+% \egroup}
+
+%D You can register additional suffixes with the following command:
+%D
+%D \starttyping
+%D \definegraphictypesynonym[jbig] [jb2]
+%D \definegraphictypesynonym[jbig2][jb2]
+%D \definegraphictypesynonym[jbg] [jb2]
+%D \stoptyping
+
+\unexpanded\def\definegraphictypesynonym
+ {\dodoubleargument\grph_include_set_type_synonym}
+
+\def\grph_include_set_type_synonym[#1][#2]%
+ {\clf_registerfiguresuffix{#1}{#2}}
+
+%D Additional paths can be installed with the regular setup command. The next
+%D macro picks up the list.
+
+\unexpanded\def\setfigurepathlist
+ {\clf_setfigurepaths{\externalfigureparameter\c!location}{\externalfigureparameter\c!directory}}
+
+%D Variables:
+
+\newbox \foundexternalfigure
+\newtoks\externalfigurepostprocessors
+
+\def\defaultfigurewidth {8\lineheight}
+\def\defaultfigureheight {6\lineheight}
+
+\def\figurestatus {\numexpr\clf_figurestatus{status}{0}\relax} % number: 0 = not found
+\def\figurewidth {\clf_figurestatus{width}{0}sp}
+\def\figureheight {\clf_figurestatus{height}{0}sp}
+\def\figurexscale {\clf_figurestatus{xscale}{1}}
+\def\figureyscale {\clf_figurestatus{yscale}{1}}
+
+\def\figuresize {\clf_figurerequest{size}{}}
+\def\figurelabel {\clf_figurerequest{label}{}}
+\def\figurefileoriginal {\clf_figurerequest{name}{}}
+\def\figurefilepage {\clf_figurerequest{page}{1}}
+\def\figurefileoptions {\clf_figurerequest{options}{}}
+\def\figurefileconversion{\clf_figurerequest{conversion}{}}
+\def\figurefilecache {\clf_figurerequest{cache}{}}
+\def\figurefileprefix {\clf_figurerequest{prefix}{}}
+
+\def\figurenaturalwidth {\clf_figureused{width}{\number\dimexpr\defaultfigurewidth\relax}sp}
+\def\figurenaturalheight {\clf_figureused{height}{\number\dimexpr\defaultfigureheight\relax}sp}
+\def\figurexresolution {\clf_figureused{xresolution}{0}}
+\def\figureyresolution {\clf_figureused{yresolution}{0}}
+\def\figurexsize {\clf_figureused{xsize}{0}}
+\def\figureysize {\clf_figureused{ysize}{0}}
+\def\figurecolordepth {\clf_figureused{colordepth}{0}}
+\def\figuredepth {\clf_figureused{depth}{0}}
+
+\def\figurefullname {\clf_figureused{fullname}{}}
+\def\noffigurepages {\clf_figureused{pages}{0}}
+
+\def\figurefilepath {\clf_figurefilepath}
+\def\figurefilename {\clf_figurefilename}
+\def\figurefiletype {\clf_figurefiletype}
+
+\let\naturalfigurewidth \figurenaturalwidth
+\let\naturalfigureheight \figurenaturalheight
+
+\let\figurescalewidth \figurewidth
+\let\figurescaleheight \figureheight
+\let\figurescalexscale \figurexscale
+\let\figurescaleyscale \figureyscale
+
+%D Abuse:
+%D
+%D \starttyping
+%D \externalfigure[rubish.pdf] \ifcase\figurestatus\relax \ctxlua{os.exit(999)} \fi
+%D \stoptyping
+
+%D Calculating:
+
+% \enabletrackers[figures.conversion]
+% \externalfigure[demo.svg]
+% \externalfigure[demo.svg][conversion=png]
+
+%D The following registers are used (if only to be downward compatible).
+
+\newconditional\c_grph_include_skip
+\newconditional\c_grph_include_test_only
+\newconditional\c_grph_include_level \setfalse\c_grph_include_level % true=background false=normal
+\newconditional\c_grph_include_flush \settrue \c_grph_include_flush % true=place false=ignore
+
+\newsystemmode\v!figure
+
+\def\grph_include_set_mode
+ {\ifcase\figurestatus
+ \global\resetsystemmode\v!figure % todo, also: \v!resource
+ \else
+ \global\setsystemmode \v!figure % todo, also: \v!resource
+ \fi}
+
+\appendtoks
+ \clf_setfigurepaths
+ {\externalfigureparameter\c!location}%
+ {\externalfigureparameter\c!directory}%
+ \clf_figure_reset
+ \foundexternalfigure
+ \defaultfigurewidth
+ \defaultfigureheight
+ \relax
+\to \everyexternalfigureresets
+
+\appendtoks
+ \edef\p_option{\externalfigureparameter\c!option}%
+ \ifx\p_option\v!frame
+ \setfalse\c_grph_include_skip
+ \letexternalfigureparameter\c!frame\v!on
+ \else\ifx\p_option\v!empty
+ \settrue\c_grph_include_skip
+ \letexternalfigureparameter\c!frame\v!off
+ \else
+ \setfalse\c_grph_include_skip
+ \fi\fi
+ % fake color in gray bitmaps, assumes that
+ % a transparent color is used
+ \edef\p_foregroundcolor{\externalfigureparameter\c!foregroundcolor}%
+ \ifx\p_foregroundcolor\empty \else
+ \setexternalfigureparameter\c!background{\v!foreground,\v!color}%
+ \letexternalfigureparameter\c!backgroundcolor\p_foregroundcolor
+ \fi
+\to \everyexternalfigurechecks
+
+%D Internal graphics are handled at the \TEX\ end:
+
+\def\grph_include_process_tex#1%
+ {\framed
+ [\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off,
+ \c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit]
+ {\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here!
+
+% used al lua end:
+
+\unexpanded\def\docheckfigurebuffer #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\getbuffer[#1]}}}
+\unexpanded\def\docheckfiguretex #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\input{#1}}}}
+\unexpanded\def\docheckfigurecld #1{\global\setbox\foundexternalfigure\vbox {\cldprocessfile{#1}}}
+\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
+ {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup
+ \vss
+ \ht\foundexternalfigure\zeropoint
+ \hpack to \wd\foundexternalfigure\bgroup
+ \box\foundexternalfigure
+ \hss
+ \egroup
+ \egroup}
+
+\unexpanded\def\startfoundexternalfigure#1#2% ht wd
+ {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup}
+
+\unexpanded\def\stopfoundexternalfigure
+ {\hss\egroup\egroup}
+
+\unexpanded\def\emptyfoundexternalfigure % sort of obsolete
+ {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight
+ \stopfoundexternalfigure}
+
+% \doifmodeelse{*\v!last}
+% {\settrue \c_grph_include_flush}
+% {\setfalse\c_grph_include_flush}%
+
+\def\grph_include_finalize
+ {\global\setbox\foundexternalfigure\vbox
+ {\ifcase\figurestatus
+ \letexternalfigureparameter\c!frame\v!on
+ \fi
+ \ifconditional\c_grph_include_flush
+ \ifconditional\c_grph_include_level % probably background
+ \ifconditional\c_grph_include_skip
+ % nothing
+ \fakebox\foundexternalfigure
+ \else\ifcase\figurestatus
+ % nothing
+ \else
+ \the\externalfigurepostprocessors
+ \box\foundexternalfigure
+ \fi\fi
+ \else
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \settrue\c_grph_include_level
+ \ifconditional\c_grph_include_skip
+ \ifcase\figurestatus
+ \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
+ \else
+ \grph_include_replacement\figurelabel\figurefullname{skipped}%
+ \fi
+ \else\ifcase\figurestatus
+ \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
+ \else
+ \the\externalfigurepostprocessors
+ \edef\p_reset{\externalfigureparameter\c!reset}%
+ \ifx\p_reset\v!yes
+ \wd\foundexternalfigure\figurewidth
+ \ht\foundexternalfigure\figureheight
+ \dp\foundexternalfigure\zeropoint
+ \box\foundexternalfigure
+ \else
+ \letexternalfigureparameter\c!offset\v!overlay
+ \letexternalfigureparameter\c!width \figurewidth
+ \letexternalfigureparameter\c!height\figureheight
+% \letexternalfigureparameter\c!align \v!middle
+% \letexternalfigureparameter\c!autowidth\v!no
+ \inheritedexternalfigureframed{\box\foundexternalfigure}%
+ \fi
+ \fi\fi
+ \fi
+ \else
+ % maybe also \the\externalfigurepostprocessors
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \fi}}
+
+\let\feedbackexternalfigure\relax % hook
+
+\unexpanded\def\getfiguredimensions
+ {\dodoubleempty\grph_include_get_dimensions}
+
+\def\grph_include_get_dimensions[#1][#2]%
+ {\startnointerference
+ \settrue\c_grph_include_test_only
+ \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
+ \stopnointerference}
+
+\unexpanded\def\doifelsefigure#1%
+ {\getfiguredimensions[#1]% so data is available !
+ \ifcase\figurestatus
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doiffigureelse\doifelsefigure
+
+% No placement, handy for preprocessing:
+
+\unexpanded\def\registerexternalfigure
+ {\dotripleempty\grph_include_register}
+
+\def\grph_include_register[#1][#2][#3]%
+ {\startnointerference
+ \c_grph_include_test_only
+ \setfalse\c_grph_include_flush % == test ?
+ \externalfigure[#1][#2][#3]% or
+ \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
+ \stopnointerference}
+
+% Helpers will be replaced when xforms are accessible at the lua end but then
+% we need to do the object offset there too.
+
+\unexpanded\def\dosetfigureobject#1#2%
+ {\setobject{#1}{#2}\vpack{\box\foundexternalfigure}}
+
+\unexpanded\def\doboxfigureobject#1#2%
+ {\global\setbox\foundexternalfigure\vpack{\getobject{#1}{#2}}} % probably one vbox too many
+
+% Figure bases
+
+\unexpanded\def\usefigurebase[#1]%
+ {\clf_usefigurebase{#1}}
+
+\appendtoks
+ \setfigurepathlist % the path may be used elsewhere too (as in x-res-04)
+\to \everysetupexternalfigure
+
+\appendtoks
+ \clf_setfigurelookuporder{\externalfigureparameter\c!order}%
+\to \everysetupexternalfigure
+
+\definecolor[missingfigurecolor][s=.8]
+
+\def\grph_include_replacement#1#2#3%
+ {\bgroup
+ \letexternalfigureparameter\c!width\figurewidth
+ \letexternalfigureparameter\c!height\figureheight
+ \letexternalfigureparameter\c!background\v!color
+ \setexternalfigureparameter\c!backgroundcolor{missingfigurecolor}%
+ \setexternalfigureparameter\c!align{\v!middle,\v!lohi}% we default to \v!none
+ \inheritedexternalfigureframed
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ file: \expanded{\verbatimstring{#2}}\\%
+ state: \expanded{\verbatimstring{#3}}}%
+ \egroup}
+
+% maybe setuphandler
+
+\newconditional\c_grph_include_in_collection
+
+\newdimen\d_grph_include_collection_minwidth
+\newdimen\d_grph_include_collection_maxwidth
+\newdimen\d_grph_include_collection_minheight
+\newdimen\d_grph_include_collection_maxheight
+
+\def\grph_include_analyze_collection[#1][#2]%
+ {\ifconditional\c_grph_include_in_collection
+ \setfalse\c_grph_include_in_collection
+ \getfiguredimensions[#1][#2]%
+ \settrue\c_grph_include_in_collection
+ \scratchdimen\naturalfigurewidth
+ \ifdim\scratchdimen>\d_grph_include_collection_maxwidth \d_grph_include_collection_maxwidth \scratchdimen \fi
+ \ifdim\scratchdimen<\d_grph_include_collection_minwidth \d_grph_include_collection_minwidth \scratchdimen \fi
+ \scratchdimen\naturalfigureheight
+ \ifdim\scratchdimen>\d_grph_include_collection_maxheight \d_grph_include_collection_maxheight\scratchdimen \fi
+ \ifdim\scratchdimen<\d_grph_include_collection_minheight \d_grph_include_collection_minheight\scratchdimen \fi
+ \fi}
+
+\unexpanded\def\startexternalfigurecollection[#1]%
+ {\begingroup
+ \def\currentexternalfigurecollection{#1}%
+ \settrue\c_grph_include_in_collection
+ \d_grph_include_collection_minwidth \maxdimen
+ \d_grph_include_collection_maxwidth \zeropoint
+ \d_grph_include_collection_minheight\maxdimen
+ \d_grph_include_collection_maxheight\zeropoint}
+
+\unexpanded\def\stopexternalfigurecollection
+ {\setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minwidth }{\the\d_grph_include_collection_minwidth }%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxwidth }{\the\d_grph_include_collection_maxwidth }%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minheight}{\the\d_grph_include_collection_minheight}%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxheight}{\the\d_grph_include_collection_maxheight}%
+ \endgroup}
+
+\def\externalfigurecollectionparameter#1#2%
+ {\csname
+ \ifcsname\??externalfigurecollection#1:#2\endcsname
+ \??externalfigurecollection#1:#2%
+ \else
+ \s!empty
+ \fi
+ \endcsname}
+
+\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth }
+\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth }
+\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight}
+\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight}
+
+\let\efcparameter\externalfigurecollectionparameter % still needed ?
+\let\efcminwidth \externalfigurecollectionminwidth % still needed ?
+\let\efcmaxwidth \externalfigurecollectionmaxwidth % still needed ?
+\let\efcminheight\externalfigurecollectionminheight % still needed ?
+\let\efcmaxheight\externalfigurecollectionmaxheight % still needed ?
+
+% \startexternalfigurecollection[name]
+% \useexternalfigure[cow] [cow.pdf]
+% \useexternalfigure[mill][mill.png]
+% \stopexternalfigurecollection
+% \starttext
+% \bTABLE
+% \bTR
+% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD
+% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD
+% \eTR
+% \eTABLE
+% \stoptext
+
+\unexpanded\def\showexternalfigures
+ {\writestatus\m!system{the \string\showexternalfigures\space command is not (yet) implemented in mkiv}}
+
+\unexpanded\def\overlayfigure#1%
+ {\externalfigure[#1][\c!width=\d_overlay_width,\c!height=\d_overlay_height]}
+
+% Bonus:
+
+\useexternalfigure
+ [\v!buffer]
+ [\jobname.buffer]
+ [\c!object=\v!no]
+
+% Another one:
+
+\defineexternalfigure
+ [\v!inline]
+ [\c!height=\lineheight]
+
+\unexpanded\def\inlinefigure[#1]{\dontleavehmode\sbox{\externalfigure[#1][\v!inline]}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-raw.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-raw.lua
new file mode 100644
index 00000000000..62e96fcc9d7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-raw.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['grph-raw'] = {
+ version = 1.001,
+ comment = "companion to grph-raw.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module is for Mojca, who wanted something like this for
+-- her gnuplot project. It's somewhat premliminary code but it
+-- works ok for that purpose.
+
+local tonumber = tonumber
+
+local report_bitmap = logs.reporter("graphics","bitmaps")
+
+local context = context
+local texsp = tex.sp
+
+function figures.bitmapimage(t)
+ local data = t.data
+ local xresolution = tonumber(t.xresolution)
+ local yresolution = tonumber(t.yresolution)
+ if data and xresolution and yresolution then
+ local width, height = t.width or "", t.height or ""
+ local n = backends.nodeinjections.injectbitmap {
+ xresolution = xresolution,
+ yresolution = yresolution,
+ width = width ~= "" and texsp(width) or nil,
+ height = height ~= "" and texsp(height) or nil,
+ data = data,
+ colorspace = t.colorspace,
+ }
+ if n then
+ context.hbox(n)
+ else
+ report_bitmap("format no supported by backend")
+ end
+ else
+ report_bitmap("invalid specification")
+ end
+end
+
+interfaces.implement {
+ name = "bitmapimage",
+ actions = figures.bitmapimage,
+ arguments = {
+ {
+ { "data" },
+ { "colorspace" },
+ { "width" },
+ { "height" },
+ { "xresolution" },
+ { "yresolution" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-raw.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-raw.mkiv
new file mode 100644
index 00000000000..8978ba2671b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-raw.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=grph-raw,
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Raw Bitmaps,
+%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 Graphic Macros / Raw Bitmaps}
+
+%D \startluacode
+%D function document.TestBitmap(nx,ny)
+%D local random = math.random
+%D local maxbit = 2^24
+%D for i=1,nx do
+%D for i=1,ny do
+%D context("%06x",random(0,maxbit))
+%D end
+%D end
+%D end
+%D \stopluacode
+%D
+%D \def\TestBitmap#1#2{\ctxlua{document.TestBitmap(#1,#2)}}
+%D
+%D \blank
+%D
+%D \startMPcode
+%D draw textext("\bitmapimage[x=100,y=100]{\TestBitmap{100}{100}}") xsized 10cm ;
+%D \stopMPcode
+%D
+%D \blank
+%D
+%D \startMPcode
+%D draw textext("\bitmapimage[x=200,y=50]{\TestBitmap{50}{200}}") xsized 10cm ;
+%D \stopMPcode
+
+\registerctxluafile{grph-raw}{1.001}
+
+\unprotect
+
+\unexpanded\def\bitmapimage[#1]#2%
+ {\hbox\bgroup
+ \getdummyparameters[\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]%
+ \clf_bitmapimage
+ data {#2}%
+ colorspace {\directdummyparameter\c!color}%
+ width {\directdummyparameter\c!width}%
+ height {\directdummyparameter\c!height}%
+ xresolution {\directdummyparameter\c!x}%
+ yresolution {\directdummyparameter\c!y}%
+ \relax
+ \egroup}
+
+\unexpanded\def\startbitmapimage[#1]#2\stopbitmapimage
+ {\bitmapimage[#1]{#2}}
+
+\let\stopbitmapimage\relax
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua
new file mode 100644
index 00000000000..5d3cb8ad5d1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua
@@ -0,0 +1,185 @@
+if not modules then modules = { } end modules ['grph-rul'] = {
+ version = 1.001,
+ comment = "companion to grph-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+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 getattribute = tex.getattribute
+
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local mpcolor = attributes.colors.mpcolor
+
+local floor = math.floor
+local random = math.random
+
+do
+
+ local simplemetapost = metapost.simple
+ local cachesize = 0
+ local maxcachesize = 256*1024
+ local cachethreshold = 1024
+
+ -- local maxcachesize = 8*1024
+ -- local cachethreshold = 1024/2
+
+ local cache = table.setmetatableindex(function(t,k)
+ local v = simplemetapost("rulefun",k) -- w, h, d
+ cachesize = cachesize + #v
+ if cachesize > maxcachesize then
+ -- print("old",cachesize)
+ for k, v in next, t do
+ local n = #v
+ if n > cachethreshold then
+ t[k] = nil
+ cachesize = cachesize - n
+ end
+ end
+ -- print("new",cachesize)
+ end
+ -- print(cachesize,maxcachesize,cachethreshold,#v)
+ t[k] = v
+ return v
+ end)
+
+ local replacer = utilities.templates.replacer
+
+ local predefined = {
+ ["fake:word"] = replacer [[
+FakeWord(%width%,%height%,%depth%,%line%,%color%);
+ ]],
+ ["fake:rule"] = replacer[[
+FakeRule(%width%,%height%,%depth%,%line%,%color%);
+ ]],
+ ["fake:rest"] = replacer [[
+RuleWidth := %width% ;
+RuleHeight := %height% ;
+RuleDepth := %depth% ;
+RuleThickness := %line% ;
+RuleFactor := %factor% ;
+RuleOffset := %offset% ;
+def RuleColor = %color% enddef ;
+%data%;
+ ]]
+ }
+
+ 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),
+ }
+ local m = cache[code]
+ if m and m ~= "" then
+ pdfprint("direct",m)
+ end
+ end
+
+end
+
+do
+
+ local f_rectangle = string.formatters["%F w %F %F %F %F re %s"]
+ local f_radtangle = string.formatters[ [[
+ %F w %F %F m
+ %F %F l %F %F %F %F y
+ %F %F l %F %F %F %F y
+ %F %F l %F %F %F %F y
+ %F %F l %F %F %F %F y
+ h %s
+ ]] ]
+
+ ruleactions.fill = function(p,h,v,i,n)
+ local l = (p.line or 65536)*bpfactor
+ local r = p and (p.radius or 0)*bpfactor or 0
+ local w = h * bpfactor
+ local h = v * bpfactor
+ local m = nil
+ local t = i == "fill" and "f" or "s"
+ local o = l / 2
+ if r > 0 then
+ w = w - o
+ h = h - o
+ m = f_radtangle(l, r,o, w-r,o, w,o,w,r, w,h-r, w,h,w-r,h, r,h, o,h,o,h-r, o,r, o,o,r,o, t)
+ else
+ w = w - l
+ h = h - l
+ m = f_rectangle(l,o,o,w,h,t)
+ end
+ pdfprint("direct",m)
+ end
+
+ ruleactions.draw = ruleactions.fill
+ ruleactions.stroke = ruleactions.fill
+
+end
+
+interfaces.implement {
+ name = "frule",
+ arguments = { {
+ { "width", "dimension" },
+ { "height", "dimension" },
+ { "depth", "dimension" },
+ { "radius", "dimension" },
+ { "line", "dimension" },
+ { "type", "string" },
+ { "data", "string" },
+ { "name", "string" },
+ } } ,
+ actions = function(t)
+ if t.type == "mp" then
+ t.ma = getattribute(a_colorspace) or 1
+ t.ca = getattribute(a_color)
+ t.ta = getattribute(a_transparency)
+ end
+ local r = userrule(t)
+ context(r)
+ end
+}
+
+interfaces.implement {
+ name = "fakeword",
+ arguments = { {
+ { "factor", "dimension" },
+ { "name", "string" }, -- can be type
+ { "min", "dimension" },
+ { "max", "dimension" },
+ { "n", "integer" },
+ } } ,
+ actions = function(t)
+ local factor = t.factor or 0
+ local rule = userrule {
+ height = 1.25*factor,
+ depth = 0.25*factor,
+ width = floor(random(t.min,t.max)/10000) * 10000,
+ line = 0.10*factor,
+ ma = getattribute(a_colorspace) or 1,
+ ca = getattribute(a_color),
+ ta = getattribute(a_transparency),
+ type = "mp",
+ name = t.name,
+ }
+ context(rule)
+ end
+}
+
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-rul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.mkiv
new file mode 100644
index 00000000000..98aab36506e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.mkiv
@@ -0,0 +1,89 @@
+%D \module
+%D [ file=grph-rul,
+%D version=2016.02.05, % from experiments
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Rule Trickery,
+%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 Graphic Macros / Rule Trickery}
+
+\registerctxluafile{grph-rul}{1.001}
+
+\unprotect
+
+\unexpanded\def\frule{\relax\clf_frule} % kind of low level
+
+% just for fun:
+
+% \defineoverlay[normalframe]
+% [\frule
+% width \overlaywidth
+% height\overlayheight
+% line \overlaylinewidth
+% \relax]
+
+% \defineoverlay[ovalframe]
+% [\frule
+% width \overlaywidth
+% height \overlayheight
+% line \overlaylinewidth
+% radius \overlayradius
+% \relax]
+
+\protect \endinput
+
+% \starttext
+%
+% \testfeatureonce{25}{\dontleavehmode
+% \ruledhbox\bgroup
+% \red \frule width 2cm height 2cm depth 1cm radius 2mm line 2pt type fill\relax
+% \hskip-2cm
+% \green \frule width 2cm height 2cm depth 1cm radius 2mm line 2pt\relax
+% \egroup
+% \space}
+%
+% \blank
+%
+% \startuseMPgraphic{demoshape:back}
+% fill
+% unitcircle xysized (RuleWidth,RuleHeight+RuleDepth)
+% withcolor RuleColor ;
+% \stopuseMPgraphic
+%
+% \startuseMPgraphic{demoshape:fore}
+% draw
+% unitcircle xysized (RuleWidth,RuleHeight+RuleDepth)
+% withcolor RuleColor
+% withpen pencircle scaled RuleThickness ;
+% \stopuseMPgraphic
+%
+% \testfeatureonce{100}{\dontleavehmode
+% \ruledhbox\bgroup
+% \red \frule width 1cm height 3mm depth 1mm type mp line 2pt data {\includeMPgraphic{demoshape:back}}\relax
+% \hskip-1cm
+% \green \frule width 1cm height 3mm depth 1mm type mp line 2pt data {\includeMPgraphic{demoshape:fore}}\relax
+% \egroup
+% \space}
+%
+% \blank
+%
+% \dontleavehmode
+% \testfeatureonce{1}{\setbox\scratchbox\hbox{\framed {test}}}
+% \framed {test}
+% \testfeatureonce{1}{\setbox\scratchbox\hbox{\framed[background=normalframe,frame=off]{test}}}
+% \framed[background=normalframe,frame=off]{test}
+% \testfeatureonce{1}{\setbox\scratchbox\hbox{\framed[corner=round] {test}}}
+% \framed[corner=round] {test}
+% \testfeatureonce{1}{\setbox\scratchbox\hbox{\framed[background=ovalframe,frame=off] {test}}}
+% \framed[background=ovalframe,frame=off] {test}
+% \testfeatureonce{1}{\setbox\scratchbox\hbox{\framed[background=ovalframe,frame=on] {test}}}
+% \framed[background=ovalframe,frame=on] {test}
+%
+% \stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua
new file mode 100644
index 00000000000..8c28b76afae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua
@@ -0,0 +1,94 @@
+if not modules then modules = { } end modules ['grph-swf'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- maybe: backends.codeinjections.insertswf
+
+local sub, format, match, byte = string.sub, string.format, string.match, string.byte
+local concat = table.concat
+local floor = math.floor
+local tonumber = tonumber
+
+local readstring = io.readstring
+local readnumber = io.readnumber
+local tobitstring = number.tobitstring
+local todimen = number.todimen
+local nodeinjections = backends.nodeinjections
+local figures = figures
+local context = context
+
+local function getheader(name)
+ local f = io.open(name,"rb")
+ if not f then
+ return
+ end
+ local signature = readstring(f,3) -- F=uncompressed, C=compressed (zlib)
+ local version = readnumber(f,1)
+ local filelength = readnumber(f,-4)
+ local compressed = sub(signature,1,1) == "C"
+ local buffer
+ if compressed then
+ buffer = zlib.decompress(f:read('*a'))
+ else
+ buffer = f:read(20) -- ('*a')
+ end
+ f:close()
+ buffer = { match(buffer,"(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)") }
+ for i=1,9 do
+ buffer[i] = tobitstring(byte(buffer[i]))
+ end
+ local framebits = concat(buffer,"",1,9)
+ local n = tonumber(sub(framebits,1,5),2)
+ local frame = { } -- xmin xmax ymin ymax
+ local xmin = tonumber(sub(framebits,6, 5 + n),2)
+ local xmax = tonumber(sub(framebits,6 + 1*n,5 + 2*n),2)
+ local ymin = tonumber(sub(framebits,6 + 2*n,5 + 3*n),2)
+ local ymax = tonumber(sub(framebits,6 + 3*n,5 + 4*n),2)
+ return {
+ filename = name,
+ version = version,
+ filelength = filelength,
+ framerate = tonumber(byte(buffer[10]) * 256 + byte(buffer[11])),
+ framecount = tonumber(byte(buffer[12]) * 256 + byte(buffer[13])),
+ -- framebits = framebits,
+ compressed = compressed,
+ width = floor((xmax - xmin) / 20),
+ height = floor((ymax - ymin) / 20),
+ rectangle = {
+ xmin = xmin,
+ xmax = xmax,
+ ymin = ymin,
+ ymax = ymax,
+ }
+ }
+end
+
+function figures.checkers.swf(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local foundname = du.fullname
+ local header = getheader(foundname)
+ local width, height = figures.applyratio(dr.width,dr.height,header.width,header.height)
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ context.startfoundexternalfigure(todimen(width),todimen(height))
+ nodeinjections.insertswf {
+ foundname = foundname,
+ width = width,
+ height = height,
+ -- factor = number.dimenfactors.bp,
+ display = dr.display,
+ controls = dr.controls,
+ -- label = dr.label,
+ resources = dr.resources,
+ }
+ context.stopfoundexternalfigure()
+ return data
+end
+
+figures.includers.swf = figures.includers.nongeneric
+
+figures.registersuffix("swf","swf")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv
new file mode 100644
index 00000000000..099efa1140f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv
@@ -0,0 +1,1238 @@
+%D \module
+%D [ file=grph-trf,
+%D version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Transformations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
+
+\unprotect
+
+%D We probably use too many dimens as the width calculations can
+%D go away. Some of this is an inheritance of limited backends
+%D (some supported fractions, some 1000's, some dimentions) so
+%D we calculate all of them. Nowadays scaling is always available
+%D so we could simplify the code. On the other hand, we now get
+%D some extra values for free.
+%D
+%D We could move the calculations to \LUA\ and clean up this
+%D lot anyway. On the other hand, there is some danger of messing
+%D up so it has a real low priority.
+
+% local:
+
+\newdimen\d_grph_scale_x_size
+\newdimen\d_grph_scale_y_size
+\newdimen\d_grph_scale_x_offset
+\newdimen\d_grph_scale_y_offset
+
+\newdimen\d_grph_scale_h_size
+\newdimen\d_grph_scale_v_size
+
+\newconditional\c_grph_scale_done
+\newconditional\c_grph_scale_scaling_done
+\newconditional\c_grph_scale_limit_factors \settrue\c_grph_scale_limit_factors
+
+\newdimen\d_grph_scale_wd
+\newdimen\d_grph_scale_ht
+\newdimen\d_grph_scale_dp
+
+% global
+
+\newdimen\d_grph_scale_used_x_size
+\newdimen\d_grph_scale_used_y_size
+
+\newcount\c_grph_scale_used_x_scale
+\newcount\c_grph_scale_used_y_scale
+
+\let \m_grph_scale_used_x_scale\!!plusone
+\let \m_grph_scale_used_y_scale\!!plusone
+
+\newdimen\d_grph_scale_outer_v_size % we cannot manipulate any global vsize !
+
+% scratch:
+
+\let\m_grph_scale_temp \empty
+\let\m_grph_scale_temp_x\empty
+\let\m_grph_scale_temp_y\empty
+
+% public:
+
+\let\finalscaleboxxscale \!!plusone
+\let\finalscaleboxyscale \!!plusone
+\let\finalscaleboxwidth \!!zeropoint
+\let\finalscaleboxheight \!!zeropoint
+
+% we can let sx/sy win (first check)
+
+\installcorenamespace{scale}
+\installcorenamespace{scalegrid}
+\installcorenamespace{scalenorm}
+
+\installcommandhandler \??scale {scale} \??scale % we can have instances
+
+\setupscale
+ [\c!sx=\scaleparameter\c!s,
+ \c!sy=\scaleparameter\c!s,
+ \c!s=1,
+ %\c!scale=,
+ %\c!xscale=,
+ %\c!yscale=,
+ %\c!width=,
+ %\c!height=,
+ %\c!lines=,
+ %\c!factor=,
+ %\c!hfactor=,
+ %\c!wfactor=,
+ %\c!grid=,
+ %\c!equalwidth=,
+ %\c!equalheight=,
+ \c!maxwidth=\scaleparameter\c!width,
+ \c!maxheight=\scaleparameter\c!height]
+
+\unexpanded\def\scale{\dodoubleempty\grph_scale}
+
+% we could have: \freezeparameter\c!scale etc (less backtracking when used multiple)
+
+\def\grph_scale[#1][#2]%
+ {\bgroup
+ % this is quite common so we might make this a helper
+ \ifsecondargument
+ \edef\currentscale{#1}%
+ \setupcurrentscale[#2]%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\let\currentscale\empty
+ \setupcurrentscale[#1]}
+ {\edef\currentscale{#1}}%
+ \else
+ \let\currentscale\empty
+ \fi\fi
+ %
+ \dowithnextboxcs\grph_scale_finish\hbox}
+
+\def\grph_scale_finish
+ {% todo: p_scale_
+ \edef\p_scale {\scaleparameter\c!scale }%
+ \edef\p_xscale {\scaleparameter\c!xscale }%
+ \edef\p_yscale {\scaleparameter\c!yscale }%
+ \edef\p_width {\scaleparameter\c!width }%
+ \edef\p_height {\scaleparameter\c!height }%
+ \edef\p_depth {\scaleparameter\c!depth }%
+ \edef\p_lines {\scaleparameter\c!lines }%
+ \edef\p_factor {\scaleparameter\c!factor }%
+ \edef\p_hfactor {\scaleparameter\c!hfactor }%
+ \edef\p_wfactor {\scaleparameter\c!wfactor }%
+ % \edef\p_grid {\scaleparameter\c!grid }% used once
+ \edef\p_maxwidth {\scaleparameter\c!maxwidth }%
+ \edef\p_maxheight {\scaleparameter\c!maxheight }%
+ \edef\p_sx {\scaleparameter\c!sx }%
+ \edef\p_sy {\scaleparameter\c!sy }%
+ \edef\p_equalwidth {\scaleparameter\c!equalwidth }%
+ \edef\p_equalheight{\scaleparameter\c!equalheight}%
+ %
+ \d_grph_scale_dp\dp\nextbox
+ \ifx\p_depth\v!no \ifzeropt\d_grph_scale_dp \else
+ \setbox\nextbox\hpack{\raise\d_grph_scale_dp\box\nextbox}% new
+ \d_grph_scale_dp\dp\nextbox
+ \fi \fi
+ \d_grph_scale_wd\wd\nextbox
+ \d_grph_scale_ht\ht\nextbox
+ \d_grph_scale_dp\dp\nextbox
+ %
+ \global\let\finalscaleboxxscale \!!plusone
+ \global\let\finalscaleboxyscale \!!plusone
+ \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}%
+ \xdef \finalscaleboxheight{\the\d_grph_scale_ht}%
+ %
+ \forgetall
+ \dontcomplain
+ %
+ \setfalse\c_grph_scale_done
+ \grph_scale_calculate
+ \ifconditional\c_grph_scale_done
+ \grph_scale_apply
+ \fi
+ \grph_scale_position
+ %
+ \box\nextbox
+ \egroup}
+
+\def\grph_scale_apply
+ {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
+ \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
+ \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
+ \setbox\nextbox\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\m_grph_scale_stamp_c{11}
+
+\def\grph_scale_calculate
+ {\ifdim\d_grph_scale_ht>\zeropoint \ifdim\d_grph_scale_wd>\zeropoint
+ \edef\m_grph_scale_stamp_a{\p_scale\p_xscale\p_yscale\p_factor\p_wfactor\p_hfactor\p_lines\p_width\p_height}%
+ \edef\m_grph_scale_stamp_b{\p_sx\p_sy}%
+ \ifx\m_grph_scale_stamp_a\empty
+ \ifx\m_grph_scale_stamp_b\m_grph_scale_stamp_c
+ % no scaling, don't change this (previous attempts failed anyway)
+ \insidefloattrue % trick
+ \grph_scale_calculations_yes
+ \else
+ \grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
+ \fi
+ \else
+ \ifx\m_grph_scale_stamp_b\empty
+ % no need to check further
+ \else
+ \grph_scale_check_sx_sy
+ \fi
+ \grph_scale_calculations_yes
+ \fi
+ \fi \fi}
+
+\def\grph_scale_check_sx_sy
+ {\ifdim\p_sx\onepoint=\onepoint\else\edef\p_width {\the\dimexpr\p_sx\d_grph_scale_wd}\fi
+ \ifdim\p_sy\onepoint=\onepoint\else\edef\p_height{\the\dimexpr\p_sy\d_grph_scale_ht}\fi}
+
+\def\grph_scale_rounded#1%
+ {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
+ \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax}
+
+\def\grph_scale_rounded_indeed#1.#2\relax{#1}
+
+\def\grph_scale_calculations_nop
+ {\settrue\c_grph_scale_done
+ \xdef\finalscaleboxwidth {\the\dimexpr\p_sx\d_grph_scale_wd\relax}%
+ \xdef\finalscaleboxheight{\the\dimexpr\p_sy\d_grph_scale_ht\relax}%
+ \glet\finalscaleboxxscale\p_sx
+ \glet\finalscaleboxyscale\p_sy
+ \ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
+ \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi}
+
+\let\grph_scale_calculations_report\relax
+
+% \def\grph_scale_calculations_report
+% {\writestatus
+% {scaled}%
+% {wd:\finalscaleboxwidth,ht:\finalscaleboxheight
+% ,xscale:\finalscaleboxxscale,yscale:\finalscaleboxyscale}}
+
+% \def\grph_scale_calculations_yes
+% {\settrue\c_grph_scale_done
+% % initial values
+% \d_grph_scale_x_offset\zeropoint
+% \d_grph_scale_y_offset\zeropoint
+% \d_grph_scale_x_size \d_grph_scale_wd
+% \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald!
+% % final values
+% \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
+% \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
+% \c_grph_scale_used_x_scale \plusone % see note * (core-fig)
+% \c_grph_scale_used_y_scale \plusone % see note * (core-fig)
+% \let\m_grph_scale_used_x_scale \!!plusone
+% \let\m_grph_scale_used_y_scale \!!plusone
+% % preparations
+% \setfalse\c_grph_scale_scaling_done
+% \grph_scale_check_parameters
+% % calculators
+% % beware, they operate in sequence, and calculate missing dimensions / messy
+% % grph_scale_by_nature % when? needed?
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
+% % used in actual scaling
+% \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+% \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+% \xdef\finalscaleboxxscale {\luaexpr{\number\c_grph_scale_used_x_scale/1000}}%
+% \xdef\finalscaleboxyscale {\luaexpr{\number\c_grph_scale_used_y_scale/1000}}%
+% \grph_scale_calculations_report}
+
+\def\grph_scale_calculations_yes
+ {\settrue\c_grph_scale_done
+ % initial values
+ \d_grph_scale_x_offset\zeropoint
+ \d_grph_scale_y_offset\zeropoint
+ \d_grph_scale_x_size \d_grph_scale_wd
+ \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald!
+ % final values
+ \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
+ \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
+ \c_grph_scale_used_x_scale \plusone % see note * (core-fig)
+ \c_grph_scale_used_y_scale \plusone % see note * (core-fig)
+ \let\m_grph_scale_used_x_scale \!!plusone
+ \let\m_grph_scale_used_y_scale \!!plusone
+ % preparations
+ \setfalse\c_grph_scale_scaling_done
+ \grph_scale_check_parameters
+ % calculators
+ % beware, they operate in sequence, and calculate missing dimensions / messy
+ % grph_scale_by_nature % when? needed?
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
+ % used in actual scaling
+ \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+ \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+ \glet\finalscaleboxxscale \m_grph_scale_used_x_scale
+ \glet\finalscaleboxyscale \m_grph_scale_used_y_scale
+ \grph_scale_calculations_report}
+
+\setvalue{\??scalegrid\v!yes }{\getnoflines \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\setvalue{\??scalegrid\v!height }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}}
+\setvalue{\??scalegrid\v!depth }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight-\strutdepth}}
+\setvalue{\??scalegrid\v!halfline}{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+.5\lineheight}}
+\setvalue{\??scalegrid\v!fit }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\letvalue{\??scalegrid\empty }\donothing
+
+\def\grph_scale_check_parameters % resolve self referencing loops
+ {\ifx\p_maxwidth \empty\else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi
+ \ifx\p_maxheight\empty\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi
+ \ifx\p_lines \empty\else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi
+ \csname\??scalegrid\scaleparameter\c!grid\endcsname}
+
+\def\grph_scale_by_nature % where ! ! ! ! !
+ {\ifx\p_width \empty\else \global\d_grph_scale_used_x_size\p_width \fi
+ \ifx\p_height\empty\else \global\d_grph_scale_used_y_size\p_height\fi
+ \ifx\p_scale \empty\else \c_grph_scale_used_x_scale\p_scale
+ \c_grph_scale_used_y_scale\p_scale \fi
+ \ifx\p_xscale\empty\else \c_grph_scale_used_x_scale\p_xscale\fi
+ \ifx\p_yscale\empty\else \c_grph_scale_used_y_scale\p_yscale\fi}
+
+% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
+% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
+% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
+% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
+
+\def\m_grph_scale_factor_set{\v!max,\v!fit,\v!broad,\v!auto} % can be an \edef
+
+\def\grph_scale_by_factor
+ {\doifelseinset\p_factor\m_grph_scale_factor_set
+ \grph_scale_by_factor_a
+ {\doifelseinset\p_hfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_b
+ {\doifelseinset\p_wfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_c
+ \grph_scale_by_factor_d}}}
+
+% \def\grph_scale_by_factor_a
+% {\grph_scale_apply_size
+% \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size
+% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
+% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+% \else
+% \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+% \fi
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_b
+% {\grph_scale_apply_size
+% \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_c
+% {\grph_scale_apply_size
+% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
+% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_d
+% {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
+% \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
+% \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize}
+
+\def\grph_scale_by_factor_a
+ {\grph_scale_apply_size
+ \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
+ \else
+ \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \fi
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_b
+ {\grph_scale_apply_size
+ \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_c
+ {\grph_scale_apply_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_d
+ {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize}
+
+\def\grph_scale_by_factor_indeed
+ {\settrue\c_grph_scale_scaling_done
+ \ifconditional\c_grph_scale_limit_factors
+ \ifdim\d_grph_scale_used_x_size>\d_grph_scale_h_size
+ \global\d_grph_scale_used_y_size\zeropoint
+ \global\d_grph_scale_used_x_size\d_grph_scale_h_size
+ \else\ifdim\d_grph_scale_used_y_size>\d_grph_scale_v_size
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\d_grph_scale_v_size
+ \fi\fi
+ \fi
+ \grph_scale_by_dimension}
+
+% \def\grph_scale_by_scale
+% {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
+% \ifx\m_grph_scale_temp\empty \else
+% \grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale
+% \global\d_grph_scale_used_x_size\zeropoint
+% \global\d_grph_scale_used_y_size\zeropoint
+% \ifx\p_maxwidth\empty
+% \ifx\p_maxheight\empty
+% \else
+% \ifdim\d_grph_scale_y_size>\p_maxheight\relax
+% \global\d_grph_scale_used_y_size\p_maxheight
+% \fi
+% \fi
+% \else
+% \ifdim\d_grph_scale_x_size>\p_maxwidth\relax
+% \global\d_grph_scale_used_x_size\p_maxwidth
+% \fi
+% \fi
+% \fi}
+
+\def\grph_scale_by_scale
+ {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
+ \ifx\m_grph_scale_temp\empty \else
+ \grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ % \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size\relax % no global needed here
+ % \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size\relax % no global needed here
+ % wrong: we need to recalculate the scale
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\zeropoint
+ %
+ \ifx\p_maxwidth\empty
+ \ifx\p_maxheight\empty
+ \else
+ \ifdim\d_grph_scale_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ \fi
+ \fi
+ \else
+ \ifdim\d_grph_scale_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ \fi
+ \fi
+ \fi}
+
+\def\grph_scale_by_dimension
+ {\ifdim\d_grph_scale_used_x_size>\zeropoint
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_a
+ \else
+ \grph_scale_by_dimension_b
+ \fi
+ \else
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_c
+ \else
+ \grph_scale_by_dimension_d
+ \fi
+ \fi}
+
+% \def\grph_scale_by_dimension_a
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}}
+%
+% \def\grph_scale_by_dimension_b
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}}
+%
+% \def\grph_scale_by_dimension_c
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+%
+% \def\grph_scale_by_dimension_d
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_a
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_b
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}}
+
+\def\grph_scale_by_dimension_c
+ {\grph_scale_by_dimension_indeed % weird .. three same cases
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_d
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_indeed#1#2#3%
+ {#1\relax
+ \ifx\p_maxwidth\empty \else
+ \ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ #2\relax
+ \fi
+ \fi
+ \ifx\p_maxheight\empty \else
+ \ifdim\d_grph_scale_used_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ #3\relax
+ \fi
+ \fi}
+
+\def\grph_scale_calculate_norm#1#2% todo: swap 1 and 2 and pass one less
+ {\csname\??scalenorm\ifcsname\??scalenorm#2\endcsname#2\else\s!unknown\fi\endcsname#1#2}
+
+\setvalue{\??scalenorm\v!max }#1#2#3#4#5{\global#1#4}
+\setvalue{\??scalenorm\v!fit }#1#2#3#4#5{\global#1#5}
+\setvalue{\??scalenorm\v!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\externalfigureparameter\c!bodyfont\relax}
+\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/10\relax\relax} % brr ex
+\setvalue{\??scalenorm\v!auto }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\empty }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\s!default}#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+
+% \def\grph_scale_calculate_scales#1#2#3#4%
+% {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
+% \c_grph_scale_used_x_scale\scratchdimen
+% \c_grph_scale_used_y_scale\scratchdimen
+% %\writestatus{!!!!}{\the#3/\luaexpr{\number\dimexpr#1\relax/\number\dimexpr#2/1000}}%
+% #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax}
+%
+% \def\grph_scale_calculate_scale#1#2#3%
+% {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax}
+%
+% \def\grph_scale_apply_scale#1#2#3#4% #4 = parameter / scale can be empty
+% {\ifcase0#4\relax
+% \ifcase0\p_scale\relax
+% #3=\plusthousand
+% \else
+% #3=\p_scale
+% \fi
+% \else
+% #3=#4%
+% \fi
+% \relax % important ! still ?
+% \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
+% \relax}
+
+\def\grph_scale_calculate_scales#1#2%
+ {\edef\m_grph_scale_used_x_scale{\luaexpr{\number#1/\number#2}}%
+ \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale}
+
+% we could inline this:
+%
+% \grph_scale_calculate_scale\m_grph_scale_used_x_scale#1#2
+% \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale
+
+\def\grph_scale_calculate_scale#1#2#3%
+ {\edef#1{\luaexpr{\number#2/\number#3}}}
+
+\def\grph_scale_apply_scale#1#2% #1 = parameter / scale can be empty
+ {\edef#1{\luaexpr
+ {\number
+ \ifx#2\empty
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else\ifnum#2=\zerocount
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else
+ #2%
+ \fi\fi
+ /1000}}}
+
+\def\grph_scale_apply_size
+ {\ifx\p_maxheight\empty
+ \d_grph_scale_outer_v_size\textheight
+ \ifinner
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinsidefloat
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinpagebody
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else % hm, there should be an option to force this
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \fi\fi\fi
+ \else
+ \scratchdimen\p_maxheight
+ \d_grph_scale_outer_v_size\scratchdimen
+ \fi
+ \ifx\p_height\empty
+ \d_grph_scale_v_size\scratchdimen
+ \else
+ \d_grph_scale_v_size\p_height
+ \fi
+ \ifx\p_width\empty
+ \d_grph_scale_h_size\hsize
+ \else
+ \d_grph_scale_h_size\p_width
+ \fi}
+
+%\def\grph_scale_convert_large_scale#1#2#3#4%
+% {\scratchdimen#1\relax
+% \ifnum#3=\plusthousand
+% % == scale 1
+% \else
+% % better 1000 100 10 ranges, evt round 2sp
+% \divide\scratchdimen \plusthousand
+% \multiply\scratchdimen #3\relax
+% \fi
+% \scratchdimen-\scratchdimen % beter hier - dan in driver
+% \edef#2{\the\scratchdimen}%
+% \scratchcounter#3\relax
+% \ifnum\scratchcounter>\plustenthousand
+% \divide\scratchcounter\plusten
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \else
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \divide\scratchdimen\plusten
+% \fi
+% \edef#4{\withoutpt\the\scratchdimen}}
+%
+% \def\grph_scale_convert_large_scale#1#2#3#4% less overflow
+% {\edef#2{\ifnum#3=\plusthousand-\the\dimexpr#1\else\luaexpr{-\number#3*\number\dimexpr#1/1000}sp\fi}%
+% \edef#4{\luaexpr{\number#3/10}}}
+
+% \startcombination
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill}
+% \stopcombination
+
+\def\grph_scale_position
+ {\ifx\p_equalwidth\empty \else
+ \scratchdimen\p_equalwidth\relax
+ \ifdim\d_grph_scale_wd<\scratchdimen
+ \setbox\nextbox\hpack to \scratchdimen{\hss\box\nextbox\hss}%
+ \fi
+ \fi
+ \ifx\p_equalheight\empty \else
+ \scratchdimen\p_equalheight\relax
+ \ifdim\d_grph_scale_ht<\scratchdimen
+ \setbox\nextbox\vpack to \scratchdimen{\vss\box\nextbox\vss}%
+ \fi
+ \fi}
+
+\unexpanded\def\fastscale#1%
+ {\ifnum#1=1000\relax
+ \expandafter\grph_scale_fast_nop
+ \else
+ \expandafter\grph_scale_fast_yes
+ \fi{#1}}
+
+\def\grph_scale_fast_nop#1%
+ {\hbox}
+
+\def\grph_scale_fast_yes#1%
+ {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1\onepoint/1000\relax}% brrr
+ \let\finalscaleboxyscale\finalscaleboxxscale
+ \dowithnextboxcs\grph_scale_fast_finish\hbox}
+
+\def\grph_scale_fast_finish
+ {\grph_scale_apply
+ \box\nextbox
+ \endgroup}
+
+\unexpanded\def\fastsxsy#1#2%
+ {\bgroup
+ \edef\p_sx{#1}%
+ \edef\p_sy{#2}%
+ \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox}
+
+\def\grph_scale_fast_sx_xy_finish
+ {\grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
+ \grph_scale_apply
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {clip, setupclipping}
+%D
+%D Although related to figures, clipping can be applied to
+%D arbitrary content. We can use \METAPOST\ to provide a non
+%D rectangular clipping path.
+%D
+%D \starttyping
+%D \startMPclip{fun}
+%D clip currentpicture to fullcircle
+%D shifted (.5,.5) xscaled \width yscaled \height ;
+%D \stopMPclip
+%D \stoptyping
+%D
+%D We get a rectangular piece of the figure when we say:
+%D
+%D \starttyping
+%D \clip[x=2,y=1]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D When we want to clip to the oval we defined a few lines ago,
+%D we say:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,x=1,y=1,mp=fun]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D The general characteristics of clipping can be set up with
+%D
+%D \showsetup{setupclipping}
+
+\installcorenamespace{clipping}
+
+\installdirectcommandhandler \??clipping {clipping}
+
+\unexpanded\def\clip
+ {\dosingleempty\grph_clip}
+
+\def\grph_clip[#1]% nb top->bottom left->right
+ {\bgroup
+ \iffirstargument
+ \setupcurrentclipping[#1]%
+ \fi
+ \dowithnextboxcs\grph_clip_finish\hbox}
+
+\def\grph_clip_finish
+ {\doifelse{\clippingparameter\c!state}\v!start
+ \grph_clip_yes_finish
+ \grph_clip_nop_finish}
+
+% \def\grph_clip_yes_finish
+% {\ifdim\@@cpwidth>\zeropoint
+% \!!dimena\@@cpwidth
+% \!!dimenc\@@cphoffset
+% \else
+% \!!dimena\wd\nextbox
+% \divide\!!dimena \@@cpnx
+% \!!dimenc\@@cpx\!!dimena
+% \advance\!!dimenc -\!!dimena
+% \!!dimena\@@cpsx\!!dimena
+% \fi
+% \relax % sure
+% \ifdim\@@cpheight>\zeropoint
+% \!!dimenb\@@cpheight
+% \!!dimend\ht\nextbox
+% \advance\!!dimend -\@@cpvoffset
+% \advance\!!dimend -\!!dimenb
+% \else
+% \!!dimenb\ht\nextbox
+% \divide\!!dimenb \@@cpny
+% \!!dimend-\@@cpy\!!dimenb
+% \advance\!!dimend -\@@cpsy\!!dimenb
+% \advance\!!dimend \!!dimenb
+% \!!dimenb\@@cpsy\!!dimenb
+% \advance\!!dimend \ht\nextbox % dimend !
+% \fi
+% \setbox\nextbox\hbox % old
+% {\advance\!!dimenc -\@@cpleftoffset % new !
+% \advance\!!dimend -\@@cpbottomoffset % new ! % - added
+% \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old
+% \wd\nextbox\zeropoint
+% \ht\nextbox\zeropoint
+% \dp\nextbox\zeropoint
+% \setbox\nextbox\hbox
+% {\advance\!!dimena \@@cpleftoffset % new !
+% \advance\!!dimena \@@cprightoffset % new !
+% \advance\!!dimenb \@@cpbottomoffset % new !
+% \advance\!!dimenb \@@cptopoffset % new !
+% \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
+% \box\nextbox
+% \dostopclipping}%
+% \setbox\nextbox\hbox % new !
+% {\!!dimena-\@@cpleftoffset % new !
+% \!!dimenb \@@cpbottomoffset % new ! % - removed
+% \hskip\!!dimena\lower\!!dimenb\box\nextbox}% new !
+% \wd\nextbox\!!dimena
+% \ht\nextbox\!!dimenb
+% \dp\nextbox\zeropoint
+% \box\nextbox
+% \egroup}
+
+\def\grph_clip_yes_finish
+ {\ifdim\clippingparameter\c!width>\zeropoint
+ \scratchwidth \clippingparameter\c!width
+ \scratchxoffset\clippingparameter\c!hoffset
+ \else
+ \scratchwidth\dimexpr\wd\nextbox/\clippingparameter\c!nx\relax
+ \scratchxoffset\dimexpr\clippingparameter\c!x\scratchwidth-\scratchwidth\relax
+ \scratchwidth\clippingparameter\c!sx\scratchwidth
+ \fi
+ \relax % sure
+ \ifdim\clippingparameter\c!height>\zeropoint
+ \scratchheight\clippingparameter\c!height
+ \scratchyoffset\dimexpr\ht\nextbox-\clippingparameter\c!voffset-\scratchheight\relax
+ \else
+ \scratchheight\dimexpr\ht\nextbox/\clippingparameter\c!ny\relax
+ \scratchyoffset\dimexpr-\clippingparameter\c!y\scratchheight-\clippingparameter\c!sy\scratchheight+\scratchheight\relax
+ \scratchheight\clippingparameter\c!sy\scratchheight
+ \advance\scratchyoffset \ht\nextbox
+ \fi
+ \setbox\nextbox\hpack
+ {\advance\scratchxoffset -\clippingparameter\c!leftoffset \relax
+ \advance\scratchyoffset -\clippingparameter\c!bottomoffset\relax
+ \hskip-\scratchxoffset
+ \lower\scratchyoffset
+ \box\nextbox}%
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \setbox\nextbox\hpack
+ {\advance\scratchwidth \dimexpr\clippingparameter\c!leftoffset +\clippingparameter\c!rightoffset\relax
+ \advance\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset \relax
+ \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight
+ \box\nextbox
+ \dostopclipping}%
+ \setbox\nextbox\hpack
+ {\hskip-\clippingparameter\c!leftoffset
+ \lower \clippingparameter\c!bottomoffset
+ \box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\def\grph_clip_nop_finish
+ {\box\nextbox
+ \egroup}
+
+\setupclipping
+ [\c!state=\v!start,
+ \c!n=\plusone, % was \plustwo
+ \c!nx=\clippingparameter\c!n,\c!x=\plusone,\c!sx=\plusone,
+ \c!ny=\clippingparameter\c!n,\c!y=\plusone,\c!sy=\plusone,
+ \c!width=\zeropoint,
+ \c!height=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!offset=\zeropoint,
+ \c!leftoffset=\clippingparameter\c!offset,
+ \c!rightoffset=\clippingparameter\c!offset,
+ \c!topoffset=\clippingparameter\c!offset,
+ \c!bottomoffset=\clippingparameter\c!offset,
+ \c!mp=]
+
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D path p ; p := fullcircle scaled 4cm ;
+%D draw p withpen pencircle scaled 1cm ;
+%D setbounds currentpicture to boundingbox p ;
+%D \stopuseMPgraphic
+%D
+%D \hbox to \hsize \bgroup
+%D \hss
+%D \ruledhbox{\useMPgraphic{test}}%
+%D \hss
+%D \ruledhbox{\clip{\useMPgraphic{test}}}%
+%D \hss
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D Mirroring.
+
+\unexpanded\def\mirror
+ {\bgroup
+ \dowithnextboxcs\grph_mirror_finish\hbox}
+
+\def\grph_mirror_finish
+ {\scratchdimen\wd\nextbox
+ % better use an hbox (if no \forgetall, leftskip etc may creep in)
+ %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \setbox\nextbox\hpack{\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \wd\nextbox\scratchdimen
+ \box\nextbox
+ \egroup}
+
+%D A couple of examples, demonstrating how the depth is
+%D taken care of:
+%D
+%D \startbuffer
+%D test\rotate[frame=on, rotation=0] {gans}%
+%D test\rotate[frame=on, rotation=90] {gans}%
+%D test\rotate[frame=on, rotation=180]{gans}%
+%D test\rotate[frame=on, rotation=270]{gans}%
+%D test
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% When we rotate over arbitrary angles, we need to relocate the
+% resulting box because rotation brings that box onto the negative
+% axis. The calculations (mostly sin and cosine) need to be tuned for
+% the way a box is packages (i.e. the refence point). A typical example
+% of drawing, scribbling, and going back to the days of school math.
+%
+% We do a bit more calculations than needed, simply because that way
+% it's easier to debug the code.
+
+% Cleanup in progress ... todo: less boxing
+
+\installcorenamespace {rotate}
+\installcorenamespace {rotatelocation}
+\installcorenamespace {rotatepreset}
+
+% we can alias these to \d_layers-* to save some dimens or maybe have a generic
+% set of scratch variables
+
+% maybe just \rotation_...
+
+\newdimen\d_grph_rotate_x_size
+\newdimen\d_grph_rotate_y_size
+\newdimen\d_grph_rotate_x_offset
+\newdimen\d_grph_rotate_y_offset
+\newdimen\d_grph_rotate_x_position
+\newdimen\d_grph_rotate_y_position
+
+\newdimen\d_grph_rotate_used_height
+
+\let\d_grph_rotate_width \!!widtha
+\let\d_grph_rotate_height\!!heighta
+\let\d_grph_rotate_depth \!!deptha
+
+\let\d_grph_rotate_saved_width \!!widthb
+\let\d_grph_rotate_saved_height\!!heightb
+\let\d_grph_rotate_saved_depth \!!depthb
+
+\newconditional\c_grph_rotate_obey_depth
+\newconditional\c_grph_rotate_not_fit
+\newconditional\c_grph_rotate_center
+
+\installframedcommandhandler \??rotate {rotate} \??rotate
+
+\setuprotate
+ [\c!rotation=90,
+ \c!location=\v!normal,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\let\p_rotation_location\empty
+\let\p_rotation_rotation\empty
+
+\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
+ {\bgroup
+ \dosingleempty\grph_rotate}
+
+\def\grph_rotate[#1]%
+ {\iffirstargument
+ \setupcurrentrotate[#1]%
+ \fi
+ \edef\p_rotation_location{\rotateparameter\c!location}%
+ \edef\p_rotation_rotation{\rotateparameter\c!rotation}%
+ \csname\??rotatelocation
+ \ifcsname\??rotatelocation\p_rotation_location\endcsname\p_rotation_location\else\v!default\fi
+ \endcsname}
+
+\def\grph_rotate_framed
+ {\resetrotateparameter\c!location
+ \dowithnextboxcs\grph_rotate_finish\vbox
+ \inheritedrotateframed}
+
+\def\grph_rotate_normal
+ {\dowithnextboxcs\grph_rotate_finish\vbox}
+
+\def\grph_rotate_finish
+ {\grph_rotate_finish_indeed
+ \egroup}
+
+\setvalue{\??rotatelocation\v!depth}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!fit}%
+ {\settrue \c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!broad}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!high}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\setvalue{\??rotatelocation\v!middle}%
+ {\setfalse\c_grph_rotate_not_fit
+ \settrue \c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth % hm, depth ?
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!default}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\unexpanded\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop % a fast low level one
+ {\ifcase#1\relax
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\grph_rotate_box
+ \fi{#1}}
+
+\def\grph_rotate_box#1% {angle} \hbox/\vbox/\vtop
+ {\bgroup
+ \hbox\bgroup % compatibility hack
+ \edef\p_rotation_rotation{#1}%
+ \dowithnextboxcs\grph_rotate_finish_box}
+
+\def\grph_rotate_finish_box
+ {\setfalse\c_grph_rotate_not_fit % this is the same as broad but
+ \setfalse\c_grph_rotate_center % without the following grab as
+ \setfalse\c_grph_rotate_obey_depth % we call finish directly
+ \grph_rotate_finish_indeed
+ \egroup
+ \egroup}
+
+\def\grph_rotate_finish_indeed
+ {\hbox\bgroup
+ \ifx\p_rotation_rotation\empty
+ \grph_rotate_finish_nop
+ \else
+ \grph_rotate_finish_yes
+ \fi
+ \egroup}
+
+\def\grph_rotate_finish_nop
+ {\boxcursor\box\nextbox}
+
+\setvalue{\??rotatepreset\v!left}%
+ {\edef\p_rotation_rotation{\doifelseoddpage{90}{270}}}
+
+\setvalue{\??rotatepreset\v!right}%
+ {\edef\p_rotation_rotation{\doifelseoddpage{270}{90}}}
+
+\setvalue{\??rotatepreset\v!inner}%
+ {\signalrightpage
+ \doifelserightpage{\def\p_rotation_rotation{270}}{\def\p_rotation_rotation{90}}}
+
+\setvalue{\??rotatepreset\v!outer}%
+ {\signalrightpage
+ \doifelserightpage{\def\p_rotation_rotation{90}}{\def\p_rotation_rotation{270}}}
+
+\setvalue{\??rotatepreset\v!default}%
+ {\edef\p_rotation_rotation{\realnumber{\p_rotation_rotation}}}% get rid of leading zeros and spaces
+
+\def\grph_rotate_finish_yes
+ {\csname\??rotatepreset
+ \ifcsname\??rotatepreset\p_rotation_rotation\endcsname\p_rotation_rotation\else\v!default\fi
+ \endcsname
+ \setbox\nextbox\vpack{\box\nextbox}% not really needed
+ \dontcomplain
+ \ifconditional\c_grph_rotate_center
+ \d_grph_rotate_saved_width \wd\nextbox
+ \d_grph_rotate_saved_height\ht\nextbox
+ \d_grph_rotate_saved_depth \dp\nextbox
+ \setbox\nextbox\vpack{\vskip.5\ht\nextbox\hskip-.5\wd\nextbox\box\nextbox}%
+ \smashbox\nextbox
+ \fi
+ \d_grph_rotate_width \wd\nextbox
+ \d_grph_rotate_height\ht\nextbox
+ \d_grph_rotate_depth \dp\nextbox
+ \setbox\nextbox\vpack{\hpack{\raise\dp\nextbox\box\nextbox}}%
+ \d_grph_rotate_used_height \ht\nextbox
+ % much of the next happens in lua (all the sin and cos) so we can do that in
+ % one go if needed
+ \setcalculatedcos\cos\p_rotation_rotation
+ \setcalculatedsin\sin\p_rotation_rotation
+ \ifdim\sin\points>\zeropoint
+ \ifdim\cos\points>\zeropoint
+ \grph_rotate_calculate_a
+ \grph_rotate_apply
+ \else
+ \grph_rotate_calculate_b
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\sin\d_grph_rotate_depth\else\d_grph_rotate_x_size\fi
+ \fi
+ \else
+ \ifdim\cos\points<\zeropoint
+ \grph_rotate_calculate_c
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \else\ifdim\sin\points=\zeropoint
+ \grph_rotate_calculate_d
+ \grph_rotate_apply
+ % no wd ?
+ \else
+ \grph_rotate_calculate_e
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \fi\fi
+ \fi
+ \ifconditional\c_grph_rotate_center
+ \setbox\nextbox\vpack{\vskip-.5\d_grph_rotate_saved_height\hskip.5\d_grph_rotate_saved_height\box\nextbox}%
+ \wd\nextbox\d_grph_rotate_saved_width
+ \ht\nextbox\d_grph_rotate_saved_height
+ \dp\nextbox\d_grph_rotate_saved_depth
+ \fi
+ \boxcursor\box\nextbox}
+
+\def\grph_rotate_calculate_a
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\cos\d_grph_rotate_used_height
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr\negated\sin\d_grph_rotate_used_height+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\cos\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_b
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\cos\d_grph_rotate_width
+ \d_grph_rotate_y_position\zeropoint
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\cos\d_grph_rotate_height
+ \fi}
+
+\def\grph_rotate_calculate_c
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\d_grph_rotate_x_size
+ \d_grph_rotate_y_position\negated\sin\d_grph_rotate_width
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\dimexpr\d_grph_rotate_y_size+\cos\d_grph_rotate_depth\relax
+ \fi}
+
+\def\grph_rotate_calculate_d
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \d_grph_rotate_x_offset\zeropoint
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_e
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\sin\d_grph_rotate_used_height
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\sin\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_apply
+ {\setbox\nextbox\vpack to \d_grph_rotate_y_size
+ {\vfill
+ \hpack to \d_grph_rotate_x_size
+ {\dostartrotation\p_rotation_rotation
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \box\nextbox
+ \dostoprotation
+ \hfill}%
+ \kern\d_grph_rotate_y_position}%
+ \setbox\nextbox\hpack
+ {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax
+ \lower\d_grph_rotate_y_offset\box\nextbox}}
+
+% \dostepwiserecurse{0}{360}{10}
+% {\startlinecorrection[blank]
+% \hbox
+% {\expanded{\setuprotate[rotation=\recurselevel]}%
+% \traceboxplacementtrue
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
+% \stoplinecorrection}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-u3d.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-u3d.lua
new file mode 100644
index 00000000000..6961c55037b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-u3d.lua
@@ -0,0 +1,51 @@
+if not modules then modules = { } end modules ['grph-u3d'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- see lpdf-u3d.lua for comment
+
+-- maybe: backends.codeinjections.insertu3d
+
+local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end)
+
+local report_u3d = logs.reporter("graphics","u3d")
+
+local figures = figures
+local context = context
+local nodeinjections = backends.nodeinjections
+local todimen = string.todimen
+
+function figures.checkers.u3d(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local width = todimen(dr.width or figures.defaultwidth)
+ local height = todimen(dr.height or figures.defaultheight)
+ local foundname = du.fullname
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ if trace_inclusion then
+ report_u3d("including u3d %a, width %p, height %p",foundname,width,height)
+ end
+ context.startfoundexternalfigure(width .. "sp",height .. "sp")
+ context(function()
+ nodeinjections.insertu3d {
+ foundname = foundname,
+ width = width,
+ height = height,
+ factor = number.dimenfactors.bp,
+ display = dr.display,
+ controls = dr.controls,
+ label = dr.label,
+ }
+ end)
+ context.stopfoundexternalfigure()
+ return data
+end
+
+figures.includers.u3d = figures.includers.nongeneric
+
+figures.registersuffix("u3d","u3d")
+figures.registersuffix("prc","u3d")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-wnd.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-wnd.lua
new file mode 100644
index 00000000000..ebb9b11691c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-wnd.lua
@@ -0,0 +1,47 @@
+if not modules then modules = { } end modules ['grph-wnd'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Thanks to Luigi Scarso for making graphic magic work in luatex.
+--
+-- \externalfigure[hacker.jpeg][width=4cm,conversion=gray.jpg]
+
+local converters, suffixes = figures.converters, figures.suffixes
+
+local trace_conversion = false trackers.register("figures.conversion", function(v) trace_conversion = v end)
+
+local report_wand = logs.reporter("graphics","wand")
+
+local function togray(oldname,newname)
+ if lfs.isfile(oldname) then
+ require("gmwand")
+ if trace_conversion then
+ report_wand("converting %a to %a using gmwand",oldname,newname)
+ end
+ gmwand.InitializeMagick("./") -- What does this path do?
+ local wand = gmwand.NewMagickWand()
+ gmwand.MagickReadImage(wand,oldname)
+ gmwand.MagickSetImageColorspace(wand,gmwand.GRAYColorspace)
+ gmwand.MagickWriteImages(wand,newname,1)
+ gmwand.DestroyMagickWand(wand)
+ else
+ report_wand("unable to convert %a to %a using gmwand",oldname,newname)
+ end
+end
+
+local formats = { "png", "jpg", "gif" }
+
+for i=1,#formats do
+ local oldformat = formats[i]
+ local newformat = "gray." .. oldformat
+ if trace_conversion then
+ report_wand("installing converter for %a to %a",oldformat,newformat)
+ end
+ converters[oldformat] = converters[oldformat] or { }
+ converters[oldformat][newformat] = togray
+ suffixes [newformat] = oldformat
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/hand-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/hand-ini.mkiv
new file mode 100644
index 00000000000..d4bffdb14a6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/hand-ini.mkiv
@@ -0,0 +1,82 @@
+%D \module
+%D [ file=hand-ini,
+%D version=2008.02.12,
+%D title=\CONTEXT\ Handling Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Handling is implemented differently in \MKIV. Maybe I'll cook up
+%D some compatibility hack.
+
+% \definefontfeature[demo][default][mode=node,expansion=quality]
+% \definefontfeature[demo][default][mode=node,protrusion=pure]
+
+% experimental setup:
+%
+% \showframe \setupalign[hanging] \enabletrackers[fonts.protrusion]
+%
+% \definefontfeature[default] [default][mode=node,script=latn]
+% %definefontfeature[whatever][default][mode=node,lfbd=yes,rtbd=yes,script=latn]
+% \definefontfeature[whatever][default][mode=node,protrusion=quality]
+% \definefontfeature[whocares][default][mode=node,protrusion=yes,opbd=yes,script=latn] % left|right|yes
+%
+% \definedfont[fxlbi.otf*default] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+% \definedfont[fxlbi.otf*whatever] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+% \definedfont[fxlbi.otf*whocares] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+%
+% %definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+% \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
+%
+% \definedfont[texgyrepagella-regularxx.otf*whocares] \input tufte
+
+\unprotect
+
+%D New stuff.
+
+\unexpanded\def\setupfontexpansion {\dodoubleargument\font_expansion_setup }
+\unexpanded\def\setupfontprotrusion{\dodoubleargument\font_protrusion_setup}
+
+\def\font_expansion_setup [#1][#2]{\clf_setupfontexpansion {#1}{#2}}
+\def\font_protrusion_setup[#1][#2]{\clf_setupfontprotrusion{#1}{#2}}
+
+% \setupfontprotrusion[quality-upright][vector=quality]
+% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5]
+
+\let\adjustspacing\relax \newcount\adjustspacing % a little bit protection
+\let\protrudechars\relax \newcount\protrudechars % a little bit protection
+
+% at some point we can introduce extreme expansion, i.e. \normaladjustspacing\plustwo
+
+% 0 = disabled
+% 1 = notused (thesis)
+% 2 = glyph + kern
+% 3 = glyph only
+
+\def\font_expansion_enable {\normaladjustspacing\plusthree}
+\def\font_expansion_enable_k{\normaladjustspacing\plustwo}
+\def\font_expansion_disable {\normaladjustspacing\zerocount}
+
+\def\font_protruding_enable {\normalprotrudechars\plustwo }
+\def\font_protruding_disable{\normalprotrudechars\zerocount}
+
+\appendtoks \font_expansion_disable \to \everyforgetall % Here or not here?
+\appendtoks \font_protruding_disable \to \everyforgetall % Here or not here?
+
+% \def\fonthandlingerror{\writestatus\m!fonts{font handling is replaced by features in mkiv}}
+%
+% \let\fonthandling\empty
+%
+% \unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
+% \unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling}
+% \unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
+% \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror}
+% \def\dosetupfonthandling [#1][#2]{\fonthandlingerror}
+% \def\usehandling [#1]{\fonthandlingerror}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv
new file mode 100644
index 00000000000..584ee13512d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv
@@ -0,0 +1,395 @@
+%D \module
+%D [ file=java-exa,
+%D version=2002.??.??,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Example 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.
+
+% XFDF versus HTML
+% localhost versus remote versus set
+
+% filename | filename-nr => name
+% fakename | fakename-nr => file upload, unless localhost
+%
+% we erase the list because otherwise we end up in browser remembering
+% problems; also, it is not possible to set upload fields 'manually'
+
+\startJSpreamble request_1 used now
+
+ var example_method = "HTML" ;
+ var example_host = "" ;
+ var example_port = "" ;
+ var example_url = "" ;
+ var example_file = "" ;
+
+ var example_log = true ; % false
+
+ function stripped_exa_value( name ) {
+ f = this.getField(name) ;
+ if (f) {
+ str = f.value ;
+ if (str.indexOf(name+'-')==0) {
+ str = str.substr(name.length+1) ;
+ }
+ return str ;
+ } else {
+ return "" ;
+ }
+ }
+
+ function identify_example_url ( ) {
+ if (example_log) {
+ console.clear ;
+ console.println("base url: "+this.baseURL) ;
+ console.println("this url: "+this.URL) ;
+ }
+ if (this.baseURL != "") {
+ example_url = this.baseURL ;
+ } else {
+ if (this.URL != "") {
+ example_url = this.URL
+ }
+ }
+ if (example_url.indexOf("file://")>=0) {
+ example_url = "" ;
+ }
+ str = stripped_exa_value("examplehost") ;
+ if (str != "auto") {
+ example_host = str ;
+ if (str == "localhost") {
+ example_port = "8061"
+ }
+ }
+ str = stripped_exa_value("exampleport") ;
+ if (str != "auto") {
+ example_port = str ;
+ }
+ if (example_log) {
+ console.println("example_url: "+example_url) ;
+ console.println("example_host: "+example_host) ;
+ console.println("example_port: "+example_port) ;
+ }
+ }
+
+ function check_example_url ( url ) {
+ if (url.indexOf("file://")>=0) {
+ url = "http://localhost:8061" ;
+ console.println("file url replaced by: "+url) ;
+ } else {
+ if (url.indexOf("://")<0) {
+ url = "http://" + url ;
+ }
+ if (example_log) {
+ console.println("url before check: "+url) ;
+ }
+% url = url.replace(/(http:\\\/\\\/.+)(\\\/.*$)/, "$1") ;
+ url = url.replace(/(https*:\\\/\\\/.+?)(\\\/.*$)/, "$1/exarequest") ;
+ if (example_log) {
+ console.println("url after check: "+url) ;
+ }
+ }
+ return url ;
+ }
+
+ function set_example_xfdf ( method ) {
+ example_method = method ;
+ }
+
+ function set_example_file ( file ) {
+ example_method = file ;
+ }
+
+ function set_example_host ( host ) {
+ example_host = host ;
+ }
+
+ function set_example_port ( port ) {
+ example_host = host ;
+ }
+
+ function do_erase_example_file(tag) {
+ f = this.getField(tag) ;
+ if (f) {
+ f.value = "" ;
+ }
+ }
+
+ function do_erase_example_list(tag) {
+ for (i=1;i<=100;i++) {
+ f = this.getField(tag+"-"+i) ;
+ if (f) {
+ f.value = "" ;
+ } else {
+ return
+ }
+ }
+ }
+
+ function do_submit_example_url ( url ) {
+ if ((example_method == "XFDF" ) || (url.indexOf("localhost")>=0)) {
+ do_erase_example_file("fakename") ;
+ do_erase_example_list("fakename") ;
+ }
+ url = check_example_url(url) ;
+ if (example_log) {
+ console.println("submitting form to "+url+" using method "+example_method) ;
+ }
+ if (example_file != "") {
+ url = url + "/" + example_file ;
+ }
+ % we need the bFDF for acrobat 5
+ this.submitForm({cURL : url, bFDF : false, cSubmitAs : example_method}) ;
+ }
+
+ function submit_example_form ( ) {
+ identify_example_url() ;
+ if (example_host != "") {
+ if (example_port != "") {
+ do_submit_example_url(example_host+":"+example_port) ;
+ } else {
+ do_submit_example_url(example_host) ;
+ }
+ } else {
+ if (example_url != "") {
+ do_submit_example_url(example_url) ;
+ } else {
+ if (example_port != "") {
+ do_submit_example_url("localhost"+":"+example_port) ;
+ } else {
+ do_submit_example_url("localhost:8061") ; % local exampler
+ }
+ }
+ }
+ resetfilename () ;
+ }
+
+ function submit_form ( host, port) {
+ set_example_host(host) ;
+ set_example_post(post) ;
+ submit_example_form ;
+ }
+
+\stopJSpreamble
+
+\startJSpreamble request_2 used now
+
+ var exa_command = "" ;
+ var exa_option = "" ;
+ var exa_filename = "" ;
+ var exa_filelist = "" ;
+ var exa_registered = "" ;
+
+ function set_request (command,option) {
+ exa_command = command ;
+ if (exa_command == "") {
+ exa_option = option ;
+ } else { if (option == "") {
+ exa_option = "" ;
+ } else { if (option.indexOf("--")<0) {
+ exa_option = "--action=" + option ;
+ } else {
+ exa_option = option ;
+ } } }
+ }
+
+ function assemble_request ( ) {
+ v = this.getField('filename') ;
+ if (v) {
+ exa_filename = v.value ;
+ }
+ v = this.getField('filelist') ;
+ if (v) {
+ exa_filelist = v.value ;
+ }
+% exa_filename = exa_filename.replace(/\\\\/g,'/') ;
+% exa_filelist = exa_filelist.replace(/\\\\/g,'/') ;
+ str = "<?xml version='1.0' ?>\\n" ;
+ str = str+"<exa:request xmlns:exa='http://www.pragma-ade.com/schemas/example.rng'><exa:application>" ;
+ if (exa_filelist == "") {
+ exa_filelist = exa_registered ;
+ } else { if (exa_registered != "") {
+ exa_filelist = exa_filelist + "\\n" + exa_registered ;
+ } }
+ if (exa_command != "") {
+ str = str+"<exa:command>"+exa_command+"</exa:command>" ;
+ }
+ if (exa_option != "") {
+ str = str+"<exa:option>"+exa_option+"</exa:option>" ;
+ }
+ if (exa_filename != "") {
+ str = str+"<exa:filename>"+exa_filename+"</exa:filename>" ;
+ }
+ var fls = "" ;
+ if (exa_filelist != "") {
+ % old method, soon obsolete
+ lst = exa_filelist.split(/\\s/) ;
+ for (i=0;i<lst.length;i++) {
+ fls = fls+"<exa:entry>"+lst[i]+"</exa:entry>" ;
+ }
+ } else { if (exa_multiple) {
+ for (i=1;i<=100;i++) {
+ % console.println("file field "+i) ;
+ f = this.getField("filename-"+ i) ;
+% if (f) { if (f.value != "") {
+% if (g) { if (g.value == "") {
+% fls = fls+"<exa:entry>"+f.value+"</exa:entry>" ;
+% } else {
+% fls = fls+"<exa:entry label='" + g.value + "'>"+f.value+"</exa:entry>" ;
+% } } else {
+% fls = fls+"<exa:entry>"+f.value+"</exa:entry>" ;
+% }
+% } }
+ if (f) { if (f.value != "") {
+ fls = fls + "<exa:entry" ;
+ g = this.getField("dataname-"+ i) ;
+ if (g) { if (g.value == "") {
+ % console.println("a") ;
+ fls = fls + ">" ;
+ } else {
+ % console.println("b") ;
+ fls = fls + " label='" + g.value + "'>" ;
+ } } else {
+ % console.println("c") ;
+ fls = fls + ">" ;
+ }
+ fls = fls + f.value + "</exa:entry>" ;
+ } }
+ }
+ } }
+ if (fls != "") {
+ str = str + "<exa:filelist>" + fls + "</exa:filelist>" ;
+ }
+ str = str + "</exa:application></exa:request>" ;
+ v = this.getField('exa:request') ;
+ if (v) {
+ v.value = str ;
+ }
+ }
+
+\stopJSpreamble
+
+\startJSpreamble request_3 used now
+
+ var exa_multiple = false ;
+
+ function setfilename ( suffixes ) {
+ if (event.targetName) {
+ var name = event.targetName ;
+ var fake = name.replace(/filename/,"fakename") ;
+ } else {
+ var name = 'filename' ;
+ var fake = 'fakename' ;
+ }
+ f = this.getField(fake) ;
+ if (f) {
+ f.browseForFileToSubmit() ;
+ if ((suffixes != "") && (f.value != "")) {
+ %
+ s = suffixes.replace(/,/g,"|") ;
+ r = new RegExp() ;
+ s = "\\\\.(" + s + ")$" ;
+ r.compile(s, "i") ;
+ if (f.value.search(r)<=0) {
+ f.value = "" ;
+ app.alert('This filetype is not permitted.') ;
+ %
+ % lst = suffixes.split(/,/) ;
+ % ok = false ;
+ % for (i=0;i<lst.length;i++) {
+ % if (f.value == lst[i]) {
+ % ok = true ;
+ % }
+ % }
+ % if (! ok) {
+ % f.value = "" ;
+ % app.alert('This filetype is not permitted.') ;
+ %
+ }
+ }
+ g = this.getField(name) ;
+ if (g) {
+ g.value = f.value ;
+ }
+% we need to set the value of the selector to empty else
+% we get some funny preloading of multimeg files in spite
+% of the specs that say that xml fields will not get sent
+% if (example_method == "XFDF" ) {
+% f.value = "" ;
+% } else {
+% identify_example_url ;
+% if (example_url.indexOf("localhost")>=0) {
+% f.value = "" ;
+% }
+% }
+ }
+ this.dirty = false ;
+ }
+
+ function addfilename () {
+ if (exa_multiple) {
+ h = this.getField("filelist") ;
+ g = this.getField("filename") ;
+ if ((g) && (h)) {
+ str = g.value ;
+ if (h.value == "") {
+ h.value = str ;
+ } else {
+ h.value = h.value + "\\n" + str ;
+ }
+ g.value = "" ;
+ this.value = "" ;
+ }
+ }
+ this.dirty = false ;
+ }
+
+ % this only works with client that assembles request
+
+ function registerfilename (str) {
+ if (str!="") {
+ h = this.getField("filelist") ;
+ if (h) {
+ if (h.value != "") {
+ h.value = h.value + "\\n" ;
+ }
+ h.value = h.value + str ;
+ } else {
+ if (exa_registered != "") {
+ exa_registered = exa_registered + "\\n" ;
+ }
+ exa_registered = exa_registered + str ;
+ }
+ }
+ console.show ;
+ console.println('registered files') ;
+ console.println("file: "+str) ;
+ console.println("list: "+exa_registered) ;
+ this.dirty = false ;
+ }
+
+ function checkfilename () {
+ }
+
+ function getfilename ( suffixes ) {
+ setfilename(suffixes) ;
+ checkfilename() ;
+ addfilename() ;
+ }
+
+ function resetfilename () {
+ do_erase_example_file("fakename") ;
+ do_erase_example_file("filename") ;
+ do_erase_example_file("filelist") ;
+ do_erase_example_list("filename") ;
+ do_erase_example_list("fakename") ;
+ }
+
+\stopJSpreamble
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv
new file mode 100644
index 00000000000..808950f2807
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=java-fil,
+%D version=1998.06.01,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Filing and Printing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startJSpreamble Auxiliary used now
+
+ function DocumentFileName() {
+ var Paths = this.path.split("/") ;
+ Paths = Paths[Paths.length-1].split(".") ;
+ return(Paths[0])
+ }
+
+ function Print_Page_Range(From,To) {
+ if ((Number(From)>0) && (Number(To) >= Number(From))) {
+ var myFrom = Number(From)-1 ;
+ var myTo = Number(To)-1 ;
+ this.print(false,myFrom,myTo,true) ;
+ }
+ }
+
+ function Print_This_Page() {
+ this.print(false,this.pageNum,this.pageNum,true) ;
+ }
+
+\stopJSpreamble
+
+\definereference
+ [PrintSubPaginas]
+ [JS(Print_Page_Range{\firstsubpage,\lastsubpage})]
+
+\definereference
+ [PrintSubPages]
+ [JS(Print_Page_Range{\firstsubpage,\lastsubpage})]
+
+\definereference
+ [PrintDezePagina]
+ [JS(Print_This_Page)]
+
+\definereference
+ [PrintThisPage]
+ [JS(Print_This_Page)]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv
new file mode 100644
index 00000000000..cbd53fffb4a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv
@@ -0,0 +1,625 @@
+%D \module
+%D [ file=java-fld,
+%D version=1998.05.20,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Field 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 In \LUATEX\ the following does not work out well:
+%D
+%D \starttyping
+%D v = v.replace(/\\\\"e/g,"\\353") ;
+%D \stoptyping
+%D
+%D But this does:
+%D
+%D \starttyping
+%D v = String(v).replace(/\\\\"e/g,"\\353") ;
+%D \stoptyping
+%D
+%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.
+
+% Is this still okay? We can have unicode now, can't we? Anyway it's kind of
+% messy and unneeded in these unicode times.
+
+\startluasetups javascript:pdfencoding
+ local ctx_verbatim = context.verbatim
+ local utfbyte = utf.byte
+ local sortedhash = table.sortedhash
+
+ ctx_verbatim("{\n")
+ for accent, group in sortedhash(characters.tex.accentmapping) do
+ for character, mapping in sortedhash(group) do
+ if character == "" then
+ character = " "
+ end
+ if accent == '"' then
+ ctx_verbatim(" '\\\\%s%s' : '\\u%04X',\n",accent,character,utfbyte(mapping))
+ else
+ ctx_verbatim(' "\\\\%s%s" : "\\u%04X",\n',accent,character,utfbyte(mapping))
+ end
+ end
+ end
+ for command, mapping in sortedhash(characters.tex.commandmapping) do
+ ctx_verbatim(' "\\\\%s" : "\\u%04X",\n',command,utfbyte(mapping))
+ end
+ -- ctx_verbatim(" '\\\\<<' : '\\u00AB',\n")
+ -- ctx_verbatim(" '\\\\>>' : '\\u00BB',\n")
+ ctx_verbatim("}\n")
+
+\stopluasetups
+
+% maybe make { } tex braces in javascript code so that we can call lua
+
+\def\JavaScriptTeXAccentMapping{\luasetup{javascript:pdfencoding}}
+
+\startJSpreamble SanitizeTeXInput used later
+
+var TeXAccentMapping = \JavaScriptTeXAccentMapping
+
+function TeX_Replacer(original,str) {
+ return (TeXAccentMapping[str] || str) ;
+}
+
+function Sanitized_TeX_String(value) {
+ return (value.replace(/(\\..)/g, TeX_Replacer)) ;
+}
+
+var TeX_Key_Mode = 0 ;
+var TeX_Key_Char = "" ;
+
+function Initialize_TeX_Keystroke() {
+ TeX_Key_Char = "" ;
+ TeX_Key_Mode = 0 ;
+}
+
+function Sanitized_TeX_Keystroke(change) {
+ if (!event.willCommit) {
+ if (change=="\\") {
+ TeX_Key_Mode = 1 ;
+ return ("")
+ } else if (TeX_Key_Mode == 1) {
+ TeX_Key_Mode = 2 ;
+ TeX_Key_Char = change ;
+ return ("")
+ } else if (TeX_Key_Mode == 2) {
+ TeX_Key_Mode = 0 ;
+ TeX_Key_Char = "\\"+TeX_Key_Char+change ;
+ return (Sanitized_TeX_String(TeX_Key_Char))
+ } else {
+ TeX_Key_Mode = 0 ;
+ return (change)
+ }
+ }
+}
+
+function Initialize_TeX_Key() {
+ Initialize_TeX_Keystroke() ;
+}
+
+function Convert_TeX_Key() {
+ if (!event.willCommit) {
+ event.change = Sanitized_TeX_Keystroke(event.change) ;
+ }
+}
+
+function Convert_TeX_String() {
+ event.value = Sanitized_TeX_String(event.value) ;
+}
+
+\stopJSpreamble
+
+% \startJScode {Initialize_TeX_Key} uses {SanitizeTeXInput}
+% Initialize_TeX_Keystroke() ;
+% \stopJScode
+%
+% \startJScode {Convert_TeX_Key} uses {SanitizeTeXInput}
+% if (!event.willCommit) {
+% event.change = Sanitized_TeX_Keystroke(event.change) ;
+% }
+% \stopJScode
+%
+% \startJScode{Convert_TeX_String} uses {SanitizeTeXInput}
+% event.value = Sanitized_TeX_String(event.value) ;
+% \stopJScode
+
+% was used now but we autocheck anyway so lets test this for a while
+
+\startJSpreamble FieldsStates used later
+
+var visible_field = new Array() ;
+var visible_fields = 0 ;
+
+function PresetFields() {
+ this.syncAnnotScan() ;
+}
+
+function Preset_Fields() {
+ this.syncAnnotScan() ;
+}
+
+function Hide_When_Down() {
+ event.target.hidden = true ;
+}
+
+function Hide_Field(Name) {
+ var v = this.getField(Name) ;
+ if (v) {
+ v.hidden = true ;
+ v.readonly = true ;
+ this.dirty = false ;
+ }
+}
+
+function Do_Vide_Field(Name, Closable) {
+ var v = this.getField(Name) ;
+ if (v) {
+ ++visible_fields ;
+ visible_field[visible_fields] = Name ;
+ v.hidden = false ;
+ if (Closable) {
+ v.readonly = false ;
+ v.value = "Yes" ;
+ }
+ this.dirty = false ;
+ }
+}
+
+function Vide_Field(Name) {
+ Do_Vide_Field(Name,false) ;
+}
+
+function Vide_Hide_Field(Name) {
+ Do_Vide_Field(Name,true) ;
+}
+
+function Hide_Fields() {
+ while (visible_fields>0) {
+ Hide_Field(visible_field[visible_fields]) ;
+ --visible_fields ;
+ }
+}
+
+function Vide_Fields(Name) {
+ Hide_Fields() ;
+ Vide_Field(Name) ;
+}
+
+function Vide_Hide_Fields(Name) {
+ Hide_Fields() ;
+ Vide_Hide_Field(Name) ;
+}
+
+function Toggle_Hide(Name) {
+ var v = this.getField(Name) ;
+ if (v) {
+ v.hidden = !v.hidden ;
+ this.dirty = false ;
+ }
+}
+
+function Field_On(Name) {
+ v = this.getField(Name) ;
+ if (v) {
+ v.value = "Yes" ;
+ this.dirty = false ;
+ }
+}
+
+function Field_Off(Name) {
+ var v = this.getField(Name) ;
+ if (v) {
+ v.value = "Off" ;
+ this.dirty = false ;
+ }
+}
+
+function Toggle_Value(Name) {
+ var v = this.getField(Name) ;
+ if (v) {
+ if (v.value != "Off") {
+ v.value = "Off" ;
+ } else {
+ v.value = "Yes" ;
+ }
+ }
+ this.dirty = false ;
+}
+
+function Toggle_Read(Name) {
+ var v = this.getField(Name);
+ if (v) {
+ v.readonly = !v.readonly ;
+ }
+}
+
+function Flip_Fields(Name) {
+ var Names = Name.split(",") ;
+ for (var i=0; i < Names.length; i++) {
+ v = this.getField(Names[i]) ;
+ if (v) {
+ v.hidden = !v.hidden ;
+ v.value = "Yes" ;
+ }
+ }
+}
+
+function Forget_Changes() {
+ this.dirty = false ;
+}
+
+function ForgetChanges() {
+ this.dirty = false ;
+}
+\stopJSpreamble
+
+\definereference[ForgetChanges][JS(Forget_Changes)]
+
+% This can be done more efficient, by keeping track of the
+% current top of the stack.
+
+\startJSpreamble FieldStack used later
+
+function Field_Name(FieldSet,i) {
+ return this.getField(FieldSet + ":" + i)
+}
+
+function Reset_Fields(FieldSet) {
+ var i = 1 ;
+ while (true) {
+ v = Field_Name(FieldSet,i) ;
+ if (!v) {
+ break ;
+ } else {
+ v.value = "Off" ;
+ }
+ i++ ;
+ }
+ this.dirty = false ;
+}
+
+function Set_Fields(FieldSet) {
+ var i = 1 ;
+ while (true) {
+ v = Field_Name(FieldSet,i) ;
+ if (!v) {
+ break ;
+ } else {
+ v.value = "Yes" ;
+ }
+ i++ ;
+ }
+ this.dirty = false ;
+}
+
+function Set_Field(FieldSet, FieldName) {
+ Reset_Fields(FieldSet) ;
+ v = Field_Name(FieldSet,FieldName) ;
+ if (v) {
+ v.value = "Yes" ;
+ this.dirty = false ;
+ }
+}
+
+function Reset_Field(FieldSet, FieldName) {
+ Set_Fields(FieldSet) ;
+ v = Field_Name(FieldSet,FieldName) ;
+ if (v) {
+ v.value = "Off" ;
+ this.dirty = false ;
+ }
+}
+
+function Walk_Field(FieldSet) {
+ var i = 1 ;
+ while (true) {
+ v = Field_Name(FieldSet,i) ;
+ if (v) {
+ if (v.value != "Off") {
+ v.value = "Off" ;
+ var ii = i ;
+ ii++ ;
+ v = Field_Name(FieldSet,ii) ;
+ if (! v) {
+ v = Field_Name(FieldSet,1) ;
+ }
+ if (v) {
+ v.value = "Yes" ;
+ }
+ break ;
+ }
+ i++ ;
+ } else {
+ break ;
+ }
+ }
+ this.dirty = false ;
+}
+
+var FieldSets = new Array() ;
+
+function Do_Get_Check_Walk_Field(FieldSet) {
+ var f = FieldSets[FieldSet]
+ if (! f) {
+ f = new Array() ;
+ f.number = 0 ;
+ f.delay = 500 ;
+ f.paused = false ;
+ f.running = false ;
+ f.name = FieldSet ;
+ f.timeout = null ;
+ f.repeat = true ;
+ f.total = 0 ;
+ f.pauseset = new Array() ;
+ FieldSets[FieldSet] = f ;
+ for (var i=1; i>0; i++) {
+ var v = Field_Name(FieldSet,i) ;
+ if (! v) {
+ f.total = i - 1 ;
+ break ;
+ }
+ }
+ f.start = 0 ;
+ f.stop = f.total ;
+ f.pause = 0 ;
+ }
+ this.dirty = false ;
+ return f
+}
+
+function Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,n) {
+ var v = Field_Name(FieldSet,fieldset.number) ;
+ if (v) {
+ if (v.value != "Off") {
+ v.value = "Off" ;
+ }
+ }
+ v = Field_Name(FieldSet,n) ;
+ if (v) {
+ fieldset.number = n ;
+ v.value = "Yes" ;
+ if (fieldset.pauseset[n]) {
+ // fieldset.pause = n ;
+ // Do_Stop_Auto_Walk_Field(Fieldset) ;
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.paused = true ;
+ }
+ }
+ this.dirty = false ;
+}
+
+function Do_Next_Auto_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ if (fieldset.number >= fieldset.stop) {
+ if (fieldset.repeat == false) {
+ fieldset.running = false ;
+ Do_Stop_Auto_Walk_Field(fieldset) ;
+ } else {
+ Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.start) ;
+ }
+ } else {
+ Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.number+1) ;
+ }
+ this.dirty = false ;
+ }
+}
+
+function Do_Stop_Auto_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ try {
+ app.clearInterval(fieldset.timeout) ;
+ app.clearTimeOut(fieldset.timeout) ;
+ } catch (e) {
+ }
+ this.dirty = false ;
+ }
+}
+
+function Do_Start_Auto_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ Do_Next_Auto_Walk_Field(FieldSet) ;
+ fieldset.timeout = app.setInterval("Do_Next_Auto_Walk_Field('"+FieldSet+"')", fieldset.delay) ;
+ this.dirty = false ;
+ }
+}
+
+function Start_Walk_Field(FieldSet, Delay) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ fieldset.number = 0 ;
+ if (Delay) {
+ fieldset.delay = Delay ;
+ }
+ Reset_Fields(FieldSet) ;
+ Do_Start_Auto_Walk_Field(FieldSet) ;
+ fieldset.running = true ;
+ fieldset.paused = false ;
+ }
+}
+
+function Pause_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ if (fieldset.running) {
+ if (fieldset.paused) {
+ Do_Start_Auto_Walk_Field(FieldSet) ;
+ fieldset.paused = false ;
+ } else {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.paused = true ;
+ }
+ }
+ }
+}
+
+function Start_Pause_Walk_Field(FieldSet, Delay, Option) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ if (Option == "once") {
+ fieldset.repeat = false ;
+ } else if (Option == "pause") {
+ fieldset.repeat = false ;
+ } else {
+ fieldset.repeat = true ;
+ }
+ if (Option == "pause") {
+ for (i=3; i<arguments.length; i++) {
+ fieldset.pauseset[parseInt(arguments[i])] = true ;
+ }
+ if (fieldset.pause == fieldset.stop) {
+ fieldset.start = 1 ;
+ fieldset.pause = 0 ;
+ } else if (fieldset.pause > 1) {
+ fieldset.start = fieldset.pause - 1 ;
+ } else {
+ fieldset.start = 1 ;
+ }
+ fieldset.stop = fieldset.total ;
+ } else {
+ var Start = arguments[3] ;
+ var Stop = arguments[4] ;
+ if (typeof Start == "string") {
+ fieldset.start = parseInt(Start) ;
+ } else if (typeof Start == "number") {
+ fieldset.start = Start ;
+ } else {
+ fieldset.start = 1 ;
+ }
+ if (typeof Stop == "string") {
+ fieldset.stop = parseInt(Stop) ;
+ } else if (typeof Stop == "number") {
+ fieldset.stop = Stop ;
+ } else {
+ fieldset.stop = fieldset.total ;
+ }
+ fieldset.pause = 0 ;
+ }
+ if (fieldset.running) {
+ if (fieldset.paused) {
+ Do_Start_Auto_Walk_Field(FieldSet) ;
+ fieldset.paused = false ;
+ } else {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.paused = true ;
+ }
+ } else {
+ fieldset.number = fieldset.start - 1 ;
+ if (Delay) {
+ fieldset.delay = Delay ;
+ }
+ Reset_Fields(FieldSet) ;
+ Do_Start_Auto_Walk_Field(FieldSet) ;
+ fieldset.running = true ;
+ fieldset.paused = false ;
+ }
+ }
+}
+
+function Stop_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.running = false ;
+ fieldset.paused = false ;
+ }
+}
+
+function Reset_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.number = 0 ;
+ fieldset.running = false ;
+ fieldset.paused = false ;
+ Reset_Fields(FieldSet) ;
+ }
+}
+
+function Previous_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.running = false ;
+ fieldset.paused = false ;
+ if (fieldset.number>0) {
+ var v = Field_Name(FieldSet,fieldset.number) ;
+ if (v) {
+ if (v.value != "Off") {
+ v.value = "Off" ;
+ }
+ }
+ fieldset.number-- ;
+ v = Field_Name(FieldSet,fieldset.number) ;
+ if (v) {
+ v.value = "Yes" ;
+ }
+ this.dirty = false ;
+ }
+ }
+}
+
+function Next_Walk_Field(FieldSet) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ fieldset.running = false ;
+ fieldset.paused = false ;
+ var f = fieldset.number + 1 ;
+ var v = Field_Name(FieldSet,f) ;
+ if (v) {
+ var v = Field_Name(FieldSet,fieldset.number) ;
+ if (v) {
+ if (v.value != "Off") {
+ v.value = "Off" ;
+ }
+ }
+ fieldset.number++ ;
+ v = Field_Name(FieldSet,fieldset.number) ;
+ if (v) {
+ v.value = "Yes" ;
+ }
+ this.dirty = false ;
+ }
+ }
+}
+
+function Set_Walk_Field_Delay(FieldSet, Delay) {
+ var fieldset = Do_Get_Check_Walk_Field(FieldSet) ;
+ if (fieldset) {
+ if (Delay) {
+ fieldset.delay = Delay ;
+ if (fieldset.running) {
+ Do_Stop_Auto_Walk_Field(FieldSet) ;
+ Do_Start_Auto_Walk_Field(FieldSet) ;
+ }
+ }
+ }
+}
+
+\stopJSpreamble
+
+\definereference[Walk] [JS(Walk_Field)]
+\definereference[StartWalk] [JS(Start_Walk_Field)]
+\definereference[StopWalk] [JS(Stop_Walk_Field)]
+\definereference[PauseWalk] [JS(Pause_Walk_Field)]
+\definereference[ResetWalk] [JS(Reset_Walk_Field)]
+\definereference[PreviousWalk][JS(Previous_Walk_Field)]
+\definereference[NextWalk] [JS(Next_Walk_Field)]
+\definereference[SetWalkDelay][JS(Set_Walk_Field_Delay)]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv
new file mode 100644
index 00000000000..5f057f55070
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv
@@ -0,0 +1,34 @@
+%D \module
+%D [ file=java-rhh,
+%D version=2010.02.01,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Runtime Highlight Hack,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D As hightlighting is rather intrusive it makes sense to turn it off when
+%D using nice appearances.
+
+% app.runtimeHighlightColor = [ "T" ] ;
+%
+% var SavedAlwaysShowFocus = app.alwaysShowFocus ;
+% app.alwaysShowFocus = true ;
+% "app.alwaysShowFocus = SavedAlwaysShowFocus ; "
+
+\startJSpreamble RuntimeHighlightHack used now
+ var SavedHighlightState = app.runtimeHighlight ;
+ var SavedFocusRectState = app.focusRect ;
+ app.runtimeHighlight = false ;
+ app.focusRect = true ;
+ this.setAction("WillClose",
+ "app.runtimeHighlight = SavedHighlightState ; " +
+ "app.focusRect = SavedFocusRectState ; "
+ ) ;
+\stopJSpreamble
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-stp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-stp.mkiv
new file mode 100644
index 00000000000..8ac5d58b8b4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-stp.mkiv
@@ -0,0 +1,123 @@
+%D \module
+%D [ file=java-stp,
+%D version=2004.03.15,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Stepping,
+%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.
+
+% we define ocglist global, otherwise we quickly run into a memory hog (even
+% out of memory in a 512 Meg machine)
+
+% we cannot use doc_visited[this.pageNum] instead of doc_currentstep because
+% of some funny side effect (i.e. dup or so)
+
+% todo: test with later as we do autoinsert now
+
+\startJSpreamble Steps used now
+
+var doc_ocglist = this.getOCGs() ;
+var doc_stepname = "step" ;
+var doc_currentstep = 0 ;
+var doc_maxstep = 50 ;
+var doc_visited = new Array() ;
+var doc_busy = new Array() ;
+
+function SetupStepper(layername,laststep) {
+ doc_stepname = layername ;
+ doc_maxstep = laststep ;
+ for (var i=0; i<=this.numPages; i++) {
+ doc_visited[i] = 0 ;
+ doc_busy[i] = 0 ;
+ }
+}
+
+for (var i=0; i<=this.numPages; i++) {
+ doc_visited[i] = 0 ;
+ doc_busy[i] = 0 ;
+}
+
+function GetOCG(name) {
+ for (var i=0; i < doc_ocglist.length; i++) {
+ if (doc_ocglist[i].name == name) {
+ return doc_ocglist[i] ;
+ }
+ }
+ return null ;
+}
+
+function CheckBusy() {
+ var ocg = GetOCG("step:busy") ;
+ if (ocg != null) {
+ if (doc_visited[this.pageNum]==0) {
+ ocg.state = true ;
+ } else {
+ if (doc_visited[this.pageNum]<doc_busy[this.pageNum]) {
+ ocg.state = true ;
+ } else {
+ ocg.state = false ;
+ }
+ }
+ }
+}
+
+function SetStepper(maxstep,state) {
+ for (var i=1; i<=maxstep; i++) {
+ try {
+ var ocg = GetOCG(doc_stepname + ':' + String(i)) ;
+ if (ocg != null) {
+ ocg.state = state ;
+ }
+ } catch (e) {
+ return ;
+ }
+ }
+}
+
+function CheckStepper(maxsteps) {
+ SetStepper(doc_visited[this.pageNum], true) ;
+ doc_busy[this.pageNum] = Number(maxsteps) ;
+ doc_currentstep = doc_visited[this.pageNum] ;
+ CheckBusy() ;
+}
+
+function ResetStepper() {
+ SetStepper(doc_maxstep, false) ;
+ doc_currentstep = 0 ;
+}
+
+function InvokeStepper() {
+ try {
+ if (doc_currentstep<doc_busy[this.pageNum]) {
+ doc_currentstep += 1 ;
+ doc_visited[this.pageNum] = doc_currentstep ;
+ var ocg = GetOCG(doc_stepname + ':' + String(doc_currentstep)) ;
+ if (ocg != null) {
+ ocg.state = true ;
+ }
+ } else {
+ if (this.pageNum+1==this.numPages) {
+ this.pageNum = 0 ;
+ } else {
+ this.pageNum += 1 ;
+ }
+ }
+ CheckBusy() ;
+ } catch (e) {
+ return ;
+ }
+}
+
+\stopJSpreamble
+
+% \definereference [SetupStepper] [JS(SetupStepper{step,50})]
+% \definereference [ResetStepper] [JS(ResetStepper)]
+% \definereference [CheckStepper] [JS(CheckStepper{\StepCounter})]
+% \definereference [InvokeStepper] [JS(InvokeStepper)]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/java-ini.lua
new file mode 100644
index 00000000000..069eb5ab610
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-ini.lua
@@ -0,0 +1,268 @@
+if not modules then modules = { } end modules ['java-ini'] = {
+ version = 1.001,
+ comment = "companion to java-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: don't flush scripts if no JS key
+
+local format = string.format
+local concat = table.concat
+local lpegmatch, P, S, C, Carg, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Carg, lpeg.Cc
+
+local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
+
+local variables = interfaces.variables
+local formatters = string.formatters
+
+local context = context
+local implement = interfaces.implement
+
+local trace_javascript = false trackers.register("backends.javascript", function(v) trace_javascript = v end)
+
+local report_javascripts = logs.reporter ("interactions","javascripts")
+local status_javascripts = logs.messenger("interactions","javascripts")
+
+local javascripts = interactions.javascripts or { }
+interactions.javascripts = javascripts
+
+local codes = allocate()
+local preambles = allocate()
+local functions = allocate()
+
+javascripts.codes = codes
+javascripts.preambles = preambles
+javascripts.functions = functions
+
+local preambled = { }
+
+local function storefunction(s,preamble)
+ if trace_javascript then
+ report_javascripts("found function %a",s)
+ end
+ functions[s] = preamble
+end
+
+local uses = P("uses")
+local used = P("used")
+local left = P("{")
+local right = P("}")
+local space = S(" \r\n")
+local spaces = space^0
+local braced = left * C((1-right-space)^1) * right
+local unbraced = C((1-space)^1)
+local name = spaces * (braced + unbraced) * spaces
+local any = P(1)
+local script = C(any^1)
+local funct = P("function")
+local leftp = P("(")
+local rightp = P(")")
+local fname = spaces * funct * spaces * (C((1-space-left-leftp)^1) * Carg(1) / storefunction) * spaces * leftp
+
+local parsecode = name * ((uses * name) + Cc("")) * spaces * script
+local parsepreamble = name * ((used * name) + Cc("")) * spaces * script
+local parsefunctions = (fname + any)^0
+
+function javascripts.storecode(str)
+ local name, uses, script = lpegmatch(parsecode,str)
+ if name and name ~= "" then
+ codes[name] = { uses, script }
+ end
+end
+
+function javascripts.storepreamble(str) -- now later
+ local name, used, script = lpegmatch(parsepreamble,str)
+ if name and name ~= "" and not preambled[name] then
+ local n = #preambles + 1
+ preambles[n] = { name, used, script }
+ preambled[name] = n
+ if trace_javascript then
+ report_javascripts("stored preamble %a, state %a, order %a",name,used,n)
+ end
+ lpegmatch(parsefunctions,script,1,n)
+ end
+end
+
+function javascripts.setpreamble(name,script) -- now later
+ if name and name ~= "" and not preambled[name] then
+ local n = #preambles + 1
+ preambles[n] = { name, "now", script }
+ preambled[name] = n
+ if trace_javascript then
+ report_javascripts("adapted preamble %a, state %a, order %a",name,"now",n)
+ end
+ lpegmatch(parsefunctions,script,1,n)
+ end
+end
+
+function javascripts.addtopreamble(name,script)
+ if name and name ~= "" then
+ local p = preambled[name]
+ if p then
+ preambles[p] = { "now", preambles[p] .. " ;\n" .. script }
+ if trace_javascript then
+ report_javascripts("extended preamble %a, state %a, order %a",name,"now",p)
+ end
+ else
+ local n = #preambles + 1
+ preambles[n] = { name, "now", script }
+ preambled[name] = n
+ if trace_javascript then
+ report_javascripts("stored preamble %a, state %a, order %a",name,"now",n)
+ end
+ lpegmatch(parsefunctions,script,1,n)
+ end
+ end
+end
+
+function javascripts.usepreamblenow(name) -- now later
+ if name and name ~= "" and name ~= variables.reset then -- todo: reset
+ 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"
+ if trace_javascript then
+ report_javascripts("used preamble %a, state %a, order %a",somename,"now","auto")
+ end
+ end
+ end
+ end
+end
+
+local splitter = lpeg.tsplitat(lpeg.patterns.commaspacer)
+
+local used, reported = false, { } -- we can cache more
+
+function javascripts.code(name,arguments)
+ local c = codes[name]
+ if c then
+ local u, code = c[1], c[2]
+ if u ~= "" then
+ local p = preambled[u]
+ if p then
+ preambles[p][2] = "now"
+ if trace_javascript and not reported[name] then
+ reported[name] = true
+ report_javascripts("used code %a, preamble %a",name,u)
+ end
+ elseif trace_javascript and not reported[name] then
+ reported[name] = true
+ report_javascripts("used code %a",name)
+ end
+ elseif trace_javascript and not reported[name] then
+ reported[name] = true
+ report_javascripts("used code %a",name)
+ end
+ used = true
+ return code
+ end
+ local f = functions[name]
+ if f then
+ used = true
+ if trace_javascript and not reported[name] then
+ reported[name] = true
+ report_javascripts("used function %a",name)
+ end
+ preambles[f][2] = "now" -- automatically tag preambles that define the function (as later)
+ if arguments then
+ local args = lpegmatch(splitter,arguments)
+ for i=1,#args do -- can be a helper
+ args[i] = formatters["%q"](args[i])
+ end
+ return formatters["%s(%s)"](name,concat(args,","))
+ else
+ return formatters["%s()"](name)
+ end
+ end
+end
+
+function javascripts.flushpreambles()
+ local t = { }
+-- if used then -- we want to be able to enforce inclusion
+ for i=1,#preambles do
+ local preamble = preambles[i]
+ if preamble[2] == "now" then
+ if trace_javascript then
+ report_javascripts("flushed preamble %a",preamble[1])
+ end
+ t[#t+1] = { preamble[1], preamble[3] }
+ end
+ end
+-- end
+ return t
+end
+
+local patterns = {
+ "java-imp-%s.mkiv",
+ "java-imp-%s.tex",
+ -- obsolete:
+ "java-%s.mkiv",
+ "java-%s.tex"
+}
+
+local function action(name,foundname)
+ context.startnointerference()
+ context.startreadingfile()
+ context.input(foundname)
+ status_javascripts("loaded: library %a",name)
+ context.stopreadingfile()
+ context.stopnointerference()
+end
+
+local function failure(name)
+ report_javascripts("unknown library %a",name)
+end
+
+function javascripts.usescripts(name)
+ if name ~= variables.reset then -- reset is obsolete
+ resolvers.uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+ end
+end
+
+-- interface
+
+implement {
+ name = "storejavascriptcode",
+ actions = javascripts.storecode,
+ arguments = "string"
+}
+
+implement {
+ name = "storejavascriptpreamble",
+ actions = javascripts.storepreamble,
+ arguments = "string"
+}
+
+implement {
+ name = "setjavascriptpreamble",
+ actions = javascripts.setpreamble,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "addtojavascriptpreamble",
+ actions = javascripts.addtopreamble,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "usejavascriptpreamble",
+ actions = javascripts.usepreamblenow,
+ arguments = "string"
+}
+
+implement {
+ name = "usejavascriptscripts",
+ actions = javascripts.usescripts,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-ini.mkiv
new file mode 100644
index 00000000000..d6fe4dd8a05
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/java-ini.mkiv
@@ -0,0 +1,159 @@
+%D \module
+%D [ file=java-ini,
+%D version=1998.01.30,
+%D title=\CONTEXT\ JavaScript 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 JavaScript Macros / Initialization}
+
+\registerctxluafile{java-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {JS*}
+%D
+%D Because \JAVASCRIPT's are activated by the user, for
+%D instance by activating on a button, their support is closely
+%D related to the referencing mechanism. Integration takes
+%D place by
+%D
+%D \starttyping
+%D \goto{calculate total}[Sum()]
+%D \stoptyping
+%D
+%D The \type{()} classify this as a script. If they are absent,
+%D the keyword is treated as a normal reference.
+%D
+%D One can pass arguments to such a script by saying:
+%D
+%D \starttyping
+%D \goto{calculate total}[Sum(1.5,2.3)]
+%D \stoptyping
+
+
+%D \macros
+%D {startJScode}
+%D
+%D A piece of \JAVASCRIPT\ code is defined by saying:
+%D
+%D \starttyping
+%D \startJScode{name}
+%D name = 4 ;
+%D \stopJScode
+%D \stoptyping
+%D
+%D This assumes uses no preamble or presumes that the preamble is
+%D always loaded, the next definition also tells \CONTEXT\ to
+%D actually include the preamble needed.
+%D
+%D \starttyping
+%D \startJScode{uses} uses {later}
+%D uses = 6 ;
+%D \stopJScode
+%D \stoptyping
+%D
+%D \macros
+%D {startJSpreamble}
+%D
+%D One can define insert \JAVASCRIPT\ code at the document level
+%D by using:
+%D
+%D \starttyping
+%D \startJSpreamble{oeps}
+%D oeps = 1 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D which is the same as:
+%D
+%D \starttyping
+%D \startJSpreamble{now} used now
+%D now = 2 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D while the next definition is only included when actually
+%D used.
+%D
+%D \starttyping
+%D \startJSpreamble{later} used later
+%D later = 3 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D This command may be used more that once, but always before
+%D the first page is shipped out.
+%D
+%D \macros
+%D {setJSpreamble, addtoJSpreamble}
+%D
+%D In addition to the previous preamble definitions, we can
+%D set a preamble \quote {in||line} and add tokens to a
+%D preamble.
+%D
+%D \macros
+%D {useJSpreamblenow}
+%D
+%D This macro can be used to force inclusion of postponed
+%D \JAVASCRIPT\ preambles.
+
+\def\m_java_escape_u{\letterbackslash u}
+
+\unexpanded\def\startJScode
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \let\u\m_java_escape_u
+ \java_start_code}
+
+\def\java_start_code#1\stopJScode
+ {\normalexpanded{\endgroup\clf_storejavascriptcode{#1}}}
+
+\let\stopJScode\relax
+
+\unexpanded\def\startJSpreamble
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \let\u\m_java_escape_u
+ \java_start_preamble}
+
+\def\java_start_preamble#1\stopJSpreamble
+ {\normalexpanded{\endgroup\clf_storejavascriptpreamble{#1}}}
+
+\let\stopJSpreamble\relax
+
+\unexpanded\def\setJSpreamble #1#2{\clf_setjavascriptpreamble {#1}{#2}}
+\unexpanded\def\addtoJSpreamble#1#2{\clf_addtojavascriptpreamble{#1}{#2}}
+
+%D \macros
+%D {useJSscripts}
+%D
+%D In due time, users will build their collections of scripts,
+%D which can be used (loaded) when applicable. Although not all
+%D public, we will provide some general purpose scripts,
+%D collected in files with names like \type{java-...}. One can
+%D load these scripts with \type{\useJSscripts}, like:
+%D
+%D \starttyping
+%D \useJSscripts[fld]
+%D \stoptyping
+%D
+%D The not so complicated implementation of this macro is:
+
+\unexpanded\def\useJSscripts
+ {\dodoubleempty\java_use_scripts}
+
+\def\java_use_scripts[#1][#2]%
+ {\clf_usejavascriptscripts {#1}% two steps as this one calls tex code
+ \clf_usejavascriptpreamble{#2}}% so this one comes later
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-boolean.lua b/Master/texmf-dist/tex/context/base/mkiv/l-boolean.lua
new file mode 100644
index 00000000000..8f18d4c003d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-boolean.lua
@@ -0,0 +1,69 @@
+if not modules then modules = { } end modules ['l-boolean'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tonumber = type, tonumber
+
+boolean = boolean or { }
+local boolean = boolean
+
+function boolean.tonumber(b)
+ if b then return 1 else return 0 end -- test and return or return
+end
+
+function toboolean(str,tolerant) -- global
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
+string.toboolean = toboolean
+
+function string.booleanstring(str)
+ if str == "0" then
+ return false
+ elseif str == "1" then
+ return true
+ elseif str == "" then
+ return false
+ elseif str == "false" then
+ return false
+ elseif str == "true" then
+ return true
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
+function string.is_boolean(str,default,strict)
+ if type(str) == "string" then
+ if str == "true" or str == "yes" or str == "on" or str == "t" or (not strict and str == "1") then
+ return true
+ elseif str == "false" or str == "no" or str == "off" or str == "f" or (not strict and str == "0") then
+ return false
+ end
+ end
+ return default
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua
new file mode 100644
index 00000000000..81ac65e506d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua
@@ -0,0 +1,593 @@
+if not modules then modules = { } end modules ['l-dir'] = {
+ 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"
+}
+
+-- todo: dir.expandname will be sped up and merged with cleanpath and collapsepath
+-- todo: keep track of currentdir (chdir, pushdir, popdir)
+
+local type, select = type, select
+local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub
+local concat, insert, remove, unpack = table.concat, table.insert, table.remove, table.unpack
+local lpegmatch = lpeg.match
+
+local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+
+dir = dir or { }
+local dir = dir
+local lfs = lfs
+
+local attributes = lfs.attributes
+local walkdir = lfs.dir
+local isdir = lfs.isdir -- not robust, will be overloaded anyway
+local isfile = lfs.isfile -- not robust, will be overloaded anyway
+local currentdir = lfs.currentdir
+local chdir = lfs.chdir
+local mkdir = lfs.mkdir
+
+local onwindows = os.type == "windows" or find(os.getenv("PATH"),";",1,true)
+
+-- in case we load outside luatex
+
+if onwindows then
+
+ -- lfs.isdir does not like trailing /
+ -- lfs.dir accepts trailing /
+
+ local tricky = S("/\\") * P(-1)
+
+ isdir = function(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode") == "directory"
+ else
+ return attributes(name.."/.","mode") == "directory"
+ end
+ end
+
+ isfile = function(name)
+ return attributes(name,"mode") == "file"
+ end
+
+ lfs.isdir = isdir
+ lfs.isfile = isfile
+
+else
+
+ isdir = function(name)
+ return attributes(name,"mode") == "directory"
+ end
+
+ isfile = function(name)
+ return attributes(name,"mode") == "file"
+ end
+
+ lfs.isdir = isdir
+ lfs.isfile = isfile
+
+end
+
+-- handy
+
+function dir.current()
+ return (gsub(currentdir(),"\\","/"))
+end
+
+-- somewhat optimized
+
+local function glob_pattern_function(path,patt,recurse,action)
+ 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
+ action(full)
+ end
+ elseif recurse and mode == "directory" then
+ if not dirs then
+ dirs = { full }
+ else
+ dirs[#dirs+1] = full
+ end
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
+ end
+ end
+end
+
+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
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
+ end
+ end
+ end
+ return result
+end
+
+local function globpattern(path,patt,recurse,method)
+ local kind = type(method)
+ if patt and sub(patt,1,-3) == path then
+ patt = false
+ end
+ if kind == "function" then
+ return glob_pattern_function(path,patt,recurse,method)
+ elseif kind == "table" then
+ return glob_pattern_table(path,patt,recurse,method)
+ else
+ return glob_pattern_table(path,patt,recurse,{ })
+ end
+end
+
+dir.globpattern = globpattern
+
+-- never or seldom used so far:
+
+local function collectpattern(path,patt,recurse,result)
+ local ok, scanner
+ result = result or { }
+ if path == "/" then
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ else
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ end
+ if ok and type(scanner) == "function" then
+ if not find(path,"/$") then
+ path = path .. '/'
+ end
+ for name in scanner, first do
+ if name == "." then
+ -- skip
+ elseif name == ".." then
+ -- skip
+ else
+ local full = path .. name
+ local attr = attributes(full)
+ local mode = attr.mode
+ if mode == 'file' then
+ if find(full,patt) then
+ result[name] = attr
+ end
+ elseif recurse and mode == "directory" then
+ attr.list = collectpattern(full,patt,recurse)
+ result[name] = attr
+ end
+ end
+ end
+ end
+ return result
+end
+
+dir.collectpattern = collectpattern
+
+local separator, pattern
+
+if onwindows then -- we could sanitize here
+
+ local slash = S("/\\") / "/"
+
+-- pattern = Ct {
+ pattern = {
+ [1] = (Cs(P(".") + slash^1) + Cs(R("az","AZ") * P(":") * slash^0) + Cc("./")) * V(2) * V(3),
+ [2] = Cs(((1-S("*?/\\"))^0 * slash)^0),
+ [3] = Cs(P(1)^0)
+ }
+
+else -- assume unix
+
+-- pattern = Ct {
+ pattern = {
+ [1] = (C(P(".") + P("/")^1) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+ }
+
+end
+
+local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%%." +
+ P("+") / "%%+" +
+ P("-") / "%%-" +
+ P(1)
+)^0 )
+
+local function glob(str,t)
+ if type(t) == "function" then
+ if type(str) == "table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif isfile(str) then
+ t(str)
+ else
+ local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter
+ if root and path and base then
+ local recurse = find(base,"**",1,true) -- find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ globpattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str) == "table" then
+ local t = t or { }
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif isfile(str) then
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
+ else
+ local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter
+ if root and path and base then
+ local recurse = find(base,"**",1,true) -- find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ return globpattern(start,result,recurse,t)
+ else
+ return { }
+ end
+ end
+ end
+end
+
+dir.glob = glob
+
+-- local c = os.clock()
+-- local t = dir.glob("e:/**")
+-- local t = dir.glob("t:/sources/**")
+-- local t = dir.glob("t:/**")
+-- print(os.clock()-c,#t)
+
+-- for i=1,3000 do print(t[i]) end
+-- for i=1,10 do print(t[i]) end
+
+-- list = dir.glob("**/*.tif")
+-- list = dir.glob("/**/*.tif")
+-- list = dir.glob("./**/*.tif")
+-- list = dir.glob("oeps/**/*.tif")
+-- list = dir.glob("/oeps/**/*.tif")
+
+local function globfiles(path,recurse,func,files) -- func == pattern or function
+ if type(func) == "string" then
+ local s = func
+ func = function(name) return find(name,s) end
+ end
+ files = files or { }
+ local noffiles = #files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ --- skip
+ else
+ local mode = attributes(name,'mode')
+ if mode == "directory" then
+ if recurse then
+ globfiles(path .. "/" .. name,recurse,func,files)
+ end
+ elseif mode == "file" then
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
+ end
+ end
+ end
+ end
+ return files
+end
+
+dir.globfiles = globfiles
+
+-- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
+-- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
+-- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
+-- t = dir.glob("f:/minimal/tex/**/*")
+-- print(dir.ls("f:/minimal/tex/**/*"))
+-- print(dir.ls("*.tex"))
+
+function dir.ls(pattern)
+ return concat(glob(pattern),"\n")
+end
+
+-- mkdirs("temp")
+-- mkdirs("a/b/c")
+-- mkdirs(".","/a/b/c")
+-- mkdirs("a","b","c")
+
+local make_indeed = true -- false
+
+if onwindows then
+
+ function dir.mkdirs(...)
+ local n = select("#",...)
+ local str
+ if n == 1 then
+ str = select(1,...)
+ if isdir(str) then
+ return str, true
+ end
+ else
+ str = ""
+ for i=1,n do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
+ end
+ end
+ end
+ local pth = ""
+ local drive = false
+ local first, middle, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ -- empty network path == local path
+ else
+ first, last = match(str,"^(//)/*(.-)$")
+ if first then
+ middle, last = match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth = "//" .. middle
+ else
+ pth = "//" .. last
+ last = ""
+ end
+ else
+ first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth, drive = first .. middle, true
+ else
+ middle, last = match(str,"^(/*)(.-)$")
+ if not middle then
+ last = str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth == "" then
+ pth = s
+ elseif drive then
+ pth, drive = pth .. s, false
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not isdir(pth) then
+ mkdir(pth)
+ end
+ end
+ return pth, (isdir(pth) == true)
+ end
+
+ -- print(dir.mkdirs("","","a","c"))
+ -- print(dir.mkdirs("a"))
+ -- print(dir.mkdirs("a:"))
+ -- print(dir.mkdirs("a:/b/c"))
+ -- print(dir.mkdirs("a:b/c"))
+ -- print(dir.mkdirs("a:/bbb/c"))
+ -- print(dir.mkdirs("/a/b/c"))
+ -- print(dir.mkdirs("/aaa/b/c"))
+ -- print(dir.mkdirs("//a/b/c"))
+ -- print(dir.mkdirs("///a/b/c"))
+ -- print(dir.mkdirs("a/bbb//ccc/"))
+
+else
+
+ function dir.mkdirs(...)
+ local n = select("#",...)
+ local str, pth
+ if n == 1 then
+ str = select(1,...)
+ if isdir(str) then
+ return str, true
+ end
+ else
+ str = ""
+ for i=1,n do
+ local s = select(i,...)
+ if s and s ~= "" then -- we catch nil and false
+ if str ~= "" then
+ str = str .. "/" .. s
+ else
+ str = s
+ end
+ end
+ end
+ end
+ str = gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth = "/"
+ for s in gmatch(str,"[^/]+") do
+ local first = (pth == "/")
+ if first then
+ pth = pth .. s
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not first and not isdir(pth) then
+ mkdir(pth)
+ end
+ end
+ else
+ pth = "."
+ for s in gmatch(str,"[^/]+") do
+ pth = pth .. "/" .. s
+ if make_indeed and not isdir(pth) then
+ mkdir(pth)
+ end
+ end
+ end
+ return pth, (isdir(pth) == true)
+ end
+
+ -- print(dir.mkdirs("","","a","c"))
+ -- print(dir.mkdirs("a"))
+ -- print(dir.mkdirs("/a/b/c"))
+ -- print(dir.mkdirs("/aaa/b/c"))
+ -- print(dir.mkdirs("//a/b/c"))
+ -- print(dir.mkdirs("///a/b/c"))
+ -- print(dir.mkdirs("a/bbb//ccc/"))
+
+end
+
+dir.makedirs = dir.mkdirs
+
+
+do
+
+ -- we can only define it here as it uses dir.chdir and we also need to
+ -- make sure we use the non sandboxed variant because otherwise we get
+ -- into a recursive loop due to usage of expandname in the file resolver
+
+ local chdir = sandbox and sandbox.original(chdir) or chdir
+
+ if onwindows then
+
+ local xcurrentdir = dir.current
+
+ function dir.expandname(str) -- will be merged with cleanpath and collapsepath\
+ local first, nothing, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ first = xcurrentdir() .. "/" -- xcurrentdir sanitizes
+ end
+ if not first then
+ first, last = match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first, last = match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d = currentdir() -- push / pop
+ if chdir(first) then
+ first = xcurrentdir() -- xcurrentdir sanitizes
+ end
+ chdir(d)
+ end
+ end
+ if not first then
+ first, last = xcurrentdir(), str
+ end
+ last = gsub(last,"//","/")
+ last = gsub(last,"/%./","/")
+ last = gsub(last,"^/*","")
+ first = gsub(first,"/*$","")
+ if last == "" or last == "." then
+ return first
+ else
+ return first .. "/" .. last
+ end
+ end
+
+ else
+
+ function dir.expandname(str) -- will be merged with cleanpath and collapsepath
+ if not find(str,"^/") then
+ str = currentdir() .. "/" .. str
+ end
+ str = gsub(str,"//","/")
+ str = gsub(str,"/%./","/")
+ str = gsub(str,"(.)/%.$","%1")
+ return str
+ end
+
+ end
+
+end
+
+file.expandname = dir.expandname -- for convenience
+
+local stack = { }
+
+function dir.push(newdir)
+ insert(stack,currentdir())
+ if newdir and newdir ~= "" then
+ chdir(newdir)
+ end
+end
+
+function dir.pop()
+ local d = remove(stack)
+ if d then
+ chdir(d)
+ end
+ return d
+end
+
+local function found(...) -- can have nil entries
+ for i=1,select("#",...) do
+ local path = select(i,...)
+ local kind = type(path)
+ if kind == "string" then
+ if isdir(path) then
+ return path
+ end
+ elseif kind == "table" then
+ -- here we asume no holes, i.e. an indexed table
+ local path = found(unpack(path))
+ if path then
+ return path
+ end
+ end
+ end
+ -- return nil -- if we want print("crappath") to show something
+end
+
+dir.found = found
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-file.lua b/Master/texmf-dist/tex/context/base/mkiv/l-file.lua
new file mode 100644
index 00000000000..7ed6370f260
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-file.lua
@@ -0,0 +1,698 @@
+if not modules then modules = { } end modules ['l-file'] = {
+ 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"
+}
+
+-- needs a cleanup
+
+file = file or { }
+local file = file
+
+if not lfs then
+ lfs = optionalrequire("lfs")
+end
+
+-- -- see later
+--
+-- if not lfs then
+--
+-- lfs = {
+-- getcurrentdir = function()
+-- return "."
+-- end,
+-- attributes = function()
+-- return nil
+-- end,
+-- isfile = function(name)
+-- local f = io.open(name,'rb')
+-- if f then
+-- f:close()
+-- return true
+-- end
+-- end,
+-- isdir = function(name)
+-- print("you need to load lfs")
+-- return false
+-- end
+-- }
+--
+-- elseif not lfs.isfile then
+--
+-- local attributes = lfs.attributes
+--
+-- function lfs.isdir(name)
+-- return attributes(name,"mode") == "directory"
+-- end
+--
+-- function lfs.isfile(name)
+-- return attributes(name,"mode") == "file"
+-- end
+--
+-- -- function lfs.isdir(name)
+-- -- local a = attributes(name)
+-- -- return a and a.mode == "directory"
+-- -- end
+--
+-- -- function lfs.isfile(name)
+-- -- local a = attributes(name)
+-- -- return a and a.mode == "file"
+-- -- end
+--
+-- end
+
+local insert, concat = table.insert, table.concat
+local match, find, gmatch = string.match, string.find, string.gmatch
+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)
+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
+end
+
+function lfs.isfile(name)
+ return attributes(name,"mode") == "file"
+end
+
+local colon = P(":")
+local period = P(".")
+local periods = P("..")
+local fwslash = P("/")
+local bwslash = P("\\")
+local slashes = S("\\/")
+local noperiod = 1-period
+local noslashes = 1-slashes
+local name = noperiod^1
+local suffix = period/"" * (1-period-slashes)^1 * -1
+
+----- pattern = C((noslashes^0 * slashes^1)^1)
+local pattern = C((1 - (slashes^1 * noslashes^1 * -1))^1) * P(1) -- there must be a more efficient way
+
+local function pathpart(name,default)
+ return name and lpegmatch(pattern,name) or default or ""
+end
+
+local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
+
+local function basename(name)
+ return name and lpegmatch(pattern,name) or name
+end
+
+-- print(pathpart("file"))
+-- print(pathpart("dir/file"))
+-- print(pathpart("/dir/file"))
+-- print(basename("file"))
+-- print(basename("dir/file"))
+-- print(basename("/dir/file"))
+
+local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
+
+local function nameonly(name)
+ return name and lpegmatch(pattern,name) or name
+end
+
+local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
+
+local function suffixonly(name)
+ return name and lpegmatch(pattern,name) or ""
+end
+
+local pattern = (noslashes^0 * slashes)^0 * noperiod^1 * ((period * C(noperiod^1))^1) * -1 + Cc("")
+
+local function suffixesonly(name)
+ if name then
+ return lpegmatch(pattern,name)
+ else
+ return ""
+ end
+end
+
+file.pathpart = pathpart
+file.basename = basename
+file.nameonly = nameonly
+file.suffixonly = suffixonly
+file.suffix = suffixonly
+file.suffixesonly = suffixesonly
+file.suffixes = suffixesonly
+
+file.dirname = pathpart -- obsolete
+file.extname = suffixonly -- obsolete
+
+-- actually these are schemes
+
+local drive = C(R("az","AZ")) * colon
+local path = C((noslashes^0 * slashes)^0)
+local suffix = period * C(P(1-period)^0 * P(-1))
+local base = C((1-suffix)^0)
+local rest = C(P(1)^0)
+
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
+
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
+
+function file.splitname(str,splitdrive)
+ if not str then
+ -- error
+ elseif splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.splitbase(str)
+ if str then
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix (path has / appended, might change at some point)
+ else
+ return "", str -- assume no path
+ end
+end
+
+---- stripslash = C((1 - P("/")^1*P(-1))^0)
+
+function file.nametotable(str,splitdrive)
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ -- if path ~= "" then
+ -- path = lpegmatch(stripslash,path) -- unfortunate hack, maybe this becomes default
+ -- end
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
+ end
+end
+
+-- print(file.splitname("file"))
+-- print(file.splitname("dir/file"))
+-- print(file.splitname("/dir/file"))
+-- print(file.splitname("file"))
+-- print(file.splitname("dir/file"))
+-- print(file.splitname("/dir/file"))
+
+-- inspect(file.nametotable("file.ext"))
+-- inspect(file.nametotable("dir/file.ext"))
+-- inspect(file.nametotable("/dir/file.ext"))
+-- inspect(file.nametotable("file.ext"))
+-- inspect(file.nametotable("dir/file.ext"))
+-- inspect(file.nametotable("/dir/file.ext"))
+
+----- pattern = Cs(((period * noperiod^1 * -1) / "" + 1)^1)
+local pattern = Cs(((period * (1-period-slashes)^1 * -1) / "" + 1)^1)
+
+function file.removesuffix(name)
+ return name and lpegmatch(pattern,name)
+end
+
+-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
+--
+-- function file.addsuffix(name, suffix)
+-- local p = lpegmatch(pattern,name)
+-- if p then
+-- return name
+-- else
+-- return name .. "." .. suffix
+-- end
+-- end
+
+local suffix = period/"" * (1-period-slashes)^1 * -1
+local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
+
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
+ return filename
+ elseif criterium == true then
+ return filename .. "." .. suffix
+ elseif not criterium then
+ local n, s = lpegmatch(pattern,filename)
+ if not s or s == "" then
+ return filename .. "." .. suffix
+ else
+ return filename
+ end
+ else
+ local n, s = lpegmatch(pattern,filename)
+ if s and s ~= "" then
+ local t = type(criterium)
+ if t == "table" then
+ -- keep if in criterium
+ for i=1,#criterium do
+ if s == criterium[i] then
+ return filename
+ end
+ end
+ elseif t == "string" then
+ -- keep if criterium
+ if s == criterium then
+ return filename
+ end
+ end
+ end
+ return (n or filename) .. "." .. suffix
+ end
+end
+
+-- print("1 " .. file.addsuffix("name","new") .. " -> name.new")
+-- print("2 " .. file.addsuffix("name.old","new") .. " -> name.old")
+-- print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new")
+-- print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new")
+-- print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old")
+-- print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new")
+-- print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new")
+-- print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old")
+
+local suffix = period * (1-period-slashes)^1 * -1
+local pattern = Cs((1-suffix)^0)
+
+function file.replacesuffix(name,suffix)
+ if name and suffix and suffix ~= "" then
+ return lpegmatch(pattern,name) .. "." .. suffix
+ else
+ return name
+ end
+end
+
+--
+
+local reslasher = lpeg.replacer(P("\\"),"/")
+
+function file.reslash(str)
+ return str and lpegmatch(reslasher,str)
+end
+
+-- We should be able to use:
+--
+-- local writable = P(1) * P("w") * Cc(true)
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(pathpart(name,"."))
+-- return a and lpegmatch(writable,a.permissions) or false
+-- end
+--
+-- But after some testing Taco and I came up with the more robust
+-- variant:
+
+function file.is_writable(name)
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
+ name = name .. "/m_t_x_t_e_s_t.tmp"
+ local f = io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ end
+ return false
+end
+
+local readable = P("r") * Cc(true)
+
+function file.is_readable(name)
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
+end
+
+file.isreadable = file.is_readable -- depricated
+file.iswritable = file.is_writable -- depricated
+
+function file.size(name)
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
+end
+
+function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+end
+
+function file.joinpath(tab,separator) -- table
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
+end
+
+local someslash = S("\\/")
+local stripper = Cs(P(fwslash)^0/"" * reslasher)
+local isnetwork = someslash * someslash * (1-someslash)
+ + (1-fwslash-colon)^1 * colon
+local isroot = fwslash^1 * -1
+local hasroot = fwslash^1
+
+local reslasher = lpeg.replacer(S("\\/"),"/")
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+-- function file.join(...)
+-- local lst = { ... }
+-- local one = lst[1]
+-- if lpegmatch(isnetwork,one) then
+-- local one = lpegmatch(reslasher,one)
+-- local two = lpegmatch(deslasher,concat(lst,"/",2))
+-- if lpegmatch(hasroot,two) then
+-- return one .. two
+-- else
+-- return one .. "/" .. two
+-- end
+-- elseif lpegmatch(isroot,one) then
+-- local two = lpegmatch(deslasher,concat(lst,"/",2))
+-- if lpegmatch(hasroot,two) then
+-- return two
+-- else
+-- return "/" .. two
+-- end
+-- elseif one == "" then
+-- return lpegmatch(stripper,concat(lst,"/",2))
+-- else
+-- return lpegmatch(deslasher,concat(lst,"/"))
+-- end
+-- end
+
+function file.join(one, two, three, ...)
+ if not two then
+ return one == "" and one or lpegmatch(stripper,one)
+ end
+ if one == "" then
+ return lpegmatch(stripper,three and concat({ two, three, ... },"/") or two)
+ end
+ if lpegmatch(isnetwork,one) then
+ local one = lpegmatch(reslasher,one)
+ local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two)
+ if lpegmatch(hasroot,two) then
+ return one .. two
+ else
+ return one .. "/" .. two
+ end
+ elseif lpegmatch(isroot,one) then
+ local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two)
+ if lpegmatch(hasroot,two) then
+ return two
+ else
+ return "/" .. two
+ end
+ else
+ return lpegmatch(deslasher,concat({ one, two, three, ... },"/"))
+ end
+end
+
+-- or we can use this:
+--
+-- function file.join(...)
+-- local n = select("#",...)
+-- local one = select(1,...)
+-- if n == 1 then
+-- return one == "" and one or lpegmatch(stripper,one)
+-- end
+-- if one == "" then
+-- return lpegmatch(stripper,n > 2 and concat({ ... },"/",2) or select(2,...))
+-- end
+-- if lpegmatch(isnetwork,one) then
+-- local one = lpegmatch(reslasher,one)
+-- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...))
+-- if lpegmatch(hasroot,two) then
+-- return one .. two
+-- else
+-- return one .. "/" .. two
+-- end
+-- elseif lpegmatch(isroot,one) then
+-- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...))
+-- if lpegmatch(hasroot,two) then
+-- return two
+-- else
+-- return "/" .. two
+-- end
+-- else
+-- return lpegmatch(deslasher,concat({ ... },"/"))
+-- end
+-- end
+
+-- print(file.join("c:/whatever"))
+-- print(file.join("c:/whatever","name"))
+-- print(file.join("//","/y"))
+-- print(file.join("/","/y"))
+-- print(file.join("","/y"))
+-- print(file.join("/x/","/y"))
+-- print(file.join("x/","/y"))
+-- print(file.join("http://","/y"))
+-- print(file.join("http://a","/y"))
+-- print(file.join("http:///a","/y"))
+-- print(file.join("//nas-1","/y"))
+-- print(file.join("//nas-1/a/b/c","/y"))
+-- print(file.join("\\\\nas-1\\a\\b\\c","\\y"))
+
+-- The previous one fails on "a.b/c" so Taco came up with a split based
+-- variant. After some skyping we got it sort of compatible with the old
+-- one. After that the anchoring to currentdir was added in a better way.
+-- Of course there are some optimizations too. Finally we had to deal with
+-- windows drive prefixes and things like sys://. Eventually gsubs and
+-- finds were replaced by lpegs.
+
+local drivespec = R("az","AZ")^1 * colon
+local anchors = fwslash
+ + drivespec
+local untouched = periods
+ + (1-period)^1 * P(-1)
+local mswindrive = Cs(drivespec * (bwslash/"/" + fwslash)^0)
+local mswinuncpath = (bwslash + fwslash) * (bwslash + fwslash) * Cc("//")
+local splitstarter = (mswindrive + mswinuncpath + Cc(false))
+ * Ct(lpeg.splitat(S("/\\")^1))
+local absolute = fwslash
+
+function file.collapsepath(str,anchor) -- anchor: false|nil, true, "."
+ if not str then
+ return
+ end
+ if anchor == true and not lpegmatch(anchors,str) then
+ str = getcurrentdir() .. "/" .. str
+ end
+ if str == "" or str =="." then
+ return "."
+ elseif lpegmatch(untouched,str) then
+ return lpegmatch(reslasher,str)
+ end
+ local starter, oldelements = lpegmatch(splitstarter,str)
+ local newelements = { }
+ local i = #oldelements
+ while i > 0 do
+ local element = oldelements[i]
+ if element == '.' then
+ -- do nothing
+ elseif element == '..' then
+ local n = i - 1
+ while n > 0 do
+ local element = oldelements[n]
+ if element ~= '..' and element ~= '.' then
+ oldelements[n] = '.'
+ break
+ else
+ n = n - 1
+ end
+ end
+ if n < 1 then
+ insert(newelements,1,'..')
+ end
+ elseif element ~= "" then
+ insert(newelements,1,element)
+ end
+ i = i - 1
+ end
+ if #newelements == 0 then
+ return starter or "."
+ elseif starter then
+ return starter .. concat(newelements, '/')
+ elseif lpegmatch(absolute,str) then
+ return "/" .. concat(newelements,'/')
+ else
+ newelements = concat(newelements, '/')
+ if anchor == "." and find(str,"^%./") then
+ return "./" .. newelements
+ else
+ return newelements
+ end
+ end
+end
+
+-- local function test(str,...)
+-- print(string.format("%-20s %-15s %-30s %-20s",str,file.collapsepath(str),file.collapsepath(str,true),file.collapsepath(str,".")))
+-- end
+-- test("a/b.c/d") test("b.c/d") test("b.c/..")
+-- test("/") test("c:/..") test("sys://..")
+-- test("") test("./") test(".") test("..") test("./..") test("../..")
+-- test("a") test("./a") test("/a") test("a/../..")
+-- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..")
+-- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..")
+-- test("./a")
+-- test([[\\a.b.c\d\e]])
+
+local validchars = R("az","09","AZ","--","..")
+local pattern_a = lpeg.replacer(1-validchars)
+local pattern_a = Cs((validchars + P(1)/"-")^1)
+local whatever = P("-")^0 / ""
+local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
+
+function file.robustname(str,strict)
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
+ end
+end
+
+file.readdata = io.loaddata
+file.savedata = io.savedata
+
+function file.copy(oldname,newname)
+ if oldname and newname then
+ local data = io.loaddata(oldname)
+ if data and data ~= "" then
+ file.savedata(newname,data)
+ end
+ end
+end
+
+-- also rewrite previous
+
+local letter = R("az","AZ") + S("_-+")
+local separator = P("://")
+
+local qualified = period^0 * fwslash
+ + letter * colon
+ + letter^1 * separator
+ + letter^1 * fwslash
+local rootbased = fwslash
+ + letter * colon
+
+lpeg.patterns.qualified = qualified
+lpeg.patterns.rootbased = rootbased
+
+-- ./name ../name /name c: :// name/name
+
+function file.is_qualified_path(filename)
+ return filename and lpegmatch(qualified,filename) ~= nil
+end
+
+function file.is_rootbased_path(filename)
+ return filename and lpegmatch(rootbased,filename) ~= nil
+end
+
+-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
+--
+-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
+-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
+
+-- -- maybe:
+--
+-- if os.type == "windows" then
+-- local currentdir = getcurrentdir
+-- function getcurrentdir()
+-- return lpegmatch(reslasher,currentdir())
+-- end
+-- end
+
+-- for myself:
+
+function file.strip(name,dir)
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
+end
+
+-- local debuglist = {
+-- "pathpart", "basename", "nameonly", "suffixonly", "suffix", "dirname", "extname",
+-- "addsuffix", "removesuffix", "replacesuffix", "join",
+-- "strip","collapsepath", "joinpath", "splitpath",
+-- }
+
+-- for i=1,#debuglist do
+-- local name = debuglist[i]
+-- local f = file[name]
+-- file[name] = function(...)
+-- print(name,f(...))
+-- return f(...)
+-- end
+-- end
+
+-- a goodie: a dumb version of mkdirs (not used in context itself, only
+-- in generic usage)
+
+function lfs.mkdirs(path)
+ local full = ""
+ for sub in gmatch(path,"(/*[^\\/]+)") do -- accepts leading c: and /
+ full = full .. sub
+ -- lfs.isdir("/foo") mistakenly returns true on windows so
+ -- so we don't test and just make as that one is not too picky
+ lfs.mkdir(full)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-function.lua b/Master/texmf-dist/tex/context/base/mkiv/l-function.lua
new file mode 100644
index 00000000000..7ded8ceecd5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-function.lua
@@ -0,0 +1,11 @@
+if not modules then modules = { } end modules ['l-functions'] = {
+ 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"
+}
+
+functions = functions or { }
+
+function functions.dummy() end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-gzip.lua b/Master/texmf-dist/tex/context/base/mkiv/l-gzip.lua
new file mode 100644
index 00000000000..5100e47222c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-gzip.lua
@@ -0,0 +1,54 @@
+if not modules then modules = { } end modules ['l-gzip'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not gzip then
+
+ -- no fallback yet
+
+ return
+
+end
+
+local suffix, suffixes = file.suffix, file.suffixes
+
+function gzip.load(filename)
+ local f = io.open(filename,"rb")
+ if not f then
+ -- invalid file
+ elseif suffix(filename) == "gz" then
+ f:close()
+ local g = gzip.open(filename,"rb")
+ if g then
+ local str = g:read("*all")
+ g:close()
+ return str
+ end
+ else
+ local str = f:read("*all")
+ f:close()
+ return str
+ end
+end
+
+function gzip.save(filename,data)
+ if suffix(filename) ~= "gz" then
+ filename = filename .. ".gz"
+ end
+ local f = io.open(filename,"wb")
+ if f then
+ local s = zlib.compress(data or "",9,nil,15+16)
+ f:write(s)
+ f:close()
+ return #s
+ end
+end
+
+function gzip.suffix(filename)
+ local suffix, extra = suffixes(filename)
+ local gzipped = extra == "gz"
+ return suffix, gzipped
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-io.lua b/Master/texmf-dist/tex/context/base/mkiv/l-io.lua
new file mode 100644
index 00000000000..a91d44d8776
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-io.lua
@@ -0,0 +1,358 @@
+if not modules then modules = { } end modules ['l-io'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local io = io
+local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
+local concat = table.concat
+local floor = math.floor
+local type = type
+
+if string.find(os.getenv("PATH"),";",1,true) then
+ io.fileseparator, io.pathseparator = "\\", ";"
+else
+ io.fileseparator, io.pathseparator = "/" , ":"
+end
+
+local function readall(f)
+ return f:read("*all")
+end
+
+-- The next one is upto 50% faster on large files and less memory consumption due
+-- to less intermediate large allocations. This phenomena was discussed on the
+-- luatex dev list.
+
+local function readall(f)
+ local size = f:seek("end")
+ if size == 0 then
+ return ""
+ elseif size < 1024*1024 then
+ f:seek("set",0)
+ return f:read('*all')
+ else
+ local done = f:seek("set",0)
+ local step
+ if size < 1024*1024 then
+ step = 1024 * 1024
+ elseif size > 16*1024*1024 then
+ step = 16*1024*1024
+ else
+ step = floor(size/(1024*1024)) * 1024 * 1024 / 8
+ end
+ local data = { }
+ while true do
+ local r = f:read(step)
+ if not r then
+ return concat(data)
+ else
+ data[#data+1] = r
+ end
+ end
+ end
+end
+
+io.readall = readall
+
+function io.loaddata(filename,textmode) -- return nil if empty
+ local f = io.open(filename,(textmode and 'r') or 'rb')
+ if f then
+ -- local data = f:read('*all')
+ local data = readall(f)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
+function io.savedata(filename,data,joiner)
+ local f = io.open(filename,"wb")
+ if f then
+ if type(data) == "table" then
+ f:write(concat(data,joiner or ""))
+ elseif type(data) == "function" then
+ data(f)
+ else
+ f:write(data or "")
+ end
+ f:close()
+ io.flush()
+ return true
+ else
+ return false
+ end
+end
+
+-- we can also chunk this one if needed: io.lines(filename,chunksize,"*l")
+
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if not f then
+ -- no file
+ elseif n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ f:close()
+ if #line > 0 then
+ return line
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
+function io.exists(filename)
+ local f = io.open(filename)
+ if f == nil then
+ return false
+ else
+ f:close()
+ return true
+ end
+end
+
+function io.size(filename)
+ local f = io.open(filename)
+ if f == nil then
+ return 0
+ else
+ local s = f:seek("end")
+ f:close()
+ return s
+ end
+end
+
+function io.noflines(f)
+ if type(f) == "string" then
+ local f = io.open(filename)
+ if f then
+ local n = f and io.noflines(f) or 0
+ f:close()
+ return n
+ else
+ return 0
+ end
+ else
+ local n = 0
+ for _ in f:lines() do
+ n = n + 1
+ end
+ f:seek('set',0)
+ return n
+ end
+end
+
+local nextchar = {
+ [ 4] = function(f)
+ return f:read(1,1,1,1)
+ end,
+ [ 2] = function(f)
+ return f:read(1,1)
+ end,
+ [ 1] = function(f)
+ return f:read(1)
+ end,
+ [-2] = function(f)
+ local a, b = f:read(1,1)
+ return b, a
+ end,
+ [-4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ return d, c, b, a
+ end
+}
+
+function io.characters(f,n)
+ if f then
+ return nextchar[n or 1], f
+ end
+end
+
+local nextbyte = {
+ [4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ if d then
+ return byte(a), byte(b), byte(c), byte(d)
+ end
+ end,
+ [3] = function(f)
+ local a, b, c = f:read(1,1,1)
+ if b then
+ return byte(a), byte(b), byte(c)
+ end
+ end,
+ [2] = function(f)
+ local a, b = f:read(1,1)
+ if b then
+ return byte(a), byte(b)
+ end
+ end,
+ [1] = function (f)
+ local a = f:read(1)
+ if a then
+ return byte(a)
+ end
+ end,
+ [-2] = function (f)
+ local a, b = f:read(1,1)
+ if b then
+ return byte(b), byte(a)
+ end
+ end,
+ [-3] = function(f)
+ local a, b, c = f:read(1,1,1)
+ if b then
+ return byte(c), byte(b), byte(a)
+ end
+ end,
+ [-4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ if d then
+ return byte(d), byte(c), byte(b), byte(a)
+ end
+ end
+}
+
+function io.bytes(f,n)
+ if f then
+ return nextbyte[n or 1], f
+ else
+ return nil, nil
+ end
+end
+
+function io.ask(question,default,options)
+ while true do
+ io.write(question)
+ if options then
+ io.write(format(" [%s]",concat(options,"|")))
+ end
+ if default then
+ io.write(format(" [%s]",default))
+ end
+ io.write(format(" "))
+ io.flush()
+ local answer = io.read()
+ answer = gsub(answer,"^%s*(.*)%s*$","%1")
+ if answer == "" and default then
+ return default
+ elseif not options then
+ return answer
+ else
+ for k=1,#options do
+ if options[k] == answer then
+ return answer
+ end
+ end
+ local pattern = "^" .. answer
+ for k=1,#options do
+ local v = options[k]
+ if find(v,pattern) then
+ return v
+ end
+ end
+ end
+ end
+end
+
+local function readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ if n == 1 then
+ return byte(f:read(1))
+ elseif n == 2 then
+ local a, b = byte(f:read(2),1,2)
+ return 256 * a + b
+ elseif n == 3 then
+ local a, b, c = byte(f:read(3),1,3)
+ return 256*256 * a + 256 * b + c
+ elseif n == 4 then
+ local a, b, c, d = byte(f:read(4),1,4)
+ return 256*256*256 * a + 256*256 * b + 256 * c + d
+ elseif n == 8 then
+ local a, b = readnumber(f,4), readnumber(f,4)
+ return 256 * a + b
+ elseif n == 12 then
+ local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
+ return 256*256 * a + 256 * b + c
+ elseif n == -2 then
+ local b, a = byte(f:read(2),1,2)
+ return 256*a + b
+ elseif n == -3 then
+ local c, b, a = byte(f:read(3),1,3)
+ return 256*256 * a + 256 * b + c
+ elseif n == -4 then
+ local d, c, b, a = byte(f:read(4),1,4)
+ return 256*256*256 * a + 256*256 * b + 256*c + d
+ elseif n == -8 then
+ local h, g, f, e, d, c, b, a = byte(f:read(8),1,8)
+ return 256*256*256*256*256*256*256 * a +
+ 256*256*256*256*256*256 * b +
+ 256*256*256*256*256 * c +
+ 256*256*256*256 * d +
+ 256*256*256 * e +
+ 256*256 * f +
+ 256 * g +
+ h
+ else
+ return 0
+ end
+end
+
+io.readnumber = readnumber
+
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ local str = gsub(f:read(n),"\000","")
+ return str
+end
+
+-- This works quite ok:
+--
+-- function io.piped(command,writer)
+-- local pipe = io.popen(command)
+-- -- for line in pipe:lines() do
+-- -- print(line)
+-- -- end
+-- while true do
+-- local line = pipe:read(1)
+-- if not line then
+-- break
+-- elseif line ~= "\n" then
+-- writer(line)
+-- end
+-- end
+-- return pipe:close() -- ok, status, (error)code
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-lpeg.lua b/Master/texmf-dist/tex/context/base/mkiv/l-lpeg.lua
new file mode 100644
index 00000000000..959ca553eb8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-lpeg.lua
@@ -0,0 +1,1173 @@
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- lpeg 12 vs lpeg 10: slower compilation, similar parsing speed (i need to check
+-- if i can use new features like capture / 2 and .B (at first sight the xml
+-- parser is some 5% slower)
+
+-- lpeg.P("abc") is faster than lpeg.P("a") * lpeg.P("b") * lpeg.P("c")
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
+
+lpeg = require("lpeg")
+
+-- The latest lpeg doesn't have print any more, and even the new ones are not
+-- available by default (only when debug mode is enabled), which is a pitty as
+-- as it helps nailing down bottlenecks. Performance seems comparable: some 10%
+-- slower pattern compilation, same parsing speed, although,
+--
+-- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1))
+-- local a = string.rep("123",100)
+-- lpeg.match(p,a)
+--
+-- seems slower and is also still suboptimal (i.e. a match that runs from begin
+-- to end, one of the cases where string matchers win).
+
+if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+-- some code will move to unicode and string
+
+-- local lpmatch = lpeg.match
+-- local lpprint = lpeg.print
+-- local lpp = lpeg.P
+-- local lpr = lpeg.R
+-- local lps = lpeg.S
+-- local lpc = lpeg.C
+-- local lpb = lpeg.B
+-- local lpv = lpeg.V
+-- local lpcf = lpeg.Cf
+-- local lpcb = lpeg.Cb
+-- local lpcg = lpeg.Cg
+-- local lpct = lpeg.Ct
+-- local lpcs = lpeg.Cs
+-- local lpcc = lpeg.Cc
+-- local lpcmt = lpeg.Cmt
+-- local lpcarg = lpeg.Carg
+
+-- function lpeg.match(l,...) print("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+-- function lpeg.P (l) local p = lpp (l) print("LPEG P =") lpprint(l) return p end
+-- function lpeg.R (l) local p = lpr (l) print("LPEG R =") lpprint(l) return p end
+-- function lpeg.S (l) local p = lps (l) print("LPEG S =") lpprint(l) return p end
+-- function lpeg.C (l) local p = lpc (l) print("LPEG C =") lpprint(l) return p end
+-- function lpeg.B (l) local p = lpb (l) print("LPEG B =") lpprint(l) return p end
+-- function lpeg.V (l) local p = lpv (l) print("LPEG V =") lpprint(l) return p end
+-- function lpeg.Cf (l) local p = lpcf (l) print("LPEG Cf =") lpprint(l) return p end
+-- function lpeg.Cb (l) local p = lpcb (l) print("LPEG Cb =") lpprint(l) return p end
+-- function lpeg.Cg (l) local p = lpcg (l) print("LPEG Cg =") lpprint(l) return p end
+-- function lpeg.Ct (l) local p = lpct (l) print("LPEG Ct =") lpprint(l) return p end
+-- function lpeg.Cs (l) local p = lpcs (l) print("LPEG Cs =") lpprint(l) return p end
+-- function lpeg.Cc (l) local p = lpcc (l) print("LPEG Cc =") lpprint(l) return p end
+-- function lpeg.Cmt (l) local p = lpcmt (l) print("LPEG Cmt =") lpprint(l) return p end
+-- function lpeg.Carg (l) local p = lpcarg(l) print("LPEG Carg =") lpprint(l) return p end
+
+local type, next, tostring = type, next, tostring
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
+----- mod, div = math.mod, math.div
+local floor = math.floor
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
+local lpegtype, lpegmatch, lpegprint = lpeg.type, lpeg.match, lpeg.print
+
+-- let's start with an inspector:
+
+if setinspector then
+ setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
+end
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local sign = S('+-')
+local zero = P('0')
+local digit = R('09')
+local octdigit = R("07")
+local lowercase = R("az")
+local uppercase = R("AZ")
+local underscore = P("_")
+local hexdigit = digit + lowercase + uppercase
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+----- newline = crlf + S("\r\n") -- cr + lf
+local newline = P("\r") * (P("\n") + P(true)) + P("\n") -- P("\r")^-1 * P("\n")^-1
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+local period = P(".")
+local comma = P(",")
+
+local utfbom_32_be = P('\000\000\254\255') -- 00 00 FE FF
+local utfbom_32_le = P('\255\254\000\000') -- FF FE 00 00
+local utfbom_16_be = P('\254\255') -- FE FF
+local utfbom_16_le = P('\255\254') -- FF FE
+local utfbom_8 = P('\239\187\191') -- EF BB BF
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfstricttype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8")
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
+
+local utf8next = R("\128\191")
+
+patterns.utfbom_32_be = utfbom_32_be
+patterns.utfbom_32_le = utfbom_32_le
+patterns.utfbom_16_be = utfbom_16_be
+patterns.utfbom_16_le = utfbom_16_le
+patterns.utfbom_8 = utfbom_8
+
+patterns.utf_16_be_nl = P("\000\r\000\n") + P("\000\r") + P("\000\n") -- P("\000\r") * (P("\000\n") + P(true)) + P("\000\n")
+patterns.utf_16_le_nl = P("\r\000\n\000") + P("\r\000") + P("\n\000") -- P("\r\000") * (P("\n\000") + P(true)) + P("\n\000")
+
+patterns.utf_32_be_nl = P("\000\000\000\r\000\000\000\n") + P("\000\000\000\r") + P("\000\000\000\n")
+patterns.utf_32_le_nl = P("\r\000\000\000\n\000\000\000") + P("\r\000\000\000") + P("\n\000\000\000")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+patterns.utfstricttype = utfstricttype
+patterns.utfoffset = utfoffset
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+local utf8character = P(1) * R("\128\191")^0 -- unchecked but fast
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.utf8character = utf8character -- this one can be used in most cases so we might use that one
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer ^0 * C((spacer ^0 * nonspacer ^1)^0) -- from example by roberto
+local fullstripper = whitespace^0 * C((whitespace^0 * nonwhitespace^1)^0)
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * endofstring / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^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_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)
+
+patterns.stripper = stripper
+patterns.fullstripper = fullstripper
+patterns.collapser = collapser
+
+patterns.b_collapser = b_collapser
+patterns.m_collapser = m_collapser
+patterns.e_collapser = e_collapser
+
+patterns.b_stripper = b_stripper
+patterns.m_stripper = m_stripper
+patterns.e_stripper = e_stripper
+
+patterns.lowercase = lowercase
+patterns.uppercase = uppercase
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.equal = P("=")
+patterns.comma = comma
+patterns.commaspacer = comma * spacer^0
+patterns.period = period
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = underscore
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
+patterns.digit = digit
+patterns.octdigit = octdigit
+patterns.hexdigit = hexdigit
+patterns.sign = sign
+patterns.cardinal = digit^1
+patterns.integer = sign^-1 * digit^1
+patterns.unsigned = digit^0 * period * digit^1
+patterns.float = sign^-1 * patterns.unsigned
+patterns.cunsigned = digit^0 * comma * digit^1
+patterns.cpunsigned = digit^0 * (period + comma) * digit^1
+patterns.cfloat = sign^-1 * patterns.cunsigned
+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 * octdigit^1
+patterns.octal = patterns.oct
+patterns.HEX = zero * P("X") * (digit+uppercase)^1
+patterns.hex = zero * P("x") * (digit+lowercase)^1
+patterns.hexadecimal = zero * S("xX") * hexdigit^1
+
+patterns.hexafloat = sign^-1
+ * zero * S("xX")
+ * (hexdigit^0 * period * hexdigit^1 + hexdigit^1 * period * hexdigit^0 + hexdigit^1)
+ * (S("pP") * sign^-1 * hexdigit^1)^-1
+patterns.decafloat = sign^-1
+ * (digit^0 * period * digit^1 + digit^1 * period * digit^0 + digit^1)
+ * S("eE") * sign^-1 * digit^1
+
+patterns.propername = (uppercase + lowercase + underscore) * (uppercase + lowercase + underscore + digit)^0 * endofstring
+
+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))
+
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
+end
+
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.split(str,separator)
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+
+-- lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+-- from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+--~ local str = " a b c d "
+
+--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]")
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(anything^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * endofstring)^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
+ local pattern
+ local u = isutf and utf8char or 1
+ if type(one) == "table" then
+ local no = #one
+ local p = P(false)
+ if no == 0 then
+ for k, v in next, one do
+ p = p + P(k) / v
+ end
+ pattern = Cs((p + u)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ -- pattern = Cs(((1-one)^1 + one/two)^0)
+ pattern = Cs((one/two + u)^0)
+ else
+ for i=1,no do
+ local o = one[i]
+ p = p + P(o[1]) / o[2]
+ end
+ pattern = Cs((p + u)^0)
+ end
+ else
+ pattern = Cs((P(one)/(two or "") + u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- local pattern1 = P(1-P(pattern))^0 * P(pattern) : test for not nil
+-- local pattern2 = (P(pattern) * Cc(true) + P(1))^0 : test for true (could be faster, but not much)
+
+function lpeg.finder(lst,makefunction,isutf) -- beware: slower than find with 'patternless finds'
+ local pattern
+ if type(lst) == "table" then
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
+ end
+ else
+ pattern = P(lst)
+ end
+ if isutf then
+ pattern = ((utf8char or 1)-pattern)^0 * pattern
+ else
+ pattern = (1-pattern)^0 * pattern
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ local pattern = P(separator)
+ splitter = C((1 - pattern)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ local pattern = P(separator)
+ splitter = (1 - pattern)^0 * pattern * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+local splitters_s, splitters_p = { }, { }
+
+function lpeg.beforesuffix(separator) -- nil if nothing but empty is ok
+ local splitter = splitters_s[separator]
+ if not splitter then
+ local pattern = P(separator)
+ splitter = C((1 - pattern)^0) * pattern * endofstring
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.afterprefix(separator) -- nil if nothing but empty is ok
+ local splitter = splitters_p[separator]
+ if not splitter then
+ local pattern = P(separator)
+ splitter = pattern * C(anything^0)
+ splitters_p[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ 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"))
+
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- table.sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local p_false = P(false)
+local p_true = P(true)
+
+local function make(t)
+ local function making(t)
+ local p = p_false
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ if k ~= "" then
+ local v = t[k]
+ if v == true then
+ p = p + P(k) * p_true
+ elseif v == false then
+ -- can't happen
+ else
+ p = p + P(k) * making(v)
+ end
+ end
+ end
+ if t[""] then
+ p = p + p_true
+ end
+ return p
+ end
+ local p = p_false
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ if k ~= "" then
+ local v = t[k]
+ if v == true then
+ p = p + P(k) * p_true
+ elseif v == false then
+ -- can't happen
+ else
+ p = p + P(k) * making(v)
+ end
+ end
+ end
+ return p
+end
+
+local function collapse(t,x)
+ if type(t) ~= "table" then
+ return t, x
+ else
+ local n = next(t)
+ if n == nil then
+ return t, x
+ elseif next(t,n) == nil then
+ -- one entry
+ local k = n
+ local v = t[k]
+ if type(v) == "table" then
+ return collapse(v,x..k)
+ else
+ return v, x .. k
+ end
+ else
+ local tt = { }
+ for k, v in next, t do
+ local vv, kk = collapse(v,k)
+ tt[kk] = vv
+ end
+ return tt, x
+ end
+ end
+end
+
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+ local tree = { }
+ local n = #list
+ if n == 0 then
+ for s in next, list do
+ local t = tree
+ local p, pk
+ for c in gmatch(s,".") do
+ if t == true then
+ t = { [c] = true, [""] = true }
+ p[pk] = t
+ p = t
+ t = false
+ elseif t == false then
+ t = { [c] = false }
+ p[pk] = t
+ p = t
+ t = false
+ else
+ local tc = t[c]
+ if not tc then
+ tc = false
+ t[c] = false
+ end
+ p = t
+ t = tc
+ end
+ pk = c
+ end
+ if t == false then
+ p[pk] = true
+ elseif t == true then
+ -- okay
+ else
+ t[""] = true
+ end
+ end
+ else
+ for i=1,n do
+ local s = list[i]
+ local t = tree
+ local p, pk
+ for c in gmatch(s,".") do
+ if t == true then
+ t = { [c] = true, [""] = true }
+ p[pk] = t
+ p = t
+ t = false
+ elseif t == false then
+ t = { [c] = false }
+ p[pk] = t
+ p = t
+ t = false
+ else
+ local tc = t[c]
+ if not tc then
+ tc = false
+ t[c] = false
+ end
+ p = t
+ t = tc
+ end
+ pk = c
+ end
+ if t == false then
+ p[pk] = true
+ elseif t == true then
+ -- okay
+ else
+ t[""] = true
+ end
+ end
+ end
+-- collapse(tree,"") -- needs testing, maybe optional, slightly faster because P("x")*P("X") seems slower than P"(xX") (why)
+-- inspect(tree)
+ return make(tree)
+end
+
+-- local t = { "start", "stoep", "staart", "paard" }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
+
+-- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
+
+-- inspect(lpegmatch(p,"a"))
+-- inspect(lpegmatch(p,"aa"))
+-- inspect(lpegmatch(p,"aaaa"))
+-- inspect(lpegmatch(p,"ac"))
+-- inspect(lpegmatch(p,"bc"))
+-- inspect(lpegmatch(p,"zzbczz"))
+-- inspect(lpegmatch(p,"zzabezz"))
+-- inspect(lpegmatch(p,"ab"))
+-- inspect(lpegmatch(p,"abc"))
+-- inspect(lpegmatch(p,"abe"))
+-- inspect(lpegmatch(p,"xa"))
+-- inspect(lpegmatch(p,"bx"))
+-- inspect(lpegmatch(p,"bax"))
+-- inspect(lpegmatch(p,"abxyz"))
+-- inspect(lpegmatch(p,"foobarbefcrap"))
+
+-- local t = { ["^"] = 1, ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1)
+-- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ "))
+
+-- local t = { ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1)
+-- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ "))
+
+-- lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- }
+
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
+
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
+
+-- The next pattern^n variant is based on an approach suggested
+-- by Roberto: constructing a big repetition in chunks.
+--
+-- Being sparse is not needed, and only complicate matters and
+-- the number of redundant entries is not that large.
+
+local function nextstep(n,step,result)
+ local m = n % step -- mod(n,step)
+ local d = floor(n/step) -- div(n,step)
+ if d > 0 then
+ local v = V(tostring(step))
+ local s = result.start
+ for i=1,d do
+ if s then
+ s = v * s
+ else
+ s = v
+ end
+ end
+ result.start = s
+ end
+ if step > 1 and result.start then
+ local v = V(tostring(step/2))
+ result[tostring(step)] = v * v
+ end
+ if step > 0 then
+ return nextstep(m,step/2,result)
+ else
+ return result
+ end
+end
+
+function lpeg.times(pattern,n)
+ return P(nextstep(n,2^16,{ "start", ["1"] = pattern }))
+end
+
+-- local p = lpeg.Cs((1 - lpeg.times(lpeg.P("AB"),25))^1)
+-- local s = "12" .. string.rep("AB",20) .. "34" .. string.rep("AB",30) .. "56"
+-- inspect(p)
+-- print(lpeg.match(p,s))
+
+-- 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 = digit^1 * (case_1 + case_2)
+local stripper = Cs((number + 1)^0)
+
+lpeg.patterns.stripzeros = stripper
+
+-- 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))
+
+-- for practical reasone we keep this here:
+
+local byte_to_HEX = { }
+local byte_to_hex = { }
+local byte_to_dec = { } -- for md5
+local hex_to_byte = { }
+
+for i=0,255 do
+ local H = format("%02X",i)
+ local h = format("%02x",i)
+ local d = format("%03i",i)
+ local c = char(i)
+ byte_to_HEX[c] = H
+ byte_to_hex[c] = h
+ byte_to_dec[c] = d
+ hex_to_byte[h] = c
+ hex_to_byte[H] = c
+end
+
+local hextobyte = P(2)/hex_to_byte
+local bytetoHEX = P(1)/byte_to_HEX
+local bytetohex = P(1)/byte_to_hex
+local bytetodec = P(1)/byte_to_dec
+local hextobytes = Cs(hextobyte^0)
+local bytestoHEX = Cs(bytetoHEX^0)
+local bytestohex = Cs(bytetohex^0)
+local bytestodec = Cs(bytetodec^0)
+
+patterns.hextobyte = hextobyte
+patterns.bytetoHEX = bytetoHEX
+patterns.bytetohex = bytetohex
+patterns.bytetodec = bytetodec
+patterns.hextobytes = hextobytes
+patterns.bytestoHEX = bytestoHEX
+patterns.bytestohex = bytestohex
+patterns.bytestodec = bytestodec
+
+function string.toHEX(s)
+ if not s or s == "" then
+ return s
+ else
+ return lpegmatch(bytestoHEX,s)
+ end
+end
+
+function string.tohex(s)
+ if not s or s == "" then
+ return s
+ else
+ return lpegmatch(bytestohex,s)
+ end
+end
+
+function string.todec(s)
+ if not s or s == "" then
+ return s
+ else
+ return lpegmatch(bytestodec,s)
+ end
+end
+
+function string.tobytes(s)
+ if not s or s == "" then
+ return s
+ else
+ return lpegmatch(hextobytes,s)
+ end
+end
+
+-- local h = "ADFE0345"
+-- local b = lpegmatch(patterns.hextobytes,h)
+-- print(h,b,string.tohex(b),string.toHEX(b))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua
new file mode 100644
index 00000000000..b90f37e3db3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['l-lua'] = {
+ 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"
+}
+
+-- potential issues with 5.3:
+
+-- i'm not sure yet if the int/float change is good for luatex
+
+-- math.min
+-- math.max
+-- tostring
+-- tonumber
+-- utf.*
+-- bit32
+
+-- compatibility hacksand helpers
+
+_MAJORVERSION, _MINORVERSION = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+
+_MAJORVERSION = tonumber(_MAJORVERSION) or 5
+_MINORVERSION = tonumber(_MINORVERSION) or 1
+_LUAVERSION = _MAJORVERSION + _MINORVERSION/10
+
+if _LUAVERSION < 5.2 and jit then
+ --
+ -- we want loadstring cum suis to behave like 5.2
+ --
+ _MINORVERSION = 2
+ _LUAVERSION = 5.2
+end
+
+-- lpeg
+
+if not lpeg then
+ lpeg = require("lpeg")
+end
+
+-- basics:
+
+if loadstring then
+
+ local loadnormal = load
+
+ function load(first,...)
+ if type(first) == "string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+
+else
+
+ loadstring = load
+
+end
+
+-- table:
+
+-- At some point it was announced that i[pairs would be dropped, which makes
+-- sense. As we already used the for loop and # in most places the impact on
+-- ConTeXt was not that large; the remaining ipairs already have been replaced.
+-- Hm, actually ipairs was retained, but we no longer use it anyway (nor
+-- pairs).
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- The unpack function has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+
+ table.unpack = _G.unpack
+
+elseif not unpack then
+
+ _G.unpack = table.unpack
+
+end
+
+-- package:
+
+-- if not package.seachers then
+--
+-- package.searchers = package.loaders -- 5.2
+--
+-- elseif not package.loaders then
+--
+-- package.loaders = package.searchers
+--
+-- end
+
+if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type
+
+ package.loaders = package.searchers
+
+end
+
+-- moved from util-deb to here:
+
+local print, select, tostring = print, select, tostring
+
+local inspectors = { }
+
+function setinspector(kind,inspector) -- global function
+ inspectors[kind] = inspector
+end
+
+function inspect(...) -- global function
+ for s=1,select("#",...) do
+ local value = select(s,...)
+ if value == nil then
+ print("nil")
+ else
+ local done = false
+ -- type driven (table)
+ local kind = type(value)
+ local inspector = inspectors[kind]
+ if inspector then
+ done = inspector(value)
+ if done then
+ break
+ end
+ end
+ -- whatever driven (token, node, ...)
+ for kind, inspector in next, inspectors do
+ done = inspector(value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
+ end
+ end
+ end
+end
+
+--
+
+local dummy = function() end
+
+function optionalrequire(...)
+ local ok, result = xpcall(require,dummy,...)
+ if ok then
+ return result
+ end
+end
+
+-- nice for non ascii scripts (this might move):
+
+if lua then
+ lua.mask = load([[τεχ = 1]]) and "utf" or "ascii"
+end
+
+local flush = io.flush
+
+if flush then
+
+ local execute = os.execute if execute then function os.execute(...) flush() return execute(...) end end
+ local exec = os.exec if exec then function os.exec (...) flush() return exec (...) end end
+ local spawn = os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
+ local popen = io.popen if popen then function io.popen (...) flush() return popen (...) end end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-math.lua b/Master/texmf-dist/tex/context/base/mkiv/l-math.lua
new file mode 100644
index 00000000000..ec62919b46a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-math.lua
@@ -0,0 +1,38 @@
+if not modules then modules = { } end modules ['l-math'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
+
+if not math.ceiling then
+ math.ceiling = math.ceil
+end
+
+if not math.round then
+ function math.round(x) return floor(x + 0.5) end
+end
+
+if not math.div then
+ function math.div(n,m) return floor(n/m) end
+end
+
+if not math.mod then
+ function math.mod(n,m) return n % m end
+end
+
+local pipi = 2*math.pi/360
+
+if not math.sind then
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
+end
+
+if not math.odd then
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-md5.lua b/Master/texmf-dist/tex/context/base/mkiv/l-md5.lua
new file mode 100644
index 00000000000..00272c873f1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-md5.lua
@@ -0,0 +1,107 @@
+if not modules then modules = { } end modules ['l-md5'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This also provides file checksums and checkers.
+
+if not md5 then
+ md5 = optionalrequire("md5")
+end
+
+if not md5 then
+ md5 = {
+ sum = function(str) print("error: md5 is not loaded (sum ignored)") return str end,
+ sumhexa = function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
+ }
+end
+
+local md5, file = md5, file
+local gsub = string.gsub
+
+-- local gsub, format, byte = string.gsub, string.format, string.byte
+--
+-- local function convert(str,fmt)
+-- return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
+-- end
+--
+-- if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
+-- if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
+-- if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+
+do
+
+ local patterns = lpeg and lpeg.patterns
+
+ if patterns then
+
+ local bytestoHEX = patterns.bytestoHEX
+ local bytestohex = patterns.bytestohex
+ local bytestodec = patterns.bytestodec
+
+ local lpegmatch = lpeg.match
+ local md5sum = md5.sum
+
+ if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
+ if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
+ if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
+
+ end
+
+end
+
+function file.needsupdating(oldname,newname,threshold) -- size modification access change
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime = lfs.attributes(newname,"modification")
+ if not newtime then
+ return true -- no new file, so no updating needed
+ elseif newtime >= oldtime then
+ return false -- new file definitely needs updating
+ elseif oldtime - newtime < (threshold or 1) then
+ return false -- new file is probably still okay
+ else
+ return true -- new file has to be updated
+ end
+ else
+ return false -- no old file, so no updating needed
+ end
+end
+
+file.needs_updating = file.needsupdating
+
+function file.syncmtimes(oldname,newname)
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
+ end
+end
+
+function file.checksum(name)
+ if md5 then
+ local data = io.loaddata(name)
+ if data then
+ return md5.HEX(data)
+ end
+ end
+ return nil
+end
+
+function file.loadchecksum(name)
+ if md5 then
+ local data = io.loaddata(name .. ".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
+end
+
+function file.savechecksum(name,checksum)
+ if not checksum then checksum = file.checksum(name) end
+ if checksum then
+ io.savedata(name .. ".md5",checksum)
+ return checksum
+ end
+ return nil
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-number.lua b/Master/texmf-dist/tex/context/base/mkiv/l-number.lua
new file mode 100644
index 00000000000..001ca31f773
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-number.lua
@@ -0,0 +1,207 @@
+if not modules then modules = { } end modules ['l-number'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module will be replaced when we have the bit library .. the number based sets
+-- might go away
+
+local tostring, tonumber = tostring, tonumber
+local format, floor, match, rep = string.format, math.floor, string.match, string.rep
+local concat, insert = table.concat, table.insert
+local lpegmatch = lpeg.match
+
+number = number or { }
+local number = number
+
+if bit32 then -- I wonder if this is faster
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p) -- why not bor?
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
+
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "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
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+
+function number.toevenhex(n)
+ local s = format("%X",n)
+ if #s % 2 == 0 then
+ return s
+ else
+ return "0" .. s
+ end
+end
+
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
+--
+-- for i=1,1000000 do
+-- local a,b,c,d,e,f,g,h = number.toset(12345678)
+-- local a,b,c,d = number.toset(1234)
+-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
+-- end
+
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
+
+function number.toset(n)
+ return lpegmatch(one,tostring(n))
+end
+
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
+ local m = n % 2
+ local n = floor(n/2)
+ if m > 0 then
+ return bits(n, i+1, i, ...)
+ else
+ return bits(n, i+1, ...)
+ end
+ else
+ return ...
+ end
+end
+
+function number.bits(n)
+ return { bits(n,1) }
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-os.lua b/Master/texmf-dist/tex/context/base/mkiv/l-os.lua
new file mode 100644
index 00000000000..0a86ea6d697
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-os.lua
@@ -0,0 +1,558 @@
+if not modules then modules = { } end modules ['l-os'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This file deals with some operating system issues. Please don't bother me
+-- with the pros and cons of operating systems as they all have their flaws
+-- and benefits. Bashing one of them won't help solving problems and fixing
+-- bugs faster and is a waste of time and energy.
+--
+-- path separators: / or \ ... we can use / everywhere
+-- suffixes : dll so exe <none> ... no big deal
+-- quotes : we can use "" in most cases
+-- expansion : unless "" are used * might give side effects
+-- piping/threads : somewhat different for each os
+-- locations : specific user file locations and settings can change over time
+--
+-- os.type : windows | unix (new, we already guessed os.platform)
+-- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
+-- os.platform : extended os.name with architecture
+
+-- os.sleep() => socket.sleep()
+-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
+
+local os = os
+local date, time = os.date, os.time
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
+local concat = table.concat
+local random, ceil, randomseed = math.random, math.ceil, math.randomseed
+local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
+
+-- The following code permits traversing the environment table, at least
+-- in luatex. Internally all environment names are uppercase.
+
+-- The randomseed in Lua is not that random, although this depends on the operating system as well
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
+
+math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+
+randomseed(math.initialseed)
+
+if not os.__getenv__ then
+
+ os.__getenv__ = os.getenv
+ os.__setenv__ = os.setenv
+
+ if os.env then
+
+ local osgetenv = os.getenv
+ local ossetenv = os.setenv
+ local osenv = os.env local _ = osenv.PATH -- initialize the table
+
+ function os.setenv(k,v)
+ if v == nil then
+ v = ""
+ end
+ local K = upper(k)
+ osenv[K] = v
+ if type(v) == "table" then
+ v = concat(v,";") -- path
+ end
+ ossetenv(K,v)
+ end
+
+ function os.getenv(k)
+ local K = upper(k)
+ local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
+ if v == "" then
+ return nil
+ else
+ return v
+ end
+ end
+
+ else
+
+ local ossetenv = os.setenv
+ local osgetenv = os.getenv
+ local osenv = { }
+
+ function os.setenv(k,v)
+ if v == nil then
+ v = ""
+ end
+ local K = upper(k)
+ osenv[K] = v
+ end
+
+ function os.getenv(k)
+ local K = upper(k)
+ local v = osenv[K] or osgetenv(K) or osgetenv(k)
+ if v == "" then
+ return nil
+ else
+ return v
+ end
+ end
+
+ local function __index(t,k)
+ return os.getenv(k)
+ end
+ local function __newindex(t,k,v)
+ os.setenv(k,v)
+ end
+
+ os.env = { }
+
+ setmetatable(os.env, { __index = __index, __newindex = __newindex } )
+
+ end
+
+end
+
+-- end of environment hack
+
+local execute = os.execute
+local iopopen = io.popen
+
+function os.resultof(command)
+ local handle = iopopen(command,"r") -- already has flush
+ if handle then
+ local result = handle:read("*all") or ""
+ handle:close()
+ return result
+ else
+ return ""
+ end
+end
+
+if not io.fileseparator then
+ if find(os.getenv("PATH"),";",1,true) then
+ io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+ else
+ io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
+ end
+end
+
+os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
+os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
+
+if os.type == "windows" then
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
+else
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
+end
+
+local launchers = {
+ windows = "start %s",
+ macosx = "open %s",
+ unix = "$BROWSER %s &> /dev/null &",
+}
+
+function os.launch(str)
+ execute(format(launchers[os.name] or launchers.unix,str))
+end
+
+if not os.times then -- ?
+ -- utime = user time
+ -- stime = system time
+ -- cutime = children user time
+ -- cstime = children system time
+ function os.times()
+ return {
+ utime = os.gettimeofday(), -- user
+ stime = 0, -- system
+ cutime = 0, -- children user
+ cstime = 0, -- children system
+ }
+ end
+end
+
+
+local gettimeofday = os.gettimeofday or os.clock
+os.gettimeofday = gettimeofday
+
+local startuptime = gettimeofday()
+
+function os.runtime()
+ return gettimeofday() - startuptime
+end
+
+-- print(os.gettimeofday()-os.time())
+-- os.sleep(1.234)
+-- print (">>",os.runtime())
+-- print(os.date("%H:%M:%S",os.gettimeofday()))
+-- print(os.date("%H:%M:%S",os.time()))
+
+-- no need for function anymore as we have more clever code and helpers now
+-- this metatable trickery might as well disappear
+
+local resolvers = os.resolvers or { }
+os.resolvers = resolvers
+
+setmetatable(os, { __index = function(t,k)
+ local r = resolvers[k]
+ return r and r(t,k) or nil -- no memoize
+end })
+
+-- we can use HOSTTYPE on some platforms
+
+local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
+
+local function guess()
+ local architecture = os.resultof("uname -m") or ""
+ if architecture ~= "" then
+ return architecture
+ end
+ architecture = os.getenv("HOSTTYPE") or ""
+ if architecture ~= "" then
+ return architecture
+ end
+ return os.resultof("echo $HOSTTYPE") or ""
+end
+
+-- os.bits = 32 | 64
+
+if platform ~= "" then
+
+ os.platform = platform
+
+elseif os.type == "windows" then
+
+ -- we could set the variable directly, no function needed here
+
+ -- PROCESSOR_ARCHITECTURE : binary platform
+ -- PROCESSOR_ARCHITEW6432 : OS platform
+
+ function resolvers.platform(t,k)
+ local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ if find(architecture,"AMD64",1,true) then
+ -- platform = "mswin-64"
+ platform = "win64"
+ else
+ platform = "mswin"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+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 os.resultof("uname -m") or ""
+ if find(architecture,"x86_64",1,true) then
+ platform = "linux-64"
+ elseif find(architecture,"ppc",1,true) then
+ platform = "linux-ppc"
+ else
+ platform = "linux"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "macosx" then
+
+ --[[
+ Identifying the architecture of OSX is quite a mess and this
+ is the best we can come up with. For some reason $HOSTTYPE is
+ a kind of pseudo environment variable, not known to the current
+ environment. And yes, uname cannot be trusted either, so there
+ is a change that you end up with a 32 bit run on a 64 bit system.
+ Also, some proper 64 bit intel macs are too cheap (low-end) and
+ therefore not permitted to run the 64 bit kernel.
+ ]]--
+
+ function resolvers.platform(t,k)
+ -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
+ -- if architecture == "" then
+ -- architecture = os.resultof("echo $HOSTTYPE") or ""
+ -- end
+ local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
+ 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"
+ elseif find(architecture,"i386",1,true) then
+ platform = "osx-intel"
+ elseif find(architecture,"x86_64",1,true) then
+ platform = "osx-64"
+ else
+ platform = "osx-ppc"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "sunos" then
+
+ function resolvers.platform(t,k)
+ local platform, architecture = "", os.resultof("uname -m") or ""
+ if find(architecture,"sparc",1,true) then
+ platform = "solaris-sparc"
+ else -- if architecture == 'i86pc'
+ platform = "solaris-intel"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "freebsd" then
+
+ function resolvers.platform(t,k)
+ local platform, architecture = "", os.resultof("uname -m") or ""
+ if find(architecture,"amd64",1,true) then
+ platform = "freebsd-amd64"
+ else
+ platform = "freebsd"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+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 os.resultof("uname -m") or ""
+ if find(architecture,"x86_64",1,true) then
+ platform = "kfreebsd-amd64"
+ else
+ platform = "kfreebsd-i386"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+else
+
+ -- platform = "linux"
+ -- os.setenv("MTX_PLATFORM",platform)
+ -- os.platform = platform
+
+ function resolvers.platform(t,k)
+ local platform = "linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+end
+
+os.newline = name == "windows" and "\013\010" or "\010" -- crlf or lf
+
+function resolvers.bits(t,k)
+ local bits = find(os.platform,"64",1,true) and 64 or 32
+ os.bits = bits
+ return bits
+end
+
+-- beware, we set the randomseed
+
+-- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
+-- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
+-- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
+-- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
+--
+-- as we don't call this function too often there is not so much risk on repetition
+
+local t = { 8, 9, "a", "b" }
+
+function os.uuid()
+ return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+ random(0xFFFF),random(0xFFFF),
+ random(0x0FFF),
+ t[ceil(random(4))] or 8,random(0x0FFF),
+ random(0xFFFF),
+ random(0xFFFF),random(0xFFFF),random(0xFFFF)
+ )
+end
+
+local d
+
+function os.timezone(delta)
+ d = d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+ if d > 0 then
+ return format("+%02i:00",d)
+ else
+ return format("-%02i:00",-d)
+ end
+ else
+ return 1
+ end
+end
+
+local timeformat = format("%%s%s",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+local lasttime = nil
+local lastdate = nil
+
+function os.fulltime(t,default)
+ t = t and tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = time()
+ end
+ if t ~= lasttime then
+ lasttime = t
+ lastdate = format(timeformat,date(dateformat))
+ end
+ return lastdate
+end
+
+local dateformat = "%Y-%m-%d %H:%M:%S"
+local lasttime = nil
+local lastdate = nil
+
+function os.localtime(t,default)
+ t = t and tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = time()
+ end
+ if t ~= lasttime then
+ lasttime = t
+ lastdate = date(dateformat,t)
+ end
+ return lastdate
+end
+
+function os.converttime(t,default)
+ local t = tonumber(t)
+ if t and t > 0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+function os.today()
+ return date("!*t") -- table with values
+end
+
+function os.now()
+ return date("!%Y-%m-%d %H:%M:%S") -- 2011-12-04 14:59:12
+end
+
+-- if not os.sleep and socket then
+-- os.sleep = socket.sleep
+-- end
+
+if not os.sleep then
+ local socket = socket
+ function os.sleep(n)
+ if not socket then
+ -- so we delay ... if os.sleep is really needed then one should also
+ -- be sure that socket can be found
+ socket = require("socket")
+ end
+ socket.sleep(n)
+ end
+end
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
+-- These are moved from core-con.lua (as I needed them elsewhere).
+
+local function isleapyear(year)
+ return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0))
+end
+
+os.isleapyear = isleapyear
+
+-- nicer:
+--
+-- local days = {
+-- [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+-- [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+-- }
+--
+-- local function nofdays(year,month)
+-- return days[isleapyear(year)][month]
+-- return month == 2 and isleapyear(year) and 29 or days[month]
+-- end
+--
+-- more efficient:
+
+local days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+
+local function nofdays(year,month)
+ if not month then
+ return isleapyear(year) and 365 or 364
+ else
+ return month == 2 and isleapyear(year) and 29 or days[month]
+ end
+end
+
+os.nofdays = nofdays
+
+function os.weekday(day,month,year)
+ return date("%w",time { year = year, month = month, day = day }) + 1
+end
+
+function os.validdate(year,month,day)
+ -- we assume that all three values are set
+ -- year is always ok, even if lua has a 1970 time limit
+ if month < 1 then
+ month = 1
+ elseif month > 12 then
+ month = 12
+ end
+ if day < 1 then
+ day = 1
+ else
+ local max = nofdays(year,month)
+ if day > max then
+ day = max
+ end
+ end
+ return year, month, day
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-package.lua b/Master/texmf-dist/tex/context/base/mkiv/l-package.lua
new file mode 100644
index 00000000000..075fcde25ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-package.lua
@@ -0,0 +1,362 @@
+if not modules then modules = { } end modules ['l-package'] = {
+ 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"
+}
+
+-- Code moved from data-lua and changed into a plug-in.
+
+-- We overload the regular loader. We do so because we operate mostly in
+-- tds and use our own loader code. Alternatively we could use a more
+-- extensive definition of package.path and package.cpath but even then
+-- we're not done. Also, we now have better tracing.
+--
+-- -- local mylib = require("libtest")
+-- -- local mysql = require("luasql.mysql")
+
+local type = type
+local gsub, format, find = string.gsub, string.format, string.find
+
+local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match
+
+local package = package
+local searchers = package.searchers or package.loaders
+
+-- dummies
+
+local filejoin = file and file.join or function(path,name) return path .. "/" .. name end
+local isreadable = file and file.is_readable or function(name) local f = io.open(name) if f then f:close() return true end end
+local addsuffix = file and file.addsuffix or function(name,suffix) return name .. "." .. suffix end
+
+-- local separator, concatinator, placeholder, pathofexecutable, ignorebefore = string.match(package.config,"(.-)\n(.-)\n(.-)\n(.-)\n(.-)\n")
+--
+-- local config = {
+-- separator = separator, -- \ or /
+-- concatinator = concatinator, -- ;
+-- placeholder = placeholder, -- ? becomes name
+-- pathofexecutable = pathofexecutable, -- ! becomes executables dir (on windows)
+-- ignorebefore = ignorebefore, -- - remove all before this when making lua_open
+-- }
+
+local function cleanpath(path) -- hm, don't we have a helper for this?
+ return path
+end
+
+local pattern = Cs((((1-S("\\/"))^0 * (S("\\/")^1/"/"))^0 * (P(".")^1/"/"+P(1))^1) * -1)
+
+local function lualibfile(name)
+ return lpegmatch(pattern,name) or name
+end
+
+local offset = luarocks and 1 or 0 -- todo: also check other extras
+
+local helpers = package.helpers or {
+ cleanpath = cleanpath,
+ lualibfile = lualibfile,
+ trace = false,
+ report = function(...) print(format(...)) end,
+ builtin = {
+ ["preload table"] = searchers[1+offset], -- special case, built-in libs
+ ["path specification"] = searchers[2+offset],
+ ["cpath specification"] = searchers[3+offset],
+ ["all in one fallback"] = searchers[4+offset], -- special case, combined libs
+ },
+ methods = {
+ },
+ sequence = {
+ "already loaded",
+ "preload table",
+ "qualified path", -- beware, lua itself doesn't handle qualified paths (prepends ./)
+ "lua extra list",
+ "lib extra list",
+ "path specification",
+ "cpath specification",
+ "all in one fallback",
+ "not loaded",
+ }
+}
+
+package.helpers = helpers
+
+local methods = helpers.methods
+local builtin = helpers.builtin
+
+-- extra tds/ctx paths ... a bit of overhead for efficient tracing
+
+local extraluapaths = { }
+local extralibpaths = { }
+local luapaths = nil -- delayed
+local libpaths = nil -- delayed
+local oldluapath = nil
+local oldlibpath = nil
+
+local nofextralua = -1
+local nofextralib = -1
+local nofpathlua = -1
+local nofpathlib = -1
+
+local function listpaths(what,paths)
+ local nofpaths = #paths
+ if nofpaths > 0 then
+ for i=1,nofpaths do
+ helpers.report("using %s path %i: %s",what,i,paths[i])
+ end
+ else
+ helpers.report("no %s paths defined",what)
+ end
+ return nofpaths
+end
+
+local function getextraluapaths()
+ if helpers.trace and #extraluapaths ~= nofextralua then
+ nofextralua = listpaths("extra lua",extraluapaths)
+ end
+ return extraluapaths
+end
+
+local function getextralibpaths()
+ if helpers.trace and #extralibpaths ~= nofextralib then
+ nofextralib = listpaths("extra lib",extralibpaths)
+ end
+ return extralibpaths
+end
+
+local function getluapaths()
+ local luapath = package.path or ""
+ if oldluapath ~= luapath then
+ luapaths = file.splitpath(luapath,";")
+ oldluapath = luapath
+ nofpathlua = -1
+ end
+ if helpers.trace and #luapaths ~= nofpathlua then
+ nofpathlua = listpaths("builtin lua",luapaths)
+ end
+ return luapaths
+end
+
+local function getlibpaths()
+ local libpath = package.cpath or ""
+ if oldlibpath ~= libpath then
+ libpaths = file.splitpath(libpath,";")
+ oldlibpath = libpath
+ nofpathlib = -1
+ end
+ if helpers.trace and #libpaths ~= nofpathlib then
+ nofpathlib = listpaths("builtin lib",libpaths)
+ end
+ return libpaths
+end
+
+package.luapaths = getluapaths
+package.libpaths = getlibpaths
+package.extraluapaths = getextraluapaths
+package.extralibpaths = getextralibpaths
+
+local hashes = {
+ lua = { },
+ lib = { },
+}
+
+local function registerpath(tag,what,target,...)
+ local pathlist = { ... }
+ local cleanpath = helpers.cleanpath
+ local trace = helpers.trace
+ local report = helpers.report
+ local hash = hashes[what]
+ --
+ local function add(path)
+ local path = cleanpath(path)
+ if not hash[path] then
+ target[#target+1] = path
+ hash[path] = true
+ if trace then
+ report("registered %s path %s: %s",tag,#target,path)
+ end
+ else
+ if trace then
+ report("duplicate %s path: %s",tag,path)
+ end
+ end
+ end
+ --
+ for p=1,#pathlist do
+ local path = pathlist[p]
+ if type(path) == "table" then
+ for i=1,#path do
+ add(path[i])
+ end
+ else
+ add(path)
+ end
+ end
+ return paths
+end
+
+helpers.registerpath = registerpath
+
+function package.extraluapath(...)
+ registerpath("extra lua","lua",extraluapaths,...)
+end
+
+function package.extralibpath(...)
+ registerpath("extra lib","lib",extralibpaths,...)
+end
+
+-- lib loader (used elsewhere)
+
+local function loadedaslib(resolved,rawname) -- todo: strip all before first -
+ local base = gsub(rawname,"%.","_")
+ -- so, we can do a require("foo/bar") and initialize bar
+ -- local base = gsub(file.basename(rawname),"%.","_")
+ local init = "luaopen_" .. gsub(base,"%.","_")
+ if helpers.trace then
+ helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
+end
+
+helpers.loadedaslib = loadedaslib
+
+-- wrapped and new loaders
+
+local function loadedbypath(name,rawname,paths,islib,what)
+ local trace = helpers.trace
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = filejoin(path,name)
+ if trace then
+ helpers.report("%s path, identifying '%s' on '%s'",what,name,path)
+ end
+ if isreadable(resolved) then
+ if trace then
+ helpers.report("%s path, '%s' found on '%s'",what,name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
+ end
+ end
+ end
+end
+
+helpers.loadedbypath = loadedbypath
+
+local function loadedbyname(name,rawname)
+ if find(name,"^/") or find(name,"^[a-zA-Z]:/") then
+ local trace=helpers.trace
+ if trace then
+ helpers.report("qualified name, identifying '%s'",what,name)
+ end
+ if isreadable(name) then
+ if trace then
+ helpers.report("qualified name, '%s' found",what,name)
+ end
+ return loadfile(name)
+ end
+ end
+end
+
+helpers.loadedbyname = loadedbyname
+
+methods["already loaded"] = function(name)
+ return package.loaded[name]
+end
+
+methods["preload table"] = function(name)
+ return builtin["preload table"](name)
+end
+
+methods["qualified path"]=function(name)
+ return loadedbyname(addsuffix(lualibfile(name),"lua"),name)
+end
+
+methods["lua extra list"] = function(name)
+ return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua")
+end
+
+methods["lib extra list"] = function(name)
+ return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true, "lib")
+end
+
+methods["path specification"] = function(name)
+ getluapaths() -- triggers list building and tracing
+ return builtin["path specification"](name)
+end
+
+methods["cpath specification"] = function(name)
+ getlibpaths() -- triggers list building and tracing
+ return builtin["cpath specification"](name)
+end
+
+methods["all in one fallback"] = function(name)
+ return builtin["all in one fallback"](name)
+end
+
+methods["not loaded"] = function(name)
+ if helpers.trace then
+ helpers.report("unable to locate '%s'",name or "?")
+ end
+ return nil
+end
+
+local level = 0
+local used = { }
+
+helpers.traceused = false
+
+function helpers.loaded(name)
+ local sequence = helpers.sequence
+ level = level + 1
+ for i=1,#sequence do
+ local method = sequence[i]
+ if helpers.trace then
+ helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name)
+ end
+ local result, rest = methods[method](name)
+ if type(result) == "function" then
+ if helpers.trace then
+ helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name)
+ end
+ if helpers.traceused then
+ used[#used+1] = { level = level, name = name }
+ end
+ level = level - 1
+ return result, rest
+ end
+ end
+ -- safeguard, we never come here
+ level = level - 1
+ return nil
+end
+
+function helpers.showused()
+ local n = #used
+ if n > 0 then
+ helpers.report("%s libraries loaded:",n)
+ helpers.report()
+ for i=1,n do
+ local u = used[i]
+ helpers.report("%i %a",u.level,u.name)
+ end
+ helpers.report()
+ end
+end
+
+function helpers.unload(name)
+ if helpers.trace then
+ if package.loaded[name] then
+ helpers.report("unloading, name '%s', %s",name,"done")
+ else
+ helpers.report("unloading, name '%s', %s",name,"not loaded")
+ end
+ end
+ package.loaded[name] = nil
+end
+
+-- overloading require does not work out well so we need to push it in
+-- front ..
+
+table.insert(searchers,1,helpers.loaded)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-pdfview.lua b/Master/texmf-dist/tex/context/base/mkiv/l-pdfview.lua
new file mode 100644
index 00000000000..6302fd6f6ac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-pdfview.lua
@@ -0,0 +1,180 @@
+if not modules then modules = { } end modules ['l-pdfview'] = {
+ version = 1.001,
+ comment = "companion to mtx-context.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Todo: add options in cnf file
+
+-- Todo: figure out pdfopen/pdfclose on linux. Calling e.g. okular directly
+-- doesn't work in linux when issued from scite as it blocks the editor (no
+-- & possible or so). Unfortunately pdfopen keeps changing with not keeping
+-- downward compatibility (command line arguments and so).
+
+-- no 2>&1 any more, needs checking on windows
+
+local format, concat = string.format, table.concat
+
+local report = logs.reporter("pdfview")
+local replace = utilities.templates.replace
+
+pdfview = pdfview or { }
+
+local opencalls -- a table with templates that open a given pdf document
+local closecalls -- a table with templates that close a given pdf document
+local allcalls -- a table with templates that close all open pdf documents
+local runner -- runner function
+local expander -- filename cleanup function
+
+-- maybe spawn/execute spec in calls
+
+if os.type == "windows" then
+
+ -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/pdf-xchange")
+ -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/sumatrapdf")
+
+ -- start is more flexible as it locates binaries in more places and doesn't lock
+
+ opencalls = {
+ ['default'] = [[pdfopen --rxi --file "%filename%"]],
+ ['acrobat'] = [[pdfopen --rxi --file "%filename%"]],
+ ['fullacrobat'] = [[pdfopen --axi --file "%filename%"]],
+ ['okular'] = [[start "test" okular.exe --unique "%filename%"]],
+ ['pdfxcview'] = [[start "test" pdfxcview.exe /A "nolock=yes=OpenParameters" "%filename%"]],
+ ['sumatra'] = [[start "test" sumatrapdf.exe -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
+ ['auto'] = [[start "%filename%"]],
+ }
+ closecalls= {
+ ['default'] = [[pdfclose --file "%filename%"]],
+ ['acrobat'] = [[pdfclose --file "%filename%"]],
+ ['okular'] = false,
+ ['pdfxcview'] = false, -- [[pdfxcview.exe /close:discard "%filename%"]],
+ ['sumatra'] = false,
+ ['auto'] = false,
+ }
+ allcalls = {
+ ['default'] = [[pdfclose --all]],
+ ['acrobat'] = [[pdfclose --all]],
+ ['okular'] = false,
+ ['pdfxcview'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
+ }
+
+ pdfview.method = "acrobat" -- no longer useful due to green pop up line and clashing reader/full
+ -- pdfview.method = "pdfxcview"
+ pdfview.method = "sumatra"
+
+ runner = function(template,variables)
+ local cmd = replace(template,variables)
+ -- cmd = cmd .. " > /null"
+ report("command: %s",cmd)
+ os.execute(cmd)
+ end
+
+ expander = function(name)
+ -- We need to avoid issues with chdir to UNC paths and therefore expand
+ -- the path when we're current. (We could use one of the helpers instead)
+ if file.pathpart(name) == "" then
+ return file.collapsepath(file.join(lfs.currentdir(),name))
+ else
+ return name
+ end
+ end
+
+else
+
+ opencalls = {
+ ['default'] = [[pdfopen "%filename%"]],
+ ['okular'] = [[okular --unique "%filename%"]],
+ ['sumatra'] = [[wine "sumatrapdf.exe" -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
+ ['pdfxcview'] = [[wine "pdfxcview.exe" /A "nolock=yes=OpenParameters" "%filename%"]],
+ ['auto'] = [[open "%filename%"]],
+ }
+ closecalls= {
+ ['default'] = [[pdfclose --file "%filename%"]],
+ ['okular'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
+ }
+ allcalls = {
+ ['default'] = [[pdfclose --all]],
+ ['okular'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
+ }
+
+ pdfview.method = "okular"
+ pdfview.method = "sumatra" -- faster and more complete
+
+ runner = function(template,variables)
+ local cmd = replace(template,variables)
+ cmd = cmd .. " 1>/dev/null 2>/dev/null &"
+ report("command: %s",cmd)
+ os.execute(cmd)
+ end
+
+ expander = function(name)
+ return name
+ end
+
+end
+
+directives.register("pdfview.method", function(v)
+ pdfview.method = (opencalls[v] and v) or 'default'
+end)
+
+function pdfview.setmethod(method)
+ if method and opencalls[method] then
+ pdfview.method = method
+ end
+end
+
+function pdfview.methods()
+ return concat(table.sortedkeys(opencalls), " ")
+end
+
+function pdfview.status()
+ return format("pdfview methods: %s, current method: %s (directives_pdfview_method)",pdfview.methods(),tostring(pdfview.method))
+end
+
+local function fullname(name)
+ return file.addsuffix(name,"pdf")
+end
+
+function pdfview.open(...)
+ local opencall = opencalls[pdfview.method]
+ if opencall then
+ local t = { ... }
+ for i=1,#t do
+ local name = expander(fullname(t[i]))
+ if io.exists(name) then
+ runner(opencall,{ filename = name })
+ end
+ end
+ end
+end
+
+function pdfview.close(...)
+ local closecall = closecalls[pdfview.method]
+ if closecall then
+ local t = { ... }
+ for i=1,#t do
+ local name = expander(fullname(t[i]))
+ if io.exists(name) then
+ replace(closecall,{ filename = name })
+ end
+ end
+ end
+end
+
+function pdfview.closeall()
+ local allcall = allcalls[pdfview.method]
+ if allcall then
+ runner(allcall)
+ end
+end
+
+return pdfview
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua b/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua
new file mode 100644
index 00000000000..f7901379cd7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua
@@ -0,0 +1,271 @@
+if not modules then modules = { } end modules ['l-sandbox'] = {
+ 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"
+}
+
+-- We use string instead of function variables, so 'io.open' instead of io.open. That
+-- way we can still intercept repetetive overloads. One complication is that when we use
+-- sandboxed function sin helpers in the sanbox checkers, we can get a recursion loop
+-- so for that vreason we need to keep originals around till we enable the sandbox.
+
+-- if sandbox then return end
+
+local global = _G
+local next = next
+local unpack = unpack or table.unpack
+local type = type
+local tprint = texio.write_nl or print
+local tostring = tostring
+local format = string.format -- no formatters yet
+local concat = table.concat
+local sort = table.sort
+local gmatch = string.gmatch
+
+sandbox = { }
+local sandboxed = false
+local overloads = { }
+local skiploads = { }
+local initializers = { }
+local finalizers = { }
+local originals = { }
+local comments = { }
+local trace = false
+local logger = false
+
+-- this comes real early, so that we can still alias
+
+local function report(...)
+ tprint("sandbox ! " .. format(...)) -- poor mans tracer
+end
+
+sandbox.report = report
+
+function sandbox.setreporter(r)
+ report = r
+ sandbox.report = r
+end
+
+function sandbox.settrace(v)
+ trace = v
+end
+
+function sandbox.setlogger(l)
+ logger = type(l) == "function" and l or false
+end
+
+local function register(func,overload,comment)
+ if type(func) == "function" then
+ if type(overload) == "string" then
+ comment = overload
+ overload = nil
+ end
+ local function f(...)
+ if sandboxed then
+ local overload = overloads[f]
+ if overload then
+ if logger then
+ local result = { overload(func,...) }
+ logger {
+ comment = comments[f] or tostring(f),
+ arguments = { ... },
+ result = result[1] and true or false,
+ }
+ return unpack(result)
+ else
+ return overload(func,...)
+ end
+ else
+ -- ignored, maybe message
+ end
+ else
+ return func(...)
+ end
+ end
+ if comment then
+ comments[f] = comment
+ if trace then
+ report("registering function: %s",comment)
+ end
+ end
+ overloads[f] = overload or false
+ originals[f] = func
+ return f
+ end
+end
+
+local function redefine(func,comment)
+ if type(func) == "function" then
+ skiploads[func] = comment or comments[func] or "unknown"
+ if overloads[func] == false then
+ overloads[func] = nil -- not initialized anyway
+ end
+ end
+end
+
+sandbox.register = register
+sandbox.redefine = redefine
+
+function sandbox.original(func)
+ return originals and originals[func] or func
+end
+
+function sandbox.overload(func,overload,comment)
+ comment = comment or comments[func] or "?"
+ if type(func) ~= "function" then
+ if trace then
+ report("overloading unknown function: %s",comment)
+ end
+ elseif type(overload) ~= "function" then
+ if trace then
+ report("overloading function with bad overload: %s",comment)
+ end
+ elseif overloads[func] == nil then
+ if trace then
+ report("function is not registered: %s",comment)
+ end
+ elseif skiploads[func] then
+ if trace then
+ report("function is not skipped: %s",comment)
+ end
+ else
+ if trace then
+ report("overloading function: %s",comment)
+ end
+ overloads[func] = overload
+ end
+ return func
+end
+
+function sandbox.initializer(f)
+ if not sandboxed then
+ initializers[#initializers+1] = f
+ elseif trace then
+ report("already enabled, discarding initializer")
+ end
+end
+
+function sandbox.finalizer(f)
+ if not sandboxed then
+ finalizers[#finalizers+1] = f
+ elseif trace then
+ report("already enabled, discarding finalizer")
+ end
+end
+
+function sandbox.enable()
+ if not sandboxed then
+ for i=1,#initializers do
+ initializers[i]()
+ end
+ for i=1,#finalizers do
+ finalizers[i]()
+ end
+ local nnot = 0
+ local nyes = 0
+ local cnot = { }
+ local cyes = { }
+ local skip = { }
+ for k, v in next, overloads do
+ local c = comments[k]
+ if v then
+ if c then
+ cyes[#cyes+1] = c
+ else -- if not skiploads[k] then
+ nyes = nyes + 1
+ end
+ else
+ if c then
+ cnot[#cnot+1] = c
+ else -- if not skiploads[k] then
+ nnot = nnot + 1
+ end
+ end
+ end
+ for k, v in next, skiploads do
+ skip[#skip+1] = v
+ end
+ if #cyes > 0 then
+ sort(cyes)
+ report(" overloaded known : %s",concat(cyes," | "))
+ end
+ if nyes > 0 then
+ report(" overloaded unknown : %s",nyes)
+ end
+ if #cnot > 0 then
+ sort(cnot)
+ report("not overloaded known : %s",concat(cnot," | "))
+ end
+ if nnot > 0 then
+ report("not overloaded unknown : %s",nnot)
+ end
+ if #skip > 0 then
+ sort(skip)
+ report("not overloaded redefined : %s",concat(skip," | "))
+ end
+ initializers = nil
+ finalizers = nil
+ originals = nil
+ sandboxed = true
+ end
+end
+
+-- we sandbox some of the built-in functions now:
+
+-- todo: require
+-- todo: load
+
+local function supported(library)
+ local l = _G[library]
+ -- if l then
+ -- for k, v in next, l do
+ -- report("%s.%s",library,k)
+ -- end
+ -- end
+ return l
+end
+
+-- io.tmpfile : we don't know where that one ends up but probably is user temp space
+-- os.tmpname : no need to deal with this: outputs rubish anyway (\s9v0. \s9v0.1 \s9v0.2 etc)
+-- os.tmpdir : not needed either (luatex.vob000 luatex.vob000 etc)
+
+-- os.setenv : maybe
+-- require : maybe (normally taken from tree)
+-- http etc : maybe (all schemes that go outside)
+
+loadfile = register(loadfile,"loadfile")
+
+if supported("io") then
+ io.open = register(io.open, "io.open")
+ io.popen = register(io.popen, "io.popen") -- needs checking
+ io.lines = register(io.lines, "io.lines")
+ io.output = register(io.output, "io.output")
+ io.input = register(io.input, "io.input")
+end
+
+if supported("os") then
+ os.execute = register(os.execute, "os.execute")
+ os.spawn = register(os.spawn, "os.spawn")
+ os.exec = register(os.exec, "os.exec")
+ os.rename = register(os.rename, "os.rename")
+ os.remove = register(os.remove, "os.remove")
+end
+
+if supported("lfs") then
+ lfs.chdir = register(lfs.chdir, "lfs.chdir")
+ lfs.mkdir = register(lfs.mkdir, "lfs.mkdir")
+ lfs.rmdir = register(lfs.rmdir, "lfs.rmdir")
+ lfs.isfile = register(lfs.isfile, "lfs.isfile")
+ lfs.isdir = register(lfs.isdir, "lfs.isdir")
+ lfs.attributes = register(lfs.attributes, "lfs.attributes")
+ lfs.dir = register(lfs.dir, "lfs.dir")
+ lfs.lock_dir = register(lfs.lock_dir, "lfs.lock_dir")
+ lfs.touch = register(lfs.touch, "lfs.touch")
+ lfs.link = register(lfs.link, "lfs.link")
+ lfs.setmode = register(lfs.setmode, "lfs.setmode")
+ lfs.readlink = register(lfs.readlink, "lfs.readlink")
+ lfs.shortname = register(lfs.shortname, "lfs.shortname")
+ lfs.symlinkattributes = register(lfs.symlinkattributes,"lfs.symlinkattributes")
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-set.lua b/Master/texmf-dist/tex/context/base/mkiv/l-set.lua
new file mode 100644
index 00000000000..2370f0139ff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-set.lua
@@ -0,0 +1,87 @@
+if not modules then modules = { } end modules ['l-set'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This will become obsolete when we have the bitset library embedded.
+
+set = set or { }
+
+local nums = { }
+local tabs = { }
+local concat = table.concat
+local next, type = next, type
+
+set.create = table.tohash
+
+function set.tonumber(t)
+ if next(t) then
+ local s = ""
+ -- we could save mem by sorting, but it slows down
+ for k, v in next, t do
+ if v then
+ -- why bother about the leading space
+ s = s .. " " .. k
+ end
+ end
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
+ end
+ return n
+ else
+ return 0
+ end
+end
+
+function set.totable(n)
+ if n == 0 then
+ return { }
+ else
+ return tabs[n] or { }
+ end
+end
+
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t, n = { }, 0
+ for k, v in next, tabs[n] do
+ if v then
+ n = n + 1
+ t[n] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
+function set.contains(n,s)
+ if type(n) == "table" then
+ return n[s]
+ elseif n == 0 then
+ return false
+ else
+ local t = tabs[n]
+ return t and t[s]
+ end
+end
+
+--~ local c = set.create{'aap','noot','mies'}
+--~ local s = set.tonumber(c)
+--~ local t = set.totable(s)
+--~ print(t['aap'])
+--~ local c = set.create{'zus','wim','jet'}
+--~ local s = set.tonumber(c)
+--~ local t = set.totable(s)
+--~ print(t['aap'])
+--~ print(t['jet'])
+--~ print(set.contains(t,'jet'))
+--~ print(set.contains(t,'aap'))
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-string.lua b/Master/texmf-dist/tex/context/base/mkiv/l-string.lua
new file mode 100644
index 00000000000..e9dc2bbbcff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-string.lua
@@ -0,0 +1,213 @@
+if not modules then modules = { } end modules ['l-string'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string = string
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
+
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
+
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
+
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
+
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
+
+function string.unquoted(str)
+ return lpegmatch(unquoted,str) or str
+end
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function string.quoted(str)
+ return format("%q",str) -- always double quote
+end
+
+function string.count(str,pattern) -- variant 3
+ local n = 0
+ for _ in gmatch(str,pattern) do -- not for utf
+ n = n + 1
+ end
+ return n
+end
+
+function string.limit(str,n,sentinel) -- not utf proof
+ if #str > n then
+ sentinel = sentinel or "..."
+ return sub(str,1,(n-#sentinel)) .. sentinel
+ else
+ return str
+ end
+end
+
+local stripper = patterns.stripper
+local fullstripper = patterns.fullstripper
+local collapser = patterns.collapser
+local longtostring = patterns.longtostring
+
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
+end
+
+function string.fullstrip(str)
+ return lpegmatch(fullstripper,str) or ""
+end
+
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+function string.longtostring(str)
+ return lpegmatch(longtostring,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1) -- maybe also newlines
+
+-- patterns.onlyspaces = pattern
+
+function string.is_empty(str)
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
+end
+
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
+
+function string.escapedpattern(str,simple)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
+end
+
+function string.topattern(str,lowercase,strict)
+ if str=="" or type(str) ~= "string" then
+ return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
+ else
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
+ end
+end
+
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern_c = Ct( C(1) ^0) -- string and not utf !
+local pattern_b = Ct((C(1)/byte)^0)
+
+function string.totable(str,bytes)
+ return lpegmatch(bytes and pattern_b or pattern_c,str)
+end
+
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-table.lua b/Master/texmf-dist/tex/context/base/mkiv/l-table.lua
new file mode 100644
index 00000000000..552097e1c10
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-table.lua
@@ -0,0 +1,1265 @@
+if not modules then modules = { } end modules ['l-table'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
+local table, string = table, string
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+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
+
+-- extra functions, some might go (when not used)
+--
+-- we could serialize using %a but that won't work well is in the code we mostly use
+-- floats and as such we get unequality e.g. in version comparisons
+
+local stripper = patterns.stripper
+
+function table.strip(tab)
+ local lst, l = { }, 0
+ for i=1,#tab do
+ local s = lpegmatch(stripper,tab[i]) or ""
+ if s == "" then
+ -- skip this one
+ else
+ l = l + 1
+ lst[l] = s
+ end
+ end
+ return lst
+end
+
+function table.keys(t)
+ if t then
+ local keys, k = { }, 0
+ for key in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
+ end
+end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and ta == "number" then
+-- return a < b
+-- else
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+-- end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and (ta == "number" or ta == "string") then
+-- return a < b
+-- else
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+-- end
+
+-- local function sortedkeys(tab)
+-- if tab then
+-- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+-- for key in next, tab do
+-- s = s + 1
+-- srt[s] = key
+-- if category == 3 then
+-- -- no further check
+-- else
+-- local tkey = type(key)
+-- if tkey == "string" then
+-- category = (category == 2 and 3) or 1
+-- elseif tkey == "number" then
+-- category = (category == 1 and 3) or 2
+-- else
+-- category = 3
+-- end
+-- end
+-- end
+-- if category == 0 or category == 3 then
+-- sort(srt,compare)
+-- else
+-- sort(srt)
+-- end
+-- return srt
+-- else
+-- return { }
+-- end
+-- end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and (ta == "number" or ta == "string") then
+-- return a < b
+-- else
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+-- end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- if ta == "number" or ta == "string" then
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb then
+-- return a < b
+-- end
+-- end
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+
+local function compare(a,b)
+ local ta = type(a) -- needed, else 11 < 2
+ if ta == "number" then
+ local tb = type(b) -- needed, else 11 < 2
+ if ta == tb then
+ return a < b
+ elseif tb == "string" then
+ return tostring(a) < b
+ end
+ elseif ta == "string" then
+ local tb = type(b) -- needed, else 11 < 2
+ if ta == tb then
+ return a < b
+ else
+ return a < tostring(b)
+ end
+ end
+ return tostring(a) < tostring(b) -- not that efficient
+end
+
+local function sortedkeys(tab)
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
+ elseif category == 1 then
+ if type(key) ~= "string" then
+ category = 3
+ end
+ elseif category == 2 then
+ if type(key) ~= "number" then
+ category = 3
+ end
+ else
+ local tkey = type(key)
+ if tkey == "string" then
+ category = 1
+ elseif tkey == "number" then
+ category = 2
+ else
+ category = 3
+ end
+ end
+ end
+ if s < 2 then
+ -- nothing to sort
+ elseif category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
+ else
+ return { }
+ end
+end
+
+local function sortedhashonly(tab)
+ if tab then
+ local srt, s = { }, 0
+ for key in next, tab do
+ if type(key) == "string" then
+ s = s + 1
+ srt[s] = key
+ end
+ end
+ if s > 1 then
+ sort(srt)
+ end
+ return srt
+ else
+ return { }
+ end
+end
+
+local function sortedindexonly(tab)
+ if tab then
+ local srt, s = { }, 0
+ for key in next, tab do
+ if type(key) == "number" then
+ s = s + 1
+ srt[s] = key
+ end
+ end
+ if s > 1 then
+ sort(srt)
+ end
+ return srt
+ else
+ return { }
+ end
+end
+
+local function sortedhashkeys(tab,cmp) -- fast one
+ if tab then
+ local srt, s = { }, 0
+ for key in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
+ end
+ if s > 1 then
+ sort(srt,cmp)
+ end
+ return srt
+ else
+ return { }
+ end
+end
+
+function table.allkeys(t)
+ local keys = { }
+ for k, v in next, t do
+ for k in next, v do
+ keys[k] = true
+ end
+ end
+ return sortedkeys(keys)
+end
+
+table.sortedkeys = sortedkeys
+table.sortedhashonly = sortedhashonly
+table.sortedindexonly = sortedindexonly
+table.sortedhashkeys = sortedhashkeys
+
+local function nothing() end
+
+local function sortedhash(t,cmp)
+ if t then
+ local s
+ if cmp then
+ -- it would be nice if the sort function would accept a third argument (or nicer, an optional first)
+ s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+ else
+ s = sortedkeys(t) -- the robust one
+ end
+ local m = #s
+ if m == 1 then
+ return next, t
+ elseif m > 0 then
+ local n = 0
+ return function()
+ if n < m then
+ n = n + 1
+ local k = s[n]
+ return k, t[k]
+ end
+ end
+ end
+ end
+ return nothing
+end
+
+table.sortedhash = sortedhash
+table.sortedpairs = sortedhash -- obsolete
+
+function table.append(t,list)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
+ end
+ return t
+end
+
+function table.prepend(t, list)
+ local nl = #list
+ local nt = nl + #t
+ for i=#t,1,-1 do
+ t[nt] = t[i]
+ nt = nt - 1
+ end
+ for i=1,#list do
+ t[i] = list[i]
+ end
+ return t
+end
+
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
+function table.merge(t, ...) -- first one is target
+ t = t or { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
+ end
+ end
+ return t
+end
+
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
+function table.merged(...)
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
+ end
+ end
+ return t
+end
+
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
+function table.imerge(t, ...)
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
+ for j=1,#nst do
+ nt = nt + 1
+ t[nt] = nst[j]
+ end
+ end
+ return t
+end
+
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
+function table.imerged(...)
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
+ for j=1,#nst do
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
+ end
+ end
+ return tmp
+end
+
+local function fastcopy(old,metatabletoo) -- fast one
+ if old then
+ local new = { }
+ for k, v in next, old do
+ if type(v) == "table" then
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
+ else
+ new[k] = v
+ end
+ end
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ end
+ return new
+ else
+ return { }
+ end
+end
+
+-- todo : copy without metatable
+
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = { }
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in next, t do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
+ else
+ i = copy(i, tables)
+ end
+ end
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
+ end
+ end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
+
+table.fastcopy = fastcopy
+table.copy = copy
+
+function table.derive(parent) -- for the moment not public
+ local child = { }
+ if parent then
+ setmetatable(child,{ __index = parent })
+ end
+ return child
+end
+
+function table.tohash(t,value)
+ local h = { }
+ if t then
+ if value == nil then value = true end
+ for _, v in next, t do -- no ipairs here
+ h[v] = value
+ end
+ end
+ return h
+end
+
+function table.fromhash(t)
+ local hsh, h = { }, 0
+ for k, v in next, t do -- no ipairs here
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
+ end
+ return hsh
+end
+
+local noquotes, hexify, handle, compact, inline, functions
+
+local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+ 'NaN', 'goto',
+}
+
+-- local function simple_table(t)
+-- if #t > 0 then
+-- local n = 0
+-- for _,v in next, t do
+-- n = n + 1
+-- end
+-- if n == #t then
+-- local tt, nt = { }, 0
+-- for i=1,#t do
+-- local v = t[i]
+-- local tv = type(v)
+-- if tv == "number" then
+-- nt = nt + 1
+-- if hexify then
+-- tt[nt] = format("0x%X",v)
+-- else
+-- tt[nt] = tostring(v) -- tostring not needed
+-- end
+-- elseif tv == "string" then
+-- nt = nt + 1
+-- tt[nt] = format("%q",v)
+-- elseif tv == "boolean" then
+-- nt = nt + 1
+-- tt[nt] = v and "true" or "false"
+-- else
+-- return nil
+-- end
+-- end
+-- return tt
+-- end
+-- end
+-- return nil
+-- end
+
+local function simple_table(t)
+ local nt = #t
+ if nt > 0 then
+ local n = 0
+ for _,v in next, t do
+ n = n + 1
+ -- if type(v) == "table" then
+ -- return nil
+ -- end
+ end
+ if n == nt then
+ local tt = { }
+ for i=1,nt do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[i] = format("0x%X",v)
+ else
+ tt[i] = tostring(v) -- tostring not needed
+ end
+ elseif tv == "string" then
+ tt[i] = format("%q",v)
+ elseif tv == "boolean" then
+ tt[i] = v and "true" or "false"
+ else
+ return nil
+ end
+ end
+ return tt
+ end
+ end
+ return nil
+end
+
+-- Because this is a core function of mkiv I moved some function calls
+-- inline.
+--
+-- twice as fast in a test:
+--
+-- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
+
+-- problem: there no good number_to_string converter with the best resolution
+
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+-- we can speed this up with repeaters and formatters but we haven't defined them
+-- yet
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
+local function dummy() end
+
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(format("%s{",depth))
+ else
+ local tn = type(name)
+ if tn == "number" then
+ if hexify then
+ handle(format("%s[0x%X]={",depth,name))
+ else
+ handle(format("%s[%s]={",depth,name))
+ end
+ elseif tn == "string" then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
+ handle(format("%s%s={",depth,name))
+ else
+ handle(format("%s[%q]={",depth,name))
+ end
+ elseif tn == "boolean" then
+ handle(format("%s[%s]={",depth,name and "true" or "false"))
+ else
+ handle(format("%s{",depth))
+ end
+ end
+ end
+ -- we could check for k (index) being number (cardinal)
+ if root and next(root) ~= nil then
+ local first, last = nil, 0
+ if compact then
+ last = #root
+ for k=1,last do
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
+ end
+ end
+ local sk = sortedkeys(root)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ local tv = type(v)
+ local tk = type(k)
+ if compact and first and tk == "number" and k >= first and k <= last then
+ if tv == "number" then
+ if hexify then
+ handle(format("%s 0x%X,",depth,v))
+ else
+ handle(format("%s %s,",depth,v)) -- %.99g
+ end
+ elseif tv == "string" then
+ handle(format("%s %q,",depth,v))
+ elseif tv == "table" then
+ if next(v) == nil then
+ handle(format("%s {},",depth))
+ elseif inline then -- and #t > 0
+ local st = simple_table(v)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ elseif tv == "boolean" then
+ handle(format("%s %s,",depth,v and "true" or "false"))
+ elseif tv == "function" then
+ if functions then
+ handle(format('%s load(%q),',depth,dump(v))) -- maybe strip
+ else
+ handle(format('%s "function",',depth))
+ end
+ else
+ handle(format("%s %q,",depth,tostring(v)))
+ end
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif tv == "number" then
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
+ end
+ elseif tk == "boolean" then
+ if hexify then
+ handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
+ else
+ handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g
+ end
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ if hexify then
+ handle(format("%s %s=0x%X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v)) -- %.99g
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
+ end
+ end
+ elseif tv == "string" then
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ elseif tv == "table" then
+ if next(v) == nil then
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]={},",depth,k and "true" or "false"))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif tv == "boolean" then
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v and "true" or "false"))
+ 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))
+ 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 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
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
+ end
+ end
+ end
+ end
+ if level > 0 then
+ handle(format("%s},",depth))
+ end
+end
+
+-- replacing handle by a direct t[#t+1] = ... (plus test) is not much
+-- faster (0.03 on 1.00 for zapfino.tma)
+
+local function serialize(_handle,root,name,specification) -- handle wins
+ local tname = type(name)
+ if type(specification) == "table" then
+ noquotes = specification.noquotes
+ hexify = specification.hexify
+ handle = _handle or specification.handle or print
+ functions = specification.functions
+ compact = specification.compact
+ inline = specification.inline and compact
+ if functions == nil then
+ functions = true
+ end
+ if compact == nil then
+ compact = true
+ end
+ if inline == nil then
+ inline = compact
+ end
+ else
+ noquotes = false
+ hexify = false
+ handle = _handle or print
+ compact = true
+ inline = true
+ functions = true
+ end
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
+ else
+ handle(name .. "={")
+ end
+ elseif tname == "number" then
+ if hexify then
+ handle(format("[0x%X]={",name))
+ else
+ handle("[" .. name .. "]={")
+ end
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
+ end
+ else
+ handle("t={")
+ end
+ if root then
+ -- The dummy access will initialize a table that has a delayed initialization
+ -- using a metatable. (maybe explicitly test for metatable)
+ if getmetatable(root) then -- todo: make this an option, maybe even per subtable
+ local dummy = root._w_h_a_t_e_v_e_r_
+ root._w_h_a_t_e_v_e_r_ = nil
+ end
+ -- Let's forget about empty tables.
+ if next(root) ~= nil then
+ do_serialize(root,name,"",0)
+ end
+ end
+ handle("}")
+end
+
+-- A version with formatters is some 20% faster than using format (because formatters are
+-- much faster) but of course, inlining the format using .. is then again faster .. anyway,
+-- as we do some pretty printing as well there is not that much to gain unless we make a
+-- 'fast' ugly variant as well. But, we would have to move the formatter to l-string then.
+
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
+
+function table.serialize(root,name,specification)
+ local t, n = { }, 0
+ local function flush(s)
+ n = n + 1
+ t[n] = s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
+end
+
+-- local a = { e = { 1,2,3,4,5,6}, a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc" } } }
+-- local t = os.clock()
+-- for i=1,10000 do
+-- table.serialize(a)
+-- end
+-- print(os.clock()-t,table.serialize(a))
+
+table.tohandle = serialize
+
+local maxtab = 2*1024
+
+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 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
+ end
+ end
+ serialize(flush,root,name,specification)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(flush,root,name,specification)
+ end
+ f:close()
+ io.flush()
+ end
+end
+
+local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 }
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume that only two arguments are given
+ depth = f
+ f = { }
+ elseif not depth then
+ depth = 0xFFFF
+ end
+ for k, v in next, t do
+ if type(k) ~= "number" then
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ else
+ f[#f+1] = v
+ end
+ end
+ end
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ else
+ f[#f+1] = v
+ end
+ end
+ return f
+end
+
+table.flattened = flattened
+
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
+ f = { } -- this one can become obsolete
+ end
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
+ else
+ f[#f+1] = v
+ end
+ end
+ return f
+end
+
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+local function are_equal(a,b,n,m) -- indexed
+ if a and b and #a == #b then
+ n = n or 1
+ m = m or #a
+ for i=n,m do
+ local ai, bi = a[i], b[i]
+ if ai==bi then
+ -- same
+ elseif type(ai) == "table" and type(bi) == "table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
+ else
+ return false
+ end
+ end
+ return true
+ else
+ return false
+ end
+end
+
+local function identical(a,b) -- assumes same structure
+ for ka, va in next, a do
+ local vb = b[ka]
+ if va == vb then
+ -- same
+ elseif type(va) == "table" and type(vb) == "table" then
+ if not identical(va,vb) then
+ return false
+ end
+ else
+ return false
+ end
+ end
+ return true
+end
+
+table.identical = identical
+table.are_equal = are_equal
+
+local function sparse(old,nest,keeptables)
+ local new = { }
+ for k, v in next, old do
+ if not (v == "" or v == false) then
+ if nest and type(v) == "table" then
+ v = sparse(v,nest)
+ if keeptables or next(v) ~= nil then
+ new[k] = v
+ end
+ else
+ new[k] = v
+ end
+ end
+ end
+ return new
+end
+
+table.sparse = sparse
+
+function table.compact(t)
+ return sparse(t,true,true)
+end
+
+function table.contains(t, v)
+ if t then
+ for i=1, #t do
+ if t[i] == v then
+ return i
+ end
+ end
+ end
+ return false
+end
+
+function table.count(t)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ end
+ return n
+end
+
+function table.swapped(t,s) -- hash
+ local n = { }
+ if s then
+ for k, v in next, s do
+ n[k] = v
+ end
+ end
+ for k, v in next, t do
+ n[v] = k
+ end
+ return n
+end
+
+function table.mirrored(t) -- hash
+ local n = { }
+ for k, v in next, t do
+ n[v] = k
+ n[k] = v
+ end
+ return n
+end
+
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
+ end
+ return tt
+ end
+end
+
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
+function table.sequenced(t,sep,simple) -- hash only
+ if not t then
+ return ""
+ end
+ local n = #t
+ local s = { }
+ if n > 0 then
+ -- indexed
+ for i=1,n do
+ s[i] = tostring(t[i])
+ end
+ else
+ -- hashed
+ n = 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ end
+ end
+ return concat(s,sep or " | ")
+end
+
+function table.print(t,...)
+ if type(t) ~= "table" then
+ print(tostring(t))
+ else
+ serialize(print,t,...)
+ end
+end
+
+if setinspector then
+ setinspector("table",function(v) if type(v) == "table" then serialize(print,v,"table") return true end end)
+end
+
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
+
+-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
+
+function table.sub(t,i,j)
+ return { unpack(t,i,j) }
+end
+
+-- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
+
+function table.is_empty(t)
+ return not t or next(t) == nil
+end
+
+function table.has_one_entry(t)
+ return t and next(t,next(t)) == nil
+end
+
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+function table.sorted(t,...)
+ sort(t,...)
+ return t -- still sorts in-place
+end
+
+--
+
+function table.values(t,s) -- optional sort flag
+ if t then
+ local values, keys, v = { }, { }, 0
+ for key, value in next, t do
+ if not keys[value] then
+ v = v + 1
+ values[v] = value
+ keys[k] = key
+ end
+ end
+ if s then
+ sort(values)
+ end
+ return values
+ else
+ return { }
+ end
+end
+
+-- maybe this will move to util-tab.lua
+
+-- for k, v in table.filtered(t,pattern) do ... end
+-- for k, v in table.filtered(t,pattern,true) do ... end
+-- for k, v in table.filtered(t,pattern,true,cmp) do ... end
+
+function table.filtered(t,pattern,sort,cmp)
+ if t and type(pattern) == "string" then
+ if sort then
+ local s
+ if cmp then
+ -- it would be nice if the sort function would accept a third argument (or nicer, an optional first)
+ s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+ else
+ s = sortedkeys(t) -- the robust one
+ end
+ local n = 0
+ local m = #s
+ local function kv(s)
+ while n < m do
+ n = n + 1
+ local k = s[n]
+ if find(k,pattern) then
+ return k, t[k]
+ end
+ end
+ end
+ return kv, s
+ else
+ local n = next(t)
+ local function iterator()
+ while n ~= nil do
+ local k = n
+ n = next(t,k)
+ if find(k,pattern) then
+ return k, t[k]
+ end
+ end
+ end
+ return iterator, t
+ end
+ else
+ return nothing
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua b/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua
new file mode 100644
index 00000000000..3dec8001345
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua
@@ -0,0 +1,1272 @@
+if not modules then modules = { } end modules ['l-unicode'] = {
+ 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"
+}
+
+-- in lua 5.3:
+
+-- utf8.char(···) : concatinated
+-- utf8.charpatt : "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
+-- utf8.codes(s) : for p, c in utf8.codes(s) do body end
+-- utf8.codepoint(s [, i [, j]])
+-- utf8.len(s [, i])
+-- utf8.offset(s, n [, i])
+
+-- todo: utf.sub replacement (used in syst-aux)
+-- we put these in the utf namespace:
+
+utf = utf or (unicode and unicode.utf8) or { }
+
+utf.characters = utf.characters or string.utfcharacters
+utf.values = utf.values or string.utfvalues
+
+-- string.utfvalues
+-- string.utfcharacters
+-- string.characters
+-- string.characterpairs
+-- string.bytes
+-- string.bytepairs
+
+local type = type
+local char, byte, format, sub, gmatch = string.char, string.byte, string.format, string.sub, string.gmatch
+local concat = table.concat
+local P, C, R, Cs, Ct, Cmt, Cc, Carg, Cp = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg, lpeg.Cp
+
+local lpegmatch = lpeg.match
+local patterns = lpeg.patterns
+local tabletopattern = lpeg.utfchartabletopattern
+
+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_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 utf.char then
+
+ local floor, char = math.floor, string.char
+
+ function utf.char(n)
+ if n < 0x80 then
+ -- 0aaaaaaa : 0x80
+ return char(n)
+ elseif n < 0x800 then
+ -- 110bbbaa : 0xC0 : n >> 6
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ return char(
+ 0xC0 + floor(n/0x40),
+ 0x80 + (n % 0x40)
+ )
+ elseif n < 0x10000 then
+ -- 1110bbbb : 0xE0 : n >> 12
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ return char(
+ 0xE0 + floor(n/0x1000),
+ 0x80 + (floor(n/0x40) % 0x40),
+ 0x80 + (n % 0x40)
+ )
+ elseif n < 0x200000 then
+ -- 11110ccc : 0xF0 : n >> 18
+ -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ -- dddd : ccccc - 1
+ return char(
+ 0xF0 + floor(n/0x40000),
+ 0x80 + (floor(n/0x1000) % 0x40),
+ 0x80 + (floor(n/0x40) % 0x40),
+ 0x80 + (n % 0x40)
+ )
+ else
+ return ""
+ end
+ end
+
+end
+
+if not utf.byte then
+
+ local utf8byte = patterns.utf8byte
+
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+
+end
+
+local utfchar, utfbyte = utf.char, utf.byte
+
+-- As we want to get rid of the (unmaintained) utf library we implement our own
+-- variants (in due time an independent module):
+
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+
+local toentities = Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+-- local utfchr = { } -- 60K -> 2.638 M extra mem but currently not called that often (on latin)
+--
+-- setmetatable(utfchr, { __index = function(t,k) local v = utfchar(k) t[k] = v return v end } )
+--
+-- collectgarbage("collect")
+-- local u = collectgarbage("count")*1024
+-- local t = os.clock()
+-- for i=1,1000 do
+-- for i=1,600 do
+-- local a = utfchr[i]
+-- end
+-- end
+-- print(os.clock()-t,collectgarbage("count")*1024-u)
+
+-- collectgarbage("collect")
+-- local t = os.clock()
+-- for i=1,1000 do
+-- for i=1,600 do
+-- local a = utfchar(i)
+-- end
+-- end
+-- print(os.clock()-t,collectgarbage("count")*1024-u)
+
+-- local byte = string.byte
+-- local utfchar = utf.char
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+-- actually one of them is already utf ... sort of useless this one
+
+-- function utf.char(n)
+-- if n < 0x80 then
+-- return char(n)
+-- elseif n < 0x800 then
+-- return char(
+-- 0xC0 + floor(n/0x40),
+-- 0x80 + (n % 0x40)
+-- )
+-- elseif n < 0x10000 then
+-- return char(
+-- 0xE0 + floor(n/0x1000),
+-- 0x80 + (floor(n/0x40) % 0x40),
+-- 0x80 + (n % 0x40)
+-- )
+-- elseif n < 0x40000 then
+-- return char(
+-- 0xF0 + floor(n/0x40000),
+-- 0x80 + floor(n/0x1000),
+-- 0x80 + (floor(n/0x40) % 0x40),
+-- 0x80 + (n % 0x40)
+-- )
+-- else
+-- -- return char(
+-- -- 0xF1 + floor(n/0x1000000),
+-- -- 0x80 + floor(n/0x40000),
+-- -- 0x80 + floor(n/0x1000),
+-- -- 0x80 + (floor(n/0x40) % 0x40),
+-- -- 0x80 + (n % 0x40)
+-- -- )
+-- return "?"
+-- end
+-- end
+--
+-- merge into:
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s) -- in string namespace
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+local validatedutf = Cs (
+ (
+ patterns.utf8one
+ + patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ + P(1) / "�"
+ )^0
+)
+
+patterns.validatedutf = validatedutf
+
+function utf.is_valid(str)
+ return type(str) == "string" and lpegmatch(validatedutf,str) or false
+end
+
+if not utf.len then
+
+ -- -- alternative 1: 0.77
+ --
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ --
+ -- function utf.len(str)
+ -- return #lpegmatch(utfcharcounter,str or "")
+ -- end
+ --
+ -- -- alternative 2: 1.70
+ --
+ -- local n = 0
+ --
+ -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ --
+ -- function utf.length(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+ --
+ -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+ -- local n = 0
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * (
+ -- -- patterns.utf8one ^1 * Cc(1)
+ -- -- + patterns.utf8two ^1 * Cc(2)
+ -- -- + patterns.utf8three^1 * Cc(3)
+ -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end
+ -- -- )^0 ) -- just as many captures as below
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( (
+ -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end))
+ -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end))
+ -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end))
+ -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end))
+ -- -- )^0 ) -- not interesting as it creates strings but sometimes faster
+ --
+ -- -- The best so far:
+ --
+ -- local utfcharcounter = utfbom^-1 * P ( (
+ -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+ -- )^0 )
+
+ -- function utf.len(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+
+ local n, f = 0, 1
+
+ local utfcharcounter = patterns.utfbom^-1 * Cmt (
+ Cc(1) * patterns.utf8one ^1
+ + Cc(2) * patterns.utf8two ^1
+ + Cc(3) * patterns.utf8three^1
+ + Cc(4) * patterns.utf8four ^1,
+ function(_,t,d) -- due to Cc no string captures, so faster
+ n = n + (t - f)/d
+ f = t
+ return true
+ end
+ )^0
+
+ function utf.len(str)
+ n, f = 0, 1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+
+ -- -- these are quite a bit slower:
+
+ -- utfcharcounter = utfbom^-1 * (Cmt(P(1) * R("\128\191")^0, function() n = n + 1 return true end))^0 -- 50+ times slower
+ -- utfcharcounter = utfbom^-1 * (Cmt(P(1), function() n = n + 1 return true end) * R("\128\191")^0)^0 -- 50- times slower
+
+end
+
+utf.length = utf.len
+
+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))
+ -- inspect(pattern)
+ -- return lpegmatch(pattern,str) or ""
+ -- end
+
+ -- local b, e, n, first, last = 0, 0, 0, 0, 0
+ --
+ -- local function slide(s,p)
+ -- n = n + 1
+ -- if n == first then
+ -- b = p
+ -- if not last then
+ -- return nil
+ -- end
+ -- end
+ -- if n == last then
+ -- e = p
+ -- return nil
+ -- else
+ -- return p
+ -- end
+ -- end
+ --
+ -- local pattern = Cmt(p_utf8char,slide)^0
+ --
+ -- function utf.sub(str,start,stop) -- todo: from the end
+ -- if not start then
+ -- return str
+ -- end
+ -- b, e, n, first, last = 0, 0, 0, start, stop
+ -- lpegmatch(pattern,str)
+ -- if not stop then
+ -- return sub(str,b)
+ -- else
+ -- return sub(str,b,e-1)
+ -- end
+ -- end
+
+ -- print(utf.sub("Hans Hagen is my name"))
+ -- print(utf.sub("Hans Hagen is my name",5))
+ -- print(utf.sub("Hans Hagen is my name",5,10))
+
+ local utflength = utf.length
+
+ -- also negative indices, upto 10 times slower than a c variant
+
+ local b, e, n, first, last = 0, 0, 0, 0, 0
+
+ local function slide_zero(s,p)
+ n = n + 1
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_one(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ end
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_two(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ else
+ return true
+ 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_first = C(patterns.utf8character)
+
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start == 0 then
+ start = 1
+ end
+ if not stop then
+ if start < 0 then
+ local l = utflength(str) -- we can inline this function if needed
+ start = l + start
+ else
+ start = start - 1
+ end
+ b, n, first = 0, 0, start
+ lpegmatch(pattern_two,str)
+ if n >= first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start < 0 or stop < 0 then
+ local l = utf.length(str)
+ if start < 0 then
+ start = l + start
+ if start <= 0 then
+ start = 1
+ else
+ start = start + 1
+ end
+ end
+ if stop < 0 then
+ stop = l + stop
+ if stop == 0 then
+ stop = 1
+ else
+ stop = stop + 1
+ end
+ end
+ end
+ if start == 1 and stop == 1 then
+ return lpegmatch(pattern_first,str) or ""
+ elseif start > stop then
+ return ""
+ elseif start > 1 then
+ b, e, n, first, last = 0, 0, 0, start - 1, stop
+ lpegmatch(pattern_one,str)
+ if n >= first and e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ else
+ b, e, n, last = 1, 0, 0, stop
+ lpegmatch(pattern_zero,str)
+ if e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ end
+ end
+
+ -- local n = 100000
+ -- local str = string.rep("123456àáâãäå",100)
+ --
+ -- for i=-15,15,1 do
+ -- for j=-15,15,1 do
+ -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then
+ -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j))
+ -- end
+ -- end
+ -- if utf.xsub(str,i) ~= utf.sub(str,i) then
+ -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i))
+ -- end
+ -- end
+
+ -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7))
+ -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7))
+ -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9))
+ -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 ))
+ -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 ))
+ -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0))
+ -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4))
+ -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0))
+ -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0))
+ -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3))
+ -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3))
+ -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 ))
+
+end
+
+-- a replacement for simple gsubs:
+
+-- function utf.remapper(mapping)
+-- local pattern = Cs((p_utf8char/mapping)^0)
+-- return function(str)
+-- if not str or str == "" then
+-- return ""
+-- else
+-- return lpegmatch(pattern,str)
+-- end
+-- end, pattern
+-- end
+
+function utf.remapper(mapping,option,action) -- static also returns a pattern
+ local variant = type(mapping)
+ if variant == "table" then
+ action = action or mapping
+ if option == "dynamic" then
+ local pattern = false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern = false end)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ if not pattern then
+ pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option == "pattern" then
+ return Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ -- elseif option == "static" then
+ else
+ local pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+ end
+ elseif variant == "function" then
+ if option == "pattern" then
+ return Cs((p_utf8char/mapping + p_utf8char)^0)
+ else
+ local pattern = Cs((p_utf8char/mapping + p_utf8char)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+ end
+ else
+ -- is actually an error
+ return function(str)
+ return str or ""
+ end
+ end
+end
+
+-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
+-- print(remap("abcd 1234 abcd"))
+
+function utf.replacer(t) -- no precheck, always string builder
+ local r = replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+
+function utf.subtituter(t) -- with precheck and no building if no match
+ local f = finder (t)
+ local r = replacer(t,false,false,true)
+ return function(str)
+ local i = lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i > #str then
+ return str
+ else
+ -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower
+ return lpegmatch(r,str)
+ end
+ end
+end
+
+-- inspect(utf.split("a b c d"))
+-- 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)
+
+patterns.utflinesplitter = utflinesplitter
+
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+function utf.split(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+function utf.totable(str) -- keeps bom
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+
+-- 0 EF BB BF UTF-8
+-- 1 FF FE UTF-16-little-endian
+-- 2 FE FF UTF-16-big-endian
+-- 3 FF FE 00 00 UTF-32-little-endian
+-- 4 00 00 FE FF UTF-32-big-endian
+--
+-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
+
+-- utf.name = {
+-- [0] = 'utf-8',
+-- [1] = 'utf-16-le',
+-- [2] = 'utf-16-be',
+-- [3] = 'utf-32-le',
+-- [4] = 'utf-32-be'
+-- }
+--
+-- function utf.magic(f)
+-- local str = f:read(4)
+-- if not str then
+-- f:seek('set')
+-- return 0
+-- -- elseif find(str,"^%z%z\254\255") then -- depricated
+-- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+-- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+-- return 4
+-- -- elseif find(str,"^\255\254%z%z") then -- depricated
+-- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+-- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+-- return 3
+-- elseif find(str,"^\254\255") then
+-- f:seek('set',2)
+-- return 2
+-- elseif find(str,"^\255\254") then
+-- f:seek('set',2)
+-- return 1
+-- elseif find(str,"^\239\187\191") then
+-- f:seek('set',3)
+-- return 0
+-- else
+-- f:seek('set')
+-- return 0
+-- end
+-- end
+
+function utf.magic(f) -- not used
+ local str = f:read(4) or ""
+ local off = lpegmatch(p_utfoffset,str)
+ if off < 4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
+end
+
+local utf16_to_utf8_be, utf16_to_utf8_le
+local utf32_to_utf8_be, utf32_to_utf8_le
+
+local utf_16_be_getbom = patterns.utfbom_16_be^-1
+local utf_16_le_getbom = patterns.utfbom_16_le^-1
+local utf_32_be_getbom = patterns.utfbom_32_be^-1
+local utf_32_le_getbom = patterns.utfbom_32_le^-1
+
+local utf_16_be_linesplitter = utf_16_be_getbom * lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter = utf_16_le_getbom * lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter = utf_32_be_getbom * lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_le_nl)
+
+-- we have three possibilities: bytepairs (using tables), gmatch (using tables), gsub and
+-- lpeg. Bytepairs are the fastert but as soon as we need to remove bombs and so the gain
+-- is less due to more testing. Also, we seldom have to convert utf16 so we don't care to
+-- much about a few milliseconds more runtime. The lpeg variant is upto 20% slower but
+-- still pretty fast.
+--
+-- for historic resone we keep the bytepairs variants around .. beware they don't grab the
+-- bom like the lpegs do so they're not dropins in the functions that follow
+--
+-- utf16_to_utf8_be = function(s)
+-- if not s then
+-- return nil
+-- elseif s == "" then
+-- return ""
+-- end
+-- local result, r, more = { }, 0, 0
+-- for left, right in bytepairs(s) do
+-- if right then
+-- local now = 256*left + right
+-- if more > 0 then
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- more = 0
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- elseif now >= 0xD800 and now <= 0xDBFF then
+-- more = now
+-- else
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- end
+-- end
+-- end
+-- return concat(result)
+-- end
+--
+-- local utf16_to_utf8_be_t = function(t)
+-- if not t then
+-- return nil
+-- elseif type(t) == "string" then
+-- t = lpegmatch(utf_16_be_linesplitter,t)
+-- end
+-- local result = { } -- we reuse result
+-- for i=1,#t do
+-- local s = t[i]
+-- if s ~= "" then
+-- local r, more = 0, 0
+-- for left, right in bytepairs(s) do
+-- if right then
+-- local now = 256*left + right
+-- if more > 0 then
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- more = 0
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- elseif now >= 0xD800 and now <= 0xDBFF then
+-- more = now
+-- else
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- end
+-- end
+-- end
+-- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
+-- end
+-- end
+-- return t
+-- end
+--
+-- utf16_to_utf8_le = function(s)
+-- if not s then
+-- return nil
+-- elseif s == "" then
+-- return ""
+-- end
+-- local result, r, more = { }, 0, 0
+-- for left, right in bytepairs(s) do
+-- if right then
+-- local now = 256*right + left
+-- if more > 0 then
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- more = 0
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- elseif now >= 0xD800 and now <= 0xDBFF then
+-- more = now
+-- else
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- end
+-- end
+-- end
+-- return concat(result)
+-- end
+--
+-- local utf16_to_utf8_le_t = function(t)
+-- if not t then
+-- return nil
+-- elseif type(t) == "string" then
+-- t = lpegmatch(utf_16_le_linesplitter,t)
+-- end
+-- local result = { } -- we reuse result
+-- for i=1,#t do
+-- local s = t[i]
+-- if s ~= "" then
+-- local r, more = 0, 0
+-- for left, right in bytepairs(s) do
+-- if right then
+-- local now = 256*right + left
+-- if more > 0 then
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- more = 0
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- elseif now >= 0xD800 and now <= 0xDBFF then
+-- more = now
+-- else
+-- r = r + 1
+-- result[r] = utfchar(now)
+-- end
+-- end
+-- end
+-- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
+-- end
+-- end
+-- return t
+-- end
+--
+-- local utf32_to_utf8_be_t = function(t)
+-- if not t then
+-- return nil
+-- elseif type(t) == "string" then
+-- t = lpegmatch(utflinesplitter,t)
+-- end
+-- local result = { } -- we reuse result
+-- for i=1,#t do
+-- local r, more = 0, -1
+-- for a,b in bytepairs(t[i]) do
+-- if a and b then
+-- if more < 0 then
+-- more = 256*256*256*a + 256*256*b
+-- else
+-- r = r + 1
+-- result[t] = utfchar(more + 256*a + b)
+-- more = -1
+-- end
+-- else
+-- break
+-- end
+-- end
+-- t[i] = concat(result,"",1,r)
+-- end
+-- return t
+-- end
+--
+-- local utf32_to_utf8_le_t = function(t)
+-- if not t then
+-- return nil
+-- elseif type(t) == "string" then
+-- t = lpegmatch(utflinesplitter,t)
+-- end
+-- local result = { } -- we reuse result
+-- for i=1,#t do
+-- local r, more = 0, -1
+-- for a,b in bytepairs(t[i]) do
+-- if a and b then
+-- if more < 0 then
+-- more = 256*b + a
+-- else
+-- r = r + 1
+-- result[t] = utfchar(more + 256*256*256*b + 256*256*a)
+-- more = -1
+-- end
+-- else
+-- break
+-- end
+-- end
+-- t[i] = concat(result,"",1,r)
+-- end
+-- return t
+-- end
+
+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
+ 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 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
+ 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 p_utf32_to_utf8_be = C(1) * C(1) * C(1) * C(1) /function(a,b,c,d)
+ return utfchar(256*256*256*byte(a) + 256*256*byte(b) + 256*byte(c) + byte(d))
+end
+
+local p_utf32_to_utf8_le = C(1) * C(1) * C(1) * C(1) /function(a,b,c,d)
+ return utfchar(256*256*256*byte(d) + 256*256*byte(c) + 256*byte(b) + byte(a))
+end
+
+p_utf16_to_utf8_be = P(true) / function() more = 0 end * utf_16_be_getbom * Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le = P(true) / function() more = 0 end * utf_16_le_getbom * Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be = P(true) / function() more = 0 end * utf_32_be_getbom * Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le = P(true) / function() more = 0 end * utf_32_le_getbom * Cs(p_utf32_to_utf8_le^0)
+
+patterns.utf16_to_utf8_be = p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le = p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be = p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le = p_utf32_to_utf8_le
+
+utf16_to_utf8_be = function(s)
+ if s and s ~= "" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
+ end
+end
+
+local utf16_to_utf8_be_t = function(t)
+ if not t then
+ return nil
+ elseif type(t) == "string" then
+ t = lpegmatch(utf_16_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ t[i] = lpegmatch(p_utf16_to_utf8_be,s)
+ end
+ end
+ return t
+end
+
+utf16_to_utf8_le = function(s)
+ if s and s ~= "" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
+ end
+end
+
+local utf16_to_utf8_le_t = function(t)
+ if not t then
+ return nil
+ elseif type(t) == "string" then
+ t = lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ t[i] = lpegmatch(p_utf16_to_utf8_le,s)
+ end
+ end
+ return t
+end
+
+utf32_to_utf8_be = function(s)
+ if s and s ~= "" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+
+local utf32_to_utf8_be_t = function(t)
+ if not t then
+ return nil
+ elseif type(t) == "string" then
+ t = lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ t[i] = lpegmatch(p_utf32_to_utf8_be,s)
+ end
+ end
+ return t
+end
+
+utf32_to_utf8_le = function(s)
+ if s and s ~= "" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+
+local utf32_to_utf8_le_t = function(t)
+ if not t then
+ return nil
+ elseif type(t) == "string" then
+ t = lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ t[i] = lpegmatch(p_utf32_to_utf8_le,s)
+ end
+ end
+ return t
+end
+
+utf.utf16_to_utf8_le_t = utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t = utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t = utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t = utf32_to_utf8_be_t
+
+utf.utf16_to_utf8_le = utf16_to_utf8_le
+utf.utf16_to_utf8_be = utf16_to_utf8_be
+utf.utf32_to_utf8_le = utf32_to_utf8_le
+utf.utf32_to_utf8_be = utf32_to_utf8_be
+
+function utf.utf8_to_utf8_t(t)
+ return type(t) == "string" and lpegmatch(utflinesplitter,t) or t
+end
+
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
+end
+
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
+end
+
+local function little(b)
+ if b < 0x10000 then
+ return char(b%256,b/256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+
+local function big(b)
+ if b < 0x10000 then
+ return char(b/256,b%256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+
+local l_remap = Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap = Cs((p_utf8byte/big +P(1)/"")^0)
+
+local function utf8_to_utf16_be(str,nobom)
+ if nobom then
+ return lpegmatch(b_remap,str)
+ else
+ return char(254,255) .. lpegmatch(b_remap,str)
+ end
+end
+
+local function utf8_to_utf16_le(str,nobom)
+ if nobom then
+ return lpegmatch(l_remap,str)
+ else
+ return char(255,254) .. lpegmatch(l_remap,str)
+ end
+end
+
+utf.utf8_to_utf16_be = utf8_to_utf16_be
+utf.utf8_to_utf16_le = utf8_to_utf16_le
+
+function utf.utf8_to_utf16(str,littleendian,nobom)
+ if littleendian then
+ return utf8_to_utf16_le(str,nobom)
+ else
+ return utf8_to_utf16_be(str,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
+)
+
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+
+function utf.ustring(s)
+ return format("U+%05X",type(s) == "number" and s or utfbyte(s))
+end
+
+function utf.xstring(s)
+ return format("0x%05X",type(s) == "number" and s or utfbyte(s))
+end
+
+function utf.toeight(str)
+ if not str or str == "" then
+ return nil
+ end
+ local utftype = lpegmatch(p_utfstricttype,str)
+ if utftype == "utf-8" then
+ return sub(str,4) -- remove the bom
+ elseif utftype == "utf-16-be" then
+ return utf16_to_utf8_be(str) -- bom gets removed
+ elseif utftype == "utf-16-le" then
+ return utf16_to_utf8_le(str) -- bom gets removed
+ else
+ return str
+ end
+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
+
+ local cache = { }
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + p_nany)^0)
+ cache[p] = p
+ end
+ return #lpegmatch(p,str)
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
+
+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
+
+ -- 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.
+
+ ----- wrap, yield, gmatch = coroutine.wrap, coroutine.yield, string.gmatch
+ local find = string.find
+
+ local dummy = function()
+ -- we share this one
+ end
+
+ -- function utf.values(str)
+ -- local n = #str
+ -- if n == 0 then
+ -- return wrap(dummy)
+ -- elseif n == 1 then
+ -- return wrap(function() yield(utfbyte(str)) end)
+ -- else
+ -- return wrap(function() for s in gmatch(str,".[\128-\191]*") do
+ -- yield(utfbyte(s))
+ -- end end)
+ -- end
+ -- end
+ --
+ -- faster:
+
+ function utf.values(str)
+ local n = #str
+ if n == 0 then
+ return dummy
+ elseif n == 1 then
+ return function() return utfbyte(str) end
+ else
+ local p = 1
+ -- local n = #str
+ return function()
+ -- if p <= n then -- slower than the last find
+ local b, e = find(str,".[\128-\191]*",p)
+ if b then
+ p = e + 1
+ return utfbyte(sub(str,b,e))
+ end
+ -- end
+ end
+ end
+ end
+
+ -- slower:
+ --
+ -- local pattern = C(patterns.utf8character) * Cp()
+ -- ----- pattern = patterns.utf8character/utfbyte * Cp()
+ -- ----- pattern = patterns.utf8byte * Cp()
+ --
+ -- function utf.values(str) -- one of the cases where a find is faster than an lpeg
+ -- local n = #str
+ -- if n == 0 then
+ -- return dummy
+ -- elseif n == 1 then
+ -- return function() return utfbyte(str) end
+ -- else
+ -- local p = 1
+ -- return function()
+ -- local s, e = lpegmatch(pattern,str,p)
+ -- if e then
+ -- p = e
+ -- return utfbyte(s)
+ -- -- return s
+ -- end
+ -- end
+ -- end
+ -- end
+
+ string.utfvalues = utf.values
+
+end
+
+function utf.chrlen(u) -- u is number
+ return
+ (u < 0x80 and 1) or
+ (u < 0xE0 and 2) or
+ (u < 0xF0 and 3) or
+ (u < 0xF8 and 4) or
+ (u < 0xFC and 5) or
+ (u < 0xFE and 6) or 0
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-url.lua b/Master/texmf-dist/tex/context/base/mkiv/l-url.lua
new file mode 100644
index 00000000000..b189ec5bba8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-url.lua
@@ -0,0 +1,366 @@
+if not modules then modules = { } end modules ['l-url'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local char, format, byte = string.char, string.format, string.byte
+local concat = table.concat
+local tonumber, type = tonumber, type
+local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V
+local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
+
+-- from wikipedia:
+--
+-- foo://username:password@example.com:8042/over/there/index.dtb?type=animal;name=narwhal#nose
+-- \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/
+-- | | | | | | | |
+-- | userinfo hostname port | | query fragment
+-- | \________________________________/\_____________|____|/
+-- scheme | | | |
+-- | authority path | |
+-- | | |
+-- | path interpretable as filename
+-- | ___________|____________ |
+-- / \ / \ |
+-- urn:example:animal:ferret:nose interpretable as extension
+--
+-- also nice: http://url.spec.whatwg.org/ (maybe some day ...)
+
+url = url or { }
+local url = url
+
+local tochar = function(s) return char(tonumber(s,16)) end
+
+local colon = P(":")
+local qmark = P("?")
+local hash = P("#")
+local slash = P("/")
+local percent = P("%")
+local endofstring = P(-1)
+
+local hexdigit = R("09","AF","af")
+local plus = P("+")
+local nothing = Cc("")
+local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar
+local escaped = (plus / " ") + escapedchar -- so no loc://foo++.tex
+
+local noslash = P("/") / ""
+
+-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+--
+-- maybe we should already split the query (better for unescaping as = & can be part of a value
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+----- querystr = Cs((escaped+(1- hash))^0)
+local querystr = Cs(( (1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
+
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
+
+local validurl = scheme * authority * path * query * fragment
+local parser = Ct(validurl)
+
+lpegpatterns.url = validurl
+lpegpatterns.urlsplitter = parser
+
+local escapes = { }
+
+setmetatable(escapes, { __index = function(t,k)
+ local v = format("%%%02X",byte(k))
+ t[k] = v
+ return v
+end })
+
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
+local getcleaner = Cs((P("+++") / "%%2B" + P("+") / "%%20" + P(1))^1)
+
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
+lpegpatterns.urlgetcleaner = getcleaner
+
+function url.unescapeget(str)
+ return lpegmatch(getcleaner,str)
+end
+
+-- todo: reconsider Ct as we can as well have five return values (saves a table)
+-- so we can have two parsers, one with and one without
+
+local function split(str)
+ return (type(str) == "string" and lpegmatch(parser,str)) or str
+end
+
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
+local function hasscheme(str)
+ if str then
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
+ else
+ return false
+ end
+end
+
+--~ print(hasscheme("home:"))
+--~ print(hasscheme("home://"))
+
+-- todo: cache them
+
+local rootletter = R("az","AZ")
+ + S("_-+")
+local separator = P("://")
+local qualified = P(".")^0 * P("/")
+ + rootletter * P(":")
+ + rootletter^1 * separator
+ + rootletter^1 * P("/")
+local rootbased = P("/")
+ + rootletter * P(":")
+
+local barswapper = replacer("|",":")
+local backslashswapper = replacer("\\","/")
+
+-- queries:
+
+local equal = P("=")
+local amp = P("&")
+local key = Cs(((escapedchar+1)-equal )^0)
+local value = Cs(((escapedchar+1)-amp -endofstring)^0)
+
+local splitquery = Cf ( Ct("") * P { "sequence",
+ sequence = V("pair") * (amp * V("pair"))^0,
+ pair = Cg(key * equal * value),
+}, rawset)
+
+-- hasher
+
+local function hashed(str) -- not yet ok (/test?test)
+ if not str or str == "" then
+ return {
+ scheme = "invalid",
+ original = str,
+ }
+ end
+ local detailed = split(str)
+ local rawscheme = ""
+ local rawquery = ""
+ local somescheme = false
+ local somequery = false
+ if detailed then
+ rawscheme = detailed[1]
+ rawquery = detailed[4]
+ somescheme = rawscheme ~= ""
+ somequery = rawquery ~= ""
+ end
+ if not somescheme and not somequery then
+ return {
+ scheme = "file",
+ authority = "",
+ path = str,
+ query = "",
+ fragment = "",
+ original = str,
+ noscheme = true,
+ filename = str,
+ }
+ end
+ -- not always a filename but handy anyway
+ local authority = detailed[2]
+ local path = detailed[3]
+ local filename = nil
+ if authority == "" then
+ filename = path
+ elseif path == "" then
+ filename = ""
+ else
+ filename = authority .. "/" .. path
+ end
+ return {
+ scheme = rawscheme,
+ authority = authority,
+ path = path,
+ query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and =
+ queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped
+ fragment = detailed[5],
+ original = str,
+ noscheme = false,
+ filename = filename,
+ }
+end
+
+-- inspect(hashed())
+-- inspect(hashed(""))
+-- inspect(hashed("template:///test"))
+-- inspect(hashed("template:///test++.whatever"))
+-- inspect(hashed("template:///test%2B%2B.whatever"))
+-- inspect(hashed("template:///test%x.whatever"))
+-- inspect(hashed("tem%2Bplate:///test%x.whatever"))
+
+-- Here we assume:
+--
+-- files: /// = relative
+-- files: //// = absolute (!)
+
+--~ table.print(hashed("file://c:/opt/tex/texmf-local")) -- c:/opt/tex/texmf-local
+--~ table.print(hashed("file://opt/tex/texmf-local" )) -- opt/tex/texmf-local
+--~ table.print(hashed("file:///opt/tex/texmf-local" )) -- opt/tex/texmf-local
+--~ table.print(hashed("file:////opt/tex/texmf-local" )) -- /opt/tex/texmf-local
+--~ table.print(hashed("file:///./opt/tex/texmf-local" )) -- ./opt/tex/texmf-local
+
+--~ table.print(hashed("c:/opt/tex/texmf-local" )) -- c:/opt/tex/texmf-local
+--~ table.print(hashed("opt/tex/texmf-local" )) -- opt/tex/texmf-local
+--~ table.print(hashed("/opt/tex/texmf-local" )) -- /opt/tex/texmf-local
+
+url.split = split
+url.hasscheme = hasscheme
+url.hashed = hashed
+
+function url.addscheme(str,scheme) -- no authority
+ if hasscheme(str) then
+ return str
+ elseif not scheme then
+ return "file:///" .. str
+ else
+ return scheme .. ":///" .. str
+ end
+end
+
+function url.construct(hash) -- dodo: we need to escape !
+ local fullurl, f = { }, 0
+ local scheme, authority, path, query, fragment = hash.scheme, hash.authority, hash.path, hash.query, hash.fragment
+ if scheme and scheme ~= "" then
+ f = f + 1 ; fullurl[f] = scheme .. "://"
+ end
+ if authority and authority ~= "" then
+ f = f + 1 ; fullurl[f] = authority
+ end
+ if path and path ~= "" then
+ f = f + 1 ; fullurl[f] = "/" .. path
+ end
+ if query and query ~= "" then
+ f = f + 1 ; fullurl[f] = "?".. query
+ end
+ if fragment and fragment ~= "" then
+ f = f + 1 ; fullurl[f] = "#".. fragment
+ end
+ return lpegmatch(escaper,concat(fullurl))
+end
+
+local pattern = Cs(slash^-1/"" * R("az","AZ") * ((S(":|")/":") + P(":")) * slash * P(1)^0)
+
+function url.filename(filename)
+ local spec = hashed(filename)
+ local path = spec.path
+ return (spec.scheme == "file" and path and lpegmatch(pattern,path)) or filename
+end
+
+-- print(url.filename("/c|/test"))
+-- print(url.filename("/c/test"))
+-- print(url.filename("file:///t:/sources/cow.svg"))
+
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+
+url.escape = escapestring
+
+function url.query(str)
+ if type(str) == "string" then
+ return lpegmatch(splitquery,str) or ""
+ else
+ return str
+ end
+end
+
+function url.toquery(data)
+ local td = type(data)
+ if td == "string" then
+ return #str and escape(data) or nil -- beware of double escaping
+ elseif td == "table" then
+ if next(data) then
+ local t = { }
+ for k, v in next, data do
+ t[#t+1] = format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ -- nil is a signal that no query
+ end
+end
+
+-- /test/ | /test | test/ | test => test
+
+local pattern = Cs(noslash^0 * (1 - noslash * P(-1))^0)
+
+function url.barepath(path)
+ if not path or path == "" then
+ return ""
+ else
+ return lpegmatch(pattern,path)
+ end
+end
+
+-- print(url.barepath("/test"),url.barepath("test/"),url.barepath("/test/"),url.barepath("test"))
+-- print(url.barepath("/x/yz"),url.barepath("x/yz/"),url.barepath("/x/yz/"),url.barepath("x/yz"))
+
+--~ print(url.filename("file:///c:/oeps.txt"))
+--~ print(url.filename("c:/oeps.txt"))
+--~ print(url.filename("file:///oeps.txt"))
+--~ print(url.filename("file:///etc/test.txt"))
+--~ print(url.filename("/oeps.txt"))
+
+--~ from the spec on the web (sort of):
+
+--~ local function test(str)
+--~ local t = url.hashed(str)
+--~ t.constructed = url.construct(t)
+--~ print(table.serialize(t))
+--~ end
+
+--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45"))
+--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45"))
+
+--~ test("sys:///./colo-rgb")
+
+--~ test("/data/site/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733/figuur-cow.jpg")
+--~ test("file:///M:/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733")
+--~ test("M:/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733")
+--~ test("file:///q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733")
+--~ test("/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733")
+
+--~ test("file:///cow%20with%20spaces")
+--~ test("file:///cow%20with%20spaces.pdf")
+--~ test("cow%20with%20spaces.pdf")
+--~ test("some%20file")
+--~ test("/etc/passwords")
+--~ test("http://www.myself.com/some%20words.html")
+--~ test("file:///c:/oeps.txt")
+--~ test("file:///c|/oeps.txt")
+--~ test("file:///etc/oeps.txt")
+--~ test("file://./etc/oeps.txt")
+--~ test("file:////etc/oeps.txt")
+--~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
+--~ test("http://www.ietf.org/rfc/rfc2396.txt")
+--~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what")
+--~ test("mailto:John.Doe@example.com")
+--~ test("news:comp.infosystems.www.servers.unix")
+--~ test("tel:+1-816-555-1212")
+--~ test("telnet://192.0.2.16:80/")
+--~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2")
+--~ test("http://www.pragma-ade.com/spaced%20name")
+
+--~ test("zip:///oeps/oeps.zip#bla/bla.tex")
+--~ test("zip:///oeps/oeps.zip?bla/bla.tex")
+
+--~ table.print(url.hashed("/test?test"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-xml.lua b/Master/texmf-dist/tex/context/base/mkiv/l-xml.lua
new file mode 100644
index 00000000000..14e97337b25
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-xml.lua
@@ -0,0 +1,23 @@
+if not modules then modules = { } end modules ['l-xml'] = {
+ version = 1.001,
+ comment = "this module is replaced by the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We asume that the helper modules l-*.lua are loaded
+-- already. But anyway if you use mtxrun to run your script
+-- all is taken care of.
+
+if not trackers then
+ require('trac-tra')
+end
+
+if not xml then
+ require('lxml-tab')
+ require('lxml-lpt')
+ require('lxml-mis')
+ require('lxml-aux')
+ require('lxml-xml')
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua
new file mode 100644
index 00000000000..c0c3981f7df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua
@@ -0,0 +1,466 @@
+if not modules then modules = { } end modules ['lang-def'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+ -- dataonly = true, -- saves 10K
+}
+
+local rawget = rawget
+local lower = string.lower
+
+languages = languages or { }
+local languages = languages
+languages.data = languages.data or { }
+local data = languages.data
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+-- The specifications are based on an analysis done by Arthur. The
+-- names of tags were changed by Hans. The data is not yet used but
+-- will be some day.
+--
+-- description
+--
+-- The description is only meant as an indication; for example 'no' is
+-- "Norwegian, undetermined" because that's really what it is.
+--
+-- script
+--
+-- This is the 4-letter script tag according to ISO 15924, the
+-- official standard.
+--
+-- bibliographical and terminological
+--
+-- Then we have *two* ISO-639 3-letter tags: one is supposed to be used
+-- for "bibliographical" purposes, the other for "terminological". The
+-- first one is quite special (and mostly used in American libraries),
+-- and the more interesting one is the other (apparently it's that one
+-- we find everywhere).
+--
+-- context
+--
+-- These are the ones used in ConteXt. Kind of numberplate ones.
+--
+-- opentype
+--
+-- This is the 3-letter OpenType language tag, obviously.
+--
+-- variant
+--
+-- This is actually the rfc4646: an extension of ISO-639 that also defines
+-- codes for variants like de-1901 for "German, 1901 orthography" or zh-Hans for
+-- "Chinese, simplified characters" ('Hans' is the ISO-15924 tag for
+-- "HAN ideographs, Simplified" :-) As I said yesterday, I think this
+-- should be the reference since it's exactly what we want: it's really
+-- standard (it's a RFC) and it's more than simply languages. To my
+-- knowledge this is the only system that addresses this issue.
+--
+-- Warning: it's not unique! Because we have two "German" languages
+-- (and could, potentially, have two Chinese, etc.)
+--
+-- Beware: the abbreviations are lowercased, which makes it more
+-- convenient to use them.
+--
+-- todo: add default features
+
+local specifications = allocate {
+ {
+ ["description"] = "Dutch",
+ ["script"] = "latn",
+ -- ["bibliographical"] = "nld",
+ -- ["terminological"] = "nld",
+ ["context"] = "nl",
+ ["opentype"] = "nld",
+ ["variant"] = "nl",
+ },
+ {
+ ["description"] = "Basque",
+ ["script"] = "latn",
+ ["bibliographical"] = "baq",
+ ["terminological"] = "eus",
+ ["context"] = "ba",
+ ["opentype"] = "euq",
+ ["variant"] = "eu",
+ },
+ {
+ ["description"] = "Welsh",
+ ["script"] = "latn",
+ ["bibliographical"] = "wel",
+ ["terminological"] = "cym",
+ ["context"] = "cy",
+ ["opentype"] = "wel",
+ ["variant"] = "cy",
+ },
+ {
+ ["description"] = "Icelandic",
+ ["script"] = "latn",
+ ["bibliographical"] = "ice",
+ ["terminological"] = "isl",
+ ["context"] = "is",
+ ["opentype"] = "isl",
+ ["variant"] = "is",
+ },
+ {
+ ["description"] = "Norwegian, undetermined",
+ ["script"] = "latn",
+ ["bibliographical"] = "nor",
+ ["terminological"] = "nor",
+ ["context"] = "no",
+ ["variant"] = "no",
+ },
+ {
+ ["description"] = "Norwegian bokmal",
+ ["script"] = "latn",
+ ["bibliographical"] = "nob",
+ ["terminological"] = "nob",
+ ["opentype"] = "nor", -- not sure!
+ ["variant"] = "nb",
+ },
+ {
+ ["description"] = "Norwegian nynorsk",
+ ["script"] = "latn",
+ ["bibliographical"] = "nno",
+ ["terminological"] = "nno",
+ ["opentype"] = "nny",
+ ["variant"] = "nn",
+ },
+ {
+ ["description"] = "Ancient Greek",
+ ["script"] = "grek",
+ ["bibliographical"] = "grc",
+ ["terminological"] = "grc",
+ ["context"] = "agr",
+ ["variant"] = "grc",
+ },
+ {
+ ["description"] = "German, 1901 orthography",
+ ["script"] = "latn",
+ ["terminological"] = "deu",
+ ["context"] = "deo",
+ ["opentype"] = "deu",
+ ["variant"] = "de-1901",
+ },
+ {
+ ["description"] = "German, 1996 orthography",
+ ["script"] = "latn",
+ ["bibliographical"] = "ger",
+ ["terminological"] = "deu",
+ ["context"] = "de",
+ ["opentype"] = "deu",
+ ["variant"] = "de-1996",
+ },
+ {
+ ["description"] = "Afrikaans",
+ ["script"] = "latn",
+ ["bibliographical"] = "afr",
+ ["terminological"] = "afr",
+ ["context"] = "af",
+ ["opentype"] = "afk",
+ ["variant"] = "af",
+ },
+ {
+ ["description"] = "Catalan",
+ ["script"] = "latn",
+ ["bibliographical"] = "cat",
+ ["terminological"] = "cat",
+ ["context"] = "ca",
+ ["opentype"] = "cat",
+ ["variant"] = "ca",
+ },
+ {
+ ["description"] = "Czech",
+ ["script"] = "latn",
+ ["bibliographical"] = "cze",
+ ["terminological"] = "ces",
+ ["context"] = "cz",
+ ["opentype"] = "csy",
+ ["variant"] = "cs",
+ },
+ {
+ ["description"] = "Greek",
+ ["script"] = "grek",
+ ["bibliographical"] = "gre",
+ ["terminological"] = "ell",
+ ["context"] = "gr",
+ ["opentype"] = "ell",
+ ["variant"] = "el",
+ },
+ {
+ ["description"] = "American English",
+ ["script"] = "latn",
+ ["bibliographical"] = "eng",
+ ["terminological"] = "eng",
+ ["context"] = "us",
+ ["opentype"] = "eng",
+ ["variant"] = "en-US",
+ },
+ {
+ ["description"] = "British English",
+ ["script"] = "latn",
+ ["bibliographical"] = "eng",
+ ["terminological"] = "eng",
+ ["context"] = "uk",
+ ["opentype"] = "eng",
+ ["variant"] = "en-UK", -- Could be en-GB as well ...
+ },
+ {
+ ["description"] = "Spanish",
+ ["script"] = "latn",
+ ["bibliographical"] = "spa",
+ ["terminological"] = "spa",
+ ["context"] = "es",
+ ["opentype"] = "esp",
+ ["variant"] = "es",
+ },
+ {
+ ["description"] = "Finnish",
+ ["script"] = "latn",
+ ["bibliographical"] = "fin",
+ ["terminological"] = "fin",
+ ["context"] = "fi",
+ ["opentype"] = "fin",
+ ["variant"] = "fi",
+ },
+ {
+ ["description"] = "French",
+ ["script"] = "latn",
+ ["bibliographical"] = "fre",
+ ["terminological"] = "fra",
+ ["context"] = "fr",
+ ["opentype"] = "fra",
+ ["variant"] = "fr",
+ },
+ {
+ ["description"] = "Croatian",
+ ["script"] = "latn",
+ ["bibliographical"] = "scr",
+ ["terminological"] = "hrv",
+ ["context"] = "hr",
+ ["opentype"] = "hrv",
+ ["variant"] = "hr",
+ },
+ {
+ ["description"] = "Hungarian",
+ ["script"] = "latn",
+ ["bibliographical"] = "hun",
+ ["terminological"] = "hun",
+ ["context"] = "hu",
+ ["opentype"] = "hun",
+ ["variant"] = "hu",
+ },
+ {
+ ["description"] = "Italian",
+ ["script"] = "latn",
+ ["bibliographical"] = "ita",
+ ["terminological"] = "ita",
+ ["context"] = "it",
+ ["opentype"] = "ita",
+ ["variant"] = "it",
+ },
+ {
+ ["description"] = "Japanese",
+ ["script"] = "jpan",
+ ["bibliographical"] = "jpn",
+ ["terminological"] = "jpn",
+ ["context"] = "ja",
+ ["opentype"] = "jan",
+ ["variant"] = "ja",
+ },
+ {
+ ["description"] = "Latin",
+ ["script"] = "latn",
+ ["bibliographical"] = "lat",
+ ["terminological"] = "lat",
+ ["context"] = "la",
+ ["opentype"] = "lat",
+ ["variant"] = "la",
+ },
+ {
+ ["description"] = "Portuguese",
+ ["script"] = "latn",
+ ["bibliographical"] = "por",
+ ["terminological"] = "por",
+ ["context"] = "pt",
+ ["opentype"] = "ptg",
+ ["variant"] = "pt",
+ },
+ {
+ ["description"] = "Polish",
+ ["script"] = "latn",
+ ["bibliographical"] = "pol",
+ ["terminological"] = "pol",
+ ["context"] = "pl",
+ ["opentype"] = "plk",
+ ["variant"] = "pl",
+ },
+ {
+ ["description"] = "Romanian",
+ ["script"] = "latn",
+ ["bibliographical"] = "rum",
+ ["terminological"] = "ron",
+ ["context"] = "ro",
+ ["opentype"] = "rom",
+ ["variant"] = "ro",
+ },
+ {
+ ["description"] = "Russian",
+ ["script"] = "cyrl",
+ ["bibliographical"] = "rus",
+ ["terminological"] = "rus",
+ ["context"] = "ru",
+ ["opentype"] = "rus",
+ ["variant"] = "ru",
+ },
+ {
+ ["description"] = "Slovak",
+ ["script"] = "latn",
+ ["bibliographical"] = "slo",
+ ["terminological"] = "slk",
+ ["context"] = "sk",
+ ["opentype"] = "sky",
+ ["variant"] = "sk",
+ },
+ {
+ ["description"] = "Slovenian",
+ ["script"] = "latn",
+ ["bibliographical"] = "slv",
+ ["terminological"] = "slv",
+ ["context"] = "sl",
+ ["opentype"] = "slv",
+ ["variant"] = "sl",
+ },
+ {
+ ["description"] = "Swedish",
+ ["script"] = "latn",
+ ["bibliographical"] = "swe",
+ ["terminological"] = "swe",
+ ["context"] = "sv",
+ ["opentype"] = "sve",
+ ["variant"] = "sv",
+ },
+ {
+ ["description"] = "Thai",
+ ["script"] = "thai",
+ -- ["bibliographical"] = "",
+ -- ["terminological"] = "",
+ ["context"] = "th",
+ ["opentype"] = "tha",
+ -- ["variant"] = "",
+ },
+ {
+ ["description"] = "Turkish",
+ ["script"] = "latn",
+ ["bibliographical"] = "tur",
+ ["terminological"] = "tur",
+ ["context"] = "tr",
+ ["opentype"] = "trk",
+ ["variant"] = "tr",
+ },
+ {
+ ["description"] = "Vietnamese",
+ ["script"] = "latn",
+ ["bibliographical"] = "vie",
+ ["terminological"] = "vie",
+ ["context"] = "vn",
+ ["opentype"] = "vit",
+ ["variant"] = "vi",
+ },
+ {
+ ["description"] = "Chinese, simplified",
+ ["script"] = "hans",
+ ["opentypescript"] = "hani",
+ ["bibliographical"] = "chi",
+ ["terminological"] = "zho",
+ ["context"] = "cn",
+ ["opentype"] = "zhs",
+ ["variant"] = "zh-hans",
+ },
+}
+
+data.specifications = specifications
+
+local variants = { } data.variants = variants
+local contexts = { } data.contexts = contexts
+local records = { } data.records = records
+local scripts = { } data.scripts = scripts
+local opentypes = { } data.opentypes = opentypes
+local opentypescripts = { } data.opentypescripts = opentypescripts
+
+for k=1,#specifications do
+ local specification = specifications[k]
+ local variant = specification.variant
+ if variant then
+ variants[lower(variant)] = specification
+ end
+ local opentype = specification.opentype
+ if opentype then
+ opentypes[lower(opentype)] = specification
+ end
+ local script = specification.script
+ if script then
+ scripts[lower(script)] = specification
+ end
+ local opentypescript = specification.opentypescript
+ if opentypescript then
+ opentypescripts[lower(opentypescript)] = specification
+ end
+ local context = context
+ if context then
+ if type(context) == "table" then
+ for k=1,#context do
+ contexts[context[k]] = specification
+ end
+ else
+ contexts[context] = specification
+ end
+ end
+end
+
+local defaultvariant = variants["en-us"]
+
+local function get(k,key)
+ local v = rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k)
+ return v and v[key]
+end
+
+setmetatableindex(variants, function(t,k)
+ k = lower(k)
+ local v = get(k,"language") or defaultvariant.language
+ t[k] = v
+ return v
+end)
+
+setmetatableindex(opentypes, function(t,k)
+ k = lower(k)
+ local v = get(k,"opentype") or "dflt"
+ t[k] = v
+ return v
+end)
+
+setmetatableindex(opentypescripts, function(t,k)
+ k = lower(k)
+ local v = get(k,"opentypescript") or get(k,"script") or defaultvariant.opentypescript or defaultvariant.script
+ t[k] = v
+ return v
+end)
+
+setmetatableindex(contexts, function(t,k)
+ k = lower(str)
+ local v = get(k,"context") or defaultvariant.context
+ v = type(v) == "table" and v[1] or v
+ t[k] = v
+ return v
+end)
+
+setmetatableindex(records, function(t,k) -- how useful is this one?
+ k = lower(k)
+ local v = get(k) or defaultvariant
+ t[k] = v
+ return v
+end)
+
+-- print(opentypes.nl,opentypescripts.nl)
+-- print(opentypes.de,opentypescripts.de)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv
new file mode 100644
index 00000000000..e4906096e0e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv
@@ -0,0 +1,713 @@
+%D \module
+%D [ file=lang-def,
+%D version=2011.01.24, % merge of language files
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Languages Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Language Macros / Definitions}
+
+%D See \type {lang-*.tex} for some historic notes.
+
+\unprotect
+
+% Germanic Languages: Danish, Faeroese, Icelandic, Norwegian,
+% Swedish, German, Yiddish, Afrikaans, Dutch, English, Flemush,
+% 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,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!month,\space,\v!day,{,\space},\v!year},
+ \s!patterns=\s!us,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage
+ [\s!de]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=3,
+ \s!righthyphenmin=3,
+ \c!leftsentence=\hbox{\endash\space},
+ \c!rightsentence=\hbox{\space\endash},
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.\space},\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!da]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\hbox{\endash\enskip}},
+ \c!rightsentence={\hbox{\enskip\endash}},
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.\space},\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!sv]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\hbox{\endash\space},
+ \c!rightsentence=\hbox{\space\endash},
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\upperrightsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperrightdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!af]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\space,\v!month,\space,\v!day}]
+
+\installlanguage
+ [\s!nb]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!nn]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
+
+
+\installlanguage [\s!no] [\s!nb]
+\installlanguage [\s!norwegian] [\s!nb]
+\installlanguage [\s!bokmal] [\s!nb]
+\installlanguage [\s!nynorsk] [\s!nn]
+
+\installlanguage % old german
+ [deo]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+\installlanguage
+ [de-de]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+\installlanguage
+ [de-at]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot]
+
+\installlanguage
+ [de-ch]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+%D And some alternative (but very real) english patterns:
+
+\installlanguage
+ [en-gb]
+ [\c!default=\s!en,
+ \s!patterns=\s!gb,
+ \s!lefthyphenmin=3,
+ \s!righthyphenmin=3,
+ % the reverse of american (or maybe the american did it the reverse)
+ \c!leftquote=\upperleftdoublesixquote,
+ \c!rightquote=\upperrightdoubleninequote,
+ \c!leftquotation=\upperleftsinglesixquote,
+ \c!rightquotation=\upperrightsingleninequote]
+
+\installlanguage
+ [en-us]
+ [\c!default=\s!en,
+ \s!patterns=\s!us]
+
+\installlanguage [\s!uk] [\s!en-\s!gb]
+\installlanguage [\s!us] [\s!en-\s!us]
+
+\installlanguage [usenglish] [\s!en-\s!us]
+\installlanguage [ukenglish] [\s!en-\s!gb]
+\installlanguage [english] [\s!en]
+\installlanguage [dutch] [\s!nl]
+\installlanguage [german] [\s!de]
+\installlanguage [danish] [\s!da]
+\installlanguage [swedish] [\s!sv]
+\installlanguage [afrikaans] [\s!af]
+
+% Slavic Languages: Belarussian, Russian, Ukrainian, Bulgarian,
+% Macedonian, Serbian, Croatian, Slovenian, Czech, Kushubian,
+% Lusatian/Sorbian/Wendish, Polish, Slovak, Albanian, Illyrian,
+% Armenian
+
+\installlanguage
+ [\s!pl]
+ [\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!cs]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax},
+ \c!rightsentence=\c!leftsentence,
+ \c!leftsubsentence=\c!leftsentence,
+ \c!rightsubsentence=\c!rightsentence,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.\fourperemspace},\v!month,\space,\v!year},
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage
+ [\s!sk]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax},
+ \c!rightsentence=\c!leftsentence,
+ \c!leftsubsentence=\c!leftsentence,
+ \c!rightsubsentence=\c!rightsentence,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.\fourperemspace},\v!month,\space,\v!year},
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage
+ [\s!hr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\hbox{\endash\space},
+ \c!rightsentence=\hbox{\space\endash},
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!sl]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\hbox{\endash\space},
+ \c!rightsentence=\hbox{\space\endash},
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\guilsingleright,
+ \c!rightquote=\guilsingleleft,
+ \c!leftquotation=\rightguillemot,
+ \c!rightquotation=\leftguillemot,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
+
+\installlanguage [\s!polish] [\s!pl]
+\installlanguage [\s!czech] [\s!cs]
+\installlanguage [\s!slovak] [\s!sk]
+\installlanguage [\s!croatian] [\s!hr]
+\installlanguage [\s!slovenian] [\s!sl]
+\installlanguage [slovene] [\s!sl] % both possible (mojca: still needed?)
+
+% Cyrillic Languages
+
+\installlanguage
+ [\s!ru]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!spacing=\v!packed,
+ \c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\lowerleftdoubleninequote,
+ \c!rightsubsentence=\upperrightdoubleninequote,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoubleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+\installlanguage
+ [\s!ua]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!spacing=\v!packed,
+ \c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\lowerleftdoubleninequote,
+ \c!rightsubsentence=\upperrightdoubleninequote,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoubleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,\space,\v!month,\space,\v!year},
+ \s!patterns=\s!uk]
+
+\installlanguage [\s!russian] [\s!ru]
+\installlanguage [\s!ukrainian] [\s!ua]
+
+% Uralic Languages: Cheremiss, Estonian, Finnish, Karelian, Laap,
+% Mordvinian, Permian tongues, Hungarian, Ostyak, Vogul, Samoyed
+
+\installlanguage
+ [\s!fi]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\space,\v!month,\space,\v!day}]
+
+\installlanguage
+ [\s!hu]
+ [\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!year,.,\space,\v!month,\space,\v!day,.}]
+
+\installlanguage [\s!finish] [\s!fi]
+\installlanguage [\s!hungarian] [\s!hu]
+
+% Altaic Languages: Uigur, Uzbek, Azeri/Azerbaijani, Chuvash,
+% Turkish, Turkmen, Kazakh, Kazar, Kireghiz, Noghay, Talar,
+% Buryat, Kalmuck, Khalkha
+
+\installlanguage
+ [\s!tr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\space,\v!month,\space,\v!day}]
+
+\installlanguage
+ [\s!tk]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\space,\v!month,\space,\v!day},
+ \s!patterns=\s!tk,
+ \s!lefthyphenmin=1,
+ \s!righthyphenmin=2]
+
+\installlanguage [\s!turkish] [\s!tr]
+\installlanguage [\s!turkmen] [\s!tk]
+
+% Anatolian Languages
+
+% Arabic Languages
+
+\installlanguage
+ [\s!ar]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\space,\v!month,{،\space},\v!year}]
+
+\installlanguage [\s!arabic] [\s!ar]
+
+% Just aliases to "ar" for now
+
+\installlanguage[\s!ar-ae][\c!default=\s!ar] % U.A.E.
+\installlanguage[\s!ar-bh][\c!default=\s!ar] % Bahrain
+\installlanguage[\s!ar-eg][\c!default=\s!ar] % Egypt
+\installlanguage[\s!ar-in][\c!default=\s!ar] % India?
+\installlanguage[\s!ar-kw][\c!default=\s!ar] % Kuwait
+\installlanguage[\s!ar-ly][\c!default=\s!ar] % Libya
+\installlanguage[\s!ar-om][\c!default=\s!ar] % Oman
+\installlanguage[\s!ar-qa][\c!default=\s!ar] % Qatar
+\installlanguage[\s!ar-sa][\c!default=\s!ar] % Saudi Arabia
+\installlanguage[\s!ar-sd][\c!default=\s!ar] % Sudan
+\installlanguage[\s!ar-tn][\c!default=\s!ar] % Tunisia
+\installlanguage[\s!ar-ye][\c!default=\s!ar] % Yemen
+
+% Syriac months
+
+\installlanguage[\s!ar-sy][\c!default=\s!ar] % Syria
+\installlanguage[\s!ar-iq][\c!default=\s!ar-sy] % Iraq
+\installlanguage[\s!ar-jo][\c!default=\s!ar-sy] % Jordan
+\installlanguage[\s!ar-lb][\c!default=\s!ar-sy] % Lebanon
+
+% Maghribi months
+
+\installlanguage[\s!ar-dz][\c!default=\s!ar] % Algeria
+\installlanguage[\s!ar-ma][\c!default=\s!ar] % Morocco
+
+% Artificial Languages: Esperanto
+
+% Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian
+
+\installlanguage
+ [\s!lt]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoublesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!year,~m.,\space,\v!month,\space,\v!day,~d.},
+ \s!patterns=\s!lt,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2]
+
+\installlanguage [\s!lithuanian] [\s!lt]
+
+% Celtic: Breton, Welsh, Irish, Manx, Scottish Gaelic
+
+\installlanguage
+ [\s!cn]
+ [\c!leftsentence=——,
+ \c!rightsentence=——,
+ \c!leftsubsentence=——,
+ \c!rightsubsentence=——,
+ \c!leftquote=‘,
+ \c!rightquote=’,
+ \c!leftquotation=“,
+ \c!rightquotation=”,
+ \c!date={\v!year,年,\space,\v!month,\v!day,日}]
+
+\installlanguage
+ [\s!ja]
+ [\c!leftsentence=——,
+ \c!rightsentence=——,
+ \c!leftsubsentence=——,
+ \c!rightsubsentence=——,
+ \c!leftquote=‘,
+ \c!rightquote=’,
+ \c!leftquotation=「,
+ \c!rightquotation=」,
+ \c!date={西暦,\v!year,年,\v!month,月,\v!day,日}]
+
+\installlanguage
+ [\s!kr]
+ [\c!leftsentence=——,
+ \c!rightsentence=——,
+ \c!leftsubsentence=——,
+ \c!rightsubsentence=——,
+ \c!leftquote=‘,
+ \c!rightquote=’,
+ \c!leftquotation=“,
+ \c!rightquotation=”,
+ % \c!date={서기,\space,\v!year,\labeltext{\v!year},\space,\v!month,\labeltext{\v!month},\space,\v!day,\labeltext{\v!day}}]
+ \c!date={\v!year,\labeltext{\v!year},\space,\v!month,\labeltext{\v!month},\space,\v!day,\labeltext{\v!day}}]
+
+% Greek
+
+\installlanguage
+ [\s!gr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\greekleftquot,
+ \c!rightquote=\greekrightquot,
+ \c!leftquotation=\greekleftquot,
+ \c!rightquotation=\greekrightquot,
+ \c!date={\v!day\space\v!month\space\v!year},
+ \s!patterns=\s!agr] % ok?
+
+\installlanguage [\s!greek] [\s!gr]
+
+\installlanguage
+ [\s!agr]
+ [\s!default=\s!gr,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote]
+
+\installlanguage [\s!ancientgreek] [\s!agr]
+
+% Indo-Iranian Languages: 34.
+
+% Italic Languages: Latin, Italian, Rhaeto-Romanic, Rumanian,
+% Sardian, Catalan, French, Ladino, Portuguese, Proven\c{c}al,
+% Spanish
+
+\ifdefined\guillemotspace \else \let\guillemotspace\empty \fi
+\ifdefined\sentencespace \else \let\sentencespace \empty \fi
+
+\installlanguage
+ [\s!fr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day:mnem,\v!space,\v!month,\v!space,\v!year}]
+
+\installlanguage
+ [\s!es]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,{ de },\v!month,{ de },\v!year}]
+
+\installlanguage [sp] [\s!es] % old times context
+
+\installlanguage
+ [\s!ca]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+% Note GB left|/|right (sub)sentences are for \quote {incisi}.
+
+\installlanguage
+ [\s!it]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\endash,
+ \c!rightsubsentence=\endash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!leftspeech=\leftguillemot,
+ \c!middlespeech=\leftguillemot,
+ \c!rightspeech=\rightguillemot,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+\installlanguage % the same as italian
+ [\s!la]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+\installlanguage % ancient latin
+ [\s!ala]
+ [\c!default=\s!la]
+
+\installlanguage
+ [\s!pt]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\space,\v!month,\space,\v!day}]
+
+\installlanguage[\s!pt-br][\c!default=\s!pt] % Brazil
+\installlanguage[\s!es-es][\c!default=\s!es] % Spain
+\installlanguage[\s!es-la][\c!default=\s!es] % Latin America
+
+\installlanguage
+ [\s!ro]
+ [\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=\upperleftdoublesixquote,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+%D For compatibility reasons we also define:
+
+\installlanguage [\s!french] [\s!fr]
+\installlanguage [\s!spanish] [\s!es]
+\installlanguage [\s!catalan] [\s!ca]
+\installlanguage [\s!italian] [\s!it]
+\installlanguage [\s!latin] [\s!la]
+\installlanguage [\s!portuguese] [\s!pt]
+\installlanguage [\s!romanian] [\s!ro]
+
+% Vietnamese Language
+
+\installlanguage
+ [\s!vi]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\quoteleft,
+ \c!rightquote=\quoteright,
+ \c!leftquotation=\quotedblleft,
+ \c!rightquotation=\quotedblright,
+ \c!date={{ },dd,{/},mm,{/},yy}]
+
+\installlanguage [\s!vietnamese] [\s!vi]
+
+% Thai (teaser for Mojca)
+
+\installlanguage
+ [\s!th]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!month,\space,\v!day,{,\space},\v!year},
+ \s!patterns=\s!th,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage [\s!thai] [\s!th]
+
+%D Malayalam (needs to be checked)
+
+\installlanguage
+ [\s!ml]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!month,\space,\v!day,{,\space},\v!year},
+ \s!patterns=\s!ml,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage [\s!malayalam] [\s!ml]
+
+%D Todo: generate this one from languages.data
+
+\installlanguage[nld][\s!nl]
+\installlanguage[deu][\s!de]
+\installlanguage[eng][\s!en]
+\installlanguage[fra][\s!fr]
+%installlanguage[grk][\s!agr]
+
+%D This might go:
+
+\installlanguage[cz][\s!cs]
+%installlanguage[fa][\s!fr] % for dutchies only
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua
new file mode 100644
index 00000000000..84d9b2d5ba8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua
@@ -0,0 +1,231 @@
+if not modules then modules = { } end modules ['lang-dis'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+
+local nodes = nodes
+
+local tasks = nodes.tasks
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+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
+local getchar = nuts.getchar
+local getdisc = nuts.getdisc
+local setdisc = nuts.setdisc
+local isglyph = nuts.isglyph
+
+local copy_node = nuts.copy
+local free_node = nuts.free
+local remove_node = nuts.remove
+local traverse_id = nuts.traverse_id
+local traverse_nodes = nuts.traverse
+
+local nodecodes = nodes.nodecodes
+local disccodes = nodes.disccodes
+
+local disc_code = nodecodes.disc
+local glyph_code = nodecodes.glyph
+local discretionary_code = disccodes.discretionary
+
+local a_visualize = attributes.private("visualizediscretionary")
+local setattribute = tex.setattribute
+
+local getlanguagedata = languages.getdata
+
+local check_regular = true
+
+local expanders = {
+ [disccodes.discretionary] = function(d,template)
+ -- \discretionary
+ return template
+ end,
+ [disccodes.explicit] = function(d,template)
+ -- \-
+ local pre, post, replace = getdisc(d)
+ local done = false
+ if pre then
+ local char = isglyph(pre)
+ if char and char <= 0 then
+ done = true
+ pre = nil
+ end
+ end
+ if post then
+ local char = isglyph(post)
+ if char and char <= 0 then
+ done = true
+ post = nil
+ end
+ end
+ if done then
+ setdisc(d,pre,post,replace,discretionary_code,tex.exhyphenpenalty)
+ end
+ return template
+ end,
+ [disccodes.automatic] = function(d,template)
+ -- following a - : the pre and post chars are already appended and set
+ -- so we have pre=preex and post=postex .. however, the previous
+ -- hyphen is already injected ... downside: the font handler sees this
+ -- so this is another argument for doing a hyphenation pass in context
+ local pre, post, replace = getdisc(d)
+ if pre then
+ -- we have a preex characters and want that one to replace the
+ -- character in front which is the trigger
+ if not template then
+ -- can there be font kerns already?
+ template = getprev(d)
+ if template and getid(template) ~= glyph_code then
+ template = getnext(d)
+ if template and getid(template) ~= glyph_code then
+ template = nil
+ end
+ end
+ end
+ if template then
+ local pseudohead = getprev(template)
+ if pseudohead then
+ while template ~= d do
+ pseudohead, template, removed = remove_node(pseudohead,template)
+ -- free old replace ?
+ replace = removed
+ -- break ?
+ end
+ else
+ -- can't happen
+ end
+ setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty)
+ else
+ -- print("lone regular discretionary ignored")
+ end
+ else
+ setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty)
+ end
+ return template
+ end,
+ [disccodes.regular] = function(d,template)
+ if check_regular then
+ -- simple
+ if not template then
+ -- can there be font kerns already?
+ template = getprev(d)
+ if template and getid(template) ~= glyph_code then
+ template = getnext(d)
+ if template and getid(template) ~= glyph_code then
+ template = nil
+ end
+ end
+ end
+ if template then
+ local language = template and getfield(template,"lang")
+ local data = getlanguagedata(language)
+ local prechar = data.prehyphenchar
+ local postchar = data.posthyphenchar
+ local pre, post, replace = getdisc(d) -- pre can be set
+ local done = false
+ if prechar and prechar > 0 then
+ done = true
+ pre = copy_node(template)
+ setchar(pre,prechar)
+ end
+ if postchar and postchar > 0 then
+ done = true
+ post = copy_node(template)
+ setchar(post,postchar)
+ end
+ if done then
+ setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty)
+ end
+ else
+ -- print("lone regular discretionary ignored")
+ end
+ return template
+ else
+ -- maybe also set penalty here
+ setsubtype(d,discretionary_code)
+ end
+ end,
+ [disccodes.first] = function()
+ -- forget about them
+ end,
+ [disccodes.second] = function()
+ -- forget about them
+ end,
+}
+
+languages.expanders = expanders
+
+function languages.expand(d,template,subtype)
+ if not subtype then
+ subtype = getsubtype(d)
+ end
+ if subtype ~= discretionary_code then
+ return expanders[subtype](d,template)
+ end
+end
+
+local setlistcolor = nodes.tracers.colors.setlist
+
+function languages.visualizediscretionaries(head)
+ for d in traverse_id(disc_code,tonut(head)) do
+ if getattr(d,a_visualize) then
+ local pre, post, replace = getdisc(d)
+ if pre then
+ setlistcolor(pre,"darkred")
+ end
+ if post then
+ setlistcolor(post,"darkgreen")
+ end
+ if replace then
+ setlistcolor(replace,"darkblue")
+ end
+ end
+ end
+end
+
+local enabled = false
+
+function languages.showdiscretionaries(v)
+ if v == false then
+ setattribute(a_visualize,unsetvalue)
+ else -- also nil
+ if not enabled then
+ nodes.tasks.enableaction("processors","languages.visualizediscretionaries")
+ enabled = true
+ end
+ setattribute(a_visualize,1)
+ end
+end
+
+interfaces.implement {
+ name = "showdiscretionaries",
+ actions = languages.showdiscretionaries
+}
+
+local toutf = nodes.listtoutf
+
+function languages.serializediscretionary(d) -- will move to tracer
+ local pre, post, replace = getdisc(d)
+ return string.formatters["{%s}{%s}{%s}"](
+ pre and toutf(pre) or "",
+ post and toutf(post) or "",
+ replace and toutf(replace) or ""
+ )
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-frd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-frd.mkiv
new file mode 100644
index 00000000000..352e5016dec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-frd.mkiv
@@ -0,0 +1,143 @@
+%D \module
+%D [ file=lang-frd,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Frequency Table Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\endinput
+
+%D This is experimental work! Old stuff, whenever I need it I might
+%D do it in \LUA.
+
+% http://www.onzetaal.nl/advies/letterfreq.html
+
+\startcharactertable[nl]
+ \charfreq a 7.47
+ \charfreq b 1.58
+ \charfreq c 1.24
+ \charfreq d 5.93
+ \charfreq e 18.91
+ \charfreq f .81
+ \charfreq g 3.4
+ \charfreq h 2.38
+ \charfreq i 6.5
+ \charfreq j 1.46
+ \charfreq k 2.25
+ \charfreq l 3.57
+ \charfreq m 2.21
+ \charfreq n 10.03
+ \charfreq o 6.06
+ \charfreq p 1.57
+ \charfreq q .009
+ \charfreq r 6.41
+ \charfreq s 3.73
+ \charfreq t 6.79
+ \charfreq u 1.99
+ \charfreq v 2.85
+ \charfreq w 1.52
+ \charfreq x .04
+ \charfreq y .035
+ \charfreq z 1.39
+\stopcharactertable
+
+% http://caislab.icu.ac.kr/course/2001/spring/ice605/down/010306.pdf
+
+% \startcharactertable[en]
+% \charfreq a 8.2
+% \charfreq b 1.5
+% \charfreq c 2.8
+% \charfreq d 4.3
+% \charfreq e 12.7
+% \charfreq f 2.2
+% \charfreq g 2
+% \charfreq h 6.1
+% \charfreq i 7
+% \charfreq j .2
+% \charfreq k .8
+% \charfreq l 4
+% \charfreq m 2.4
+% \charfreq n 6.7
+% \charfreq o 7.5
+% \charfreq p 1.9
+% \charfreq q .1
+% \charfreq r 6
+% \charfreq s 6.3
+% \charfreq t 9.1
+% \charfreq u 2.8
+% \charfreq v 1
+% \charfreq w 2.3
+% \charfreq x .1
+% \charfreq y 2
+% \charfreq z .1
+% \stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[en]
+ \charfreq a 8.04
+ \charfreq b 1.54
+ \charfreq c 3.06
+ \charfreq d 3.99
+ \charfreq e 12.51
+ \charfreq f 2.3
+ \charfreq g 1.96
+ \charfreq h 5.49
+ \charfreq i 7.26
+ \charfreq j .16
+ \charfreq k .67
+ \charfreq l 4.14
+ \charfreq m 2.53
+ \charfreq n 7.09
+ \charfreq o 7.6
+ \charfreq p 2
+ \charfreq q .11
+ \charfreq r 6.12
+ \charfreq s 6.54
+ \charfreq t 9.25
+ \charfreq u 2.71
+ \charfreq v .99
+ \charfreq w 1.92
+ \charfreq x .19
+ \charfreq y 1.73
+ \charfreq z .09
+\stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[de]
+ \charfreq a 6.47
+ \charfreq b 1.93
+ \charfreq c 2.68
+ \charfreq d 4.83
+ \charfreq e 17.48
+ \charfreq f 1.65
+ \charfreq g 3.06
+ \charfreq h 4.23
+ \charfreq i 7.73
+ \charfreq j .27
+ \charfreq k 1.46
+ \charfreq l 3.49
+ \charfreq m 2.58
+ \charfreq n 9.84
+ \charfreq o 2.98
+ \charfreq p .96
+ \charfreq q .02
+ \charfreq r 7.54
+ \charfreq s 6.83
+ \charfreq t 6.13
+ \charfreq u 4.17
+ \charfreq v .94
+ \charfreq w 1.48
+ \charfreq x .04
+ \charfreq y .08
+ \charfreq z 1.14
+\stopcharactertable
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-frq-de.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-de.lua
new file mode 100644
index 00000000000..5f5794258fb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-de.lua
@@ -0,0 +1,12 @@
+return {
+ language = "de",
+ source = "http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm",
+ frequencies = {
+ [0x61] = 6.47, [0x62] = 1.93, [0x63] = 2.68, [0x64] = 4.83, [0x65] = 17.48,
+ [0x66] = 1.65, [0x67] = 3.06, [0x68] = 4.23, [0x69] = 7.73, [0x6A] = 0.27,
+ [0x6B] = 1.46, [0x6C] = 3.49, [0x6D] = 2.58, [0x6E] = 9.84, [0x6F] = 2.98,
+ [0x70] = 0.96, [0x71] = 0.02, [0x72] = 7.54, [0x73] = 6.83, [0x74] = 6.13,
+ [0x75] = 4.17, [0x76] = 0.94, [0x77] = 1.48, [0x78] = 0.04, [0x79] = 0.08,
+ [0x7A] = 1.14,
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-frq-en.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-en.lua
new file mode 100644
index 00000000000..5d2cfed4f9d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-en.lua
@@ -0,0 +1,26 @@
+-- return {
+-- language = "en",
+-- source = "http://caislab.icu.ac.kr/course/2001/spring/ice605/down/010306.pdf",
+-- frequencies = {
+-- [0x61] = 8.2, [0x62] = 1.5, [0x63] = 2.8, [0x64] = 4.3, [0x65] = 12.7,
+-- [0x66] = 2.2, [0x67] = 2.0, [0x68] = 6.1, [0x69] = 7.0, [0x6A] = 0.2,
+-- [0x6B] = 0.8, [0x6C] = 4.0, [0x6D] = 2.4, [0x6E] = 6.7, [0x6F] = 7.5,
+-- [0x70] = 1.9, [0x71] = 0.1, [0x72] = 6.0, [0x73] = 6.3, [0x74] = 9.1,
+-- [0x75] = 2.8, [0x76] = 1.0, [0x77] = 2.3, [0x78] = 0.1, [0x79] = 2.0,
+-- [0x7A] = 0.1,
+-- }
+-- }
+
+return {
+ language = "en",
+ source = "http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm",
+ frequencies = {
+ [0x61] = 8.04, [0x62] = 1.54, [0x63] = 3.06, [0x64] = 3.99, [0x65] = 12.51,
+ [0x66] = 2.30, [0x67] = 1.96, [0x68] = 5.49, [0x69] = 7.26, [0x6A] = 0.16,
+ [0x6B] = 0.67, [0x6C] = 4.14, [0x6D] = 2.53, [0x6E] = 7.09, [0x6F] = 7.60,
+ [0x70] = 2.00, [0x71] = 0.11, [0x72] = 6.12, [0x73] = 6.54, [0x74] = 9.25,
+ [0x75] = 2.71, [0x76] = 0.99, [0x77] = 1.92, [0x78] = 0.19, [0x79] = 1.73,
+ [0x7A] = 0.09,
+ }
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-frq-nl.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-nl.lua
new file mode 100644
index 00000000000..a7ba75376eb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-frq-nl.lua
@@ -0,0 +1,12 @@
+return {
+ language = "nl",
+ source = "http://www.onzetaal.nl/advies/letterfreq.html",
+ frequencies = {
+ [0x61] = 7.47, [0x62] = 1.58, [0x63] = 1.24, [0x64] = 5.93, [0x65] = 18.91,
+ [0x66] = 0.81, [0x67] = 3.40, [0x68] = 2.38, [0x69] = 6.50, [0x6A] = 1.46,
+ [0x6B] = 2.25, [0x6C] = 3.57, [0x6D] = 2.21, [0x6E] = 10.03, [0x6F] = 6.06,
+ [0x70] = 1.57, [0x71] = 0.009, [0x72] = 6.41, [0x73] = 3.73, [0x74] = 6.79,
+ [0x75] = 1.99, [0x76] = 2.85, [0x77] = 1.52, [0x78] = 0.04, [0x79] = 0.035,
+ [0x7A] = 1.39,
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-frq.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-frq.mkiv
new file mode 100644
index 00000000000..eaa93281a92
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-frq.mkiv
@@ -0,0 +1,235 @@
+%D \module
+%D [ file=lang-frq,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Frequency Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\endinput
+
+\writestatus{loading}{ConTeXt Language Macros / Frequency Tables}
+
+%D Some day I might redo this \LUA. But anyway, who uses it. It's rather
+%D old code.
+
+\unprotect
+
+%M \usemodule[layout]
+
+%D \macros
+%D {charwidthmethod}
+%D
+%D This module implements a method for determining the width of an
+%D average character in a language. It uses the dimensions of the
+%D current fonts.
+%D
+%D \def\ShwChrWd#1#2#3%
+%D {\chardef\charwidthmethod#1\relax
+%D \mainlanguage[#2#3]\the\dimexpr(\averagecharwidth)}
+%D
+%D \starttabulate[|c|c|c|c|c|c|]
+%D \HL
+%D \NC \NC\bf0=amount\NC\bf1=.5em\NC2=ex\NC\bf3=frequency\NC\bf4=list\NC\NR
+%D \HL
+%D \NC\bf en\NC\ShwChrWd0en\NC\ShwChrWd1en\NC\ShwChrWd2en\NC\ShwChrWd3en\NC\ShwChrWd4en\NC\NR
+%D \NC\bf nl\NC\ShwChrWd0nl\NC\ShwChrWd1nl\NC\ShwChrWd2nl\NC\ShwChrWd3nl\NC\ShwChrWd4nl\NC\NR
+%D \NC\bf de\NC\ShwChrWd0de\NC\ShwChrWd1de\NC\ShwChrWd2de\NC\ShwChrWd3de\NC\ShwChrWd4de\NC\NR
+%D \HL
+%D \stoptabulate
+%D
+%D Method~1 ignores the widths and assumes that each character has a
+%D width of .5em, which is true for most monospaced fonts. Method~2
+%D takes the x as starting point, and assumes that it's height kind of
+%D matches its width. Method~3 is the best one, and determines the
+%D average width based on the language specific character table.
+%D Method~4 is a mixture between the first two methods: character
+%D specific widths applied to an equal distribution. Method~0 reports
+%D the total count, which normally is~100.
+
+\chardef\charwidthmethod=3 % 0=amount 1=em 2=ex 3=frequency 4=flattened >4=ex
+
+%D \macros
+%D {charwidthlanguage}
+%D
+%D The language used for the calculations is defined as:
+
+\def\charwidthlanguage{\currentmainlanguage}
+
+%D \macros
+%D {charfreq}
+%D
+%D This method comes into action in the following macro:
+
+\def\charfreq#1 #2 % character fraction
+ {+(\ifcase\charwidthmethod
+ #2\dimexpr100\onepoint\relax
+ \or
+ #2\dimexpr\emwidth/2\relax
+ \or
+ #2\dimexpr\exheight\relax
+ \or
+ #2\fontcharwd\font`#1%
+ \or
+ \dimexpr100\fontcharwd\font`#1/\charactertsize\charwidthlanguage\relax % ugly hack
+ \else
+ #2\dimexpr\exheight\relax
+ \fi)}
+
+%D \macros
+%D {startcharactertable}
+%D
+%D A frequency table is defined with the following macro. The \type
+%D {charfreq} macro is used in this table.
+
+\installcorenamespace{frequencywidths}
+\installcorenamespace{frequencycounts}
+
+\let\stopcharactertable\relax
+
+\unexpanded\def\startcharactertable[#1]#2\stopcharactertable % \dimexpr has fuzzy lookahead
+ {\startnointerference
+ \setgvalue{\??frequencywidths#1}{#2}% the width vector
+ \scratchcounter\zerocount \def\charfreq##1 ##2 {\advance\scratchcounter\plusone} #2%
+ \setxvalue{\??frequencycounts#1}{\the\scratchcounter}% the character count
+ \stopnointerference}
+
+%D \macros
+%D {charactertable,charactertsize}
+%D
+%D The table content as well as the number of entries can be fetched with
+%D the following two macros. The architecture of the table and calling
+%D macro permits a fully expandable application.
+
+\def\charactertable#1%
+ {\csname\??frequencywidths\ifcsname\??frequencywidths#1\endcsname#1\else\s!en\fi\endcsname}
+
+\def\charactertsize#1%
+ {\csname\??frequencycounts\ifcsname\??frequencycounts#1\endcsname#1\else\s!en\fi\endcsname}
+
+%D Although it is of hardly any use, you can inherit a character table:
+%D
+%D \starttyping
+%D \startcharactertable[cz] \charactertable{en} \stopcharactertable
+%D \stoptyping
+
+\startcharactertable[en]
+ % empty
+\stopcharactertable % kind of default
+
+%D \macros
+%D {averagecharwidth}
+%D
+%D This macro reports the average width for the current main
+%D language (\the \dimexpr (\averagecharwidth)).
+
+\def\averagecharwidth{\dimexpr(\zeropoint\charactertable\charwidthlanguage)/100\relax}
+
+\unexpanded\def\showcharfreq
+ {\hbox\bgroup
+ \charwidthlanguage:%
+ \dostepwiserecurse\zerocount\plusfour\plusone
+ {\chardef\charwidthmethod\recurselevel\relax
+ \enspace\recurselevel/\the\dimexpr(\averagecharwidth)}%
+ \egroup}
+
+%D Just for fun, we show a few frequency tables as graphic (\in {figure}
+%D [fig:charfreq]).
+%D
+%D \startbuffer
+%D \definepalet [charfreq] [en=darkred, nl=darkgreen, de=darkblue]
+%D
+%D \def\charfreq#1 #2 %
+%D {\startMPdrawing
+%D interim linejoin := butt ;
+%D a := ASCII "#1" ;
+%D if (a >= (ASCII "a")) and (a <= (ASCII "z")) :
+%D draw ((0,#2*.25cm)--origin--(0,#2*.5cm))
+%D shifted (a*4mm+o,0)
+%D withpen pencircle scaled .5mm
+%D withcolor c;
+%D fi ;
+%D \stopMPdrawing}
+%D
+%D \resetMPdrawing
+%D \startMPdrawing
+%D numeric a, o ; a := o := 0 ;
+%D color c ; c := .5white ;
+%D string s ; s := "" ;
+%D \stopMPdrawing
+%D
+%D \startMPdrawing o := 0mm ; c := \MPcolor{charfreq:en} ; \stopMPdrawing
+%D \charactertable{en}
+%D
+%D \startMPdrawing o := 1mm ; c := \MPcolor{charfreq:nl} ; \stopMPdrawing
+%D \charactertable{nl}
+%D
+%D \startMPdrawing o := 2mm ; c := \MPcolor{charfreq:de} ; \stopMPdrawing
+%D \charactertable{de}
+%D
+%D \startMPdrawing
+%D for a := ASCII "a" upto ASCII "z" :
+%D draw textext.bot("\strut\tttf " & char a) shifted (a*4mm+1mm,-1mm) ;
+%D endfor ;
+%D \stopMPdrawing
+%D
+%D \MPdrawingdonetrue \getMPdrawing \resetMPdrawing
+%D \stopbuffer
+%D
+%D \placefigure
+%D [here]
+%D [fig:charfreq]
+%D {The character distributions for English, Dutch and German.}
+%D {\getbuffer}
+%D
+%D A few samples of usage of this mechanism are shown below:
+%D
+%D \startbuffer
+%D {\mainlanguage[en]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[nl]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[de]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Although the widthts differ, the consequenes for breaking the paragraph
+%D into lines are minimal.
+
+%D \macros
+%D {freezeaveragecharacterwidth}
+%D
+%D This macro can be used to make sure that the width does not change during a
+%D page break when another font is used.
+
+\let\normalaveragecharacterwidth\averagecharacterwidth
+
+\unexpanded\def\freezeaveragecharacterwidth % global
+ {\xdef\averagecharacterwidth{\dimexpr\the\normalaveragecharacterwidth\relax}}
+
+%D Example:
+%D
+%D \starttyping
+%D \input lang-frq.mkiv
+%D \input lang-frd.mkiv
+%D
+%D \setupbodyfont
+%D [dejavu]
+%D
+%D \setemeasure{textwidth}{\the\dimexpr70\averagecharwidth}
+%D
+%D \setuplayout
+%D [width=\measure{textwidth}]
+%D
+%D \showframe
+%D
+%D \starttext
+%D \input ward
+%D \stoptext
+%D \stoptyping
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua
new file mode 100644
index 00000000000..146aea4a85c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua
@@ -0,0 +1,1700 @@
+if not modules then modules = { } end modules ['lang-hyp'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: hyphenate over range if needed
+-- todo: check boundary nodes
+
+-- setattr: helper for full attr
+
+-- to be considered: reset dictionary.hyphenated when a pattern is added
+-- or maybe an explicit reset of the cache
+
+-- In an automated workflow hypenation of long titles can be somewhat problematic
+-- especially when demands conflict. For that reason I played a bit with a Lua based
+-- variant of the traditional hyphenation machinery. This mechanism has been extended
+-- several times in projects, of which a good description can be found in TUGboat,
+-- Volume 27 (2006), No. 2 — Proceedings of EuroTEX2006: Automatic non-standard
+-- hyphenation in OpenOffice.org by László Németh.
+--
+-- Being the result of two days experimenting the following implementation is probably
+-- not completely okay yet. If there is demand I might add some more features and plugs.
+-- The performance is quite okay but can probably improved a bit, although this is not
+-- the most critital code.
+--
+-- . a l g o r i t h m .
+-- 4l1g4
+-- l g o3
+-- 1g o
+-- 2i t h
+-- 4h1m
+-- ---------------------
+-- 4 1 4 3 2 0 4 1
+-- a l-g o-r i t h-m
+
+-- . a s s z o n n y a l .
+-- s1s z/sz=sz,1,3
+-- n1n y/ny=ny,1,3
+-- -----------------------
+-- 0 1 0 0 0 1 0 0 0/sz=sz,2,3,ny=ny,6,3
+-- a s-s z o n-n y a l/sz=sz,2,3,ny=ny,6,3
+--
+-- ab1cd/ef=gh,2,2 : acd - efd (pattern/replacement,start,length
+--
+-- In the procecess of wrapping up (for the ctx conference proceedings) I cleaned up
+-- and extended the code a bit.
+
+local type, rawset, tonumber, next = type, rawset, tonumber, next
+
+local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs
+local lpegmatch = lpeg.match
+
+local concat = table.concat
+local insert = table.insert
+local remove = table.remove
+local formatters = string.formatters
+local utfchar = utf.char
+local utfbyte = utf.byte
+
+if not characters then
+ require("char-ini")
+end
+
+local setmetatableindex = table.setmetatableindex
+
+-- \enabletrackers[hyphenator.steps=silent] will not write to the terminal
+
+local trace_steps = false trackers.register("hyphenator.steps", function(v) trace_steps = v end)
+local trace_visualize = false trackers.register("hyphenator.visualize",function(v) trace_visualize = v end)
+
+local report = logs.reporter("hyphenator")
+
+local implement = interfaces and interfaces.implement or function() end
+
+languages = languages or { }
+local hyphenators = languages.hyphenators or { }
+languages.hyphenators = hyphenators
+local traditional = hyphenators.traditional or { }
+hyphenators.traditional = traditional
+
+local dictionaries = setmetatableindex(function(t,k)
+ local v = {
+ patterns = { },
+ hyphenated = { },
+ specials = { },
+ exceptions = { },
+ loaded = false,
+ }
+ t[k] = v
+ return v
+end)
+
+hyphenators.dictionaries = dictionaries
+
+local character = lpeg.patterns.utf8character
+local digit = R("09")
+local weight = digit/tonumber + Cc(0)
+local fence = P(".")
+local hyphen = P("-")
+local space = P(" ")
+local char = character - space
+local validcharacter = (character - S("./"))
+local keycharacter = character - S("/")
+----- basepart = Ct( (Cc(0) * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc(0))^-1)
+local specpart = (P("/") * Cf ( Ct("") *
+ Cg ( Cc("before") * C((1-P("="))^1) * P("=") ) *
+ Cg ( Cc("after") * C((1-P(","))^1) ) *
+ ( P(",") *
+ Cg ( Cc("start") * ((1-P(","))^1/tonumber) * P(",") ) *
+ Cg ( Cc("length") * ((1-P(-1) )^1/tonumber) )
+ )^-1
+ , rawset))^-1
+
+local make_hashkey_p = Cs((digit/"" + keycharacter)^1)
+----- make_pattern_p = basepart * specpart
+local make_hashkey_e = Cs((hyphen/"" + keycharacter)^1)
+local make_pattern_e = Ct(P(char) * (hyphen * Cc(true) * P(char) + P(char) * Cc(false))^1) -- catch . and char after -
+
+-- local make_hashkey_c = Cs((digit + keycharacter/"")^1)
+-- local make_pattern_c = Ct((P(1)/tonumber)^1)
+
+-- local cache = setmetatableindex(function(t,k)
+-- local n = lpegmatch(make_hashkey_c,k)
+-- local v = lpegmatch(make_pattern_c,n)
+-- t[k] = v
+-- return v
+-- end)
+--
+-- local weight_n = digit + Cc("0")
+-- local basepart_n = Cs( (Cc("0") * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc("0"))^-1) / cache
+-- local make_pattern_n = basepart_n * specpart
+
+local make_pattern_c = Ct((P(1)/tonumber)^1)
+
+-- us + nl: 17664 entries -> 827 unique (saves some 3M)
+
+local cache = setmetatableindex(function(t,k)
+ local v = lpegmatch(make_pattern_c,k)
+ t[k] = v
+ return v
+end)
+
+local weight_n = digit + Cc("0")
+local fence_n = fence / "0"
+local char_n = validcharacter / ""
+local basepart_n = Cs(fence_n^-1 * (weight_n * char_n)^1 * weight_n * fence_n^-1) / cache
+local make_pattern_n = basepart_n * specpart
+
+local function register_pattern(patterns,specials,str,specification)
+ local k = lpegmatch(make_hashkey_p,str)
+ -- local v1, v2 = lpegmatch(make_pattern_p,str)
+ local v1, v2 = lpegmatch(make_pattern_n,str)
+ patterns[k] = v1 -- is this key still ok for complex patterns
+ if specification then
+ specials[k] = specification
+ elseif v2 then
+ specials[k] = v2
+ end
+end
+
+local function unregister_pattern(patterns,specials,str)
+ local k = lpegmatch(make_hashkey_p,str)
+ patterns[k] = nil
+ specials[k] = nil
+end
+
+local p_lower = lpeg.patterns.utf8lower
+
+local function register_exception(exceptions,str,specification)
+ local l = lpegmatch(p_lower,str)
+ local k = lpegmatch(make_hashkey_e,l)
+ local v = lpegmatch(make_pattern_e,l)
+ exceptions[k] = v
+end
+
+local p_pattern = ((Carg(1) * Carg(2) * C(char^1)) / register_pattern + 1)^1
+local p_exception = ((Carg(1) * C(char^1)) / register_exception + 1)^1
+local p_split = Ct(C(character)^1)
+
+function traditional.loadpatterns(language,filename)
+ local dictionary = dictionaries[language]
+ if not dictionary.loaded then
+ if not filename or filename == "" then
+ filename = "lang-" .. language
+ end
+ filename = file.addsuffix(filename,"lua")
+ local fullname = resolvers.findfile(filename)
+ if fullname and fullname ~= "" then
+ local specification = dofile(fullname)
+ if specification then
+ local patterns = specification.patterns
+ if patterns then
+ local data = patterns.data
+ if data and data ~= "" then
+ lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials)
+ end
+ end
+ local exceptions = specification.exceptions
+ if exceptions then
+ local data = exceptions.data
+ if data and data ~= "" then
+ lpegmatch(p_exception,data,1,dictionary.exceptions)
+ end
+ end
+ end
+ end
+ dictionary.loaded = true
+ end
+ return dictionary
+end
+
+local lcchars = characters.lcchars
+local uccodes = characters.uccodes
+local categories = characters.categories
+local nofwords = 0
+local nofhashed = 0
+
+local steps = nil
+local f_show = formatters["%w%s"]
+
+local function show_log()
+ if trace_steps == true then
+ report()
+ local w = #steps[1][1]
+ for i=1,#steps do
+ local s = steps[i]
+ report("%s%w%S %S",s[1],w - #s[1] + 3,s[2],s[3] or "")
+ end
+ report()
+ end
+end
+
+local function show_1(wsplit)
+ local u = concat(wsplit," ")
+ steps = { { f_show(0,u), f_show(0,u) } }
+end
+
+local function show_2(c,m,wsplit,done,i,spec)
+ local s = lpegmatch(p_split,c)
+ local t = { }
+ local n = #m
+ local w = #wsplit
+ for j=1,n do
+ t[#t+1] = m[j]
+ t[#t+1] = s[j]
+ end
+ local m = 2*i-2
+ local l = #t
+ local s = spec and table.sequenced(spec) or ""
+ if m == 0 then
+ steps[#steps+1] = { f_show(m, concat(t,"",2)), f_show(1,concat(done," ",2,#done),s) }
+ elseif i+1 == w then
+ steps[#steps+1] = { f_show(m-1,concat(t,"",1,#t-1)), f_show(1,concat(done," ",2,#done),s) }
+ else
+ steps[#steps+1] = { f_show(m-1,concat(t)), f_show(1,concat(done," ",2,#done),s) }
+ end
+end
+
+local function show_3(wsplit,done)
+ local t = { }
+ local h = { }
+ local n = #wsplit
+ for i=1,n do
+ local w = wsplit[i]
+ if i > 1 then
+ local d = done[i]
+ t[#t+1] = i > 2 and d % 2 == 1 and "-" or " "
+ h[#h+1] = d
+ end
+ t[#t+1] = w
+ h[#h+1] = w
+ end
+ steps[#steps+1] = { f_show(0,concat(h)), f_show(0,concat(t)) }
+ show_log()
+end
+
+local function show_4(wsplit,done)
+ steps = { { concat(wsplit," ") } }
+ show_log()
+end
+
+function traditional.lasttrace()
+ return steps
+end
+
+-- We could reuse the w table but as we cache the resolved words
+-- there is not much gain in that complication.
+--
+-- Beware: word can be a table and when n is passed to we can
+-- assume reuse so we need to honor that n then.
+
+-- todo: a fast variant for tex ... less lookups (we could check is
+-- dictionary has changed) ... although due to caching the already
+-- done words, we don't do much here
+
+local function hyphenate(dictionary,word,n) -- odd is okay
+ nofwords = nofwords + 1
+ local hyphenated = dictionary.hyphenated
+ local isstring = type(word) == "string"
+ if isstring then
+ local done = hyphenated[word]
+ if done ~= nil then
+ return done
+ end
+ elseif n then
+ local done = hyphenated[concat(word,"",1,n)]
+ if done ~= nil then
+ return done
+ end
+ else
+ local done = hyphenated[concat(word)]
+ if done ~= nil then
+ return done
+ end
+ end
+ local key
+ if isstring then
+ key = word
+ word = lpegmatch(p_split,word)
+ if not n then
+ n = #word
+ end
+ else
+ if not n then
+ n = #word
+ end
+ key = concat(word,"",1,n)
+ end
+ local l = 1
+ local w = { "." }
+ -- local d = dictionary.codehash or lcchars[c]
+ for i=1,n do
+ local c = word[i]
+ l = l + 1
+ -- w[l] = d[c] or c -- needs testing
+ w[l] = lcchars[c] or c
+ end
+ l = l + 1
+ w[l] = "."
+ local c = concat(w,"",2,l-1)
+ --
+ local done = hyphenated[c]
+ if done ~= nil then
+ hyphenated[key] = done
+ nofhashed = nofhashed + 1
+ return done
+ end
+ --
+ local exceptions = dictionary.exceptions
+ local exception = exceptions[c]
+ if exception then
+ if trace_steps then
+ show_4(w,exception)
+ end
+ hyphenated[key] = exception
+ nofhashed = nofhashed + 1
+ return exception
+ end
+ --
+ if trace_steps then
+ show_1(w)
+ end
+ --
+ local specials = dictionary.specials
+ local patterns = dictionary.patterns
+ --
+-- inspect(specials)
+ local spec
+ for i=1,l do
+ for j=i,l do
+ local c = concat(w,"",i,j)
+ local m = patterns[c]
+ if m then
+ local s = specials[c]
+ if not done then
+ done = { }
+ spec = nil
+ -- the string that we resolve has explicit fences (.) so
+ -- done starts at the first fence and runs upto the last
+ -- one so we need one slot less
+ for i=1,l do
+ done[i] = 0
+ end
+ end
+ -- we run over the pattern that always has a (zero) value for
+ -- each character plus one more as we look at both sides
+ for k=1,#m do
+ local new = m[k]
+ if not new then
+ break
+ elseif new == true then
+ report("fatal error")
+ break
+ elseif new > 0 then
+ local pos = i + k - 1
+ local old = done[pos]
+ if not old then
+ -- break ?
+ elseif new > old then
+ done[pos] = new
+ if s then
+ local b = i + (s.start or 1) - 1
+ if b > 0 then
+ local e = b + (s.length or 2) - 1
+ if e > 0 then
+ if pos >= b and pos <= e then
+ if spec then
+ spec[pos] = { s, k - 1 }
+ else
+ spec = { [pos] = { s, k - 1 } }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if trace_steps and done then
+ show_2(c,m,w,done,i,s)
+ end
+ end
+ end
+ end
+ if trace_steps and done then
+ show_3(w,done)
+ end
+ if done then
+ local okay = false
+ for i=3,#done do
+ if done[i] % 2 == 1 then
+ done[i-2] = spec and spec[i] or true
+ okay = true
+ else
+ done[i-2] = false
+ end
+ end
+ if okay then
+ done[#done] = nil
+ done[#done] = nil
+ else
+ done = false
+ end
+ else
+ done = false
+ end
+ hyphenated[key] = done
+ nofhashed = nofhashed + 1
+ return done
+end
+
+function traditional.gettrace(language,word)
+ if not word or word == "" then
+ return
+ end
+ local dictionary = dictionaries[language]
+ if dictionary then
+ local hyphenated = dictionary.hyphenated
+ hyphenated[word] = nil
+ hyphenate(dictionary,word)
+ return steps
+ end
+end
+
+local methods = setmetatableindex(function(t,k) local v = hyphenate t[k] = v return v end)
+
+function traditional.installmethod(name,f)
+ if rawget(methods,name) then
+ report("overloading %a is not permitted",name)
+ else
+ methods[name] = f
+ end
+end
+
+local s_detail_1 = "-"
+local f_detail_2 = formatters["%s-%s"]
+local f_detail_3 = formatters["{%s}{%s}{}"]
+local f_detail_4 = formatters["{%s%s}{%s%s}{%s}"]
+
+function traditional.injecthyphens(dictionary,word,specification)
+ if not word then
+ return false
+ end
+ if not specification then
+ return word
+ end
+ local hyphens = hyphenate(dictionary,word)
+ if not hyphens then
+ return word
+ end
+
+ -- the following code is similar to code later on but here we have
+ -- strings while there we have hyphen specs
+
+ local word = lpegmatch(p_split,word)
+ local size = #word
+
+ local leftmin = specification.leftcharmin or 2
+ local rightmin = size - (specification.rightcharmin or leftmin)
+ local leftchar = specification.leftchar
+ local rightchar = specification.rightchar
+
+ local result = { }
+ local rsize = 0
+ local position = 1
+
+ while position <= size do
+ if position >= leftmin and position <= rightmin then
+ local hyphen = hyphens[position]
+ if not hyphen then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ elseif hyphen == true then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ rsize = rsize + 1
+ if leftchar and rightchar then
+ result[rsize] = f_detail_3(rightchar,leftchar)
+ else
+ result[rsize] = s_detail_1
+ end
+ position = position + 1
+ else
+ local o, h = hyphen[2]
+ if o then
+ h = hyphen[1]
+ else
+ h = hyphen
+ o = 1
+ end
+ local b = position - o + (h.start or 1)
+ local e = b + (h.length or 2) - 1
+ if b > 0 and e >= b then
+ for i=1,b-position do
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ rsize = rsize + 1
+ if leftchar and rightchar then
+ result[rsize] = f_detail_4(h.before,rightchar,leftchar,h.after,concat(word,"",b,e))
+ else
+ result[rsize] = f_detail_2(h.before,h.after)
+ end
+ position = e + 1
+ else
+ -- error
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ else
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ return concat(result)
+end
+
+do
+
+ local word = C((1-space)^1)
+ local spaces = space^1
+
+ local u_pattern = (Carg(1) * Carg(2) * word / unregister_pattern + spaces)^1
+ local r_pattern = (Carg(1) * Carg(2) * word * Carg(3) / register_pattern + spaces)^1
+ local e_pattern = (Carg(1) * word / register_exception + spaces)^1
+
+ function traditional.registerpattern(language,str,specification)
+ local dictionary = dictionaries[language]
+ if specification == false then
+ lpegmatch(u_pattern,str,1,dictionary.patterns,dictionary.specials)
+ -- unregister_pattern(dictionary.patterns,dictionary.specials,str)
+ else
+ lpegmatch(r_pattern,str,1,dictionary.patterns,dictionary.specials,type(specification) == "table" and specification or false)
+ -- register_pattern(dictionary.patterns,dictionary.specials,str,specification)
+ end
+ end
+
+ function traditional.registerexception(language,str)
+ lpegmatch(e_pattern,str,1,dictionaries[language].exceptions)
+ end
+
+end
+
+-- todo: unicodes or utfhash ?
+
+if context then
+
+ local nodecodes = nodes.nodecodes
+ local disccodes = nodes.disccodes
+
+ local glyph_code = nodecodes.glyph
+ local disc_code = nodecodes.disc
+ local math_code = nodecodes.math
+ local hlist_code = nodecodes.hlist
+
+ local discretionary_code = disccodes.discretionary
+ local explicit_code = disccodes.explicit
+ local regular_code = disccodes.regular
+ local automatic_code = disccodes.automatic
+
+ local nuts = nodes.nuts
+ local tonut = nodes.tonut
+ local tonode = nodes.tonode
+ local nodepool = nuts.pool
+
+ local new_disc = nodepool.disc
+ local new_glyph = nodepool.glyph
+ local new_penalty = nodepool.penalty
+
+ local getfield = nuts.getfield
+ local getfont = nuts.getfont
+ local getid = nuts.getid
+ local getattr = nuts.getattr
+ local getnext = nuts.getnext
+ local getprev = nuts.getprev
+ local getsubtype = nuts.getsubtype
+ local getlist = nuts.getlist
+ local isglyph = nuts.isglyph
+
+ local setfield = nuts.setfield
+ local setchar = nuts.setchar
+ local setdisc = nuts.setdisc
+
+ local insert_before = nuts.insert_before
+ local insert_after = nuts.insert_after
+ local copy_node = nuts.copy
+ 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 setcolor = nodes.tracers.colors.set
+
+ local variables = interfaces.variables
+ local v_reset = variables.reset
+ local v_yes = variables.yes
+ local v_word = variables.word
+ local v_all = variables.all
+
+ local settings_to_array = utilities.parsers.settings_to_array
+
+ local unsetvalue = attributes.unsetvalue
+ local texsetattribute = tex.setattribute
+
+ local prehyphenchar = lang.prehyphenchar
+ local posthyphenchar = lang.posthyphenchar
+ local preexhyphenchar = lang.preexhyphenchar
+ local postexhyphenchar = lang.postexhyphenchar
+
+ local a_hyphenation = attributes.private("hyphenation")
+
+ local interwordpenalty = 5000
+
+ function traditional.loadpatterns(language)
+ return dictionaries[language]
+ end
+
+ setmetatableindex(dictionaries,function(t,k) -- for the moment we use an independent data structure
+ if type(k) == "string" then
+ -- this will force a load if not yet loaded (we need a nicer way)
+ -- for the moment that will do (nneeded for examples that register
+ -- a pattern specification
+ languages.getnumber(k)
+ end
+ local specification = languages.getdata(k)
+ local dictionary = {
+ patterns = { },
+ exceptions = { },
+ hyphenated = { },
+ specials = { },
+ instance = false,
+ characters = { },
+ unicodes = { },
+ }
+ if specification then
+ local resources = specification.resources
+ if resources then
+ local characters = dictionary.characters or { }
+ local unicodes = dictionary.unicodes or { }
+ for i=1,#resources do
+ local r = resources[i]
+ if not r.in_dictionary then
+ r.in_dictionary = true
+ local patterns = r.patterns
+ if patterns then
+ local data = patterns.data
+ if data then
+ -- regular patterns
+ lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials)
+ end
+ local extra = patterns.extra
+ if extra then
+ -- special patterns
+ lpegmatch(p_pattern,extra,1,dictionary.patterns,dictionary.specials)
+ end
+ end
+ local exceptions = r.exceptions
+ if exceptions then
+ local data = exceptions.data
+ if data and data ~= "" then
+ lpegmatch(p_exception,data,1,dictionary.exceptions)
+ end
+ end
+ local usedchars = lpegmatch(p_split,patterns.characters)
+ for i=1,#usedchars do
+ local char = usedchars[i]
+ local code = utfbyte(char)
+ local upper = uccodes[code]
+ characters[char] = code
+ unicodes [code] = char
+ if type(upper) == "table" then
+ for i=1,#upper do
+ local u = upper[i]
+ unicodes[u] = utfchar(u)
+ end
+ else
+ unicodes[upper] = utfchar(upper)
+ end
+ end
+ end
+ end
+ dictionary.characters = characters
+ dictionary.unicodes = unicodes
+ setmetatableindex(characters,function(t,k) local v = k and utfbyte(k) t[k] = v return v end)
+ end
+ t[specification.number] = dictionary
+ dictionary.instance = specification.instance -- needed for hyphenchars
+ end
+ t[k] = dictionary
+ return dictionary
+ end)
+
+ -- Beware: left and right min doesn't mean that in a 1 mmm hsize there can be snippets
+ -- with less characters than either of them! This could be an option but such a narrow
+ -- hsize doesn't make sense anyway.
+
+ -- We assume that featuresets are defined global ... local definitions
+ -- (also mid paragraph) make not much sense anyway. For the moment we
+ -- assume no predefined sets so we don't need to store them. Nor do we
+ -- need to hash them in order to save space ... no sane user will define
+ -- many of them.
+
+ local featuresets = hyphenators.featuresets or { }
+ hyphenators.featuresets = featuresets
+
+ storage.shared.noflanguagesfeaturesets = storage.shared.noflanguagesfeaturesets or 0
+
+ local noffeaturesets = storage.shared.noflanguagesfeaturesets
+
+ storage.register("languages/hyphenators/featuresets",featuresets,"languages.hyphenators.featuresets")
+
+ ----- hash = table.sequenced(featureset,",") -- no need now
+
+ local function register(name,featureset)
+ noffeaturesets = noffeaturesets + 1
+ featureset.attribute = noffeaturesets
+ featuresets[noffeaturesets] = featureset -- access by attribute
+ featuresets[name] = featureset -- access by name
+ storage.shared.noflanguagesfeaturesets = noffeaturesets
+ return noffeaturesets
+ end
+
+ local function makeset(...) -- a bit overkill, supporting variants but who cares
+ local set = { }
+ for i=1,select("#",...) do
+ local list = select(i,...)
+ local kind = type(list)
+ local used = nil
+ if kind == "string" then
+ if list == v_all then
+ -- not ok ... now all get ignored
+ return setmetatableindex(function(t,k) local v = utfchar(k) t[k] = v return v end)
+ elseif list ~= "" then
+ used = lpegmatch(p_split,list)
+ set = set or { }
+ for i=1,#used do
+ local char = used[i]
+ set[utfbyte(char)] = char
+ end
+ end
+ elseif kind == "table" then
+ if next(list) then
+ set = set or { }
+ for byte, char in next, list do
+ set[byte] = char == true and utfchar(byte) or char
+ end
+ elseif #list > 0 then
+ set = set or { }
+ for i=1,#list do
+ local l = list[i]
+ if type(l) == "number" then
+ set[l] = utfchar(l)
+ else
+ set[utfbyte(l)] = l
+ end
+ end
+ end
+ end
+ end
+ return set
+ end
+
+ local defaulthyphens = {
+ [0x2D] = true, -- hyphen
+ [0xAD] = true, -- soft hyphen
+ }
+
+ local defaultjoiners = {
+ [0x200C] = true, -- nzwj
+ [0x200D] = true, -- zwj
+ }
+
+ local function somehyphenchar(c)
+ c = tonumber(c)
+ return c ~= 0 and c or nil
+ end
+
+ local function definefeatures(name,featureset)
+ local extrachars = featureset.characters -- "[]()"
+ local hyphenchars = featureset.hyphens
+ local joinerchars = featureset.joiners
+ local alternative = featureset.alternative
+ local rightwordmin = tonumber(featureset.rightwordmin)
+ local charmin = tonumber(featureset.charmin) -- luatex now also has hyphenationmin
+ local leftcharmin = tonumber(featureset.leftcharmin)
+ local rightcharmin = tonumber(featureset.rightcharmin)
+ local rightedge = featureset.rightedge
+ local leftchar = somehyphenchar(featureset.leftchar)
+ local rightchar = somehyphenchar(featureset.rightchar)
+ local rightchars = featureset.rightchars
+ rightchars = rightchars == v_word and true or tonumber(rightchars)
+ joinerchars = joinerchars == v_yes and defaultjoiners or joinerchars
+ hyphenchars = hyphenchars == v_yes and defaulthyphens or hyphenchars
+ -- not yet ok: extrachars have to be ignored so it cannot be all)
+ featureset.extrachars = makeset(joinerchars or "",extrachars or "")
+ featureset.hyphenchars = makeset(hyphenchars or "")
+ featureset.alternative = alternative or "hyphenate"
+ featureset.rightwordmin = rightwordmin and rightwordmin > 0 and rightwordmin or nil
+ featureset.charmin = charmin and charmin > 0 and charmin or nil
+ featureset.leftcharmin = leftcharmin and leftcharmin > 0 and leftcharmin or nil
+ featureset.rightcharmin = rightcharmin and rightcharmin > 0 and rightcharmin or nil
+ featureset.rightchars = rightchars
+ featureset.leftchar = leftchar
+ featureset.rightchar = rightchar
+ featureset.strict = rightedge == 'tex'
+ --
+ return register(name,featureset)
+ end
+
+ local function setfeatures(n)
+ if not n or n == v_reset then
+ n = false
+ else
+ local f = featuresets[n]
+ if not f and type(n) == "string" then
+ local t = settings_to_array(n)
+ local s = { }
+ for i=1,#t do
+ local ti = t[i]
+ local fs = featuresets[ti]
+ if fs then
+ for k, v in next, fs do
+ s[k] = v
+ end
+ end
+ end
+ n = register(n,s)
+ else
+ n = f and f.attribute
+ end
+ end
+ texsetattribute(a_hyphenation,n or unsetvalue)
+ end
+
+ traditional.definefeatures = definefeatures
+ traditional.setfeatures = setfeatures
+
+ implement {
+ name = "definehyphenationfeatures",
+ actions = definefeatures,
+ arguments = {
+ "string",
+ {
+ { "characters" },
+ { "hyphens" },
+ { "joiners" },
+ { "rightchars" },
+ { "rightwordmin", "integer" },
+ { "charmin", "integer" },
+ { "leftcharmin", "integer" },
+ { "rightcharmin", "integer" },
+ { "leftchar", "integer" },
+ { "rightchar", "integer" },
+ { "alternative" },
+ { "rightedge" },
+ }
+ }
+ }
+
+ implement {
+ name = "sethyphenationfeatures",
+ actions = setfeatures,
+ arguments = "string"
+ }
+
+ implement {
+ name = "registerhyphenationpattern",
+ actions = traditional.registerpattern,
+ arguments = { "string", "string", "boolean" }
+ }
+
+ implement {
+ name = "registerhyphenationexception",
+ actions = traditional.registerexception,
+ arguments = { "string", "string" }
+ }
+
+ -- This is a relative large function with local variables and local
+ -- functions. A previous implementation had the functions outside but
+ -- this is cleaner and as efficient. The test runs 100 times over
+ -- tufte.tex, knuth.tex, zapf.tex, ward.tex and darwin.tex in lower
+ -- and uppercase with a 1mm hsize.
+ --
+ -- language=0 language>0 4 | 3 * slower
+ --
+ -- tex 2.34 | 1.30 2.55 | 1.45 0.21 | 0.15
+ -- lua 2.42 | 1.38 3.30 | 1.84 0.88 | 0.46
+ --
+ -- Of course we have extra overhead (virtual Lua machine) but also we
+ -- check attributes and support specific local options). The test puts
+ -- the typeset text in boxes and discards it. If we also flush the
+ -- runtime is 4.31|2.56 and 4.99|2.94 seconds so the relative difference
+ -- is (somehow) smaller. The test has 536 pages. There is a little bit
+ -- of extra overhead because we store the patterns in a different way.
+ --
+ -- As usual I will look for speedups. Some 0.01 seconds could be gained
+ -- by sharing patterns which is not impressive but it does save some
+ -- 3M memory on this test. (Some optimizations already brought the 3.30
+ -- seconds down to 3.14 but it all depends on aggressive caching.)
+
+ -- As we kick in the hyphenator before fonts get handled, we don't look
+ -- at implicit (font) kerns or ligatures.
+
+ local starttiming = statistics.starttiming
+ local stoptiming = statistics.stoptiming
+
+ local strictids = {
+ [nodecodes.hlist] = true,
+ [nodecodes.vlist] = true,
+ [nodecodes.rule] = true,
+ [nodecodes.disc] = true,
+ [nodecodes.accent] = true,
+ [nodecodes.math] = true,
+ }
+
+ function traditional.hyphenate(head)
+
+ local first = tonut(head)
+ local tail = nil
+ local last = nil
+ local current = first
+ local dictionary = nil
+ local instance = nil
+ local characters = nil
+ local unicodes = nil
+ local exhyphenchar = tex.exhyphenchar
+ local extrachars = nil
+ local hyphenchars = nil
+ local language = nil
+ local start = nil
+ local stop = nil
+ local word = { } -- we reuse this table
+ local size = 0
+ local leftchar = false
+ local rightchar = false -- utfbyte("-")
+ local leftexchar = false
+ local rightexchar = false -- utfbyte("-")
+ local leftmin = 0
+ local rightmin = 0
+ local charmin = 1
+ local leftcharmin = nil
+ local rightcharmin = nil
+ ----- leftwordmin = nil
+ local rightwordmin = nil
+ local rightchars = nil
+ local leftchar = nil
+ local rightchar = nil
+ local attr = nil
+ local lastwordlast = nil
+ local hyphenated = hyphenate
+ local strict = nil
+ local hyphenpenalty = tex.hyphenpenalty
+
+ -- We cannot use an 'enabled' boolean (false when no characters or extras) because we
+ -- can have plugins that set a characters metatable and so) ... it doesn't save much
+ -- anyway. Using (unicodes and unicodes[code]) and a nil table when no characters also
+ -- doesn't save much. So there not that much to gain for languages that don't hyphenate.
+ --
+ -- enabled = (unicodes and (next(unicodes) or getmetatable(unicodes))) or (extrachars and next(extrachars))
+ --
+ -- This can be used to not add characters i.e. keep size 0 but then we need to check for
+ -- attributes that change it, which costs time too. Not much to gain there.
+
+ starttiming(traditional)
+
+ local function insertpenalty()
+ local p = new_penalty(interwordpenalty)
+ setfield(p,"attr",getfield(last,"attr"))
+ if trace_visualize then
+ nuts.setvisual(p,"penalty")
+ end
+ last = getprev(last)
+ first, last = insert_after(first,last,p)
+ end
+
+ local function synchronizefeatureset(a)
+ local f = a and featuresets[a]
+ if f then
+ hyphenated = methods[f.alternative or "hyphenate"]
+ extrachars = f.extrachars
+ hyphenchars = f.hyphenchars
+ rightwordmin = f.rightwordmin
+ charmin = f.charmin
+ leftcharmin = f.leftcharmin
+ rightcharmin = f.rightcharmin
+ leftchar = f.leftchar
+ rightchar = f.rightchar
+ strict = f.strict and strictids
+ rightchars = f.rightchars
+ if rightwordmin and rightwordmin > 0 and lastwordlast ~= rightwordmin then
+ -- so we can change mid paragraph but it's kind of unpredictable then
+ if not tail then
+ tail = node_tail(first)
+ end
+ last = tail
+ local inword = false
+ local count = 0
+ while last and rightwordmin > 0 do
+ local id = getid(last)
+ if id == glyph_code then
+ count = count + 1
+ inword = true
+ if trace_visualize then
+ setcolor(last,"darkgreen")
+ end
+ elseif inword then
+ inword = false
+ rightwordmin = rightwordmin - 1
+ if rightchars == true then
+ if rightwordmin > 0 then
+ insertpenalty()
+ end
+ elseif rightchars and count <= rightchars then
+ insertpenalty()
+ end
+ end
+ last = getprev(last)
+ end
+ lastwordlast = rightwordmin
+ end
+ if not charmin or charmin == 0 then
+ charmin = 1
+ end
+ else
+ hyphenated = methods.hyphenate
+ extrachars = false
+ hyphenchars = false
+ rightwordmin = false
+ charmin = 1
+ leftcharmin = false
+ rightcharmin = false
+ leftchar = false
+ rightchar = false
+ strict = false
+ end
+
+ return a
+ end
+
+ local function flush(hyphens) -- todo: no need for result
+
+ local rightmin = size - rightmin
+ local result = { }
+ local rsize = 0
+ local position = 1
+
+ -- todo: remember last dics and don't go back to before that (plus
+ -- message) .. for simplicity we also assume that we don't start
+ -- with a dics node
+ --
+ -- there can be a conflict: if we backtrack then we can end up in
+ -- another disc and get out of sync (dup chars and so)
+
+ while position <= size do
+ if position >= leftmin and position <= rightmin then
+ local hyphen = hyphens[position]
+ if not hyphen then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ elseif hyphen == true then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ rsize = rsize + 1
+ result[rsize] = true
+ position = position + 1
+ else
+ local o, h = hyphen[2]
+ if o then
+ -- { hyphen, offset)
+ h = hyphen[1]
+ else
+ -- hyphen
+ h = hyphen
+ o = 1
+ end
+ local b = position - o + (h.start or 1)
+ local e = b + (h.length or 2) - 1
+ if b > 0 and e >= b then
+ for i=1,b-position do
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ rsize = rsize + 1
+ result[rsize] = {
+ h.before or "", -- pre
+ h.after or "", -- post
+ concat(word,"",b,e), -- replace
+ h.right, -- optional after pre
+ h.left, -- optional before post
+ }
+ position = e + 1
+ else
+ -- error
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ else
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+
+ local function serialize(replacement,leftchar,rightchar)
+ if not replacement then
+ return
+ elseif replacement == true then
+ local glyph = copy_node(stop)
+ setchar(glyph,leftchar or rightchar)
+ return glyph
+ end
+ local head = nil
+ local current = nil
+ if leftchar then
+ head = copy_node(stop)
+ current = head
+ setchar(head,leftchar)
+ end
+ local rsize = #replacement
+ if rsize == 1 then
+ local glyph = copy_node(stop)
+ setchar(glyph,characters[replacement])
+ if head then
+ insert_after(current,current,glyph)
+ else
+ head = glyph
+ end
+ current = glyph
+ elseif rsize > 0 then
+ local list = lpegmatch(p_split,replacement) -- this is an utf split (could be cached)
+ for i=1,#list do
+ local glyph = copy_node(stop)
+ setchar(glyph,characters[list[i]])
+ if head then
+ insert_after(current,current,glyph)
+ else
+ head = glyph
+ end
+ current = glyph
+ end
+ end
+ if rightchar then
+ local glyph = copy_node(stop)
+ insert_after(current,current,glyph)
+ setchar(glyph,rightchar)
+ end
+ return head
+ end
+
+ local current = start
+
+ local attributes = getfield(start,"attr") -- todo: just copy the last disc .. faster
+
+ for i=1,rsize do
+ local r = result[i]
+ if r == true then
+ local disc = new_disc()
+ local pre = nil
+ local post = nil
+ if rightchar then
+ pre = serialize(true,rightchar)
+ end
+ if leftchar then
+ post = serialize(true,leftchar)
+ end
+ setdisc(disc,pre,post,nil,discretionary_code,hyphenpenalty)
+ if attributes then
+ setfield(disc,"attr",attributes)
+ end
+ -- could be a replace as well
+ insert_before(first,current,disc)
+ elseif type(r) == "table" then
+ local disc = new_disc()
+ local pre = r[1]
+ local post = r[2]
+ local replace = r[3]
+ local right = r[4] ~= false and rightchar
+ local left = r[5] ~= false and leftchar
+ if pre then
+ if pre ~= "" then
+ pre = serialize(pre,false,right)
+ else
+ pre = nil
+ end
+ end
+ if post then
+ if post ~= "" then
+ post = serialize(post,left,false)
+ else
+ post = nil
+ end
+ end
+ if replace then
+ if replace ~= "" then
+ replace = serialize(replace)
+ else
+ replace = nil
+ end
+ end
+ setdisc(disc,pre,post,replace,discretionary_code,hyphenpenalty)
+ if attributes then
+ setfield(disc,"attr",attributes)
+ end
+ insert_before(first,current,disc)
+ else
+ setchar(current,characters[r])
+ if i < rsize then
+ current = getnext(current)
+ end
+ end
+ end
+ if current and current ~= stop then
+ local current = getnext(current)
+ local last = getnext(stop)
+ while current ~= last do
+ first, current = remove_node(first,current,true)
+ end
+ end
+
+ end
+
+ local function inject(leftchar,rightchar,code,attributes)
+ if first ~= current then
+ local disc = new_disc()
+ first, current, glyph = remove_node(first,current)
+ first, current = insert_before(first,current,disc)
+ if trace_visualize then
+ setcolor(glyph,"darkred") -- these get checked
+ setcolor(disc,"darkgreen") -- in the colorizer
+ end
+ local pre = mil
+ local post = nil
+ local replace = glyph
+ if not leftchar then
+ leftchar = code
+ end
+ if rightchar then
+ pre = copy_node(glyph)
+ setchar(pre,rightchar)
+ end
+ if leftchar then
+ post = copy_node(glyph)
+ setchar(post,leftchar)
+ end
+ setdisc(disc,pre,post,replace,discretionary_code,hyphenpenalty)
+ if attributes then
+ setfield(disc,"attr",attributes)
+ end
+ end
+ return current
+ end
+
+ local a = getattr(first,a_hyphenation)
+ if a ~= attr then
+ attr = synchronizefeatureset(a)
+ end
+
+ -- The first attribute in a word determines the way a word gets hyphenated
+ -- and if relevant, other properties are also set then. We could optimize for
+ -- silly one-char cases but it has no priority as the code is still not that
+ -- much slower than the native hyphenator and this variant also provides room
+ -- for extensions.
+
+ while current and current ~= last do -- and current
+ local code, id = isglyph(current)
+ if code then
+ local lang = getfield(current,"lang")
+ if lang ~= language then
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ language = lang
+ if language > 0 then
+ --
+ dictionary = dictionaries[language]
+ instance = dictionary.instance
+ characters = dictionary.characters
+ unicodes = dictionary.unicodes
+ --
+ local a = getattr(current,a_hyphenation)
+ attr = synchronizefeatureset(a)
+ leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more
+ rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed
+ leftexchar = (instance and preexhyphenchar (instance))
+ rightexchar = (instance and postexhyphenchar(instance))
+ leftmin = leftcharmin or getfield(current,"left")
+ rightmin = rightcharmin or getfield(current,"right")
+ if not leftchar or leftchar < 0 then
+ leftchar = false
+ end
+ if not rightchar or rightchar < 0 then
+ rightchar = false
+ end
+ --
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ word[1] = char
+ size = 1
+ start = current
+ else
+ size = 0
+ end
+ else
+ size = 0
+ end
+ elseif language <= 0 then
+ --
+ elseif size > 0 then
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ size = size + 1
+ word[size] = char
+ elseif dictionary then
+ if size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ size = 0
+ -- maybe also a strict mode here: no hyphenation before hyphenchars and skip
+ -- the next set (but then, strict is an option)
+ if code == exhyphenchar then
+ current = inject(leftexchar,rightexchar,code,getfield(current,"attr"))
+ elseif hyphenchars and hyphenchars[code] then
+ current = inject(leftchar,rightchar,code,getfield(current,"attr"))
+ end
+ end
+ else
+ local a = getattr(current,a_hyphenation)
+ if a ~= attr then
+ attr = synchronizefeatureset(a) -- influences extrachars
+ leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more
+ rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed
+ leftexchar = (instance and preexhyphenchar (instance))
+ rightexchar = (instance and postexhyphenchar(instance))
+ leftmin = leftcharmin or getfield(current,"left")
+ rightmin = rightcharmin or getfield(current,"right")
+ if not leftchar or leftchar < 0 then
+ leftchar = false
+ end
+ if not rightchar or rightchar < 0 then
+ rightchar = false
+ end
+ end
+ --
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ word[1] = char
+ size = 1
+ start = current
+ end
+ end
+ stop = current
+ current = getnext(current)
+ else
+ if id == disc_code then
+ local subtype = getsubtype(current)
+ if subtype == discretionary_code then -- \discretionary
+ size = 0
+ current = getnext(current)
+ elseif subtype == explicit_code then -- \- => only here
+ size = 0
+ current = getnext(current)
+ while current do
+ local id = getid(current)
+ if id == glyph_code or id == disc_code then
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ -- todo: change to discretionary_code
+ else
+ -- automatic (-) : the hyphenator turns an exhyphen into glyph+disc
+ -- first : done by the hyphenator
+ -- second : done by the hyphenator
+ -- regular : done by the hyphenator
+ size = 0
+ current = getnext(current)
+ end
+ elseif strict and strict[id] then
+ current = id == math_code and getnext(end_of_math(current)) or getnext(current)
+ size = 0
+ else
+ current = id == math_code and getnext(end_of_math(current)) or getnext(current)
+ end
+ if size > 0 then
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ size = 0
+ end
+ end
+ end
+ -- we can have quit due to last so we need to flush the last seen word, we could move this in
+ -- the loop and test for current but ... messy
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+
+ stoptiming(traditional)
+
+ return head, true
+ end
+
+ statistics.register("hyphenation",function()
+ if nofwords > 0 or statistics.elapsed(traditional) > 0 then
+ return string.format("%s words hyphenated, %s unique, used time %s",
+ nofwords,nofhashed,statistics.elapsedseconds(traditional) or 0)
+ end
+ end)
+
+ local texmethod = "builders.kernel.hyphenation"
+ local oldmethod = texmethod
+ local newmethod = texmethod
+
+ -- local newmethod = "languages.hyphenators.traditional.hyphenate"
+ --
+ -- nodes.tasks.prependaction("processors","words",newmethod)
+ -- nodes.tasks.disableaction("processors",oldmethod)
+ --
+ -- nodes.tasks.replaceaction("processors","words",oldmethod,newmethod)
+
+ -- \enabledirectives[hyphenators.method=traditional]
+ -- \enabledirectives[hyphenators.method=builtin]
+
+ -- push / pop ? check first attribute
+
+ -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches)
+
+ local hyphenate = lang.hyphenate
+ local expanders = languages.expanders
+ local methods = { }
+ local usedmethod = false
+ local stack = { }
+
+ local function original(head)
+ local done = hyphenate(head)
+ return head, done
+ end
+
+ local function expanded(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
+
+ local getcount = tex.getcount
+
+ hyphenators.methods = methods
+ hyphenators.optimize = false
+
+ function hyphenators.handler(head,groupcode)
+ if usedmethod then
+ if groupcode == "hbox" and hyphenators.optimize then
+ if getcount("hyphenstate") > 0 then
+ forced = false
+ return usedmethod(head)
+ else
+ return head, false
+ end
+ else
+ return usedmethod(head)
+ end
+ else
+ return head, false
+ end
+ end
+
+ methods.tex = original
+ methods.original = original
+ methods.expanded = expanded
+ methods.traditional = languages.hyphenators.traditional.hyphenate
+ methods.none = false -- function(head) return head, false end
+
+ usedmethod = original
+
+ local function setmethod(method)
+ usedmethod = type(method) == "string" and methods[method]
+ if usedmethod == nil then
+ usedmethod = methods.tex
+ end
+ end
+ local function pushmethod(method)
+ insert(stack,usedmethod)
+ usedmethod = type(method) == "string" and methods[method]
+ if usedmethod == nil then
+ usedmethod = methods.tex
+ end
+ end
+ local function popmethod()
+ usedmethod = remove(stack) or methods.tex
+ end
+
+ hyphenators.setmethod = setmethod
+ hyphenators.pushmethod = pushmethod
+ hyphenators.popmethod = popmethod
+
+ directives.register("hyphenators.method",setmethod)
+
+ function hyphenators.setup(specification)
+ local method = specification.method
+ if method then
+ setmethod(method)
+ end
+ end
+
+ implement { name = "sethyphenationmethod", actions = setmethod, arguments = "string" }
+ implement { name = "pushhyphenation", actions = pushmethod, arguments = "string" }
+ implement { name = "pophyphenation", actions = popmethod }
+
+ -- can become a runtime loaded one:
+
+ local context = context
+ local ctx_NC = context.NC
+ local ctx_NR = context.NR
+ local ctx_verbatim = context.verbatim
+
+ function hyphenators.showhyphenationtrace(language,word)
+ if not word or word == "" then
+ return
+ end
+ local saved = trace_steps
+ trace_steps = "silent"
+ local steps = traditional.gettrace(language,word)
+ trace_steps = saved
+ if steps then
+ local n = #steps
+ if n > 0 then
+ context.starttabulate { "|r|l|l|l|" }
+ for i=1,n do
+ local s = steps[i]
+ ctx_NC() if i > 1 and i < n then context(i-1) end
+ ctx_NC() ctx_verbatim(s[1])
+ ctx_NC() ctx_verbatim(s[2])
+ ctx_NC() ctx_verbatim(s[3])
+ ctx_NC()
+ ctx_NR()
+ end
+ context.stoptabulate()
+ end
+ end
+ end
+
+ implement {
+ name = "showhyphenationtrace",
+ actions = hyphenators.showhyphenationtrace,
+ arguments = { "string", "string" }
+ }
+
+ 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
+ remove_node(h,false,true)
+ end
+ end
+ return tonode(h)
+ end
+
+
+else
+
+-- traditional.loadpatterns("nl","lang-nl")
+-- traditional.loadpatterns("de","lang-de")
+-- traditional.loadpatterns("us","lang-us")
+
+-- traditional.registerpattern("nl","e1ë", { start = 1, length = 2, before = "e", after = "e" } )
+-- traditional.registerpattern("nl","oo7ë", { start = 2, length = 3, before = "o", after = "e" } )
+-- traditional.registerpattern("de","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } )
+
+-- local specification = {
+-- leftcharmin = 2,
+-- rightcharmin = 2,
+-- leftchar = "<",
+-- rightchar = ">",
+-- }
+
+-- print("reëel", traditional.injecthyphens(dictionaries.nl,"reëel", specification),"r{e>}{<e}{eë}el")
+-- print("reeëel", traditional.injecthyphens(dictionaries.nl,"reeëel", specification),"re{e>}{<e}{eë}el")
+-- print("rooëel", traditional.injecthyphens(dictionaries.nl,"rooëel", specification),"r{o>}{<e}{ooë}el")
+
+-- print( "qxcxkq", traditional.injecthyphens(dictionaries.de, "qxcxkq", specification),"")
+-- print( "qqxcxkqq", traditional.injecthyphens(dictionaries.de, "qqxcxkqq", specification),"")
+-- print( "qqqxcxkqqq", traditional.injecthyphens(dictionaries.de, "qqqxcxkqqq", specification),"")
+-- print("qqqqxcxkqqqq",traditional.injecthyphens(dictionaries.de,"qqqqxcxkqqqq",specification),"")
+
+-- print("kunstmatig", traditional.injecthyphens(dictionaries.nl,"kunstmatig", specification),"")
+-- print("kunststofmatig", traditional.injecthyphens(dictionaries.nl,"kunststofmatig", specification),"")
+-- print("kunst[stof]matig", traditional.injecthyphens(dictionaries.nl,"kunst[stof]matig", specification),"")
+
+-- traditional.loadpatterns("us","lang-us")
+
+-- local specification = {
+-- leftcharmin = 2,
+-- rightcharmin = 2,
+-- leftchar = false,
+-- rightchar = false,
+-- }
+
+-- trace_steps = true
+
+-- print("components", traditional.injecthyphens(dictionaries.us,"components", specification),"")
+-- print("single", traditional.injecthyphens(dictionaries.us,"single", specification),"sin-gle")
+-- print("everyday", traditional.injecthyphens(dictionaries.us,"everyday", specification),"every-day")
+-- print("associate", traditional.injecthyphens(dictionaries.us,"associate", specification),"as-so-ciate")
+-- print("philanthropic", traditional.injecthyphens(dictionaries.us,"philanthropic", specification),"phil-an-thropic")
+-- print("projects", traditional.injecthyphens(dictionaries.us,"projects", specification),"projects")
+-- print("Associate", traditional.injecthyphens(dictionaries.us,"Associate", specification),"As-so-ciate")
+-- print("Philanthropic", traditional.injecthyphens(dictionaries.us,"Philanthropic", specification),"Phil-an-thropic")
+-- print("Projects", traditional.injecthyphens(dictionaries.us,"Projects", specification),"Projects")
+
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv
new file mode 100644
index 00000000000..ca911338623
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv
@@ -0,0 +1,274 @@
+%D \module
+%D [ file=lang-ini,
+%D version=2014.08.10,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Experimental Patterns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is an experimental module. We often have to deal with titles
+%D that have conflicting demands:
+%D
+%D \startitemize
+%D \startitem They go into a dedicated space (often a graphic). \stopitem
+%D \startitem The words cannot be hyphenated. \stopitem
+%D \startitem But as an escape they can get hyphenated. \stopitem
+%D \startitem In that case we want at least an extra word on the last line. \stopitem
+%D \stopitemize
+%D
+%D These and maybe more cases can be dealt with using dedicated hyphenation
+%D mechanisms. At he same time we want to experiment with more extensive patterns
+%D as discussed in {\em TUGboat, Volume 27 (2006), No. 2—Proceedings of EuroTEX2006}.
+
+% lua: 5.341 5.354
+% tex: 5.174 5.262
+
+\writestatus{loading}{ConTeXt Language Macros / Initialization}
+
+\registerctxluafile{lang-dis}{1.001}
+\registerctxluafile{lang-hyp}{1.001}
+
+\unprotect
+
+\definesystemattribute[hyphenation][public]
+
+%D This command can change! At some point we will keep the setting with the
+%D paragraph and then the \type {\par} can go.
+
+% \unexpanded\def\atleastoneword#1%
+% {\begingroup
+% \enabledirectives[hyphenators.method=traditional]%
+% \enabledirectives[hyphenators.rightwordsmin=1]%
+% \lefthyphenmin \plusfour
+% \righthyphenmin\plusfour
+% #1\par
+% \disabledirectives[hyphenators.rightwordsmin]%
+% \enabledirectives[hyphenators.method]%
+% \endgroup}
+
+
+% \exhyphenchar \hyphenasciicode
+% \preexhyphenchar \lessthanasciicode
+% \postexhyphenchar\morethanasciicode
+
+%D Here is the real way:
+
+\installcorenamespace{hyphenation}
+\installcorenamespace{hyphenationfeatures}
+
+\installparameterhandler \??hyphenation {hyphenation}
+\installsetuphandler \??hyphenation {hyphenation}
+
+\setuphyphenation
+ [\c!method=\s!default,
+ \s!righthyphenchar=0, % number tzt g: etc
+ \s!lefthyphenchar=0] % number
+
+\appendtoks
+ \clf_sethyphenationmethod{\hyphenationparameter\c!method}%
+\to \everysetuphyphenation
+
+%D These are mostly meant for manuals:
+
+\unexpanded\def\starthyphenation[#1]%
+ {\begingroup
+ \clf_pushhyphenation{#1}}
+
+\unexpanded\def\stophyphenation
+ {\ifhmode\par\fi
+ \clf_pophyphenation
+ \endgroup}
+
+% This is a global setting, so we need to disable it when needed. However, as
+% we are (hopefully) compatible and attribute driven one can also just keep it
+% enabled.
+%
+% \setuphyphenation
+% [\c!method=\s!traditional] % no translations
+
+\unexpanded\def\definehyphenationfeatures
+ {\dodoubleargument\lang_hyphenation_define_features}
+
+\unexpanded\def\lang_hyphenation_define_features[#1][#2]%
+ {\begingroup
+ \letdummyparameter\c!characters\empty % maybe \s!
+ \letdummyparameter\c!hyphens\empty % maybe \s!
+ \letdummyparameter\c!joiners\empty % maybe \s!
+ \letdummyparameter\c!rightwords\zerocount % maybe \s!
+ \letdummyparameter\s!lefthyphenmin\zerocount
+ \letdummyparameter\s!righthyphenmin\zerocount
+ \letdummyparameter\s!hyphenmin\zerocount
+ \letdummyparameter\s!lefthyphenchar\zerocount
+ \letdummyparameter\s!righthyphenchar\zerocount
+ \letdummyparameter\c!alternative\empty
+ \letdummyparameter\c!rightedge\empty
+ \letdummyparameter\c!rightchars\empty
+ \getdummyparameters[#2]%
+ \clf_definehyphenationfeatures
+ {#1}%
+ {
+ characters {\dummyparameter\c!characters}%
+ hyphens {\dummyparameter\c!hyphens}%
+ joiners {\dummyparameter\c!joiners}%
+ rightwordmin \numexpr\dummyparameter\c!rightwords\relax
+ rightchars {\dummyparameter\c!rightchars}%
+ charmin \numexpr\dummyparameter\s!hyphenmin\relax
+ leftcharmin \numexpr\dummyparameter\s!lefthyphenmin\relax
+ rightcharmin \numexpr\dummyparameter\s!righthyphenmin\relax
+ leftchar \numexpr\dummyparameter\s!lefthyphenchar\relax
+ rightchar \numexpr\dummyparameter\s!righthyphenchar\relax
+ alternative {\dummyparameter\c!alternative}%
+ rightedge {\dummyparameter\c!rightedge}%
+ }%
+ \relax
+ \endgroup}
+
+\unexpanded\def\sethyphenationfeatures[#1]%
+ {\clf_sethyphenationfeatures{#1}}
+
+\unexpanded\def\resethyphenationfeatures
+ {\hyphenationattribute\attributeunsetvalue}
+
+\resethyphenationfeatures
+
+% todo: \start ... \stop too
+
+\unexpanded\def\registerhyphenationpattern
+ {\dodoubleempty\lang_hyphenation_register_pattern}
+
+\def\lang_hyphenation_register_pattern[#1][#2]%
+ {\clf_registerhyphenationpattern\ifsecondargument{#1}{#2}\else{\currentlanguage}{#1}\fi\s!true\relax}
+
+\unexpanded\def\unregisterhyphenationpattern
+ {\dodoubleempty\lang_hyphenation_unregister_pattern}
+
+\def\lang_hyphenation_unregister_pattern[#1][#2]%
+ {\clf_registerhyphenationpattern\ifsecondargument{#1}{#2}\else{\currentlanguage}{#1}\fi\s!false\relax}
+
+\unexpanded\def\registerhyphenationexception
+ {\dodoubleempty\lang_hyphenation_register_exception}
+
+\def\lang_hyphenation_register_exception[#1][#2]%
+ {\clf_registerhyphenationexception\ifsecondargument{#1}{#2}\else{\currentlanguage}{#1}\fi\relax}
+
+\unexpanded\def\showhyphenationtrace
+ {\dodoubleempty\lang_hyphenation_show_trace}
+
+\def\lang_hyphenation_show_trace[#1][#2]%
+ {\begingroup
+ \tt
+ \clf_showhyphenationtrace\ifsecondargument{#1}{#2}\else{\currentlanguage}{#1}\fi\relax
+ \endgroup}
+
+% For old times sake:
+
+\unexpanded\def\atleastoneword#1%
+ {\begingroup
+ \starthyphenation[traditional]% this might become default or a faster switch
+ \sethyphenationfeatures[words]%
+ #1\par
+ \stophyphenation
+ \endgroup}
+
+%D For me:
+
+\unexpanded\def\showdiscretionaries
+ {\clf_showdiscretionaries}
+
+%D These are (at least now) not cummulative:
+
+\definehyphenationfeatures % just an example
+ [fences]
+ [\c!characters={[]()}]
+
+\definehyphenationfeatures
+ [words]
+ [\c!rightwords=1,
+ \s!lefthyphenmin=4,
+ \s!righthyphenmin=4]
+
+\definehyphenationfeatures
+ [default]
+ [%c!rightedge=\v!tex,
+ \c!hyphens=\v!yes,
+ \c!joiners=\v!yes]
+
+\definehyphenationfeatures
+ [strict]
+ [\c!rightedge=\s!tex]
+
+% \sethyphenationfeatures
+% [fences]
+
+% \sethyphenationfeatures
+% [default,fences]
+
+% \setuphyphenation % will be default
+% [method=expanded]
+
+\protect \endinput
+
+% \starttext
+%
+% \enabledirectives[hyphenators.method=traditional]
+%
+% % \dorecurse{1000}{\input tufte \par}
+%
+% \setupalign[verytolerant,flushleft]
+% \setuplayout[width=140pt] \showframe
+%
+% longword longword long word longword longwordword \blank
+%
+% \enabledirectives[hyphenators.rightwordsmin=1]
+%
+% longword longword long word longword longwordword\blank
+%
+% \disabledirectives[hyphenators.rightwordsmin]
+%
+% longword longword long word longword longwordword\blank
+%
+% \atleastoneword{longword longword long word longword longwordword}
+%
+% \enabledirectives[hyphenators.method=traditional]
+%
+% \stoptext
+
+% \startluacode
+% -- e1ë/e=e reëel re-eel
+% -- a1atje./a=t,1,3 omaatje oma-tje
+% -- schif1f/ff=f,5,2 Schiffahrt Schiff-fahrt
+%
+% languages.hyphenators.traditional.registerpattern("en","a1b", { start = 1, length = 2, before = "CD", after = "EF" } )
+% languages.hyphenators.traditional.registerpattern("en","e1ë", { start = 1, length = 2, before = "e", after = "e" } )
+% languages.hyphenators.traditional.registerpattern("en","oo1ë", { start = 2, length = 2, before = "o", after = "e" } )
+% languages.hyphenators.traditional.registerpattern("en","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } ) -- replacement start length
+%
+% -- print("reëel", injecthyphens(dictionaries.nl,"reëel", 2,2))
+% -- print("reeëel", injecthyphens(dictionaries.nl,"reeëel", 2,2))
+% -- print("rooëel", injecthyphens(dictionaries.nl,"rooëel", 2,2))
+% -- print( "QXcXkQ", injecthyphens(dictionaries.de, "QXcXkQ", 2,2))
+% -- print( "QQXcXkQQ", injecthyphens(dictionaries.de, "QQXcXkQQ", 2,2))
+% -- print( "QQQXcXkQQQ", injecthyphens(dictionaries.de, "QQQXcXkQQQ", 2,2))
+% -- print("QQQQXcXkQQQQ",injecthyphens(dictionaries.de,"QQQQXcXkQQQQ",2,2))
+% --
+% -- print( "QQXcXkQQ QQXcXkQQ", injecthyphens(dictionaries.de, "QQXcXkQQ QQXcXkQQ", 2,2))
+% \stopluacode
+%
+% \starttext
+%
+% \blank
+%
+% xreëel rooëel \par xxabxx xxxabxxx \par
+%
+% \hsize1mm \lefthyphenmin2 \righthyphenmin2
+%
+% \blank Capacity \blank capacity \blank xyabxy \blank xreëel \blank rooëel \blank
+%
+% xy\discretionary{CD}{EF}{ab}xy % xxacceedxxx
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua
new file mode 100644
index 00000000000..eb7e32b89f3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua
@@ -0,0 +1,476 @@
+if not modules then modules = { } end modules ['lang-ini'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- needs a cleanup (share locals)
+-- discard language when redefined
+
+-- 002D : hyphen-minus (ascii)
+-- 2010 : hyphen
+-- 2011 : nonbreakable hyphen
+-- 2013 : endash (compound hyphen)
+
+--~ lang:hyphenation(string) string = lang:hyphenation() lang:clear_hyphenation()
+
+-- todo: no foo:bar but foo(bar,...)
+
+local type, tonumber = type, tonumber
+local utfbyte = utf.byte
+local format, gsub = string.format, string.gsub
+local concat, sortedkeys, sortedpairs = table.concat, table.sortedkeys, table.sortedpairs
+local utfbytes, strip = string.utfvalues, string.strip
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local trace_patterns = false trackers.register("languages.patterns", function(v) trace_patterns = v end)
+
+local report_initialization = logs.reporter("languages","initialization")
+
+local lang = lang
+
+local prehyphenchar = lang.prehyphenchar -- global per language
+local posthyphenchar = lang.posthyphenchar -- global per language
+local preexhyphenchar = lang.preexhyphenchar -- global per language
+local postexhyphenchar = lang.postexhyphenchar -- global per language
+local lefthyphenmin = lang.lefthyphenmin
+local righthyphenmin = lang.righthyphenmin
+local sethjcode = lang.sethjcode
+
+local uccodes = characters.uccodes
+
+lang.exceptions = lang.hyphenation
+local new_langage = lang.new
+
+languages = languages or {}
+local languages = languages
+
+languages.version = 1.010
+
+languages.registered = languages.registered or { }
+local registered = languages.registered
+
+languages.associated = languages.associated or { }
+local associated = languages.associated
+
+languages.numbers = languages.numbers or { }
+local numbers = languages.numbers
+
+languages.data = languages.data or { }
+local data = languages.data
+
+storage.register("languages/registered",registered,"languages.registered")
+storage.register("languages/associated",associated,"languages.associated")
+storage.register("languages/numbers", numbers, "languages.numbers")
+storage.register("languages/data", data, "languages.data")
+
+local nofloaded = 0
+
+local function resolve(tag)
+ local data, instance = registered[tag], nil
+ if data then
+ instance = data.instance
+ if not instance then
+ instance = new_langage(data.number)
+ data.instance = instance
+ end
+ end
+ return data, instance
+end
+
+local function tolang(what) -- returns lang object
+ if not what then
+ what = tex.language
+ end
+ local tag = numbers[what]
+ local data = tag and registered[tag] or registered[what]
+ if data then
+ local instance = data.lang
+ if not instance then
+ instance = new_langage(data.number)
+ data.instance = instance
+ end
+ return instance
+ end
+end
+
+function languages.getdata(tag) -- or number
+ if tag then
+ return registered[tag] or registered[numbers[tag]]
+ else
+ return registered[numbers[tex.language]]
+ end
+end
+
+-- languages.tolang = tolang
+
+-- patterns=en
+-- patterns=en,de
+
+local function validdata(loaded,what,tag)
+ local dataset = loaded[what]
+ if dataset then
+ local data = dataset.data
+ if not data or data == "" then
+ return nil
+ elseif dataset.compression == "zlib" then
+ data = zlib.decompress(data)
+ if dataset.length and dataset.length ~= #data then
+ report_initialization("compression error in %a for language %a","patterns",what,tag)
+ end
+ return data
+ else
+ return data
+ end
+ end
+end
+
+local function sethjcodes(instance,loaded,what)
+ local l = loaded[what]
+ local c = l and l.characters
+ if c then
+ local h = l.codehash
+ if not h then
+ h = { }
+ l.codehash = h
+ end
+ local s = tex.savinghyphcodes
+ tex.savinghyphcodes = 0
+ for l in utfbytes(c) do
+ local u = uccodes[l]
+ sethjcode(instance,l,l)
+ h[l] = l
+ if type(u) == "number" then
+ -- we don't want ß -> SS
+ sethjcode(instance,u,l)
+ h[u] = l
+ end
+ end
+ tex.savinghyphcodes = s
+ end
+end
+
+local function loaddefinitions(tag,specification)
+ statistics.starttiming(languages)
+ local data, instance = resolve(tag)
+ local definitions = settings_to_array(specification.patterns or "")
+ if #definitions > 0 then
+ if trace_patterns then
+ report_initialization("pattern specification for language %a: %s",tag,specification.patterns)
+ end
+ local dataused = data.used
+ local ok = false
+ local resources = data.resources or { }
+ data.resources = resources
+ for i=1,#definitions do
+ local definition = definitions[i]
+ if definition == "" then
+ -- error
+ elseif definition == "reset" then -- interfaces.variables.reset
+ if trace_patterns then
+ report_initialization("clearing patterns for language %a",tag)
+ end
+ instance:clear_patterns()
+ elseif not dataused[definition] then
+ dataused[definition] = definition
+ local filename = "lang-" .. definition .. ".lua"
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname == "" then
+ fullname = resolvers.findfile(filename .. ".gz") or ""
+ end
+ if fullname ~= "" then
+ if trace_patterns then
+ report_initialization("loading definition %a for language %a from %a",definition,tag,fullname)
+ end
+ local suffix, gzipped = gzip.suffix(fullname)
+ local loaded = table.load(fullname,gzipped and gzip.load)
+ if loaded then -- todo: version test
+ ok, nofloaded = true, nofloaded + 1
+ sethjcodes(instance,loaded,"patterns")
+ sethjcodes(instance,loaded,"exceptions")
+ instance:patterns (validdata(loaded,"patterns", tag) or "")
+ instance:hyphenation(validdata(loaded,"exceptions",tag) or "")
+ resources[#resources+1] = loaded -- so we can use them otherwise
+ else
+ report_initialization("invalid definition %a for language %a in %a",definition,tag,filename)
+ end
+ elseif trace_patterns then
+ report_initialization("invalid definition %a for language %a in %a",definition,tag,filename)
+ end
+ elseif trace_patterns then
+ report_initialization("definition %a for language %a already loaded",definition,tag)
+ end
+ end
+ return ok
+ elseif trace_patterns then
+ report_initialization("no definitions for language %a",tag)
+ end
+ statistics.stoptiming(languages)
+end
+
+storage.shared.noflanguages = storage.shared.noflanguages or 0
+
+local noflanguages = storage.shared.noflanguages
+
+function languages.define(tag,parent)
+ noflanguages = noflanguages + 1
+ if trace_patterns then
+ report_initialization("assigning number %a to %a",noflanguages,tag)
+ end
+ numbers[noflanguages] = tag
+ registered[tag] = {
+ tag = tag,
+ parent = parent or "",
+ patterns = "",
+ loaded = false,
+ used = { },
+ dirty = true,
+ number = noflanguages,
+ instance = nil, -- luatex data structure
+ synonyms = { },
+ }
+ storage.shared.noflanguages = noflanguages
+end
+
+function languages.setsynonym(synonym,tag) -- convenience function
+ local l = registered[tag]
+ if l then
+ l.synonyms[synonym] = true -- maybe some day more info
+ end
+end
+
+function languages.installed(separator)
+ return concat(sortedkeys(registered),separator or ",")
+end
+
+function languages.current(n)
+ return numbers[n and tonumber(n) or tex.language]
+end
+
+function languages.associate(tag,script,language) -- not yet used
+ associated[tag] = { script, language }
+end
+
+function languages.association(tag) -- not yet used
+ if type(tag) == "number" then
+ tag = numbers[tag]
+ end
+ local lat = tag and associated[tag]
+ if lat then
+ return lat[1], lat[2]
+ end
+end
+
+function languages.loadable(tag,defaultlanguage) -- hack
+ local l = registered[tag] -- no synonyms
+ if l and resolvers.findfile("lang-"..l.patterns..".lua") then
+ return true
+ else
+ return false
+ end
+end
+
+-- a bit messy, we will do all language setting in lua as we can now assign
+-- and 'patterns' will go away here.
+
+function languages.unload(tag)
+ local l = registered[tag]
+ if l then
+ l.dirty = true
+ end
+end
+
+if environment.initex then
+
+ function languages.getnumber()
+ return 0
+ end
+
+else
+
+ function languages.getnumber(tag,default,patterns)
+ local l = registered[tag]
+ if l then
+ if l.dirty then
+ if trace_patterns then
+ report_initialization("checking patterns for %a with default %a",tag,default)
+ end
+ -- patterns is already resolved to parent patterns if applicable
+ if patterns and patterns ~= "" then
+ if l.patterns ~= patterns then
+ l.patterns = patterns
+ if trace_patterns then
+ report_initialization("loading patterns for %a using specification %a",tag,patterns)
+ end
+ loaddefinitions(tag,l)
+ else
+ -- unchanged
+ end
+ elseif l.patterns == "" then
+ l.patterns = tag
+ if trace_patterns then
+ report_initialization("loading patterns for %a using tag",tag)
+ end
+ local ok = loaddefinitions(tag,l)
+ if not ok and tag ~= default then
+ l.patterns = default
+ if trace_patterns then
+ report_initialization("loading patterns for %a using default",tag)
+ end
+ loaddefinitions(tag,l)
+ end
+ end
+ l.loaded = true
+ l.dirty = false
+ end
+ return l.number
+ else
+ return 0
+ end
+ end
+
+end
+
+-- not that usefull, global values
+
+function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) end
+function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end
+function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end
+function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end
+function languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end
+function languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end
+
+-- e['implementer']= 'imple{m}{-}{-}menter'
+-- e['manual'] = 'man{}{}{}'
+-- e['as'] = 'a-s'
+-- e['user-friendly'] = 'user=friend-ly'
+-- e['exceptionally-friendly'] = 'excep-tionally=friend-ly'
+
+function languages.loadwords(tag,filename)
+ local data, instance = resolve(tag)
+ if data then
+ statistics.starttiming(languages)
+ instance:hyphenation(io.loaddata(filename) or "")
+ statistics.stoptiming(languages)
+ end
+end
+
+function languages.setexceptions(tag,str)
+ local data, instance = resolve(tag)
+ if data then
+ instance:hyphenation(strip(str)) -- we need to strip leading spaces
+ end
+end
+
+function languages.hyphenate(tag,str)
+ -- todo: does this still work?
+ local data, instance = resolve(tag)
+ if data then
+ return instance:hyphenate(str)
+ else
+ return str
+ end
+end
+
+-- hyphenation.define ("zerolanguage")
+-- hyphenation.loadpatterns ("zerolanguage") -- else bug
+-- hyphenation.loadexceptions("zerolanguage") -- else bug
+
+languages.logger = languages.logger or { }
+
+function languages.logger.report()
+ local result, r = { }, 0
+ for tag, l in sortedpairs(registered) do
+ if l.loaded then
+ r = r + 1
+ result[r] = format("%s:%s:%s",tag,l.parent,l.number)
+ end
+ end
+ return r > 0 and concat(result," ") or "none"
+end
+
+-- must happen at the tex end .. will use lang-def.lua
+
+languages.associate('en','latn','eng')
+languages.associate('uk','latn','eng')
+languages.associate('nl','latn','nld')
+languages.associate('de','latn','deu')
+languages.associate('fr','latn','fra')
+
+statistics.register("loaded patterns", function()
+ local result = languages.logger.report()
+ if result ~= "none" then
+ -- return result
+ return format("%s, load time: %s",result,statistics.elapsedtime(languages))
+ end
+end)
+
+-- statistics.register("language load time", function()
+-- -- often zero so we can merge that in the above
+-- return statistics.elapsedseconds(languages, format(", nofpatterns: %s",nofloaded))
+-- end)
+
+-- interface
+
+implement {
+ name = "languagenumber",
+ actions = { languages.getnumber, context },
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "installedlanguages",
+ actions = { languages.installed, context },
+}
+
+implement {
+ name = "definelanguage",
+ actions = languages.define,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setlanguagesynonym",
+ actions = languages.setsynonym,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "unloadlanguage",
+ actions = languages.unload,
+ arguments = { "string" }
+}
+
+implement {
+ name = "setlanguageexceptions",
+ actions = languages.setexceptions,
+ arguments = { "string", "string" }
+}
+
+
+implement {
+ name = "currentprehyphenchar",
+ actions = function()
+ local c = prehyphenchar(tolang())
+ if c and c > 0 then
+ context.char(c)
+ end
+ end
+}
+
+implement {
+ name = "currentposthyphenchar",
+ actions = function()
+ local c = posthyphenchar(tolang())
+ if c and c > 0 then
+ context.char(c)
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv
new file mode 100644
index 00000000000..8ff41b28792
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv
@@ -0,0 +1,831 @@
+%D \module
+%D [ file=lang-ini,
+%D version=1996.01.25,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module needs a further cleanup (real split between ii/iv).
+
+% \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.
+
+\writestatus{loading}{ConTeXt Language Macros / Initialization}
+
+\registerctxluafile{lang-ini}{1.001}
+\registerctxluafile{lang-def}{1.001}
+
+\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 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.
+
+\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
+%D \starttyping
+%D \dorecurse{3}
+%D {\language[nl]
+%D \startmode[*en] english \stopmode
+%D \startmode[*nl] dutch \stopmode
+%D \language[en]
+%D \startmode[*en] english \stopmode
+%D \startmode[*nl] dutch \stopmode}
+%D \stoptyping
+
+\let\currentlanguage \empty
+\let\currentmainlanguage\empty
+
+%D \macros
+%D {defaultlanguage,languageparameter,specificlanguageparameter}
+
+%D We don't use the commandhandler here (yet) because we have
+%D a rather special fallback mechanism so quite some compatibility
+%D testing is needed.
+
+\installcorenamespace{language}
+\installcorenamespace{languagelinked}
+
+\def\currentusedlanguage{\currentlanguage}
+
+\def\defaultlanguage#1%
+ {\ifcsname\??language#1\s!default\endcsname
+ \expandafter\defaultlanguage\lastnamedcs
+ \else
+ #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
+ \else\ifcsname\??language\currentlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \else\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\def\specificlanguageparameter#1#2%
+ {\ifcsname\??language#1#2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??language#1\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#2}%
+ \else\ifcsname\??language\s!default#2\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\def\mainlanguageparameter#1%
+ {\ifcsname\??language\currentmainlanguage#1\endcsname
+ \lastnamedcs
+ \else\ifcsname\??language\currentmainlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \else\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\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
+ \else\ifcsname\??language\currentusedlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\lastnamedcs{#1}%
+ \else\ifcsname\??language\s!default#1\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\unexpanded\def\setlanguageparameter#1%
+ {\edef\currentusedlanguage{\reallanguagetag{#1\c!language}}%
+ %\let\setlanguageparameter\gobbleoneargument
+ \ifx\currentusedlanguage\empty
+ \let\currentusedlanguage \currentlanguage
+ \let\usedlanguageparameter\languageparameter
+ \else\ifx\currentusedlanguage\v!global
+ \let\currentusedlanguage \currentmainlanguage
+ \let\usedlanguageparameter\mainlanguageparameter
+ \else\ifx\currentusedlanguage\v!local
+ \let\currentusedlanguage \currentlanguage
+ \let\usedlanguageparameter\languageparameter
+ \else
+ \let\usedlanguageparameter\askedlanguageparameter
+ \fi\fi\fi}
+
+\unexpanded\def\setupcurrentlanguage[#1]%
+ {\setcurrentlanguage\currentmainlanguage{#1}}
+
+\unexpanded\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
+ {\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage
+ \ifx\xaskedlanguage\empty \else
+ \ifx\currentmainlanguage\empty\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
+ \let\currentmainlanguage\xaskedlanguage
+ \setsystemmode{\systemmodeprefix\currentmainlanguage}%
+ \fi
+ \edef\xaskedlanguage{#2}%
+ \ifx\xaskedlanguage\empty \else
+ \ifx\currentlanguage\empty\else\resetsystemmode\currentlanguage\fi
+ \let\currentlanguage\xaskedlanguage
+ \setsystemmode\currentlanguage
+ \fi}
+
+%D The internal macros will be defined later.
+
+%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
+%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 \f!languageprefix-identifier.\f!patternsextension
+%D \f!languageprefix-identifier.\f!hyhensextension
+%D \stoptyping
+%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
+%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.
+
+\newtoks \everysetuplanguage
+
+\def\installedlanguages{\clf_installedlanguages}
+
+\unexpanded\def\doifelselanguage#1%
+ {\ifcsname\??language#1\c!state\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\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
+
+\unexpanded\def\installlanguage
+ {\dodoubleargument\lang_basics_install}
+
+\def\lang_basics_install[#1][#2]%
+ {\doifelseassignment{#2}
+ {\doifelselanguage{#1}
+ {\getparameters[\??language#1][#2]}
+ {\setvalue{\??languagelinked#1}{#1}%
+ \lang_basics_install_indeed{#1}{#1}%
+ \getparameters[\??language#1][\c!state=\v!start,#2]}%
+ \edef\currentsetuplanguage{#1}%
+ \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}%
+ \the\everysetuplanguage}
+ {\setvalue{\??languagelinked#1}{#2}%
+ \clf_setlanguagesynonym{#1}{#2}%
+ \lang_basics_install_indeed{#1}{#2}}}
+
+\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.
+
+\unexpanded\def\doifelsepatterns#1%
+ {\begingroup % will change
+ \lang_basics_set_current[#1]%
+ \ifnum\normallanguage>\zerocount
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifpatternselse\doifelsepatterns
+
+%D \macros
+%D {setuplanguage}
+%D
+%D Quick and dirty, but useful:
+%D
+%D \showsetup{setuplanguage}
+%D
+%D Beware, this command can only be used when a language is installed.
+
+\unexpanded\def\setuplanguage
+ {\dodoubleempty\lang_basics_setup}
+
+\ifdefined\lang_basics_synchronize \else
+ \let\lang_basics_synchronize\relax % be nice for setups till we have one
+\fi
+
+\def\lang_basics_setup[#1][#2]%
+ {\ifsecondargument
+ \pushmacro\currentlanguage % can be default
+ \edef\currentsetuplanguage{\reallanguagetag{#1}}%
+ \getparameters[\??language\currentsetuplanguage][#2]%
+ \the\everysetuplanguage
+ \popmacro\currentlanguage
+ %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default)
+ \else
+ \let\currentsetuplanguage\currentlanguage
+ \getparameters[\??language\currentsetuplanguage][#1]%
+ \the\everysetuplanguage
+ \fi
+ \lang_basics_synchronize}
+
+\appendtoks
+ \clf_unloadlanguage{\currentsetuplanguage}%
+\to \everysetuplanguage
+
+\setuplanguage
+ [\s!default]
+ [\s!patterns=,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \s!lefthyphenchar=-1,
+ \s!righthyphenchar=45,
+ % used in compound i.e. interfaced with c! and can be anything so no numbers
+ \c!lefthyphen=,
+ \c!righthyphen=-,
+ \c!hyphen=-,
+ \c!spacing=\v!packed,
+ \c!compoundhyphen=\compoundhyphen,
+ \c!rightcompoundhyphen=\compoundhyphen,
+ \c!leftcompoundhyphen=,
+ \c!midsentence=---,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!leftspeech=\languageparameter\c!leftquotation,
+ \c!middlespeech=,
+ \c!rightspeech=\languageparameter\c!rightquotation,
+ \c!limittext=\unknown,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \c!text=Ag,
+ \s!font=] % \v!auto : experimental !
+
+% to be tested:
+%
+% \setuplanguage
+% [\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 \macros
+%D {currentdatespecification}
+%D
+%D Just to make things easy we can ask for the current date
+%D specification by saying:
+
+\def\currentdatespecification{\languageparameter\c!date}
+
+%D This command is not meant for users.
+
+%D Carefull reading of these macros shows that it's legal to
+%D say
+%D
+%D \starttyping
+%D \installlanguage [du] [de]
+%D \stoptyping
+
+%D \macros
+%D {language,mainlanguage}
+%D
+%D Switching to another language (actually another hyphenation
+%D pattern) is done 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
+%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
+%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).
+
+\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
+\to \everysetuplanguage
+
+\def\lang_basics_synchronize_yes
+ {\zerocount % see below
+ \global\expandafter\chardef\csname\??languagenumbers\currentlanguage\endcsname
+ \clf_languagenumber
+ {\currentlanguage}%
+ {\defaultlanguage\currentlanguage}%
+ {\languageparameter\s!patterns}%
+ \relax
+ \normallanguage\csname\??languagenumbers\currentlanguage\endcsname}
+
+\let\lang_basics_synchronize_nop\zerocount % not loaded anyway
+
+\letvalue{\??languagenumbers}\lang_basics_synchronize_nop % initime
+
+\appendtoks
+ \letvalue{\??languagenumbers}\lang_basics_synchronize_yes % runtime
+\to \everydump
+
+\def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex
+ {\normallanguage\csname\??languagenumbers
+ \ifcsname\??languagenumbers\currentlanguage\endcsname
+ \currentlanguage
+ \fi
+ \endcsname
+ \relax
+ \the\everylanguage
+ \relax}
+
+% experimental
+
+\newcount\hyphenstate
+
+% so far
+
+\newcount\hyphenminoffset
+
+\unexpanded\def\lesshyphens
+ {\advance\hyphenminoffset\plusone
+ \lang_basics_synchronize_min_max}
+
+\unexpanded\def\morehyphens
+ {\ifcase\hyphenminoffset \else
+ \advance\hyphenminoffset\minusone
+ \fi
+ \lang_basics_synchronize_min_max}
+
+% \unexpanded\def\nohyphens % % % % % not clever, we still hyphenate but supress application
+% {\ifx\dohyphens\relax
+% \unexpanded\edef\dohyphens
+% {\hyphenpenalty \the\hyphenpenalty
+% \exhyphenpenalty\the\exhyphenpenalty
+% \relax}%
+% \fi
+% \hyphenpenalty \plustenthousand
+% \exhyphenpenalty\plustenthousand}
+
+\unexpanded\def\nohyphens % nicer for url's
+ {\ifx\dohyphens\relax
+ \unexpanded\edef\dohyphens
+ {\hyphenminoffset\the\hyphenminoffset\relax
+ \lang_basics_synchronize_min_max}%
+ \fi
+ \hyphenminoffset\plusthousand
+ \lang_basics_synchronize_min_max}
+
+\let\dohyphens\relax
+
+\unexpanded\def\lang_basics_synchronize_min_max
+ {% these values are stored along with glyph nodes
+ \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
+ \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax
+ \hyphenationmin\numexpr0\languageparameter\s!hyphenmin\relax
+ % these values are stored with the language (global!)
+ \prehyphenchar \languageparameter\s!righthyphenchar\relax
+ \posthyphenchar\languageparameter\s!lefthyphenchar \relax}
+
+\appendtoks
+ \lang_basics_synchronize_min_max
+\to \everylanguage
+
+\unexpanded\def\unhyphenated
+ {\groupedcommand{\lefthyphenmin\maxdimen}\donothing}
+
+% \appendtoks
+% \setups[\languageparameter\c!setups]%
+% \to \everylanguage
+
+%D You can setup the 'default' language to reset settings.
+
+\appendtoks
+ \edef\currentlanguagesetups{\languageparameter\c!setups}%
+ \ifx\currentlanguagesetups\empty \else
+ \setups[\currentlanguagesetups]%
+ \fi
+\to \everylanguage
+
+% this will move to core-spa !
+
+\appendtoks
+ \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing
+\to \everylanguage
+
+% \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?]
+%
+% \dorecurse{100}{dit is toch wel een heel\normalhyphendiscretionary lang\normalhyphendiscretionary woord \recurselevel\ }
+% \dorecurse{100}{dit is toch wel een heellangwoord \recurselevel\ }
+
+% new experimental feature
+
+\unexpanded\def\setuplanguages
+ {\setuplanguage[\s!default]}
+
+% \setuplanguages[\s!font=\v!auto]
+% \setuplanguage[\s!default][\s!font=\v!auto]
+% \setuplanguage[nl][\s!font=\v!auto]
+
+\ifdefined\feature \else \let\feature\gobbleoneargument \fi
+
+\appendtoks
+ \edef\p_language_font{\languageparameter\s!font}%
+ \ifx\p_language_font\v!auto
+ \doaddfeature\currentlanguage
+ \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
+% {\ifx\askedlanguage\empty \else
+% \ifcsname\??languagelinked\askedlanguage\endcsname
+% \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+% \ifx\currentlanguage\askedlanguage \else
+% \setcurrentlanguage\currentmainlanguage\askedlanguage
+% \lang_basics_synchronize
+% \fi
+% \fi
+% \fi}
+
+\def\lang_basics_switch_asked
+ {\ifx\askedlanguage\empty \else
+ \ifcsname\??languagelinked\askedlanguage\endcsname
+ %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+ \edef\askedlanguage{\lastnamedcs}%
+ \ifx\currentlanguage\askedlanguage \else
+ \setcurrentlanguage\currentmainlanguage\askedlanguage
+ \lang_basics_synchronize
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\uselanguageparameter#1%
+ {\edef\askedlanguage{#1\c!language}%
+ \lang_basics_switch_asked}
+
+\unexpanded\def\lang_basics_set_current[#1]%
+ {\edef\askedlanguage{#1}%
+ \lang_basics_switch_asked}
+
+\unexpanded\def\language
+ {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
+
+\let\setlanguage\language % we make these synonyms
+
+\let\patterns\gobbleoneargument
+
+\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}
+
+\unexpanded\def\mainlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty \else
+ \ifcsname\??languagelinked\askedlanguage\endcsname
+ %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+ \edef\askedlanguage{\lastnamedcs}%
+ \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}
+
+\appendtoks
+ \normallanguage\mainlanguagenumber
+\to \everybeforepagebody
+
+%D Used at all?
+
+\def\splitsequence#1#2%
+ {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}}
+
+\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
+%D \def\ShowLanguageValues [#1] [#2] #3 #4
+%D {\blank
+%D \startlinecorrection
+%D \vbox\bgroup
+%D \language[#1]
+%D \midaligned{\bf#2 subsentence symbol and quotes}
+%D \framed[width=\hsize,frame=off,topframe=on,bottomframe=on,offset=.5ex]
+%D {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
+%D \startsubsentence\startsubsentence#3\stopsubsentence#4\stopsubsentence\hfil}
+%D \egroup
+%D \stoplinecorrection
+%D \blank}
+%D
+%D \ShowLanguageValues [af] [afrikaans] afrikaanse ...
+%D \ShowLanguageValues [ca] [catalan] catalan ...
+%D \ShowLanguageValues [cs] [czech] tjechisch tex
+%D \ShowLanguageValues [cs] [slovak] slowaakse ...
+%D \ShowLanguageValues [da] [danish] deense ...
+%D \ShowLanguageValues [de] [german] duitse degelijkheid
+%D \ShowLanguageValues [en] [english] engelse humor
+%D \ShowLanguageValues [fi] [finnish] finse ...
+%D \ShowLanguageValues [fr] [french] franse slag
+%D \ShowLanguageValues [it] [italian] italiaanse ...
+%D \ShowLanguageValues [la] [latin] latijnse missen
+%D \ShowLanguageValues [nl] [dutch] nederlandse zuinigheid
+%D \ShowLanguageValues [nb] [bokmal] noorse zalm
+%D \ShowLanguageValues [nn] [nnynorsk] noorse zalm
+%D \ShowLanguageValues [pl] [polish] poolse vlag
+%D \ShowLanguageValues [pt] [portuguese] portugese ...
+%D \ShowLanguageValues [es] [spanish] spaans benauwd
+%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
+%D \unprotect
+%D \placetable{The germanic languages (\type{lang-ger})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!nl \NC dutch \NC germanic \NC\FR
+%D \NC \s!en \NC english \NC germanic \NC\MR
+%D \NC \s!de \NC german \NC germanic \NC\MR
+%D \NC \s!da \NC danish \NC germanic \NC\MR
+%D \NC \s!sv \NC swedish \NC germanic \NC\MR
+%D \NC \s!af \NC afrikaans \NC germanic \NC\MR
+%D \NC \s!nb \NC bokmal \NC germanic \NC\LR
+%D \NC \s!nn \NC nynorsk \NC germanic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D
+%D \unprotect
+%D \placetable{The italic languages (\type{lang-ita})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!fr \NC french \NC italic \NC\FR
+%D \NC \s!ca \NC catalan \NC italic \NC\MR
+%D \NC \s!es \NC spanish \NC italic \NC\MR
+%D \NC \s!it \NC italian \NC italic \NC\MR
+%D \NC \s!la \NC latin \NC italic \NC\MR
+%D \NC \s!pt \NC portuguese \NC italic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D
+%D \unprotect
+%D \placetable{The slavic languages (\type{lang-sla})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!pl \NC polish \NC slavic \NC\FR
+%D \NC \s!cs \NC czech \NC slavic \NC\MR
+%D \NC \s!sk \NC slavik \NC slavic \NC\LR
+%D \HL
+%D \stoptable
+%D \protect
+%D \unprotect
+%D
+%D \placetable{The altaic languages (\type{lang-alt})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!tr \NC turkish \NC altaic \NC\SR
+%D \HL
+%D \stoptable
+%D
+%D \placetable{The uralic languages (\type{lang-ura})}
+%D \starttable[||||]
+%D \HL
+%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
+%D \HL
+%D \NC \s!fi \NC finnish \NC uralic \NC\SR
+%D \HL
+%D \stoptable
+%D \protect
+
+\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.
+
+\setupcurrentlanguage[\s!en]
+
+\unexpanded\def\initializemainlanguage
+ {\mainlanguage[\currentlanguage]%
+ \showmessage\m!languages9\currentlanguage}
+
+%D New:
+
+\let\stopexceptions\relax
+
+\unexpanded\def\startexceptions
+ {\dosingleempty\lang_basics_start_exceptions}
+
+\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not?
+ {\begingroup
+ \edef\askedlanguage{\reallanguagetag{#1}}%
+ \ifx\askedlanguage\empty
+ \let\askedlanguage\currentlanguage
+ \fi
+ \clf_setlanguageexceptions{\askedlanguage}{#2}%
+ \endgroup}
+
+%D For the moment here:
+
+\uchyph 1 % also treat uppercase
+\exhyphenchar 45 % to permit breaking at explicit hyphens
+
+%D New:
+
+\unexpanded\def\traceddiscretionary#1#2#3%
+ {\dontleavehmode
+ \discretionary{\darkred#1}{\darkgreen#2}{\darkblue#3}}
+
+\unexpanded\def\samplediscretionary
+ {\traceddiscretionary
+ {pre\clf_currentprehyphenchar}%
+ {\clf_currentposthyphenchar post}%
+ {replace}}
+
+% todo: make this configurable
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-lab.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.lua
new file mode 100644
index 00000000000..f5ae6de5ead
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.lua
@@ -0,0 +1,171 @@
+if not modules then modules = { } end modules ['lang-lab'] = {
+ version = 1.001,
+ comment = "companion to lang-lab.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find = string.format, string.find
+local next, rawget, type = next, rawget, type
+local lpegmatch = lpeg.match
+local formatters = string.formatters
+
+local prtcatcodes = catcodes.numbers.prtcatcodes -- todo: use different method
+
+local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end)
+local report_labels = logs.reporter("languages","labels")
+
+languages.labels = languages.labels or { }
+local labels = languages.labels
+
+local context = context
+local implement = interfaces.implement
+
+local variables = interfaces.variables
+local settings_to_array = utilities.parsers.settings_to_array
+
+local splitter = lpeg.splitat(":")
+
+local function split(tag)
+ return lpegmatch(splitter,tag)
+end
+
+labels.split = split
+
+local contextsprint = context.sprint
+
+local f_setlabeltextpair = formatters["\\setlabeltextpair{%s}{%s}{%s}{%s}{%s}"]
+local f_key_key = formatters["\\v!%s:\\v!%s"]
+local f_key_raw = formatters["\\v!%s:%s"]
+local f_raw_key = formatters["%s:\\v!%s"]
+local f_raw_raw = formatters["%s:%s"]
+local f_key = formatters["\\v!%s"]
+local f_raw = formatters["%s"]
+
+local function definelanguagelabels(data,class,tag,rawtag)
+ for language, text in next, data.labels do
+ if text == "" then
+ -- skip
+ elseif type(text) == "table" then
+ contextsprint(prtcatcodes,f_setlabeltextpair(class,language,tag,text[1],text[2]))
+ if trace_labels then
+ report_labels("language %a, defining label %a as %a and %a",language,rawtag,text[1],text[2])
+ end
+ else
+ contextsprint(prtcatcodes,f_setlabeltextpair(class,language,tag,text,""))
+ if trace_labels then
+ report_labels("language %a, defining label %a as %a",language,rawtag,text)
+ end
+ end
+ end
+end
+
+function labels.define(class,name,prefixed)
+ local list = languages.data.labels[name]
+ if list then
+ report_labels("defining label set %a",name)
+ for tag, data in next, list do
+ tag = variables[tag] or tag
+ if data.hidden then
+ -- skip
+ elseif prefixed then
+ local first, second = lpegmatch(splitter,tag)
+ if second then
+ if rawget(variables,first) then
+ if rawget(variables,second) then
+ definelanguagelabels(data,class,f_key_key(first,second),tag)
+ else
+ definelanguagelabels(data,class,f_key_raw(first,second),tag)
+ end
+ elseif rawget(variables,second) then
+ definelanguagelabels(data,class,f_raw_key(first,second),tag)
+ else
+ definelanguagelabels(data,class,f_raw_raw(first,second),tag)
+ end
+ elseif rawget(variables,rawtag) then
+ definelanguagelabels(data,class,f_key(tag),tag)
+ else
+ definelanguagelabels(data,class,tag,tag)
+ end
+ else
+ definelanguagelabels(data,class,tag,tag)
+ end
+ end
+ else
+ report_labels("unknown label set %a",name)
+ end
+end
+
+-- function labels.check()
+-- for category, list in next, languages.data.labels do
+-- for tag, specification in next, list do
+-- for language, text in next, specification.labels do
+-- if type(text) == "string" and find(text,",") then
+-- report_labels("warning: label with comma found, category %a, language %a, tag %a, text %a",
+-- category, language, tag, text)
+-- end
+-- end
+-- end
+-- end
+-- end
+--
+-- labels.check()
+
+-- interface
+
+interfaces.implement {
+ name = "definelabels",
+ actions = labels.define,
+ arguments = { "string", "string", "boolean" }
+}
+
+-- function commands.setstrippedtextprefix(str)
+-- context(string.strip(str))
+-- end
+
+-- list : { "a", "b", "c" }
+-- separator : ", "
+-- last : " and "
+
+-- text : "a,b,c"
+-- separators : "{, },{ and }"
+
+local function concatcommalist(settings) -- it's too easy to forget that this one is there
+ local list = settings.list or settings_to_array(settings.text or "")
+ local size = #list
+ local command = settings.command and context[settings.command] or context
+ if size > 1 then
+ local separator, last = " ", " "
+ if settings.separators then
+ local set = settings_to_array(settings.separators)
+ separator = set[1] or settings.separator or separator
+ last = set[2] or settings.last or last
+ else
+ separator = settings.separator or separator
+ last = settings.last or last
+ end
+ command(list[1])
+ for i=2,size-1 do
+ context(separator)
+ command(list[i])
+ end
+ context(last)
+ end
+ if size > 0 then
+ command(list[size])
+ end
+end
+
+implement {
+ name = "concatcommalist",
+ actions = concatcommalist,
+ arguments = {
+ {
+ { "text" },
+ { "separators" },
+ { "separator" },
+ { "last" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv
new file mode 100644
index 00000000000..26c10086f22
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv
@@ -0,0 +1,385 @@
+%D \module
+%D [ file=lang-lab,
+%D version=1997.08.27,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Labels,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Language Macros / Labels}
+
+\registerctxluafile{lang-lab}{1.001}
+\registerctxluafile{lang-txt}{1.001}
+
+\unprotect
+
+%D Left-overs:
+
+\ifdefined\sixperemspace \else
+ \def\sixperemspace{\normalUchar"2006}
+\fi
+
+%D In this module we deal with language dependant labels and
+%D prefixes, like in {\em Figure~12} and {\em Chapter 1}. In
+%D this file we set the default values. Users can easily
+%D overrule these.
+%D
+%D This module is dedicated to the grandfather of Tobias
+%D Burnus, who's extensive languages oriented library helped us
+%D a lot in finding the right translations. All those labels
+%D are collected in files that reflect their common ancestor.
+%D
+%D Not all languages can be satisfied with the labeling
+%D mechanism as provided here. Chinese for instance put a label
+%D in front as well as after a part number. This is why the
+%D current implementation of labels supports two labels too.
+
+%D \macros
+%D {setupheadtext, setuplabeltext}
+%D
+%D First we present some macros that deal with what we will
+%D call head and label texts. Such texts are defines by:
+%D
+%D \showsetup{setupheadtext}
+%D \showsetup{setuplabeltext}
+%D
+%D A regular \CONTEXT\ stores some 1500 labels at most.
+%D
+%D These commands accept all kind of inputs:
+%D
+%D \starttyping
+%D \setuplabeltext [language] [labellabel=text]
+%D \setuplabeltext [language] [labellabel=text,labellabel=text,...]
+%D \setuplabeltext [labellabel=text]
+%D \setuplabeltext [labellabel=text,labellabel=text,...]
+%D \stoptyping
+%D
+%D The last two cases concern the current language.
+
+\installcorenamespace{label}
+
+\let\currentlabelcategory\empty
+
+\unexpanded\def\definelabelclass
+ {\dodoubleempty\lang_labels_define_class}
+
+\def\lang_labels_define_class[#1][#2]%
+ {\normalexpanded
+ {\lang_labels_define_class_indeed
+ {#1}%
+ {\ifsecondargument#2\else\zerocount\fi}%
+ \expandafter\noexpand\csname dogetupsome#1text\endcsname
+ \expandafter\noexpand\csname #1language\endcsname
+ \expandafter\noexpand\csname dodogetupsome#1text\endcsname
+ \expandafter\noexpand\csname left#1text\endcsname
+ \expandafter\noexpand\csname right#1text\endcsname
+ \expandafter\noexpand\csname #1texts\endcsname
+ \expandafter\noexpand\csname #1text\endcsname}}
+
+\unexpanded\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9%
+ {\setuvalue{setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
+ \setuvalue{preset#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
+ \setuvalue{copy#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_copy}%
+ \setuvalue{start#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dotripleempty\lang_labels_text_prefix_start[#1]}%
+ \letvalue{stop#1text}\relax
+ \def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}%
+ \ifnum#2=\plustwo % used for math and tags
+ \def#3{#5#4}%
+ \def#5##1##2% ##1=language
+ {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??label#1:##1:##2\endcsname
+ \lastnamedcs
+ % \else\ifcsname\??language#4\s!default\endcsname
+ % \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \else\ifcsname\??language##1\s!default\endcsname
+ %\expandafter#5\csname\??language##1\s!default\endcsname{##2}%
+ \expandafter#5\lastnamedcs{##2}%
+ \else\ifcsname\??label\currentlabelcategory#1:##2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??label#1:##2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??label#1:\s!en:##2\endcsname
+ \lastnamedcs
+ \else
+ ##2%
+ \fi\fi\fi\fi\fi\fi\fi}%
+ \let#6\gobbleoneargument
+ \let#7\gobbleoneargument
+ \let#8\gobbletwoarguments
+ \let#9#3%
+ \else
+ \unexpanded\def#3{#5#4}%
+ \unexpanded\def#5##1##2%
+ {\ifcsname\??label#1:##1:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \else\ifcsname\??language#4\s!default\endcsname
+ %\expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \expandafter#5\lastnamedcs{##2}%
+ \else\ifcsname\??label#1:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \else\ifcsname\??label#1:\s!en:##2\endcsname
+ %\expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \else
+ \let\thetextprefix\dummytextprefix
+ \fi\fi\fi\fi}%
+ \unexpanded\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \unexpanded\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}%
+ \unexpanded\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2
+ \unexpanded\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \fi
+ \appendtoks
+ \let#6\firstofoneargument % to be checked
+ \let#7\firstofoneargument % to be checked
+ \let#8\firstofoneargument % to be checked
+ \let#9\firstofoneargument % to be checked
+ \to \everysimplifycommands}
+
+\let\flushleftlabelclass \firstoftwoarguments
+\let\flushrightlabelclass\secondoftwoarguments
+\def\flushbothlabelclass #1#2#3{#1#3#2}
+\def\dummytextprefix {\empty\empty}
+
+%D \macros
+%D {headtext, labeltext, leftlabeltext, rightlabeltext, labeltexts}
+%D
+%D Once defined, head and label texts can be called upon using:
+%D
+%D \showsetup{headtext}
+%D \showsetup{labeltext}
+%D
+%D \macros
+%D {presetheadtext,presetlabeltext}
+%D
+%D These macros enable us to automatically define head and label
+%D texts without replacing predefined ones. They are internal macros.
+
+\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
+
+\newconstant\protecttextprefixes
+
+\let\currenttextprefixtag \s!unknown
+\let\currenttextprefixclass\s!unknown
+
+\def\lang_labels_text_prefix_start[#1][#2][#3]% class language name
+ {\ifthirdargument
+ \edef\currenttextprefixtag{\reallanguagetag{#2}}%
+ \edef\currenttextprefixname{#3}%
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \edef\currenttextprefixname{#2}%
+ \fi
+ \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed}
+
+\def\lang_labels_text_prefix_start_indeed#1% text (not special checking done here yet, only for long texts anyway)
+ {\expandafter\edef\csname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname%
+ {{\clf_strip{#1}}\empty}}
+
+\def\lang_labels_text_prefix_setup[#1][#2]%
+ {\ifsecondargument
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_setup_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \processcommalist[#1]\lang_labels_text_prefix_setup_indeed
+ \fi}
+
+\def\lang_labels_text_prefix_setup_indeed#1%
+ {\lang_labels_text_prefix_assign[#1]}
+
+\def\lang_labels_text_prefix_assign[#1=#2]%
+ {\lang_labels_text_prefix_assign_indeed{#1}[#2,,]}
+
+\def\lang_labels_text_prefix_assign_indeed#1%
+ {\ifcase\protecttextprefixes
+ % no checking
+ \expandafter\lang_labels_text_prefix_assign_yes
+ \or
+ % checking
+ \ifcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_nop
+ \else
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_yes
+ \fi
+ \or
+ % simple assignment (a bit overkill but it fits in the whole)
+ \expandafter\lang_labels_text_prefix_assign_dumb
+ \fi{#1}}
+
+\let\m_lang_labels_left \empty
+\let\m_lang_labels_right\empty
+
+% \def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+% {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+% \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+% \ifx\m_lang_labels_right\empty
+% \ifx\m_lang_labels_left\empty
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
+% \else
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
+% \fi
+% \else
+% \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
+% \fi}
+%
+% how we love obscure efficicency ...
+
+\def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+ {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+ \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+ \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1%
+ \ifx\m_lang_labels_right\empty
+ \ifx\m_lang_labels_left\empty
+ \endcsname{\empty\empty}%
+ \else
+ \endcsname{{#2}\empty}%
+ \fi
+ \else
+ \endcsname{{#2}{#3}}%
+ \fi}
+
+\def\lang_labels_text_prefix_assign_nop#1[#2]%
+ {}
+
+\def\lang_labels_text_prefix_assign_dumb#1[#2,#3]%
+ {\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
+
+\unexpanded\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end
+ {%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}%
+ \expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right
+
+\def\lang_labels_text_prefix_copy[#1][#2]%
+ {\ifsecondargument
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_copy_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \processcommalist[#1]\lang_labels_text_prefix_copy_indeed
+ \fi}
+
+\def\lang_labels_text_prefix_copy_indeed#1%
+ {\lang_labels_text_prefix_copy_pair[#1]}
+
+\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}
+
+\definelabelclass [head] [0] % titles
+\definelabelclass [label] [0] % texts
+\definelabelclass [mathlabel] [0] % functions
+\definelabelclass [taglabel] [2] % tags
+
+\clf_definelabels{head}{titles}\s!true\relax
+\clf_definelabels{label}{texts}\s!true\relax
+\clf_definelabels{mathlabel}{functions}\s!false\relax
+\clf_definelabels{taglabel}{tags}\s!false\relax
+
+%D \macros
+%D {translate}
+%D
+%D Sometimes macros contain language specific words that are to
+%D be typeset. Such macros can be made (more) language
+%D independant by using:
+%D
+%D \showsetup{translate}
+%D
+%D like for instance:
+%D
+%D \starttyping
+%D \translate[en=something,nl=iets]
+%D \stoptyping
+%D
+%D which expands to {\em something} or {\em iets}, depending on
+%D de current language.
+
+\installcorenamespace{translation}
+
+\unexpanded\def\translate
+ {\dosingleempty\lang_translate}
+
+\def\lang_translate[#1]%
+ {\getparameters[\??translation][#1]%
+ \ifcsname\??translation\currentlanguage\endcsname
+ \lastnamedcs
+ \else\ifcsname\??translation\s!en\endcsname
+ \lastnamedcs
+ \else
+ [translation #1]%
+ \fi\fi}
+
+%D When used without argument, the last defined values are
+%D used. This enables repetitive use like
+%D
+%D \starttyping
+%D \en \translate\ means \nl \translate
+%D \stoptyping
+
+%D \macros
+%D {assigntranslation}
+%D
+%D This macro is a system macro, and can be used to assign a
+%D translation to a macro. Its form is:
+%D
+%D \starttyping
+%D \assigntranslation[en=something,nl=iets]\to\command
+%D \stoptyping
+
+\unexpanded\def\assigntranslation[#1]\to#2% bad, this \to
+ {\getparameters[\??translation][#1]%
+ \edef#2{\csname\??translation\currentlanguage\endcsname}}
+
+%D \macros
+%D {commalistsentence}
+%D
+%D Redone in \LUA:
+%D
+%D \startbuffer
+%D \commalistsentence[aap,noot,mies]
+%D \commalistsentence[aap,noot]
+%D \commalistsentence[aap]
+%D \commalistsentence[a,b,c]
+%D \commalistsentence[a,b,c][{ \& },{ and }]
+%D \commalistsentence[a,b,c][+,-]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\unexpanded\def\commalistsentence
+ {\dodoubleempty\typo_helpers_concat_comma_list}
+
+\def\typo_helpers_concat_comma_list[#1][#2]%
+ {\clf_concatcommalist
+ text {#1}%
+ separators {#2}%
+ separator {\detokenize\expandafter{\normalexpanded{\labeltext{and-1}}}}%
+ last {\detokenize\expandafter{\normalexpanded{\labeltext{and-2}}}}%
+ \relax}
+
+\setuplabeltext [\s!nl] [and-1={{, }}, and-2={{ en }}] % 1, 2 en 3
+\setuplabeltext [\s!en] [and-1={{, }}, and-2={{, }}] % 1, 2, 3
+\setuplabeltext [\s!de] [and-1={{, }}, and-2={{ und }}] % 1, 2 und 3
+\setuplabeltext [\s!hr] [and-1={{, }}, and-2={{ i }}] % 1, 2 i 3
+
+%D Goodie (handy at \LUA\ end):
+
+\unexpanded\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases!
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv
new file mode 100644
index 00000000000..ada8f81ea6c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv
@@ -0,0 +1,697 @@
+%D \module
+%D [ file=lang-mis,
+%D version=1997.03.20, % used to be supp-lan.tex
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Compounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Language Macros / Compounds}
+
+%D More or less replaced.
+
+%D \gdef\starttest#1\stoptest{\starttabulate[|l|l|p|]#1\stoptabulate}
+%D \gdef\test #1{\NC\detokenize{#1}\NC\hyphenatedword{#1}\NC#1\NC\NR}
+
+\unprotect
+
+%D One of \TEX's strong points in building paragraphs is the way hyphenations are
+%D handled. Although for real good hyphenation of non||english languages some
+%D extensions to the program are needed, fairly good results can be reached with the
+%D standard mechanisms and an additional macro, at least in Dutch.
+%D
+%D \CONTEXT\ originates in the wish to typeset educational materials, especially in
+%D a technical environment. In production oriented environments, a lot of compound
+%D words are used. Because the Dutch language poses no limits on combining words, we
+%D often favor putting dashes between those words, because it facilitates reading,
+%D at least for those who are not that accustomed to it.
+%D
+%D In \TEX\ compound words, separated by a hyphen, are not hyphenated at all. In
+%D spite of the multiple pass paragraph typesetting this can lead to parts of words
+%D sticking into the margin. The solution lays in saying \type
+%D {spoelwater||terugwinunit} instead of \type {spoelwater-terugwinunit}. By using a
+%D one character command like \type {|}, delimited by the same character \type {|},
+%D we get ourselves both a decent visualization (in \TEXEDIT\ and colored verbatim
+%D we color these commands yellow) and an efficient way of combining words.
+%D
+%D The sequence \type{||} simply leads to two words connected by a hyphen. Because
+%D we want to distinguish such a hyphen from the one inserted when \TEX\ hyphenates
+%D a word, we use a bit longer one.
+%D
+%D \hyphenation {spoel-wa-ter te-rug-win-unit}
+%D
+%D \starttest
+%D \test {spoelwater||terugwinunit}
+%D \stoptest
+%D
+%D As we already said, the \type{|} is a command. This commands accepts an optional
+%D argument before it's delimiter, which is also a \type{|}.
+%D
+%D \hyphenation {po-ly-meer che-mie}
+%D
+%D \starttest
+%D \test {polymeer|*|chemie}
+%D \stoptest
+%D
+%D Arguments like \type{*} are not interpreted and inserted directly, in contrary to
+%D arguments like:
+%D
+%D \starttest
+%D \test {polymeer|~|chemie}
+%D \test {|(|polymeer|)|chemie}
+%D \test {polymeer|(|chemie|)| }
+%D \stoptest
+%D
+%D Although such situations seldom occur |<|we typeset thousands of pages before we
+%D encountered one that forced us to enhance this mechanism|>| we also have to take
+%D care of comma's.
+%D
+%D \hyphenation {uit-stel-len}
+%D
+%D \starttest
+%D \test {op||, in|| en uitstellen}
+%D \stoptest
+%D
+%D The next special case (concerning quotes) was brought to my attention by Piet
+%D Tutelaers, one of the driving forces behind rebuilding hyphenation patterns for
+%D the dutch language.\footnote{In 1996 the spelling of the dutch language has been
+%D slightly reformed which made this topic actual again.} We'll also take care of
+%D this case.
+%D
+%D \starttest
+%D \test {AOW|'|er}
+%D \test {cd|'|tje}
+%D \test {ex|-|PTT|'|er}
+%D \test {rock|-|'n|-|roller}
+%D \stoptest
+%D
+%D Tobias Burnus pointed out that I should also support something like
+%D
+%D \starttest
+%D \test {well|_|known}
+%D \stoptest
+%D
+%D to stress the compoundness of hyphenated words.
+%D
+%D Of course we also have to take care of the special case:
+%D
+%D \starttest
+%D \test {text||color and ||font}
+%D \stoptest
+
+%D \macros
+%D {installdiscretionaries}
+%D
+%D The mechanism described here is one of the older inner parts of \CONTEXT. The
+%D most recent extensions concerns some special cases as well as the possibility to
+%D install other characters as delimiters. The prefered way of specifying compound
+%D words is using \type{||}, which is installed by:
+%D
+%D \starttyping
+%D \installdiscretionary | -
+%D \stoptyping
+%D
+%D Some alternative definitions are:
+%D
+%D \startbuffer
+%D \installdiscretionary * -
+%D \installdiscretionary + -
+%D \installdiscretionary / -
+%D \installdiscretionary ~ -
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D after which we can say:
+%D
+%D \start \getbuffer
+%D \starttest
+%D \test {test**test**test}
+%D \test {test++test++test}
+%D \test {test//test//test}
+%D \test {test~~test~~test}
+%D \stoptest
+%D \stop
+
+%D \macros
+%D {compoundhyphen,
+%D beginofsubsentence,endofsubsentence}
+%D
+%D Now let's go to the macros. First we define some variables. In the main \CONTEXT\
+%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
+\ifx\beginofsubsentence\undefined \unexpanded\def\beginofsubsentence{\hbox{\emdash}} \fi
+\ifx\endofsubsentence \undefined \unexpanded\def\endofsubsentence {\hbox{\emdash}} \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
+%D compound characters like |-| or || to be separated from the words. \TEX\ hackers
+%D will recognise the next two macro's:
+
+\ifx\prewordbreak \undefined \unexpanded\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
+\ifx\postwordbreak\undefined \unexpanded\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi
+\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % language specific
+
+\unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces
+
+%D \macros
+%D {beginofsubsentencespacing,endofsubsentencespacing}
+%D
+%D In the previous macros we provided two hooks which can be used to support nested
+%D sub||sentences. In \CONTEXT\ these hooks are used to insert a small space when
+%D needed.
+
+\ifx\beginofsubsentencespacing\undefined \let\beginofsubsentencespacing\relax \fi
+\ifx\endofsubsentencespacing \undefined \let\endofsubsentencespacing \relax \fi
+
+%D The following piece of code is a torture test compound handling. The \type
+%D {\relax} before the \type {\ifmmode} is needed because of the alignment scanner
+%D (in \ETEX\ this problem is not present because there a protected macro is not
+%D expanded. Thanks to Tobias Burnus for providing this example.
+%D
+%D \startformula
+%D \left|f(x_n)-{1\over2}\right| =
+%D {\cases{|{1\over2}-x_n| &for $0\le x_n < {1\over2}$\cr
+%D |x_n-{1\over2}| &for ${1\over2}<x_n\le1$ \cr}}
+%D \stopformula
+
+\installcorenamespace{discretionaryaction}
+\installcorenamespace{discretionarytext}
+\installcorenamespace{discretionarymath}
+\installcorenamespace{discretionaryboth}
+\installcorenamespace{discretionarymode}
+
+\unexpanded\def\installdiscretionary#1#2%
+ {\setevalue{\??discretionarymath\detokenize{#1}}{\detokenize{#1}}% ?
+ \setvalue {\??discretionarytext\detokenize{#1}}{#2}%
+ \setvalue {\??discretionaryboth\detokenize{#1}}{\lang_discretionaries_command#1}%
+ \scratchcounter\expandafter`\detokenize{#1}%
+ \expandafter\uedcatcodecommand\expandafter\ctxcatcodes\expandafter\scratchcounter\csname\??discretionaryboth\detokenize{#1}\endcsname}
+
+\unexpanded\def\handlemathmodediscretionary#1{\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs}
+\unexpanded\def\handletextmodediscretionary#1{\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs}
+
+\unexpanded\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete
+
+\setnewconstant\discretionarymode\plusone
+
+\unexpanded\def\ignorediscretionaries
+ {\discretionarymode\zerocount}
+
+\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
+ \else\ifmmode
+ m% \csstring\lang_discretionaries_process_math
+ \else
+ t% \csstring\lang_discretionaries_process_text
+ \fi\fi
+ \endcsname}
+
+% \def\lang_discretionaries_process_none#1%
+\setvalue{\??discretionarymode n}#1%
+ {\detokenize{#1}}
+
+%D The macro \type{\lang_discretionaries_check_before} takes care of loners like
+%D \type{||word}, while it counterpart \type {\lang_discretionaries_check_after} is
+%D responsible for handling the comma.
+
+\newsignal\compoundbreakpoint
+
+\newconditional\punctafterdiscretionary
+\newconditional\spaceafterdiscretionary
+
+\def\lang_discretionaries_check_before
+ {\ifvmode
+ \dontleavehmode
+ \fi
+ \ifhmode
+ \begingroup
+ \setbox\scratchbox\lastbox
+ \ifzeropt\wd\scratchbox
+ \let\postwordbreak\prewordbreak
+ \fi
+ \box\scratchbox\relax
+ \endgroup
+ \fi}
+
+\def\lang_discretionaries_check_after
+ {\setfalse\punctafterdiscretionary
+ \setfalse\spaceafterdiscretionary
+ \ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \else
+ \ifx\space \nextnext \settrue \spaceafterdiscretionary \else
+ \ifx .\nextnext \settrue \punctafterdiscretionary \else
+ \ifx ,\nextnext \settrue \punctafterdiscretionary \else
+ \ifx :\nextnext \settrue \punctafterdiscretionary \else
+ \ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
+
+%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
+ \def\next##1#1%
+ {\def\next{\activedododotextmodediscretionary#1{##1}}%
+ \futurelet\nextnext\next}%
+ \next}
+
+\unexpanded\def\activedododotextmodediscretionary#1#2%
+ {\edef\discretionarytoken{\detokenize{#2}}%
+ \def\textmodediscretionary{\handletextmodediscretionary{#1}}%
+ \lang_discretionaries_check_after
+ \ifx\discretionarytoken\empty
+ \ifx#1\nextnext % takes care of ||| and +++ and ......
+ \ifcsname\??discretionaryaction\string#1\endcsname
+ \lastnamedcs
+ \else\ifconditional\spaceafterdiscretionary
+ \prewordbreak\hbox{\string#1}\relax
+ \else\ifconditional\punctafterdiscretionary
+ \prewordbreak\hbox{\string#1}\relax
+ \else
+ \prewordbreak\hbox{\string#1}\prewordbreak
+ \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
+ % but an hbox blocks a possible \discretionary
+ \ifcsname\??discretionaryaction\endcsname
+ \lastnamedcs
+ \else\ifconditional\spaceafterdiscretionary
+ \prewordbreak\textmodediscretionary\relax
+ \else\ifconditional\punctafterdiscretionary
+ \prewordbreak\textmodediscretionary\relax
+ \else
+ \prewordbreak\textmodediscretionary\prewordbreak
+ \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
+ \else\ifconditional\punctafterdiscretionary
+ \prewordbreak\hbox{#2}\relax
+ \else
+ \prewordbreak\discretionary{\hbox{#2}}{}{\hbox{#2}}\allowbreak\postwordbreak
+ \fi\fi
+ \fi\fi
+ \nextnextnext} % lookahead in commands
+
+%D \macros
+%D {directdiscretionary}
+%D
+%D In those situations where the nature of characters is less predictable, we can
+%D use the more direct approach:
+
+\unexpanded\def\directdiscretionary
+ {\csname\??discretionarymode
+ \ifcase\discretionarymode
+ n% \csstring\lang_discretionaries_process_none
+ \else
+ d% \csstring\lang_discretionaries_process_direct
+ \fi
+ \endcsname}
+
+\unexpanded\def\indirectdiscretionary
+ {\csname\??discretionarymode
+ \ifcase\discretionarymode
+ n% \csstring\lang_discretionaries_process_none
+ \else
+ i% \csstring\lang_discretionaries_process_indirect
+ \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}
+
+\unexpanded\def\definetextmodediscretionary #1
+ {\setvalue{\??discretionaryaction\detokenize{#1}}}
+
+% \start \hsize 1mm
+% test |||test test|||, test\blank
+% test test|-|, test|-| and test|-|test\blank
+% test test|_|, test|_| and test|_|test\blank
+% test cd|'|tje\blank
+% test |(|test test|)|, test\blank
+% test test test|x|, test\blank
+% test|~|test
+% test|^|test
+% \stop
+
+% x\discretionary{1}{2}{3}xxxxxxx
+% xxxxxxx\discretionary{1}{2}{3}x
+%
+% xxx3xxx
+% xxx1<newline>2xxx
+
+\def\lang_discretionaries_hyphen_like#1#2%
+ {\ifconditional\spaceafterdiscretionary
+ \prewordbreak\hbox{#1}\relax
+ \else\ifconditional\punctafterdiscretionary
+ \prewordbreak\hbox{#1}\relax
+ \else
+ \prewordbreak#2\postwordbreak % was prewordbreak
+ \fi\fi}
+
+\definetextmodediscretionary {}
+ {\lang_discretionaries_hyphen_like\textmodehyphen\textmodehyphendiscretionary}
+
+\definetextmodediscretionary -
+ {\lang_discretionaries_hyphen_like\normalhyphen\normalhyphendiscretionary}
+
+\definetextmodediscretionary _
+ {\lang_discretionaries_hyphen_like\composedhyphen\composedhyphendiscretionary}
+
+\definetextmodediscretionary )
+ {\lang_discretionaries_hyphen_like{)}{\discretionary{-)}{}{)}}}
+
+\definetextmodediscretionary (
+ {\ifdim\lastskip>\zeropoint
+ (\prewordbreak
+ \else
+ \prewordbreak\discretionary{}{(-}{(}\prewordbreak
+ \fi}
+
+\definetextmodediscretionary ~
+ {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak}
+
+\definetextmodediscretionary '
+ {\prewordbreak\discretionary{-}{}{'}\postwordbreak}
+
+\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\compoundhyphen}
+
+% 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 *
+ {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak}
+
+% spanish
+
+\definetextmodediscretionary ?? {\prewordbreak\questiondown}
+\definetextmodediscretionary !! {\prewordbreak\exclamdown}
+
+% \ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+%D \installdiscretionary | +
+%D \installdiscretionary + =
+
+\def\defaultdiscretionaryhyphen{\compoundhyphen}
+
+\installdiscretionary | \defaultdiscretionaryhyphen % installs in ctx and prt will fall back on it
+
+%D \macros
+%D {fakecompoundhyphen}
+%D
+%D In headers and footers as well as in active pieces of text we need a dirty hack.
+%D Try to imagine what is needed to savely break the next text across a line and at
+%D the same time make the words interactive.
+%D
+%D \starttyping
+%D \goto{Some||Long||Word}
+%D \stoptyping
+
+\unexpanded\def\fakecompoundhyphen
+ {\def\|{\mathortext\vert\lang_compounds_fake_hyphen}}
+
+\def\lang_compounds_fake_hyphen
+ {\def##1|%
+ {\doifelsenothing{##1}\compoundhyphen{##1}%
+ \kern\compoundbreakpoint\allowbreak}}
+
+%D \macros
+%D {midworddiscretionary}
+%D
+%D If needed, one can add a discretionary hyphen using \type
+%D {\midworddiscretionary}. This macro does the same as \PLAIN\ \TEX's \type {\-},
+%D but, like the ones implemented earlier, this one also looks ahead for spaces and
+%D grouping tokens.
+
+\unexpanded\def\midworddiscretionary
+ {\futurelet\nexttoken\lang_discretionaries_mid_word}
+
+\def\lang_discretionaries_mid_word
+ {\ifx\nexttoken\blankspace\else
+ \ifx\nexttoken\bgroup \else
+ \ifx\nexttoken\egroup \else
+ \discretionary{-}{}{}%
+ \fi\fi\fi}
+
+% As this is rather mkii-ish we keep the mkiv definition around for educational
+% purposes but consider this feature obsolete in post mkii versions.
+
+% %D \macros
+% %D {installcompoundcharacter}
+% %D
+% %D When Tobias Burnus started translating the dutch manual of \PPCHTEX\ into german,
+% %D he suggested to let \CONTEXT\ support the \type{german.sty} method of handling
+% %D compound characters, especially the umlaut. This package is meant for use with
+% %D \PLAIN\ \TEX\ as well as \LATEX.
+% %D
+% %D I decided to implement compound character support as versatile as possible. As a
+% %D result one can define his own compound character support, like:
+% %D
+% %D \starttyping
+% %D \installcompoundcharacter "a {\"a}
+% %D \installcompoundcharacter "e {\"e}
+% %D \installcompoundcharacter "i {\"i}
+% %D \installcompoundcharacter "u {\"u}
+% %D \installcompoundcharacter "o {\"o}
+% %D \installcompoundcharacter "s {\SS}
+% %D \stoptyping
+% %D
+% %D or even
+% %D
+% %D \starttyping
+% %D \installcompoundcharacter "ck {\discretionary {k-}{k}{ck}}
+% %D \installcompoundcharacter "ff {\discretionary{ff-}{f}{ff}}
+% %D \stoptyping
+% %D
+% %D The support is not limited to alphabetic characters, so the next definition is
+% %D also valid.
+% %D
+% %D \starttyping
+% %D \installcompoundcharacter ". {.\doifnextcharelse{\spacetoken}{}{\kern.125em}}
+% %D \stoptyping
+% %D
+% %D The implementation looks familiar and uses the same tricks as mentioned earlier
+% %D in this module. We take care of two arguments, which complicates things a bit.
+%
+% \installcorenamespace{compoundnormal}
+% \installcorenamespace{compoundsingle}
+% \installcorenamespace{compoundmultiple}
+% \installcorenamespace{compounddefinition}
+%
+% %D When I started working on \MKIV\ code, we needed a different approach for
+% %D defining the active character itself. In \MKII\ as well as in \MKIV\ we now use
+% %D the catcode vectors.
+%
+% \setnewconstant\compoundcharactermode\plusone
+%
+% \newcount\c_lang_compounds_character
+%
+% \def\installcompoundcharacter #1#2#3 #4% {#4} no grouping
+% {\ifcase\compoundcharactermode
+% % ignore mode
+% \else
+% \chardef\c_lang_compounds_character`#1%
+% \expandafter\chardef\csname\??compoundnormal\string#1\endcsname\c_lang_compounds_character
+% \def\!!stringa{#3}%
+% \expandafter\def\csname\ifx\!!stringa\empty\??compoundsingle\else\??compoundmultiple\fi\detokenize{#1#2#3}\endcsname{#4}%
+% \setevalue{\??compounddefinition\detokenize{#1}}{\noexpand\lang_compounds_handle_character{\detokenize{#1}}}% beter nr's
+% \expandafter\letcatcodecommand\expandafter\ctxcatcodes\expandafter\c_lang_compounds_character\csname\??compounddefinition\detokenize{#1}\endcsname
+% \fi}
+%
+% %D We can also ignore definitions (needed in for instance \XML). Beware, this macro
+% %D is supposed to be used grouped!
+%
+% \def\ignorecompoundcharacter
+% {\compoundcharactermode\zerocount}
+
+\let\ignorecompoundcharacter\relax
+
+% %D In handling the compound characters we have to take care of \type {\bgroup} and
+% %D \type {\egroup} tokens, so we end up with a multi||step interpretation macro. We
+% %D look ahead for a \type {\bgroup}, \type {\egroup} or \type {\blankspace}. Being
+% %D no user of this mechanism, the credits for testing them goes to Tobias Burnus,
+% %D the first german user of \CONTEXT.
+% %D
+% %D We need to look into the future with \type{\futurelet} to prevent spaces from
+% %D disappearing.
+%
+% \def\lang_compounds_handle_character#1%
+% {\def\lang_compounds_handle_character_finish{\lang_compounds_handle_character_finish_indeed{#1}}%
+% \futurelet\nexttoken\xhandlecompoundcharacter}
+%
+% \def\lang_compounds_handle_character_finish_indeed
+% {\ifx\nexttoken\bgroup
+% %\expandafter\lang_compounds_handle_character_pickup % handle "{ee} -> \"ee
+% %\expandafter\gobbleoneargument % forget "{ee} -> ee
+% \expandafter\lang_compounds_handle_character_one % ignore "{ee} -> "ee
+% \else\ifx\nexttoken\egroup
+% \doubleexpandafter\lang_compounds_handle_character_normal
+% \else\ifx\nexttoken\blankspace
+% \tripleexpandafter\lang_compounds_handle_character_normal
+% \else
+% \tripleexpandafter\lang_compounds_handle_character_pickup
+% \fi\fi\fi}
+%
+% \def\lang_compounds_handle_character_normal#1%
+% {\csname\??compoundnormal\string#1\endcsname}
+%
+% \def\lang_compounds_handle_character_pickup#1#2% preserve space
+% {\def\lang_compounds_handle_character_finish{\lang_compounds_handle_character_finish_indeed#1#2}%
+% \futurelet\nexttoken\lang_compounds_handle_character_finish}
+%
+% \def\lang_compounds_handle_character_finish_indeed
+% {\ifx\nexttoken\bgroup
+% \expandafter\lang_compounds_handle_character_one
+% \else\ifx\nexttoken\egroup
+% \doubleexpandafter\lang_compounds_handle_character_one
+% \else\ifx\nexttoken\blankspace
+% \tripleexpandafter\lang_compounds_handle_character_one
+% \else
+% \tripleexpandafter\lang_compounds_handle_character_two
+% \fi\fi\fi}
+%
+% %D Besides taken care of the grouping and space tokens, we have to deal with three
+% %D situations. First we look if the next character equals the first one, if so, then
+% %D we just insert the original. Next we look if indeed a compound character is
+% %D defined. We either execute the compound character or just insert the first. So we
+% %D have
+% %D
+% %D \starttyping
+% %D <key><key> <key><known> <key><unknown>
+% %D \stoptyping
+% %D
+% %D In later modules we will see how these commands are used.
+%
+% \def\lang_compounds_handle_character_one#1#2%
+% {\if\string#1\string#2% was: \ifx#1#2%
+% %\expandafter\let\expandafter\next\csname\??compoundnormal\string#1\endcsname
+% \csname\??compoundnormal\string#1\expandafter\endcsname
+% \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+% %\expandafter\let\expandafter\next\lastnamedcs
+% \expandafter\lastnamedcs
+% \else
+% %\expandafter\let\expandafter\next\lastnamedcs
+% \expandafter\lastnamedcs
+% \fi\fi}
+%
+% \def\lang_compounds_handle_character_two#1#2#3%
+% {\if\string#1\string#2%
+% \def\next{\csname\??compoundnormal\string#1\endcsname#3}%
+% \else\ifcsname\??compoundmultiple\string#1\string#2\string#3\endcsname
+% \expandafter\let\expandafter\next\lastnamedcs
+% \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+% \expandafter\let\expandafter\next\lastnamedcs
+% \else
+% \expandafter\let\expandafter\next\lastnamedcs
+% \fi\fi\fi
+% \next}
+%
+% %D For very obscure applications (see for an application \type {lang-sla.tex}) we
+% %D provide:
+%
+% % \def\simplifiedcompoundcharacter#1#2%
+% % {\ifcsname\??compoundsingle\string#1\string#2\endcsname
+% % \doubleexpandafter\firstofoneargument\csname\??compoundsingle\string#1\string#2\endcsname
+% % \else
+% % #2%
+% % \fi}
+%
+% \def\simplifiedcompoundcharacter#1#2%
+% {\ifcsname\??compoundsingle\string#1\string#2\endcsname
+% \doubleexpandafter\firstofoneargument\lastnamedcs
+% \else
+% #2%
+% \fi}
+
+%D \macros
+%D {disablediscretionaries,disablecompoundcharacter}
+%D
+%D Occasionally we need to disable this mechanism. For the moment we assume that
+%D \type {|} is used.
+
+\let\disablediscretionaries \ignorediscretionaries
+\let\disablecompoundcharacters\ignorecompoundcharacter
+
+%D \macros
+%D {normalcompound}
+%D
+%D Handy in for instance XML. (Kind of obsolete)
+
+\ifdefined\normalcompound \else \let\normalcompound=| \fi
+
+%D \macros
+%D {compound}
+%D
+%D We will overload the already active \type {|} so we have to save its meaning in
+%D order to be able to use this handy macro.
+%D
+%D \starttyping
+%D so test\compound{}test can be used instead of test||test
+%D \stoptyping
+
+\bgroup
+
+ \catcode\barasciicode\activecatcode
+
+ \unexpanded\gdef\compound#1{|#1|}
+
+ \doglobal \appendtoks
+ \def|#1|{\ifx#1\empty\empty-\else#1\fi}%
+ \to \everysimplifycommands
+
+\egroup
+
+%D Here we hook some code into the clean up mechanism needed for verbatim data.
+
+\appendtoks
+ %\disablecompoundcharacters
+ \disablediscretionaries
+\to \everycleanupfeatures
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua
new file mode 100644
index 00000000000..28f2e5d50cc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua
@@ -0,0 +1,336 @@
+if not modules then modules = { } end modules ['lang-rep'] = {
+ version = 1.001,
+ comment = "companion to lang-rep.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A BachoTeX 2013 experiment, probably not that useful. Eventually I used a simpler
+-- more generic example. I'm sure no one ever notices of even needs this code.
+--
+-- As a follow up on a question by Alan about special treatment of dropped caps I wonder
+-- if I can make this one more clever (probably in a few more dev steps). For instance
+-- injecting nodes or replacing nodes. It's a prelude to a kind of lpeg for nodes,
+-- although (given experiences so far) we don't really need that. After all, each problem
+-- is somewhat unique.
+
+local type, tonumber = type, tonumber
+local utfbyte, utfsplit = utf.byte, utf.split
+local P, C, U, Cc, Ct, Cs, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns.utf8character, lpeg.Cc, lpeg.Ct, lpeg.Cs, lpeg.match
+local find = string.find
+
+local zwnj = 0x200C
+local grouped = P("{") * ( Ct((U/utfbyte-P("}"))^1) + Cc(false) ) * P("}")-- grouped
+local splitter = Ct((
+ #P("{") * (
+ P("{}") / function() return zwnj end
+ + Ct(Cc("discretionary") * grouped * grouped * grouped)
+ + Ct(Cc("noligature") * grouped)
+ )
+ + U/utfbyte
+ )^1)
+
+local stripper = P("{") * Cs((1-P(-2))^0) * P("}") * P(-1)
+
+local trace_replacements = false trackers.register("languages.replacements", function(v) trace_replacements = v end)
+local trace_detail = false trackers.register("languages.replacements.detail", function(v) trace_detail = v end)
+
+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
+local getattr = nuts.getattr
+local getid = nuts.getid
+local getchar = nuts.getchar
+local isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setchar = nuts.setchar
+
+local insert_node_before = nuts.insert_before
+local remove_node = nuts.remove
+local copy_node = nuts.copy
+local flush_list = nuts.flush_list
+local insert_after = nuts.insert_after
+
+local nodepool = nuts.pool
+local new_glyph = nodepool.glyph
+local new_disc = nodepool.disc
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+local implement = interfaces.implement
+
+local replacements = languages.replacements or { }
+languages.replacements = replacements
+
+local a_replacements = attributes.private("replacements")
+local a_noligature = attributes.private("noligature")
+
+local lists = { }
+local last = 0
+local trees = { }
+
+table.setmetatableindex(lists,function(lists,name)
+ last = last + 1
+ local list = { }
+ local data = { name = name, list = list, attribute = last }
+ lists[last] = data
+ lists[name] = data
+ trees[last] = list
+ return data
+end)
+
+lists[v_reset].attribute = unsetvalue -- so we discard 0
+
+-- todo: glue kern attr
+
+local function add(root,word,replacement)
+ local replacement = lpegmatch(stripper,replacement) or replacement
+ local list = utfsplit(word,true)
+ local size = #list
+ for i=1,size do
+ local l = utfbyte(list[i])
+ if not root[l] then
+ root[l] = { }
+ end
+ if i == size then
+ -- local newlist = utfsplit(replacement,true)
+ -- for i=1,#newlist do
+ -- newlist[i] = utfbyte(newlist[i])
+ -- end
+ local special = find(replacement,"{",1,true)
+ local newlist = lpegmatch(splitter,replacement)
+ --
+ root[l].final = {
+ word = word,
+ replacement = replacement,
+ oldlength = size,
+ newcodes = newlist,
+ special = special,
+ }
+ end
+ root = root[l]
+ end
+end
+
+function replacements.add(category,word,replacement)
+ local root = lists[category].list
+ if type(word) == "table" then
+ for word, replacement in next, word do
+ add(root,word,replacement)
+ end
+ else
+ add(root,word,replacement or "")
+ end
+end
+
+local function hit(a,head)
+ local tree = trees[a]
+ if tree then
+ local root = tree[getchar(head)]
+ if root then
+ local current = getnext(head)
+ local lastrun = false
+ local lastfinal = false
+ while current do
+ local char = isglyph(current)
+ if char then
+ local newroot = root[char]
+ if not newroot then
+ return lastrun, lastfinal
+ else
+ local final = newroot.final
+ if final then
+ if trace_detail then
+ report_replacement("hitting word %a, replacement %a",final.word,final.replacement)
+ end
+ lastrun = current
+ lastfinal = final
+ else
+ root = newroot
+ end
+ end
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if lastrun then
+ return lastrun, lastfinal
+ end
+ end
+ end
+end
+
+local function tonodes(list,template)
+ local head, current
+ for i=1,#list do
+ local new = copy_node(template)
+ setchar(new,list[i])
+ if head then
+ head, current = insert_after(head,current,new)
+ else
+ head, current = new, new
+ end
+ end
+ return head
+end
+
+
+function replacements.handler(head)
+ head = tonut(head)
+ local current = head
+ local done = false
+ while current do
+ if getid(current) == glyph_code then
+ local a = getattr(current,a_replacements)
+ if a then
+ local last, final = hit(a,current)
+ if last then
+ local oldlength = final.oldlength
+ local newcodes = final.newcodes
+ local newlength = #newcodes
+ if trace_replacement then
+ report_replacement("replacing word %a by %a",final.word,final.replacement)
+ end
+ if final.special then
+ -- easier is to delete and insert (a simple callout to tex would be more efficient)
+ -- maybe just walk over a replacement string instead
+ local prev = getprev(current)
+ local next = getnext(last)
+ local list = current
+ setnext(last)
+ setlink(prev,next)
+ current = prev
+ if not current then
+ head = nil
+ end
+ local i = 1
+ while i <= newlength do
+ local codes = newcodes[i]
+ local new = nil
+ if type(codes) == "table" then
+ local method = codes[1]
+ if method == "discretionary" then
+ local pre, post, replace = codes[2], codes[3], codes[4]
+ new = new_disc()
+ if pre then
+ setfield(new,"pre",tonodes(pre,last))
+ end
+ if post then
+ setfield(new,"post",tonodes(post,last))
+ end
+ if replace then
+ setfield(new,"replace",tonodes(replace,last))
+ end
+ head, current = insert_after(head,current,new)
+ elseif method == "noligature" then
+ -- not that efficient to copy but ok for testing
+ local list = codes[2]
+ if list then
+ for i=1,#list do
+ new = copy_node(last)
+ setchar(new,list[i])
+ setattr(new,a_noligature,1)
+ head, current = insert_after(head,current,new)
+ end
+ else
+ new = copy_node(last)
+ setchar(new,zwnj)
+ head, current = insert_after(head,current,new)
+ end
+ else
+ -- todo
+ end
+ else
+ new = copy_node(last)
+ setchar(new,codes)
+ head, current = insert_after(head,current,new)
+ end
+ i = i + 1
+ end
+ flush_list(list)
+ elseif oldlength == newlength then -- #old == #new
+ if final.word == final.replacement then
+ -- nothing to do but skip
+ else
+ for i=1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ end
+ elseif oldlength < newlength then -- #old < #new
+ for i=1,newlength-oldlength do
+ local n = copy_node(current)
+ setchar(n,newcodes[i])
+ head, current = insert_node_before(head,current,n)
+ current = getnext(current)
+ end
+ for i=newlength-oldlength+1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ else -- #old > #new
+ for i=1,oldlength-newlength do
+ head, current = remove_node(head,current,true)
+ end
+ for i=1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ end
+ done = true
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ return tonode(head), done
+end
+
+local enabled = false
+
+function replacements.set(n)
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = lists[n].attribute
+ if not enabled then
+ nodes.tasks.enableaction("processors","languages.replacements.handler")
+ if trace_replacements then
+ report_replacement("enabling replacement handler")
+ end
+ enabled = true
+ end
+ end
+ texsetattribute(a_replacements,n)
+end
+
+-- interface
+
+implement {
+ name = "setreplacements",
+ actions = replacements.set,
+ arguments = "string"
+}
+
+implement {
+ name = "addreplacements",
+ actions = replacements.add,
+ arguments = { "string", "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-rep.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.mkiv
new file mode 100644
index 00000000000..48e1fd44b7b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.mkiv
@@ -0,0 +1,75 @@
+%D \module
+%D [ file=lang-rep,
+%D version=2013.04.28,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Substitution,
+%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 I needed an example of messing with nodes for the bacho\TEX\ tutorial
+%D I cooked up this. In the end I decided to stick to a simpler example and
+%D just finished this off in case someone really needs it.
+
+\writestatus{loading}{ConTeXt Language Macros / Replacements}
+
+\unprotect
+
+\registerctxluafile{lang-rep}{1.001}
+
+\definesystemattribute[replacements][public,global]
+
+%D \startluacode
+%D
+%D -- todo: other nodes (prelude to more experiments with auto dropped caps)
+%D
+%D languages.replacements.add("basics", {
+%D ["aap"] = "monkey",
+%D ["noot"] = "nut",
+%D ["never"] = "forever",
+%D ["newer"] = "cooler",
+%D ["new"] = "cool",
+%D -- ["special"] = "veryspe{>>>}{<<<}{=}cial",
+%D })
+%D
+%D \stopluacode
+%D
+%D \replaceword[more][this][that]
+%D \replaceword[more][crap][support]
+%D \replaceword[more][---][—]
+%D \replaceword[basics][special][veryspe{>>>}{<<<}{=}cial]
+%D
+%D \starttyping
+%D \start \setreplacements[basics] What the heck, it's now or never, isn't it new? \par \stop
+%D \start \setreplacements[more] Do we --- {\it really} --- need this kind of crap? \par \stop
+%D \start \setreplacements[basics] All kinds of special thingies! \par \stop
+%D \start \setreplacements[basics] \hsize1mm special \par \stop
+%D \stoptyping
+
+\unexpanded\def\setreplacements[#1]%
+ {\clf_setreplacements{#1}}
+
+\unexpanded\def\resetreplacements
+ {\attribute\replacementsattribute\attributeunsetvalue}
+
+\unexpanded\def\replaceword
+ {\dotripleargument\languages_replacements_replace}
+
+\unexpanded\def\languages_replacements_replace[#1][#2][#3]%
+ {\ifthirdargument
+ \clf_addreplacements{#1}{#2}{#3}%
+ \fi}
+
+\appendtoks
+ \resetreplacements
+\to \everyresettypesetting
+
+\appendtoks
+ \resetreplacements
+\to \everyinitializeverbatim
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv
new file mode 100644
index 00000000000..e7cb0025fd6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv
@@ -0,0 +1,76 @@
+%D \module
+%D [ file=lang-spa,
+%D version=2002.04.17,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Spacing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Language Macros / Spacing}
+
+%D This module was created in the process of enhancing
+%D support for French (with the help of Daniel Flipo).
+%D
+%D This will (or already has) become obsolete!
+
+\unprotect
+
+\definehspace [\s!fr] [quotation] [\flexiblespaceamount{.8}{.3}{.8}]
+\definehspace [\s!fr] [sentence] [\fixedspaceamount{1}]
+
+%definehspace [\s!fr] [quote] [\flexiblespaceamount{.8}{.3}{.8}]
+%definehspace [\s!fr] [speech] [\flexiblespaceamount{.8}{.3}{.8}]
+
+\definehspace [\s!fr] [interquotation] [\zeropoint]
+\definehspace [\s!fr] [intersentence] [\zeropoint]
+
+\definehspace [\string :] [\zeropoint]
+\definehspace [\string ;] [\zeropoint]
+\definehspace [\string !] [\zeropoint]
+\definehspace [\string ?] [\zeropoint]
+
+\definehspace [\s!fr] [\string :] [\spaceamount]
+\definehspace [\s!fr] [\string ;] [.16667em]
+\definehspace [\s!fr] [\string !] [.16667em]
+\definehspace [\s!fr] [\string ?] [.16667em]
+
+%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{!}!}
+
+%D \startbuffer
+%D \mainlanguage[en] \quotation{test \quotation{test} test}\par
+%D \mainlanguage[nl] \quotation{test \quotation{test} test}\par
+%D \mainlanguage[fr] \quotation{test \quotation{test} test}\par
+%D
+%D \mainlanguage[en] \quotation{\quotation{test} test}\par
+%D \mainlanguage[nl] \quotation{\quotation{test} test}\par
+%D \mainlanguage[fr] \quotation{\quotation{test} test}\par
+%D
+%D \mainlanguage[en] |<|test |<|test|>| test|>| \par
+%D \mainlanguage[nl] |<|test |<|test|>| test|>| \par
+%D \mainlanguage[fr] |<|test |<|test|>| test|>| \par
+%D
+%D \mainlanguage[en] |<||<|test|>| test|>| \par
+%D \mainlanguage[nl] |<||<|test|>| test|>| \par
+%D \mainlanguage[fr] |<||<|test|>| test|>| \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua
new file mode 100644
index 00000000000..2938550eef3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua
@@ -0,0 +1,2804 @@
+if not modules then modules = { } end modules ['lang-txt'] = {
+ version = 1.001,
+ comment = "companion to lang-lab.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+-- The content of this file is derived from the mkii lang-* files and
+-- early 2011 the mkii labels are generated from this file. The
+-- translations have been collected over years by users, using named
+-- glyphs. This file uses utf exclusively.
+--
+-- Many of the initial translations were done by Tobias Burnus but
+-- completed by numerous users. The following list is incomplete so feel
+-- free to send me corrections.
+--
+-- af Afrikaans ...
+-- ar Arabic Idris Samawi Hamid, Khaled Hosny
+-- ca Catalan ...
+-- cn Chinese Wang Lei, ...
+-- cs Czech Tom Hudec, Petr Sojka, Richard Gabriel
+-- da Danish Arne Jorgensen
+-- de German Tobias Burnus, ...
+-- en English Hans Hagen, ...
+-- es Spanish Andrés Montoya, ...
+-- fi Finish ...
+-- fr French Daniel Flipo, Arthur Reutenauer
+-- gr Greek Apostolos Syropoulos, Thomas Schmitz
+-- hr Croatian Željko Vrba, Richard Gabriel, Vedran Miletić
+-- hu Hungarian Adam Reviczky
+-- it Italian Giuseppe Bilotta, Luigi Scarso
+-- ja Japanese Richard Gabriel
+-- kr Korean Jeong Dalyoung
+-- la Latin ...
+-- lt Lithuanian Marius Aleknevičius
+-- nb Norwegian Hans Fredrik Nordhaug, ...
+-- nn Norwegian Hans Fredrik Nordhaug, ...
+-- nl Dutch Hans Hagen
+-- pl Polish Grzegorz Sapijaszko
+-- pt Portuguese Pedro F. M. Mendonça
+-- ro Romanian Dan Seracu, ...
+-- ru Russian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ...
+-- sk Slovak ...
+-- sl Slovenian Mojca Miklavec
+-- sv Swedish ...
+-- tk Turkish Tobias Burnus
+-- tr Turkmen Nazar Annagurban
+-- ua Ukrainian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ...
+-- vi Vietnamese Han The Thanh
+
+-- For the moment we keep this table in memory. In the future we can then
+-- enable labels.
+
+-- thinspace == sixperemspace = 0x2006
+-- print("!"..utf.char(0x2006).."!")
+
+languages = languages or { }
+local languages = languages
+
+languages.data = languages.data or utilities.storage.allocate { }
+local data = languages.data
+
+data.labels={
+ functions={
+ Pr={
+ labels={
+ cz="P",
+ en="Pr",
+ sk="P",
+ },
+ },
+ arccos={
+ labels={
+ cz="arccos",
+ en="arccos",
+ es="arc\\sixperemspace cos",
+ hr="arc\\sixperemspace cos",
+ pl="arc\\sixperemspace cos",
+ sk="arccos",
+ },
+ },
+ arcctg={
+ labels={
+ cz="arccotg",
+ en="arccot",
+ es="arc\\sixperemspace cot",
+ hr="arc\\sixperemspace ctg",
+ pl="arc\\sixperemspace ctg",
+ sk="arccotg",
+ },
+ },
+ arcsin={
+ labels={
+ cz="arcsin",
+ en="arcsin",
+ es="arc\\sixperemspace sen",
+ hr="arc\\sixperemspace sin",
+ pl="arc\\sixperemspace sin",
+ sk="arcsin",
+ },
+ },
+ arctan={
+ labels={
+ cz="arctg",
+ en="arctan",
+ es="arc\\sixperemspace tan",
+ hr="arc\\sixperemspace tg",
+ pl="arc\\sixperemspace tg",
+ sk="arctg",
+ },
+ },
+ arctg={
+ labels={
+ cz="arctg",
+ en="arctan",
+ es="arc\\sixperemspace tan",
+ hr="arc\\sixperemspace tg",
+ pl="arc\\sixperemspace tg",
+ sk="arctg",
+ },
+ },
+ arg={
+ labels={
+ cz="arg",
+ en="arg",
+ es="arg",
+ sk="arg",
+ },
+ },
+ cos={
+ labels={
+ cz="cos",
+ en="cos",
+ es="cos",
+ sk="cos",
+ },
+ },
+ cosh={
+ labels={
+ cz="cosh",
+ en="cosh",
+ es="cosh",
+ sk="cosh",
+ },
+ },
+ cot={
+ labels={
+ cz="cotg",
+ en="cot",
+ es="cot",
+ hr="ctg",
+ pl="ctg",
+ sk="cotg",
+ },
+ },
+ coth={
+ labels={
+ cz="cotgh",
+ en="coth",
+ es="coth",
+ sk="cotgh",
+ },
+ },
+ csc={
+ labels={
+ cz="cosec",
+ en="csc",
+ es="csc",
+ sk="cosec",
+ },
+ },
+ ctg={
+ labels={
+ cz="cotg",
+ en="cot",
+ es="cot",
+ hr="ctg",
+ pl="ctg",
+ sk="cotg",
+ },
+ },
+ diff={
+ labels={
+ en="d",
+ },
+ },
+ deg={
+ labels={
+ cz="deg",
+ en="deg",
+ es="gr",
+ sk="deg",
+ },
+ },
+ det={
+ labels={
+ cz="det",
+ en="det",
+ es="det",
+ sk="det",
+ },
+ },
+ dim={
+ labels={
+ cz="dim",
+ en="dim",
+ es="dim",
+ sk="dim",
+ },
+ },
+ exp={
+ labels={
+ cz="exp",
+ en="exp",
+ es="exp",
+ sk="exp",
+ },
+ },
+ gcd={
+ labels={
+ cz="NSD",
+ en="gcd",
+ es="mcd",
+ hr="nzd",
+ nl="ggd",
+ sk="NSD",
+ },
+ },
+ hom={
+ labels={
+ cz="Hom",
+ en="hom",
+ es="hom",
+ sk="Hom",
+ },
+ },
+ inf={
+ labels={
+ cz="inf",
+ en="inf",
+ es="inf",
+ sk="inf",
+ },
+ },
+ injlim={
+ labels={
+ cz="inj\\sixperemspace lim",
+ en="inj\\sixperemspace lim",
+ es="lím\\sixperemspace iny",
+ sk="inj\\sixperemspace lim",
+ },
+ },
+ ker={
+ labels={
+ cz="ker",
+ en="ker",
+ es="Ker",
+ sk="ker",
+ },
+ },
+ lcm={
+ labels={
+ cz="NSN",
+ en="lcm",
+ es="MCM",
+ hr="nzv",
+ nl="kgv",
+ sk="NSN",
+ },
+ },
+ lg={
+ labels={
+ cz="log",
+ en="lg",
+ es="log",
+ sk="log",
+ },
+ },
+ lim={
+ labels={
+ cz="lim",
+ en="lim",
+ es="lím",
+ sk="lim",
+ },
+ },
+ liminf={
+ labels={
+ cz="lim\\sixperemspace inf",
+ en="lim\\sixperemspace inf",
+ es="lím\\sixperemspace inf",
+ sk="lim\\sixperemspace inf",
+ },
+ },
+ limsup={
+ labels={
+ cz="lim\\sixperemspace sup",
+ en="lim\\sixperemspace sup",
+ es="lím\\sixperemspace sup",
+ sk="lim\\sixperemspace sup",
+ },
+ },
+ ln={
+ labels={
+ cz="ln",
+ en="ln",
+ es="ln",
+ sk="ln",
+ },
+ },
+ log={
+ labels={
+ cz="log",
+ en="log",
+ es="log",
+ sk="log",
+ },
+ },
+ max={
+ labels={
+ cz="max",
+ en="max",
+ es="máx",
+ sk="max",
+ },
+ },
+ median={
+ labels={
+ cz="\\tilde",
+ en="median",
+ es="Mediana",
+ sk="\\tilde",
+ },
+ },
+ min={
+ labels={
+ cz="min",
+ en="min",
+ es="mín",
+ sk="min",
+ },
+ },
+ mod={
+ labels={
+ cz="mod",
+ en="mod",
+ es="mod",
+ sk="mod",
+ },
+ },
+ projlim={
+ labels={
+ cz="proj\\sixperemspace lim",
+ en="proj\\sixperemspace lim",
+ es="lím\\sixperemspace proy",
+ sk="proj\\sixperemspace lim",
+ },
+ },
+ sec={
+ labels={
+ cz="sec",
+ en="sec",
+ es="sec",
+ sk="sec",
+ },
+ },
+ sin={
+ labels={
+ cz="sin",
+ en="sin",
+ es="sen",
+ sk="sin",
+ },
+ },
+ sinh={
+ labels={
+ cz="sinh",
+ en="sinh",
+ es="senh",
+ sk="sinh",
+ },
+ },
+ sup={
+ labels={
+ cz="sup",
+ en="sup",
+ es="sup",
+ sk="sup",
+ },
+ },
+ tan={
+ labels={
+ cz="tg",
+ en="tan",
+ es="tan",
+ hr="tg",
+ pl="tg",
+ sk="tg",
+ },
+ },
+ tanh={
+ labels={
+ cz="tgh",
+ en="tanh",
+ es="tanh",
+ sk="tgh",
+ },
+ },
+ tg={
+ labels={
+ cz="tg",
+ en="tan",
+ es="tan",
+ hr="tg",
+ pl="tg",
+ sk="tg",
+ },
+ },
+ },
+ texts={
+ ["year"]={
+ labels={
+ en="year",
+ nl="jaar",
+ kr="년",
+ },
+ },
+ ["month"]={
+ labels={
+ en="month",
+ nl="maand",
+ kr="월",
+ },
+ },
+ ["day"]={
+ labels={
+ en="day",
+ nl="dag",
+ kr="일",
+ },
+ },
+ ["and"]={
+ labels={
+ af="",
+ ca="",
+ cs="a",
+ da="",
+ de="und",
+ en="and",
+ es="y",
+ fi="",
+ fr="",
+ gr="",
+ hr="i",
+ hu="és",
+ it="",
+ la="",
+ lt="",
+ nb="",
+ nl="en",
+ nn="",
+ pl="i",
+ pt="",
+ ro="",
+ ru="",
+ sk="a",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ appendix={
+ hidden=true,
+ labels={
+ af="Bylae ",
+ ar="ملحق ",
+ ca="Apèndix ",
+ cn="附录",
+ cs="Příloha ",
+ da="Bilag ",
+ de="Anhang ",
+ en="Appendix ",
+ es="Apéndice ",
+ fi="",
+ fr="Annexe ",
+ gr="Παράρτημα",
+ hr="Dodatak ",
+ hu="Melléklet ",
+ it="",
+ ja="付録",
+ kr="부록",
+ la="",
+ lt="",
+ nb="Tillegg ",
+ nl="",
+ nn="Tillegg ",
+ pl="Dodatek ",
+ pt="",
+ ro="",
+ ru="",
+ sk="Príloha ",
+ sl="Dodatek ",
+ sv="",
+ tk="Goşmaça",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ april={
+ labels={
+ af="april",
+ ar="أبريل",
+ ["ar-dz"]="أفريل",
+ ["ar-sy"]="نيسان",
+ ca="abril",
+ cn="四月",
+ cs="dubna",
+ da="april",
+ de="April",
+ en="April",
+ es="abril",
+ fi="huhtikuu",
+ fr="avril",
+ gr="Απρίλιος",
+ hr="travnja",
+ hu="április",
+ it="aprile",
+ ja="4",
+ kr="4",
+ la="Aprilis",
+ lt="balandžio",
+ nb="april",
+ nl="april",
+ nn="april",
+ pl="kwietnia",
+ pt="abril",
+ ro="aprilie",
+ ru="апреля",
+ sk="apríla",
+ sl="april",
+ sv="april",
+ tk="aprel",
+ tr="nisan",
+ ua="квітня",
+ vi="tháng tư",
+ },
+ },
+ ["april:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="dub.",
+ da="",
+ de="",
+ en="apr",
+ es="abr.",
+ fi="",
+ fr="",
+ gr="",
+ hr="tra",
+ hu="ápr.",
+ it="",
+ la="",
+ lt="apr",
+ nb="april",
+ nl="",
+ nn="april",
+ pl="kwi.",
+ pt="",
+ ro="",
+ ru="",
+ sk="apr.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ atpage={
+ labels={
+ af="",
+ ar="في صفحة ",
+ ca="",
+ cs="na straně ",
+ da="på side ",
+ de="auf Seite ",
+ en="at page ",
+ es="en la página ",
+ fi="",
+ fr="à la page ",
+ gr="",
+ hr="na stranici ",
+ hu="oldal ",
+ it="a pagina ",
+ la="",
+ lt="puslapyje ",
+ nb="på side ",
+ nl="op pagina ",
+ nn="på side ",
+ pl="na stronie ",
+ pt="",
+ ro="",
+ ru="на странице ",
+ sk="na strane ",
+ sl="na strani ",
+ sv="på sida ",
+ tk="",
+ tr="",
+ ua="на сторінці ",
+ vi="",
+ },
+ },
+ august={
+ labels={
+ af="augustus",
+ ar="أغسطس",
+ ["ar-dz"]="أوت",
+ ["ar-ma"]="غشت",
+ ["ar-sy"]="آب",
+ ca="agost",
+ cn="八月",
+ cs="srpna",
+ da="august",
+ de="August",
+ en="August",
+ es="agosto",
+ fi="elokuu",
+ fr="août",
+ gr="Αύγουστος",
+ hr="kolovoza",
+ hu="augusztus",
+ it="agosto",
+ ja="8",
+ kr="8",
+ la="Augustus",
+ lt="rugpjūčio",
+ nb="august",
+ nl="augustus",
+ nn="august",
+ pl="sierpnia",
+ pt="agosto",
+ ro="august",
+ ru="августа",
+ sk="augusta",
+ sl="avgust",
+ sv="augusti",
+ tk="awgust",
+ tr="ağustos",
+ ua="серпня",
+ vi="tháng tám",
+ },
+ },
+ ["august:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="srp.",
+ da="",
+ de="",
+ en="aug",
+ es="ago.",
+ fi="",
+ fr="",
+ gr="",
+ hr="kol",
+ hu="aug.",
+ it="",
+ la="",
+ lt="aug",
+ nb="aug.",
+ nl="",
+ nn="aug.",
+ pl="sier.",
+ pt="",
+ ro="",
+ ru="",
+ sk="aug.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ chapter={
+ hidden=true,
+ labels={
+ af="Hoofstuk ",
+ ar="باب ",
+ ca="Capítol ",
+ cn={"第","章"},
+ cs="Kapitola ",
+ da="",
+ de="Kapitel ",
+ en="Chapter ",
+ es="Capítulo ",
+ fi="",
+ fr="Chapitre ",
+ gr="Κεφάλαιο",
+ hr="Poglavlje ",
+ hu={""," fejezet"},
+ it="",
+ ja={"第","章"},
+ kr={"제","장"},
+ la="",
+ lt="",
+ nb="",
+ nl="",
+ nn="",
+ pl="Rozdział ",
+ pt="",
+ ro="",
+ ru="",
+ sk="Kapitola ",
+ sl="Poglavje ",
+ sv="",
+ tk="Bap",
+ tr="",
+ ua="",
+ vi="Chương ",
+ },
+ },
+ continued={
+ labels={
+ af="",
+ ca="",
+ cs=" (pokračování)",
+ da="",
+ de="",
+ en=" (continued)",
+ es=" (continúa)",
+ fi="",
+ fr="",
+ gr="",
+ hr=" (nastavak)",
+ hu=" (folytatás)",
+ it="",
+ la="",
+ lt="",
+ nb="",
+ nl=" (vervolgd)",
+ nn="",
+ pl="",
+ pt="",
+ ro="",
+ ru="",
+ sk=" (pokračovanie)",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ december={
+ labels={
+ af="desember",
+ ar="ديسمبر",
+ ["ar-ma"]="دجنبر",
+ ["ar-sy"]="كانون الأول",
+ ca="desembre",
+ cn="十二月",
+ cs="prosince",
+ da="december",
+ de="Dezember",
+ en="December",
+ es="diciembre",
+ fi="joulukuu",
+ fr="décembre",
+ gr="Δεκέμβριος",
+ hr="prosinca",
+ hu="december",
+ it="dicembre",
+ ja="12",
+ kr="12",
+ la="December",
+ lt="gruodžio",
+ nb="desember",
+ nl="december",
+ nn="desember",
+ pl="grudnia",
+ pt="dezembro",
+ ro="decembrie",
+ ru="декабря",
+ sk="decembra",
+ sl="december",
+ sv="december",
+ tk="dekabr",
+ tr="aralık",
+ ua="грудня",
+ vi="tháng mười hai",
+ },
+ },
+ ["december:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="pros.",
+ da="",
+ de="",
+ en="dec",
+ es="dic.",
+ fi="",
+ fr="",
+ gr="",
+ hr="pro",
+ hu="dec.",
+ it="",
+ la="",
+ lt="dec",
+ nb="des.",
+ nl="",
+ nn="des.",
+ pl="gru.",
+ pt="",
+ ro="",
+ ru="",
+ sk="dec.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ february={
+ labels={
+ af="februarie",
+ ar="فبراير",
+ ["ar-dz"]="فيفري",
+ ["ar-sy"]="شباط",
+ ca="febrer",
+ cn="二月",
+ cs="února",
+ da="februar",
+ de="Februar",
+ en="February",
+ es="febrero",
+ fi="helmikuu",
+ fr="février",
+ gr="Φεβρουάριος",
+ hr="veljače",
+ hu="február",
+ it="febbraio",
+ ja="2",
+ kr="2",
+ la="Februarius",
+ lt="vasario",
+ nb="februar",
+ nl="februari",
+ nn="februar",
+ pl="lutego",
+ pt="fevereiro",
+ ro="februarie",
+ ru="февраля",
+ sk="februára",
+ sl="februar",
+ sv="februari",
+ tk="fewral",
+ tr="Şubat",
+ ua="лютого",
+ vi="tháng hai",
+ },
+ },
+ ["february:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="ún.",
+ da="",
+ de="",
+ en="feb",
+ es="feb.",
+ fi="",
+ fr="",
+ gr="",
+ hr="velj",
+ hu="feb.",
+ it="",
+ la="",
+ lt="feb",
+ nb="feb.",
+ nl="",
+ nn="feb.",
+ pl="lut.",
+ pt="",
+ ro="",
+ ru="",
+ sk="feb.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ figure={
+ labels={
+ af="Figuur ",
+ ar="شكل ",
+ ca="Figura ",
+ cn="图",
+ cs="Obrázek ",
+ da="Figur ",
+ de="Abbildung ",
+ en="Figure ",
+ es="Figura ",
+ fi="Kuva ",
+ fr="Figure ",
+ gr="Σχήμα",
+ hr="Slika ",
+ hu={""," ábra"},
+ it="Fig. ",
+ ja="図",
+ kr="그림 ",
+ la="Imago ",
+ lt={""," pav."},
+ nb="Figur ",
+ nl="Figuur ",
+ nn="Figur ",
+ pl="Ilustracja ",
+ pt="Figura ",
+ ro="Figura ",
+ ru="Рисунок ",
+ sk="Obrázok ",
+ sl="Slika ",
+ sv="Figur ",
+ tk="Surat",
+ tr="Şekil ",
+ ua="Малюнок ",
+ vi="Hình ",
+ },
+ },
+ friday={
+ labels={
+ af="vrydag",
+ ar="الجمعة",
+ ca="divendres",
+ cn="星期五",
+ cs="pátek",
+ da="fredag",
+ de="Freitag",
+ en="Friday",
+ es="viernes",
+ fi="perjantai",
+ fr="vendredi",
+ gr="Παρασκευή",
+ hr="petak",
+ hu="péntek",
+ it="venerdì",
+ ja="金曜日",
+ kr="금요일",
+ la="Dies Veneris",
+ lt="penktadienis",
+ nb="fredag",
+ nl="vrijdag",
+ nn="fredag",
+ pl="piątek",
+ pt="sexta-feira",
+ ro="vineri",
+ ru="пятница",
+ sk="piatok",
+ sl="petek",
+ sv="fredag",
+ tk="bäşinji gün",
+ tr="cuma",
+ ua="п'ятниця",
+ vi="thứ sáu",
+ },
+ },
+ graphic={
+ labels={
+ af="Grafiek ",
+ ar="رسم ",
+ ca="Gràfica ",
+ cn="插图",
+ cs="Graf ",
+ da="Grafik ",
+ de="Graphik ",
+ en="Graphic ",
+ es="Gráfico ",
+ fi="Grafiikka ",
+ fr="Illustration ",
+ gr="Γραφικό",
+ hr="Slika ",
+ hu={""," kép"},
+ it="Grafico ",
+ ja="イラスト",
+ la="Typus ",
+ lt="Graphic ",
+ nb="Bilde ",
+ nl="Grafiek ",
+ nn="Bilete ",
+ pl="Grafika ",
+ pt="Gráfico ",
+ ro="Graficul ",
+ ru="График ",
+ sk="Graf ",
+ sl="Slika ",
+ sv="Grafik ",
+ tk="Grafik",
+ tr="Grafik",
+ ua="График ",
+ vi="Đồ thị",
+ },
+ },
+ precedingpage={
+ labels={
+ en="on a preceding page",
+ nl="op een voorgaande bladzijde",
+ },
+ },
+ followingpage={
+ labels={
+ en="on a following page",
+ nl="op een volgende bladzijde",
+ },
+ },
+ hencefore={
+ labels={
+ af="",
+ ar="كما وضحنا سابقا",
+ ca="",
+ cs="viz výše",
+ da="se foroven",
+ de="siehe oben",
+ en="as we show above",
+ es="como se muestra arriba",
+ fi="",
+ fr="ci-dessus",
+ gr="",
+ hr="vidi gore",
+ hu="lásd feljebb",
+ kr="그러므로",
+ it="come mostrato sopra",
+ la="",
+ lt="kaip parodyta aukščiau",
+ nb="som vist over",
+ nl="hierboven",
+ nn="som vist over",
+ pl="jak pokazano wyżej",
+ pt="",
+ ro="",
+ ru="см. выше",
+ sk="pozri hore",
+ sl="glej zgoraj",
+ sv="se ovan",
+ tk="",
+ tr="",
+ ua="як показано вище",
+ vi="",
+ },
+ },
+ hereafter={
+ labels={
+ af="",
+ ar="كما نوضح لاحقا",
+ ca="",
+ cs="viz níže",
+ da="se forneden",
+ de="siehe unten",
+ en="as we show below",
+ es="como se muestra abajo",
+ fi="",
+ fr="ci-dessous",
+ gr="",
+ hr="vidi ispod",
+ hu="lásd lejjebb",
+ it="come mostrato sotto",
+ kr="이후로",
+ la="",
+ lt="kaip parodyta žemiau",
+ nb="som vist under",
+ nl="hieronder",
+ nn="som vist under",
+ pl="jak pokazano niżej",
+ pt="",
+ ro="",
+ ru="см. ниже",
+ sk="pozri ďalej",
+ sl="glej spodaj",
+ sv="se nedan",
+ tk="",
+ tr="",
+ ua="як показано нижче",
+ vi="",
+ },
+ },
+ intermezzo={
+ labels={
+ af="Intermezzo ",
+ ar="فسحة ",
+ ca="Intermedi ",
+ cn="퉣",
+ cs="Intermezzo ",
+ da="Intermezzo ",
+ de="Intermezzo ",
+ en="Intermezzo ",
+ es="Intermedio ",
+ fi="Intermezzo ",
+ fr="Intermède ",
+ gr="Παύση",
+ hr="Intermeco ",
+ hu={""," intermezzo"},
+ it="Intermezzo ",
+ ja="間奏曲",
+ kr="간주곡",
+ la="Intermissum ",
+ lt="Intermezzo ",
+ nb="Intermesso ",
+ nl="Intermezzo ",
+ nn="Intermesso ",
+ pl="Intermezzo ",
+ pt="Intermédio ",
+ ro="Intermezzo ",
+ ru="Вставка ",
+ sk="Intermezzo ",
+ sl="Intermezzo ",
+ sv="Intermezzo ",
+ tk="Arakesme",
+ tr="",
+ ua="Вставка ",
+ vi="intermezzo",
+ },
+ },
+ january={
+ labels={
+ af="januarie",
+ ar="يناير",
+ ["ar-dz"]="جانفي",
+ ["ar-sy"]="كانون الثاني",
+ ca="gener",
+ cn="一月",
+ cs="ledna",
+ da="januar",
+ de="Januar",
+ en="January",
+ es="enero",
+ fi="tammikuu",
+ fr="janvier",
+ gr="Ιανουάριος",
+ hr="siječnja",
+ hu="január",
+ it="gennaio",
+ ja="1",
+ kr="1",
+ la="Ianuarius",
+ lt="sausio",
+ nb="januar",
+ nl="januari",
+ nn="januar",
+ pl="stycznia",
+ pt="janeiro",
+ ro="ianuarie",
+ ru="января",
+ sk="januára",
+ sl="januar",
+ sv="januari",
+ tk="ýanwar",
+ tr="ocak",
+ ua="січня",
+ vi="tháng giêng",
+ },
+ },
+ ["january:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="led.",
+ da="",
+ de="",
+ en="jan",
+ es="ene.",
+ fi="",
+ fr="",
+ gr="",
+ hr="sij",
+ hu="jan.",
+ it="",
+ la="",
+ lt="jan",
+ nb="jan.",
+ nl="",
+ nn="jan.",
+ pl="sty.",
+ pt="",
+ ro="",
+ ru="",
+ sk="jan.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ july={
+ labels={
+ af="julie",
+ ar="يوليو",
+ ["ar-dz"]="جويلة",
+ ["ar-ma"]="يوليوز",
+ ["ar-sy"]="تموز",
+ ca="juliol",
+ cn="七月",
+ cs="července",
+ da="juli",
+ de="Juli",
+ en="July",
+ es="julio",
+ fi="heinäkuu",
+ fr="juillet",
+ gr="Ιούλιος",
+ hr="srpnja",
+ hu="július",
+ it="luglio",
+ ja="7",
+ kr="7",
+ la="Iulius",
+ lt="liepos",
+ nb="juli",
+ nl="juli",
+ nn="juli",
+ pl="lipca",
+ pt="julho",
+ ro="iulie",
+ ru="июля",
+ sk="júla",
+ sl="julij",
+ sv="juli",
+ tk="iýul",
+ tr="temmuz",
+ ua="липня",
+ vi="tháng bảy",
+ },
+ },
+ ["july:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="čce",
+ da="",
+ de="",
+ en="jul",
+ es="jul.",
+ fi="",
+ fr="",
+ gr="",
+ hr="srp",
+ hu="júl.",
+ it="",
+ la="",
+ lt="jul",
+ nb="juli",
+ nl="",
+ nn="juli",
+ pl="lip.",
+ pt="",
+ ro="",
+ ru="",
+ sk="júla",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ june={
+ labels={
+ af="junie",
+ ar="يونيو",
+ ["ar-dz"]="جوان",
+ ["ar-sy"]="حزيران",
+ ca="juny",
+ cn="六月",
+ cs="června",
+ da="juni",
+ de="Juni",
+ en="June",
+ es="junio",
+ fi="kesäkuu",
+ fr="juin",
+ gr="Ιούνιος",
+ hr="lipnja",
+ hu="június",
+ it="giugno",
+ ja="6",
+ kr="6",
+ la="Iunius",
+ lt="birželio",
+ nb="juni",
+ nl="juni",
+ nn="juni",
+ pl="czerwca",
+ pt="junho",
+ ro="iunie",
+ ru="июня",
+ sk="júna",
+ sl="junij",
+ sv="juni",
+ tk="iýun",
+ tr="haziran",
+ ua="червня",
+ vi="tháng sáu",
+ },
+ },
+ ["june:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="čer.",
+ da="",
+ de="",
+ en="jun",
+ es="jun.",
+ fi="",
+ fr="",
+ gr="",
+ hr="lip",
+ hu="jún.",
+ it="",
+ la="",
+ lt="jun",
+ nb="juni",
+ nl="",
+ nn="juni",
+ pl="czerw.",
+ pt="",
+ ro="",
+ ru="",
+ sk="júna",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ line={
+ labels={
+ af="reël ",
+ ar="سطر ",
+ ca="línia ",
+ cn="行",
+ cs="řádek ",
+ da="linie ",
+ de="Zeile ",
+ en="line ",
+ es="línea ",
+ fi="rivi ",
+ fr="ligne ",
+ gr="Γραμμή",
+ hr="redak ",
+ hu={""," sor"},
+ it="riga ",
+ ja="線",
+ kr="행",
+ la="versus ",
+ lt="line ",
+ nb="linje ",
+ nl="regel ",
+ nn="linje ",
+ pl="wiersz ",
+ pt="linha ",
+ ro="linia ",
+ ru="строка ",
+ sk="riadok ",
+ sl="vrstica ",
+ sv="rad ",
+ tk="setir",
+ tr="satır ",
+ ua="рядок ",
+ vi="dòng ",
+ },
+ },
+ lines={
+ labels={
+ af="reëls ",
+ ar="السطور ",
+ ca="línies ",
+ cn="行",
+ cs="řádky ",
+ da="linier ",
+ de="Zeilen ",
+ en="lines ",
+ es="líneas ",
+ fi="rivie ",
+ fr="lignes ",
+ gr="Γραμμές",
+ hr="retci ",
+ hu="sorok ",
+ it="righe ",
+ ja="線",
+ kr="행",
+ la="versus ",
+ lt="lines ",
+ nb="linjer ",
+ nl="regels ",
+ nn="linjer ",
+ pl="wiersze ",
+ pt="linhas ",
+ ro="liniile ",
+ ru="строки ",
+ sk="riadky ",
+ sl="vrstice ",
+ sv="rader ",
+ tk="setirler",
+ tr="satırlar ",
+ ua="рядки ",
+ vi="dòng ",
+ },
+ },
+ march={
+ labels={
+ af="maart",
+ ar="مارس",
+ ["ar-sy"]="آذار",
+ ca="març",
+ cn="三月",
+ cs="března",
+ da="marts",
+ de="März",
+ en="March",
+ es="marzo",
+ fi="maaliskuu",
+ fr="mars",
+ gr="Μάρτιος",
+ hr="ožujka",
+ hu="március",
+ it="marzo",
+ ja="3",
+ kr="3",
+ la="Martius",
+ lt="kovo",
+ nb="mars",
+ nl="maart",
+ nn="mars",
+ pl="marca",
+ pt="março",
+ ro="martie",
+ ru="марта",
+ sk="marca",
+ sl="marec",
+ sv="mars",
+ tk="mart",
+ tr="mart",
+ ua="березня",
+ vi="tháng ba",
+ },
+ },
+ ["march:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="břez.",
+ da="",
+ de="",
+ en="mar",
+ es="mar.",
+ fi="",
+ fr="",
+ gr="",
+ hr="ožu",
+ hu="már.",
+ it="",
+ la="",
+ lt="mar",
+ nb="mars",
+ nl="",
+ nn="mars",
+ pl="mar.",
+ pt="",
+ ro="",
+ ru="",
+ sk="mar.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ may={
+ labels={
+ af="mei",
+ ar="مايو",
+ ["ar-dz"]="ماي",
+ ["ar-ma"]="ماي",
+ ["ar-sy"]="أيار",
+ ca="maig",
+ cn="五月",
+ cs="května",
+ da="maj",
+ de="Mai",
+ en="May",
+ es="mayo",
+ fi="toukokuu",
+ fr="mai",
+ gr="Μάιος",
+ hr="svibnja",
+ hu="május",
+ it="maggio",
+ ja="5",
+ kr="5",
+ la="Maius",
+ lt="gegužės",
+ nb="mai",
+ nl="mei",
+ nn="mai",
+ pl="maja",
+ pt="maio",
+ ro="mai",
+ ru="мая",
+ sk="mája",
+ sl="maj",
+ sv="maj",
+ tk="maý",
+ tr="mayıs",
+ ua="травня",
+ vi="tháng năm",
+ },
+ },
+ ["may:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="květ.",
+ da="",
+ de="",
+ en="may",
+ es="may.",
+ fi="",
+ fr="",
+ gr="",
+ hr="svi",
+ hu="máj.",
+ it="",
+ la="",
+ lt="may",
+ nb="mai",
+ nl="",
+ nn="mai",
+ pl="maja",
+ pt="",
+ ro="",
+ ru="",
+ sk="mája",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ monday={
+ labels={
+ af="maandag",
+ ar="الاثنين",
+ ca="dilluns",
+ cn="星期一",
+ cs="pondělí",
+ da="mandag",
+ de="Montag",
+ en="Monday",
+ es="lunes",
+ fi="maanantai",
+ fr="lundi",
+ gr="Δευτέρα",
+ hr="ponedjeljak",
+ hu="hétfő",
+ it="lunedì",
+ ja="月曜日",
+ kr="월요일",
+ la="Dies Lunae",
+ lt="pirmadienis",
+ nb="mandag",
+ nl="maandag",
+ nn="måndag",
+ pl="poniedziałek",
+ pt="segunda-feira",
+ ro="luni",
+ ru="понедельник",
+ sk="pondelok",
+ sl="ponedeljek",
+ sv="måndag",
+ tk="birinji gün",
+ tr="pazartesi",
+ ua="понеділок",
+ vi="thứ hai",
+ },
+ },
+ november={
+ labels={
+ af="november",
+ ar="نوفمبر",
+ ["ar-ma"]="نونبر",
+ ["ar-sy"]="تشرين الثاني",
+ ca="novembre",
+ cn="十一月",
+ cs="listopadu",
+ da="november",
+ de="November",
+ en="November",
+ es="noviembre",
+ fi="marraskuu",
+ fr="novembre",
+ gr="Νοέμβριος",
+ hr="studenog",
+ hu="november",
+ it="novembre",
+ ja="11",
+ kr="11",
+ la="November",
+ lt="lapkričio",
+ nb="november",
+ nl="november",
+ nn="november",
+ pl="listopada",
+ pt="novembro",
+ ro="noiembrie",
+ ru="ноября",
+ sk="novembra",
+ sl="november",
+ sv="november",
+ tk="noýabr",
+ tr="kasım",
+ ua="листопада",
+ vi="tháng mười một",
+ },
+ },
+ ["november:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="list.",
+ da="",
+ de="",
+ en="nov",
+ es="nov.",
+ fi="",
+ fr="",
+ gr="",
+ hr="stu",
+ hu="nov.",
+ it="",
+ la="",
+ lt="nov",
+ nb="nov.",
+ nl="",
+ nn="nov.",
+ pl="lis.",
+ pt="",
+ ro="",
+ ru="",
+ sk="nov.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ october={
+ labels={
+ af="oktober",
+ ar="أكتوبر",
+ ["ar-sy"]="تشرين الأول",
+ ca="octubre",
+ cn="十月",
+ cs="října",
+ da="oktober",
+ de="Oktober",
+ en="October",
+ es="octubre",
+ fi="lokakuu",
+ fr="octobre",
+ gr="Οκτώβριος",
+ hr="listopada",
+ hu="október",
+ it="ottobre",
+ ja="10",
+ kr="10",
+ la="October",
+ lt="spalio",
+ nb="oktober",
+ nl="oktober",
+ nn="oktober",
+ pl="października",
+ pt="outubro",
+ ro="octombrie",
+ ru="октября",
+ sk="októbra",
+ sl="oktober",
+ sv="oktober",
+ tk="oktýabr",
+ tr="ekim",
+ ua="жовтня",
+ vi="tháng mười",
+ },
+ },
+ ["october:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="říj.",
+ da="",
+ de="",
+ en="oct",
+ es="oct.",
+ fi="",
+ fr="",
+ gr="",
+ hr="lis",
+ hu="okt.",
+ it="",
+ la="",
+ lt="oct",
+ nb="okt.",
+ nl="",
+ nn="okt.",
+ pl="paź.",
+ pt="",
+ ro="",
+ ru="",
+ sk="okt.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ page={
+ labels={
+ af="",
+ ar="صفحة ",
+ ca="",
+ cs="strana ",
+ da="Side ",
+ de="Seite ",
+ en="page ",
+ es="página ",
+ fi="",
+ fr="page ",
+ gr="",
+ hr="stranica ",
+ hu="oldal ",
+ it="pagina ",
+ kr="쪽",
+ la="",
+ lt="puslapis ",
+ nb="side ",
+ nl="pagina ",
+ nn="side ",
+ pl="strona ",
+ pt="",
+ ro="",
+ ru="страница ",
+ sk="strana ",
+ sl="stran ",
+ sv="Sida ",
+ tk="",
+ tr="",
+ ua="сторінка ",
+ vi="",
+ },
+ },
+ part={
+ labels={
+ af="Deel ",
+ ar="جزء ",
+ ca="Part ",
+ cn={"第","部分"},
+ cs="Část ",
+ da="Del ",
+ de="Teil ",
+ en="Part ",
+ es="Parte ",
+ fi="Osa ",
+ fr="Partie ",
+ gr="Μέρος",
+ hr="Dio ",
+ hu={""," rész"},
+ it="Parte ",
+ ja={"第","パート"},
+ kr={"제","부"},
+ la="Pars ",
+ lt={""," dalis"},
+ nb="Del",
+ nl="Deel ",
+ nn="Del",
+ pl="Część ",
+ pt="Parte ",
+ ro="Partea ",
+ ru="Часть ",
+ sk="Časť ",
+ sl="Del ",
+ sv="Del ",
+ tk="Bölüm",
+ tr="Cilt ",
+ ua="Частина ",
+ vi="Phần ",
+ },
+ },
+ saturday={
+ labels={
+ af="saterdag",
+ ar="السبت",
+ ca="dissabte",
+ cn="星期六",
+ cs="sobota",
+ da="lørdag",
+ de="Samstag",
+ en="Saturday",
+ es="sábado",
+ fi="lauantai",
+ fr="samedi",
+ gr="Σάββατο",
+ hr="subota",
+ hu="szombat",
+ it="sabato",
+ ja="土曜日",
+ kr="토요일",
+ la="Dies Saturni",
+ lt="šeštadienis",
+ nb="lørdag",
+ nl="zaterdag",
+ nn="laurdag",
+ pl="sobota",
+ pt="sábado",
+ ro="sâmbătă",
+ ru="суббота",
+ sk="sobota",
+ sl="sobota",
+ sv="lördag",
+ tk="altynjy gün",
+ tr="cumartesi",
+ ua="субота",
+ vi="thứ bảy",
+ },
+ },
+ section={
+ hidden=true,
+ labels={
+ af="Paragraaf ",
+ ar="فصل ",
+ ca="Secció ",
+ cn={"第","节"},
+ cs="Sekce ",
+ da="",
+ de="",
+ en="",
+ es="Sección ",
+ fi="",
+ fr="Section ",
+ gr="Ενότητα",
+ hr="Odjeljak ",
+ hu="Fejezet ",
+ it="",
+ ja={"第","項"},
+ kr={"제","절"},
+ la="",
+ lt="",
+ nb="",
+ nl="",
+ nn="",
+ pl="Podrozdział ",
+ pt="",
+ ro="",
+ ru="",
+ sk="Sekcia ",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ see={
+ labels={
+ af="",
+ ar="انظر ",
+ ca="",
+ cs="viz ",
+ da="se ",
+ de="siehe ",
+ en="see ",
+ es="ver: ",
+ fi="",
+ fr="cf. ",
+ gr="",
+ hr="vidi ",
+ hu="lásd ",
+ it="cf. ",
+ kr="",
+ la="",
+ lt="žiūrėti ",
+ nb="se ",
+ nl="zie ",
+ nn="sjå ",
+ pl="patrz ",
+ pt="",
+ ro="",
+ ru="см. ",
+ sk="pozri ",
+ sl="glej ",
+ sv="se ",
+ tk="",
+ tr="",
+ ua="див. ",
+ vi="",
+ },
+ },
+ september={
+ labels={
+ af="september",
+ ar="سبتمبر",
+ ["ar-ma"]="شتنبر",
+ ["ar-sy"]="أيلول",
+ ca="setembre",
+ cn="九月",
+ cs="září",
+ da="september",
+ de="September",
+ en="September",
+ es="septiembre",
+ fi="syyskuu",
+ fr="septembre",
+ gr="Σεπτέμβριος",
+ hr="rujna",
+ hu="szeptember",
+ it="settembre",
+ ja="9",
+ kr="9",
+ la="September",
+ lt="rugsėjo",
+ nb="september",
+ nl="september",
+ nn="september",
+ pl="września",
+ pt="setembro",
+ ro="septembrie",
+ ru="сентября",
+ sk="septembra",
+ sl="september",
+ sv="september",
+ tk="sentýabr",
+ tr="eylül",
+ ua="вересня",
+ vi="tháng chín",
+ },
+ },
+ ["september:mnem"]={
+ labels={
+ af="",
+ ca="",
+ cs="září",
+ da="",
+ de="",
+ en="sep",
+ es="sep.",
+ fi="",
+ fr="",
+ gr="",
+ hr="ruj",
+ hu="szep.",
+ it="",
+ la="",
+ lt="sep",
+ nb="sep.",
+ nl="",
+ nn="sep.",
+ pl="wrz.",
+ pt="",
+ ro="",
+ ru="",
+ sk="sept.",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ subsection={
+ hidden=true,
+ labels={
+ af="",
+ ar="فصل أدنى ",
+ ca="Subsecció ",
+ cn="",
+ cs="Podsekce ",
+ da="",
+ de="",
+ en="",
+ es="Subsección ",
+ fi="",
+ fr="Soussection ",
+ gr="Υπόενότητα",
+ hr="Pododjeljak ",
+ hu="Alfejezet ",
+ it="",
+ ja="",
+ la="",
+ lt="",
+ nb="",
+ nl="",
+ nn="",
+ pl="Podpodrozdział ",
+ pt="",
+ ro="",
+ ru="",
+ sk="Podsekcia ",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ subsubsection={
+ hidden=true,
+ labels={
+ af="",
+ ar="فصل أ دنى أدنى ",
+ ca="Subsubsecció ",
+ cn="",
+ cs="Podpodsekce ",
+ da="",
+ de="",
+ en="",
+ es="Subsubsección ",
+ fi="",
+ fr="Soussoussection ",
+ gr="",
+ hr="Podpododjeljak ",
+ hu="Al-alfejezet ",
+ it="",
+ ja="",
+ la="",
+ lt="",
+ nb="",
+ nl="",
+ nn="",
+ pl="",
+ pt="",
+ ro="",
+ ru="",
+ sk="Podpodsekcia ",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ subsubsubsection={
+ hidden=true,
+ labels={
+ af="",
+ ar="فصل أدنى أدنى أدنى ",
+ ca="Subsubsubsecció ",
+ cn="",
+ cs="Podpodpodsekce ",
+ da="",
+ de="",
+ en="",
+ es="Subsubsubsección ",
+ fi="",
+ fr="Soussoussoussection ",
+ gr="",
+ hr="Podpodpododjeljak ",
+ hu="Al-al-alfejezet ",
+ it="",
+ ja="",
+ la="",
+ lt="",
+ nb="",
+ nl="",
+ nn="",
+ pl="", -- not used in Polish
+ pt="",
+ ro="",
+ ru="",
+ sk="Podpodpodsekcia ",
+ sl="",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ sunday={
+ labels={
+ af="sondag",
+ ar="الأحد",
+ ca="diumenge",
+ cn="星期日",
+ cs="neděle",
+ da="søndag",
+ de="Sonntag",
+ en="Sunday",
+ es="domingo",
+ fi="sunnuntai",
+ fr="dimanche",
+ gr="Κυριακή",
+ hr="nedjelja",
+ hu="vasárnap",
+ it="domenica",
+ ja="日曜日",
+ kr="일요일",
+ la="Dies Solis",
+ lt="sekmadienis",
+ nb="søndag",
+ nl="zondag",
+ nn="sundag",
+ pl="niedziela",
+ pt="domingo",
+ ro="duminică",
+ ru="воскресенье",
+ sk="nedeľa",
+ sl="nedelja",
+ sv="söndag",
+ tk="dynç gün",
+ tr="pazar",
+ ua="неділя",
+ vi="chủ nhật",
+ },
+ },
+ table={
+ labels={
+ af="Tabel",
+ ar="جدول ",
+ ca="Taula ",
+ cn="表",
+ cs="Tabulka ",
+ da="Tabel ",
+ de="Tabelle ",
+ en="Table ",
+ es="Tabla ",
+ fi="Taulukko ",
+ fr="Tableau ",
+ gr="Πίνακας",
+ hr="Tablica ",
+ hu={""," táblázat"},
+ it="Tabella ",
+ ja="表",
+ kr="표 ",
+ la="Tabula ",
+ lt={""," lentelė."},
+ nb="Tabell ",
+ nl="Tabel ",
+ nn="Tabell ",
+ pl="Tabela ",
+ pt="Tabela ",
+ ro="Tabelul ",
+ ru="Таблица ",
+ sk="Tabuľka ",
+ sl="Tabela ",
+ sv="Tabell ",
+ tk="Tablisa",
+ tr="Tablo ",
+ ua="Таблиця ",
+ vi="Bảng ",
+ },
+ },
+ thursday={
+ labels={
+ af="donderdag",
+ ar="الخميس",
+ ca="dijous",
+ cn="星期四",
+ cs="čtvrtek",
+ da="torsdag",
+ de="Donnerstag",
+ en="Thursday",
+ es="jueves",
+ fi="torstai",
+ fr="jeudi",
+ gr="Πέμπτη",
+ hr="četvrtak",
+ hu="csütörtök",
+ it="giovedì",
+ ja="木曜日",
+ kr="목요일",
+ la="Dies Iovis",
+ lt="ketvirtadienis",
+ nb="torsdag",
+ nl="donderdag",
+ nn="torsdag",
+ pl="czwartek",
+ pt="quinta-feira",
+ ro="joi",
+ ru="четверг",
+ sk="štvrtok",
+ sl="četrtek",
+ sv="torsdag",
+ tk="dördünji gün",
+ tr="perşembe",
+ ua="четвер",
+ vi="thứ năm",
+ },
+ },
+ tuesday={
+ labels={
+ af="dinsdag",
+ ar="الثلاثاء",
+ ca="dimarts",
+ cn="星期二",
+ cs="úterý",
+ da="tirsdag",
+ de="Dienstag",
+ en="Tuesday",
+ es="martes",
+ fi="tiistai",
+ fr="mardi",
+ gr="Τρίτη",
+ hr="utorak",
+ hu="kedd",
+ it="martedì",
+ ja="火曜日",
+ kr="화요일",
+ la="Dies Martis",
+ lt="antradienis",
+ nb="tirsdag",
+ nl="dinsdag",
+ nn="tysdag",
+ pl="wtorek",
+ pt="terça-feira",
+ ro="marți",
+ ru="вторник",
+ sk="utorok",
+ sl="torek",
+ sv="tisdag",
+ tk="ikinji gün",
+ tr="salı",
+ ua="вівторок",
+ vi="thứ ba",
+ },
+ },
+ wednesday={
+ labels={
+ af="woensdag",
+ ar="الأربعاء",
+ ca="dimecres",
+ cn="星期三",
+ cs="středa",
+ da="onsdag",
+ de="Mittwoch",
+ en="Wednesday",
+ es="miércoles",
+ fi="keskiviikko",
+ fr="mercredi",
+ gr="Τετάρτη",
+ hr="srijeda",
+ hu="szerda",
+ it="mercoledì",
+ ja="水曜日",
+ kr="수요일",
+ la="Dies Mercuri",
+ lt="trečiadienis",
+ nb="onsdag",
+ nl="woensdag",
+ nn="onsdag",
+ pl="środa",
+ pt="quarta-feira",
+ ro="miercuri",
+ ru="среда",
+ sk="streda",
+ sl="sreda",
+ sv="onsdag",
+ tk="üçünji",
+ tr="çarşamba",
+ ua="середа",
+ vi="thứ tư",
+ },
+ },
+ },
+ titles={
+ abbreviations={
+ labels={
+ af="Afkortings",
+ ar="الاختصارات",
+ ca="Abreviacions",
+ cn="缩略语",
+ cs="Zkratky",
+ da="Forkortelser",
+ de="Abkürzungen",
+ en="Abbreviations",
+ es="Abreviaturas",
+ fi="Lyhennyksi",
+ fr="Abréviations",
+ gr="Συντομογραφίες",
+ hr="Kratice",
+ hu="Rövidítések",
+ it="Abbreviazioni",
+ ja="略語",
+ kr="약어",
+ la="Notae",
+ lt="Santrumpos",
+ nb="Forkortelser",
+ nl="Afkortingen",
+ nn="Forkortingar",
+ pl="Wykaz skrótów",
+ pt="Abreviaturas",
+ ro="Abrevieri",
+ ru="Список сокращений",
+ sk="Skratky",
+ sl="Kratice",
+ sv="Förkortningar",
+ tk="Gysgaltmalar",
+ tr="Kısaltmalar",
+ ua="Перелік скорочень",
+ vi="Chữ viết tắt",
+ },
+ },
+ content={
+ labels={
+ af="Inhoud",
+ ar="المحتويات",
+ ca="Índex de continguts",
+ cn="目录",
+ cs="Obsah",
+ da="Indhold",
+ de="Inhalt",
+ en="Contents",
+ es="Contenido",
+ fi="Sisällys",
+ fr="Table des matières",
+ gr="Περιεχόμενα",
+ hr="Sadržaj",
+ hu="Tartalom",
+ it="Indice",
+ ja="目次",
+ kr="목차",
+ la="Quod in libro continetur",
+ lt="Turinys",
+ nb="Innhold",
+ nl="Inhoud",
+ nn="Innhald",
+ pl="Spis treści",
+ pt="Conteúdo",
+ ro="Cuprins",
+ ru="Содержание",
+ sk="Obsah",
+ sl="Kazalo",
+ sv="Innehåll",
+ tk="Mazmuny",
+ tr="Fihrist",
+ ua="Зміст",
+ vi="Mục lục",
+ },
+ },
+ figures={
+ labels={
+ af="Figure",
+ ar="الأشكال",
+ ca="Figures",
+ cn="图形",
+ cs="Seznam obrázků",
+ da="Figurer",
+ de="Abbildungen",
+ en="Figures",
+ es="Figuras",
+ fi="Kuvi",
+ fr="Figures",
+ gr="Σχήματα",
+ hr="Slike",
+ hu="Ábrák",
+ it="Figure",
+ ja="図",
+ kr="그림 ",
+ la="Imagines",
+ lt="Iliustracijos",
+ nb="Figurer",
+ nl="Figuren",
+ nn="Figurar",
+ pl="Ilustracje",
+ pt="Figuras",
+ ro="Figuri",
+ ru="Список иллюстраций",
+ sk="Zoznam obrázkov",
+ sl="Slike",
+ sv="Figurer",
+ tk="Suratlar",
+ tr="Şekiller",
+ ua="Перелік ілюстрацій",
+ vi="Danh sách hình vẽ",
+ },
+ },
+ graphics={
+ labels={
+ af="Grafieke",
+ ar="الرسوم",
+ ca="Gràfiques",
+ cn="图",
+ cs="Seznam grafů",
+ da="Grafik",
+ de="Graphiken",
+ en="Graphics",
+ es="Gráficos",
+ fi="Grafiikkaoi",
+ fr="Graphiques",
+ gr="Γραφικά",
+ hr="Slike",
+ hu="Grafikák",
+ it="Grafici",
+ ja="グラフ",
+ kr="그래픽 ",
+ la="Typi",
+ lt="Graphics",
+ nb="Bilde",
+ nl="Grafieken",
+ nn="Bilete",
+ pl="Grafiki",
+ pt="Gráficos",
+ ro="Grafice",
+ ru="Список графиков",
+ sk="Zoznam grafov",
+ sl="Slike",
+ sv="Grafik",
+ tk="Grafikler",
+ tr="Grafikler",
+ ua="Перелік графіков",
+ vi="Đồ thị",
+ },
+ },
+ index={
+ labels={
+ af="Indeks",
+ ar="الفهرس",
+ ca="Índex alfabètic",
+ cn="索引",
+ cs="Rejstřík",
+ da="Indeks",
+ de="Index",
+ en="Index",
+ es="Índice",
+ fi="Indeksiluku",
+ fr="Index",
+ gr="Ευρετήριο",
+ hr="Indeks",
+ hu="Index",
+ it="Indice",
+ ja="目次",
+ kr="찾아보기",
+ la="Indices",
+ lt="Rodyklė",
+ nb="Register",
+ nl="Index",
+ nn="Register",
+ pl="Indeks",
+ pt="Índice",
+ ro="Index",
+ ru="Алфавитный указатель",
+ sk="Zoznam",
+ sl="Stvarno kazalo",
+ sv="Sakregister",
+ tk="Indeks",
+ tr="İndex",
+ ua="Покажчик",
+ vi="Chỉ số",
+ },
+ },
+ intermezzi={
+ labels={
+ af="Intermezzos",
+ ar="فسح",
+ ca="Intermedis",
+ cn="퉣",
+ cs="Intermezza",
+ da="Intermezzoer",
+ de="Intermezzi",
+ en="Intermezzos",
+ es="Intermedios",
+ fi="Intermezzos",
+ fr="Intermèdes",
+ gr="Παύσεις",
+ hr="Intermeci",
+ hu="Intermezzok",
+ it="Intermezzi",
+ ja="間奏曲",
+ kr="간주곡",
+ la="Intermissa",
+ lt="Intermezzos",
+ nb="Intermesso",
+ nl="Intermezzo's",
+ nn="Intermesso",
+ pl="Intermezza",
+ pt="Intermédios",
+ ro="Intermzzo",
+ ru="Список вставок",
+ sk="Intermezzá",
+ sl="Intermezzi",
+ sv="Intermezzon",
+ tk="Arakesmeler",
+ tr="",
+ ua="Перелік вставок",
+ vi="Intermezzos",
+ },
+ },
+ logos={
+ labels={
+ af="Logos",
+ ar="الشعارات",
+ ca="Logotips",
+ cn="徽贬",
+ cs="Loga",
+ da="Logoer",
+ de="Logos",
+ en="Logos",
+ es="Logotipos",
+ fi="Vertauskuva",
+ fr="Logos",
+ gr="Λογότυπα",
+ hr="Logotipi",
+ hu="Fejlécek",
+ it="Logotipi",
+ ja="理性",
+ kr="이성",
+ la="Typi negotiales",
+ lt="Logos",
+ nb="Logoer",
+ nl="Logo's",
+ nn="Logoar",
+ pl="Znaki",
+ pt="Logotipos",
+ ro="Logo-uri",
+ ru="Логотипы",
+ sk="Logá",
+ sl="Logotipi",
+ sv="Loggor",
+ tk="Logolar",
+ tr="Logolar",
+ ua="Логотипи",
+ vi="Biểu tượng",
+ },
+ },
+ pubs={
+ labels={
+ af="",
+ ca="Referències",
+ cs="Literatura",
+ da="",
+ de="Literatur",
+ en="References",
+ es="Bibliografía",
+ fi="",
+ fr="Bibliographie",
+ gr="",
+ hr="Literatura",
+ hu="Bibliográfia",
+ it="Bibliografia",
+ kr="참고문헌",
+ la="",
+ lt="Literatūra",
+ nb="",
+ nl="Literatuur",
+ nn="",
+ pl="Bibliografia",
+ pt="",
+ ro="",
+ ru="",
+ sk="Literatúra",
+ sl="Literatura",
+ sv="",
+ tk="",
+ tr="",
+ ua="",
+ vi="",
+ },
+ },
+ tables={
+ labels={
+ af="Tabelle",
+ ar="الجداول",
+ ca="Taules",
+ cn="表格",
+ cs="Seznam tabulek",
+ da="Tabeller",
+ de="Tabellen",
+ en="Tables",
+ es="Tablas",
+ fi="Taulukkoj",
+ fr="Tableaux",
+ gr="Πίνακες",
+ hr="Tablice",
+ hu="Táblázatok",
+ it="Tabelle",
+ ja="机",
+ kr="표 ",
+ la="Tabulae",
+ lt="Lentelės",
+ nb="Tabeller",
+ nl="Tabellen",
+ nn="Tabellar",
+ pl="Tabele",
+ pt="Tabelas",
+ ro="Tabele",
+ ru="Список таблиц",
+ sk="Zoznam tabuliek",
+ sl="Tabele",
+ sv="Tabeller",
+ tk="Tablisalar",
+ tr="Tablolar",
+ ua="Перелік таблиць",
+ vi="Danh sách bảng",
+ },
+ },
+ units={
+ labels={
+ af="Eenhede",
+ ar="الوحدات",
+ ca="Unitats",
+ cn="计量单位",
+ cs="Jednotky",
+ da="Enheder",
+ de="Einheiten",
+ en="Units",
+ es="Unidades",
+ fi="Yksiköt",
+ fr="Unités",
+ gr="Μονάδες",
+ hr="Jedinice",
+ hu="Mértékegységek",
+ it="Unità",
+ ja="ユニッツ",
+ kr="측정단위",
+ la="Modi",
+ lt="Units",
+ nb="Enheter",
+ nl="Eenheden",
+ nn="Einingar",
+ pl="Jednostki",
+ pt="Unidades",
+ ro="Unități",
+ ru="Единицы измерения",
+ sk="Jednotky",
+ sl="Enote",
+ sv="Enheter",
+ tk="Birlikler",
+ tr="Birimler",
+ ua="Одиниці виміру",
+ vi="Đơn vị",
+ },
+ },
+ },
+ btx = {
+ ["mastersthesis"] = {
+ labels = {
+ en = "Master's thesis",
+ fr = "Thèse de master (DEA, DESS, master)",
+ de = "Masterarbeit",
+ },
+ },
+ ["phdthesis"] = {
+ labels = {
+ en = "PhD thesis",
+ fr = "Thèse de doctorat",
+ de = "Dissertation",
+ },
+ },
+ ["technicalreport"] = {
+ labels = {
+ en = "Technical report",
+ fr = "Rapport technique",
+ de = "Technischer Bericht",
+ },
+ },
+ --
+ ["editor"] = {
+ labels = {
+ en = "editor",
+ fr = "éditeur",
+ de = "Herausgeber",
+ },
+ },
+ ["editors"] = {
+ labels = {
+ en = "editors",
+ fr = "éditeurs",
+ de = "Herausgeber",
+ },
+ },
+ ["edition"] = {
+ labels = {
+ en = "edition",
+ fr = "édition",
+ de = "Auflage",
+ },
+ },
+ --
+ ["volume"] = {
+ labels = {
+ en = "volume",
+ de = "Band",
+ },
+ },
+ ["Volume"] = {
+ labels = {
+ en = "Volume",
+ de = "Band",
+ },
+ },
+ ["number"] = {
+ labels = {
+ en = "number",
+ fr = "numéro",
+ de = "Numer",
+ },
+ },
+ ["Number"] = {
+ labels = {
+ en = "Number",
+ fr = "Numéro",
+ de = "Numer",
+ },
+ },
+ ["in"] = {
+ labels = {
+ en = "in",
+ fr = "dans",
+ de = "in",
+ },
+ },
+ ["of"] = {
+ labels = {
+ en = "of",
+ fr = "de",
+ de = "von",
+ },
+ },
+ --
+ ["In"] = {
+ labels = {
+ en = "In",
+ fr = "Dans",
+ de = "In",
+ },
+ },
+ --
+ ["p"] = {
+ labels = {
+ en = "p",
+ de = "S",
+ },
+ },
+ ["pp"] = {
+ labels = {
+ en = "pp",
+ de = "S",
+ },
+ },
+ ["pages"] = {
+ labels = {
+ en = "pages",
+ de = "Seiten",
+ },
+ },
+ --
+ ["and"] = {
+ labels = {
+ en = "and",
+ de = "und",
+ },
+ },
+ ["others"] = {
+ labels = {
+ en = "et al.",
+ },
+ },
+ }
+}
+
+local functions = data.labels.functions
+
+functions.asin = functions.arcsin
+functions.acos = functions.arccos
+functions.atan = functions.arctan
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua
new file mode 100644
index 00000000000..93c3c02a8db
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua
@@ -0,0 +1,167 @@
+if not modules then modules = { } end modules ['lang-url'] = {
+ version = 1.001,
+ comment = "companion to lang-url.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char
+local min, max = math.min, math.max
+
+local context = context
+
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+local v_before = variables.before
+local v_after = variables.after
+
+local is_letter = characters.is_letter
+
+--[[
+<p>Hyphenating <l n='url'/>'s is somewhat tricky and a matter of taste. I did
+consider using a dedicated hyphenation pattern or dealing with it by node
+parsing, but the following solution suits as well. After all, we're mostly
+dealing with <l n='ascii'/> characters.</p>
+]]--
+
+local urls = { }
+languages.urls = urls
+
+local characters = utilities.storage.allocate {
+ ["!"] = "before",
+ ['"'] = "before",
+ ["#"] = "before",
+ ["$"] = "before",
+ ["%"] = "before",
+ ["&"] = "before",
+ ["("] = "before",
+ ["*"] = "before",
+ ["+"] = "before",
+ [","] = "before",
+ ["-"] = "before",
+ ["."] = "before",
+ ["/"] = "before",
+ [":"] = "before",
+ [";"] = "before",
+ ["<"] = "before",
+ ["="] = "before",
+ [">"] = "before",
+ ["?"] = "before",
+ ["@"] = "before",
+ ["["] = "before",
+ ["\\"] = "before",
+ ["^"] = "before",
+ ["_"] = "before",
+ ["`"] = "before",
+ ["{"] = "before",
+ ["|"] = "before",
+ ["~"] = "before",
+
+ ["'"] = "after",
+ [")"] = "after",
+ ["]"] = "after",
+ ["}"] = "after",
+}
+
+local mapping = utilities.storage.allocate {
+ -- [utfchar(0xA0)] = "~", -- nbsp (catch)
+}
+
+urls.characters = characters
+urls.mapping = mapping
+urls.lefthyphenmin = 2
+urls.righthyphenmin = 3
+urls.discretionary = nil
+urls.packslashes = false
+
+directives.register("hyphenators.urls.packslashes",function(v)
+ urls.packslashes = v
+end)
+
+local ctx_a = context.a
+local ctx_b = context.b
+local ctx_d = context.d
+local ctx_c = context.c
+local ctx_l = context.l
+local ctx_C = context.C
+local ctx_L = context.L
+
+local function action(hyphenatedurl,str,left,right,disc)
+ --
+ left = max( left or urls.lefthyphenmin, 2)
+ right = min(#str-(right or urls.righthyphenmin)+2,#str)
+ disc = disc or urls.discretionary
+ --
+ local word = nil
+ local prev = nil
+ local pack = urls.packslashes
+ local length = 0
+ --
+ for char in utfcharacters(str) do
+ length = length + 1
+ char = mapping[char] or char
+ if prev == char and prev == "/" then
+ ctx_c(utfbyte(char))
+ elseif char == disc then
+ ctx_d()
+ else
+ if prev == "/" then
+ ctx_d()
+ end
+ local how = characters[char]
+ if how == v_before then
+ word = false
+ ctx_b(utfbyte(char))
+ elseif how == v_after then
+ word = false
+ ctx_a(utfbyte(char))
+ else
+ local letter = is_letter[char]
+ if length <= left or length >= right then
+ if word and letter then
+ ctx_L(utfbyte(char))
+ else
+ ctx_C(utfbyte(char))
+ end
+ elseif word and letter then
+ ctx_l(utfbyte(char))
+ else
+ ctx_c(utfbyte(char))
+ end
+ word = letter
+ end
+ end
+ if pack then
+ prev = char
+ end
+ end
+end
+
+-- urls.action = function(_,...) action(...) end -- sort of obsolete
+
+table.setmetatablecall(hyphenatedurl,action) -- watch out: a caller
+
+-- todo, no interface in mkiv yet
+
+function urls.setcharacters(str,value) -- 1, 2 == before, after
+ for s in utfcharacters(str) do
+ characters[s] = value or v_before
+ end
+end
+
+-- .urls.setcharacters("')]}",2)
+
+implement {
+ name = "sethyphenatedurlcharacters",
+ actions = urls.setcharacters,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "hyphenatedurl",
+ scope = "private",
+ actions = function(...) action(hyphenatedurl,...) end,
+ arguments = { "string", "integer", "integer", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-url.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-url.mkiv
new file mode 100644
index 00000000000..833a583f9f0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-url.mkiv
@@ -0,0 +1,172 @@
+%D \module
+%D [ file=lang-url,
+%D version=2008.01.22, % used to be lang-mis
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Options,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{lang-url}{1.001}
+
+\unprotect
+
+%D Traditionally this code is in the language namespace as
+%D hyphenation relates to languages.
+
+%D \macros
+%D {hyphenatedurl}
+%D
+%D For those who want to put full \URL's in a text, we offer
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://optimist.optimist/optimist/optimist.optimist#optimist}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which breaks at the appropriate places. Watch the \type{#}
+%D hack.
+%D
+%D When passed as argument, like in \type {\goto}, one needs
+%D to substitute a \type {\\} for each \type{#}.
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://this.is.a.rather/strange/reference#indeed}
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\newtoks\everyhyphenatedurl
+
+\appendtoks
+ \resetfontfeature
+ \resetcharacterspacing
+ %
+ \let\&\letterampersand
+ \let\#\letterhash
+ \let\~\lettertilde
+ \let\\\letterbackslash
+ \let\$\letterdollar
+ \let\^\letterhat
+ \let\_\letterunderscore
+ \let\{\letterleftbrace
+ \let\}\letterrightbrace
+ \let\|\letterbar
+ \let~=\lettertilde
+ \let|=\letterbar
+ \let\Ux\eUx
+\to \everyhyphenatedurl
+
+\let\hyphenatedurlseparator \empty % \periodcentered
+\let\hyphenatedurldiscretionary\empty
+
+\setnewconstant\hyphenatedurllefthyphenmin \plusthree
+\setnewconstant\hyphenatedurlrighthyphenmin\plusthree
+
+\def\lang_url_more{\penalty\plustenthousand\hskip\scratchskipone\penalty\plustenthousand}
+\def\lang_url_less{\penalty\plustenthousand\hskip\scratchskiptwo\penalty\plustenthousand}
+\def\lang_url_trac{\penalty\plustenthousand\hsmash{\darkred\vl}\penalty\plustenthousand}
+
+\def\lang_url_a#1{\lang_url_more\char#1\lang_url_show\discretionary{}{\hyphenatedurlseparator}{}}
+\def\lang_url_b#1{\lang_url_more\discretionary{\hyphenatedurlseparator}{}{}\lang_url_show\char#1\relax}
+\def\lang_url_d {\lang_url_more\discretionary{\lang_url_show}{\lang_url_show}{\lang_url_show}}
+\def\lang_url_l#1{\lang_url_less\char#1\relax}
+\def\lang_url_c#1{\lang_url_more\char#1\relax}
+\def\lang_url_L#1{\lang_url_less\char#1\relax}
+\def\lang_url_C#1{\lang_url_more\char#1\relax}
+
+\unexpanded\def\showhyphenatedurlbreaks % for old times sake
+ {\let\lang_url_show\lang_url_trac}
+
+\installtextracker
+ {languages.url}
+ {\let\lang_url_show\lang_url_trac}
+ {\let\lang_url_show\relax}
+
+\let\lang_url_show\relax
+
+\unexpanded\def\sethyphenatedurlnormal#1{\clf_sethyphenatedurlcharacters{#1}{\v!normal}}
+\unexpanded\def\sethyphenatedurlbefore#1{\clf_sethyphenatedurlcharacters{#1}{\v!before}}
+\unexpanded\def\sethyphenatedurlafter #1{\clf_sethyphenatedurlcharacters{#1}{\v!after }}
+
+% \sethyphenatedurlafter{ABCDEF}
+
+\unexpanded\def\hyphenatedurl#1%
+ {\dontleavehmode
+ \begingroup
+ \the\everyhyphenatedurl
+ \normallanguage\zerocount
+ \let\a\lang_url_a % after
+ \let\b\lang_url_b % before
+ \let\d\lang_url_d % disc
+ \let\l\lang_url_l % letter
+ \let\c\lang_url_c % character
+ \let\L\lang_url_L % letter_nobreak
+ \let\C\lang_url_C % character_nobreak
+ \scratchskipone\zeropoint\s!plus\dimexpr\emwidth/12\s!minus\dimexpr\emwidth/24\relax % 1.00pt @ 12pt
+ \scratchskiptwo\zeropoint\s!plus\dimexpr\emwidth/48\s!minus\dimexpr\emwidth/96\relax % 0.25pt @ 12pt
+ \normalexpanded{\noexpand\clf_hyphenatedurl
+ {\noexpand\detokenize{#1}}%
+ \hyphenatedurllefthyphenmin
+ \hyphenatedurlrighthyphenmin
+ {\hyphenatedurldiscretionary}%
+ }%
+ \endgroup}
+
+%D \macros
+%D {hyphenatedfilename}
+%D
+%D For the moment we treat filenames in a similar way,
+%D
+%D \starttyping
+%D \hyphenatedfilename{here/there/filename.suffix}
+%D \stoptyping
+
+\ifx\hyphenatedfilename\undefined \let\hyphenatedfilename\hyphenatedurl \fi
+
+% \def\test#1%
+% {\dontleavehmode
+% \begingroup
+% \tttf
+% \hyphenatedurl {%
+% \letterampersand #1\letterampersand #1\letterampersand #1\letterampersand #1\letterampersand
+% \letterhash #1\letterhash #1\letterpercent #1\letterslash #1\letterampersand
+% }%
+% \endgroup}
+
+% \dorecurse{100}{\test{a} \test{ab} \test{abc} \test{abcd} \test{abcde} \test{abcdef}}
+
+\protect \endinput
+
+% \setuppapersize[A7]
+%
+% \unexpanded\def\WhateverA#1%
+% {\dontleavehmode
+% \begingroup
+% \prehyphenchar"B7\relax
+% \setbox\scratchbox\hbox{\tttf#1}%
+% \prehyphenchar`-\relax
+% \unhbox\scratchbox
+% \endgroup}
+%
+% \unexpanded\def\WhateverB#1%
+% {\dontleavehmode
+% \begingroup
+% \tttf
+% \prehyphenchar\minusone
+% % \localrightbox{\llap{_}}%
+% \localrightbox{\llap{\smash{\lower1.5ex\hbox{\char"2192}}}}%
+% \setbox\scratchbox\hbox{#1}%
+% \prehyphenchar`-\relax
+% \unhbox\scratchbox
+% \endgroup}
+%
+% \begingroup \hsize1cm
+% \WhateverA{thisisaboringandverylongcommand}\par
+% \WhateverB{thisisaboringandverylongcommand}\par
+% \endgroup
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua
new file mode 100644
index 00000000000..38e6187af5b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua
@@ -0,0 +1,413 @@
+if not modules then modules = { } end modules ['lang-wrd'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lower = string.lower
+local utfchar = utf.char
+local concat, setmetatableindex = table.concat, table.setmetatableindex
+local lpegmatch = lpeg.match
+local P, S, Cs, Cf, Cg, Cc, C = lpeg.P, lpeg.S, lpeg.Cs, lpeg.Cf, lpeg.Cg, lpeg.Cc, lpeg.C
+
+local report_words = logs.reporter("languages","words")
+
+local nodes = nodes
+local languages = languages
+
+local implement = interfaces.implement
+
+languages.words = languages.words or { }
+local words = languages.words
+
+words.data = words.data or { }
+words.enables = false
+words.threshold = 4
+
+local numbers = languages.numbers
+local registered = languages.registered
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local setattr = nuts.setattr
+local isglyph = nuts.isglyph
+
+local traverse_nodes = nuts.traverse
+local traverse_ids = nuts.traverse_id
+
+local wordsdata = words.data
+local chardata = characters.data
+local tasks = nodes.tasks
+
+local unsetvalue = attributes.unsetvalue
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+
+local kerning_code = kerncodes.kerning
+local lowerchar = characters.lower
+
+local a_color = attributes.private('color')
+local colist = attributes.list[a_color]
+
+local is_letter = characters.is_letter -- maybe is_character as variant
+
+local spacing = S(" \n\r\t")
+local markup = S("-=") / ""
+local lbrace = P("{") / ""
+local rbrace = P("}") / ""
+local snippet = lbrace * (1-rbrace)^0 * rbrace
+local disc = snippet/"" -- pre
+ * snippet/"" -- post
+ * snippet -- replace
+local word = Cs((markup + disc + (1-spacing))^1)
+
+-- lpegmatch((spacing + word/function(s) print(s) end)^0,"foo foo-bar bar{}{}{}foo bar{}{}{foo}")
+
+local loaded = { } -- we share lists
+local loaders = {
+ txt = function(list,fullname)
+ local data = io.loaddata(fullname)
+ if data and data ~= "" then
+ local parser = (spacing + word/function(s) list[s] = true end)^0
+ -- local parser = Cf(Cc(list) * Cg(spacing^0 * word * Cc(true))^1,rawset) -- not better
+ lpegmatch(parser,data)
+ end
+ end,
+ lua = function(list,fullname)
+ local data = dofile(fullname)
+ if data and type(data) == "table" then
+ local words = data.words
+ if words then
+ for k, v in next, words do
+ list[k] = true
+ end
+ end
+ end
+ end,
+}
+
+loaders.luc = loaders.lua
+
+function words.load(tag,filename)
+ local fullname = resolvers.findfile(filename,'other text file') or ""
+ if fullname ~= "" then
+ report_words("loading word file %a",fullname)
+ statistics.starttiming(languages)
+ local list = loaded[fullname]
+ if not list then
+ list = wordsdata[tag] or { }
+ local suffix = file.suffix(fullname)
+ local loader = loaders[suffix] or loaders.txt
+ loader(list,fullname)
+ loaded[fullname] = list
+ end
+ wordsdata[tag] = list
+ statistics.stoptiming(languages)
+ else
+ report_words("missing word file %a",filename)
+ end
+end
+
+function words.found(id, str)
+ local tag = languages.numbers[id]
+ if tag then
+ local data = wordsdata[tag]
+ if data then
+ if data[str] then
+ return 1
+ elseif data[lower(str)] then
+ return 2
+ end
+ end
+ end
+end
+
+-- The following code is an adaption of experimental code for hyphenating and
+-- spell checking.
+
+-- there is an n=1 problem somewhere in nested boxes
+
+local function mark_words(head,whenfound) -- can be optimized and shared
+ local current, language, done = tonut(head), nil, nil, 0, false
+ 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
+ end
+ end
+ n, s = 0, 0
+ end
+ -- we haven't done the fonts yet so we have characters (otherwise
+ -- we'd have to use the tounicodes)
+ while current do
+ local code, id = isglyph(current)
+ if code then
+ local a = getfield(current,"lang")
+ if a then
+ if a ~= language then
+ if s > 0 then
+ action()
+ end
+ language = a
+ end
+ elseif s > 0 then
+ action()
+ language = a
+ end
+ local data = chardata[code]
+ if is_letter[data.category] then
+ n = n + 1
+ nds[n] = current
+ s = s + 1
+ str[s] = utfchar(code)
+ elseif s > 0 then
+ action()
+ end
+ elseif id == disc_code then -- take the replace
+ if n > 0 then
+ local r = getfield(current,"replace")
+ if r then
+ for current in traverse_ids(glyph_code,r) do
+ local code = getchar(current)
+ n = n + 1
+ nds[n] = current
+ s = s + 1
+ str[s] = utfchar(code)
+ end
+ end
+ end
+ elseif id == kern_code and getsubtype(current) == kerning_code and s > 0 then
+ -- ok
+ elseif s > 0 then
+ action()
+ end
+ current = getnext(current)
+ end
+ if s > 0 then
+ action()
+ end
+ return head, done
+end
+
+local methods = { }
+words.methods = methods
+
+local enablers = { }
+words.enablers = enablers
+
+local wordmethod = 1
+local enabled = false
+
+function words.check(head)
+ if enabled then
+ return methods[wordmethod](head)
+ elseif not head then
+ return head, false
+ else
+ return head, false
+ end
+end
+
+function words.enable(settings)
+ local method = settings.method
+ wordmethod = method and tonumber(method) or wordmethod or 1
+ local e = enablers[wordmethod]
+ if e then
+ e(settings)
+ end
+ tasks.enableaction("processors","languages.words.check")
+ enabled = true
+end
+
+function words.disable()
+ enabled = false
+end
+
+-- colors
+
+local cache = { } -- can also be done with method 1 -- frozen colors once used
+
+table.setmetatableindex(cache, function(t,k) -- k == language, numbers[k] == tag
+ local c
+ if type(k) == "string" then
+ c = colist[k]
+ elseif k < 0 then
+ c = colist["word:unset"]
+ else
+ c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"]
+ end
+ local v = c and function(n) setattr(n,a_color,c) end or false
+ t[k] = v
+ return v
+end)
+
+-- method 1
+
+local function sweep(language,str)
+ if #str < words.threshold then
+ return false
+ elseif words.found(language,str) then -- can become a local wordsfound
+ return cache["word:yes"] -- maybe variables.yes
+ else
+ return cache["word:no"]
+ end
+end
+
+methods[1] = function(head)
+ for n in traverse_nodes(head) do
+ setattr(n,a_color,unsetvalue) -- hm, not that selective (reset color)
+ end
+ return mark_words(head,sweep)
+end
+
+-- method 2
+
+local dumpname = nil
+local dumpthem = false
+local listname = "document"
+
+local category = { }
+
+local categories = setmetatableindex(function(t,k)
+ local languages = setmetatableindex(function(t,k)
+ local r = registered[k]
+ local v = {
+ number = language,
+ parent = r and r.parent or nil,
+ patterns = r and r.patterns or nil,
+ tag = r and r.tag or nil,
+ list = { },
+ total = 0,
+ unique = 0,
+ }
+ t[k] = v
+ return v
+ end)
+ local v = {
+ languages = languages,
+ total = 0,
+ }
+ t[k] = v
+ return v
+end)
+
+local collected = {
+ total = 0,
+ version = 1.000,
+ categories = categories,
+}
+
+enablers[2] = function(settings)
+ local name = settings.list
+ listname = name and name ~= "" and name or "document"
+ category = collected.categories[listname]
+end
+
+local function sweep(language,str)
+ if #str >= words.threshold then
+ str = lowerchar(str)
+ local words = category.languages[numbers[language] or "unset"]
+ local list = words.list
+ local ls = list[str]
+ if ls then
+ list[str] = ls + 1
+ else
+ list[str] = 1
+ words.unique = words.unique + 1
+ end
+ collected.total = collected.total + 1
+ category.total = category.total + 1
+ words.total = words.total + 1
+ end
+end
+
+methods[2] = function(head)
+ dumpthem = true
+ return mark_words(head,sweep)
+end
+
+local function dumpusedwords()
+ if dumpthem then
+ collected.threshold = words.threshold
+ dumpname = dumpname or file.addsuffix(tex.jobname,"words")
+ report_words("saving list of used words in %a",dumpname)
+ io.savedata(dumpname,table.serialize(collected,true))
+ -- table.tofile(dumpname,list,true)
+ end
+end
+
+directives.register("languages.words.dump", function(v)
+ dumpname = (type(v) == "string" and v ~= "" and v) or dumpname
+end)
+
+luatex.registerstopactions(dumpusedwords)
+
+-- method 3
+
+local function sweep(language,str)
+ return cache[language]
+end
+
+methods[3] = function(head)
+ for n in traverse_nodes(head) do
+ setattr(n,a_color,unsetvalue)
+ end
+ return mark_words(head,sweep)
+end
+
+-- for the moment we hook it into the attribute handler
+
+-- languagehacks = { }
+
+-- function languagehacks.process(namespace,attribute,head)
+-- return languages.check(head)
+-- end
+
+-- chars.plugins[chars.plugins+1] = {
+-- name = "language",
+-- namespace = languagehacks,
+-- processor = languagehacks.process
+-- }
+
+-- interface
+
+implement {
+ name = "enablespellchecking",
+ actions = words.enable,
+ arguments = {
+ {
+ { "method" },
+ { "list" }
+ }
+ }
+}
+
+implement {
+ name = "disablespellchecking",
+ actions = words.disable
+}
+
+implement {
+ name = "loadspellchecklist",
+ arguments = { "string", "string" },
+ actions = words.load
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.mkiv
new file mode 100644
index 00000000000..8c544773b3a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=lang-wrd,
+%D version=2006.XX.XX,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Experimental.
+
+\writestatus{loading}{ConTeXt Language Macros / Checking}
+
+\registerctxluafile{lang-wrd}{1.001}
+
+\unprotect
+
+% \loadspellchecklist[en][words-en.txt]
+% \loadspellchecklist[us][words-en.txt]
+% \loadspellchecklist[nl][words-nl.txt]
+% \setupspellchecking[state=start,method=1]
+%
+% \setupspellchecking[state=start,method=2]
+% ...
+% \typefile{\jobname.words}
+%
+% beware, maybe some day we will honour grouping
+%
+% 1: spell checking
+% 2: word counting
+% 3: language coloring
+
+\installcorenamespace{spell}
+
+\installdirectcommandhandler \??spell {spellchecking}
+
+\appendtoks
+ \doifelse{\directspellcheckingparameter\c!state}\v!start
+ {\clf_enablespellchecking
+ method {\directspellcheckingparameter\c!method}%
+ list {\directspellcheckingparameter\c!list}%
+ \relax}
+ {\clf_disablespellchecking}%
+\to \everysetupspellchecking
+
+\unexpanded\def\loadspellchecklist
+ {\dodoubleempty\lang_spellchecking_load_list}
+
+\def\lang_spellchecking_load_list[#1][#2]%
+ {\clf_loadspellchecklist{#1}{#2}}
+
+\setupspellchecking
+ [\c!state=\v!stop,
+ \c!method=1,
+ \c!list=]
+
+\definecolor[word:yes] [g=.75]
+\definecolor[word:no] [r=.75]
+
+%definecolor[word:unset] [s=.75]
+\definecolor[word:en] [b=.75]
+\definecolor[word:de] [r=.75]
+\definecolor[word:nl] [g=.75]
+\definecolor[word:unknown][r=.75,g=.75]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/layo-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/layo-ini.lua
new file mode 100644
index 00000000000..d35d7ef6965
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/layo-ini.lua
@@ -0,0 +1,54 @@
+if not modules then modules = { } end modules ['layo-ini'] = {
+ version = 1.001,
+ comment = "companion to layo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We need to share information between the TeX and Lua end about the typographical
+-- model. This happens here. This code might move.
+
+local texgetcount = tex.getcount
+local conditionals = tex.conditionals
+
+layouts = {
+ status = { },
+}
+
+local status = layouts.status
+
+function status.leftorrightpagection(left,right)
+ if left == nil then
+ left, right = false, true
+ end
+ if not conditionals.layoutisdoublesided then
+ return left, right
+ elseif conditionals.layoutissinglesided then
+ return left, right
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ if texgetcount("realpageno") % 2 == 0 then
+ return right, left
+ else
+ return left, right
+ end
+ else
+ if texgetcount("realpageno") % 2 == 0 then
+ return left, right
+ else
+ return right, left
+ end
+ end
+end
+
+function status.isleftpage()
+ if not conditionals.layoutisdoublesided then
+ return false
+ elseif conditionals.layoutissinglesided then
+ return false
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ return texgetcount("realpageno") % 2 == 0
+ else
+ return not texgetcount("realpageno") % 2 == 0
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/layo-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/layo-ini.mkiv
new file mode 100644
index 00000000000..9097265c9c4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/layo-ini.mkiv
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=layo-ini,
+%D version=2011.02.18,
+%D title=\CONTEXT\ Layout 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 Layout Macros / Initialization}
+
+%D This module deals with the basic variables etc. for layout
+%D and code from other modules will move here. This will make
+%D the dependencies somewhat cleaner.
+
+\unprotect
+
+%D We need to check this in case a smaller format is loaded.
+
+\ifdefined\layoutisdoublesided \else \newconditional\layoutisdoublesided \fi
+\ifdefined\layoutissinglesided \else \newconditional\layoutissinglesided \fi
+\ifdefined\pagenoshift \else \newcount \pagenoshift \fi
+\ifdefined\realpageno \else \newcount \realpageno \fi
+
+\registerctxluafile{layo-ini}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
new file mode 100644
index 00000000000..72800bc648c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
@@ -0,0 +1,1271 @@
+if not modules then modules = { } end modules ['lpdf-ano'] = {
+ 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"
+}
+
+-- when using rotation: \disabledirectives[refences.sharelinks] (maybe flag links)
+
+-- todo: /AA << WC << ... >> >> : WillClose actions etc
+
+-- internal references are indicated by a number (and turned into <autoprefix><number>)
+-- we only flush internal destinations that are referred
+
+local next, tostring, tonumber, rawget = next, tostring, tonumber, rawget
+local rep, format, find = string.rep, string.format, string.find
+local min = math.min
+local lpegmatch = lpeg.match
+local formatters = string.formatters
+
+local backends, lpdf = backends, lpdf
+
+local trace_references = false trackers.register("references.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("references.destinations", function(v) trace_destinations = v end)
+local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end)
+
+local log_destinations = false directives.register("destinations.log", function(v) log_destinations = v end)
+
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_bookmark = logs.reporter("backend","bookmarks")
+
+local variables = interfaces.variables
+local v_auto = variables.auto
+local v_page = variables.page
+local v_name = variables.name
+
+local factor = number.dimenfactors.bp
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+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
+local bookmarks = structures.bookmarks
+
+local flaginternals = references.flaginternals
+local usedinternals = references.usedinternals
+local usedviews = references.usedviews
+
+local runners = references.runners
+local specials = references.specials
+local handlers = references.handlers
+local executers = references.executers
+
+local nodepool = nodes.pool
+
+----- pdfannotation_node = nodepool.pdfannotation
+----- pdfdestination_node = nodepool.pdfdestination
+----- latelua_node = nodepool.latelua
+local latelua_function_node = nodepool.lateluafunction -- still node ... todo
+
+local texgetcount = tex.getcount
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfconstant = lpdf.constant
+local pdfflushobject = lpdf.flushobject
+local pdfshareobjectreference = lpdf.shareobjectreference
+local pdfreserveobject = lpdf.reserveobject
+local pdfpagereference = lpdf.pagereference
+local pdfdelayedobject = lpdf.delayedobject
+local pdfregisterannotation = lpdf.registerannotation -- forward definition (for the moment)
+local pdfnull = lpdf.null
+local pdfaddtocatalog = lpdf.addtocatalog
+local pdfaddtonames = lpdf.addtonames
+local pdfaddtopageattributes = lpdf.addtopageattributes
+local pdfrectangle = lpdf.rectangle
+
+-- todo: 3dview
+
+local pdf_annot = pdfconstant("Annot")
+local pdf_uri = pdfconstant("URI")
+local pdf_gotor = pdfconstant("GoToR")
+local pdf_goto = pdfconstant("GoTo")
+local pdf_launch = pdfconstant("Launch")
+local pdf_javascript = pdfconstant("JavaScript")
+local pdf_link = pdfconstant("Link")
+local pdf_n = pdfconstant("N")
+local pdf_t = pdfconstant("T")
+local pdf_fit = pdfconstant("Fit")
+local pdf_named = pdfconstant("Named")
+
+local autoprefix = "#"
+
+-- 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
+-- is used. Also, we default to a non-intrusive gray and the outline is kept
+-- 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 function pdfborder()
+ set_border = true
+ return pdf_border_style, pdf_border_color
+end
+
+lpdf.border = pdfborder
+
+directives.register("references.border",function(v)
+ if v and not set_border then
+ if type(v) == "string" then
+ local m = attributes.list[attributes.private('color')] or { }
+ 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]
+ -- if r == g and g == b then
+ -- pdf_border_color = pdfarray { r } -- reduced, not not ... bugged viewers
+ -- else
+ pdf_border_color = pdfarray { r, g, b } -- always rgb
+ -- end
+ end
+ end
+ if not pdf_border_color then
+ pdf_border_color = pdfarray { .6, .6, .6 } -- no reduce to { 0.6 } as there are buggy viewers out there
+ end
+ pdf_border_style = pdfarray { 0, 0, .5 } -- < 0.5 is not show by acrobat (at least not in my version)
+ end
+end)
+
+-- the used and flag code here is somewhat messy in the sense
+-- that it belongs in strc-ref but at the same time depends on
+-- the backend so we keep it here
+
+-- the caching is somewhat memory intense on the one hand but
+-- it saves many small temporary tables so it might pay off
+
+local pagedestinations = setmetatableindex(function(t,k)
+ k = tonumber(k)
+ if not k or k <= 0 then
+ return pdfnull()
+ end
+ local v = rawget(t,k)
+ if v then
+ -- report_reference("page number expected, got %s: %a",type(k),k)
+ return v
+ end
+ local v = k > 0 and pdfarray {
+ pdfreference(pdfpagereference(k)),
+ pdf_fit,
+ } or pdfnull()
+ t[k] = v
+ return v
+end)
+
+local pagereferences = setmetatableindex(function(t,k)
+ k = tonumber(k)
+ if not k or k <= 0 then
+ return nil
+ end
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ local v = pdfdictionary { -- can be cached
+ S = pdf_goto,
+ D = pagedestinations[k],
+ }
+ t[k] = v
+ return v
+end)
+
+local defaultdestination = pdfarray { 0, pdf_fit }
+
+-- fit is default (see lpdf-nod)
+
+local destinations = { } -- to be used soon
+
+local function pdfregisterdestination(name,reference)
+ local d = destinations[name]
+ if d then
+ report_destination("ignoring duplicate destination %a with reference %a",name,reference)
+ else
+ destinations[name] = reference
+ end
+end
+
+lpdf.registerdestination = pdfregisterdestination
+
+local maxslice = 32 -- could be made configureable ... 64 is also ok
+
+luatex.registerstopactions(function()
+ if log_destinations and next(destinations) then
+ local logsnewline = logs.newline
+ local log_destinations = logs.reporter("system","references")
+ local log_destination = logs.reporter("destination")
+ logs.pushtarget("logfile")
+ logsnewline()
+ log_destinations("start used destinations")
+ logsnewline()
+ local n = 0
+ for destination, pagenumber in table.sortedhash(destinations) do
+ log_destination("% 4i : %-5s : %s",pagenumber,usedviews[destination] or defaultview,destination)
+ n = n + 1
+ end
+ logsnewline()
+ log_destinations("stop used destinations")
+ logsnewline()
+ logs.poptarget()
+ report_destination("%s destinations saved in log file",n)
+ end
+end)
+
+
+local function pdfnametree(destinations)
+ local slices = { }
+ local sorted = table.sortedkeys(destinations)
+ local size = #sorted
+
+ if size <= 1.5*maxslice then
+ maxslice = size
+ end
+
+ for i=1,size,maxslice do
+ local amount = min(i+maxslice-1,size)
+ local names = pdfarray { }
+ 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)
+ end
+ local first = sorted[i]
+ local last = sorted[amount]
+ local limits = pdfarray {
+ first,
+ last,
+ }
+ local d = pdfdictionary {
+ Names = names,
+ Limits = limits,
+ }
+ slices[#slices+1] = {
+ reference = pdfreference(pdfflushobject(d)),
+ limits = limits,
+ }
+ 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
+ end
+ return d
+ end
+ if #slices == 1 then
+ return slices[1].reference
+ else
+ while true do
+ if #slices > maxslice then
+ local temp = { }
+ 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,
+ }
+ end
+ slices = temp
+ else
+ return pdfreference(pdfflushobject(collectkids(slices,1,#slices)))
+ end
+ end
+ end
+end
+
+local function pdfdestinationspecification()
+ if next(destinations) then -- safeguard
+ local r = pdfnametree(destinations)
+ -- pdfaddtocatalog("Dests",r)
+ pdfaddtonames("Dests",r)
+ if not log_destinations then
+ destinations = nil
+ end
+ end
+end
+
+lpdf.nametree = pdfnametree
+lpdf.destinationspecification = pdfdestinationspecification
+
+lpdf.registerdocumentfinalizer(pdfdestinationspecification,"collect destinations")
+
+-- todo
+
+local destinations = { }
+
+local f_xyz = formatters["<< /D [ %i 0 R /XYZ %0.3F %0.3F 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 v_standard = variables.standard
+local v_frame = variables.frame
+local v_width = variables.width
+local v_minwidth = variables.minwidth
+local v_height = variables.height
+local v_minheight = variables.minheight
+local v_fit = variables.fit
+local v_tight = variables.tight
+
+-- nicer is to create dictionaries and set properties but it's a bit overkill
+
+-- The problem with the following settings is that they are guesses: we never know
+-- if a box is part of something larger that needs to be in view, or that we are
+-- dealing with a vbox or vtop so the used h/d values cannot be trusted in a tight
+-- view. Of course some decent additional offset would be nice so maybe i'll add
+-- that some day. I never use anything else than 'fit' anyway as I think that the
+-- document should fit the device (and vice versa). In fact, with todays swipe
+-- and finger zooming this whole view is rather useless and as with any zooming
+-- one looses the overview and keeps zooming.
+
+-- todo: scaling
+
+-- local destinationactions = {
+-- [v_standard] = function(r,w,h,d) return f_xyz (r,gethpos()*factor,(getvpos()+h)*factor) end, -- local left,top with no zoom
+-- [v_frame] = function(r,w,h,d) return f_fitr (r,pdfrectangle(w,h,d)) end, -- fit rectangle in window
+-- [v_width] = function(r,w,h,d) return f_fith (r,(getvpos()+h)*factor) end, -- top coordinate, fit width of page in window
+-- [v_minwidth] = function(r,w,h,d) return f_fitbh(r,(getvpos()+h)*factor) end, -- top coordinate, fit width of content in window
+-- [v_height] = function(r,w,h,d) return f_fitv (r,gethpos()*factor) end, -- left coordinate, fit height of page in window
+-- [v_minheight] = function(r,w,h,d) return f_fitbv(r,gethpos()*factor) end, -- left coordinate, fit height of content in window [v_fit] = f_fit, -- fit page in window
+-- [v_tight] = f_fitb, -- fit content in window
+-- [v_fit] = f_fit,
+-- }
+
+local destinationactions = {
+ [v_standard] = function(r,w,h,d,o) -- local left,top with no zoom
+ local tx, ty = getpos()
+ return f_xyz(r,tx*factor,(ty+h+2*o)*factor) -- we can assume margins
+ end,
+ [v_frame] = function(r,w,h,d,o) -- fit rectangle in window
+ return f_fitr(r,pdfrectangle(w,h,d,o))
+ end,
+ [v_width] = function(r,w,h,d,o) -- top coordinate, fit width of page in window
+ return f_fith(r,(getvpos()+h+o)*factor)
+ end,
+ [v_minwidth] = function(r,w,h,d,o) -- top coordinate, fit width of content in window
+ return f_fitbh(r,(getvpos()+h+o)*factor)
+ end,
+ [v_height] = function(r,w,h,d,o) -- left coordinate, fit height of page in window
+ return f_fitv(r,(gethpos())*factor)
+ end,
+ [v_minheight] = function(r,w,h,d,o) -- left coordinate, fit height of content in window
+ return f_fitbv(r,(gethpos())*factor)
+ end,
+ [v_tight] = f_fitb, -- fit content in window
+ [v_fit] = f_fit, -- fit content in window
+}
+
+local mapping = {
+ [v_standard] = v_standard, xyz = v_standard,
+ [v_frame] = v_frame, fitr = v_frame,
+ [v_width] = v_width, fith = v_width,
+ [v_minwidth] = v_minwidth, fitbh = v_minwidth,
+ [v_height] = v_height, fitv = v_height,
+ [v_minheight] = v_minheight, fitbv = v_minheight,
+ [v_fit] = v_fit, fit = v_fit,
+ [v_tight] = v_tight, fitb = v_tight,
+}
+
+local defaultview = v_fit
+local defaultaction = destinationactions[defaultview]
+local offset = 0 -- 65536*5
+
+directives.register("destinations.offset", function(v)
+ offset = string.todimen(v) or 0
+end)
+
+-- A complication is that we need to use named destinations when we have views so we
+-- end up with a mix. A previous versions just output multiple destinations but now
+-- that we moved all to here we can be more sparse.
+
+local pagedestinations = setmetatableindex(function(t,k) -- not the same as the one above!
+ local v = pdfdelayedobject(f_fit(k))
+ t[k] = v
+ return v
+end)
+
+local function flushdestination(width,height,depth,names,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))
+ end
+ for n=1,#names do
+ local name = names[n]
+ if name then
+ pdfregisterdestination(name,r)
+ end
+ end
+end
+
+function nodeinjections.destination(width,height,depth,names,view)
+ -- todo check if begin end node / was comment
+ view = view and mapping[view] or defaultview
+ if trace_destinations then
+ report_destination("width %p, height %p, depth %p, names %|t, view %a",width,height,depth,names,view)
+ end
+ local method = references.innermethod
+ local noview = view == defaultview
+ local doview = false
+ -- we could save some aut's by using a name when given but it doesn't pay off apart
+ -- from making the code messy and tracing hard .. we only save some destinations
+ -- which we already share anyway
+ if method == v_page then
+ for n=1,#names do
+ local name = names[n]
+ local used = usedviews[name]
+ if used and used ~= true then
+ -- already done, maybe a warning
+ elseif type(name) == "number" then
+ -- if noview then
+ -- usedviews[name] = view
+ -- names[n] = false
+ -- else
+ usedviews[name] = view
+ names[n] = false
+ -- end
+ else
+ usedviews[name] = view
+ end
+ end
+ elseif method == v_name then
+ for n=1,#names do
+ local name = names[n]
+ local used = usedviews[name]
+ if used and used ~= true then
+ -- already done, maybe a warning
+ elseif type(name) == "number" then
+ local used = usedinternals[name]
+ usedviews[name] = view
+ names[n] = autoprefix .. name
+ doview = true
+ else
+ usedviews[name] = view
+ doview = true
+ end
+ end
+ else
+ for n=1,#names do
+ local name = names[n]
+ if usedviews[name] then
+ -- already done, maybe a warning
+ elseif type(name) == "number" then
+ if noview then
+ usedviews[name] = view
+ names[n] = false
+ else
+ local used = usedinternals[name]
+ if used and used ~= defaultview then
+ usedviews[name] = view
+ names[n] = autoprefix .. name
+ doview = true
+ else
+ -- names[n] = autoprefix .. name
+ names[n] = false
+ end
+ end
+ else
+ usedviews[name] = view
+ doview = true
+ end
+ end
+ end
+ if doview then
+ return latelua_function_node(function() flushdestination(width,height,depth,names,view) end)
+ end
+end
+
+-- we could share dictionaries ... todo
+
+local function pdflinkpage(page)
+ return pagereferences[page]
+end
+
+local function pdflinkinternal(internal,page)
+ local method = references.innermethod
+ if internal then
+ flaginternals[internal] = true -- for bookmarks and so
+ local used = usedinternals[internal]
+ if used == defaultview or used == true then
+ return pagereferences[page]
+ else
+ if type(internal) ~= "string" then
+ internal = autoprefix .. internal
+ end
+ return pdfdictionary {
+ S = pdf_goto,
+ D = internal,
+ }
+ end
+ else
+ return pagereferences[page]
+ end
+end
+
+local function pdflinkname(destination,internal,page)
+ local method = references.innermethod
+ if method == v_auto then
+ local used = defaultview
+ if internal then
+ flaginternals[internal] = true -- for bookmarks and so
+ used = usedinternals[internal] or defaultview
+ end
+ if used == defaultview then -- or used == true then
+ return pagereferences[page]
+ else
+ return pdfdictionary {
+ S = pdf_goto,
+ D = destination,
+ }
+ end
+ elseif method == v_name then
+ -- flaginternals[internal] = true -- for bookmarks and so
+ return pdfdictionary {
+ S = pdf_goto,
+ D = destination,
+ }
+ else
+ return pagereferences[page]
+ end
+end
+
+-- annotations
+
+local function pdffilelink(filename,destination,page,actions)
+ if not filename or filename == "" or file.basename(filename) == tex.jobname then
+ return false
+ end
+ filename = file.addsuffix(filename,"pdf")
+ if not destination or destination == "" then
+ destination = pdfarray { (page or 0) - 1, pdf_fit }
+ end
+ return pdfdictionary {
+ S = pdf_gotor, -- can also be pdf_launch
+ F = filename,
+ D = destination or defaultdestination, -- D is mandate
+ NewWindow = actions.newwindow and true or nil,
+ }
+end
+
+local function pdfurllink(url,destination,page)
+ if not url or url == "" then
+ return false
+ end
+ if destination and destination ~= "" then
+ url = url .. "#" .. destination
+ end
+ return pdfdictionary {
+ S = pdf_uri,
+ URI = url,
+ }
+end
+
+local function pdflaunch(program,parameters)
+ if not program or program == "" then
+ return false
+ end
+ return pdfdictionary {
+ S = pdf_launch,
+ F = program,
+ D = ".",
+ P = parameters ~= "" and parameters or nil
+ }
+end
+
+local function pdfjavascript(name,arguments)
+ local script = javascriptcode(name,arguments) -- make into object (hash)
+ if script then
+ return pdfdictionary {
+ S = pdf_javascript,
+ JS = script,
+ }
+ end
+end
+
+local function pdfaction(actions)
+ local nofactions = #actions
+ if nofactions > 0 then
+ local a = actions[1]
+ local action = runners[a.kind]
+ if action then
+ action = action(a,actions)
+ end
+ if action then
+ local first = action
+ for i=2,nofactions do
+ local a = actions[i]
+ local what = runners[a.kind]
+ if what then
+ what = what(a,actions)
+ end
+ if action == what then
+ -- ignore this one, else we get a loop
+ elseif what then
+ action.Next = what
+ action = what
+ else
+ -- error
+ return nil
+ end
+ end
+ return first, actions.n
+ end
+ end
+end
+
+lpdf.action = pdfaction
+
+function codeinjections.prerollreference(actions) -- share can become option
+ if actions then
+ local main, n = pdfaction(actions)
+ if main then
+ local bs, bc = pdfborder()
+ main = pdfdictionary {
+ Subtype = pdf_link,
+ Border = bs,
+ C = bc,
+ H = (not actions.highlight and pdf_n) or nil,
+ A = pdfshareobjectreference(main),
+ F = 4, -- print (mandate in pdf/a)
+ }
+ return main("A"), n
+ end
+ end
+end
+
+-- local function use_normal_annotations()
+--
+-- local function reference(width,height,depth,prerolled) -- keep this one
+-- if prerolled then
+-- if trace_references then
+-- report_reference("width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
+-- end
+-- return pdfannotation_node(width,height,depth,prerolled)
+-- end
+-- end
+--
+-- local function finishreference()
+-- end
+--
+-- return reference, finishreference
+--
+-- end
+
+-- eventually we can do this for special refs only
+
+local hashed = { }
+local nofunique = 0
+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 ] >>"]
+
+directives.register("references.sharelinks", function(v) share = v end)
+
+setmetatableindex(hashed,function(t,k)
+ local v = pdfdelayedobject(k)
+ if share then
+ t[k] = v
+ end
+ nofunique = nofunique + 1
+ 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))]
+ nofused = nofused + 1
+ return pdfregisterannotation(annot)
+end
+
+local function finishannotation(width,height,depth,prerolled,r)
+ local annot = f_annot(prerolled,pdfrectangle(width,height,depth))
+ if r then
+ pdfdelayedobject(annot,r)
+ else
+ r = pdfdelayedobject(annot)
+ end
+ nofspecial = nofspecial + 1
+ return pdfregisterannotation(r)
+end
+
+function nodeinjections.reference(width,height,depth,prerolled)
+ if prerolled then
+ if trace_references then
+ report_reference("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
+ end
+ return latelua_function_node(function() finishreference(width,height,depth,prerolled) end)
+ end
+end
+
+function nodeinjections.annotation(width,height,depth,prerolled,r)
+ if prerolled then
+ if trace_references then
+ report_reference("special: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
+ end
+ return latelua_function_node(function() finishannotation(width,height,depth,prerolled,r or false) end)
+ end
+end
+
+-- beware, we register during a latelua sweep so we have to make sure that
+-- we finalize after that (also in a latelua for the moment as we have no
+-- callback yet)
+
+local annotations = nil
+
+function lpdf.registerannotation(n)
+ if annotations then
+ annotations[#annotations+1] = pdfreference(n)
+ else
+ annotations = pdfarray { pdfreference(n) } -- no need to use lpdf.array cum suis
+ end
+end
+
+pdfregisterannotation = lpdf.registerannotation
+
+function lpdf.annotationspecification()
+ if annotations then
+ local r = pdfdelayedobject(tostring(annotations)) -- delayed so okay in latelua
+ pdfaddtopageattributes("Annots",pdfreference(r))
+ annotations = nil
+ end
+end
+
+lpdf.registerpagefinalizer(lpdf.annotationspecification,"finalize annotations")
+
+statistics.register("pdf annotations", function()
+ if nofused > 0 or nofspecial > 0 then
+ return format("%s links (%s unique), %s special",nofused,nofunique,nofspecial)
+ else
+ return nil
+ end
+end)
+
+-- runners and specials
+
+local splitter = lpeg.splitat(",",true)
+
+runners["inner"] = function(var,actions)
+ local internal = false
+ local name = nil
+ local method = references.innermethod
+ local vi = var.i
+ local page = var.r
+ if vi then
+ local vir = vi.references
+ if vir then
+ -- todo: no need for it when we have a real reference ... although we need
+ -- this mess for prefixes anyway
+ local reference = vir.reference
+ if reference and reference ~= "" then
+ reference = lpegmatch(splitter,reference) or reference
+ var.inner = reference
+ local prefix = var.p
+ if prefix and prefix ~= "" then
+ var.prefix = prefix
+ name = prefix .. ":" .. reference
+ else
+ name = reference
+ end
+ end
+ internal = vir.internal
+ if internal then
+ flaginternals[internal] = true
+ end
+ end
+ end
+ if name then
+ return pdflinkname(name,internal,page)
+ elseif internal then
+ return pdflinkinternal(internal,page)
+ elseif page then
+ return pdflinkpage(page)
+ else
+ -- real bad
+ end
+end
+
+runners["inner with arguments"] = function(var,actions)
+ report_reference("todo: inner with arguments")
+ return false
+end
+
+runners["outer"] = function(var,actions)
+ local file, url = references.checkedfileorurl(var.outer,var.outer)
+ if file then
+ return pdffilelink(file,var.arguments,nil,actions)
+ elseif url then
+ return pdfurllink(url,var.arguments,nil,actions)
+ end
+end
+
+runners["outer with inner"] = function(var,actions)
+ return pdffilelink(references.checkedfile(var.outer),var.inner,var.r,actions)
+end
+
+runners["special outer with operation"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["special outer"] = function(var,actions)
+ report_reference("todo: special outer")
+ return false
+end
+
+runners["special"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["outer with inner with arguments"] = function(var,actions)
+ report_reference("todo: outer with inner with arguments")
+ return false
+end
+
+runners["outer with special and operation and arguments"] = function(var,actions)
+ report_reference("todo: outer with special and operation and arguments")
+ return false
+end
+
+runners["outer with special"] = function(var,actions)
+ report_reference("todo: outer with special")
+ return false
+end
+
+runners["outer with special and operation"] = function(var,actions)
+ report_reference("todo: outer with special and operation")
+ return false
+end
+
+runners["special operation"] = runners["special"]
+runners["special operation with arguments"] = runners["special"]
+
+function specials.internal(var,actions) -- better resolve in strc-ref
+ local i = tonumber(var.operation)
+ local v = i and references.internals[i]
+ if not v then
+ -- error
+ report_reference("no internal reference %a",i or "<unset>")
+ else
+ flaginternals[i] = true
+ return pdflinkinternal(i,v.references.realpage)
+ end
+end
+
+-- realpage already resolved
+
+specials.i = specials.internal
+
+local pages = references.pages
+
+function specials.page(var,actions)
+ local file = var.f
+ if file then
+ return pdffilelink(references.checkedfile(file),nil,var.operation,actions)
+ else
+ local p = var.r
+ if not p then -- todo: call special from reference code
+ p = pages[var.operation]
+ if type(p) == "function" then -- double
+ p = p()
+ else
+ p = references.realpageofpage(tonumber(p))
+ end
+ end
+ return pdflinkpage(p or var.operation)
+ end
+end
+
+function specials.realpage(var,actions)
+ local file = var.f
+ if file then
+ return pdffilelink(references.checkedfile(file),nil,var.operation,actions)
+ else
+ return pdflinkpage(var.operation)
+ end
+end
+
+function specials.userpage(var,actions)
+ local file = var.f
+ if file then
+ return pdffilelink(references.checkedfile(file),nil,var.operation,actions)
+ else
+ local p = var.r
+ if not p then -- todo: call special from reference code
+ p = var.operation
+ if p then -- no function and special check here. only numbers
+ p = references.realpageofpage(tonumber(p))
+ end
+ -- if p then
+ -- var.r = p
+ -- end
+ end
+ return pdflinkpage(p or var.operation)
+ end
+end
+
+function specials.deltapage(var,actions)
+ local p = tonumber(var.operation)
+ if p then
+ p = references.checkedrealpage(p + texgetcount("realpageno"))
+ return pdflinkpage(p)
+ end
+end
+
+-- sections
+
+-- function specials.section(var,actions)
+-- local sectionname = var.operation
+-- local destination = var.arguments
+-- local internal = structures.sections.internalreference(sectionname,destination)
+-- if internal then
+-- var.special = "internal"
+-- var.operation = internal
+-- var.arguments = nil
+-- specials.internal(var,actions)
+-- end
+-- end
+
+specials.section = specials.internal -- specials.section just need to have a value as it's checked
+
+-- todo, do this in references namespace ordered instead (this is an experiment)
+
+local splitter = lpeg.splitat(":")
+
+function specials.order(var,actions) -- references.specials !
+ local operation = var.operation
+ if operation then
+ local kind, name, n = lpegmatch(splitter,operation)
+ local order = structures.lists.ordered[kind]
+ order = order and order[name]
+ local v = order[tonumber(n)]
+ local r = v and v.references.realpage
+ if r then
+ var.operation = r -- brrr, but test anyway
+ return specials.page(var,actions)
+ end
+ end
+end
+
+function specials.url(var,actions)
+ return pdfurllink(references.checkedurl(var.operation),var.arguments,nil,actions)
+end
+
+function specials.file(var,actions)
+ return pdffilelink(references.checkedfile(var.operation),var.arguments,nil,actions)
+end
+
+function specials.fileorurl(var,actions)
+ local file, url = references.checkedfileorurl(var.operation,var.operation)
+ if file then
+ return pdffilelink(file,var.arguments,nil,actions)
+ elseif url then
+ return pdfurllink(url,var.arguments,nil,actions)
+ end
+end
+
+function specials.program(var,content)
+ local program = references.checkedprogram(var.operation)
+ return pdflaunch(program,var.arguments)
+end
+
+function specials.javascript(var)
+ return pdfjavascript(var.operation,var.arguments)
+end
+
+specials.JS = specials.javascript
+
+executers.importform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ImportFDF") }
+executers.exportform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ExportFDF") }
+executers.first = pdfdictionary { S = pdf_named, N = pdfconstant("FirstPage") }
+executers.previous = pdfdictionary { S = pdf_named, N = pdfconstant("PrevPage") }
+executers.next = pdfdictionary { S = pdf_named, N = pdfconstant("NextPage") }
+executers.last = pdfdictionary { S = pdf_named, N = pdfconstant("LastPage") }
+executers.backward = pdfdictionary { S = pdf_named, N = pdfconstant("GoBack") }
+executers.forward = pdfdictionary { S = pdf_named, N = pdfconstant("GoForward") }
+executers.print = pdfdictionary { S = pdf_named, N = pdfconstant("Print") }
+executers.exit = pdfdictionary { S = pdf_named, N = pdfconstant("Quit") }
+executers.close = pdfdictionary { S = pdf_named, N = pdfconstant("Close") }
+executers.save = pdfdictionary { S = pdf_named, N = pdfconstant("Save") }
+executers.savenamed = pdfdictionary { S = pdf_named, N = pdfconstant("SaveAs") }
+executers.opennamed = pdfdictionary { S = pdf_named, N = pdfconstant("Open") }
+executers.help = pdfdictionary { S = pdf_named, N = pdfconstant("HelpUserGuide") }
+executers.toggle = pdfdictionary { S = pdf_named, N = pdfconstant("FullScreen") }
+executers.search = pdfdictionary { S = pdf_named, N = pdfconstant("Find") }
+executers.searchagain = pdfdictionary { S = pdf_named, N = pdfconstant("FindAgain") }
+executers.gotopage = pdfdictionary { S = pdf_named, N = pdfconstant("GoToPage") }
+executers.query = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:Query") }
+executers.queryagain = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:NextHit") }
+executers.fitwidth = pdfdictionary { S = pdf_named, N = pdfconstant("FitWidth") }
+executers.fitheight = pdfdictionary { S = pdf_named, N = pdfconstant("FitHeight") }
+
+local function fieldset(arguments)
+ -- [\dogetfieldset{#1}]
+ return nil
+end
+
+function executers.resetform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdfconstant("ResetForm"),
+ Field = fieldset(arguments[1])
+ }
+end
+
+local formmethod = "post" -- "get" "post"
+local formformat = "xml" -- "xml" "html" "fdf"
+
+-- bit 3 = html bit 6 = xml bit 4 = get
+
+local flags = {
+ get = {
+ html = 12, fdf = 8, xml = 40,
+ },
+ post = {
+ html = 4, fdf = 0, xml = 32,
+ }
+}
+
+function executers.submitform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments)
+ local flag = flags[formmethod] or flags.post
+ flag = (flag and (flag[formformat] or flag.xml)) or 32 -- default: post, xml
+ return pdfdictionary {
+ S = pdfconstant("SubmitForm"),
+ F = arguments[1],
+ Field = fieldset(arguments[2]),
+ Flags = flag,
+ -- \PDFsubmitfiller
+ }
+end
+
+local pdf_hide = pdfconstant("Hide")
+
+function executers.hide(arguments)
+ return pdfdictionary {
+ S = pdf_hide,
+ H = true,
+ T = arguments,
+ }
+end
+
+function executers.show(arguments)
+ return pdfdictionary {
+ S = pdf_hide,
+ H = false,
+ T = arguments,
+ }
+end
+
+local pdf_movie = pdfconstant("Movie")
+local pdf_start = pdfconstant("Start")
+local pdf_stop = pdfconstant("Stop")
+local pdf_resume = pdfconstant("Resume")
+local pdf_pause = pdfconstant("Pause")
+
+local function movie_or_sound(operation,arguments)
+ arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdf_movie,
+ T = format("movie %s",arguments[1] or "noname"),
+ Operation = operation,
+ }
+end
+
+function executers.startmovie (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function executers.startsound (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumesound(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function specials.action(var)
+ local operation = var.operation
+ if var.operation and operation ~= "" then
+ local e = executers[operation]
+ if type(e) == "table" then
+ return e
+ elseif type(e) == "function" then
+ return e(var.arguments)
+ end
+ end
+end
+
+local function build(levels,start,parent,method,nested)
+ local startlevel = levels[start].level
+ local noflevels = #levels
+ local i, n = start, 0
+ local child, entry, m, prev, first, last, f, l
+ while i and i <= noflevels do
+ local current = levels[i]
+ if current.usedpage == false then
+ -- safeguard
+ i = i + 1
+ else
+ local level = current.level
+ local title = current.title
+ local reference = current.reference
+ local opened = current.opened
+ local reftype = type(reference)
+ local block = nil
+ local variant = "unknown"
+ if reftype == "table" then
+ -- we're okay
+ variant = "list"
+ block = reference.block
+ elseif reftype == "string" then
+ local resolved = references.identify("",reference)
+ local realpage = resolved and structures.references.setreferencerealpage(resolved) or 0
+ if realpage > 0 then
+ variant = "realpage"
+ realpage = realpage
+ reference = structures.pages.collected[realpage]
+ block = reference and reference.block
+ end
+ elseif reftype == "number" then
+ if reference > 0 then
+ variant = "realpage"
+ realpage = reference
+ reference = structures.pages.collected[realpage]
+ block = reference and reference.block
+ end
+ else
+ -- error
+ end
+ current.block = block
+ if variant == "unknown" then
+ -- error, ignore
+ i = i + 1
+ -- elseif (level < startlevel) or (i > 1 and block ~= levels[i-1].reference.block) then
+ elseif (level < startlevel) or (i > 1 and block ~= levels[i-1].block) then
+ if nested then -- could be an option but otherwise we quit too soon
+ if entry then
+ pdfflushobject(child,entry)
+ else
+ report_bookmark("error 1")
+ end
+ return i, n, first, last
+ else
+ report_bookmark("confusing level change at level %a around %a",level,title)
+ startlevel = level
+ end
+ end
+ if level == startlevel then
+ if trace_bookmarks then
+ report_bookmark("%3i %w%s %s",realpage,(level-1)*2,(opened and "+") or "-",title)
+ end
+ local prev = child
+ child = pdfreserveobject()
+ if entry then
+ entry.Next = child and pdfreference(child)
+ pdfflushobject(prev,entry)
+ end
+ local action = nil
+ if variant == "list" then
+ action = pdflinkinternal(reference.internal,reference.realpage)
+ elseif variant == "realpage" then
+ action = pagereferences[realpage]
+ else
+ -- hm, what to do
+ end
+ entry = pdfdictionary {
+ Title = pdfunicode(title),
+ Parent = parent,
+ Prev = prev and pdfreference(prev),
+ A = action,
+ }
+ -- entry.Dest = pdflinkinternal(reference.internal,reference.realpage)
+ if not first then
+ first, last = child, child
+ end
+ prev = child
+ last = prev
+ n = n + 1
+ i = i + 1
+ elseif i < noflevels and level > startlevel then
+ i, m, f, l = build(levels,i,pdfreference(child),method,true)
+ if entry then
+ entry.Count = (opened and m) or -m
+ if m > 0 then
+ entry.First = pdfreference(f)
+ entry.Last = pdfreference(l)
+ end
+ else
+ report_bookmark("error 2")
+ end
+ else
+ -- missing intermediate level but ok
+ i, m, f, l = build(levels,i,pdfreference(child),method,true)
+ if entry then
+ entry.Count = (opened and m) or -m
+ if m > 0 then
+ entry.First = pdfreference(f)
+ entry.Last = pdfreference(l)
+ end
+ pdfflushobject(child,entry)
+ else
+ report_bookmark("error 3")
+ end
+ return i, n, first, last
+ end
+ end
+ end
+ pdfflushobject(child,entry)
+ return nil, n, first, last
+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 {
+ Type = pdfconstant("Outlines"),
+ First = pdfreference(first),
+ Last = pdfreference(last),
+ Count = m,
+ }
+ pdfflushobject(parent,dict)
+ pdfaddtocatalog("Outlines",lpdf.reference(parent))
+ end
+end
+
+-- this could also be hooked into the frontend finalizer
+
+lpdf.registerdocumentfinalizer(function() bookmarks.place() end,1,"bookmarks") -- hm, why indirect call
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua
new file mode 100644
index 00000000000..877c01a1c24
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua
@@ -0,0 +1,735 @@
+if not modules then modules = { } end modules ['lpdf-col'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tostring, tonumber = type, next, tostring, tonumber
+local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
+local concat = table.concat
+local round = math.round
+local formatters = string.formatters
+
+local backends, lpdf, nodes = backends, lpdf, nodes
+
+local allocate = utilities.storage.allocate
+local formatters = string.formatters
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local nodepool = nodes.pool
+local register = nodepool.register
+local pdfliteral = nodepool.pdfliteral
+
+local pdfconstant = lpdf.constant
+local pdfstring = lpdf.string
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfverbose = lpdf.verbose
+local pdfflushobject = lpdf.flushobject
+local pdfdelayedobject = lpdf.delayedobject
+local pdfflushstreamobject = lpdf.flushstreamobject
+
+local pdfshareobjectreference = lpdf.shareobjectreference
+
+local addtopageattributes = lpdf.addtopageattributes
+local adddocumentcolorspace = lpdf.adddocumentcolorspace
+local adddocumentextgstate = lpdf.adddocumentextgstate
+
+local colors = attributes.colors
+local transparencies = attributes.transparencies
+local registertransparancy = transparencies.register
+local registercolor = colors.register
+local colorsvalue = colors.value
+local transparenciesvalue = transparencies.value
+local forcedmodel = colors.forcedmodel
+local getpagecolormodel = colors.getpagecolormodel
+
+local c_transparency = pdfconstant("Transparency")
+
+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_spot = formatters["/%s cs /%s CS %s SCN %s scn"]
+local f_tr = formatters["Tr%s"]
+local f_cm = formatters["q %F %F %F %F %F %F cm"]
+local f_effect = formatters["%s Tc %s w %s Tr"]
+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"]
+
+local report_color = logs.reporter("colors","backend")
+
+-- page groups (might move to lpdf-ini.lua)
+
+local colorspaceconstants = allocate { -- v_none is ignored
+ gray = pdfconstant("DeviceGray"),
+ rgb = pdfconstant("DeviceRGB"),
+ cmyk = pdfconstant("DeviceCMYK"),
+ all = pdfconstant("DeviceRGB"), -- brr
+}
+
+local transparencygroups = { }
+
+lpdf.colorspaceconstants = colorspaceconstants
+lpdf.transparencygroups = transparencygroups
+
+table.setmetatableindex(transparencygroups, function(transparencygroups,colormodel)
+ local cs = colorspaceconstants[colormodel]
+ if cs then
+ local d = pdfdictionary {
+ S = c_transparency,
+ CS = cs,
+ I = true,
+ }
+ -- local g = pdfreference(pdfflushobject(tostring(d)))
+ local g = pdfreference(pdfdelayedobject(tostring(d)))
+ transparencygroups[colormodel] = g
+ return g
+ else
+ transparencygroups[colormodel] = false
+ return false
+ end
+end)
+
+local function addpagegroup()
+ local model = getpagecolormodel()
+ if model then
+ local g = transparencygroups[model]
+ if g then
+ addtopageattributes("Group",g)
+ end
+ end
+end
+
+lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup")
+
+-- injection code (needs a bit reordering)
+
+-- color injection
+
+function nodeinjections.rgbcolor(r,g,b)
+ return register(pdfliteral(f_rgb(r,g,b,r,g,b)))
+end
+
+function nodeinjections.cmykcolor(c,m,y,k)
+ return register(pdfliteral(f_cmyk(c,m,y,k,c,m,y,k)))
+end
+
+function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
+ return register(pdfliteral(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(pdfliteral(f_spot(n,n,p,p)))
+end
+
+function nodeinjections.transparency(n)
+ return register(pdfliteral(f_tr_gs(n)))
+end
+
+-- a bit weird but let's keep it here for a while
+
+local effects = {
+ normal = 0,
+ inner = 0,
+ outer = 1,
+ both = 2,
+ hidden = 3,
+}
+
+local bp = number.dimenfactors.bp
+
+function nodeinjections.effect(effect,stretch,rulethickness)
+ -- always, no zero test (removed)
+ rulethickness = bp * rulethickness
+ effect = effects[effect] or effects['normal']
+ return register(pdfliteral(f_effect(stretch,rulethickness,effect))) -- watch order
+end
+
+-- spot- and indexcolors
+
+local pdf_separation = pdfconstant("Separation")
+local pdf_indexed = pdfconstant("Indexed")
+local pdf_device_n = pdfconstant("DeviceN")
+local pdf_device_rgb = pdfconstant("DeviceRGB")
+local pdf_device_cmyk = pdfconstant("DeviceCMYK")
+local pdf_device_gray = pdfconstant("DeviceGray")
+local pdf_extgstate = pdfconstant("ExtGState")
+
+local pdf_rbg_range = pdfarray { 0, 1, 0, 1, 0, 1 }
+local pdf_cmyk_range = pdfarray { 0, 1, 0, 1, 0, 1, 0, 1 }
+local pdf_gray_range = pdfarray { 0, 1 }
+
+local f_rgb_function = formatters["dup %s mul exch dup %s mul exch %s mul"]
+local f_cmyk_function = formatters["dup %s mul exch dup %s mul exch dup %s mul exch %s mul"]
+local f_gray_function = formatters["%s mul"]
+
+local documentcolorspaces = pdfdictionary()
+
+local spotcolorhash = { } -- not needed
+local spotcolornames = { }
+local indexcolorhash = { }
+local delayedindexcolors = { }
+
+function registrations.spotcolorname(name,e)
+ spotcolornames[name] = e or name
+end
+
+function registrations.getspotcolorreference(name)
+ return spotcolorhash[name]
+end
+
+-- beware: xpdf/okular/evince cannot handle the spot->process shade
+
+-- This should become delayed i.e. only flush when used; in that case we need
+-- need to store the specification and then flush them when accesssomespotcolor
+-- is called. At this moment we assume that splotcolors that get defined are
+-- also used which keeps the overhad small anyway. Tricky for mp ...
+
+local processcolors
+
+local function registersomespotcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ if noffractions == 0 then
+ -- can't happen
+ elseif noffractions == 1 then
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = { 0, 1 },
+ Range = range,
+ }
+ local calculations = pdfflushstreamobject(format("{ %s }",funct),dictionary)
+ -- local calculations = pdfobject {
+ -- type = "stream",
+ -- immediate = true,
+ -- string = format("{ %s }",funct),
+ -- attr = dictionary(),
+ -- }
+ local array = pdfarray {
+ pdf_separation,
+ pdfconstant(spotcolornames[name] or name),
+ colorspace,
+ pdfreference(calculations),
+ }
+ local m = pdfflushobject(array)
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ adddocumentcolorspace(name,mr)
+ else
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ local colorants = pdfdictionary()
+ for n in gmatch(names,"[^,]+") do
+ local name = spotcolornames[n] or n
+ -- the cmyk names assume that they are indeed these colors
+ if n == "cyan" then
+ name = "Cyan"
+ elseif n == "magenta" then
+ name = "Magenta"
+ elseif n == "yellow" then
+ name = "Yellow"
+ elseif n == "black" then
+ name = "Black"
+ else
+ local sn = spotcolorhash[name] or spotcolorhash[n]
+ if not sn then
+ report_color("defining %a as colorant",name)
+ colors.definespotcolor("",name,"p=1",true)
+ sn = spotcolorhash[name] or spotcolorhash[n]
+ end
+ if sn then
+ colorants[name] = pdfreference(sn)
+ else
+ -- maybe some day generate colorants (spot colors for multi) automatically
+ report_color("unknown colorant %a, using black instead",name or n)
+ name = "Black"
+ end
+ end
+ cnames[#cnames+1] = pdfconstant(name)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ if not processcolors then
+ local specification = pdfdictionary {
+ ColorSpace = pdfconstant("DeviceCMYK"),
+ Components = pdfarray {
+ pdfconstant("Cyan"),
+ pdfconstant("Magenta"),
+ pdfconstant("Yellow"),
+ pdfconstant("Black")
+ }
+ }
+ processcolors = pdfreference(pdfflushobject(specification))
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local calculation = pdfflushstreamobject(format("{ %s %s }",rep("pop ",noffractions),funct),dictionary)
+ local channels = pdfdictionary {
+ Subtype = pdfconstant("NChannel"),
+ Colorants = colorants,
+ Process = processcolors,
+ }
+ local array = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(calculation),
+ pdfshareobjectreference(tostring(channels)), -- optional but needed for shades
+ }
+ local m = pdfflushobject(array)
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ adddocumentcolorspace(name,mr)
+ end
+end
+
+-- wrong name
+
+local function registersomeindexcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ if names == "" then
+ names = name .. ",None"
+ else
+ names = names .. ",None"
+ end
+ for n in gmatch(names,"[^,]+") do
+ cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local n = pdfflushstreamobject(format("{ %s %s }",rep("exch pop ",noffractions),funct),dictionary) -- exch pop
+ local a = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(n),
+ }
+ if p == "" then
+ p = "1"
+ else
+ p = p .. ",1"
+ end
+ local pi = { }
+ for pp in gmatch(p,"[^,]+") do
+ pi[#pi+1] = tonumber(pp)
+ end
+ local vector, set, n = { }, { }, #pi
+ for i=255,0,-1 do
+ for j=1,n do
+ set[j] = format("%02X",round(pi[j]*i))
+ end
+ vector[#vector+1] = concat(set)
+ end
+ vector = pdfverbose { "<", concat(vector, " "), ">" }
+ local n = pdfflushobject(pdfarray{ pdf_indexed, a, 255, vector })
+ adddocumentcolorspace(format("%s_indexed",name),pdfreference(n))
+ return n
+end
+
+-- actually, names (parent) is the hash
+
+local function delayindexcolor(name,names,func)
+ local hash = (names ~= "" and names) or name
+ delayedindexcolors[hash] = func
+end
+
+local function indexcolorref(name) -- actually, names (parent) is the hash
+ if not indexcolorhash[name] then
+ local delayedindexcolor = delayedindexcolors[name]
+ if type(delayedindexcolor) == "function" then
+ indexcolorhash[name] = delayedindexcolor()
+ delayedindexcolors[name] = true
+ end
+ end
+ return indexcolorhash[name]
+end
+
+function registrations.rgbspotcolor(name,noffractions,names,p,r,g,b)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,f_rgb_function(r,g,b))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,f_num_3(r,g,b))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,f_rgb_function(r,g,b))
+ end)
+end
+
+function registrations.cmykspotcolor(name,noffractions,names,p,c,m,y,k)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_num_4(c,m,y,k))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
+ end)
+end
+
+function registrations.grayspotcolor(name,noffractions,names,p,s)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_num_1(s))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
+ end)
+end
+
+function registrations.rgbindexcolor(name,noffractions,names,p,r,g,b)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,f_rgb_function(r,g,b))
+end
+
+function registrations.cmykindexcolor(name,noffractions,names,p,c,m,y,k)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
+end
+
+function registrations.grayindexcolor(name,noffractions,names,p,s)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
+end
+
+function codeinjections.setfigurecolorspace(data,figure)
+ local color = data.request.color
+ if color then
+ local ref = indexcolorref(color)
+ if ref then
+ figure.colorspace = ref
+ data.used.color = color
+ end
+ end
+end
+
+-- transparency
+
+local transparencies = { [0] =
+ pdfconstant("Normal"),
+ pdfconstant("Normal"),
+ pdfconstant("Multiply"),
+ pdfconstant("Screen"),
+ pdfconstant("Overlay"),
+ pdfconstant("SoftLight"),
+ pdfconstant("HardLight"),
+ pdfconstant("ColorDodge"),
+ pdfconstant("ColorBurn"),
+ pdfconstant("Darken"),
+ pdfconstant("Lighten"),
+ pdfconstant("Difference"),
+ pdfconstant("Exclusion"),
+ pdfconstant("Hue"),
+ pdfconstant("Saturation"),
+ pdfconstant("Color"),
+ pdfconstant("Luminosity"),
+ pdfconstant("Compatible"), -- obsolete; 'Normal' is used in this case
+}
+
+local documenttransparencies = { }
+local transparencyhash = { } -- share objects
+
+local done, signaled = false, false
+
+function registrations.transparency(n,a,t)
+ if not done then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = 1,
+ CA = 1,
+ BM = transparencies[1],
+ AIS = false,
+ }
+ local m = pdfflushobject(d)
+ local mr = pdfreference(m)
+ transparencyhash[0] = m
+ documenttransparencies[0] = mr
+ adddocumentextgstate("Tr0",mr)
+ done = true
+ end
+ if n > 0 and not transparencyhash[n] then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = tonumber(t),
+ CA = tonumber(t),
+ BM = transparencies[tonumber(a)] or transparencies[0],
+ AIS = false,
+ }
+ local m = pdfflushobject(d)
+ local mr = pdfreference(m)
+ transparencyhash[n] = m
+ documenttransparencies[n] = mr
+ adddocumentextgstate(f_tr(n),mr)
+ end
+end
+
+statistics.register("page group warning", function()
+ if done then
+ local model = getpagecolormodel()
+ if model and not transparencygroups[model] then
+ return "transparencies are used but no pagecolormodel is set"
+ end
+ end
+end)
+
+-- Literals needed to inject code in the mp stream, we cannot use attributes there
+-- since literals may have qQ's, much may go away once we have mplib code in place.
+--
+-- This module assumes that some functions are defined in the colors namespace
+-- which most likely will be loaded later.
+
+local function lpdfcolor(model,ca,default) -- todo: use gray when no color
+ if colors.supported then
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ model = forcedmodel(model)
+ if model == 2 then
+ local s = cv[2]
+ return f_gray(s,s)
+ elseif model == 3 then
+ local r, g, b = cv[3], cv[4], 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]
+ 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]
+ if type(p) == "string" then
+ p = gsub(p,","," ") -- brr misuse of spot
+ end
+ return f_spot(n,n,p,p)
+ end
+ else
+ return f_gray(default or 0,default or 0)
+ end
+ else
+ return ""
+ end
+end
+
+lpdf.color = lpdfcolor
+
+interfaces.implement {
+ name = "lpdf_color",
+ actions = { lpdfcolor, context },
+ arguments = "integer"
+}
+
+function lpdf.colorspec(model,ca,default)
+ if ca and ca > 0 then
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return pdfarray { cv[2] }
+ elseif model == 3 then
+ return pdfarray { cv[3],cv[4],cv[5] }
+ elseif model == 4 then
+ return pdfarray { cv[6],cv[7],cv[8],cv[9] }
+ elseif model == 5 then
+ return pdfarray { cv[13] }
+ end
+ end
+ end
+ if default then
+ return default
+ end
+end
+
+function lpdf.pdfcolor(attribute) -- bonus, for pgf and friends
+ return lpdfcolor(1,attribute)
+end
+
+function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
+ -- beware, we need this hack because normally transparencies are not
+ -- yet registered and therefore the number is not not known ... we
+ -- might use the attribute number itself in the future
+ if transparencies.supported then
+ local ct = transparenciesvalue(ct)
+ if ct then
+ return f_tr_gs(registertransparancy(nil,ct[1],ct[2],true))
+ else
+ return f_tr_gs(0)
+ end
+ else
+ return ""
+ end
+end
+
+function lpdf.colorvalue(model,ca,default)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ model = forcedmodel(model)
+ if model == 2 then
+ return f_num_1(cv[2])
+ elseif model == 3 then
+ return f_num_3(cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return f_num_4(cv[6],cv[7],cv[8],cv[9])
+ else
+ return f_num_1(cv[13])
+ end
+ else
+ return f_num_1(default or 0)
+ end
+end
+
+function lpdf.colorvalues(model,ca,default)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ model = forcedmodel(model)
+ if model == 2 then
+ return cv[2]
+ elseif model == 3 then
+ return cv[3], cv[4], cv[5]
+ elseif model == 4 then
+ return cv[6], cv[7], cv[8], cv[9]
+ elseif model == 4 then
+ return cv[13]
+ end
+ else
+ return default or 0
+ end
+end
+
+function lpdf.transparencyvalue(ta,default)
+ local tv = transparenciesvalue(ta)
+ if tv then
+ return tv[2]
+ else
+ return default or 1
+ end
+end
+
+function lpdf.colorspace(model,ca)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ model = forcedmodel(model)
+ if model == 2 then
+ return "DeviceGray"
+ elseif model == 3 then
+ return "DeviceRGB"
+ elseif model == 4 then
+ return "DeviceCMYK"
+ end
+ end
+ return "DeviceGRAY"
+end
+
+-- by registering we getconversion for free (ok, at the cost of overhead)
+
+local intransparency = false
+local pdfcolor = lpdf.color
+
+function lpdf.rgbcode(model,r,g,b)
+ if colors.supported then
+ return pdfcolor(model,registercolor(nil,'rgb',r,g,b))
+ else
+ return ""
+ end
+end
+
+function lpdf.cmykcode(model,c,m,y,k)
+ if colors.supported then
+ return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k))
+ else
+ return ""
+ end
+end
+
+function lpdf.graycode(model,s)
+ if colors.supported then
+ return pdfcolor(model,registercolor(nil,'gray',s))
+ else
+ return ""
+ end
+end
+
+function lpdf.spotcode(model,n,f,d,p)
+ if colors.supported then
+ return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect
+ else
+ return ""
+ end
+end
+
+function lpdf.transparencycode(a,t)
+ if transparencies.supported then
+ intransparency = true
+ return f_tr_gs(registertransparancy(nil,a,t,true)) -- true forces resource
+ else
+ return ""
+ end
+end
+
+function lpdf.finishtransparencycode()
+ if transparencies.supported and intransparency then
+ intransparency = false
+ return f_tr_gs(0) -- we happen to know this -)
+ else
+ return ""
+ end
+end
+
+-- this will move to lpdf-spe.lua
+
+local f_slant = formatters["pdf: q 1 0 %F 1 0 0 cm"]
+
+backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color
+
+ red = { "special", 'pdf: 1 0 0 rg 1 0 0 RG' },
+ green = { "special", 'pdf: 0 1 0 rg 0 1 0 RG' },
+ blue = { "special", 'pdf: 0 0 1 rg 0 0 1 RG' },
+ gray = { "special", 'pdf: .75 g .75 G' },
+ black = { "special", 'pdf: 0 g 0 G' },
+
+ rulecolors = {
+ red = { "special", 'pdf: 1 0 0 rg' },
+ green = { "special", 'pdf: 0 1 0 rg' },
+ blue = { "special", 'pdf: 0 0 1 rg' },
+ gray = { "special", 'pdf: .5 g' },
+ black = { "special", 'pdf: 0 g' },
+ palered = { "special", 'pdf: 1 .75 .75 rg' },
+ palegreen = { "special", 'pdf: .75 1 .75 rg' },
+ paleblue = { "special", 'pdf: .75 .75 1 rg' },
+ palegray = { "special", 'pdf: .75 g' },
+ },
+
+ startslant = function(a) return { "special", f_slant(a) } end,
+ stopslant = { "special", "pdf: Q" },
+
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-enc.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-enc.lua
new file mode 100644
index 00000000000..090fb15cd5d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-enc.lua
@@ -0,0 +1,157 @@
+if not modules then modules = { } end modules ['lpdf-enc'] = {
+ 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"
+}
+
+-- delayed loading
+
+local pdfconstant = lpdf.constant
+
+return lpdf.dictionary {
+ Type = pdfconstant("Encoding"),
+ Differences = lpdf.array {
+ 24,
+ pdfconstant("breve"),
+ pdfconstant("caron"),
+ pdfconstant("circumflex"),
+ pdfconstant("dotaccent"),
+ pdfconstant("hungarumlaut"),
+ pdfconstant("ogonek"),
+ pdfconstant("ring"),
+ pdfconstant("tilde"),
+ 39,
+ pdfconstant("quotesingle"),
+ 96,
+ pdfconstant("grave"),
+ 128,
+ pdfconstant("bullet"),
+ pdfconstant("dagger"),
+ pdfconstant("daggerdbl"),
+ pdfconstant("ellipsis"),
+ pdfconstant("emdash"),
+ pdfconstant("endash"),
+ pdfconstant("florin"),
+ pdfconstant("fraction"),
+ pdfconstant("guilsinglleft"),
+ pdfconstant("guilsinglright"),
+ pdfconstant("minus"),
+ pdfconstant("perthousand"),
+ pdfconstant("quotedblbase"),
+ pdfconstant("quotedblleft"),
+ pdfconstant("quotedblright"),
+ pdfconstant("quoteleft"),
+ pdfconstant("quoteright"),
+ pdfconstant("quotesinglbase"),
+ pdfconstant("trademark"),
+ pdfconstant("fi"),
+ pdfconstant("fl"),
+ pdfconstant("Lslash"),
+ pdfconstant("OE"),
+ pdfconstant("Scaron"),
+ pdfconstant("Ydieresis"),
+ pdfconstant("Zcaron"),
+ pdfconstant("dotlessi"),
+ pdfconstant("lslash"),
+ pdfconstant("oe"),
+ pdfconstant("scaron"),
+ pdfconstant("zcaron"),
+ 160,
+ pdfconstant("Euro"),
+ 164,
+ pdfconstant("currency"),
+ 166,
+ pdfconstant("brokenbar"),
+ 168,
+ pdfconstant("dieresis"),
+ pdfconstant("copyright"),
+ pdfconstant("ordfeminine"),
+ 172,
+ pdfconstant("logicalnot"),
+ pdfconstant(".notdef"),
+ pdfconstant("registered"),
+ pdfconstant("macron"),
+ pdfconstant("degree"),
+ pdfconstant("plusminus"),
+ pdfconstant("twosuperior"),
+ pdfconstant("threesuperior"),
+ pdfconstant("acute"),
+ pdfconstant("mu"),
+ 183,
+ pdfconstant("periodcentered"),
+ pdfconstant("cedilla"),
+ pdfconstant("onesuperior"),
+ pdfconstant("ordmasculine"),
+ 188,
+ pdfconstant("onequarter"),
+ pdfconstant("onehalf"),
+ pdfconstant("threequarters"),
+ 192,
+ pdfconstant("Agrave"),
+ pdfconstant("Aacute"),
+ pdfconstant("Acircumflex"),
+ pdfconstant("Atilde"),
+ pdfconstant("Adieresis"),
+ pdfconstant("Aring"),
+ pdfconstant("AE"),
+ pdfconstant("Ccedilla"),
+ pdfconstant("Egrave"),
+ pdfconstant("Eacute"),
+ pdfconstant("Ecircumflex"),
+ pdfconstant("Edieresis"),
+ pdfconstant("Igrave"),
+ pdfconstant("Iacute"),
+ pdfconstant("Icircumflex"),
+ pdfconstant("Idieresis"),
+ pdfconstant("Eth"),
+ pdfconstant("Ntilde"),
+ pdfconstant("Ograve"),
+ pdfconstant("Oacute"),
+ pdfconstant("Ocircumflex"),
+ pdfconstant("Otilde"),
+ pdfconstant("Odieresis"),
+ pdfconstant("multiply"),
+ pdfconstant("Oslash"),
+ pdfconstant("Ugrave"),
+ pdfconstant("Uacute"),
+ pdfconstant("Ucircumflex"),
+ pdfconstant("Udieresis"),
+ pdfconstant("Yacute"),
+ pdfconstant("Thorn"),
+ pdfconstant("germandbls"),
+ pdfconstant("agrave"),
+ pdfconstant("aacute"),
+ pdfconstant("acircumflex"),
+ pdfconstant("atilde"),
+ pdfconstant("adieresis"),
+ pdfconstant("aring"),
+ pdfconstant("ae"),
+ pdfconstant("ccedilla"),
+ pdfconstant("egrave"),
+ pdfconstant("eacute"),
+ pdfconstant("ecircumflex"),
+ pdfconstant("edieresis"),
+ pdfconstant("igrave"),
+ pdfconstant("iacute"),
+ pdfconstant("icircumflex"),
+ pdfconstant("idieresis"),
+ pdfconstant("eth"),
+ pdfconstant("ntilde"),
+ pdfconstant("ograve"),
+ pdfconstant("oacute"),
+ pdfconstant("ocircumflex"),
+ pdfconstant("otilde"),
+ pdfconstant("odieresis"),
+ pdfconstant("divide"),
+ pdfconstant("oslash"),
+ pdfconstant("ugrave"),
+ pdfconstant("uacute"),
+ pdfconstant("ucircumflex"),
+ pdfconstant("udieresis"),
+ pdfconstant("yacute"),
+ pdfconstant("thorn"),
+ pdfconstant("ydieresis"),
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua
new file mode 100644
index 00000000000..c72e2a424f4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua
@@ -0,0 +1,418 @@
+if not modules then modules = { } end modules ['lpdf-epa'] = {
+ 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"
+}
+
+-- This is a rather experimental feature and the code will probably
+-- change.
+
+local type, tonumber = type, tonumber
+local format, gsub, lower = string.format, string.gsub, string.lower
+local formatters = string.formatters
+local abs = math.abs
+
+----- lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+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 report_link = logs.reporter("backend","link")
+local report_outline = logs.reporter("backend","outline")
+
+local epdf = epdf
+local backends = backends
+local lpdf = lpdf
+local context = context
+
+local loadpdffile = lpdf.epdf.load
+
+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 bookmarks = structures.bookmarks
+
+local maxdimen = 2^30-1
+
+local layerspec = { -- predefining saves time
+ "epdflinks"
+}
+
+local f_namespace = formatters["lpdf-epa-%s-"]
+
+local function makenamespace(filename)
+ filename = gsub(lower(nameonly(filename)),"[^%a%d]+","-")
+ return f_namespace(filename)
+end
+
+local function add_link(x,y,w,h,destination,what)
+ x = x .. "bp"
+ y = y .. "bp"
+ w = w .. "bp"
+ h = h .. "bp"
+ if trace_links then
+ report_link("destination %a, type %a, dx %s, dy %s, wd %s, ht %s",destination,what,x,y,w,h)
+ end
+ local locationspec = { -- predefining saves time
+ x = x,
+ y = y,
+ preset = "leftbottom",
+ }
+ local buttonspec = {
+ width = w,
+ height = h,
+ offset = variables.overlay,
+ frame = trace_links and variables.on or variables.off,
+ }
+ context.setlayer (
+ layerspec,
+ locationspec,
+ function() context.button ( buttonspec, "", { destination } ) end
+ -- context.nested.button(buttonspec, "", { destination }) -- time this
+ )
+end
+
+local function link_goto(x,y,w,h,document,annotation,pagedata,namespace)
+ local a = annotation.A
+ if a then
+ local destination = a.D -- [ 18 0 R /Fit ]
+ local what = "page"
+ if type(destination) == "string" then
+ local destinations = document.destinations
+ local wanted = destinations[destination]
+ destination = wanted and wanted.D -- is this ok? isn't it destination already a string?
+ if destination then what = "named" end
+ end
+ local pagedata = destination and destination[1]
+ if pagedata then
+ local destinationpage = pagedata.number
+ if destinationpage then
+ add_link(x,y,w,h,namespace .. destinationpage,what)
+ end
+ end
+ end
+end
+
+local function link_uri(x,y,w,h,document,annotation)
+ local url = annotation.A.URI
+ if url then
+ -- url = lpegmatch(urlescaper,url)
+ -- url = lpegmatch(utftohigh,url)
+ url = escapetex(url)
+ add_link(x,y,w,h,formatters["url(%s)"](url),"url")
+ end
+end
+
+-- The rules in PDF on what a 'file specification' is, is in fact quite elaborate
+-- (see section 3.10 in the 1.7 reference) so we need to test for string as well
+-- as a table. TH/20140916
+
+local function link_file(x,y,w,h,document,annotation)
+ local a = annotation.A
+ if a then
+ local filename = a.F
+ if type(filename) == "table" then
+ filename = filename.F
+ end
+ if filename then
+ filename = escapetex(filename)
+ local destination = a.D
+ if not destination then
+ add_link(x,y,w,h,formatters["file(%s)"](filename),"file")
+ elseif type(destination) == "string" then
+ add_link(x,y,w,h,formatters["%s::%s"](filename,destination),"file (named)")
+ else
+ destination = destination[1] -- array
+ if tonumber(destination) then
+ add_link(x,y,w,h,formatters["%s::page(%s)"](filename,destination),"file (page)")
+ else
+ add_link(x,y,w,h,formatters["file(%s)"](filename),"file")
+ end
+ end
+ end
+ end
+end
+
+function codeinjections.mergereferences(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 document = loadpdffile(fullname) -- costs time
+ if document then
+ 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 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
+ 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
+ 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 [%f %f %f %f] (max: %f)",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)
+ 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
+ if trace_links then
+ report_link("setting figure reference to %a",reference)
+ end
+ specification.reference = reference
+ return namespace
+ end
+ end
+ return ""-- no namespace, empty, not nil
+end
+
+function codeinjections.mergeviewerlayers(specification)
+ -- todo: parse included page for layers .. or only for whole document inclusion
+ if true then
+ return
+ end
+ if not specification then
+ specification = figures and figures.current()
+ specification = specification and specification.status
+ 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)
+ 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
+ end
+end
+
+-- new: for taco
+
+-- 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
+-- and convert to utf.
+
+function codeinjections.getbookmarks(filename)
+
+ -- The first version built a nested tree and flattened that afterwards ... but I decided
+ -- to keep it simple and flat.
+
+ local list = bookmarks.extras.get(filename)
+
+ if list then
+ return list
+ else
+ list = { }
+ end
+
+ local document = nil
+
+ if lfs.isfile(filename) then
+ document = loadpdffile(filename)
+ else
+ report_outline("unknown file %a",filename)
+ bookmarks.extras.register(filename,list)
+ return list
+ end
+
+ local outlines = document.Catalog.Outlines
+ local pages = document.pages
+ local nofpages = pages.n -- we need to access once in order to initialize
+ local destinations = document.destinations
+
+ -- I need to check this destination analyzer with the one in annotations .. best share
+ -- code (and not it's inconsistent). On the todo list ...
+
+ local function setdestination(current,entry)
+ local destination = nil
+ local action = current.A
+ if action then
+ local subtype = action.S
+ if subtype == "GoTo" then
+ destination = action.D
+ if type(destination) == "string" then
+ entry.destination = destination
+ destination = destinations[destination]
+ local pagedata = destination and destination[1]
+ if pagedata then
+ entry.realpage = pagedata.number
+ end
+ else
+ -- maybe
+ end
+ else
+ -- maybe
+ end
+ else
+ local destination = current.Dest
+ if destination then
+ if type(destination) == "string" then
+ local wanted = destinations[destination]
+ destination = wanted and wanted.D
+ if destination then
+ entry.destination = destination
+ end
+ else
+ local pagedata = destination and destination[1]
+ if pagedata and pagedata.Type == "Page" then
+ entry.realpage = pagedata.number
+ end
+ end
+ end
+ end
+ end
+
+ local function traverse(current,depth)
+ while current do
+ -- local title = current.Title
+ local title = current("Title") -- can be pdfdoc or unicode
+ if title then
+ local entry = {
+ level = depth,
+ title = title,
+ }
+ list[#list+1] = entry
+ setdestination(current,entry)
+ if trace_outlines then
+ report_outline("%w%s",2*depth,title)
+ end
+ end
+ local first = current.First
+ if first then
+ local current = first
+ while current do
+ local title = current.Title
+ if title and trace_outlines then
+ report_outline("%w%s",2*depth,title)
+ end
+ local entry = {
+ level = depth,
+ title = title,
+ }
+ setdestination(current,entry)
+ list[#list+1] = entry
+ traverse(current.First,depth+1)
+ current = current.Next
+ end
+ end
+ current = current.Next
+ end
+ end
+
+ if outlines then
+ if trace_outlines then
+ report_outline("outline of %a:",document.filename)
+ report_outline()
+ end
+ traverse(outlines,0)
+ if trace_outlines then
+ report_outline()
+ end
+ elseif trace_outlines then
+ report_outline("no outline in %a",document.filename)
+ end
+
+ bookmarks.extras.register(filename,list)
+
+ return list
+
+end
+
+function codeinjections.mergebookmarks(specification)
+ -- codeinjections.getbookmarks(document)
+ if not specification then
+ specification = figures and figures.current()
+ specification = specification and specification.status
+ end
+ if specification then
+ local fullname = specification.fullname
+ local bookmarks = backends.codeinjections.getbookmarks(fullname)
+ local realpage = tonumber(specification.page) or 1
+ for i=1,#bookmarks do
+ local b = bookmarks[i]
+ if not b.usedpage then
+ if b.realpage == realpage then
+ if trace_options then
+ report_outline("using %a at page %a of file %a",b.title,realpage,fullname)
+ end
+ b.usedpage = true
+ b.section = structures.sections.currentsectionindex()
+ b.pageindex = specification.pageindex
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua
new file mode 100644
index 00000000000..0f62d6189ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua
@@ -0,0 +1,839 @@
+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"
+}
+
+-- This is an experimental layer around the epdf library. The reason for this layer is that
+-- I want to be independent of the library (which implements a selection of what a file
+-- provides) and also because I want an interface closer to Lua's table model while the API
+-- stays close to the original xpdf library. Of course, after prototyping a solution, we can
+-- optimize it using the low level epdf accessors. However, not all are accessible (this will
+-- be fixed).
+--
+-- It will be handy when we have a __length and __next that can trigger the resolve till then
+-- we will provide .n as #; maybe in Lua 5.3 or later.
+--
+-- As there can be references to the parent we cannot expand a tree. I played with some
+-- expansion variants but it does not pay off; adding extra checks is not worth the trouble.
+--
+-- The document stays open. In order to free memory one has to explicitly unload the loaded
+-- document.
+--
+-- We have much more checking then needed in the prepare functions because occasionally
+-- we run into bugs in poppler or the epdf interface. It took us a while to realize that
+-- there was a long standing gc issue the on long runs with including many pages could
+-- crash the analyzer.
+--
+-- Normally a value is fetched by key, as in foo.Title but as it can be in pdfdoc encoding
+-- a safer bet is foo("Title") which will return a decoded string (or the original if it
+-- already was unicode).
+
+local setmetatable, rawset, rawget, type = setmetatable, rawset, rawget, type
+local tostring, tonumber = tostring, tonumber
+local lower, match, char, byte, find = string.lower, string.match, string.char, string.byte, string.find
+local abs = math.abs
+local concat = table.concat
+local toutf, toeight, utfchar = string.toutf, utf.toeight, utf.char
+
+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
+
+local epdf = epdf
+ lpdf = lpdf or { }
+local lpdf = lpdf
+local lpdf_epdf = { }
+lpdf.epdf = lpdf_epdf
+
+local pdf_open = epdf.open
+
+local report_epdf = logs.reporter("epdf")
+
+local getDict, getArray, getReal, getNum, getString, getBool, getName, getRef, getRefNum
+local getType, getTypeName
+local dictGetLength, dictGetVal, dictGetValNF, dictGetKey
+local arrayGetLength, arrayGetNF, arrayGet
+local streamReset, streamGetDict, streamGetChar
+
+do
+ local object = epdf.Object()
+ --
+ getDict = object.getDict
+ getArray = object.getArray
+ getReal = object.getReal
+ getNum = object.getNum
+ getString = object.getString
+ getBool = object.getBool
+ getName = object.getName
+ getRef = object.getRef
+ getRefNum = object.getRefNum
+ --
+ getType = object.getType
+ getTypeName = object.getTypeName
+ --
+ streamReset = object.streamReset
+ streamGetDict = object.streamGetDict
+ streamGetChar = object.streamGetChar
+ --
+end
+
+local function initialize_methods(xref)
+ local dictionary = epdf.Dict(xref)
+ local array = epdf.Array(xref)
+ --
+ dictGetLength = dictionary.getLength
+ dictGetVal = dictionary.getVal
+ dictGetValNF = dictionary.getValNF
+ dictGetKey = dictionary.getKey
+ --
+ arrayGetLength = array.getLength
+ arrayGetNF = array.getNF
+ arrayGet = array.get
+ --
+ initialize_methods = function()
+ -- already done
+ end
+end
+
+local typenames = { [0] =
+ "boolean",
+ "integer",
+ "real",
+ "string",
+ "name",
+ "null",
+ "array",
+ "dictionary",
+ "stream",
+ "ref",
+ "cmd",
+ "error",
+ "eof",
+ "none",
+ "integer64",
+}
+
+local typenumbers = table.swapped(typenames)
+
+local null_code = typenumbers.null
+local ref_code = typenumbers.ref
+
+local function fatal_error(...)
+ report_epdf(...)
+ report_epdf("aborting job in order to avoid crash")
+ os.exit()
+end
+
+-- epdf is the built-in library
+
+function epdf.type(o)
+ local t = lower(match(tostring(o),"[^ :]+"))
+ return t or "?"
+end
+
+local checked_access
+
+-- dictionaries (can be optimized: ... resolve and redefine when all locals set)
+
+local frompdfdoc = lpdf.frompdfdoc
+
+local function get_flagged(t,f,k)
+ local fk = f[k]
+ if not fk then
+ return t[k]
+ elseif fk == "rawtext" then
+ return frompdfdoc(t[k])
+ else -- no other flags yet
+ return t[k]
+ end
+end
+
+local function prepare(document,d,t,n,k,mt,flags)
+ for i=1,n do
+ local v = dictGetVal(d,i)
+ if v then
+ local r = dictGetValNF(d,i)
+ local kind = getType(v)
+ if kind == null_code then
+ -- ignore
+ else
+ 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 c 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
+ else
+ report_epdf("warning: nil value for key %a in dictionary",key)
+ end
+ end
+ else
+ fatal_error("error: invalid value at index %a in dictionary of %a",i,document.filename)
+ 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
+ local t = { }
+ local f = { }
+ setmetatable(t, {
+ __index = function(t,k)
+ return prepare(document,d,t,n,k,_,_,f)
+ end,
+ __call = function(t,k)
+ return get_flagged(t,f,k)
+ end,
+ } )
+ return t
+ end
+end
+
+local function get_dictionary(object,document,r,mt)
+ local d = getDict(object)
+ local n = d and dictGetLength(d) or 0
+ if n > 0 then
+ local t = { }
+ local f = { }
+ setmetatable(t, {
+ __index = function(t,k)
+ return prepare(document,d,t,n,k,mt,f)
+ end,
+ __call = function(t,k)
+ return get_flagged(t,f,k)
+ end,
+ } )
+ return t
+ end
+end
+
+-- arrays (can be optimized: ... resolve and redefine when all locals set)
+
+local function prepare(document,a,t,n,k)
+ for i=1,n do
+ local v = arrayGet(a,i)
+ if v then
+ local kind = getType(v)
+ if kind == null_code then
+ -- ignore
+ elseif kind then
+ local r = arrayGetNF(a,i)
+ 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)
+ document.__cache__[objnum] = cached
+ document.__xrefs__[cached] = objnum
+ end
+ t[i] = cached
+ else
+ t[i] = checked_access[kind](v,document)
+ end
+ else
+ report_epdf("warning: nil value for index %a in array",i)
+ end
+ else
+ fatal_error("error: invalid value at index %a in array of %a",i,document.filename)
+ end
+ end
+ getmetatable(t).__index = nil
+ return t[k]
+end
+
+local function some_array(a,document)
+ local n = a and arrayGetLength(a) or 0
+ if n > 0 then
+ local t = { n = n }
+ setmetatable(t, {
+ __index = function(t,k)
+ return prepare(document,a,t,n,k)
+ end
+ } )
+ return t
+ end
+end
+
+local function get_array(object,document)
+ local a = getArray(object)
+ local n = a and arrayGetLength(a) or 0
+ if n > 0 then
+ local t = { n = n }
+ setmetatable(t, {
+ __index = function(t,k)
+ return prepare(document,a,t,n,k)
+ end
+ } )
+ return t
+ end
+end
+
+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)
+ end
+end
+
+local function get_stream(d,document)
+ if d then
+ streamReset(d)
+ local s = some_dictionary(streamGetDict(d),document)
+ getmetatable(s).__call = function(...) return streamaccess(d,...) end
+ return s
+ 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 u_pattern = lpeg.patterns.utfbom_16_be * lpeg.patterns.utf16_to_utf8_be
+----- b_pattern = lpeg.patterns.hextobytes
+
+local function get_string(v)
+ -- the toutf function only converts a utf16 string and leves the original
+ -- untouched otherwise; one might want to apply lpdf.frompdfdoc to a
+ -- non-unicode string
+ local s = getString(v)
+ if not s or s == "" then
+ return ""
+ end
+ local u = lpegmatch(u_pattern,s)
+ if u then
+ return u -- , "unicode"
+ end
+ -- this is too tricky and fails on e.g. reload of url www.pragma-ade.com)
+ -- local b = lpegmatch(b_pattern,s)
+ -- if b then
+ -- return b, "rawtext"
+ -- end
+ return s, "rawtext"
+end
+
+local function get_null()
+ return nil
+end
+
+-- we have dual access: by typenumber and by typename
+
+local function invalidaccess(k,document)
+ local fullname = type(document) == "table" and document.fullname
+ if fullname then
+ fatal_error("error, asking for key %a in checker of %a",k,fullname)
+ else
+ fatal_error("error, asking for key %a in checker",k)
+ end
+end
+
+checked_access = table.setmetatableindex(function(t,k)
+ return function(v,document)
+ invalidaccess(k,document)
+ end
+end)
+
+checked_access[typenumbers.boolean] = getBool
+checked_access[typenumbers.integer] = getNum
+checked_access[typenumbers.real] = getReal
+checked_access[typenumbers.string] = get_string -- getString
+checked_access[typenumbers.name] = getName
+checked_access[typenumbers.null] = get_null
+checked_access[typenumbers.array] = get_array -- d,document,r
+checked_access[typenumbers.dictionary] = get_dictionary -- d,document,r
+checked_access[typenumbers.stream] = get_stream
+checked_access[typenumbers.ref] = getRef
+
+for i=0,#typenames do
+ local checker = checked_access[i]
+ if not checker then
+ checker = function()
+ return function(v,document)
+ invalidaccess(i,document)
+ end
+ end
+ checked_access[i] = checker
+ end
+ checked_access[typenames[i]] = checker
+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.n,2 do
+ target[Names[i]] = Names[i+1]
+ end
+ else
+ local Kids = n.Kids
+ if Kids then
+ for i=1,Kids.n 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.n do
+ target = getkids(document,Kids[i],target)
+ end
+ elseif target then
+ target[#target+1] = n
+ else
+ target = { n }
+ end
+ return target
+ end
+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 [ ]
+-- >>
+-- >>
+
+local function getlayers(document)
+ local properties = document.Catalog.OCProperties
+ if properties then
+ local layers = properties.OCGs
+ if layers then
+ local t = { }
+ local n = layers.n
+ for i=1,n do
+ local layer = layers[i]
+ t[i] = layer.Name
+ end
+ t.n = n
+ return t
+ end
+ end
+end
+
+local function getstructure(document)
+ -- this might become a tree
+ return document.Catalog.StructTreeRoot
+end
+
+local function getpages(document,Catalog)
+ local __data__ = document.__data__
+ local __xrefs__ = document.__xrefs__
+ local __cache__ = document.__cache__
+ local __xref__ = document.__xref__
+ --
+ local catalog = __data__:getCatalog()
+ local pages = { }
+ local nofpages = catalog:getNumPages()
+ local metatable = { __index = Catalog.Pages }
+ --
+ for pagenumber=1,nofpages do
+ local pagereference = catalog:getPageRef(pagenumber).num
+ local pageobject = __xref__:fetch(pagereference,0)
+ local pagedata = get_dictionary(pageobject,document,pagereference,metatable)
+ if pagedata then
+ -- rawset(pagedata,"number",pagenumber)
+ pagedata.number = pagenumber
+ pages[pagenumber] = pagedata
+ __xrefs__[pagedata] = pagereference
+ __cache__[pagereference] = pagedata
+ else
+ report_epdf("missing pagedata at slot %i",i)
+ end
+ end
+ --
+ pages.n = nofpages
+ --
+ return pages
+end
+
+-- loader
+
+local function delayed(document,tag,f)
+ local t = { }
+ setmetatable(t, { __index = function(t,k)
+ local result = f()
+ if result then
+ document[tag] = result
+ return result[k]
+ end
+ end } )
+ return t
+end
+
+-- local catobj = data:getXRef():fetch(data:getXRef():getRootNum(),data:getXRef():getRootGen())
+-- print(catobj:getDict(),data:getXRef():getCatalog():getDict())
+
+local loaded = { }
+
+function lpdf_epdf.load(filename)
+ local document = loaded[filename]
+ if not document then
+ statistics.starttiming(lpdf_epdf)
+ local __data__ = pdf_open(filename) -- maybe resolvers.find_file
+ if __data__ then
+ local __xref__ = __data__:getXRef()
+ document = {
+ filename = filename,
+ __cache__ = { },
+ __xrefs__ = { },
+ __fonts__ = { },
+ __data__ = __data__,
+ __xref__ = __xref__,
+ }
+ --
+ initialize_methods(__xref__)
+ --
+ local Catalog = some_dictionary(__xref__:getCatalog():getDict(),document)
+ local Info = some_dictionary(__xref__:getDocInfo():getDict(),document)
+ --
+ document.Catalog = Catalog
+ document.Info = Info
+ -- a few handy helper tables
+ document.pages = delayed(document,"pages", function() return getpages(document,Catalog) end)
+ document.destinations = delayed(document,"destinations", function() return getnames(document,Catalog.Names and Catalog.Names.Dests) end)
+ document.javascripts = delayed(document,"javascripts", function() return getnames(document,Catalog.Names and Catalog.Names.JS) end)
+ document.widgets = delayed(document,"widgets", function() return getnames(document,Catalog.Names and Catalog.Names.AcroForm) end)
+ document.embeddedfiles = delayed(document,"embeddedfiles",function() return getnames(document,Catalog.Names and Catalog.Names.EmbeddedFiles) end)
+ document.layers = delayed(document,"layers", function() return getlayers(document) end)
+ document.structure = delayed(document,"structure", function() return getstructure(document) 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)
+ local document = loaded[filename]
+ if document then
+ loaded[document] = nil
+ loaded[filename] = nil
+ end
+end
+
+-- for k, v in next, expand(t) do
+
+local function expand(t)
+ if type(t) == "table" then
+ local dummy = t.dummy
+ end
+ return t
+end
+
+-- for k, v in expanded(t) do
+
+local function expanded(t)
+ if type(t) == "table" then
+ local dummy = t.dummy
+ end
+ return next, t
+end
+
+lpdf_epdf.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 hexdigit = R("09","AF")
+local numchar = ( P("\\") * ( (R("09")^3/tonumber) + C(1) ) ) + C(1)
+local number = lpegpatterns.number / tonumber
+local spaces = lpegpatterns.whitespace^1
+local optspaces = lpegpatterns.whitespace^0
+local keyword = P("/") * C(R("AZ","az","09")^1)
+local operator = C((R("AZ","az")+P("'")+P('"'))^1)
+
+local grammar = P { "start",
+ start = (keyword + number + V("dictionary") + V("unicode") + V("string") + V("unicode")+ V("array") + spaces)^1,
+ -- keyvalue = (keyword * spaces * V("start") + spaces)^1,
+ keyvalue = optspaces * Cf(Ct("") * Cg(keyword * optspaces * V("start") * optspaces)^1,rawset),
+ array = P("[") * Ct(V("start")^1) * P("]"),
+ dictionary = P("<<") * V("keyvalue") * P(">>"),
+ unicode = P("<") * Ct(Cc("hex") * C((1-P(">"))^1)) * P(">"),
+ string = P("(") * Ct(Cc("dec") * C((V("string")+numchar)^1)) * P(")"), -- untested
+}
+
+local operation = Ct(grammar^1 * operator)
+local parser = Ct((operation + P(1))^1)
+
+-- 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
+ 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
+ -- -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 { }
+ }
+ table.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 neet it I can improve it, fo rinstance
+-- 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) 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].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
+
+-- document.Catalog.StructTreeRoot.ParentTree.Nums[2][1].A.P[1])
+
+-- helpers
+
+-- function lpdf_epdf.getdestinationpage(document,name)
+-- local destination = document.__data__:findDest(name)
+-- return destination and destination.number
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua
new file mode 100644
index 00000000000..75d0ba98e03
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua
@@ -0,0 +1,1423 @@
+if not modules then modules = { } end modules ['lpdf-fld'] = {
+ 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"
+}
+
+-- The problem with widgets is that so far each version of acrobat
+-- has some rendering problem. I tried to keep up with this but
+-- it makes no sense to do so as one cannot rely on the viewer
+-- not changing. Especially Btn fields are tricky as their appearences
+-- need to be synchronized in the case of children but e.g. acrobat
+-- 10 does not retain the state and forces a check symbol. If you
+-- make a file in acrobat then it has MK entries that seem to overload
+-- the already present appearance streams (they're probably only meant for
+-- printing) as it looks like the viewer has some fallback on (auto
+-- generated) MK behaviour built in. So ... hard to test. Unfortunately
+-- not even the default appearance is generated. This will probably be
+-- solved at some point.
+--
+-- Also, for some reason the viewer does not always show custom appearances
+-- when fields are being rolled over or clicked upon, and circles or checks
+-- pop up when you don't expect them. I fear that this kind of instability
+-- eventually will kill pdf forms. After all, the manual says: "individual
+-- annotation handlers may ignore this entry and provide their own appearances"
+-- and one might wonder what 'individual' means here, but effectively this
+-- renders the whole concept of appearances useless.
+--
+-- Okay, here is one observation. A pdf file contains objects and one might
+-- consider each one to be a static entity when read in. However, acrobat
+-- starts rendering and seems to manipulate (appearance streams) of objects
+-- in place (this is visible when the file is saved again). And, combined
+-- with some other caching and hashing, this might give side effects for
+-- shared objects. So, it seems that for some cases one can best be not too
+-- clever and not share but duplicate information. Of course this defeats the
+-- whole purpose of these objects. Of course I can be wrong.
+--
+-- A rarther weird side effect of the viewer is that the highlighting of fields
+-- obscures values, unless you uses one of the BS variants, and this makes
+-- custum appearances rather useless as there is no way to control this apart
+-- from changing the viewer preferences. It could of course be a bug but it would
+-- be nice if the highlighting was at least transparent. I have no clue why the
+-- built in shapes work ok (some xform based appearances are generated) while
+-- equally valid other xforms fail. It looks like acrobat appearances come on
+-- top (being refered to in the MK) while custom ones are behind the highlight
+-- rectangle. One can disable the "Show border hover color for fields" option
+-- in the preferences. If you load java-imp-rhh this side effect gets disabled
+-- and you get what you expect (it took me a while to figure out this hack).
+--
+-- When highlighting is enabled, those default symbols flash up, so it looks
+-- like we have some inteference between this setting and custom appearances.
+--
+-- Anyhow, the NeedAppearances is really needed in order to get a rendering
+-- for printing especially when highlighting (those colorfull foregrounds) is
+-- on.
+
+local tostring, next = tostring, next
+local gmatch, lower, format, formatters = string.gmatch, string.lower, string.format, string.formatters
+local lpegmatch = lpeg.match
+local utfchar = utf.char
+local bpfactor, todimen = number.dimenfactors.bp, string.todimen
+
+local trace_fields = false trackers.register("backends.fields", function(v) trace_fields = v end)
+
+local report_fields = logs.reporter("backend","fields")
+
+local backends, lpdf = backends, lpdf
+
+local variables = interfaces.variables
+local context = context
+
+local references = structures.references
+local settings_to_array = utilities.parsers.settings_to_array
+
+local pdfbackend = backends.pdf
+
+local nodeinjections = pdfbackend.nodeinjections
+local codeinjections = pdfbackend.codeinjections
+local registrations = pdfbackend.registrations
+
+local registeredsymbol = codeinjections.registeredsymbol
+
+local pdfstream = lpdf.stream
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfconstant = lpdf.constant
+local pdftoeight = lpdf.toeight
+local pdfflushobject = lpdf.flushobject
+local pdfshareobjectreference = lpdf.shareobjectreference
+local pdfshareobject = lpdf.shareobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfaction = lpdf.action
+
+local pdfcolor = lpdf.color
+local pdfcolorvalues = lpdf.colorvalues
+local pdflayerreference = lpdf.layerreference
+
+local hpack_node = node.hpack
+
+local submitoutputformat = 0 -- 0=unknown 1=HTML 2=FDF 3=XML => not yet used, needs to be checked
+
+local pdf_widget = pdfconstant("Widget")
+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_off = pdfconstant("Off")
+local pdf_p = pdfconstant("P") -- None Invert Outline Push
+local pdf_n = pdfconstant("N") -- None Invert Outline Push
+--
+local pdf_no_rect = pdfarray { 0, 0, 0, 0 }
+
+local splitter = lpeg.splitat("=>")
+
+local formats = {
+ html = 1, fdf = 2, xml = 3,
+}
+
+function codeinjections.setformsmethod(name)
+ submitoutputformat = formats[lower(name)] or formats.xml
+end
+
+local flag = { -- /Ff
+ ReadOnly = 2^ 0, -- 1
+ Required = 2^ 1, -- 2
+ NoExport = 2^ 2, -- 3
+ MultiLine = 2^12, -- 13
+ Password = 2^13, -- 14
+ NoToggleToOff = 2^14, -- 15
+ Radio = 2^15, -- 16
+ PushButton = 2^16, -- 17
+ PopUp = 2^17, -- 18
+ Edit = 2^18, -- 19
+ Sort = 2^19, -- 20
+ FileSelect = 2^20, -- 21
+ DoNotSpellCheck = 2^22, -- 23
+ DoNotScroll = 2^23, -- 24
+ Comb = 2^24, -- 25
+ RichText = 2^25, -- 26
+ RadiosInUnison = 2^25, -- 26
+ CommitOnSelChange = 2^26, -- 27
+}
+
+local plus = { -- /F
+ Invisible = 2^0, -- 1
+ Hidden = 2^1, -- 2
+ Printable = 2^2, -- 3
+ Print = 2^2, -- 3
+ NoZoom = 2^3, -- 4
+ NoRotate = 2^4, -- 5
+ NoView = 2^5, -- 6
+ ReadOnly = 2^6, -- 7
+ Locked = 2^7, -- 8
+ ToggleNoView = 2^8, -- 9
+ LockedContents = 2^9, -- 10,
+ AutoView = 2^8, -- 6 + 9 ?
+}
+
+-- todo: check what is interfaced
+
+flag.readonly = flag.ReadOnly
+flag.required = flag.Required
+flag.protected = flag.Password
+flag.sorted = flag.Sort
+flag.unavailable = flag.NoExport
+flag.nocheck = flag.DoNotSpellCheck
+flag.fixed = flag.DoNotScroll
+flag.file = flag.FileSelect
+
+plus.hidden = plus.Hidden
+plus.printable = plus.Printable
+plus.auto = plus.AutoView
+
+-- some day .. lpeg with function or table
+
+local function fieldflag(specification) -- /Ff
+ local o, n = specification.option, 0
+ if o and o ~= "" then
+ for f in gmatch(o,"[^, ]+") do
+ n = n + (flag[f] or 0)
+ end
+ end
+ return n
+end
+
+local function fieldplus(specification) -- /F
+ local o, n = specification.option, 0
+ if o and o ~= "" then
+ for p in gmatch(o,"[^, ]+") do
+ n = n + (plus[p] or 0)
+ end
+ end
+-- n = n + 4
+ return n
+end
+
+-- keep:
+--
+-- local function checked(what)
+-- local set, bug = references.identify("",what)
+-- if not bug and #set > 0 then
+-- local r, n = pdfaction(set)
+-- return pdfshareobjectreference(r)
+-- end
+-- end
+--
+-- local function fieldactions(specification) -- share actions
+-- local d, a = { }, nil
+-- a = specification.mousedown
+-- or specification.clickin if a and a ~= "" then d.D = checked(a) end
+-- a = specification.mouseup
+-- or specification.clickout if a and a ~= "" then d.U = checked(a) end
+-- a = specification.regionin if a and a ~= "" then d.E = checked(a) end -- Enter
+-- a = specification.regionout if a and a ~= "" then d.X = checked(a) end -- eXit
+-- a = specification.afterkey if a and a ~= "" then d.K = checked(a) end
+-- a = specification.format if a and a ~= "" then d.F = checked(a) end
+-- a = specification.validate if a and a ~= "" then d.V = checked(a) end
+-- a = specification.calculate if a and a ~= "" then d.C = checked(a) end
+-- a = specification.focusin if a and a ~= "" then d.Fo = checked(a) end
+-- a = specification.focusout if a and a ~= "" then d.Bl = checked(a) end
+-- a = specification.openpage if a and a ~= "" then d.PO = checked(a) end
+-- a = specification.closepage if a and a ~= "" then d.PC = checked(a) end
+-- -- a = specification.visiblepage if a and a ~= "" then d.PV = checked(a) end
+-- -- a = specification.invisiblepage if a and a ~= "" then d.PI = checked(a) end
+-- return next(d) and pdfdictionary(d)
+-- end
+
+local mapping = {
+ mousedown = "D", clickin = "D",
+ mouseup = "U", clickout = "U",
+ regionin = "E",
+ regionout = "X",
+ afterkey = "K",
+ format = "F",
+ validate = "V",
+ calculate = "C",
+ focusin = "Fo",
+ focusout = "Bl",
+ openpage = "PO",
+ closepage = "PC",
+ -- visiblepage = "PV",
+ -- invisiblepage = "PI",
+}
+
+local function fieldactions(specification) -- share actions
+ local d = nil
+ for key, target in next, mapping do
+ local code = specification[key]
+ if code and code ~= "" then
+ -- local a = checked(code)
+ local set, bug = references.identify("",code)
+ if not bug and #set > 0 then
+ local a = pdfaction(set) -- r, n
+ if a then
+ local r = pdfshareobjectreference(a)
+ if d then
+ d[target] = r
+ else
+ d = pdfdictionary { [target] = r }
+ end
+ else
+ report_fields("invalid field action %a, case %s",code,2)
+ end
+ else
+ report_fields("invalid field action %a, case %s",code,1)
+ end
+ end
+ end
+ -- if d then
+ -- d = pdfshareobjectreference(d) -- not much overlap or maybe only some patterns
+ -- end
+ return d
+end
+
+-- fonts and color
+
+local pdfdocencodingvector, pdfdocencodingcapsule
+
+-- The pdf doc encoding vector is needed in order to trigger propper unicode. Interesting is that when
+-- a glyph is not in the vector, it is still visible as it is taken from some other font. Messy.
+
+-- To be checked: only when text/line fields.
+
+local function checkpdfdocencoding()
+ report_fields("adding pdfdoc encoding vector")
+ local encoding = dofile(resolvers.findfile("lpdf-enc.lua")) -- no checking, fatal if not present
+ pdfdocencodingvector = pdfreference(pdfflushobject(encoding))
+ local capsule = pdfdictionary {
+ PDFDocEncoding = pdfdocencodingvector
+ }
+ pdfdocencodingcapsule = pdfreference(pdfflushobject(capsule))
+ checkpdfdocencoding = function() end
+end
+
+local fontnames = {
+ rm = {
+ tf = "Times-Roman",
+ bf = "Times-Bold",
+ it = "Times-Italic",
+ sl = "Times-Italic",
+ bi = "Times-BoldItalic",
+ bs = "Times-BoldItalic",
+ },
+ ss = {
+ tf = "Helvetica",
+ bf = "Helvetica-Bold",
+ it = "Helvetica-Oblique",
+ sl = "Helvetica-Oblique",
+ bi = "Helvetica-BoldOblique",
+ bs = "Helvetica-BoldOblique",
+ },
+ tt = {
+ tf = "Courier",
+ bf = "Courier-Bold",
+ it = "Courier-Oblique",
+ sl = "Courier-Oblique",
+ bi = "Courier-BoldOblique",
+ bs = "Courier-BoldOblique",
+ },
+ symbol = {
+ dingbats = "ZapfDingbats",
+ }
+}
+
+local usedfonts = { }
+
+local function fieldsurrounding(specification)
+ local fontsize = specification.fontsize or "12pt"
+ local fontstyle = specification.fontstyle or "rm"
+ local fontalternative = specification.fontalternative or "tf"
+ local colorvalue = tonumber(specification.colorvalue)
+ local s = fontnames[fontstyle]
+ if not s then
+ fontstyle, s = "rm", fontnames.rm
+ end
+ local a = s[fontalternative]
+ if not a then
+ alternative, a = "tf", s.tf
+ end
+ local tag = fontstyle .. fontalternative
+ 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)
+ -- 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
+ report_fields("using font, style %a, alternative %a, size %p, tag %a, code %a",fontstyle,fontalternative,fontsize,tag,fontcode)
+ report_fields("using color, value %a, code %a",colorvalue,colorcode)
+ end
+ local stream = pdfstream {
+ pdfconstant(tag),
+ formatters["%s %s"](fontcode,colorcode)
+ }
+ usedfonts[tag] = a -- the name
+ -- move up with "x.y Ts"
+ return tostring(stream)
+end
+
+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 f = pdfdictionary {
+ Type = pdffonttype,
+ Subtype = pdffontsubtype,
+ Name = pdfconstant(tag),
+ BaseFont = pdfconstant(name),
+ Encoding = pdfdocencodingvector,
+ }
+ d[tag] = pdfreference(pdfflushobject(f))
+ end
+ return d
+ end
+end
+
+-- symbols
+
+local function fieldappearances(specification)
+ -- todo: caching
+ local values = specification.values
+ local default = specification.default -- todo
+ if not values then
+ -- error
+ return
+ end
+ local v = settings_to_array(values)
+ local n, r, d
+ if #v == 1 then
+ n, r, d = v[1], v[1], v[1]
+ elseif #v == 2 then
+ n, r, d = v[1], v[1], v[2]
+ else
+ n, r, d = v[1], v[2], v[3]
+ end
+ local appearance = pdfdictionary {
+ 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.
+--
+-- TODO: the same as radio .. play safe and use different names.
+
+local function fieldstates_check(specification,forceyes,values,default,yesdefault)
+ -- we don't use Opt here (too messy for radio buttons)
+ local values, default = values or specification.values, default or specification.default
+ if not values or values == "" then
+ -- error
+ return
+ end
+ local v = settings_to_array(values)
+ local yes, off, yesn, yesr, yesd, offn, offr, offd
+ if #v == 1 then
+ yes, off = v[1], v[1]
+ else
+ yes, off = v[1], v[2]
+ end
+ local yesshown, yesvalue = lpegmatch(splitter,yes)
+ if not (yesshown and yesvalue) then
+ yesshown = yes, yes
+ end
+ yes = settings_to_array(yesshown)
+ local offshown, offvalue = lpegmatch(splitter,off)
+ if not (offshown and offvalue) then
+ offshown = off, off
+ end
+ off = settings_to_array(offshown)
+ if #yes == 1 then
+ yesn, yesr, yesd = yes[1], yes[1], yes[1]
+ elseif #yes == 2 then
+ yesn, yesr, yesd = yes[1], yes[1], yes[2]
+ else
+ yesn, yesr, yesd = yes[1], yes[2], yes[3]
+ end
+ if #off == 1 then
+ offn, offr, offd = off[1], off[1], off[1]
+ elseif #off == 2 then
+ offn, offr, offd = off[1], off[1], off[2]
+ else
+ offn, offr, offd = off[1], off[2], off[3]
+ end
+ if not yesvalue then
+ yesvalue = yesdefault or yesn
+ end
+ 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)
+ else
+ default = pdf_off
+ end
+ local appearance
+ if false then -- needs testing
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfshareobjectreference(pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
+ R = pdfshareobjectreference(pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
+ D = pdfshareobjectreference(pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
+ }
+ else
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ }
+ end
+ local appearanceref = pdfshareobjectreference(appearance)
+ -- local appearanceref = pdfreference(pdfflushobject(appearance))
+ return appearanceref, default, yesvalue
+end
+
+-- It looks like there is always a (MK related) symbol used and that
+-- the appearances are only used as ornaments behind a symbol. So,
+-- contrary to what we did when widgets showed up, we now limit
+-- ourself to more dumb definitions. Especially when highlighting is
+-- enabled weird interferences happen. So, we play safe (some nice code
+-- has been removed that worked well till recently).
+
+local function fieldstates_radio(specification,name,parent)
+ local values = values or specification.values
+ local default = default or parent.default -- specification.default
+ if not values or values == "" then
+ -- error
+ return
+ end
+ local v = settings_to_array(values)
+ local yes, off, yesn, yesr, yesd, offn, offr, offd
+ if #v == 1 then
+ yes, off = v[1], v[1]
+ else
+ yes, off = v[1], v[2]
+ end
+ -- yes keys might be the same in the three appearances within a field
+ -- but can best be different among fields ... don't ask why
+ local yessymbols, yesvalue = lpegmatch(splitter,yes) -- n,r,d=>x
+ if not (yessymbols and yesvalue) then
+ yessymbols = yes
+ end
+ if not yesvalue then
+ yesvalue = name
+ end
+ yessymbols = settings_to_array(yessymbols)
+ if #yessymbols == 1 then
+ yesn = yessymbols[1]
+ yesr = yesn
+ yesd = yesr
+ elseif #yessymbols == 2 then
+ yesn = yessymbols[1]
+ yesr = yessymbols[2]
+ yesd = yesr
+ else
+ yesn = yessymbols[1]
+ yesr = yessymbols[2]
+ yesd = yessymbols[3]
+ end
+ -- we don't care about names, as all will be /Off
+ local offsymbols = lpegmatch(splitter,off) or off
+ offsymbols = settings_to_array(offsymbols)
+ if #offsymbols == 1 then
+ offn = offsymbols[1]
+ offr = offn
+ offd = offr
+ elseif #offsymbols == 2 then
+ offn = offsymbols[1]
+ offr = offsymbols[2]
+ offd = offr
+ else
+ offn = offsymbols[1]
+ offr = offsymbols[2]
+ offd = offsymbols[3]
+ end
+ if default == name then
+ default = pdfconstant(name)
+ else
+ default = pdf_off
+ end
+ --
+ local appearance
+ if false then -- needs testing
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
+ R = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
+ D = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
+ }
+ else
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfdictionary { [name] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { [name] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { [name] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ }
+ end
+ local appearanceref = pdfshareobjectreference(appearance) -- pdfreference(pdfflushobject(appearance))
+ return appearanceref, default, yesvalue
+end
+
+local function fielddefault(field)
+ local default = field.default
+ if not default or default == "" then
+ local values = settings_to_array(field.values)
+ default = values[1]
+ end
+ if not default or default == "" then
+ return pdf_off
+ else
+ return pdfconstant(default)
+ end
+end
+
+local function fieldoptions(specification)
+ local values = specification.values
+ local default = specification.default
+ if values then
+ local v = settings_to_array(values)
+ for i=1,#v do
+ local vi = v[i]
+ local shown, value = lpegmatch(splitter,vi)
+ if shown and value then
+ v[i] = pdfarray { pdfunicode(value), shown }
+ else
+ v[i] = pdfunicode(v[i])
+ end
+ end
+ return pdfarray(v)
+ end
+end
+
+local mapping = {
+ -- acrobat compliant (messy, probably some pdfdoc encoding interference here)
+ check = "4", -- 0x34
+ circle = "l", -- 0x6C
+ cross = "8", -- 0x38
+ diamond = "u", -- 0x75
+ square = "n", -- 0x6E
+ star = "H", -- 0x48
+}
+
+local function todingbat(n)
+ if n and n ~= "" then
+ return mapping[n] or ""
+ end
+end
+
+local function fieldrendering(specification)
+ local bvalue = tonumber(specification.backgroundcolorvalue)
+ local fvalue = tonumber(specification.framecolorvalue)
+ local svalue = specification.fontsymbol
+ if bvalue or fvalue or (svalue and svalue ~= "") then
+ return pdfdictionary {
+ BG = bvalue and pdfarray { pdfcolorvalues(3,bvalue) } or nil, -- or zero_bg,
+ BC = fvalue and pdfarray { pdfcolorvalues(3,fvalue) } or nil, -- or zero_bc,
+ CA = svalue and pdfstring (svalue) or nil,
+ }
+ end
+end
+
+-- layers
+
+local function fieldlayer(specification) -- we can move this in line
+ local layer = specification.layer
+ return (layer and pdflayerreference(layer)) or nil
+end
+
+-- defining
+
+local fields, radios, clones, fieldsets, calculationset = { }, { }, { }, { }, nil
+
+local xfdftemplate = [[
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xfdf xmlns='http://ns.adobe.com/xfdf/'>
+ <f href='%s.pdf'/>
+ <fields>
+%s
+ </fields>
+</xfdf>
+]]
+
+function codeinjections.exportformdata(name)
+ local result = { }
+ for k, v in table.sortedhash(fields) do
+ result[#result+1] = formatters[" <field name='%s'><value>%s</value></field>"](v.name or k,v.default or "")
+ end
+ local base = file.basename(tex.jobname)
+ local xfdf = format(xfdftemplate,base,table.concat(result,"\n"))
+ if not name or name == "" then
+ name = base
+ end
+ io.savedata(file.addsuffix(name,"xfdf"),xfdf)
+end
+
+function codeinjections.definefieldset(tag,list)
+ fieldsets[tag] = list
+end
+
+function codeinjections.getfieldset(tag)
+ return fieldsets[tag]
+end
+
+local function fieldsetlist(tag)
+ if tag then
+ local ft = fieldsets[tag]
+ if ft then
+ local a = pdfarray()
+ for name in gmatch(list,"[^, ]+") do
+ local f = field[name]
+ if f and f.pobj then
+ a[#a+1] = pdfreference(f.pobj)
+ end
+ end
+ return a
+ end
+ end
+end
+
+function codeinjections.setfieldcalculationset(tag)
+ calculationset = tag
+end
+
+interfaces.implement {
+ name = "setfieldcalculationset",
+ actions = codeinjections.setfieldcalculationset,
+ arguments = "string",
+}
+
+local function predefinesymbols(specification)
+ local values = specification.values
+ if values then
+ local symbols = settings_to_array(values)
+ for i=1,#symbols do
+ local symbol = symbols[i]
+ local a, b = lpegmatch(splitter,symbol)
+ codeinjections.presetsymbol(a or symbol)
+ end
+ end
+end
+
+function codeinjections.getdefaultfieldvalue(name)
+ local f = fields[name]
+ if f then
+ local values = f.values
+ local default = f.default
+ if not default or default == "" then
+ local symbols = settings_to_array(values)
+ local symbol = symbols[1]
+ if symbol then
+ local a, b = lpegmatch(splitter,symbol) -- splits at =>
+ default = a or symbol
+ end
+ end
+ return default
+ end
+end
+
+function codeinjections.definefield(specification)
+ local n = specification.name
+ local f = fields[n]
+ if not f then
+ local fieldtype = specification.type
+ if not fieldtype then
+ if trace_fields then
+ report_fields("invalid definition for %a, unknown type",n)
+ end
+ elseif fieldtype == "radio" then
+ local values = specification.values
+ if values and values ~= "" then
+ values = settings_to_array(values)
+ for v=1,#values do
+ radios[values[v]] = { parent = n }
+ end
+ fields[n] = specification
+ if trace_fields then
+ report_fields("defining %a as type %a",n,"radio")
+ end
+ elseif trace_fields then
+ report_fields("invalid definition of radio %a, missing values",n)
+ end
+ elseif fieldtype == "sub" then
+ -- not in main field list !
+ local radio = radios[n]
+ if radio then
+ -- merge specification
+ for key, value in next, specification do
+ radio[key] = value
+ end
+ if trace_fields then
+ local p = radios[n] and radios[n].parent
+ report_fields("defining %a as type sub of radio %a",n,p)
+ end
+ elseif trace_fields then
+ report_fields("invalid definition of radio sub %a, no parent given",n)
+ end
+ predefinesymbols(specification)
+ elseif fieldtype == "text" or fieldtype == "line" then
+ fields[n] = specification
+ if trace_fields then
+ report_fields("defining %a as type %a",n,fieldtype)
+ end
+ if specification.values ~= "" and specification.default == "" then
+ specification.default, specification.values = specification.values, nil
+ end
+ else
+ fields[n] = specification
+ if trace_fields then
+ report_fields("defining %a as type %a",n,fieldtype)
+ end
+ predefinesymbols(specification)
+ end
+ elseif trace_fields then
+ report_fields("invalid definition for %a, already defined",n)
+ end
+end
+
+function codeinjections.clonefield(specification) -- obsolete
+ local p, c, v = specification.parent, specification.children, specification.alternative
+ if not p or not c then
+ if trace_fields then
+ report_fields("invalid clone, children %a, parent %a, alternative %a",c,p,v)
+ end
+ return
+ end
+ local x = fields[p] or radios[p]
+ if not x then
+ if trace_fields then
+ report_fields("invalid clone, unknown parent %a",p)
+ end
+ return
+ end
+ for n in gmatch(c,"[^, ]+") do
+ local f, r, c = fields[n], radios[n], clones[n]
+ if f or r or c then
+ if trace_fields then
+ report_fields("already cloned, child %a, parent %a, alternative %a",n,p,v)
+ end
+ else
+ if trace_fields then
+ report_fields("cloning, child %a, parent %a, alternative %a",n,p,v)
+ end
+ clones[n] = specification
+ predefinesymbols(specification)
+ end
+ end
+end
+
+function codeinjections.getfieldcategory(name)
+ local f = fields[name] or radios[name] or clones[name]
+ if f then
+ local g = f.category
+ if not g or g == "" then
+ local v, p, t = f.alternative, f.parent, f.type
+ if v == "clone" or v == "copy" then
+ f = fields[p] or radios[p]
+ g = f and f.category
+ elseif t == "sub" then
+ f = fields[p]
+ g = f and f.category
+ end
+ end
+ return g
+ end
+end
+
+--
+
+function codeinjections.validfieldcategory(name)
+ return fields[name] or radios[name] or clones[name]
+end
+
+function codeinjections.validfieldset(name)
+ return fieldsets[tag]
+end
+
+function codeinjections.validfield(name)
+ return fields[name]
+end
+
+--
+
+local alignments = {
+ flushleft = 0, right = 0,
+ center = 1, middle = 1,
+ flushright = 2, left = 2,
+}
+
+local function fieldalignment(specification)
+ return alignments[specification.align] or 0
+end
+
+local function enhance(specification,option)
+ local so = specification.option
+ if so and so ~= "" then
+ specification.option = so .. "," .. option
+ else
+ specification.option = option
+ end
+ return specification
+end
+
+-- finish
+
+local collected = pdfarray()
+local forceencoding = false
+
+local function finishfields()
+ local sometext = forceencoding
+ for name, field in next, fields do
+ local kids = field.kids
+ if kids then
+ pdfflushobject(field.kidsnum,kids)
+ end
+ local opt = field.opt
+ if opt then
+ pdfflushobject(field.optnum,opt)
+ end
+ local type = field.type
+ if not sometext and (type == "text" or type == "line") then
+ sometext = true
+ end
+ end
+ for name, field in next, radios do
+ local kids = field.kids
+ if kids then
+ pdfflushobject(field.kidsnum,kids)
+ end
+ local opt = field.opt
+ if opt then
+ pdfflushobject(field.optnum,opt)
+ end
+ end
+ if #collected > 0 then
+ local acroform = pdfdictionary {
+ NeedAppearances = true,
+ Fields = pdfreference(pdfflushobject(collected)),
+ CO = fieldsetlist(calculationset),
+ }
+ if sometext then
+ checkpdfdocencoding()
+ usedfonts.tttf = fontnames.tt.tf
+ acroform.DA = "/tttf 12 Tf 0 g"
+ acroform.DR = pdfdictionary {
+ Font = registerfonts(),
+ Encoding = pdfdocencodingcapsule,
+ }
+ end
+ lpdf.addtocatalog("AcroForm",pdfreference(pdfflushobject(acroform)))
+ end
+end
+
+lpdf.registerdocumentfinalizer(finishfields,"form fields")
+
+local methods = { }
+
+function nodeinjections.typesetfield(name,specification)
+ local field = fields[name] or radios[name] or clones[name]
+ if not field then
+ report_fields( "unknown child %a",name)
+ -- unknown field
+ return
+ end
+ local alternative, parent = field.alternative, field.parent
+ if alternative == "copy" or alternative == "clone" then -- only in clones
+ field = fields[parent] or radios[parent]
+ end
+ local method = methods[field.type]
+ if method then
+ return method(name,specification,alternative)
+ else
+ report_fields( "unknown method %a for child %a",field.type,name)
+ end
+end
+
+local function save_parent(field,specification,d,hasopt)
+ local kidsnum = pdfreserveobject()
+ d.Kids = pdfreference(kidsnum)
+ field.kidsnum = kidsnum
+ field.kids = pdfarray()
+ if hasopt then
+ local optnum = pdfreserveobject()
+ d.Opt = pdfreference(optnum)
+ field.optnum = optnum
+ field.opt = pdfarray()
+ end
+ local pnum = pdfflushobject(d)
+ field.pobj = pnum
+ collected[#collected+1] = pdfreference(pnum)
+end
+
+local function save_kid(field,specification,d,optname)
+ local kn = pdfreserveobject()
+ field.kids[#field.kids+1] = pdfreference(kn)
+ if optname then
+ local opt = field.opt
+ if opt then
+ opt[#opt+1] = optname
+ end
+ end
+ local width, height, depth = specification.width or 0, specification.height or 0, specification.depth
+ local box = hpack_node(nodeinjections.annotation(width,height,depth,d(),kn))
+ box.width, box.height, box.depth = width, height, depth -- redundant
+ return box
+end
+
+local function makelineparent(field,specification)
+ local text = pdfunicode(field.default)
+ local length = tonumber(specification.length or 0) or 0
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ FT = pdf_tx,
+ Q = fieldalignment(specification),
+ MaxLen = length == 0 and 1000 or length,
+ DV = text,
+ V = text,
+ }
+ save_parent(field,specification,d)
+end
+
+local function makelinechild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent text %a",parent.name)
+ end
+ makelineparent(parent,specification)
+ end
+ else
+ parent = fields[name]
+ field = parent
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent text %a",name)
+ end
+ makelineparent(parent,specification)
+ end
+ end
+ if trace_fields then
+ report_fields("using child text %a",name)
+ end
+ -- we could save a little by not setting some key/value when it's the
+ -- same as parent but it would cost more memory to keep track of it
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ MK = fieldrendering(specification),
+ Q = fieldalignment(specification),
+ }
+ return save_kid(parent,specification,d)
+end
+
+function methods.line(name,specification)
+ return makelinechild(name,specification)
+end
+
+function methods.text(name,specification)
+ return makelinechild(name,enhance(specification,"MultiLine"))
+end
+
+-- copy of line ... probably also needs a /Lock
+
+local function makesignatureparent(field,specification)
+ local text = pdfunicode(field.default)
+ local length = tonumber(specification.length or 0) or 0
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ FT = pdf_sig,
+ Q = fieldalignment(specification),
+ MaxLen = length == 0 and 1000 or length,
+ DV = text,
+ V = text,
+ }
+ save_parent(field,specification,d)
+end
+
+local function makesignaturechild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent signature %a",parent.name)
+ end
+ makesignatureparent(parent,specification)
+ end
+ else
+ parent = fields[name]
+ field = parent
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent text %a",name)
+ end
+ makesignatureparent(parent,specification)
+ end
+ end
+ if trace_fields then
+ report_fields("using child text %a",name)
+ end
+ -- we could save a little by not setting some key/value when it's the
+ -- same as parent but it would cost more memory to keep track of it
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ MK = fieldrendering(specification),
+ Q = fieldalignment(specification),
+ }
+ return save_kid(parent,specification,d)
+end
+
+function methods.signature(name,specification)
+ return makesignaturechild(name,specification)
+end
+--
+
+local function makechoiceparent(field,specification)
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ FT = pdf_ch,
+ Opt = fieldoptions(field), -- todo
+ }
+ save_parent(field,specification,d)
+end
+
+local function makechoicechild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent choice %a",parent.name)
+ end
+ makechoiceparent(parent,specification,extras)
+ end
+ else
+ parent = fields[name]
+ field = parent
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent choice %a",name)
+ end
+ makechoiceparent(parent,specification,extras)
+ end
+ end
+ if trace_fields then
+ report_fields("using child choice %a",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ }
+ return save_kid(parent,specification,d) -- do opt here
+end
+
+function methods.choice(name,specification)
+ return makechoicechild(name,specification)
+end
+
+function methods.popup(name,specification)
+ return makechoicechild(name,enhance(specification,"PopUp"))
+end
+
+function methods.combo(name,specification)
+ return makechoicechild(name,enhance(specification,"PopUp,Edit"))
+end
+
+local function makecheckparent(field,specification)
+ 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),
+ FT = pdf_btn,
+ V = fielddefault(field),
+ }
+ save_parent(field,specification,d,true)
+end
+
+local function makecheckchild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent check %a",parent.name)
+ end
+ makecheckparent(parent,specification,extras)
+ end
+ else
+ parent = fields[name]
+ field = parent
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent check %a",name)
+ end
+ makecheckparent(parent,specification,extras)
+ end
+ end
+ if trace_fields then
+ report_fields("using child check %a",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ H = pdf_n,
+ }
+ local fontsymbol = specification.fontsymbol
+ if fontsymbol and fontsymbol ~= "" then
+ specification.fontsymbol = todingbat(fontsymbol)
+ specification.fontstyle = "symbol"
+ specification.fontalternative = "dingbats"
+ d.DA = fieldsurrounding(specification)
+ d.MK = fieldrendering(specification)
+ return save_kid(parent,specification,d)
+ else
+ local appearance, default, value = fieldstates_check(field,true)
+ d.AS = default
+ d.AP = appearance
+ return save_kid(parent,specification,d,value)
+ end
+end
+
+function methods.check(name,specification)
+ return makecheckchild(name,specification)
+end
+
+local function makepushparent(field,specification) -- check if we can share with the previous
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ FT = pdf_btn,
+ AP = fieldappearances(field),
+ H = pdf_p,
+ }
+ save_parent(field,specification,d)
+end
+
+local function makepushchild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent push %a",parent.name)
+ end
+ makepushparent(parent,specification)
+ end
+ else
+ parent = fields[name]
+ field = parent
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent push %a",name)
+ end
+ makepushparent(parent,specification)
+ end
+ end
+ if trace_fields then
+ report_fields("using child push %a",name)
+ end
+ local fontsymbol = specification.fontsymbol
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(field.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ H = pdf_p,
+ }
+ if fontsymbol and fontsymbol ~= "" then
+ specification.fontsymbol = todingbat(fontsymbol)
+ specification.fontstyle = "symbol"
+ specification.fontalternative = "dingbats"
+ d.DA = fieldsurrounding(specification)
+ d.MK = fieldrendering(specification)
+ else
+ d.AP = fieldappearances(field)
+ end
+ return save_kid(parent,specification,d)
+end
+
+function methods.push(name,specification)
+ return makepushchild(name,enhance(specification,"PushButton"))
+end
+
+local function makeradioparent(field,specification)
+-- specification = enhance(specification,"Radio,RadiosInUnison")
+ specification = enhance(specification,"Radio,RadiosInUnison,Print,NoToggleToOff")
+-- specification = enhance(specification,"Radio,Print,NoToggleToOff")
+ local d = pdfdictionary {
+ T = field.name,
+ FT = pdf_btn,
+-- F = fieldplus(specification),
+ Ff = fieldflag(specification),
+-- H = pdf_n,
+ V = fielddefault(field),
+ }
+ save_parent(field,specification,d,true)
+end
+
+-- local function makeradiochild(name,specification)
+-- local field, parent = clones[name], nil
+-- if field then
+-- field = radios[field.parent]
+-- parent = fields[field.parent]
+-- if not parent.pobj then
+-- if trace_fields then
+-- report_fields("forcing parent radio %a",parent.name)
+-- end
+-- makeradioparent(parent,parent)
+-- end
+-- else
+-- field = radios[name]
+-- if not field then
+-- report_fields("there is some problem with field %a",name)
+-- return nil
+-- end
+-- parent = fields[field.parent]
+-- if not parent.pobj then
+-- if trace_fields then
+-- report_fields("using parent radio %a",name)
+-- end
+-- makeradioparent(parent,parent)
+-- end
+-- end
+-- if trace_fields then
+-- report_fields("using child radio %a with values %a and default %a",name,field.values,field.default)
+-- end
+-- local fontsymbol = specification.fontsymbol
+-- fontsymbol="star"
+-- local d = pdfdictionary {
+-- Subtype = pdf_widget,
+-- Parent = pdfreference(parent.pobj),
+-- F = fieldplus(specification),
+-- OC = fieldlayer(specification),
+-- AA = fieldactions(specification),
+-- H = pdf_n,
+-- }
+-- if fontsymbol and fontsymbol ~= "" then
+-- local appearance, default, value = fieldstates_radio(field,true,false,false,name) -- false is also ok
+-- specification.fontsymbol = todingbat(fontsymbol)
+-- specification.fontstyle = "symbol"
+-- specification.fontalternative = "dingbats"
+-- d.DA = fieldsurrounding(specification)
+-- d.MK = fieldrendering(specification)
+-- d.AS = pdfconstant(value) -- default -- mandate when AP but confuses viewers
+-- d.AP = appearance
+-- return save_kid(parent,specification,d,value)
+-- -- return save_kid(parent,specification,d,name)
+-- else
+-- -- local appearance, default, value = fieldstates_radio(field,true) -- false is also ok
+-- local appearance, default, value = fieldstates_radio(field,true,false,false,name) -- false is also ok
+-- d.AS = default -- mandate when AP but confuses viewers
+-- d.AP = appearance
+-- return save_kid(parent,specification,d,value)
+-- end
+-- end
+
+local function makeradiochild(name,specification)
+ local field, parent = clones[name], nil
+ if field then
+ field = radios[field.parent]
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("forcing parent radio %a",parent.name)
+ end
+ makeradioparent(parent,parent)
+ end
+ else
+ field = radios[name]
+ if not field then
+ report_fields("there is some problem with field %a",name)
+ return nil
+ end
+ parent = fields[field.parent]
+ if not parent.pobj then
+ if trace_fields then
+ report_fields("using parent radio %a",name)
+ end
+ makeradioparent(parent,parent)
+ end
+ end
+ if trace_fields then
+ report_fields("using child radio %a with values %a and default %a",name,field.values,field.default)
+ end
+ local fontsymbol = specification.fontsymbol
+ -- fontsymbol = "circle"
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ H = pdf_n,
+ }
+ if fontsymbol and fontsymbol ~= "" then
+ specification.fontsymbol = todingbat(fontsymbol)
+ specification.fontstyle = "symbol"
+ specification.fontalternative = "dingbats"
+ d.DA = fieldsurrounding(specification)
+ d.MK = fieldrendering(specification)
+ end
+ local appearance, default, value = fieldstates_radio(field,name,fields[field.parent])
+ d.AP = appearance
+ d.AS = default -- /Whatever
+ return save_kid(parent,specification,d,value)
+end
+
+function methods.sub(name,specification)
+ return makeradiochild(name,enhance(specification,"Radio,RadiosInUnison"))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua
new file mode 100644
index 00000000000..b1d9a4b0ca4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua
@@ -0,0 +1,842 @@
+if not modules then modules = { } end modules ['lpdf-fmt'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Peter Rolf and Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- Thanks to Luigi and Steffen for testing.
+
+-- context --directives="backend.format=PDF/X-1a:2001" --trackers=backend.format yourfile
+
+local lower, gmatch, format, find = string.lower, string.gmatch, string.format, string.find
+local concat, serialize = table.concat, table.serialize
+
+local trace_format = false trackers.register("backend.format", function(v) trace_format = v end)
+local trace_variables = false trackers.register("backend.variables", function(v) trace_variables = v end)
+
+local report_backend = logs.reporter("backend","profiles")
+
+local backends, lpdf = backends, lpdf
+
+local codeinjections = backends.pdf.codeinjections
+
+local variables = interfaces.variables
+local viewerlayers = attributes.viewerlayers
+local colors = attributes.colors
+local transparencies = attributes.transparencies
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+local pdfstring = lpdf.string
+local pdfverbose = lpdf.verbose
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
+
+local addtoinfo = lpdf.addtoinfo
+local injectxmpinfo = lpdf.injectxmpinfo
+local insertxmpinfo = lpdf.insertxmpinfo
+
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+--[[
+ Comments by Peter:
+
+ output intent : only one profile per color space (and device class)
+ default color space : (theoretically) several profiles per color space possible
+
+ The default color space profiles define the current gamuts (part of/all the
+ colors we have in the document), while the output intent profile declares the
+ gamut of the output devices (the colors that we get normally a printer or
+ monitor).
+
+ Example:
+
+ I have two RGB pictures (both 'painted' in /DeviceRGB) and I declare sRGB as
+ default color space for one picture and AdobeRGB for the other. As output
+ intent I use ISO_coated_v2_eci.icc.
+
+ If I had more than one output intent profile for the combination CMYK/printer I
+ can't decide which one to use. But it is no problem to use several default color
+ space profiles for the same color space as it's just a different color
+ transformation. The relation between picture and profile is clear.
+]]--
+
+local channels = {
+ gray = 1,
+ grey = 1,
+ rgb = 3,
+ cmyk = 4,
+}
+
+local prefixes = {
+ gray = "DefaultGray",
+ grey = "DefaultGray",
+ rgb = "DefaultRGB",
+ cmyk = "DefaultCMYK",
+}
+
+local formatspecification, formatname = nil, nil
+
+-- * correspondent document wide flags (write once) needed for permission tests
+
+local formats = utilities.storage.allocate {
+ ["version"] = {
+ external_icc_profiles = 1.4, -- 'p' in name; URL reference of output intent
+ jbig2_compression = 1.4,
+ jpeg2000_compression = 1.5, -- not supported yet
+ nchannel_colorspace = 1.6, -- 'n' in name; n-channel colorspace support
+ open_prepress_interface = 1.3, -- 'g' in name; reference to external graphics
+ optional_content = 1.5,
+ transparency = 1.4,
+ object_compression = 1.5,
+ },
+ ["default"] = {
+ pdf_version = 1.7, -- todo: block tex primitive
+ format_name = "default",
+ xmp_file = "lpdf-pdx.xml",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ nchannel_colorspace = true, -- unknown
+ internal_icc_profiles = true, -- controls profile inclusion
+ external_icc_profiles = true, -- controls profile inclusion
+ include_intents = true,
+ open_prepress_interface = true, -- unknown
+ optional_content = true, -- todo: block at lua level
+ transparency = true, -- todo: block at lua level
+ jbig2_compression = true, -- todo: block at lua level
+ jpeg2000_compression = true, -- todo: block at lua level
+ inject_metadata = function()
+ -- nothing
+ end
+ },
+ ["pdf/x-1a:2001"] = {
+ pdf_version = 1.3,
+ format_name = "PDF/X-1a:2001",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ spot_colors = true,
+ internal_icc_profiles = 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)
+ end
+ },
+ ["pdf/x-1a:2003"] = {
+ pdf_version = 1.4,
+ format_name = "PDF/X-1a:2003",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ spot_colors = true,
+ internal_icc_profiles = 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)
+ end
+ },
+ ["pdf/x-3:2002"] = {
+ pdf_version = 1.3,
+ format_name = "PDF/X-3:2002",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ include_intents = true,
+ inject_metadata = function()
+ addtoinfo("GTS_PDFXVersion","PDF/X-3:2002")
+ end
+ },
+ ["pdf/x-3:2003"] = {
+ pdf_version = 1.4,
+ format_name = "PDF/X-3:2003",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ include_intents = true,
+ jbig2_compression = true,
+ inject_metadata = function()
+ addtoinfo("GTS_PDFXVersion","PDF/X-3:2003")
+ end
+ },
+ ["pdf/x-4"] = {
+ pdf_version = 1.6,
+ format_name = "PDF/X-4",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ include_intents = true,
+ optional_content = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = 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)
+ insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:RenditionClass>default</xmpMM:RenditionClass>",false)
+ end
+ },
+ ["pdf/x-4p"] = {
+ pdf_version = 1.6,
+ format_name = "PDF/X-4p",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ external_icc_profiles = true,
+ include_intents = true,
+ optional_content = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = 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)
+ insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:RenditionClass>default</xmpMM:RenditionClass>",false)
+ end
+ },
+ ["pdf/x-5g"] = {
+ pdf_version = 1.6,
+ format_name = "PDF/X-5g",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ include_intents = true,
+ open_prepress_interface = true,
+ optional_content = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = true,
+ inject_metadata = function()
+ -- todo
+ end
+ },
+ ["pdf/x-5pg"] = {
+ pdf_version = 1.6,
+ format_name = "PDF/X-5pg",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ external_icc_profiles = true,
+ include_intents = true,
+ open_prepress_interface = true,
+ optional_content = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = true,
+ inject_metadata = function()
+ -- todo
+ end
+ },
+ ["pdf/x-5n"] = {
+ pdf_version = 1.6,
+ format_name = "PDF/X-5n",
+ xmp_file = "lpdf-pdx.xml",
+ gts_flag = "GTS_PDFX",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ calibrated_rgb_colors = true,
+ spot_colors = true,
+ cielab_colors = true,
+ internal_icc_profiles = true,
+ include_intents = true,
+ optional_content = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ nchannel_colorspace = true,
+ object_compression = true,
+ inject_metadata = function()
+ -- todo
+ end
+ },
+ ["pdf/a-1a:2005"] = {
+ pdf_version = 1.4,
+ format_name = "pdf/a-1a:2005",
+ xmp_file = "lpdf-pda.xml",
+ gts_flag = "GTS_PDFA1",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ include_intents = true,
+ forms = true, -- NEW; forms are allowed (with limitations); no JS, other restrictions are unknown (TODO)
+ tagging = true, -- NEW; the only difference to PDF/A-1b
+ internal_icc_profiles = 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
+ },
+ ["pdf/a-1b:2005"] = {
+ pdf_version = 1.4,
+ format_name = "pdf/a-1b:2005",
+ xmp_file = "lpdf-pda.xml",
+ gts_flag = "GTS_PDFA1",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ include_intents = true,
+ forms = true,
+ internal_icc_profiles = 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
+ },
+ ["pdf/a-2a"] = { -- untested; only PDF/A Attachments are allowed
+ pdf_version = 1.7,
+ format_name = "pdf/a-2a",
+ xmp_file = "lpdf-pda.xml",
+ gts_flag = "GTS_PDFA2",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ include_intents = true,
+ forms = true,
+ tagging = true,
+ internal_icc_profiles = true,
+ transparency = true, -- NEW
+ jbig2_compression = true,
+ jpeg2000_compression = true, -- NEW
+ object_compression = true,
+ 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
+ },
+ ["pdf/a-3a"] = { -- untested; NEW: any type of attachment is allowed
+ pdf_version = 1.7,
+ format_name = "pdf/a-3a",
+ xmp_file = "lpdf-pda.xml",
+ gts_flag = "GTS_PDFA3",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ include_intents = true,
+ forms = true,
+ tagging = true,
+ internal_icc_profiles = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = true,
+ 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
+ },
+ ["pdf/ua-1"] = { -- based on PDF/A-3a, but no 'gts_flag'
+ pdf_version = 1.7,
+ format_name = "pdf/ua-1",
+ xmp_file = "lpdf-pua.xml",
+ gray_scale = true,
+ cmyk_colors = true,
+ rgb_colors = true,
+ spot_colors = true,
+ calibrated_rgb_colors = true, -- unknown
+ cielab_colors = true, -- unknown
+ include_intents = true,
+ forms = true,
+ tagging = true,
+ internal_icc_profiles = true,
+ transparency = true,
+ jbig2_compression = true,
+ jpeg2000_compression = true,
+ object_compression = true,
+ 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)
+ end
+ },
+}
+
+lpdf.formats = formats -- it does not hurt to have this one visible
+
+local filenames = {
+ "colorprofiles.xml",
+ "colorprofiles.lua",
+}
+
+local function locatefile(filename)
+ local fullname = resolvers.findfile(filename,"icc",1,true)
+ if not fullname or fullname == "" then
+ fullname = resolvers.finders.byscheme("loc",filename) -- could be specific to the project
+ end
+ return fullname or ""
+end
+
+local function loadprofile(name,filename)
+ local profile = false
+ local databases = filename and filename ~= "" and settings_to_array(filename) or filenames
+ for i=1,#databases do
+ local filename = locatefile(databases[i])
+ if filename and filename ~= "" then
+ local suffix = file.suffix(filename)
+ local lname = lower(name)
+ if suffix == "xml" then
+ local xmldata = xml.load(filename) -- no need for caching it
+ if xmldata then
+ profile = xml.filter(xmldata,format('xml://profiles/profile/(info|filename)[lower(text())=="%s"]/../table()',lname))
+ end
+ elseif suffix == "lua" then
+ local luadata = loadfile(filename)
+ luadata = ludata and luadata()
+ if luadata then
+ profile = luadata[name] or luadata[lname] -- hashed
+ if not profile then
+ for i=1,#luadata do
+ local li = luadata[i]
+ if lower(li.info) == lname then -- indexed
+ profile = li
+ break
+ end
+ end
+ end
+ end
+ end
+ if profile then
+ if next(profile) then
+ report_backend("profile specification %a loaded from %a",name,filename)
+ return profile
+ elseif trace_format then
+ report_backend("profile specification %a loaded from %a but empty",name,filename)
+ end
+ return false
+ end
+ end
+ end
+ report_backend("profile specification %a not found in %a",name,concat(filenames, ", "))
+end
+
+local function urls(url)
+ if not url or url == "" then
+ return nil
+ else
+ local u = pdfarray()
+ for url in gmatch(url,"([^, ]+)") do
+ if find(url,"^http") then
+ u[#u+1] = pdfdictionary {
+ FS = pdfconstant("URL"),
+ F = pdfstring(url),
+ }
+ end
+ end
+ return u
+ end
+end
+
+local function profilename(filename)
+ return lower(file.basename(filename))
+end
+
+local internalprofiles = { }
+
+local function handleinternalprofile(s,include)
+ local filename, colorspace = s.filename or "", s.colorspace or ""
+ if filename == "" or colorspace == "" then
+ report_backend("error in internal profile specification: %s",serialize(s,false))
+ else
+ local tag = profilename(filename)
+ local profile = internalprofiles[tag]
+ if not profile then
+ local colorspace = lower(colorspace)
+ if include then
+ -- local fullname = resolvers.findctxfile(filename) or ""
+ local fullname = locatefile(filename)
+ local channel = channels[colorspace] or nil
+ if fullname == "" then
+ report_backend("error, couldn't locate profile %a",filename)
+ elseif not channel then
+ report_backend("error, couldn't resolve channel entry for colorspace %a",colorspace)
+ else
+ profile = pdfflushstreamfileobject(fullname,pdfdictionary{ N = channel },false) -- uncompressed
+ internalprofiles[tag] = profile
+ if trace_format then
+ report_backend("including %a color profile from %a",colorspace,fullname)
+ end
+ end
+ else
+ internalprofiles[tag] = true
+ if trace_format then
+ report_backend("not including %a color profile %a",colorspace,filename)
+ end
+ end
+ end
+ return profile
+ end
+end
+
+local externalprofiles = { }
+
+local function handleexternalprofile(s,include) -- specification (include ignored here)
+ local name, url, filename, checksum, version, colorspace =
+ s.info or s.filename or "", s.url or "", s.filename or "", s.checksum or "", s.version or "", s.colorspace or ""
+ if false then -- somehow leads to invalid pdf
+ local iccprofile = colors.iccprofile(filename)
+ if iccprofile then
+ name = name ~= "" and name or iccprofile.tags.desc.cleaned or ""
+ url = url ~= "" and url or iccprofile.tags.dmnd.cleaned or ""
+ checksum = checksum ~= "" and checksum or file.checksum(iccprofile.fullname) or ""
+ version = version ~= "" and version or iccprofile.header.version or ""
+ colorspace = colorspace ~= "" and colorspace or iccprofile.header.colorspace or ""
+ end
+ -- table.print(iccprofile)
+ end
+ if name == "" or url == "" or checksum == "" or version == "" or colorspace == "" or filename == "" then
+ local profile = handleinternalprofile(s)
+ if profile then
+ report_backend("incomplete external profile specification, falling back to internal")
+ else
+ report_backend("error in external profile specification: %s",serialize(s,false))
+ end
+ else
+ local tag = profilename(filename)
+ local profile = externalprofiles[tag]
+ if not profile then
+ local d = pdfdictionary {
+ ProfileName = name, -- not file name!
+ ProfileCS = colorspace,
+ URLs = urls(url), -- array containing at least one URL
+ CheckSum = pdfverbose { "<", lower(checksum), ">" }, -- 16byte MD5 hash
+ ICCVersion = pdfverbose { "<", version, ">" }, -- bytes 8..11 from the header of the ICC profile, as a hex string
+ }
+ profile = pdfflushobject(d)
+ externalprofiles[tag] = profile
+ end
+ return profile
+ end
+end
+
+local loadeddefaults = { }
+
+local function handledefaultprofile(s,spec) -- specification
+ local filename, colorspace = s.filename or "", lower(s.colorspace or "")
+ if filename == "" or colorspace == "" then
+ report_backend("error in default profile specification: %s",serialize(s,false))
+ elseif not loadeddefaults[colorspace] then
+ local tag = profilename(filename)
+ local n = internalprofiles[tag] -- or externalprofiles[tag]
+ if n == true then -- not internalized
+ report_backend("no default profile %a for colorspace %a",filename,colorspace)
+ elseif n then
+ local a = pdfarray {
+ pdfconstant("ICCBased"),
+ pdfreference(n),
+ }
+ -- used in page /Resources, so this must be inserted at runtime
+ lpdf.adddocumentcolorspace(prefixes[colorspace],pdfreference(pdfflushobject(a)))
+ loadeddefaults[colorspace] = true
+ report_backend("setting %a as default %a color space",filename,colorspace)
+ else
+ report_backend("no default profile %a for colorspace %a",filename,colorspace)
+ end
+ elseif trace_format then
+ report_backend("a default %a colorspace is already in use",colorspace)
+ end
+end
+
+local loadedintents, intents = { }, pdfarray()
+
+local function handleoutputintent(s,spec)
+ local name, url, filename, id, outputcondition, info = s.info or s.filename or "", s.url or "", s.filename or "", s.id or "", s.outputcondition or "", s.info or ""
+ if name == "" or id == "" then
+ report_backend("error in output intent specification: %s",serialize(s,false))
+ elseif not loadedintents[name] then
+ local tag = profilename(filename)
+ local internal, external = internalprofiles[tag], externalprofiles[tag]
+ if internal or external then
+ local d = {
+ Type = pdfconstant("OutputIntent"),
+ S = pdfconstant(spec.gts_flag or "GTS_PDFX"),
+ OutputConditionIdentifier = id,
+ RegistryName = url,
+ OutputCondition = outputcondition,
+ Info = info,
+ }
+ if internal and internal ~= true then
+ d.DestOutputProfile = pdfreference(internal)
+ elseif external and external ~= true then
+ d.DestOutputProfileRef = pdfreference(external)
+ else
+ report_backend("omitting reference to profile for intent %a",name)
+ end
+ intents[#intents+1] = pdfreference(pdfflushobject(pdfdictionary(d)))
+ if trace_format then
+ report_backend("setting output intent to %a with id %a for entry %a",name,id,#intents)
+ end
+ else
+ report_backend("invalid output intent %a",name)
+ end
+ loadedintents[name] = true
+ elseif trace_format then
+ report_backend("an output intent with name %a is already in use",name)
+ end
+end
+
+local function handleiccprofile(message,spec,name,filename,how,options,alwaysinclude,gts_flag)
+ if name and name ~= "" then
+ local list = settings_to_array(name)
+ for i=1,#list do
+ local name = list[i]
+ local profile = loadprofile(name,filename)
+ if trace_format then
+ report_backend("handling %s %a",message,name)
+ end
+ if profile then
+ if formatspecification.cmyk_colors then
+ profile.colorspace = profile.colorspace or "CMYK"
+ else
+ profile.colorspace = profile.colorspace or "RGB"
+ end
+ local external = formatspecification.external_icc_profiles
+ local internal = formatspecification.internal_icc_profiles
+ local include = formatspecification.include_intents
+ local always, never = options[variables.always], options[variables.never]
+ if always or alwaysinclude then
+ if trace_format then
+ report_backend("forcing internal profiles") -- can make preflight unhappy
+ end
+ -- internal, external = true, false
+ internal, external = not never, false
+ elseif never then
+ if trace_format then
+ report_backend("forcing external profiles") -- can make preflight unhappy
+ end
+ internal, external = false, true
+ end
+ if external then
+ if trace_format then
+ report_backend("handling external profiles cf. %a",name)
+ end
+ handleexternalprofile(profile,false)
+ else
+ if trace_format then
+ report_backend("handling internal profiles cf. %a",name)
+ end
+ if internal then
+ handleinternalprofile(profile,always or include)
+ else
+ report_backend("no profile inclusion for %a",formatname)
+ end
+ end
+ how(profile,spec)
+ elseif trace_format then
+ report_backend("unknown profile %a",name)
+ end
+ end
+ end
+end
+
+local function flushoutputintents()
+ if #intents > 0 then
+ lpdf.addtocatalog("OutputIntents",pdfreference(pdfflushobject(intents)))
+ end
+end
+
+lpdf.registerdocumentfinalizer(flushoutputintents,2,"output intents")
+
+function codeinjections.setformat(s)
+ local format = s.format or ""
+ local level = tonumber(s.level)
+ local intent = s.intent or ""
+ local profile = s.profile or ""
+ local option = s.option or ""
+ local filename = s.file or ""
+ if format ~= "" then
+ local spec = formats[lower(format)]
+ if spec then
+ formatspecification = spec
+ formatname = spec.format_name
+ report_backend("setting format to %a",formatname)
+ local xmp_file = formatspecification.xmp_file or ""
+ if xmp_file == "" then
+ -- weird error
+ else
+ codeinjections.setxmpfile(xmp_file)
+ end
+ if not level then
+ level = 3 -- good compromise, default anyway
+ end
+ local pdf_version = spec.pdf_version * 10
+ local inject_metadata = spec.inject_metadata
+ local majorversion = math.div(pdf_version,10)
+ local minorversion = math.mod(pdf_version,10)
+ local objectcompression = spec.object_compression and pdf_version >= 15
+ local compresslevel = level or pdf.getcompresslevel() -- keep default
+ local objectcompresslevel = (objectcompression and (level or pdf.getobjcompresslevel())) or 0
+ pdf.setcompresslevel (compresslevel)
+ pdf.setobjcompresslevel(objectcompresslevel)
+ pdf.setmajorversion (majorversion)
+ pdf.setminorversion (minorversion)
+ if objectcompression then
+ report_backend("forcing pdf version %s.%s, compression level %s, object compression level %s",
+ majorversion,minorversion,compresslevel,objectcompresslevel)
+ elseif compresslevel > 0 then
+ report_backend("forcing pdf version %s.%s, compression level %s, object compression disabled",
+ majorversion,minorversion,compresslevel)
+ else
+ report_backend("forcing pdf version %s.%s, compression disabled",
+ majorversion,minorversion)
+ end
+ --
+ -- context.setupcolors { -- not this way
+ -- cmyk = spec.cmyk_colors and variables.yes or variables.no,
+ -- rgb = spec.rgb_colors and variables.yes or variables.no,
+ -- }
+ --
+ colors.forcesupport(
+ spec.gray_scale or false,
+ spec.rgb_colors or false,
+ spec.cmyk_colors or false,
+ spec.spot_colors or false,
+ spec.nchannel_colorspace or false
+ )
+ transparencies.forcesupport(
+ spec.transparency or false
+ )
+ viewerlayers.forcesupport(
+ spec.optional_content or false
+ )
+ viewerlayers.setfeatures(
+ spec.has_order or false -- new
+ )
+ --
+ -- spec.jbig2_compression : todo, block in image inclusion
+ -- spec.jpeg2000_compression : todo, block in image inclusion
+ --
+ if type(inject_metadata) == "function" then
+ inject_metadata()
+ end
+ local options = settings_to_hash(option)
+ handleiccprofile("color profile",spec,profile,filename,handledefaultprofile,options,true)
+ handleiccprofile("output intent",spec,intent,filename,handleoutputintent,options,false)
+ if trace_variables then
+ for k, v in table.sortedhash(formats.default) do
+ local v = formatspecification[k]
+ if type(v) ~= "function" then
+ report_backend("%a = %a",k,v or false)
+ end
+ end
+ end
+ function codeinjections.setformat(noname)
+ if trace_format then
+ report_backend("error, format is already set to %a, ignoring %a",formatname,noname.format)
+ end
+ end
+ else
+ report_backend("error, format %a is not supported",format)
+ end
+ elseif level then
+ pdf.setcompresslevel(level)
+ pdf.setobjcompresslevel(level)
+ else
+ -- we ignore this as we hook it in \everysetupbackend
+ end
+end
+
+directives.register("backend.format", function(v) -- table !
+ local tv = type(v)
+ if tv == "table" then
+ codeinjections.setformat(v)
+ elseif tv == "string" then
+ codeinjections.setformat { format = v }
+ end
+end)
+
+interfaces.implement {
+ name = "setformat",
+ actions = codeinjections.setformat,
+ arguments = { { "*" } }
+}
+
+function codeinjections.getformatoption(key)
+ return formatspecification and formatspecification[key]
+end
+
+function codeinjections.supportedformats()
+ local t = { }
+ for k, v in table.sortedhash(formats) do
+ if find(k,"pdf",1,true) then
+ t[#t+1] = k
+ end
+ end
+ return t
+end
+
+--~ The following is somewhat cleaner but then we need to flag that there are
+--~ color spaces set so that the page flusher does not optimize the (at that
+--~ moment) still empty array away. So, next(d_colorspaces) should then become
+--~ a different test, i.e. also on flag. I'll add that when we need more forward
+--~ referencing.
+--~
+--~ local function embedprofile = handledefaultprofile
+--~
+--~ local function flushembeddedprofiles()
+--~ for colorspace, filename in next, defaults do
+--~ embedprofile(colorspace,filename)
+--~ end
+--~ end
+--~
+--~ local function handledefaultprofile(s)
+--~ defaults[lower(s.colorspace)] = s.filename
+--~ end
+--~
+--~ lpdf.registerdocumentfinalizer(flushembeddedprofiles,1,"embedded color profiles")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua
new file mode 100644
index 00000000000..0eac52dfb3a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua
@@ -0,0 +1,295 @@
+if not modules then modules = { } end modules ['lpdf-grp'] = {
+ 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 type = type
+local formatters, gsub = string.formatters, string.gsub
+local concat = table.concat
+local round = math.round
+
+local backends, lpdf = backends, lpdf
+
+local nodeinjections = backends.pdf.nodeinjections
+
+local colors = attributes.colors
+local basepoints = number.dimenfactors["bp"]
+local inches = number.dimenfactors["in"]
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+
+-- 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 >>
+-- 22 : << /Bounds [ ] /Domain [ 0.0 1.0 ] /Encode [ 0.0 1.0 ] /FunctionType 3 /Functions [ 31 0 R ] >>
+-- 31 : << /C0 [ 1.0 0.0 ] /C1 [ 0.0 1.0 ] /Domain [ 0.0 1.0 ] /FunctionType 2 /N 1.0 >>
+
+local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps)
+ if steps then
+ color_a = color_a[1]
+ color_b = color_b[1]
+ end
+ local f = pdfdictionary {
+ FunctionType = 2,
+ Domain = pdfarray(domain), -- domain is actually a string
+ C0 = pdfarray(color_a),
+ C1 = pdfarray(color_b),
+ N = tonumber(n),
+ }
+ separation = separation and registrations.getspotcolorreference(separation)
+ local s = pdfdictionary {
+ ShadingType = stype,
+ ColorSpace = separation and pdfreference(separation) or pdfconstant(colorspace),
+ Function = pdfreference(pdfflushobject(f)),
+ Coords = pdfarray(coordinates),
+ Extend = pdfarray { true, true },
+ AntiAlias = pdfboolean(true),
+ }
+ lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s)))
+end
+
+local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
+ local func = nil
+ if steps then
+ local list = pdfarray()
+ local bounds = pdfarray()
+ local encode = pdfarray()
+ for i=1,steps do
+ bounds[i] = fractions[i] or 1
+ encode[2*i-1] = 0
+ encode[2*i] = 1
+ list [i] = pdfdictionary {
+ FunctionType = 2,
+ Domain = pdfarray(domain), -- domain is actually a string
+ C0 = pdfarray(color_a[i]),
+ C1 = pdfarray(color_b[i]),
+ N = tonumber(n),
+ }
+ end
+ func = pdfdictionary {
+ FunctionType = 3,
+ Bounds = bounds,
+ Encode = encode,
+ Functions = list,
+ Domain = pdfarray(domain), -- domain is actually a string
+ }
+ else
+ func = pdfdictionary {
+ FunctionType = 2,
+ Domain = pdfarray(domain), -- domain is actually a string
+ C0 = pdfarray(color_a),
+ C1 = pdfarray(color_b),
+ N = tonumber(n),
+ }
+ end
+ separation = separation and registrations.getspotcolorreference(separation)
+ local s = pdfdictionary {
+ ShadingType = stype,
+ ColorSpace = separation and pdfreference(separation) or pdfconstant(colorspace),
+ Function = pdfreference(pdfflushobject(func)),
+ Coords = pdfarray(coordinates),
+ Extend = pdfarray { true, true },
+ AntiAlias = pdfboolean(true),
+ }
+ lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s)))
+end
+
+function lpdf.circularshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
+ shade(3,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
+end
+
+function lpdf.linearshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
+ shade(2,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions)
+end
+
+-- inline bitmaps but xform'd
+--
+-- we could derive the colorspace if we strip the data
+-- and divide by x*y
+
+local template = "q BI %s ID %s > EI Q"
+local factor = 72/300
+
+function nodeinjections.injectbitmap(t)
+ -- encoding is ascii hex, no checking here
+ local xresolution, yresolution = t.xresolution or 0, t.yresolution or 0
+ if xresolution == 0 or yresolution == 0 then
+ return -- fatal error
+ end
+ local colorspace = t.colorspace
+ if colorspace ~= "rgb" and colorspace ~= "cmyk" and colorspace ~= "gray" then
+ -- not that efficient but ok
+ local d = gsub(t.data,"[^0-9a-f]","")
+ local b = math.round(#d / (xresolution * yresolution))
+ if b == 2 then
+ colorspace = "gray"
+ elseif b == 6 then
+ colorspace = "rgb"
+ elseif b == 8 then
+ colorspace = "cmyk"
+ end
+ end
+ colorspace = lpdf.colorspaceconstants[colorspace]
+ if not colorspace then
+ return -- fatal error
+ end
+ local d = pdfdictionary {
+ W = xresolution,
+ H = yresolution,
+ CS = colorspace,
+ BPC = 8,
+ F = pdfconstant("AHx"),
+ -- CS = nil,
+ -- BPC = 1,
+ -- IM = true,
+ }
+ -- for some reasons it only works well if we take a 1bp boundingbox
+ local urx, ury = 1/basepoints, 1/basepoints
+ -- urx = (xresolution/300)/basepoints
+ -- ury = (yresolution/300)/basepoints
+ local width, height = t.width or 0, t.height or 0
+ if width == 0 and height == 0 then
+ width = factor * xresolution / basepoints
+ height = factor * yresolution / basepoints
+ elseif width == 0 then
+ width = height * xresolution / yresolution
+ elseif height == 0 then
+ height = width * yresolution / xresolution
+ end
+ local image = img.new {
+ stream = formatters[template](d(),t.data),
+ width = width,
+ height = height,
+ bbox = { 0, 0, urx, ury },
+ }
+ return img.node(image)
+end
+
+-- general graphic helpers
+
+function codeinjections.setfigurealternative(data,figure)
+ local request = data.request
+ local display = request.display
+ if display and display ~= "" then
+ local nested = figures.push {
+ name = display,
+ page = request.page,
+ size = request.size,
+ prefix = request.prefix,
+ cache = request.cache,
+ width = request.width,
+ height = request.height,
+ }
+ figures.identify()
+ local displayfigure = figures.check()
+ if displayfigure then
+ -- figure.aform = true
+ img.immediatewrite(figure)
+ local a = pdfarray {
+ pdfdictionary {
+ Image = pdfreference(figure.objnum),
+ DefaultForPrinting = true,
+ }
+ }
+ local d = pdfdictionary {
+ Alternates = pdfreference(pdfflushobject(a)),
+ }
+ displayfigure.attr = d()
+ figures.pop()
+ return displayfigure, nested
+ else
+ figures.pop()
+ end
+ end
+end
+
+function codeinjections.getpreviewfigure(request)
+ local figure = figures.initialize(request)
+ if not figure then
+ return
+ end
+ figure = figures.identify(figure)
+ if not (figure and figure.status and figure.status.fullname) then
+ return
+ end
+ figure = figures.check(figure)
+ if not (figure and figure.status and figure.status.fullname) then
+ return
+ end
+ local image = figure.status.private
+ if image then
+ img.immediatewrite(image)
+ end
+ return figure
+end
+
+function codeinjections.setfiguremask(data,figure) -- mark
+ local request = data.request
+ local mask = request.mask
+ if mask and mask ~= "" then
+ figures.push {
+ name = mask,
+ page = request.page,
+ size = request.size,
+ prefix = request.prefix,
+ cache = request.cache,
+ width = request.width,
+ height = request.height,
+ }
+ figures.identify()
+ local maskfigure = figures.check()
+ if maskfigure then
+ local image = maskfigure.status.private
+ if image then
+ img.immediatewrite(image)
+ local d = pdfdictionary {
+ Interpolate = false,
+ SMask = pdfreference(image.objnum),
+ }
+ figure.attr = d()
+ end
+ end
+ figures.pop()
+ end
+end
+
+-- temp hack
+
+local factor = number.dimenfactors.bp
+
+function img.package(image) -- see lpdf-u3d **
+ local boundingbox = image.bbox
+ local imagetag = "Im" .. image.index
+ local resources = pdfdictionary {
+ ProcSet = pdfarray {
+ pdfconstant("PDF"),
+ pdfconstant("ImageC")
+ },
+ Resources = pdfdictionary {
+ XObject = pdfdictionary {
+ [imagetag] = pdfreference(image.objnum)
+ }
+ }
+ }
+ local width = boundingbox[3]
+ local height = boundingbox[4]
+ local xform = img.scan {
+ attr = resources(),
+ stream = formatters["%F 0 0 %F 0 0 cm /%s Do"](width,height,imagetag),
+ bbox = { 0, 0, width/factor, height/factor },
+ }
+ img.immediatewrite(xform)
+ return xform
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua
new file mode 100644
index 00000000000..2149f4729a4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua
@@ -0,0 +1,1271 @@
+if not modules then modules = { } end modules ['lpdf-ini'] = {
+ 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"
+}
+
+-- beware of "too many locals" here
+
+local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset
+local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch
+local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values
+local sind, cosd, floor, max, min = math.sind, math.cosd, math.floor, 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 formatters = string.formatters
+local isboolean = string.is_boolean
+
+local report_objects = logs.reporter("backend","objects")
+local report_finalizing = logs.reporter("backend","finalizing")
+local report_blocked = logs.reporter("backend","blocked")
+
+local implement = interfaces.implement
+local two_strings = interfaces.strings[2]
+
+-- In ConTeXt MkIV we use utf8 exclusively so all strings get mapped onto a hex
+-- 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
+
+do
+
+ local texget = tex.get
+ local texset = tex.set
+
+ function pdf.setmajorversion (n) texset("global","pdfmajorversion", n) end
+ function pdf.getmajorversion ( ) return texget("pdfmajorversion") end
+
+end
+
+local pdfsetinfo = pdf.setinfo
+local pdfsetcatalog = pdf.setcatalog
+local pdfsetnames = pdf.setnames
+local 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
+
+pdfdisablecommand("setinfo")
+pdfdisablecommand("setcatalog")
+pdfdisablecommand("setnames")
+pdfdisablecommand("settrailer")
+pdfdisablecommand("setpageresources")
+pdfdisablecommand("setpageattributes")
+pdfdisablecommand("setpagesattributes")
+pdfdisablecommand("registerannot")
+
+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 = {
+ comment = "backend for directly generating pdf output",
+ nodeinjections = { },
+ codeinjections = { },
+ registrations = { },
+ tables = { },
+}
+backends.pdf = pdfbackend
+lpdf = lpdf or { }
+local lpdf = lpdf
+
+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.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 = 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)
+ end
+end
+
+-- we could use a hash of predefined unicodes
+
+-- 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
+-- local r, n = { "<feff" }, 1
+-- for b in utfvalues(str) do
+-- n = n + 1
+-- if b < 0x10000 then
+-- r[n] = format("%04x",b)
+-- else
+-- -- r[n] = format("%04x%04x",b/1024+0xD800,b%1024+0xDC00)
+-- r[n] = format("%04x%04x",floor(b/1024),b%1024+0xDC00) --bit32.rshift(b,10)
+-- end
+-- end
+-- n = n + 1
+-- r[n] = ">"
+-- return concat(r)
+-- 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",v/1024+0xD800,v%1024+0xDC00)
+ v = format("%04x%04x",floor(v/1024),v%1024+0xDC00)
+ 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 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)
+ 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)
+ end
+end
+
+local pattern = P(true) / function() more = 0 end * Cs(pattern^0)
+
+local function fromsixteen(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+end
+
+local toregime = regimes.toregime
+local fromregime = regimes.fromregime
+
+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
+ end
+end
+
+local function frompdfdoc(str)
+ if not str or str == "" then
+ return ""
+ else
+ return fromregime("pdfdoc",str)
+ 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 function toeight(str)
+ if not str or str == "" then
+ return "()"
+ else
+ return lpegmatch(escaped,str)
+ 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
+
+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"]
+
+-- 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 tostring_a, tostring_d
+
+-- tostring_d = function(t,contentonly,key)
+-- if next(t) then
+-- local r, rn = { }, 0
+-- for k, v in next, t do
+-- -- for k, v in sortedhash(t) do -- can be an option
+-- rn = rn + 1
+-- local tv = type(v)
+-- if tv == "string" then
+-- r[rn] = f_key_value(k,toeight(v))
+-- elseif tv == "number" then
+-- r[rn] = f_key_number(k,v)
+-- -- elseif tv == "unicode" then -- can't happen
+-- -- r[rn] = 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[rn] = f_key_null(k)
+-- -- else
+-- r[rn] = f_key_value(k,tostring(v))
+-- -- end
+-- elseif v[1] then
+-- r[rn] = f_key_value(k,tostring_a(v))
+-- else
+-- r[rn] = f_key_value(k,tostring_d(v))
+-- end
+-- else
+-- r[rn] = f_key_value(k,tostring(v))
+-- end
+-- end
+-- if contentonly then
+-- return concat(r," ")
+-- elseif key then
+-- return f_key_dictionary(key,r)
+-- else
+-- return f_dictionary(r)
+-- end
+-- elseif contentonly then
+-- return ""
+-- else
+-- return "<< >>"
+-- end
+-- end
+
+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))
+ else
+ r[i] = f_key_value(k,tostring_d(v))
+ end
+ else
+ r[i] = f_key_value(k,tostring(v))
+ end
+ end
+ if contentonly then
+ return concat(r," ")
+ elseif key then
+ return f_key_dictionary(key,r)
+ else
+ return f_dictionary(r)
+ 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)
+ else
+ r[k] = tostring_d(v)
+ end
+ else
+ r[k] = tostring(v)
+ end
+ end
+ if contentonly then
+ return concat(r, " ")
+ elseif key then
+ return f_key_array(key,r)
+ else
+ return f_array(r)
+ end
+ elseif contentonly then
+ return ""
+ else
+ return "[ ]"
+ end
+end
+
+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
+local tostring_u = function(t) return tosixteen(t[1]) end
+----- tostring_n = function(t) return tostring(t[1]) end -- tostring not needed
+local tostring_n = function(t) return f_tonumber(t[1]) end -- tostring not needed
+local tostring_c = function(t) return t[1] end -- already prefixed (hashed)
+local tostring_z = function() return "null" end
+local tostring_t = function() return "true" end
+local tostring_f = function() return "false" end
+local tostring_r = function(t) local n = t[1] return n and n > 0 and (n .. " 0 R") or "null" end
+
+local tostring_v = function(t)
+ local s = t[1]
+ if type(s) == "table" then
+ return concat(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
+local function value_u(t) return t[1] end
+local function value_n(t) return t[1] end
+local function value_c(t) return sub(t[1],2) end
+local function value_d(t) return tostring_d(t,true) end
+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 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 function pdfstream(t) -- we need to add attributes
+ if t then
+ for i=1,#t do
+ t[i] = tostring(t[i])
+ end
+ end
+ return setmetatable(t or { },mt_x)
+end
+
+local function pdfdictionary(t)
+ return setmetatable(t or { },mt_d)
+end
+
+local function pdfarray(t)
+ if type(t) == "string" then
+ return setmetatable({ t },mt_a)
+ else
+ return setmetatable(t or { },mt_a)
+ end
+end
+
+local function pdfstring(str,default)
+ return setmetatable({ str or default or "" },mt_s)
+end
+
+local function pdfdocstring(str,default,defaultchar)
+ return setmetatable({ str or default or "", defaultchar or " " },mt_p)
+end
+
+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
+end
+
+for i=-1,9 do cache[i] = pdfnumber(i) end
+
+local cache = { } -- can be weak
+
+local forbidden, replacements = "\0\t\n\r\f ()[]{}/%%#\\", { } -- table faster than function
+
+for s in gmatch(forbidden,".") do
+ replacements[s] = format("#%02x",byte(s))
+end
+
+local escaped = Cs(Cc("/") * (S(forbidden)/replacements + P(1))^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
+ 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
+
+do
+
+ local p_null = { } setmetatable(p_null, mt_z)
+ local p_true = { } setmetatable(p_true, mt_t)
+ local p_false = { } setmetatable(p_false,mt_f)
+
+ pdfnull = function()
+ return p_null
+ end
+
+ pdfboolean = function(b,default)
+ if type(b) == "boolean" then
+ return b and p_true or p_false
+ else
+ return default and p_true or p_false
+ end
+ end
+
+ -- print(pdfboolean(false),pdfboolean(false,false),pdfboolean(false,true))
+ -- print(pdfboolean(true),pdfboolean(true,false),pdfboolean(true,true))
+ -- print(pdfboolean(nil,true),pdfboolean(nil,false))
+
+ local r_zero = setmetatable({ 0 },mt_r)
+
+ pdfreference = function(r) -- maybe make a weak table
+ if r and r ~= 0 then
+ return setmetatable({ r },mt_r)
+ else
+ return r_zero
+ end
+ end
+
+ local v_zero = setmetatable({ 0 },mt_v)
+ local v_empty = setmetatable({ "" },mt_v)
+
+ pdfverbose = function(t) -- maybe check for type
+ if t == 0 then
+ return v_zero
+ elseif t == "" then
+ return v_empty
+ else
+ return setmetatable({ t },mt_v)
+ end
+ end
+
+end
+
+lpdf.stream = pdfstream -- THIS WILL PROBABLY CHANGE
+lpdf.dictionary = pdfdictionary
+lpdf.array = pdfarray
+lpdf.docstring = pdfdocstring
+lpdf.string = pdfstring
+lpdf.unicode = pdfunicode
+lpdf.number = pdfnumber
+lpdf.constant = pdfconstant
+lpdf.null = pdfnull
+lpdf.boolean = pdfboolean
+lpdf.reference = pdfreference
+lpdf.verbose = pdfverbose
+
+local names, cache = { }, { }
+
+function lpdf.reserveobject(name)
+ local r = pdfreserveobject() -- we don't support "annot"
+ if name then
+ names[name] = r
+ if trace_objects then
+ report_objects("reserving number %a under name %a",r,name)
+ end
+ elseif trace_objects then
+ report_objects("reserving number %a",r)
+ end
+ return r
+end
+
+-- lpdf.immediateobject = pdfimmediateobject
+-- lpdf.deferredobject = pdfdeferredobject
+-- lpdf.object = pdfdeferredobject
+-- lpdf.referenceobject = pdfreferenceobject
+
+local pagereference = pdf.pageref -- tex.pdfpageref is obsolete
+local nofpages = 0
+
+function lpdf.pagereference(n)
+ if nofpages == 0 then
+ nofpages = structures.pages.nofpages
+ if nofpages == 0 then
+ nofpages = 1
+ end
+ end
+ if n > nofpages then
+ return pagereference(nofpages) -- or 1, could be configureable
+ else
+ return pagereference(n)
+ end
+end
+
+function lpdf.delayedobject(data,n)
+ if n then
+ pdfdeferredobject(n,data)
+ else
+ n = pdfdeferredobject(data)
+ end
+ pdfreferenceobject(n)
+ return n
+end
+
+function lpdf.flushobject(name,data)
+ if data then
+ local named = names[name]
+ if named then
+ if not trace_objects then
+ elseif trace_detail then
+ report_objects("flushing data to reserved object with name %a, data: %S",name,data)
+ else
+ report_objects("flushing data to reserved object with name %a",name)
+ end
+ return pdfimmediateobject(named,tostring(data))
+ else
+ if not trace_objects then
+ elseif trace_detail then
+ report_objects("flushing data to reserved object with number %s, data: %S",name,data)
+ else
+ report_objects("flushing data to reserved object with number %s",name)
+ end
+ return pdfimmediateobject(name,tostring(data))
+ end
+ else
+ if trace_objects and trace_detail then
+ report_objects("flushing data: %S",name)
+ end
+ return pdfimmediateobject(tostring(name))
+ end
+end
+
+
+function lpdf.flushstreamobject(data,dict,compressed) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream object of %s bytes",#data)
+ end
+ local dtype = type(dict)
+ return pdfdeferredobject {
+ immediate = true,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ string = data,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+end
+
+function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream file object %a",filename)
+ end
+ local dtype = type(dict)
+ return pdfdeferredobject {
+ immediate = true,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ file = filename,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+end
+
+local shareobjectcache, shareobjectreferencecache = { }, { }
+
+function lpdf.shareobject(content)
+ if content == nil then
+ -- invalid object not created
+ else
+ content = tostring(content)
+ local o = shareobjectcache[content]
+ if not o then
+ o = pdfimmediateobject(content)
+ shareobjectcache[content] = o
+ end
+ return o
+ end
+end
+
+function lpdf.shareobjectreference(content)
+ if content == nil then
+ -- invalid object not created
+ else
+ content = tostring(content)
+ local r = shareobjectreferencecache[content]
+ if not r then
+ local o = shareobjectcache[content]
+ if not o then
+ o = pdfimmediateobject(content)
+ shareobjectcache[content] = o
+ end
+ r = pdfreference(o)
+ shareobjectreferencecache[content] = r
+ end
+ return r
+ end
+end
+
+-- three priority levels, default=2
+
+local pagefinalizers = { { }, { }, { } }
+local documentfinalizers = { { }, { }, { } }
+
+local pageresources, pageattributes, pagesattributes
+
+local function resetpageproperties()
+ pageresources = pdfdictionary()
+ pageattributes = pdfdictionary()
+ pagesattributes = pdfdictionary()
+end
+
+resetpageproperties()
+
+local function setpageproperties()
+ pdfsetpageresources (pageresources ())
+ pdfsetpageattributes (pageattributes ())
+ pdfsetpagesattributes(pagesattributes())
+end
+
+local function addtopageresources (k,v) pageresources [k] = v end
+local function addtopageattributes (k,v) pageattributes [k] = v end
+local function addtopagesattributes(k,v) pagesattributes[k] = v end
+
+lpdf.addtopageresources = addtopageresources
+lpdf.addtopageattributes = addtopageattributes
+lpdf.addtopagesattributes = addtopagesattributes
+
+local function set(where,what,f,when,comment)
+ if type(when) == "string" then
+ when, comment = 2, when
+ elseif not when then
+ when = 2
+ end
+ local w = where[when]
+ w[#w+1] = { f, comment }
+ if trace_finalizers then
+ report_finalizing("%s set: [%s,%s]",what,when,#w)
+ end
+end
+
+local function run(where,what)
+ if trace_finalizers then
+ report_finalizing("start backend, category %a, n %a",what,#where)
+ end
+ for i=1,#where do
+ local w = where[i]
+ for j=1,#w do
+ local wj = w[j]
+ if trace_finalizers then
+ report_finalizing("%s finalizer: [%s,%s] %s",what,i,j,wj[2] or "")
+ end
+ wj[1]()
+ end
+ end
+ if trace_finalizers then
+ report_finalizing("stop finalizing")
+ end
+end
+
+local function registerpagefinalizer(f,when,comment)
+ set(pagefinalizers,"page",f,when,comment)
+end
+
+local function registerdocumentfinalizer(f,when,comment)
+ set(documentfinalizers,"document",f,when,comment)
+end
+
+lpdf.registerpagefinalizer = registerpagefinalizer
+lpdf.registerdocumentfinalizer = registerdocumentfinalizer
+
+function lpdf.finalizepage(shipout)
+ if shipout and not environment.initex then
+ -- resetpageproperties() -- maybe better before
+ run(pagefinalizers,"page")
+ setpageproperties()
+ resetpageproperties() -- maybe better before
+ end
+end
+
+function lpdf.finalizedocument()
+ if not environment.initex then
+ run(documentfinalizers,"document")
+ function lpdf.finalizedocument()
+ 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")
+
+end
+
+callbacks.register("finish_pdffile", lpdf.finalizedocument)
+
+
+do
+
+ -- some minimal tracing, handy for checking the order
+
+ local function trace_set(what,key)
+ if trace_resources then
+ report_finalizing("setting key %a in %a",key,what)
+ end
+ end
+
+ local function trace_flush(what)
+ if trace_resources then
+ report_finalizing("flushing %a",what)
+ end
+ end
+
+ lpdf.protectresources = true
+
+ local catalog = pdfdictionary { Type = pdfconstant("Catalog") } -- nicer, but when we assign we nil the Type
+ 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()
+ if not environment.initex then
+ trace_flush("catalog")
+ catalog.Type = nil
+ pdfsetcatalog(catalog())
+ end
+ end
+
+ local function flushinfo()
+ if not environment.initex then
+ trace_flush("info")
+ 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.addtocatalog(k,v)
+ if not (lpdf.protectresources and catalog[k]) then
+ trace_set("catalog",k)
+ catalog[k] = v
+ end
+ end
+
+ function lpdf.addtoinfo(k,v)
+ if not (lpdf.protectresources and info[k]) then
+ trace_set("info",k)
+ info[k] = v
+ end
+ end
+
+ -- local function lpdf.addtonames(k,v)
+ -- if not (lpdf.protectresources and names[k]) then
+ -- trace_set("names",k)
+ -- names[k] = v
+ -- end
+ -- end
+
+ local names = pdfdictionary {
+ -- Type = pdfconstant("Names")
+ }
+
+ local function flushnames()
+ if next(names) and not environment.initex then
+ names.Type = pdfconstant("Names")
+ trace_flush("names")
+ lpdf.addtocatalog("Names",pdfreference(pdfimmediateobject(tostring(names))))
+ end
+ end
+
+ function lpdf.addtonames(k,v)
+ if not (lpdf.protectresources and names[k]) then
+ trace_set("names", k)
+ names [k] = v
+ 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 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 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
+
+ function lpdf.collectedresources()
+ 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
+ if ExtGState or ColorSpace or Pattern or Shading then
+ local collected = pdfdictionary {
+ ExtGState = ExtGState,
+ ColorSpace = ColorSpace,
+ Pattern = Pattern,
+ Shading = Shading,
+ -- ProcSet = pdfarray { pdfconstant("PDF") },
+ }
+ return collected()
+ else
+ return ""
+ 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
+
+ registerdocumentfinalizer(flushextgstates,3,"extended graphic states")
+ registerdocumentfinalizer(flushcolorspaces,3,"color spaces")
+ registerdocumentfinalizer(flushpatterns,3,"patterns")
+ registerdocumentfinalizer(flushshades,3,"shades")
+
+ registerdocumentfinalizer(flushnames,3,"names") -- before catalog
+ registerdocumentfinalizer(flushcatalog,3,"catalog")
+ registerdocumentfinalizer(flushinfo,3,"info")
+
+ registerpagefinalizer(checkextgstates,3,"extended graphic states")
+ registerpagefinalizer(checkcolorspaces,3,"color spaces")
+ registerpagefinalizer(checkpatterns,3,"patterns")
+ registerpagefinalizer(checkshades,3,"shades")
+
+end
+
+-- in strc-bkm: lpdf.registerdocumentfinalizer(function() structures.bookmarks.place() end,1)
+
+function lpdf.rotationcm(a)
+ local s, c = sind(a), cosd(a)
+ return format("%0.6F %0.6F %0.6F %0.6F 0 0 cm",c,s,-s,c)
+end
+
+-- ! -> universaltime
+
+do
+
+ local timestamp = os.date("%Y-%m-%dT%X") .. os.timezone(true)
+
+ function lpdf.timestamp()
+ return timestamp
+ end
+
+ function lpdf.pdftimestamp(str)
+ local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$")
+ 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()
+ return format("%s.%s",tex.jobname,timestamp)
+ end
+
+end
+
+-- return nil is nicer in test prints
+
+function lpdf.checkedkey(t,key,variant)
+ local pn = t and t[key]
+ if pn ~= nil then
+ local tn = type(pn)
+ if tn == variant then
+ if variant == "string" then
+ if pn ~= "" then
+ return pn
+ end
+ elseif variant == "table" then
+ if next(pn) then
+ return pn
+ end
+ else
+ return pn
+ end
+ elseif tn == "string" then
+ if variant == "number" then
+ return tonumber(pn)
+ elseif variant == "boolean" then
+ return isboolean(pn,nil,true)
+ end
+ end
+ end
+ -- return nil
+end
+
+function lpdf.checkedvalue(value,variant) -- code not shared
+ if value ~= nil then
+ local tv = type(value)
+ if tv == variant then
+ if variant == "string" then
+ if value ~= "" then
+ return value
+ end
+ elseif variant == "table" then
+ if next(value) then
+ return value
+ end
+ else
+ return value
+ end
+ elseif tv == "string" then
+ if variant == "number" then
+ return tonumber(value)
+ elseif variant == "boolean" then
+ return isboolean(value,nil,true)
+ end
+ end
+ end
+ -- return nil
+end
+
+function lpdf.limited(n,min,max,default)
+ if not n then
+ return default
+ else
+ n = tonumber(n)
+ if not n then
+ return default
+ elseif n > max then
+ return max
+ elseif n < min then
+ return min
+ else
+ return n
+ end
+ 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
+-- newline plus space.
+
+-- return formatters["BT /Span << /ActualText (CONTEXT) >> BDC [<feff>] TJ % t EMC ET"](code)
+
+do
+
+ local f_actual_text_one = formatters["BT /Span << /ActualText <feff%04x> >> BDC [<feff>] TJ %s EMC ET"]
+ local f_actual_text_one_b = formatters["BT /Span << /ActualText <feff%04x> >> BDC [<feff>] TJ "]
+ local f_actual_text_two = formatters["BT /Span << /ActualText <feff%04x%04x> >> BDC [<feff>] TJ %s EMC ET"]
+ local f_actual_text_two_b = formatters["BT /Span << /ActualText <feff%04x%04x> >> BDC [<feff>] TJ "]
+ local s_actual_text_e = " EMC ET"
+ local f_actual_text = formatters["/Span <</ActualText %s >> BDC"]
+
+ local context = context
+ local pdfdirect = nodes.pool.pdfdirect
+
+ -- todo: use tounicode from the font mapper
+
+ function codeinjections.unicodetoactualtext(unicode,pdfcode)
+ if unicode < 0x10000 then
+ return f_actual_text_one(unicode,pdfcode)
+ else
+ return f_actual_text_two(unicode/1024+0xD800,unicode%1024+0xDC00,pdfcode)
+ end
+ end
+
+ function codeinjections.startunicodetoactualtext(unicode)
+ if unicode < 0x10000 then
+ return f_actual_text_one_b(unicode)
+ else
+ return f_actual_text_two_b(unicode/1024+0xD800,unicode%1024+0xDC00)
+ end
+ end
+
+ function codeinjections.stopunicodetoactualtext()
+ return s_actual_text_e
+ end
+
+ implement {
+ name = "startactualtext",
+ arguments = "string",
+ actions = function(str)
+ context(pdfdirect(f_actual_text(tosixteen(str))))
+ end
+ }
+
+ implement {
+ name = "stopactualtext",
+ actions = function()
+ context(pdfdirect("EMC"))
+ end
+ }
+
+end
+
+-- interface
+
+implement { name = "lpdf_collectedresources", actions = { lpdf.collectedresources, context } }
+implement { name = "lpdf_addtocatalog", arguments = two_strings, actions = lpdf.addtocatalog }
+implement { name = "lpdf_addtoinfo", arguments = two_strings, actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted
+implement { name = "lpdf_addtonames", arguments = two_strings, actions = lpdf.addtonames }
+implement { name = "lpdf_addtopageattributes", arguments = two_strings, actions = lpdf.addtopageattributes }
+implement { name = "lpdf_addtopagesattributes", arguments = two_strings, actions = lpdf.addtopagesattributes }
+implement { name = "lpdf_addtopageresources", arguments = two_strings, actions = lpdf.addtopageresources }
+implement { name = "lpdf_adddocumentextgstate", arguments = two_strings, actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentcolorspace", arguments = two_strings, actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentpattern", arguments = two_strings, actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentshade", arguments = two_strings, actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end }
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua
new file mode 100644
index 00000000000..62713727d8e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua
@@ -0,0 +1,472 @@
+if not modules then modules = { } end modules ['lpdf-mis'] = {
+ 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"
+}
+
+-- Although we moved most pdf handling to the lua end, we didn't change
+-- the overall approach. For instance we share all resources i.e. we
+-- don't make subsets for each xform or page. The current approach is
+-- quite efficient. A big difference between MkII and MkIV is that we
+-- now use forward references. In this respect the MkII code shows that
+-- it evolved over a long period, when backends didn't provide forward
+-- referencing and references had to be tracked in multiple passes. Of
+-- course there are a couple of more changes.
+
+local next, tostring = next, tostring
+local format, gsub, formatters = string.format, string.gsub, string.formatters
+local texset, texget = tex.set, tex.get
+
+local backends, lpdf, nodes = backends, lpdf, nodes
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local copy_node = node.copy
+
+local nodepool = nodes.pool
+local pdfliteral = nodepool.pdfliteral
+local register = nodepool.register
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfboolean = lpdf.boolean
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfverbose = lpdf.verbose
+local pdfstring = lpdf.string
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfaction = lpdf.action
+
+local formattedtimestamp = lpdf.pdftimestamp
+local adddocumentextgstate = lpdf.adddocumentextgstate
+local addtocatalog = lpdf.addtocatalog
+local addtoinfo = lpdf.addtoinfo
+local addtopageattributes = lpdf.addtopageattributes
+local addtonames = lpdf.addtonames
+
+local variables = interfaces.variables
+local v_stop = variables.stop
+
+local positive = register(pdfliteral("/GSpositive gs"))
+local negative = register(pdfliteral("/GSnegative gs"))
+local overprint = register(pdfliteral("/GSoverprint gs"))
+local knockout = register(pdfliteral("/GSknockout gs"))
+
+local function initializenegative()
+ local a = pdfarray { 0, 1 }
+ local g = pdfconstant("ExtGState")
+ local d = pdfdictionary {
+ FunctionType = 4,
+ Range = a,
+ Domain = a,
+ }
+ local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) }
+ local positive = pdfdictionary { Type = g, TR = pdfconstant("Identity") }
+ adddocumentextgstate("GSnegative", pdfreference(pdfflushobject(negative)))
+ adddocumentextgstate("GSpositive", pdfreference(pdfflushobject(positive)))
+ initializenegative = nil
+end
+
+local function initializeoverprint()
+ local g = pdfconstant("ExtGState")
+ local knockout = pdfdictionary { Type = g, OP = false, OPM = 0 }
+ local overprint = pdfdictionary { Type = g, OP = true, OPM = 1 }
+ adddocumentextgstate("GSknockout", pdfreference(pdfflushobject(knockout)))
+ adddocumentextgstate("GSoverprint", pdfreference(pdfflushobject(overprint)))
+ initializeoverprint = nil
+end
+
+function nodeinjections.overprint()
+ if initializeoverprint then initializeoverprint() end
+ return copy_node(overprint)
+end
+function nodeinjections.knockout ()
+ if initializeoverprint then initializeoverprint() end
+ return copy_node(knockout)
+end
+
+function nodeinjections.positive()
+ if initializenegative then initializenegative() end
+ return copy_node(positive)
+end
+function nodeinjections.negative()
+ if initializenegative then initializenegative() end
+ return copy_node(negative)
+end
+
+-- function codeinjections.addtransparencygroup()
+-- -- png: /CS /DeviceRGB /I true
+-- local d = pdfdictionary {
+-- S = pdfconstant("Transparency"),
+-- I = true,
+-- K = true,
+-- }
+-- lpdf.registerpagefinalizer(function() addtopageattributes("Group",d) end) -- hm
+-- end
+
+-- actions (todo: store and update when changed)
+
+local openpage, closepage, opendocument, closedocument
+
+function codeinjections.registerdocumentopenaction(open)
+ opendocument = open
+end
+
+function codeinjections.registerdocumentcloseaction(close)
+ closedocument = close
+end
+
+function codeinjections.registerpageopenaction(open)
+ openpage = open
+end
+
+function codeinjections.registerpagecloseaction(close)
+ closepage = close
+end
+
+local function flushdocumentactions()
+ if opendocument then
+ addtocatalog("OpenAction",pdfaction(opendocument))
+ end
+ if closedocument then
+ addtocatalog("CloseAction",pdfaction(closedocument))
+ end
+end
+
+local function flushpageactions()
+ if openpage or closepage then
+ local d = pdfdictionary()
+ if openpage then
+ d.O = pdfaction(openpage)
+ end
+ if closepage then
+ d.C = pdfaction(closepage)
+ end
+ addtopageattributes("AA",d)
+ end
+end
+
+lpdf.registerpagefinalizer (flushpageactions, "page actions")
+lpdf.registerdocumentfinalizer(flushdocumentactions,"document actions")
+
+--- info : this can change and move elsewhere
+
+local identity = { }
+
+function codeinjections.setupidentity(specification)
+ for k, v in next, specification do
+ if v ~= "" then
+ identity[k] = v
+ end
+ end
+end
+
+local done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register
+
+local function setupidentity()
+ if not done then
+ local title = identity.title
+ if not title or title == "" then
+ title = tex.jobname
+ end
+ addtoinfo("Title", pdfunicode(title), title)
+ local subtitle = identity.subtitle or ""
+ if subtitle ~= "" then
+ addtoinfo("Subject", pdfunicode(subtitle), subtitle)
+ end
+ local author = identity.author or ""
+ if author ~= "" then
+ addtoinfo("Author", pdfunicode(author), author) -- '/Author' in /Info, 'Creator' in XMP
+ end
+ local creator = identity.creator or ""
+ if creator ~= "" then
+ addtoinfo("Creator", pdfunicode(creator), creator) -- '/Creator' in /Info, 'CreatorTool' in XMP
+ end
+ local currenttimestamp = lpdf.timestamp()
+ addtoinfo("CreationDate", pdfstring(formattedtimestamp(currenttimestamp)))
+ local date = identity.date or ""
+ local pdfdate = formattedtimestamp(date)
+ if pdfdate then
+ addtoinfo("ModDate", pdfstring(pdfdate), date)
+ else
+ -- users should enter the date in 2010-01-19T23:27:50+01:00 format
+ -- and if not provided that way we use the creation time instead
+ addtoinfo("ModDate", pdfstring(formattedtimestamp(currenttimestamp)), currenttimestamp)
+ end
+ local keywords = identity.keywords or ""
+ if keywords ~= "" then
+ keywords = gsub(keywords, "[%s,]+", " ")
+ addtoinfo("Keywords",pdfunicode(keywords), keywords)
+ end
+ local id = lpdf.id()
+ addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x
+ --
+ addtoinfo("ConTeXt.Version", environment.version)
+ addtoinfo("ConTeXt.Time", os.date("%Y-%m-%d %H:%M"))
+ addtoinfo("ConTeXt.Jobname", environment.jobname or tex.jobname)
+ addtoinfo("ConTeXt.Url", "www.pragma-ade.com")
+ addtoinfo("ConTeXt.Support", "contextgarden.net")
+ --
+ done = true
+ else
+ -- no need for a message
+ end
+end
+
+lpdf.registerpagefinalizer(setupidentity,"identity")
+
+-- or when we want to be able to set things after pag e1:
+--
+-- lpdf.registerdocumentfinalizer(setupidentity,1,"identity")
+
+local function flushjavascripts()
+ local t = interactions.javascripts.flushpreambles()
+ if #t > 0 then
+ local a = pdfarray()
+ local pdf_javascript = pdfconstant("JavaScript")
+ for i=1,#t do
+ local name, script = t[i][1], t[i][2]
+ local j = pdfdictionary {
+ S = pdf_javascript,
+ JS = pdfreference(pdfflushstreamobject(script)),
+ }
+ a[#a+1] = pdfstring(name)
+ a[#a+1] = pdfreference(pdfflushobject(j))
+ end
+ addtonames("JavaScript",pdfreference(pdfflushobject(pdfdictionary{ Names = a })))
+ end
+end
+
+lpdf.registerdocumentfinalizer(flushjavascripts,"javascripts")
+
+-- -- --
+
+local pagespecs = {
+ [variables.max] = { mode = "FullScreen", layout = false, fit = false, fixed = false, duplex = false },
+ [variables.bookmark] = { mode = "UseOutlines", layout = false, fit = false, fixed = false, duplex = false },
+ [variables.fit] = { mode = "UseNone", layout = false, fit = true, fixed = false, duplex = false },
+ [variables.doublesided] = { mode = "UseNone", layout = "TwoColumnRight", fit = true, fixed = false, duplex = false },
+ [variables.singlesided] = { mode = "UseNone", layout = false, fit = false, fixed = false, duplex = false },
+ [variables.default] = { mode = "UseNone", layout = "auto", fit = false, fixed = false, duplex = false },
+ [variables.auto] = { mode = "UseNone", layout = "auto", fit = false, fixed = false, duplex = false },
+ [variables.none] = { mode = false, layout = false, fit = false, fixed = false, duplex = false },
+ -- new
+ [variables.fixed] = { mode = "UseNone", layout = "auto", fit = false, fixed = true, duplex = false }, -- noscale
+ [variables.landscape] = { mode = "UseNone", layout = "auto", fit = false, fixed = true, duplex = "DuplexFlipShortEdge" },
+ [variables.portrait] = { mode = "UseNone", layout = "auto", fit = false, fixed = true, duplex = "DuplexFlipLongEdge" },
+ [variables.page] = { mode = "UseNone", layout = "auto", fit = false, fixed = true, duplex = "Simplex" },
+}
+
+local pagespec, topoffset, leftoffset, height, width, doublesided = "default", 0, 0, 0, 0, false
+local cropoffset, bleedoffset, trimoffset, artoffset = 0, 0, 0, 0
+
+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
+ 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")
+ --
+ cropoffset = specification.cropoffset or 0
+ trimoffset = cropoffset - (specification.trimoffset or 0)
+ bleedoffset = trimoffset - (specification.bleedoffset or 0)
+ artoffset = bleedoffset - (specification.artoffset or 0)
+ --
+ if paperdouble ~= nil then
+ doublesided = paperdouble
+ end
+end
+
+local function documentspecification()
+ if not pagespec or pagespec == "" then
+ pagespec = variables.default
+ end
+ -- local settings = utilities.parsers.settings_to_array(pagespec)
+ -- local spec = pagespecs[variables.default]
+ -- for i=1,#settings do
+ -- local s = pagespecs[settings[i]]
+ -- if s then
+ -- for k, v in next, s do
+ -- spec[k] = v
+ -- end
+ -- end
+ -- end
+ local spec = pagespecs[pagespec] or pagespecs[variables.default]
+ if spec.layout == "auto" then
+ if doublesided then
+ local s = pagespecs[variables.doublesided] -- to be checked voor interfaces
+ for k, v in next, s do
+ spec[k] = v
+ end
+ else
+ spec.layout = false
+ end
+ end
+ local layout = spec.layout
+ local mode = spec.mode
+ local fit = spec.fit
+ local fixed = spec.fixed
+ local duplex = spec.duplex
+ if layout then
+ addtocatalog("PageLayout",pdfconstant(layout))
+ end
+ if mode then
+ addtocatalog("PageMode",pdfconstant(mode))
+ end
+ if fit or fixed or duplex then
+ addtocatalog("ViewerPreferences",pdfdictionary {
+ FitWindow = fit and true or nil,
+ PrintScaling = fixed and pdfconstant("None") or nil,
+ Duplex = duplex and pdfconstant(duplex) or nil,
+ })
+ end
+ addtoinfo ("Trapped", pdfconstant("False")) -- '/Trapped' in /Info, 'Trapped' in XMP
+ addtocatalog("Version", pdfconstant(format("1.%s",pdf.getminorversion())))
+end
+
+-- temp hack: the mediabox is not under our control and has a precision of 4 digits
+
+local factor = number.dimenfactors.bp
+local f_value = formatters["%0.4F"]
+
+local function boxvalue(n) -- we could share them
+ return pdfverbose(f_value(factor * n))
+end
+
+local function pagespecification()
+ local llx = leftoffset
+ local lly = texget("pageheight") + topoffset - height
+ local urx = width - leftoffset
+ local ury = texget("pageheight") - topoffset
+ -- boxes can be cached
+ local function extrabox(WhatBox,offset,always)
+ if offset ~= 0 or always then
+ addtopageattributes(WhatBox, pdfarray {
+ boxvalue(llx + offset),
+ boxvalue(lly + offset),
+ boxvalue(urx - offset),
+ boxvalue(ury - offset),
+ })
+ 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
+end
+
+lpdf.registerpagefinalizer(pagespecification,"page specification")
+lpdf.registerdocumentfinalizer(documentspecification,"document specification")
+
+-- Page Label support ...
+--
+-- In principle we can also support /P (prefix) as we can just use the verbose form
+-- and we can then forget about the /St (start) as we don't care about those few
+-- extra bytes due to lack of collapsing. Anyhow, for that we need a stupid prefix
+-- variant and that's not on the agenda now.
+
+local map = {
+ numbers = "D",
+ Romannumerals = "R",
+ romannumerals = "r",
+ Characters = "A",
+ characters = "a",
+}
+
+-- local function featurecreep()
+-- local pages, lastconversion, list = structures.pages.tobesaved, nil, pdfarray()
+-- local getstructureset = structures.sets.get
+-- for i=1,#pages do
+-- local p = pages[i]
+-- if not p then
+-- return -- fatal error
+-- else
+-- local numberdata = p.numberdata
+-- if numberdata then
+-- local conversionset = numberdata.conversionset
+-- if conversionset then
+-- local conversion = getstructureset("structure:conversions",p.block,conversionset,1,"numbers")
+-- if conversion ~= lastconversion then
+-- lastconversion = conversion
+-- list[#list+1] = i - 1 -- pdf starts numbering at 0
+-- list[#list+1] = pdfdictionary { S = pdfconstant(map[conversion] or map.numbers) }
+-- end
+-- end
+-- end
+-- if not lastconversion then
+-- lastconversion = "numbers"
+-- list[#list+1] = i - 1 -- pdf starts numbering at 0
+-- list[#list+1] = pdfdictionary { S = pdfconstant(map.numbers) }
+-- end
+-- end
+-- end
+-- addtocatalog("PageLabels", pdfdictionary { Nums = list })
+-- end
+
+local function featurecreep()
+ local pages = structures.pages.tobesaved
+ local list = pdfarray()
+ local getset = structures.sets.get
+ local stopped = false
+ local oldlabel = nil
+ local olconversion = nil
+ for i=1,#pages do
+ local p = pages[i]
+ if not p then
+ return -- fatal error
+ end
+ local label = p.viewerprefix or ""
+ if p.status == v_stop then
+ if not stopped then
+ list[#list+1] = i - 1 -- pdf starts numbering at 0
+ list[#list+1] = pdfdictionary {
+ P = pdfunicode(label),
+ }
+ stopped = true
+ end
+ oldlabel = nil
+ oldconversion = nil
+ stopped = false
+ else
+ local numberdata = p.numberdata
+ local conversion = nil
+ local number = p.number
+ if numberdata then
+ local conversionset = numberdata.conversionset
+ if conversionset then
+ conversion = getset("structure:conversions",p.block,conversionset,1,"numbers")
+ end
+ end
+ conversion = conversion and map[conversion] or map.numbers
+ if number == 1 or oldlabel ~= label or oldconversion ~= conversion then
+ list[#list+1] = i - 1 -- pdf starts numbering at 0
+ list[#list+1] = pdfdictionary {
+ S = pdfconstant(conversion),
+ St = number,
+ P = label ~= "" and pdfunicode(label) or nil,
+ }
+ end
+ oldlabel = label
+ oldconversion = conversion
+ stopped = false
+ end
+ end
+ addtocatalog("PageLabels", pdfdictionary { Nums = list })
+end
+
+lpdf.registerdocumentfinalizer(featurecreep,"featurecreep")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-mov.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mov.lua
new file mode 100644
index 00000000000..87375e4ce74
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mov.lua
@@ -0,0 +1,67 @@
+if not modules then modules = { } end modules ['lpdf-mov'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local lpdf = lpdf
+
+local nodeinjections = backends.pdf.nodeinjections
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfborder = lpdf.border
+local write_node = node.write
+
+function nodeinjections.insertmovie(specification)
+ -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname
+ local width = specification.width
+ local height = specification.height
+ local factor = specification.factor or number.dimenfactors.bp
+ local moviedict = pdfdictionary {
+ F = specification.foundname,
+ Aspect = pdfarray { factor * width, factor * height },
+ Poster = (specification.preview and true) or false,
+ }
+ local controldict = pdfdictionary {
+ ShowControls = (specification.controls and true) or false,
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil,
+ }
+ local bs, bc = pdfborder()
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = bs,
+ C = bc,
+ T = format("movie %s",specification.label),
+ Movie = moviedict,
+ A = controldict,
+ }
+ write_node(nodeinjections.annotation(width,height,0,action())) -- test: context(...)
+end
+
+function nodeinjections.insertsound(specification)
+ -- rmanaged in interaction: repeat, label, foundname
+ local soundclip = interactions.soundclips.soundclip(specification.label)
+ if soundclip then
+ local controldict = pdfdictionary {
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil
+ }
+ local sounddict = pdfdictionary {
+ F = soundclip.filename
+ }
+ local bs, bc = pdfborder()
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = bs,
+ C = bc,
+ T = format("sound %s",specification.label),
+ Movie = sounddict,
+ A = controldict,
+ }
+ write_node(nodeinjections.annotation(0,0,0,action())) -- test: context(...)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua
new file mode 100644
index 00000000000..3dd5a664807
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua
@@ -0,0 +1,183 @@
+if not modules then modules = { } end modules ['lpdf-nod'] = {
+ 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 type = type
+
+local formatters = string.formatters
+
+local whatsitcodes = nodes.whatsitcodes
+local nodeinjections = backends.nodeinjections
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local setfield = nuts.setfield
+
+local copy_node = nuts.copy
+local new_node = nuts.new
+
+local nodepool = nuts.pool
+local register = nodepool.register
+
+local pdfliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfliteral,"mode",1)
+local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave))
+local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore))
+local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix))
+----- pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched
+----- pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot))
+
+local variables = interfaces.variables
+
+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.pdfliteral(str)
+ local t = copy_node(pdfliteral)
+ setfield(t,"data",str)
+ return t
+end
+
+function nodepool.pdfdirect(str)
+ local t = copy_node(pdfliteral)
+ setfield(t,"data",str)
+ setfield(t,"mode",1)
+ return t
+end
+
+function nodepool.pdfsave()
+ return copy_node(pdfsave)
+end
+
+function nodepool.pdfrestore()
+ return copy_node(pdfrestore)
+end
+
+function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty
+ local t = copy_node(pdfsetmatrix)
+ if type(rx) == "string" then
+ setfield(t,"data",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
+ 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
+ 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
+end
+
+-- (!) The next code in pdfdest.w is wrong:
+--
+-- case pdf_dest_xyz:
+-- if (matrixused()) {
+-- set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin) ;
+-- } else {
+-- pdf_ann_left(p) = pos.h ;
+-- pdf_ann_top (p) = pos.v ;
+-- }
+-- break ;
+--
+-- so we need to force a matrix.
+
+function nodepool.pdfdestination(w,h,d,name,view,n)
+ 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
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml
new file mode 100644
index 00000000000..3f6b969c01d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0"?>
+
+<!-- lpdf-pda.xml -->
+
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <!-- http://www.pdfa.org/wp-content/uploads/2011/08/tn0008_predefined_xmp_properties_in_pdfa-1_2008-03-20.pdf -->
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:creator>
+ <rdf:Seq>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Seq>
+ </dc:creator>
+ <dc:description>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:description>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
+ <pdfx:ConTeXt.Jobname/>
+ <pdfx:ConTeXt.Time/>
+ <pdfx:ConTeXt.Url/>
+ <pdfx:ConTeXt.Version/>
+ <pdfx:ID/>
+ <pdfx:PTEX.Fullbanner/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+ <xmp:CreateDate/>
+ <xmp:CreatorTool/>
+ <xmp:ModifyDate/>
+ <xmp:MetadataDate/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Keywords/>
+ <pdf:Producer/>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
+ <xmpMM:DocumentID/>
+ <xmpMM:InstanceID/>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
+ xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
+ xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/pdf/1.3/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdf</pdfaSchema:prefix>
+ <pdfaSchema:schema>Adobe PDF Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>A name object indicating whether the document has been modified to include trapping information</pdfaProperty:description>
+ <pdfaProperty:name>Trapped</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://purl.org/dc/elements/1.1/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdf</pdfaSchema:prefix>
+ <pdfaSchema:schema>Dubline Core Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Subject in Document Properties</pdfaProperty:description>
+ <pdfaProperty:name>description</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/pdfx/1.3/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdfx</pdfaSchema:prefix>
+ <pdfaSchema:schema>PDF/X ID Schema</pdfaSchema:schema>
+ <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>
+ </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>
+ </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>
+ </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: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>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>
+ <pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>UUID based identifier for specific incarnation of a document</pdfaProperty:description>
+ <pdfaProperty:name>InstanceID</pdfaProperty:name>
+ <pdfaProperty:valueType>URI</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>
+ <pdfaSchema:schema>PDF/A ID Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Part of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>part</pdfaProperty:name>
+ <pdfaProperty:valueType>Integer</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Amendment of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>amd</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Conformance level of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>conformance</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml
new file mode 100644
index 00000000000..d55e1fdf303
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<!-- lpdf-pdx.xml -->
+
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:creator>
+ <rdf:Seq>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Seq>
+ </dc:creator>
+ <dc:description>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:description>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
+ <pdfx:ConTeXt.Jobname/>
+ <pdfx:ConTeXt.Time/>
+ <pdfx:ConTeXt.Url/>
+ <pdfx:ConTeXt.Version/>
+ <pdfx:ID/>
+ <pdfx:PTEX.Fullbanner/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+ <xmp:CreateDate/>
+ <xmp:CreatorTool/>
+ <xmp:ModifyDate/>
+ <xmp:MetadataDate/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Keywords/>
+ <pdf:Producer/>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
+ <xmpMM:DocumentID/>
+ <xmpMM:InstanceID/>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml
new file mode 100644
index 00000000000..c50e1f05be4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0"?>
+
+<!-- lpdf-pua.xml -->
+
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:creator>
+ <rdf:Seq>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Seq>
+ </dc:creator>
+ <dc:description>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:description>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default"/>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
+ <pdfx:ConTeXt.Jobname/>
+ <pdfx:ConTeXt.Time/>
+ <pdfx:ConTeXt.Url/>
+ <pdfx:ConTeXt.Version/>
+ <pdfx:ID/>
+ <pdfx:PTEX.Fullbanner/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+ <xmp:CreateDate/>
+ <xmp:CreatorTool/>
+ <xmp:ModifyDate/>
+ <xmp:MetadataDate/>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Keywords/>
+ <pdf:Producer/>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
+ <xmpMM:DocumentID/>
+ <xmpMM:InstanceID/>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
+ xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
+ xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/pdf/1.3/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdf</pdfaSchema:prefix>
+ <pdfaSchema:schema>Adobe PDF Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>A name object indicating whether the document has been modified to include trapping information</pdfaProperty:description>
+ <pdfaProperty:name>Trapped</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://purl.org/dc/elements/1.1/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdf</pdfaSchema:prefix>
+ <pdfaSchema:schema>Dubline Core Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Subject in Document Properties</pdfaProperty:description>
+ <pdfaProperty:name>description</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/pdfx/1.3/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdfx</pdfaSchema:prefix>
+ <pdfaSchema:schema>PDF/X ID Schema</pdfaSchema:schema>
+ <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>
+ </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>
+ </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>
+ </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: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>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>
+ <pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>UUID based identifier for specific incarnation of a document</pdfaProperty:description>
+ <pdfaProperty:name>InstanceID</pdfaProperty:name>
+ <pdfaProperty:valueType>URI</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>
+ <pdfaSchema:schema>PDF/A ID Schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Part of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>part</pdfaProperty:name>
+ <pdfaProperty:valueType>Integer</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Amendment of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>amd</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Conformance level of PDF/A standard</pdfaProperty:description>
+ <pdfaProperty:name>conformance</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:namespaceURI>http://www.aiim.org/pdfua/ns/id/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>pdfuaid</pdfaSchema:prefix>
+ <pdfaSchema:schema>PDF/UA identification schema</pdfaSchema:schema>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>PDF/UA version identifier</pdfaProperty:description>
+ <pdfaProperty:name>part</pdfaProperty:name>
+ <pdfaProperty:valueType>Integer</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>PDF/UA amendment identifier</pdfaProperty:description>
+ <pdfaProperty:name>amd</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>PDF/UA corrigenda identifier</pdfaProperty:description>
+ <pdfaProperty:name>corr</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua
new file mode 100644
index 00000000000..81b9e9f2024
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua
@@ -0,0 +1,386 @@
+if not modules then modules = { } end modules ['lpdf-ren'] = {
+ 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"
+}
+
+-- rendering
+
+local tostring, tonumber, next = tostring, tonumber, next
+local format, rep = string.format, string.rep
+local concat = table.concat
+local settings_to_array = utilities.parsers.settings_to_array
+
+local backends, lpdf, nodes, node = backends, lpdf, nodes, node
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+local viewerlayers = attributes.viewerlayers
+
+local references = structures.references
+
+references.executers = references.executers or { }
+local executers = references.executers
+
+local variables = interfaces.variables
+
+local v_no = variables.no
+local v_yes = variables.yes
+local v_start = variables.start
+local v_stop = variables.stop
+local v_reset = variables.reset
+local v_auto = variables.auto
+local v_random = variables.random
+
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+
+local addtopageattributes = lpdf.addtopageattributes
+local addtopageresources = lpdf.addtopageresources
+local addtocatalog = lpdf.addtocatalog
+
+local escaped = lpdf.escaped
+
+local nodepool = nodes.pool
+local register = nodepool.register
+local pdfliteral = nodepool.pdfliteral
+
+local pdf_ocg = pdfconstant("OCG")
+local pdf_ocmd = pdfconstant("OCMD")
+local pdf_off = pdfconstant("OFF")
+local pdf_on = pdfconstant("ON")
+local pdf_view = pdfconstant("View")
+local pdf_design = pdfconstant("Design")
+local pdf_toggle = pdfconstant("Toggle")
+local pdf_setocgstate = pdfconstant("SetOCGState")
+
+local copy_node = node.copy
+
+local pdf_print = {
+ [v_yes] = pdfdictionary { PrintState = pdf_on },
+ [v_no ] = pdfdictionary { PrintState = pdf_off },
+}
+
+local pdf_intent = {
+ [v_yes] = pdf_view,
+ [v_no] = pdf_design,
+}
+
+local pdf_export = {
+ [v_yes] = pdf_on,
+ [v_no] = pdf_off,
+}
+
+-- We can have references to layers before they are places, for instance from
+-- hide and vide actions. This is why we need to be able to force usage of layers
+-- at several moments.
+
+-- management
+
+local pdfln, pdfld = { }, { }
+local textlayers, hidelayers, videlayers = pdfarray(), pdfarray(), pdfarray()
+local pagelayers, pagelayersreference, cache = nil, nil, { }
+local alphabetic = { }
+
+local escapednames = table.setmetatableindex(function(t,k)
+ local v = escaped(k)
+ t[k] = v
+ return v
+end)
+
+local specifications = { }
+local initialized = { }
+
+function codeinjections.defineviewerlayer(specification)
+ if viewerlayers.supported and textlayers then
+ local tag = specification.tag
+ if not specifications[tag] then
+ specifications[tag] = specification
+ end
+ end
+end
+
+local function useviewerlayer(name) -- move up so that we can use it as local
+ if not environment.initex and not initialized[name] then
+ local specification = specifications[name]
+ if specification then
+ specifications[name] = nil -- or not
+ initialized [name] = true
+ if not pagelayers then
+ pagelayers = pdfdictionary()
+ pagelayersreference = pdfreserveobject()
+ end
+ local tag = specification.tag
+ -- todo: reserve
+ local nn = pdfreserveobject()
+ local nr = pdfreference(nn)
+ local nd = pdfdictionary {
+ Type = pdf_ocg,
+ Name = specification.title or "unknown",
+ Usage = {
+ Intent = pdf_intent[specification.editable or v_yes], -- disable layer hiding by user (useless)
+ Print = pdf_print [specification.printable or v_yes], -- printable or not
+ Export = pdf_export[specification.export or v_yes], -- export or not
+ },
+ }
+ cache[#cache+1] = { nn, nd }
+ pdfln[tag] = nr -- was n
+ local dn = pdfreserveobject()
+ local dr = pdfreference(dn)
+ local dd = pdfdictionary {
+ Type = pdf_ocmd,
+ OCGs = pdfarray { nr },
+ }
+ cache[#cache+1] = { dn, dd }
+ pdfld[tag] = dr
+ textlayers[#textlayers+1] = nr
+ alphabetic[tag] = nr
+ if specification.visible == v_start then
+ videlayers[#videlayers+1] = nr
+ else
+ hidelayers[#hidelayers+1] = nr
+ end
+ pagelayers[escapednames[tag]] = dr -- check
+ else
+ -- todo: message
+ end
+ end
+end
+
+codeinjections.useviewerlayer = useviewerlayer
+
+local function layerreference(name)
+ local r = pdfln[name]
+ if r then
+ return r
+ else
+ useviewerlayer(name)
+ return pdfln[name]
+ end
+end
+
+lpdf.layerreference = layerreference -- also triggered when a hide or vide happens
+
+local function flushtextlayers()
+ if viewerlayers.supported then
+ if pagelayers then
+ pdfflushobject(pagelayersreference,pagelayers)
+ end
+ for i=1,#cache do
+ local ci = cache[i]
+ pdfflushobject(ci[1],ci[2])
+ end
+ if textlayers and #textlayers > 0 then -- we can group them if needed, like: layout
+ local sortedlayers = { }
+ for k, v in table.sortedhash(alphabetic) do
+ sortedlayers[#sortedlayers+1] = v -- maybe do a proper numeric sort as well
+ end
+ local d = pdfdictionary {
+ OCGs = textlayers,
+ D = pdfdictionary {
+ Name = "Document",
+ -- Order = (viewerlayers.hasorder and textlayers) or nil,
+ Order = (viewerlayers.hasorder and sortedlayers) or nil,
+ ON = videlayers,
+ OFF = hidelayers,
+ BaseState = pdf_on,
+ AS = pdfarray {
+ pdfdictionary {
+ Category = pdfarray { pdfconstant("Print") },
+ Event = pdfconstant("Print"),
+ OCGs = (viewerlayers.hasorder and sortedlayers) or nil,
+ }
+ },
+ },
+ }
+ addtocatalog("OCProperties",d)
+ textlayers = nil
+ end
+ end
+end
+
+local function flushpagelayers() -- we can share these
+ if pagelayers then
+ addtopageresources("Properties",pdfreference(pagelayersreference)) -- we could cache this
+ end
+end
+
+lpdf.registerpagefinalizer (flushpagelayers,"layers")
+lpdf.registerdocumentfinalizer(flushtextlayers,"layers")
+
+local function setlayer(what,arguments)
+ -- maybe just a gmatch of even better, earlier in lpeg
+ arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments)
+ local state = pdfarray { what }
+ for i=1,#arguments do
+ local p = layerreference(arguments[i])
+ if p then
+ state[#state+1] = p
+ end
+ end
+ return pdfdictionary {
+ S = pdf_setocgstate,
+ State = state,
+ }
+end
+
+function executers.hidelayer (arguments) return setlayer(pdf_off, arguments) end
+function executers.videlayer (arguments) return setlayer(pdf_on, arguments) end
+function executers.togglelayer(arguments) return setlayer(pdf_toggle,arguments) end
+
+-- injection
+
+function codeinjections.startlayer(name) -- used in mp
+ if not name then
+ name = "unknown"
+ end
+ useviewerlayer(name)
+ return format("/OC /%s BDC",escapednames[name])
+end
+
+function codeinjections.stoplayer(name) -- used in mp
+ return "EMC"
+end
+
+local cache = { }
+
+function nodeinjections.startlayer(name)
+ local c = cache[name]
+ if not c then
+ useviewerlayer(name)
+ c = register(pdfliteral(format("/OC /%s BDC",escapednames[name])))
+ cache[name] = c
+ end
+ return copy_node(c)
+end
+
+local stop = register(pdfliteral("EMC"))
+
+function nodeinjections.stoplayer()
+ return copy_node(stop)
+end
+
+-- experimental stacker code (slow, can be optimized): !!!! TEST CODE !!!!
+
+local values = viewerlayers.values
+local startlayer = codeinjections.startlayer
+local stoplayer = codeinjections.stoplayer
+
+function nodeinjections.startstackedlayer(s,t,first,last)
+ local r = { }
+ for i=first,last do
+ r[#r+1] = startlayer(values[t[i]])
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
+function nodeinjections.stopstackedlayer(s,t,first,last)
+ local r = { }
+ for i=last,first,-1 do
+ r[#r+1] = stoplayer()
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
+function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
+ local r = { }
+ for i=last1,first1,-1 do
+ r[#r+1] = stoplayer()
+ end
+ for i=first2,last2 do
+ r[#r+1] = startlayer(values[t2[i]])
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
+-- transitions
+
+local pagetransitions = {
+ {"split","in","vertical"}, {"split","in","horizontal"},
+ {"split","out","vertical"}, {"split","out","horizontal"},
+ {"blinds","horizontal"}, {"blinds","vertical"},
+ {"box","in"}, {"box","out"},
+ {"wipe","east"}, {"wipe","west"}, {"wipe","north"}, {"wipe","south"},
+ {"dissolve"},
+ {"glitter","east"}, {"glitter","south"},
+ {"fly","in","east"}, {"fly","in","west"}, {"fly","in","north"}, {"fly","in","south"},
+ {"fly","out","east"}, {"fly","out","west"}, {"fly","out","north"}, {"fly","out","south"},
+ {"push","east"}, {"push","west"}, {"push","north"}, {"push","south"},
+ {"cover","east"}, {"cover","west"}, {"cover","north"}, {"cover","south"},
+ {"uncover","east"}, {"uncover","west"}, {"uncover","north"}, {"uncover","south"},
+ {"fade"},
+}
+
+local mapping = {
+ split = { "S" , pdfconstant("Split") },
+ blinds = { "S" , pdfconstant("Blinds") },
+ box = { "S" , pdfconstant("Box") },
+ wipe = { "S" , pdfconstant("Wipe") },
+ dissolve = { "S" , pdfconstant("Dissolve") },
+ glitter = { "S" , pdfconstant("Glitter") },
+ replace = { "S" , pdfconstant("R") },
+ fly = { "S" , pdfconstant("Fly") },
+ push = { "S" , pdfconstant("Push") },
+ cover = { "S" , pdfconstant("Cover") },
+ uncover = { "S" , pdfconstant("Uncover") },
+ fade = { "S" , pdfconstant("Fade") },
+ horizontal = { "Dm" , pdfconstant("H") },
+ vertical = { "Dm" , pdfconstant("V") },
+ ["in"] = { "M" , pdfconstant("I") },
+ out = { "M" , pdfconstant("O") },
+ east = { "Di" , 0 },
+ north = { "Di" , 90 },
+ west = { "Di" , 180 },
+ south = { "Di" , 270 },
+}
+
+local last = 0
+
+-- n: number, "stop", "reset", "random", "a,b,c" delay: number, "none"
+
+function codeinjections.setpagetransition(specification)
+ local n, delay = specification.n, specification.delay
+ if not n or n == "" then
+ return -- let's forget about it
+ elseif n == v_auto then
+ if last >= #pagetransitions then
+ last = 0
+ end
+ n = last + 1
+ elseif n == v_stop then
+ return
+ elseif n == v_reset then
+ last = 0
+ return
+ elseif n == v_random then
+ n = math.random(1,#pagetransitions)
+ else
+ n = tonumber(n)
+ end
+ local t = n and pagetransitions[n] or pagetransitions[1]
+ if not t then
+ t = settings_to_array(n)
+ end
+ if t and #t > 0 then
+ local d = pdfdictionary()
+ for i=1,#t do
+ local m = mapping[t[i]]
+ d[m[1]] = m[2]
+ end
+ delay = tonumber(delay)
+ if delay and delay > 0 then
+ addtopageattributes("Dur",delay)
+ end
+ addtopageattributes("Trans",d)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua
new file mode 100644
index 00000000000..ca092c772bf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua
@@ -0,0 +1,40 @@
+if not modules then modules = { } end modules ['lpdf-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"
+}
+
+local codeinjections = backends.codeinjections
+local implement = interfaces.implement
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+
+local setfield = nuts.setfield
+local setlist = nuts.setlist
+
+local new_hlist = nuts.pool.hlist
+
+local saveboxresource = tex.saveboxresource
+local useboxresource = tex.useboxresource
+local getboxresource = tex.getboxresourcedimensions
+
+function codeinjections.registerboxresource(n)
+ return saveboxresource(n,nil,lpdf.collectedresources(),true) -- direct, todo: accept functions as attr/resources
+end
+
+function codeinjections.restoreboxresource(index)
+ local hbox = new_hlist()
+ local list, wd, ht, dp = useboxresource(index)
+ setlist(hbox,tonut(list))
+ setfield(hbox,"width", wd)
+ setfield(hbox,"height", ht)
+ setfield(hbox,"depth", dp)
+ return hbox -- so we return a nut !
+end
+
+function codeinjections.boxresourcedimensions(index)
+ return getboxresource(index)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua
new file mode 100644
index 00000000000..88cdcc4ec51
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua
@@ -0,0 +1,304 @@
+if not modules then modules = { } end modules ['lpdf-swf'] = {
+ 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"
+}
+
+-- The following code is based on tests by Luigi Scarso. His prototype
+-- was using tex code. This is the official implementation.
+
+local format, gsub = string.format, string.gsub
+
+local backends, lpdf = backends, lpdf
+
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfstring = lpdf.string
+local pdfunicode = lpdf.unicode
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfnull = lpdf.null
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+
+local checkedkey = lpdf.checkedkey
+
+local codeinjections = backends.pdf.codeinjections
+local nodeinjections = backends.pdf.nodeinjections
+
+local trace_swf = false trackers.register("backend.swf", function(v) trace_swf = v end)
+
+local report_swf = logs.reporter("backend","swf")
+
+local activations = {
+ click = "XA",
+ page = "PO",
+ focus = "PV",
+}
+
+local deactivations = {
+ click = "XD",
+ page = "PI",
+ focus = "PC",
+}
+
+table.setmetatableindex(activations, function() return activations .click end)
+table.setmetatableindex(deactivations,function() return deactivations.focus end)
+
+local function insertswf(spec)
+
+ local width = spec.width
+ local height = spec.height
+ local filename = spec.foundname
+ local resources = spec.resources
+ local display = spec.display
+ local controls = spec.controls
+
+ local resources = resources and parametersets[resources]
+ local display = display and parametersets[display]
+ local controls = controls and parametersets[controls] -- not yet used
+
+ local preview = checkedkey(display,"preview","string")
+ local toolbar = checkedkey(display,"toolbar","boolean")
+
+ local embeddedreference = codeinjections.embedfile { file = filename }
+
+ local flash = pdfdictionary {
+ Subtype = pdfconstant("Flash"),
+ Instances = pdfarray {
+ pdfdictionary {
+ Asset = embeddedreference,
+ Params = pdfdictionary {
+ Binding = pdfconstant("Background") -- Foreground makes swf behave erratic
+ }
+ },
+ },
+ }
+
+ local flashreference = pdfreference(pdfflushobject(flash))
+
+ local configuration = pdfdictionary {
+ Configurations = pdfarray { flashreference },
+ Assets = pdfdictionary {
+ Names = pdfarray {
+ pdfstring(filename),
+ embeddedreference,
+ }
+ },
+ }
+
+ -- todo: check op subpath figuur (relatief)
+
+ -- filename : ./test.swf (graphic)
+ -- root : .
+ -- prefix : ^%./
+ -- fullname : ./assets/whatever.xml
+ -- usedname : assets/whatever.xml
+ -- filename : assets/whatever.xml
+
+ local root = file.dirname(filename)
+ local relativepaths = nil
+ local paths = nil
+
+ if resources then
+ local names = configuration.Assets.Names
+ local prefix = false
+ if root ~= "" and root ~= "." then
+ prefix = format("^%s/",string.topattern(root))
+ end
+ if prefix and trace_swf then
+ report_swf("using strip pattern %a",prefix)
+ end
+ local function add(fullname,strip)
+ local filename = gsub(fullname,"^%./","")
+ local usedname = strip and prefix and gsub(filename,prefix,"") or filename
+ local embeddedreference = codeinjections.embedfile {
+ file = fullname,
+ usedname = usedname,
+ keepdir = true,
+ }
+ names[#names+1] = pdfstring(filename)
+ names[#names+1] = embeddedreference
+ if trace_swf then
+ report_swf("embedding file %a as %a",fullname,usedname)
+ end
+ end
+ relativepaths = resources.relativepaths
+ if relativepaths then
+ if trace_swf then
+ report_swf("checking %s relative paths",#relativepaths)
+ end
+ for i=1,#relativepaths do
+ local relativepath = relativepaths[i]
+ if trace_swf then
+ report_swf("checking path %a relative to %a",relativepath,root)
+ end
+ local path = file.join(root == "" and "." or root,relativepath)
+ local files = dir.glob(path .. "/**")
+ for i=1,#files do
+ add(files[i],true)
+ end
+ end
+ end
+ paths = resources.paths
+ if paths then
+ if trace_swf then
+ report_swf("checking absolute %s paths",#paths)
+ end
+ for i=1,#paths do
+ local path = paths[i]
+ if trace_swf then
+ report_swf("checking path %a",path)
+ end
+ local files = dir.glob(path .. "/**")
+ for i=1,#files do
+ add(files[i],false)
+ end
+ end
+ end
+ local relativefiles = resources.relativefiles
+ if relativefiles then
+ if trace_swf then
+ report_swf("checking %s relative files",#relativefiles)
+ end
+ for i=1,#relativefiles do
+ add(relativefiles[i],true)
+ end
+ end
+ local files = resources.files
+ if files then
+ if trace_swf then
+ report_swf("checking absolute %s files",#files)
+ end
+ for i=1,#files do
+ add(files[i],false)
+ end
+ end
+ end
+
+ local opendisplay = display and display.open or false
+ local closedisplay = display and display.close or false
+
+ local configurationreference = pdfreference(pdfflushobject(configuration))
+
+ local activation = pdfdictionary {
+ Type = pdfconstant("RichMediaActivation"),
+ Condition = pdfconstant(activations[opendisplay]),
+ Configuration = flashreference,
+ Animation = pdfdictionary {
+ Subtype = pdfconstant("Linear"),
+ Speed = 1,
+ Playcount = 1,
+ },
+ Presentation = pdfdictionary {
+ PassContextClick = false,
+ Style = pdfconstant("Embedded"),
+ Toolbar = toolbar,
+ NavigationPane = false,
+ Transparent = true,
+ Window = pdfdictionary {
+ Type = pdfconstant("RichMediaWindow"),
+ Width = pdfdictionary {
+ Default = 100,
+ Min = 100,
+ Max = 100,
+ },
+ Height = pdfdictionary {
+ Default = 100,
+ Min = 100,
+ Max = 100,
+ },
+ Position = pdfdictionary {
+ Type = pdfconstant("RichMediaPosition"),
+ HAlign = pdfconstant("Near"),
+ VAlign = pdfconstant("Near"),
+ HOffset = 0,
+ VOffset = 0,
+ }
+ }
+ },
+ -- View
+ -- Scripts
+ }
+
+ local deactivation = pdfdictionary {
+ Type = pdfconstant("RichMediaDeactivation"),
+ Condition = pdfconstant(deactivations[closedisplay]),
+ }
+
+ local richmediasettings = pdfdictionary {
+ Type = pdfconstant("RichMediaSettings"),
+ Activation = activation,
+ Deactivation = deactivation,
+ }
+
+ local settingsreference = pdfreference(pdfflushobject(richmediasettings))
+
+ local appearance
+
+ if preview then
+ preview = gsub(preview,"%*",file.nameonly(filename))
+ local figure = codeinjections.getpreviewfigure { name = preview, width = width, height = height }
+ if relativepaths and not figure then
+ for i=1,#relativepaths do
+ local path = file.join(root == "" and "." or root,relativepaths[i])
+ if trace_swf then
+ report_swf("checking preview on relative path %s",path)
+ end
+ local p = file.join(path,preview)
+ figure = codeinjections.getpreviewfigure { name = p, width = width, height = height }
+ if figure then
+ preview = p
+ break
+ end
+ end
+ end
+ if paths and not figure then
+ for i=1,#paths do
+ local path = paths[i]
+ if trace_swf then
+ report_swf("checking preview on absolute path %s",path)
+ end
+ local p = file.join(path,preview)
+ figure = codeinjections.getpreviewfigure { name = p, width = width, height = height }
+ if figure then
+ preview = p
+ break
+ end
+ end
+ end
+ if figure then
+ local image = img.package(figure.status.private)
+ appearance = pdfdictionary { N = pdfreference(image.objnum) }
+ if trace_swf then
+ report_swf("using preview %s",preview)
+ end
+ end
+ end
+
+ local annotation = pdfdictionary {
+ Subtype = pdfconstant("RichMedia"),
+ RichMediaContent = configurationreference,
+ RichMediaSettings = settingsreference,
+ AP = appearance,
+ }
+
+ return annotation, nil, nil
+
+end
+
+function backends.pdf.nodeinjections.insertswf(spec)
+ local annotation, preview, ref = insertswf {
+ foundname = spec.foundname,
+ width = spec.width,
+ height = spec.height,
+ display = spec.display,
+ controls = spec.controls,
+ resources = spec.resources,
+ -- factor = spec.factor,
+ -- label = spec.label,
+ }
+ context(nodeinjections.annotation(spec.width,spec.height,0,annotation())) -- the context wrap is probably also needed elsewhere
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua
new file mode 100644
index 00000000000..79b8ac36877
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua
@@ -0,0 +1,617 @@
+if not modules then modules = { } end modules ['lpdf-tag'] = {
+ version = 1.001,
+ comment = "companion to lpdf-tag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+local format, match, concat = string.format, string.match, table.concat
+local lpegmatch, P, S, C = lpeg.match, lpeg.P, lpeg.S, lpeg.C
+local utfchar = utf.char
+local settings_to_hash = utilities.parsers.settings_to_hash
+local formatters = string.formatters
+
+local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end)
+
+local report_tags = logs.reporter("backend","tags")
+
+local backends = backends
+local lpdf = lpdf
+local nodes = nodes
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+
+local tasks = nodes.tasks
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfboolean = lpdf.boolean
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfpagereference = lpdf.pagereference
+
+local addtocatalog = lpdf.addtocatalog
+local addtopageattributes = lpdf.addtopageattributes
+
+local texgetcount = tex.getcount
+
+local nodecodes = nodes.nodecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+
+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 pdfliteral = nodepool.pdfliteral
+
+local getid = nuts.getid
+local getattr = nuts.getattr
+local getprev = nuts.getprev
+local getnext = nuts.getnext
+local getlist = nuts.getlist
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+
+local traverse_nodes = nuts.traverse
+local tosequence = nuts.tosequence
+local slide_nodelist = nuts.slide
+local insert_before = nuts.insert_before
+local insert_after = nuts.insert_after
+
+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 tree = { }
+local elements = { }
+local names = pdfarray()
+
+local structurestags = structures.tags
+local taglist = structurestags.taglist
+local specifications = structurestags.specifications
+local usedlabels = structurestags.labels
+local properties = structurestags.properties
+local lasttaginchain = structurestags.lastinchain
+local usewithcare = structurestags.usewithcare
+
+local usedmapping = { }
+
+----- tagsplitter = structurestags.patterns.splitter
+
+-- local embeddedtags = false -- true will id all, for tracing
+-- local f_tagid = formatters["%s-%04i"]
+-- local embeddedfilelist = pdfarray() -- /AF crap
+--
+-- directives.register("structures.tags.embedmath",function(v)
+-- if not v then
+-- -- only enable
+-- elseif embeddedtags == true then
+-- -- already all tagged
+-- elseif embeddedtags then
+-- embeddedtags.math = true
+-- else
+-- embeddedtags = { math = true }
+-- end
+-- end)
+
+-- function codeinjections.maptag(original,target,kind)
+-- mapping[original] = { target, kind or "inline" }
+-- end
+
+local function finishstructure()
+ if #structure_kids > 0 then
+ local nums, n = pdfarray(), 0
+ for i=1,#tree do
+ n = n + 1 ; nums[n] = i - 1
+ n = n + 1 ; nums[n] = pdfreference(pdfflushobject(tree[i]))
+ end
+ local parenttree = pdfdictionary {
+ Nums = nums
+ }
+ -- we need to split names into smaller parts (e.g. alphabetic or so)
+ -- we already have code for that somewhere
+ if #names > 0 then
+ local kids = pdfdictionary {
+ Limits = pdfarray { names[1], names[#names-1] },
+ Names = names,
+ }
+ local idtree = pdfdictionary {
+ Kids = pdfarray { pdfreference(pdfflushobject(kids)) },
+ }
+ end
+ --
+ local rolemap = pdfdictionary()
+ for k, v in next, usedmapping do
+ k = usedlabels[k] or k
+ local p = properties[k]
+ rolemap[k] = pdfconstant(p and p.pdf or "Span") -- or "Div"
+ end
+ local structuretree = pdfdictionary {
+ Type = pdfconstant("StructTreeRoot"),
+ K = pdfreference(pdfflushobject(structure_kids)),
+ ParentTree = pdfreference(pdfflushobject(parent_ref,parenttree)),
+ IDTree = #names > 0 and pdfreference(pdfflushobject(idtree)) or nil,
+ RoleMap = rolemap,
+ }
+ pdfflushobject(structure_ref,structuretree)
+ addtocatalog("StructTreeRoot",pdfreference(structure_ref))
+ --
+ local markinfo = pdfdictionary {
+ Marked = pdfboolean(true),
+ -- UserProperties = pdfboolean(true),
+ -- Suspects = pdfboolean(true),
+ -- AF = #embeddedfilelist > 0 and pdfreference(pdfflushobject(embeddedfilelist)) or nil,
+ }
+ addtocatalog("MarkInfo",pdfreference(pdfflushobject(markinfo)))
+ --
+ for fulltag, element in next, elements do
+ pdfflushobject(element.knum,element.kids)
+ end
+ end
+end
+
+lpdf.registerdocumentfinalizer(finishstructure,"document structure")
+
+local index, pageref, pagenum, list = 0, nil, 0, nil
+
+local pdf_mcr = pdfconstant("MCR")
+local pdf_struct_element = pdfconstant("StructElem")
+
+local function initializepage()
+ index = 0
+ pagenum = texgetcount("realpageno")
+ pageref = pdfreference(pdfpagereference(pagenum))
+ list = pdfarray()
+ tree[pagenum] = list -- we can flush after done, todo
+end
+
+local function finishpage()
+ -- flush what can be flushed
+ addtopageattributes("StructParents",pagenum-1)
+end
+
+-- here we can flush and free elements that are finished
+
+local pdf_userproperties = pdfconstant("UserProperties")
+
+local function makeattribute(t)
+ if t and next(t) then
+ local properties = pdfarray()
+ for k, v in next, t do
+ properties[#properties+1] = pdfdictionary {
+ N = pdfunicode(k),
+ V = pdfunicode(v),
+ }
+ end
+ return pdfdictionary {
+ O = pdf_userproperties,
+ P = properties,
+ }
+ end
+end
+
+local function makeelement(fulltag,parent)
+ local specification = specifications[fulltag]
+ local tag = specification.tagname
+ if tag == "ignore" then
+ return false
+ elseif tag == "mstackertop" or tag == "mstackerbot" or tag == "mstackermid"then
+ -- TODO
+ return true
+ end
+ --
+ local detail = specification.detail
+ local userdata = specification.userdata
+ --
+ usedmapping[tag] = true
+ --
+ -- specification.attribute is unique
+ --
+ local id = nil
+ -- local af = nil
+ -- if embeddedtags then
+ -- local tagname = specification.tagname
+ -- local tagindex = specification.tagindex
+ -- if embeddedtags == true or embeddedtags[tagname] then
+ -- id = f_tagid(tagname,tagindex)
+ -- af = job.fileobjreferences.collected[id]
+ -- if af then
+ -- local r = pdfreference(af)
+ -- af = pdfarray { r }
+ -- -- embeddedfilelist[#embeddedfilelist+1] = r
+ -- end
+ -- end
+ -- end
+ --
+ local k = pdfarray()
+ local r = pdfreserveobject()
+ local t = usedlabels[tag] or tag
+ local d = pdfdictionary {
+ Type = pdf_struct_element,
+ S = pdfconstant(t),
+ ID = id,
+ T = detail and detail or nil,
+ P = parent.pref,
+ Pg = pageref,
+ K = pdfreference(r),
+ A = a and makeattribute(a) or nil,
+ -- Alt = " Who cares ",
+ -- ActualText = " Hi Hans ",
+ AF = af,
+ }
+ local s = pdfreference(pdfflushobject(d))
+ if id then
+ names[#names+1] = id
+ names[#names+1] = s
+ end
+ local kids = parent.kids
+ kids[#kids+1] = s
+ local e = {
+ tag = t,
+ pref = s,
+ kids = k,
+ knum = r,
+ pnum = pagenum
+ }
+ elements[fulltag] = e
+ return e
+end
+
+local f_BDC = formatters["/%s <</MCID %s>> BDC"]
+
+local function makecontent(parent,id,specification)
+ local tag = parent.tag
+ local kids = parent.kids
+ local last = index
+ if id == "image" then
+ local list = specification.taglist
+ local data = usewithcare.images[list[#list]]
+ local label = data and data.label
+ local d = pdfdictionary {
+ Type = pdf_mcr,
+ Pg = pageref,
+ MCID = last,
+ Alt = pdfunicode(label ~= "" and label or "image"),
+ }
+ kids[#kids+1] = d
+ elseif pagenum == parent.pnum then
+ kids[#kids+1] = last
+ else
+ local d = pdfdictionary {
+ Type = pdf_mcr,
+ Pg = pageref,
+ MCID = last,
+ }
+ -- kids[#kids+1] = pdfreference(pdfflushobject(d))
+ kids[#kids+1] = d
+ end
+ --
+ index = index + 1
+ list[index] = parent.pref -- page related list
+ --
+ return f_BDC(tag,last)
+end
+
+local function makeignore(specification)
+ return "/Artifact BMC"
+end
+
+-- no need to adapt head, as we always operate on lists
+
+function nodeinjections.addtags(head)
+
+ local last = nil
+ local ranges = { }
+ local range = nil
+ local head = tonut(head)
+
+ local function collectranges(head,list)
+ for n in traverse_nodes(head) do
+ local id = getid(n) -- 14: image, 8: literal (mp)
+ if id == glyph_code then
+ local at = getattr(n,a_tagged)
+ if not at then
+ range = nil
+ elseif last ~= at then
+ range = { at, "glyph", n, n, list } -- attr id start stop list
+ ranges[#ranges+1] = range
+ last = at
+ elseif range then
+ range[4] = n -- stop
+ end
+ 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
+ ranges[#ranges+1] = { at, "image", n, n, list } -- attr id start stop list
+ end
+ last = nil
+ else
+ local nl = getlist(n)
+ -- slide_nodelist(nl) -- temporary hack till math gets slided (tracker item)
+ collectranges(nl,n)
+ end
+ end
+ end
+ end
+
+ initializepage()
+
+ collectranges(head)
+
+ if trace_tags then
+ 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 tags = taglist[attr]
+ if tags then -- not ok ... only first lines
+ report_tags("%s => %s : %05i % t",tosequence(start,start),tosequence(stop,stop),attr,tags.taglist)
+ end
+ end
+ end
+
+ local top = nil
+ local noftop = 0
+
+ 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
+ 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
+ end
+ end
+
+ if prev then
+ literal = pdfliteral(makecontent(prev,id,specification))
+ elseif ignore then
+ literal = pdfliteral(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)
+ end
+ -- use insert instead:
+ local literal = pdfliteral("EMC")
+ local next = getnext(stop)
+ if next then
+ setlink(literal,next)
+ end
+ setlink(stop,literal)
+ end
+ top = taglist
+ noftop = noftags
+ end
+
+ finishpage()
+
+ head = tonode(head)
+ return head, true
+
+end
+
+-- variant: more structure but funny collapsing in viewer
+
+-- function nodeinjections.addtags(head)
+--
+-- 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)
+-- if id == glyph_code then
+-- local at = getattr(n,a_tagged)
+-- if not at then
+-- range = nil
+-- elseif last ~= at then
+-- range = { at, "glyph", n, n, list } -- attr id start stop list
+-- ranges[#ranges+1] = range
+-- last = at
+-- elseif range then
+-- range[4] = n -- stop
+-- end
+-- 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
+-- ranges[#ranges+1] = { at, "image", n, n, list } -- attr id start stop list
+-- end
+-- last = nil
+-- else
+-- local nl = getlist(n)
+-- -- slide_nodelist(nl) -- temporary hack till math gets slided (tracker item)
+-- collectranges(nl,n)
+-- end
+-- end
+-- end
+-- end
+--
+-- initializepage()
+--
+-- head = tonut(head)
+-- collectranges(head)
+--
+-- if trace_tags then
+-- 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 tags = taglist[attr]
+-- if tags then -- not ok ... only first lines
+-- report_tags("%s => %s : %05i % t",tosequence(start,start),tosequence(stop,stop),attr,tags.taglist)
+-- end
+-- end
+-- end
+--
+-- local top = nil
+-- local noftop = 0
+-- local last = nil
+--
+-- 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 tag = nil
+-- local common = 0
+-- -- local prev = root
+--
+-- 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
+--
+-- local result = { }
+-- local r = noftop - common
+-- if r > 0 then
+-- for i=1,r do
+-- result[i] = "EMC"
+-- end
+-- end
+--
+-- 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
+-- -- break
+-- -- elseif prv == true then
+-- -- -- skip this one
+-- -- else
+-- prev = prv
+-- r = r + 1
+-- result[r] = makecontent(prev,id)
+-- -- end
+-- end
+--
+-- if r > 0 then
+-- local literal = pdfliteral(concat(result,"\n"))
+-- -- use insert instead:
+-- local literal = pdfliteral(result)
+-- local prev = getprev(start)
+-- if prev then
+-- setlink(prev,literal)
+-- end
+-- setlink(literal,start)
+-- if list and getlist(list) == start then
+-- setlist(list,literal)
+-- end
+-- end
+--
+-- top = taglist
+-- noftop = noftags
+-- last = stop
+--
+-- end
+--
+-- if last and noftop > 0 then
+-- local result = { }
+-- for i=1,noftop do
+-- result[i] = "EMC"
+-- end
+-- local literal = pdfliteral(concat(result,"\n"))
+-- -- use insert instead:
+-- local next = getnext(last)
+-- if next then
+-- setlink(literal,next)
+-- end
+-- setlink(last,literal)
+-- end
+--
+-- finishpage()
+--
+-- head = tonode(head)
+-- return head, true
+--
+-- end
+
+-- this belongs elsewhere (export is not pdf related)
+
+function codeinjections.enabletags(tg,lb)
+ structures.tags.handler = nodeinjections.addtags
+ tasks.enableaction("shipouts","structures.tags.handler")
+ tasks.enableaction("shipouts","nodes.handlers.accessibility")
+ tasks.enableaction("math","noads.handlers.tags")
+ -- maybe also textblock
+ if trace_tags then
+ report_tags("enabling structure tags")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua
new file mode 100644
index 00000000000..c9f4a03691e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua
@@ -0,0 +1,487 @@
+if not modules then modules = { } end modules ['lpdf-u3d'] = {
+ 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"
+}
+
+-- The following code is based on a working prototype provided
+-- by Michael Vidiassov. It is rewritten using the lpdf library
+-- and different checking is used. The macro calls are adapted
+-- (and will eventually be removed). The user interface needs
+-- an overhaul. There are some messy leftovers that will be
+-- removed in future versions.
+
+-- For some reason no one really tested this code so at some
+-- point we will end up with a reimplementation. For instance
+-- it makes sense to add the same activation code as with swf.
+
+local tonumber = tonumber
+local formatters, find = string.formatters, string.find
+local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, math.atan2, math.abs
+
+local backends, lpdf = backends, lpdf
+
+local nodeinjections = backends.pdf.nodeinjections
+
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfnumber = lpdf.number
+local pdfunicode = lpdf.unicode
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfnull = lpdf.null
+local pdfreference = lpdf.reference
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
+
+local checkedkey = lpdf.checkedkey
+local limited = lpdf.limited
+
+local schemes = table.tohash {
+ "Artwork", "None", "White", "Day", "Night", "Hard",
+ "Primary", "Blue", "Red", "Cube", "CAD", "Headlamp",
+}
+
+local modes = table.tohash {
+ "Solid", "SolidWireframe", "Transparent", "TransparentWireframe", "BoundingBox",
+ "TransparentBoundingBox", "TransparentBoundingBoxOutline", "Wireframe",
+ "ShadedWireframe", "HiddenWireframe", "Vertices", "ShadedVertices", "Illustration",
+ "SolidOutline", "ShadedIllustration",
+}
+
+local function normalize(x, y, z)
+ local modulo = sqrt(x*x + y*y + z*z);
+ if modulo ~= 0 then
+ return x/modulo, y/modulo, z/modulo
+ else
+ return x, y, z
+ end
+end
+
+local function rotate(vect_x,vect_y,vect_z, tet, axis_x,axis_y,axis_z)
+ -- rotate vect by tet about axis counterclockwise
+ local c, s = cos(tet*pi/180), sin(tet*pi/180)
+ local r = 1 - c
+ local n = sqrt(axis_x*axis_x+axis_y*axis_y+axis_z*axis_z)
+ axis_x, axis_y, axis_z = axis_x/n, axis_y/n, axis_z/n
+ return
+ (axis_x*axis_x*r+c )*vect_x + (axis_x*axis_y*r-axis_z*s)*vect_y + (axis_x*axis_z*r+axis_y*s)*vect_z,
+ (axis_x*axis_y*r+axis_z*s)*vect_x + (axis_y*axis_y*r+c )*vect_y + (axis_y*axis_z*r-axis_x*s)*vect_z,
+ (axis_x*axis_z*r-axis_y*s)*vect_x + (axis_y*axis_z*r+axis_x*s)*vect_y + (axis_z*axis_z*r+c )*vect_z
+end
+
+local function make3dview(view)
+
+ local name = view.name
+ local name = pdfunicode(name ~= "" and name or "unknown view")
+
+ local viewdict = pdfdictionary {
+ Type = pdfconstant("3DView"),
+ XN = name,
+ IN = name,
+ NR = true,
+ }
+
+ local bg = checkedkey(view,"bg","table")
+ if bg then
+ viewdict.BG = pdfdictionary {
+ Type = pdfconstant("3DBG"),
+ C = pdfarray { limited(bg[1],1,1,1), limited(bg[2],1,1,1), limited(bg[3],1,1,1) },
+ }
+ end
+
+ local lights = checkedkey(view,"lights","string")
+ if lights and schemes[lights] then
+ viewdict.LS = pdfdictionary {
+ Type = pdfconstant("3DLightingScheme"),
+ Subtype = pdfconstant(lights),
+ }
+ end
+
+ -- camera position is taken from 3d model
+
+ local u3dview = checkedkey(view, "u3dview", "string")
+ if u3dview then
+ viewdict.MS = pdfconstant("U3D")
+ viewdict.U3DPath = u3dview
+ end
+
+ -- position the camera as given
+
+ local c2c = checkedkey(view, "c2c", "table")
+ local coo = checkedkey(view, "coo", "table")
+ local roo = checkedkey(view, "roo", "number")
+ local azimuth = checkedkey(view, "azimuth", "number")
+ local altitude = checkedkey(view, "altitude", "number")
+
+ if c2c or coo or roo or azimuth or altitude then
+
+ local pos = checkedkey(view, "pos", "table")
+ local dir = checkedkey(view, "dir", "table")
+ local upv = checkedkey(view, "upv", "table")
+ local roll = checkedkey(view, "roll", "table")
+
+ local coo_x, coo_y, coo_z = 0, 0, 0
+ local dir_x, dir_y, dir_z = 0, 0, 0
+ local trans_x, trans_y, trans_z = 0, 0, 0
+ local left_x, left_y, left_z = 0, 0, 0
+ local up_x, up_y, up_z = 0, 0, 0
+
+ -- point camera is aimed at
+
+ if coo then
+ coo_x, coo_y, coo_z = tonumber(coo[1]) or 0, tonumber(coo[2]) or 0, tonumber(coo[3]) or 0
+ end
+
+ -- distance from camera to target
+
+ if roo then
+ roo = abs(roo)
+ end
+ if not roo or roo == 0 then
+ roo = 0.000000000000000001
+ end
+
+ -- set it via camera position
+
+ if pos then
+ dir_x = coo_x - (tonumber(pos[1]) or 0)
+ dir_y = coo_y - (tonumber(pos[2]) or 0)
+ dir_z = coo_z - (tonumber(pos[3]) or 0)
+ if not roo then
+ roo = sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z)
+ end
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it directly
+
+ if dir then
+ dir_x, dir_y, dir_z = tonumber(dir[1] or 0), tonumber(dir[2] or 0), tonumber(dir[3] or 0)
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it movie15 style with vector from target to camera
+
+ if c2c then
+ dir_x, dir_y, dir_z = - tonumber(c2c[1] or 0), - tonumber(c2c[2] or 0), - tonumber(c2c[3] or 0)
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it with azimuth and altitutde
+
+ if altitude or azimuth then
+ dir_x, dir_y, dir_z = -1, 0, 0
+ if altitude then dir_x, dir_y, dir_z = rotate(dir_x,dir_y,dir_z, -altitude, 0,1,0) end
+ if azimuth then dir_x, dir_y, dir_z = rotate(dir_x,dir_y,dir_z, azimuth, 0,0,1) end
+ end
+
+ -- set it with rotation like in MathGL
+
+ if rot then
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_z = -1 end
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[1]) or 0, 1,0,0)
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[2]) or 0, 0,1,0)
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[3]) or 0, 0,0,1)
+ end
+
+ -- set it with default movie15 orientation looking up y axis
+
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+
+ -- left-vector
+ -- up-vector
+
+ if upv then
+ up_x, up_y, up_z = tonumber(upv[1]) or 0, tonumber(upv[2]) or 0, tonumber(upv[3]) or 0
+ else
+ -- set default up-vector
+ if abs(dir_x) == 0 and abs(dir_y) == 0 then
+ if dir_z < 0 then
+ up_y = 1 -- top view
+ else
+ up_y = -1 -- bottom view
+ end
+ else
+ -- other camera positions than top and bottom, up-vector = up_world - (up_world dot dir) dir
+ up_x, up_y, up_z = - dir_z*dir_x, - dir_z*dir_y, - dir_z*dir_z + 1
+ end
+ end
+
+ -- normalize up-vector
+
+ up_x, up_y, up_z = normalize(up_x,up_y,up_z)
+
+ -- left vector = up x dir
+
+ left_x, left_y, left_z = dir_z*up_y - dir_y*up_z, dir_x*up_z - dir_z*up_x, dir_y*up_x - dir_x*up_y
+
+ -- normalize left vector
+
+ left_x, left_y, left_z = normalize(left_x,left_y,left_z)
+
+ -- apply camera roll
+
+ if roll then
+ local sinroll = sin((roll/180.0)*pi)
+ local cosroll = cos((roll/180.0)*pi)
+ left_x = left_x*cosroll + up_x*sinroll
+ left_y = left_y*cosroll + up_y*sinroll
+ left_z = left_z*cosroll + up_z*sinroll
+ up_x = up_x*cosroll + left_x*sinroll
+ up_y = up_y*cosroll + left_y*sinroll
+ up_z = up_z*cosroll + left_z*sinroll
+ end
+
+ -- translation vector
+
+ trans_x, trans_y, trans_z = coo_x - roo*dir_x, coo_y - roo*dir_y, coo_z - roo*dir_z
+
+ viewdict.MS = pdfconstant("M")
+ viewdict.CO = roo
+ viewdict.C2W = pdfarray {
+ left_x, left_y, left_z,
+ up_x, up_y, up_z,
+ dir_x, dir_y, dir_z,
+ trans_x, trans_y, trans_z,
+ }
+
+ end
+
+ local aac = tonumber(view.aac) -- perspective projection
+ local mag = tonumber(view.mag) -- ortho projection
+
+ if aac and aac > 0 and aac < 180 then
+ viewdict.P = pdfdictionary {
+ Subtype = pdfconstant("P"),
+ PS = pdfconstant("Min"),
+ FOV = aac,
+ }
+ elseif mag and mag > 0 then
+ viewdict.P = pdfdictionary {
+ Subtype = pdfconstant("O"),
+ OS = mag,
+ }
+ end
+
+ local mode = modes[view.rendermode]
+ if mode then
+ pdfdictionary {
+ Type = pdfconstant("3DRenderMode"),
+ Subtype = pdfconstant(mode),
+ }
+ end
+
+ -- crosssection
+
+ local crosssection = checkedkey(view,"crosssection","table")
+ if crosssection then
+ local crossdict = pdfdictionary {
+ Type = pdfconstant("3DCrossSection")
+ }
+
+ local c = checkedkey(crosssection,"point","table") or checkedkey(crosssection,"center","table")
+ if c then
+ crossdict.C = pdfarray { tonumber(c[1]) or 0, tonumber(c[2]) or 0, tonumber(c[3]) or 0 }
+ end
+
+ local normal = checkedkey(crosssection,"normal","table")
+ if normal then
+ local x, y, z = tonumber(normal[1] or 0), tonumber(normal[2] or 0), tonumber(normal[3] or 0)
+ if sqrt(x*x + y*y + z*z) == 0 then
+ x, y, z = 1, 0, 0
+ end
+ crossdict.O = pdfarray {
+ pdfnull,
+ atan2(-z,sqrt(x*x + y*y))*180/pi,
+ atan2(y,x)*180/pi,
+ }
+ end
+
+ local orient = checkedkey(crosssection,"orient","table")
+ if orient then
+ crossdict.O = pdfarray {
+ tonumber(orient[1]) or 1,
+ tonumber(orient[2]) or 0,
+ tonumber(orient[3]) or 0,
+ }
+ end
+
+ crossdict.IV = cross.intersection or false
+ crossdict.ST = cross.transparent or false
+
+ viewdict.SA = next(crossdict) and pdfarray { crossdict } -- maybe test if # > 1
+ end
+
+ local nodes = checkedkey(view,"nodes","table")
+ if nodes then
+ local nodelist = pdfarray()
+ for i=1,#nodes do
+ local node = checkedkey(nodes,i,"table")
+ if node then
+ local position = checkedkey(node,"position","table")
+ nodelist[#nodelist+1] = pdfdictionary {
+ Type = pdfconstant("3DNode"),
+ N = node.name or ("node_" .. i), -- pdfunicode ?
+ M = position and #position == 12 and pdfarray(position),
+ V = node.visible or true,
+ O = node.opacity or 0,
+ RM = pdfdictionary {
+ Type = pdfconstant("3DRenderMode"),
+ Subtype = pdfconstant(node.rendermode or "Solid"),
+ },
+ }
+ end
+ end
+ viewdict.NA = nodelist
+ end
+
+ return viewdict
+
+end
+
+local stored_js, stored_3d, stored_pr, streams = { }, { }, { }, { }
+
+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
+ local display, controls, label, foundname = spec.display, spec.controls, spec.label, spec.foundname
+
+ local param = (display and parametersets[display]) or { }
+ local streamparam = (controls and parametersets[controls]) or { }
+ local name = "3D Artwork " .. (param.name or label or "Unknown")
+
+ local activationdict = pdfdictionary {
+ TB = pdfboolean(param.toolbar,true),
+ NP = pdfboolean(param.tree,false),
+ }
+
+ local stream = streams[label]
+ if not stream then
+
+ local subtype, subdata = "U3D", io.loaddata(foundname) or ""
+ if find(subdata,"^PRC") then
+ subtype = "PRC"
+ elseif find(subdata,"^U3D") then
+ subtype = "U3D"
+ elseif file.suffix(foundname) == "prc" then
+ subtype = "PRC"
+ end
+
+ local attr = pdfdictionary {
+ Type = pdfconstant("3D"),
+ Subtype = pdfconstant(subtype),
+ }
+ local streamviews = checkedkey(streamparam, "views", "table")
+ if streamviews then
+ local list = pdfarray()
+ for i=1,#streamviews do
+ local v = checkedkey(streamviews, i, "table")
+ if v then
+ list[#list+1] = make3dview(v)
+ end
+ end
+ attr.VA = list
+ end
+ if checkedkey(streamparam, "view", "table") then
+ attr.DV = make3dview(streamparam.view)
+ elseif checkedkey(streamparam, "view", "string") then
+ attr.DV = streamparam.view
+ end
+ local js = checkedkey(streamparam, "js", "string")
+ if js then
+ local jsref = stored_js[js]
+ if not jsref then
+ jsref = pdfflushstreamfileobject(js)
+ stored_js[js] = jsref
+ end
+ attr.OnInstantiate = pdfreference(jsref)
+ end
+ stored_3d[label] = pdfflushstreamfileobject(foundname,attr)
+ stream = 1
+ else
+ stream = stream + 1
+ end
+ streams[label] = stream
+
+ local name = pdfunicode(name)
+
+ local annot = pdfdictionary {
+ Subtype = pdfconstant("3D"),
+ T = name,
+ Contents = name,
+ NM = name,
+ ["3DD"] = pdfreference(stored_3d[label]),
+ ["3DA"] = activationdict,
+ }
+ if checkedkey(param,"view","table") then
+ annot["3DV"] = make3dview(param.view)
+ elseif checkedkey(param,"view","string") then
+ annot["3DV"] = param.view
+ end
+
+ local preview = checkedkey(param,"preview","string")
+ if preview then
+ activationdict.A = pdfconstant("XA")
+ local tag = formatters["%s:%s:%s"](label,stream,preview)
+ local ref = stored_pr[tag]
+ if not ref then
+ local figure = img.immediatewrite {
+ filename = preview,
+ width = width,
+ height = height
+ }
+ ref = figure.objnum
+ 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 },
+ Resources = pdfdictionary {
+ XObject = pdfdictionary {
+ IM = pdfreference(ref)
+ }
+ },
+ ExtGState = pdfdictionary {
+ GS = pdfdictionary {
+ Type = pdfconstant("ExtGState"),
+ CA = one,
+ ca = one,
+ }
+ },
+ ProcSet = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
+ }
+ local pwd = pdfflushstreamobject(formatters["q /GS gs %F 0 0 %F 0 0 cm /IM Do Q"](factor*width,factor*height),pw)
+ annot.AP = pdfdictionary {
+ N = pdfreference(pwd)
+ }
+ end
+ return annot, figure, ref
+ else
+ activationdict.A = pdfconstant("PV")
+ return annot, nil, nil
+ end
+end
+
+function nodeinjections.insertu3d(spec)
+ local annotation, preview, ref = insert3d { -- just spec
+ foundname = spec.foundname,
+ width = spec.width,
+ height = spec.height,
+ factor = spec.factor,
+ display = spec.display,
+ controls = spec.controls,
+ label = spec.label,
+ }
+ node.write(nodeinjections.annotation(spec.width,spec.height,0,annotation()))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua
new file mode 100644
index 00000000000..73a56caa327
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua
@@ -0,0 +1,682 @@
+if not modules then modules = { } end modules ['lpdf-wid'] = {
+ 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 gmatch, gsub, find, lower, format = string.gmatch, string.gsub, string.find, string.lower, string.format
+local stripstring = string.strip
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local report_media = logs.reporter("backend","media")
+local report_attachment = logs.reporter("backend","attachment")
+
+local backends = backends
+local lpdf = lpdf
+local nodes = nodes
+local context = context
+
+local texgetcount = tex.getcount
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local executers = structures.references.executers
+local variables = interfaces.variables
+
+local v_hidden = variables.hidden
+local v_normal = variables.normal
+local v_auto = variables.auto
+local v_embed = variables.embed
+local v_unknown = variables.unknown
+local v_max = variables.max
+
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfboolean = lpdf.boolean
+local pdfcolorspec = lpdf.colorspec
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfpagereference = lpdf.pagereference
+local pdfshareobjectreference = lpdf.shareobjectreference
+local pdfaction = lpdf.action
+local pdfborder = lpdf.border
+
+local pdftransparencyvalue = lpdf.transparencyvalue
+local pdfcolorvalues = lpdf.colorvalues
+
+local hpack_node = node.hpack
+local write_node = node.write -- test context(...) instead
+
+-- symbols
+
+local presets = { } -- xforms
+
+local function registersymbol(name,n)
+ presets[name] = pdfreference(n)
+end
+
+local function registeredsymbol(name)
+ return presets[name]
+end
+
+local function presetsymbol(symbol)
+ if not presets[symbol] then
+ context.predefinesymbol { symbol }
+ end
+end
+
+local function presetsymbollist(list)
+ if list then
+ for symbol in gmatch(list,"[^, ]+") do
+ presetsymbol(symbol)
+ end
+ end
+end
+
+codeinjections.registersymbol = registersymbol
+codeinjections.registeredsymbol = registeredsymbol
+codeinjections.presetsymbol = presetsymbol
+codeinjections.presetsymbollist = presetsymbollist
+
+-- comments
+
+-- local symbols = {
+-- Addition = pdfconstant("NewParagraph"),
+-- Attachment = pdfconstant("Attachment"),
+-- Balloon = pdfconstant("Comment"),
+-- Check = pdfconstant("Check Mark"),
+-- CheckMark = pdfconstant("Check Mark"),
+-- Circle = pdfconstant("Circle"),
+-- Cross = pdfconstant("Cross"),
+-- CrossHairs = pdfconstant("Cross Hairs"),
+-- Graph = pdfconstant("Graph"),
+-- InsertText = pdfconstant("Insert Text"),
+-- New = pdfconstant("Insert"),
+-- Paperclip = pdfconstant("Paperclip"),
+-- RightArrow = pdfconstant("Right Arrow"),
+-- RightPointer = pdfconstant("Right Pointer"),
+-- Star = pdfconstant("Star"),
+-- Tag = pdfconstant("Tag"),
+-- Text = pdfconstant("Note"),
+-- TextNote = pdfconstant("Text Note"),
+-- UpArrow = pdfconstant("Up Arrow"),
+-- UpLeftArrow = pdfconstant("Up-Left Arrow"),
+-- }
+
+local attachment_symbols = {
+ Graph = pdfconstant("Graph"),
+ Paperclip = pdfconstant("Paperclip"),
+ Pushpin = pdfconstant("PushPin"),
+}
+
+attachment_symbols.PushPin = attachment_symbols.Pushpin
+attachment_symbols.Default = attachment_symbols.Pushpin
+
+local comment_symbols = {
+ Comment = pdfconstant("Comment"),
+ Help = pdfconstant("Help"),
+ Insert = pdfconstant("Insert"),
+ Key = pdfconstant("Key"),
+ Newparagraph = pdfconstant("NewParagraph"),
+ Note = pdfconstant("Note"),
+ Paragraph = pdfconstant("Paragraph"),
+}
+
+comment_symbols.NewParagraph = Newparagraph
+comment_symbols.Default = Note
+
+local function analyzesymbol(symbol,collection)
+ if not symbol or symbol == "" then
+ return collection.Default, nil
+ elseif collection[symbol] then
+ return collection[symbol], nil
+ else
+ local setn, setr, setd
+ local set = settings_to_array(symbol)
+ if #set == 1 then
+ setn, setr, setd = set[1], set[1], set[1]
+ elseif #set == 2 then
+ setn, setr, setd = set[1], set[1], set[2]
+ else
+ setn, setr, setd = set[1], set[2], set[3]
+ end
+ local appearance = pdfdictionary {
+ N = setn and registeredsymbol(setn),
+ R = setr and registeredsymbol(setr),
+ D = setd and registeredsymbol(setd),
+ }
+ local appearanceref = pdfshareobjectreference(appearance)
+ return nil, appearanceref
+ end
+end
+
+local function analyzelayer(layer)
+ -- todo: (specification.layer ~= "" and pdfreference(specification.layer)) or nil, -- todo: ref to layer
+end
+
+local function analyzecolor(colorvalue,colormodel)
+ local cvalue = colorvalue and tonumber(colorvalue)
+ local cmodel = colormodel and tonumber(colormodel) or 3
+ return cvalue and pdfarray { pdfcolorvalues(cmodel,cvalue) } or nil
+end
+
+local function analyzetransparency(transparencyvalue)
+ local tvalue = transparencyvalue and tonumber(transparencyvalue)
+ return tvalue and pdftransparencyvalue(tvalue) or nil
+end
+
+-- Attachments
+
+local nofattachments = 0
+local attachments = { }
+local filestreams = { }
+local referenced = { }
+local ignorereferenced = true -- fuzzy pdf spec .. twice in attachment list, can become an option
+local tobesavedobjrefs = utilities.storage.allocate()
+local collectedobjrefs = utilities.storage.allocate()
+
+local fileobjreferences = {
+ collected = collectedobjrefs,
+ tobesaved = tobesavedobjrefs,
+}
+
+job.fileobjreferences = fileobjreferences
+
+local function initializer()
+ collectedobjrefs = job.fileobjreferences.collected or { }
+ tobesavedobjrefs = job.fileobjreferences.tobesaved or { }
+end
+
+job.register('job.fileobjreferences.collected', tobesavedobjrefs, initializer)
+
+local function flushembeddedfiles()
+ if next(filestreams) then
+ local e = pdfarray()
+ for tag, reference in next, filestreams do
+ if not reference then
+ report_attachment("unreferenced file, tag %a",tag)
+ elseif referenced[tag] == "hidden" then
+ 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
+ end
+ end
+ lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e })))
+ end
+end
+
+lpdf.registerdocumentfinalizer(flushembeddedfiles,"embeddedfiles")
+
+function codeinjections.embedfile(specification)
+ local data = specification.data
+ local filename = specification.file
+ local name = specification.name or ""
+ local title = specification.title or ""
+ local hash = specification.hash or filename
+ local keepdir = specification.keepdir -- can change
+ local usedname = specification.usedname
+ local filetype = specification.filetype
+ if filename == "" then
+ filename = nil
+ end
+ if data then
+ local r = filestreams[hash]
+ if r == false then
+ return nil
+ elseif r then
+ return r
+ elseif not filename then
+ filename = specification.tag
+ if not filename or filename == "" then
+ filename = specification.registered
+ end
+ if not filename or filename == "" then
+ filename = hash
+ end
+ end
+ else
+ if not filename then
+ return nil
+ end
+ local r = filestreams[hash]
+ if r == false then
+ return nil
+ elseif r then
+ return r
+ else
+ local foundname = resolvers.findbinfile(filename) or ""
+ if foundname == "" or not lfs.isfile(foundname) then
+ filestreams[filename] = false
+ return nil
+ else
+ specification.foundname = foundname
+ end
+ end
+ end
+ -- needs to cleaned up:
+ usedname = usedname ~= "" and usedname or filename or name
+ local basename = keepdir == true and usedname or file.basename(usedname)
+ local basename = gsub(basename,"%./","")
+ local savename = name ~= "" and name or basename
+ if not filetype or filetype == "" then
+ filetype = name and (filename and file.suffix(filename)) or "txt"
+ end
+ savename = file.addsuffix(savename,filetype) -- type is mandate for proper working in viewer
+ local mimetype = specification.mimetype
+ local a = pdfdictionary {
+ Type = pdfconstant("EmbeddedFile"),
+ Subtype = mimetype and mimetype ~= "" and pdfconstant(mimetype) or nil,
+ }
+ local f
+ if data then
+ f = pdfflushstreamobject(data,a)
+ specification.data = true -- signal that still data but already flushed
+ else
+ local foundname = specification.foundname or filename
+ f = pdfflushstreamfileobject(foundname,a)
+ end
+ local d = pdfdictionary {
+ Type = pdfconstant("Filespec"),
+ F = pdfstring(savename),
+ UF = pdfstring(savename),
+ EF = pdfdictionary { F = pdfreference(f) },
+ Desc = title ~= "" and pdfunicode(title) or nil,
+ -- AFRelationship = pdfconstant("Source"), -- some day maybe, not mandate
+ }
+ local r = pdfreference(pdfflushobject(d))
+ filestreams[hash] = r
+ return r
+end
+
+function nodeinjections.attachfile(specification)
+ local registered = specification.registered or "<unset>"
+ local data = specification.data
+ local hash
+ local filename
+ if data then
+ hash = md5.HEX(data)
+ else
+ filename = specification.file
+ if not filename or filename == "" then
+ report_attachment("no file specified, using registered %a instead",registered)
+ filename = registered
+ specification.file = registered
+ end
+ local foundname = resolvers.findbinfile(filename) or ""
+ if foundname == "" or not lfs.isfile(foundname) then
+ report_attachment("invalid filename %a, ignoring registered %a",filename,registered)
+ return nil
+ else
+ specification.foundname = foundname
+ end
+ hash = filename
+ end
+ specification.hash = hash
+ nofattachments = nofattachments + 1
+ local registered = specification.registered or ""
+ local title = specification.title or ""
+ local subtitle = specification.subtitle or ""
+ local author = specification.author or ""
+ if registered == "" then
+ registered = filename
+ end
+ if author == "" and title ~= "" then
+ author = title
+ title = filename or ""
+ end
+ if author == "" then
+ author = filename or "<unknown>"
+ end
+ if title == "" then
+ title = registered
+ end
+ local aref = attachments[registered]
+ if not aref then
+ aref = codeinjections.embedfile(specification)
+ attachments[registered] = aref
+ end
+ local reference = specification.reference
+ if reference and aref then
+ tobesavedobjrefs[reference] = aref[1]
+ end
+ if not aref then
+ report_attachment("skipping attachment, registered %a",registered)
+ -- already reported
+ elseif specification.method == v_hidden then
+ referenced[hash] = "hidden"
+ else
+ referenced[hash] = "annotation"
+ local name, appearance = analyzesymbol(specification.symbol,attachment_symbols)
+ local d = pdfdictionary {
+ Subtype = pdfconstant("FileAttachment"),
+ FS = aref,
+ Contents = pdfunicode(title),
+ Name = name,
+ NM = pdfstring(format("attachment:%s",nofattachments)),
+ T = author ~= "" and pdfunicode(author) or nil,
+ Subj = subtitle ~= "" and pdfunicode(subtitle) or nil,
+ C = analyzecolor(specification.colorvalue,specification.colormodel),
+ CA = analyzetransparency(specification.transparencyvalue),
+ AP = appearance,
+ OC = analyzelayer(specification.layer),
+ }
+ local width, height, depth = specification.width or 0, specification.height or 0, specification.depth
+ local box = hpack_node(nodeinjections.annotation(width,height,depth,d()))
+ box.width, box.height, box.depth = width, height, depth
+ return box
+ end
+end
+
+function codeinjections.attachmentid(filename) -- not used in context
+ return filestreams[filename]
+end
+
+local nofcomments, usepopupcomments, stripleading = 0, false, true
+
+local defaultattributes = {
+ ["xmlns"] = "http://www.w3.org/1999/xhtml",
+ ["xmlns:xfa"] = "http://www.xfa.org/schema/xfa-data/1.0/",
+ ["xfa:contentType"] = "text/html",
+ ["xfa:APIVersion"] = "Acrobat:8.0.0",
+ ["xfa:spec"] = "2.4",
+}
+
+local function checkcontent(text,option)
+ if option and option.xml then
+ local root = xml.convert(text)
+ if root and not root.er then
+ xml.checkbom(root)
+ local body = xml.first(root,"/body")
+ if body then
+ local at = body.at
+ for k, v in next, defaultattributes do
+ if not at[k] then
+ at[k] = v
+ end
+ end
+ -- local content = xml.textonly(root)
+ local richcontent = xml.tostring(root)
+ return nil, pdfunicode(richcontent)
+ end
+ end
+ end
+ return pdfunicode(text)
+end
+
+function nodeinjections.comment(specification) -- brrr: seems to be done twice
+ nofcomments = nofcomments + 1
+ local text = stripstring(specification.data or "")
+ if stripleading then
+ text = gsub(text,"[\n\r] *","\n")
+ end
+ local name, appearance = analyzesymbol(specification.symbol,comment_symbols)
+ local tag = specification.tag or "" -- this is somewhat messy as recent
+ local title = specification.title or "" -- versions of acrobat see the title
+ local subtitle = specification.subtitle or "" -- as author
+ local author = specification.author or ""
+ local option = settings_to_hash(specification.option or "")
+ if author == "" then
+ if title == "" then
+ title = tag
+ end
+ else
+ if subtitle == "" then
+ subtitle = title
+ elseif title ~= "" then
+ subtitle = subtitle .. ", " .. title
+ end
+ title = author
+ end
+ local content, richcontent = checkcontent(text,option)
+ local d = pdfdictionary {
+ Subtype = pdfconstant("Text"),
+ Open = option[v_max] and pdfboolean(true) or nil,
+ Contents = content,
+ RC = richcontent,
+ T = title ~= "" and pdfunicode(title) or nil,
+ Subj = subtitle ~= "" and pdfunicode(subtitle) or nil,
+ C = analyzecolor(specification.colorvalue,specification.colormodel),
+ CA = analyzetransparency(specification.transparencyvalue),
+ OC = analyzelayer(specification.layer),
+ Name = name,
+ NM = pdfstring(format("comment:%s",nofcomments)),
+ AP = appearance,
+ }
+ local width, height, depth = specification.width or 0, specification.height or 0, specification.depth
+ local box
+ if usepopupcomments then
+ -- rather useless as we can hide/vide
+ local nd = pdfreserveobject()
+ local nc = pdfreserveobject()
+ local c = pdfdictionary {
+ Subtype = pdfconstant("Popup"),
+ Parent = pdfreference(nd),
+ }
+ d.Popup = pdfreference(nc)
+ box = hpack_node(
+ nodeinjections.annotation(0,0,0,d(),nd),
+ nodeinjections.annotation(width,height,depth,c(),nc)
+ )
+ else
+ box = hpack_node(nodeinjections.annotation(width,height,depth,d()))
+ end
+ box.width, box.height, box.depth = width, height, depth -- redundant
+ return box
+end
+
+-- rendering stuff
+--
+-- object_1 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >>
+-- object_2 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >>
+-- rendering -> <</Type /Rendition /S /MS [objref_1 objref_2]>>
+--
+-- we only work foreward here (currently)
+-- annotation is to be packed at the tex end
+
+-- aiff audio/aiff
+-- au audio/basic
+-- avi video/avi
+-- mid audio/midi
+-- mov video/quicktime
+-- mp3 audio/x-mp3 (mpeg)
+-- mp4 audio/mp4
+-- mp4 video/mp4
+-- mpeg video/mpeg
+-- smil application/smil
+-- swf application/x-shockwave-flash
+
+-- P media play parameters (evt /BE for controls etc
+-- A boolean (audio)
+-- C boolean (captions)
+-- O boolean (overdubs)
+-- S boolean (subtitles)
+-- PL pdfconstant("ADBE_MCI"),
+
+-- F = flags,
+-- T = title,
+-- Contents = rubish,
+-- AP = irrelevant,
+
+-- sound is different, no window (or zero) so we need to collect them and
+-- force them if not set
+
+local ms, mu, mf = { }, { }, { }
+
+local function delayed(label)
+ local a = pdfreserveobject()
+ mu[label] = a
+ return pdfreference(a)
+end
+
+local function insertrenderingwindow(specification)
+ local label = specification.label
+ -- local openpage = specification.openpage
+ -- local closepage = specification.closepage
+ if specification.option == v_auto then
+ if openpageaction then
+ -- \handlereferenceactions{\v!StartRendering{#2}}
+ end
+ if closepageaction then
+ -- \handlereferenceactions{\v!StopRendering {#2}}
+ end
+ end
+ local actions = nil
+ if openpage or closepage then
+ actions = pdfdictionary {
+ PO = (openpage and lpdfaction(openpage )) or nil,
+ PC = (closepage and lpdfaction(closepage)) or nil,
+ }
+ end
+ local page = tonumber(specification.page) or texgetcount("realpageno") -- todo
+ local r = mu[label] or pdfreserveobject() -- why the reserve here?
+ local a = pdfdictionary {
+ S = pdfconstant("Rendition"),
+ R = mf[label],
+ OP = 0,
+ AN = pdfreference(r),
+ }
+ local bs, bc = pdfborder()
+ local d = pdfdictionary {
+ Subtype = pdfconstant("Screen"),
+ P = pdfreference(pdfpagereference(page)),
+ A = a, -- needed in order to make the annotation clickable (i.e. don't bark)
+ Border = bs,
+ C = bc,
+ AA = actions,
+ }
+ local width = specification.width or 0
+ local height = specification.height or 0
+ if height == 0 or width == 0 then
+ -- todo: sound needs no window
+ end
+ write_node(nodeinjections.annotation(width,height,0,d(),r)) -- save ref
+ return pdfreference(r)
+end
+
+-- some dictionaries can have a MH (must honor) or BE (best effort) capsule
+
+local function insertrendering(specification)
+ local label = specification.label
+ local option = settings_to_hash(specification.option)
+ if not mf[label] then
+ local filename = specification.filename
+ local isurl = find(filename,"://",1,true)
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("T"), -- time
+ -- T = pdfdictionary { -- time
+ -- Type = pdfconstant("Timespan"),
+ -- S = pdfconstant("S"),
+ -- V = 3, -- time in seconds
+ -- },
+ -- }
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("F"), -- frame
+ -- F = 100 -- framenumber
+ -- }
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("M"), -- mark
+ -- M = "somemark",
+ -- }
+ -- local parameters = pdfdictionary {
+ -- BE = pdfdictionary {
+ -- B = start,
+ -- }
+ -- }
+ -- local parameters = pdfdictionary {
+ -- Type = pdfconstant(MediaPermissions),
+ -- TF = pdfstring("TEMPALWAYS") }, -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS
+ -- }
+ local descriptor = pdfdictionary {
+ Type = pdfconstant("Filespec"),
+ F = filename,
+ }
+ if isurl then
+ descriptor.FS = pdfconstant("URL")
+ elseif option[v_embed] then
+ descriptor.EF = codeinjections.embedfile { file = filename }
+ end
+ local clip = pdfdictionary {
+ Type = pdfconstant("MediaClip"),
+ S = pdfconstant("MCD"),
+ N = label,
+ CT = specification.mime,
+ Alt = pdfarray { "", "file not found" }, -- language id + message
+ D = pdfreference(pdfflushobject(descriptor)),
+ -- P = pdfreference(pdfflushobject(parameters)),
+ }
+ local rendition = pdfdictionary {
+ Type = pdfconstant("Rendition"),
+ S = pdfconstant("MR"),
+ N = label,
+ C = pdfreference(pdfflushobject(clip)),
+ }
+ mf[label] = pdfreference(pdfflushobject(rendition))
+ end
+end
+
+local function insertrenderingobject(specification) -- todo
+ local label = specification.label
+ if not mf[label] then
+ report_media("unknown medium, label %a",label)
+ local clip = pdfdictionary { -- does not work that well one level up
+ Type = pdfconstant("MediaClip"),
+ S = pdfconstant("MCD"),
+ N = label,
+ D = pdfreference(unknown), -- not label but objectname, hm .. todo?
+ }
+ local rendition = pdfdictionary {
+ Type = pdfconstant("Rendition"),
+ S = pdfconstant("MR"),
+ N = label,
+ C = pdfreference(pdfflushobject(clip)),
+ }
+ mf[label] = pdfreference(pdfflushobject(rendition))
+ end
+end
+
+function codeinjections.processrendering(label)
+ local specification = interactions.renderings.rendering(label)
+ if not specification then
+ -- error
+ elseif specification.type == "external" then
+ insertrendering(specification)
+ else
+ insertrenderingobject(specification)
+ end
+end
+
+function codeinjections.insertrenderingwindow(specification)
+ local label = specification.label
+ codeinjections.processrendering(label)
+ ms[label] = insertrenderingwindow(specification)
+end
+
+local function set(operation,arguments)
+ codeinjections.processrendering(arguments)
+ return pdfdictionary {
+ S = pdfconstant("Rendition"),
+ OP = operation,
+ R = mf[arguments],
+ AN = ms[arguments] or delayed(arguments),
+ }
+end
+
+function executers.startrendering (arguments) return set(0,arguments) end
+function executers.stoprendering (arguments) return set(1,arguments) end
+function executers.pauserendering (arguments) return set(2,arguments) end
+function executers.resumerendering(arguments) return set(3,arguments) end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua
new file mode 100644
index 00000000000..b8170319c11
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua
@@ -0,0 +1,279 @@
+if not modules then modules = { } end modules ['lpdf-xmp'] = {
+ 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",
+ comment = "with help from Peter Rolf",
+}
+
+local tostring, type = tostring, type
+local format, random, char, gsub, concat = string.format, math.random, string.char, string.gsub, table.concat
+local xmlfillin = xml.fillin
+
+local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
+local trace_info = false trackers.register("backend.info", function(v) trace_info = v end)
+
+local report_xmp = logs.reporter("backend","xmp")
+local report_info = logs.reporter("backend","info")
+
+local backends, lpdf = backends, lpdf
+
+local codeinjections = backends.pdf.codeinjections -- normally it is registered
+
+local pdfdictionary = lpdf.dictionary
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushstreamobject = lpdf.flushstreamobject
+
+-- I wonder why this begin end is empty / w (no time now to look into it) / begin can also be "?"
+
+local xpacket = [[
+<?xpacket begin="" id="%s"?>
+
+%s
+
+<?xpacket end="w"?>]]
+
+local mapping = {
+ -- user defined keys (pdfx:)
+ ["ConTeXt.Jobname"] = { "context", "rdf:Description/pdfx:ConTeXt.Jobname" },
+ ["ConTeXt.Time"] = { "date", "rdf:Description/pdfx:ConTeXt.Time" },
+ ["ConTeXt.Url"] = { "context", "rdf:Description/pdfx:ConTeXt.Url" },
+ ["ConTeXt.Version"] = { "context", "rdf:Description/pdfx:ConTeXt.Version" },
+ ["ID"] = { "date", "rdf:Description/pdfx:ID" }, -- has date
+ ["PTEX.Fullbanner"] = { "metadata","rdf:Description/pdfx:PTEX.Fullbanner" },
+ -- Adobe PDF schema
+ ["Keywords"] = { "metadata","rdf:Description/pdf:Keywords" },
+ ["Producer"] = { "metadata","rdf:Description/pdf:Producer" },
+ -- ["Trapped"] = { "pdf", "rdf:Description/pdf:Trapped" }, -- '/False' in /Info, but 'False' in XMP
+ -- Dublin Core schema
+ ["Author"] = { "metadata","rdf:Description/dc:creator/rdf:Seq/rdf:li" },
+ ["Format"] = { "metadata","rdf:Description/dc:format" }, -- optional, but nice to have
+ ["Subject"] = { "metadata","rdf:Description/dc:description/rdf:Alt/rdf:li" },
+ ["Title"] = { "metadata","rdf:Description/dc:title/rdf:Alt/rdf:li" },
+ -- XMP Basic schema
+ ["CreateDate"] = { "date", "rdf:Description/xmp:CreateDate" },
+ ["CreationDate"] = { "date", "rdf:Description/xmp:CreationDate" }, -- dummy
+ ["Creator"] = { "metadata","rdf:Description/xmp:CreatorTool" },
+ ["MetadataDate"] = { "date", "rdf:Description/xmp:MetadataDate" },
+ ["ModDate"] = { "date", "rdf:Description/xmp:ModDate" }, -- dummy
+ ["ModifyDate"] = { "date", "rdf:Description/xmp:ModifyDate" },
+ -- XMP Media Management schema
+ ["DocumentID"] = { "date", "rdf:Description/xmpMM:DocumentID" }, -- uuid
+ ["InstanceID"] = { "date", "rdf:Description/xmpMM:InstanceID" }, -- uuid
+ ["RenditionClass"] = { "pdf", "rdf:Description/xmpMM:RenditionClass" }, -- PDF/X-4
+ ["VersionID"] = { "pdf", "rdf:Description/xmpMM:VersionID" }, -- PDF/X-4
+ -- additional entries
+ -- PDF/X
+ ["GTS_PDFXVersion"] = { "pdf", "rdf:Description/pdfxid:GTS_PDFXVersion" },
+ -- optional entries
+ -- all what is visible in the 'document properties --> additional metadata' window
+ -- XMP Rights Management schema (optional)
+ ["Marked"] = { "pdf", "rdf:Description/xmpRights:Marked" },
+ -- ["Owner"] = { "metadata", "rdf:Description/xmpRights:Owner/rdf:Bag/rdf:li" }, -- maybe useful (not visible)
+ -- ["UsageTerms"] = { "metadata", "rdf:Description/xmpRights:UsageTerms" }, -- maybe useful (not visible)
+ ["WebStatement"] = { "metadata", "rdf:Description/xmpRights:WebStatement" },
+ -- Photoshop PDF schema (optional)
+ ["AuthorsPosition"] = { "metadata", "rdf:Description/photoshop:AuthorsPosition" },
+ ["Copyright"] = { "metadata", "rdf:Description/photoshop:Copyright" },
+ ["CaptionWriter"] = { "metadata", "rdf:Description/photoshop:CaptionWriter" },
+}
+
+pdf.setsuppressoptionalinfo(
+ 0 --
+ + 1 -- pdfnofullbanner
+ + 2 -- pdfnofilename
+ + 4 -- pdfnopagenumber
+ + 8 -- pdfnoinfodict
+ + 16 -- pdfnocreator
+ + 32 -- pdfnocreationdate
+ + 64 -- pdfnomoddate
+ + 128 -- pdfnoproducer
+ + 256 -- pdfnotrapped
+ -- + 512 -- pdfnoid
+)
+
+local included = table.setmetatableindex( {
+ context = true,
+ id = true,
+ metadata = true,
+ date = true,
+ id = true,
+ pdf = true,
+}, function(t,k)
+ return true
+end)
+
+directives.register("backend.nodates", function(v)
+ included.date = not v
+ if v then
+ report_info("no date/time information will be added to the PDF file")
+ end
+end)
+
+directives.register("backend.trailerid", function(v)
+ if v then
+ if toboolean(v) or v == "" then
+ v = "This file is processed by ConTeXt and LuaTeX."
+ else
+ v = tostring(v)
+ end
+ local h = md5.HEX(v)
+ report_info("using hashed trailer id %a (%a)",v,h)
+ pdf.settrailerid(format("[<%s> <%s>]",h,h))
+ end
+end)
+
+local function permitdetail(what)
+ local m = mapping[what]
+ if m then
+ return included[m[1]] and m[2]
+ else
+ return included[what]
+ end
+end
+
+lpdf.permitdetail = permitdetail
+
+-- maybe some day we will load the xmp file at runtime
+
+local xmp, xmpfile, xmpname = nil, nil, "lpdf-pdx.xml"
+
+local function setxmpfile(name)
+ if xmp then
+ report_xmp("discarding loaded file %a",xmpfile)
+ xmp = nil
+ end
+ xmpfile = name ~= "" and name
+end
+
+codeinjections.setxmpfile = setxmpfile
+
+interfaces.implement {
+ name = "setxmpfile",
+ arguments = "string",
+ actions = setxmpfile
+}
+
+local function valid_xmp()
+ if not xmp then
+ -- local xmpfile = xmpfile or resolvers.findfile(xmpname) or ""
+ if xmpfile and xmpfile ~= "" then
+ xmpfile = resolvers.findfile(xmpfile) or ""
+ end
+ if not xmpfile or xmpfile == "" then
+ xmpfile = resolvers.findfile(xmpname) or ""
+ end
+ if xmpfile ~= "" then
+ report_xmp("using file %a",xmpfile)
+ end
+ local xmpdata = xmpfile ~= "" and io.loaddata(xmpfile) or ""
+ xmp = xml.convert(xmpdata)
+ end
+ return xmp
+end
+
+function lpdf.addxmpinfo(tag,value,check)
+ local pattern = permitdetail(tag)
+ if type(pattern) == "string" then
+ xmlfillin(xmp or valid_xmp(),pattern,value,check)
+ end
+end
+
+-- redefined
+
+local pdfaddtoinfo = lpdf.addtoinfo
+local pdfaddxmpinfo = lpdf.addxmpinfo
+
+function lpdf.addtoinfo(tag,pdfvalue,strvalue)
+ local pattern = permitdetail(tag)
+ if pattern then
+ pdfaddtoinfo(tag,pdfvalue)
+ end
+ if type(pattern) == "string" then
+ local value = strvalue or gsub(tostring(pdfvalue),"^%((.*)%)$","%1") -- hack
+ if trace_info then
+ report_info("set %a to %a",tag,value)
+ end
+ xmlfillin(xmp or valid_xmp(),pattern,value,check)
+ end
+end
+
+local pdfaddtoinfo = lpdf.addtoinfo -- used later
+
+-- for the do-it-yourselvers
+
+function lpdf.insertxmpinfo(pattern,whatever,prepend)
+ xml.insert(xmp or valid_xmp(),pattern,whatever,prepend)
+end
+
+function lpdf.injectxmpinfo(pattern,whatever,prepend)
+ xml.inject(xmp or valid_xmp(),pattern,whatever,prepend)
+end
+
+-- flushing
+
+local t = { } for i=1,24 do t[i] = random() end
+
+local function flushxmpinfo()
+ commands.pushrandomseed()
+ commands.setrandomseed(os.time())
+
+ local t = { } for i=1,24 do t[i] = char(96 + random(26)) end
+ local packetid = concat(t)
+
+ local documentid = format("uuid:%s",os.uuid())
+ local instanceid = format("uuid:%s",os.uuid())
+ local producer = format("LuaTeX-%0.2f.%s",status.luatex_version/100,status.luatex_revision)
+ local creator = "LuaTeX + ConTeXt MkIV"
+ local time = lpdf.timestamp()
+ local fullbanner = status.banner
+
+ pdfaddxmpinfo("DocumentID", documentid)
+ pdfaddxmpinfo("InstanceID", instanceid)
+ pdfaddxmpinfo("Producer", producer)
+ pdfaddxmpinfo("CreatorTool", creator)
+ pdfaddxmpinfo("CreateDate", time)
+ pdfaddxmpinfo("ModifyDate", time)
+ pdfaddxmpinfo("MetadataDate", time)
+ pdfaddxmpinfo("PTEX.Fullbanner", fullbanner)
+
+ pdfaddtoinfo("Producer", producer)
+ pdfaddtoinfo("Creator", creator)
+ pdfaddtoinfo("CreationDate", time)
+ pdfaddtoinfo("ModDate", time)
+ -- pdfaddtoinfo("PTEX.Fullbanner", fullbanner) -- no checking done on existence
+
+ local blob = xml.tostring(xml.first(xmp or valid_xmp(),"/x:xmpmeta"))
+ local md = pdfdictionary {
+ Subtype = pdfconstant("XML"),
+ Type = pdfconstant("Metadata"),
+ }
+ if trace_xmp then
+ report_xmp("data flushed, see log file")
+ logs.pushtarget("logfile")
+ report_xmp("start xmp blob")
+ logs.newline()
+ logs.writer(blob)
+ logs.newline()
+ report_xmp("stop xmp blob")
+ logs.poptarget()
+ end
+ blob = format(xpacket,packetid,blob)
+ if not verbose and pdf.getcompresslevel() > 0 then
+ blob = gsub(blob,">%s+<","><")
+ end
+ local r = pdfflushstreamobject(blob,md,false) -- uncompressed
+ lpdf.addtocatalog("Metadata",pdfreference(r))
+
+ commands.poprandomseed() -- hack
+end
+
+-- his will be enabled when we can inhibit compression for a stream at the lua end
+
+lpdf.registerdocumentfinalizer(flushxmpinfo,1,"metadata")
+
+directives.register("backend.verbosexmp", function(v)
+ verbose = v
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv
new file mode 100644
index 00000000000..cb00d8f55e7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=luat-bas, % moved from luat-lib,
+%D version=2006.09.11,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Basic \LUA\ 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 / Basic Lua Libraries}
+
+\registerctxluafile{l-lua} {1.001} % before sandbox
+\registerctxluafile{l-sandbox} {1.001}
+\registerctxluafile{l-package} {1.001}
+\registerctxluafile{l-lpeg} {1.001}
+\registerctxluafile{l-function}{1.001}
+\registerctxluafile{l-string} {1.001}
+\registerctxluafile{l-table} {1.001}
+\registerctxluafile{l-boolean} {1.001}
+\registerctxluafile{l-number} {1.001}
+\registerctxluafile{l-math} {1.001}
+%registerctxluafile{l-aux} {1.001}
+\registerctxluafile{l-io} {1.001}
+\registerctxluafile{l-os} {1.001}
+\registerctxluafile{l-file} {1.001}
+\registerctxluafile{l-gzip} {1.001}
+\registerctxluafile{l-md5} {1.001}
+\registerctxluafile{l-dir} {1.001}
+\registerctxluafile{l-unicode} {1.001}
+%registerctxluafile{l-utils} {1.001}
+\registerctxluafile{l-url} {1.001}
+\registerctxluafile{l-set} {1.001}
+
+% \registerctxluafile{socket.lua}{}
+% \registerctxluafile{ltn12.lua} {}
+% \registerctxluafile{mime.lua} {}
+% \registerctxluafile{http.lua} {}
+% \registerctxluafile{url.lua} {}
+% \registerctxluafile{tp.lua} {}
+% \registerctxluafile{ftp.lua} {}
+% %registerctxluafile{smtp.lua} {}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-bwc.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-bwc.lua
new file mode 100644
index 00000000000..993de7bf3f4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-bwc.lua
@@ -0,0 +1,32 @@
+if not modules then modules = { } end modules ['luat-bwc'] = {
+ 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"
+}
+
+-- backward compatibility
+
+if not tex.wd then
+
+ local box = tex.box
+
+ local wd = { } setmetatable(wd, {
+ __index = function(t,k) local bk = box[k] return bk and bk.width or 0 end,
+ __newindex = function(t,k,v) local bk = box[k] if bk then bk.width = v end end,
+ } )
+
+ local ht = { } setmetatable(ht, {
+ __index = function(t,k) local bk = box[k] return bk and bk.height or 0 end,
+ __newindex = function(t,k,v) local bk = box[k] if bk then bk.height = v end end,
+ } )
+
+ local dp = { } setmetatable(dp, {
+ __index = function(t,k) local bk = box[k] return bk and bk.depth or 0 end,
+ __newindex = function(t,k,v) local bk = box[k] if bk then bk.depth = v end end,
+ } )
+
+ -- tex.wd, tex.ht, tex.dp = wd, ht, dp
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua
new file mode 100644
index 00000000000..2c3bede72c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua
@@ -0,0 +1,386 @@
+if not modules then modules = { } end modules ['luat-cbk'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, concat = table.insert, table.remove, table.concat
+local find, format = string.find, string.format
+local collectgarbage, type, next = collectgarbage, type, next
+local round = math.round
+local sortedhash, sortedkeys, tohash = table.sortedhash, table.sortedkeys, table.tohash
+
+--[[ldx--
+<p>Callbacks are the real asset of <l n='luatex'/>. They permit you to hook
+your own code into the <l n='tex'/> engine. Here we implement a few handy
+auxiliary functions.</p>
+--ldx]]--
+
+callbacks = callbacks or { }
+local callbacks = callbacks
+
+--[[ldx--
+<p>When you (temporarily) want to install a callback function, and after a
+while wants to revert to the original one, you can use the following two
+functions. This only works for non-frozen ones.</p>
+--ldx]]--
+
+local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end)
+local trace_calls = false -- only used when analyzing performance and initializations
+local trace_checking = false trackers.register("memory.checking", function(v) trace_checking = v end)
+
+local report_system = logs.reporter("system")
+local report_callbacks = logs.reporter("system","callbacks")
+local report_memory = logs.reporter("system","memory")
+
+local register_callback = callback.register
+local find_callback = callback.find
+local list_callbacks = callback.list
+local register_usercall = false
+local original_register = register_callback
+
+local frozen = { }
+local stack = { }
+local list = callbacks.list
+local permit_overloads = false
+local block_overloads = false
+
+--[[ldx--
+<p>By now most callbacks are frozen and most provide a way to plug in your own code. For instance
+all node list handlers provide before/after namespaces and the file handling code can be extended
+by adding schemes and if needed I can add more hooks. So there is no real need to overload a core
+callback function. It might be ok for quick and dirty testing but anyway you're on your own if
+you permanently overload callback functions.</p>
+--ldx]]--
+
+-- This might become a configuration file only option when it gets abused too much.
+
+directives.register("system.callbacks.permitoverloads", function(v)
+ if block_overloads or permit_overloads then
+ -- once bad news, always bad news
+ elseif v then
+ permit_overloads = { }
+ report_system()
+ report_system("The callback system has been brought in an unprotected state. As a result of directly")
+ report_system("setting of callbacks subsystems of ConTeXt can stop working. There is no support for")
+ report_system("bugs resulting from this state. It's better to use the official extension mechanisms.")
+ report_system()
+ end
+end)
+
+sandbox.initializer(function()
+ block_overloads = true
+end)
+
+if not list then -- otherwise counters get reset
+
+ list = utilities.storage.allocate(list_callbacks())
+
+ for k in next, list do
+ list[k] = 0
+ end
+
+ callbacks.list = list
+
+end
+
+local delayed = tohash {
+ "buildpage_filter",
+}
+
+if trace_calls then
+
+ local functions = { }
+
+ register_callback = function(name,func)
+ if type(func) == "function" then
+ if functions[name] then
+ functions[name] = func
+ return find_callback(name)
+ else
+ functions[name] = func
+ local cnuf = function(...)
+ list[name] = list[name] + 1
+ return functions[name](...)
+ end
+ return original_register(name,cnuf)
+ end
+ else
+ return original_register(name,func)
+ end
+ end
+
+end
+
+local reported = { }
+
+local function register_usercall(what,name,func)
+ if list[name] then
+ if trace_callbacks or not reported[name] then
+ report_system()
+ report_system("disabling core code by %s user function into callback '%s' (reported only once)",what,name)
+ report_system()
+ reported[name] = true
+ end
+ permit_overloads[name] = true
+ return original_register(name,function(...)
+ if trace_callbacks then
+ report_callbacks("calling user function from '%s'",name)
+ end
+ return func(...)
+ end)
+ else
+ report_callbacks("not %s function into invalid callback '%s'",name)
+ return nil, format("unknown callback '%s'",name)
+ end
+end
+
+local function frozen_callback(name)
+ report_callbacks("not %s frozen %a","registering",name)
+ return nil, format("callback '%s' is frozen",name) -- no formatter yet
+end
+
+local function state(name)
+ local f = find_callback(name)
+ if f == false then
+ return "disabled"
+ elseif f then
+ return "enabled"
+ else
+ return "undefined"
+ end
+end
+
+function callbacks.known(name)
+ return list[name]
+end
+
+function callbacks.report()
+ for name, _ in sortedhash(list) do
+ local str = frozen[name]
+ if str then
+ report_callbacks("%s: %s -> %s",state(name),name,str)
+ else
+ report_callbacks("%s: %s",state(name),name)
+ end
+ end
+end
+
+function callbacks.freeze(name,freeze)
+ if not permit_overloads then
+ freeze = type(freeze) == "string" and freeze
+ if find(name,"*",1,true) then
+ local pattern = name
+ for name, _ in next, list do
+ if find(name,pattern) then
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+ end
+ else
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+ end
+end
+
+function callbacks.register(name,func,freeze)
+ if frozen[name] then
+ if permit_overloads then
+ return register_usercall("registering",name,func)
+ else
+ return frozen_callback(name)
+ end
+ elseif freeze then
+ frozen[name] = type(freeze) == "string" and freeze or "registered"
+ end
+ if delayed[name] and environment.initex then
+ return nil
+ end
+ return register_callback(name,func)
+end
+
+function callback.register(name,func) -- original
+ if not frozen[name] then
+ return register_callback(name,func)
+ elseif permit_overloads then
+ return register_usercall("registering",name,func)
+ else
+ return frozen_callback(name)
+ end
+end
+
+function callbacks.push(name,func)
+ if not frozen[name] or permit_overloads then
+ local sn = stack[name]
+ if not sn then
+ sn = { }
+ stack[name] = sn
+ end
+ insert(sn,find_callback(name))
+ if permit_overloads then
+ register_usercall("pushing",name,func)
+ else
+ register_callback(name,func)
+ end
+ else
+ report_callbacks("not %s frozen %a","pushing",name)
+ end
+end
+
+function callbacks.pop(name)
+ if not frozen[name] or permit_overloads then
+ local sn = stack[name]
+ if not sn or #sn == 0 then
+ -- some error
+ register_callback(name,nil) -- ! really needed
+ else
+ -- this fails: register_callback(name, remove(stack[name]))
+ local func = remove(sn)
+ register_callback(name,func)
+ end
+ end
+end
+
+if trace_calls then
+ statistics.register("callback details", function()
+ local t = { } -- todo: pass function to register and quit at nil
+ for name, n in sortedhash(list) do
+ if n > 0 then
+ t[#t+1] = format("%s -> %s",name,n)
+ end
+ end
+ return concat(t," ")
+ end)
+end
+
+statistics.register("callbacks overloaded by user", function()
+ if permit_overloads then
+ return concat(sortedkeys(permit_overloads)," ")
+ end
+end)
+
+-- -- somehow crashes later on
+--
+-- callbacks.freeze("find_.*_file","finding file")
+-- callbacks.freeze("read_.*_file","reading file")
+-- callbacks.freeze("open_.*_file","opening file")
+
+--[[ldx--
+<p>The simple case is to remove the callback:</p>
+
+<code>
+callbacks.push('linebreak_filter')
+... some actions ...
+callbacks.pop('linebreak_filter')
+</code>
+
+<p>Often, in such case, another callback or a macro call will pop
+the original.</p>
+
+<p>In practice one will install a new handler, like in:</p>
+
+<code>
+callbacks.push('linebreak_filter', function(...)
+ return something_done(...)
+end)
+</code>
+
+<p>Even more interesting is:</p>
+
+<code>
+callbacks.push('linebreak_filter', function(...)
+ callbacks.pop('linebreak_filter')
+ return something_done(...)
+end)
+</code>
+
+<p>This does a one-shot.</p>
+--ldx]]--
+
+--[[ldx--
+<p>Callbacks may result in <l n='lua'/> doing some hard work
+which takes time and above all resourses. Sometimes it makes
+sense to disable or tune the garbage collector in order to
+keep the use of resources acceptable.</p>
+
+<p>At some point in the development we did some tests with counting
+nodes (in this case 121049).</p>
+
+<table>
+<tr><td>setstepmul</td><td>seconds</td><td>megabytes</td></tr>
+<tr><td>200</td><td>24.0</td><td>80.5</td></tr>
+<tr><td>175</td><td>21.0</td><td>78.2</td></tr>
+<tr><td>150</td><td>22.0</td><td>74.6</td></tr>
+<tr><td>160</td><td>22.0</td><td>74.6</td></tr>
+<tr><td>165</td><td>21.0</td><td>77.6</td></tr>
+<tr><td>125</td><td>21.5</td><td>89.2</td></tr>
+<tr><td>100</td><td>21.5</td><td>88.4</td></tr>
+</table>
+
+<p>The following code is kind of experimental. In the documents
+that describe the development of <l n='luatex'/> we report
+on speed tests. One observation is thta it sometimes helps to
+restart the collector. Okay, experimental code has been removed,
+because messing aroudn with the gc is too unpredictable.</p>
+--ldx]]--
+
+-- For the moment we keep this here and not in util-gbc.lua or so.
+
+utilities = utilities or { }
+utilities.garbagecollector = utilities.garbagecollector or { }
+local garbagecollector = utilities.garbagecollector
+
+garbagecollector.enabled = false -- could become a directive
+garbagecollector.criterium = 4*1024*1024
+
+-- Lua allocates up to 12 times the amount of memory needed for
+-- handling a string, and for large binary chunks (like chinese otf
+-- files) we get a prominent memory consumption. Even when a variable
+-- is nilled, there is some delay in freeing the associated memory (the
+-- hashed string) because if we do the same thing directly afterwards,
+-- we see only a slight increase in memory. For that reason it makes
+-- sense to do a collector pass after a huge file.
+--
+-- test file:
+--
+-- function test()
+-- local b = collectgarbage("count")
+-- local s = io.loaddata("some font table, e.g. a big tmc file")
+-- local a = collectgarbage("count")
+-- print(">>> STATUS",b,a,a-b,#s,1000*(a-b)/#s)
+-- end
+--
+-- test() test() test() test() collectgarbage("collect") test() test() test() test()
+--
+-- As a result of this, LuaTeX now uses an optimized version of f:read("*a"),
+-- one that does not use the 4K allocations but allocates in one step.
+
+function garbagecollector.check(size,criterium)
+ if garbagecollector.enabled then
+ criterium = criterium or garbagecollector.criterium
+ if not size or (criterium and criterium > 0 and size > criterium) then
+ if trace_checking then
+ local b = collectgarbage("count")
+ collectgarbage("collect")
+ local a = collectgarbage("count")
+ report_memory("forced sweep, collected: %s MB, used: %s MB",round((b-a)/1000),round(a/1000))
+ else
+ collectgarbage("collect")
+ end
+ end
+ end
+end
+
+-- this will move to a module
+
+commands = commands or { }
+
+function commands.showcallbacks()
+ local NC, NR, verbatim = context.NC, context.NR, context.type
+ context.starttabulate { "|l|l|p|" }
+ for name, _ in sortedhash(list) do
+ NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
+ end
+ context.stoptabulate()
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua
new file mode 100644
index 00000000000..83622ef5399
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua
@@ -0,0 +1,214 @@
+if not modules then modules = { } end modules ['luat-cnf'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tostring, tonumber = type, next, tostring, tonumber
+local format, concat, find, lower, gsub = string.format, table.concat, string.find, string.lower, string.gsub
+
+local report = logs.reporter("system")
+
+local allocate = utilities.storage.allocate
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+
+luatex = luatex or { }
+local luatex = luatex
+
+texconfig.error_line = 79 -- frozen
+texconfig.expand_depth = 10000
+texconfig.half_error_line = 50 -- frozen
+texconfig.hash_extra = 100000
+texconfig.max_in_open = 1000 -- frozen
+texconfig.max_print_line = 100000 -- frozen
+texconfig.max_strings = 500000
+texconfig.nest_size = 1000
+texconfig.param_size = 25000
+texconfig.save_size = 100000
+texconfig.stack_size = 10000
+
+local stub = [[
+
+-- checking
+
+storage = storage or { }
+luatex = luatex or { }
+
+-- we provide our own file handling
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+
+-- as soon as possible
+
+luatex.starttime = os.gettimeofday()
+
+-- this will happen after the format is loaded
+
+function texconfig.init()
+
+ -- development
+
+ local builtin, globals = { }, { }
+
+ libraries = { -- we set it here as we want libraries also 'indexed'
+ basiclua = {
+ "string", "table", "coroutine", "debug", "file", "io", "lpeg", "math", "os", "package", "bit32",
+ },
+ basictex = { -- noad
+ "callback", "font", "img", "lang", "lua", "node", "pdf", "status", "tex", "texconfig", "texio", "token",
+ },
+ extralua = {
+ "gzip", "zip", "zlib", "lfs", "ltn12", "mime", "socket", "md5", "profiler", "unicode", "utf",
+ },
+ extratex = {
+ "epdf", "fontloader", "kpse", "mplib",
+ },
+ obsolete = {
+ "fontforge", -- can be filled by luat-log
+ "kpse",
+ "token",
+ },
+ functions = {
+ "assert", "pcall", "xpcall", "error", "collectgarbage",
+ "dofile", "load","loadfile", "require", "module",
+ "getmetatable", "setmetatable",
+ "ipairs", "pairs", "rawequal", "rawget", "rawset", "next",
+ "tonumber", "tostring",
+ "type", "unpack", "select", "print",
+ },
+ builtin = builtin, -- to be filled
+ globals = globals, -- to be filled
+ }
+
+ for k, v in next, _G do
+ globals[k] = tostring(v)
+ end
+
+ local function collect(t,fnc)
+ local lib = { }
+ for k, v in next, t do
+ if fnc then
+ lib[v] = _G[v]
+ else
+ local keys = { }
+ local gv = _G[v]
+ local tv = type(gv)
+ if tv == "table" then
+ for k, v in next, gv do
+ keys[k] = tostring(v) -- true -- by tostring we cannot call overloades functions (security)
+ end
+ end
+ lib[v] = keys
+ builtin[v] = keys
+ end
+ end
+ return lib
+ end
+
+ libraries.basiclua = collect(libraries.basiclua)
+ libraries.basictex = collect(libraries.basictex)
+ libraries.extralua = collect(libraries.extralua)
+ libraries.extratex = collect(libraries.extratex)
+ libraries.functions = collect(libraries.functions,true)
+ libraries.obsolete = collect(libraries.obsolete)
+
+ -- shortcut and helper
+
+ local bytecode = lua.bytecode
+
+ local function init(start)
+ local i = start
+ local t = os.clock()
+ while bytecode[i] do
+ bytecode[i]() ;
+ bytecode[i] = nil ;
+ i = i + 1
+ -- collectgarbage('step')
+ end
+ return i - start, os.clock() - t
+ end
+
+ -- the stored tables and modules
+
+ storage.noftables , storage.toftables = init(0)
+ storage.nofmodules, storage.tofmodules = init(%s)
+
+ if modules then
+ local loaded = package.loaded
+ for module, _ in next, modules do
+ loaded[module] = true
+ end
+ end
+
+ texconfig.init = function() end
+
+end
+
+-- we provide a qualified path
+
+callback.register('find_format_file',function(name)
+ texconfig.formatname = name
+ return name
+end)
+
+-- done, from now on input and callbacks are internal
+]]
+
+local variablenames = {
+ error_line = false,
+ half_error_line = false,
+ max_print_line = false,
+ max_in_open = false,
+ expand_depth = true,
+ hash_extra = true,
+ nest_size = true,
+ max_strings = true,
+ param_size = true,
+ save_size = true,
+ stack_size = true,
+}
+
+local function makestub()
+ name = name or (environment.jobname .. ".lui")
+ report("creating stub file %a using directives:",name)
+ report()
+ firsttable = firsttable or lua.firstbytecode
+ local t = {
+ "-- this file is generated, don't change it\n",
+ "-- configuration (can be overloaded later)\n"
+ }
+ for v, permitted in table.sortedhash(variablenames) do
+ local d = "luatex." .. gsub(lower(v),"[^%a]","")
+ local dv = directives.value(d)
+ local tv = texconfig[v]
+ if dv then
+ if not tv then
+ report(" %s = %s (%s)",d,dv,"configured")
+ tv = dv
+ elseif not permitted then
+ report(" %s = %s (%s)",d,tv,"frozen")
+ elseif tonumber(dv) >= tonumber(tv) then
+ report(" %s = %s (%s)",d,dv,"overloaded")
+ tv = dv
+ else
+ report(" %s = %s (%s)",d,tv,"preset kept")
+ end
+ elseif tv then
+ report(" %s = %s (%s)",d,tv,permitted and "preset" or "frozen")
+ else
+ report(" %s = <unset>",d)
+ end
+ if tv then
+ 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)))
+ logs.newline()
+end
+
+lua.registerfinalizer(makestub,"create stub file")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua
new file mode 100644
index 00000000000..f62396a8e10
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua
@@ -0,0 +1,184 @@
+if not modules then modules = { } end modules ['luat-cod'] = {
+ version = 1.001,
+ comment = "companion to luat-cod.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, loadfile = type, loadfile
+local match, gsub, find, format = string.match, string.gsub, string.find, string.format
+
+local texconfig, lua = texconfig, lua
+
+-- some basic housekeeping
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+texconfig.max_print_line = 100000
+texconfig.max_in_open = 1000
+
+-- registering bytecode chunks
+
+local bytecode = lua.bytecode or { }
+local bytedata = lua.bytedata or { }
+local bytedone = lua.bytedone or { }
+
+lua.bytecode = bytecode -- built in anyway
+lua.bytedata = bytedata
+lua.bytedone = bytedone
+
+lua.firstbytecode = 501
+lua.lastbytecode = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier
+
+function lua.registeredcodes()
+ return lua.lastbytecode - lua.firstbytecode + 1
+end
+
+-- no file.* functions yet
+
+function lua.registercode(filename,version)
+ local barename = gsub(filename,"%.[%a%d]+$","")
+ if barename == filename then filename = filename .. ".lua" end
+ local basename = match(barename,"^.+[/\\](.-)$") or barename
+ if not bytedone[basename] then
+ local code = environment.luafilechunk(filename)
+ if code then
+ bytedone[basename] = true
+ if environment.initex then
+ local n = lua.lastbytecode + 1
+ bytedata[n] = { barename, version or "0.000" }
+ bytecode[n] = code
+ lua.lastbytecode = n
+ end
+ elseif environment.initex then
+ texio.write_nl("\nerror loading file: " .. filename .. " (aborting)")
+ os.exit()
+ end
+ end
+end
+
+local finalizers = { }
+
+function lua.registerfinalizer(f,comment)
+ comment = comment or "unknown"
+ if type(f) == "function" then
+ finalizers[#finalizers+1] = { action = f, comment = comment }
+ else
+ print(format("\nfatal error: invalid finalizer, action: %s\n",comment))
+ os.exit()
+ end
+end
+
+function lua.finalize(logger)
+ for i=1,#finalizers do
+ local finalizer = finalizers[i]
+ finalizer.action()
+ if logger then
+ logger("finalize action: %s",finalizer.comment)
+ end
+ end
+end
+
+-- A first start with environments. This will be overloaded later.
+
+environment = environment or { }
+local environment = environment
+
+-- no string.unquoted yet
+
+local sourcefile = gsub(arg and arg[1] or "","^\"(.*)\"$","%1")
+local sourcepath = find(sourcefile,"/",1,true) and gsub(sourcefile,"/[^/]+$","") or ""
+local targetpath = "."
+
+-- delayed (via metatable):
+--
+-- environment.jobname = tex.jobname
+-- environment.version = tostring(tex.toks.contextversiontoks)
+
+environment.initex = tex.formatname == ""
+
+if not environment.luafilechunk then
+
+ function environment.luafilechunk(filename)
+ if sourcepath ~= "" then
+ filename = sourcepath .. "/" .. filename
+ end
+ local data = loadfile(filename)
+ texio.write("term and log","<",data and "+ " or "- ",filename,">")
+ if data then
+ data()
+ end
+ return data
+ end
+
+end
+
+if not environment.engineflags then -- raw flags
+
+ local engineflags = { }
+
+ for i=-10,#arg do
+ local a = arg[i]
+ if a then
+ local flag, content = match(a,"^%-%-([^=]+)=?(.-)$")
+ if flag then
+ engineflags[flag] = content or ""
+ end
+ end
+ end
+
+ environment.engineflags = engineflags
+
+end
+
+-- We need a few premature callbacks in the format generator. We
+-- also do this when the format is loaded as otherwise we get
+-- a kpse error when disabled. This is an engine issue that will
+-- be sorted out in due time.
+
+local isfile = lfs.isfile
+
+local function source_file(name)
+ local fullname = sourcepath .. "/" .. name
+ if isfile(fullname) then
+ return fullname
+ end
+ fullname = fullname .. ".tex"
+ if isfile(fullname) then
+ return fullname
+ end
+ if isfile(name) then
+ return name
+ end
+ name = name .. ".tex"
+ if isfile(name) then
+ return name
+ end
+ return nil
+end
+
+local function target_file(name)
+ return targetpath .. "/" .. name
+end
+
+local function find_read_file(id,name)
+ return source_file(name)
+end
+
+local function find_write_file(id,name)
+ return target_file(name)
+end
+
+local function open_read_file(name)
+ local f = io.open(name,'rb')
+ return {
+ reader = function()
+ return f:read("*line")
+ end
+ }
+end
+
+callback.register('find_read_file' , find_read_file )
+callback.register('open_read_file' , open_read_file )
+callback.register('find_write_file', find_write_file)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cod.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.mkiv
new file mode 100644
index 00000000000..9ce6161c32c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.mkiv
@@ -0,0 +1,79 @@
+%D \module
+%D [ file=luat-cod,
+%D version=2005.05.26,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Code,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \writestatus{loading}{ConTeXt Lua Macros / Code}
+
+\unprotect
+
+%D We cannot use the following due to the fact that existing usage
+%D demanded duplicating hashes.
+%D
+%D \starttyping
+%D \def\expanded#1{\normalexpanded{\noexpand#1}} % ## mess
+%D \stoptyping
+
+\newif\ifproductionrun
+
+%D Originally we compiled the \LUA\ files externally and loaded
+%D then at runtime, but when the amount grew, we realized that
+%D we needed away to store them in the format, which is what
+%D bytecode arrays do. And so the following is obsolete:
+%D
+%D \starttyping
+%D \setnewconstant\ctxluaembeddingmode \plusone
+%D
+%D 0 = external compilation and loading
+%D 1 = runtime compilation and embedding
+%D \stoptyping
+%D
+%D Allocation of \LUA\ engines has changed too. The original idea
+%D was to have multiple \LUA\ instances and it worked that way for
+%D several years. Hoewver in practice we used only one engine because
+%D scripts need to share data anyway. So eventually \LUATEX\ got only
+%D one instance. Because each call is reentrant there is not much
+%D danger for crashes.
+%D
+%D Most code here has changed after version 0.60 as part of adaption to
+%D new functionality. We no longer support the hooks for initializing
+%D code as this can be done at the \LUA\ end.
+
+% we can drop the \zerocount as it's default
+
+\let\ctxdirectlua \directlua
+\let\ctxlatelua \latelua
+\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens
+\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens
+\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens
+\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens
+\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens
+\def\ctxreport #1{\directlua{logs.writer[[#1]]}}
+
+%D Take your choice \unknown
+
+\let\ctxlua \ctxdirectlua
+\let\luacode \ctxdirectlua
+\let\lateluacode \ctxlatelua
+\let\directluacode\ctxdirectlua
+
+%D Reporting the version of \LUA\ that we use is done as follows:
+
+\edef\luaversion{\ctxwrite{_VERSION}}
+
+\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}}
+\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}}
+
+\registerctxluafile{luat-cod}{1.001}
+
+% \everydump\expandafter{\the\everydump\ctxlua{lua.finalize()}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua
new file mode 100644
index 00000000000..5f2a0d281a0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua
@@ -0,0 +1,184 @@
+ if not modules then modules = { } end modules ['luat-env'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A former version provided functionality for non embeded core scripts i.e. runtime
+-- library loading. Given the amount of Lua code we use now, this no longer makes
+-- 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 trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_lua = logs.reporter("resolvers","lua")
+
+local luautilities = utilities.lua
+local luasuffixes = luautilities.suffixes
+
+local texgettoks = tex and tex.gettoks
+
+environment = environment or { }
+local environment = environment
+
+-- environment
+
+local mt = {
+ __index = function(_,k)
+ if k == "version" then
+ local version = texgettoks and texgettoks("contextversiontoks")
+ if version and version ~= "" then
+ rawset(environment,"version",version)
+ return version
+ else
+ return "unknown"
+ end
+ elseif k == "kind" then
+ local kind = texgettoks and texgettoks("contextkindtoks")
+ if kind and kind ~= "" then
+ rawset(environment,"kind",kind)
+ return kind
+ else
+ return "unknown"
+ end
+ elseif k == "jobname" or k == "formatname" then
+ local name = tex and tex[k]
+ if name or name== "" then
+ rawset(environment,k,name)
+ return name
+ else
+ return "unknown"
+ end
+ elseif k == "outputfilename" then
+ local name = environment.jobname
+ rawset(environment,k,name)
+ return name
+ end
+ end
+}
+
+setmetatable(environment,mt)
+
+-- weird place ... depends on a not yet loaded module
+
+function environment.texfile(filename)
+ return resolvers.findfile(filename,'tex')
+end
+
+function environment.luafile(filename) -- needs checking
+ local resolved = resolvers.findfile(filename,'tex') or ""
+ if resolved ~= "" then
+ return resolved
+ end
+ resolved = resolvers.findfile(filename,'texmfscripts') or ""
+ if resolved ~= "" then
+ return resolved
+ end
+ return resolvers.findfile(filename,'luatexlibs') or ""
+end
+
+-- local function checkstrip(filename)
+-- local modu = modules[file.nameonly(filename)]
+-- return modu and modu.dataonly
+-- end
+
+local stripindeed = false directives.register("system.compile.strip", function(v) stripindeed = v end)
+
+local function strippable(filename)
+ if stripindeed then
+ local modu = modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+ else
+ return false
+ end
+end
+
+function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
+ filename = file.replacesuffix(filename, "lua")
+ local fullname = environment.luafile(filename)
+ if fullname and fullname ~= "" then
+ local data = luautilities.loadedluacode(fullname,strippable,filename) -- can be overloaded
+-- if trace_locating then
+-- report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
+-- elseif not silent then
+-- texio.write("<",data and "+ " or "- ",fullname,">")
+-- end
+ if not silent then
+ report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
+ end
+ return data
+ else
+-- if trace_locating then
+-- report_lua("unknown file %a",filename)
+-- end
+ if not silent then
+ report_lua("unknown file %a",filename)
+ end
+ return nil
+ end
+end
+
+-- the next ones can use the previous ones / combine
+
+function environment.loadluafile(filename, version)
+ local lucname, luaname, chunk
+ local basename = file.removesuffix(filename)
+ if basename == filename then
+ luaname = file.addsuffix(basename,luasuffixes.lua)
+ lucname = file.addsuffix(basename,luasuffixes.luc)
+ else
+ luaname = basename -- forced suffix
+ lucname = nil
+ end
+ -- when not overloaded by explicit suffix we look for a luc file first
+ local fullname = (lucname and environment.luafile(lucname)) or ""
+ if fullname ~= "" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
+ end
+ -- maybe: package.loaded[file.nameonly(fullname)] = true
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ -- we check of the version number of this chunk matches
+ local v = version -- can be nil
+ if modules and modules[filename] then
+ v = modules[filename].version -- new method
+ elseif versions and versions[filename] then
+ v = versions[filename] -- old method
+ end
+ if v == version then
+ return true
+ else
+ if trace_locating then
+ report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
+ end
+ environment.loadluafile(filename)
+ end
+ else
+ return true
+ end
+ end
+ fullname = (luaname and environment.luafile(luaname)) or ""
+ if fullname ~= "" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
+ end
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ if not chunk then
+ if trace_locating then
+ report_lua("unknown file %a",filename)
+ end
+ else
+ assert(chunk)()
+ return true
+ end
+ end
+ return false
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-exe.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-exe.lua
new file mode 100644
index 00000000000..d8d954a307b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-exe.lua
@@ -0,0 +1,73 @@
+if not modules then modules = { } end modules ['luat-exe'] = {
+ 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 not sandbox then require("l-sandbox") require("util-sbx") end -- for testing
+
+local type = type
+
+local executers = resolvers.executers or { }
+resolvers.executers = executers
+
+local disablerunners = sandbox.disablerunners
+local registerbinary = sandbox.registerbinary
+local registerroot = sandbox.registerroot
+
+local lpegmatch = lpeg.match
+
+local sc_splitter = lpeg.tsplitat(";")
+local cm_splitter = lpeg.tsplitat(",")
+
+local execution_mode directives.register("system.executionmode", function(v) execution_mode = v end)
+local execution_list directives.register("system.executionlist", function(v) execution_list = v end)
+local root_list directives.register("system.rootlist", function(v) root_list = v end)
+
+sandbox.initializer(function()
+ if execution_mode == "none" then
+ -- will be done later
+ elseif execution_mode == "list" then
+ if type(execution_list) == "string" then
+ execution_list = lpegmatch(cm_splitter,execution_list)
+ end
+ if type(execution_list) == "table" then
+ for i=1,#execution_list do
+ registerbinary(execution_list[i])
+ end
+ end
+ else
+ -- whatever else we have configured
+ end
+end)
+
+sandbox.initializer(function()
+ if type(root_list) == "string" then
+ root_list = lpegmatch(sc_splitter,root_list)
+ end
+ if type(root_list) == "table" then
+ for i=1,#root_list do
+ local entry = root_list[i]
+ if entry ~= "" then
+ registerroot(entry)
+ end
+ end
+ end
+end)
+
+sandbox.finalizer(function()
+ if execution_mode == "none" then
+ disablerunners()
+ end
+end)
+
+-- Let's prevent abuse of these libraries (built-in support still works).
+
+sandbox.finalizer(function()
+ mplib = nil
+ epdf = nil
+ zip = nil
+ fontloader = nil
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua
new file mode 100644
index 00000000000..2b083b58285
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['luat-fio'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local concat = table.concat
+local sequenced = table.sequenced
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+texconfig.max_print_line = 100000
+texconfig.max_in_open = 1000
+
+if not resolvers.instance then
+
+ resolvers.reset()
+
+ resolvers.instance.validfile = resolvers.validctxfile
+
+ -- we now load the file database as we might need files other than
+ -- tex and lua file on the given path
+
+ -- trackers.enable("resolvers.*")
+ resolvers.load()
+ -- trackers.disable("resolvers.*")
+
+ local findbinfile, loadbinfile = resolvers.findbinfile, resolvers.loadbinfile
+ local findtexfile, opentexfile = resolvers.findtexfile, resolvers.opentexfile
+
+ if callback then
+
+ local register = callbacks.register
+
+ local addsuffix = file.addsuffix
+ local join = file.join
+
+ local function findpk(font,dpi)
+ local dpi = dpi or 600 -- could take from resolution
+ -- <font>.pk
+ local name = addsuffix(font,"pk")
+ -- <dpi>/name.pk
+ local temp = join(dpi,name)
+ local okay = findbinfile(temp,"pk")
+ -- print(temp,okay)
+ if okay and okay ~= "" then
+ return okay
+ end
+ -- <dpi>.dpi/name.pk
+ local temp = join(dpi..".dpi",name)
+ local okay = findbinfile(temp,"pk")
+ -- print(temp,okay)
+ if okay and okay ~= "" then
+ return okay
+ end
+ -- <font>.<dpi>pk
+ local name = addsuffix(font,dpi.."pk")
+ -- name.<dpi>pk
+ local temp = name
+ local okay = findbinfile(temp,"pk")
+ -- print(temp,okay)
+ if okay and okay ~= "" then
+ return okay
+ end
+ -- <dpi>.dpi/name.<dpi>pk
+ local temp = join(dpi..".dpi",name)
+ local okay = findbinfile(temp,"pk")
+ -- print(temp,okay)
+ return okay or ""
+ end
+
+ -- 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('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)
+ register('find_image_file' , function(name) return findbinfile(name,"tex") end, true)
+ register('find_map_file' , function(name) return findbinfile(name,"map") end, true)
+ register('find_opentype_file' , function(name) return findbinfile(name,"otf") end, true)
+ register('find_output_file' , function(name) return name end, true)
+ register('find_pk_file' , findpk, true)
+ register('find_sfd_file' , function(name) return findbinfile(name,"sfd") end, true)
+ register('find_truetype_file' , function(name) return findbinfile(name,"ttf") end, true)
+ register('find_type1_file' , function(name) return findbinfile(name,"pfb") end, true)
+ register('find_vf_file' , function(name) return findbinfile(name,"vf") end, true)
+ register('find_cidmap_file' , function(name) return findbinfile(name,"cidmap") end, true)
+
+ register('read_data_file' , function(file) return loadbinfile(file,"tex") end, true)
+ register('read_enc_file' , function(file) return loadbinfile(file,"enc") end, true)
+ register('read_font_file' , function(file) return loadbinfile(file,"tfm") end, true)
+ -- format
+ -- image
+ register('read_map_file' , function(file) return loadbinfile(file,"map") end, true)
+ -- output
+ register('read_pk_file' , function(file) return loadbinfile(file,"pk") end, true) -- 600dpi/manfnt.720pk
+ register('read_sfd_file' , function(file) return loadbinfile(file,"sfd") end, true)
+ register('read_vf_file' , function(file) return loadbinfile(file,"vf" ) end, true)
+
+ -- register('find_font_file' , function(name) return findbinfile(name,"ofm") end, true)
+ -- register('find_vf_file' , function(name) return findbinfile(name,"ovf") end, true)
+
+ -- register('read_font_file' , function(file) return loadbinfile(file,"ofm") end, true)
+ -- register('read_vf_file' , function(file) return loadbinfile(file,"ovf") end, true)
+
+ -- register('read_opentype_file' , function(file) return loadbinfile(file,"otf") end, true)
+ -- register('read_truetype_file' , function(file) return loadbinfile(file,"ttf") end, true)
+ -- register('read_type1_file' , function(file) return loadbinfile(file,"pfb") end, true)
+ -- register('read_cidmap_file' , function(file) return loadbinfile(file,"cidmap") end, true)
+
+ register('find_write_file' , function(id,name) return name end, true)
+ register('find_format_file' , function(name) return name end, true)
+
+ end
+
+end
+
+statistics.register("resource resolver", function()
+ local scandata = resolvers.scandata()
+ return format("loadtime %s seconds, %s scans with scantime %s seconds, %s shared scans, %s found files, scanned paths: %s",
+ resolvers.loadtime(),
+ scandata.n,
+ scandata.time,
+ scandata.shared,
+ #resolvers.instance.foundintrees,
+ #scandata.paths > 0 and concat(scandata.paths," ") or "<none>"
+ )
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua
new file mode 100644
index 00000000000..9a86ef50e87
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua
@@ -0,0 +1,157 @@
+if not modules then modules = { } end modules ['luat-fmt'] = {
+ version = 1.001,
+ comment = "companion to mtxrun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local concat = table.concat
+local quoted = string.quoted
+local luasuffixes = utilities.lua.suffixes
+
+local report_format = logs.reporter("resolvers","formats")
+
+local function primaryflags() -- not yet ok
+ local trackers = environment.argument("trackers")
+ local directives = environment.argument("directives")
+ local flags = { }
+ if trackers and trackers ~= "" then
+ flags = { "--trackers=" .. quoted(trackers) }
+ end
+ if directives and directives ~= "" then
+ flags = { "--directives=" .. quoted(directives) }
+ end
+ if environment.argument("jit") then
+ flags = { "--jiton" }
+ end
+ return concat(flags," ")
+end
+
+-- The silent option is 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.
+
+function environment.make_format(name,silent)
+ local engine = environment.ownmain or "luatex"
+ -- change to format path (early as we need expanded paths)
+ local olddir = dir.current()
+ local path = caches.getwritablepath("formats",engine) or "" -- maybe platform
+ if path ~= "" then
+ lfs.chdir(path)
+ end
+ report_format("using format path %a",dir.current())
+ -- check source file
+ local texsourcename = file.addsuffix(name,"mkiv")
+ local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
+ if fulltexsourcename == "" then
+ texsourcename = file.addsuffix(name,"tex")
+ fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
+ end
+ if fulltexsourcename == "" then
+ report_format("no tex source file with name %a (mkiv or tex)",name)
+ lfs.chdir(olddir)
+ return
+ else
+ report_format("using tex source file %a",fulltexsourcename)
+ end
+ local texsourcepath = dir.expandname(file.dirname(fulltexsourcename)) -- really needed
+ -- check specification
+ local specificationname = file.replacesuffix(fulltexsourcename,"lus")
+ local fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
+ if fullspecificationname == "" then
+ specificationname = file.join(texsourcepath,"context.lus")
+ fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
+ end
+ if fullspecificationname == "" then
+ report_format("unknown stub specification %a",specificationname)
+ lfs.chdir(olddir)
+ return
+ end
+ local specificationpath = file.dirname(fullspecificationname)
+ -- load specification
+ local usedluastub = nil
+ local usedlualibs = dofile(fullspecificationname)
+ if type(usedlualibs) == "string" then
+ usedluastub = file.join(file.dirname(fullspecificationname),usedlualibs)
+ elseif type(usedlualibs) == "table" then
+ report_format("using stub specification %a",fullspecificationname)
+ local texbasename = file.basename(name)
+ local luastubname = file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname = file.addsuffix(texbasename,luasuffixes.luc)
+ -- pack libraries in stub
+ report_format("creating initialization file %a",luastubname)
+ utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
+ -- compile stub file (does not save that much as we don't use this stub at startup any more)
+ if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
+ report_format("using compiled initialization file %a",lucstubname)
+ usedluastub = lucstubname
+ else
+ report_format("using uncompiled initialization file %a",luastubname)
+ usedluastub = luastubname
+ end
+ else
+ report_format("invalid stub specification %a",fullspecificationname)
+ lfs.chdir(olddir)
+ return
+ end
+ -- generate format
+ local dump = os.platform=="unix" and "\\\\dump" or "\\dump"
+ if silent then
+ statistics.starttiming()
+ local command = format("%s --ini --interaction=batchmode %s --lua=%s %s %s > temp.log",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),dump)
+ local result = os.execute(command)
+ local runtime = statistics.stoptiming()
+ if result ~= 0 then
+ print(format("%s silent make > fatal error when making format %q",engine,name)) -- we use a basic print
+ else
+ print(format("%s silent make > format %q made in %.3f seconds",engine,name,runtime)) -- we use a basic print
+ end
+ os.remove("temp.log")
+ else
+ local command = format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),dump)
+ report_format("running command: %s\n",command)
+ os.execute(command)
+ end
+ -- remove related mem files
+ local pattern = file.removesuffix(file.basename(usedluastub)).."-*.mem"
+ -- report_format("removing related mplib format with pattern %a", pattern)
+ local mp = dir.glob(pattern)
+ if mp then
+ for i=1,#mp do
+ local name = mp[i]
+ report_format("removing related mplib format %a", file.basename(name))
+ os.remove(name)
+ end
+ end
+ lfs.chdir(olddir)
+end
+
+function environment.run_format(name,data,more)
+ if name and name ~= "" then
+ local engine = environment.ownmain or "luatex"
+ local barename = file.removesuffix(name)
+ local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
+ if fmtname == "" then
+ fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
+ end
+ fmtname = resolvers.cleanpath(fmtname)
+ if fmtname == "" then
+ report_format("no format with name %a",name)
+ else
+ local barename = file.removesuffix(name) -- expanded name
+ local luaname = file.addsuffix(barename,"luc")
+ if not lfs.isfile(luaname) then
+ luaname = file.addsuffix(barename,"lua")
+ end
+ if not lfs.isfile(luaname) then
+ report_format("using format name %a",fmtname)
+ report_format("no luc/lua file with name %a",barename)
+ else
+ local command = format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
+ report_format("running command: %s",command)
+ os.execute(command)
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua
new file mode 100644
index 00000000000..cd1f45692a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua
@@ -0,0 +1,28 @@
+if not modules then modules = { } end modules ['luat-ini'] = {
+ 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"
+}
+
+--[[ldx--
+<p>We cannot load anything yet. However what we will do us reserve a few tables.
+These can be used for runtime user data or third party modules and will not be
+cluttered by macro package code.</p>
+--ldx]]--
+
+userdata = userdata or { } -- for users (e.g. functions etc)
+thirddata = thirddata or { } -- only for third party modules
+moduledata = moduledata or { } -- only for development team
+documentdata = documentdata or { } -- for users (e.g. raw data)
+parametersets = parametersets or { } -- experimental for team
+
+table.setmetatableindex(moduledata,table.autokey)
+table.setmetatableindex(thirddata, table.autokey)
+
+if not global then
+ global = _G
+end
+
+LUATEXVERSION = status.luatex_version/100 + tonumber(status.luatex_revision)/1000
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv
new file mode 100644
index 00000000000..e19b72d14ea
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv
@@ -0,0 +1,283 @@
+%D \module
+%D [ file=luat-ini,
+%D version=2005.08.11,
+%D title=\CONTEXT\ Lua 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 Lua Macros / Initialization}
+
+\unprotect
+
+%D Loading lua code can be done using \type {startup.lua}. The following
+%D method uses the \TEX\ input file locator of kpse. At least we need to
+%D use that way of loading when we haven't yet define our own code, which
+%D we keep outside the format. We will keep code outside \TEX\ files as
+%D much as possible.
+
+\ifdefined\setnaturalcatcodes \else \let\setnaturalcatcodes\relax \fi
+\ifdefined\obeylualines \else \let\obeylualines \relax \fi
+\ifdefined\obeyluatokens \else \let\obeyluatokens \relax \fi
+
+%D A few more goodies:
+
+\let\stoplua \relax % tex catcodes
+\let\stopluacode\relax % lua catcodes
+
+% It might makes sense to have a \type {\directelua} so that we can avoid
+% the \type {\normalexpanded} around \type {\directlua}. Something to discuss
+% in the team.
+
+\normalprotected\def\startlua % \stoplua
+ {\begingroup
+ \obeylualines
+ \luat_start_lua_indeed}
+
+\def\luat_start_lua_indeed#1\stoplua
+ {\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default
+
+\normalprotected\def\startluacode % \stopluacode
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \luat_start_lua_code_indeed}
+
+\def\luat_start_lua_code_indeed#1\stopluacode
+ {\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default
+
+%D Some delayed definitions:
+
+\ifdefined\obeylines \else \let\obeylines \relax \fi
+\ifdefined\obeyedline \else \let\obeyedline \relax \fi
+\ifdefined\obeyspaces \else \let\obeyspaces \relax \fi
+\ifdefined\obeyedspace \else \let\obeyedspace \relax \fi
+
+\let\obeylualines\relax
+
+\newtoks\everyluacode
+
+\edef\lua_letter_backslash{\string\\}
+\edef\lua_letter_bar {\string\|} \edef\lua_letter_dash {\string\-}
+\edef\lua_letter_lparent {\string\(} \edef\lua_letter_rparent {\string\)}
+\edef\lua_letter_lbrace {\string\{} \edef\lua_letter_rbrace {\string\}}
+\edef\lua_letter_squote {\string\'} \edef\lua_letter_dquote {\string\"}
+\edef\lua_letter_n {\string\n} \edef\lua_letter_r {\string\r}
+\edef\lua_letter_f {\string\f} \edef\lua_letter_t {\string\t}
+\edef\lua_letter_a {\string\a} \edef\lua_letter_b {\string\b}
+\edef\lua_letter_v {\string\v} \edef\lua_letter_s {\string\s}
+\edef\lua_letter_one {\string\1} \edef\lua_letter_two {\string\2}
+\edef\lua_letter_three {\string\3} \edef\lua_letter_four {\string\4}
+\edef\lua_letter_five {\string\5} \edef\lua_letter_six {\string\6}
+\edef\lua_letter_seven {\string\7} \edef\lua_letter_eight {\string\8}
+\edef\lua_letter_nine {\string\9} \edef\lua_letter_zero {\string\0}
+
+\everyluacode {% \appendtoks
+ \let\\\lua_letter_backslash
+ \let\|\lua_letter_bar \let\-\lua_letter_dash
+ \let\(\lua_letter_lparent \let\)\lua_letter_rparent
+ \let\{\lua_letter_lbrace \let\}\lua_letter_rbrace
+ \let\'\lua_letter_squote \let\"\lua_letter_dquote
+ \let\n\lua_letter_n \let\r\lua_letter_r
+ \let\f\lua_letter_f \let\t\lua_letter_t
+ \let\a\lua_letter_a \let\b\lua_letter_b
+ \let\v\lua_letter_v \let\s\lua_letter_s
+ \let\1\lua_letter_one \let\2\lua_letter_two
+ \let\3\lua_letter_three \let\4\lua_letter_four
+ \let\5\lua_letter_five \let\6\lua_letter_six
+ \let\7\lua_letter_seven \let\8\lua_letter_eight
+ \let\9\lua_letter_nine \let\0\lua_letter_zero
+} % \to \everyluacode
+
+\normalprotected\def\obeyluatokens
+ {\setcatcodetable\luacatcodes
+ \the\everyluacode}
+
+\edef\luamajorversion{\ctxwrite{_MINORVERSION}}
+\edef\luaminorversion{\ctxwrite{_MAJORVERSION}}
+
+%D We need a way to pass strings safely to \LUA\ without the
+%D need for tricky escaping. Compare:
+%D
+%D \starttyping
+%D \ctxlua {something("anything tricky can go here")}
+%D \ctxlua {something([\luastringsep[anything tricky can go here]\luastringsep])}
+%D \stoptyping
+
+\def\luastringsep{===} % this permits \typefile{self} otherwise nested b/e sep problems
+
+\edef\!!bs{[\luastringsep[}
+\edef\!!es{]\luastringsep]}
+
+%D We have a the following available as primitive so there is no need
+%D for it:
+%D
+%D \starttyping
+%D \edef\luaescapestring#1{\!!bs#1\!!es}
+%D \stoptyping
+
+\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}}
+\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
+\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}}
+\def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax}
+\def\getdocumentargument #1{\clf_getdocumentargument{#1}{}}
+\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
+\def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}}
+
+% seldom used so no need for speedy variants:
+
+\def\doifelsedocumentargument #1{\doifelsesomething{\clf_getdocumentargument{#1}}}
+\def\doifdocumentargument #1{\doifsomething {\clf_getdocumentargument{#1}}}
+\def\doifnotdocumentargument #1{\doifnothing {\clf_getdocumentargument{#1}}}
+\def\doifelsedocumentfilename #1{\doifelsesomething{\clf_getdocumentfilename\numexpr#1\relax}}
+\def\doifdocumentfilename #1{\doifsomething {\clf_getdocumentfilename\numexpr#1\relax}}
+\def\doifnotdocumentfilename #1{\doifnothing {\clf_getdocumentfilename\numexpr#1\relax}}
+
+\let\doifdocumentargumentelse\doifelsedocumentargument
+\let\doifdocumentfilenameelse\doifelsedocumentfilename
+
+%D A handy helper:
+
+\def\luaexpanded#1{\luaescapestring\expandafter{\normalexpanded{#1}}}
+
+%D Experimental:
+
+\normalprotected\def\startluaparameterset[#1]%
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \luat_start_lua_parameter_set{#1}}
+
+\def\luat_start_lua_parameter_set#1#2\stopluaparameterset
+ {\ctxlua{parametersets["#1"]={#2}}%
+ \endgroup}
+
+\let\stopluaparameterset\relax
+
+\def\luaparameterset#1#2{\ctxlua{parametersets["#1"]={#2} context("#1")}}
+
+% todo: \mergeparameterset
+
+% usage:
+%
+% \startluaparameterset [u3d:myset:display:1]
+% toolbar=false,
+% tree=true
+% \stopluaparameterset
+%
+% option=u3d:myset:display:1
+%
+% or:
+%
+% option=\luaparameterset{u3d:myset:display:1}{toolbar=false,tree=true}
+
+%D A Handy helper:
+
+\def\luaconditional#1{\ifcase#1tru\else fals\fi e}
+
+%D Goodie:
+%D
+%D \starttyping
+%D \ctxluacode{context("%0.5f",1/3)}
+%D \stoptyping
+
+\normalprotected\def\ctxluacode
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \catcode\leftbraceasciicode \plusone
+ \catcode\rightbraceasciicode\plustwo
+ \afterassignment\luat_lua_code
+ \scratchtoks=}
+
+% Hm, are we sure that the \* commands work out okay here? We could probably
+% use \setcatcodetable\luacatcodes instead of \obeyluatokens now.
+
+\def\luat_lua_code
+ {\normalexpanded{\endgroup\noexpand\directlua\expandafter{\the\scratchtoks}}} % \zerocount is default
+
+% \startctxfunction MyFunctionA
+% context(" A1 ")
+% \stopctxfunction
+%
+% \startctxfunctiondefinition MyFunctionB
+% context(" B2 ")
+% \stopctxfunctiondefinition
+%
+% \starttext
+% \dorecurse{10000}{\ctxfunction{MyFunctionA}} \page
+% \dorecurse{10000}{\MyFunctionB} \page
+% \dorecurse{10000}{\ctxlua{context(" C3 ")}} \page
+% \stoptext
+
+\installsystemnamespace{ctxfunction}
+
+\normalprotected\def\startctxfunctiondefinition #1 %
+ {\begingroup \obeylualines \obeyluatokens \luat_start_lua_function_definition_indeed{#1}}
+
+\installsystemnamespace{luafunction}
+
+\def\luat_start_lua_function_definition_indeed#1#2\stopctxfunctiondefinition
+ {\endgroup
+ \expandafter\chardef\csname\??luafunction#1\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es)}\relax
+ \expandafter\edef\csname#1\endcsname{\noexpand\luafunction\csname\??luafunction#1\endcsname}}
+
+\normalprotected\def\setctxluafunction#1#2% experiment
+ {\expandafter\chardef\csname\??luafunction#1\endcsname#2\relax
+ \expandafter\edef\csname#1\endcsname{\noexpand\luafunction\csname\??luafunction#1\endcsname}}
+
+\let\stopctxfunctiondefinition\relax
+
+\normalprotected\def\startctxfunction #1 %
+ {\begingroup \obeylualines \obeyluatokens \luat_start_lua_function_indeed{#1}}
+
+\def\luat_start_lua_function_indeed#1#2\stopctxfunction
+ {\endgroup\expandafter\edef\csname\??ctxfunction#1\endcsname{\noexpand\luafunction\ctxcommand{ctxfunction(\!!bs#2\!!es)}\relax}}
+
+\let\stopctxfunction\relax
+
+\def\ctxfunction#1%
+ {\csname\??ctxfunction#1\endcsname}
+
+% In theory this is faster due to the call not being wrapped in a function but in
+% practice the speedup can't be noticed. The actions called for often have lots of
+% lookups so an extra one doesn't matter much. The kind of calls differs a lot per
+% document and often there are other ways to optimize a style. For instance we can
+% gain a lot when defining a font, but when a frozen definition is used that gain
+% gets completely lost. For some calls (take list writers) it can get worse if only
+% because readability gets worse and passing is already efficient due to selective
+% flushing, while with the token scanners one has to scan all of them.
+
+% \startctxfunctiondefinition foo commands.foo() \stopctxfunctiondefinition
+%
+% \installctxfunction\foo{commands.foo}
+
+% This is a forward definition:
+
+% \def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
+% {\expandafter\syst_helpers_checked_stripped_csname\string#1}
+%
+% \def\syst_helpers_checked_stripped_csname#1%
+% {\if\noexpand#1\letterbackslash\else#1\fi}
+
+\normalprotected\def\installctxfunction#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{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
+
+\normalprotected\def\installctxscanner#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{\noexpand\luafunction\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}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-iop.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-iop.lua
new file mode 100644
index 00000000000..e1772af4e90
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-iop.lua
@@ -0,0 +1,24 @@
+if not modules then modules = { } end modules ['luat-iop'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local cleanedpathlist = resolvers.cleanedpathlist
+local registerroot = sandbox.registerroot
+
+sandbox.initializer(function()
+ local function register(str,mode)
+ local trees = cleanedpathlist(str)
+ for i=1,#trees do
+ registerroot(trees[i],mode)
+ end
+ end
+ register("TEXMF","read")
+ register("TEXINPUTS","read")
+ register("MPINPUTS","read")
+ -- register("TEXMFCACHE","write")
+ registerroot(".","write")
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv
new file mode 100644
index 00000000000..cbe15c8a1cb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv
@@ -0,0 +1,91 @@
+%D \module
+%D [ file=luat-lib,
+%D version=2006.09.11,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Libraries,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Lua Macros / Libraries}
+
+\registerctxluafile{util-str}{1.001}
+\registerctxluafile{util-tab}{1.001}
+\registerctxluafile{util-fil}{1.001}
+\registerctxluafile{util-sac}{1.001}
+\registerctxluafile{util-sto}{1.001} % could also be done in trac-deb.mkiv
+\registerctxluafile{util-pck}{1.001}
+\registerctxluafile{util-seq}{1.001}
+%registerctxluafile{util-mrg}{1.001} % not needed in context itself, only mtxrun
+%registerctxluafile{util-lua}{1.001} % moved
+\registerctxluafile{util-prs}{1.001}
+\registerctxluafile{util-fmt}{1.001}
+\registerctxluafile{util-dim}{1.001}
+
+%registerctxluafile{trac-inf}{1.001}
+\registerctxluafile{trac-set}{1.001}
+\registerctxluafile{trac-log}{1.001}
+\registerctxluafile{trac-inf}{1.001}
+%registerctxluafile{trac-pro}{1.001}
+\registerctxluafile{util-lua}{1.001}
+\registerctxluafile{util-deb}{1.001} % could also be done in trac-deb.mkiv
+
+\registerctxluafile{util-tpl}{1.001} % needs tracker
+
+\registerctxluafile{util-sta}{1.001}
+
+\registerctxluafile{util-sbx}{1.001} % needs tracker and templates
+
+\registerctxluafile{data-ini}{1.001}
+\registerctxluafile{data-exp}{1.001}
+\registerctxluafile{data-env}{1.001}
+\registerctxluafile{data-tmp}{1.001}
+\registerctxluafile{data-met}{1.001}
+\registerctxluafile{data-res}{1.001}
+\registerctxluafile{data-inp}{1.001}
+\registerctxluafile{data-out}{1.001}
+\registerctxluafile{data-fil}{1.001}
+
+\registerctxluafile{data-pre}{1.001}
+\registerctxluafile{data-tex}{1.001}
+\registerctxluafile{data-vir}{1.001}
+\registerctxluafile{data-bin}{1.001}
+\registerctxluafile{data-zip}{1.001}
+%registerctxluafile{data-crl}{1.001}
+\registerctxluafile{data-sch}{1.001}
+\registerctxluafile{data-tre}{1.001}
+\registerctxluafile{data-lua}{1.001}
+\registerctxluafile{data-ctx}{1.001}
+\registerctxluafile{data-con}{1.001}
+\registerctxluafile{data-use}{1.001}
+\registerctxluafile{data-aux}{1.001}
+
+\registerctxluafile{util-lib}{1.001}
+
+\registerctxluafile{luat-cbk}{1.001}
+\registerctxluafile{luat-run}{1.001}
+\registerctxluafile{luat-fio}{1.001}
+\registerctxluafile{luat-cnf}{1.001}
+\registerctxluafile{luat-lua}{1.001}
+\registerctxluafile{luat-sto}{1.001}
+\registerctxluafile{luat-ini}{1.001}
+\registerctxluafile{util-env}{1.001}
+\registerctxluafile{luat-env}{1.001}
+\registerctxluafile{luat-exe}{1.001} % simplified
+\registerctxluafile{luat-iop}{1.001} % simplified
+\registerctxluafile{luat-bwc}{1.001}
+\registerctxluafile{trac-lmx}{1.001} % might become l-lmx or luat-lmx
+\registerctxluafile{luat-mac}{1.001}
+%registerctxluafile{luat-prp}{1.001} % for the moment of not much use
+
+\registerctxluafile{lxml-tab}{1.001}
+\registerctxluafile{lxml-lpt}{1.001}
+\registerctxluafile{lxml-xml}{1.001}
+\registerctxluafile{lxml-aux}{1.001}
+\registerctxluafile{lxml-mis}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-lua.lua
new file mode 100644
index 00000000000..972004e887d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-lua.lua
@@ -0,0 +1,45 @@
+if not modules then modules = { } end modules ['luat-lua'] = {
+ 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 lua then do
+
+ local delayed = { }
+
+ function lua.flushdelayed(...)
+ local t = delayed
+ delayed = { }
+ for i=1, #t do
+ t[i](...)
+ end
+ end
+
+ function lua.delay(f)
+ delayed[#delayed+1] = f
+ end
+
+ function lua.flush(...)
+ context.directlua("lua.flushdelayed(%,t)",{...})
+ end
+
+end end
+
+-- See mk.pdf for an explanation of the following code:
+--
+-- function test(n)
+-- lua.delay(function(...)
+-- context("pi: %s %s %s",...)
+-- context.par()
+-- end)
+-- lua.delay(function(...)
+-- context("more pi: %s %s %s",...)
+-- context.par()
+-- end)
+-- context("\\setbox0=\\hbox{%s}",math.pi*n)
+-- local box = tex.box[0]
+-- lua.flush(box.width,box.height,box.depth)
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-mac.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-mac.lua
new file mode 100644
index 00000000000..4274fe9f9e1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-mac.lua
@@ -0,0 +1,439 @@
+if not modules then modules = { } end modules ['luat-mac'] = {
+ 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"
+}
+
+-- Sometimes we run into situations like:
+--
+-- \def\foo#1{\expandafter\def\csname#1\endcsname}
+--
+-- As this confuses the parser, the following should be used instead:
+--
+-- \def\foo#1{\expandafter\normaldef\csname#1\endcsname}
+
+local P, V, S, R, C, Cs, Cmt, Carg = lpeg.P, lpeg.V, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.Cmt, lpeg.Carg
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+
+local insert, remove = table.insert, table.remove
+local rep, sub = string.rep, string.sub
+local setmetatable = setmetatable
+local filesuffix = file.suffix
+local convertlmxstring = lmx and lmx.convertstring
+
+local pushtarget, poptarget = logs.pushtarget, logs.poptarget
+
+local report_macros = logs.reporter("interface","macros")
+
+local stack, top, n, hashes = { }, nil, 0, { }
+
+local function set(s)
+ if top then
+ n = n + 1
+ if n > 9 then
+ report_macros("number of arguments > 9, ignoring %s",s)
+ else
+ local ns = #stack
+ local h = hashes[ns]
+ if not h then
+ h = rep("#",2^(ns-1))
+ hashes[ns] = h
+ end
+ local m = h .. n
+ top[s] = m
+ return m
+ end
+ end
+end
+
+local function get(s)
+ if not top then
+ report_macros("keeping #%s, no stack",s)
+ return "#" .. s -- can be lua
+ end
+ local m = top[s]
+ if m then
+ return m
+ else
+ report_macros("keeping #%s, not on stack",s)
+ return "#" .. s -- quite likely an error
+ end
+end
+
+local function push()
+ top = { }
+ n = 0
+ local s = stack[#stack]
+ if s then
+ setmetatable(top,{ __index = s })
+ end
+ insert(stack,top)
+end
+
+local function pop()
+ top = remove(stack)
+end
+
+local leftbrace = P("{") -- will be in patterns
+local rightbrace = P("}")
+local escape = P("\\")
+
+local space = patterns.space
+local spaces = space^1
+local newline = patterns.newline
+local nobrace = 1 - leftbrace - rightbrace
+
+local longleft = leftbrace -- P("(")
+local longright = rightbrace -- P(")")
+local nolong = 1 - longleft - longright
+
+local utf8character = P(1) * R("\128\191")^1 -- unchecked but fast
+
+local name = (R("AZ","az") + utf8character)^1
+local csname = (R("AZ","az") + S("@?!_:-*") + utf8character)^1
+local longname = (longleft/"") * (nolong^1) * (longright/"")
+local variable = P("#") * Cs(name + longname)
+local escapedname = escape * csname
+local definer = escape * (P("def") + S("egx") * P("def")) -- tex
+local setter = escape * P("set") * (P("u")^-1 * S("egx")^-1) * P("value") -- context specific
+--- + escape * P("install") * (1-P("handler"))^1 * P("handler") -- context specific
+local startcode = P("\\starttexdefinition") -- context specific
+local stopcode = P("\\stoptexdefinition") -- context specific
+local anything = patterns.anything
+local always = patterns.alwaysmatched
+
+local definer = escape * (P("u")^-1 * S("egx")^-1 * P("def")) -- tex
+
+-- The comment nilling can become an option but it nicely compensates the Lua
+-- parsing here with less parsing at the TeX end. We keep lines so the errors
+-- get reported all right, but comments are never seen there anyway. We keep
+-- comment that starts inline as it can be something special with a % (at some
+-- point we can do that as well, esp if we never use \% or `% somewhere
+-- unpredictable). We need to skip comments anyway. Hm, too tricky, this
+-- stripping as we can have Lua code etc.
+
+local commenttoken = P("%")
+local crorlf = S("\n\r")
+----- commentline = commenttoken * ((Carg(1) * C((1-crorlf)^0))/function(strip,s) return strip and "" or s end)
+local commentline = commenttoken * ((1-crorlf)^0)
+local leadingcomment = (commentline * crorlf^1)^1
+local furthercomment = (crorlf^1 * commentline)^1
+
+local pushlocal = always / push
+local poplocal = always / pop
+local declaration = variable / set
+local identifier = variable / get
+
+local argument = P { leftbrace * ((identifier + V(1) + (1 - leftbrace - rightbrace))^0) * rightbrace }
+
+local function matcherror(str,pos)
+ report_macros("runaway definition at: %s",sub(str,pos-30,pos))
+end
+
+local csname_endcsname = P("\\csname") * (identifier + (1 - P("\\endcsname")))^1
+
+local grammar = { "converter",
+ texcode = pushlocal
+ * startcode
+ * spaces
+ * (csname * spaces)^1 -- new: multiple, new:csname instead of name
+ -- * (declaration + furthercomment + (1 - newline - space))^0
+ * ((declaration * (space^0/""))^1 + furthercomment + (1 - newline - space))^0 -- accepts #a #b #c
+ * V("texbody")
+ * stopcode
+ * poplocal,
+ texbody = (
+leadingcomment -- new per 2015-03-03 (ugly)
++
+ V("definition")
+ + identifier
+ + V("braced")
+ + (1 - stopcode)
+ )^0,
+ definition = pushlocal
+ * definer
+ * spaces^0
+ * escapedname
+-- * (declaration + furthercomment + commentline + (1-leftbrace))^0
+ * (declaration + furthercomment + commentline + csname_endcsname + (1-leftbrace))^0
+ * V("braced")
+ * poplocal,
+ setcode = pushlocal
+ * setter
+ * argument
+ * (declaration + furthercomment + commentline + (1-leftbrace))^0
+ * V("braced")
+ * poplocal,
+ braced = leftbrace
+ * ( V("definition")
+ + identifier
+ + V("setcode")
+ + V("texcode")
+ + V("braced")
+ + furthercomment
+ + leadingcomment -- new per 2012-05-15 (message on mailing list)
+ + nobrace
+ )^0
+ -- * rightbrace^-1, -- the -1 catches errors
+ * (rightbrace + Cmt(always,matcherror)),
+
+ pattern = leadingcomment
+ + V("definition")
+ + V("setcode")
+ + V("texcode")
+ + furthercomment
+ + anything,
+
+ converter = V("pattern")^1,
+}
+
+local parser = Cs(grammar)
+
+local checker = P("%") * (1 - newline - P("macros"))^0
+ * P("macros") * space^0 * P("=") * space^0 * C(patterns.letter^1)
+
+-- maybe namespace
+
+local macros = { } resolvers.macros = macros
+
+function macros.preprocessed(str,strip)
+ return lpegmatch(parser,str,1,strip)
+end
+
+function macros.convertfile(oldname,newname) -- beware, no testing on oldname == newname
+ local data = resolvers.loadtexfile(oldname)
+ data = interfaces.preprocessed(data) or "" -- interfaces not yet defined
+ io.savedata(newname,data)
+end
+
+function macros.version(data)
+ return lpegmatch(checker,data)
+end
+
+-- function macros.processmkvi(str,filename)
+-- if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+-- local oldsize = #str
+-- str = lpegmatch(parser,str,1,true) or str
+-- pushtarget("log")
+-- report_macros("processed mkvi file %a, delta %s",filename,oldsize-#str)
+-- poptarget("log")
+-- end
+-- return str
+-- end
+--
+-- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+-- the document variables hack is temporary
+
+local processors = { }
+
+function processors.mkvi(str,filename)
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkvi file %a, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkix(str,filename) -- we could intercept earlier so that caching works better
+ if not document then -- because now we hash the string as well as the
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ pushtarget("log")
+ report_macros("processed mkix file %a, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkxi(str,filename)
+ if not document then
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkxi file %a, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function macros.processmk(str,filename)
+ if filename then
+ local suffix = filesuffix(filename)
+ local processor = processors[suffix] or processors[lpegmatch(checker,str)]
+ if processor then
+ str = processor(str,filename)
+ end
+ end
+ return str
+end
+
+function macros.processmkvi(str,filename)
+ if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkvi file %a, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ end
+ return str
+end
+
+local sequencers = utilities.sequencers
+
+if sequencers then
+
+ sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmk")
+ sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+end
+
+-- bonus
+
+if resolvers.schemes then
+
+ local function handler(protocol,name,cachename)
+ local hashed = url.hashed(name)
+ local path = hashed.path
+ if path and path ~= "" then
+ local str = resolvers.loadtexfile(path)
+ if filesuffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ -- already done automatically
+ io.savedata(cachename,str)
+ else
+ local result = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed scheme %a, delta %s",filename,#str-#result)
+ poptarget("log")
+ io.savedata(cachename,result)
+ end
+ end
+ return cachename
+ end
+
+ resolvers.schemes.install('mkvi',handler,1) -- this will cache !
+
+end
+
+-- print(macros.preprocessed(
+-- [[
+-- \starttexdefinition unexpanded test #aa #bb #cc
+-- test
+-- \stoptexdefinition
+-- ]]))
+
+-- print(macros.preprocessed([[\checked \def \bla #bla{bla#{bla}}]]))
+-- print(macros.preprocessed([[\def\bla#bla{#{bla}bla}]]))
+-- print(macros.preprocessed([[\def\blä#{blá}{blà:#{blá}}]]))
+-- print(macros.preprocessed([[\def\blä#bla{blà:#bla}]]))
+-- print(macros.preprocessed([[\setvalue{xx}#bla{blà:#bla}]]))
+-- print(macros.preprocessed([[\def\foo#bar{\setvalue{xx#bar}{#bar}}]]))
+-- print(macros.preprocessed([[\def\bla#bla{bla:#{bla}}]]))
+-- print(macros.preprocessed([[\def\bla_bla#bla{bla:#bla}]]))
+-- print(macros.preprocessed([[\def\test#oeps{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\test_oeps#oeps{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\test#oeps{test:#{oeps}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\x[#a][#b][#c]{\setvalue{\y{#a}\z{#b}}{#c}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
+-- print(macros.preprocessed([[% test
+-- \def\test#oeps{#oeps} % {test}
+-- % test
+--
+-- % test
+-- two
+-- %test]]))
+-- print(macros.preprocessed([[
+-- \def\scrn_button_make_normal#namespace#current#currentparameter#text%
+-- {\ctxlua{structures.references.injectcurrentset(nil,nil)}%
+-- % \hbox attr \referenceattribute \lastreferenceattribute {\localframed[#namespace:#current]{#text}}}
+-- \hbox attr \referenceattribute \lastreferenceattribute {\directlocalframed[#namespace:#current]{#text}}}
+-- ]]))
+--
+-- print(macros.preprocessed([[
+-- \def\definefoo[#name]%
+-- {\setvalue{start#name}{\dostartfoo{#name}}}
+-- \def\dostartfoo#name%
+-- {\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname{#name : #content}%
+-- \next}
+-- \def\dostartfoo#name%
+-- {\normalexpanded{\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname}{#name : #content}%
+-- \next}
+-- ]]))
+--
+-- print(macros.preprocessed([[
+-- \def\dosomething#content{%%% {{
+-- % { }{{ %%
+-- \bgroup\italic#content\egroup
+-- }
+-- ]]))
+--
+-- print(macros.preprocessed([[
+-- \unexpanded\def\start#tag#stoptag%
+-- {\initialize{#tag}%
+-- \normalexpanded
+-- {\def\yes[#one]#two\csname\e!stop#stoptag\endcsname{\command_yes[#one]{#two}}%
+-- \def\nop #one\csname\e!stop#stoptag\endcsname{\command_nop {#one}}}%
+-- \doifelsenextoptional\yes\nop}
+-- ]]))
+--
+-- print(macros.preprocessed([[
+-- \normalexpanded{\long\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}%
+-- {\def\currentinteractionmenu{#tag}%
+-- \expandafter\settrue\csname\??menustate\interactionmenuparameter\c!category\endcsname
+-- \setinteractionmenuparameter\c!menu{#content}}
+-- ]]))
+--
+-- Just an experiment:
+--
+-- \catcode\numexpr"10FF25=\commentcatcode %% > 110000 is invalid
+--
+-- We could have a push/pop mechanism but binding to txtcatcodes
+-- is okay too.
+
+local txtcatcodes = false -- also signal and yet unknown
+
+local commentsignal = utf.char(0x10FF25)
+
+local encodecomment = P("%%") / commentsignal --
+----- encodepattern = Cs(((1-encodecomment)^0 * encodecomment)) -- strips but not nice for verbatim
+local encodepattern = Cs((encodecomment + 1)^0)
+local decodecomment = P(commentsignal) / "%%%%" -- why doubles here?
+local decodepattern = Cs((decodecomment + 1)^0)
+
+function resolvers.macros.encodecomment(str)
+ if txtcatcodes and tex.catcodetable == txtcatcodes then
+ return lpegmatch(encodepattern,str) or str
+ else
+ return str
+ end
+end
+
+function resolvers.macros.decodecomment(str) -- normally not needed
+ return txtcatcodes and lpegmatch(decodepattern,str) or str
+end
+
+-- resolvers.macros.commentsignal = commentsignal
+-- resolvers.macros.encodecommentpattern = encodepattern
+-- resolvers.macros.decodecommentpattern = decodepattern
+
+function resolvers.macros.enablecomment(thecatcodes)
+ if not txtcatcodes then
+ txtcatcodes = thecatcodes or catcodes.numbers.txtcatcodes
+ utilities.sequencers.appendaction(resolvers.openers.helpers.textlineactions,"system","resolvers.macros.encodecomment")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua
new file mode 100644
index 00000000000..7e81350f0f2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua
@@ -0,0 +1,236 @@
+if not modules then modules = { } end modules ['luat-run'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find = string.format, string.find
+local insert, remove = table.insert, table.remove
+
+-- trace_job_status is also controlled by statistics.enable that is set via the directive system.nostatistics
+
+local trace_lua_dump = false trackers.register("system.dump", function(v) trace_lua_dump = v end)
+local trace_temp_files = false trackers.register("system.tempfiles", function(v) trace_temp_files = v end)
+local trace_job_status = true trackers.register("system.jobstatus", function(v) trace_job_status = v end)
+local trace_tex_status = false trackers.register("system.texstatus", function(v) trace_tex_status = v end)
+
+local report_lua = logs.reporter("system","lua")
+local report_tex = logs.reporter("system","status")
+local report_tempfiles = logs.reporter("resolvers","tempfiles")
+
+luatex = luatex or { }
+local luatex = luatex
+
+local startactions = { }
+local stopactions = { }
+local dumpactions = { }
+
+function luatex.registerstartactions(...) insert(startactions, ...) end
+function luatex.registerstopactions (...) insert(stopactions, ...) end
+function luatex.registerdumpactions (...) insert(dumpactions, ...) end
+
+local function start_run()
+ if logs.start_run then
+ logs.start_run()
+ end
+ for i=1,#startactions do
+ startactions[i]()
+ end
+end
+
+local function stop_run()
+ for i=1,#stopactions do
+ stopactions[i]()
+ end
+ if trace_job_status then
+ statistics.show()
+ end
+ if trace_tex_status then
+ for k, v in table.sortedhash(status.list()) do
+ report_tex("%S=%S",k,v)
+ end
+ end
+ if logs.stop_run then
+ logs.stop_run()
+ end
+end
+
+local function start_shipout_page()
+ logs.start_page_number()
+end
+
+local function stop_shipout_page()
+ logs.stop_page_number()
+end
+
+local function report_output_pages()
+end
+
+local function report_output_log()
+end
+
+-- local function show_open()
+-- end
+
+-- local function show_close()
+-- end
+
+local function pre_dump_actions()
+ for i=1,#dumpactions do
+ dumpactions[i]()
+ end
+ lua.finalize(trace_lua_dump and report_lua or nil)
+ -- statistics.savefmtstatus("\jobname","\contextversion","context.tex")
+end
+
+-- this can be done later
+
+callbacks.register('start_run', start_run, "actions performed at the beginning of a run")
+callbacks.register('stop_run', stop_run, "actions performed at the end of a run")
+
+---------.register('show_open', show_open, "actions performed when opening a file")
+---------.register('show_close', show_close, "actions performed when closing a file")
+
+callbacks.register('report_output_pages', report_output_pages, "actions performed when reporting pages")
+callbacks.register('report_output_log', report_output_log, "actions performed when reporting log file")
+
+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")
+
+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
+
+-- an example:
+
+local tempfiles = { }
+
+function luatex.registertempfile(name,extrasuffix,keep) -- namespace might change
+ if extrasuffix then
+ name = name .. ".mkiv-tmp" -- maybe just .tmp
+ end
+ if trace_temp_files and not tempfiles[name] then
+ report_tempfiles("registering temporary file %a",name)
+ end
+ tempfiles[name] = keep or false
+ return name
+end
+
+function luatex.cleanuptempfiles()
+ for name, keep in next, tempfiles do
+ if not keep then
+ if trace_temp_files then
+ report_tempfiles("removing temporary file %a",name)
+ end
+ os.remove(name)
+ end
+ end
+ tempfiles = { }
+end
+
+luatex.registerstopactions(luatex.cleanuptempfiles)
+
+-- for the moment here
+
+local report_system = logs.reporter("system")
+local synctex = 0
+
+directives.register("system.synctex", function(v)
+ synctex = tonumber(v) or (toboolean(v,true) and 1) or (v == "zipped" and 1) or (v == "unzipped" and -1) or 0
+ if synctex ~= 0 then
+ report_system("synctex functionality is enabled (%s), expect runtime overhead!",tostring(synctex))
+ else
+ report_system("synctex functionality is disabled!")
+ end
+ tex.normalsynctex = synctex
+end)
+
+statistics.register("synctex tracing",function()
+ if synctex ~= 0 then
+ return "synctex has been enabled (extra log file generated)"
+ end
+end)
+
+-- 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")
+
+local register = callbacks.register
+
+local level = 0
+local total = 0
+local stack = { }
+local all = false
+
+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 "?")
+ end
+ elseif find(name,"virtual://") then
+ insert(stack,false)
+ else
+ insert(stack,name)
+ total = total + 1
+ level = level + 1
+ report_open("%i > %i > %s",level,total,name or "?")
+ 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 "?")
+ level = level - 1
+ end
+ end
+end
+
+local function report_none()
+end
+
+register("start_file",report_start)
+register("stop_file", report_stop)
+
+directives.register("system.reportfiles", function(v)
+ if v == "noresources" then
+ all = false
+ register("start_file",report_start)
+ register("stop_file", report_stop)
+ elseif toboolean(v) or v == "all" then
+ all = true
+ register("start_file",report_start)
+ register("stop_file", report_stop)
+ elseif v == "traditional" then
+ register("start_file",nil)
+ register("stop_file", nil)
+ else
+ register("start_file",report_none)
+ register("stop_file", report_none)
+ end
+end)
+
+-- start_run doesn't work
+
+-- luatex.registerstartactions(function()
+-- if environment.arguments.sandbox then
+-- sandbox.enable()
+-- end
+-- end)
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua
new file mode 100644
index 00000000000..9342a4b3375
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua
@@ -0,0 +1,11 @@
+-- This is just a loader. The package handler knows about the TEX tree.
+
+-- require "luatex/lua/socket.lua"
+-- require "luatex/lua/ltn12.lua"
+-- require "luatex/lua/mime.lua"
+-- require "luatex/lua/socket/http.lua"
+-- require "luatex/lua/socket/url.lua"
+-- require "luatex/lua/socket/tp.lua"
+-- require "luatex/lua/socket/ftp.lua"
+
+-- "luatex/lua/socket/smtp.lua"
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-sta.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-sta.lua
new file mode 100644
index 00000000000..8b58774d357
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-sta.lua
@@ -0,0 +1,211 @@
+if not modules then modules = { } end modules ['luat-sta'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this code is used in the updater
+
+local gmatch, match = string.gmatch, string.match
+local type = type
+
+states = states or { }
+local states = states
+
+states.data = states.data or { }
+local data = states.data
+
+states.hash = states.hash or { }
+local hash = states.hash
+
+states.tag = states.tag or ""
+states.filename = states.filename or ""
+
+function states.save(filename,tag)
+ tag = tag or states.tag
+ filename = file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n" ..
+ "-- state tag : " .. tag .. "\n\n" ..
+ table.serialize(data[tag or states.tag] or {},true)
+ )
+end
+
+function states.load(filename,tag)
+ states.filename = filename
+ states.tag = tag or "whatever"
+ states.filename = file.addsuffix(states.filename,'lus')
+ data[states.tag], hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+end
+
+local function set_by_tag(tag,key,value,default,persistent)
+ local d, h = data[tag], hash[tag]
+ if d then
+ if type(d) == "table" then
+ local dkey, hkey = key, key
+ local pre, post = match(key,"(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in gmatch(pre,"[^%.]+") do
+ local dk = d[k]
+ if not dk then
+ dk = { }
+ d[k] = dk
+ elseif type(dk) == "string" then
+ -- invalid table, unable to upgrade structure
+ -- hope for the best or delete the state file
+ break
+ end
+ d = dk
+ end
+ dkey, hkey = post, key
+ end
+ if value == nil then
+ value = default
+ elseif value == false then
+ -- special case
+ elseif persistent then
+ value = value or d[dkey] or default
+ else
+ value = value or default
+ end
+ d[dkey], h[hkey] = value, value
+ elseif type(d) == "string" then
+ -- weird
+ data[tag], hash[tag] = value, value
+ end
+ end
+end
+
+local function get_by_tag(tag,key,default)
+ local h = hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d = data[tag]
+ if d then
+ for k in gmatch(key,"[^%.]+") do
+ local dk = d[k]
+ if dk ~= nil then
+ d = dk
+ else
+ return default
+ end
+ end
+ if d == false then
+ return false
+ else
+ return d or default
+ end
+ end
+ end
+end
+
+states.set_by_tag = set_by_tag
+states.get_by_tag = get_by_tag
+
+function states.set(key,value,default,persistent)
+ set_by_tag(states.tag,key,value,default,persistent)
+end
+
+function states.get(key,default)
+ return get_by_tag(states.tag,key,default)
+end
+
+--~ data.update = {
+--~ ["version"] = {
+--~ ["major"] = 0,
+--~ ["minor"] = 1,
+--~ },
+--~ ["rsync"] = {
+--~ ["server"] = "contextgarden.net",
+--~ ["module"] = "minimals",
+--~ ["repository"] = "current",
+--~ ["flags"] = "-rpztlv --stats",
+--~ },
+--~ ["tasks"] = {
+--~ ["update"] = true,
+--~ ["make"] = true,
+--~ ["delete"] = false,
+--~ },
+--~ ["platform"] = {
+--~ ["host"] = true,
+--~ ["other"] = {
+--~ ["mswin"] = false,
+--~ ["linux"] = false,
+--~ ["linux-64"] = false,
+--~ ["osx-intel"] = false,
+--~ ["osx-ppc"] = false,
+--~ ["sun"] = false,
+--~ },
+--~ },
+--~ ["context"] = {
+--~ ["available"] = {"current", "beta", "alpha", "experimental"},
+--~ ["selected"] = "current",
+--~ },
+--~ ["formats"] = {
+--~ ["cont-en"] = true,
+--~ ["cont-nl"] = true,
+--~ ["cont-de"] = false,
+--~ ["cont-cz"] = false,
+--~ ["cont-fr"] = false,
+--~ ["cont-ro"] = false,
+--~ },
+--~ ["engine"] = {
+--~ ["pdftex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["pdftex"] = true,
+--~ },
+--~ },
+--~ ["luatex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ },
+--~ },
+--~ ["xetex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["xetex"] = false,
+--~ },
+--~ },
+--~ ["metapost"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["mpost"] = true,
+--~ ["metafun"] = true,
+--~ },
+--~ },
+--~ },
+--~ ["fonts"] = {
+--~ },
+--~ ["doc"] = {
+--~ },
+--~ ["modules"] = {
+--~ ["f-urwgaramond"] = false,
+--~ ["f-urwgothic"] = false,
+--~ ["t-bnf"] = false,
+--~ ["t-chromato"] = false,
+--~ ["t-cmscbf"] = false,
+--~ ["t-cmttbf"] = false,
+--~ ["t-construction-plan"] = false,
+--~ ["t-degrade"] = false,
+--~ ["t-french"] = false,
+--~ ["t-lettrine"] = false,
+--~ ["t-lilypond"] = false,
+--~ ["t-mathsets"] = false,
+--~ ["t-tikz"] = false,
+--~ ["t-typearea"] = false,
+--~ ["t-vim"] = false,
+--~ },
+--~ }
+
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.set_by_tag("update","rsync.server","oeps")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua
new file mode 100644
index 00000000000..b04d655c29d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua
@@ -0,0 +1,187 @@
+if not modules then modules = { } end modules ['luat-sto'] = {
+ 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"
+}
+
+-- we could nil some function in the productionrun
+
+local type, next, setmetatable, getmetatable, collectgarbage = type, next, setmetatable, getmetatable, collectgarbage
+local gmatch, format = string.gmatch, string.format
+local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash
+local bytecode = lua.bytecode
+local strippedloadstring = utilities.lua.strippedloadstring
+local formatters = string.formatters
+
+local trace_storage = false
+local report_storage = logs.reporter("system","storage")
+
+storage = storage or { }
+local storage = storage
+
+local data = { }
+storage.data = data
+
+storage.min = 0 -- 500
+storage.max = storage.min - 1
+storage.noftables = storage.noftables or 0
+storage.nofmodules = storage.nofmodules or 0
+
+storage.mark = utilities.storage.mark
+storage.allocate = utilities.storage.allocate
+storage.marked = utilities.storage.marked
+storage.strip = false
+
+directives.register("system.compile.strip", function(v) storage.strip = v end)
+
+function storage.register(...)
+ local t = { ... }
+ local d = t[2]
+ if d then
+ storage.mark(d)
+ else
+ report_storage("fatal error: invalid storage %a",t[1])
+ os.exit()
+ end
+ data[#data+1] = t
+ return t
+end
+
+local n = 0 -- is that one used ?
+
+if environment.initex then
+
+ -- local function dump()
+ -- local max = storage.max
+ -- for i=1,#data do
+ -- local d = data[i]
+ -- local message, original, target = d[1], d[2] ,d[3]
+ -- local c, code, name = 0, { }, nil
+ -- -- we have a nice definer for this
+ -- for str in gmatch(target,"([^%.]+)") do
+ -- if name then
+ -- name = name .. "." .. str
+ -- else
+ -- name = str
+ -- end
+ -- c = c + 1 ; code[c] = formatters["%s = %s or { }"](name,name)
+ -- end
+ -- max = max + 1
+ -- if trace_storage then
+ -- c = c + 1 ; code[c] = formatters["print('restoring %s from slot %s')"](message,max)
+ -- end
+ -- c = c + 1 ; code[c] = serialize(original,name)
+ -- if trace_storage then
+ -- report_storage('saving %a in slot %a, size %s',message,max,#code[c])
+ -- end
+ -- -- we don't need tracing in such tables
+ -- bytecode[max] = strippedloadstring(concat(code,"\n"),storage.strip,format("slot %s (%s)",max,name))
+ -- collectgarbage("step")
+ -- end
+ -- storage.max = max
+ -- end
+
+ local function dump()
+ local max = storage.max
+ local strip = storage.strip
+ for i=1,#data do
+ max = max + 1
+ local tabledata = data[i]
+ local message = tabledata[1]
+ local original = tabledata[2]
+ local target = tabledata[3]
+ local definition = utilities.tables.definetable(target,false,true)
+ local comment = formatters["restoring %s from slot %s"](message,max)
+ if trace_storage then
+ comment = formatters["print('%s')"](comment)
+ else
+ comment = formatters["-- %s"](comment)
+ end
+ local dumped = serialize(original,target)
+ if trace_storage then
+ report_storage('saving %a in slot %a, size %s',message,max,#dumped)
+ end
+ -- we don't need tracing in such tables
+ dumped = concat({ definition, comment, dumped },"\n")
+ bytecode[max] = strippedloadstring(dumped,strip,formatters["slot %s (%s)"](max,name))
+ collectgarbage("step")
+ end
+ storage.max = max
+ end
+
+ lua.registerfinalizer(dump,"dump storage")
+
+end
+
+-- to be tested with otf caching:
+
+function lua.collectgarbage(threshold)
+ local current = collectgarbage("count")
+ local threshold = threshold or 256 * 1024
+ while true do
+ collectgarbage("collect")
+ local previous = collectgarbage("count")
+ if current - previous < threshold then
+ break
+ else
+ current = previous
+ end
+ end
+end
+
+-- -- we also need to count at generation time (nicer for message)
+--
+-- if lua.bytecode then -- from 0 upwards
+-- local i, b = storage.min, lua.bytecode
+-- while b[i] do
+-- storage.noftables = i
+-- b[i]()
+-- b[i] = nil
+-- i = i + 1
+-- end
+-- end
+
+statistics.register("stored bytecode data", function()
+ local nofmodules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - lua.firstbytecode - 1)
+ local nofdumps = (storage.noftables > 0 and storage.noftables ) or storage.max-storage.min + 1
+ local tofmodules = storage.tofmodules or 0
+ local tofdumps = storage.toftables or 0
+ if environment.initex then
+ local luautilities = utilities.lua
+ return format("%s modules, %s tables, %s chunks, %s chunks stripped (%s bytes)",
+ nofmodules,
+ nofdumps,
+ nofmodules + nofdumps,
+ luautilities.nofstrippedchunks or 0,
+ luautilities.nofstrippedbytes or 0
+ )
+ else
+ return format("%s modules (%0.3f sec), %s tables (%0.3f sec), %s chunks (%0.3f sec)",
+ nofmodules, tofmodules,
+ nofdumps, tofdumps,
+ nofmodules + nofdumps, tofmodules + tofdumps
+ )
+ end
+end)
+
+if lua.bytedata then
+ storage.register("lua/bytedata",lua.bytedata,"lua.bytedata")
+end
+
+-- Because the storage mechanism assumes tables, we define a table for storing
+-- (non table) values.
+
+storage.shared = storage.shared or { }
+
+storage.register("storage/shared", storage.shared, "storage.shared")
+
+local mark = storage.mark
+
+if string.patterns then mark(string.patterns) end
+if string.formatters then mark(string.formatters) end
+if lpeg.patterns then mark(lpeg.patterns) end
+if os.env then mark(os.env) end
+if number.dimenfactors then mark(number.dimenfactors) end
+if libraries then for k,v in next, libraries do mark(v) end end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua
new file mode 100644
index 00000000000..071e3bf5bb9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua
@@ -0,0 +1,192 @@
+if not modules then modules = { } end modules ['luat-usr'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local global = global
+
+local moduledata = moduledata
+local thirddata = thirddata
+local userdata = userdata
+local documentdata = documentdata
+
+local context = context
+local tostring = tostring
+local tonumber = tonumber
+local print = print
+
+local string = string
+local table = table
+local lpeg = lpeg
+local math = math
+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
+local instance_banner = string.formatters["=[instance: %s]"] -- the = controls the lua error / see: lobject.c
+local tex_errormessage = context.errmessage
+
+local implement = interfaces.implement
+local reporter = logs.reporter
+
+local report_instance = reporter("lua instance")
+local report_script = reporter("lua script")
+local report_thread = reporter("lua thread")
+local newline = logs.newline
+
+lua.numbers = lua.numbers or { }
+lua.messages = lua.messages or { }
+
+local numbers = lua.numbers
+local messages = lua.messages
+
+storage.register("lua/numbers", numbers, "lua.numbers" )
+storage.register("lua/messages", messages, "lua.messages")
+
+-- First we implement a pure lua version of directlua and a persistent
+-- variant of it:
+
+local function runscript(code)
+ local done, message = loadstring(code)
+ if done then
+ done()
+ else
+ newline()
+ report_script("error : %s",message or "unknown")
+ report_script()
+ report_script("code : %s",code)
+ newline()
+ end
+end
+
+local threads = setmetatableindex(function(t,k)
+ local v = setmetatableindex({},global)
+ t[k] = v
+ return v
+end)
+
+local function runthread(name,code)
+ if not code or code == "" then
+ threads[name] = nil
+ else
+ local thread = threads[name]
+ local done, message = loadstring(code,nil,nil,thread)
+ if done then
+ done()
+ else
+ newline()
+ report_thread("thread: %s",name)
+ report_thread("error : %s",message or "unknown")
+ report_thread()
+ report_thread("code : %s",code)
+ newline()
+ end
+ end
+end
+
+interfaces.implement {
+ name = "luascript",
+ actions = runscript,
+ arguments = "string"
+}
+
+interfaces.implement {
+ name = "luathread",
+ actions = runthread,
+ arguments = { "string", "string" }
+}
+
+-- local scanners = interfaces.scanners
+--
+-- local function ctxscanner(name)
+-- local scanner = scanners[name]
+-- if scanner then
+-- scanner()
+-- else
+-- report("unknown scanner: %s",name)
+-- end
+-- end
+--
+-- interfaces.implement {
+-- name = "clfscanner",
+-- actions = ctxscanner,
+-- arguments = "string",
+-- }
+
+local function registername(name,message)
+ if not name or name == "" then
+ report_instance("no valid name given")
+ return
+ end
+ if not message or message == "" then
+ message = name
+ end
+ local lnn = numbers[name]
+ if not lnn then
+ lnn = #messages + 1
+ 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:
+ global = global, -- or maybe just a metatable
+ -- some protected data
+ moduledata = setmetatableindex(moduledata),
+ thirddata = setmetatableindex(thirddata),
+ -- less protected data
+ userdata = userdata,
+ documentdata = documentdata,
+ -- always there fast
+ context = context,
+ tostring = tostring,
+ tonumber = tonumber,
+ -- standard lua modules
+ string = string,
+ table = table,
+ lpeg = lpeg,
+ math = math,
+ io = io,
+ os = os,
+ lpeg = lpeg,
+ --
+ print = print,
+ report = report,
+ }
+ return function(code)
+ local code, message = load(code,nil,nil,proxy)
+ if not code then
+ report_instance("error: %s",message or code)
+ elseif not xpcall(code,report) then
+ tex_errormessage("hit return to continue or quit this run")
+ end
+ end
+end
+
+lua.registername = registername
+
+implement {
+ name = "registernamedlua",
+ arguments = { "string", "string", "string" },
+ actions = function(name,message,csname)
+ if csname and csname ~= "" then
+ implement {
+ name = csname,
+ arguments = "string",
+ actions = registername(name,message) or report,
+ scope = "private",
+ }
+ else
+ report_instance("unvalid csname for %a",message or name or "?")
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv
new file mode 100644
index 00000000000..92d40010c0f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv
@@ -0,0 +1,126 @@
+%D \module
+%D [ file=luat-usr,
+%D version=2005.08.11,% moved from luat-ini
+%D title=\CONTEXT\ Lua 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 Lua Macros / Userspace}
+
+\unprotect
+
+\registerctxluafile{luat-usr}{1.001}
+
+%D A few goodies:
+%D
+%D \startbuffer
+%D \luascript { context("foo 1:") context(i) }
+%D \luathread {test} { i = 10 context("bar 1:") context(i) }
+%D \luathread {test} { context("bar 2:") context(i) }
+%D \luathread {test} {}
+%D \luathread {test} { context("bar 3:") context(i) }
+%D \luascript { context("foo 2:") context(i) }
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+\let\luascript \clf_luascript
+\let\luathread \clf_luathread
+%let\clfscanner\clf_clfscanner
+%def\clfscanner#1{\csname clf_#1\endcsname}
+
+%D \macros
+%D {definenamedlua}
+%D
+%D We provide an interface for defining instances:
+
+\def\s!lua {lua}
+\def\s!code {code}
+\def\s!data {data}
+%def\s!start{start}
+%def\s!stop {stop}
+
+%D Beware: because \type {\expanded} is een convert command, the error
+%D message will show \type{<inserted text>} as part of the message.
+
+\installsystemnamespace{luacode}
+
+\unexpanded\def\definenamedlua
+ {\bgroup
+ \dodoubleempty\syst_definenamedlua}
+
+\unexpanded\def\syst_definenamedlua[#1][#2]% no optional arg handling here yet / we could use numbers instead (more efficient)
+ {\iffirstargument
+ \ifcsname\??luacode#1\endcsname \else
+ %
+ \edef\fullname{lua_code_#1}%
+ %
+ \clf_registernamedlua{#1}{#2}{\fullname}%
+ %
+ \unexpanded\expandafter\xdef\csname\s!start#1\s!code\endcsname
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \csname\??luacode#1\endcsname}%
+ %
+ \global\expandafter\let\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
+ \noexpand\expandafter
+ \expandafter\noexpand\csname clf_\fullname\endcsname
+ \noexpand\expandafter{\noexpand\normalexpanded{##1}}}%
+ %
+ \global\expandafter\let\csname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname
+ \fi
+ \fi
+ \egroup}
+
+%D We predefine a few.
+
+% \definenamedlua[module][module instance] % not needed
+
+\definenamedlua[user] [private user]
+\definenamedlua[third] [third party module]
+\definenamedlua[isolated][isolated]
+
+%D In practice this works out as follows:
+%D
+%D \startbuffer
+%D \startluacode
+%D context("LUA")
+%D \stopluacode
+%D
+%D \startusercode
+%D global.context("USER 1")
+%D context.par()
+%D context("USER 2")
+%D context.par()
+%D if characters then
+%D context("ACCESS directly")
+%D elseif global.characters then
+%D context("ACCESS via global")
+%D else
+%D context("NO ACCESS at all")
+%D end
+%D context.par()
+%D if bogus then
+%D context("ACCESS directly")
+%D elseif global.bogus then
+%D context("ACCESS via global")
+%D else
+%D context("NO ACCESS at all")
+%D end
+%D context.par()
+%D \stopusercode
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua
new file mode 100644
index 00000000000..4112db1e5fa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua
@@ -0,0 +1,1010 @@
+if not modules then modules = { } end modules ['lxml-aux'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- not all functions here make sense anymore vbut we keep them for
+-- compatibility reasons
+
+local trace_manipulations = false trackers.register("lxml.manipulations", function(v) trace_manipulations = v end)
+local trace_inclusions = false trackers.register("lxml.inclusions", function(v) trace_inclusions = v end)
+
+local report_xml = logs.reporter("xml")
+
+local xml = xml
+
+local xmlcopy, xmlname = xml.copy, xml.name
+local xmlinheritedconvert = xml.inheritedconvert
+local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
+
+local type, next, setmetatable, getmetatable = type, next, setmetatable, getmetatable
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format, find, strip = string.gmatch, string.gsub, string.format, string.find, string.strip
+local utfbyte = utf.byte
+local lpegmatch = lpeg.match
+local striplinepatterns = utilities.strings.striplinepatterns
+
+local function report(what,pattern,c,e)
+ report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+end
+
+local function withelements(e,handle,depth)
+ if e and handle then
+ local edt = e.dt
+ if edt then
+ depth = depth or 0
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "table" then
+ handle(e,depth)
+ withelements(e,handle,depth+1)
+ end
+ end
+ end
+ end
+end
+
+xml.withelements = withelements
+
+function xml.withelement(e,n,handle) -- slow
+ if e and n ~= 0 and handle then
+ local edt = e.dt
+ if edt then
+ if n > 0 then
+ for i=1,#edt do
+ local ei = edt[i]
+ if type(ei) == "table" then
+ if n == 1 then
+ handle(ei)
+ return
+ else
+ n = n - 1
+ end
+ end
+ end
+ elseif n < 0 then
+ for i=#edt,1,-1 do
+ local ei = edt[i]
+ if type(ei) == "table" then
+ if n == -1 then
+ handle(ei)
+ return
+ else
+ n = n + 1
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function xml.each(root,pattern,handle,reverse)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ if handle then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ end
+ end
+ return collected
+ end
+end
+
+function xml.processattributes(root,pattern,handle)
+ local collected = xmlapplylpath(root,pattern)
+ if collected and handle then
+ for c=1,#collected do
+ handle(collected[c].at)
+ end
+ end
+ return collected
+end
+
+--[[ldx--
+<p>The following functions collect elements and texts.</p>
+--ldx]]--
+
+-- are these still needed -> lxml-cmp.lua
+
+function xml.collect(root, pattern)
+ return xmlapplylpath(root,pattern)
+end
+
+function xml.collecttexts(root, pattern, flatten) -- todo: variant with handle
+ local collected = xmlapplylpath(root,pattern)
+ if collected and flatten then
+ local xmltostring = xml.tostring
+ for c=1,#collected do
+ collected[c] = xmltostring(collected[c].dt)
+ end
+ end
+ return collected or { }
+end
+
+function xml.collect_tags(root, pattern, nonamespace)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ local t, n = { }, 0
+ for c=1,#collected do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace then
+ t[n] = tg
+ elseif ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
+ end
+ end
+ return t
+ end
+end
+
+--[[ldx--
+<p>We've now arrived at the functions that manipulate the tree.</p>
+--ldx]]--
+
+local no_root = { no_root = true }
+
+local function redo_ni(d)
+ for k=1,#d do
+ local dk = d[k]
+ if type(dk) == "table" then
+ dk.ni = k
+ end
+ end
+end
+
+xml.reindex = redo_ni
+
+local function xmltoelement(whatever,root)
+ if not whatever then
+ return nil
+ end
+ local element
+ if type(whatever) == "string" then
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
+ else
+ element = whatever -- we assume a table
+ end
+ if element.error then
+ return whatever -- string
+ end
+ if element then
+ --~ if element.ri then
+ --~ element = element.dt[element.ri].dt
+ --~ else
+ --~ element = element.dt
+ --~ end
+ end
+ return element
+end
+
+xml.toelement = xmltoelement
+
+local function copiedelement(element,newparent)
+ if type(element) == "string" then
+ return element
+ else
+ element = xmlcopy(element).dt
+ if newparent and type(element) == "table" then
+ element.__p__ = newparent
+ end
+ return element
+ end
+end
+
+function xml.delete(root,pattern)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ local ni = e.ni
+ if ni <= #d then
+ if false then
+ p.dt[ni] = ""
+ else
+ -- what if multiple deleted in one set
+ remove(d,ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ -- disturbing
+ end
+ end
+ end
+ end
+ end
+end
+
+function xml.replace(root,pattern,whatever)
+ local element = root and xmltoelement(whatever,root)
+ local collected = element and xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('replacing',pattern,c,e)
+ end
+ local d = p.dt
+ d[e.ni] = copiedelement(element,p)
+ redo_ni(d) -- probably not needed
+ end
+ end
+ end
+end
+
+local function wrap(e,wrapper)
+ local t = {
+ rn = e.rn,
+ tg = e.tg,
+ ns = e.ns,
+ at = e.at,
+ dt = e.dt,
+ __p__ = e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn = wrapper.rn or e.rn or ""
+ e.tg = wrapper.tg or e.tg or ""
+ e.ns = wrapper.ns or e.ns or ""
+ e.at = fastcopy(wrapper.at)
+ e.dt = { t }
+end
+
+function xml.wrap(root,pattern,whatever)
+ if whatever then
+ local wrapper = xmltoelement(whatever,root)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ if trace_manipulations then
+ report('wrapping',pattern,c,e)
+ end
+ wrap(e,wrapper)
+ end
+ end
+ else
+ wrap(root,xmltoelement(pattern))
+ end
+end
+
+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 edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
+ end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
+ end
+ end
+end
+
+local function insert_element(root,pattern,whatever,before) -- todo: element als functie
+ local element = root and xmltoelement(whatever,root)
+ local collected = element and xmlapplylpath(root,pattern)
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
+ for c=1,#collected do
+ insert_e(collected[c])
+ end
+ end
+end
+
+xml.insert_element = insert_element
+xml.insertafter = insert_element
+xml.insertbefore = function(r,p,e) insert_element(r,p,e,true) end
+xml.injectafter = inject_element
+xml.injectbefore = function(r,p,e) inject_element(r,p,e,true) end
+
+-- loaddata can restrict loading
+
+local function include(xmldata,pattern,attribute,recursive,loaddata,level)
+ -- attribute = attribute or 'href'
+ pattern = pattern or 'include'
+ loaddata = loaddata or io.loaddata
+ local collected = xmlapplylpath(xmldata,pattern)
+ if collected then
+ if not level then
+ level = 1
+ end
+ for c=1,#collected do
+ local ek = collected[c]
+ local name = nil
+ local ekdt = ek.dt
+ if ekdt then
+ local ekat = ek.at
+ local ekrt = ek.__p__
+ if ekrt then
+ local epdt = ekrt.dt
+ if not attribute or attribute == "" then
+ name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str
+ end
+ if not name then
+ for a in gmatch(attribute or "href","([^|]+)") do
+ name = ekat[a]
+ if name then
+ break
+ end
+ end
+ end
+ local data = nil
+ if name and name ~= "" then
+ data = loaddata(name) or ""
+ if trace_inclusions then
+ report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
+ end
+ end
+ if not data or data == "" then
+ epdt[ek.ni] = "" -- xml.empty(d,k)
+ elseif ekat["parse"] == "text" then
+ -- for the moment hard coded
+ epdt[ek.ni] = xml.escaped(data) -- d[k] = xml.escaped(data)
+ else
+ local xi = xmlinheritedconvert(data,xmldata)
+ if not xi then
+ epdt[ek.ni] = "" -- xml.empty(d,k)
+ else
+ if recursive then
+ include(xi,pattern,attribute,recursive,loaddata,level+1)
+ end
+ local child = xml.body(xi) -- xml.assign(d,k,xi)
+ child.__p__ = ekrt
+ child.__f__ = name -- handy for tracing
+ epdt[ek.ni] = child
+ local settings = xmldata.settings
+ local inclusions = settings and settings.inclusions
+ if inclusions then
+ inclusions[#inclusions+1] = name
+ elseif settings then
+ settings.inclusions = { name }
+ else
+ settings = { inclusions = { name } }
+ xmldata.settings = settings
+ end
+ if child.er then
+ local badinclusions = settings.badinclusions
+ if badinclusions then
+ badinclusions[#badinclusions+1] = name
+ else
+ settings.badinclusions = { name }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+xml.include = include
+
+function xml.inclusion(e,default)
+ while e do
+ local f = e.__f__
+ if f then
+ return f
+ else
+ e = e.__p__
+ end
+ end
+ return default
+end
+
+local function getinclusions(key,e,sorted)
+ while e do
+ local settings = e.settings
+ if settings then
+ local inclusions = settings[key]
+ if inclusions then
+ inclusions = table.unique(inclusions) -- a copy
+ if sorted then
+ table.sort(inclusions) -- so we sort the copy
+ end
+ return inclusions -- and return the copy
+ else
+ e = e.__p__
+ end
+ else
+ e = e.__p__
+ end
+ end
+end
+
+function xml.inclusions(e,sorted)
+ return getinclusions("inclusions",e,sorted)
+end
+
+function xml.badinclusions(e,sorted)
+ return getinclusions("badinclusions",e,sorted)
+end
+
+local b_collapser = lpeg.patterns.b_collapser
+local m_collapser = lpeg.patterns.m_collapser
+local e_collapser = lpeg.patterns.e_collapser
+
+local b_stripper = lpeg.patterns.b_stripper
+local m_stripper = lpeg.patterns.m_stripper
+local e_stripper = lpeg.patterns.e_stripper
+
+local lpegmatch = lpeg.match
+
+local function stripelement(e,nolines,anywhere)
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 0 then
+ return e -- convenient
+ elseif anywhere then
+ local t = { }
+ local m = 0
+ for e=1,n do
+ local str = edt[e]
+ if type(str) ~= "string" then
+ m = m + 1
+ t[m] = str
+ elseif str ~= "" then
+ if nolines then
+ str = lpegmatch((n == 1 and b_collapser) or (n == m and e_collapser) or m_collapser,str)
+ else
+ str = lpegmatch((n == 1 and b_stripper) or (n == m and e_stripper) or m_stripper,str)
+ end
+ if str ~= "" then
+ m = m + 1
+ t[m] = str
+ end
+ end
+ end
+ e.dt = t
+ else
+ local str = edt[1]
+ if type(str) == "string" then
+ if str ~= "" then
+ str = lpegmatch(nolines and b_collapser or b_stripper,str)
+ end
+ if str == "" then
+ remove(edt,1)
+ n = n - 1
+ else
+ edt[1] = str
+ end
+ end
+ if n > 0 then
+ str = edt[n]
+ if type(str) == "string" then
+ if str == "" then
+ remove(edt)
+ else
+ str = lpegmatch(nolines and e_collapser or e_stripper,str)
+ if str == "" then
+ remove(edt)
+ else
+ edt[n] = str
+ end
+ end
+ end
+ end
+ end
+ end
+ return e -- convenient
+end
+
+xml.stripelement = stripelement
+
+function xml.strip(root,pattern,nolines,anywhere) -- strips all leading and trailing spacing
+ local collected = xmlapplylpath(root,pattern) -- beware, indices no longer are valid now
+ if collected then
+ for i=1,#collected do
+ stripelement(collected[i],nolines,anywhere)
+ end
+ end
+end
+
+local function renamespace(root, oldspace, newspace) -- fast variant
+ local ndt = #root.dt
+ for i=1,ndt or 0 do
+ local e = root[i]
+ if type(e) == "table" then
+ if e.ns == oldspace then
+ e.ns = newspace
+ if e.rn then
+ e.rn = newspace
+ end
+ end
+ local edt = e.dt
+ if edt then
+ renamespace(edt, oldspace, newspace)
+ end
+ end
+ end
+end
+
+xml.renamespace = renamespace
+
+function xml.remaptag(root, pattern, newtg)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].tg = newtg
+ end
+ end
+end
+
+function xml.remapnamespace(root, pattern, newns)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].ns = newns
+ end
+ end
+end
+
+function xml.checknamespace(root, pattern, newns)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ if (not e.rn or e.rn == "") and e.ns == "" then
+ e.rn = newns
+ end
+ end
+ end
+end
+
+function xml.remapname(root, pattern, newtg, newns, newrn)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ e.tg, e.ns, e.rn = newtg, newns, newrn
+ end
+ end
+end
+
+--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+-- local x = xml.convert("<x><a>1<b>2</b>3</a></x>")
+-- xml.texttocdata(xml.first(x,"a"))
+-- print(x) -- <x><![CDATA[1<b>2</b>3]]></x>
+
+function xml.texttocdata(e) -- could be a finalizer
+ local dt = e.dt
+ local s = xml.tostring(dt) -- no shortcut?
+ e.tg = "@cd@"
+ e.special = true
+ e.ns = ""
+ e.rn = ""
+ e.dt = { s }
+ e.at = nil
+end
+
+-- local x = xml.convert("<x><a>1<b>2</b>3</a></x>")
+-- xml.tocdata(xml.first(x,"a"))
+-- print(x) -- <x><![CDATA[<a>1<b>2</b>3</a>]]></x>
+
+function xml.elementtocdata(e) -- could be a finalizer
+ local dt = e.dt
+ local s = xml.tostring(e) -- no shortcut?
+ e.tg = "@cd@"
+ e.special = true
+ e.ns = ""
+ e.rn = ""
+ e.dt = { s }
+ e.at = nil
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
+<p>Here are a few synonyms.</p>
+--ldx]]--
+
+xml.all = xml.each
+xml.insert = xml.insertafter
+xml.inject = xml.injectafter
+xml.after = xml.insertafter
+xml.before = xml.insertbefore
+xml.process = xml.each
+
+-- obsolete
+
+xml.obsolete = xml.obsolete or { }
+local obsolete = xml.obsolete
+
+xml.strip_whitespace = xml.strip obsolete.strip_whitespace = xml.strip
+xml.collect_elements = xml.collect obsolete.collect_elements = xml.collect
+xml.delete_element = xml.delete obsolete.delete_element = xml.delete
+xml.replace_element = xml.replace obsolete.replace_element = xml.replacet
+xml.each_element = xml.each obsolete.each_element = xml.each
+xml.process_elements = xml.process obsolete.process_elements = xml.process
+xml.insert_element_after = xml.insertafter obsolete.insert_element_after = xml.insertafter
+xml.insert_element_before = xml.insertbefore obsolete.insert_element_before = xml.insertbefore
+xml.inject_element_after = xml.injectafter obsolete.inject_element_after = xml.injectafter
+xml.inject_element_before = xml.injectbefore obsolete.inject_element_before = xml.injectbefore
+xml.process_attributes = xml.processattributes obsolete.process_attributes = xml.processattributes
+xml.collect_texts = xml.collecttexts obsolete.collect_texts = xml.collecttexts
+xml.inject_element = xml.inject obsolete.inject_element = xml.inject
+xml.remap_tag = xml.remaptag obsolete.remap_tag = xml.remaptag
+xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
+xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n)
+ insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.insertcdata(e,str,n)
+ insert(e.dt,n or 1,{
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcomment(e,str,n)
+ e.dt = { {
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
+function xml.setcdata(e,str)
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
+-- maybe helpers like this will move to an autoloader
+
+function xml.separate(x,pattern)
+ local collected = xmlapplylpath(x,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local d = e.dt
+ if d == x then
+ report_xml("warning: xml.separate changes root")
+ x = d
+ end
+ local t, n = { "\n" }, 1
+ local i, nd = 1, #d
+ while i <= nd do
+ while i <= nd do
+ local di = d[i]
+ if type(di) == "string" then
+ if di == "\n" or find(di,"^%s+$") then -- first test is speedup
+ i = i + 1
+ else
+ d[i] = strip(di)
+ break
+ end
+ else
+ break
+ end
+ end
+ if i > nd then
+ break
+ end
+ t[n+1] = "\n"
+ t[n+2] = d[i]
+ t[n+3] = "\n"
+ n = n + 3
+ i = i + 1
+ end
+ t[n+1] = "\n"
+ setmetatable(t,getmetatable(d))
+ e.dt = t
+ end
+ end
+ return x
+end
+
+--
+
+local helpers = xml.helpers or { }
+xml.helpers = helpers
+
+local function normal(e,action)
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ local str = edt[i]
+ if type(str) == "string" and str ~= "" then
+ edt[i] = action(str)
+ end
+ end
+ end
+end
+
+local function recurse(e,action)
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ local str = edt[i]
+ if type(str) ~= "string" then
+ recurse(str,action) -- ,recursive
+ elseif str ~= "" then
+ edt[i] = action(str)
+ end
+ end
+ end
+end
+
+function helpers.recursetext(collected,action,recursive)
+ if recursive then
+ for i=1,#collected do
+ recurse(collected[i],action)
+ end
+ else
+ for i=1,#collected do
+ normal(collected[i],action)
+ end
+ end
+end
+
+-- on request ... undocumented ...
+--
+-- _tag : element name
+-- _type : node type (_element can be an option)
+-- _namespace : only if given
+--
+-- [1..n] : text or table
+-- key : value or attribite 'key'
+--
+-- local str = [[
+-- <?xml version="1.0" ?>
+-- <a one="1">
+-- <!-- rubish -->
+-- <b two="1"/>
+-- <b two="2">
+-- c &gt; d
+-- </b>
+-- </a>
+-- ]]
+--
+-- inspect(xml.totable(xml.convert(str)))
+-- inspect(xml.totable(xml.convert(str),true))
+-- inspect(xml.totable(xml.convert(str),true,true))
+
+local specials = {
+ ["@rt@"] = "root",
+ ["@pi@"] = "instruction",
+ ["@cm@"] = "comment",
+ ["@dt@"] = "declaration",
+ ["@cd@"] = "cdata",
+}
+
+local function convert(x,strip,flat)
+ local ns = x.ns
+ local tg = x.tg
+ local at = x.at
+ local dt = x.dt
+ local node = flat and {
+ [0] = (not x.special and (ns ~= "" and ns .. ":" .. tg or tg)) or nil,
+ } or {
+ _namespace = ns ~= "" and ns or nil,
+ _tag = not x.special and tg or nil,
+ _type = specials[tg] or "_element",
+ }
+ if at then
+ for k, v in next, at do
+ node[k] = v
+ end
+ end
+ local n = 0
+ for i=1,#dt do
+ local di = dt[i]
+ if type(di) == "table" then
+ if flat and di.special then
+ -- ignore
+ else
+ di = convert(di,strip,flat)
+ if di then
+ n = n + 1
+ node[n] = di
+ end
+ end
+ elseif strip then
+ di = lpegmatch(strip,di)
+ if di ~= "" then
+ n = n + 1
+ node[n] = di
+ end
+ else
+ n = n + 1
+ node[n] = di
+ end
+ end
+ if next(node) then
+ return node
+ end
+end
+
+function xml.totable(x,strip,flat)
+ if type(x) == "table" then
+ if strip then
+ strip = striplinepatterns[strip]
+ end
+ return convert(x,strip,flat)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua
new file mode 100644
index 00000000000..fa921b24f48
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua
@@ -0,0 +1,171 @@
+if not modules then modules = { } end modules ['lxml-css'] = {
+ version = 1.001,
+ comment = "companion to lxml-css.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber, rawset = tonumber, rawset
+local lower, format = string.lower, string.format
+local P, S, C, R, Cb, Cg, Carg, Ct, Cc, Cf = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg, lpeg.Ct, lpeg.Cc, lpeg.Cf
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+xml.css = xml.css or { }
+local css = xml.css
+
+if not number.dimenfactors then
+ require("util-dim.lua")
+end
+
+local dimenfactors = number.dimenfactors
+local bpf = 1/dimenfactors.bp
+local cmf = 1/dimenfactors.cm
+local mmf = 1/dimenfactors.mm
+local inf = 1/dimenfactors["in"]
+
+local percentage, exheight, emwidth, pixels
+
+if tex then
+
+ local exheights = fonts.hashes.exheights
+ local emwidths = fonts.hashes.emwidths
+ local texget = tex.get
+
+ percentage = function(s,pcf) return tonumber(s) * (pcf or texget("hsize")) end
+ exheight = function(s,exf) return tonumber(s) * (exf or exheights[true]) end
+ emwidth = function(s,emf) return tonumber(s) * (emf or emwidths[true]) end
+ pixels = function(s,pxf) return tonumber(s) * (pxf or emwidths[true]/300) end
+
+else
+
+ local function generic(s,unit) return tonumber(s) * unit end
+
+ percentage = generic
+ exheight = generic
+ emwidth = generic
+ pixels = generic
+
+end
+
+local validdimen = Cg(lpegpatterns.number,'a') * (
+ Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end
+ + Cb('a') * P("cm") / function(s) return tonumber(s) * cmf end
+ + Cb('a') * P("mm") / function(s) return tonumber(s) * mmf end
+ + Cb('a') * P("in") / function(s) return tonumber(s) * inf end
+ + Cb('a') * P("px") * Carg(1) / pixels
+ + Cb('a') * P("%") * Carg(2) / percentage
+ + Cb('a') * P("ex") * Carg(3) / exheight
+ + Cb('a') * P("em") * Carg(4) / emwidth
+ + Cb('a') * Carg(1) / pixels
+ )
+
+local pattern = (validdimen * lpegpatterns.whitespace^0)^1
+
+-- todo: default if ""
+
+local function dimension(str,pixel,percent,exheight,emwidth)
+ return (lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth))
+end
+
+local function padding(str,pixel,percent,exheight,emwidth)
+ local top, bottom, left, right = lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth)
+ if not bottom then
+ bottom, left, right = top, top, top
+ elseif not left then
+ bottom, left, right = top, bottom, bottom
+ elseif not right then
+ bottom, left, right = left, bottom, bottom
+ end
+ return top, bottom, left, right
+end
+
+css.dimension = dimension
+css.padding = padding
+
+-- local hsize = 655360*100
+-- local exheight = 65536*4
+-- local emwidth = 65536*10
+-- local pixel = emwidth/100
+--
+-- print(padding("10px",pixel,hsize,exheight,emwidth))
+-- print(padding("10px 20px",pixel,hsize,exheight,emwidth))
+-- print(padding("10px 20px 30px",pixel,hsize,exheight,emwidth))
+-- print(padding("10px 20px 30px 40px",pixel,hsize,exheight,emwidth))
+--
+-- print(padding("10%",pixel,hsize,exheight,emwidth))
+-- print(padding("10% 20%",pixel,hsize,exheight,emwidth))
+-- print(padding("10% 20% 30%",pixel,hsize,exheight,emwidth))
+-- print(padding("10% 20% 30% 40%",pixel,hsize,exheight,emwidth))
+--
+-- print(padding("10",pixel,hsize,exheight,emwidth))
+-- print(padding("10 20",pixel,hsize,exheight,emwidth))
+-- print(padding("10 20 30",pixel,hsize,exheight,emwidth))
+-- print(padding("10 20 30 40",pixel,hsize,exheight,emwidth))
+--
+-- print(padding("10pt",pixel,hsize,exheight,emwidth))
+-- print(padding("10pt 20pt",pixel,hsize,exheight,emwidth))
+-- print(padding("10pt 20pt 30pt",pixel,hsize,exheight,emwidth))
+-- print(padding("10pt 20pt 30pt 40pt",pixel,hsize,exheight,emwidth))
+
+-- 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 pattern = Cf( Ct("") * (
+ Cg(
+ Cc("style") * (
+ C("italic")
+ + C("oblique")
+ + C("slanted") / "oblique"
+ )
+ + Cc("variant") * (
+ (C("smallcaps") + C("caps")) / "small-caps"
+ )
+ + Cc("weight") *
+ C("bold")
+ + Cc("family") * (
+ (C("mono") + C("type")) / "monospace" -- just ignore the "space(d)"
+ + (C("sansserif") + C("sans")) / "sans-serif" -- match before serif
+ + C("serif")
+ )
+ )
+--+ P("\\") * (
+-- P("bf") * ( Cg ( Cc("weight") * Cc("bold") ) )
+-- + P("bi") * ( Cg ( Cc("weight") * Cc("bold") )
+-- * Cg ( Cc("style") * Cc("italic") ) )
+-- + P("bs") * ( Cg ( Cc("weight") * Cc("bold") )
+-- * Cg ( Cc("style") * Cc("oblique") ) )
+-- + P("it") * ( Cg ( Cc("style") * Cc("italic") ) )
+-- + P("sl") * ( Cg ( Cc("style") * Cc("oblique") ) )
+-- + P("sc") * ( Cg ( Cc("variant") * Cc("small-caps") ) )
+-- + P("tt") * ( Cg ( Cc("family") * Cc("monospace") ) )
+--)
+ + P(1)
+)^0 , rawset)
+
+function css.fontspecification(str)
+ return str and lpegmatch(pattern,lower(str))
+end
+
+function css.colorspecification(str)
+ local c = str and attributes.colors.values[tonumber(str)]
+ return c and format("rgb(%s%%,%s%%,%s%%)",c[3]*100,c[4]*100,c[5]*100)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-css.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.mkiv
new file mode 100644
index 00000000000..79de85c088c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.mkiv
@@ -0,0 +1,39 @@
+%D \module
+%D [ file=lxml-css,
+%D version=2010.01.28,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Css Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{lxml-css}{1.001}
+
+\def\ctxmodulecss#1{\ctxlua{moduledata.css.#1}}
+
+% No stable interface yet.
+
+% \edef\CellPadding{\xmlatt{#1}{cellpadding}}
+% \ifx\CellPadding\empty
+% \edef\CellPadding{.25ex}
+% \else
+% \edef\CellPadding{\cssgetsinglepadding{\xmlatt{#1}{cellpadding}}}
+% \fi
+
+% \starttexdefinition cssgetsinglepadding #1
+% \ctxlua {
+% context((moduledata.css.padding(
+% "#1",
+% \number\dimexpr0.1ex,
+% \number\dimexpr0.01\hsize,
+% \number\dimexpr1ex,
+% \number\dimexpr1em
+% ))) % returns 4 values therefore ()
+% }sp
+% \stoptexdefinition
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.lua
new file mode 100644
index 00000000000..677fd6a0154
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.lua
@@ -0,0 +1,142 @@
+if not modules then modules = { } end modules ['lxml-ctx'] = {
+ version = 1.001,
+ comment = "companion to lxml-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- will be cleaned up
+
+local format, find, gsub = string.format, string.find, string.gsub
+
+local xml = xml
+xml.ctx = { }
+xml.ctx.enhancers = { }
+
+local context = context
+local commands = commands
+
+-- hashen
+
+function xml.ctx.enhancers.compound(root,lpath,before,tokens,after) -- todo lpeg
+ local before = before or "[%a%d][%a%d][%a%d]"
+ local tokens = tokens or "[%/%-]"
+ local after = after or "[%a%d][%a%d][%a%d]"
+ local pattern = "(" .. before .. ")(" .. tokens .. ")(" .. after .. ")"
+ local action = function(a,b,c)
+ return a .. "<compound token=" .. format("%q",b) .. "/>" .. c -- formatters["%s<compound token=%q/>%s"](a,b,c)
+ end
+ xml.enhance(root,lpath,pattern,action) -- still present?
+end
+
+local loaded = { }
+
+local nodesettostring = xml.nodesettostring
+
+-- maybe use detokenize instead of \type
+
+local function cleaned(str)
+ str = gsub(str,"|","\\textbar ")
+ return str
+end
+
+function xml.ctx.tshow(specification)
+ local pattern = specification.pattern
+ local xmlroot = specification.xmlroot
+ local attribute = specification.attribute
+ if context then
+ local xmlpattern = pattern
+ if not find(xmlpattern,"^[%a]+://") then
+ xmlpattern = "xml://" .. pattern
+ end
+ local parsed = xml.lpath(xmlpattern)
+ local titlecommand = specification.title or "type"
+ if parsed.state then
+ context[titlecommand]("pattern: " .. cleaned(pattern) .. " (".. parsed.state .. ")")
+ else
+ context[titlecommand]("pattern: " .. cleaned(pattern))
+ end
+ context.starttabulate({ "|Tr|Tl|Tp|" } )
+ if specification.warning then
+ local comment = parsed.comment
+ if comment then
+ for k=1,#comment do
+ context.NC()
+ context("!")
+ context.NC()
+ context.rlap(comment[k])
+ context.NR()
+ end
+ context.TB()
+ end
+ end
+ for p=1,#parsed do
+ local pp = parsed[p]
+ local kind = pp.kind
+ context.NC()
+ context(p)
+ context.NC()
+ context(kind)
+ context.NC()
+ if kind == "axis" then
+ context(cleaned(pp.axis))
+ elseif kind == "nodes" then
+ context(cleaned(nodesettostring(pp.nodes,pp.nodetest)))
+ elseif kind == "expression" then
+-- -- context("%s => %s",pp.expression,pp.converted)
+ context(cleaned(pp.expression))
+ elseif kind == "finalizer" then
+ context("%s(%s)",pp.name,pp.arguments)
+ elseif kind == "error" and pp.eqrror then
+ context(pp.error)
+ end
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+ if xmlroot and xmlroot ~= "" then
+ if not loaded[xmlroot] then
+ loaded[xmlroot] = xml.convert(buffers.getcontent(xmlroot))
+ end
+ local collected = xml.filter(loaded[xmlroot],xmlpattern)
+ if collected then
+ local tc = type(collected)
+ if not tc then
+ -- skip
+ else
+ context.blank()
+ context.type("result : ")
+ if tc == "string" then
+ context.type(collected)
+ elseif tc == "table" then
+ if collected.tg then
+ collected = { collected }
+ end
+ for c=1,#collected do
+ local cc = collected[c]
+ if attribute and attribute ~= "" then
+ local ccat = cc.at
+ local a = ccat and ccat[attribute]
+ if a and a ~= "" then
+ context.type(a)
+ context.type(">")
+ end
+ end
+ local ccns = cc.ns
+ if ccns == "" then
+ context.type(cc.tg)
+ else
+ context.type(ccns .. ":" .. cc.tg)
+ end
+ context.space()
+ end
+ else
+ context.type(tostring(tc))
+ end
+ context.blank()
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.mkiv
new file mode 100644
index 00000000000..6691e36bbe7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ctx.mkiv
@@ -0,0 +1,58 @@
+%D \module
+%D [ file=lxml-ctx,
+%D version=2007.08.17,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Experimental. This might change! Also, it might become a module
+%D instead if core code.
+
+\writestatus{loading}{ConTeXt XML Support / Goodies}
+
+\registerctxluafile{lxml-ctx}{1.001}
+
+\unprotect
+
+\settrue \xmllshowbuffer
+\setfalse\xmllshowtitle
+\settrue \xmllshowwarning
+
+\definehead
+ [lshowtitle]
+ [subsubsubsubsubject]
+
+\setuphead
+ [lshowtitle]
+ [\c!style=\tta]
+
+\unexpanded\def\xmllshow#1%
+ {\ctxlua{xml.ctx.tshow {
+ pattern = \!!bs\detokenize{#1}\!!es,
+ \ifconditional\xmllshowtitle
+ title = "lshowtitle",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }}
+
+\unexpanded\def\xmllshowbuffer#1#2#3%
+ {\ctxlua{xml.ctx.tshow {
+ pattern = \!!bs\detokenize{#2}\!!es,
+ \ifconditional\xmllshowbuffer
+ xmlroot = "#1",
+ attribute = "#3",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-dir.lua
new file mode 100644
index 00000000000..48c0ac41e73
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-dir.lua
@@ -0,0 +1,117 @@
+if not modules then modules = { } end modules ['lxml-dir'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gsub = string.gsub
+local formatters = string.formatters
+
+-- <?xml version="1.0" standalone="yes"?>
+-- <!-- demo.cdx -->
+-- <directives>
+-- <!--
+-- <directive attribute='id' value="100" setup="cdx:100"/>
+-- <directive attribute='id' value="101" setup="cdx:101"/>
+-- -->
+-- <!--
+-- <directive attribute='cdx' value="colors" element="cals:table" setup="cdx:cals:table:colors"/>
+-- <directive attribute='cdx' value="vertical" element="cals:table" setup="cdx:cals:table:vertical"/>
+-- <directive attribute='cdx' value="noframe" element="cals:table" setup="cdx:cals:table:noframe"/>
+-- -->
+-- <directive attribute='cdx' value="*" element="cals:table" setup="cdx:cals:table:*"/>
+-- </directives>
+
+local lxml = lxml
+local context = context
+
+local getid = lxml.getid
+
+local directives = lxml.directives or { }
+lxml.directives = directives
+
+local report_lxml = logs.reporter("xml","tex")
+
+local data = {
+ setup = { },
+ before = { },
+ after = { }
+}
+
+local function load_setup(filename)
+ local fullname = resolvers.findtexfile(filename) or ""
+ if fullname ~= "" then
+ filename = fullname
+ end
+ local collection = xml.applylpath({ getid(xml.load(filename)) },"directive") -- is { } needed ?
+ if collection then
+ local valid = 0
+ for i=1,#collection do
+ local at = collection[i].at
+ local attribute, value, element = at.attribute or "", at.value or "", at.element or '*'
+ local setup, before, after = at.setup or "", at.before or "", at.after or ""
+ if attribute ~= "" and value ~= "" then
+ local key = formatters["%s::%s::%s"](element,attribute,value)
+ local t = data[key] or { }
+ if setup ~= "" then t.setup = setup end
+ if before ~= "" then t.before = before end
+ if after ~= "" then t.after = after end
+ data[key] = t
+ valid = valid + 1
+ end
+ end
+ report_lxml("%s directives found in %a, valid %s",#collection,filename,valid)
+ else
+ report_lxml("no directives found in %a",filename)
+ end
+end
+
+local function handle_setup(category,root,attribute,element)
+ root = getid(root)
+ if attribute then
+ local value = root.at[attribute]
+ if value then
+ if not element then
+ local ns, tg = root.rn or root.ns, root.tg
+ if ns == "" then
+ element = tg
+ else
+ element = ns .. ':' .. tg
+ end
+ end
+ local setup = data[formatters["%s::%s::%s"](element,attribute,value)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ context.directsetup(setup)
+ else
+ setup = data[formatters["%s::%s::*"](element,attribute)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ setup = gsub(setup,'%*',value)
+ context.directsetup(setup)
+ end
+ end
+ end
+ end
+end
+
+directives.load = load_setup
+directives.handle = handle_setup
+
+function directives.setup(root,attribute,element)
+ handle_setup('setup',root,attribute,element)
+end
+
+function directives.before(root,attribute,element)
+ handle_setup('before',root,attribute,element)
+end
+
+function directives.after(root,attribute,element)
+ handle_setup('after',root,attribute,element)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ent.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-ent.lua
new file mode 100644
index 00000000000..c392713f0a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ent.lua
@@ -0,0 +1,66 @@
+if not modules then modules = { } end modules ['lxml-ent'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tonumber = type, next, tonumber
+local byte, format = string.byte, string.format
+local utfchar = utf.char
+local lpegmatch = lpeg.match
+local setmetatableindex = table.setmetatableindex
+
+--[[ldx--
+<p>We provide (at least here) two entity handlers. The more extensive
+resolver consults a hash first, tries to convert to <l n='utf'/> next,
+and finaly calls a handler when defines. When this all fails, the
+original entity is returned.</p>
+
+<p>We do things different now but it's still somewhat experimental</p>
+--ldx]]--
+
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
+
+local report_xml = logs.reporter("xml")
+
+local xml = xml
+
+xml.entities = xml.entities or { }
+
+storage.register("xml/entities", xml.entities, "xml.entities" )
+
+local entities = xml.entities -- maybe some day properties
+
+function xml.registerentity(key,value)
+ entities[key] = value
+ if trace_entities then
+ report_xml("registering entity %a as %a",key,value)
+ end
+end
+
+if characters and characters.entities then
+
+ -- the big entity table also has amp, quot, apos, lt, gt in them
+
+ local loaded = false
+
+ function characters.registerentities(forcecopy)
+ if loaded then
+ return
+ end
+ if forcecopy then
+ setmetatableindex(entities,nil)
+ for name, value in next, characters.entities do
+ if not entities[name] then
+ entities[name] = value
+ end
+ end
+ else
+ setmetatableindex(entities,characters.entities)
+ end
+ loaded = true
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua
new file mode 100644
index 00000000000..8f1157c7d4c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua
@@ -0,0 +1,58 @@
+if not modules then modules = { } end modules ['lxml-inf'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This file will be loaded runtime by x-pending.tex.
+
+local concat = table.concat
+
+local xmlwithelements = xml.withelements
+local getid = lxml.getid
+
+local status, stack
+
+local function get(e,d)
+ local ns, tg = e.ns, e.tg
+ local name = tg
+ if ns ~= "" then name = ns .. ":" .. tg end
+ stack[d] = name
+ local ec = e.command
+ if ec == true then
+ ec = "system: text"
+ elseif ec == false then
+ ec = "system: skip"
+ elseif ec == nil then
+ ec = "system: not set"
+ elseif type(ec) == "string" then
+ ec = "setup: " .. ec
+ else -- function
+ ec = tostring(ec)
+ end
+ local tag = concat(stack," => ",1,d)
+ local s = status[tag]
+ if not s then
+ s = { }
+ status[tag] = s
+ end
+ s[ec] = (s[ec] or 0) + 1
+end
+
+local function get_command_status(id)
+ status, stack = {}, {}
+ if id then
+ xmlwithelements(getid(id),get)
+ return status
+ else
+ local t = { }
+ for id, _ in next, loaded do
+ t[id] = get_command_status(id)
+ end
+ return t
+ end
+end
+
+lxml.get_command_status = get_command_status
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.lua
new file mode 100644
index 00000000000..6026b1090bc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.lua
@@ -0,0 +1,143 @@
+ if not modules then modules = { } end modules ['lxml-ini'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local xml = xml
+local lxml = lxml
+
+-- this defines an extra scanner lxmlid:
+
+local scanners = tokens.scanners
+local scanstring = scanners.string
+local getid = lxml.id
+
+scanners.lxmlid = function() return getid(scanstring()) end
+
+local implement = interfaces.implement
+
+-- lxml.id
+
+implement { name = "lxmlid", actions = lxml.getid, arguments = "string" }
+
+implement { name = "xmldoif", actions = lxml.doif, arguments = { "string", "string" } }
+implement { name = "xmldoifnot", actions = lxml.doifnot, arguments = { "string", "string" } }
+implement { name = "xmldoifelse", actions = lxml.doifelse, arguments = { "string", "string" } }
+implement { name = "xmldoiftext", actions = lxml.doiftext, arguments = { "string", "string" } }
+implement { name = "xmldoifnottext", actions = lxml.doifnottext, arguments = { "string", "string" } }
+implement { name = "xmldoifelsetext", actions = lxml.doifelsetext, arguments = { "string", "string" } }
+
+implement { name = "xmldoifempty", actions = lxml.doifempty, arguments = { "string", "string" } }
+implement { name = "xmldoifnotempty", actions = lxml.doifnotempty, arguments = { "string", "string" } }
+implement { name = "xmldoifelseempty", actions = lxml.doifelseempty, arguments = { "string", "string" } }
+implement { name = "xmldoifselfempty", actions = lxml.doifempty, arguments = "string" } -- second arg is not passed (used)
+implement { name = "xmldoifnotselfempty", actions = lxml.doifnotempty, arguments = "string" } -- second arg is not passed (used)
+implement { name = "xmldoifelseselfempty", actions = lxml.doifelseempty, arguments = "string" } -- second arg is not passed (used)
+
+--------- { name = "xmlcontent", actions = lxml.content, arguments = "string" }
+--------- { name = "xmlflushstripped", actions = lxml.strip, arguments = { "string", true } }
+implement { name = "xmlall", actions = lxml.all, arguments = { "string", "string" } }
+implement { name = "xmllastmatch", actions = lxml.lastmatch }
+implement { name = "xmlatt", actions = lxml.att, arguments = { "string", "string" } }
+implement { name = "xmllastatt", actions = lxml.lastatt }
+implement { name = "xmlattdef", actions = lxml.att, arguments = { "string", "string", "string" } }
+implement { name = "xmlattribute", actions = lxml.attribute, arguments = { "string", "string", "string" } }
+implement { name = "xmlattributedef", actions = lxml.attribute, arguments = { "string", "string", "string", "string" } }
+implement { name = "xmlpath", actions = lxml.path, arguments = { "string", "'/'" } }
+implement { name = "xmlchainatt", actions = lxml.chainattribute, arguments = { "string", "'/'", "string" } }
+implement { name = "xmlchainattdef", actions = lxml.chainattribute, arguments = { "string", "'/'", "string", "string" } }
+implement { name = "xmlrefatt", actions = lxml.refatt, arguments = { "string", "string" } }
+implement { name = "xmlchecknamespace", actions = xml.checknamespace, arguments = { "lxmlid", "string", "string" } }
+implement { name = "xmlcommand", actions = lxml.command, arguments = { "string", "string", "string" } }
+implement { name = "xmlconcat", actions = lxml.concat, arguments = { "string", "string", "string" } } -- \detokenize{#3}
+implement { name = "xmlconcatrange", actions = lxml.concatrange, arguments = { "string", "string", "string", "string", "string" } } -- \detokenize{#5}
+implement { name = "xmlcontext", actions = lxml.context, arguments = { "string", "string" } }
+implement { name = "xmlcount", actions = lxml.count, arguments = { "string", "string" } }
+implement { name = "xmldelete", actions = lxml.delete, arguments = { "string", "string" } }
+implement { name = "xmldirect", actions = lxml.direct, arguments = "string" }
+implement { name = "xmldirectives", actions = lxml.directives.setup, arguments = "string" }
+implement { name = "xmldirectivesafter", actions = lxml.directives.after, arguments = "string" }
+implement { name = "xmldirectivesbefore", actions = lxml.directives.before, arguments = "string" }
+implement { name = "xmldisplayverbatim", actions = lxml.displayverbatim, arguments = "string" }
+implement { name = "xmlelement", actions = lxml.element, arguments = { "string", "string" } } -- could be integer but now we can alias
+implement { name = "xmlfilter", actions = lxml.filter, arguments = { "string", "string" } }
+implement { name = "xmlfilterlist", actions = lxml.filterlist, arguments = { "string", "string" } }
+implement { name = "xmlfirst", actions = lxml.first, arguments = { "string", "string" } }
+implement { name = "xmlflush", actions = lxml.flush, arguments = "string" }
+implement { name = "xmlflushcontext", actions = lxml.context, arguments = "string" }
+implement { name = "xmlflushlinewise", actions = lxml.flushlinewise, arguments = "string" }
+implement { name = "xmlflushspacewise", actions = lxml.flushspacewise, arguments = "string" }
+implement { name = "xmlfunction", actions = lxml.applyfunction, arguments = { "string", "string" } }
+implement { name = "xmlinclude", actions = lxml.include, arguments = { "string", "string", "string", true } }
+implement { name = "xmlincludeoptions", actions = lxml.include, arguments = { "string", "string", "string", "string" } }
+implement { name = "xmlinclusion", actions = lxml.inclusion, arguments = "string" }
+implement { name = "xmlinclusions", actions = lxml.inclusions, arguments = "string" }
+implement { name = "xmlbadinclusions", actions = lxml.badinclusions, arguments = "string" }
+implement { name = "xmlindex", actions = lxml.index, arguments = { "string", "string", "string" } } -- can be integer but now we can alias
+implement { name = "xmlinlineverbatim", actions = lxml.inlineverbatim, arguments = "string" }
+implement { name = "xmllast", actions = lxml.last, arguments = { "string", "string" } }
+implement { name = "xmlload", actions = lxml.load, arguments = { "string", "string", "string" } }
+implement { name = "xmlloadbuffer", actions = lxml.loadbuffer, arguments = { "string", "string", "string" } }
+implement { name = "xmlloaddata", actions = lxml.loaddata, arguments = { "string", "string", "string" } }
+implement { name = "xmlloaddirectives", actions = lxml.directives.load, arguments = "string" }
+implement { name = "xmlmain", actions = lxml.main, arguments = "string" }
+implement { name = "xmlmatch", actions = lxml.match, arguments = "string" }
+implement { name = "xmlname", actions = lxml.name, arguments = "string" }
+implement { name = "xmlnamespace", actions = lxml.namespace, arguments = "string" }
+implement { name = "xmlnonspace", actions = lxml.nonspace, arguments = { "string", "string" } }
+implement { name = "xmlpos", actions = lxml.pos, arguments = "string" }
+implement { name = "xmlraw", actions = lxml.raw, arguments = { "string", "string" } }
+implement { name = "xmlrawtex", actions = lxml.rawtex, arguments = { "string", "string" } }
+implement { name = "xmlregisterns", actions = xml.registerns, arguments = { "string", "string" } }
+implement { name = "xmlremapname", actions = xml.remapname, arguments = { "lxmlid", "string","string","string" } }
+implement { name = "xmlremapnamespace", actions = xml.renamespace, arguments = { "lxmlid", "string", "string" } }
+implement { name = "xmlsave", actions = lxml.save, arguments = { "string", "string" } }
+implement { name = "xmlsetsetup", actions = lxml.setsetup, arguments = { "string", "string", "string" } }
+implement { name = "xmlsnippet", actions = lxml.snippet, arguments = { "string", "string" } }
+implement { name = "xmlstrip", actions = lxml.strip, arguments = { "string", "string" } }
+implement { name = "xmlstripanywhere", actions = lxml.strip, arguments = { "string", "string", true, true } }
+implement { name = "xmlstripnolines", actions = lxml.strip, arguments = { "string", "string", true } }
+implement { name = "xmlstripped", actions = lxml.stripped, arguments = { "string", "string" } }
+implement { name = "xmlstrippednolines", actions = lxml.stripped, arguments = { "string", "string", true } }
+implement { name = "xmltag", actions = lxml.tag, arguments = "string" }
+implement { name = "xmltext", actions = lxml.text, arguments = { "string", "string" } }
+implement { name = "xmlpure", actions = lxml.pure, arguments = { "string", "string" } }
+implement { name = "xmlflushtext", actions = lxml.text, arguments = "string" }
+implement { name = "xmlflushpure", actions = lxml.pure, arguments = "string" }
+implement { name = "xmltobuffer", actions = lxml.tobuffer, arguments = { "string", "string", "string" } }
+implement { name = "xmltobufferverbose", actions = lxml.tobuffer, arguments = { "string", "string", "string", true } }
+implement { name = "xmltofile", actions = lxml.tofile, arguments = { "string", "string", "string" } }
+implement { name = "xmltoparameters", actions = lxml.toparameters, arguments = "string" }
+implement { name = "xmlverbatim", actions = lxml.verbatim, arguments = "string" }
+
+implement { name = "xmlstartraw", actions = lxml.startraw }
+implement { name = "xmlstopraw", actions = lxml.stopraw }
+
+implement { name = "xmlprependsetup", actions = lxml.installsetup, arguments = { 1, "string", "string" } } -- 2:*
+implement { name = "xmlappendsetup", actions = lxml.installsetup, arguments = { 2, "string", "string" } } -- 2:*
+implement { name = "xmlbeforesetup", actions = lxml.installsetup, arguments = { 3, "string", "string", "string" } } -- 2:*
+implement { name = "xmlaftersetup", actions = lxml.installsetup, arguments = { 4, "string", "string", "string" } } -- 2:*
+implement { name = "xmlremovesetup", actions = lxml.removesetup, arguments = { "string", "string" } } -- 1:*
+implement { name = "xmlflushsetups", actions = lxml.flushsetups, arguments = { "string", "string", "string" } } -- 2:*
+implement { name = "xmlresetsetups", actions = lxml.resetsetups, arguments = "string" }
+
+implement { name = "xmlgetindex", actions = lxml.getindex, arguments = { "string", "string" } }
+implement { name = "xmlwithindex", actions = lxml.withindex, arguments = { "string", "string", "string" } }
+
+implement { name = "xmlsetentity", actions = xml.registerentity, arguments = { "string", "string" } }
+implement { name = "xmltexentity", actions = lxml.registerentity, arguments = { "string", "string" } }
+
+implement { name = "xmlsetcommandtotext", actions = lxml.setcommandtotext, arguments = "string" }
+implement { name = "xmlsetcommandtonone", actions = lxml.setcommandtonone, arguments = "string" }
+
+implement { name = "xmlstarttiming", actions = function() statistics.starttiming(lxml) end }
+implement { name = "xmlstoptiming", actions = function() statistics.stoptiming (lxml) end }
+
+implement { name = "xmlloadentities", actions = characters.registerentities, onceonly = true }
+
+-- kind of special (3rd argument is a function)
+
+commands.xmlsetfunction = lxml.setaction
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv
new file mode 100644
index 00000000000..6fa14ddfc8b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv
@@ -0,0 +1,517 @@
+%D \module
+%D [ file=lxml-ini,
+%D version=2007.08.17,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Todo: auto apply setups (manage at lua end)
+%D Todo: manuak: \xmlinclusion \xmlinclusions
+
+\writestatus{loading}{ConTeXt XML Support / Initialization}
+
+%registerctxluafile{lxml-tab}{1.001} % loader
+%registerctxluafile{lxml-lpt}{1.001} % parser
+%registerctxluafile{lxml-xml}{1.001} % xml finalizers
+%registerctxluafile{lxml-aux}{1.001} % extras using parser
+%registerctxluafile{lxml-mis}{1.001} % extras independent of parser
+\registerctxluafile{lxml-ent}{1.001} % entity hacks
+\registerctxluafile{lxml-tex}{1.001} % tex finalizers
+\registerctxluafile{lxml-dir}{1.001} % ctx hacks
+\registerctxluafile{lxml-ini}{1.001} % interface
+
+\unprotect
+
+% todo: { } mandate so that we can alias
+
+% undocumented:
+
+\def\ctxlxml #1{\ctxlua{lxml.#1}}
+
+% 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}}
+
+% aliased
+
+\let\xmlall \clf_xmlall
+\let\xmlatt \clf_xmlatt
+\let\xmlattdef \clf_xmlattdef
+\let\xmlattribute \clf_xmlattribute
+\let\xmlattributedef \clf_xmlattributedef
+\let\xmlchainatt \clf_xmlchainatt
+\let\xmlchainattdef \clf_xmlchainattdef
+\let\xmlchecknamespace \clf_xmlchecknamespace
+\let\xmlcommand \clf_xmlcommand
+\let\xmlcontext \clf_xmlcontext
+\let\xmlcount \clf_xmlcount
+\let\xmldelete \clf_xmldelete
+\let\xmldirect \clf_xmldirect % in loops, not dt but root
+\let\xmldirectives \clf_xmldirectives
+\let\xmldirectivesafter \clf_xmldirectivesafter
+\let\xmldirectivesbefore \clf_xmldirectivesbefore
+\let\xmldisplayverbatim \clf_xmldisplayverbatim
+\let\xmlelement \clf_xmlelement
+\let\xmlfilter \clf_xmlfilter
+\let\xmlfilterlist \clf_xmlfilterlist
+\let\xmlfirst \clf_xmlfirst
+\let\xmlflush \clf_xmlflush
+\let\xmlflushcontext \clf_xmlflushcontext
+\let\xmlflushlinewise \clf_xmlflushlinewise
+\let\xmlflushpure \clf_xmlflushpure
+\let\xmlflushspacewise \clf_xmlflushspacewise
+\let\xmlflushtext \clf_xmlflushtext
+\let\xmlfunction \clf_xmlfunction
+\let\xmlinclude \clf_xmlinclude
+\let\xmlincludeoptions \clf_xmlincludeoptions
+\let\xmlinclusion \clf_xmlinclusion
+\let\xmlinclusions \clf_xmlinclusions
+\let\xmlbadinclusions \clf_xmlbadinclusions
+\let\xmlindex \clf_xmlindex
+\let\xmlinlineverbatim \clf_xmlinlineverbatim
+\let\xmllast \clf_xmllast
+\let\xmllastatt \clf_xmllastatt
+\let\xmllastmatch \clf_xmllastmatch
+\let\xmlloaddirectives \clf_xmlloaddirectives
+\let\xmlmain \clf_xmlmain
+\let\xmlmatch \clf_xmlmatch
+\let\xmlname \clf_xmlname
+\let\xmlnamespace \clf_xmlnamespace
+\let\xmlnonspace \clf_xmlnonspace
+\let\xmlpath \clf_xmlpath
+\let\xmlpos \clf_xmlpos
+\let\xmlposition \clf_xmlindex
+\let\xmlpure \clf_xmlpure
+\let\xmlraw \clf_xmlraw
+\let\xmlrefatt \clf_xmlrefatt
+\let\xmlregisterns \clf_xmlregisterns % document
+\let\xmlremapname \clf_xmlremapname % element
+\let\xmlremapnamespace \clf_xmlremapnamespace % document
+\let\xmlsave \clf_xmlsave
+\let\xmlsetsetup \clf_xmlsetsetup
+\let\xmlsnippet \clf_xmlsnippet
+\let\xmlstrip \clf_xmlstrip
+\let\xmlstripanywhere \clf_xmlstripanywhere
+\let\xmlstripnolines \clf_xmlstripnolines
+\let\xmlstripped \clf_xmlstripped
+\let\xmlstrippednolines \clf_xmlstrippednolines
+\let\xmltag \clf_xmltag
+\let\xmltext \clf_xmltext
+\let\xmltobuffer \clf_xmltobuffer % id pattern name
+\let\xmltobufferverbose \clf_xmltobufferverbose % id pattern name
+\let\xmltofile \clf_xmltofile % id pattern filename
+\let\xmltoparameters \clf_xmltoparameters
+\let\xmlverbatim \clf_xmlverbatim
+
+\unexpanded\def\xmlinfo #1{\hbox{\ttxx[\clf_xmlname{#1}]}}
+\unexpanded\def\xmlshow #1{\startpacked\ttx\xmlverbatim{#1}\stoppacked}
+
+% the next one is handy for mode runs because it enforces a consistent
+% #1 indexing (needed when using \xmltext{main:123}{...} like calls
+
+\let\xmladdindex \clf_xmladdindex
+
+% we need to pass the last argument as function, so
+
+\unexpanded\def\xmlsetfunction#1#2#3{\ctxcommand{xmlsetfunction("#1",\!!bs#2\!!es,#3)}}
+
+% goodie:
+
+\unexpanded\def\xmlprettyprint#1#2%
+ {\xmltobufferverbose{#1}{.}{xml-temp}%
+ \ifdefined\scitebuffer
+ \scitebuffer[#2][xml-temp]%
+ \else
+ \typebuffer[xml-temp][\c!option=#2]%
+ \fi}
+
+% kind of special:
+
+\let\xmlstartraw\clf_xmlstartraw
+\let\xmlstopraw \clf_xmlstopraw
+
+\let\startxmlraw\clf_xmlstartraw
+\let\stopxmlraw \clf_xmlstopraw
+
+% these are expandable! todo: \xmldoifelseattribute
+
+\let\xmldoif \clf_xmldoif
+\let\xmldoifnot \clf_xmldoifnot
+\let\xmldoifelse \clf_xmldoifelse
+\let\xmldoiftext \clf_xmldoiftext
+\let\xmldoifnottext \clf_xmldoifnottext
+\let\xmldoifelsetext \clf_xmldoifelsetext
+
+\let\xmldoifempty \clf_xmldoifempty
+\let\xmldoifnotempty \clf_xmldoifnotempty
+\let\xmldoifelseempty \clf_xmldoifelseempty
+\let\xmldoifselfempty \clf_xmldoifselfempty
+\let\xmldoifnotselfempty \clf_xmldoifnotselfempty
+\let\xmldoifelseselfempty \clf_xmldoifelseselfempty
+
+\let\xmldoiftextelse \xmldoifelsetext
+\let\xmldoifemptyelse \xmldoifelseempty
+\let\xmldoifselfemptyelse \xmldoifelseselfempty
+
+% \startxmlsetups xml:include
+% \xmlinclude{main}{include}{filename|href}
+% \stopxmlsetups
+%
+% \xmlprependsetup{xml:include}
+
+% \let\xmlgrab\xmlsetsetup % obsolete
+% \let\xmlself\s!unknown % obsolete
+
+\let\xmlsetup\setupwithargumentswapped
+\let\xmls \setupwithargumentswapped % hardly any faster
+\let\xmlw \setupwithargument % hardly any faster
+
+% todo: 1:xml:whatever always before 3:xml:something
+
+\unexpanded\def\xmlprependsetup #1{\clf_xmlprependsetup{*}{#1}}
+\unexpanded\def\xmlappendsetup #1{\clf_xmlappendsetup {*}{#1}}
+\unexpanded\def\xmlbeforesetup #1#2{\clf_xmlbeforesetup {*}{#1}{#2}}
+\unexpanded\def\xmlaftersetup #1#2{\clf_xmlaftersetup {*}{#1}{#2}}
+\unexpanded\def\xmlremovesetup #1{\clf_xmlremovesetup {*}{#1}}
+\unexpanded\def\xmlresetsetups {\clf_xmlresetsetups {*}}
+
+\unexpanded\def\xmlprependdocumentsetup #1#2{\clf_xmlprependsetup{#1}{#2}}
+\unexpanded\def\xmlappenddocumentsetup #1#2{\clf_xmlappendsetup {#1}{#2}}
+\unexpanded\def\xmlbeforedocumentsetup #1#2#3{\clf_xmlbeforesetup {#1}{#2}{#3}}
+\unexpanded\def\xmlafterdocumentsetup #1#2#3{\clf_xmlaftersetup {#1}{#2}{#3}}
+\unexpanded\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}}
+\unexpanded\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}}
+
+\unexpanded\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2
+
+\let\xmlregistersetup \xmlappendsetup
+\let\xmlregisterdocumentsetup\xmlappenddocumentsetup
+
+\def\xmldocument{main}
+
+\unexpanded\def\xmlregisteredsetups
+ {\xmlstarttiming
+ \xmlflushsetups
+ \xmldefaulttotext\xmldocument % after include
+ \xmlstoptiming}
+
+\unexpanded\def\xmlregistereddocumentsetups#1#2% id setups
+ {\xmlstarttiming
+ % todo: test for duplicates !
+ \xmlflushdocumentsetups{#1}{#2}%
+ \xmldefaulttotext{#1}% after include
+ \xmlstoptiming}
+
+\unexpanded\def\xmlstarttiming{\clf_xmlstarttiming} % undocumented
+\unexpanded\def\xmlstoptiming {\clf_xmlstoptiming} % undocumented
+
+\def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup
+ {\begingroup
+ \edef\xmldocument{#3}% #2 can be \xmldocument and set as such
+ %xmlpushdocument{#3}%
+ #2{#3}{#4}%
+ \setcatcodetable\notcatcodes
+ \doifelsenothing{#5}
+ {\xmlsetup{#3}{xml:process}}
+ {\xmlsetup{#3}{#5}}%
+ %xmlpopdocument
+ \endgroup}
+
+\unexpanded\def\xmlprocessfile {\lxml_process\plusone \xmlload}
+\unexpanded\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata}
+\unexpanded\def\xmlprocessbuffer {\lxml_process\zerocount\xmlloadbuffer}
+ \let\xmlprocess \xmlprocessfile
+
+\startxmlsetups xml:flush
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:process
+ \xmlregistereddocumentsetups{#1}{#1}
+ \xmlmain{#1}
+\stopxmlsetups
+
+\unexpanded\def\xmlloadonly#1#2#3%
+ {\xmlload{#1}{#2}%
+ \xmlregistereddocumentsetups{#1}{#3}}
+
+% replaced by concat
+%
+% \unexpanded\def\xmlconnect#1#2#3% inefficient
+% {\scratchcounter\xmlcount{#1}{#2}\relax
+% \ifcase\scratchcounter \or
+% \xmlall{#1}{#2}%
+% \else
+% \dorecurse \scratchcounter
+% {\ifnum\recurselevel>\plusone#3\fi
+% \xmlidx{#1}{#2}\recurselevel}%
+% \fi}
+
+\unexpanded\def\xmlcdataobeyedline {\obeyedline}
+\unexpanded\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\unexpanded\def\xmlcdatabefore {\begingroup\tt}
+\unexpanded\def\xmlcdataafter {\endgroup}
+
+% verbatim (dodo:pre/post whitespace, maybe splot verbatim and
+% cdata commands), experimental:
+%
+% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim}
+% \xmlsetfunction{main}{verb} {lxml.inlineverbatim}
+
+% we use an xml: namespace so one has to define a suitable verbatim, say
+%
+% \definetyping[xml:verbatim][typing]
+%
+% this is experimental!
+
+\unexpanded\def\startxmldisplayverbatim
+ {\dosingleempty\lxml_start_display_verbatim}
+
+\def\lxml_start_display_verbatim[#1]%
+ {\startpacked
+ \edef\currenttyping{#1}%
+ \ifx\currenttyping\empty
+ \let\currenttyping\v!typing
+ \else % maybe test for existence
+ \edef\currenttyping{xml:\currenttyping}%
+ \fi
+ \unexpanded\def\stopxmldisplayverbatim
+ {\endofverbatimlines
+ \stoppacked}
+ \doinitializeverbatim
+ \beginofverbatimlines}
+
+\unexpanded\def\startxmlinlineverbatim
+ {\dosingleempty\lxml_start_inline_verbatim}
+
+\unexpanded\def\lxml_start_inline_verbatim[#1]%
+ {\begingroup
+ \edef\currenttype{#1}%
+ \ifx\currenttype\empty
+ \let\currenttype\v!type
+ \else % maybe test for existence
+ \edef\currenttype{xml:\currenttype}%
+ \fi
+ \let\stopxmlinlineverbatim\endgroup
+ \doinitializeverbatim}
+
+% processing instructions
+
+\unexpanded\def\xmlinstalldirective#1#2%
+ {\clf_xmlinstalldirective{#1}{\csstring#2}}
+
+% \def\xmlcontextdirective#1% kind class key value
+% {\executeifdefined{xml#1directive}\gobblethreearguments}
+
+% setting up xml:
+%
+% \setupxml[\c!default=] % mkiv only == text
+% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden
+% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text
+
+% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}}
+
+\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden
+
+\installcorenamespace{xml}
+\installcorenamespace{xmldefaults}
+\installcorenamespace{xmlmapvalue}
+
+\installdirectcommandhandler \??xml {xml}
+
+\letvalue{\??xmldefaults\v!normal}\zerocount
+\letvalue{\??xmldefaults\v!none }\zerocount
+\letvalue{\??xmldefaults\v!text }\plusone
+\letvalue{\??xmldefaults\v!hidden}\plustwo
+
+\unexpanded\def\xmldefaulttotext
+ {\ifcase\xmlprocessingmode
+ \expandafter\gobbleoneargument % 0 (none)
+ \or
+ \expandafter\clf_xmlsetcommandtotext % 1 (normal)
+ \or
+ \expandafter\clf_xmlsetcommandtonone % 2 (hidden)
+ \else
+ \expandafter\gobbleoneargument % (none)
+ \fi}
+
+\appendtoks
+ \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone
+\to \everysetupxml
+
+\setupxml
+ [\c!default=, % flush all
+ \c!compress=\v!no, % strip comment
+ \c!entities=\v!no] % load big entity file
+
+\appendtoks
+ \doif{\directxmlparameter\c!entities}\clf_xmlloadentities
+\to \everysetupxml
+
+\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces
+\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+
+\def\xmlvalue#1#2% #3
+ {\ifcsname\??xmlmapvalue#1:#2\endcsname
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\xmlmappedvalue#1#2#3%
+ {\ifcsname\??xmlmapvalue#1:#2\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \csname\??xmlmapvalue#1:#3\expandafter\endcsname
+ \fi}
+
+\let\xmldoifvalueelse\xmldoifelsevalue
+
+\let\xmlmapval\xmlmapvalue
+\let\xmlval \xmlvalue
+
+%D Experimental:
+
+\def\xmlgetindex #1{\clf_xmlgetindex {\xmldocument}{#1}}
+\def\xmlwithindex #1#2{\clf_xmlwithindex{\xmldocument}{#1}{#2}}
+\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}}
+
+%D Entities:
+%D
+%D \starttyping
+%D \xmlsetentity{tex}{\TEX{}} % {} needed
+%D \stoptyping
+
+\unexpanded\def\xmlsetentity#1#2{\clf_xmlsetentity{#1}{\detokenize{#2}}}
+\unexpanded\def\xmltexentity#1#2{\clf_xmltexentity{#1}{\detokenize{#2}}}
+
+%D The following might change (or even disappear) so we keep it undocumented.
+
+\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower
+
+\unexpanded\def\xmle
+ {\ifcase\xmlautoentities
+ \expandafter\lxml_e_none
+ \or
+ \expandafter\lxml_e_upper
+ \or
+ \expandafter\lxml_e_upperlower
+ \else
+ \expandafter\lxml_e_none
+ \fi}
+
+\def\lxml_e_none#1#2% safe
+ {#1}
+
+\def\lxml_e_upper#1#2% can be abbreviation
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \else
+ #1%
+ \fi}
+
+\def\lxml_e_upperlower#1#2% can be anything, so unsafe
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \else\ifcsname#1\endcsname
+ \csname#1\expandafter\expandafter\expandafter\endcsname
+ \else
+ #1%
+ \fi\fi}
+
+% \def\lxml_e_upper#1#2% can be abbreviation
+% {\ifcsname\detokenize{#2}\endcsname
+% \lastnamedcs
+% \else
+% \detokenize{#1}%
+% \fi}
+
+% \def\lxml_e_upperlower#1#2% can be anything, so unsafe
+% {\ifcsname\detokenize{#2}\endcsname
+% \expandafter\lastnamedcs
+% \else\ifcsname\detokenize{#1}\endcsname
+% \doubleexpandafter\lastnamedcs
+% \else
+% \detokenize{#1}%
+% \fi\fi}
+
+%D We keep these around as there are also MP, LUA and TEX variants but
+%D they are not the same as in \MKII.
+
+\unexpanded\def\processXMLbuffer
+ {\dosingleempty\lxml_process_buffer}
+
+\def\lxml_process_buffer[#1]%
+ {\xmlprocessbuffer{temp}{#1}{}}
+
+\unexpanded\def\processXMLfile#1%
+ {\xmlprocessfile{temp}{#1}{}}
+
+\unexpanded\def\XMLdata#1%
+ {\xmlprocessdata{temp}{#1}{}}
+
+\let\processxmlbuffer\processXMLbuffer
+\let\processxmlfile \processXMLfile
+\let\xmldata \XMLdata
+
+\unexpanded\def\xmlsetinjectors[#1]%
+ {\clf_xmlsetinjectors{#1}}
+
+\unexpanded\def\xmlresetinjectors
+ {\clf_xmlresetinjectors{}}
+
+% \def\xmlinjector#1{\executeifdefined{#1}\donothing}
+
+\def\xmlinjector#1{\fastsetup{xml:directive:injector:#1}}
+
+\startsetups xml:directive:injector:page
+ \page
+\stopsetups
+
+\startsetups xml:directive:injector:column
+ \column
+\stopsetups
+
+\startsetups xml:directive:injector:blank
+ \blank
+\stopsetups
+
+\startsetups xml:directive:injector:noline
+ \vskip-\lineheight
+\stopsetups
+
+\let\xmlapplyselectors\clf_xmlapplyselectors
+
+% \let\xmlcatcodes\notcatcodes
+
+\protect \endinput
+
+% \newcount\charactersactiveoffset \charactersactiveoffset="10000
+%
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \startextendcatcodetable\xmlcatcodes % not needed
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \ctxlua { % entities are remembered in the format
+% commands.remapentity("<",characters.activeoffset + utf.byte("<"))
+% commands.remapentity("&",characters.activeoffset + utf.byte("&"))
+% commands.remapentity(">",characters.activeoffset + utf.byte(">"))
+% }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua
new file mode 100644
index 00000000000..b722fc318bc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua
@@ -0,0 +1,1586 @@
+if not modules then modules = { } end modules ['lxml-lpt'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- e.ni is only valid after a filter run
+-- todo: B/C/[get first match]
+
+local concat, remove, insert = table.concat, table.remove, table.insert
+local type, next, tonumber, tostring, setmetatable, load, select = type, next, tonumber, tostring, setmetatable, load, select
+local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters -- no need (yet) as paths are cached anyway
+
+-- beware, this is not xpath ... e.g. position is different (currently) and
+-- we have reverse-sibling as reversed preceding sibling
+
+--[[ldx--
+<p>This module can be used stand alone but also inside <l n='mkiv'/> in
+which case it hooks into the tracker code. Therefore we provide a few
+functions that set the tracers. Here we overload a previously defined
+function.</p>
+<p>If I can get in the mood I will make a variant that is XSLT compliant
+but I wonder if it makes sense.</P>
+--ldx]]--
+
+--[[ldx--
+<p>Expecially the lpath code is experimental, we will support some of xpath, but
+only things that make sense for us; as compensation it is possible to hook in your
+own functions. Apart from preprocessing content for <l n='context'/> we also need
+this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
+files.</p>
+
+<typing>
+a/b/c /*/c
+a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
+a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
+</typing>
+--ldx]]--
+
+local trace_lpath = false
+local trace_lparse = false
+local trace_lprofile = false
+local report_lpath = logs.reporter("xml","lpath")
+
+if trackers then
+ trackers.register("xml.path", function(v)
+ trace_lpath = v
+ end)
+ trackers.register("xml.parse", function(v)
+ trace_lparse = v
+ end)
+ trackers.register("xml.profile", function(v)
+ trace_lpath = v
+ trace_lparse = v
+ trace_lprofile = v
+ end)
+end
+
+--[[ldx--
+<p>We've now arrived at an interesting part: accessing the tree using a subset
+of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
+will explain more about its usage in other documents.</p>
+--ldx]]--
+
+local xml = xml
+
+local lpathcalls = 0 function xml.lpathcalls () return lpathcalls end
+local lpathcached = 0 function xml.lpathcached() return lpathcached end
+
+xml.functions = xml.functions or { } -- internal
+local functions = xml.functions
+
+xml.expressions = xml.expressions or { } -- in expressions
+local expressions = xml.expressions
+
+xml.finalizers = xml.finalizers or { } -- fast do-with ... (with return value other than collection)
+local finalizers = xml.finalizers
+
+xml.specialhandler = xml.specialhandler or { }
+local specialhandler = xml.specialhandler
+
+lpegpatterns.xml = lpegpatterns.xml or { }
+local xmlpatterns = lpegpatterns.xml
+
+finalizers.xml = finalizers.xml or { }
+finalizers.tex = finalizers.tex or { }
+
+local function fallback (t, name)
+ local fn = finalizers[name]
+ if fn then
+ t[name] = fn
+ else
+ report_lpath("unknown sub finalizer %a",name)
+ fn = function() end
+ end
+ return fn
+end
+
+setmetatableindex(finalizers.xml, fallback)
+setmetatableindex(finalizers.tex, fallback)
+
+xml.defaultprotocol = "xml"
+
+-- as xsl does not follow xpath completely here we will also
+-- be more liberal especially with regards to the use of | and
+-- the rootpath:
+--
+-- test : all 'test' under current
+-- /test : 'test' relative to current
+-- a|b|c : set of names
+-- (a|b|c) : idem
+-- ! : not
+--
+-- after all, we're not doing transformations but filtering. in
+-- addition we provide filter functions (last bit)
+--
+-- todo: optimizer
+--
+-- .. : parent
+-- * : all kids
+-- / : anchor here
+-- // : /**/
+-- ** : all in between
+--
+-- so far we had (more practical as we don't transform)
+--
+-- {/test} : kids 'test' under current node
+-- {test} : any kid with tag 'test'
+-- {//test} : same as above
+
+-- evaluator (needs to be redone, for the moment copied)
+
+-- todo: apply_axis(list,notable) and collection vs single
+
+local apply_axis = { }
+
+apply_axis['root'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local rt = ll
+ while ll do
+ ll = ll.__p__
+ if ll then
+ rt = ll
+ end
+ end
+ collected[l] = rt
+ end
+ return collected
+end
+
+apply_axis['self'] = function(list)
+--~ 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
+ 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]
+ if dk.tg then
+ c = c + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ end
+ end
+ ll.en = en
+ end
+ end
+ return collected
+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]
+ if dk.tg then
+ c = c + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ c = collect(dk,collected,c)
+ end
+ end
+ list.en = en
+ end
+ return c
+end
+
+apply_axis['descendant'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ c = collect(list[l],collected,c)
+ end
+ return collected
+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]
+ if dk.tg then
+ c = c + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ c = collect(dk,collected,c)
+ end
+ end
+ list.en = en
+ end
+ return c
+end
+apply_axis['descendant-or-self'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ local ll = list[l]
+ if ll.special ~= true then -- catch double root
+ c = c + 1
+ collected[c] = ll
+ end
+ c = collect(ll,collected,c)
+ end
+ return collected
+end
+
+apply_axis['ancestor'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ local ll = list[l]
+ while ll do
+ ll = ll.__p__
+ if ll then
+ c = c + 1
+ collected[c] = ll
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['ancestor-or-self'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ local ll = list[l]
+ c = c + 1
+ collected[c] = ll
+ while ll do
+ ll = ll.__p__
+ if ll then
+ c = c + 1
+ collected[c] = ll
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['parent'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ local pl = list[l].__p__
+ if pl then
+ c = c + 1
+ collected[c] = pl
+ end
+ end
+ return collected
+end
+
+apply_axis['attribute'] = function(list)
+ return { }
+end
+
+apply_axis['namespace'] = function(list)
+ return { }
+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
+ 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
+ return { }
+end
+
+apply_axis['following-sibling'] = function(list)
+ 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
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['preceding-sibling'] = function(list)
+ local collected, c = { }, 0
+ for l=1,#list do
+ local ll = list[l]
+ local p = ll.__p__
+ local d = p.dt
+ for i=1,ll.ni-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ c = c + 1
+ collected[c] = di
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['reverse-sibling'] = function(list) -- reverse preceding
+ 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
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['auto-descendant-or-self'] = apply_axis['descendant-or-self']
+apply_axis['auto-descendant'] = apply_axis['descendant']
+apply_axis['auto-child'] = apply_axis['child']
+apply_axis['auto-self'] = apply_axis['self']
+apply_axis['initial-child'] = apply_axis['child']
+
+local function apply_nodes(list,directive,nodes)
+ -- todo: nodes[1] etc ... negated node name in set ... when needed
+ -- ... currently ignored
+ local maxn = #nodes
+ if maxn == 3 then --optimized loop
+ local nns, ntg = nodes[2], nodes[3]
+ if not nns and not ntg then -- wildcard
+ if directive then
+ return list
+ else
+ return { }
+ end
+ else
+ local collected, c, m, p = { }, 0, 0, nil
+ if not nns then -- only check tag
+ for l=1,#list do
+ 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
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ elseif ntg ~= ltg then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ end
+ end
+ elseif not ntg then -- only check namespace
+ for l=1,#list do
+ 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
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ elseif lns ~= nns then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ end
+ end
+ else -- check both
+ for l=1,#list do
+ local ll = list[l]
+ local ltg = ll.tg
+ if ltg then
+ local lns = ll.rn or ll.ns
+ 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
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ elseif not ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ end
+ end
+ end
+ return collected
+ end
+ else
+ local collected, c, m, p = { }, 0, 0, nil
+ for l=1,#list do
+ local ll = list[l]
+ local ltg = ll.tg
+ if ltg then
+ local lns = ll.rn or ll.ns
+ local ok = false
+ for n=1,maxn,3 do
+ local nns, ntg = nodes[n+1], nodes[n+2]
+ ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
+ if ok then
+ break
+ end
+ end
+ if directive then
+ if ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ elseif not ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ c = c + 1
+ collected[c], ll.mi = ll, m
+ end
+ end
+ end
+ return collected
+ end
+end
+
+local quit_expression = false
+
+local function apply_expression(list,expression,order)
+ local collected, c = { }, 0
+ quit_expression = false
+ for l=1,#list do
+ local ll = list[l]
+ if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
+ c = c + 1
+ collected[c] = ll
+ end
+ if quit_expression then
+ break
+ end
+ end
+ return collected
+end
+
+-- this one can be made faster but there are not that many conversions so it doesn't
+-- really pay of
+
+local P, V, C, Cs, Cc, Ct, R, S, Cg, Cb = lpeg.P, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cb
+
+local spaces = S(" \n\r\t\f")^0
+local lp_space = S(" \n\r\t\f")
+local lp_any = P(1)
+local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
+local lp_doequal = P("=") / "=="
+local lp_or = P("|") / " or "
+local lp_and = P("&") / " and "
+
+-- local lp_builtin = (
+-- P("text") / "(ll.dt[1] or '')" + -- fragile
+-- P("content") / "ll.dt" +
+-- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+-- P("tag") / "ll.tg" +
+-- P("position") / "l" + -- is element in finalizer
+-- P("firstindex") / "1" +
+-- P("lastindex") / "(#ll.__p__.dt or 1)" +
+-- P("firstelement") / "1" +
+-- P("lastelement") / "(ll.__p__.en or 1)" +
+-- P("first") / "1" +
+-- P("last") / "#list" +
+-- P("rootposition") / "order" +
+-- P("order") / "order" +
+-- P("element") / "(ll.ei or 1)" +
+-- P("index") / "(ll.ni or 1)" +
+-- P("match") / "(ll.mi or 1)" +
+-- P("namespace") / "ll.ns" +
+-- P("ns") / "ll.ns"
+-- ) * ((spaces * P("(") * spaces * P(")"))/"")
+
+local builtin = {
+ text = "(ll.dt[1] or '')", -- fragile
+ content = "ll.dt",
+ name = "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)",
+ tag = "ll.tg",
+ position = "l", -- is element in finalizer
+ firstindex = "1",
+ firstelement = "1",
+ first = "1",
+ lastindex = "(#ll.__p__.dt or 1)",
+ lastelement = "(ll.__p__.en or 1)",
+ last = "#list",
+ rootposition = "order",
+ order = "order",
+ element = "(ll.ei or 1)",
+ index = "(ll.ni or 1)",
+ match = "(ll.mi or 1)",
+ namespace = "ll.ns",
+ ns = "ll.ns",
+}
+
+local lp_builtin = lpeg.utfchartabletopattern(builtin)/builtin * ((spaces * P("(") * spaces * P(")"))/"")
+
+-- for the moment we keep namespaces with attributes
+
+local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
+
+----- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end
+----- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end
+
+local lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0"
+local lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))"
+local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+
+local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
+
+-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+-- return t .. "("
+-- end
+
+-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0("
+local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0"
+
+local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
+ if expressions[t] then
+ return "expr." .. t .. "("
+ else
+ return "expr.error("
+ end
+end
+
+local lparent = P("(")
+local rparent = P(")")
+local noparent = 1 - (lparent+rparent)
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
+
+local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
+local lp_number = S("+-") * R("09")^1
+local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'")
+local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"'))
+
+local cleaner
+
+local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * value / function(t,s)
+ if expressions[t] then
+ s = s and s ~= "" and lpegmatch(cleaner,s)
+ if s and s ~= "" then
+ return "expr." .. t .. "(ll," .. s ..")"
+ else
+ return "expr." .. t .. "(ll)"
+ end
+ else
+ return "expr.error(" .. t .. ")"
+ end
+end
+
+local content =
+ lp_builtin +
+ lp_attribute +
+ lp_special +
+ lp_noequal + lp_doequal +
+ lp_or + lp_and +
+ lp_reserved +
+ lp_lua_function + lp_function +
+ lp_content + -- too fragile
+ lp_child +
+ lp_any
+
+local converter = Cs (
+ lp_fastpos + (P { lparent * (V(1))^0 * rparent + content } )^0
+)
+
+cleaner = Cs ( (
+ -- lp_fastpos +
+ lp_reserved +
+ lp_number +
+ lp_string +
+1 )^1 )
+
+local template_e = [[
+ local expr = xml.expressions
+ return function(list,ll,l,order)
+ return %s
+ end
+]]
+
+local template_f_y = [[
+ local finalizer = xml.finalizers['%s']['%s']
+ return function(collection)
+ return finalizer(collection,%s)
+ end
+]]
+
+local template_f_n = [[
+ return xml.finalizers['%s']['%s']
+]]
+
+--
+
+local register_last_match = { kind = "axis", axis = "last-match" } -- , apply = apply_axis["self"] }
+local register_self = { kind = "axis", axis = "self" } -- , apply = apply_axis["self"] }
+local register_parent = { kind = "axis", axis = "parent" } -- , apply = apply_axis["parent"] }
+local register_descendant = { kind = "axis", axis = "descendant" } -- , apply = apply_axis["descendant"] }
+local register_child = { kind = "axis", axis = "child" } -- , apply = apply_axis["child"] }
+local register_descendant_or_self = { kind = "axis", axis = "descendant-or-self" } -- , apply = apply_axis["descendant-or-self"] }
+local register_root = { kind = "axis", axis = "root" } -- , apply = apply_axis["root"] }
+local register_ancestor = { kind = "axis", axis = "ancestor" } -- , apply = apply_axis["ancestor"] }
+local register_ancestor_or_self = { kind = "axis", axis = "ancestor-or-self" } -- , apply = apply_axis["ancestor-or-self"] }
+local register_attribute = { kind = "axis", axis = "attribute" } -- , apply = apply_axis["attribute"] }
+local register_namespace = { kind = "axis", axis = "namespace" } -- , apply = apply_axis["namespace"] }
+local register_following = { kind = "axis", axis = "following" } -- , apply = apply_axis["following"] }
+local register_following_sibling = { kind = "axis", axis = "following-sibling" } -- , apply = apply_axis["following-sibling"] }
+local register_preceding = { kind = "axis", axis = "preceding" } -- , apply = apply_axis["preceding"] }
+local register_preceding_sibling = { kind = "axis", axis = "preceding-sibling" } -- , apply = apply_axis["preceding-sibling"] }
+local register_reverse_sibling = { kind = "axis", axis = "reverse-sibling" } -- , apply = apply_axis["reverse-sibling"] }
+
+local register_auto_descendant_or_self = { kind = "axis", axis = "auto-descendant-or-self" } -- , apply = apply_axis["auto-descendant-or-self"] }
+local register_auto_descendant = { kind = "axis", axis = "auto-descendant" } -- , apply = apply_axis["auto-descendant"] }
+local register_auto_self = { kind = "axis", axis = "auto-self" } -- , apply = apply_axis["auto-self"] }
+local register_auto_child = { kind = "axis", axis = "auto-child" } -- , apply = apply_axis["auto-child"] }
+
+local register_initial_child = { kind = "axis", axis = "initial-child" } -- , apply = apply_axis["initial-child"] }
+
+local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } }
+
+local skip = { }
+
+local function errorrunner_e(str,cnv)
+ if not skip[str] then
+ report_lpath("error in expression: %s => %s",str,cnv)
+ skip[str] = cnv or str
+ end
+ return false
+end
+
+local function errorrunner_f(str,arg)
+ report_lpath("error in finalizer: %s(%s)",str,arg or "")
+ return false
+end
+
+local function register_nodes(nodetest,nodes)
+ return { kind = "nodes", nodetest = nodetest, nodes = nodes }
+end
+
+local function register_expression(expression)
+ local converted = lpegmatch(converter,expression)
+ local runner = load(format(template_e,converted))
+ runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
+end
+
+local function register_finalizer(protocol,name,arguments)
+ local runner
+ if arguments and arguments ~= "" then
+ runner = load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+ runner = load(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
+end
+
+local expression = P { "ex",
+ ex = "[" * C((V("sq") + V("dq") + (1 - S("[]")) + V("ex"))^0) * "]",
+ sq = "'" * (1 - S("'"))^0 * "'",
+ dq = '"' * (1 - S('"'))^0 * '"',
+}
+
+local arguments = P { "ar",
+ ar = "(" * Cs((V("sq") + V("dq") + V("nq") + P(1-P(")")))^0) * ")",
+ nq = ((1 - S("),'\""))^1) / function(s) return format("%q",s) end,
+ sq = P("'") * (1 - P("'"))^0 * P("'"),
+ dq = P('"') * (1 - P('"'))^0 * P('"'),
+}
+
+-- todo: better arg parser
+
+local function register_error(str)
+ return { kind = "error", error = format("unparsed: %s",str) }
+end
+
+-- there is a difference in * and /*/ and so we need to catch a few special cases
+
+local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes) -- last one not needed
+local special_2 = P("/") * Cc(register_auto_self)
+local special_3 = P("") * Cc(register_auto_self)
+
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
+
+ patterns = spaces * V("protocol") * spaces * (
+ ( V("special") * spaces * P(-1) ) +
+ ( V("initial") * spaces * V("step") * spaces * (P("/") * spaces * V("step") * spaces)^0 )
+ ),
+
+ protocol = Cg(V("letters"),"protocol") * P("://") + Cg(Cc(nil),"protocol"),
+
+ -- the / is needed for // as descendant or self is somewhat special
+ --
+ -- step = (V("shortcuts") + V("axis") * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
+ step = ((V("shortcuts") + P("/") + V("axis")) * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
+
+ axis = V("last_match")
+ + V("descendant")
+ + V("child")
+ + V("parent")
+ + V("self")
+ + V("root")
+ + V("ancestor")
+ + V("descendant_or_self")
+ + V("following_sibling")
+ + V("following")
+ + V("reverse_sibling")
+ + V("preceding_sibling")
+ + V("preceding")
+ + V("ancestor_or_self")
+ + #(1-P(-1)) * Cc(register_auto_child),
+
+ special = special_1
+ + special_2
+ + special_3,
+
+ initial = (P("/") * spaces * Cc(register_initial_child))^-1,
+
+ error = (P(1)^1) / register_error,
+
+ shortcuts_a = V("s_descendant_or_self")
+ + V("s_descendant")
+ + V("s_child")
+ + V("s_parent")
+ + V("s_self")
+ + V("s_root")
+ + V("s_ancestor"),
+
+ shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
+
+ s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
+ s_descendant = P("**") * Cc(register_descendant),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
+ s_parent = P("..") * Cc(register_parent ),
+ s_self = P("." ) * Cc(register_self ),
+ s_root = P("^^") * Cc(register_root ),
+ s_ancestor = P("^") * Cc(register_ancestor ),
+
+ -- we can speed this up when needed but we cache anyway so ...
+
+ descendant = P("descendant::") * Cc(register_descendant ),
+ child = P("child::") * Cc(register_child ),
+ parent = P("parent::") * Cc(register_parent ),
+ self = P("self::") * Cc(register_self ),
+ root = P('root::') * Cc(register_root ),
+ ancestor = P('ancestor::') * Cc(register_ancestor ),
+ descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
+ ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
+ -- attribute = P('attribute::') * Cc(register_attribute ),
+ -- namespace = P('namespace::') * Cc(register_namespace ),
+ following = P('following::') * Cc(register_following ),
+ following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
+ preceding = P('preceding::') * Cc(register_preceding ),
+ preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
+ reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
+ last_match = P('last-match::') * Cc(register_last_match ),
+
+ nodes = (V("nodefunction") * spaces * P("(") * V("nodeset") * P(")") + V("nodetest") * V("nodeset")) / register_nodes,
+
+ expressions = expression / register_expression,
+
+ letters = R("az")^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
+ negate = P("!") * Cc(false),
+
+ nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
+ nodetest = V("negate") + Cc(true),
+ nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
+ nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
+
+ finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
+
+}
+
+xmlpatterns.pathparser = pathparser
+
+local cache = { }
+
+local function nodesettostring(set,nodetest)
+ local t = { }
+ for i=1,#set,3 do
+ local directive, ns, tg = set[i], set[i+1], set[i+2]
+ if not ns or ns == "" then ns = "*" end
+ if not tg or tg == "" then tg = "*" end
+ tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest == false then
+ return format("not(%s)",concat(t,"|"))
+ else
+ return concat(t,"|")
+ end
+end
+
+local function tagstostring(list)
+ if #list == 0 then
+ return "no elements"
+ else
+ local t = { }
+ for i=1, #list do
+ local li = list[i]
+ local ns, tg = li.ns, 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)
+ end
+ return concat(t," ")
+ end
+end
+
+xml.nodesettostring = nodesettostring
+
+local lpath -- we have a harmless kind of circular reference
+
+local function lshow(parsed)
+ if type(parsed) == "string" then
+ parsed = lpath(parsed)
+ end
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
+ table.serialize(parsed,false))
+end
+
+xml.lshow = lshow
+
+local function add_comment(p,str)
+ local pc = p.comment
+ if not pc then
+ p.comment = { str }
+ else
+ pc[#pc+1] = str
+ end
+end
+
+lpath = function (pattern) -- the gain of caching is rather minimal
+ lpathcalls = lpathcalls + 1
+ if type(pattern) == "table" then
+ return pattern
+ else
+ local parsed = cache[pattern]
+ if parsed then
+ lpathcached = lpathcached + 1
+ else
+ parsed = lpegmatch(pathparser,pattern)
+ if parsed then
+ parsed.pattern = pattern
+ local np = #parsed
+ if np == 0 then
+ parsed = { pattern = pattern, register_self, state = "parsing error" }
+ report_lpath("parsing error in pattern: %s",pattern)
+ lshow(parsed)
+ else
+ -- we could have done this with a more complex parser but this
+ -- is cleaner
+ local pi = parsed[1]
+ if pi.axis == "auto-child" then
+ if false then
+ add_comment(parsed, "auto-child replaced by auto-descendant-or-self")
+ parsed[1] = register_auto_descendant_or_self
+ else
+ add_comment(parsed, "auto-child replaced by auto-descendant")
+ parsed[1] = register_auto_descendant
+ end
+ elseif pi.axis == "initial-child" and np > 1 and parsed[2].axis then
+ add_comment(parsed, "initial-child removed") -- we could also make it a auto-self
+ remove(parsed,1)
+ end
+ local np = #parsed -- can have changed
+ if np > 1 then
+ local pnp = parsed[np]
+ if pnp.kind == "nodes" and pnp.nodetest == true then
+ local nodes = pnp.nodes
+ if nodes[1] == true and nodes[2] == false and nodes[3] == false then
+ add_comment(parsed, "redundant final wildcard filter removed")
+ remove(parsed,np)
+ end
+ end
+ end
+ end
+ else
+ parsed = { pattern = pattern }
+ end
+ cache[pattern] = parsed
+ if trace_lparse and not trace_lprofile then
+ lshow(parsed)
+ end
+ end
+ return parsed
+ end
+end
+
+xml.lpath = lpath
+
+-- we can move all calls inline and then merge the trace back
+-- technically we can combine axis and the next nodes which is
+-- what we did before but this a bit cleaner (but slower too)
+-- but interesting is that it's not that much faster when we
+-- go inline
+--
+-- beware: we need to return a collection even when we filter
+-- else the (simple) cache gets messed up
+
+-- caching found lookups saves not that much (max .1 sec on a 8 sec run)
+-- and it also messes up finalizers
+
+-- watch out: when there is a finalizer, it's always called as there
+-- can be cases that a finalizer returns (or does) something in case
+-- there is no match; an example of this is count()
+
+do
+
+ local profiled = { }
+ xml.profiled = profiled
+ local lastmatch = nil -- we remember the last one .. drawback: no collection till new collect
+ local keepmatch = nil -- we remember the last one .. drawback: no collection till new collect
+
+ if directives then
+ directives.register("xml.path.keeplastmatch",function(v)
+ keepmatch = v
+ lastmatch = nil
+ end)
+ end
+
+ apply_axis["last-match"] = function()
+ return lastmatch or { }
+ end
+
+ local function profiled_apply(list,parsed,nofparsed,order)
+ local p = profiled[parsed.pattern]
+ if p then
+ p.tested = p.tested + 1
+ else
+ p = { tested = 1, matched = 0, finalized = 0 }
+ profiled[parsed.pattern] = p
+ end
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ collected = apply_axis[pi.axis](collected)
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ elseif kind == "finalizer" then
+ collected = pi.finalizer(collected) -- no check on # here
+ p.matched = p.matched + 1
+ p.finalized = p.finalized + 1
+ return collected
+ end
+ if not collected or #collected == 0 then
+ local pn = i < nofparsed and parsed[nofparsed]
+ if pn and pn.kind == "finalizer" then
+ collected = pn.finalizer(collected) -- collected can be nil
+ p.finalized = p.finalized + 1
+ return collected
+ end
+ return nil
+ end
+ end
+ if collected then
+ p.matched = p.matched + 1
+ end
+ return collected
+ end
+
+ local function traced_apply(list,parsed,nofparsed,order)
+ if trace_lparse then
+ lshow(parsed)
+ end
+ report_lpath("collecting: %s",parsed.pattern)
+ report_lpath("root tags : %s",tagstostring(list))
+ report_lpath("order : %s",order or "unset")
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ collected = apply_axis[pi.axis](collected)
+ report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
+ elseif kind == "finalizer" then
+ collected = pi.finalizer(collected)
+ report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+ return collected
+ end
+ if not collected or #collected == 0 then
+ local pn = i < nofparsed and parsed[nofparsed]
+ if pn and pn.kind == "finalizer" then
+ collected = pn.finalizer(collected)
+ report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
+ return collected
+ end
+ return nil
+ end
+ end
+ return collected
+ end
+
+ local function normal_apply(list,parsed,nofparsed,order)
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ local axis = pi.axis
+ if axis ~= "self" then
+ collected = apply_axis[axis](collected)
+ end
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ elseif kind == "finalizer" then
+ return pi.finalizer(collected)
+ end
+ if not collected or #collected == 0 then
+ local pf = i < nofparsed and parsed[nofparsed].finalizer
+ if pf then
+ return pf(collected) -- can be anything
+ end
+ return nil
+ end
+ end
+ return collected
+ end
+
+ local apply = normal_apply
+
+ if trackers then
+ -- local function check()
+ -- if trace_lprofile or then
+ -- apply = profiled_apply
+ -- elseif trace_lpath then
+ -- apply = traced_apply
+ -- else
+ -- apply = normal_apply
+ -- end
+ -- end
+ -- trackers.register("xml.path", check) -- can be "xml.path,xml.parse,xml.profile
+ -- trackers.register("xml.parse", check)
+ -- trackers.register("xml.profile",check)
+
+ trackers.register("xml.path,xml.parse,xml.profile",function()
+ if trace_lprofile then
+ apply = profiled_apply
+ elseif trace_lpath then
+ apply = traced_apply
+ else
+ apply = normal_apply
+ end
+ end)
+ end
+
+
+ function xml.applylpath(list,pattern)
+ if not list then
+ lastmatch = nil
+ return
+ end
+ local parsed = cache[pattern]
+ if parsed then
+ lpathcalls = lpathcalls + 1
+ lpathcached = lpathcached + 1
+ elseif type(pattern) == "table" then
+ lpathcalls = lpathcalls + 1
+ parsed = pattern
+ else
+ parsed = lpath(pattern) or pattern
+ end
+ if not parsed then
+ lastmatch = nil
+ return
+ end
+ local nofparsed = #parsed
+ if nofparsed == 0 then
+ lastmatch = nil
+ return -- something is wrong
+ end
+ local collected = apply({ list },parsed,nofparsed,list.mi)
+ lastmatch = keepmatch and collected or nil
+ return collected
+ end
+
+ function xml.lastmatch()
+ return lastmatch
+ end
+
+end
+
+local applylpath = xml.applylpath
+--[[ldx--
+<p>This is the main filter function. It returns whatever is asked for.</p>
+--ldx]]--
+
+function xml.filter(root,pattern) -- no longer funny attribute handling here
+ return applylpath(root,pattern)
+end
+
+-- internal (parsed)
+
+expressions.child = function(e,pattern)
+ return applylpath(e,pattern) -- todo: cache
+end
+
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
+ local collected = applylpath(e,pattern) -- todo: cache
+ return pattern and (collected and #collected) or 0
+end
+
+-- external
+
+-- expressions.oneof = function(s,...)
+-- local t = {...}
+-- for i=1,#t do
+-- if s == t[i] then
+-- return true
+-- end
+-- end
+-- return false
+-- end
+
+expressions.oneof = function(s,...)
+ for i=1,select("#",...) do
+ if s == select(i,...) then
+ return true
+ end
+ end
+ return false
+end
+
+expressions.error = function(str)
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
+ return false
+end
+
+expressions.undefined = function(s)
+ return s == nil
+end
+
+expressions.quit = function(s)
+ if s or s == nil then
+ quit_expression = true
+ end
+ return true
+end
+
+expressions.print = function(...)
+ print(...)
+ return true
+end
+
+expressions.find = find
+expressions.upper = upper
+expressions.lower = lower
+expressions.number = tonumber
+expressions.boolean = toboolean
+
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function xml.expressions.idstring(str)
+ return type(str) == "string" and gsub(str,"^#","") or ""
+end
+
+-- user interface
+
+local function traverse(root,pattern,handle)
+ -- report_lpath("use 'xml.selection' instead for pattern: %s",pattern)
+ local collected = applylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local r = e.__p__
+ handle(r,r.dt,e.ni)
+ end
+ end
+end
+
+local function selection(root,pattern,handle)
+ local collected = applylpath(root,pattern)
+ if collected then
+ if handle then
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ else
+ return collected
+ end
+ end
+end
+
+xml.traverse = traverse -- old method, r, d, k
+xml.selection = selection -- new method, simple handle
+
+--~ function xml.cachedpatterns()
+--~ return cache
+--~ end
+
+-- generic function finalizer (independant namespace)
+
+local function dofunction(collected,fnc,...)
+ if collected then
+ local f = functions[fnc]
+ if f then
+ for c=1,#collected do
+ f(collected[c],...)
+ end
+ else
+ report_lpath("unknown function %a",fnc)
+ end
+ end
+end
+
+finalizers.xml["function"] = dofunction
+finalizers.tex["function"] = dofunction
+
+-- functions
+
+expressions.text = function(e,n)
+ local rdt = e.__p__.dt
+ return rdt and rdt[n] or ""
+end
+
+expressions.name = function(e,n) -- ns + tg
+ local found = false
+ n = tonumber(n) or 0
+ if n == 0 then
+ found = type(e) == "table" and e
+ elseif n < 0 then
+ local d, k = e.__p__.dt, e.ni
+ for i=k-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == -1 then
+ found = di
+ break
+ else
+ n = n + 1
+ end
+ end
+ end
+ else
+ local d, k = e.__p__.dt, e.ni
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == 1 then
+ found = di
+ break
+ else
+ n = n - 1
+ end
+ end
+ end
+ end
+ if found then
+ local ns, tg = found.rn or found.ns or "", found.tg
+ if ns ~= "" then
+ return ns .. ":" .. tg
+ else
+ return tg
+ end
+ else
+ return ""
+ end
+end
+
+expressions.tag = function(e,n) -- only tg
+ if not e then
+ return ""
+ else
+ local found = false
+ n = tonumber(n) or 0
+ 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
+ for i=k-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == -1 then
+ found = di
+ break
+ else
+ n = n + 1
+ end
+ end
+ end
+ else
+ local d, k = e.__p__.dt, e.ni
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == 1 then
+ found = di
+ break
+ else
+ n = n - 1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
+end
+
+--[[ldx--
+<p>Often using an iterators looks nicer in the code than passing handler
+functions. The <l n='lua'/> book describes how to use coroutines for that
+purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
+code like:</p>
+
+<typing>
+for r, d, k in xml.elements(xml.load('text.xml'),"title") do
+ print(d[k]) -- old method
+end
+for e in xml.collected(xml.load('text.xml'),"title") do
+ print(e) -- new one
+end
+</typing>
+--ldx]]--
+
+-- local wrap, yield = coroutine.wrap, coroutine.yield
+-- local dummy = function() end
+--
+-- function xml.elements(root,pattern,reverse) -- r, d, k
+-- local collected = applylpath(root,pattern)
+-- if collected then
+-- if reverse then
+-- return wrap(function() for c=#collected,1,-1 do
+-- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
+-- end end)
+-- else
+-- return wrap(function() for c=1,#collected do
+-- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
+-- end end)
+-- end
+-- end
+-- return wrap(dummy)
+-- end
+--
+-- function xml.collected(root,pattern,reverse) -- e
+-- local collected = applylpath(root,pattern)
+-- if collected then
+-- if reverse then
+-- return wrap(function() for c=#collected,1,-1 do yield(collected[c]) end end)
+-- else
+-- return wrap(function() for c=1,#collected do yield(collected[c]) end end)
+-- end
+-- end
+-- return wrap(dummy)
+-- end
+
+-- faster:
+
+local dummy = function() end
+
+function xml.elements(root,pattern,reverse) -- r, d, k
+ local collected = applylpath(root,pattern)
+ if not collected then
+ return dummy
+ end
+ local n = #collected
+ if n == 0 then
+ return dummy
+ end
+ if reverse then
+ local c = n + 1
+ return function()
+ if c > 1 then
+ c = c - 1
+ local e = collected[c]
+ local r = e.__p__
+ return r, r.dt, e.ni
+ end
+ end
+ else
+ local c = 0
+ return function()
+ if c < n then
+ c = c + 1
+ local e = collected[c]
+ local r = e.__p__
+ return r, r.dt, e.ni
+ end
+ end
+ end
+end
+
+function xml.collected(root,pattern,reverse) -- e
+ local collected = applylpath(root,pattern)
+ if not collected then
+ return dummy
+ end
+ local n = #collected
+ if n == 0 then
+ return dummy
+ end
+ if reverse then
+ local c = n + 1
+ return function()
+ if c > 1 then
+ c = c - 1
+ return collected[c]
+ end
+ end
+ else
+ local c = 0
+ return function()
+ if c < n then
+ c = c + 1
+ return collected[c]
+ end
+ end
+ end
+end
+
+-- handy
+
+function xml.inspect(collection,pattern)
+ pattern = pattern or "."
+ for e in xml.collected(collection,pattern or ".") do
+ report_lpath("pattern: %s\n\n%s\n",pattern,xml.tostring(e))
+ end
+end
+
+-- texy (see xfdf):
+
+local function split(e) -- todo: use helpers / lpeg
+ local dt = e.dt
+ if dt then
+ for i=1,#dt do
+ local dti = dt[i]
+ if type(dti) == "string" then
+ dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+ dti = gsub(dti,"[\n\r]+","\n\n")
+ dt[i] = dti
+ else
+ split(dti)
+ end
+ end
+ end
+ return e
+end
+
+function xml.finalizers.paragraphs(c)
+ for i=1,#c do
+ split(c[i])
+ end
+ return c
+end
+
+-- local lpegmatch = lpeg.match
+-- 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
+-- if class then
+-- return lpegmatch(p,class)
+-- else
+-- return { }
+-- end
+-- end
+
+-- local gmatch = string.gmatch
+
+-- function xml.functions.hasclass(e,c,class)
+-- class = class and e.at[class] or e.at.class
+-- if class and class ~= "" then
+-- if class == c then
+-- return true
+-- else
+-- for s in gmatch(class,"%S+") do
+-- if s == c then
+-- return true
+-- end
+-- end
+-- end
+-- end
+-- return false
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-mis.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-mis.lua
new file mode 100644
index 00000000000..94a26b97414
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-mis.lua
@@ -0,0 +1,103 @@
+if not modules then modules = { } end modules ['lxml-mis'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local xml, lpeg, string = xml, lpeg, string
+
+local concat = table.concat
+local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local format, gsub, match = string.format, string.gsub, string.match
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
+
+lpegpatterns.xml = lpegpatterns.xml or { }
+local xmlpatterns = lpegpatterns.xml
+
+--[[ldx--
+<p>The following helper functions best belong to the <t>lxml-ini</t>
+module. Some are here because we need then in the <t>mk</t>
+document and other manuals, others came up when playing with
+this module. Since this module is also used in <l n='mtxrun'/> we've
+put them here instead of loading mode modules there then needed.</p>
+--ldx]]--
+
+local function xmlgsub(t,old,new) -- will be replaced
+ local dt = t.dt
+ if dt then
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "string" then
+ dt[k] = gsub(v,old,new)
+ else
+ xmlgsub(v,old,new)
+ end
+ end
+ end
+end
+
+--~ xml.gsub = xmlgsub
+
+function xml.stripleadingspaces(dk,d,k) -- cosmetic, for manual
+ if d and k then
+ local dkm = d[k-1]
+ if dkm and type(dkm) == "string" then
+ local s = match(dkm,"\n(%s+)")
+ xmlgsub(dk,"\n"..rep(" ",#s),"\n")
+ end
+ end
+end
+
+--~ xml.escapes = { ['&'] = '&amp;', ['<'] = '&lt;', ['>'] = '&gt;', ['"'] = '&quot;' }
+--~ xml.unescapes = { } for k,v in next, xml.escapes do xml.unescapes[v] = k end
+
+--~ function xml.escaped (str) return (gsub(str,"(.)" , xml.escapes )) end
+--~ function xml.unescaped(str) return (gsub(str,"(&.-;)", xml.unescapes)) end
+--~ function xml.cleansed (str) return (gsub(str,"<.->" , '' )) end -- "%b<>"
+
+-- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
+--
+-- 1021:0335:0287:0247
+
+-- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
+--
+-- 1559:0257:0288:0190 (last one suggested by roberto)
+
+-- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
+-- escaped = Cs((S("<")/"&lt;" + S(">")/"&gt;" + S("&")/"&amp;" + 1)^0)
+local normal = (1 - S("<&>"))^0
+local special = P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;"
+local escaped = Cs(normal * (special * normal)^0)
+
+-- 100 * 1000 * "oeps&lt; oeps&gt; oeps&amp;" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
+
+local normal = (1 - S"&")^0
+local special = P("&lt;")/"<" + P("&gt;")/">" + P("&amp;")/"&"
+local unescaped = Cs(normal * (special * normal)^0)
+
+-- 100 * 5000 * "oeps <oeps bla='oeps' foo='bar'> oeps </oeps> oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
+
+local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
+
+xmlpatterns.escaped = escaped
+xmlpatterns.unescaped = unescaped
+xmlpatterns.cleansed = cleansed
+
+function xml.escaped (str) return lpegmatch(escaped,str) end
+function xml.unescaped(str) return lpegmatch(unescaped,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str) end
+
+-- this might move
+
+function xml.fillin(root,pattern,str,check)
+ local e = xml.first(root,pattern)
+ if e then
+ local n = #e.dt
+ if not check or n == 0 or (n == 1 and e.dt[1] == "") then
+ e.dt = { str }
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.lua
new file mode 100644
index 00000000000..aba1c3b8d3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.lua
@@ -0,0 +1,162 @@
+if not modules then modules = { } end modules ['lxml-sor'] = {
+ version = 1.001,
+ comment = "companion to lxml-sor.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat, rep = string.format, table.concat, string.rep
+local lpegmatch = lpeg.match
+
+local xml = xml
+local lxml = lxml
+local context = context
+
+local lxmlsorters = lxml.sorters or { }
+lxml.sorters = lxmlsorters
+
+if not lxml.splitid then
+ local splitter = lpeg.C((1-lpeg.P(":"))^1) * lpeg.P("::") * lpeg.C(lpeg.P(1)^1)
+ function lxml.splitid(id)
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ return d, i
+ else
+ return "", id
+ end
+ end
+end
+
+local lists = { }
+
+function lxmlsorters.reset(name)
+ lists[name] = {
+ sorted = false,
+ entries = { },
+ reverse = { },
+ results = { },
+ }
+end
+
+function lxmlsorters.add(name,n,key)
+ local list = lists[name]
+ if list.sorted then
+ -- reverse is messed up, we could regenerate it and go on
+ else
+ local entries = list and list.entries
+ if entries then
+ local reverse = list.reverse
+ local e = reverse[n]
+ if e then
+ local keys = entries[e][2]
+ keys[#keys+1] = key
+ else
+ entries[#entries+1] = { n, { key } }
+ reverse[n] = #entries
+ end
+ end
+ end
+end
+
+function lxmlsorters.show(name)
+ local list = lists[name]
+ local entries = list and list.entries
+ local NC, NR, bold = context.NC, context.NR, context.bold -- somehow bold is not working
+ if entries then
+ local maxn = 1
+ for i=1,#entries do
+ if #entries[i][2] > maxn then maxn = #entries[i][2] end
+ end
+ context.starttabulate { "|Tr|Tr|" .. rep("Tlp|",maxn) }
+ NC() bold("n")
+ NC() bold("id")
+ if maxn > 1 then
+ for i=1,maxn do
+ NC() bold("entry " .. i)
+ end
+ else
+ NC() bold("entry")
+ end
+ NC() NR()
+ context.HL()
+ for i=1,#entries do
+ local entry = entries[i]
+ local document, node = lxml.splitid(entry[1])
+ NC() context(i)
+ NC() context(node)
+ local e = entry[2]
+ for i=1,#e do
+ NC() context.detokenize(e[i])
+ end
+ NC() NR()
+ end
+ context.stoptabulate()
+ end
+end
+
+lxmlsorters.compare = sorters.comparers.basic -- (a,b)
+
+function lxmlsorters.sort(name)
+ local list = lists[name]
+ local entries = list and list.entries
+ if entries then
+ -- filtering
+ local results = { }
+ list.results = results
+ for i=1,#entries do
+ local entry = entries[i]
+ results[i] = {
+ entry = entry[1],
+ key = concat(entry[2], " "),
+ }
+ end
+ -- preparation
+ local strip = sorters.strip
+ local splitter = sorters.splitters.utf
+ local firstofsplit = sorters.firstofsplit
+ for i=1, #results do
+ local r = results[i]
+ r.split = splitter(strip(r.key))
+ end
+ -- sorting
+ sorters.sort(results,lxmlsorters.compare)
+ -- finalizing
+ list.nofsorted = #results
+ local split = { }
+ for k=1,#results do -- rather generic so maybe we need a function
+ local v = results[k]
+ local entry, tag = firstofsplit(v)
+ local s = split[entry] -- keeps track of change
+ if not s then
+ s = { tag = tag, data = { } }
+ split[entry] = s
+ end
+ s.data[#s.data+1] = v
+ end
+ list.results = split
+ -- done
+ list.sorted = true
+ end
+end
+
+function lxmlsorters.flush(name,setup)
+ local list = lists[name]
+ local results = list and list.results
+ local xmlw = context.xmlw
+ if results and next(results) then
+ for key, result in next, results do
+ local tag, data = result.tag, result.data
+ for d=1,#data do
+ xmlw(setup,data[d].entry)
+ end
+ end
+ else
+ local entries = list and list.entries
+ if entries then
+ for i=1,#entries do
+ xmlw(setup,entries[i][1])
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.mkiv
new file mode 100644
index 00000000000..0d8eb6ba174
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-sor.mkiv
@@ -0,0 +1,97 @@
+%D \module
+%D [ file=lxml-sor,
+%D version=2009.08.24,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Sorting,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D THIS IS VERY EXPERIMENTAL!
+
+\writestatus{loading}{ConTeXt XML Support / Sorting}
+
+\registerctxluafile{lxml-sor}{1.001}
+
+\unprotect
+
+% the flusher is unexpandable so that it can be used in tables (noalign
+% interferences)
+
+\unexpanded\def\xmlresetsorter #1{\ctxlxml{sorters.reset("#1")}}
+\unexpanded\def\xmladdsortentry#1#2#3{\ctxlxml{sorters.add("#1","#2",\!!bs#3\!!es)}}
+\unexpanded\def\xmlshowsorter #1{\ctxlxml{sorters.show("#1")}}
+ \def\xmlflushsorter #1#2{\ctxlxml{sorters.flush("#1","#2")}}
+\unexpanded\def\xmlsortentries #1{\ctxlxml{sorters.sort("#1")}}
+
+\protect \endinput
+
+\startbuffer[test]
+<demo>
+ <entry>
+ <category>one</category>
+ <key>alpha</key>
+ <content>alpha indeed</content>
+ </entry>
+ <entry>
+ <category>one</category>
+ <key>gamma</key>
+ <content>gamma indeed</content>
+ </entry>
+ <entry>
+ <category>one</category>
+ <key>beta</key>
+ <content>beta indeed</content>
+ </entry>
+ <entry>
+ <category>two</category>
+ <key>alpha</key>
+ <content>alpha again</content>
+ </entry>
+ <entry>
+ <category>two</category>
+ <key>gamma</key>
+ <content>gamma again</content>
+ </entry>
+ <entry>
+ <category>two</category>
+ <key>beta</key>
+ <content>beta again</content>
+ </entry>
+</demo>
+\stopbuffer
+
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{\xmldocument}{demo|entry|content}{xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:mysetups}
+
+\startxmlsetups xml:demo
+ \xmlresetsorter{demo}
+ \xmlfilter{#1}{entry/command(xml:entry:getkeys)}
+ \blank sortkeys: \blank\xmlshowsorter{demo}\blank
+ \xmlsortentries{demo}
+ \xmlflushsorter{demo}{xml:entry:flush}
+\stopxmlsetups
+
+\startxmlsetups xml:entry:getkeys
+ \xmladdsortentry{demo}{#1}{\xmltext{#1}{category}}
+ \xmladdsortentry{demo}{#1}{\xmltext{#1}{key|entry}}
+\stopxmlsetups
+
+\startxmlsetups xml:entry:flush
+ \xmltext{#1}{content}\par
+\stopxmlsetups
+
+\startxmlsetups xml:entry
+ \xmltext{#1}{content}\par
+\stopxmlsetups
+
+\starttext
+ \xmlprocessbuffer{main}{test}{}
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-tab.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-tab.lua
new file mode 100644
index 00000000000..60d6262c7dd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-tab.lua
@@ -0,0 +1,1790 @@
+if not modules then modules = { } end modules ['lxml-tab'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module needs a cleanup: check latest lpeg, passing args, (sub)grammar, etc etc
+-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
+-- trouble
+
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
+local trace_entities = false trackers .register("xml.entities", function(v) trace_entities = v end)
+
+local report_xml = logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end
+
+--[[ldx--
+<p>The parser used here is inspired by the variant discussed in the lua book, but
+handles comment and processing instructions, has a different structure, provides
+parent access; a first version used different trickery but was less optimized to we
+went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
+The find based parser can be found in l-xml-edu.lua along with other older code.</p>
+--ldx]]--
+
+if lpeg.setmaxstack then lpeg.setmaxstack(1000) end -- deeply nested xml files
+
+xml = xml or { }
+local xml = xml
+
+--~ local xml = xml
+
+local concat, remove, insert = table.concat, table.remove, table.insert
+local type, next, setmetatable, getmetatable, tonumber, rawset = type, next, setmetatable, getmetatable, tonumber, rawset
+local lower, find, match, gsub = string.lower, string.find, string.match, string.gsub
+local sort = table.sort
+local utfchar = utf.char
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
+local formatters = string.formatters
+
+--[[ldx--
+<p>First a hack to enable namespace resolving. A namespace is characterized by
+a <l n='url'/>. The following function associates a namespace prefix with a
+pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
+find based solution where we loop over an array of patterns. Less code and
+much cleaner.</p>
+--ldx]]--
+
+do -- begin of namespace closure (we ran out of locals)
+
+xml.xmlns = xml.xmlns or { }
+
+--[[ldx--
+<p>The next function associates a namespace prefix with an <l n='url'/>. This
+normally happens independent of parsing.</p>
+
+<typing>
+xml.registerns("mml","mathml")
+</typing>
+--ldx]]--
+
+local check = P(false)
+local parse = check
+
+function xml.registerns(namespace, pattern) -- pattern can be an lpeg
+ check = check + C(P(lower(pattern))) / namespace
+ parse = P { P(check) + 1 * V(1) }
+end
+
+--[[ldx--
+<p>The next function also registers a namespace, but this time we map a
+given namespace prefix onto a registered one, using the given
+<l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
+
+<typing>
+xml.checkns("m","http://www.w3.org/mathml")
+</typing>
+--ldx]]--
+
+function xml.checkns(namespace,url)
+ local ns = lpegmatch(parse,lower(url))
+ if ns and namespace ~= ns then
+ xml.xmlns[namespace] = ns
+ end
+end
+
+--[[ldx--
+<p>Next we provide a way to turn an <l n='url'/> into a registered
+namespace. This used for the <t>xmlns</t> attribute.</p>
+
+<typing>
+resolvedns = xml.resolvens("http://www.w3.org/mathml")
+</typing>
+
+This returns <t>mml</t>.
+--ldx]]--
+
+function xml.resolvens(url)
+ return lpegmatch(parse,lower(url)) or ""
+end
+
+--[[ldx--
+<p>A namespace in an element can be remapped onto the registered
+one efficiently by using the <t>xml.xmlns</t> table.</p>
+--ldx]]--
+
+end -- end of namespace closure
+
+--[[ldx--
+<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
+such. This version is about twice as fast which is mostly due to the fact that
+we don't have to prepare the stream for cdata, doctype etc etc. This variant is
+is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
+took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
+the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
+<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
+
+<p>Next comes the parser. The rather messy doctype definition comes in many
+disguises so it is no surprice that later on have to dedicate quite some
+<l n='lpeg'/> code to it.</p>
+
+<typing>
+<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
+<!DOCTYPE Something PUBLIC "... ..." "..." >
+<!DOCTYPE Something SYSTEM "... ..." [ ... ] >
+<!DOCTYPE Something SYSTEM "... ..." >
+<!DOCTYPE Something [ ... ] >
+<!DOCTYPE Something >
+</typing>
+
+<p>The code may look a bit complex but this is mostly due to the fact that we
+resolve namespaces and attach metatables. There is only one public function:</p>
+
+<typing>
+local x = xml.convert(somestring)
+</typing>
+
+<p>An optional second boolean argument tells this function not to create a root
+element.</p>
+
+<p>Valid entities are:</p>
+
+<typing>
+<!ENTITY xxxx SYSTEM "yyyy" NDATA zzzz>
+<!ENTITY xxxx PUBLIC "yyyy" >
+<!ENTITY xxxx "yyyy" >
+</typing>
+--ldx]]--
+
+-- not just one big nested table capture (lpeg overflow)
+
+local nsremap, resolvens = xml.xmlns, xml.resolvens
+
+local stack, level, top, at, xmlnms, errorstr
+local entities, parameters
+local strip, utfize, resolve, cleanup, resolve_predefined, unify_predefined
+local dcache, hcache, acache
+local mt, dt, nt
+
+local function preparexmlstate(settings)
+ if settings then
+ stack = { }
+ level = 0
+ top = { }
+ at = { }
+ mt = { }
+ dt = { }
+ nt = 0 -- some 5% faster than #dt on cont-en.xml
+ xmlns = { }
+ errorstr = nil
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities -- enable this in order to apply the dtd
+ resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ parameters = { }
+ reported_at_errors = { }
+ dcache = { }
+ hcache = { }
+ acache = { }
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ else
+ stack = nil
+ level = nil
+ top = nil
+ at = nil
+ mt = nil
+ dt = nil
+ nt = nil
+ xmlns = nil
+ errorstr = nil
+ strip = nil
+ utfize = nil
+ resolve = nil
+ resolve_predefined = nil
+ unify_predefined = nil
+ cleanup = nil
+ entities = nil
+ parameters = nil
+ reported_at_errors = nil
+ dcache = nil
+ hcache = nil
+ acache = nil
+ end
+end
+
+local function initialize_mt(root)
+ mt = { __index = root } -- will be redefined later
+end
+
+function xml.setproperty(root,k,v)
+ getmetatable(root).__index[k] = v
+end
+
+function xml.checkerror(top,toclose)
+ return "" -- can be set
+end
+
+local checkns = xml.checkns
+
+local function add_attribute(namespace,tag,value)
+ if cleanup and value ~= "" then
+ value = cleanup(value) -- new
+ end
+ if tag == "xmlns" then
+ xmlns[#xmlns+1] = resolvens(value)
+ at[tag] = value
+ elseif namespace == "" then
+ at[tag] = value
+ elseif namespace == "xmlns" then
+ checkns(tag,value)
+ at["xmlns:" .. tag] = value
+ else
+ -- for the moment this way:
+ at[namespace .. ":" .. tag] = value
+ end
+end
+
+local function add_empty(spacing, namespace, tag)
+ if spacing ~= "" then
+ nt = nt + 1
+ dt[nt] = spacing
+ end
+ local resolved = namespace == "" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top = stack[level]
+ dt = top.dt
+ nt = #dt + 1
+ local t = {
+ ns = namespace or "",
+ rn = resolved,
+ tg = tag,
+ at = at,
+ dt = { },
+ __p__ = top
+ }
+ dt[nt] = t
+ setmetatable(t, mt)
+ if at.xmlns then
+ remove(xmlns)
+ end
+ at = { }
+end
+
+local function add_begin(spacing, namespace, tag)
+ if spacing ~= "" then
+ nt = nt + 1
+ dt[nt] = spacing
+ end
+ local resolved = namespace == "" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top = {
+ ns = namespace or "",
+ rn = resolved,
+ tg = tag,
+ at = at,
+ dt = {},
+ __p__ = stack[level]
+ }
+ setmetatable(top, mt)
+ dt = top.dt
+ nt = #dt
+ level = level + 1
+ stack[level] = top
+ at = { }
+end
+
+local function add_end(spacing, namespace, tag)
+ if spacing ~= "" then
+ nt = nt + 1
+ dt[nt] = spacing
+ end
+ local toclose = stack[level]
+ level = level - 1
+ top = stack[level]
+ if level < 1 then
+ errorstr = formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
+ report_xml(errorstr)
+ elseif toclose.tg ~= tag then -- no namespace check
+ errorstr = formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
+ report_xml(errorstr)
+ end
+ dt = top.dt
+ nt = #dt + 1
+ dt[nt] = toclose
+ -- dt[0] = top -- nasty circular reference when serializing table
+ if toclose.at.xmlns then
+ remove(xmlns)
+ end
+end
+
+-- local spaceonly = lpegpatterns.whitespace^0 * P(-1)
+--
+-- will be an option: dataonly
+--
+-- if #text == 0 or lpegmatch(spaceonly,text) then
+-- return
+-- end
+
+local function add_text(text)
+ if text == "" then
+ return
+ end
+ if cleanup then
+ if nt > 0 then
+ local s = dt[nt]
+ if type(s) == "string" then
+ dt[nt] = s .. cleanup(text)
+ else
+ nt = nt + 1
+ dt[nt] = cleanup(text)
+ end
+ else
+ nt = 1
+ dt[1] = cleanup(text)
+ end
+ else
+ if nt > 0 then
+ local s = dt[nt]
+ if type(s) == "string" then
+ dt[nt] = s .. text
+ else
+ nt = nt + 1
+ dt[nt] = text
+ end
+ else
+ nt = 1
+ dt[1] = text
+ end
+ end
+end
+
+local function add_special(what, spacing, text)
+ if spacing ~= "" then
+ nt = nt + 1
+ dt[nt] = spacing
+ end
+ if strip and (what == "@cm@" or what == "@dt@") then
+ -- forget it
+ else
+ nt = nt + 1
+ dt[nt] = { special=true, ns="", tg=what, dt={ text } }
+ end
+end
+
+local function set_message(txt)
+ errorstr = "garbage at the end of the file: " .. gsub(txt,"([ \n\r\t]*)","")
+end
+
+local function attribute_value_error(str)
+ if not reported_at_errors[str] then
+ report_xml("invalid attribute value %a",str)
+ reported_at_errors[str] = true
+ at._error_ = str
+ end
+ return str
+end
+
+local function attribute_specification_error(str)
+ if not reported_at_errors[str] then
+ report_xml("invalid attribute specification %a",str)
+ reported_at_errors[str] = true
+ at._error_ = str
+ end
+ return str
+end
+
+-- these will be set later
+
+local grammar_parsed_text_one
+local grammar_parsed_text_two
+
+local handle_hex_entity
+local handle_dec_entity
+local handle_any_entity_dtd
+local handle_any_entity_text
+
+-- in order to overcome lua limitations we wrap entity stuff in a
+-- closure
+
+do
+
+ local badentity = "&" -- was "&error;"
+
+ xml.placeholders = {
+ unknown_dec_entity = function(str) return str == "" and badentity or formatters["&%s;"](str) end,
+ unknown_hex_entity = function(str) return formatters["&#x%s;"](str) end,
+ unknown_any_entity = function(str) return formatters["&#x%s;"](str) end,
+ }
+
+ local function fromhex(s)
+ local n = tonumber(s,16)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["h:%s"](s), true
+ end
+ end
+
+ local function fromdec(s)
+ local n = tonumber(s)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["d:%s"](s), true
+ end
+ end
+
+ local p_rest = (1-P(";"))^0
+ local p_many = P(1)^0
+ local p_char = lpegpatterns.utf8character
+
+ local parsedentity =
+ P("&#") * (P("x")*(p_rest/fromhex) + (p_rest/fromdec)) * P(";") * P(-1) +
+ P ("#") * (P("x")*(p_many/fromhex) + (p_many/fromdec))
+
+ xml.parsedentitylpeg = parsedentity
+
+ -- parsing in the xml file
+
+ local predefined_unified = {
+ [38] = "&amp;",
+ [42] = "&quot;",
+ [47] = "&apos;",
+ [74] = "&lt;",
+ [76] = "&gt;",
+ }
+
+ local predefined_simplified = {
+ [38] = "&", amp = "&",
+ [42] = '"', quot = '"',
+ [47] = "'", apos = "'",
+ [74] = "<", lt = "<",
+ [76] = ">", gt = ">",
+ }
+
+ local nofprivates = 0xF0000 -- shared but seldom used
+
+ local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+ }
+
+ local privates_p = { -- needed for roundtrip as well as serialize to tex
+ }
+
+ local privates_s = { -- for tex
+ [ [["]] ] = "&U+22;",
+ [ [[#]] ] = "&U+23;",
+ [ [[$]] ] = "&U+24;",
+ [ [[%]] ] = "&U+25;",
+ [ [[&]] ] = "&U+26;",
+ [ [[']] ] = "&U+27;",
+ [ [[<]] ] = "&U+3C;",
+ [ [[>]] ] = "&U+3E;",
+ [ [[\]] ] = "&U+5C;",
+ [ [[{]] ] = "&U+7B;",
+ [ [[|]] ] = "&U+7C;",
+ [ [[}]] ] = "&U+7D;",
+ [ [[~]] ] = "&U+7E;",
+ }
+
+ local privates_n = { -- keeps track of defined ones
+ }
+
+ local escaped = utf.remapper(privates_u,"dynamic")
+ local unprivatized = utf.remapper(privates_p,"dynamic")
+ local unspecialized = utf.remapper(privates_s,"dynamic")
+
+ xml.unprivatized = unprivatized
+ xml.unspecialized = unspecialized
+ xml.escaped = escaped
+
+ local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ privates_s[p] = s
+ end
+ return p
+ end
+
+ xml.privatetoken = unescaped
+ xml.privatecodes = privates_n
+ xml.specialcodes = privates_s
+
+ function xml.addspecialcode(key,value)
+ privates_s[key] = value or "&" .. s .. ";"
+ end
+
+ handle_hex_entity = function(str)
+ local h = hcache[str]
+ if not h then
+ local n = tonumber(str,16)
+ h = unify_predefined and predefined_unified[n]
+ if h then
+ if trace_entities then
+ report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
+ end
+ elseif utfize then
+ h = (n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring hex entity &#x%s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
+ end
+ else
+ if trace_entities then
+ report_xml("found entity &#x%s;",str)
+ end
+ h = "&#x" .. str .. ";"
+ end
+ hcache[str] = h
+ end
+ return h
+ end
+
+ handle_dec_entity = function(str)
+ local d = dcache[str]
+ if not d then
+ local n = tonumber(str)
+ d = unify_predefined and predefined_unified[n]
+ if d then
+ if trace_entities then
+ report_xml("utfize, converting dec entity &#%s; into %a",str,d)
+ end
+ elseif utfize then
+ d = (n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring dec entity &#%s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting dec entity &#%s; into %a",str,d)
+ end
+ else
+ if trace_entities then
+ report_xml("found entity &#%s;",str)
+ end
+ d = "&#" .. str .. ";"
+ end
+ dcache[str] = d
+ end
+ return d
+ end
+
+ handle_any_entity_dtd = function(str)
+ if resolve then
+ local a = resolve_predefined and predefined_simplified[str] -- true by default
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to predefined %a",str,a)
+ end
+ else
+ if type(resolve) == "function" then
+ a = resolve(str,entities) or entities[str]
+ else
+ a = entities[str]
+ end
+ if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; to function call",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ else
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
+ end
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to external %s",str,a)
+ end
+ else
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = badentity
+ else
+ a = "&" .. str .. ";"
+ end
+ end
+ end
+ end
+ return a
+ else
+ local a = acache[str]
+ if not a then
+ a = resolve_predefined and predefined_simplified[str]
+ if a then
+ -- one of the predefined
+ acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %a",str,a)
+ end
+ elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
+ a = badentity
+ acache[str] = a
+ else
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
+ acache[str] = a
+ end
+ end
+ return a
+ end
+ end
+
+ handle_any_entity_text = function(str)
+ if resolve then
+ local a = resolve_predefined and predefined_simplified[str]
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to predefined %a",str,a)
+ end
+ else
+ if type(resolve) == "function" then
+ a = resolve(str,entities) or entities[str]
+ else
+ a = entities[str]
+ end
+ if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; to function call",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(grammar_parsed_text_two,a) or a
+ if type(a) == "number" then
+ return ""
+ else
+ a = lpegmatch(parsedentity,a) or a -- for nested
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ end
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ else
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
+ end
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to external %s",str,a)
+ end
+ else
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = badentity
+ else
+ a = "&" .. str .. ";"
+ end
+ end
+ end
+ end
+ return a
+ else
+ local a = acache[str]
+ if not a then
+ a = resolve_predefined and predefined_simplified[str]
+ if a then
+ -- one of the predefined
+ acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %a",str,a)
+ end
+ elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
+ a = badentity
+ acache[str] = a
+ else
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
+ acache[str] = a
+ end
+ end
+ return a
+ end
+ end
+
+ -- for tex
+
+ local p_rest = (1-P(";"))^1
+
+ local spec = {
+ [0x23] = "\\Ux{23}", -- #
+ [0x24] = "\\Ux{24}", -- $
+ [0x25] = "\\Ux{25}", -- %
+ [0x5C] = "\\Ux{5C}", -- \
+ [0x7B] = "\\Ux{7B}", -- {
+ [0x7C] = "\\Ux{7C}", -- |
+ [0x7D] = "\\Ux{7D}", -- }
+ [0x7E] = "\\Ux{7E}", -- ~
+ }
+
+ local hash = table.setmetatableindex(spec,function(t,k)
+ local v = utfchar(k)
+ t[k] = v
+ return v
+ end)
+
+ local function fromuni(s)
+ local n = tonumber(s,16)
+ if n then
+ return hash[n]
+ else
+ return formatters["u:%s"](s), true
+ end
+ end
+
+ local function fromhex(s)
+ local n = tonumber(s,16)
+ if n then
+ return hash[n]
+ else
+ return formatters["h:%s"](s), true
+ end
+ end
+
+ local function fromdec(s)
+ local n = tonumber(s)
+ if n then
+ return hash[n]
+ else
+ return formatters["d:%s"](s), true
+ end
+ end
+
+ local reparsedentity =
+ P("U+") * (p_rest/fromuni)
+ + P("#") * (
+ P("x") * (p_rest/fromhex)
+ + p_rest/fromdec
+ )
+
+ local hash = table.setmetatableindex(function(t,k)
+ local v = utfchar(k)
+ t[k] = v
+ return v
+ end)
+
+ local function fromuni(s)
+ local n = tonumber(s,16)
+ if n then
+ return hash[n]
+ else
+ return formatters["u:%s"](s), true
+ end
+ end
+
+ local function fromhex(s)
+ local n = tonumber(s,16)
+ if n then
+ return hash[n]
+ else
+ return formatters["h:%s"](s), true
+ end
+ end
+
+ local function fromdec(s)
+ local n = tonumber(s)
+ if n then
+ return hash[n]
+ else
+ return formatters["d:%s"](s), true
+ end
+ end
+
+ local unescapedentity =
+ P("U+") * (p_rest/fromuni)
+ + P("#") * (
+ P("x") * (p_rest/fromhex)
+ + p_rest/fromdec
+ )
+
+ xml.reparsedentitylpeg = reparsedentity -- with \Ux{...} for special tex entities
+ xml.unescapedentitylpeg = unescapedentity -- normal characters
+
+end
+
+-- we use these later on
+
+local escaped = xml.escaped
+local unescaped = xml.unescaped
+local placeholders = xml.placeholders
+
+--
+
+local function handle_end_entity(str)
+ report_xml("error in entity, %a found without ending %a",str,";")
+ return str
+end
+
+local function handle_crap_error(chr)
+ report_xml("error in parsing, unexpected %a found ",chr)
+ add_text(chr)
+ return chr
+end
+
+local space = S(' \r\n\t')
+local open = P('<')
+local close = P('>')
+local squote = S("'")
+local dquote = S('"')
+local equal = P('=')
+local slash = P('/')
+local colon = P(':')
+local semicolon = P(';')
+local ampersand = P('&')
+local valid = R('az', 'AZ', '09') + S('_-.')
+local name_yes = C(valid^1) * colon * C(valid^1)
+local name_nop = C(P(true)) * C(valid^1)
+local name = name_yes + name_nop
+local utfbom = lpegpatterns.utfbom -- no capture
+local spacing = C(space^0)
+
+----- entitycontent = (1-open-semicolon)^0
+local anyentitycontent = (1-open-semicolon-space-close-ampersand)^0
+local hexentitycontent = R("AF","af","09")^1
+local decentitycontent = R("09")^1
+local parsedentity = P("#")/"" * (
+ P("x")/"" * (hexentitycontent/handle_hex_entity) +
+ (decentitycontent/handle_dec_entity)
+ ) + (anyentitycontent/handle_any_entity_dtd) -- can be Cc(true)
+local parsedentity_text= P("#")/"" * (
+ P("x")/"" * (hexentitycontent/handle_hex_entity) +
+ (decentitycontent/handle_dec_entity)
+ ) + (anyentitycontent/handle_any_entity_text) -- can be Cc(false)
+----- entity = ampersand/"" * parsedentity * ( (semicolon/"") + #(P(1)/handle_end_entity))
+local entity = (ampersand/"") * parsedentity * (semicolon/"")
+ + ampersand * (anyentitycontent / handle_end_entity)
+local entity_text = (ampersand/"") * parsedentity_text * (semicolon/"")
+ + ampersand * (anyentitycontent / handle_end_entity)
+
+local text_unparsed = C((1-open)^1)
+local text_parsed = (Cs((1-open-ampersand)^1)/add_text + Cs(entity_text)/add_text)^1
+
+local somespace = space^1
+local optionalspace = space^0
+
+----- value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote) -- ampersand and < also invalid in value
+local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dquote * Cs((entity + (1 - dquote))^0) * dquote) -- ampersand and < also invalid in value
+
+local endofattributes = slash * close + close -- recovery of flacky html
+local whatever = space * name * optionalspace * equal
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
+----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
+local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
+
+local attributevalue = value + wrongvalue
+
+local attribute = (somespace * name * optionalspace * equal * optionalspace * attributevalue) / add_attribute
+----- attributes = (attribute)^0
+
+local attributes = (attribute + somespace^-1 * (((1-endofattributes)^1)/attribute_specification_error))^0
+
+local parsedtext = text_parsed -- / add_text
+local unparsedtext = text_unparsed / add_text
+local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
+
+local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
+local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
+local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
+
+-- todo: combine the opens in:
+
+local begincomment = open * P("!--")
+local endcomment = P("--") * close
+local begininstruction = open * P("?")
+local endinstruction = P("?") * close
+local begincdata = open * P("![CDATA[")
+local endcdata = P("]]") * close
+
+local someinstruction = C((1 - endinstruction)^0)
+local somecomment = C((1 - endcomment )^0)
+local somecdata = C((1 - endcdata )^0)
+
+local function weirdentity(k,v)
+ if trace_entities then
+ report_xml("registering %s entity %a as %a","weird",k,v)
+ end
+ parameters[k] = v
+end
+local function normalentity(k,v)
+ if trace_entities then
+ report_xml("registering %s entity %a as %a","normal",k,v)
+ end
+ entities[k] = v
+end
+local function systementity(k,v,n)
+ if trace_entities then
+ report_xml("registering %s entity %a as %a","system",k,v)
+ end
+ entities[k] = v
+end
+local function publicentity(k,v,n)
+ if trace_entities then
+ report_xml("registering %s entity %a as %a","public",k,v)
+ end
+ entities[k] = v
+end
+
+-- todo: separate dtd parser
+
+local begindoctype = open * P("!DOCTYPE")
+local enddoctype = close
+local beginset = P("[")
+local endset = P("]")
+local wrdtypename = C((1-somespace-P(";"))^1)
+local doctypename = C((1-somespace-close)^0)
+local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
+local weirdentitytype = P("%") * (somespace * doctypename * somespace * value) / weirdentity
+local normalentitytype = (doctypename * somespace * value) / normalentity
+local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
+local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
+local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype + weirdentitytype) * optionalspace * close
+
+local function weirdresolve(s)
+ lpegmatch(entitydoctype,parameters[s])
+end
+
+local function normalresolve(s)
+ lpegmatch(entitydoctype,entities[s])
+end
+
+local entityresolve = P("%") * (wrdtypename/weirdresolve ) * P(";")
+ + P("&") * (wrdtypename/normalresolve) * P(";")
+
+entitydoctype = entitydoctype + entityresolve
+
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + entityresolve + basiccomment + space)^0 * optionalspace * endset
+local definitiondoctype= doctypename * somespace * doctypeset
+local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
+local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
+local simpledoctype = (1-close)^1 -- * balanced^0
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+
+local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
+local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
+local cdata = (spacing * begincdata * somecdata * endcdata ) / function(...) add_special("@cd@",...) end
+local doctype = (spacing * begindoctype * somedoctype * enddoctype ) / function(...) add_special("@dt@",...) end
+
+local crap_parsed = 1 - beginelement - endelement - emptyelement - begininstruction - begincomment - begincdata - ampersand
+local crap_unparsed = 1 - beginelement - endelement - emptyelement - begininstruction - begincomment - begincdata
+local parsedcrap = Cs((crap_parsed^1 + entity_text)^1) / handle_crap_error
+local parsedcrap = Cs((crap_parsed^1 + entity_text)^1) / handle_crap_error
+local unparsedcrap = Cs((crap_unparsed )^1) / handle_crap_error
+
+-- nicer but slower:
+--
+-- local instruction = (Cc("@pi@") * spacing * begininstruction * someinstruction * endinstruction) / add_special
+-- local comment = (Cc("@cm@") * spacing * begincomment * somecomment * endcomment ) / add_special
+-- local cdata = (Cc("@cd@") * spacing * begincdata * somecdata * endcdata ) / add_special
+-- local doctype = (Cc("@dt@") * spacing * begindoctype * somedoctype * enddoctype ) / add_special
+
+local trailer = space^0 * (text_unparsed/set_message)^0
+
+-- comment + emptyelement + text + cdata + instruction + V("parent"), -- 6.5 seconds on 40 MB database file
+-- text + comment + emptyelement + cdata + instruction + V("parent"), -- 5.8
+-- text + V("parent") + emptyelement + comment + cdata + instruction, -- 5.5
+
+-- local grammar_parsed_text = P { "preamble",
+-- preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * V("parent") * trailer,
+-- parent = beginelement * V("children")^0 * endelement,
+-- children = parsedtext + V("parent") + emptyelement + comment + cdata + instruction + parsedcrap,
+-- }
+
+grammar_parsed_text_one = P { "preamble",
+ preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0,
+}
+
+grammar_parsed_text_two = P { "followup",
+ followup = V("parent") * trailer,
+ parent = beginelement * V("children")^0 * endelement,
+ children = parsedtext + V("parent") + emptyelement + comment + cdata + instruction + parsedcrap,
+}
+
+local grammar_unparsed_text = P { "preamble",
+ preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * V("parent") * trailer,
+ parent = beginelement * V("children")^0 * endelement,
+ children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction + unparsedcrap,
+}
+
+-- maybe we will add settings to result as well
+
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ preparexmlstate(settings)
+ if settings.parent_root then
+ mt = getmetatable(settings.parent_root)
+ else
+ initialize_mt(top)
+ end
+ level = level + 1
+ stack[level] = top
+ top.dt = { }
+ dt = top.dt
+ nt = 0
+ if not data or data == "" then
+ errorstr = "empty xml file"
+ elseif utfize or resolve then
+ local m = lpegmatch(grammar_parsed_text_one,data)
+ if m then
+ m = lpegmatch(grammar_parsed_text_two,data,m)
+ end
+ -- local m = lpegmatch(grammar_parsed_text,data)
+ if m then
+ -- errorstr = "" can be set!
+ else
+ errorstr = "invalid xml file - parsed text"
+ end
+ elseif type(data) == "string" then
+ if lpegmatch(grammar_unparsed_text,data) then
+ errorstr = ""
+ else
+ errorstr = "invalid xml file - unparsed text"
+ end
+ else
+ errorstr = "invalid xml file - no text at all"
+ end
+ local result
+ if errorstr and errorstr ~= "" then
+ result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } }
+ setmetatable(result, mt)
+ setmetatable(result.dt[1], mt)
+ setmetatable(stack, mt)
+ local errorhandler = settings.error_handler
+ if errorhandler == false then
+ -- no error message
+ else
+ errorhandler = errorhandler or xml.errorhandler
+ if errorhandler then
+ local currentresource = settings.currentresource
+ if currentresource and currentresource ~= "" then
+ xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr))
+ else
+ xml.errorhandler(formatters["load error: %s"](errorstr))
+ end
+ end
+ end
+ else
+ result = stack[1]
+ end
+ if not settings.no_root then
+ result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={ }, entities = entities, settings = settings }
+ setmetatable(result, mt)
+ local rdt = result.dt
+ for k=1,#rdt do
+ local v = rdt[k]
+ if type(v) == "table" and not v.special then -- always table -)
+ result.ri = k -- rootindex
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ break
+ end
+ end
+ end
+ if errorstr and errorstr ~= "" then
+ result.error = true
+ else
+ errorstr = nil
+ end
+ result.statistics = {
+ errormessage = errorstr,
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ intermediates = parameters,
+ }
+ }
+ preparexmlstate() -- resets
+ return result
+end
+
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+local function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("",settings)
+ end
+end
+
+xml.convert = xmlconvert
+
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
+ local settings = xmldata.settings
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
+ -- settings.no_root = true
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
+ -- xc.settings = nil
+ -- xc.entities = nil
+ -- xc.special = nil
+ -- xc.ri = nil
+ -- print(xc.tg)
+ return xc
+end
+
+--[[ldx--
+<p>Packaging data in an xml like table is done with the following
+function. Maybe it will go away (when not used).</p>
+--ldx]]--
+
+function xml.is_valid(root)
+ return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
+end
+
+function xml.package(tag,attributes,data)
+ local ns, tg = match(tag,"^(.-):?([^:]+)$")
+ local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
+ setmetatable(t, mt)
+ return t
+end
+
+function xml.is_valid(root)
+ return root and not root.error
+end
+
+xml.errorhandler = report_xml
+
+--[[ldx--
+<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
+the whole file first. The function accepts a string representing
+a filename or a file handle.</p>
+--ldx]]--
+
+function xml.load(filename,settings)
+ local data = ""
+ if type(filename) == "string" then
+ -- local data = io.loaddata(filename) - -todo: check type in io.loaddata
+ local f = io.open(filename,'r') -- why not 'rb'
+ if f then
+ data = f:read("*all") -- io.readall(f) ... only makes sense for large files
+ f:close()
+ end
+ elseif filename then -- filehandle
+ data = filename:read("*all") -- io.readall(f) ... only makes sense for large files
+ end
+ if settings then
+ settings.currentresource = filename
+ local result = xmlconvert(data,settings)
+ settings.currentresource = nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource = filename })
+ end
+end
+
+--[[ldx--
+<p>When we inject new elements, we need to convert strings to
+valid trees, which is what the next function does.</p>
+--ldx]]--
+
+local no_root = { no_root = true }
+
+function xml.toxml(data)
+ if type(data) == "string" then
+ local root = { xmlconvert(data,no_root) }
+ return (#root > 1 and root) or root[1]
+ else
+ return data
+ end
+end
+
+--[[ldx--
+<p>For copying a tree we use a dedicated function instead of the
+generic table copier. Since we know what we're dealing with we
+can speed up things a bit. The second argument is not to be used!</p>
+--ldx]]--
+
+-- local function copy(old,tables)
+-- if old then
+-- if not tables then
+-- tables = { }
+-- end
+-- local new = { }
+-- if not tables[old] then
+-- tables[old] = new
+-- end
+-- for k,v in next, old do
+-- new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
+-- end
+-- local mt = getmetatable(old)
+-- if mt then
+-- setmetatable(new,mt)
+-- end
+-- return new
+-- else
+-- return { }
+-- end
+-- end
+
+local function copy(old)
+ if old then
+ local new = { }
+ for k,v in next, old do
+ if type(v) == "table" then
+ new[k] = table.copy(v)
+ else
+ new[k] = v
+ end
+ end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
+ end
+end
+
+xml.copy = copy
+
+--[[ldx--
+<p>In <l n='context'/> serializing the tree or parts of the tree is a major
+actitivity which is why the following function is pretty optimized resulting
+in a few more lines of code than needed. The variant that uses the formatting
+function for all components is about 15% slower than the concatinating
+alternative.</p>
+--ldx]]--
+
+-- todo: add <?xml version='1.0' standalone='yes'?> when not present
+
+function xml.checkbom(root) -- can be made faster
+ if root.ri then
+ local dt = root.dt
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
+ return
+ end
+ end
+ insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } )
+ insert(dt, 2, "\n" )
+ end
+end
+
+--[[ldx--
+<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
+and then handle the lot.</p>
+--ldx]]--
+
+-- new experimental reorganized serialize
+
+local f_attribute = formatters['%s=%q']
+
+-- we could reuse ats
+
+local function verbose_element(e,handlers,escape) -- options
+ local handle = handlers.handle
+ local serialize = handlers.serialize
+ local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { }
+ if ats then
+ -- we now sort attributes
+ local n = 0
+ for k in next, eat do
+ n = n + 1
+ ats[n] = k
+ end
+ if n == 1 then
+ local k = ats[1]
+ ats = f_attribute(k,escaped(eat[k]))
+ else
+ sort(ats)
+ for i=1,n do
+ local k = ats[i]
+ ats[i] = f_attribute(k,escaped(eat[k]))
+ end
+ ats = concat(ats," ")
+ end
+ end
+ if ern and trace_entities and ern ~= ens then
+ ens = ern
+ end
+ local n = edt and #edt
+ if ens ~= "" then
+ if n and n > 0 then
+ if ats then
+ handle("<",ens,":",etg," ",ats,">")
+ else
+ handle("<",ens,":",etg,">")
+ end
+ for i=1,n do
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("</",ens,":",etg,">")
+ else
+ if ats then
+ handle("<",ens,":",etg," ",ats,"/>")
+ else
+ handle("<",ens,":",etg,"/>")
+ end
+ end
+ else
+ if n and n > 0 then
+ if ats then
+ handle("<",etg," ",ats,">")
+ else
+ handle("<",etg,">")
+ end
+ for i=1,n do
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("</",etg,">")
+ else
+ if ats then
+ handle("<",etg," ",ats,"/>")
+ else
+ handle("<",etg,"/>")
+ end
+ end
+ end
+end
+
+local function verbose_pi(e,handlers)
+ handlers.handle("<?",e.dt[1],"?>")
+end
+
+local function verbose_comment(e,handlers)
+ handlers.handle("<!--",e.dt[1],"-->")
+end
+
+local function verbose_cdata(e,handlers)
+ handlers.handle("<![CDATA[", e.dt[1],"]]>")
+end
+
+local function verbose_doctype(e,handlers)
+ handlers.handle("<!DOCTYPE",e.dt[1],">") -- has space at end of string
+end
+
+local function verbose_root(e,handlers)
+ handlers.serialize(e.dt,handlers)
+end
+
+local function verbose_text(e,handlers)
+ handlers.handle(escaped(e))
+end
+
+local function verbose_document(e,handlers)
+ local serialize = handlers.serialize
+ local functions = handlers.functions
+ for i=1,#e do
+ local ei = e[i]
+ if type(ei) == "string" then
+ functions["@tx@"](ei,handlers)
+ else
+ serialize(ei,handlers)
+ end
+ end
+end
+
+local function serialize(e,handlers,...)
+ if e then
+ local initialize = handlers.initialize
+ local finalize = handlers.finalize
+ local functions = handlers.functions
+ if initialize then
+ local state = initialize(...)
+ if not state == true then
+ return state
+ end
+ end
+ local etg = e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ -- elseif type(e) == "string" then
+ -- functions["@tx@"](e,handlers)
+ else
+ functions["@dc@"](e,handlers) -- dc ?
+ end
+ if finalize then
+ return finalize()
+ end
+ end
+end
+
+local function xserialize(e,handlers)
+ if e then
+ local functions = handlers.functions
+ local etg = e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ -- elseif type(e) == "string" then
+ -- functions["@tx@"](e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+ end
+end
+
+local handlers = { }
+
+local function newhandlers(settings)
+ local t = table.copy(handlers[settings and settings.parent or "verbose"] or { }) -- merge
+ if settings then
+ for k,v in next, settings do
+ if type(v) == "table" then
+ local tk = t[k] if not tk then tk = { } t[k] = tk end
+ for kk,vv in next, v do
+ tk[kk] = vv
+ end
+ else
+ t[k] = v
+ end
+ end
+ if settings.name then
+ handlers[settings.name] = t
+ end
+ end
+ utilities.storage.mark(t)
+ return t
+end
+
+local nofunction = function() end
+
+function xml.sethandlersfunction(handler,name,fnc)
+ handler.functions[name] = fnc or nofunction
+end
+
+function xml.gethandlersfunction(handler,name)
+ return handler.functions[name]
+end
+
+function xml.gethandlers(name)
+ return handlers[name]
+end
+
+newhandlers {
+ name = "verbose",
+ initialize = false, -- faster than nil and mt lookup
+ finalize = false, -- faster than nil and mt lookup
+ serialize = xserialize,
+ handle = print,
+ functions = {
+ ["@dc@"] = verbose_document,
+ ["@dt@"] = verbose_doctype,
+ ["@rt@"] = verbose_root,
+ ["@el@"] = verbose_element,
+ ["@pi@"] = verbose_pi,
+ ["@cm@"] = verbose_comment,
+ ["@cd@"] = verbose_cdata,
+ ["@tx@"] = verbose_text,
+ }
+}
+
+--[[ldx--
+<p>How you deal with saving data depends on your preferences. For a 40 MB database
+file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
+
+<lines>
+1.3 : load data from file to string
+6.1 : convert string into tree
+5.3 : saving in file using xmlsave
+6.8 : converting to string using xml.tostring
+3.6 : saving converted string in file
+</lines>
+
+<p>Beware, these were timing with the old routine but measurements will not be that
+much different I guess.</p>
+--ldx]]--
+
+-- maybe this will move to lxml-xml
+
+local result
+
+local xmlfilehandler = newhandlers {
+ name = "file",
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
+}
+
+-- no checking on writeability here but not faster either
+--
+-- local xmlfilehandler = newhandlers {
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
+-- handle = io.write,
+-- }
+
+function xml.save(root,name)
+ serialize(root,xmlfilehandler,name)
+end
+
+local result
+
+local xmlstringhandler = newhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+}
+
+local function xmltostring(root) -- 25% overhead due to collecting
+ if not root then
+ return ""
+ elseif type(root) == "string" then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
+ end
+end
+
+local function __tostring(root) -- inline
+ return (root and xmltostring(root)) or ""
+end
+
+initialize_mt = function(root) -- redefinition
+ mt = { __tostring = __tostring, __index = root }
+end
+
+xml.defaulthandlers = handlers
+xml.newhandlers = newhandlers
+xml.serialize = serialize
+xml.tostring = xmltostring
+
+--[[ldx--
+<p>The next function operated on the content only and needs a handle function
+that accepts a string.</p>
+--ldx]]--
+
+local function xmlstring(e,handle)
+ if not handle or (e.special and e.tg ~= "@rt@") then
+ -- nothing
+ elseif e.tg then
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ xmlstring(edt[i],handle)
+ end
+ end
+ else
+ handle(e)
+ end
+end
+
+xml.string = xmlstring
+
+--[[ldx--
+<p>A few helpers:</p>
+--ldx]]--
+
+--~ xmlsetproperty(root,"settings",settings)
+
+function xml.settings(e)
+ while e do
+ local s = e.settings
+ if s then
+ return s
+ else
+ e = e.__p__
+ end
+ end
+ return nil
+end
+
+function xml.root(e)
+ local r = e
+ while e do
+ e = e.__p__
+ if e then
+ r = e
+ end
+ end
+ return r
+end
+
+function xml.parent(root)
+ return root.__p__
+end
+
+function xml.body(root)
+ return root.ri and root.dt[root.ri] or root -- not ok yet
+end
+
+function xml.name(root)
+ if not root then
+ return ""
+ end
+ local ns = root.ns
+ local tg = root.tg
+ if ns == "" then
+ return tg
+ else
+ return ns .. ":" .. tg
+ end
+end
+
+--[[ldx--
+<p>The next helper erases an element but keeps the table as it is,
+and since empty strings are not serialized (effectively) it does
+not harm. Copying the table would take more time. Usage:</p>
+--ldx]]--
+
+function xml.erase(dt,k)
+ if dt then
+ if k then
+ dt[k] = ""
+ else for k=1,#dt do
+ dt[1] = { "" }
+ end end
+ end
+end
+
+--[[ldx--
+<p>The next helper assigns a tree (or string). Usage:</p>
+
+<typing>
+dt[k] = xml.assign(root) or xml.assign(dt,k,root)
+</typing>
+--ldx]]--
+
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k] = type(root) == "table" and xml.body(root) or root
+ return dt[k]
+ else
+ return xml.body(root)
+ end
+end
+
+-- the following helpers may move
+
+--[[ldx--
+<p>The next helper assigns a tree (or string). Usage:</p>
+<typing>
+xml.tocdata(e)
+xml.tocdata(e,"error")
+</typing>
+--ldx]]--
+
+function xml.tocdata(e,wrapper) -- a few more in the aux module
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
+ if wrapper then
+ whatever = formatters["<%s>%s</%s>"](wrapper,whatever,wrapper)
+ end
+ local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e }
+ setmetatable(t,getmetatable(e))
+ e.dt = { t }
+end
+
+function xml.makestandalone(root)
+ if root.ri then
+ local dt = root.dt
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "table" and v.special and v.tg == "@pi@" then
+ local txt = v.dt[1]
+ if find(txt,"xml.*version=") then
+ v.dt[1] = txt .. " standalone='yes'"
+ break
+ end
+ end
+ end
+ end
+ return root
+end
+
+function xml.kind(e)
+ local dt = e and e.dt
+ if dt then
+ local n = #dt
+ if n == 1 then
+ local d = dt[1]
+ if d.special then
+ local tg = d.tg
+ if tg == "@cd@" then
+ return "cdata"
+ elseif tg == "@cm" then
+ return "comment"
+ elseif tg == "@pi@" then
+ return "instruction"
+ elseif tg == "@dt@" then
+ return "declaration"
+ end
+ elseif type(d) == "string" then
+ return "text"
+ end
+ return "element"
+ elseif n > 0 then
+ return "mixed"
+ end
+ end
+ return "empty"
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua
new file mode 100644
index 00000000000..3a49ea3d2e9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua
@@ -0,0 +1,2368 @@
+if not modules then modules = { } end modules ['lxml-tex'] = {
+ version = 1.001,
+ comment = "companion to lxml-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Because we split and resolve entities we use the direct printing
+-- interface and not the context one. If we ever do that there will
+-- be an cldf-xml helper library.
+
+local utfchar = utf.char
+local concat, insert, remove, sortedkeys, reversed = table.concat, table.insert, table.remove, table.sortedkeys, table.reverse
+local format, sub, gsub, find, gmatch, match = string.format, string.sub, string.gsub, string.find, string.gmatch, string.match
+local type, next, tonumber, tostring, select = type, next, tonumber, tostring, select
+local lpegmatch = lpeg.match
+local P, S, C, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs
+local patterns = lpeg.patterns
+local setmetatableindex = table.setmetatableindex
+
+local tex, xml = tex, xml
+local lowerchars, upperchars, lettered = characters.lower, characters.upper, characters.lettered
+local basename, dirname, joinfile = file.basename, file.dirname, file.join
+
+lxml = lxml or { }
+local lxml = lxml
+
+local catcodenumbers = catcodes.numbers
+local ctxcatcodes = catcodenumbers.ctxcatcodes -- todo: use different method
+local notcatcodes = catcodenumbers.notcatcodes -- todo: use different method
+
+local commands = commands
+local context = context
+local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing)
+
+local implement = interfaces.implement
+
+local xmlelements = xml.elements
+local xmlcollected = xml.collected
+local xmlsetproperty = xml.setproperty
+local xmlwithelements = xml.withelements
+local xmlserialize = xml.serialize
+local xmlcollect = xml.collect
+local xmltext = xml.text
+local xmltostring = xml.tostring
+local xmlapplylpath = xml.applylpath
+local xmlunspecialized = xml.unspecialized
+local xmlprivatetoken = xml.privatetoken
+local xmlstripelement = xml.stripelement
+local xmlinclusion = xml.inclusion
+local xmlinclusions = xml.inclusions
+local xmlbadinclusions = xml.badinclusions
+local xmlcontent = xml.content
+local xmllastmatch = xml.lastmatch
+
+directives.enable("xml.path.keeplastmatch")
+
+local variables = interfaces and interfaces.variables or { }
+
+local settings_to_hash = utilities.parsers.settings_to_hash
+local settings_to_set = utilities.parsers.settings_to_set
+local options_to_hash = utilities.parsers.options_to_hash
+local options_to_array = utilities.parsers.options_to_array
+
+local insertbeforevalue = utilities.tables.insertbeforevalue
+local insertaftervalue = utilities.tables.insertaftervalue
+
+local resolveprefix = resolvers.resolve
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local trace_setups = false trackers.register("lxml.setups", function(v) trace_setups = v end)
+local trace_loading = false trackers.register("lxml.loading", function(v) trace_loading = v end)
+local trace_access = false trackers.register("lxml.access", function(v) trace_access = v end)
+local trace_comments = false trackers.register("lxml.comments", function(v) trace_comments = v end)
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
+local trace_selectors = false trackers.register("lxml.selectors",function(v) trace_selectors = v end)
+
+local report_lxml = logs.reporter("lxml","tex")
+local report_xml = logs.reporter("xml","tex")
+
+local forceraw = false
+
+local p_texescape = patterns.texescape
+
+-- tex entities
+
+lxml.entities = lxml.entities or { }
+
+storage.register("lxml/entities",lxml.entities,"lxml.entities")
+
+local xmlentities = xml.entities -- these are more or less standard entities
+local texentities = lxml.entities -- these are specific for a tex run
+local reparsedentity = xml.reparsedentitylpeg -- \Ux{...}
+local unescapedentity = xml.unescapedentitylpeg
+local parsedentity = reparsedentity
+local useelement = false -- probably no longer needed / used
+
+function lxml.startunescaped()
+ parsedentity = unescapedentity
+end
+
+function lxml.stopunescaped()
+ parsedentity = reparsedentity
+end
+
+directives.register("lxml.entities.useelement",function(v)
+ useelement = v
+end)
+
+function lxml.registerentity(key,value)
+ texentities[key] = value
+ if trace_entities then
+ report_xml("registering tex entity %a as %a",key,value)
+ end
+end
+
+function lxml.resolvedentity(str)
+ if forceraw then
+ -- should not happen as we then can as well bypass this function
+ if trace_entities then
+ report_xml("passing entity %a as &%s;",str,str)
+ end
+ context("&%s;",str)
+ else
+ local e = texentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ if trace_entities then
+ report_xml("passing entity %a using function",str)
+ end
+ e(str)
+ elseif e then
+ if trace_entities then
+ report_xml("passing entity %a as %a using %a",str,e,"ctxcatcodes")
+ end
+ context(e)
+ end
+ return
+ end
+ local e = xmlentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ e = e(str)
+ end
+ if e then
+ if trace_entities then
+ report_xml("passing entity %a as %a using %a",str,e,"notcatcodes")
+ end
+ contextsprint(notcatcodes,e)
+ return
+ end
+ end
+ -- resolve hex and dec, todo: escape # & etc for ctxcatcodes
+ -- normally this is already solved while loading the file
+ local chr, err = lpegmatch(parsedentity,str)
+ if chr then
+ if parsedentity == reparsedentity then
+ if trace_entities then
+ report_xml("passing entity %a as %a using %a",str,chr,"ctxcatcodes")
+ end
+ context(chr)
+ else
+ contextsprint(notcatcodes,chr)
+ if trace_entities then
+ report_xml("passing entity %a as %a using %a",str,chr,"notcatcodes")
+ end
+ end
+ elseif err then
+ if trace_entities then
+ report_xml("passing faulty entity %a as %a",str,err)
+ end
+ context(err)
+ elseif useelement then
+ local tag = upperchars(str)
+ if trace_entities then
+ report_xml("passing entity %a to \\xmle using tag %a",str,tag)
+ end
+ contextsprint(texcatcodes,"\\xmle{")
+ contextsprint(notcatcodes,e)
+ contextsprint(texcatcodes,"}")
+ else
+ if trace_entities then
+ report_xml("passing entity %a as %a using %a",str,str,"notcatcodes")
+ end
+ contextsprint(notcatcodes,str)
+ end
+ end
+end
+
+-- tex interface
+
+lxml.loaded = lxml.loaded or { }
+local loaded = lxml.loaded
+
+-- print(contextdirective("context-mathml-directive function reduction yes "))
+-- print(contextdirective("context-mathml-directive function "))
+
+xml.defaultprotocol = "tex"
+
+local finalizers = xml.finalizers
+
+finalizers.xml = finalizers.xml or { }
+finalizers.tex = finalizers.tex or { }
+
+local xmlfinalizers = finalizers.xml
+local texfinalizers = finalizers.tex
+
+-- serialization with entity handling
+
+local ampersand = P("&")
+local semicolon = P(";")
+
+local entity = (ampersand * C((1-semicolon)^1) * semicolon) / lxml.resolvedentity -- context.bold
+
+local _, xmltextcapture_yes = context.newtexthandler {
+ catcodes = notcatcodes,
+ exception = entity,
+}
+local _, xmltextcapture_nop = context.newtexthandler {
+ catcodes = notcatcodes,
+}
+
+local _, xmlspacecapture_yes = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ catcodes = notcatcodes,
+ exception = entity,
+}
+local _, xmlspacecapture_nop = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ catcodes = notcatcodes,
+}
+
+local _, xmllinecapture_yes = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ catcodes = notcatcodes,
+ exception = entity,
+}
+local _, xmllinecapture_nop = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ catcodes = notcatcodes,
+}
+
+local _, ctxtextcapture_yes = context.newtexthandler {
+ catcodes = ctxcatcodes,
+ exception = entity,
+}
+local _, ctxtextcapture_nop = context.newtexthandler {
+ catcodes = ctxcatcodes,
+}
+
+local xmltextcapture = xmltextcapture_yes
+local xmlspacecapture = xmlspacecapture_yes
+local xmllinecapture = xmllinecapture_yes
+local ctxtextcapture = ctxtextcapture_yes
+
+directives.register("lxml.entities.escaped",function(v)
+ if v then
+ xmltextcapture = xmltextcapture_yes
+ xmlspacecapture = xmlspacecapture_yes
+ xmllinecapture = xmllinecapture_yes
+ ctxtextcapture = ctxtextcapture_yes
+ else
+ xmltextcapture = xmltextcapture_nop
+ xmlspacecapture = xmlspacecapture_nop
+ xmllinecapture = xmllinecapture_nop
+ ctxtextcapture = ctxtextcapture_nop
+ end
+end)
+
+-- cdata
+
+local toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+}
+
+lxml.toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+ strip = true,
+}
+
+-- raw flushing
+
+function lxml.startraw()
+ forceraw = true
+end
+
+function lxml.stopraw()
+ forceraw = false
+end
+
+function lxml.startraw()
+ forceraw = true
+end
+
+function lxml.stopraw()
+ forceraw = false
+end
+
+function lxml.rawroot()
+ return rawroot
+end
+
+-- storage
+
+function lxml.store(id,root,filename)
+ loaded[id] = root
+ xmlsetproperty(root,"name",id)
+ if filename then
+ xmlsetproperty(root,"filename",filename)
+ end
+end
+
+local splitter = lpeg.splitat("::")
+
+lxml.idsplitter = splitter
+
+function lxml.splitid(id)
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ return d, i
+ else
+ return "", id
+ end
+end
+
+local function getid(id, qualified)
+ if id then
+ local lid = loaded[id]
+ if lid then
+ return lid
+ elseif type(id) == "table" then
+ return id
+ else
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ local ld = loaded[d]
+ if ld then
+ local ldi = ld.index
+ if ldi then
+ local root = ldi[tonumber(i)]
+ if root then
+ if qualified then -- we need this else two args that confuse others
+ return root, d
+ else
+ return root
+ end
+ elseif trace_access then
+ report_lxml("%a has no index entry %a",d,i)
+ end
+ elseif trace_access then
+ report_lxml("%a has no index",d)
+ end
+ elseif trace_access then
+ report_lxml("%a is not loaded",d)
+ end
+ elseif trace_access then
+ report_lxml("%a is not loaded",i)
+ end
+ end
+ elseif trace_access then
+ report_lxml("invalid id (nil)")
+ end
+end
+
+lxml.id = getid -- we provide two names as locals can already use such
+lxml.getid = getid -- names and we don't want clashes
+
+function lxml.root(id)
+ return loaded[id]
+end
+
+-- index
+
+local nofindices = 0
+
+local function addindex(name,check_sum,force)
+ local root = getid(name)
+ if root and (not root.index or force) then -- weird, only called once
+ local n, index, maxindex, check = 0, root.index or { }, root.maxindex or 0, root.check or { }
+ local function nest(root)
+ local dt = root.dt
+ if not root.ix then
+ maxindex = maxindex + 1
+ root.ix = maxindex
+ check[maxindex] = root.tg -- still needed ?
+ index[maxindex] = root
+ n = n + 1
+ end
+ if dt then
+ for k=1,#dt do
+ local dk = dt[k]
+ if type(dk) == "table" then
+ nest(dk)
+ end
+ end
+ end
+ end
+ nest(root)
+ nofindices = nofindices + n
+ --
+ if type(name) ~= "string" then
+ name = "unknown"
+ end
+ root.index = index
+ root.maxindex = maxindex
+ if trace_access then
+ report_lxml("indexed entries %a, found nodes %a",tostring(name),maxindex)
+ end
+ end
+end
+
+lxml.addindex = addindex
+
+implement {
+ name = "xmladdindex",
+ arguments = { "string" },
+ actions = addindex,
+}
+
+-- another cache
+
+local function lxmlapplylpath(id,pattern) -- better inline, saves call
+ return xmlapplylpath(getid(id),pattern)
+end
+
+lxml.filter = lxmlapplylpath
+
+function lxml.filterlist(list,pattern)
+ for s in gmatch(list,"[^, ]+") do -- we could cache a table
+ xmlapplylpath(getid(s),pattern)
+ end
+end
+
+function lxml.applyfunction(id,name)
+ local f = xml.functions[name]
+ return f and f(getid(id))
+end
+
+-- rather new, indexed storage (backward refs), maybe i will merge this
+
+function lxml.checkindex(name)
+ local root = getid(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,"}")
+ end
+end
+
+function lxml.getindex(name,n) -- will change as name is always there now
+ local i, p = lpegmatch(splitter,n)
+ if p then
+ contextsprint(ctxcatcodes,n)
+ else
+ contextsprint(ctxcatcodes,name,"::",n)
+ end
+end
+
+-- loading (to be redone, no overload) .. best use different methods and
+-- keep raw xml (at least as option)
+
+xml.originalload = xml.originalload or xml.load
+
+local noffiles, nofconverted = 0, 0
+
+function xml.load(filename,settings)
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ starttiming(xml)
+ local ok, data = resolvers.loadbinfile(filename)
+ settings = settings or { }
+ settings.currentresource = filename
+ local xmltable = xml.convert((ok and data) or "",settings)
+ settings.currentresource = nil
+ stoptiming(xml)
+ return xmltable
+end
+
+local function entityconverter(id,str,ent) -- todo: disable tex entities when raw
+ -- tex driven entity
+ local t = texentities[str]
+ if t then
+ local p = xmlprivatetoken(str)
+-- only once
+-- context.xmlprivate(p,t)
+ return p
+ end
+ -- dtd determined entity
+ local e = ent and ent[str]
+ if e then
+ return e
+ end
+ -- predefined entity (mathml and so)
+ local x = xmlentities[str]
+ if x then
+ return x
+ end
+ -- keep original somehow
+ return xmlprivatetoken(str)
+end
+
+local function lxmlconvert(id,data,compress,currentresource)
+ local settings = { -- we're now roundtrip anyway
+ unify_predefined_entities = false, -- is also default
+ utfize_entities = true, -- is also default
+ resolve_predefined_entities = true, -- is also default
+ resolve_entities = function(str,ent) return entityconverter(id,str,ent) end,
+ currentresource = tostring(currentresource or id),
+ }
+ if compress and compress == variables.yes then
+ settings.strip_cm_and_dt = true
+ end
+ return xml.convert(data,settings)
+end
+
+lxml.convert = lxmlconvert
+
+function lxml.load(id,filename,compress)
+ filename = ctxrunner.preparedfile(filename)
+ if trace_loading then
+ report_lxml("loading file %a as %a",filename,id)
+ end
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ starttiming(xml)
+ local ok, data = resolvers.loadbinfile(filename)
+ local xmltable = lxmlconvert(id,(ok and data) or "",compress,format("id: %s, file: %s",id,filename))
+ stoptiming(xml)
+ lxml.store(id,xmltable,filename)
+ return xmltable, filename
+end
+
+function lxml.register(id,xmltable,filename)
+ lxml.store(id,xmltable,filename)
+ return xmltable
+end
+
+-- recurse prepare rootpath resolve basename
+
+local options_true = { "recurse", "prepare", "rootpath" }
+local options_nil = { "prepare", "rootpath" }
+
+function lxml.include(id,pattern,attribute,options)
+ starttiming(xml)
+ local root = getid(id)
+ if options == true then
+ -- downward compatible
+ options = options_true
+ elseif not options then
+ -- downward compatible
+ options = options_nil
+ else
+ options = settings_to_hash(options) or { }
+ end
+ xml.include(root,pattern,attribute,options.recurse,function(filename)
+ if filename then
+ -- preprocessing
+ if options.prepare then
+ filename = commands.preparedfile(filename)
+ end
+ -- handy if we have a flattened structure
+ if options.basename then
+ filename = basename(filename)
+ end
+ if options.resolve then
+ filename = resolveprefix(filename) or filename
+ end
+ -- some protection
+ if options.rootpath then
+ if dirname(filename) == "" and root.filename then
+ local dn = dirname(root.filename)
+ if dn ~= "" then
+ filename = joinfile(dn,filename)
+ end
+ end
+ end
+ if trace_loading then
+ report_lxml("including file %a",filename)
+ end
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ return resolvers.loadtexfile(filename) or ""
+ else
+ return ""
+ end
+ end)
+ stoptiming(xml)
+end
+
+function lxml.inclusion(id,default)
+ local inclusion = xmlinclusion(getid(id),default)
+ if inclusion then
+ context(inclusion)
+ end
+end
+
+function lxml.inclusions(id,sorted)
+ local inclusions = xmlinclusions(getid(id),sorted)
+ if inclusions then
+ context(concat(inclusions,","))
+ end
+end
+
+function lxml.badinclusions(id,sorted)
+ local badinclusions = xmlbadinclusions(getid(id),sorted)
+ if badinclusions then
+ context(concat(badinclusions,","))
+ end
+end
+
+function lxml.save(id,name)
+ xml.save(getid(id),name)
+end
+
+function xml.getbuffer(name,compress) -- we need to make sure that commands are processed
+ if not name or name == "" then
+ name = tex.jobname
+ end
+ nofconverted = nofconverted + 1
+ local data = buffers.getcontent(name)
+ xmltostring(lxmlconvert(name,data,compress,format("buffer: %s",tostring(name or "?")))) -- one buffer
+end
+
+function lxml.loadbuffer(id,name,compress)
+ starttiming(xml)
+ nofconverted = nofconverted + 1
+ local data = buffers.collectcontent(name or id) -- name can be list
+ local xmltable = lxmlconvert(id,data,compress,format("buffer: %s",tostring(name or id or "?")))
+ lxml.store(id,xmltable)
+ stoptiming(xml)
+ return xmltable, name or id
+end
+
+function lxml.loaddata(id,str,compress)
+ starttiming(xml)
+ nofconverted = nofconverted + 1
+ local xmltable = lxmlconvert(id,str or "",compress,format("id: %s",id))
+ lxml.store(id,xmltable)
+ stoptiming(xml)
+ return xmltable, id
+end
+
+-- e.command:
+--
+-- string : setup
+-- true : text (no <self></self>)
+-- false : ignore
+-- function : call
+
+local function tex_doctype(e,handlers)
+ -- ignore
+end
+
+local function tex_comment(e,handlers)
+ if trace_comments then
+ report_lxml("comment %a",e.dt[1])
+ end
+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 function tex_element(e,handlers)
+ 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
+ end
+end
+
+-- <?context-directive foo ... ?>
+-- <?context-foo-directive ... ?>
+
+local pihandlers = { } xml.pihandlers = pihandlers
+
+local space = S(" \n\r")
+local spaces = space^0
+local class = C((1-space)^0)
+local key = class
+local rest = C(P(1)^0)
+local value = C(P(1-(space * -1))^0)
+local category = P("context-") * (
+ C((1-P("-"))^1) * P("-directive")
+ + P("directive") * spaces * key
+ )
+
+local c_parser = category * spaces * value -- rest
+local k_parser = class * spaces * key * spaces * rest --value
+
+implement {
+ name = "xmlinstalldirective",
+ arguments = { "string", "string" },
+ actions = function(name,csname)
+ if csname then
+ local keyvalueparser = k_parser / context[csname]
+ local keyvaluechecker = function(category,rest,e)
+ lpegmatch(keyvalueparser,rest)
+ end
+ pihandlers[name] = keyvaluechecker
+ end
+ end
+}
+
+local function tex_pi(e,handlers)
+ local str = e.dt[1]
+ if str and str ~= "" then
+ local category, rest = lpegmatch(c_parser,str)
+ if category and rest and #rest > 0 then
+ local handler = pihandlers[category]
+ if handler then
+ handler(category,rest,e)
+ end
+ end
+ end
+end
+
+local obeycdata = true
+
+function lxml.setcdata()
+ obeycdata = true
+end
+
+function lxml.resetcdata()
+ obeycdata = false
+end
+
+local function tex_cdata(e,handlers)
+ if obeycdata then
+ toverbatim(e.dt[1])
+ end
+end
+
+-- we could try to merge the conversion and flusher but we don't gain much and it makes tracing
+-- harder: xunspecialized = utf.remapper(xml.specialcodes,"dynamic",lxml.resolvedentity)
+
+local function tex_text(e)
+ e = xmlunspecialized(e)
+ lpegmatch(xmltextcapture,e)
+end
+
+--
+
+local function ctx_text(e) -- can be just context(e) as we split there
+ lpegmatch(ctxtextcapture,e)
+end
+
+local function tex_handle(...)
+ contextsprint(ctxcatcodes,...) -- notcatcodes is active anyway
+end
+
+local xmltexhandler = xml.newhandlers {
+ name = "tex",
+ handle = tex_handle,
+ functions = {
+ -- ["@dc@"] = tex_document,
+ ["@dt@"] = tex_doctype,
+ -- ["@rt@"] = tex_root,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_text,
+ }
+}
+
+lxml.xmltexhandler = xmltexhandler
+
+-- begin of test
+
+local function tex_space(e)
+ e = xmlunspecialized(e)
+ lpegmatch(xmlspacecapture,e)
+end
+
+local xmltexspacehandler = xml.newhandlers {
+ name = "texspace",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_space,
+ }
+}
+
+local function tex_line(e)
+ e = xmlunspecialized(e)
+ lpegmatch(xmllinecapture,e)
+end
+
+local xmltexlinehandler = xml.newhandlers {
+ name = "texline",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_line,
+ }
+}
+
+function lxml.flushspacewise(id) -- keeps spaces and lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexspacehandler)
+ end
+end
+
+function lxml.flushlinewise(id) -- keeps lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexlinehandler)
+ end
+end
+
+-- end of test
+
+function lxml.serialize(root)
+ xmlserialize(root,xmltexhandler)
+end
+
+function lxml.setaction(id,pattern,action)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ collected[c].command = action
+ end
+ end
+ end
+end
+
+local function sprint(root) -- check rawroot usage
+ if root then
+ local tr = type(root)
+ if tr == "string" then -- can also be result of lpath
+ -- rawroot = false -- ?
+ root = xmlunspecialized(root)
+ lpegmatch(xmltextcapture,root)
+ elseif tr == "table" then
+ if forceraw then
+ rawroot = root
+ -- contextsprint(ctxcatcodes,xmltostring(root)) -- goes wrong with % etc
+ root = xmlunspecialized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
+ else
+ xmlserialize(root,xmltexhandler)
+ end
+ end
+ end
+end
+
+local function tprint(root) -- we can move sprint inline
+ local tr = type(root)
+ if tr == "table" then
+ local n = #root
+ if n == 0 then
+ -- skip
+ else
+ for i=1,n do
+ sprint(root[i])
+ end
+ end
+ elseif tr == "string" then
+ root = xmlunspecialized(root)
+ lpegmatch(xmltextcapture,root)
+ end
+end
+
+local function cprint(root) -- content
+ if not root then
+ -- rawroot = false
+ -- quit
+ elseif type(root) == 'string' then
+ -- rawroot = false
+ root = xmlunspecialized(root)
+ lpegmatch(xmltextcapture,root)
+ else
+ local rootdt = root.dt
+ if forceraw then
+ rawroot = root
+ -- contextsprint(ctxcatcodes,xmltostring(rootdt or root))
+ root = xmlunspecialized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
+ else
+ xmlserialize(rootdt or root,xmltexhandler)
+ end
+ end
+end
+
+xml.sprint = sprint local xmlsprint = sprint -- calls ct mathml -> will be replaced
+xml.tprint = tprint local xmltprint = tprint -- only used here
+xml.cprint = cprint local xmlcprint = cprint -- calls ct mathml -> will be replaced
+
+-- now we can flush
+
+function lxml.main(id)
+ xmlserialize(getid(id),xmltexhandler) -- the real root (@rt@)
+end
+
+-- -- lines (untested)
+--
+-- local buffer = { }
+--
+-- local xmllinescapture = (
+-- newline^2 / function() buffer[#buffer+1] = "" end +
+-- newline / function() buffer[#buffer] = buffer[#buffer] .. " " end +
+-- content / function(s) buffer[#buffer] = buffer[#buffer] .. s end
+-- )^0
+--
+-- local xmllineshandler = table.copy(xmltexhandler)
+--
+-- xmllineshandler.handle = function(...) lpegmatch(xmllinescapture,concat{ ... }) end
+--
+-- function lines(root)
+-- if not root then
+-- -- rawroot = false
+-- -- quit
+-- elseif type(root) == 'string' then
+-- -- rawroot = false
+-- lpegmatch(xmllinescapture,root)
+-- elseif next(root) then -- tr == 'table'
+-- xmlserialize(root,xmllineshandler)
+-- end
+-- end
+--
+-- function xml.lines(root) -- used at all?
+-- buffer = { "" }
+-- lines(root)
+-- return result
+-- end
+
+local function to_text(e)
+ if e.command == nil then
+ local etg = e.tg
+ if etg and e.special and etg ~= "@rt@" then
+ e.command = false -- i.e. skip
+ else
+ e.command = true -- i.e. no <self></self>
+ end
+ end
+end
+
+local function to_none(e)
+ if e.command == nil then
+ e.command = false -- i.e. skip
+ end
+end
+
+-- setups
+
+local setups = { }
+
+function lxml.setcommandtotext(id)
+ xmlwithelements(getid(id),to_text)
+end
+
+function lxml.setcommandtonone(id)
+ xmlwithelements(getid(id),to_none)
+end
+
+function lxml.installsetup(what,document,setup,where)
+ document = document or "*"
+ local sd = setups[document]
+ if not sd then sd = { } setups[document] = sd end
+ for k=1,#sd do
+ if sd[k] == setup then sd[k] = nil break end
+ end
+ if what == 1 then
+ if trace_loading then
+ report_lxml("prepending setup %a for %a",setup,document)
+ end
+ insert(sd,1,setup)
+ elseif what == 2 then
+ if trace_loading then
+ report_lxml("appending setup %a for %a",setup,document)
+ end
+ insert(sd,setup)
+ elseif what == 3 then
+ if trace_loading then
+ report_lxml("inserting setup %a for %a before %a",setup,document,where)
+ end
+ insertbeforevalue(sd,setup,where)
+ elseif what == 4 then
+ if trace_loading then
+ report_lxml("inserting setup %a for %a after %a",setup,document,where)
+ end
+ insertaftervalue(sd,setup,where)
+ end
+end
+
+function lxml.flushsetups(id,...)
+ local done = { }
+ for i=1,select("#",...) do
+ local document = select(i,...)
+ local sd = setups[document]
+ if sd then
+ for k=1,#sd do
+ local v= sd[k]
+ if not done[v] then
+ if trace_loading then
+ report_lxml("applying setup %02i : %a to %a",k,v,document)
+ end
+ contextsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
+ done[v] = true
+ end
+ end
+ elseif trace_loading then
+ report_lxml("no setups for %a",document)
+ end
+ end
+end
+
+function lxml.resetsetups(document)
+ if trace_loading then
+ report_lxml("resetting all setups for %a",document)
+ end
+ setups[document] = { }
+end
+
+function lxml.removesetup(document,setup)
+ local s = setups[document]
+ if s then
+ for i=1,#s do
+ if s[i] == setup then
+ if trace_loading then
+ report_lxml("removing setup %a for %a",setup,document)
+ end
+ remove(t,i)
+ break
+ end
+ end
+ end
+end
+
+function lxml.setsetup(id,pattern,setup)
+ if not setup or setup == "" or setup == "*" or setup == "-" or setup == "+" then
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix or 0
+ if setup == "-" then
+ e.command = false
+ report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
+ elseif setup == "+" then
+ e.command = true
+ report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
+ else
+ local tg = e.tg
+ if tg then -- to be sure
+ e.command = tg
+ local ns = e.rn or e.ns
+ if ns == "" then
+ report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
+ else
+ report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ end
+ end
+ end
+ end
+ elseif setup == "-" then
+ for c=1,nc do
+ collected[c].command = false
+ end
+ elseif setup == "+" then
+ for c=1,nc do
+ collected[c].command = true
+ end
+ else
+ for c=1,nc do
+ local e = collected[c]
+ e.command = e.tg
+ end
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","zero",pattern)
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","no",pattern)
+ end
+ else
+ local a, b = match(setup,"^(.+:)([%*%-])$")
+ if a and b then
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if b == "-" then
+ e.command = false
+ if ns == "" then
+ report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ else
+ report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ end
+ elseif b == "+" then
+ e.command = true
+ if ns == "" then
+ report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
+ else
+ report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
+ end
+ else
+ e.command = a .. tg
+ if ns == "" then
+ report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ else
+ report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ end
+ end
+ end
+ elseif b == "-" then
+ for c=1,nc do
+ collected[c].command = false
+ end
+ elseif b == "+" then
+ for c=1,nc do
+ collected[c].command = true
+ end
+ else
+ for c=1,nc do
+ local e = collected[c]
+ e.command = a .. e.tg
+ end
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","zero",pattern)
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","no",pattern)
+ end
+ else
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ e.command = setup
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if ns == "" then
+ report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
+ else
+ report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ end
+ end
+ else
+ for c=1,nc do
+ collected[c].command = setup
+ end
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","zero",pattern)
+ end
+ elseif trace_setups then
+ report_lxml("%s lpath matches for pattern: %s","no",pattern)
+ end
+ end
+ end
+end
+
+-- finalizers
+
+local function first(collected)
+ if collected and #collected > 0 then
+ xmlsprint(collected[1])
+ end
+end
+
+local function last(collected)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ xmlsprint(collected[nc])
+ end
+ end
+end
+
+local function all(collected)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ xmlsprint(collected[c])
+ end
+ end
+ end
+end
+
+local function reverse(collected)
+ if collected then
+ local nc = #collected
+ if nc >0 then
+ for c=nc,1,-1 do
+ xmlsprint(collected[c])
+ end
+ end
+ end
+end
+
+local function count(collected)
+ contextsprint(ctxcatcodes,(collected and #collected) or 0) -- why ctxcatcodes
+end
+
+local function position(collected,n)
+ -- todo: if not n then == match
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ xmlsprint(cn)
+ return
+ end
+ end
+ end
+ end
+end
+
+local function match(collected) -- is match in preceding collected, never change, see bibxml
+ local m = collected and collected[1]
+ contextsprint(ctxcatcodes,m and m.mi or 0) -- why ctxcatcodes
+end
+
+local function index(collected,n)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1 -- brrr
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ contextsprint(ctxcatcodes,cn.ni or 0) -- why ctxcatcodes
+ return
+ end
+ end
+ end
+ end
+ contextsprint(ctxcatcodes,0) -- why ctxcatcodes
+end
+
+-- 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,"%*")
+ 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
+end
+
+-- local wildcards = setmetatableindex(function(t,k)
+-- local v = false
+-- if find(k,"%*") then
+-- v = setmetatableindex(function(t,kk)
+-- local v = gsub(k,"%*",kk)
+-- t[k] = v
+-- -- report_lxml("wildcard %a key %a value %a",kk,k,v)
+-- return v
+-- end)
+-- end
+-- t[k] = v
+-- return v
+-- end)
+--
+-- local function command(collected,cmd,otherwise)
+-- local n = collected and #collected
+-- if n and n > 0 then
+-- local wildcard = wildcards[cmd]
+-- 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{",wildcard[e.tg],"}{",name,"::",ix,"}")
+-- else
+-- contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}")
+-- end
+-- end
+-- elseif otherwise then
+-- contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
+-- end
+-- end
+
+local function attribute(collected,a,default)
+ if collected and #collected > 0 then
+ local at = collected[1].at
+ local str = (at and at[a]) or default
+ if str and str ~= "" then
+ contextsprint(notcatcodes,str)
+ end
+ elseif default then
+ contextsprint(notcatcodes,default)
+ end
+end
+
+local function chainattribute(collected,arguments) -- todo: optional levels
+ if collected and #collected > 0 then
+ local e = collected[1]
+ while e do
+ local at = e.at
+ if at then
+ local a = at[arguments]
+ if a then
+ contextsprint(notcatcodes,a)
+ end
+ else
+ break -- error
+ end
+ e = e.__p__
+ end
+ end
+end
+
+local function chainpath(collected,nonamespace)
+ if collected and #collected > 0 then
+ local e = collected[1]
+ local t = { }
+ while e do
+ local tg = e.tg
+ local rt = e.__p__
+ local ns = e.ns
+ if tg == "@rt@" then
+ break
+ elseif rt.tg == "@rt@" then
+ if nonamespace or not ns or ns == "" then
+ t[#t+1] = tg
+ else
+ t[#t+1] = ns .. ":" .. tg
+ end
+ else
+ if nonamespace or not ns or ns == "" then
+ t[#t+1] = tg .. "[" .. e.ei .. "]"
+ else
+ t[#t+1] = ns .. ":" .. tg .. "[" .. e.ei .. "]"
+ end
+ end
+ e = rt
+ end
+ contextsprint(notcatcodes,concat(reversed(t),"/"))
+ end
+end
+
+local function text(collected)
+ if collected then
+ local nc = #collected
+ if nc == 0 then
+ -- nothing
+ elseif nc == 1 then -- hardly any gain so this will go
+ cprint(collected[1])
+ else for c=1,nc do
+ cprint(collected[c])
+ end end
+ end
+end
+
+local function ctxtext(collected)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,collected[c].dt)
+ end
+ end
+ end
+end
+
+local function stripped(collected) -- tricky as we strip in place
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ cprint(xmlstripelement(collected[c]))
+ end
+ end
+ end
+end
+
+local function lower(collected)
+ if not collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lowerchars(collected[c].dt[1]))
+ end
+ end
+ end
+end
+
+local function upper(collected)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,upperchars(collected[c].dt[1]))
+ end
+ end
+ end
+end
+
+local function number(collected)
+ local nc = collected and #collected or 0
+ local n = 0
+ if nc > 0 then
+ for c=1,nc do
+ n = n + tonumber(collected[c].dt[1] or 0)
+ end
+ end
+ contextsprint(ctxcatcodes,n)
+end
+
+local function concatrange(collected,start,stop,separator,lastseparator,textonly) -- test this on mml
+ if collected then
+ local nofcollected = #collected
+ if nofcollected > 0 then
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
+ if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
+ for i=start,stop do
+ if textonly then
+ xmlcprint(collected[i])
+ else
+ xmlsprint(collected[i])
+ end
+ if i == nofcollected then
+ -- nothing
+ elseif i == nofcollected-1 and lastseparator ~= "" then
+ contextsprint(ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ contextsprint(ctxcatcodes,separator)
+ end
+ end
+ end
+ end
+end
+
+local function concat(collected,separator,lastseparator,textonly) -- test this on mml
+ concatrange(collected,false,false,separator,lastseparator,textonly)
+end
+
+texfinalizers.first = first
+texfinalizers.last = last
+texfinalizers.all = all
+texfinalizers.reverse = reverse
+texfinalizers.count = count
+texfinalizers.command = command
+texfinalizers.attribute = attribute
+texfinalizers.text = text
+texfinalizers.stripped = stripped
+texfinalizers.lower = lower
+texfinalizers.upper = upper
+texfinalizers.ctxtext = ctxtext
+texfinalizers.context = ctxtext
+texfinalizers.position = position
+texfinalizers.match = match
+texfinalizers.index = index
+texfinalizers.concat = concat
+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
+ if nc > 0 then
+ n = tonumber(n) or 0
+ local c
+ if n == 0 then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if c then
+ contextsprint(ctxcatcodes,c.tg)
+ end
+ end
+ end
+end
+
+function texfinalizers.name(collected,n)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if c then
+ local ns = c.ns
+ if not ns or ns == "" then
+ contextsprint(ctxcatcodes,c.tg)
+ else
+ contextsprint(ctxcatcodes,ns,":",c.tg)
+ end
+ end
+ end
+ end
+end
+
+function texfinalizers.tags(collected,nonamespace)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ local e = collected[c]
+ local ns = e.ns
+ if nonamespace or (not ns or ns == "") then
+ contextsprint(ctxcatcodes,e.tg)
+ else
+ contextsprint(ctxcatcodes,ns,":",e.tg)
+ end
+ end
+ end
+ end
+end
+
+--
+
+local function verbatim(id,before,after)
+ local e = getid(id)
+ if e then
+ if before then contextsprint(ctxcatcodes,before,"[",e.tg or "?","]") end
+ lxml.toverbatim(xmltostring(e.dt)) -- lxml.toverbatim(xml.totext(e.dt))
+ if after then contextsprint(ctxcatcodes,after) end
+ end
+end
+
+function lxml.inlineverbatim(id)
+ verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
+end
+
+function lxml.displayverbatim(id)
+ verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
+end
+
+lxml.verbatim = verbatim
+
+-- helpers
+
+function lxml.first(id,pattern)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ first(collected)
+ end
+end
+
+function lxml.last(id,pattern)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ last(collected)
+ end
+end
+
+function lxml.all(id,pattern)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ all(collected)
+ end
+end
+
+function lxml.count(id,pattern)
+ -- always needs to produce a result so no test here
+ count(xmlapplylpath(getid(id),pattern))
+end
+
+function lxml.attribute(id,pattern,a,default)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ attribute(collected,a,default)
+ end
+end
+
+function lxml.raw(id,pattern) -- the content, untouched by commands
+ local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
+ if collected and #collected > 0 then
+ local s = xmltostring(collected[1].dt)
+ if s ~= "" then
+ contextsprint(notcatcodes,s)
+ end
+ end
+end
+
+-- templates
+
+function lxml.rawtex(id,pattern) -- the content, untouched by commands
+ local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
+ if collected and #collected > 0 then
+ local s = xmltostring(collected[1].dt)
+ if s ~= "" then
+ contextsprint(notcatcodes,lpegmatch(p_texescape,s) or s)
+ end
+ end
+end
+
+function lxml.context(id,pattern) -- the content, untouched by commands
+ if pattern then
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected and #collected > 0 then
+ ctx_text(collected[1].dt[1])
+ end
+ else
+ local collected = getid(id)
+ if collected then
+ local dt = collected.dt
+ if dt and #dt > 0 then
+ ctx_text(dt[1])
+ end
+ end
+ end
+end
+
+function lxml.text(id,pattern)
+ if pattern then
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected and #collected > 0 then
+ text(collected)
+ end
+ else
+ local e = getid(id)
+ if e then
+ text(e.dt)
+ end
+ end
+end
+
+function lxml.pure(id,pattern)
+ if pattern then
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected and #collected > 0 then
+ parsedentity = unescapedentity
+ text(collected)
+ parsedentity = reparsedentity
+ end
+ else
+ parsedentity = unescapedentity
+ local e = getid(id)
+ if e then
+ text(e.dt)
+ end
+ parsedentity = reparsedentity
+ end
+end
+
+lxml.content = text
+
+function lxml.position(id,pattern,n)
+ position(xmlapplylpath(getid(id),pattern),tonumber(n))
+end
+
+function lxml.chainattribute(id,pattern,a,default)
+ chainattribute(xmlapplylpath(getid(id),pattern),a,default)
+end
+
+function lxml.path(id,pattern,nonamespace)
+ chainpath(xmlapplylpath(getid(id),pattern),nonamespace)
+end
+
+function lxml.concatrange(id,pattern,start,stop,separator,lastseparator,textonly) -- test this on mml
+ concatrange(xmlapplylpath(getid(id),pattern),start,stop,separator,lastseparator,textonly)
+end
+
+function lxml.concat(id,pattern,separator,lastseparator,textonly)
+ concatrange(xmlapplylpath(getid(id),pattern),false,false,separator,lastseparator,textonly)
+end
+
+function lxml.element(id,n)
+ position(xmlapplylpath(getid(id),"/*"),tonumber(n)) -- tonumber handy
+end
+
+lxml.index = lxml.position
+
+function lxml.pos(id)
+ local e = getid(id)
+ contextsprint(ctxcatcodes,e and e.ni or 0)
+end
+
+-- function lxml.att(id,a,default)
+-- local root = getid(id)
+-- if root then
+-- local at = root.at
+-- local str = (at and at[a]) or default
+-- if str and str ~= "" then
+-- contextsprint(notcatcodes,str)
+-- end
+-- elseif default then
+-- contextsprint(notcatcodes,default)
+-- end
+-- end
+--
+-- no need for an assignment so:
+
+-- function lxml.att(id,a,default)
+-- local e = getid(id)
+-- if e then
+-- local at = e.at
+-- if at then
+-- -- normally always true
+-- local str = at[a]
+-- if not str then
+-- if default and default ~= "" then
+-- contextsprint(notcatcodes,default)
+-- end
+-- elseif str ~= "" then
+-- contextsprint(notcatcodes,str)
+-- else
+-- -- explicit empty is valid
+-- end
+-- elseif default and default ~= "" then
+-- contextsprint(notcatcodes,default)
+-- end
+-- elseif default and default ~= "" then
+-- contextsprint(notcatcodes,default)
+-- end
+-- end
+
+do
+
+ local att
+
+ function lxml.att(id,a,default)
+ local e = getid(id)
+ if e then
+ local at = e.at
+ if at then
+ -- normally always true
+ att = at[a]
+ if not att then
+ if default and default ~= "" then
+ att = default
+ contextsprint(notcatcodes,default)
+ end
+ elseif att ~= "" then
+ contextsprint(notcatcodes,att)
+ else
+ -- explicit empty is valid
+ end
+ elseif default and default ~= "" then
+ att = default
+ contextsprint(notcatcodes,default)
+ end
+ elseif default and default ~= "" then
+ att = default
+ contextsprint(notcatcodes,default)
+ else
+ att = ""
+ end
+ end
+
+ function lxml.refatt(id,a)
+ local e = getid(id)
+ if e then
+ local at = e.at
+ if at then
+ att = at[a]
+ if att and att ~= "" then
+ att = gsub(att,"^#+","")
+ if att ~= "" then
+ contextsprint(notcatcodes,att)
+ return
+ end
+ end
+ end
+ end
+ att = ""
+ end
+
+ function lxml.lastatt()
+ contextsprint(notcatcodes,att)
+ end
+
+end
+
+function lxml.name(id)
+ local e = getid(id)
+ if e then
+ local ns = e.rn or e.ns
+ if ns and ns ~= "" then
+ contextsprint(ctxcatcodes,ns,":",e.tg)
+ else
+ contextsprint(ctxcatcodes,e.tg)
+ end
+ end
+end
+
+function lxml.match(id)
+ local e = getid(id)
+ contextsprint(ctxcatcodes,e and e.mi or 0)
+end
+
+function lxml.tag(id) -- tag vs name -> also in l-xml tag->name
+ local e = getid(id)
+ if e then
+ local tg = e.tg
+ if tg and tg ~= "" then
+ contextsprint(ctxcatcodes,tg)
+ end
+ end
+end
+
+function lxml.namespace(id)
+ local e = getid(id)
+ if e then
+ local ns = e.rn or e.ns
+ if ns and ns ~= "" then
+ contextsprint(ctxcatcodes,ns)
+ end
+ end
+end
+
+function lxml.flush(id)
+ local e = getid(id)
+ if e then
+ local dt = e.dt
+ if dt then
+ xmlsprint(dt)
+ end
+ end
+end
+
+function lxml.lastmatch()
+ local collected = xmllastmatch()
+ if collected then
+ all(collected)
+ end
+end
+
+function lxml.snippet(id,i)
+ local e = getid(id)
+ if e then
+ local dt = e.dt
+ if dt then
+ local dti = dt[i]
+ if dti then
+ xmlsprint(dti)
+ end
+ end
+ end
+end
+
+function lxml.direct(id)
+ local e = getid(id)
+ if e then
+ xmlsprint(e)
+ 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
+ end
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
+ end
+ end
+ end
+end
+
+-- loops
+
+function lxml.collected(id,pattern,reverse)
+ return xmlcollected(getid(id),pattern,reverse)
+end
+
+function lxml.elements(id,pattern,reverse)
+ return xmlelements(getid(id),pattern,reverse)
+end
+
+-- testers
+
+local found, empty = xml.found, xml.empty
+
+local doif, doifnot, doifelse = commands.doif, commands.doifnot, commands.doifelse
+
+function lxml.doif (id,pattern) doif (found(getid(id),pattern)) end
+function lxml.doifnot (id,pattern) doifnot (found(getid(id),pattern)) end
+function lxml.doifelse (id,pattern) doifelse(found(getid(id),pattern)) end
+function lxml.doiftext (id,pattern) doif (not empty(getid(id),pattern)) end
+function lxml.doifnottext (id,pattern) doifnot (not empty(getid(id),pattern)) end
+function lxml.doifelsetext (id,pattern) doifelse(not empty(getid(id),pattern)) end
+
+-- special case: "*" and "" -> self else lpath lookup
+
+local function checkedempty(id,pattern)
+ local e = getid(id)
+ if not pattern or pattern == "" then
+ local dt = e.dt
+ local nt = #dt
+ return (nt == 0) or (nt == 1 and dt[1] == "")
+ else
+ return empty(getid(id),pattern)
+ end
+end
+
+function lxml.doifempty (id,pattern) doif (checkedempty(id,pattern)) end
+function lxml.doifnotempty (id,pattern) doifnot (checkedempty(id,pattern)) end
+function lxml.doifelseempty(id,pattern) doifelse(checkedempty(id,pattern)) end
+
+-- status info
+
+statistics.register("xml load time", function()
+ if noffiles > 0 or nofconverted > 0 then
+ return format("%s seconds, %s files, %s converted", statistics.elapsedtime(xml), noffiles, nofconverted)
+ else
+ return nil
+ end
+end)
+
+statistics.register("lxml preparation time", function()
+ if noffiles > 0 or nofconverted > 0 then
+ local calls = xml.lpathcalls()
+ local cached = xml.lpathcached()
+ if calls > 0 or cached > 0 then
+ return format("%s seconds, %s nodes, %s lpath calls, %s cached calls",
+ statistics.elapsedtime(lxml), nofindices, calls, cached)
+ else
+ return nil
+ end
+ else
+ -- pretty close to zero so not worth mentioning
+ end
+end)
+
+statistics.register("lxml lpath profile", function()
+ local p = xml.profiled
+ if p and next(p) then
+ local s = table.sortedkeys(p)
+ local tested, matched, finalized = 0, 0, 0
+ logs.pushtarget("logfile")
+ logs.writer("\nbegin of lxml profile\n")
+ logs.writer("\n tested matched finalized pattern\n\n")
+ for i=1,#s do
+ local pattern = s[i]
+ local pp = p[pattern]
+ local t, m, f = pp.tested, pp.matched, pp.finalized
+ tested, matched, finalized = tested + t, matched + m, finalized + f
+ logs.writer(format("%9i %9i %9i %s",t,m,f,pattern))
+ end
+ logs.writer("\nend of lxml profile\n")
+ logs.poptarget()
+ return format("%s patterns, %s tested, %s matched, %s finalized (see log for details)",#s,tested,matched,finalized)
+ else
+ return nil
+ end
+end)
+
+-- misc
+
+function lxml.nonspace(id,pattern) -- slow, todo loop
+ xmltprint(xmlcollect(getid(id),pattern,true))
+end
+
+function lxml.strip(id,pattern,nolines,anywhere)
+ xml.strip(getid(id),pattern,nolines,anywhere)
+end
+
+function lxml.stripped(id,pattern,nolines)
+ local str = xmltext(getid(id),pattern) or ""
+ str = gsub(str,"^%s*(.-)%s*$","%1")
+ if nolines then
+ str = gsub(str,"%s+"," ")
+ end
+ xmlsprint(str)
+end
+
+function lxml.delete(id,pattern)
+ xml.delete(getid(id),pattern)
+end
+
+lxml.obsolete = { }
+
+lxml.get_id = getid lxml.obsolete.get_id = getid
+
+-- goodies:
+
+function texfinalizers.lettered(collected)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lettered(collected[c].dt[1]))
+ end
+ 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)
+ if e then
+ local a = e.at
+ if a and next(a) then
+ local setups, s = { }, 0
+ for k, v in next, a do
+ s = s + 1
+ setups[s] = k .. "=" .. v
+ end
+ setups = concat(setups,",")
+ -- tracing
+ context(setups)
+ end
+ end
+end
+
+local template = '<?xml version="1.0" ?>\n\n<!-- %s -->\n\n%s'
+
+function lxml.tofile(id,pattern,filename,comment)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ io.savedata(filename,format(template,comment or "exported fragment",tostring(collected[1])))
+ else
+ os.remove(filename) -- get rid of old content
+ end
+end
+
+texfinalizers.upperall = xmlfinalizers.upperall
+texfinalizers.lowerall = xmlfinalizers.lowerall
+
+function lxml.tobuffer(id,pattern,name,unescaped)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ if unescaped then
+ collected = xmlcontent(collected[1]) -- expanded entities !
+ else
+ collected = tostring(collected[1])
+ end
+ buffers.assign(name,collected)
+ else
+ buffers.erase(name)
+ end
+end
+
+-- relatively new:
+
+local permitted = nil
+local ctx_xmlinjector = context.xmlinjector
+
+xml.pihandlers["injector"] = function(category,rest,e)
+ local options = options_to_array(rest)
+ local action = options[1]
+ if not action then
+ return
+ end
+ local n = #options
+ if n > 1 then
+ local category = options[2]
+ if category == "*" then
+ ctx_xmlinjector(action)
+ elseif permitted then
+ if n == 2 then
+ if permitted[category] then
+ ctx_xmlinjector(action)
+ end
+ else
+ for i=2,n do
+ local category = options[i]
+ if category == "*" or permitted[category] then
+ ctx_xmlinjector(action)
+ return
+ end
+ end
+ end
+ end
+ else
+ ctx_xmlinjector(action)
+ end
+end
+
+local pattern = P("context-") * C((1-patterns.whitespace)^1) * C(P(1)^1)
+
+function lxml.applyselectors(id)
+ local root = getid(id)
+ local function filter(e)
+ local dt = e.dt
+ local ndt = #dt
+ local done = false
+ local i = 1
+ while i <= ndt do
+ local dti = dt[i]
+ if type(dti) == "table" then
+ if dti.tg == "@pi@" then
+ local text = dti.dt[1]
+ local what, rest = lpegmatch(pattern,text)
+ if what == "select" then
+ local categories = options_to_hash(rest)
+ if categories["begin"] then
+ local okay = false
+ if permitted then
+ for k, v in next, permitted do
+ if categories[k] then
+ okay = k
+ break
+ end
+ end
+ end
+ if okay then
+ if trace_selectors then
+ report_lxml("accepting selector: %s",okay)
+ end
+ else
+ categories.begin = false
+ if trace_selectors then
+ report_lxml("rejecting selector: % t",sortedkeys(categories))
+ end
+ end
+ for j=i,ndt do
+ local dtj = dt[j]
+ if type(dtj) == "table" then
+ local tg = dtj.tg
+ if tg == "@pi@" then
+ local text = dtj.dt[1]
+ local what, rest = lpegmatch(pattern,text)
+ if what == "select" then
+ local categories = options_to_hash(rest)
+ if categories["end"] then
+ i = j
+ break
+ else
+ -- error
+ end
+ end
+ elseif not okay then
+ dtj.tg = "@cm@"
+ end
+ else
+-- dt[j] = "" -- okay ?
+ end
+ end
+ end
+ elseif what == "include" then
+ local categories = options_to_hash(rest)
+ if categories["begin"] then
+ local okay = false
+ if permitted then
+ for k, v in next, permitted do
+ if categories[k] then
+ okay = k
+ break
+ end
+ end
+ end
+ if okay then
+ if trace_selectors then
+ report_lxml("accepting include: %s",okay)
+ end
+ else
+ categories.begin = false
+ if trace_selectors then
+ report_lxml("rejecting include: % t",sortedkeys(categories))
+ end
+ end
+ if okay then
+ for j=i,ndt do
+ local dtj = dt[j]
+ if type(dtj) == "table" then
+ local tg = dtj.tg
+ if tg == "@cm@" then
+ local content = dtj.dt[1]
+ local element = root and xml.toelement(content,root)
+ dt[j] = element
+ element.__p__ = dt -- needs checking
+ done = true
+ elseif tg == "@pi@" then
+ local text = dtj.dt[1]
+ local what, rest = lpegmatch(pattern,text)
+ if what == "include" then
+ local categories = options_to_hash(rest)
+ if categories["end"] then
+ i = j
+ break
+ else
+ -- error
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ filter(dti)
+ end
+ end
+ if done then
+ -- probably not needed
+ xml.reindex(dt)
+ end
+ end
+ i = i + 1
+ end
+ end
+ xmlwithelements(root,filter)
+end
+
+function xml.setinjectors(set)
+ local s = settings_to_set(set)
+ if permitted then
+ for k, v in next, s do
+ permitted[k] = true
+ end
+ else
+ permitted = s
+ end
+end
+
+function xml.resetinjectors(set)
+ if permitted and set and set ~= "" then
+ local s = settings_to_set(set)
+ for k, v in next, s do
+ if v then
+ permitted[k] = nil
+ end
+ end
+ else
+ permitted = nil
+ end
+end
+
+implement {
+ name = "xmlsetinjectors",
+ actions = xml.setinjectors,
+ arguments = "string"
+}
+
+implement {
+ name = "xmlresetinjectors",
+ actions = xml.resetinjectors,
+ arguments = "string"
+}
+
+implement {
+ name = "xmlapplyselectors",
+ actions = lxml.applyselectors,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-xml.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-xml.lua
new file mode 100644
index 00000000000..d0e25607820
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-xml.lua
@@ -0,0 +1,445 @@
+if not modules then modules = { } end modules ['lxml-xml'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+local find, lower, upper = string.find, string.lower, string.upper
+
+local xml = xml
+
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
+
+local function first(collected) -- wrong ?
+ return collected and collected[1]
+end
+
+local function last(collected)
+ return collected and collected[#collected]
+end
+
+local function all(collected)
+ return collected
+end
+
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
+
+local reverse = table.reversed
+
+local function attribute(collected,name)
+ if collected and #collected > 0 then
+ local at = collected[1].at
+ return at and at[name]
+ end
+end
+
+local function att(id,name)
+ local at = id.at
+ return at and at[name]
+end
+
+local function count(collected)
+ return collected and #collected or 0
+end
+
+local function position(collected,n)
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
+ end
+end
+
+local function match(collected)
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
+end
+
+local function index(collected)
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
+end
+
+local function attributes(collected,arguments)
+ if collected and #collected > 0 then
+ local at = collected[1].at
+ if arguments then
+ return at[arguments]
+ elseif next(at) then
+ return at -- all of them
+ end
+ end
+end
+
+local function chainattribute(collected,arguments) -- todo: optional levels
+ if collected and #collected > 0 then
+ local e = collected[1]
+ while e do
+ local at = e.at
+ if at then
+ local a = at[arguments]
+ if a then
+ return a
+ end
+ else
+ break -- error
+ end
+ e = e.__p__
+ end
+ end
+ return ""
+end
+
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
+ local e = collected[1] or collected
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
+ else
+ return ""
+ end
+end
+
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
+local function text(collected) -- hybrid
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
+ else
+ return ""
+ end
+end
+
+local function texts(collected)
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
+ end
+ end
+ return t
+end
+
+local function tag(collected,n)
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
+end
+
+local function name(collected,n)
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
+ end
+end
+
+local function tags(collected,nonamespace)
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
+ end
+ end
+ return t
+end
+
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
+ return false
+ end
+ elseif n > 1 then
+ return false
+ end
+ end
+ end
+ end
+ return true
+end
+
+finalizers.first = first
+finalizers.last = last
+finalizers.all = all
+finalizers.reverse = reverse
+finalizers.elements = all
+finalizers.default = all
+finalizers.attribute = attribute
+finalizers.att = att
+finalizers.count = count
+finalizers.position = position
+finalizers.match = match
+finalizers.index = index
+finalizers.attributes = attributes
+finalizers.chainattribute = chainattribute
+finalizers.text = text
+finalizers.texts = texts
+finalizers.tag = tag
+finalizers.name = name
+finalizers.tags = tags
+finalizers.empty = empty
+
+-- shortcuts -- we could support xmlfilter(id,pattern,first)
+
+function xml.first(id,pattern)
+ return first(xmlfilter(id,pattern))
+end
+
+function xml.last(id,pattern)
+ return last(xmlfilter(id,pattern))
+end
+
+function xml.count(id,pattern)
+ return count(xmlfilter(id,pattern))
+end
+
+function xml.attribute(id,pattern,a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
+end
+
+function xml.raw(id,pattern)
+ if pattern then
+ return raw(xmlfilter(id,pattern))
+ else
+ return raw(id)
+ end
+end
+
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
+ if pattern then
+ -- return text(xmlfilter(id,pattern))
+ local collected = xmlfilter(id,pattern)
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
+ elseif id then
+ -- return text(id)
+ return xmltotext(id) or ""
+ else
+ return ""
+ end
+end
+
+xml.content = text
+
+--
+
+function xml.position(id,pattern,n) -- element
+ return position(xmlfilter(id,pattern),n)
+end
+
+function xml.match(id,pattern) -- number
+ return match(xmlfilter(id,pattern))
+end
+
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
+end
+
+xml.all = xml.filter
+xml.index = xml.position
+xml.found = xml.filter
+
+-- a nice one:
+
+local function totable(x)
+ local t = { }
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg] = xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+
+xml.table = totable
+finalizers.table = totable
+
+local function textonly(e,t)
+ if e then
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "table" then
+ textonly(e,t)
+ else
+ t[#t+1] = e
+ end
+ end
+ end
+ end
+ return t
+end
+
+function xml.textonly(e) -- no pattern
+ return concat(textonly(e,{}))
+end
+
+--
+
+-- local x = xml.convert("<x><a x='+'>1<B>2</B>3</a></x>")
+-- xml.filter(x,"**/lowerall()") print(x)
+-- xml.filter(x,"**/upperall()") print(x)
+
+function finalizers.lowerall(collected)
+ for c=1,#collected do
+ local e = collected[c]
+ if not e.special then
+ e.tg = lower(e.tg)
+ local eat = e.at
+ if eat then
+ local t = { }
+ for k,v in next, eat do
+ t[lower(k)] = v
+ end
+ e.at = t
+ end
+ end
+ end
+end
+
+function finalizers.upperall(collected)
+ for c=1,#collected do
+ local e = collected[c]
+ if not e.special then
+ e.tg = upper(e.tg)
+ local eat = e.at
+ if eat then
+ local t = { }
+ for k,v in next, eat do
+ t[upper(k)] = v
+ end
+ e.at = t
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/m-newcolumnsets.mkiv b/Master/texmf-dist/tex/context/base/mkiv/m-newcolumnsets.mkiv
new file mode 100644
index 00000000000..e0fe60f3f4d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/m-newcolumnsets.mkiv
@@ -0,0 +1,38 @@
+%D \module
+%D [ file=m-newcolumnsets,
+%D version=2016.02.29,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=New Columnsets,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module will eventually be replaced by \type {m-oldcolumnsets}.
+
+\ifdefined \definepagegrid
+ \expandafter \endinput
+\else
+ \loadmarkfile{page-cst}
+\fi
+
+% \let\definecolumnset \definepagegrid
+% \let\setupcolumnset \setuppagegrid
+% \let\setupcolumnsetlines \setuppagegridlines
+% \let\setupcolumnsetstart \setuppagegridstart
+% \let\startcolumnset \startpagegrid
+% \let\stopcolumnset \stoppagegrid
+% \let\definecolumnsetspan \definepagegridspan
+% \let\setupcolumnsetspan \setuppagegridspan
+% \let\startcolumnsetspan \startpagegridspan
+% \let\stopcolumnsetspan \stoppagegridspan
+% \let\columnsetspanwidth \pagegridspanwidth
+% \let\definecolumnsetarea \definepagegridarea
+% \let\setupcolumnsetarea \setuppagegridarea
+% \let\setupcolumnsetareatext\setuppagegridareatext
+
+\endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/m-oldbibtex.mkiv b/Master/texmf-dist/tex/context/base/mkiv/m-oldbibtex.mkiv
new file mode 100644
index 00000000000..08c23e7cc87
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/m-oldbibtex.mkiv
@@ -0,0 +1,16 @@
+%D \module
+%D [ file=m-oldbibtex,
+%D version=2013.12.12, % based on bibl-apa.tex and later xml variant
+%D title=Falback on old method,
+%D subtitle=Publications,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted
+%D by \PRAGMA. See mreadme.pdf for details.
+
+\loadmarkfile{bibl-bib}
+\loadmarkfile{bibl-tra}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv
new file mode 100644
index 00000000000..c7c468d93ec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv
@@ -0,0 +1,77 @@
+%D \module
+%D [ file=m-oldotf,
+%D version=2015.07.08,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Traditional OTF Loader,
+%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
+
+\startluacode
+ local files = {
+ "font-otf",
+ "font-otb",
+ "font-inj",
+-- "font-ota",
+ "font-otn",
+ "font-otd",
+ "font-otp",
+ "font-otc",
+ "font-oth",
+ "font-odv",
+ "font-map",
+ "font-fbk",
+ "font-gds",
+ }
+ local report = logs.reporter("oldotf")
+ local findfile = resolvers.findfile
+ local addsuffix = file.addsuffix
+ report()
+ report("using traditional font loader code")
+ report()
+ for i=1,#files do
+ local foundfile = findfile(addsuffix(files[i],"lua"))
+ if foundfile and foundfile ~= "" then
+ report("loading %a",foundfile)
+ dofile(foundfile)
+ end
+ end
+ report()
+
+ -- needed for testing:
+
+ local nuts = nodes.nuts
+ local copy_node = nuts.copy
+ local kern = nuts.pool.register(nuts.pool.kern())
+ local setfield = nuts.setfield
+
+ nuts.setattr(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared
+
+ nodes.injections.installnewkern(function(k)
+ local c = copy_node(kern)
+ setfield(c,"kern",k)
+ return c
+ end)
+
+ directives.register("fonts.injections.fontkern", function(v) setfield(kern,"subtype",v and 0 or 1) end)
+
+ local fonts = fonts
+ local handlers = fonts.handlers
+ local otf = handlers.otf -- brrr
+ local afm = handlers.afm -- brrr
+ local getters = fonts.getters
+
+ getters.kern .opentype = otf.getkern
+ getters.substitution.opentype = otf.getsubstitution
+ getters.alternate .opentype = otf.getalternate
+ getters.multiple .opentype = otf.getmultiple
+
+\stopluacode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-acc.mkvi b/Master/texmf-dist/tex/context/base/mkiv/math-acc.mkvi
new file mode 100644
index 00000000000..415f2b91f2d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-acc.mkvi
@@ -0,0 +1,181 @@
+%D \module
+%D [ file=math-acc,
+%D version=2013.07.31,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Accents,
+%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 / Accents}
+
+% There are probably errors ... too distracted by amazing (piano) music videos running
+% on top of scite ... so: experimental code.
+
+\unprotect
+
+% This module permits overloading of accents so that we can do fancy things. The
+% implementation is similar to stackers. By default accenst are defined in a simple
+% way. Contrary to extensibles accents cannot grow indefinitely. Alas the
+% implementation of accents is different too, in the sense that they are
+% prepositioned i.e. are already raised. (In my opinion for no real reason as they
+% need to adapt anyway).
+%
+% $ \ruledhbox{$H$} \hat{H} \ruledhbox{$\widehat{H}$} \widehat{H} $
+%
+% One alternative is:
+%
+% \definemathoverextensible [top] [hoed] ["FE302]
+% \definemathoverextensible [top] [slang] ["FE303]
+%
+% $ \hoed{H} \ruledhbox{$\hoed{H}$} \ruledhbox{$\hoed{\tf H}$} \slang{H} $
+%
+% But that nills the italic correction (and I'm in nood to mess with that again).
+%
+% \definemathaccents [myaccents] [color=darkred]
+% \definemathtopaccent [myaccents] [mywidehat] ["0302]
+%
+% $ \hat{H} \widehat{H} \mywidehat{H} $
+
+% A first variant (kept for educational purposed):
+%
+% \installcorenamespace{mathaccents}
+%
+% \installcommandhandler \??mathaccents {mathaccent} \??mathaccents
+%
+% \let\setupmathaccents\setupmathaccent
+%
+% \setupmathaccents
+% [\c!top=,
+% \c!bottom=,
+% \c!mathstyle=,
+% \c!color=,
+% \c!command=\v!yes]
+%
+% \appendtoks
+% \edef\p_top_bottom{\namedmathaccentparameter\currentmathaccent\c!top\namedmathaccentparameter\currentmathaccent\c!bottom}%
+% \ifx\p_top_bottom\empty\else
+% \edef\p_command{\mathaccentparameter\c!command}%
+% \ifx\p_command\v!yes
+% \setuevalue\currentmathaccent{\math_accent{\currentmathaccent}}%
+% \fi
+% \fi
+% \to \everydefinemathaccent
+%
+% \def\math_accented_color_do_push{\pushcolor[\p_math_accent_color]}
+% \let\math_accented_color_do_pop \popcolor
+%
+% \unexpanded\def\math_accent#1#2%
+% {\begingroup
+% \edef\currentmathaccent{#1}%
+% \edef\p_math_accent_top {\mathaccentparameter\c!top}%
+% \edef\p_math_accent_bottom{\mathaccentparameter\c!bottom}%
+% \edef\p_math_accent_color {\mathaccentparameter\c!color}%
+% \startusemathstyleparameter\mathaccentparameter
+% \ifx\p_math_accented_color\empty
+% \let\math_accented_color_do_pop\donothing
+% \else
+% \let\math_accented_color_do_pop\popcolor
+% \math_accented_color_do_push
+% \fi
+% \ifx\p_math_accent_top\empty
+% \ifx\p_math_accent_bottom\empty
+% \else
+% \Umathaccent bottom \fam\zerocount\p_math_accent_bottom
+% \fi
+% \else
+% \ifx\p_math_accent_bottom\empty
+% \Umathaccent \fam\zerocount\p_math_accent_top
+% \else
+% \Umathaccent both \fam\zerocount\p_math_accent_top
+% \fam\zerocount\p_math_accent_bottom
+% \fi
+% \fi
+% {\popcolor#2}%
+% \stopusemathstyleparameter
+% \endgroup}
+%
+% \definemathaccent [myaccents] [\c!color=red]
+% \definemathaccent [mywidehat] [myaccents] [\c!top="0302]
+
+\installcorenamespace{mathaccents}
+
+\installcommandhandler \??mathaccents {mathaccents} \??mathaccents
+
+\setupmathaccents
+ [\c!top=,
+ \c!bottom=,
+ \c!mathstyle=,
+ \c!color=,
+ \c!command=\v!yes]
+
+\definemathaccents
+ [\v!both]
+
+\definemathaccents
+ [\v!top]
+ [\v!both]
+
+\definemathaccents
+ [\v!bottom]
+ [\v!both]
+
+\unexpanded\def\definemathtopaccent {\dotripleempty \math_accents_define_top }
+\unexpanded\def\definemathbottomaccent{\dotripleempty \math_accents_define_bottom}
+\unexpanded\def\definemathdoubleaccent{\doquadrupleempty\math_accents_define_double}
+
+\def\math_accents_define_top[#1][#2][#3]% class name top
+ {\ifthirdargument
+ \setuevalue{#2}{\math_accents_make_double {#1}\plusone{\number#3}\zerocount}%
+ \else
+ \setuevalue{#1}{\math_accents_make_double\noexpand\currentmathaccents\plusone{\number#2}\zerocount}%
+ \fi}
+
+\def\math_accents_define_bottom[#1][#2][#3]% class name bottom
+ {\ifthirdargument
+ \setuevalue{#2}{\math_accents_make_double {#1}\plustwo\zerocount{\number#3}}%
+ \else
+ \setuevalue{#1}{\math_accents_make_double\noexpand\currentmathaccents\plustwo\zerocount{\number#2}}%
+ \fi}
+
+\def\math_accents_define_double[#1][#2][#3][#4]% class name top bottom
+ {\iffourthargument
+ \setuevalue{#2}{\math_accents_make_double {#1}\plusthree{\number#3}{\number#4}}%
+ \else
+ \setuevalue{#1}{\math_accents_make_double\noexpand\currentmathaccents\plusthree{\number#2}{\number#3}}%
+ \fi}
+
+\def\math_accents_color_push_yes
+ {\pushcolor[\p_math_accent_color]%
+ \let\math_accents_color_pop\popcolor}
+
+\def\math_accents_color_push_nop
+ {\let\math_accents_color_pop\donothing}
+
+\unexpanded\def\math_accents_make_double#class#kind#top#bottom#content%
+ {\begingroup
+ \edef\currentmathaccents {#class}%
+ \edef\p_math_accent_color{\mathaccentsparameter\c!color}%
+ \startusemathstyleparameter\mathaccentsparameter
+ \ifx\p_math_accent_color\empty
+ \math_accents_color_push_nop
+ \else
+ \math_accents_color_push_yes
+ \fi
+ \ifcase#kind\or
+ \Umathaccent \fam\zerocount#top
+ \or
+ \Umathaccent bottom \fam\zerocount#bottom
+ \or
+ \Umathaccent both \fam\zerocount#top
+ \fam\zerocount#bottom
+ \fi
+ {\math_accents_color_pop#content}%
+ \stopusemathstyleparameter
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-act.lua b/Master/texmf-dist/tex/context/base/mkiv/math-act.lua
new file mode 100644
index 00000000000..d0ea789909c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-act.lua
@@ -0,0 +1,661 @@
+if not modules then modules = { } end modules ['math-act'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Here we tweak some font properties (if needed).
+
+local type, next = type, next
+local fastcopy = table.fastcopy
+local formatters = string.formatters
+
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+local trace_collecting = false trackers.register("math.collecting", function(v) trace_collecting = v end)
+
+local report_math = logs.reporter("mathematics","initializing")
+
+local context = context
+local commands = commands
+local mathematics = mathematics
+local texsetdimen = tex.setdimen
+local abs = math.abs
+
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+
+local fontchars = fonts.hashes.characters
+
+local mathfontparameteractions = sequencers.new {
+ name = "mathparameters",
+ arguments = "target,original",
+}
+
+appendgroup("mathparameters","before") -- user
+appendgroup("mathparameters","system") -- private
+appendgroup("mathparameters","after" ) -- user
+
+function fonts.constructors.assignmathparameters(original,target)
+ local runner = mathfontparameteractions.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
+function mathematics.initializeparameters(target,original)
+ local mathparameters = original.mathparameters
+ if mathparameters and next(mathparameters) then
+ target.mathparameters = mathematics.dimensions(mathparameters)
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.initializeparameters")
+
+local how = {
+ -- RadicalKernBeforeDegree = "horizontal",
+ -- RadicalKernAfterDegree = "horizontal",
+ ScriptPercentScaleDown = "unscaled",
+ ScriptScriptPercentScaleDown = "unscaled",
+ RadicalDegreeBottomRaisePercent = "unscaled"
+}
+
+function mathematics.scaleparameters(target,original)
+ if not target.properties.math_is_scaled then
+ local mathparameters = target.mathparameters
+ if mathparameters and next(mathparameters) then
+ local parameters = target.parameters
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ for name, value in next, mathparameters do
+ local h = how[name]
+ if h == "unscaled" then
+ -- kept
+ elseif h == "horizontal" then
+ value = value * hfactor
+ elseif h == "vertical"then
+ value = value * vfactor
+ else
+ value = value * factor
+ end
+ mathparameters[name] = value
+ end
+ end
+ target.properties.math_is_scaled = true
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.scaleparameters")
+
+-- AccentBaseHeight vs FlattenedAccentBaseHeight
+
+function mathematics.checkaccentbaseheight(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters and mathparameters.AccentBaseHeight == 0 then
+ mathparameters.AccentBaseHeight = target.parameters.x_height -- needs checking
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.checkaccentbaseheight") -- should go in lfg instead
+
+function mathematics.checkprivateparameters(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters then
+ local parameters = target.parameters
+ local properties = target.properties
+ if parameters then
+ local size = parameters.size
+ if size then
+ if not mathparameters.FractionDelimiterSize then
+ mathparameters.FractionDelimiterSize = 1.01 * size
+ end
+ if not mathparameters.FractionDelimiterDisplayStyleSize then
+ mathparameters.FractionDelimiterDisplayStyleSize = 2.40 * size
+ end
+ elseif properties then
+ report_math("invalid parameters in font %a",properties.fullname or "?")
+ else
+ report_math("invalid parameters in font")
+ end
+ elseif properties then
+ report_math("no parameters in font %a",properties.fullname or "?")
+ else
+ report_math("no parameters and properties in font")
+ end
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.checkprivateparameters")
+
+function mathematics.overloadparameters(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters and next(mathparameters) then
+ local goodies = target.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local parameters = mathematics and mathematics.parameters
+ if parameters then
+ if trace_defining then
+ report_math("overloading math parameters in %a @ %p",target.properties.fullname,target.parameters.size)
+ end
+ for name, value in next, parameters do
+ local tvalue = type(value)
+ if tvalue == "string" then
+ report_math("comment for math parameter %a: %s",name,value)
+ else
+ local oldvalue = mathparameters[name]
+ local newvalue = oldvalue
+ if oldvalue then
+ if tvalue == "number" then
+ newvalue = value
+ elseif tvalue == "function" then
+ newvalue = value(oldvalue,target,original)
+ elseif not tvalue then
+ newvalue = nil
+ end
+ if trace_defining and oldvalue ~= newvalue then
+ report_math("overloading math parameter %a: %S => %S",name,oldvalue,newvalue)
+ end
+ else
+ report_math("invalid math parameter %a",name)
+ end
+ mathparameters[name] = newvalue
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.overloadparameters")
+
+local function applytweaks(when,target,original)
+ local goodies = original.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local tweaks = mathematics and mathematics.tweaks
+ if tweaks then
+ tweaks = tweaks[when]
+ if tweaks then
+ if trace_defining then
+ report_math("tweaking math of %a @ %p (%s)",target.properties.fullname,target.parameters.size,when)
+ end
+ for i=1,#tweaks do
+ local tweak= tweaks[i]
+ local tvalue = type(tweak)
+ if tvalue == "function" then
+ tweak(target,original)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function mathematics.tweakbeforecopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("beforecopying",target,original)
+ end
+end
+
+function mathematics.tweakaftercopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("aftercopying",target,original)
+ end
+end
+
+sequencers.appendaction("beforecopyingcharacters","system","mathematics.tweakbeforecopyingfont")
+sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaftercopyingfont")
+
+function mathematics.overloaddimensions(target,original,set)
+ local goodies = target.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local dimensions = mathematics and mathematics.dimensions
+ if dimensions then
+ if trace_defining then
+ report_math("overloading dimensions in %a @ %p",target.properties.fullname,target.parameters.size)
+ end
+ local characters = target.characters
+ local parameters = target.parameters
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ local addprivate = fonts.helpers.addprivate
+ local function overload(dimensions)
+ for unicode, data in next, dimensions do
+ local character = characters[unicode]
+ if character then
+ --
+ local width = data.width
+ 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)
+ end
+ if width then character.width = width * hfactor end
+ if height then character.height = height * vfactor end
+ if depth then character.depth = depth * vfactor end
+ --
+ local xoffset = data.xoffset
+ local yoffset = data.yoffset
+ if xoffset then
+ xoffset = { "right", xoffset * hfactor }
+ end
+ if yoffset then
+ yoffset = { "down", -yoffset * vfactor }
+ end
+ if xoffset or yoffset then
+ local slot = { "slot", 1, addprivate(target,nil,fastcopy(character)) }
+ if xoffset and yoffset then
+ character.commands = { xoffset, yoffset, slot }
+ elseif xoffset then
+ character.commands = { xoffset, slot }
+ else
+ character.commands = { yoffset, slot }
+ end
+ character.index = nil
+ end
+ elseif trace_defining then
+ report_math("no overloading dimensions of %C, not in font",unicode)
+ end
+ end
+ end
+ if set == nil then
+ set = { "default" }
+ end
+ if set == "all" or set == true then
+ for name, set in next, dimensions do
+ overload(set)
+ end
+ else
+ if type(set) == "string" then
+ set = utilities.parsers.settings_to_array(set)
+ end
+ if type(set) == "table" then
+ for i=1,#set do
+ local d = dimensions[set[i]]
+ if d then
+ overload(d)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions")
+
+-- a couple of predefined tweaks:
+
+local tweaks = { }
+mathematics.tweaks = tweaks
+
+-- function tweaks.fixbadprime(target,original)
+-- target.characters[0xFE325] = target.characters[0x2032]
+-- end
+
+-- these could go to math-fbk
+
+-- local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap)
+-- local characters = target.characters
+-- -- if not characters[newchr] then -- xits needs an enforce
+-- local addprivate = fonts.helpers.addprivate
+-- local olddata = characters[oldchr]
+-- if olddata then
+-- if swap then
+-- swap = characters[swap]
+-- height = swap.depth
+-- depth = 0
+-- else
+-- height = height or 0
+-- depth = depth or 0
+-- end
+-- local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height }
+-- local newdata = {
+-- commands = { correction, { "slot", 1, oldchr } },
+-- width = olddata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- characters[newchr] = newdata
+-- local nextglyph = olddata.next
+-- while nextglyph do
+-- local oldnextdata = characters[nextglyph]
+-- local newnextdata = {
+-- commands = { correction, { "slot", 1, nextglyph } },
+-- width = oldnextdata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- local newnextglyph = addprivate(target,formatters["original-%H"](nextglyph),newnextdata)
+-- newdata.next = newnextglyph
+-- local nextnextglyph = oldnextdata.next
+-- if nextnextglyph == nextglyph then
+-- break
+-- else
+-- olddata = oldnextdata
+-- newdata = newnextdata
+-- nextglyph = nextnextglyph
+-- end
+-- end
+-- local hv = olddata.horiz_variants
+-- if hv then
+-- hv = fastcopy(hv)
+-- newdata.horiz_variants = hv
+-- for i=1,#hv do
+-- local hvi = hv[i]
+-- local oldglyph = hvi.glyph
+-- local olddata = characters[oldglyph]
+-- local newdata = {
+-- commands = { correction, { "slot", 1, oldglyph } },
+-- width = olddata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- hvi.glyph = addprivate(target,formatters["original-%H"](oldglyph),newdata)
+-- end
+-- end
+-- end
+-- -- end
+-- end
+
+-- function tweaks.fixoverline(target,original)
+-- local height, depth = 0, 0
+-- local mathparameters = target.mathparameters
+-- if mathparameters then
+-- height = mathparameters.OverbarVerticalGap
+-- depth = mathparameters.UnderbarVerticalGap
+-- else
+-- height = target.parameters.xheight/4
+-- depth = height
+-- end
+-- accent_to_extensible(target,0x203E,original,0x0305,height,depth)
+-- -- also crappy spacing for our purpose: push to top of baseline
+-- accent_to_extensible(target,0xFE3DE,original,0x23DE,height,depth,0x23DF)
+-- accent_to_extensible(target,0xFE3DC,original,0x23DC,height,depth,0x23DD)
+-- accent_to_extensible(target,0xFE3B4,original,0x23B4,height,depth,0x23B5)
+-- -- for symmetry
+-- target.characters[0xFE3DF] = original.characters[0x23DF]
+-- target.characters[0xFE3DD] = original.characters[0x23DD]
+-- target.characters[0xFE3B5] = original.characters[0x23B5]
+-- -- inspect(fonts.helpers.expandglyph(target.characters,0x203E))
+-- -- inspect(fonts.helpers.expandglyph(target.characters,0x23DE))
+-- end
+
+-- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweaks.fixoverline") -- for the moment always
+
+-- helpers
+
+local setmetatableindex = table.setmetatableindex
+local family_font = node.family_font
+
+local fontcharacters = fonts.hashes.characters
+local fontdescriptions = fonts.hashes.descriptions
+local extensibles = utilities.storage.allocate()
+fonts.hashes.extensibles = extensibles
+
+local chardata = characters.data
+local extensibles = mathematics.extensibles
+
+-- we use numbers at the tex end (otherwise we could stick to chars)
+
+local e_left = extensibles.left
+local e_right = extensibles.right
+local e_horizontal = extensibles.horizontal
+local e_vertical = extensibles.vertical
+local e_mixed = extensibles.mixed
+local e_unknown = extensibles.unknown
+
+local unknown = { e_unknown, false, false }
+
+local function extensiblecode(font,unicode)
+ local characters = fontcharacters[font]
+ local character = characters[unicode]
+ if not character then
+ return unknown
+ end
+ local first = character.next
+ local code = unicode
+ local next = first
+ while next do
+ code = next
+ character = characters[next]
+ next = character.next
+ end
+ local char = chardata[unicode]
+ if not char then
+ return unknown
+ end
+ if character.horiz_variants then
+ if character.vert_variants then
+ return { e_mixed, code, character }
+ else
+ local m = char.mathextensible
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ end
+ elseif character.vert_variants then
+ local m = char.mathextensible
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ elseif first then
+ -- assume accent (they seldom stretch .. sizes)
+ local m = char.mathextensible or char.mathstretch
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ else
+ return unknown
+ end
+end
+
+setmetatableindex(extensibles,function(extensibles,font)
+ local codes = { }
+ setmetatableindex(codes, function(codes,unicode)
+ local status = extensiblecode(font,unicode)
+ codes[unicode] = status
+ return status
+ end)
+ extensibles[font] = codes
+ return codes
+end)
+
+local function extensiblecode(family,unicode)
+ return extensibles[family_font(family or 0)][unicode][1]
+end
+
+-- left : [head] ...
+-- right : ... [head]
+-- horizontal : [head] ... [head]
+--
+-- abs(right["start"] - right["end"]) | right.advance | characters[right.glyph].width
+
+local function horizontalcode(family,unicode)
+ local font = family_font(family or 0)
+ local data = extensibles[font][unicode]
+ local kind = data[1]
+ local loffset = 0
+ local roffset = 0
+ if kind == e_left then
+ local charlist = data[3].horiz_variants
+ if charlist then
+ local left = charlist[1]
+ loffset = abs((left["start"] or 0) - (left["end"] or 0))
+ end
+ elseif kind == e_right then
+ local charlist = data[3].horiz_variants
+ local right = charlist[#charlist]
+ roffset = abs((right["start"] or 0) - (right["end"] or 0))
+ elseif kind == e_horizontal then
+ local charlist = data[3].horiz_variants
+ if charlist then
+ local left = charlist[1]
+ local right = charlist[#charlist]
+ loffset = abs((left ["start"] or 0) - (left ["end"] or 0))
+ roffset = abs((right["start"] or 0) - (right["end"] or 0))
+ end
+ end
+ return kind, loffset, roffset
+end
+
+mathematics.extensiblecode = extensiblecode
+mathematics.horizontalcode = horizontalcode
+
+interfaces.implement {
+ name = "extensiblecode",
+ arguments = { "integer", "integer" },
+ actions = { extensiblecode, context }
+}
+
+interfaces.implement {
+ name = "horizontalcode",
+ arguments = { "integer", "integer" },
+ actions = function(family,unicode)
+ local kind, loffset, roffset = horizontalcode(family,unicode)
+ texsetdimen("scratchleftoffset", loffset)
+ texsetdimen("scratchrightoffset",roffset)
+ context(kind)
+ end
+}
+
+-- experiment
+
+-- check: when true, only set when present in font
+-- force: when false, then not set when already set
+
+local blocks = characters.blocks -- this will move to char-ini
+
+-- operators : 0x02200
+-- symbolsa : 0x02701
+-- symbolsb : 0x02901
+-- supplemental : 0x02A00
+
+-- from mathematics.gaps:
+
+blocks["lowercaseitalic"].gaps = {
+ [0x1D455] = 0x0210E, -- ℎ h
+}
+
+blocks["uppercasescript"].gaps = {
+ [0x1D49D] = 0x0212C, -- ℬ script B
+ [0x1D4A0] = 0x02130, -- ℰ script E
+ [0x1D4A1] = 0x02131, -- ℱ script F
+ [0x1D4A3] = 0x0210B, -- ℋ script H
+ [0x1D4A4] = 0x02110, -- ℐ script I
+ [0x1D4A7] = 0x02112, -- ℒ script L
+ [0x1D4A8] = 0x02133, -- ℳ script M
+ [0x1D4AD] = 0x0211B, -- ℛ script R
+}
+
+blocks["lowercasescript"].gaps = {
+ [0x1D4BA] = 0x0212F, -- ℯ script e
+ [0x1D4BC] = 0x0210A, -- ℊ script g
+ [0x1D4C4] = 0x02134, -- ℴ script o
+}
+
+blocks["uppercasefraktur"].gaps = {
+ [0x1D506] = 0x0212D, -- ℭ fraktur C
+ [0x1D50B] = 0x0210C, -- ℌ fraktur H
+ [0x1D50C] = 0x02111, -- ℑ fraktur I
+ [0x1D515] = 0x0211C, -- ℜ fraktur R
+ [0x1D51D] = 0x02128, -- ℨ fraktur Z
+}
+
+blocks["uppercasedoublestruck"].gaps = {
+ [0x1D53A] = 0x02102, -- ℂ bb C
+ [0x1D53F] = 0x0210D, -- ℍ bb H
+ [0x1D545] = 0x02115, -- ℕ bb N
+ [0x1D547] = 0x02119, -- ℙ bb P
+ [0x1D548] = 0x0211A, -- ℚ bb Q
+ [0x1D549] = 0x0211D, -- ℝ bb R
+ [0x1D551] = 0x02124, -- ℤ bb Z
+}
+
+-- todo: tounicode
+
+function mathematics.injectfallbacks(target,original)
+ local properties = original.properties
+ if properties and properties.hasmath then
+ local specification = target.specification
+ if specification then
+ local fallbacks = specification.fallbacks
+ if fallbacks then
+ local definitions = fonts.collections.definitions[fallbacks]
+ if definitions then
+ if trace_collecting then
+ report_math("adding fallback characters to font %a",specification.hash)
+ end
+ local definedfont = fonts.definers.internal
+ local copiedglyph = fonts.handlers.vf.math.copy_glyph
+ local fonts = target.fonts
+ local size = specification.size -- target.size
+ local characters = target.characters
+ if not fonts then
+ fonts = { }
+ target.fonts = fonts
+ target.type = "virtual"
+ target.properties.virtualized = true
+ end
+ if #fonts == 0 then
+ fonts[1] = { id = 0, size = size } -- sel, will be resolved later
+ end
+ local done = { }
+ for i=1,#definitions do
+ local definition = definitions[i]
+ local name = definition.font
+ local start = definition.start
+ local stop = definition.stop
+ local gaps = definition.gaps
+ local check = definition.check
+ local force = definition.force
+ local rscale = definition.rscale or 1
+ local offset = definition.offset or start
+ local id = definedfont { name = name, size = size * rscale }
+ local index = #fonts + 1
+ fonts[index] = { id = id, size = size }
+ local chars = fontchars[id]
+ local function remap(unic,unicode,gap)
+ local unic = unicode + offset - start
+ if check and not chars[unicode] then
+ -- not in font
+ elseif force or (not done[unic] and not characters[unic]) then
+ if trace_collecting then
+ report_math("remapping math character, vector %a, font %a, character %C%s%s",
+ fallbacks,name,unic,check and ", checked",gap and ", gap plugged")
+ end
+ characters[unic] = copiedglyph(target,characters,chars,unicode,index)
+ done[unic] = true
+ end
+ end
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ remap(unic,unicode,false)
+ end
+ if gaps then
+ for unic, unicode in next, gaps do
+ remap(unic,unicode,true)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+sequencers.appendaction("aftercopyingcharacters", "system","mathematics.injectfallbacks")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv
new file mode 100644
index 00000000000..ebb20e33e31
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv
@@ -0,0 +1,1287 @@
+%D \module
+%D [ file=math-ali,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Math Alignments,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Math Alignments}
+
+\unprotect
+
+%D The code here has been moved from other files. Beware: the \MKII\ and
+%D \MKIV\ code is not gathered in files with the same name. In the
+%D meantime this code has been adapted to \MKIV\ but mnore is possible.
+
+%D \macros
+%D {definemathalignment, setupmathalignment, startmathalignment}
+%D
+%D Modules may provide additional alignment features. The following
+%D mechanisms are provided by the core.
+
+% n>1 ### needed, strange # interaction in recurse
+
+\newtoks\c_math_align_a
+\newtoks\c_math_align_b
+\newtoks\c_math_align_c
+
+\def\displayopenupvalue{.25\bodyfontsize}
+
+\def\math_build_eqalign
+ {\scratchtoks\emptytoks
+ \dorecurse{\mathalignmentparameter\c!m}\math_build_eqalign_step
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}}
+
+\def\math_build_eqalign_step
+ {\ifnum\recurselevel>\plusone
+ \scratchtoks\expandafter{\the\scratchtoks\tabskip\mathalignmentparameter\c!distance\aligntab\tabskip\zeropoint}%
+ \fi
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}%
+ \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}}
+
+\def\math_math_in_eqalign#1%
+ {\startforceddisplaymath
+ \tabskip\zeropoint
+ \everycr\emptytoks
+ {{}#1{}}%
+ \stopforceddisplaymath}
+
+\def\math_text_in_eqalign#1%
+ {\startimath
+ \tabskip\zeropoint
+ \everycr\emptytoks
+ #1%
+ \stopimath}
+
+\def\eqalign#1% why no halign here, probably because of displaywidth
+ {\emptyhbox
+ \mskip\thinmuskip
+ \vcenter
+ {\math_openup\displayopenupvalue % was: \openup\jot
+ \mathsurround\zeropoint
+ \ialign{%
+ \strut
+ \hfil
+ \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath
+ \aligntab
+ \startforceddisplaymath{{}\alignmark\alignmark{}}\stopforceddisplaymath
+ \hfil\crcr
+ #1\crcr}%
+ }%
+ \mskip\thinmuskip}
+
+% preamble is scanned for tabskips so we need the span to prevent an error message
+
+\setnewconstant\eqalignmode\plusone
+
+% use zeroskipplusfill
+
+% i really need to redo this eqno mess ... in lua
+
+\def\math_prepare_r_eqalign_no
+ {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}%
+ \c_math_align_b{\aligntab\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \c_math_align_c{\hfil\aligntab\span\math_text_in_eqalign{\alignmark\alignmark}\tabskip\zeropoint}%
+ \else\ifnum\mathraggedstatus=\plusthree
+ \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill\aligntab\span\math_text_in_eqalign{\alignmark\alignmark}\tabskip\zeropoint}%
+ \else
+ \c_math_align_c{\hfil\tabskip\centering\aligntab\llap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\zeropoint}%
+ \fi\fi
+ \global\mathnumberstatus\zerocount
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
+ \tabskip\centering}
+
+\def\math_prepare_l_eqalign_no % \checkeddisplaymath
+ {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}%
+ \c_math_align_b{\aligntab\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}%
+ % problem: number is handled after rest and so ends up in the margin
+ \ifnum\mathraggedstatus=\plusone
+ \c_math_align_c{\hfil\aligntab\kern-\displaywidth\rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}%
+ \else\ifnum\mathraggedstatus=\plusthree
+ \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill\aligntab\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}%
+ \else
+ \c_math_align_c{\hfil\tabskip\centering\aligntab\kern-\displaywidth\rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}%
+ \fi\fi
+ \global\mathnumberstatus\zerocount
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
+ \tabskip\centering}
+
+\def\math_both_eqalign_no_normal#1#2%
+ {\ifmmode
+ \the\mathdisplayaligntweaks % \let\strc_formulas_place_number\relax % strange hack
+ \vcenter\bgroup
+ \let\math_finish_eqalign_no\egroup
+ \else
+ \let\math_finish_eqalign_no\relax
+ \fi
+ #1%
+ \halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi \expandafter {\the\scratchtoks\crcr#2\crcr}%
+ \math_finish_eqalign_no}
+
+\def\math_both_eqalign_no_aligned#1%
+ {\ifmmode
+ \the\mathdisplayaligntweaks
+ \global\mathnumberstatus\plusone
+ \ifcase\mathraggedstatus
+ \def\math_finish_eqalign_no{\crcr\egroup}%
+ \else
+ % we're in a mathbox
+ \vcenter\bgroup
+ \def\math_finish_eqalign_no{\crcr\egroup\egroup}%
+ \fi
+ \fi
+ #1%
+ \halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi \expandafter \bgroup\the\scratchtoks\crcr}
+
+\def\math_rlap#1%
+ {\setbox\scratchbox\hbox{#1}%
+ \ifdim\wd\scratchbox>\mathnumbercorrection
+ \xdef\mathnumbercorrection{\the\wd\scratchbox}%
+ \fi
+ \box\scratchbox
+ \global\mathnumberstatus\plustwo}
+
+\def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no}
+\def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no}
+\def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no}
+\def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no}
+\def\math_finish_eqalign_no {\crcr\egroup}
+
+\let \reqalignno \math_handle_eqalign_no_r_normal
+\let \leqalignno \math_handle_eqalign_no_l_normal
+\let\alignreqalignno \math_handle_eqalign_no_r_aligned
+\let\alignleqalignno \math_handle_eqalign_no_l_aligned
+\let \eqalignno \math_handle_eqalign_no_r_normal
+\let \aligneqalignno \math_handle_eqalign_no_r_aligned
+
+%D Here we implement the user interface part. We start with basic math alignments:
+
+\newcount\c_math_eqalign_column
+
+\newtoks \everymathalignment
+
+\def\math_alignment_NR_indeed[#1][#2]%
+ {\strc_formulas_place_number_nested{#1}{#2}% to be tagged (better an attribute)
+ \crcr
+ \dostoptagged % finish row
+ \noalign{\glet\math_alignment_NC\math_alignment_NC_first}} % noalign used for change state, conditional does not work here
+
+\def\math_alignment_NC_first
+ {\glet\math_alignment_NC\math_alignment_NC_rest}
+
+\def\math_alignment_NC_rest
+ {\aligntab}
+
+\def\math_alignment_EQ
+ {\NC=}
+
+\def\math_alignment_NR
+ {\aligntab
+ \dostoptagged % finish cell
+ \dodoubleempty\math_alignment_NR_indeed} % use xx from tabulate
+
+\appendtoks
+ \glet\math_alignment_NC\math_alignment_NC_first
+ \unexpanded\def\NC{\math_alignment_NC}% messy, due to lookahead (we cannot use a flag)
+ \let\EQ\math_alignment_EQ
+ \let\NR\math_alignment_NR
+\to \everymathalignment
+
+\let\math_alignment_snap_start\relax
+\let\math_alignment_snap_stop \relax
+
+% experimental
+
+\def\math_alignment_snap_start
+ {\ifgridsnapping
+ \snaptogrid[\v!both]\vbox\bgroup
+ \fi}
+
+\def\math_alignment_snap_stop
+ {\ifgridsnapping
+ \egroup
+ \fi}
+
+% end of experimental
+
+\unexpanded\def\math_alignment_start#1%
+ {\edef\currentmathalignment{#1}%
+ \dosingleempty\math_alignment_start_indeed}
+
+\def\math_alignment_start_indeed[#1]%
+ {% \begingroup not permitted ($$...assignments...\halign... )
+ \math_alignment_snap_start
+ \iffirstargument
+ \setupmathalignment[\currentmathalignment][#1]% bad! ungrouped
+ \fi
+ \the\everymathalignment
+ \c_math_eqalign_column\zerocount
+ \processcommacommand
+ [\mathalignmentparameter\c!align]
+ {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument
+ \global\c_math_eqalign_column\plusone
+ \dostarttagged\t!math\empty
+ \dostarttagged\t!mathtable\currentmathalignment
+ \numberedeqalign}
+
+\def\math_alignment_stop
+ {\math_finish_eqalign_no
+ \dostoptagged
+ \dostoptagged
+ \math_alignment_snap_stop}
+
+\installcorenamespace{mathalignment}
+\installcorenamespace{mathalignmentvariant}
+
+\installcommandhandler \??mathalignment {mathalignment} \??mathalignment
+
+\appendtoks
+ \setuevalue{\e!start\currentmathalignment}{\math_alignment_start{\currentmathalignment}}%
+ \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}%
+\to \everydefinemathalignment
+
+\setupmathalignment
+ [\c!n=2,
+ \c!m=1,
+ \c!distance=\emwidth]
+
+\definemathalignment[align] % default case (this is what amstex users expect)
+\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
+
+% special case.. in case one mistypes ..
+
+\ifdefined \startalignment
+
+ \let\align_math_normal_start\startalign
+ \let\align_math_normal_stop \stopalign
+
+ \let\align_text_normal_start\startalignment
+ \let\align_text_normal_stop \stopalignment
+
+ \unexpanded\def\startalign
+ {\ifmmode
+ \let\stopalign\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align
+ \expandafter\align_math_normal_start
+ \else
+ \let\stopalign\align_text_normal_stop
+ \expandafter\align_text_normal_start
+ \fi}
+
+ \let\stopalign\relax
+
+ \unexpanded\def\startalignment
+ {\ifmmode
+ \let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align
+ \expandafter\align_math_normal_start
+ \else
+ \let\stopalignment\align_text_normal_stop
+ \expandafter\align_text_normal_start
+ \fi}
+
+ \let\stopalignment\relax
+
+\fi
+
+%
+
+\unexpanded\def\numberedeqalign
+ {\doifelse{\formulaparameter\c!location}\v!left
+ \math_handle_eqalign_no_l_aligned
+ \math_handle_eqalign_no_r_aligned}
+
+\def\math_first_in_eqalign
+ {\global\c_math_eqalign_column\plusone
+ \dostarttagged\t!mathtablerow \empty
+ \dostarttagged\t!mathtablecell\empty}
+
+\def\math_next_in_eqalign
+ {\global\advance\c_math_eqalign_column\plusone
+ \dostoptagged % finish cell
+ \dostarttagged\t!mathtablecell\empty}
+
+\def\math_left_of_equalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or
+ \relax \or \hfill \or \hfill
+ \fi
+ \fi}
+
+\def\math_right_of_eqalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or
+ \hfill \or \relax \or \hfill
+ \fi
+ \fi}
+
+\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments)
+ {\expandafter\let\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\endcsname
+ \csname\??mathalignmentvariant\ifcsname\??mathalignmentvariant#1\endcsname#1\else\v!normal\fi\endcsname}
+
+\letvalue{\??mathalignmentvariant\v!normal}\zerocount
+\letvalue{\??mathalignmentvariant\v!left }\plusone
+\letvalue{\??mathalignmentvariant\v!right }\plustwo
+\letvalue{\??mathalignmentvariant\v!middle}\plusthree
+
+\def\math_align_NR_generic[#1][#2]%
+ {\strc_formulas_place_number_nested{#1}{#2}\crcr}
+
+%D \starttyping
+%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0]
+%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1]
+%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2]
+%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3]
+%D \stoptyping
+
+%D \startbuffer
+%D \placeformula \startformula \eqalignno {
+%D a &= b & \formulanumber \cr
+%D c &= d \cr
+%D &= e \cr
+%D &= f & \formulanumber
+%D } \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR[for:demo-a-1]
+%D \NC \EQ g \NR[for:demo-a-2][a]
+%D \NC \EQ h \NR[for:demo-a-3][b]
+%D \NC \EQ i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR
+%D \NC \EQ g \NR
+%D \NC \EQ h \NR
+%D \NC \EQ i \NR[+]
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \NC \eq b \NR[+]
+%D \NC c \NC \neq d \NR
+%D \NC \NC \neq f \NR[for:demo-b-1]
+%D \NC \NC \geq g \NR[for:demo-b-2][a]
+%D \NC \NC \leq h \NR[for:demo-b-3][b]
+%D \NC \NC \neq i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={left,middle,right}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={right,middle,left}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \setupmathalignment[n=3,align={middle,middle,middle}]%
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \dorecurse{5}{\startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula}
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathcases, setupmathcases, startmathcases}
+%D
+%D Another wish \unknown
+
+\installcorenamespace{mathcases}
+
+\installcommandhandler \??mathcases {mathcases} \??mathcases
+
+\setupmathcases
+ [\c!distance=\emwidth,
+ \c!strut=\v!yes, % new
+ \c!numberdistance=2.5\emwidth,
+ \c!left={\left\{\mskip\thinmuskip},
+ \c!right={\right.}]
+
+\appendtoks
+ \setuevalue{\e!start\currentmathcases}{\math_cases_start{\currentmathcases}}%
+ \setvalue {\e!stop \currentmathcases}{\math_cases_stop}%
+\to \everydefinemathcases
+
+\unexpanded\def\math_cases_start#1%
+ {\begingroup
+ \edef\currentmathcases{#1}%
+ \dosingleempty\math_cases_start_indeed}
+
+\def\math_cases_NC_zero
+ {\math_cases_NC}
+
+\def\math_cases_MC_zero
+ {\math_cases_NC
+ \ifmmode\else
+ \startimath
+ \let\math_cases_end_math\stopimath
+ \fi}
+
+\let\math_cases_end_math\relax
+
+\def\math_cases_NR_zero
+ {\unskip
+ \math_cases_end_math
+ \aligntab
+ \global\let\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}
+
+\def\math_cases_NC_second
+ {\math_cases_end_math\aligntab}
+
+\let\math_cases_NR\math_align_NR_generic
+
+\unexpanded\def\math_cases_start_indeed[#1]%
+ {\iffirstargument
+ \setupcurrentmathcases[#1]%
+ \fi
+ \edef\p_strut{\mathcasesparameter\c!strut}%
+ \ifx\p_strut\v!yes
+ \let\math_cases_strut\strut
+ \else
+ \let\math_cases_strut\relax
+ \fi
+ \mathcasesparameter\c!left
+ \vcenter\bgroup
+ \pushmacro\math_cases_NC
+ \let\endmath\relax
+ \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
+ \normalbaselines
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \global\c_math_eqalign_column\plusone
+ \halign\bgroup
+ \startimath
+ \mathcasesparameter\c!style
+ \alignmark\alignmark
+ \stopimath
+ \hfil
+ \aligntab
+ \hskip\mathcasesparameter\c!distance\relax
+ \popmacro\math_cases_NC
+ \math_cases_strut % looks better
+ \alignmark\alignmark
+ \hfil
+ \aligntab
+ \hskip\mathcasesparameter\c!numberdistance\relax
+ \let\formuladistance\!!zeropoint
+ \span\math_text_in_eqalign{\alignmark\alignmark}%
+ \crcr} % todo: number
+
+\def\math_cases_stop
+ {\crcr
+ \egroup
+ \popmacro\math_cases_NC
+ \egroup
+ \mathcasesparameter\c!right
+ \endgroup}
+
+\definemathcases[cases]
+\definemathcases[\v!mathcases]
+
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR[+]
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR[+]
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathmatrix, setupmathmatrix, startmathmatrix}
+%D
+%D Yet another one \unknown
+
+\installcorenamespace{mathmatrix}
+
+\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix
+
+\setupmathmatrix
+ [\c!distance=\emwidth,
+ \c!left=,
+ \c!right=,
+ \c!align=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start{\currentmathmatrix}}%
+ \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem
+\to \everydefinemathmatrix
+
+\let\math_matrix_NC\relax
+
+\unexpanded\def\math_matrix_start#1%
+ {\begingroup
+ \edef\currentmathmatrix{#1}%
+ \dosingleempty\math_matrix_start_indeed}
+
+\unexpanded\def\math_matrix_start_indeed[#1]%
+ {\iffirstargument
+ \setupcurrentmathmatrix[#1]%
+ \fi
+ % \emptyhbox % noted at 25-05-2014: what was that one doing here? it messed up spacing
+ \math_matrix_align_method_analyze
+ \mathmatrixleft
+ % new per 13-10-2014
+ \edef\p_strut{\mathmatrixparameter\c!strut}%
+ \ifx\p_strut\v!no
+ \let\m_matrix_strut\relax
+ \else
+ \let\m_matrix_strut\strut
+ \ifx\p_strut\v!yes\else
+ \spacing\p_strut
+ \fi
+ \fi
+ %
+ \mathmatrixbox\bgroup
+ \pushmacro\math_matrix_NC
+ \let\endmath\relax
+ \def\NC{\math_matrix_NC}%
+ \def\MC{\math_matrix_NC\ifmmode\else\startimath\let\endmath\stopimath\fi}%
+ \global\let\math_matrix_NC\math_matrix_NC_indeed
+ \def\NR{\endmath\global\let\math_matrix_NC\math_matrix_NC_indeed\m_matrix_strut \crcr}%
+ \normalbaselines
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \c_math_eqalign_column\zerocount
+ \processcommacommand
+ [\mathmatrixparameter\c!align]
+ {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}%
+ \scratchcounter\ifnum\c_math_eqalign_column>\zerocount \c_math_eqalign_column \else \plusone \fi
+ \global\c_math_eqalign_column\plusone
+ \math_matrix_prepare}
+
+\def\math_matrix_stop
+ {\crcr
+ \mathstrut\crcr
+ \noalign{\kern-\baselineskip}%
+ \egroup
+ \popmacro\math_matrix_NC
+ \egroup
+ \mathmatrixright
+ \endgroup}
+
+\definemathmatrix[matrix]
+\definemathmatrix[\v!mathmatrix]
+
+\def\math_matrix_prepare
+ {\c_math_align_a{\strut\math_first_in_eqalign\math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}%
+ \c_math_align_b{\aligntab\hskip\mathmatrixparameter\c!distance
+ \math_next_in_eqalign\math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}%
+ \c_math_align_c{\aligntab\aligntab\hskip\mathmatrixparameter\c!distance
+ \math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}%
+ \scratchtoks\emptytoks
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}%
+ \dorecurse{\numexpr\scratchcounter-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}%
+ \halign \expandafter \bgroup\the\scratchtoks \crcr}
+
+\unexpanded\def\math_matrix_NC_indeed
+ {\gdef\math_matrix_NC{\endmath\aligntab}}
+
+\installcorenamespace{mathmatrixalignmethod}
+
+\let\mathmatrixleft \empty % experimental hook
+\let\mathmatrixright\empty % experimental hook
+
+\def\math_matrix_process#1#2%
+ {\dowithnextbox
+ {\scratchdimen\dimexpr(\nextboxdp-\nextboxht)/2 \ifcase#2\or+\mathaxisheight\textfont2\fi\relax
+ \ifcase#1\relax\or\lower\scratchdimen\or\or\raise\scratchdimen\fi\hbox\bgroup
+ \normalstartimath
+ \mathmatrixparameter\c!left
+ \vcenter{\unvbox\nextbox}%
+ \mathmatrixparameter\c!right
+ \normalstopimath
+ \egroup}%
+ \vbox}
+
+\unexpanded\def\installmathmatrixalignmethod#1#2%
+ {\setvalue{\??mathmatrixalignmethod#1}{#2}}
+
+\def\math_matrix_align_method_analyze
+ {\csname\??mathmatrixalignmethod\ifcsname\??mathmatrixalignmethod\mathmatrixparameter\c!location\endcsname
+ \mathmatrixparameter\c!location
+ \else
+ \v!normal
+ \fi\endcsname}
+
+\installmathmatrixalignmethod\v!top {\def\mathmatrixbox{\math_matrix_process\plusthree\plusone }}
+\installmathmatrixalignmethod\v!high {\def\mathmatrixbox{\math_matrix_process\plusthree\zerocount}}
+\installmathmatrixalignmethod\v!lohi {\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}}
+\installmathmatrixalignmethod\v!low {\def\mathmatrixbox{\math_matrix_process\plusone \zerocount}}
+\installmathmatrixalignmethod\v!bottom{\def\mathmatrixbox{\math_matrix_process\plusone \plusone }}
+\installmathmatrixalignmethod\v!normal{\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}} % lohi
+
+%D \startbuffer
+%D \placeformula \startformula[-] \startmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25]
+%D
+%D \startbuffer
+%D \placeformula \startformula[-] \startbmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopbmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Taco added some code (dedicated to Aditya Mahajan) that gives more
+%D control over aligments:
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix
+%D \NC a + x \NC = \NC a + d \NR
+%D \NC y \NC = \NC d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [distance=3pt,align={right,left}]
+%D \NC a + x \NC = a + d \NR
+%D \NC y \NC = d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [left=\left(,right=\right)]
+%D \NC a + x \NR
+%D \NC y \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D A bit more complex code:
+%D
+%D \startbuffer
+%D \startformula
+%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}}
+%D \left\{ (R_1, R_2) :
+%D \startmatrix[distance=1em,align={left,left,right}]
+%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR
+%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR
+%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR
+%D \stopmatrix
+%D \right\}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {startmatrices}
+%D
+%D Just a handy keystroke safer:
+
+\unexpanded\def\startmatrices
+ {\begingroup
+ \setupmathmatrix}
+
+\unexpanded\def\stopmatrices
+ {\endgroup}
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix[left={\left(},right={\right)}]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=low]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=high]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \startformula
+%D \startmatrices[left={\left(},right={\right)}]
+%D \startmatrix
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=bottom]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=top]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopmatrices
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % does not run well: \getbuffer
+
+%D \macros
+%D {startintertext}
+%D
+%D Preliminary feature:
+%D
+%D {\em example code}
+%D
+%D The intertext commands have to be expandable (in aligment lookahead) so
+%D we cannot use \type {\unexpanded}.
+
+\def\startintertext#1\stopintertext
+ {\noalign{\math_intertext{#1}}}
+
+\let\stopintertext\relax
+
+\def\intertext#1%
+ {\noalign{\math_intertext{#1}}}
+
+\unexpanded\def\math_intertext#1%
+ {\penalty\postdisplaypenalty
+ \afterdisplayspace
+ \vbox{\forgetall\noindent#1\par}%
+ \penalty\predisplaypenalty
+ \beforedisplayspace}
+
+%D \macros
+%D {substack}
+%D
+%D Preliminary code:
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{%
+%D \startsubstack
+%D i = 1 \NR
+%D i \neq n \NR
+%D i \neq m
+%D \stopsubstack
+%D }a_i
+%D \stopformula
+%D \stopbuffer
+%D
+%D \getbuffer which was typed as \typebuffer
+%D
+%D Notice that these macros give the correct spacing for
+%D subscripts. Compare for example
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{\startsubstack a \NR b \NR \stopsubstack}
+%D \text{ and }
+%D \sum_{\scriptstyle a \atop \scriptstyle}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+\unexpanded\def\startsubstack
+ {\begingroup
+ \vcenter\bgroup
+ \baselineskip\mathstacktotal
+ \lineskip\mathstackvgap
+ \lineskiplimit\lineskip
+ \let\stopmathmode\relax
+ \def\NC{\math_matrix_NC}%
+ \def\MC{\math_matrix_NC\startmathmode}%
+ \global\let\math_matrix_NC\math_matrix_NC_indeed
+ \def\NR
+ {\stopmathmode
+ \global\let\math_matrix_NC\math_matrix_NC_indeed
+ \crcr}%
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr}
+
+\def\stopsubstack
+ {\crcr
+ \egroup
+ \egroup
+ \endgroup}
+
+%D \macros
+%D {bordermatrix}
+%D
+%D In \PLAIN\ \TEX\ the width of a parenthesis is stored in
+%D the \DIMENSION\ \type{\mathparentwd}. This value is derived from
+%D the width of \type{\tenrm B}, so let's take care of it now:
+
+\ifx\mathparentwd\undefined \newdimen\mathparentwd \fi
+
+\let\normalbordermatrix\bordermatrix % move that code to here instead
+
+\def\bordermatrix
+ {\begingroup
+ \setbox\scratchbox\hbox{\mr\char"239C}%
+ \global\mathparentwd\wd\scratchbox
+ \endgroup
+ \normalbordermatrix}
+
+% to be tested
+%
+% \def\bordermatrix
+% {\begingroup\mr\global\mathparentwd\fontcharwd\font"239C\relax\endgroup
+% \normalbordermatrix}
+
+%D \macros{overset, underset}
+%D
+%D The macros \type{\overset} and \type{\underset} are provided by
+%D \AMS\ packages in \LATEX. These macro allows you to place a symbol
+%D above or below another symbol, irrespective of whether the other
+%D symbol is a relation or something else, and without influencing the
+%D spacing. For most cases there is a better way to do such things
+%D (declaring a math command with limop option, or using accents), but
+%D occasionally these macros can be useful, for example:
+%D
+%D \startbuffer
+%D \startformula
+%D \overset{*}{X} \underset{*}{X}
+%D \stopformula
+%D \stopbuffer
+%D \typebuffer \getbuffer
+%D
+%D Use these macros sparingly. Remember, \TEX\ was designed for
+%D mathematics, so there is usually a proper method for typesetting
+%D common math notation.
+%D
+%D These macros are a cleaner version of \type {\binrel@} and
+%D \type {\binrel@@} macros in \AMSTEX\ packages.
+
+\def\math_binrel_apply#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\thinmuskip 0mu
+ \medmuskip -1mu
+ \thickmuskip -1mu
+ \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}%
+ \kern-\wd\scratchbox
+ \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}%
+ \ifdim\wd\scratchbox<\zeropoint
+ \endgroup
+ \expandafter\mathbin
+ \else\ifdim\wd\scratchbox>\zeropoint
+ \endgroup
+ \doubleexpandafter\mathrel
+ \else
+ \endgroup
+ \doubleexpandafter\firstofoneargument
+ \fi\fi}
+
+\unexpanded\def\overset#1#2%
+ {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}}
+
+\unexpanded\def\underset#1#2%
+ {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}}
+
+%D The following code comes from \type {math-str.mkiv}.
+%D
+%D Here we implement a basic math alignment mechanism. Numbers
+%D are also handled. The macros \type {\startinnermath} and
+%D \type {\stopinnermath} can be overloaded in specialized
+%D modules.
+
+\installcorenamespace{mathinnerstart}
+\installcorenamespace{mathinnerstop}
+
+% \unexpanded\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname}
+% \unexpanded\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname}
+
+\unexpanded\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal}
+\unexpanded\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal}
+
+\unexpanded\def\mathinnerstrut
+ {\doif{\formulaparameter\c!strut}\v!yes\strut}
+
+\unexpanded\def\defineinnermathhandler#1#2#3%
+ {\setvalue{\??mathinnerstart#1}{#2}%
+ \setvalue{\??mathinnerstop #1}{#3}}
+
+\newif\iftracemath
+
+\def\math_hbox
+ {\iftracemath\ruledhbox\else\hbox\fi}
+
+\newconstant\mathraggedstatus % normal left center right
+\newconstant\mathnumberstatus % nothing normal shift_right
+
+\let\mathnumbercorrection\!!zeropoint
+
+\let\math_the_r_eq_no\empty
+\let\math_the_l_eq_no\empty
+
+\unexpanded\def\startmathbox#1%
+ {\hsize\displaywidth % \checkeddisplaymath
+ \global\mathnumberstatus\plusone
+ \mathraggedstatus#1\relax
+ \let\mathnumbercorrection\!!zeropoint
+ \global\let\math_the_r_eq_no\empty
+ \global\let\math_the_l_eq_no\empty
+ \def\reqno{\gdef\math_the_r_eq_no}%
+ \def\leqno{\gdef\math_the_l_eq_no}%
+ \let\eqno\reqno
+ % added
+ \let\normalreqno\reqno
+ \let\normalleqno\leqno
+ \let\normaleqno \eqno
+ % added
+ \strc_formulas_place_number
+ \setbox\scratchbox\math_hbox to \displaywidth\bgroup % \checkeddisplaymath
+ \mathinnerstrut
+ \startforceddisplaymath
+ \ifcase\mathraggedstatus\or\hfill\or\hfill\fi}
+
+\def\math_box_llapped_math_no
+ {\ifcase\mathraggedstatus\or
+ \math_the_r_eq_no
+ \or
+ \llap{\math_the_r_eq_no}%
+ \or
+ \llap{\math_the_r_eq_no}%
+ \fi}
+
+\def\math_box_rlapped_math_no
+ {\ifcase\mathraggedstatus\or
+ \rlap{\math_the_l_eq_no}%
+ \or
+ \rlap{\math_the_l_eq_no}%
+ \or
+ \math_the_l_eq_no
+ \fi}
+
+\unexpanded\def\stopmathbox
+ {\stopforceddisplaymath
+ \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi
+ \egroup
+ \setbox0\hbox{\unhcopy\scratchbox}%
+ \scratchdimen\wd0
+ % to be tested: \scratchdimen\naturalwd\scratchbox
+ \ifdim\scratchdimen>\displaywidth % \checkeddisplaymath
+ \donetrue
+ \else
+ \donefalse
+ \fi
+ \hbox to \displaywidth\bgroup
+ \ifcase\mathnumberstatus
+ \box\scratchbox
+ \or
+ \ifx\math_the_l_eq_no\empty
+ \ifx\math_the_r_eq_no\empty
+ \box\scratchbox
+ \else
+ \ifdone
+ \vpack{\box\scratchbox\hpack to \displaywidth{\hss\math_box_llapped_math_no}}% \checkeddisplaymath
+ \else
+ \hss\box\scratchbox\math_box_llapped_math_no % hss makes room for number
+ \fi
+ \fi
+ \else
+ \ifdone
+ \vpack{\hpack to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}% \checkeddisplaymath
+ \else
+ \math_box_rlapped_math_no\box\scratchbox\hss % hss makes room for number
+ \fi
+ \fi
+ \or
+ \hskip\mathnumbercorrection
+ \box\scratchbox
+ \hss
+ \else
+ \box\scratchbox
+ \fi
+ \egroup}
+
+\defineinnermathhandler\v!left {\startmathbox\plusone }{\stopmathbox}
+\defineinnermathhandler\v!middle {\startmathbox\plustwo }{\stopmathbox}
+\defineinnermathhandler\v!right {\startmathbox\plusthree}{\stopmathbox}
+\defineinnermathhandler\v!flushleft {\startmathbox\plusthree}{\stopmathbox}
+\defineinnermathhandler\v!center {\startmathbox\plustwo }{\stopmathbox}
+\defineinnermathhandler\v!flushright{\startmathbox\plusone }{\stopmathbox}
+\defineinnermathhandler\v!normal {} {}
+
+%defineinnermathhandler\v!normal {\startmathbox\plustwo }{\stopmathbox}
+
+%D [The examples below are in english and don't process in the
+%D documentation style, which will be english some day.]
+%D
+%D Normally a formula is centered, but in case you want to
+%D align it left or right, you can set up formulas to behave
+%D that way. Normally a formula will adapt is left indentation
+%D to the environment:
+%D
+%D \startbuffer
+%D \fakewords{20}{40}\epar
+%D \startitemize
+%D \item \fakewords{20}{40}\epar
+%D \placeformula \startformula \fakeformula \stopformula
+%D \item \fakewords{20}{40}\epar
+%D \stopitemize
+%D \fakewords{20}{40}\epar
+%D \stopbuffer
+%D
+%D % \getbuffer
+%D
+%D In the next examples we explicitly align formulas to the
+%D left (\type {\raggedleft}), center and right (\type
+%D {\raggedright}):
+%D
+%D \startbuffer
+%D \setupformulas[align=left]
+%D \startformula\fakeformula\stopformula
+%D \setupformulas[align=middle]
+%D \startformula\fakeformula\stopformula
+%D \setupformulas[align=right]
+%D \startformula\fakeformula\stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Or in print:
+%D
+%D % {\getbuffer}
+%D
+%D With formula numbers these formulas look as follows:
+%D
+%D \startbuffer
+%D \setupformulas[align=left]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \setupformulas[align=middle]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \setupformulas[align=right]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \stopbuffer
+%D
+%D % {\getbuffer}
+%D
+%D This was keyed in as:
+%D
+%D \typebuffer
+%D
+%D When tracing is turned on (\type {\tracemathtrue}) you can
+%D visualize the bounding box of the formula,
+%D
+%D % {\tracemathtrue\getbuffer}
+%D
+%D As you can see, the dimensions are the natural ones, but if
+%D needed you can force a normalized line:
+%D
+%D \startbuffer
+%D \setupformulas[strut=yes]
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This time we get a more spacy result.
+%D
+%D % {\tracemathtrue\getbuffer}
+%D
+%D We will now show a couple of more settings and combinations
+%D of settings. In centered formulas, the number takes no space
+%D
+%D \startbuffer
+%D \setupformulas[align=middle]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D You can influence the placement of the whole box with the
+%D parameters \type {leftmargin} and \type {rightmargin}.
+%D
+%D \startbuffer
+%D \setupformulas[align=right,leftmargin=3em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D
+%D \setupformulas[align=left,rightmargin=1em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D You can also inherit the margin from the environment.
+%D
+%D \startbuffer
+%D \setupformulas[align=right,margin=standard]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D The distance between the formula and the number is only
+%D applied when the formula is left or right aligned.
+%D
+%D \startbuffer
+%D \setupformulas[align=left,distance=2em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+
+\protect \endinput
+
+% \placeformula \startformula[-] \startmatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopmatrix \stopformula
+
+% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}]
+
+% \placeformula \startformula[-] \startbordermatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopbordermatrix \stopformula
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv
new file mode 100644
index 00000000000..28aad8adadf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv
@@ -0,0 +1,462 @@
+%D \module
+%D [ file=math-arr,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Arrows,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We keep this file around as reference of his things were done in the
+%D past. You can still load this module but it has been replaced by more
+%D modern code.
+
+\writestatus{loading}{ConTeXt Math Macros / Arrows}
+
+\unprotect
+
+%D These will be generalized! Is it still needed in \MKIV? Also, we need to
+%D to it using regular opentype math!
+
+% Plain code:
+%
+% \def\rightarrowfill
+% {$%
+% \mathsurround\zeropoint
+% \smash-%
+% \mkern-7mu%
+% \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+% \mkern-7mu%
+% \mathord\rightarrow
+% $}
+%
+% \def\leftarrowfill % brrr no longer in luatex
+% {$%
+% \mathsurround\zeropoint
+% \mathord\leftarrow
+% \mkern-7mu%
+% \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+% \mkern-7mu
+% \smash-%
+% $}
+
+%D Extensible arrows are arrows that change their length according to the width of
+%D the text to be placed above and below the arrow.
+%D
+%D Since we need to define a lot of arrows, we first define some helper macros. The
+%D basic idea is to measure the width of the box to be placed above and below the
+%D arrow, and make the \quote {body} of the arrow as long as the bigger of the two
+%D widths.
+
+\installcorenamespace{matharrowsettings}
+
+\def\m_math_arrows_factor{1}
+\def\m_math_arrows_extra {0}
+
+\setvalue{\??matharrowsettings\v!none }{\def\m_math_arrows_factor{0}}
+\setvalue{\??matharrowsettings\v!small }{\def\m_math_arrows_extra{10}}
+\setvalue{\??matharrowsettings\v!medium }{\def\m_math_arrows_extra{15}}
+\setvalue{\??matharrowsettings\v!big }{\def\m_math_arrows_extra{20}}
+\setvalue{\??matharrowsettings\v!normal }{}
+\setvalue{\??matharrowsettings }{}
+\setvalue{\??matharrowsettings\s!unknown}{\doifelsenumber\p_math_spacing{\let\m_math_arrows_extra\p_math_spacing}\donothing}
+
+\def\math_arrows_construct#1#2#3#4#5% hm, looks like we do a double mathrel (a bit cleaned up .. needs checking)
+ {\begingroup
+ \def\m_math_arrows_factor{1}%
+ \def\m_math_arrows_extra {0}%
+ \edef\p_math_spacing{#1}%
+ \csname\??matharrowsettings
+ \ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi
+ \endcsname
+ \mathsurround\zeropoint
+ \muskip0=\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
+ \fi
+ \ifdim\wd4>\dimen0
+ \dimen0\wd4\relax
+ \fi
+ \ifdim\wd4=\dimen0\else
+ \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \fi
+ \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}%
+ \endgroup}
+
+\let\math_arrows_construct_single\math_arrows_construct
+
+%D There are some arrows which are created by stacking two arrows. The next
+%D macro helps in defining such \quotation{double arrows}.
+
+% weird, we get a shift with the double ... but will become core luatex anyway
+%
+% \startchemicalformula
+% \chemical{S}
+% \chemical{+}
+% \chemical{O_2}
+% \chemical{EQUILIBRIUM}{boven}{onder}
+% \chemical{SO_2}
+% \stopchemicalformula
+
+\def\math_arrows_construct_double#1#2#3#4#5#6#7% opt l r sp rs top bot
+ {\mathrel
+ {\scratchdimen.32\exheight\relax % was .22, todo: make configurable
+ \setbox\scratchboxone\hbox{\normalstartimath\math_arrows_construct{#1}{#2}{#4}{\phantom{#6}}{#7}\normalstopimath}%
+ \setbox\scratchboxtwo\hbox{\normalstartimath\math_arrows_construct{#1}{#3}{#5}{#6}{\phantom{#7}}\normalstopimath}%
+ \raise\scratchdimen\box\scratchboxone
+ \kern-\wd\scratchboxtwo
+ \lower\scratchdimen\box\scratchboxtwo}}
+
+%D \macros{definematharrow}
+%D
+%D Macro for defining new arrows. We can define two types of arrows|<|single arrows
+%D and double arrows. Single arrows are defined as
+%D
+%D \starttyping
+%D \definematharrow [xrightarrow] [0359] [\rightarrowfill]
+%D \stoptyping
+%D
+%D The first argument is the name of the arrow (\tex {xrightarrow} in this case.) The
+%D second argument consists of a set of 4 numbers and specify the spacing correction
+%D in math units~\type {mu}. These numbers define:
+%D
+%D \startlines
+%D 1st number: arrow||tip correction
+%D 2nd number: arrow||tip correction
+%D 3rd number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D 4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D \stoplines
+%D
+%D The third argument is the name of the extensible fill. The third argument is optional
+%D when the arrow is redefined later (this is useful for font specific tweaking of the
+%D skips.) For example,
+%D
+%D \startbuffer
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][0000]
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][55{50}{50}]
+%D \math{\xrightarrow{above}}
+%D \stopbuffer
+%D \typebuffer gives {\getbuffer}
+%D
+%D The double arrows are defined as follows
+%D
+%D \starttyping
+%D \definematharrow [xrightleftharpoons] [3095,0359]
+%D [\rightharpoonupfill,\leftharpoondownfill]
+%D \stoptyping
+%D
+%D The second and the third set of arguments consist of comma separated values. The
+%D first element of the second argument (\type {3095}) corresponds to the spacing
+%D correction of top arrow fill (\tex{rightarrowupfill}). Similarly, \type {0359}
+%D corresponds to bottom arrow fill \tex {leftharpoondownfill}). Stacking them on
+%D top of each other we get $\xrightleftharpoons [big] {above} {below}$. The
+%D following math arrows are defined
+%D
+%D \placetable[none]{}{\starttable[|l|m|]
+%D \NC \tex{xrightarrow} \NC \xrightarrow [big] \NC \NR
+%D \NC \tex{xleftarrow} \NC \xleftarrow [big] \NC \NR
+%D \NC \tex{xequal} \NC \xequal [big] \NC \NR
+%D \NC \tex{xRightarrow} \NC \xRightarrow [big] \NC \NR
+%D \NC \tex{xLeftarrow} \NC \xLeftarrow [big] \NC \NR
+%D \NC \tex{xLeftrightarrow} \NC \xLeftrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightarrow} \NC \xleftrightarrow [big] \NC \NR
+%D \NC \tex{xmapsto} \NC \xmapsto [big] \NC \NR
+%D \NC \tex{xtwoheadrightarrow} \NC \xtwoheadrightarrow [big] \NC \NR
+%D \NC \tex{xtwoheadleftarrow} \NC \xtwoheadleftarrow [big] \NC \NR
+%D \NC \tex{xrightharpoondown} \NC \xrightharpoondown [big] \NC \NR
+%D \NC \tex{xrightharpoonup} \NC \xrightharpoonup [big] \NC \NR
+%D \NC \tex{xleftharpoondown} \NC \xleftharpoondown [big] \NC \NR
+%D \NC \tex{xleftharpoonup} \NC \xleftharpoonup [big] \NC \NR
+%D \NC \tex{xhookleftarrow} \NC \xhookleftarrow [big] \NC \NR
+%D \NC \tex{xhookrightarrow} \NC \xhookrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightharpoons} \NC \xleftrightharpoons [big] \NC \NR
+%D \NC \tex{xrightleftharpoons} \NC \xrightleftharpoons [big] \NC \NR
+%D \stoptable}
+
+%D If needed this can be optimized (i.e. we can preexpand using \type
+%D {\docheckedpair}).
+
+\unexpanded\def\definematharrow
+ {\doquadrupleargument\math_arrows_define}
+
+\def\math_arrows_define[#1][#2][#3][#4]% name type[none|both] template command
+ {\iffourthargument
+ \executeifdefined{math_arrows_define_#2}\gobblethreearguments{#1}{#3}{#4}%
+ \else\ifthirdargument
+ \math_arrows_define_both{#1}{#2}{#3}%
+ \else\ifsecondargument
+ \math_arrows_define_both_again{#1}{#2}{#3}%
+ \fi\fi\fi}
+
+\def\math_arrows_define_both_again#1#2#3% real dirty, this overload!
+ {\ifcsname#1\endcsname
+ \pushmacro\math_arrows_do
+ \def\math_arrows_do[##1][##2]{\setuvalue{#1}{\math_arrows_do[#2][##2]}}%
+ \csname#1\endcsname
+ \popmacro\math_arrows_do
+ \fi}
+
+\def\math_arrows_define_both#1#2#3%
+ {\setuvalue{#1}{\math_arrows_do[#2][#3]}}
+
+\unexpanded\def\math_arrows_do
+ {\doquadrupleempty\math_arrows_handle}
+
+\def\math_arrows_handle[#1][#2][#3][#4]% #3 == optional arg .. \empty can be just 'empty' [#4] gobbles spaces
+ {\def\math_arrows_handle_indeed{\math_arrows_handle_finalize[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
+ \dodoublegroupempty\math_arrows_handle_indeed}
+
+\def\math_arrows_handle_finalize[#1,#2,#3][#4,#5,#6][#7]#8#9% [#7] is the optional arg
+ {\edef\!!stringa{#2}%
+ \ifx\!!stringa\empty
+ \ifsecondargument
+ \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{#8}{#9}}%
+ \else
+ \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{}{#8}}%
+ \fi
+ \else
+ \ifsecondargument
+ \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
+ \else
+ \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{}{#8}}%
+ \fi
+ \fi}
+
+% Adapted from amsmath.
+
+%D \macros{mtharrowfill,defaultmtharrowfill}
+%D
+%D To extend the arrows we need to define a \quotation {math arrow fill}. This
+%D command takes 8 arguments: the first four correspond the second argument of
+%D \tex {definematharrow} explained above. The other three specify the tail,
+%D body and head of the arrow. The last argument specifies the math-mode in which
+%D the arrow is drawn. \tex {defaultmtharrowfill} has values tweaked to match
+%D Latin Modern fonts. For fonts that are significantly different (e.g. cows) a
+%D different set of values need to be determined.
+
+\def\mtharrowfill#1#2#3#4#5#6#7#8%
+ {\normalstartimath
+ \mathsurround\zeropoint
+ \thickmuskip\zeromuskip\medmuskip\thickmuskip\thinmuskip\thickmuskip
+ \relax#8#5%
+ \mkern-#1\onemuskip
+ \cleaders\hbox{\normalstartimath#8\mkern-#2\onemuskip#6\mkern-#3\onemuskip\normalstopimath}\hfill
+ \mkern-#4\onemuskip#7%
+ \normalstopimath}
+
+\def\defaultmtharrowfill{\mtharrowfill 7227}
+
+%D We now define some arrow fills that will be used for defining the arrows. Plain
+%D \TEX\ already defines \tex {leftarrowfill} and \tex {rightarrowfill}. The \tex
+%D {defaultmtharrowfill} command defines an arrowfill that takes an argument (so
+%D that it can also be used with over and under arrows). However the Plain \TEX\
+%D definitions of \tex {leftarrowfill} and \tex {rightarrowfill} do not take this
+%D extra argument. To be backward compatible with Plain \TEX, we define two
+%D arrowfills: \tex {specrightarrowfill} which takes an extra argument, and \tex
+%D {rightarrowfill} which does not.
+
+\unexpanded\def\specrightarrowfill {\defaultmtharrowfill \relbar \relbar \rightarrow}
+\unexpanded\def\specleftarrowfill {\defaultmtharrowfill \leftarrow \relbar \relbar}
+
+\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle}
+\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle}
+
+\unexpanded\def\equalfill {\defaultmtharrowfill \Relbar \Relbar \Relbar}
+\unexpanded\def\Rightarrowfill {\defaultmtharrowfill \Relbar \Relbar \Rightarrow}
+\unexpanded\def\Leftarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Relbar}
+\unexpanded\def\Leftrightarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Rightarrow}
+\unexpanded\def\leftrightarrowfill {\defaultmtharrowfill \leftarrow \relbar \rightarrow}
+\unexpanded\def\mapstofill {\defaultmtharrowfill{\mapstochar\relbar} \relbar \rightarrow}
+\unexpanded\def\twoheadrightarrowfill{\defaultmtharrowfill \relbar \relbar \twoheadrightarrow}
+\unexpanded\def\twoheadleftarrowfill {\defaultmtharrowfill \twoheadleftarrow \relbar \relbar}
+\unexpanded\def\rightharpoondownfill {\defaultmtharrowfill \relbar \relbar \rightharpoondown}
+\unexpanded\def\rightharpoonupfill {\defaultmtharrowfill \relbar \relbar \rightharpoonup}
+\unexpanded\def\leftharpoondownfill {\defaultmtharrowfill \leftharpoondown \relbar \relbar}
+\unexpanded\def\leftharpoonupfill {\defaultmtharrowfill \leftharpoonup \relbar \relbar}
+\unexpanded\def\hookleftfill {\defaultmtharrowfill \leftarrow \relbar{\relbar\joinrel\rhook}}
+\unexpanded\def\hookrightfill {\defaultmtharrowfill{\lhook\joinrel\relbar}\relbar \rightarrow}
+\unexpanded\def\relfill {\defaultmtharrowfill \relbar \relbar \relbar}
+
+\unexpanded\def\triplerelbar {\mathrel\equiv}
+\unexpanded\def\triplerelfill{\defaultmtharrowfill\triplerelbar\triplerelbar\triplerelbar}
+
+\unexpanded\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}}
+\unexpanded\def\doublebond{{\xequal}}
+\unexpanded\def\triplebond{{\xtriplerel}}
+
+%D A bit or arrow juggling:
+%D
+%D \startbuffer
+%D \hbox to \hsize{\rightoverleftarrowfill}
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\unexpanded\def\rightoverleftarrowfill
+ {\specrightoverleftarrowfill}
+
+\unexpanded\def\specrightoverleftarrowfill
+ {\defaultmtharrowfill
+ \ctxdoublearrowfillleftend
+ \ctxdoublearrowfillmiddlepart
+ \ctxdoublearrowfillrightend
+ \textstyle}
+
+%D Now we define most commonly used arrows. These include arrows defined in \filename
+%D {amsmath.sty}, \filename {extarrows.sty}, \filename {extpfel.sty} and \filename
+%D {mathtools.sty} packages for \LATEX\ (plus a few more).
+
+\definematharrow [xrightarrow] [0359] [\specrightarrowfill]
+\definematharrow [xleftarrow] [3095] [\specleftarrowfill]
+\definematharrow [xequal] [0099] [\equalfill]
+\definematharrow [xRightarrow] [0359] [\Rightarrowfill]
+\definematharrow [xLeftarrow] [3095] [\Leftarrowfill]
+\definematharrow [xLeftrightarrow] [0099] [\Leftrightarrowfill]
+\definematharrow [xleftrightarrow] [0099] [\leftrightarrowfill]
+\definematharrow [xmapsto] [3599] [\mapstofill]
+\definematharrow [xtwoheadrightarrow] [5009] [\twoheadrightarrowfill]
+\definematharrow [xtwoheadleftarrow] [0590] [\twoheadleftarrowfill]
+\definematharrow [xrightharpoondown] [0359] [\rightharpoondownfill]
+\definematharrow [xrightharpoonup] [0359] [\rightharpoonupfill]
+\definematharrow [xleftharpoondown] [3095] [\leftharpoondownfill]
+\definematharrow [xleftharpoonup] [3095] [\leftharpoonupfill]
+\definematharrow [xhookleftarrow] [3095] [\hookleftfill]
+\definematharrow [xhookrightarrow] [0395] [\hookrightfill]
+\definematharrow [xrel] [0099] [\relfill]
+\definematharrow [xtriplerel] [0099] [\triplerelfill]
+\definematharrow [xrightoverleftarrow] [0359,3095] [\specrightarrowfill,\specleftarrowfill]
+\definematharrow [xleftrightharpoons] [3399,3399] [\leftharpoonupfill,\rightharpoondownfill]
+\definematharrow [xrightleftharpoons] [3399,3399] [\rightharpoonupfill,\leftharpoondownfill]
+
+%D These arrows can be used as follows:
+%D
+%D \startbuffer
+%D \startformula \xrightarrow{stuff on top}\stopformula
+%D \startformula \xrightarrow{}{stuff on top}\stopformula
+%D \startformula \xrightarrow{stuff below}{}\stopformula
+%D \startformula \xrightarrow{stuff below}{stuff on top}\stopformula
+%D
+%D \startformula \xleftarrow [none]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [small]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [medium]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [big]{stuff below}{stuff on top}\stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+%D \macros{definemathoverarrow,defineunderarrow}
+%D
+%D These macros for define math-overarrows are adapted from \filename {amsmath.sty}
+
+\unexpanded\def\definemathoverarrow
+ {\dotripleargument\math_arrows_define_over}
+
+\def\math_arrows_define_over[#1][#2][#3]%
+ {\ifthirdargument
+ \setuvalue{#1}{\math_arrows_over_handle[#2][#3]}%
+ \else
+ \setuvalue{#1}{\math_arrows_over_handle[\zeropoint][#2]}%
+ \fi}
+
+\def\math_arrows_over_handle[#1][#2]%
+ {\mathpalette{\math_arrows_over_handle_indeed{#1}{#2}}}
+
+%D Note: \filename {math-pln.tex} has \type {\kern-\onepoint} and \filename
+%D {amsmath.sty} does not. We keep the kern amount configurable. This is useful
+%D for harpoons.
+
+\def\math_arrows_over_handle_indeed#1#2#3#4%
+ {\vbox{\ialign{%
+ \alignmark\alignmark
+ \crcr
+ #2#3%
+ \crcr
+ \noalign{\kern#1\nointerlineskip}%
+ \normalstartimath
+ \mathsurround\zeropoint\hfil#3#4\hfil
+ \normalstopimath
+ \crcr
+ }}}
+
+%D Now the under arrows
+
+\unexpanded\def\definemathunderarrow
+ {\dotripleargument\math_arrows_define_under}
+
+%D For underarrows the default kern is 0.3ex
+
+\def\math_arrows_define_under[#1][#2][#3]%
+ {\ifthirdargument
+ \setuvalue{#1}{\math_arrows_under_handle[#2][#3]}%
+ \else
+ \setuvalue{#1}{\math_arrows_under_handle[0.3ex][#2]}%
+ \fi}
+
+\def\math_arrows_under_handle[#1][#2]%
+ {\mathpalette{\math_arrows_under_handle_indeed{#1}{#2}}}
+
+\def\math_arrows_under_handle_indeed#1#2#3#4%
+ {\vtop{\ialign{%
+ \alignmark\alignmark
+ \crcr
+ \normalstartimath\mathsurround\zeropoint\hfil#3#4\hfil\normalstopimath
+ \crcr
+ \noalign{\nointerlineskip\kern#1}%
+ #2#3%
+ \crcr
+ }}}
+
+%D Now we define the arrows
+
+\definemathoverarrow [overleftarrow] [\specleftarrowfill]
+\definemathoverarrow [overrightarrow] [\specrightarrowfill]
+\definemathoverarrow [overleftrightarrow] [\leftrightarrowfill]
+\definemathoverarrow [overtwoheadrightarrow] [\twoheadrightarrowfill]
+\definemathoverarrow [overtwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathoverarrow [overrightharpoondown] [1pt] [\rightharpoondownfill]
+\definemathoverarrow [overrightharpoonup] [\rightharpoonupfill]
+\definemathoverarrow [overleftharpoondown] [1pt] [\leftharpoondownfill]
+\definemathoverarrow [overleftharpoonup] [\leftharpoonupfill]
+
+\definemathunderarrow [underleftarrow] [\specleftarrowfill]
+\definemathunderarrow [underrightarrow] [\specrightarrowfill]
+\definemathunderarrow [underleftrightarrow] [\leftrightarrowfill]
+\definemathunderarrow [undertwoheadrightarrow][\twoheadrightarrowfill]
+\definemathunderarrow [undertwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathunderarrow [underrightharpoondown] [\rightharpoondownfill]
+\definemathunderarrow [underrightharpoonup] [\rightharpoonupfill]
+\definemathunderarrow [underleftharpoondown] [\leftharpoondownfill]
+\definemathunderarrow [underleftharpoonup] [\leftharpoonupfill]
+
+%D These can be used as follows:
+%D
+%D \startbuffer
+%D $\overleftarrow{A}$ $\overleftarrow{ABC}$
+%D $a_{\overleftarrow{A}}$ $b_{\overleftarrow{ABC}}$
+%D \stopbuffer
+%D \typebuffer which gives \getbuffer
+
+%D TODO: Possibly have a single arrow command define all the arrows.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-def.mkiv
new file mode 100644
index 00000000000..a8af5af5cec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-def.mkiv
@@ -0,0 +1,158 @@
+%D \module
+%D [ file=math-tex,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Definitions,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Definitions}
+
+\unprotect
+
+%D Some day this will be done at the lua end.
+
+\startluacode
+ mathematics.define(\number\defaultmathfamily)
+ -- mathematics.xml.registerentities()
+\stopluacode
+
+\activatemathcharacters
+
+%D The \mfunction macro is an alternative for \hbox with a controlable font
+%D switch.
+
+\definemathcommand [arccos] [nolop] {\mfunctionlabeltext{arccos}}
+\definemathcommand [arcsin] [nolop] {\mfunctionlabeltext{arcsin}}
+\definemathcommand [arctan] [nolop] {\mfunctionlabeltext{arctan}}
+\definemathcommand [acos] [nolop] {\mfunctionlabeltext{acos}}
+\definemathcommand [asin] [nolop] {\mfunctionlabeltext{asin}}
+\definemathcommand [atan] [nolop] {\mfunctionlabeltext{atan}}
+\definemathcommand [arg] [nolop] {\mfunctionlabeltext{arg}}
+\definemathcommand [cosh] [nolop] {\mfunctionlabeltext{cosh}}
+\definemathcommand [cos] [nolop] {\mfunctionlabeltext{cos}}
+\definemathcommand [coth] [nolop] {\mfunctionlabeltext{coth}}
+\definemathcommand [cot] [nolop] {\mfunctionlabeltext{cot}}
+\definemathcommand [csc] [nolop] {\mfunctionlabeltext{csc}}
+\definemathcommand [deg] [nolop] {\mfunctionlabeltext{deg}}
+\definemathcommand [det] [limop] {\mfunctionlabeltext{det}}
+\definemathcommand [dim] [nolop] {\mfunctionlabeltext{dim}}
+\definemathcommand [exp] [nolop] {\mfunctionlabeltext{exp}}
+\definemathcommand [gcd] [limop] {\mfunctionlabeltext{gcd}}
+\definemathcommand [hom] [nolop] {\mfunctionlabeltext{hom}}
+\definemathcommand [inf] [limop] {\mfunctionlabeltext{inf}}
+\definemathcommand [injlim] [limop] {\mfunctionlabeltext{injlim}}
+\definemathcommand [ker] [nolop] {\mfunctionlabeltext{ker}}
+\definemathcommand [lg] [nolop] {\mfunctionlabeltext{lg}}
+\definemathcommand [liminf] [limop] {\mfunctionlabeltext{liminf}}
+\definemathcommand [limsup] [limop] {\mfunctionlabeltext{limsup}}
+\definemathcommand [lim] [limop] {\mfunctionlabeltext{lim}}
+\definemathcommand [ln] [nolop] {\mfunctionlabeltext{ln}}
+\definemathcommand [log] [nolop] {\mfunctionlabeltext{log}}
+\definemathcommand [median] [limop] {\mfunctionlabeltext{median}}
+\definemathcommand [max] [limop] {\mfunctionlabeltext{max}}
+\definemathcommand [min] [limop] {\mfunctionlabeltext{min}}
+\definemathcommand [mod] [limop] {\mfunctionlabeltext{mod}}
+%definemathcommand [div] [limop] {\mfunctionlabeltext{div}} % overloads \div symbol
+\definemathcommand [projlim] [limop] {\mfunctionlabeltext{projlim}}
+\definemathcommand [Pr] [limop] {\mfunctionlabeltext{Pr}}
+\definemathcommand [sec] [nolop] {\mfunctionlabeltext{sec}}
+\definemathcommand [sinh] [nolop] {\mfunctionlabeltext{sinh}}
+\definemathcommand [sin] [nolop] {\mfunctionlabeltext{sin}}
+\definemathcommand [sup] [limop] {\mfunctionlabeltext{sup}}
+\definemathcommand [tanh] [nolop] {\mfunctionlabeltext{tanh}}
+\definemathcommand [tan] [nolop] {\mfunctionlabeltext{tan}}
+\definemathcommand [diff] {\mfunctionlabeltext{diff}}
+
+\let\normalmatharg\arg % todo: maybe automatically
+
+%D This needs checking:
+
+\unexpanded\def\setoperatorlimits#1#2% operator limits
+ {\savenormalmeaning{#1}%
+ \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}}
+
+\setoperatorlimits \int \intlimits
+\setoperatorlimits \iint \intlimits
+\setoperatorlimits \iiint \intlimits
+\setoperatorlimits \oint \intlimits
+\setoperatorlimits \oiint \intlimits
+\setoperatorlimits \oiiint \intlimits
+\setoperatorlimits \intclockwise \intlimits
+\setoperatorlimits \ointclockwise \intlimits
+\setoperatorlimits \ointctrclockwise \intlimits
+
+%D \macros
+%D {centercolon, colonminus, minuscolon, colonequals, equalscolon,
+%D colonapprox, approxcolon, colonsim, simcolon, coloncolon,
+%D coloncolonminus, minuscoloncolon, coloncolonequals,
+%D equalscoloncolon, coloncolonapprox, approxcoloncolon,
+%D colonsim, simcoloncolon}
+%D
+%D The following colon related definitions are provided by Aditya
+%D Mahajan who derived them from \type {mathtools.sty} and \type
+%D {colonequals.sty}. This will be redone as part of the overhaul
+%D and font updates.
+%D
+%D In $a := b$ the colon is not vertically centered with the equal
+%D to. Also the distance between colon and equal to is a bit large.
+%D So, we define a vertically centered colon \tex {centercolon} and
+%D a few macros for colon and double colon relation symbols.
+%D
+%D \startlines
+%D \formula {A \centercolon B}
+%D \formula {A \colonminus B}
+%D \formula {A \minuscolon B}
+%D \formula {A \colonequals B}
+%D \formula {A \equalscolon B}
+%D \formula {A \colonapprox B}
+%D \formula {A \approxcolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcolon B}
+%D \formula {A \coloncolon B}
+%D \formula {A \coloncolonminus B}
+%D \formula {A \minuscoloncolon B}
+%D \formula {A \coloncolonequals B}
+%D \formula {A \equalscoloncolon B}
+%D \formula {A \coloncolonapprox B}
+%D \formula {A \approxcoloncolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcoloncolon B}
+%D \stoplines
+%D
+%D The next macros take care of the space between the colon and the
+%D relation symbol.
+
+\definemathcommand [colonsep] {\mkern-1.2mu}
+\definemathcommand [doublecolonsep] {\mkern-0.9mu}
+
+\definemathcommand [centercolon] [rel] {\mathstylevcenteredhbox\colon}
+\definemathcommand [colonminus] [rel] {\centercolon\colonsep\mathrel{-}}
+\definemathcommand [minuscolon] [rel] {\mathrel{-}\colonsep\centercolon} % native char
+\definemathcommand [colonequals] [rel] {\centercolon\colonsep=} % native char
+\definemathcommand [equalscolon] [rel] {=\centercolon\colonsep} % native char
+\definemathcommand [colonapprox] [rel] {\centercolon\colonsep\approx}
+\definemathcommand [approxcolon] [rel] {\approx\centercolon\colonsep}
+\definemathcommand [colonsim] [rel] {\centercolon\colonsep\sim}
+\definemathcommand [simcolon] [rel] {\sim\centercolon\colonsep}
+
+\definemathcommand [coloncolon] [rel] {\centercolon\doublecolonsep\centercolon}
+\definemathcommand [coloncolonminus] [rel] {\coloncolon\colonsep\mathrel{-}}
+\definemathcommand [minuscoloncolon] [rel] {\mathrel{-}\colonsep\coloncolon}
+\definemathcommand [coloncolonequals] [rel] {\coloncolon\colonsep=} % native char
+\definemathcommand [equalscoloncolon] [rel] {=\coloncolon\colonsep}
+\definemathcommand [coloncolonapprox] [rel] {\coloncolon\colonsep\approx}
+\definemathcommand [approxcoloncolon] [rel] {\approx\coloncolon\colonsep}
+\definemathcommand [coloncolonsim] [rel] {\coloncolon\colonsep\sim}
+\definemathcommand [simcoloncolon] [rel] {\sim\coloncolon\colonsep}
+
+% \appendtoks
+% \def\over{\primitive\over}%
+% \to \everymathematics
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-del.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-del.mkiv
new file mode 100644
index 00000000000..be78b581f4f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-del.mkiv
@@ -0,0 +1,121 @@
+%D \module
+%D [ file=math-del,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Delimiters,
+%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 / Delimiters}
+
+\unprotect
+
+%D Old code that will be redone:
+%D
+%D \macros
+%D {checkdelimiters, fakeleftdelimiter, fakerightdelimiter}
+%D
+%D Handy for non matching situations (as with mathml):
+%D
+%D \starttyping
+%D \checkdelimiters{... bla bla ...}
+%D \fakeleftdelimiter
+%D ... bla bla ...
+%D \fakerightdelimiter
+%D \stoptyping
+
+% Actually we can do better now with lua hacks.
+
+\newcount\c_math_delimiter_nesting
+
+\def\leftfakedelimiter {\advance\c_math_delimiter_nesting\minusone\gobbleoneargument}
+\def\rightfakedelimiter{\advance\c_math_delimiter_nesting\plusone \gobbleoneargument}
+
+\def\checkdelimiters#1%
+ {\c_math_delimiter_nesting\zerocount
+ \setbox\scratchbox\hbox\bgroup
+ \let\left \leftfakedelimiter
+ \let\right\rightfakedelimiter
+ \normalstartimath#1\expandafter\normalstopimath\expandafter
+ \egroup
+ \expandafter\c_math_delimiter_nesting\the\c_math_delimiter_nesting\relax}
+
+\def\fakeleftdelimiter {\ifnum\c_math_delimiter_nesting>\zerocount\left .\fi}
+\def\fakerightdelimiter{\ifnum\c_math_delimiter_nesting<\zerocount\right.\fi}
+
+%D The following macros are used in the MathML interpreter, so
+%D there is a good change of them never being documented for
+%D other usage.
+
+\let\normalordelimiter\secondoftwoarguments
+\let\normalorfiller \firstoftwoarguments
+
+\unexpanded\def\enabledelimiter {\let\normalordelimiter\secondoftwoarguments}
+\unexpanded\def\disabledelimiter{\let\normalordelimiter\firstoftwoarguments}
+
+\unexpanded\def\enablefiller {\let\normalorfiller\secondoftwoarguments}
+\unexpanded\def\disablefiller {\let\normalorfiller\firstoftwoarguments}
+
+% \def\mathopnolimits#1{\mathop{\mr\mathrm#1}\nolimits} % was \rm, which follows text fonts (used in mml parser)
+% \def\mathopdolimits#1{\mathop{\mr\mathrm#1}} % was \rm, which follows text fonts (used in mml parser)
+
+\def\mathopnolimits#1{\mathop{\mathrm#1}\nolimits} % was \rm, which follows text fonts (used in mml parser, check!)
+\def\mathopdolimits#1{\mathop{\mathrm#1}} % was \rm, which follows text fonts (used in mml parser, check!)
+
+% A new experiment:
+
+\installcorenamespace {mathextensible}
+
+\installcommandhandler \??mathextensible {mathextensible} \??mathextensible
+
+\let\setupmathextensibles\setupmathextensible
+
+\setupmathextensibles
+ [\c!symbol=0,
+ \c!command=\v!yes,
+ \c!factor=1.5,
+ \c!height=\exheight,
+ \c!depth=\exheight]
+
+\appendtoks
+ \edef\p_command{\mathextensibleparameter\c!command}%
+ \ifx\p_command\v!yes
+ \setuevalue\currentmathextensible{\math_fenced_extensible[\currentmathextensible]}%
+ \fi
+\to \everydefinemathextensible
+
+\unexpanded\def\math_fenced_extensible
+ {\dodoubleempty\math_fenced_extensible_indeed}
+
+\unexpanded\def\math_fenced_extensible_indeed[#1][#2]%
+ {\mathop{%
+ \edef\currentmathextensible{#1}%
+ \edef\p_factor{\mathextensibleparameter\c!factor}%
+ \ifsecondargument
+ \doifassignmentelse{#2}
+ {\setupcurrentmathextensible[#2]}%
+ {\edef\p_factor{#2}}%
+ \fi
+ \Uvextensible
+ axis % can be an option
+ height \p_factor\dimexpr\mathextensibleparameter\c!height\relax
+ depth \p_factor\dimexpr\mathextensibleparameter\c!depth\relax
+ \Udelimiter\zerocount\zerocount\mathextensibleparameter\c!symbol
+ \relax}%
+ }
+
+\let\mathextensible\math_fenced_extensible
+
+% \startformula
+% \integral[factor=3] \frac{1}{2}
+% \integral[5] \frac{1}{2}
+% \stopformula
+
+\definemathextensible[integral][\c!symbol="222B]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua b/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua
new file mode 100644
index 00000000000..b5241cb5a66
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua
@@ -0,0 +1,246 @@
+if not modules then modules = { } end modules ['math-dim'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Beware: only Taco and Ulrik really understands in depth what these dimensions
+-- do so if you run into problems ask on the context list.
+
+-- The radical_rule value is also used as a trigger. In luatex the accent
+-- placement happens either the opentype way (using top_accent cum suis) or the
+-- traditional way. In order to determine what method to use the \Umathradicalrule
+-- setting is consulted to determine what method to use. This is more efficient
+-- than analyzing the (potentially spread over multiple families) situation. For
+-- this reason we need to set the radical_rule here. It used to be "<unset>" in
+-- which case the engine takes the rulethickness. In c-speak:
+--
+-- int compat_mode = (radical_rule(cur_style) == undefined_math_parameter) ;
+
+local abs, next = math.abs, next
+
+local defaults = {
+ axis = { default = { "AxisHeight", "axis_height" }, },
+ accent_base_height = { default = { "AccentBaseHeight", "x_height" }, },
+ fraction_del_size = { default = { "FractionDelimiterSize", "delim2" },
+ cramped_display_style = { "FractionDelimiterDisplayStyleSize", "delim1" },
+ display_style = { "FractionDelimiterDisplayStyleSize", "delim1" }, },
+ fraction_denom_down = { default = { "FractionDenominatorShiftDown", "denom2" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" },
+ display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" }, },
+ fraction_denom_vgap = { default = { "FractionDenominatorGapMin", "default_rule_thickness" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
+ display_style = { "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" }, },
+ fraction_num_up = { default = { "FractionNumeratorShiftUp", "num2" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" },
+ display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" }, },
+ fraction_num_vgap = { default = { "FractionNumeratorGapMin", "default_rule_thickness" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
+ display_style = { "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" }, },
+ skewed_fraction_hgap = { default = { "SkewedFractionHorizontalGap", "math_quad/2" },
+ cramped_display_style = { "SkewedFractionHorizontalGap", "math_quad/2" },
+ display_style = { "SkewedFractionHorizontalGap", "math_quad/2" }, },
+ skewed_fraction_vgap = { default = { "SkewedFractionVerticalGap", "x_height" },
+ cramped_display_style = { "SkewedFractionVerticalGap", "x_height" },
+ display_style = { "SkewedFractionVerticalGap", "x_height" }, },
+ fraction_rule = { default = { "FractionRuleThickness", "default_rule_thickness" }, },
+ limit_above_bgap = { default = { "UpperLimitBaselineRiseMin", "big_op_spacing3" }, },
+ limit_above_vgap = { default = { "UpperLimitGapMin", "big_op_spacing1" }, },
+ limit_above_kern = { default = { "0", "big_op_spacing5" }, },
+ limit_below_bgap = { default = { "LowerLimitBaselineDropMin", "big_op_spacing4" }, },
+ limit_below_vgap = { default = { "LowerLimitGapMin", "big_op_spacing2" }, },
+ limit_below_kern = { default = { "0", "big_op_spacing5" }, },
+ math_operator_size = { default = { "DisplayOperatorMinHeight", "math_x_height*3" }, }, -- 2
+ overbar_kern = { default = { "OverbarExtraAscender", "default_rule_thickness" }, },
+ overbar_rule = { default = { "OverbarRuleThickness", "default_rule_thickness" }, },
+ overbar_vgap = { default = { "OverbarVerticalGap", "3*default_rule_thickness" }, },
+ quad = { default = { "font_size(f)", "math_quad" }, },
+ radical_kern = { default = { "RadicalExtraAscender", "default_rule_thickness" }, },
+ radical_rule = { default = { "RadicalRuleThickness", "default_rule_thickness" }, },
+ -- default = { "surd_height(f)", "default_rule_thickness" },
+ radical_vgap = { default = { "RadicalVerticalGap", "default_rule_thickness+(abs(default_rule_thickness)/4)" },
+ display_style = { "RadicalDisplayStyleVerticalGap", "default_rule_thickness+(abs(math_x_height)/4)" }, },
+ space_after_script = { default = { "SpaceAfterScript", "script_space" }, },
+ stack_denom_down = { default = { "StackBottomShiftDown", "denom2" },
+ cramped_display_style = { "StackBottomDisplayStyleShiftDown", "denom1" },
+ display_style = { "StackBottomDisplayStyleShiftDown", "denom1" }, },
+ stack_num_up = { default = { "StackTopShiftUp", "num3" },
+ cramped_display_style = { "StackTopDisplayStyleShiftUp", "num1" },
+ display_style = { "StackTopDisplayStyleShiftUp", "num1" }, },
+ stack_vgap = { default = { "StackGapMin", "3*default_rule_thickness" },
+ cramped_display_style = { "StackDisplayStyleGapMin", "7*default_rule_thickness" },
+ display_style = { "StackDisplayStyleGapMin", "7*default_rule_thickness" }, },
+ sub_shift_down = { default = { "SubscriptShiftDown", "sub1" }, },
+ sub_shift_drop = { default = { "SubscriptBaselineDropMin", "sub_drop" }, },
+ sub_sup_shift_down = { default = { "SubscriptShiftDown", "sub2" }, },
+ sub_top_max = { default = { "SubscriptTopMax", "abs(math_x_height*4)/5" }, },
+ subsup_vgap = { default = { "SubSuperscriptGapMin", "4*default_rule_thickness" }, },
+ sup_bottom_min = { default = { "SuperscriptBottomMin", "abs(math_x_height)/4" }, },
+ sup_shift_drop = { default = { "SuperscriptBaselineDropMax", "sup_drop" }, },
+ sup_shift_up = { cramped_display_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_text_style = { "SuperscriptShiftUpCramped", "sup3" },
+ display_style = { "SuperscriptShiftUp", "sup1" },
+ script_script_style = { "SuperscriptShiftUp", "sup2" },
+ script_style = { "SuperscriptShiftUp", "sup2" },
+ text_style = { "SuperscriptShiftUp", "sup2" }, },
+ sup_sub_bottom_max = { default = { "SuperscriptBottomMaxWithSubscript", "abs(math_x_height*4)/5" }, },
+ underbar_kern = { default = { "UnderbarExtraDescender", "0" }, },
+ underbar_rule = { default = { "UnderbarRuleThickness", "default_rule_thickness" }, },
+ underbar_vgap = { default = { "UnderbarVerticalGap", "3*default_rule_thickness" }, },
+ connector_overlap_min = { default = { "MinConnectorOverlap", "0.25*default_rule_thickness" }, },
+ over_delimiter_vgap = { default = { "StretchStackGapBelowMin", "big_op_spacing1" }, },
+ over_delimiter_bgap = { default = { "StretchStackTopShiftUp", "big_op_spacing3" }, },
+ under_delimiter_vgap = { default = { "StretchStackGapAboveMin", "big_op_spacing2" }, },
+ under_delimiter_bgap = { default = { "StretchStackBottomShiftDown", "big_op_spacing4" }, },
+ radical_degree_before = { default = { "RadicalKernBeforeDegree", "(5/18)*quad" }, },
+ radical_degree_after = { default = { "RadicalKernAfterDegree", "(-10/18)*quad" }, },
+ radical_degree_raise = { default = { "RadicalDegreeBottomRaisePercent", "60" }, },
+}
+
+local styles = {
+ 'cramped_display_style',
+ 'cramped_script_script_style',
+ 'cramped_script_style',
+ 'cramped_text_style',
+ 'display_style',
+ 'script_script_style',
+ 'script_style',
+ 'text_style',
+}
+
+for k, v in next, defaults do
+ for _, s in next, styles do
+ if not v[s] then
+ v[s] = v.default
+ end
+ end
+end
+
+-- we cannot use a metatable because we do a copy (takes a bit more work)
+--
+-- local mt = { } setmetatable(defaults,mt)
+--
+-- mt.__index = function(t,s)
+-- return t.default or t.text_style or 0
+-- end
+
+function mathematics.dimensions(dimens) -- beware, dimens get spoiled
+ if dimens.SpaceAfterScript then
+ dimens.SubscriptShiftDownWithSuperscript = dimens.SubscriptShiftDown * 1.5 -- move this one
+ return table.fastcopy(dimens), { }
+ elseif dimens.AxisHeight or dimens.axis_height then
+ local t = { }
+ local math_x_height = dimens.x_height or 10*65536
+ local math_quad = dimens.quad or 10*65536
+ local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65536
+ dimens["0"] = 0
+ dimens["60"] = 60
+ dimens["0.25*default_rule_thickness"] = default_rule_thickness / 4
+ dimens["3*default_rule_thickness"] = 3 * default_rule_thickness
+ dimens["4*default_rule_thickness"] = 4 * default_rule_thickness
+ dimens["7*default_rule_thickness"] = 7 * default_rule_thickness
+ dimens["(5/18)*quad"] = (math_quad * 5) / 18
+ dimens["(-10/18)*quad"] = - (math_quad * 10) / 18
+ dimens["math_x_height*3"] = math_x_height * 3 -- needs checking
+ dimens["abs(math_x_height*4)/5"] = abs(math_x_height * 4) / 5
+ dimens["default_rule_thickness+(abs(default_rule_thickness)/4)"] = default_rule_thickness+(abs(default_rule_thickness) / 4)
+ dimens["default_rule_thickness+(abs(math_x_height)/4)"] = default_rule_thickness+(abs(math_x_height) / 4)
+ dimens["abs(math_x_height)/4"] = abs(math_x_height) / 4
+ dimens["abs(math_x_height*4)/5"] = abs(math_x_height * 4) / 5
+ dimens["<not set>"] = false
+ dimens["script_space"] = false -- at macro level
+ for variable, styles in next, defaults do
+ local tt = { }
+ for style, default in next, styles do
+ local one, two = default[1], default[2]
+ local value = dimens[one]
+ if value then
+ tt[style] = value
+ else
+ value = dimens[two]
+ if value == false then
+ tt[style] = nil
+ else
+ tt[style] = value or 0
+ end
+ end
+ end
+ t[variable] = tt
+ end
+ local d = {
+ AccentBaseHeight = t . accent_base_height . text_style,
+ AxisHeight = t . axis . text_style,
+ -- DelimitedSubFormulaMinHeight
+ DisplayOperatorMinHeight = t . math_operator_size . text_style, -- no longer let tex decide (weird values)
+ -- FlattenedAccentBaseHeight
+ FractionDenominatorDisplayStyleGapMin = t . fraction_denom_vgap . display_style,
+ FractionDenominatorDisplayStyleShiftDown = t . fraction_denom_down . display_style,
+ FractionDenominatorGapMin = t . fraction_denom_vgap . text_style,
+ FractionDenominatorShiftDown = t . fraction_denom_down . text_style,
+ FractionNumeratorDisplayStyleGapMin = t . fraction_num_vgap . display_style,
+ FractionNumeratorDisplayStyleShiftUp = t . fraction_num_up . display_style,
+ FractionNumeratorGapMin = t . fraction_num_vgap . text_style,
+ FractionNumeratorShiftUp = t . fraction_num_up . text_style,
+ FractionRuleThickness = t . fraction_rule . text_style,
+ FractionDelimiterSize = t . fraction_del_size . text_style,
+ FractionDelimiterDisplayStyleSize = t . fraction_del_size . display_style,
+ LowerLimitBaselineDropMin = t . limit_below_bgap . text_style,
+ LowerLimitGapMin = t . limit_below_vgap . text_style,
+ -- MathLeading
+ MinConnectorOverlap = t . connector_overlap_min . text_style,
+ OverbarExtraAscender = t . overbar_kern . text_style,
+ OverbarRuleThickness = t . overbar_rule . text_style,
+ OverbarVerticalGap = t . overbar_vgap . text_style,
+ RadicalDisplayStyleVerticalGap = t . radical_vgap . display_style,
+ RadicalExtraAscender = t . radical_kern . text_style,
+ RadicalRuleThickness = t . radical_rule . text_style,
+ RadicalVerticalGap = t . radical_vgap . text_style,
+ RadicalKernBeforeDegree = t . radical_degree_before . display_style,
+ RadicalKernAfterDegree = t . radical_degree_after . display_style,
+ RadicalDegreeBottomRaisePercent = t . radical_degree_raise . display_style,
+ -- ScriptPercentScaleDown
+ -- ScriptScriptPercentScaleDown
+ -- SkewedFractionHorizontalGap
+ -- SkewedFractionVerticalGap
+ SpaceAfterScript = t . space_after_script . text_style,
+ StackBottomDisplayStyleShiftDown = t . stack_denom_down . display_style,
+ StackBottomShiftDown = t . stack_denom_down . text_style,
+ StackDisplayStyleGapMin = t . stack_vgap . display_style,
+ StackGapMin = t . stack_vgap . text_style,
+ StackTopDisplayStyleShiftUp = t . stack_num_up . display_style,
+ StackTopShiftUp = t . stack_num_up . text_style,
+ StretchStackGapBelowMin = t . over_delimiter_vgap . text_style,
+ StretchStackTopShiftUp = t . over_delimiter_bgap . text_style,
+ StretchStackGapAboveMin = t . under_delimiter_vgap . text_style,
+ StretchStackBottomShiftDown = t . under_delimiter_bgap . text_style,
+ SubSuperscriptGapMin = t . subsup_vgap . text_style,
+ SubscriptBaselineDropMin = t . sub_shift_drop . text_style,
+ SubscriptShiftDown = t . sub_shift_down . text_style,
+ SubscriptShiftDownWithSuperscript = t . sub_sup_shift_down . text_style,
+ SubscriptTopMax = t . sub_top_max . text_style,
+ SuperscriptBaselineDropMax = t . sup_shift_drop . text_style,
+ SuperscriptBottomMaxWithSubscript = t . sup_sub_bottom_max . text_style,
+ SuperscriptBottomMin = t . sup_bottom_min . text_style,
+ SuperscriptShiftUp = t . sup_shift_up . text_style,
+ SuperscriptShiftUpCramped = t . sup_shift_up . cramped_text_style,
+ UnderbarExtraDescender = t . underbar_kern . text_style,
+ UnderbarRuleThickness = t . underbar_rule . text_style,
+ UnderbarVerticalGap = t . underbar_vgap . text_style,
+ UpperLimitBaselineRiseMin = t . limit_above_bgap . text_style,
+ UpperLimitGapMin = t . limit_above_vgap . text_style,
+ }
+
+ -- too fragile for tx/px ... even the same values give different results
+ d.DisplayOperatorMinHeight = nil
+ --
+ d.AccentBaseHeight = 0 -- here? still?
+ return d, t -- t only for diagnostics
+ else
+ return { }, { }
+ end
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua
new file mode 100644
index 00000000000..c9c2a38dddc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua
@@ -0,0 +1,172 @@
+if not modules then modules = { } end modules ['math-dir'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- As I'm wrapping up the updated math support (for CTX/TUG 2013) I wondered about numbers in
+-- r2l math mode. Googling lead me to TUGboat, Volume 25 (2004), No. 2 where I see numbers
+-- running from left to right. Makes me wonder how far we should go. And as I was looking
+-- into bidi anyway, it's a nice distraction.
+--
+-- I first tried to hook something into noads but that gets pretty messy due to indirectness
+-- char noads. If needed, I'll do it that way. With regards to spacing: as we can assume that
+-- only numbers are involved we can safely swap them and the same is true for mirroring. But
+-- anyway, I'm not too happy with this solution so eventually I'll do something with noads (as
+-- an alternative method). Yet another heuristic approach.
+
+local nodes, node = nodes, node
+
+local trace_directions = false trackers.register("typesetters.directions.math", function(v) trace_directions = v end)
+
+local report_directions = logs.reporter("typesetting","math directions")
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getchar = nuts.getchar
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+
+local setfield = nuts.setfield
+local setchar = nuts.setchar
+local setlist = nuts.setlist
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+
+local nodecodes = nodes.nodecodes
+local tasks = nodes.tasks
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local nodepool = nuts.pool
+
+local new_textdir = nodepool.textdir
+
+local chardirections = characters.directions
+local charmirrors = characters.mirrors
+local charclasses = characters.textclasses
+
+local directions = typesetters.directions or { }
+
+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"))
+ if trace_directions then
+ report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop))
+ end
+ done = true
+ start = false
+ stop = nil
+ end
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ local char = getchar(current)
+ local cdir = chardirections[char]
+ if cdir == "en" or cdir == "an" then -- we could check for mathclass punctuation
+ if not start then
+ start = current
+ end
+ stop = current
+ else
+ if not start then
+ -- nothing
+ elseif start == stop then
+ start = nil
+ else
+ capsulate()
+ end
+ if cdir == "on" then
+ local mirror = charmirrors[char]
+ if mirror then
+ local class = charclasses[char]
+ if class == "open" or class == "close" then
+ setchar(current,mirror)
+ if trace_directions then
+ report_directions("mirrored: %C to %C",char,mirror)
+ end
+ done = true
+ end
+ end
+ end
+ end
+ elseif not start then
+ -- nothing
+if id == hlist_code or id == vlist_code then
+ local list, d = processmath(getlist(current))
+ setlist(current,list)
+ if d then
+ done = true
+ end
+end
+ elseif start == stop then
+ start = nil
+ else
+ capsulate(head,start,stop)
+ -- 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))
+ setlist(current,list)
+ if d then
+ done = true
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ if not start then
+ -- nothing
+ elseif start == stop then
+ -- nothing
+ else
+ capsulate()
+ end
+ return head, done
+end
+
+local enabled = false
+
+function directions.processmath(head) -- style, penalties
+ if enabled then
+ local h = tonut(head)
+ local a = getattr(h,a_mathbidi)
+ if a and a > 0 then
+ local head, done = processmath(h)
+ return tonode(head), done
+ end
+ end
+ return head, false
+end
+
+function directions.setmath(n)
+ if not enabled and n and n > 0 then
+ if trace_directions then
+ report_directions("enabling directions handler")
+ end
+ tasks.enableaction("math","typesetters.directions.processmath")
+ enabled = true
+ end
+end
+
+interfaces.implement {
+ name = "setmathdirection",
+ actions = directions.setmath,
+ arguments = "integer"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-dis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-dis.mkiv
new file mode 100644
index 00000000000..5b70970f3cc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-dis.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=math-ali,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Display,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Display}
+
+\unprotect
+
+% display spacing code will move here
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua
new file mode 100644
index 00000000000..b00d6cde273
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua
@@ -0,0 +1,197 @@
+if not modules then modules = { } end modules ['math-ext'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
+
+local basename = file.basename
+
+local mathematics = mathematics
+local characters = characters
+
+local report_math = logs.reporter("mathematics")
+
+mathematics.extras = mathematics.extras or { }
+local extras = mathematics.extras
+
+characters.math = characters.math or { }
+local mathdata = characters.math
+local chardata = characters.data
+
+function extras.add(unicode,t) -- todo: if already stored ...
+ local min, max = mathematics.extrabase, mathematics.privatebase - 1
+ -- if mathdata[unicode] or chardata[unicode] then
+ -- report_math("extra %U overloads existing character",unicode)
+ -- end
+ if unicode >= min and unicode <= max then
+ mathdata[unicode], chardata[unicode] = t, t
+ else
+ report_math("extra %U should be in range %U - %U",unicode,min,max)
+ end
+end
+
+function extras.copy(target,original)
+ local characters = target.characters
+ local properties = target.properties
+ local parameters = target.parameters
+ for unicode, extradesc in next, mathdata do
+ -- always, because in an intermediate step we can have a non math font
+ local extrachar = characters[unicode]
+ local nextinsize = extradesc.nextinsize
+ if nextinsize then
+ local first = 1
+ local charused = unicode
+ if not extrachar then
+ for i=1,#nextinsize do
+ local slot = nextinsize[i]
+ extrachar = characters[slot]
+ if extrachar then
+ characters[unicode] = extrachar
+ first = i + 1
+ charused = slot
+ break
+ end
+ end
+ end
+ if not extrachar then
+ if trace_virtual then
+ report_math("extra %U in %a at %p with class %a and name %a is not mapped",
+ unicode,basename(properties.fullname),parameters.size,
+ extradesc.mathclass,extradesc.mathname)
+ end
+ elseif not extrachar.next then
+ local nextused = false
+ for i=first,#nextinsize do
+ local nextslot = nextinsize[i]
+ local nextbase = characters[nextslot]
+ if nextbase then
+ local nextnext = nextbase and nextbase.next
+ if nextnext then
+ local nextchar = characters[nextnext]
+ if nextchar then
+ extrachar.next = nextchar
+ nextused = nextslot
+ break
+ end
+ end
+ end
+ end
+ if trace_virtual then
+ if nextused then
+ report_math("extra %U in %a at %p with class %a and name %a maps onto %U with next %U",
+ unicode,basename(properties.fullname),parameters.size,charused,
+ extradesc.mathclass,extradesc.mathname,nextused)
+ else
+ report_math("extra %U in %a at %p with class %a and name %a maps onto %U with no next",
+ unicode,basename(properties.fullname),parameters.size,charused,
+ extradesc.mathclass,extradesc.mathname)
+ end
+ end
+ else
+ if trace_virtual then
+ report_math("extra %U in %a at %p with class %a and name %a maps onto %U with no next", -- own next
+ unicode,basename(properties.fullname),parameters.size,charused,
+ extradesc.mathclass,extradesc.mathname)
+ end
+ end
+ end
+ end
+end
+
+utilities.sequencers.appendaction(mathactions,"system","mathematics.extras.copy")
+
+-- 0xFE302 -- 0xFE320 for accents (gone with new lm/gyre)
+--
+-- extras.add(0xFE302, {
+-- category="mn",
+-- description="WIDE MATHEMATICAL HAT",
+-- direction="nsm",
+-- linebreak="cm",
+-- mathclass="topaccent",
+-- mathname="widehat",
+-- mathstretch="h",
+-- unicodeslot=0xFE302,
+-- nextinsize={ 0x00302, 0x0005E },
+-- } )
+--
+-- extras.add(0xFE303, {
+-- category="mn",
+-- cjkwd="a",
+-- description="WIDE MATHEMATICAL TILDE",
+-- direction="nsm",
+-- linebreak="cm",
+-- mathclass="topaccent",
+-- mathname="widetilde",
+-- mathstretch="h",
+-- unicodeslot=0xFE303,
+-- nextinsize={ 0x00303, 0x0007E },
+-- } )
+
+-- 0xFE321 -- 0xFE340 for missing characters
+
+extras.add(0xFE321, {
+ category="sm",
+ description="MATHEMATICAL SHORT BAR",
+ -- direction="on",
+ -- linebreak="nu",
+ mathclass="relation",
+ mathname="mapstochar",
+ unicodeslot=0xFE321,
+} )
+
+extras.add(0xFE322, {
+ category="sm",
+ description="MATHEMATICAL LEFT HOOK",
+ mathclass="relation",
+ mathname="lhook",
+ unicodeslot=0xFE322,
+} )
+
+extras.add(0xFE323, {
+ category="sm",
+ description="MATHEMATICAL RIGHT HOOK",
+ mathclass="relation",
+ mathname="rhook",
+ unicodeslot=0xFE323,
+} )
+
+extras.add(0xFE324, {
+ category="sm",
+ description="MATHEMATICAL SHORT BAR MIRRORED",
+-- direction="on",
+-- linebreak="nu",
+ mathclass="relation",
+ mathname="mapsfromchar",
+ unicodeslot=0xFE324,
+} )
+
+--~ extras.add(0xFE304, {
+--~ category="sm",
+--~ description="TOP AND BOTTOM PARENTHESES",
+--~ direction="on",
+--~ linebreak="al",
+--~ mathclass="doubleaccent",
+--~ mathname="doubleparent",
+--~ unicodeslot=0xFE304,
+--~ accents={ 0x023DC, 0x023DD },
+--~ } )
+
+--~ extras.add(0xFE305, {
+--~ category="sm",
+--~ description="TOP AND BOTTOM BRACES",
+--~ direction="on",
+--~ linebreak="al",
+--~ mathclass="doubleaccent",
+--~ mathname="doublebrace",
+--~ unicodeslot=0xFE305,
+--~ accents={ 0x023DE, 0x023DF },
+--~ } )
+
+--~ \Umathchardef\braceld="0 "1 "FF07A
+--~ \Umathchardef\bracerd="0 "1 "FF07B
+--~ \Umathchardef\bracelu="0 "1 "FF07C
+--~ \Umathchardef\braceru="0 "1 "FF07D
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua
new file mode 100644
index 00000000000..564ece8d7ca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua
@@ -0,0 +1,614 @@
+if not modules then modules = { } end modules ['math-fbk'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_fallbacks = false trackers.register("math.fallbacks", function(v) trace_fallbacks = v end)
+
+local report_fallbacks = logs.reporter("math","fallbacks")
+
+local formatters = string.formatters
+local fastcopy = table.fastcopy
+local byte = string.byte
+
+local fallbacks = { }
+mathematics.fallbacks = fallbacks
+
+local virtualcharacters = { }
+
+local identifiers = fonts.hashes.identifiers
+local lastmathids = fonts.hashes.lastmathids
+
+-- we need a trick (todo): if we define scriptscript, script and text in
+-- that order we could use their id's .. i.e. we could always add a font
+-- table with those id's .. in fact, we could also add a whole lot more
+-- as it doesn't hurt
+--
+-- todo: use index 'true when luatex provides that feature (on the agenda)
+
+-- to be considered:
+--
+-- in luatex provide reserve_id (and pass id as field of tfmdata)
+-- in context define three sizes but pass them later i.e. do virtualize afterwards
+
+function fallbacks.apply(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ local characters = target.characters
+ local parameters = target.parameters
+ local mathsize = parameters.mathsize
+ local size = parameters.size
+ local usedfonts = target.fonts
+ if not usedfonts then
+ usedfonts = { }
+ target.fonts = usedfonts
+ end
+ -- This is not okay yet ... we have no proper way to refer to 'self'
+ -- otherwise I will make my own id allocator).
+ local self = #usedfonts == 0 and font.nextid() or nil -- will be true
+ local textid, scriptid, scriptscriptid
+ local textindex, scriptindex, scriptscriptindex
+ local textdata, scriptdata, scriptscriptdata
+ if mathsize == 3 then
+ -- scriptscriptsize
+ -- textid = nil -- self
+ -- scriptid = nil -- no smaller
+ -- scriptscriptid = nil -- no smaller
+ textid = self
+ scriptid = self
+ scriptscriptid = self
+ elseif mathsize == 2 then
+ -- scriptsize
+ -- textid = nil -- self
+ textid = self
+ scriptid = lastmathids[3]
+ scriptscriptid = lastmathids[3]
+ else
+ -- textsize
+ -- textid = nil -- self
+ textid = self
+ scriptid = lastmathids[2]
+ scriptscriptid = lastmathids[3]
+ end
+ if textid then
+ textindex = #usedfonts + 1
+ usedfonts[textindex] = { id = textid }
+-- textdata = identifiers[textid] or target
+ textdata = target
+ else
+ textdata = target
+ end
+ if scriptid then
+ scriptindex = #usedfonts + 1
+ usedfonts[scriptindex] = { id = scriptid }
+ scriptdata = identifiers[scriptid]
+ else
+ scriptindex = textindex
+ scriptdata = textdata
+ end
+ if scriptscriptid then
+ scriptscriptindex = #usedfonts + 1
+ usedfonts[scriptscriptindex] = { id = scriptscriptid }
+ scriptscriptdata = identifiers[scriptscriptid]
+ else
+ scriptscriptindex = scriptindex
+ scriptscriptdata = scriptdata
+ end
+ -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid)
+ local data = {
+ textdata = textdata,
+ scriptdata = scriptdata,
+ scriptscriptdata = scriptscriptdata,
+ textindex = textindex,
+ scriptindex = scriptindex,
+ scriptscriptindex = scriptscriptindex,
+ textid = textid,
+ scriptid = scriptid,
+ scriptscriptid = scriptscriptid,
+ characters = characters,
+ unicode = k,
+ target = target,
+ original = original,
+ size = size,
+ mathsize = mathsize,
+ }
+ target.mathrelation = data
+ -- inspect(usedfonts)
+ for k, v in next, virtualcharacters do
+ if not characters[k] then
+ local tv = type(v)
+ local cd = nil
+ if tv == "table" then
+ cd = v
+ elseif tv == "number" then
+ cd = characters[v]
+ elseif tv == "function" then
+ cd = v(data)
+ end
+ if cd then
+ characters[k] = cd
+ else
+ -- something else
+ end
+ if trace_fallbacks and characters[k] then
+ report_fallbacks("extending math font %a with %U",target.properties.fullname,k)
+ end
+ end
+ end
+ data.unicode = nil
+ end
+end
+
+utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply")
+
+function fallbacks.install(unicode,value)
+ virtualcharacters[unicode] = value
+end
+
+-- a few examples:
+
+local function reference(index,char)
+ if index then
+ return { "slot", index, char }
+ else
+ return { "char", char }
+ end
+end
+
+local function raised(data,down)
+ local replacement = data.replacement
+ local character = data.scriptdata.characters[replacement]
+ if character then
+ return {
+ width = character.width,
+ height = character.height,
+ depth = character.depth,
+ commands = {
+ { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight
+ reference(data.scriptindex,replacement)
+ }
+ }
+ end
+end
+
+-- virtualcharacters[0x207A] = 0x2212
+-- virtualcharacters[0x207B] = 0x002B
+-- virtualcharacters[0x208A] = 0x2212
+-- virtualcharacters[0x208B] = 0x002B
+
+virtualcharacters[0x207A] = function(data)
+ data.replacement = 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
+
+-- 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 commands = { }
+-- for i=1,n-1 do
+-- width = width + delta
+-- commands[#commands+1] = c
+-- commands[#commands+1] = -delta
+-- end
+-- commands[#commands+1] = c
+-- return {
+-- width = width,
+-- height = character.height,
+-- depth = character.depth,
+-- commands = commands,
+-- }
+-- end
+-- end
+
+-- virtualcharacters[0x222C] = function(data)
+-- return repeated(data,0x222B,2,1/8)
+-- end
+
+-- virtualcharacters[0x222D] = function(data)
+-- return repeated(data,0x222B,3,1/8)
+-- end
+
+local addextra = mathematics.extras.add
+
+addextra(0xFE350, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW LEFT END",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillleftend",
+ unicodeslot=0xFE350,
+} )
+
+addextra(0xFE351, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW MIDDLE PART",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillmiddlepart",
+ unicodeslot=0xFE351,
+} )
+
+addextra(0xFE352, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW RIGHT END",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillrightend",
+ unicodeslot=0xFE352,
+} )
+
+local push = { "push" }
+local pop = { "pop" }
+local leftarrow = { "char", 0x2190 }
+local relbar = { "char", 0x2212 }
+local rightarrow = { "char", 0x2192 }
+
+virtualcharacters[0xFE350] = function(data)
+ -- return combined(data,0x2190,0x2212) -- leftarrow relbar
+ local charone = data.characters[0x2190]
+ local chartwo = data.characters[0x2212]
+ if charone and chartwo then
+ local size = data.size/2
+ return {
+ width = chartwo.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ leftarrow,
+ pop,
+ { "down", -size/2 },
+ relbar,
+ }
+ }
+ end
+end
+
+virtualcharacters[0xFE351] = function(data)
+ -- return combined(data,0x2212,0x2212) -- relbar, relbar (isn't that just equal)
+ local char = data.characters[0x2212]
+ if char then
+ local size = data.size/2
+ return {
+ width = char.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ relbar,
+ pop,
+ { "down", -size/2 },
+ relbar,
+ }
+ }
+ end
+end
+
+virtualcharacters[0xFE352] = function(data)
+ -- return combined(data,0x2192,0x2212) -- rightarrow relbar
+ local charone = data.characters[0x2192]
+ local chartwo = data.characters[0x2212]
+ if charone and chartwo then
+ local size = data.size/2
+ return {
+ width = chartwo.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ relbar,
+ pop,
+ { "right", chartwo.width - charone.width },
+ { "down", -size/2 },
+ rightarrow,
+ }
+ }
+ end
+end
+
+-- we could move the defs from math-act here
+
+local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap,offset,unicode)
+ local characters = target.characters
+ local olddata = characters[oldchr]
+ -- brrr ... pagella has only next
+ if olddata and not olddata.commands and olddata.width > 0 then
+ local addprivate = fonts.helpers.addprivate
+ if swap then
+ swap = characters[swap]
+ height = swap.depth or 0
+ depth = 0
+ else
+ 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 newdata = {
+ commands = { correction, { "slot", 1, oldchr } },
+ width = olddata.width,
+ height = height,
+ depth = depth,
+ unicode = unicode,
+ }
+ local glyphdata = newdata
+ local nextglyph = olddata.next
+ while nextglyph do
+ local oldnextdata = characters[nextglyph]
+ if oldnextdata then
+ local newnextdata = {
+ commands = { correction, { "slot", 1, nextglyph } },
+ width = oldnextdata.width,
+ height = height,
+ depth = depth,
+ }
+ local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata)
+ newdata.next = newnextglyph
+ local nextnextglyph = oldnextdata.next
+ if nextnextglyph == nextglyph then
+ break
+ else
+ olddata = oldnextdata
+ newdata = newnextdata
+ nextglyph = nextnextglyph
+ end
+ else
+ report_fallbacks("error in fallback: no valid next, slot %X",nextglyph)
+ break
+ end
+ end
+ local hv = olddata.horiz_variants
+ if hv then
+ hv = fastcopy(hv)
+ newdata.horiz_variants = hv
+ for i=1,#hv do
+ local hvi = hv[i]
+ local oldglyph = hvi.glyph
+ local olddata = characters[oldglyph]
+ if olddata then
+ local newdata = {
+ commands = { correction, { "slot", 1, oldglyph } },
+ width = olddata.width,
+ height = height,
+ depth = depth,
+ }
+ 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
+ end
+ end
+ return glyphdata, true
+ else
+ return olddata, false
+ end
+end
+
+virtualcharacters[0x203E] = function(data) -- could be FE33E instead
+ local target = data.target
+ local height, depth = 0, 0
+ local mathparameters = target.mathparameters
+ if mathparameters then
+ height = mathparameters.OverbarVerticalGap
+ depth = mathparameters.UnderbarVerticalGap
+ else
+ height = target.parameters.xheight/4
+ depth = height
+ end
+ return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E)
+end
+
+virtualcharacters[0xFE33E] = virtualcharacters[0x203E] -- convenient
+virtualcharacters[0xFE33F] = virtualcharacters[0x203E] -- convenient
+
+-- spacing
+
+local c_zero = byte('0')
+local c_period = byte('.')
+
+local function spacefraction(data,fraction)
+ local width = fraction * data.target.parameters.space
+ return {
+ width = width,
+ commands = { right = width }
+ }
+end
+
+local function charfraction(data,char)
+ local width = data.target.characters[char].width
+ return {
+ width = width,
+ commands = { right = width }
+ }
+end
+
+local function quadfraction(data,fraction)
+ local width = fraction * data.target.parameters.quad
+ return {
+ width = width,
+ commands = { right = width }
+ }
+end
+
+virtualcharacters[0x00A0] = function(data) return spacefraction(data,1) end -- nbsp
+virtualcharacters[0x2000] = function(data) return quadfraction (data,1/2) end -- enquad
+virtualcharacters[0x2001] = function(data) return quadfraction (data,1) end -- emquad
+virtualcharacters[0x2002] = function(data) return quadfraction (data,1/2) end -- enspace
+virtualcharacters[0x2003] = function(data) return quadfraction (data,1) end -- emspace
+virtualcharacters[0x2004] = function(data) return quadfraction (data,1/3) end -- threeperemspace
+virtualcharacters[0x2005] = function(data) return quadfraction (data,1/4) end -- fourperemspace
+virtualcharacters[0x2006] = function(data) return quadfraction (data,1/6) end -- sixperemspace
+virtualcharacters[0x2007] = function(data) return charfraction (data,c_zero) end -- figurespace
+virtualcharacters[0x2008] = function(data) return charfraction (data,c_period) end -- punctuationspace
+virtualcharacters[0x2009] = function(data) return quadfraction (data,1/8) end -- breakablethinspace
+virtualcharacters[0x200A] = function(data) return quadfraction (data,1/8) end -- hairspace
+virtualcharacters[0x200B] = function(data) return quadfraction (data,0) end -- zerowidthspace
+virtualcharacters[0x202F] = function(data) return quadfraction (data,1/8) end -- narrownobreakspace
+virtualcharacters[0x205F] = function(data) return spacefraction(data,1/2) end -- math thinspace
+
+--
+
+local function smashed(data,unicode,swap,private)
+ local target = data.target
+ local original = data.original
+ local chardata = target.characters[unicode]
+ if chardata and chardata.height > target.parameters.xheight then
+ return accent_to_extensible(target,private,original,unicode,0,0,swap,nil,unicode)
+ else
+ return original.characters[unicode]
+ end
+end
+
+addextra(0xFE3DE, { description="EXTENSIBLE OF 0x03DE", unicodeslot=0xFE3DE, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } )
+addextra(0xFE3DC, { description="EXTENSIBLE OF 0x03DC", unicodeslot=0xFE3DC, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } )
+addextra(0xFE3B4, { description="EXTENSIBLE OF 0x03B4", unicodeslot=0xFE3B4, mathextensible = "r", mathstretch = "h", mathclass = "topaccent" } )
+
+virtualcharacters[0xFE3DE] = function(data) return smashed(data,0x23DE,0x23DF,0xFE3DE) end
+virtualcharacters[0xFE3DC] = function(data) return smashed(data,0x23DC,0x23DD,0xFE3DC) end
+virtualcharacters[0xFE3B4] = function(data) return smashed(data,0x23B4,0x23B5,0xFE3B4) end
+
+addextra(0xFE3DF, { description="EXTENSIBLE OF 0x03DF", unicodeslot=0xFE3DF, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } )
+addextra(0xFE3DD, { description="EXTENSIBLE OF 0x03DD", unicodeslot=0xFE3DD, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } )
+addextra(0xFE3B5, { description="EXTENSIBLE OF 0x03B5", unicodeslot=0xFE3B5, mathextensible = "r", mathstretch = "h", mathclass = "botaccent" } )
+
+virtualcharacters[0xFE3DF] = function(data) local c = data.target.characters[0x23DF] if c then c.unicode = 0x23DF return c end end
+virtualcharacters[0xFE3DD] = function(data) local c = data.target.characters[0x23DD] if c then c.unicode = 0x23DD return c end end
+virtualcharacters[0xFE3B5] = function(data) local c = data.target.characters[0x23B5] if c then c.unicode = 0x23B5 return c end end
+
+-- todo: add some more .. numbers might change
+
+addextra(0xFE302, { description="EXTENSIBLE OF 0x0302", unicodeslot=0xFE302, mathstretch = "h", mathclass = "topaccent" } )
+addextra(0xFE303, { description="EXTENSIBLE OF 0x0303", unicodeslot=0xFE303, mathstretch = "h", mathclass = "topaccent" } )
+
+local function smashed(data,unicode,private)
+ local target = data.target
+ local height = target.parameters.xheight / 2
+ local c, done = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height,unicode)
+ if done then
+ c.top_accent = nil -- or maybe also all the others
+ end
+ return c
+end
+
+virtualcharacters[0xFE302] = function(data) return smashed(data,0x0302,0xFE302) end
+virtualcharacters[0xFE303] = function(data) return smashed(data,0x0303,0xFE303) end
+
+-- another crazy hack .. doesn't work as we define scrscr first .. we now have smaller
+-- primes so we have smaller primes for the moment, big ones will become an option ..
+-- these primes in fonts are a real mess .. kind of a dead end, so don't wonder about
+-- the values below
+
+-- todo: check tounicodes
+
+local function smashed(data,unicode,optional)
+ local oldchar = data.characters[unicode]
+ if oldchar then
+ local xheight = data.target.parameters.xheight
+ local height = 1.2 * xheight
+ local shift = oldchar.height - height
+ local newchar = {
+ commands = {
+ { "down", shift },
+ { "char", unicode },
+ },
+ height = height,
+ width = oldchar.width,
+ }
+ return newchar
+ elseif not optional then
+ report_fallbacks("missing %U prime in font %a",unicode,data.target.properties.fullname)
+ end
+end
+
+-- -- relocate all but less flexible so not used .. instead some noad hackery plus
+-- -- the above
+--
+-- local function smashed(data,unicode,optional)
+-- local oldchar = data.characters[unicode]
+-- if oldchar then
+-- local xheight = data.target.parameters.xheight
+-- local height = oldchar.height
+-- local shift = oldchar.height < 1.5*xheight and -(1.8*xheight-height) or 0
+-- local newchar = {
+-- commands = {
+-- { "down", shift },
+-- { "char", unicode },
+-- },
+-- unicode = unicode,
+-- height = height,
+-- width = oldchar.width,
+-- }
+-- return newchar
+-- elseif not optional then
+-- report_fallbacks("missing %U prime in font %a",unicode,data.target.properties.fullname)
+-- end
+-- end
+
+addextra(0xFE932, { description="SMASHED PRIME 0x02032", unicodeslot=0xFE932 } )
+addextra(0xFE933, { description="SMASHED PRIME 0x02033", unicodeslot=0xFE933 } )
+addextra(0xFE934, { description="SMASHED PRIME 0x02034", unicodeslot=0xFE934 } )
+addextra(0xFE957, { description="SMASHED PRIME 0x02057", unicodeslot=0xFE957 } )
+
+addextra(0xFE935, { description="SMASHED BACKWARD PRIME 0x02035", unicodeslot=0xFE935 } )
+addextra(0xFE936, { description="SMASHED BACKWARD PRIME 0x02036", unicodeslot=0xFE936 } )
+addextra(0xFE937, { description="SMASHED BACKWARD PRIME 0x02037", unicodeslot=0xFE937 } )
+
+virtualcharacters[0xFE932] = function(data) return smashed(data,0x02032) end
+virtualcharacters[0xFE933] = function(data) return smashed(data,0x02033) end
+virtualcharacters[0xFE934] = function(data) return smashed(data,0x02034) end
+virtualcharacters[0xFE957] = function(data) return smashed(data,0x02057) end
+
+virtualcharacters[0xFE935] = function(data) return smashed(data,0x02035,true) end
+virtualcharacters[0xFE936] = function(data) return smashed(data,0x02036,true) end
+virtualcharacters[0xFE937] = function(data) return smashed(data,0x02037,true) end
+
+-- actuarian (beware: xits has an ugly one)
+
+addextra(0xFE940, { category = "mn", description="SMALL ANNUITY SYMBOL", unicodeslot=0xFE940, mathclass="topaccent", mathname="smallactuarial" })
+
+local function actuarian(data)
+ local characters = data.target.characters
+ local parameters = data.target.parameters
+ local basechar = characters[0x0078] -- x (0x0058 X) or 0x1D431
+ local linewidth = parameters.xheight / 10
+ local basewidth = basechar.width
+ local baseheight = basechar.height
+ return {
+ -- todo: add alttext
+ -- compromise: lm has large hooks e.g. \actuarial{a}
+ width = basewidth + 4 * linewidth,
+ unicode = 0x20E7,
+ commands = {
+ { "right", 2 * linewidth },
+ { "down", - baseheight - 3 * linewidth },
+ { "rule", linewidth, basewidth + 4 * linewidth },
+ { "right", -linewidth },
+ { "down", baseheight + 4 * linewidth },
+ { "rule", baseheight + 5 * linewidth, linewidth },
+ },
+ }
+end
+
+virtualcharacters[0x020E7] = actuarian -- checked
+virtualcharacters[0xFE940] = actuarian -- unchecked
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv
new file mode 100644
index 00000000000..81e39723d3c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv
@@ -0,0 +1,716 @@
+%D \module
+%D [ file=math-fen,
+%D version=2012.02.18,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fences,
+%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 / Fences}
+
+\unprotect
+
+% todo: mathstyle
+
+% \definemathfence [fancybracket] [bracket] [command=yes,color=blue]
+%
+% test $|x|$ test \par
+% test $||x||$ test (okay) \par
+% test $a\left|\frac{1}{b}\right|c$ test \par
+% test $a\left||\frac{1}{b}\right||c$ test (not okay) \par
+%
+% \setupmathfences [color=red]
+%
+% test $a\fenced[bar]{\frac{1}{b}}c$ test \par
+% test $a\fenced[doublebar]{\frac{1}{b}}c$ test \par
+% test $a\fenced[bracket]{\frac{1}{b}}c$ test \par
+% test $a\fancybracket{\frac{1}{b}}c$ test \par
+
+\installcorenamespace{mathfences}
+
+\installcommandhandler \??mathfences {mathfence} \??mathfences
+
+\let\setupmathfences\setupmathfence
+
+\setupmathfences
+ [\c!left=,
+ \c!right=,
+ \c!middle=,
+ \c!mathstyle=,
+ \c!color=,
+ \c!command=]
+
+\appendtoks
+ \edef\p_command{\mathfenceparameter\c!command}%
+ \ifx\p_command\v!yes
+ \setuevalue\currentmathfence{\math_fenced_fenced[\currentmathfence]}%
+ \fi
+\to \everydefinemathfence
+
+% we need the direct use of \Udelimiter because of { etc
+
+\def\math_fenced_left {\edef\p_left{\mathfenceparameter\c!left}%
+ \math_fenced_color_push
+ \normalleft\ifx\p_left\empty.\else\Udelimiter\plusfour\fam\p_left\relax\fi
+ \math_fenced_color_pop}
+\def\math_fenced_middle{\edef\p_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_color_pop
+ \mskip\thinmuskip}
+\def\math_fenced_right {\edef\p_right{\mathfenceparameter\c!right}%
+ \math_fenced_color_push
+ \normalright\ifx\p_right\empty.\else\Udelimiter\plusfive\fam\p_right\relax\fi
+ \math_fenced_color_pop}
+
+\def\math_fenced_color_do_push{\pushcolor[\p_math_fenced_color]}
+\let\math_fenced_color_do_pop \popcolor
+
+\let\math_fenced_color_push\donothing
+\let\math_fenced_color_pop \donothing
+
+\let\fence \relax
+\let\fenced\relax
+
+\newcount\c_math_fenced_nesting
+
+\unexpanded\def\math_fenced_fenced_start#1%
+ {\advance\c_math_fenced_nesting\plusone
+ \begingroup
+ \edef\currentmathfence{#1}%
+ \startusemathstyleparameter\mathfenceparameter
+ \let\fence\math_fenced_middle
+ \edef\p_math_fenced_color{\mathfenceparameter\c!color}%
+ \ifx\p_math_fenced_color\empty
+ \let\math_fenced_color_push\donothing
+ \let\math_fenced_color_pop \donothing
+ \else
+ \let\math_fenced_color_push\math_fenced_color_do_push
+ \let\math_fenced_color_pop \math_fenced_color_do_pop
+ \fi
+ \math_fenced_left}
+
+\unexpanded\def\math_fenced_fenced_stop#1%
+ {\edef\currentmathfence{#1}%
+ \math_fenced_right
+ \stopusemathstyleparameter
+ \endgroup
+ \advance\c_math_fenced_nesting\minusone}
+
+\unexpanded\def\math_fenced_fenced[#1]#2%
+ {\math_fenced_fenced_start{#1}%
+ #2%
+ \math_fenced_right
+ \stopusemathstyleparameter
+ \endgroup
+ \advance\c_math_fenced_nesting\minusone}
+
+\appendtoks
+ \let\fenced\math_fenced_fenced
+\to \everymathematics
+
+% todo: | in mathmode letter
+%
+% \appendtoks
+% \let\bar\letterbar
+% \to \everymathematics
+%
+% but then we don't have it in embedded text too so ...
+
+\definemathfence [parenthesis] [\c!left="0028,\c!right="0029]
+\definemathfence [bracket] [\c!left="005B,\c!right="005D]
+\definemathfence [brace] [\c!left="007B,\c!right="007D]
+\definemathfence [bar] [\c!left="007C,\c!right="007C]
+\definemathfence [doublebar] [\c!left="2016,\c!right="2016]
+\definemathfence [triplebar] [\c!left="2980,\c!right="2980]
+\definemathfence [angle] [\c!left="27E8,\c!right="27E9]
+\definemathfence [doubleangle] [\c!left="27EA,\c!right="27EB]
+\definemathfence [solidus] [\c!left="2044,\c!right="2044]
+\definemathfence [ceiling] [\c!left="2308,\c!right="2309]
+\definemathfence [floor] [\c!left="230A,\c!right="230B]
+\definemathfence [moustache] [\c!left="23B0,\c!right="23B1]
+\definemathfence [uppercorner] [\c!left="231C,\c!right="231D]
+\definemathfence [lowercorner] [\c!left="231E,\c!right="231F]
+\definemathfence [group] [\c!left="27EE,\c!right="27EF]
+\definemathfence [openbracket] [\c!left="27E6,\c!right="27E7]
+
+\definemathfence [nothing]
+
+\definemathfence [mirrored] % \v!mirrored
+
+\definemathfence [mirroredparenthesis] [mirrored] [\c!right="0028,\c!left="0029]
+\definemathfence [mirroredbracket] [mirrored] [\c!right="005B,\c!left="005D]
+\definemathfence [mirroredbrace] [mirrored] [\c!right="007B,\c!left="007D]
+\definemathfence [mirroredbar] [mirrored] [\c!right="007C,\c!left="007C]
+\definemathfence [mirroreddoublebar] [mirrored] [\c!right="2016,\c!left="2016]
+\definemathfence [mirroredtriplebar] [mirrored] [\c!right="2980,\c!left="2980]
+\definemathfence [mirroredangle] [mirrored] [\c!right="27E8,\c!left="27E9]
+\definemathfence [mirroreddoubleangle] [mirrored] [\c!right="27EA,\c!left="27EB]
+\definemathfence [mirroredsolidus] [mirrored] [\c!right="2044,\c!left="2044]
+\definemathfence [mirroredceiling] [mirrored] [\c!right="2308,\c!left="2309]
+\definemathfence [mirroredfloor] [mirrored] [\c!right="230A,\c!left="230B]
+\definemathfence [mirroredmoustache] [mirrored] [\c!right="23B0,\c!left="23B1]
+\definemathfence [mirroreduppercorner] [mirrored] [\c!right="231C,\c!left="231D]
+\definemathfence [mirroredlowercorner] [mirrored] [\c!right="231E,\c!left="231F]
+\definemathfence [mirroredgroup] [mirrored] [\c!right="27EE,\c!left="27EF]
+\definemathfence [mirroredopenbracket] [mirrored] [\c!right="27E6,\c!left="27E7]
+
+\definemathfence [mirrorednothing] [mirrored]
+
+%D A bonus:
+
+\unexpanded\def\Lparenthesis {\math_fenced_fenced_start{parenthesis}} \unexpanded\def\Rparenthesis {\math_fenced_fenced_stop {parenthesis}}
+\unexpanded\def\Lbracket {\math_fenced_fenced_start{bracket}} \unexpanded\def\Rbracket {\math_fenced_fenced_stop {bracket}}
+\unexpanded\def\Lbrace {\math_fenced_fenced_start{brace}} \unexpanded\def\Rbrace {\math_fenced_fenced_stop {brace}}
+\unexpanded\def\Langle {\math_fenced_fenced_start{angle}} \unexpanded\def\Rangle {\math_fenced_fenced_stop {angle}}
+\unexpanded\def\Ldoubleangle {\math_fenced_fenced_start{doubleangle}} \unexpanded\def\Rdoubleangle {\math_fenced_fenced_stop {doubleangle}}
+\unexpanded\def\Lbar {\math_fenced_fenced_start{bar}} \unexpanded\def\Rbar {\math_fenced_fenced_stop {bar}}
+\unexpanded\def\Ldoublebar {\math_fenced_fenced_start{doublebar}} \unexpanded\def\Rdoublebar {\math_fenced_fenced_stop {doublebar}}
+\unexpanded\def\Ltriplebar {\math_fenced_fenced_start{triplebar}} \unexpanded\def\Rtriplebar {\math_fenced_fenced_stop {triplebar}}
+\unexpanded\def\Lsolidus {\math_fenced_fenced_start{solidus}} \unexpanded\def\Rsolidus {\math_fenced_fenced_stop {solidus}}
+\unexpanded\def\Lfloor {\math_fenced_fenced_start{floor}} \unexpanded\def\Rfloor {\math_fenced_fenced_stop {floor}}
+\unexpanded\def\Lceiling {\math_fenced_fenced_start{ceiling}} \unexpanded\def\Rceiling {\math_fenced_fenced_stop {ceiling}}
+\unexpanded\def\Lmoustache {\math_fenced_fenced_start{moustache}} \unexpanded\def\Rmoustache {\math_fenced_fenced_stop {moustache}}
+\unexpanded\def\Luppercorner {\math_fenced_fenced_start{uppercorner}} \unexpanded\def\Ruppercorner {\math_fenced_fenced_stop {uppercorner}}
+\unexpanded\def\Llowercorner {\math_fenced_fenced_start{lowercorner}} \unexpanded\def\Rlowercorner {\math_fenced_fenced_stop {lowercorner}}
+\unexpanded\def\Lgroup {\math_fenced_fenced_start{group}} \unexpanded\def\Rgroup {\math_fenced_fenced_stop {group}}
+\unexpanded\def\Lopenbracket {\math_fenced_fenced_start{openbracket}} \unexpanded\def\Ropenbracket {\math_fenced_fenced_stop {openbracket}}
+\unexpanded\def\Lnothing {\math_fenced_fenced_start{nothing}} \unexpanded\def\Rnothing {\math_fenced_fenced_stop {nothing}}
+
+\unexpanded\def\Lparenthesismirrored {\math_fenced_fenced_stop {mirroredparenthesis}} \unexpanded\def\Rparenthesismirrored {\math_fenced_fenced_start{mirroredparenthesis}}
+\unexpanded\def\Lbracketmirrored {\math_fenced_fenced_stop {mirroredbracket}} \unexpanded\def\Rbracketmirrored {\math_fenced_fenced_start{mirroredbracket}}
+\unexpanded\def\Lbracemirrored {\math_fenced_fenced_stop {mirroredbrace}} \unexpanded\def\Rbracemirrored {\math_fenced_fenced_start{mirroredbrace}}
+\unexpanded\def\Langlemirrored {\math_fenced_fenced_stop {mirroredangle}} \unexpanded\def\Ranglemirrored {\math_fenced_fenced_start{mirroredangle}}
+\unexpanded\def\Ldoubleanglemirrored {\math_fenced_fenced_stop {mirroreddoubleangle}} \unexpanded\def\Rdoubleanglemirrored {\math_fenced_fenced_start{mirroreddoubleangle}}
+\unexpanded\def\Lbarmirrored {\math_fenced_fenced_stop {mirroredbar}} \unexpanded\def\Rbarmirrored {\math_fenced_fenced_start{mirroredbar}}
+\unexpanded\def\Ldoublebarmirrored {\math_fenced_fenced_stop {mirroreddoublebar}} \unexpanded\def\Rdoublebarmirrored {\math_fenced_fenced_start{mirroreddoublebar}}
+\unexpanded\def\Ltriplebarmirrored {\math_fenced_fenced_stop {mirroredtriplebar}} \unexpanded\def\Rtriplebarmirrored {\math_fenced_fenced_start{mirroredtriplebar}}
+\unexpanded\def\Lsolidusmirrored {\math_fenced_fenced_stop {mirroredsolidus}} \unexpanded\def\Rsolidusmirrored {\math_fenced_fenced_start{mirroredsolidus}}
+\unexpanded\def\Lfloormirrored {\math_fenced_fenced_stop {mirroredfloor}} \unexpanded\def\Rfloormirrored {\math_fenced_fenced_start{mirroredfloor}}
+\unexpanded\def\Lceilingmirrored {\math_fenced_fenced_stop {mirroredceiling}} \unexpanded\def\Rceilingmirrored {\math_fenced_fenced_start{mirroredceiling}}
+\unexpanded\def\Lmoustachemirrored {\math_fenced_fenced_stop {mirroredmoustache}} \unexpanded\def\Rmoustachemirrored {\math_fenced_fenced_start{mirroredmoustache}}
+\unexpanded\def\Luppercornermirrored {\math_fenced_fenced_stop {mirroreduppercorner}} \unexpanded\def\Ruppercornermirrored {\math_fenced_fenced_start{mirroreduppercorner}}
+\unexpanded\def\Llowercornermirrored {\math_fenced_fenced_stop {mirroredlowercorner}} \unexpanded\def\Rlowercornermirrored {\math_fenced_fenced_start{mirroredlowercorner}}
+\unexpanded\def\Lgroupmirrored {\math_fenced_fenced_stop {mirroredgroup}} \unexpanded\def\Rgroupmirrored {\math_fenced_fenced_start{mirroredgroup}}
+\unexpanded\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}} \unexpanded\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}}
+\unexpanded\def\Lnothingmirrored {\math_fenced_fenced_stop {mirrorednothing}} \unexpanded\def\Rnothingmirrored {\math_fenced_fenced_start{mirrorednothing}}
+
+% \startformula
+% \left{ \frac{1}{a} \right}
+% \left[ \frac{1}{b} \right]
+% \left( \frac{1}{c} \right)
+% \left< \frac{1}{d} \right>
+% \left| \frac{1}{e} \right|
+% \stopformula
+
+\installcorenamespace{mathleft}
+\installcorenamespace{mathright}
+\installcorenamespace{mathmiddle}
+
+\unexpanded\def\left {\afterassignment\math_left \let\nexttoken}
+\unexpanded\def\right {\afterassignment\math_right \let\nexttoken}
+\unexpanded\def\middle{\afterassignment\math_middle\let\nexttoken}
+
+\let\leftorright\relax
+
+\newconditional\c_math_fenced_done
+\newconditional\c_math_fenced_unknown \settrue\c_math_fenced_unknown
+
+% maybe use \detokenize ... todo \lastnamedcs
+
+% \setvalue{\??mathleft \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft \nexttoken\fi}
+% \setvalue{\??mathright \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
+% \setvalue{\??mathmiddle\s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
+%
+% \def\math_left
+% {\settrue\c_math_fenced_done
+% \edef\m_math_left{\meaning\nexttoken}%
+% \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+%
+% \def\math_right
+% {\settrue\c_math_fenced_done
+% \edef\m_math_right{\meaning\nexttoken}%
+% \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+%
+% \def\math_middle
+% {\settrue\c_math_fenced_done
+% \edef\m_math_middle{\meaning\nexttoken}%
+% \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\lfence#1%
+% {\settrue\c_math_fenced_done
+% \let\nexttoken#1%
+% \edef\m_math_left{\meaning#1}%
+% \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\rfence#1%
+% {\settrue\c_math_fenced_done
+% \let\nexttoken#1%
+% \edef\m_math_right{\meaning#1}%
+% \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\mfence#1%
+% {\settrue\c_math_fenced_done
+% \let\nexttoken#1%
+% \edef\m_math_middle{\meaning#1}%
+% \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
+
+\unexpanded\def\installmathfencepair#1#2#3#4%
+ {\expandafter\let\csname\??mathleft \meaning#1\endcsname#2%
+ \expandafter\let\csname\??mathright\meaning#3\endcsname#4}
+
+\def\math_unknown_left {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft \nexttoken\fi}
+\def\math_unknown_right {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
+\def\math_unknown_middle{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
+
+\letvalue{\??mathleft \s!unknown}\math_unknown_left
+\letvalue{\??mathright \s!unknown}\math_unknown_right
+\letvalue{\??mathmiddle\s!unknown}\math_unknown_middle
+
+\def\math_left
+ {\settrue\c_math_fenced_done
+ \ifcsname\??mathleft\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_left
+ \fi}
+
+\def\math_right
+ {\settrue\c_math_fenced_done
+ \ifcsname\??mathright\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_right
+ \fi}
+
+\def\math_middle
+ {\settrue\c_math_fenced_done
+ \ifcsname\??mathmiddle\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_middle
+ \fi}
+
+\unexpanded\def\lfence#1%
+ {\settrue\c_math_fenced_done
+ \let\nexttoken#1%
+ \ifcsname\??mathleft\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_left
+ \fi}
+
+\unexpanded\def\rfence#1%
+ {\settrue\c_math_fenced_done
+ \let\nexttoken#1%
+ \ifcsname\??mathright\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_right
+ \fi}
+
+\unexpanded\def\mfence#1%
+ {\settrue\c_math_fenced_done
+ \let\nexttoken#1%
+ \ifcsname\??mathmiddle\meaning\nexttoken\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\math_unknown_middle
+ \fi}
+
+\normalexpanded{\installmathfencepair {|\detokenize {|}} \Ldoublebar {|\detokenize {|}} \Rdoublebar}
+\normalexpanded{\installmathfencepair {|\detokenize{||}} \Ltriplebar {|\detokenize{||}} \Rtriplebar}
+
+\installmathfencepair \bgroup \Lbrace \egroup \Rbrace
+\installmathfencepair \egroup \Rbracemirrored \bgroup \Lbracemirrored
+
+\installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts
+
+\installmathfencepair . \Lnothing . \Rnothing
+\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored
+
+\installmathfencepair [ \Lbracket ] \Rbracket
+\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored
+
+\installmathfencepair ( \Lparenthesis ) \Rparenthesis
+\installmathfencepair ) \Rparentmirrored ( \Lparentmirrored
+
+\installmathfencepair < \Langle > \Rangle
+\installmathfencepair > \Ranglemirrored < \Langlemirrored
+
+\installmathfencepair / \Lsolidus / \Rsolidus
+%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored
+
+\installmathfencepair | \Lbar | \Rbar
+%installmathfencepair | \Rbarmirrored | \Lbarmirrored
+
+\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor
+\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored
+\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling
+\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored
+
+\installmathfencepair ⟨ \Langle ⟩ \Rangle
+\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored
+
+\installmathfencepair ⟪ \Ldoubleangle ⟫ \Rdoubleangle
+\installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored
+
+\installmathfencepair ‖ \Ldoublebar ‖ \Rdoublebar
+%installmathfencepair ‖ \Rdoublebarmirrored ‖ \Ldoublebarmirrored
+
+\installmathfencepair ⦀ \Ltriplebar ⦀ \Rtriplebar
+%installmathfencepair ⦀ \Rtriplebarmirrored ⦀ \Ltriplebarmirrored
+
+% \installmathfencepair { \Lbrace } \Rbrace
+% \installmathfencepair } \Rbracemirrored { \Lbracemirrored
+
+\appendtoks
+ \ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
+\to \everymathematics
+
+% We unofficial support some synonyms as we need them for some fuzzy web related math.
+
+% The names in char-def.lua (historic mess):
+
+\let\lbrack \lbracket
+\let\rbrack \rbracket
+\let\lceiling \lceil
+\let\rceiling \rceil
+\let\lparenthesis\lparent
+\let\rparenthesis\rparent
+\let\lparen \lparent
+\let\rparen \rparent
+
+% Just defined:
+
+\let\Lceil \Lceiling
+\let\Rceil \Rceiling
+\let\Lparent\Lparenthesis
+\let\Rparent\Rparenthesis
+\let\Lparen \Lparenthesis
+\let\Rparen \Rparenthesis
+
+\installmathfencepair \lbrace \Lbrace \rbrace \Rbrace
+\installmathfencepair \lbracket \Lbracket \rbracket \Rbracket
+\installmathfencepair \lbrack \Lbracket \rbracket \Rbracket
+\installmathfencepair \lparenthesis \Lparenthesis \rparenthesis \Rparenthesis
+\installmathfencepair \lparent \Lparenthesis \rparent \Rparenthesis
+\installmathfencepair \lparen \Lparenthesis \rparen \Rparenthesis
+\installmathfencepair \langle \Langle \rangle \Rangle
+\installmathfencepair \llangle \Ldoubleangle \rrangle \Rdoubleangle
+%installmathfencepair \lbar \Lbar \rbar \Rbar
+\installmathfencepair \lVert \Ldoublebar \rVert \Rdoublebar
+\installmathfencepair \vert \Lbar \vert \Rbar
+\installmathfencepair \solidus \Lsolidus \solidus \Rsolidus
+\installmathfencepair \lfloor \Lfloor \rfloor \Rfloor
+\installmathfencepair \lceiling \Lceiling \rceiling \Rceiling
+\installmathfencepair \lceil \Lceiling \rceil \Rceiling
+
+\installmathfencepair \ulcorner \Luppercorner \urcorner \Ruppercorner
+\installmathfencepair \llcorner \Llowercorner \lrcorner \Rlowercorner
+\installmathfencepair \lmoustache \Lmoustache \rmoustache \Rmoustache
+\installmathfencepair \llbracket \Lopenbracket \rrbracket \Ropenbracket
+\installmathfencepair \lgroup \Lgroup \rgroup \Rgroup
+
+\let\textlbar\lbar \let\mathlbar\Lbar
+\let\textrbar\lbar \let\mathrbar\Rbar
+
+\unexpanded\def\lbar{\mathortext\mathlbar\textlbar}
+\unexpanded\def\rbar{\mathortext\mathrbar\textrbar}
+
+% \setupmathfences[color=darkgreen]
+
+\unexpanded\def\{{\mathortext\lbrace \letterleftbrace } % or maybe a chardef
+\unexpanded\def\}{\mathortext\rbrace \letterrightbrace } % or maybe a chardef
+\unexpanded\def\[{\mathortext\lbracket \letterleftbracket } % or maybe a chardef
+\unexpanded\def\]{\mathortext\rbracket \letterrightbracket } % or maybe a chardef
+\unexpanded\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef
+\unexpanded\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef
+\unexpanded\def\|{\mathortext\vert \letterbar } % or maybe a chardef
+%unexpanded\def\/{\mathortext\solidus \letterslash } % or maybe a chardef
+
+\installmathfencepair \{ \Lbrace \} \Rbrace
+\installmathfencepair \[ \Lbracket \] \Rbracket
+\installmathfencepair \( \Lparenthesis \) \Rparenthesis
+\installmathfencepair \< \Langle \> \Rangle
+\installmathfencepair \| \Lbar \| \Rbar
+
+%D As we have overloaded \type {\left} and \type {\right} we also need a more
+%D clever version of the following:
+
+% methods:
+%
+% 1: none
+% 2: lua
+% 3: tex
+
+% variants:
+%
+% 1: step 1
+% 2: step 2
+% 3: htdp * 1.33^n
+% 4: size * 1.33^n
+
+\setnewconstant\bigmathdelimitermethod \plusone
+\setnewconstant\bigmathdelimitervariant\plusthree
+
+\unexpanded\def\plainbigdelimiters % traditional method
+ {\bigmathdelimitermethod\plustwo}
+
+\plainbigdelimiters % is default for the moment but not so nice
+
+% \setconstant\bigmathdelimitermethod\plusone
+
+\installcorenamespace{mathbig}
+
+\unexpanded\def\choosemathbig#1#2% so we accept \big{||} as well
+ {{\hbox\bgroup
+ \startimath
+ \ifcase\bigmathdelimitermethod
+ \math_fenced_step#2\relax
+ \or
+ \attribute\mathsizeattribute\numexpr\bigmathdelimitervariant*\plushundred+#1\relax
+ \math_fenced_step#2\relax
+ \else
+ \math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}%
+ \fi
+ \nulldelimiterspace\zeropoint\relax
+ \mathsurround\zeropoint
+ \stopimath
+ \egroup}}
+
+\def\math_fenced_step#1#2%
+ {\setfalse\c_math_fenced_unknown
+ \setfalse\c_math_fenced_done
+ \left#1\relax
+ \ifconditional\c_math_fenced_done
+ #2%
+ \right.\relax
+ \else
+ \left.\relax
+ #2%
+ \setfalse\c_math_fenced_done
+ \right#1\relax
+ \ifconditional\c_math_fenced_done
+ \else
+ \right.\relax
+ \fi
+ \fi}
+
+\unexpanded\def\mathdelimiterstep#1#2%
+ {\begingroup
+ \attribute\mathsizeattribute\numexpr\plushundred+#1\relax
+ \math_fenced_step#2\relax
+ \endgroup}
+
+\setvalue{\??mathbig1}{0.85}
+\setvalue{\??mathbig2}{1.15}
+\setvalue{\??mathbig3}{1.45}
+\setvalue{\??mathbig4}{1.75}
+
+\definemathcommand [big] {\choosemathbig\plusone }
+\definemathcommand [Big] {\choosemathbig\plustwo }
+\definemathcommand [bigg] {\choosemathbig\plusthree}
+\definemathcommand [Bigg] {\choosemathbig\plusfour }
+
+\definemathcommand [bigl] [open] [one] {\big}
+\definemathcommand [bigm] [rel] [one] {\big}
+\definemathcommand [bigr] [close] [one] {\big}
+\definemathcommand [Bigl] [open] [one] {\Big}
+\definemathcommand [Bigm] [rel] [one] {\Big}
+\definemathcommand [Bigr] [close] [one] {\Big}
+\definemathcommand [biggl] [open] [one] {\bigg}
+\definemathcommand [biggm] [rel] [one] {\bigg}
+\definemathcommand [biggr] [close] [one] {\bigg}
+\definemathcommand [Biggl] [open] [one] {\Bigg}
+\definemathcommand [Biggm] [rel] [one] {\Bigg}
+\definemathcommand [Biggr] [close] [one] {\Bigg}
+
+% \definemathfence [integral] [\c!left="222B]
+%
+% \unexpanded\def\Lintegral {\math_fenced_fenced_start{integral}}
+% \unexpanded\def\Rintegral {\math_fenced_fenced_stop {integral}}
+%
+% \installmathfencepair \lintegral \Lintegral \rintegral \Rintegral
+%
+% \left\lintegral
+% \vrule height 3cm depth 3cm
+% \right\rintegral
+
+%definemathfence [fancybracket] [bracket] [command=yes,color=red]
+
+% experimental accents:
+%
+% \definemathoverextensible [top] [hoed] ["FE302]
+% \definemathoverextensible [top] [slang] ["FE303]
+
+%D This is needed for mathml (used in mrow, so it gets reset):
+
+% old code:
+
+% \let\math_fences_saved_left \left
+% \let\math_fences_saved_middle\middle
+% \let\math_fences_saved_right \right
+%
+% % \def\math_fences_traced#1{\ruledhbox{\ttx#1\low{\the\c_math_fenced_nesting}}}
+%
+% \unexpanded\def\math_fences_checked_left
+% {%\math_fences_traced L%
+% \math_fences_saved_left}
+%
+% \unexpanded\def\math_fences_checked_middle
+% {%\math_fences_traced M%
+% \ifcase\c_math_fenced_nesting
+% \expandafter\math_fences_saved_middle
+% \else
+% \expandafter\firstofoneargument
+% \fi}
+%
+% \unexpanded\def\math_fences_checked_right
+% {%\math_fences_traced R%
+% \ifcase\c_math_fenced_nesting
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\math_fences_saved_right
+% \fi}
+%
+% \newconditional\c_math_checked_done % only bars
+%
+% \unexpanded\def\math_fences_checked_left_or_right
+% {%\math_fences_traced B%
+% \ifcase\c_math_fenced_nesting
+% \settrue\c_math_checked_done
+% \expandafter\math_fences_saved_left
+% \else\ifconditional\c_math_checked_done
+% \setfalse\c_math_checked_done
+% \doubleexpandafter\math_fences_saved_right
+% \else
+% \doubleexpandafter\math_fences_saved_middle
+% \fi\fi}
+%
+% \unexpanded\def\math_fences_checked_start
+% {\c_math_fenced_nesting\zerocount}
+%
+% \unexpanded\def\math_fences_checked_stop
+% {\ifcase\c_math_fenced_nesting\else
+% \right.\relax % error, todo: nil spacing
+% \expandafter\math_fences_checked_stop
+% \fi}
+%
+% \unexpanded\def\startcheckedfences
+% {\begingroup
+% \let\left \math_fences_checked_left
+% \let\middle\math_fences_checked_middle
+% \let\right \math_fences_checked_right
+% \math_fences_checked_start}
+%
+% \unexpanded\def\stopcheckedfences
+% {\math_fences_checked_stop
+% \endgroup}
+%
+% \let\leftorright\math_fences_checked_left_or_right % for bars
+
+\definesystemattribute[mathautofence][public]
+
+\let\math_fences_normal_left \left
+\let\math_fences_normal_right \right
+\let\math_fences_normal_middle\middle
+\let\math_fences_normal_both \leftorright
+
+\unexpanded\def\math_fences_auto_left #1{\attribute\mathautofenceattribute\plusone #1\attribute\mathautofenceattribute\attributeunsetvalue}
+\unexpanded\def\math_fences_auto_right #1{\attribute\mathautofenceattribute\plustwo #1\attribute\mathautofenceattribute\attributeunsetvalue}
+\unexpanded\def\math_fences_auto_middle#1{\attribute\mathautofenceattribute\plusthree#1\attribute\mathautofenceattribute\attributeunsetvalue}
+\unexpanded\def\math_fences_auto_both #1{\attribute\mathautofenceattribute\plusfour #1\attribute\mathautofenceattribute\attributeunsetvalue}
+
+\let\autofenceopen \math_fences_auto_left % for testing
+\let\autofenceclose \math_fences_auto_right % for testing
+\let\autofenceleft \math_fences_auto_left % for testing
+\let\autofenceright \math_fences_auto_right % for testing
+\let\autofencemiddle\math_fences_auto_middle % for testing
+\let\autofenceboth \math_fences_auto_both % for testing
+
+% fences are used not that often (i.e. no performance issue) so we can use a state
+% instead of \let ... also some state variable can come in handy in the future
+
+\newconditional\c_math_fences_auto
+
+\unexpanded\def\enableautofences
+ {\clf_enableautofences
+ \glet\clf_enableautofences\relax % onlyonce anyway
+ \unexpanded\gdef\enableautofences{\settrue\c_math_fences_auto}%
+ \enableautofences}
+
+\unexpanded\def\disableautofences
+ {\setfalse\c_math_fences_auto}
+
+\unexpanded\def\math_fences_used_left
+ {\ifconditional\c_math_fences_auto
+ \expandafter\math_fences_auto_left
+ \else
+ \expandafter\math_fences_normal_left
+ \fi}
+\unexpanded\def\math_fences_used_right
+ {\ifconditional\c_math_fences_auto
+ \expandafter\math_fences_auto_right
+ \else
+ \expandafter\math_fences_normal_right
+ \fi}
+\unexpanded\def\math_fences_used_middle
+ {\ifconditional\c_math_fences_auto
+ \expandafter\math_fences_auto_middle
+ \else
+ \expandafter\math_fences_normal_middle
+ \fi}
+\unexpanded\def\math_fences_used_both
+ {\ifconditional\c_math_fences_auto
+ \expandafter\math_fences_auto_both
+ \else
+ \expandafter\math_fences_normal_both
+ \fi}
+
+\let\left \math_fences_used_left
+\let\right \math_fences_used_right
+\let\middle \math_fences_used_middle
+\let\leftorright\math_fences_used_both
+
+% wrappers
+
+\unexpanded\def\startcheckedfences
+ {\begingroup
+ \enableautofences}
+
+\unexpanded\def\stopcheckedfences
+ {\endgroup}
+
+\appendtoks
+ % maybe: safeguard against overloading
+ %
+ % \let\left \math_fences_used_left
+ % \let\right \math_fences_used_right
+ % \let\middle \math_fences_used_middle
+ % \let\leftorright\math_fences_used_both
+\to \everymathematics
+
+\appendtoks
+ \ifx\currentmathfence\empty
+ \doifelse{\mathfenceparameter\c!state}\v!auto\enableautofences\disableautofences
+ \fi
+\to \everysetupmathfence
+
+% some day default: \setupmathfences[\c!state=\v!auto]
+
+%D The next characters were used for constructing nicer extensibles but
+%D nowadays we have real characters.
+
+\Umathchardef\braceld\zerocount \defaultmathfamily "FF07A
+\Umathchardef\bracerd\zerocount \defaultmathfamily "FF07B
+\Umathchardef\bracelu\zerocount \defaultmathfamily "FF07C
+\Umathchardef\braceru\zerocount \defaultmathfamily "FF07D
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-for.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-for.mkiv
new file mode 100644
index 00000000000..0c8bd05aeac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-for.mkiv
@@ -0,0 +1,33 @@
+%D \module
+%D [ file=strc-mat,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Math Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Math Formulas}
+
+%D This module only provides the code for defining formulas and
+%D fetching parameters. The action takes place later.
+
+\unprotect
+
+%D \macros
+%D {setupformulas,setupsubformulas}
+
+\installcorenamespace{formula}
+\installcorenamespace{subformula}
+
+\installcommandhandler \??formula {formula} \??formula
+\installcommandhandler \??subformula {subformula} \??subformula % maybe just setuphandler (no childs used yet)
+
+\let\setupformulas \setupformula
+\let\setupsubformulas\setupsubformula
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua b/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua
new file mode 100644
index 00000000000..639edc94ba3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['math-frc'] = {
+ version = 1.001,
+ comment = "companion to math-frc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfchar = utf.char
+
+local context = context
+local variables = interfaces.variables
+
+local v_no = variables.no
+local v_yes = variables.yes
+
+local resolved = {
+ [0x007B] = "\\{",
+ [0x007D] = "\\}",
+}
+
+table.setmetatableindex(resolved, function(t,k)
+ local v = utfchar(k)
+ t[k] = v
+ return v
+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
+ if left == 0x002E and right == 0x002E then
+ ctx_normalatop()
+ else
+ context("\\atopwithdelims%s%s",resolved[left],resolved[right])
+ end
+ elseif how == v_yes then
+ if left == 0x002E and right == 0x002E then
+ context("\\normalabove%ssp",width)
+ else
+ context("\\abovewithdelims%s%s%ssp",resolved[left],resolved[right],width)
+ end
+ else -- v_auto
+ if left == 0x002E and right == 0x002E then
+ ctx_normalover()
+ else
+ context("\\overwithdelims%s%s",resolved[left],resolved[right])
+ end
+ end
+end
+
+interfaces.implement {
+ name = "mathfraction",
+ actions = mathfraction,
+ arguments = { "string", "number", "number", "dimen" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv
new file mode 100644
index 00000000000..16ea6e9e131
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv
@@ -0,0 +1,618 @@
+%D \module
+%D [ file=math-frc,
+%D version=2013.04.06, % 2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fractions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Fractions}
+
+\unprotect
+
+%D I need to check it all again as there was a bug in luatex with dimensions that could
+%D resulted in side effects that made me mess with spacing.
+
+\unexpanded\def\topstrut{\vrule\s!width\zeropoint\s!height\strutht\s!depth\zeropoint\relax}
+\unexpanded\def\botstrut{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp\relax}
+
+\unexpanded\def\mathtopstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\ht\scratchbox\s!depth\zeropoint\relax}
+\unexpanded\def\mathbotstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\dp\scratchbox\relax}
+
+%D This module is reimplemented in \MKIV\ style.
+
+\registerctxluafile{math-frc}{1.001}
+
+%D \macros
+%D {frac, xfrac, xxfrac}
+%D
+%D This is another one Tobias asked for. It replaces the primitive \type
+%D {\over}. We also take the opportunity to handle math style restoring,
+%D which makes sure units and chemicals come out ok. The \type {\frac}
+%D macro kind of replaces the awkward \type {\over} primitive. Say that
+%D we have the following formulas:
+%D
+%D \startbuffer[sample]
+%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$
+%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$
+%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$
+%D \stopbuffer
+%D
+%D \typebuffer[sample]
+%D
+%D With the most straightforward definitions, we get:
+%D
+%D \startbuffer[code]
+%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
+%D
+%D \def\frac {\dofrac\mathstyle}
+%D \def\xfrac {\dofrac\scriptstyle}
+%D \def\xxfrac{\dofrac\scriptscriptstyle}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D Since this does not work well, we can try:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}}
+%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D This for sure looks better than:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}}
+%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D So we stick to the next definitions (watch the local overloading of
+%D \type {\xfrac}).
+%D
+%D In the meantime, in \LUATEX, we have better control over styles so the
+%D following macros are different from the \MKII\ ones.
+
+% obsolete, is now c!mathstyle
+%
+% 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle
+%
+% $\mathfracmode0 \frac{1}{2}$
+% $\mathfracmode1 \frac{1}{2}$
+% $\mathfracmode2 \frac{1}{2}$
+% $\mathfracmode3 \frac{1}{2}$
+% $\mathfracmode4 \frac{1}{2}$
+% $\mathfracmode5 \frac{1}{2}$
+%
+% we keep the constant for a while
+
+\setnewconstant\mathfracmode\zerocount
+
+\installcorenamespace{mathfractions}
+\installcorenamespace{mathfractionstyle}
+\installcorenamespace{mathfractionalternative}
+
+\installcommandhandler \??mathfractions {mathfraction} \??mathfractions
+
+\let\setupmathfractions\setupmathfraction
+
+% color only applies to rule, use regular color for rest
+
+\setupmathfractions
+ [\c!mathstyle=,
+ \c!alternative=\v!inner,
+ \c!margin=\zeropoint,
+ \c!rulethickness=.25\exheight,
+ \c!left=0x2E,
+ \c!right=0x2E,
+ \c!strut=\v!yes,
+ \c!topdistance=,
+ \c!bottomdistance=,
+ \c!rule=\v!auto]
+
+\appendtoks
+ \setuevalue{\currentmathfraction}{\math_frac{\currentmathfraction}}%
+\to \everydefinemathfraction
+
+% Sometimes users want control over the distances:
+
+\let\math_fraction_set_distance\relax
+
+\appendtoks
+ \math_fraction_set_distance
+\to \everymathematics
+
+% why only displaystyle .. a bit weak
+
+\unexpanded\def\math_fraction_set_distance_top
+ {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top
+ \relax}
+
+\unexpanded\def\math_fraction_set_distance_bot
+ {\Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot
+ \relax}
+
+\unexpanded\def\math_fraction_set_distance_all
+ {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top
+ \Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot
+ \relax}
+
+\appendtoks
+ \ifx\currentmathfraction\empty
+ \edef\m_math_fraction_distance_top{\mathfractionparameter\c!topdistance}%
+ \edef\m_math_fraction_distance_bot{\mathfractionparameter\c!bottomdistance}%
+ \ifx\m_math_fraction_distance_top\empty
+ \ifx\m_math_fraction_distance_bot\empty
+ \let\math_fraction_set_distance\relax
+ \else
+ \let\math_fraction_set_distance\math_fraction_set_distance_bot
+ \fi
+ \else
+ \ifx\m_math_fraction_distance_bot\empty
+ \let\math_fraction_set_distance\math_fraction_set_distance_top
+ \else
+ \let\math_fraction_set_distance\math_fraction_set_distance_all
+ \fi
+ \fi
+ \fi
+\to \everysetupmathfraction
+
+% So far for control.
+
+\installcorenamespace{mathfractionstrut}
+
+\def\math_frac_no_strut
+ {\let\m_fractions_strut_top\relax
+ \let\m_fractions_strut_bot\relax}
+
+\setvalue{\??mathfractionstrut\v!yes}%
+ {\let\m_fractions_strut_top\mathstrut
+ \let\m_fractions_strut_bot\mathstrut}
+
+\setvalue{\??mathfractionstrut\v!math}%
+ {\let\m_fractions_strut_top\mathstrut
+ \let\m_fractions_strut_bot\mathstrut}
+
+\letvalue{\??mathfractionstrut\v!no}\math_frac_no_strut
+
+\setvalue{\??mathfractionstrut\v!tight}%
+ {\let\m_fractions_strut_top\mathbotstrut % indeed swapped name
+ \let\m_fractions_strut_bot\mathtopstrut} % indeed swapped name
+
+\math_frac_no_strut
+
+\newdimen\d_math_fraction_margin
+
+\unexpanded\def\math_frac#1%
+ {\begingroup
+ \edef\currentmathfraction{#1}%
+ %
+ \d_math_fraction_margin\mathfractionparameter\c!margin
+ %
+ \edef\p_math_fractions_color{\mathfractionparameter\c!color}%
+ %
+ \edef\p_math_fractions_strut{\mathfractionparameter\c!strut}%
+ \ifcsname\??mathfractionstrut\p_math_fractions_strut\endcsname
+ \lastnamedcs
+ \else
+ \math_frac_no_strut
+ \fi
+ %
+ \ifx\p_math_fractions_color\empty
+ \expandafter\math_frac_normal
+ \else
+ \expandafter\math_frac_colored
+ \fi}
+
+\unexpanded\def\math_frac_colored#1#2%
+ {\savecolor
+ \colo_helpers_activate\p_math_fractions_color
+ \math_frac_normal{\restorecolor#1}{\restorecolor#2}}
+
+\unexpanded\def\math_frac_normal
+ {\expandnamespaceparameter\??mathfractionalternative\mathfractionparameter\c!alternative\v!inner}
+
+% we use utfchar anyway so we can as well do all at the lua end
+
+\def\math_frac_command
+ {\clf_mathfraction
+ {\mathfractionparameter\c!rule}%
+ \mathfractionparameter\c!left\space
+ \mathfractionparameter\c!right\space
+ \dimexpr\mathfractionparameter\c!rulethickness\relax
+ \relax}
+
+% Having a \withmarginornot{#1}{#2} makes not much sense nor do 4 tests or 4 redundant
+% kerns (longer node lists plus possible interference). A split in normal and margin
+% also makes testing easier. When left and right margins are needed we might merge the
+% variants again. After all, these are not real installers.
+
+\setvalue{\??mathfractionalternative\v!inner}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_inner_normal
+ \else
+ \expandafter\math_fraction_inner_margin
+ \fi}
+
+\setvalue{\??mathfractionalternative\v!outer}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_outer_normal
+ \else
+ \expandafter\math_fraction_outer_margin
+ \fi}
+
+\setvalue{\??mathfractionalternative\v!both}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_both_normal
+ \else
+ \expandafter\math_fraction_both_margin
+ \fi}
+
+% todo: store first state and reuse second time
+
+\def\math_fraction_inner_normal#1#2%
+ {\Ustack{%
+ {%
+ {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}%
+ \math_frac_command
+ {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}%
+ }%
+ }\endgroup}
+
+\def\math_fraction_outer_normal#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\m_fractions_strut_top#1}%
+ \math_frac_command
+ {\m_fractions_strut_bot#2}%
+ }%
+ }\endgroup}
+
+\def\math_fraction_both_normal#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}%
+ \math_frac_command
+ {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}%
+ }%
+ }\endgroup}
+
+\def\math_fraction_inner_margin#1#2%
+ {\Ustack{%
+ {%
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}%
+ \kern\d_math_fraction_margin}%
+ }%
+ }\endgroup}
+
+\def\math_fraction_outer_margin#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\kern\d_math_fraction_margin
+ \m_fractions_strut_top#1%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \m_fractions_strut_bot#2%
+ \kern\d_math_fraction_margin}%
+ }%
+ }\endgroup}
+
+\def\math_fraction_both_margin#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2%
+ \kern\d_math_fraction_margin}%
+ }%
+ }\endgroup}
+
+
+\definemathfraction[xfrac] [\c!alternative=\v!inner,\c!mathstyle=\s!script]
+\definemathfraction[xxfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript]
+
+\let\normalxfrac\xfrac
+
+\unexpanded\def\xfrac#1#2{\normalxfrac{\let\xfrac\xxfrac#1}{\let\xfrac\xxfrac#2}}
+
+%D Spacing:
+
+\unexpanded\def\nomathfractiongaps {\normalexpanded{\math_no_fraction_gaps \triggermathstyle\mathstyle}} % maybe collect settings
+\unexpanded\def\overlaymathfractiongaps{\normalexpanded{\math_overlay_fraction_gaps\triggermathstyle\mathstyle}} % maybe collect settings
+
+\unexpanded\def\math_no_fraction_gaps#1%
+ {\Umathfractionnumup #1\zeropoint
+ \Umathfractiondenomdown#1\zeropoint}
+
+\unexpanded\def\math_overlay_fraction_gaps#1%
+ {\Umathfractionnumup #1\zeropoint
+ \Umathfractionnumvgap #1\zeropoint
+ %Umathfractionrule #1\zeropoint
+ \Umathfractiondenomvgap#1\zeropoint
+ \Umathfractiondenomdown#1\zeropoint}
+
+\installcorenamespace{mathfractiondistance}
+
+\letvalue{\??mathfractiondistance\v!none }\nomathfractiongaps
+\letvalue{\??mathfractiondistance\v!no }\nomathfractiongaps
+\letvalue{\??mathfractiondistance\v!overlay}\overlaymathfractiongaps
+
+\setupmathfractions
+ [\c!distance=\v!none]
+
+\appendtoks
+ \edef\p_distance{\rootmathfractionparameter\c!distance}%
+ \ifx\p_distance\empty\else
+ \ifcsname\??mathfractiondistance\p_distance\endcsname
+ \lastnamedcs
+ \fi
+ \fi
+\to \everymathematics
+
+%D \macros
+%D {dfrac, tfrac, frac, dbinom, tbinom, binom}
+%D
+%D \startbuffer
+%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$
+%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+% $$
+% {{a}\over{b}} +
+% {{a}\overwithdelims(){b}} +
+% {{a}\atopwithdelims(){b}} +
+% {{a}\abovewithdelims()\zeropoint{b}} +
+% \left({{a}\over{b}}\right)
+% $$
+
+% \dorecurse {10} { % weird
+% $$ {{a}\abovewithdelims()#1pt{b}} $$
+% }
+
+\definemathfraction[i:frac] [\c!alternative=\v!inner,\c!mathstyle=] % was script and then small but nothing needed
+\definemathfraction[i:tfrac][\c!alternative=\v!inner,\c!mathstyle=\s!text] % was script (before luatex fix)
+\definemathfraction[i:sfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript]
+\definemathfraction[i:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display]
+
+\definemathfraction[d:frac] [\c!alternative=\v!inner,\c!mathstyle=\s!cramped] % was cramped,text
+\definemathfraction[d:tfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!text}] % was cramped,script (before luatex fix)
+\definemathfraction[d:sfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!scriptscript}]
+\definemathfraction[d:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display]
+
+%D \unexpanded\def\ShowMathFractions#1#2%
+%D {\dontleavehmode
+%D \begingroup
+%D \showmathstruts
+%D \mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}%
+%D \endgroup}
+%D
+%D The default \type {tfrac}, \type {frac} and \type \sfrac} look like this:
+%D
+%D \blank
+%D \ShowMathFractions{a}{a}\par
+%D \ShowMathFractions{1}{x}\par
+%D \ShowMathFractions{a}{b}\par
+%D \ShowMathFractions{1}{b}\par
+%D \blank
+
+\unexpanded\def\frac {\csname\inlineordisplaymath id:frac\endcsname}
+\unexpanded\def\tfrac{\csname\inlineordisplaymath id:tfrac\endcsname}
+\unexpanded\def\sfrac{\csname\inlineordisplaymath id:sfrac\endcsname}
+\unexpanded\def\dfrac{\csname\inlineordisplaymath id:dfrac\endcsname}
+
+\definemathfraction[ams] [\c!strut=\v!no,\c!alternative=\v!outer]
+\definemathfraction[i:ams:frac][ams][\c!mathstyle={\s!cramped,\s!text}]
+\definemathfraction[d:ams:frac][ams][\c!mathstyle={\s!cramped,\s!display}]
+
+\unexpanded\def\ctxfrac{\csname\inlineordisplaymath id:frac\endcsname}
+\unexpanded\def\amsfrac{\csname\inlineordisplaymath id:ams:frac\endcsname}
+
+% \appendtoks
+% \doifelse{\mathfractionparameter\c!option}{ams}%
+% {\let\frac\amsfrac}%
+% {\let\frac\ctxfrac}%
+% \to \everysetupmathfraction
+
+\appendtoks
+ \doifelse{\mathematicsparameter\c!fractions}{ams}%
+ {\let\frac\amsfrac}%
+ {\let\frac\ctxfrac}%
+\to \everysetupmathematics
+
+% \definemathfraction[ddfrac][\c!mathstyle=\s!display]
+% \definemathfraction[ttfrac][\c!mathstyle=\s!text]
+% \definemathfraction[ssfrac][\c!mathstyle=\s!script]
+
+% \unexpanded\def\binom #1#2{{\Ustack {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+% \unexpanded\def\dbinom#1#2{{\displaystyle{{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+% \unexpanded\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+
+\definemathfraction[binom] [\c!alternative=\v!outer,\c!rule=\v!no,\c!left=0x28,\c!right=0x29,\c!mathstyle=\s!auto]
+\definemathfraction[dbinom][\c!alternative=\v!outer,\c!rule=\v!no,\c!left=0x28,\c!right=0x29,\c!mathstyle=\s!display]
+\definemathfraction[tbinom][\c!alternative=\v!outer,\c!rule=\v!no,\c!left=0x28,\c!right=0x29,\c!mathstyle=\s!text]
+
+%D \macros
+%D {cfrac}
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Now we can align every combination we want:
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$
+%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+\unexpanded\def\cfrac
+ {\doifelsenextoptionalcs\math_cfrac_yes\math_cfrac_nop}
+
+\def\math_cfrac_nop {\math_cfrac_indeed[cc]}
+\def\math_cfrac_yes[#1]{\math_cfrac_indeed[#1cc]}
+
+\def\math_cfrac_indeed[#1#2#3]#4#5%
+ {{\displaystyle
+ \frac
+ {\strut
+ \ifx r#1\hfill\fi#4\ifx l#1\hfill\fi}%
+ {\ifx r#2\hfill\fi#5\ifx l#2\hfill\fi}%
+ \kern-\nulldelimiterspace}}
+
+%D \macros
+%D {splitfrac, splitdfrac}
+%D
+%D Occasionally one needs to typeset multi||line fractions.
+%D These commands use \tex{genfrac} to create such fractions.
+%D
+%D \startbuffer
+%D \startformula
+%D a=\frac{
+%D \splitfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D =\frac{
+%D \splitdfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D These macros are based on Michael J.~Downes posting on
+%D comp.text.tex on 2001/12/06 but adapted a bit.
+
+\unexpanded\def\splitfrac #1#2%
+ {{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}}
+
+\unexpanded\def\splitdfrac#1#2%
+ {{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}}
+
+%D For testing:
+
+% \unexpanded\def\ShowMathFractions#1#2%
+% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}}
+
+\protect \endinput
+
+% I have no clue what \mthfrac and \mthsqrt are supposed to do but
+% I guess that it can be done with tweaking luatex's math parameters.
+% Otherwise I'll write something from scratch.
+
+% \def\math_stylebuilders_frac#1#2#3#4#5#6#7%
+% {\begingroup
+% \mathsurround\zeropoint
+% \setbox0\hbox{$#1 #6$}%
+% \setbox2\hbox{$#1 #7$}%
+% \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi
+% \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}%
+% \mathord{\vcenter{{\offinterlineskip
+% \hbox to \dimen0{\hss\box0\hss}%
+% \kern\ht4%
+% \hbox to \dimen0{\hss\copy4\hss}%
+% \kern\ht4%
+% \hbox to \dimen0{\hss\box2\hss}}}}%
+% \endgroup}
+%
+% \def\math_stylebuilders_sqrt#1#2#3#4#5%
+% {\begingroup
+% \mathsurround\zeropoint
+% \setbox0\hbox{$#1 #5$}%
+% \ht0\dimexpr1.05\ht0+\onepoint\relax
+% \dp0\dimexpr1.05\dp0+\onepoint\relax
+% \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}%
+% \delimitershortfall\zeropoint
+% \nulldelimiterspace\zeropoint
+% \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point?
+% \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
+% \endgroup}
+%
+% \def\mthfrac#1#2#3#4#5{\mathchoice
+% {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
+%
+% \def\mthsqrt#1#2#3{\mathchoice
+% {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}}
+
+% \unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]}
+% \unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]}
+
+% used for prototypine \Uskewed
+%
+% \unexpanded\def\skewedfractiona#1#2{%
+% \raise
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax$%
+% \egroup
+% \hbox to \zeropoint\bgroup
+% \hss$\textstyle/$\hss
+% \egroup
+% \lower
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax\scriptstyle#2$%
+% \egroup
+% }
+%
+% \unexpanded\def\skewedfractionb#1#2{%
+% \raise
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax$%
+% \egroup
+% \hbox to \zeropoint\bgroup
+% \hss$\textstyle/$\hss
+% \egroup
+% \lower
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax\scriptstyle#2$%
+% \egroup
+% }
+%
+% $\skewedfractiona{1}{2}$
+% $\skewedfractionb{1}{2}$
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua
new file mode 100644
index 00000000000..e6a35c39ee7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua
@@ -0,0 +1,712 @@
+if not modules then modules = { } end modules ['math-ini'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- if needed we can use the info here to set up xetex definition files
+-- the "8000 hackery influences direct characters (utf) as indirect \char's
+--
+-- isn't characters.data loaded already ... shortcut it here
+--
+-- replace code 7 by 0 as we don't use it anyway (chars with code 7 will adapt to
+-- to the fam when set ... we use other means .. ok, we could use it for spacing but
+-- then we also have to set the other characters (only a subset done now)
+
+local formatters, find = string.formatters, string.find
+local utfchar, utfbyte, utflength = utf.char, utf.byte, utf.length
+local floor = math.floor
+local toboolean = toboolean
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local context_sprint = context.sprint
+----- context_fprint = context.fprint -- a bit inefficient
+local ctx_doifelsesomething = commands.doifelsesomething
+
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+
+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
+
+local unsetvalue = attributes.unsetvalue
+local allocate = utilities.storage.allocate
+local chardata = characters.data
+
+local texsetattribute = tex.setattribute
+local setmathcode = tex.setmathcode
+local setdelcode = tex.setdelcode
+
+local families = allocate {
+ mr = 0,
+ mb = 1,
+}
+
+--- to be checked .. afew defaults in char-def that should be alpha
+
+local classes = allocate {
+ ord = 0, -- mathordcomm mathord
+ op = 1, -- mathopcomm mathop
+ bin = 2, -- mathbincomm mathbin
+ rel = 3, -- mathrelcomm mathrel
+ open = 4, -- mathopencomm mathopen
+ middle = 4,
+ close = 5, -- mathclosecomm mathclose
+ punct = 6, -- mathpunctcomm mathpunct
+ alpha = 7, -- mathalphacomm firstofoneargument
+ accent = 8, -- class 0
+ radical = 9,
+ xaccent = 10, -- class 3
+ topaccent = 11, -- class 0
+ botaccent = 12, -- class 0
+ under = 13,
+ over = 14,
+ delimiter = 15,
+ inner = 0, -- mathinnercomm mathinner
+ nothing = 0, -- mathnothingcomm firstofoneargument
+ choice = 0, -- mathchoicecomm @@mathchoicecomm
+ box = 0, -- mathboxcomm @@mathboxcomm
+ limop = 1, -- mathlimopcomm @@mathlimopcomm
+ nolop = 1, -- mathnolopcomm @@mathnolopcomm
+ --
+ ordinary = 0, -- ord
+ alphabetic = 7, -- alpha
+ unknown = 0, -- nothing
+ default = 0, -- nothing
+ punctuation = 6, -- punct
+ normal = 0, -- nothing
+ opening = 4, -- open
+ closing = 5, -- close
+ binary = 2, -- bin
+ relation = 3, -- rel
+ fence = 0, -- unknown
+ diacritic = 8, -- accent
+ large = 1, -- op
+ variable = 7, -- alphabetic
+ number = 7, -- alphabetic
+ root = 16, -- a private one
+}
+
+local open_class = 4
+local middle_class = 4
+local close_class = 5
+
+local accents = allocate {
+ accent = true, -- some can be both
+ topaccent = true, [11] = true,
+ botaccent = true, [12] = true,
+ under = true, [13] = true,
+ over = true, [14] = true,
+ unknown = false,
+}
+
+local codes = allocate {
+ ordinary = 0, [0] = "ordinary",
+ largeoperator = 1, [1] = "largeoperator",
+ binaryoperator = 2, [2] = "binaryoperator",
+ relation = 3, [3] = "relation",
+ openingsymbol = 4, [4] = "openingsymbol",
+ closingsymbol = 5, [5] = "closingsymbol",
+ punctuation = 6, [6] = "punctuation",
+ variable = 7, [7] = "variable",
+}
+
+local extensibles = allocate {
+ unknown = 0,
+ l = 1, left = 1,
+ r = 2, right = 2,
+ h = 3, horizontal = 3,-- lr or rl
+ u = 5, up = 4,
+ d = 5, down = 5,
+ v = 6, vertical = 6,-- ud or du
+ m = 7, mixed = 7,
+}
+
+table.setmetatableindex(extensibles,function(t,k) t[k] = 0 return 0 end)
+
+mathematics.extensibles = extensibles
+mathematics.classes = classes
+mathematics.codes = codes
+-----------.accents = codes
+mathematics.families = families
+
+-- there will be proper functions soon (and we will move this code in-line)
+-- no need for " in class and family (saves space)
+
+local function mathchar(class,family,slot)
+ return formatters['\\Umathchar "%X "%X "%X '](class,family,slot)
+end
+
+local function mathaccent(class,family,slot)
+ return formatters['\\Umathaccent "%X "%X "%X '](0,family,slot) -- no class
+end
+
+local function delimiter(class,family,slot)
+ return formatters['\\Udelimiter "%X "%X "%X '](class,family,slot)
+end
+
+local function radical(family,slot)
+ return formatters['\\Uradical "%X "%X '](family,slot)
+end
+
+local function root(family,slot)
+ return formatters['\\Uroot "%X "%X '](family,slot)
+end
+
+local function mathchardef(name,class,family,slot)
+ return formatters['\\Umathchardef\\%s "%X "%X "%X '](name,class,family,slot)
+end
+
+local function mathcode(target,class,family,slot)
+ return formatters['\\Umathcode%s="%X "%X "%X '](target,class,family,slot)
+end
+
+local function mathtopaccent(class,family,slot)
+ return formatters['\\Umathaccent "%X "%X "%X '](0,family,slot) -- no class
+end
+
+local function mathbotaccent(class,family,slot)
+ return formatters['\\Umathaccent bottom "%X "%X "%X '](0,family,slot) -- no class
+end
+
+local function mathtopdelimiter(class,family,slot)
+ return formatters['\\Udelimiterover "%X "%X '](family,slot) -- no class
+end
+
+local function mathbotdelimiter(class,family,slot)
+ return formatters['\\Udelimiterunder "%X "%X '](family,slot) -- no class
+end
+
+local escapes = characters.filters.utf.private.escapes
+
+-- not that many so no need to reuse tables
+
+local setmathcharacter = function(class,family,slot,unicode,mset,dset)
+ if mset and codes[class] then -- regular codes < 7
+ setmathcode("global",slot,{class,family,unicode})
+ mset = false
+ end
+ if dset and class == open_class or class == close_class or class == middle_class then
+ setdelcode("global",slot,{family,unicode,0,0})
+ dset = false
+ end
+ return mset, dset
+end
+
+local f_accent = formatters[ [[\ugdef\%s{\Umathaccent 0 "%X "%X }]] ]
+local f_topaccent = formatters[ [[\ugdef\%s{\Umathaccent 0 "%X "%X }]] ]
+local f_botaccent = formatters[ [[\ugdef\%s{\Umathbotaccent 0 "%X "%X }]] ]
+local f_over = formatters[ [[\ugdef\%s{\Udelimiterover "%X "%X }]] ]
+local f_under = formatters[ [[\ugdef\%s{\Udelimiterunder "%X "%X }]] ]
+local f_fence = formatters[ [[\ugdef\%s{\Udelimiter "%X "%X "%X }]] ]
+local f_delimiter = formatters[ [[\ugdef\%s{\Udelimiter 0 "%X "%X }]] ]
+local f_radical = formatters[ [[\ugdef\%s{\Uradical "%X "%X }]] ]
+local f_root = formatters[ [[\ugdef\%s{\Uroot "%X "%X }]] ]
+----- f_char = formatters[ [[\ugdef\%s{\Umathchar "%X "%X "%X }]]
+local f_char = formatters[ [[\Umathchardef\%s "%X "%X "%X ]] ]
+
+local setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing
+ if class == classes.accent then
+ context_sprint(f_accent(name,family,slot))
+ elseif class == classes.topaccent then
+ context_sprint(f_topaccent(name,family,slot))
+ elseif class == classes.botaccent then
+ context_sprint(f_botaccent(name,family,slot))
+ elseif class == classes.over then
+ context_sprint(f_over(name,family,slot))
+ elseif class == classes.under then
+ context_sprint(f_under(name,family,slot))
+ elseif class == open_class or class == close_class or class == middle_class then
+ setdelcode("global",slot,{family,slot,0,0})
+ context_sprint(f_fence(name,class,family,slot))
+ elseif class == classes.delimiter then
+ setdelcode("global",slot,{family,slot,0,0})
+ context_sprint(f_delimiter(name,family,slot))
+ elseif class == classes.radical then
+ context_sprint(f_radical(name,family,slot))
+ elseif class == classes.root then
+ context_sprint(f_root(name,family,slot))
+ else
+ -- beware, open/close and other specials should not end up here
+ context_sprint(f_char(name,class,family,slot))
+ end
+end
+
+local function report(class,family,unicode,name)
+ local nametype = type(name)
+ if nametype == "string" then
+ report_math("class name %a, class %a, family %a, char %C, name %a",classname,class,family,unicode,name)
+ elseif nametype == "number" then
+ report_math("class name %a, class %a, family %a, char %C, number %U",classname,class,family,unicode,name)
+ else
+ report_math("class name %a, class %a, family %a, char %C", classname,class,family,unicode)
+ end
+end
+
+-- there will be a combined \(math)chardef (tracker)
+
+function mathematics.define(family)
+ family = family or 0
+ family = families[family] or family
+ local data = characters.data
+ for unicode, character in next, data do
+ local symbol = character.mathsymbol
+ local mset, dset = true, true
+ if symbol then
+ local other = data[symbol]
+ local class = other.mathclass
+ if class then
+ class = classes[class] or class -- no real checks needed
+ if trace_defining then
+ report(class,family,unicode,symbol)
+ end
+ mset, dset = setmathcharacter(class,family,unicode,symbol,mset,dset)
+ end
+ local spec = other.mathspec
+ if spec then
+ for i, m in next, spec do
+ local class = m.class
+ if class then
+ class = classes[class] or class -- no real checks needed
+ mset, dset = setmathcharacter(class,family,unicode,symbol,mset,dset)
+ end
+ end
+ end
+ end
+ local mathclass = character.mathclass
+ local mathspec = character.mathspec
+ if mathspec then
+ for i, m in next, mathspec do
+ local name = m.name
+ local class = m.class
+ if not class then
+ class = mathclass
+ elseif not mathclass then
+ mathclass = class
+ end
+ if class then
+ class = classes[class] or class -- no real checks needed
+ if name then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ setmathsymbol(name,class,family,unicode)
+ else
+ name = class == classes.variable or class == classes.number and character.adobename
+ if name and trace_defining then
+ report(class,family,unicode,name)
+ end
+ end
+ mset, dset = setmathcharacter(class,family,unicode,m.unicode or unicode,mset,dset) -- see solidus
+ end
+ end
+ end
+ if mathclass then
+ local name = character.mathname
+ local class = classes[mathclass] or mathclass -- no real checks needed
+ if name == false then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ mset, dset = setmathcharacter(class,family,unicode,mset,dset)
+ else
+ name = name or character.contextname
+ if name then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ setmathsymbol(name,class,family,unicode)
+ else
+ if trace_defining then
+ report(class,family,unicode,character.adobename)
+ end
+ end
+ mset, dset = setmathcharacter(class,family,unicode,unicode,mset,dset)
+ end
+ end
+ end
+end
+
+-- needed for mathml analysis
+-- string with # > 1 are invalid
+-- we could cache
+
+local lpegmatch = lpeg.match
+
+local utf8byte = lpeg.patterns.utf8byte * lpeg.P(-1)
+
+-- function somechar(c)
+-- local b = lpegmatch(utf8byte,c)
+-- return b and chardata[b]
+-- end
+
+
+local somechar = { }
+
+table.setmetatableindex(somechar,function(t,k)
+ if k then
+ local b = lpegmatch(utf8byte,k)
+ local v = b and chardata[b] or false
+ t[k] = v
+ return v
+ end
+end)
+
+local function utfmathclass(chr, default)
+ local cd = somechar[chr]
+ return cd and cd.mathclass or default or "unknown"
+end
+
+local function utfmathaccent(chr,default,asked1,asked2)
+ local cd = somechar[chr]
+ if not cd then
+ return default or false
+ end
+ if asked1 and asked1 ~= "" then
+ local mc = cd.mathclass
+ if mc and (mc == asked1 or mc == asked2) then
+ return true
+ end
+ local ms = cd.mathspec
+ if not ms then
+ local mp = cd.mathparent
+ if mp then
+ ms = chardata[mp].mathspec
+ end
+ end
+ if ms then
+ for i=1,#ms do
+ local msi = ms[i]
+ local mc = msi.class
+ if mc and (mc == asked1 or mc == asked2) then
+ return true
+ end
+ end
+ end
+ else
+ local mc = cd.mathclass
+ if mc then
+ return accents[mc] or default or false
+ end
+ local ms = cd.mathspec
+ if ms then
+ for i=1,#ms do
+ local msi = ms[i]
+ local mc = msi.class
+ if mc then
+ return accents[mc] or default or false
+ end
+ end
+ end
+ end
+ return default or false
+end
+
+local function utfmathstretch(chr,default) -- "h", "v", "b", ""
+ local cd = somechar[chr]
+ return cd and cd.mathstretch or default or ""
+end
+
+local function utfmathcommand(chr,default,asked1,asked2)
+ local cd = somechar[chr]
+ if not cd then
+ return default or ""
+ end
+ if asked1 then
+ local mn = cd.mathname
+ local mc = cd.mathclass
+ if mn and mc and (mc == asked1 or mc == asked2) then
+ return mn
+ end
+ local ms = cd.mathspec
+ if not ms then
+ local mp = cd.mathparent
+ if mp then
+ ms = chardata[mp].mathspec
+ end
+ end
+ if ms then
+ for i=1,#ms do
+ local msi = ms[i]
+ local mn = msi.name
+ if mn then
+ local mc = msi.class
+ if mc == asked1 or mc == asked2 then
+ return mn
+ end
+ end
+ end
+ end
+ else
+ local mn = cd.mathname
+ if mn then
+ return mn
+ end
+ local ms = cd.mathspec
+ if ms then
+ for i=1,#ms do
+ local msi = ms[i]
+ local mn = msi.name
+ if mn then
+ return mn
+ end
+ end
+ end
+ end
+ return default or ""
+end
+
+local function utfmathfiller(chr, default)
+ local cd = somechar[chr]
+ local cmd = cd and cd.mathfiller -- or cd.mathname
+ return cmd or default or ""
+end
+
+mathematics.utfmathclass = utfmathclass
+mathematics.utfmathstretch = utfmathstretch
+mathematics.utfmathcommand = utfmathcommand
+mathematics.utfmathfiller = utfmathfiller
+mathematics.utfmathaccent = utfmathaccent
+
+-- interfaced
+
+implement {
+ name = "utfmathclass",
+ actions = { utfmathclass, context },
+ arguments = "string"
+}
+
+implement {
+ name = "utfmathstretch",
+ actions = { utfmathstretch, context },
+ arguments = "string"
+}
+
+implement {
+ name = "utfmathcommand",
+ actions = { utfmathcommand, context },
+ arguments = "string"
+}
+
+implement {
+ name = "utfmathfiller",
+ actions = { utfmathfiller, context },
+ arguments = "string"
+}
+
+implement {
+ name = "utfmathcommandabove",
+ actions = { utfmathcommand, context },
+ arguments = { "string", false, "'topaccent'","'over'" }
+}
+
+implement {
+ name = "utfmathcommandbelow",
+ actions = { utfmathcommand, context },
+ arguments = { "string", false, "'botaccent'","'under'" }
+}
+implement {
+ name = "utfmathcommandfiller",
+ actions = { utfmathfiller, context },
+ arguments = "string"
+}
+
+-- todo: make this a helper:
+
+implement {
+ name = "doifelseutfmathabove",
+ actions = { utfmathaccent, ctx_doifelsesomething },
+ arguments = { "string", false, "'topaccent'", "'over'" }
+}
+
+implement {
+ name = "doifelseutfmathbelow",
+ actions = { utfmathaccent, ctx_doifelsesomething },
+ arguments = { "string", false, "'botaccent'", "'under'" }
+}
+
+implement {
+ name = "doifelseutfmathaccent",
+ actions = { utfmathaccent, ctx_doifelsesomething },
+ arguments = "string",
+}
+
+implement {
+ name = "doifelseutfmathfiller",
+ actions = { utfmathfiller, ctx_doifelsesomething },
+ arguments = "string",
+}
+
+-- helpers
+--
+-- 1: step 1
+-- 2: step 2
+-- 3: htdp * 1.33^n
+-- 4: size * 1.33^n
+
+function mathematics.big(tfmdata,unicode,n,method)
+ local t = tfmdata.characters
+ local c = t[unicode]
+ if c and n > 0 then
+ local vv = c.vert_variants or c.next and t[c.next].vert_variants
+ if vv then
+ local vvn = vv[n]
+ return vvn and vvn.glyph or vv[#vv].glyph or unicode
+ elseif method == 1 or method == 2 then
+ if method == 2 then -- large steps
+ n = n * 2
+ end
+ local next = c.next
+ while next do
+ if n <= 1 then
+ return next
+ else
+ n = n - 1
+ local tn = t[next].next
+ if tn then
+ next = tn
+ else
+ return next
+ end
+ end
+ end
+ else
+ local size = 1.33^n
+ if method == 4 then
+ size = tfmdata.parameters.size * size
+ else -- if method == 3 then
+ size = (c.height + c.depth) * size
+ end
+ local next = c.next
+ while next do
+ local cn = t[next]
+ if (cn.height + cn.depth) >= size then
+ return next
+ else
+ local tn = cn.next
+ if tn then
+ next = tn
+ else
+ return next
+ end
+ end
+ end
+ end
+ end
+ return unicode
+end
+
+-- experimental
+
+-- local categories = { } -- indexed + hashed
+--
+-- local a_mathcategory = attributes.private("mathcategory")
+--
+-- local function registercategory(category,tag,data) -- always same data for tag
+-- local c = categories[category]
+-- if not c then
+-- c = { }
+-- categories[category] = c
+-- end
+-- local n = c[tag]
+-- if not n then
+-- n = #c + 1
+-- c[n] = data
+-- n = n * 1000 + category
+-- c[tag] = n
+-- end
+-- return n
+-- end
+--
+-- function mathematics.getcategory(n)
+-- local category = n % 1000
+-- return category, categories[category][floor(n/1000)]
+-- end
+--
+-- mathematics.registercategory = registercategory
+--
+-- function commands.taggedmathfunction(tag,label)
+-- if label then
+-- texsetattribute(a_mathcategory,registercategory(1,tag,tag))
+-- context.mathlabeltext(tag)
+-- else
+-- texsetattribute(a_mathcategory,1)
+-- context(tag)
+-- end
+-- end
+
+local categories = { }
+mathematics.categories = categories
+
+local a_mathcategory = attributes.private("mathcategory")
+
+local functions = storage.allocate()
+local noffunctions = 1000 -- offset
+
+categories.functions = functions
+
+implement {
+ name = "tagmfunctiontxt",
+ arguments = { "string", "conditional" },
+ actions = function(tag,apply)
+ local delta = apply and 1000 or 0
+ texsetattribute(a_mathcategory,1000 + delta)
+ end
+}
+
+implement {
+ name = "tagmfunctionlab",
+ arguments = { "string", "conditional" },
+ actions = function(tag,apply)
+ local delta = apply and 1000 or 0
+ local n = functions[tag]
+ if not n then
+ noffunctions = noffunctions + 1
+ functions[noffunctions] = tag
+ functions[tag] = noffunctions
+ texsetattribute(a_mathcategory,noffunctions + delta)
+ else
+ texsetattribute(a_mathcategory,n + delta)
+ end
+ end
+}
+
+--
+
+local list
+
+function mathematics.resetattributes()
+ if not list then
+ list = { }
+ for k, v in next, attributes.numbers do
+ if find(k,"^math") then
+ list[#list+1] = v
+ end
+ end
+ end
+ for i=1,#list do
+ texsetattribute(list[i],unsetvalue)
+ end
+end
+
+implement {
+ name = "resetmathattributes",
+ actions = mathematics.resetattributes
+}
+
+-- weird to do this here but it's a side affect of math anyway
+
+interfaces.implement {
+ name = "enableasciimode",
+ onlyonce = true,
+ actions = resolvers.macros.enablecomment,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv
new file mode 100644
index 00000000000..8627436b7bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv
@@ -0,0 +1,2424 @@
+%D \module
+%D [ file=math-ini,
+%D version=2008.01.02,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Initializations}
+
+% todo: hpack as we skip math anyway
+%
+% todo: 0x2061 : function application
+% todo: 0x2062 : invisible times
+% todo: 0x2063 : invisible comma
+
+% Todo in luatex maincontrol.w: also accept a number here:
+%
+% case set_math_param_cmd:
+% p = cur_chr;
+% get_token();
+% if (cur_cmd != math_style_cmd) {
+%
+% plus two new math styles: larger/smaller
+%
+% \unexpanded\def\Umathshow#1%
+% {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}}
+
+%D This module provides namespaces for math fonts, thereby permitting mixed usage of
+%D math fonts. Although not strictly needed, we also provide a family name mapping
+%D mechanism as used in the (original) AMS math definition files, but here these
+%D names can recursively be remapped and if needed, dynamically be changed. We've
+%D tried to minimize the number of definition commands and use plain \TEX\
+%D definitions as fallback. We've tried to follow a couple of conventions from plain
+%D and AMS math in order to achieve backward compatinility. We also kept an eye on
+%D future usage of these modules in the perspective of MathML and unicode fonts.
+
+%D There is a subtle issue with grouping: the \type {\begingroup} method will not
+%D restore a changed mathstyle so best avoid that one. However, there are cases where
+%D we really need to use such grouping.
+
+% Weird, these fail, maybe amp is solved in a later state from char noads (needs a
+% fix in luatex):
+%
+% $\char"26$
+% $\a$
+% $\string&$
+
+% mathop applied to characters centers it vertically
+
+\unprotect
+
+%D We move these definitions into the format:
+
+% test [[\char948 \cldcontext{utf.char(948)}]]
+% test $[[\char948 \cldcontext{utf.char(948)}]]$
+
+\registerctxluafile{math-ini}{1.001}
+\registerctxluafile{math-dim}{1.001}
+\registerctxluafile{math-act}{1.001}
+\registerctxluafile{math-ext}{1.001}
+\registerctxluafile{math-vfu}{1.001}
+\registerctxluafile{math-ttv}{1.001}
+\registerctxluafile{math-map}{1.001}
+\registerctxluafile{math-ren}{1.001}
+\registerctxluafile{math-noa}{1.001}
+\registerctxluafile{math-tag}{1.001}
+\registerctxluafile{math-fbk}{1.001}
+\registerctxluafile{math-dir}{1.001}
+
+%D A few compatibility helpers:
+
+\def\Umathbotaccent{\Umathaccent \s!bottom }
+\def\Umathaccents {\Umathaccent \s!both }
+
+\ifdefined\Umathcharclass \else
+ \def\Umathcharclass{\cldcontext{tex.getmathcode(token.scan_int())[1]}}
+ \def\Umathcharfam {\cldcontext{tex.getmathcode(token.scan_int())[2]}}
+ \def\Umathcharslot {\cldcontext{tex.getmathcode(token.scan_int())[3]}}
+\fi
+
+%D The attributes that we will use:
+
+\definesystemattribute[mathalphabet] [public]
+\definesystemattribute[mathsize] [public]
+\definesystemattribute[mathpunctuation][public]
+\definesystemattribute[mathgreek] [public] % will become generic
+\definesystemattribute[mathalternate] [public]
+\definesystemattribute[mathrendering] [public]
+\definesystemattribute[mathcategory] [public]
+\definesystemattribute[mathmode] [public]
+\definesystemattribute[mathitalics] [public]
+\definesystemattribute[mathbidi] [public]
+\definesystemattribute[mathdomain] [public]
+
+\definesystemattribute[displaymath] [public]
+
+\appendtoks
+ \attribute\mathmodeattribute\plusone
+\to \everydisplay
+
+\appendtoks
+ \attribute\mathmodeattribute\plusone
+\to \everybeforedisplayformula
+
+\appendtoksonce
+ \attribute\displaymathattribute\plusone
+\to \everybeforedisplayformula
+
+\setnewconstant\defaultmathfamily \zerocount % 255
+
+\unexpanded\def\resetmathattributes{\clf_resetmathattributes}
+
+% handy
+
+\newconditional\indisplaymath
+
+\appendtoks
+ \setfalse\indisplaymath
+\to \everymath
+
+\appendtoks
+ \settrue\indisplaymath
+\to \everydisplay
+
+\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
+
+\unexpanded\def\forcedisplaymath
+ {\ifmmode
+ \displaystyle
+ \settrue\indisplaymath
+ \fi}
+
+\unexpanded\def\startforceddisplaymath
+ {\startimath
+ \displaystyle
+ \settrue\indisplaymath}
+
+\unexpanded\def\stopforceddisplaymath
+ {\stopimath}
+
+% \unexpanded\def\rawmathcharacter#1% slow but only for tracing
+% {\begingroup
+% \ifmmode
+% \resetmathattributes\Uchar#1%
+% \else
+% \startimath\resetmathattributes\Uchar#1\stopimath
+% \fi
+% \endgroup}
+
+\unexpanded\def\rawmathematics#1% slow but only for tracing
+ {\begingroup
+ \ifmmode
+ \clf_resetmathattributes#1%
+ \else
+ \startimath\clf_resetmathattributes#1\stopimath
+ \fi
+ \endgroup}
+
+%D Some measures (maybe spac-mth):
+
+% \def\mathskipsmall {\mskip\thinmuskip}
+% \def\mathskipmedium{\mskip\medmuskip}
+% \def\mathskipbig {\mskip\thickmuskip}
+
+%D \macros
+%D {setupmathematics}
+%D
+%D Configuration for integrals. (If needed we can speed this up and make it
+%D installable; no processaction is needed then).
+
+\installcorenamespace{mathematics}
+
+\installswitchcommandhandler \??mathematics {mathematics} \??mathematics
+
+\unexpanded\def\startmathematics % no grouping, if ever then also an optional second
+ {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop}
+
+\unexpanded\def\math_mathematics_start_yes[#1]%
+ {\pushmacro\currentmathematics
+ \edef\currentmathematics{#1}% check for valid
+ \the\everyswitchmathematics}
+
+\unexpanded\def\math_mathematics_start_nop
+ {\pushmacro\currentmathematics
+ \let\currentmathematics\empty
+ \the\everyswitchmathematics}
+
+\unexpanded\def\stopmathematics
+ {\popmacro\currentmathematics
+ \the\everyswitchmathematics}
+
+\definemathematics[\v!default] % not needed, but nicer when nesting back to normal
+
+% Now we redefine \type {\mathematics} and \type {\m}:
+
+\unexpanded\def\mathematics
+ {\doifelsenextoptionalcs\math_m_yes\math_m_nop}
+
+\def\math_m_yes
+ {\relax
+ \ifmmode
+ \expandafter\math_m_yes_math
+ \else
+ \expandafter\math_m_yes_text
+ \fi}
+
+\def\math_m_yes_math[#1]#2%
+ {#2}
+
+\def\math_m_yes_text[#1]%
+ {\begingroup
+ \edef\currentmathematics{#1}% check for valid
+ \edef\p_openup{\mathematicsparameter\c!openup}%
+ \ifx\p_openup\v!yes
+ \expandafter\math_m_yes_text_openedup
+ \else
+ \expandafter\math_m_yes_text_normal
+ \fi}
+
+\def\math_m_yes_text_openedup#1%
+ {\setbox\scratchbox\hbox\bgroup
+ \normalstartimath
+ \the\everyswitchmathematics\relax
+ #1%
+ \normalstopimath
+ \egroup
+ \ifdim\ht\scratchbox>\strutht
+ \math_inline_openup_start_yes
+ \else\ifdim\dp\scratchbox>\strutdp
+ \math_inline_openup_start_yes
+ \else
+ \math_inline_openup_start_nop
+ \fi\fi
+ \unhbox\scratchbox % \normalstartimath#1\normalstopimath
+ \math_inline_openup_stop
+ \endgroup}
+
+\def\math_m_yes_text_normal#1%
+ {\normalstartimath
+ \the\everyswitchmathematics\relax
+ #1%
+ \normalstopimath
+ \endgroup}
+
+\def\math_m_nop#1%
+ {\relax
+ \ifmmode
+ #1%
+ \else
+ \normalstartimath
+ #1%
+ \normalstopimath
+ \fi}
+
+\let\m \mathematics
+\let\math\mathematics
+
+% e.g.: \definemathematics[i:mp][setups=i:tight,openup=yes]
+
+\newmuskip\defaultthickmuskip \defaultthickmuskip 5mu plus 5mu
+\newmuskip\defaultmedmuskip \defaultmedmuskip 4mu plus 2mu minus 4mu
+\newmuskip\defaultthinmuskip \defaultthinmuskip 3mu
+
+\newmuskip\halfthickmuskip \halfthickmuskip 2.5mu plus 2.5mu
+\newmuskip\halfmedmuskip \halfmedmuskip 2.0mu plus 1.0mu minus 2.0mu
+\newmuskip\halfthinmuskip \halfthinmuskip 1.5mu
+
+\newcount \defaultrelpenalty \defaultrelpenalty 500
+\newcount \defaultbinoppenalty \defaultbinoppenalty 700
+
+\startsetups math:spacing:default
+ \thickmuskip \defaultthickmuskip
+ \medmuskip \defaultmedmuskip
+ \thinmuskip \defaultthinmuskip
+ \relpenalty \defaultrelpenalty
+ \binoppenalty \defaultbinoppenalty
+\stopsetups
+
+\startsetups math:spacing:half
+ \thickmuskip \halfthickmuskip
+ \medmuskip \halfmedmuskip
+ \thinmuskip \halfthinmuskip
+ \relpenalty \defaultrelpenalty
+ \binoppenalty \defaultbinoppenalty
+\stopsetups
+
+\startsetups math:spacing:tight
+ \ifcase\raggedstatus
+ \thickmuskip \halfthickmuskip
+ \medmuskip \halfmedmuskip
+ \thinmuskip \halfthinmuskip
+ \else
+ \thickmuskip 1\halfthickmuskip
+ \medmuskip 1\halfmedmuskip
+ \thinmuskip 1\halfthinmuskip
+ \fi
+ \relpenalty \defaultrelpenalty
+ \binoppenalty \maxdimen
+\stopsetups
+
+\startsetups math:spacing:fixed
+ \ifcase\raggedstatus
+ \thickmuskip \halfthickmuskip
+ \medmuskip \halfmedmuskip
+ \thinmuskip \halfthinmuskip
+ \else
+ \thickmuskip 1\halfthickmuskip
+ \medmuskip 1\halfmedmuskip
+ \thinmuskip 1\halfthinmuskip
+ \fi
+ \relpenalty \maxdimen
+ \binoppenalty \maxdimen
+\stopsetups
+
+% \dorecurse{80}{test \m[i:tight]{\red \fakeformula} test }
+
+\definemathematics[i:default][\c!setups=math:spacing:equal]
+\definemathematics[i:half] [\c!setups=math:spacing:half]
+\definemathematics[i:tight] [\c!setups=math:spacing:tight]
+\definemathematics[i:fixed] [\c!setups=math:spacing:fixed]
+
+% Normally the next is applied to only one character.
+%
+% $ABC$ $\cal ABC$ $\mathaltcal ABC$
+
+% todo: only in mmode
+% these commands are semi-public but should not be used directly (lua names wil change)
+
+\unexpanded\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
+\unexpanded\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi}
+\unexpanded\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi}
+\unexpanded\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi}
+
+\installcorenamespace{mathstylealternate} % might become a setuphandler
+
+\unexpanded\def\math_set_font_style_alternate#1%
+ {\ifcsname\??mathstylealternate\fontclass:#1\endcsname
+ %\expandafter\math_set_font_alternate\csname\??mathstylealternate\fontclass:#1\endcsname
+ \expandafter\math_set_font_alternate\lastnamedcs
+ \else\ifcsname\??mathstylealternate#1\endcsname
+ %\expandafter\math_set_font_alternate\csname\??mathstylealternate#1\endcsname
+ \expandafter\math_set_font_alternate\lastnamedcs
+ \fi\fi}
+
+\unexpanded\def\setupmathrendering % the name might change
+ {\dodoubleargument\math_setup_rendering}
+
+\def\math_setup_rendering[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??mathstylealternate#1:][#2]%
+ \else
+ \getparameters[\??mathstylealternate][#1]%
+ \fi}
+
+% if there were many features we could have a feature pass over math nodes but it makes no
+% sense now so we have commands to deal with it
+
+\unexpanded\def\mathaltcal {\math_set_font_alternate{cal}\cal} % set via goody file
+%unexpanded\def\mathslashedzero {\math_set_font_alternate{zero}0} % set via goody file or automatic
+\unexpanded\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic
+\unexpanded\def\mathdotlessi {{\mathdotless i}}
+\unexpanded\def\mathdotlessj {{\mathdotless j}}
+
+%let\textslashedzero\slashedzero \unexpanded\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero}
+\let\textdotlessi \dotlessi \unexpanded\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi}
+\let\textdotlessj \dotlessj \unexpanded\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj}
+
+\appendtoks
+ %let\slashedzero\autoslashedzero
+ \let\dotlessi \autodotlessi
+ \let\dotlessj \autodotlessj
+\to \everymathematics
+
+\let\setmathattribute \math_set_attribute
+\let\setmathalphabet \math_set_alphabet
+\let\setmathfontstyle \math_set_font_style
+\let\setmathfontalternate \math_set_font_alternate
+\let\setmathfontstylealternate\math_set_font_style_alternate
+
+\let\mathalternate \math_set_font_alternate
+
+\unexpanded\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf}
+\unexpanded\def\mathdefault {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it}
+\unexpanded\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script}
+\unexpanded\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur}
+\unexpanded\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\s!blackboard}
+
+\unexpanded\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf}
+\unexpanded\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf}
+\unexpanded\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\s!tf}
+
+\unexpanded\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf}
+\unexpanded\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl
+\unexpanded\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\s!it}
+
+\unexpanded\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf}
+\unexpanded\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl
+\unexpanded\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi}
+
+\let\tfmath\mathtf % maybe a grouped command
+\let\slmath\mathsl
+\let\itmath\mathit
+
+\let\bfmath\mathbf
+\let\bsmath\mathbs
+\let\bimath\mathbi
+
+\let\Bbb\mathblackboard
+
+\unexpanded\def\frak {\ifmmode\expandafter\mathfraktur \fi}
+\unexpanded\def\cal {\ifmmode\expandafter\mathscript \fi}
+\unexpanded\def\bbd {\ifmmode\expandafter\mathblackboard\fi}
+\unexpanded\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
+\unexpanded\def\fraktur {\ifmmode\expandafter\mathfraktur \fi}
+\unexpanded\def\gothic {\ifmmode\expandafter\mathfraktur \fi}
+
+\unexpanded\def\mathcal #1{{\mathscript #1}} % for AMS compatibility
+\unexpanded\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility
+\unexpanded\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility
+
+\ifdefined\normaltf\else\let\normaltf\tf\fi \unexpanded\def\tf{\ifmmode\mathtf\else\normaltf\fi}
+\ifdefined\normalbf\else\let\normalbf\bf\fi \unexpanded\def\bf{\ifmmode\mathbf\else\normalbf\fi}
+\ifdefined\normalit\else\let\normalit\it\fi \unexpanded\def\it{\ifmmode\mathit\else\normalit\fi}
+\ifdefined\normalsl\else\let\normalsl\sl\fi \unexpanded\def\sl{\ifmmode\mathsl\else\normalsl\fi}
+\ifdefined\normalbi\else\let\normalbi\bi\fi \unexpanded\def\bi{\ifmmode\mathbi\else\normalbi\fi}
+\ifdefined\normalbs\else\let\normalbs\bs\fi \unexpanded\def\bs{\ifmmode\mathbs\else\normalbs\fi}
+
+\let\normalrm\rm \unexpanded\def\rm{\ifmmode\mathrm\else\normalrm\fi}
+\let\normalss\ss \unexpanded\def\ss{\ifmmode\mathss\else\normalss\fi}
+\let\normaltt\tt \unexpanded\def\tt{\ifmmode\mathtt\else\normaltt\fi}
+
+\ifdefined\mr \else \let\mr\relax \fi
+\ifdefined\mb \else \let\mb\relax \fi
+
+% 1: $\setmathattribute{ss}{bf}3$
+% 2: $\setmathattribute{ss}{bf}\setmathfontstylealternate{bf}3$
+% 3: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}3$
+% 4: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}\setmathfontstylealternate{bf}3$
+% 5: $e=mc^2 \quad \mb e=mc^2$
+
+\prependtoks
+ \mathdefault
+\to \everymathematics
+
+%D We could set the rendering attribute at the \LUA\ end but as there can be many
+%D small math snippets we keep track of the state at the \TEX\ end (mapping is
+%D export safe).
+%D
+%D \starttyping
+%D \startformula
+%D \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
+%D \stopformula
+%D
+%D \setupmathematics
+%D [symbolset=blackboard-to-bold]
+%D
+%D \startformula
+%D \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
+%D \stopformula
+%D \stoptyping
+
+\newcount\c_math_renderings_attribute
+
+\appendtoks
+ \c_math_renderings_attribute\clf_mathrenderset{\mathematicsparameter\c!symbolset}\relax
+\to \everysetupmathematics % only in mathematics
+
+\appendtoks
+ \ifcase\c_math_renderings_attribute\else
+ \attribute\mathrenderingattribute\c_math_renderings_attribute
+ \fi
+\to \everymathematics
+
+\setupmathematics
+ [\c!symbolset=]
+
+%D \macros
+%D {boldsymbol}
+%D
+%D To be done.
+
+\let\mathboldsymbol\relax % yet unsupported, will be
+
+\unexpanded\def\boldsymbol
+ {\mathortext\mathboldsymbol\bold}
+
+%D Helpers
+
+\def\utfmathclass #1{\clf_utfmathclass {#1}}
+\def\utfmathstretch#1{\clf_utfmathstretch{#1}}
+\def\utfmathcommand#1{\clf_utfmathcommand{#1}}
+\def\utfmathfiller #1{\clf_utfmathfiller {#1}}
+
+\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}}
+\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}}
+\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}}
+
+\unexpanded\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}}
+\unexpanded\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}}
+\unexpanded\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}}
+\unexpanded\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}}
+
+\let\doifutfmathaccentelse \doifelseutfmathaccent
+\let\doifutfmathaboveelse \doifelseutfmathabove
+\let\doifutfmathbelowelse \doifelseutfmathbelow
+\let\doifutfmathfillerelse \doifelseutfmathfiller
+
+%D Not used that much:
+
+\installcorenamespace{mathcodecommand}
+
+\unexpanded\def\mathlimop#1{\mathop{#1}} %no \limits
+\unexpanded\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
+\unexpanded\def\mathnolop#1{\mathop{#1}\nolimits}
+
+\let\mathnothing\firstofoneunexpanded
+\let\mathalpha \firstofoneunexpanded
+
+\setnewconstant\mathordcode \zerocount \letvalue{\??mathcodecommand ord}\mathord
+\setnewconstant\mathopcode \plusone \letvalue{\??mathcodecommand op}\mathop
+\setnewconstant\mathbincode \plustwo \letvalue{\??mathcodecommand bin}\mathbin
+\setnewconstant\mathrelcode \plusthree \letvalue{\??mathcodecommand rel}\mathrel
+\setnewconstant\mathopencode \plusfour \letvalue{\??mathcodecommand open}\mathopen
+\setnewconstant\mathclosecode \plusfive \letvalue{\??mathcodecommand close}\mathclose
+\setnewconstant\mathpunctcode \plussix \letvalue{\??mathcodecommand punct}\mathpunct
+\setnewconstant\mathalphacode \plusseven \letvalue{\??mathcodecommand alpha}\mathalpha
+\setnewconstant\mathinnercode \zerocount \letvalue{\??mathcodecommand inner}\mathinner
+\setnewconstant\mathnothingcode \zerocount \letvalue{\??mathcodecommand nothing}\mathnothing
+\setnewconstant\mathlimopcode \plusone \letvalue{\??mathcodecommand limop}\mathlimop
+\setnewconstant\mathnolopcode \plusone \letvalue{\??mathcodecommand nolop}\mathnolop
+\setnewconstant\mathboxcode \zerocount \letvalue{\??mathcodecommand box}\mathbox
+\setnewconstant\mathchoicecode \zerocount %letvalue{\??mathcodecommand choice}\mathnothing
+
+\setnewconstant\mathaccentcode \pluseight
+\setnewconstant\mathradicalcode \plusnine
+
+ \def\mathcodenumber #1{\the\csname math#1code\endcsname}
+\unexpanded\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}
+
+% \startlines
+% $\mathopnolimits{\rm d}x$
+% $\mathopnolimits{\kern\zeropoint \rm d}x$
+% $\mathcodecommand{nolop}{\rm d}x$
+% $\mathcodecommand{nolop}{\kern\zeropoint\rm d}x$
+% \blank
+% $\mathcodecommand{nolop}{\mr d}x$
+% $\mathcodecommand{nolop}{\kern\zeropoint\mr d}x$
+% $\mathop{\kern\zeropoint\mr d}x$
+% $\mathopnolimits{\kern\zeropoint d}x$
+% \stoplines
+
+\installcorenamespace{mathcommand}
+
+\unexpanded\def\definemathcommand
+ {\dotripleempty\math_define_command}
+
+\def\math_define_command[#1][#2][#3]#4% command class args meaning
+ {\ifthirdargument
+ \edef\nofmathcommandarguments{#3}%
+ \ifx\nofmathcommandarguments\v!one
+ \setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}%
+ \else\ifx\nofmathcommandarguments\v!two
+ \setuvalue{\??mathcommand#1}##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
+ \else
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
+ \fi\fi
+ \else\ifsecondargument
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
+ \else
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}%
+ \fi\fi
+ \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname}
+
+\unexpanded\def\mathcommand#1%
+ {\csname\??mathcommand#1\endcsname}
+
+%D Let's define a few comands here:
+
+%definemathcommand [mathstrut] {\vphantom{(}}
+%definemathcommand [joinrel] {\mathrel{\mkern-3mu}}
+\definemathcommand [joinrel] [rel] {\mkern-3mu}
+
+\chardef\c_math_strut"28
+
+\unexpanded\def\math_strut_htdp#1%
+ {\s!height\fontcharht#1\c_math_strut
+ \s!depth \fontchardp#1\c_math_strut}
+
+\unexpanded\def\math_strut_normal
+ {\vrule
+ \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
+ \s!width \zeropoint
+ \relax}
+
+\unexpanded\def\math_strut_visual
+ {\hskip-.01\emwidth
+ \vrule
+ \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
+ \s!width .02\emwidth
+ \relax
+ \hskip-.01\emwidth}
+
+\unexpanded\def\showmathstruts % let's not overload \math_strut_normal
+ {\let\math_strut\math_strut_visual}
+
+\let\math_strut\math_strut_normal
+
+% \unexpanded\def\mathstrut{\mathcodecommand{nothing}{\math_strut}}
+
+\definemathcommand [mathstrut] {\math_strut}
+
+%D We could have a arg variant \unknown\ but not now.
+
+\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
+\unexpanded\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
+
+%D Moved from font-ini.mkiv:
+%D
+%D \macros
+%D {mf,mbox,enablembox,mathop}
+%D
+%D Todo:
+
+\unexpanded\def\mf
+ {\begincsname\fontalternative\endcsname}
+
+% \let\normalmathop\mathop % already defined
+
+% no longer needed as we no longer switch fonts
+%
+% \unexpanded\def\mathop
+% {\normalmathop
+% \bgroup
+% % no: \let\rm\mf
+% \afterassignment\math_op\let\nexttoken=}
+%
+% \def\math_op{\ifx\nexttoken\bgroup\else\nexttoken\egroup\fi}
+
+
+% this one too: \letvalue{\??mathcodecommand op}\mathop ?
+
+\unexpanded\def\normalmbox
+ {\normalhbox\bgroup
+ \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new
+ \dowithnextboxcs\math_mbox_finish\normalhbox}
+
+\def\math_mbox_finish
+ {\flushnextbox
+ \egroup}
+
+\unexpanded\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
+ {\ifmmode\normalmbox\else\normalhbox\fi}
+
+\unexpanded\def\enablembox
+ {\appendtoks\math_enable_mbox\to \everymathematics}
+ {\everymathematics\expandafter{\the\everymathematics\math_enable_mbox}}
+
+\def\math_enable_mbox
+ {\ifdefined\normalhbox\else\let\normalhbox\hbox\fi % ?
+ \let\hbox\mbox}
+
+\unexpanded\def\snappedmath#1% sort of \struttedbox
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox\bgroup
+ \startimath#1\stopimath
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\mtext#1%
+ {\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}}
+
+%D The next hack is needed needed for sine, cosine etc.
+
+\let\mathfunction\firstofoneunexpanded
+
+\let\math_tags_function \firstofoneunexpanded
+\let\math_tags_functionlabeltext\mathlabeltext
+
+\let\math_tags_mo\firstofoneunexpanded
+\let\math_tags_mi\firstofoneunexpanded
+
+\unexpanded\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup}
+\unexpanded\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup}
+
+% Once this is stable we can store the number at the tex end which is
+% faster. Functions getnumbers >= 1000.
+
+% \setupmathematics[functionstyle=normal] % will give ligatures and kerning
+
+\setupmathematics
+ [\c!textstyle=, % rm ss etc i.e. known alternatives, otherwise math
+ \c!textcolor=,
+ \c!functionstyle=, % rm ss etc i.e. known alternatives, otherwise math
+ \c!functioncolor=]
+
+% \unexpanded\def\math_mfunction_styled
+% {\edef\m_math_text_choice_face{\textstyleface\normalmathstyle}%
+% \dowithnextbox
+% {\mathop{\box\nextbox}}%
+% \hbox\bgroup
+% \usemathematicsstyleandcolor\c!functionstyle\c!functioncolor
+% \m_math_text_choice_face
+% \let\next}
+
+\unexpanded\def\math_mfunction_styled
+ {\begingroup
+ \usemathematicscolorparameter\c!functioncolor
+ \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
+ \ifx\p_functionstyle\empty
+ \expandafter\math_mfunction_styled_none
+ \else\ifcsname\??alternativestyles\p_functionstyle\endcsname
+ \doubleexpandafter\math_mfunction_styled_text
+ \else
+ \doubleexpandafter\math_mfunction_styled_math
+ \fi\fi}
+
+\unexpanded\def\math_mfunction_styled_text#1%
+ {\mathoptext{\csname\??alternativestyles\p_functionstyle\endcsname#1}%
+ \endgroup}
+
+\unexpanded\def\math_mfunction_styled_math#1%
+ {\p_functionstyle
+ #1%
+ \endgroup}
+
+\unexpanded\def\math_mfunction_styled_none#1%
+ {\mathupright
+ #1%
+ \endgroup}
+
+\unexpanded\def\mfunction#1%
+ {\begingroup
+ \math_tags_mfunctiontxt{#1}\c_apply_function
+ \math_mfunction_styled{#1}%
+ \endgroup}
+
+\unexpanded\def\mfunctionlabeltext#1%
+ {\begingroup
+ \math_tags_mfunctionlab{#1}\c_apply_function
+ \math_mfunction_styled{\mathlabeltext{#1}}%
+ \endgroup}
+
+\let\math_tags_mfunctiontxt\gobbletwoarguments
+\let\math_tags_mfunctionlab\gobbletwoarguments
+
+\unexpanded\def\math_tags_mo_indeed#1{\begingroup \attribute\mathcategoryattribute\plusone #1\endgroup}
+\unexpanded\def\math_tags_mi_indeed#1{\begingroup \attribute\mathcategoryattribute\plustwo #1\endgroup}
+\unexpanded\def\math_tags_mn_indeed#1{\begingroup\mathupright\attribute\mathcategoryattribute\plusthree\math_set_o_both#1\endgroup}
+\unexpanded\def\math_tags_ms_indeed#1{\begingroup\mathupright\attribute\mathcategoryattribute\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext
+
+\newconditional\c_apply_function
+
+\unexpanded\def\math_tags_apply#1#2%
+ {\begingroup
+ \settrue\c_apply_function
+ #1%
+ \endgroup
+ \begingroup
+ % todo: auto ()
+ #2%
+ \endgroup}
+
+\appendtoks
+ \let\math_tags_mfunctiontxt\clf_tagmfunctiontxt
+ \let\math_tags_mfunctionlab\clf_tagmfunctionlab
+ \let\math_tags_mo \math_tags_mo_indeed
+ \let\math_tags_mi \math_tags_mi_indeed
+ \let\math_tags_mn \math_tags_mn_indeed
+ \let\math_tags_ms \math_tags_ms_indeed
+\to \everyenableelements
+
+\appendtoks
+ \let\mo \math_tags_mo
+ \let\mi \math_tags_mi
+ \let\mn \math_tags_mn
+ \let\ms \math_tags_ms
+ \let\apply\math_tags_apply
+\to\everymathematics
+
+% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}}
+% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}
+
+% %D Taco posted this solution as response to a mail by Olivier, so let's integrate
+% %D it here.
+%
+% \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
+%
+% \unexpanded\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits}
+% \unexpanded\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}}
+% \unexpanded\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}}
+%
+% \unexpanded\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
+% {\doifsomething{#1}
+% {\def\currentmscaledstyle{#1}%
+% \let\mathopnolimits \math_function_style_opnolimits
+% \let\mfunction \math_function_style_mfunction
+% \let\mfunctionlabeltext\math_function_style_mfunctionlabeltext}}
+
+\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
+
+\unexpanded\def\mscaledtext#1%
+ {\mathchoice
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}
+
+\unexpanded\def\setmathfunctionstyle#1%
+ {\setupmathematics[\c!functionstyle=#1]} % for old times sake
+
+%D Usage:
+%D
+%D \starttyping
+%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
+%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \stoptyping
+
+%D \macros
+%D {nonknuthmode, donknuthmode}
+%D
+%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
+%D it to be a math specific character. And since computer modern fonts didn't
+%D have an underscore, one had to use commands to fake one. Nowadays we do
+%D have underscores in latin modern, and since all other fonts have them, we
+%D decided to get away from the restriction to use the underscore character in
+%D text mode.
+%D
+%D \starttyping
+%D \def\test#1{#1}
+%D
+%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D
+%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D \stoptyping
+%D
+%D The result is as expected: the first line typesets ok, while the second
+%D one triggers an error message.
+
+\setnewconstant\activemathcharcode "8000
+
+\newtoks\activatedmathcharacters
+
+\unexpanded\def\activatemathcharacter#1%
+ {\appendtoks
+ \global\mathcode#1=\activemathcharcode
+ \to \activatedmathcharacters}
+
+\def\activatemathcharacters
+ {\the\activatedmathcharacters}
+
+% beware, not runtime, so has to happen at format generation
+
+\activatemathcharacter\circumflexasciicode
+\activatemathcharacter\underscoreasciicode
+\activatemathcharacter\ampersandasciicode
+
+% \activatemathcharacter\primeasciicode
+
+% not used:
+%
+% \mathcode\spaceasciicode\activemathcharcode
+%
+% not used:
+%
+% \bgroup
+% \catcode\underscoreasciicode\activecatcode
+% \doglobal\appendtoks
+% \mathcode\underscoreasciicode\activemathcharcode
+% \let_\activemathunderscore
+% \to \everymathematics
+% \egroup
+
+% Here follows some plain legacy: primes.
+%
+% The \let\prime\math_prime_indeed might become an obsolete as we have \doubleprime
+% and \tripleprime and collapsing can nicely handle the script then.
+%
+% Collapsing to 0x2033 and 0x2034 happens elsewhere.
+%
+% \switchtobodyfont[modern]
+% \switchtobodyfont[cambria]
+% \switchtobodyfont[xits]
+% \switchtobodyfont[minion]
+% \setupbodyfont[dejavu]
+%
+% \startbuffer
+% \def\SampleLine#1{%
+% \NC#1
+% \NC\switchtobodyfont[#1]$f^2$ % 1
+% \NC\switchtobodyfont[#1]$f\prime^2$ % 2
+% \NC\switchtobodyfont[#1]$f\prime\prime^2$ % 3
+% \NC\switchtobodyfont[#1]$f\prime\prime\prime^2$ % 4
+% \NC\switchtobodyfont[#1]$f{\prime}^2$ % 5
+% \NC\switchtobodyfont[#1]$f{\prime\prime}^2$ % 6
+% \NC\switchtobodyfont[#1]$f{\prime\prime\prime}^2$ % 7
+% \NC\switchtobodyfont[#1]$f'(x)$ % 8
+% \NC\switchtobodyfont[#1]$f''(x)$ % 9
+% \NC\switchtobodyfont[#1]$f'''(x)$ % 10
+% \NC\NR
+% }
+%
+% \starttabulate[|Tl|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|]
+% \NC\NC1\NC2\NC3\NC4\NC5\NC6\NC7\NC8\NC9\NC10\NC\NR
+% \SampleLine{modern}
+% \SampleLine{cambria}
+% \SampleLine{xits}
+% \SampleLine{minion}
+% \stoptabulate
+% \stopbuffer
+%
+% \typebuffer \getbuffer
+
+% 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^ }
+
+\ifdefined \prime \else
+ \Umathchardef\prime "0 "0 "2032
+\fi
+
+% \let\math_prime_indeed_normal\prime
+%
+% \appendtoks
+% \let\math_prime_indeed_normal\prime % gets defined later
+% \let\mathfontprime\prime % for tracing
+% \let\prime\math_prime_indeed % so this is needed
+% \to \everydump
+%
+% \unexpanded\def\math_prime_indeed
+% {\iffontchar\textfont\zerocount"FE325\relax
+% ^\bgroup
+% \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal)
+% \else
+% % \expandafter\math_prime_indeed_normal % gets collapsed
+% \expandafter\math_prime_indeed_crapped % gets collapsed
+% \fi}
+%
+% \def\math_prime_indeed_crapped
+% {{^{\math_prime_indeed_normal}}}
+%
+% % \let\prime\math_prime_indeed
+%
+% \def\math_prime_indeed_virtual
+% {\math_prime_indeed_normal
+% \futurelet\nexttoken\math_prime_indeed_choice}
+%
+% \installcorenamespace{mathprime}
+%
+% \def\math_prime_indeed_choice
+% {\csname\??mathprime
+% \ifx '\nexttoken a\else
+% \ifx \math_prime_indeed_normal\nexttoken a\else
+% \ifx \prime\nexttoken a\else
+% \ifx\superscriptcircumflextoken\nexttoken b\else
+% \ifx\othercircumflextoken \nexttoken b\else
+% c\fi\fi\fi\fi\fi
+% \endcsname}
+%
+% \setvalue{\??mathprime a}#1{\math_prime_indeed_virtual}
+% \setvalue{\??mathprime b}#1#2{#2\egroup}
+% \setvalue{\??mathprime c}{\egroup}
+%
+% \let\activemathprime\math_prime_indeed
+%
+% \bgroup
+%
+% \catcode\primeasciicode\activecatcode
+%
+% \global\everymathematics\expandafter{\the\everymathematics\let'\math_prime_indeed} % todo: do this at the lua end
+%
+% \egroup
+
+\bgroup
+
+ \catcode\underscoreasciicode\activecatcode
+ \catcode\circumflexasciicode\activecatcode
+ \catcode\ampersandasciicode \activecatcode
+
+ \doglobal \appendtoks
+ \let _\normalsubscript
+ \let ^\normalsuperscript
+ \let &\normalmathaligntab % use \def when it's \aligntab
+ \to \everymathematics
+
+\egroup
+
+\newtoks\everydonknuthmode
+\newtoks\everynonknuthmode
+
+\newconditional \knuthmode
+
+\let\nonknuthmode\relax % no longer needed in MkIV
+\let\donknuthmode\relax % no longer needed in MkIV
+
+% \def\nonknuthmode
+% {\pushcatcodetable
+% \setcatcodetable\ctxcatcodes
+% \the\everynonknuthmode
+% \let\nonknuthmode\relax
+% \popcatcodetable}
+%
+% \def\donknuthmode
+% {\pushcatcodetable
+% \setcatcodetable\ctxcatcodes
+% \the\everydonknuthmode
+% \popcatcodetable}
+%
+% \bgroup
+%
+% \catcode\underscoreasciicode\activecatcode
+% \catcode\circumflexasciicode\activecatcode
+% \catcode\ampersandasciicode \activecatcode
+%
+% \global \everynonknuthmode {\appendtoks
+% \let_\normalsubscript
+% \let^\normalsuperscript
+% \let&\normalmathaligntab % use \def when it's \aligntab
+% \to \everymathematics}
+%
+% \egroup
+%
+% \appendtoks
+% \setfalse\knuthmode
+% \catcode\underscoreasciicode\othercatcode
+% \catcode\circumflexasciicode\othercatcode
+% \catcode\ampersandasciicode \othercatcode
+% \to \everynonknuthmode
+%
+% \appendtoks
+% \settrue\knuthmode
+% \catcode\underscoreasciicode\subscriptcatcode
+% \catcode\circumflexasciicode\superscriptcatcode
+% \catcode\ampersandasciicode \alignmentcatcode
+% \to \everydonknuthmode
+%
+% \appendtoks
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\underscoreasciicode\othercatcode
+% \catcode\circumflexasciicode\othercatcode
+% \catcode\ampersandasciicode \othercatcode
+% \stopextendcatcodetable
+% \to \everynonknuthmode
+%
+% \appendtoks
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\underscoreasciicode\subscriptcatcode
+% \catcode\circumflexasciicode\superscriptcatcode
+% \catcode\ampersandasciicode \alignmentcatcode
+% \stopextendcatcodetable
+% \to \everydonknuthmode
+
+%D Even more drastic (this code will move as nonknuthmode is default now)
+
+% \unexpanded\def\enableasciimode
+% {\ctxlua{resolvers.macros.enablecomment()}%
+% \glet\enableasciimode\relax}
+%
+% \unexpanded\def\asciimode
+% {\catcodetable\txtcatcodes
+% \enableasciimode
+% \nonknuthmode}
+%
+% \unexpanded\def\startasciimode
+% {\pushcatcodetable
+% \catcodetable\txtcatcodes
+% \enableasciimode
+% \nonknuthmode}
+%
+% \unexpanded\def\stopasciimode
+% {\popcatcodetable
+% \ifconditional\knuthmode\else\donknuthmode\fi}
+
+\unexpanded\def\enableasciimode
+ {\clf_enableasciimode} % relaxes itself
+
+\unexpanded\def\asciimode
+ {\catcodetable\txtcatcodes
+ \clf_enableasciimode}
+
+\unexpanded\def\startasciimode
+ {\pushcatcodetable
+ \catcodetable\txtcatcodes
+ \clf_enableasciimode}
+
+\unexpanded\def\stopasciimode
+ {\popcatcodetable}
+
+%D Needed for unicode:
+
+\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}
+
+%D Memory saver:
+
+\appendtoks
+ \ifx\currentmathematics\empty
+ \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]%
+ \fi
+\to \everysetupmathematics
+
+\setupmathematics
+ [\c!compact=\v!no]
+
+% \enabletrackers[typesetters.directions.math]
+
+%D Right||to||left typesetting in math is supported by the \type {align} parameter
+%D with as option the \type {bidi} parameter. Of course support for special symbols
+%D like square roots depends on the font as well. We probably need to mirror a few
+%D more characters.
+%D
+%D \startbuffer
+%D \removeunwantedspaces
+%D \m{ ( 1 = 1) }\quad
+%D \m{ (123 = 123) }\quad
+%D \m{ a ( 1 = 1) b }\quad
+%D \m{ a (123 = 123) b }\quad
+%D \m{ x = 123 y + (1 / \sqrt {x}) }
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \starttabulate[|T|T||]
+%D \HL
+%D \NC align \NC bidi \NC \NC \NR
+%D \HL
+%D \NC l2r \NC no \NC \setupmathematics[bidi=no] \getbuffer \NC \NR
+%D \NC l2r \NC yes \NC \setupmathematics[bidi=yes] \getbuffer \NC \NR
+%D \NC r2l \NC no \NC \setupmathematics[align=r2l,bidi=no] \getbuffer \NC \NR
+%D \NC r2l \NC yes \NC \setupmathematics[align=r2l,bidi=yes] \getbuffer \NC \NR
+%D \HL
+%D \stoptabulate
+
+\newconditional\c_math_right_to_left
+
+\appendtoks
+ \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left
+\to \everyswitchmathematics
+
+\unexpanded\def\math_basics_synchronize_direction
+ {\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T}
+
+\appendtoks
+ \math_basics_synchronize_direction
+%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now (should be a property of beginmath nodes and passed to callbacks)
+\to \everyswitchmathematics
+
+% experimental (needed for an article)
+
+\installcorenamespace {mathbidi}
+
+\newcount\c_math_bidi
+
+\def\math_bidi_enable {\clf_setmathdirection\plusone \relax\c_math_bidi\plusone}
+\def\math_bidi_disable{\clf_setmathdirection\zerocount\relax\c_math_bidi\attributeunsetvalue}
+
+\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
+\to \everysetupmathematics
+
+\appendtoks
+ \attribute\mathbidiattribute\ifconditional\c_math_right_to_left\c_math_bidi\else\attributeunsetvalue\fi
+\to \everyswitchmathematics
+
+%D Delayed: greek.
+%D
+%D \starttyping
+%D \usetypescript[cambria]\setupbodyfont[cambria]
+%D \startTEXpage
+%D $\alpha \mathgreekupright \alpha \mathgreekitalic \alpha$
+%D \stopTEXpage
+%D \stoptyping
+
+% [lc uc] normal (upright) = 2, italic = 3, none = 0/1
+
+% We can move the setting to the lua end and use abstract numbers instead
+% if funny ones here.
+
+\installcorenamespace{mathgreek}
+
+\newconstant\c_math_greek_attribute
+
+\setvalue{\??mathgreek\v!none }{1}
+\setvalue{\??mathgreek\v!normal}{2}
+\setvalue{\??mathgreek\v!italic}{3}
+
+% \appendtoks
+% \edef\p_sygreek{\mathematicsparameter\s!sygreek}%
+% \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}%
+% \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}%
+% \c_math_greek_attribute"% hex digits
+% \csname\??mathgreek\ifcsname\??mathgreek\p_sygreek\endcsname\p_sygreek\else\v!none\fi\endcsname
+% \csname\??mathgreek\ifcsname\??mathgreek\p_lcgreek\endcsname\p_lcgreek\else\v!none\fi\endcsname
+% \csname\??mathgreek\ifcsname\??mathgreek\p_ucgreek\endcsname\p_ucgreek\else\v!none\fi\endcsname
+% \relax
+% \ifcase\c_math_greek_attribute
+% \c_math_greek_attribute\attributeunsetvalue
+% \fi
+% \to \everyswitchmathematics
+
+\appendtoks
+ \edef\p_sygreek{\mathematicsparameter\s!sygreek}% still needed ?
+ \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}% still needed ?
+ \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}% still needed ?
+ \c_math_greek_attribute"% hex digits
+ \ifcsname\??mathgreek\p_sygreek\endcsname\lastnamedcs\else1\fi
+ \ifcsname\??mathgreek\p_lcgreek\endcsname\lastnamedcs\else1\fi
+ \ifcsname\??mathgreek\p_ucgreek\endcsname\lastnamedcs\else1\fi
+ \relax
+ \ifcase\c_math_greek_attribute
+ \c_math_greek_attribute\attributeunsetvalue
+ \fi
+\to \everyswitchmathematics
+
+% only used local
+
+\unexpanded\def\mathgreekupright{\attribute\mathgreekattribute"222\relax}
+\unexpanded\def\mathgreekitalic {\attribute\mathgreekattribute"333\relax}
+\unexpanded\def\mathgreekdefault{\attribute\mathgreekattribute"000\relax}
+
+\let\mathgreeknormal\mathgreekupright
+\let\mathgreeknone \mathgreekdefault
+
+\appendtoks
+ \attribute\mathgreekattribute\c_math_greek_attribute
+\to \everymathematics
+
+\setupmathematics
+ [\s!sygreek=\v!normal,
+ \s!lcgreek=\v!italic,
+ \s!ucgreek=\v!normal] % was: none
+
+%D Math italics (experiment)
+
+%D We need keys but what names to use and because we have hardcoded solution
+%D we can stick to numbers.
+
+\installcorenamespace{mathitalics}
+
+\setnewconstant\c_math_italics_attribute\attributeunsetvalue
+
+\letvalue{\??mathitalics 1}\plusone % fontitalics
+\letvalue{\??mathitalics 2}\plustwo % fontdata
+\letvalue{\??mathitalics 3}\plusthree % quad based
+\letvalue{\??mathitalics 4}\plusfour % combination of 1 and 3
+\letvalue{\??mathitalics\v!none }\attributeunsetvalue
+\letvalue{\??mathitalics\v!reset}\attributeunsetvalue
+
+\def\math_italics_initialize
+ {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
+ \clf_initializemathitalics % one time
+ \global\let\math_italics_initialize\relax
+ \fi}
+
+% \appendtoks
+% \edef\p_italics{\mathematicsparameter\s!italics}%
+% \c_math_italics_attribute\csname\??mathitalics
+% \ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi
+% \endcsname\relax
+% % \math_italics_initialize
+% \to \everyswitchmathematics % only in mathematics
+
+\appendtoks
+ \edef\p_italics{\mathematicsparameter\s!italics}%
+ \c_math_italics_attribute
+ \ifcsname\??mathitalics\p_italics\endcsname\lastnamedcs\else\attributeunsetvalue\fi
+ \relax
+ % \math_italics_initialize
+\to \everyswitchmathematics % only in mathematics
+
+\appendtoks
+ \math_italics_initialize
+ \attribute\mathitalicsattribute\c_math_italics_attribute
+\to \everymathematics
+
+\setupmathematics
+ [\s!italics=3] % 4 is probably better
+
+% looks nicer but can generate bogus csnames
+%
+% \setvalue{\??mathitalics1}{\math_italics_initialize\c_math_italics_attribute\plusone } % fontitalics
+% \setvalue{\??mathitalics2}{\math_italics_initialize\c_math_italics_attribute\plustwo } % fontdata
+% \setvalue{\??mathitalics3}{\math_italics_initialize\c_math_italics_attribute\plusthree} % quad based
+% \setvalue{\??mathitalics4}{\math_italics_initialize\c_math_italics_attribute\plusfour } % combination of 1 and 3
+%
+% \appendtoks
+% \c_math_italics_attribute\attributeunsetvalue
+% \csname\??mathitalics\mathematicsparameter\s!italics\endcsname
+% \to \everyswitchmathematics % only in mathematics
+
+%D \macros
+%D {enablemathpunctuation,disablemathpunctuation}
+%D
+%D \startbuffer
+%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \blank{\getbuffer}\blank
+
+% \newconditional\automathpunctuation
+%
+% \unexpanded\def\enablemathpunctuation {\settrue \automathpunctuation}
+% \unexpanded\def\disablemathpunctuation{\setfalse\automathpunctuation}
+%
+% \appendtoks
+% \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
+% \to \everyswitchmathematics
+%
+% \setupmathematics
+% [\v!autopunctuation=\v!no]
+%
+% \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi}
+%
+% \unexpanded\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
+% \unexpanded\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
+%
+% \setnewconstant\c_math_comma "002C
+% \setnewconstant\c_math_period "002E
+% \setnewconstant\c_math_special"8000
+%
+% \bgroup
+%
+% \catcode\c_math_comma \activecatcode
+% \catcode\c_math_period\activecatcode
+%
+% \unexpanded\gdef\math_punctuation_initialize_indeed
+% {\mathcode\c_math_comma \c_math_special
+% \mathcode\c_math_period\c_math_special
+% \let,\math_punctuation_comma
+% \let.\math_punctuation_period
+% \attribute\mathpunctuationattribute\plustwo}
+%
+% \unexpanded\gdef\math_punctuation_initialize_yes
+% {\attribute\mathpunctuationattribute\plustwo}
+%
+% \unexpanded\gdef\math_punctuation_initialize_nop
+% {\attribute\mathpunctuationattribute\plusone}
+%
+% \egroup
+%
+% \appendtoks
+% \ifconditional\automathpunctuation
+% \math_punctuation_initialize_indeed
+% \math_punctuation_initialize_yes
+% \let\enablemathpunctuation \math_punctuation_initialize_yes
+% \let\disablemathpunctuation\math_punctuation_initialize_nop
+% \fi
+% \to \everymathematics
+
+% Later I will look again into a \LUATEX\ based solution. It only makes sense
+% to delegate to \LUA\ when we have more variants and need analysis (experimental
+% trickery removed for a while).
+
+% \def\math_punctuation_comma_next {\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textcomma }}
+% \def\math_punctuation_period_next{\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textperiod}}
+%
+% \unexpanded\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
+% \unexpanded\def\math_punctuation_nop_period{\mathord{\textperiod}}
+%
+% \unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
+% \unexpanded\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
+%
+% \let\math_punctuation_yes_comma \math_punctuation_all_comma
+% \let\math_punctuation_yes_period\math_punctuation_nop_period
+%
+% The next one is more efficient as it produces more flat noad lists for numbers.
+
+\setnewconstant\c_math_comma "002C
+\setnewconstant\c_math_period "002E
+\setnewconstant\c_math_special"8000
+
+\def\math_set_o_period{\Umathcode\c_math_period\mathordcode \zerocount\c_math_period}
+\def\math_set_p_period{\Umathcode\c_math_period\mathpunctcode\zerocount\c_math_period}
+\def\math_set_o_comma {\Umathcode\c_math_comma \mathordcode \zerocount\c_math_comma }
+\def\math_set_p_comma {\Umathcode\c_math_comma \mathpunctcode\zerocount\c_math_comma }
+
+\edef\math_set_o_both {\math_set_o_period\math_set_o_comma}
+\edef\math_set_p_both {\math_set_p_period\math_set_p_comma}
+
+\unexpanded\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup}
+\unexpanded\def\math_punctuation_nop_period{\begingroup\math_set_o_period.\endgroup}
+
+\unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
+\unexpanded\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
+
+ \let\math_punctuation_yes_comma \math_punctuation_all_comma
+ \let\math_punctuation_yes_period\math_punctuation_nop_period
+
+\def\math_punctuation_comma_next {\begingroup\Umathcode\c_math_comma \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_comma ,\endgroup}
+\def\math_punctuation_period_next{\begingroup\Umathcode\c_math_period\ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_period.\endgroup}
+
+\setnewconstant\c_math_comma "002C
+\setnewconstant\c_math_period "002E
+\setnewconstant\c_math_special"8000
+
+\installcorenamespace {mathautopunctuation}
+
+\bgroup
+
+ \catcode\c_math_comma \activecatcode
+ \catcode\c_math_period\activecatcode
+
+ \setgvalue{\??mathautopunctuation\v!no}%
+ {\let,\math_punctuation_nop_comma
+ \let.\math_punctuation_nop_period}
+
+ % more efficient list:
+ %
+ % \setgvalue{\??mathautopunctuation\v!no}%
+ % {\Umathcode\c_math_period\mathordcode \zerocount\c_math_period
+ % \Umathcode\c_math_comma \mathpunctcode\zerocount\c_math_comma }
+
+ \setgvalue{\??mathautopunctuation\v!yes}%
+ {\let,\math_punctuation_yes_comma
+ \let.\math_punctuation_yes_period}
+
+ \setgvalue{\??mathautopunctuation\v!all}%
+ {\let,\math_punctuation_all_comma
+ \let.\math_punctuation_all_period}
+
+\egroup
+
+% \appendtoks
+% \global\mathcode\c_math_comma \c_math_special
+% \global\mathcode\c_math_period\c_math_special
+% \to \everyjob
+
+% \activatemathcharacter\c_math_comma
+% \activatemathcharacter\c_math_period
+
+\appendtoks
+ \mathcode\c_math_comma \c_math_special
+ \mathcode\c_math_period\c_math_special
+ \csname\??mathautopunctuation\mathematicsparameter\v!autopunctuation\endcsname
+\to \everymathematics
+
+\appendtoks
+ \ifcsname\??mathautopunctuation\mathematicsparameter\v!autopunctuation\endcsname \else
+ \letmathematicsparameter\v!autopunctuation\v!no
+ \fi
+\to \everysetupmathematics
+
+\def\enablemathpunctuation {\csname\??mathautopunctuation\v!no \endcsname}
+\def\disablemathpunctuation{\csname\??mathautopunctuation\v!yes\endcsname}
+
+\setupmathematics
+ [\v!autopunctuation=\v!no] % no | yes | all
+
+%D \macros
+%D {mathstyle}
+%D
+%D If one want to be sure that something is typeset in the appropriate style, \type
+%D {\mathstyle} can be used:
+%D
+%D \starttyping
+%D \mathstyle{something}
+%D \stoptyping
+
+% \def\mathstyle#1%
+% {\mathchoice
+% {\displaystyle #1}%
+% {\textstyle #1}%
+% {\scriptstyle #1}%
+% {\scriptscriptstyle#1}}
+%
+% We now have a primitive operation for this. As the macro overloads a new
+% primitive introduced in \LUATEX, we need to use \type {\normalmathstyle} when we
+% consult the current math style.
+%
+% \let \mathstyle \Ustack % spoils cramped
+%
+% \let \mathstyle \firstofoneargument
+%
+% 0 = display
+% 1 = crampeddisplay
+% 2 = text
+% 3 = crampedtext
+% 4 = script
+% 5 = crampedscript
+% 6 = scriptscript
+% 7 = crampedscriptscript
+
+\def\uncramped#1%
+ {{\ifcase\normalmathstyle
+ \or \displaystyle \or
+ \or \textstyle \or
+ \or \scriptstyle \or
+ \or \scriptscriptstyle \fi
+ #1}}
+
+\def\cramped#1%
+ {{\ifcase\normalmathstyle
+ \crampeddisplaystyle \or \or % 0 -> 1
+ \crampedtextstyle \or \or % 2 -> 3
+ \crampedscriptstyle \or \or % 4 -> 5
+ \crampedscriptscriptstyle \fi % 6 -> 7
+ #1}}
+
+\def\triggermathstyle#1% #1 is number
+ {\ifcase\numexpr#1\relax
+ \displaystyle \or % 0
+ \crampeddisplaystyle \or % 1
+ \textstyle \or % 2
+ \crampedtextstyle \or % 3
+ \scriptstyle \or % 4
+ \crampedscriptstyle \or % 5
+ \scriptscriptstyle \or % 6
+ \crampedscriptscriptstyle \else
+ % error
+ \fi}
+
+\def\mathstylefont#1% #1 is number (\normalmathstyle)
+ {\ifcase\numexpr#1\relax
+ \textfont \or
+ \textfont \or
+ \textfont \or
+ \textfont \or
+ \scriptfont \or
+ \scriptfont \or
+ \scriptscriptfont \or
+ \scriptscriptfont \else
+ \textfont
+ \fi\zerocount} % hm, can ie other value as well
+
+\def\mathsmallstylefont#1% #1 is number (\normalmathstyle)
+ {\ifcase\numexpr#1\relax
+ \scriptfont \or
+ \scriptfont \or
+ \scriptfont \or
+ \scriptfont \or
+ \scriptscriptfont \or
+ \scriptscriptfont \or
+ \scriptscriptfont \or
+ \scriptscriptfont \else
+ \scriptfont
+ \fi\zerocount} % hm, can ie other value as well
+
+\def\mathstyleface#1% #1 is number (\normalmathstyle)
+ {\ifcase\numexpr#1\relax
+ \textface \or
+ \textface \or
+ \textface \or
+ \textface \or
+ \scriptface \or
+ \scriptface \or
+ \scriptscriptface \or
+ \scriptscriptface \else
+ \textface
+ \fi}
+
+\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
+ {\ifcase\numexpr#1\relax
+ \scriptface \or
+ \scriptface \or
+ \scriptface \or
+ \scriptface \or
+ \scriptscriptface \or
+ \scriptscriptface \or
+ \scriptscriptface \or
+ \scriptscriptface \else
+ \scriptface
+ \fi}
+
+\def\mathstylecommand#1#2#3%
+ {\ifcase\numexpr\normalmathstyle\relax
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#2\or
+ \expandafter#2\or
+ \expandafter#3\or
+ \expandafter#3\else
+ \expandafter#1\fi}
+
+% \def\textstyleface#1% #1 is number (\normalmathstyle)
+% {\ifcase\numexpr#1\relax
+% \tf \or
+% \tf \or
+% \tf \or
+% \tf \or
+% \tfx \or
+% \tfx \or
+% \tfxx \or
+% \tfxx \else
+% \tf
+% \fi}
+
+\unexpanded\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
+ {{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax
+ display\or % 0
+ crampeddisplay\or % 1
+ text\or % 2
+ crampedtext\or % 3
+ script\or % 4
+ crampedscript\or % 5
+ scriptscript\or % 6
+ crampedscriptscript\else % 7
+ unknown\fi]}}}
+
+\unexpanded\def\showmathstyle{\verbosemathstyle\normalmathstyle}
+
+%D A plain inheritance:
+
+\def\mathpalette#1#2%
+ {\mathchoice
+ {#1\displaystyle {#2}}%
+ {#1\textstyle {#2}}%
+ {#1\scriptstyle {#2}}%
+ {#1\scriptscriptstyle{#2}}}
+
+%D Often we can use:
+%D
+%D \startbuffer
+%D $x^{\mathstylehbox{x^{\mathstylehbox{x}}}}$
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% to be tested: {#1} but it could have side effects
+
+\unexpanded\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b}
+ {\normalexpanded{\hbox\bgroup
+ \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
+
+\unexpanded\def\mathstylevbox#1%
+ {\normalexpanded{\vbox\bgroup
+ \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
+
+\unexpanded\def\mathstylevcenter#1%
+ {\normalexpanded{\vcenter\bgroup
+ \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
+
+\unexpanded\def\mathstylevcenteredhbox#1%
+ {\normalexpanded{\vcenter\bgroup\hbox\bgroup
+ \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
+
+\unexpanded\def\mathstylevcenteredvbox#1%
+ {\normalexpanded{\vcenter\bgroup\vbox\bgroup
+ \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
+
+\unexpanded\def\setmathsmalltextbox#1#2#%
+ {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}%
+ \setbox#1#2\bgroup
+ \font_basics_switchtobodyfont\m_math_text_choice_face
+ \let\next}
+
+\unexpanded\def\setmathtextbox#1#2#%
+ {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
+ \setbox#1#2\bgroup
+ \font_basics_switchtobodyfont\m_math_text_choice_face
+ \let\next}
+
+%D Here is the new mechanism ... it might replace some of the above but we will do
+%D that stepwise. Keep in mind that cramped only affects superscripts and even then,
+%D only when in a smaller size than normal.
+%D
+%D \def\TestMe#1%
+%D {\NC \ttbf #1
+%D \NC \ruledhbox{$\setupmathstyle[#1]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
+%D \NC \ruledhbox{$\setupmathstyle[#1,small]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
+%D \NC \NR}
+%D
+%D \starttabulate[|l|r|l|]
+%D \HL
+%D \NC \NC \NC \ttbf ...,small \NC \NR
+%D \HL
+%D \TestMe{text} \TestMe{text,cramped}
+%D \TestMe{script} \TestMe{script,cramped}
+%D \TestMe{scriptscript} \TestMe{scriptscript,cramped}
+%D \TestMe{display} \TestMe{display,cramped}
+%D \HL
+%D \stoptabulate
+
+\def\triggerdisplaystyle
+ {\ifcase\normalmathstyle\relax
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \fi}
+
+\def\triggertextstyle
+ {\ifcase\normalmathstyle\relax
+ \textstyle \or
+ \crampedtextstyle \or
+ \textstyle \or
+ \crampedtextstyle \or
+ \textstyle \or
+ \crampedtextstyle \or
+ \textstyle \or
+ \crampedtextstyle \else
+ \fi}
+
+\def\triggerscriptstyle
+ {\ifcase\normalmathstyle\relax
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \fi}
+
+\def\triggerscriptscriptstyle
+ {\ifcase\normalmathstyle\relax
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \fi}
+
+\def\triggeruncrampedstyle
+ {\ifcase\normalmathstyle\relax
+ \or \displaystyle \or
+ \or \textstyle \or
+ \or \scriptstyle \or
+ \or \scriptscriptstyle \fi}
+
+\def\triggercrampedstyle
+ {\ifcase\normalmathstyle\relax
+ \crampeddisplaystyle \or \or
+ \crampedtextstyle \or \or
+ \crampedscriptstyle \or \or
+ \crampedscriptscriptstyle \fi}
+
+\def\triggersmallstyle
+ {\ifcase\normalmathstyle\relax
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \fi}
+
+\def\triggeruncrampedsmallstyle
+ {\ifcase\normalmathstyle\relax
+ \scriptstyle \or
+ \scriptstyle \or
+ \scriptstyle \or
+ \scriptstyle \or
+ \scriptscriptstyle \or
+ \scriptscriptstyle \or
+ \scriptscriptstyle \or
+ \scriptscriptstyle \or
+ \fi}
+
+\def\triggercrampedsmallstyle
+ {\ifcase\normalmathstyle\relax
+ \crampedscriptstyle \or
+ \crampedscriptstyle \or
+ \crampedscriptstyle \or
+ \crampedscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \crampedscriptscriptstyle \or
+ \fi}
+
+\def\triggerbigstyle
+ {\ifcase\normalmathstyle\relax
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \textstyle \or
+ \crampedtextstyle \or
+ \textstyle \or
+ \crampedtextstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \fi}
+
+\def\triggeruncrampedbigstyle
+ {\ifcase\normalmathstyle\relax
+ \displaystyle \or
+ \displaystyle \or
+ \textstyle \or
+ \textstyle \or
+ \textstyle \or
+ \textstyle \or
+ \scriptstyle \or
+ \scriptstyle \or
+ \fi}
+
+\def\triggercrampedbigstyle
+ {\ifcase\normalmathstyle\relax
+ \crampeddisplaystyle \or
+ \crampeddisplaystyle \or
+ \crampedtextstyle \or
+ \crampedtextstyle \or
+ \crampedtextstyle \or
+ \crampedtextstyle \or
+ \crampedscriptstyle \or
+ \crampedscriptstyle \or
+ \fi}
+
+\newcount\c_math_saved_style
+
+\unexpanded\def\pushmathstyle % assumes begingroup .. endgroup
+ {\c_math_saved_style\mathstyle}
+
+\unexpanded\def\popmathstyle
+ {\ifnum\mathstyle=\c_math_saved_style\else
+ \triggermathstyle\c_math_saved_style
+ \fi}
+
+\installcorenamespace{mathstylecommand}
+\installcorenamespace{mathstylecache}
+
+\newconstant\c_math_styles_state_style
+\newconstant\c_math_styles_state_cramped
+\newconstant\c_math_styles_state_size
+
+\def\math_style_add_to_cache_choice {%
+ \ifcase\c_math_styles_state_size
+ \ifcase\c_math_styles_state_style
+ \ifcase\c_math_styles_state_cramped
+ \relax \or
+ \noexpand\triggeruncrampedstyle \or
+ \noexpand\triggercrampedstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerdisplaystyle \or
+ \displaystyle \or
+ \crampeddisplaystyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggertextstyle \or
+ \textstyle \or
+ \crampedtextstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \fi
+ \fi
+ \or % small
+ \ifcase\c_math_styles_state_style
+ \ifcase\c_math_styles_state_cramped
+ \noexpand\triggersmallstyle \or
+ \noexpand\triggeruncrampedsmallstyle \or
+ \noexpand\triggercrampedsmallstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \fi
+ \fi
+ \or % large
+ \ifcase\c_math_styles_state_style
+ \ifcase\c_math_styles_state_cramped
+ \noexpand\triggerbigstyle \or
+ \noexpand\triggeruncrampedbigstyle \or
+ \noexpand\triggercrampedbigstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerdisplaystyle \or
+ \displaystyle \or
+ \crampeddisplaystyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggertextstyle \or
+ \textstyle \or
+ \crampedtextstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggertextstyle \or
+ \textstyle \or
+ \crampedtextstyle \fi
+ \or\ifcase\c_math_styles_state_cramped
+ \noexpand\triggerscriptstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \fi
+ \fi
+ \fi
+}
+
+\unexpanded\def\math_style_set#1%
+ {\edef\m_math_style_asked{#1}%
+ \ifx\m_math_style_asked\empty \else
+ \math_style_set_indeed
+ \fi}
+
+\let\setmathstyle\math_style_set
+
+\def\installmathstyle#1#2%
+ {\ifcsname\??mathstylecommand#1\endcsname \else
+ \setvalue{\??mathstylecommand#1}{#2}%
+ \fi}
+
+\def\math_style_collect#1%
+ {\csname\??mathstylecommand#1\endcsname}
+
+\setvalue{\??mathstylecommand\s!display }{\c_math_styles_state_style \plusone}
+\setvalue{\??mathstylecommand\s!text }{\c_math_styles_state_style \plustwo}
+\setvalue{\??mathstylecommand\s!script }{\c_math_styles_state_style \plusthree}
+\setvalue{\??mathstylecommand\s!scriptscript}{\c_math_styles_state_style \plusfour}
+
+\setvalue{\??mathstylecommand\s!uncramped }{\c_math_styles_state_cramped\plusone}
+\setvalue{\??mathstylecommand\s!cramped }{\c_math_styles_state_cramped\plustwo}
+\setvalue{\??mathstylecommand\v!normal }{\c_math_styles_state_cramped\plusone}
+\setvalue{\??mathstylecommand\v!packed }{\c_math_styles_state_cramped\plustwo}
+
+\setvalue{\??mathstylecommand\v!small }{\c_math_styles_state_size \plusone}
+\setvalue{\??mathstylecommand\v!big }{\c_math_styles_state_size \plustwo}
+
+\unexpanded\def\setupmathstyle[#1]%
+ {\edef\m_math_style_asked{#1}%
+ \ifx\m_math_style_asked\empty \else
+ \math_style_set_indeed
+ \fi}
+
+\unexpanded\def\usemathstyleparameter#1% faster local variant
+ {\edef\m_math_style_asked{#1\c!mathstyle}%
+ \ifx\m_math_style_asked\empty \else
+ \math_style_set_indeed
+ \fi}
+
+%D \startbuffer
+%D \definemathstyle[mystyle][scriptscript]
+%D
+%D $text\startmathstyle[mystyle]scriptscript\stopmathstyle text$
+%D \stopbuffer
+%D
+%D \typebuffer \blank \start \getbuffer \stop \blank
+
+\installcorenamespace {mathstyle}
+
+\unexpanded\def\definemathstyle
+ {\dodoubleargument\math_style_define}
+
+\def\math_style_define[#1][#2]%
+ {\c_math_styles_state_style \zerocount
+ \c_math_styles_state_cramped\zerocount
+ \c_math_styles_state_size \zerocount
+ \rawprocesscommacommand[#2]\math_style_collect
+ \expandafter\let\csname\??mathstyle#1\normalexpanded{\endcsname\math_style_add_to_cache_choice}}
+
+% \def\math_style_set_indeed
+% {\csname\??mathstyle
+% \ifcsname\??mathstyle\m_math_style_asked\endcsname
+% \m_math_style_asked
+% \else
+% \??mathstyle
+% \fi
+% \endcsname}
+%
+% \setvalue{\??mathstyle\??mathstyle}%
+% {\csname\??mathstylecache
+% \ifcsname\??mathstylecache\m_math_style_asked\endcsname
+% \m_math_style_asked
+% \else
+% \??mathstylecache
+% \fi
+% \endcsname}
+%
+% \setvalue{\??mathstylecache\??mathstylecache}%
+% {\c_math_styles_state_style \zerocount
+% \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}%
+% \csname\??mathstylecache\m_math_style_asked\endcsname}
+
+\def\math_style_set_indeed
+ {\ifcsname\??mathstyle\m_math_style_asked\endcsname
+ \lastnamedcs
+ \else
+ \math_style_set_mathstyle_mathstyle
+ \fi}
+
+\def\math_style_set_mathstyle_mathstyle
+ {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
+ \lastnamedcs
+ \else
+ \math_style_set_mathstyle_mathstylecache
+ \fi}
+
+\def\math_style_set_mathstyle_mathstylecache
+ {\c_math_styles_state_style \zerocount
+ \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}%
+ \csname\??mathstylecache\m_math_style_asked\endcsname}
+
+\letvalue{\??mathstyle \??mathstyle }\math_style_set_mathstyle_mathstyle % still needed?
+\letvalue{\??mathstylecache\??mathstylecache}\math_style_set_mathstyle_mathstylecache % still needed?
+
+%D \startbuffer
+%D $x\begingroup\setupmathstyle[script]x\endgroup x$
+%D $x{\setupmathstyle[script]x}x$
+%D $x\startmathstyle[script]x\stopmathstyle x$
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\startmathstyle[#1]%
+ {\edef\m_math_style_asked{#1}%
+ \ifx\m_math_style_asked\empty
+ \let\stopmathstyle\relax
+ \else
+ \bgroup
+ \math_style_set_indeed
+ \let\stopmathstyle\egroup
+ \fi}
+
+\let\stopmathstyle\relax
+
+\unexpanded\def\startusemathstyleparameter#1%
+ {\edef\m_math_style_asked{#1\c!mathstyle}%
+ \ifx\m_math_style_asked\empty
+ \let\stopusemathstyleparameter\relax
+ \else
+ \bgroup
+ \math_style_set_indeed
+ \let\stopusemathstyleparameter\egroup
+ \fi}
+
+\let\stopusemathstyleparameter\relax
+
+%D Something similar can be used in the (re|)|definition of \type {\text}. This
+%D version is a variation on the one in the math module (see \type{m-math} and|/|or
+%D \type {m-newmat}).
+
+\let\m_math_text_choice_face\relax
+
+% if needed we can get rid of the normalize (predo in font code)
+
+\def\math_text_choice_font#1%
+ {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
+ \hbox\bgroup
+ \font_basics_switchtobodyfont\m_math_text_choice_face
+ #1%
+ \let\next}
+
+\def\math_text_choice_word#1%
+ {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
+ \hbox\bgroup
+ \font_basics_switchtobodyfont\m_math_text_choice_face
+ #1%
+ \nospacing % \normalnospaces\plusone
+ \let\next}
+
+% \ruledhbox{$\mathtext{abc ffi}$}
+% \ruledhbox{$\mathword{abc ffi}$}
+
+\unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox}
+\unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox}
+
+\unexpanded\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
+\unexpanded\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
+\unexpanded\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
+\unexpanded\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
+\unexpanded\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
+\unexpanded\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
+
+\unexpanded\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
+\unexpanded\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
+\unexpanded\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
+\unexpanded\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
+\unexpanded\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
+\unexpanded\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}
+
+%D Safeguard against redefinitions:
+
+\appendtoks
+ \let\_\normalunderscore % is textunderscore or fakeunderscore
+\to \everymathematics
+
+%D Because we may overload \type {\text} in other (structuring) macros, we say:
+
+\appendtoks \let\text\mathtext \to \everymathematics
+
+%D The next code is derived from plain \TEX. The names will change!
+
+\newcount\interdisplaylinepenalty \interdisplaylinepenalty\plushundred
+
+% Actually, not using an if saves one macro so there is no penalty
+% for splitting up this macro.
+%
+% \newif\ifdt@p
+%
+% \def\displ@y
+% {\global\dt@ptrue
+% \math_openup\displayopenupvalue % was \openup\jot
+% \everycr
+% {\noalign
+% {\ifdt@p
+% \global\dt@pfalse
+% \ifdim\prevdepth>-\thousandpoint
+% \vskip-\lineskiplimit
+% \vskip\normallineskiplimit
+% \fi
+% \else
+% \penalty\interdisplaylinepenalty
+% \fi}}}
+
+\newtoks\mathdisplayaligntweaks
+
+\appendtoks
+ \resetdisplaymatheq % moved to here
+\to \mathdisplayaligntweaks
+
+\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
+ \math_openup\displayopenupvalue % was \math_openup\jot
+ \everycr{\noalign{\math_display_align_hack_indeed}}}
+
+\def\math_display_align_hack_remove_skip
+ {\ifdim\prevdepth>-\thousandpoint
+ \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax
+ \fi
+ \global\let\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}
+
+\def\math_display_align_hack_insert_penalty
+ {\penalty\interdisplaylinepenalty}
+
+\appendtoks
+ \math_display_align_hack
+\to \mathdisplayaligntweaks
+
+%D Text in math:
+
+\unexpanded\def\mathortext
+ {\ifmmode
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+% \defineactivecharacter _ {\mathortext{_}{\_}} text_text $a^2$
+
+% force text mode, will be overloaded later
+
+\ifdefined\text\else \let\text\hbox \fi
+
+% \unexpanded\def\mathoptext#1{\mathop{\text{#1}}}
+
+\unexpanded\def\mathoptext
+ {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
+ %\showmathstyle
+ \dowithnextbox
+ {\mathop{\box\nextbox}}%
+ \hbox\bgroup\font_basics_switchtobodyfont\m_math_text_choice_face\let\next}
+
+% new:
+
+% \startsetups math:morespacing
+% \Umathordordspacing\textstyle 1mu plus .5mu minus .25mu\relax
+% \stopsetups
+%
+% \setupmathematics
+% [setups=math:morespacing]
+
+\appendtoks
+ \edef\p_setups{\mathematicsparameter\c!setups}%
+ \ifx\p_setups\empty\else
+ \directsetup\p_setups
+ \fi
+\to \everyswitchmathematics
+
+% new:
+
+\unexpanded\def\smallmathsymbol#1%
+ {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath
+ \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1%
+ \normalstopimath}}}}}
+
+% this should be a primitive:
+
+\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax}
+\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax}
+
+% experimental:
+
+%D \starttyping
+%D \enabletrackers[math.openedup]
+%D
+%D \dorecurse{10}{\dorecurse{#1}{whatever }}
+%D
+%D \startitemize[packed]
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \stopitemize
+%D \startitemize[packed,columns]
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \stopitemize
+%D
+%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
+%D
+%D \startitemize[packed,columns]
+%D \startitem whatever \openedupimath{1+2} whatever
+%D \startitem whatever \openedupimath{1+2} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{1+2} whatever
+%D \startitem whatever \openedupimath{1+2} whatever
+%D \stopitemize
+%D
+%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{1+2} }
+%D
+%D \startitemize[packed]
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \startitem whatever \openedupimath{\frac{1}{2}} whatever
+%D \stopitemize
+%D
+%D \dorecurse{10}{whatever }
+%D \dorecurse {5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
+%D \dorecurse{10}{whatever }
+%D \stoptyping
+
+\def\m_math_inline_openup_ht{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}
+\def\m_math_inline_openup_dp{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}
+
+% \def\m_math_inline_openup_ht{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}
+% \def\m_math_inline_openup_dp{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}
+
+\installtextracker
+ {math.openedup}
+ {\let\math_inline_openup_start_yes\math_inline_openup_traced_start}
+ {\let\math_inline_openup_start_yes\math_inline_openup_normal_start}
+
+\unexpanded\def\math_inline_openup_normal_start
+ {\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax
+ \scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax
+ \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
+ \begingroup
+ \let\math_inline_openup_stop\math_inline_openup_normal_stop}
+
+\unexpanded\def\math_inline_openup_normal_stop
+ {\endgroup
+ \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}
+
+\unexpanded\def\math_inline_openup_traced_start
+ {\scratchtopoffset \ht\scratchbox
+ \scratchbottomoffset\dp\scratchbox
+ \scratchheight \dimexpr\scratchtopoffset +\m_math_inline_openup_ht\relax
+ \scratchdepth \dimexpr\scratchbottomoffset+\m_math_inline_openup_dp\relax
+ \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
+ \begingroup
+ \dofastcoloractivation{darkred}%
+ \vrule\s!width\emwidth\s!height\scratchheight\s!depth-\scratchtopoffset\relax
+ \endgroup
+ \kern-\emwidth
+ \begingroup
+ \let\math_inline_openup_stop\math_inline_openup_traced_stop}
+
+\unexpanded\def\math_inline_openup_traced_stop
+ {\endgroup
+ \kern-\emwidth
+ \begingroup
+ \dofastcoloractivation{darkblue}%
+ \vrule\s!width\emwidth\s!height-\scratchbottomoffset\s!depth\scratchdepth\relax
+ \endgroup
+ \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}
+
+\let\math_inline_openup_start_yes\math_inline_openup_normal_start
+\let\math_inline_openup_stop \relax
+
+\def\math_inline_openup_start_nop
+ {\let\math_inline_openup_stop\relax}
+
+\unexpanded\def\openedupimath
+ {\dontleavehmode
+ \begingroup
+ \ifmmode
+ \expandafter\openedupimath_math
+ \else
+ \expandafter\openedupimath_text
+ \fi}
+
+\unexpanded\def\openedupimath_math#1%
+ {\setbox\scratchbox\mathstylehbox{#1}%
+ \ifdim\ht\scratchbox>\strutht
+ \math_inline_openup_start_yes
+ \else\ifdim\dp\scratchbox>\strutdp
+ \math_inline_openup_start_yes
+ \else
+ \math_inline_openup_start_nop
+ \fi\fi
+ #1%
+ \math_inline_openup_stop
+ \endgroup}
+
+\unexpanded\def\openedupimath_text#1%
+ {\setbox\scratchbox\hbox{\startimath#1\stopimath}%
+ \ifdim\ht\scratchbox>\strutht
+ \math_inline_openup_start_yes
+ \else\ifdim\dp\scratchbox>\strutdp
+ \math_inline_openup_start_yes
+ \else
+ \math_inline_openup_start_nop
+ \fi\fi
+ \startimath
+ #1%
+ \stopimath
+ \math_inline_openup_stop
+ \endgroup}
+
+% Also handy, especially for units:
+%
+% 0x002B=plus 0x2212=minus 0x2013=endash
+
+\unexpanded\def\mathplus {+}
+\unexpanded\def\mathminus{\ifmmode –\else\iffontchar\font`−−\else –\fi\fi}
+
+%D The \type {\displaywidth} is only known inside a display formula, so we need to catch
+%D it when still zero.
+
+\def\checkeddisplaywidth % hsize if zero
+ {\dimexpr
+ \ifdim\displaywidth=\zeropoint
+ \hsize
+ \else
+ \displaywidth
+ \fi
+ \relax}
+
+\def\maximizeddisplaywidth % larger than zero but within hsize
+ {\dimexpr
+ \ifdim\displaywidth=\zeropoint
+ \hsize
+ \else\ifdim\displaywidth>\hsize
+ \hsize
+ \else
+ \displaywidth
+ \fi\fi
+ \relax}
+
+%D Experiment: (todo: same switch as italic, using \type {\everyswitchmathematics}).
+
+\newcount\c_math_domain_attribute
+
+\def\math_domain_initialize
+ {\ifnum\c_math_domain_attribute=\attributeunsetvalue \else
+ \clf_initializemathdomain % one time
+ \global\let\math_domain_initialize\relax
+ \fi}
+
+\appendtoks
+ \edef\p_domain{\mathematicsparameter\c!domain}%
+ \ifx\p_domain\empty
+ \c_math_domain_attribute\attributeunsetvalue
+ \else
+ \c_math_domain_attribute\clf_getmathdomain\p_domain\relax
+ \math_domain_initialize
+ \fi
+\to \everyswitchmathematics % only in mathematics
+
+\appendtoks
+ \attribute\mathdomainattribute\c_math_domain_attribute
+\to \everymathematics
+
+\setupmathematics
+ [\s!italics=3] % for the moment only this one makes sense .. still experimental
+
+\protect \endinput
+
+% % not used (yet)
+%
+% \newtoks \everystartimath
+% \newtoks \everystopimath
+%
+% \unexpanded\def\startimath{\Ustartmath\the\everystartimath}
+% \unexpanded\def\stopimath {\the\everystopimath\Ustopmath}
+%
+% \unexpanded\def\m%
+% {\relax
+% \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi}
+%
+% \unexpanded\def\math_m_math#1%
+% {\startimath#1\stopimath}
+%
+% \let\math_m_stay\firstofoneargument
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-inl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-inl.mkiv
new file mode 100644
index 00000000000..2c7284458a5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-inl.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=math-inl,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Inline,
+%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 / Inline}
+
+\unprotect
+
+% The \MKII\ math grid snapping code has gone. A pity as it was rather effective
+% and worked quite well (for a couple of projects where it was demanded). Other code
+% might show up / move here.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-int.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-int.mkiv
new file mode 100644
index 00000000000..5876eb7bb25
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-int.mkiv
@@ -0,0 +1,141 @@
+%D \module
+%D [ file=math-int,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Scripts,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Integrals}
+
+% todo: int and sum etc can be stackers
+
+\unprotect
+
+%D \startbuffer
+%D $\int _a^b f(x) dx $ and also
+%D $\iint _a^b f(x,y) dxdy$,
+%D $\iiint _a^b f(x,y) dxdy$,
+%D \startformula
+%D \int _a^b f(x) dx \quad
+%D \iint _a^b f(x) dx \quad
+%D \iiint _a^b f(x) dx \quad
+%D \stopformula
+%D \stopbuffer
+%D
+%D Default: \getbuffer
+%D
+%D Displaylimits: \setupmathematics[integral=displaylimits] \getbuffer
+%D
+%D Limits: \setupmathematics[integral=limits] \getbuffer
+
+%D Adapted to mkiv by HH from code by AM.
+
+\installcorenamespace{mathintegral}
+
+\newconstant\mathintlimitmode
+
+\def\intlimits % also used elsewhere
+ {\ifcase\mathintlimitmode
+ \nolimits
+ \or
+ \displaylimits
+ \or
+ \limits
+ \or
+ \ifnum\attribute\mathmodeattribute=\plusone
+ \limits
+ \else
+ \nolimits
+ \fi
+ \else
+ % none
+ \fi}
+
+\letvalue{\??mathintegral nolimits}\zerocount
+\letvalue{\??mathintegral displaylimits}\plusone
+\letvalue{\??mathintegral limits}\plustwo
+\letvalue{\??mathintegral autolimits}\plusthree
+\letvalue{\??mathintegral none}\plusfour
+
+\appendtoks
+ \mathintlimitmode\executeifdefined{\??mathintegral\mathematicsparameter\s!integral}\zerocount
+\to \everyswitchmathematics
+
+\setupmathematics
+% [\v!integral=nolimits]
+ [\v!integral=autolimits]
+
+%D The following code is used for fallbacks and might become obsolete once
+%D we have enough \OPENTYPE\ math fonts.
+
+% \def\math_repeated_integal_i
+% {\int}
+
+% \def\math_repeated_integal_ii
+% {\math_repeated_integal_i
+% \math_repeated_integral_kern
+% \math_repeated_integal_i
+% \math_repeat_integral_finish
+% \intlimits}
+
+% \def\math_repeated_integal_iii
+% {\math_repeated_integal_i
+% \math_repeated_integral_kern
+% \math_repeated_integal_ii}
+%
+% \def\math_repeated_integal_iiii
+% {\math_repeated_integal_i
+% \math_repeated_integral_kern
+% \math_repeated_integal_iii}
+%
+% \unexpanded\def\math_repeat_integral#1%
+% {\let\math_repeat_integral_finish\donothing
+% \iffontchar\textfont\zerocount#1\relax
+% \expandafter\math_repeat_integral_real
+% \else
+% \expandafter\math_repeat_integral_fake
+% \fi}
+%
+% \def\math_repeat_integral_fake#1#2%
+% {\let\math_repeat_integral_fake_symbol#2%
+% \futurelet\next\math_repeat_integral_fake_indeed}
+%
+% \def\math_repeat_integral_real#1#2%
+% {#1}
+%
+% \definemathcommand [iint] {\math_repeat_integral{"0222C}\normalint \math_repeated_integal_ii } % double
+% \definemathcommand [iiint] {\math_repeat_integral{"0222D}\normaliint \math_repeated_integal_iii } % tripple
+% \definemathcommand [iiiint] {\math_repeat_integral{"FFFFF}\normaliiint\math_repeated_integal_iiii} % quadruple
+%
+% \def\math_repeated_integral_kern
+% {\mkern-6mu\mathchoice{\mkern-3mu}{}{}{}}
+%
+% \def\math_repeat_integral_fake_indeed
+% {\ifx\next\limits
+% \math_repeated_integral_correction
+% \else\ifx\next\displaylimits
+% \math_repeated_integral_correction
+% \else\ifx\next\nolimits
+% % nothing
+% \else\ifcase\mathintlimitmode
+% % nothing
+% \else
+% \math_repeated_integral_correction
+% \fi\fi\fi\fi
+% \math_repeat_integral_fake_symbol}
+%
+% \def\math_repeated_integral_correction
+% {\mkern-7mu\mathchoice{\mkern-2mu}{}{}{}%
+% \mathop\bgroup\mkern7mu\mathchoice{\mkern2mu}{}{}{}\let\math_repeat_integral_finish\egroup}
+%
+% %D If the \type{\limits} option is used after \type {\iint}, use \type
+% %D {\mathop} and fudge the left hand space a bit to make the subscript
+% %D visually centered.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-map.lua b/Master/texmf-dist/tex/context/base/mkiv/math-map.lua
new file mode 100644
index 00000000000..94dde41103c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-map.lua
@@ -0,0 +1,805 @@
+if not modules then modules = { } end modules ['math-map'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: make sparse .. if self
+
+--[[ldx--
+<p>Remapping mathematics alphabets.</p>
+--ldx]]--
+
+-- oldstyle: not really mathematics but happened to be part of
+-- the mathematics fonts in cmr
+--
+-- persian: we will also provide mappers for other
+-- scripts
+
+-- todo: alphabets namespace
+-- maybe: script/scriptscript dynamic,
+
+-- superscripped primes get unscripted !
+
+-- to be looked into once the fonts are ready (will become font
+-- goodie):
+--
+-- (U+2202,U+1D715) : upright
+-- (U+2202,U+1D715) : italic
+-- (U+2202,U+1D715) : upright
+--
+-- plus add them to the regular vectors below so that they honor \it etc
+
+local type, next = type, next
+local floor, div = math.floor, math.div
+local merged = table.merged
+local extract = bit32.extract
+
+local allocate = utilities.storage.allocate
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local setmetatableindex = table.setmetatableindex
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+
+local trace_greek = false trackers.register("math.greek", function(v) trace_greek = v end)
+local report_remapping = logs.reporter("mathematics","remapping")
+
+mathematics = mathematics or { }
+local mathematics = mathematics
+
+local implement = interfaces.implement
+
+-- Unfortunately some alphabets have gaps (thereby troubling all applications that
+-- need to deal with math). Somewhat strange considering all those weird symbols that
+-- were added afterwards. The following trickery (and data) is only to be used for
+-- diagnostics and quick and dirty alphabet tracing (s-mat-10.mkiv) as we deal with
+-- it otherwise.
+
+-- todo: allocate
+
+mathematics.styles = allocate { "regular", "sansserif", "monospaced", "fraktur", "script", "blackboard" }
+mathematics.alternatives = allocate { "normal", "bold", "italic", "bolditalic" }
+mathematics.sets = allocate { "ucletters", "lcletters", "digits", "ucgreek", "lcgreek", "symbols" }
+
+mathematics.charactersets = allocate {
+ ucletters = {
+ 0x00041, 0x00042, 0x00043, 0x00044, 0x00045,
+ 0x00046, 0x00047, 0x00048, 0x00049, 0x0004A,
+ 0x0004B, 0x0004C, 0x0004D, 0x0004E, 0x0004F,
+ 0x00050, 0x00051, 0x00052, 0x00053, 0x00054,
+ 0x00055, 0x00056, 0x00057, 0x00058, 0x00059,
+ 0x0005A,
+ },
+ lcletters = {
+ 0x00061, 0x00062, 0x00063, 0x00064, 0x00065,
+ 0x00066, 0x00067, 0x00068, 0x00069, 0x0006A,
+ 0x0006B, 0x0006C, 0x0006D, 0x0006E, 0x0006F,
+ 0x00070, 0x00071, 0x00072, 0x00073, 0x00074,
+ 0x00075, 0x00076, 0x00077, 0x00078, 0x00079,
+ 0x0007A,
+ },
+ digits = {
+ 0x00030, 0x00031, 0x00032, 0x00033, 0x00034,
+ 0x00035, 0x00036, 0x00037, 0x00038, 0x00039,
+ },
+ ucgreek = {
+ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
+ 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
+ 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ },
+ lcgreek = {
+ 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
+ 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
+ 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4,
+ 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9,
+ 0x03D1, 0x03D5, 0x03D6, 0x03F0, 0x03F1,
+ 0x03F4, 0x03F5
+ },
+}
+
+mathematics.gaps = allocate {
+ [0x1D455] = 0x0210E, -- ℎ h
+ [0x1D49D] = 0x0212C, -- ℬ script B
+ [0x1D4A0] = 0x02130, -- ℰ script E
+ [0x1D4A1] = 0x02131, -- ℱ script F
+ [0x1D4A3] = 0x0210B, -- ℋ script H
+ [0x1D4A4] = 0x02110, -- ℐ script I
+ [0x1D4A7] = 0x02112, -- ℒ script L
+ [0x1D4A8] = 0x02133, -- ℳ script M
+ [0x1D4AD] = 0x0211B, -- ℛ script R
+ [0x1D4BA] = 0x0212F, -- ℯ script e
+ [0x1D4BC] = 0x0210A, -- ℊ script g
+ [0x1D4C4] = 0x02134, -- ℴ script o
+ [0x1D506] = 0x0212D, -- ℭ fraktur C
+ [0x1D50B] = 0x0210C, -- ℌ fraktur H
+ [0x1D50C] = 0x02111, -- ℑ fraktur I
+ [0x1D515] = 0x0211C, -- ℜ fraktur R
+ [0x1D51D] = 0x02128, -- ℨ fraktur Z
+ [0x1D53A] = 0x02102, -- ℂ bb C
+ [0x1D53F] = 0x0210D, -- ℍ bb H
+ [0x1D545] = 0x02115, -- ℕ bb N
+ [0x1D547] = 0x02119, -- ℙ bb P
+ [0x1D548] = 0x0211A, -- ℚ bb Q
+ [0x1D549] = 0x0211D, -- ℝ bb R
+ [0x1D551] = 0x02124, -- ℤ bb Z
+}
+
+local function fillinmathgaps(tfmdata,key,value)
+ local mathgaps = mathematics.gaps
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ for gap, original in next, mathgaps do
+ if characters[original] and not characters[gap] then
+ characters [gap] = characters [original]
+ descriptions[gap] = descriptions[original]
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathgaps",
+ description = "plug gaps in math alphabets",
+ comment = "regular document sources should not depend on this",
+ manipulators = {
+ base = fillinmathgaps,
+ node = fillinmathgaps,
+ }
+}
+
+-- we could use one level less and have tf etc be tables directly but the
+-- following approach permits easier remapping of a-a, A-Z and 0-9 to
+-- fallbacks; symbols is currently mostly greek
+
+local function todigit (n) local t = { } for i=0, 9 do t[0x00030+i] = n+i end return t end
+local function toupper (n) local t = { } for i=0,25 do t[0x00041+i] = n+i end return t end
+local function tolower (n) local t = { } for i=0,25 do t[0x00061+i] = n+i end return t end
+local function tovector(t) return t end
+
+local regular_tf = {
+ digits = todigit(0x00030),
+ ucletters = toupper(0x00041),
+ lcletters = tolower(0x00061),
+ ucgreek = {
+ [0x0391]=0x0391, [0x0392]=0x0392, [0x0393]=0x0393, [0x0394]=0x0394, [0x0395]=0x0395,
+ [0x0396]=0x0396, [0x0397]=0x0397, [0x0398]=0x0398, [0x0399]=0x0399, [0x039A]=0x039A,
+ [0x039B]=0x039B, [0x039C]=0x039C, [0x039D]=0x039D, [0x039E]=0x039E, [0x039F]=0x039F,
+ [0x03A0]=0x03A0, [0x03A1]=0x03A1, [0x03A3]=0x03A3, [0x03A4]=0x03A4, [0x03A5]=0x03A5,
+ [0x03A6]=0x03A6, [0x03A7]=0x03A7, [0x03A8]=0x03A8, [0x03A9]=0x03A9,
+ },
+ lcgreek = {
+ [0x03B1]=0x03B1, [0x03B2]=0x03B2, [0x03B3]=0x03B3, [0x03B4]=0x03B4, [0x03B5]=0x03B5,
+ [0x03B6]=0x03B6, [0x03B7]=0x03B7, [0x03B8]=0x03B8, [0x03B9]=0x03B9, [0x03BA]=0x03BA,
+ [0x03BB]=0x03BB, [0x03BC]=0x03BC, [0x03BD]=0x03BD, [0x03BE]=0x03BE, [0x03BF]=0x03BF,
+ [0x03C0]=0x03C0, [0x03C1]=0x03C1, [0x03C2]=0x03C2, [0x03C3]=0x03C3, [0x03C4]=0x03C4,
+ [0x03C5]=0x03C5, [0x03C6]=0x03C6, [0x03C7]=0x03C7, [0x03C8]=0x03C8, [0x03C9]=0x03C9,
+ [0x03D1]=0x03D1, [0x03D5]=0x03D5, [0x03D6]=0x03D6, [0x03F0]=0x03F0, [0x03F1]=0x03F1,
+ [0x03F4]=0x03F4, [0x03F5]=0x03F5,
+ },
+ symbols = {
+ [0x2202]=0x2202, [0x2207]=0x2207,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local regular_it = {
+ digits = tovector(regular_tf.digits),
+ ucletters = toupper(0x1D434),
+ lcletters = { -- H
+ [0x00061]=0x1D44E, [0x00062]=0x1D44F, [0x00063]=0x1D450, [0x00064]=0x1D451, [0x00065]=0x1D452,
+ [0x00066]=0x1D453, [0x00067]=0x1D454, [0x00068]=0x0210E, [0x00069]=0x1D456, [0x0006A]=0x1D457,
+ [0x0006B]=0x1D458, [0x0006C]=0x1D459, [0x0006D]=0x1D45A, [0x0006E]=0x1D45B, [0x0006F]=0x1D45C,
+ [0x00070]=0x1D45D, [0x00071]=0x1D45E, [0x00072]=0x1D45F, [0x00073]=0x1D460, [0x00074]=0x1D461,
+ [0x00075]=0x1D462, [0x00076]=0x1D463, [0x00077]=0x1D464, [0x00078]=0x1D465, [0x00079]=0x1D466,
+ [0x0007A]=0x1D467,
+ -- arabic
+ [0x00627] = 0x1EE00, [0x00628] = 0x1EE21, [0x0062A] = 0x1EE15, [0x0062B] = 0x1EE16,
+ [0x0062C] = 0x1EE22, [0x0062D] = 0x1EE07, [0x0062E] = 0x1EE17, [0x0062F] = 0x1EE03,
+ [0x00630] = 0x1EE18, [0x00631] = 0x1EE13, [0x00632] = 0x1EE06, [0x00633] = 0x1EE0E,
+ [0x00634] = 0x1EE14, [0x00635] = 0x1EE11, [0x00636] = 0x1EE19, [0x00637] = 0x1EE08,
+ [0x00638] = 0x1EE1A, [0x00639] = 0x1EE0F, [0x0063A] = 0x1EE1B, [0x00641] = 0x1EE10,
+ [0x00642] = 0x1EE12, [0x00643] = 0x1EE0A, [0x00644] = 0x1EE0B, [0x00645] = 0x1EE0C,
+ [0x00646] = 0x1EE0D, [0x00647] = 0x1EE24, [0x00648] = 0x1EE05, [0x0064A] = 0x1EE09,
+ [0x0066E] = 0x1EE1C, [0x0066F] = 0x1EE1F, [0x006A1] = 0x1EE1E, [0x006BA] = 0x1EE1D,
+ },
+ ucgreek = {
+ [0x0391]=0x1D6E2, [0x0392]=0x1D6E3, [0x0393]=0x1D6E4, [0x0394]=0x1D6E5, [0x0395]=0x1D6E6,
+ [0x0396]=0x1D6E7, [0x0397]=0x1D6E8, [0x0398]=0x1D6E9, [0x0399]=0x1D6EA, [0x039A]=0x1D6EB,
+ [0x039B]=0x1D6EC, [0x039C]=0x1D6ED, [0x039D]=0x1D6EE, [0x039E]=0x1D6EF, [0x039F]=0x1D6F0,
+ [0x03A0]=0x1D6F1, [0x03A1]=0x1D6F2, [0x03A3]=0x1D6F4, [0x03A4]=0x1D6F5, [0x03A5]=0x1D6F6,
+ [0x03A6]=0x1D6F7, [0x03A7]=0x1D6F8, [0x03A8]=0x1D6F9, [0x03A9]=0x1D6FA,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D6FC, [0x03B2]=0x1D6FD, [0x03B3]=0x1D6FE, [0x03B4]=0x1D6FF, [0x03B5]=0x1D700,
+ [0x03B6]=0x1D701, [0x03B7]=0x1D702, [0x03B8]=0x1D703, [0x03B9]=0x1D704, [0x03BA]=0x1D705,
+ [0x03BB]=0x1D706, [0x03BC]=0x1D707, [0x03BD]=0x1D708, [0x03BE]=0x1D709, [0x03BF]=0x1D70A,
+ [0x03C0]=0x1D70B, [0x03C1]=0x1D70C, [0x03C2]=0x1D70D, [0x03C3]=0x1D70E, [0x03C4]=0x1D70F,
+ [0x03C5]=0x1D710, [0x03C6]=0x1D711, [0x03C7]=0x1D712, [0x03C8]=0x1D713, [0x03C9]=0x1D714,
+ [0x03D1]=0x1D717, [0x03D5]=0x1D719, [0x03D6]=0x1D71B, [0x03F0]=0x1D718, [0x03F1]=0x1D71A,
+ [0x03F4]=0x1D6F3, [0x03F5]=0x1D716,
+ },
+ symbols = {
+ [0x2202]=0x1D715, [0x2207]=0x1D6FB,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local regular_bf= {
+ digits = todigit(0x1D7CE),
+ ucletters = toupper(0x1D400),
+ lcletters = tolower(0x1D41A),
+ ucgreek = {
+ [0x0391]=0x1D6A8, [0x0392]=0x1D6A9, [0x0393]=0x1D6AA, [0x0394]=0x1D6AB, [0x0395]=0x1D6AC,
+ [0x0396]=0x1D6AD, [0x0397]=0x1D6AE, [0x0398]=0x1D6AF, [0x0399]=0x1D6B0, [0x039A]=0x1D6B1,
+ [0x039B]=0x1D6B2, [0x039C]=0x1D6B3, [0x039D]=0x1D6B4, [0x039E]=0x1D6B5, [0x039F]=0x1D6B6,
+ [0x03A0]=0x1D6B7, [0x03A1]=0x1D6B8, [0x03A3]=0x1D6BA, [0x03A4]=0x1D6BB, [0x03A5]=0x1D6BC,
+ [0x03A6]=0x1D6BD, [0x03A7]=0x1D6BE, [0x03A8]=0x1D6BF, [0x03A9]=0x1D6C0,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D6C2, [0x03B2]=0x1D6C3, [0x03B3]=0x1D6C4, [0x03B4]=0x1D6C5, [0x03B5]=0x1D6C6,
+ [0x03B6]=0x1D6C7, [0x03B7]=0x1D6C8, [0x03B8]=0x1D6C9, [0x03B9]=0x1D6CA, [0x03BA]=0x1D6CB,
+ [0x03BB]=0x1D6CC, [0x03BC]=0x1D6CD, [0x03BD]=0x1D6CE, [0x03BE]=0x1D6CF, [0x03BF]=0x1D6D0,
+ [0x03C0]=0x1D6D1, [0x03C1]=0x1D6D2, [0x03C2]=0x1D6D3, [0x03C3]=0x1D6D4, [0x03C4]=0x1D6D5,
+ [0x03C5]=0x1D6D6, [0x03C6]=0x1D6D7, [0x03C7]=0x1D6D8, [0x03C8]=0x1D6D9, [0x03C9]=0x1D6DA,
+ [0x03D1]=0x1D6DD, [0x03D5]=0x1D6DF, [0x03D6]=0x1D6E1, [0x03F0]=0x1D6DE, [0x03F1]=0x1D6E0,
+ [0x03F4]=0x1D6B9, [0x03F5]=0x1D6DC,
+ },
+ symbols = {
+ [0x2202]=0x1D6DB, [0x2207]=0x1D6C1,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local regular_bi = {
+ digits = tovector(regular_bf.digits),
+ ucletters = toupper(0x1D468),
+ lcletters = tolower(0x1D482),
+ ucgreek = {
+ [0x0391]=0x1D71C, [0x0392]=0x1D71D, [0x0393]=0x1D71E, [0x0394]=0x1D71F, [0x0395]=0x1D720,
+ [0x0396]=0x1D721, [0x0397]=0x1D722, [0x0398]=0x1D723, [0x0399]=0x1D724, [0x039A]=0x1D725,
+ [0x039B]=0x1D726, [0x039C]=0x1D727, [0x039D]=0x1D728, [0x039E]=0x1D729, [0x039F]=0x1D72A,
+ [0x03A0]=0x1D72B, [0x03A1]=0x1D72C, [0x03A3]=0x1D72E, [0x03A4]=0x1D72F, [0x03A5]=0x1D730,
+ [0x03A6]=0x1D731, [0x03A7]=0x1D732, [0x03A8]=0x1D733, [0x03A9]=0x1D734,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D736, [0x03B2]=0x1D737, [0x03B3]=0x1D738, [0x03B4]=0x1D739, [0x03B5]=0x1D73A,
+ [0x03B6]=0x1D73B, [0x03B7]=0x1D73C, [0x03B8]=0x1D73D, [0x03B9]=0x1D73E, [0x03BA]=0x1D73F,
+ [0x03BB]=0x1D740, [0x03BC]=0x1D741, [0x03BD]=0x1D742, [0x03BE]=0x1D743, [0x03BF]=0x1D744,
+ [0x03C0]=0x1D745, [0x03C1]=0x1D746, [0x03C2]=0x1D747, [0x03C3]=0x1D748, [0x03C4]=0x1D749,
+ [0x03C5]=0x1D74A, [0x03C6]=0x1D74B, [0x03C7]=0x1D74C, [0x03C8]=0x1D74D, [0x03C9]=0x1D74E,
+ [0x03D1]=0x1D751, [0x03D5]=0x1D753, [0x03D6]=0x1D755, [0x03F0]=0x1D752, [0x03F1]=0x1D754,
+ [0x03F4]=0x1D72D, [0x03F5]=0x1D750,
+ },
+ symbols = {
+ [0x2202]=0x1D74F, [0x2207]=0x1D735,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local regular = {
+ tf = regular_tf,
+ it = regular_it,
+ bf = regular_bf,
+ bi = regular_bi,
+}
+
+local sansserif_tf = {
+ digits = todigit(0x1D7E2),
+ ucletters = toupper(0x1D5A0),
+ lcletters = tolower(0x1D5BA),
+ lcgreek = tovector(regular_tf.lcgreek),
+ ucgreek = tovector(regular_tf.ucgreek),
+ symbols = tovector(regular_tf.symbols),
+}
+
+local sansserif_it = {
+ digits = tovector(regular_tf.digits),
+ ucletters = toupper(0x1D608),
+ lcletters = tolower(0x1D622),
+ lcgreek = tovector(regular_tf.lcgreek),
+ ucgreek = tovector(regular_tf.ucgreek),
+ symbols = tovector(regular_tf.symbols),
+}
+
+local sansserif_bf = {
+ digits = todigit(0x1D7EC),
+ ucletters = toupper(0x1D5D4),
+ lcletters = tolower(0x1D5EE),
+ ucgreek = {
+ [0x0391]=0x1D756, [0x0392]=0x1D757, [0x0393]=0x1D758, [0x0394]=0x1D759, [0x0395]=0x1D75A,
+ [0x0396]=0x1D75B, [0x0397]=0x1D75C, [0x0398]=0x1D75D, [0x0399]=0x1D75E, [0x039A]=0x1D75F,
+ [0x039B]=0x1D760, [0x039C]=0x1D761, [0x039D]=0x1D762, [0x039E]=0x1D763, [0x039F]=0x1D764,
+ [0x03A0]=0x1D765, [0x03A1]=0x1D766, [0x03A3]=0x1D768, [0x03A4]=0x1D769, [0x03A5]=0x1D76A,
+ [0x03A6]=0x1D76B, [0x03A7]=0x1D76C, [0x03A8]=0x1D76D, [0x03A9]=0x1D76E,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D770, [0x03B2]=0x1D771, [0x03B3]=0x1D772, [0x03B4]=0x1D773, [0x03B5]=0x1D774,
+ [0x03B6]=0x1D775, [0x03B7]=0x1D776, [0x03B8]=0x1D777, [0x03B9]=0x1D778, [0x03BA]=0x1D779,
+ [0x03BB]=0x1D77A, [0x03BC]=0x1D77B, [0x03BD]=0x1D77C, [0x03BE]=0x1D77D, [0x03BF]=0x1D77E,
+ [0x03C0]=0x1D77F, [0x03C1]=0x1D780, [0x03C2]=0x1D781, [0x03C3]=0x1D782, [0x03C4]=0x1D783,
+ [0x03C5]=0x1D784, [0x03C6]=0x1D785, [0x03C7]=0x1D786, [0x03C8]=0x1D787, [0x03C9]=0x1D788,
+ [0x03D1]=0x1D78B, [0x03D5]=0x1D78D, [0x03D6]=0x1D78F, [0x03F0]=0x1D78C, [0x03F1]=0x1D78E,
+ [0x03F4]=0x1D767, [0x03F5]=0x1D78A,
+ },
+ symbols = {
+ [0x2202]=0x1D789, [0x2207]=0x1D76F,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local sansserif_bi = {
+ digits = tovector(sansserif_bf.digits),
+ ucletters = toupper(0x1D63C),
+ lcletters = tolower(0x1D656),
+ ucgreek = {
+ [0x0391]=0x1D790, [0x0392]=0x1D791, [0x0393]=0x1D792, [0x0394]=0x1D793, [0x0395]=0x1D794,
+ [0x0396]=0x1D795, [0x0397]=0x1D796, [0x0398]=0x1D797, [0x0399]=0x1D798, [0x039A]=0x1D799,
+ [0x039B]=0x1D79A, [0x039C]=0x1D79B, [0x039D]=0x1D79C, [0x039E]=0x1D79D, [0x039F]=0x1D79E,
+ [0x03A0]=0x1D79F, [0x03A1]=0x1D7A0, [0x03A3]=0x1D7A2, [0x03A4]=0x1D7A3, [0x03A5]=0x1D7A4,
+ [0x03A6]=0x1D7A5, [0x03A7]=0x1D7A6, [0x03A8]=0x1D7A7, [0x03A9]=0x1D7A8,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D7AA, [0x03B2]=0x1D7AB, [0x03B3]=0x1D7AC, [0x03B4]=0x1D7AD, [0x03B5]=0x1D7AE,
+ [0x03B6]=0x1D7AF, [0x03B7]=0x1D7B0, [0x03B8]=0x1D7B1, [0x03B9]=0x1D7B2, [0x03BA]=0x1D7B3,
+ [0x03BB]=0x1D7B4, [0x03BC]=0x1D7B5, [0x03BD]=0x1D7B6, [0x03BE]=0x1D7B7, [0x03BF]=0x1D7B8,
+ [0x03C0]=0x1D7B9, [0x03C1]=0x1D7BA, [0x03C2]=0x1D7BB, [0x03C3]=0x1D7BC, [0x03C4]=0x1D7BD,
+ [0x03C5]=0x1D7BE, [0x03C6]=0x1D7BF, [0x03C7]=0x1D7C0, [0x03C8]=0x1D7C1, [0x03C9]=0x1D7C2,
+ [0x03D1]=0x1D7C5, [0x03D5]=0x1D7C7, [0x03D6]=0x1D7C9, [0x03F0]=0x1D7C6, [0x03F1]=0x1D7C8,
+ [0x03F4]=0x1D7A1, [0x03F5]=0x1D7C4,
+ },
+ symbols = {
+ [0x2202]=0x1D7C3, [0x2207]=0x1D7A9,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+local sansserif = {
+ tf = sansserif_tf,
+ it = sansserif_it,
+ bf = sansserif_bf,
+ bi = sansserif_bi,
+}
+
+local monospaced_tf = {
+ digits = todigit(0x1D7F6),
+ ucletters = toupper(0x1D670),
+ lcletters = tolower(0x1D68A),
+ lcgreek = tovector(sansserif_tf.lcgreek),
+ ucgreek = tovector(sansserif_tf.ucgreek),
+ symbols = tovector(sansserif_tf.symbols),
+}
+
+local monospaced_it = tovector(sansserif_it)
+local monospaced_bf = tovector(sansserif_bf)
+local monospaced_bi = tovector(sansserif_bi)
+
+local monospaced = {
+ tf = monospaced_tf,
+ it = monospaced_tf,
+ bf = monospaced_tf,
+ bi = monospaced_bf,
+}
+
+local blackboard_tf = {
+ digits = todigit(0x1D7D8),
+ ucletters = { -- C H N P Q R Z
+ [0x00041]=0x1D538, [0x00042]=0x1D539, [0x00043]=0x02102, [0x00044]=0x1D53B, [0x00045]=0x1D53C,
+ [0x00046]=0x1D53D, [0x00047]=0x1D53E, [0x00048]=0x0210D, [0x00049]=0x1D540, [0x0004A]=0x1D541,
+ [0x0004B]=0x1D542, [0x0004C]=0x1D543, [0x0004D]=0x1D544, [0x0004E]=0x02115, [0x0004F]=0x1D546,
+ [0x00050]=0x02119, [0x00051]=0x0211A, [0x00052]=0x0211D, [0x00053]=0x1D54A, [0x00054]=0x1D54B,
+ [0x00055]=0x1D54C, [0x00056]=0x1D54D, [0x00057]=0x1D54E, [0x00058]=0x1D54F, [0x00059]=0x1D550,
+ [0x0005A]=0x02124,
+ },
+ lcletters = {
+ -- tolower(0x1D552) :
+ [0x00061] = 0x1D552, [0x00062] = 0x1D553, [0x00063] = 0x1D554, [0x00064] = 0x1D555,
+ [0x00065] = 0x1D556, [0x00066] = 0x1D557, [0x00067] = 0x1D558, [0x00068] = 0x1D559,
+ [0x00069] = 0x1D55A, [0x0006A] = 0x1D55B, [0x0006B] = 0x1D55C, [0x0006C] = 0x1D55D,
+ [0x0006D] = 0x1D55E, [0x0006E] = 0x1D55F, [0x0006F] = 0x1D560, [0x00070] = 0x1D561,
+ [0x00071] = 0x1D562, [0x00072] = 0x1D563, [0x00073] = 0x1D564, [0x00074] = 0x1D565,
+ [0x00075] = 0x1D566, [0x00076] = 0x1D567, [0x00077] = 0x1D568, [0x00078] = 0x1D569,
+ [0x00079] = 0x1D56A, [0x0007A] = 0x1D56B,
+ -- arabic
+ [0x00628] = 0x1EEA1, [0x0062A] = 0x1EEB5, [0x0062B] = 0x1EEB6, [0x0062C] = 0x1EEA2,
+ [0x0062D] = 0x1EEA7, [0x0062E] = 0x1EEB7, [0x0062F] = 0x1EEA3, [0x00630] = 0x1EEB8,
+ [0x00631] = 0x1EEB3, [0x00632] = 0x1EEA6, [0x00633] = 0x1EEAE, [0x00634] = 0x1EEB4,
+ [0x00635] = 0x1EEB1, [0x00636] = 0x1EEB9, [0x00637] = 0x1EEA8, [0x00638] = 0x1EEBA,
+ [0x00639] = 0x1EEAF, [0x0063A] = 0x1EEBB, [0x00641] = 0x1EEB0, [0x00642] = 0x1EEB2,
+ [0x00644] = 0x1EEAB, [0x00645] = 0x1EEAC, [0x00646] = 0x1EEAD, [0x00648] = 0x1EEA5,
+ [0x0064A] = 0x1EEA9,
+ },
+ lcgreek = { -- gamma pi
+ [0x03B3]=0x0213C, [0x03C0]=0x0213D,
+ },
+ ucgreek = { -- Gamma pi
+ [0x0393]=0x0213E, [0x03A0]=0x0213F,
+ },
+ symbols = { -- sum
+ [0x2211]=0x02140,
+ [0x0027]=0x2032, -- prime
+ },
+}
+
+blackboard_tf.lcgreek = merged(regular_tf.lcgreek, blackboard_tf.lcgreek)
+blackboard_tf.ucgreek = merged(regular_tf.ucgreek, blackboard_tf.ucgreek)
+blackboard_tf.symbols = merged(regular_tf.symbols, blackboard_tf.symbols)
+
+local blackboard = {
+ tf = blackboard_tf,
+ it = blackboard_tf,
+ bf = blackboard_tf,
+ bi = blackboard_tf,
+}
+
+local fraktur_tf= {
+ digits = tovector(regular_tf.digits),
+ ucletters = { -- C H I R Z
+ [0x00041]=0x1D504, [0x00042]=0x1D505, [0x00043]=0x0212D, [0x00044]=0x1D507, [0x00045]=0x1D508,
+ [0x00046]=0x1D509, [0x00047]=0x1D50A, [0x00048]=0x0210C, [0x00049]=0x02111, [0x0004A]=0x1D50D,
+ [0x0004B]=0x1D50E, [0x0004C]=0x1D50F, [0x0004D]=0x1D510, [0x0004E]=0x1D511, [0x0004F]=0x1D512,
+ [0x00050]=0x1D513, [0x00051]=0x1D514, [0x00052]=0x0211C, [0x00053]=0x1D516, [0x00054]=0x1D517,
+ [0x00055]=0x1D518, [0x00056]=0x1D519, [0x00057]=0x1D51A, [0x00058]=0x1D51B, [0x00059]=0x1D51C,
+ [0x0005A]=0x02128,
+ },
+ lcletters = tolower(0x1D51E),
+ lcgreek = tovector(regular_tf.lcgreek),
+ ucgreek = tovector(regular_tf.ucgreek),
+ symbols = tovector(regular_tf.symbols),
+}
+
+local fraktur_bf = {
+ digits = tovector(regular_bf.digits),
+ ucletters = toupper(0x1D56C),
+ lcletters = tolower(0x1D586),
+ lcgreek = tovector(regular_bf.lcgreek),
+ ucgreek = tovector(regular_bf.ucgreek),
+ symbols = tovector(regular_bf.symbols),
+}
+
+local fraktur = { -- ok
+ tf = fraktur_tf,
+ bf = fraktur_bf,
+ it = fraktur_tf,
+ bi = fraktur_bf,
+}
+
+local script_tf = {
+ digits = tovector(regular_tf.digits),
+ ucletters = { -- B E F H I L M R -- P 2118
+ [0x00041]=0x1D49C, [0x00042]=0x0212C, [0x00043]=0x1D49E, [0x00044]=0x1D49F, [0x00045]=0x02130,
+ [0x00046]=0x02131, [0x00047]=0x1D4A2, [0x00048]=0x0210B, [0x00049]=0x02110, [0x0004A]=0x1D4A5,
+ [0x0004B]=0x1D4A6, [0x0004C]=0x02112, [0x0004D]=0x02133, [0x0004E]=0x1D4A9, [0x0004F]=0x1D4AA,
+ [0x00050]=0x1D4AB, [0x00051]=0x1D4AC, [0x00052]=0x0211B, [0x00053]=0x1D4AE, [0x00054]=0x1D4AF,
+ [0x00055]=0x1D4B0, [0x00056]=0x1D4B1, [0x00057]=0x1D4B2, [0x00058]=0x1D4B3, [0x00059]=0x1D4B4,
+ [0x0005A]=0x1D4B5,
+ },
+ lcletters = { -- E G O -- L 2113
+ [0x00061]=0x1D4B6, [0x00062]=0x1D4B7, [0x00063]=0x1D4B8, [0x00064]=0x1D4B9, [0x00065]=0x0212F,
+ [0x00066]=0x1D4BB, [0x00067]=0x0210A, [0x00068]=0x1D4BD, [0x00069]=0x1D4BE, [0x0006A]=0x1D4BF,
+ [0x0006B]=0x1D4C0, [0x0006C]=0x1D4C1, [0x0006D]=0x1D4C2, [0x0006E]=0x1D4C3, [0x0006F]=0x02134,
+ [0x00070]=0x1D4C5, [0x00071]=0x1D4C6, [0x00072]=0x1D4C7, [0x00073]=0x1D4C8, [0x00074]=0x1D4C9,
+ [0x00075]=0x1D4CA, [0x00076]=0x1D4CB, [0x00077]=0x1D4CC, [0x00078]=0x1D4CD, [0x00079]=0x1D4CE,
+ [0x0007A]=0x1D4CF,
+ },
+ lcgreek = tovector(regular_tf.lcgreek),
+ ucgreek = tovector(regular_tf.ucgreek),
+ symbols = tovector(regular_tf.symbols),
+}
+
+local script_bf = {
+ digits = tovector(regular_bf.digits),
+ ucletters = toupper(0x1D4D0),
+ lcletters = tolower(0x1D4EA),
+ lcgreek = tovector(regular_bf.lcgreek),
+ ucgreek = tovector(regular_bf.ucgreek),
+ symbols = tovector(regular_bf.symbols),
+}
+
+local script = {
+ tf = script_tf,
+ bf = script_bf,
+ it = script_tf,
+ bi = script_bf,
+}
+
+local alphabets = allocate {
+ regular = regular,
+ sansserif = sansserif,
+ monospaced = monospaced,
+ blackboard = blackboard,
+ fraktur = fraktur,
+ script = script,
+}
+
+alphabets.tt = tovector(monospaced)
+alphabets.ss = tovector(sansserif)
+alphabets.rm = tovector(regular)
+alphabets.bb = tovector(blackboard)
+alphabets.fr = tovector(fraktur)
+alphabets.sr = tovector(script)
+
+monospaced.normal = tovector(monospaced_tf)
+monospaced.italic = tovector(monospaced_it)
+monospaced.bold = tovector(monospaced_bf)
+monospaced.bolditalic = tovector(monospaced_bi)
+
+sansserif.normal = tovector(sansserif_tf)
+sansserif.italic = tovector(sansserif_it)
+sansserif.bold = tovector(sansserif_bf)
+sansserif.bolditalic = tovector(sansserif_bi)
+
+regular.normal = tovector(regular_tf)
+regular.italic = tovector(regular_it)
+regular.bold = tovector(regular_bf)
+regular.bolditalic = tovector(regular_bi)
+
+alphabets.serif = tovector(regular)
+alphabets.type = tovector(monospaced)
+alphabets.teletype = tovector(monospaced)
+
+mathematics.alphabets = alphabets
+
+local mathremap = allocate { }
+mathematics.mapremap = mathremap
+
+local boldmap = allocate { }
+mathematics.boldmap = boldmap
+
+-- all math (a bit of redundancy here)
+
+for alphabet, styles in next, alphabets do -- per 9/6/2011 we also have attr for missing
+ for style, data in next, styles do
+ -- let's keep the long names (for tracing)
+ local n = #mathremap + 1
+ local d = {
+ attribute = n,
+ alphabet = alphabet,
+ style = style,
+ }
+ styles[style] = d
+ setmetatableindex(d,data) -- we could use a alphadata table
+ mathremap[n] = d
+ end
+end
+
+-- bold math
+
+local function remapbold(tf,bf)
+ local styles = mathematics.styles
+ local sets = mathematics.sets
+ for i=1,#styles do
+ for j=1,#sets do
+ local one = styles[i]
+ local two = sets[j]
+ local a = alphabets[one]
+ local tf = a[tf][two]
+ local bf = a[bf][two]
+ if tf and bf then
+ for k, v in next, tf do
+ boldmap[v] = bf[k]
+ end
+ end
+ end
+ end
+end
+
+remapbold("tf","bf")
+remapbold("it","bi")
+
+-- table.save("e:/tmp/a.lua",alphabets)
+-- table.save("e:/tmp/b.lua",boldmap)
+
+function mathematics.tostyle(attribute)
+ local r = mathremap[attribute]
+ return r and r.style or "tf"
+end
+
+function mathematics.toname(attribute)
+ local r = mathremap[attribute]
+ return r and r.alphabet or "regular"
+end
+
+-- of course we could do some div/mod trickery instead
+
+local mathalphabet = attributes.private("mathalphabet")
+
+function mathematics.getboth(alphabet,style)
+ local data = alphabet and alphabets[alphabet] or regular
+ data = data[style or "tf"] or data.tf
+ return data and data.attribute
+end
+
+function mathematics.getstyle(style)
+ local r = mathremap[texgetattribute(mathalphabet)]
+ local alphabet = r and r.alphabet or "regular"
+ local data = alphabets[alphabet][style]
+ return data and data.attribute
+end
+
+function mathematics.syncboth(alphabet,style)
+ local data = alphabet and alphabets[alphabet] or regular
+ data = style and data[style] or data.tf
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+end
+
+function mathematics.syncstyle(style)
+ local r = mathremap[texgetattribute(mathalphabet)]
+ local alphabet = r and r.alphabet or "regular"
+ local data = alphabets[alphabet][style]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+end
+
+function mathematics.syncname(alphabet)
+ -- local r = mathremap[mathalphabet]
+ local r = mathremap[texgetattribute(mathalphabet)]
+ local style = r and r.style or "tf"
+ local data = alphabets[alphabet][style]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+end
+
+implement {
+ name = "setmathattribute",
+ arguments = { "string", "string" },
+ actions = function(alphabet,style)
+ local data = alphabets[alphabet] or regular
+ data = data[style] or data.tf
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+ end
+}
+
+implement {
+ name = "setmathstyle",
+ arguments = "string",
+ actions = function(style)
+ local r = mathremap[texgetattribute(mathalphabet)]
+ local alphabet = r and r.alphabet or "regular"
+ local data = alphabets[alphabet][style]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+ end
+}
+
+implement {
+ name = "setmathalphabet",
+ arguments = "string",
+ actions = function(alphabet)
+ -- local r = mathremap[mathalphabet]
+ local r = mathremap[texgetattribute(mathalphabet)]
+ local style = r and r.style or "tf"
+ local data = alphabets[alphabet][style]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
+ end
+}
+
+local islcgreek = regular_tf.lcgreek
+local isucgreek = regular_tf.ucgreek
+local issygreek = regular_tf.symbols
+local isgreek = merged(islcgreek,isucgreek,issygreek)
+
+local greekremapping = {
+ [1] = { what = "unchanged" }, -- upright
+ [2] = { what = "upright", it = "tf", bi = "bf" }, -- upright
+ [3] = { what = "italic", tf = "it", bf = "bi" }, -- italic
+}
+
+local usedremap = { }
+
+local function resolver(map)
+ return function (t,k)
+ local v =
+ map.digits [k] or
+ map.lcletters[k] or map.ucletters[k] or
+ map.lcgreek [k] or map.ucgreek [k] or
+ map.symbols [k] or k
+ t[k] = v
+ return v
+ end
+end
+
+for k, v in next, mathremap do
+ local t = { }
+ setmetatableindex(t,resolver(v))
+ usedremap[k] = t
+end
+
+local function remapgreek(mathalphabet,how,detail,char)
+ local r = mathremap[mathalphabet] -- what if 0
+ local alphabet = r and r.alphabet or "regular"
+ local style = r and r.style or "tf"
+ local remapping = greekremapping[how]
+ if trace_greek then
+ report_remapping("greek %s, %s char %C, alphabet %a %a, method %a","before",detail,char,alphabet,style,remapping.what)
+ end
+ local newstyle = remapping[style]
+ if newstyle then
+ local data = alphabets[alphabet][newstyle] -- always something
+ mathalphabet = data and data.attribute or mathalphabet
+ style = newstyle
+ end
+ if trace_greek then
+ report_remapping("greek %s, %s char %C, alphabet %a %a, method %a","after",detail,char,alphabet,style,remapping.what)
+ end
+ return mathalphabet, style
+end
+
+function mathematics.remapalphabets(char,mathalphabet,mathgreek)
+ if not mathalphabet then
+ return
+ end
+ if mathgreek and mathgreek > 0 then
+ if not isgreek[char] then
+ -- nothing needed
+ elseif islcgreek[char] then
+ local lc = extract(mathgreek,4,4)
+ if lc > 1 then
+ mathalphabet = remapgreek(mathalphabet,lc,"lowercase",char)
+ end
+ elseif isucgreek[char] then
+ local uc = extract(mathgreek,0,4)
+ if uc > 1 then
+ mathalphabet = remapgreek(mathalphabet,uc,"uppercase",char)
+ end
+ elseif issygreek[char] then
+ local sy = extract(mathgreek,8,4)
+ if sy > 1 then
+ mathalphabet = remapgreek(mathalphabet,sy,"symbol",char)
+ end
+ end
+ end
+ if mathalphabet > 0 then
+ local remap = usedremap[mathalphabet] -- redundant check
+ if remap then
+ local newchar = remap[char]
+ return newchar ~= char and newchar
+ end
+ end
+ -- return nil
+end
+
+-- begin of experiment
+
+local fallback = {
+ tf = "bf",
+ it = "bi",
+ bf = "tf",
+ bi = "it",
+}
+
+function mathematics.fallbackstyleattr(attribute)
+ local r = mathremap[attribute]
+ local alphabet = r.alphabet or "regular"
+ local style = r.style or "tf"
+ local fback = fallback[style]
+ if fback then
+ local data = alphabets[alphabet][fback]
+ if data then
+ local attr = data.attribute
+ return attribute ~= attr and attr
+ end
+ end
+end
+
+-- end of experiment
+
+local function checkedcopy(characters,child,parent)
+ for k, v in next, child do
+ if not characters[v] then
+ characters[v] = characters[parent[k]]
+ end
+ end
+end
+
+function mathematics.addfallbacks(main)
+ local characters = main.characters
+ checkedcopy(characters,regular.bf.ucgreek,regular.tf.ucgreek)
+ checkedcopy(characters,regular.bf.lcgreek,regular.tf.lcgreek)
+ checkedcopy(characters,regular.bi.ucgreek,regular.it.ucgreek)
+ checkedcopy(characters,regular.bi.lcgreek,regular.it.lcgreek)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-mis.mkiv
new file mode 100644
index 00000000000..6346da9a02d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-mis.mkiv
@@ -0,0 +1,60 @@
+%D \module
+%D [ file=math-mis,
+%D version=2013.04.06, % 2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Miscellaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Miscellaneous}
+
+\unprotect
+
+%D This file contains left-overs moved from other files. It's mostly old stuff
+%D that we keep around for compatbility reasons.
+
+%D \macros
+%D {qedsymbol}
+%D
+%D [HH] The general Quod Erat Demonstrandum symbol is defined in such a way that
+%D we can configure it. Because this symbol is also used in text mode, we make it
+%D a normal text symbol with special behavior.
+
+\unexpanded\def\qedsymbol#1%
+ {\ifhmode
+ \unskip\nobreakspace\hfill#1\par
+ \else\ifmmode
+ #1\relax % leading \eqno removed
+ \else
+ \dontleavehmode\emptyhbox\hfill#1\par
+ \fi\fi}
+
+\definesymbol [qed] [\qedsymbol{\mathematics{\square}}]
+
+%D \macros
+%D {QED}
+%D
+%D [HH] For compatbility reasons we also provide the \type {\QED} command. In case
+%D this command is overloaded, we still have the symbol available. \symbol[qed]
+
+\unexpanded\def\QED{\symbol[qed]}
+
+%D \macros
+%D {boxed}
+%D
+%D [HH] Another macro that users might expect (slightly adapted):
+
+\unexpanded\def\boxed % maybe obsolete
+ {\ifmmode\expandafter\mframed\else\expandafter\framed\fi}
+
+%D Something low level for scientific calculator notation:
+
+\unexpanded\def\scinot#1#2%
+ {#1\times10^{#2}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua b/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua
new file mode 100644
index 00000000000..d3409e01b25
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua
@@ -0,0 +1,1763 @@
+if not modules then modules = { } end modules ['math-noa'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware: this is experimental code and there will be a more generic (attribute value
+-- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will
+-- start cleaning up as by then the bigger picture is clear and code has been used for
+-- years; the main handlers will get some extensions)
+--
+-- we will also make dedicated processors (faster)
+--
+-- beware: names will change as we wil make noads.xxx.handler i.e. xxx
+-- subnamespaces
+
+-- 20D6 -> 2190
+-- 20D7 -> 2192
+
+-- todo: most is math_char so we can have simple dedicated loops
+
+-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types)
+
+local utfchar, utfbyte = utf.char, utf.byte
+local formatters = string.formatters
+local sortedhash = table.sortedhash
+local insert, remove = table.insert, table.remove
+local div = math.div
+
+local fonts = fonts
+local nodes = nodes
+local node = node
+local mathematics = mathematics
+local context = context
+
+local otf = fonts.handlers.otf
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local privateattribute = attributes.private
+local registertracker = trackers.register
+local registerdirective = directives.register
+local logreporter = logs.reporter
+
+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_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_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_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_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 setnext = nuts.setnext
+local setprev = nuts.setprev
+local setchar = nuts.setchar
+local setsubtype = nuts.setsubtype
+local setattr = nuts.setattr
+
+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 getattr = nuts.getattr
+
+local free_node = nuts.free
+local new_node = nuts.new -- todo: pool: math_noad math_sub
+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_rule = nodepool.rule
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+local fontproperties = fonthashes.properties
+local fontitalics = fonthashes.italics
+local fontemwidths = fonthashes.emwidths
+local fontexheights = fonthashes.exheights
+
+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 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_box = nodecodes.subbox -- attr list
+local math_sub = 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
+local math_style = nodecodes.style -- attr style
+local math_choice = nodecodes.choice -- attr display text script scriptscript
+local math_fence = nodecodes.fence -- attr subtype
+
+local left_fence_code = fencecodes.left
+local middle_fence_code = fencecodes.middle
+local right_fence_code = fencecodes.right
+
+-- this initial stuff is tricky as we can have removed and new nodes with the same address
+-- the only way out is a free-per-page list of nodes (not bad anyway)
+
+local function process(start,what,n,parent)
+ if n then
+ n = n + 1
+ else
+ n = 0
+ end
+ --
+ local initial = start
+ --
+ slide_nodes(start) -- we still miss a prev in noads -- fences test code
+ --
+ while start do
+ local id = getid(start)
+ if trace_processing then
+ if id == math_noad then
+ report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)])
+ elseif id == math_char then
+ local char = getchar(start)
+ local font = getfont(start)
+ local fam = getfield(start,"fam")
+ report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char)
+ else
+ report_processing("%w%S",n*2,nutstring(start))
+ end
+ end
+ local proc = what[id]
+ if proc then
+ -- report_processing("start processing")
+ local done, newstart, newinitial = proc(start,what,n,parent) -- prev is bugged: or getprev(start)
+ if newinitial then
+ initial = newinitial -- temp hack .. we will make all return head
+ if newstart then
+ start = newstart
+ -- report_processing("stop processing (new start)")
+ else
+ -- report_processing("quit processing (done)")
+ break
+ end
+ else
+ if newstart then
+ start = newstart
+ -- report_processing("stop processing (new start)")
+ else
+ -- report_processing("stop processing")
+ end
+ end
+ elseif id == math_noad then
+ -- single characters are like this
+ local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list
+ elseif id == math_char or id == math_textchar or id == math_delim then
+ break
+ elseif id == math_box or id == math_sub then
+ local noad = getfield(start,"list") if noad then process(noad,what,n,start) end -- list (not getlist !)
+ elseif id == math_fraction then
+ local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
+ noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter
+ elseif id == math_choice then
+ local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list
+ elseif id == math_fence then
+ local noad = getfield(start,"delim") if noad then process(noad,what,n,start) end -- delimiter
+ elseif id == math_radical then
+ local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sub") 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
+ local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"sub") 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
+ -- -- has a next
+ -- else
+ -- -- glue, penalty, etc
+ end
+ start = getnext(start)
+ end
+ if not parent then
+ return initial, true -- 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
+ noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sub") if noad then process(noad,what,n,current) end -- list
+ elseif id == math_box or id == math_sub then
+ noad = getfield(current,"list") if noad then process(noad,what,n,current) end -- list (not getlist !)
+ elseif id == math_fraction then
+ noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
+ noad = getfield(current,"right") if noad then process(noad,what,n,current) end -- delimiter
+ elseif id == math_choice then
+ noad = getfield(current,"display") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list
+ elseif id == math_fence then
+ noad = getfield(current,"delim") if noad then process(noad,what,n,current) end -- delimiter
+ elseif id == math_radical then
+ noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sub") 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
+ noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"sub") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list
+ end
+end
+
+local function processstep(current,process,n,id)
+ local noad = nil
+ local id = id or getid(current)
+ if id == math_noad then
+ noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sub") if noad then process(noad,n,current) end -- list
+ elseif id == math_box or id == math_sub then
+ noad = getfield(current,"list") if noad then process(noad,n,current) end -- list (not getlist !)
+ elseif id == math_fraction then
+ noad = getfield(current,"num") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
+ noad = getfield(current,"right") if noad then process(noad,n,current) end -- delimiter
+ elseif id == math_choice then
+ noad = getfield(current,"display") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"text") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"script") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list
+ elseif id == math_fence then
+ noad = getfield(current,"delim") if noad then process(noad,n,current) end -- delimiter
+ elseif id == math_radical then
+ noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sub") 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
+ noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"sub") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list
+ end
+end
+
+local function processnoads(head,actions,banner)
+ local h, d
+ if trace_processing then
+ report_processing("start %a",banner)
+ h, d = process(tonut(head),actions)
+ report_processing("stop %a",banner)
+ else
+ h, d = process(tonut(head),actions)
+ end
+ return h and tonode(h) or head, d == nil and true or d
+end
+
+noads.process = processnoads
+noads.processnested = processnested
+noads.processouter = process
+
+
+-- experiment (when not present fall back to fam 0) -- needs documentation
+
+local unknowns = { }
+local checked = { } -- simple case
+local tracked = false trackers.register("fonts.missing", function(v) tracked = v end)
+local cached = table.setmetatableindex("table") -- complex case
+
+local function errorchar(font,char)
+ local done = unknowns[char]
+ if done then
+ unknowns[char] = done + 1
+ else
+ unknowns[char] = 1
+ end
+ if tracked then
+ -- slower as we check each font too and we always replace as math has
+ -- more demands than text
+ local fake = cached[font][char]
+ if fake then
+ return fake
+ else
+ local kind, fake = fonts.checkers.placeholder(font,char)
+ if not fake or kind ~= "char" then
+ fake = 0x3F
+ end
+ cached[font][char] = fake
+ return fake
+ end
+ else
+ -- only simple checking, report at the end so one should take
+ -- action anyway ... we can miss a few checks but that is ok
+ -- as there is at least one reported
+ if not checked[char] then
+ if trace_normalizing then
+ report_normalizing("character %C is not available",char)
+ end
+ checked[char] = true
+ end
+ return 0x3F
+ end
+end
+
+-- 0-2 regular
+-- 3-5 bold
+-- 6-8 pseudobold
+
+-- this could best be integrated in the remapper, and if we run into problems, we
+-- might as well do this
+
+do
+
+ local families = { }
+ local a_mathfamily = privateattribute("mathfamily")
+ local boldmap = mathematics.boldmap
+
+ local familymap = { [0] =
+ "regular",
+ "regular",
+ "regular",
+ "bold",
+ "bold",
+ "bold",
+ "pseudobold",
+ "pseudobold",
+ "pseudobold",
+ }
+
+ families[math_char] = function(pointer)
+ if getfield(pointer,"fam") == 0 then
+ local a = getattr(pointer,a_mathfamily)
+ if a and a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ local char = getchar(pointer)
+ local bold = boldmap[char]
+ local newa = a - 3
+ if not bold then
+ if trace_families then
+ report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
+ end
+ setfield(pointer,"fam",newa)
+ elseif not fontcharacters[font_of_family(newa)][bold] then
+ if trace_families then
+ report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
+ end
+ if newa > 3 then
+ setfield(pointer,"fam",newa-3)
+ end
+ else
+ setattr(pointer,a_exportstatus,char)
+ setchar(pointer,bold)
+ if trace_families then
+ report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa])
+ end
+ setfield(pointer,"fam",newa)
+ end
+ else
+ local char = getchar(pointer)
+ if not fontcharacters[font_of_family(a)][char] then
+ if trace_families then
+ report_families("no bold replacement for %C",char)
+ end
+ else
+ if trace_families then
+ report_families("family of %C becomes %s with remap %s",char,a,familymap[a])
+ end
+ setfield(pointer,"fam",a)
+ end
+ end
+ end
+ end
+ end
+
+ families[math_delim] = function(pointer)
+ if getfield(pointer,"small_fam") == 0 then
+ local a = getattr(pointer,a_mathfamily)
+ if a and a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ -- no bold delimiters in unicode
+ a = a - 3
+ end
+ local char = getfield(pointer,"small_char")
+ local okay = fontcharacters[font_of_family(a)][char]
+ if okay then
+ setfield(pointer,"small_fam",a)
+ elseif a > 2 then
+ setfield(pointer,"small_fam",a-3)
+ end
+ local char = getfield(pointer,"large_char")
+ local okay = fontcharacters[font_of_family(a)][char]
+ if okay then
+ setfield(pointer,"large_fam",a)
+ elseif a > 2 then
+ setfield(pointer,"large_fam",a-3)
+ end
+ else
+ setfield(pointer,"small_fam",0)
+ setfield(pointer,"large_fam",0)
+ end
+ end
+ end
+
+ families[math_textchar] = families[math_char]
+
+ function handlers.families(head,style,penalties)
+ processnoads(head,families,"families")
+ return true
+ end
+
+end
+
+-- character remapping
+
+do
+
+ local a_mathalphabet = privateattribute("mathalphabet")
+ local a_mathgreek = privateattribute("mathgreek")
+
+ processors.relocate = { }
+
+ local function report_remap(tag,id,old,new,extra)
+ report_remapping("remapping %s in font %s from %C to %C%s",tag,id,old,new,extra)
+ end
+
+ local remapalphabets = mathematics.remapalphabets
+ local fallbackstyleattr = mathematics.fallbackstyleattr
+ local setnodecolor = nodes.tracers.colors.set
+
+ local function checked(pointer)
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local data = fontcharacters[font]
+ if not data[char] then
+ local specials = characters.data[char].specials
+ if specials and (specials[1] == "char" or specials[1] == "font") then
+ local newchar = specials[#specials]
+ if trace_remapping then
+ report_remap("fallback",font,char,newchar)
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setattr(pointer,a_exportstatus,char) -- testcase: exponentiale
+ setchar(pointer,newchar)
+ return true
+ end
+ end
+ end
+
+ processors.relocate[math_char] = function(pointer)
+ local g = getattr(pointer,a_mathgreek) or 0
+ local a = getattr(pointer,a_mathalphabet) or 0
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local characters = fontcharacters[font]
+ if a > 0 or g > 0 then
+ if a > 0 then
+ setattr(pointer,a_mathgreek,0)
+ end
+ if g > 0 then
+ setattr(pointer,a_mathalphabet,0)
+ end
+ local newchar = remapalphabets(char,a,g)
+ if newchar then
+ if characters[newchar] then
+ if trace_remapping then
+ report_remap("char",font,char,newchar)
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setchar(pointer,newchar)
+ return true
+ else
+ local fallback = fallbackstyleattr(a)
+ if fallback then
+ local newchar = remapalphabets(char,fallback,g)
+ if newchar then
+ if characters[newchar] then
+ if trace_remapping then
+ report_remap("char",font,char,newchar," (fallback remapping used)")
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setchar(pointer,newchar)
+ return true
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback character)")
+ end
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback remap character)")
+ end
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback style)")
+ end
+ end
+ end
+ end
+ if not characters[char] then
+ setchar(pointer,errorchar(font,char))
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:medi")
+ end
+ if check_coverage then
+ return checked(pointer)
+ end
+ end
+
+ processors.relocate[math_textchar] = function(pointer)
+ if trace_analyzing then
+ setnodecolor(pointer,"font:init")
+ end
+ end
+
+ processors.relocate[math_delim] = function(pointer)
+ if trace_analyzing then
+ setnodecolor(pointer,"font:fina")
+ end
+ end
+
+ function handlers.relocate(head,style,penalties)
+ processnoads(head,processors.relocate,"relocate")
+ return true
+ end
+
+end
+
+-- rendering (beware, not exported)
+
+processors.render = { }
+
+local rendersets = mathematics.renderings.numbers or { } -- store
+
+processors.render[math_char] = function(pointer)
+ local attr = getattr(pointer,a_mathrendering)
+ if attr and attr > 0 then
+ local char = getchar(pointer)
+ local renderset = rendersets[attr]
+ if renderset then
+ local newchar = renderset[char]
+ if newchar then
+ local font = getfont(pointer)
+ local characters = fontcharacters[font]
+ if characters and characters[newchar] then
+ setchar(pointer,newchar)
+ setattr(pointer,a_exportstatus,char)
+ end
+ end
+ end
+ end
+end
+
+function handlers.render(head,style,penalties)
+ processnoads(head,processors.render,"render")
+ return true
+end
+
+-- some resize options (this works ok because the content is
+-- empty and no larger next will be forced)
+--
+-- beware: we don't use \delcode but \Udelcode and as such have
+-- no large_fam; also, we need to check for subtype and/or
+-- small_fam not being 0 because \. sits in 0,0 by default
+--
+-- todo: just replace the character by an ord noad
+-- and remove the right delimiter as well
+
+local a_mathsize = privateattribute("mathsize") -- this might move into other fence code
+local resize = { }
+processors.resize = resize
+
+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 = getfield(delimiter,"small_char")
+ if chr > 0 then
+ local fam = getfield(delimiter,"small_fam")
+ local id = font_of_family(fam)
+ if id > 0 then
+ setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method))
+ end
+ end
+ end
+ end
+end
+
+function handlers.resize(head,style,penalties)
+ processnoads(head,resize,"resize")
+ return true
+end
+
+local a_autofence = privateattribute("mathautofence")
+local autofences = { }
+processors.autofences = autofences
+local dummyfencechar = 0x2E
+
+local function makefence(what,char)
+ local d = new_node(math_delim)
+ local f = new_node(math_fence)
+ if char then
+ local sym = getfield(char,"nucleus")
+ local chr = getfield(sym,"char")
+ local fam = getfield(sym,"fam")
+ if chr == dummyfencechar then
+ chr = 0
+ end
+ setfield(d,"small_char",chr)
+ setfield(d,"small_fam", fam)
+ free_node(sym)
+ end
+ setsubtype(f,what)
+ setfield(f,"delim",d)
+ return f
+end
+
+local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
+ local list = new_node(math_sub)
+ setfield(list,"head",f_o)
+ setsubtype(noad,noad_inner)
+ setfield(noad,"nucleus",list)
+ setlink(f_o,o_next)
+ setlink(c_prev,f_c)
+ if middle and next(middle) then
+ local prev = f_o
+ local current = o_next
+ while current ~= f_c do
+ local m = middle[current]
+ if m then
+ local next = getnext(current)
+ local fence = makefence(middle_fence_code,current)
+ setfield(current,"nucleus",nil)
+ free_node(current)
+ middle[current] = nil
+ -- replace_node
+ setlink(prev,fence)
+ setlink(fence,next)
+ prev = fence
+ current = next
+ else
+ prev = current
+ current = getnext(current)
+ end
+ end
+ end
+end
+
+local function convert_both(open,close,middle)
+ local o_prev, o_next = getboth(open)
+ local c_prev, c_next = getboth(close)
+ if o_next == close then
+ return close
+ else
+ local f_o = makefence(left_fence_code,open)
+ local f_c = makefence(right_fence_code,close)
+ makelist(open,f_o,o_next,c_prev,f_c,middle)
+ setfield(close,"nucleus",nil)
+ free_node(close)
+ if c_next then
+ setprev(c_next,open)
+ end
+ setnext(open,c_next)
+ return open
+ end
+end
+
+local function convert_open(open,last,middle)
+ local f_o = makefence(left_fence_code,open)
+ local f_c = makefence(right_fence_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)
+ if l_next then
+ setprev(l_next,open)
+ end
+ setnext(open,l_next)
+ return open
+end
+
+local function convert_close(close,first,middle)
+ local f_o = makefence(left_fence_code)
+ local f_c = makefence(right_fence_code,close)
+ local c_prev = getprev(close)
+ makelist(close,f_o,first,c_prev,f_c,middle)
+ return close
+end
+
+local stacks = table.setmetatableindex("table")
+
+local function processfences(pointer,n,parent)
+ local current = pointer
+ local last = pointer
+ local start = pointer
+ local done = false
+ local initial = pointer
+ local stack = nil
+ local middle = nil -- todo: use properties
+ while current do
+ local id = getid(current)
+ if id == math_noad then
+ local a = getattr(current,a_autofence)
+ if a and a > 0 then
+ local stack = stacks[n]
+ setattr(current,a_autofence,0)
+ if a == 1 or (a == 4 and (not stack or #stack == 0)) then
+ if trace_fences then
+ report_fences("%2i: pushing open on stack",n)
+ end
+ insert(stack,current)
+ elseif a == 2 or a == 4 then
+ local open = remove(stack)
+ if open then
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"both",#stack)
+ end
+ current = convert_both(open,current,middle)
+ elseif current == start then
+ -- skip
+ else
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"close",#stack)
+ end
+ current = convert_close(current,initial,middle)
+ if not parent then
+ initial = current
+ end
+ end
+ elseif a == 3 then
+ if trace_fences then
+ report_fences("%2i: registering middle",n)
+ end
+ if middle then
+ middle[current] = last
+ else
+ middle = { [current] = last }
+ end
+ end
+ done = true
+ else
+ processstep(current,processfences,n+1,id)
+ end
+ else
+ -- next at current level
+ processstep(current,processfences,n,id)
+ end
+ last = current
+ current = getnext(current)
+ end
+ if done then
+ local stack = stacks[n]
+ local s = #stack
+ if s > 0 then
+ if trace_fences then
+ report_fences("%2i: handling %s stack levels",n,s)
+ end
+ for i=1,s do
+ local open = remove(stack)
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"open",#stack)
+ end
+ last = convert_open(open,last,middle)
+ end
+ end
+ end
+end
+
+-- we can have a first changed node .. an option is to have a leading dummy node in math
+-- lists like the par node as it can save a lot of mess
+
+local enabled = false
+
+implement {
+ name = "enableautofences",
+ onlyonce = true,
+ actions = function()
+ tasks.enableaction("math","noads.handlers.autofences")
+ enabled = true
+ end
+}
+
+function handlers.autofences(head,style,penalties)
+ if enabled then -- tex.modes.c_math_fences_auto
+ -- inspect(nodes.totree(head))
+ processfences(tonut(head),1)
+ -- inspect(nodes.totree(head))
+ end
+end
+
+-- normalize scripts
+
+local unscript = { } noads.processors.unscript = unscript
+local superscripts = characters.superscripts
+local subscripts = characters.subscripts
+local fractions = characters.fractions
+local replaced = { }
+
+local function replace(pointer,what,n,parent)
+ pointer = parent -- we're following the parent list (chars trigger this)
+ local next = getnext(pointer)
+ local start_super, stop_super, start_sub, stop_sub
+ local mode = "unset"
+ while next and getid(next) == math_noad do
+ local nextnucleus = getfield(next,"nucleus")
+ if nextnucleus and getid(nextnucleus) == math_char and not getfield(next,"sub") and not getfield(next,"sup") then
+ local char = getchar(nextnucleus)
+ local s = superscripts[char]
+ if s then
+ if not start_super then
+ start_super = next
+ mode = "super"
+ elseif mode == "sub" then
+ break
+ end
+ stop_super = next
+ next = getnext(next)
+ setchar(nextnucleus,s)
+ replaced[char] = (replaced[char] or 0) + 1
+ if trace_normalizing then
+ report_normalizing("superscript %C becomes %C",char,s)
+ end
+ else
+ local s = subscripts[char]
+ if s then
+ if not start_sub then
+ start_sub = next
+ mode = "sub"
+ elseif mode == "super" then
+ break
+ end
+ stop_sub = next
+ next = getnext(next)
+ setchar(nextnucleus,s)
+ replaced[char] = (replaced[char] or 0) + 1
+ if trace_normalizing then
+ report_normalizing("subscript %C becomes %C",char,s)
+ end
+ else
+ break
+ end
+ end
+ else
+ break
+ end
+ end
+ if start_super then
+ if start_super == stop_super then
+ setfield(pointer,"sup",getfield(start_super,"nucleus"))
+ else
+ local list = new_node(math_sub) -- todo attr
+ setfield(list,"list",start_super)
+ setfield(pointer,"sup",list)
+ end
+ if mode == "super" then
+ setnext(pointer,getnext(stop_super))
+ end
+ setnext(stop_super)
+ end
+ if start_sub then
+ if start_sub == stop_sub then
+ setfield(pointer,"sub",getfield(start_sub,"nucleus"))
+ else
+ local list = new_node(math_sub) -- todo attr
+ setfield(list,"list",start_sub)
+ setfield(pointer,"sub",list)
+ end
+ if mode == "sub" then
+ setnext(pointer,getnext(stop_sub))
+ end
+ setnext(stop_sub)
+ end
+ -- we could return stop
+end
+
+unscript[math_char] = replace -- not noads as we need to recurse
+
+function handlers.unscript(head,style,penalties)
+ processnoads(head,unscript,"unscript")
+-- processnoads(head,checkers,"checkers")
+ return true
+end
+
+local function collected(list)
+ if list and next(list) then
+ local n, t = 0, { }
+ for k, v in sortedhash(list) do
+ n = n + v
+ t[#t+1] = formatters["%C"](k)
+ end
+ return formatters["% t (n=%s)"](t,n)
+ end
+end
+
+statistics.register("math script replacements", function()
+ return collected(replaced)
+end)
+
+statistics.register("unknown math characters", function()
+ return collected(unknowns)
+end)
+
+-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
+-- math alternates: (in lucidanova lgf: $ABC \mathalternate{italic} ABC$)
+
+-- todo: set alternate for specific symbols
+-- todo: no need to do this when already loaded
+
+local defaults = {
+ dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
+ -- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet)
+}
+
+local function initializemathalternates(tfmdata)
+ local goodies = tfmdata.goodies
+ local autolist = table.copy(defaults)
+
+ local function setthem(alternates)
+ local resources = tfmdata.resources -- was tfmdata.shared
+ local lastattribute = 0
+ local attributes = { }
+ for k, v in sortedhash(alternates) do
+ lastattribute = lastattribute + 1
+ v.attribute = lastattribute
+ attributes[lastattribute] = v
+ end
+ resources.mathalternates = alternates -- to be checked if shared is ok here
+ resources.mathalternatesattributes = attributes -- to be checked if shared is ok here
+ end
+
+ if goodies then
+ local done = { }
+ for i=1,#goodies do
+ -- first one counts
+ -- we can consider sharing the attributes ... todo (only once scan)
+ local mathgoodies = goodies[i].mathematics
+ local alternates = mathgoodies and mathgoodies.alternates
+ if alternates then
+ if trace_goodies then
+ report_goodies("loading alternates for font %a",tfmdata.properties.name)
+ end
+ for k, v in next, autolist do
+ if not alternates[k] then
+ alternates[k] = v
+ end
+ end
+ setthem(alternates)
+ return
+ end
+ end
+ end
+
+ if trace_goodies then
+ report_goodies("loading default alternates for font %a",tfmdata.properties.name)
+ end
+ setthem(autolist)
+
+end
+
+registerotffeature {
+ name = "mathalternates",
+ description = "additional math alternative shapes",
+ initializers = {
+ base = initializemathalternates,
+ node = initializemathalternates,
+ }
+}
+
+-- local getalternate = otf.getalternate (runtime new method so ...)
+
+-- todo: not shared but copies ... one never knows
+
+local a_mathalternate = privateattribute("mathalternate")
+
+local alternate = { } -- processors.alternate = alternate
+
+function mathematics.setalternate(fam,tag)
+ local id = font_of_family(fam)
+ local tfmdata = fontdata[id]
+ local resources = tfmdata.resources -- was tfmdata.shared
+ if resources then
+ local mathalternates = resources.mathalternates
+ if mathalternates then
+ local m = mathalternates[tag]
+ texsetattribute(a_mathalternate,m and m.attribute or unsetvalue)
+ end
+ end
+end
+
+implement {
+ name = "setmathalternate",
+ actions = mathematics.setalternate,
+ arguments = { "integer", "string" }
+}
+
+alternate[math_char] = function(pointer)
+ local a = getattr(pointer,a_mathalternate)
+ if a and a > 0 then
+ setattr(pointer,a_mathalternate,0)
+ local tfmdata = fontdata[getfont(pointer)]
+ local resources = tfmdata.resources -- was tfmdata.shared
+ if resources then
+ local mathalternatesattributes = resources.mathalternatesattributes
+ if mathalternatesattributes then
+ local what = mathalternatesattributes[a]
+ local char = getchar(pointer)
+ local alt = otf.getalternate(tfmdata,char,what.feature,what.value)
+ if alt ~= char then
+ if trace_alternates then
+ report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U",
+ tostring(what.feature),tostring(what.value),getchar(pointer),alt)
+ end
+ setchar(pointer,alt)
+ end
+ end
+ end
+ end
+end
+
+function handlers.alternates(head,style,penalties)
+ processnoads(head,alternate,"alternate")
+ return true
+end
+
+-- italics: we assume that only characters matter
+--
+-- = we check for correction first because accessing nodes is slower
+-- = the actual glyph is not that important (we can control it with numbers)
+
+-- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on
+-- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all
+-- those heuristics. We want to deal with it ourselves also in the perspective of mixed math
+-- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and
+-- real ones.
+
+-- in opentype the italic correction of a limop is added to the width and luatex does some juggling
+-- that we want to avoid but we need to do something here (in fact, we could better fix the width of
+-- the character
+
+local a_mathitalics = privateattribute("mathitalics")
+
+local italics = { }
+local default_factor = 1/20
+
+local setcolor = nodes.tracers.colors.set
+local resetcolor = nodes.tracers.colors.reset
+local italic_kern = new_kern
+local c_positive_d = "trace:dg"
+local c_negative_d = "trace:dr"
+
+local function insert_kern(current,kern)
+ local sub = new_node(math_sub) -- todo: pool
+ local noad = new_node(math_noad) -- todo: pool
+ setfield(sub,"list",kern)
+ setnext(kern,noad)
+ setfield(noad,"nucleus",current)
+ return sub
+end
+
+registertracker("math.italics.visualize", function(v)
+ if v then
+ italic_kern = function(k)
+ local n = new_kern(k)
+ set_visual(n,"italic")
+ return n
+ end
+ else
+ italic_kern = new_kern
+ end
+end)
+
+local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex)
+
+ local visual = chardata[char].visual
+
+ if method == 1 then
+ -- check on state
+ local italics = fontitalics[font]
+ if italics then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ elseif method == 2 then
+ -- no check
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ elseif method == 3 then
+ -- check on visual
+ if visual == "it" or visual == "bi" then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ elseif method == 4 then
+ -- combination of 1 and 3
+ local italics = fontitalics[font]
+ if italics and (visual == "it" or visual == "bi") then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ end
+
+end
+
+italics[math_char] = function(pointer,what,n,parent)
+ local method = getattr(pointer,a_mathitalics)
+ if method and method > 0 and method < 100 then
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local correction, visual = getcorrection(method,font,char)
+ if correction and correction ~= 0 then
+ local next_noad = getnext(parent)
+ if not next_noad then
+ if n == 1 then -- only at the outer level .. will become an option (always,endonly,none)
+ if trace_italics then
+ report_italics("method %a, flagging italic correction between %C and end math",method,correction,char)
+ end
+ setattr(pointer,a_mathitalics,101)
+ setattr(parent,a_mathitalics,101)
+ end
+ end
+ end
+ end
+end
+
+function handlers.italics(head,style,penalties)
+ processnoads(head,italics,"italics")
+ return true
+end
+
+local enable
+
+enable = function()
+ tasks.enableaction("math", "noads.handlers.italics")
+ if trace_italics then
+ report_italics("enabling math italics")
+ end
+ enable = false
+end
+
+-- best do this only on math mode (less overhead)
+
+function mathematics.setitalics(name)
+ if enable then
+ enable()
+ end
+ texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none
+end
+
+function mathematics.getitalics(name)
+ if enable then
+ enable()
+ end
+ context(name and name ~= v_reset and tonumber(name) or unsetvalue)
+end
+
+function mathematics.resetitalics()
+ texsetattribute(a_mathitalics,unsetvalue)
+end
+
+implement {
+ name = "initializemathitalics",
+ actions = enable,
+ onlyonce = true,
+}
+
+implement {
+ name = "setmathitalics",
+ actions = mathematics.setitalics,
+ arguments = "string",
+}
+
+implement {
+ name = "getmathitalics",
+ actions = mathematics.getitalics,
+ arguments = "string",
+}
+
+implement {
+ name = "resetmathitalics",
+ actions = mathematics.resetitalics
+}
+
+-- primes and such
+
+local collapse = { } processors.collapse = collapse
+
+local mathpairs = characters.mathpairs -- next will move to char-def
+
+mathpairs[0x2032] = { [0x2032] = 0x2033, [0x2033] = 0x2034, [0x2034] = 0x2057 } -- (prime,prime) (prime,doubleprime) (prime,tripleprime)
+mathpairs[0x2033] = { [0x2032] = 0x2034, [0x2033] = 0x2057 } -- (doubleprime,prime) (doubleprime,doubleprime)
+mathpairs[0x2034] = { [0x2032] = 0x2057 } -- (tripleprime,prime)
+
+mathpairs[0x2035] = { [0x2035] = 0x2036, [0x2036] = 0x2037 } -- (reversedprime,reversedprime) (reversedprime,doublereversedprime)
+mathpairs[0x2036] = { [0x2035] = 0x2037 } -- (doublereversedprime,reversedprime)
+
+mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D }
+mathpairs[0x222C] = { [0x222B] = 0x222D }
+
+mathpairs[0x007C] = { [0x007C] = 0x2016, [0x2016] = 0x2980 } -- bar+bar=double bar+double=triple
+mathpairs[0x2016] = { [0x007C] = 0x2980 } -- double+bar=triple
+
+local movesub = {
+ -- primes
+ [0x2032] = 0xFE932,
+ [0x2033] = 0xFE933,
+ [0x2034] = 0xFE934,
+ [0x2057] = 0xFE957,
+ -- reverse primes
+ [0x2035] = 0xFE935,
+ [0x2036] = 0xFE936,
+ [0x2037] = 0xFE937,
+}
+
+local validpair = {
+ [noad_rel] = true,
+ [noad_ord] = true,
+ [noad_bin] = true, -- new
+ [noad_punct] = true, -- new
+ [noad_opdisplaylimits] = true,
+ [noad_oplimits] = true,
+ [noad_opnolimits] = true,
+}
+
+local function movesubscript(parent,current_nucleus,current_char)
+ local prev = getprev(parent)
+ if prev and getid(prev) == math_noad then
+ if not getfield(prev,"sup") and not getfield(prev,"sub") then
+ -- {f} {'}_n => f_n^'
+ setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
+ local nucleus = getfield(parent,"nucleus")
+ local sub = getfield(parent,"sub")
+ local sup = getfield(parent,"sup")
+ setfield(prev,"sup",nucleus)
+ setfield(prev,"sub",sub)
+ local dummy = copy_node(nucleus)
+ setchar(dummy,0)
+ setfield(parent,"nucleus",dummy)
+ setfield(parent,"sub",nil)
+ if trace_collapsing then
+ report_collapsing("fixing subscript")
+ end
+ elseif not getfield(prev,"sup") then
+ -- {f} {'}_n => f_n^'
+ setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
+ local nucleus = getfield(parent,"nucleus")
+ local sup = getfield(parent,"sup")
+ setfield(prev,"sup",nucleus)
+ local dummy = copy_node(nucleus)
+ setchar(dummy,0)
+ setfield(parent,"nucleus",dummy)
+ if trace_collapsing then
+ report_collapsing("fixing subscript")
+ end
+ end
+ end
+end
+
+local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
+ if parent then
+ if validpair[getsubtype(parent)] then
+ local current_nucleus = getfield(parent,"nucleus")
+ if getid(current_nucleus) == math_char then
+ local current_char = getchar(current_nucleus)
+ if not getfield(parent,"sub") and not getfield(parent,"sup") then
+ local mathpair = mathpairs[current_char]
+ if mathpair then
+ local next_noad = getnext(parent)
+ if next_noad and getid(next_noad) == math_noad then
+ if validpair[getsubtype(next_noad)] then
+ local next_nucleus = getfield(next_noad,"nucleus")
+ local next_char = getchar(next_nucleus)
+ if getid(next_nucleus) == math_char then
+ local newchar = mathpair[next_char]
+ if newchar then
+ local id = getfont(current_nucleus)
+ local characters = fontcharacters[id]
+ if characters and characters[newchar] then
+ if trace_collapsing then
+ report_collapsing("%U + %U => %U",current_char,next_char,newchar)
+ end
+ setchar(current_nucleus,newchar)
+ local next_next_noad = getnext(next_noad)
+ if next_next_noad then
+ setlink(parent,next_next_noad)
+ else
+ setnext(parent)
+ end
+ setfield(parent,"sup",getfield(next_noad,"sup"))
+ setfield(parent,"sub",getfield(next_noad,"sub"))
+ setfield(next_noad,"sup",nil)
+ setfield(next_noad,"sub",nil)
+ free_node(next_noad)
+ collapsepair(pointer,what,n,parent,true)
+ -- if not nested and movesub[current_char] then
+ -- movesubscript(parent,current_nucleus,current_char)
+ -- end
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ end
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ end
+ end
+ end
+end
+
+collapse[math_char] = collapsepair
+
+function noads.handlers.collapse(head,style,penalties)
+ processnoads(head,collapse,"collapse")
+ return true
+end
+
+-- variants
+
+local variants = { }
+
+local validvariants = { -- fast check on valid
+ [0x2229] = 0xFE00, [0x222A] = 0xFE00,
+ [0x2268] = 0xFE00, [0x2269] = 0xFE00,
+ [0x2272] = 0xFE00, [0x2273] = 0xFE00,
+ [0x228A] = 0xFE00, [0x228B] = 0xFE00,
+ [0x2293] = 0xFE00, [0x2294] = 0xFE00,
+ [0x2295] = 0xFE00,
+ [0x2297] = 0xFE00,
+ [0x229C] = 0xFE00,
+ [0x22DA] = 0xFE00, [0x22DB] = 0xFE00,
+ [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00,
+ [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00,
+ [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00,
+ [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00,
+}
+
+variants[math_char] = function(pointer,what,n,parent) -- also set export value
+ local char = getchar(pointer)
+ local selector = validvariants[char]
+ if selector then
+ local next = getnext(parent)
+ if next and getid(next) == math_noad then
+ local nucleus = getfield(next,"nucleus")
+ if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then
+ local variant
+ local tfmdata = fontdata[getfont(pointer)]
+ local mathvariants = tfmdata.resources.variants -- and variantdata
+ if mathvariants then
+ mathvariants = mathvariants[selector]
+ if mathvariants then
+ variant = mathvariants[char]
+ end
+ end
+ if variant then
+ setchar(pointer,variant)
+ setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup
+ if trace_variants then
+ report_variants("variant (%U,%U) replaced by %U",char,selector,variant)
+ end
+ else
+ if trace_variants then
+ report_variants("no variant (%U,%U)",char,selector)
+ end
+ end
+ setprev(next,pointer)
+ setnext(parent,getnext(next))
+ free_node(next)
+ end
+ end
+ end
+end
+
+function handlers.variants(head,style,penalties)
+ processnoads(head,variants,"unicode variant")
+ return true
+end
+
+-- for manuals
+
+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 = "",
+}
+
+classes[math_char] = function(pointer,what,n,parent)
+ local color = colors[getsubtype(parent)]
+ if color then
+ setcolor(pointer,color)
+ else
+ resetcolor(pointer)
+ end
+end
+
+function handlers.classes(head,style,penalties)
+ processnoads(head,classes,"classes")
+ return true
+end
+
+registertracker("math.classes",function(v) tasks.setaction("math","noads.handlers.classes",v) end)
+
+-- experimental
+
+do
+
+ -- mathematics.registerdomain {
+ -- name = "foo",
+ -- parents = { "bar" },
+ -- characters = {
+ -- [0x123] = { char = 0x234, class = binary },
+ -- },
+ -- }
+
+ local domains = { }
+ local categories = { }
+ local numbers = { }
+ local mclasses = mathematics.classes
+ 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,
+ }
+
+ function mathematics.registerdomain(data)
+ local name = data.name
+ if not name then
+ return
+ end
+ local attr = #numbers + 1
+ categories[name] = data
+ numbers[attr] = data
+ data.attribute = attr
+ -- we delay hashing
+ return attr
+ end
+
+ local enable
+
+ enable = function()
+ tasks.enableaction("math", "noads.handlers.domains")
+ if trace_domains then
+ report_domains("enabling math domains")
+ end
+ enable = false
+ end
+
+ function mathematics.setdomain(name)
+ if enable then
+ enable()
+ end
+ local data = name and name ~= v_reset and categories[name]
+ texsetattribute(a_mathdomain,data and data.attribute or unsetvalue)
+ end
+
+ function mathematics.getdomain(name)
+ if enable then
+ enable()
+ end
+ local data = name and name ~= v_reset and categories[name]
+ context(data and data.attribute or unsetvalue)
+ end
+
+ implement {
+ name = "initializemathdomain",
+ actions = enable,
+ onlyonce = true,
+ }
+
+ implement {
+ name = "setmathdomain",
+ arguments = "string",
+ actions = mathematics.setdomain,
+ }
+
+ implement {
+ name = "getmathdomain",
+ arguments = "string",
+ actions = mathematics.getdomain,
+ }
+
+ local function makehash(data)
+ local hash = { }
+ local parents = data.parents
+ if parents then
+ local function merge(name)
+ if name then
+ local c = categories[name]
+ if c then
+ local hash = c.hash
+ if not hash then
+ hash = makehash(c)
+ end
+ for k, v in next, hash do
+ hash[k] = v
+ end
+ end
+ end
+ end
+ if type(parents) == "string" then
+ merge(parents)
+ elseif type(parents) == "table" then
+ for i=1,#parents do
+ merge(parents[i])
+ end
+ end
+ end
+ local characters = data.characters
+ if characters then
+ for k, v in next, characters do
+ -- local chr = n.char
+ local cls = v.class
+ if cls then
+ v.code = permitted[cls]
+ else
+ -- invalid class
+ end
+ hash[k] = v
+ end
+ end
+ data.hash = hash
+ return hash
+ end
+
+ domains[math_char] = function(pointer,what,n,parent)
+ local attr = getattr(pointer,a_mathdomain)
+ if attr then
+ local domain = numbers[attr]
+ if domain then
+ local hash = domain.hash
+ if not hash then
+ hash = makehash(domain)
+ end
+ local char = getchar(pointer)
+ local okay = hash[char]
+ if okay then
+ local chr = okay.char
+ local cls = okay.code
+ if chr and chr ~= char then
+ setchar(pointer,chr)
+ end
+ if cls and cls ~= getsubtype(parent) then
+ setsubtype(parent,cls)
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.domains(head,style,penalties)
+ processnoads(head,domains,"domains")
+ return true
+ end
+
+end
+
+
+-- just for me
+
+function handlers.showtree(head,style,penalties)
+ inspect(nodes.totree(head))
+end
+
+registertracker("math.showtree",function(v) tasks.setaction("math","noads.handlers.showtree",v) end)
+
+-- the normal builder
+
+function builders.kernel.mlist_to_hlist(head,style,penalties)
+ return mlist_to_hlist(head,style,penalties), true
+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)
+ stoptiming(noads)
+ return head, done
+end
+
+callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list")
+
+-- tracing
+
+statistics.register("math processing time", function()
+ return statistics.elapsedseconds(noads)
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv
new file mode 100644
index 00000000000..a5ecdd11dda
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv
@@ -0,0 +1,141 @@
+%D \module
+%D [ file=math-pln,
+%D version=2001.11.16,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Plain Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Here we collect some Plain \TEX\ leftovers.
+
+\writestatus{loading}{ConTeXt Math Macros / Plain Helpers}
+
+\unprotect
+
+% we need proper unicode:
+
+\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to
+
+% might change
+
+\unexpanded\def\hrulefill{\leaders\hrule\hfill}
+\unexpanded\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill}
+
+% will move
+
+\def\oalign#1%
+ {\leavevmode
+ \vtop
+ {\baselineskip\zeroskip
+ \lineskip.25\exheight
+ \ialign{\alignmark\alignmark\crcr#1\crcr}}}
+
+\def\ooalign % chars over each other
+ {\lineskiplimit-\maxdimen
+ \oalign}
+
+% needs checking
+
+\def\choose{\atopwithdelims()}
+\def\brack {\atopwithdelims[]}
+\def\brace {\atopwithdelims\{\}}
+
+% needs checking
+
+\unexpanded\def\buildrel#1\over#2%
+ {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
+
+\unexpanded\def\bmod
+ {\nonscript
+ \mskip-\medmuskip
+ \mkern5mu
+ \mfunction{mod}%
+ \penalty900
+ \mkern5mu
+ \nonscript
+ \mskip-\medmuskip}
+
+\unexpanded\def\pmod#1%
+ {\allowbreak
+ \mkern18mu
+ (\mfunction{mod}\mskip\medmuskip#1)}
+
+\unexpanded\def\cases#1%
+ {\left\{%
+ \mskip\thinmuskip
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{%
+ \normalstartimath\alignmark\alignmark\hfil\normalstopimath
+ \aligntab
+ \quad\alignmark\alignmark\hfil
+ \crcr
+ #1%
+ \crcr}}%
+ \right.}
+
+\unexpanded\def\matrix#1%
+ {\emptyhbox
+ \mskip\thinmuskip
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{%
+ \hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil
+ \aligntab
+ \aligntab
+ \quad\hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil
+ \crcr
+ \mathstrut
+ \crcr
+ \noalign{\kern-\baselineskip}
+ #1\crcr
+ \mathstrut
+ \crcr
+ \noalign{\kern-\baselineskip}}}%
+ \mskip\thinmuskip}
+
+\unexpanded\def\pmatrix#1%
+ {\left(\matrix{#1}\right)}
+
+% \unexpanded\def\openup
+% {\afterassignment\math_openup\scratchdimen=}
+%
+% \def\math_openup
+% {\advance\lineskip \scratchdimen
+% \advance\baselineskip \scratchdimen
+% \advance\lineskiplimit\scratchdimen}
+
+\let\math_closeup\relax
+
+\unexpanded\def\math_openup
+ {\afterassignment\math_openup_indeed\scratchdimen}
+
+\def\math_openup_indeed
+ {\unexpanded\edef\math_closeup
+ {\lineskip \the\lineskip
+ \baselineskip \the\baselineskip
+ \lineskiplimit\the\lineskiplimit
+ \relax}%
+ \advance \lineskip \scratchdimen
+ \advance \baselineskip \scratchdimen
+ \advance \lineskiplimit \scratchdimen}
+
+\let\openup \math_openup
+\def\closeup{\math_closeup} % dynamic
+
+\unexpanded\def\displaylines#1%
+ {\the\mathdisplayaligntweaks
+ \tabskip\zeroskip
+ \halign
+ {\hbox to \displaywidth{%
+ \normalstartimath\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle\alignmark\alignmark\hfil\normalstopimath}\crcr
+ #1\crcr}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-rad.mkvi b/Master/texmf-dist/tex/context/base/mkiv/math-rad.mkvi
new file mode 100644
index 00000000000..113d4af500c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-rad.mkvi
@@ -0,0 +1,290 @@
+%D \module
+%D [ file=math-rad,
+%D version=2013.07.13,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Radicals,
+%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 / Radicals}
+
+\unprotect
+
+%D \starttyping
+%D $\sqrt[3]{10}$
+%D \stoptyping
+%D
+%D This root command will be overloaded later:
+
+%D Old stuff:
+
+% \def\rootradical{\Uroot \defaultmathfamily "221A } % can be done in char-def
+% \def\surdradical{\Uradical \defaultmathfamily "221A } % can be done in char-def
+
+\def\root#1\of{\rootradical{#1}} % #2
+
+\unexpanded\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree}
+
+\unexpanded\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
+ {\normalexpanded{\rootradical{\normalunexpanded{#1}}{\noexpand\triggermathstyle{\normalmathstyle}\normalunexpanded{#2}}}}
+
+\unexpanded\def\rootwithdegree[#1]{\rootradical{#1}}
+\unexpanded\def\rootwithoutdegree {\rootradical {}}
+
+%D Even older stuff:
+
+% % is now a ordinary character
+%
+% \let\normalsurd\surd % \Uradical "0 "221A
+% \unexpanded\def\surd{\normalsurd{}}
+
+
+%D The real thing:
+
+\installcorenamespace{mathradical}
+\installcorenamespace{mathradicalalternative}
+
+\installcommandhandler \??mathradical {mathradical} \??mathradical
+
+\setupmathradical
+ [\c!alternative=\v!normal,
+ \c!mpoffset=.25\exheight]
+
+\appendtoks
+ \setuevalue{\currentmathradical}{\math_radical_handle{\currentmathradical}}
+\to \everydefinemathradical
+
+\unexpanded\def\math_radical_handle#tag%
+ {\begingroup
+ \edef\currentmathradical{#tag}%
+ \doifelsenextoptionalcs\math_radical_degree_yes\math_radical_degree_nop}
+
+\def\math_radical_alternative{\csname\??mathradicalalternative\mathradicalparameter\c!alternative\endcsname}
+
+\def\m_math_no_degree{{}}
+
+\def\math_radical_degree_yes[#degree]{\edef\currentmathradicaldegree{#degree}\math_radical_indeed}
+\def\math_radical_degree_nop {\let\currentmathradicaldegree\m_math_no_degree\math_radical_indeed}
+
+\def\math_radical_indeed#body%
+ {\math_radical_alternative{#body}\endgroup}
+
+\setvalue{\??mathradicalalternative\v!default}% #body%
+ {\rootradical{\currentmathradicaldegree}} % {#body}}
+
+\setvalue{\??mathradicalalternative\v!normal}#body%
+ {\edef\p_color{\mathradicalparameter\c!color}%
+ \ifx\p_color\empty
+ \styledrootradical{\currentmathradicaldegree}{#body}% {} really needed as \rootradical expands first
+ \else\ifx\currentmathradicaldegree\empty
+ \pushcolor[\p_color]%
+ \styledrootradical{\currentmathradicaldegree}%
+ {\popcolor#body}%
+ \else
+ \pushcolor[\p_color]%
+ \styledrootradical{\popcolor\currentmathradicaldegree\pushcolor[\p_color]}%
+ {\popcolor#body}%
+ \fi\fi}
+
+% As I had a long standing whish to see a proper final root element I decided
+% to make one my own.
+%
+% \startMPcode
+% path p ; p := unitsquare xysized(4cm,1cm) ;
+%
+% path q ; q := boundingbox p enlarged (bbheight(p)/10) ;
+% numeric h ; h := bbheight(q) ;
+%
+% draw p ;
+% draw
+% llcorner q shifted (-h/2,h/2) --
+% llcorner q shifted (-h/4,0) --
+% ulcorner q --
+% urcorner q --
+% urcorner q shifted (0,-h/10) ;
+% \stopMPcode
+%
+% \startMPextensions
+% vardef math_root(expr w,h,d,o) =
+% path q ; q := boundingbox unitsquare xysized(w,h) enlarged (o);
+% llcorner q shifted (-h/2,h/2) --
+% llcorner q shifted (-h/4,-d) --
+% ulcorner q --
+% urcorner q --
+% urcorner q shifted (0,-h/10)
+% enddef ;
+% \stopMPextensions
+%
+% \startuniqueMPgraphic{root}{width,height,depth,offset,linewidth}
+% pickup pencircle scaled \MPvar{linewidth} ;
+% draw math_root(\MPvar{width},\MPvar{height},\MPvar{depth},\MPvar{offset}) ;
+% \stopuniqueMPgraphic
+%
+% \unexpanded\def\sqrt#1%
+% {\begingroup
+% \setbox\scratchbox\mathstylehbox{#1}%
+% \scratchoffset\MPrawvar{root}{offset}%.25\exheight
+% \scratchwidth \wd\scratchbox
+% \scratchheight\ht\scratchbox
+% \scratchdepth \dp\scratchbox
+% \setbox2=\hbox\bgroup % todo: tag this box as sqrt
+% \uniqueMPgraphic
+% {root}%
+% {width=\the\scratchwidth,%
+% depth=\the\scratchdepth,%
+% height=\the\scratchheight,%
+% offset=\the\scratchoffset,
+% linewidth=\the\linewidth}%
+% \egroup
+% \scratchdimen\wd2
+% \lower\dimexpr\scratchoffset+\scratchdepth\relax\box2
+% \hskip-\scratchdimen
+% \hbox to \scratchdimen{\hss\box\scratchbox\hskip\scratchoffset}%
+% \endgroup}
+
+\startMPextensions
+ vardef math_radical_simple(expr w,h,d,o) =
+ (-h/2-o,h/2-o) --
+ (-h/4-o,-d-o) --
+ (-o,h+o) --
+ (w+o,h+o) --
+ (w+o,h-h/10+o)
+ enddef ;
+\stopMPextensions
+
+\startuniqueMPgraphic{math:radical:default}%{...}
+ draw
+ math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset)
+ withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30
+ % dashed evenly
+ withcolor OverlayLineColor ;
+\stopuniqueMPgraphic
+
+% todo: spacing .. this is just an experiment (article driven)
+
+\setvalue{\??mathradicalalternative\v!mp}#body% we could use dowithnextbox
+ {\begingroup
+ \scratchoffset\mathradicalparameter\c!mpoffset
+ \setbox\nextbox\mathstylehbox{#body}%
+ % we use the \overlay variables as these are passes anyway and
+ % it's more efficient than using parameters
+ \d_overlay_width \wd\nextbox
+ \d_overlay_height \ht\nextbox
+ \d_overlay_depth \dp\nextbox
+ \d_overlay_offset \scratchoffset
+ \d_overlay_linewidth\linewidth
+ \edef\overlaylinecolor{\mathradicalparameter\c!color}%
+ %
+ \edef\p_mp{\mathradicalparameter\c!mp}%
+ %
+ \setbox\scratchbox\hpack\bgroup % todo: tag this box as sqrt
+ \uniqueMPgraphic
+ {\p_mp}%
+ %{...}%
+ \egroup
+ \scratchdimen \wd\scratchbox
+ \scratchtopoffset \dimexpr\scratchoffset+\dp\nextbox\relax
+ \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
+ \hpack to \scratchdimen{\hss\box\nextbox\hskip\scratchoffset}%
+ \hskip-\scratchdimen
+ \lower\dimexpr\scratchtopoffset\box\scratchbox%
+ \ifx\currentmathradicaldegree\empty \else
+ \setbox\scratchbox\mathstylehbox{\scriptscriptstyle\currentmathradicaldegree\hss}%
+ \wd\scratchbox\scratchdimen
+ \hskip-\scratchdimen
+ \raise\dimexpr\scratchbottomoffset\box\scratchbox
+ \fi
+ \endgroup}
+
+\definemathradical[sqrt][mp=math:radical:default]
+
+% \setupmathradical[sqrt][alternative=normal,color=darkblue]
+% \setupmathradical[sqrt][alternative=mp,color=darkgreen]
+
+%D Because I wanted to illustrate some more fun stuff another mechanism
+%D is provided as well ... let's put some dangerous tools in the hand of
+%D math juglers like Aditya.
+
+\installcorenamespace{mathornament}
+\installcorenamespace{mathornamentalternative}
+
+\installcommandhandler \??mathornament {mathornament} \??mathornament
+
+\setupmathornament
+ [\c!alternative=\v!mp, % currently mp only .. maybe some day layer too
+ \c!mpoffset=.25\exheight]
+
+\appendtoks
+ \setuevalue{\currentmathornament}{\math_ornament_handle{\currentmathornament}}
+\to \everydefinemathornament
+
+\unexpanded\def\math_ornament_handle#tag#body%
+ {\begingroup
+ \edef\currentmathornament{#tag}%
+ \csname\??mathornamentalternative\mathornamentparameter\c!alternative\endcsname{#body}%
+ \endgroup}
+
+\setvalue{\??mathornamentalternative\v!mp}#body% we could use dowithnextbox
+ {\begingroup
+ \scratchoffset\mathornamentparameter\c!mpoffset
+ \setbox\nextbox\mathstylehbox{#body}%
+ \d_overlay_width \wd\nextbox
+ \d_overlay_height \ht\nextbox
+ \d_overlay_depth \dp\nextbox
+ \d_overlay_offset \scratchoffset
+ \d_overlay_linewidth\linewidth
+ \edef\overlaylinecolor{\mathornamentparameter\c!color}%
+ \edef\p_mp{\mathornamentparameter\c!mp}%
+ % thw width of the graphic determines the width of the final result
+ \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
+ \scratchdimen \wd\scratchbox
+ % \scratchtopoffset \dimexpr\scratchoffset+\dp\nextbox\relax
+ % \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
+ \hpack to \scratchdimen{\hss\box\nextbox\hss}%
+ \hskip-\scratchdimen
+ \box\scratchbox
+ \endgroup}
+
+% \startMPextensions
+% vardef math_ornament_hat(expr w,h,d,o,l) =
+% image ( path p ; p :=
+% (w/2,h + 10l) --
+% (o + w,h + o) --
+% (w/2,h + 7l) --
+% (-o,h + o) --
+% cycle ;
+% fill p ;
+% setbounds currentpicture to (-o,0) -- (w+o,0) -- (w+o,h+2o) -- (-o,h+2o) -- cycle ;
+% )
+% enddef ;
+% \stopMPextensions
+%
+% \startuniqueMPgraphic{math:ornament:hat}
+% draw
+% math_ornament_hat(
+% OverlayWidth,
+% OverlayHeight,
+% OverlayDepth,
+% OverlayOffset,
+% OverlayLineWidth
+% )
+% withpen
+% pencircle
+% xscaled (2OverlayLineWidth)
+% yscaled (3OverlayLineWidth/4)
+% rotated 30
+% withcolor
+% OverlayLineColor ;
+% draw boundingbox currentpicture;
+% \stopuniqueMPgraphic
+%
+% \definemathornament [mathhat] [mp=math:ornament:hat]
+%
+% \dorecurse{8}{$\mathhat{\blackrule[width=#1ex,color=gray]}$ }
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ren.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ren.lua
new file mode 100644
index 00000000000..4628ffe5587
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ren.lua
@@ -0,0 +1,67 @@
+if not modules then modules = { } end modules ['math-ren'] = {
+ version = 1.001,
+ comment = "companion to math-ren.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+local gsub = string.gsub
+
+local settings_to_array = utilities.parsers.settings_to_array
+local allocate = storage.allocate
+
+local renderings = { }
+mathematics.renderings = renderings
+
+local mappings = allocate()
+renderings.mappings = mappings
+
+local numbers = allocate()
+renderings.numbers = numbers
+
+local sets = allocate()
+renderings.sets = sets
+
+mappings["blackboard-to-bold"] = {
+ [0x1D538] = 0x1D400, [0x1D539] = 0x1D401, [0x02102] = 0x1D402, [0x1D53B] = 0x1D403, [0x1D53C] = 0x1D404,
+ [0x1D53D] = 0x1D405, [0x1D53E] = 0x1D406, [0x0210D] = 0x1D407, [0x1D540] = 0x1D408, [0x1D541] = 0x1D409,
+ [0x1D542] = 0x1D40A, [0x1D543] = 0x1D40B, [0x1D544] = 0x1D40C, [0x02115] = 0x1D40D, [0x1D546] = 0x1D40E,
+ [0x02119] = 0x1D40F, [0x0211A] = 0x1D410, [0x0211D] = 0x1D411, [0x1D54A] = 0x1D412, [0x1D54B] = 0x1D413,
+ [0x1D54C] = 0x1D414, [0x1D54D] = 0x1D415, [0x1D54E] = 0x1D416, [0x1D54F] = 0x1D417, [0x1D550] = 0x1D418,
+ [0x02124] = 0x1D419,
+}
+
+local function renderset(list) -- order matters
+ local tag = gsub(list," ","")
+ local n = sets[tag]
+ if not n then
+ local list = settings_to_array(tag)
+ local mapping = { }
+ for i=1,#list do
+ local m = mappings[list[i]]
+ if m then
+ for k, v in next, m do
+ mapping[k] = v
+ end
+ end
+ end
+ if next(mapping) then
+ n = #numbers + 1
+ numbers[n] = mapping
+ else
+ n = attributes.unsetvalue
+ end
+ sets[tag] = n
+ end
+ return n
+end
+
+mathematics.renderset = renderset
+
+interfaces.implement {
+ name = "mathrenderset",
+ actions = { renderset, context },
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-scr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-scr.mkiv
new file mode 100644
index 00000000000..2decaa81fc5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-scr.mkiv
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=math-scr,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Scripts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Scripts}
+
+\unprotect
+
+%D These macros were first needed by Frits (Gajes) Spijker
+%D (of the Math4All project that we participate in), and used
+%D for typesetting the minus sign that is keyed into scientific
+%D calculators. We use the monospaced signs, that we also define
+%D as symbol, so that they can be overloaded.
+
+\def\math_scripts_raised_symbol#1%
+ {\mathchoice
+ {\math_scripts_raised_symbol_indeed5\tf {#1}}%
+ {\math_scripts_raised_symbol_indeed5\tf {#1}}%
+ {\math_scripts_raised_symbol_indeed4\tx {#1}}%
+ {\math_scripts_raised_symbol_indeed3\txx{#1}}}
+
+\def\math_scripts_raised_symbol_indeed#1#2#3%
+ {\mathord{{#2\raise.#1ex\hbox{#2\symbol[#3]}}}}
+
+\def\math_scripts_raised_number#1%
+ {\mathchoice
+ {\math_scripts_raised_number_indeed\tf {#1}}%
+ {\math_scripts_raised_number_indeed\tf {#1}}%
+ {\math_scripts_raised_number_indeed\tx {#1}}%
+ {\math_scripts_raised_number_indeed\txx{#1}}}
+
+\def\math_scripts_raised_number_indeed#1#2%
+ {\setbox\scratchbox\hbox{0}%
+ \mathord{\hbox to \wd\scratchbox{\hss#1\symbol[#2]\hss}}}
+
+\definesymbol[positive] [\getglyph{Mono}{+}]
+\definesymbol[negative] [\getglyph{Mono}{-}]
+\definesymbol[zeroamount][\getglyph{Mono}{-}]
+
+\unexpanded\def\negative {\math_scripts_raised_symbol{negative}}
+\unexpanded\def\positive {\math_scripts_raised_symbol{positive}}
+\unexpanded\def\zeroamount{\math_scripts_raised_number{zeroamount}}
+
+%D How negative such a symbol looks is demonstrated in:
+%D $\negative 10^{\negative 10^{\negative 10}}$.
+
+% \setuptextformulas % why here
+% [\c!size=\v!normal]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi b/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi
new file mode 100644
index 00000000000..96e1738db07
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi
@@ -0,0 +1,1293 @@
+%D \module
+%D [ file=math-stc,
+%D version=2012.12.29,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Stackers,
+%D comment=This replaces math-arr and friends,
+%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 / Stackers}
+
+\unprotect
+
+%D WARNING: If the code here changes, the export needs to be checked! Stackers are rather
+%D special because the order in mathml matters, so we flush in [base under over] order. We
+%D also do some analysis at the \TEX\ end (passing the right variant). It's easy in the
+%D export to deal with it but in the pdf stream less trivial as we don't actually analyze
+%D there.
+
+%D At some point the \MKII\ arrow mechanism has been converted to \MKIV, but we kept
+%D most of the logic. We now have a more generic variant dealing with extensibles.
+%D There are a few demands than we need to meet:
+%D
+%D \startitemize
+%D \startitem The width of the extensible need to adapt itself automatically. \stopitem
+%D \startitem We need to be able to control horizontal and vertical offsets. \stopitem
+%D \startitem We best have a math as well as a text variant (which is handy for chemistry). \stopitem
+%D \startitem For historic reasons we need to deal with optional arguments in a special (reverse) way. \stopitem
+%D \startitem We need alternatives for extensibles on top, in the middle and at the bottom. \stopitem
+%D \stopitemize
+%D
+%D After I had experimented a bit with virtual characters for two headed arrows I
+%D discussed the issue with the Gyre folks and we came to the conclusion that it
+%D made sense to have real extensibles instead of constructing them out of snippets.
+%D After all, \OPENTYPE\ math provides for it. So, in December 2013 beta versions of
+%D Latin Modern and Gyre fonts came available that had these! Because we still want
+%D to support the traditional Latin Modern Virtual math font those were extended
+%D with a couple of virtual extensibles as well.
+%D
+%D {\em For the moment we still have some mess here: we can deal with known dimensions, but
+%D fillers (like \type {\rightarrowfil} don't work with \OPENTYPE\ extensibles yet
+%D because there is no way to let them stretch like leaders. At some point \LUATEX\
+%D might provide a auto||fit||to||encapsulated||box and if not I will cook up a \LUA\
+%D based variant.}
+%D
+%D We could mess with something like \type {$mid\limits^{top}_{bottom}$} but we like
+%D a bit more control. At some point we need to add some hacks to get exports
+%D working well.
+%D
+%D In the end we have a more flexible mechanism which also handles text variants.
+
+%D When wrapping up some math developments I decided to add mp support here
+%D as well. A nice evening job with Joe Bonamassa performing live on the big
+%D screen (real nice bluray's). See meta-imp-mat.mkiv for examples.
+
+% possible improvements:
+%
+% - we could skip the left/right offsets when offset=normal, this saves some access time
+% at the lua end and some checking: use \mathhorizontalcode or \mathextensiblecode
+% but in practice arrows etc are not used that often
+
+\installcorenamespace {mathextensiblefallbacks}
+
+% currently no italic correction ... problem is that we don't know yet if we have an italic
+% below so we we need to postpone
+
+\def\math_stackers_fallback
+ {\hbox to \scratchwidth{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname}}
+ %{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname }
+
+% \def\math_stackers_regular
+% {\mathstylehbox{\Umathaccent\fam\zerocount\scratchunicode{\hskip\scratchwidth}}}
+
+\def\math_stackers_regular
+ {\mathstylehbox{\usemathstackerscolorparameter\c!color
+ \Umathaccent\fam\zerocount\scratchunicode{\hskip\scratchwidth}}}
+
+\def\math_stackers_stretch % we don't have that one yet
+ {\mathstylehbox{\usemathstackerscolorparameter\c!color
+ \Umathaccent\fam\zerocount\scratchunicode{\hskip\hsize}}}
+
+% these delimiters are a unuseable as they don't center for small arguments:
+%
+% $\Umathaccent 0 0 "2190{x}$ \par $\Umathaccent 0 0 "27F8{x}$\par
+% $\Udelimiterunder 0 "2190{x}$ \par $\Udelimiterunder 0 "27F8{x}$\par
+
+\setvalue{\??mathextensiblefallbacks}{\hbox{\vrule\!!width\scratchwidth\!!height.1\exheight\!!depth\zeropoint}}
+
+% \def\math_stackers_with_fallback#codepoint%
+% {\begingroup
+% \scratchunicode#codepoint\relax
+% \ifcase\mathextensiblecode\fam\scratchunicode\relax
+% \math_stackers_fallback
+% \else
+% \math_stackers_stretch
+% \fi
+% \endgroup}
+
+%D We don't really need this because we can assume that fonts have the right
+%D extensibles. If needed I will make a general virtual extender for \OPENTYPE\
+%D fonts.
+%D
+%D Because we have quite some control over positioning, we have somewhat extensive
+%D tracing built in.
+
+\let\math_stackers_top \relax
+\let\math_stackers_middle\relax
+\let\math_stackers_bottom\relax
+\let\math_stackers_skip \hskip
+
+\installtextracker
+ {math.stackers.texts}
+ {\let\math_stackers_top \filledhboxb
+ \let\math_stackers_middle\filledhboxr
+ \let\math_stackers_bottom\filledhboxg
+ \let\math_stackers_skip \math_stackers_skip_indeed}
+ {\let\math_stackers_top \relax
+ \let\math_stackers_middle\relax
+ \let\math_stackers_bottom\relax
+ \let\math_stackers_skip \hskip}
+
+\def\math_stackers_skip_indeed#amount%
+ {\filledhboxk{\unsetteststrut\strut\hskip#amount}} % \dontshowstruts
+
+\let\math_stackers_start_tagged_mid\relax
+\let\math_stackers_start_tagged_top\relax
+\let\math_stackers_start_tagged_bot\relax
+\let\math_stackers_stop_tagged \relax
+
+\appendtoks
+ \def\math_stackers_start_tagged_mid{\dostarttagged\t!mathstackermid\empty\hbox\bgroup}%
+ \def\math_stackers_start_tagged_top{\dostarttagged\t!mathstackertop\empty\hbox\bgroup}%
+ \def\math_stackers_start_tagged_bot{\dostarttagged\t!mathstackerbot\empty\hbox\bgroup}%
+ \def\math_stackers_stop_tagged {\egroup\dostoptagged}%
+\to \everysetuptagging
+
+%D We define a full featured command handler.
+
+\installcorenamespace {mathstackers}
+
+\installcommandhandler \??mathstackers {mathstackers} \??mathstackers
+
+\setupmathstackers
+ [%c!alternative=\v!text, % text | mathematics
+ \c!left=,
+ \c!right=,
+ \c!mathclass=\s!rel,
+ \c!alternative=\v!normal,
+ \c!mp=math:stacker:\number\scratchunicode,
+ \c!mpheight=\exheight,
+ \c!mpdepth=\exheight,
+ \c!mpoffset=.25\exheight,
+ \c!voffset=.25\exheight,
+ \c!hoffset=.5\emwidth,
+ \c!distance=\mathstackersparameter\c!voffset, % distance between symbol and base (can be different from voffset)
+ \c!minheight=\exheight,
+ \c!mindepth=\zeropoint,
+ \c!minwidth=.5\emwidth,
+ \c!order=\v!normal,
+ \c!strut=,
+ \c!color=, % todo: when I need it
+ \c!topcommand=,
+ \c!middlecommand=,
+ \c!bottomcommand=,
+ \c!offset=\v!normal, % normal | min | max
+ \c!location=\v!top] % none | normal | small | medium | big
+
+%D We assume that the middle characters (that can be an extensible) to sit on
+%D top of the baseline by default.
+
+\installcorenamespace {mathstackerslocation}
+\installcorenamespace {mathstackersalternative}
+
+\letvalue{\??mathstackerslocation\v!top }\plusone % on top of baseline
+\letvalue{\??mathstackerslocation\v!high }\plustwo % 25 % down
+\letvalue{\??mathstackerslocation\v!middle }\plusthree % centered
+\letvalue{\??mathstackerslocation\v!low }\plusfour % 75 % down
+\letvalue{\??mathstackerslocation\v!bottom }\plusfive % below baseline
+\letvalue{\??mathstackerslocation }\zerocount
+
+%D First we implement the helper that deals with an extensible in the middle and
+%D top and|/|or bottom texts:
+
+\let\m_math_stackers_text_top \empty
+\let\m_math_stackers_text_bottom\empty
+\let\m_math_stackers_text_middle\empty
+
+\def\math_stackers_flushtext#command#text%
+ {\ifdim\scratchleftoffset >\zeropoint\math_stackers_skip\scratchleftoffset \fi
+ \ifx\p_strut\v!no \else
+ \strut
+ \fi
+ \mathstackersparameter#command#text%
+ \ifdim\scratchrightoffset>\zeropoint\math_stackers_skip\scratchrightoffset\fi}
+
+\def\math_stackers_toptext {\math_stackers_flushtext\c!topcommand \m_math_stackers_text_top }
+\def\math_stackers_bottomtext{\math_stackers_flushtext\c!bottomcommand\m_math_stackers_text_bottom}
+\def\math_stackers_middletext{\math_stackers_flushtext\c!middlecommand\m_math_stackers_text_middle}
+
+\def\math_stackers_content
+ {\ifcase\scratchcounter
+ \math_stackers_fallback
+ \or % left
+ \math_stackers_regular
+ \or % right
+ \math_stackers_regular
+ \or % horizontal
+ \math_stackers_regular
+ \else
+ \math_stackers_fallback
+ \fi}
+
+% no checking, we assume sane use
+
+\letvalue{\??mathstackersalternative\v!normal }\math_stackers_content
+\letvalue{\??mathstackersalternative\v!default}\math_stackers_content
+
+\setvalue{\??mathstackersalternative\v!mp}%
+ {\hbox\bgroup % todo: add code key + tag
+ \d_overlay_width \scratchwidth
+ \d_overlay_height \dimexpr\mathstackersparameter\c!mpheight
+ \d_overlay_depth \dimexpr\mathstackersparameter\c!mpdepth
+ \d_overlay_offset \dimexpr\mathstackersparameter\c!mpoffset
+ \d_overlay_linewidth\linewidth
+ \edef\overlaylinecolor{\mathstackersparameter\c!color}%
+ \edef\p_mp{\mathstackersparameter\c!mp}%
+ \uniqueMPgraphic{\p_mp}%
+ \egroup}
+
+\def\math_stackers_check_unicode#codepoint%
+ {\scratchunicode#codepoint\relax
+ \scratchhoffset\mathstackersparameter\c!hoffset\relax
+ \scratchvoffset\mathstackersparameter\c!voffset\relax
+ \scratchcounter\mathhorizontalcode\fam\scratchunicode\relax % also sets \leftscratchoffset and \rightscratchoffset
+ \ifx\p_offset\v!max
+ % heads/tails + hoffset
+ \else\ifx\p_offset\v!min
+ % heads/tails - hoffset
+ \advance\scratchleftoffset-\scratchhoffset
+ \advance\scratchrightoffset-\scratchhoffset
+ \else % \v!normal
+ % hoffset
+ \scratchleftoffset\zeropoint
+ \scratchrightoffset\zeropoint
+ \fi\fi
+ \ifdim\scratchleftoffset<\zeropoint
+ \scratchleftoffset\zeropoint
+ \fi
+ \ifdim\scratchrightoffset<\zeropoint
+ \scratchrightoffset\zeropoint
+ \fi}
+
+\def\math_stackers_normalize_three
+ {\scratchheight\ht\scratchboxthree
+ \scratchdepth \dp\scratchboxthree
+ \scratchtopoffset \scratchheight
+ \scratchbottomoffset\scratchdepth
+ \scratchdimen\mathstackersparameter\c!minheight\relax
+ \ifdim\scratchheight<\scratchdimen
+ \scratchheight\scratchdimen
+ \ht\scratchboxthree\scratchheight
+ \fi
+ \scratchdimen\mathstackersparameter\c!mindepth\relax
+ \ifdim\scratchdepth<\scratchdimen
+ \scratchdepth\scratchdimen
+ \dp\scratchboxthree\scratchdepth
+ \fi
+ \advance\scratchtopoffset -\scratchheight
+ \advance\scratchbottomoffset-\scratchdepth
+ \ifdim\scratchtopoffset<\zeropoint
+ \scratchtopoffset\zeropoint
+ \fi
+ \ifdim\scratchbottomoffset<\zeropoint
+ \scratchbottomoffset\zeropoint
+ \fi}
+
+\unexpanded\def\math_stackers_triplet#method#category#codepoint#toptext#bottomtext%
+ %{\math_stackers_start_group{#category}%
+ {\begingroup
+ \edef\currentmathstackers{#category}%
+ \mathstackersparameter\c!left\relax
+ \dostarttagged\t!mathstacker\currentmathstackers
+ \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
+ {\edef\p_offset {\mathstackersparameter\c!offset}%
+ \edef\p_location {\mathstackersparameter\c!location}%
+ \edef\p_order {\mathstackersparameter\c!order}%
+ \edef\p_strut {\mathstackersparameter\c!strut}%
+ \edef\p_alternative{\mathstackersparameter\c!alternative}%
+ \ifx\p_order\v!reverse
+ \edef\m_math_stackers_text_top {#bottomtext}%
+ \edef\m_math_stackers_text_bottom{#toptext}%
+ \else
+ \edef\m_math_stackers_text_top {#toptext}%
+ \edef\m_math_stackers_text_bottom{#bottomtext}%
+ \fi
+ \scratchleftoffset \zeropoint
+ \scratchrightoffset\zeropoint
+ \ifcase#method\relax
+ \math_stackers_check_unicode{#codepoint}%
+ \else
+ \edef\m_math_stackers_text_middle{#codepoint}%
+ \fi
+ \ifx\m_math_stackers_text_top\empty
+ \setbox\scratchboxone\emptyhbox
+ \else
+ \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}%
+ \fi
+ \ifx\m_math_stackers_text_bottom\empty
+ \setbox\scratchboxtwo\emptyhbox
+ \else
+ \setmathsmalltextbox\scratchboxtwo\hbox{\math_stackers_bottomtext}%
+ \fi
+ %
+ \ifcase#method\relax
+ \scratchwidth\wd
+ \ifdim\wd\scratchboxone>\wd\scratchboxtwo
+ \scratchboxone
+ \else
+ \scratchboxtwo
+ \fi
+ \relax
+ \else
+ \ifx\m_math_stackers_text_middle\empty
+ \setbox\scratchboxthree\emptyhbox
+ \else
+ \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
+ \fi
+ \scratchwidth\wd
+ \ifdim\wd\scratchboxone>\wd\scratchboxtwo
+ \ifdim\wd\scratchboxone>\wd\scratchboxthree
+ \scratchboxone
+ \else
+ \scratchboxthree
+ \fi
+ \else\ifdim\wd\scratchboxtwo>\wd\scratchboxthree
+ \scratchboxtwo
+ \else
+ \scratchboxthree
+ \fi\fi
+ \relax
+ \fi
+ %
+ \scratchdimen\mathstackersparameter\c!minwidth\relax
+ \ifdim\scratchwidth<\scratchdimen
+ \scratchwidth\scratchdimen
+ \fi
+ \advance\scratchwidth2\scratchhoffset
+ %
+ \ifcase#method\relax
+ \dostarttagged\t!mathstackermid\empty
+ \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname
+ \dostoptagged
+ \fi
+ %
+ \ifdim\wd\scratchboxone<\scratchwidth
+ \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
+ \fi
+ \ifdim\wd\scratchboxtwo<\scratchwidth
+ \setbox\scratchboxtwo\hbox to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
+ \fi
+ \ifdim\wd\scratchboxthree<\scratchwidth
+ \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
+ \fi
+ %
+ \ifcsname\??mathstackerslocation\p_location\endcsname
+ \ifcase\csname\??mathstackerslocation\p_location\endcsname\relax
+ \scratchdistance\zeropoint
+ \or
+ % top
+ \scratchdistance\zeropoint
+ \or
+ % high
+ \scratchdistance.25\htdp\scratchboxthree
+ \or
+ % centered
+ \scratchdistance.5\htdp\scratchboxthree
+ \or
+ % low
+ \scratchdistance.75\htdp\scratchboxthree
+ \or
+ % bottom
+ \scratchdistance\htdp\scratchboxthree
+ \else
+ \scratchdistance\zeropoint
+ \fi
+ \else
+ \scratchdistance\p_location\htdp\scratchboxthree
+ \fi
+ %
+ \ifzeropt\scratchdistance\else
+ \setbox\scratchboxthree\hbox{\lower\scratchdistance\box\scratchboxthree}%
+ \fi
+ %
+ \math_stackers_normalize_three
+ % analysis
+ \ifdim\htdp\scratchboxtwo>\zeropoint
+ \ifdim\htdp\scratchboxone>\zeropoint
+ \dosettagproperty\s!subtype\t!munderover
+ \else
+ \dosettagproperty\s!subtype\t!munder
+ \fi
+ \else
+ \ifdim\htdp\scratchboxone>\zeropoint
+ \dosettagproperty\s!subtype\t!mover
+ \else
+ % brrr
+ \fi
+ \fi
+ % base
+ \math_stackers_start_tagged_mid
+ \math_stackers_middle\bgroup
+ \box\scratchboxthree
+ \egroup
+ \math_stackers_stop_tagged
+ % under
+ \ifdim\htdp\scratchboxtwo>\zeropoint
+ \math_stackers_start_tagged_bot
+ \scratchoffset\scratchvoffset
+ \kern-\scratchwidth
+ \math_stackers_bottom\bgroup
+ \lower\dimexpr\ht\scratchboxtwo+\scratchdepth+\scratchoffset+\scratchbottomoffset\relax
+ \box\scratchboxtwo
+ \egroup
+ \math_stackers_stop_tagged
+ \fi
+ % over
+ \ifdim\htdp\scratchboxone>\zeropoint
+ \math_stackers_start_tagged_top
+ \scratchoffset\scratchvoffset
+ \kern-\scratchwidth
+ \math_stackers_top\bgroup
+ \raise\dimexpr\dp\scratchboxone+\scratchheight+\scratchoffset+\scratchtopoffset\relax
+ \box\scratchboxone
+ \egroup
+ \math_stackers_stop_tagged
+ \fi
+ %
+ }%
+ \dostoptagged
+ \mathstackersparameter\c!right\relax
+ \endgroup}
+ %\math_stackers_start_group}
+
+\unexpanded\def\definemathextensible
+ {\dotripleempty\math_stackers_define_normal}
+
+\def\math_stackers_define_normal[#1][#2][#3]% category name unicode
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_auto_normal{#1}{\number#3}}%
+ \else
+ \setuevalue{#1}{\math_stackers_auto_normal\noexpand\currentmathstackers{\number#2}}%
+ \fi}
+
+\unexpanded\def\math_stackers_auto_normal#category#codepoint%
+ {\begingroup
+ \edef\currentmathstackers{#category}%
+ \scratchcounter#codepoint\relax
+ \dosingleempty\math_stackers_auto_normal_first}
+
+\unexpanded\def\math_stackers_auto_normal_first[#category]% [#2]% #2 gobble spaces
+ {\iffirstargument\edef\currentmathstackers{#category}\fi
+ \permitspacesbetweengroups
+ \dodoublegroupempty\math_stackers_auto_normal_second}
+
+\def\math_stackers_auto_normal_second#toptext#bottomtext%
+ {\math_stackers_triplet\zerocount\currentmathstackers\scratchcounter{#toptext}{#bottomtext}%
+ \endgroup}
+
+%D A few direct accessors:
+
+\unexpanded\def\mathextensible{\begingroup\dosingleempty\math_stackers_handle_math}
+\unexpanded\def\textextensible{\begingroup\dosingleempty\math_stackers_handle_text}
+
+\unexpanded\def\math_stackers_handle_math[#category]%
+ {\math_stackers_handle_extensible{\iffirstargument#category\else\v!mathematics\fi}} % will be defined later on
+
+\unexpanded\def\math_stackers_handle_text[#category]%
+ {\math_stackers_handle_extensible{\iffirstargument#category\else\v!text \fi}} % will be defined later on
+
+\def\math_stackers_handle_extensible#category#codepoint#toptext#bottomtext%
+ {\math_stackers_triplet\zerocount{#category}{#codepoint}{#toptext}{#bottomtext}%
+ \endgroup}
+
+%D The next one deals with under and over extensibles (arrows mostly):
+
+\installcorenamespace {mathclasses}
+
+\letvalue{\??mathclasses }\mathord
+\letvalue{\??mathclasses rel}\mathrel
+\letvalue{\??mathclasses ord}\mathord
+
+\def\math_class_by_parameter#1%
+ {\normalexpanded{\noexpand\math_class_by_parameter_indeed{#1\c!mathclass}}}
+
+\def\math_class_by_parameter_indeed#1%
+ {\csname\??mathclasses\ifcsname\??mathclasses#1\endcsname#1\fi\endcsname}
+
+% 1 0 name n 0 | 0 1 name n 0 | 1 1 name n n
+
+\unexpanded\def\math_stackers_start_group#category%
+ {\begingroup
+ \edef\currentmathstackers{#category}%
+ \edef\p_limits{\mathstackersparameter\c!mathlimits}%
+ \ifx\p_limits\v!yes
+ \def\math_stackers_stop_group{\egroup\endgroup\limits}%
+ \mathop\bgroup
+ \else
+ \let\math_stackers_stop_group\endgroup
+ \fi}
+
+\unexpanded\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#text%
+ {\math_stackers_start_group{#category}%
+ \mathstackersparameter\c!left\relax
+ \dostarttagged\t!mathstacker\currentmathstackers
+ \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
+ {\edef\m_math_stackers_text_middle {#text}%
+ %
+ \edef\p_offset {\mathstackersparameter\c!offset}%
+ \edef\p_location {\mathstackersparameter\c!location}%
+ \edef\p_strut {\mathstackersparameter\c!strut}%
+ \edef\p_alternative{\mathstackersparameter\c!alternative}%
+ %
+ \scratchleftoffset \zeropoint
+ \scratchrightoffset\zeropoint
+ %
+ \math_stackers_check_unicode{#codepoint}%
+ %
+ \ifx\math_stackers_middle\empty
+ \setbox\scratchboxthree\emptyhbox
+ \else
+ \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
+ \fi
+ \scratchwidth\wd\scratchboxthree
+ %
+ \scratchdimen\mathstackersparameter\c!minwidth\relax
+ \ifdim\scratchwidth<\scratchdimen
+ \scratchwidth\scratchdimen
+ \fi
+ \advance\scratchwidth2\scratchhoffset
+ %
+ \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
+ \setbox\scratchboxthree\hbox to \scratchwidth{\hss\box\scratchboxthree\hss}%
+ %
+ \scratchunicode#codeextra\relax
+ \ifcase\scratchunicode\else
+ \setbox\scratchboxone\csname\??mathstackersalternative\p_alternative\endcsname
+ \fi
+ %
+ \math_stackers_normalize_three
+ % analysis
+ \ifcase#bottom\relax
+ \ifcase#top\relax
+ \dosettagproperty\s!subtype\t!munderover
+ \else
+ \dosettagproperty\s!subtype\t!mover
+ \fi
+ \else
+ \ifcase#top\relax
+ \dosettagproperty\s!subtype\t!munder
+ \else
+ % brrr
+ \fi
+ \fi
+ % base
+ \math_stackers_start_tagged_mid
+ \math_stackers_middle\bgroup
+ \box\scratchboxthree
+ \egroup
+ \math_stackers_stop_tagged
+ %
+ \ifdim\htdp\scratchboxtwo>\zeropoint
+ \ifcase#bottom\else
+ \kern-\scratchwidth
+ % under
+ \math_stackers_start_tagged_bot
+ \math_stackers_bottom\bgroup
+ \lower\dimexpr
+ \scratchdepth
+ +\ht\scratchboxtwo
+ +\mathstackersparameter\c!distance % was \c!voffset
+ \relax
+ \ifcase#top\relax
+ \box\scratchboxtwo
+ \else
+ \box\scratchboxone
+ \fi
+ \egroup
+ \math_stackers_stop_tagged
+ \fi
+ \ifcase#top\else
+ \kern-\scratchwidth
+ % over
+ \math_stackers_start_tagged_top
+ \math_stackers_top\bgroup
+ \raise\dimexpr
+ \scratchheight
+ +\dp\scratchboxtwo % new
+ +\mathstackersparameter\c!distance % was \c!voffset
+ \relax
+ \box\scratchboxtwo
+ \egroup
+ \math_stackers_stop_tagged
+ \fi
+ %
+ \fi}%
+ \dostoptagged
+ \mathstackersparameter\c!right\relax
+ \math_stackers_stop_group}
+
+\unexpanded\def\definemathoverextensible {\dotripleempty \math_extensibles_define_over }
+\unexpanded\def\definemathunderextensible {\dotripleempty \math_extensibles_define_under}
+\unexpanded\def\definemathdoubleextensible{\doquadrupleempty\math_extensibles_define_double}
+
+\def\math_extensibles_define_over[#1][#2][#3]%
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_make_double\plusone \zerocount{#1}{\number#3}{0}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double\plusone \zerocount\noexpand\currentmathstackers{\number#2}{0}}%
+ \fi}
+
+\def\math_extensibles_define_under[#1][#2][#3]%
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_make_double\zerocount\plusone{#1}{\number#3}{0}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double\zerocount\plusone\noexpand\currentmathstackers{\number#2}{0}}%
+ \fi}
+
+\def\math_extensibles_define_double[#1][#2][#3][#4]%
+ {\iffourthargument
+ \setuevalue{#2}{\math_stackers_make_double\plusone \plusone{#1}{\number#3}{\number#4}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double\plusone \plusone\noexpand\currentmathstackers{\number#2}{\number#3}}%
+ \fi}
+
+\unexpanded\def\mathover {\begingroup\dosingleempty\math_stackers_handle_over }
+\unexpanded\def\mathunder {\begingroup\dosingleempty\math_stackers_handle_under }
+\unexpanded\def\mathdouble{\begingroup\dodoubleempty\math_stackers_handle_double}
+
+\def\math_stackers_handle_over[#category]%
+ {\math_stackers_direct_double\plusone\zerocount
+ {\iffirstargument#category\else\v!top \fi}} % will be defined later on
+
+\def\math_stackers_handle_under[#category]%
+ {\math_stackers_direct_double\zerocount\plusone
+ {\iffirstargument#category\else\v!bottom\fi}} % will be defined later on
+
+\def\math_stackers_handle_double[#topcategory][#bottomcategory]%
+ {\math_stackers_direct_double\plusone\plusone
+ {\iffirstargument #topcategory\else\v!top \fi}%
+ {\ifsecondargument#bottomcategory\else\v!bottom\fi}}
+
+\def\math_stackers_direct_double#top#bottom#category#codepoint#text%
+ {\math_stackers_make_double#top#bottom{#category}{#codepoint}{0}{#text}%
+ \endgroup}
+
+%D A relative new one is a combination of accents and text (as needed in mathml):
+
+\unexpanded\def\math_stackers_make_double_text#where#category#codepoint#text#extra%
+ {\math_stackers_start_group{#category}%
+ \mathstackersparameter\c!left\relax
+ \dostarttagged\t!mathstacker\currentmathstackers
+ \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
+ {\edef\currentmathstackers{#category}%
+ %
+ \edef\p_offset {\mathstackersparameter\c!offset}%
+ \edef\p_location {\mathstackersparameter\c!location}%
+ \edef\p_strut {\mathstackersparameter\c!strut}%
+ \edef\p_alternative{\mathstackersparameter\c!alternative}%
+ %
+ \scratchleftoffset \zeropoint
+ \scratchrightoffset\zeropoint
+ %
+ \edef\m_math_stackers_text_middle{#text}%
+ \math_stackers_check_unicode{#codepoint}%
+ \scratchunicode#codepoint\relax
+ %
+ \ifx\math_stackers_middle\empty
+ \setbox\scratchboxthree\emptyhbox
+ \else
+ \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
+ \fi
+ %
+ \ifcase#where\relax
+ \edef\m_math_stackers_text_top{#extra}%
+ \ifx\math_stackers_top\empty
+ \setbox\scratchboxone\emptyhbox
+ \else
+ \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}%
+ \fi
+ \else
+ \edef\m_math_stackers_text_bottom{#extra}%
+ \ifx\math_stackers_bottom\empty
+ \setbox\scratchboxone\emptyhbox
+ \else
+ \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_bottomtext}%
+ \fi
+ \fi
+ %
+ \scratchwidth\wd
+ \ifdim\wd\scratchboxone>\wd\scratchboxthree
+ \scratchboxone
+ \else
+ \scratchboxthree
+ \fi
+ \relax
+ \scratchdimen\mathstackersparameter\c!minwidth\relax
+ \ifdim\scratchwidth<\scratchdimen
+ \scratchwidth\scratchdimen
+ \fi
+ \advance\scratchwidth2\scratchhoffset
+ %
+ \ifdim\wd\scratchboxone<\scratchwidth
+ \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}%
+ \fi
+ \ifdim\wd\scratchboxthree<\scratchwidth
+ \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
+ \fi
+ %
+ \math_stackers_normalize_three
+ % analysis
+ \dosettagproperty\s!subtype\t!munderover
+ % base
+ \math_stackers_start_tagged_mid
+ \math_stackers_middle\bgroup
+ \box\scratchboxthree
+ \egroup
+ \math_stackers_stop_tagged
+ %
+ \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
+ \kern-\scratchwidth
+ \ifcase#where\relax
+ % under
+ \math_stackers_start_tagged_bot
+ \math_stackers_bottom\bgroup
+ \lower\dimexpr
+ \scratchdepth
+ +\ht\scratchboxtwo
+ +\mathstackersparameter\c!distance
+ \relax
+ \box\scratchboxtwo % accent
+ \egroup
+ \math_stackers_stop_tagged
+ \kern-\scratchwidth
+ % over
+ \math_stackers_start_tagged_top
+ \math_stackers_top\bgroup
+ \raise\dimexpr
+ \scratchheight
+ +\dp\scratchboxone
+ +\mathstackersparameter\c!voffset
+ \relax
+ \box\scratchboxone % toptext
+ \egroup
+ \math_stackers_stop_tagged
+ \else
+ % under
+ \math_stackers_start_tagged_bot
+ \math_stackers_bottom\bgroup
+ \lower\dimexpr
+ \scratchdepth
+ +\ht\scratchboxone
+ +\mathstackersparameter\c!voffset
+ \relax
+ \box\scratchboxone % bottext
+ \egroup
+ \math_stackers_stop_tagged
+ \kern-\scratchwidth
+ % over
+ \math_stackers_start_tagged_top
+ \math_stackers_top\bgroup
+ \raise\dimexpr
+ \scratchheight
+ +\dp\scratchboxtwo % new
+ +\mathstackersparameter\c!distance
+ \relax
+ \box\scratchboxtwo % accent
+ \egroup
+ \math_stackers_stop_tagged
+ \fi
+ }%
+ \dostoptagged
+ \mathstackersparameter\c!right\relax
+ \math_stackers_stop_group}
+
+\unexpanded\def\definemathovertextextensible {\dotripleempty\math_extensibles_define_over_text }
+\unexpanded\def\definemathundertextextensible{\dotripleempty\math_extensibles_define_under_text}
+
+\def\math_extensibles_define_over_text[#1][#2][#3]%
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_make_double_text\plusone {#1}{\number#3}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double_text\plusone \noexpand\currentmathstackers{\number#2}}%
+ \fi}
+
+\def\math_extensibles_define_under_text[#1][#2][#3]%
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_make_double_text\zerocount{#1}{\number#3}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double_text\zerocount\noexpand\currentmathstackers{\number#2}}%
+ \fi}
+
+\unexpanded\def\mathovertext {\begingroup\dosingleempty\math_stackers_handle_over_text }
+\unexpanded\def\mathundertext{\begingroup\dosingleempty\math_stackers_handle_under_text }
+
+\def\math_stackers_handle_over_text[#category]%
+ {\math_stackers_direct_double_text\plusone {\iffirstargument#category\else\v!top \fi}} % will be defined later on
+
+\def\math_stackers_handle_under_text[#category]%
+ {\math_stackers_direct_double_text\zerocount{\iffirstargument#category\else\v!bottom\fi}} % will be defined later on
+
+\def\math_stackers_direct_double_text#where#category#codepoint#text#extra%%
+ {\math_stackers_make_double_text#where{#category}{#codepoint}{#text}{#extra}%
+ \endgroup}
+
+%D Here is a bonus macro that takes three texts. It can be used to get consistent
+%D mixed usage.
+
+\unexpanded\def\mathtriplet
+ {\begingroup
+ \dosingleempty\math_stackers_handle_triplet}
+
+\def\math_stackers_handle_triplet[#category]#middletext#toptext#bottomtext%
+ {\math_stackers_triplet\plusone{\iffirstargument#category\else\currentmathstackers\fi}{#middletext}{#toptext}{#bottomtext}%
+ \endgroup}
+
+\unexpanded\def\definemathtriplet
+ {\dotripleempty\math_stackers_define_triplet}
+
+\def\math_stackers_define_triplet[#1][#2][#3]% category name default
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_auto_triplet_yes{#1}{#3}}%
+ \else\ifsecondargument
+ \setuevalue{#2}{\math_stackers_auto_triplet_nop{#1}}%
+ \else
+ \setuevalue{#1}{\math_stackers_auto_triplet_nop\noexpand\currentmathstackers}%
+ \fi\fi}
+
+\unexpanded\def\math_stackers_auto_triplet_yes#category#middletext%
+ {\begingroup
+ \edef\currentmathstackers {#category}%
+ \def \m_math_stackers_text_middle{#middletext}%
+ \dosingleempty\math_stackers_auto_triplet_yes_first}
+
+\unexpanded\def\math_stackers_auto_triplet_yes_first[#category]% [#2]% #2 gobble spaces
+ {\iffirstargument\edef\currentmathstackers{#category}\fi
+ \permitspacesbetweengroups
+ \dodoublegroupempty\math_stackers_auto_triplet_yes_second}
+
+\def\math_stackers_auto_triplet_yes_second#toptext#bottomtext%
+ {\math_stackers_triplet\plusone\currentmathstackers\m_math_stackers_text_middle{#toptext}{#bottomtext}%
+ \endgroup}
+
+\unexpanded\def\math_stackers_auto_triplet_nop#category%
+ {\begingroup
+ \edef\currentmathstackers{#category}%
+ \dosingleempty\math_stackers_auto_triplet_nop_first}
+
+\unexpanded\def\math_stackers_auto_triplet_nop_first[#category]% [#2]% #2 gobble spaces
+ {\iffirstargument\edef\currentmathstackers{#category}\fi
+ \permitspacesbetweengroups
+ \dotriplegroupempty\math_stackers_auto_triplet_nop_second}
+
+\def\math_stackers_auto_triplet_nop_second#middletext#toptext#bottomtext%
+ {\math_stackers_triplet\plusone\currentmathstackers{#middletext}{#toptext}{#bottomtext}%
+ \endgroup}
+
+%D Definitions:
+
+\definemathstackers
+ [\v!mathematics]
+ [\c!topcommand=\mathematics,
+ \c!middlecommand=\mathematics,
+ \c!bottomcommand=\mathematics]
+
+\definemathstackers
+ [\s!math]
+ [\v!mathematics]
+
+\definemathstackers
+ [\v!text]
+ [\v!mathematics]
+ [\c!topcommand=,
+ \c!middlecommand=\mathematics,
+ \c!bottomcommand=]
+
+\definemathstackers
+ [\v!reverse]
+ [\v!mathematics]
+ [\c!order=\v!reverse]
+
+\definemathstackers
+ [\v!both]
+ [\v!mathematics]
+ [\c!location=\v!top, % ?
+ \c!strut=\v!no,
+ \c!middlecommand=\mathematics,
+ \c!hoffset=\zeropoint]
+
+\definemathstackers
+ [\v!top]
+ [\v!both]
+
+\definemathstackers
+ [\v!bottom]
+ [\v!both]
+
+\definemathstackers
+ [\v!vfenced]
+ [\v!both]
+ [\c!mathclass=\s!ord,
+ \c!mathlimits=\v!yes]
+
+% these are needed for mathml:
+
+% \setupmathstackers
+% [\v!both]
+% [\c!hoffset=1pt,
+% \c!voffset=1pt]
+
+\definemathstackers
+ [\v!bothtext]
+ [\v!both]
+ [\c!strut=\v!yes]
+
+% These are compatibity definitions, math only.
+
+% todo: top= bottom= middle= is nicer (compare math-fen)
+
+%D We save a few definitions that we automatically got from the \type {char-def.lua}
+%D database.
+
+% Be careful in choosing what accents you take (the code below uses a
+% combining one):
+%
+% \startbuffer
+% % $\Umathaccent top 0 0 "20D7 {example}$
+% % $\Umathaccent top fixed 0 0 "20D7 {example}$
+% $\Umathaccent 0 0 "20D7 {example}$
+% $\Umathaccent fixed 0 0 "20D7 {example}$
+% $\Umathaccent bottom 0 0 "20D7 {example}$
+% $\Umathaccent bottom fixed 0 0 "20D7 {example}$
+% $\Umathaccent both 0 0 "20D7
+% 0 0 "20D7 {example}$
+% $\Umathaccent both fixed 0 0 "20D7
+% fixed 0 0 "20D7 {example}$
+% $\Umathaccent both 0 0 "20D7
+% fixed 0 0 "20D7 {example}$
+% $\Umathaccent both fixed 0 0 "20D7
+% 0 0 "20D7 {example}$
+% \stopbuffer
+%
+% \setupbodyfont[modern] \getbuffer
+% \setupbodyfont[xits] \getbuffer
+% \setupbodyfont[cambria] \getbuffer
+
+\unexpanded\def\normaldoublebrace {\Umathaccents 0 \defaultmathfamily "23DE 0 \defaultmathfamily "23DF }
+\unexpanded\def\normaldoubleparent{\Umathaccents 0 \defaultmathfamily "23DC 0 \defaultmathfamily "23DD }
+
+% let's keep this
+
+\let\normaloverbrace \overbrace
+\let\normalunderbrace \underbrace
+\let\normaloverparent \overparent
+\let\normalunderparent \underparent
+\let\normaloverbracket \overbracket
+\let\normalunderbracket \underbracket
+\let\normalunderleftarrow \underleftarrow
+\let\normaloverleftarrow \overleftarrow
+\let\normalunderrightarrow\underrightarrow
+\let\normaloverrightarrow \overrightarrow
+
+%D Here come the new ones:
+
+\definemathstackers [\v!none] [\v!mathematics] [\c!hoffset=\zeropoint]
+\definemathstackers [\v!normal] [\v!mathematics] [\c!hoffset=0.5\emwidth] % the default
+\definemathstackers [\v!small] [\v!mathematics] [\c!hoffset=1\emwidth]
+\definemathstackers [\v!medium] [\v!mathematics] [\c!hoffset=1.5\emwidth]
+\definemathstackers [\v!big] [\v!mathematics] [\c!hoffset=2\emwidth]
+
+\definemathextensible [\v!reverse] [xrel] ["002D]
+\definemathextensible [\v!reverse] [xequal] ["003D]
+\definemathextensible [\v!reverse] [xleftarrow] ["2190] % ["27F5]
+\definemathextensible [\v!reverse] [xrightarrow] ["2192] % ["27F6]
+\definemathextensible [\v!reverse] [xleftrightarrow] ["27F7]
+\definemathextensible [\v!reverse] [xLeftarrow] ["27F8]
+\definemathextensible [\v!reverse] [xRightarrow] ["27F9]
+\definemathextensible [\v!reverse] [xLeftrightarrow] ["27FA]
+\definemathextensible [\v!reverse] [xtwoheadleftarrow] ["219E]
+\definemathextensible [\v!reverse] [xtwoheadrightarrow] ["21A0]
+\definemathextensible [\v!reverse] [xmapsto] ["21A6]
+\definemathextensible [\v!reverse] [xhookleftarrow] ["21A9]
+\definemathextensible [\v!reverse] [xhookrightarrow] ["21AA]
+\definemathextensible [\v!reverse] [xleftharpoondown] ["21BD]
+\definemathextensible [\v!reverse] [xleftharpoonup] ["21BC]
+\definemathextensible [\v!reverse] [xrightharpoondown] ["21C1]
+\definemathextensible [\v!reverse] [xrightharpoonup] ["21C0]
+\definemathextensible [\v!reverse] [xrightoverleftarrow] ["21C4]
+\definemathextensible [\v!reverse] [xleftrightharpoons] ["21CB]
+\definemathextensible [\v!reverse] [xrightleftharpoons] ["21CC]
+\definemathextensible [\v!reverse] [xtriplerel] ["2261]
+
+\definemathextensible [\v!mathematics] [mrel] ["002D]
+\definemathextensible [\v!mathematics] [mequal] ["003D]
+\definemathextensible [\v!mathematics] [mleftarrow] ["2190] % ["27F5]
+\definemathextensible [\v!mathematics] [mrightarrow] ["2192] % ["27F6]
+\definemathextensible [\v!mathematics] [mleftrightarrow] ["27F7]
+\definemathextensible [\v!mathematics] [mLeftarrow] ["27F8]
+\definemathextensible [\v!mathematics] [mRightarrow] ["27F9]
+\definemathextensible [\v!mathematics] [mLeftrightarrow] ["27FA]
+\definemathextensible [\v!mathematics] [mtwoheadleftarrow] ["219E]
+\definemathextensible [\v!mathematics] [mtwoheadrightarrow] ["21A0]
+\definemathextensible [\v!mathematics] [mmapsto] ["21A6]
+\definemathextensible [\v!mathematics] [mhookleftarrow] ["21A9]
+\definemathextensible [\v!mathematics] [mhookrightarrow] ["21AA]
+\definemathextensible [\v!mathematics] [mleftharpoondown] ["21BD]
+\definemathextensible [\v!mathematics] [mleftharpoonup] ["21BC]
+\definemathextensible [\v!mathematics] [mrightharpoondown] ["21C1]
+\definemathextensible [\v!mathematics] [mrightharpoonup] ["21C0]
+\definemathextensible [\v!mathematics] [mrightoverleftarrow] ["21C4]
+\definemathextensible [\v!mathematics] [mleftrightharpoons] ["21CB]
+\definemathextensible [\v!mathematics] [mrightleftharpoons] ["21CC]
+\definemathextensible [\v!mathematics] [mtriplerel] ["2261]
+
+\definemathextensible [\v!mathematics] [eleftarrowfill] ["2190] % ["27F5]
+\definemathextensible [\v!mathematics] [erightarrowfill] ["2192] % ["27F6]
+\definemathextensible [\v!mathematics] [eleftrightarrowfill] ["27F7]
+\definemathextensible [\v!mathematics] [etwoheadrightarrowfill] ["27F9]
+\definemathextensible [\v!mathematics] [eleftharpoondownfill] ["21BD]
+\definemathextensible [\v!mathematics] [eleftharpoonupfill] ["21BC]
+\definemathextensible [\v!mathematics] [erightharpoondownfill] ["21C1]
+\definemathextensible [\v!mathematics] [erightharpoonupfill] ["21C0]
+
+\definemathextensible [\v!mathematics] [eoverbarfill] ["FE33E]
+\definemathextensible [\v!mathematics] [eunderbarfill] ["FE33F]
+\definemathextensible [\v!mathematics] [eoverbracefill] ["FE3DE]
+\definemathextensible [\v!mathematics] [eunderbracefill] ["FE3DF]
+\definemathextensible [\v!mathematics] [eoverparentfill] ["FE3DC]
+\definemathextensible [\v!mathematics] [eunderparentfill] ["FE3DD]
+\definemathextensible [\v!mathematics] [eoverbracketfill] ["FE3B4]
+\definemathextensible [\v!mathematics] [eunderbracketfill] ["FE3B5]
+
+\definemathextensible [\v!text] [trel] ["002D]
+\definemathextensible [\v!text] [tequal] ["003D]
+\definemathextensible [\v!text] [tmapsto] ["21A6]
+\definemathextensible [\v!text] [tleftarrow] ["2190] % ["27F5]
+\definemathextensible [\v!text] [trightarrow] ["2192] % ["27F6]
+\definemathextensible [\v!text] [tleftrightarrow] ["27F7]
+\definemathextensible [\v!text] [tLeftarrow] ["27F8]
+\definemathextensible [\v!text] [tRightarrow] ["27F9]
+\definemathextensible [\v!text] [tLeftrightarrow] ["27FA]
+\definemathextensible [\v!text] [ttwoheadleftarrow] ["219E]
+\definemathextensible [\v!text] [ttwoheadrightarrow] ["21A0]
+\definemathextensible [\v!text] [thookleftarrow] ["21A9]
+\definemathextensible [\v!text] [thookrightarrow] ["21AA]
+\definemathextensible [\v!text] [tleftharpoondown] ["21BD]
+\definemathextensible [\v!text] [tleftharpoonup] ["21BC]
+\definemathextensible [\v!text] [trightharpoondown] ["21C1]
+\definemathextensible [\v!text] [trightharpoonup] ["21C0]
+\definemathextensible [\v!text] [trightoverleftarrow] ["21C4]
+\definemathextensible [\v!text] [tleftrightharpoons] ["21CB]
+\definemathextensible [\v!text] [trightleftharpoons] ["21CC]
+\definemathextensible [\v!text] [ttriplerel] ["2261]
+
+\definemathoverextensible [\v!top] [overleftarrow] ["2190] % ["27F5]
+\definemathoverextensible [\v!top] [overrightarrow] ["2192] % ["27F6]
+\definemathoverextensible [\v!top] [overleftrightarrow] ["27F7]
+\definemathoverextensible [\v!top] [overtwoheadleftarrow] ["27F8]
+\definemathoverextensible [\v!top] [overtwoheadrightarrow] ["27F9]
+\definemathoverextensible [\v!top] [overleftharpoondown] ["21BD]
+\definemathoverextensible [\v!top] [overleftharpoonup] ["21BC]
+\definemathoverextensible [\v!top] [overrightharpoondown] ["21C1]
+\definemathoverextensible [\v!top] [overrightharpoonup] ["21C0]
+
+\definemathunderextensible [\v!bottom] [underleftarrow] ["2190] % ["27F5]
+\definemathunderextensible [\v!bottom] [underrightarrow] ["2192] % ["27F6]
+\definemathunderextensible [\v!bottom] [underleftrightarrow] ["27F7]
+\definemathunderextensible [\v!bottom] [undertwoheadleftarrow] ["27F8]
+\definemathunderextensible [\v!bottom] [undertwoheadrightarrow] ["27F9]
+\definemathunderextensible [\v!bottom] [underleftharpoondown] ["21BD]
+\definemathunderextensible [\v!bottom] [underleftharpoonup] ["21BC]
+\definemathunderextensible [\v!bottom] [underrightharpoondown] ["21C1]
+\definemathunderextensible [\v!bottom] [underrightharpoonup] ["21C0]
+
+% We don't use overline and underline. This is one of the overlooked aspects of
+% unicode cq. opentype math: why treat rules different than e.g. arrows and
+% accents. It is a bit unfortunate that the opportunity to move math to new
+% technologies happened outside the tex domain (and/or some aspects were kept
+% while in fact they were side effects of limitations of traditional fonts).
+% From the unicode aware tex engines' implementation point of view things
+% could have been done a bit nicer but then: the community didn't seem to care
+% too much and just has to follow now.
+%
+% Anyhow, we use a character based approach so that at least we get unicode
+% stuff in the backend (okay, we still need to deal with some cut and paste
+% issues but at least we now know what we deal with.
+
+% alternatively we can move the original to FE*
+
+\definemathoverextensible [vfenced] [overbar] ["FE33E] % ["203E]
+\definemathunderextensible [vfenced] [underbar] ["FE33F] % ["203E]
+\definemathdoubleextensible [vfenced] [doublebar] ["FE33E] ["FE33F]
+
+\definemathoverextensible [vfenced] [overbrace] ["FE3DE] % ["023DE]
+\definemathunderextensible [vfenced] [underbrace] ["FE3DF] % ["023DF]
+\definemathdoubleextensible [vfenced] [doublebrace] ["FE3DE] ["FE3DF]
+
+\definemathoverextensible [vfenced] [overparent] ["FE3DC] % ["023DC]
+\definemathunderextensible [vfenced] [underparent] ["FE3DD] % ["023DD]
+\definemathdoubleextensible [vfenced] [doubleparent] ["FE3DC] ["FE3DD]
+
+\definemathoverextensible [vfenced] [overbracket] ["FE3B4] % ["023B4]
+\definemathunderextensible [vfenced] [underbracket] ["FE3B5] % ["023B5]
+\definemathdoubleextensible [vfenced] [doublebracket] ["FE3B4] ["FE3B5]
+
+% \unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
+
+%D For mathml:
+
+\definemathdoubleextensible [both] [overbarunderbar] ["FE33E] ["FE33F]
+\definemathdoubleextensible [both] [overbraceunderbrace] ["FE3DE] ["FE3DF]
+\definemathdoubleextensible [both] [overparentunderparent] ["FE3DC] ["FE3DD]
+\definemathdoubleextensible [both] [overbracketunderbracket] ["FE3B4] ["FE3B5]
+
+\definemathovertextextensible [bothtext] [overbartext] ["FE33E]
+\definemathundertextextensible [bothtext] [underbartext] ["FE33F]
+\definemathovertextextensible [bothtext] [overbracetext] ["FE3DE]
+\definemathundertextextensible [bothtext] [underbracetext] ["FE3DF]
+\definemathovertextextensible [bothtext] [overparenttext] ["FE3DC]
+\definemathundertextextensible [bothtext] [underparenttext] ["FE3DD]
+\definemathovertextextensible [bothtext] [overbrackettext] ["FE3B4]
+\definemathundertextextensible [bothtext] [underbrackettext] ["FE3B5]
+
+%D Some bonus ones (for the moment here):
+
+\definemathstackers
+ [\v!chemistry]
+ [\c!offset=\v!max,
+ \c!left=\enspace,
+ \c!right=\enspace,
+ \c!hoffset=.5\emwidth]
+
+\definemathextensible [\v!chemistry] [cleftarrow] ["2190]
+\definemathextensible [\v!chemistry] [crightarrow] ["2192]
+\definemathextensible [\v!chemistry] [crightoverleftarrow] ["21C4]
+
+% for the moment:
+
+\def\math_stackers_hacked_fill#1#2#3%
+ {\mathematics
+ {\begingroup
+ \mathsurround\zeropoint
+ \thickmuskip \zeromuskip
+ \medmuskip \zeromuskip
+ \thinmuskip \zeromuskip
+ #1%
+ \mkern-7\onemuskip
+ \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill
+ \mkern-7\onemuskip
+ #3%
+ \endgroup}}
+
+% These will be defined in char-def as well once we have \leaders<number>
+
+\unexpanded\def\rightarrowfill {\math_stackers_hacked_fill \relbar \relbar \rightarrow}
+\unexpanded\def\leftarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \relbar }
+\unexpanded\def\rightoverleftarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillleftend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillrightend}
+\unexpanded\def\equalfill {\math_stackers_hacked_fill \Relbar \Relbar \Relbar}
+\unexpanded\def\Rightarrowfill {\math_stackers_hacked_fill \Relbar \Relbar \Rightarrow}
+\unexpanded\def\Leftarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Relbar}
+\unexpanded\def\Leftrightarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Rightarrow}
+\unexpanded\def\leftrightarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \rightarrow}
+\unexpanded\def\mapstofill {\math_stackers_hacked_fill{\mapstochar\relbar} \relbar \rightarrow}
+\unexpanded\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar \relbar \twoheadrightarrow}
+\unexpanded\def\twoheadleftarrowfill {\math_stackers_hacked_fill \twoheadleftarrow \relbar \relbar}
+\unexpanded\def\rightharpoondownfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoondown}
+\unexpanded\def\rightharpoonupfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoonup}
+\unexpanded\def\leftharpoondownfill {\math_stackers_hacked_fill \leftharpoondown \relbar \relbar}
+\unexpanded\def\leftharpoonupfill {\math_stackers_hacked_fill \leftharpoonup \relbar \relbar}
+\unexpanded\def\hookleftfill {\math_stackers_hacked_fill \leftarrow \relbar {\relbar\joinrel\rhook}}
+\unexpanded\def\hookrightfill {\math_stackers_hacked_fill{\lhook\joinrel\relbar} \relbar \rightarrow}
+\unexpanded\def\relfill {\math_stackers_hacked_fill \relbar \relbar \relbar}
+\unexpanded\def\triplerelfill {\math_stackers_hacked_fill \equiv \equiv \equiv}
+
+\unexpanded\def\singlebond {{\xrel}} % or \def\singlebond{{\xrel[2]}}
+\unexpanded\def\doublebond {{\xequal}}
+\unexpanded\def\triplebond {{\xtriplerel}}
+
+\unexpanded\def\defineextensiblefiller
+ {\dodoubleargument\math_stackers_define_filler}
+
+\def\math_stackers_define_filler[#1][#2]%
+ {\setuevalue{#1}{\leaders\number#2\hfill}}
+
+%D For the moment:
+
+\def\math_stackers_define_filler[#1][#2]%
+ {\expandafter\let\csname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname
+ \expandafter\let\csname #1\expandafter\endcsname\csname#1\endcsname}
+
+\defineextensiblefiller [barfill] ["203E]
+\defineextensiblefiller [relfill] ["002D]
+\defineextensiblefiller [equalfill] ["003D]
+\defineextensiblefiller [leftarrowfill] ["2190]
+\defineextensiblefiller [rightarrowfill] ["2192]
+\defineextensiblefiller [twoheadleftarrowfill] ["219E]
+\defineextensiblefiller [twoheadrightarrowfill] ["21A0]
+\defineextensiblefiller [mapstofill] ["21A6]
+\defineextensiblefiller [hookleftarrowfill] ["21A9]
+\defineextensiblefiller [hookrightarrowfill] ["21AA]
+\defineextensiblefiller [leftharpoondownfill] ["21BD]
+\defineextensiblefiller [leftharpoonupfill] ["21BC]
+\defineextensiblefiller [rightharpoondownfill] ["21C1]
+\defineextensiblefiller [rightharpoonupfill] ["21C0]
+\defineextensiblefiller [rightoverleftarrowfill] ["21C4]
+\defineextensiblefiller [leftrightharpoonsfill] ["21CB]
+\defineextensiblefiller [rightleftharpoonsfill] ["21CC]
+\defineextensiblefiller [triplerelfill] ["2261]
+\defineextensiblefiller [leftrightarrowfill] ["27F7]
+\defineextensiblefiller [Leftarrowfill] ["27F8]
+\defineextensiblefiller [Rightarrowfill] ["27F9]
+\defineextensiblefiller [Leftrightarrowfill] ["27FA]
+\defineextensiblefiller [Leftrightarrowfill] ["27FA]
+
+%defineextensiblefiller [overbarfill] ["FE33E] % untested
+%defineextensiblefiller [underbarfill] ["FE33F] % untested
+\defineextensiblefiller [overbracefill] ["FE3DE] % untested
+\defineextensiblefiller [underbracefill] ["FE3DF] % untested
+\defineextensiblefiller [overparentfill] ["FE3DC] % untested
+\defineextensiblefiller [underparentfill] ["FE3DD] % untested
+\defineextensiblefiller [overbracketfill] ["FE3B4] % untested
+\defineextensiblefiller [underbracketfill] ["FE3B5] % untested
+
+%D Extra:
+
+\unexpanded\edef\singlebond{\mathematics{\mathsurround\zeropoint\char\number"002D\relax}}
+\unexpanded\edef\doublebond{\mathematics{\mathsurround\zeropoint\char\number"003D\relax}}
+\unexpanded\edef\triplebond{\mathematics{\mathsurround\zeropoint\char\number"2261\relax}}
+
+% \mathchardef\singlebond"002D
+% \mathchardef\doublebond"003D
+% \mathchardef\triplebond"2261
+
+%D Also handy:
+
+\unexpanded\def\definemathunstacked
+ {\dotripleempty\math_stackers_define_unstacked_normal}
+
+\def\math_stackers_define_unstacked_normal[#1][#2][#3]% category name unicode
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_unstacked_normal{#1}{\number#3}}%
+ \else
+ \setuevalue{#1}{\math_stackers_unstacked_normal\noexpand\currentmathstackers{\number#2}}%
+ \fi}
+
+\unexpanded\def\math_stackers_unstacked_normal#category#codepoint%
+ {\begingroup
+ \edef\currentmathstackers{#category}%
+ \edef\p_moffset{\mathstackersparameter\c!moffset}%
+ \ifx\p_moffset\empty \else
+ \mskip\p_moffset\relax
+ \fi
+ \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
+ {\usemathstackerscolorparameter\c!color
+ \Umathchar\zerocount\defaultmathfamily#codepoint}%
+ \ifx\p_moffset\empty \else
+ \mskip\p_moffset\relax
+ \fi
+ \endgroup}
+
+\definemathstackers [\v!wide] [\c!moffset=\thickmuskip,\c!mathclass=\s!rel]
+
+\definemathunstacked [\v!wide] [And] ["0026] % \mathrel{\;&\;}
+\definemathunstacked [\v!wide] [impliedby] ["27F8] % \mathrel{\;\Longleftarrow\;}
+\definemathunstacked [\v!wide] [implies] ["27F9] % \mathrel{\;\Longrightarrow\;}
+\definemathunstacked [\v!wide] [iff] ["27FA] % \mathrel{\;\Longleftrightarrow\;}
+
+\protect \endinput
+
+% \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}
+% \limits\normalsuperscript{\box0}\normalsubscript{\box2}}%
+
+% $\Uoverdelimiter \defaultmathfamily "2194 {xxxx}$
+% $\Uunderdelimiter\defaultmathfamily "2194 {xxxx}$
+% $\Udelimiterover \defaultmathfamily "2194 {xxxx}$
+% $\Udelimiterunder\defaultmathfamily "2194 {xxxx}$
+% $\Udelimiterover \defaultmathfamily "219A {\Udelimiterunder \defaultmathfamily "219B {xxxx}}$
+
+% $a \mathrel{\mathop{\filledhboxr{mid}}}\limits^{\filledhboxg{\strut top}}_{\filledhboxb{\strut bottom}} b$
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua
new file mode 100644
index 00000000000..e83b401fb2d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua
@@ -0,0 +1,555 @@
+if not modules then modules = { } end modules ['math-tag'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: have a local list with local tags that then get appended
+-- todo: use tex.getmathcodes (no table)
+
+-- use lpeg matchers
+
+local find, match = string.find, string.match
+local insert, remove, concat = table.insert, table.remove, table.concat
+
+local attributes = attributes
+local nodes = nodes
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getlist = nuts.getlist
+local getfield = nuts.getfield
+local getdisc = nuts.getdisc
+local getsubtype = nuts.getsubtype
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+
+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 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_taggedpar = attributes.private('taggedpar')
+local a_exportstatus = attributes.private('exportstatus')
+local a_mathcategory = attributes.private('mathcategory')
+local a_mathmode = attributes.private('mathmode')
+local a_fontkern = attributes.private('fontkern')
+
+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 getmathcode = tex.getmathcode
+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 process
+
+local function processsubsup(start)
+ -- At some point we might need to add an attribute signaling the
+ -- super- and subscripts because TeX and MathML use a different
+ -- order. The mrows are needed to keep mn's separated.
+ local nucleus = getfield(start,"nucleus")
+ local sup = getfield(start,"sup")
+ local sub = getfield(start,"sub")
+ if sub then
+ if sup then
+ setattr(start,a_tagged,start_tagged("msubsup"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow")
+ process(sub)
+ stop_tagged()
+ start_tagged("mrow")
+ process(sup)
+ stop_tagged()
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("msub"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow")
+ process(sub)
+ stop_tagged()
+ stop_tagged()
+ end
+ elseif sup then
+ setattr(start,a_tagged,start_tagged("msup"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow")
+ process(sup)
+ stop_tagged()
+ stop_tagged()
+ else
+ process(nucleus)
+ end
+end
+
+-- todo: check function here and keep attribute the same
+
+-- todo: variants -> original
+
+local actionstack = { }
+local fencesstack = { }
+
+-- glyph nodes and such can happen in under and over stuff
+
+local function getunicode(n) -- instead of getchar
+ local char = getchar(n)
+ -- local font = 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 content = { }
+local found = false
+
+content[math_char_code] = function() found = true end
+
+local function hascontent(head)
+ found = false
+ processnoads(head,content,"content")
+ return found
+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
+
+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)
+
+ if id == glyph_code or id == disc_code then
+ if not mtexttag then
+ mtexttag = start_tagged("mtext")
+ end
+ setattr(start,a_tagged,mtexttag)
+ elseif mtexttag and id == kern_code and (getsubtype(start) == fontkern_code or getattr(start,a_fontkern)) then
+ setattr(start,a_tagged,mtexttag)
+ else
+ if mtexttag then
+ stop_tagged()
+ mtexttag = nil
+ end
+ if id == math_char_code then
+ local char = getchar(start)
+ local code = getmathcode(char)
+ if code then
+ code = code[1]
+ end
+ local tag
+ if code == ordinary_code or code == variable_code then
+ local ch = chardata[char]
+ local mc = ch and ch.mathclass
+ if mc == "number" then
+ tag = "mn"
+ elseif mc == "variable" or not mc then -- variable is default
+ tag = "mi"
+ else
+ tag = "mo"
+ end
+ else
+ tag = "mo"
+ end
+ local a = getattr(start,a_mathcategory)
+ if a then
+ setattr(start,a_tagged,start_tagged(tag,{ mathcategory = a }))
+ else
+ setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory
+ end
+ stop_tagged()
+ break -- okay?
+ elseif id == math_textchar_code then -- or id == glyph_code
+ -- check for code
+ local a = getattr(start,a_mathcategory)
+ if a then
+ setattr(start,a_tagged,start_tagged("ms",{ mathcategory = a })) -- mtext
+ else
+ setattr(start,a_tagged,start_tagged("ms")) -- mtext
+ end
+ stop_tagged()
+ break
+ elseif id == math_delim_code then
+ -- check for code
+ setattr(start,a_tagged,start_tagged("mo"))
+ stop_tagged()
+ break
+ elseif id == math_style_code then
+ -- has a next
+ elseif id == math_noad_code then
+ 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
+ local attr = getattr(start,a_tagged)
+ local specification = taglist[attr]
+ local tag = specification.tagname
+ if tag == "formulacaption" then
+ -- skip
+ elseif tag == "mstacker" then
+ local list = getfield(start,"list")
+ 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 = getfield(start,"list")
+ 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 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
+ end
+ else
+ ac = text
+ end
+ cache[aa] = ac
+ end
+ setattr(n,a_tagged,ac)
+ else
+ setattr(n,a_tagged,text)
+ end
+
+ if id == hlist_code or id == vlist_code then
+ runner(getlist(n),depth+1)
+ elseif id == glyph_code then
+ runner(getfield(n,"components"),depth+1) -- this should not be needed
+ 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
+ end
+ runner(list,0)
+ end
+ stop_tagged()
+ end
+ elseif id == math_sub_code then -- normally a hbox
+ local list = getfield(start,"list")
+ if list then
+ local attr = getattr(start,a_tagged)
+ local last = attr and taglist[attr]
+ if last then
+ local tag = last.tagname
+ local detail = last.detail
+ if tag == "maction" then
+ if detail == "" then
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ elseif actionstack[#actionstack] == action then
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ else
+ insert(actionstack,action)
+ setattr(start,a_tagged,start_tagged("mrow",{ detail = action }))
+ process(list)
+ stop_tagged()
+ remove(actionstack)
+ end
+ elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then
+ -- looks like it gets processed twice
+-- do we still end up here ?
+ setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute
+ process(list)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ end
+ else -- never happens, we're always document
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ end
+ end
+ elseif id == math_fraction_code then
+ local num = getfield(start,"num")
+ local denom = getfield(start,"denom")
+ local left = getfield(start,"left")
+ local right = getfield(start,"right")
+ if left then
+ setattr(left,a_tagged,start_tagged("mo"))
+ process(left)
+ stop_tagged()
+ end
+ setattr(start,a_tagged,start_tagged("mfrac"))
+ process(num)
+ process(denom)
+ stop_tagged()
+ if right then
+ setattr(right,a_tagged,start_tagged("mo"))
+ process(right)
+ stop_tagged()
+ end
+ elseif id == math_choice_code then
+ local display = getfield(start,"display")
+ local text = getfield(start,"text")
+ local script = getfield(start,"script")
+ local scriptscript = getfield(start,"scriptscript")
+ if display then
+ process(display)
+ end
+ if text then
+ process(text)
+ end
+ if script then
+ process(script)
+ end
+ if scriptscript then
+ process(scriptscript)
+ end
+ elseif id == math_fence_code then
+ local delim = getfield(start,"delim")
+ local subtype = getfield(start,"subtype")
+ if subtype == 1 then
+ -- left
+ local properties = { }
+ insert(fencesstack,properties)
+ setattr(start,a_tagged,start_tagged("mfenced",{ properties = properties })) -- needs checking
+ if delim then
+ start_tagged("ignore")
+ local chr = getfield(delim,"small_char")
+ if chr ~= 0 then
+ properties.left = chr
+ end
+ process(delim)
+ stop_tagged()
+ end
+ start_tagged("mrow") -- begin of subsequence
+ elseif subtype == 2 then
+ -- middle
+ if delim then
+ start_tagged("ignore")
+ local top = fencesstack[#fencesstack]
+ local chr = getfield(delim,"small_char")
+ if chr ~= 0 then
+ local mid = top.middle
+ if mid then
+ mid[#mid+1] = chr
+ else
+ top.middle = { chr }
+ end
+ end
+ process(delim)
+ stop_tagged()
+ end
+ stop_tagged() -- end of subsequence
+ start_tagged("mrow") -- begin of subsequence
+ elseif subtype == 3 then
+ local properties = remove(fencesstack)
+ if not properties then
+ report_tags("missing right fence")
+ properties = { }
+ end
+ if delim then
+ start_tagged("ignore")
+ local chr = getfield(delim,"small_char")
+ if chr ~= 0 then
+ properties.right = chr
+ end
+ process(delim)
+ stop_tagged()
+ end
+ stop_tagged() -- end of subsequence
+ stop_tagged()
+ else
+ -- can't happen
+ end
+ elseif id == math_radical_code then
+ local left = getfield(start,"left")
+ local degree = getfield(start,"degree")
+ if left then
+ start_tagged("ignore")
+ process(left) -- root symbol, ignored
+ stop_tagged()
+ end
+ if degree and hascontent(degree) then
+ setattr(start,a_tagged,start_tagged("mroot"))
+ processsubsup(start)
+ process(degree)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("msqrt"))
+ processsubsup(start)
+ stop_tagged()
+ end
+ elseif id == math_accent_code then
+ local accent = getfield(start,"accent")
+ local bot_accent = getfield(start,"bot_accent")
+ local subtype = getsubtype(start)
+ if bot_accent then
+ if accent then
+ setattr(start,a_tagged,start_tagged("munderover", {
+ accent = true,
+ top = getunicode(accent),
+ bottom = getunicode(bot_accent),
+ topfixed = subtype == math_fixed_top or subtype == math_fixed_both,
+ bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both,
+ }))
+ processsubsup(start)
+ process(bot_accent)
+ process(accent)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("munder", {
+ accent = true,
+ bottom = getunicode(bot_accent),
+ bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both,
+ }))
+ processsubsup(start)
+ process(bot_accent)
+ stop_tagged()
+ end
+ elseif accent then
+ setattr(start,a_tagged,start_tagged("mover", {
+ accent = true,
+ top = getunicode(accent),
+ topfixed = subtype == math_fixed_top or subtype == math_fixed_both,
+ }))
+ processsubsup(start)
+ process(accent)
+ stop_tagged()
+ else
+ processsubsup(start)
+ end
+ elseif id == glue_code then
+ -- setattr(start,a_tagged,start_tagged("mspace",{ width = getfield(start,"width") }))
+ setattr(start,a_tagged,start_tagged("mspace"))
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] }))
+ stop_tagged()
+ end
+ end
+ start = getnext(start)
+ end
+ if mtexttag then
+ stop_tagged()
+ 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" })
+ setattr(head,a_tagged,start_tagged("mrow"))
+ process(head)
+ stop_tagged()
+ stop_tagged()
+ return true
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ttv.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ttv.lua
new file mode 100644
index 00000000000..1f644e78834
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-ttv.lua
@@ -0,0 +1,801 @@
+if not modules then modules = { } end modules ['math-ttv'] = {
+ version = 1.001,
+ comment = "traditional tex vectors, companion to math-vfu.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+local vfmath = fonts.handlers.vf.math
+local setletters = vfmath.setletters
+local setdigits = vfmath.setdigits
+
+local mathencodings = fonts.encodings.math
+
+-- varphi is part of the alphabet, contrary to the other var*s'
+
+mathencodings["large-to-small"] = {
+ [0x00028] = 0x00, -- (
+ [0x00029] = 0x01, -- )
+ [0x0005B] = 0x02, -- [
+ [0x0005D] = 0x03, -- ]
+ [0x0230A] = 0x04, -- lfloor
+ [0x0230B] = 0x05, -- rfloor
+ [0x02308] = 0x06, -- lceil
+ [0x02309] = 0x07, -- rceil
+ [0x0007B] = 0x08, -- {
+ [0x0007D] = 0x09, -- }
+ [0x027E8] = 0x0A, -- <
+ [0x027E9] = 0x0B, -- >
+ [0x0007C] = 0x0C, -- |
+ -- [0x0] = 0x0D, -- lVert rVert Vert
+ -- [0x0002F] = 0x0E, -- /
+ [0x0005C] = 0x0F, -- \
+ -- [0x0] = 0x3A, -- lgroup
+ -- [0x0] = 0x3B, -- rgroup
+ -- [0x0] = 0x3C, -- arrowvert
+ -- [0x0] = 0x3D, -- Arrowvert
+ [0x02195] = 0x3F, -- updownarrow
+ -- [0x0] = 0x40, -- lmoustache
+ -- [0x0] = 0x41, -- rmoustache
+ [0x0221A] = 0x70, -- sqrt
+ [0x021D5] = 0x77, -- Updownarrow
+ [0x02191] = 0x78, -- uparrow
+ [0x02193] = 0x79, -- downarrow
+ [0x021D1] = 0x7E, -- Uparrow
+ [0x021D3] = 0x7F, -- Downarrow
+ [0x0220F] = 0x59, -- prod
+ [0x02210] = 0x61, -- coprod
+ [0x02211] = 0x58, -- sum
+ [0x0222B] = 0x5A, -- intop
+ [0x0222E] = 0x49, -- ointop
+ -- [0xFE302] = 0x62, -- widehat
+ -- [0xFE303] = 0x65, -- widetilde
+ [0x00302] = 0x62, -- widehat
+ [0x00303] = 0x65, -- widetilde
+ [0x022C0] = 0x5E, -- bigwedge
+ [0x022C1] = 0x5F, -- bigvee
+ [0x022C2] = 0x5C, -- bigcap
+ [0x022C3] = 0x5B, -- bigcup
+ [0x02044] = 0x0E, -- /
+}
+
+-- Beware: these are (in cm/lm) below the baseline due to limitations
+-- in the tfm format bu the engien (combined with the mathclass) takes
+-- care of it. If we need them in textmode, we should make them virtual
+-- and move them up but we're in no hurry with that.
+
+mathencodings["tex-ex"] = {
+ [0x0220F] = 0x51, -- prod
+ [0x02210] = 0x60, -- coprod
+ [0x02211] = 0x50, -- sum
+ [0x0222B] = 0x52, -- intop
+ [0x0222E] = 0x48, -- ointop
+ [0x022C0] = 0x56, -- bigwedge
+ [0x022C1] = 0x57, -- bigvee
+ [0x022C2] = 0x54, -- bigcap
+ [0x022C3] = 0x53, -- bigcup
+ [0x02A00] = 0x4A, -- bigodot -- fixed BJ
+ [0x02A01] = 0x4C, -- bigoplus
+ [0x02A02] = 0x4E, -- bigotimes
+ -- [0x02A03] = , -- bigudot --
+ [0x02A04] = 0x55, -- biguplus
+ [0x02A06] = 0x46, -- bigsqcup
+}
+
+-- only math stuff is needed, since we always use an lm or gyre
+-- font as main font
+
+mathencodings["tex-mr"] = {
+ [0x00393] = 0x00, -- Gamma
+ [0x00394] = 0x01, -- Delta
+ [0x00398] = 0x02, -- Theta
+ [0x0039B] = 0x03, -- Lambda
+ [0x0039E] = 0x04, -- Xi
+ [0x003A0] = 0x05, -- Pi
+ [0x003A3] = 0x06, -- Sigma
+ [0x003A5] = 0x07, -- Upsilon
+ [0x003A6] = 0x08, -- Phi
+ [0x003A8] = 0x09, -- Psi
+ [0x003A9] = 0x0A, -- Omega
+-- [0x00060] = 0x12, -- [math]grave
+-- [0x000B4] = 0x13, -- [math]acute
+-- [0x002C7] = 0x14, -- [math]check
+-- [0x002D8] = 0x15, -- [math]breve
+-- [0x000AF] = 0x16, -- [math]bar
+-- [0x00021] = 0x21, -- !
+-- [0x00028] = 0x28, -- (
+-- [0x00029] = 0x29, -- )
+-- [0x0002B] = 0x2B, -- +
+-- [0x0002F] = 0x2F, -- /
+-- [0x0003A] = 0x3A, -- :
+-- [0x02236] = 0x3A, -- colon
+-- [0x0003B] = 0x3B, -- ;
+-- [0x0003C] = 0x3C, -- <
+-- [0x0003D] = 0x3D, -- =
+-- [0x0003E] = 0x3E, -- >
+-- [0x0003F] = 0x3F, -- ?
+ [0x00391] = 0x41, -- Alpha
+ [0x00392] = 0x42, -- Beta
+ [0x02145] = 0x44,
+ [0x00395] = 0x45, -- Epsilon
+ [0x00397] = 0x48, -- Eta
+ [0x00399] = 0x49, -- Iota
+ [0x0039A] = 0x4B, -- Kappa
+ [0x0039C] = 0x4D, -- Mu
+ [0x0039D] = 0x4E, -- Nu
+ [0x0039F] = 0x4F, -- Omicron
+ [0x003A1] = 0x52, -- Rho
+ [0x003A4] = 0x54, -- Tau
+ [0x003A7] = 0x58, -- Chi
+ [0x00396] = 0x5A, -- Zeta
+-- [0x0005B] = 0x5B, -- [
+-- [0x0005D] = 0x5D, -- ]
+-- [0x0005E] = 0x5E, -- [math]hat -- the text one
+ [0x00302] = 0x5E, -- [math]hat -- the real math one
+-- [0x002D9] = 0x5F, -- [math]dot
+ [0x02146] = 0x64,
+ [0x02147] = 0x65,
+-- [0x002DC] = 0x7E, -- [math]tilde -- the text one
+ [0x00303] = 0x7E, -- [math]tilde -- the real one
+-- [0x000A8] = 0x7F, -- [math]ddot
+}
+
+mathencodings["tex-mr-missing"] = {
+ [0x02236] = 0x3A, -- colon
+}
+
+mathencodings["tex-mi"] = {
+ [0x1D6E4] = 0x00, -- Gamma
+ [0x1D6E5] = 0x01, -- Delta
+ [0x1D6E9] = 0x02, -- Theta
+ [0x1D6F3] = 0x02, -- varTheta (not present in TeX)
+ [0x1D6EC] = 0x03, -- Lambda
+ [0x1D6EF] = 0x04, -- Xi
+ [0x1D6F1] = 0x05, -- Pi
+ [0x1D6F4] = 0x06, -- Sigma
+ [0x1D6F6] = 0x07, -- Upsilon
+ [0x1D6F7] = 0x08, -- Phi
+ [0x1D6F9] = 0x09, -- Psi
+ [0x1D6FA] = 0x0A, -- Omega
+ [0x1D6FC] = 0x0B, -- alpha
+ [0x1D6FD] = 0x0C, -- beta
+ [0x1D6FE] = 0x0D, -- gamma
+ [0x1D6FF] = 0x0E, -- delta
+ [0x1D716] = 0x0F, -- epsilon TODO: 1D716
+ [0x1D701] = 0x10, -- zeta
+ [0x1D702] = 0x11, -- eta
+ [0x1D703] = 0x12, -- theta TODO: 1D703
+ [0x1D704] = 0x13, -- iota
+ [0x1D705] = 0x14, -- kappa
+ [0x1D718] = 0x14, -- varkappa, not in tex fonts
+ [0x1D706] = 0x15, -- lambda
+ [0x1D707] = 0x16, -- mu
+ [0x1D708] = 0x17, -- nu
+ [0x1D709] = 0x18, -- xi
+ [0x1D70B] = 0x19, -- pi
+ [0x1D70C] = 0x1A, -- rho
+ [0x1D70E] = 0x1B, -- sigma
+ [0x1D70F] = 0x1C, -- tau
+ [0x1D710] = 0x1D, -- upsilon
+ [0x1D719] = 0x1E, -- phi
+ [0x1D712] = 0x1F, -- chi
+ [0x1D713] = 0x20, -- psi
+ [0x1D714] = 0x21, -- omega
+ [0x1D700] = 0x22, -- varepsilon (the other way around)
+ [0x1D717] = 0x23, -- vartheta
+ [0x1D71B] = 0x24, -- varpi
+ [0x1D71A] = 0x25, -- varrho
+ [0x1D70D] = 0x26, -- varsigma
+ [0x1D711] = 0x27, -- varphi (the other way around)
+ [0x021BC] = 0x28, -- leftharpoonup
+ [0x021BD] = 0x29, -- leftharpoondown
+ [0x021C0] = 0x2A, -- rightharpoonup
+ [0x021C1] = 0x2B, -- rightharpoondown
+ [0xFE322] = 0x2C, -- lhook (hook for combining arrows)
+ [0xFE323] = 0x2D, -- rhook (hook for combining arrows)
+ [0x025B7] = 0x2E, -- triangleright : cf lmmath / BJ
+ [0x025C1] = 0x2F, -- triangleleft : cf lmmath / BJ
+ [0x022B3] = 0x2E, -- triangleright : cf lmmath this a cramped triangles / BJ / see *
+ [0x022B2] = 0x2F, -- triangleleft : cf lmmath this a cramped triangles / BJ / see *
+-- [0x00041] = 0x30, -- 0
+-- [0x00041] = 0x31, -- 1
+-- [0x00041] = 0x32, -- 2
+-- [0x00041] = 0x33, -- 3
+-- [0x00041] = 0x34, -- 4
+-- [0x00041] = 0x35, -- 5
+-- [0x00041] = 0x36, -- 6
+-- [0x00041] = 0x37, -- 7
+-- [0x00041] = 0x38, -- 8
+-- [0x00041] = 0x39, -- 9
+--~ [0x0002E] = 0x3A, -- .
+ [0x0002C] = 0x3B, -- ,
+ [0x0003C] = 0x3C, -- <
+-- [0x0002F] = 0x3D, -- /, slash, solidus
+ [0x02044] = 0x3D, -- / AM: Not sure
+ [0x0003E] = 0x3E, -- >
+ [0x022C6] = 0x3F, -- star
+ [0x02202] = 0x40, -- partial
+--
+ [0x0266D] = 0x5B, -- flat
+ [0x0266E] = 0x5C, -- natural
+ [0x0266F] = 0x5D, -- sharp
+ [0x02323] = 0x5E, -- smile
+ [0x02322] = 0x5F, -- frown
+ [0x02113] = 0x60, -- ell
+--
+ [0x1D6A4] = 0x7B, -- imath (TODO: also 0131)
+ [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237)
+ [0x02118] = 0x7D, -- wp
+ [0x020D7] = 0x7E, -- vec (TODO: not sure)
+-- 0x7F, -- (no idea what that could be)
+}
+
+mathencodings["tex-it"] = {
+-- [0x1D434] = 0x41, -- A
+ [0x1D6E2] = 0x41, -- Alpha
+-- [0x1D435] = 0x42, -- B
+ [0x1D6E3] = 0x42, -- Beta
+-- [0x1D436] = 0x43, -- C
+-- [0x1D437] = 0x44, -- D
+-- [0x1D438] = 0x45, -- E
+ [0x1D6E6] = 0x45, -- Epsilon
+-- [0x1D439] = 0x46, -- F
+-- [0x1D43A] = 0x47, -- G
+-- [0x1D43B] = 0x48, -- H
+ [0x1D6E8] = 0x48, -- Eta
+-- [0x1D43C] = 0x49, -- I
+ [0x1D6EA] = 0x49, -- Iota
+-- [0x1D43D] = 0x4A, -- J
+-- [0x1D43E] = 0x4B, -- K
+ [0x1D6EB] = 0x4B, -- Kappa
+-- [0x1D43F] = 0x4C, -- L
+-- [0x1D440] = 0x4D, -- M
+ [0x1D6ED] = 0x4D, -- Mu
+-- [0x1D441] = 0x4E, -- N
+ [0x1D6EE] = 0x4E, -- Nu
+-- [0x1D442] = 0x4F, -- O
+ [0x1D6F0] = 0x4F, -- Omicron
+-- [0x1D443] = 0x50, -- P
+ [0x1D6F2] = 0x50, -- Rho
+-- [0x1D444] = 0x51, -- Q
+-- [0x1D445] = 0x52, -- R
+-- [0x1D446] = 0x53, -- S
+-- [0x1D447] = 0x54, -- T
+ [0x1D6F5] = 0x54, -- Tau
+-- [0x1D448] = 0x55, -- U
+-- [0x1D449] = 0x56, -- V
+-- [0x1D44A] = 0x57, -- W
+-- [0x1D44B] = 0x58, -- X
+ [0x1D6F8] = 0x58, -- Chi
+-- [0x1D44C] = 0x59, -- Y
+-- [0x1D44D] = 0x5A, -- Z
+--
+-- [0x1D44E] = 0x61, -- a
+-- [0x1D44F] = 0x62, -- b
+-- [0x1D450] = 0x63, -- c
+-- [0x1D451] = 0x64, -- d
+-- [0x1D452] = 0x65, -- e
+-- [0x1D453] = 0x66, -- f
+-- [0x1D454] = 0x67, -- g
+-- [0x1D455] = 0x68, -- h
+ [0x0210E] = 0x68, -- Planck constant (h)
+-- [0x1D456] = 0x69, -- i
+-- [0x1D457] = 0x6A, -- j
+-- [0x1D458] = 0x6B, -- k
+-- [0x1D459] = 0x6C, -- l
+-- [0x1D45A] = 0x6D, -- m
+-- [0x1D45B] = 0x6E, -- n
+-- [0x1D45C] = 0x6F, -- o
+ [0x1D70A] = 0x6F, -- omicron
+-- [0x1D45D] = 0x70, -- p
+-- [0x1D45E] = 0x71, -- q
+-- [0x1D45F] = 0x72, -- r
+-- [0x1D460] = 0x73, -- s
+-- [0x1D461] = 0x74, -- t
+-- [0x1D462] = 0x75, -- u
+-- [0x1D463] = 0x76, -- v
+-- [0x1D464] = 0x77, -- w
+-- [0x1D465] = 0x78, -- x
+-- [0x1D466] = 0x79, -- y
+-- [0x1D467] = 0x7A, -- z
+}
+
+mathencodings["tex-ss"] = { }
+mathencodings["tex-tt"] = { }
+mathencodings["tex-bf"] = { }
+mathencodings["tex-bi"] = { }
+mathencodings["tex-fraktur"] = { }
+mathencodings["tex-fraktur-bold"] = { }
+
+mathencodings["tex-sy"] = {
+ [0x0002D] = 0x00, -- -
+ [0x02212] = 0x00, -- -
+-- [0x02201] = 0x00, -- complement
+-- [0x02206] = 0x00, -- increment
+-- [0x02204] = 0x00, -- not exists
+-- [0x000B7] = 0x01, -- cdot
+ [0x022C5] = 0x01, -- cdot
+ [0x000D7] = 0x02, -- times
+ [0x0002A] = 0x03, -- *
+ [0x02217] = 0x03, -- *
+ [0x000F7] = 0x04, -- div
+ [0x022C4] = 0x05, -- diamond
+ [0x000B1] = 0x06, -- pm
+ [0x02213] = 0x07, -- mp
+ [0x02295] = 0x08, -- oplus
+ [0x02296] = 0x09, -- ominus
+ [0x02297] = 0x0A, -- otimes
+ [0x02298] = 0x0B, -- oslash
+ [0x02299] = 0x0C, -- odot
+ [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo
+ [0x02218] = 0x0E, -- circ
+ [0x02219] = 0x0F, -- bullet
+ [0x02022] = 0x0F, -- bullet
+ [0x0224D] = 0x10, -- asymp
+ [0x02261] = 0x11, -- equiv
+ [0x02286] = 0x12, -- subseteq
+ [0x02287] = 0x13, -- supseteq
+ [0x02264] = 0x14, -- leq
+ [0x02265] = 0x15, -- geq
+ [0x02AAF] = 0x16, -- preceq
+-- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF
+ [0x02AB0] = 0x17, -- succeq
+-- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0
+ [0x0223C] = 0x18, -- sim
+ [0x02248] = 0x19, -- approx
+ [0x02282] = 0x1A, -- subset
+ [0x02283] = 0x1B, -- supset
+ [0x0226A] = 0x1C, -- ll
+ [0x0226B] = 0x1D, -- gg
+ [0x0227A] = 0x1E, -- prec
+ [0x0227B] = 0x1F, -- succ
+ [0x02190] = 0x20, -- leftarrow
+ [0x02192] = 0x21, -- rightarrow
+--~ [0xFE190] = 0x20, -- leftarrow
+--~ [0xFE192] = 0x21, -- rightarrow
+ [0x02191] = 0x22, -- uparrow
+ [0x02193] = 0x23, -- downarrow
+ [0x02194] = 0x24, -- leftrightarrow
+ [0x02197] = 0x25, -- nearrow
+ [0x02198] = 0x26, -- searrow
+ [0x02243] = 0x27, -- simeq
+ [0x021D0] = 0x28, -- Leftarrow
+ [0x021D2] = 0x29, -- Rightarrow
+ [0x021D1] = 0x2A, -- Uparrow
+ [0x021D3] = 0x2B, -- Downarrow
+ [0x021D4] = 0x2C, -- Leftrightarrow
+ [0x02196] = 0x2D, -- nwarrow
+ [0x02199] = 0x2E, -- swarrow
+ [0x0221D] = 0x2F, -- propto
+ [0x02032] = 0x30, -- prime
+ [0x0221E] = 0x31, -- infty
+ [0x02208] = 0x32, -- in
+ [0x0220B] = 0x33, -- ni
+ [0x025B3] = 0x34, -- triangle, bigtriangleup
+ [0x025BD] = 0x35, -- bigtriangledown
+ [0x00338] = 0x36, -- not
+-- 0x37, -- (beginning of arrow)
+ [0x02200] = 0x38, -- forall
+ [0x02203] = 0x39, -- exists
+ [0x000AC] = 0x3A, -- neg, lnot
+ [0x02205] = 0x3B, -- empty set
+ [0x0211C] = 0x3C, -- Re
+ [0x02111] = 0x3D, -- Im
+ [0x022A4] = 0x3E, -- top
+ [0x022A5] = 0x3F, -- bot, perp
+ [0x02135] = 0x40, -- aleph
+ [0x1D49C] = 0x41, -- script A
+ [0x0212C] = 0x42, -- script B
+ [0x1D49E] = 0x43, -- script C
+ [0x1D49F] = 0x44, -- script D
+ [0x02130] = 0x45, -- script E
+ [0x02131] = 0x46, -- script F
+ [0x1D4A2] = 0x47, -- script G
+ [0x0210B] = 0x48, -- script H
+ [0x02110] = 0x49, -- script I
+ [0x1D4A5] = 0x4A, -- script J
+ [0x1D4A6] = 0x4B, -- script K
+ [0x02112] = 0x4C, -- script L
+ [0x02133] = 0x4D, -- script M
+ [0x1D4A9] = 0x4E, -- script N
+ [0x1D4AA] = 0x4F, -- script O
+ [0x1D4AB] = 0x50, -- script P
+ [0x1D4AC] = 0x51, -- script Q
+ [0x0211B] = 0x52, -- script R
+ [0x1D4AE] = 0x53, -- script S
+ [0x1D4AF] = 0x54, -- script T
+ [0x1D4B0] = 0x55, -- script U
+ [0x1D4B1] = 0x56, -- script V
+ [0x1D4B2] = 0x57, -- script W
+ [0x1D4B3] = 0x58, -- script X
+ [0x1D4B4] = 0x59, -- script Y
+ [0x1D4B5] = 0x5A, -- script Z
+ [0x0222A] = 0x5B, -- cup
+ [0x02229] = 0x5C, -- cap
+ [0x0228E] = 0x5D, -- uplus
+ [0x02227] = 0x5E, -- wedge, land
+ [0x02228] = 0x5F, -- vee, lor
+ [0x022A2] = 0x60, -- vdash
+ [0x022A3] = 0x61, -- dashv
+ [0x0230A] = 0x62, -- lfloor
+ [0x0230B] = 0x63, -- rfloor
+ [0x02308] = 0x64, -- lceil
+ [0x02309] = 0x65, -- rceil
+ [0x0007B] = 0x66, -- {, lbrace
+ [0x0007D] = 0x67, -- }, rbrace
+ [0x027E8] = 0x68, -- <, langle
+ [0x027E9] = 0x69, -- >, rangle
+ [0x0007C] = 0x6A, -- |, mid, lvert, rvert
+ [0x02225] = 0x6B, -- parallel
+ -- [0x0 ] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert
+ [0x02195] = 0x6C, -- updownarrow
+ [0x021D5] = 0x6D, -- Updownarrow
+ [0x0005C] = 0x6E, -- \, backslash, setminus
+ [0x02216] = 0x6E, -- setminus
+ [0x02240] = 0x6F, -- wr
+ [0x0221A] = 0x70, -- sqrt. AM: Check surd??
+ [0x02A3F] = 0x71, -- amalg
+ [0x1D6FB] = 0x72, -- nabla
+-- [0x0222B] = 0x73, -- smallint (TODO: what about intop?)
+ [0x02294] = 0x74, -- sqcup
+ [0x02293] = 0x75, -- sqcap
+ [0x02291] = 0x76, -- sqsubseteq
+ [0x02292] = 0x77, -- sqsupseteq
+ [0x000A7] = 0x78, -- S
+ [0x02020] = 0x79, -- dagger, dag
+ [0x02021] = 0x7A, -- ddagger, ddag
+ [0x000B6] = 0x7B, -- P
+ [0x02663] = 0x7C, -- clubsuit
+ [0x02662] = 0x7D, -- diamondsuit
+ [0x02661] = 0x7E, -- heartsuit
+ [0x02660] = 0x7F, -- spadesuit
+ [0xFE321] = 0x37, -- mapstochar
+
+ [0xFE325] = 0x30, -- prime 0x02032
+}
+
+-- The names in masm10.enc can be trusted best and are shown in the first
+-- column, while in the second column we show the tex/ams names. As usual
+-- it costs hours to figure out such a table.
+
+mathencodings["tex-ma"] = {
+ [0x022A1] = 0x00, -- squaredot \boxdot
+ [0x0229E] = 0x01, -- squareplus \boxplus
+ [0x022A0] = 0x02, -- squaremultiply \boxtimes
+ [0x025A1] = 0x03, -- square \square \Box
+ [0x025A0] = 0x04, -- squaresolid \blacksquare
+ [0x025AA] = 0x05, -- squaresmallsolid \centerdot
+ [0x022C4] = 0x06, -- diamond \Diamond \lozenge
+ [0x02666] = 0x07, -- diamondsolid \blacklozenge
+ [0x021BB] = 0x08, -- clockwise \circlearrowright
+ [0x021BA] = 0x09, -- anticlockwise \circlearrowleft
+ [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons
+ [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons
+ [0x0229F] = 0x0C, -- squareminus \boxminus
+ [0x022A9] = 0x0D, -- forces \Vdash
+ [0x022AA] = 0x0E, -- forcesbar \Vvdash
+ [0x022A8] = 0x0F, -- satisfies \vDash
+ [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow
+ [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow
+ [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows
+ [0x021C9] = 0x13, -- dblarrowright \rightrightarrows
+ [0x021C8] = 0x14, -- dblarrowup \upuparrows
+ [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows
+ [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction
+ [0x021C2] = 0x17, -- harpoondownright \downharpoonright
+ [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft
+ [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft
+ [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail
+ [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail
+ [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows
+-- [0x021C5] = 0x00, -- \updownarrows (missing in lm)
+ [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows
+ [0x021B0] = 0x1E, -- shiftleft \Lsh
+ [0x021B1] = 0x1F, -- shiftright \Rsh
+ [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow
+ [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow
+ [0x021AB] = 0x22, -- curlyleft \looparrowleft
+ [0x021AC] = 0x23, -- curlyright \looparrowright
+ [0x02257] = 0x24, -- circleequal \circeq
+ [0x0227F] = 0x25, -- followsorequal \succsim
+ [0x02273] = 0x26, -- greaterorsimilar \gtrsim
+ [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox
+ [0x022B8] = 0x28, -- multimap \multimap
+ [0x02234] = 0x29, -- therefore \therefore
+ [0x02235] = 0x2A, -- because \because
+ [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot
+ [0x0225C] = 0x2C, -- defines \triangleq
+ [0x0227E] = 0x2D, -- precedesorequal \precsim
+ [0x02272] = 0x2E, -- lessorsimilar \lesssim
+ [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox
+ [0x02A95] = 0x30, -- equalorless \eqslantless
+ [0x02A96] = 0x31, -- equalorgreater \eqslantgtr
+ [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec
+ [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc
+ [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq
+ [0x02266] = 0x35, -- lessdblequal \leqq
+ [0x02A7D] = 0x36, -- lessorequalslant \leqslant
+ [0x02276] = 0x37, -- lessorgreater \lessgtr
+ [0x02035] = 0x38, -- primereverse \backprime
+ -- [0x0] = 0x39, -- axisshort \dabar
+ [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq
+ [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq
+ [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq
+ [0x02267] = 0x3D, -- greaterdblequal \geqq
+ [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant
+ [0x02277] = 0x3F, -- greaterorless \gtrless
+ [0x0228F] = 0x40, -- squareimage \sqsubset
+ [0x02290] = 0x41, -- squareoriginal \sqsupset
+ -- wrong: see **
+ -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
+ -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
+ -- cf lm
+ [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq
+ [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq
+ --
+ [0x02605] = 0x46, -- star \bigstar
+ [0x0226C] = 0x47, -- between \between
+ [0x025BC] = 0x48, -- triangledownsld \blacktriangledown
+ [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright
+ [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft
+ -- [0x0] = 0x4B, -- arrowaxisright
+ -- [0x0] = 0x4C, -- arrowaxisleft
+ [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle
+ [0x025B2] = 0x4E, -- trianglesolid \blacktriangle
+ [0x025BD] = 0x4F, -- triangleinv \triangledown
+ [0x02256] = 0x50, -- ringinequal \eqcirc
+ [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr
+ [0x022DB] = 0x52, -- greaterlessequal \gtreqless
+ [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr
+ [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless
+ [0x000A5] = 0x55, -- Yen \yen
+ [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow
+ [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow
+ [0x02713] = 0x58, -- check \checkmark
+ [0x022BB] = 0x59, -- orunderscore \veebar
+ [0x022BC] = 0x5A, -- nand \barwedge
+ [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge
+ [0x02220] = 0x5C, -- angle \angle
+ [0x02221] = 0x5D, -- measuredangle \measuredangle
+ [0x02222] = 0x5E, -- sphericalangle \sphericalangle
+ -- [0x0] = 0x5F, -- proportional \varpropto
+ -- [0x0] = 0x60, -- smile \smallsmile
+ -- [0x0] = 0x61, -- frown \smallfrown
+ [0x022D0] = 0x62, -- subsetdbl \Subset
+ [0x022D1] = 0x63, -- supersetdbl \Supset
+ [0x022D3] = 0x64, -- uniondbl \doublecup \Cup
+ [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap
+ [0x022CF] = 0x66, -- uprise \curlywedge
+ [0x022CE] = 0x67, -- downfall \curlyvee
+ [0x022CB] = 0x68, -- multiopenleft \leftthreetimes
+ [0x022CC] = 0x69, -- multiopenright \rightthreetimes
+ [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq
+ [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq
+ [0x0224F] = 0x6C, -- difference \bumpeq
+ [0x0224E] = 0x6D, -- geomequivalent \Bumpeq
+ [0x022D8] = 0x6E, -- muchless \lll \llless
+ [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr
+ [0x0231C] = 0x70, -- rightanglenw \ulcorner
+ [0x0231D] = 0x71, -- rightanglene \urcorner
+ [0x024C7] = 0x72, -- circleR \circledR
+ [0x024C8] = 0x73, -- circleS \circledS
+ [0x022D4] = 0x74, -- fork \pitchfork
+ [0x02214] = 0x75, -- dotplus \dotplus
+ [0x0223D] = 0x76, -- revsimilar \backsim
+ [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq.
+ [0x0231E] = 0x78, -- rightanglesw \llcorner
+ [0x0231F] = 0x79, -- rightanglese \lrcorner
+ [0x02720] = 0x7A, -- maltesecross \maltese
+ [0x02201] = 0x7B, -- complement \complement
+ [0x022BA] = 0x7C, -- intercal \intercal
+ [0x0229A] = 0x7D, -- circlering \circledcirc
+ [0x0229B] = 0x7E, -- circleasterisk \circledast
+ [0x0229D] = 0x7F, -- circleminus \circleddash
+}
+
+mathencodings["tex-mb"] = {
+ -- [0x0] = 0x00, -- lessornotequal \lvertneqq
+ -- [0x0] = 0x01, -- greaterornotequal \gvertneqq
+ [0x02270] = 0x02, -- notlessequal \nleq
+ [0x02271] = 0x03, -- notgreaterequal \ngeq
+ [0x0226E] = 0x04, -- notless \nless
+ [0x0226F] = 0x05, -- notgreater \ngtr
+ [0x02280] = 0x06, -- notprecedes \nprec
+ [0x02281] = 0x07, -- notfollows \nsucc
+ [0x02268] = 0x08, -- lessornotdbleql \lneqq
+ [0x02269] = 0x09, -- greaterornotdbleql \gneqq
+ -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant
+ -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant
+ [0x02A87] = 0x0C, -- lessnotequal \lneq
+ [0x02A88] = 0x0D, -- greaternotequal \gneq
+ -- [0x0] = 0x0E, -- notprecedesoreql \npreceq
+ -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq
+ [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim
+ [0x022E9] = 0x11, -- followornoteqvlnt \succnsim
+ [0x022E6] = 0x12, -- lessornotsimilar \lnsim
+ [0x022E7] = 0x13, -- greaterornotsimilar \gnsim
+ -- [0x0] = 0x14, -- notlessdblequal \nleqq
+ -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq
+ [0x02AB5] = 0x16, -- precedenotslnteql \precneqq
+ [0x02AB6] = 0x17, -- follownotslnteql \succneqq
+ [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox
+ [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox
+ [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox
+ [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox
+ [0x02241] = 0x1C, -- notsimilar \nsim
+ [0x02247] = 0x1D, -- notapproxequal \ncong
+ -- [0x0] = 0x1E, -- upslope \diagup
+ -- [0x0] = 0x1F, -- downslope \diagdown
+ -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq
+ -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq
+ -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq
+ -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq
+ [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq
+ [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq
+ -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq
+ -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq
+ [0x0228A] = 0x28, -- subsetnoteql \subsetneq
+ [0x0228B] = 0x29, -- supersetnoteql \supsetneq
+ [0x02288] = 0x2A, -- notsubseteql \nsubseteq
+ [0x02289] = 0x2B, -- notsuperseteql \nsupseteq
+ [0x02226] = 0x2C, -- notparallel \nparallel
+ [0x02224] = 0x2D, -- notbar \nmid \ndivides
+ -- [0x0] = 0x2E, -- notshortbar \nshortmid
+ -- [0x0] = 0x2F, -- notshortparallel \nshortparallel
+ [0x022AC] = 0x30, -- notturnstile \nvdash
+ [0x022AE] = 0x31, -- notforces \nVdash
+ [0x022AD] = 0x32, -- notsatisfies \nvDash
+ [0x022AF] = 0x33, -- notforcesextra \nVDash
+ [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq
+ [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq
+ [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft
+ [0x022EB] = 0x37, -- nottriangleright \ntriangleright
+ [0x0219A] = 0x38, -- notarrowleft \nleftarrow
+ [0x0219B] = 0x39, -- notarrowright \nrightarrow
+ [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow
+ [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow
+ [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow
+ [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow
+ [0x022C7] = 0x3E, -- dividemultiply \divideontimes
+ [0x02300] = 0x3F, -- diametersign \varnothing
+ [0x02204] = 0x40, -- notexistential \nexists
+ [0x1D538] = 0x41, -- A (blackboard A)
+ [0x1D539] = 0x42, -- B
+ [0x02102] = 0x43, -- C
+ [0x1D53B] = 0x44, -- D
+ [0x1D53C] = 0x45, -- E
+ [0x1D53D] = 0x46, -- F
+ [0x1D53E] = 0x47, -- G
+ [0x0210D] = 0x48, -- H
+ [0x1D540] = 0x49, -- I
+ [0x1D541] = 0x4A, -- J
+ [0x1D542] = 0x4B, -- K
+ [0x1D543] = 0x4C, -- L
+ [0x1D544] = 0x4D, -- M
+ [0x02115] = 0x4E, -- N
+ [0x1D546] = 0x4F, -- O
+ [0x02119] = 0x50, -- P
+ [0x0211A] = 0x51, -- Q
+ [0x0211D] = 0x52, -- R
+ [0x1D54A] = 0x53, -- S
+ [0x1D54B] = 0x54, -- T
+ [0x1D54C] = 0x55, -- U
+ [0x1D54D] = 0x56, -- V
+ [0x1D54E] = 0x57, -- W
+ [0x1D54F] = 0x58, -- X
+ [0x1D550] = 0x59, -- Y
+ [0x02124] = 0x5A, -- Z (blackboard Z)
+ [0x02132] = 0x60, -- finv \Finv
+ [0x02141] = 0x61, -- fmir \Game
+ -- [0x0] = 0x62, tildewide
+ -- [0x0] = 0x63, tildewider
+ -- [0x0] = 0x64, Finv
+ -- [0x0] = 0x65, Gmir
+ [0x02127] = 0x66, -- Omegainv \mho
+ [0x000F0] = 0x67, -- eth \eth
+ [0x02242] = 0x68, -- equalorsimilar \eqsim
+ [0x02136] = 0x69, -- beth \beth
+ [0x02137] = 0x6A, -- gimel \gimel
+ [0x02138] = 0x6B, -- daleth \daleth
+ [0x022D6] = 0x6C, -- lessdot \lessdot
+ [0x022D7] = 0x6D, -- greaterdot \gtrdot
+ [0x022C9] = 0x6E, -- multicloseleft \ltimes
+ [0x022CA] = 0x6F, -- multicloseright \rtimes
+ -- [0x0] = 0x70, -- barshort \shortmid
+ -- [0x0] = 0x71, -- parallelshort \shortparallel
+ -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy
+ -- [0x0] = 0x73, -- similar \thicksim
+ -- [0x0] = 0x74, -- approxequal \thickapprox
+ [0x0224A] = 0x75, -- approxorequal \approxeq
+ [0x02AB8] = 0x76, -- followsorequal \succapprox
+ [0x02AB7] = 0x77, -- precedesorequal \precapprox
+ [0x021B6] = 0x78, -- archleftdown \curvearrowleft
+ [0x021B7] = 0x79, -- archrightdown \curvearrowright
+ [0x003DC] = 0x7A, -- Digamma \digamma
+ [0x003F0] = 0x7B, -- kappa \varkappa
+ [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k)
+ [0x0210F] = 0x7D, -- planckover2pi \hslash % 0x7D
+ [0x00127] = 0x7E, -- planckover2pi1 \hbar % 0x7E
+ [0x003F6] = 0x7F, -- epsiloninv \backepsilon
+}
+
+mathencodings["tex-mc"] = {
+ -- this file has no tfm so it gets mapped in the private space
+ [0xFE324] = "mapsfromchar",
+}
+
+mathencodings["tex-fraktur"] = {
+-- [0x1D504] = 0x41, -- A (fraktur A)
+-- [0x1D505] = 0x42, -- B
+ [0x0212D] = 0x43, -- C
+-- [0x1D507] = 0x44, -- D
+-- [0x1D508] = 0x45, -- E
+-- [0x1D509] = 0x46, -- F
+-- [0x1D50A] = 0x47, -- G
+ [0x0210C] = 0x48, -- H
+ [0x02111] = 0x49, -- I
+-- [0x1D50D] = 0x4A, -- J
+-- [0x1D50E] = 0x4B, -- K
+-- [0x1D50F] = 0x4C, -- L
+-- [0x1D510] = 0x4D, -- M
+-- [0x1D511] = 0x4E, -- N
+-- [0x1D512] = 0x4F, -- O
+-- [0x1D513] = 0x50, -- P
+-- [0x1D514] = 0x51, -- Q
+ [0x0211C] = 0x52, -- R
+-- [0x1D516] = 0x53, -- S
+-- [0x1D517] = 0x54, -- T
+-- [0x1D518] = 0x55, -- U
+-- [0x1D519] = 0x56, -- V
+-- [0x1D51A] = 0x57, -- W
+-- [0x1D51B] = 0x58, -- X
+-- [0x1D51C] = 0x59, -- Y
+ [0x02128] = 0x5A, -- Z (fraktur Z)
+-- [0x1D51E] = 0x61, -- a (fraktur a)
+-- [0x1D51F] = 0x62, -- b
+-- [0x1D520] = 0x63, -- c
+-- [0x1D521] = 0x64, -- d
+-- [0x1D522] = 0x65, -- e
+-- [0x1D523] = 0x66, -- f
+-- [0x1D524] = 0x67, -- g
+-- [0x1D525] = 0x68, -- h
+-- [0x1D526] = 0x69, -- i
+-- [0x1D527] = 0x6A, -- j
+-- [0x1D528] = 0x6B, -- k
+-- [0x1D529] = 0x6C, -- l
+-- [0x1D52A] = 0x6D, -- m
+-- [0x1D52B] = 0x6E, -- n
+-- [0x1D52C] = 0x6F, -- o
+-- [0x1D52D] = 0x70, -- p
+-- [0x1D52E] = 0x71, -- q
+-- [0x1D52F] = 0x72, -- r
+-- [0x1D530] = 0x73, -- s
+-- [0x1D531] = 0x74, -- t
+-- [0x1D532] = 0x75, -- u
+-- [0x1D533] = 0x76, -- v
+-- [0x1D534] = 0x77, -- w
+-- [0x1D535] = 0x78, -- x
+-- [0x1D536] = 0x79, -- y
+-- [0x1D537] = 0x7A, -- z
+}
+
+-- now that all other vectors are defined ...
+
+setletters(mathencodings, "tex-it", 0x1D434, 0x1D44E)
+setletters(mathencodings, "tex-ss", 0x1D5A0, 0x1D5BA)
+setletters(mathencodings, "tex-tt", 0x1D670, 0x1D68A)
+setletters(mathencodings, "tex-bf", 0x1D400, 0x1D41A)
+setletters(mathencodings, "tex-bi", 0x1D468, 0x1D482)
+setletters(mathencodings, "tex-fraktur", 0x1D504, 0x1D51E)
+setletters(mathencodings, "tex-fraktur-bold", 0x1D56C, 0x1D586)
+
+setdigits (mathencodings, "tex-ss", 0x1D7E2)
+setdigits (mathencodings, "tex-tt", 0x1D7F6)
+setdigits (mathencodings, "tex-bf", 0x1D7CE)
+
+-- setdigits (mathencodings, "tex-bi", 0x1D7CE)
+
+-- todo: add ss, tt, bf etc vectors
+-- todo: we can make ss tt etc an option
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua b/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua
new file mode 100644
index 00000000000..a683e02cfdc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua
@@ -0,0 +1,1107 @@
+if not modules then modules = { } end modules ['math-vfu'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- All these math vectors .. thanks to Aditya and Mojca they become
+-- better and better. If you have problems with math fonts or miss
+-- characters report it to the ConTeXt mailing list. Also thanks to
+-- Boguslaw for finding a couple of errors.
+--
+-- This mechanism will stay around. Even when we've switched to the
+-- real fonts, one can still say:
+--
+-- \enablemode[lmmath,pxmath,txmath]
+--
+-- to get the virtual counterparts. There are still areas where the
+-- virtuals are better.
+
+-- 20D6 -> 2190
+-- 20D7 -> 2192
+
+local type, next = type, next
+local max = math.max
+local format = string.format
+local utfchar = utf.char
+local fastcopy = table.copy
+
+local fonts, nodes, mathematics = fonts, nodes, mathematics
+
+local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
+local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end)
+
+local add_optional = false directives.register("math.virtual.optional",function(v) add_optional = v end)
+
+local report_virtual = logs.reporter("fonts","virtual math")
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local chardata = characters.data
+
+local mathencodings = allocate()
+fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vectors
+local vfmath = allocate()
+fonts.handlers.vf.math = vfmath
+
+local shared = { }
+
+-- local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 }
+--
+-- local function negate(main,characters,id,size,unicode,basecode)
+-- if not characters[unicode] then
+-- local basechar = characters[basecode]
+-- if basechar then
+-- local ht, wd = basechar.height, basechar.width
+-- characters[unicode] = {
+-- width = wd,
+-- height = ht,
+-- depth = basechar.depth,
+-- italic = basechar.italic,
+-- kerns = basechar.kerns,
+-- commands = {
+-- { "slot", 1, basecode },
+-- push,
+-- { "down", ht/5},
+-- { "right", - wd/2},
+-- back,
+-- push,
+-- }
+-- }
+-- end
+-- end
+-- end
+--
+-- \Umathchardef\braceld="0 "1 "FF07A
+-- \Umathchardef\bracerd="0 "1 "FF07B
+-- \Umathchardef\bracelu="0 "1 "FF07C
+-- \Umathchardef\braceru="0 "1 "FF07D
+
+local function brace(main,characters,id,size,unicode,first,rule,left,right,rule,last)
+ if not characters[unicode] then
+ characters[unicode] = {
+ horiz_variants = {
+ { extender = 0, glyph = first },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = left },
+ { extender = 0, glyph = right },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = last },
+ }
+ }
+ end
+end
+
+local function extension(main,characters,id,size,unicode,first,middle,last)
+ local chr = characters[unicode]
+ if not chr then
+ return -- skip
+ end
+ local fw = characters[first]
+ if not fw then
+ return
+ end
+ local mw = characters[middle]
+ if not mw then
+ return
+ end
+ local lw = characters[last]
+ if not lw then
+ return
+ end
+ fw = fw.width
+ mw = mw.width
+ lw = lw.width
+ if fw == 0 then
+ fw = 1
+ end
+ if lw == 0 then
+ lw = 1
+ end
+ chr.horiz_variants = {
+ { extender = 0, glyph = first, ["end"] = fw/2, start = 0, advance = fw },
+ { extender = 1, glyph = middle, ["end"] = mw/2, start = mw/2, advance = mw },
+ { extender = 0, glyph = last, ["end"] = 0, start = lw/2, advance = lw },
+ }
+end
+
+local function parent(main,characters,id,size,unicode,first,rule,last)
+ if not characters[unicode] then
+ characters[unicode] = {
+ horiz_variants = {
+ { extender = 0, glyph = first },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = last },
+ }
+ }
+ end
+end
+
+local push, pop, step = { "push" }, { "pop" }, 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]
+ 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 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
+ if not characters[uprule] then
+ 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
+ if not characters[dnrule] then
+ 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 } }
+ 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 width = minus.width
+ if width > step then
+ width = width - step
+ step = step / 2
+ else
+ width = width / 2
+ step = width
+ end
+ characters[unicode] = {
+ width = width,
+ height = minus.height,
+ depth = minus.depth,
+ commands = { push, { "right", -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 slot = { "slot", id_of_smaller, private }
+ local commands = {
+ push,
+ { "down", - up },
+ slot,
+ }
+ for i=2,n do
+ commands[#commands+1] = slot
+ end
+ commands[#commands+1] = pop
+ characters[unicode] = {
+ width = n * raised.width,
+ height = (raised.height or 0) + up,
+ depth = (raised.depth or 0) - up,
+ italic = raised.italic,
+ commands = commands,
+ }
+ end
+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 }
+ 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 }
+ characters[unicode] = {
+ width = 3*w + 2*3*mu, height = h, depth = d,
+ 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 }
+ }
+ elseif unicode == 0x22F1 then
+ characters[unicode] = {
+ 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,
+ pop
+ }
+ }
+ elseif unicode == 0x22F0 then
+ characters[unicode] = {
+ 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,
+ pop
+ }
+ }
+ else
+ characters[unicode] = {
+ width = 3*w + 2*3*mu, height = h, depth = d,
+ commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ }
+ end
+ end
+end
+
+local function vertbar(main,characters,id,size,parent,scale,unicode)
+ local cp = characters[parent]
+ if cp then
+ local sc = scale * size
+ local pc = { "slot", id, parent }
+ characters[unicode] = {
+ width = cp.width,
+ height = cp.height + sc,
+ depth = cp.depth + sc,
+ commands = {
+ push, { "down", -sc }, pc, pop,
+ push, { "down", 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]
+ if c1 and c2 then
+ local w1, w2 = c1.width, c2.width
+ local mu = size/18
+ characters[unicode] = {
+ width = w1 + w2 - d12 * mu,
+ height = max(c1.height or 0, c2.height or 0),
+ depth = max(c1.depth or 0, c2.depth or 0),
+ commands = {
+ { "slot", id, u1 },
+ { "right", -d12*mu } ,
+ { "slot", id, u2 },
+ },
+ }
+ end
+end
+
+local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3)
+ local c1, c2, c3 = characters[u1], characters[u2], characters[u3]
+ if c1 and c2 and c3 then
+ local w1, w2, w3 = c1.width, c2.width, 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),
+ commands = {
+ { "slot", id, u1 },
+ { "right", - d12*mu } ,
+ { "slot", id, u2 },
+ { "right", - d23*mu },
+ { "slot", id, u3 },
+ }
+ }
+ end
+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 },
+ }
+ }
+ end
+end
+
+local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- math-fbk.lua
+ local c = characters[u]
+ 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 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)
+ next = private
+ end
+ characters[unicode] = {
+ width = width + (n-1)*(width-italic),
+ height = c.height,
+ depth = c.depth,
+ italic = italic,
+ commands = commands,
+ next = next,
+ }
+ end
+end
+
+local function cloned(main,characters,id,size,source,target)
+ local data = characters[source]
+ if data then
+ characters[target] = data
+ return true
+ end
+end
+
+-- we use the fact that context defines the smallest sizes first .. a real dirty and ugly hack
+
+local data_of_smaller = nil
+local size_of_smaller = 0
+
+function vfmath.addmissing(main,id,size)
+
+ local id_of_smaller = nil
+
+ if size < size_of_smaller or size_of_smaller == 0 then
+ data_of_smaller = main.fonts[id]
+ id_of_smaller = id
+ else
+ id_of_smaller = #main.fonts + 1
+ main.fonts[id_of_smaller] = data_of_smaller
+ end
+
+ -- here id is the index in fonts (normally 14 or so) and that slot points to self
+
+ local characters = main.characters
+ local shared = main.shared
+ local variables = main.goodies.mathematics and main.goodies.mathematics.variables or { }
+ local joinrelfactor = variables.joinrelfactor or 3
+
+ for i=0x7A,0x7D do
+ make(main,characters,id,size,i,1)
+ end
+
+ brace (main,characters,id,size,0x23DE,0xFF17A,0xFF301,0xFF17D,0xFF17C,0xFF301,0xFF17B)
+ brace (main,characters,id,size,0x23DF,0xFF27C,0xFF401,0xFF27B,0xFF27A,0xFF401,0xFF27D)
+
+ parent (main,characters,id,size,0x23DC,0xFF17A,0xFF301,0xFF17B)
+ parent (main,characters,id,size,0x23DD,0xFF27C,0xFF401,0xFF27D)
+
+ -- negate (main,characters,id,size,0x2260,0x003D)
+ dots (main,characters,id,size,0x2026) -- ldots
+ dots (main,characters,id,size,0x22EE) -- vdots
+ dots (main,characters,id,size,0x22EF) -- cdots
+ dots (main,characters,id,size,0x22F1) -- ddots
+ dots (main,characters,id,size,0x22F0) -- udots
+
+ vertbar (main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize
+ vertbar (main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize
+ vertbar (main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize
+ vertbar (main,characters,id,size,0xFF603,0.30,0xFF604) -- Bigg : 1.75 bodyfontsize
+ vertbar (main,characters,id,size,0x02016,0.10,0xFF605)
+ vertbar (main,characters,id,size,0xFF605,0.30,0xFF606)
+ vertbar (main,characters,id,size,0xFF606,0.30,0xFF607)
+ vertbar (main,characters,id,size,0xFF607,0.30,0xFF608)
+
+ clipped (main,characters,id,size,0xFF501,0x0002D) -- minus
+ clipped (main,characters,id,size,0xFF502,0x02190) -- lefthead
+ clipped (main,characters,id,size,0xFF503,0x02192) -- righthead
+ clipped (main,characters,id,size,0xFF504,0xFE321) -- mapsto
+ clipped (main,characters,id,size,0xFF505,0xFE322) -- lhook
+ clipped (main,characters,id,size,0xFF506,0xFE323) -- rhook
+ clipped (main,characters,id,size,0xFF507,0xFE324) -- mapsfrom
+ clipped (main,characters,id,size,0xFF508,0x021D0) -- double lefthead
+ clipped (main,characters,id,size,0xFF509,0x021D2) -- double righthead
+ clipped (main,characters,id,size,0xFF50A,0x0003D) -- equal
+ clipped (main,characters,id,size,0xFF50B,0x0219E) -- lefttwohead
+ clipped (main,characters,id,size,0xFF50C,0x021A0) -- righttwohead
+ clipped (main,characters,id,size,0xFF50D,0xFF350) -- lr arrow combi snippet
+ clipped (main,characters,id,size,0xFF50E,0xFF351) -- lr arrow combi snippet
+ clipped (main,characters,id,size,0xFF50F,0xFF352) -- lr arrow combi snippet
+ clipped (main,characters,id,size,0xFF510,0x02261) -- equiv
+
+ extension(main,characters,id,size,0x2190,0xFF502,0xFF501,0xFF501) -- \leftarrow
+ extension(main,characters,id,size,0x2192,0xFF501,0xFF501,0xFF503) -- \rightarrow
+
+ extension(main,characters,id,size,0x002D,0xFF501,0xFF501,0xFF501) -- \rel
+ extension(main,characters,id,size,0x003D,0xFF50A,0xFF50A,0xFF50A) -- \equal
+ extension(main,characters,id,size,0x2261,0xFF510,0xFF510,0xFF510) -- \equiv
+
+ jointwo (main,characters,id,size,0x21A6,0xFE321,0,0x02192) -- \mapstochar\rightarrow
+ jointwo (main,characters,id,size,0x21A9,0x02190,joinrelfactor,0xFE323) -- \leftarrow\joinrel\rhook
+ jointwo (main,characters,id,size,0x21AA,0xFE322,joinrelfactor,0x02192) -- \lhook\joinrel\rightarrow
+ jointwo (main,characters,id,size,0x27F5,0x02190,joinrelfactor,0x0002D) -- \leftarrow\joinrel\relbar
+ jointwo (main,characters,id,size,0x27F6,0x0002D,joinrelfactor,0x02192,2) -- \relbar\joinrel\rightarrow
+ jointwo (main,characters,id,size,0x27F7,0x02190,joinrelfactor,0x02192) -- \leftarrow\joinrel\rightarrow
+ jointwo (main,characters,id,size,0x27F8,0x021D0,joinrelfactor,0x0003D) -- \Leftarrow\joinrel\Relbar
+ jointwo (main,characters,id,size,0x27F9,0x0003D,joinrelfactor,0x021D2) -- \Relbar\joinrel\Rightarrow
+ jointwo (main,characters,id,size,0x27FA,0x021D0,joinrelfactor,0x021D2) -- \Leftarrow\joinrel\Rightarrow
+ jointhree(main,characters,id,size,0x27FB,0x02190,joinrelfactor,0x0002D,0,0xFE324) -- \leftarrow\joinrel\relbar\mapsfromchar
+ jointhree(main,characters,id,size,0x27FC,0xFE321,0,0x0002D,joinrelfactor,0x02192) -- \mapstochar\relbar\joinrel\rightarrow
+
+ extension(main,characters,id,size,0x21A6,0xFF504,0xFF501,0xFF503) -- \mapstochar\rightarrow
+ extension(main,characters,id,size,0x21A9,0xFF502,0xFF501,0xFF506) -- \leftarrow\joinrel\rhook
+ extension(main,characters,id,size,0x21AA,0xFF505,0xFF501,0xFF503) -- \lhook\joinrel\rightarrow
+ extension(main,characters,id,size,0x27F5,0xFF502,0xFF501,0xFF501) -- \leftarrow\joinrel\relbar
+ extension(main,characters,id,size,0x27F6,0xFF501,0xFF501,0xFF503) -- \relbar\joinrel\rightarrow
+ extension(main,characters,id,size,0x27F7,0xFF502,0xFF501,0xFF503) -- \leftarrow\joinrel\rightarrow
+ extension(main,characters,id,size,0x27F8,0xFF508,0xFF50A,0xFF50A) -- \Leftarrow\joinrel\Relbar
+ extension(main,characters,id,size,0x27F9,0xFF50A,0xFF50A,0xFF509) -- \Relbar\joinrel\Rightarrow
+ extension(main,characters,id,size,0x27FA,0xFF508,0xFF50A,0xFF509) -- \Leftarrow\joinrel\Rightarrow
+ extension(main,characters,id,size,0x27FB,0xFF502,0xFF501,0xFF507) -- \leftarrow\joinrel\relbar\mapsfromchar
+ extension(main,characters,id,size,0x27FC,0xFF504,0xFF501,0xFF503) -- \mapstochar\relbar\joinrel\rightarrow
+
+ extension(main,characters,id,size,0x219E,0xFF50B,0xFF501,0xFF501) -- \twoheadleftarrow\joinrel\relbar
+ extension(main,characters,id,size,0x21A0,0xFF501,0xFF501,0xFF50C) -- \relbar\joinrel\twoheadrightarrow
+ extension(main,characters,id,size,0x21C4,0xFF50D,0xFF50E,0xFF50F) -- leftoverright
+
+ -- 21CB leftrightharpoon
+ -- 21CC rightleftharpoon
+
+ stack(main,characters,id,size,0x2259,0x0003D,3,0x02227) -- \buildrel\wedge\over=
+
+ jointwo(main,characters,id,size,0x22C8,0x022B3,joinrelfactor,0x022B2) -- \mathrel\triangleright\joinrel\mathrel\triangleleft (4 looks better than 3)
+ jointwo(main,characters,id,size,0x22A7,0x0007C,joinrelfactor,0x0003D) -- \mathrel|\joinrel=
+ jointwo(main,characters,id,size,0x2260,0x00338,0,0x0003D) -- \not\equal
+ jointwo(main,characters,id,size,0x2284,0x00338,0,0x02282) -- \not\subset
+ jointwo(main,characters,id,size,0x2285,0x00338,0,0x02283) -- \not\supset
+ jointwo(main,characters,id,size,0x2209,0x00338,0,0x02208) -- \not\in
+ jointwo(main,characters,id,size,0x2254,0x03A,0,0x03D) -- := (≔)
+
+ repeated(main,characters,id,size,0x222C,0x222B,2,0xFF800,1/3)
+ repeated(main,characters,id,size,0x222D,0x222B,3,0xFF810,1/3)
+
+ if cloned(main,characters,id,size,0x2032,0xFE325) then
+ raise(main,characters,id,size,0x2032,0xFE325,1,id_of_smaller) -- prime
+ raise(main,characters,id,size,0x2033,0xFE325,2,id_of_smaller) -- double prime
+ raise(main,characters,id,size,0x2034,0xFE325,3,id_of_smaller) -- triple prime
+ end
+
+ -- there are more (needs discussion first):
+
+ -- characters[0x20D6] = characters[0x2190]
+ -- characters[0x20D7] = characters[0x2192]
+
+ characters[0x02B9] = characters[0x2032] -- we're nice
+
+ data_of_smaller = main.fonts[id]
+ size_of_smaller = size
+
+end
+
+local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage
+
+local reported = { }
+local reverse = { } -- index -> unicode
+
+setmetatableindex(reverse, function(t,name)
+ if trace_virtual then
+ report_virtual("initializing math vector %a",name)
+ end
+ local m, r = mathencodings[name], { }
+ for u, i in next, m do
+ r[i] = u
+ end
+ reverse[name] = r
+ return r
+end)
+
+local function copy_glyph(main,target,original,unicode,slot)
+ local addprivate = fonts.helpers.addprivate
+ local olddata = original[unicode]
+ if olddata then
+ local newdata = {
+ width = olddata.width,
+ height = olddata.height,
+ depth = olddata.depth,
+ italic = olddata.italic,
+ kerns = olddata.kerns,
+ commands = { { "slot", slot, unicode } },
+ }
+ local glyphdata = newdata
+ local nextglyph = olddata.next
+ while nextglyph do
+ local oldnextdata = original[nextglyph]
+ local newnextdata = {
+ commands = { { "slot", slot, nextglyph } },
+ width = oldnextdata.width,
+ height = oldnextdata.height,
+ depth = oldnextdata.depth,
+ }
+ 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
+ else
+ olddata = oldnextdata
+ newdata = newnextdata
+ nextglyph = nextnextglyph
+ end
+ end
+ local hv = olddata.horiz_variants
+ if hv then
+ hv = fastcopy(hv)
+ newdata.horiz_variants = hv
+ for i=1,#hv do
+ local hvi = hv[i]
+ local oldglyph = hvi.glyph
+ local olddata = original[oldglyph]
+ local newdata = {
+ commands = { { "slot", slot, oldglyph } },
+ width = olddata.width,
+ height = olddata.height,
+ depth = olddata.depth,
+ }
+ 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
+ if vv then
+ vv = fastcopy(vv)
+ newdata.vert_variants = vv
+ for i=1,#vv do
+ local vvi = vv[i]
+ local oldglyph = vvi.glyph
+ local olddata = original[oldglyph]
+ local newdata = {
+ commands = { { "slot", slot, oldglyph } },
+ width = olddata.width,
+ height = olddata.height,
+ depth = olddata.depth,
+ }
+ 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
+ end
+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
+ for s=1,#set do
+ local ss = set[s]
+ local ssname = ss.name
+ if add_optional and ss.optional then
+ if trace_virtual then
+ report_virtual("loading font %a subfont %s with name %a at %p is skipped",name,s,ssname,size)
+ end
+ else
+ if ss.features then
+ ssname = ssname .. "*" .. ss.features
+ end
+ if ss.main then
+ main = s
+ end
+ local alreadyloaded = names[ssname] -- for px we load one twice (saves .04 sec)
+ local f, id
+ if alreadyloaded then
+ f, id = alreadyloaded.f, alreadyloaded.id
+ if trace_virtual then
+ report_virtual("loading font %a subfont %s with name %a is reused",name,s,ssname)
+ end
+ else
+ f, id = fonts.constructors.readanddefine(ssname,size)
+ names[ssname] = { f = f, id = id }
+ end
+ if not f or id == 0 then
+ report_virtual("loading font %a subfont %s with name %a at %p is skipped, not found",name,s,ssname,size)
+ else
+ n = n + 1
+ okset[n] = ss
+ loaded[n] = f
+ fontlist[n] = { id = id, size = size }
+ if not shared[s] then
+ shared[n] = { }
+ end
+ if trace_virtual then
+ report_virtual("loading font %a subfont %s with name %a at %p as id %s using encoding %a",name,s,ssname,size,id,ss.vector)
+ end
+ if not ss.checked then
+ ss.checked = true
+ local vector = mathencodings[ss.vector]
+ if vector then
+ -- we resolve named glyphs only once as we can assume that vectors
+ -- are unique to a font set (when we read an afm we get those names
+ -- mapped onto the private area)
+ for unicode, index in next, vector do
+ if not tonumber(index) then
+ local u = f.unicodes
+ u = u and u[index]
+ if u then
+ if trace_virtual then
+ report_virtual("resolving name %a to %s",index,u) -- maybe more detail for u
+ end
+ else
+ report_virtual("unable to resolve name %a",index)
+ end
+ vector[unicode] = u
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- beware, loaded[1] is already passed to tex (we need to make a simple copy then .. todo)
+ local parent = loaded[1] or { } -- a text font
+ local characters = { }
+ local parameters = { }
+ local mathparameters = { }
+ local descriptions = { }
+ local metadata = { }
+ local properties = { }
+ local goodies = { }
+ local main = {
+ metadata = metadata,
+ properties = properties,
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ mathparameters = mathparameters,
+ fonts = fontlist,
+ goodies = goodies,
+ }
+ --
+ --
+ for key, value in next, parent do
+ if type(value) ~= "table" then
+ main[key] = value
+ end
+ end
+ --
+ if parent.characters then
+ for unicode, character in next, parent.characters do
+ characters[unicode] = character
+ end
+ else
+ report_virtual("font %a has no characters",name)
+ end
+ --
+ if parent.parameters then
+ for key, value in next, parent.parameters do
+ parameters[key] = value
+ end
+ else
+ report_virtual("font %a has no parameters",name)
+ end
+ --
+ local description = { name = "<unset>" }
+ setmetatableindex(descriptions,function() return description end)
+ --
+ if parent.properties then
+ setmetatableindex(properties,parent.properties)
+ end
+ --
+ if parent.goodies then
+ setmetatableindex(goodies,parent.goodies)
+ end
+ --
+ properties.virtualized = true
+ properties.hasitalics = true
+ properties.hasmath = true
+ --
+ local fullname = properties.fullname -- parent via mt
+ if fullname then
+ unique = unique + 1
+ properties.fullname = fullname .. "-" .. unique
+ end
+ --
+ -- we need to set some values in main as well (still?)
+ --
+ main.fullname = properties.fullname
+ main.type = "virtual"
+ main.nomath = false
+ --
+ parameters.x_height = parameters.x_height or 0
+ --
+ local already_reported = false
+ local parameters_done = false
+ for s=1,n do
+ local ss, fs = okset[s], loaded[s]
+ if not fs then
+ -- skip, error
+ elseif add_optional and ss.optional then
+ -- skip, redundant
+ else
+ local newparameters = fs.parameters
+ local newmathparameters = fs.mathparameters
+ if newmathparameters then
+ if not parameters_done or ss.parameters then
+ mathparameters = newmathparameters
+ parameters_done = true
+ end
+ elseif not newparameters then
+ report_virtual("no parameters set in font %a",name)
+ elseif ss.extension then
+ mathparameters.math_x_height = newparameters.x_height or 0 -- math_x_height : height of x
+ mathparameters.default_rule_thickness = newparameters[ 8] or 0 -- default_rule_thickness : thickness of \over bars
+ mathparameters.big_op_spacing1 = newparameters[ 9] or 0 -- big_op_spacing1 : minimum clearance above a displayed op
+ mathparameters.big_op_spacing2 = newparameters[10] or 0 -- big_op_spacing2 : minimum clearance below a displayed op
+ mathparameters.big_op_spacing3 = newparameters[11] or 0 -- big_op_spacing3 : minimum baselineskip above displayed op
+ mathparameters.big_op_spacing4 = newparameters[12] or 0 -- big_op_spacing4 : minimum baselineskip below displayed op
+ mathparameters.big_op_spacing5 = newparameters[13] or 0 -- big_op_spacing5 : padding above and below displayed limits
+ -- report_virtual("loading and virtualizing font %a at size %p, setting ex parameters",name,size)
+ elseif ss.parameters then
+ mathparameters.x_height = newparameters.x_height or mathparameters.x_height
+ mathparameters.x_height = mathparameters.x_height or fp.x_height or 0 -- x_height : height of x
+ mathparameters.num1 = newparameters[ 8] or 0 -- num1 : numerator shift-up in display styles
+ mathparameters.num2 = newparameters[ 9] or 0 -- num2 : numerator shift-up in non-display, non-\atop
+ mathparameters.num3 = newparameters[10] or 0 -- num3 : numerator shift-up in non-display \atop
+ mathparameters.denom1 = newparameters[11] or 0 -- denom1 : denominator shift-down in display styles
+ mathparameters.denom2 = newparameters[12] or 0 -- denom2 : denominator shift-down in non-display styles
+ mathparameters.sup1 = newparameters[13] or 0 -- sup1 : superscript shift-up in uncramped display style
+ mathparameters.sup2 = newparameters[14] or 0 -- sup2 : superscript shift-up in uncramped non-display
+ mathparameters.sup3 = newparameters[15] or 0 -- sup3 : superscript shift-up in cramped styles
+ mathparameters.sub1 = newparameters[16] or 0 -- sub1 : subscript shift-down if superscript is absent
+ mathparameters.sub2 = newparameters[17] or 0 -- sub2 : subscript shift-down if superscript is present
+ mathparameters.sup_drop = newparameters[18] or 0 -- sup_drop : superscript baseline below top of large box
+ mathparameters.sub_drop = newparameters[19] or 0 -- sub_drop : subscript baseline below bottom of large box
+ mathparameters.delim1 = newparameters[20] or 0 -- delim1 : size of \atopwithdelims delimiters in display styles
+ mathparameters.delim2 = newparameters[21] or 0 -- delim2 : size of \atopwithdelims delimiters in non-displays
+ mathparameters.axis_height = newparameters[22] or 0 -- axis_height : height of fraction lines above the baseline
+ -- 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 first = ss.first
+ if first then
+ local last = ss.last or first
+ for unicode = first, last do
+ characters[unicode] = copy_glyph(main,characters,fc,unicode,s)
+ end
+ else
+ for unicode, data in next, fc do
+ characters[unicode] = copy_glyph(main,characters,fc,unicode,s)
+ end
+ end
+ else
+ local vectorname = ss.vector
+ if vectorname then
+ local offset = 0xFF000
+ local vector = mathencodings[vectorname]
+ local rotcev = reverse[vectorname]
+ local isextension = ss.extension
+ if vector and rotcev then
+ local fc, fd, si = fs.characters, fs.descriptions, shared[s]
+ local skewchar = ss.skewchar
+ for unicode, index in next, vector do
+ local fci = fc[index]
+ if not fci then
+ local fontname = fs.properties.name or "unknown"
+ local rf = reported[fontname]
+ if not rf then rf = { } reported[fontname] = rf end
+ local rv = rf[vectorname]
+ if not rv then rv = { } rf[vectorname] = rv end
+ local ru = rv[unicode]
+ if not ru then
+ if trace_virtual then
+ report_virtual("unicode slot %U has no index %H in vector %a for font %a (%S)",unicode,index,vectorname,fontname,chardata[unicode].description)
+ elseif not already_reported then
+ report_virtual("the mapping is incomplete for %a at %p",name,size)
+ already_reported = true
+ end
+ rv[unicode] = true
+ end
+ else
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local kerns = fci.kerns
+ local width = fci.width
+ local italic = fci.italic
+ if italic and italic > 0 then
+ -- int_a^b
+ if isextension then
+ width = width + italic -- for obscure reasons the integral as a width + italic correction
+ end
+ end
+ if kerns then
+ local krn = { }
+ for k, v in next, kerns do -- kerns is sparse
+ local rk = rotcev[k]
+ if rk then
+ krn[rk] = v -- kerns[k]
+ end
+ end
+ if not next(krn) then
+ krn = nil
+ end
+ local t = {
+ width = width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = italic,
+ kerns = krn,
+ commands = ref,
+ }
+ if skewchar then
+ local k = kerns[skewchar]
+ if k then
+ t.top_accent = width/2 + k
+ end
+ end
+ characters[unicode] = t
+ else
+ characters[unicode] = {
+ width = width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = italic,
+ commands = ref,
+ }
+ end
+ end
+ end
+ if isextension then
+ -- todo: if multiple ex, then 256 offsets per instance
+ local extension = mathencodings["large-to-small"]
+ local variants_done = fs.variants_done
+ for index, fci in next, fc do -- the raw ex file
+ if type(index) == "number" then
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local italic = fci.italic
+ local t = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = italic,
+ commands = ref,
+ }
+ local n = fci.next
+ if n then
+ t.next = offset + n
+ elseif variants_done then
+ local vv = fci.vert_variants
+ if vv then
+ t.vert_variants = vv
+ end
+ local hv = fci.horiz_variants
+ if hv then
+ t.horiz_variants = hv
+ end
+ else
+ local vv = fci.vert_variants
+ if vv then
+ for i=1,#vv do
+ local vvi = vv[i]
+ vvi.glyph = vvi.glyph + offset
+ end
+ t.vert_variants = vv
+ end
+ local hv = fci.horiz_variants
+ if hv then
+ for i=1,#hv do
+ local hvi = hv[i]
+ hvi.glyph = hvi.glyph + offset
+ end
+ t.horiz_variants = hv
+ end
+ end
+ characters[offset + index] = t
+ end
+ end
+ fs.variants_done = true
+ for unicode, index in next, extension do
+ local cu = characters[unicode]
+ if cu then
+ cu.next = offset + index
+ else
+ local fci = fc[index]
+ if not fci then
+ -- do nothing
+ else
+ -- probably never entered
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local kerns = fci.kerns
+ if kerns then
+ local krn = { }
+ -- for k=1,#kerns do
+ -- krn[offset + k] = kerns[k]
+ -- end
+ for k, v in next, kerns do -- is kerns sparse?
+ krn[offset + k] = v
+ end
+ characters[unicode] = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ kerns = krn,
+ next = offset + index,
+ }
+ else
+ characters[unicode] = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ next = offset + index,
+ }
+ end
+ end
+ end
+ end
+ end
+ else
+ report_virtual("error in loading %a, problematic vector %a",name,vectorname)
+ end
+ end
+ end
+ mathematics.extras.copy(main) --not needed here (yet)
+ end
+ end
+ --
+ fontlist[#fontlist+1] = {
+ id = font.nextid(),
+ size = size,
+ }
+ --
+ main.mathparameters = mathparameters -- still traditional ones
+ vfmath.addmissing(main,#fontlist,size)
+ mathematics.addfallbacks(main)
+ --
+ main.properties.math_is_scaled = true -- signal
+ fonts.constructors.assignmathparameters(main,main)
+ --
+ main.MathConstants = main.mathparameters -- we directly pass it to TeX (bypasses the scaler) so this is needed
+ --
+ if trace_virtual or trace_timings then
+ report_virtual("loading and virtualizing font %a at size %p took %0.3f seconds",name,size,os.clock()-start)
+ end
+ --
+ return main
+end
+
+function mathematics.makefont(name,set,goodies)
+ fonts.definers.methods.variants[name] = function(specification)
+ return vfmath.define(specification,set,goodies)
+ end
+end
+
+-- helpers
+
+function vfmath.setletters(font_encoding, name, uppercase, lowercase)
+ local enc = font_encoding[name]
+ for i = 0,25 do
+ enc[uppercase+i] = i + 0x41
+ enc[lowercase+i] = i + 0x61
+ end
+end
+
+function vfmath.setdigits(font_encoding, name, digits)
+ local enc = font_encoding[name]
+ for i = 0,9 do
+ enc[digits+i] = i + 0x30
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fig.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-fig.mkiv
new file mode 100644
index 00000000000..bf37aa7bfa7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fig.mkiv
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=meta-fig,
+%D version=2000.09.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Stand Alone Graphics,
+%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 / Stand Alone Graphics}
+
+\unprotect
+
+%D This module implements a method for defining
+%D stand||alone||graphics, that is, each graphic gets is own
+%D page. Because graphics are wrapped in a \type {\framed},
+%D you can add overlays to the graphic directly, and since the
+%D whole \CONTEXT\ machinery is available, you can also add
+%D page backgrounds.
+%D
+%D \starttyping
+%D \setupMPpage
+%D [offset=1pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \startMPpage
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopMPpage
+%D
+%D \startMPpage
+%D fill fullsquare rotated 45 scaled 8cm withcolor blue ;
+%D \stopMPpage
+%D \stoptyping
+%D
+%D Although this is hardly of any use, you can mix these
+%D definitions with the text flow, since all settings are
+%D kept local. The page is clipped to the image size.
+
+\definefittingpage
+ [MPpage]
+ [\c!align=,
+ \c!command=\meta_process_graphic_instance{\fittingpageparameter\c!instance},
+ \c!instance=]
+
+\unexpanded\def\setupMPpage
+ {\setupfittingpage[MPpage]}
+
+%D \macros
+%D {MPfigure}
+%D
+%D A bit out of place, here but nevertheless:
+
+\unexpanded\def\MPfigure#1#2% test for dup figure, can be replaced by a textext
+ {\bgroup
+ \getfiguredimensions[#1]% [\c!object=\v!no] already set
+ \startMPcode
+ draw externalfigure "#1"
+ xscaled \the\dimexpr\figurewidth \relax\space % must be points
+ yscaled \the\dimexpr\figureheight\relax\space % must be points
+ #2 ;
+ \stopMPcode
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua
new file mode 100644
index 00000000000..95bdfa6d966
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua
@@ -0,0 +1,266 @@
+if not modules then modules = { } end modules ['meta-fnt'] = {
+ version = 1.001,
+ comment = "companion to meta-fnt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+local format = string.format
+local formatters = string.formatters
+local chardata = characters.data
+local fontdata = fonts.hashes.identifiers
+
+local vffonts = fonts.handlers.vf
+
+local mpfonts = fonts.mp or { }
+fonts.mp = mpfonts
+
+mpfonts.version = mpfonts.version or 1.20
+mpfonts.inline = true
+mpfonts.cache = containers.define("fonts", "mp", mpfonts.version, true)
+
+metapost.fonts = metapost.fonts or { }
+
+local function unicodetoactualtext(...)
+ unicodetoactualtext = backends.codeinjections.unicodetoactualtext
+ return unicodetoactualtext(...)
+end
+
+-- a few glocals
+
+local characters, descriptions = { }, { }
+local factor, code, slot, width, height, depth, total, variants, bbox, llx, lly, urx, ury = 100, { }, 0, 0, 0, 0, 0, 0, true, 0, 0, 0, 0
+
+local flusher = {
+ startfigure = function(_chr_,_llx_,_lly_,_urx_,_ury_)
+ code = { }
+ slot = _chr_
+ llx = _llx_
+ lly = _lly_
+ urx = _urx_
+ ury = _ury_
+ width = urx - llx
+ height = ury
+ depth = -lly
+ total = total + 1
+ inline = mpfonts.inline
+ end,
+ flushfigure = function(t)
+ for i=1,#t do
+ code[#code+1] = t[i]
+ end
+ end,
+ stopfigure = function()
+ local cd = chardata[n]
+ local code = unicodetoactualtext(slot,concat(code," ")) or ""
+ descriptions[slot] = {
+ -- unicode = slot,
+ name = cd and cd.adobename,
+ width = width * 100,
+ height = height * 100,
+ depth = depth * 100,
+ boundingbox = { llx, lly, urx, ury },
+ }
+ if inline then
+ characters[slot] = {
+ commands = {
+ { "special", "pdf:" .. code },
+ }
+ }
+ else
+ characters[slot] = {
+ commands = {
+ {
+ "image",
+ {
+ stream = code,
+ bbox = { 0, -depth * 65536, width * 65536, height * 65536 }
+ },
+ },
+ }
+ }
+ end
+ code = nil -- no need to keep that
+ end
+}
+
+local function process(mpxformat,name,instances,scalefactor)
+ local filename = resolvers.findfile(name)
+ local attributes = filename and lfs.isfile(filename) and lfs.attributes(filename)
+ if attributes then
+ statistics.starttiming(metapost.fonts)
+ scalefactor = scalefactor or 1
+ instances = instances or metapost.fonts.instances or 1 -- maybe store in liost too
+ local fontname = file.removesuffix(file.basename(name))
+ local modification = attributes.modification
+ local filesize = attributes.size
+ local hash = file.robustname(formatters["%s %05i %03i"](fontname,scalefactor*1000,instances))
+ local lists = containers.read(mpfonts.cache,hash)
+ if not lists or lists.modification ~= modification or lists.filesize ~= filesize or lists.instances ~= instances or lists.scalefactor ~= scalefactor then
+ statistics.starttiming(flusher)
+ local data = io.loaddata(filename)
+ metapost.reset(mpxformat)
+ metapost.setoutercolor(2) -- no outer color and no reset either
+ lists = { }
+ for i=1,instances do
+ characters = { }
+ descriptions = { }
+ metapost.process(
+ mpxformat,
+ {
+ formatters["randomseed := %s ;"](i*10),
+ formatters["charscale := %s ;"](scalefactor),
+ data,
+ },
+ false,
+ flusher,
+ false,
+ false,
+ "all"
+ )
+ lists[i] = {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = {
+ designsize = 655360,
+ slant = 0,
+ space = 333 * scalefactor,
+ space_stretch = 166.5 * scalefactor,
+ space_shrink = 111 * scalefactor,
+ x_height = 431 * scalefactor,
+ quad = 1000 * scalefactor,
+ extra_space = 0,
+ },
+ properties = {
+ name = formatters["%s-%03i"](hash,i),
+ virtualized = true,
+ spacer = "space",
+ }
+ }
+ end
+ lists.version = metapost.variables.fontversion or "1.000"
+ lists.modification = modification
+ lists.filesize = filesize
+ lists.instances = instances
+ lists.scalefactor = scalefactor
+ metapost.reset(mpxformat) -- saves memory
+ lists = containers.write(mpfonts.cache, hash, lists)
+ statistics.stoptiming(flusher)
+ end
+ variants = variants + #lists
+ statistics.stoptiming(metapost.fonts)
+ return lists
+ else
+ return { }
+ end
+end
+
+metapost.fonts.flusher = flusher
+metapost.fonts.instances = 1
+metapost.fonts.process = process
+
+local function build(g,v)
+ local size = g.specification.size
+ local data = process(v[2],v[3],v[4],size/655360,v[6])
+ local list = { }
+ local t = { }
+ for d=1,#data do
+ t = fonts.constructors.scale(data[d],-1000)
+ local id = font.nextid()
+ t.fonts = { { id = id } }
+ fontdata[id] = t
+ if v[5] then
+ vffonts.helpers.composecharacters(t)
+ end
+ list[d] = font.define(t)
+ end
+ for k, v in next, t do -- last t
+ g[k] = v -- kind of replace, when not present, make nil
+ end
+ g.properties.virtualized = true
+ g.variants = list
+end
+
+vffonts.combiner.commands.metapost = build
+vffonts.combiner.commands.metafont = build
+
+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, %i glyphs/second", total, time, total/time)
+ else
+ return format("%i glyphs, %.3f seconds runtime", total, time)
+ end
+ end
+end)
+
+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, %0.3f instances/second", time, variants, variants/time)
+ else
+ return format("%.3f seconds, %i instances", time, variants)
+ end
+ end
+end)
+
+-- fonts.definers.methods.install( "bidi", {
+-- {
+-- "metapost", -- method
+-- "metafun", -- format
+-- "fontoeps.mp", -- filename
+-- 1, -- instances
+-- false, -- compose
+-- },
+-- } )
+
+local report = logs.reporter("metapost","fonts")
+
+function metapost.fonts.define(specification)
+ local fontname = specification.fontname or ""
+ local filename = specification.filename or ""
+ local format = specification.format or "metafun"
+ if fontname == "" then
+ report("no fontname given")
+ return
+ end
+ if filename == "" then
+ report("no filename given for %a",fontname)
+ return
+ end
+ local fullname = resolvers.findfile(filename)
+ if fullname == "" then
+ report("unable to locate file %a",filename)
+ return
+ end
+ report("generating font %a using format %a and file %a",fontname,format,filename)
+ fonts.definers.methods.install(fontname, {
+ {
+ specification.engine or "metapost",
+ format,
+ filename,
+ specification.instances or 1,
+ specification.compose or false,
+ },
+ } )
+end
+
+interfaces.implement {
+ name = "definemetafont",
+ actions = metapost.fonts.define,
+ arguments = {
+ {
+ { "fontname" },
+ { "filename" },
+ }
+ }
+}
+
+-- metapost.fonts.define {
+-- fontname = "bidi",
+-- filename = "bidi-symbols.mp",
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.mkiv
new file mode 100644
index 00000000000..e54c0be0a4f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.mkiv
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=meta-fnt,
+%D version=2013.09.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Fonts,
+%D author=Hans Hagen,
+%D date=\ currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{MetaPost Graphics / Fonts}
+
+\registerctxluafile{meta-fnt}{1.001}
+
+\unprotect
+
+\unexpanded\def\definemetafont
+ {\dotripleempty\meta_font_define}
+
+\def\meta_font_define[#1][#2][#3]%
+ {\clf_definemetafont
+ fontname {#1}%
+ filename {#2}%
+ % no #3 settings yet (compose, instances)
+ \relax}
+
+% \startluacode
+% metapost.fonts.define { fontname = "bidi-symbols", filename = "bidi-symbols.mp" }
+% \stopluacode
+
+% \definemetafont[bidi-symbols][bidi-symbols.mp]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fun.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-fun.lua
new file mode 100644
index 00000000000..7aaaf2818ec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fun.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['meta-fun'] = {
+ version = 1.001,
+ comment = "companion to meta-fun.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- very experimental, actually a joke ... see metafun manual for usage
+
+local format, load, type = string.format, load, type
+
+local metapost = metapost
+
+metapost.metafun = metapost.metafun or { }
+local metafun = metapost.metafun
+
+function metafun.topath(t,connector)
+ context("(")
+ if #t > 0 then
+ for i=1,#t do
+ if i > 1 then
+ context(connector or "..")
+ end
+ local ti = t[i]
+ if type(ti) == "string" then
+ context(ti)
+ else
+ context("(%F,%F)",ti.x or ti[1] or 0,ti.y or ti[2] or 0)
+ end
+ end
+ else
+ context("origin")
+ end
+ context(")")
+end
+
+function metafun.interpolate(f,b,e,s,c)
+ local done = false
+ context("(")
+ for i=b,e,(e-b)/s do
+ local d = load(format("return function(x) return %s end",f))
+ if d then
+ d = d()
+ if done then
+ context(c or "...")
+ else
+ done = true
+ end
+ context("(%F,%F)",i,d(i))
+ end
+ end
+ if not done then
+ context("origin")
+ end
+ context(")")
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fun.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-fun.mkiv
new file mode 100644
index 00000000000..c3a4ce8d417
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fun.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=meta-fun,
+%D version=2009.06.02,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Goodies,
+%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 / Goodies}
+
+\registerctxluafile{meta-fun}{1.001}
+
+\unprotect
+
+%D Just a few handy helpers:
+
+\ifdefined\MPtoks\else \newtoks\MPtoks \fi
+\ifdefined\MPbox \else \newbox \MPbox \fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-grd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-grd.mkiv
new file mode 100644
index 00000000000..da410ba689d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-grd.mkiv
@@ -0,0 +1,116 @@
+%D \module
+%D [ file=meta-grd,
+%D version=2012.06.28,
+%D title=\METAPOST\ Graphics,
+%D subtitle=grids,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{MetaPost Graphics / Grids}
+
+%D This used to be a \TEX\ method, and a rather old one too. We keep it around but
+%D in a more modern way.
+%D
+%D \startbuffer
+%D \basegrid
+%D [nx=8,ny=5,
+%D dx=.5,dy=.25,
+%D unit=cm,scale=2,factor=1,
+%D offset=1ex,xstep=2,ystep=1,
+%D align=middle,style=\tt\tx]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \placefigure
+%D {An example of a grid.}
+%D {\getbuffer}
+
+\startuseMPgraphic{grid}{nx,ny,dx,dy,factor,scale,xstep,ystep,xoffset,yoffset,align}
+ begingroup ;
+
+ save nx, ny, dx, dy, wd, ht, xstep, ystep, xoffset, yoffset, align, xalign, yalign ;
+
+ numeric nx ; nx := \MPvar{nx} ;
+ numeric ny ; ny := \MPvar{ny} ;
+ numeric dx ; dx := \MPvar{factor} * \MPvar{scale} * \MPvar{dx} ;
+ numeric dy ; dy := \MPvar{factor} * \MPvar{scale} * \MPvar{dy} ;
+ numeric wd ; wd := nx * dx ;
+ numeric ht ; ht := ny * dy ;
+ numeric xstep ; xstep := \MPvar{xstep} ;
+ numeric ystep ; ystep := \MPvar{ystep} ;
+ numeric xoffset ; xoffset := \MPvar{xoffset} ;
+ numeric yoffset ; yoffset := \MPvar{yoffset} ;
+ numeric align ; align := \MPvar{align} ;
+ numeric xalign ; xalign := 0 ;
+ numeric yalign ; yalign := 0 ;
+
+ if align = 1 :
+ xalign := dx/2 ;
+ yalign := dy/2 ;
+ fi ;
+
+ for i=0 step dx until wd :
+ draw (i,0) -- (i,ht) ;
+ endfor ;
+ for i=0 step dy until ht :
+ draw (0,i) -- (wd,i) ;
+ endfor ;
+
+ if xstep > 0 :
+ for i=1 step xstep until nx :
+ draw thetextext.bot(decimal i,(i*dx-xalign,-xoffset)) ;
+ endfor ;
+ fi ;
+ if ystep > 0 :
+ for i=1 step ystep until ny :
+ draw thetextext.lft(decimal i,(-yoffset,i*dy-yalign)) ;
+ endfor ;
+ fi ;
+
+ endgroup ;
+\stopuseMPgraphic
+
+\unprotect
+
+\unexpanded\def\basegrid
+ {\dosingleempty\typo_grid_base}
+
+\def\typo_grid_base[#1]%
+ {\hbox\bgroup
+ \getdummyparameters
+ [\c!nx=10,\c!ny=10,\c!dx=.5,\c!dy=.5,\c!xstep=0,\c!ystep=0,
+ \c!unit=\s!cm,\c!scale=1,\c!factor=1,
+ \c!offset=.25ex,\c!xoffset=\directdummyparameter\c!offset,\c!yoffset=\directdummyparameter\c!offset,
+ \c!align=,
+ #1]%
+ \usedummystyleandcolor\c!style\c!color
+ \edef\p_align{\directdummyparameter\c!align}%
+ \ifx\p_align\v!middle
+ \let\p_align\!!plusone
+ \else
+ \let\p_align\!!zerocount
+ \fi
+ \useMPgraphic
+ {grid}%
+ {nx=\directdummyparameter\c!nx,%
+ ny=\directdummyparameter\c!ny,%
+ dx=\directdummyparameter\c!dx\directdummyparameter\c!unit,%
+ dy=\directdummyparameter\c!dy\directdummyparameter\c!unit,%
+ factor=\directdummyparameter\c!factor,%
+ scale=\directdummyparameter\c!scale,%
+ xstep=\directdummyparameter\c!xstep,%
+ ystep=\directdummyparameter\c!ystep,%
+ xoffset=\directdummyparameter\c!xoffset,%
+ yoffset=\directdummyparameter\c!yoffset,%
+ align=\p_align}%
+ \egroup}
+
+\let\grid\basegrid
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-clp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-clp.mkiv
new file mode 100644
index 00000000000..89886b38969
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-clp.mkiv
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=meta-imp-clp,
+%D version=2000.07.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Clipping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In this library, we define a bunch of clipping paths that
+%D can be fed to \type {\clip}.
+
+\startMPclip{ellipse}
+ clip currentpicture to unitcircle
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{negellipse}
+ clip currentpicture to (unitcircle peepholed unitsquare)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{urellipse}
+ clip currentpicture to urcircle scaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{ulellipse}
+ clip currentpicture to ulcircle scaled 2 shifted (1,0)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{llellipse}
+ clip currentpicture to llcircle scaled 2 shifted (1,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lrellipse}
+ clip currentpicture to lrcircle scaled 2 shifted (0,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{tellipse}
+ clip currentpicture to tcircle shifted (.5,0) yscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{bellipse}
+ clip currentpicture to bcircle shifted (.5,.5) yscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lellipse}
+ clip currentpicture to lcircle shifted (.5,.5) xscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{rellipse}
+ clip currentpicture to rcircle shifted (0,.5) xscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{diamond}
+ clip currentpicture to unitdiamond
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{negdiamond}
+ clip currentpicture to (unitdiamond peepholed unitsquare)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{urtriangle}
+ clip currentpicture to urtriangle scaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{ultriangle}
+ clip currentpicture to ultriangle scaled 2 shifted (1,0)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lltriangle}
+ clip currentpicture to lltriangle scaled 2 shifted (1,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lrtriangle}
+ clip currentpicture to lrtriangle scaled 2 shifted (0,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+% More efficient:
+%
+% \def\dosimpleMPclip#1
+% {clip currentpicture to (#1) xscaled \width yscaled \height ;}
+%
+% \def\simpleMPclip#1#2%
+% {\startMPclip{#1}\dosimpleMPclip{#2}\stopMPclip}
+%
+% \simpleMPclip {ellipse} {unitcircle}
+% \simpleMPclip {diamond} {unitdiamond}
+%
+% \simpleMPclip {negellipse} {unitcircle peepholed unitsquare}
+% \simpleMPclip {negdiamond} {unitdiamond peepholed unitsquare}
+%
+% \simpleMPclip {urellipse} {urcircle scaled 2 shifted (0,0)}
+% \simpleMPclip {ulellipse} {ulcircle scaled 2 shifted (1,0)}
+% \simpleMPclip {llellipse} {llcircle scaled 2 shifted (1,1)}
+% \simpleMPclip {lrellipse} {lrcircle scaled 2 shifted (0,1)}
+%
+% \simpleMPclip {tellipse} {tcircle shifted (.5,0) yscaled 2}
+% \simpleMPclip {bellipse} {bcircle shifted (.5,.5) yscaled 2}
+% \simpleMPclip {lellipse} {lcircle shifted (.5,.5) xscaled 2}
+% \simpleMPclip {rellipse} {rcircle shifted (0,.5) xscaled 2}
+%
+% \simpleMPclip {urtriangle} {urtriangle scaled 2 shifted (0,0)}
+% \simpleMPclip {ultriangle} {ultriangle scaled 2 shifted (1,0)}
+% \simpleMPclip {lltriangle} {lltriangle scaled 2 shifted (1,1)}
+% \simpleMPclip {lrtriangle} {lrtriangle scaled 2 shifted (0,1)}
+
+%D \in {Figure} [fig:clipping paths] shows which paths are
+%D predefined. When applied to a whole picture, their usage
+%D is:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,mp=ellipse]{some clippable content}
+%D \stoptyping
+%D
+%D \startbuffer
+%D \setupclipping [nx=1,ny=1,x=1,y=1]
+%D \setupblackrules[width=2cm,height=1cm]
+%D \startcombination[6*3] % \startcombination[6*3]
+%D {\clip[mp=urellipse] {\blackrule}} {urellipse}
+%D {\clip[mp=ulellipse] {\blackrule}} {ulellipse}
+%D {\clip[mp=llellipse] {\blackrule}} {llellipse}
+%D {\clip[mp=lrellipse] {\blackrule}} {lrellipse}
+%D {\clip[mp=ellipse] {\blackrule}} {ellipse}
+%D {\clip[mp=negellipse]{\blackrule}} {negellipse}
+%D {\clip[mp=tellipse] {\blackrule}} {tellipse}
+%D {\clip[mp=bellipse] {\blackrule}} {bellipse}
+%D {\clip[mp=lellipse] {\blackrule}} {lellipse}
+%D {\clip[mp=rellipse] {\blackrule}} {rellipse}
+%D {} {}
+%D {} {}
+%D {\clip[mp=urtriangle]{\blackrule}} {urtriangle}
+%D {\clip[mp=ultriangle]{\blackrule}} {ultriangle}
+%D {\clip[mp=lltriangle]{\blackrule}} {lltriangle}
+%D {\clip[mp=lrtriangle]{\blackrule}} {lrtriangle}
+%D {\clip[mp=diamond] {\blackrule}} {diamond}
+%D {\clip[mp=negdiamond]{\blackrule}} {negdiamond}
+%D \stopcombination % \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure % \placefigure
+%D [here][fig:clipping paths]
+%D {The predefined clipping paths.}
+%D {\getbuffer} % {\getbuffer}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv
new file mode 100644
index 00000000000..e6ccc234c6d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv
@@ -0,0 +1,216 @@
+%D \module
+%D [ file=meta-dum,
+%D version=2003.03.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Dummy (External) Graphics,
+%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 This library overloads the normal external figure
+%D placeholder by a nicer one.
+%D
+%D \startbuffer
+%D \useMPlibrary[dum]
+%D
+%D \startlinecorrection
+%D \externalfigure[unknown-a][width=3cm,height=1cm]
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \externalfigure[unknown-b][width=4cm,height=5cm]
+%D \stoplinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% currently preparempvariables is unable to resolve number
+% fractions like reduction
+
+% June 22, 2003, this definition was patched to adapt itself
+% to transparent colors, but ... in 2011 we no longer have
+% is_transparent so we revert.
+%
+% \startuseMPgraphic{placeholder}{width,height,reduction,color}
+% numeric w, h, d, r ; color c, b, cc ; path p ; boolean t ;
+% t := is_transparent(\MPvar{color}) ;
+% c := not_transparent(\MPvar{color}) ;
+% b := not_transparent(white) ;
+% w := \MPvar{width} ;
+% h := \MPvar{height} ;
+% r := \MPvar{reduction} ;
+% d := max(w,h) ;
+% p := unitsquare xyscaled (w,h) ;
+% cc := r[.5c,b] ;
+% fill p withcolor if t : transparent(1,.5,cc) else : cc fi ;
+% for i := 1 upto 60 :
+% cc := r[c randomized(.3,.9),b] ;
+% fill fullcircle
+% scaled (d/5 randomized (d/5))
+% shifted (center p randomized (d))
+% withcolor if t : transparent(1,.5,cc) else : cc fi ;
+% endfor ;
+% clip currentpicture to p ;
+% \stopuseMPgraphic
+
+\startuseMPgraphic{figure:placeholder}{width,height,reduction,color}
+ begingroup ;
+ save w, h, d, r, p, c, b ;
+ numeric w, h, d, r ; path p ;
+ if cmykcolor \MPvar{color} :
+ cmykcolor c, b ; b := (0,0,0,0)
+ else :
+ color c, b ; ; b := (1,1,1)
+ fi ;
+ c := \MPvar{color} ;
+ w := \MPvar{width} ;
+ h := \MPvar{height} ;
+ r := \MPvar{reduction} ;
+ d := max(w,h) ;
+ p := unitsquare xyscaled (w,h) ;
+ fill p withcolor r[.5c,b] ;
+ for i := 1 upto 60 :
+ fill fullcircle
+ scaled (d/5 randomized (d/5))
+ shifted (center p randomized (d))
+ withcolor r[c randomized(.3,.9),b] ;
+ endfor ;
+ clip currentpicture to p ;
+ endgroup ;
+\stopuseMPgraphic
+
+\defineoverlay
+ [figure:placeholder:graphic]
+ [\useMPgraphic
+ {figure:placeholder}%
+ {width=\figurewidth,%
+ height=\figureheight,%
+ reduction=\externalfigureparameter\c!reduction,%
+ color=placeholder:\the\c_grph_replacement_n}]
+
+\definepalet
+ [placeholder]
+ [1=red,2=green,3=blue,4=cyan,5=magenta,6=yellow]
+
+\newcount\c_grph_replacement_n
+
+\setupexternalfigures
+ [\c!reduction=0,
+ \c!text=\v!yes]
+
+\let\grph_include_replacement_saved\grph_include_replacement
+
+\unexpanded\def\grph_include_replacement#1#2#3%
+ {\begingroup
+ \getpaletsize[placeholder]%
+ \ifnum\c_grph_replacement_n=\zerocount
+ \getrandomnumber \m_grph_replacement_n\plusone\paletsize
+ \global\c_grph_replacement_n \m_grph_replacement_n\relax
+ \else
+ \global\advance\c_grph_replacement_n\plusone
+ \fi
+ \ifnum\c_grph_replacement_n>\paletsize
+ \global\c_grph_replacement_n\plusone
+ \fi
+ \setupcurrentexternalfigure
+ [\c!width=\figurewidth,
+ \c!height=\figureheight,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!align={\v!middle,\v!lohi},
+ \c!background=figure:placeholder:graphic,
+ \c!foregroundcolor=\s!white]%
+ \doifelse{\externalfigureparameter\c!text}\v!yes
+ {\edef\m_graphics_text_a{#1}\edef\m_graphics_text_a{\ifx\m_graphics_text_a\s!dummy\else\detokenize\expandafter{\m_graphics_text_a}\fi}%
+ \edef\m_graphics_text_b{#2}\edef\m_graphics_text_b{\ifx\m_graphics_text_b\s!dummy\else\detokenize\expandafter{\m_graphics_text_b}\fi}%
+ \edef\m_graphics_text_c{#3}\edef\m_graphics_text_c{\ifx\m_graphics_text_c\s!dummy\else\detokenize\expandafter{\m_graphics_text_c}\fi}%
+ \infofont\setupinterlinespace\dohyphens
+ \inheritedexternalfigureframed{\directsetup{figure:placeholder:text}}}%
+ {\inheritedexternalfigureframed{}}%
+ \endgroup}
+
+\unexpanded\def\dummyfigure
+ {\externalfigure[placeholder]}
+
+\startsetups figure:placeholder:text
+ \ifx\m_graphics_text_a\empty\else
+ \strut name: \m_graphics_text_a\par
+ \fi
+ \ifx\m_graphics_text_b\empty\else
+ \strut
+ \ifx\m_graphics_text_a\empty
+ \ifx\m_graphics_text_c\empty
+ \else
+ file:\space
+ \fi
+ \else
+ file:\space
+ \fi
+ \m_graphics_text_b\par
+ \fi
+ \ifx\m_graphics_text_c\empty\else
+ \strut state: \m_graphics_text_c\par
+ \fi
+\stopsetups
+
+%D \starttyping
+%D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:comment]
+%D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:dummy]
+%D \externalfigure[mediashow.swf][background=figure:dummy]
+%D \stoptyping
+
+\defineframed
+ [figurecomment]
+ [\c!background=\v!color,
+ \c!backgroundcolor=\s!gray,
+ \c!frame=\v!off,
+ \c!foregroundstyle=\ttbf,
+ \c!align={\v!middle,\v!lohi},
+ \c!height=\figureheight,
+ \c!width=\figurewidth]
+
+\defineframed
+ [figuredummy]
+ [\c!background=figure:dummy:only,
+ \c!foregroundcolor=\s!white,
+ \c!backgroundcolor=\v!gray,
+ \c!frame=\v!off,
+ \c!foregroundstyle=\ttbf,
+ \c!align={\v!middle,\v!lohi},
+ \c!height=\figureheight,
+ \c!width=\figurewidth]
+
+\defineoverlay
+ [figure:dummy:only]
+ [\grph_include_replacement\empty\empty\empty]
+
+\defineoverlay
+ [figure:comment]
+ [\figurecomment{\externalfigureparameter\c!comment}]
+
+\defineoverlay
+ [figure:dummy]
+ [\figuredummy{\externalfigureparameter\c!comment}]
+
+\setupexternalfigures
+ [\c!comment=]
+
+\protect
+
+\continueifinputfile{meta-imp-dum.mkiv}
+
+\starttext
+
+ \externalfigure[whatever-missing]
+
+ \blank
+
+ \externalfigure[whatever-missing][width=2cm]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-fen.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-fen.mkiv
new file mode 100644
index 00000000000..307a59b4db6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-fen.mkiv
@@ -0,0 +1,173 @@
+%D \module
+%D [ file=meta-imp-fen,
+%D version=2011.07.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Fences,
+%D author=Wolfgang Schuster & Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The shape and background example code was posted by Wolfgang on the
+%D \CONTEXT\ list and due to request by Aditya has been turned into
+%D library.
+
+\startMPextensions
+ vardef BasicBraceSymbol (expr rotation) =
+ save p ; path p ;
+ z1 = (-233, 0) ;
+ z2 = (-220, 22) ;
+ z3 = (-155, 211) ;
+ z4 = (-200, 690) ;
+ z5 = (-142, 1033) ;
+ z6 = ( -97, 1106) ;
+ z7 = ( -71, 1125) ;
+ z8 = ( -61, 1104) ;
+ z9 = ( -80, 1077) ;
+ z10 = (-108, 1002) ;
+ z11 = (-129, 666) ;
+ z12 = (-117, 207) ;
+ z13 = (-197, 19) ;
+ z14 = (-208, 0) ;
+ z15 = (-197, -19) ;
+ z16 = (-117, -207) ;
+ z17 = (-129, -666) ;
+ z18 = (-108,-1026) ;
+ z19 = ( -80,-1077) ;
+ z20 = ( -61,-1104) ;
+ z21 = ( -71,-1125) ;
+ z22 = ( -97,-1106) ;
+ z23 = (-143,-1031) ;
+ z24 = (-199, -673) ;
+ z25 = (-155, -211) ;
+ z26 = (-220, -22) ;
+ p := z1 for i= 2 upto 14 : .. z[i] endfor
+ & z14 for j=15 upto 26 : .. z[j] endfor
+ .. z1
+ & cycle ;
+ p := p rotated rotation ;
+ p := p ysized 100 ;
+ p shifted - center p
+ enddef ;
+ vardef RawLeftBraceSymbol =
+ fill BasicBraceSymbol(0) ysized OverlayHeight withcolor OverlayColor ;
+ enddef ;
+ vardef RawRightBraceSymbol =
+ fill BasicBraceSymbol(180) ysized OverlayHeight withcolor OverlayColor ;
+ enddef ;
+ vardef RawTopBraceSymbol =
+ fill BasicBraceSymbol(270) xsized OverlayWidth withcolor OverlayColor ;
+ enddef ;
+ vardef RawBottomBraceSymbol =
+ fill BasicBraceSymbol(90) xsized OverlayWidth withcolor OverlayColor ;
+ enddef ;
+ vardef LeftBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(0) ysized OverlayHeight ;
+ fill p shifted (-xpart lrcorner currentpicture + xpart lrcorner p,0) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef RightBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(180) ysized OverlayHeight ;
+ fill p shifted (xpart lrcorner currentpicture - xpart lrcorner p,0) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef TopBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(270) xsized OverlayWidth ;
+ fill p shifted (0,ypart ulcorner currentpicture - ypart ulcorner p) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef BottomBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(90) xsized OverlayWidth ;
+ fill p shifted (0,ypart lrcorner currentpicture - ypart lrcorner p) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+\stopMPextensions
+
+\startuniqueMPgraphic{raw_brace_left} RawLeftBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_right} RawRightBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_top} RawTopBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_bottom} RawBottomBraceSymbol ; \stopuniqueMPgraphic
+
+\startuniqueMPgraphic{brace_left} LeftBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_right} RightBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_top} TopBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_bottom} BottomBraceSymbol ; \stopuniqueMPgraphic
+
+\defineoverlay[leftbrace] [\uniqueMPgraphic{brace_left}]
+\defineoverlay[rightbrace] [\uniqueMPgraphic{brace_right}]
+\defineoverlay[topbrace] [\uniqueMPgraphic{brace_top}]
+\defineoverlay[bottombrace][\uniqueMPgraphic{brace_bottom}]
+
+\installleftframerenderer {brace}{\uniqueMPgraphic{raw_brace_left}}
+\installrightframerenderer {brace}{\uniqueMPgraphic{raw_brace_right}}
+\installtopframerenderer {brace}{\uniqueMPgraphic{raw_brace_top}}
+\installbottomframerenderer{brace}{\uniqueMPgraphic{raw_brace_bottom}}
+
+\continueifinputfile{meta-imp-fen.mkiv}
+
+\starttext
+
+\startTEXpage[offset=10pt]
+
+ \framed
+ [offset=1ex,
+ leftframe=brace,
+ rightframe=brace,
+ topframe=brace,
+ bottomframe=brace,
+ background=color,
+ backgroundcolor=red]
+ {OEPS}
+
+\stopTEXpage
+
+\startTEXpage \uniqueMPgraphic{brace_left} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_right} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_top} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_bottom} \stopTEXpage
+
+\framedtext
+ [frame=off,
+ offset=2em,
+ background={leftbrace,rightbrace,topbrace,bottombrace},
+ backgroundcolor=red]{\input{knuth}}
+
+\setupTABLE[frame=off,offset=1ex]
+\setupTABLE[row][each][align={middle,lohi}]
+
+\bTABLE
+ \bTR
+ \bTD[nr=3,background=leftbrace] drei \eTD
+ \bTD[nr=2,background=leftbrace] zwei \eTD
+ \bTD f \eTD
+ \bTD o \eTD
+ \bTD u \eTD
+ \bTD r \eTD
+ \bTD [nr=3,background=rightbrace] three \eTD
+ \eTR
+ \bTR
+ \bTD [background=leftbrace] eins \eTD
+ \bTD [background={topbrace,bottombrace}] null \eTD
+ \bTD [background=rightbrace] one \eTD
+ \bTD [nr=2,background=rightbrace] two \eTD
+ \eTR
+ \bTR
+ \bTD v \eTD
+ \bTD i \eTD
+ \bTD e \eTD
+ \bTD r \eTD
+ \eTR
+\eTABLE
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-grid.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-grid.mkiv
new file mode 100644
index 00000000000..9208a3dae14
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-grid.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=meta-imp-grid,
+%D version=2016.01.08,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Grid Tracing,
+%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.
+
+\startMPextensions
+ color mfun_grid_lgc[] ;
+ numeric mfun_grid_lgi ;
+ mfun_grid_lgc[1] := red ;
+ mfun_grid_lgc[2] := green ;
+ mfun_grid_lgc[3] := blue ;
+ mfun_grid_lgi := 1 ;
+\stopMPextensions
+
+\startuseMPgraphic{linegrid}
+ % if unknown mfun_grid_lgi :
+ % color mfun_grid_lgc[] ;
+ % numeric mfun_grid_lgi ;
+ % mfun_grid_lgc[1] := red ;
+ % mfun_grid_lgc[2] := green ;
+ % mfun_grid_lgc[3] := blue ;
+ % mfun_grid_lgi := 1 ;
+ % elseif mfun_grid_lgi = 3 :
+ if mfun_grid_lgi = 3 :
+ mfun_grid_lgi := 1 ;
+ else :
+ mfun_grid_lgi := mfun_grid_lgi + 1 ;
+ fi ;
+ draw image (
+ save f, t ;
+ pair f, t ;
+ f := (0,-2*LineHeight) ;
+ t := (0, 2*LineHeight) ;
+ for i=ypart f - eps step LineHeight/5 until ypart t + eps:
+ draw (-EmWidth,i) -- (0,i) ;
+ endfor ;
+ draw f -- t ;
+ draw (-EmWidth,0) -- (EmWidth,0) ;
+ % ) shifted (-mfun_grid_lgi*EmWidth/3,0) withcolor mfun_grid_lgc[mfun_grid_lgi] ;
+ ) shifted (-EmWidth/2,0) withcolor mfun_grid_lgc[mfun_grid_lgi] ;
+ setbounds currentpicture to origin -- cycle ;
+\stopuseMPgraphic
+
+\unexpanded\def\showlinegrid{\dontleavehmode\smash{\useMPgraphic{linegrid}}}
+
+\continueifinputfile{meta-imp-grid.mkiv}
+
+\starttext
+
+\showlinegrid \input tufte \par
+\showlinegrid \input tufte \par
+\showlinegrid \input ward \par
+\showlinegrid \input ward \par
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mis.mkiv
new file mode 100644
index 00000000000..e8282c381b8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mis.mkiv
@@ -0,0 +1,54 @@
+%D \module
+%D [ file=meta-mis,
+%D version=2006.06.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Misc Test Graphics,
+%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
+
+% p/s 1/false 1/true 2/false 2/true
+%
+% MKII 8.5 8.0 8.8 8.5
+% MKIV 16.1 7.2 16.3 7.4
+
+\startuseMPgraphic{mptopdf-test}
+ prologues := 2;
+ mpprocset := 1 ;
+ fill fullcircle scaled 3cm withcolor red ;
+ fill fullcircle scaled 2cm withcolor green ;
+ fill fullcircle scaled 1cm withcolor blue ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+ fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+ fill fullcircle scaled 1cm withcolor cmyk(1,0,0,0) ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ draw fullcircle scaled 3cm dashed evenly ;
+ draw fullcircle scaled 2cm dashed withdots ;
+ draw origin withpen pencircle scaled 3mm;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+ fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+ fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+ fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+ currentpicture := currentpicture shifted (12cm,-4cm) ;
+ draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ % bug: shift
+ draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+ draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+ filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ % shade cannot handle shift
+ circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+ circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+ filldraw boundingbox currentpicture enlarged (-bbheight(currentpicture)/2+2.5mm) withpen pencircle scaled 1pt withcolor .5white ;
+\stopuseMPgraphic
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-nav.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-nav.mkiv
new file mode 100644
index 00000000000..45a31ba5ecf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-nav.mkiv
@@ -0,0 +1,65 @@
+%D \module
+%D [ file=meta-nav,
+%D version=2003.03.28,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Navigational Graphics,
+%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.
+
+\startuniqueMPgraphic{navplus}{size,color,type,mode}
+ color c ; numeric s, t ; path p ;
+ t := \MPvar{type} ; c := \MPvar{color} ; s := \MPvar{size} ;
+ if \MPvar{mode} = 1 : c := .5[c,white] fi ;
+ if t = 1 :
+ p := ((0,0)--(1/2,0)--(1,1/3)--(1,1)--(0,1)--(0,0)--cycle)
+ xyscaled (3,4) ;
+ elseif t = 2 :
+ p := ((0,0)--(1,0)--(1,1)--(0,1)--(1/2,2/5)--(1,1)--(0,1)--cycle)
+ xyscaled (4,3) ;
+ else :
+ p := fullsquare xyscaled (3,3) ;
+ fi ;
+ draw p withpen pencircle scaled (1/2) withcolor .75white ;
+ fill p withcolor c ;
+ draw p withpen pencircle scaled (1/3) withcolor .5c ;
+ currentpicture := currentpicture scaled s ;
+ currentpicture := currentpicture shifted -center currentpicture ;
+\stopuniqueMPgraphic
+
+\setupMPvariables
+ [navplus]
+ [size=1ex,
+ color=black,
+ type=1,
+ mode=0]
+
+\definepalet
+ [navplus]
+ [attach=darkred,
+ comment=darkblue]
+
+\definesymbol
+ [comment-normal]
+ [\uniqueMPgraphic{navplus}{type=1,color=navplus:comment}]
+\definesymbol
+ [comment-down]
+ [\uniqueMPgraphic{navplus}{type=1,color=navplus:comment,mode=1}]
+
+\definesymbol
+ [attach-normal]
+ [\uniqueMPgraphic{navplus}{type=2,color=navplus:attach}]
+\definesymbol
+ [attach-down]
+ [\uniqueMPgraphic{navplus}{type=2,color=navplus:attach,mode=1}]
+
+\unprotect
+
+\setupcomment [\c!symbol={comment-normal,comment-down}]
+\setupattachments[\c!symbol={attach-normal,attach-down}]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-outlines.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-outlines.mkiv
new file mode 100644
index 00000000000..7d74950371f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-outlines.mkiv
@@ -0,0 +1,176 @@
+%D \module
+%D [ file=meta-imp-outlines,
+%D version=2015.06.02,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Outlines,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startluacode
+
+local concat = table.concat
+local formatters = string.formatters
+local validstring = string.valid
+
+local f_setbounds = formatters["setbounds currentpicture to (%s) enlarged %.4G;"]
+local f_index = formatters['draw anchored.bot(textext("\\tttf\\setstrut\\strut index %i") ysized 2bp ,.5[llcorner currentpicture,lrcorner currentpicture] shifted (0,%.4G));']
+local f_unicode = formatters['draw anchored.bot(textext("\\tttf\\setstrut\\strut unicode %05X") ysized 2bp ,.5[llcorner currentpicture,lrcorner currentpicture] shifted (0,%.4G));']
+
+local f_in_red = formatters["draw %s withpen pencircle scaled .15 withcolor .5red;"]
+local f_in_green = formatters["draw %s withpen pencircle scaled .15 withcolor .5green;"]
+local f_in_blue = formatters["draw %s withpen pencircle scaled .15 withcolor .5blue;"]
+local f_in_gray = formatters["draw image(%s) withcolor .75yellow;"]
+
+local f_glyph = formatters [ [[
+pickup pencircle scaled .15;
+pointlabelfont := "Mono sa .125";
+pointlabelscale := 1bp ;
+drawoptionsfactor := .2bp ;
+originlength := 2bp ;
+%s;
+]] ]
+
+local metapost = fonts.metapost
+
+local variables = interfaces.variables
+
+local v_all = variables.all
+local v_page = variables.page
+local v_text = variables.text
+local v_command = variables.command
+
+function metapost.showglyph(specification)
+ local fontid = font.current()
+ local shapedata = fonts.hashes.shapes[fontid] -- by index
+ local chardata = fonts.hashes.characters[fontid] -- by unicode
+ local shapeglyphs = shapedata.glyphs
+ local character = validstring(specification.character)
+ local index = validstring(specification.index)
+ local alternative = validstring(specification.alternative)
+ local command = validstring(specification.command)
+
+ local function shape(index,what,f_comment)
+ if not index then
+ return
+ end
+ local glyph = shapeglyphs[index]
+ if glyph and (glyph.segments or glyph.sequence) then
+ local units = data.fontheader and data.fontheader.emsize or 1000
+ local factor = 100/units
+ local paths = metapost.paths(glyph,factor)
+ if #paths > 0 then
+ local graphic = f_glyph(concat{
+ f_in_gray(metapost.fill(paths)),
+ metapost.draw(paths,true), -- true triggers trace
+ f_in_red(metapost.boundingbox(glyph,factor)),
+ f_in_green(metapost.widthline(glyph,factor)),
+ f_in_blue(metapost.zeroline(glyph,factor)),
+ f_setbounds(metapost.maxbounds(data,index,factor),offset or 1),
+ f_comment(what,1)
+ })
+ if alternative == v_page then
+ context.startMPpage()
+ context(graphic)
+ context.stopMPpage()
+ elseif alternative == v_command then
+ context[command](graphic)
+ else -- v_text
+ context.startMPcode()
+ context(graphic)
+ context.stopMPcode()
+ end
+ end
+ end
+ end
+
+ if character == v_all then
+ for u, c in table.sortedhash(chardata) do
+ shape(c.index,u,f_unicode)
+ end
+ return
+ end
+ if type(character) == "string" then
+ character = utf.byte(character)
+ end
+ if type(character) == "number" then
+ local c = chardata[character]
+ if c then
+ shape(c.index,c.index,f_index)
+ end
+ return
+ end
+ if type(index) == "number" then
+ shape(index,index,f_index)
+ return
+ end
+ local first, last
+ if type(index) == "string" then
+ first, last = string.match(index,"^(.-):(.*)$")
+ if first and last then
+ first = tonumber(first)
+ last = tonumber(last)
+ else
+ first = tonumber(index)
+ last = first
+ end
+ if not first then
+ first = 1
+ last = #shapeglyphs
+ elseif not last then
+ last = first
+ end
+ else
+ first = 1
+ last = #shapeglyphs
+ end
+ for index=first,last do
+ shape(index,index,f_index)
+ end
+end
+
+\stopluacode
+
+\unprotect
+
+\unexpanded\def\showshape
+ {\dosingleargument\meta_shapes_show}
+
+\def\meta_shapes_show[#1]%
+ {\begingroup
+ \getdummyparameters[\c!alternative=\v!text,#1]%
+ \ctxlua{fonts.metapost.showglyph{
+ character = "\dummyparameter\c!character",
+ index = "\dummyparameter\c!index",
+ alternative = "\dummyparameter\c!alternative",
+ command = "\dummyparameter\c!command",
+ }}%
+ \endgroup}
+
+\protect
+
+\continueifinputfile{meta-imp-outlines.mkiv}
+
+\starttext
+
+% \setupbodyfont[pagella]
+
+% \definedfont[latinmodern-math]\showshape[index=3078,alternative=page]
+
+% \setupbodyfont[pagella]
+% \showshape[character=all,alternative=page]
+
+\setupbodyfont[dejavu]
+\showshape[character=P,alternative=text]
+
+% \definedfont[almfixed]
+% \showshape[character=all,alternative=page]
+
+% \definedfont[file:sourcehansans-bold.otf]
+% \showshape[index=40000:41000,alternative=page]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-pre.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-pre.mkiv
new file mode 100644
index 00000000000..098be030b19
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-pre.mkiv
@@ -0,0 +1,68 @@
+%D \module
+%D [ file=meta-pre,
+%D version=2001.03.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Predefined Goodies,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In this library, we define a couple of handy graphics.
+
+% todo: use the predefine grid macros, mp code will move to
+% mp-* file
+
+\startuseMPgraphic{pagegrid}
+ StartPage ;
+ drawoptions(withcolor .8white) ;
+ fill Field[Text][Text] ;
+ drawoptions(withcolor .65white) ;
+ fill Field[Footer][Text] ;
+ fill Field[Header][Text] ;
+ fill Field[LeftMargin][Text] ;
+ fill Field[RightMargin][Text] ;
+ drawoptions(withcolor .65yellow) ;
+ fill Field[LeftEdge][Text] ;
+ fill Field[RightEdge][Text] ;
+ fill Field[Bottom][Text] ;
+ fill Field[Top][Text] ;
+ drawoptions(withpen pencircle scaled .3pt withcolor .65white) ;
+ for i=-3cm step 1cm until PaperWidth+3cm :
+ draw (i,-3cm)--(i,PaperHeight+3cm) ;
+ endfor ;
+ for i=PaperHeight+3cm step -1cm until -3cm :
+ draw (-3cm,i)--(PaperWidth+3cm,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .15pt) ;
+ for i=.5cm-3cm step 1cm until PaperWidth+3cm :
+ draw (i,-3cm)--(i,PaperHeight+3cm) ;
+ endfor ;
+ for i=PaperHeight-.5cm+3cm step -1cm until -3cm :
+ draw (-3cm,i)--(PaperWidth+3cm,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .3pt withcolor .65red) ;
+ for i=0 step 1cm until PaperWidth :
+ draw (i,0)--(i,PaperHeight) ;
+ endfor ;
+ for i=PaperHeight step -1cm until 0 :
+ draw (0,i)--(PaperWidth,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .15pt withcolor .65red) ;
+ for i=.5cm step 1cm until PaperWidth :
+ draw (i,0)--(i,PaperHeight) ;
+ endfor ;
+ for i=PaperHeight-.5cm step -1cm until 0 :
+ draw (0,i)--(PaperWidth,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled 5pt withcolor .65red) ;
+ draw ulcorner Page ;
+ StopPage ;
+\stopuseMPgraphic
+
+\defineoverlay[pagegrid][\useMPgraphic{pagegrid}]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-tab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-tab.mkiv
new file mode 100644
index 00000000000..a4affbea458
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-tab.mkiv
@@ -0,0 +1,73 @@
+%D \module
+%D [ file=meta-tab,
+%D version=2003.03.21, % very old but now with splitter
+%D title=\METAPOST\ Graphics,
+%D subtitle=Dummy (External) Graphics,
+%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.
+
+\startuseMPgraphic{TallyBar}
+ height := (10/12) * LineHeight ;
+ span := ( 4/10) * LineHeight ;
+ drift := ( 1/10) * LineHeight ;
+ def d = (uniformdeviate drift) enddef ;
+ for i := 1 upto \MPvar{n} :
+ draw
+ if (i mod 5)=0 :
+ ((-d-4.5span,d)--(+d-0.5span,height-d))
+ else :
+ ((-d,+d)--(+d,height-d))
+ fi
+ shifted (span*i,d-drift) withpen pencircle ;
+ endfor ;
+ currentpicture := currentpicture scaled .75 ;
+\stopuseMPgraphic
+
+\setupMPvariables
+ [TallyBar]
+ [n=0]
+
+\unexpanded\def\tallynumeral#1%
+ {\dontleavehmode
+ \lower.25\exheight\hbox{\useMPgraphic{TallyBar}{n=#1}}}
+
+\unexpanded\def\tallynumerals#1%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter#1\relax
+ \doloop
+ {\ifnum\scratchcounter>\plusfive
+ \lower.25\exheight\hbox{\useMPgraphic{TallyBar}{n=5}}%
+ \advance\scratchcounter-\plusfive
+ \space
+ \else
+ \lower.25\exheight\hbox{\useMPgraphic{TallyBar}{n=\the\scratchcounter}}%
+ \exitloop
+ \fi}%
+ \endgroup}
+
+\let\FunnyBar\tallynumeral
+
+\defineconversion[tally][\tallynumerals]
+
+\continueifinputfile{meta-imp-tab.mkiv}
+
+\starttext
+
+ \starttabulate[|pr|c|]
+ \NC \tallynumerals {24} \NC \NR
+ \NC \tallynumerals {12} \NC \times \NR
+ \HL
+ \NC \tallynumerals{288} \NC = \NR
+ \stoptabulate
+
+ \tallynumerals{"FFFF}
+
+\stoptext
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv
new file mode 100644
index 00000000000..7069d21a4ea
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv
@@ -0,0 +1,337 @@
+%D \module
+%D [ file=meta-txt,
+%D version=2000.07.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Text Tricks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In this library some handy text manipulations are
+%D defined. Some can and will be improved as soon as the
+%D \TEX||\METAPOST\ interface is stable. Some of the
+%D solutions may look weird, which is entirely my fault,
+%D since I implemented them in the process of getting grip
+%D on this kind of manipulations. Undoubtly better
+%D \METAPOST\ code is possible, but my way of learning
+%D this kind of trickery happens to be by \quote {trial
+%D and error} and \quote {look and feel} (as well as
+%D identifying tricks in Hobby's code).
+
+% textext ipv btex ... etex
+
+% we need a proper prefix here
+
+\unprotect
+
+\definesystemvariable {sh} % ShapedText .. todo: commandhandler
+
+\startMPextensions
+ if unknown context_text: input "mp-text.mpiv" ; fi;
+\stopMPextensions
+
+%%%%%%%
+
+% \def\newchar#1{\chardef#1=0 }
+
+\ifdefined\MPtoks \else \newtoks\MPtoks \fi
+\ifdefined\MPbox \else \newbox \MPbox \fi
+
+\ifdefined\parwidth \else \newdimen\parwidth \fi
+\ifdefined\parheight \else \newdimen\parheight \fi
+\ifdefined\parvoffset \else \newdimen\parvoffset \fi
+\ifdefined\parhoffset \else \newdimen\parhoffset \fi
+\ifdefined\parlines \else \newcount\parlines \fi
+\ifdefined\partoks \else \newtoks \partoks \fi
+\ifdefined\shapetextbox \else \newbox \shapetextbox \fi
+ \newif \ifparseries
+\ifdefined\parfirst \else \chardef \parfirst=0 \fi
+
+\unexpanded\def\startshapetext[#1]%
+ {\global\newcounter\currentshapetext
+ \global\setbox\shapetextbox\vbox\bgroup
+ \expanded{\switchtobodyfont[\@@shbodyfont]}%
+ \dontcomplain
+ \hsize\parwidth
+ \setuptolerance[\v!verytolerant,\v!stretch]%
+ \!!counta\zerocount
+ \!!toksa\emptytoks
+ \def\docommand##1%
+ {\setbox\scratchbox\hbox{\useMPgraphic{##1}}%
+ \global\chardef\parfirst\zerocount
+ \getMPdata % \readlocfile{\MPdatafile}{}{}%
+ \setshapecharacteristics
+ \advance\!!counta by \parlines
+ \expandafter\appendtoks\the\partoks\to\!!toksa}%
+ \processcommalist[#1]\docommand
+ \global\parseriestrue
+ \xdef\totalparlines{\the\!!counta}%
+ \global\partoks\!!toksa
+ %\ifx\partoks\emptytoks\else % safeguard
+ \expanded{\parshape \the\!!counta \the\!!toksa}%
+ %\fi
+ \setshapecharacteristics % extra dummy
+ \ifparseries\def\par{\endgraf\adaptparshape}\fi
+ \EveryPar{\begstrut}}
+
+\unexpanded\def\stopshapetext
+ {\endstrut
+ %\removebottomthings
+ \egroup
+ \global\newcounter\currentshapetext
+ \getshapecharacteristics}
+
+\unexpanded\def\adaptparshape
+ {\def\docommand##1%
+ {\ifcase\!!counta
+ \expandafter\appendtoks\space##1 \to\!!toksa
+ \else
+ \advance\!!counta \minusone
+ \fi}%
+ \!!counta\prevgraf
+ \doglobal\decrement(\totalparlines,\!!counta)%
+ \multiply\!!counta \plustwo
+ \!!toksa\emptytoks
+ \expanded{\processseparatedlist[\the\partoks][\space]}\docommand
+ \global\partoks\!!toksa
+ %\ifx\partoks\emptytoks\else % safeguard
+ \expanded{\parshape\totalparlines\the\partoks}%
+ }%\fi}
+
+\unexpanded\def\getshapecharacteristics
+ {\doglobal\increment\currentshapetext
+ \doifelsedefined{parlines:\currentshapetext}
+ {\global\parlines \getvalue{parlines:\currentshapetext}%
+ \global\chardef\parfirst \getvalue{parfirst:\currentshapetext}%
+ \global\parvoffset \getvalue{parvoffset:\currentshapetext}%
+ \global\parhoffset \getvalue{parhoffset:\currentshapetext}%
+ \global\parwidth \getvalue{parwidth:\currentshapetext}%
+ \global\parheight \getvalue{parheight:\currentshapetext}}
+ {\global\parlines \plusone
+ \global\chardef\parfirst \zerocount
+ \global\parvoffset \zeropoint
+ \global\parhoffset \zeropoint
+ \global\parwidth \hsize
+ \global\parheight \vsize}}
+
+\unexpanded\def\setshapecharacteristics
+ {\doglobal\increment\currentshapetext
+ \setxvalue{parlines:\currentshapetext }{\the\parlines}%
+ \setxvalue{parfirst:\currentshapetext }{\the\parfirst}%
+ \setxvalue{parvoffset:\currentshapetext}{\the\parvoffset}%
+ \setxvalue{parhoffset:\currentshapetext}{\the\parhoffset}%
+ \setxvalue{parwidth:\currentshapetext }{\the\parwidth}%
+ \setxvalue{parheight:\currentshapetext }{\the\parheight}}
+
+\unexpanded\def\getshapetext % option: unvbox
+ {\vbox\bgroup
+ \forgetall
+ \setbox\scratchbox\vbox to \parheight
+ {\expanded{\switchtobodyfont[\@@shbodyfont]}% evt strutheight en
+ \splittopskip\strutheight % lineheight opslaan
+ \vskip\parvoffset % scheelt switch en
+ \ifcase\parfirst\or\vskip\lineheight\fi % is ook veiliger
+ \hskip\parhoffset
+ \hbox{\vsplit\shapetextbox to \parlines\lineheight}}%
+ \wd\scratchbox\parwidth
+ \ht\scratchbox\parheight
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \getshapecharacteristics
+ \egroup}
+
+\unexpanded\def\setupshapetexts
+ {\dodoubleempty\getparameters[\??sh]}
+
+\setupshapetexts
+ [\c!bodyfont=]
+
+%%%%%%% rotfont nog definieren
+
+\doifundefined{RotFont}{\definefont[RotFont][RegularBold*default]}
+
+\unexpanded\def\processfollowingtoken#1% strut toegevoegd
+ {\appendtoks#1\to\MPtoks
+ \setbox\MPbox=\hbox{\RotFont\setstrut\strut\the\MPtoks}%
+ \startMPdrawing
+ n := n + 1 ; len[n] := \the\wd\MPbox ;
+ \stopMPdrawing
+ \startMPdrawing[-]
+ % pic[n] := textext{\RotFont\setstrut\strut#1} ; % btex \RotFont\setstrut\strut#1 etex ;
+ pic[n] := btex \RotFont\setstrut\strut#1 etex ;
+ pic[n] := pic[n] shifted - llcorner pic[n] ;
+ \stopMPdrawing}
+
+\startuseMPgraphic{followtokens}
+ % we default to nothing
+\stopuseMPgraphic
+
+\unexpanded\def\dofollowtokens#1#2%
+ {\vbox\bgroup
+ \forgetall
+ \dontcomplain
+ \doifundefined{RotFont}{\definefont[RotFont][RegularBold*default]}%
+ \MPtoks\emptytoks
+ \resetMPdrawing
+ \startMPdrawing
+ \includeMPgraphic{followtokens} ;
+ picture pic[] ; numeric len[], n ; n := 0 ;
+ \stopMPdrawing
+ \handletokens#2\with\processfollowingtoken
+ \startMPdrawing
+ if unknown RotPath : path RotPath ; RotPath := origin ; fi ;
+ if unknown RotColor : color RotColor ; RotColor := black ; fi ;
+ if unknown TraceRot : boolean TraceRot ; TraceRot := false ; fi ;
+ if unknown ExtraRot : numeric ExtraRot ; ExtraRot := 0 ; fi ;
+ numeric al, at, pl, pc, wid, pos ; pair ap, ad ;
+ al := arclength RotPath ;
+ if al=0 :
+ al := len[n] + ExtraRot ;
+ RotPath := origin -- (al,0) ;
+ fi ;
+ if al<len[n]:
+ RotPath := RotPath scaled ((len[n]+ExtraRot)/al) ;
+ al := arclength RotPath ;
+ fi ;
+ if \number#1 = 1 :
+ pl := (al-len[n])/(if n>1 : (n-1) else : 1 fi) ;
+ pc := 0 ;
+ else : % centered / MP
+ pl := 0 ;
+ pc := arclength RotPath/2 - len[n]/2 ;
+ fi ;
+ if TraceRot :
+ draw RotPath withpen pencircle scaled 1pt withcolor blue ;
+ fi ;
+ for i=1 upto n :
+ wid := abs(xpart urcorner pic[i] - xpart llcorner pic[i]) ;
+ pos := len[i]-wid/2 + (i-1)*pl + pc ;
+ at := arctime pos of RotPath ;
+ ap := point at of RotPath ;
+ ad := direction at of RotPath ;
+ draw pic[i] shifted (-wid/2,0) rotated(angle(ad)) shifted ap
+ withcolor RotColor ;
+ if TraceRot :
+ draw boundingbox
+ pic[i] shifted (-wid/2,0) rotated(angle(ad)) shifted ap
+ withpen pencircle scaled .25pt withcolor red ;
+ draw ap
+ withpen pencircle scaled .50pt withcolor green ;
+ fi ;
+ endfor ;
+% fill boundingbox currentpicture ;
+ \stopMPdrawing
+ \MPdrawingdonetrue
+ \getMPdrawing
+ \resetMPdrawing
+ \egroup}
+
+\unexpanded\def\followtokens {\dofollowtokens1}
+\unexpanded\def\followtokenscentered{\dofollowtokens0}
+
+% stretched variant:
+%
+% \followtokens
+% {This is just a dummy text, kerned by T{\kern
+% -.1667em\lower .5ex\hbox {E}}{\kern -.125emX} and typeset
+% in a circle using {\setMFPfont M}{\setMFPfont
+% E}{\setMFPfont T}{\setMFPfont A}{\setMFPfont
+% P}{\setMFPfont O}{\setMFPfont S}{\setMFPfont T}.\quad}
+
+% centered variant:
+%
+% \def\followtokengraphicscale#1{%%
+% \startuseMPgraphic {followtokens}
+% path RotPath; RotPath := reverse halfcircle scaled #1 ;
+% draw RotPath ;
+% setbounds currentpicture to boundingbox fullcircle scaled 12cm ;
+% \stopuseMPgraphic}
+%
+% \startoverlay
+% {\followtokengraphicscale{12cm}%%
+% \followtokenscentered{There was question on the list about this kind of graphics.}}
+% {\followtokengraphicscale{10cm}%%
+% \followtokenscentered{And Marco patched followingtokens to handle a centered text.}}
+% {\followtokengraphicscale{8cm}%%
+% \followtokenscentered{That ended up as variant branch in the main macro.}}
+% {\followtokengraphicscale{6cm}%%
+% \followtokenscentered{So now we have two commands.}}
+% \stopoverlay
+
+
+\startuseMPgraphic{fuzzycount}
+ begingroup
+ save height, span, drift, d, cp ;
+ height := 3/ 5 * \baselinedistance ;
+ span := 1/ 3 * height ;
+ drift := 1/10 * height ;
+ pickup pencircle scaled (1/12 * height) ;
+ def d = (uniformdeviate drift) enddef ;
+ for i := 1 upto \MPvar{n} :
+ draw
+ if (i mod 5)=0 : ((-d-4.5span,d)--(+d-0.5span,height-d))
+ else : ((-d,+d)--(+d,height-d)) fi
+ shifted (span*i,d-drift) ;
+ endfor;
+ picture cp ; cp := currentpicture ; % for readability
+ setbounds currentpicture to
+ (llcorner cp shifted (0,-ypart llcorner cp) --
+ lrcorner cp shifted (0,-ypart lrcorner cp) --
+ urcorner cp -- ulcorner cp -- cycle) ;
+ endgroup ;
+\stopuseMPgraphic
+
+\setupMPvariables
+ [fuzzycount]
+ [n=10]
+
+\def\fuzzycount#1%
+ {{\tx\useMPgraphic{fuzzycount}{n=#1}}}
+
+\defineconversion[fuzzy][\fuzzycount]
+
+%%%%%%%
+
+\setupMPvariables
+ [EnglishRule]
+ [height=1ex,
+ width=\the\localhsize, % without \the, problems in non e-tex
+ color=darkgray]
+
+\defineblank
+ [EnglishRule]
+ [medium]
+
+\startuniqueMPgraphic{EnglishRule}{height,width,color}
+ height = \MPvar{height} ;
+ x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ;
+ y1 = y3 = 0 ; y2 = -y4 = height/2 ;
+ fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ;
+\stopuniqueMPgraphic
+
+\unexpanded\def\EnglishRule
+ {\startlinecorrection[EnglishRule]
+ \setlocalhsize \noindent \reuseMPgraphic{EnglishRule}
+ \stoplinecorrection}
+
+%D The following macro returns a tight bound character
+%D sequence.
+%D
+%D \useMPlibrary[txt]
+%D
+%D \startlinecorrection
+%D \TightText{\ss\bf 123}{0cm}{3cm}{red}
+%D \stoplinecorrection
+
+\unexpanded\def\TightText#1#2#3#4%
+ {\hbox % \ruledhbox
+ {\startMPcode
+ picture p ; p := image (graphictext "#1" withfillcolor red) ;
+ draw p xsized #2 ysized #3 withcolor \MPcolor{#4} ;
+ \stopMPcode}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua
new file mode 100644
index 00000000000..8f713126323
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua
@@ -0,0 +1,137 @@
+if not modules then modules = { } end modules ['meta-ini'] = {
+ version = 1.001,
+ comment = "companion to meta-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 = string.format
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, Cs, R, S, C, Cc = lpeg.P, lpeg.Cs, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc
+
+local context = context
+
+metapost = metapost or { }
+
+-- experimental
+
+local colorhash = attributes.list[attributes.private('color')]
+
+local textype = tex.type
+local MPcolor = context.MPcolor
+
+-- local validdimen = lpegpatterns.validdimen * P(-1)
+--
+-- function commands.prepareMPvariable(v) -- slow but ok
+-- if v == "" then
+-- MPcolor("black")
+-- else
+-- local typ, var = match(v,"(.):(.*)")
+-- if not typ then
+-- -- parse
+-- if colorhash[v] then
+-- MPcolor(v)
+-- elseif tonumber(v) then
+-- context(v)
+-- elseif lpegmatch(validdimen,v) then
+-- return context("\\the\\dimexpr %s",v)
+-- else
+-- for s in gmatch(v,"\\([a-zA-Z]+)") do -- can have trailing space
+-- local t = textype(s)
+-- if t == "dimen" then
+-- return context("\\the\\dimexpr %s",v)
+-- elseif t == "count" then
+-- return context("\\the\\numexpr %s",v)
+-- end
+-- end
+-- context("\\number %s",v) -- 0.4 ...
+-- end
+-- elseif typ == "d" then -- to be documented
+-- -- dimension
+-- context("\\the\\dimexpr %s",var)
+-- elseif typ == "n" then -- to be documented
+-- -- number
+-- context("\\the\\numexpr %s",var)
+-- elseif typ == "s" then -- to be documented
+-- -- string
+-- context(var)
+-- elseif typ == "c" then -- to be documented
+-- -- color
+-- MPcolor(var)
+-- else
+-- context(var)
+-- end
+-- end
+-- end
+
+-- we can actually get the dimen/count values here
+
+local dimenorname =
+ lpegpatterns.validdimen / function(s)
+ context("\\the\\dimexpr %s",s)
+ end
+ + (C(lpegpatterns.float) + Cc(1)) * lpegpatterns.space^0 * P("\\") * C(lpegpatterns.letter^1) / function(f,s)
+ local t = textype(s)
+ if t == "dimen" then
+ context("\\the\\dimexpr %s\\%s",f,s)
+ elseif t == "count" then
+ context("\\the\\numexpr \\%s * %s\\relax",s,f) -- <n>\scratchcounter is not permitted
+ end
+ end
+
+local splitter = lpeg.splitat(":",true)
+
+function commands.prepareMPvariable(v) -- slow but ok
+ if v == "" then
+ MPcolor("black")
+ else
+ local typ, var = lpegmatch(splitter,v)
+ if not var then
+ -- parse
+ if colorhash[v] then
+ MPcolor(v)
+ elseif tonumber(v) then
+ context(v)
+ elseif not lpegmatch(dimenorname,v) then
+ context("\\number %s",v) -- 0.4 ...
+ end
+ elseif typ == "d" then -- to be documented
+ -- dimension
+ context("\\the\\dimexpr %s",var)
+ elseif typ == "n" then -- to be documented
+ -- number
+ context("\\the\\numexpr %s",var)
+ elseif typ == "s" then -- to be documented
+ -- string
+ context(var)
+ elseif typ == "c" then -- to be documented
+ -- color
+ MPcolor(var)
+ else
+ context(var)
+ end
+ end
+end
+
+-- function metapost.formatnumber(f,n) -- just lua format
+-- f = gsub(f,"@(%d)","%%.%1")
+-- f = gsub(f,"@","%%")
+-- f = format(f,tonumber(n) or 0)
+-- f = gsub(f,"e([%+%-%d]+)",function(s)
+-- return format("\\times10^{%s}",tonumber(s) or s) -- strips leading zeros
+-- end)
+-- context.mathematics(f)
+-- end
+
+-- formatters["\\times10^{%N}"](s) -- strips leading zeros too
+
+local one = Cs((P("@")/"%%." * (R("09")^1) + P("@")/"%%" + 1)^0)
+local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1) / function(s) return format("\\times10^{%s}",tonumber(s) or s) end) + 1)^1)
+
+-- local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1) / formatters["\\times10^{%N}"]) + 1)^1)
+
+function metapost.formatnumber(fmt,n) -- just lua format
+ context.mathematics(lpegmatch(two,format(lpegmatch(one,fmt),n)))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv
new file mode 100644
index 00000000000..9f53aea69f6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv
@@ -0,0 +1,1567 @@
+%D \module
+%D [ file=meta-ini,
+%D version=2008.03.25,
+%D title=\METAPOST\ Graphics,
+%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.
+
+% initializations:
+%
+% - pass settings from tex to mp (delayed expansion)
+% - used by context core (and modules)
+% - cummulative definitions
+% - flushed each graphic
+% - can be disabled per instance
+% - managed at the tex end
+%
+% extensions:
+%
+% - add mp functionality (immediate expansion)
+% - cummulative
+% - all instances or subset of instances
+% - can be disabled per instance
+% - managed at the lua/mp end
+% - could be managed at the tex end but no real reason and also messy
+%
+% definitions:
+%
+% - add mp functionality (delayed expansion)
+% - cummulative
+% - per instance
+% - managed at the tex end
+%
+% inclusions:
+%
+% - add mp functionality (delayed expansion)
+% - cummulative only when [+]
+% - per instance
+% - managed at the tex end
+%
+% order of execution:
+%
+% definitions
+% extensions
+% inclusions
+% beginfig
+% initializations
+% graphic
+% endfig
+
+% The instance will be implemented stepwise ... I should redo some code in order to
+% make the macros look better than they do now.
+
+\writestatus{loading}{MetaPost Graphics / Initializations}
+
+\registerctxluafile{meta-ini}{1.001}
+
+\unprotect
+
+\newtoks \everyMPgraphic % mp % public or not ?
+
+\appendtoks
+ \restoreendofline % see interferences-001.tex
+\to \everyMPgraphic
+
+\def\MPruntimefile {mprun}
+\def\currentMPformat {metafun}
+\def\defaultMPinstance{metafun}
+
+%installcorenamespace{graphicvariable} % todo
+\installcorenamespace{mpinstance}
+\installcorenamespace{mpinclusions}
+\installcorenamespace{mpdefinitions}
+\installcorenamespace{mpgraphic}
+\installcorenamespace{mpstaticgraphic}
+\installcorenamespace{mpclip}
+
+\newtoks \t_meta_initializations % tex, each
+\def \t_meta_inclusions {\csname\??mpinclusions \currentMPinstance\endcsname} % token register
+\def \t_meta_definitions {\csname\??mpdefinitions\currentMPinstance\endcsname} % token register
+
+% The next command is, of course, dedicated to Mojca, who
+% needs it for gnuplot. Anyway, the whole multiple engine
+% mechanism is to keep her gnuplot from interfering.
+
+\unexpanded\def\startMPdefinitions
+ {\dosinglegroupempty\meta_start_definitions}
+
+\def\meta_start_definitions#1#2\stopMPdefinitions
+ {\let\m_meta_saved_instance\currentMPinstance
+ \edef\currentMPinstance{#1}%
+ \ifx\currentMPinstance\empty
+ \let\currentMPinstance\defaultMPinstance
+ \fi
+ \global\t_meta_definitions\expandafter{\the\t_meta_definitions#2}%
+ \let\currentMPinstance\m_meta_saved_instance}
+
+\let\stopMPdefinitions\relax
+
+\unexpanded\def\startMPextensions
+ {\dosinglegroupempty\meta_start_extensions}
+
+\def\meta_start_extensions#1#2\stopMPextensions % we could use buffers instead
+ {\clf_setmpextensions{#1}{#2}}
+
+\let\stopMPextensions\relax
+
+\unexpanded\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled
+ {\global\t_meta_initializations\expandafter{\the\t_meta_initializations#1}}
+
+\let\stopMPinitializations\relax
+
+\unexpanded\def\startMPinclusions
+ {\dosingleempty\meta_start_inclusions}
+
+\unexpanded\def\meta_start_inclusions[#1]%
+ {\edef\m_meta_option{#1}%
+ \dosinglegroupempty\meta_start_inclusions_indeed}
+
+\def\meta_start_inclusions_indeed#1#2\stopMPinclusions
+ {\let\m_meta_saved_instance\currentMPinstance
+ \edef\currentMPinstance{#1}%
+ \ifx\currentMPinstance\empty
+ \let\currentMPinstance\defaultMPinstance
+ \fi
+ \ifx\m_meta_option\!!plustoken \else
+ \global\t_meta_inclusions\emptytoks
+ \fi
+ \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}%
+ \let\currentMPinstance\m_meta_saved_instance}
+
+\let\stopMPinclusions\relax
+
+\unexpanded\def\MPinclusions
+ {\dosingleempty\meta_inclusions}
+
+\def\meta_inclusions[#1]%
+ {\edef\m_meta_option{#1}%
+ \dosinglegroupempty\meta_inclusions_indeed}
+
+\def\meta_inclusions_indeed#1#2%
+ {\let\m_meta_saved_instance\currentMPinstance
+ \edef\currentMPinstance{#1}%
+ \ifx\currentMPinstance\empty
+ \let\currentMPinstance\defaultMPinstance
+ \fi
+ \ifx\m_meta_option\!!plustoken \else
+ \global\t_meta_inclusions\emptytoks
+ \fi
+ \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}%
+ \let\currentMPinstance\m_meta_saved_instance}
+
+% \def\meta_preset_definitions
+% {\edef\overlaywidth {\overlaywidth \space}%
+% \edef\overlayheight {\overlayheight \space}%
+% \edef\overlaylinewidth{\overlaylinewidth\space}}
+
+\let\meta_preset_definitions\relax
+
+\installcommandhandler \??mpinstance {MPinstance} \??mpinstance
+
+\setupMPinstance
+ [\s!format=metafun,
+ \s!extensions=\v!no,
+ \s!initializations=\v!no,
+ \c!method=\s!default,
+ \c!textstyle=,
+ \c!textcolor=]
+
+\appendtoks
+ \ifcsname\??mpdefinitions\currentMPinstance\endcsname \else
+ \expandafter\newtoks\csname\??mpdefinitions\currentMPinstance\endcsname
+ \fi
+ \ifcsname\??mpinclusions\currentMPinstance\endcsname \else
+ \expandafter\newtoks\csname\??mpinclusions\currentMPinstance\endcsname
+ \fi
+ \t_meta_definitions\emptytoks % in case we redefine
+ \t_meta_inclusions \emptytoks % in case we redefine
+\to \everydefineMPinstance
+
+\unexpanded\def\resetMPinstance[#1]%
+ {\writestatus\m!metapost{reset will be implemented when needed}}
+
+\def\meta_analyze_graphicname[#1]%
+ %{\normalexpanded{\meta_analyze_graphicname_indeed[#1::::]}}
+ {\normalexpanded{\meta_analyze_graphicname_indeed[#1}::::]}
+
+\def\meta_show_properties_indeed
+ {\writestatus{metapost}{name: \currentMPgraphicname, instance: \currentMPinstance, format: \currentMPformat}}
+
+\let\meta_show_properties\donothing
+
+\installtextracker
+ {metapost.properties}
+ {\let\meta_show_properties\meta_show_properties_indeed}
+ {\let\meta_show_properties\donothing}
+
+\unexpanded\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance ::
+ {\edef\currentMPgraphicname{#2}%
+ \ifx\currentMPgraphicname\empty
+ \edef\currentMPgraphicname{#1}%
+ \let\currentMPinstance\defaultMPinstance
+ \else\ifcsname\??mpdefinitions#1\endcsname
+ \edef\currentMPinstance{#1}%
+ \else
+ \let\currentMPinstance\defaultMPinstance
+ \fi\fi
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_show_properties}
+
+\def\currentMPgraphicname{\s!unknown}
+\def\currentMPinstance {\defaultMPinstance}
+\def\currentMPformat {\currentMPinstance}
+
+\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[lessfun] [\s!format=metafun]
+\defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double]
+\defineMPinstance[binaryfun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!binary]
+\defineMPinstance[decimalfun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!decimal]
+
+\defineMPinstance[mprun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+
+\defineMPinstance[metapost] [\s!format=mpost]
+\defineMPinstance[nofun] [\s!format=mpost]
+\defineMPinstance[doublepost] [\s!format=mpost,\c!method=\s!double]
+\defineMPinstance[binarypost] [\s!format=mpost,\c!method=\s!binary]
+\defineMPinstance[decimalpost][\s!format=mpost,\c!method=\s!decimal]
+
+%defineMPinstance[megapost] [\s!format=mpost,\c!method=\s!decimal]
+
+\newconditional\c_meta_include_initializations
+
+\def\meta_begin_graphic_group#1%
+ {\begingroup
+ \meta_analyze_graphicname[#1]}
+
+\def\meta_end_graphic_group
+ {\endgroup}
+
+\def\MPaskedfigure{false}
+
+\def\meta_flush_current_initializations
+ {\ifconditional\c_meta_include_initializations
+ \the\t_meta_initializations
+ \fi
+ \theMPrandomseed;}
+
+\def\meta_flush_current_inclusions
+ {\the\t_meta_inclusions}
+
+\def\meta_flush_current_definitions
+ {\the\t_meta_definitions}
+
+\def\meta_start_current_graphic
+ {\begingroup
+ \meta_enable_include
+ \the\everyMPgraphic
+ \meta_preset_definitions
+ \setMPrandomseed % this has to change
+ \edef\p_initializations{\MPinstanceparameter\s!initializations}%
+ \ifx\p_initializations\v!yes
+ \settrue \c_meta_include_initializations
+ \else
+ \setfalse\c_meta_include_initializations
+ \fi
+ \edef\p_setups{\MPinstanceparameter\c!setups}%
+ \ifx\p_setups\empty \else
+ \setups[\p_setups]%
+ \fi
+ \useMPinstancestyleparameter\c!textstyle}
+
+\def\meta_set_current_color
+ {\useMPinstancecolorparameter\c!textcolor}
+
+\def\meta_stop_current_graphic
+ {\global\t_meta_definitions\emptytoks
+ \global\t_meta_inclusions\emptytoks
+ \endgroup}
+
+\def\meta_process_graphic_start
+ {\setbox\b_meta_graphic\hpack\bgroup}
+
+\def\meta_process_graphic_stop
+ {\egroup
+ \meta_place_graphic}
+
+\unexpanded\def\meta_process_graphic_instance#1%
+ {\edef\currentMPinstance{#1}%
+ \ifx\currentMPinstance\empty
+ \let\currentMPinstance\defaultMPinstance
+ \fi
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_process_graphic}
+
+\unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig
+ {\meta_start_current_graphic
+ \forgetall
+ \edef\p_extensions{\MPinstanceparameter\s!extensions}%
+ \meta_process_graphic_start
+ \normalexpanded{\noexpand\clf_mpgraphic
+ instance {\currentMPinstance}%
+ format {\currentMPformat}%
+ data {#1;}%
+ initializations {\meta_flush_current_initializations}%
+ \ifx\p_extensions\v!yes
+ extensions {\clf_getmpextensions{\currentMPinstance}}% goes through tex again
+ \fi
+ inclusions {\meta_flush_current_inclusions}%
+ definitions {\meta_flush_current_definitions}%
+ figure {\MPaskedfigure}%
+ method {\MPinstanceparameter\c!method}%
+ \relax}%
+ \meta_process_graphic_stop
+ \meta_stop_current_graphic}
+
+\let\meta_process_graphic_figure_start\relax
+\let\meta_process_graphic_figure_stop \relax
+
+\unexpanded\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages
+ {\begingroup
+ \let\normal_meta_process_graphic_start\meta_process_graphic_start
+ \let\normal_meta_process_graphic_stop \meta_process_graphic_stop
+ \let\meta_process_graphic_start\relax
+ \let\meta_process_graphic_stop \relax
+ \def\meta_process_graphic_figure_start{\startTEXpage[\c!offset=\v!overlay,\c!align=]\normal_meta_process_graphic_start}%
+ \def\meta_process_graphic_figure_stop {\normal_meta_process_graphic_stop\stopTEXpage}
+ \def\MPaskedfigure{all}%
+ \meta_process_graphic{input "#1" ;}%
+ \endgroup}
+
+\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default
+
+\let\theMPrandomseed\empty
+
+\def\setMPrandomseed
+ {\ifsetMPrandomseed
+ \def\theMPrandomseed{randomseed:=\mprandomnumber;}%
+ \else
+ \let\theMPrandomseed\empty
+ \fi}
+
+%D Calling up previously defined graphics.
+
+% \def\includeMPgraphic#1% gets expanded !
+% {\ifcsname\??mpgraphic#1\endcsname
+% \csname\??mpgraphic#1\endcsname ; % ; is safeguard
+% \fi}
+%
+% \unexpanded\def\meta_enable_include % public
+% {\let\meta_handle_use_graphic \thirdofthreearguments
+% \let\meta_handle_reusable_graphic\thirdofthreearguments}
+%
+% but ... we want this too:
+%
+% \startuseMPgraphic{x}
+% draw textext("\externalfigure[foo.pdf]") ;
+% \stopuseMPgraphic
+%
+% \useMPgraphic{x}
+%
+% so we cannot overload unless we let back to the original meanings
+% each graphic ... a better solution is:
+
+\def\includeMPgraphic#1% gets expanded !
+ {\ifcsname\??mpgraphic#1\endcsname
+ %\doubleexpandafter\fourthoffourarguments\csname\??mpgraphic#1\endcsname ; % ; is safeguard
+ \doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard
+ \fi}
+
+\let\meta_enable_include\relax
+
+%D Drawings (stepwise built):
+
+\newif\ifMPdrawingdone \MPdrawingdonefalse
+
+\unexpanded\def\finalizeMPdrawing
+ {\MPdrawingdonetrue}
+
+\let\MPdrawingdata\empty
+
+\unexpanded\def\resetMPdrawing
+ {\global\let\MPdrawingdata\empty
+ \global\MPdrawingdonefalse}
+
+\unexpanded\def\pushMPdrawing
+ {\globalpushmacro\MPdrawingdata
+ \global\let\MPdrawingdata\empty}
+
+\unexpanded\def\popMPdrawing
+ {\globalpopmacro\MPdrawingdata}
+
+\unexpanded\def\getMPdrawing
+ {\ifMPdrawingdone
+ \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed?
+ \fi}
+
+\def\startMPdrawing
+ {\dosingleempty\meta_start_drawing}
+
+\def\meta_start_drawing[#1]#2\stopMPdrawing
+ {\relax
+ \bgroup
+ \meta_enable_include
+ \meta_preset_definitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\def\asciia{#2}}%
+ \xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \egroup}
+
+\let\stopMPdrawing\relax
+
+\def\MPdrawing#1%
+ {\relax
+ \bgroup
+ \meta_enable_include
+ \meta_preset_definitions
+ \xdef\MPdrawingdata{\MPdrawingdata#1}%
+ \egroup}
+
+\unexpanded\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
+ {\setgvalue{\??mpclip#1}{#2}}
+
+\let\stopMPclip\relax
+
+\unexpanded\def\meta_grab_clip_path#1#2#3#4% #4 is alternative (called in backend code)
+ {\begingroup
+ \edef\width {#2}% \let\overlaywidth \width
+ \edef\height{#3}% \let\overlayheight\height
+ \d_overlay_width #2\onebasepoint
+ \d_overlay_height#3\onebasepoint
+ \edef\currentMPclip{#1}%
+ \ifcsname\??mpclip\currentMPclip\endcsname
+ \meta_grab_clip_path_indeed
+ \ifx\MPclippath\empty
+ \xdef\MPclippath{#4}%
+ \fi
+ \else
+ \xdef\MPclippath{#4}%
+ \fi
+ \endgroup}
+
+\def\meta_grab_clip_path_indeed
+ {\meta_start_current_graphic
+ \normalexpanded{\noexpand\clf_mpsetclippath
+ instance {\currentMPinstance}%
+ format {\currentMPformat}%
+ data {\csname\??mpclip\currentMPclip\endcsname}%
+ initializations {\meta_flush_current_initializations}%
+ useextensions {\MPinstanceparameter\s!extensions}%
+ inclusions {\meta_flush_current_inclusions}%
+ method {\MPinstanceparameter\c!method}%
+ \relax}%
+ \meta_stop_current_graphic}
+
+%D Since we want lables to follow the document settings, we
+%D also set the font related variables.
+
+\unexpanded\def\MPfontsizehskip#1%
+ {\dontleavehmode
+ \begingroup
+ \definedfont[#1]%
+ \hskip\clf_currentdesignsize\scaledpoint\relax
+ \endgroup}
+
+\definefontsynonym[MetafunDefault][Regular*default]
+
+\startMPinitializations % scale is not yet ok
+ defaultfont:="\truefontname{MetafunDefault}";
+ % defaultscale:=\the\bodyfontsize/10pt; % only when hard coded 10pt
+ % defaultscale:=1;
+\stopMPinitializations
+
+% watch out, this is a type1 font because mp can only handle 8 bit fonts
+
+% \startMPinitializations % scale is not yet ok
+% defaultfont:="rm-lmtt10";
+% \stopMPinitializations
+
+%D A signal that we're in combined \CONTEXT||\METAFUN mode:
+
+\startMPextensions
+ string contextversion;
+ contextversion:="\contextversion"; % expanded
+\stopMPextensions
+
+%D \macros
+%D {setupMPvariables}
+%D
+%D When we build collections of \METAPOST\ graphics, like
+%D background and buttons, the need for passing settings
+%D arises. By (mis|)|using the local prefix that belongs to
+%D \type {\framed}, we get a rather natural interface to
+%D backgrounds. To prevent conflicts, we will use the \type
+%D {-} in \METAPOST\ specific variables, like:
+%D
+%D \starttyping
+%D \setupMPvariables[meta:button][size=20pt]
+%D \stoptyping
+
+% \lineheight 2pt 2 \scratchcounter red 0.4 .5\bodyfontsize
+%
+% see cont-loc for test code
+%
+% currently the inheritance of backgrounds does not work and
+% we might drop it anyway (too messy)
+
+\newbox\b_meta_variable_box
+
+\let \currentmpvariableclass \empty
+\let \m_meta_current_variable \empty
+\let \m_meta_current_variable_template\empty
+
+\installcorenamespace{graphicvariable}
+
+\def \meta_prepare_variable_default {\MPcolor{black}} % just to be sure we use a color but ...
+\edef\meta_unknown_variable_template {\??graphicvariable:\s!unknown}
+
+\letvalue{\??graphicvariable:\s!unknown}\empty
+
+\unexpanded\def\setupMPvariables
+ {\dodoubleempty\meta_setup_variables}
+
+\def\meta_setup_variables[#1][#2]%
+ {\ifsecondargument
+ \getrawparameters[\??graphicvariable#1:][#2]%
+ \else
+ \getrawparameters[\??graphicvariable:][#1]%
+ \fi}
+
+\unexpanded\def\presetMPvariable
+ {\dodoubleargument\meta_preset_variable}
+
+\def\meta_preset_variable[#1][#2=#3]%
+ {\ifcsname\??graphicvariable#1:#2\endcsname \else
+ \setvalue{\??graphicvariable#1:#2}{#3}%
+ \fi}
+
+\def\MPrawvar#1#2% no checking
+ %{\csname\??graphicvariable#1:#2\endcsname}
+ {\begincsname\??graphicvariable#1:#2\endcsname}
+
+\def\MPvariable#1% todo: could be a framed chain
+ %{\csname\??graphicvariable\currentmpvariableclass:#1\endcsname}
+ {\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname}
+
+\unexpanded\def\useMPvariables
+ {\dodoubleargument\meta_use_variables}
+
+\def\meta_use_variables[#1][#2]%
+ {\edef\currentmpvariableclass{#1}%
+ \meta_prepare_variables{#2}}
+
+\unexpanded\def\meta_prepare_variables#1%
+ {\processcommalist[#1]\meta_prepare_variable}
+
+\unexpanded\def\meta_prepare_variable#1%
+ {\edef\m_meta_current_variable_template
+ {\??graphicvariable\currentmpvariableclass:#1}%
+ \edef\m_meta_current_variable
+ {\csname\ifcsname\m_meta_current_variable_template\endcsname
+ \m_meta_current_variable_template\else\meta_unknown_variable_template
+ \fi\endcsname}%
+ \ifx\m_meta_current_variable\empty
+ \expandafter\meta_prepare_variable_nop
+ \else
+ \expandafter\meta_prepare_variable_yes
+ \fi}
+
+\unexpanded\def\meta_prepare_instance_variables
+ {\expandafter\processcommalist\expandafter[\m_meta_instance_variables]\meta_prepare_instance_variable}
+
+\unexpanded\def\meta_prepare_instance_variable#1%
+ {\edef\m_meta_current_variable_template
+ {\??graphicvariable\currentmpvariableclass:#1}%
+ \edef\m_meta_current_variable
+ {\csname
+ \ifcsname\m_meta_current_variable_template\endcsname
+ \m_meta_current_variable_template
+ \else\ifcsname\??graphicvariable\currentMPgraphicname:#1\endcsname
+ \??graphicvariable\currentMPgraphicname:#1%
+ \else
+ \meta_unknown_variable_template
+ \fi\fi
+ \endcsname}%
+ \ifx\m_meta_current_variable\empty
+ \expandafter\meta_prepare_variable_nop
+ \else
+ \expandafter\meta_prepare_variable_yes
+ \fi}
+
+\def\meta_prepare_variable_nop
+ {\expandafter \let\csname\m_meta_current_variable_template\endcsname\meta_prepare_variable_default}
+
+\def\meta_prepare_variable_color
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\MPcolor\m_meta_current_variable}}
+
+\def\meta_prepare_variable_number
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\number\m_meta_current_variable}}% also accepts 0.number
+
+\def\meta_prepare_variable_dimension
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}}
+
+\def\meta_prepare_variable_yes
+ {\defconvertedcommand\ascii\m_meta_current_variable % otherwise problems
+ \doifelsecolor \ascii % with 2\bodyfontsize
+ {\meta_prepare_variable_color}
+ {\begingroup
+ \setbox\b_meta_variable_box\hpack{\scratchdimen\m_meta_current_variable sp}%
+ \ifzeropt\wd\b_meta_variable_box
+ \endgroup\meta_prepare_variable_number
+ \else
+ \endgroup\meta_prepare_variable_dimension
+ \fi}}
+
+\let\MPvar \MPvariable
+\let\setMPvariables\setupMPvariables
+
+%D \macros
+%D {startuniqueMPgraphic, uniqueMPgraphic}
+%D
+%D This macros is probably of most use to myself, since I like
+%D to use graphics that adapt themselves. The next \METAPOST\
+%D kind of graphic is both unique and reused when possible.
+%D
+%D \starttyping
+%D \defineoverlay[example][\uniqueMPgraphic{test}]
+%D
+%D \startuniqueMPgraphic {test}
+%D draw unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D \stopuniqueMPgraphic
+%D \stoptyping
+
+\def\overlaystamp % watch the \MPcolor, since colors can be redefined
+ {\the\d_overlay_width :%
+ \the\d_overlay_height :%
+ \the\d_overlay_depth :%
+ \the\d_overlay_offset :%
+ \the\d_overlay_linewidth:%
+ \MPcolor\overlaycolor :% % todo, expand once \m_overlaycolor
+ \MPcolor\overlaylinecolor} % todo, expand once \m_overlaylinecolor
+
+%D A better approach is to let additional variables play a role
+%D in determining the uniqueness. In the next macro, the
+%D second, optional, argument is used to guarantee the
+%D uniqueness, as well as prepare variables for passing them to
+%D \METAPOST.
+%D
+%D \starttyping
+%D \startuniqueMPgraphic{meta:hash}{gap,angle,...}
+%D \stoptyping
+%D
+%D The calling macro also accepts a second argument. For
+%D convenient use in overlay definitions, we use \type {{}}
+%D instead of \type {[]}.
+%D
+%D \starttyping
+%D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30}
+%D \stoptyping
+
+\newcount\c_meta_object_counter
+\newbox \b_meta_graphic
+
+% hm, isn't this already done elsewhere?
+
+\unexpanded\def\meta_obey_box_depth
+ {\setbox\b_meta_graphic\hpack\bgroup
+ \raise\MPlly\box\b_meta_graphic
+ \egroup}
+
+\unexpanded\def\meta_ignore_box_depth
+ {\normalexpanded
+ {\meta_obey_box_depth % hence the \unexpanded
+ \wd\b_meta_graphic\the\wd\b_meta_graphic
+ \ht\b_meta_graphic\the\ht\b_meta_graphic
+ \dp\b_meta_graphic\the\dp\b_meta_graphic}}
+
+\unexpanded\def\meta_obey_box_origin
+ {\setbox\b_meta_graphic\hpack\bgroup
+ \kern\MPllx\raise\MPlly\box\b_meta_graphic
+ \egroup}
+
+\unexpanded\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth }
+\unexpanded\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth}
+\unexpanded\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin }
+\unexpanded\def\normalMPboxdepth{\let\meta_relocate_box\relax }
+
+\let\meta_relocate_box\relax
+
+\unexpanded\def\meta_place_graphic % the converter also displaces so in fact we revert
+ {\meta_relocate_box
+ \box\b_meta_graphic}
+
+\unexpanded\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens
+ {\MPllx#2\MPlly#3\MPurx#4\MPury#5%
+ \hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
+
+% \unexpanded\def\meta_use_box
+% {\setobject{MP}}
+
+\unexpanded\def\meta_use_box
+ {\setunreferencedobject{MP}}
+
+\def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although,
+ {\begingroup % when there are that many they're probably not that unique anyway
+ \edef\currentmpvariableclass{#1}%
+ \extendMPoverlaystamp{#2}% incl prepare
+ \ifcsname\??mpgraphic\overlaystamp:#1\endcsname\else
+ \meta_enable_include % redundant
+ \global\advance\c_meta_object_counter\plusone
+ \meta_use_box{\number\c_meta_object_counter}\hpack{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\??mpgraphic\overlaystamp:#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
+ \fi
+ \csname\??mpgraphic\overlaystamp:#1\endcsname\empty
+ \endgroup}
+
+\unexpanded\def\startuniqueMPgraphic
+ {\dodoublegroupempty\meta_start_unique_graphic}
+
+% \def\meta_start_unique_graphic#1#2#3\stopuniqueMPgraphic
+% {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}}
+
+\def\meta_start_unique_graphic#1%
+ {\normalexpanded{\meta_start_unique_graphic_indeed{#1}}}
+
+\unexpanded\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}}
+
+\let\stopuniqueMPgraphic\relax
+
+\unexpanded\def\uniqueMPgraphic
+ {\dodoublegroupempty\meta_unique_graphic}
+
+\def\meta_unique_graphic#1#2%
+ {\meta_begin_graphic_group{#1}%
+% \setupMPvariables[\currentMPgraphicname][#2]%
+ \setupMPvariables[#1][#2]%
+ \csname\??mpgraphic#1\endcsname\empty
+ \meta_end_graphic_group}
+
+\def\meta_handle_use_graphic#1#2#3%
+ {\begingroup
+ \edef\currentmpvariableclass{#1}%
+ \edef\m_meta_instance_variables{#2}%
+ \ifx\m_meta_instance_variables\empty \else
+ \meta_prepare_instance_variables
+ \fi
+ \meta_enable_include % redundant
+ \meta_process_graphic{#3}%
+ \endgroup}
+
+\unexpanded\def\startuseMPgraphic
+ {\dodoublegroupempty\meta_start_use_graphic}
+
+% \def\meta_start_use_graphic#1#2#3\stopuseMPgraphic
+% {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
+%
+% better, expansion of #1:
+%
+% \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}}}
+%
+% cleaner:
+
+\def\meta_start_use_graphic#1%
+ {\normalexpanded{\meta_start_use_graphic_indeed{#1}}}
+
+\unexpanded\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
+
+\let\stopuseMPgraphic\relax
+
+\unexpanded\def\startusableMPgraphic % redundant but handy
+ {\dodoublegroupempty\meta_start_usable_graphic}
+
+% \def\meta_start_usable_graphic#1#2#3\stopusableMPgraphic
+% {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
+
+\def\meta_start_usable_graphic#1%
+ {\normalexpanded{\meta_start_usable_graphic_indeed{#1}}}
+
+\unexpanded\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
+
+\let\stopusableMPgraphic\relax
+
+\def\meta_handle_reusable_graphic#1#2#3%
+ {\begingroup
+ \edef\currentmpvariableclass{#1}%
+ \edef\m_meta_instance_variables{#2}%
+ \ifx\m_meta_instance_variables\empty \else
+ \meta_prepare_instance_variables
+ \fi
+ \meta_enable_include % redundant
+ \global\advance\c_meta_object_counter\plusone
+ \meta_use_box{\number\c_meta_object_counter}\hpack{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\??mpgraphic#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
+ \csname\??mpgraphic#1\endcsname\empty
+ \endgroup}
+
+\unexpanded\def\startreusableMPgraphic
+ {\dodoublegroupempty\meta_start_reusable_graphic}
+
+% \def\meta_start_reusable_graphic#1#2#3\stopreusableMPgraphic
+% {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}}
+
+\def\meta_start_reusable_graphic#1%
+ {\normalexpanded{\meta_start_reusable_graphic_indeed{#1}}}
+
+\unexpanded\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}}
+
+\let\stopreusableMPgraphic\relax
+
+\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}
+
+\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
+\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed
+
+%D \macros
+%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
+%D
+%D Experimental.
+
+\def\m_meta_page_prefix{\doifelseoddpage oe}
+
+% \def\overlaypagestamp
+% {\m_meta_page_prefix:\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+\def\overlaypagestamp
+ {\m_meta_page_prefix :%
+ \the\d_overlay_width :%
+ \the\d_overlay_height :%
+ \the\d_overlay_depth :%
+ \the\d_overlay_offset :%
+ \the\d_overlay_linewidth:%
+ \MPcolor\overlaycolor :%
+ \MPcolor\overlaylinecolor}
+
+\unexpanded\def\startuniqueMPpagegraphic
+ {\dodoublegroupempty\meta_start_unique_page_graphic}
+
+% \def\meta_start_unique_page_graphic#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage
+% {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state
+% \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined
+
+\def\meta_start_unique_page_graphic#1%
+ {\normalexpanded{\meta_start_unique_page_graphic_indeed{#1}}}
+
+\unexpanded\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage
+ {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state
+ \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined
+
+\let\stopuniqueMPpagegraphic\relax
+
+\unexpanded\def\uniqueMPpagegraphic
+ {\dodoublegroupempty\meta_unique_page_graphic}
+
+\def\meta_unique_page_graphic#1#2%
+ {\meta_begin_graphic_group{#1}%
+ \let\overlaystamp\overlaypagestamp
+% \setupMPvariables[\m_meta_page_prefix:\currentMPgraphicname][#2]% prefix is new here
+ \setupMPvariables[\m_meta_page_prefix:#1][#2]% prefix is new here
+ \csname\??mpgraphic\m_meta_page_prefix:#1\endcsname\empty
+ \meta_end_graphic_group}
+
+%D One way of defining a stamp is:
+%D
+%D \starttyping
+%D \def\extendMPoverlaystamp#1%
+%D {\def\docommand##1%
+%D {\edef\overlaystamp{\overlaystamp:\MPvariable{##1}}}%
+%D \processcommalist[#1]\docommand}
+%D \stoptyping
+
+%D Since we need to feed \METAPOST\ with expanded dimensions,
+%D we introduce a dedicated expansion engine.
+
+%D We redefine \type {\extendMPoverlaystamp} to preprocess
+%D variables using \type {\meta_prepare_variable}.
+
+\unexpanded\def\extendMPoverlaystamp#1%
+ {\processcommalist[#1]\meta_extend_overlay_stamp}
+
+\def\meta_extend_overlay_stamp#1%
+ {\meta_prepare_instance_variable{#1}%
+ \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
+
+%D \macros
+%D {MPdatafile}
+%D
+%D We redefine a macro from \type {supp-mps.tex}:
+
+% This will change ...
+
+\def\MPdataMPDfile{\jobname-mpgraph.mpd} % this one will become obsolete
+\def\MPdataMPOfile{\jobname-mpgraph.mpo}
+\def\MPdataMPYfile{\jobname-mpgraph.mpy}
+
+% makempy.registerfile(filename)
+
+% % hm. extensions get expanded so the wrong names then end up in format
+%
+% \startMPinitializations
+% boolean collapse_data; collapse_data:=true ; % will be obsolete
+% def data_mpd_file = "\MPdataMPDfile" enddef ; % will go via lua
+% def data_mpo_file = "\MPdataMPOfile" enddef ;
+% def data_mpy_file = "\MPdataMPYfile" enddef ;
+% \stopMPinitializations
+
+\startMPextensions
+ boolean collapse_data; collapse_data:=true ; % will be obsolete
+ def data_mpd_file = "\noexpand\MPdataMPDfile" enddef ; % will go via lua
+ def data_mpo_file = "\noexpand\MPdataMPOfile" enddef ;
+ def data_mpy_file = "\noexpand\MPdataMPYfile" enddef ;
+\stopMPextensions
+
+\unexpanded\def\getMPdata
+ {\let\MPdata\secondoftwoarguments
+ \startreadingfile
+ % \startnointerference % no, else we need to do all data global
+ \readlocfile\MPdataMPDfile\donothing\donothing
+ % \stopnointerference
+ \stopreadingfile}
+
+% We need this trick because we need to make sure that the tex scanner
+% sees newlines and does not quit. Also, we do need to flush the buffer
+% under a normal catcode regime in order to expand embedded tex macros.
+% As usual with buffers, \type {#1} can be a list.
+
+\unexpanded\def\processMPbuffer
+ {\dosingleempty\meta_process_buffer}
+
+\def\meta_process_buffer[#1]%
+ {\meta_begin_graphic_group{#1}%
+ \meta_process_graphic{\clf_feedback{\currentMPgraphicname}}%
+ \meta_end_graphic_group}
+
+\unexpanded\def\runMPbuffer
+ {\dosingleempty\meta_run_buffer}
+
+\def\meta_run_buffer[#1]% processing only
+ {\startnointerference\meta_process_buffer[#1]\stopnointerference}
+
+%D \macros
+%D {startMPenvironment, resetMPenvironment}
+%D
+%D In order to synchronize the main \TEX\ run and the runs
+%D local to \METAPOST, environments can be passed.
+
+% \unexpanded\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
+% {\dodoubleempty\dostartMPenvironment}
+
+% \def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
+% {\edef\m_meta_option{#1}
+% \ifx\m_meta_option\s!reset
+% \resetMPenvironment % reset mp toks
+% \else\ifx\m_meta_option\v!global
+% #3% % use in main doc too
+% \else\ifx\m_meta_option\!!plustoken
+% #3% % use in main doc too
+% \fi\fi\fi
+% \ctxlua{metapost.tex.set(\!!bs\detokenize{#3}\!!es)}}
+
+\unexpanded\def\startMPenvironment
+ {\begingroup
+ \catcode\endoflineasciicode \ignorecatcode
+ \dosingleempty\meta_start_environment}
+
+\def\meta_start_environment[#1]#2\stopMPenvironment
+ {\endgroup
+ \edef\m_meta_option{#1}
+ \ifx\m_meta_option\s!reset
+ \resetMPenvironment % reset mp toks
+ \else\ifx\m_meta_option\v!global
+ #2% % use in main doc too
+ \else\ifx\m_meta_option\!!plustoken
+ #2% % use in main doc too
+ \fi\fi\fi
+ \clf_mptexset{\detokenize{#2}}}
+
+\let\stopMPenvironment\relax
+
+\unexpanded\def\resetMPenvironment
+ {\clf_mptexreset}
+
+\unexpanded\def\useMPenvironmentbuffer[#1]%
+ {\clf_mptexsetfrombuffer{#1}}
+
+%D This command takes \type {[reset]} as optional
+%D argument.
+%D
+%D \starttyping
+%D \startMPenvironment
+%D \setupbodyfont[pos,14.4pt]
+%D \stopMPenvironment
+%D
+%D \startMPcode
+%D draw btex \sl Hans Hagen etex scaled 5 ;
+%D \stopMPcode
+%D \stoptyping
+%D
+%D The most simple case:
+
+\unexpanded\def\startMPcode
+ {\dosinglegroupempty\meta_start_code}
+
+\def\meta_start_code
+ {\iffirstargument
+ \expandafter\meta_start_code_instance
+ \else
+ \expandafter\meta_start_code_standard
+ \fi}
+
+\def\meta_start_code_instance#1#2\stopMPcode
+ {\begingroup
+ \edef\currentMPinstance{#1}%
+ \let\currentMPgraphicname\empty
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_enable_include
+ \meta_process_graphic{#2}%
+ \endgroup}
+
+\def\meta_start_code_standard#1#2\stopMPcode
+ {\begingroup
+ \let\currentMPinstance\defaultMPinstance
+ \let\currentMPgraphicname\empty
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_process_graphic{#2}%
+ \endgroup}
+
+\let\stopMPcode\relax
+
+\unexpanded\def\MPcode
+ {\dodoublegroupempty\meta_code}
+
+\def\meta_code
+ {\ifsecondargument
+ \expandafter\meta_code_instance
+ \else
+ \expandafter\meta_code_standard
+ \fi}
+
+\def\meta_code_instance#1#2%
+ {\meta_begin_graphic_group{#1}%
+ \meta_enable_include
+ \meta_process_graphic{#2}%
+ \meta_end_graphic_group}
+
+\def\meta_code_standard#1#2%
+ {\let\currentMPinstance\defaultMPinstance
+ \meta_enable_include
+ \meta_process_graphic{#1}}
+
+% a bit nasty (also needed for compatibility:
+
+% \startMPrun input mp-www.mp ; \stopMPrun
+% \externalfigure[mprun.3][width=10cm,height=8cm]
+
+% \startMPrun{mprun} input mp-www.mp ; \stopMPrun % instance
+% \externalfigure[mprun.4][width=10cm,height=8cm]
+
+\let\MPruninstance\defaultMPinstance
+
+\unexpanded\def\useMPrun#1#2% name n
+ {\begingroup
+ \def\MPaskedfigure{#2}%
+ \doifelsenothing{#1}
+ {\useMPgraphic{mprun}}%
+ {\useMPgraphic{#1}}%
+ \endgroup}
+
+\unexpanded\def\startMPrun
+ {\dosinglegroupempty\meta_start_run}
+
+\def\meta_start_run#1#2\stopMPrun
+ {\iffirstargument
+ \startuseMPgraphic{#1}#2\stopuseMPgraphic
+ \else
+ \startuseMPgraphic{mprun}#2\stopuseMPgraphic
+ \fi}
+
+\let\stopMPrun\relax
+
+%D The \type {\resetMPenvironment} is a quick way to erase
+%D the token list.
+%D
+%D You should be aware of independencies. For instance, if you use a font
+%D in a graphic that is not used in the main document, you need to load the
+%D typescript at the outer level (either directly or by using the global
+%D option).
+%D
+%D \starttyping
+%D \usetypescript[palatino][texnansi]
+%D
+%D \startMPenvironment
+%D \usetypescript[palatino][texnansi]
+%D \enableregime[utf]
+%D \setupbodyfont[palatino]
+%D \stopMPenvironment
+%D
+%D \startMPpage
+%D draw btex aap‒noot coördinatie – één etex ;
+%D \stopMPpage
+%D \stoptyping
+
+%D Loading specific \METAPOST\ related definitions is
+%D accomplished by:
+
+\unexpanded\def\useMPlibrary[#1]{\clf_useMPlibrary{#1}}
+
+%D \macros
+%D {setMPtext, MPtext, MPstring, MPbetex}
+%D
+%D To be documented:
+%D
+%D \starttyping
+%D \setMPtext{identifier}{text}
+%D
+%D \MPtext {identifier}
+%D \MPstring{identifier}
+%D \MPbetex {identifier}
+%D \stoptyping
+
+\installcorenamespace{mptext}
+
+\unexpanded\def\setMPtext#1#2% todo : #1 must be made : safe
+ {\defconvertedargument\ascii{#2}%
+ \dodoglobal\letvalue{\??mptext#1}\ascii}
+
+\def\MPtext #1{\begincsname\??mptext#1\endcsname\empty}
+\def\MPstring#1{"\begincsname\??mptext#1\endcsname\empty"}
+\def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex}
+
+%D In order to communicate conveniently with the \TEX\
+%D engine, we introduce some typesetting variables.
+
+% \setupcolors[state=stop,conversion=never] % quite tricky ... type mismatch
+
+% \startMPextensions
+% color OverlayColor,OverlayLineColor;
+% \stopMPextensions
+
+\startMPinitializations
+ CurrentLayout:="\currentlayout";
+\stopMPinitializations
+
+% \startMPinitializations
+% OverlayWidth:=\overlaywidth;
+% OverlayHeight:=\overlayheight;
+% OverlayDepth:=\overlaydepth;
+% OverlayLineWidth:=\overlaylinewidth;
+% OverlayOffset:=\overlayoffset;
+% \stopMPinitializations
+
+% A dirty trick, ** in colo-ini.lua (mpcolor). We cannot use a vardef, because
+% that fails with spot colors.
+
+\startMPinitializations
+ def OverlayLineColor=\ifx\overlaylinecolor\empty black \else\MPcolor{\overlaylinecolor} \fi enddef;
+ def OverlayColor =\ifx\overlaycolor \empty black \else\MPcolor{\overlaycolor} \fi enddef;
+\stopMPinitializations
+
+% \newcount\c_overlay_colormodel
+% \newcount\c_overlay_color
+% \newcount\c_overlay_transparency
+% \newcount\c_overlay_linecolor
+% \newcount\c_overlay_linetransparency
+
+% \appendtoks
+% \c_overlay_colormodel \attribute\colormodelattribute
+% \c_overlay_color \colo_helpers_inherited_current_ca\overlaycolor
+% \c_overlay_transparency \colo_helpers_inherited_current_ta\overlaycolor
+% \c_overlay_linecolor \colo_helpers_inherited_current_ca\overlaylinecolor
+% \c_overlay_linetransparency\colo_helpers_inherited_current_ta\overlaylinecolor
+% \to \everyMPgraphic
+
+% \startMPinitializations
+% BaseLineSkip:=\the\baselineskip;
+% LineHeight:=\the\baselineskip;
+% BodyFontSize:=\the\bodyfontsize;
+% %
+% TopSkip:=\the\topskip;
+% StrutHeight:=\strutheight;
+% StrutDepth:=\strutdepth;
+% %
+% CurrentWidth:=\the\hsize;
+% CurrentHeight:=\the\vsize;
+% HSize:=\the\hsize ;
+% VSize:=\the\vsize ;
+% %
+% EmWidth:=\the\emwidth;
+% ExHeight:=\the\exheight;
+% \stopMPinitializations
+
+\appendtoks
+ \disablediscretionaries
+ %\disablecompoundcharacters
+\to \everyMPgraphic
+
+% \appendtoks % before color, inefficient, replace by low level copy
+% \doregistercolor{currentcolor}\currentcolorname
+% \to \everyMPgraphic
+
+% \color[green]{abc \startMPcode
+% fill fullcircle scaled 3cm withoutcolor;
+% fill fullcircle scaled 2cm withcolor \MPcolor{currentcolor} ;
+% fill fullcircle scaled 1cm withcolor \MPcolor{red} ;
+% \stopMPcode def}
+
+\appendtoks
+ \baselineskip1\baselineskip
+ \lineheight 1\lineheight
+ \topskip 1\topskip
+\to \everyMPgraphic
+
+\appendtoks
+ \let \# \letterhash
+ \let \_ \letterunderscore
+ \let \& \letterampersand
+ \let \{ \letteropenbrace
+ \let \} \letterclosebrace
+\to \everyMPgraphic
+
+%D \macros
+%D {PDFMPformoffset}
+%D
+%D In \PDF, forms are clipped and therefore we have to take
+%D precautions to get this right. Since this is related to
+%D objects, we use the same offset as used there.
+
+\def\PDFMPformoffset{\objectoffset}
+
+% %D \macros
+% %D {insertMPfile}
+% %D
+% %D Bypassing the special driver and figure mechanism is not
+% %D that nice but saves upto 5\% time in embedding \METAPOST\
+% %D graphics by using the low level \PDF\ converter directly,
+% %D given of course that we use \PDFTEX. As a result we need to
+% %D fool around with the object trigger.
+
+\newtoks\everyinsertMPfile
+
+\startMPextensions
+ def initialize_form_numbers =
+ do_initialize_numbers;
+ enddef;
+\stopMPextensions
+
+\startMPextensions
+ vardef ForegroundBox =
+ unitsquare xysized(HSize,VSize)
+ enddef ;
+\stopMPextensions
+
+% \startMPextensions
+% PageFraction := 1 ;
+% \stopMPextensions
+
+% \startMPinitializations
+% PageFraction := if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi ;
+% \stopMPinitializations
+
+\startMPdefinitions {metapost}
+ if unknown context_bare : input mp-bare.mpiv ; fi ;
+\stopMPdefinitions
+\startMPdefinitions {binarypost}
+ if unknown context_bare : input mp-bare.mpiv ; fi ;
+\stopMPdefinitions
+\startMPdefinitions {decimalpost}
+ if unknown context_bare : input mp-bare.mpiv ; fi ;
+\stopMPdefinitions
+\startMPdefinitions {doublepost}
+ if unknown context_bare : input mp-bare.mpiv ; fi ;
+\stopMPdefinitions
+
+% \startMPdefinitions {nofun}
+% if unknown context_bare : input mp-bare.mpiv ; fi ;
+% \stopMPdefinitions
+
+%D And some more. These are not really needed since we
+%D don't use the normal figure inclusion macros any longer.
+
+\appendtoks
+ \externalfigurepostprocessors\emptytoks % safeguard
+\to \everyinsertMPfile
+
+%D We also take care of disabling fancy figure features, that
+%D can terribly interfere when dealing with symbols,
+%D background graphics and running (postponed) graphics.
+%D You won't believe me if I tell you what funny side effects
+%D can occur. One took me over a day to uncover when
+%D processing the screen version of the \METAFUN\ manual.
+
+\def\doifelseMPgraphic#1%
+ {\ifcsname\??mpgraphic #1\endcsname \expandafter \firstoftwoarguments \else
+ \ifcsname\??mpgraphic o:#1\endcsname \doubleexpandafter\firstoftwoarguments \else
+ \ifcsname\??mpgraphic e:#1\endcsname \tripleexpandafter\firstoftwoarguments \else
+ \tripleexpandafter\secondoftwoarguments \fi\fi\fi}
+
+\let\doifMPgraphicelse\doifelseMPgraphic
+
+%D New:
+
+\definelayerpreset % no dx,dy - else nasty non-mp placement
+ [mp]
+ [\c!y=-\MPury,
+ \c!x=\MPllx,
+ \c!method=\v!fit]
+
+\definelayer
+ [mp]
+ [\c!preset=mp]
+
+%D Usage:
+%D
+%D \starttyping
+%D \defineviewerlayer[one][state=start]
+%D \defineviewerlayer[two][state=stop]
+%D
+%D \startuseMPgraphic{step-1}
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopuseMPgraphic
+%D
+%D \startuseMPgraphic{step-2}
+%D fill fullcircle scaled 5cm withcolor green ;
+%D \stopuseMPgraphic
+%D
+%D \setlayer[mp]{\viewerlayer[one]{\useMPgraphic{step-1}}}
+%D \setlayer[mp]{\viewerlayer[two]{\useMPgraphic{step-2}}}
+%D
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+%D
+%D Reusing graphics is also possible (now):
+%D
+%D \starttyping
+%D \startreusableMPgraphic{axis}
+%D tickstep := 1cm ; ticklength := 2mm ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D tickstep := tickstep/2 ; ticklength := ticklength/2 ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D \stopreusableMPgraphic
+%D
+%D \startuseMPgraphic{demo}
+%D drawpoint "1cm,1.5cm" ;
+%D \stopuseMPgraphic
+%D
+%D \definelayer[mp][preset=mp]
+%D \setlayer[mp]{\reuseMPgraphic{axis}}
+%D \setlayer[mp]{\useMPgraphic{demo}}
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+
+%D \macros
+%D {startstaticMPfigure,useMPstaticfigure}
+%D
+%D Static figures are processed only when there has been
+%D something changed. Here is Aditya Mahajan's testcase:
+%D
+%D \startbuffer
+%D \startstaticMPfigure{circle}
+%D fill fullcircle scaled 1cm withcolor blue;
+%D \stopstaticMPfigure
+%D
+%D \startstaticMPfigure{axis}
+%D drawarrow (0,0)--(2cm,0) ;
+%D drawarrow (0,0)--(0,2cm) ;
+%D label.llft(textext("(0,0)") ,origin) ;
+%D \stopstaticMPfigure
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure
+ {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic}
+
+\unexpanded\def\startstaticMPgraphic
+ {\dodoublegroupempty\meta_start_static_graphic}
+
+\def\meta_start_static_graphic#1#2#3\stopstaticMPgraphic
+ {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic}
+
+\let\stopstaticMPfigure \relax
+\let\stopstaticMPgraphic\relax
+
+\unexpanded\def\usestaticMPfigure
+ {\dodoubleempty\meta_use_static_figure}
+
+\def\meta_use_static_figure[#1][#2]%
+ {\ifsecondargument
+ \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}%
+ \else
+ \reuseMPgraphic{\??mpstaticgraphic#1}%
+ \fi}
+
+%D Goody for preventing overflows:
+
+\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}
+
+%D There is no way to distinguish the black color that you get when
+%D you issue a \type {draw} without color specification from a color
+%D that has an explicit black specification unless you set the
+%D variable \type {defaultcolormodel} to 1. Hoewever, in that case
+%D you cannot distinguish that draw from one with a \type
+%D {withoutcolor} specification. This means that we have to provide
+%D multiple variants of inheritance.
+%D
+%D In any case we need to tell the converter what the inherited color
+%D is to start with. Case~3 is kind of unpredictable as it closely
+%D relates to the order in which paths are flushed. If you want to
+%D inherit automatically from the surrounding, you can best stick to
+%D variant 1. Variant 0 (an isolated graphic) is the default.
+%D
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D drawoptions(withpen pencircle scaled 1pt) ;
+%D def shift_cp = currentpicture := currentpicture shifted (-15pt,0) ; enddef ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt ; shift_cp ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt withcolor red ; shift_cp ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt ; shift_cp ;
+%D \stopuseMPgraphic
+%D
+%D \starttabulate
+%D \NC 0\quad \NC \MPcolormethod0 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 1\quad \NC \MPcolormethod1 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 2\quad \NC \MPcolormethod2 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 3\quad \NC \MPcolormethod3 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\newconstant\MPcolormethod
+
+\appendtoks
+ \clf_mpsetoutercolor
+ \MPcolormethod\space
+ \attribute\colormodelattribute\space
+ \attribute\colorattribute\space
+ \dogetattribute{transparency}\relax
+\to \everyMPgraphic
+
+% \startMPinitializations
+% defaultcolormodel := \ifcase\MPcolormethod1\or1\or3\else3\fi;
+% \stopMPinitializations
+
+%D macros
+%D {mprunvar,mpruntab,mprunset}
+%D
+%D \starttyping
+%D \startMPcode
+%D passvariable("version","1.0") ;
+%D passvariable("number",123) ;
+%D passvariable("string","whatever") ;
+%D passvariable("point",(1.5,2.8)) ;
+%D passvariable("triplet",(1/1,1/2,1/3)) ;
+%D passvariable("quad",(1.1,2.2,3.3,4.4)) ;
+%D passvariable("boolean",false) ;
+%D passvariable("path",fullcircle scaled 1cm) ;
+%D draw fullcircle scaled 20pt ;
+%D \stopMPcode
+%D
+%D \ctxlua{inspect(metapost.variables)}
+%D
+%D \MPrunvar{version} \MPruntab{quad}{3} (\MPrunset{triplet}{,})
+%D
+%D $(x,y) = (\MPruntab{point}{1},\MPruntab{point}{2})$
+%D $(x,y) = (\MPrunset{point}{,})$
+%D \stoptyping
+
+\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar
+\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number
+\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset
+
+%D We also provide an outputless run:
+
+\unexpanded\def\startMPcalculation
+ {\begingroup
+ \setbox\nextbox\hpack\bgroup
+ \dosinglegroupempty\meta_start_calculation}
+
+\def\meta_start_calculation
+ {\iffirstargument
+ \expandafter\meta_start_calculation_instance
+ \else
+ \expandafter\meta_start_calculation_standard
+ \fi}
+
+\def\meta_start_calculation_instance#1#2\stopMPcalculation
+ {\edef\currentMPinstance{#1}%
+ \let\currentMPgraphicname\empty
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_enable_include
+ \meta_process_graphic{#2;draw origin}%
+ \egroup
+ \endgroup}
+
+\def\meta_start_calculation_standard#1#2\stopMPcalculation
+ {\let\currentMPinstance\defaultMPinstance
+ \let\currentMPgraphicname\empty
+ \edef\currentMPformat{\MPinstanceparameter\s!format}%
+ \meta_process_graphic{#2;draw origin}%
+ \egroup
+ \endgroup}
+
+\let\stopMPcalculation\relax
+
+%D \macros
+%D {setupMPgraphics}
+%D
+%D Here is a generic setup command:
+
+\installcorenamespace{MPgraphics}
+
+\installsetuponlycommandhandler \??MPgraphics {MPgraphics}
+
+%D Here we hook in the outer color. When \type {color} is set to \type
+%D {global} we get the outer color automatically. If you change this
+%D setting, you should do it grouped in order not to make other graphics
+%D behave in unexpected ways.
+
+\appendtoks
+ \doifelse{\directMPgraphicsparameter\c!color}\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}%
+\to \everysetupMPgraphics
+
+\setupMPgraphics
+ [\c!color=\v!local]
+
+%D This can save some runtime: rename the mpy file from a first run (when stable) to
+%D another file and reuse it. One can also use the original filename, but a copy is
+%D often better.
+%D
+%D \starttyping
+%D \setupMPgraphics
+%D [mpy=\jobname.mpy]
+%D \stoptyping
+
+\appendtoks
+ \edef\p_mpy{\directMPgraphicsparameter{mpy}}%
+ \ifx\p_mpy\empty \else
+ \let\MPdataMPYfile\p_mpy
+ \clf_registermpyfile{\p_mpy}%
+ \fi
+\to \everysetupMPgraphics
+
+%D Done.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-pag.mkiv
new file mode 100644
index 00000000000..6b6abd21135
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pag.mkiv
@@ -0,0 +1,121 @@
+%D \module
+%D [ file=meta-pag,
+%D version=1999.07.10,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D These definitions used to be part of the old \type
+%D {core-mps} file, later changed into \type {meta-ini}, but
+%D keeping them separate is cleaner.
+
+\writestatus{loading}{MetaPost Graphics / Page Data Management}
+
+\unprotect
+
+%D The next few macros tell \METAPOST\ how the \CONTEXT\
+%D pagebody looks.
+
+\startMPextensions
+ boolean PageStateAvailable;
+ PageStateAvailable:=true;
+\stopMPextensions
+
+% maybe always set as frozen anyway
+
+% \startMPinitializations
+% PaperHeight:=\the\paperheight;
+% PaperWidth:=\the\paperwidth;
+% PrintPaperHeight:=\the\printpaperheight;
+% PrintPaperWidth:=\the\printpaperwidth;
+% TopSpace:=\the\topspace;
+% BottomSpace:=\the\bottomspace;
+% BackSpace:=\the\backspace;
+% CutSpace:=\the\cutspace;
+% MakeupHeight:=\the\makeupheight;
+% MakeupWidth:=\the\makeupwidth;
+% TopHeight:=\the\topheight;
+% TopDistance:=\the\topdistance;
+% HeaderHeight:=\the\headerheight;
+% HeaderDistance:=\the\headerdistance;
+% TextHeight:=\the\textheight;
+% FooterDistance:=\the\footerdistance;
+% FooterHeight:=\the\footerheight;
+% BottomDistance:=\the\bottomdistance;
+% BottomHeight:=\the\bottomheight;
+% LeftEdgeWidth:=\the\leftedgewidth;
+% LeftEdgeDistance:=\the\leftedgedistance;
+% LeftMarginWidth:=\the\leftmarginwidth;
+% LeftMarginDistance:=\the\leftmargindistance;
+% TextWidth:=\the\textwidth;
+% RightMarginDistance:=\the\rightmargindistance;
+% RightMarginWidth:=\the\rightmarginwidth;
+% RightEdgeDistance:=\the\rightedgedistance;
+% RightEdgeWidth:=\the\rightedgewidth;
+% InnerMarginDistance:=\the\innermargindistance;
+% InnerMarginWidth:=\the\innermarginwidth;
+% OuterMarginDistance:=\the\outermargindistance;
+% OuterMarginWidth:=\the\outermarginwidth;
+% InnerEdgeDistance:=\the\inneredgedistance;
+% InnerEdgeWidth:=\the\inneredgewidth;
+% OuterEdgeDistance:=\the\outeredgedistance;
+% OuterEdgeWidth:=\the\outeredgewidth;
+% PageOffset:=\the\pagebackgroundoffset;
+% PageDepth:=\the\pagebackgrounddepth;
+% LayoutColumns:=\the\layoutcolumns;
+% LayoutColumnDistance:=\the\layoutcolumndistance;
+% LayoutColumnWidth:=\the\layoutcolumnwidth;
+% %
+% boolean OnRightPage,OnOddPage,InPageBody;
+% %
+% OnRightPage:=\MPonrightpage;
+% OnOddPage:=\MPonoddpage;
+% InPageBody:=\ifinpagebody true \else false \fi;
+% %
+% RealPageNumber:=\the\realpageno;
+% PageNumber:=\the\pageno;
+% NOfPages:=\lastpage;
+% LastPageNumber:=\lastpage;
+% %
+% CurrentColumn:=\number\mofcolumns;
+% NOfColumns:=\number\nofcolumns;
+% \stopMPinitializations
+
+\def\MPonrightpage{true}
+\def\MPonoddpage {true}
+
+\def\freezeMPpagelayout
+ {\edef\MPonrightpage{\doifbothsides {tru}{tru}{fals}e}%
+ \edef\MPonoddpage {\doifelseoddpage {tru}{fals}e}}
+
+%D We need to freeze the pagelayout before the backgrounds
+%D are build, because the overlay will temporarily become
+%D zero (overlay).
+
+\appendtoks
+ \freezeMPpagelayout
+\to \everybeforepagebody
+
+%D By freezing these value every graphic, we can use layout
+%D variables that change halfways a page, whatever use that
+%D has.
+
+% obsolete (but keep the code)
+%
+% \prependtoks
+% \calculatereducedvsizes % this is really needed
+% \freezeMPpagelayout
+% \freezeMPlayout % to be used grouped
+% \to \everyMPgraphic
+
+\prependtoks
+ \calculatereducedvsizes % bah, this is really needed
+\to \everyMPgraphic
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua
new file mode 100644
index 00000000000..3cbff63b168
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua
@@ -0,0 +1,583 @@
+if not modules then modules = { } end modules ['meta-pdf'] = {
+ version = 1.001,
+ comment = "companion to meta-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Finally we used an optimized version. The test code can be found in
+-- meta-pdh.lua but since we no longer want to overload functione we use
+-- more locals now. This module keeps changing as it is also a testbed.
+--
+-- We can make it even more efficient if needed, but as we don't use this
+-- code often in \MKIV\ it makes no sense.
+
+local concat, unpack = table.concat, table.unpack
+local gsub, find, byte, gmatch, match = string.gsub, string.find, string.byte, string.gmatch, string.match
+local lpegmatch = lpeg.match
+local round = math.round
+local formatters, format = string.formatters, string.format
+
+local report_mptopdf = logs.reporter("graphics","mptopdf")
+
+local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
+
+local texgetattribute = tex.getattribute
+
+local pdfrgbcode = lpdf.rgbcode
+local pdfcmykcode = lpdf.cmykcode
+local pdfgraycode = lpdf.graycode
+local pdfspotcode = lpdf.spotcode
+local pdftransparencycode = lpdf.transparencycode
+local pdffinishtransparencycode = lpdf.finishtransparencycode
+local pdfliteral = nodes.pool.pdfliteral
+
+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 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 specials = { }
+
+local function resetpath()
+ m_stack_close, m_stack_path, m_stack_concat = false, { }, nil
+end
+
+local function resetall()
+ m_path, m_stack, m_texts, m_version, m_shortcuts = { }, { }, { }, 0, false
+ extra_path_code, 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(pdfliteral(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
+ end
+ ignore_path = false
+ else
+ pdfcode(str)
+ end
+end
+
+-- auxiliary functions
+
+local function flushconcat()
+ if m_stack_concat then
+ mpscode(f_concat(unpack(m_stack_concat)))
+ m_stack_concat = nil
+ end
+end
+
+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 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])
+ 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])
+ end
+ path[k] = concat(v," ")
+ end
+ else
+ for k=1,#m_stack_path do
+ path[k] = concat(m_stack_path[k]," ")
+ end
+ end
+ flushconcat()
+ pdfcode(concat(path," "))
+ if m_stack_close then
+ mpscode("h " .. cmd)
+ else
+ mpscode(cmd)
+ end
+ end
+ resetpath()
+end
+
+-- mp interface
+
+local mps = { }
+
+function mps.creator(a, b, c)
+ m_version = tonumber(b)
+end
+
+function mps.creationdate(a)
+ m_date = a
+end
+
+function mps.newpath()
+ m_stack_path = { }
+end
+
+function mps.boundingbox(llx, lly, urx, ury)
+ context.setMPboundingbox(llx,lly,urx,ury)
+end
+
+function mps.moveto(x,y)
+ m_stack_path[#m_stack_path+1] = { x, y, "m" }
+end
+
+function mps.curveto(ax, ay, bx, by, cx, cy)
+ m_stack_path[#m_stack_path+1] = { ax, ay, bx, by, cx, cy, "c" }
+end
+
+function mps.lineto(x,y)
+ m_stack_path[#m_stack_path+1] = { x, y, "l" }
+end
+
+function mps.rlineto(x,y)
+ local dx, dy = 0, 0
+ local topofstack = #m_stack_path
+ if topofstack > 0 then
+ local msp = m_stack_path[topofstack]
+ dx = msp[1]
+ dy = msp[2]
+ end
+ m_stack_path[topofstack+1] = { dx, dy, "l" }
+end
+
+function mps.translate(tx,ty)
+ mpscode(f_translate(tx,ty))
+end
+
+function mps.scale(sx,sy)
+ m_stack_concat = { sx, 0, 0, sy, 0, 0 }
+end
+
+function mps.concat(sx, rx, ry, sy, tx, ty)
+ m_stack_concat = { sx, rx, ry, sy, tx, ty }
+end
+
+function mps.setlinejoin(d)
+ mpscode(d .. " j")
+end
+
+function mps.setlinecap(d)
+ mpscode(d .. " J")
+end
+
+function mps.setmiterlimit(d)
+ mpscode(d .. " M")
+end
+
+function mps.gsave()
+ mpscode("q")
+end
+
+function mps.grestore()
+ mpscode("Q")
+end
+
+function mps.setdash(...) -- can be made faster, operate on t = { ... }
+ local n = select("#",...)
+ mpscode("[" .. concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d")
+ -- mpscode("[" .. concat({select(1,n-1)}," ") .. "] " .. select(n,...) .. " d")
+end
+
+function mps.resetdash()
+ mpscode("[ ] 0 d")
+end
+
+function mps.setlinewidth(d)
+ mpscode(d .. " w")
+end
+
+function mps.closepath()
+ m_stack_close = true
+end
+
+function mps.fill()
+ flushpath('f')
+end
+
+function mps.stroke()
+ flushpath('S')
+end
+
+function mps.both()
+ flushpath('B')
+end
+
+function mps.clip()
+ flushpath('W n')
+end
+
+function mps.textext(font, scale, str) -- old parser
+ local dx, dy = 0, 0
+ if #m_stack_path > 0 then
+ dx, dy = m_stack_path[1][1], m_stack_path[1][2]
+ end
+ flushconcat()
+ context.MPtextext(font,scale,str,dx,dy)
+ resetpath()
+end
+
+local handlers = { }
+
+handlers[1] = function(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfcmykcode(mps.colormodel,s[3],s[4],s[5],s[6]))
+end
+handlers[2] = function(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfspotcode(mps.colormodel,s[3],s[4],s[5],s[6]))
+end
+handlers[3] = function(s)
+ pdfcode(pdfrgbcode(mps.colormodel,s[4],s[5],s[6]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+handlers[4] = function(s)
+ pdfcode(pdfcmykcode(mps.colormodel,s[4],s[5],s[6],s[7]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+handlers[5] = function(s)
+ pdfcode(pdfspotcode(mps.colormodel,s[4],s[5],s[6],s[7]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+
+-- todo: color conversion
+
+local nofshades, tn = 0, tonumber
+
+local function linearshade(colorspace,domain,ca,cb,coordinates)
+ pdfcode(pdffinishtransparencycode())
+ 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
+ pdfcode("q /Pattern cs")
+end
+
+local function circularshade(colorspace,domain,ca,cb,coordinates)
+ pdfcode(pdffinishtransparencycode())
+ 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
+ pdfcode("q /Pattern cs")
+end
+
+handlers[30] = function(s)
+ linearshade("DeviceRGB", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]) }, { tn(s[10]), tn(s[11]), tn(s[12]) },
+ { tn(s[ 8]), tn(s[ 9]), tn(s[13]), tn(s[14]) } )
+end
+
+handlers[31] = function(s)
+ circularshade("DeviceRGB", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]) }, { tn(s[11]), tn(s[12]), tn(s[13]) },
+ { tn(s[ 8]), tn(s[ 9]), tn(s[10]), tn(s[14]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[32] = function(s)
+ linearshade("DeviceCMYK", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]), tn(s[ 8]) }, { tn(s[11]), tn(s[12]), tn(s[13]), tn(s[14]) },
+ { tn(s[ 9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[33] = function(s)
+ circularshade("DeviceCMYK", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]), tn(s[ 8]) }, { tn(s[12]), tn(s[13]), tn(s[14]), tn(s[15]) },
+ { tn(s[ 9]), tn(s[10]), tn(s[11]), tn(s[16]), tn(s[17]), tn(s[18]) } )
+end
+
+handlers[34] = function(s) -- todo (after further cleanup)
+ linearshade("DeviceGray", { tn(s[ 2]), tn(s[ 3]) }, { 0 }, { 1 }, { tn(s[9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[35] = function(s) -- todo (after further cleanup)
+ circularshade("DeviceGray", { tn(s[ 2]), tn(s[ 3]) }, { 0 }, { 1 }, { tn(s[9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+-- not supported in mkiv , use mplib instead
+
+handlers[10] = function() report_mptopdf("skipping special %s",10) end
+handlers[20] = function() report_mptopdf("skipping special %s",20) end
+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
+ if r == 0.0123 and g < 0.1 then
+ g, b = round(g*10000), round(b*10000)
+ local s = specials[b]
+ local h = round(s[#s])
+ local handler = handlers[h]
+ if handler then
+ handler(s)
+ else
+ 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)
+ local s = specials[b]
+ local h = round(s[#s])
+ local handler = handlers[h]
+ if handler then
+ handler(s)
+ else
+ report_mptopdf("unknown special handler %s (2)",h)
+ end
+ else
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfrgbcode(mps.colormodel,r,g,b))
+ end
+end
+
+function mps.setcmykcolor(c,m,y,k)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfcmykcode(mps.colormodel,c,m,y,k))
+end
+
+function mps.setgray(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfgraycode(mps.colormodel,s))
+end
+
+function mps.specials(version,signal,factor) -- 2.0 123 1000
+end
+
+function mps.special(...) -- 7 1 0.5 1 0 0 1 3
+ local t = { ... }
+ local n = tonumber(t[#t-1])
+ specials[n] = t
+end
+
+function mps.begindata()
+end
+
+function mps.enddata()
+end
+
+function mps.showpage()
+end
+
+-- lpeg parser
+
+-- The lpeg based parser is rather optimized for the kind of output
+-- that MetaPost produces. It's my first real lpeg code, which may
+-- show. Because the parser binds to functions, we define it last.
+
+local lpegP, lpegR, lpegS, lpegC, lpegCc, lpegCs = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs
+
+local digit = lpegR("09")
+local eol = lpegS('\r\n')^1
+local sp = lpegP(' ')^1
+local space = lpegS(' \r\n')^1
+local number = lpegS('0123456789.-+')^1
+local nonspace = lpegP(1-lpegS(' \r\n'))^1
+
+local spec = digit^2 * lpegP("::::") * digit^2
+local text = lpegCc("{") * (
+ lpegP("\\") * ( (digit * digit * digit) / function(n) return "c" .. tonumber(n,8) end) +
+ lpegP(" ") / function(n) return "\\c32" end + -- never in new mp
+ lpegP(1) / function(n) return "\\c" .. byte(n) end
+ ) * lpegCc("}")
+local package = lpegCs(spec + text^0)
+
+function mps.fshow(str,font,scale) -- lpeg parser
+ mps.textext(font,scale,lpegmatch(package,str))
+end
+
+----- cnumber = lpegC(number)
+local cnumber = number/tonumber -- we now expect numbers (feeds into %F)
+local cstring = lpegC(nonspace)
+
+local specials = (lpegP("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mps.specials
+local special = (lpegP("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mps.special
+local boundingbox = (lpegP("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+local highresboundingbox = (lpegP("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+
+local setup = lpegP("%%BeginSetup") * (1 - lpegP("%%EndSetup") )^1
+local prolog = lpegP("%%BeginProlog") * (1 - lpegP("%%EndProlog"))^1
+local comment = lpegP('%')^1 * (1 - eol)^1
+
+local curveto = ((cnumber * sp)^6 * lpegP("curveto") ) / mps.curveto
+local lineto = ((cnumber * sp)^2 * lpegP("lineto") ) / mps.lineto
+local rlineto = ((cnumber * sp)^2 * lpegP("rlineto") ) / mps.rlineto
+local moveto = ((cnumber * sp)^2 * lpegP("moveto") ) / mps.moveto
+local setrgbcolor = ((cnumber * sp)^3 * lpegP("setrgbcolor") ) / mps.setrgbcolor
+local setcmykcolor = ((cnumber * sp)^4 * lpegP("setcmykcolor") ) / mps.setcmykcolor
+local setgray = ((cnumber * sp)^1 * lpegP("setgray") ) / mps.setgray
+local newpath = ( lpegP("newpath") ) / mps.newpath
+local closepath = ( lpegP("closepath") ) / mps.closepath
+local fill = ( lpegP("fill") ) / mps.fill
+local stroke = ( lpegP("stroke") ) / mps.stroke
+local clip = ( lpegP("clip") ) / mps.clip
+local both = ( lpegP("gsave fill grestore")) / mps.both
+local showpage = ( lpegP("showpage") )
+local setlinejoin = ((cnumber * sp)^1 * lpegP("setlinejoin") ) / mps.setlinejoin
+local setlinecap = ((cnumber * sp)^1 * lpegP("setlinecap") ) / mps.setlinecap
+local setmiterlimit = ((cnumber * sp)^1 * lpegP("setmiterlimit") ) / mps.setmiterlimit
+local gsave = ( lpegP("gsave") ) / mps.gsave
+local grestore = ( lpegP("grestore") ) / mps.grestore
+
+local setdash = (lpegP("[") * (cnumber * sp^0)^0 * lpegP("]") * sp * cnumber * sp * lpegP("setdash")) / mps.setdash
+local concat = (lpegP("[") * (cnumber * sp^0)^6 * lpegP("]") * sp * lpegP("concat") ) / mps.concat
+local scale = ( (cnumber * sp^0)^6 * sp * lpegP("concat") ) / mps.concat
+
+local fshow = (lpegP("(") * lpegC((1-lpegP(")"))^1) * lpegP(")") * space * cstring * space * cnumber * space * lpegP("fshow")) / mps.fshow
+local fshow = (lpegP("(") * lpegCs( ( lpegP("\\(")/"\\050" + lpegP("\\)")/"\\051" + (1-lpegP(")")) )^1 )
+ * lpegP(")") * space * cstring * space * cnumber * space * lpegP("fshow")) / mps.fshow
+
+local setlinewidth_x = (lpegP("0") * sp * cnumber * sp * lpegP("dtransform truncate idtransform setlinewidth pop")) / mps.setlinewidth
+local setlinewidth_y = (cnumber * sp * lpegP("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mps.setlinewidth
+
+local c = ((cnumber * sp)^6 * lpegP("c") ) / mps.curveto -- ^6 very inefficient, ^1 ok too
+local l = ((cnumber * sp)^2 * lpegP("l") ) / mps.lineto
+local r = ((cnumber * sp)^2 * lpegP("r") ) / mps.rlineto
+local m = ((cnumber * sp)^2 * lpegP("m") ) / mps.moveto
+local vlw = ((cnumber * sp)^1 * lpegP("vlw")) / mps.setlinewidth
+local hlw = ((cnumber * sp)^1 * lpegP("hlw")) / mps.setlinewidth
+
+local R = ((cnumber * sp)^3 * lpegP("R") ) / mps.setrgbcolor
+local C = ((cnumber * sp)^4 * lpegP("C") ) / mps.setcmykcolor
+local G = ((cnumber * sp)^1 * lpegP("G") ) / mps.setgray
+
+local lj = ((cnumber * sp)^1 * lpegP("lj") ) / mps.setlinejoin
+local ml = ((cnumber * sp)^1 * lpegP("ml") ) / mps.setmiterlimit
+local lc = ((cnumber * sp)^1 * lpegP("lc") ) / mps.setlinecap
+
+local n = lpegP("n") / mps.newpath
+local p = lpegP("p") / mps.closepath
+local S = lpegP("S") / mps.stroke
+local F = lpegP("F") / mps.fill
+local B = lpegP("B") / mps.both
+local W = lpegP("W") / mps.clip
+local P = lpegP("P") / mps.showpage
+
+local q = lpegP("q") / mps.gsave
+local Q = lpegP("Q") / mps.grestore
+
+local sd = (lpegP("[") * (cnumber * sp^0)^0 * lpegP("]") * sp * cnumber * sp * lpegP("sd")) / mps.setdash
+local rd = ( lpegP("rd")) / mps.resetdash
+
+local s = ( (cnumber * sp^0)^2 * lpegP("s") ) / mps.scale
+local t = (lpegP("[") * (cnumber * sp^0)^6 * lpegP("]") * sp * lpegP("t") ) / mps.concat
+
+-- experimental
+
+local preamble = (
+ prolog + setup +
+ boundingbox + highresboundingbox + specials + special +
+ comment
+)
+
+local procset = (
+ lj + ml + lc +
+ c + l + m + n + p + r +
+ R + C + G +
+ S + F + B + W +
+ vlw + hlw +
+ Q + q +
+ sd + rd +
+ t + s +
+ fshow +
+ P
+)
+
+local verbose = (
+ curveto + lineto + moveto + newpath + closepath + rlineto +
+ setrgbcolor + setcmykcolor + setgray +
+ setlinejoin + setmiterlimit + setlinecap +
+ stroke + fill + clip + both +
+ setlinewidth_x + setlinewidth_y +
+ gsave + grestore +
+ concat + scale +
+ fshow +
+ setdash + -- no resetdash
+ showpage
+)
+
+-- order matters in terms of speed / we could check for procset first
+
+local captures_old = ( space + verbose + preamble )^0
+local captures_new = ( space + verbose + procset + preamble )^0
+
+local function parse(m_data)
+ if find(m_data,"%%%%BeginResource: procset mpost") then
+ -- report_mptopdf("using sparse scanner, case 1")
+ lpegmatch(captures_new,m_data)
+ elseif find(m_data,"%%%%BeginProlog%s*%S+(.-)%%%%EndProlog") then
+ -- report_mptopdf("using sparse scanner, case 2")
+ lpegmatch(captures_new,m_data)
+ else
+ -- report_mptopdf("using verbose ps scanner")
+ lpegmatch(captures_old,m_data)
+ end
+end
+
+-- main converter
+
+local a_colorspace = attributes.private('colormodel')
+
+function mptopdf.convertmpstopdf(name)
+ resetall()
+ local ok, m_data, n = resolvers.loadbinfile(name, 'tex') -- we need a binary load !
+ if ok then
+ mps.colormodel = texgetattribute(a_colorspace)
+ statistics.starttiming(mptopdf)
+ mptopdf.nofconverted = mptopdf.nofconverted + 1
+ pdfcode(formatters["\\letterpercent\\space mptopdf begin: n=%s, file=%s"](mptopdf.nofconverted,file.basename(name)))
+ pdfcode("q 1 0 0 1 0 0 cm")
+ parse(m_data)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode("Q")
+ pdfcode("\\letterpercent\\space mptopdf end")
+ resetall()
+ statistics.stoptiming(mptopdf)
+ else
+ report_mptopdf("file %a not found",name)
+ end
+end
+
+-- status info
+
+statistics.register("mps conversion time",function()
+ local n = mptopdf.nofconverted
+ if n > 0 then
+ return format("%s seconds, %s conversions", statistics.elapsedtime(mptopdf),n)
+ else
+ return nil
+ end
+end)
+
+-- interface
+
+interfaces.implement {
+ name = "convertmpstopdf",
+ arguments = "string",
+ actions = mptopdf.convertmpstopdf
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.mkiv
new file mode 100644
index 00000000000..14c97042e3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.mkiv
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=meta-pdf,
+%D version=2006.06.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Conversion to \PDF,
+%D author=Hans Hagen \& others (see text),
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{meta-pdf}{1.003}
+
+\writestatus{loading}{MetaPost Graphics / MPS to PDF}
+
+\unprotect
+
+%D \macros
+%D {convertMPtoPDF}
+%D
+%D The next set of macros implements \METAPOST\ to \PDF\ conversion. The
+%D traditional method is in the MkII files and the older \MKIV\ method is
+%D kept in meta-pdh files. The main conversion command is still the same
+%D but the scale parameters are ignored in \MKIV:
+%D
+%D \starttyping
+%D \convertMPtoPDF {filename} {x scale} {y scale}
+%D \stoptyping
+%D
+%D Much code has gone due to the fact that we now use pre and post scripts
+%D and no specials. This also means that you should use a modern \METAPOST\
+%D or reprocess graphics. The color control flags are also gone as we now
+%D integrate into the regular colorspace handling (i.e.\ no longer independent
+%D configurations.)
+
+\def\PDFMPformoffset{\ifdefined\objectoffset\objectoffset\else\zeropoint\fi} % obsolete, will go
+
+\unexpanded\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 are ignored)
+ {\dostarttagged\t!mpgraphic\empty
+ \naturalvpack attr \imageattribute 1 \bgroup
+ \message{[MP to PDF]}%
+ \xdef\MPfilename{#1}%
+ \resetMPboundingbox
+ \forgetall
+ \offinterlineskip
+ \setbox\MPbox\vpack\bgroup
+ \clf_convertmpstopdf{\MPfilename}%
+ \removeunwantedspaces % not that needed
+ \egroup
+ \finalizeMPbox
+ \box\MPbox
+ \egroup
+ \dostoptagged}
+
+\protect \endinput
+
+%D Test code:
+%D
+%D \startbuffer
+%D \startMPcode
+%D fill fullcircle scaled 3cm withcolor red ;
+%D fill fullcircle scaled 2cm withcolor green ;
+%D fill fullcircle scaled 1cm withcolor blue ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+%D fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+%D fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D draw fullcircle scaled 3cm dashed evenly ;
+%D draw fullcircle scaled 2cm dashed withdots ;
+%D draw origin withpen pencircle scaled 3mm;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+%D fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+%D fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+%D fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+%D currentpicture := currentpicture shifted (12cm,-4cm) ;
+%D draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D % bug: shift
+%D draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+%D draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+%D filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D % shade cannot handle shift
+%D circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+%D circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+%D filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ;
+%D \stopMPcode
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.lua
new file mode 100644
index 00000000000..5040715c4f9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.lua
@@ -0,0 +1,610 @@
+if not modules then modules = { } end modules ['meta-pdf'] = {
+ version = 1.001,
+ comment = "companion to meta-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if true then
+ return -- or os.exit()
+end
+
+-- This file contains the history of the converter. We keep it around as it
+-- relates to the development of luatex.
+
+-- This is the third version. Version 1 converted to Lua code,
+-- version 2 gsubbed the file into TeX code, and version 3 uses
+-- the new lpeg functionality and streams the result into TeX.
+
+-- We will move old stuff to edu.
+
+--~ old lpeg 0.4 lpeg 0.5
+--~ 100 times test graphic 2.45 (T:1.07) 0.72 (T:0.24) 0.580 (0.560 no table) -- 0.54 optimized for one space (T:0.19)
+--~ 100 times big graphic 10.44 4.30/3.35 nogb 2.914 (2.050 no table) -- 1.99 optimized for one space (T:0.85)
+--~ 500 times test graphic T:1.29 T:1.16 (T:1.10 no table) -- T:1.10
+
+-- only needed for mp output on disk
+
+local concat, format, find, gsub, gmatch = table.concat, string.format, string.find, string.gsub, string.gmatch
+local tostring, tonumber, select = tostring, tonumber, select
+local lpegmatch = lpeg.match
+
+local metapost = metapost
+
+metapost.mptopdf = metapost.mptopdf or { }
+local mptopdf = metapost.mptopdf
+
+mptopdf.parsers = { }
+mptopdf.parser = 'none'
+mptopdf.nofconverted = 0
+
+function mptopdf.reset()
+ mptopdf.data = ""
+ mptopdf.path = { }
+ mptopdf.stack = { }
+ mptopdf.texts = { }
+ mptopdf.version = 0
+ mptopdf.shortcuts = false
+ mptopdf.resetpath()
+end
+
+function mptopdf.resetpath()
+ mptopdf.stack.close = false
+ mptopdf.stack.path = { }
+ mptopdf.stack.concat = nil
+ mptopdf.stack.special = false
+end
+
+mptopdf.reset()
+
+function mptopdf.parsers.none()
+ -- no parser set
+end
+
+function mptopdf.parse()
+ mptopdf.parsers[mptopdf.parser]()
+end
+
+-- old code
+
+mptopdf.steps = { }
+
+mptopdf.descapes = {
+ ['('] = "\\\\char40 ",
+ [')'] = "\\\\char41 ",
+ ['"'] = "\\\\char92 "
+}
+
+function mptopdf.descape(str)
+ str = gsub(str,"\\(%d%d%d)",function(n)
+ return "\\char" .. tonumber(n,8) .. " "
+ end)
+ return gsub(str,"\\([%(%)\\])",mptopdf.descapes)
+end
+
+function mptopdf.steps.descape(str)
+ str = gsub(str,"\\(%d%d%d)",function(n)
+ return "\\\\char" .. tonumber(n,8) .. " "
+ end)
+ return gsub(str,"\\([%(%)\\])",mptopdf.descapes)
+end
+
+function mptopdf.steps.strip() -- .3 per expr
+ mptopdf.data = gsub(mptopdf.data,"^(.-)%%+Page:.-%c+(.*)%s+%a+%s+%%+EOF.*$", function(preamble, graphic)
+ local bbox = "0 0 0 0"
+ for b in gmatch(preamble,"%%%%%a+oundingBox: +(.-)%c+") do
+ bbox = b
+ end
+ local name, version = gmatch(preamble,"%%%%Creator: +(.-) +(.-) ")
+ mptopdf.version = tostring(version or "0")
+ if find(preamble,"/hlw{0 dtransform") then
+ mptopdf.shortcuts = true
+ end
+ -- the boundingbox specification needs to come before data, well, not really
+ return bbox .. " boundingbox\n" .. "\nbegindata\n" .. graphic .. "\nenddata\n"
+ end, 1)
+ mptopdf.data = gsub(mptopdf.data,"%%%%MetaPostSpecials: +(.-)%c+", "%1 specials\n", 1)
+ mptopdf.data = gsub(mptopdf.data,"%%%%MetaPostSpecial: +(.-)%c+", "%1 special\n")
+ mptopdf.data = gsub(mptopdf.data,"%%.-%c+", "")
+end
+
+function mptopdf.steps.cleanup()
+ if not mptopdf.shortcuts then
+ mptopdf.data = gsub(mptopdf.data,"gsave%s+fill%s+grestore%s+stroke", "both")
+ mptopdf.data = gsub(mptopdf.data,"([%d%.]+)%s+([%d%.]+)%s+dtransform%s+exch%s+truncate%s+exch%s+idtransform%s+pop%s+setlinewidth", function(wx,wy)
+ if tonumber(wx) > 0 then return wx .. " setlinewidth" else return wy .. " setlinewidth" end
+ end)
+ mptopdf.data = gsub(mptopdf.data,"([%d%.]+)%s+([%d%.]+)%s+dtransform%s+truncate%s+idtransform%s+setlinewidth%s+pop", function(wx,wy)
+ if tonumber(wx) > 0 then return wx .. " setlinewidth" else return wy .. " setlinewidth" end
+ end)
+ end
+end
+
+function mptopdf.steps.convert()
+ mptopdf.data = gsub(mptopdf.data,"%c%((.-)%) (.-) (.-) fshow", function(str,font,scale)
+ mptopdf.texts[mptopdf.texts+1] = {mptopdf.steps.descape(str), font, scale}
+ return "\n" .. #mptopdf.texts .. " textext"
+ end)
+ mptopdf.data = gsub(mptopdf.data,"%[%s*(.-)%s*%]", function(str)
+ return gsub(str,"%s+"," ")
+ end)
+ local t
+ mptopdf.data = gsub(mptopdf.data,"%s*([^%a]-)%s*(%a+)", function(args,cmd)
+ if cmd == "textext" then
+ t = mptopdf.texts[tonumber(args)]
+ return "metapost.mps.textext(" .. "\"" .. t[2] .. "\"," .. t[3] .. ",\"" .. t[1] .. "\")\n"
+ else
+ return "metapost.mps." .. cmd .. "(" .. gsub(args," +",",") .. ")\n"
+ end
+ end)
+end
+
+function mptopdf.steps.process()
+ assert(loadstring(mptopdf.data))() -- () runs the loaded chunk
+end
+
+function mptopdf.parsers.gsub()
+ mptopdf.steps.strip()
+ mptopdf.steps.cleanup()
+ mptopdf.steps.convert()
+ mptopdf.steps.process()
+end
+
+-- end of old code
+
+-- from lua to tex
+
+function mptopdf.pdfcode(str)
+ context.pdfliteral(str) -- \\MPScode
+end
+
+function mptopdf.texcode(str)
+ context(str)
+end
+
+-- auxiliary functions
+
+function mptopdf.flushconcat()
+ if mptopdf.stack.concat then
+ mptopdf.pdfcode(concat(mptopdf.stack.concat," ") .. " cm")
+ mptopdf.stack.concat = nil
+ end
+end
+
+function mptopdf.flushpath(cmd)
+ -- faster: no local function and loop
+ if #mptopdf.stack.path > 0 then
+ local path = { }
+ if mptopdf.stack.concat then
+ local sx, sy = mptopdf.stack.concat[1], mptopdf.stack.concat[4]
+ local rx, ry = mptopdf.stack.concat[2], mptopdf.stack.concat[3]
+ local tx, ty = mptopdf.stack.concat[5], mptopdf.stack.concat[6]
+ local d = (sx*sy) - (rx*ry)
+ local function mpconcat(px, py)
+ return (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d
+ end
+ local stackpath = mptopdf.stack.path
+ for k=1,#stackpath do
+ local v = stackpath[k]
+ v[1],v[2] = mpconcat(v[1],v[2])
+ if #v == 7 then
+ v[3],v[4] = mpconcat(v[3],v[4])
+ v[5],v[6] = mpconcat(v[5],v[6])
+ end
+ path[#path+1] = concat(v," ")
+ end
+ else
+ local stackpath = mptopdf.stack.path
+ for k=1,#stackpath do
+ path[#path+1] = concat(stackpath[k]," ")
+ end
+ end
+ mptopdf.flushconcat()
+ mptopdf.texcode("\\MPSpath{" .. concat(path," ") .. "}")
+ if mptopdf.stack.close then
+ mptopdf.texcode("\\MPScode{h " .. cmd .. "}")
+ else
+ mptopdf.texcode("\\MPScode{" .. cmd .."}")
+ end
+ end
+ mptopdf.resetpath()
+end
+
+function mptopdf.loaded(name)
+ local ok, n
+ mptopdf.reset()
+ ok, mptopdf.data, n = resolvers.loadbinfile(name, 'tex') -- we need a binary load !
+ return ok
+end
+
+if not mptopdf.parse then
+ function mptopdf.parse() end -- forward declaration
+end
+
+function mptopdf.convertmpstopdf(name)
+ if mptopdf.loaded(name) then
+ mptopdf.nofconverted = mptopdf.nofconverted + 1
+ statistics.starttiming(mptopdf)
+ mptopdf.parse()
+ mptopdf.reset()
+ statistics.stoptiming(mptopdf)
+ else
+ context("file " .. name .. " not found")
+ end
+end
+
+-- mp interface
+
+metapost.mps = metapost.mps or { }
+local mps = metapost.mps or { }
+
+function mps.creator(a, b, c)
+ mptopdf.version = tonumber(b)
+end
+
+function mps.creationdate(a)
+ mptopdf.date= a
+end
+
+function mps.newpath()
+ mptopdf.stack.path = { }
+end
+
+function mps.boundingbox(llx, lly, urx, ury)
+ mptopdf.texcode("\\MPSboundingbox{" .. llx .. "}{" .. lly .. "}{" .. urx .. "}{" .. ury .. "}")
+end
+
+function mps.moveto(x,y)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"m"}
+end
+
+function mps.curveto(ax, ay, bx, by, cx, cy)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {ax,ay,bx,by,cx,cy,"c"}
+end
+
+function mps.lineto(x,y)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"l"}
+end
+
+function mps.rlineto(x,y)
+ local dx, dy = 0, 0
+ if #mptopdf.stack.path > 0 then
+ dx, dy = mptopdf.stack.path[#mptopdf.stack.path][1], mptopdf.stack.path[#mptopdf.stack.path][2]
+ end
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {dx,dy,"l"}
+end
+
+function mps.translate(tx,ty)
+ mptopdf.pdfcode("1 0 0 0 1 " .. tx .. " " .. ty .. " cm")
+end
+
+function mps.scale(sx,sy)
+ mptopdf.stack.concat = {sx,0,0,sy,0,0}
+end
+
+function mps.concat(sx, rx, ry, sy, tx, ty)
+ mptopdf.stack.concat = {sx,rx,ry,sy,tx,ty}
+end
+
+function mps.setlinejoin(d)
+ mptopdf.pdfcode(d .. " j")
+end
+
+function mps.setlinecap(d)
+ mptopdf.pdfcode(d .. " J")
+end
+
+function mps.setmiterlimit(d)
+ mptopdf.pdfcode(d .. " M")
+end
+
+function mps.gsave()
+ mptopdf.pdfcode("q")
+end
+
+function mps.grestore()
+ mptopdf.pdfcode("Q")
+end
+
+function mps.setdash(...)
+ local n = select("#",...)
+ mptopdf.pdfcode("[" .. concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d")
+end
+
+function mps.resetdash()
+ mptopdf.pdfcode("[ ] 0 d")
+end
+
+function mps.setlinewidth(d)
+ mptopdf.pdfcode(d .. " w")
+end
+
+function mps.closepath()
+ mptopdf.stack.close = true
+end
+
+function mps.fill()
+ mptopdf.flushpath('f')
+end
+
+function mps.stroke()
+ mptopdf.flushpath('S')
+end
+
+function mps.both()
+ mptopdf.flushpath('B')
+end
+
+function mps.clip()
+ mptopdf.flushpath('W n')
+end
+
+function mps.textext(font, scale, str) -- old parser
+ local dx, dy = 0, 0
+ if #mptopdf.stack.path > 0 then
+ dx, dy = mptopdf.stack.path[1][1], mptopdf.stack.path[1][2]
+ end
+ mptopdf.flushconcat()
+ mptopdf.texcode("\\MPStextext{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
+ mptopdf.resetpath()
+end
+
+--~ function mps.handletext(font,scale.str,dx,dy)
+--~ local one, two = string.match(str, "^(%d+)::::(%d+)")
+--~ if one and two then
+--~ mptopdf.texcode("\\MPTOPDFtextext{"..font.."}{"..scale.."}{"..one.."}{"..two.."}{"..dx.."}{"..dy.."}")
+--~ else
+--~ mptopdf.texcode("\\MPTOPDFtexcode{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
+--~ end
+--~ end
+
+function mps.setrgbcolor(r,g,b) -- extra check
+ r, g = tonumber(r), tonumber(g) -- needed when we use lpeg
+ if r == 0.0123 and g < 0.1 then
+ mptopdf.texcode("\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}")
+ elseif r == 0.123 and g < 0.1 then
+ mptopdf.texcode("\\MPSspecial{" .. g* 1000 .. "}{" .. b* 1000 .. "}")
+ else
+ mptopdf.texcode("\\MPSrgb{" .. r .. "}{" .. g .. "}{" .. b .. "}")
+ end
+end
+
+function mps.setcmykcolor(c,m,y,k)
+ mptopdf.texcode("\\MPScmyk{" .. c .. "}{" .. m .. "}{" .. y .. "}{" .. k .. "}")
+end
+
+function mps.setgray(s)
+ mptopdf.texcode("\\MPSgray{" .. s .. "}")
+end
+
+function mps.specials(version,signal,factor) -- 2.0 123 1000
+end
+
+function mps.special(...) -- 7 1 0.5 1 0 0 1 3
+ local n = select("#",...)
+ mptopdf.texcode("\\MPSbegin\\MPSset{" .. concat({...},"}\\MPSset{",2,n) .. "}\\MPSend")
+end
+
+function mps.begindata()
+end
+
+function mps.enddata()
+end
+
+function mps.showpage()
+end
+
+mps.n = mps.newpath -- n
+mps.p = mps.closepath -- h
+mps.l = mps.lineto -- l
+mps.r = mps.rlineto -- r
+mps.m = mps.moveto -- m
+mps.c = mps.curveto -- c
+mps.hlw = mps.setlinewidth
+mps.vlw = mps.setlinewidth
+
+mps.C = mps.setcmykcolor -- k
+mps.G = mps.setgray -- g
+mps.R = mps.setrgbcolor -- rg
+
+mps.lj = mps.setlinejoin -- j
+mps.ml = mps.setmiterlimit -- M
+mps.lc = mps.setlinecap -- J
+mps.sd = mps.setdash -- d
+mps.rd = mps.resetdash
+
+mps.S = mps.stroke -- S
+mps.F = mps.fill -- f
+mps.B = mps.both -- B
+mps.W = mps.clip -- W
+
+mps.q = mps.gsave -- q
+mps.Q = mps.grestore -- Q
+
+mps.s = mps.scale -- (not in pdf)
+mps.t = mps.concat -- (not the same as pdf anyway)
+
+mps.P = mps.showpage
+
+-- experimental
+
+function mps.attribute(id,value)
+ mptopdf.texcode("\\attribute " .. id .. "=" .. value .. " ")
+-- mptopdf.texcode("\\dompattribute{" .. id .. "}{" .. value .. "}")
+end
+
+-- lpeg parser
+
+-- The lpeg based parser is rather optimized for the kind of output
+-- that MetaPost produces. It's my first real lpeg code, which may
+-- show. Because the parser binds to functions, we define it last.
+
+do -- assumes \let\c\char
+
+ local byte = string.byte
+ local digit = lpeg.R("09")
+ local spec = digit^2 * lpeg.P("::::") * digit^2
+ local text = lpeg.Cc("{") * (
+ lpeg.P("\\") * ( (digit * digit * digit) / function(n) return "c" .. tonumber(n,8) end) +
+ lpeg.P(" ") / function(n) return "\\c32" end + -- never in new mp
+ lpeg.P(1) / function(n) return "\\c" .. byte(n) end
+ ) * lpeg.Cc("}")
+ local package = lpeg.Cs(spec + text^0)
+
+ function mps.fshow(str,font,scale) -- lpeg parser
+ mps.textext(font,scale,lpegmatch(package,str))
+ end
+
+end
+
+do
+
+ local eol = lpeg.S('\r\n')^1
+ local sp = lpeg.P(' ')^1
+ local space = lpeg.S(' \r\n')^1
+ local number = lpeg.S('0123456789.-+')^1
+ local nonspace = lpeg.P(1-lpeg.S(' \r\n'))^1
+
+ local cnumber = lpeg.C(number)
+ local cstring = lpeg.C(nonspace)
+
+ local specials = (lpeg.P("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mps.specials
+ local special = (lpeg.P("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mps.special
+ local boundingbox = (lpeg.P("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+ local highresboundingbox = (lpeg.P("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+
+ local setup = lpeg.P("%%BeginSetup") * (1 - lpeg.P("%%EndSetup") )^1
+ local prolog = lpeg.P("%%BeginProlog") * (1 - lpeg.P("%%EndProlog"))^1
+ local comment = lpeg.P('%')^1 * (1 - eol)^1
+
+ local curveto = ((cnumber * sp)^6 * lpeg.P("curveto") ) / mps.curveto
+ local lineto = ((cnumber * sp)^2 * lpeg.P("lineto") ) / mps.lineto
+ local rlineto = ((cnumber * sp)^2 * lpeg.P("rlineto") ) / mps.rlineto
+ local moveto = ((cnumber * sp)^2 * lpeg.P("moveto") ) / mps.moveto
+ local setrgbcolor = ((cnumber * sp)^3 * lpeg.P("setrgbcolor") ) / mps.setrgbcolor
+ local setcmykcolor = ((cnumber * sp)^4 * lpeg.P("setcmykcolor") ) / mps.setcmykcolor
+ local setgray = ((cnumber * sp)^1 * lpeg.P("setgray") ) / mps.setgray
+ local newpath = ( lpeg.P("newpath") ) / mps.newpath
+ local closepath = ( lpeg.P("closepath") ) / mps.closepath
+ local fill = ( lpeg.P("fill") ) / mps.fill
+ local stroke = ( lpeg.P("stroke") ) / mps.stroke
+ local clip = ( lpeg.P("clip") ) / mps.clip
+ local both = ( lpeg.P("gsave fill grestore")) / mps.both
+ local showpage = ( lpeg.P("showpage") )
+ local setlinejoin = ((cnumber * sp)^1 * lpeg.P("setlinejoin") ) / mps.setlinejoin
+ local setlinecap = ((cnumber * sp)^1 * lpeg.P("setlinecap") ) / mps.setlinecap
+ local setmiterlimit = ((cnumber * sp)^1 * lpeg.P("setmiterlimit") ) / mps.setmiterlimit
+ local gsave = ( lpeg.P("gsave") ) / mps.gsave
+ local grestore = ( lpeg.P("grestore") ) / mps.grestore
+
+ local setdash = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("setdash")) / mps.setdash
+ local concat = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("concat") ) / mps.concat
+ local scale = ( (cnumber * sp^0)^6 * sp * lpeg.P("concat") ) / mps.concat
+
+ local fshow = (lpeg.P("(") * lpeg.C((1-lpeg.P(")"))^1) * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow
+ local fshow = (lpeg.P("(") *
+ lpeg.Cs( ( lpeg.P("\\(")/"\\050" + lpeg.P("\\)")/"\\051" + (1-lpeg.P(")")) )^1 )
+ * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow
+
+ local setlinewidth_x = (lpeg.P("0") * sp * cnumber * sp * lpeg.P("dtransform truncate idtransform setlinewidth pop")) / mps.setlinewidth
+ local setlinewidth_y = (cnumber * sp * lpeg.P("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mps.setlinewidth
+
+ local c = ((cnumber * sp)^6 * lpeg.P("c") ) / mps.curveto -- ^6 very inefficient, ^1 ok too
+ local l = ((cnumber * sp)^2 * lpeg.P("l") ) / mps.lineto
+ local r = ((cnumber * sp)^2 * lpeg.P("r") ) / mps.rlineto
+ local m = ((cnumber * sp)^2 * lpeg.P("m") ) / mps.moveto
+ local vlw = ((cnumber * sp)^1 * lpeg.P("vlw")) / mps.setlinewidth
+ local hlw = ((cnumber * sp)^1 * lpeg.P("hlw")) / mps.setlinewidth
+
+ local R = ((cnumber * sp)^3 * lpeg.P("R") ) / mps.setrgbcolor
+ local C = ((cnumber * sp)^4 * lpeg.P("C") ) / mps.setcmykcolor
+ local G = ((cnumber * sp)^1 * lpeg.P("G") ) / mps.setgray
+
+ local lj = ((cnumber * sp)^1 * lpeg.P("lj") ) / mps.setlinejoin
+ local ml = ((cnumber * sp)^1 * lpeg.P("ml") ) / mps.setmiterlimit
+ local lc = ((cnumber * sp)^1 * lpeg.P("lc") ) / mps.setlinecap
+
+ local n = lpeg.P("n") / mps.newpath
+ local p = lpeg.P("p") / mps.closepath
+ local S = lpeg.P("S") / mps.stroke
+ local F = lpeg.P("F") / mps.fill
+ local B = lpeg.P("B") / mps.both
+ local W = lpeg.P("W") / mps.clip
+ local P = lpeg.P("P") / mps.showpage
+
+ local q = lpeg.P("q") / mps.gsave
+ local Q = lpeg.P("Q") / mps.grestore
+
+ local sd = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("sd")) / mps.setdash
+ local rd = ( lpeg.P("rd")) / mps.resetdash
+
+ local s = ( (cnumber * sp^0)^2 * lpeg.P("s") ) / mps.scale
+ local t = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("t") ) / mps.concat
+
+ -- experimental
+
+ local attribute = ((cnumber * sp)^2 * lpeg.P("attribute")) / mps.attribute
+ local A = ((cnumber * sp)^2 * lpeg.P("A")) / mps.attribute
+
+ local preamble = (
+ prolog + setup +
+ boundingbox + highresboundingbox + specials + special +
+ comment
+ )
+
+ local procset = (
+ lj + ml + lc +
+ c + l + m + n + p + r +
+ A +
+ R + C + G +
+ S + F + B + W +
+ vlw + hlw +
+ Q + q +
+ sd + rd +
+ t + s +
+ fshow +
+ P
+ )
+
+ local verbose = (
+ curveto + lineto + moveto + newpath + closepath + rlineto +
+ setrgbcolor + setcmykcolor + setgray +
+ attribute +
+ setlinejoin + setmiterlimit + setlinecap +
+ stroke + fill + clip + both +
+ setlinewidth_x + setlinewidth_y +
+ gsave + grestore +
+ concat + scale +
+ fshow +
+ setdash + -- no resetdash
+ showpage
+ )
+
+ -- order matters in terms of speed / we could check for procset first
+
+ local captures_old = ( space + verbose + preamble )^0
+ local captures_new = ( space + procset + preamble + verbose )^0
+
+ function mptopdf.parsers.lpeg()
+ if find(mptopdf.data,"%%%%BeginResource: procset mpost") then
+ lpegmatch(captures_new,mptopdf.data)
+ else
+ lpegmatch(captures_old,mptopdf.data)
+ end
+ end
+
+end
+
+mptopdf.parser = 'lpeg'
+
+-- status info
+
+statistics.register("mps conversion time",function()
+ local n = mptopdf.nofconverted
+ if n > 0 then
+ return format("%s seconds, %s conversions", statistics.elapsedtime(mptopdf),n)
+ else
+ return nil
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv
new file mode 100644
index 00000000000..3787a56389b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv
@@ -0,0 +1,773 @@
+%D \module
+%D [ file=meta-pdf,
+%D version=2006.06.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Conversion to \PDF,
+%D author=Hans Hagen \& others (see text),
+%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.
+
+\endinput
+
+%D Formerly known as supp-pdf.tex and supp-mpe.tex and meta-pdf.mkiv.
+%D
+%D Beware: this file is not used but kept for historic purposed! Never
+%D mix this one into mkiv again as it uses other variables.
+
+% \useMPgraphic{1}
+% \testfeatureonce{250}{\setbox0\hbox{\convertMPtoPDF{test-mps-mpgraph.1}{1}{1}}}
+%
+% 8.4 : mkii, direct parsing by tex
+% 11.8 : mkiv, dirty conversion (10.8 with dirty tricks)
+% 14.5 : mkiv, clean conversion
+% 7.4 : mkiv, simulated clean direct lua from mp
+% 0.3 : time taken by tex to handle converted code
+%
+% timings may differ now that we revamped the backend
+
+\registerctxluafile{meta-pdf}{1.003}
+
+%D We will clean up the color mess later.
+
+\writestatus{loading}{MetaPost Graphics / MPS to PDF}
+
+\unprotect
+
+%D First we define a handy constant:
+
+\bgroup \catcode\commentasciicode\othercatcode \xdef\letterpercent{\string%} \egroup
+
+%D \macros
+%D {convertMPtoPDF}
+%D
+%D The next set of macros implements \METAPOST\ to \PDF\
+%D conversion. The traditional method is in the MkII file.
+%D
+%D The main conversion command is:
+%D
+%D \starttyping
+%D \convertMPtoPDF {filename} {x scale} {y scale}
+%D \stoptyping
+%D
+%D The dimensions are derived from the bounding box. So we
+%D only have to say:
+%D
+%D \starttyping
+%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
+%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
+%D \stoptyping
+
+%D \macros
+%D {makeMPintoPDFobject,lastPDFMPobject}
+%D
+%D For experts there are a few more options. When attributes
+%D are to be added, the code must be embedded in an object
+%D accompanied with the appropriate directives. One can
+%D influence this process with \type {\makeMPintoPDFobject}.
+%D
+%D This option defaults to~0, because \CONTEXT\ takes care
+%D of objects at another level, which saves some bytes.
+%D
+%D \starttabulate[|l|l|p|]
+%D \NC 0 \NC never \NC don't use an object \NC\NR
+%D \NC 1 \NC always \NC always use an object \NC\NR
+%D \NC 2 \NC optional \NC use object when needed \NC\NR
+%D \stoptabulate
+%D
+%D The last object number used is avaliable in the macro
+%D \type {\lastPDFMPobject}.
+
+\ifx\makeMPintoPDFobject \undefined \newconstant\makeMPintoPDFobject \fi
+\ifx\everyMPtoPDFconversion\undefined \newtoks \everyMPtoPDFconversion \fi
+
+\let\lastPDFMPobject \!!zerocount
+\let\currentPDFresources\empty
+\let\setMPextensions \relax
+
+\def\PDFMPformoffset
+ {\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}}
+
+%D The main macro:
+
+\def\convertMPtoPDF#1#2#3% watch the transparency reset
+ {\resetMPvariables{#1}{#2}{#3}%
+ \vpack\bgroup
+ \forgetall
+ \offinterlineskip
+ \setbox\scratchbox\vpack\bgroup
+ \setnormalcatcodes % we can be in verbatim or so
+ \message{[MP to PDF]}%
+ \startMPresources
+ \pdfliteral{\letterpercent\space mps begin}%
+ \pdfliteral{q 1 0 0 1 0 0 cm}%
+ \ctxlua{metapost.mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
+ \pdfliteral{Q}%
+ \pdfliteral{\letterpercent\space mps end}%
+ \stopMPresources
+ \egroup
+ \setbox\scratchbox\hpack\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vpack to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup}
+
+\let\processMPtoPDFfile\convertMPtoPDF
+
+%D A common hook.
+
+\let\MPfshowcommand\empty
+
+%D Objects.
+
+\def\dopackageMPgraphic#1% #1 = boxregister
+ {\ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else
+ % an existing value of 2 signals object support (set elsewhere)
+ \makeMPintoPDFobject\plusone
+ \fi\fi
+ \ifcase\makeMPintoPDFobject
+ \box#1%
+ \or
+ \scratchdimen\PDFMPformoffset\relax
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \setbox#1\vpack spread 2\scratchdimen
+ {\forgetall\vss\hpack spread 2\scratchdimen{\hss\box#1\hss}\vss}%
+ \fi
+ \setMPPDFobject{\currentPDFresources}{#1}%
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \vpack to \MPheight
+ {\forgetall\vss\hpack to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
+ \else
+ \getMPPDFobject
+ \fi
+ \global\let\currentPDFresources\empty
+ \else
+ \box#1%
+ \fi}
+
+\def\setMPPDFobject#1#2% resources boxnumber
+ {\ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi
+ \immediate\saveboxresource resources{#1}#2%
+ \edef\getMPPDFobject{\noexpand\useboxresource\the\lastsavedboxresourceindex}}
+
+\let\getMPPDFobject\relax
+
+%D \macros
+%D {deleteMPgraphic,
+%D startMPresources,
+%D stopMPresources}
+
+\ifx\deleteMPgraphic\undefined
+ \def\deleteMPgraphic#1{}
+\fi
+
+\ifx\startMPresources\undefined
+ \let\startMPresources\relax
+ \let\stopMPresources\relax
+\fi
+
+%D We implement extensions by using the \METAPOST\ special
+%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
+%D are flushed before or after the graphic data, but thereby
+%D are no longer connected to a position.
+%D
+%D We implement specials by overloading the \type {fill}
+%D operator. By counting the fills, we can let the converter
+%D treat the appropriate fill in a special way. The
+%D specification of the speciality can have two forms,
+%D determined by the setting of a boolean variable:
+%D
+%D \starttyping
+%D _inline_specials_ := false ; % comment like code (default)
+%D _inline_specials_ := true ; % command like code
+%D \stoptyping
+%D
+%D When the specification is embedded as comment, it looks
+%D like:
+%D
+%D \starttyping
+%D %%MetaPostSpecial <size> <data> <number> <identifier>
+%D \stoptyping
+%D
+%D The in||line alternative is more tuned for \POSTSCRIPT,
+%D since it permits us to define a macro \type {special}.
+%D
+%D \starttyping
+%D inline : <data> <number> <identifier> <size> special
+%D \stoptyping
+%D
+%D The \type {identifier} determines what to do, and the data
+%D can be used to accomplish this. A type~2 shading function
+%D has identifier~2. Alltogether, the number of parameters is
+%D specified in \type {size}. The \type {number} is the number
+%D of the fill that needs the special treatment. For a type~2
+%D and~3 shaded fill, the datablock contains the following
+
+%D data:
+%D
+%D \starttyping
+%D from to n inner_r g b x y outer_r g b x y
+%D from to n inner_r g b x y radius outer_r g b x y radius
+%D \stoptyping
+
+\newconditional\manyMPspecials \settrue\manyMPspecials
+
+%D In case of \PDF, we need to prepare resourcs.
+
+\newtoks\MPstartresources
+\newtoks\MPstopresources
+
+\def\startMPresources
+ {\the\MPstartresources}
+
+\def\stopMPresources
+ {\the\MPstopresources}
+
+%D Some day we may consider collecting local resources.
+
+\appendtoks
+ \global\let\currentPDFresources\empty % kind of redundant
+\to \MPstartresources
+
+% \appendtoks
+% \collectPDFresources
+% \global\let\currentPDFresources\collectedPDFresources
+% \to \MPstopresources
+
+\appendtoksonce
+ \the\everyPDFxform
+\to \MPstopresources
+
+%D Since colors are not subjected to transformations, we can
+%D only use colors as signal. In our case, we use a dummy colored
+%D path with a red color component of \type {0.n}, so \type
+%D {0.001} is the first path and \type {0.010} the tenth. Since
+%D \METAPOST strips trailing zeros, we have to padd the string.
+
+\newif\ifMPcmykcolors
+\newif\ifMPspotcolors
+
+%D Specials:
+
+% \settrue \manyMPspecials \newcount\nofMParguments \let\extraMPpathcode\empty
+%
+% \def\@@MP {@@MP}
+% \def\@@MPSK{@MPSK@}
+%
+% \def\MPspecial{\@@MPSK\@@MPSK\gMPs\nofMParguments}
+%
+% \unexpanded\def\defineMPspecial#1#2%
+% {\setvalue{\@@MPSK\@@MPSK#1}{#2}}
+
+%D Special number~1 is dedicated to \CMYK\ support. If you
+%D want to know why: look at this:
+%D
+%D \startbuffer[mp]
+%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
+%D \stopbuffer
+%D
+%D \startbuffer[cmyk]
+%D \startcombination[4*1]
+%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
+%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15}
+%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8}
+%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure
+%D {\CMYK\ support disabled,
+%D conversion to \RGB.}
+%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no support in \METAPOST.}
+%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no conversion to \RGB,
+%D support in \METAPOST}
+%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
+
+% \let\revokeMPtransparencyspecial\relax
+
+%D Transparency support used specials 60 (rgb) and 61
+%D (cmyk).
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor transparent(1,.5,yellow) ;
+%D fill p rotated 210 withcolor transparent(1,.5,green) ;
+%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D One can also communicate colors between \CONTEXT\ and
+%D \METAPOST:
+%D
+%D \startbuffer
+%D \definecolor[tcyan] [c=1,k=.2,t=.5]
+%D \definecolor[tmagenta][m=1,k=.2,t=.5]
+%D \definecolor[tyellow] [y=1,k=.2,t=.5]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor \MPcolor{tcyan} ;
+%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
+%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
+%D \stopbuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+
+%D Shading is an example of a more advanced graphic feature,
+%D but users will seldom encounter those complications. Here
+%D we only show a few simple examples, but many other
+%D alternatives are possible by setting up the functions built
+%D in \PDF\ in the appropriate way.
+%D
+%D Shading has to do with interpolation between two or more
+%D points or user supplied ranges. In \PDF, the specifications
+%D of a shade has to be encapsulated in objects and passed on
+%D as resources. This is a \PDF\ level 1.3. feature. One can
+%D simulate three dimensional shades as well and define simple
+%D functions using a limited set of \POSTSCRIPT\ primitives.
+%D Given the power of \METAPOST\ and these \PDF\ features, we
+%D can achieve superb graphic effects.
+%D
+%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
+%D we can stick to high level \CONTEXT\ command, as shown in
+%D the following exmples.
+%D
+%D \startbuffer
+%D \startuniqueMPgraphic{CircularShade}
+%D path p ; p := unitsquare xscaled OverlayWidth yscaled OverlayHeight ;
+%D circular_shade(p,0,.2red,.9red) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{LinearShade}
+%D path p ; p := unitsquare xscaled OverlayWidth yscaled OverlayHeight ;
+%D linear_shade(p,0,.2blue,.9blue) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{DuotoneShade}
+%D path p ; p := unitsquare xscaled OverlayWidth yscaled OverlayHeight ;
+%D linear_shade(p,2,.5green,.5red) ;
+%D \stopuniqueMPgraphic
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These graphics can be hooked into the overlay mechanism,
+%D which is available in many commands.
+%D
+%D \startbuffer
+%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
+%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}]
+%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These backgrounds can for instance be applied to \type
+%D {\framed}:
+%D
+%D \startbuffer
+%D \setupframed[width=3cm,height=2cm,frame=off]
+%D \startcombination[3*1]
+%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
+%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
+%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D There are a few more alternatives, determined by the second
+%D parameter passed to \type {circular_shade} and alike.
+%D
+%D \def\SomeShade#1#2#3#4#5%
+%D {\startuniqueMPgraphic{Shade-#1}
+%D width := OverlayWidth ;
+%D height := OverlayHeight ;
+%D path p ; p := unitsquare xscaled width yscaled height ;
+%D #2_shade(p,#3,#4,#5) ;
+%D \stopuniqueMPgraphic
+%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
+%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
+%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
+%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
+%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
+%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
+%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
+%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
+%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
+%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[4*1]
+%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
+%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
+%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
+%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D These macros closely cooperate with the \METAPOST\ module
+%D \type {mp-spec.mp}, which is part of the \CONTEXT\
+%D distribution.
+%D
+%D The low level (\PDF) implementation is based on the \TEX\
+%D based \METAPOST\ to \PDF\ converter. Shading is supported
+%D by overloading the \type {fill} operator as implemented
+%D earlier. In \PDF\ type~2 and~3 shading functions are
+%D specified in terms of:
+%D
+%D \starttabulate[|Tl|l|]
+%D \NC /Domain \NC sort of meeting range \NC \NR
+%D \NC /C0 \NC inner shade \NC \NR
+%D \NC /C1 \NC outer shade \NC \NR
+%D \NC /N \NC smaller values, bigger inner circles \NC \NR
+%D \stoptabulate
+
+% \newcount\currentPDFshade % 0 % global (document wide) counter
+%
+% \def\dosetMPsomePDFshade#1#2%
+% {\immediate\pdfobj
+% {<</FunctionType 2
+% /Domain [\gMPs1 \gMPs2]
+% /C0 [\MPshadeA]
+% /C1 [\MPshadeB]
+% /N \gMPs3>>}%
+% \immediate\pdfobj
+% {<</ShadingType #1
+% /ColorSpace /\MPresolvedspace
+% /Function \the\pdflastobj\space 0 R
+% /Coords [\MPshadeC]
+% /Extend [true true]>>}%
+% \global\advance\currentPDFshade \plusone
+% \ctxlua{lpdf.adddocumentshade("Sh\the\currentPDFshade",lpdf.reference(\the\pdflastobj))}%
+% \setxvalue{\@@MPSK#2}{\noexpand\dohandleMPshade{\the\currentPDFshade}}}
+%
+% \def\dosetMPlinearshade {\dosetMPsomePDFshade2}% #1
+% \def\dosetMPcircularshade{\dosetMPsomePDFshade3}% #1
+%
+% \defineMPspecial{30}
+% {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{9}}{\gMPs{10}}{\gMPs{11}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}}%
+% \dosetMPlinearshade{\gMPs{14}}}
+%
+% \defineMPspecial{31}
+% {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}}%
+% \dosetMPcircularshade{\gMPs{16}}}
+%
+% \defineMPspecial{32}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+% \dosetMPlinearshade{\gMPs{16}}}
+%
+% \defineMPspecial{33}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+% \dosetMPcircularshade{\gMPs{18}}}
+%
+% \defineMPspecial{34}
+% {\normalexpanded{\noexpand\resolveMPspotcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPspotcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+% \dosetMPlinearshade{\gMPs{16}}}
+%
+% \defineMPspecial{35}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+% \dosetMPcircularshade{\gMPs{18}}}
+%
+% \newconditional\ignoreMPpath
+%
+% \def\dohandleMPshade#1%
+% {\revokeMPtransparencyspecial
+% \settrue\ignoreMPpath
+% \def\extraMPpathcode{/Sh#1 sh Q}%
+% \pdfliteral{q /Pattern cs}}
+%
+% \defineMPspecial{10}
+% {\setxvalue{\@@MPSK\gMPs8}%
+% {\noexpand\handleMPfigurespecial{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}{\gMPs8}}}
+%
+% \def\handleMPfigurespecial#1#2#3#4#5#6#7#8% todo : combine with ext fig
+% {\letgvalueempty{\@@MPSK#8}%
+% \vbox to \zeropoint
+% {\vss
+% \hbox to \zeropoint
+% {\ifcase\pdfoutput\or % will be hooked into the special driver
+% \doiffileelse{#7}
+% {\doifundefinedelse{mps:x:#7}
+% {\immediate\pdfximage\s!width\onebasepoint\s!height\onebasepoint{#7}%
+% \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}%
+% {\message{[reusing figure #7]}}%
+% \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}%
+% \rlap{\getvalue{mps:x:#7}}%
+% \pdfliteral{Q}}
+% {\message{[unknown figure #7]}}%
+% \fi
+% \hss}}}
+
+%D An example of using both special features is the
+%D following.
+%D
+%D \starttyping
+%D \startMPpage
+%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm);
+%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
+%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ;
+%D path p ; p := unitcircle xscaled 15cm yscaled 20cm;
+%D path q ; q := p rotatedaround(center p,90) ;
+%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
+%D path s ; s := boundingbox currentpicture enlarged 5mm ;
+%D picture c ; c := currentpicture ; currentpicture := nullpicture ;
+%D circular_shade(s,0,.2red,.9red) ;
+%D addto currentpicture also c ;
+%D \stopMPpage
+%D \stoptyping
+
+% \defineMPspecial{20}
+% {\setxvalue{\@@MPSK\gMPs6}%
+% {\noexpand\handleMPhyperlink{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}}
+%
+% \def\handleMPhyperlink#1#2#3#4#5#6%
+% {\letgvalueempty{\@@MPSK#6}%
+% \setbox\scratchbox\hbox
+% {\setbox\scratchbox\emptyhbox
+% \wd\scratchbox\dimexpr-#1\onebasepoint+#3\onebasepoint\relax
+% \ht\scratchbox\dimexpr-#2\onebasepoint+#4\onebasepoint\relax
+% \gotobox{\box\scratchbox}[#5]}%
+% \setbox\scratchbox\hbox
+% {\hskip\dimexpr\MPxoffset\onebasepoint+#1\onebasepoint\relax
+% \raise\dimexpr\MPyoffset\onebasepoint+#2\onebasepoint\relax
+% \box\scratchbox}%
+% \smashbox\scratchbox
+% \box\scratchbox}
+
+%D This special (number 50) passes positions to a tex file.
+%D This method uses a two||pass approach an (mis|)|used the
+%D context positioning macros. In \type {core-pos} we will
+%D implement the low level submacro needed.
+%D
+%D \startbuffer
+%D \definelayer[test]
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-1},y=\MPy{somepos-1}]
+%D {Whatever we want here!}
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-2},y=\MPy{somepos-2}]
+%D {Whatever we need there!}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 6cm withcolor red ;
+%D register ("somepos-1",1cm,2cm,center currentpicture) ;
+%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here the width and height are not realy used, but one can
+%D imagine situations where tex has to work with values
+%D calculated by \METAPOST.
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D Later we will implement a more convenient macro:
+%D
+%D \starttyping
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \stoptyping
+
+\startMPinitializations
+ mp_shade_version := 2 ;
+\stopMPinitializations
+
+%D This is done much cleaner in \MPLIB.
+
+\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
+ {\def\MPtextdata{#3}% % delegate the splitter to lua + redesign
+ \def\MPtextsize{#2}%
+ \def\lastMPmoveX{#4}%
+ \def\lastMPmoveY{#5}%
+ \defconvertedcommand\MPtextdata\MPtextdata % no edef
+ \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
+ \executeifdefined{handleMPtext\MPtexttag}
+ {\setbox\scratchbox\hbox % text
+ {\font\temp=#1\space at #2\onebasepoint
+ \let\c\char
+ \temp
+ \MPfshowcommand{#3}}%
+ \setbox\scratchbox\hpack
+ {\hskip#4\onebasepoint
+ \raise#5\onebasepoint
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox}}
+
+%D We save the special variables on a stack. It's not that
+%D fast, but it make implementing the special more convenient.
+
+% \def\MPSbegin
+% {\nofMParguments\zerocount}
+%
+% \def\MPSend
+% {\csname\MPspecial\endcsname}
+%
+% \def\MPSset
+% {\advance\nofMParguments\plusone
+% \expandafter\def\csname\@@MP\number\nofMParguments\endcsname}
+%
+% \def\gMPs#1{\csname\@@MP\number#1\endcsname}
+
+%D The boundingbox.
+
+\def\MPSboundingbox#1#2#3#4%
+ {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
+ \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+
+\MPSboundingbox0000
+
+% \def\MPSspecial#1#2%
+% {\csname\@@MPSK#2\endcsname}
+
+%D A path is (in most cases) just a sequence of \PDF\ commands.
+
+% \newconditional\ignoreMPpath
+
+% \def\MPSpath
+% {\pdfliteral}
+
+% \def\MPScode % hack, will be improved
+% {\ifconditional\ignoreMPpath
+% \pdfliteral{h W n}%
+% \ifx\extraMPpathcode\empty\else
+% \pdfliteral{\extraMPpathcode}%
+% \let\extraMPpathcode\empty
+% \fi
+% \setfalse\ignoreMPpath
+% \expandafter\gobbleoneargument
+% \else
+% \expandafter\pdfliteral
+% \fi}
+
+%D Test code:
+
+% \startMPcode
+% fill fullcircle scaled 3cm withcolor red ;
+% fill fullcircle scaled 2cm withcolor green ;
+% fill fullcircle scaled 1cm withcolor blue ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+% fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+% fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% draw fullcircle scaled 3cm dashed evenly ;
+% draw fullcircle scaled 2cm dashed withdots ;
+% draw origin withpen pencircle scaled 3mm;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+% fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+% fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+% fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+% currentpicture := currentpicture shifted (12cm,-4cm) ;
+% draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% % bug: shift
+% draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+% draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+% filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% % shade cannot handle shift
+% circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+% circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+% filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ;
+% \stopMPcode
+
+% We cannot use attributes for switching colors in mp literals because
+% grouping (qQ) interferes.
+
+% \def\dohandleMPshade#1%
+% {\revokeMPtransparencyspecial
+% \settrue\ignoreMPpath
+% \def\extraMPpathcode{/#1 sh Q}%
+% \pdfliteral{q /Pattern cs}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua
new file mode 100644
index 00000000000..1008e45c05e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua
@@ -0,0 +1,208 @@
+if not modules then modules = { } end modules ['meta-tex'] = {
+ version = 1.001,
+ comment = "companion to meta-tex.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tostring = tostring
+local format, gsub, find, match = string.format, string.gsub, string.find, string.match
+local formatters = string.formatters
+local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
+
+metapost = metapost or { }
+
+local implement = interfaces.implement
+
+-- local left = P("[")
+-- local right = P("]")
+-- local space = P(" ")
+-- local argument = left * C((1-right)^1) * right
+-- local pattern = (argument + space)^0
+
+-- function metapost.sometxt(optional,str)
+-- if optional == "" then
+-- context.sometxta(str)
+-- else
+-- local one, two = lpegmatch(pattern,optional)
+-- if two then
+-- context.sometxtc(one,two,str)
+-- elseif one then
+-- context.sometxtb(one,str)
+-- else
+-- context.sometxta(str)
+-- end
+-- end
+-- end
+
+local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0) -- or \char
+
+function metapost.escaped(str)
+ context(lpegmatch(pattern,str))
+end
+
+implement {
+ name = "metapostescaped",
+ actions = metapost.escaped,
+ arguments = "string"
+}
+
+local simplify = true
+
+-- local function strip(n,e)
+-- -- get rid of e(0)
+-- -- get rid of e(+*)
+-- e = gsub(e,"^+","")
+-- -- remove leading zeros
+-- e = gsub(e,"^([+-]*)0+(%d)","%1%2")
+-- if not simplify then
+-- -- take it as it is
+-- elseif n == "1" then
+-- return format("10^{%s}",e)
+-- end
+-- return format("%s\\times10^{%s}",n,e)
+-- end
+--
+-- function metapost.format_n(fmt,...)
+-- fmt = gsub(fmt,"@","%%")
+-- local initial, hasformat, final = match(fmt,"^(.-)(%%.-[%a])(.-)$")
+-- if hasformat then
+-- str = format(fmt,...)
+-- str = gsub(str,"(.-)e(.-)$",strip)
+-- str = format("%s\\mathematics{%s}%s",initial,str,final)
+-- elseif not find(fmt,"%%") then
+-- str = format("%"..fmt,...)
+-- str = gsub(str,"(.-)e(.-)$",strip)
+-- str = format("\\mathematics{%s}",str)
+-- end
+-- context(str)
+-- end
+
+-- todo: proper lpeg
+
+-- local function strip(n,e)
+-- -- get rid of e(0)
+-- -- get rid of e(+*)
+-- e = gsub(e,"^+","")
+-- -- remove leading zeros
+-- e = gsub(e,"^([+-]*)0+(%d)","%1%2")
+-- if not simplify then
+-- -- take it as it is
+-- elseif n == "1" then
+-- return format("\\mathematics{10^{%s}}",e)
+-- end
+-- return format("\\mathematics{%s\\times10^{%s}}",n,e)
+-- end
+--
+-- function metapost.format_n(fmt,...)
+-- fmt = gsub(fmt,"@","%%")
+-- if find(fmt,"%%") then
+-- str = format(fmt,...)
+-- else -- yes or no
+-- str = format("%"..fmt,...)
+-- end
+-- str = gsub(str,"([%-%+]-[%.%d]+)e([%-%+]-[%.%d]+)",strip)
+-- context(str)
+-- end
+--
+-- function metapost.format_v(fmt,str)
+-- metapost.format_n(fmt,metapost.untagvariable(str,false))
+-- end
+
+-- -- --
+
+local number = C((S("+-")^0 * R("09","..")^1))
+local enumber = number * S("eE") * number
+
+local cleaner = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0)
+
+context = context or { exponent = function(...) print(...) end }
+
+function metapost.format_string(fmt,...)
+ context(lpegmatch(cleaner,fmt),...)
+end
+
+function metapost.format_number(fmt,num)
+ local number = tonumber(num)
+ if number then
+ local base, exponent = lpegmatch(enumber,formatters[lpegmatch(cleaner,fmt)](number))
+ if base and exponent then
+ context.MPexponent(base,exponent)
+ else
+ context(number)
+ end
+ else
+ context(tostring(num))
+ end
+end
+
+-- This is experimental and will change!
+
+function metapost.svformat(fmt,str)
+ metapost.format_string(fmt,metapost.untagvariable(str,false))
+end
+
+function metapost.nvformat(fmt,str)
+ metapost.format_number(fmt,metapost.untagvariable(str,false))
+end
+
+implement { name = "metapostformatted", actions = metapost.svformat, arguments = { "string", "string" } }
+implement { name = "metapostgraphformat", actions = metapost.nvformat, arguments = { "string", "string" } }
+
+-- local function test(fmt,n)
+-- logs.report("mp format test","fmt: %s, n: %s, result: %s, \\exponent{%s}{%s}",fmt,n,
+-- formatters[lpegmatch(cleaner,fmt)](n),
+-- lpegmatch(enumber,formatters[lpegmatch(cleaner,fmt)](n))
+-- )
+-- end
+--
+-- test("@j","1e-8")
+-- test("@j",1e-8)
+-- test("@j","1e+8")
+-- test("@j","1e-10")
+-- test("@j",1e-10)
+-- test("@j","1e+10")
+-- test("@j","1e-12")
+-- test("@j","1e+12")
+-- test("@j","1e-0")
+-- test("@j","1e+0")
+-- test("@j","1")
+-- test("@j test","1")
+-- test("@j","-1")
+-- test("@j","1e-102")
+-- test("@1.4j","1e+102")
+-- test("@j","1.2e+102")
+-- test("@j","1.23e+102")
+-- test("@j","1.234e+102")
+
+local f_textext = formatters[ [[textext("%s")]] ]
+local f_mthtext = formatters[ [[textext("\mathematics{%s}")]] ]
+local f_exptext = formatters[ [[textext("\mathematics{%s\times10^{%s}}")]] ]
+
+local mpprint = mp.print
+
+function mp.format(fmt,str)
+ fmt = lpegmatch(cleaner,fmt)
+ mpprint(f_textext(formatters[fmt](metapost.untagvariable(str,false))))
+end
+
+function mp.formatted(fmt,num) -- svformat
+ fmt = lpegmatch(cleaner,fmt)
+ mpprint(f_textext(formatters[fmt](tonumber(num) or num)))
+end
+
+function mp.graphformat(fmt,num) -- nvformat
+ fmt = lpegmatch(cleaner,fmt)
+ local number = tonumber(num)
+ if number then
+ local base, exponent = lpegmatch(enumber,number)
+ if base and exponent then
+ mpprint(f_exptext(base,exponent))
+ else
+ mpprint(f_mthtext(num))
+ end
+ else
+ mpprint(f_textext(tostring(num)))
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-tex.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.mkiv
new file mode 100644
index 00000000000..35b5c133b95
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.mkiv
@@ -0,0 +1,153 @@
+%D \module
+%D [ file=meta-tex,
+%D version=2006.06.07,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=\METAPOST\ fast text insertion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{meta-tex}{1.001}
+
+\unprotect
+
+% Ok, we support this in MkIV because Mojca kept the pressure on. It
+% looks a bit like a hack. But in fact this method is obsolete and
+% eventually might go away.
+
+\installcorenamespace{graphictextext}
+\installcorenamespace{graphictexdepth}
+\installcorenamespace{graphictexarguments}
+
+\unexpanded\def\startTeXtexts#1\stopTeXtexts
+ {#1}
+
+\let\stopTeXtexts\relax
+
+\unexpanded\def\TeXtext
+ {\dosingleempty\meta_textext}
+
+\def\meta_textext[#1]#2#3% contrary to mkii we don't process yet but we do expand
+ {\setxvalue{\??graphictextext#2}{\meta_textext_indeed{#1}{#3}}}
+
+\unexpanded\def\meta_textext_indeed#1#2%
+ {\begingroup
+ \setbox\nextbox\hbox{#2}%
+ \executeifdefined{\??graphictexdepth#1}{\getvalue{\??graphictexdepth\s!depth}}%
+ \box\nextbox
+ \endgroup}
+
+\def\getTeXtext#1%
+ {\getvalue{\??graphictextext#1}}
+
+\setvalue{\??graphictexdepth d}{\setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}} % unchecked
+\letvalue{\??graphictexdepth n}\donothing % unchecked
+
+\setvalue{\??graphictexdepth\s!depth }{\getvalue{\??graphictexdepth d}}
+\letvalue{\??graphictexdepth\s!nodepth}\donothing
+
+% \definetextext[framed]{\framed}
+%
+% \startMPcode
+% draw \sometxt[framed]{black} rotated 45 ;
+% \stopMPcode
+%
+% But Mojca wanted more! Two arguments.
+%
+% \definetextext[framed]{\framed}
+%
+% \startMPcode
+% draw \sometxt{This is for} rotated 45 ;
+% draw \sometxt[framed][foregroundstyle=bold]{Mojca's};
+% draw \sometxt[framed]{eyes only!} rotated -45 ;
+% \stopMPcode
+
+\unexpanded\def\definetextext[#1]%
+ {\def\currenttextext{#1}%
+ \doifelsenextoptionalcs\meta_textext_define_one\meta_textext_define_zero}
+
+\def\meta_textext_define_one {\setvalue{\??graphictexarguments1:\currenttextext}}
+\def\meta_textext_define_zero{\setvalue{\??graphictexarguments0:\currenttextext}}
+
+\def\sometxt#1#{\meta_some_txt{#1}}
+
+\def\meta_some_txt#1#2% we need to capture embedded quotes (a bit messy as later on textext is filtered
+ {textext.drt("\mpsometxt#1{\clf_metapostescaped{#2}}")}
+
+\unexpanded\def\mpsometxt % no _ catcode
+ {\doifelsenextoptionalcs\meta_some_txt_indeed_yes\meta_some_txt_indeed_nop}
+
+\def\meta_some_txt_indeed_yes[#1]%
+ {\def\currenttextext{#1}%
+ \csname\??graphictexarguments
+ \ifcsname\??graphictexarguments0:#1\endcsname0\else
+ \ifcsname\??graphictexarguments1:#1\endcsname1\else
+ ?\fi\fi
+ \endcsname}
+
+\def\meta_some_txt_indeed_nop
+ {}
+
+\setvalue{\??graphictexarguments ?}{}
+\setvalue{\??graphictexarguments 0}{\csname\??graphictexarguments\currenttextext\endcsname}
+\setvalue{\??graphictexarguments 1}{\dosingleempty\meta_gx_one}
+
+\def\meta_gx_one{\csname\??graphictexarguments1:\currenttextext\endcsname}
+
+% \definetextext[framed][#1]#2{\framed[width=4cm]{\switchtobodyfont[#1]#2}}
+% \definetextext[simple]{\framed[width=8cm]}
+%
+% \starttext
+%
+% \startMPcode
+% draw \sometxt{This is for} rotated 45 ;
+% draw \sometxt[framed][ss,16pt] {Mojca's};
+% draw \sometxt[framed]{eyes only!} rotated -45 ;
+% draw \sometxt[simple]{Quotes "indeed" work!} rotated 180 ;
+% \stopMPcode
+%
+% \stoptext
+%
+% a lua one:
+%
+% \unexpanded\def\definetextext[#1]#2{\setvalue{@@st@@#1}{#2}}
+%
+% \def\sometxt #1#{\dosometxt{#1}} % grab optional [args]
+% \def\dosometxt #1#2{\ctxlua{metapost.sometxt(\!!bs#1\!!es,\!!bs#2\!!es)}}
+%
+% \def\sometxta #1{textext.drt("#1")}
+% \def\sometxtb #1#2{textext.drt("\getvalue{@@st@@#1}{#2}")}
+% \def\sometxtc #1#2#3{textext.drt("\getvalue{@@st@@#1}{\switchtobodyfont[#2]#3}")}
+
+% Best use the mp macro instead since it provides positioning.
+%
+% \startuseMPgraphic{testgraphic}
+% draw \sometxt{\ruledhbox{\strut hans hagen}} scaled 3;
+% % draw textext.drt("\ruledhbox{\strut hans hagen}") scaled 3;
+% % draw textext.dlft("\ruledhbox{\strut hans hagen}") scaled 3;
+% % draw textext.lft("\ruledhbox{\strut hans hagen}") scaled 3;
+% draw llcorner currentpicture -- urcorner currentpicture withcolor yellow;
+% draw lrcorner currentpicture -- ulcorner currentpicture withcolor yellow;
+% draw boundingbox currentpicture withcolor blue ;
+% draw origin withcolor red withpen pencircle scaled 1pt;
+% \stopuseMPgraphic
+%
+% {\showstruts\useMPgraphic{testgraphic}}
+
+\unexpanded\def\MPexponent #1#2{\mathematics{#1\times10^{#2}}}
+\unexpanded\def\MPformatted #1#2{\clf_metapostformatted{#1}{#2}}
+\unexpanded\def\MPgraphformat#1#2{\clf_metapostgraphformat{#1}{#2}}
+
+%D Some new fun (but exprimental for a while):
+
+\unexpanded\def\MPLIBoutlinetext#1#2#3% index kind text
+ {\begingroup
+ \setbox\scratchbox\hbox{#3}%
+ \clf_MPLIBconvertoutlinetext\numexpr#1\relax{#2}\scratchbox
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-xml.mkiv
new file mode 100644
index 00000000000..bd93bda8c5b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/meta-xml.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=meta-xml,
+%D version=2002.11.27,
+%D title=\METAPOST\ Graphics,
+%D subtitle=XML Hacks,
+%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 / XML Hacks}
+
+\unprotect
+
+% not needed in mkiv
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/metatex.lus b/Master/texmf-dist/tex/context/base/mkiv/metatex.lus
new file mode 100644
index 00000000000..df7bc191425
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/metatex.lus
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['metatex'] = {
+ version = 1.001,
+ comment = "companion to metatex.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return "luat-cod.lua"
diff --git a/Master/texmf-dist/tex/context/base/mkiv/metatex.tex b/Master/texmf-dist/tex/context/base/mkiv/metatex.tex
new file mode 100644
index 00000000000..b5f54c4eef1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/metatex.tex
@@ -0,0 +1,165 @@
+%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 luatools --make --compile metatex
+%D \stoptyping
+%D
+%D Remark: this is far from complete. We will gradually add
+%D more. Also, it's not yet clean what exactly will be part
+%D of it. This is a prelude to a configureable macro package.
+
+\catcode`\{=1 \catcode`\}=2 \catcode`\#=6
+
+\edef\metatexformat {\jobname}
+\edef\metatexversion{2007.04.03 13:01}
+
+\let\fmtname \metatexformat
+\let\fmtversion\metatexversion
+
+\ifx\normalinput\undefined \let\normalinput\input \fi
+
+\def\loadcorefile#1{\normalinput#1.tex \relax}
+\def\loadmarkfile#1{\normalinput#1.mkiv\relax}
+
+\loadmarkfile{syst-ini}
+
+\ifnum\luatexversion<60 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.60!}
+ \expandafter\end
+\fi
+
+\newtoks\metatexversiontoks \metatexversiontoks\expandafter{\metatexversion} % at the lua end
+
+\loadmarkfile{syst-pln} % plain tex initializations of internal registers (no further code)
+\loadmarkfile{syst-mes}
+
+\loadmarkfile{luat-cod} %
+\loadmarkfile{luat-bas} %
+\loadmarkfile{luat-lib} %
+
+% needs stripping:
+
+\loadmarkfile{catc-ini} % catcode table management
+\loadmarkfile{catc-act} % active character definition mechanisms
+\loadmarkfile{catc-def} % some generic catcode tables
+\loadmarkfile{catc-ctx} % a couple of context specific tables but expected by later modules
+\loadmarkfile{catc-sym} % some definitions related to \letter<tokens>
+
+% helpers, maybe less
+
+\loadmarkfile{syst-aux} % a whole lot of auxiliary macros
+%loadmarkfile{syst-lua} % some helpers using lua instead
+%loadmarkfile{syst-con} % some rather basic conversions
+%loadmarkfile{syst-fnt}
+%loadmarkfile{syst-str}
+%loadmarkfile{syst-rtp}
+
+% not needed
+
+% \loadmarkfile{supp-fil}
+% \loadmarkfile{supp-dir}
+
+% characters
+
+\loadmarkfile{char-utf}
+\loadmarkfile{char-ini}
+\loadmarkfile{char-enc} % \registerctxluafile{char-enc}{1.001}
+
+% attributes
+
+\loadmarkfile{attr-ini}
+
+% nodes
+
+\loadmarkfile{node-ini}
+%loadmarkfile{node-fin}
+%loadmarkfile{node-par}
+
+% attributes, not needed:
+
+%loadmarkfile{attr-ini}
+
+% regimes
+
+% \loadmarkfile{regi-ini}
+% \loadcorefile{regi-syn}
+
+% languages
+
+% fonts
+
+% \loadcorefile{enco-ini.mkiv}
+% \loadcorefile{hand-ini.mkiv}
+
+\registerctxluafile{font-ini}{1.001}
+
+\registerctxluafile{node-fnt}{1.001}
+
+\registerctxluafile{font-enc}{1.001}
+\registerctxluafile{font-map}{1.001}
+\registerctxluafile{font-syn}{1.001}
+\registerctxluafile{font-tfm}{1.001}
+\registerctxluafile{font-afm}{1.001}
+\registerctxluafile{font-cid}{1.001}
+\registerctxluafile{font-ott}{1.001}
+\registerctxluafile{font-otf}{1.001}
+\registerctxluafile{font-otb}{1.001}
+\registerctxluafile{font-otn}{1.001}
+\registerctxluafile{font-ota}{1.001}
+\registerctxluafile{font-otp}{1.001}
+\registerctxluafile{font-otc}{1.001}
+%registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-def}{1.001}
+%registerctxluafile{font-ctx}{1.001}
+\registerctxluafile{font-xtx}{1.001}
+%registerctxluafile{font-fbk}{1.001}
+%registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-pat}{1.001}
+%registerctxluafile{font-chk}{1.001}
+
+%registerctxluafile{math-ini}{1.001}
+%registerctxluafile{math-dim}{1.001}
+%registerctxluafile{math-ent}{1.001}
+%registerctxluafile{math-ext}{1.001}
+%registerctxluafile{math-vfu}{1.001}
+%registerctxluafile{math-map}{1.001}
+%registerctxluafile{math-noa}{1.001}
+
+\registerctxluafile{task-ini}{1.001}
+
+%registerctxluafile{l-xml}{1.001} % needed for font database
+
+% why not ...
+
+\pdfoutput\plusone
+
+% too
+
+\appendtoks
+ \ctxlua{statistics.savefmtstatus("\jobname","\metatexversion","metatex.tex")}% can become automatic
+\to \everydump
+
+% done
+
+\errorstopmode \dump \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua
new file mode 100644
index 00000000000..3fe7118b787
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua
@@ -0,0 +1,375 @@
+if not modules then modules = { } end modules ['mlib-ctx'] = {
+ 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",
+}
+
+-- for the moment we have the scanners here but they migh tbe moved to
+-- the other modules
+
+local type, tostring = type, tostring
+local format, concat = string.format, table.concat
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local report_metapost = logs.reporter("metapost")
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local mplib = mplib
+
+metapost = metapost or {}
+local metapost = metapost
+
+local setters = tokens.setters
+local setmacro = setters.macro
+local implement = interfaces.implement
+
+local v_no = interfaces.variables.no
+
+metapost.defaultformat = "metafun"
+metapost.defaultinstance = "metafun"
+metapost.defaultmethod = "default"
+
+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 extensiondata = metapost.extensiondata or storage.allocate { }
+metapost.extensiondata = extensiondata
+
+storage.register("metapost/extensiondata",extensiondata,"metapost.extensiondata")
+
+function metapost.setextensions(instances,data)
+ if data and data ~= "" then
+ extensiondata[#extensiondata+1] = {
+ usedinall = not instances or instances == "",
+ instances = settings_to_hash(instances or ""),
+ extensions = data,
+ }
+ end
+end
+
+function metapost.getextensions(instance,state)
+ if state and state == v_no then
+ return ""
+ else
+ local t = { }
+ for i=1,#extensiondata do
+ local e = extensiondata[i]
+ local status = e.instances[instance]
+ if (status ~= true) and (e.usedinall or status) then
+ t[#t+1] = e.extensions
+ e.instances[instance] = true
+ end
+ end
+ return concat(t," ")
+ end
+end
+
+-- function commands.getmpextensions(instance,state)
+-- context(metapost.getextensions(instance,state))
+-- end
+
+implement {
+ name = "setmpextensions",
+ actions = metapost.setextensions,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "getmpextensions",
+ actions = { metapost.getextensions, context } ,
+ arguments = "string"
+}
+
+local report_metapost = logs.reporter ("metapost")
+local status_metapost = logs.messenger("metapost")
+
+local patterns = {
+ "meta-imp-%s.mkiv",
+ "meta-imp-%s.tex",
+ -- obsolete:
+ "meta-%s.mkiv",
+ "meta-%s.tex"
+}
+
+local function action(name,foundname)
+ status_metapost("library %a is loaded",name)
+ context.startreadingfile()
+ context.input(foundname)
+ context.stopreadingfile()
+end
+
+local function failure(name)
+ report_metapost("library %a is unknown or invalid",name)
+end
+
+implement {
+ name = "useMPlibrary",
+ arguments = "string",
+ actions = function(name)
+ resolvers.uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+ end
+}
+
+-- metapost.variables = { } -- to be stacked
+
+implement {
+ name = "mprunvar",
+ arguments = "string",
+ actions = function(name)
+ local value = metapost.variables[name]
+ if value ~= nil then
+ local tvalue = type(value)
+ if tvalue == "table" then
+ context(concat(value," "))
+ elseif tvalue == "number" or tvalue == "boolean" then
+ context(tostring(value))
+ elseif tvalue == "string" then
+ context(value)
+ end
+ end
+ end
+}
+
+implement {
+ name = "mpruntab",
+ arguments = { "string", "integer" },
+ actions = function(name,n)
+ local value = metapost.variables[name]
+ if value ~= nil then
+ local tvalue = type(value)
+ if tvalue == "table" then
+ context(value[n])
+ elseif tvalue == "number" or tvalue == "boolean" then
+ context(tostring(value))
+ elseif tvalue == "string" then
+ context(value)
+ end
+ end
+ end
+}
+
+implement {
+ name = "mprunset",
+ actions = function(name,connector)
+ local value = metapost.variables[name]
+ if value ~= nil then
+ local tvalue = type(value)
+ if tvalue == "table" then
+ context(concat(value,connector))
+ elseif tvalue == "number" or tvalue == "boolean" then
+ context(tostring(value))
+ elseif tvalue == "string" then
+ context(value)
+ end
+ end
+ end
+}
+
+-- we need to move more from pps to here as pps is the plugin .. the order is a mess
+-- or just move the scanners to pps
+
+function metapost.graphic(specification)
+ metapost.graphic_base_pass(setmpsformat(specification))
+end
+
+implement {
+ name = "mpgraphic",
+ actions = metapost.graphic,
+ arguments = {
+ {
+ { "instance" },
+ { "format" },
+ { "data" },
+ { "initializations" },
+ { "extensions" },
+ { "inclusions" },
+ { "definitions" },
+ { "figure" },
+ { "method" },
+ }
+ }
+}
+
+implement {
+ name = "mpsetoutercolor",
+ actions = function(...) metapost.setoutercolor(...) end, -- not yet implemented
+ arguments = { "integer", "integer", "integer", "integer" }
+}
+
+implement {
+ name = "mpflushreset",
+ actions = function() metapost.flushreset() end -- not yet implemented
+}
+
+implement {
+ name = "mpflushliteral",
+ actions = function(str) metapost.flushliteral(str) end, -- not yet implemented
+ arguments = "string",
+}
+
+function metapost.getclippath(specification) -- why not a special instance for this
+ setmpsformat(specification)
+ local mpx = specification.mpx
+ local data = specification.data or ""
+ if mpx and data ~= "" then
+ starttiming(metapost)
+ starttiming(metapost.exectime)
+ local result = mpx:execute ( format ( "%s;%s;beginfig(1);%s;%s;endfig;",
+ specification.extensions or "",
+ specification.inclusions or "",
+ specification.initializations or "",
+ data
+ ) )
+ stoptiming(metapost.exectime)
+ if result.status > 0 then
+ report_metapost("%s: %s", result.status, result.error or result.term or result.log)
+ result = nil
+ else
+ result = metapost.filterclippath(result)
+ end
+ stoptiming(metapost)
+ return result
+ end
+end
+
+function metapost.filterclippath(result)
+ if result then
+ local figures = result.fig
+ if figures and #figures > 0 then
+ local figure = figures[1]
+ local objects = figure:objects()
+ if objects then
+ local lastclippath
+ for o=1,#objects do
+ local object = objects[o]
+ if object.type == "start_clip" then
+ lastclippath = object.path
+ end
+ end
+ return lastclippath
+ end
+ end
+ end
+end
+
+function metapost.theclippath(...)
+ local result = metapost.getclippath(...)
+ if result then -- we could just print the table
+-- return concat(metapost.flushnormalpath(result),"\n")
+ return concat(metapost.flushnormalpath(result)," ")
+ else
+ return ""
+ end
+end
+
+implement {
+ name = "mpsetclippath",
+ actions = function(specification)
+ setmacro("MPclippath",metapost.theclippath(specification),"global")
+ end,
+ arguments = {
+ {
+ { "instance" },
+ { "format" },
+ { "data" },
+ { "initializations" },
+ { "useextensions" },
+ { "inclusions" },
+ { "method" },
+ },
+ }
+}
+
+statistics.register("metapost processing time", 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",
+ 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
+ else
+ return nil
+ end
+end)
+
+-- only used in graphictexts
+
+metapost.tex = metapost.tex or { }
+local mptex = metapost.tex
+
+local environments = { }
+
+function mptex.set(str)
+ environments[#environments+1] = str
+end
+
+function mptex.setfrombuffer(name)
+ environments[#environments+1] = buffers.getcontent(name)
+end
+
+function mptex.get()
+ return concat(environments,"\n")
+end
+
+function mptex.reset()
+ environments = { }
+end
+
+implement {
+ name = "mptexset",
+ arguments = "string",
+ actions = mptex.set
+}
+
+implement {
+ name = "mptexsetfrombuffer",
+ arguments = "string",
+ actions = mptex.setfrombuffer
+}
+
+implement {
+ name = "mptexget",
+ actions = { mptex.get, context }
+}
+
+implement {
+ name = "mptexreset",
+ actions = mptex.reset
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.mkiv
new file mode 100644
index 00000000000..a7bb612c854
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.mkiv
@@ -0,0 +1,83 @@
+%D \module
+%D [ file=mlib-ctx,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file contains the \MPLIB\ variants of the by now ancient
+%D \MPTOPDF\ code.
+
+\writestatus{loading}{MetaPost Library Graphics / Initializations}
+
+\registerctxluafile{mlib-run}{1.001}
+\registerctxluafile{mlib-ctx}{1.001}
+\registerctxluafile{mlib-lua}{1.001}
+\registerctxluafile{mlib-int}{1.001} % here ?
+
+\unprotect
+
+\protect \endinput
+
+% local mpgraphic = [[
+% for i=1 upto 1000 :
+% beginfig(0);
+% draw halfcircle scaled 1cm withcolor green ;
+% picture p ; p := "oeps" infont defaultfont scaled .75 rotated 45 ;
+% p := p shifted - (xpart center p,0) ;
+% draw p ; draw boundingbox p ;
+% endfig ;
+% beginfig(0);
+% draw halfcircle scaled 1cm dashed evenly withcolor green ;
+% endfig ;
+% beginfig(0);
+% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
+% draw halfcircle scaled 1cm withcolor red ;
+% endfig ;
+% beginfig(0);
+% draw halfcircle scaled 1cm ;
+% endfig ;
+% beginfig(0);
+% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
+% for k:=1 upto 10 :
+% draw halfcircle scaled uniformdeviate(1cm) withcolor (red/(k/4)) ;
+% endfor ;
+% endfig ;
+% endfor ;
+% ]]
+% -- local mpx = metapost.format("metafun")
+% metapost.process(metapost.format("metafun"),mpgraphic)
+
+% \starttext
+% \setupcolors[state=start]
+% \definecolor[red] [r=1]
+% \definecolor[cyan][c=1]
+% \setbox\scratchbox\hbox{\startMPcode\stopMPcode} % first specials are forgotten
+% \definecolor[sss][t=.5,a=1,r=1]
+% \definespotcolor[oeps1][green][p=.5]
+% \definespotcolor[oeps2][green][p=.25]
+% \definespotcolor[oeps3][green][p=.25,t=.5,a=1]
+% \startMPpage
+% fill fullcircle scaled 10cm withcolor \MPcolor{red} ;
+% fill fullcircle scaled 8cm withcolor cmyk(1,0,0,0) ;
+% fill fullcircle scaled 6cm withcolor cmyk(0,1,0,0) ;
+% fill fullcircle scaled 4cm withcolor cmyk(0,0,1,0) ;
+% fill fullcircle scaled 2cm withcolor cmyk(0,0,0,1) ;
+% currentpicture := currentpicture shifted (-7.5cm,0) ;
+% fill fullcircle scaled 10cm withcolor transparent(1,0.75,cmyk(0,0,1,0)) ;
+% fill fullcircle scaled 8cm withcolor \MPcolor{sss} ;
+% fill fullcircle scaled 6cm withcolor \MPcolor{oeps1} ;
+% fill fullcircle scaled 4cm withcolor \MPcolor{oeps2} ;
+% currentpicture := currentpicture shifted (-7.5cm,0) ;
+% fill fullcircle scaled 10cm withcolor \MPcolor{oeps3} ;
+% circular_shade(fullcircle scaled 8cm, 1, red, blue) ;
+% circular_shade(fullcircle scaled 6cm, 1, (1,0,0,0), (0,1,0,0)) ;
+% circular_shade(fullcircle scaled 4cm, 1, cmyk(.5,.5,1,0), (0,1,0,0)) ;
+% \stopMPpage
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua
new file mode 100644
index 00000000000..6d219fe0490
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua
@@ -0,0 +1,153 @@
+if not modules then modules = { } end modules ['mlib-int'] = {
+ 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",
+}
+
+local factor = number.dimenfactors.bp
+local mpprint = mp.print
+local mpboolean = mp.boolean
+local mpquoted = mp.quoted
+local getdimen = tex.getdimen
+local getcount = tex.getcount
+local get = tex.get
+local mpcolor = attributes.colors.mpcolor
+local emwidths = fonts.hashes.emwidths
+local exheights = fonts.hashes.exheights
+
+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.PageNumber () mpprint(getcount("pageno")) end
+function mp.RealPageNumber () mpprint(getcount("realpageno")) end
+function mp.NOfPages () mpprint(getcount("lastpageno")) end
+
+function mp.CurrentColumn () mpprint(getcount("mofcolumns")) end
+function mp.NOfColumns () mpprint(getcount("nofcolumns")) end
+
+function mp.BaseLineSkip () mpprint(getdimen("baselineskip") *factor) end
+function mp.LineHeight () mpprint(getdimen("lineheight") *factor) end
+function mp.BodyFontSize () mpprint(getdimen("bodyfontsize") *factor) end
+
+function mp.TopSkip () mpprint(getdimen("topskip") *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
+
+mp.HSize = mp.CurrentWidth
+mp.VSize = mp.CurrentHeight
+mp.LastPageNumber = mp.NOfPages
+
+function mp.PageFraction ()
+ local lastpage = getcount("lastpageno")
+ if lastpage > 1 then
+ mpprint((getcount("realpageno")-1)/(lastpage-1))
+ else
+ mpprint(1)
+ end
+end
+
+-- locals
+
+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.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.defaultcolormodel()
+ 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
+end
+
+-- not much difference (10000 calls in a graphic neither as expansion seems to win
+-- over defining the macro etc) so let's not waste counters then
+
+-- function mp.OverlayColor()
+-- local c = mpcolor(
+-- getcount("c_overlay_colormodel"),
+-- getcount("c_overlay_color"),
+-- getcount("c_overlay_transparency")
+-- )
+-- mpquoted(c)
+-- end
+--
+-- function mp.OverlayLineColor()
+-- local c = mpcolor(
+-- getcount("c_overlay_colormodel"),
+-- getcount("c_overlay_linecolor"),
+-- getcount("c_overlay_linetransparency")
+-- )
+-- mpquoted(c)
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua
new file mode 100644
index 00000000000..baf9346c472
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua
@@ -0,0 +1,392 @@
+if not modules then modules = { } end modules ['mlib-lua'] = {
+ 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 is very preliminary code!
+
+-- maybe we need mplib.model, but how with instances
+
+local type, tostring, select, loadstring = type, tostring, select, loadstring
+local find, gsub = string.find, string.gsub
+
+local formatters = string.formatters
+local concat = table.concat
+local lpegmatch = lpeg.match
+
+local P, S, Ct = lpeg.P, lpeg.S, lpeg.Ct
+
+local report_luarun = logs.reporter("metapost","lua")
+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)
+
+mp = mp or { } -- system namespace
+MP = MP or { } -- user namespace
+
+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_pair = formatters["(%.16f,%.16f)"]
+local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
+local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
+
+function mp.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] = value
+ elseif t == "table" then
+ buffer[n] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[n] = tostring(value)
+ end
+ end
+ end
+end
+
+function mp.boolean(n)
+ n = n + 1
+ buffer[n] = n and "true" or "false"
+end
+
+function mp.numeric(n)
+ n = n + 1
+ buffer[n] = n and f_numeric(n) or "0"
+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)
+ 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)
+ 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)
+ 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 = "--"
+ 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])
+ end
+ if cycle then
+ n = n + 1 ; buffer[n] = connector
+ n = n + 1 ; buffer[n] = "cycle"
+ end
+ end
+ end
+end
+
+function mp.size(t)
+ n = n + 1
+ buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
+end
+
+-- experiment: names can change
+
+local datasets = { }
+mp.datasets = datasets
+
+function datasets.load(tag,filename)
+ if not filename then
+ tag, filename = file.basename(tag), tag
+ 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 replacer = lpeg.replacer("@","%%")
+
+function mp.format(fmt,...)
+ n = n + 1
+ if not find(fmt,"%%") then
+ fmt = lpegmatch(replacer,fmt)
+ end
+ buffer[n] = formatters[fmt](...)
+end
+
+function mp.quoted(fmt,s,...)
+ n = n + 1
+ if s then
+ if not find(fmt,"%%") then
+ fmt = lpegmatch(replacer,fmt)
+ end
+ buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
+ elseif fmt then
+ buffer[n] = '"' .. fmt .. '"'
+ else
+ -- something is wrong
+ end
+end
+
+function mp.n(t)
+ return type(t) == "table" and #t or 0
+end
+
+local whitespace = lpeg.patterns.whitespace
+local newline = lpeg.patterns.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
+
+function mp.dataset(str)
+ return lpegmatch(pattern,str)
+end
+
+-- \startluacode
+-- local str = [[
+-- 10 20 20 20
+-- 30 40 40 60
+-- 50 10
+--
+-- 10 10 20 30
+-- 30 50 40 50
+-- 50 20 -- the last one
+--
+-- 10 20 % comment
+-- 20 10
+-- 30 40 # comment
+-- 40 20
+-- 50 10
+-- ]]
+--
+-- MP.myset = mp.dataset(str)
+--
+-- inspect(MP.myset)
+-- \stopluacode
+--
+-- \startMPpage
+-- color c[] ; c[1] := red ; c[2] := green ; c[3] := blue ;
+-- for i=1 upto lua("mp.print(mp.n(MP.myset))") :
+-- draw lua("mp.path(MP.myset[" & decimal i & "])") withcolor c[i] ;
+-- endfor ;
+-- \stopMPpage
+
+-- function metapost.runscript(code)
+-- local f = loadstring(f_code(code))
+-- if f then
+-- local result = f()
+-- if result then
+-- local t = type(result)
+-- if t == "number" then
+-- return f_numeric(result)
+-- elseif t == "string" then
+-- return result
+-- else
+-- return tostring(result)
+-- end
+-- end
+-- end
+-- return ""
+-- end
+
+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")
+ 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
+
+function mp.tt_initialize(tt)
+ textexts = tt
+end
+
+-- 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[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
+
+function mp.report(a,b)
+ if b then
+ report_message("%s : %s",a,b)
+ elseif a then
+ report_message("%s : %s","message",a)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua
new file mode 100644
index 00000000000..a2d4638a904
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua
@@ -0,0 +1,722 @@
+if not modules then modules = { } end modules ['mlib-pdf'] = {
+ 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",
+}
+
+-- maybe %s is better than %f
+
+local format, concat, gsub = string.format, table.concat, string.gsub
+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
+local lpegmatch = lpeg.match
+local formatters = string.formatters
+
+local report_metapost = logs.reporter("metapost")
+
+local trace_variables = false trackers.register("metapost.variables",function(v) trace_variables = v end)
+
+local mplib = mplib
+local context = context
+
+local allocate = utilities.storage.allocate
+
+local copy_node = node.copy
+local write_node = node.write
+
+local pen_info = mplib.pen_info
+local object_fields = mplib.fields
+
+local save_table = false
+
+metapost = metapost or { }
+local metapost = metapost
+
+metapost.flushers = metapost.flushers or { }
+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 f_j = formatters["%i j"]
+local f_J = formatters["%i J"]
+local f_d = formatters["[%s] %F d"]
+local f_w = formatters["%F w"]
+
+directives.register("metapost.savetable",function(v)
+ if type(v) == "string" then
+ save_table = file.addsuffix(v,"mpl")
+ elseif v then
+ save_table = file.addsuffix(environment.jobname .. "-graphic","mpl")
+ else
+ save_table = false
+ end
+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
+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)
+ end
+ return true -- done
+end
+
+function metapost.flushliteral(d)
+ if savedliterals then
+ local literal = copy_node(mpsliteral)
+ literal.data = savedliterals[d]
+ write_node(literal)
+ else
+ report_metapost("problem flushing literal %a",d)
+ end
+end
+
+function metapost.flushreset() -- will become obsolete and internal
+ savedliterals = nil
+end
+
+function pdfflusher.comment(message)
+ if message then
+ message = formatters["%% mps graphic %s: %s"](metapost.n,message)
+ if experiment then
+ context(pdfliteral(message))
+ else
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = message
+ context.MPLIBtoPDF(last)
+ else
+ savedliterals = { message }
+ context.MPLIBtoPDF(1)
+ end
+ end
+ end
+end
+
+function pdfflusher.startfigure(n,llx,lly,urx,ury,message)
+ savedliterals = nil
+ metapost.n = metapost.n + 1
+ context.startMPLIBtoPDF(f_f(llx),f_f(lly),f_f(urx),f_f(ury))
+ if message then pdfflusher.comment(message) end
+end
+
+function pdfflusher.stopfigure(message)
+ if message then pdfflusher.comment(message) end
+ context.stopMPLIBtoPDF()
+ context.MPLIBflushreset() -- maybe just at the beginning
+end
+
+function pdfflusher.flushfigure(pdfliterals) -- table
+ if #pdfliterals > 0 then
+ pdfliterals = concat(pdfliterals,"\n")
+ if experiment then
+ context(pdfliteral(pdfliterals))
+ else
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = pdfliterals
+ context.MPLIBtoPDF(last)
+ else
+ savedliterals = { pdfliterals }
+ context.MPLIBtoPDF(1)
+ end
+ end
+ end
+end
+
+function pdfflusher.textfigure(font,size,text,width,height,depth) -- we could save the factor
+ text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib)
+ context.MPtextext(font,size,text,0,-number.dimenfactors.bp*depth)
+end
+
+local bend_tolerance = 131/65536
+
+local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+
+local function pen_characteristics(object)
+ local t = pen_info(object)
+ rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
+ divider = sx*sy - rx*ry
+ return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
+end
+
+local function mpconcat(px, py) -- no tx, ty here / we can move this one inline if needed
+ return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+end
+
+local function curved(ith,pth)
+ local d = pth.left_x - ith.right_x
+ if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
+ d = pth.left_y - ith.right_y
+ if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
+ return false
+ end
+ end
+ return true
+end
+
+local function flushnormalpath(path, t, open)
+ local pth, ith, nt
+ if t then
+ nt = #t
+ else
+ t = { }
+ nt = 0
+ end
+ for i=1,#path do
+ nt = nt + 1
+ pth = path[i]
+ if not ith then
+ t[nt] = f_m(pth.x_coord,pth.y_coord)
+ elseif curved(ith,pth) then
+ t[nt] = f_c(ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+ else
+ t[nt] = f_l(pth.x_coord,pth.y_coord)
+ end
+ ith = pth
+ end
+ if not open then
+ nt = nt + 1
+ local one = path[1]
+ if curved(pth,one) then
+ t[nt] = f_c(pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+ else
+ t[nt] = f_l(one.x_coord,one.y_coord)
+ end
+ elseif #path == 1 then
+ -- special case .. draw point
+ local one = path[1]
+ nt = nt + 1
+ t[nt] = f_l(one.x_coord,one.y_coord)
+ end
+ return t
+end
+
+local function flushconcatpath(path, t, open)
+ local pth, ith, nt
+ if t then
+ nt = #t
+ else
+ t = { }
+ nt = 0
+ end
+ nt = nt + 1
+ t[nt] = f_cm(sx,rx,ry,sy,tx,ty)
+ for i=1,#path do
+ nt = nt + 1
+ pth = path[i]
+ if not ith then
+ t[nt] = f_m(mpconcat(pth.x_coord,pth.y_coord))
+ elseif curved(ith,pth) then
+ local a, b = mpconcat(ith.right_x,ith.right_y)
+ local c, d = mpconcat(pth.left_x,pth.left_y)
+ t[nt] = f_c(a,b,c,d,mpconcat(pth.x_coord,pth.y_coord))
+ else
+ t[nt] = f_l(mpconcat(pth.x_coord, pth.y_coord))
+ end
+ ith = pth
+ end
+ if not open then
+ nt = nt + 1
+ local one = path[1]
+ if curved(pth,one) then
+ local a, b = mpconcat(pth.right_x,pth.right_y)
+ local c, d = mpconcat(one.left_x,one.left_y)
+ t[nt] = f_c(a,b,c,d,mpconcat(one.x_coord, one.y_coord))
+ else
+ t[nt] = f_l(mpconcat(one.x_coord,one.y_coord))
+ end
+ elseif #path == 1 then
+ -- special case .. draw point
+ nt = nt + 1
+ local one = path[1]
+ t[nt] = f_l(mpconcat(one.x_coord,one.y_coord))
+ end
+ return t
+end
+
+metapost.flushnormalpath = flushnormalpath
+
+-- The flusher is pdf based, if another backend is used, we need to overload the
+-- flusher; this is beta code, the organization will change (already upgraded in
+-- sync with mplib)
+--
+-- We can avoid the before table but I like symmetry. There is of course a small
+-- performance penalty, but so is passing extra arguments (result, flusher, after)
+-- and returning stuff.
+
+local ignore = function () end
+
+local space = P(" ")
+local equal = P("=")
+local key = C((1-equal)^1) * equal
+local newline = S("\n\r")^1
+local number = (((1-space-newline)^1) / tonumber) * (space^0)
+
+local p_number = number
+local p_string = C((1-newline)^0)
+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
+ + P("3:") * p_boolean
+ + S("4568") * P(":") * p_set
+ + P("7:") * p_path
+
+local pattern_tab = Cf ( Carg(1) * (Cg(variable * newline^0)^0), rawset)
+
+local variable =
+ P("1:") * p_number
+ + P("2:") * p_string
+ + P("3:") * p_boolean
+ + S("4568") * P(":") * number^1
+ + P("7:") * (number * number^-5)^1
+
+local pattern_lst = (variable * newline^0)^0
+
+metapost.variables = { } -- to be stacked
+metapost.properties = { } -- to be stacked
+
+function metapost.untagvariable(str,variables) -- will be redone
+ if variables == false then
+ return lpegmatch(pattern_lst,str)
+ else
+ return lpegmatch(pattern_tab,str,1,variables or { })
+ end
+end
+
+-- function metapost.processspecial(str)
+-- lpegmatch(pattern_key,object.prescript,1,variables)
+-- end
+
+function metapost.processspecial(str)
+ local code = loadstring(str)
+ if code then
+ if trace_variables then
+ report_metapost("executing special code: %s",str)
+ end
+ code()
+ else
+ report_metapost("invalid special code: %s",str)
+ end
+end
+
+local function setproperties(figure)
+ local boundingbox = figure:boundingbox()
+ local properties = {
+ llx = boundingbox[1],
+ lly = boundingbox[2],
+ urx = boundingbox[3],
+ ury = boundingbox[4],
+ slot = figure:charcode(),
+ width = figure:width(),
+ height = figure:height(),
+ depth = figure:depth(),
+ italic = figure:italcorr(),
+ number = figure:charcode() or 0,
+ }
+ metapost.properties = properties
+ return properties
+end
+
+local function setvariables(figure)
+ local variables = { }
+ metapost.variables = variables
+ return variables
+end
+
+function metapost.flush(result,flusher,askedfig)
+ if result then
+ 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 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
+ local variables = setvariables(figure) -- also resets then in case of not found
+ 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)
+ 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
+ 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
+ end
+ 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)
+ end
+ if both then
+ if dashed ~= false then -- was just dashed test
+ result[#result+1] = "[] 0 d"
+ dashed = 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
+ 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'
+ 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)
+ end
+ end
+ savedpath = nil
+ end
+ if transformed then
+ flushconcatpath(path,result,open)
+ else
+ flushnormalpath(path,result,open)
+ end
+ if 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" -- f* = 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
+ 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)
+ 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 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 after then
+ result = pluginactions(after,result,flushfigure)
+ 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
+ end
+ result[#result+1] = "Q"
+ flushfigure(result)
+ stopfigure("end")
+ end
+ if askedfig ~= "all" then
+ break
+ end
+ end
+ end
+ 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
+ end
+ return multipass
+ end
+ end
+end
+
+-- tracing:
+
+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()
+ end
+}
+
+function metapost.pdfliterals(result)
+ metapost.flush(result,flusher)
+ return result
+end
+
+function metapost.totable(result,askedfig)
+ local askedfig = askedfig or 1
+ 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]
+ local result = { }
+ local fields = object_fields(object) -- hm, is this the whole list, if so, we can get it once
+ for f=1,#fields do
+ local field = fields[f]
+ result[field] = object[field]
+ end
+ results[o] = result
+ end
+ local boundingbox = figure:boundingbox()
+ return {
+ boundingbox = {
+ llx = boundingbox[1],
+ lly = boundingbox[2],
+ urx = boundingbox[3],
+ ury = boundingbox[4],
+ },
+ objects = results
+ }
+ else
+ return nil
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv
new file mode 100644
index 00000000000..78dab716df6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv
@@ -0,0 +1,184 @@
+%D \module
+%D [ file=mlib-pdf,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Conversion to PDF,
+%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
+
+% We use bit more code that needed because we want to limit the
+% amount of boxing.
+
+\registerctxluafile{mlib-pdf}{1.001}
+
+%D Some code is shared between MPLIB and MPS. The following variables
+%D are also available for introspection and other purposes.
+
+\ifdefined\MPwidth \else \newdimen\MPwidth \fi
+\ifdefined\MPheight \else \newdimen\MPheight \fi
+
+\ifdefined\MPllx \else \newdimen\MPllx \fi
+\ifdefined\MPlly \else \newdimen\MPlly \fi
+\ifdefined\MPurx \else \newdimen\MPurx \fi
+\ifdefined\MPury \else \newdimen\MPury \fi
+
+\ifdefined\MPbox \else \newbox \MPbox \fi
+
+\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points
+ {\global\MPllx #1\onebasepoint
+ \global\MPlly #2\onebasepoint
+ \global\MPurx #3\onebasepoint
+ \global\MPury #4\onebasepoint
+ \global\MPwidth \dimexpr\MPurx-\MPllx\relax
+ \global\MPheight\dimexpr\MPury-\MPlly\relax}
+
+\def\resetMPboundingbox
+ {\global\MPwidth \zeropoint
+ \global\MPheight\zeropoint
+ \global\MPllx \zeropoint
+ \global\MPlly \zeropoint
+ \global\MPurx \zeropoint
+ \global\MPury \zeropoint}
+
+\def\repositionMPboxindeed
+ {\setbox\MPbox\hpack\bgroup
+ \kern-\MPllx
+ \raise-\MPlly
+ \box\MPbox
+ \egroup}
+
+\def\repositionMPbox
+ {\ifzeropt\MPllx
+ \ifzeropt\MPlly
+ % okay
+ \else
+ \repositionMPboxindeed
+ \fi
+ \else
+ \repositionMPboxindeed
+ \fi}
+
+\def\finalizeMPbox
+ {\repositionMPbox
+ \setbox\MPbox\vpack to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\MPbox
+ \box\MPbox
+ \egroup
+ \wd\MPbox\MPwidth
+ \ht\MPbox\MPheight}
+
+\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:
+
+\def\MPLIBtoPDF{\clf_mpflushliteral}
+
+\def\startMPLIBtoPDF#1#2#3#4%
+ {\meta_process_graphic_figure_start
+ \dostarttagged\t!mpgraphic\empty
+ \naturalhbox attr \imageattribute 1 \bgroup
+ \dousecolorparameter\s!black\forcecolorhack
+ \setMPboundingbox{#1}{#2}{#3}{#4}%
+ \setbox\MPbox\vpack\bgroup
+ % \forgetall % already done elsewhere
+ \noindent} % forces the proper cm in the backend
+
+\def\stopMPLIBtoPDF
+ {\egroup
+ \finalizeMPbox
+ \box\MPbox
+ \egroup
+ \dostoptagged
+ \meta_process_graphic_figure_stop}
+
+\def\MPLIBflushreset % This can (will) move to the Lua end.
+ {\clf_mpflushreset}
+
+%D Kind of special:
+%
+% test.mp:
+%
+% beginfig(1) fill fullcircle scaled 10cm withcolor red ; endfig ;
+% beginfig(2) draw fullcircle scaled 5cm withcolor blue ; endfig ;
+% beginfig(3) draw textext("just some text") ; endfig ;
+%
+% standalone pages:
+%
+% \starttext
+% \directMPgraphic{input "test.mp" ;}
+% \stoptext
+
+\let\normalstartMPLIBtoPDF\startMPLIBtoPDF
+\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF
+
+\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF}
+\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage}
+
+\unexpanded\def\directMPgraphic
+ {\dodoublegroupempty\mlib_direct_graphic}
+
+% \def\mlib_direct_graphic#1#2% makes pages (todo: make boxes)
+% {\meta_begin_graphic_group{#1}%
+% \let\startMPLIBtoPDF\directstartMPLIBtoPDF
+% \let\stopMPLIBtoPDF \directstopMPLIBtoPDF
+% \meta_start_current_graphic
+% \forgetall
+% \edef\p_extensions{\MPinstanceparameter\s!extensions}%
+% \normalexpanded{\noexpand\ctxlua{metapost.graphic {
+% instance = "\currentMPinstance",
+% format = "\currentMPformat",
+% data = \!!bs#2;\!!es,
+% initializations = \!!bs\meta_flush_current_initializations\!!es,
+% % useextensions = "\MPinstanceparameter\s!extensions",
+% \ifx\p_extensions\v!yes
+% extensions = \!!bs\clf_getmpextensions{\currentMPinstance}\!!es,
+% \fi
+% inclusions = \!!bs\meta_flush_current_inclusions\!!es,
+% definitions = \!!bs\meta_flush_current_definitions\!!es,
+% figure = "all",
+% method = "\MPinstanceparameter\c!method",
+% }}}%
+% \meta_stop_current_graphic
+% \meta_end_graphic_group}
+
+\def\mlib_direct_graphic#1#2% makes pages (todo: make boxes)
+ {\meta_begin_graphic_group{#1}%
+ \let\startMPLIBtoPDF\directstartMPLIBtoPDF
+ \let\stopMPLIBtoPDF \directstopMPLIBtoPDF
+ \meta_start_current_graphic
+ \forgetall
+ \edef\p_extensions{\MPinstanceparameter\s!extensions}%
+ \normalexpanded{\noexpand\clf_mpgraphic
+ instance {\currentMPinstance}%
+ format {\currentMPformat}%
+ data {#2;}%
+ initializations {\meta_flush_current_initializations}%
+ \ifx\p_extensions\v!yes
+ extensions {\clf_getmpextensions{\currentMPinstance}}%
+ \fi
+ inclusions {\meta_flush_current_inclusions}%
+ definitions {\meta_flush_current_definitions}%
+ figure {all}%
+ method {\MPinstanceparameter\c!method}%
+ \relax}%
+ \meta_stop_current_graphic
+ \meta_end_graphic_group}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua
new file mode 100644
index 00000000000..c016e0f3615
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua
@@ -0,0 +1,1497 @@
+if not modules then modules = { } end modules ['mlib-pps'] = {
+ 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",
+}
+
+local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split
+local tonumber, type, unpack = tonumber, type, unpack
+local round = math.round
+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
+local lpegmatch, tsplitat, tsplitter = lpeg.match, lpeg.tsplitat, lpeg.tsplitter
+local formatters = string.formatters
+
+local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
+
+local context = context
+local context_setvalue = context.setvalue
+
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+local textakebox = tex.takebox
+local copy_list = node.copy_list
+local free_list = node.flush_list
+local setmetatableindex = table.setmetatableindex
+local sortedhash = table.sortedhash
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local trace_runs = false trackers.register("metapost.runs", function(v) trace_runs = v end)
+local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end)
+local trace_scripts = false trackers.register("metapost.scripts", function(v) trace_scripts = v end)
+
+local report_metapost = logs.reporter("metapost")
+local report_textexts = logs.reporter("metapost","textexts")
+local report_scripts = logs.reporter("metapost","scripts")
+
+local colors = attributes.colors
+local defineprocesscolor = colors.defineprocesscolor
+local definespotcolor = colors.definespotcolor
+local definemultitonecolor = colors.definemultitonecolor
+local colorvalue = colors.value
+
+local transparencies = attributes.transparencies
+local registertransparency = transparencies.register
+local transparencyvalue = transparencies.value
+
+local rgbtocmyk = colors.rgbtocmyk -- or function() return 0,0,0,1 end
+local cmyktorgb = colors.cmyktorgb -- or function() return 0,0,0 end
+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
+local outercolor = nooutercolor
+local outertransparency = nooutertransparency
+local innercolor = nooutercolor
+local innertransparency = nooutertransparency
+
+local pdfcolor = lpdf.color
+local pdftransparency = lpdf.transparency
+
+function metapost.setoutercolor(mode,colormodel,colorattribute,transparencyattribute)
+ -- has always to be called before conversion
+ -- todo: transparency (not in the mood now)
+ outercolormode = mode
+ if mode == 1 or mode == 3 then
+ -- inherit from outer (registered color)
+ outercolor = pdfcolor(colormodel,colorattribute) or nooutercolor
+ outertransparency = pdftransparency(transparencyattribute) or nooutertransparency
+ elseif mode == 2 then
+ -- stand alone (see m-punk.tex)
+ outercolor = ""
+ outertransparency = ""
+ else -- 0
+ outercolor = nooutercolor
+ outertransparency = nooutertransparency
+ end
+ innercolor = outercolor
+ innertransparency = outertransparency -- not yet used
+end
+
+-- todo: get this from the lpdf module
+
+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_spot = formatters["/%s cs /%s CS %s SCN %s scn"]
+
+local function checked_color_pair(color,...)
+ if not color then
+ return innercolor, outercolor
+ end
+ if outercolormode == 3 then
+ innercolor = color(...)
+ return innercolor, innercolor
+ else
+ return color(...), outercolor
+ end
+end
+
+function metapost.colorinitializer()
+ innercolor = outercolor
+ innertransparency = outertransparency
+ return outercolor, outertransparency
+end
+
+--~
+
+local specificationsplitter = tsplitat(" ")
+local colorsplitter = tsplitter(":",tonumber) -- no need for :
+local domainsplitter = tsplitter(" ",tonumber)
+local centersplitter = domainsplitter
+local coordinatesplitter = domainsplitter
+
+-- thanks to taco's reading of the postscript manual:
+--
+-- x' = sx * x + ry * y + tx
+-- y' = rx * x + sy * y + ty
+
+local nofshades = 0 -- todo: hash resources, start at 1000 in order not to clash with older
+
+local function normalize(ca,cb)
+ if #cb == 1 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = 0, 0, 0, 1-cb[1]
+ else
+ cb[1], cb[2], cb[3] = cb[1], cb[1], cb[1]
+ end
+ elseif #cb == 3 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ else
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ end
+ end
+end
+
+
+local commasplitter = tsplitat(",")
+
+local function checkandconvertspot(n_a,f_a,c_a,v_a,n_b,f_b,c_b,v_b)
+ -- must be the same but we don't check
+ local name = f_shade(nofshades)
+ local ca = lpegmatch(commasplitter,v_a)
+ local cb = lpegmatch(commasplitter,v_b)
+ if #ca == 0 or #cb == 0 then
+ return { 0 }, { 1 }, "DeviceGray", name
+ else
+ for i=1,#ca do ca[i] = tonumber(ca[i]) or 0 end
+ for i=1,#cb do cb[i] = tonumber(cb[i]) or 1 end
+ --~ spotcolorconverter(n_a,f_a,c_a,v_a) -- not really needed
+ return ca, cb, n_a or n_b, name
+ end
+end
+
+local function checkandconvert(ca,cb,model)
+ local name = f_shade(nofshades)
+ if not ca or not cb or type(ca) == "string" then
+ return { 0 }, { 1 }, "DeviceGray", name
+ else
+ if #ca > #cb then
+ normalize(ca,cb)
+ elseif #ca < #cb then
+ normalize(cb,ca)
+ end
+ if not model then
+ model = colors.model
+ end
+ if model == "all" then
+ model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray"
+ end
+ if model == "rgb" then
+ if #ca == 4 then
+ 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]
+ ca = { a, a, a }
+ cb = { b, b, b }
+ end
+ return ca, cb, "DeviceRGB", name, model
+ elseif model == "cmyk" then
+ if #ca == 3 then
+ ca = { rgbtocmyk(ca[1],ca[2],ca[3]) }
+ cb = { rgbtocmyk(cb[1],cb[2],cb[3]) }
+ elseif #ca == 1 then
+ ca = { 0, 0, 0, ca[1] }
+ cb = { 0, 0, 0, ca[1] }
+ end
+ return ca, cb, "DeviceCMYK", name, model
+ else
+ if #ca == 4 then
+ ca = { cmyktogray(ca[1],ca[2],ca[3],ca[4]) }
+ cb = { cmyktogray(cb[1],cb[2],cb[3],cb[4]) }
+ elseif #ca == 3 then
+ ca = { rgbtogray(ca[1],ca[2],ca[3]) }
+ cb = { rgbtogray(cb[1],cb[2],cb[3]) }
+ end
+ -- backend specific (will be renamed)
+ return ca, cb, "DeviceGray", name, model
+ end
+ end
+end
+
+-- We keep textexts in a shared list (as it's easier that way and we also had that in
+-- the beginning). Each graphic gets its own (1 based) subtable so that we can also
+-- handle multiple conversions in one go which is needed when we process mp files
+-- directly.
+
+local stack = { } -- quick hack, we will pass topofstack around
+local top = nil
+local nofruns = 0 -- askedfig: "all", "first", number
+
+local function preset(t,k)
+ -- references to textexts by mp index
+ local v = {
+ textrial = 0,
+ texfinal = 0,
+ texslots = { },
+ texorder = { },
+ texhash = { },
+ }
+ t[k] = v
+ return v
+end
+
+local function startjob(plugmode)
+ 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
+ }
+ insert(stack,top)
+ if trace_runs then
+ report_metapost("starting run at level %i",#stack)
+ end
+ return top
+end
+
+local function stopjob()
+ if top then
+ for n, tn in next, top.textexts do
+ free_list(tn)
+ if trace_textexts then
+ report_textexts("freeing text %s",n)
+ end
+ end
+ if trace_runs then
+ report_metapost("stopping run at level %i",#stack)
+ end
+ remove(stack)
+ top = stack[#stack]
+ return top
+ end
+end
+
+function metapost.getjobdata()
+ return top
+end
+
+-- end of new
+
+local function settext(box,slot)
+ if top then
+ -- if trace_textexts then
+ -- report_textexts("getting text %s from box %s",slot,box)
+ -- end
+ top.textexts[slot] = copy_list(texgetbox(box))
+ texsetbox(box,nil)
+ -- this can become
+ -- top.textexts[slot] = textakebox(box)
+ else
+ -- weird error
+ end
+end
+
+local function gettext(box,slot)
+ if top then
+ texsetbox(box,copy_list(top.textexts[slot]))
+ -- if trace_textexts then
+ -- report_textexts("putting text %s in box %s",slot,box)
+ -- end
+ -- top.textexts[slot] = nil -- no, pictures can be placed several times
+ else
+ -- weird error
+ end
+end
+
+metapost.settext = settext
+metapost.gettext = gettext
+
+implement { name = "mpsettext", actions = settext, arguments = { "integer", "integer" } } -- box slot
+implement { name = "mpgettext", actions = gettext, arguments = { "integer", "integer" } } -- box slot
+
+-- rather generic pdf, so use this elsewhere too it no longer pays
+-- off to distinguish between outline and fill (we now have both
+-- too, e.g. in arrows)
+
+metapost.reducetogray = true
+
+local models = { }
+
+function models.all(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ 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]
+ 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]
+ if c == m and m == y and y == 0 then
+ k = 1 - k
+ return checked_color_pair(f_gray,k,k)
+ else
+ return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
+ end
+ end
+ elseif n == 1 then
+ 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]
+ 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]
+ return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
+ end
+end
+
+function models.rgb(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ 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]
+ 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]
+ if c == m and m == y and y == 0 then
+ k = 1 - k
+ return checked_color_pair(f_gray,k,k)
+ else
+ local r, g, b = cmyktorgb(c,m,y,k)
+ return checked_color_pair(f_rgb,r,g,b,r,g,b)
+ end
+ end
+ elseif n == 1 then
+ local s = cr[1]
+ return checked_color_pair(f_gray,s,s)
+ else
+ 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]
+ end
+ return checked_color_pair(f_rgb,r,g,b,r,g,b)
+ end
+end
+
+function models.cmyk(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ 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]
+ if r == g and g == b then
+ return checked_color_pair(f_gray,r,r)
+ else
+ local c, m, y, k = rgbtocmyk(r,g,b)
+ 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]
+ if c == m and m == y and y == 0 then
+ k = k - 1
+ return checked_color_pair(f_gray,k,k)
+ else
+ return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
+ end
+ end
+ elseif n == 1 then
+ local s = cr[1]
+ return checked_color_pair(f_gray,s,s)
+ else
+ local c, m, y, k
+ 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]
+ 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
+ if n == 0 then
+ return checked_color_pair()
+ elseif n == 4 then
+ s = cmyktogray(cr[1],cr[2],cr[3],cr[4])
+ elseif n == 3 then
+ s = rgbtogray(cr[1],cr[2],cr[3])
+ else
+ s = cr[1]
+ end
+ return checked_color_pair(f_gray,s,s)
+end
+
+setmetatableindex(models, function(t,k)
+ local v = models.gray
+ t[k] = v
+ return v
+end)
+
+local function colorconverter(cs)
+ return models[colors.model](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 = true 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)
+
+-- function metapost.edefsxsy(wd,ht,dp) -- helper for figure
+-- local hd = ht + dp
+-- context_setvalue("sx",wd ~= 0 and factor/wd or 0)
+-- context_setvalue("sy",hd ~= 0 and factor/hd or 0)
+-- end
+
+implement {
+ name = "mpsetsxsy",
+ arguments = { "dimen", "dimen", "dimen" },
+ actions = function(wd,ht,dp)
+ local hd = ht + dp
+ setmacro("sx",wd ~= 0 and factor/wd or 0)
+ setmacro("sy",hd ~= 0 and factor/hd or 0)
+ end
+}
+
+local function sxsy(wd,ht,dp) -- helper for text
+ local hd = ht + dp
+ return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
+end
+
+-- 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()
+ local textexts = top.textexts
+ local collected = { }
+ 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
+ collected[n] = box
+ else
+ break
+ end
+ end
+ end
+ mp.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 function checkaskedfig(askedfig) -- return askedfig, wrappit
+ if not askedfig then
+ return "direct", true
+ elseif askedfig == "all" then
+ return "all", false
+ elseif askedfig == "direct" then
+ return "all", true
+ else
+ askedfig = tonumber(askedfig)
+ if askedfig then
+ return askedfig, false
+ else
+ return "direct", true
+ end
+ end
+end
+
+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)
+end
+
+function metapost.graphic_base_pass(specification) -- name will change (see mlib-ctx.lua)
+ local top = startjob(true)
+ --
+ 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(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
+ 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
+ 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, {
+ preamble,
+ 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
+
+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
+end
+
+implement {
+ name = "registermpyfile",
+ actions = makempy.registerfile,
+ arguments = "string"
+}
+
+function makempy.processgraphics(graphics)
+ if #graphics == 0 then
+ return
+ end
+ if mpyfilename and io.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")
+ io.savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n")
+ local command = format("context --once %s %s", (tex.interactionmode == 0 and "--batchmode") or "", texfile)
+ os.execute(command)
+ if io.exists(pdffile) then
+ command = format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)
+ logs.newline()
+ report_metapost("running: %s",command)
+ logs.newline()
+ os.execute(command)
+ if io.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
+ io.savedata(mpyfile,concat(result,""))
+ end
+ end
+ end
+ stoptiming(makempy)
+end
+
+-- -- the new plugin handler -- --
+
+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" }
+
+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 )
+
+local function splitprescript(script)
+ local hash = lpegmatch(scriptsplitter,script)
+ for i=#hash,1,-1 do
+ local h = hash[i]
+ hash[h[1]] = h[2]
+ end
+ if trace_scripts then
+ report_scripts(table.serialize(hash,"prescript"))
+ end
+ return hash
+end
+
+-- -- not used:
+--
+-- local function splitpostscript(script)
+-- local hash = lpegmatch(scriptsplitter,script)
+-- for i=1,#hash do
+-- local h = hash[i]
+-- hash[h[1]] = h[2]
+-- end
+-- if trace_scripts then
+-- report_scripts(table.serialize(hash,"postscript"))
+-- end
+-- return hash
+-- end
+
+function metapost.pluginactions(what,t,flushfigure) -- before/after object, depending on what
+ if top.plugmode then -- hm, what about other features
+ for i=1,#what do
+ local wi = what[i]
+ if type(wi) == "function" then
+ -- assume injection
+ flushfigure(t) -- to be checked: too many 0 g 0 G
+ t = { }
+ wi()
+ else
+ t[#t+1] = wi
+ end
+ end
+ return t
+ end
+end
+
+function metapost.resetplugins(t) -- intialize plugins, before figure
+ if top.plugmode then
+ -- 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
+ end
+ return false
+end
+
+function metapost.processplugins(object) -- each object (second pass)
+ if top.plugmode then
+ local prescript = object.prescript -- specifications
+ if prescript and #prescript > 0 then
+ local before = { }
+ local after = { }
+ processor(object,splitprescript(prescript) or {},before,after)
+ return #before > 0 and before, #after > 0 and after
+ else
+ local c = object.color
+ if c and #c > 0 then
+ local b, a = colorconverter(c)
+ return { b }, { a }
+ end
+ end
+ end
+end
+
+-- helpers
+
+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 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
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ return sx, rx, ry, sy, tx, ty
+ else
+ return 1, 0, 0, 1, 0, 0 -- weird case
+ end
+end
+
+-- color
+
+local function cl_reset(t)
+ t[#t+1] = metapost.colorinitializer() -- only color
+end
+
+local function tx_reset()
+ if top then
+ -- why ?
+ top.texhash = { }
+ top.texlast = 0
+ 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 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)
+ end
+ 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)
+ 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)
+ 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)
+ 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)
+ end
+ 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
+ end
+ 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]
+ if trace_textexts then
+ report_textexts("stage %a, usage %a, number %a, use %a",tx_stage,tx_final,tx_number,n)
+ end
+ local sx, rx, ry, sy, tx, ty = cm(object) -- needs to be frozen outside the function
+ local box = top.textexts[n]
+ if box then
+ before[#before+1] = function()
+ -- flush always happens, we can have a special flush function injected before
+ context.MPLIBgettextscaledcm(n,
+ f_f(sx), -- bah ... %s no longer checks
+ f_f(rx), -- bah ... %s no longer checks
+ f_f(ry), -- bah ... %s no longer checks
+ f_f(sy), -- bah ... %s no longer checks
+ f_f(tx), -- bah ... %s no longer checks
+ f_f(ty), -- bah ... %s no longer checks
+ sxsy(box.width,box.height,box.depth))
+ end
+ else
+ before[#before+1] = function()
+ report_textexts("unknown %s",tx_number)
+ end
+ end
+ if not trace_textexts then
+ object.path = false -- else: keep it
+ end
+ object.color = false
+ object.grouped = true
+ object.istext = true
+ end
+ end
+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 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
+ end
+end
+
+-- local function gt_process(object,prescript,before,after)
+-- local gt_stage = prescript.gt_stage
+-- if gt_stage == "final" then
+-- end
+-- end
+
+-- shades
+
+local function sh_process(object,prescript,before,after)
+ local sh_type = prescript.sh_type
+ if sh_type then
+ nofshades = nofshades + 1
+ local domain = lpegmatch(domainsplitter,prescript.sh_domain or "0 1")
+ local centera = lpegmatch(centersplitter,prescript.sh_center_a or "0 0")
+ local centerb = lpegmatch(centersplitter,prescript.sh_center_b or "0 0")
+ local steps = tonumber(prescript.sh_step) or 1
+ local sh_color_a = prescript.sh_color_a_1 or prescript.sh_color_a or "1"
+ local sh_color_b = prescript.sh_color_b_1 or prescript.sh_color_b or "1" -- sh_color_b_<sh_steps>
+ local ca, cb, colorspace, name, model, separation, fractions
+ if prescript.sh_color == "into" and prescript.sp_name then
+ -- some spotcolor
+ local value_a, components_a, fractions_a, name_a
+ local value_b, components_b, fractions_b, name_b
+ for i=1,#prescript do
+ -- { "sh_color_a", "1" },
+ -- { "sh_color", "into" },
+ -- { "sh_radius_b", "0" },
+ -- { "sh_radius_a", "141.73225" },
+ -- { "sh_center_b", "425.19676 141.73225" },
+ -- { "sh_center_a", "425.19676 0" },
+ -- { "sh_factor", "1" },
+ local tag = prescript[i][1]
+ if not name_a and tag == "sh_color_a" then
+ value_a = prescript[i-5][2]
+ components_a = prescript[i-4][2]
+ fractions_a = prescript[i-3][2]
+ name_a = prescript[i-2][2]
+ elseif not name_b and tag == "sh_color_b" then
+ value_b = prescript[i-5][2]
+ components_b = prescript[i-4][2]
+ fractions_b = prescript[i-3][2]
+ name_b = prescript[i-2][2]
+ end
+ if name_a and name_b then
+ break
+ end
+ end
+ ca, cb, separation, name = checkandconvertspot(
+ name_a,fractions_a,components_a,value_a,
+ name_b,fractions_b,components_b,value_b
+ )
+ else
+ local colora = lpegmatch(colorsplitter,sh_color_a)
+ local colorb = lpegmatch(colorsplitter,sh_color_b)
+ ca, cb, colorspace, name, model = checkandconvert(colora,colorb)
+ -- test:
+ if steps > 1 then
+ ca = { ca }
+ cb = { cb }
+ fractions = { tonumber(prescript[formatters["sh_fraction_%i"](1)]) or 0 }
+ for i=2,steps do
+ local colora = lpegmatch(colorsplitter,prescript[formatters["sh_color_a_%i"](i)])
+ local colorb = lpegmatch(colorsplitter,prescript[formatters["sh_color_b_%i"](i)])
+ ca[i], cb[i] = checkandconvert(colora,colorb,model)
+ fractions[i] = tonumber(prescript[formatters["sh_fraction_%i"](i)]) or (i/steps)
+ end
+ end
+ end
+ if not ca or not cb then
+ ca, cb, colorspace, name = checkandconvert()
+ steps = 1
+ end
+ if sh_type == "linear" then
+ local coordinates = { centera[1], centera[2], centerb[1], centerb[2] }
+ lpdf.linearshade(name,domain,ca,cb,1,colorspace,coordinates,separation,steps>1 and steps,fractions) -- backend specific (will be renamed)
+ elseif sh_type == "circular" then
+ local factor = tonumber(prescript.sh_factor) or 1
+ local radiusa = factor * tonumber(prescript.sh_radius_a)
+ local radiusb = factor * tonumber(prescript.sh_radius_b)
+ local coordinates = { centera[1], centera[2], radiusa, centerb[1], centerb[2], radiusb }
+ lpdf.circularshade(name,domain,ca,cb,1,colorspace,coordinates,separation,steps>1 and steps,fractions) -- backend specific (will be renamed)
+ else
+ -- fatal error
+ end
+ before[#before+1] = "q /Pattern cs"
+ after [#after+1] = formatters["W n /%s sh Q"](name)
+ -- false, not nil, else mt triggered
+ object.colored = false -- hm, not object.color ?
+ object.type = false
+ object.grouped = true
+ end
+end
+
+-- bitmaps
+
+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] = function()
+ figures.bitmapimage {
+ xresolution = tonumber(bm_xresolution),
+ yresolution = tonumber(prescript.bm_yresolution),
+ width = 1/basepoints,
+ height = 1/basepoints,
+ data = object.postscript
+ }
+ end
+ before[#before+1] = "Q"
+ object.path = false
+ object.color = false
+ object.grouped = true
+ end
+end
+
+-- positions
+
+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 properties = metapost.properties
+ x = x - properties.llx
+ y = properties.ury - y
+ before[#before+1] = function()
+ context.MPLIBpositionwhd(ps_label,x,y,w,h)
+ end
+ object.path = false
+ end
+end
+
+-- figures
+
+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] = function()
+ context.MPLIBfigure(fg_name,prescript.fg_mask or "")
+ end
+ before[#before+1] = "Q"
+ object.path = false
+ object.grouped = true
+ end
+end
+
+-- color and transparency
+
+local value = Cs ( (
+ (Carg(1) * C((1-P(","))^1)) / function(a,b) return f_f3(a * tonumber(b)) end
+ + P(","))^1
+)
+
+-- should be codeinjections
+
+local t_list = attributes.list[attributes.private('transparency')]
+local c_list = attributes.list[attributes.private('color')]
+
+local remappers = {
+ [1] = formatters["s=%s"],
+ [3] = formatters["r=%s,g=%s,b=%s"],
+ [4] = formatters["c=%s,m=%s,y=%s,k=%s"],
+}
+
+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
+ end
+ local cs = object.color
+ if cs and #cs > 0 then
+ local c_b, c_a
+ local sp_type = prescript.sp_type
+ if not sp_type then
+ c_b, c_a = colorconverter(cs)
+ 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)
+ sp_type = "named"
+ elseif sp_type == "multitone" then
+ local sp_value = prescript.sp_value or "s:1"
+ local sp_spec = { }
+ 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)
+ end
+ sp_spec = concat(sp_spec,",")
+ definemultitonecolor(sp_name,sp_spec,"","",true)
+ sp_type = "named"
+ end
+ if sp_type == "named" then
+ -- we might move this to another namespace .. also, named can be a spotcolor
+ -- so we need to check for that too ... also we need to resolve indirect
+ -- colors so we might need the second pass for this (draw dots with \MPcolor)
+ if not tr_alternative then
+ -- todo: sp_name is not yet registered at this time
+ local t = t_list[sp_name] -- string or attribute
+ local v = t and 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
+ end
+ end
+ local c = c_list[sp_name] -- string or attribute
+ local v = c and colorvalue(c)
+ if v then
+ -- all=1 gray=2 rgb=3 cmyk=4
+ local colorspace = v[1]
+ local f = cs[1]
+ if colorspace == 2 then
+ local s = f*v[2]
+ c_b, c_a = checked_color_pair(f_gray,s,s)
+ elseif colorspace == 3 then
+ local r, g, b = f*v[3], f*v[4], f*v[5]
+ c_b, c_a = checked_color_pair(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]
+ 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
+ for i=1,#value do
+ value[i] = f * (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]
+ c_b, c_a = checked_color_pair(f_gray,s,s)
+ end
+ end
+ end
+ end
+ if c_a and c_b then
+ before[#before+1] = c_b
+ after [#after +1] = c_a
+ end
+ end
+end
+
+-- layers (nasty: we need to keep the 'grouping' right
+
+local function la_process(object,prescript,before,after)
+ local la_name = prescript.la_name
+ if la_name then
+ before[#before+1] = backends.codeinjections.startlayer(la_name)
+ insert(after,1,backends.codeinjections.stoplayer())
+ end
+end
+
+-- groups
+
+local types = {
+ isolated
+}
+
+local function gr_process(object,prescript,before,after)
+ local gr_state = prescript.gr_state
+ if gr_state then
+ if gr_state == "start" then
+ local gr_type = utilities.parsers.settings_to_hash(prescript.gr_type)
+ before[#before+1] = function()
+ context.MPLIBstartgroup(
+ gr_type.isolated and 1 or 0,
+ gr_type.knockout and 1 or 0,
+ prescript.gr_llx,
+ prescript.gr_lly,
+ prescript.gr_urx,
+ prescript.gr_ury
+ )
+ end
+ elseif gr_state == "stop" then
+ after[#after+1] = function()
+ context.MPLIBstopgroup()
+ end
+ end
+ object.path = false
+ object.color = false
+ object.grouped = true
+ end
+end
+
+-- outlines
+
+local outlinetexts = { }
+
+local function ot_reset()
+ outlinetexts = { }
+end
+
+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)
+ end
+end
+
+local function ot_process(object,prescript,before,after)
+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
+}
+
+function mp.get_outline_text(index) -- maybe we need a more private namespace
+ mp.print(outlinetexts[index] or "draw origin;")
+end
+
+
+-- definitions
+
+appendaction(resetteractions, "system",ot_reset)
+appendaction(resetteractions, "system",cl_reset)
+appendaction(resetteractions, "system",tx_reset)
+
+appendaction(processoractions,"system",ot_process)
+appendaction(processoractions,"system",gr_process)
+
+appendaction(analyzeractions, "system",ot_analyze)
+appendaction(analyzeractions, "system",tx_analyze)
+appendaction(analyzeractions, "system",gt_analyze)
+
+appendaction(processoractions,"system",sh_process)
+-- (processoractions,"system",gt_process)
+appendaction(processoractions,"system",bm_process)
+appendaction(processoractions,"system",tx_process)
+appendaction(processoractions,"system",ps_process)
+appendaction(processoractions,"system",fg_process)
+appendaction(processoractions,"system",tr_process) -- last, as color can be reset
+
+appendaction(processoractions,"system",la_process)
+
+-- 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
+
+-- we're nice and set them already
+
+resetter = resetteractions .runner
+analyzer = analyzeractions .runner
+processor = processoractions.runner
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv
new file mode 100644
index 00000000000..cdccfc379a9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv
@@ -0,0 +1,154 @@
+%D \module
+%D [ file=mlib-pps,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\registerctxluafile{mlib-pps}{1.001}
+
+%D Todo: catch nested graphics like external figures with dummies.
+
+% todo: figure out why this is shifted
+%
+% \setupbodyfont[palatino]
+%
+% \starttext
+% \startMPpage
+% draw textext("123") ;
+% \stopMPpage
+% \stoptext
+%
+% A slightly larger picture works ok so maybe there is some kind
+% of interference with the page builder.
+
+\newbox \MPtextbox
+\newtoks\everyMPLIBsettext % not used
+
+\def\doMPLIBflushenvironment
+ {%\writestatus\m!metapost{flushing environment}%
+ \clf_mptexget
+ \let\MPLIBflushenvironment\relax}% MPenvironments are depricated}
+
+\let\MPLIBflushenvironment\doMPLIBflushenvironment
+
+\unexpanded\def\MPLIBsetNtext#1% #2% box text
+ {\MPLIBflushenvironment
+ \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text
+ \meta_set_current_color
+ \let\MPLIBflushenvironment\doMPLIBflushenvironment
+ \let\next} % gobble open brace
+
+\unexpanded\def\MPLIBsetCtext#1#2% #3% box colorspec text
+ {\MPLIBflushenvironment
+ \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text
+ \directcolored[#2]%
+ \meta_set_current_color % so, textcolor wins !
+ \let\MPLIBflushenvironment\doMPLIBflushenvironment
+ \let\next} % gobble open brace
+
+\let\MPLIBsettext\MPLIBsetNtext
+
+\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}}}
+
+% horrible (we could inline scale and matrix code):
+
+\unexpanded\def\MPLIBgettextscaledcm#1#2#3#4#5#6#7#8#9% 2-7: sx,rx,ry,sy,tx,ty
+ {\clf_mpgettext\MPtextbox #1%
+ \setbox\MPbox\hpack\bgroup
+ \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}% does push pop ... will be changed to proper lua call (avoid small numbers)
+ \vpack to \zeropoint\bgroup
+ \vss
+ \hpack to \zeropoint \bgroup
+ % \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}%
+ % \scale[\c!sx=#8,\c!sy=#9,\c!depth=\v!no]{\box\MPtextbox}%
+ \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}%
+ % This gives: LuaTeX warning: Misplaced \pdfrestore .. don't ask me why.
+ % but I'll retry it some day soon.
+ % \dostartscaling{#8}{#9}%
+ % \raise\dp\MPtextbox\box\MPtextbox
+ % \dostopscaling
+ \forcecolorhack % can go away ... already in the scale macro
+ \hss
+ \egroup
+ \egroup
+ \egroup
+ \smashbox\MPbox
+ \box\MPbox}
+
+\unexpanded\def\MPLIBgraphictext#1% use at mp end
+ {\startTEXpage[\c!scale=10000]#1\stopTEXpage}
+
+%D \startbuffer
+%D \definelayer[test]
+%D
+%D \setlayerframed
+%D [test]
+%D [x=\MPx{somepos-1},y=\MPy{somepos-1}]
+%D [width=\MPw{somepos-1},height=\MPh{somepos-1}]
+%D {Whatever we want here!}
+%D
+%D \setlayerframed
+%D [test]
+%D [x=\MPx{somepos-2},y=\MPy{somepos-2}]
+%D [width=\MPw{somepos-2},height=\MPh{somepos-2}]
+%D {Whatever we need there!}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 6cm withcolor red ;
+%D register ("somepos-1",5cm,1cm,center currentpicture) ;
+%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}}
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+\unexpanded\def\MPLIBpositionwhd#1#2#3#4#5% bp !
+ {\dosavepositionwhd{#1}\zerocount{#2\onebasepoint}{#3\onebasepoint}{#4\onebasepoint}{#5\onebasepoint}\zeropoint}
+
+% \def\MPLIBextrapass#1%
+% {\ctxlua{metapost.graphic_extra_pass("#1")}}
+
+%D Experiment
+
+\def\doMPLIBstopgroup#1#2#3#4#5#6% some day this might happen elsewhere
+ {\egroup
+ \setbox\scratchbox\hpack{\kern\onebasepoint\box\scratchbox}% weird correction
+ \wd\scratchbox \dimexpr#5\onebasepoint-#3\onebasepoint+2\onebasepoint\relax
+ \ht\scratchbox #6\onebasepoint
+ \dp\scratchbox-#4\onebasepoint
+ \saveboxresource
+ attr {/Group << /S /Transparency /I \ifnum#1=1 true \else false \fi /K \ifnum#1=1 true \else false \fi >>}
+ resources {\pdfbackendcurrentresources}
+ \scratchbox
+ % \setbox\scratchbox\hbox\bgroup\kern-\onebasepoint\useboxresource\lastsavedboxresourceindex\egroup % why twice?
+ \setbox\scratchbox\hpack\bgroup\kern-\onebasepoint\useboxresource\lastsavedboxresourceindex\egroup
+ \wd\scratchbox\zeropoint
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\MPLIBstartgroup#1#2#3#4#5#6% isolated 0/1, knockout 0/1 llx lly urx ury
+ {\begingroup
+ \setbox\scratchbox\hpack\bgroup
+ \unexpanded\def\MPLIBstopgroup{\doMPLIBstopgroup{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua
new file mode 100644
index 00000000000..8109cff2d21
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua
@@ -0,0 +1,617 @@
+if not modules then modules = { } end modules ['mlib-run'] = {
+ 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",
+}
+
+--~ cmyk -> done, native
+--~ spot -> done, but needs reworking (simpler)
+--~ multitone ->
+--~ shade -> partly done, todo: cm
+--~ figure -> done
+--~ hyperlink -> low priority, easy
+
+-- new * run
+-- or
+-- new * execute^1 * finish
+
+-- a*[b,c] == b + a * (c-b)
+
+--[[ldx--
+<p>The directional helpers and pen analysis are more or less translated from the
+<l n='c'/> code. It really helps that Taco know that source so well. Taco and I spent
+quite some time on speeding up the <l n='lua'/> and <l n='c'/> code. There is not
+much to gain, especially if one keeps in mind that when integrated in <l n='tex'/>
+only a part of the time is spent in <l n='metapost'/>. Of course an integrated
+approach is way faster than an external <l n='metapost'/> and processing time
+nears zero.</p>
+--ldx]]--
+
+local type, tostring, tonumber = type, tostring, tonumber
+local format, gsub, match, find = string.format, string.gsub, string.match, string.find
+local concat = table.concat
+local emptystring = string.is_empty
+local P = lpeg.P
+
+local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
+local trace_tracingall = false trackers.register("metapost.tracingall", function(v) trace_tracingall = v end)
+
+local report_metapost = logs.reporter("metapost")
+local texerrormessage = logs.texerrormessage
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local formatters = string.formatters
+
+local mplib = mplib
+metapost = metapost or { }
+local metapost = metapost
+
+metapost.showlog = false
+metapost.lastlog = ""
+metapost.collapse = true -- currently mplib cannot deal with begingroup/endgroup mismatch in stepwise processing
+metapost.texerrors = false
+metapost.exectime = metapost.exectime or { } -- hack
+
+-- metapost.collapse = false
+
+directives.register("mplib.texerrors", function(v) metapost.texerrors = v end)
+trackers.register ("metapost.showlog", function(v) metapost.showlog = v end)
+
+function metapost.resetlastlog()
+ metapost.lastlog = ""
+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)
+--
+-- for some reason mp sometimes calls this function twice which is inefficient
+-- but we cannot catch this
+
+do
+
+ local finders = { }
+ mplib.finders = finders -- also used in meta-lua.lua
+
+ local new_instance = mplib.new
+ local resolved_file = resolvers.findfile
+
+ 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
+ elseif ftype == 0 then
+ -- mplib bug
+ else
+ return ftype
+ end
+ end
+
+ finders.file = function(specification,name,mode,ftype)
+ return preprocessed(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
+
+ local function o_finder(name,mode,ftype)
+ return name
+ end
+
+ o_finder = sandbox.register(o_finder,sandbox.filehandlerone,"mplib output finder")
+
+ local function finder(name,mode,ftype)
+ return (mode == "w" and o_finder or i_finder)(name,mode,validftype(ftype))
+ end
+
+ function mplib.new(specification)
+ specification.find_file = finder -- so we block an overload
+ return new_instance(specification)
+ end
+
+ mplib.finder = finder
+
+end
+
+local new_instance = mplib.new
+local find_file = mplib.finder
+
+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
+ if t and t ~= "" then
+ (metapost.texerrors and texerrormessage or report_metapost)("terminal: %s",t)
+ end
+ if e == "" or e == "no-error" then
+ e = nil
+ end
+ if e then
+ (metapost.texerrors and texerrormessage or report_metapost)("error: %s",e)
+ end
+ if not t and not e and l then
+ metapost.lastlog = metapost.lastlog .. "\n" .. l
+ report_metapost("log: %s",l)
+ else
+ report_metapost("error: unknown, no error, terminal or log messages")
+ end
+ else
+ return false
+ end
+ return true
+end
+
+local f_preamble = formatters [ [[
+ boolean mplib ; mplib := true ;
+ let dump = endinput ;
+ input "%s" ;
+]] ]
+
+local methods = {
+ double = "double",
+ scaled = "scaled",
+ binary = "binary",
+ decimal = "decimal",
+ default = "scaled",
+}
+
+function metapost.runscript(code)
+ return code
+end
+
+function metapost.scripterror(str)
+ report_metapost("script error: %s",str)
+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
+
+function metapost.load(name,method)
+ starttiming(mplib)
+ method = method and methods[method] or "scaled"
+ local mpx = new_instance {
+ ini_version = true,
+ math_mode = method,
+ run_script = metapost.runscript,
+ script_error = metapost.scripterror,
+ make_text = metapost.maketext,
+ extensions = 1,
+ }
+ report_metapost("initializing number mode %a",method)
+ local result
+ if not mpx then
+ result = { status = 99, error = "out of memory"}
+ else
+ result = mpx:execute(f_preamble(file.addsuffix(name,"mp"))) -- addsuffix is redundant
+ end
+ stoptiming(mplib)
+ metapost.reporterror(result)
+ return mpx, result
+end
+
+function metapost.checkformat(mpsinput,method)
+ local mpsversion = environment.version or "unset version"
+ local mpsinput = mpsinput or "metafun"
+ local foundfile = ""
+ if file.suffix(mpsinput) ~= "" then
+ foundfile = find_file(mpsinput) or ""
+ end
+ if foundfile == "" then
+ foundfile = find_file(file.replacesuffix(mpsinput,"mpvi")) or ""
+ end
+ if foundfile == "" then
+ foundfile = find_file(file.replacesuffix(mpsinput,"mpiv")) or ""
+ end
+ if foundfile == "" then
+ foundfile = find_file(file.replacesuffix(mpsinput,"mp")) or ""
+ end
+ if foundfile == "" then
+ report_metapost("loading %a fails, format not found",mpsinput)
+ else
+ report_metapost("loading %a as %a using method %a",mpsinput,foundfile,method or "default")
+ local mpx, result = metapost.load(foundfile,method)
+ if mpx then
+ return mpx
+ else
+ report_metapost("error in loading %a",mpsinput)
+ metapost.reporterror(result)
+ end
+ end
+end
+
+function metapost.unload(mpx)
+ starttiming(mplib)
+ if mpx then
+ mpx:finish()
+ end
+ stoptiming(mplib)
+end
+
+local mpxformats = { }
+
+function metapost.format(instance,name,method)
+ if not instance or instance == "" then
+ instance = "metafun" -- brrr
+ 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
+ end
+ return mpx
+end
+
+function metapost.instance(instance)
+ return mpxformats[instance]
+end
+
+function metapost.reset(mpx)
+ if not mpx then
+ -- nothing
+ elseif type(mpx) == "string" then
+ if mpxformats[mpx] then
+ mpxformats[mpx]:finish()
+ mpxformats[mpx] = nil
+ end
+ else
+ for name, instance in next, mpxformats do
+ if instance == mpx then
+ mpx:finish()
+ mpxformats[name] = nil
+ break
+ end
+ end
+ end
+end
+
+local mp_tra = { }
+local mp_tag = 0
+
+-- key/values
+
+if not metapost.initializescriptrunner then
+ function metapost.initializescriptrunner() end
+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
+ end
+ if mpx and data then
+ local tra = nil
+ starttiming(metapost)
+ metapost.initializescriptrunner(mpx,trialrun)
+ if trace_graphics then
+ tra = mp_tra[mpx]
+ if not tra then
+ mp_tag = mp_tag + 1
+ local jobname = tex.jobname
+ tra = {
+ inp = io.open(formatters["%s-mplib-run-%03i.mp"] (jobname,mp_tag),"w"),
+ log = io.open(formatters["%s-mplib-run-%03i.log"](jobname,mp_tag),"w"),
+ }
+ 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))
+ 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
+ if type(data) == "table" then
+ if trace_tracingall then
+ mpx:execute("tracingall;")
+ end
+ -- table.insert(data,2,"")
+ for i=1,#data do
+ local d = data[i]
+ -- d = string.gsub(d,"\r","")
+ if d then
+ if trace_graphics then
+ tra.inp:write(formatters["\n%% begin snippet %s\n"](i))
+ tra.inp:write(d)
+ tra.inp:write(formatters["\n%% end snippet %s\n"](i))
+ end
+ starttiming(metapost.exectime)
+ result = mpx:execute(d) -- some day we wil use a coroutine with textexts
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ tra.log:write(str)
+ end
+ end
+ if not metapost.reporterror(result) then
+ if metapost.showlog then
+ local str = result.term ~= "" and result.term or "no terminal output"
+ if not emptystring(str) then
+ metapost.lastlog = metapost.lastlog .. "\n" .. str
+ report_metapost("log: %s",str)
+ end
+ end
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ end
+ end
+ else
+ report_metapost("error: invalid graphic component %s",i)
+ end
+ end
+ else
+ if trace_tracingall then
+ data = "tracingall;" .. data
+ end
+ if trace_graphics then
+ tra.inp:write(data)
+ end
+ starttiming(metapost.exectime)
+ result = mpx:execute(data)
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ tra.log:write(str)
+ end
+ end
+ -- todo: error message
+ if not result then
+ report_metapost("error: no result object returned")
+ elseif result.status > 0 then
+ report_metapost("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ report_metapost("info: %s",result.term or "no-term")
+ end
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ end
+ end
+ end
+ if trace_graphics then
+ local banner = "\n% end graphic\n\n"
+ tra.inp:write(banner)
+ tra.log:write(banner)
+ end
+ stoptiming(metapost)
+ end
+ return converted, result
+end
+
+function metapost.convert()
+ report_metapost('warning: no converter set')
+end
+
+-- handy
+
+function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
+ local fullname = file.addsuffix(filename,"mp")
+ local data = mpdata or io.loaddata(fullname)
+ if outputformat ~= "svg" then
+ outputformat = "mps"
+ end
+ if not data then
+ report_metapost("unknown file %a",filename)
+ else
+ local mpx = metapost.checkformat(formatname)
+ if not mpx then
+ report_metapost("unknown format %a",formatname)
+ else
+ report_metapost("processing %a",(mpdata and (filename or "data")) or fullname)
+ local result = mpx:execute(data)
+ if not result then
+ report_metapost("error: no result object returned")
+ elseif result.status > 0 then
+ report_metapost("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ report_metapost("info: %s",result.term or "no-term")
+ end
+ local figures = result.fig
+ if figures then
+ local sorted = table.sortedkeys(figures)
+ if astable then
+ local result = { }
+ report_metapost("storing %s figures in table",#sorted)
+ for k=1,#sorted do
+ local v = sorted[k]
+ if outputformat == "mps" then
+ result[v] = figures[v]:postscript()
+ else
+ result[v] = figures[v]:svg() -- (3) for prologues
+ end
+ end
+ return result
+ else
+ local basename = file.removesuffix(file.basename(filename))
+ for k=1,#sorted do
+ local v = sorted[k]
+ local output
+ if outputformat == "mps" then
+ output = figures[v]:postscript()
+ else
+ output = figures[v]:svg() -- (3) for prologues
+ end
+ local outname = formatters["%s-%s.%s"](basename,v,outputformat)
+ report_metapost("saving %s bytes in %a",#output,outname)
+ io.savedata(outname,output)
+ end
+ return #sorted
+ end
+ end
+ end
+ end
+ end
+end
+
+-- goodie
+
+function metapost.quickanddirty(mpxformat,data,plugmode)
+ if not data then
+ mpxformat = "metafun"
+ data = mpxformat
+ end
+ local code, bbox
+ local flusher = {
+ startfigure = function(n,llx,lly,urx,ury)
+ code = { }
+ bbox = { llx, lly, urx, ury }
+ end,
+ flushfigure = function(t)
+ for i=1,#t do
+ code[#code+1] = t[i]
+ end
+ end,
+ stopfigure = function()
+ end
+ }
+ local data = formatters["; beginfig(1) ;\n %s\n ; endfig ;"](data)
+ metapost.process(mpxformat, { data }, false, flusher, false, false, "all", plugmode)
+ if code then
+ return {
+ bbox = bbox or { 0, 0, 0, 0 },
+ code = code,
+ data = data,
+ }
+ else
+ report_metapost("invalid quick and dirty run")
+ end
+end
+
+function metapost.getstatistics(memonly)
+ if memonly then
+ local n, m = 0, 0
+ for name, mpx in next, mpxformats do
+ n = n + 1
+ m = m + mpx:statistics().memory
+ end
+ return n, m
+ else
+ local t = { }
+ for name, mpx in next, mpxformats do
+ t[name] = mpx:statistics()
+ end
+ return t
+ end
+end
+
+do
+
+ local result = { }
+ local width = 0
+ local height = 0
+ local depth = 0
+ local mpx = false
+
+ local flusher = {
+ startfigure = function(n,llx,lly,urx,ury)
+ result = { }
+ width = urx - llx
+ height = ury
+ depth = -lly
+ end,
+ flushfigure = function(t)
+ for i=1,#t do
+ result[#result+1] = t[i]
+ end
+ end,
+ stopfigure = function()
+ end
+ }
+
+ function metapost.simple(format,code) -- even less than metapost.quickcanddirty
+ local mpx = metapost.format(format or "metafun","metafun")
+ -- metapost.setoutercolor(2)
+ metapost.process(mpx,
+ { "beginfig(1);", code, "endfig;" },
+ false, flusher, false, false, 1, true -- last true is plugmode !
+ )
+ if result then
+ local stream = concat(result," ")
+ result = nil -- cleanup
+ return stream, width, height, depth
+ else
+ return "", 0, 0, 0
+ end
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-arrange.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-arrange.tex
new file mode 100644
index 00000000000..a3e6e9db3d1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-arrange.tex
@@ -0,0 +1,123 @@
+%D \module
+%D [ file=mtx-context-arrange,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Arrange Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=arrange [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --noduplex : singlesided (doublesided is default)
+% --backspace=dimension : extra left offset
+% --topspace=dimension : extra top offset
+% --marking : add cutmarks
+% --addempty=list : add empty pages at/after (comma separated list)
+% --printformat : 2UP, etc
+% --paperformat=spec : paper*print or paperxprint
+%
+% example: context --extra=arrange --printformat=2UP --paperformat=A4*A3,landscape myfile
+%
+% end help
+
+\input mtx-context-common.tex
+
+\doifdocumentargument {paperoffset} {
+ \definepapersize
+ [offset=\getdocumentargument{paperoffset}]
+}
+
+\doifdocumentargumentelse {noduplex} {
+ \setuppagenumbering
+ [alternative=doublesided]
+ \setdocumentargument{sided}{doublesided}
+} {
+ \setdocumentargument{sided}{singlesided}
+}
+
+
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+% todo: autopapersize
+%
+% \setuppapersize
+% [A4]
+% [A3,landscape]
+
+\setdocumentargumentdefault {textwidth} {0cm}
+\setdocumentargumentdefault {backspace} {0cm}
+\setdocumentargumentdefault {topspace} {0cm}
+
+\setuplayout
+ [backspace=\getdocumentargument{backspace},
+ topspace=\getdocumentargument{topspace},
+ width=middle,
+ height=middle,
+ location=middle,
+ header=0pt,
+ footer=0pt]
+
+\doifdocumentargument {marking} {yes} {
+ \setuplayout
+ [marking=on]
+}
+
+\startluacode
+ local printformat = document.arguments.printformat or ""
+ if printformat == "" then
+ printformat = "normal"
+ elseif string.find(printformat,".*up") then
+ printformat = "2UP,\\v!rotated"
+ elseif string.find(printformat,".*down") then
+ printformat = "2DOWN,\\v!rotated"
+ elseif string.find(printformat,".*side") then
+ printformat = "2SIDE,\\v!rotated"
+ end
+ document.setargument("printformat",printformat)
+\stopluacode
+
+\setuparranging
+ [\getdocumentargument{sided},
+ \getdocumentargument{printformat}]
+
+\starttext
+
+\startluacode
+ local arguments = document.arguments
+ local files = document.files
+ local noffiles = #files
+ if noffiles > 0 then
+ if arguments.sort then
+ table.sort(files)
+ end
+ local emptypages = arguments.addempty or ""
+ local textwidth = arguments.textwidth or "0cm"
+ for i=1,noffiles do
+ local filename = files[i]
+ if not string.find(filename,"^mtx%-context%-") then
+ context.insertpages (
+ { filename },
+ { emptypages },
+ { width = textwidth }
+ )
+ end
+ end
+ else
+ context("no files given")
+ end
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-combine.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-combine.tex
new file mode 100644
index 00000000000..05e31d80087
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-combine.tex
@@ -0,0 +1,116 @@
+%D \module
+%D [ file=mtx-context-combine,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Combine Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=combine [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --nobanner : no footer etc
+% --combination : h*v or hxv
+% --paperformat=spec : paper*print or paperxprint
+% --nobanner : no footerlines
+% --bannerheight=dimension : height of banner
+% --bannerstring=dimension : height of bannerstring
+%
+% end help
+
+\input mtx-context-common.tex
+
+\doifdocumentargumentelse {paperoffset} {
+
+ \setuplayout
+ [topspace=\getdocumentargument{paperoffset},
+ backspace=\getdocumentargument{paperoffset}]
+
+} {
+
+ \setuplayout
+ [topspace=0pt,
+ backspace=0pt]
+
+}
+
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+\setuplayout
+ [header=0pt,
+ footer=0pt,
+ width=middle,
+ height=middle]
+
+\doifnotdocumentargument {bannerheight} {
+ \setuplayout
+ [footer=1cm]
+}
+
+\doifelse {\getdocumentargument{nobanner}} {yes} {
+ \setuplayout
+ [footer=0cm]
+ \setupbackgrounds
+ [page]
+ [background=]
+} {
+ \definelayer
+ [page]
+ [width=\paperwidth,
+ height=\paperheight]
+
+ \setupbackgrounds
+ [page]
+ [background=page]
+}
+
+\setupexternalfigures
+ [directory=]
+
+\starttext
+
+\startluacode
+ local format = string.format
+
+ if #document.files > 0 then
+ if document.arguments["sort"] then
+ table.sort(document.files)
+ end
+ local dobanner = not document.arguments["nobanner"]
+ local bannerheight = document.arguments["bannerheight"]
+ local nx = document.arguments.combination_nx or 2
+ local ny = document.arguments.combination_ny or 2
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ -- could be a macro
+ local bannerstring = format("\\tttf\\detokenize{%s}\\quad\\quad\\currentdate\\quad\\quad\\pagenumber",file.basename(filename))
+ if dobanner then
+ if bannerheight then
+ context("\\setuptexttexts[{\\setlayerframed[page][preset=middlebottom][frame=off,height=%s]{%s}}]",bannerheight,bannerstring)
+ else
+ context("\\setupfootertexts[{%s}]",bannerstring)
+ end
+ end
+ context("\\combinepages[%s][nx=%s,ny=%s]",filename,nx,ny)
+ context("\\page")
+ end
+ end
+ else
+ context("no files given")
+ end
+\stopluacode
+
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-common.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-common.tex
new file mode 100644
index 00000000000..2db0a5be2ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-common.tex
@@ -0,0 +1,43 @@
+%D \module
+%D [ file=mtx-context-common,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Common Stuff,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startluacode
+ local combination = document.arguments['combination'] or '2*2'
+ local nx, ny = string.match(combination,"^(%d+)%s*[%*x]%s*(%d+)$")
+ if not nx then
+ nx, ny = 2, 2
+ elseif not ny then
+ nx = tonumber(combination) or 2
+ ny = nx
+ else
+ nx = tonumber(nx) or 2
+ ny = tonumber(ny) or nx or 2
+ end
+ document.setargument("combination_nx",nx)
+ document.setargument("combination_ny",ny)
+\stopluacode
+
+\startluacode
+ local paperformat = document.arguments['paperformat'] or 'A4*A4'
+ -- paperformat = string.upper(paperformat) -- no, as we don't want to uppercase 'landscape'
+ local f, t = string.match(paperformat,"^(.-)%s*[%*xX]%s*(.-)$")
+ if not f then
+ f, t = "A4", "A4"
+ elseif not t then
+ t = f
+ end
+ document.setargument("paperformat_paper",f)
+ document.setargument("paperformat_print",t)
+\stopluacode
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-copy.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-copy.tex
new file mode 100644
index 00000000000..b798b3f8d16
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-copy.tex
@@ -0,0 +1,151 @@
+% engine=luatex
+
+%D \module
+%D [ file=mtx-context-copy,
+%D version=2008.11.10, % about that time i started playing with this
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Copying Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=copy [options] list-of-files
+%
+% --interaction : add hyperlinks
+%
+% end help
+
+\input mtx-context-common.tex
+
+\doif {\getdocumentargument{interaction}} {yes} {
+ \setupinteraction
+ [state=start]
+ \setupexternalfigures
+ [interaction=yes]
+}
+
+\setupexternalfigures
+ [directory=]
+
+\definepapersize
+ [fit]
+ [width=\figurewidth,
+ height=\figureheight]
+
+\setuplayout
+ [page]
+
+% this will be an option to \copypages
+
+\unexpanded\def\CopyPages[#1]%
+ {\dorecurse
+ {\noffigurepages}
+ {\startTEXpage
+ \externalfigure[#1][page=\recurselevel]%
+ \stopTEXpage}}
+
+\starttext
+
+\startluacode
+
+ if #document.files == 0 then
+ context("no files given")
+ else
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ logs.report("copy",filename)
+ context.getfiguredimensions
+ { filename }
+ context.setuppapersize
+ { "fit" }
+ context.CopyPages
+ { filename }
+ end
+ end
+ end
+
+\stopluacode
+
+\stoptext
+
+
+% def copyoutput
+% copyortrim(false,'copy')
+% end
+
+% def trimoutput
+% copyortrim(true,'trim')
+% end
+
+% def copyortrim(trim=false,what='unknown')
+% if job = TEX.new(logger) then
+% prepare(job)
+% job.cleanuptemprunfiles
+% files = if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+% if files.length > 0 then
+% if f = File.open(job.tempfilename('tex'),'w') then
+% scale = @commandline.checkedoption('scale')
+% begin
+% scale = (scale.to_f * 1000.0).to_i if scale.to_i < 10
+% rescue
+% scale = 1000
+% end
+% scale = scale.to_i
+% paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+% f << "\\starttext\n"
+% files.each do |filename|
+% result = @commandline.checkedoption('result','texexec')
+% begin
+% if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
+% report("copying file: #{filename}")
+% f << "\\getfiguredimensions\n"
+% f << " [#{filename}]\n"
+% f << " [scale=#{scale},\n"
+% f << " page=1,\n"
+% f << " size=trimbox\n" if trim
+% f << "]\n"
+% f << "\\definepapersize\n"
+% f << " [copy]\n"
+% f << " [width=\\figurewidth,\n"
+% f << " height=\\figureheight]\n"
+% f << "\\setuppapersize\n"
+% f << " [copy][copy]\n"
+% f << "\\setuplayout\n"
+% f << " [page]\n"
+% f << "\\setupexternalfigures\n"
+% f << " [directory=]\n"
+% f << "\\copypages\n"
+% f << " [#{filename}]\n"
+% f << " [scale=#{scale},\n"
+% f << " marking=on,\n" if @commandline.option('markings')
+% f << " size=trimbox,\n" if trim
+% f << " offset=#{paperoffset}]\n"
+% end
+% rescue
+% report("wrong specification")
+% end
+% end
+% f << "\\stoptext\n"
+% f.close
+% job.setvariable('interface','english')
+% job.setvariable('simplerun',true)
+% # job.setvariable('nooptionfile',true)
+% job.setvariable('files',[job.tempfilename])
+% job.processtex
+% else
+% report("no files to #{what}")
+% end
+% else
+% report("no files to #{what}")
+% end
+% job.cleanuptemprunfiles
+% end
+% end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-ideas.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-ideas.tex
new file mode 100644
index 00000000000..d10eefc7684
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-ideas.tex
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=mtx-context-ideas,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Placeholder File,
+%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.
+
+% The hard coded goodies in texexec are now external. We also use this
+% opportunity to explore mixed tex/lua user interfacing so you will see
+% some old and new tricks here that might disappear or become extended.
+%
+% if users want to add their own ... go ahead but use a different
+% namespace:
+%
+% mtx-context-third-somename.tex
+% mtx-context-user-somename.tex
+
+% \startluacode
+% -- some day we might move the whole ui to lua
+% context = context or { }
+% function interfaces.tosetups(setups)
+% if not setups then
+% return ""
+% elseif type(setups) == "table" then
+% local t = { }
+% for k,v in next, setups do
+% t[k] = "{" .. v .. "}"
+% end
+% return table.concat(t,",")
+% else
+% return setups
+% end
+% end
+% function context.setuplayout(category,setups)
+% setups = setups or category
+% tex.sprint(string.format("\\setuplayout[%s]",interfaces.tosetups(setups))
+% end
+% local topspace = document.arguments["topspace"] or 0
+% if dimen(topspace) > dimen(0) then
+% context.setuplayout { topspace = dimen(topspace) }
+% end
+% local backspace = document.arguments["backspace"] or 0
+% if dimen(topspace) > dimen(0) then
+% context.setuplayout { backspace = dimen(backspace) }
+% end
+% \stopluacode
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex
new file mode 100644
index 00000000000..2deffd7958e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex
@@ -0,0 +1,138 @@
+%D \module
+%D [ file=mtx-context-listing,
+%D version=2008.11.10, % about that time i started playing with this
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Listing Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=listing [options] list-of-files
+%
+% --sort : sort filenames first
+% --topspace=dimension : distance above first line
+% --backspace=dimension : distance before left margin
+% --pretty : pretty print comform suffix
+% --scite : pretty print comform suffix using scite lexer
+% --bodyfont=list : additional bodyfont settings
+% --paperformat=spec : paper*print or paperxprint
+% --compact : small margins, 8pt font
+% --verycompact : small margins, 7pt font
+%
+% end help
+
+\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,11pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete
+
+\setuptyping
+ [lines=yes]
+
+\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}]
+
+% \startluacode
+% -- syntax check
+% local topspace = dimen(document.arguments.topspace or 0)
+% local backspace = dimen(document.arguments.backspace or 0)
+% local zeropoint = dimen(0)
+% if topspace > zeropoint then
+% context.setuplayout { topspace = tostring(topspace) }
+% end
+% if backspace > zeropoint then
+% context.setuplayout { backspace = tostring(backspace) }
+% end
+% \stopluacode
+
+\starttext
+
+\startluacode
+ local types = {
+ mkiv = "tex",
+ mkii = "tex",
+ cld = "lua",
+ lfg = "lua",
+ }
+
+ local pattern = document.arguments.pattern
+ local scite = document.arguments.scite
+
+ if pattern then
+ document.files = dir.glob(pattern)
+ end
+
+ if scite then
+ context.usemodule { "scite" }
+ end
+
+ if #document.files > 0 then
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ for i=1,#document.files do
+ local filename = document.files[i]
+ if not string.find(filename,"^mtx%-context%-") then
+ local pretty = document.arguments.pretty
+ if pretty == true then
+ pretty = file.extname(filename) or ""
+ elseif pretty == false then
+ pretty = ""
+ else
+ -- forced
+ end
+ context.page()
+ context.setupfootertexts( -- return true: we need to keep this entry
+ { function() context.detokenize(pattern and filename or file.basename(filename)) return true end },
+ { function() context.pagenumber() return true end }
+ )
+ if scite then
+ context.scitefile { filename } -- here { }
+ elseif pretty then
+ if type(pretty) ~= "string" or pretty == "" then
+ context.setuptyping { option = "color" }
+ else
+ context.setuptyping { option = types[pretty] or pretty }
+ end
+ context.typefile(filename)
+ else
+ context.typefile(filename)
+ end
+ end
+ end
+ else
+ context("no files given")
+ end
+
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-markdown.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-markdown.tex
new file mode 100644
index 00000000000..1bd57945f21
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-markdown.tex
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=mtx-context-markdown,
+%D version=2011.07.24,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Rendering Markdown Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=markdown [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --duplex : doublesided (singlesided is default)
+% --backspace=dimension : extra left offset
+% --topspace=dimension : extra top offset
+% --bodyfont=specification : additional bodyfont specification
+% --contents : add table of contents
+%
+% end help
+
+\usemodule[markdown]
+
+\doifdocumentargument {paperoffset} {
+ \definepapersize
+ [offset=\getdocumentargument{paperoffset}]
+}
+
+\doifdocumentargument{duplex} {
+ \setuppagenumbering
+ [alternative=doublesided]
+} {
+ \setuppagenumbering
+ [alternative=singlesided]
+}
+
+\setdocumentargumentdefault {textwidth} {middle}
+\setdocumentargumentdefault {backspace} {2cm}
+\setdocumentargumentdefault {topspace} {2cm}
+\setdocumentargumentdefault {bodyfont} {}
+
+\setuptolerance
+ [verytolerant,stretch]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ backspace=\getdocumentargument{backspace},
+ topspace=\getdocumentargument{topspace},
+ footer=0pt]
+
+\setupbodyfont
+ [dejavu,10pt,\getdocumentargument{bodyfont}]
+
+\setupwhitespace
+ [big]
+
+% \enabletrackers[context.trace]
+
+\setuplist
+ [chapter,section,subsection]
+ [aligntitle=yes,
+ width=4em]
+
+\starttext
+
+\doifdocumentargument{contents} {
+ \starttitle[title={Table of contents}]
+ \placelist[chapter,section,subsection] % todo: levels
+ \stoptitle
+}
+
+
+\startluacode
+ if #document.files > 0 then
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ for i=1,#document.files do
+ context.processmarkdownfile(document.files[i])
+ context.page()
+ end
+ end
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-precache.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-precache.tex
new file mode 100644
index 00000000000..9cbb46cf2c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-precache.tex
@@ -0,0 +1,161 @@
+%D \module
+%D [ file=mtx-context-precache,
+%D version=2014.12.24,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Precaching Fonts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=precache [no options yet]
+%
+% example: context --extra=precache
+%
+% end help
+
+\startluacode
+
+local lower = string.lower
+local filesuffix = file.suffix
+local findfile = resolvers.find_file
+
+local report = logs.reporter("fonts","precache")
+
+function fonts.names.precache()
+ local handlers = fonts.handlers
+ if not handlers then
+ report("no handlers available")
+ return
+ end
+ local otfloader = handlers.otf and handlers.otf.load
+ local afmloader = handlers.afm and handlers.afm.load
+ if not (otfloader or afmloader) then
+ report("no otf or afm handler available")
+ return
+ end
+ fonts.names.load()
+ local data = fonts.names.data
+ if not data then
+ report("no font data available")
+ return
+ end
+ local specifications = data.specifications
+ if not specifications then
+ report("no font specifications available")
+ return
+ end
+ local n = 0
+ for i=1,#specifications do
+ local specification = specifications[i]
+ local filename = specification.filename
+ local cleanfilename = specification.cleanfilename
+ local foundfile = findfile(filename)
+ if foundfile and foundfile ~= "" then
+ local suffix = lower(filesuffix(foundfile))
+ if suffix == "otf" or suffix == "ttf" then
+ if otfloader then
+ report("caching otf file: %s",foundfile)
+ otfloader(foundfile) -- todo: ttc/sub
+ n = n + 1
+ end
+ elseif suffix == "afm" then
+ if afmloader then
+ report("caching afm file: %s",foundfile)
+ afmloader(foundfile)
+ n = n + 1
+ end
+ end
+ end
+ end
+ report("%s files out of %s cached",n,#specifications)
+end
+
+\stopluacode
+
+\starttext
+
+\setuppapersize
+ [A4,landscape]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ footer=0pt,
+ header=1cm,
+ headerdistance=0cm,
+ backspace=5mm,
+ topspace=5mm]
+
+\setupbodyfont
+ [dejavu,6pt,tt]
+
+\startmode[*first]
+ \startluacode
+ fonts.names.precache()
+ \stopluacode
+\stopmode
+
+\startluacode
+ fonts.names.load()
+
+ local specifications = fonts.names.data.specifications
+
+ local sorted = { }
+ local hashed = { }
+
+ for i=1,#specifications do
+ local filename = specifications[i].cleanfilename
+ sorted[i] = filename
+ hashed[filename] = i
+ end
+
+ table.sort(sorted)
+
+ local context = context
+ local basename = file.basename
+
+ local NC = context.NC
+ local NR = context.NR
+ local HL = context.HL
+ local bold = context.bold
+
+ context.starttabulate { "||||||||||" }
+ HL()
+ NC() bold("format")
+ NC() bold("cleanfilename")
+ NC() bold("filename")
+ -- NC() bold("familyname")
+ -- NC() bold("fontname")
+ NC() bold("fullname")
+ NC() bold("rawname")
+ NC() bold("style")
+ NC() bold("variant")
+ NC() bold("weight")
+ NC() bold("width")
+ NC() NR()
+ HL()
+ for i=1,#sorted do
+ local specification = specifications[hashed[sorted[i]]]
+ NC() context(specification.format)
+ NC() context(specification.cleanfilename)
+ NC() context(basename(specification.filename))
+ -- NC() context(specification.familyname)
+ -- NC() context(specification.fontname)
+ NC() context(specification.fullname)
+ NC() context(specification.rawname)
+ NC() context(specification.style)
+ NC() context(specification.variant)
+ NC() context(specification.weight)
+ NC() context(specification.width)
+ NC() NR()
+ end
+ context.stoptabulate()
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-select.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-select.tex
new file mode 100644
index 00000000000..2f63f595513
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-select.tex
@@ -0,0 +1,110 @@
+% engine=luatex
+
+%D \module
+%D [ file=mtx-context-select,
+%D version=2008.11.10, % about that time i started playing with this
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Selecting Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=select [options] list-of-files
+%
+% --sort : sort filenames first
+% --topspace=dimension : distance above first line
+% --backspace=dimension : distance before left margin
+% --selection=list : n:m,p:q,...
+% --paperformat=spec : paper*print or paperxprint or 'fit'
+% --interaction : add hyperlinks
+%
+% end help
+
+\input mtx-context-common.tex
+
+\setuppapersize
+ [\getdocumentargumentdefault{paperformat_from}{A4}]
+ [\getdocumentargumentdefault{paperformat_to}{A4}]
+
+\setuppaper
+ [offset=\getdocumentargumentdefault{paperformat_to}{0pt}]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ topspace=\getdocumentargumentdefault{topspace}{0pt},
+ backspace=\getdocumentargumentdefault{backspace}{0pt},
+ location=middle,
+ header=0pt,
+ footer=0pt]
+
+\doif {\getdocumentargument{marking}} {yes} {
+ \setuplayout
+ [marking=on]
+}
+
+\doif {\getdocumentargument{interaction}} {yes} {
+ \setupinteraction
+ [state=start]
+ \setupexternalfigures
+ [interaction=yes]
+}
+
+\setupexternalfigures
+ [directory=]
+
+\doifelse {\getdocumentargument{paperformat_paper}} {fit} {
+ \doifdocumentfilename {1} {
+ \getfiguredimensions
+ [\getdocumentfilename{1}]
+ \definepapersize
+ [fit]
+ [width=\figurewidth,
+ height=\figureheight]
+ \setuppapersize
+ [fit]
+ [fit]
+ }
+}
+
+\starttext
+
+\startluacode
+
+ local papersize = document.arguments.paperformat_paper or "A4"
+ local printsize = document.arguments.paperformat_print or "A4"
+ local selection = document.arguments.selection or ""
+ local textwidth = document.arguments.textwidth or "0cm" -- needed ?
+
+ if #document.files == 0 then
+ context("no files given")
+ elseif selection == "" then
+ context("no selection given")
+ else
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ logs.report("select",filename)
+ context.filterpages (
+ { filename },
+ { selection },
+ { width = textwidth }
+ )
+ end
+ end
+ end
+
+\stopluacode
+
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-setups.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-setups.tex
new file mode 100644
index 00000000000..be99211ba1b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-setups.tex
@@ -0,0 +1,78 @@
+%D \module
+%D [ file=mtx-context-setups,
+%D version=2016.04.05,
+%D title=\CONTEXT\ Command Overvews,
+%D subtitle=Combine Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=setups [options] [categories]
+%
+% --interface : user interface (en, nl, etc)
+% --overview [--save] : use collection of files
+% --list : show know collections
+%
+% end help
+
+\input mtx-context-common.tex
+
+\starttext
+
+\startluacode
+ local report_setups = logs.reporter("setups")
+
+ context.starttext()
+
+ if document.arguments.list then
+ local okay = resolvers.findfile("context.mkiv") or "" -- will become an i file
+ if okay ~= "" then
+ okay = file.collapsepath(okay,true)
+ okay = string.gsub(okay,"/base/","/interface/")
+ okay = string.gsub(okay,"/sources/","/interface/")
+ local path = file.pathpart(okay)
+ local pattern = file.join(path,"i-*.xml")
+ local files = dir.glob(pattern)
+ local valid = { }
+ table.sort(files)
+ for i=1,#files do
+ local name = file.nameonly(files[i])
+ local base = string.match(name,"^i%-([a-z]+)$")
+ if base then
+ valid[#valid+1] = base
+ end
+ end
+ if #valid > 0 then
+ report_setups("% t",valid)
+ end
+ context.bold("available setup groups: ")
+ context("%, t.",valid)
+ end
+ elseif document.arguments.overview then
+ if document.arguments.save then
+ context.enablemode { "setups:save" }
+ end
+ context.input("x-setups-overview.mkiv")
+ elseif #document.files > 0 then
+ context.usemodule { "x-setups-basics" }
+ for i=1,#document.files do
+ local filename = "i-" .. document.files[i]
+ report_setups("processing %a",filename)
+ context.loadsetups { filename }
+ end
+ context.input("x-setups-proofing.mkiv")
+ else
+ context("no setups")
+ end
+
+ context.stoptext()
+\stopluacode
+
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-sql.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-sql.tex
new file mode 100644
index 00000000000..16613c2453a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-sql.tex
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=mtx-context-sql-tables,
+%D version=2012.10.19,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=SQL Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=sql --tables [options]
+%
+% --host : hostname (default: localhost)
+% --username : username (default: root)
+% --password : password
+% --database : database of which we want tables
+%
+% example: context --extra=sql --tables --host=localhost --username=root --password=*** --database=test
+%
+% end help
+
+\usemodule
+ [art-01,sql-tables]
+
+\setupbodyfont
+ [10pt]
+
+\setupheader
+ [state=high]
+
+\setuptabulate
+ [before={\blank[big,samepage]}]
+
+\starttext
+
+\startluacode
+
+ require("s-sql-tables")
+
+ local arguments = environment.arguments
+
+ local presets = arguments.presets
+ local preloaded = presets and table.load(presets) or { }
+
+ local presets = {
+ host = preloaded.host or arguments.host or "localhost",
+ username = preloaded.username or arguments.username or "root",
+ password = preloaded.password or arguments.password or "",
+ database = preloaded.database or arguments.database or "",
+ }
+
+
+ if arguments.tables then
+ moduledata.sql.tables.showdefined(presets)
+ end
+
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-timing.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-timing.tex
new file mode 100644
index 00000000000..c545c768f97
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-timing.tex
@@ -0,0 +1,48 @@
+%D \module
+%D [ file=mtx-context-timing,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Timing Runs,
+%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=timing filename
+%
+% end help
+
+\enablemode[no-timing] \usemodule[timing]
+
+\setuplayout
+ [topspace=1cm,
+ bottomspace=.5cm,
+ header=0pt,
+ width=middle,
+ height=middle,
+ style=\tt]
+
+\setupfootertexts
+ [\getdocumentfilename{1}-luatex-progress.lut \emdash\ \pagenumber]
+
+\setupcolors
+ [state=start]
+
+\starttext
+
+
+ \doifsomethingelse {\getdocumentfilename{1}} {
+ \writestatus{system}{processing timings of \getdocumentfilename{1}}
+ \LoadUsage{\getdocumentfilename{1}-luatex-progress}
+ \ShowUsage{\getdocumentfilename{1}-luatex-progress}
+ } {
+ \writestatus{system}{no filename given for timings}
+ }
+
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-trim.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-trim.tex
new file mode 100644
index 00000000000..46d0c31886b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-trim.tex
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=mtx-context-trim,
+%D version=2016.03.04,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Trimming Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a very old module based feature that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=trim [options] filename
+%
+% --paperwidth : target paperwidth
+% --paperheight : target paperheight
+% --file : processed file
+% --x : page x offset
+% --y : page y offset
+% --hoffset : horizontal clip offset
+% --voffset : vertical clip offset
+% --width : clip width
+% --height : clip height
+%
+% example: context --extra=trim --file=trimtest --hoffset=3.50cm --voffset=3.50cm --width=15cm --height=21cm
+%
+% end help
+
+\input mtx-context-common.tex
+
+\setdocumentargumentdefault {paperwidth} {21cm}
+\setdocumentargumentdefault {paperheight} {29.7cm}
+\setdocumentargumentdefault {file} {\getdocumentfilename{1}}
+\setdocumentargumentdefault {hoffset} {0cm}
+\setdocumentargumentdefault {voffset} {0cm}
+\setdocumentargumentdefault {width} {17cm}
+\setdocumentargumentdefault {height} {24cm}
+\setdocumentargumentdefault {x} {0cm}
+\setdocumentargumentdefault {y} {0cm}
+
+\doifnothing{\getdocumentargument{file}} {\starttext missing filename \stoptext}
+\doif {\getdocumentargument{file}}{\inputfilename.tex}{\starttext missing filename \stoptext}
+
+\definepapersize
+ [fuzzy]
+ [width=\getdocumentargument{paperwidth},
+ height=\getdocumentargument{paperheight}]
+
+\setuppapersize
+ [fuzzy]
+ [fuzzy]
+
+\setuplayout
+ [page]
+
+\starttext
+
+ \trimpages
+ [file=\getdocumentargument{file},
+ hoffset=\getdocumentargument{hoffset},
+ voffset=\getdocumentargument{voffset},
+ width=\getdocumentargument{width},
+ height=\getdocumentargument{height},
+ x=\getdocumentargument{x},
+ y=\getdocumentargument{y}]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex
new file mode 100644
index 00000000000..eeaca321340
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex
@@ -0,0 +1,76 @@
+%D \module
+%D [ file=mtx-context-xml,
+%D version=2013.05.30,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Analyzing XML files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% This module replaces mkii analyzers.
+
+% begin help
+%
+% usage: context --extra=xml [options] list-of-files
+%
+% --analyze : show elements and characters
+% --topspace=dimension : distance above first line
+% --backspace=dimension : distance before left margin
+% --bodyfont=list : additional bodyfont settings
+% --paperformat=spec : paper*print or paperxprint
+%
+% end help
+
+\input mtx-context-common.tex
+
+\setupbodyfont
+ [dejavu,11pt,tt,\getdocumentargument{bodyfont}]
+
+\setuptyping
+ [lines=yes]
+
+\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}]
+
+\usemodule[xml-analyzers]
+
+\starttext
+
+\startluacode
+ local pattern = document.arguments.pattern
+ local files = document.files
+
+ if pattern then
+ files = dir.glob(pattern)
+ context.setupfootertexts( { pattern }, { "pagenumber" })
+ else
+ context.setupfootertexts( { table.concat(files," ") }, { "pagenumber" })
+ end
+
+ if #files > 0 then
+ if document.arguments.analyze then
+ moduledata.xml.analyzers.structure (files)
+ context.page()
+ moduledata.xml.analyzers.characters(files)
+ else
+ context("no action given")
+ end
+ else
+ context("no files given")
+ end
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.lua
new file mode 100644
index 00000000000..353b5e69c3a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.lua
@@ -0,0 +1,168 @@
+if not modules then modules = { } end modules ['mult-aux'] = {
+ version = 1.001,
+ comment = "companion to mult-aux.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find = string.find
+
+interfaces.namespaces = interfaces.namespaces or { }
+local namespaces = interfaces.namespaces
+local variables = interfaces.variables
+
+local context = context
+
+local trace_namespaces = false trackers.register("interfaces.namespaces", function(v) trace_namespaces = v end)
+
+local report_namespaces = logs.reporter("interface","namespaces")
+
+local v_yes, v_list = variables.yes, variables.list
+
+local prefix = "????"
+local meaning = "@@@@"
+
+local data = { }
+
+function namespaces.define(namespace,settings)
+ if trace_namespaces then
+ report_namespaces("installing namespace %a with settings %a",namespace,settings)
+ end
+ if data[namespace] then
+ report_namespaces("namespace %a is already taken",namespace)
+ end
+ if #namespace < 2 then
+ report_namespaces("namespace %a should have more than 1 character",namespace)
+ end
+ local ns = { }
+ data[namespace] = ns
+ utilities.parsers.settings_to_hash(settings,ns)
+ local name = ns.name
+ if not name or name == "" then
+ report_namespaces("provide a (command) name in namespace %a",namespace)
+ end
+ local self = "\\" .. prefix .. namespace
+ context.unprotect()
+ -- context.installnamespace(namespace)
+ context("\\def\\%s%s{%s%s}",prefix,namespace,meaning,namespace) -- or context.setvalue
+ if trace_namespaces then
+ report_namespaces("using namespace %a for %a",namespace,name)
+ end
+ local parent = ns.parent or ""
+ if parent ~= "" then
+ if trace_namespaces then
+ report_namespaces("namespace %a for %a uses parent %a",namespace,name,parent)
+ end
+ if not find(parent,"\\",1,true) then
+ parent = "\\" .. prefix .. parent
+ -- todo: check if defined
+ end
+ end
+ context.installparameterhandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing parameter handler for %a",name)
+ end
+ context.installparameterhashhandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing parameterhash handler for %a",name)
+ end
+ local style = ns.style
+ if style == v_yes then
+ context.installstyleandcolorhandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing attribute handler for %a",name)
+ end
+ end
+ local command = ns.command
+ if command == v_yes then
+ context.installdefinehandler(self,name,parent)
+ if trace_namespaces then
+ report_namespaces("installing definition command for %a (single)",name)
+ end
+ elseif command == v_list then
+ context.installdefinehandler(self,name,parent)
+ if trace_namespaces then
+ report_namespaces("installing definition command for %a (multiple)",name)
+ end
+ end
+ local setup = ns.setup
+ if setup == v_yes then
+ context.installsetuphandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing setup command for %a (%s)",name,"single")
+ end
+ elseif setup == v_list then
+ context.installsetuphandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing setup command for %a (%s)",name,"multiple")
+ end
+ end
+ local set = ns.set
+ if set == v_yes then
+ context.installparametersethandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing set/let/reset command for %a (%s)",name,"single")
+ end
+ elseif set == v_list then
+ context.installparametersethandler(self,name)
+ if trace_namespaces then
+ report_namespaces("installing set/let/reset command for %a (%s)",name,"multiple")
+ end
+ end
+ local frame = ns.frame
+ if frame == v_yes then
+ context.installinheritedframed(name)
+ if trace_namespaces then
+ report_namespaces("installing framed command for %a",name)
+ end
+ end
+ context.protect()
+end
+
+function utilities.formatters.list(data,key,keys)
+ if not keys then
+ keys = { }
+ for _, v in next, data do
+ for k, _ in next, v do
+ keys[k] = true
+ end
+ end
+ keys = table.sortedkeys(keys)
+ end
+ context.starttabulate { "|"..string.rep("l|",#keys+1) }
+ context.NC()
+ context(key)
+ for i=1,#keys do
+ context.NC()
+ context(keys[i])
+ end context.NR()
+ context.HL()
+ for k, v in table.sortedhash(data) do
+ context.NC()
+ context(k)
+ for i=1,#keys do
+ context.NC()
+ context(v[keys[i]])
+ end context.NR()
+ end
+ context.stoptabulate()
+end
+
+function namespaces.list()
+ -- utilities.formatters.list(data,"namespace")
+ local keys = { "type", "name", "comment", "version", "parent", "definition", "setup", "style" }
+ utilities.formatters.list(data,"namespace",keys)
+end
+
+
+interfaces.implement {
+ name = "definenamespace",
+ arguments = { "string", "string" },
+ actions = namespaces.define
+}
+
+interfaces.implement {
+ name = "listnamespaces",
+ actions = namespaces.list
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv
new file mode 100644
index 00000000000..d44c0242ee4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv
@@ -0,0 +1,1271 @@
+%D \module
+%D [ file=mult-aux,
+%D version=2010.08.2,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: setupxxx and setupxxxs (so a plural for the root setup and
+% we can consider blocking the root)
+
+% todo (e.g for columnsets and registers): \definexxx[parent][1]
+%
+
+%D A generalization of \MKIV-like inheritance. Just something to play
+%D with (interface might change). The code here evolved in an email
+%D exchange between me and Wolgang Schuster.
+
+% todo: doifelse<whatever>
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
+
+\registerctxluafile{mult-aux}{1.001}
+
+\unprotect
+
+\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % cancel: dec:24 hex:18
+
+%D \starttyping
+%D \unprotect
+%D \def\????aa{@@@@aa}
+%D
+%D \installparameterhandler \????aa {whatever}
+%D \installsetuphandler \????aa {whatever}
+%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot
+%D \installfontandcolorhandler\????aa {whatever}
+%D
+%D % \installcommandhandler \????aa {whatever} \????aa
+%D \protect
+%D
+%D % \whateverparameter \c!test
+%D % \whateverparameterhash \c!test
+%D % \namedwhateverparameter \mycurrentwhatever \c!test
+%D % \usewhateverstyleandcolor \c!style \c!color
+%D % \everydefinewhatever (sets \currentwhatever)
+%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
+%D % \everysetupwhatever (sets \currentwhatever)
+%D
+%D \starttext
+%D \definewhatever[first] \definewhatever[second][first]
+%D test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D \setupwhatever [method=unset] test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D \setupwhatever[first] [method=first] test: \def\currentwhatever{first} \whateverparameter{method} \par
+%D test: \def\currentwhatever{second} \whateverparameter{method} \par
+%D \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par
+%D \stoptext
+%D \stoptyping
+
+% problem: every* could clash
+%
+% There can be less {} in the following definitions if we assume \??aa and \c!somecs
+%
+% todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root
+%
+% it might be more efficient to do this at the lua and
+%
+% watch the push/pop and predefinition of current .. this is needed for nested
+% definitions and overloaded defines using the predefined one
+
+% todo: add (relaxed) postsetup and postdefine hooks, just after the everys
+
+% Start of experimental code: especially tables can have many assignments
+% and although most time is spent in the typesetting anyway, we can squeeze
+% out a little bit. Of course having 500 rows of 50 columns each with some
+% setting does not happen that often. One should keep in mind that in the
+% average document having some 500 assignments is no exception but there we're
+% talking of neglectable runtime for them. Of course in the definitions below
+% there is no real gain, only in the generated \setup* commands. Another
+% situation with many assignments is \XML\ where we can pass attributes
+% and normally don't do testing of them making sense.
+%
+% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
+% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
+% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s
+
+\let\m_mult_interfaces_namespace\empty
+
+\def\mult_interfaces_get_parameters#1[#2%
+ {\if\noexpand#2]%
+ \expandafter\gobbleoneargument
+ \else
+ \def\m_mult_interfaces_namespace{#1}%
+ \expandafter\mult_interfaces_get_parameters_indeed
+ \fi#2}
+
+\def\mult_interfaces_get_parameters_indeed#1]% namespace already set
+ {\mult_interfaces_get_parameters_item#1,],\_e_o_p_}
+
+\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
+ {\if,#1,% dirty trick for testing #1=empty
+ \expandafter\mult_interfaces_get_parameters_item
+ \else\if]#1%
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
+ % \doubleexpandafter\mult_interfaces_get_parameters_item % saves skipping when at end
+ \fi\fi#2}
+
+\def\mult_interfaces_get_parameters_error#1#2% #3%
+ {\mult_interfaces_get_parameters_error_indeed{#1}{#2}%
+ \gobbleoneargument}
+
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
+ {\showassignerror{#2}{\the\inputlineno\space(#1)}}
+
+\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
+ {\ifx\empty#1\empty
+ \expandafter\mult_interfaces_get_parameters_error
+ \else\ifx#3\empty
+ \doubleexpandafter\mult_interfaces_get_parameters_error
+ \else
+ \doubleexpandafter\mult_interfaces_def
+ \fi\fi
+ \m_mult_interfaces_namespace{#1}{#2}%
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\startinterface english
+
+ % some 10% faster
+
+ \let\mult_interfaces_get_parameters_error\undefined
+
+ \def\mult_interfaces_get_parameters_error_one#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue}
+
+ \def\mult_interfaces_get_parameters_error_two#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}}
+
+ \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
+ {\ifx\empty#1\empty
+ \mult_interfaces_get_parameters_error_one
+ \else\ifx#3\empty
+ \mult_interfaces_get_parameters_error_two
+ \else
+ \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}%
+ \fi\fi
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+ % interesting but not faster
+ %
+ % \def\mult_interfaces_get_parameters_error_one#1\m_mult_interfaces_namespace#2\fi\fi%
+ % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi}
+ %
+ % \def\mult_interfaces_get_parameters_error_two#1\m_mult_interfaces_namespace#2\fi\fi%
+ % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi\fi}
+ %
+ % \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
+ % {\expandafter\def\csname
+ % \ifx\empty#1\empty
+ % \mult_interfaces_get_parameters_error_one
+ % \else\ifx#3\empty
+ % \mult_interfaces_get_parameters_error_two
+ % \else
+ % \m_mult_interfaces_namespace#1%
+ % \fi\fi
+ % \endcsname{#2}
+ % \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\stopinterface
+
+\newif\ifassignment
+
+\def\mult_check_for_assignment_indeed#1=#2#3\_end_
+ {\if#2@\assignmentfalse\else\assignmenttrue\fi}
+
+\def\mult_check_for_assignment#1%
+ {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}
+
+% End of experimental code.
+
+\unexpanded\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\unexpanded\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \unexpanded\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname}
+
+\stopinterface
+
+% the commented detokenized variant that backtracks ... needs testing usage first
+%
+% \let\whatever\relax
+%
+% \definetest[oeps][bagger=\whatever]
+%
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
+
+\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
+
+\unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only)
+ {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
+ %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
+ \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
+ \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ %\def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+ \def#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#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
+ % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+%% \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
+ \def#8##1{\begincsname#1#2:##1\endcsname}%
+ \def#9##1{\csname#1#2:##1\endcsname}} % can go when we use \begincsname
+
+% pre-expansion can be a bit faster but handly any effect on a normal run so let's go for
+% saving some memory
+%
+% \unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only)
+% {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
+% %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
+% \edef#3##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1\noexpand#2:\s!parent\endcsname{##1}\noexpand\fi\endcsname}%
+% \edef#4##1##2{\noexpand\ifcsname##1:##2\endcsname##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname##1:\s!parent\endcsname{##2}\noexpand\fi}%
+% \def #5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+% \edef#6##1##2{\noexpand\csname\noexpand\ifcsname#1##1:##2\endcsname#1##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1##1:\s!parent\endcsname{##2}\noexpand\fi\endcsname}%
+% \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
+% % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
+% % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+% \edef#8##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\s!empty\noexpand\fi\endcsname}%
+% \edef#9##1{\noexpand\csname#1#2:##1\endcsname}}
+
+\unexpanded\def\installparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_parameter_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter
+ \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter
+ \expandafter\noexpand\csname named#2parameter\endcsname
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname strict#2parameter\endcsname % checked
+ \expandafter\noexpand\csname direct#2parameter\endcsname}} % unchecked
+
+\unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3%
+ {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
+ %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}
+ %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\??empty\fi\endcsname}}
+ \def#3##1{\begincsname#1:##1\endcsname}}
+
+\unexpanded\def\installrootparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_root_parameter_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
+ \expandafter\noexpand\csname root#2parameter\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#2\relax\let#2\empty\fi
+ \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
+ \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
+ \def#6{#1#2:}%
+ \def#7##1{#1##1:}%
+ \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
+ \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}
+
+\unexpanded\def\installparameterhashhandler#1#2%
+ {\expandafter\let\csname#2namespace\endcsname#1%
+ \normalexpanded
+ {\mult_interfaces_install_parameter_hash_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameterhash\endcsname
+ \expandafter\noexpand\csname do#2parameterhash\endcsname % or : #2_parameter_hash
+ \expandafter\noexpand\csname do#2parentparameterhash\endcsname % or : #2_parent_parameter_hash
+ \expandafter\noexpand\csname current#2hash\endcsname
+ \expandafter\noexpand\csname named#2hash\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname chaintocurrent#2\endcsname}}
+
+% In \MKIV\ we can probably use the english variant for all other
+% languages too.
+
+% todo: inline the def/let
+
+\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
+ {\ifx#2\relax\let#2\empty\fi
+ \unexpanded\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2
+ \unexpanded\def#6{\mult_interfaces_lete{#1#2:}}}% ##1
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
+ {\ifx#2\relax\let#2\empty\fi
+ \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2
+ \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1
+
+\stopinterface
+
+\unexpanded\def\installparametersethandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_parameter_set_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
+ \expandafter\noexpand\csname let#2parameter\endcsname
+ \expandafter\noexpand\csname reset#2parameter\endcsname}}
+
+\let\dousecurrentstyleparameter\relax
+\let\dousecurrentcolorparameter\relax
+
+\let\currentstyleparameter\empty
+\let\currentcolorparameter\empty
+
+\unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
+ {\unexpanded\def#2##1##2% style color
+ {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
+ \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
+ \unexpanded\def#3##1% style
+ {\edef\currentstyleparameter{#1{##1}}% this name is public
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
+ \unexpanded\def#4##1% color
+ {\edef\currentcolorparameter{#1{##1}}% this name is public
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}
+
+\unexpanded\def\installstyleandcolorhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_style_and_color_handler
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
+ \expandafter\noexpand\csname use#2styleparameter\endcsname
+ \expandafter\noexpand\csname use#2colorparameter\endcsname}}
+
+\let\definehandlerparent\empty
+
+\def\mult_check_for_parent#1#2#3#4%
+ {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else
+ \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
+ \fi \fi}
+
+%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
+%def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+
+\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi}
+\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname}
+\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname}
+
+\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
+ \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
+ \ifassignment
+ \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]%
+ \else
+ \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}%
+ \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
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname define#2\endcsname
+ {\noexpand#3}% root
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname define_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everypreset#2\endcsname
+ \expandafter\noexpand\csname everydefine#2\endcsname
+ \expandafter\noexpand\csname current#2parent\endcsname
+ \expandafter\noexpand\csname saved_defined_#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dodoubleempty#4}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
+ \newtoks#5%
+ \newtoks#8%
+ \unexpanded\def#4[##1][##2]% maybe helper
+ {\let#7#3%
+ \ifsecondargument
+ \def#9####1% we will have a simple one as well
+ {\edef#3{####1}%
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5}%
+ \processcommalist[##1]#9%
+ \else
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \fi
+ \let#3#7%
+ \the#8}}
+
+\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 setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value]
+\let\doingrootsetuproot \plustwo % \setuplayout [key=value]
+\let\doingrootsetnamed \plusthree % \setuplayout[name]
+\let\doingrootsetroot \plusfour % \setuplayout
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dodoubleempty#4}%
+ \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}}
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
+ {\newtoks#5%
+ \newconstant#2%
+ \newtoks#8%
+ \newtoks#9%
+ \ifx#6\relax\let#6\empty\fi
+ \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}%
+ \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
+ \ifassignment
+ % \setuplayout[key=value]
+ \let#7#3%
+ \let#6#3%
+ \let#3\empty
+ #2\doingrootsetuproot
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \the#8% switchsetups
+ \let#3#7%
+ \else
+ % \setuplayout[whatever]
+ \let#6#3% % previous becomes current
+ \edef#3{##1}% this will catch reset so one needs to test for it
+ #2\doingrootsetnamed
+ \the#5% % we can check for previous vs current
+ \the#8% switchsetups
+ \fi
+ \else
+ % \setuplayout
+ \let#6#3% % previous becomes current
+ \let#3\empty % current becomes empty
+ #2\doingrootsetroot
+ \the#5%
+ \the#8% switchsetups
+ \fi\fi
+ #2\zerocount % mode is always zero at the end
+ \the#9}}
+
+\unexpanded\def\installswitchsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_switch_setup_handler_a
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \mult_interfaces_install_switch_setup_handler_b
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname #2setupmode\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname previous#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everyswitch#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dotripleempty#4}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}%
+ \newtoks#5%
+ \def#4[##1][##2][##3]%
+ {\let#8#3%
+ \ifthirdargument
+ \def#9####1%
+ {\edef#3{####1}%
+ \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
+ \the#5}%
+ \processcommalist[##1]#9%
+ \else\ifsecondargument
+ \def#9####1%
+ {\edef#3{####1}%
+ #7% checks parent and sets if needed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5}%
+ \processcommalist[##1]#9%
+ \else
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \fi\fi
+ \let#3#8}}
+
+\unexpanded\def\installautosetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_auto_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+\unexpanded\def\installbasicparameterhandler#1#2%
+ {\installparameterhandler {#1}{#2}%
+ \installparameterhashhandler{#1}{#2}%
+ \installparametersethandler {#1}{#2}%
+ \installrootparameterhandler{#1}{#2}}
+
+\unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installautosetuphandler {#1}{#2}}
+
+\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installswitchsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installautosetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
+ {\installbasicparameterhandler{#1}{#2}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+%D Many mechanisms have some kind of inheritance in place, and these are
+%D the speed||critical ones. Therefore there is no reason to stick to
+%D \type {\@@xxkey} for the sake of performance. For this reason we also
+%D provide a direct variant. This permits a more consistent treatment of
+%D namespaces. A \type {\whateverparameter} call is three times slower
+%D and a \type {\directwhateverparameter} call two times but for some
+%D 100K expansions we only loose some .1 second which is neglectable
+%D given the small amount of expansions in real runs.
+
+%D We don't need colons for such simple cases.
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
+%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+ {\def#3##1{\begincsname#1##1\endcsname}%
+ \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
+ % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+ \def#5##1{\csname#1##1\endcsname}}
+
+\unexpanded\def\installdirectparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_handler
+ {\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname direct#2parameter\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
+ {\unexpanded\def#2{\dosingleempty#3}%
+ \newtoks#5%
+ \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
+ \def#4{\mult_interfaces_get_parameters#1}}
+
+\unexpanded\def\installdirectsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
+ \expandafter\noexpand\csname everysetup#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2{\mult_interfaces_def #1}%
+ \unexpanded\def#3{\mult_interfaces_edef#1}%
+ \unexpanded\def#4{\mult_interfaces_let #1}%
+ \unexpanded\def#5{\mult_interfaces_let #1\empty}}%
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}%
+ \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
+ \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}%
+ \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%
+
+\stopinterface
+
+\unexpanded\def\installdirectparametersethandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_set_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
+ \expandafter\noexpand\csname let#2parameter\endcsname
+ \expandafter\noexpand\csname reset#2parameter\endcsname}}
+
+\let\installdirectstyleandcolorhandler\installstyleandcolorhandler
+
+\unexpanded\def\installdirectcommandhandler#1#2%
+ {\installdirectparameterhandler {#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ \installdirectparametersethandler {#1}{#2}%
+ \installdirectstyleandcolorhandler{#1}{#2}}
+
+\unexpanded\def\installsetuponlycommandhandler#1#2%
+ {\installdirectparameterhandler{#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ }% maybe \installdirectparametersethandler {#1}{#2}%
+
+% Experiment:
+
+% \installcorenamespace {one}
+% \installcorenamespace {two}
+%
+% \installcommandhandler \??one {one} \??one
+% \installcommandhandler \??two {two} \??two
+%
+% \defineone[test] \setupone[test][alpha=first]
+% \definetwo[test] \setuptwo[test][beta=second]
+%
+% \protect
+%
+% \def\currentone{test}
+% \def\currenttwo{test}
+%
+% \relateparameterhandlers {two} {test} {one} {test}
+%
+% yes:\oneparameter{alpha}\par
+% nop:\oneparameter{beta}\par
+% yes:\twoparameter{alpha}\par
+% yes:\twoparameter{beta}\par
+
+\unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
+ {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
+
+\unexpanded\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance}
+ {\expandafter\edef\csname#1#2:\s!parent\endcsname{#3#4}}
+
+%D Here is another experiment:
+
+\unexpanded\def\installactionhandler#1%
+ {\normalexpanded
+ {\mult_interfaces_install_action_handler
+ {#1}%
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname
+ \expandafter\noexpand\csname #1_action\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
+ {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
+ \unexpanded\def#4[##1][##2]%
+ {\begingroup
+ \ifsecondargument
+ \edef#2{##1}%
+ #3[##2]%
+ \else\iffirstargument
+ \doifelseassignment{##1}
+ {\let#2\empty
+ #3[##1]}%
+ {\edef#2{##1}}%
+ \else
+ \let#2\empty
+ \fi\fi
+ \directsetup{handler:action:#1}%
+ \endgroup}}
+
+% First we had, in tune with the regular system variables:
+%
+% \starttyping
+% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
+% \stoptyping
+%
+% The following variant is nicer and in principle faster but that gets
+% unnoticed unless lots of expansion happens. Also, we can use long tags
+% but the internal expansion will be relatively small (and unlikely more
+% than 4 characters). For instance, \??xx used to expand to @@xx but now
+% becomes for instance 123::. This is one character more but in quite some
+% cases we had : after such a tag in the old situation. In the new situation
+% we create more namespaces and don't need that : any more, so we end up
+% with on the average the same amount of tokens and definitely less when
+% we consider cases like \??xx:\c!align: which now is just \??somealign and
+% therefore has length 5 now (instead of 4+1+5+1=10).
+%
+% Eventualy we will have a verbose \blablanamespace and the difference between
+% core and regular can go ... after all, \xxxparameter can already clash between
+% the two prefix groups .. if users use this mechanism a lot they should use
+% verbose names anyway (the old two character names were mostly an optimization
+% as they also expanded to these characters).
+
+% todo: register namespaces at lua end for logging and reverse resolve
+% todo: move this to syst-ini so that we can use it real early
+
+\newcount\c_mult_interfaces_n_of_namespaces
+
+%def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>}
+\def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>}
+
+\def\v_interfaces_prefix_template % consistently %03i>
+ {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi
+ \number\c_mult_interfaces_n_of_namespaces>}
+
+\def\v_interfaces_prefix_template % consistently %03i>
+ {\number\c_mult_interfaces_n_of_namespaces>}
+
+\unexpanded\def\installnamespace#1% for modules and users
+ {\ifcsname ????#1\endcsname
+ \writestatus\m!system{duplicate user namespace '#1'}\wait
+ \else
+ \global\advance\c_mult_interfaces_n_of_namespaces\plusone
+ \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
+ \fi}
+
+\unexpanded\def\installcorenamespace#1%
+ {\ifcsname ??#1\endcsname
+ \writestatus\m!system{duplicate core namespace '#1'}\wait
+ \else
+ \global\advance\c_mult_interfaces_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
+ \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
+ \fi}
+
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
+ {\clf_showassignerror{#1}{#2}\inputlineno} % no longer \waitonfatalerror
+
+% We install two core namespaces here, as we want nice error messages. Maybe
+% we will reserve the first 9.
+
+\installcorenamespace{fontinstanceready}
+\installcorenamespace{fontinstancebasic}
+\installcorenamespace{fontinstanceclass}
+
+%D The next one is handy for local assignments.
+
+\installcorenamespace{dummy}
+
+\letvalue\??dummy\empty
+
+%% \def\dummyparameter #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
+ \def\dummyparameter #1{\begincsname\??dummy#1\endcsname}
+ \def\directdummyparameter#1{\csname\??dummy#1\endcsname}
+\unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname}
+\unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname}
+
+% \unexpanded\def\getdummyparameters
+% {\mult_interfaces_get_parameters\??dummy}
+
+\unexpanded\def\getdummyparameters[#1%
+ {\if\noexpand#1]%
+ \expandafter\gobbleoneargument
+ \else
+ \let\m_mult_interfaces_namespace\??dummy
+ \expandafter\mult_interfaces_get_parameters_indeed
+ \fi#1}
+
+\mult_interfaces_install_style_and_color_handler
+ \directdummyparameter
+ \usedummystyleandcolor
+ \usedummystyleparameter
+ \usedummycolorparameter
+
+% Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
+% but we don't gain much. Actually we might just inline all definitions.
+
+% \enabletrackers[interfaces.namespaces,context.flush]
+%
+% \definenamespace
+% [xy]
+% [type=module,
+% comment=test module,
+% version=1,
+% name=test,
+% style=yes,
+% command=yes,
+% setup=list,
+% set=yes,
+% parent=xy]
+%
+% \unprotect
+% \getparameters
+% [\????xy]
+% [text=]
+% \protect
+%
+% \definetest[one]
+%
+% \starttext
+%
+% “\testparameter{text}”
+%
+% \setuptest[text=foo]
+%
+% “\testparameter{text}”
+%
+% \setuptest[one][text=bar]
+%
+% “\testparameter{text}”
+%
+% \stoptext
+%
+% This is a user (module) command:
+
+\unexpanded\def\definenamespace
+ {\dodoubleargument\mult_interfaces_define_name_space}
+
+\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
+ {\clf_definenamespace{#1}{#2}}
+
+\def\listnamespaces
+ {\clf_listnamespaces}
+
+%D Helper:
+%D
+%D \starttyping
+%D \showparentchain{@@am}{left}
+%D \stoptyping
+
+\unexpanded\def\showparentchain#1#2%
+ {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
+
+% \def\mult_interfaces_show_parent_chain#1%
+% {#1 => %
+% \ifcsname#1:\s!parent\endcsname
+% \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+% \fi}
+
+\def\mult_interfaces_show_parent_chain#1%
+ {#1 => %
+ \ifcsname#1:\s!parent\endcsname
+ %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+ \expandafter\mult_interfaces_show_parent_chain\lastnamedcs
+ \fi}
+
+%D Another helper (needs to be applied):
+
+\unexpanded\def\doifelsecommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
+\unexpanded\def\doifcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
+% another set of (fast) helpers (grep for usage):
+
+\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
+ {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}
+
+\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy
+ {#1\endcsname#1\else#2\fi\endcsname}
+
+\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
+ {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
+
+\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
+ {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}
+
+\def\syst_helpers_expand_checked_value#1#2%
+ {#1\endcsname#1\else#2\fi\endcsname}
+
+%D Conventions:
+%D
+%D \starttyping
+%D \newcount \c_class_whatever
+%D \newconditional \c_class_whatever
+%D \newconstant \c_class_whatever
+%D \newdimen \d_class_whatever
+%D \newskip \s_class_whatever
+%D \newmuskip \s_class_whatever
+%D \newbox \b_class_whatever
+%D \newtoks \t_class_whatever
+%D
+%D \edef\p_class_whatever{\classparameter\c!whatever}
+%D \edef\m_class_whatever{whatever}
+%D \stoptyping
+
+% experiment: in principle this is faster but not that noticeable as we don't do that
+% many assignments and mechanism that do are also slow; the advantage is mostly nicer
+% in tracing
+
+\def\s!simple{simple}
+\def\s!single{single}
+\def\s!double{double}
+\def\s!triple{triple}
+
+\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
+% only use one extra)
+%
+% \global\advance\commalevel \plusone
+% \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname####1,%
+% {\edef#3{####1}%
+% \mult_interfaces_get_parameters{#1#3:}[##2]%
+% \the#5%
+% \syst_helpers_do_process_comma_item}%
+% \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument\relax##1,]\relax
+% % \syst_helpers_do_do_process_comma_item##1,]\relax
+% \global\advance\commalevel \minusone
+
+% The next one is experimental (and used in publications):
+
+\let\c_mult_set\relax
+
+\unexpanded\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7%
+ {\newcount#3%
+ \let#6\empty
+ \unexpanded\def#2%
+ {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname
+ \ifx\c_mult_set\relax
+ \expandafter\newtoks\c_mult_set
+ \expandafter\let\csname #1_t_#6\endcsname\c_mult_set
+ \fi}
+ \unexpanded\def#4##1%
+ {\pushmacro#6%
+ \advance#3\plusone
+ \edef#6{##1}%
+ \unprotect}%
+ \unexpanded\def#5%
+ {\protect
+ \advance#3\minusone
+ \popmacro#6}%
+ \unexpanded\def#7##1%
+ {\edef#6{##1}%
+ #2%
+ \the\c_mult_set\relax}}
+
+\unexpanded\def\installdefinitionset#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname push#2\endcsname
+ \expandafter\noexpand\csname pop#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname use#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc
+ {\let#5#2%
+ \unexpanded\def#2%
+ {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}%
+ \unexpanded\def#6%
+ {\dodoubleempty#7}%
+ \unexpanded\def#7[##1][##2]%
+ {\ifsecondargument
+ #3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
+ \else\iffirstargument
+ #3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
+ \fi\fi}}
+
+\unexpanded\def\installdefinitionsetmember#1#2#3#4%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set_member
+ {\noexpand#3}% \??aa
+ \expandafter\noexpand\csname setup#4\endcsname
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname normal_setup_#4\endcsname
+ \expandafter\noexpand\csname delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname do_delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname setup#4_\s!single\endcsname
+ \expandafter\noexpand\csname setup#4_\s!double\endcsname}}
+
+%D Another experiment:
+
+\unexpanded\def\mult_interfaces_install_parent_injector#1#2#3#4%
+ {\unexpanded\def#4##1%
+ {\ifx#3\empty
+ \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}%
+ \fi}}
+
+\unexpanded\def\installparentinjector#1#2%
+ {\normalexpanded{\mult_interfaces_install_parent_injector
+ {\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname current#2parent\endcsname
+ \expandafter\noexpand\csname inject#2parent\endcsname}}
+
+\protect
+
+%\unprotect
+% \installcorenamespace {test} \installcommandhandler \??test {test} \??test
+% \unexpanded\def\TestMeA[#1]%
+% {\edef\currenttest{#1}
+% \edef\p_before{\testparameter\c!before}%
+% \ifx\p_before\empty \relax \else \relax \fi}
+% \unexpanded\def\TestMeB[#1]%
+% {\edef\currenttest{#1}
+% \doifelsenothing{\testparameter\c!before}\relax\relax}
+% \unexpanded\def\TestMeC[#1]%
+% {\edef\currenttest{#1}
+% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
+% \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
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-chk.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-chk.lua
new file mode 100644
index 00000000000..44a9f739f9e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-chk.lua
@@ -0,0 +1,93 @@
+if not modules then modules = { } end modules ['mult-chk'] = {
+ version = 1.001,
+ comment = "companion to mult-chk.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local lpegmatch = lpeg.match
+local type = type
+
+local make_settings_to_hash_pattern = utilities.parsers.make_settings_to_hash_pattern
+local settings_to_set = utilities.parsers.settings_to_set
+local allocate = utilities.storage.allocate
+
+local report_interface = logs.reporter("interface","checking")
+
+local interfaces = interfaces
+local implement = interfaces.implement
+
+interfaces.syntax = allocate {
+ test = { keys = table.tohash { "a","b","c","d","e","f","g" } }
+}
+
+function interfaces.invalidkey(category,key)
+ report_interface("invalid key %a for %a in line %a",key,category,tex.inputlineno)
+end
+
+function interfaces.setvalidkeys(category,list)
+ local s = interfaces.syntax[category]
+ if not s then
+ interfaces.syntax[category] = {
+ keys = settings_to_set(list)
+ }
+ else
+ s.keys = settings_to_set(list)
+ end
+end
+
+function interfaces.addvalidkeys(category,list)
+ local s = interfaces.syntax[category]
+ if not s then
+ interfaces.syntax[category] = {
+ keys = settings_to_set(list)
+ }
+ else
+ settings_to_set(list,s.keys)
+ end
+end
+
+implement {
+ name = "setvalidinterfacekeys",
+ actions = interfaces.setvalidkeys,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "addvalidinterfacekeys",
+ actions = interfaces.addvalidkeys,
+ arguments = { "string", "string" }
+}
+
+-- weird code, looks incomplete ... probably an experiment
+
+local prefix, category, keys
+
+local setsomevalue = context.setsomevalue
+local invalidkey = interfaces.invalidkey
+
+local function set(key,value)
+ if keys and not keys[key] then
+ invalidkey(category,key)
+ else
+ setsomevalue(prefix,key,value)
+ end
+end
+
+local pattern = make_settings_to_hash_pattern(set,"tolerant")
+
+function interfaces.getcheckedparameters(k,p,s)
+ if s and s ~= "" then
+ prefix, category = p, k
+ keys = k and k ~= "" and interfaces.syntax[k].keys
+ lpegmatch(pattern,s)
+ end
+end
+
+implement {
+ name = "getcheckedinterfaceparameters",
+ actions = interfaces.getcheckedparameters,
+ arguments = { "string", "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-chk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-chk.mkiv
new file mode 100644
index 00000000000..9208a73e1e5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-chk.mkiv
@@ -0,0 +1,103 @@
+%D \module
+%D [ file=mult-chk,
+%D version=2009.04.13,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Checking}
+
+%D This is very experimental code that eventually might be used
+%D once we have split the whole code base.
+
+%D \startbuffer
+%D \getcheckedparameters[MyTest][MyNamespace][a=1,b=2,c=3,d=4,crap=whatever]
+%D
+%D \MyNamespacea\quad
+%D \MyNamespaceb\quad
+%D \MyNamespacec\quad
+%D \MyNamespaced\quad
+%D crap is \ifdefined\MyNamespacecrap\else un\fi defined
+%D \stopbuffer
+%D
+%D \enablecheckparameters
+%D
+%D \setvalidparameterkeys[MyTest][a,b,c,d] \getbuffer \par
+%D \addvalidparameterkeys[MyTest][crap] \getbuffer \par
+
+\unprotect
+
+\registerctxluafile{mult-chk}{1.001}
+
+\unexpanded\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys}
+\unexpanded\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys}
+
+\def\mult_checkers_set_valid_parameter_keys[#1][#2]{\clf_setvalidinterfacekeys{#1}{#2}}
+\def\mult_checkers_add_valid_parameter_keys[#1][#2]{\clf_addvalidinterfacekeys{#1}{#2}}
+
+\def\mult_checkers_get_checked_parameters_yes[#1]#2[#3]#4[#5%
+ {\if\noexpand#5]%
+ \expandafter\gobblethreearguments
+ \else
+ \let\setsomevalue\dosetvalue % used at the lua end
+ \expandafter\mult_checkers_get_checked_parameters_yes_indeed
+ \fi{#1}{#3}#5}
+
+\def\mult_checkers_get_checked_parameters_yes_indeed#1#2#3]%
+ {\clf_getcheckedinterfaceparameters{#1}{#2}{\detokenize{#3}}}
+
+\def\mult_checkers_get_checked_parameters_nop[#1]#2[#3]#4[#5%
+ {\if\noexpand#5]%
+ \expandafter\gobbletwoarguments
+ \else
+ \let\setsomevalue\dosetvalue % used at the lua end
+ \expandafter\mult_checkers_get_checked_parameters_nop_indeed
+ \fi{#3}#5}
+
+\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]% needs checking with adapted syst-aux.mkiv
+ {\def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#1}% will change
+ \syst_helpers_process_comma_item#2,],\_e_o_p_}
+
+\unexpanded\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop}
+\unexpanded\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes}
+
+\disablecheckparameters
+
+\protect \endinput
+
+\starttext
+
+\testfeatureonce{10000}{\getcheckedparameters[test][xx][a=b,c= d, e = f]} % 0.20 seconds
+
+\enablecheckparameters
+
+\testfeatureonce{10000}{\getcheckedparameters[test][xx][a=b,c= d, e = f]} % 0.35 seconds
+
+\getcheckedparameters[test][xx][a=a]
+\getcheckedparameters[test][xx][b= b]
+\getcheckedparameters[test][xx][c = c]
+\getcheckedparameters[test][xx][d = d d , e = e ,f = f ]
+\getcheckedparameters[test][xx][g={oeps {oeps}}]
+\getcheckedparameters[test][xx][crap=whatever]
+
+\startlines
+[a:\getvalue{xxa}][a]
+[b:\getvalue{xxb}][b]
+[c:\getvalue{xxc}][c]
+[d:\getvalue{xxd}][d d ]
+[e:\getvalue{xxe}][e ]
+[f:\getvalue{xxf}][f ]
+[g:\getvalue{xxg}][\detokenize\expandafter{\xxg}]
+\stoplines
+
+\setvalidparameterkeys[test][crap]
+
+\getcheckedparameters[test][xx][crap=whatever]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua
new file mode 100644
index 00000000000..0d0c30c3054
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua
@@ -0,0 +1,17725 @@
+if not modules then modules = { } end modules ['mult-def'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+-- we can remove some commands, like inleftmargin and so (see typo-mar.mkiv)
+
+return {
+ ["commands"]={
+ ["CAPPED"]={
+ ["cs"]="KAP",
+ ["de"]="KAP",
+ ["en"]="CAP",
+ ["fr"]="CAP",
+ ["it"]="CAP",
+ ["nl"]="KAP",
+ ["pe"]="CAP",
+ ["ro"]="KAP",
+ },
+ ["Character"]={
+ ["cs"]="Znak",
+ ["de"]="Buchstabe",
+ ["en"]="Character",
+ ["fr"]="Caractere",
+ ["it"]="Lettera",
+ ["nl"]="Letter",
+ ["pe"]="Character",
+ ["ro"]="Litera",
+ },
+ ["Characters"]={
+ ["cs"]="Znaky",
+ ["de"]="Buchstaben",
+ ["en"]="Characters",
+ ["fr"]="Caracteres",
+ ["it"]="Lettere",
+ ["nl"]="Letters",
+ ["pe"]="Characters",
+ ["ro"]="Litere",
+ },
+ ["MONTH"]={
+ ["cs"]="MESIC",
+ ["de"]="MONAT",
+ ["en"]="MONTH",
+ ["fr"]="MOIS",
+ ["it"]="MESE",
+ ["nl"]="MAAND",
+ ["pe"]="MONTH",
+ ["ro"]="LUNA",
+ },
+ ["Numbers"]={
+ ["cs"]="Cisla",
+ ["de"]="Ziffern",
+ ["en"]="Numbers",
+ ["fr"]="Numeros",
+ ["it"]="Numeri",
+ ["nl"]="Cijfers",
+ ["pe"]="Numbers",
+ ["ro"]="Numere",
+ },
+ ["Romannumerals"]={
+ ["cs"]="Rimskecislice",
+ ["de"]="Roemischezahlen",
+ ["en"]="Romannumerals",
+ ["fr"]="Chiffresromains",
+ ["it"]="Numeriromani",
+ ["nl"]="Romeins",
+ ["pe"]="Romannumerals",
+ ["ro"]="Numereromane",
+ },
+ ["SmallCapped"]={
+ ["cs"]="Kap",
+ ["de"]="Kap",
+ ["en"]="Cap",
+ ["fr"]="Cap",
+ ["it"]="Cap",
+ ["nl"]="Kap",
+ ["pe"]="Cap",
+ ["ro"]="Kap",
+ },
+ ["SmallCaps"]={
+ ["cs"]="Kaps",
+ ["de"]="Kaps",
+ ["en"]="Caps",
+ ["fr"]="Caps",
+ ["it"]="Caps",
+ ["nl"]="Kaps",
+ ["pe"]="Caps",
+ ["ro"]="Kaps",
+ },
+ ["WEEKDAY"]={
+ ["cs"]="VSEDNIDEN",
+ ["de"]="WOCHENTAG",
+ ["en"]="WEEKDAY",
+ ["fr"]="JOURSEMAINE",
+ ["it"]="GIORNOSETTIMANA",
+ ["nl"]="WEEKDAG",
+ ["pe"]="WEEKDAY",
+ ["ro"]="ZIDINSAPTAMANA",
+ },
+ ["WORD"]={
+ ["cs"]="SLOVO",
+ ["de"]="WORT",
+ ["en"]="WORD",
+ ["fr"]="MOT",
+ ["it"]="PAROLA",
+ ["nl"]="WOORD",
+ ["pe"]="WORD",
+ ["ro"]="CUVANT",
+ },
+ ["WORDS"]={
+ ["cs"]="SLOVA",
+ ["de"]="WOERTER",
+ ["en"]="WORDS",
+ ["fr"]="MOTS",
+ ["it"]="PAROLE",
+ ["nl"]="WOORDEN",
+ ["pe"]="WORDS",
+ ["ro"]="CUVINTE",
+ },
+ ["Word"]={
+ ["cs"]="Slovo",
+ ["de"]="Wort",
+ ["en"]="Word",
+ ["fr"]="Mot",
+ ["it"]="Parola",
+ ["nl"]="Woord",
+ ["pe"]="Word",
+ ["ro"]="Cuvant",
+ },
+ ["Words"]={
+ ["cs"]="Slova",
+ ["de"]="Woerter",
+ ["en"]="Words",
+ ["fr"]="Mots",
+ ["it"]="Parole",
+ ["nl"]="Woorden",
+ ["pe"]="Words",
+ ["ro"]="Cuvinte",
+ },
+ ["about"]={
+ ["cs"]="oref",
+ ["de"]="ueber",
+ ["en"]="about",
+ ["fr"]="concernant",
+ ["it"]="intorno",
+ ["nl"]="about",
+ ["pe"]="درمورد",
+ ["ro"]="despre",
+ },
+ ["adaptlayout"]={
+ ["cs"]="prizpusobvzhled",
+ ["de"]="passelayoutan",
+ ["en"]="adaptlayout",
+ ["fr"]="adaptedisposition",
+ ["it"]="adattalayout",
+ ["nl"]="paslayoutaan",
+ ["pe"]="تنظیم‌طرح‌بندی",
+ ["ro"]="adapteazaaspect",
+ },
+ ["adding"]={},
+ ["arg"]={
+ ["cs"]="arg",
+ ["de"]="arg",
+ ["en"]="arg",
+ ["fr"]="arg",
+ ["it"]="arg",
+ ["nl"]="arg",
+ ["pe"]="افزودن",
+ ["ro"]="arg",
+ },
+ ["at"]={
+ ["cs"]="pref",
+ ["de"]="bei",
+ ["en"]="at",
+ ["fr"]="a",
+ ["it"]="al",
+ ["nl"]="op",
+ ["pe"]="در",
+ ["ro"]="la",
+ },
+ ["atleftmargin"]={
+ ["cs"]="atleftmargin",
+ ["de"]="atleftmargin",
+ ["en"]="atleftmargin",
+ ["fr"]="atleftmargin",
+ ["it"]="atleftmargin",
+ ["nl"]="oplinkermarge",
+ ["pe"]="درحاشیه‌چپ",
+ ["ro"]="atleftmargin",
+ },
+ ["atpage"]={
+ ["cs"]="nastrane",
+ ["de"]="aufseite",
+ ["en"]="atpage",
+ ["fr"]="alapage",
+ ["it"]="apagina",
+ ["nl"]="oppagina",
+ ["pe"]="درصفحه",
+ ["ro"]="lapagina",
+ },
+ ["atrightmargin"]={
+ ["cs"]="atrightmargin",
+ ["de"]="atrightmargin",
+ ["en"]="atrightmargin",
+ ["fr"]="atrightmargin",
+ ["it"]="atrightmargin",
+ ["nl"]="oprechtermarge",
+ ["pe"]="درحاشیه‌راست",
+ ["ro"]="atrightmargin",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پس‌زمینه",
+ ["ro"]="fundal",
+ },
+ ["backspace"]={
+ ["cs"]="odsazenizleva",
+ ["de"]="rumpfweite",
+ ["en"]="backspace",
+ ["fr"]="retourarriere",
+ ["it"]="spaziodietro",
+ ["nl"]="rugwit",
+ ["pe"]="فاصله‌پشت",
+ ["ro"]="spatiuspate",
+ },
+ ["blackrule"]={
+ ["cs"]="cernalinka",
+ ["de"]="rechteck",
+ ["en"]="blackrule",
+ ["fr"]="lignenoire",
+ ["it"]="lineanera",
+ ["nl"]="blokje",
+ ["pe"]="خط‌سیاه",
+ ["ro"]="linieneagra",
+ },
+ ["blackrules"]={
+ ["cs"]="cernelinky",
+ ["de"]="rechtecke",
+ ["en"]="blackrules",
+ ["fr"]="lignesnoires",
+ ["it"]="lineenere",
+ ["nl"]="blokjes",
+ ["pe"]="خطهای‌سیاه",
+ ["ro"]="liniinegre",
+ },
+ ["blank"]={
+ ["cs"]="preskoc",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blanc",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["bottomdistance"]={
+ ["cs"]="vzdalenostspodku",
+ ["de"]="abstandunten",
+ ["en"]="bottomdistance",
+ ["fr"]="distanceinf",
+ ["it"]="distanzafondo",
+ ["nl"]="onderafstand",
+ ["pe"]="فاصله‌پایین",
+ ["ro"]="distantajos",
+ },
+ ["bottomheight"]={
+ ["cs"]="vyskaspodku",
+ ["de"]="hoeheunten",
+ ["en"]="bottomheight",
+ ["fr"]="hauteurinf",
+ ["it"]="altezzafondo",
+ ["nl"]="onderhoogte",
+ ["pe"]="ارتفاع‌پایین",
+ ["ro"]="inaltimejos",
+ },
+ ["bottomspace"]={
+ ["cs"]="bottomspace",
+ ["de"]="bottomspace",
+ ["en"]="bottomspace",
+ ["fr"]="espaceinf",
+ ["it"]="spaziofondo",
+ ["nl"]="bodemwit",
+ ["pe"]="فضای‌پایین",
+ ["ro"]="spatiujos",
+ },
+ ["but"]={
+ ["cs"]="spodek",
+ ["de"]="but",
+ ["en"]="but",
+ ["fr"]="but",
+ ["it"]="fondo",
+ ["nl"]="but",
+ ["pe"]="اما",
+ ["ro"]="but",
+ },
+ ["button"]={
+ ["cs"]="tlacitko",
+ ["de"]="knopf",
+ ["en"]="button",
+ ["fr"]="bouton",
+ ["it"]="pulsante",
+ ["nl"]="button",
+ ["pe"]="دکمه",
+ ["ro"]="buton",
+ },
+ ["bypassblocks"]={
+ ["cs"]="bypassblocks",
+ ["de"]="bypassblocks",
+ ["en"]="bypassblocks",
+ ["fr"]="sauteblocs",
+ ["it"]="saltablocchi",
+ ["nl"]="passeerblokken",
+ ["pe"]="عبوربلوکها",
+ ["ro"]="saripesteblocuri",
+ },
+ ["character"]={
+ ["cs"]="znak",
+ ["de"]="buchstabe",
+ ["en"]="character",
+ ["fr"]="caractere",
+ ["it"]="lettera",
+ ["nl"]="letter",
+ ["pe"]="حرف",
+ ["ro"]="litera",
+ },
+ ["characters"]={
+ ["cs"]="znaky",
+ ["de"]="buchstaben",
+ ["en"]="characters",
+ ["fr"]="caracteres",
+ ["it"]="lettere",
+ ["nl"]="letters",
+ ["pe"]="حرفها",
+ ["ro"]="litere",
+ },
+ ["chem"]={
+ ["cs"]="chem",
+ ["de"]="chem",
+ ["en"]="chem",
+ ["fr"]="chem",
+ ["it"]="chim",
+ ["nl"]="chem",
+ ["pe"]="chem",
+ ["ro"]="chem",
+ },
+ ["clip"]={
+ ["cs"]="orez",
+ ["de"]="ausschnitt",
+ ["en"]="clip",
+ ["fr"]="clip",
+ ["it"]="clip",
+ ["nl"]="clip",
+ ["pe"]="گیره",
+ ["ro"]="clip",
+ },
+ ["clonefield"]={
+ ["cs"]="klonujpole",
+ ["de"]="klonierefeld",
+ ["en"]="clonefield",
+ ["fr"]="clonechamp",
+ ["it"]="clonacampo",
+ ["nl"]="kloonveld",
+ ["pe"]="میدان‌شبیه‌سازی",
+ ["ro"]="cloneazacamp",
+ },
+ ["color"]={
+ ["cs"]="barva",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["colorbar"]={
+ ["cs"]="barevnalista",
+ ["de"]="farbbalken",
+ ["en"]="colorbar",
+ ["fr"]="barrecouleur",
+ ["it"]="barracolori",
+ ["nl"]="kleurenbalk",
+ ["pe"]="میله‌رنگ",
+ ["ro"]="baraculoare",
+ },
+ ["colorvalue"]={
+ ["cs"]="hodnotabarvy",
+ ["de"]="farbewert",
+ ["en"]="colorvalue",
+ ["fr"]="valeurcouleur",
+ ["it"]="valorecolore",
+ ["nl"]="kleurwaarde",
+ ["pe"]="مقداررنگ",
+ ["ro"]="valoareculoare",
+ },
+ ["column"]={
+ ["cs"]="sloupec",
+ ["de"]="spalte",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["comparecolorgroup"]={
+ ["cs"]="porovnejskupinubarev",
+ ["de"]="vergleichefarbengruppe",
+ ["en"]="comparecolorgroup",
+ ["fr"]="comparegroupecouleur",
+ ["it"]="confrontagruppocolori",
+ ["nl"]="vergelijkkleurgroep",
+ ["pe"]="مقایسه‌گروه‌رنگ",
+ ["ro"]="comparagrupculoare",
+ },
+ ["comparepalet"]={
+ ["cs"]="porovnejpaletu",
+ ["de"]="vergleichepalette",
+ ["en"]="comparepalet",
+ ["fr"]="comparepalette",
+ ["it"]="confrontatavolozza",
+ ["nl"]="vergelijkpalet",
+ ["pe"]="لوح‌مقایسه",
+ ["ro"]="comparapaleta",
+ },
+ ["completepagenumber"]={
+ ["cs"]="completepagenumber",
+ ["de"]="completepagenumber",
+ ["en"]="completepagenumber",
+ ["fr"]="completenumeropage",
+ ["it"]="numeropaginacompleto",
+ ["nl"]="volledigepaginanummer",
+ ["pe"]="شماره‌صفحه‌کامل",
+ ["ro"]="completeazanumarpagina",
+ },
+ ["completeregister"]={
+ ["cs"]="completeregister",
+ ["de"]="completeregister",
+ ["en"]="completeregister",
+ ["fr"]="completeregistre",
+ ["it"]="completeregister",
+ ["nl"]="volledigregister",
+ ["pe"]="ثبت‌کامل",
+ ["ro"]="completeregister",
+ },
+ ["component"]={
+ ["cs"]="komponenta",
+ ["de"]="komponente",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="componenet",
+ ["nl"]="onderdeel",
+ ["pe"]="مولفه",
+ ["ro"]="componenta",
+ },
+ ["convertnumber"]={
+ ["cs"]="konvertujcislo",
+ ["de"]="konvertierezahl",
+ ["en"]="convertnumber",
+ ["fr"]="convertitnumero",
+ ["it"]="convertinumero",
+ ["nl"]="converteernummer",
+ ["pe"]="شماره‌مبدل",
+ ["ro"]="convertestenumar",
+ },
+ ["copyfield"]={
+ ["cs"]="kopirujpole",
+ ["de"]="kopierefeld",
+ ["en"]="copyfield",
+ ["fr"]="copitchamp",
+ ["it"]="copiacampo",
+ ["nl"]="copieerveld",
+ ["pe"]="میدان‌کپی",
+ ["ro"]="copiazacamp",
+ },
+ ["correctwhitespace"]={
+ ["cs"]="korekcebilehomista",
+ ["de"]="korrigierezwischenraum",
+ ["en"]="correctwhitespace",
+ ["fr"]="corrigeespaceblanc",
+ ["it"]="correggispaziobianco",
+ ["nl"]="corrigeerwitruimte",
+ ["pe"]="فضای‌سفیدصحیح",
+ ["ro"]="corecteazaspatiualb",
+ },
+ ["coupledocument"]={
+ ["cs"]="propojenydokument",
+ ["de"]="verknuepfedokument",
+ ["en"]="coupledocument",
+ ["fr"]="coupledocument",
+ ["it"]="accoppiadocumento",
+ ["nl"]="koppeldocument",
+ ["pe"]="نوشتارزوج",
+ ["ro"]="cupleazadocument",
+ },
+ ["couplemarking"]={
+ ["cs"]="propojeneznaceni",
+ ["de"]="verknuepfebeschriftung",
+ ["en"]="couplemarking",
+ ["fr"]="couplemarquage",
+ ["it"]="accoppiamarcatura",
+ ["nl"]="koppelmarkering",
+ ["pe"]="نشانه‌گذاری‌زوج",
+ ["ro"]="cupleazamarcaje",
+ },
+ ["couplepage"]={
+ ["cs"]="parovastrana",
+ ["de"]="doppelseite",
+ ["en"]="couplepage",
+ ["fr"]="pagedouble",
+ ["it"]="accoppiapagina",
+ ["nl"]="koppelpagina",
+ ["pe"]="صفحه‌زوج",
+ ["ro"]="paginadubla",
+ },
+ ["couplepaper"]={
+ ["cs"]="dvoustrannypapir",
+ ["de"]="doppelseitigespapier",
+ ["en"]="couplepaper",
+ ["fr"]="couplepapier",
+ ["it"]="accoppiacarta",
+ ["nl"]="koppelpapier",
+ ["pe"]="کاغذزوج",
+ ["ro"]="hartiedubla",
+ },
+ ["coupleregister"]={
+ ["cs"]="propojenyrejstrik",
+ ["de"]="verknuepfregister",
+ ["en"]="coupleregister",
+ ["fr"]="coupleregistre",
+ ["it"]="accoppiaregistro",
+ ["nl"]="koppelregister",
+ ["pe"]="ثبت‌زوج",
+ ["ro"]="cupleazaregistru",
+ },
+ ["crlf"]={
+ ["cs"]="crlf",
+ ["de"]="crlf",
+ ["en"]="crlf",
+ ["fr"]="crlf",
+ ["it"]="crlf",
+ ["nl"]="crlf",
+ ["pe"]="crlf",
+ ["ro"]="crlf",
+ },
+ ["currentdate"]={
+ ["cs"]="aktualnidatum",
+ ["de"]="heutigesdatum",
+ ["en"]="currentdate",
+ ["fr"]="datecourante",
+ ["it"]="datadioggi",
+ ["nl"]="huidigedatum",
+ ["pe"]="تاریخ‌جاری",
+ ["ro"]="datacurenta",
+ },
+ ["currentheadnumber"]={
+ ["cs"]="aktualnicislonadpisu",
+ ["de"]="heutigeskopfnummer",
+ ["en"]="currentheadnumber",
+ ["fr"]="numerotetecourant",
+ ["it"]="numerotestacorrente",
+ ["nl"]="huidigekopnummer",
+ ["pe"]="شماره‌سرجاری",
+ ["ro"]="numartitlucurent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضای‌برش",
+ ["ro"]="cutspace",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["decouplemarking"]={
+ ["cs"]="rozpojeneznaceni",
+ ["de"]="entknuepfebeschriftung",
+ ["en"]="decouplemarking",
+ ["fr"]="decouplemarquage",
+ ["it"]="separamarcatura",
+ ["nl"]="ontkoppelmarkering",
+ ["pe"]="جداسازی‌نشانه‌گذاری",
+ ["ro"]="decupleazamarcaje",
+ },
+ ["decrementnumber"]={
+ ["cs"]="decrementnumber",
+ ["de"]="decrementnumber",
+ ["en"]="decrementnumber",
+ ["fr"]="decrementenumero",
+ ["it"]="decrementnumber",
+ ["nl"]="verlaagnummer",
+ ["pe"]="شماره‌کاهش",
+ ["ro"]="decrementnumber",
+ },
+ ["define"]={
+ ["cs"]="definuj",
+ ["de"]="definieren",
+ ["en"]="define",
+ ["fr"]="definit",
+ ["it"]="definisci",
+ ["nl"]="definieer",
+ ["pe"]="تعریف",
+ ["ro"]="defineste",
+ },
+ ["defineaccent"]={
+ ["cs"]="definujakcent",
+ ["de"]="definiereakzent",
+ ["en"]="defineaccent",
+ ["fr"]="definitaccent",
+ ["it"]="definisciaccento",
+ ["nl"]="definieeraccent",
+ ["pe"]="تعریف‌لهجه",
+ ["ro"]="definesteaccent",
+ },
+ ["defineblank"]={
+ ["cs"]="definujpreskok",
+ ["de"]="definiereblanko",
+ ["en"]="defineblank",
+ ["fr"]="definitvide",
+ ["it"]="definiscirigovuoto",
+ ["nl"]="definieerblanko",
+ ["pe"]="تعریف‌خالی",
+ ["ro"]="definesteblanc",
+ },
+ ["defineblock"]={
+ ["cs"]="definujblok",
+ ["de"]="definiereblock",
+ ["en"]="defineblock",
+ ["fr"]="definitbloc",
+ ["it"]="definisciblocco",
+ ["nl"]="definieerblok",
+ ["pe"]="تعریف‌بلوک",
+ ["ro"]="definestebloc",
+ },
+ ["definebodyfont"]={
+ ["cs"]="definujzakladnifont",
+ ["de"]="definierefliesstext",
+ ["en"]="definebodyfont",
+ ["fr"]="definitpolicecorps",
+ ["it"]="definiscifontdeltesto",
+ ["nl"]="definieerkorps",
+ ["pe"]="تعریف‌قلم‌متن",
+ ["ro"]="definestefonttext",
+ },
+ ["definebodyfontenvironment"]={
+ ["cs"]="definujprostredizakladnihofontu",
+ ["de"]="definierefliesstextumgebung",
+ ["en"]="definebodyfontenvironment",
+ ["fr"]="definitenvironnementpolicecorps",
+ ["it"]="definisciambientefontdeltesto",
+ ["nl"]="definieerkorpsomgeving",
+ ["pe"]="تعریف‌محیط‌قلم‌بدنه",
+ ["ro"]="definestemediulfonttext",
+ },
+ ["definebuffer"]={
+ ["cs"]="definujbuffer",
+ ["de"]="definierepuffer",
+ ["en"]="definebuffer",
+ ["fr"]="definitbuffer",
+ ["it"]="definiscibuffer",
+ ["nl"]="definieerbuffer",
+ ["pe"]="تعریف‌بافر",
+ ["ro"]="definestebuffer",
+ },
+ ["definecharacter"]={
+ ["cs"]="definujznak",
+ ["de"]="definierezeichen",
+ ["en"]="definecharacter",
+ ["fr"]="definicaractere",
+ ["it"]="definiscicarattere",
+ ["nl"]="definieerkarakter",
+ ["pe"]="تعریف‌حرف",
+ ["ro"]="definestecaracter",
+ },
+ ["definecolor"]={
+ ["cs"]="definujbarvu",
+ ["de"]="definierefarbe",
+ ["en"]="definecolor",
+ ["fr"]="definitcouleur",
+ ["it"]="definiscicolore",
+ ["nl"]="definieerkleur",
+ ["pe"]="تعریف‌رنگ",
+ ["ro"]="definesteculoare",
+ },
+ ["definecolorgroup"]={
+ ["cs"]="definujskupinubarev",
+ ["de"]="definierefarbengruppe",
+ ["en"]="definecolorgroup",
+ ["fr"]="definitgroupecouleur",
+ ["it"]="definiscigruppocolori",
+ ["nl"]="definieerkleurgroep",
+ ["pe"]="تعریف‌گروه‌رنگ",
+ ["ro"]="definestegrupculori",
+ },
+ ["definecolumnbreak"]={
+ ["cs"]="definecolumnbreak",
+ ["de"]="definecolumnbreak",
+ ["en"]="definecolumnbreak",
+ ["fr"]="definitsautdecolonne",
+ ["it"]="definecolumnbreak",
+ ["nl"]="definieerkolomovergang",
+ ["pe"]="تعریف‌شکستن‌ستون",
+ ["ro"]="definecolumnbreak",
+ },
+ ["definecolumnset"]={
+ ["cs"]="definecolumnset",
+ ["de"]="definecolumnset",
+ ["en"]="definecolumnset",
+ ["fr"]="definitjeucolonne",
+ ["it"]="definiscigruppocolonne",
+ ["nl"]="definieerkolomgroep",
+ ["pe"]="تعریف‌مجموعه‌ستون",
+ ["ro"]="definecolumnset",
+ },
+ ["definecombination"]={
+ ["cs"]="definecombination",
+ ["de"]="definecombination",
+ ["en"]="definecombination",
+ ["fr"]="definecombination",
+ ["it"]="definecombination",
+ ["nl"]="definieercombinatie",
+ ["pe"]="تعریف‌ترکیب",
+ ["ro"]="definecombination",
+ },
+ ["definecombinedlist"]={
+ ["cs"]="definujkombinovanyseznam",
+ ["de"]="definierezusammengestellteliste",
+ ["en"]="definecombinedlist",
+ ["fr"]="definitlisteimbriquee",
+ ["it"]="definiscielencocombinato",
+ ["nl"]="definieersamengesteldelijst",
+ ["pe"]="تعریف‌لیست‌ترکیبی",
+ ["ro"]="definestelistacombinata",
+ },
+ ["definecommand"]={
+ ["cs"]="definujprikaz",
+ ["de"]="definierebefehl",
+ ["en"]="definecommand",
+ ["fr"]="definitcommande",
+ ["it"]="definiscicomando",
+ ["nl"]="definieercommando",
+ ["pe"]="تعریف‌فرمان",
+ ["ro"]="definestecomanda",
+ },
+ ["defineconversion"]={
+ ["cs"]="definujkonverzi",
+ ["de"]="definierekonversion",
+ ["en"]="defineconversion",
+ ["fr"]="definitconversion",
+ ["it"]="definisciconversione",
+ ["nl"]="definieerconversie",
+ ["pe"]="تعریف‌تبدیل",
+ ["ro"]="definesteconversie",
+ },
+ ["definedescription"]={
+ ["cs"]="definujpopis",
+ ["de"]="definierebeschreibung",
+ ["en"]="definedescription",
+ ["fr"]="definitdescription",
+ ["it"]="definiscidescrizione",
+ ["nl"]="doordefinieren",
+ ["pe"]="تعریف‌شرح",
+ ["ro"]="definestedescriere",
+ },
+ ["defineenumeration"]={
+ ["cs"]="definujvycet",
+ ["de"]="definierenummerierung",
+ ["en"]="defineenumeration",
+ ["fr"]="definitenumeration",
+ ["it"]="definiscienumerazione",
+ ["nl"]="doornummeren",
+ ["pe"]="تعریف‌شماره‌بندی",
+ ["ro"]="definesteenumerare",
+ },
+ ["definefield"]={
+ ["cs"]="definujpole",
+ ["de"]="definierefeld",
+ ["en"]="definefield",
+ ["fr"]="definitchamp",
+ ["it"]="definiscicampo",
+ ["nl"]="definieerveld",
+ ["pe"]="تعریف‌میدان",
+ ["ro"]="definestecamp",
+ },
+ ["definefieldstack"]={
+ ["cs"]="definujzasobnikpoli",
+ ["de"]="definierefeldstapel",
+ ["en"]="definefieldstack",
+ ["fr"]="definitpilechamp",
+ ["it"]="definiscistackcampi",
+ ["nl"]="definieerveldstapel",
+ ["pe"]="تعریف‌توده‌میدان",
+ ["ro"]="definestestivacampuri",
+ },
+ ["definefiguresymbol"]={
+ ["cs"]="definujobrazeksymbol",
+ ["de"]="definiereabbsymbol",
+ ["en"]="definefiguresymbol",
+ ["fr"]="definitsymbolefigure",
+ ["it"]="definiscifigurasimbolo",
+ ["nl"]="definieerfiguursymbool",
+ ["pe"]="تعریف‌نمادشکل",
+ ["ro"]="definestesimbolfigura",
+ },
+ ["definefloat"]={
+ ["cs"]="definujplvouciobjekt",
+ ["de"]="definieregleitobjekt",
+ ["en"]="definefloat",
+ ["fr"]="definitflottant",
+ ["it"]="definiscioggettomobile",
+ ["nl"]="definieerplaatsblok",
+ ["pe"]="تعریف‌شناور",
+ ["ro"]="definestefloat",
+ },
+ ["definefont"]={
+ ["cs"]="definujfont",
+ ["de"]="definiereschrift",
+ ["en"]="definefont",
+ ["fr"]="definitpolice",
+ ["it"]="definiscifont",
+ ["nl"]="definieerfont",
+ ["pe"]="تعریف‌قلم",
+ ["ro"]="definestefont",
+ },
+ ["definefontstyle"]={
+ ["cs"]="definujstylfontu",
+ ["de"]="definiereschriftstil",
+ ["en"]="definefontstyle",
+ ["fr"]="definitstylepolice",
+ ["it"]="definiscistilefont",
+ ["nl"]="definieerfontstijl",
+ ["pe"]="تعریف‌سبک‌قلم",
+ ["ro"]="definestestilfont",
+ },
+ ["definefontsynonym"]={
+ ["cs"]="definujsynonumumfontu",
+ ["de"]="defineschriftsynonym",
+ ["en"]="definefontsynonym",
+ ["fr"]="definitsynonymepolice",
+ ["it"]="definiscisinonimofont",
+ ["nl"]="definieerfontsynoniem",
+ ["pe"]="تعریف‌مترادف‌قلم",
+ ["ro"]="definestesinonimfont",
+ },
+ ["defineframed"]={
+ ["cs"]="definujoramovani",
+ ["de"]="definiereumrahmt",
+ ["en"]="defineframed",
+ ["fr"]="defineframed",
+ ["it"]="definisciincorniciato",
+ ["nl"]="definieeromlijnd",
+ ["pe"]="تعریف‌قالبی",
+ ["ro"]="definesteinconjurare",
+ },
+ ["defineframedtext"]={
+ ["cs"]="definujoramovanytext",
+ ["de"]="definiereumrahmtertext",
+ ["en"]="defineframedtext",
+ ["fr"]="defineframedtext",
+ ["it"]="definiscitestoincorniciato",
+ ["nl"]="definieerkadertekst",
+ ["pe"]="تعریف‌متن‌قالبی",
+ ["ro"]="definestetextinconjurat",
+ },
+ ["definehbox"]={
+ ["cs"]="definujhbox",
+ ["de"]="definierehbox",
+ ["en"]="definehbox",
+ ["fr"]="definithbox",
+ ["it"]="definiscihbox",
+ ["nl"]="definieerhbox",
+ ["pe"]="تعریف‌جعبه‌‌افقی",
+ ["ro"]="definestehbox",
+ },
+ ["definehead"]={
+ ["cs"]="definujnadpis",
+ ["de"]="definiereueberschrift",
+ ["en"]="definehead",
+ ["fr"]="definittete",
+ ["it"]="definiscitesta",
+ ["nl"]="definieerkop",
+ ["pe"]="تعریف‌سر",
+ ["ro"]="definesteantet",
+ },
+ ["defineindentedtext"]={
+ ["en"]="defineindentedtext",
+ ["nl"]="definieeringesprongentext",
+ },
+ ["defineinmargin"]={
+ ["cs"]="defineinmargin",
+ ["de"]="defineinmargin",
+ ["en"]="defineinmargin",
+ ["fr"]="definitdansmarge",
+ ["it"]="defineinmargin",
+ ["nl"]="definieerinmarge",
+ ["pe"]="تعریف‌درون‌حاشیه",
+ ["ro"]="defineinmargin",
+ },
+ ["defineinteractionmenu"]={
+ ["cs"]="definujinterakcnimenu",
+ ["de"]="definiereinteraktionsmenue",
+ ["en"]="defineinteractionmenu",
+ ["fr"]="definitmenuinteraction",
+ ["it"]="definiscimenuinterazione",
+ ["nl"]="definieerinteractiemenu",
+ ["pe"]="تعریف‌منوی‌پانل",
+ ["ro"]="definestemeniuinteractiune",
+ },
+ ["defineitemgroup"]={
+ ["cs"]="defineitemgroup",
+ ["de"]="defineitemgroup",
+ ["en"]="defineitemgroup",
+ ["fr"]="defineitemgroup",
+ ["it"]="defineitemgroup",
+ ["nl"]="definieeritemgroep",
+ ["pe"]="تعریف‌گروه‌آیتم",
+ ["ro"]="defineitemgroup",
+ },
+ ["definelabel"]={
+ ["cs"]="definujpopisek",
+ ["de"]="definierelabel",
+ ["en"]="definelabel",
+ ["fr"]="definitetiquette",
+ ["it"]="definiscietichetta",
+ ["nl"]="doorlabelen",
+ ["pe"]="تعریف‌برچسب",
+ ["ro"]="definesteeticheta",
+ },
+ ["definelayer"]={
+ ["cs"]="definelayer",
+ ["de"]="definelayer",
+ ["en"]="definelayer",
+ ["fr"]="definitcalque",
+ ["it"]="definelayer",
+ ["nl"]="definieerlayer",
+ ["pe"]="تعریف‌لایه",
+ ["ro"]="definelayer",
+ },
+ ["definelayout"]={
+ ["cs"]="definelayout",
+ ["de"]="definelayout",
+ ["en"]="definelayout",
+ ["fr"]="definitdisposition",
+ ["it"]="definiscilayout",
+ ["nl"]="definieerlayout",
+ ["pe"]="تعریف‌طرح‌بندی",
+ ["ro"]="definelayout",
+ },
+ ["definelist"]={
+ ["cs"]="definujseznam",
+ ["de"]="definiereliste",
+ ["en"]="definelist",
+ ["fr"]="definitliste",
+ ["it"]="definiscielenco",
+ ["nl"]="definieerlijst",
+ ["pe"]="تعریف‌لیست",
+ ["ro"]="definestelista",
+ },
+ ["definelogo"]={
+ ["cs"]="definujlogo",
+ ["de"]="definierelogo",
+ ["en"]="definelogo",
+ ["fr"]="definitlogo",
+ ["it"]="definiscilogo",
+ ["nl"]="definieerbeeldmerk",
+ ["pe"]="تعریف‌آرم",
+ ["ro"]="definestelogo",
+ },
+ ["definemainfield"]={
+ ["cs"]="definujhlavnipole",
+ ["de"]="definierehauptfeld",
+ ["en"]="definemainfield",
+ ["fr"]="definitchampprincipal",
+ ["it"]="definiscicampoprincipale",
+ ["nl"]="definieerhoofdveld",
+ ["pe"]="تعریف‌میدان‌اصلی",
+ ["ro"]="definestecampprincipal",
+ },
+ ["definemakeup"]={
+ ["cs"]="definujupravu",
+ ["de"]="definiereumbruch",
+ ["en"]="definemakeup",
+ ["fr"]="definitmakeup",
+ ["it"]="definiscimakeup",
+ ["nl"]="definieeropmaak",
+ ["pe"]="تعریف‌آرایش",
+ ["ro"]="definestemakeup",
+ },
+ ["definemarking"]={
+ ["cs"]="definujznaceni",
+ ["de"]="definierebeschriftung",
+ ["en"]="definemarking",
+ ["fr"]="definitmarquage",
+ ["it"]="definiscimarcatura",
+ ["nl"]="definieermarkering",
+ ["pe"]="تعریف‌نشانه‌گذاری",
+ ["ro"]="definestemarcaje",
+ },
+ ["definemathalignment"]={
+ ["cs"]="definemathalignment",
+ ["de"]="definemathalignment",
+ ["en"]="definemathalignment",
+ ["fr"]="definemathalignment",
+ ["it"]="definemathalignment",
+ ["nl"]="definieerwiskundeuitlijnen",
+ ["pe"]="تعریف‌تنظیم‌ریاضی",
+ ["ro"]="definemathalignment",
+ },
+ ["defineoutput"]={
+ ["cs"]="definujvystup",
+ ["de"]="defineoutput",
+ ["en"]="defineoutput",
+ ["fr"]="definitsortie",
+ ["it"]="definiscioutput",
+ ["nl"]="definieeruitvoer",
+ ["pe"]="تعریف‌خروجی",
+ ["ro"]="definesteoutput",
+ },
+ ["defineoverlay"]={
+ ["cs"]="definujprekryv",
+ ["de"]="definiereoverlay",
+ ["en"]="defineoverlay",
+ ["fr"]="definitrevetement",
+ ["it"]="definiscisovrapposizione",
+ ["nl"]="definieeroverlay",
+ ["pe"]="تعریف‌پوشش",
+ ["ro"]="definesteoverlay",
+ },
+ ["definepagebreak"]={
+ ["cs"]="definepagebreak",
+ ["de"]="definepagebreak",
+ ["en"]="definepagebreak",
+ ["fr"]="definitsautdepage",
+ ["it"]="definepagebreak",
+ ["nl"]="definieerpaginaovergang",
+ ["pe"]="تعریف‌شکست‌صفحه",
+ ["ro"]="definepagebreak",
+ },
+ ["definepalet"]={
+ ["cs"]="definujpaletu",
+ ["de"]="definierepalette",
+ ["en"]="definepalet",
+ ["fr"]="definitpalette",
+ ["it"]="definiscitavolozza",
+ ["nl"]="definieerpalet",
+ ["pe"]="تعریف‌لوح",
+ ["ro"]="definestepaleta",
+ },
+ ["definepapersize"]={
+ ["cs"]="definujvelikostpapiru",
+ ["de"]="definierepapierformat",
+ ["en"]="definepapersize",
+ ["fr"]="definittaillepapier",
+ ["it"]="definiscidimensionicarta",
+ ["nl"]="definieerpapierformaat",
+ ["pe"]="تعریف‌اندازه‌برگ",
+ ["ro"]="definestedimensiunehartie",
+ },
+ ["defineparagraphs"]={
+ ["cs"]="definujodstavce",
+ ["de"]="definiereabsaetze",
+ ["en"]="defineparagraphs",
+ ["fr"]="definitparagraphes",
+ ["it"]="definiscicapoversi",
+ ["nl"]="definieeralineas",
+ ["pe"]="تعریف‌پاراگرافها",
+ ["ro"]="definesteparagraf",
+ },
+ ["defineplacement"]={
+ ["cs"]="defineplacement",
+ ["de"]="defineplacement",
+ ["en"]="defineplacement",
+ ["fr"]="defineplacement",
+ ["it"]="defineplacement",
+ ["nl"]="definieerplaats",
+ ["pe"]="تعریف‌جانشانی",
+ ["ro"]="defineplacement",
+ },
+ ["defineprofile"]={
+ ["cs"]="definujprofil",
+ ["de"]="definiereprofil",
+ ["en"]="defineprofile",
+ ["fr"]="definitprofil",
+ ["it"]="definisciprofilo",
+ ["nl"]="definieerprofiel",
+ ["pe"]="تعریف‌پروفایل",
+ ["ro"]="definesteprofil",
+ },
+ ["defineprogram"]={
+ ["cs"]="definujprogram",
+ ["de"]="definiereprogramme",
+ ["en"]="defineprogram",
+ ["fr"]="definitprogramme",
+ ["it"]="definisciprogramma",
+ ["nl"]="definieerprogramma",
+ ["pe"]="تعریف‌برنامه",
+ ["ro"]="definesteprogram",
+ },
+ ["definerawfont"]={
+ ["cs"]="definerawfont",
+ ["de"]="definerawfont",
+ ["en"]="definerawfont",
+ ["fr"]="definitpolicebrute",
+ ["it"]="definiscifontgrezzo",
+ ["nl"]="definerawfont",
+ ["pe"]="تعریف‌قلم‌خام",
+ ["ro"]="definestefontraw",
+ },
+ ["definereference"]={
+ ["cs"]="definujodkaz",
+ ["de"]="definierereferenz",
+ ["en"]="definereference",
+ ["fr"]="definitreference",
+ ["it"]="definisciriferimento",
+ ["nl"]="definieerreferentie",
+ ["pe"]="تعریف‌مرجع",
+ ["ro"]="definestereferinte",
+ },
+ ["definereferenceformat"]={
+ ["cs"]="definujformatodkazu",
+ ["de"]="definierereferenzformat",
+ ["en"]="definereferenceformat",
+ ["fr"]="definitformatreference",
+ ["it"]="definisciformatoriferimento",
+ ["nl"]="definieerreferentieformaat",
+ ["pe"]="تعریف‌شمایل‌مرجع",
+ ["ro"]="definesteformatreferinte",
+ },
+ ["definereferencelist"]={
+ ["cs"]="definujseznamodkazu",
+ ["de"]="definierereferenzliste",
+ ["en"]="definereferencelist",
+ ["fr"]="definitlistereference",
+ ["it"]="definiscilistariferimenti",
+ ["nl"]="definieerreferentielijst",
+ ["pe"]="تعریف‌لیست‌مرجع",
+ ["ro"]="definestelistareferinte",
+ },
+ ["defineregister"]={
+ ["cs"]="definujrejstrik",
+ ["de"]="definiereregister",
+ ["en"]="defineregister",
+ ["fr"]="definitregistre",
+ ["it"]="definisciregistro",
+ ["nl"]="definieerregister",
+ ["pe"]="تعریف‌ثبت",
+ ["ro"]="definesteregistru",
+ },
+ ["definerule"]={
+ ["cs"]="definerule",
+ ["de"]="definerule",
+ ["en"]="definerule",
+ ["fr"]="definitregle",
+ ["it"]="definiscilinea",
+ ["nl"]="definieerlijn",
+ ["pe"]="تعریف‌خط‌حائل",
+ ["ro"]="definesterigla",
+ },
+ ["definesection"]={
+ ["cs"]="definujsekci",
+ ["de"]="definiereabschnitt",
+ ["en"]="definesection",
+ ["fr"]="definitsection",
+ ["it"]="definiscisezione",
+ ["nl"]="definieersectie",
+ ["pe"]="تعریف‌بخش",
+ ["ro"]="definestesectiune",
+ },
+ ["definesectionblock"]={
+ ["cs"]="definujbloksekce",
+ ["de"]="definiereabschnittsblock",
+ ["en"]="definesectionblock",
+ ["fr"]="definitblocsection",
+ ["it"]="definiscibloccosezione",
+ ["nl"]="definieersectieblok",
+ ["pe"]="تعریف‌بلوک‌بخش",
+ ["ro"]="definesteblocsectiune",
+ },
+ ["definesorting"]={
+ ["cs"]="definujtrideni",
+ ["de"]="definieresortieren",
+ ["en"]="definesorting",
+ ["fr"]="definittri",
+ ["it"]="definisciordinamento",
+ ["nl"]="definieersorteren",
+ ["pe"]="تعریف‌ترتیب",
+ ["ro"]="definestesortare",
+ },
+ ["definestartstop"]={
+ ["cs"]="definujstartstop",
+ ["de"]="definierestartstop",
+ ["en"]="definestartstop",
+ ["fr"]="definitdemarrestoppe",
+ ["it"]="definisciiniziatermina",
+ ["nl"]="definieerstartstop",
+ ["pe"]="تعریف‌شروع‌پایان",
+ ["ro"]="definestestartstop",
+ },
+ ["definestyle"]={
+ ["cs"]="definujstyl",
+ ["de"]="definierestil",
+ ["en"]="definestyle",
+ ["fr"]="definitstyle",
+ ["it"]="definiscistile",
+ ["nl"]="definieerletter",
+ ["pe"]="تعریف‌سبک",
+ ["ro"]="definestestil",
+ },
+ ["definesubfield"]={
+ ["cs"]="definujpodpole",
+ ["de"]="definieresubfeld",
+ ["en"]="definesubfield",
+ ["fr"]="definitsouschamp",
+ ["it"]="definiscisottocampo",
+ ["nl"]="definieersubveld",
+ ["pe"]="تعریف‌زیرمیدان",
+ ["ro"]="definestesubcamp",
+ },
+ ["definesymbol"]={
+ ["cs"]="definujsymbol",
+ ["de"]="definieresymbol",
+ ["en"]="definesymbol",
+ ["fr"]="definitsymbole",
+ ["it"]="definiscisimbolo",
+ ["nl"]="definieersymbool",
+ ["pe"]="تعریف‌نماد",
+ ["ro"]="definestesimbol",
+ },
+ ["definesynonyms"]={
+ ["cs"]="definujsynonyma",
+ ["de"]="definieresynonyme",
+ ["en"]="definesynonyms",
+ ["fr"]="definitsynonymes",
+ ["it"]="definiscisinonimi",
+ ["nl"]="definieersynoniemen",
+ ["pe"]="تعریف‌مترادفها",
+ ["ro"]="definestesinonim",
+ },
+ ["definetabletemplate"]={
+ ["cs"]="definujsablonutabulky",
+ ["de"]="definieretabellenvorlage",
+ ["en"]="definetabletemplate",
+ ["fr"]="definittrametableau",
+ ["it"]="definiscimodellotabella",
+ ["nl"]="definieertabelvorm",
+ ["pe"]="تعریف‌الگوی‌جدول",
+ ["ro"]="definestesablontabel",
+ },
+ ["definetabulate"]={
+ ["cs"]="definujtabelaci",
+ ["de"]="definieretabulator",
+ ["en"]="definetabulate",
+ ["fr"]="definittabulation",
+ ["it"]="definiscitabulato",
+ ["nl"]="definieertabulatie",
+ ["pe"]="تعریف‌جدول‌بندی",
+ ["ro"]="definestetabulatori",
+ },
+ ["definetext"]={
+ ["cs"]="definujtext",
+ ["de"]="definieretext",
+ ["en"]="definetext",
+ ["fr"]="definittexte",
+ ["it"]="definiscitesto",
+ ["nl"]="definieertekst",
+ ["pe"]="تعریف‌متن",
+ ["ro"]="definestetext",
+ },
+ ["definetextbackground"]={
+ ["en"]="definetextbackground",
+ ["nl"]="definieertekstachtergrond",
+ },
+ ["definetextposition"]={
+ ["cs"]="definetextposition",
+ ["de"]="definetextposition",
+ ["en"]="definetextposition",
+ ["fr"]="definitpositiontexte",
+ ["it"]="definisciposizionetesto",
+ ["nl"]="definieertekstpositie",
+ ["pe"]="تعریف‌مکان‌متن",
+ ["ro"]="definestepozitietext",
+ },
+ ["definetextvariable"]={
+ ["cs"]="definetextvariable",
+ ["de"]="definetextvariable",
+ ["en"]="definetextvariable",
+ ["fr"]="definitvariabletexte",
+ ["it"]="definiscivariabiletesto",
+ ["nl"]="definieertekstvariabele",
+ ["pe"]="تعریف‌متغیرمتن",
+ ["ro"]="definestevariabilatext",
+ },
+ ["definetype"]={
+ ["cs"]="definetype",
+ ["de"]="definetype",
+ ["en"]="definetype",
+ ["fr"]="definittype",
+ ["it"]="definiscitype",
+ ["nl"]="definieertype",
+ ["pe"]="تعریف‌تایپ",
+ ["ro"]="definetype",
+ },
+ ["definetyping"]={
+ ["cs"]="definujopis",
+ ["de"]="definieretippen",
+ ["en"]="definetyping",
+ ["fr"]="definitdactylo",
+ ["it"]="definiscityping",
+ ["nl"]="definieertypen",
+ ["pe"]="تعریف‌تایپ‌کردن",
+ ["ro"]="definestetyping",
+ },
+ ["defineversion"]={
+ ["cs"]="definujverzi",
+ ["de"]="definiereversion",
+ ["en"]="defineversion",
+ ["fr"]="definitversion",
+ ["it"]="definisciversion",
+ ["nl"]="definieerversie",
+ ["pe"]="تعریف‌نسخه",
+ ["ro"]="definesteversiune",
+ },
+ ["determineheadnumber"]={
+ ["cs"]="stanovcislonadpisu",
+ ["de"]="bestimmekopfnummer",
+ ["en"]="determineheadnumber",
+ ["fr"]="determinenumerotete",
+ ["it"]="determinanumerotesta",
+ ["nl"]="bepaalkopnummer",
+ ["pe"]="تعیین‌شماره‌سر",
+ ["ro"]="determinanumartitlu",
+ },
+ ["determinelistcharacteristics"]={
+ ["cs"]="stanovcharakteristickuseznamu",
+ ["de"]="bestimmelistencharakeristika",
+ ["en"]="determinelistcharacteristics",
+ ["fr"]="determinecaracteristiqueliste",
+ ["it"]="determinacarattersticheelenco",
+ ["nl"]="bepaallijstkenmerken",
+ ["pe"]="تعیین‌مشخصات‌لیست",
+ ["ro"]="determinacaracteristicilelistei",
+ },
+ ["determineregistercharacteristics"]={
+ ["cs"]="urcicharakteristikurejstriku",
+ ["de"]="bestimmeregistercharakteristika",
+ ["en"]="determineregistercharacteristics",
+ ["fr"]="determinecaracteristiquesregistre",
+ ["it"]="determinacaratteristicheregistro",
+ ["nl"]="bepaalregisterkenmerken",
+ ["pe"]="تعیین‌مشخصات‌ثبت",
+ ["ro"]="determinacaracteristiciregistru",
+ },
+ ["dimension"]={
+ ["cs"]="rozmer",
+ ["de"]="dimension",
+ ["en"]="dimension",
+ ["fr"]="dimension",
+ ["it"]="dimensione",
+ ["nl"]="dimensie",
+ ["pe"]="بعد",
+ ["ro"]="dimensiune",
+ },
+ ["disableinteractionmenu"]={
+ ["cs"]="zablokujinterakcnimenu",
+ ["de"]="inaktiviereinteraktionsmenue",
+ ["en"]="disableinteractionmenu",
+ ["fr"]="inhibemenuinteraction",
+ ["it"]="disabilitamenuinterazione",
+ ["nl"]="blokkeerinteractiemenu",
+ ["pe"]="ازکارانداختن‌منوی‌پانل",
+ ["ro"]="dezactiveazameniuinteractiune",
+ },
+ ["domicile"]={
+ ["cs"]="bydliste",
+ ["de"]="wohnort",
+ ["en"]="domicile",
+ ["fr"]="domicile",
+ ["it"]="domicilio",
+ ["nl"]="woonplaats",
+ ["pe"]="مسکن",
+ ["ro"]="domiciliu",
+ },
+ ["donttest"]={
+ ["cs"]="zadnytest",
+ ["de"]="keintest",
+ ["en"]="donttest",
+ ["fr"]="sanstest",
+ ["it"]="notest",
+ ["nl"]="geentest",
+ ["pe"]="امتحان‌نکن",
+ ["ro"]="nutesta",
+ },
+ ["edgedistance"]={
+ ["cs"]="vzdalenostokraje",
+ ["de"]="randabstand",
+ ["en"]="edgedistance",
+ ["fr"]="distancebord",
+ ["it"]="distanzabordo",
+ ["nl"]="randafstand",
+ ["pe"]="فاصله‌لبه",
+ ["ro"]="distantacolt",
+ },
+ ["edgewidth"]={
+ ["cs"]="sirkaokraje",
+ ["de"]="randbreite",
+ ["en"]="edgewidth",
+ ["fr"]="largeurbord",
+ ["it"]="ampiezzabordo",
+ ["nl"]="randbreedte",
+ ["pe"]="عرض‌لبه",
+ ["ro"]="latimecolturi",
+ },
+ ["emptylines"]={
+ ["cs"]="emptylines",
+ ["de"]="emptylines",
+ ["en"]="emptylines",
+ ["fr"]="emptylines",
+ ["it"]="emptylines",
+ ["nl"]="legeregels",
+ ["pe"]="خطها‌خالی",
+ ["ro"]="emptylines",
+ },
+ ["environment"]={
+ ["cs"]="prostredi",
+ ["de"]="umgebung",
+ ["en"]="environment",
+ ["fr"]="environement",
+ ["it"]="ambiente",
+ ["nl"]="omgeving",
+ ["pe"]="محیط",
+ ["ro"]="mediu",
+ },
+ ["externalfigure"]={
+ ["cs"]="externiobraz",
+ ["de"]="externeabbildung",
+ ["en"]="externalfigure",
+ ["fr"]="figureexterne",
+ ["it"]="figuraesterna",
+ ["nl"]="externfiguur",
+ ["pe"]="شکل‌خارجی",
+ ["ro"]="figuraexterna",
+ },
+ ["fact"]={
+ ["cs"]="fakt",
+ ["de"]="geg",
+ ["en"]="fact",
+ ["fr"]="fait",
+ ["it"]="fatto",
+ ["nl"]="geg",
+ ["pe"]="حقیقت",
+ ["ro"]="fact",
+ },
+ ["field"]={
+ ["cs"]="pole",
+ ["de"]="feld",
+ ["en"]="field",
+ ["fr"]="champ",
+ ["it"]="campi",
+ ["nl"]="veld",
+ ["pe"]="میدان",
+ ["ro"]="camp",
+ },
+ ["fieldstack"]={
+ ["cs"]="zasobnikpoli",
+ ["de"]="feldstapel",
+ ["en"]="fieldstack",
+ ["fr"]="pilechamp",
+ ["it"]="stackcampi",
+ ["nl"]="veldstapel",
+ ["pe"]="میدان‌پشته",
+ ["ro"]="stivacampuri",
+ },
+ ["fillinfield"]={
+ ["cs"]="vyplnovepole",
+ ["de"]="ausfuellfeld",
+ ["en"]="fillinfield",
+ ["fr"]="remplitchamp",
+ ["it"]="camporiempimento",
+ ["nl"]="invulveld",
+ ["pe"]="درج‌درمیدان",
+ ["ro"]="campumplere",
+ },
+ ["fillinline"]={
+ ["cs"]="vyplnovyradek",
+ ["de"]="gefuelltezeile",
+ ["en"]="fillinline",
+ ["fr"]="remplitligne",
+ ["it"]="rigariempimento",
+ ["nl"]="invulregel",
+ ["pe"]="درج‌درخط",
+ ["ro"]="linieumplere",
+ },
+ ["fillinrules"]={
+ ["cs"]="vyplnovelinky",
+ ["de"]="gefuelltesrechteck",
+ ["en"]="fillinrules",
+ ["fr"]="remplitlignesreglees",
+ ["it"]="lineeriempimento",
+ ["nl"]="invullijnen",
+ ["pe"]="درج‌درخطها",
+ ["ro"]="rigleumplere",
+ },
+ ["fillintext"]={
+ ["cs"]="vyplnenytext",
+ ["de"]="ausfuelltext",
+ ["en"]="fillintext",
+ ["fr"]="remplittexte",
+ ["it"]="testoriempimento",
+ ["nl"]="invultekst",
+ ["pe"]="درج‌درمتن",
+ ["ro"]="textumplere",
+ },
+ ["fitfield"]={
+ ["cs"]="prizpusobivepole",
+ ["de"]="passendfeld",
+ ["en"]="fitfield",
+ ["fr"]="ajustechamp",
+ ["it"]="adattacampo",
+ ["nl"]="passendveld",
+ ["pe"]="پرکردن‌میدان",
+ ["ro"]="potrivestecamp",
+ },
+ ["fixedspace"]={
+ ["cs"]="tvrdamezera",
+ ["de"]="festesspatium",
+ ["en"]="fixedspace",
+ ["fr"]="espacefixe",
+ ["it"]="spaziofisso",
+ ["nl"]="vastespatie",
+ ["pe"]="فضای‌ثابت",
+ ["ro"]="spatiufixat",
+ },
+ ["fixedspaces"]={
+ ["cs"]="tvrdemezery",
+ ["de"]="festesspatium",
+ ["en"]="fixedspaces",
+ ["fr"]="espacesfixes",
+ ["it"]="spazifissi",
+ ["nl"]="vastespaties",
+ ["pe"]="فضاهای‌ثابت",
+ ["ro"]="spatiifixate",
+ },
+ ["followprofile"]={
+ ["cs"]="dodrzujprofil",
+ ["de"]="folgeprofil",
+ ["en"]="followprofile",
+ ["fr"]="suivantprofil",
+ ["it"]="seguiprofilo",
+ ["nl"]="volgprofiel",
+ ["pe"]="پیروی‌پروفایل",
+ ["ro"]="urmeazaprofil",
+ },
+ ["followprofileversion"]={
+ ["cs"]="dodrzujverziprofilu",
+ ["de"]="folgeprofilversion",
+ ["en"]="followprofileversion",
+ ["fr"]="suivantversionprofil",
+ ["it"]="seguiversioneprofilo",
+ ["nl"]="volgprofielversie",
+ ["pe"]="پیروی‌نسخه‌پروفایل",
+ ["ro"]="urmeazaversiuneprofil",
+ },
+ ["followversion"]={
+ ["cs"]="dodrzujverzi",
+ ["de"]="folgeversion",
+ ["en"]="followversion",
+ ["fr"]="suivantversion",
+ ["it"]="seguiversione",
+ ["nl"]="volgversie",
+ ["pe"]="پیروی‌نسخه",
+ ["ro"]="urmeazaversiune",
+ },
+ ["footerdistance"]={
+ ["cs"]="vzdalenostupati",
+ ["de"]="fusszeileabstand",
+ ["en"]="footerdistance",
+ ["fr"]="distancepdp",
+ ["it"]="distanzapdp",
+ ["nl"]="voetafstand",
+ ["pe"]="فاصله‌ته‌برگ",
+ ["ro"]="distantasubsol",
+ },
+ ["footerheight"]={
+ ["cs"]="vyskaupati",
+ ["de"]="fusszeilenhoehe",
+ ["en"]="footerheight",
+ ["fr"]="hauteurpdp",
+ ["it"]="altezzapdp",
+ ["nl"]="voethoogte",
+ ["pe"]="ارتفاع‌ته‌برگ",
+ ["ro"]="inaltimesubsol",
+ },
+ ["footnote"]={
+ ["cs"]="poznamkapodcarou",
+ ["de"]="fussnote",
+ ["en"]="footnote",
+ ["fr"]="notepdp",
+ ["it"]="notapdp",
+ ["nl"]="voetnoot",
+ ["pe"]="پانوشت",
+ ["ro"]="notasubsol",
+ },
+ ["footnotetext"]={
+ ["cs"]="footnotetext",
+ ["de"]="footnotetext",
+ ["en"]="footnotetext",
+ ["fr"]="textenotepdp",
+ ["it"]="testonotapdp",
+ ["nl"]="voetnoottekst",
+ ["pe"]="متن‌پانوشت",
+ ["ro"]="footnotetext",
+ },
+ ["forceblocks"]={
+ ["cs"]="forceblocks",
+ ["de"]="forceblocks",
+ ["en"]="forceblocks",
+ ["fr"]="forceblocs",
+ ["it"]="forzablocchi",
+ ["nl"]="forceerblokken",
+ ["pe"]="اجباربلوکها",
+ ["ro"]="forteazablocuri",
+ },
+ ["formulanumber"]={
+ ["cs"]="cislorovnice",
+ ["de"]="formelnummer",
+ ["en"]="formulanumber",
+ ["fr"]="numeroformule",
+ ["it"]="numeroformula",
+ ["nl"]="formulenummer",
+ ["pe"]="شماره‌فرمول",
+ ["ro"]="numarformula",
+ },
+ ["fraction"]={
+ ["cs"]="zlomek",
+ ["de"]="bruch",
+ ["en"]="fraction",
+ ["fr"]="fraction",
+ ["it"]="frazione",
+ ["nl"]="breuk",
+ ["pe"]="کسر",
+ ["ro"]="fractie",
+ },
+ ["framed"]={
+ ["cs"]="oramovani",
+ ["de"]="umrahmt",
+ ["en"]="framed",
+ ["fr"]="framed",
+ ["it"]="incorniciato",
+ ["nl"]="omlijnd",
+ ["pe"]="قالبی",
+ ["ro"]="framed",
+ },
+ ["from"]={
+ ["cs"]="zref",
+ ["de"]="von",
+ ["en"]="from",
+ ["fr"]="de",
+ ["it"]="da",
+ ["nl"]="uit",
+ ["pe"]="از",
+ ["ro"]="din",
+ },
+ ["getbuffer"]={
+ ["cs"]="ziskejbuffer",
+ ["de"]="holepuffer",
+ ["en"]="getbuffer",
+ ["fr"]="prendbuffer",
+ ["it"]="prendibuffer",
+ ["nl"]="haalbuffer",
+ ["pe"]="دریافت‌بافر",
+ ["ro"]="adubuffer",
+ },
+ ["getmarking"]={
+ ["cs"]="ziskejznaceni",
+ ["de"]="holebeschriftung",
+ ["en"]="getmarking",
+ ["fr"]="obtientmarquage",
+ ["it"]="prendimarcatura",
+ ["nl"]="haalmarkering",
+ ["pe"]="دریافت‌نشانه",
+ ["ro"]="adumarcaje",
+ },
+ ["getnumber"]={
+ ["cs"]="getnumber",
+ ["de"]="getnumber",
+ ["en"]="getnumber",
+ ["fr"]="getnumber",
+ ["it"]="getnumber",
+ ["nl"]="haalnummer",
+ ["pe"]="دریافت‌شماره",
+ ["ro"]="getnumber",
+ },
+ ["godown"]={
+ ["cs"]="jdidolu",
+ ["de"]="nachunten",
+ ["en"]="godown",
+ ["fr"]="vaenbas",
+ ["it"]="vaigiu",
+ ["nl"]="omlaag",
+ ["pe"]="بروپایین",
+ ["ro"]="injos",
+ },
+ ["goto"]={
+ ["cs"]="jdina",
+ ["de"]="zu",
+ ["en"]="goto",
+ ["fr"]="va",
+ ["it"]="vaia",
+ ["nl"]="naar",
+ ["pe"]="بروبه",
+ ["ro"]="dute",
+ },
+ ["gotobox"]={
+ ["cs"]="jdinabox",
+ ["de"]="zurbox",
+ ["en"]="gotobox",
+ ["fr"]="vaalaboite",
+ ["it"]="vaiabox",
+ ["nl"]="naarbox",
+ ["pe"]="بروبه‌جعبه",
+ ["ro"]="dutebox",
+ },
+ ["gotopage"]={
+ ["cs"]="jdinastranu",
+ ["de"]="zurseite",
+ ["en"]="gotopage",
+ ["fr"]="vaalapage",
+ ["it"]="vaiapagina",
+ ["nl"]="naarpagina",
+ ["pe"]="بروبه‌صفحه",
+ ["ro"]="dutepagina",
+ },
+ ["graycolor"]={
+ ["cs"]="sedabarva",
+ ["de"]="graufarbe",
+ ["en"]="graycolor",
+ ["fr"]="couleurgrise",
+ ["it"]="coloregrigio",
+ ["nl"]="grijskleur",
+ ["pe"]="رنگ‌خاکستری",
+ ["ro"]="culoaregri",
+ },
+ ["greyvalue"]={
+ ["cs"]="hodnotasedi",
+ ["de"]="grauwert",
+ ["en"]="greyvalue",
+ ["fr"]="valeurgris",
+ ["it"]="valoregrigio",
+ ["nl"]="grijswaarde",
+ ["pe"]="مقدارخاکستری",
+ ["ro"]="valoaregri",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gitter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="rooster",
+ ["pe"]="توری",
+ ["ro"]="grid",
+ },
+ ["hairline"]={
+ ["cs"]="vlasovalinka",
+ ["de"]="haarlinie",
+ ["en"]="hairline",
+ ["fr"]="ligneh",
+ ["it"]="capello",
+ ["nl"]="haarlijn",
+ ["pe"]="خط‌مو",
+ ["ro"]="firdepar",
+ },
+ ["head"]={
+ ["cs"]="nadpis",
+ ["de"]="kopf",
+ ["en"]="head",
+ ["fr"]="tete",
+ ["it"]="testa",
+ ["nl"]="kop",
+ ["pe"]="سر",
+ ["ro"]="titlu",
+ },
+ ["headerdistance"]={
+ ["cs"]="vzdalenostzahlavi",
+ ["de"]="kopfzeilenabstand",
+ ["en"]="headerdistance",
+ ["fr"]="distanceentete",
+ ["it"]="distanzaintestazione",
+ ["nl"]="hoofdafstand",
+ ["pe"]="فاصله‌سربرگ",
+ ["ro"]="distantaantet",
+ },
+ ["headerheight"]={
+ ["cs"]="vyskazahlavi",
+ ["de"]="kopfzeilenhoehe",
+ ["en"]="headerheight",
+ ["fr"]="hauteurentete",
+ ["it"]="altezzaintestazione",
+ ["nl"]="hoofdhoogte",
+ ["pe"]="ارتفاع‌سربرگ",
+ ["ro"]="inaltimeantet",
+ },
+ ["headlevel"]={
+ ["cs"]="hlavniuroven",
+ ["de"]="kopfniveau",
+ ["en"]="headlevel",
+ ["fr"]="niveautete",
+ ["it"]="livellotesta",
+ ["nl"]="kopniveau",
+ ["pe"]="مرحله‌سر",
+ ["ro"]="niveltitlu",
+ },
+ ["headnumber"]={
+ ["cs"]="cislonadpisu",
+ ["de"]="kopfnummer",
+ ["en"]="headnumber",
+ ["fr"]="numerotete",
+ ["it"]="numerotesta",
+ ["nl"]="kopnummer",
+ ["pe"]="شماره‌سر",
+ ["ro"]="numartitlu",
+ },
+ ["headsym"]={
+ ["cs"]="headsym",
+ ["de"]="headsym",
+ ["en"]="headsym",
+ ["fr"]="headsym",
+ ["it"]="headsym",
+ ["nl"]="kopsym",
+ ["pe"]="نمادسر",
+ ["ro"]="headsym",
+ },
+ ["headtext"]={
+ ["cs"]="texthlavicky",
+ ["de"]="ueberschrifttext",
+ ["en"]="headtext",
+ ["fr"]="textetete",
+ ["it"]="testoinstestazioni",
+ ["nl"]="koptekst",
+ ["pe"]="متن‌سر",
+ ["ro"]="texttitlu",
+ },
+ ["hideblocks"]={
+ ["cs"]="schovejbloky",
+ ["de"]="verbergebloecke",
+ ["en"]="hideblocks",
+ ["fr"]="cacheblocs",
+ ["it"]="nascondiblocchi",
+ ["nl"]="verbergblokken",
+ ["pe"]="بلوکها‌پنهان",
+ ["ro"]="ascundeblocuri",
+ },
+ ["high"]={
+ ["cs"]="vysoky",
+ ["de"]="hoch",
+ ["en"]="high",
+ ["fr"]="haut",
+ ["it"]="ap",
+ ["nl"]="hoog",
+ ["pe"]="بلند",
+ ["ro"]="inalt",
+ },
+ ["hl"]={
+ ["cs"]="hl",
+ ["de"]="hl",
+ ["en"]="hl",
+ ["fr"]="hl",
+ ["it"]="hl",
+ ["nl"]="hl",
+ ["pe"]="خ‌ا",
+ ["ro"]="hl",
+ },
+ ["immediatebetweenlist"]={
+ ["cs"]="immediatebetweenlist",
+ ["de"]="immediatebetweenlist",
+ ["en"]="immediatebetweenlist",
+ ["fr"]="immediatebetweenlist",
+ ["it"]="immediatebetweenlist",
+ ["nl"]="directtussenlijst",
+ ["pe"]="فوری‌بین‌لیست",
+ ["ro"]="immediatebetweenlist",
+ },
+ ["immediatetolist"]={
+ ["cs"]="immediatetolist",
+ ["de"]="immediatetolist",
+ ["en"]="immediatetolist",
+ ["fr"]="immediatetolist",
+ ["it"]="immediatetolist",
+ ["nl"]="directnaarlijst",
+ ["pe"]="فوری‌به‌لیست",
+ ["ro"]="immediatetolist",
+ },
+ ["in"]={
+ ["cs"]="tref",
+ ["de"]="in",
+ ["en"]="in",
+ ["fr"]="dans",
+ ["it"]="in",
+ ["nl"]="in",
+ ["pe"]="درون",
+ ["ro"]="in",
+ },
+ ["incrementnumber"]={
+ ["cs"]="zvysujicicislo",
+ ["de"]="nummererhoehen",
+ ["en"]="incrementnumber",
+ ["fr"]="incrementenumero",
+ ["it"]="incrementanumero",
+ ["nl"]="verhoognummer",
+ ["pe"]="شماره‌افزایش",
+ ["ro"]="numarincrement",
+ },
+ ["indenting"]={
+ ["cs"]="odsazovani",
+ ["de"]="einziehen",
+ ["en"]="indenting",
+ ["fr"]="composeenalinea",
+ ["it"]="rientro",
+ ["nl"]="inspringen",
+ ["pe"]="تورفتگی",
+ ["ro"]="aliniat",
+ },
+ ["inframed"]={
+ ["cs"]="zaramovani",
+ ["de"]="imumriss",
+ ["en"]="inframed",
+ ["fr"]="inframed",
+ ["it"]="circondato",
+ ["nl"]="inlijnd",
+ ["pe"]="درقالبی",
+ ["ro"]="inframed",
+ },
+ ["infull"]={
+ ["cs"]="plnezneni",
+ ["de"]="volleswort",
+ ["en"]="infull",
+ ["fr"]="infull",
+ ["it"]="perlungo",
+ ["nl"]="voluit",
+ ["pe"]="درپر",
+ ["ro"]="pelung",
+ },
+ ["ininner"]={
+ ["cs"]="ininner",
+ ["de"]="ininner",
+ ["en"]="ininner",
+ ["fr"]="ininner",
+ ["it"]="ininner",
+ ["nl"]="inbinnen",
+ ["pe"]="درداخلی",
+ ["ro"]="ininner",
+ },
+ ["inleft"]={
+ ["cs"]="vlevo",
+ ["de"]="imlinken",
+ ["en"]="inleft",
+ ["fr"]="dansgauche",
+ ["it"]="insinistra",
+ ["nl"]="inlinker",
+ ["pe"]="درچپ",
+ ["ro"]="instanga",
+ },
+ ["inleftedge"]={
+ ["cs"]="nalevo",
+ ["de"]="imlinkenrand",
+ ["en"]="inleftedge",
+ ["fr"]="dansbordgauche",
+ ["it"]="inlatosinistro",
+ ["nl"]="inlinkerrand",
+ ["pe"]="درلبه‌چپ",
+ ["ro"]="inparteastanga",
+ },
+ ["inleftmargin"]={
+ ["cs"]="nalevyokraj",
+ ["de"]="inlinkermarginale",
+ ["en"]="inleftmargin",
+ ["fr"]="dansmargegauche",
+ ["it"]="inmarginesinistro",
+ ["nl"]="inlinkermarge",
+ ["pe"]="درحاشیه‌چپ",
+ ["ro"]="inmargineastanga",
+ },
+ ["inline"]={
+ ["cs"]="vradku",
+ ["de"]="inzeile",
+ ["en"]="inline",
+ ["fr"]="alaligne",
+ ["it"]="inriga",
+ ["nl"]="inregel",
+ ["pe"]="درخط",
+ ["ro"]="inlinie",
+ },
+ ["inmargin"]={
+ ["cs"]="naokraj",
+ ["de"]="inmarginalie",
+ ["en"]="inmargin",
+ ["fr"]="dansmarge",
+ ["it"]="inmargine",
+ ["nl"]="inmarge",
+ ["pe"]="درحاشیه",
+ ["ro"]="marginal",
+ },
+ ["inmframed"]={
+ ["cs"]="mazaramovani",
+ ["de"]="immaumrise",
+ ["en"]="inmaframed",
+ ["fr"]="inmframed",
+ ["it"]="inmaframed",
+ ["nl"]="inwilijnd",
+ ["pe"]="inmframed",
+ ["ro"]="inmaframed",
+ },
+ ["inneredgedistance"]={
+ ["cs"]="inneredgedistance",
+ ["de"]="inneredgedistance",
+ ["en"]="inneredgedistance",
+ ["fr"]="inneredgedistance",
+ ["it"]="inneredgedistance",
+ ["nl"]="binnenrandafstand",
+ ["pe"]="فاصله‌لبه‌داخلی",
+ ["ro"]="inneredgedistance",
+ },
+ ["inneredgewidth"]={
+ ["cs"]="inneredgewidth",
+ ["de"]="inneredgewidth",
+ ["en"]="inneredgewidth",
+ ["fr"]="inneredgewidth",
+ ["it"]="inneredgewidth",
+ ["nl"]="binnenrandbreedte",
+ ["pe"]="عرض‌لبه‌داخلی",
+ ["ro"]="inneredgewidth",
+ },
+ ["innermargindistance"]={
+ ["cs"]="innermargindistance",
+ ["de"]="innermargindistance",
+ ["en"]="innermargindistance",
+ ["fr"]="innermargindistance",
+ ["it"]="innermargindistance",
+ ["nl"]="binnenmargeafstand",
+ ["pe"]="فاصله‌حاشیه‌داخلی",
+ ["ro"]="innermargindistance",
+ },
+ ["innermarginwidth"]={
+ ["cs"]="innermarginwidth",
+ ["de"]="innermarginwidth",
+ ["en"]="innermarginwidth",
+ ["fr"]="innermarginwidth",
+ ["it"]="innermarginwidth",
+ ["nl"]="binnenmargebreedte",
+ ["pe"]="عرض‌حاشیه‌داخلی",
+ ["ro"]="innermarginwidth",
+ },
+ ["inothermargin"]={
+ ["cs"]="nadruhyokraj",
+ ["de"]="inanderermarginale",
+ ["en"]="inothermargin",
+ ["fr"]="dansautremarge",
+ ["it"]="inaltromargine",
+ ["nl"]="inanderemarge",
+ ["pe"]="درحاشیه‌دیگر",
+ ["ro"]="inaltamargine",
+ },
+ ["inouter"]={
+ ["cs"]="inouter",
+ ["de"]="inouter",
+ ["en"]="inouter",
+ ["fr"]="inouter",
+ ["it"]="inouter",
+ ["nl"]="inbuiten",
+ ["pe"]="درخارجی",
+ ["ro"]="inouter",
+ },
+ ["inright"]={
+ ["cs"]="vpravo",
+ ["de"]="imrechten",
+ ["en"]="inright",
+ ["fr"]="dansdroite",
+ ["it"]="indestra",
+ ["nl"]="inrechter",
+ ["pe"]="درراست",
+ ["ro"]="indreapta",
+ },
+ ["inrightedge"]={
+ ["cs"]="napravo",
+ ["de"]="imrechtenrand",
+ ["en"]="inrightedge",
+ ["fr"]="dansborddroit",
+ ["it"]="inlatodestro",
+ ["nl"]="inrechterrand",
+ ["pe"]="درلبه‌راست",
+ ["ro"]="inparteadreapta",
+ },
+ ["inrightmargin"]={
+ ["cs"]="napravyokraj",
+ ["de"]="inrechtermarginale",
+ ["en"]="inrightmargin",
+ ["fr"]="dansmargedroite",
+ ["it"]="inmarginedestro",
+ ["nl"]="inrechtermarge",
+ ["pe"]="درحاشیه‌راست",
+ ["ro"]="inmargineadreapta",
+ },
+ ["installlanguage"]={
+ ["cs"]="instalacejazyka",
+ ["de"]="installieresprache",
+ ["en"]="installlanguage",
+ ["fr"]="installelangue",
+ ["it"]="installalingua",
+ ["nl"]="installeertaal",
+ ["pe"]="نصب‌زبان",
+ ["ro"]="instalarelimba",
+ },
+ ["interactionbar"]={
+ ["cs"]="interakcnilista",
+ ["de"]="interaktionsbalken",
+ ["en"]="interactionbar",
+ ["fr"]="barreinteraction",
+ ["it"]="barrainterazione",
+ ["nl"]="interactiebalk",
+ ["pe"]="میله‌پانل",
+ ["ro"]="barainteractiune",
+ },
+ ["interactionbuttons"]={
+ ["cs"]="interakcnitlacitka",
+ ["de"]="interaktionsknopfe",
+ ["en"]="interactionbuttons",
+ ["fr"]="boutonsinteraction",
+ ["it"]="pulsantinterazione",
+ ["nl"]="interactiebuttons",
+ ["pe"]="دکمه‌پانل",
+ ["ro"]="butoaneinteractiune",
+ },
+ ["interactionmenu"]={
+ ["cs"]="interaktivnimenu",
+ ["de"]="interaktionsmenue",
+ ["en"]="interactionmenu",
+ ["fr"]="menuinteraction",
+ ["it"]="menuinterattivo",
+ ["nl"]="interactiemenu",
+ ["pe"]="منوی‌پانل",
+ ["ro"]="meniuinteractiune",
+ },
+ ["item"]={
+ ["cs"]="polozka",
+ ["de"]="pos",
+ ["en"]="item",
+ ["fr"]="element",
+ ["it"]="elemento",
+ ["nl"]="som",
+ ["pe"]="آیتم",
+ ["ro"]="element",
+ },
+ ["items"]={
+ ["cs"]="polozky",
+ ["de"]="posten",
+ ["en"]="items",
+ ["fr"]="elements",
+ ["it"]="elementi",
+ ["nl"]="items",
+ ["pe"]="آیتمها",
+ ["ro"]="element",
+ },
+ ["its"]={
+ ["cs"]="pol",
+ ["de"]="its",
+ ["en"]="its",
+ ["fr"]="el",
+ ["it"]="el",
+ ["nl"]="its",
+ ["pe"]="its",
+ ["ro"]="el",
+ },
+ ["keepblocks"]={
+ ["cs"]="zachovejbloky",
+ ["de"]="behaltebloecke",
+ ["en"]="keepblocks",
+ ["fr"]="gardeblocs",
+ ["it"]="tieniblocchi",
+ ["nl"]="handhaafblokken",
+ ["pe"]="حفظ‌بلوکها",
+ ["ro"]="pastreazablocuri",
+ },
+ ["label"]={
+ ["cs"]="poppisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["labels"]={
+ ["cs"]="popisky",
+ ["de"]="labels",
+ ["en"]="labels",
+ ["fr"]="etiquettes",
+ ["it"]="etichette",
+ ["nl"]="labels",
+ ["pe"]="برچسبها",
+ ["ro"]="etichete",
+ },
+ ["labeltext"]={
+ ["cs"]="textpopisku",
+ ["de"]="labeltext",
+ ["en"]="labeltext",
+ ["fr"]="labeltexte",
+ ["it"]="testoetichetta",
+ ["nl"]="labeltekst",
+ ["pe"]="متن‌برچسب",
+ ["ro"]="texteticheta",
+ },
+ ["language"]={
+ ["cs"]="jazyk",
+ ["de"]="sprache",
+ ["en"]="language",
+ ["fr"]="langue",
+ ["it"]="lingua",
+ ["nl"]="taal",
+ ["pe"]="زبان",
+ ["ro"]="limba",
+ },
+ ["leftaligned"]={
+ ["cs"]="zarovnanovlevo",
+ ["de"]="linksbuendig",
+ ["en"]="leftaligned",
+ ["fr"]="aligneagauche",
+ ["it"]="allineasinistra",
+ ["nl"]="regellinks",
+ ["pe"]="چپ‌چین",
+ ["ro"]="aliniatstanga",
+ },
+ ["leftedgedistance"]={
+ ["cs"]="vzdalenostlevehookraje",
+ ["de"]="abstandlinkerrand",
+ ["en"]="leftedgedistance",
+ ["fr"]="distancebordgauche",
+ ["it"]="distanzabordosinistro",
+ ["nl"]="linkerrandafstand",
+ ["pe"]="فاصله‌لبه‌چپ",
+ ["ro"]="distantacoltstanga",
+ },
+ ["leftedgewidth"]={
+ ["cs"]="sirkalevehookraje",
+ ["de"]="breitelinkerrand",
+ ["en"]="leftedgewidth",
+ ["fr"]="largeurbordgauche",
+ ["it"]="ampiezzabordosinistro",
+ ["nl"]="linkerrandbreedte",
+ ["pe"]="عرض‌لبه‌چپ",
+ ["ro"]="latimecoltstanga",
+ },
+ ["leftmargindistance"]={
+ ["cs"]="vzdalenostlevemarginalie",
+ ["de"]="linkemarginalafstand",
+ ["en"]="leftmargindistance",
+ ["fr"]="distancemargegauche",
+ ["it"]="distanzamarginesinistro",
+ ["nl"]="linkermargeafstand",
+ ["pe"]="فاصله‌حاشیه‌چپ",
+ ["ro"]="distantamarginestanga",
+ },
+ ["leftmarginwidth"]={
+ ["cs"]="sirkalevemarginalie",
+ ["de"]="linkemarginalbreite",
+ ["en"]="leftmarginwidth",
+ ["fr"]="largeurmargegauche",
+ ["it"]="ampiezzamarginesinistro",
+ ["nl"]="linkermargebreedte",
+ ["pe"]="عرض‌حاشیه‌چپ",
+ ["ro"]="latimemarginestanga",
+ },
+ ["leg"]={
+ ["cs"]="leg",
+ ["de"]="leg",
+ ["en"]="leg",
+ ["fr"]="leg",
+ ["it"]="leg",
+ ["nl"]="leg",
+ ["pe"]="پا",
+ ["ro"]="leg",
+ },
+ ["linewidth"]={
+ ["cs"]="tloustkacary",
+ ["de"]="liniendicke",
+ ["en"]="linethickness",
+ ["fr"]="largeurligne",
+ ["it"]="spessoreriga",
+ ["nl"]="lijndikte",
+ ["pe"]="عرض‌خط",
+ ["ro"]="grosimelinie",
+ },
+ ["listheight"]={
+ ["cs"]="vyskaseznamu",
+ ["de"]="listenhoehe",
+ ["en"]="listheight",
+ ["fr"]="hauteurliste",
+ ["it"]="altezzaelenco",
+ ["nl"]="lijsthoogte",
+ ["pe"]="ارتفاع‌خط",
+ ["ro"]="inaltimelista",
+ },
+ ["listlength"]={
+ ["cs"]="delkaseznamu",
+ ["de"]="listenlaenge",
+ ["en"]="listlength",
+ ["fr"]="llongueurliste",
+ ["it"]="lunghezzaelenco",
+ ["nl"]="lijstlengte",
+ ["pe"]="طول‌لیست",
+ ["ro"]="lungimelista",
+ },
+ ["listsymbol"]={
+ ["cs"]="listsymbol",
+ ["de"]="listsymbol",
+ ["en"]="listsymbol",
+ ["fr"]="listesymbole",
+ ["it"]="listsymbol",
+ ["nl"]="lijstsymbool",
+ ["pe"]="نمادلیست",
+ ["ro"]="listsymbol",
+ },
+ ["listwidth"]={
+ ["cs"]="sirkaseznamu",
+ ["de"]="listenbreite",
+ ["en"]="listwidth",
+ ["fr"]="largeurliste",
+ ["it"]="ampiezzaelenco",
+ ["nl"]="lijstbreedte",
+ ["pe"]="عرض‌لیست",
+ ["ro"]="latimelista",
+ },
+ ["logfields"]={
+ ["cs"]="zaznamovepole",
+ ["de"]="registrierefelder",
+ ["en"]="logfields",
+ ["fr"]="logchamp",
+ ["it"]="logcampi",
+ ["nl"]="registreervelden",
+ ["pe"]="میدانهای‌گزارش",
+ ["ro"]="logcampuri",
+ },
+ ["lohi"]={
+ ["cs"]="nivy",
+ ["de"]="tiho",
+ ["en"]="lohi",
+ ["fr"]="baha",
+ ["it"]="pedap",
+ ["nl"]="laho",
+ ["pe"]="پابا",
+ ["ro"]="jossus",
+ },
+ ["low"]={
+ ["cs"]="nizky",
+ ["de"]="tief",
+ ["en"]="low",
+ ["fr"]="bas",
+ ["it"]="ped",
+ ["nl"]="laag",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["macroname"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nommacro",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نام‌ماکرو",
+ ["ro"]="nume",
+ },
+ ["mainlanguage"]={
+ ["cs"]="hlavnijazyk",
+ ["de"]="hauptsprache",
+ ["en"]="mainlanguage",
+ ["fr"]="langueprincipale",
+ ["it"]="linguaprincipale",
+ ["nl"]="hoofdtaal",
+ ["pe"]="زبان‌اصلی",
+ ["ro"]="limbaprincipala",
+ },
+ ["makeupheight"]={
+ ["cs"]="vyskasazby",
+ ["de"]="satzhoehe",
+ ["en"]="makeupheight",
+ ["fr"]="hauteurmakeup",
+ ["it"]="altezzamakeup",
+ ["nl"]="zethoogte",
+ ["pe"]="ارتفاع‌آرایش",
+ ["ro"]="inaltimemakeup",
+ },
+ ["makeupwidth"]={
+ ["cs"]="sirkasazby",
+ ["de"]="satzbreite",
+ ["en"]="makeupwidth",
+ ["fr"]="largeurmakeup",
+ ["it"]="ampiezzamakeup",
+ ["nl"]="zetbreedte",
+ ["pe"]="عرض‌آرایش",
+ ["ro"]="latimemakeup",
+ },
+ ["mar"]={
+ ["cs"]="okr",
+ ["de"]="mar",
+ ["en"]="mar",
+ ["fr"]="mar",
+ ["it"]="mar",
+ ["nl"]="mar",
+ ["pe"]="حاش",
+ ["ro"]="mar",
+ },
+ ["margindistance"]={
+ ["cs"]="vzdalenostmarginalie",
+ ["de"]="marginalafstand",
+ ["en"]="margindistance",
+ ["fr"]="distancemarge",
+ ["it"]="distanzamargine",
+ ["nl"]="margeafstand",
+ ["pe"]="فاصله‌حاشیه",
+ ["ro"]="distantamargine",
+ },
+ ["marginrule"]={
+ ["cs"]="marginalnilinka",
+ ["de"]="marginallinie",
+ ["en"]="marginrule",
+ ["fr"]="margereglee",
+ ["it"]="lineamargine",
+ ["nl"]="kantlijn",
+ ["pe"]="خط‌حاشیه",
+ ["ro"]="liniemargine",
+ },
+ ["margintext"]={
+ ["cs"]="marginalnitext",
+ ["de"]="marginaltext",
+ ["en"]="margintext",
+ ["fr"]="textemarge",
+ ["it"]="testoinmargine",
+ ["nl"]="margetekst",
+ ["pe"]="متن‌حاشیه",
+ ["ro"]="textmarginal",
+ },
+ ["margintitle"]={
+ ["cs"]="marginalninadpis",
+ ["de"]="marginaltitel",
+ ["en"]="margintitle",
+ ["fr"]="titremarge",
+ ["it"]="titoloinmargine",
+ ["nl"]="margetitel",
+ ["pe"]="عنوان‌حاشیه",
+ ["ro"]="titlumarginal",
+ },
+ ["marginwidth"]={
+ ["cs"]="sirkamarginalie",
+ ["de"]="marginalbreite",
+ ["en"]="marginwidth",
+ ["fr"]="largeurmarge",
+ ["it"]="ampiezzamargine",
+ ["nl"]="margebreedte",
+ ["pe"]="عرض‌حاشیه",
+ ["ro"]="latimemargine",
+ },
+ ["marginword"]={
+ ["cs"]="marginalnislovo",
+ ["de"]="marginalwort",
+ ["en"]="marginword",
+ ["fr"]="motmarge",
+ ["it"]="parolainmargine",
+ ["nl"]="margewoord",
+ ["pe"]="کلمه‌حاشیه",
+ ["ro"]="cuvantmarginal",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markeer",
+ ["pe"]="نشانه‌گذاری",
+ ["ro"]="marcaje",
+ },
+ ["markversion"]={
+ ["cs"]="oznacverzi",
+ ["de"]="beschrifteversion",
+ ["en"]="markversion",
+ ["fr"]="marquageversion",
+ ["it"]="marcaversione",
+ ["nl"]="markeerversie",
+ ["pe"]="نسخه‌نشانه",
+ ["ro"]="marcheazaversiune",
+ },
+ ["mathematics"]={
+ ["cs"]="matematika",
+ ["de"]="mathematik",
+ ["en"]="mathematics",
+ ["fr"]="mathematique",
+ ["it"]="matematica",
+ ["nl"]="wiskunde",
+ ["pe"]="ریاضی",
+ ["ro"]="matematica",
+ },
+ ["menubutton"]={
+ ["cs"]="tlacitkomenu",
+ ["de"]="menueknopf",
+ ["en"]="menubutton",
+ ["fr"]="boutonmenu",
+ ["it"]="pulsantemenu",
+ ["nl"]="menubutton",
+ ["pe"]="دکمه‌منو",
+ ["ro"]="butonmeniu",
+ },
+ ["mframed"]={
+ ["cs"]="maoramovani",
+ ["de"]="maumrise",
+ ["en"]="maframed",
+ ["fr"]="mframed",
+ ["it"]="maframed",
+ ["nl"]="wilijnd",
+ ["pe"]="mframed",
+ ["ro"]="maframed",
+ },
+ ["midaligned"]={
+ ["cs"]="zarovnanonastred",
+ ["de"]="zentriert",
+ ["en"]="midaligned",
+ ["fr"]="aligneaumilieu",
+ ["it"]="allineacentro",
+ ["nl"]="regelmidden",
+ ["pe"]="تنظیم‌وسط",
+ ["ro"]="aliniatcentru",
+ },
+ ["mirror"]={
+ ["cs"]="zrcadlit",
+ ["de"]="spiegeln",
+ ["en"]="mirror",
+ ["fr"]="reflete",
+ ["it"]="riflessione",
+ ["nl"]="spiegel",
+ ["pe"]="آینه",
+ ["ro"]="reflexie",
+ },
+ ["month"]={
+ ["cs"]="mesic",
+ ["de"]="monat",
+ ["en"]="month",
+ ["fr"]="mois",
+ ["it"]="mese",
+ ["nl"]="maand",
+ ["pe"]="ماه",
+ ["ro"]="luna",
+ },
+ ["moveformula"]={
+ ["cs"]="moveformula",
+ ["de"]="moveformula",
+ ["en"]="moveformula",
+ ["fr"]="deplaceformule",
+ ["it"]="spostaformula",
+ ["nl"]="verplaatsformule",
+ ["pe"]="انتقال‌فرمول",
+ ["ro"]="moveformula",
+ },
+ ["moveongrid"]={
+ ["cs"]="premistinamrizku",
+ ["de"]="amgitterneuausrichten",
+ ["en"]="moveongrid",
+ ["fr"]="deplacesurgrille",
+ ["it"]="spostaagriglia",
+ ["nl"]="verplaatsopgrid",
+ ["pe"]="انتقال‌به‌توری",
+ ["ro"]="mutapegrid",
+ },
+ ["movesidefloat"]={
+ ["cs"]="movesidefloat",
+ ["de"]="movesidefloat",
+ ["en"]="movesidefloat",
+ ["fr"]="movesidefloat",
+ ["it"]="movesidefloat",
+ ["nl"]="verplaatszijblok",
+ ["pe"]="انتقال‌کنار‌شناور",
+ ["ro"]="movesidefloat",
+ },
+ ["navigating"]={
+ ["cs"]="navigating",
+ ["de"]="navigating",
+ ["en"]="navigating",
+ ["fr"]="navigating",
+ ["it"]="navigating",
+ ["nl"]="navigerend",
+ ["pe"]="هدایت",
+ ["ro"]="navigating",
+ },
+ ["nodimension"]={
+ ["cs"]="zadnyrozmer",
+ ["de"]="keindimension",
+ ["en"]="nodimension",
+ ["fr"]="sansdimension",
+ ["it"]="nientedimensioni",
+ ["nl"]="geendimensie",
+ ["pe"]="بدون‌بعد",
+ ["ro"]="faradimensiune",
+ },
+ ["noheaderandfooterlines"]={
+ ["cs"]="zadnezahlaviaupati",
+ ["de"]="keinekopfundfusszeilen",
+ ["en"]="noheaderandfooterlines",
+ ["fr"]="sanslignesenteteetpdp",
+ ["it"]="nientelineintestazionepdp",
+ ["nl"]="geenhoofdenvoetregels",
+ ["pe"]="بدون‌خط‌سروته‌برگ",
+ ["ro"]="faraliniiantetsisubsol",
+ },
+ ["noindenting"]={
+ ["cs"]="zadneodsazovani",
+ ["de"]="nichteinziehen",
+ ["en"]="noindenting",
+ ["fr"]="sansalinea",
+ ["it"]="nienterientro",
+ ["nl"]="nietinspringen",
+ ["pe"]="بدون‌تورفتگی",
+ ["ro"]="faraaliniat",
+ },
+ ["nolist"]={
+ ["cs"]="zadnyseznam",
+ ["de"]="keineliste",
+ ["en"]="nolist",
+ ["fr"]="sansliste",
+ ["it"]="nienteelenco",
+ ["nl"]="geenlijst",
+ ["pe"]="بدون‌لیست",
+ ["ro"]="faralista",
+ },
+ ["nomarking"]={
+ ["cs"]="zadneznaceni",
+ ["de"]="keinebeschriftung",
+ ["en"]="nomarking",
+ ["fr"]="sansmarquage",
+ ["it"]="nientemarcatura",
+ ["nl"]="geenmarkering",
+ ["pe"]="بدون‌نشانه‌گذاری",
+ ["ro"]="faramarcaje",
+ },
+ ["nomoreblocks"]={
+ ["cs"]="zadnedalsibloky",
+ ["de"]="keinebloeckemehr",
+ ["en"]="nomoreblocks",
+ ["fr"]="pasplusdeblocs",
+ ["it"]="bastablocchi",
+ ["nl"]="geenblokkenmeer",
+ ["pe"]="بدون‌بلوکهای‌بیشتر",
+ ["ro"]="gatablocuri",
+ },
+ ["nomorefiles"]={
+ ["cs"]="zadnedalsisoubory",
+ ["de"]="keinedateienmehr",
+ ["en"]="nomorefiles",
+ ["fr"]="pasplusdefichiers",
+ ["it"]="bastafile",
+ ["nl"]="geenfilesmeer",
+ ["pe"]="بدون‌فایلهای‌بیشتر",
+ ["ro"]="farafisiere",
+ },
+ ["nop"]={
+ ["cs"]="nop",
+ ["de"]="nop",
+ ["en"]="nop",
+ ["fr"]="nop",
+ ["it"]="nop",
+ ["nl"]="nop",
+ ["pe"]="منفی",
+ ["ro"]="nop",
+ },
+ ["nospace"]={
+ ["cs"]="zadnamezera",
+ ["de"]="keinspatium",
+ ["en"]="nospace",
+ ["fr"]="sansespace",
+ ["it"]="nientespazio",
+ ["nl"]="geenspatie",
+ ["pe"]="بدون‌فضا",
+ ["ro"]="faraspatiu",
+ },
+ ["note"]={
+ ["cs"]="poznamka",
+ ["de"]="notiz",
+ ["en"]="note",
+ ["fr"]="note",
+ ["it"]="nota",
+ ["nl"]="noot",
+ ["pe"]="یادداشت",
+ ["ro"]="nota",
+ },
+ ["notopandbottomlines"]={
+ ["cs"]="zadnehorniadolniradky",
+ ["de"]="keinzeilenobenundunten",
+ ["en"]="notopandbottomlines",
+ ["fr"]="sanslignessupetinf",
+ ["it"]="nientelineecimafondo",
+ ["nl"]="geenbovenenonderregels",
+ ["pe"]="بدون‌خط‌بالاوپایین",
+ ["ro"]="faraliniisussijos",
+ },
+ ["notsmallcapped"]={
+ ["cs"]="nokap",
+ ["de"]="nokap",
+ ["en"]="nocap",
+ ["fr"]="nocap",
+ ["it"]="nocap",
+ ["nl"]="nokap",
+ ["pe"]="سرپوش‌کوچک‌نه",
+ ["ro"]="nokap",
+ },
+ ["nowhitespace"]={
+ ["cs"]="zadnebilemisto",
+ ["de"]="keinzwischenraum",
+ ["en"]="nowhitespace",
+ ["fr"]="sansespaceblanc",
+ ["it"]="nientespaziobianco",
+ ["nl"]="geenwitruimte",
+ ["pe"]="بدون‌فضای‌سفید",
+ ["ro"]="faraspatiualb",
+ },
+ ["numberofsubpages"]={
+ ["cs"]="numberofsubpages",
+ ["de"]="numberofsubpages",
+ ["en"]="numberofsubpages",
+ ["fr"]="nombredesouspages",
+ ["it"]="numberofsubpages",
+ ["nl"]="aantalsubpaginas",
+ ["pe"]="شماره‌زیرصفحه",
+ ["ro"]="numberofsubpages",
+ },
+ ["numbers"]={
+ ["cs"]="cisla",
+ ["de"]="ziffern",
+ ["en"]="numbers",
+ ["fr"]="numeros",
+ ["it"]="numeri",
+ ["nl"]="cijfers",
+ ["pe"]="شماره‌ها",
+ ["ro"]="numere",
+ },
+ ["outeredgedistance"]={
+ ["cs"]="outeredgedistance",
+ ["de"]="outeredgedistance",
+ ["en"]="outeredgedistance",
+ ["fr"]="outeredgedistance",
+ ["it"]="outeredgedistance",
+ ["nl"]="buitenrandafstand",
+ ["pe"]="فاصله‌لبه‌خارجی",
+ ["ro"]="outeredgedistance",
+ },
+ ["outeredgewidth"]={
+ ["cs"]="outeredgewidth",
+ ["de"]="outeredgewidth",
+ ["en"]="outeredgewidth",
+ ["fr"]="outeredgewidth",
+ ["it"]="outeredgewidth",
+ ["nl"]="buitenrandbreedte",
+ ["pe"]="عرض‌لبه‌خارجی",
+ ["ro"]="outeredgewidth",
+ },
+ ["outermargindistance"]={
+ ["cs"]="outermargindistance",
+ ["de"]="outermargindistance",
+ ["en"]="outermargindistance",
+ ["fr"]="outermargindistance",
+ ["it"]="outermargindistance",
+ ["nl"]="buitenmargeafstand",
+ ["pe"]="فاصله‌حاشیه‌خارجی",
+ ["ro"]="outermargindistance",
+ },
+ ["outermarginwidth"]={
+ ["cs"]="outermarginwidth",
+ ["de"]="outermarginwidth",
+ ["en"]="outermarginwidth",
+ ["fr"]="outermarginwidth",
+ ["it"]="outermarginwidth",
+ ["nl"]="buitenmargebreedte",
+ ["pe"]="عرض‌حاشیه‌خارجی",
+ ["ro"]="outermarginwidth",
+ },
+ ["packed"]={
+ ["cs"]="zhustene",
+ ["de"]="kleinerdurchschuss",
+ ["en"]="packed",
+ ["fr"]="groupe",
+ ["it"]="impaccato",
+ ["nl"]="opelkaar",
+ ["pe"]="فشرده",
+ ["ro"]="impachetat",
+ },
+ ["page"]={
+ ["cs"]="strana",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pagedepth"]={
+ ["cs"]="pagedepth",
+ ["de"]="pagedepth",
+ ["en"]="pagedepth",
+ ["fr"]="pagedepth",
+ ["it"]="pagedepth",
+ ["nl"]="paginadiepte",
+ ["pe"]="عمق‌صفحه",
+ ["ro"]="pagedepth",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostrany",
+ ["de"]="seitenummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شماره‌صفحه",
+ ["ro"]="numarpagina",
+ },
+ ["pageoffset"]={
+ ["cs"]="pageoffset",
+ ["de"]="pageoffset",
+ ["en"]="pageoffset",
+ ["fr"]="pageoffset",
+ ["it"]="pageoffset",
+ ["nl"]="paginaoffset",
+ ["pe"]="آفست‌صفحه",
+ ["ro"]="pageoffset",
+ },
+ ["pagereference"]={
+ ["cs"]="odkaznastranu",
+ ["de"]="seitenreferenz",
+ ["en"]="pagereference",
+ ["fr"]="referencepage",
+ ["it"]="riferimentopagina",
+ ["nl"]="paginareferentie",
+ ["pe"]="مرجع‌صفحه",
+ ["ro"]="referintapagina",
+ },
+ ["paperheight"]={
+ ["cs"]="vyskapapiru",
+ ["de"]="papierhoehe",
+ ["en"]="paperheight",
+ ["fr"]="hauteurpapier",
+ ["it"]="altezzacarta",
+ ["nl"]="papierhoogte",
+ ["pe"]="ارتفاع‌برگ",
+ ["ro"]="inaltimehartie",
+ },
+ ["paperwidth"]={
+ ["cs"]="sirkapapiru",
+ ["de"]="papierbreite",
+ ["en"]="paperwidth",
+ ["fr"]="largeurpapier",
+ ["it"]="ampiezzacarta",
+ ["nl"]="papierbreedte",
+ ["pe"]="عرض‌برگ",
+ ["ro"]="latimehartie",
+ },
+ ["periods"]={
+ ["cs"]="tecky",
+ ["de"]="punkt",
+ ["en"]="periods",
+ ["fr"]="periodes",
+ ["it"]="punti",
+ ["nl"]="punten",
+ ["pe"]="نقطه‌ها",
+ ["ro"]="puncte",
+ },
+ ["placebookmarks"]={
+ ["cs"]="umistizalozky",
+ ["de"]="platzierebookmarks",
+ ["en"]="placebookmarks",
+ ["fr"]="placemarquespages",
+ ["it"]="mettisegnalibro",
+ ["nl"]="plaatsbookmarks",
+ ["pe"]="درج‌چوب‌خط",
+ ["ro"]="plaseazasemnecarte",
+ },
+ ["placecombinedlist"]={
+ ["cs"]="umistikombinovanyseznam",
+ ["de"]="platzierezusammengestellteliste",
+ ["en"]="placecombinedlist",
+ ["fr"]="placelisteinmbriquee",
+ ["it"]="mettielencocombinato",
+ ["nl"]="plaatssamengesteldelijst",
+ ["pe"]="درج‌لیست‌مختلط",
+ ["ro"]="punelistacombinata",
+ },
+ ["placefloat"]={
+ ["cs"]="placefloat",
+ ["de"]="placefloat",
+ ["en"]="placefloat",
+ ["fr"]="placeflottant",
+ ["it"]="placefloat",
+ ["nl"]="plaatsplaatsblok",
+ ["pe"]="درج‌شناور",
+ ["ro"]="placefloat",
+ },
+ ["placefootnotes"]={
+ ["cs"]="umistipoznamkypodcarou",
+ ["de"]="platzierefussnoten",
+ ["en"]="placefootnotes",
+ ["fr"]="placenotespdp",
+ ["it"]="mettinotepdp",
+ ["nl"]="plaatsvoetnoten",
+ ["pe"]="درج‌پانوشتها",
+ ["ro"]="punenotesubsol",
+ },
+ ["placeformula"]={
+ ["cs"]="umistirovnici",
+ ["de"]="platziereformel",
+ ["en"]="placeformula",
+ ["fr"]="placeformule",
+ ["it"]="mettiformula",
+ ["nl"]="plaatsformule",
+ ["pe"]="درج‌فرمول",
+ ["ro"]="puneformula",
+ },
+ ["placeheadnumber"]={
+ ["cs"]="placeheadnumber",
+ ["de"]="placeheadnumber",
+ ["en"]="placeheadnumber",
+ ["fr"]="placenumerotete",
+ ["it"]="posizionanumerotesta",
+ ["nl"]="plaatskopnummer",
+ ["pe"]="درج‌شماره‌سر",
+ ["ro"]="placeheadnumber",
+ },
+ ["placeheadtext"]={
+ ["cs"]="placeheadtext",
+ ["de"]="placeheadtext",
+ ["en"]="placeheadtext",
+ ["fr"]="placetextetete",
+ ["it"]="posizionatestotesta",
+ ["nl"]="plaatskoptekst",
+ ["pe"]="درج‌متن‌سر",
+ ["ro"]="placeheadtext",
+ },
+ ["placelegend"]={
+ ["cs"]="umistilegendu",
+ ["de"]="platzierelegende",
+ ["en"]="placelegend",
+ ["fr"]="placelegende",
+ ["it"]="mettilegenda",
+ ["nl"]="plaatslegenda",
+ ["pe"]="درج‌راهنما",
+ ["ro"]="punelegenda",
+ },
+ ["placelist"]={
+ ["cs"]="umistiseznam",
+ ["de"]="platziereliste",
+ ["en"]="placelist",
+ ["fr"]="placeliste",
+ ["it"]="mettielenco",
+ ["nl"]="plaatslijst",
+ ["pe"]="درج‌لیست",
+ ["ro"]="punelista",
+ },
+ ["placelistofsynonyms"]={
+ ["en"]="placelistofsynonyms",
+ ["nl"]="plaatslijstmetsynoniemen",
+ },
+ ["placelocalfootnotes"]={
+ ["cs"]="umistilokalnipoznamkypodcarou",
+ ["de"]="platzierelokalefussnoten",
+ ["en"]="placelocalfootnotes",
+ ["fr"]="placenotespdplocales",
+ ["it"]="mettinotepdplocali",
+ ["nl"]="plaatslokalevoetnoten",
+ ["pe"]="درج‌پانوشتهای‌موضعی",
+ ["ro"]="punenotesubsollocale",
+ },
+ ["placelogos"]={
+ ["cs"]="umistiloga",
+ ["de"]="platzierelogo",
+ ["en"]="placelogos",
+ ["fr"]="placelogos",
+ ["it"]="mettiloghi",
+ ["nl"]="plaatsbeeldmerken",
+ ["pe"]="درج‌آرمها",
+ ["ro"]="punelogouri",
+ },
+ ["placeongrid"]={
+ ["cs"]="umistinamrizku",
+ ["de"]="amgitterausrichten",
+ ["en"]="placeongrid",
+ ["fr"]="placesurgrille",
+ ["it"]="mettiingriglia",
+ ["nl"]="plaatsopgrid",
+ ["pe"]="درج‌در‌توری",
+ ["ro"]="plaseazapegrid",
+ },
+ ["placeontopofeachother"]={
+ ["cs"]="umistinadsebe",
+ ["de"]="platziereuntereinander",
+ ["en"]="placeontopofeachother",
+ ["fr"]="placelesunsaudessusdesautres",
+ ["it"]="mettiunosullaltro",
+ ["nl"]="plaatsonderelkaar",
+ ["pe"]="درج‌در‌بالای‌یکدیگر",
+ ["ro"]="punedeasuprafiecareia",
+ },
+ ["placepagenumber"]={
+ ["cs"]="placepagenumber",
+ ["de"]="placepagenumber",
+ ["en"]="placepagenumber",
+ ["fr"]="placenumeropage",
+ ["it"]="mettinumeropagina",
+ ["nl"]="plaatspaginanummer",
+ ["pe"]="درج‌شماره‌صفحه",
+ ["ro"]="punenumarpagina",
+ },
+ ["placerawlist"]={
+ ["cs"]="placerawlist",
+ ["de"]="placerawlist",
+ ["en"]="placerawlist",
+ ["fr"]="placerawlist",
+ ["it"]="placerawlist",
+ ["nl"]="plaatsruwelijst",
+ ["pe"]="درج‌لیست‌خام",
+ ["ro"]="placerawlist",
+ },
+ ["placereferencelist"]={
+ ["cs"]="placereferencelist",
+ ["de"]="placereferencelist",
+ ["en"]="placereferencelist",
+ ["fr"]="placelistereference",
+ ["it"]="placereferencelist",
+ ["nl"]="plaatsreferentielijst",
+ ["pe"]="درج‌لیست‌مرجع",
+ ["ro"]="placereferencelist",
+ },
+ ["placeregister"]={
+ ["cs"]="umistirejstrik",
+ ["de"]="platziereregister",
+ ["en"]="placeregister",
+ ["fr"]="placeregistre",
+ ["it"]="mettiregistro",
+ ["nl"]="plaatsregister",
+ ["pe"]="درج‌ثبت",
+ ["ro"]="puneregistru",
+ },
+ ["placerule"]={
+ ["cs"]="placerule",
+ ["de"]="placerule",
+ ["en"]="placerule",
+ ["fr"]="placeregle",
+ ["it"]="mettilinea",
+ ["nl"]="plaatslijn",
+ ["pe"]="درج‌خط",
+ ["ro"]="punerigla",
+ },
+ ["placesidebyside"]={
+ ["cs"]="umistivedlesebe",
+ ["de"]="platzierenebeneinander",
+ ["en"]="placesidebyside",
+ ["fr"]="placecoteacote",
+ ["it"]="mettifiancoafianco",
+ ["nl"]="plaatsnaastelkaar",
+ ["pe"]="درج‌کنار‌به‌کنار",
+ ["ro"]="punefatainfata",
+ },
+ ["placesubformula"]={
+ ["cs"]="umistipodrovnici",
+ ["de"]="platziereunterformel",
+ ["en"]="placesubformula",
+ ["fr"]="placesousformule",
+ ["it"]="mettisottoformula",
+ ["nl"]="plaatssubformule",
+ ["pe"]="درج‌زیرفرمول",
+ ["ro"]="punesubformula",
+ },
+ ["placetextvariable"]={
+ ["cs"]="placetextvariable",
+ ["de"]="placetextvariable",
+ ["en"]="placetextvariable",
+ ["fr"]="placevariabletexte",
+ ["it"]="mettivariabiletesto",
+ ["nl"]="plaatstekstvariabele",
+ ["pe"]="درج‌متغیرمتن",
+ ["ro"]="punevariabilatext",
+ },
+ ["position"]={
+ ["cs"]="pozice",
+ ["de"]="position",
+ ["en"]="position",
+ ["fr"]="position",
+ ["it"]="posizione",
+ ["nl"]="positioneer",
+ ["pe"]="مکان",
+ ["ro"]="pozitie",
+ },
+ ["positiontext"]={
+ ["cs"]="positiontext",
+ ["de"]="positiontext",
+ ["en"]="positiontext",
+ ["fr"]="positionnetexte",
+ ["it"]="posizionatesto",
+ ["nl"]="positioneertekst",
+ ["pe"]="مکان‌متن",
+ ["ro"]="pozitietext",
+ },
+ ["printpaperheight"]={
+ ["cs"]="vyskatiskpapiru",
+ ["de"]="printpapierhoehe",
+ ["en"]="printpaperheight",
+ ["fr"]="hauteureditionpapier",
+ ["it"]="altezzacartastampa",
+ ["nl"]="printpapierhoogte",
+ ["pe"]="چاپ‌ارتفاع‌برگ",
+ ["ro"]="inaltimehartieimprimanta",
+ },
+ ["printpaperwidth"]={
+ ["cs"]="sirkatiskpapiru",
+ ["de"]="printpapierbreite",
+ ["en"]="printpaperwidth",
+ ["fr"]="largeureditionpapier",
+ ["it"]="ampiezzacartastampa",
+ ["nl"]="printpapierbreedte",
+ ["pe"]="چاپ‌عرض‌برگ",
+ ["ro"]="latimehartieimprimanta",
+ },
+ ["processblocks"]={
+ ["cs"]="zpracujbloky",
+ ["de"]="bearbeitebloecke",
+ ["en"]="processblocks",
+ ["fr"]="traiteblocs",
+ ["it"]="elaborablocchi",
+ ["nl"]="verwerkblokken",
+ ["pe"]="بلوکهای‌پردازش",
+ ["ro"]="proceseazabloc",
+ },
+ ["processpage"]={
+ ["cs"]="zpracujstranu",
+ ["de"]="bearbeiteseite",
+ ["en"]="processpage",
+ ["fr"]="traitepage",
+ ["it"]="elaborapagina",
+ ["nl"]="verwerkpagina",
+ ["pe"]="صفحه‌پردازش",
+ ["ro"]="proceseazapagina",
+ },
+ ["product"]={
+ ["cs"]="produkt",
+ ["de"]="produkt",
+ ["en"]="product",
+ ["fr"]="produit",
+ ["it"]="prodotto",
+ ["nl"]="produkt",
+ ["pe"]="تولید",
+ ["ro"]="produs",
+ },
+ ["program"]={
+ ["cs"]="program",
+ ["de"]="programm",
+ ["en"]="program",
+ ["fr"]="programme",
+ ["it"]="programma",
+ ["nl"]="programma",
+ ["pe"]="برنامه",
+ ["ro"]="program",
+ },
+ ["project"]={
+ ["cs"]="projekt",
+ ["de"]="projekt",
+ ["en"]="project",
+ ["fr"]="projet",
+ ["it"]="progetto",
+ ["nl"]="projekt",
+ ["pe"]="پروژه",
+ ["ro"]="proiect",
+ },
+ ["publication"]={
+ ["cs"]="publikace",
+ ["de"]="publikation",
+ ["en"]="publication",
+ ["fr"]="publication",
+ ["it"]="pubblicazione",
+ ["nl"]="publicatie",
+ ["pe"]="نشر",
+ ["ro"]="publicatie",
+ },
+ ["quotation"]={
+ ["cs"]="citace",
+ ["de"]="zitat",
+ ["en"]="quotation",
+ ["fr"]="citation",
+ ["it"]="citazione",
+ ["nl"]="citaat",
+ ["pe"]="نقل‌قول",
+ ["ro"]="citat",
+ },
+ ["quote"]={
+ ["cs"]="citovat",
+ ["de"]="zitieren",
+ ["en"]="quote",
+ ["fr"]="citer",
+ ["it"]="menzione",
+ ["nl"]="citeer",
+ ["pe"]="نقل",
+ ["ro"]="minicitat",
+ },
+ ["ran"]={
+ ["cs"]="ran",
+ ["de"]="ran",
+ ["en"]="ran",
+ ["fr"]="ran",
+ ["it"]="ran",
+ ["nl"]="ran",
+ ["pe"]="ran",
+ ["ro"]="ran",
+ },
+ ["redo"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="redo",
+ ["fr"]="refait",
+ ["it"]="rifai",
+ ["nl"]="herhaal",
+ ["pe"]="انجام‌دوباره",
+ ["ro"]="refa",
+ },
+ ["ref"]={
+ ["cs"]="ref",
+ ["de"]="ref",
+ ["en"]="ref",
+ ["fr"]="ref",
+ ["it"]="rif",
+ ["nl"]="ref",
+ ["pe"]="رج",
+ ["ro"]="ref",
+ },
+ ["reference"]={
+ ["cs"]="odkaz",
+ ["de"]="referenz",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="riferimento",
+ ["nl"]="referentie",
+ ["pe"]="مرجع",
+ ["ro"]="referinta",
+ },
+ ["referral"]={
+ ["cs"]="odkaz",
+ ["de"]="verweis",
+ ["en"]="referral",
+ ["fr"]="recommandation",
+ ["it"]="referral",
+ ["nl"]="kenmerk",
+ ["pe"]="رجوع",
+ ["ro"]="referit",
+ },
+ ["referraldate"]={
+ ["cs"]="odkaznadatum",
+ ["de"]="verweisdatum",
+ ["en"]="referraldate",
+ ["fr"]="daterecommandation",
+ ["it"]="datareferral",
+ ["nl"]="kenmerkdatum",
+ ["pe"]="تاریخ‌رجوع",
+ ["ro"]="datareferit",
+ },
+ ["referring"]={
+ ["cs"]="odkazujici",
+ ["de"]="referieren",
+ ["en"]="referring",
+ ["fr"]="faitreference",
+ ["it"]="referring",
+ ["nl"]="refereer",
+ ["pe"]="مراجعه",
+ ["ro"]="referring",
+ },
+ ["remark"]={
+ ["cs"]="oznaceni",
+ ["de"]="bemerkung",
+ ["en"]="remark",
+ ["fr"]="commentaire",
+ ["it"]="commento",
+ ["nl"]="toelichting",
+ ["pe"]="توجه",
+ ["ro"]="remarca",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="ruecksetzten",
+ ["en"]="reset",
+ ["fr"]="raz",
+ ["it"]="reimposta",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["resetmarking"]={
+ ["cs"]="resetznaceni",
+ ["de"]="ruecksetztenbeschriftung",
+ ["en"]="resetmarking",
+ ["fr"]="razmarquage",
+ ["it"]="reimpostamarcatura",
+ ["nl"]="resetmarkering",
+ ["pe"]="بازنشانی‌نشانه‌گذاری",
+ ["ro"]="reseteazamarcaje",
+ },
+ ["resetnumber"]={
+ ["cs"]="resetnumber",
+ ["de"]="resetnumber",
+ ["en"]="resetnumber",
+ ["fr"]="raznumero",
+ ["it"]="resetnumber",
+ ["nl"]="resetnummer",
+ ["pe"]="بازنشانی‌شماره",
+ ["ro"]="resetnumber",
+ },
+ ["resettext"]={
+ ["cs"]="resettextcontent",
+ ["de"]="resettextcontent",
+ ["en"]="resettextcontent",
+ ["fr"]="resettextcontent",
+ ["it"]="resettextcontent",
+ ["nl"]="resettekstinhoud",
+ ["pe"]="بازنشانی‌متن",
+ ["ro"]="resettextcontent",
+ },
+ ["rightaligned"]={
+ ["cs"]="zarovnanovpravo",
+ ["de"]="rechtsbuendig",
+ ["en"]="rightaligned",
+ ["fr"]="aligneadroite",
+ ["it"]="allineadestra",
+ ["nl"]="regelrechts",
+ ["pe"]="تنظیم‌راست",
+ ["ro"]="aliniatdreapta",
+ },
+ ["rightedgedistance"]={
+ ["cs"]="vzdalenostpravehookraje",
+ ["de"]="abstandrechterrand",
+ ["en"]="rightedgedistance",
+ ["fr"]="distanceborddroit",
+ ["it"]="distanzabordodestro",
+ ["nl"]="rechterrandafstand",
+ ["pe"]="فاصله‌لبه‌راست",
+ ["ro"]="distantacoltdreapta",
+ },
+ ["rightedgewidth"]={
+ ["cs"]="sirkapravehookraje",
+ ["de"]="breiterechterrand",
+ ["en"]="rightedgewidth",
+ ["fr"]="largeurborddroit",
+ ["it"]="ampiezzabordodestro",
+ ["nl"]="rechterrandbreedte",
+ ["pe"]="عرض‌لبه‌راست",
+ ["ro"]="latimecoltdreapta",
+ },
+ ["rightmargindistance"]={
+ ["cs"]="vzdalenostpravemarginalie",
+ ["de"]="rechtemarginalafstand",
+ ["en"]="rightmargindistance",
+ ["fr"]="distancemargedroite",
+ ["it"]="distanzamarginedestro",
+ ["nl"]="rechtermargeafstand",
+ ["pe"]="فاصله‌حاشیه‌راست",
+ ["ro"]="distantamarginedreapta",
+ },
+ ["rightmarginwidth"]={
+ ["cs"]="sirkapravemarginalie",
+ ["de"]="rechtemarginalbreite",
+ ["en"]="rightmarginwidth",
+ ["fr"]="largeurmargedroite",
+ ["it"]="ampiezzamarginedestro",
+ ["nl"]="rechtermargebreedte",
+ ["pe"]="عرض‌حاشیه‌راست",
+ ["ro"]="latimemarginedreapta",
+ },
+ ["romannumerals"]={
+ ["cs"]="rimskecislice",
+ ["de"]="roemischezahlen",
+ ["en"]="romannumerals",
+ ["fr"]="chiffresromains",
+ ["it"]="numeriromani",
+ ["nl"]="romeins",
+ ["pe"]="اعدادلاتین",
+ ["ro"]="numereromane",
+ },
+ ["rotate"]={
+ ["cs"]="otocit",
+ ["de"]="drehen",
+ ["en"]="rotate",
+ ["fr"]="oriente",
+ ["it"]="ruota",
+ ["nl"]="roteer",
+ ["pe"]="دوران",
+ ["ro"]="roteste",
+ },
+ ["scale"]={
+ ["cs"]="meritko",
+ ["de"]="format",
+ ["en"]="scale",
+ ["fr"]="echelle",
+ ["it"]="scala",
+ ["nl"]="schaal",
+ ["pe"]="مقیاس",
+ ["ro"]="scala",
+ },
+ ["screen"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="scherm",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["selectblocks"]={
+ ["cs"]="vyberbloky",
+ ["de"]="waehlebloeckeaus",
+ ["en"]="selectblocks",
+ ["fr"]="selectionneblocs",
+ ["it"]="selezionablocchi",
+ ["nl"]="selecteerblokken",
+ ["pe"]="انتخاب‌بلوکها",
+ ["ro"]="selecteazablocuri",
+ },
+ ["selectpaper"]={
+ ["cs"]="vyberpapir",
+ ["de"]="waehlepapieraus",
+ ["en"]="selectpaper",
+ ["fr"]="selectionnepapier",
+ ["it"]="selezionacarta",
+ ["nl"]="selecteerpapier",
+ ["pe"]="انتخاب‌برگ",
+ ["ro"]="selecteazahartie",
+ },
+ ["selectversion"]={
+ ["cs"]="vyberverzi",
+ ["de"]="waehleversionaus",
+ ["en"]="selectversion",
+ ["fr"]="selectionneversion",
+ ["it"]="selezionaversione",
+ ["nl"]="selecteerversie",
+ ["pe"]="انتخاب‌نسخه",
+ ["ro"]="selecteazaversiune",
+ },
+ ["setnumber"]={
+ ["cs"]="setnumber",
+ ["de"]="setnumber",
+ ["en"]="setnumber",
+ ["fr"]="affectenumero",
+ ["it"]="setnumber",
+ ["nl"]="setnummer",
+ ["pe"]="تعیین‌شماره",
+ ["ro"]="setnumber",
+ },
+ ["settextcontent"]={
+ ["cs"]="settextcontent",
+ ["de"]="settext",
+ ["en"]="settextcontent",
+ ["fr"]="settext",
+ ["it"]="settext",
+ ["nl"]="steltekstinhoudin",
+ ["pe"]="تعیین‌محتوای‌متن",
+ ["ro"]="settextcontent",
+ },
+ ["settextvariable"]={
+ ["cs"]="settextvariable",
+ ["de"]="settextvariable",
+ ["en"]="settextvariable",
+ ["fr"]="affectevariabletexte",
+ ["it"]="setvariabiletesto",
+ ["nl"]="kentekstvariabeletoe",
+ ["pe"]="تعیین‌متغیر‌متن",
+ ["ro"]="setvariabilatext",
+ },
+ ["setupalign"]={
+ ["cs"]="nastavzarovnani",
+ ["de"]="stelleausrichtungein",
+ ["en"]="setupalign",
+ ["fr"]="reglealignement",
+ ["it"]="impostaallineamento",
+ ["nl"]="steluitlijnenin",
+ ["pe"]="بارگذاری‌تنظیم",
+ ["ro"]="seteazaalinierea",
+ },
+ ["setupanswerarea"]={
+ ["cs"]="setupanswerarea",
+ ["de"]="setupanswerarea",
+ ["en"]="setupanswerarea",
+ ["fr"]="setupanswerarea",
+ ["it"]="setupanswerarea",
+ ["nl"]="stelantwoordgebiedin",
+ ["pe"]="setupanswerarea",
+ ["ro"]="setupanswerarea",
+ },
+ ["setuparranging"]={
+ ["cs"]="nastavusporadani",
+ ["de"]="stelleanordnenein",
+ ["en"]="setuparranging",
+ ["fr"]="reglearrangement",
+ ["it"]="impostaparranging",
+ ["nl"]="stelarrangerenin",
+ ["pe"]="بارگذاری‌ترتیب",
+ ["ro"]="seteazaaranjareapag",
+ },
+ ["setupbackground"]={
+ ["cs"]="nastavpozadi",
+ ["de"]="stellehintergrundein",
+ ["en"]="setupbackground",
+ ["fr"]="reglearriereplan",
+ ["it"]="impostasfondo",
+ ["nl"]="stelachtergrondin",
+ ["pe"]="بارگذاری‌پس‌زمینه",
+ ["ro"]="seteazafundal",
+ },
+ ["setupbackgrounds"]={
+ ["cs"]="nastavpozadi",
+ ["de"]="stellehintergruendeein",
+ ["en"]="setupbackgrounds",
+ ["fr"]="reglearriereplans",
+ ["it"]="impostasfondi",
+ ["nl"]="stelachtergrondenin",
+ ["pe"]="بارگذاری‌پس‌زمینه‌ها",
+ ["ro"]="seteazafundaluri",
+ },
+ ["setupblackrules"]={
+ ["cs"]="nastavcernelinky",
+ ["de"]="stellerechteckein",
+ ["en"]="setupblackrules",
+ ["fr"]="reglelignesnoires",
+ ["it"]="impostalineenere",
+ ["nl"]="stelblokjesin",
+ ["pe"]="بارگذاری‌خطهای‌سیاه",
+ ["ro"]="seteazaliniinegre",
+ },
+ ["setupblank"]={
+ ["cs"]="nastavpreskok",
+ ["de"]="stelleblankoein",
+ ["en"]="setupblank",
+ ["fr"]="definitvide",
+ ["it"]="impostarigovuoto",
+ ["nl"]="stelblankoin",
+ ["pe"]="بارگذاری‌خالی",
+ ["ro"]="seteazablanc",
+ },
+ ["setupblock"]={
+ ["cs"]="nastavblok",
+ ["de"]="stelleblockein",
+ ["en"]="setupblock",
+ ["fr"]="reglebloc",
+ ["it"]="impostablocco",
+ ["nl"]="stelblokin",
+ ["pe"]="بارگذاری‌بلوک",
+ ["ro"]="seteazabloc",
+ },
+ ["setupbodyfont"]={
+ ["cs"]="nastavzakladnifont",
+ ["de"]="stellefliesstextein",
+ ["en"]="setupbodyfont",
+ ["fr"]="reglepolicecorps",
+ ["it"]="impostafontdeltesto",
+ ["nl"]="stelkorpsin",
+ ["pe"]="بارگذاری‌قلم‌متن",
+ ["ro"]="seteazafonttext",
+ },
+ ["setupbodyfontenvironment"]={
+ ["cs"]="nastavprostredizakladnihofontu",
+ ["de"]="stellefliesstextumgebungein",
+ ["en"]="setupbodyfontenvironment",
+ ["fr"]="regleenvironnementpolicecorps",
+ ["it"]="impostaambientefontdeltesto",
+ ["nl"]="stelkorpsomgevingin",
+ ["pe"]="بارگذاری‌محیط‌قلم‌متن",
+ ["ro"]="seteazamediulfonttext",
+ },
+ ["setupbottom"]={
+ ["cs"]="nastavspodek",
+ ["de"]="stelleuntenein",
+ ["en"]="setupbottom",
+ ["fr"]="regleinf",
+ ["it"]="impostafondo",
+ ["nl"]="stelonderin",
+ ["pe"]="بارگذاری‌پایین",
+ ["ro"]="seteazajos",
+ },
+ ["setupbottomtexts"]={
+ ["cs"]="nastavdolnitexty",
+ ["de"]="stelletextuntenein",
+ ["en"]="setupbottomtexts",
+ ["fr"]="regletextesinf",
+ ["it"]="impostatestifondo",
+ ["nl"]="stelondertekstenin",
+ ["pe"]="بارگذاری‌متن‌پایین",
+ ["ro"]="seteazatextejos",
+ },
+ ["setupbuffer"]={
+ ["cs"]="nastavbuffer",
+ ["de"]="stellepufferein",
+ ["en"]="setupbuffer",
+ ["fr"]="reglebuffer",
+ ["it"]="impostabuffer",
+ ["nl"]="stelbufferin",
+ ["pe"]="بارگذاری‌بافر",
+ ["ro"]="seteazabuffer",
+ },
+ ["setupbuttons"]={
+ ["cs"]="nastavtlacitka",
+ ["de"]="stelleknopfein",
+ ["en"]="setupbuttons",
+ ["fr"]="regleboutons",
+ ["it"]="impostapulsanti",
+ ["nl"]="stelbuttonsin",
+ ["pe"]="بارگذاری‌دکمه‌ها",
+ ["ro"]="seteazabutoane",
+ },
+ ["setupcapitals"]={
+ ["cs"]="nastavkapitalky",
+ ["de"]="stelleversalienein",
+ ["en"]="setupcapitals",
+ ["fr"]="reglecapitales",
+ ["it"]="impostamaiuscole",
+ ["nl"]="stelkapitalenin",
+ ["pe"]="setupcapitals",
+ ["ro"]="seteazamajuscule",
+ },
+ ["setupcaption"]={
+ ["cs"]="nastavpopisek",
+ ["de"]="stellebildunterschriftein",
+ ["en"]="setupcaption",
+ ["fr"]="regleintitule",
+ ["it"]="impostacaption",
+ ["nl"]="stelblokkopjein",
+ ["pe"]="بارگذاری‌شرح",
+ ["ro"]="seteazalegenda",
+ },
+ ["setupcaptions"]={
+ ["cs"]="nastavpopisky",
+ ["de"]="stellebilderunterschriftein",
+ ["en"]="setupcaptions",
+ ["fr"]="regleintitules",
+ ["it"]="impostacaptions",
+ ["nl"]="stelblokkopjesin",
+ ["pe"]="بارگذاری‌شرحها",
+ ["ro"]="seteazalegendele",
+ },
+ ["setupclipping"]={
+ ["cs"]="nastavorez",
+ ["de"]="stelleausschnittein",
+ ["en"]="setupclipping",
+ ["fr"]="regleclipping",
+ ["it"]="impostaclippling",
+ ["nl"]="stelclipin",
+ ["pe"]="بارگذاری‌چیدن",
+ ["ro"]="seteazaclipping",
+ },
+ ["setupcolor"]={
+ ["cs"]="nastavbarvu",
+ ["de"]="stellefarbeein",
+ ["en"]="setupcolor",
+ ["fr"]="reglecouleur",
+ ["it"]="impostacolore",
+ ["nl"]="stelkleurin",
+ ["pe"]="بارگذاری‌رنگ",
+ ["ro"]="seteazaculoare",
+ },
+ ["setupcolors"]={
+ ["cs"]="nastavbarvy",
+ ["de"]="stellefarbenein",
+ ["en"]="setupcolors",
+ ["fr"]="reglecouleurs",
+ ["it"]="impostacolori",
+ ["nl"]="stelkleurenin",
+ ["pe"]="بارگذاری‌رنگها",
+ ["ro"]="seteazaculori",
+ },
+ ["setupcolumns"]={
+ ["cs"]="nastavsloupce",
+ ["de"]="stellespaltenein",
+ ["en"]="setupcolumns",
+ ["fr"]="reglecolonnes",
+ ["it"]="impostacolonne",
+ ["nl"]="stelkolommenin",
+ ["pe"]="بارگذاری‌ستونها",
+ ["ro"]="seteazacoloane",
+ },
+ ["setupcolumnset"]={
+ ["cs"]="setupcolumnset",
+ ["de"]="setupcolumnset",
+ ["en"]="setupcolumnset",
+ ["fr"]="reglejeucolonne",
+ ["it"]="impostagruppocolonne",
+ ["nl"]="stelkolomgroepin",
+ ["pe"]="بارگذاری‌مجموعه‌ستون",
+ ["ro"]="setupcolumnset",
+ },
+ ["setupcolumnsetlines"]={
+ ["cs"]="setupcolumnsetlines",
+ ["de"]="setupcolumnsetlines",
+ ["en"]="setupcolumnsetlines",
+ ["fr"]="setupcolumnsetlines",
+ ["it"]="setupcolumnsetlines",
+ ["nl"]="stelkolomgroepregelsin",
+ ["pe"]="بارگذاری‌خطهای‌مجموعه‌ستون",
+ ["ro"]="setupcolumnsetlines",
+ },
+ ["setupcolumnsetstart"]={
+ ["cs"]="setupcolumnsetstart",
+ ["de"]="setupcolumnsetstart",
+ ["en"]="setupcolumnsetstart",
+ ["fr"]="setupcolumnsetstart",
+ ["it"]="setupcolumnsetstart",
+ ["nl"]="stelkolomgroepstartin",
+ ["pe"]="بارگذاری‌شروع‌مجموعه‌ستون",
+ ["ro"]="setupcolumnsetstart",
+ },
+ ["setupcombinations"]={
+ ["cs"]="nastavspojeni",
+ ["de"]="stellekombinationein",
+ ["en"]="setupcombinations",
+ ["fr"]="reglecombinaisons",
+ ["it"]="impostacombinazioni",
+ ["nl"]="stelcombinatiesin",
+ ["pe"]="بارگذاری‌ترکیب‌ها",
+ ["ro"]="seteazacombinari",
+ },
+ ["setupcombinedlist"]={
+ ["cs"]="nastavkombinovanyseznam",
+ ["de"]="stellezusammengestelltelisteein",
+ ["en"]="setupcombinedlist",
+ ["fr"]="reglelisteimbriquee",
+ ["it"]="impostaelencocombinato",
+ ["nl"]="stelsamengesteldelijstin",
+ ["pe"]="بارگذاری‌لیست‌ترکیبی",
+ ["ro"]="seteazalistacombinata",
+ },
+ ["setupcomment"]={
+ ["cs"]="nastavkomentar",
+ ["de"]="stellekommentarein",
+ ["en"]="setupcomment",
+ ["fr"]="reglecommentaire",
+ ["it"]="impostacommento",
+ ["nl"]="stelcommentaarin",
+ ["pe"]="بارگذاری‌توضیح",
+ ["ro"]="seteazacomentariu",
+ },
+ ["setupdescriptions"]={
+ ["cs"]="nastavpopisy",
+ ["de"]="definierebeschreibungen",
+ ["en"]="setupdescriptions",
+ ["fr"]="regledescriptions",
+ ["it"]="impostadescrizioni",
+ ["nl"]="steldoordefinierenin",
+ ["pe"]="بارگذاری‌شرح",
+ ["ro"]="seteazadescriere",
+ },
+ ["setupenumerations"]={
+ ["cs"]="nastavvycty",
+ ["de"]="stellebeschreibungein",
+ ["en"]="setupenumerations",
+ ["fr"]="regleenumerations",
+ ["it"]="impostaenumerazioni",
+ ["nl"]="steldoornummerenin",
+ ["pe"]="بارگذاری‌شماره‌گذاریها",
+ ["ro"]="seteazaenumerare",
+ },
+ ["setupexternalfigures"]={
+ ["cs"]="nastavexterniobrazy",
+ ["de"]="stelleexterneabbildungenein",
+ ["en"]="setupexternalfigures",
+ ["fr"]="reglefiguresexternes",
+ ["it"]="impostafigureesterne",
+ ["nl"]="stelexternefigurenin",
+ ["pe"]="بارگذاری‌شکلهای‌خارجی",
+ ["ro"]="seteazafiguriexterne",
+ },
+ ["setupfield"]={
+ ["cs"]="nastavpole",
+ ["de"]="stellefeldein",
+ ["en"]="setupfield",
+ ["fr"]="reglechamp",
+ ["it"]="impostacampo",
+ ["nl"]="stelveldin",
+ ["pe"]="بارگذاری‌میدان",
+ ["ro"]="seteazacamp",
+ },
+ ["setupfields"]={
+ ["cs"]="nastavvsechnapole",
+ ["de"]="stellefelderin",
+ ["en"]="setupfields",
+ ["fr"]="reglechamps",
+ ["it"]="impostacampi",
+ ["nl"]="stelveldenin",
+ ["pe"]="بارگذاری‌میدانها",
+ ["ro"]="seteazacampuri",
+ },
+ ["setupfillinlines"]={
+ ["cs"]="nastavvyplnoveradky",
+ ["de"]="stellegefuelltezeileein",
+ ["en"]="setupfillinlines",
+ ["fr"]="regleremplitligne",
+ ["it"]="impostarigheriempimento",
+ ["nl"]="stelinvulregelsin",
+ ["pe"]="بارگذاری‌پرکردن‌خطها",
+ ["ro"]="seteazaliniiumplere",
+ },
+ ["setupfillinrules"]={
+ ["cs"]="nastavvyplnovelinky",
+ ["de"]="stellegefuelltesrechteckein",
+ ["en"]="setupfillinrules",
+ ["fr"]="regleremplitlignesreglees",
+ ["it"]="impostalineeriempimento",
+ ["nl"]="stelinvullijnenin",
+ ["pe"]="بارگذاری‌درج‌درخطها",
+ ["ro"]="seteazarigleumplere",
+ },
+ ["setupfloat"]={
+ ["cs"]="nastavplvouciobjekt",
+ ["de"]="stellegleitobjektein",
+ ["en"]="setupfloat",
+ ["fr"]="regleflottant",
+ ["it"]="impostaoggettomobile",
+ ["nl"]="stelplaatsblokin",
+ ["pe"]="بارگذاری‌شناور",
+ ["ro"]="seteazafloat",
+ },
+ ["setupfloats"]={
+ ["cs"]="nastavplvouciobjekty",
+ ["de"]="stellegleitobjekteein",
+ ["en"]="setupfloats",
+ ["fr"]="regleflottants",
+ ["it"]="impostaoggettimobili",
+ ["nl"]="stelplaatsblokkenin",
+ ["pe"]="بارگذاری‌شناورها",
+ ["ro"]="seteazafloats",
+ },
+ ["setupfloatsplitting"]={
+ ["cs"]="nastavdeleniplvoucichobjektu",
+ ["de"]="stelleplatziegeteiltegleitobjekt",
+ ["en"]="setupfloatsplitting",
+ ["fr"]="regleseparationflottant",
+ ["it"]="impostaspezzamentooggettomobile",
+ ["nl"]="stelplaatsbloksplitsenin",
+ ["pe"]="بارگذاری‌شکافتن‌شناورها",
+ ["ro"]="seteazaimpartireafloat",
+ },
+ ["setupfooter"]={
+ ["cs"]="nastavupati",
+ ["de"]="stellefusszeileein",
+ ["en"]="setupfooter",
+ ["fr"]="reglepdp",
+ ["it"]="impostapdp",
+ ["nl"]="stelvoetin",
+ ["pe"]="بارگذاری‌ته‌برگ",
+ ["ro"]="seteazasubsol",
+ },
+ ["setupfootertexts"]={
+ ["cs"]="nastavtextyupati",
+ ["de"]="stellefusszeilentextein",
+ ["en"]="setupfootertexts",
+ ["fr"]="regletextespdp",
+ ["it"]="impostatestipdp",
+ ["nl"]="stelvoettekstenin",
+ ["pe"]="بارگذاری‌متن‌پانوشت",
+ ["ro"]="seteazatextesubsol",
+ },
+ ["setupfootnotedefinition"]={
+ ["cs"]="nastavdefinicipoznamekpodcarou",
+ ["de"]="stellefussnotendefinitionein",
+ ["en"]="setupfootnotedefinition",
+ ["fr"]="definitnotepdp",
+ ["it"]="impostadefinizionenotepdp",
+ ["nl"]="stelvoetnootdefinitiein",
+ ["pe"]="بارگذاری‌تعریف‌پانوشت",
+ ["ro"]="seteazadefinireanotasubsol",
+ },
+ ["setupfootnotes"]={
+ ["cs"]="nastavpoznamkypodcarou",
+ ["de"]="stellefussnotenein",
+ ["en"]="setupfootnotes",
+ ["fr"]="reglenotepdp",
+ ["it"]="impostanotepdp",
+ ["nl"]="stelvoetnotenin",
+ ["pe"]="بارگذاری‌پانوشتها",
+ ["ro"]="seteazanotasubsol",
+ },
+ ["setupforms"]={
+ ["cs"]="setupforms",
+ ["de"]="setupforms",
+ ["en"]="setupforms",
+ ["fr"]="regleformulaires",
+ ["it"]="impostaforms",
+ ["nl"]="stelformulierenin",
+ ["pe"]="بارگذاری‌طرح",
+ ["ro"]="seteazaformulare",
+ },
+ ["setupformulas"]={
+ ["cs"]="nastavrovnice",
+ ["de"]="stelleformelnein",
+ ["en"]="setupformulae",
+ ["fr"]="regleformules",
+ ["it"]="impostaformule",
+ ["nl"]="stelformulesin",
+ ["pe"]="بارگذاری‌فرمولها",
+ ["ro"]="seteazaformule",
+ },
+ ["setupframed"]={
+ ["cs"]="nastavoramovani",
+ ["de"]="stelleumrahmtein",
+ ["en"]="setupframed",
+ ["fr"]="regleencadre",
+ ["it"]="impostaincorniciato",
+ ["nl"]="stelomlijndin",
+ ["pe"]="بارگذاری‌قالبی",
+ ["ro"]="seteazainconjurat",
+ },
+ ["setupframedtexts"]={
+ ["cs"]="nastavoramovanetexty",
+ ["de"]="stelleumrahmtetexteein",
+ ["en"]="setupframedtexts",
+ ["fr"]="setupframedtexts",
+ ["it"]="impostatestiincorniciati",
+ ["nl"]="stelkadertekstenin",
+ ["pe"]="بارگذاری‌متن‌قالبی",
+ ["ro"]="definestetexteinconjurate",
+ },
+ ["setuphead"]={
+ ["cs"]="nastavnadpis",
+ ["de"]="stelleueberschriftein",
+ ["en"]="setuphead",
+ ["fr"]="regletete",
+ ["it"]="impostatesta",
+ ["nl"]="stelkopin",
+ ["pe"]="بارگذاری‌سر",
+ ["ro"]="seteazatitlu",
+ },
+ ["setupheader"]={
+ ["cs"]="nastavzahlavi",
+ ["de"]="stellekopfzeileein",
+ ["en"]="setupheader",
+ ["fr"]="regleentete",
+ ["it"]="impostainstestazione",
+ ["nl"]="stelhoofdin",
+ ["pe"]="بارگذاری‌سربرگ",
+ ["ro"]="seteazaantet",
+ },
+ ["setupheadertexts"]={
+ ["cs"]="nastavtextyzahlavi",
+ ["de"]="stellekopfzeilentextein",
+ ["en"]="setupheadertexts",
+ ["fr"]="regletextesentete",
+ ["it"]="impostatestiintestazioni",
+ ["nl"]="stelhoofdtekstenin",
+ ["pe"]="بارگذاری‌متن‌سربرگ",
+ ["ro"]="seteazatexteantet",
+ },
+ ["setupheadnumber"]={
+ ["cs"]="nastavcislonadpisu",
+ ["de"]="stellekopfzahlein",
+ ["en"]="setupheadnumber",
+ ["fr"]="reglenumerotete",
+ ["it"]="impostanumerotesta",
+ ["nl"]="stelkopnummerin",
+ ["pe"]="بارگذاری‌شماره‌سر",
+ ["ro"]="seteazanumartitlu",
+ },
+ ["setupheads"]={
+ ["cs"]="nastavnadpisy",
+ ["de"]="stelleueberschriftenein",
+ ["en"]="setupheads",
+ ["fr"]="regletetes",
+ ["it"]="impostateste",
+ ["nl"]="stelkoppenin",
+ ["pe"]="بارگذاری‌سرها",
+ ["ro"]="seteazatitluri",
+ },
+ ["setupheadtext"]={
+ ["cs"]="nastavtexthlavicky",
+ ["de"]="stelleueberschrifttextein",
+ ["en"]="setupheadtext",
+ ["fr"]="regletextetete",
+ ["it"]="impostatestointestazioni",
+ ["nl"]="stelkoptekstin",
+ ["pe"]="بارگذاری‌متن‌سر",
+ ["ro"]="seteazatexttitlu",
+ },
+ ["setuphyphenmark"]={
+ ["cs"]="nastavdelitko",
+ ["de"]="stellebindestrichein",
+ ["en"]="setuphyphenmark",
+ ["fr"]="reglemarquagehyphenation",
+ ["it"]="impostasegnosillabazione",
+ ["nl"]="stelkoppeltekenin",
+ ["pe"]="بارگذاری‌نشانه‌شکستن",
+ ["ro"]="seteazaliniesilabe",
+ },
+ ["setupindentedtext"]={
+ ["en"]="setupindentedtext",
+ ["nl"]="stelingesprongentextin",
+ },
+ ["setupindenting"]={
+ ["cs"]="nastavodsazovani",
+ ["de"]="stelleeinziehenein",
+ ["en"]="setupindenting",
+ ["fr"]="reglecomposeenalinea",
+ ["it"]="impostarientro",
+ ["nl"]="stelinspringenin",
+ ["pe"]="بارگذاری‌تورفتگی",
+ ["ro"]="seteazaaliniat",
+ },
+ ["setupinmargin"]={
+ ["cs"]="nastavmarginalie",
+ ["de"]="stelleinmarginalieein",
+ ["en"]="setupinmargin",
+ ["fr"]="regledansmarge",
+ ["it"]="impostainmargine",
+ ["nl"]="stelinmargein",
+ ["pe"]="بارگذاری‌درون‌حاشیه",
+ ["ro"]="seteazamarginal",
+ },
+ ["setupinteraction"]={
+ ["cs"]="nastavinterakci",
+ ["de"]="stelleinteraktionein",
+ ["en"]="setupinteraction",
+ ["fr"]="regleinteraction",
+ ["it"]="impostainterazione",
+ ["nl"]="stelinteractiein",
+ ["pe"]="بارگذاری‌پانل",
+ ["ro"]="seteazainteractiunea",
+ },
+ ["setupinteractionbar"]={
+ ["cs"]="nastavinterakcnilistu",
+ ["de"]="stelleinteraktionsbalkenein",
+ ["en"]="setupinteractionbar",
+ ["fr"]="reglebarreinteraction",
+ ["it"]="impostabarrainterazione",
+ ["nl"]="stelinteractiebalkin",
+ ["pe"]="بارگذاری‌میله‌پانل",
+ ["ro"]="seteazabarainteractiune",
+ },
+ ["setupinteractionmenu"]={
+ ["cs"]="nastavinterakcnimenu",
+ ["de"]="stelleinteraktionsmenueein",
+ ["en"]="setupinteractionmenu",
+ ["fr"]="reglemenuinteraction",
+ ["it"]="impostamenuinterazione",
+ ["nl"]="stelinteractiemenuin",
+ ["pe"]="بارگذاری‌منوی‌پانل",
+ ["ro"]="seteazameniuinteractiune",
+ },
+ ["setupinteractionscreen"]={
+ ["cs"]="nastavinterakcniobrazovku",
+ ["de"]="stelleinteraktionsbildschirmein",
+ ["en"]="setupinteractionscreen",
+ ["fr"]="regleecraninteraction",
+ ["it"]="impostaschermointerazione",
+ ["nl"]="stelinteractieschermin",
+ ["pe"]="بارگذاری‌پرده‌پانل",
+ ["ro"]="seteazaecraninteractiune",
+ },
+ ["setupinterlinespace"]={
+ ["cs"]="nastavmeziradkovoumezeru",
+ ["de"]="stellezeilenabstandein",
+ ["en"]="setupinterlinespace",
+ ["fr"]="regleespacementinterligne",
+ ["it"]="impostainterlinea",
+ ["nl"]="stelinterliniein",
+ ["pe"]="بارگذاری‌فاصله‌بین‌خط",
+ ["ro"]="seteazaspatiuinterliniar",
+ },
+ ["setupitemgroup"]={
+ ["cs"]="setupitemgroup",
+ ["de"]="setupitemgroup",
+ ["en"]="setupitemgroup",
+ ["fr"]="setupitemgroup",
+ ["it"]="setupitemgroup",
+ ["nl"]="stelitemgroepin",
+ ["pe"]="بارگذاری‌گروه‌آیتم",
+ ["ro"]="setupitemgroup",
+ },
+ ["setupitemgroups"]={
+ ["cs"]="nastavvycty",
+ ["de"]="stelleaufzaehlungenein",
+ ["en"]="setupitemizations",
+ ["fr"]="reglegroupeselements",
+ ["it"]="impostaelencazioni",
+ ["nl"]="stelopsommingenin",
+ ["pe"]="بارگذاری‌گروههای‌آیتم",
+ ["ro"]="setareitemization",
+ },
+ ["setupitems"]={
+ ["cs"]="nastavpolozky",
+ ["de"]="stellepostenein",
+ ["en"]="setupitems",
+ ["fr"]="regleelements",
+ ["it"]="impostaelementi",
+ ["nl"]="stelitemsin",
+ ["pe"]="بارگذاری‌آیتمها",
+ ["ro"]="seteazaelemente",
+ },
+ ["setuplabeltext"]={
+ ["cs"]="nastavtextpopisku",
+ ["de"]="stellelabeltextein",
+ ["en"]="setuplabeltext",
+ ["fr"]="reglelabeltexte",
+ ["it"]="impostatestoetichette",
+ ["nl"]="stellabeltekstin",
+ ["pe"]="باگذاری‌متن‌برچسب",
+ ["ro"]="seteazatexteticheta",
+ },
+ ["setuplanguage"]={
+ ["cs"]="nastavjazyk",
+ ["de"]="stellespracheein",
+ ["en"]="setuplanguage",
+ ["fr"]="reglelangue",
+ ["it"]="impostalingua",
+ ["nl"]="steltaalin",
+ ["pe"]="بارگذاری‌زبان",
+ ["ro"]="setarelimba",
+ },
+ ["setuplayout"]={
+ ["cs"]="nastavvzhled",
+ ["de"]="stellelayoutein",
+ ["en"]="setuplayout",
+ ["fr"]="regledisposition",
+ ["it"]="impostalayout",
+ ["nl"]="stellayoutin",
+ ["pe"]="بارگذاری‌طرح‌بندی",
+ ["ro"]="seteazaaspect",
+ },
+ ["setuplegend"]={
+ ["cs"]="nastavlegendu",
+ ["de"]="stellelegendeein",
+ ["en"]="setuplegend",
+ ["fr"]="reglelegende",
+ ["it"]="impostalegenda",
+ ["nl"]="stellegendain",
+ ["pe"]="بارگذاری‌راهنما",
+ ["ro"]="seteazalegenda",
+ },
+ ["setuplinenumbering"]={
+ ["cs"]="nastavcislovaniradku",
+ ["de"]="stellezeilennumerierungein",
+ ["en"]="setuplinenumbering",
+ ["fr"]="reglenumerotationligne",
+ ["it"]="impostanumerazionerighe",
+ ["nl"]="stelregelnummerenin",
+ ["pe"]="بارگذاری‌شماره‌‌گذاری‌خط",
+ ["ro"]="seteazanumerotarelinii",
+ },
+ ["setuplines"]={
+ ["cs"]="nastavradky",
+ ["de"]="stellezeilenein",
+ ["en"]="setuplines",
+ ["fr"]="reglelignes",
+ ["it"]="impostarighe",
+ ["nl"]="stelregelsin",
+ ["pe"]="بارگذاری‌خطها",
+ ["ro"]="seteazalinii",
+ },
+ ["setuplinewidth"]={
+ ["cs"]="nastavsirkucary",
+ ["de"]="stellelinienbreiteein",
+ ["en"]="setuplinewidth",
+ ["fr"]="regleepaisseurligne",
+ ["it"]="impostaampiezzariga",
+ ["nl"]="stellijndiktein",
+ ["pe"]="بارگذاری‌عرض‌خط",
+ ["ro"]="seteazagrosimelinie",
+ },
+ ["setuplist"]={
+ ["cs"]="nastavseznam",
+ ["de"]="stellelisteein",
+ ["en"]="setuplist",
+ ["fr"]="regleliste",
+ ["it"]="impostaelenco",
+ ["nl"]="stellijstin",
+ ["pe"]="بارگذاری‌لیست",
+ ["ro"]="seteazalista",
+ },
+ ["setupmakeup"]={
+ ["cs"]="nastavupravu",
+ ["de"]="stelleumbruchein",
+ ["en"]="setupmakeup",
+ ["fr"]="reglemakeup",
+ ["it"]="impostamakeup",
+ ["nl"]="stelopmaakin",
+ ["pe"]="بارگذاری‌آرایش",
+ ["ro"]="seteazamakeup",
+ },
+ ["setupmarginblocks"]={
+ ["cs"]="nastavmarginalniblok",
+ ["de"]="stellemarginalblockein",
+ ["en"]="setupmarginblocks",
+ ["fr"]="regleblocmarge",
+ ["it"]="impostablocchimargine",
+ ["nl"]="stelmargeblokkenin",
+ ["pe"]="بارگذاری‌بلوکهای‌حاشیه",
+ ["ro"]="seteazablocurimarginale",
+ },
+ ["setupmarginrules"]={
+ ["cs"]="nastavmarginalnilinky",
+ ["de"]="stellemarginallinieein",
+ ["en"]="setupmarginrules",
+ ["fr"]="reglemargereglee",
+ ["it"]="impostalineemargine",
+ ["nl"]="stelkantlijnin",
+ ["pe"]="بارگذاری‌خطهای‌حاشیه",
+ ["ro"]="seteazaliniimargine",
+ },
+ ["setupmarking"]={
+ ["cs"]="nastavznaceni",
+ ["de"]="stellebeschriftungein",
+ ["en"]="setupmarking",
+ ["fr"]="reglemarquage",
+ ["it"]="impostamarcatura",
+ ["nl"]="stelmarkeringin",
+ ["pe"]="بارگذاری‌نشانه‌گذاری",
+ ["ro"]="seteazamarcaje",
+ },
+ ["setupmathalignment"]={
+ ["cs"]="setupmathalignment",
+ ["de"]="setupmathalignment",
+ ["en"]="setupmathalignment",
+ ["fr"]="setupmathalignment",
+ ["it"]="setupmathalignment",
+ ["nl"]="stelwiskundeuitlijnenin",
+ ["pe"]="بارگذاری‌تنظیم‌ریاضی",
+ ["ro"]="setupmathalignment",
+ },
+ ["setupnarrower"]={
+ ["cs"]="nastavzuzeni",
+ ["de"]="stelleengerein",
+ ["en"]="setupnarrower",
+ ["fr"]="reglecompoetroite",
+ ["it"]="impostapiustretto",
+ ["nl"]="stelsmallerin",
+ ["pe"]="بارگذاری‌باریکتر",
+ ["ro"]="seteazaingust",
+ },
+ ["setupnumber"]={
+ ["cs"]="setupnumber",
+ ["de"]="setupnumber",
+ ["en"]="setupnumber",
+ ["fr"]="reglenumero",
+ ["it"]="impostanumerazione",
+ ["nl"]="stelnummerin",
+ ["pe"]="بارگذاری‌شماره",
+ ["ro"]="setupnumber",
+ },
+ ["setupnumbering"]={
+ ["cs"]="nastavcislovani",
+ ["de"]="stellenummerierungein",
+ ["en"]="setupnumbering",
+ ["fr"]="reglenumerotation",
+ ["it"]="impostanumerazione",
+ ["nl"]="stelnummerenin",
+ ["pe"]="بارگذاری‌شماره‌گذاری",
+ ["ro"]="seteazanumerotare",
+ },
+ ["setupoppositeplacing"]={
+ ["cs"]="nastavumisteniprotejsku",
+ ["de"]="stellegegenueberplatzierenein",
+ ["en"]="setupoppositeplacing",
+ ["fr"]="regleplacementopposition",
+ ["it"]="impostaposizionamentoopposti",
+ ["nl"]="stelnaastplaatsenin",
+ ["pe"]="بارگذاری‌درج‌مخالف",
+ ["ro"]="seteazaplasareaopozita",
+ },
+ ["setupoutput"]={
+ ["cs"]="nastavvystup",
+ ["de"]="stelleausgabeein",
+ ["en"]="setupoutput",
+ ["fr"]="reglesortie",
+ ["it"]="impostaoutput",
+ ["nl"]="steluitvoerin",
+ ["pe"]="بارگذاری‌خروجی",
+ ["ro"]="setareoutput",
+ },
+ ["setuppagecomment"]={
+ ["cs"]="nastavkomentarstrany",
+ ["de"]="stelleseitenkommentarein",
+ ["en"]="setuppagecomment",
+ ["fr"]="reglecommentairepage",
+ ["it"]="impostacommentopagina",
+ ["nl"]="stelpaginacommentaarin",
+ ["pe"]="بارگذاری‌توضیح‌صفحه",
+ ["ro"]="seteazacomentariupagina",
+ },
+ ["setuppagenumber"]={
+ ["cs"]="nastavcislostrany",
+ ["de"]="stelleseitennummerein",
+ ["en"]="setuppagenumber",
+ ["fr"]="reglenumeropage",
+ ["it"]="impostanumeropagina",
+ ["nl"]="stelpaginanummerin",
+ ["pe"]="بارگذاری‌شماره‌صفحه",
+ ["ro"]="seteazanumarpagina",
+ },
+ ["setuppagenumbering"]={
+ ["cs"]="nastavcislovanistran",
+ ["de"]="stelleseitennummeriernungein",
+ ["en"]="setuppagenumbering",
+ ["fr"]="reglenumerotationpage",
+ ["it"]="impostanumerazionepagina",
+ ["nl"]="stelpaginanummeringin",
+ ["pe"]="بارگذاری‌شماره‌گذاری‌صفحه",
+ ["ro"]="seteazanumerotarepagina",
+ },
+ ["setuppagetransitions"]={
+ ["cs"]="nastavprechodstrany",
+ ["de"]="stelleseitenuebergangein",
+ ["en"]="setuppagetransitions",
+ ["fr"]="regletransitionspage",
+ ["it"]="impostatransizionepagina",
+ ["nl"]="stelpaginaovergangenin",
+ ["pe"]="بارگذاری‌گذارصفحه",
+ ["ro"]="seteazatranzitiepagina",
+ },
+ ["setuppalet"]={
+ ["cs"]="nastavpaletu",
+ ["de"]="stellepaletteein",
+ ["en"]="setuppalet",
+ ["fr"]="reglepalette",
+ ["it"]="impostatavolozza",
+ ["nl"]="stelpaletin",
+ ["pe"]="بارگذاری‌لوح",
+ ["ro"]="seteazapaleta",
+ },
+ ["setuppaper"]={
+ ["cs"]="setuppaper",
+ ["de"]="setuppaper",
+ ["en"]="setuppaper",
+ ["fr"]="reglepapier",
+ ["it"]="setuppaper",
+ ["nl"]="stelpapierin",
+ ["pe"]="بارگذاری‌برگ",
+ ["ro"]="setuppaper",
+ },
+ ["setuppapersize"]={
+ ["cs"]="nastavvelikostpapiru",
+ ["de"]="stellepapierformatein",
+ ["en"]="setuppapersize",
+ ["fr"]="regletaillepapier",
+ ["it"]="impostadimensionicarta",
+ ["nl"]="stelpapierformaatin",
+ ["pe"]="بارگذاری‌اندازه‌برگ",
+ ["ro"]="seteazadimensiunihartie",
+ },
+ ["setupparagraphnumbering"]={
+ ["cs"]="nastavcislovaniodstavcu",
+ ["de"]="stelleabsatznummerierungein",
+ ["en"]="setupparagraphnumbering",
+ ["fr"]="reglenumerotationparagraphe",
+ ["it"]="impostanumerazionecapoversi",
+ ["nl"]="stelparagraafnummerenin",
+ ["pe"]="بارگذاری‌شماره‌گذاری‌پاراگراف",
+ ["ro"]="seteazanumerotareparagrafe",
+ },
+ ["setupparagraphs"]={
+ ["cs"]="nastavodstavce",
+ ["de"]="stelleabsaetzeein",
+ ["en"]="setupparagraphs",
+ ["fr"]="regleparagraphes",
+ ["it"]="impostacapoversi",
+ ["nl"]="stelalineasin",
+ ["pe"]="بارگذاری‌پاراگرافها",
+ ["ro"]="seteazaparagrafe",
+ },
+ ["setupplacement"]={
+ ["cs"]="setupplacement",
+ ["de"]="setupplacement",
+ ["en"]="setupplacement",
+ ["fr"]="setupplacement",
+ ["it"]="setupplacement",
+ ["nl"]="stelplaatsin",
+ ["pe"]="بارگذاری‌جانشانی",
+ ["ro"]="setupplacement",
+ },
+ ["setuppositioning"]={
+ ["cs"]="nastavumistovani",
+ ["de"]="stellepositionierenein",
+ ["en"]="setuppositioning",
+ ["fr"]="reglepositionnement",
+ ["it"]="impostaposizionamento",
+ ["nl"]="stelpositionerenin",
+ ["pe"]="بارگذاری‌مکان‌گذاری",
+ ["ro"]="setarepozitie",
+ },
+ ["setupprofiles"]={
+ ["cs"]="nastavprofily",
+ ["de"]="stelleprofilein",
+ ["en"]="setupprofiles",
+ ["fr"]="regleprofils",
+ ["it"]="impostaprofili",
+ ["nl"]="stelprofielenin",
+ ["pe"]="بارگذاری‌پروفایلها",
+ ["ro"]="seteazaprofile",
+ },
+ ["setupprograms"]={
+ ["cs"]="nastavprogramy",
+ ["de"]="stelleprogrammein",
+ ["en"]="setupprograms",
+ ["fr"]="regleprogrammes",
+ ["it"]="impostaprogrammi",
+ ["nl"]="stelprogrammasin",
+ ["pe"]="بارگذاری‌برنامه‌ها",
+ ["ro"]="seteazaprograme",
+ },
+ ["setuppublications"]={
+ ["cs"]="nastavpublikace",
+ ["de"]="stellepublikationein",
+ ["en"]="setuppublications",
+ ["fr"]="reglepublications",
+ ["it"]="impostapubblicazioni",
+ ["nl"]="stelpublicatiesin",
+ ["pe"]="بارگذاری‌نشرها",
+ ["ro"]="seteazapublicatii",
+ },
+ ["setupquote"]={
+ ["cs"]="nastavcitaci",
+ ["de"]="stellezitierenein",
+ ["en"]="setupquote",
+ ["fr"]="demarreciter",
+ ["it"]="impostamenzione",
+ ["nl"]="stelciterenin",
+ ["pe"]="بارگذاری‌نقل",
+ ["ro"]="seteazaminicitat",
+ },
+ ["setupreferencelist"]={
+ ["cs"]="nastavseznamodkazu",
+ ["de"]="stellereferenzlisteein",
+ ["en"]="setupreferencelist",
+ ["fr"]="reglelistereference",
+ ["it"]="impostalistariferimenti",
+ ["nl"]="stelreferentielijstin",
+ ["pe"]="بارگذاری‌لیست‌مرجع",
+ ["ro"]="seteazalistareferinte",
+ },
+ ["setupreferencing"]={
+ ["cs"]="nastavodkazovani",
+ ["de"]="stellereferenzierenein",
+ ["en"]="setupreferencing",
+ ["fr"]="reglereferencage",
+ ["it"]="impostariferimento",
+ ["nl"]="stelrefererenin",
+ ["pe"]="بارگذاری‌ارجاع",
+ ["ro"]="seteazareferinte",
+ },
+ ["setupregister"]={
+ ["cs"]="nastavrejstrik",
+ ["de"]="stelleregisterein",
+ ["en"]="setupregister",
+ ["fr"]="regleregistre",
+ ["it"]="impostaregistro",
+ ["nl"]="stelregisterin",
+ ["pe"]="بارگذاری‌ثبت",
+ ["ro"]="seteazaregistru",
+ },
+ ["setuprotate"]={
+ ["cs"]="nastavotoceni",
+ ["de"]="stelledrehenein",
+ ["en"]="setuprotate",
+ ["fr"]="regleoriente",
+ ["it"]="impostarotazione",
+ ["nl"]="stelroterenin",
+ ["pe"]="بارگذاری‌دوران",
+ ["ro"]="seteazarotare",
+ },
+ ["setuprule"]={
+ ["cs"]="setuprule",
+ ["de"]="setuprule",
+ ["en"]="setuprule",
+ ["fr"]="regleregle",
+ ["it"]="impostalinea",
+ ["nl"]="stellijnin",
+ ["pe"]="بارگذاری‌خط",
+ ["ro"]="seteazarigla",
+ },
+ ["setupscreens"]={
+ ["cs"]="nastavrastr",
+ ["de"]="stellerasterein",
+ ["en"]="setupscreens",
+ ["fr"]="regleecrans",
+ ["it"]="impostaschermi",
+ ["nl"]="stelrastersin",
+ ["pe"]="بارگذاری‌پرده‌ها",
+ ["ro"]="seteazaecrane",
+ },
+ ["setupsection"]={
+ ["cs"]="nastavsekci",
+ ["de"]="stelleabschnittein",
+ ["en"]="setupsection",
+ ["fr"]="reglesection",
+ ["it"]="impostasezione",
+ ["nl"]="stelsectiein",
+ ["pe"]="بارگذاری‌بخش",
+ ["ro"]="seteazasectiune",
+ },
+ ["setupsectionblock"]={
+ ["cs"]="nastavbloksekce",
+ ["de"]="stelleabschnittsblockein",
+ ["en"]="setupsectionblock",
+ ["fr"]="regleblocsection",
+ ["it"]="impostabloccosezione",
+ ["nl"]="stelsectieblokin",
+ ["pe"]="بارگذاری‌بلوک‌بخش",
+ ["ro"]="seteazablocsectiune",
+ },
+ ["setupsorting"]={
+ ["cs"]="nastavtrideni",
+ ["de"]="stellesortierenein",
+ ["en"]="setupsorting",
+ ["fr"]="regletri",
+ ["it"]="impostaordinamento",
+ ["nl"]="stelsorterenin",
+ ["pe"]="بارگذاری‌ترتیب",
+ ["ro"]="seteazasortare",
+ },
+ ["setupspacing"]={
+ ["cs"]="nastavradkovani",
+ ["de"]="stellespatiumein",
+ ["en"]="setupspacing",
+ ["fr"]="regleespacement",
+ ["it"]="impostaspaziatura",
+ ["nl"]="stelspatieringin",
+ ["pe"]="بارگذاری‌فضا‌گذاری",
+ ["ro"]="seteazaspatiu",
+ },
+ ["setupstartstop"]={
+ ["cs"]="setupstartstop",
+ ["de"]="setupstartstop",
+ ["en"]="setupstartstop",
+ ["fr"]="regledemarrestoppe",
+ ["it"]="impostainiziatermina",
+ ["nl"]="stelstartstopin",
+ ["pe"]="بارگذاری‌شروع‌پایان",
+ ["ro"]="setupstartstop",
+ },
+ ["setupstrut"]={
+ ["cs"]="setupstrut",
+ ["de"]="setupstrut",
+ ["en"]="setupstrut",
+ ["fr"]="reglestrut",
+ ["it"]="impostastrut",
+ ["nl"]="stelstrutin",
+ ["pe"]="بارگذاری‌بست",
+ ["ro"]="seteazastrut",
+ },
+ ["setupsubpagenumber"]={
+ ["cs"]="nastavpodcislostrany",
+ ["de"]="stelleunterseitennummerein",
+ ["en"]="setupsubpagenumber",
+ ["fr"]="reglesousnumeropage",
+ ["it"]="impostanumerosottopagina",
+ ["nl"]="stelsubpaginanummerin",
+ ["pe"]="بارگذاری‌شماره‌زیرصفحه",
+ ["ro"]="seteazanumarsubpagina",
+ },
+ ["setupsymbolset"]={
+ ["cs"]="nastavsadusymbolu",
+ ["de"]="stellesymbolsetein",
+ ["en"]="setupsymbolset",
+ ["fr"]="reglejeusymboles",
+ ["it"]="impostasetsimboli",
+ ["nl"]="stelsymboolsetin",
+ ["pe"]="بارگذاری‌مجموعه‌نماد",
+ ["ro"]="seteazasimbol",
+ },
+ ["setupsynchronization"]={
+ ["cs"]="nastavsynchronizaci",
+ ["de"]="stellesynchronisationein",
+ ["en"]="setupsynchronization",
+ ["fr"]="reglesynchronisation",
+ ["it"]="impostasincronizzazione",
+ ["nl"]="stelsynchronisatiein",
+ ["pe"]="بارگذاری‌تطابق",
+ ["ro"]="setaresincronizare",
+ },
+ ["setupsynchronizationbar"]={
+ ["cs"]="nastavsynchronizacnilistu",
+ ["de"]="stellesynchronisationsbalkenein",
+ ["en"]="setupsynchronizationbar",
+ ["fr"]="reglebarresynchronisation",
+ ["it"]="impostabarrasincronizzazione",
+ ["nl"]="stelsynchronisatiebalkin",
+ ["pe"]="بارگذاری‌میله‌تطابق",
+ ["ro"]="setarebarasincronizare",
+ },
+ ["setupsynonyms"]={
+ ["cs"]="nastavsynonyma",
+ ["de"]="stellesynonymein",
+ ["en"]="setupsynonyms",
+ ["fr"]="reglesynonymes",
+ ["it"]="impostasinonimi",
+ ["nl"]="stelsynoniemenin",
+ ["pe"]="بارگذاری‌مترادفها",
+ ["ro"]="seteazasinonime",
+ },
+ ["setupsystem"]={
+ ["cs"]="nastavsystem",
+ ["de"]="stellesystemein",
+ ["en"]="setupsystem",
+ ["fr"]="reglesysteme",
+ ["it"]="impostasistema",
+ ["nl"]="stelsysteemin",
+ ["pe"]="بارگذاری‌سیستم",
+ ["ro"]="seteazasistem",
+ },
+ ["setuptab"]={
+ ["cs"]="nastavtab",
+ ["de"]="stelletabein",
+ ["en"]="setuptab",
+ ["fr"]="regletab",
+ ["it"]="impostatab",
+ ["nl"]="steltabin",
+ ["pe"]="بارگذاری‌تب",
+ ["ro"]="seteazatab",
+ },
+ ["setuptables"]={
+ ["cs"]="nastavtabulky",
+ ["de"]="stelletabellenein",
+ ["en"]="setuptables",
+ ["fr"]="regletableaux",
+ ["it"]="impostatabelle",
+ ["nl"]="steltabellenin",
+ ["pe"]="بارگذاری‌جدولها",
+ ["ro"]="seteazatabele",
+ },
+ ["setuptabulate"]={
+ ["cs"]="nastavtabelaci",
+ ["de"]="stelletabulatorein",
+ ["en"]="setuptabulate",
+ ["fr"]="regletabulation",
+ ["it"]="impostatabulato",
+ ["nl"]="steltabulatiein",
+ ["pe"]="بارگذاری‌جدول‌بندی",
+ ["ro"]="seteazatabulatori",
+ },
+ ["setuptext"]={
+ ["cs"]="nastavtext",
+ ["de"]="stelletextein",
+ ["en"]="setuptext",
+ ["fr"]="regletexte",
+ ["it"]="impostatesto",
+ ["nl"]="steltekstin",
+ ["pe"]="بارگذاری‌متن",
+ ["ro"]="seteazatext",
+ },
+ ["setuptextbackground"]={
+ ["en"]="setuptextbackground",
+ ["nl"]="steltekstachtergrondin",
+ },
+ ["setuptextposition"]={
+ ["cs"]="setuptextposition",
+ ["de"]="setuptextposition",
+ ["en"]="setuptextposition",
+ ["fr"]="reglepositiontexte",
+ ["it"]="impostaposizionetesto",
+ ["nl"]="steltekstpositiein",
+ ["pe"]="بارگذاری‌مکان‌متن",
+ ["ro"]="seteazapozitietext",
+ },
+ ["setuptextrules"]={
+ ["cs"]="nastavtextovelinky",
+ ["de"]="stelletextumrissein",
+ ["en"]="setuptextrules",
+ ["fr"]="reglelignesreglestexte",
+ ["it"]="impostalineetesto",
+ ["nl"]="steltekstlijnenin",
+ ["pe"]="بارگذاری‌خطهای‌متن",
+ ["ro"]="seteazarigletext",
+ },
+ ["setuptexttexts"]={
+ ["cs"]="nastavtexttexty",
+ ["de"]="stelletexttexteein",
+ ["en"]="setuptexttexts",
+ ["fr"]="regletextestexte",
+ ["it"]="impostatestotesti",
+ ["nl"]="stelteksttekstenin",
+ ["pe"]="بارگذاری‌متن‌متنها",
+ ["ro"]="seteazatextetext",
+ },
+ ["setuptextvariable"]={
+ ["cs"]="setuptextvariable",
+ ["de"]="setuptextvariable",
+ ["en"]="setuptextvariable",
+ ["fr"]="reglevariabletexte",
+ ["it"]="impostavariabiletesto",
+ ["nl"]="steltekstvariabelein",
+ ["pe"]="بارگذاری‌متغیر‌متن",
+ ["ro"]="seteazavariabilatext",
+ },
+ ["setupthinrules"]={
+ ["cs"]="nastavtenkelinky",
+ ["de"]="stelleduennerumrissein",
+ ["en"]="setupthinrules",
+ ["fr"]="regletraitsfins",
+ ["it"]="impostalineesottili",
+ ["nl"]="steldunnelijnenin",
+ ["pe"]="بارگذاری‌خطها‌ی‌نازک",
+ ["ro"]="seteazaliniesubtire",
+ },
+ ["setuptolerance"]={
+ ["cs"]="nastavtoleranci",
+ ["de"]="stelletoleranzein",
+ ["en"]="setuptolerance",
+ ["fr"]="regletolerance",
+ ["it"]="impostatolleranza",
+ ["nl"]="steltolerantiein",
+ ["pe"]="بارگذاری‌بردباری",
+ ["ro"]="seteazatoleranta",
+ },
+ ["setuptop"]={
+ ["cs"]="nastavhorejsek",
+ ["de"]="stellenobenein",
+ ["en"]="setuptop",
+ ["fr"]="reglesup",
+ ["it"]="impostacima",
+ ["nl"]="stelbovenin",
+ ["pe"]="بارگذاری‌بالا",
+ ["ro"]="seteazasus",
+ },
+ ["setuptoptexts"]={
+ ["cs"]="nastavhornitexty",
+ ["de"]="stelletextobenein",
+ ["en"]="setuptoptexts",
+ ["fr"]="regletextessup",
+ ["it"]="impostatesticima",
+ ["nl"]="stelboventekstenin",
+ ["pe"]="بارگذاری‌متنهای‌بالا",
+ ["ro"]="seteazatextesus",
+ },
+ ["setuptype"]={
+ ["cs"]="nastavtype",
+ ["de"]="stelletipein",
+ ["en"]="setuptype",
+ ["fr"]="regletype",
+ ["it"]="impostatype",
+ ["nl"]="steltypein",
+ ["pe"]="بارگذاری‌تایپ",
+ ["ro"]="seteazatype",
+ },
+ ["setuptyping"]={
+ ["cs"]="nastavopis",
+ ["de"]="stelletippenein",
+ ["en"]="setuptyping",
+ ["fr"]="regledactylo",
+ ["it"]="impostatyping",
+ ["nl"]="steltypenin",
+ ["pe"]="بارگذاری‌تایپ‌کردن",
+ ["ro"]="seteazatyping",
+ },
+ ["setupunderbar"]={
+ ["cs"]="nastavpodtrzeni",
+ ["de"]="stelleunterstreichenein",
+ ["en"]="setupunderbar",
+ ["fr"]="reglesouslignage",
+ ["it"]="impostasottolinea",
+ ["nl"]="stelonderstrepenin",
+ ["pe"]="بارگذاری‌میله‌زیر",
+ ["ro"]="seteazasublinie",
+ },
+ ["setupurl"]={
+ ["cs"]="nastavurl",
+ ["de"]="stelleurlein",
+ ["en"]="setupurl",
+ ["fr"]="regleurl",
+ ["it"]="impostaurl",
+ ["nl"]="stelurlin",
+ ["pe"]="setupurl",
+ ["ro"]="seteazaurl",
+ },
+ ["setupversions"]={
+ ["cs"]="nastavverze",
+ ["de"]="stelleversionein",
+ ["en"]="setupversions",
+ ["fr"]="regleversions",
+ ["it"]="impostaversioni",
+ ["nl"]="stelversiesin",
+ ["pe"]="بارگذاری‌نسخه‌ها",
+ ["ro"]="seteazaversiuni",
+ },
+ ["setupwhitespace"]={
+ ["cs"]="nastavbilamista",
+ ["de"]="stellezwischenraumein",
+ ["en"]="setupwhitespace",
+ ["fr"]="regleespaceblanc",
+ ["it"]="impostaspaziobianco",
+ ["nl"]="stelwitruimtein",
+ ["pe"]="بارگذاری‌فضای‌سفید",
+ ["ro"]="seteazaspatiualb",
+ },
+ ["showbodyfont"]={
+ ["cs"]="ukazzakladnifont",
+ ["de"]="zeigefliesstext",
+ ["en"]="showbodyfont",
+ ["fr"]="montrepolicecorps",
+ ["it"]="mostrafontdeltesto",
+ ["nl"]="toonkorps",
+ ["pe"]="نمایش‌قلم‌بدنه",
+ ["ro"]="afiseazafonttext",
+ },
+ ["showbodyfontenvironment"]={
+ ["cs"]="ukazpostredizakladnihofontu",
+ ["de"]="zeigefliesstextumgebung",
+ ["en"]="showbodyfontenvironment",
+ ["fr"]="montreenvironnementpolicecorps",
+ ["it"]="mostraambientefontdeltesto",
+ ["nl"]="toonkorpsomgeving",
+ ["pe"]="نمایش‌محیط‌قلم‌بدنه",
+ ["ro"]="afiseazamediufonttext",
+ },
+ ["showcolor"]={
+ ["cs"]="ukazbarvu",
+ ["de"]="zeigefarbe",
+ ["en"]="showcolor",
+ ["fr"]="montrecouleur",
+ ["it"]="mostracolore",
+ ["nl"]="toonkleur",
+ ["pe"]="نمایش‌رنگ",
+ ["ro"]="afiseazaculoare",
+ },
+ ["showcolorgroup"]={
+ ["cs"]="ukazskupinubarev",
+ ["de"]="zeigefarbengruppe",
+ ["en"]="showcolorgroup",
+ ["fr"]="montregroupecouleur",
+ ["it"]="mostragruppocolori",
+ ["nl"]="toonkleurgroep",
+ ["pe"]="نمایش‌گروه‌رنگ",
+ ["ro"]="afiseazagrupculoare",
+ },
+ ["showexternalfigures"]={
+ ["cs"]="ukazexterniobrazy",
+ ["de"]="zeigeexterneabbildungen",
+ ["en"]="showexternalfigures",
+ ["fr"]="montrefiguresexternes",
+ ["it"]="mostrafiguresterne",
+ ["nl"]="toonexternefiguren",
+ ["pe"]="نمایش‌شکلهای‌خارجی",
+ ["ro"]="afiseazafiguriexterne",
+ },
+ ["showfields"]={
+ ["cs"]="ukazpole",
+ ["de"]="zeigefelder",
+ ["en"]="showfields",
+ ["fr"]="montrechamps",
+ ["it"]="mostracampi",
+ ["nl"]="toonvelden",
+ ["pe"]="نمایش‌میدانها",
+ ["ro"]="afiseazacampuri",
+ },
+ ["showframe"]={
+ ["cs"]="ukazramecek",
+ ["de"]="zeigerahmen",
+ ["en"]="showframe",
+ ["fr"]="montrecadre",
+ ["it"]="mostracornice",
+ ["nl"]="toonkader",
+ ["pe"]="نمایش‌قالب",
+ ["ro"]="afiseazarama",
+ },
+ ["showgrid"]={
+ ["cs"]="ukazmrizku",
+ ["de"]="zeigegitter",
+ ["en"]="showgrid",
+ ["fr"]="montregrille",
+ ["it"]="mostragriglia",
+ ["nl"]="toongrid",
+ ["pe"]="نمایش‌توری",
+ ["ro"]="afiseazagrid",
+ },
+ ["showlayout"]={
+ ["cs"]="ukazvzhled",
+ ["de"]="zeigelayout",
+ ["en"]="showlayout",
+ ["fr"]="montredisposition",
+ ["it"]="mostralyout",
+ ["nl"]="toonlayout",
+ ["pe"]="نمایش‌طرح‌بندی",
+ ["ro"]="afiseazaaspect",
+ },
+ ["showmakeup"]={
+ ["cs"]="ukazupravu",
+ ["de"]="zeigeumbruch",
+ ["en"]="showmakeup",
+ ["fr"]="montremakeup",
+ ["it"]="mostramakeup",
+ ["nl"]="toonopmaak",
+ ["pe"]="نمایش‌آرایش",
+ ["ro"]="afiseazamakeup",
+ },
+ ["showpalet"]={
+ ["cs"]="ukazpaletu",
+ ["de"]="zeigepalette",
+ ["en"]="showpalet",
+ ["fr"]="montrepalette",
+ ["it"]="mostratavolozza",
+ ["nl"]="toonpalet",
+ ["pe"]="نمایش‌لوح",
+ ["ro"]="afiseazapaleta",
+ },
+ ["showprint"]={
+ ["cs"]="ukazvytisk",
+ ["de"]="zeigedruck",
+ ["en"]="showprint",
+ ["fr"]="montreedition",
+ ["it"]="mostrastampa",
+ ["nl"]="toonprint",
+ ["pe"]="نمایش‌چاپ",
+ ["ro"]="afiseazatiparire",
+ },
+ ["showsetups"]={
+ ["cs"]="ukaznastaveni",
+ ["de"]="zeigeeinstellungen",
+ ["en"]="showsetups",
+ ["fr"]="montrereglages",
+ ["it"]="mostraimpostazioni",
+ ["nl"]="tooninstellingen",
+ ["pe"]="نمایش‌بارگذاریها",
+ ["ro"]="afiseazasetari",
+ },
+ ["showstruts"]={
+ ["cs"]="ukazpodpery",
+ ["de"]="zeigestruts",
+ ["en"]="showstruts",
+ ["fr"]="montrestruts",
+ ["it"]="mostrastruts",
+ ["nl"]="toonstruts",
+ ["pe"]="نمایش‌بستها",
+ ["ro"]="afiseazastruts",
+ },
+ ["showsymbolset"]={
+ ["cs"]="ukazsadusymbolu",
+ ["de"]="showsymbolset",
+ ["en"]="showsymbolset",
+ ["fr"]="montrejeusymboles",
+ ["it"]="mostrasetsimboli",
+ ["nl"]="toonsymboolset",
+ ["pe"]="نمایش‌مجموعه‌علامت",
+ ["ro"]="afiseazasetsimboluri",
+ },
+ ["smallcapped"]={
+ ["cs"]="kap",
+ ["de"]="kap",
+ ["en"]="cap",
+ ["fr"]="cap",
+ ["it"]="cap",
+ ["nl"]="kap",
+ ["pe"]="cap",
+ ["ro"]="kap",
+ },
+ ["someline"]={
+ ["cs"]="nejakyradek",
+ ["de"]="einezeile",
+ ["en"]="someline",
+ ["fr"]="uneligne",
+ ["it"]="qualcheriga",
+ ["nl"]="eenregel",
+ ["pe"]="یک‌خط",
+ ["ro"]="olinie",
+ },
+ ["somewhere"]={
+ ["cs"]="nekde",
+ ["de"]="irgendwo",
+ ["en"]="somewhere",
+ ["fr"]="qqpart",
+ ["it"]="daqualcheparte",
+ ["nl"]="ergens",
+ ["pe"]="یک‌جا",
+ ["ro"]="undeva",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["splitfloat"]={
+ ["cs"]="rozdelplvouciobjekt",
+ ["de"]="teilegleitobjekt",
+ ["en"]="splitfloat",
+ ["fr"]="separeflottant",
+ ["it"]="spezzaoggettomobile",
+ ["nl"]="splitsplaatsblok",
+ ["pe"]="شکافتن‌شناور",
+ ["ro"]="impartefloat",
+ },
+ ["startalignment"]={
+ ["cs"]="startzarovnavani",
+ ["de"]="startausrichtung",
+ ["en"]="startalignment",
+ ["fr"]="demarrealignement",
+ ["it"]="iniziaallineamento",
+ ["nl"]="startuitlijnen",
+ ["pe"]="شروع‌تنظیم",
+ ["ro"]="startaliniere",
+ },
+ ["startbackground"]={
+ ["cs"]="startpozadi",
+ ["de"]="starthintergrund",
+ ["en"]="startbackground",
+ ["fr"]="demarrearriereplan",
+ ["it"]="iniziasfondo",
+ ["nl"]="startachtergrond",
+ ["pe"]="شروع‌پس‌زمینه",
+ ["ro"]="startfundal",
+ },
+ ["startcoding"]={
+ ["cs"]="startkodovani",
+ ["de"]="startkodierung",
+ ["en"]="startcoding",
+ ["fr"]="demarrecodage",
+ ["it"]="iniziacodifica",
+ ["nl"]="startcodering",
+ ["pe"]="شروع‌کد",
+ ["ro"]="startcodificare",
+ },
+ ["startcolor"]={
+ ["cs"]="startbarva",
+ ["de"]="startfarbe",
+ ["en"]="startcolor",
+ ["fr"]="demarrecouleur",
+ ["it"]="iniziacolore",
+ ["nl"]="startkleur",
+ ["pe"]="شروع‌رنگ",
+ ["ro"]="startculoare",
+ },
+ ["startcolumnmakeup"]={
+ ["cs"]="startcolumnmakeup",
+ ["de"]="startcolumnmakeup",
+ ["en"]="startcolumnmakeup",
+ ["fr"]="startcolumnmakeup",
+ ["it"]="startcolumnmakeup",
+ ["nl"]="startkolomopmaak",
+ ["pe"]="شروع‌آرایش‌ستون",
+ ["ro"]="startcolumnmakeup",
+ },
+ ["startcolumns"]={
+ ["cs"]="startsloupce",
+ ["de"]="startspalten",
+ ["en"]="startcolumns",
+ ["fr"]="demarrecolonnes",
+ ["it"]="iniziacolonne",
+ ["nl"]="startkolommen",
+ ["pe"]="شروع‌ستونها",
+ ["ro"]="startcoloane",
+ },
+ ["startcolumnset"]={
+ ["cs"]="startcolumnset",
+ ["de"]="startcolumnset",
+ ["en"]="startcolumnset",
+ ["fr"]="demarrejeucolonne",
+ ["it"]="iniziagruppocolonne",
+ ["nl"]="startkolomgroep",
+ ["pe"]="شروع‌مجموعه‌ستون",
+ ["ro"]="startcolumnset",
+ },
+ ["startcombination"]={
+ ["cs"]="startspojeni",
+ ["de"]="startkombination",
+ ["en"]="startcombination",
+ ["fr"]="demarrecombinaison",
+ ["it"]="iniziacombinazione",
+ ["nl"]="startcombinatie",
+ ["pe"]="شروع‌ترکیب",
+ ["ro"]="startcombinare",
+ },
+ ["startcomponent"]={
+ ["cs"]="startkomponenta",
+ ["de"]="startkomponente",
+ ["en"]="startcomponent",
+ ["fr"]="demarrecomposant",
+ ["it"]="iniziacomponente",
+ ["nl"]="startonderdeel",
+ ["pe"]="شروع‌مولفه",
+ ["ro"]="startcomponenta",
+ },
+ ["startdocument"]={
+ ["cs"]="startdokument",
+ ["de"]="startdokument",
+ ["en"]="startdocument",
+ ["fr"]="demarredocument",
+ ["it"]="iniziadocumento",
+ ["nl"]="startdocument",
+ ["pe"]="شروع‌نوشتار",
+ ["ro"]="startdocument",
+ },
+ ["startenvironment"]={
+ ["cs"]="startprostredi",
+ ["de"]="startumgebung",
+ ["en"]="startenvironment",
+ ["fr"]="demarreenvironement",
+ ["it"]="iniziaambiente",
+ ["nl"]="startomgeving",
+ ["pe"]="شروع‌محیط",
+ ["ro"]="startmediu",
+ },
+ ["startfigure"]={
+ ["cs"]="startobraz",
+ ["de"]="startabbildung",
+ ["en"]="startfigure",
+ ["fr"]="demarrefigure",
+ ["it"]="iniziafigura",
+ ["nl"]="startfiguur",
+ ["pe"]="شروع‌شکل",
+ ["ro"]="startfigura",
+ },
+ ["startframed"]={
+ ["en"]="startframed",
+ ["nl"]="startomlijnd",
+ },
+ ["startglobal"]={
+ ["cs"]="startglobalni",
+ ["de"]="startglobal",
+ ["en"]="startglobal",
+ ["fr"]="demarreglobal",
+ ["it"]="iniziaglobale",
+ ["nl"]="startglobaal",
+ ["pe"]="شروع‌سراسری",
+ ["ro"]="startglobal",
+ },
+ ["startline"]={
+ ["cs"]="startradek",
+ ["de"]="startzeile",
+ ["en"]="startline",
+ ["fr"]="demarreligne",
+ ["it"]="iniziariga",
+ ["nl"]="startregel",
+ ["pe"]="شروع‌خط",
+ ["ro"]="startlinie",
+ },
+ ["startlinecorrection"]={
+ ["cs"]="startkorekceradku",
+ ["de"]="startzeilenkorrektur",
+ ["en"]="startlinecorrection",
+ ["fr"]="demarrecorrectionligne",
+ ["it"]="iniziacorrezioneriga",
+ ["nl"]="startregelcorrectie",
+ ["pe"]="شروع‌تصحیح‌خط",
+ ["ro"]="startcorectielinie",
+ },
+ ["startlinenumbering"]={
+ ["cs"]="startcislovaniradku",
+ ["de"]="startzeilennumerierung",
+ ["en"]="startlinenumbering",
+ ["fr"]="demarrenumerotationligne",
+ ["it"]="inizianumerazionerighe",
+ ["nl"]="startregelnummeren",
+ ["pe"]="شروع‌شماره‌گذاری‌خط",
+ ["ro"]="startnumerotarelinii",
+ },
+ ["startlines"]={
+ ["cs"]="startradky",
+ ["de"]="startzeilen",
+ ["en"]="startlines",
+ ["fr"]="demarrelignes",
+ ["it"]="iniziarighe",
+ ["nl"]="startregels",
+ ["pe"]="شروع‌خطها",
+ ["ro"]="startlinii",
+ },
+ ["startlocal"]={
+ ["cs"]="startlokalni",
+ ["de"]="startlokal",
+ ["en"]="startlocal",
+ ["fr"]="demarrelocal",
+ ["it"]="inizialocale",
+ ["nl"]="startlokaal",
+ ["pe"]="شروع‌موضعی",
+ ["ro"]="startlocal",
+ },
+ ["startlocalfootnotes"]={
+ ["cs"]="startlokalnipoznamkypodcarou",
+ ["de"]="startlokalefussnoten",
+ ["en"]="startlocalfootnotes",
+ ["fr"]="demarrenotespdplocales",
+ ["it"]="inizianotepdplocali",
+ ["nl"]="startlokalevoetnoten",
+ ["pe"]="شروع‌پانوشتهای‌موضعی",
+ ["ro"]="startnotesubsollocale",
+ },
+ ["startmakeup"]={
+ ["cs"]="startuprava",
+ ["de"]="startumbruch",
+ ["en"]="startmakeup",
+ ["fr"]="demarremakeup",
+ ["it"]="iniziamakeup",
+ ["nl"]="startopmaak",
+ ["pe"]="شروع‌آرایش",
+ ["ro"]="startmakeup",
+ },
+ ["startmarginblock"]={
+ ["cs"]="startmarginalniblok",
+ ["de"]="startmarginalblock",
+ ["en"]="startmarginblock",
+ ["fr"]="demarreblocmarge",
+ ["it"]="iniziabloccomargine",
+ ["nl"]="startmargeblok",
+ ["pe"]="شروع‌بلوک‌حاشیه",
+ ["ro"]="startblocmarginal",
+ },
+ ["startmarginrule"]={
+ ["cs"]="startmarginalnilinka",
+ ["de"]="startmarginallinie",
+ ["en"]="startmarginrule",
+ ["fr"]="demarremargereglee",
+ ["it"]="inizialineamargine",
+ ["nl"]="startkantlijn",
+ ["pe"]="شروع‌خط‌حاشیه",
+ ["ro"]="startliniemargine",
+ },
+ ["startnarrower"]={
+ ["cs"]="startzuzeni",
+ ["de"]="startenger",
+ ["en"]="startnarrower",
+ ["fr"]="demarrecompoetroite",
+ ["it"]="iniziapiustretto",
+ ["nl"]="startsmaller",
+ ["pe"]="شروع‌باریکتر",
+ ["ro"]="startingust",
+ },
+ ["startopposite"]={
+ ["cs"]="startprotejsek",
+ ["de"]="startgegenueber",
+ ["en"]="startopposite",
+ ["fr"]="demarreopposition",
+ ["it"]="iniziaopposto",
+ ["nl"]="startnaast",
+ ["pe"]="شروع‌مخالف",
+ ["ro"]="startopozit",
+ },
+ ["startoverlay"]={
+ ["cs"]="startprekryv",
+ ["de"]="startoverlay",
+ ["en"]="startoverlay",
+ ["fr"]="demarrerevetement",
+ ["it"]="iniziasovrapposizione",
+ ["nl"]="startoverlay",
+ ["pe"]="شروع‌پوشش",
+ ["ro"]="startoverlay",
+ },
+ ["startoverzicht"]={
+ ["cs"]="startprehled",
+ ["de"]="startueberblick",
+ ["en"]="startoverview",
+ ["fr"]="demarrevuedensemble",
+ ["it"]="iniziaoverview",
+ ["nl"]="startoverzicht",
+ ["pe"]="شروع‌بازبینی",
+ ["ro"]="startoverview",
+ },
+ ["startpacked"]={
+ ["cs"]="startzhustene",
+ ["de"]="startkleinerdurchschuss",
+ ["en"]="startpacked",
+ ["fr"]="demarregroupe",
+ ["it"]="iniziaimpaccato",
+ ["nl"]="startopelkaar",
+ ["pe"]="شروع‌فشرده",
+ ["ro"]="startimpachetat",
+ },
+ ["startpositioning"]={
+ ["cs"]="startumistovani",
+ ["de"]="startpositionieren",
+ ["en"]="startpositioning",
+ ["fr"]="demarrepositionnement",
+ ["it"]="iniziaposizionamento",
+ ["nl"]="startpositioneren",
+ ["pe"]="شروع‌مکان‌گذاری",
+ ["ro"]="startpozitionare",
+ },
+ ["startproduct"]={
+ ["cs"]="startprodukt",
+ ["de"]="startprodukt",
+ ["en"]="startproduct",
+ ["fr"]="demarreproduit",
+ ["it"]="iniziaprodotto",
+ ["nl"]="startprodukt",
+ ["pe"]="شروع‌تولید",
+ ["ro"]="startprodus",
+ },
+ ["startprofile"]={
+ ["cs"]="startprofil",
+ ["de"]="startprofil",
+ ["en"]="startprofile",
+ ["fr"]="demarreprofil",
+ ["it"]="iniziaprofilo",
+ ["nl"]="startprofiel",
+ ["pe"]="شروع‌پروفایل",
+ ["ro"]="startprofil",
+ },
+ ["startproject"]={
+ ["cs"]="startprojekt",
+ ["de"]="startprojekt",
+ ["en"]="startproject",
+ ["fr"]="demarreprojet",
+ ["it"]="iniziaprogetto",
+ ["nl"]="startprojekt",
+ ["pe"]="شروع‌پروژه",
+ ["ro"]="startproiect",
+ },
+ ["startquotation"]={
+ ["cs"]="startcitace",
+ ["de"]="startzitat",
+ ["en"]="startquotation",
+ ["fr"]="demarrecitation",
+ ["it"]="iniziacitazione",
+ ["nl"]="startcitaat",
+ ["pe"]="شروع‌نقل‌قول",
+ ["ro"]="startcitat",
+ },
+ ["startraster"]={
+ ["cs"]="startrastr",
+ ["de"]="startraster",
+ ["en"]="startraster",
+ ["fr"]="demarreraster",
+ ["it"]="iniziaraster",
+ ["nl"]="startraster",
+ ["pe"]="startraster",
+ ["ro"]="startraster",
+ },
+ ["startsymbolset"]={
+ ["cs"]="startsadasymbolu",
+ ["de"]="startsymbolset",
+ ["en"]="startsymbolset",
+ ["fr"]="demarrejeusymboles",
+ ["it"]="iniziasetsimboli",
+ ["nl"]="startsymboolset",
+ ["pe"]="شروع‌مجموعه‌نماد",
+ ["ro"]="startsetsimboluri",
+ },
+ ["startsynchronization"]={
+ ["cs"]="startsynchronizace",
+ ["de"]="startsynchronisation",
+ ["en"]="startsynchronization",
+ ["fr"]="demarresynchronisation",
+ ["it"]="iniziasincronizzazione",
+ ["nl"]="startsynchronisatie",
+ ["pe"]="شروع‌تطابق",
+ ["ro"]="startsincronizare",
+ },
+ ["starttable"]={
+ ["cs"]="starttabulka",
+ ["de"]="starttabelle",
+ ["en"]="starttable",
+ ["fr"]="demarretableau",
+ ["it"]="iniziatabella",
+ ["nl"]="starttabel",
+ ["pe"]="شروع‌جدول",
+ ["ro"]="starttabel",
+ },
+ ["starttables"]={
+ ["cs"]="starttabulky",
+ ["de"]="starttabellen",
+ ["en"]="starttables",
+ ["fr"]="demarretableaux",
+ ["it"]="iniziatabelle",
+ ["nl"]="starttabellen",
+ ["pe"]="شروع‌جدولها",
+ ["ro"]="starttabele",
+ },
+ ["starttext"]={
+ ["cs"]="starttext",
+ ["de"]="starttext",
+ ["en"]="starttext",
+ ["fr"]="demarretexte",
+ ["it"]="iniziatesto",
+ ["nl"]="starttekst",
+ ["pe"]="شروع‌متن",
+ ["ro"]="starttext",
+ },
+ ["starttextbackground"]={
+ ["en"]="starttextbackground",
+ ["nl"]="starttekstachtergrond",
+ },
+ ["starttextrule"]={
+ ["cs"]="starttextovalinka",
+ ["de"]="starttextlinie",
+ ["en"]="starttextrule",
+ ["fr"]="demarreligneregleetexte",
+ ["it"]="inizialineatesto",
+ ["nl"]="starttekstlijn",
+ ["pe"]="شروع‌خط‌متن",
+ ["ro"]="startriglatext",
+ },
+ ["startunpacked"]={
+ ["cs"]="startnezhustene",
+ ["de"]="startgrosserdurchschuss",
+ ["en"]="startunpacked",
+ ["fr"]="demarredegroupe",
+ ["it"]="iniziaunpacked",
+ ["nl"]="startvanelkaar",
+ ["pe"]="شروع‌غیر‌فشرده",
+ ["ro"]="startneimpachetat",
+ },
+ ["startversion"]={
+ ["cs"]="startverze",
+ ["de"]="startversion",
+ ["en"]="startversion",
+ ["fr"]="demarreversion",
+ ["it"]="iniziaversione",
+ ["nl"]="startversie",
+ ["pe"]="شروع‌نسخه",
+ ["ro"]="startversiune",
+ },
+ ["stopalignment"]={
+ ["cs"]="stopzarovnavani",
+ ["de"]="stopausrichtung",
+ ["en"]="stopalignment",
+ ["fr"]="stoppealignement",
+ ["it"]="terminaallineamento",
+ ["nl"]="stopuitlijnen",
+ ["pe"]="پایان‌تنظیم",
+ ["ro"]="stopaliniere",
+ },
+ ["stopbackground"]={
+ ["cs"]="stoppozadi",
+ ["de"]="stophintergrund",
+ ["en"]="stopbackground",
+ ["fr"]="stoppearriereplan",
+ ["it"]="terminasfondo",
+ ["nl"]="stopachtergrond",
+ ["pe"]="پایان‌پس‌زمینه",
+ ["ro"]="stopfundal",
+ },
+ ["stopcoding"]={
+ ["cs"]="stopkodovani",
+ ["de"]="stopkodierung",
+ ["en"]="stopcoding",
+ ["fr"]="stoppecodage",
+ ["it"]="terminacodifica",
+ ["nl"]="stopcodering",
+ ["pe"]="پایان‌کد",
+ ["ro"]="stopcodificare",
+ },
+ ["stopcolor"]={
+ ["cs"]="stopbarva",
+ ["de"]="stopfarbe",
+ ["en"]="stopcolor",
+ ["fr"]="stoppecouleur",
+ ["it"]="terminacolore",
+ ["nl"]="stopkleur",
+ ["pe"]="پایان‌رنگ",
+ ["ro"]="stopculoare",
+ },
+ ["stopcolumnmakeup"]={
+ ["cs"]="stopcolumnmakeup",
+ ["de"]="stopcolumnmakeup",
+ ["en"]="stopcolumnmakeup",
+ ["fr"]="stopcolumnmakeup",
+ ["it"]="stopcolumnmakeup",
+ ["nl"]="stopkolomopmaak",
+ ["pe"]="پایان‌آرایش‌ستون",
+ ["ro"]="stopcolumnmakeup",
+ },
+ ["stopcolumns"]={
+ ["cs"]="stopsloupce",
+ ["de"]="stopspalten",
+ ["en"]="stopcolumns",
+ ["fr"]="stoppecolonnes",
+ ["it"]="terminacolonne",
+ ["nl"]="stopkolommen",
+ ["pe"]="پایان‌ستونها",
+ ["ro"]="stopcoloane",
+ },
+ ["stopcolumnset"]={
+ ["cs"]="stopcolumnset",
+ ["de"]="stopcolumnset",
+ ["en"]="stopcolumnset",
+ ["fr"]="stoppejeucolonne",
+ ["it"]="terminagruppocolonne",
+ ["nl"]="stopkolomgroep",
+ ["pe"]="پایان‌مجموعه‌ستون",
+ ["ro"]="stopcolumnset",
+ },
+ ["stopcombination"]={
+ ["cs"]="stopspojeni",
+ ["de"]="stopkombination",
+ ["en"]="stopcombination",
+ ["fr"]="stoppecombinaison",
+ ["it"]="terminacombinazione",
+ ["nl"]="stopcombinatie",
+ ["pe"]="پایان‌ترکیب",
+ ["ro"]="stopcombinare",
+ },
+ ["stopcomponent"]={
+ ["cs"]="stopkomponenta",
+ ["de"]="stopkomponente",
+ ["en"]="stopcomponent",
+ ["fr"]="stoppecomposant",
+ ["it"]="terminacomponente",
+ ["nl"]="stoponderdeel",
+ ["pe"]="پایان‌مولفه",
+ ["ro"]="stopcomponenta",
+ },
+ ["stopdocument"]={
+ ["cs"]="stopdokument",
+ ["de"]="stopdokument",
+ ["en"]="stopdocument",
+ ["fr"]="stoppedocument",
+ ["it"]="terminadocumento",
+ ["nl"]="stopdocument",
+ ["pe"]="پایان‌نوشتار",
+ ["ro"]="stopdocument",
+ },
+ ["stopenvironment"]={
+ ["cs"]="stopprostredi",
+ ["de"]="stopumgebung",
+ ["en"]="stopenvironment",
+ ["fr"]="stoppeenvironement",
+ ["it"]="terminaambiente",
+ ["nl"]="stopomgeving",
+ ["pe"]="پایان‌محیط",
+ ["ro"]="stopmediu",
+ },
+ ["stopframed"]={
+ ["en"]="stopframed",
+ ["nl"]="stopomlijnd",
+ },
+ ["stopglobal"]={
+ ["cs"]="stopglobalni",
+ ["de"]="stopglobal",
+ ["en"]="stopglobal",
+ ["fr"]="stoppeglobal",
+ ["it"]="terminaglobale",
+ ["nl"]="stopglobaal",
+ ["pe"]="پایان‌سراسری",
+ ["ro"]="stopblobal",
+ },
+ ["stopline"]={
+ ["cs"]="stopradek",
+ ["de"]="stopzeile",
+ ["en"]="stopline",
+ ["fr"]="stoppeligne",
+ ["it"]="terminariga",
+ ["nl"]="stopregel",
+ ["pe"]="پایان‌خط",
+ ["ro"]="stoplinie",
+ },
+ ["stoplinecorrection"]={
+ ["cs"]="stopkorekceradku",
+ ["de"]="stopzeilenkorrektur",
+ ["en"]="stoplinecorrection",
+ ["fr"]="stoppecorrectionligne",
+ ["it"]="terminacorrezioneriga",
+ ["nl"]="stopregelcorrectie",
+ ["pe"]="پایان‌تصحیح‌خط",
+ ["ro"]="stopcorectielinie",
+ },
+ ["stoplinenumbering"]={
+ ["cs"]="stopcislovaniradku",
+ ["de"]="stopzeilennumerierung",
+ ["en"]="stoplinenumbering",
+ ["fr"]="stoppenumerotationligne",
+ ["it"]="terminanumerazionerighe",
+ ["nl"]="stopregelnummeren",
+ ["pe"]="پایان‌شماره‌گذاری‌خط",
+ ["ro"]="stopnumerotarelinii",
+ },
+ ["stoplines"]={
+ ["cs"]="stopradky",
+ ["de"]="stopzeilen",
+ ["en"]="stoplines",
+ ["fr"]="stoppelignes",
+ ["it"]="terminarighe",
+ ["nl"]="stopregels",
+ ["pe"]="پایان‌خطها",
+ ["ro"]="stoplinii",
+ },
+ ["stoplocal"]={
+ ["cs"]="stoplokalni",
+ ["de"]="stoplokal",
+ ["en"]="stoplocal",
+ ["fr"]="stoppelocal",
+ ["it"]="terminalocale",
+ ["nl"]="stoplokaal",
+ ["pe"]="پایان‌موضعی",
+ ["ro"]="stoplocal",
+ },
+ ["stoplocalfootnotes"]={
+ ["cs"]="stoplokalnipoznamkypodcarou",
+ ["de"]="stoplokalefussnoten",
+ ["en"]="stoplocalfootnotes",
+ ["fr"]="stoppenotespdplocales",
+ ["it"]="terminanotepdplocali",
+ ["nl"]="stoplokalevoetnoten",
+ ["pe"]="پایان‌پانوشتهای‌موضعی",
+ ["ro"]="stopnotesubsollocale",
+ },
+ ["stopmakeup"]={
+ ["cs"]="stopuprava",
+ ["de"]="stopumbruch",
+ ["en"]="stopmakeup",
+ ["fr"]="stoppemakeup",
+ ["it"]="terminamakeup",
+ ["nl"]="stopopmaak",
+ ["pe"]="پایان‌آرایش",
+ ["ro"]="stopmakeup",
+ },
+ ["stopmarginblock"]={
+ ["cs"]="stopmarginalniblok",
+ ["de"]="stopmarginalblock",
+ ["en"]="stopmarginblock",
+ ["fr"]="stoppeblocmarge",
+ ["it"]="terminabloccomargine",
+ ["nl"]="stopmargeblok",
+ ["pe"]="پایان‌بلوک‌حاشیه",
+ ["ro"]="stopblocmarginal",
+ },
+ ["stopmarginrule"]={
+ ["cs"]="stopmarginalnilinka",
+ ["de"]="stopmarginallinie",
+ ["en"]="stopmarginrule",
+ ["fr"]="stoppemargereglee",
+ ["it"]="terminalineamargine",
+ ["nl"]="stopkantlijn",
+ ["pe"]="پایان‌خط‌حاشیه",
+ ["ro"]="stopliniemargine",
+ },
+ ["stopnarrower"]={
+ ["cs"]="stopzuzeni",
+ ["de"]="stopenger",
+ ["en"]="stopnarrower",
+ ["fr"]="stopcompoetroite",
+ ["it"]="terminapiustretto",
+ ["nl"]="stopsmaller",
+ ["pe"]="پایان‌نازکتر",
+ ["ro"]="stopingust",
+ },
+ ["stopopposite"]={
+ ["cs"]="stopprotejsek",
+ ["de"]="stopgegenueber",
+ ["en"]="stopopposite",
+ ["fr"]="stoppeopposition",
+ ["it"]="terminaopposto",
+ ["nl"]="stopnaast",
+ ["pe"]="پایان‌مخالف",
+ ["ro"]="stopopozit",
+ },
+ ["stopoverlay"]={
+ ["cs"]="stopprekryv",
+ ["de"]="stopoverlay",
+ ["en"]="stopoverlay",
+ ["fr"]="stopperevetement",
+ ["it"]="terminasovrapposizione",
+ ["nl"]="stopoverlay",
+ ["pe"]="پایان‌پوشش",
+ ["ro"]="stopoverlay",
+ },
+ ["stopoverzicht"]={
+ ["cs"]="stopprehled",
+ ["de"]="stopueberblick",
+ ["en"]="stopoverview",
+ ["fr"]="stoppevuedensemble",
+ ["it"]="terminaoverview",
+ ["nl"]="stopoverzicht",
+ ["pe"]="پایان‌بازبینی",
+ ["ro"]="stopoverview",
+ },
+ ["stoppacked"]={
+ ["cs"]="stopzhustene",
+ ["de"]="stopkleinerdurchschuss",
+ ["en"]="stoppacked",
+ ["fr"]="stoppegroupe",
+ ["it"]="terminaimpaccato",
+ ["nl"]="stopopelkaar",
+ ["pe"]="پایان‌فشرده",
+ ["ro"]="stopimpachetat",
+ },
+ ["stoppositioning"]={
+ ["cs"]="stopumistovani",
+ ["de"]="stoppositionieren",
+ ["en"]="stoppositioning",
+ ["fr"]="stoppepositionnement",
+ ["it"]="terminaposizionamento",
+ ["nl"]="stoppositioneren",
+ ["pe"]="پایان‌مکان‌گذاری",
+ ["ro"]="stoppozitionare",
+ },
+ ["stopproduct"]={
+ ["cs"]="stopprodukt",
+ ["de"]="stopprodukt",
+ ["en"]="stopproduct",
+ ["fr"]="stoppeproduit",
+ ["it"]="terminaprodotto",
+ ["nl"]="stopprodukt",
+ ["pe"]="پایان‌تولید",
+ ["ro"]="stopprodus",
+ },
+ ["stopprofile"]={
+ ["cs"]="stopprofil",
+ ["de"]="stopprofil",
+ ["en"]="stopprofile",
+ ["fr"]="stoppeprofil",
+ ["it"]="terminaprofili",
+ ["nl"]="stopprofiel",
+ ["pe"]="پایان‌پروفایل",
+ ["ro"]="stopprofil",
+ },
+ ["stopproject"]={
+ ["cs"]="stopprojekt",
+ ["de"]="stopprojekt",
+ ["en"]="stopproject",
+ ["fr"]="stoppeprojet",
+ ["it"]="terminaprogetto",
+ ["nl"]="stopprojekt",
+ ["pe"]="پایان‌پروژه",
+ ["ro"]="stopproiect",
+ },
+ ["stopquotation"]={
+ ["cs"]="stopcitace",
+ ["de"]="stopzitat",
+ ["en"]="stopquotation",
+ ["fr"]="stoppecitation",
+ ["it"]="terminacitazione",
+ ["nl"]="stopcitaat",
+ ["pe"]="پایان‌نقل‌قول",
+ ["ro"]="stopcitat",
+ },
+ ["stopraster"]={
+ ["cs"]="stoprastr",
+ ["de"]="stopraster",
+ ["en"]="stopraster",
+ ["fr"]="stopperaster",
+ ["it"]="terminaraster",
+ ["nl"]="stopraster",
+ ["pe"]="stopraster",
+ ["ro"]="stopraster",
+ },
+ ["stopsynchronization"]={
+ ["cs"]="stopsynchronizace",
+ ["de"]="stopsynchronisation",
+ ["en"]="stopsynchronization",
+ ["fr"]="stoppesynchronisation",
+ ["it"]="terminasincronizzazione",
+ ["nl"]="stopsynchronisatie",
+ ["pe"]="پایان‌تطابق",
+ ["ro"]="stopsincronizare",
+ },
+ ["stoptable"]={
+ ["cs"]="stoptabulka",
+ ["de"]="stoptabelle",
+ ["en"]="stoptable",
+ ["fr"]="stoppetableau",
+ ["it"]="terminatabella",
+ ["nl"]="stoptabel",
+ ["pe"]="پایان‌جدول",
+ ["ro"]="stoptabel",
+ },
+ ["stoptables"]={
+ ["cs"]="stoptabulky",
+ ["de"]="stoptabellen",
+ ["en"]="stoptables",
+ ["fr"]="stoppetableaux",
+ ["it"]="terminatabelle",
+ ["nl"]="stoptabellen",
+ ["pe"]="پایان‌جدولها",
+ ["ro"]="stoptabele",
+ },
+ ["stoptext"]={
+ ["cs"]="stoptext",
+ ["de"]="stoptext",
+ ["en"]="stoptext",
+ ["fr"]="stoppetexte",
+ ["it"]="terminatesto",
+ ["nl"]="stoptekst",
+ ["pe"]="پایان‌متن",
+ ["ro"]="stoptext",
+ },
+ ["stoptextbackground"]={
+ ["en"]="stoptextbackground",
+ ["nl"]="stoptekstachtergrond",
+ },
+ ["stoptextrule"]={
+ ["cs"]="stoptextovalinka",
+ ["de"]="stoptextlinie",
+ ["en"]="stoptextrule",
+ ["fr"]="stoppeligneregleetexte",
+ ["it"]="terminalineatesto",
+ ["nl"]="stoptekstlijn",
+ ["pe"]="پایان‌خط‌متن",
+ ["ro"]="stopriglatext",
+ },
+ ["stopunpacked"]={
+ ["cs"]="stopnezhustene",
+ ["de"]="stopgrosserdurchschuss",
+ ["en"]="stopunpacked",
+ ["fr"]="stoppedegroupe",
+ ["it"]="terminaunpacked",
+ ["nl"]="stopvanelkaar",
+ ["pe"]="پایان‌غیرفشرده",
+ ["ro"]="stopneimpachetat",
+ },
+ ["stopversion"]={
+ ["cs"]="stopverze",
+ ["de"]="stopversion",
+ ["en"]="stopversion",
+ ["fr"]="stoppeversion",
+ ["it"]="terminaversioni",
+ ["nl"]="stopversie",
+ ["pe"]="پایان‌نسخه",
+ ["ro"]="stopversiune",
+ },
+ ["stretched"]={
+ ["cs"]="roztazene",
+ ["de"]="gestreckt",
+ ["en"]="stretched",
+ ["fr"]="etire",
+ ["it"]="stirato",
+ ["nl"]="uitgerekt",
+ ["pe"]="کشیده",
+ ["ro"]="intins",
+ },
+ ["subformulanumber"]={
+ ["cs"]="cislopodrovnice",
+ ["de"]="unterformelnummer",
+ ["en"]="subformulanumber",
+ ["fr"]="numerosousformule",
+ ["it"]="numerosottoformula",
+ ["nl"]="subformulenummer",
+ ["pe"]="شماره‌زیرفرمول",
+ ["ro"]="numarsubformula",
+ },
+ ["subpagenumber"]={
+ ["cs"]="subpagenumber",
+ ["de"]="subpagenumber",
+ ["en"]="subpagenumber",
+ ["fr"]="sousnumeropage",
+ ["it"]="subpagenumber",
+ ["nl"]="subpaginanummer",
+ ["pe"]="شماره‌زیرصفحه",
+ ["ro"]="subpagenumber",
+ },
+ ["switchtobodyfont"]={
+ ["cs"]="prepninazakladnifont",
+ ["de"]="wechselezumfliesstext",
+ ["en"]="switchtobodyfont",
+ ["fr"]="changepolicecorps",
+ ["it"]="cambiaafontdeltesto",
+ ["nl"]="switchnaarkorps",
+ ["pe"]="تغییربه‌قلم‌بدنه",
+ ["ro"]="trecilafonttext",
+ },
+ ["switchtorawfont"]={
+ ["cs"]="switchtorawfont",
+ ["de"]="switchtorawfont",
+ ["en"]="switchtorawfont",
+ ["fr"]="changepolicebrute",
+ ["it"]="passaafontgrezzo",
+ ["nl"]="switchtorawfont",
+ ["pe"]="تغییربه‌قلم‌خام",
+ ["ro"]="trecilafontraw",
+ },
+ ["sym"]={
+ ["cs"]="sym",
+ ["de"]="sym",
+ ["en"]="sym",
+ ["fr"]="sym",
+ ["it"]="sim",
+ ["nl"]="sym",
+ ["pe"]="نم",
+ ["ro"]="sim",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["symoffset"]={
+ ["en"]="symoffset",
+ ["nl"]="symoffset",
+ },
+ ["synchronizationbar"]={
+ ["cs"]="synchronizacnilista",
+ ["de"]="synchronisationsbalken",
+ ["en"]="synchronizationbar",
+ ["fr"]="barresynchronisation",
+ ["it"]="barrasincronizzazione",
+ ["nl"]="synchronisatiebalk",
+ ["pe"]="میله‌تطابق",
+ ["ro"]="barasincronizare",
+ },
+ ["synchronize"]={
+ ["cs"]="synchronizovat",
+ ["de"]="synchronisieren",
+ ["en"]="synchronize",
+ ["fr"]="synchronise",
+ ["it"]="sincronizza",
+ ["nl"]="synchroniseer",
+ ["pe"]="تطابق",
+ ["ro"]="sincronizeaza",
+ },
+ ["tab"]={
+ ["cs"]="tab",
+ ["de"]="tab",
+ ["en"]="tab",
+ ["fr"]="tab",
+ ["it"]="tab",
+ ["nl"]="tab",
+ ["pe"]="تب",
+ ["ro"]="tab",
+ },
+ ["testcolumn"]={
+ ["cs"]="testcolumn",
+ ["de"]="testcolumn",
+ ["en"]="testcolumn",
+ ["fr"]="testcolumn",
+ ["it"]="testcolumn",
+ ["nl"]="testkolom",
+ ["pe"]="ستون‌امتحان",
+ ["ro"]="testcolumn",
+ },
+ ["testpage"]={
+ ["cs"]="testpage",
+ ["de"]="testpage",
+ ["en"]="testpage",
+ ["fr"]="testpage",
+ ["it"]="testpage",
+ ["nl"]="testpagina",
+ ["pe"]="صفحه‌تست",
+ ["ro"]="testpage",
+ },
+ ["tex"]={
+ ["cs"]="tex",
+ ["de"]="tex",
+ ["en"]="tex",
+ ["fr"]="tex",
+ ["it"]="tex",
+ ["nl"]="tex",
+ ["pe"]="تک",
+ ["ro"]="tex",
+ },
+ ["textheight"]={
+ ["cs"]="vyskatextu",
+ ["de"]="texthoehe",
+ ["en"]="textheight",
+ ["fr"]="hauteurtexte",
+ ["it"]="altezzatesto",
+ ["nl"]="teksthoogte",
+ ["pe"]="ارتفاع‌متن",
+ ["ro"]="inaltimetext",
+ },
+ ["textreference"]={
+ ["cs"]="odkaznatext",
+ ["de"]="textreferenz",
+ ["en"]="textreference",
+ ["fr"]="referencetexte",
+ ["it"]="riferimentotesto",
+ ["nl"]="tekstreferentie",
+ ["pe"]="مرجع‌متن",
+ ["ro"]="referintatext",
+ },
+ ["textrule"]={
+ ["cs"]="textovalinka",
+ ["de"]="textlinie",
+ ["en"]="textrule",
+ ["fr"]="ligneregleetexte",
+ ["it"]="lineatesto",
+ ["nl"]="tekstlijn",
+ ["pe"]="خط‌متن",
+ ["ro"]="riglatext",
+ },
+ ["textvariable"]={
+ ["cs"]="textvariable",
+ ["de"]="textvariable",
+ ["en"]="textvariable",
+ ["fr"]="variabletexte",
+ ["it"]="variabiletesto",
+ ["nl"]="tekstvariabele",
+ ["pe"]="متغیر متن",
+ ["ro"]="variabilatext",
+ },
+ ["textwidth"]={
+ ["cs"]="sirkatextu",
+ ["de"]="textbreite",
+ ["en"]="textwidth",
+ ["fr"]="largeurtexte",
+ ["it"]="ampiezzatesto",
+ ["nl"]="tekstbreedte",
+ ["pe"]="عرض‌متن",
+ ["ro"]="latimetext",
+ },
+ ["thinrule"]={
+ ["cs"]="tenkalinka",
+ ["de"]="duennelinie",
+ ["en"]="thinrule",
+ ["fr"]="traitfin",
+ ["it"]="lineasottile",
+ ["nl"]="dunnelijn",
+ ["pe"]="خط‌نازک",
+ ["ro"]="liniesubtire",
+ },
+ ["thinrules"]={
+ ["cs"]="tenkelinky",
+ ["de"]="duennerumriss",
+ ["en"]="thinrules",
+ ["fr"]="traitsfins",
+ ["it"]="lineesottili",
+ ["nl"]="dunnelijnen",
+ ["pe"]="خطهای‌نازک",
+ ["ro"]="liniisubtiri",
+ },
+ ["tooltip"]={
+ ["cs"]="bublinkovanapoveda",
+ ["de"]="tooltip",
+ ["en"]="tooltip",
+ ["fr"]="suggestion",
+ ["it"]="tooltip",
+ ["nl"]="suggestie",
+ ["pe"]="tooltip",
+ ["ro"]="tooltip",
+ },
+ ["topdistance"]={
+ ["cs"]="vzdalenosthorejsku",
+ ["de"]="abstandoben",
+ ["en"]="topdistance",
+ ["fr"]="distancesup",
+ ["it"]="distanzacima",
+ ["nl"]="bovenafstand",
+ ["pe"]="فاصله‌بالا",
+ ["ro"]="distantasus",
+ },
+ ["topheight"]={
+ ["cs"]="vyskahorejsku",
+ ["de"]="hoeheoben",
+ ["en"]="topheight",
+ ["fr"]="hauteursup",
+ ["it"]="altezzacima",
+ ["nl"]="bovenhoogte",
+ ["pe"]="ارتفاع‌بالا",
+ ["ro"]="inaltimesus",
+ },
+ ["topspace"]={
+ ["cs"]="odsazenishora",
+ ["de"]="kopfweite",
+ ["en"]="topspace",
+ ["fr"]="espacesup",
+ ["it"]="spaziocima",
+ ["nl"]="kopwit",
+ ["pe"]="فضای‌بالا",
+ ["ro"]="spatiusus",
+ },
+ ["totalnumberofpages"]={
+ ["cs"]="celkovypocetstran",
+ ["de"]="gesamtseitenanzahl",
+ ["en"]="totalnumberofpages",
+ ["fr"]="nombretotaldepages",
+ ["it"]="numerototaledipagine",
+ ["nl"]="totaalaantalpaginas",
+ ["pe"]="شماره‌کل‌صفحه‌ها",
+ ["ro"]="numartotalpagini",
+ },
+ ["translate"]={
+ ["cs"]="prelozit",
+ ["de"]="uebersetzten",
+ ["en"]="translate",
+ ["fr"]="traduire",
+ ["it"]="traduci",
+ ["nl"]="vertaal",
+ ["pe"]="ترجمه",
+ ["ro"]="traduce",
+ },
+ ["txt"]={
+ ["cs"]="txt",
+ ["de"]="txt",
+ ["en"]="txt",
+ ["fr"]="txt",
+ ["it"]="txt",
+ ["nl"]="txt",
+ ["pe"]="txt",
+ ["ro"]="txt",
+ },
+ ["typ"]={
+ ["cs"]="pis",
+ ["de"]="tip",
+ ["en"]="typ",
+ ["fr"]="typ",
+ ["it"]="typ",
+ ["nl"]="typ",
+ ["pe"]="typ",
+ ["ro"]="typ",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="tippen",
+ ["en"]="type",
+ ["fr"]="dactylographier",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["typebuffer"]={
+ ["cs"]="typebuffer",
+ ["de"]="tippepuffer",
+ ["en"]="typebuffer",
+ ["fr"]="tapebuffer",
+ ["it"]="typebuffer",
+ ["nl"]="typebuffer",
+ ["pe"]="تایپ‌بافر",
+ ["ro"]="scriebuffer",
+ },
+ ["typefile"]={
+ ["cs"]="opissoubor",
+ ["de"]="tippedatei",
+ ["en"]="typefile",
+ ["fr"]="fichierdactylo",
+ ["it"]="typefile",
+ ["nl"]="typefile",
+ ["pe"]="تایپ‌پرونده",
+ ["ro"]="typefile",
+ },
+ ["unitmeaning"]={
+ ["cs"]="vyznam",
+ ["de"]="bedeutung",
+ ["en"]="unitmeaning",
+ ["fr"]="sensunite",
+ ["it"]="nomeunita",
+ ["nl"]="betekenis",
+ ["pe"]="معنی‌واحد",
+ ["ro"]="numeunitate",
+ },
+ ["unknown"]={
+ ["cs"]="neznamo",
+ ["de"]="unbekant",
+ ["en"]="unknown",
+ ["fr"]="inconnu",
+ ["it"]="ignoto",
+ ["nl"]="onbekend",
+ ["pe"]="ناشناس",
+ ["ro"]="necunoscut",
+ },
+ ["useJSscripts"]={
+ ["cs"]="uzijJSscripts",
+ ["de"]="verwendeJSscript",
+ ["en"]="useJSscripts",
+ ["fr"]="utiliseJSscripts",
+ ["it"]="usaJSscripts",
+ ["nl"]="gebruikJSscripts",
+ ["pe"]="useJSscripts",
+ ["ro"]="folosestescriptJS",
+ },
+ ["useURL"]={
+ ["cs"]="uzijURL",
+ ["de"]="verwendeURL",
+ ["en"]="useURL",
+ ["fr"]="utiliseURL",
+ ["it"]="usaURL",
+ ["nl"]="gebruikURL",
+ ["pe"]="useURL",
+ ["ro"]="folosesteURL",
+ },
+ ["useXMLfilter"]={
+ ["cs"]="useXMLfilter",
+ ["de"]="useXMLfilter",
+ ["en"]="useXMLfilter",
+ ["fr"]="useXMLfilter",
+ ["it"]="useXMLfilter",
+ ["nl"]="gebruikXMLfilter",
+ ["pe"]="useXMLfilter",
+ ["ro"]="useXMLfilter",
+ },
+ ["useblocks"]={
+ ["cs"]="uzijbloky",
+ ["de"]="verwendebloecke",
+ ["en"]="useblocks",
+ ["fr"]="utiliseblocs",
+ ["it"]="usablocco",
+ ["nl"]="gebruikblokken",
+ ["pe"]="استفاده‌بلوکها",
+ ["ro"]="folosestebloc",
+ },
+ ["usecommands"]={
+ ["cs"]="uzijprikazy",
+ ["de"]="verwendebefehl",
+ ["en"]="usecommands",
+ ["fr"]="utilisecommandes",
+ ["it"]="usacomandi",
+ ["nl"]="gebruikcommandos",
+ ["pe"]="استفاده‌فرمانها",
+ ["ro"]="folosestecomenzi",
+ },
+ ["useencoding"]={
+ ["cs"]="uzijkodovani",
+ ["de"]="benutzekodierung",
+ ["en"]="useencoding",
+ ["fr"]="utiliseencodage",
+ ["it"]="usacodifica",
+ ["nl"]="usecodering",
+ ["pe"]="استفاده‌رمزینه",
+ ["ro"]="folosestecodificarea",
+ },
+ ["useexternaldocument"]={
+ ["cs"]="uzijexternidokument",
+ ["de"]="verwendeexteresdokument",
+ ["en"]="useexternaldocument",
+ ["fr"]="utilisedocumentexterne",
+ ["it"]="usadocumentoesterno",
+ ["nl"]="gebruikexterndocument",
+ ["pe"]="استفاده‌نوشتارخارجی",
+ ["ro"]="folosestedocumentextern",
+ },
+ ["useexternalfigure"]={
+ ["cs"]="uzijexterniobraz",
+ ["de"]="verwendeexterneabbildung",
+ ["en"]="useexternalfigure",
+ ["fr"]="utilisefigureexterne",
+ ["it"]="usafiguraesterna",
+ ["nl"]="gebruikexternfiguur",
+ ["pe"]="استفاده‌شکل‌خارجی",
+ ["ro"]="folosestefiguraexterna",
+ },
+ ["useexternalfile"]={
+ ["cs"]="uzijexternisoubor",
+ ["de"]="verwendeexternedatei",
+ ["en"]="useexternalfile",
+ ["fr"]="utilisefichierexterne",
+ ["it"]="usafileesterno",
+ ["nl"]="gebruikexternefile",
+ ["pe"]="استفاده‌پرونده‌خارجی",
+ ["ro"]="folosestefisierextern",
+ },
+ ["useexternalfiles"]={
+ ["cs"]="uzijexternisoubory",
+ ["de"]="verwendeexternedateien",
+ ["en"]="useexternalfiles",
+ ["fr"]="utilisefichiersexternes",
+ ["it"]="usafileesterni",
+ ["nl"]="gebruikexternefiles",
+ ["pe"]="استفاده‌پرونده‌های‌خارجی",
+ ["ro"]="folosestefisiereexterne",
+ },
+ ["useexternalsoundtrack"]={
+ ["cs"]="uzijexternizvuk",
+ ["de"]="verwendeexternestonstueck",
+ ["en"]="useexternalsoundtrack",
+ ["fr"]="utilisepsiteaudioexterne",
+ ["it"]="usacolonnasonoraesterna",
+ ["nl"]="gebruikexterngeluidsfragment",
+ ["pe"]="استفاده‌قطعه‌موزیک‌خارجی",
+ ["ro"]="folosestemuzicaexterna",
+ },
+ ["usemodule"]={
+ ["cs"]="uzijmodul",
+ ["de"]="verwendemodul",
+ ["en"]="usemodule",
+ ["fr"]="utilisemodule",
+ ["it"]="usamodulo",
+ ["nl"]="gebruikmodule",
+ ["pe"]="استفاده‌مدول",
+ ["ro"]="folosestemodul",
+ },
+ ["usemodules"]={
+ ["cs"]="uzijmoduly",
+ ["de"]="verwendemodule",
+ ["en"]="usemodules",
+ ["fr"]="utilisemodules",
+ ["it"]="usamoduli",
+ ["nl"]="gebruikmodules",
+ ["pe"]="استفاده‌مدولها",
+ ["ro"]="folosestemodule",
+ },
+ ["usepath"]={
+ ["cs"]="uzijadresar",
+ ["de"]="benutzeverzeichnis",
+ ["en"]="usedirectory",
+ ["fr"]="utilisechemin",
+ ["it"]="usacartella",
+ ["nl"]="gebruikgebied",
+ ["pe"]="استفاده‌مسیر",
+ ["ro"]="folosestedirector",
+ },
+ ["usereferences"]={
+ ["cs"]="uzijodkazy",
+ ["de"]="verwendereferenzen",
+ ["en"]="usereferences",
+ ["fr"]="utilisereferences",
+ ["it"]="usariferimenti",
+ ["nl"]="gebruikreferenties",
+ ["pe"]="استفاده‌مرجعها",
+ ["ro"]="folosestereferinte",
+ },
+ ["usespecials"]={
+ ["cs"]="uzijspeciality",
+ ["de"]="benutzespezielles",
+ ["en"]="usespecials",
+ ["fr"]="utilisespecialites",
+ ["it"]="usaspecialita",
+ ["nl"]="gebruikspecials",
+ ["pe"]="استفاده‌ویژگیها",
+ ["ro"]="folosestespeciale",
+ },
+ ["usesymbols"]={
+ ["cs"]="uzijsymbol",
+ ["de"]="verwendesymbole",
+ ["en"]="usesymbols",
+ ["fr"]="utilisesymboles",
+ ["it"]="usasimboli",
+ ["nl"]="gebruiksymbolen",
+ ["pe"]="استفاده‌نمادها",
+ ["ro"]="folosestesimboluri",
+ },
+ ["usetypescript"]={
+ ["cs"]="usetypescript",
+ ["de"]="usetypescript",
+ ["en"]="usetypescript",
+ ["fr"]="usetypescript",
+ ["it"]="usetypescript",
+ ["nl"]="gebruiktypescript",
+ ["pe"]="استفاده‌دستخط‌تایپ",
+ ["ro"]="usetypescript",
+ },
+ ["usetypescriptfile"]={
+ ["cs"]="usetypescriptfile",
+ ["de"]="usetypescriptfile",
+ ["en"]="usetypescriptfile",
+ ["it"]="usetypescriptfile",
+ ["nl"]="gebruiktypescriptfile",
+ ["pe"]="استفاده‌پرونده‌دستخط‌تایپ",
+ ["ro"]="usetypescriptfile",
+ },
+ ["useurl"]={
+ ["cs"]="uzijurl",
+ ["de"]="verwendeurl",
+ ["en"]="useurl",
+ ["fr"]="utiliseurl",
+ ["it"]="usaurl",
+ ["nl"]="gebruikurl",
+ ["pe"]="useurl",
+ ["ro"]="folosesteurl",
+ },
+ ["version"]={
+ ["cs"]="verze",
+ ["de"]="version",
+ ["en"]="version",
+ ["fr"]="version",
+ ["it"]="versione",
+ ["nl"]="versie",
+ ["pe"]="نسخه",
+ ["ro"]="versiune",
+ },
+ ["vl"]={
+ ["cs"]="vl",
+ ["de"]="vl",
+ ["en"]="vl",
+ ["fr"]="vl",
+ ["it"]="vl",
+ ["nl"]="vl",
+ ["pe"]="خ‌ع",
+ ["ro"]="vl",
+ },
+ ["weekday"]={
+ ["cs"]="vsedniden",
+ ["de"]="wochentag",
+ ["en"]="weekday",
+ ["fr"]="joursemaine",
+ ["it"]="giornosettimana",
+ ["nl"]="weekdag",
+ ["pe"]="روزهفته",
+ ["ro"]="zidinsaptamana",
+ },
+ ["whitespace"]={
+ ["cs"]="bilemisto",
+ ["de"]="zwischenraum",
+ ["en"]="whitespace",
+ ["fr"]="espaceblanc",
+ ["it"]="spaziobianco",
+ ["nl"]="witruimte",
+ ["pe"]="فضای‌سفید",
+ ["ro"]="spatiualb",
+ },
+ ["wordright"]={
+ ["cs"]="slovovpravo",
+ ["de"]="wortrechts",
+ ["en"]="wordright",
+ ["fr"]="motdroit",
+ ["it"]="paroladestra",
+ ["nl"]="woordrechts",
+ ["pe"]="کلمه‌راست",
+ ["ro"]="cuvantdreapta",
+ },
+ ["writebetweenlist"]={
+ ["cs"]="zapismeziseznam",
+ ["de"]="schreibezwischenliste",
+ ["en"]="writebetweenlist",
+ ["fr"]="ecritentreliste",
+ ["it"]="scrividentroelenco",
+ ["nl"]="schrijftussenlijst",
+ ["pe"]="بنویس‌بین‌لیست",
+ ["ro"]="scrieintreliste",
+ },
+ ["writetolist"]={
+ ["cs"]="zapisdoseznamu",
+ ["de"]="schreibezurliste",
+ ["en"]="writetolist",
+ ["fr"]="ecritdansliste",
+ ["it"]="scriviinelenco",
+ ["nl"]="schrijfnaarlijst",
+ ["pe"]="بنویس‌در‌لیست",
+ ["ro"]="scrieinlista",
+ },
+ ["writetoreferencelist"]={
+ ["cs"]="zapisdoseznamuodkazu",
+ ["de"]="schreibezurreferenzliste",
+ ["en"]="writetoreferencelist",
+ ["fr"]="ecritdanslistereference",
+ ["it"]="scriviinlistariferimenti",
+ ["nl"]="schrijfnaarreferentielijst",
+ ["pe"]="بنویس‌درلیست‌مرجع",
+ ["ro"]="scrieinlistareferinte",
+ },
+ ["writetoregister"]={
+ ["cs"]="zapisdorejstriku",
+ ["de"]="schreibezumregister",
+ ["en"]="writetoregister",
+ ["fr"]="ecritregistre",
+ ["it"]="scriviinregistro",
+ ["nl"]="schrijfnaarregister",
+ ["pe"]="بنویس‌درثبت",
+ ["ro"]="scrieinregistru",
+ },
+ },
+ ["constants"]={
+ ["fractions"]={
+ ["en"]="fractions",
+ ["nl"]="breuken",
+ },
+ ["action"]={
+ ["cs"]="akce",
+ ["de"]="aktion",
+ ["en"]="action",
+ ["fr"]="action",
+ ["it"]="azione",
+ ["nl"]="actie",
+ ["pe"]="کنش",
+ ["ro"]="actiune",
+ },
+ ["address"]={
+ ["cs"]="adresa",
+ ["de"]="adresse",
+ ["en"]="address",
+ ["fr"]="adresse",
+ ["it"]="indirizzo",
+ ["nl"]="adres",
+ ["pe"]="نشانی",
+ ["ro"]="adresa",
+ },
+ ["after"]={
+ ["cs"]="po",
+ ["de"]="nach",
+ ["en"]="after",
+ ["fr"]="apres",
+ ["it"]="dopo",
+ ["nl"]="na",
+ ["pe"]="بعداز",
+ ["ro"]="dupa",
+ },
+ ["afterhead"]={
+ ["cs"]="pohlavicce",
+ ["de"]="nachkopf",
+ ["en"]="afterhead",
+ ["fr"]="aprestete",
+ ["it"]="dopotesta",
+ ["nl"]="kopna",
+ ["pe"]="بعدازسر",
+ ["ro"]="dupatitlu",
+ },
+ ["afterkey"]={
+ ["cs"]="klavesapo",
+ ["de"]="nachtaste",
+ ["en"]="afterkey",
+ ["fr"]="aprescle",
+ ["it"]="dopotasto",
+ ["nl"]="natoets",
+ ["pe"]="بعدازکلید",
+ ["ro"]="dupatasta",
+ },
+ ["aftersection"]={
+ ["en"]="aftersection",
+ ["nl"]="nasectie",
+ },
+ ["align"]={
+ ["cs"]="zarovnani",
+ ["de"]="ausrichtung",
+ ["en"]="align",
+ ["fr"]="alignement",
+ ["it"]="allinea",
+ ["nl"]="uitlijnen",
+ ["pe"]="تنظیم",
+ ["ro"]="aliniere",
+ },
+ ["aligncharacter"]={
+ ["cs"]="aligncharacter",
+ ["de"]="aligncharacter",
+ ["en"]="aligncharacter",
+ ["fr"]="caracterealigne",
+ ["it"]="allineacarattere",
+ ["nl"]="karakteruitlijnen",
+ ["pe"]="حرف‌تنظیم",
+ ["ro"]="aliniazacaracter",
+ },
+ ["alignmentcharacter"]={
+ ["cs"]="alignmentcharacter",
+ ["de"]="alignmentcharacter",
+ ["en"]="alignmentcharacter",
+ ["fr"]="alignementcaractere",
+ ["it"]="carattereallineamento",
+ ["nl"]="uitlijnkarakter",
+ ["pe"]="حرف‌تنظیم‌کردن",
+ ["ro"]="alierecaracter",
+ },
+ ["alignsymbol"]={
+ ["en"]="alignsymbol",
+ },
+ ["aligntitle"]={
+ ["cs"]="zarovnejtitul",
+ ["de"]="titelausrichten",
+ ["en"]="aligntitle",
+ ["fr"]="alignementtitre",
+ ["it"]="allineatitolo",
+ ["nl"]="titeluitlijnen",
+ ["pe"]="عنوان‌تنظیم",
+ ["ro"]="alinieretitlu",
+ },
+ ["alternative"]={
+ ["cs"]="alternativa",
+ ["de"]="alternative",
+ ["en"]="alternative",
+ ["fr"]="alternative",
+ ["it"]="alternativa",
+ ["nl"]="variant",
+ ["pe"]="جایگزین",
+ ["ro"]="alternativ",
+ },
+ ["anchor"]={
+ ["en"]="anchor",
+ ["nl"]="anker",
+ },
+ ["andtext"]={
+ ["en"]="andtext",
+ },
+ ["apa"]={
+ ["cs"]="apa",
+ ["de"]="apa",
+ ["en"]="apa",
+ ["fr"]="apa",
+ ["it"]="apa",
+ ["nl"]="apa",
+ ["pe"]="apa",
+ ["ro"]="apa",
+ },
+ ["arrow"]={
+ ["cs"]="sipka",
+ ["de"]="pfeil",
+ ["en"]="arrow",
+ ["fr"]="fleche",
+ ["it"]="freccia",
+ ["nl"]="pijl",
+ ["pe"]="پیکان",
+ ["ro"]="sageata",
+ },
+ ["artauthor"]={
+ ["en"]="artauthor",
+ },
+ ["artauthoretaldisplay"]={
+ ["en"]="artauthoretaldisplay",
+ },
+ ["artauthoretallimit"]={
+ ["en"]="artauthoretallimit",
+ },
+ ["artauthoretaltext"]={
+ ["en"]="artauthoretaltext",
+ },
+ ["artoffset"]={
+ ["en"]="artoffset",
+ },
+ ["at"]={
+ ["cs"]="u",
+ ["de"]="bei",
+ ["en"]="at",
+ ["fr"]="a",
+ ["it"]="ad",
+ ["nl"]="op",
+ ["pe"]="در",
+ ["ro"]="la",
+ },
+ ["author"]={
+ ["cs"]="autor",
+ ["de"]="autor",
+ ["en"]="author",
+ ["fr"]="auteur",
+ ["it"]="autore",
+ ["nl"]="auteur",
+ ["pe"]="نویسنده",
+ ["ro"]="autor",
+ },
+ ["authorconversion"]={
+ ["en"]="authorconversion",
+ },
+ ["authoretaldisplay"]={
+ ["en"]="authoretaldisplay",
+ },
+ ["authoretallimit"]={
+ ["en"]="authoretallimit",
+ },
+ ["authoretaltext"]={
+ ["en"]="authoretaltext",
+ },
+ ["auto"]={
+ ["cs"]="auto",
+ ["de"]="auto",
+ ["en"]="auto",
+ ["fr"]="auto",
+ ["it"]="auto",
+ ["nl"]="auto",
+ ["pe"]="خودکار",
+ ["ro"]="auto",
+ },
+ ["autocase"]={
+ ["en"]="autocase",
+ ["nl"]="autocase",
+ },
+ ["autofile"]={
+ ["cs"]="autofile",
+ ["de"]="autofile",
+ ["en"]="autofile",
+ ["fr"]="autofile",
+ ["it"]="autofile",
+ ["nl"]="autofile",
+ ["pe"]="پرونده‌خودکار",
+ ["ro"]="autofile",
+ },
+ ["autofocus"]={
+ ["cs"]="autoostreni",
+ ["de"]="autofocus",
+ ["en"]="autofocus",
+ ["fr"]="autofocus",
+ ["it"]="autofocus",
+ ["nl"]="autofocus",
+ ["pe"]="تمرکز‌خودکار",
+ ["ro"]="autofocus",
+ },
+ ["autohang"]={
+ ["cs"]="autohang",
+ ["de"]="autohang",
+ ["en"]="autohang",
+ ["fr"]="autohang",
+ ["it"]="autohang",
+ ["nl"]="autohang",
+ ["pe"]="آویزان‌خودکار",
+ ["ro"]="autohang",
+ },
+ ["autostrut"]={
+ ["cs"]="autostrut",
+ ["de"]="autostrut",
+ ["en"]="autostrut",
+ ["fr"]="autostrut",
+ ["it"]="autostrut",
+ ["nl"]="autostrut",
+ ["pe"]="بست‌خودکار",
+ ["ro"]="autostrut",
+ },
+ ["autowidth"]={
+ ["cs"]="autosirka",
+ ["de"]="autobreite",
+ ["en"]="autowidth",
+ ["fr"]="autolargeur",
+ ["it"]="autoampiezza",
+ ["nl"]="autobreedte",
+ ["pe"]="عرض‌خودکار",
+ ["ro"]="autolatime",
+ },
+ ["availableheight"]={
+ ["en"]="availableheight",
+ ["nl"]="beschikbarehoogte",
+ },
+ ["availablewidth"]={
+ ["en"]="availablewidth",
+ ["nl"]="beschikbarebreedte",
+ },
+ ["axis"]={
+ ["cs"]="osa",
+ ["de"]="achsen",
+ ["en"]="axis",
+ ["fr"]="axe",
+ ["it"]="asse",
+ ["nl"]="assenstelsel",
+ ["pe"]="محورها",
+ ["ro"]="axa",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پس‌زمینه",
+ ["ro"]="fundal",
+ },
+ ["backgroundcolor"]={
+ ["cs"]="barvapozadi",
+ ["de"]="hintergrundfarbe",
+ ["en"]="backgroundcolor",
+ ["fr"]="couleurarriereplan",
+ ["it"]="coloresfondo",
+ ["nl"]="achtergrondkleur",
+ ["pe"]="رنگ‌پس‌زمینه",
+ ["ro"]="culoarefundal",
+ },
+ ["backgroundcorner"]={
+ ["cs"]="rohpozadi",
+ ["de"]="hintergrundwinkel",
+ ["en"]="backgroundcorner",
+ ["fr"]="coinarriereplan",
+ ["it"]="angolosfondo",
+ ["nl"]="achtergrondhoek",
+ ["pe"]="گوشه‌پس‌زمینه",
+ ["ro"]="coltfundal",
+ },
+ ["backgrounddepth"]={
+ ["cs"]="hloubkapozadi",
+ ["de"]="hintergrundtiefe",
+ ["en"]="backgrounddepth",
+ ["fr"]="profondeurarriereplan",
+ ["it"]="profonditasfondo",
+ ["nl"]="achtergronddiepte",
+ ["pe"]="عمق‌پس‌زمینه",
+ ["ro"]="adancimefundal",
+ },
+ ["backgroundoffset"]={
+ ["cs"]="offsetpozadi",
+ ["de"]="hintergrundoffset",
+ ["en"]="backgroundoffset",
+ ["fr"]="decalagearriereplan",
+ ["it"]="offsetsfondo",
+ ["nl"]="achtergrondoffset",
+ ["pe"]="آفست‌پس‌زمینه",
+ ["ro"]="offsetfundal",
+ },
+ ["backgroundradius"]={
+ ["cs"]="polomerpozadi",
+ ["de"]="hintergrundradius",
+ ["en"]="backgroundradius",
+ ["fr"]="rayonarriereplan",
+ ["it"]="raggiosfondo",
+ ["nl"]="achtergrondstraal",
+ ["pe"]="شعاع‌پس‌زمینه",
+ ["ro"]="razafundal",
+ },
+ ["backgroundscreen"]={
+ ["cs"]="rastrpozadi",
+ ["de"]="hintergrundraster",
+ ["en"]="backgroundscreen",
+ ["fr"]="ecranarriereplan",
+ ["it"]="schermosfondo",
+ ["nl"]="achtergrondraster",
+ ["pe"]="پرده‌پس‌زمینه",
+ ["ro"]="ecranfundal",
+ },
+ ["backreference"]={
+ ["en"]="backreference",
+ ["nl"]="terugreferentie",
+ },
+ ["backspace"]={
+ ["cs"]="zpetnamezera",
+ ["de"]="rumpfspatium",
+ ["en"]="backspace",
+ ["fr"]="retour",
+ ["it"]="backspace",
+ ["nl"]="rugwit",
+ ["pe"]="فضای‌پس",
+ ["ro"]="spatiuspate",
+ },
+ ["balance"]={
+ ["cs"]="rovnovaha",
+ ["de"]="ausgleichen",
+ ["en"]="balance",
+ ["fr"]="equilibre",
+ ["it"]="bilanciamento",
+ ["nl"]="balanceren",
+ ["pe"]="تعادل",
+ ["ro"]="balanta",
+ },
+ ["before"]={
+ ["cs"]="pred",
+ ["de"]="vor",
+ ["en"]="before",
+ ["fr"]="avant",
+ ["it"]="prima",
+ ["nl"]="voor",
+ ["pe"]="قبل‌از",
+ ["ro"]="inainte",
+ },
+ ["beforehead"]={
+ ["cs"]="predhlavickou",
+ ["de"]="vorkopf",
+ ["en"]="beforehead",
+ ["fr"]="avanttete",
+ ["it"]="primaditesta",
+ ["nl"]="kopvoor",
+ ["pe"]="قبل‌ازسر",
+ ["ro"]="inaintetitlu",
+ },
+ ["beforesection"]={
+ ["en"]="beforesection",
+ ["nl"]="voorsectie",
+ },
+ ["bet"]={
+ ["cs"]="bet",
+ ["de"]="bet",
+ ["en"]="bet",
+ ["fr"]="bet",
+ ["it"]="bet",
+ ["nl"]="bet",
+ ["pe"]="bet",
+ ["ro"]="bet",
+ },
+ ["bidi"]={
+ ["en"]="bidi",
+ },
+ ["big"]={
+ ["cs"]="velky",
+ ["de"]="gross",
+ ["en"]="big",
+ ["fr"]="grand",
+ ["it"]="grande",
+ ["nl"]="groot",
+ ["pe"]="بزرگ",
+ ["ro"]="mare",
+ },
+ ["blank"]={
+ ["cs"]="prazdny",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blanc",
+ },
+ ["bleedoffset"]={
+ ["en"]="bleedoffset",
+ },
+ ["blockway"]={
+ ["cs"]="dobloku",
+ ["de"]="blockauf",
+ ["en"]="blockway",
+ ["fr"]="blockway",
+ ["it"]="blockway",
+ ["nl"]="blokwijze",
+ ["pe"]="راه‌بلوک",
+ ["ro"]="blockway",
+ },
+ ["bodyfont"]={
+ ["cs"]="zakladnifont",
+ ["de"]="fliesstext",
+ ["en"]="bodyfont",
+ ["fr"]="policecorps",
+ ["it"]="fonttesto",
+ ["nl"]="korps",
+ ["pe"]="قلم‌بدنه",
+ ["ro"]="fonttext",
+ },
+ ["boffset"]={
+ ["en"]="boffset",
+ },
+ ["boldfeatures"]={
+ ["en"]="boldfeatures",
+ },
+ ["boldfont"]={
+ ["en"]="boldfont",
+ },
+ ["bolditalicfeatures"]={
+ ["en"]="bolditalicfeatures",
+ },
+ ["bolditalicfont"]={
+ ["en"]="bolditalicfont",
+ },
+ ["boldslantedfeatures"]={
+ ["en"]="boldslantedfeatures",
+ },
+ ["boldslantedfont"]={
+ ["en"]="boldslantedfont",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["bottom"]={
+ ["cs"]="spodek",
+ ["de"]="unten",
+ ["en"]="bottom",
+ ["fr"]="inf",
+ ["it"]="fondo",
+ ["nl"]="onder",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["bottomafter"]={
+ ["en"]="bottomafter",
+ },
+ ["bottombefore"]={
+ ["en"]="bottombefore",
+ },
+ ["bottomcommand"]={
+ ["en"]="bottomcommand",
+ ["nl"]="ondercommando",
+ },
+ ["bottomdistance"]={
+ ["cs"]="vzdalenostspodku",
+ ["de"]="abstandunten",
+ ["en"]="bottomdistance",
+ ["fr"]="distanceinf",
+ ["it"]="distanzafondo",
+ ["nl"]="onderafstand",
+ ["pe"]="فاصله‌پایین",
+ ["ro"]="distantajos",
+ },
+ ["bottomframe"]={
+ ["cs"]="ramecekdole",
+ ["de"]="untenrahmen",
+ ["en"]="bottomframe",
+ ["fr"]="cadreinf",
+ ["it"]="cornicefondo",
+ ["nl"]="onderkader",
+ ["pe"]="قالب‌پایین",
+ ["ro"]="framejos",
+ },
+ ["bottomoffset"]={
+ ["cs"]="offsetspodku",
+ ["de"]="untenoffset",
+ ["en"]="bottomoffset",
+ ["fr"]="decalageinf",
+ ["it"]="offsetfondo",
+ ["nl"]="onderoffset",
+ ["pe"]="آفست‌پایین",
+ ["ro"]="offsetjos",
+ },
+ ["bottomspace"]={
+ ["cs"]="bottomspace",
+ ["de"]="bottomspace",
+ ["en"]="bottomspace",
+ ["fr"]="espaceinf",
+ ["it"]="spaziofondo",
+ ["nl"]="bodemwit",
+ ["pe"]="فضای‌پایین",
+ ["ro"]="spatiujos",
+ },
+ ["bottomstate"]={
+ ["cs"]="statusspodku",
+ ["de"]="untenstatus",
+ ["en"]="bottomstate",
+ ["fr"]="etatinf",
+ ["it"]="statofondo",
+ ["nl"]="onderstatus",
+ ["pe"]="وضعیت‌پایین",
+ ["ro"]="starejos",
+ },
+ ["buffer"]={
+ ["en"]="buffer",
+ ["nl"]="buffer",
+ },
+ ["cache"]={
+ ["cs"]="cache",
+ ["de"]="cache",
+ ["en"]="cache",
+ ["fr"]="cache",
+ ["it"]="cache",
+ ["nl"]="cache",
+ ["pe"]="میانگیر",
+ ["ro"]="cache",
+ },
+ ["calculate"]={
+ ["cs"]="pocitat",
+ ["de"]="berechnen",
+ ["en"]="calculate",
+ ["fr"]="calculer",
+ ["it"]="calcola",
+ ["nl"]="bereken",
+ ["pe"]="محاسبه",
+ ["ro"]="calculeaza",
+ },
+ ["category"]={
+ ["en"]="category",
+ ["nl"]="categorie",
+ },
+ ["ccommand"]={
+ ["cs"]="cprikaz",
+ ["de"]="cbefehl",
+ ["en"]="ccommand",
+ ["fr"]="ccommande",
+ ["it"]="ccomando",
+ ["nl"]="ccommando",
+ ["pe"]="فرمان",
+ ["ro"]="comandac",
+ },
+ ["character"]={
+ ["en"]="character",
+ },
+ ["characters"]={
+ ["en"]="characters",
+ },
+ ["check"]={
+ ["en"]="check",
+ },
+ ["click"]={
+ ["cs"]="klik",
+ ["de"]="klick",
+ ["en"]="click",
+ ["fr"]="clic",
+ ["it"]="click",
+ ["nl"]="klik",
+ ["pe"]="فشردن",
+ ["ro"]="click",
+ },
+ ["clickin"]={
+ ["cs"]="klikuvnitr",
+ ["de"]="klickin",
+ ["en"]="clickin",
+ ["fr"]="clicinterieur",
+ ["it"]="clickdentro",
+ ["nl"]="klikin",
+ ["pe"]="فشردن‌داخل",
+ ["ro"]="clickintru",
+ },
+ ["clickout"]={
+ ["cs"]="klikvne",
+ ["de"]="klickaus",
+ ["en"]="clickout",
+ ["fr"]="clicexterieur",
+ ["it"]="clickfuori",
+ ["nl"]="klikuit",
+ ["pe"]="فشردن‌خارج",
+ ["ro"]="clickies",
+ },
+ ["clipoffset"]={
+ ["cs"]="clipoffset",
+ ["de"]="clipoffset",
+ ["en"]="clipoffset",
+ ["fr"]="clipoffset",
+ ["it"]="clipoffset",
+ ["nl"]="clipoffset",
+ ["pe"]="آفست‌کلیپ",
+ ["ro"]="clipoffset",
+ },
+ ["closeaction"]={
+ ["cs"]="zavriakci",
+ ["de"]="schliessenaktion",
+ ["en"]="closeaction",
+ ["fr"]="actionfermeture",
+ ["it"]="azionechiudi",
+ ["nl"]="sluitactie",
+ ["pe"]="بستن‌کنش",
+ ["ro"]="actiuneinchidere",
+ },
+ ["closecommand"]={
+ ["cs"]="closecommand",
+ ["de"]="closecommand",
+ ["en"]="closecommand",
+ ["fr"]="closecommand",
+ ["it"]="closecommand",
+ ["nl"]="sluitcommando",
+ ["pe"]="بستن‌فرمان",
+ ["ro"]="closecommand",
+ },
+ ["closepage"]={
+ ["en"]="closepage",
+ ["nl"]="sluitpagina",
+ },
+ ["closepageaction"]={
+ ["cs"]="akcezavrenistranky",
+ ["de"]="closepageaction",
+ ["en"]="closepageaction",
+ ["fr"]="actionfermeturepage",
+ ["it"]="azionechiudipagina",
+ ["nl"]="sluitpaginaactie",
+ ["pe"]="بستن‌عمل‌صفحه",
+ ["ro"]="actiuneinchiderepagina",
+ },
+ ["closesymbol"]={
+ ["cs"]="closesymbol",
+ ["de"]="closesymbol",
+ ["en"]="closesymbol",
+ ["fr"]="closesymbol",
+ ["it"]="closesymbol",
+ ["nl"]="sluitsymbool",
+ ["pe"]="بستن‌نماد",
+ ["ro"]="closesymbol",
+ },
+ ["color"]={
+ ["cs"]="barva",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["column"]={
+ ["cs"]="sloupec",
+ ["de"]="spalte",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["columndistance"]={
+ ["cs"]="vzdalenostsloupcu",
+ ["de"]="spaltenabstand",
+ ["en"]="columndistance",
+ ["fr"]="distancecolonne",
+ ["it"]="distanzacolonne",
+ ["nl"]="kolomafstand",
+ ["pe"]="فاصله‌ستون",
+ ["ro"]="distantacoloane",
+ },
+ ["columns"]={
+ ["cs"]="sloupce",
+ ["de"]="spalten",
+ ["en"]="columns",
+ ["fr"]="colonnes",
+ ["it"]="colonne",
+ ["nl"]="kolommen",
+ ["pe"]="ستونها",
+ ["ro"]="coloane",
+ },
+ ["comma"]={
+ ["en"]="comma",
+ },
+ ["command"]={
+ ["cs"]="prikaz",
+ ["de"]="befehl",
+ ["en"]="command",
+ ["fr"]="commande",
+ ["it"]="comando",
+ ["nl"]="commando",
+ ["pe"]="فرمان",
+ ["ro"]="comanda",
+ },
+ ["commandafter"]={
+ ["cs"]="prikazpo",
+ ["de"]="zumbefehl",
+ ["en"]="commandafter",
+ ["fr"]="commandeapres",
+ ["it"]="comdandodopo",
+ ["nl"]="nacommando",
+ ["pe"]="فرمان‌بعداز",
+ ["ro"]="comandadupa",
+ },
+ ["commandbefore"]={
+ ["cs"]="predchoziprikaz",
+ ["de"]="vorbefehl",
+ ["en"]="commandbefore",
+ ["fr"]="commandeavant",
+ ["it"]="comandoprima",
+ ["nl"]="voorcommando",
+ ["pe"]="فرمان‌قبل‌از",
+ ["ro"]="comandainainte",
+ },
+ ["commands"]={
+ ["cs"]="prikazy",
+ ["de"]="befehle",
+ ["en"]="commands",
+ ["fr"]="commandes",
+ ["it"]="comandi",
+ ["nl"]="commandos",
+ ["pe"]="فرمانها",
+ ["ro"]="comenzi",
+ },
+ ["comment"]={
+ ["en"]="comment",
+ },
+ ["commentchar"]={
+ ["en"]="commentchar",
+ },
+ ["commentoffset"]={
+ ["en"]="commentoffset",
+ },
+ ["compact"]={
+ ["en"]="compact",
+ ["nl"]="compact",
+ },
+ ["component"]={
+ ["cs"]="component",
+ ["de"]="component",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="component",
+ ["nl"]="component",
+ ["pe"]="مولفه",
+ ["ro"]="component",
+ },
+ ["compoundhyphen"]={
+ ["cs"]="compoundhyphen",
+ ["de"]="compoundhyphen",
+ ["en"]="compoundhyphen",
+ ["fr"]="compoundhyphen",
+ ["it"]="compoundhyphen",
+ ["nl"]="koppelteken",
+ ["pe"]="compoundhyphen",
+ ["ro"]="compoundhyphen",
+ },
+ ["compress"]={
+ ["cs"]="compress",
+ ["de"]="compress",
+ ["en"]="compress",
+ ["fr"]="compress",
+ ["it"]="compress",
+ ["nl"]="comprimeren",
+ ["pe"]="فشردن",
+ ["ro"]="compress",
+ },
+ ["compressseparator"]={
+ ["en"]="compressseparator",
+ },
+ ["concerns"]={
+ ["en"]="concerns",
+ ["nl"]="betreft",
+ },
+ ["connector"]={
+ ["en"]="connector",
+ },
+ ["continue"]={
+ ["cs"]="pokracovat",
+ ["de"]="fortsetzen",
+ ["en"]="continue",
+ ["fr"]="continue",
+ ["it"]="continua",
+ ["nl"]="doorgaan",
+ ["pe"]="ادامه",
+ ["ro"]="continua",
+ },
+ ["contrastcolor"]={
+ ["cs"]="kontrastnibarva",
+ ["de"]="kontrastfarbe",
+ ["en"]="contrastcolor",
+ ["fr"]="coleurcontraste",
+ ["it"]="colorecontrasto",
+ ["nl"]="contrastkleur",
+ ["pe"]="contrastcolor",
+ ["ro"]="culoarecontrast",
+ },
+ ["controls"]={
+ ["cs"]="controls",
+ ["de"]="controls",
+ ["en"]="controls",
+ ["fr"]="controles",
+ ["it"]="controlli",
+ ["nl"]="sturing",
+ ["pe"]="کنترلها",
+ ["ro"]="controale",
+ },
+ ["conversion"]={
+ ["cs"]="konverze",
+ ["de"]="konversion",
+ ["en"]="conversion",
+ ["fr"]="conversion",
+ ["it"]="conversione",
+ ["nl"]="conversie",
+ ["pe"]="تبدیل",
+ ["ro"]="conversie",
+ },
+ ["convertfile"]={
+ ["cs"]="konverzesouboru",
+ ["de"]="konvertieredatei",
+ ["en"]="convertfile",
+ ["fr"]="conversionfichier",
+ ["it"]="convertifile",
+ ["nl"]="converteerfile",
+ ["pe"]="پرونده‌تبدیل",
+ ["ro"]="convertestefisier",
+ },
+ ["corner"]={
+ ["cs"]="roh",
+ ["de"]="winkel",
+ ["en"]="corner",
+ ["fr"]="coin",
+ ["it"]="angolo",
+ ["nl"]="hoek",
+ ["pe"]="گوشه",
+ ["ro"]="colt",
+ },
+ ["coupling"]={
+ ["cs"]="propojeni",
+ ["de"]="verknuepfung",
+ ["en"]="coupling",
+ ["fr"]="couplage",
+ ["it"]="accoppiamento",
+ ["nl"]="koppeling",
+ ["pe"]="تزویج",
+ ["ro"]="cuplare",
+ },
+ ["couplingway"]={
+ ["cs"]="zpusobpropojeni",
+ ["de"]="verkopplungsart",
+ ["en"]="couplingway",
+ ["fr"]="modecouplage",
+ ["it"]="modoaccoppiamento",
+ ["nl"]="koppelwijze",
+ ["pe"]="روش‌تزویج",
+ ["ro"]="modcuplare",
+ },
+ ["criterium"]={
+ ["cs"]="kriterium",
+ ["de"]="kriterium",
+ ["en"]="criterium",
+ ["fr"]="critere",
+ ["it"]="criterio",
+ ["nl"]="criterium",
+ ["pe"]="criterium",
+ ["ro"]="criteriu",
+ },
+ ["cropoffset"]={
+ ["en"]="cropoffset",
+ },
+ ["cssfile"]={
+ ["en"]="cssfile",
+ },
+ ["current"]={
+ ["cs"]="aktualni",
+ ["de"]="aktuell",
+ ["en"]="current",
+ ["fr"]="courant",
+ ["it"]="corrente",
+ ["nl"]="huidige",
+ ["pe"]="جاری",
+ ["ro"]="curent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضای‌برش",
+ ["ro"]="cutspace",
+ },
+ ["dash"]={
+ ["cs"]="pomlcka",
+ ["de"]="strich",
+ ["en"]="dash",
+ ["fr"]="pointille",
+ ["it"]="dash",
+ ["nl"]="streep",
+ ["pe"]="دش",
+ ["ro"]="dash",
+ },
+ ["dat"]={
+ ["cs"]="dat",
+ ["de"]="dat",
+ ["en"]="dat",
+ ["fr"]="dat",
+ ["it"]="dat",
+ ["nl"]="dat",
+ ["pe"]="dat",
+ ["ro"]="dat",
+ },
+ ["database"]={
+ ["en"]="database",
+ },
+ ["dataset"]={
+ ["en"]="dataset",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["deepnumbercommand"]={
+ ["cs"]="deepnumbercommand",
+ ["de"]="deepnumbercommand",
+ ["en"]="deepnumbercommand",
+ ["fr"]="deepnumbercommand",
+ ["it"]="deepnumbercommand",
+ ["nl"]="diepnummercommando",
+ ["pe"]="فرمان‌شماره‌عمیق",
+ ["ro"]="deepnumbercommand",
+ },
+ ["deeptextcommand"]={
+ ["cs"]="deeptextcommand",
+ ["de"]="deeptextcommand",
+ ["en"]="deeptextcommand",
+ ["fr"]="deeptextcommand",
+ ["it"]="deeptextcommand",
+ ["nl"]="dieptekstcommando",
+ ["pe"]="فرمان‌متن‌عمیق",
+ ["ro"]="deeptextcommand",
+ },
+ ["default"]={
+ ["cs"]="implicitni",
+ ["de"]="default",
+ ["en"]="default",
+ ["fr"]="defaut",
+ ["it"]="implicito",
+ ["nl"]="default",
+ ["pe"]="پیش‌فرض",
+ ["ro"]="implicit",
+ },
+ ["delay"]={
+ ["cs"]="prodleva",
+ ["de"]="wartezeit",
+ ["en"]="delay",
+ ["fr"]="delai",
+ ["it"]="attesa",
+ ["nl"]="wachttijd",
+ ["pe"]="تاخیر",
+ ["ro"]="intarziere",
+ },
+ ["depth"]={
+ ["cs"]="hloubka",
+ ["de"]="tiefe",
+ ["en"]="depth",
+ ["fr"]="profondeur",
+ ["it"]="profondita",
+ ["nl"]="diepte",
+ ["pe"]="عمق",
+ ["ro"]="inaltime",
+ },
+ ["depthcorrection"]={
+ ["cs"]="korekcehloubky",
+ ["de"]="tiefekorrektur",
+ ["en"]="depthcorrection",
+ ["fr"]="correctionprofondeur",
+ ["it"]="correzioneprofondita",
+ ["nl"]="dieptecorrectie",
+ ["pe"]="تصحیح‌عمق",
+ ["ro"]="corectieadancime",
+ },
+ ["direction"]={
+ ["cs"]="smer",
+ ["de"]="richtung",
+ ["en"]="direction",
+ ["fr"]="direction",
+ ["it"]="direzione",
+ ["nl"]="richting",
+ ["pe"]="جهت",
+ ["ro"]="directie",
+ },
+ ["directory"]={
+ ["cs"]="adresar",
+ ["de"]="verzeichnis",
+ ["en"]="directory",
+ ["fr"]="repertoire",
+ ["it"]="directory",
+ ["nl"]="directory",
+ ["pe"]="پوشه",
+ ["ro"]="director",
+ },
+ ["display"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="display",
+ ["fr"]="affichage",
+ ["it"]="display",
+ ["nl"]="scherm",
+ ["pe"]="نمایش",
+ ["ro"]="display",
+ },
+ ["distance"]={
+ ["cs"]="vzdalenost",
+ ["de"]="abstand",
+ ["en"]="distance",
+ ["fr"]="distance",
+ ["it"]="distanza",
+ ["nl"]="afstand",
+ ["pe"]="فاصله",
+ ["ro"]="distanta",
+ },
+ ["domain"]={
+ ["en"]="domain",
+ },
+ ["dot"]={
+ ["cs"]="tecka",
+ ["de"]="punkt",
+ ["en"]="dot",
+ ["fr"]="point",
+ ["it"]="punto",
+ ["nl"]="punt",
+ ["pe"]="نقطه",
+ ["ro"]="punct",
+ },
+ ["doublesided"]={
+ ["cs"]="oboustranne",
+ ["de"]="doppelseitig",
+ ["en"]="doublesided",
+ ["fr"]="rectoverso",
+ ["it"]="doppiafaccia",
+ ["nl"]="dubbelzijdig",
+ ["pe"]="دورو",
+ ["ro"]="douafete",
+ },
+ ["down"]={
+ ["en"]="down",
+ },
+ ["dummy"]={
+ ["cs"]="dummy",
+ ["de"]="dummy",
+ ["en"]="dummy",
+ ["fr"]="dummy",
+ ["it"]="dummy",
+ ["nl"]="dummy",
+ ["pe"]="مصنوعی",
+ ["ro"]="dummy",
+ },
+ ["dx"]={
+ ["cs"]="dx",
+ ["de"]="dx",
+ ["en"]="dx",
+ ["fr"]="dx",
+ ["it"]="dx",
+ ["nl"]="dx",
+ ["pe"]="dx",
+ ["ro"]="dx",
+ },
+ ["dy"]={
+ ["cs"]="dy",
+ ["de"]="dy",
+ ["en"]="dy",
+ ["fr"]="dy",
+ ["it"]="dy",
+ ["nl"]="dy",
+ ["pe"]="dy",
+ ["ro"]="dy",
+ },
+ ["edge"]={
+ ["cs"]="hrana",
+ ["de"]="kante",
+ ["en"]="edge",
+ ["fr"]="bord",
+ ["it"]="bordo",
+ ["nl"]="rand",
+ ["pe"]="لبه",
+ ["ro"]="bordura",
+ },
+ ["edgedistance"]={
+ ["cs"]="vzdalenosthrany",
+ ["de"]="kantenabstand",
+ ["en"]="edgedistance",
+ ["fr"]="distancebord",
+ ["it"]="distanzabordo",
+ ["nl"]="randafstand",
+ ["pe"]="فاصله‌لبه",
+ ["ro"]="distantabordura",
+ },
+ ["editor"]={
+ ["en"]="editor",
+ },
+ ["editoretaldisplay"]={
+ ["en"]="editoretaldisplay",
+ },
+ ["editoretallimit"]={
+ ["en"]="editoretallimit",
+ },
+ ["editoretaltext"]={
+ ["en"]="editoretaltext",
+ },
+ ["empty"]={
+ ["cs"]="prazdne",
+ ["de"]="leer",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="vuoto",
+ ["nl"]="leeg",
+ ["pe"]="تهی",
+ ["ro"]="gol",
+ },
+ ["entities"]={
+ ["en"]="entities",
+ ["nl"]="entities",
+ },
+ ["entries"]={
+ ["en"]="entries",
+ ["nl"]="ingangen",
+ },
+ ["equalheight"]={
+ ["cs"]="equalheight",
+ ["de"]="equalheight",
+ ["en"]="equalheight",
+ ["fr"]="equalheight",
+ ["it"]="equalheight",
+ ["nl"]="equalheight",
+ ["pe"]="ارتفاع‌یکسان",
+ ["ro"]="equalheight",
+ },
+ ["equalwidth"]={
+ ["cs"]="equalwidth",
+ ["de"]="equalwidth",
+ ["en"]="equalwidth",
+ ["fr"]="equalwidth",
+ ["it"]="equalwidth",
+ ["nl"]="equalwidth",
+ ["pe"]="عرض‌یکسان",
+ ["ro"]="equalwidth",
+ },
+ ["escape"]={
+ ["cs"]="escape",
+ ["de"]="escape",
+ ["en"]="escape",
+ ["fr"]="escape",
+ ["it"]="escape",
+ ["nl"]="escape",
+ ["pe"]="فرار",
+ ["ro"]="escape",
+ },
+ ["etaldisplay"]={
+ ["en"]="etaldisplay",
+ },
+ ["etallimit"]={
+ ["en"]="etallimit",
+ },
+ ["etaloption"]={
+ ["en"]="etaloption",
+ },
+ ["etaltext"]={
+ ["en"]="etaltext",
+ },
+ ["evenmargin"]={
+ ["cs"]="sudamarginalie",
+ ["de"]="geraderand",
+ ["en"]="evenmargin",
+ ["fr"]="margepaire",
+ ["it"]="marginepari",
+ ["nl"]="evenmarge",
+ ["pe"]="حاشیه‌زوج",
+ ["ro"]="marginepara",
+ },
+ ["exitoffset"]={
+ ["en"]="exitoffset",
+ },
+ ["expansion"]={
+ ["cs"]="expanzen",
+ ["de"]="expansion",
+ ["en"]="expansion",
+ ["fr"]="expansion",
+ ["it"]="espansione",
+ ["nl"]="expansie",
+ ["pe"]="گسترش",
+ ["ro"]="expansiune",
+ },
+ ["export"]={
+ ["en"]="export",
+ ["nl"]="exporteer",
+ },
+ ["extras"]={
+ ["cs"]="extras",
+ ["de"]="extras",
+ ["en"]="extras",
+ ["fr"]="extras",
+ ["it"]="extras",
+ ["nl"]="extras",
+ ["pe"]="extras",
+ ["ro"]="extras",
+ },
+ ["factor"]={
+ ["cs"]="faktor",
+ ["de"]="faktor",
+ ["en"]="factor",
+ ["fr"]="facteur",
+ ["it"]="fattore",
+ ["nl"]="factor",
+ ["pe"]="عامل",
+ ["ro"]="factor",
+ },
+ ["fallback"]={
+ ["cs"]="fallback",
+ ["de"]="fallback",
+ ["en"]="fallback",
+ ["fr"]="fallback",
+ ["it"]="fallback",
+ ["nl"]="terugval",
+ ["pe"]="عقب‌ریختن",
+ ["ro"]="fallback",
+ },
+ ["family"]={
+ ["cs"]="rodina",
+ ["de"]="familie",
+ ["en"]="family",
+ ["fr"]="famille",
+ ["it"]="famiglia",
+ ["nl"]="soort",
+ ["pe"]="خانواده",
+ ["ro"]="familie",
+ },
+ ["features"]={
+ ["en"]="features",
+ },
+ ["fences"]={
+ ["en"]="fences",
+ },
+ ["field"]={
+ ["en"]="field",
+ },
+ ["fieldbackgroundcolor"]={
+ ["cs"]="barvapozadipole",
+ ["de"]="feldhintergrundfarbe",
+ ["en"]="fieldbackgroundcolor",
+ ["fr"]="couleurarrierreplanchamp",
+ ["it"]="coloresfondocampo",
+ ["nl"]="veldachtergrondkleur",
+ ["pe"]="رنگ‌پس‌زمینه‌میدان",
+ ["ro"]="culoarefundalcamp",
+ },
+ ["fieldframecolor"]={
+ ["cs"]="barvarameckupole",
+ ["de"]="feldrahmenfarbe",
+ ["en"]="fieldframecolor",
+ ["fr"]="couleurcadrechamp",
+ ["it"]="colorecornicecampo",
+ ["nl"]="veldkaderkleur",
+ ["pe"]="رنگ‌قالب‌میدان",
+ ["ro"]="culoareframecamp",
+ },
+ ["fieldlayer"]={
+ ["cs"]="fieldlayer",
+ ["de"]="fieldlayer",
+ ["en"]="fieldlayer",
+ ["fr"]="calquechamp",
+ ["it"]="fieldlayer",
+ ["nl"]="veldlaag",
+ ["pe"]="لایه‌میدان",
+ ["ro"]="fieldlayer",
+ },
+ ["fieldoffset"]={
+ ["cs"]="offsetpole",
+ ["de"]="feldoffset",
+ ["en"]="fieldoffset",
+ ["fr"]="offsetchamp",
+ ["it"]="offsetcampo",
+ ["nl"]="veldoffset",
+ ["pe"]="آفست‌میدان",
+ ["ro"]="offsetcamp",
+ },
+ ["file"]={
+ ["cs"]="soubor",
+ ["de"]="datei",
+ ["en"]="file",
+ ["fr"]="fichier",
+ ["it"]="file",
+ ["nl"]="file",
+ ["pe"]="پرونده",
+ ["ro"]="fisier",
+ },
+ ["filler"]={
+ ["en"]="filler",
+ },
+ ["filtercommand"]={
+ ["en"]="filtercommand",
+ },
+ ["finalnamesep"]={
+ ["en"]="finalnamesep",
+ },
+ ["finalpagesep"]={
+ ["en"]="finalpagesep",
+ },
+ ["finalpubsep"]={
+ ["en"]="finalpubsep",
+ },
+ ["first"]={
+ ["en"]="first",
+ },
+ ["firstnamesep"]={
+ ["en"]="firstnamesep",
+ },
+ ["firstpage"]={
+ ["cs"]="prvnistranka",
+ ["de"]="ersteseite",
+ ["en"]="firstpage",
+ ["fr"]="premierepage",
+ ["it"]="primapagina",
+ ["nl"]="eerstepagina",
+ ["pe"]="صفحه‌اول",
+ ["ro"]="primapagina",
+ },
+ ["focus"]={
+ ["cs"]="zaostreni",
+ ["de"]="focus",
+ ["en"]="focus",
+ ["fr"]="focus",
+ ["it"]="focus",
+ ["nl"]="focus",
+ ["pe"]="تمرکز",
+ ["ro"]="focus",
+ },
+ ["focusin"]={
+ ["cs"]="focusin",
+ ["de"]="focusin",
+ ["en"]="focusin",
+ ["fr"]="focusin",
+ ["it"]="focusin",
+ ["nl"]="focusin",
+ ["pe"]="تمرکزدرون",
+ ["ro"]="focusin",
+ },
+ ["focusout"]={
+ ["cs"]="focusout",
+ ["de"]="focusout",
+ ["en"]="focusout",
+ ["fr"]="focusout",
+ ["it"]="focusout",
+ ["nl"]="focusuit",
+ ["pe"]="تمرکزبیرون",
+ ["ro"]="focusout",
+ },
+ ["focusoffset"]={
+ ["en"]="focusoffset",
+ ["nl"]="focusoffset",
+ },
+ ["footer"]={
+ ["cs"]="upati",
+ ["de"]="fusszeile",
+ ["en"]="footer",
+ ["fr"]="pdp",
+ ["it"]="piedipagina",
+ ["nl"]="voet",
+ ["pe"]="ته‌برگ",
+ ["ro"]="subsol",
+ },
+ ["footerdistance"]={
+ ["cs"]="vzdalenostupati",
+ ["de"]="fusszeilenabstand",
+ ["en"]="footerdistance",
+ ["fr"]="dsitancepdp",
+ ["it"]="distanzapdp",
+ ["nl"]="voetafstand",
+ ["pe"]="فاصله‌ته‌برگ",
+ ["ro"]="distantasubsol",
+ },
+ ["footerstate"]={
+ ["cs"]="statusupati",
+ ["de"]="fusszeilenstatus",
+ ["en"]="footerstate",
+ ["fr"]="etatpdp",
+ ["it"]="statopdp",
+ ["nl"]="voetstatus",
+ ["pe"]="وضعیت‌ته‌برگ",
+ ["ro"]="staresubsol",
+ },
+ ["force"]={
+ ["cs"]="sila",
+ ["de"]="zwinge",
+ ["en"]="force",
+ ["fr"]="force",
+ ["it"]="forza",
+ ["nl"]="forceer",
+ ["pe"]="اجبار",
+ ["ro"]="fortat",
+ },
+ ["foregroundcolor"]={
+ ["cs"]="foregroundcolor",
+ ["de"]="foregroundcolor",
+ ["en"]="foregroundcolor",
+ ["fr"]="couleurpremierplan",
+ ["it"]="coloreprimopiano",
+ ["nl"]="voorgrondkleur",
+ ["pe"]="رنگ‌پیش‌زمینه",
+ ["ro"]="foregroundcolor",
+ },
+ ["foregroundstyle"]={
+ ["cs"]="foregroundstyle",
+ ["de"]="foregroundstyle",
+ ["en"]="foregroundstyle",
+ ["fr"]="stylepremierplan",
+ ["it"]="foregroundstyle",
+ ["nl"]="voorgrondletter",
+ ["pe"]="سبک‌پیش‌زمینه",
+ ["ro"]="foregroundstyle",
+ },
+ ["format"]={
+ ["cs"]="formatovat",
+ ["de"]="formatieren",
+ ["en"]="format",
+ ["fr"]="formatter",
+ ["it"]="format",
+ ["nl"]="formatteer",
+ ["pe"]="شمایل",
+ ["ro"]="format",
+ },
+ ["frame"]={
+ ["cs"]="ramecek",
+ ["de"]="rahmen",
+ ["en"]="frame",
+ ["fr"]="cadre",
+ ["it"]="cornice",
+ ["nl"]="kader",
+ ["pe"]="قالب",
+ ["ro"]="frame",
+ },
+ ["framecolor"]={
+ ["cs"]="barvaramecku",
+ ["de"]="rahmenfarbe",
+ ["en"]="framecolor",
+ ["fr"]="couleurcadre",
+ ["it"]="colorecornice",
+ ["nl"]="kaderkleur",
+ ["pe"]="رنگ‌قالب",
+ ["ro"]="culoareframe",
+ },
+ ["framecorner"]={
+ ["cs"]="rohramecku",
+ ["de"]="rahmenwinkel",
+ ["en"]="framecorner",
+ ["fr"]="coincadre",
+ ["it"]="angolocornice",
+ ["nl"]="kaderhoek",
+ ["pe"]="گوشه‌قالب",
+ ["ro"]="coltframe",
+ },
+ ["framedepth"]={
+ ["cs"]="hloubkaramecku",
+ ["de"]="rahmentiefe",
+ ["en"]="framedepth",
+ ["fr"]="profondeurcadre",
+ ["it"]="profonditacornice",
+ ["nl"]="kaderdiepte",
+ ["pe"]="عمق‌قالب",
+ ["ro"]="adancimeframe",
+ },
+ ["frameoffset"]={
+ ["cs"]="offsetramecku",
+ ["de"]="rahmenoffset",
+ ["en"]="frameoffset",
+ ["fr"]="decalagecadre",
+ ["it"]="offsetcornice",
+ ["nl"]="kaderoffset",
+ ["pe"]="آفست‌قالب",
+ ["ro"]="offsetframe",
+ },
+ ["frameradius"]={
+ ["cs"]="polomerramecku",
+ ["de"]="rahmenradius",
+ ["en"]="frameradius",
+ ["fr"]="rayoncadre",
+ ["it"]="raggiocornice",
+ ["nl"]="kaderstraal",
+ ["pe"]="شعاع‌قالب",
+ ["ro"]="razaframe",
+ },
+ ["frames"]={
+ ["cs"]="ramecky",
+ ["de"]="umrahmen",
+ ["en"]="frames",
+ ["fr"]="cadres",
+ ["it"]="cornici",
+ ["nl"]="hokjes",
+ ["pe"]="قالبها",
+ ["ro"]="frames",
+ },
+ ["from"]={
+ ["cs"]="z",
+ ["de"]="von",
+ ["en"]="from",
+ ["fr"]="de",
+ ["it"]="da",
+ ["nl"]="van",
+ ["pe"]="از",
+ ["ro"]="dela",
+ },
+ ["functioncolor"]={
+ ["en"]="functioncolor",
+ },
+ ["functionstyle"]={
+ ["en"]="functionstyle",
+ },
+ ["get"]={
+ ["cs"]="ziskat",
+ ["de"]="hole",
+ ["en"]="get",
+ ["fr"]="obtient",
+ ["it"]="prendi",
+ ["nl"]="haal",
+ ["pe"]="بگیر",
+ ["ro"]="adu",
+ },
+ ["global"]={
+ ["cs"]="globalne",
+ ["de"]="global",
+ ["en"]="global",
+ ["fr"]="global",
+ ["it"]="globale",
+ ["nl"]="globaal",
+ ["pe"]="سراسری",
+ ["ro"]="global",
+ },
+ ["goodies"]={
+ ["en"]="goodies",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gritter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="grid",
+ ["pe"]="توری",
+ ["ro"]="grid",
+ },
+ ["group"]={
+ ["en"]="group",
+ },
+ ["groupsuffix"]={
+ ["en"]="groupsuffix",
+ },
+ ["hang"]={
+ ["cs"]="zaveseni",
+ ["de"]="haengend",
+ ["en"]="hang",
+ ["fr"]="suspend",
+ ["it"]="sospendi",
+ ["nl"]="hang",
+ ["pe"]="بیاویز",
+ ["ro"]="suspenda",
+ },
+ ["hcompact"]={
+ ["en"]="hcompact",
+ ["nl"]="hcomprimeer",
+ },
+ ["headalign"]={
+ ["en"]="headalign",
+ ["nl"]="kopuitlijnen",
+ },
+ ["headcolor"]={
+ ["cs"]="barvahlavicky",
+ ["de"]="kopffarbe",
+ ["en"]="headcolor",
+ ["fr"]="couleurtete",
+ ["it"]="coloretesta",
+ ["nl"]="kopkleur",
+ ["pe"]="رنگ‌سر",
+ ["ro"]="culoaretitlu",
+ },
+ ["headcommand"]={
+ ["cs"]="headcommand",
+ ["de"]="headcommand",
+ ["en"]="headcommand",
+ ["fr"]="commandetete",
+ ["it"]="headcommand",
+ ["nl"]="kopcommando",
+ ["pe"]="فرمان‌سر",
+ ["ro"]="headcommand",
+ },
+ ["headconversion"]={
+ ["cs"]="konverzehlavicky",
+ ["de"]="headconversion",
+ ["en"]="headconversion",
+ ["fr"]="conversiontete",
+ ["it"]="conversionetesta",
+ ["nl"]="kopconversie",
+ ["pe"]="تبدیل‌سر",
+ ["ro"]="conversietitlu",
+ },
+ ["header"]={
+ ["cs"]="zahlavi",
+ ["de"]="kopfzeile",
+ ["en"]="header",
+ ["fr"]="entete",
+ ["it"]="intestazione",
+ ["nl"]="hoofd",
+ ["pe"]="سربرگ",
+ ["ro"]="antet",
+ },
+ ["headerdistance"]={
+ ["cs"]="vzdalenostzahlavi",
+ ["de"]="kopfzeilenabstand",
+ ["en"]="headerdistance",
+ ["fr"]="distanceentete",
+ ["it"]="distanzaintestazione",
+ ["nl"]="hoofdafstand",
+ ["pe"]="فاصله‌سربرگ",
+ ["ro"]="distantaantet",
+ },
+ ["headerstate"]={
+ ["cs"]="statuszahlavi",
+ ["de"]="kopfzeilenstatus",
+ ["en"]="headerstate",
+ ["fr"]="etatentete",
+ ["it"]="statointestazione",
+ ["nl"]="hoofdstatus",
+ ["pe"]="وضعیت‌سربرگ",
+ ["ro"]="stareantet",
+ },
+ ["headlabel"]={
+ ["cs"]="popisekhlavicky",
+ ["de"]="headlabel",
+ ["en"]="headlabel",
+ ["fr"]="etiquettetete",
+ ["it"]="etichettatesta",
+ ["nl"]="koplabel",
+ ["pe"]="برچسب‌سر",
+ ["ro"]="etichetatitlu",
+ },
+ ["headnumber"]={
+ ["cs"]="cislonadpisu",
+ ["de"]="kopfnummer",
+ ["en"]="headnumber",
+ ["fr"]="numerotete",
+ ["it"]="numerotesta",
+ ["nl"]="kopnummer",
+ ["pe"]="شماره‌سر",
+ ["ro"]="numartitlu",
+ },
+ ["headstyle"]={
+ ["cs"]="stylhlavicky",
+ ["de"]="kopfstil",
+ ["en"]="headstyle",
+ ["fr"]="styletete",
+ ["it"]="stiletesta",
+ ["nl"]="kopletter",
+ ["pe"]="سبک‌سر",
+ ["ro"]="stiltitlu",
+ },
+ ["height"]={
+ ["cs"]="vyska",
+ ["de"]="hoehe",
+ ["en"]="height",
+ ["fr"]="hauteur",
+ ["it"]="altezza",
+ ["nl"]="hoogte",
+ ["pe"]="ارتفاع",
+ ["ro"]="inaltime",
+ },
+ ["hfactor"]={
+ ["cs"]="vfaktor",
+ ["de"]="hfaktor",
+ ["en"]="hfactor",
+ ["fr"]="facteurhauteur",
+ ["it"]="hfactor",
+ ["nl"]="hfactor",
+ ["pe"]="عامل‌ارتفاع",
+ ["ro"]="hfactor",
+ },
+ ["hfil"]={
+ ["cs"]="hfil",
+ ["de"]="hfil",
+ ["en"]="hfil",
+ ["fr"]="hfil",
+ ["it"]="hfil",
+ ["nl"]="hfil",
+ ["pe"]="پرکردن‌ارتفاع",
+ ["ro"]="hfil",
+ },
+ ["hidenumber"]={
+ ["en"]="hidenumber",
+ },
+ ["hoffset"]={
+ ["cs"]="hoffset",
+ ["de"]="hoffset",
+ ["en"]="hoffset",
+ ["fr"]="decalagehauteur",
+ ["it"]="hoffset",
+ ["nl"]="hoffset",
+ ["pe"]="آفست‌ا",
+ ["ro"]="hoffset",
+ },
+ ["horoffset"]={
+ ["cs"]="horoffset",
+ ["de"]="rumpfabstand",
+ ["en"]="horoffset",
+ ["fr"]="horoffset",
+ ["it"]="horoffset",
+ ["nl"]="rugoffset",
+ ["pe"]="آفست‌افق",
+ ["ro"]="offsetoriz",
+ },
+ ["hyphen"]={
+ ["cs"]="hyphen",
+ ["de"]="hyphen",
+ ["en"]="hyphen",
+ ["fr"]="hyphen",
+ ["it"]="hyphen",
+ ["nl"]="hyphen",
+ ["pe"]="شکستن",
+ ["ro"]="hyphen",
+ },
+ ["hyphens"]={
+ ["en"]="hyphens",
+ },
+ ["icommand"]={
+ ["cs"]="iprikaz",
+ ["de"]="ibefehl",
+ ["en"]="icommand",
+ ["fr"]="icommande",
+ ["it"]="icomando",
+ ["nl"]="icommando",
+ ["pe"]="icommand",
+ ["ro"]="comandai",
+ },
+ ["ignore"]={
+ ["en"]="ignore",
+ },
+ ["in"]={
+ ["cs"]="v",
+ ["de"]="in",
+ ["en"]="in",
+ ["fr"]="in",
+ ["it"]="in",
+ ["nl"]="in",
+ ["pe"]="درون",
+ ["ro"]="in",
+ },
+ ["inbetween"]={
+ ["cs"]="mezi",
+ ["de"]="zwischen",
+ ["en"]="inbetween",
+ ["fr"]="entre",
+ ["it"]="tra",
+ ["nl"]="tussen",
+ ["pe"]="دربین",
+ ["ro"]="intre",
+ },
+ ["increment"]={
+ ["cs"]="zvysit",
+ ["de"]="erhoehen",
+ ["en"]="increment",
+ ["fr"]="incremente",
+ ["it"]="incremento",
+ ["nl"]="verhoog",
+ ["pe"]="افزایش",
+ ["ro"]="increment",
+ },
+ ["incrementnumber"]={
+ ["cs"]="zvysujicicislo",
+ ["de"]="nummererhoehen",
+ ["en"]="incrementnumber",
+ ["fr"]="incrementenumero",
+ ["it"]="incrementanumero",
+ ["nl"]="verhoognummer",
+ ["pe"]="شماره‌افزایش",
+ ["ro"]="numarincrement",
+ },
+ ["indenting"]={
+ ["cs"]="odsazovani",
+ ["de"]="einziehen",
+ ["en"]="indenting",
+ ["fr"]="composeenalinea",
+ ["it"]="rientro",
+ ["nl"]="inspringen",
+ ["pe"]="تورفتگی",
+ ["ro"]="aliniat",
+ },
+ ["indentnext"]={
+ ["cs"]="odsadpristi",
+ ["de"]="ziehefolgendeein",
+ ["en"]="indentnext",
+ ["fr"]="indentesuivant",
+ ["it"]="rientrasuccessivo",
+ ["nl"]="springvolgendein",
+ ["pe"]="متن‌تورفته",
+ ["ro"]="aliniaturmator",
+ },
+ ["index"]={
+ ["en"]="index",
+ },
+ ["indicator"]={
+ ["cs"]="indikator",
+ ["de"]="indikator",
+ ["en"]="indicator",
+ ["fr"]="indicateur",
+ ["it"]="indicatore",
+ ["nl"]="aanduiding",
+ ["pe"]="اندیکاتور",
+ ["ro"]="indicator",
+ },
+ ["initialsep"]={
+ ["en"]="initialsep",
+ },
+ ["inner"]={
+ ["cs"]="vnitrni",
+ ["de"]="innen",
+ ["en"]="inner",
+ ["fr"]="interieur",
+ ["it"]="interno",
+ ["nl"]="binnen",
+ ["pe"]="داخلی",
+ ["ro"]="intern",
+ },
+ ["innermargin"]={
+ ["cs"]="innermargin",
+ ["de"]="innermargin",
+ ["en"]="innermargin",
+ ["fr"]="margeinterieure",
+ ["it"]="margineinterno",
+ ["nl"]="binnenmarge",
+ ["pe"]="حاشیه‌داخلی",
+ ["ro"]="innermargin",
+ },
+ ["inputfile"]={
+ ["cs"]="inputfile",
+ ["de"]="inputfile",
+ ["en"]="inputfile",
+ ["fr"]="fichierentree",
+ ["it"]="inputfile",
+ ["nl"]="inputfile",
+ ["pe"]="پرونده‌ورودی",
+ ["ro"]="inputfile",
+ },
+ ["insidesection"]={
+ ["en"]="insidesection",
+ ["nl"]="binnensectie",
+ },
+ ["instance"]={
+ ["en"]="instance",
+ },
+ ["intent"]={
+ ["en"]="intent",
+ },
+ ["interaction"]={
+ ["cs"]="interakce",
+ ["de"]="interaktion",
+ ["en"]="interaction",
+ ["fr"]="interaction",
+ ["it"]="interazione",
+ ["nl"]="interactie",
+ ["pe"]="پانل",
+ ["ro"]="interactiune",
+ },
+ ["interlinespace"]={
+ ["cs"]="meziradkovamezera",
+ ["de"]="zeilenabstande",
+ ["en"]="interlinespace",
+ ["fr"]="espaceinterligne",
+ ["it"]="interlinea",
+ ["nl"]="interlinie",
+ ["pe"]="فضای‌بین‌خط",
+ ["ro"]="spatiereinterliniara",
+ },
+ ["internalgrid"]={
+ ["en"]="internalgrid",
+ ["nl"]="interngrid",
+ },
+ ["italicfeatures"]={
+ ["en"]="italicfeatures",
+ },
+ ["italicfont"]={
+ ["en"]="italicfont",
+ },
+ ["itemalign"]={
+ ["cs"]="itemalign",
+ ["de"]="itemalign",
+ ["en"]="itemalign",
+ ["fr"]="itemalign",
+ ["it"]="itemalign",
+ ["nl"]="itemuitlijnen",
+ ["pe"]="تنظیم‌آیتم",
+ ["ro"]="itemalign",
+ },
+ ["items"]={
+ ["cs"]="polozky",
+ ["de"]="posten",
+ ["en"]="items",
+ ["fr"]="elements",
+ ["it"]="elementi",
+ ["nl"]="items",
+ ["pe"]="آیتمها",
+ ["ro"]="elemente",
+ },
+ ["joiners"]={
+ ["en"]="joiners",
+ },
+ ["journalconversion"]={
+ ["en"]="journalconversion",
+ },
+ ["juniorsep"]={
+ ["en"]="juniorsep",
+ },
+ ["keeptogether"]={
+ ["en"]="keeptogether",
+ },
+ ["ken"]={
+ ["cs"]="ken",
+ ["de"]="ken",
+ ["en"]="ken",
+ ["fr"]="ken",
+ ["it"]="ken",
+ ["nl"]="ken",
+ ["pe"]="ken",
+ ["ro"]="ken",
+ },
+ ["keyexpansion"]={
+ ["cs"]="keyexpansion",
+ ["de"]="keyexpansion",
+ ["en"]="keyexpansion",
+ ["fr"]="keyexpansion",
+ ["it"]="keyexpansion",
+ ["nl"]="sleutelexpansie",
+ ["pe"]="گسترش‌کلید",
+ ["ro"]="keyexpansion",
+ },
+ ["keys"]={
+ ["en"]="keys",
+ ["nl"]="sleutels",
+ },
+ ["keyword"]={
+ ["cs"]="keyword",
+ ["de"]="keyword",
+ ["en"]="keyword",
+ ["fr"]="motcle",
+ ["it"]="parolachiave",
+ ["nl"]="trefwoord",
+ ["pe"]="کلید‌واژه",
+ ["ro"]="keyword",
+ },
+ ["label"]={
+ ["cs"]="popisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["labeloffset"]={
+ ["en"]="labeloffset",
+ },
+ ["language"]={
+ ["en"]="language",
+ },
+ ["last"]={
+ ["en"]="last",
+ },
+ ["lastnamesep"]={
+ ["en"]="lastnamesep",
+ },
+ ["lastpage"]={
+ ["cs"]="poslednistrana",
+ ["de"]="letzteseite",
+ ["en"]="lastpage",
+ ["fr"]="dernierepage",
+ ["it"]="ultimapagina",
+ ["nl"]="laatstepagina",
+ ["pe"]="صفحه‌آخر",
+ ["ro"]="ultimapagina",
+ },
+ ["lastpagesep"]={
+ ["en"]="lastpagesep",
+ },
+ ["lastpubsep"]={
+ ["en"]="lastpubsep",
+ },
+ ["layout"]={
+ ["en"]="layout",
+ ["nl"]="layout",
+ },
+ ["left"]={
+ ["cs"]="vlevo",
+ ["de"]="links",
+ ["en"]="left",
+ ["fr"]="gauche",
+ ["it"]="sinistra",
+ ["nl"]="links",
+ ["pe"]="چپ",
+ ["ro"]="stanga",
+ },
+ ["leftcolor"]={
+ ["cs"]="barvavlevo",
+ ["de"]="linkerfarbe",
+ ["en"]="leftcolor",
+ ["fr"]="couleurgauche",
+ ["it"]="coloresinistra",
+ ["nl"]="linkerkleur",
+ ["pe"]="رنگ‌چپ",
+ ["ro"]="culoarestanga",
+ },
+ ["leftcompoundhyphen"]={
+ ["cs"]="leftcompoundhyphen",
+ ["de"]="leftcompoundhyphen",
+ ["en"]="leftcompoundhyphen",
+ ["fr"]="leftcompoundhyphen",
+ ["it"]="leftcompoundhyphen",
+ ["nl"]="linkerkoppelteken",
+ ["pe"]="leftcompoundhyphen",
+ ["ro"]="leftcompoundhyphen",
+ },
+ ["leftedge"]={
+ ["cs"]="levahrana",
+ ["de"]="linkekante",
+ ["en"]="leftedge",
+ ["fr"]="bordgauche",
+ ["it"]="bordosinistro",
+ ["nl"]="linkerrand",
+ ["pe"]="لبه‌چپ",
+ ["ro"]="bordurastanga",
+ },
+ ["leftedgedistance"]={
+ ["cs"]="vzdalenostlevehrany",
+ ["de"]="linkerkantenabstand",
+ ["en"]="leftedgedistance",
+ ["fr"]="distancebordgauche",
+ ["it"]="distanzabordosinistro",
+ ["nl"]="linkerrandafstand",
+ ["pe"]="فاصله‌لبه‌چپ",
+ ["ro"]="distantabordurastanga",
+ },
+ ["leftframe"]={
+ ["cs"]="ramecekvlevo",
+ ["de"]="linkerrahmen",
+ ["en"]="leftframe",
+ ["fr"]="cadregauche",
+ ["it"]="cornicesinistra",
+ ["nl"]="linkerkader",
+ ["pe"]="قالب‌چپ",
+ ["ro"]="framestanga",
+ },
+ ["lefthyphen"]={
+ ["cs"]="lefthyphen",
+ ["de"]="lefthyphen",
+ ["en"]="lefthyphen",
+ ["fr"]="lefthyphen",
+ ["it"]="lefthyphen",
+ ["nl"]="lefthyphen",
+ ["pe"]="شکست‌چپ",
+ ["ro"]="lefthyphen",
+ },
+ ["leftmargin"]={
+ ["cs"]="levyokraj",
+ ["de"]="linkerrand",
+ ["en"]="leftmargin",
+ ["fr"]="margegauche",
+ ["it"]="marginesinistro",
+ ["nl"]="linkermarge",
+ ["pe"]="حاشیه‌چپ",
+ ["ro"]="marginestanga",
+ },
+ ["leftmargindistance"]={
+ ["cs"]="vzdalenostlevehookraje",
+ ["de"]="linkerrandabstand",
+ ["en"]="leftmargindistance",
+ ["fr"]="distancemargegauche",
+ ["it"]="distanzamarginesinistro",
+ ["nl"]="linkermargeafstand",
+ ["pe"]="فاصله‌حاشیه‌چپ",
+ ["ro"]="distantamarginestanga",
+ },
+ ["leftoffset"]={
+ ["cs"]="levyoffset",
+ ["de"]="linkeroffset",
+ ["en"]="leftoffset",
+ ["fr"]="decalagegauche",
+ ["it"]="offsetsinistro",
+ ["nl"]="linkeroffset",
+ ["pe"]="آفست‌چپ",
+ ["ro"]="offsetstanga",
+ },
+ ["leftquotation"]={
+ ["cs"]="citacevlevo",
+ ["de"]="linkerzitat",
+ ["en"]="leftquotation",
+ ["fr"]="citationgauche",
+ ["it"]="citazionesinistra",
+ ["nl"]="linkercitaat",
+ ["pe"]="نقل‌قول‌چپ",
+ ["ro"]="citatstanga",
+ },
+ ["leftquote"]={
+ ["cs"]="citovatvlevo",
+ ["de"]="linkerzitieren",
+ ["en"]="leftquote",
+ ["fr"]="citergauche",
+ ["it"]="menzionesinistra",
+ ["nl"]="linkerciteer",
+ ["pe"]="نقل‌چپ",
+ ["ro"]="minicitatstanga",
+ },
+ ["leftsentence"]={
+ ["cs"]="vetavlevo",
+ ["de"]="linkersatz",
+ ["en"]="leftsentence",
+ ["fr"]="phrasegauche",
+ ["it"]="frasesinistra",
+ ["nl"]="linkerzin",
+ ["pe"]="جمله‌چپ",
+ ["ro"]="propozitiestanga",
+ },
+ ["leftspeech"]={
+ ["cs"]="leftspeech",
+ ["de"]="leftspeech",
+ ["en"]="leftspeech",
+ ["fr"]="leftspeech",
+ ["it"]="leftspeech",
+ ["nl"]="linkeruitspraak",
+ ["pe"]="سخنرانی‌چپ",
+ ["ro"]="leftspeech",
+ },
+ ["leftstyle"]={
+ ["cs"]="stylvlevo",
+ ["de"]="linkerstil",
+ ["en"]="leftstyle",
+ ["fr"]="leftstyle",
+ ["it"]="stilesinistra",
+ ["nl"]="linkerletter",
+ ["pe"]="سبک‌چپ",
+ ["ro"]="stilstanga",
+ },
+ ["leftsubsentence"]={
+ ["cs"]="podvetavlevo",
+ ["de"]="linkersubsatz",
+ ["en"]="leftsubsentence",
+ ["fr"]="sousphrasegauche",
+ ["it"]="sottofrasesinistra",
+ ["nl"]="linkersubzin",
+ ["pe"]="زیرجمله‌چپ",
+ ["ro"]="subpropozitiestanga",
+ },
+ ["lefttext"]={
+ ["cs"]="textvlevo",
+ ["de"]="linkertext",
+ ["en"]="lefttext",
+ ["fr"]="textegauche",
+ ["it"]="testosinistro",
+ ["nl"]="linkertekst",
+ ["pe"]="متن‌چپ",
+ ["ro"]="textstanga",
+ },
+ ["leftwidth"]={
+ ["cs"]="sirkavlevo",
+ ["de"]="linkerbreite",
+ ["en"]="leftwidth",
+ ["fr"]="largeurgauche",
+ ["it"]="ampiezzasinistra",
+ ["nl"]="linkerbreedte",
+ ["pe"]="عرض‌خط",
+ ["ro"]="latimestanga",
+ },
+ ["leftwords"]={
+ ["en"]="leftwords",
+ },
+ ["less"]={
+ ["en"]="less",
+ ["nl"]="minder",
+ },
+ ["level"]={
+ ["cs"]="uroven",
+ ["de"]="niveau",
+ ["en"]="level",
+ ["fr"]="niveau",
+ ["it"]="livello",
+ ["nl"]="niveau",
+ ["pe"]="مرحله",
+ ["ro"]="nivel",
+ },
+ ["levels"]={
+ ["cs"]="urovne",
+ ["de"]="niveaus",
+ ["en"]="levels",
+ ["fr"]="niveaux",
+ ["it"]="livelli",
+ ["nl"]="niveaus",
+ ["pe"]="مرحله‌ها",
+ ["ro"]="nivele",
+ },
+ ["limittext"]={
+ ["cs"]="limittext",
+ ["de"]="limittext",
+ ["en"]="limittext",
+ ["fr"]="limittext",
+ ["it"]="limittext",
+ ["nl"]="limiettekst",
+ ["pe"]="مرزمتن",
+ ["ro"]="limittext",
+ },
+ ["line"]={
+ ["cs"]="radek",
+ ["de"]="zeile",
+ ["en"]="line",
+ ["fr"]="ligne",
+ ["it"]="riga",
+ ["nl"]="regel",
+ ["pe"]="خط",
+ ["ro"]="linie",
+ },
+ ["linecorrection"]={
+ ["cs"]="korekceradku",
+ ["de"]="zeilekorrektur",
+ ["en"]="linecorrection",
+ ["fr"]="correctionligne",
+ ["it"]="correzioneriga",
+ ["nl"]="regelcorrectie",
+ ["pe"]="تصحیح‌خط",
+ ["ro"]="corectielinie",
+ },
+ ["lines"]={
+ ["cs"]="radky",
+ ["de"]="zeilen",
+ ["en"]="lines",
+ ["fr"]="lignes",
+ ["it"]="righe",
+ ["nl"]="regels",
+ ["pe"]="خطها",
+ ["ro"]="linii",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="liste",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["listtext"]={
+ ["cs"]="listtext",
+ ["de"]="listtext",
+ ["en"]="listtext",
+ ["fr"]="texteliste",
+ ["it"]="listtext",
+ ["nl"]="lijsttekst",
+ ["pe"]="متن‌لیست",
+ ["ro"]="listtext",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokaal",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["location"]={
+ ["cs"]="misto",
+ ["de"]="platz",
+ ["en"]="location",
+ ["fr"]="emplacement",
+ ["it"]="luogo",
+ ["nl"]="plaats",
+ ["pe"]="مکان",
+ ["ro"]="locatie",
+ },
+ ["loffset"]={
+ ["en"]="loffset",
+ },
+ ["logo"]={
+ ["cs"]="logo",
+ ["de"]="logo",
+ ["en"]="logo",
+ ["fr"]="logo",
+ ["it"]="logo",
+ ["nl"]="logo",
+ ["pe"]="آرم",
+ ["ro"]="logo",
+ },
+ ["logos"]={
+ ["cs"]="loga",
+ ["de"]="logos",
+ ["en"]="logos",
+ ["fr"]="logos",
+ ["it"]="loghi",
+ ["nl"]="logos",
+ ["pe"]="آرمها",
+ ["ro"]="logos",
+ },
+ ["marcolor"]={
+ ["cs"]="barvaznacky",
+ ["de"]="beschrfarbe",
+ ["en"]="marcolor",
+ ["fr"]="couleurmarquage",
+ ["it"]="coloremarcatura",
+ ["nl"]="markleur",
+ ["pe"]="رنگ‌حاش",
+ ["ro"]="culoaremarcaj",
+ },
+ ["margin"]={
+ ["cs"]="marginalie",
+ ["de"]="marginalie",
+ ["en"]="margin",
+ ["fr"]="marge",
+ ["it"]="margine",
+ ["nl"]="marge",
+ ["pe"]="حاشیه",
+ ["ro"]="margine",
+ },
+ ["margindistance"]={
+ ["cs"]="vzdalenostokraje",
+ ["de"]="marginalabstand",
+ ["en"]="margindistance",
+ ["fr"]="distancemarge",
+ ["it"]="distanzamargine",
+ ["nl"]="margeafstand",
+ ["pe"]="فاصله‌حاشیه",
+ ["ro"]="distantamargine",
+ },
+ ["marginedge"]={
+ ["cs"]="textovahrana",
+ ["de"]="marginalkante",
+ ["en"]="marginedge",
+ ["fr"]="bordmarge",
+ ["it"]="bordomargine",
+ ["nl"]="kantlijn",
+ ["pe"]="لبه‌حاشیه",
+ ["ro"]="coltbordura",
+ },
+ ["marginedgetext"]={
+ ["cs"]="textmarginalnihookraje",
+ ["de"]="marginalkantetext",
+ ["en"]="marginedgetext",
+ ["fr"]="textebordmarge",
+ ["it"]="testobordomargine",
+ ["nl"]="kantlijntekst",
+ ["pe"]="متن‌لبه‌حاشیه",
+ ["ro"]="textcoltbordura",
+ },
+ ["margintext"]={
+ ["cs"]="textmarginalie",
+ ["de"]="marginaltext",
+ ["en"]="margintext",
+ ["fr"]="textemarge",
+ ["it"]="testomargine",
+ ["nl"]="margetekst",
+ ["pe"]="متن‌حاشیه",
+ ["ro"]="textmargine",
+ },
+ ["mark"]={
+ ["en"]="mark",
+ ["nl"]="kernmerk",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markering",
+ ["pe"]="نشانه‌گذاری",
+ ["ro"]="marcaje",
+ },
+ ["marstyle"]={
+ ["cs"]="stylsnacky",
+ ["de"]="beschrstil",
+ ["en"]="marstyle",
+ ["fr"]="stylemarquage",
+ ["it"]="stilemarcatura",
+ ["nl"]="marletter",
+ ["pe"]="سبک‌حاش",
+ ["ro"]="stilmarcaj",
+ },
+ ["mask"]={
+ ["en"]="mask",
+ ["nl"]="masker",
+ },
+ ["mathclass"]={
+ ["en"]="mathclass",
+ },
+ ["mathlimits"]={
+ ["en"]="mathlimits",
+ },
+ ["mathstyle"]={
+ ["en"]="mathstyle",
+ },
+ ["max"]={
+ ["cs"]="max",
+ ["de"]="max",
+ ["en"]="max",
+ ["fr"]="max",
+ ["it"]="max",
+ ["nl"]="max",
+ ["pe"]="بیشترین",
+ ["ro"]="max",
+ },
+ ["maxdepth"]={
+ ["en"]="maxdepth",
+ },
+ ["maxheight"]={
+ ["cs"]="maxvyska",
+ ["de"]="maxhoehe",
+ ["en"]="maxheight",
+ ["fr"]="hauteurmax",
+ ["it"]="altezzamax",
+ ["nl"]="maxhoogte",
+ ["pe"]="بیشترین‌ارتفاع",
+ ["ro"]="inaltimemaxima",
+ },
+ ["maxwidth"]={
+ ["cs"]="maxsirka",
+ ["de"]="maxbreite",
+ ["en"]="maxwidth",
+ ["fr"]="largeurmax",
+ ["it"]="ampiezzamax",
+ ["nl"]="maxbreedte",
+ ["pe"]="بیشترین‌عرض",
+ ["ro"]="latimemaxima",
+ },
+ ["maybeyear"]={
+ ["en"]="maybeyear",
+ },
+ ["menu"]={
+ ["cs"]="menu",
+ ["de"]="menue",
+ ["en"]="menu",
+ ["fr"]="menu",
+ ["it"]="menu",
+ ["nl"]="menu",
+ ["pe"]="منو",
+ ["ro"]="meniu",
+ },
+ ["method"]={
+ ["cs"]="metoda",
+ ["de"]="methode",
+ ["en"]="method",
+ ["fr"]="methode",
+ ["it"]="metodo",
+ ["nl"]="methode",
+ ["pe"]="روش",
+ ["ro"]="metoda",
+ },
+ ["middle"]={
+ ["cs"]="stredni",
+ ["de"]="mittig",
+ ["en"]="middle",
+ ["fr"]="milieu",
+ ["it"]="centro",
+ ["nl"]="midden",
+ ["pe"]="میان",
+ ["ro"]="mijloc",
+ },
+ ["middlecommand"]={
+ ["en"]="middlecommand",
+ ["nl"]="middencommando",
+ },
+ ["middlespeech"]={
+ ["cs"]="middlespeech",
+ ["de"]="middlespeech",
+ ["en"]="middlespeech",
+ ["fr"]="middlespeech",
+ ["it"]="middlespeech",
+ ["nl"]="middenuitspraak",
+ ["pe"]="سخنرانی‌میانی",
+ ["ro"]="middlespeech",
+ },
+ ["middletext"]={
+ ["cs"]="strednitext",
+ ["de"]="mittigertext",
+ ["en"]="middletext",
+ ["fr"]="textecentre",
+ ["it"]="testocentro",
+ ["nl"]="middentekst",
+ ["pe"]="متن‌میانی",
+ ["ro"]="textmijloc",
+ },
+ ["midsentence"]={
+ ["cs"]="midsentence",
+ ["de"]="midsentence",
+ ["en"]="midsentence",
+ ["fr"]="midsentence",
+ ["it"]="midsentence",
+ ["nl"]="middenzin",
+ ["pe"]="جمله‌میانی",
+ ["ro"]="midsentence",
+ },
+ ["min"]={
+ ["cs"]="min",
+ ["de"]="min",
+ ["en"]="min",
+ ["fr"]="min",
+ ["it"]="min",
+ ["nl"]="min",
+ ["pe"]="کمترین",
+ ["ro"]="min",
+ },
+ ["mindepth"]={
+ ["cs"]="mindepth",
+ ["de"]="mindepth",
+ ["en"]="mindepth",
+ ["fr"]="profondeurmin",
+ ["it"]="mindepth",
+ ["nl"]="mindiepte",
+ ["pe"]="کمترین‌عمق",
+ ["ro"]="mindepth",
+ },
+ ["minheight"]={
+ ["cs"]="minvyska",
+ ["de"]="minhoehe",
+ ["en"]="minheight",
+ ["fr"]="hauteurmin",
+ ["it"]="altezzamin",
+ ["nl"]="minhoogte",
+ ["pe"]="کمترین‌ارتفاع",
+ ["ro"]="inaltimeminima",
+ },
+ ["minwidth"]={
+ ["cs"]="minsirka",
+ ["de"]="minbreite",
+ ["en"]="minwidth",
+ ["fr"]="largeurmin",
+ ["it"]="ampiezzamin",
+ ["nl"]="minbreedte",
+ ["pe"]="کمترین‌عرض",
+ ["ro"]="latimeminima",
+ },
+ ["moffset"]={
+ ["cs"]="moffset",
+ ["de"]="moffset",
+ ["en"]="moffset",
+ ["fr"]="moffset",
+ ["it"]="moffset",
+ ["nl"]="moffset",
+ ["pe"]="moffset",
+ ["ro"]="moffset",
+ },
+ ["monthconversion"]={
+ ["en"]="monthconversion",
+ ["nl"]="maandconversie",
+ },
+ ["more"]={
+ ["en"]="more",
+ ["nl"]="meer",
+ },
+ ["mpdepth"]={
+ ["en"]="mpdepth",
+ ["nl"]="mpdiepte",
+ },
+ ["mpheight"]={
+ ["en"]="mpheight",
+ ["nl"]="mphoogte",
+ },
+ ["mpoffset"]={
+ ["en"]="mpoffset",
+ ["nl"]="mpoffset",
+ },
+ ["mpwidth"]={
+ ["en"]="mpwidth",
+ ["nl"]="mpbreedte",
+ },
+ ["n"]={
+ ["cs"]="n",
+ ["de"]="n",
+ ["en"]="n",
+ ["fr"]="n",
+ ["it"]="n",
+ ["nl"]="n",
+ ["pe"]="n",
+ ["ro"]="n",
+ },
+ ["name"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nom",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نام",
+ ["ro"]="nume",
+ },
+ ["namesep"]={
+ ["en"]="namesep",
+ },
+ ["nbottom"]={
+ ["cs"]="nspodek",
+ ["de"]="nunten",
+ ["en"]="nbottom",
+ ["fr"]="ninf",
+ ["it"]="nfondo",
+ ["nl"]="nonder",
+ ["pe"]="nbottom",
+ ["ro"]="njos",
+ },
+ ["nc"]={
+ ["cs"]="nc",
+ ["de"]="nc",
+ ["en"]="nc",
+ ["fr"]="nc",
+ ["it"]="nc",
+ ["nl"]="nc",
+ ["pe"]="nc",
+ ["ro"]="nc",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="suivant",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["nextleft"]={
+ ["en"]="nextleft",
+ },
+ ["nextleftquotation"]={
+ ["en"]="nextleftquotation",
+ },
+ ["nextright"]={
+ ["en"]="nextright",
+ },
+ ["nextrightquotation"]={
+ ["en"]="nextrightquotation",
+ },
+ ["nl"]={
+ ["cs"]="nl",
+ ["de"]="nl",
+ ["en"]="nl",
+ ["fr"]="nl",
+ ["it"]="nl",
+ ["nl"]="nl",
+ ["pe"]="nl",
+ ["ro"]="nl",
+ },
+ ["nleft"]={
+ ["cs"]="nvlevo",
+ ["de"]="nlinks",
+ ["en"]="nleft",
+ ["fr"]="ngauche",
+ ["it"]="nsinistra",
+ ["nl"]="nlinks",
+ ["pe"]="nleft",
+ ["ro"]="nstanga",
+ },
+ ["nlines"]={
+ ["cs"]="nradky",
+ ["de"]="zzeile",
+ ["en"]="nlines",
+ ["fr"]="nlignes",
+ ["it"]="nrighe",
+ ["nl"]="nregels",
+ ["pe"]="nlines",
+ ["ro"]="nlinii",
+ },
+ ["norm"]={
+ ["cs"]="norm",
+ ["de"]="norm",
+ ["en"]="norm",
+ ["fr"]="norme",
+ ["it"]="norma",
+ ["nl"]="norm",
+ ["pe"]="norm",
+ ["ro"]="norm",
+ },
+ ["note"]={
+ ["en"]="note",
+ },
+ ["nr"]={
+ ["cs"]="nr",
+ ["de"]="nr",
+ ["en"]="nr",
+ ["fr"]="nr",
+ ["it"]="nr",
+ ["nl"]="nr",
+ ["pe"]="nr",
+ ["ro"]="nr",
+ },
+ ["nright"]={
+ ["cs"]="nvpravo",
+ ["de"]="nrechts",
+ ["en"]="nright",
+ ["fr"]="ndroite",
+ ["it"]="ndestra",
+ ["nl"]="nrechts",
+ ["pe"]="nright",
+ ["ro"]="ndreapta",
+ },
+ ["ntop"]={
+ ["cs"]="nvrsek",
+ ["de"]="noben",
+ ["en"]="ntop",
+ ["fr"]="nsup",
+ ["it"]="ncima",
+ ["nl"]="nboven",
+ ["pe"]="ntop",
+ ["ro"]="nsus",
+ },
+ ["number"]={
+ ["cs"]="cislo",
+ ["de"]="nummer",
+ ["en"]="number",
+ ["fr"]="numero",
+ ["it"]="numero",
+ ["nl"]="nummer",
+ ["pe"]="شماره",
+ ["ro"]="numar",
+ },
+ ["numberalign"]={
+ ["en"]="numberalign",
+ ["nl"]="nummeruitlijnen",
+ },
+ ["numbercolor"]={
+ ["cs"]="barvacisla",
+ ["de"]="nummernfarbe",
+ ["en"]="numbercolor",
+ ["fr"]="couleurnumero",
+ ["it"]="colorenumero",
+ ["nl"]="nummerkleur",
+ ["pe"]="رنگ‌شماره",
+ ["ro"]="culoarenumar",
+ },
+ ["numbercommand"]={
+ ["cs"]="ciselnyprikaz",
+ ["de"]="nummerbefehl",
+ ["en"]="numbercommand",
+ ["fr"]="commandenumero",
+ ["it"]="comandonumero",
+ ["nl"]="nummercommando",
+ ["pe"]="فرمان‌شماره",
+ ["ro"]="comandanumar",
+ },
+ ["numberconversion"]={
+ ["en"]="numberconversion",
+ },
+ ["numberconversionset"]={
+ ["en"]="numberconversionset",
+ },
+ ["numberdistance"]={
+ ["cs"]="numberdistance",
+ ["de"]="numberdistance",
+ ["en"]="numberdistance",
+ ["fr"]="numberdistance",
+ ["it"]="numberdistance",
+ ["nl"]="nummerafstand",
+ ["pe"]="فاصله‌شماره",
+ ["ro"]="numberdistance",
+ },
+ ["numbering"]={
+ ["cs"]="cislovani",
+ ["de"]="nummerierung",
+ ["en"]="numbering",
+ ["fr"]="numerotation",
+ ["it"]="numerazione",
+ ["nl"]="nummeren",
+ ["pe"]="شماره‌گذاری",
+ ["ro"]="numerotare",
+ },
+ ["numberorder"]={
+ ["en"]="numberorder",
+ },
+ ["numberprefix"]={
+ ["en"]="numberprefix",
+ },
+ ["numbersegments"]={
+ ["en"]="numbersegments",
+ },
+ ["numberseparator"]={
+ ["cs"]="oddelovaccisla",
+ ["de"]="nummernseperator",
+ ["en"]="numberseparator",
+ ["fr"]="separateurnumbero",
+ ["it"]="separatorenumero",
+ ["nl"]="nummerscheider",
+ ["pe"]="جداکننده‌شماره",
+ ["ro"]="separatornumar",
+ },
+ ["numberseparatorset"]={
+ ["en"]="numberseparatorset",
+ },
+ ["numberset"]={
+ ["en"]="numberset",
+ },
+ ["numberstarter"]={
+ ["en"]="numberstarter",
+ },
+ ["numberstopper"]={
+ ["en"]="numberstopper",
+ },
+ ["numberstyle"]={
+ ["cs"]="stylcisla",
+ ["de"]="nummernstil",
+ ["en"]="numberstyle",
+ ["fr"]="stylenumero",
+ ["it"]="stilenumero",
+ ["nl"]="nummerletter",
+ ["pe"]="سبک‌شماره",
+ ["ro"]="stilnumar",
+ },
+ ["numberwidth"]={
+ ["cs"]="numberwidth",
+ ["de"]="numberwidth",
+ ["en"]="numberwidth",
+ ["fr"]="numberwidth",
+ ["it"]="numberwidth",
+ ["nl"]="nummerbreedte",
+ ["pe"]="عرض‌شماره",
+ ["ro"]="numberwidth",
+ },
+ ["nx"]={
+ ["cs"]="nx",
+ ["de"]="nx",
+ ["en"]="nx",
+ ["fr"]="nx",
+ ["it"]="nx",
+ ["nl"]="nx",
+ ["pe"]="nx",
+ ["ro"]="nx",
+ },
+ ["ny"]={
+ ["cs"]="ny",
+ ["de"]="ny",
+ ["en"]="ny",
+ ["fr"]="ny",
+ ["it"]="ny",
+ ["nl"]="ny",
+ ["pe"]="ny",
+ ["ro"]="ny",
+ },
+ ["object"]={
+ ["cs"]="objekt",
+ ["de"]="objekt",
+ ["en"]="object",
+ ["fr"]="objet",
+ ["it"]="oggetto",
+ ["nl"]="object",
+ ["pe"]="شیئ",
+ ["ro"]="obiect",
+ },
+ ["obstruction"]={
+ ["cs"]="prekazka",
+ ["de"]="gesperrt",
+ ["en"]="obstruction",
+ ["fr"]="obstruction",
+ ["it"]="ostruzione",
+ ["nl"]="blokkade",
+ ["pe"]="انسداد",
+ ["ro"]="obstructie",
+ },
+ ["oddmargin"]={
+ ["cs"]="lichyokraj",
+ ["de"]="ungeraderand",
+ ["en"]="oddmargin",
+ ["fr"]="margepaire",
+ ["it"]="marginedispari",
+ ["nl"]="onevenmarge",
+ ["pe"]="حاشیه‌فرد",
+ ["ro"]="margineimpara",
+ },
+ ["offset"]={
+ ["cs"]="offset",
+ ["de"]="offset",
+ ["en"]="offset",
+ ["fr"]="offset",
+ ["it"]="offset",
+ ["nl"]="offset",
+ ["pe"]="آفست",
+ ["ro"]="offset",
+ },
+ ["openaction"]={
+ ["cs"]="otevriakci",
+ ["de"]="oeffenaktion",
+ ["en"]="openaction",
+ ["fr"]="actionouverture",
+ ["it"]="azioneapri",
+ ["nl"]="openactie",
+ ["pe"]="عمل‌باز",
+ ["ro"]="actiunedeschidere",
+ },
+ ["openpage"]={
+ ["en"]="openpage",
+ ["nl"]="openpagina",
+ },
+ ["openpageaction"]={
+ ["cs"]="akceotevrenistranky",
+ ["de"]="openpageaction",
+ ["en"]="openpageaction",
+ ["fr"]="actionouverturepage",
+ ["it"]="azioneapripagina",
+ ["nl"]="openpaginaactie",
+ ["pe"]="عمل‌صفحه‌باز",
+ ["ro"]="actiunedeschiderepagina",
+ },
+ ["openup"]={
+ ["en"]="openup",
+ },
+ ["opticalsize"]={
+ ["en"]="opticalsize",
+ },
+ ["option"]={
+ ["cs"]="volba",
+ ["de"]="option",
+ ["en"]="option",
+ ["fr"]="option",
+ ["it"]="opzione",
+ ["nl"]="optie",
+ ["pe"]="گزینه",
+ ["ro"]="optiune",
+ },
+ ["order"]={
+ ["en"]="order",
+ ["nl"]="volgorde",
+ },
+ ["orientation"]={
+ ["cs"]="orientation",
+ ["de"]="orientation",
+ ["en"]="orientation",
+ ["fr"]="orientation",
+ ["it"]="orientation",
+ ["nl"]="orientatie",
+ ["pe"]="جهت‌دهی",
+ ["ro"]="orientation",
+ },
+ ["otherstext"]={
+ ["en"]="otherstext",
+ },
+ ["outermargin"]={
+ ["cs"]="outermargin",
+ ["de"]="outermargin",
+ ["en"]="outermargin",
+ ["fr"]="margeexterieure",
+ ["it"]="margineesterno",
+ ["nl"]="buitenmarge",
+ ["pe"]="حاشیه‌خارجی",
+ ["ro"]="outermargin",
+ },
+ ["overprint"]={
+ ["cs"]="overprint",
+ ["de"]="overprint",
+ ["en"]="overprint",
+ ["fr"]="overprint",
+ ["it"]="overprint",
+ ["nl"]="overprint",
+ ["pe"]="overprint",
+ ["ro"]="overprint",
+ },
+ ["ownnumber"]={
+ ["cs"]="vlastnicislo",
+ ["de"]="eigenenummer",
+ ["en"]="ownnumber",
+ ["fr"]="numeroproprio",
+ ["it"]="numeroproprio",
+ ["nl"]="eigennummer",
+ ["pe"]="شماره‌خود",
+ ["ro"]="numarpropriu",
+ },
+ ["page"]={
+ ["cs"]="stranka",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pageboundaries"]={
+ ["cs"]="hranicestranky",
+ ["de"]="seitenbegrenzung",
+ ["en"]="pageboundaries",
+ ["fr"]="limitespage",
+ ["it"]="limitipagina",
+ ["nl"]="paginaovergangen",
+ ["pe"]="مرزهای‌صفحه",
+ ["ro"]="marginipagina",
+ },
+ ["pagecolor"]={
+ ["cs"]="barvastranky",
+ ["de"]="seitenfarbe",
+ ["en"]="pagecolor",
+ ["fr"]="couleurpage",
+ ["it"]="colorepagina",
+ ["nl"]="paginakleur",
+ ["pe"]="رنگ‌صفحه",
+ ["ro"]="culoarepagina",
+ },
+ ["pagecolormodel"]={
+ ["en"]="pagecolormodel",
+ ["nl"]="paginakleurmodel",
+ },
+ ["pagecommand"]={
+ ["cs"]="strankovyprikaz",
+ ["de"]="seitenbefehl",
+ ["en"]="pagecommand",
+ ["fr"]="commandepage",
+ ["it"]="comandopagina",
+ ["nl"]="paginacommando",
+ ["pe"]="فرمان‌صفحه",
+ ["ro"]="comandapagina",
+ },
+ ["pageconnector"]={
+ ["en"]="pageconnector",
+ },
+ ["pageconversion"]={
+ ["en"]="pageconversion",
+ },
+ ["pageconversionset"]={
+ ["en"]="pageconversionset",
+ },
+ ["pageleft"]={
+ ["en"]="pageleft",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostranky",
+ ["de"]="seitennummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شماره‌صفحه",
+ ["ro"]="numarpagina",
+ },
+ ["pageprefix"]={
+ ["en"]="pageprefix",
+ },
+ ["pageprefixconnector"]={
+ ["en"]="pageprefixconnector",
+ },
+ ["pageprefixconversion"]={
+ ["en"]="pageprefixconversion",
+ },
+ ["pageprefixconversionset"]={
+ ["en"]="pageprefixconversionset",
+ },
+ ["pageprefixsegments"]={
+ ["en"]="pageprefixsegments",
+ },
+ ["pageprefixseparatorset"]={
+ ["en"]="pageprefixseparatorset",
+ },
+ ["pageprefixset"]={
+ ["en"]="pageprefixset",
+ },
+ ["pageprefixstarter"]={
+ ["en"]="pageprefixstarter",
+ },
+ ["pageprefixstopper"]={
+ ["en"]="pageprefixstopper",
+ },
+ ["pageright"]={
+ ["en"]="pageright",
+ },
+ ["pagesegments"]={
+ ["en"]="pagesegments",
+ },
+ ["pagesep"]={
+ ["en"]="pagesep",
+ },
+ ["pageseparatorset"]={
+ ["en"]="pageseparatorset",
+ },
+ ["pageset"]={
+ ["en"]="pageset",
+ },
+ ["pagestarter"]={
+ ["en"]="pagestarter",
+ },
+ ["pagestate"]={
+ ["cs"]="pagestate",
+ ["de"]="pagestate",
+ ["en"]="pagestate",
+ ["fr"]="etatpage",
+ ["it"]="statopagina",
+ ["nl"]="paginastatus",
+ ["pe"]="وضعیت‌صفحه",
+ ["ro"]="pagestate",
+ },
+ ["pagestopper"]={
+ ["en"]="pagestopper",
+ },
+ ["pagestyle"]={
+ ["cs"]="stylstranky",
+ ["de"]="seitenstil",
+ ["en"]="pagestyle",
+ ["fr"]="stylepage",
+ ["it"]="stilepagina",
+ ["nl"]="paginaletter",
+ ["pe"]="سبک‌صفحه",
+ ["ro"]="stilpagina",
+ },
+ ["palet"]={
+ ["cs"]="paleta",
+ ["de"]="palette",
+ ["en"]="palet",
+ ["fr"]="palette",
+ ["it"]="tavolozza",
+ ["nl"]="palet",
+ ["pe"]="لوح",
+ ["ro"]="paleta",
+ },
+ ["paper"]={
+ ["cs"]="papir",
+ ["de"]="papier",
+ ["en"]="paper",
+ ["fr"]="papier",
+ ["it"]="carta",
+ ["nl"]="papier",
+ ["pe"]="برگ",
+ ["ro"]="hartie",
+ },
+ ["paragraph"]={
+ ["cs"]="odstavec",
+ ["de"]="absatz",
+ ["en"]="paragraph",
+ ["fr"]="paragraphe",
+ ["it"]="capoverso",
+ ["nl"]="alinea",
+ ["pe"]="پاراگراف",
+ ["ro"]="paragraf",
+ },
+ ["period"]={
+ ["en"]="period",
+ },
+ ["place"]={
+ ["cs"]="umistit",
+ ["de"]="platziere",
+ ["en"]="place",
+ ["fr"]="place",
+ ["it"]="metti",
+ ["nl"]="plaatsen",
+ ["pe"]="بگذار",
+ ["ro"]="pune",
+ },
+ ["placehead"]={
+ ["cs"]="umistihlavicku",
+ ["de"]="setzekopf",
+ ["en"]="placehead",
+ ["fr"]="placetete",
+ ["it"]="mettitesta",
+ ["nl"]="plaatskop",
+ ["pe"]="بگذارسر",
+ ["ro"]="punetitlu",
+ },
+ ["placestopper"]={
+ ["cs"]="predelmista",
+ ["de"]="setzetrenner",
+ ["en"]="placestopper",
+ ["fr"]="emplacementstopper",
+ ["it"]="mettistopper",
+ ["nl"]="plaatsafsluiter",
+ ["pe"]="بگذارایست",
+ ["ro"]="punestopper",
+ },
+ ["position"]={
+ ["cs"]="position",
+ ["de"]="position",
+ ["en"]="position",
+ ["fr"]="position",
+ ["it"]="posizione",
+ ["nl"]="positie",
+ ["pe"]="موقعیت",
+ ["ro"]="pozitie",
+ },
+ ["prefix"]={
+ ["cs"]="prefix",
+ ["de"]="prefix",
+ ["en"]="prefix",
+ ["fr"]="prefixe",
+ ["it"]="prefisso",
+ ["nl"]="prefix",
+ ["pe"]="پیشوند",
+ ["ro"]="prefix",
+ },
+ ["prefixconnector"]={
+ ["en"]="prefixconnector",
+ },
+ ["prefixconversion"]={
+ ["en"]="prefixconversion",
+ },
+ ["prefixconversionset"]={
+ ["en"]="prefixconversionset",
+ },
+ ["prefixsegments"]={
+ ["en"]="prefixsegments",
+ },
+ ["prefixseparatorset"]={
+ ["en"]="prefixseparatorset",
+ },
+ ["prefixset"]={
+ ["en"]="prefixset",
+ },
+ ["prefixstarter"]={
+ ["en"]="prefixstarter",
+ },
+ ["prefixstopper"]={
+ ["en"]="prefixstopper",
+ },
+ ["preset"]={
+ ["cs"]="prednastaveni",
+ ["de"]="voreinstellung",
+ ["en"]="preset",
+ ["fr"]="prereglage",
+ ["it"]="preimpostato",
+ ["nl"]="preset",
+ ["pe"]="preset",
+ ["ro"]="preset",
+ },
+ ["preview"]={
+ ["cs"]="nahled",
+ ["de"]="vorschau",
+ ["en"]="preview",
+ ["fr"]="previsualisation",
+ ["it"]="anteprima",
+ ["nl"]="preview",
+ ["pe"]="پیش‌دید",
+ ["ro"]="previzualizare",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorige",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precendent",
+ },
+ ["previousnumber"]={
+ ["cs"]="predchozicislo",
+ ["de"]="vorigenummer",
+ ["en"]="previousnumber",
+ ["fr"]="numeroprecedent",
+ ["it"]="numeroprecedente",
+ ["nl"]="vorigenummer",
+ ["pe"]="شماره‌قبلی",
+ ["ro"]="numarprecedent",
+ },
+ ["printable"]={
+ ["cs"]="tisknutelne",
+ ["de"]="druckbar",
+ ["en"]="printable",
+ ["fr"]="editable",
+ ["it"]="stampabile",
+ ["nl"]="printbaar",
+ ["pe"]="قابل‌چاپ",
+ ["ro"]="tiparibil",
+ },
+ ["process"]={
+ ["cs"]="process",
+ ["de"]="process",
+ ["en"]="process",
+ ["fr"]="process",
+ ["it"]="process",
+ ["nl"]="proces",
+ ["pe"]="پردازش",
+ ["ro"]="process",
+ },
+ ["profile"]={
+ ["en"]="profile",
+ },
+ ["properties"]={
+ ["en"]="properties",
+ },
+ ["pubsep"]={
+ ["en"]="pubsep",
+ },
+ ["quotechar"]={
+ ["en"]="quotechar",
+ },
+ ["radius"]={
+ ["cs"]="polomer",
+ ["de"]="radius",
+ ["en"]="radius",
+ ["fr"]="rayon",
+ ["it"]="raggio",
+ ["nl"]="straal",
+ ["pe"]="شعاع",
+ ["ro"]="raza",
+ },
+ ["random"]={
+ ["cs"]="nahodne",
+ ["de"]="zufaellig",
+ ["en"]="random",
+ ["fr"]="aleatoire",
+ ["it"]="casuale",
+ ["nl"]="willekeur",
+ ["pe"]="تصادفی",
+ ["ro"]="aleator",
+ },
+ ["range"]={
+ ["en"]="range",
+ ["nl"]="bereik",
+ },
+ ["reduction"]={
+ ["cs"]="redukce",
+ ["de"]="reduktion",
+ ["en"]="reduction",
+ ["fr"]="reduction",
+ ["it"]="riduzione",
+ ["nl"]="reductie",
+ ["pe"]="کاهش",
+ ["ro"]="reducere",
+ },
+ ["ref"]={
+ ["cs"]="ref",
+ ["de"]="ref",
+ ["en"]="ref",
+ ["fr"]="ref",
+ ["it"]="ref",
+ ["nl"]="ref",
+ ["pe"]="رج",
+ ["ro"]="ref",
+ },
+ ["refcommand"]={
+ ["en"]="refcommand",
+ },
+ ["reference"]={
+ ["cs"]="odkaz",
+ ["de"]="referenz",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="riferimento",
+ ["nl"]="referentie",
+ ["pe"]="مرجع",
+ ["ro"]="referinta",
+ },
+ ["referencemethod"]={
+ ["en"]="referencemethod",
+ },
+ ["referenceprefix"]={
+ ["en"]="referenceprefix",
+ },
+ ["referencing"]={
+ ["cs"]="odkazujici",
+ ["de"]="referieren",
+ ["en"]="referencing",
+ ["fr"]="referencing",
+ ["it"]="referencing",
+ ["nl"]="refereren",
+ ["pe"]="مراجعه",
+ ["ro"]="referinta",
+ },
+ ["region"]={
+ ["en"]="region",
+ ["nl"]="gebied",
+ },
+ ["regionin"]={
+ ["cs"]="oblastuvnitr",
+ ["de"]="regionin",
+ ["en"]="regionin",
+ ["fr"]="entreregion",
+ ["it"]="entraregione",
+ ["nl"]="gebiedin",
+ ["pe"]="ناحیه‌درون",
+ ["ro"]="regiuneintrare",
+ },
+ ["regionout"]={
+ ["cs"]="oblastvne",
+ ["de"]="regionaus",
+ ["en"]="regionout",
+ ["fr"]="regionexterieure",
+ ["it"]="esciregione",
+ ["nl"]="gebieduit",
+ ["pe"]="ناحیه‌بیرون",
+ ["ro"]="regiuneiesire",
+ },
+ ["register"]={
+ ["en"]="register",
+ },
+ ["regularfeatures"]={
+ ["en"]="regularfeatures",
+ },
+ ["regularfont"]={
+ ["en"]="regularfont",
+ },
+ ["renderingsetup"]={
+ ["en"]="renderingsetup",
+ },
+ ["repeat"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="repeat",
+ ["fr"]="repete",
+ ["it"]="ripeti",
+ ["nl"]="herhaal",
+ ["pe"]="تکرار",
+ ["ro"]="repeta",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="reset",
+ ["en"]="reset",
+ ["fr"]="reset",
+ ["it"]="reset",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["resetnumber"]={
+ ["cs"]="resetnumber",
+ ["de"]="resetnumber",
+ ["en"]="resetnumber",
+ ["fr"]="raznumero",
+ ["it"]="resetnumber",
+ ["nl"]="resetnummer",
+ ["pe"]="بازنشانی‌شماره",
+ ["ro"]="resetnumber",
+ },
+ ["resolution"]={
+ ["cs"]="rozliseni",
+ ["de"]="aufloesung",
+ ["en"]="resolution",
+ ["fr"]="resolution",
+ ["it"]="risoluzione",
+ ["nl"]="resolutie",
+ ["pe"]="کیفیت",
+ ["ro"]="rezolutie",
+ },
+ ["resources"]={
+ ["en"]="resources",
+ },
+ ["reverse"]={
+ ["cs"]="reverse",
+ ["de"]="reverse",
+ ["en"]="reverse",
+ ["fr"]="inverse",
+ ["it"]="invertito",
+ ["nl"]="omgekeerd",
+ ["pe"]="برعکس",
+ ["ro"]="reverse",
+ },
+ ["right"]={
+ ["cs"]="vpravo",
+ ["de"]="rechts",
+ ["en"]="right",
+ ["fr"]="droite",
+ ["it"]="destra",
+ ["nl"]="rechts",
+ ["pe"]="راست",
+ ["ro"]="dreapta",
+ },
+ ["rightcolor"]={
+ ["cs"]="barvavpravo",
+ ["de"]="rechterfarbe",
+ ["en"]="rightcolor",
+ ["fr"]="couleurdroite",
+ ["it"]="coloredestra",
+ ["nl"]="rechterkleur",
+ ["pe"]="رنگ‌راست",
+ ["ro"]="culoaredreapta",
+ },
+ ["rightcompoundhyphen"]={
+ ["cs"]="rightcompoundhyphen",
+ ["de"]="rightcompoundhyphen",
+ ["en"]="rightcompoundhyphen",
+ ["fr"]="rightcompoundhyphen",
+ ["it"]="rightcompoundhyphen",
+ ["nl"]="rechterkoppelteken",
+ ["pe"]="rightcompoundhyphen",
+ ["ro"]="rightcompoundhyphen",
+ },
+ ["rightedge"]={
+ ["cs"]="pravahrana",
+ ["de"]="rechtekante",
+ ["en"]="rightedge",
+ ["fr"]="borddroit",
+ ["it"]="bordodestro",
+ ["nl"]="rechterrand",
+ ["pe"]="لبه‌راست",
+ ["ro"]="borduradreapta",
+ },
+ ["rightedgedistance"]={
+ ["cs"]="vzdalenostpravehrany",
+ ["de"]="rechterkantenabstand",
+ ["en"]="rightedgedistance",
+ ["fr"]="distanceborddroit",
+ ["it"]="distanzabordodestro",
+ ["nl"]="rechterrandafstand",
+ ["pe"]="فاصله‌لبه‌راست",
+ ["ro"]="distantacoltdreapta",
+ },
+ ["rightframe"]={
+ ["cs"]="ramecekvpravo",
+ ["de"]="rechterrahmen",
+ ["en"]="rightframe",
+ ["fr"]="cadredroit",
+ ["it"]="cornicedestra",
+ ["nl"]="rechterkader",
+ ["pe"]="قالب‌راست",
+ ["ro"]="framedreapta",
+ },
+ ["righthyphen"]={
+ ["cs"]="righthyphen",
+ ["de"]="righthyphen",
+ ["en"]="righthyphen",
+ ["fr"]="righthyphen",
+ ["it"]="righthyphen",
+ ["nl"]="righthyphen",
+ ["pe"]="righthyphen",
+ ["ro"]="righthyphen",
+ },
+ ["rightmargin"]={
+ ["cs"]="pravyokraj",
+ ["de"]="rechterrand",
+ ["en"]="rightmargin",
+ ["fr"]="margedroite",
+ ["it"]="marginedestro",
+ ["nl"]="rechtermarge",
+ ["pe"]="حاشیه‌راست",
+ ["ro"]="marginedreapta",
+ },
+ ["rightmargindistance"]={
+ ["cs"]="vzdalenostpravehookraje",
+ ["de"]="rechterrandabstand",
+ ["en"]="rightmargindistance",
+ ["fr"]="distancemargedroite",
+ ["it"]="distanzamarginedestro",
+ ["nl"]="rechtermargeafstand",
+ ["pe"]="فاصله‌حاشیه‌راست",
+ ["ro"]="distantamarginedreapta",
+ },
+ ["rightoffset"]={
+ ["cs"]="pravyoffset",
+ ["de"]="rechterabstand",
+ ["en"]="rightoffset",
+ ["fr"]="rightoffset",
+ ["it"]="offsetdestro",
+ ["nl"]="rechteroffset",
+ ["pe"]="آفست‌راست",
+ ["ro"]="offsetdreapta",
+ },
+ ["rightquotation"]={
+ ["cs"]="citacevpravo",
+ ["de"]="rechterzitat",
+ ["en"]="rightquotation",
+ ["fr"]="citationdroite",
+ ["it"]="citazionedestra",
+ ["nl"]="rechtercitaat",
+ ["pe"]="نقل‌قول‌راست",
+ ["ro"]="citatdreapta",
+ },
+ ["rightquote"]={
+ ["cs"]="citovatvpravo",
+ ["de"]="rechterzitieren",
+ ["en"]="rightquote",
+ ["fr"]="citerdroite",
+ ["it"]="menzionedestra",
+ ["nl"]="rechterciteer",
+ ["pe"]="نقل‌راست",
+ ["ro"]="minicitatdreapta",
+ },
+ ["rightsentence"]={
+ ["cs"]="vetavpravo",
+ ["de"]="rechtersatz",
+ ["en"]="rightsentence",
+ ["fr"]="phrasedroite",
+ ["it"]="frasedestra",
+ ["nl"]="rechterzin",
+ ["pe"]="جمله‌راست",
+ ["ro"]="propozitiedreapta",
+ },
+ ["rightspeech"]={
+ ["cs"]="rightspeech",
+ ["de"]="rightspeech",
+ ["en"]="rightspeech",
+ ["fr"]="rightspeech",
+ ["it"]="rightspeech",
+ ["nl"]="rechteruitspraak",
+ ["pe"]="سخنرانی‌راست",
+ ["ro"]="rightspeech",
+ },
+ ["rightstyle"]={
+ ["cs"]="stylvpravo",
+ ["de"]="rechterstil",
+ ["en"]="rightstyle",
+ ["fr"]="styledroit",
+ ["it"]="stiledestra",
+ ["nl"]="rechterletter",
+ ["pe"]="سبک‌راست",
+ ["ro"]="stildreapta",
+ },
+ ["rightsubsentence"]={
+ ["cs"]="podvetavpravo",
+ ["de"]="rechtersubsatz",
+ ["en"]="rightsubsentence",
+ ["fr"]="sousphrasedroite",
+ ["it"]="sottofrasedestra",
+ ["nl"]="rechtersubzin",
+ ["pe"]="زیرجمله‌راست",
+ ["ro"]="subpropozitiedreapta",
+ },
+ ["righttext"]={
+ ["cs"]="textvpravo",
+ ["de"]="rechtertext",
+ ["en"]="righttext",
+ ["fr"]="textedroit",
+ ["it"]="testodestro",
+ ["nl"]="rechtertekst",
+ ["pe"]="متن‌راست",
+ ["ro"]="textdreapta",
+ },
+ ["rightwidth"]={
+ ["cs"]="sirkavpravo",
+ ["de"]="rechterbreite",
+ ["en"]="rightwidth",
+ ["fr"]="largeurdroite",
+ ["it"]="ampiezzadestra",
+ ["nl"]="rechterbreedte",
+ ["pe"]="عرض‌راست",
+ ["ro"]="marginedreapta",
+ },
+ ["rightwords"]={
+ ["en"]="rightwords",
+ },
+ ["rightchars"]={
+ ["en"]="rightchars",
+ },
+ ["roffset"]={
+ ["en"]="roffset",
+ },
+ ["rotation"]={
+ ["cs"]="rotace",
+ ["de"]="rotation",
+ ["en"]="rotation",
+ ["fr"]="rotation",
+ ["it"]="rotazione",
+ ["nl"]="rotatie",
+ ["pe"]="دوران",
+ ["ro"]="rotatie",
+ },
+ ["rule"]={
+ ["cs"]="linka",
+ ["de"]="linie",
+ ["en"]="rule",
+ ["fr"]="ligne",
+ ["it"]="linea",
+ ["nl"]="lijn",
+ ["pe"]="خط",
+ ["ro"]="rigla",
+ },
+ ["rulecolor"]={
+ ["cs"]="barvalinky",
+ ["de"]="linienfarbe",
+ ["en"]="rulecolor",
+ ["fr"]="couleurligne",
+ ["it"]="colorelinea",
+ ["nl"]="lijnkleur",
+ ["pe"]="رنگ‌خط",
+ ["ro"]="culoarerigla",
+ },
+ ["rulecommand"]={
+ ["en"]="rulecommand",
+ ["nl"]="lijncommando",
+ },
+ ["rulethickness"]={
+ ["cs"]="tloustkalinky",
+ ["de"]="liniendicke",
+ ["en"]="rulethickness",
+ ["fr"]="epaisseurligne",
+ ["it"]="spessorelinea",
+ ["nl"]="lijndikte",
+ ["pe"]="ضخامت‌خط",
+ ["ro"]="grosimerigla",
+ },
+ ["samepage"]={
+ ["cs"]="stejnastranka",
+ ["de"]="selbeseite",
+ ["en"]="samepage",
+ ["fr"]="memepage",
+ ["it"]="stessapagina",
+ ["nl"]="zelfdepagina",
+ ["pe"]="همان‌صفحه",
+ ["ro"]="aceeasipagina",
+ },
+ ["sample"]={
+ ["cs"]="vzor",
+ ["de"]="muster",
+ ["en"]="sample",
+ ["fr"]="echantillon",
+ ["it"]="campione",
+ ["nl"]="monster",
+ ["pe"]="نمونه",
+ ["ro"]="exemplu",
+ },
+ ["samplesize"]={
+ ["en"]="samplesize",
+ },
+ ["saveinlist"]={
+ ["en"]="saveinlist",
+ },
+ ["scale"]={
+ ["cs"]="meritko",
+ ["de"]="format",
+ ["en"]="scale",
+ ["fr"]="echelle",
+ ["it"]="scala",
+ ["nl"]="schaal",
+ ["pe"]="مقیاس",
+ ["ro"]="scala",
+ },
+ ["scope"]={
+ ["cs"]="rozsah",
+ ["de"]="bereich",
+ ["en"]="scope",
+ ["fr"]="scope",
+ ["it"]="scope",
+ ["nl"]="scope",
+ ["pe"]="طرح",
+ ["ro"]="scop",
+ },
+ ["screen"]={
+ ["cs"]="rastr",
+ ["de"]="raster",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="raster",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["section"]={
+ ["cs"]="oddil",
+ ["de"]="abschnitt",
+ ["en"]="section",
+ ["fr"]="section",
+ ["it"]="sezione",
+ ["nl"]="sectie",
+ ["pe"]="بخش",
+ ["ro"]="sectiune",
+ },
+ ["sectionblock"]={
+ ["en"]="sectionblock",
+ },
+ ["sectionconversion"]={
+ ["en"]="sectionconversion",
+ },
+ ["sectionconversionset"]={
+ ["en"]="sectionconversionset",
+ },
+ ["sectionnumber"]={
+ ["cs"]="cislooddilu",
+ ["de"]="abschnittsnummer",
+ ["en"]="sectionnumber",
+ ["fr"]="numerosection",
+ ["it"]="numerosezione",
+ ["nl"]="sectienummer",
+ ["pe"]="شماره‌بخش",
+ ["ro"]="numarsectiune",
+ },
+ ["sectionresetset"]={
+ ["en"]="sectionresetset",
+ },
+ ["sectionsegments"]={
+ ["en"]="sectionsegments",
+ },
+ ["sectionseparatorset"]={
+ ["en"]="sectionseparatorset",
+ },
+ ["sectionset"]={
+ ["en"]="sectionset",
+ },
+ ["sectionstarter"]={
+ ["en"]="sectionstarter",
+ },
+ ["sectionstopper"]={
+ ["en"]="sectionstopper",
+ },
+ ["separator"]={
+ ["cs"]="oddelovac",
+ ["de"]="seperator",
+ ["en"]="separator",
+ ["fr"]="separateur",
+ ["it"]="separatore",
+ ["nl"]="scheider",
+ ["pe"]="جداکننده",
+ ["ro"]="separator",
+ },
+ ["separatorcolor"]={
+ ["en"]="separatorcolor",
+ ["nl"]="scheiderkleur",
+ },
+ ["separatorstyle"]={
+ ["en"]="separatorstyle",
+ ["nl"]="scheiderletter",
+ },
+ ["set"]={
+ ["cs"]="set",
+ ["de"]="set",
+ ["en"]="set",
+ ["fr"]="set",
+ ["it"]="set",
+ ["nl"]="set",
+ ["pe"]="قراربده",
+ ["ro"]="set",
+ },
+ ["setups"]={
+ ["comment"]="no translations",
+ ["en"]="setups",
+ },
+ ["shrink"]={
+ ["en"]="shrink",
+ ["nl"]="krimp",
+ },
+ ["side"]={
+ ["cs"]="pocitat",
+ ["de"]="objektabstand",
+ ["en"]="side",
+ ["fr"]="cote",
+ ["it"]="lato",
+ ["nl"]="zij",
+ ["pe"]="کنار",
+ ["ro"]="parte",
+ },
+ ["sidealign"]={
+ ["cs"]="sidealign",
+ ["de"]="sidealign",
+ ["en"]="sidealign",
+ ["fr"]="sidealign",
+ ["it"]="sidealign",
+ ["nl"]="zijuitlijnen",
+ ["pe"]="تنظیم‌کنار",
+ ["ro"]="sidealign",
+ },
+ ["sidemethod"]={
+ ["cs"]="sidemethod",
+ ["de"]="sidemethod",
+ ["en"]="sidemethod",
+ ["fr"]="sidemethod",
+ ["it"]="sidemethod",
+ ["nl"]="zijmethode",
+ ["pe"]="روش‌کنار",
+ ["ro"]="sidemethod",
+ },
+ ["sidespaceafter"]={
+ ["cs"]="bocnimezeraza",
+ ["de"]="nebennachspatium",
+ ["en"]="sidespaceafter",
+ ["fr"]="espacelateralapres",
+ ["it"]="spaziolateraledopo",
+ ["nl"]="zijnawit",
+ ["pe"]="فضای‌کناری‌بعد",
+ ["ro"]="spatiulateraldupa",
+ },
+ ["sidespacebefore"]={
+ ["cs"]="bocnimezerapred",
+ ["de"]="nebenvorspatium",
+ ["en"]="sidespacebefore",
+ ["fr"]="espacelateralavant",
+ ["it"]="spaziolateraleprima",
+ ["nl"]="zijvoorwit",
+ ["pe"]="فضای‌کناری‌قبل",
+ ["ro"]="spatiulateralinainte",
+ },
+ ["sign"]={
+ ["cs"]="znak",
+ ["de"]="zeichen",
+ ["en"]="sign",
+ ["fr"]="signe",
+ ["it"]="segno",
+ ["nl"]="teken",
+ ["pe"]="علامت",
+ ["ro"]="semn",
+ },
+ ["size"]={
+ ["cs"]="velikost",
+ ["de"]="groesse",
+ ["en"]="size",
+ ["fr"]="dimension",
+ ["it"]="dimensione",
+ ["nl"]="formaat",
+ ["pe"]="اندازه",
+ ["ro"]="dimensiune",
+ },
+ ["slantedfeatures"]={
+ ["en"]="slantedfeatures",
+ },
+ ["slantedfont"]={
+ ["en"]="slantedfont",
+ },
+ ["small"]={
+ ["cs"]="male",
+ ["de"]="klein",
+ ["en"]="small",
+ ["fr"]="petit",
+ ["it"]="piccolo",
+ ["nl"]="klein",
+ ["pe"]="کوچک",
+ ["ro"]="mic",
+ },
+ ["smallcapsfeatures"]={
+ ["en"]="smallcapsfeatures",
+ },
+ ["smallcapsfont"]={
+ ["en"]="smallcapsfont",
+ },
+ ["solution"]={
+ ["en"]="solution",
+ ["nl"]="oplossing",
+ },
+ ["sort"]={
+ ["en"]="sort",
+ },
+ ["sorttype"]={
+ ["cs"]="sorttype",
+ ["de"]="sorttype",
+ ["en"]="sorttype",
+ ["fr"]="sorttype",
+ ["it"]="sorttype",
+ ["nl"]="sortering",
+ ["pe"]="ترتیب‌تایپ",
+ ["ro"]="sorttype",
+ },
+ ["source"]={
+ ["cs"]="zdroj",
+ ["de"]="quelle",
+ ["en"]="source",
+ ["fr"]="origine",
+ ["it"]="origine",
+ ["nl"]="bron",
+ ["pe"]="منبع",
+ ["ro"]="sursa",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["spaceafter"]={
+ ["cs"]="mezeraza",
+ ["de"]="nachspatium",
+ ["en"]="spaceafter",
+ ["fr"]="espaceapres",
+ ["it"]="spaziodopo",
+ ["nl"]="nawit",
+ ["pe"]="فضا‌بعداز",
+ ["ro"]="spatiudupa",
+ },
+ ["spacebefore"]={
+ ["cs"]="mezerapred",
+ ["de"]="vorspatium",
+ ["en"]="spacebefore",
+ ["fr"]="espaceavant",
+ ["it"]="spazioprima",
+ ["nl"]="voorwit",
+ ["pe"]="فضا‌قبل‌از",
+ ["ro"]="spatiuinainte",
+ },
+ ["spaceinbetween"]={
+ ["cs"]="spaceinbetween",
+ ["de"]="spaceinbetween",
+ ["en"]="spaceinbetween",
+ ["fr"]="spaceinbetween",
+ ["it"]="spaceinbetween",
+ ["nl"]="tussenwit",
+ ["pe"]="فضا‌دربین",
+ ["ro"]="spaceinbetween",
+ },
+ ["spacing"]={
+ ["cs"]="mezerovani",
+ ["de"]="spatiumausgleich",
+ ["en"]="spacing",
+ ["fr"]="espacement",
+ ["it"]="spaziatura",
+ ["nl"]="spatiering",
+ ["pe"]="فضاگذاری",
+ ["ro"]="spatiere",
+ },
+ ["specification"]={
+ ["en"]="specification",
+ },
+ ["split"]={
+ ["cs"]="split",
+ ["de"]="split",
+ ["en"]="split",
+ ["fr"]="split",
+ ["it"]="separa",
+ ["nl"]="splitsen",
+ ["pe"]="شکافتن",
+ ["ro"]="split",
+ },
+ ["splitcolor"]={
+ ["cs"]="splitcolor",
+ ["de"]="splitcolor",
+ ["en"]="splitcolor",
+ ["fr"]="splitcolor",
+ ["it"]="splitcolor",
+ ["nl"]="splitskleur",
+ ["pe"]="شکافتن‌رنگ",
+ ["ro"]="splitcolor",
+ },
+ ["splitmethod"]={
+ ["cs"]="splitmethod",
+ ["de"]="splitmethod",
+ ["en"]="splitmethod",
+ ["fr"]="splitmethod",
+ ["it"]="splitmethod",
+ ["nl"]="splitsmethode",
+ ["pe"]="روش‌شکافتن",
+ ["ro"]="splitmethod",
+ },
+ ["splitoffset"]={
+ ["cs"]="splitoffset",
+ ["de"]="splitoffset",
+ ["en"]="splitoffset",
+ ["fr"]="splitoffset",
+ ["it"]="splitoffset",
+ ["nl"]="splitsoffset",
+ ["pe"]="شکافتن‌آفست",
+ ["ro"]="splitoffset",
+ },
+ ["spot"]={
+ ["cs"]="spot",
+ ["de"]="spot",
+ ["en"]="spot",
+ ["fr"]="spot",
+ ["it"]="spot",
+ ["nl"]="spot",
+ ["pe"]="لکه",
+ ["ro"]="spot",
+ },
+ ["stack"]={
+ ["cs"]="stack",
+ ["de"]="stack",
+ ["en"]="stack",
+ ["fr"]="stack",
+ ["it"]="stack",
+ ["nl"]="stapel",
+ ["pe"]="توده",
+ ["ro"]="stack",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["starter"]={
+ ["en"]="starter",
+ ["nl"]="opener",
+ },
+ ["state"]={
+ ["cs"]="status",
+ ["de"]="status",
+ ["en"]="state",
+ ["fr"]="etat",
+ ["it"]="stato",
+ ["nl"]="status",
+ ["pe"]="وضعیت",
+ ["ro"]="stare",
+ },
+ ["step"]={
+ ["cs"]="krok",
+ ["de"]="schritt",
+ ["en"]="step",
+ ["fr"]="pas",
+ ["it"]="passo",
+ ["nl"]="stap",
+ ["pe"]="گام",
+ ["ro"]="pas",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["stopper"]={
+ ["cs"]="predel",
+ ["de"]="abschnitttrenner",
+ ["en"]="stopper",
+ ["fr"]="taquet",
+ ["it"]="stopper",
+ ["nl"]="afsluiter",
+ ["pe"]="ایست",
+ ["ro"]="stopper",
+ },
+ ["stretch"]={
+ ["cs"]="natahnout",
+ ["de"]="strecken",
+ ["en"]="stretch",
+ ["fr"]="etire",
+ ["it"]="dilata",
+ ["nl"]="rek",
+ ["pe"]="کشیدن",
+ ["ro"]="dilatat",
+ },
+ ["strip"]={
+ ["en"]="strip",
+ },
+ ["strut"]={
+ ["cs"]="strut",
+ ["de"]="strut",
+ ["en"]="strut",
+ ["fr"]="strut",
+ ["it"]="strut",
+ ["nl"]="strut",
+ ["pe"]="بست",
+ ["ro"]="strut",
+ },
+ ["style"]={
+ ["cs"]="pismeno",
+ ["de"]="stil",
+ ["en"]="style",
+ ["fr"]="style",
+ ["it"]="stile",
+ ["nl"]="letter",
+ ["pe"]="سبک",
+ ["ro"]="stil",
+ },
+ ["sub"]={
+ ["cs"]="pod",
+ ["de"]="unter",
+ ["en"]="sub",
+ ["fr"]="sous",
+ ["it"]="sotto",
+ ["nl"]="sub",
+ ["pe"]="زیر",
+ ["ro"]="sub",
+ },
+ ["subtitle"]={
+ ["cs"]="podtitulek",
+ ["de"]="untertitel",
+ ["en"]="subtitle",
+ ["fr"]="soustitre",
+ ["it"]="sottotitolo",
+ ["nl"]="subtitel",
+ ["pe"]="زیرعنوان",
+ ["ro"]="subtitlu",
+ },
+ ["suffix"]={
+ ["cs"]="suffix",
+ ["de"]="suffix",
+ ["en"]="suffix",
+ ["fr"]="suffix",
+ ["it"]="suffix",
+ ["nl"]="suffix",
+ ["pe"]="پسوند",
+ ["ro"]="suffix",
+ },
+ ["suffixseparator"]={
+ ["en"]="suffixseparator",
+ ["nl"]="suffixscheider",
+ },
+ ["suffixstopper"]={
+ ["en"]="suffixstopper",
+ ["nl"]="suffixafsluiter",
+ },
+ ["surnamefirstnamesep"]={
+ ["en"]="surnamefirstnamesep",
+ },
+ ["surnameinitialsep"]={
+ ["en"]="surnameinitialsep",
+ },
+ ["surnamesep"]={
+ ["en"]="surnamesep",
+ },
+ ["svgstyle"]={
+ ["en"]="svgstyle",
+ },
+ ["sx"]={
+ ["cs"]="sx",
+ ["de"]="sx",
+ ["en"]="sx",
+ ["fr"]="sx",
+ ["it"]="sx",
+ ["nl"]="sx",
+ ["pe"]="sx",
+ ["ro"]="sx",
+ },
+ ["sy"]={
+ ["cs"]="sy",
+ ["de"]="sy",
+ ["en"]="sy",
+ ["fr"]="sy",
+ ["it"]="sy",
+ ["nl"]="sy",
+ ["pe"]="sy",
+ ["ro"]="sy",
+ },
+ ["symalign"]={
+ ["cs"]="symzarovnani",
+ ["de"]="symausrichtung",
+ ["en"]="symalign",
+ ["fr"]="symalignement",
+ ["it"]="symallinea",
+ ["nl"]="symuitlijnen",
+ ["pe"]="تنظیم‌نماد",
+ ["ro"]="symaliniere",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["symbolcommand"]={
+ ["en"]="symbolcommand",
+ },
+ ["symbolset"]={
+ ["cs"]="sadasymbolu",
+ ["de"]="symbolset",
+ ["en"]="symbolset",
+ ["fr"]="jeusymbole",
+ ["it"]="setsimboli",
+ ["nl"]="symboolset",
+ ["pe"]="مجموعه‌نماد",
+ ["ro"]="setsimbol",
+ },
+ ["symcolor"]={
+ ["cs"]="barvasymbolu",
+ ["de"]="symfarbe",
+ ["en"]="symcolor",
+ ["fr"]="couleursym",
+ ["it"]="coloresimbolo",
+ ["nl"]="symkleur",
+ ["pe"]="رنگ‌نماد",
+ ["ro"]="culoaresimbol",
+ },
+ ["symstyle"]={
+ ["cs"]="stylsymboly",
+ ["de"]="symstil",
+ ["en"]="symstyle",
+ ["fr"]="stylesym",
+ ["it"]="stilesimbolo",
+ ["nl"]="symletter",
+ ["pe"]="سبک‌نماد",
+ ["ro"]="stilsimbol",
+ },
+ ["synonym"]={
+ ["cs"]="synonymum",
+ ["de"]="synonym",
+ ["en"]="synonym",
+ ["fr"]="synonyme",
+ ["it"]="sinonimo",
+ ["nl"]="synoniem",
+ ["pe"]="مترادف",
+ ["ro"]="sinonim",
+ },
+ ["synonymcolor"]={
+ ["cs"]="barvasynonyma",
+ ["de"]="synonymfarbe",
+ ["en"]="synonymcolor",
+ ["fr"]="couleursynonyme",
+ ["it"]="coloresinonimi",
+ ["nl"]="synoniemkleur",
+ ["pe"]="رنگ‌مترادف",
+ ["ro"]="culoaresinonim",
+ },
+ ["synonymcommand"]={
+ ["cs"]="synonymcommand",
+ ["de"]="synonymbefehl",
+ ["en"]="synonymcommand",
+ ["fr"]="synonymcommand",
+ ["it"]="synonymcommand",
+ ["nl"]="synoniemcommando",
+ ["pe"]="synonymcommand",
+ ["ro"]="synonymcommand",
+ },
+ ["synonymstyle"]={
+ ["cs"]="stylsynonyma",
+ ["de"]="synonymstil",
+ ["en"]="synonymstyle",
+ ["fr"]="stylesynonyme",
+ ["it"]="stilesinonimi",
+ ["nl"]="synoniemletter",
+ ["pe"]="سبک‌مترادف",
+ ["ro"]="stilsinonim",
+ },
+ ["tab"]={
+ ["cs"]="tab",
+ ["de"]="tab",
+ ["en"]="tab",
+ ["fr"]="tab",
+ ["it"]="tab",
+ ["nl"]="tab",
+ ["pe"]="تب",
+ ["ro"]="tab",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["textalign"]={
+ ["en"]="textalign",
+ },
+ ["textcolor"]={
+ ["cs"]="barvatextu",
+ ["de"]="textfarbe",
+ ["en"]="textcolor",
+ ["fr"]="couleurtexte",
+ ["it"]="coloretesto",
+ ["nl"]="tekstkleur",
+ ["pe"]="رنگ‌متن",
+ ["ro"]="culoaretext",
+ },
+ ["textcommand"]={
+ ["cs"]="textovyprikaz",
+ ["de"]="textbefehl",
+ ["en"]="textcommand",
+ ["fr"]="commandetexte",
+ ["it"]="comandotesto",
+ ["nl"]="tekstcommando",
+ ["pe"]="فرمان‌متن",
+ ["ro"]="comandatext",
+ },
+ ["textdistance"]={
+ ["cs"]="textdistance",
+ ["de"]="textdistance",
+ ["en"]="textdistance",
+ ["fr"]="distancetexte",
+ ["it"]="distanzatesto",
+ ["nl"]="tekstafstand",
+ ["pe"]="فاصله‌متن",
+ ["ro"]="textdistance",
+ },
+ ["textheight"]={
+ ["cs"]="vyskatextu",
+ ["de"]="texthoehe",
+ ["en"]="textheight",
+ ["fr"]="hauteurtexte",
+ ["it"]="altezzatesto",
+ ["nl"]="teksthoogte",
+ ["pe"]="ارتفاع‌متن",
+ ["ro"]="inaltimetext",
+ },
+ ["textlayer"]={
+ ["cs"]="textlayer",
+ ["de"]="textlayer",
+ ["en"]="textlayer",
+ ["fr"]="calquetexte",
+ ["it"]="textlayer",
+ ["nl"]="tekstlaag",
+ ["pe"]="لایه‌متن",
+ ["ro"]="textlayer",
+ },
+ ["textmargin"]={
+ ["cs"]="textmargin",
+ ["de"]="textmargin",
+ ["en"]="textmargin",
+ ["fr"]="margetexte",
+ ["it"]="textmargin",
+ ["nl"]="tekstmarge",
+ ["pe"]="حاشیه‌متن",
+ ["ro"]="textmargin",
+ },
+ ["textmethod"]={
+ ["cs"]="textmethod",
+ ["de"]="textmethod",
+ ["en"]="textmethod",
+ ["fr"]="textmethod",
+ ["it"]="textmethod",
+ ["nl"]="tekstmethode",
+ ["pe"]="روش‌متن",
+ ["ro"]="textmethod",
+ },
+ ["textseparator"]={
+ ["cs"]="oddelovactextu",
+ ["de"]="textseparator",
+ ["en"]="textseparator",
+ ["fr"]="separateurtexte",
+ ["it"]="separatoretesto",
+ ["nl"]="tekstscheider",
+ ["pe"]="جداکننده‌متن",
+ ["ro"]="separatortext",
+ },
+ ["textsize"]={
+ ["cs"]="velikosttextu",
+ ["de"]="textgroesse",
+ ["en"]="textsize",
+ ["fr"]="tailletexte",
+ ["it"]="dimensionetesto",
+ ["nl"]="tekstformaat",
+ ["pe"]="اندازه‌متن",
+ ["ro"]="dimensiunetext",
+ },
+ ["textstate"]={
+ ["cs"]="statustextu",
+ ["de"]="textstatus",
+ ["en"]="textstate",
+ ["fr"]="etattexte",
+ ["it"]="statotesto",
+ ["nl"]="tekststatus",
+ ["pe"]="وضعیت‌متن",
+ ["ro"]="staretext",
+ },
+ ["textstyle"]={
+ ["cs"]="styltextu",
+ ["de"]="textstil",
+ ["en"]="textstyle",
+ ["fr"]="styletexte",
+ ["it"]="stiletesto",
+ ["nl"]="tekstletter",
+ ["pe"]="سبک‌متن",
+ ["ro"]="stiltext",
+ },
+ ["textwidth"]={
+ ["cs"]="sirkatextu",
+ ["de"]="textbreite",
+ ["en"]="textwidth",
+ ["fr"]="largeurtexte",
+ ["it"]="ampiezzatesto",
+ ["nl"]="tekstbreedte",
+ ["pe"]="عرض‌متن",
+ ["ro"]="latimetext",
+ },
+ ["threshold"]={
+ ["en"]="threshold",
+ },
+ ["title"]={
+ ["cs"]="titul",
+ ["de"]="titel",
+ ["en"]="title",
+ ["fr"]="titre",
+ ["it"]="titolo",
+ ["nl"]="titel",
+ ["pe"]="عنوان",
+ ["ro"]="titlu",
+ },
+ ["titlecolor"]={
+ ["cs"]="barvatitulek",
+ ["de"]="titelfarbe",
+ ["en"]="titlecolor",
+ ["fr"]="couleurtitre",
+ ["it"]="coloretitolo",
+ ["nl"]="titelkleur",
+ ["pe"]="رنگ‌عنوان",
+ ["ro"]="culoaretitlu",
+ },
+ ["titlecommand"]={
+ ["cs"]="titlecommand",
+ ["de"]="titlecommand",
+ ["en"]="titlecommand",
+ ["fr"]="titlecommand",
+ ["it"]="titlecommand",
+ ["nl"]="titelcommando",
+ ["pe"]="فرمان‌عنوان",
+ ["ro"]="titlecommand",
+ },
+ ["titledistance"]={
+ ["cs"]="vzdalenosttitulek",
+ ["de"]="titelabstand",
+ ["en"]="titledistance",
+ ["fr"]="distancetitre",
+ ["it"]="distanzatitolo",
+ ["nl"]="titelafstand",
+ ["pe"]="فاصله‌عنوان",
+ ["ro"]="distantatitlu",
+ },
+ ["titleleft"]={
+ ["cs"]="titleleft",
+ ["de"]="titleleft",
+ ["en"]="titleleft",
+ ["fr"]="titleleft",
+ ["it"]="titleleft",
+ ["nl"]="titellinks",
+ ["pe"]="عنوان‌چپ",
+ ["ro"]="titleleft",
+ },
+ ["titleright"]={
+ ["cs"]="titleright",
+ ["de"]="titleright",
+ ["en"]="titleright",
+ ["fr"]="titleright",
+ ["it"]="titleright",
+ ["nl"]="titelrechts",
+ ["pe"]="عنوان‌راست",
+ ["ro"]="titleright",
+ },
+ ["titlestyle"]={
+ ["cs"]="styltitulek",
+ ["de"]="titelstil",
+ ["en"]="titlestyle",
+ ["fr"]="styletitre",
+ ["it"]="stiletitolo",
+ ["nl"]="titelletter",
+ ["pe"]="سبک‌عنوان",
+ ["ro"]="stiltitlu",
+ },
+ ["to"]={
+ ["cs"]="na",
+ ["de"]="zu",
+ ["en"]="to",
+ ["fr"]="vers",
+ ["it"]="verso",
+ ["nl"]="aan",
+ ["pe"]="به",
+ ["ro"]="catre",
+ },
+ ["toffset"]={
+ ["en"]="toffset",
+ },
+ ["tolerance"]={
+ ["cs"]="tolerance",
+ ["de"]="toleranz",
+ ["en"]="tolerance",
+ ["fr"]="tolerance",
+ ["it"]="tolleranza",
+ ["nl"]="tolerantie",
+ ["pe"]="بردباری",
+ ["ro"]="toleranta",
+ },
+ ["top"]={
+ ["cs"]="vrsek",
+ ["de"]="oben",
+ ["en"]="top",
+ ["fr"]="sup",
+ ["it"]="cima",
+ ["nl"]="boven",
+ ["pe"]="بالا",
+ ["ro"]="sus",
+ },
+ ["topcommand"]={
+ ["en"]="topcommand",
+ ["nl"]="bovencommando",
+ },
+ ["topdistance"]={
+ ["cs"]="vzdalenostvrsku",
+ ["de"]="obenabstand",
+ ["en"]="topdistance",
+ ["fr"]="distancesup",
+ ["it"]="distanzacima",
+ ["nl"]="bovenafstand",
+ ["pe"]="فاصله‌بالا",
+ ["ro"]="distantasus",
+ },
+ ["topframe"]={
+ ["cs"]="rameceknahore",
+ ["de"]="obenrahmen",
+ ["en"]="topframe",
+ ["fr"]="cadresup",
+ ["it"]="cornicecima",
+ ["nl"]="bovenkader",
+ ["pe"]="قالب‌راست",
+ ["ro"]="framesus",
+ },
+ ["topoffset"]={
+ ["cs"]="offsetvrsku",
+ ["de"]="obenoffset",
+ ["en"]="topoffset",
+ ["fr"]="decalagesup",
+ ["it"]="offsetcima",
+ ["nl"]="bovenoffset",
+ ["pe"]="آفست‌بالا",
+ ["ro"]="offsetsus",
+ },
+ ["topspace"]={
+ ["cs"]="svrchnimezera",
+ ["de"]="kopfspatium",
+ ["en"]="topspace",
+ ["fr"]="espacesup",
+ ["it"]="spaziocima",
+ ["nl"]="kopwit",
+ ["pe"]="فضای‌بالا",
+ ["ro"]="spatiusus",
+ },
+ ["topstate"]={
+ ["cs"]="statusvrsku",
+ ["de"]="statusoben",
+ ["en"]="topstate",
+ ["fr"]="etatsup",
+ ["it"]="statocima",
+ ["nl"]="bovenstatus",
+ ["pe"]="وضعیت‌بالا",
+ ["ro"]="staresus",
+ },
+ ["totalnumber"]={
+ ["en"]="totalnumber",
+ },
+ ["translate"]={
+ ["en"]="translate",
+ },
+ ["trimoffset"]={
+ ["en"]="trimoffset",
+ },
+ ["type"]={
+ ["cs"]="typ",
+ ["de"]="typ",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["unit"]={
+ ["cs"]="jednotka",
+ ["de"]="einheit",
+ ["en"]="unit",
+ ["fr"]="unite",
+ ["it"]="unita",
+ ["nl"]="eenheid",
+ ["pe"]="واحد",
+ ["ro"]="unitate",
+ },
+ ["unknownreference"]={
+ ["cs"]="neznamyodkaz",
+ ["de"]="unbekantereferenz",
+ ["en"]="unknownreference",
+ ["fr"]="referenceinconnue",
+ ["it"]="riferimentoingoto",
+ ["nl"]="onbekendereferentie",
+ ["pe"]="مرجع‌ناشناس",
+ ["ro"]="referintanecunoscuta",
+ },
+ ["up"]={
+ ["en"]="up",
+ },
+ ["urlalternative"]={
+ ["cs"]="urlalternativa",
+ ["de"]="urlalternative",
+ ["en"]="urlalternative",
+ ["fr"]="alternativeurl",
+ ["it"]="alternativaurl",
+ ["nl"]="urlvariant",
+ ["pe"]="urlalternative",
+ ["ro"]="urlalternativ",
+ },
+ ["urlspace"]={
+ ["cs"]="prostorurl",
+ ["de"]="urlspatium",
+ ["en"]="urlspace",
+ ["fr"]="espaceurl",
+ ["it"]="spaziourl",
+ ["nl"]="urlspatie",
+ ["pe"]="urlspace",
+ ["ro"]="spatiuurl",
+ },
+ ["validate"]={
+ ["cs"]="validovat",
+ ["de"]="validieren",
+ ["en"]="validate",
+ ["fr"]="valider",
+ ["it"]="verifica",
+ ["nl"]="valideer",
+ ["pe"]="تاییداعتبار",
+ ["ro"]="verifica",
+ },
+ ["values"]={
+ ["en"]="values",
+ ["nl"]="waarden",
+ },
+ ["vcommand"]={
+ ["cs"]="vprikaz",
+ ["de"]="vbefehl",
+ ["en"]="vcommand",
+ ["fr"]="vcommande",
+ ["it"]="vcomando",
+ ["nl"]="vcommando",
+ ["pe"]="vcommand",
+ ["ro"]="comandav",
+ },
+ ["vcompact"]={
+ ["en"]="vcompact",
+ ["nl"]="vcomprimeer",
+ },
+ ["vector"]={
+ ["en"]="vector",
+ ["nl"]="vector",
+ },
+ ["veroffset"]={
+ ["cs"]="offsethlavicky",
+ ["de"]="kopfoffset",
+ ["en"]="veroffset",
+ ["fr"]="veroffset",
+ ["it"]="veroffset",
+ ["nl"]="kopoffset",
+ ["pe"]="آفست‌عم",
+ ["ro"]="veroffset",
+ },
+ ["vfil"]={
+ ["cs"]="vfil",
+ ["de"]="vfil",
+ ["en"]="vfil",
+ ["fr"]="vfil",
+ ["it"]="vfil",
+ ["nl"]="vfil",
+ ["pe"]="vfil",
+ ["ro"]="vfil",
+ },
+ ["viewerprefix"]={
+ ["en"]="viewerprefix",
+ },
+ ["voffset"]={
+ ["cs"]="voffset",
+ ["de"]="voffset",
+ ["en"]="voffset",
+ ["fr"]="voffset",
+ ["it"]="voffset",
+ ["nl"]="voffset",
+ ["pe"]="آفست‌ع",
+ ["ro"]="voffset",
+ },
+ ["vonsep"]={
+ ["en"]="vonsep",
+ },
+ ["way"]={
+ ["cs"]="zpusob",
+ ["de"]="art",
+ ["en"]="way",
+ ["fr"]="mode",
+ ["it"]="modo",
+ ["nl"]="wijze",
+ ["pe"]="راه",
+ ["ro"]="mod",
+ },
+ ["wfactor"]={
+ ["cs"]="sfaktor",
+ ["de"]="bfaktor",
+ ["en"]="wfactor",
+ ["fr"]="facteurlargeur",
+ ["it"]="wfactor",
+ ["nl"]="bfactor",
+ ["pe"]="wfactor",
+ ["ro"]="factorw",
+ },
+ ["white"]={
+ ["cs"]="bily",
+ ["de"]="weiss",
+ ["en"]="white",
+ ["fr"]="blanc",
+ ["it"]="bianco",
+ ["nl"]="wit",
+ ["pe"]="سفید",
+ ["ro"]="alb",
+ },
+ ["width"]={
+ ["cs"]="sirka",
+ ["de"]="breite",
+ ["en"]="width",
+ ["fr"]="largeur",
+ ["it"]="ampiezza",
+ ["nl"]="breedte",
+ ["pe"]="عرض",
+ ["ro"]="latime",
+ },
+ ["words"]={
+ ["en"]="words",
+ },
+ ["xfactor"]={
+ ["cs"]="xfaktor",
+ ["de"]="xfaktor",
+ ["en"]="xfactor",
+ ["fr"]="xfactor",
+ ["it"]="xfactor",
+ ["nl"]="xfactor",
+ ["pe"]="فاکتورایکس",
+ ["ro"]="xfactor",
+ },
+ ["xhtml"]={
+ ["en"]="xhtml",
+ },
+ ["xmax"]={
+ ["cs"]="xmax",
+ ["de"]="xmax",
+ ["en"]="xmax",
+ ["fr"]="xmax",
+ ["it"]="xmax",
+ ["nl"]="xmax",
+ ["pe"]="xmax",
+ ["ro"]="xmax",
+ },
+ ["xmlsetup"]={
+ ["en"]="xmlsetup",
+ },
+ ["xoffset"]={
+ ["cs"]="xoffset",
+ ["de"]="xoffset",
+ ["en"]="xoffset",
+ ["fr"]="xoffset",
+ ["it"]="xoffset",
+ ["nl"]="xoffset",
+ ["pe"]="آفست‌ایکس",
+ ["ro"]="xoffset",
+ },
+ ["xscale"]={
+ ["cs"]="xmeritko",
+ ["de"]="xformat",
+ ["en"]="xscale",
+ ["fr"]="xscale",
+ ["it"]="xscale",
+ ["nl"]="xschaal",
+ ["pe"]="مقیاس‌ایکس",
+ ["ro"]="xscala",
+ },
+ ["xstep"]={
+ ["cs"]="xkrok",
+ ["de"]="xschritt",
+ ["en"]="xstep",
+ ["fr"]="xstep",
+ ["it"]="xstep",
+ ["nl"]="xstap",
+ ["pe"]="گام‌ایکس",
+ ["ro"]="xstep",
+ },
+ ["yfactor"]={
+ ["cs"]="yfaktor",
+ ["de"]="yfaktor",
+ ["en"]="yfactor",
+ ["fr"]="yfactor",
+ ["it"]="yfactor",
+ ["nl"]="yfactor",
+ ["pe"]="فاکتوروای",
+ ["ro"]="yfactor",
+ },
+ ["ymax"]={
+ ["cs"]="ymax",
+ ["de"]="ymax",
+ ["en"]="ymax",
+ ["fr"]="ymax",
+ ["it"]="ymax",
+ ["nl"]="ymax",
+ ["pe"]="ymax",
+ ["ro"]="ymax",
+ },
+ ["yoffset"]={
+ ["cs"]="yoffset",
+ ["de"]="yoffset",
+ ["en"]="yoffset",
+ ["fr"]="yoffset",
+ ["it"]="yoffset",
+ ["nl"]="yoffset",
+ ["pe"]="آفست‌وای",
+ ["ro"]="yoffset",
+ },
+ ["yscale"]={
+ ["cs"]="ymeritko",
+ ["de"]="yformat",
+ ["en"]="yscale",
+ ["fr"]="yscale",
+ ["it"]="yscale",
+ ["nl"]="yschaal",
+ ["pe"]="مقیاس‌وای",
+ ["ro"]="yscala",
+ },
+ ["ystep"]={
+ ["cs"]="ykrok",
+ ["de"]="yschritt",
+ ["en"]="ystep",
+ ["fr"]="ystep",
+ ["it"]="ystep",
+ ["nl"]="ystap",
+ ["pe"]="گام‌وای",
+ ["ro"]="ystep",
+ },
+ },
+ ["elements"]={
+ ["answerlines"]={
+ ["cs"]="answerlines",
+ ["de"]="answerlines",
+ ["en"]="answerlines",
+ ["fr"]="answerlines",
+ ["it"]="answerlines",
+ ["nl"]="antwoordregels",
+ ["pe"]="answerlines",
+ ["ro"]="answerlines",
+ },
+ ["answerspace"]={
+ ["cs"]="answerspace",
+ ["de"]="answerspace",
+ ["en"]="answerspace",
+ ["fr"]="answerspace",
+ ["it"]="answerspace",
+ ["nl"]="antwoordruimte",
+ ["pe"]="answerspace",
+ ["ro"]="answerspace",
+ },
+ ["begin"]={
+ ["cs"]="zacatek",
+ ["de"]="anfang",
+ ["en"]="begin",
+ ["fr"]="debut",
+ ["it"]="inizio",
+ ["nl"]="beginvan",
+ ["pe"]="عنصرها",
+ ["ro"]="inceput",
+ },
+ ["complete"]={
+ ["cs"]="uplny",
+ ["de"]="vollende",
+ ["en"]="complete",
+ ["fr"]="complete",
+ ["it"]="completo",
+ ["nl"]="volledige",
+ ["pe"]="کامل",
+ ["ro"]="complet",
+ },
+ ["coupled"]={
+ ["cs"]="propojene",
+ ["de"]="verknuepft",
+ ["en"]="coupled",
+ ["fr"]="couple",
+ ["it"]="accoppiato",
+ ["nl"]="gekoppelde",
+ ["pe"]="مزدوج",
+ ["ro"]="cuplat",
+ },
+ ["currentlocal"]={
+ ["cs"]="aktualnelokalni",
+ ["de"]="aktuelllokal",
+ ["en"]="currentlocal",
+ ["fr"]="localcourant",
+ ["it"]="correntelocale",
+ ["nl"]="huidigelokale",
+ ["pe"]="موضعی‌جاری",
+ ["ro"]="localcurent",
+ },
+ ["end"]={
+ ["cs"]="konec",
+ ["de"]="ende",
+ ["en"]="end",
+ ["fr"]="fin",
+ ["it"]="fine",
+ ["nl"]="eindvan",
+ ["pe"]="انتها",
+ ["ro"]="sfarsit",
+ },
+ ["endsetup"]={
+ ["cs"]="",
+ ["de"]="ein",
+ ["en"]="",
+ ["fr"]="",
+ ["it"]="",
+ ["nl"]="in",
+ ["pe"]="انتهای‌بارگذاری",
+ ["ro"]="",
+ },
+ ["get"]={
+ ["cs"]="ziskat",
+ ["de"]="get",
+ ["en"]="get",
+ ["fr"]="obtient",
+ ["it"]="prendi",
+ ["nl"]="haal",
+ ["pe"]="بگیر",
+ ["ro"]="get",
+ },
+ ["increment"]={
+ ["cs"]="zvysit",
+ ["de"]="erhoehen",
+ ["en"]="increment",
+ ["fr"]="incremente",
+ ["it"]="incrementa",
+ ["nl"]="verhoog",
+ ["pe"]="افزایش",
+ ["ro"]="increment",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="auflisten",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["listof"]={
+ ["cs"]="seznam",
+ ["de"]="auflistenvon",
+ ["en"]="listof",
+ ["fr"]="listede",
+ ["it"]="elencodi",
+ ["nl"]="lijstmet",
+ ["pe"]="لیست‌از",
+ ["ro"]="listade",
+ },
+ ["load"]={
+ ["cs"]="nacist",
+ ["de"]="laden",
+ ["en"]="load",
+ ["fr"]="charge",
+ ["it"]="carica",
+ ["nl"]="laad",
+ ["pe"]="بارگذاشتن",
+ ["ro"]="incarca",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokale",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["makeup"]={
+ ["cs"]="zlom",
+ ["de"]="umbruch",
+ ["en"]="makeup",
+ ["fr"]="makeup",
+ ["it"]="makeup",
+ ["nl"]="opmaak",
+ ["pe"]="آرایش",
+ ["ro"]="makeup",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="suivant",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["place"]={
+ ["cs"]="umisti",
+ ["de"]="platziere",
+ ["en"]="place",
+ ["fr"]="place",
+ ["it"]="metti",
+ ["nl"]="plaats",
+ ["pe"]="مکان",
+ ["ro"]="pune",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorige",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precedent",
+ },
+ ["previouslocal"]={
+ ["cs"]="predchozilokalni",
+ ["de"]="voriglokal",
+ ["en"]="previouslocal",
+ ["fr"]="localprecedent",
+ ["it"]="precedentelocale",
+ ["nl"]="vorigelokale",
+ ["pe"]="موضع‌قبلی",
+ ["ro"]="precedentlocal",
+ },
+ ["reserve"]={
+ ["cs"]="rezervovat",
+ ["de"]="reservieren",
+ ["en"]="reserve",
+ ["fr"]="reserver",
+ ["it"]="riserva",
+ ["nl"]="reserveer",
+ ["pe"]="رزرو",
+ ["ro"]="rezervat",
+ },
+ ["see"]={
+ ["cs"]="viz",
+ ["de"]="sieh",
+ ["en"]="see",
+ ["fr"]="voit",
+ ["it"]="vedi",
+ ["nl"]="zie",
+ ["pe"]="ببینید",
+ ["ro"]="vezi",
+ },
+ ["setup"]={
+ ["cs"]="nastaveni",
+ ["de"]="stelle",
+ ["en"]="setup",
+ ["fr"]="regle",
+ ["it"]="imposta",
+ ["nl"]="stel",
+ ["pe"]="بارگذاری",
+ ["ro"]="setare",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="type",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ },
+ ["variables"]={
+ ["aside"]={
+ ["en"]="aside",
+ },
+ ["ordinal"]={
+ ["en"]="ordinal",
+ },
+ ["Ordinal"]={
+ ["en"]="Ordinal",
+ },
+ ["Addition"]={
+ ["cs"]="Pridavek",
+ ["de"]="Zusatz",
+ ["en"]="Addition",
+ ["fr"]="Ajout",
+ ["it"]="Aggiunta",
+ ["nl"]="Toevoeging",
+ ["pe"]="جمع",
+ ["ro"]="Adaugare",
+ },
+ ["Alphabetic"]={
+ ["en"]="Alphabetic",
+ },
+ ["Balloon"]={
+ ["cs"]="Bublinka",
+ ["de"]="Ballon",
+ ["en"]="Balloon",
+ ["fr"]="Ballon",
+ ["it"]="Pallone",
+ ["nl"]="Ballon",
+ ["pe"]="بادکنک",
+ ["ro"]="Balon",
+ },
+ ["Cap"]={
+ ["cs"]="Kap",
+ ["de"]="Kap",
+ ["en"]="Cap",
+ ["fr"]="Cap",
+ ["it"]="Cap",
+ ["nl"]="Kap",
+ ["pe"]="Cap",
+ ["ro"]="Cap",
+ },
+ ["Capital"]={
+ ["cs"]="Kapitalky",
+ ["de"]="Versalien",
+ ["en"]="Capital",
+ ["fr"]="Capitale",
+ ["it"]="Maiuscolo",
+ ["nl"]="Kapitaal",
+ ["pe"]="Capital",
+ ["ro"]="Majuscula",
+ },
+ ["Character"]={
+ ["cs"]="Pismeno",
+ ["de"]="Buchstabe",
+ ["en"]="Character",
+ ["fr"]="Caratere",
+ ["it"]="Lettera",
+ ["nl"]="Letter",
+ ["pe"]="Character",
+ ["ro"]="Caracter",
+ },
+ ["Characters"]={
+ ["cs"]="Pismena",
+ ["de"]="Buchstaben",
+ ["en"]="Characters",
+ ["fr"]="Caracteres",
+ ["it"]="Lettere",
+ ["nl"]="Letters",
+ ["pe"]="Characters",
+ ["ro"]="Caractere",
+ },
+ ["CloseDocument"]={
+ ["cs"]="ZavritDokument",
+ ["de"]="SchliesseDokument",
+ ["en"]="CloseDocument",
+ ["fr"]="FermeDocument",
+ ["it"]="ChiudiDocumento",
+ ["nl"]="SluitDocument",
+ ["pe"]="بستن‌نوشتار",
+ ["ro"]="InchideDocument",
+ },
+ ["ExitViewer"]={
+ ["cs"]="UkoncitProhlizec",
+ ["de"]="BeendeViewer",
+ ["en"]="ExitViewer",
+ ["fr"]="SortVisualisateur",
+ ["it"]="EsciVisualizzatore",
+ ["nl"]="VerlaatViewer",
+ ["pe"]="خروج‌نمایشگر",
+ ["ro"]="IesireVizualizator",
+ },
+ ["FirstPage"]={
+ ["cs"]="PrvniStrana",
+ ["de"]="ErsteSeite",
+ ["en"]="FirstPage",
+ ["fr"]="PremierePage",
+ ["it"]="PrimaPagina",
+ ["nl"]="EerstePagina",
+ ["pe"]="صفحه‌اول",
+ ["ro"]="PrimaPagina",
+ },
+ ["FitHeight"]={
+ ["cs"]="FitHeight",
+ ["de"]="HoehePassend",
+ ["en"]="FitHeight",
+ ["fr"]="AjusteHauteur",
+ ["it"]="FitHeight",
+ ["nl"]="HoogtePassend",
+ ["pe"]="پرکردن‌ارتفاع",
+ ["ro"]="AjustatInaltime",
+ },
+ ["FitWidth"]={
+ ["cs"]="FitWidth",
+ ["de"]="BreitePassend",
+ ["en"]="FitWidth",
+ ["fr"]="AjusteLargeur",
+ ["it"]="FitWidth",
+ ["nl"]="BreedtePassend",
+ ["pe"]="پرکردن‌عرض",
+ ["ro"]="AjustatLatime",
+ },
+ ["GotoPage"]={
+ ["cs"]="JdiNaStranku",
+ ["de"]="GotoPage",
+ ["en"]="GotoPage",
+ ["fr"]="VaalaPage",
+ ["it"]="VaiAPagina",
+ ["nl"]="GaNaarPagina",
+ ["pe"]="برو‌به‌صفحه",
+ ["ro"]="LaPagina",
+ },
+ ["Greek"]={
+ ["cs"]="Recky",
+ ["de"]="Griechisch",
+ ["en"]="Greek",
+ ["fr"]="Grec",
+ ["it"]="Greco",
+ ["nl"]="Grieks",
+ ["pe"]="یونانی",
+ ["ro"]="Grec",
+ },
+ ["Help"]={
+ ["cs"]="Napoveda",
+ ["de"]="Hilfe",
+ ["en"]="Help",
+ ["fr"]="Aide",
+ ["it"]="Aiuto",
+ ["nl"]="Help",
+ ["pe"]="کمک",
+ ["ro"]="Ajutor",
+ },
+ ["HideField"]={
+ ["cs"]="SkryjPole",
+ ["de"]="VerbergeFeld",
+ ["en"]="HideField",
+ ["fr"]="CacheChamp",
+ ["it"]="NascondiCampo",
+ ["nl"]="VerbergVeld",
+ ["pe"]="پنهان‌میدان",
+ ["ro"]="AscundeCamp",
+ },
+ ["HideLayer"]={
+ ["cs"]="HideLayer",
+ ["de"]="HideLayer",
+ ["en"]="HideLayer",
+ ["fr"]="CacheCalque",
+ ["it"]="HideLayer",
+ ["nl"]="VerbergLaag",
+ ["pe"]="پنهان‌لایه",
+ ["ro"]="HideLayer",
+ },
+ ["Key"]={
+ ["cs"]="Klavesa",
+ ["de"]="Schluessel",
+ ["en"]="Key",
+ ["fr"]="Cle",
+ ["it"]="Tasto",
+ ["nl"]="Sleutel",
+ ["pe"]="کلید",
+ ["ro"]="Cheie",
+ },
+ ["LastPage"]={
+ ["cs"]="PosledniStrana",
+ ["de"]="LetzteSeite",
+ ["en"]="LastPage",
+ ["fr"]="DernierePage",
+ ["it"]="UltimaPagina",
+ ["nl"]="LaatstePagina",
+ ["pe"]="صفحه‌آخر",
+ ["ro"]="UltimaPagina",
+ },
+ ["LoadForm"]={
+ ["cs"]="NacistFormular",
+ ["de"]="LadeFormular",
+ ["en"]="LoadForm",
+ ["fr"]="ChargeForm",
+ ["it"]="CaricaForm",
+ ["nl"]="LaadFormulier",
+ ["pe"]="بارگذاشتن‌فرم",
+ ["ro"]="IncarcaFormular",
+ },
+ ["MONTH"]={
+ ["cs"]="MESIC",
+ ["de"]="MONAT",
+ ["en"]="MONTH",
+ ["fr"]="MOIS",
+ ["it"]="MESE",
+ ["nl"]="MAAND",
+ ["pe"]="ماه",
+ ["ro"]="LUNA",
+ },
+ ["New"]={
+ ["cs"]="Novy",
+ ["de"]="Neu",
+ ["en"]="New",
+ ["fr"]="Nouveau",
+ ["it"]="Nuovo",
+ ["nl"]="Nieuw",
+ ["pe"]="جدید",
+ ["ro"]="Nou",
+ },
+ ["NextJump"]={
+ ["cs"]="NasledujiciSkok",
+ ["de"]="NaechsterSprung",
+ ["en"]="NextJump",
+ ["fr"]="SautSuivant",
+ ["it"]="SaltoSuccessivo",
+ ["nl"]="VolgendeSprong",
+ ["pe"]="پرش‌بعدی",
+ ["ro"]="SaltUrmator",
+ },
+ ["NextPage"]={
+ ["cs"]="DalsiStrana",
+ ["de"]="FolgendeSeite",
+ ["en"]="NextPage",
+ ["fr"]="PageSuivante",
+ ["it"]="PaginaSuccessiva",
+ ["nl"]="VolgendePagina",
+ ["pe"]="صفحه‌بعدی",
+ ["ro"]="PaginaUrmatoare",
+ },
+ ["Numbers"]={
+ ["cs"]="Cisla",
+ ["de"]="Ziffern",
+ ["en"]="Numbers",
+ ["fr"]="Numeros",
+ ["it"]="Numeri",
+ ["nl"]="Cijfers",
+ ["pe"]="شماره‌ها",
+ ["ro"]="Numere",
+ },
+ ["OpenNamedDocument"]={
+ ["cs"]="OpenNamedDocument",
+ ["de"]="OpenNamedDocument",
+ ["en"]="OpenNamedDocument",
+ ["fr"]="OuvreDocumentNomme",
+ ["it"]="OpenNamedDocument",
+ ["nl"]="OpenDocumentOpNaam",
+ ["pe"]="بازکردن‌نوشتار‌ذخیره‌شده",
+ ["ro"]="OpenNamedDocument",
+ },
+ ["Paragraph"]={
+ ["cs"]="Odstavec",
+ ["de"]="Absatz",
+ ["en"]="Paragraph",
+ ["fr"]="Paragraphe",
+ ["it"]="Capoverso",
+ ["nl"]="Paragraaf",
+ ["pe"]="پاراگراف",
+ ["ro"]="Paragraf",
+ },
+ ["PauseMovie"]={
+ ["cs"]="PozastavitFilm",
+ ["de"]="PauseFilm",
+ ["en"]="PauseMovie",
+ ["fr"]="PauseFilm",
+ ["it"]="PausaFilm",
+ ["nl"]="PauzeerFilm",
+ ["pe"]="ایست‌فیلم",
+ ["ro"]="PauzaFilm",
+ },
+ ["PauseRendering"]={
+ ["cs"]="PauseRendering",
+ ["de"]="PauseRendering",
+ ["en"]="PauseRendering",
+ ["fr"]="PauseRendering",
+ ["it"]="PauseRendering",
+ ["nl"]="PauzeerRendering",
+ ["pe"]="توقف‌تعبیر",
+ ["ro"]="PauseRendering",
+ },
+ ["PauseSound"]={
+ ["cs"]="PozastavitZvuk",
+ ["de"]="PauseSound",
+ ["en"]="PauseSound",
+ ["fr"]="PauseSon",
+ ["it"]="PausaSuono",
+ ["nl"]="PauzeerGeluid",
+ ["pe"]="ایست‌صدا",
+ ["ro"]="PauzaSunet",
+ },
+ ["PreviousJump"]={
+ ["cs"]="PredchoziSkok",
+ ["de"]="VorigerSprung",
+ ["en"]="PreviousJump",
+ ["fr"]="SautPrecedent",
+ ["it"]="SaltoPrecedente",
+ ["nl"]="VorigeSprong",
+ ["pe"]="پرش‌قبلی",
+ ["ro"]="SaltPrecedent",
+ },
+ ["PreviousPage"]={
+ ["cs"]="PredchoziStrana",
+ ["de"]="VorigeSeite",
+ ["en"]="PreviousPage",
+ ["fr"]="PagePrecedente",
+ ["it"]="PaginaPrecedente",
+ ["nl"]="VorigePagina",
+ ["pe"]="صفحه‌قبلی",
+ ["ro"]="PaginaPrecedenta",
+ },
+ ["PrintDocument"]={
+ ["cs"]="VytisknoutDokument",
+ ["de"]="DruckeDokument",
+ ["en"]="PrintDocument",
+ ["fr"]="ImprimeDocument",
+ ["it"]="StampaDocumento",
+ ["nl"]="PrintDocument",
+ ["pe"]="چاپ‌نوشتار",
+ ["ro"]="TiparesteDocument",
+ },
+ ["Query"]={
+ ["cs"]="Query",
+ ["de"]="Query",
+ ["en"]="Query",
+ ["fr"]="Query",
+ ["it"]="Richiesta",
+ ["nl"]="RaadpleegDocument",
+ ["pe"]="پرسش",
+ ["ro"]="Query",
+ },
+ ["QueryAgain"]={
+ ["cs"]="QueryAgain",
+ ["de"]="QueryAgain",
+ ["en"]="QueryAgain",
+ ["fr"]="QueryAgain",
+ ["it"]="RinnovaRichiesta",
+ ["nl"]="HerhaalRaadplegen",
+ ["pe"]="پرسش‌دوباره",
+ ["ro"]="QueryAgain",
+ },
+ ["ResetForm"]={
+ ["cs"]="ResetFormulare",
+ ["de"]="ZuruecksetzenFormular",
+ ["en"]="ResetForm",
+ ["fr"]="RazForm",
+ ["it"]="ReimpostaForm",
+ ["nl"]="ResetFormulier",
+ ["pe"]="دوباره‌نشانی‌فرم",
+ ["ro"]="ResetareFormular",
+ },
+ ["ResumeMovie"]={
+ ["cs"]="PokracovatFilm",
+ ["de"]="FortsetzenFilm",
+ ["en"]="ResumeMovie",
+ ["fr"]="ReprendFilm",
+ ["it"]="RiprendiFilm",
+ ["nl"]="HervatFilm",
+ ["pe"]="ادامه‌فیلم",
+ ["ro"]="RepornesteFilm",
+ },
+ ["ResumeRendering"]={
+ ["cs"]="ResumeRendering",
+ ["de"]="ResumeRendering",
+ ["en"]="ResumeRendering",
+ ["fr"]="ResumeRendering",
+ ["it"]="ResumeRendering",
+ ["nl"]="HervatRendering",
+ ["pe"]="ادامه‌تعبیر",
+ ["ro"]="ResumeRendering",
+ },
+ ["ResumeSound"]={
+ ["cs"]="PokracovatZvuk",
+ ["de"]="ResumeSound",
+ ["en"]="ResumeSound",
+ ["fr"]="ReprendSon",
+ ["it"]="RiprendiSuono",
+ ["nl"]="HervatGeluid",
+ ["pe"]="ادامه‌صدا",
+ ["ro"]="RepornesteSunet",
+ },
+ ["Romannumerals"]={
+ ["cs"]="Rimskecislice",
+ ["de"]="Roemischezahlen",
+ ["en"]="Romannumerals",
+ ["fr"]="Chiffresromains",
+ ["it"]="Numeriromani",
+ ["nl"]="Romeins",
+ ["pe"]="اعداد‌بزرگ‌لاتین",
+ ["ro"]="Numereromane",
+ },
+ ["SaveDocument"]={
+ ["cs"]="UlozitDokument",
+ ["de"]="SpeichereDokument",
+ ["en"]="SaveDocument",
+ ["fr"]="SauvegardeDocument",
+ ["it"]="SalvaDocumento",
+ ["nl"]="BewaarDocument",
+ ["pe"]="ذخیره‌نوشتار",
+ ["ro"]="SalvareDocument",
+ },
+ ["SaveForm"]={
+ ["cs"]="UlozitFormular",
+ ["de"]="SpeicheFormular",
+ ["en"]="SaveForm",
+ ["fr"]="SauvegardeForm",
+ ["it"]="SalvaForm",
+ ["nl"]="BewaarFormulier",
+ ["pe"]="ذخیره‌فرم",
+ ["ro"]="SalveazaFormular",
+ },
+ ["SaveNamedDocument"]={
+ ["cs"]="SaveNamedDocument",
+ ["de"]="SaveNamedDocument",
+ ["en"]="SaveNamedDocument",
+ ["fr"]="SauvegardeDocumentNomme",
+ ["it"]="SaveNamedDocument",
+ ["nl"]="BewaarDocumentOpNaam",
+ ["pe"]="ذخیره‌نوشتار‌بانام",
+ ["ro"]="SaveNamedDocument",
+ },
+ ["SearchAgain"]={
+ ["cs"]="HledatZnovu",
+ ["de"]="WeiterSuchen",
+ ["en"]="SearchAgain",
+ ["fr"]="RechercheSuivant",
+ ["it"]="CercaAncora",
+ ["nl"]="HerhaalZoeken",
+ ["pe"]="جستجوی‌دوباره",
+ ["ro"]="CautaDinNou",
+ },
+ ["SearchDocument"]={
+ ["cs"]="ProhledatDokument",
+ ["de"]="DokumentDurchsuchen",
+ ["en"]="SearchDocument",
+ ["fr"]="RechercheDocument",
+ ["it"]="CercaDocumento",
+ ["nl"]="DoorzoekDocument",
+ ["pe"]="جستجوی‌نوشتار",
+ ["ro"]="CautaDocument",
+ },
+ ["ShowBookmarks"]={
+ ["cs"]="UkazZalozky",
+ ["de"]="ShowBookmarks",
+ ["en"]="ShowBookmarks",
+ ["fr"]="ShowBookmarks",
+ ["it"]="MostraSegnalibro",
+ ["nl"]="ShowBookmarks",
+ ["pe"]="نمایش‌چوبخط",
+ ["ro"]="ShowBookmarks",
+ },
+ ["ShowField"]={
+ ["cs"]="UkazPole",
+ ["de"]="ZeigeFeld",
+ ["en"]="ShowField",
+ ["fr"]="MontreChamp",
+ ["it"]="MostraCampo",
+ ["nl"]="ToonVeld",
+ ["pe"]="نمایش‌میدان",
+ ["ro"]="AfiseazaCamp",
+ },
+ ["ShowThumbs"]={
+ ["cs"]="UkazNahledy",
+ ["de"]="ShowThumbs",
+ ["en"]="ShowThumbs",
+ ["fr"]="ShowThumbs",
+ ["it"]="MostraThumbs",
+ ["nl"]="ShowThumbs",
+ ["pe"]="نمایش‌شصت",
+ ["ro"]="ShowThumbs",
+ },
+ ["StartMovie"]={
+ ["cs"]="SpustitFilm",
+ ["de"]="StartFilm",
+ ["en"]="StartMovie",
+ ["fr"]="DemarreFilm",
+ ["it"]="IniziaFilm",
+ ["nl"]="StartFilm",
+ ["pe"]="شروع‌فیلم",
+ ["ro"]="StartFilm",
+ },
+ ["StartRendering"]={
+ ["cs"]="StartRendering",
+ ["de"]="StartRendering",
+ ["en"]="StartRendering",
+ ["fr"]="StartRendering",
+ ["it"]="StartRendering",
+ ["nl"]="StartRendering",
+ ["pe"]="شروع‌تعبیر",
+ ["ro"]="StartRendering",
+ },
+ ["StartSound"]={
+ ["cs"]="StartZvuk",
+ ["de"]="StartSound",
+ ["en"]="StartSound",
+ ["fr"]="DemarreSon",
+ ["it"]="IniziaSuono",
+ ["nl"]="StartGeluid",
+ ["pe"]="شروع‌صدا",
+ ["ro"]="StartSunet",
+ },
+ ["StopMovie"]={
+ ["cs"]="ZastavitFilm",
+ ["de"]="StopFilm",
+ ["en"]="StopMovie",
+ ["fr"]="StoppeFilm",
+ ["it"]="FermaFilm",
+ ["nl"]="StopFilm",
+ ["pe"]="پایان‌فیلم",
+ ["ro"]="StopFilm",
+ },
+ ["StopRendering"]={
+ ["cs"]="StopRendering",
+ ["de"]="StopRendering",
+ ["en"]="StopRendering",
+ ["fr"]="StopRendering",
+ ["it"]="StopRendering",
+ ["nl"]="StopRendering",
+ ["pe"]="پایان‌تعبیر",
+ ["ro"]="StopRendering",
+ },
+ ["StopSound"]={
+ ["cs"]="StopZvuk",
+ ["de"]="StopSound",
+ ["en"]="StopSound",
+ ["fr"]="StoppeSon",
+ ["it"]="FermaSuono",
+ ["nl"]="StopGeluid",
+ ["pe"]="پایان‌صدا",
+ ["ro"]="StopSunet",
+ },
+ ["SubmitForm"]={
+ ["cs"]="PoslatFormular",
+ ["de"]="VersendeFormular",
+ ["en"]="SubmitForm",
+ ["fr"]="SoumettreForm",
+ ["it"]="MandaForm",
+ ["nl"]="VerzendFormulier",
+ ["pe"]="تسلیم‌فرم",
+ ["ro"]="TrimiteFormular",
+ },
+ ["ToggleLayer"]={
+ ["cs"]="ToggleLayer",
+ ["de"]="ToggleLayer",
+ ["en"]="ToggleLayer",
+ ["fr"]="ToggleLayer",
+ ["it"]="ToggleLayer",
+ ["nl"]="WisselLaag",
+ ["pe"]="تغییرلایه",
+ ["ro"]="ToggleLayer",
+ },
+ ["ToggleViewer"]={
+ ["cs"]="ZmenitProhlizec",
+ ["de"]="WechseleViewer",
+ ["en"]="ToggleViewer",
+ ["fr"]="ChangeVisualisateur",
+ ["it"]="ScambiaVisualizzatore",
+ ["nl"]="WisselViewer",
+ ["pe"]="تغییرنمایشگر",
+ ["ro"]="SchimbaVizualizator",
+ },
+ ["URL"]={
+ ["cs"]="URL",
+ ["de"]="URL",
+ ["en"]="URL",
+ ["fr"]="URL",
+ ["it"]="URL",
+ ["nl"]="URL",
+ ["pe"]="URL",
+ ["ro"]="URL",
+ },
+ ["VideLayer"]={
+ ["cs"]="VideLayer",
+ ["de"]="VideLayer",
+ ["en"]="VideLayer",
+ ["fr"]="VideLayer",
+ ["it"]="VideLayer",
+ ["nl"]="ToonLaag",
+ ["pe"]="VideLayer",
+ ["ro"]="VideLayer",
+ },
+ ["ViewerHelp"]={
+ ["cs"]="NapovedaProhlizece",
+ ["de"]="ViewerHilfe",
+ ["en"]="ViewerHelp",
+ ["fr"]="AideVisualisateur",
+ ["it"]="AiutoVisualizzatore",
+ ["nl"]="ViewerHelp",
+ ["pe"]="کمک‌نمایشگر",
+ ["ro"]="AjutorVizualizator",
+ },
+ ["WEEKDAY"]={
+ ["cs"]="VSEDNIDEN",
+ ["de"]="WOCHENTAG",
+ ["en"]="WEEKDAY",
+ ["fr"]="JOURSEMAINE",
+ ["it"]="GIORNOSETTIMANA",
+ ["nl"]="WEEKDAG",
+ ["pe"]="روزهفته",
+ ["ro"]="ZISAPTAMANA",
+ },
+ ["WORD"]={
+ ["cs"]="SLOVO",
+ ["de"]="WORT",
+ ["en"]="WORD",
+ ["fr"]="MOT",
+ ["it"]="PAROLA",
+ ["nl"]="WOORD",
+ ["pe"]="کلمه",
+ ["ro"]="CUVANT",
+ },
+ ["WORDS"]={
+ ["cs"]="SLOVA",
+ ["de"]="WOERTER",
+ ["en"]="WORDS",
+ ["fr"]="MOTS",
+ ["it"]="PAROLE",
+ ["nl"]="WOORDEN",
+ ["pe"]="WORDS",
+ ["ro"]="CUVINTE",
+ },
+ ["Word"]={
+ ["cs"]="Slovo",
+ ["de"]="Wort",
+ ["en"]="Word",
+ ["fr"]="Mot",
+ ["it"]="Parola",
+ ["nl"]="Woord",
+ ["pe"]="Word",
+ ["ro"]="Cuvant",
+ },
+ ["Words"]={
+ ["cs"]="Slova",
+ ["de"]="Woerter",
+ ["en"]="Words",
+ ["fr"]="Mots",
+ ["it"]="Parole",
+ ["nl"]="Woorden",
+ ["pe"]="Words",
+ ["ro"]="Cuvinte",
+ },
+ ["abbreviation"]={
+ ["cs"]="zkratka",
+ ["de"]="abkuerzung",
+ ["en"]="abbreviation",
+ ["fr"]="abreviation",
+ ["it"]="abbreviazione",
+ ["nl"]="afkorting",
+ ["pe"]="اختصار",
+ ["ro"]="abreviere",
+ },
+ ["abbreviations"]={
+ ["cs"]="zkratky",
+ ["de"]="abkuerzungen",
+ ["en"]="abbreviations",
+ ["fr"]="abreviations",
+ ["it"]="abbreviazioni",
+ ["nl"]="afkortingen",
+ ["pe"]="اختصارات",
+ ["ro"]="abrevieri",
+ },
+ ["absolute"]={
+ ["cs"]="absolutni",
+ ["de"]="absolut",
+ ["en"]="absolute",
+ ["fr"]="absolute",
+ ["it"]="assoluto",
+ ["nl"]="absoluut",
+ ["pe"]="قطعی",
+ ["ro"]="absolut",
+ },
+ ["action"]={
+ ["cs"]="akce",
+ ["de"]="aktion",
+ ["en"]="action",
+ ["fr"]="action",
+ ["it"]="azione",
+ ["nl"]="actie",
+ ["pe"]="کنش",
+ ["ro"]="actiune",
+ },
+ ["after"]={
+ ["cs"]="po",
+ ["de"]="nach",
+ ["en"]="after",
+ ["fr"]="apres",
+ ["it"]="dopo",
+ ["nl"]="na",
+ ["pe"]="بعداز",
+ ["ro"]="dupa",
+ },
+ ["all"]={
+ ["cs"]="vse",
+ ["de"]="alles",
+ ["en"]="all",
+ ["fr"]="tout",
+ ["it"]="tutti",
+ ["nl"]="alles",
+ ["pe"]="همه",
+ ["ro"]="tot",
+ },
+ ["alphabetic"]={
+ ["en"]="alphabetic",
+ },
+ ["always"]={
+ ["cs"]="vzdy",
+ ["de"]="immer",
+ ["en"]="always",
+ ["fr"]="toujours",
+ ["it"]="sempre",
+ ["nl"]="altijd",
+ ["pe"]="همواره",
+ ["ro"]="totdeauna",
+ },
+ ["and"]={
+ ["de"]="und",
+ ["en"]="and",
+ ["nl"]="en",
+ },
+ ["answerarea"]={
+ ["cs"]="answerarea",
+ ["de"]="answerarea",
+ ["en"]="answerarea",
+ ["fr"]="answerarea",
+ ["it"]="answerarea",
+ ["nl"]="antwoordgebied",
+ ["pe"]="answerarea",
+ ["ro"]="answerarea",
+ },
+ ["appendices"]={
+ ["cs"]="dodatky",
+ ["de"]="anhaenge",
+ ["en"]="appendices",
+ ["fr"]="annexes",
+ ["it"]="appendici",
+ ["nl"]="bijlagen",
+ ["pe"]="پیوستها",
+ ["ro"]="apendixuri",
+ },
+ ["appendix"]={
+ ["cs"]="dodatek",
+ ["de"]="anhang",
+ ["en"]="appendix",
+ ["fr"]="annexe",
+ ["it"]="appendice",
+ ["nl"]="bijlage",
+ ["pe"]="پیوست",
+ ["ro"]="apendix",
+ },
+ ["april"]={
+ ["cs"]="duben",
+ ["de"]="april",
+ ["en"]="april",
+ ["fr"]="avril",
+ ["it"]="aprile",
+ ["nl"]="april",
+ ["pe"]="آوریل",
+ ["ro"]="aprilie",
+ },
+ ["atleftmargin"]={
+ ["cs"]="atleftmargin",
+ ["de"]="atleftmargin",
+ ["en"]="atleftmargin",
+ ["fr"]="atleftmargin",
+ ["it"]="atleftmargin",
+ ["nl"]="oplinkermarge",
+ ["pe"]="درحاشیه‌چپ",
+ ["ro"]="atleftmargin",
+ },
+ ["atmargin"]={
+ ["cs"]="naokraji",
+ ["de"]="amrand",
+ ["en"]="atmargin",
+ ["fr"]="alamarge",
+ ["it"]="almargine",
+ ["nl"]="opmarge",
+ ["pe"]="درحاشیه",
+ ["ro"]="lamargine",
+ },
+ ["atpage"]={
+ ["cs"]="nastrance",
+ ["de"]="aufseite",
+ ["en"]="atpage",
+ ["fr"]="alapage",
+ ["it"]="apagina",
+ ["nl"]="oppagina",
+ ["pe"]="درصفحه",
+ ["ro"]="lapagina",
+ },
+ ["atrightmargin"]={
+ ["cs"]="atrightmargin",
+ ["de"]="atrightmargin",
+ ["en"]="atrightmargin",
+ ["fr"]="atrightmargin",
+ ["it"]="atrightmargin",
+ ["nl"]="oprechtermarge",
+ ["pe"]="درحاشیه‌راست",
+ ["ro"]="atrightmargin",
+ },
+ ["attachment"]={
+ ["en"]="attachment",
+ ["nl"]="aanhangsel",
+ },
+ ["august"]={
+ ["cs"]="srpen",
+ ["de"]="august",
+ ["en"]="august",
+ ["fr"]="août",
+ ["it"]="agosto",
+ ["nl"]="augustus",
+ ["pe"]="آگوست",
+ ["ro"]="august",
+ },
+ ["author"]={
+ ["cs"]="autor",
+ ["de"]="autor",
+ ["en"]="author",
+ ["fr"]="auteur",
+ ["it"]="autore",
+ ["nl"]="auteur",
+ ["ro"]="autor",
+ },
+ ["auto"]={
+ ["cs"]="auto",
+ ["de"]="auto",
+ ["en"]="auto",
+ ["fr"]="auto",
+ ["it"]="auto",
+ ["nl"]="auto",
+ ["pe"]="خودکار",
+ ["ro"]="auto",
+ },
+ ["autointro"]={
+ ["cs"]="autouvod",
+ ["de"]="autointro",
+ ["en"]="autointro",
+ ["fr"]="autointro",
+ ["it"]="autointro",
+ ["nl"]="autointro",
+ ["pe"]="پیشگفتارخودکار",
+ ["ro"]="autointro",
+ },
+ ["autopunctuation"]={
+ ["en"]="autopunctuation",
+ },
+ ["back"]={
+ ["cs"]="zpet",
+ ["de"]="zurueck",
+ ["en"]="back",
+ ["fr"]="retour",
+ ["it"]="dietro",
+ ["nl"]="terug",
+ ["pe"]="پشت",
+ ["ro"]="inapot",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پس‌زمینه",
+ ["ro"]="fundal",
+ },
+ ["backmatter"]={
+ ["cs"]="epilogy",
+ ["de"]="epiloge",
+ ["en"]="backmatter",
+ ["fr"]="epilogue",
+ ["it"]="postambolo",
+ ["nl"]="uitleidingen",
+ ["pe"]="پس‌مطلب",
+ ["ro"]="epilogul",
+ },
+ ["backpart"]={
+ ["cs"]="epilog",
+ ["de"]="epilog",
+ ["en"]="backpart",
+ ["fr"]="postface",
+ ["it"]="postfazione",
+ ["nl"]="uitleiding",
+ ["pe"]="پس‌قسمت",
+ ["ro"]="epilog",
+ },
+ ["backspace"]={
+ ["cs"]="zpetnamezera",
+ ["de"]="rumpfspatium",
+ ["en"]="backspace",
+ ["fr"]="retourarriere",
+ ["it"]="backspace",
+ ["nl"]="rugwit",
+ ["pe"]="فضای‌پشت",
+ ["ro"]="spatiuspate",
+ },
+ ["backward"]={
+ ["cs"]="zpet",
+ ["de"]="rueckwaerts",
+ ["en"]="backward",
+ ["fr"]="retourarriere",
+ ["it"]="indietro",
+ ["nl"]="achteruit",
+ ["pe"]="عقب‌گرد",
+ ["ro"]="inapoi",
+ },
+ ["bbl"]={
+ ["en"]="bbl",
+ },
+ ["before"]={
+ ["cs"]="pred",
+ ["de"]="vor",
+ ["en"]="before",
+ ["fr"]="avant",
+ ["it"]="prima",
+ ["nl"]="voor",
+ ["pe"]="قبل‌از",
+ ["ro"]="inainte",
+ },
+ ["begin"]={
+ ["en"]="begin",
+ ["nl"]="begin",
+ },
+ ["bib"]={
+ ["en"]="bib",
+ },
+ ["big"]={
+ ["cs"]="velke",
+ ["de"]="gross",
+ ["en"]="big",
+ ["fr"]="grand",
+ ["it"]="grande",
+ ["nl"]="groot",
+ ["pe"]="بزرگ",
+ ["ro"]="mare",
+ },
+ ["bigbodyfont"]={
+ ["cs"]="bigbodyfont",
+ ["de"]="bigbodyfont",
+ ["en"]="bigbodyfont",
+ ["fr"]="grandepolicecorp",
+ ["it"]="grossofontdeltesto",
+ ["nl"]="grootkorps",
+ ["pe"]="قلم‌بدنه‌بزرگ",
+ ["ro"]="bigbodyfont",
+ },
+ ["bigger"]={
+ ["en"]="bigger",
+ ["nl"]="groter",
+ },
+ ["bigpreference"]={
+ ["cs"]="vysokapriorita",
+ ["de"]="grosszuegig",
+ ["en"]="bigpreference",
+ ["fr"]="grandepreference",
+ ["it"]="grandepreferenza",
+ ["nl"]="grotevoorkeur",
+ ["pe"]="اولویت‌بزرگ",
+ ["ro"]="preferintamare",
+ },
+ ["blank"]={
+ ["cs"]="prazdny",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blank",
+ },
+ ["block"]={
+ ["en"]="block",
+ },
+ ["blockquote"]={
+ ["cs"]="blockquote",
+ ["de"]="blockquote",
+ ["en"]="blockquote",
+ ["fr"]="blockquote",
+ ["it"]="blockquote",
+ ["nl"]="blokcitaat",
+ ["pe"]="نقل‌بلوک",
+ ["ro"]="blockquote",
+ },
+ ["bodymatter"]={
+ ["cs"]="hlavnicasti",
+ ["de"]="haupttexte",
+ ["en"]="bodymatter",
+ ["fr"]="texteprincipal",
+ ["it"]="testiprincipali",
+ ["nl"]="hoofdteksten",
+ ["pe"]="مطلب‌بدنه",
+ ["ro"]="principalul",
+ },
+ ["bodypart"]={
+ ["cs"]="hlavnicast",
+ ["de"]="haupttext",
+ ["en"]="bodypart",
+ ["fr"]="corpsdetexte",
+ ["it"]="testoprincipale",
+ ["nl"]="hoofdtekst",
+ ["pe"]="قسمت‌بدنه",
+ ["ro"]="principal",
+ },
+ ["bold"]={
+ ["cs"]="tucne",
+ ["de"]="fett",
+ ["en"]="bold",
+ ["fr"]="gras",
+ ["it"]="grassetto",
+ ["nl"]="vet",
+ ["pe"]="مشکی",
+ ["ro"]="aldin",
+ },
+ ["bolditalic"]={
+ ["cs"]="tucnekurzivni",
+ ["de"]="fettitalic",
+ ["en"]="bolditalic",
+ ["fr"]="italiquegras",
+ ["it"]="grassettocorsivo",
+ ["nl"]="vetitalic",
+ ["pe"]="ایتالیک‌مشکی",
+ ["ro"]="aldinitalic",
+ },
+ ["boldslanted"]={
+ ["cs"]="tucnesklonene",
+ ["de"]="fettgeneigt",
+ ["en"]="boldslanted",
+ ["fr"]="inclinegras",
+ ["it"]="grassettoinclinato",
+ ["nl"]="vetschuin",
+ ["pe"]="خوابیده‌مشکی",
+ ["ro"]="aldininclinat",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["both"]={
+ ["cs"]="obe",
+ ["de"]="beide",
+ ["en"]="both",
+ ["fr"]="lesdeux",
+ ["it"]="entrambi",
+ ["nl"]="beide",
+ ["pe"]="هردو",
+ ["ro"]="ambele",
+ },
+ ["bothtext"]={
+ ["en"]="bothtext",
+ },
+ ["bottom"]={
+ ["cs"]="spodek",
+ ["de"]="unten",
+ ["en"]="bottom",
+ ["fr"]="inf",
+ ["it"]="fondo",
+ ["nl"]="onder",
+ ["pe"]="پایین",
+ ["ro"]="subsol",
+ },
+ ["box"]={
+ ["en"]="box",
+ },
+ ["brief"]={
+ ["cs"]="brief",
+ ["de"]="brief",
+ ["en"]="brief",
+ ["fr"]="brief",
+ ["it"]="brief",
+ ["nl"]="brief",
+ ["pe"]="مختصر",
+ ["ro"]="brief",
+ },
+ ["broad"]={
+ ["cs"]="siroky",
+ ["de"]="breit",
+ ["en"]="broad",
+ ["fr"]="large",
+ ["it"]="ampio",
+ ["nl"]="ruim",
+ ["pe"]="گسترده",
+ ["ro"]="broad",
+ },
+ ["buffer"]={
+ ["cs"]="buffer",
+ ["de"]="puffer",
+ ["en"]="buffer",
+ ["fr"]="buffer",
+ ["it"]="buffer",
+ ["nl"]="buffer",
+ ["pe"]="بافر",
+ ["ro"]="buffer",
+ },
+ ["by"]={
+ ["cs"]="skrz",
+ ["de"]="pro",
+ ["en"]="by",
+ ["fr"]="par",
+ ["it"]="da",
+ ["nl"]="per",
+ ["pe"]="بوسیله",
+ ["ro"]="de",
+ },
+ ["calligraphic"]={
+ ["cs"]="kaligraficke",
+ ["de"]="kalligraphie",
+ ["en"]="calligraphic",
+ ["fr"]="calligraphique",
+ ["it"]="calligrafico",
+ ["nl"]="calligrafie",
+ ["pe"]="خوشنویسی",
+ ["ro"]="caligrafic",
+ },
+ ["camel"]={
+ ["en"]="camel",
+ },
+ ["cap"]={
+ ["cs"]="kap",
+ ["de"]="kap",
+ ["en"]="cap",
+ ["fr"]="cap",
+ ["it"]="cap",
+ ["nl"]="kap",
+ ["pe"]="cap",
+ ["ro"]="cap",
+ },
+ ["capital"]={
+ ["cs"]="kapitalky",
+ ["de"]="versalien",
+ ["en"]="capital",
+ ["fr"]="capitale",
+ ["it"]="maiuscolo",
+ ["nl"]="kapitaal",
+ ["pe"]="capital",
+ ["ro"]="majuscula",
+ },
+ ["center"]={
+ ["cs"]="center",
+ ["de"]="center",
+ ["en"]="center",
+ ["fr"]="center",
+ ["it"]="center",
+ ["nl"]="centreer",
+ ["pe"]="مرکز",
+ ["ro"]="center",
+ },
+ ["centerlast"]={
+ ["en"]="centerlast",
+ },
+ ["chapter"]={
+ ["cs"]="kapitola",
+ ["de"]="kapitel",
+ ["en"]="chapter",
+ ["fr"]="chapitre",
+ ["it"]="capitolo",
+ ["nl"]="hoofdstuk",
+ ["pe"]="فصل",
+ ["ro"]="capitol",
+ },
+ ["character"]={
+ ["cs"]="pismeno",
+ ["de"]="buchstabe",
+ ["en"]="character",
+ ["fr"]="caractere",
+ ["it"]="lettera",
+ ["nl"]="letter",
+ ["pe"]="حرف",
+ ["ro"]="caracter",
+ },
+ ["characters"]={
+ ["cs"]="pismena",
+ ["de"]="buchstaben",
+ ["en"]="characters",
+ ["fr"]="caracteres",
+ ["it"]="lettere",
+ ["nl"]="letters",
+ ["pe"]="حرفها",
+ ["ro"]="caractere",
+ },
+ ["chemical"]={
+ ["en"]="chemical",
+ },
+ ["chemicals"]={
+ ["en"]="chemicals",
+ },
+ ["chemistry"]={
+ ["en"]="chemistry",
+ ["nl"]="chemie",
+ },
+ ["cite"]={
+ ["en"]="cite",
+ },
+ ["color"]={
+ ["cs"]="barevne",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["column"]={
+ ["cs"]="column",
+ ["de"]="column",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["columns"]={
+ ["cs"]="sloupce",
+ ["de"]="spalten",
+ ["en"]="columns",
+ ["fr"]="colonnes",
+ ["it"]="colonne",
+ ["nl"]="kolommen",
+ ["pe"]="ستونها",
+ ["ro"]="coloane",
+ },
+ ["combination"]={
+ ["en"]="combination",
+ },
+ ["command"]={
+ ["cs"]="prikaz",
+ ["de"]="befehl",
+ ["en"]="command",
+ ["fr"]="commande",
+ ["it"]="comando",
+ ["nl"]="commando",
+ ["pe"]="فرمان",
+ ["ro"]="comanda",
+ },
+ ["commands"]={
+ ["cs"]="prikazy",
+ ["de"]="befehle",
+ ["en"]="commands",
+ ["fr"]="commandes",
+ ["it"]="comandi",
+ ["nl"]="commandos",
+ ["pe"]="فرمانها",
+ ["ro"]="comenzi",
+ },
+ ["comment"]={
+ ["cs"]="komentar",
+ ["de"]="kommentar",
+ ["en"]="comment",
+ ["fr"]="commentaire",
+ ["it"]="commento",
+ ["nl"]="commentaar",
+ ["pe"]="توضیح",
+ ["ro"]="comentariu",
+ },
+ ["component"]={
+ ["cs"]="komponenta",
+ ["de"]="komponente",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="componente",
+ ["nl"]="onderdeel",
+ ["pe"]="مولفه",
+ ["ro"]="componenta",
+ },
+ ["compressseparator"]={
+ ["en"]="compressseparator",
+ },
+ ["concept"]={
+ ["cs"]="koncept",
+ ["de"]="konzept",
+ ["en"]="concept",
+ ["fr"]="concept",
+ ["it"]="concetto",
+ ["nl"]="concept",
+ ["pe"]="مفهوم",
+ ["ro"]="concept",
+ },
+ ["construction"]={
+ ["en"]="construction",
+ },
+ ["content"]={
+ ["cs"]="obsah",
+ ["de"]="inhalt",
+ ["en"]="content",
+ ["fr"]="contenu",
+ ["it"]="indice",
+ ["nl"]="inhoud",
+ ["pe"]="محتوا",
+ ["ro"]="cuprins",
+ },
+ ["contents"]={
+ ["cs"]="obsah",
+ ["de"]="inhalte",
+ ["en"]="contents",
+ ["fr"]="contenus",
+ ["it"]="indici",
+ ["nl"]="inhouden",
+ ["pe"]="محتویات",
+ ["ro"]="cuprinsuri",
+ },
+ ["continue"]={
+ ["cs"]="pokracovat",
+ ["de"]="fortsetzten",
+ ["en"]="continue",
+ ["fr"]="continue",
+ ["it"]="continua",
+ ["nl"]="verder",
+ ["pe"]="ادامه",
+ ["ro"]="continuu",
+ },
+ ["continued"]={
+ ["en"]="continued",
+ ["nl"]="vervolgd",
+ },
+ ["controls"]={
+ ["cs"]="controls",
+ ["de"]="controls",
+ ["en"]="controls",
+ ["fr"]="controles",
+ ["it"]="controlli",
+ ["nl"]="sturing",
+ ["pe"]="کنترلها",
+ ["ro"]="controale",
+ },
+ ["conversion"]={
+ ["cs"]="konverze",
+ ["de"]="konversion",
+ ["en"]="conversion",
+ ["fr"]="conversion",
+ ["it"]="coversione",
+ ["nl"]="conversie",
+ ["pe"]="تبدیل",
+ ["ro"]="conversie",
+ },
+ ["current"]={
+ ["cs"]="aktualni",
+ ["de"]="aktuell",
+ ["en"]="current",
+ ["fr"]="courant",
+ ["it"]="corrente",
+ ["nl"]="huidige",
+ ["pe"]="جاری",
+ ["ro"]="curent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضای‌برش",
+ ["ro"]="cutspace",
+ },
+ ["dataset"]={
+ ["en"]="dataset",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["day"]={
+ ["cs"]="den",
+ ["de"]="tag",
+ ["en"]="day",
+ ["fr"]="jour",
+ ["it"]="giorno",
+ ["nl"]="dag",
+ ["pe"]="روز",
+ ["ro"]="zi",
+ },
+ ["december"]={
+ ["cs"]="prosinec",
+ ["de"]="dezember",
+ ["en"]="december",
+ ["fr"]="decembre",
+ ["it"]="dicembre",
+ ["nl"]="december",
+ ["pe"]="دسامبر",
+ ["ro"]="decembrie",
+ },
+ ["default"]={
+ ["cs"]="implicitni",
+ ["de"]="default",
+ ["en"]="default",
+ ["fr"]="defaut",
+ ["it"]="implicito",
+ ["nl"]="default",
+ ["pe"]="پیش‌فرض",
+ ["ro"]="implicit",
+ },
+ ["depth"]={
+ ["cs"]="podlehloubky",
+ ["de"]="tiefe",
+ ["en"]="depth",
+ ["fr"]="profondeur",
+ ["it"]="profondita",
+ ["nl"]="diepte",
+ ["pe"]="عمق",
+ ["ro"]="adancime",
+ },
+ ["description"]={
+ ["cs"]="popis",
+ ["de"]="beschreibung",
+ ["en"]="description",
+ ["fr"]="description",
+ ["it"]="descrizione",
+ ["nl"]="doordefinitie",
+ ["pe"]="شرح",
+ ["ro"]="descriere",
+ },
+ ["disable"]={
+ ["cs"]="zablokovat",
+ ["de"]="sperren",
+ ["en"]="disable",
+ ["fr"]="desactiver",
+ ["it"]="disattiva",
+ ["nl"]="blokkeer",
+ ["pe"]="ناتوان",
+ ["ro"]="dezactivat",
+ },
+ ["display"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="display",
+ ["fr"]="affichage",
+ ["it"]="schermo",
+ ["nl"]="scherm",
+ ["pe"]="نمایش",
+ ["ro"]="display",
+ },
+ ["dot"]={
+ ["cs"]="tecka",
+ ["de"]="punkt",
+ ["en"]="dot",
+ ["fr"]="point",
+ ["it"]="punto",
+ ["nl"]="punt",
+ ["pe"]="نقطه",
+ ["ro"]="punct",
+ },
+ ["doublesided"]={
+ ["cs"]="dvoustranny",
+ ["de"]="doppelseitig",
+ ["en"]="doublesided",
+ ["fr"]="rectoverso",
+ ["it"]="doppiafaccia",
+ ["nl"]="dubbelzijdig",
+ ["pe"]="دورو",
+ ["ro"]="douafete",
+ },
+ ["down"]={
+ ["en"]="down",
+ ["nl"]="omlaag",
+ },
+ ["each"]={
+ ["cs"]="kazdy",
+ ["de"]="jede",
+ ["en"]="each",
+ ["fr"]="chaque",
+ ["it"]="ogni",
+ ["nl"]="elk",
+ ["pe"]="هر",
+ ["ro"]="fiecare",
+ },
+ ["edge"]={
+ ["cs"]="hrana",
+ ["de"]="kante",
+ ["en"]="edge",
+ ["fr"]="bord",
+ ["it"]="bordo",
+ ["nl"]="rand",
+ ["pe"]="لبه",
+ ["ro"]="bordura",
+ },
+ ["embed"]={
+ ["en"]="embed",
+ ["nl"]="sluitin",
+ },
+ ["empty"]={
+ ["cs"]="prazdne",
+ ["de"]="leer",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="vuoto",
+ ["nl"]="leeg",
+ ["pe"]="تهی",
+ ["ro"]="gol",
+ },
+ ["end"]={
+ ["en"]="end",
+ ["nl"]="eind",
+ },
+ ["endnote"]={
+ ["cs"]="endnote",
+ ["de"]="endnote",
+ ["en"]="endnote",
+ ["fr"]="notefin",
+ ["it"]="endnote",
+ ["nl"]="eindnoot",
+ ["pe"]="ته‌نوشت",
+ ["ro"]="endnote",
+ },
+ ["enumeration"]={
+ ["cs"]="vycet",
+ ["de"]="nummerierung",
+ ["en"]="enumeration",
+ ["fr"]="enumeration",
+ ["it"]="enumerazione",
+ ["nl"]="doornummering",
+ ["pe"]="شماره‌بندی",
+ ["ro"]="enumerare",
+ },
+ ["environment"]={
+ ["cs"]="prostredi",
+ ["de"]="umgebung",
+ ["en"]="environment",
+ ["fr"]="environement",
+ ["it"]="ambiente",
+ ["nl"]="omgeving",
+ ["pe"]="محیط",
+ ["ro"]="mediu",
+ },
+ ["even"]={
+ ["cs"]="sude",
+ ["de"]="gerade",
+ ["en"]="even",
+ ["fr"]="paire",
+ ["it"]="pari",
+ ["nl"]="even",
+ ["pe"]="زوج",
+ ["ro"]="par",
+ },
+ ["export"]={
+ ["en"]="export",
+ },
+ ["external"]={
+ ["cs"]="externi",
+ ["de"]="extern",
+ ["en"]="external",
+ ["fr"]="external",
+ ["it"]="esterno",
+ ["nl"]="extern",
+ ["pe"]="خارجی",
+ ["ro"]="extern",
+ },
+ ["extremestretch"]={
+ ["en"]="extremestretch",
+ },
+ ["fact"]={
+ ["cs"]="fakt",
+ ["de"]="gegeben",
+ ["en"]="fact",
+ ["fr"]="fait",
+ ["it"]="fatto",
+ ["nl"]="gegeven",
+ ["pe"]="fact",
+ ["ro"]="fapt",
+ },
+ ["february"]={
+ ["cs"]="unor",
+ ["de"]="februar",
+ ["en"]="february",
+ ["fr"]="fevrier",
+ ["it"]="febbraio",
+ ["nl"]="februari",
+ ["pe"]="فوریه",
+ ["ro"]="februarie",
+ },
+ ["figure"]={
+ ["cs"]="obrazek",
+ ["de"]="abbildung",
+ ["en"]="figure",
+ ["fr"]="figure",
+ ["it"]="figura",
+ ["nl"]="figuur",
+ ["pe"]="شکل",
+ ["ro"]="figura",
+ },
+ ["figures"]={
+ ["cs"]="obrazky",
+ ["de"]="abbildungen",
+ ["en"]="figures",
+ ["fr"]="figures",
+ ["it"]="figure",
+ ["nl"]="figuren",
+ ["pe"]="شکلها",
+ ["ro"]="figure",
+ },
+ ["file"]={
+ ["cs"]="soubor",
+ ["de"]="datei",
+ ["en"]="file",
+ ["fr"]="fichier",
+ ["it"]="file",
+ ["nl"]="file",
+ ["pe"]="پرونده",
+ ["ro"]="fisier",
+ },
+ ["final"]={
+ ["cs"]="finalni",
+ ["de"]="endfassung",
+ ["en"]="final",
+ ["fr"]="final",
+ ["it"]="finale",
+ ["nl"]="definitief",
+ ["pe"]="نهایی",
+ ["ro"]="final",
+ },
+ ["first"]={
+ ["cs"]="prvni",
+ ["de"]="erste",
+ ["en"]="first",
+ ["fr"]="premier",
+ ["it"]="primo",
+ ["nl"]="eerste",
+ ["pe"]="اولی",
+ ["ro"]="primul",
+ },
+ ["firstcolumn"]={
+ ["cs"]="firstcolumn",
+ ["de"]="firstcolumn",
+ ["en"]="firstcolumn",
+ ["fr"]="premierecolonne",
+ ["it"]="firstcolumn",
+ ["nl"]="eerstekolom",
+ ["pe"]="ستون‌اول",
+ ["ro"]="firstcolumn",
+ },
+ ["firstpage"]={
+ ["cs"]="prvnistranka",
+ ["de"]="ersteseite",
+ ["en"]="firstpage",
+ ["fr"]="premierepage",
+ ["it"]="primapagina",
+ ["nl"]="eerstepagina",
+ ["pe"]="صفحه‌اول",
+ ["ro"]="primapagina",
+ },
+ ["firstsubpage"]={
+ ["cs"]="prvnipodstranka",
+ ["de"]="ersteunterseite",
+ ["en"]="firstsubpage",
+ ["fr"]="premieresouspage",
+ ["it"]="primasottopagina",
+ ["nl"]="eerstesubpagina",
+ ["pe"]="زیرصفحه‌اول",
+ ["ro"]="primasubpagina",
+ },
+ ["fit"]={
+ ["cs"]="prizpusobive",
+ ["de"]="passend",
+ ["en"]="fit",
+ ["fr"]="adapte",
+ ["it"]="adatta",
+ ["nl"]="passend",
+ ["pe"]="پرکردن",
+ ["ro"]="ajustat",
+ },
+ ["five"]={
+ ["cs"]="pet",
+ ["de"]="fuenf",
+ ["en"]="five",
+ ["fr"]="cinq",
+ ["it"]="cinque",
+ ["nl"]="vijf",
+ ["pe"]="پنج",
+ ["ro"]="cinci",
+ },
+ ["six"]={
+ ["cs"]="six",
+ ["de"]="sechs",
+ ["en"]="six",
+ ["fr"]="six",
+ ["it"]="six",
+ ["nl"]="zes",
+ ["pe"]="six",
+ ["ro"]="six",
+ },
+ ["seven"]={
+ ["cs"]="seven",
+ ["de"]="sieben",
+ ["en"]="seven",
+ ["fr"]="seven",
+ ["it"]="seven",
+ ["nl"]="zeven",
+ ["pe"]="seven",
+ ["ro"]="seven",
+ },
+ ["eight"]={
+ ["cs"]="eight",
+ ["de"]="acht",
+ ["en"]="eight",
+ ["fr"]="eight",
+ ["it"]="eight",
+ ["nl"]="acht",
+ ["pe"]="eight",
+ ["ro"]="eight",
+ },
+ ["nine"]={
+ ["cs"]="nine",
+ ["de"]="neun",
+ ["en"]="nine",
+ ["fr"]="nine",
+ ["it"]="nine",
+ ["nl"]="negen",
+ ["pe"]="nine",
+ ["ro"]="nine",
+ },
+ ["fix"]={
+ ["cs"]="fixuj",
+ ["de"]="stellewiederher",
+ ["en"]="fix",
+ ["fr"]="fixe",
+ ["it"]="fisso",
+ ["nl"]="herstel",
+ ["pe"]="ثابت‌کن",
+ ["ro"]="fix",
+ },
+ ["fixed"]={
+ ["cs"]="fixne",
+ ["de"]="fest",
+ ["en"]="fixed",
+ ["fr"]="fixe",
+ ["it"]="fisso",
+ ["nl"]="vast",
+ ["pe"]="ثابت",
+ ["ro"]="fixat",
+ },
+ ["flexible"]={
+ ["cs"]="prizpusobive",
+ ["de"]="flexibel",
+ ["en"]="flexible",
+ ["fr"]="flexible",
+ ["it"]="flessibile",
+ ["nl"]="flexibel",
+ ["pe"]="انعطافپذیر",
+ ["ro"]="flexibil",
+ },
+ ["float"]={
+ ["cs"]="plvouciobjekt",
+ ["de"]="gleitobjekt",
+ ["en"]="float",
+ ["fr"]="flottant",
+ ["it"]="oggettomobile",
+ ["nl"]="blok",
+ ["pe"]="شناور",
+ ["ro"]="obiectmobil",
+ },
+ ["flushinner"]={
+ ["cs"]="flushinner",
+ ["de"]="flushinner",
+ ["en"]="flushinner",
+ ["fr"]="flushinner",
+ ["it"]="flushinner",
+ ["nl"]="lijnbinnen",
+ ["pe"]="پمپ‌داخلی",
+ ["ro"]="flushinner",
+ },
+ ["flushleft"]={
+ ["cs"]="flushleft",
+ ["de"]="flushleft",
+ ["en"]="flushleft",
+ ["fr"]="flushleft",
+ ["it"]="flushleft",
+ ["nl"]="lijnlinks",
+ ["pe"]="پمپ‌چپ",
+ ["ro"]="flushleft",
+ },
+ ["flushouter"]={
+ ["cs"]="flushouter",
+ ["de"]="flushouter",
+ ["en"]="flushouter",
+ ["fr"]="flushouter",
+ ["it"]="flushouter",
+ ["nl"]="lijnbuiten",
+ ["pe"]="پمپ‌خارجی",
+ ["ro"]="flushouter",
+ },
+ ["flushright"]={
+ ["cs"]="flushright",
+ ["de"]="flushright",
+ ["en"]="flushright",
+ ["fr"]="flushright",
+ ["it"]="flushright",
+ ["nl"]="lijnrechts",
+ ["pe"]="پمپ‌راست",
+ ["ro"]="flushright",
+ },
+ ["followingpage"]={
+ ["en"]="followingpage",
+ ["nl"]="opvolgendepagina",
+ },
+ ["footer"]={
+ ["cs"]="upati",
+ ["de"]="fusszeile",
+ ["en"]="footer",
+ ["fr"]="pdp",
+ ["it"]="piedipagina",
+ ["nl"]="voet",
+ ["pe"]="ته‌برگ",
+ ["ro"]="subsol",
+ },
+ ["footnote"]={
+ ["cs"]="poznamkapodcarou",
+ ["de"]="fussnote",
+ ["en"]="footnote",
+ ["fr"]="notepdp",
+ ["it"]="notapdp",
+ ["nl"]="voetnoot",
+ ["pe"]="پانوشت",
+ ["ro"]="notasubsol",
+ },
+ ["force"]={
+ ["cs"]="sila",
+ ["de"]="zwinge",
+ ["en"]="force",
+ ["fr"]="force",
+ ["it"]="forza",
+ ["nl"]="forceer",
+ ["pe"]="اجبار",
+ ["ro"]="fortat",
+ },
+ ["foreground"]={
+ ["cs"]="popredi",
+ ["de"]="vordergrund",
+ ["en"]="foreground",
+ ["fr"]="premierplan",
+ ["it"]="foreground",
+ ["nl"]="voorgrond",
+ ["pe"]="پیش‌زمینه",
+ ["ro"]="primplan",
+ },
+ ["formeel"]={
+ ["cs"]="formeel",
+ ["de"]="formeel",
+ ["en"]="formeel",
+ ["fr"]="formeel",
+ ["it"]="formeel",
+ ["nl"]="formeel",
+ ["pe"]="formeel",
+ ["ro"]="formeel",
+ },
+ ["formula"]={
+ ["cs"]="rovnice",
+ ["de"]="formel",
+ ["en"]="formula",
+ ["fr"]="formule",
+ ["it"]="formula",
+ ["nl"]="formule",
+ ["pe"]="فرمول",
+ ["ro"]="formula",
+ },
+ ["formulae"]={
+ ["cs"]="rovnice",
+ ["de"]="formeln",
+ ["en"]="formulae",
+ ["fr"]="formules",
+ ["it"]="formule",
+ ["nl"]="formules",
+ ["pe"]="فرمولها",
+ ["ro"]="formule",
+ },
+ ["forward"]={
+ ["cs"]="vpred",
+ ["de"]="vorwaerts",
+ ["en"]="forward",
+ ["fr"]="avance",
+ ["it"]="avanti",
+ ["nl"]="vooruit",
+ ["pe"]="به‌جلو",
+ ["ro"]="avans",
+ },
+ ["four"]={
+ ["cs"]="ctyri",
+ ["de"]="vier",
+ ["en"]="four",
+ ["fr"]="quatre",
+ ["it"]="quattro",
+ ["nl"]="vier",
+ ["pe"]="چهار",
+ ["ro"]="patru",
+ },
+ ["frame"]={
+ ["cs"]="ramecek",
+ ["de"]="rahmen",
+ ["en"]="frame",
+ ["fr"]="cadre",
+ ["it"]="cornice",
+ ["nl"]="kader",
+ ["pe"]="قالب",
+ ["ro"]="incadrat",
+ },
+ ["framedtext"]={
+ ["cs"]="oramovanytext",
+ ["de"]="umrahmtertext",
+ ["en"]="framedtext",
+ ["fr"]="texteencadre",
+ ["it"]="testoincorniciato",
+ ["nl"]="kadertekst",
+ ["pe"]="متن‌قالبی",
+ ["ro"]="textinconjurat",
+ },
+ ["friday"]={
+ ["cs"]="patek",
+ ["de"]="freitag",
+ ["en"]="friday",
+ ["fr"]="vendredi",
+ ["it"]="venerdi",
+ ["nl"]="vrijdag",
+ ["pe"]="جمعه",
+ ["ro"]="vineri",
+ },
+ ["frontmatter"]={
+ ["cs"]="prednicasti",
+ ["de"]="einleitungen",
+ ["en"]="frontmatter",
+ ["fr"]="preambule",
+ ["it"]="preambolo",
+ ["nl"]="inleidingen",
+ ["pe"]="پیش‌مطلب",
+ ["ro"]="prologul",
+ },
+ ["frontpart"]={
+ ["cs"]="prednicast",
+ ["de"]="einleitung",
+ ["en"]="frontpart",
+ ["fr"]="preface",
+ ["it"]="prefazione",
+ ["nl"]="inleiding",
+ ["pe"]="پیش‌قسمت",
+ ["ro"]="prolog",
+ },
+ ["fullhz"]={
+ ["cs"]="fullhz",
+ ["de"]="fullhz",
+ ["en"]="fullhz",
+ ["fr"]="fullhz",
+ ["it"]="fullhz",
+ ["nl"]="fullenhz",
+ ["pe"]="fullhz",
+ ["ro"]="fullhz",
+ },
+ ["global"]={
+ ["cs"]="globalne",
+ ["de"]="global",
+ ["en"]="global",
+ ["fr"]="global",
+ ["it"]="globale",
+ ["nl"]="globaal",
+ ["pe"]="سراسری",
+ ["ro"]="global",
+ },
+ ["graphic"]={
+ ["cs"]="graf",
+ ["de"]="grafik",
+ ["en"]="graphic",
+ ["fr"]="graphique",
+ ["it"]="grafico",
+ ["nl"]="grafiek",
+ ["pe"]="گرافیک",
+ ["ro"]="graficul",
+ },
+ ["graphics"]={
+ ["cs"]="grafy",
+ ["de"]="grafiken",
+ ["en"]="graphics",
+ ["fr"]="graphiques",
+ ["it"]="grafici",
+ ["nl"]="grafieken",
+ ["pe"]="گرافیکها",
+ ["ro"]="graficele",
+ },
+ ["gray"]={
+ ["cs"]="seda",
+ ["de"]="grau",
+ ["en"]="gray",
+ ["fr"]="gris",
+ ["it"]="grigio",
+ ["nl"]="grijs",
+ ["pe"]="خاکستری",
+ ["ro"]="gri",
+ },
+ ["greek"]={
+ ["cs"]="recky",
+ ["de"]="griechisch",
+ ["en"]="greek",
+ ["fr"]="grec",
+ ["it"]="greco",
+ ["nl"]="grieks",
+ ["pe"]="یونانی",
+ ["ro"]="grec",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gritter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="grid",
+ ["pe"]="توری",
+ ["ro"]="grila",
+ },
+ ["halfline"]={
+ ["cs"]="pulradku",
+ ["de"]="halbezeile",
+ ["en"]="halfline",
+ ["fr"]="demiligne",
+ ["it"]="mezzariga",
+ ["nl"]="halveregel",
+ ["pe"]="نیم‌خط",
+ ["ro"]="jumatatelinie",
+ },
+ ["handwritten"]={
+ ["cs"]="rukopisne",
+ ["de"]="handschrift",
+ ["en"]="handwritten",
+ ["fr"]="manuscript",
+ ["it"]="grafiamanuale",
+ ["nl"]="handschrift",
+ ["pe"]="دست‌نوشته",
+ ["ro"]="scrismanual",
+ },
+ ["hang"]={
+ ["cs"]="zaveseni",
+ ["de"]="haengend",
+ ["en"]="hang",
+ ["fr"]="suspend",
+ ["it"]="sospendi",
+ ["nl"]="hang",
+ ["pe"]="بیاویز",
+ ["ro"]="suspenda",
+ },
+ ["hanging"]={
+ ["cs"]="visici",
+ ["de"]="haengend",
+ ["en"]="hanging",
+ ["fr"]="suspend",
+ ["it"]="sospeso",
+ ["nl"]="hangend",
+ ["pe"]="آویزان",
+ ["ro"]="suspendat",
+ },
+ ["head"]={
+ ["cs"]="hlavicka",
+ ["de"]="kopf",
+ ["en"]="head",
+ ["fr"]="tete",
+ ["it"]="testa",
+ ["nl"]="kop",
+ ["pe"]="سر",
+ ["ro"]="antet",
+ },
+ ["header"]={
+ ["cs"]="zahlavi",
+ ["de"]="kopfzeile",
+ ["en"]="header",
+ ["fr"]="entete",
+ ["it"]="intestazione",
+ ["nl"]="hoofd",
+ ["pe"]="سربرگ",
+ ["ro"]="antet",
+ },
+ ["height"]={
+ ["cs"]="vyska",
+ ["de"]="hoehe",
+ ["en"]="height",
+ ["fr"]="hauteur",
+ ["it"]="altezza",
+ ["nl"]="hoogte",
+ ["pe"]="ارتفاع",
+ ["ro"]="inaltime",
+ },
+ ["helptext"]={
+ ["cs"]="textnapovedy",
+ ["de"]="hilfetext",
+ ["en"]="helptext",
+ ["fr"]="texteaide",
+ ["it"]="testoaiuto",
+ ["nl"]="helptekst",
+ ["pe"]="متن‌کمکی",
+ ["ro"]="textajutator",
+ },
+ ["hencefore"]={
+ ["cs"]="vyse",
+ ["de"]="vorher",
+ ["en"]="hencefore",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="hierboven",
+ ["pe"]="hencefore",
+ ["ro"]="precedent",
+ },
+ ["here"]={
+ ["cs"]="zde",
+ ["de"]="hier",
+ ["en"]="here",
+ ["fr"]="ici",
+ ["it"]="qui",
+ ["nl"]="hier",
+ ["pe"]="اینجا",
+ ["ro"]="aici",
+ },
+ ["hereafter"]={
+ ["cs"]="nize",
+ ["de"]="nachher",
+ ["en"]="hereafter",
+ ["fr"]="suivant",
+ ["it"]="seguente",
+ ["nl"]="hieronder",
+ ["pe"]="ازاین‌به‌بعد",
+ ["ro"]="urmator",
+ },
+ ["hidden"]={
+ ["cs"]="skryte",
+ ["de"]="versteckt",
+ ["en"]="hidden",
+ ["fr"]="cache",
+ ["it"]="nascosto",
+ ["nl"]="verborgen",
+ ["pe"]="پنهانی",
+ ["ro"]="ascuns",
+ },
+ ["hiding"]={
+ ["cs"]="skryt",
+ ["de"]="verbergen",
+ ["en"]="hiding",
+ ["fr"]="cache",
+ ["it"]="nascondere",
+ ["nl"]="verbergen",
+ ["pe"]="پنهان‌کردن",
+ ["ro"]="ascundere",
+ },
+ ["high"]={
+ ["cs"]="vysoko",
+ ["de"]="hoch",
+ ["en"]="high",
+ ["fr"]="haut",
+ ["it"]="alto",
+ ["nl"]="hoog",
+ ["pe"]="بلند",
+ ["ro"]="inalt",
+ },
+ ["horizontal"]={
+ ["cs"]="horizontalne",
+ ["de"]="horizontal",
+ ["en"]="horizontal",
+ ["fr"]="horizontale",
+ ["it"]="orizzontale",
+ ["nl"]="horizontaal",
+ ["pe"]="افقی",
+ ["ro"]="orizontal",
+ },
+ ["hyphenated"]={
+ ["cs"]="hyphenated",
+ ["de"]="hyphenate",
+ ["en"]="hyphenated",
+ ["fr"]="hyphenated",
+ ["it"]="sillabato",
+ ["nl"]="afgebroken",
+ ["pe"]="شکسته",
+ ["ro"]="despsilabe",
+ },
+ ["hz"]={
+ ["cs"]="hz",
+ ["de"]="hz",
+ ["en"]="hz",
+ ["fr"]="hz",
+ ["it"]="hz",
+ ["nl"]="hz",
+ ["pe"]="hz",
+ ["ro"]="hz",
+ },
+ ["inbetween"]={
+ ["cs"]="mezi",
+ ["de"]="zwischen",
+ ["en"]="inbetween",
+ ["fr"]="entre",
+ ["it"]="tra",
+ ["nl"]="tussen",
+ ["pe"]="دربین",
+ ["ro"]="intre",
+ },
+ ["index"]={
+ ["cs"]="rejstrik",
+ ["de"]="index",
+ ["en"]="index",
+ ["fr"]="index",
+ ["it"]="indiceanalitico",
+ ["nl"]="index",
+ ["pe"]="نمایه",
+ ["ro"]="index",
+ },
+ ["indices"]={
+ ["cs"]="rejstriky",
+ ["de"]="indizies",
+ ["en"]="indices",
+ ["fr"]="indices",
+ ["it"]="indicianalitici",
+ ["nl"]="indices",
+ ["pe"]="نمایه‌ها",
+ ["ro"]="indexuri",
+ },
+ ["informeel"]={
+ ["cs"]="informeel",
+ ["de"]="informeel",
+ ["en"]="informeel",
+ ["fr"]="informeel",
+ ["it"]="informeel",
+ ["nl"]="informeel",
+ ["pe"]="informeel",
+ ["ro"]="informeel",
+ },
+ ["inherit"]={
+ ["cs"]="inherit",
+ ["de"]="inherit",
+ ["en"]="inherit",
+ ["fr"]="herite",
+ ["it"]="inherit",
+ ["nl"]="erf",
+ ["pe"]="ارث‌بردن",
+ ["ro"]="inherit",
+ },
+ ["ininner"]={
+ ["cs"]="ininner",
+ ["de"]="ininner",
+ ["en"]="ininner",
+ ["fr"]="ininner",
+ ["it"]="ininner",
+ ["nl"]="inbinnen",
+ ["pe"]="درداخلی",
+ ["ro"]="ininner",
+ },
+ ["ininneredge"]={
+ ["en"]="ininneredge",
+ },
+ ["ininnermargin"]={
+ ["en"]="ininnermargin",
+ },
+ ["inleft"]={
+ ["cs"]="ivlevo",
+ ["de"]="imlinken",
+ ["en"]="inleft",
+ ["fr"]="dansgauche",
+ ["it"]="insinistra",
+ ["nl"]="inlinker",
+ ["pe"]="درون‌چپ",
+ ["ro"]="instanga",
+ },
+ ["inleftedge"]={
+ ["cs"]="nalevo",
+ ["de"]="imlinkenrand",
+ ["en"]="inleftedge",
+ ["fr"]="dansbordgauche",
+ ["it"]="inlatosinistro",
+ ["nl"]="inlinkerrand",
+ ["pe"]="درلبه‌چپ",
+ ["ro"]="inparteastanga",
+ },
+ ["inleftmargin"]={
+ ["cs"]="nalevyokraj",
+ ["de"]="inlinkermarginale",
+ ["en"]="inleftmargin",
+ ["fr"]="dansmargegauche",
+ ["it"]="inmarginesinistro",
+ ["nl"]="inlinkermarge",
+ ["pe"]="درحاشیه‌چپ",
+ ["ro"]="inmargineastanga",
+ },
+ ["inline"]={
+ ["en"]="inline",
+ },
+ ["inmargin"]={
+ ["cs"]="naokraji",
+ ["de"]="imrand",
+ ["en"]="inmargin",
+ ["fr"]="dansmarge",
+ ["it"]="inmargine",
+ ["nl"]="inmarge",
+ ["pe"]="درون‌حاشیه",
+ ["ro"]="inmargine",
+ },
+ ["inner"]={
+ ["cs"]="uvnitr",
+ ["de"]="innen",
+ ["en"]="inner",
+ ["fr"]="interieur",
+ ["it"]="interno",
+ ["nl"]="binnen",
+ ["pe"]="داخلی",
+ ["ro"]="intern",
+ },
+ ["inneredge"]={
+ ["cs"]="inneredge",
+ ["de"]="inneredge",
+ ["en"]="inneredge",
+ ["fr"]="bordinterieur",
+ ["it"]="bordointerno",
+ ["nl"]="binnenrand",
+ ["pe"]="لبه‌داخلی",
+ ["ro"]="inneredge",
+ },
+ ["innermargin"]={
+ ["cs"]="innermargin",
+ ["de"]="innermargin",
+ ["en"]="innermargin",
+ ["fr"]="margeinterieure",
+ ["it"]="margineinterno",
+ ["nl"]="binnenmarge",
+ ["pe"]="حاشیه‌داخلی",
+ ["ro"]="innermargin",
+ },
+ ["inother"]={
+ ["cs"]="inother",
+ ["de"]="inother",
+ ["en"]="inother",
+ ["fr"]="inother",
+ ["it"]="inother",
+ ["nl"]="inandere",
+ ["pe"]="inother",
+ ["ro"]="inother",
+ },
+ ["inouter"]={
+ ["cs"]="inouter",
+ ["de"]="inouter",
+ ["en"]="inouter",
+ ["fr"]="inouter",
+ ["it"]="inouter",
+ ["nl"]="inbuiten",
+ ["pe"]="درخارجی",
+ ["ro"]="inouter",
+ },
+ ["inouteredge"]={
+ ["en"]="inouteredge",
+ },
+ ["inoutermargin"]={
+ ["en"]="inoutermargin",
+ },
+ ["inright"]={
+ ["cs"]="ivpravo",
+ ["de"]="imrechten",
+ ["en"]="inright",
+ ["fr"]="dansdroit",
+ ["it"]="indestra",
+ ["nl"]="inrechter",
+ ["pe"]="درون‌راست",
+ ["ro"]="indreapta",
+ },
+ ["inrightedge"]={
+ ["cs"]="napravo",
+ ["de"]="imrechtenrand",
+ ["en"]="inrightedge",
+ ["fr"]="dansborddroit",
+ ["it"]="inlatodestro",
+ ["nl"]="inrechterrand",
+ ["pe"]="درلبه‌راست",
+ ["ro"]="inparteadreapta",
+ },
+ ["inrightmargin"]={
+ ["cs"]="napravyokraj",
+ ["de"]="inrechtermarginale",
+ ["en"]="inrightmargin",
+ ["fr"]="dansmargedroite",
+ ["it"]="inmarginedestro",
+ ["nl"]="inrechtermarge",
+ ["pe"]="درحاشیه‌راست",
+ ["ro"]="inmargineadreapta",
+ },
+ ["integral"]={
+ ["en"]="integral",
+ },
+ ["interaction"]={
+ ["cs"]="interakce",
+ ["de"]="interaktion",
+ ["en"]="interaction",
+ ["fr"]="interaction",
+ ["it"]="interazione",
+ ["nl"]="interactie",
+ ["pe"]="پانل",
+ ["ro"]="interactiune",
+ },
+ ["interactionmenu"]={
+ ["cs"]="interaktivnimenu",
+ ["de"]="interaktionsmenue",
+ ["en"]="interactionmenu",
+ ["fr"]="menuinteraction",
+ ["it"]="menuinterattivo",
+ ["nl"]="interactiemenu",
+ ["pe"]="منوی‌پانل",
+ ["ro"]="meniuinteractiune",
+ },
+ ["interactive"]={
+ ["en"]="interactive",
+ },
+ ["intermezzi"]={
+ ["cs"]="intermezzi",
+ ["de"]="intermezzi",
+ ["en"]="intermezzi",
+ ["fr"]="intermezzi",
+ ["it"]="intermezzi",
+ ["nl"]="intermezzos",
+ ["pe"]="میان‌پرده‌ها",
+ ["ro"]="intermezzi",
+ },
+ ["intermezzo"]={
+ ["cs"]="intermezzo",
+ ["de"]="intermezzo",
+ ["en"]="intermezzo",
+ ["fr"]="intermezzo",
+ ["it"]="intermezzo",
+ ["nl"]="intermezzo",
+ ["pe"]="میان‌پرده",
+ ["ro"]="intermezzo",
+ },
+ ["intext"]={
+ ["cs"]="dotextu",
+ ["de"]="imtext",
+ ["en"]="intext",
+ ["fr"]="danstexte",
+ ["it"]="intesto",
+ ["nl"]="intekst",
+ ["pe"]="درون‌متن",
+ ["ro"]="intext",
+ },
+ ["intro"]={
+ ["cs"]="uvod",
+ ["de"]="intro",
+ ["en"]="intro",
+ ["fr"]="intro",
+ ["it"]="intro",
+ ["nl"]="intro",
+ ["pe"]="پیشگفتار",
+ ["ro"]="intro",
+ },
+ ["italic"]={
+ ["cs"]="kurziva",
+ ["de"]="italic",
+ ["en"]="italic",
+ ["fr"]="italique",
+ ["it"]="corsivo",
+ ["nl"]="italic",
+ ["pe"]="ایتالیک",
+ ["ro"]="italic",
+ },
+ ["italicbold"]={
+ ["cs"]="kurzivnitucne",
+ ["de"]="italicfett",
+ ["en"]="italicbold",
+ ["fr"]="grasitalique",
+ ["it"]="corsivograssetto",
+ ["nl"]="italicvet",
+ ["pe"]="مشکی‌ایتالیک",
+ ["ro"]="italicaldin",
+ },
+ ["item"]={
+ ["cs"]="polozka",
+ ["de"]="pos",
+ ["en"]="item",
+ ["fr"]="element",
+ ["it"]="elemento",
+ ["nl"]="som",
+ ["pe"]="آیتم",
+ ["ro"]="element",
+ },
+ ["itemize"]={
+ ["cs"]="vycet",
+ ["de"]="aufzaehlung",
+ ["en"]="itemize",
+ ["fr"]="lister",
+ ["it"]="elenco",
+ ["nl"]="opsomming",
+ ["pe"]="آیتم‌بندی",
+ ["ro"]="enumerare",
+ },
+ ["its"]={
+ ["cs"]="pol",
+ ["de"]="its",
+ ["en"]="its",
+ ["fr"]="its",
+ ["it"]="its",
+ ["nl"]="its",
+ ["pe"]="آیم",
+ ["ro"]="propriu",
+ },
+ ["january"]={
+ ["cs"]="leden",
+ ["de"]="januar",
+ ["en"]="january",
+ ["fr"]="janvier",
+ ["it"]="gennaio",
+ ["nl"]="januari",
+ ["pe"]="ژانویه",
+ ["ro"]="ianuarie",
+ },
+ ["joinedup"]={
+ ["cs"]="spojeno",
+ ["de"]="keinabstand",
+ ["en"]="joinedup",
+ ["fr"]="joinedup",
+ ["it"]="unito",
+ ["nl"]="aansluitend",
+ ["pe"]="متصل‌بالا",
+ ["ro"]="unit",
+ },
+ ["july"]={
+ ["cs"]="cervenec",
+ ["de"]="juli",
+ ["en"]="july",
+ ["fr"]="juillet",
+ ["it"]="luglio",
+ ["nl"]="juli",
+ ["pe"]="ژولای",
+ ["ro"]="iulie",
+ },
+ ["june"]={
+ ["cs"]="cerven",
+ ["de"]="juni",
+ ["en"]="june",
+ ["fr"]="juin",
+ ["it"]="giugno",
+ ["nl"]="juni",
+ ["pe"]="ژوئن",
+ ["ro"]="iunie",
+ },
+ ["keep"]={
+ ["cs"]="drzet",
+ ["de"]="behalte",
+ ["en"]="keep",
+ ["fr"]="maintient",
+ ["it"]="mantieni",
+ ["nl"]="handhaaf",
+ ["pe"]="نگهدار",
+ ["ro"]="mentine",
+ },
+ ["kerncharacters"]={
+ ["en"]="kerncharacters",
+ },
+ ["knockout"]={
+ ["cs"]="knockout",
+ ["de"]="knockout",
+ ["en"]="knockout",
+ ["fr"]="knockout",
+ ["it"]="knockout",
+ ["nl"]="knockout",
+ ["pe"]="knockout",
+ ["ro"]="knockout",
+ },
+ ["label"]={
+ ["cs"]="popisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["landscape"]={
+ ["cs"]="nasirku",
+ ["de"]="querformat",
+ ["en"]="landscape",
+ ["fr"]="paysage",
+ ["it"]="orizzontale",
+ ["nl"]="liggend",
+ ["pe"]="صفحه‌گسترده",
+ ["ro"]="vedere",
+ },
+ ["last"]={
+ ["cs"]="posledni",
+ ["de"]="letzte",
+ ["en"]="last",
+ ["fr"]="dernier",
+ ["it"]="ultimo",
+ ["nl"]="laatste",
+ ["pe"]="آخرین",
+ ["ro"]="ultim",
+ },
+ ["lastcolumn"]={
+ ["cs"]="lastcolumn",
+ ["de"]="lastcolumn",
+ ["en"]="lastcolumn",
+ ["fr"]="dernierecolonne",
+ ["it"]="lastcolumn",
+ ["nl"]="laatstekolom",
+ ["pe"]="آخرین‌ستون",
+ ["ro"]="lastcolumn",
+ },
+ ["lastpage"]={
+ ["cs"]="poslednistrana",
+ ["de"]="letzteseite",
+ ["en"]="lastpage",
+ ["fr"]="dernierepage",
+ ["it"]="ultimapagina",
+ ["nl"]="laatstepagina",
+ ["pe"]="صفحه‌آخر",
+ ["ro"]="ultimapagina",
+ },
+ ["lastpagenumber"]={
+ ["cs"]="lastpagenumber",
+ ["de"]="lastpagenumber",
+ ["en"]="lastpagenumber",
+ ["fr"]="derniernumeropage",
+ ["it"]="lastpagenumber",
+ ["nl"]="laatstepaginanummer",
+ ["pe"]="شماه‌صفحه‌آخر",
+ ["ro"]="lastpagenumber",
+ },
+ ["lastsubpage"]={
+ ["cs"]="poslaednipodstranka",
+ ["de"]="letzteunterseite",
+ ["en"]="lastsubpage",
+ ["fr"]="dernieresouspage",
+ ["it"]="ultimasottopagina",
+ ["nl"]="laatstesubpagina",
+ ["pe"]="زیرصفحه‌آخر",
+ ["ro"]="ultimasubpagina",
+ },
+ ["layer"]={
+ ["cs"]="layer",
+ ["de"]="layer",
+ ["en"]="layer",
+ ["fr"]="layer",
+ ["it"]="layer",
+ ["nl"]="layer",
+ ["pe"]="layer",
+ ["ro"]="layer",
+ },
+ ["left"]={
+ ["cs"]="vlevo",
+ ["de"]="links",
+ ["en"]="left",
+ ["fr"]="gauche",
+ ["it"]="sinistra",
+ ["nl"]="links",
+ ["pe"]="چپ",
+ ["ro"]="stanga",
+ },
+ ["leftedge"]={
+ ["cs"]="levahrana",
+ ["de"]="linkekante",
+ ["en"]="leftedge",
+ ["fr"]="bordgauche",
+ ["it"]="bordosinistro",
+ ["nl"]="linkerrand",
+ ["pe"]="لبه‌چپ",
+ ["ro"]="bordurastanga",
+ },
+ ["lefthanging"]={
+ ["cs"]="lefthanging",
+ ["de"]="lefthanging",
+ ["en"]="lefthanging",
+ ["fr"]="lefthanging",
+ ["it"]="lefthanging",
+ ["nl"]="linkshangend",
+ ["pe"]="آویزان‌چپ",
+ ["ro"]="lefthanging",
+ },
+ ["leftmargin"]={
+ ["cs"]="levyokraj",
+ ["de"]="linkerrand",
+ ["en"]="leftmargin",
+ ["fr"]="margegauche",
+ ["it"]="marginesinistro",
+ ["nl"]="linkermarge",
+ ["pe"]="حاشیه‌چپ",
+ ["ro"]="marginestanga",
+ },
+ ["leftpage"]={
+ ["cs"]="levastranka",
+ ["de"]="linkerseite",
+ ["en"]="leftpage",
+ ["fr"]="pagegauche",
+ ["it"]="paginasinistra",
+ ["nl"]="linkerpagina",
+ ["pe"]="صفحه‌چپ",
+ ["ro"]="paginastanga",
+ },
+ ["lefttoright"]={
+ ["cs"]="lefttoright",
+ ["de"]="lefttoright",
+ ["en"]="lefttoright",
+ ["fr"]="lefttoright",
+ ["it"]="lefttoright",
+ ["nl"]="lefttoright",
+ ["pe"]="lefttoright",
+ ["ro"]="lefttoright",
+ },
+ ["legend"]={
+ ["cs"]="legenda",
+ ["de"]="legende",
+ ["en"]="legend",
+ ["fr"]="legende",
+ ["it"]="legenda",
+ ["nl"]="legenda",
+ ["pe"]="راهنما",
+ ["ro"]="legenda",
+ },
+ ["less"]={
+ ["en"]="less",
+ ["nl"]="minder",
+ },
+ ["lesshyphenation"]={
+ ["cs"]="lesshyphenation",
+ ["de"]="lesshyphenation",
+ ["en"]="lesshyphenation",
+ ["fr"]="lesshyphenation",
+ ["it"]="lesshyphenation",
+ ["nl"]="lesshyphenation",
+ ["pe"]="شکست‌کلمات‌کمتر",
+ ["ro"]="lesshyphenation",
+ },
+ ["letterspacing"]={
+ ["en"]="letterspacing",
+ },
+ ["line"]={
+ ["cs"]="radek",
+ ["de"]="zeile",
+ ["en"]="line",
+ ["fr"]="ligne",
+ ["it"]="riga",
+ ["nl"]="regel",
+ ["pe"]="خط",
+ ["ro"]="linie",
+ },
+ ["linenote"]={
+ ["cs"]="linenote",
+ ["de"]="linenote",
+ ["en"]="linenote",
+ ["fr"]="noteligne",
+ ["it"]="linenote",
+ ["nl"]="regelnoot",
+ ["pe"]="خط‌نوشت",
+ ["ro"]="linenote",
+ },
+ ["lines"]={
+ ["cs"]="radky",
+ ["de"]="zeilen",
+ ["en"]="lines",
+ ["fr"]="lignes",
+ ["it"]="righe",
+ ["nl"]="regels",
+ ["pe"]="خطها",
+ ["ro"]="linii",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="liste",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokaal",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["localenvironment"]={
+ ["cs"]="lokalnihoprostredi",
+ ["de"]="lokaleumgebung",
+ ["en"]="localenvironment",
+ ["fr"]="environementlocal",
+ ["it"]="ambientelocale",
+ ["nl"]="deelomgeving",
+ ["pe"]="محیط‌موضعی",
+ ["ro"]="mediulocal",
+ },
+ ["logo"]={
+ ["cs"]="logo",
+ ["de"]="logo",
+ ["en"]="logo",
+ ["fr"]="logo",
+ ["it"]="logo",
+ ["nl"]="logo",
+ ["pe"]="آرم",
+ ["ro"]="logo",
+ },
+ ["logos"]={
+ ["cs"]="loga",
+ ["de"]="logos",
+ ["en"]="logos",
+ ["fr"]="logos",
+ ["it"]="loghi",
+ ["nl"]="logos",
+ ["pe"]="آرمها",
+ ["ro"]="logos",
+ },
+ ["lohi"]={
+ ["cs"]="nivy",
+ ["de"]="hoti",
+ ["en"]="lohi",
+ ["fr"]="baha",
+ ["it"]="pedap",
+ ["nl"]="laho",
+ ["pe"]="پابا",
+ ["ro"]="lohi",
+ },
+ ["long"]={
+ ["en"]="long",
+ },
+ ["loose"]={
+ ["cs"]="uvolnene",
+ ["de"]="lose",
+ ["en"]="loose",
+ ["fr"]="perte",
+ ["it"]="lento",
+ ["nl"]="los",
+ ["pe"]="شل",
+ ["ro"]="larg",
+ },
+ ["low"]={
+ ["cs"]="nizko",
+ ["de"]="tief",
+ ["en"]="low",
+ ["fr"]="bas",
+ ["it"]="basso",
+ ["nl"]="laag",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["ls"]={
+ ["cs"]="ls",
+ ["de"]="ls",
+ ["en"]="ls",
+ ["fr"]="ls",
+ ["it"]="ls",
+ ["nl"]="ls",
+ ["pe"]="ls",
+ ["ro"]="ls",
+ },
+ ["makeup"]={
+ ["cs"]="zlom",
+ ["de"]="umbruch",
+ ["en"]="makeup",
+ ["fr"]="makeup",
+ ["it"]="makeup",
+ ["nl"]="opmaak",
+ ["pe"]="آرایش",
+ ["ro"]="marcaj",
+ },
+ ["mar"]={
+ ["cs"]="mar",
+ ["de"]="mar",
+ ["en"]="mar",
+ ["fr"]="mar",
+ ["it"]="mar",
+ ["nl"]="mar",
+ ["pe"]="حاش",
+ ["ro"]="mar",
+ },
+ ["march"]={
+ ["cs"]="brezen",
+ ["de"]="maerz",
+ ["en"]="march",
+ ["fr"]="mars",
+ ["it"]="marzo",
+ ["nl"]="maart",
+ ["pe"]="مارس",
+ ["ro"]="martie",
+ },
+ ["margin"]={
+ ["cs"]="marginalie",
+ ["de"]="marginalie",
+ ["en"]="margin",
+ ["fr"]="marge",
+ ["it"]="margine",
+ ["nl"]="marge",
+ ["pe"]="حاشیه",
+ ["ro"]="margine",
+ },
+ ["marginedge"]={
+ ["cs"]="textovahrana",
+ ["de"]="marginalkante",
+ ["en"]="marginedge",
+ ["fr"]="bordmarge",
+ ["it"]="bordomargine",
+ ["nl"]="kantlijn",
+ ["pe"]="لبه‌حاشیه",
+ ["ro"]="marginebordura",
+ },
+ ["margintext"]={
+ ["cs"]="marginalnitext",
+ ["de"]="marginaltext",
+ ["en"]="margintext",
+ ["fr"]="textemarge",
+ ["it"]="testoinmargine",
+ ["nl"]="margetekst",
+ ["pe"]="متن‌حاشیه",
+ ["ro"]="textmarginal",
+ },
+ ["margintitle"]={
+ ["cs"]="titulmarginalie",
+ ["de"]="marginaltitel",
+ ["en"]="margintitle",
+ ["fr"]="titremarge",
+ ["it"]="titoloinmargine",
+ ["nl"]="margetitel",
+ ["pe"]="عنوان‌حاشیه",
+ ["ro"]="titlumarginal",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markering",
+ ["pe"]="نشانه‌گذاری",
+ ["ro"]="marcaje",
+ },
+ ["math"]={
+ ["en"]="math",
+ },
+ ["mathalignment"]={
+ ["cs"]="mathalignment",
+ ["de"]="mathalignment",
+ ["en"]="mathalignment",
+ ["fr"]="mathalignment",
+ ["it"]="mathalignment",
+ ["nl"]="wiskundeuitlijnen",
+ ["pe"]="تنظیم‌ریاضی",
+ ["ro"]="mathalignment",
+ },
+ ["mathcases"]={
+ ["cs"]="mathcases",
+ ["de"]="mathcases",
+ ["en"]="mathcases",
+ ["fr"]="mathcases",
+ ["it"]="mathcases",
+ ["nl"]="mathcases",
+ ["pe"]="حالتهای‌ریاضی",
+ ["ro"]="mathcases",
+ },
+ ["mathematics"]={
+ ["cs"]="mathematika",
+ ["de"]="mathematik",
+ ["en"]="mathematics",
+ ["fr"]="mathematique",
+ ["it"]="matematica",
+ ["nl"]="wiskunde",
+ ["pe"]="ریاضی",
+ ["ro"]="matematica",
+ },
+ ["mathmatrix"]={
+ ["cs"]="mathmatrix",
+ ["de"]="mathmatrix",
+ ["en"]="mathmatrix",
+ ["fr"]="mathmatrix",
+ ["it"]="mathmatrix",
+ ["nl"]="wiskundematrix",
+ ["pe"]="ماتریش‌ریاضی",
+ ["ro"]="mathmatrix",
+ },
+ ["max"]={
+ ["cs"]="max",
+ ["de"]="max",
+ ["en"]="max",
+ ["fr"]="max",
+ ["it"]="max",
+ ["nl"]="max",
+ ["pe"]="بیشترین",
+ ["ro"]="max",
+ },
+ ["maxdepth"]={
+ ["en"]="maxdepth",
+ ["nl"]="maxdiepte",
+ },
+ ["maxheight"]={
+ ["en"]="maxheight",
+ ["nl"]="maxhoogte",
+ },
+ ["maxwidth"]={
+ ["en"]="maxwidth",
+ ["nl"]="maxbreedte",
+ },
+ ["may"]={
+ ["cs"]="kveten",
+ ["de"]="mai",
+ ["en"]="may",
+ ["fr"]="mai",
+ ["it"]="maggio",
+ ["nl"]="mei",
+ ["pe"]="مه",
+ ["ro"]="mai",
+ },
+ ["mediaeval"]={
+ ["cs"]="stredoveky",
+ ["de"]="mittelalterlich",
+ ["en"]="mediaeval",
+ ["fr"]="medieval",
+ ["it"]="medievale",
+ ["nl"]="mediaeval",
+ ["pe"]="mediaeval",
+ ["ro"]="medieval",
+ },
+ ["medium"]={
+ ["cs"]="stredni",
+ ["de"]="mittel",
+ ["en"]="medium",
+ ["fr"]="moyen",
+ ["it"]="medio",
+ ["nl"]="middel",
+ ["pe"]="متوسط",
+ ["ro"]="mediu",
+ },
+ ["middle"]={
+ ["cs"]="nastred",
+ ["de"]="mittig",
+ ["en"]="middle",
+ ["fr"]="milieu",
+ ["it"]="centro",
+ ["nl"]="midden",
+ ["pe"]="میان",
+ ["ro"]="centru",
+ },
+ ["min"]={
+ ["cs"]="min",
+ ["de"]="min",
+ ["en"]="min",
+ ["fr"]="min",
+ ["it"]="min",
+ ["nl"]="min",
+ ["pe"]="کمترین",
+ ["ro"]="min",
+ },
+ ["mindepth"]={
+ ["en"]="mindepth",
+ ["nl"]="mindiepte",
+ },
+ ["minheight"]={
+ ["cs"]="minvyska",
+ ["de"]="minhoehe",
+ ["en"]="minheight",
+ ["fr"]="hauteurmin",
+ ["it"]="altezzamin",
+ ["nl"]="minhoogte",
+ ["pe"]="کمترین‌ارتفاع",
+ ["ro"]="inaltimeminima",
+ },
+ ["minwidth"]={
+ ["cs"]="minsirka",
+ ["de"]="minbreite",
+ ["en"]="minwidth",
+ ["fr"]="largeurmin",
+ ["it"]="ampiezzamin",
+ ["nl"]="minbreedte",
+ ["pe"]="کمترین‌عرض",
+ ["ro"]="latimeminima",
+ },
+ ["mirrored"]={
+ ["cs"]="zrcadleno",
+ ["de"]="gespiegelt",
+ ["en"]="mirrored",
+ ["fr"]="reflete",
+ ["it"]="riflesso",
+ ["nl"]="gespiegeld",
+ ["pe"]="منعکس",
+ ["ro"]="oglindit",
+ },
+ ["mixed"]={
+ ["en"]="mixed",
+ },
+ ["monday"]={
+ ["cs"]="pondeli",
+ ["de"]="montag",
+ ["en"]="monday",
+ ["fr"]="lundi",
+ ["it"]="lunedi",
+ ["nl"]="maandag",
+ ["pe"]="دوشنبه",
+ ["ro"]="luni",
+ },
+ ["mono"]={
+ ["cs"]="mono",
+ ["de"]="mono",
+ ["en"]="mono",
+ ["fr"]="mono",
+ ["it"]="mono",
+ ["nl"]="mono",
+ ["pe"]="مونو",
+ ["ro"]="mono",
+ },
+ ["monobold"]={
+ ["cs"]="monotucne",
+ ["de"]="monofett",
+ ["en"]="monobold",
+ ["fr"]="monogras",
+ ["it"]="monograssetto",
+ ["nl"]="monovet",
+ ["pe"]="monobold",
+ ["ro"]="monoaldin",
+ },
+ ["mononormal"]={
+ ["en"]="mononormal",
+ },
+ ["month"]={
+ ["cs"]="mesic",
+ ["de"]="monat",
+ ["en"]="month",
+ ["fr"]="mois",
+ ["it"]="mese",
+ ["nl"]="maand",
+ ["pe"]="ماه",
+ ["ro"]="luna",
+ },
+ ["more"]={
+ ["en"]="more",
+ ["nl"]="meer",
+ },
+ ["morehyphenation"]={
+ ["cs"]="morehyphenation",
+ ["de"]="morehyphenation",
+ ["en"]="morehyphenation",
+ ["fr"]="morehyphenation",
+ ["it"]="morehyphenation",
+ ["nl"]="morehyphenation",
+ ["pe"]="شکست‌کلمات‌بیشتر",
+ ["ro"]="morehyphenation",
+ },
+ ["name"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nom",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نام",
+ ["ro"]="nume",
+ },
+ ["narrow"]={
+ ["cs"]="uzky",
+ ["de"]="schmall",
+ ["en"]="narrow",
+ ["fr"]="etroit",
+ ["it"]="stretto",
+ ["nl"]="smal",
+ ["pe"]="نازک",
+ ["ro"]="ingust",
+ },
+ ["negative"]={
+ ["cs"]="negativ",
+ ["de"]="negativ",
+ ["en"]="negative",
+ ["fr"]="negatif",
+ ["it"]="negativo",
+ ["nl"]="negatief",
+ ["pe"]="منفی",
+ ["ro"]="negativ",
+ },
+ ["never"]={
+ ["cs"]="nikdy",
+ ["de"]="nie",
+ ["en"]="never",
+ ["fr"]="jamais",
+ ["it"]="mai",
+ ["nl"]="nooit",
+ ["pe"]="هیچگاه",
+ ["ro"]="niciodata",
+ },
+ ["new"]={
+ ["cs"]="novy",
+ ["de"]="neu",
+ ["en"]="new",
+ ["fr"]="nouveau",
+ ["it"]="nuovo",
+ ["nl"]="nieuw",
+ ["pe"]="جدید",
+ ["ro"]="nou",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="prochain",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["nextevenpage"]={
+ ["cs"]="dalsisudastranka",
+ ["de"]="naechstegeradeseite",
+ ["en"]="nextevenpage",
+ ["fr"]="pagepairesuivante",
+ ["it"]="paginaparisuccessiva",
+ ["nl"]="volgendeevenpagina",
+ ["pe"]="صفحه‌زوج‌بعدی",
+ ["ro"]="paginaparaurmatoarea",
+ },
+ ["nextoddpage"]={
+ ["cs"]="dalsilichastranka",
+ ["de"]="naechsteungeradeseite",
+ ["en"]="nextoddpage",
+ ["fr"]="pageimpairesuivante",
+ ["it"]="paginadisparisuccessiva",
+ ["nl"]="volgendeonevenpagina",
+ ["pe"]="صفحه‌فردبعدی",
+ ["ro"]="paginaimparaurmatoarea",
+ },
+ ["nextpage"]={
+ ["cs"]="dalsistranka",
+ ["de"]="folgendeseite",
+ ["en"]="nextpage",
+ ["fr"]="pagesuivante",
+ ["it"]="paginasuccessiva",
+ ["nl"]="volgendepagina",
+ ["pe"]="صفحه‌بعدی",
+ ["ro"]="paginaurmatoare",
+ },
+ ["nextsubpage"]={
+ ["cs"]="dalsipodstranka",
+ ["de"]="folgendeunterseite",
+ ["en"]="nextsubpage",
+ ["fr"]="souspagesuivante",
+ ["it"]="sottopaginasuccessiva",
+ ["nl"]="volgendesubpagina",
+ ["pe"]="زیرصفحه‌بعدی",
+ ["ro"]="urmatoareasubpagina",
+ },
+ ["no"]={
+ ["cs"]="ne",
+ ["de"]="nein",
+ ["en"]="no",
+ ["fr"]="non",
+ ["it"]="no",
+ ["nl"]="nee",
+ ["pe"]="نه",
+ ["ro"]="nu",
+ },
+ ["nocheck"]={
+ ["cs"]="nocheck",
+ ["de"]="nocheck",
+ ["en"]="nocheck",
+ ["fr"]="nonverifie",
+ ["it"]="nocheck",
+ ["nl"]="geencontrole",
+ ["pe"]="بدون‌بررسی",
+ ["ro"]="nocheck",
+ },
+ ["nodepth"]={
+ ["en"]="nodepth",
+ },
+ ["nofit"]={
+ ["cs"]="nofit",
+ ["de"]="nofit",
+ ["en"]="nofit",
+ ["fr"]="nofit",
+ ["it"]="nofit",
+ ["nl"]="nietpassend",
+ ["pe"]="بدون‌پرکردن",
+ ["ro"]="nofit",
+ },
+ ["nogrid"]={
+ ["cs"]="nogrid",
+ ["de"]="nogrid",
+ ["en"]="nogrid",
+ ["fr"]="nogrid",
+ ["it"]="nogrid",
+ ["nl"]="geengrid",
+ ["pe"]="بدون‌توری",
+ ["ro"]="nogrid",
+ },
+ ["noheight"]={
+ ["en"]="noheight",
+ },
+ ["nohz"]={
+ ["cs"]="nohz",
+ ["de"]="nohz",
+ ["en"]="nohz",
+ ["fr"]="nohz",
+ ["it"]="nohz",
+ ["nl"]="geenhz",
+ ["pe"]="nohz",
+ ["ro"]="nohz",
+ },
+ ["noline"]={
+ ["en"]="noline",
+ },
+ ["nomarking"]={
+ ["cs"]="zadneznaceni",
+ ["de"]="keinebeschriftung",
+ ["en"]="nomarking",
+ ["fr"]="sansmarquage",
+ ["it"]="nomarcature",
+ ["nl"]="geenmarkering",
+ ["pe"]="بدون‌نشانه‌گذاری",
+ ["ro"]="faramarcare",
+ },
+ ["none"]={
+ ["cs"]="zadny",
+ ["de"]="kein",
+ ["en"]="none",
+ ["fr"]="rien",
+ ["it"]="nessuno",
+ ["nl"]="geen",
+ ["pe"]="هیچکدام",
+ ["ro"]="niciunul",
+ },
+ ["nonumber"]={
+ ["cs"]="nonumber",
+ ["de"]="nonumber",
+ ["en"]="nonumber",
+ ["fr"]="sansnumero",
+ ["it"]="nonumber",
+ ["nl"]="geennummer",
+ ["pe"]="بدون‌شماره",
+ ["ro"]="nonumber",
+ },
+ ["norepeat"]={
+ ["en"]="norepeat",
+ },
+ ["normal"]={
+ ["cs"]="normalni",
+ ["de"]="normal",
+ ["en"]="normal",
+ ["fr"]="normal",
+ ["it"]="normale",
+ ["nl"]="normaal",
+ ["pe"]="نرمال",
+ ["ro"]="normal",
+ },
+ ["nospacing"]={
+ ["cs"]="nospacing",
+ ["de"]="nospacing",
+ ["en"]="nospacing",
+ ["fr"]="sansespacement",
+ ["it"]="nospacing",
+ ["nl"]="geenspatiering",
+ ["pe"]="بدون‌فضاگذاری",
+ ["ro"]="nospacing",
+ },
+ ["not"]={
+ ["cs"]="ne",
+ ["de"]="nicht",
+ ["en"]="not",
+ ["fr"]="pas",
+ ["it"]="non",
+ ["nl"]="niet",
+ ["pe"]="بدون",
+ ["ro"]="nu",
+ },
+ ["notation"]={
+ ["en"]="notation",
+ },
+ ["note"]={
+ ["en"]="note",
+ },
+ ["nothanging"]={
+ ["cs"]="nothanging",
+ ["de"]="nothanging",
+ ["en"]="nothanging",
+ ["fr"]="nonsuspendu",
+ ["it"]="nonsospeso",
+ ["nl"]="niethangend",
+ ["pe"]="بدون‌آویزان‌کردن",
+ ["ro"]="nothanging",
+ },
+ ["nothyphenated"]={
+ ["cs"]="nothyphenated",
+ ["de"]="nothyphenated",
+ ["en"]="nothyphenated",
+ ["fr"]="nothyphenated",
+ ["it"]="nonsillabato",
+ ["nl"]="nietafgebroken",
+ ["pe"]="بدون‌شکست",
+ ["ro"]="nedespsilabe",
+ },
+ ["november"]={
+ ["cs"]="listopad",
+ ["de"]="november",
+ ["en"]="november",
+ ["fr"]="novembre",
+ ["it"]="novembre",
+ ["nl"]="november",
+ ["pe"]="نوامبر",
+ ["ro"]="noiembrie",
+ },
+ ["nowhere"]={
+ ["cs"]="nikde",
+ ["de"]="nirgens",
+ ["en"]="nowhere",
+ ["fr"]="nulpart",
+ ["it"]="danessunaparte",
+ ["nl"]="nergens",
+ ["pe"]="هیچ‌حا",
+ ["ro"]="niciunde",
+ },
+ ["nowhite"]={
+ ["cs"]="zadnabila",
+ ["de"]="keinweiss",
+ ["en"]="nowhite",
+ ["fr"]="sansblanc",
+ ["it"]="nobianco",
+ ["nl"]="geenwit",
+ ["pe"]="سفید‌نه",
+ ["ro"]="faraalb",
+ },
+ ["number"]={
+ ["cs"]="cislo",
+ ["de"]="nummer",
+ ["en"]="number",
+ ["fr"]="numero",
+ ["it"]="numero",
+ ["nl"]="nummer",
+ ["pe"]="شماره",
+ ["ro"]="numar",
+ },
+ ["numbers"]={
+ ["cs"]="cisla",
+ ["de"]="ziffern",
+ ["en"]="numbers",
+ ["fr"]="numeros",
+ ["it"]="numeri",
+ ["nl"]="cijfers",
+ ["pe"]="شماره‌ها",
+ ["ro"]="numere",
+ },
+ ["october"]={
+ ["cs"]="rijen",
+ ["de"]="oktober",
+ ["en"]="october",
+ ["fr"]="octobre",
+ ["it"]="ottobre",
+ ["nl"]="oktober",
+ ["pe"]="اکتبر",
+ ["ro"]="octombrie",
+ },
+ ["odd"]={
+ ["cs"]="liche",
+ ["de"]="ungerade",
+ ["en"]="odd",
+ ["fr"]="impair",
+ ["it"]="dispari",
+ ["nl"]="oneven",
+ ["pe"]="فرد",
+ ["ro"]="impar",
+ },
+ ["off"]={
+ ["cs"]="vyp",
+ ["de"]="aus",
+ ["en"]="off",
+ ["fr"]="desactive",
+ ["it"]="disattivo",
+ ["nl"]="uit",
+ ["pe"]="خاموش",
+ ["ro"]="dezactivat",
+ },
+ ["offset"]={
+ ["cs"]="offset",
+ ["de"]="offset",
+ ["en"]="offset",
+ ["fr"]="offset",
+ ["it"]="offset",
+ ["nl"]="offset",
+ ["pe"]="آفست",
+ ["ro"]="offset",
+ },
+ ["old"]={
+ ["cs"]="old",
+ ["de"]="old",
+ ["en"]="old",
+ ["fr"]="old",
+ ["it"]="old",
+ ["nl"]="oud",
+ ["pe"]="قدیمی",
+ ["ro"]="old",
+ },
+ ["oldstyle"]={
+ ["en"]="oldstyle",
+ },
+ ["on"]={
+ ["cs"]="zap",
+ ["de"]="an",
+ ["en"]="on",
+ ["fr"]="actif",
+ ["it"]="attivo",
+ ["nl"]="aan",
+ ["pe"]="روی",
+ ["ro"]="on",
+ },
+ ["one"]={
+ ["cs"]="jedna",
+ ["de"]="eins",
+ ["en"]="one",
+ ["fr"]="un",
+ ["it"]="uno",
+ ["nl"]="een",
+ ["pe"]="یک",
+ ["ro"]="unu",
+ },
+ ["opposite"]={
+ ["cs"]="naproti",
+ ["de"]="gegenueber",
+ ["en"]="opposite",
+ ["fr"]="opposition",
+ ["it"]="opposto",
+ ["nl"]="naast",
+ ["pe"]="مخالف",
+ ["ro"]="opus",
+ },
+ ["outer"]={
+ ["cs"]="vnejsi",
+ ["de"]="aussen",
+ ["en"]="outer",
+ ["fr"]="exterieur",
+ ["it"]="esterno",
+ ["nl"]="buiten",
+ ["pe"]="خارجی",
+ ["ro"]="extern",
+ },
+ ["outeredge"]={
+ ["cs"]="outeredge",
+ ["de"]="outeredge",
+ ["en"]="outeredge",
+ ["fr"]="bordexterieur",
+ ["it"]="bordoesterno",
+ ["nl"]="buitenrand",
+ ["pe"]="لبه‌خارجی",
+ ["ro"]="outeredge",
+ },
+ ["outermargin"]={
+ ["cs"]="outermargin",
+ ["de"]="outermargin",
+ ["en"]="outermargin",
+ ["fr"]="margeexterieure",
+ ["it"]="margineesterno",
+ ["nl"]="buitenmarge",
+ ["pe"]="حاشیه‌خارجی",
+ ["ro"]="outermargin",
+ },
+ ["overbar"]={
+ ["cs"]="nadtrzeno",
+ ["de"]="ueberstrichen",
+ ["en"]="overbar",
+ ["fr"]="overbar",
+ ["it"]="sopralinea",
+ ["nl"]="overstreep",
+ ["pe"]="میله‌رو",
+ ["ro"]="barasus",
+ },
+ ["overbars"]={
+ ["cs"]="nadtrzeni",
+ ["de"]="ueberstreichen",
+ ["en"]="overbars",
+ ["fr"]="overbars",
+ ["it"]="sopralinee",
+ ["nl"]="overstrepen",
+ ["pe"]="میله‌ها‌رو",
+ ["ro"]="supralinie",
+ },
+ ["overlay"]={
+ ["cs"]="prekryv",
+ ["de"]="overlay",
+ ["en"]="overlay",
+ ["fr"]="revetement",
+ ["it"]="sovrapponi",
+ ["nl"]="overlay",
+ ["pe"]="پوشش",
+ ["ro"]="overlay",
+ },
+ ["overprint"]={
+ ["cs"]="overprint",
+ ["de"]="overprint",
+ ["en"]="overprint",
+ ["fr"]="overprint",
+ ["it"]="overprint",
+ ["nl"]="overprint",
+ ["pe"]="overprint",
+ ["ro"]="overprint",
+ },
+ ["overstrike"]={
+ ["cs"]="preskrtnuto",
+ ["de"]="durchgestrichen",
+ ["en"]="overstrike",
+ ["fr"]="surlignetout",
+ ["it"]="sbarrato",
+ ["nl"]="doorstreep",
+ ["pe"]="خط‌زدن",
+ ["ro"]="liniepeste",
+ },
+ ["overstrikes"]={
+ ["cs"]="preskrtnuti",
+ ["de"]="durchstreichen",
+ ["en"]="overstrikes",
+ ["fr"]="surligne",
+ ["it"]="sbarrati",
+ ["nl"]="doorstrepen",
+ ["pe"]="خط‌زدنها",
+ ["ro"]="liniipeste",
+ },
+ ["packed"]={
+ ["cs"]="zhustene",
+ ["de"]="gepackt",
+ ["en"]="packed",
+ ["fr"]="groupe",
+ ["it"]="impaccato",
+ ["nl"]="opelkaar",
+ ["pe"]="فشرده",
+ ["ro"]="impachetat",
+ },
+ ["page"]={
+ ["cs"]="stranka",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pagecomment"]={
+ ["cs"]="komentarstranky",
+ ["de"]="pagecomment",
+ ["en"]="pagecomment",
+ ["fr"]="commentairepage",
+ ["it"]="commentopagina",
+ ["nl"]="paginacommentaar",
+ ["pe"]="توضیح‌صفحه",
+ ["ro"]="comentariupagina",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostranky",
+ ["de"]="seitennummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شماره‌صفحه",
+ ["ro"]="numarpagina",
+ },
+ ["paper"]={
+ ["cs"]="papir",
+ ["de"]="papier",
+ ["en"]="paper",
+ ["fr"]="papier",
+ ["it"]="carta",
+ ["nl"]="papier",
+ ["pe"]="برگ",
+ ["ro"]="foaie",
+ },
+ ["paragraph"]={
+ ["cs"]="odstavec",
+ ["de"]="absatz",
+ ["en"]="paragraph",
+ ["fr"]="paragraphe",
+ ["it"]="capoverso",
+ ["nl"]="alinea",
+ ["pe"]="پاراگراف",
+ ["ro"]="paragraf",
+ },
+ ["part"]={
+ ["cs"]="cast",
+ ["de"]="teil",
+ ["en"]="part",
+ ["fr"]="partie",
+ ["it"]="parte",
+ ["nl"]="deel",
+ ["pe"]="قسمت",
+ ["ro"]="parte",
+ },
+ ["positive"]={
+ ["cs"]="positiv",
+ ["de"]="positiv",
+ ["en"]="positive",
+ ["fr"]="positif",
+ ["it"]="positivo",
+ ["nl"]="positief",
+ ["pe"]="مثبت",
+ ["ro"]="positiv",
+ },
+ ["postponing"]={
+ ["cs"]="odlozit",
+ ["de"]="verschieben",
+ ["en"]="postponing",
+ ["fr"]="postponing",
+ ["it"]="posporre",
+ ["nl"]="uitstellen",
+ ["pe"]="تاخیر",
+ ["ro"]="postponing",
+ },
+ ["postscript"]={
+ ["cs"]="postscript",
+ ["de"]="postscript",
+ ["en"]="postscript",
+ ["fr"]="postscript",
+ ["it"]="postscript",
+ ["nl"]="postscript",
+ ["pe"]="پست‌اسکریپت",
+ ["ro"]="postscript",
+ },
+ ["precedingpage"]={
+ ["en"]="followingpage",
+ ["nl"]="voorafgaandepagina",
+ },
+ ["preference"]={
+ ["cs"]="nastaveni",
+ ["de"]="einstellung",
+ ["en"]="preference",
+ ["fr"]="preference",
+ ["it"]="preferenza",
+ ["nl"]="voorkeur",
+ ["pe"]="ترجیح",
+ ["ro"]="preferinta",
+ },
+ ["preview"]={
+ ["cs"]="nahled",
+ ["de"]="vorschau",
+ ["en"]="preview",
+ ["fr"]="previsualisation",
+ ["it"]="anteprima",
+ ["nl"]="preview",
+ ["pe"]="پیش‌دید",
+ ["ro"]="previzualizare",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorig",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precedent",
+ },
+ ["previousevenpage"]={
+ ["cs"]="predchozisudastranka",
+ ["de"]="vorigegeradeseite",
+ ["en"]="previousevenpage",
+ ["fr"]="pagepaireprecedente",
+ ["it"]="paginapariprecedente",
+ ["nl"]="vorigeevenpagina",
+ ["pe"]="صفحه‌زوج‌قبلی",
+ ["ro"]="paginaparaprecedenta",
+ },
+ ["previousoddpage"]={
+ ["cs"]="predchozilichastranka",
+ ["de"]="vorigeungeradeseite",
+ ["en"]="previousoddpage",
+ ["fr"]="pageimpaireprecedente",
+ ["it"]="paginadispariprecedente",
+ ["nl"]="vorigeonevenpagina",
+ ["pe"]="صفحه‌فردقبلی",
+ ["ro"]="paginaimparaprecedenta",
+ },
+ ["previouspage"]={
+ ["cs"]="predchozistranka",
+ ["de"]="vorigeseite",
+ ["en"]="previouspage",
+ ["fr"]="pageprecedente",
+ ["it"]="paginaprecedente",
+ ["nl"]="vorigepagina",
+ ["pe"]="صفحه‌قبلی",
+ ["ro"]="paginaanterioara",
+ },
+ ["previoussubpage"]={
+ ["cs"]="predchozipodstranka",
+ ["de"]="vorigeunterseite",
+ ["en"]="previoussubpage",
+ ["fr"]="souspageprecedente",
+ ["it"]="sottopaginaprecedente",
+ ["nl"]="vorigesubpagina",
+ ["pe"]="زیرصفحه‌قبلی",
+ ["ro"]="subpaginaanterioara",
+ },
+ ["print"]={
+ ["en"]="print",
+ ["nl"]="print",
+ },
+ ["printable"]={
+ ["cs"]="tisknutelne",
+ ["de"]="druckbar",
+ ["en"]="printable",
+ ["fr"]="editable",
+ ["it"]="stampabile",
+ ["nl"]="printbaar",
+ ["pe"]="قابل‌چاپ",
+ ["ro"]="tiparibil",
+ },
+ ["process"]={
+ ["cs"]="process",
+ ["de"]="process",
+ ["en"]="process",
+ ["fr"]="process",
+ ["it"]="process",
+ ["nl"]="proces",
+ ["pe"]="پردازش",
+ ["ro"]="process",
+ },
+ ["product"]={
+ ["cs"]="produkt",
+ ["de"]="produkt",
+ ["en"]="product",
+ ["fr"]="produit",
+ ["it"]="prodotto",
+ ["nl"]="produkt",
+ ["pe"]="محصول",
+ ["ro"]="produs",
+ },
+ ["program"]={
+ ["cs"]="program",
+ ["de"]="programm",
+ ["en"]="program",
+ ["fr"]="programme",
+ ["it"]="programma",
+ ["nl"]="programma",
+ ["pe"]="برنامه",
+ ["ro"]="program",
+ },
+ ["project"]={
+ ["cs"]="projekt",
+ ["de"]="projekt",
+ ["en"]="project",
+ ["fr"]="projet",
+ ["it"]="progetto",
+ ["nl"]="project",
+ ["pe"]="پروژه",
+ ["ro"]="proiect",
+ },
+ ["protected"]={
+ ["cs"]="chranene",
+ ["de"]="geschuetzt",
+ ["en"]="protected",
+ ["fr"]="protege",
+ ["it"]="protetto",
+ ["nl"]="beschermd",
+ ["pe"]="حفاظت‌شده",
+ ["ro"]="protejat",
+ },
+ ["quadruple"]={
+ ["cs"]="ctyrnasobny",
+ ["de"]="viertel",
+ ["en"]="quadruple",
+ ["fr"]="quadruple",
+ ["it"]="quadruplo",
+ ["nl"]="viertal",
+ ["pe"]="quadruple",
+ ["ro"]="cvadrupul",
+ },
+ ["quarterline"]={
+ ["en"]="quarterline",
+ ["nl"]="kwartregel",
+ },
+ ["quotation"]={
+ ["cs"]="citace",
+ ["de"]="zitat",
+ ["en"]="quotation",
+ ["fr"]="citation",
+ ["it"]="citazione",
+ ["nl"]="citaat",
+ ["pe"]="نقل‌قول",
+ ["ro"]="citat",
+ },
+ ["quote"]={
+ ["cs"]="citovat",
+ ["de"]="zitieren",
+ ["en"]="quote",
+ ["fr"]="citer",
+ ["it"]="menzione",
+ ["nl"]="citeer",
+ ["pe"]="نقل",
+ ["ro"]="minicitat",
+ },
+ ["ran"]={
+ ["cs"]="rozsah",
+ ["de"]="ran",
+ ["en"]="ran",
+ ["fr"]="cours",
+ ["it"]="corse",
+ ["nl"]="ran",
+ ["pe"]="برد",
+ ["ro"]="rulat",
+ },
+ ["random"]={
+ ["cs"]="nahodny",
+ ["de"]="zufaellig",
+ ["en"]="random",
+ ["fr"]="aleatoire",
+ ["it"]="casuale",
+ ["nl"]="willekeurig",
+ ["pe"]="تصادفی",
+ ["ro"]="aleator",
+ },
+ ["readonly"]={
+ ["cs"]="pouzeprocteni",
+ ["de"]="nurlesbar",
+ ["en"]="readonly",
+ ["fr"]="lectureseule",
+ ["it"]="solalettura",
+ ["nl"]="alleenleesbaar",
+ ["pe"]="تنهاخواندنی",
+ ["ro"]="readonly",
+ },
+ ["rectangular"]={
+ ["cs"]="pravouhly",
+ ["de"]="rechteckig",
+ ["en"]="rectangular",
+ ["fr"]="rectangulaire",
+ ["it"]="rettangolare",
+ ["nl"]="recht",
+ ["pe"]="چهارگوشه",
+ ["ro"]="rectangular",
+ },
+ ["reference"]={
+ ["cs"]="odkaz",
+ ["de"]="referenz",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="riferimento",
+ ["nl"]="referentie",
+ ["pe"]="مرجع",
+ ["ro"]="referinta",
+ },
+ ["referral"]={
+ ["cs"]="znacka",
+ ["de"]="merkmal",
+ ["en"]="referral",
+ ["fr"]="referral",
+ ["it"]="referral",
+ ["nl"]="kenmerk",
+ ["pe"]="مراجعه",
+ ["ro"]="referinta",
+ },
+ ["register"]={
+ ["cs"]="rejstrik",
+ ["de"]="register",
+ ["en"]="register",
+ ["fr"]="registre",
+ ["it"]="registro",
+ ["nl"]="register",
+ ["pe"]="ثبت",
+ ["ro"]="registru",
+ },
+ ["regular"]={
+ ["cs"]="pravidelne",
+ ["de"]="regular",
+ ["en"]="regular",
+ ["fr"]="regulier",
+ ["it"]="regolare",
+ ["nl"]="regular",
+ ["pe"]="منظم",
+ ["ro"]="regular",
+ },
+ ["rekening"]={
+ ["cs"]="rekening",
+ ["de"]="rekening",
+ ["en"]="rekening",
+ ["fr"]="rekening",
+ ["it"]="rekening",
+ ["nl"]="rekening",
+ ["pe"]="rekening",
+ ["ro"]="rekening",
+ },
+ ["relative"]={
+ ["cs"]="relativni",
+ ["de"]="relativ",
+ ["en"]="relative",
+ ["fr"]="relatif",
+ ["it"]="relativo",
+ ["nl"]="relatief",
+ ["pe"]="نسبی",
+ ["ro"]="relativ",
+ },
+ ["repeat"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="repeat",
+ ["fr"]="repete",
+ ["it"]="ripeti",
+ ["nl"]="herhaal",
+ ["pe"]="تکرار",
+ ["ro"]="repetat",
+ },
+ ["required"]={
+ ["cs"]="pozadovane",
+ ["de"]="obligatorisch",
+ ["en"]="required",
+ ["fr"]="recquis",
+ ["it"]="richiestp",
+ ["nl"]="verplicht",
+ ["pe"]="موردنیاز",
+ ["ro"]="obligatoriu",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="zuruecksetzten",
+ ["en"]="reset",
+ ["fr"]="raz",
+ ["it"]="reimposta",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["reverse"]={
+ ["cs"]="reverse",
+ ["de"]="reverse",
+ ["en"]="reverse",
+ ["fr"]="inverse",
+ ["it"]="invertito",
+ ["nl"]="omgekeerd",
+ ["pe"]="برعکس",
+ ["ro"]="reverse",
+ },
+ ["right"]={
+ ["cs"]="vpravo",
+ ["de"]="rechts",
+ ["en"]="right",
+ ["fr"]="droite",
+ ["it"]="destra",
+ ["nl"]="rechts",
+ ["pe"]="راست",
+ ["ro"]="dreapta",
+ },
+ ["rightedge"]={
+ ["cs"]="pravahrana",
+ ["de"]="rechterkante",
+ ["en"]="rightedge",
+ ["fr"]="borddroit",
+ ["it"]="bordodestro",
+ ["nl"]="rechterrand",
+ ["pe"]="لبه‌راست",
+ ["ro"]="borduradreapta",
+ },
+ ["righthanging"]={
+ ["cs"]="righthanging",
+ ["de"]="righthanging",
+ ["en"]="righthanging",
+ ["fr"]="righthanging",
+ ["it"]="righthanging",
+ ["nl"]="rechtshangend",
+ ["pe"]="آویزان‌کردن‌راست",
+ ["ro"]="righthanging",
+ },
+ ["rightmargin"]={
+ ["cs"]="pravyokraj",
+ ["de"]="rechterrand",
+ ["en"]="rightmargin",
+ ["fr"]="margedroite",
+ ["it"]="marginedestro",
+ ["nl"]="rechtermarge",
+ ["pe"]="حاشیه‌راست",
+ ["ro"]="marginedreapta",
+ },
+ ["rightpage"]={
+ ["cs"]="pravastranka",
+ ["de"]="rechterseite",
+ ["en"]="rightpage",
+ ["fr"]="pagedroite",
+ ["it"]="paginadestra",
+ ["nl"]="rechterpagina",
+ ["pe"]="صفحه‌راست",
+ ["ro"]="paginadreapta",
+ },
+ ["righttoleft"]={
+ ["cs"]="righttoleft",
+ ["de"]="righttoleft",
+ ["en"]="righttoleft",
+ ["fr"]="righttoleft",
+ ["it"]="righttoleft",
+ ["nl"]="righttoleft",
+ ["pe"]="righttoleft",
+ ["ro"]="righttoleft",
+ },
+ ["roman"]={
+ ["cs"]="antikva",
+ ["de"]="antiqua",
+ ["en"]="roman",
+ ["fr"]="roman",
+ ["it"]="roman",
+ ["nl"]="romaan",
+ ["pe"]="رومن",
+ ["ro"]="roman",
+ },
+ ["romannumerals"]={
+ ["cs"]="rimskecislice",
+ ["de"]="roemischezahlen",
+ ["en"]="romannumerals",
+ ["fr"]="chiffresromains",
+ ["it"]="numeriromani",
+ ["nl"]="romeins",
+ ["pe"]="شماره‌لاتین",
+ ["ro"]="numereromane",
+ },
+ ["rotate"]={
+ ["cs"]="otoc",
+ ["de"]="drehe",
+ ["en"]="rotate",
+ ["fr"]="oriente",
+ ["it"]="ruota",
+ ["nl"]="roteer",
+ ["pe"]="دوران",
+ ["ro"]="rotit",
+ },
+ ["rotated"]={
+ ["cs"]="otoceno",
+ ["de"]="gedreht",
+ ["en"]="rotated",
+ ["fr"]="tourne",
+ ["it"]="ruotato",
+ ["nl"]="geroteerd",
+ ["pe"]="دوران‌یافته",
+ ["ro"]="rotat",
+ },
+ ["round"]={
+ ["cs"]="zaobleny",
+ ["de"]="rund",
+ ["en"]="round",
+ ["fr"]="rond",
+ ["it"]="rotondo",
+ ["nl"]="rond",
+ ["pe"]="گرد",
+ ["ro"]="rotund",
+ },
+ ["row"]={
+ ["cs"]="row",
+ ["de"]="row",
+ ["en"]="row",
+ ["fr"]="rang",
+ ["it"]="row",
+ ["nl"]="rij",
+ ["pe"]="سطر",
+ ["ro"]="rand",
+ },
+ ["rule"]={
+ ["cs"]="linka",
+ ["de"]="linie",
+ ["en"]="rule",
+ ["fr"]="regle",
+ ["it"]="linea",
+ ["nl"]="lijn",
+ ["pe"]="خط",
+ ["ro"]="rigla",
+ },
+ ["samepage"]={
+ ["cs"]="stejnastranka",
+ ["de"]="selbeseite",
+ ["en"]="samepage",
+ ["fr"]="memepage",
+ ["it"]="stessapagina",
+ ["nl"]="zelfdepagina",
+ ["pe"]="همان‌صفحه",
+ ["ro"]="aceeasipagina",
+ },
+ ["sans"]={
+ ["cs"]="sans",
+ ["de"]="sans",
+ ["en"]="sans",
+ ["fr"]="sans",
+ ["it"]="sans",
+ ["nl"]="sans",
+ ["pe"]="سانز",
+ ["ro"]="sans",
+ },
+ ["sansbold"]={
+ ["cs"]="sanstucne",
+ ["de"]="sansfett",
+ ["en"]="sansbold",
+ ["fr"]="sansgras",
+ ["it"]="sansgrassetto",
+ ["nl"]="sansvet",
+ ["pe"]="مشکی‌سانز",
+ ["ro"]="sansaldin",
+ },
+ ["sansnormal"]={
+ ["en"]="sansnormal",
+ },
+ ["sansserif"]={
+ ["cs"]="bezserifu",
+ ["de"]="grotesk",
+ ["en"]="sansserif",
+ ["fr"]="sansserif",
+ ["it"]="sansserif",
+ ["nl"]="schreefloos",
+ ["pe"]="سانزسریف",
+ ["ro"]="sansserif",
+ },
+ ["saturday"]={
+ ["cs"]="sobota",
+ ["de"]="samstag",
+ ["en"]="saturday",
+ ["fr"]="samedi",
+ ["it"]="sabato",
+ ["nl"]="zaterdag",
+ ["pe"]="شنبه",
+ ["ro"]="sambata",
+ },
+ ["screen"]={
+ ["cs"]="rastr",
+ ["de"]="raster",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="raster",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["section"]={
+ ["cs"]="sekce",
+ ["de"]="absatz",
+ ["en"]="section",
+ ["fr"]="section",
+ ["it"]="capoverso",
+ ["nl"]="paragraaf",
+ ["pe"]="بخش",
+ ["ro"]="sectiune",
+ },
+ ["sectionblockenvironment"]={
+ ["cs"]="sectionblockenvironment",
+ ["de"]="sectionblockenvironment",
+ ["en"]="sectionblockenvironment",
+ ["fr"]="environementblocsection",
+ ["it"]="ambientebloccosezione",
+ ["nl"]="sectieblokomgeving",
+ ["pe"]="محیط‌بلوک‌بخش",
+ ["ro"]="blocsectiuneambient",
+ },
+ ["sectionnumber"]={
+ ["cs"]="cislooddilu",
+ ["de"]="abschnittsnummer",
+ ["en"]="sectionnumber",
+ ["fr"]="numerosection",
+ ["it"]="numerosezione",
+ ["nl"]="sectienummer",
+ ["pe"]="شماره‌بخش",
+ ["ro"]="numarsetiune",
+ },
+ ["see"]={
+ ["cs"]="viz",
+ ["de"]="sieh",
+ ["en"]="see",
+ ["fr"]="voit",
+ ["it"]="vedi",
+ ["nl"]="zie",
+ ["pe"]="ببینید",
+ ["ro"]="vezi",
+ },
+ ["selectfont"]={
+ ["en"]="selectfont",
+ },
+ ["september"]={
+ ["cs"]="zari",
+ ["de"]="september",
+ ["en"]="september",
+ ["fr"]="septembre",
+ ["it"]="settembre",
+ ["nl"]="september",
+ ["pe"]="سپتامبر",
+ ["ro"]="septembrie",
+ },
+ ["serif"]={
+ ["cs"]="serif",
+ ["de"]="serif",
+ ["en"]="serif",
+ ["fr"]="serif",
+ ["it"]="serif",
+ ["nl"]="serif",
+ ["pe"]="سریف",
+ ["ro"]="serif",
+ },
+ ["serifbold"]={
+ ["en"]="serifbold",
+ },
+ ["serifnormal"]={
+ ["en"]="serifnormal",
+ },
+ ["serried"]={
+ ["cs"]="semknuto",
+ ["de"]="kleinerabstand",
+ ["en"]="serried",
+ ["fr"]="serried",
+ ["it"]="vicino",
+ ["nl"]="aanelkaar",
+ ["pe"]="تنگ‌هم",
+ ["ro"]="serried",
+ },
+ ["setups"]={
+ ["comment"]="no translations",
+ ["en"]="setups",
+ },
+ ["sheet"]={
+ ["cs"]="sheet",
+ ["de"]="sheet",
+ ["en"]="sheet",
+ ["fr"]="sheet",
+ ["it"]="sheet",
+ ["nl"]="sheet",
+ ["pe"]="ورقه",
+ ["ro"]="sheet",
+ },
+ ["shiftdown"]={
+ ["en"]="shiftdown",
+ },
+ ["shiftup"]={
+ ["en"]="shiftup",
+ },
+ ["short"]={
+ ["cs"]="short",
+ ["de"]="kurz",
+ ["en"]="short",
+ ["fr"]="short",
+ ["it"]="short",
+ ["nl"]="kort",
+ ["ro"]="short",
+ },
+ ["simplefonts"]={
+ ["en"]="simplefonts",
+ },
+ ["simplelist"]={
+ ["en"]="simplelist",
+ },
+ ["singlesided"]={
+ ["cs"]="jednostranne",
+ ["de"]="einzelseitig",
+ ["en"]="singlesided",
+ ["fr"]="recto",
+ ["it"]="facciasingola",
+ ["nl"]="enkelzijdig",
+ ["pe"]="یک‌رو",
+ ["ro"]="ofata",
+ },
+ ["slanted"]={
+ ["cs"]="sklonene",
+ ["de"]="geneigt",
+ ["en"]="slanted",
+ ["fr"]="incline",
+ ["it"]="inclinato",
+ ["nl"]="schuin",
+ ["pe"]="خوابیده",
+ ["ro"]="inclinat",
+ },
+ ["slantedbold"]={
+ ["cs"]="sklonenetucne",
+ ["de"]="geneigtfett",
+ ["en"]="slantedbold",
+ ["fr"]="grasincline",
+ ["it"]="inclinatograssetto",
+ ["nl"]="schuinvet",
+ ["pe"]="مشکی‌خوابیده",
+ ["ro"]="inclinataldin",
+ },
+ ["small"]={
+ ["cs"]="male",
+ ["de"]="klein",
+ ["en"]="small",
+ ["fr"]="petit",
+ ["it"]="piccolo",
+ ["nl"]="klein",
+ ["pe"]="کوچک",
+ ["ro"]="mic",
+ },
+ ["smallbodyfont"]={
+ ["cs"]="smallbodyfont",
+ ["de"]="smallbodyfont",
+ ["en"]="smallbodyfont",
+ ["fr"]="petitepolicecorps",
+ ["it"]="piccolofontdelcorpo",
+ ["nl"]="kleinkorps",
+ ["pe"]="قلم‌بدنه‌کوچک",
+ ["ro"]="smallbodyfont",
+ },
+ ["smallbold"]={
+ ["cs"]="maletucne",
+ ["de"]="kleinfett",
+ ["en"]="smallbold",
+ ["fr"]="graspetit",
+ ["it"]="piccolograssetto",
+ ["nl"]="kleinvet",
+ ["pe"]="مشکی‌کوچک",
+ ["ro"]="micaldin",
+ },
+ ["smallbolditalic"]={
+ ["cs"]="maletucnekurzivni",
+ ["de"]="kleinfettitalic",
+ ["en"]="smallbolditalic",
+ ["fr"]="italiquegraspetit",
+ ["it"]="piccolograssettocorsivo",
+ ["nl"]="kleinvetitalic",
+ ["pe"]="ایتالیک‌مشکی‌کوچک",
+ ["ro"]="micaldininclinat",
+ },
+ ["smallboldslanted"]={
+ ["cs"]="maletucnesklonene",
+ ["de"]="kleinfettgeneigt",
+ ["en"]="smallboldslanted",
+ ["fr"]="inclinegraspetit",
+ ["it"]="piccolograssettoinclinato",
+ ["nl"]="kleinvetschuin",
+ ["pe"]="خوابیده‌مشکی‌کوچک",
+ ["ro"]="micaldininclinat",
+ },
+ ["smallcaps"]={
+ ["cs"]="kapitalky",
+ ["de"]="smallcaps",
+ ["en"]="smallcaps",
+ ["fr"]="petitescapitales",
+ ["it"]="maiuscoletto",
+ ["nl"]="smallcaps",
+ ["pe"]="smallcaps",
+ ["ro"]="majusculemici",
+ },
+ ["smaller"]={
+ ["en"]="smaller",
+ ["nl"]="kleiner",
+ },
+ ["smallitalic"]={
+ ["cs"]="malekurzivni",
+ ["de"]="kleinitalic",
+ ["en"]="smallitalic",
+ ["fr"]="italiquepetit",
+ ["it"]="piccolocorsivo",
+ ["nl"]="kleinitalic",
+ ["pe"]="ایتالیک‌کوچک",
+ ["ro"]="micitalic",
+ },
+ ["smallitalicbold"]={
+ ["cs"]="malekurzivnitucne",
+ ["de"]="kleinitalicfett",
+ ["en"]="smallitalicbold",
+ ["fr"]="grasitaliquepetit",
+ ["it"]="piccolocorsivograssetto",
+ ["nl"]="kleinitalicvet",
+ ["pe"]="مشکی‌ایتالیک‌کوچک",
+ ["ro"]="micitalicaldin",
+ },
+ ["smallnormal"]={
+ ["cs"]="malenormalni",
+ ["de"]="kleinnormal",
+ ["en"]="smallnormal",
+ ["fr"]="normalpetit",
+ ["it"]="piccolonormale",
+ ["nl"]="kleinnormaal",
+ ["pe"]="نرمال‌کوچک",
+ ["ro"]="micnormal",
+ },
+ ["smallslanted"]={
+ ["cs"]="malesklonene",
+ ["de"]="kleingeneigt",
+ ["en"]="smallslanted",
+ ["fr"]="inclinepetit",
+ ["it"]="piccoloinclinato",
+ ["nl"]="kleinschuin",
+ ["pe"]="خوابیده‌کوچک",
+ ["ro"]="micinclinat",
+ },
+ ["smallslantedbold"]={
+ ["cs"]="malesklonenetucne",
+ ["de"]="kleingeneigtfett",
+ ["en"]="smallslantedbold",
+ ["fr"]="grasinclinepetit",
+ ["it"]="piccoloinclinatograssetto",
+ ["nl"]="kleinschuinvet",
+ ["pe"]="مشکی‌خوابیده‌کوچک",
+ ["ro"]="micinclinataldin",
+ },
+ ["smalltype"]={
+ ["cs"]="maletype",
+ ["de"]="kleintippen",
+ ["en"]="smalltype",
+ ["fr"]="petittype",
+ ["it"]="piccolotype",
+ ["nl"]="kleintype",
+ ["pe"]="تایپ‌کوچک",
+ ["ro"]="mictype",
+ },
+ ["somewhere"]={
+ ["cs"]="nekde",
+ ["de"]="irgendwo",
+ ["en"]="somewhere",
+ ["fr"]="qqpart",
+ ["it"]="daqualcheparte",
+ ["nl"]="ergens",
+ ["pe"]="جایی",
+ ["ro"]="undeva",
+ },
+ ["sorted"]={
+ ["cs"]="tridene",
+ ["de"]="sortiert",
+ ["en"]="sorted",
+ ["fr"]="trie",
+ ["it"]="ordinato",
+ ["nl"]="gesorteerd",
+ ["pe"]="مرتب",
+ ["ro"]="sortat",
+ },
+ ["sorting"]={
+ ["en"]="sorting",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["spacing"]={
+ ["cs"]="mezerovani",
+ ["de"]="spatiumausgleich",
+ ["en"]="spacing",
+ ["fr"]="espacement",
+ ["it"]="spaziatura",
+ ["nl"]="spatiering",
+ ["pe"]="فضاگذاری",
+ ["ro"]="spatiere",
+ },
+ ["speech"]={
+ ["cs"]="speech",
+ ["de"]="speech",
+ ["en"]="speech",
+ ["fr"]="discours",
+ ["it"]="speech",
+ ["nl"]="spraak",
+ ["pe"]="سخنرانی",
+ ["ro"]="speech",
+ },
+ ["split"]={
+ ["cs"]="split",
+ ["de"]="split",
+ ["en"]="split",
+ ["fr"]="split",
+ ["it"]="separa",
+ ["nl"]="splitsen",
+ ["pe"]="شکافتن",
+ ["ro"]="split",
+ },
+ ["spot"]={
+ ["cs"]="spot",
+ ["de"]="spot",
+ ["en"]="spot",
+ ["fr"]="spot",
+ ["it"]="spot",
+ ["nl"]="spot",
+ ["pe"]="لکه",
+ ["ro"]="spot",
+ },
+ ["standard"]={
+ ["cs"]="standardni",
+ ["de"]="standard",
+ ["en"]="standard",
+ ["fr"]="standard",
+ ["it"]="standard",
+ ["nl"]="standaard",
+ ["pe"]="استاندارد",
+ ["ro"]="standard",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["starter"]={
+ ["en"]="starter",
+ ["nl"]="opener",
+ },
+ ["sticker"]={
+ ["cs"]="sticker",
+ ["de"]="sticker",
+ ["en"]="sticker",
+ ["fr"]="sticker",
+ ["it"]="sticker",
+ ["nl"]="sticker",
+ ["pe"]="دشنه",
+ ["ro"]="sticker",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["stopper"]={
+ ["cs"]="predel",
+ ["de"]="trenner",
+ ["en"]="stopper",
+ ["fr"]="stopper",
+ ["it"]="stopper",
+ ["nl"]="afsluiter",
+ ["pe"]="ایست",
+ ["ro"]="stopper",
+ },
+ ["stretch"]={
+ ["cs"]="natahnout",
+ ["de"]="strecken",
+ ["en"]="stretch",
+ ["fr"]="etire",
+ ["it"]="dilata",
+ ["nl"]="rek",
+ ["pe"]="بکش",
+ ["ro"]="dilatat",
+ },
+ ["stretched"]={
+ ["en"]="stretched",
+ },
+ ["strict"]={
+ ["cs"]="striktni",
+ ["de"]="streng",
+ ["en"]="strict",
+ ["fr"]="strict",
+ ["it"]="rigido",
+ ["nl"]="streng",
+ ["pe"]="اکید",
+ ["ro"]="strict",
+ },
+ ["strong"]={
+ ["cs"]="strong",
+ ["de"]="strong",
+ ["en"]="strong",
+ ["fr"]="strong",
+ ["it"]="strong",
+ ["nl"]="sterk",
+ ["pe"]="محکم",
+ ["ro"]="strong",
+ },
+ ["strut"]={
+ ["cs"]="strut",
+ ["de"]="strut",
+ ["en"]="strut",
+ ["fr"]="strut",
+ ["it"]="strut",
+ ["nl"]="strut",
+ ["pe"]="بست",
+ ["ro"]="strut",
+ },
+ ["sub"]={
+ ["cs"]="pod",
+ ["de"]="unter",
+ ["en"]="sub",
+ ["fr"]="sous",
+ ["it"]="sotto",
+ ["nl"]="sub",
+ ["pe"]="زیر",
+ ["ro"]="sub",
+ },
+ ["subbackward"]={
+ ["cs"]="podzpet",
+ ["de"]="unterrueckwaerts",
+ ["en"]="subbackward",
+ ["fr"]="sousretourarriere",
+ ["it"]="sottoindietro",
+ ["nl"]="subachteruit",
+ ["pe"]="زیرعقب‌گرد",
+ ["ro"]="subinapoi",
+ },
+ ["subformula"]={
+ ["cs"]="subrovnice",
+ ["de"]="subformel",
+ ["en"]="subformula",
+ ["fr"]="subformule",
+ ["it"]="subformula",
+ ["nl"]="subformule",
+ ["pe"]="زیرفرمول",
+ ["ro"]="subformula",
+ },
+ ["subforward"]={
+ ["cs"]="podvpred",
+ ["de"]="untervorwaerts",
+ ["en"]="subforward",
+ ["fr"]="sousavance",
+ ["it"]="sottoavanti",
+ ["nl"]="subvooruit",
+ ["pe"]="زیرجلوگرد",
+ ["ro"]="subavans",
+ },
+ ["subject"]={
+ ["cs"]="tema",
+ ["de"]="thema",
+ ["en"]="subject",
+ ["fr"]="sujet",
+ ["it"]="argomento",
+ ["nl"]="onderwerp",
+ ["pe"]="موضوع",
+ ["ro"]="subiect",
+ },
+ ["subpage"]={
+ ["cs"]="podstranka",
+ ["de"]="unterseite",
+ ["en"]="subpage",
+ ["fr"]="souspage",
+ ["it"]="sottopagina",
+ ["nl"]="subpagina",
+ ["pe"]="زیرصفحه",
+ ["ro"]="subpagina",
+ },
+ ["subs"]={
+ ["en"]="subs",
+ },
+ ["subsection"]={
+ ["cs"]="podsekce",
+ ["de"]="unterabsatz",
+ ["en"]="subsection",
+ ["fr"]="soussection",
+ ["it"]="sottocapoverso",
+ ["nl"]="subparagraaf",
+ ["pe"]="زیربخش",
+ ["ro"]="subsectiune",
+ },
+ ["subsubject"]={
+ ["cs"]="podtema",
+ ["de"]="unterthema",
+ ["en"]="subsubject",
+ ["fr"]="soussujet",
+ ["it"]="sottoargomento",
+ ["nl"]="subonderwerp",
+ ["pe"]="زیرموضوع",
+ ["ro"]="subsubiect",
+ },
+ ["subsubsection"]={
+ ["cs"]="podpodsekce",
+ ["de"]="unterunterabsatz",
+ ["en"]="subsubsection",
+ ["fr"]="soussoussection",
+ ["it"]="sottosottocapoverso",
+ ["nl"]="subsubparagraaf",
+ ["pe"]="زیرزیربخش",
+ ["ro"]="subsubsectiune",
+ },
+ ["subsubsubject"]={
+ ["cs"]="podpodtema",
+ ["de"]="unterunterthema",
+ ["en"]="subsubsubject",
+ ["fr"]="soussoussujet",
+ ["it"]="sottosottoargomento",
+ ["nl"]="subsubonderwerp",
+ ["pe"]="زیرزیرموضوع",
+ ["ro"]="subsubsubiect",
+ },
+ ["subsubsubsection"]={
+ ["cs"]="podpodpodsekce",
+ ["de"]="unterunterunterabsatz",
+ ["en"]="subsubsubsection",
+ ["fr"]="soussoussoussection",
+ ["it"]="sottosottosottocapoverso",
+ ["nl"]="subsubsubparagraaf",
+ ["pe"]="زیرزیرزیربخش",
+ ["ro"]="subsubsubsectiune",
+ },
+ ["subsubsubsubject"]={
+ ["cs"]="podpodpodtema",
+ ["de"]="unterunterunterthema",
+ ["en"]="subsubsubsubject",
+ ["fr"]="soussoussoussujet",
+ ["it"]="sottosottosottoargomento",
+ ["nl"]="subsubsubonderwerp",
+ ["pe"]="زیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubiect",
+ },
+ ["subsubsubsubsection"]={
+ ["cs"]="podpodpodpodsekce",
+ ["de"]="unterunterunterunterabsatz",
+ ["en"]="subsubsubsubsection",
+ ["fr"]="soussoussoussoussection",
+ ["it"]="sottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsectiune",
+ },
+ ["subsubsubsubsubject"]={
+ ["cs"]="podpodpodpodtema",
+ ["de"]="unterunterunterunterthema",
+ ["en"]="subsubsubsubsubject",
+ ["fr"]="soussoussoussoussujet",
+ ["it"]="sottosottosottosottoargomento",
+ ["nl"]="subsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubsubsubiect",
+ },
+ ["sunday"]={
+ ["cs"]="nedele",
+ ["de"]="sonntag",
+ ["en"]="sunday",
+ ["fr"]="dimanche",
+ ["it"]="domenica",
+ ["nl"]="zondag",
+ ["pe"]="یک‌شنبه",
+ ["ro"]="duminica",
+ },
+ ["support"]={
+ ["cs"]="podpora",
+ ["de"]="support",
+ ["en"]="support",
+ ["fr"]="support",
+ ["it"]="supporto",
+ ["nl"]="support",
+ ["pe"]="حمایت",
+ ["ro"]="suport",
+ },
+ ["sym"]={
+ ["cs"]="sym",
+ ["de"]="sym",
+ ["en"]="sym",
+ ["fr"]="sym",
+ ["it"]="sim",
+ ["nl"]="sym",
+ ["pe"]="نم",
+ ["ro"]="sym",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["synchronize"]={
+ ["cs"]="synchronize",
+ ["de"]="synchronize",
+ ["en"]="synchronize",
+ ["fr"]="synchronize",
+ ["it"]="synchronize",
+ ["nl"]="synchroniseer",
+ ["pe"]="تطابق",
+ ["ro"]="synchronize",
+ },
+ ["synonym"]={
+ ["en"]="synonym",
+ },
+ ["system"]={
+ ["cs"]="system",
+ ["de"]="systeme",
+ ["en"]="system",
+ ["fr"]="systeme",
+ ["it"]="sistema",
+ ["nl"]="systeem",
+ ["pe"]="سیستم",
+ ["ro"]="sistem",
+ },
+ ["table"]={
+ ["cs"]="tabulka",
+ ["de"]="tabelle",
+ ["en"]="table",
+ ["fr"]="tableau",
+ ["it"]="tabella",
+ ["nl"]="tabel",
+ ["pe"]="جدول",
+ ["ro"]="tabelul",
+ },
+ ["tablehead"]={
+ ["cs"]="zahlavitabulky",
+ ["de"]="tabellenueberschrift",
+ ["en"]="tablehead",
+ ["fr"]="tetetableau",
+ ["it"]="testatabella",
+ ["nl"]="tabelkop",
+ ["pe"]="سرجدول",
+ ["ro"]="antettabel",
+ },
+ ["tables"]={
+ ["cs"]="tabulky",
+ ["de"]="tabellen",
+ ["en"]="tables",
+ ["fr"]="tables",
+ ["it"]="tabelle",
+ ["nl"]="tabellen",
+ ["pe"]="جدولها",
+ ["ro"]="tabelele",
+ },
+ ["tabletail"]={
+ ["cs"]="konectabulky",
+ ["de"]="tabellenende",
+ ["en"]="tabletail",
+ ["fr"]="queuetableau",
+ ["it"]="codatabella",
+ ["nl"]="tabelstaart",
+ ["pe"]="دنباله‌جدول",
+ ["ro"]="subsoltabel",
+ },
+ ["tabulate"]={
+ ["cs"]="tabelator",
+ ["de"]="tabulator",
+ ["en"]="tabulate",
+ ["fr"]="tabule",
+ ["it"]="tabulato",
+ ["nl"]="tabulatie",
+ ["pe"]="جدول‌بندی",
+ ["ro"]="tabulate",
+ },
+ ["tabulatehead"]={
+ ["cs"]="tabulatehead",
+ ["de"]="tabulatehead",
+ ["en"]="tabulatehead",
+ ["fr"]="tetetabule",
+ ["it"]="testatabulato",
+ ["nl"]="tabulatiekop",
+ ["pe"]="سرجدول‌بندی",
+ ["ro"]="tabulatehead",
+ },
+ ["tabulatetail"]={
+ ["cs"]="tabulatetail",
+ ["de"]="tabulatetail",
+ ["en"]="tabulatetail",
+ ["fr"]="queuetabule",
+ ["it"]="codatabulato",
+ ["nl"]="tabulatiestaart",
+ ["pe"]="دنباله‌جدول‌بندی",
+ ["ro"]="tabulatetail",
+ },
+ ["tall"]={
+ ["cs"]="vysoko",
+ ["de"]="lang",
+ ["en"]="tall",
+ ["fr"]="long",
+ ["it"]="alto",
+ ["nl"]="lang",
+ ["pe"]="دراز",
+ ["ro"]="inalt",
+ },
+ ["teletype"]={
+ ["cs"]="strojopis",
+ ["de"]="fernschreiber",
+ ["en"]="teletype",
+ ["fr"]="teletype",
+ ["it"]="teletype",
+ ["nl"]="teletype",
+ ["pe"]="دورنگاره",
+ ["ro"]="teletype",
+ },
+ ["temporary"]={
+ ["cs"]="docasne",
+ ["de"]="temporaer",
+ ["en"]="temporary",
+ ["fr"]="temporaire",
+ ["it"]="temporaneo",
+ ["nl"]="voorlopig",
+ ["pe"]="موقتی",
+ ["ro"]="temporar",
+ },
+ ["test"]={
+ ["cs"]="test",
+ ["de"]="test",
+ ["en"]="test",
+ ["fr"]="test",
+ ["it"]="test",
+ ["nl"]="test",
+ ["pe"]="تست",
+ ["ro"]="test",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["three"]={
+ ["cs"]="tri",
+ ["de"]="drei",
+ ["en"]="three",
+ ["fr"]="trois",
+ ["it"]="tre",
+ ["nl"]="drie",
+ ["pe"]="سه",
+ ["ro"]="trei",
+ },
+ ["thursday"]={
+ ["cs"]="ctvrtek",
+ ["de"]="donnerstag",
+ ["en"]="thursday",
+ ["fr"]="jeudi",
+ ["it"]="giovedi",
+ ["nl"]="donderdag",
+ ["pe"]="پنج‌شنبه",
+ ["ro"]="joi",
+ },
+ ["tight"]={
+ ["en"]="tight",
+ ["nl"]="krap",
+ },
+ ["title"]={
+ ["cs"]="titul",
+ ["de"]="titel",
+ ["en"]="title",
+ ["fr"]="titre",
+ ["it"]="titolo",
+ ["nl"]="titel",
+ ["pe"]="عنوان",
+ ["ro"]="titlu",
+ },
+ ["toggle"]={
+ ["cs"]="toggle",
+ ["de"]="toggle",
+ ["en"]="wissel",
+ ["fr"]="toggle",
+ ["it"]="toggle",
+ ["nl"]="toggle",
+ ["pe"]="تغییر",
+ ["ro"]="toggle",
+ },
+ ["tolerant"]={
+ ["cs"]="tolerantni",
+ ["de"]="tolerant",
+ ["en"]="tolerant",
+ ["fr"]="tolerant",
+ ["it"]="tollerante",
+ ["nl"]="soepel",
+ ["pe"]="بردبار",
+ ["ro"]="tolerant",
+ },
+ ["top"]={
+ ["cs"]="vrsek",
+ ["de"]="oben",
+ ["en"]="top",
+ ["fr"]="sup",
+ ["it"]="cima",
+ ["nl"]="boven",
+ ["pe"]="بالا",
+ ["ro"]="sus",
+ },
+ ["tuesday"]={
+ ["cs"]="utery",
+ ["de"]="dienstag",
+ ["en"]="tuesday",
+ ["fr"]="mardi",
+ ["it"]="martedi",
+ ["nl"]="dinsdag",
+ ["pe"]="سه‌شنبه",
+ ["ro"]="marti",
+ },
+ ["two"]={
+ ["cs"]="dve",
+ ["de"]="zwei",
+ ["en"]="two",
+ ["fr"]="deux",
+ ["it"]="due",
+ ["nl"]="twee",
+ ["pe"]="دو",
+ ["ro"]="doi",
+ },
+ ["txt"]={
+ ["cs"]="txt",
+ ["de"]="txt",
+ ["en"]="txt",
+ ["fr"]="txt",
+ ["it"]="txt",
+ ["nl"]="txt",
+ ["pe"]="txt",
+ ["ro"]="txt",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="tippen",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["typing"]={
+ ["cs"]="typing",
+ ["de"]="tippen",
+ ["en"]="typing",
+ ["fr"]="typing",
+ ["it"]="typing",
+ ["nl"]="typen",
+ ["pe"]="تایپ‌کردن",
+ ["ro"]="typing",
+ },
+ ["unavailable"]={
+ ["cs"]="nedostupne",
+ ["de"]="nichtverfuegbar",
+ ["en"]="unavailable",
+ ["fr"]="indisponible",
+ ["it"]="nondisponibile",
+ ["nl"]="nietbeschikbaar",
+ ["pe"]="غیرموجود",
+ ["ro"]="nedisponibil",
+ },
+ ["underbar"]={
+ ["cs"]="podtrzeno",
+ ["de"]="unterstrichen",
+ ["en"]="underbar",
+ ["fr"]="souslignetout",
+ ["it"]="sottolinea",
+ ["nl"]="onderstreep",
+ ["pe"]="میله‌زیر",
+ ["ro"]="sublinie",
+ },
+ ["underbars"]={
+ ["cs"]="podtrzeni",
+ ["de"]="unterstreichen",
+ ["en"]="underbars",
+ ["fr"]="sousligne",
+ ["it"]="sottolinee",
+ ["nl"]="onderstrepen",
+ ["pe"]="میله‌‌های‌زیر",
+ ["ro"]="sublinii",
+ },
+ ["understrike"]={
+ ["en"]="understrike",
+ },
+ ["understrikes"]={
+ ["en"]="understrikes",
+ },
+ ["unframed"]={
+ ["en"]="unframed",
+ },
+ ["unit"]={
+ ["cs"]="jednotka",
+ ["de"]="einheit",
+ ["en"]="unit",
+ ["fr"]="unite",
+ ["it"]="unita",
+ ["nl"]="eenheid",
+ ["pe"]="واحد",
+ ["ro"]="unitate",
+ },
+ ["units"]={
+ ["cs"]="jednotky",
+ ["de"]="einheiten",
+ ["en"]="units",
+ ["fr"]="unites",
+ ["it"]="unita",
+ ["nl"]="eenheden",
+ ["pe"]="واحدها",
+ ["ro"]="unitati",
+ },
+ ["unknown"]={
+ ["cs"]="neznamy",
+ ["de"]="unbekannt",
+ ["en"]="unknown",
+ ["fr"]="inconnu",
+ ["it"]="ignoto",
+ ["nl"]="onbekend",
+ ["pe"]="ناشناس",
+ ["ro"]="necunoscut",
+ },
+ ["unpacked"]={
+ ["cs"]="rozbalene",
+ ["de"]="ungepackt",
+ ["en"]="unpacked",
+ ["fr"]="degroupe",
+ ["it"]="unpacked",
+ ["nl"]="vanelkaar",
+ ["pe"]="غیرفشرده",
+ ["ro"]="despachetat",
+ },
+ ["up"]={
+ ["en"]="up",
+ ["nl"]="omhoog",
+ },
+ ["url"]={
+ ["cs"]="url",
+ ["de"]="url",
+ ["en"]="url",
+ ["fr"]="url",
+ ["it"]="url",
+ ["nl"]="url",
+ ["pe"]="url",
+ ["ro"]="url",
+ },
+ ["used"]={
+ ["cs"]="uzito",
+ ["de"]="verwende",
+ ["en"]="used",
+ ["fr"]="used",
+ ["it"]="usato",
+ ["nl"]="gebruikt",
+ ["pe"]="استفاده‌شده",
+ ["ro"]="folosit",
+ },
+ ["value"]={
+ ["cs"]="hodnota",
+ ["de"]="wert",
+ ["en"]="value",
+ ["fr"]="valeur",
+ ["it"]="valore",
+ ["nl"]="waarde",
+ ["pe"]="مقدار",
+ ["ro"]="valoare",
+ },
+ ["vertical"]={
+ ["cs"]="vertikalne",
+ ["de"]="vertikal",
+ ["en"]="vertical",
+ ["fr"]="verticale",
+ ["it"]="verticale",
+ ["nl"]="vertikaal",
+ ["pe"]="عمودی",
+ ["ro"]="vertical",
+ },
+ ["very"]={
+ ["cs"]="velmi",
+ ["de"]="sehr",
+ ["en"]="very",
+ ["fr"]="tres",
+ ["it"]="molto",
+ ["nl"]="zeer",
+ ["pe"]="خیلی",
+ ["ro"]="foarte",
+ },
+ ["verystrict"]={
+ ["cs"]="velmistriktni",
+ ["de"]="sehrstreng",
+ ["en"]="verystrict",
+ ["fr"]="tresstrict",
+ ["it"]="moltorigido",
+ ["nl"]="zeerstreng",
+ ["pe"]="خیلی‌سختگیر",
+ ["ro"]="foartestrict",
+ },
+ ["verytolerant"]={
+ ["cs"]="velmitolerantni",
+ ["de"]="sehrtolerant",
+ ["en"]="verytolerant",
+ ["fr"]="trestolerant",
+ ["it"]="moltotollerante",
+ ["nl"]="zeersoepel",
+ ["pe"]="خیلی‌بردبار",
+ ["ro"]="foartetolerant",
+ },
+ ["vfenced"]={
+ ["en"]="vfenced",
+ },
+ ["vulgarfraction"]={
+ ["en"]="vulgarfraction",
+ },
+ ["weak"]={
+ ["cs"]="weak",
+ ["de"]="weak",
+ ["en"]="weak",
+ ["fr"]="weak",
+ ["it"]="weak",
+ ["nl"]="zwak",
+ ["pe"]="هفته",
+ ["ro"]="weak",
+ },
+ ["wednesday"]={
+ ["cs"]="streda",
+ ["de"]="mittwoch",
+ ["en"]="wednesday",
+ ["fr"]="mercredi",
+ ["it"]="mercoledi",
+ ["nl"]="woensdag",
+ ["pe"]="چهارشنبه",
+ ["ro"]="miercuri",
+ },
+ ["week"]={
+ ["cs"]="tyden",
+ ["de"]="woche",
+ ["en"]="week",
+ ["fr"]="semaine",
+ ["it"]="settimana",
+ ["nl"]="week",
+ ["pe"]="هفته",
+ ["ro"]="saptamana",
+ },
+ ["weekday"]={
+ ["cs"]="vsedniden",
+ ["de"]="wochentag",
+ ["en"]="weekday",
+ ["fr"]="joursemaine",
+ ["it"]="giornosettimana",
+ ["nl"]="weekdag",
+ ["pe"]="روزهفته",
+ ["ro"]="zisaptamana",
+ },
+ ["white"]={
+ ["cs"]="bily",
+ ["de"]="weiss",
+ ["en"]="white",
+ ["fr"]="blanc",
+ ["it"]="bianco",
+ ["nl"]="wit",
+ ["pe"]="سفید",
+ ["ro"]="alb",
+ },
+ ["wide"]={
+ ["cs"]="siroce",
+ ["de"]="breit",
+ ["en"]="wide",
+ ["fr"]="ample",
+ ["it"]="ampio",
+ ["nl"]="breed",
+ ["pe"]="گسترده",
+ ["ro"]="larg",
+ },
+ ["width"]={
+ ["cs"]="sirka",
+ ["de"]="breite",
+ ["en"]="width",
+ ["fr"]="largeur",
+ ["it"]="ampiezza",
+ ["nl"]="breedte",
+ ["pe"]="عرض",
+ ["ro"]="latime",
+ },
+ ["word"]={
+ ["cs"]="slovo",
+ ["de"]="wort",
+ ["en"]="word",
+ ["fr"]="mot",
+ ["it"]="parola",
+ ["nl"]="woord",
+ ["pe"]="word",
+ ["ro"]="cuvant",
+ },
+ ["words"]={
+ ["en"]="words",
+ },
+ ["xml"]={
+ ["cs"]="xml",
+ ["de"]="xml",
+ ["en"]="xml",
+ ["fr"]="xml",
+ ["it"]="xml",
+ ["nl"]="xml",
+ ["pe"]="xml",
+ ["ro"]="xml",
+ },
+ ["year"]={
+ ["cs"]="rok",
+ ["de"]="jahr",
+ ["en"]="year",
+ ["fr"]="annee",
+ ["it"]="anno",
+ ["nl"]="jaar",
+ ["pe"]="سال",
+ ["ro"]="an",
+ },
+ ["yes"]={
+ ["cs"]="ano",
+ ["de"]="ja",
+ ["en"]="yes",
+ ["fr"]="oui",
+ ["it"]="si",
+ ["nl"]="ja",
+ ["pe"]="بله",
+ ["ro"]="da",
+ },
+ },
+ ["setupstrings"]={
+ ["cd:buffer"]={
+ ["cs"]="buffer",
+ ["de"]="buffer",
+ ["en"]="buffer",
+ ["fr"]="buffer",
+ ["it"]="buffer",
+ ["nl"]="buffer",
+ ["ro"]="buffer",
+ },
+ ["cd:category"]={
+ ["cs"]="category",
+ ["de"]="category",
+ ["en"]="category",
+ ["fr"]="category",
+ ["it"]="category",
+ ["nl"]="category",
+ ["ro"]="category",
+ },
+ ["cd:character"]={
+ ["cs"]="character",
+ ["de"]="character",
+ ["en"]="character",
+ ["fr"]="character",
+ ["it"]="character",
+ ["nl"]="karakter",
+ ["ro"]="character",
+ },
+ ["cd:color"]={
+ ["cs"]="color",
+ ["de"]="color",
+ ["en"]="color",
+ ["fr"]="color",
+ ["it"]="color",
+ ["nl"]="kleur",
+ ["ro"]="color",
+ },
+ ["cd:column"]={
+ ["cs"]="column",
+ ["de"]="column",
+ ["en"]="column",
+ ["fr"]="column",
+ ["it"]="column",
+ ["nl"]="kolom",
+ ["ro"]="column",
+ },
+ ["cd:command"]={
+ ["cs"]="Befehl",
+ ["de"]="Befehl",
+ ["en"]="command",
+ ["fr"]="Befehl",
+ ["it"]="Befehl",
+ ["nl"]="commando",
+ ["ro"]="Befehl",
+ },
+ ["cd:content"]={
+ ["cs"]="content",
+ ["de"]="content",
+ ["en"]="content",
+ ["fr"]="content",
+ ["it"]="content",
+ ["nl"]="inhoud",
+ ["ro"]="content",
+ },
+ ["cd:csname"]={
+ ["cs"]="csname",
+ ["de"]="csname",
+ ["en"]="csname",
+ ["fr"]="csname",
+ ["it"]="csname",
+ ["nl"]="naam",
+ ["ro"]="csname",
+ },
+ ["cd:delimiter"]={
+ ["cs"]="delimiter",
+ ["de"]="delimiter",
+ ["en"]="delimiter",
+ ["fr"]="delimiter",
+ ["it"]="delimiter",
+ ["nl"]="delimiter",
+ ["ro"]="delimiter",
+ },
+ ["cd:destination"]={
+ ["cs"]="destination",
+ ["de"]="destination",
+ ["en"]="destination",
+ ["fr"]="destination",
+ ["it"]="destination",
+ ["nl"]="bestemming",
+ ["ro"]="destination",
+ },
+ ["cd:dimension"]={
+ ["cs"]="Dimension",
+ ["de"]="Dimension",
+ ["en"]="dimension",
+ ["fr"]="Dimension",
+ ["it"]="Dimension",
+ ["nl"]="maat",
+ ["ro"]="Dimension",
+ },
+ ["cd:displaymath"]={
+ ["cs"]="formula",
+ ["de"]="formula",
+ ["en"]="formula",
+ ["fr"]="formula",
+ ["it"]="formula",
+ ["nl"]="formule",
+ ["ro"]="formula",
+ },
+ ["cd:false"]={
+ ["cs"]="false",
+ ["de"]="false",
+ ["en"]="false",
+ ["fr"]="false",
+ ["it"]="false",
+ ["nl"]="false",
+ ["ro"]="false",
+ },
+ ["cd:file"]={
+ ["cs"]="file",
+ ["de"]="file",
+ ["en"]="file",
+ ["fr"]="file",
+ ["it"]="file",
+ ["nl"]="file",
+ ["ro"]="file",
+ },
+ ["cd:path"]={
+ ["cs"]="path",
+ ["de"]="path",
+ ["en"]="path",
+ ["fr"]="path",
+ ["it"]="path",
+ ["nl"]="path",
+ ["ro"]="path",
+ },
+ ["cd:first"]={
+ ["cs"]="first",
+ ["de"]="first",
+ ["en"]="first",
+ ["fr"]="first",
+ ["it"]="first",
+ ["nl"]="eerste",
+ ["ro"]="first",
+ },
+ ["cd:font"]={
+ ["cs"]="font",
+ ["de"]="font",
+ ["en"]="font",
+ ["fr"]="font",
+ ["it"]="font",
+ ["nl"]="font",
+ ["ro"]="font",
+ },
+ ["cd:formula"]={
+ ["cs"]="Formel",
+ ["de"]="Formel",
+ ["en"]="formula",
+ ["fr"]="Formel",
+ ["it"]="Formel",
+ ["nl"]="formule",
+ ["ro"]="Formel",
+ },
+ ["cd:identifier"]={
+ ["cs"]="Name",
+ ["de"]="Name",
+ ["en"]="identifier",
+ ["fr"]="Name",
+ ["it"]="Name",
+ ["nl"]="naam",
+ ["ro"]="Name",
+ },
+ ["cd:index"]={
+ ["cs"]="entry",
+ ["de"]="entry",
+ ["en"]="entry",
+ ["fr"]="entry",
+ ["it"]="entry",
+ ["nl"]="ingang",
+ ["ro"]="entry",
+ },
+ ["cd:inherits"]={
+ ["cs"]="inherits",
+ ["de"]="inherits",
+ ["en"]="inherits",
+ ["fr"]="inherits",
+ ["it"]="inherits",
+ ["nl"]="erft",
+ ["ro"]="inherits",
+ },
+ ["cd:key"]={
+ ["cs"]="key",
+ ["de"]="key",
+ ["en"]="key",
+ ["fr"]="key",
+ ["it"]="key",
+ ["nl"]="parameter",
+ ["ro"]="key",
+ },
+ ["cd:language"]={
+ ["cs"]="sprache",
+ ["de"]="sprache",
+ ["en"]="language",
+ ["fr"]="sprache",
+ ["it"]="sprache",
+ ["nl"]="taal",
+ ["ro"]="sprache",
+ },
+ ["cd:last"]={
+ ["cs"]="last",
+ ["de"]="last",
+ ["en"]="last",
+ ["fr"]="last",
+ ["it"]="last",
+ ["nl"]="laatste",
+ ["ro"]="last",
+ },
+ ["cd:list"]={
+ ["cs"]="Liste",
+ ["de"]="Liste",
+ ["en"]="list",
+ ["fr"]="Liste",
+ ["it"]="Liste",
+ ["nl"]="lijst",
+ ["ro"]="Liste",
+ },
+ ["cd:lpath"]={
+ ["cs"]="lpath",
+ ["de"]="lpath",
+ ["en"]="lpath",
+ ["fr"]="lpath",
+ ["it"]="lpath",
+ ["nl"]="lpath",
+ ["ro"]="lpath",
+ },
+ ["cd:luafunction"]={
+ ["cs"]="luafunction",
+ ["de"]="luafunction",
+ ["en"]="luafunction",
+ ["fr"]="luafunction",
+ ["it"]="luafunction",
+ ["nl"]="luafunction",
+ ["ro"]="luafunction",
+ },
+ ["cd:mark"]={
+ ["cs"]="Beschriftung",
+ ["de"]="Beschriftung",
+ ["en"]="mark",
+ ["fr"]="Beschriftung",
+ ["it"]="Beschriftung",
+ ["nl"]="markering",
+ ["ro"]="Beschriftung",
+ },
+ ["cd:marking"]={
+ ["cs"]="marking",
+ ["de"]="marking",
+ ["en"]="marking",
+ ["fr"]="marking",
+ ["it"]="marking",
+ ["nl"]="markering",
+ ["ro"]="marking",
+ },
+ ["cd:math"]={
+ ["cs"]="formula",
+ ["de"]="formula",
+ ["en"]="formula",
+ ["fr"]="formula",
+ ["it"]="formula",
+ ["nl"]="formule",
+ ["ro"]="formula",
+ },
+ ["cd:matrix"]={
+ ["cs"]="n*m",
+ ["de"]="n*m",
+ ["en"]="n*m",
+ ["fr"]="n*m",
+ ["it"]="n*m",
+ ["nl"]="n*m",
+ ["ro"]="n*m",
+ },
+ ["cd:name"]={
+ ["cs"]="Name",
+ ["de"]="Name",
+ ["en"]="name",
+ ["fr"]="Name",
+ ["it"]="Name",
+ ["nl"]="naam",
+ ["ro"]="Name",
+ },
+ ["cd:node"]={
+ ["cs"]="node",
+ ["de"]="node",
+ ["en"]="node",
+ ["fr"]="node",
+ ["it"]="node",
+ ["nl"]="node",
+ ["ro"]="node",
+ },
+ ["cd:nothing"]={
+ ["cs"]="empty",
+ ["de"]="empty",
+ ["en"]="empty",
+ ["fr"]="empty",
+ ["it"]="empty",
+ ["nl"]="leeg",
+ ["ro"]="empty",
+ },
+ ["cd:number"]={
+ ["cs"]="Nummer",
+ ["de"]="Nummer",
+ ["en"]="number",
+ ["fr"]="Nummer",
+ ["it"]="Nummer",
+ ["nl"]="getal",
+ ["ro"]="Nummer",
+ },
+ ["cd:optional"]={
+ ["cs"]="opt",
+ ["de"]="opt",
+ ["en"]="opt",
+ ["fr"]="opt",
+ ["it"]="opt",
+ ["nl"]="opt",
+ ["ro"]="opt",
+ },
+ ["cd:plural"]={
+ ["cs"]="plural",
+ ["de"]="plural",
+ ["en"]="plural",
+ ["fr"]="plural",
+ ["it"]="plural",
+ ["nl"]="naam",
+ ["ro"]="plural",
+ },
+ ["cd:position"]={
+ ["cs"]="position",
+ ["de"]="position",
+ ["en"]="position",
+ ["fr"]="position",
+ ["it"]="position",
+ ["nl"]="positie",
+ ["ro"]="position",
+ },
+ ["cd:processor"]={
+ ["cs"]="processor",
+ ["de"]="processor",
+ ["en"]="processor",
+ ["fr"]="processor",
+ ["it"]="processor",
+ ["nl"]="verwerker",
+ ["ro"]="processor",
+ },
+ ["cd:reference"]={
+ ["cs"]="reference",
+ ["de"]="reference",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="reference",
+ ["nl"]="verwijzing",
+ ["ro"]="reference",
+ },
+ ["cd:row"]={
+ ["cs"]="row",
+ ["de"]="row",
+ ["en"]="row",
+ ["fr"]="row",
+ ["it"]="row",
+ ["nl"]="rij",
+ ["ro"]="row",
+ },
+ ["cd:section"]={
+ ["cs"]="Abschnitt",
+ ["de"]="Abschnitt",
+ ["en"]="section",
+ ["fr"]="Abschnitt",
+ ["it"]="Abschnitt",
+ ["nl"]="sectie",
+ ["ro"]="Abschnitt",
+ },
+ ["cd:sectionblock"]={
+ ["cs"]="sectionblock",
+ ["de"]="sectionblock",
+ ["en"]="sectionblock",
+ ["fr"]="sectionblock",
+ ["it"]="sectionblock",
+ ["nl"]="sectieblok",
+ ["ro"]="sectionblock",
+ },
+ ["cd:see"]={
+ ["cs"]="siehe",
+ ["de"]="siehe",
+ ["en"]="see",
+ ["fr"]="siehe",
+ ["it"]="siehe",
+ ["nl"]="zie",
+ ["ro"]="siehe",
+ },
+ ["cd:setup"]={
+ ["cs"]="setup",
+ ["de"]="setup",
+ ["en"]="setup",
+ ["fr"]="setup",
+ ["it"]="setup",
+ ["nl"]="setup",
+ ["ro"]="setup",
+ },
+ ["cd:singular"]={
+ ["cs"]="singular",
+ ["de"]="singular",
+ ["en"]="singular",
+ ["fr"]="singular",
+ ["it"]="singular",
+ ["nl"]="naam",
+ ["ro"]="singular",
+ },
+ ["cd:style"]={
+ ["cs"]="style",
+ ["de"]="style",
+ ["en"]="style",
+ ["fr"]="style",
+ ["it"]="style",
+ ["nl"]="letter",
+ ["ro"]="style",
+ },
+ ["cd:template"]={
+ ["cs"]="template",
+ ["de"]="template",
+ ["en"]="template",
+ ["fr"]="template",
+ ["it"]="template",
+ ["nl"]="sjabloon",
+ ["ro"]="template",
+ },
+ ["cd:text"]={
+ ["cs"]="Text",
+ ["de"]="Text",
+ ["en"]="text",
+ ["fr"]="Text",
+ ["it"]="Text",
+ ["nl"]="tekst",
+ ["ro"]="Text",
+ },
+ ["cd:title"]={
+ ["cs"]="Setup",
+ ["de"]="Setup",
+ ["en"]="setup",
+ ["fr"]="Setup",
+ ["it"]="Setup",
+ ["nl"]="setup",
+ ["ro"]="Setup",
+ },
+ ["cd:triplet"]={
+ ["cs"]="triplet",
+ ["de"]="triplet",
+ ["en"]="triplet",
+ ["fr"]="triplet",
+ ["it"]="triplet",
+ ["nl"]="triplet",
+ ["ro"]="triplet",
+ },
+ ["cd:true"]={
+ ["cs"]="true",
+ ["de"]="true",
+ ["en"]="true",
+ ["fr"]="true",
+ ["it"]="true",
+ ["nl"]="true",
+ ["ro"]="true",
+ },
+ ["cd:url"]={
+ ["cs"]="url",
+ ["de"]="url",
+ ["en"]="url",
+ ["fr"]="url",
+ ["it"]="url",
+ ["nl"]="url",
+ ["ro"]="url",
+ },
+ ["cd:userdata"]={
+ ["cs"]="userdata",
+ ["de"]="userdata",
+ ["en"]="userdata",
+ ["fr"]="userdata",
+ ["it"]="userdata",
+ ["nl"]="gebruikersdata",
+ ["ro"]="userdata",
+ },
+ ["cd:value"]={
+ ["cs"]="value",
+ ["de"]="value",
+ ["en"]="value",
+ ["fr"]="value",
+ ["it"]="value",
+ ["nl"]="waarde",
+ ["ro"]="value",
+ },
+ ["cd:word"]={
+ ["cs"]="word",
+ ["de"]="word",
+ ["en"]="word",
+ ["fr"]="word",
+ ["it"]="word",
+ ["nl"]="woord",
+ ["ro"]="word",
+ },
+ ["cd:xmlsetup"]={
+ ["cs"]="xmlsetup",
+ ["de"]="xmlsetup",
+ ["en"]="xmlsetup",
+ ["fr"]="xmlsetup",
+ ["it"]="xmlsetup",
+ ["nl"]="xmlsetup",
+ ["ro"]="xmlsetup",
+ },
+ ["cd:sign-s"] = { en = "[-+]" },
+ ["cd:sign-l"] = { en = "[-+]" },
+ ["cd:csname-s"] = { en = "\\..." },
+ ["cd:csname-l"] = { en = "\\..." },
+ ["cd:noargument-s"] = { en = "\\..." },
+ ["cd:noargument-l"] = { en = "\\..." },
+ ["cd:oneargument-s"] = { en = "\\...#1" },
+ ["cd:oneargument-l"] = { en = "\\...#1" },
+ ["cd:twoarguments-s"] = { en = "\\...#1#2" },
+ ["cd:twoarguments-l"] = { en = "\\...#1#2" },
+ ["cd:threearguments-s"] = { en = "\\...#1#2#3" },
+ ["cd:threearguments-l"] = { en = "\\...#1#2#3" },
+ ["cd:braces-s"] = { en = "{...}", lua = '"..."' },
+ ["cd:braces-l"] = { en = "{...,...}", lua = '".. ... .."' },
+ ["cd:brackets-s"] = { en = "[...]", lua = "{ ... }" },
+ ["cd:brackets-l"] = { en = "[...,...]", lua = "{..., ...}" },
+ ["cd:index-s"] = { en = "[...]" },
+ ["cd:index-l"] = { en = "[..+...+..]" },
+ ["cd:math-s"] = { en = "$...$" },
+ ["cd:math-l"] = { en = "$...$" },
+ ["cd:inlinemath-s"] = { en = "$...$" },
+ ["cd:inlinemath-l"] = { en = "$...$" },
+ ["cd:displaymath-s"] = { en = "$$...$$" },
+ ["cd:displaymath-l"] = { en = "$$...$$" },
+ ["cd:template-s"] = { en = "[|...|]" },
+ ["cd:template-l"] = { en = "[|...|...|]" },
+ ["cd:twowords-s"] = { en = "[..+..]" },
+ ["cd:twowords-l"] = { en = "[..+..]" },
+ ["cd:threewords-s"] = { en = "[..+..+..]" },
+ ["cd:threewords-l"] = { en = "[..+..+..]" },
+ ["cd:angle-s"] = { en = "<<...>>" },
+ ["cd:angle-l"] = { en = "<<...>>" },
+ ["cd:reference-s"] = { en = "[...]", lua = "{ ... }" },
+ ["cd:reference-l"] = { en = "[...,...]", lua = "{..., ...}" },
+ ["cd:position-s"] = { en = "(...)" },
+ ["cd:position-l"] = { en = "(...,...)" },
+ ["cd:triplet-s"] = { en = "[x:y:z]" },
+ ["cd:triplet-l"] = { en = "[x:y:z,..]" },
+ ["cd:word-s"] = { en = "{...}", lua = '"..."' },
+ ["cd:word-l"] = { en = "{.. ... ..}", lua = '".. ... .."' },
+ ["cd:content-s"] = { en = "{...}", lua = '"..."' },
+ ["cd:content-l"] = { en = "{.. ... ..}", lua = '".. ... .."' },
+ ["cd:textual-s"] = { en = "..." },
+ ["cd:textual-l"] = { en = ".. ... .." },
+ ["cd:none-s"] = { en = "..." },
+ ["cd:none-l"] = { en = ".. ... .." },
+ ["cd:macro-s"] = { en = "\\... " },
+ ["cd:macro-l"] = { en = "\\... " },
+ ["cd:to-s"] = { en = "\\to " },
+ ["cd:to-l"] = { en = "\\to " },
+ ["cd:destination-s"] = { en = "[{..[ref]}]" },
+ ["cd:destination-l"] = { en = "[..,{..[ref,..]},..]" },
+ ["cd:nothing-s"] = { en = "..." },
+ ["cd:nothing-l"] = { en = "..." },
+ ["cd:file-s"] = { en = " ... " },
+ ["cd:file-l"] = { en = " ... " },
+ ["cd:assignment-s"] = { en = "[..=..]", lua = "{ ..=.. } " },
+ ["cd:assignment-l"] = { en = "[..,..=..,..]", lua = "{ ..,..=..,.. } " },
+ ["cd:assignmentbraces-s"] = { en = "{..=..}" },
+ ["cd:assignmentbraces-l"] = { en = "{..,..=..,..}" },
+ ["cd:assignmentbrackets-s"] = { en = "[..=..]", lua = "{ ..=.. } " },
+ ["cd:assignmentbrackets-l"] = { en = "[..,..=..,..]", lua = "{ ..,..=..,.. } " },
+ ["cd:assignmentparentheses-s"] = { en = "(..=..)" },
+ ["cd:assignmentparentheses-l"] = { en = "(..,..=..,..)" },
+ ["cd:apply-s"] = { en = "[..=>..]" },
+ ["cd:apply-l"] = { en = "[..,..=>..,..]" },
+ ["cd:if-s"] = { en = "\\if... " },
+ ["cd:if-l"] = { en = "\\if... " },
+ ["cd:case-s"] = { en = "\\case " },
+ ["cd:case-l"] = { en = "\\case " },
+ ["cd:else-s"] = { en = "\\else " },
+ ["cd:else-l"] = { en = "\\else " },
+ ["cd:or-s"] = { en = "\\or " },
+ ["cd:or-l"] = { en = "\\or " },
+ ["cd:fi-s"] = { en = "\\fi " },
+ ["cd:fi-l"] = { en = "\\fi " },
+ ["cd:par-s"] = { en = "\\par " },
+ ["cd:par-l"] = { en = "\\par " },
+ ["cd:sep-s"] = { en = "\\" },
+ ["cd:sep-l"] = { en = "\\" },
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-def.mkiv
new file mode 100644
index 00000000000..d9404bc1625
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-def.mkiv
@@ -0,0 +1,46 @@
+%D \module
+%D [ file=mult-def,
+%D version=2008.10.22,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\installcorenamespace{multilingual}
+
+\setvalue{\??multilingual czech}{cs}
+\setvalue{\??multilingual german}{de}
+\setvalue{\??multilingual english}{en}
+\setvalue{\??multilingual french}{fr}
+\setvalue{\??multilingual italian}{it}
+\setvalue{\??multilingual dutch}{nl}
+\setvalue{\??multilingual persian}{pe}
+\setvalue{\??multilingual romanian}{ro}
+
+% \def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\csname\??multilingual\currentinterface\endcsname\else en\fi}
+% \def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\csname\??multilingual\currentresponses\endcsname\else en\fi}
+
+\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\lastnamedcs\else en\fi}
+\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\lastnamedcs\else en\fi}
+
+% \input mult-\userinterfacetag \relax
+% \input mult-m\userresponsestag \relax
+
+\clf_setuserinterface{\userinterfacetag}{\userresponsestag}
+
+% some left-overs
+
+\def\c!HL {HL}
+\def\c!VL {VL}
+\def\c!NL {NL}
+
+% stop todo
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-dim.mkvi b/Master/texmf-dist/tex/context/base/mkiv/mult-dim.mkvi
new file mode 100644
index 00000000000..0224e3dbb16
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-dim.mkvi
@@ -0,0 +1,170 @@
+%D \module
+%D [ file=core-gen,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=General,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / General}
+
+% we could write a proper parser now in lua
+
+\unprotect
+
+%D \macros
+%D {assigndimension,assignalfadimension}
+%D
+%D The following commands are used to process keyword based
+%D dimension setters.
+%D
+%D \starttyping
+%D \assigndimension
+%D {<value>|small|medium|big|-small|-medium|-big|none}
+%D {\dimension}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+%D
+%D The given keyword determines the result.
+
+\installcorenamespace{dimensionnormal}
+
+\def\assign_dimension_direct#value#dimension#small#medium#big{#dimension=#value\relax}
+
+\setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint}
+\setvalue{\??dimensionnormal \empty }#value#dimension#small#medium#big{#dimension\zeropoint}
+\setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax}
+\setvalue{\??dimensionnormal \v!medium}#value#dimension#small#medium#big{#dimension=#medium\relax}
+\setvalue{\??dimensionnormal \v!big }#value#dimension#small#medium#big{#dimension=#big\relax}
+\setvalue{\??dimensionnormal-\v!small }#value#dimension#small#medium#big{#dimension=-#small\relax}
+\setvalue{\??dimensionnormal-\v!medium}#value#dimension#small#medium#big{#dimension=-#medium\relax}
+\setvalue{\??dimensionnormal-\v!big }#value#dimension#small#medium#big{#dimension=-#big\relax}
+\letvalue{\??dimensionnormal\s!unknown}\assign_dimension_direct
+
+% \unexpanded\def\assigndimension#value%
+% {\csname\??dimensionnormal\ifcsname\??dimensionnormal#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+\unexpanded\def\assigndimension#value%
+ {\ifcsname\??dimensionnormal#value\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\assign_dimension_direct
+ \fi{#value}}
+
+%D The next variant assigns to a macro instead of a dimension.
+%D
+%D \starttyping
+%D \assignalfadimension
+%D {<value>|small|medium|big|none}
+%D {\macro}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+%D
+%D This one is used for factors.
+
+\installcorenamespace{dimensionalfa}
+
+\def\assign_alpha_dimension_direct#value#macro#small#medium#big{\edef#macro{#value}}
+
+\setvalue{\??dimensionalfa\v!none }#value#macro#small#medium#big{\let #macro\!!zerocount}
+\setvalue{\??dimensionalfa\v!small }#value#macro#small#medium#big{\edef#macro{#small}}
+\setvalue{\??dimensionalfa\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
+\setvalue{\??dimensionalfa\v!big }#value#macro#small#medium#big{\edef#macro{#big}}
+\letvalue{\??dimensionalfa\s!unknown}\assign_alpha_dimension_direct
+
+% \unexpanded\def\assignalfadimension#value%
+% {\csname\??dimensionalfa\ifcsname\??dimensionalfa#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+\unexpanded\def\assignalfadimension#value%
+ {\ifcsname\??dimensionalfa#value\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\assign_alpha_dimension_direct
+ \fi
+ {#value}}
+
+%D \macros
+%D {assignvalue}
+%D
+%D A variant that does not assume dimenions ios the following:
+%D
+%D \starttyping
+%D \assignvalue
+%D {<value>|small|medium|big}
+%D {\macro}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+
+\installcorenamespace{dimensionvalue}
+
+\def\assign_value_direct#value#macro#small#medium#big{\edef#macro{#value}}
+
+\setvalue{\??dimensionvalue\v!small }#value#macro#small#medium#big{\edef#macro{#small}}
+\setvalue{\??dimensionvalue\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
+\setvalue{\??dimensionvalue\v!big }#value#macro#small#medium#big{\edef#macro{#big}}
+\letvalue{\??dimensionvalue\s!unknown}\assign_value_direct
+
+% \unexpanded\def\assignvalue#value%
+% {\csname\??dimensionvalue\ifcsname\??dimensionvalue#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+\unexpanded\def\assignvalue#value%
+ {\ifcsname\??dimensionvalue#value\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\assign_value_direct
+ \fi{#value}}
+
+%D \macros
+%D {assignwidth}
+%D
+%D Een breedte van een opgegeven tekst kan worden berekend en
+%D toegekend aan een \DIMENSION\ met:
+%D
+%D \starttyping
+%D \assignwidth
+%D {<value>|fit|broad}
+%D {\dimension}
+%D {text}
+%D {extra}
+%D \stoptyping
+
+\installcorenamespace{dimensionwidth}
+
+\newbox\b_assign_width
+
+\def\assign_width_direct#value#dimension#content#extra{#dimension=#value\relax}
+
+% line is like fit but can be used later as signal for ...
+
+\setvalue{\??dimensionwidth }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!fit }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!broad }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\dimexpr\wd\b_assign_width+#extra\relax
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!line }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
+ \setbox\b_assign_width\emptybox}
+\letvalue{\??dimensionwidth\s!unknown}\assign_width_direct
+
+% \unexpanded\def\assignwidth#value%
+% {\csname\??dimensionwidth\ifcsname\??dimensionwidth#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+\unexpanded\def\assignwidth#value%
+ {\ifcsname\??dimensionwidth#value\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\assign_width_direct
+ \fi{#value}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua
new file mode 100644
index 00000000000..76a2ab915ad
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua
@@ -0,0 +1,136 @@
+return {
+ internals = {
+ --
+ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel",
+ "shadefactor",
+ "textextoffset",
+ "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent",
+ "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent",
+ "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent",
+ "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent",
+ -- "originlength", "tickstep ", "ticklength",
+ -- "autoarrows", "ahfactor",
+ -- "angleoffset", anglelength", anglemethod",
+ "ahvariant", "ahdimple", "ahfactor",
+ "metapostversion",
+ "maxdimensions",
+ "drawoptionsfactor",
+ },
+ commands = {
+ "transparency",
+ --
+ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian",
+ "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos",
+ "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh",
+ "zmod",
+ "paired", "tripled",
+ "unitcircle", "fulldiamond", "unitdiamond", "fullsquare",
+ -- "halfcircle", "quartercircle",
+ "llcircle", "lrcircle", "urcircle", "ulcircle",
+ "tcircle", "bcircle", "lcircle", "rcircle",
+ "lltriangle", "lrtriangle", "urtriangle", "ultriangle",
+ "uptriangle", "downtriangle", "lefttriangle", "righttriangle", "triangle",
+ "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened",
+ "punked", "curved", "unspiked", "simplified", "blownup", "stretched",
+ "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged",
+ "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed",
+ "llenlarged", "lrenlarged", "urenlarged", "ulenlarged",
+ "llmoved", "lrmoved", "urmoved", "ulmoved",
+ "rightarrow", "leftarrow", "centerarrow",
+ "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox",
+ "bottomboundary", "leftboundary", "topboundary", "rightboundary",
+ "xsized", "ysized", "xysized", "sized", "xyscaled",
+ "intersection_point", "intersection_found", "penpoint",
+ "bbwidth", "bbheight",
+ "withshade", "withcircularshade", "withlinearshade", -- old but kept
+ "defineshade", "shaded",
+ -- "withshading", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor",
+ "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector",
+ "withshadecenter", "withshadedirection", "withshadestep", "withshadefraction",
+ "cmyk", "spotcolor", "multitonecolor", "namedcolor",
+ "drawfill", "undrawfill",
+ "inverted", "uncolored", "softened", "grayed", "greyed",
+ "onlayer",
+ "along",
+ "graphictext", "loadfigure", "externalfigure", "figure", "register", "outlinetext", -- "lua",
+ "checkedbounds", "checkbounds", "strut", "rule",
+ "withmask", "bitmapimage",
+ "colordecimals", "ddecimal", "dddecimal", "ddddecimal",
+ "textext", "thetextext", "rawtextext", "textextoffset",
+ "verbatim",
+ "thelabel", "label",
+ "autoalign",
+ "transparent", "withtransparency",
+ "property", "properties", "withproperties",
+ "asgroup",
+ "infont", -- redefined using textext
+ -- "set_linear_vector", "set_circular_vector",
+ -- "linear_shade", "circular_shade",
+ -- "define_linear_shade", "define_circular_shade",
+ -- "define_circular_linear_shade", "define_circular_linear_shade",
+ -- "define_sampled_linear_shade", "define_sampled_circular_shade",
+ "space", "crlf", "dquote", "percent", "SPACE", "CRLF", "DQUOTE", "PERCENT",
+ "grayscale", "greyscale", "withgray", "withgrey",
+ "colorpart",
+ "readfile",
+ "clearxy", "unitvector", "center", -- redefined
+ "epsed", "anchored",
+ "originpath", "infinite",
+ "break",
+ "xstretched", "ystretched", "snapped",
+ --
+ "pathconnectors", "function",
+ "constructedfunction", "constructedpath", "constructedpairs",
+ -- "punkedfunction", "punkedpath", "punkedpairs",
+ "straightfunction", "straightpath", "straightpairs",
+ "curvedfunction", "curvedpath", "curvedpairs",
+ -- "tightfunction", "tightpath", "tightpairs",
+ --
+ "evenly", "oddly",
+ --
+ "condition",
+ --
+ "pushcurrentpicture", "popcurrentpicture",
+ --
+ "arrowpath",
+ -- "colorlike", "dowithpath", "rangepath", "straightpath", "addbackground",
+ -- "cleanstring", "asciistring", "setunstringed", "getunstringed", "unstringed",
+ -- "showgrid",
+ -- "phantom",
+ -- "xshifted", "yshifted",
+ -- "drawarrowpath", "midarrowhead", "arrowheadonpath",
+ -- "drawxticks", "drawyticks", "drawticks",
+ -- "pointarrow",
+ -- "thefreelabel", "freelabel", "freedotlabel",
+ -- "anglebetween", "colorcircle",
+ -- "remapcolors", "normalcolors", "resetcolormap", "remapcolor", "remappedcolor",
+ -- "recolor", "refill", "redraw", "retext", "untext", "restroke", "reprocess", "repathed",
+ "tensecircle", "roundedsquare",
+ "colortype", "whitecolor", "blackcolor", "basiccolors",
+ --
+ -- "swappointlabels",
+ "normalfill", "normaldraw", "visualizepaths", "detailpaths", "naturalizepaths",
+ "drawboundary", "drawwholepath", "drawpathonly",
+ "visualizeddraw", "visualizedfill", "detaileddraw",
+ "draworigin", "drawboundingbox",
+ "drawpath",
+ "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines",
+ "drawpointlabels",
+ "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions",
+ "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions",
+ --
+ "undashed",
+ --
+ "decorated", "redecorated", "undecorated",
+ --
+ "passvariable", "passarrayvariable", "tostring", "format", "formatted",
+ "startpassingvariable", "stoppassingvariable",
+ --
+ "eofill", "eoclip", "nofill", "fillup", "eofillup",
+ "area",
+ --
+ "addbackground",
+ --
+ "shadedup", "shadeddown", "shadedleft", "shadedright",
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua
new file mode 100644
index 00000000000..409c735b7a6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua
@@ -0,0 +1,464 @@
+if not modules then modules = { } end modules ['mult-ini'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, gmatch, match, find, sub = string.format, string.gmatch, string.match, string.find, string.sub
+local lpegmatch = lpeg.match
+local serialize, concat = table.serialize, table.concat
+local rawget, type = rawget, type
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+local prtcatcodes = catcodes.numbers.prtcatcodes
+local vrbcatcodes = catcodes.numbers.vrbcatcodes
+local contextsprint = context.sprint
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local report_interface = logs.reporter("interface","initialization")
+
+interfaces = interfaces or { }
+interfaces.constants = mark(interfaces.constants or { })
+interfaces.variables = mark(interfaces.variables or { })
+interfaces.elements = mark(interfaces.elements or { })
+interfaces.formats = mark(interfaces.formats or { })
+interfaces.translations = mark(interfaces.translations or { })
+interfaces.setupstrings = mark(interfaces.setupstrings or { })
+interfaces.corenamespaces = mark(interfaces.corenamespaces or { })
+
+local registerstorage = storage.register
+local sharedstorage = storage.shared
+
+local constants = interfaces.constants
+local variables = interfaces.variables
+local elements = interfaces.elements
+local formats = interfaces.formats
+local translations = interfaces.translations
+local setupstrings = interfaces.setupstrings
+local corenamespaces = interfaces.corenamespaces
+local reporters = { } -- just an optimization
+
+registerstorage("interfaces/constants", constants, "interfaces.constants")
+registerstorage("interfaces/variables", variables, "interfaces.variables")
+registerstorage("interfaces/elements", elements, "interfaces.elements")
+registerstorage("interfaces/formats", formats, "interfaces.formats")
+registerstorage("interfaces/translations", translations, "interfaces.translations")
+registerstorage("interfaces/setupstrings", setupstrings, "interfaces.setupstrings")
+registerstorage("interfaces/corenamespaces", corenamespaces, "interfaces.corenamespaces")
+
+interfaces.interfaces = {
+ "cs", "de", "en", "fr", "it", "nl", "ro", "pe",
+}
+
+sharedstorage.currentinterface = sharedstorage.currentinterface or "en"
+sharedstorage.currentresponse = sharedstorage.currentresponse or "en"
+
+local currentinterface = sharedstorage.currentinterface
+local currentresponse = sharedstorage.currentresponse
+
+interfaces.currentinterface = currentinterface
+interfaces.currentresponse = currentresponse
+
+local complete = allocate()
+interfaces.complete = complete
+
+local function resolve(t,k) -- one access needed to get loaded (not stored!)
+ report_interface("loading interface definitions from 'mult-def.lua'")
+ complete = dofile(resolvers.findfile("mult-def.lua"))
+ report_interface("loading interface messages from 'mult-mes.lua'")
+ complete.messages = dofile(resolvers.findfile("mult-mes.lua"))
+ interfaces.complete = complete
+ return rawget(complete,k)
+end
+
+setmetatableindex(complete, resolve)
+
+local function valueiskey(t,k) -- will be helper
+ t[k] = k
+ return k
+end
+
+setmetatableindex(variables, valueiskey)
+setmetatableindex(constants, valueiskey)
+setmetatableindex(elements, valueiskey)
+setmetatableindex(formats, valueiskey)
+setmetatableindex(translations, valueiskey)
+setmetatableindex(setupstrings, valueiskey)
+
+function interfaces.registernamespace(n,namespace)
+ corenamespaces[n] = namespace
+end
+
+local function resolve(t,k)
+ local v = logs.reporter(k)
+ t[k] = v
+ return v
+end
+
+setmetatableindex(reporters,resolve)
+
+for category, _ in next, translations do
+ -- We pre-create reporters for already defined messages
+ -- because otherwise listing is incomplete and we want
+ -- to use that for checking so delaying makes not much
+ -- sense there.
+ local r = reporters[category]
+end
+
+-- adding messages
+
+local function add(target,tag,values)
+ local t = target[tag]
+ if not f then
+ target[tag] = values
+ else
+ for k, v in next, values do
+ if f[k] then
+ -- error
+ else
+ f[k] = v
+ end
+ end
+ end
+end
+
+function interfaces.settranslation(tag,values)
+ add(translations,tag,values)
+end
+
+function interfaces.setformat(tag,values)
+ add(formats,tag,values)
+end
+
+local function getsetupstring(tag)
+ return setupstrings[tag] or tag
+end
+
+interfaces.getsetupstring = getsetupstring
+
+-- the old method:
+
+local replacer = lpeg.replacer { { "--", "%%a" } }
+
+local function fulltag(category,tag)
+ return formatters["%s:%s"](category,lpegmatch(replacer,tag))
+end
+
+function interfaces.setmessages(category,str)
+ for tag, message in gmatch(str,"(%S+) *: *(.-) *[\n\r]") do
+ if tag == "title" then
+ translations[tag] = translations[tag] or tag
+ else
+ formats[fulltag(category,tag)] = lpegmatch(replacer,message)
+ end
+ end
+end
+
+function interfaces.setmessage(category,tag,message)
+ formats[fulltag(category,tag)] = lpegmatch(replacer,message)
+end
+
+function interfaces.getmessage(category,tag,default)
+ return formats[fulltag(category,tag)] or default or "unknown message"
+end
+
+function interfaces.doifelsemessage(category,tag)
+ return rawget(formats,fulltag(category,tag))
+end
+
+local splitter = lpeg.splitat(",")
+
+function interfaces.showmessage(category,tag,arguments)
+ local r = reporters[category]
+ local f = formats[fulltag(category,tag)]
+ local t = type(arguments)
+ if t == "string" and #arguments > 0 then
+ r(f,lpegmatch(splitter,arguments))
+ elseif t == "table" then
+ r(f,unpack(arguments))
+ elseif arguments then
+ r(f,arguments)
+ else
+ r(f)
+ end
+end
+
+-- till here
+
+function interfaces.setvariable(variable,given)
+ variables[given] = variable
+end
+
+function interfaces.setconstant(constant,given)
+ constants[given] = constant
+end
+
+function interfaces.setelement(element,given)
+ elements[given] = element
+end
+
+-- the real thing:
+
+logs.setmessenger(context.verbatim.ctxreport)
+
+-- todo: use setmacro
+
+function interfaces.setuserinterface(interface,response)
+ sharedstorage.currentinterface, currentinterface = interface, interface
+ sharedstorage.currentresponse, currentresponse = response, response
+ if environment.initex then
+ local setmacro = false
+ -- local setmacro = interfaces.setmacro -- cleaner (but we need to test first)
+ local nofconstants = 0
+ local nofvariables = 0
+ local nofelements = 0
+ local nofcommands = 0
+ local nofformats = 0
+ local noftranslations = 0
+ local nofsetupstrings = 0
+ --
+ if setmacro then
+ for given, constant in next, complete.constants do
+ constant = constant[interface] or constant.en or given
+ constants[constant] = given -- breedte -> width
+ nofconstants = nofconstants + 1
+ setmacro("c!"..given,given)
+ if currentinterface ~= "en" then
+ setmacro("k!"..constant,given)
+ end
+ end
+ else
+ local t, f, s = { }, formatters["\\ui_c{%s}{%s}"], formatters["\\ui_s{%s}"]
+ for given, constant in next, complete.constants do
+ constant = constant[interface] or constant.en or given
+ constants[constant] = given -- breedte -> width
+ nofconstants = nofconstants + 1
+ if given == constant then
+ t[nofconstants] = s(given)
+ else
+ t[nofconstants] = f(given,constant)
+ end
+ end
+ contextsprint(prtcatcodes,concat(t))
+ end
+ --
+ if setmacro then
+ for given, variable in next, complete.variables do
+ variable = variable[interface] or variable.en or given
+ variables[given] = variable -- ja -> yes
+ nofvariables = nofvariables + 1
+ setmacro("v!"..given,variable)
+ end
+ else
+ local t, f = { }, formatters["\\ui_v{%s}{%s}"]
+ for given, variable in next, complete.variables do
+ variable = variable[interface] or variable.en or given
+ variables[given] = variable -- ja -> yes
+ nofvariables = nofvariables + 1
+ t[nofvariables] = f(given,variable)
+ end
+ contextsprint(prtcatcodes,concat(t))
+ end
+ --
+ if setmacro then
+ for given, element in next, complete.elements do
+ element = element[interface] or element.en or given
+ elements[element] = given
+ nofelements = nofelements + 1
+ setmacro("e!"..given,element)
+ end
+ else
+ local t, f = { }, formatters["\\ui_e{%s}{%s}"]
+ for given, element in next, complete.elements do
+ element = element[interface] or element.en or given
+ elements[element] = given
+ nofelements = nofelements + 1
+ t[nofelements] = f(given,element)
+ end
+ contextsprint(prtcatcodes,concat(t))
+ end
+ --
+ if setmacro then
+ -- this can only work ok when we already have defined the command
+ luatex.registerdumpactions(function()
+ for given, command in next, complete.commands do
+ command = command[interface] or command.en or given
+ if command ~= given then
+ setmacro(prtcatcodes,given,"\\"..command)
+ end
+ nofcommands = nofcommands + 1
+ end
+ end)
+ else
+ local t, n, f = { }, 0, formatters["\\ui_m{%s}{%s}"]
+ for given, command in next, complete.commands do
+ command = command[interface] or command.en or given
+ if command ~= given then
+ n = n + 1
+ t[n] = f(given,command)
+ end
+ nofcommands = nofcommands + 1
+ end
+ contextsprint(prtcatcodes,concat(t))
+ end
+ --
+ for given, format in next, complete.messages.formats do
+ formats[given] = format[interface] or format.en or given
+ nofformats = nofformats + 1
+ end
+ --
+ for given, translation in next, complete.messages.translations do
+ translations[given] = translation[interface] or translation.en or given
+ noftranslations = noftranslations + 1
+ end
+ --
+ for given, setupstring in next, complete.setupstrings do
+ setupstring = setupstring[interface] or setupstring.en or given
+ setupstrings[given] = setupstring
+ nofsetupstrings = nofsetupstrings + 1
+ end
+ --
+ report_interface("definitions: %a constants, %a variables, %a elements, %a commands, %a formats, %a translations, %a setupstrings",
+ nofconstants,nofvariables,nofelements,nofcommands,nofformats,noftranslations,nofsetupstrings)
+ else
+ report_interface("the language(s) can only be set when making the format")
+ end
+ interfaces.currentinterface = currentinterface
+ interfaces.currentresponse = currentresponse
+end
+
+interfaces.implement {
+ name = "setuserinterface",
+ actions = interfaces.setuserinterface,
+ arguments = { "string", "string" }
+}
+
+interfaces.cachedsetups = interfaces.cachedsetups or { }
+interfaces.hashedsetups = interfaces.hashedsetups or { }
+
+local cachedsetups = interfaces.cachedsetups
+local hashedsetups = interfaces.hashedsetups
+
+storage.register("interfaces/cachedsetups", cachedsetups, "interfaces.cachedsetups")
+storage.register("interfaces/hashedsetups", hashedsetups, "interfaces.hashedsetups")
+
+function interfaces.cachesetup(t)
+ local hash = serialize(t)
+ local done = hashedsetups[hash]
+ if done then
+ return cachedsetups[done]
+ else
+ done = #cachedsetups + 1
+ cachedsetups[done] = t
+ hashedsetups[hash] = done
+ return t
+ end
+end
+
+function interfaces.interfacedcommand(name)
+ local command = complete.commands[name]
+ return command and command[currentinterface] or name
+end
+
+-- interface
+
+function interfaces.writestatus(category,message)
+ reporters[category](message) -- could also be a setmetatablecall
+end
+
+function interfaces.message(str)
+ texio.write(str) -- overloaded
+end
+
+implement { name = "registernamespace", actions = interfaces.registernamespace, arguments = { "integer", "string" } }
+implement { name = "setinterfaceconstant", actions = interfaces.setconstant, arguments = { "string", "string" } }
+implement { name = "setinterfacevariable", actions = interfaces.setvariable, arguments = { "string", "string" } }
+implement { name = "setinterfaceelement", actions = interfaces.setelement, arguments = { "string", "string" } }
+implement { name = "setinterfacemessage", actions = interfaces.setmessage, arguments = { "string", "string", "string" } }
+implement { name = "setinterfacemessages", actions = interfaces.setmessages, arguments = { "string", "string" } }
+implement { name = "showmessage", actions = interfaces.showmessage, arguments = { "string", "string", "string" } }
+
+implement {
+ name = "doifelsemessage",
+ actions = { interfaces.doifelsemessage, commands.doifelse },
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "getmessage",
+ actions = { interfaces.getmessage, context },
+ arguments = { "string", "string", "string" },
+}
+
+implement {
+ name = "writestatus",
+ overload = true,
+ actions = interfaces.writestatus,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "message",
+ overload = true,
+ actions = interfaces.message,
+ arguments = "string",
+}
+
+implement {
+ name = "getsetupstring",
+ actions = function(s)
+ contextsprint(vrbcatcodes,getsetupstring(s))
+ end,
+ arguments = "string",
+}
+
+local function showassignerror(namespace,key,line)
+ local ns, instance = match(namespace,"^(%d+)[^%a]+(%a*)")
+ if ns then
+ namespace = corenamespaces[tonumber(ns)] or ns
+ end
+ -- injected in the stream for timing:
+ if instance and instance ~= "" then
+ context.writestatus("setup",formatters["error in line %a, namespace %a, instance %a, key %a"](line,namespace,instance,key))
+ else
+ context.writestatus("setup",formatters["error in line %a, namespace %a, key %a"](line,namespace,key))
+ end
+end
+
+implement {
+ name = "showassignerror",
+ actions = showassignerror,
+ arguments = { "string", "string", "integer" },
+}
+
+-- a simple helper
+
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local makesparse = function(t)
+ for k, v in next, t do
+ if not v or v == "" then
+ t[k] = nil
+ end
+ end
+ return t
+end
+
+function interfaces.checkedspecification(specification)
+ local kind = type(specification)
+ if kind == "table" then
+ return makesparse(specification)
+ elseif kind == "string" and specification ~= "" then
+ return makesparse(settings_to_hash(specification))
+ else
+ return { }
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv
new file mode 100644
index 00000000000..8ed147c63e4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv
@@ -0,0 +1,859 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is a stripped down version of \type {mult-ini.tex},
+%D which we keep around as \type {mult-kep.tex} for sentimental
+%D reasons. There you will find some more historic information.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Initialization}
+
+\unprotect
+
+\registerctxluafile{mult-ini}{1.001}
+
+%D \macros
+%D [constanten,variabelen,commands]
+%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!}
+%D
+%D In the system modules we introduced some prefixed constants,
+%D variables (both macros) and registers. Apart from a
+%D tremendous saving in terms of memory and a gain in speed we
+%D use from now on prefixes when possible for just another
+%D reason: consistency and multi||linguality. Systematically
+%D using prefixed macros enables us to implement a
+%D multi||lingual user interface. Redefining these next set of
+%D prefixes therefore can have desastrous results.
+%D
+%D \startlinecorrection
+%D \starttable[|c|c|c|]
+%D \HL
+%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR
+%D \HL
+%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR
+%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\FR
+%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR
+%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR
+%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR
+%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR
+%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D In the single||lingual version we used \type{!}, \type{!!},
+%D \type{!!!} and \type{!!!!}. In the meantime some of these
+%D are obsolete (we had some 12 originally).
+
+\def\c!prefix!{c!}
+\def\k!prefix!{k!}
+\def\e!prefix!{e!}
+\def\f!prefix!{f!} % for the moment we keep this one
+\def\m!prefix!{m!}
+\def\s!prefix!{s!}
+\def\v!prefix!{v!}
+
+%D \macros
+%D [constants,variables,commands]
+%D {@@,??}
+%D
+%D Variables generated by the system can be recognized on their
+%D prefix \type{@@}. They are composed of a command (class)
+%D specific tag, which can be recognized on \type{??}, and a
+%D system constant, which has the prefix \type{c!}. We'll se
+%D some more of this.
+
+\def\??prefix {??}
+\def\@@prefix {@@}
+
+%D Just to be complete we repeat some of the already defined
+%D system constants here. Maybe their prefix \type{\s!} now
+%D falls into place.
+
+\def\s!next {next} \def\s!default {default}
+\def\s!dummy {dummy} \def\s!unknown {unknown}
+
+\def\s!do {do} \def\s!dodo {dodo}
+
+\def\s!complex {complex} \def\s!start {start}
+\def\s!simple {simple} \def\s!stop {stop}
+
+\def\s!true {true}
+\def\s!false {false}
+
+%D The word \type{height} takes 6~token memory cells. The
+%D control sequence \type{\height} on the other hand uses only
+%D one. Knowing this, we can improve the performance of \TEX,
+%D both is terms of speed and memory usage, by using control
+%D sequences instead of the words written in full.
+%D
+%D Where in the \ASCII\ file the second lines takes nine extra
+%D characters, \TEX\ saves us 13~tokens.
+%D
+%D \starttyping
+%D \hrule width 10pt height 2pt depth 1pt
+%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt
+%D \stoptyping
+%D
+%D One condition is that we have defined \type {\s!height},
+%D \type {\s!width} and \type {\s!depth} as respectively
+%D \type {height}, \type {width} and \type {depth}. Using this
+%D scheme therefore only makes sense when a token sequence is
+%D used more than once. Savings like this should of course be
+%D implemented in english, just because \TEX\ is english.
+
+\def\s!width {width} \let\!!width \s!width % obsolete
+\def\s!height{height} \let\!!height\s!height % obsolete
+\def\s!depth {depth} \let\!!depth \s!depth % obsolete
+\def\s!spread{spread} \let\!!spread\s!spread % obsolete
+\def\s!plus {plus} \let\!!plus \s!plus % obsolete
+\def\s!minus {minus} \let\!!minus \s!minus % obsolete
+\def\s!fil {fil}
+\def\s!fill {fill} \let\!!fill \s!fill % obsolete
+\def\s!filll {filll}
+\def\s!to {to} \let\!!to \s!to % obsolete
+\def\s!attr {attr}
+
+\def\s!bottom{bottom}
+\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,
+%D defineinterfaceelement,
+%D definesystemvariable,
+%D definesystemconstant,
+%D definemessageconstant,
+%D definefileconstant}
+%D
+%D The first part of this module is dedicated to dealing with
+%D multi||lingual constants and variables. When \CONTEXT\ grew
+%D bigger and bigger in terms of bytes and used string space,
+%D we switched to predefined constants. At the cost of more
+%D hash table entries, the macros not only becase more compact,
+%D they became much faster too. Maybe an even bigger advantage
+%D was that mispelling could no longer lead to problems. Even a
+%D multi||lingual interface became possible.
+%D
+%D Constants --- we'll introduce the concept of variables later
+%D on --- are preceded by a type specific prefix, followed by a
+%D \type{!}. To force consistency, we provide a few commands
+%D for defining such constants.
+%D
+%D \starttyping
+%D \defineinterfaceconstant {name} {meaning}
+%D \defineinterfacevariable {name} {meaning}
+%D \defineinterfaceelement {name} {meaning}
+%D \stoptyping
+%D
+%D Which is the same as:
+%D
+%D \starttyping
+%D \def\c!name{meaning}
+%D \def\v!name{meaning}
+%D \def\e!name{meaning}
+%D \stoptyping
+
+\unexpanded\def\defineinterfaceconstant #1#2{\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
+\unexpanded\def\defineinterfacevariable #1#2{\expandafter\def\csname\v!prefix!#1\endcsname{#2}}
+\unexpanded\def\defineinterfaceelement #1#2{\expandafter\def\csname\e!prefix!#1\endcsname{#2}}
+
+%D Next come some interface independant constants:
+%D
+%D \starttyping
+%D \definefileconstant {name} {meaning}
+%D \stoptyping
+
+\unexpanded\def\definefileconstant #1#2{\expandafter\def\csname\f!prefix!#1\endcsname{#2}}
+
+%D And finaly we have the one argument, space saving constants
+%D
+%D \starttyping
+%D \definesystemconstant {name}
+%D \definemessageconstant {name}
+%D \stoptyping
+
+\unexpanded\def\definesystemconstant #1{\expandafter\def\csname\s!prefix!#1\endcsname{#1}}
+\unexpanded\def\definemessageconstant #1{\expandafter\def\csname\m!prefix!#1\endcsname{#1}}
+
+%D In a parameter driven system, some parameters are shared
+%D by more system components. In \CONTEXT\ we can distinguish
+%D parameters by a unique prefix. Such a prefix is defined
+%D with:
+%D
+%D \starttyping
+%D \definesystemvariable {name}
+%D \stoptyping
+
+\unexpanded\def\definesystemvariable#1{\expandafter\edef\csname\??prefix#1\endcsname{\@@prefix#1}}
+
+\definesystemvariable{ms}
+
+%D \macros
+%D {selectinterface,
+%D defaultinterface, currentinterface, currentresponses}
+%D
+%D With \type{\selectinterface} we specify the language we are
+%D going to use. The system asks for the language wanted, and
+%D defaults to \type{\currentinterface} when we just give
+%D \type{enter}. By default the message system uses the
+%D current interface language, but \type{\currentresponses}
+%D can specify another language too.
+%D
+%D Because we want to generate formats directly too, we do
+%D not ask for interface specifications when these are already
+%D defined (like in cont-nl.tex and alike).
+
+\ifdefined\defaultinterface
+
+ \def\selectinterface
+ {\writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\else
+
+ \def\defaultinterface{english}
+
+ \def\selectinterface
+ {\def\selectinterface##1##2%
+ {\bgroup
+ \endlinechar\minusone
+ \global\read16 to ##1
+ \egroup
+ \doifnothing\currentinterface{\let##1=##2}%
+ \doifundefined{\s!prefix!##1}{\let##1=##2}}%
+ \selectinterface\currentinterface\defaultinterface
+ \writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \selectinterface\currentresponses\currentinterface
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\fi
+
+\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi
+\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi
+
+%D \macros
+%D {startinterface}
+%D
+%D Sometimes we want to define things only for specific
+%D interface languages. This can be done by means of the
+%D selector:
+%D
+%D \starttyping
+%D \startinterface language
+%D
+%D language specific definitions & commands
+%D
+%D \stopinterface
+%D \stoptyping
+
+\unexpanded\def\startinterface #1
+ {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}}
+
+\let\stopinterface\relax
+
+%D \macros
+%D {startmessages,
+%D getmessage,
+%D showmessage,
+%D makemessage}
+%D
+%D A package as large as \CONTEXT\ can hardly function without
+%D a decent message mechanism. Due to its multi||lingual
+%D interface, the message subsystem has to be multi||lingual
+%D too. A major drawback of this feature is that we have to
+%D code messages. As a result, the source becomes less self
+%D documented. On the other hand, consistency will improve.
+%D
+%D Because the overhead in terms of entries in the (already
+%D exhausted) hash table has to be minimal, messages are packed
+%D in libraries. We can extract a message from such a library
+%D in three ways:
+%D
+%D \starttyping
+%D \getmessage {library} {tag}
+%D \showmessage {library} {tag} {data}
+%D \makemessage {library} {tag} {data}
+%D \stoptyping
+%D
+%D The first command gets the message \type{tag} from the
+%D \type{library} specified. The other commands take an extra
+%D argument: a list of items to be inserted in the message
+%D text. While \type{\showmessage} shows the message at the
+%D terminal, the other commands generate the message as text.
+%D Before we explain the \type{data} argument, we give an
+%D example of a library.
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D title: something
+%D 1: first message
+%D 2: second (--) message --
+%D \stopmessages
+%D \stoptyping
+%D
+%D The first message is a simple one and can be shown with:
+%D
+%D \starttyping
+%D \showmessage {alfa} {1} {}
+%D \stoptyping
+%D
+%D The second message on the other hand needs some extra data:
+%D
+%D \starttyping
+%D \showmessage {alfa} {2} {and last,to you}
+%D \stoptyping
+%D
+%D This message is shown as:
+%D
+%D \starttyping
+%D something : second (and last) message to you
+%D \stoptyping
+%D
+%D As we can see, the title entry is shown with the message.
+%D The data fields are comma separated and are specified in the
+%D message text by \type{--}.
+%D
+%D It is not required to define all messages in a library at
+%D once. We can add messages to a library in the following way:
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D 10: tenth message
+%D \stopmessages
+%D \stoptyping
+%D
+%D Because such definitions can take place in different
+%D modules, the system gives a warning when a tag occurs more
+%D than once. The first occurrence takes preference over later
+%D ones, so we had better use a save offset, as shown in the
+%D example. As we can see, the title field is specified only
+%D the first time!
+%D
+%D Because we want to check for duplicate tags, the macros
+%D are a bit more complicated than neccessary. The \NEWLINE\
+%D token is used as message separator.
+%D
+%D For internal purposes one can use \type {\setmessagetext},
+%D which puts the message text asked for in \type
+%D {\currentmessagetext}.
+
+%D These will become obsolete:
+
+\unexpanded\def\startmessages #1 library: #2 %
+ {\bgroup
+ \ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi
+ \catcode\endoflineasciicode\activecatcode
+ \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}
+
+\def\mult_messages_start_nop#1#2\stopmessages
+ {\egroup}
+
+\let\stopmessages\relax
+
+\unexpanded\def\setinterfacemessage#1#2#3%
+ {\ifcsname\m!prefix!#1\endcsname\else\setgvalue{\m!prefix!#1}{#1}\fi
+ \clf_setinterfacemessage{#1}{#2}{#3}}
+
+\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\clf_getmessage{#1}{#2}}}
+\unexpanded\def\getmessage #1#2{\clf_getmessage{#1}{#2}}
+\unexpanded\def\doifelsemessage #1#2{\clf_doifelsemessage{#1}{#2}}
+\unexpanded\def\showmessage #1#2#3{\clf_showmessage{#1}{#2}{#3}}
+\unexpanded\def\writestatus #1#2{\clf_writestatus{#1}{#2}}
+\unexpanded\def\message {\clf_message}
+
+\let\doifmessageelse\doifelsemessage
+
+\unexpanded\def\inlinemessage #1{\dontleavehmode{\tttf#1}}
+\unexpanded\def\displaymessage#1{\blank\inlinemessage{#1}\blank}
+
+\let\getsetupstring\clf_getsetupstring
+
+%D \macros
+%D {ifshowwarnings, ifshowmessages}
+%D
+%D Sometimes displaying message can slow down processing
+%D considerably. We therefore introduce warnings. Users can
+%D turn of warnings and messages by saying:
+%D
+%D \starttyping
+%D \showwarningstrue
+%D \showmessagestrue
+%D \stoptyping
+%D
+%D Turning off messages also turns off warnings, which is
+%D quote logical because they are less important.
+
+% not yet mkiv
+
+\newif\ifshowwarnings \showwarningstrue
+\newif\ifshowmessages \showmessagestrue
+
+\let\normalshowmessage\showmessage
+
+\unexpanded\def\showwarning
+ {\ifshowwarnings
+ \expandafter\showmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+\unexpanded\def\showmessage
+ {\ifshowmessages
+ \expandafter\normalshowmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue
+%D
+%D We already defined these auxiliary macros in the system
+%D modules. Starting with this module however, we have to take
+%D multi||linguality a bit more serious.
+
+%D In due time, when we exclusively use the parameter handler code, we can drop
+%D the backmapping (\type{\c!k...}) and make \type {\c!c...} similar to
+%D \type {\v!...}. In that case we can simply the following setters.
+
+\unexpanded\def\doletvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetvalue #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetevalue #1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetgvalue #1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetxvalue #1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\doresetvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\unexpanded\def\doignorevalue#1#2#3{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+
+\unexpanded\def\docopyvalue#1#2#3%
+ {\ifcsname\k!prefix!#3\endcsname
+ \expandafter\def\csname#1\csname\k!prefix!#3\endcsname\expandafter\endcsname\expandafter
+ {\csname#2\csname\k!prefix!#3\endcsname\endcsname}%
+ \else
+ \expandafter\def\csname#1#3\expandafter\endcsname\expandafter
+ {\csname#2#3\endcsname}%
+ \fi}
+
+\startinterface english
+
+ \unexpanded\def\doletvalue #1#2{\expandafter \let\csname#1#2\endcsname}
+ \unexpanded\def\dosetvalue #1#2{\expandafter \def\csname#1#2\endcsname}
+ \unexpanded\def\dosetevalue #1#2{\expandafter\edef\csname#1#2\endcsname}
+ \unexpanded\def\dosetgvalue #1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \unexpanded\def\dosetxvalue #1#2{\expandafter\xdef\csname#1#2\endcsname}
+ \unexpanded\def\doresetvalue #1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \unexpanded\def\doignorevalue#1#2#3{\expandafter \let\csname#1#2\endcsname\empty}
+
+ \unexpanded\def\docopyvalue#1#2#3%
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter
+ {\csname#2#3\endcsname}}
+
+\stopinterface
+
+%D We can now redefine some messages that will be
+%D introduced in the multi||lingual system module.
+
+\unexpanded\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}\waitonfatalerror}
+\unexpanded\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}\waitonfatalerror}
+\unexpanded\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}\waitonfatalerror}
+
+%D \CONTEXT\ is a parameter driven package. This means that
+%D users instruct the system by means of variables, values and
+%D keywords. These instructions take the form:
+%D
+%D \starttyping
+%D \setupsomething[some variable=some value, another one=a keyword]
+%D \stoptyping
+%D
+%D or by keyword only:
+%D
+%D \starttyping
+%D \dosomething[this way,that way,no way]
+%D \stoptyping
+%D
+%D Because the same variables can occur in more than one setup
+%D command, we have to be able to distinguish them. This is
+%D achieved by assigning them a unique prefix.
+%D
+%D Imagine a setup command for boxed text, that enables us to
+%D specify the height and width of the box. Behide the scenes
+%D the command
+%D
+%D \starttyping
+%D \setupbox [width=12cm, height=3cm]
+%D \stoptyping
+%D
+%D results in something like
+%D
+%D \starttyping
+%D \<box><width> {12cm}
+%D \<box><height> {3cm}
+%D \stoptyping
+%D
+%D while a similar command for specifying the page dimensions
+%D of an \cap{A4} page results in:
+%D
+%D \starttyping
+%D \<page><width> {21.0cm}
+%D \<page><height> {27.9cm}
+%D \stoptyping
+%D
+%D The prefixes \type{<box>} and \type{<page>} are hidden from
+%D users and can therefore be language independant. Variables
+%D on the other hand, differ for each language:
+%D
+%D \starttyping
+%D \<box><color> {<blue>}
+%D \<box><kleur> {<blauw>}
+%D \<box><couleur> {<blue>}
+%D \stoptyping
+%D
+%D In this example we can see that the assigned values or
+%D keywords are language dependant too. This will be a
+%D complication when defining multi||lingual setup files.
+%D
+%D A third phenomena is that variables and values can have a
+%D similar meaning.
+%D
+%D \starttyping
+%D \<pagenumber><location> {<left>}
+%D \<skip><left> {12cm}
+%D \stoptyping
+%D
+%D A (minor) complication is that where in english we use
+%D \type{<left>}, in dutch we find both \type{<links>} and
+%D \type{<linker>}. This means that when we use some sort of
+%D translation table, we have to distinguish between the
+%D variables at the left side and the fixed values at the
+%D right.
+%D
+%D The same goes for commands that are composed of different
+%D user supplied and/or language specific elements. In english
+%D we can use:
+%D
+%D \starttyping
+%D \<empty><figure>
+%D \<empty><intermezzo>
+%D \stoptyping
+%D
+%D But in dutch we have the following:
+%D
+%D \starttyping
+%D \<lege><figuur>
+%D \<leeg><intermezzo>
+%D \stoptyping
+%D
+%D These subtle differences automatically lead to a solution
+%D where variables, values, elements and other components have
+%D a similar logical name (used in macro's) but a different
+%D meaning (supplied by the user).
+%D
+%D Our solution is one in which the whole system is programmed
+%D in terms of identifiers with language specific meanings. In
+%D such an implementation, each fixed variable is available as:
+%D
+%D \starttyping
+%D \<prefix><variable>
+%D \stoptyping
+%D
+%D This means that for instance:
+%D
+%D \starttyping
+%D \setupbox[width=12cm]
+%D \stoptyping
+%D
+%D expands to something like:
+%D
+%D \starttyping
+%D \def\boxwidth{12cm}
+%D \stoptyping
+%D
+%D because we don't want to recode the source, a setup command
+%D in another language has to expand to this variable, so:
+%D
+%D \starttyping
+%D \setupblock[width=12cm]
+%D \stoptyping
+%D
+%D has to result in the definition of \type{\boxwidth} too.
+%D This method enables us to build compact, fast and readable
+%D code.
+%D
+%D An alternative method, which we considered using, uses a
+%D more indirect way. In this case, both calls generate a
+%D different variable:
+%D
+%D \starttyping
+%D \def\boxwidth {12cm}
+%D \def\boxbreedte {12cm}
+%D \stoptyping
+%D
+%D And because we don't want to recode those megabytes of
+%D already developed code, this variable has to be called with
+%D something like:
+%D
+%D \starttyping
+%D \valueof\box\width
+%D \stoptyping
+%D
+%D where \type{\valueof} takes care of the translation of
+%D \type{width} or \type{breedte} to \type{width} and
+%D combining this with \type{box} to \type{\boxwidth}.
+%D
+%D One advantage of this other scheme is that, within certain
+%D limits, we can implement an interface that can be switched
+%D to another language at will, while the current approach
+%D fixes the interface at startup. There are, by the way,
+%D other reasons too for not choosing this scheme. Switching
+%D user generated commands is for instance impossible and a
+%D dual interface would therefore give a strange mix of
+%D languages.
+%D
+%D Now let's work out the first scheme. Although the left hand
+%D of the assignment is a variable from the users point of
+%D view, it is a constant in terms of the system. Both
+%D \type{width} and \type{breedte} expand to \type{width}
+%D because in the source we only encounter \type{width}. Such
+%D system constants are presented as
+%D
+%D \starttyping
+%D \c!width
+%D \stoptyping
+%D
+%D This constant is always equivalent to \type{width}. As we
+%D can see, we use \type{c!} to mark this one as constant. Its
+%D dutch counterpart is:
+%D
+%D \starttyping
+%D breedte
+%D \stoptyping
+%D
+%D When we interpret a setup command each variable is
+%D translated to it's \type{c!} counterpart. This means that
+%D \type{breedte} and \type{width} expand to \type{breedte}
+%D and \type{\c!width} which both expand to \type{width}. That
+%D way user variables become system constants.
+%D
+%D The interpretation is done by means of a general setup
+%D command \type{\getparameters} that we introduced in the
+%D system module. Let us define some simple setup command:
+%D
+%D \starttyping
+%D \unexpanded\def\setupbox[#1]%
+%D {\getparameters[\??bx][#1]}
+%D \stoptyping
+%D
+%D This command can be used as:
+%D
+%D \starttyping
+%D \setupbox [width=3cm, height=1cm]
+%D \stoptyping
+%D
+%D Afterwards we have two variables \type{\@@bxwidth} and
+%D \type{\@@bxheight} which have the values \type{3cm} and
+%D \type{1cm} assigned. These variables are a combinatiom of
+%D the setup prefix \type{\??bx}, which expands to \type{@@bx}
+%D and the translated user supplied variables \type{width} and
+%D \type{height} or \type{breedte} and \type{hoogte},
+%D depending on the actual language. In dutch we just say:
+%D
+%D \starttyping
+%D \stelblokin [breedte=3cm,hoogte=1cm]
+%D \stoptyping
+%D
+%D and get ourselves \type{\@@bxwidth} and \type{\@@bxheight}
+%D too. In the source of \CONTEXT, we can recognize constants
+%D and variables on their leading \type{c!}, \type{v!} etc.,
+%D prefixes on \type{??} and composed variables on \type{@@}.
+%D
+%D We already saw that user supplied keywords need some
+%D special treatment too. This time we don't translate the
+%D keyword, but instead use in the source a variable which
+%D meaning depends on the interface language.
+%D
+%D \starttyping
+%D \v!left
+%D \stoptyping
+%D
+%D Which can be used in macro's like:
+%D
+%D \starttyping
+%D \processaction
+%D [\@@bxlocation]
+%D [ \v!left=>\dosomethingontheleft,
+%D \v!middle=>\dosomthinginthemiddle,
+%D \v!right=>\dosomethingontheright]
+%D \stoptyping
+%D
+%D Because variables like \type{\@@bxlocation} can have a lot
+%D of meanings, including tricky expandable tokens, we cannot
+%D translate this meaning when we compare. This means that
+%D \type{\@@bxlocation} can be \type{left} of \type{links} of
+%D whatever meaning suits the language. But because
+%D \type{\v!left} also has a meaning that suits the language,
+%D we are able to compare.
+%D
+%D Although we know it sounds confusing we want to state two
+%D important characteristics of the interface as described:
+%D
+%D \startnarrower \em
+%D user variables become system constants
+%D \stopnarrower
+%D
+%D and
+%D
+%D \startnarrower \em
+%D user constants (keywords) become system variables
+%D \stopnarrower
+
+%D The \type {\c!internal} is a left over from the time that
+%D the user interface documents were not using a specification
+%D alongside a keyword specification but used a shared file in
+%D which case we need to go in both directions.
+
+% temporary mkiv hack (we can best just store the whole table in memory)
+
+\unexpanded\def\setinterfaceconstant#1#2%
+ {\clf_setinterfaceconstant{#1}{#2}%
+ \expandafter\def\csname\c!prefix!#1\endcsname{#1}}
+
+\unexpanded\def\setinterfacevariable#1#2%
+ {\clf_setinterfacevariable{#1}{#2}%
+ \expandafter\def\csname\v!prefix!#1\endcsname{#2}}
+
+%D \macros
+%D {defineinterfaceconstant}
+%D
+%D Next we redefine a previously defined macro to take care of
+%D interface translation too. It's a bit redundant, because
+%D in these situations we could use the c||version, but for
+%D documentation purposes the x||alternative comes in handy.
+
+\unexpanded\def\defineinterfaceconstant#1#2%
+ {\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
+
+%D \macros
+%D {startelements}
+%D
+%D Due to the object oriented nature of \CONTEXT, we also need
+%D to define the elements that are used to build commands.
+%D
+%D Such elements sometimes are the same in diferent
+%D languages, but mostly they differ. Things can get even
+%D confusing when we look at for instance the setup commands.
+%D In english we say \type{\setup<something>}, but in dutch we
+%D have: \type{\stel<iets>in}. Such split elements are no
+%D problem, because we just define two elements. When no second
+%D part is needed, we use a \type{-}:
+
+\unexpanded\def\setinterfaceelement#1#2%
+ {\clf_setinterfaceelement{#1}{#2}%
+ \ifcsname\e!prefix!#1\endcsname
+ \doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}%
+ \else
+ \setvalue{\e!prefix!#1}{#2}%
+ \fi}
+
+\unexpanded\def\setinterfacecommand#1#2%
+ {\doifnot{#1}{#2}% todo: let when already defined
+ {\expandafter\def\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}}
+
+%D We just ignore these:
+
+\unexpanded\def\startvariables{\gobbleuntil\stopvariables} \let\stopvariables\relax
+\unexpanded\def\startconstants{\gobbleuntil\stopconstants} \let\stopconstants\relax
+\unexpanded\def\startelements {\gobbleuntil\stopelements } \let\stopelements \relax
+\unexpanded\def\startcommands {\gobbleuntil\stopcommands } \let\stopcommands \relax
+
+%D For at the \LUA\ end (experiment):
+
+% \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+% \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english
+% \def\do@sivar#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}}
+% \def\do@siele#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}}
+% \def\do@sicom#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}
+%
+% \startinterface english
+%
+% \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+%
+% \stopinterface
+
+\def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english
+\def\ui_s #1{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \expandafter\gdef\csname\k!prefix!#1\endcsname{#1}} % backmapping from non english
+\def\ui_v#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}}
+\def\ui_e#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}}
+\def\ui_m#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}
+
+\startinterface english
+
+ \def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+ \def\ui_s #1{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+
+\stopinterface
+
+%D So much for the basic multi||lingual interface commands. The
+%D macro's can be enhanced with more testing facilities, but
+%D for the moment they suffice.
+
+\ifdefined\zwnj \else \edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+\ifdefined\zwj \else \edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+
+%D Out of convenience we define the banners here. This might move
+%D to the \LUA\ end.
+
+\def\contextbanner
+ {ConTeXt \space
+ ver: \contextversion \space \contextmark \space \contextkind \space \space
+ fmt: \formatversion \space \space
+ int: \currentinterface/\currentresponses}
+
+\unexpanded\def\showcontextbanner
+ {\writeline\writebanner{\contextbanner}\writeline}
+
+\edef\formatversion
+ {\the\normalyear .\the\normalmonth.\the\normalday}
+
+\ifx\contextversion\undefined
+ \def\contextversion {unknown}
+ \def\contextversionnumber{0}
+\else
+ %\def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5}
+ \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi\purenumber{#2}\ifnum#3<10 0\fi\purenumber{#3} #4:#5}
+ \edef\contextversionnumber{\expandafter\contextversionnumber\contextversion\relax\space\contextmark}
+\fi
+
+\ifx\undefined\everydump
+ \newtoks\everydump
+ \def\dump{\the\everydump\normaldump}
+\fi
+
+\appendtoks \showcontextbanner \to \everydump
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua
new file mode 100644
index 00000000000..c9a13c1e8b7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua
@@ -0,0 +1,425 @@
+if not modules then modules = { } end modules ['mult-low'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- for syntax highlighters, only the ones that are for users (boring to collect them)
+
+return {
+ ["constants"] = {
+ --
+ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive",
+ "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plustwohundred",
+ "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "maxcardminusone",
+ "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint",
+ "points", "halfpoint",
+ "zeroskip",
+ "zeromuskip", "onemuskip",
+ "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi",
+ "normalpagebox",
+ -- --
+ "endoflinetoken", "outputnewlinechar",
+ --
+ "emptytoks", "empty", "undefined",
+ --
+ "voidbox", "emptybox", "emptyvbox", "emptyhbox",
+ --
+ "bigskipamount", "medskipamount", "smallskipamount",
+ --
+ "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion",
+ "luatexengine", "pdftexengine", "xetexengine", "unknownengine",
+ -- "etexversion",
+ -- "pdftexversion", "pdftexrevision",
+ -- "xetexversion", "xetexrevision",
+ --
+ "activecatcode",
+ --
+ "bgroup", "egroup",
+ "endline",
+ --
+ "conditionaltrue", "conditionalfalse",
+ --
+ "attributeunsetvalue",
+ --
+ "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle",
+ --
+ "inicatcodes",
+ "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes",
+ "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes",
+ "xmlcatcodes", "ctdcatcodes",
+ --
+ "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode",
+ "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode",
+ "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode",
+ --
+ "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode",
+ "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode",
+ "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode",
+ "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode",
+ "lessthanasciicode", "morethanasciicode", "doublecommentsignal",
+ "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode",
+ "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode",
+ "primeasciicode", "hyphenasciicode",
+ --
+ "activemathcharcode",
+ --
+ "activetabtoken", "activeformfeedtoken", "activeendoflinetoken",
+ --
+ "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode",
+ --
+ "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode",
+ "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode",
+ "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode",
+ "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode",
+ --
+ "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode",
+ "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode",
+ "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode",
+ --
+ "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode",
+ "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode",
+ "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode",
+ --
+ "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink",
+ "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint",
+ "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace",
+ "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight",
+ "muquad",
+ --
+ -- maybe a different class
+ --
+ "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset",
+ "doifmode", "doifelsemode", "doifmodeelse", "doifnotmode",
+ "startmodeset","stopmodeset",
+ "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes",
+ "doifallmodes", "doifelseallmodes", "doifallmodeselse", "doifnotallmodes",
+ "startenvironment", "stopenvironment", "environment",
+ "startcomponent", "stopcomponent", "component",
+ "startproduct", "stopproduct", "product",
+ "startproject", "stopproject", "project",
+ "starttext", "stoptext", "startnotext", "stopnotext","startdocument", "stopdocument", "documentvariable", "setupdocument",
+ "startmodule", "stopmodule", "usemodule", "usetexmodule", "useluamodule","setupmodule","currentmoduleparameter","moduleparameter",
+ "everystarttext", "everystoptext",
+ --
+ "startTEXpage", "stopTEXpage",
+ -- "startMPpage", "stopMPpage", -- already catched by nested lexer
+ --
+ "enablemode", "disablemode", "preventmode", "definemode",
+ "globalenablemode", "globaldisablemode", "globalpreventmode",
+ "pushmode", "popmode",
+ --
+ "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix",
+ --
+ "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode",
+ "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode",
+ "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode",
+ --
+ "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument",
+ --
+ "continueifinputfile",
+ --
+ "luastringsep", "!!bs", "!!es",
+ --
+ "lefttorightmark", "righttoleftmark",
+ --
+ "breakablethinspace", "nobreakspace", "nonbreakablespace", "narrownobreakspace", "zerowidthnobreakspace",
+ "ideographicspace", "ideographichalffillspace",
+ "twoperemspace", "threeperemspace", "fourperemspace", "fiveperemspace", "sixperemspace",
+ "figurespace", "punctuationspace", "hairspace",
+ "zerowidthspace", "zerowidthnonjoiner", "zerowidthjoiner", "zwnj", "zwj",
+ "optionalspace", "asciispacechar",
+ --
+ "Ux", "eUx", "Umathaccents",
+ },
+ ["helpers"] = {
+ --
+ "startsetups", "stopsetups",
+ "startxmlsetups", "stopxmlsetups",
+ "startluasetups", "stopluasetups",
+ "starttexsetups", "stoptexsetups",
+ "startrawsetups", "stoprawsetups",
+ "startlocalsetups", "stoplocalsetups",
+ "starttexdefinition", "stoptexdefinition",
+ "starttexcode", "stoptexcode",
+ "startcontextcode", "stopcontextcode",
+ "startcontextdefinitioncode", "stopcontextdefinitioncode",
+ "texdefinition",
+ --
+ "doifelsesetups", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "fastsetup",
+ "doifelsecommandhandler", "doifcommandhandlerelse", "doifnotcommandhandler", "doifcommandhandler",
+ --
+ "newmode", "setmode", "resetmode",
+ "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode",
+ "booleanmodevalue",
+ --
+ "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif",
+ "newlanguage", "newfamily", "newfam", "newhelp", -- not used
+ --
+ "then",
+ "begcsname",
+ --
+ "strippedcsname","checkedstrippedcsname",
+ --
+ "firstargumentfalse", "firstargumenttrue",
+ "secondargumentfalse", "secondargumenttrue",
+ "thirdargumentfalse", "thirdargumenttrue",
+ "fourthargumentfalse", "fourthargumenttrue",
+ "fifthargumentfalse", "fifthsargumenttrue",
+ "sixthargumentfalse", "sixtsargumenttrue",
+ --
+ "doglobal", "dodoglobal", "redoglobal", "resetglobal",
+ --
+ "donothing", "dontcomplain", "forgetall",
+ --
+ "donetrue", "donefalse", "foundtrue", "foundfalse",
+ --
+ "inlineordisplaymath","indisplaymath","forcedisplaymath","startforceddisplaymath","stopforceddisplaymath","reqno",
+ --
+ "mathortext",
+ --
+ "htdp",
+ "unvoidbox",
+ "hfilll", "vfilll",
+ --
+ "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha",
+ --
+ "currentcatcodetable", "defaultcatcodetable", "catcodetablename",
+ "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable",
+ "pushcatcodetable", "popcatcodetable", "restorecatcodes",
+ "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand",
+ --
+ "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg",
+ --
+ "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg",
+ "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg",
+ "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox",
+ "ruledhpack", "ruledvpack", "ruledtpack",
+ "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern",
+ "ruledhglue", "ruledvglue", "normalhglue", "normalvglue",
+ "ruledpenalty",
+ --
+ "filledhboxb", "filledhboxr", "filledhboxg", "filledhboxc", "filledhboxm", "filledhboxy", "filledhboxk",
+ --
+ "scratchcounter", "globalscratchcounter",
+ "scratchdimen", "globalscratchdimen",
+ "scratchskip", "globalscratchskip",
+ "scratchmuskip", "globalscratchmuskip",
+ "scratchtoks", "globalscratchtoks",
+ "scratchbox", "globalscratchbox",
+ --
+ "normalbaselineskip", "normallineskip", "normallineskiplimit",
+ --
+ "availablehsize", "localhsize", "setlocalhsize", "distributedhsize", "hsizefraction",
+ --
+ "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "flushnextbox",
+ --
+ "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance",
+ "scratchhsize", "scratchvsize",
+ "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset",
+ "scratchxposition", "scratchyposition",
+ "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset",
+ --
+ "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchcounterfour", "scratchcounterfive", "scratchcountersix",
+ "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchdimenfour", "scratchdimenfive", "scratchdimensix",
+ "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchskipfour", "scratchskipfive", "scratchskipsix",
+ "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchmuskipfour", "scratchmuskipfive", "scratchmuskipsix",
+ "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchtoksfour", "scratchtoksfive", "scratchtokssix",
+ "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchboxfour", "scratchboxfive", "scratchboxsix",
+ "scratchnx", "scratchny", "scratchmx", "scratchmy",
+ "scratchunicode",
+ "scratchmin", "scratchmax",
+ --
+ "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip",
+ --
+ "doif", "doifnot", "doifelse",
+ "doifinset", "doifnotinset",
+ "doifelseinset", "doifinsetelse",
+ "doifelsenextchar", "doifnextcharelse",
+ "doifelsenextoptional", "doifnextoptionalelse",
+ "doifelsenextoptionalcs", "doifnextoptionalcselse",
+ "doifelsefastoptionalcheck", "doiffastoptionalcheckelse",
+ "doifelsenextbgroup", "doifnextbgroupelse",
+ "doifelsenextbgroupcs", "doifnextbgroupcselse",
+ "doifelsenextparenthesis", "doifnextparenthesiselse",
+ "doifelseundefined", "doifundefinedelse",
+ "doifelsedefined", "doifdefinedelse",
+ "doifundefined", "doifdefined",
+ "doifelsevalue", "doifvalue", "doifnotvalue",
+ "doifnothing", "doifsomething",
+ "doifelsenothing", "doifnothingelse",
+ "doifelsesomething", "doifsomethingelse",
+ "doifvaluenothing", "doifvaluesomething",
+ "doifelsevaluenothing", "doifvaluenothingelse",
+ "doifelsedimension", "doifdimensionelse",
+ "doifelsenumber", "doifnumberelse", "doifnumber", "doifnotnumber",
+ "doifelsecommon", "doifcommonelse", "doifcommon", "doifnotcommon",
+ "doifinstring", "doifnotinstring", "doifelseinstring", "doifinstringelse",
+ "doifelseassignment", "doifassignmentelse", "docheckassignment",
+ --
+ "tracingall", "tracingnone", "loggingall",
+ --
+ "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to",
+ --
+ "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "nbsp",
+ "obeyspaces", "obeylines", "obeyedspace", "obeyedline", "obeyedtab", "obeyedpage",
+ "normalspace",
+ --
+ "executeifdefined",
+ --
+ "singleexpandafter", "doubleexpandafter", "tripleexpandafter",
+ --
+ "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces",
+ "removepunctuation",
+ --
+ "wait", "writestatus", "define", "defineexpandable", "redefine",
+ --
+ "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "measured",
+ --
+ "installcorenamespace",
+ --
+ "getvalue", "getuvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue",
+ "resetvalue", "undefinevalue", "ignorevalue",
+ "setuvalue", "setuevalue", "setugvalue", "setuxvalue",
+ --
+ "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "checked", "unique",
+ --
+ "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters",
+ --
+ "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter",
+ "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter",
+ --
+ "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist",
+ "processaction", "processallactions", "processfirstactioninset", "processallactionsinset",
+ --
+ "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect",
+ --
+ "firstofoneargument",
+ "firstoftwoarguments", "secondoftwoarguments",
+ "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments",
+ "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments",
+ "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments",
+ "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments",
+ --
+ "firstofoneunexpanded",
+ "firstoftwounexpanded", "secondoftwounexpanded",
+ "firstofthreeunexpanded", "secondofthreeunexpanded", "thirdofthreeunexpanded",
+ --
+ "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments",
+ "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals",
+ --
+ "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "dowith",
+ --
+ "newconstant", "setnewconstant", "setconstant", "setconstantvalue",
+ "newconditional", "settrue", "setfalse", "settruevalue", "setfalsevalue",
+ --
+ "newmacro", "setnewmacro", "newfraction",
+ "newsignal",
+ --
+ "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty",
+ "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument",
+ "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty",
+ "permitspacesbetweengroups", "dontpermitspacesbetweengroups",
+ --
+ "nopdfcompression", "maximumpdfcompression", "normalpdfcompression",
+ --
+ "modulonumber", "dividenumber",
+ --
+ "getfirstcharacter", "doifelsefirstchar", "doiffirstcharelse",
+ --
+ "startnointerference", "stopnointerference",
+ --
+ "twodigits","threedigits",
+ --
+ "leftorright",
+ --
+ "offinterlineskip", "oninterlineskip", "nointerlineskip",
+ --
+ "strut", "halfstrut", "quarterstrut", "depthstrut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight",
+ "leftboundary", "rightboundary", "signalcharacter",
+ --
+ "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing",
+ "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing",
+ --
+ "opordspacing", "opopspacing", "opbinspacing", "oprelspacing",
+ "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing",
+ --
+ "binordspacing", "binopspacing", "binbinspacing", "binrelspacing",
+ "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing",
+ --
+ "relordspacing", "relopspacing", "relbinspacing", "relrelspacing",
+ "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing",
+ --
+ "openordspacing", "openopspacing", "openbinspacing", "openrelspacing",
+ "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing",
+ --
+ "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing",
+ "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing",
+ --
+ "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing",
+ "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing",
+ --
+ "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing",
+ "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing",
+ --
+ "normalreqno",
+ --
+ "startimath", "stopimath", "normalstartimath", "normalstopimath",
+ "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath",
+ "normalsuperscript", "normalsubscript",
+ --
+ "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathsmallstylefont", "mathstyleface", "mathsmallstyleface", "mathstylecommand", "mathpalette",
+ "mathstylehbox", "mathstylevbox", "mathstylevcenter", "mathstylevcenteredhbox", "mathstylevcenteredvbox",
+ "mathtext", "setmathsmalltextbox", "setmathtextbox",
+ "pushmathstyle", "popmathstyle",
+ --
+ "triggerdisplaystyle", "triggertextstyle", "triggerscriptstyle", "triggerscriptscriptstyle",
+ "triggeruncrampedstyle", "triggercrampedstyle",
+ "triggersmallstyle", "triggeruncrampedsmallstyle", "triggercrampedsmallstyle",
+ "triggerbigstyle", "triggeruncrampedbigstyle", "triggercrampedbigstyle",
+ --
+ "luaexpr",
+ "expelsedoif", "expdoif", "expdoifnot",
+ "expdoifelsecommon", "expdoifcommonelse",
+ "expdoifelseinset", "expdoifinsetelse",
+ --
+ "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport",
+ "ctxlua", "luacode", "lateluacode", "directluacode",
+ "registerctxluafile", "ctxloadluafile",
+ "luaversion", "luamajorversion", "luaminorversion",
+ "ctxluacode", "luaconditional", "luaexpanded",
+ "startluaparameterset", "stopluaparameterset", "luaparameterset",
+ "definenamedlua",
+ "obeylualines", "obeyluatokens",
+ "startluacode", "stopluacode", "startlua", "stoplua",
+ "startctxfunction","stopctxfunction","ctxfunction",
+ "startctxfunctiondefinition","stopctxfunctiondefinition", "installctxfunction",
+ "cldprocessfile", "cldloadfile", "cldcontext", "cldcommand",
+ --
+ "carryoverpar",
+ --
+ "assumelongusagecs",
+ --
+ "Umathbotaccent",
+ --
+ "righttolefthbox", "lefttorighthbox", "righttoleftvbox", "lefttorightvbox", "righttoleftvtop", "lefttorightvtop",
+ "rtlhbox", "ltrhbox", "rtlvbox", "ltrvbox", "rtlvtop", "ltrvtop",
+ "autodirhbox", "autodirvbox", "autodirvtop",
+ "leftorrighthbox", "leftorrightvbox", "leftorrightvtop",
+ "lefttoright", "righttoleft","synchronizelayoutdirection","synchronizedisplaydirection","synchronizeinlinedirection",
+ --
+ "lesshyphens", "morehyphens", "nohyphens", "dohyphens",
+ --
+ "Ucheckedstartdisplaymath", "Ucheckedstopdisplaymath",
+ --
+ "break", "nobreak", "allowbreak", "goodbreak",
+ --
+ "nospace", "nospacing", "dospacing",
+ --
+ "naturalhbox", "naturalvbox", "naturalhpack", "naturalvpack",
+ --
+ "frule",
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-mes.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-mes.lua
new file mode 100644
index 00000000000..979831726eb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-mes.lua
@@ -0,0 +1,1777 @@
+if not modules then modules = { } end modules ['mult-mes'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+-- floatsblocks -> floats
+-- bodyfont -> fonts
+-- verbatims -> buffers
+
+-- check all interfaces.showmessage
+-- replace all writestatus (tricky as %'s in names, but we can support --)
+
+return {
+ formats = {
+ ["adapted: preamble %a, state %a, order %a"] = {
+ nl = "aangepast: preamble %a, status %a, volgorde %a",
+ },
+ ["already loaded: %a"] = {
+ nl = "al geladen: %a",
+ },
+ ["check:1"] = {
+ cs = "postradam '=' po %a na radku %a",
+ de = "Fehlendes '=' nach %a in Zeile %a",
+ en = "missing or ungrouped '=' after %a in line %a",
+ fr = "manquant ou dégroupé '=' après %a à la ligne %a",
+ it = "'=' mancante o non raggruppato dopo %a alla riga %a",
+ nl = "'=' ontbreekt of zonder {} na %a in regel %a",
+ no = "manglende '=' etter %a i linje %a",
+ ro = "lipseste '=' dupa %a in linia %a",
+ },
+ ["check:2"] = {
+ cs = "ocekavam %a argument(y) na radku %a",
+ de = "%a Argument(e) in Zeile %a erwartet",
+ en = "%a argument(s) expected in line %a",
+ fr = "%a argument(s) attendu(s) à la ligne %a",
+ it = "%a argomento/i attesi alla riga %a",
+ nl = "%a argument(en) verwacht in regel %a",
+ no = "%a argument forventet i linje %a",
+ ro = "argumentul(ele) %a sunt asteptate in linia %a",
+ },
+ ["check:3"] = {
+ cs = "%a %a nahrazuje makro, uzijte VERZALKY!",
+ de = "%a %a ersetzt ein Makro, verwende VERSALIEN!",
+ en = "%a %a replaces a macro, use CAPITALS!",
+ fr = "%a %a remplace une macro, utilisez des MAJUSCULES !",
+ it = "%a %a sostituisce una macro, usare le MAIUSCOLE!",
+ nl = "%a %a vervangt een macro, gebruik HOOFDLETTERS!",
+ no = "%a %a overskygger en makro, bruk STORE BOKSTAVER!",
+ ro = "%a %a inlocuieste un macro, folositi MAJUSCULE!",
+ },
+ ["checking file: %a"] = {
+ nl = "controleren file: %a",
+ },
+ ["checking url: %a"] = {
+ nl = "controleren url: %a",
+ },
+ ["colors:1"] = {
+ cs = "system %a je globalne aktivovana",
+ de = "system %a ist global aktiviert",
+ en = "system %a is global activated",
+ fr = "le système %a est globalement activé",
+ it = "sistema %a attivato globalmente",
+ nl = "systeem %a is globaal actief",
+ no = "system %a er aktivert globalt",
+ ro = "sistem %a este activata global",
+ },
+ ["colors:10"] = {
+ cs = "%a prostor barev je podporovan",
+ de = "%a Farbraum wird unterstuetzt",
+ en = "%a color space is supported",
+ fr = "%a l'espace de couleur est supporté",
+ it = "spazio dei colori %a supportato",
+ nl = "%a kleurruimte wordt ondersteund",
+ no = "%a fargerom er støttet",
+ ro = "spatiul de culoare %a este suportat",
+ },
+ ["colors:11"] = {
+ cs = "barva je prevedena na sed",
+ de = "Farbe wird in Grau umgewandelt",
+ en = "color is converted to gray",
+ fr = "la couleur est convertie en niveau de gris",
+ it = "il colore ø convertito in grigio",
+ nl = "kleur wordt vertaald in grijs",
+ no = "fargen vil bli vist som grø",
+ ro = "culoarea este convertita la gri",
+ },
+ ["colors:12"] = {
+ cs = "%a is registered",
+ de = "%a is registered",
+ en = "%a is registered",
+ fr = "%a est enregistré",
+ it = "%a is registered",
+ nl = "%a is geregistreerd",
+ no = "%a is registered",
+ ro = "%a is registered",
+ },
+ ["colors:2"] = {
+ cs = "system %a je lokalne activovana",
+ de = "system %a ist lokal aktiviert",
+ en = "system %a is local activated",
+ fr = "le système %a est localement activé",
+ it = "sistema %a attivato localmente",
+ nl = "systeem %a is lokaal actief",
+ no = "system %a er aktivert lokalt",
+ ro = "sistem %a este activata local",
+ },
+ ["colors:3"] = {
+ cs = "%a neni definovana %a",
+ de = "%a ist undefiniert %a",
+ en = "%a is not defined %a",
+ fr = "%a n'est pas défini %a",
+ it = "%a non definito %a",
+ nl = "%a is niet gedefinieerd %a",
+ no = "%a er udefinert %a",
+ ro = "%a nu este definita %a",
+ },
+ ["colors:4"] = {
+ cs = "system %a je nacten",
+ de = "system %a ist geladen",
+ en = "system %a is loaded",
+ fr = "le système %a est chargé",
+ it = "sistema %a caricato",
+ nl = "systeem %a wordt geladen",
+ no = "system %a er lest inn",
+ ro = "sistem %a este incarcata",
+ },
+ ["colors:5"] = {
+ cs = "neznamy system %a",
+ de = "unbekanntes System %a",
+ en = "unknown system %a",
+ fr = "système %a inconnu",
+ it = "sistema %a sconosciuto",
+ nl = "onbekend systeem %a",
+ no = "ukjent system %a",
+ ro = "sistem %a necunoscuta",
+ },
+ ["colors:6"] = {
+ cs = "palette %a je k dispozici",
+ de = "palette %a ist verfuegbar",
+ en = "palette %a is available",
+ fr = "la palette %a est disponible",
+ it = "tavolozza %a resa disponibile",
+ nl = "palet %a is beschikbaar",
+ no = "palett %a er tilgjengelig",
+ ro = "paleta %a este disponibila",
+ },
+ ["colors:7"] = {
+ cs = "palette %a neni k dispozici",
+ de = "palette %a ist nicht verfuegbar",
+ en = "palette %a is not available",
+ fr = "le palette %a n'est pas disponible",
+ it = "tavolozza %a non disponibile",
+ nl = "palet %a is niet beschikbaar",
+ no = "palett %a er ikke tilgjengelig",
+ ro = "palette %a nu este disponibila",
+ },
+ ["colors:8"] = {
+ cs = "specifikace %a v barve %a bude cerna",
+ de = "Spezifikation %a bei Farbe %a wird schwarz",
+ en = "specification %a at color %a becomes black",
+ fr = "la spécification %a de la couleur %a devient noire",
+ it = "specifica %a del colore %a convertita in nero",
+ nl = "specificatie %a bij %a wordt zwart",
+ no = "spesifikasjon %a for farge %a gir kun svart",
+ ro = "specificatia %a la culoarea %a devine neagra",
+ },
+ ["colors:9"] = {
+ cs = "%a prostor barev neni podporovan",
+ de = "%a Farbraum wird nicht unterstuetzt",
+ en = "%a color space is not supported",
+ fr = "l'espace de couleur %a n'est pas supporté",
+ it = "spazio dei colori %a non supportato",
+ nl = "%a kleurruimte wordt niet ondersteund",
+ no = "%a fargerom er ikke støttet",
+ ro = "spatiul de culoare %a nu este suportat",
+ },
+ ["columns:1"] = {
+ cs = "je mozno pouze %a sloupcu",
+ de = "nur %a Spalten moeglich",
+ en = "only %a columns possible",
+ fr = "seules %a colonnes possibles",
+ it = "solo %a colonne possibili",
+ nl = "maximaal %a kolommen",
+ no = "maksimalt %a kolonner",
+ ro = "este posibil numai %a coloane",
+ },
+ ["columns:10"] = {
+ cs = "zbyl (mene nez) 1 radek",
+ de = "(weniger als) 1 Zeile uebrig",
+ en = "(less than) 1 line left",
+ fr = "(moins de) 1 ligne restante",
+ it = "(meno di) una riga rimasta",
+ nl = "(minder dan) 1 regel over",
+ no = "(mindre enn) 1 linje igjen",
+ ro = "a mai ramas (mai putin de) 1 linie",
+ },
+ ["columns:11"] = {
+ cs = "plovouci objekt je pro sloupec prilis siroky",
+ de = "Gleitobjekt zu breit fuer Spalte",
+ en = "float too wide for column",
+ fr = "flottant mis à la largeur de la colonne",
+ it = "oggetto mobile troppo ampio per la colonna",
+ nl = "plaatsblok te breed voor kolom",
+ no = "flytblokk for bredt for kolonna",
+ ro = "blocul este prea lat pentru coloana",
+ },
+ ["columns:12"] = {
+ cs = "plovouci objekt je presunut do nasledujiciho sloupce / %a",
+ de = "Gleitobjekt in naechste Zeile verschoben / %a",
+ en = "float moved to next column / %a",
+ fr = "flottant déplacé à la colonne suivante / %a",
+ it = "oggetto mobile spostata alla colonna successiva / %a",
+ nl = "plaatsblok verplaatst naar volgende kolom / %a",
+ no = "flytblokk forskjøvet til neste kolonne / %a",
+ ro = "blocul este mutat pe urmatoarea coloana / %a",
+ },
+ ["columns:13"] = {
+ cs = "siroky plovouci objekt je presunut nad sloupce",
+ de = "breites Gleitobjekt an den Anfang der Spalten verschoben",
+ en = "wide float moved to top of columns",
+ fr = "flottant large déplacé dans la partie supérieure de la colonne",
+ it = "oggetto mobile ampio spostato sopra le colonne",
+ nl = "breed figuur geplaatst boven kolommen",
+ no = "bred flytblokk forksjøvet til toppen av kolonnene",
+ ro = "blocul lat este mutat in partea de sus a coloanelor",
+ },
+ ["columns:2"] = {
+ cs = "pouzijte \\string\\filbreak\\space jako alternativu",
+ de = "benutzte \\string\\filbreak\\space als Alternative",
+ en = "use \\string\\filbreak\\space as alternative",
+ fr = "utilisez \\string\\filbreak\\space en tant qu'alternative",
+ it = "in alternativa, usare \\string\\filbreak",
+ nl = "gebruik eventueel \\string\\filbreak",
+ no = "bruk \\string\\filbreak\\space som et alternativ",
+ ro = "folositi \\string\\filbreak\\space ca alternativa",
+ },
+ ["columns:3"] = {
+ cs = "problem, vypina se vyvazovani",
+ de = "Problem, verwende [ausgleich=nein]",
+ en = "problems, disable balancing",
+ fr = "problèmes, désactive l'équilibrage",
+ it = "problemi, disabilitare il bilanciamento",
+ nl = "probleempje, probeer [balanceren=nee]",
+ no = "problemer, slår av balansering",
+ ro = "probleme, se dezactiveaza alinierea",
+ },
+ ["columns:4"] = {
+ cs = "horni plovouci objekt jeste neni podporovan",
+ de = "Gleitobjekt oben ncoh nicht unterstuetzt",
+ en = "top float not yet supported",
+ fr = "flottant en partie supérieure pas encore supporté",
+ it = "float in cima non ancora supportato",
+ nl = "plaatsblok boven nog niet mogelijk",
+ no = "flytblokker øverst er ikke støttet enda",
+ ro = "cadrele top (top float) nu sunt inca suportate",
+ },
+ ["columns:5"] = {
+ cs = "spodni plovouci objekt jeste neni podporovan",
+ de = "Gleitobjekt unten ncoh nicht unterstuetzt",
+ en = "bottom float not yet supported",
+ fr = "flottant en partie inférieure pas encore supporté",
+ it = "float in fondo non ancora supportato",
+ nl = "plaatsblok onder nog niet mogelijk",
+ no = "flytblokker nedert er ikke støttet enda",
+ ro = "cadrele bottom (bottom float) nu sunt inca suportate",
+ },
+ ["columns:6"] = {
+ cs = "%a plovouci objekt(y) odlozeny",
+ de = "%a Gleitobjekt(e) verschoben",
+ en = "%a float(s) postponed",
+ fr = "%a flottant(s) reporté(s)",
+ it = "%a float(s) posticipate",
+ nl = "%a plaatsblok(en) opgeschort",
+ no = "%a flytblokk forskjøvet",
+ ro = "%a blocurile sunt amanate",
+ },
+ ["columns:7"] = {
+ cs = "vyvazovani ukonceno po 100 krocich",
+ de = "ausgleich nach 100 Schritten abgebrocheb",
+ en = "balancing aborted after 100 steps",
+ fr = "équilibrage abandonné après 100 pas",
+ it = "bilanciamento annullato dopo 100 passi",
+ nl = "balanceren afgebroken na 100 stappen",
+ no = "balansering avbrutt etter 100 iterasjoner",
+ ro = "alinierea este oprita dupa 100 de incercari",
+ },
+ ["columns:8"] = {
+ cs = "vyvazeno v %a krocich",
+ de = "ausgeglichen nach %a Schritt(en)",
+ en = "balanced in %a step(s)",
+ fr = "équilibré en %a pas",
+ it = "bilanciamento in %a passo/i",
+ nl = "gebalanceerd in %a stap(pen)",
+ no = "balansert etter %a iterasjoner",
+ ro = "aliniat in %a pas(i)",
+ },
+ ["columns:9"] = {
+ cs = "kontrola nerovnost",
+ de = "Ausrichtung ueberpruefen",
+ en = "check raggedness",
+ fr = "vérification des irrégularités",
+ it = "controllare seghettamento",
+ nl = "uitlijnen controleren!",
+ no = "kontroller tekstlayout!",
+ ro = "verificat alinierea",
+ },
+ ["databases:1"] = {
+ cs = "%a",
+ de = "%a",
+ en = "%a",
+ fr = "%a",
+ it = "%a",
+ nl = "%a",
+ no = "%a",
+ ro = "%a",
+ },
+ ["databases:2"] = {
+ cs = "local file %a",
+ de = "lokale Datei %a",
+ en = "local file %a",
+ fr = "fichier local %a",
+ it = "file locale %a",
+ nl = "lokaal bestand %a",
+ no = "lokal fil %a",
+ ro = "fisier local %a",
+ },
+ ["databases:3"] = {
+ cs = "global file %a",
+ de = "globale Datei %a",
+ en = "global file %a",
+ fr = "fichier global %a",
+ it = "file globale %a",
+ nl = "globaal bestand %a",
+ no = "global fil %a",
+ ro = "fisier global %a",
+ },
+ ["databases:4"] = {
+ cs = "unknown file %a",
+ de = "unbekannte Datei %a",
+ en = "unknown file %a",
+ fr = "fichier inconnu %a",
+ it = "file sconosciuto %a",
+ nl = "onbekend bestand %a",
+ no = "ukjent fil %a",
+ ro = "fisier necunoscut %a",
+ },
+ ["extended: preamble %a, state %a, order %a"] = {
+ nl = "uitgebreid: preamble %a, status %a, volgorde %a",
+ },
+ ["figures:1"] = {
+ cs = "obraz %a nelze nalezt",
+ de = "Abbildung %a kann nicht gefunden werden",
+ en = "figure %a can not be found",
+ fr = "la figure %a ne peut être trouvée",
+ it = "figura %a non trovata",
+ nl = "figuur %a is niet te vinden",
+ ro = "figura %a nu poate fi gasita",
+ },
+ ["figures:2"] = {
+ cs = "obraz %a nepritomen",
+ de = "Abbildung %a wird nicht erstellt",
+ en = "figure %a is not preset",
+ fr = "la figure %a n'est pas pré-sélectionnée",
+ it = "la figura %a non è preimpostata",
+ nl = "figuur %a wordt niet preset",
+ ro = "figura %a nu este presetata",
+ },
+ ["figures:3"] = {
+ cs = "dimensions of %a are determined externally",
+ de = "dimensions of %a are determined externally",
+ en = "dimensions of %a are determined externally",
+ fr = "dimensions of %a are determined externally",
+ it = "dimensions of %a are determined externally",
+ nl = "maten van %a worden extern vastgesteld",
+ ro = "dimensions of %a are determined externally",
+ },
+ ["figures:4"] = {
+ cs = "dimenze obrazu %a nacteny primo z jeho souboru",
+ de = "Dimensionen von %a geladen aus der Abbildungsdatei selbst",
+ en = "dimensions of %a loaded from figurefile itself",
+ fr = "les dimensions de %a chargées implicitement à partir du fichier de figure",
+ it = "dimensioni di %a caricate dal file di immagini stesso",
+ nl = "maten van %a geladen uit figuurfile zelf",
+ ro = "dimensiunea figurii %a se incarca din fisierul insusi",
+ },
+ ["figures:5"] = {
+ cs = "dimensions of %a are unknown",
+ de = "Dimensions of %a are unknown",
+ en = "dimensions of %a are unknown",
+ fr = "dimensions of %a are unknown",
+ it = "dimensions of %a are unknown",
+ nl = "maten van %a zijn onbekend",
+ ro = "dimensions of %a are unknown",
+ },
+ ["figures:6"] = {
+ cs = "dimenze obrazu %a spocteny programem rlxtools",
+ de = "Dimensionen von %a ausgerechnet durch rlxtools",
+ en = "dimensions of %a calculated by rlxtools",
+ fr = "les dimensions de %a calculées par rlxtools",
+ it = "dimensioni di %a calcolate da rlxtools",
+ nl = "maten van %a berekend door rlxtools",
+ ro = "dimensiunea figurii %a este calculata de rlxtools",
+ },
+ ["figures:8"] = {
+ cs = "obrazovy objekt %a je znovu pouzit",
+ de = "Abbildungobjekt %a wurde wiederverwandt",
+ en = "figureobject %a is reused",
+ fr = "figureobject %a est réutilisé",
+ it = "oggetto-figura %a riutilizzato",
+ nl = "figuurobject %a wordt opnieuw gebruikt",
+ ro = "obiectul figura %a este refolosit",
+ },
+ ["files:1"] = {
+ cs = "synonymum souboru %a je jiz pouzito pro %a",
+ de = "Dateisynonym %a wird bereits fuer %a benutzt",
+ en = "file synonym %a is already used for %a",
+ fr = "le synonyme de fichier %a est déjà utilisé pour %a",
+ it = "sinonimo file %a già in uso per %a",
+ nl = "file synoniem %a is al in gebruik voor %a",
+ no = "filesynonym %a er allerede brukt for %a",
+ ro = "sinonimul fisierelor %a este folosit deja pentru %a",
+ },
+ ["filters:1"] = {
+ cs = "filter %a is loaded",
+ de = "filter %a ist geladen",
+ en = "filter %a is loaded",
+ fr = "le filtre %a est chargé",
+ it = "filtro %a caricato",
+ nl = "filter %a wordt geladen",
+ },
+ ["filters:2"] = {
+ cs = "unknown filter %a",
+ de = "unknown filter %a",
+ en = "unknown filter %a",
+ fr = "filtre %a inconnu",
+ it = "filtro sconosciuto %a",
+ nl = "onbekend filter %a",
+ },
+ ["floatblocks:1"] = {
+ cs = "%a precislovano / %a => %a",
+ de = "%a neu nummeriert / %a => %a",
+ en = "%a renumbered / %a => %a",
+ fr = "%a renuméroté / %a => %a",
+ it = "%a rinumerato / %a => %a",
+ nl = "%a hernummerd / %a => %a",
+ no = "%a renummerert / %a => %a",
+ ro = "%a renumerotat / %a => %a",
+ },
+ ["floatblocks:10"] = {
+ cs = "%a omezeno",
+ de = "%a begrenzt",
+ en = "%a limited",
+ fr = "%a limité",
+ it = "%a limitato",
+ nl = "%a begrensd",
+ no = "%a begrenset",
+ ro = "%a limitat",
+ },
+ ["floatblocks:11"] = {
+ cs = "nedan zadny blok",
+ de = "kein Block gegeben",
+ en = "no block given",
+ fr = "pas de bloc donné",
+ it = "nessun oggetto specificato",
+ nl = "geen blok opgegeven",
+ no = "ingen blokk oppgitt",
+ ro = "nu este dat nici un bloc",
+ },
+ ["floatblocks:12"] = {
+ cs = "nedefinovano",
+ de = "undefiniert",
+ en = "undefined",
+ fr = "indéfini",
+ it = "non definito",
+ nl = "niet gedefinieerd",
+ no = "udefinert",
+ ro = "nedefinit",
+ },
+ ["floatblocks:13"] = {
+ cs = "there is nothing to split",
+ de = "there is nothing to split",
+ en = "there is nothing to split",
+ fr = "there is nothing to split",
+ it = "there is nothing to split",
+ nl = "er is niets te splitsen",
+ no = "there is nothing to split",
+ ro = "there is nothing to split",
+ },
+ ["floatblocks:1"] = {
+ en = "%a is empty",
+ },
+ ["floatblocks:2"] = {
+ cs = "%a ulozeno",
+ de = "%a gespeichert",
+ en = "%a saved",
+ fr = "%a sauvegardé",
+ it = "%a salvato",
+ nl = "%a bewaard",
+ no = "%a lagret",
+ ro = "%a salvat",
+ },
+ ["floatblocks:3"] = {
+ cs = "%a presunuto",
+ de = "%a verschoben",
+ en = "%a moved",
+ fr = "%a déplacé",
+ it = "%a mosso",
+ nl = "%a verplaatst",
+ no = "%a flyttet",
+ ro = "%a mutat",
+ },
+ ["floatblocks:4"] = {
+ cs = "%a umisteno",
+ de = "%a plaziert",
+ en = "%a placed",
+ fr = "%a placé",
+ it = "%a sistemato",
+ nl = "%a geplaatst",
+ no = "%a plassert",
+ ro = "%a plasat",
+ },
+ ["floatblocks:5"] = {
+ cs = "poradi prizpusobeno",
+ de = "Reihenfolge angepasst",
+ en = "order adapted",
+ fr = "ordre adapté",
+ it = "ordine aggiustato",
+ nl = "volgorde aangepast",
+ no = "rekkefølge tilpasset",
+ ro = "ordinea adaptata",
+ },
+ ["floatblocks:6"] = {
+ cs = "pocet hornich plovoucich objektu je omezen na %a",
+ de = "Anz. der oberen Gleitobjekte beschraengt auf %a",
+ en = "n of top floats limited to %a",
+ fr = "n flottants de haut de page limité à %a",
+ it = "n di top floats limitato a %a",
+ nl = "maximaal %a boven",
+ no = "maksimalt %a flytblokker øverst",
+ ro = "nr. cadrelor de sus limitat la %a",
+ },
+ ["floatblocks:7"] = {
+ cs = "pocet spodnich plovoucich objektu je omezen na %a",
+ de = "Anz. der unteren Gleitobjekte beschraengt auf %a",
+ en = "n of bottom floats limited to %a",
+ fr = "n flottants de bas de page limité à %a",
+ it = "n di bottom floats limitato a %a",
+ nl = "maximaal %a onder",
+ no = "maksimalt %a flytblokker nederst",
+ ro = "nr. blocurilor de jos limitat la %a",
+ },
+ ["floatblocks:8"] = {
+ cs = "radku je mene nez %a",
+ de = "weniger als %a zeilen",
+ en = "less than %a lines",
+ fr = "moins de %a lignes",
+ it = "meno di %a righe",
+ nl = "minder dan %a regels",
+ no = "mindre enn %a linjer",
+ ro = "mai putin de %a linii",
+ },
+ ["floatblocks:9"] = {
+ cs = "poradi naruseno",
+ de = "Reigenfolge gestoert",
+ en = "order disturbed",
+ fr = "ordre perturbé",
+ it = "ordine disturbato",
+ nl = "volgorde verstoord",
+ no = "rekkefølge endret",
+ ro = "ordinea deranjata",
+ },
+ ["flushed: preamble %a"] = {
+ nl = "weggeschreven: preamble %a",
+ },
+ ["fonts:1"] = {
+ cs = "kodovani %a",
+ de = "Kodierung %a",
+ en = "coding %a",
+ fr = "encodage %a",
+ it = "codifica %a",
+ nl = "codering %a",
+ no = "koding %a",
+ ro = "codificarea %a",
+ },
+ ["fonts:10"] = {
+ cs = "neznamy font %a",
+ de = "unbekanntes Font %a",
+ en = "unknown font file %a",
+ fr = "fichier de police %a inconnu",
+ it = "file di font sconosciuto %a",
+ nl = "onbekende font file %a",
+ no = "ukjent fontfil %a",
+ ro = "fisier font necunoscut %a",
+ },
+ ["fonts:14"] = {
+ cs = "bodyfont %a is defined (can better be done global)",
+ de = "Fliesstext %a wurde definiert (besser waere globale Definition)",
+ en = "bodyfont %a is defined (can better be done global)",
+ fr = "policecorps %a est défini (une définition globale pourrait être plus adéquat)",
+ it = "corpo del testo %a definito (sarebbe meglio globale)",
+ nl = "korps %a is gedefinieerd (kan beter globaal plaatsvinden)",
+ no = "bodyfont %a is defined (can better be done global)",
+ ro = "bodyfont %a is defined (can better be done global)",
+ },
+ ["fonts:2"] = {
+ cs = "varianta %a je nactena",
+ de = "Variante %a ist geladen",
+ en = "variant %a is loaded",
+ fr = "la variante %a est chargée",
+ it = "variante %a caricata",
+ nl = "variant %a wordt geladen",
+ no = "variant %a er lest inn",
+ ro = "varianta %a este incarcata",
+ },
+ ["fonts:3"] = {
+ cs = "neznama varianta %a",
+ de = "Unbekannte Variante %a",
+ en = "unknown variant %a",
+ fr = "variante %a inconnue",
+ it = "variante sconosciuta %a",
+ nl = "onbekende variant %a",
+ no = "ukjent variant %a",
+ ro = "varianta necunoscuta %a",
+ },
+ ["fonts:4"] = {
+ cs = "zakladni font %a neni definovan",
+ de = "Fliesstext %a ist nicht definiert",
+ en = "bodyfont %a is not defined",
+ fr = "policecorps %a n'est pas définie",
+ it = "corpo del testo %a non definito",
+ nl = "korps %a is niet gedefinieerd",
+ no = "hovedfont %a er ikke definert",
+ ro = "corpul de litere %a nu este definit",
+ },
+ ["fonts:5"] = {
+ cs = "styl %a neni definovan",
+ de = "Stil %a ist nicht definiert",
+ en = "style %a is not defined",
+ fr = "le style %a n'est pas défini",
+ it = "stile %a non definito",
+ nl = "stijl %a is niet gedefinieerd",
+ no = "stil %a er ikke definert",
+ ro = "stilul %a nu este definit",
+ },
+ ["fonts:6"] = {
+ cs = "%a je nacten",
+ de = "%a ist geladen",
+ en = "%a is loaded",
+ fr = "%a est chargé",
+ it = "%a caricato",
+ nl = "%a wordt geladen",
+ no = "%a er lest inn",
+ ro = "%a este incarcat",
+ },
+ ["fonts:7"] = {
+ cs = "neznamy format %a",
+ de = "unbekanntes Format %a",
+ en = "unknown format %a",
+ fr = "format %a inconnu",
+ it = "formato sconosciuto %a",
+ nl = "onbekend formaat %a",
+ no = "ukjent format %a",
+ ro = "format necunoscut %a",
+ },
+ ["fonts:8"] = {
+ cs = "styl %a definovan",
+ de = "Stil %a definiert",
+ en = "style %a defined",
+ fr = "style %a défini",
+ it = "stile %a definito",
+ nl = "stijl %a gedefinieerd",
+ no = "stil %a definert",
+ ro = "stilul %a definit",
+ },
+ ["interactions:1"] = {
+ cs = "pomer %a x %a (s x v)",
+ de = "Seitenverhaeltnis %a x %a (B x H)",
+ en = "aspect ratio %a x %a (b x h)",
+ fr = "ratio d'aspect %a x %a (b x h)",
+ it = "rapporto %a x %a (b x a)",
+ nl = "aspect ratio %a x %a (b x h)",
+ no = "forholdstall %a x %a (b x h)",
+ ro = "aspectul %a x %a (b x h)",
+ },
+ ["interactions:2"] = {
+ cs = "aktivni",
+ de = "aktiv",
+ en = "active",
+ fr = "actif",
+ it = "attiva",
+ nl = "actief",
+ no = "aktiv",
+ ro = "activ",
+ },
+ ["interactions:21"] = {
+ cs = "%a kod vlozen",
+ de = "%a Code eingefuegt",
+ en = "%a code inserted",
+ fr = "%a code inseré",
+ it = "codice %a inserito",
+ nl = "%a code tussengevoegd",
+ no = "%a kode satt inn / tilføyd",
+ ro = "%a cod inserat",
+ },
+ ["interactions:3"] = {
+ cs = "neaktivni",
+ de = "inaktiv",
+ en = "inactive",
+ fr = "inactif",
+ it = "inattiva",
+ nl = "niet actief",
+ no = "inaktiv",
+ ro = "inactiv",
+ },
+ ["interactions:4"] = {
+ cs = "zadna strankova synchronizace (%a) v hmode",
+ de = "keine Seitensynchronisation (%a) im hmode",
+ en = "no pagesynchronisation (%a) in hmode",
+ fr = "pas de synchronisation de page (%a) dans le hmode",
+ it = "sincronizzazione di pagina (%a) non disponibile in hmode",
+ nl = "geen paginasynchronisatie (%a) in hmode",
+ no = "ingen sidesynkronisering (%a) i hmode",
+ ro = "nu exista sincronizare pt. pagini (%a) in hmode",
+ },
+ ["interactions:5"] = {
+ cs = "unknown attachment %a",
+ de = "unknown attachment %a",
+ en = "unknown attachment %a",
+ fr = "le fichier joint %a est inconnu",
+ it = "unknown attachment %a",
+ nl = "onbekend attachment %a",
+ no = "unknown attachment %a",
+ ro = "unknown attachment %a",
+ },
+ ["interactions:6"] = {
+ cs = "attachment file %a does not exist",
+ de = "attachment file %a does not exist",
+ en = "attachment file %a does not exist",
+ fr = "le fichier joint %a n'existe pas",
+ it = "attachment file %a does not exist",
+ nl = "attachment file %a bestaat niet",
+ no = "attachment file %a does not exist",
+ ro = "attachment file %a does not exist",
+ },
+ ["languages:1"] = {
+ cs = "vzory %a pro %a nacteny (n=%a,e=%a,m=%a)",
+ de = "Trennmuster %a fuer %a geladen (n=%a,e=%a,m=%a)",
+ en = "patterns %a for %a loaded (n=%a,e=%a,m=%a)",
+ fr = "les motifs %a pour %a sont chargés (n=%a,e=%a,m=%a)",
+ it = "schemi %a per %a caricati (n=%a,e=%a,m=%a)",
+ nl = "afbreekpatronen %a voor %a geladen (n=%a,e=%a,m=%a)",
+ no = "orddelingsmønster %a for %a er lest inn (n=%a,e=%a,m=%a)",
+ ro = "sablonul %a pentru %a s-a incarcat (n=%a,e=%a,m=%a)",
+ },
+ ["languages:10"] = {
+ cs = "vzory %a nacteny",
+ de = "Trennmuster %a geladen",
+ en = "patterns %a loaded",
+ fr = "motifs %a chargés",
+ it = "schemi %a caricati",
+ nl = "patronen %ageladen",
+ no = "orddelingsmønster %a er lest inn",
+ ro = "sabloanele %a incarcate",
+ },
+ ["languages:2"] = {
+ cs = "zadne vzory %a pro %a (n=%a,e=%a,m=%a) (%a,%a)",
+ de = "Keine Trennmuster %a fuer %a (n=%a,e=%a,m=%a) (%a,%a)",
+ en = "no patterns %a for %a (n=%a,e=%a,m=%a) (%a,%a)",
+ fr = "pas de motifs %a pour %a (n=%a,e=%a,m=%a) (%a,%a)",
+ it = "niente schemi %a per %a (n=%a,e=%a,m=%a) (%a,%a)",
+ nl = "geen afbreekpatronen %a voor %a (n=%a,e=%a,m=%a) (%a,%a)",
+ no = "ingen orddelingsmønster %a for %a (n=%a,e=%a,m=%a) (%a,%a)",
+ ro = "nu exista sabloane %a pentru %a (n=%a,e=%a,m=%a) (%a,%a)",
+ },
+ ["languages:3"] = {
+ cs = "deleni slov %a pro %a nacteno (n=%a,e=%a,m=%a)",
+ de = "Trenndefinitionen %a fuer %a geladen (n=%a,e=%a,m=%a)",
+ en = "hyphenations %a for %a loaded (n=%a,e=%a,m=%a)",
+ fr = "hyphenations %a pour %a chargés (n=%a,e=%a,m=%a)",
+ it = "sillabazione %a per %a caricata (n=%a,e=%a,m=%a)",
+ nl = "afbreekdefinities %a voor %a geladen (n=%a,e=%a,m=%a)",
+ no = "orddelingsdefinisjon %a for %a er lest inn (n=%a,e=%a,m=%a)",
+ ro = "despartirea in silabe %a pentru %a s-a incarcat (n=%a,e=%a,m=%a)",
+ },
+ ["languages:4"] = {
+ cs = "zadne deleni slov %a pro %a (n=%a,e=%a,m=%a)",
+ de = "Keine Trenndefinitionen %a fuer %a (n=%a,e=%a,m=%a)",
+ en = "no hyphenations %a for %a (n=%a,e=%a,m=%a)",
+ fr = "pas d'hyphenations %a pour %a (n=%a,e=%a,m=%a)",
+ it = "niente sillabazione %a per %a (n=%a,e=%a,m=%a)",
+ nl = "geen afbreekdefinities %a voor %a (n=%a,e=%a,m=%a)",
+ no = "ingen orddelingsdefinisjon %a for %a (n=%a,e=%a,m=%a)",
+ ro = "nu exista despartire in silabe %a pentru %a (n=%a,e=%a,m=%a)",
+ },
+ ["languages:5"] = {
+ cs = "vzory pro %a nenacteny",
+ de = "Trennmuster fuer %a nicht geladen",
+ en = "patterns for %a not loaded",
+ fr = "les motifs pour %a ne sont pas chargés",
+ it = "schemi per %a non caricati",
+ nl = "afbreekpatronen voor %a niet geladen",
+ no = "orddelingsmønster for %a er ikke lest inn",
+ ro = "sabloanele pentru %a nu sunt incarcate",
+ },
+ ["languages:6"] = {
+ cs = "jazyk %a neni definovan",
+ de = "Sprache %a ist undefiniert",
+ en = "language %a is undefined",
+ fr = "langue %a non définie",
+ it = "lingua %a non definita",
+ nl = "taal %a is niet gedefinieerd",
+ no = "spràk %a er udefinert",
+ ro = "limba %a nu este definita",
+ },
+ ["languages:7"] = {
+ cs = "specificke volby jazyka [%a] zavadeji %a (zavlecenou) mezeru",
+ de = "Sprachenspezifische Option [%a] fuegt eine Luecke von %a ein",
+ en = "language specific options [%a] introduce a %a skip",
+ fr = "les options spécifiques de langue [%a] introduisent un %a saut",
+ it = "opzioni specifiche per la lingua [%a] introducono un salto %a",
+ nl = "taal specifieke opties [%a] introduceren een skip van %a",
+ no = "spràk spesifikk opsjon [%a] introduserer et %a hopp",
+ ro = "optiunile specifice ale limbii [%a] introduc un spatiu %a",
+ },
+ ["languages:8"] = {
+ cs = "specificke volby jazyka [%a] bez mezer pripojeny",
+ de = "Sprachenspezifische Option [%a] nahtlos hinzugefuegt",
+ en = "language specific options [%a] seamless appended",
+ fr = "les options spécifiques de langue [%a] sont ajoutés en douceur",
+ it = "opzioni specifiche per la lingua [%a] aggiunte trasparentemente",
+ nl = "taal specifieke opties [%a] naadloos toegevoegd",
+ no = "spràk spesifikk opsjon [%a] problemfritt tilføyd",
+ ro = "optiunile specifice ale limbii [%a] adaugate",
+ },
+ ["languages:9"] = {
+ cs = "language %a is active",
+ de = "Sprache %a ist aktiv",
+ en = "language %a is active",
+ fr = "la langue %a est active",
+ it = "lingua %a attiva",
+ nl = "taal %a is actief",
+ no = "spràk %a er aktivt",
+ ro = "limba %a este activa",
+ },
+ ["layouts:1"] = {
+ cs = "vyska textu prizpusobena s %a na strane %a",
+ de = "Texthoehe angepasst mit %a auf Seite %a",
+ en = "textheight adapted with %a at page %a",
+ fr = "hauteurtexte adaptée avec %a à la page %a",
+ it = "altezza del testo adattata con %a a pagina %a",
+ nl = "teksthoogte aangepast met %a op pagina %a",
+ no = "teksthøyde tilpasset med %a på side %a",
+ ro = "textheight adaptat cu %a la pagina %a",
+ },
+ ["layouts:10"] = {
+ cs = "%a a %a nedava dohromady 1.0",
+ de = "%a und %a ergeben zusammen nicht 1.0",
+ en = "%a and %a don't add up to 1.0",
+ fr = "%a et %a ne sont pas ajoutés à 1.0",
+ it = "%a e %a non sommano a 1.0",
+ nl = "%a en %a tellen niet op tot 1.0",
+ no = "%a og %a er ikke 1.0 til sammen",
+ ro = "%a si %a nu se adauga pana la 1.0",
+ },
+ ["layouts:11"] = {
+ cs = "svisla mezera %a neni povolena v pevnem radkovem rejstriku",
+ de = "Zwischenraum %a nicht im Grittermoduserlau",
+ en = "spacing %a not permitted in gridmode",
+ fr = "espacement %a non permis en modegrille",
+ it = "spaziatura %a non permessa in modo griglia",
+ nl = "interlinie %a niet toegestaan in gridmode",
+ no = "mellomrom %a ikke tillatt i gridmodus",
+ ro = "spatierea %a nu este permisa in gridmode",
+ },
+ ["layouts:2"] = {
+ cs = "%a krat odlozeny text umisten",
+ de = "%a mal verschobener Text plaziert",
+ en = "%a times postponed text placed",
+ fr = "%a times postponed text placed",
+ it = "posizionato testo posticipato %a volte",
+ nl = "%a maal uitgestelde tekst tussengevoegd",
+ no = "%a ganger forskjøvet tekst plassert",
+ ro = "textul amanat de %a ori a fost plasat",
+ },
+ ["layouts:3"] = {
+ cs = "%a krat text odlozen",
+ de = "%a mal Text verschoben",
+ en = "%a times text postponed",
+ fr = "%a times text postponed",
+ it = "testo posticipato %a volte",
+ nl = "%a maal tekst plaatsen uitstellen",
+ no = "%a ganger tekst forskjøvet",
+ ro = "textul amanat de %a ori",
+ },
+ ["layouts:4"] = {
+ cs = "okrajove bloky aktivni",
+ de = "marginalbloecke aktiv",
+ en = "marginblocks active",
+ fr = "blocsmarge actifs",
+ it = "blocchi in margine attivi",
+ nl = "margeblokken actief",
+ no = "margblokker aktive",
+ ro = "blocuri marginale active",
+ },
+ ["layouts:5"] = {
+ cs = "okrajove bloky neaktivni",
+ de = "marginalbloecke inaktiv",
+ en = "marginblocks inactive",
+ fr = "blocsmarge inactifs",
+ it = "blocchi in margine inattivi",
+ nl = "margeblokken inactief",
+ no = "margblokker inaktive",
+ ro = "blocuri marginale inactive",
+ },
+ ["layouts:6"] = {
+ cs = "sada stran %a zpracovana (velikost %a)",
+ de = "Unterseitenfolge %a verarbeitet (Groesse %a)",
+ en = "subpage set %a processed (size %a)",
+ fr = "jeu de souspage %a traité (taille %a)",
+ it = "gruppo di sottopagine %a elaborato (dimensione %a)",
+ nl = "subpagina reeks %a verwerkt (aantal %a)",
+ no = "delside sett %a behandlet (størrelse %a)",
+ ro = "setul %a de subpagini procesat (dimensiunea %a)",
+ },
+ ["layouts:7"] = {
+ cs = "pocita se misto pro logo",
+ de = "berechne Platzbedarf des Logos",
+ en = "calculating logospace",
+ fr = "calcul de l'espace pour le logo",
+ it = "calcolo dello spazio per logo",
+ nl = "beeldmerken berekenen",
+ no = "beregner plass for logo",
+ ro = "se calculeaza spatiul pentru logo",
+ },
+ ["layouts:8"] = {
+ cs = "pocita se pozadi",
+ de = "berechne Hintergrund",
+ en = "calculating backgrounds",
+ fr = "calcul des arrières-plans",
+ it = "calcolo dello sfondo",
+ nl = "achtergronden berekenen",
+ no = "beregner bakgrunn",
+ ro = "se calculeaza fundalurile",
+ },
+ ["layouts:9"] = {
+ cs = "aktualne ne vice nez %a urovne/urovni vyctu",
+ de = "z.Z. nicht mehr als %a Ebenen in Aufzaehlungen",
+ en = "currently no more than %a levels in itemizations",
+ fr = "pas plus de %a niveaux pour l'instant dans les élémentarisations",
+ it = "attualmente non più di %a livelli di elencazione",
+ nl = "momenteel maximaal %a niveaus in opsommingen",
+ no = "for øyeblikket maksimalt %a nivåer i opplisting",
+ ro = "acum nu se supota mai mult de %a nivele de adancime la iteratii",
+ },
+ ["loaded: %a"] = {
+ nl = "geladen: %a",
+ },
+ ["loaded: library %a"] = {
+ nl = "geladen: bibliotheek %a",
+ },
+ ["loading: %a"] = {
+ nl = "laden: %a",
+ },
+ ["locating: %a"] = {
+ nl = "zoeken: %a",
+ },
+ ["not found: %a"] = {
+ nl = "niet gevonden: %a",
+ },
+ ["number 1: %a, number 2: %a"] = {
+ en = "number 1: (%a), number 2: (%a)",
+ nl = "nummer 1: (%a), nummer 2: (%a)",
+ },
+ ["popping level: %a"] = {
+ nl = "niveau omlaag: %a",
+ },
+ ["publications:1"] = {
+ en = "file %a not found, unknown style ignored",
+ },
+ ["publications:2"] = {
+ en = "file %a not found, waiting for bibtex",
+ },
+ ["publications:3"] = {
+ en = "wrote a new auxiliary file %a",
+ },
+ ["publications:4"] = {
+ en = "loading database from %a",
+ },
+ ["publications:5"] = {
+ en = "warning: unknown cite argument %a on line %a",
+ },
+ ["publications:6"] = {
+ en = "loading formatting style from %a",
+ },
+ ["publications:7"] = {
+ en = "placing all entries, use 'text' to be more selective",
+ },
+ ["publications:10"] = {
+ en = "unknown command %a, using built-in context variant %a",
+ },
+ ["publications:11"] = {
+ en = "unknown command %a",
+ },
+ ["publications:12"] = {
+ en = "missing setup: %s",
+ },
+ ["publications:13"] = {
+ en = "no field %a for tag %a in dataset %a",
+ },
+ ["publications:14"] = {
+ en = "unknown rendering alternative %a",
+ },
+ ["pushing level: %a"] = {
+ nl = "niveau omhoog: %a",
+ },
+ ["references:1"] = {
+ cs = "neznama reference %a",
+ de = "unbekannte Referenz %a",
+ en = "unknown reference %a",
+ fr = "réference %a inconnue",
+ it = "riferimento sconosciuto %a",
+ nl = "onbekende verwijzing %a",
+ no = "ukjent referanse %a",
+ ro = "referinta necunoscuta %a",
+ },
+ ["references:2"] = {
+ cs = "duplicitni reference %a na strane %a",
+ de = "doppelte Referenz %a auf Seite %a",
+ en = "duplicate reference %a on page %a",
+ fr = "réference %a dupliquée à la page %a",
+ it = "riferimento duplicato %a a pagina %a",
+ nl = "dubbele verwijzing %a op pagina %a",
+ no = "duplikat referanse %a pø side %a",
+ ro = "referinta duplicat %a la pagina %a",
+ },
+ ["references:21"] = {
+ cs = "dokument %a nacten",
+ de = "Dokument %a geladen",
+ en = "document %a loaded",
+ fr = "document %a chargé",
+ it = "documento %a caricato",
+ nl = "document %a geladen",
+ no = "dokument %a er lest inn",
+ ro = "documentul %a este incarcat",
+ },
+ ["references:22"] = {
+ cs = "dokument %a neni interaktivni",
+ de = "Dokument %a ist nicht aktiv",
+ en = "document %a is not interactive",
+ fr = "le document %a n'est pas interactif",
+ it = "il documento %a non ø interattivo",
+ nl = "document %a is niet interactief",
+ no = "dokument %a er ikke interaktivt",
+ ro = "documentul %a nu este interactiv",
+ },
+ ["references:23"] = {
+ cs = "obskurni (nejasna) reference %a (prefix=%a)",
+ de = "Obskure Referenz %a (Prefix=%a)",
+ en = "obscure reference %a (prefix=%a)",
+ fr = "reference %a indéterminé (préfixe=%a)",
+ it = "riferimento ambiguo %a (prefisso=%a)",
+ nl = "onduidelijke verwijzing %a (prefix=%a)",
+ no = "obskur referanse %a (Prefix=%a)",
+ ro = "referinta obscura %a (prefix=%a)",
+ },
+ ["references:24"] = {
+ en = "references from document %a are not exported",
+ },
+ ["references:25"] = {
+ en = "references from document %a are not imported (export again)",
+ },
+ ["references:26"] = {
+ en = "references from document %a are imported",
+ },
+ ["references:3"] = {
+ cs = "neznamy typ reference %a",
+ de = "unbekannte Referenz Typ %a",
+ en = "unknown reference type %a",
+ fr = "type %a de réference inconnu",
+ it = "riferimento di tipo sconosciuto %a",
+ nl = "type verwijzing %a onbekend",
+ no = "ukjent referansetype %a",
+ ro = "tip necunoscut de referinta %a",
+ },
+ ["references:30"] = {
+ cs = "neznamy objekt %a",
+ de = "unbekanntes Object %a",
+ en = "unknown object %a",
+ fr = "objet %a inconnu",
+ it = "oggetto sconosciuto %a",
+ nl = "onbekend object %a",
+ no = "ukjent objekt %a",
+ ro = "obiect necunoscut %a",
+ },
+ ["references:31"] = {
+ cs = "duplicitni object %a",
+ de = "doppeltes Object %a",
+ en = "duplicate object %a",
+ fr = "objet %a dupliqué",
+ it = "oggetto duplicato %a",
+ nl = "dubbel object %a",
+ no = "duplikat objekt %a",
+ ro = "obiect duplicat %a",
+ },
+ ["references:4"] = {
+ cs = "nedovolena reference %a",
+ de = "illegale Referenz %a",
+ en = "illegal reference %a",
+ fr = "réference %a inconnue",
+ it = "riferimento illecito %a",
+ nl = "verboden verwijzing %a",
+ no = "ulovlig referanse %a",
+ ro = "referinta eronata %a",
+ },
+ -- ["number of unknown references: %a"] = {
+ -- },
+ ["references:6"] = {
+ en = "number of illegal references: %a",
+ },
+ ["start: %a"] = {
+ },
+ ["stop: %a"] = {
+ },
+ ["stored: preamble %a, state %a, order %a"] = {
+ nl = "opgeslagen: preamble %a, status %a, volgorde %a",
+ },
+ ["structures:1"] = {
+ cs = "zacatek oddilu (sekce) %a",
+ de = "Begin des Abschnittsblocks %a",
+ en = "begin of sectionblock %a",
+ fr = "début de blocsection %a",
+ it = "inizio del blocco (sezione) %a",
+ nl = "begin van sectieblok %a",
+ no = "starten av blokk %a (seksjon)",
+ ro = "inceput de bloc sectiune %a",
+ },
+ ["structures:2"] = {
+ cs = "konec oddilu (sekce) %a",
+ de = "Ende des Abschnittsblocks %a",
+ en = "end of sectionblock %a",
+ fr = "fin de blocsection %a",
+ it = "fine del blocco (sezione) %a",
+ nl = "eind van sectieblok %a",
+ no = "slutten av blokk %a (seksjon)",
+ ro = "sfarsit de bloc sectiune %a",
+ },
+ ["symbols:1"] = {
+ cs = "nacita se soubor symbolu %a",
+ de = "Lade Symboldatei %a",
+ en = "loading symbolset %a",
+ fr = "chargement du jeu de symbole %a",
+ it = "caricamento gruppo di simboli %a",
+ nl = "symboolset %a wordt geladen",
+ no = "leser inn symbolsett %a",
+ ro = "se incarca setul de simboluri %a",
+ },
+ ["system:1"] = {
+ cs = "nacteni pomocneho souboru odlozeno (typemode)",
+ de = "Laden der Hilfsdatei aufgeschoben (Eingabe-Modus)",
+ en = "loading utility-file postponed (typemode)",
+ fr = "chargement de fichier utilitaire reporté (typemode)",
+ it = "caricamento dei file supplementari posticipato (typemode)",
+ nl = "laden hulpfile uitgesteld (typemode)",
+ no = "innlesning av hjelpefila utsatt (typemode)",
+ ro = "se incarca utilitarul-fisierul este amanat (typemode)",
+ },
+ ["system:10"] = {
+ cs = "nepouzivejte em v %a",
+ de = "Benutzte kein em in %a",
+ en = "don't use em in %a",
+ fr = "n'utilisez pas em dans %a",
+ it = "non usare em in %a",
+ nl = "gebruik geen em in %a",
+ no = "ikke bruk em i %a",
+ ro = "nu folositi em in %a",
+ },
+ ["system:11"] = {
+ cs = "vytvarim jednoduchy pomocny soubor",
+ de = "Erstelle einfache Hilfdatei",
+ en = "building simple util",
+ fr = "construction util simple",
+ it = "costruzione di un semplice supplemento",
+ nl = "aanmaken basale hulpfile",
+ no = "lager enkel hjelpefil",
+ ro = "se creeaza un utilitar simplu",
+ },
+ ["system:12"] = {
+ cs = "pomosny soubor neni setriden, pouzijte texutil",
+ de = "Die Hilfdatei ist nicht sortiert, verwende texutil",
+ en = "the utility-file is not sorted, use texutil",
+ fr = "le fichier utilitaire n'est pas trié, utilise texutil",
+ it = "file di supplemento non ordinato, usare texutil",
+ nl = "de hulpfile is niet gesorteerd, gebruik texutil",
+ no = "hjelpefila er ikke sortert, bruk texutil",
+ ro = "fisierul utilitar nu este sortat, folositi texutil",
+ },
+ ["system:13"] = {
+ cs = "znacka %a definovana %a",
+ de = "Beschriftung %a definiert %a",
+ en = "mark %a defined %a",
+ fr = "marquage %a defini %a",
+ it = "marcatura %a definita %a",
+ nl = "markering %a gedefinieerd %a",
+ no = "markering %a definert %a",
+ ro = "marcajul %a definit %a",
+ },
+ ["system:14"] = {
+ cs = "vynucena nova stranka v seznamu na %a",
+ de = "Erzwungendes Seitenumbruch in Liste bei %a",
+ en = "forced newpage in list at %a",
+ fr = "nouvellepage forcée dans la liste à %a",
+ it = "nuova pagina obbligata in lista a %a",
+ nl = "geforceerde paginaovergang in lijst voor %a",
+ no = "tvunget sideskift i liste ved %a",
+ ro = "s-a fortat trecere pa pagina noua in lista la %a",
+ },
+ ["system:15"] = {
+ cs = "uklada se buffer %a",
+ de = "Speichere Buffer %a",
+ en = "saving buffer %a",
+ fr = "sauvegarde du tampon (buffer) %a",
+ it = "salvataggio del buffer %a",
+ nl = "wegschrijven buffer %a",
+ no = "lagrer Buffer %a",
+ ro = "buffer salvat %a",
+ },
+ ["system:16"] = {
+ cs = "sazi se buffer %a",
+ de = "Setzte Buffer %a",
+ en = "typesetting buffer %a",
+ fr = "composition du tampon (buffer) %a",
+ it = "composizione del buffer %a",
+ nl = "inlezen buffer %a",
+ no = "tegnsetter buffer %a",
+ ro = "buffer-ul %a s-a cules",
+ },
+ ["system:17"] = {
+ cs = "sazi se doslovny (verbatim) buffer %a",
+ de = "Setzte tippen-Buffer %a",
+ en = "typesetting verbatim buffer %a",
+ fr = "composition textuelle du tampon (buffer) %a",
+ it = "composizione verbatim del buffer %a",
+ nl = "verbatim inlezen buffer %a",
+ no = "tegnsetter verbatim-buffer %a",
+ ro = "se culege buffer-ul verbatim %a",
+ },
+ ["system:18"] = {
+ cs = "synonymum %a %a neexistuje",
+ de = "Synonym %a %a existiert nicht",
+ en = "synonym %a %a does not exist",
+ fr = "le synonyme %a %a n'existe pas",
+ it = "sinonimo %a %a non esistente",
+ nl = "synoniem %a %a bestaat niet",
+ no = "synonym %a %a eksisterer ikke",
+ ro = "sinonimul %a %a nu exista",
+ },
+ ["system:19"] = {
+ cs = "vyznam (synonyma) %a nacten",
+ de = "Bedeutung (synonyme) von %a geladen",
+ en = "meaning (synonyms) of %a loaded",
+ fr = "signification (synonymes) de %a chargée",
+ it = "significato (sinonimi) di %a caricato",
+ nl = "betekenissen (synoniemen) van %a geladen",
+ no = "betydning (synonymer) av %a er lest inn",
+ ro = "intelesul (sinonimele) pentru %a incarcat",
+ },
+ ["system:2"] = {
+ cs = "%a nacteno",
+ de = "%a geladen",
+ en = "%a loaded",
+ fr = "%a chargé",
+ it = "%a caricato",
+ nl = "%a geladen",
+ no = "%a er lest inn",
+ ro = "%a s-a incarcat",
+ },
+ ["system:20"] = {
+ cs = "vyznam (trideni) %a nacten",
+ de = "Bedeutung (sortieren) von %a geladen",
+ en = "meaning (sorts) of %a loaded",
+ fr = "signification (tris) de %a chargée",
+ it = "significato (specie) di %a caricato",
+ nl = "betekenissen (sorteren) van %a geladen",
+ no = "betydning (sorterer) av %a er lest inn",
+ ro = "intelesul (ordinea) pentru %a incarcat",
+ },
+ ["system:21"] = {
+ cs = "pomocny soubor necten",
+ de = "Die Hilfsdatei ist nicht geladen",
+ en = "no utility data is loaded",
+ fr = "pas de données utilitaires chargées",
+ it = "nessuna informazione supplementare caricata",
+ nl = "de hulpfile is niet geladen",
+ no = "hjelpefila er ikke lest inn",
+ ro = "nici o data utilitara nu este incarcata",
+ },
+ ["system:22"] = {
+ cs = "pouzijte platny pomocny soubor",
+ de = "Benoetige gueltige Hilfsdateie",
+ en = "use a valid utilityfile",
+ fr = "utilise un fichier utilitaire valide",
+ it = "usare un file supplementare valido",
+ nl = "gebruik een goede hulpfile",
+ no = "bruk en gyldig hjelpefil",
+ ro = "folositi un fisier utilitar valid",
+ },
+ ["system:23"] = {
+ cs = "%a upraveno na %a",
+ de = "%a angeordnet auf %a",
+ en = "%a arranged at %a",
+ fr = "%a arrangé à %a",
+ it = "%a sistemato a %a",
+ nl = "%a gearrangeerd op %a",
+ no = "%a arrangert på %a",
+ ro = "%a aranjat la %a",
+ },
+ ["system:24"] = {
+ cs = "plovouci bloky",
+ de = "Fliessbloecke",
+ en = "Floatblocks",
+ fr = "blocsflottants",
+ it = "Oggetti mobili",
+ nl = "Plaatsblokken",
+ no = "Flytblokker",
+ ro = "Blocuri",
+ },
+ ["system:25"] = {
+ cs = "reference",
+ de = "Referenzen",
+ en = "References",
+ fr = "Réferences",
+ it = "Riferimenti",
+ nl = "Verwijzingen",
+ no = "Referanser",
+ ro = "Referinte",
+ },
+ ["system:26"] = {
+ cs = "registry",
+ de = "Register",
+ en = "Registers",
+ fr = "Registres",
+ it = "Registri",
+ nl = "Registers",
+ no = "Registere",
+ ro = "Registri",
+ },
+ ["system:27"] = {
+ cs = "verze",
+ de = "Version",
+ en = "Version",
+ fr = "Version",
+ it = "Versione",
+ nl = "Versie",
+ no = "Versjon",
+ ro = "Versiune",
+ },
+ ["system:4"] = {
+ cs = "prikaz %a je jiz definovan",
+ de = "Befehl %a ist bereits definiert",
+ en = "command %a is already defined",
+ fr = "la commande %a est déjà définie",
+ it = "comando %a già definito",
+ nl = "commando %a is al gedefinieerd",
+ no = "kommando %a er allerede definert",
+ ro = "comanda %a este deja definita",
+ },
+ ["system:41"] = {
+ cs = "externi soubor %a ve skupine %a neexistuje",
+ de = "Externe Datei %a in Gruppe %a existiert nicht",
+ en = "external file %a in group %a does not exist",
+ fr = "le fichier externe %a du groupe %a n'existe pas",
+ it = "il file esterno %a del gruppo %a non esiste",
+ nl = "externe file %a in groep %a bestaat niet",
+ no = "ekstern fil %a i gruppe %a eksisterer ikke",
+ ro = "fisierul extern %a din grupul %a nu exista",
+ },
+ ["system:5"] = {
+ cs = "makra z %a nactena",
+ de = "Modul %a geladen",
+ en = "module %a loaded",
+ fr = "module %a chargé",
+ it = "macro del modulo %a caricate",
+ nl = "module %a geladen",
+ no = "makroene i modul %a er lest inn",
+ ro = "macro-urile din modulul %a s-au incarcat",
+ },
+ ["system:6"] = {
+ cs = "zadna makra v %a nenalezena",
+ de = "Modul %a gefunden",
+ en = "module %a not found",
+ fr = "module %a non trouvé",
+ it = "nessuna macro trovata nel modulo %a",
+ nl = "geen module %a gevonden",
+ no = "ingen makroer funnet i modul %a-",
+ ro = "nu s-au gasit macro-uri in modulul %a",
+ },
+ ["system:7"] = {
+ cs = "makra z %a jsou jiz nactena",
+ de = "Modul %a bereits geladen",
+ en = "module %a already loaded",
+ fr = "module %a déjà chargé",
+ it = "macro del modulo %a già caricate",
+ nl = "module %a reeds geladen",
+ no = "makroene i modul %a er allerede lest inn",
+ ro = "macro-urile din modulul %a s-au incarcat deja",
+ },
+ ["system:8"] = {
+ cs = "nova verze pomocneho souboru, je treba druheho behu",
+ de = "Neue Version der Hilfsdatei, zweiter Durchlauf benoetigt",
+ en = "new version of utility file, second pass needed",
+ fr = "nouvelle version de fichier utilitaire, seconde passe nécessaire",
+ it = "nuova versione del file supplementare, seconda passata necessaria",
+ nl = "nieuwe versie hulpfile, tweede run nodig",
+ no = "ny versjon av hjelpefil, andre gjennomkjøring nødvendig",
+ ro = "o noua versiune de fisier utilitar, este necesara o noua trecere",
+ },
+ ["system:9"] = {
+ cs = "%a nenalezeno/nezpracovano",
+ de = "%a nicht gefunden/verarbeitet",
+ en = "%a not found/processed",
+ fr = "%a non trouvé/traité",
+ it = "%a non trovato/elaborato",
+ nl = "%a niet gevonden/geplaatst",
+ no = "%a ikke funnet/behandlet",
+ ro = "%a nu este gasit/procesat",
+ },
+ ["system:91"] = {
+ en = "papertray %a",
+ nl = "papierlade %a",
+ },
+ ["textblocks:1"] = {
+ cs = "nova verze, je treba druhy beh",
+ de = "neue Version, zweiter Durchlauf benoetigt",
+ en = "new version, second pass needed",
+ fr = "nouvelle version, une seconde passe est nécessaire",
+ it = "nuova versione, seconda passata necessaria",
+ nl = "nieuwe versie, tweede run nodig",
+ no = "ny versjon, andre gjennomkjøring nødvendig",
+ ro = "o noua versiune, este nevoie de inca o trecere",
+ },
+ ["textblocks:10"] = {
+ cs = "%a nacteno a zpracovano",
+ de = "%a geladen und verarbeitet",
+ en = "%a loaded and processed",
+ fr = "%a chargé et traité",
+ it = "%a caricato ed elaborato",
+ nl = "%a geladen en verwerkt",
+ no = "%a lest inn og behandlet",
+ ro = "%a incarcat si procesat",
+ },
+ ["textblocks:11"] = {
+ cs = "%a nacteno a vysazeno",
+ de = "%a geladen und gesetzt",
+ en = "%a loaded and typeset",
+ fr = "%a chargé et composé",
+ it = "%a caricato e composto",
+ nl = "%a geladen en geplaatst",
+ no = "%a lest inn og tegnsatt",
+ ro = "%a incarcat si cules",
+ },
+ ["textblocks:12"] = {
+ cs = "%a preskoceno",
+ de = "%a ausgelassen",
+ en = "%a skipped",
+ fr = "%a sauté",
+ it = "%a saltato",
+ nl = "%a overgeslagen",
+ no = "%a utelatt",
+ ro = "%a sarit peste",
+ },
+ ["textblocks:2"] = {
+ cs = "zapisuji bloky do %a",
+ de = "schreibe Bloecke zu %a",
+ en = "writing blocks to %a",
+ fr = "ecriture des blocs vers %a",
+ it = "scrittura dei blocchi su %a",
+ nl = "wegschrijven blokken naar %a",
+ no = "skriver blokker til %a",
+ ro = "se scriu blocurile in %a",
+ },
+ ["textblocks:3"] = {
+ cs = "ctu bloky z %a",
+ de = "lese Bloecke von %a",
+ en = "reading blocks from %a",
+ fr = "lecture des blocs en provenance de %a",
+ it = "lettura dei blocchi da %a",
+ nl = "inlezen blokken uit %a",
+ no = "leser blokker fra %a",
+ ro = "se citesc blocurile din %a",
+ },
+ ["textblocks:4"] = {
+ cs = "je treba druhy beh",
+ de = "zweiter Durchlauf benoetigt",
+ en = "second pass needed",
+ fr = "seconde passe nécessaire",
+ it = "seconda passata necessaria",
+ nl = "er is een tweede run nodig",
+ no = "andre gjennomkjøring nødvendig",
+ ro = "este nevoie de inca o trecere",
+ },
+ ["textblocks:5"] = {
+ cs = "%a neni skryto",
+ de = "%a nicht verborgen",
+ en = "%a not hidden",
+ fr = "%a non caché",
+ it = "%a non nascosto",
+ nl = "%a niet verborgen",
+ no = "%a ikke skjult",
+ ro = "%a nu este ascuns",
+ },
+ ["textblocks:6"] = {
+ cs = "%a skryto a zpracovano",
+ de = "%a verborgen und verarbeitet",
+ en = "%a hidden and processed",
+ fr = "%a caché et traité",
+ it = "%a nascosto ed elaborato",
+ nl = "%a verborgen en verwerkt",
+ no = "%a skjult og behandlet",
+ ro = "%a ascuns si procesat",
+ },
+ ["textblocks:7"] = {
+ cs = "%a skryto",
+ de = "%a verborgen",
+ en = "%a hidden",
+ fr = "%a caché",
+ it = "%a nascosto",
+ nl = "%a verborgen",
+ no = "%a skjult",
+ ro = "%a ascuns",
+ },
+ ["textblocks:8"] = {
+ cs = "%a vysazeno",
+ de = "%a gesetzt",
+ en = "%a typeset",
+ fr = "%a composé",
+ it = "%a composto",
+ nl = "%a gehandhaafd",
+ no = "%a tegnsatt",
+ ro = "%a cules",
+ },
+ ["textblocks:9"] = {
+ cs = "%a nevysazeno",
+ de = "%a nicht gesetzt",
+ en = "%a not typeset",
+ fr = "%a non composé",
+ it = "%a non composto",
+ nl = "%a niet gehandhaafd",
+ no = "%a ikke tegnsatt",
+ ro = "%a nu este cules",
+ },
+ ["unknown: library %a"] = {
+ nl = "onbekend: bibliotheek %a",
+ },
+ ["used: code %a"] = {
+ nl = "gebruikt: code %a",
+ },
+ ["used: code %a, preamble %a"] = {
+ nl = "gebruikt: code %a, preamble %a",
+ },
+ ["used: function %a"] = {
+ nl = "gebruikt: functie %a",
+ },
+ ["used: preamble %a, state %a, order %a"] = {
+ nl = "gebruikt: preamble %a, status %a, volgorde %a",
+ },
+ ["vector %a is loaded"] = {
+ nl = "vector %a is geladen",
+ },
+ ["vector %a is unknown"] = {
+ nl = "onbekende vector %a",
+ },
+ ["verbatims:1"] = {
+ cs = "soubor %a neexistuje",
+ de = "Datei %a existiert nicht",
+ en = "file %a does not exist",
+ fr = "le fichier %a n'existe pas",
+ it = "il file %a non esiste",
+ nl = "file %a bestaat niet",
+ no = "fil %a eksisterer ikke",
+ ro = "fisierul %a nu exista",
+ },
+ },
+ translations = {
+ check = {
+ cs = "kontrola",
+ de = "check",
+ en = "check",
+ fr = "vérification",
+ it = "controllo",
+ nl = "controle",
+ no = "kontroll",
+ ro = "verificari",
+ },
+ colors = {
+ cs = "barva",
+ de = "farbe",
+ en = "colors",
+ fr = "couleurs",
+ it = "colore",
+ nl = "kleuren",
+ no = "farge",
+ ro = "culori",
+ },
+ columns = {
+ cs = "sloupce",
+ de = "Spalten",
+ en = "columns",
+ fr = "colonnes",
+ it = "colonne",
+ nl = "kolommen",
+ no = "kolonner",
+ ro = "coloane",
+ },
+ databases = {
+ cs = "databases",
+ de = "Datenbank",
+ en = "databases",
+ fr = "bases de données",
+ it = "database",
+ nl = "database",
+ no = "databaser",
+ ro = "baze de date",
+ },
+ figures = {
+ cs = "obrazy",
+ de = "Abbildungen",
+ en = "figures",
+ fr = "figures",
+ it = "figure",
+ nl = "figuren",
+ ro = "figuri",
+ },
+ files = {
+ cs = "soubory",
+ de = "files",
+ en = "files",
+ fr = "fichiers",
+ it = "file",
+ nl = "files",
+ no = "filer",
+ ro = "fisiere",
+ },
+ filters = {
+ cs = "filters",
+ de = "filters",
+ en = "filters",
+ fr = "filtre",
+ it = "filtri",
+ nl = "filters",
+ },
+ floatblocks = {
+ cs = "plovouciobjekty",
+ de = "Gleitobjektbloecke",
+ en = "floatblocks",
+ fr = "blocs de flottants",
+ it = "oggetti mobili",
+ nl = "plaatsblokken",
+ no = "flytblokker",
+ ro = "Blocuri",
+ },
+ fonts = {
+ cs = "zakladnifont",
+ de = "Fliesstext",
+ en = "bodyfont",
+ fr = "corps de texte",
+ it = "font del corpo",
+ nl = "korps",
+ no = "hovedfont",
+ ro = "corp de litere",
+ },
+ interactions = {
+ cs = "interakce",
+ de = "Interaktions",
+ en = "interactions",
+ fr = "interactions",
+ it = "interazione",
+ nl = "interacties",
+ no = "interaksjon",
+ ro = "interactiuni",
+ },
+ languages = {
+ cs = "jazyky",
+ de = "Sprache",
+ en = "languages",
+ fr = "langue",
+ it = "lingua",
+ nl = "talen",
+ no = "sprøk",
+ ro = "limbi",
+ },
+ layouts = {
+ cs = "layouts",
+ de = "Layouts",
+ en = "layouts",
+ fr = "calque",
+ it = "layouts",
+ nl = "layouts",
+ no = "layouts",
+ ro = "aranjamente",
+ },
+ numbers = {
+ nl = "nummers",
+ },
+ publications = {
+ en = "publications",
+ },
+ references = {
+ cs = "reference",
+ de = "referenzen",
+ en = "references",
+ fr = "réferences",
+ it = "riferimenti",
+ nl = "verwijzingen",
+ no = "referanser",
+ ro = "referinte",
+ },
+ regimes = {
+ de = "Kodierungen",
+ fr = "encodages",
+ nl = "regimes",
+ },
+ structures = {
+ cs = "struktury",
+ de = "strukture",
+ en = "structures",
+ fr = "structures",
+ it = "struttura",
+ nl = "structuren",
+ no = "struktur",
+ ro = "structuri",
+ },
+ symbols = {
+ cs = "symboly",
+ de = "Symbole",
+ en = "symbols",
+ fr = "symboles",
+ it = "simboli",
+ nl = "symbolen",
+ no = "symboler",
+ ro = "simboluri",
+ },
+ system = {
+ cs = "system",
+ de = "system",
+ en = "system",
+ fr = "système",
+ it = "sistema",
+ nl = "systeem",
+ no = "system",
+ ro = "sistem",
+ },
+ textblocks = {
+ cs = "textovyblok",
+ de = "textblock",
+ en = "textblocks",
+ fr = "blocs de texte",
+ it = "blocchi di testo",
+ nl = "tekstblokken",
+ no = "tekstblokker",
+ ro = "blocuri de text",
+ },
+ verbatims = {
+ cs = "verbatim",
+ de = "verbatim",
+ en = "verbatim",
+ fr = "verbatim",
+ it = "verbatim",
+ nl = "typen",
+ no = "verbatim",
+ ro = "verbatim",
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-mps.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-mps.lua
new file mode 100644
index 00000000000..a6bebc26613
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-mps.lua
@@ -0,0 +1,162 @@
+return {
+ tex = {
+ "btex", "etex", "verbatimtex",
+ },
+ shortcuts = {
+ "..", "...", "--", "---", "&", "\\",
+ },
+ primitives = { -- to be checked
+ "charcode", "day", "linecap", "linejoin", "miterlimit", "month", "pausing",
+ "prologues", "showstopping", "time", "tracingcapsules", "tracingchoices", "mpprocset",
+ "tracingcommands", "tracingequations", "tracinglostchars",
+ "tracingmacros", "tracingonline", "tracingoutput", "tracingrestores",
+ "tracingspecs", "tracingstats", "tracingtitles", "truecorners",
+ "warningcheck", "year",
+ "false", "nullpicture", "pencircle", "true",
+ "and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot",
+ "char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize",
+ "hex", "infont", "intersectiontimes", "known", "length", "llcorner",
+ "lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not",
+ "numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point",
+ "postcontrol", "precontrol", "reverse", "rotated", "scaled",
+ "shifted", "sind", "slanted", "sqrt", "str", "string", "subpath", "substring",
+ "transform", "transformed", "ulcorner", "uniformdeviate", "unknown",
+ "urcorner", "xpart", "xscaled", "xxpart", "xypart", "ypart", "yscaled", "yxpart",
+ "yypart", "zscaled",
+ "addto", "clip", "input", "interim", "let", "newinternal", "save", "setbounds",
+ "shipout", "show", "showdependencies", "showtoken", "showvariable",
+ "special",
+ "begingroup", "endgroup", "of", "curl", "tension", "and", "controls",
+ "interpath", "on", "off",
+ "def", "vardef", "enddef", "expr", "suffix", "text", "primary", "secondary",
+ "tertiary", "primarydef", "secondarydef", "tertiarydef",
+ "randomseed", "also", "contour", "doublepath",
+ "withcolor", "withcmykcolor", "withpen",
+ "dashed",
+ "if", "else", "elseif", "fi", "for", "endfor", "forever", "exitif", "within",
+ "forsuffixes", "step", "until",
+ "charlist", "extensible", "fontdimen", "headerbyte", "kern", "ligtable",
+ "boundarychar", "chardp", "charext", "charht", "charic", "charwd", "designsize",
+ "fontmaking", "charexists",
+ "cullit", "currenttransform", "gfcorners", "grayfont", "hround",
+ "imagerules", "lowres_fix", "nodisplays", "notransforms", "openit",
+ "displaying", "currentwindow", "screen_rows", "screen_cols",
+ "pixels_per_inch", "cull", "display", "openwindow", "numspecial",
+ "totalweight", "autorounding", "fillin", "proofing", "tracingpens",
+ "xoffset", "chardx", "granularity", "smoothing", "turningcheck", "yoffset",
+ "chardy", "hppp", "tracingedges", "vppp",
+ "extra_beginfig", "extra_endfig", "mpxbreak",
+ "endinput",
+ "message", "delimiters", "turningnumber", "errmessage",
+ "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom",
+ "withprescript", "withpostscript",
+ "top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt",
+ --
+ "redpart", "greenpart", "bluepart",
+ "cyanpart", "magentapart", "yellowpart",
+ "blackpart",
+ "prescriptpart", "postscriptpart",
+ "rgbcolor", "cmykcolor", -- "greycolor", "graycolor",
+ "colormodel", "graypart", "greypart", "greycolor", "graycolor",
+ "dashpart", "penpart",
+-- "colorpart",
+ "stroked", "filled", "textual", "clipped", "bounded", "pathpart",
+ "expandafter",
+ "minute", "hour",
+ "outputformat", "outputtemplate", "filenametemplate", "fontmapfile", "fontmapline",
+ "fontpart", "fontsize", "glyph", "restoreclipcolor", "troffmode",
+ --
+ "runscript", "maketext",
+ },
+ commands = {
+ "upto", "downto",
+ "beginfig", "endfig",
+ "beginglyph", "endglyph", -- actually a mult-fun one
+ "rotatedaround", "reflectedabout",
+ "arrowhead",
+ "currentpen", "currentpicture", "cuttings",
+ "defaultfont", "extra_beginfig", "extra_endfig",
+ "ditto", "EOF", "down",
+ "evenly", "fullcircle", "halfcircle", "identity", "in", "left",
+ "pensquare", "penrazor", "penspec",
+ "origin", "quartercircle", "right",
+ "unitsquare", "up", "withdots",
+ "abs", "bbox", "ceiling", "center", "cutafter", "cutbefore", "dir",
+ "directionpoint", "div", "dotprod", "intersectionpoint", "inverse", "mod",
+ "round", "unitvector", "whatever",
+ "cutdraw", "draw", "drawarrow", "drawdblarrow", "fill", "filldraw", "drawdot",
+ "loggingall", "interact", "tracingall", "tracingnone",
+ "pickup",
+ "undraw", "unfill", "unfilldraw",
+ "buildcycle", "dashpattern", "decr", "dotlabel", "dotlabels", "drawoptions",
+ "incr", "label", "labels", "max", "min", "thelabel", "z",
+ "beginchar", "blacker", "capsule_end", "change_width",
+ "define_blacker_pixels", "define_corrected_pixels",
+ "define_good_x_pixels", "define_good_y_pixels",
+ "define_horizontal_corrected_pixels", "define_pixels",
+ "define_whole_blacker_pixels", "define_whole_pixels",
+ "define_whole_vertical_blacker_pixels",
+ "define_whole_vertical_pixels", "endchar", "extra_beginchar",
+ "extra_endchar", "extra_setup", "font_coding_scheme",
+ "clearxy", "clearit", "clearpen", "shipit",
+ "font_extra_space",
+ "exitunless",
+ "relax", "hide", "gobble", "gobbled", "stop",
+ "blankpicture",
+ "counterclockwise", "tensepath", "takepower", "direction",
+ "softjoin", -- "magstep",
+ "makelabel", -- "laboff",
+ "rotatedabout", "flex", "superellipse", "image",
+ "nullpen", "savepen", "clearpen", "penpos", "penlabels", -- "clear_pen_memory",
+ "range", "thru",
+ "z", "laboff",
+ "bye",
+ --
+ "red", "green", "blue", "cyan", "magenta", "yellow", "black", "white", "background",
+ --
+ "mm", "pt", "dd", "bp", "cm", "pc", "cc", "in",
+ --
+ "triplet", "quadruplet",
+ },
+ internals = { -- we need to remove duplicates above
+ --
+ "mitered", "rounded", "beveled", "butt", "squared",
+ "eps", "epsilon", "infinity",
+ "bboxmargin",
+ "ahlength", "ahangle",
+ "labeloffset", "dotlabeldiam",
+ "defaultpen", "defaultscale",
+ "join_radius",
+ "charscale", -- actually a mult-fun one
+ --
+ "pen_lft", "pen_rt", "pen_top", "pen_bot", -- "pen_count_",
+ },
+ metafont = {
+ -- :: =: =:| =:|> |=: |=:> |=:| |=:|> |=:|>> ||:
+ "autorounding", "beginchar", "blacker", "boundarychar", "capsule_def",
+ "capsule_end", "change_width", "chardp", "chardx", "chardy", "charexists",
+ "charext", "charht", "charic", "charlist", "charwd", "cull", "cullit",
+ "currenttransform", "currentwindow", "define_blacker_pixels",
+ "define_corrected_pixels", "define_good_x_pixels", "define_good_y_pixels",
+ "define_horizontal_corrected_pixels", "define_pixels",
+ "define_whole_blacker_pixels", "define_whole_pixels",
+ "define_whole_vertical_blacker_pixels", "define_whole_vertical_pixels",
+ "designsize", "display", "displaying", "endchar", "extensible", "extra_beginchar",
+ "extra_endchar", "extra_setup", "fillin", "font_coding_scheme",
+ "font_extra_space", "font_identifier", "font_normal_shrink",
+ "font_normal_space", "font_normal_stretch", "font_quad", "font_size",
+ "font_slant", "font_x_height", "fontdimen", "fontmaking", "gfcorners",
+ "granularity", "grayfont", "headerbyte", "hppp", "hround", "imagerules",
+ "italcorr", "kern", "labelfont", "ligtable", "lowres_fix", "makebox",
+ "makegrid", "maketicks", "mode_def", "mode_setup", "nodisplays",
+ "notransforms", "numspecial", "o_correction", "openit", "openwindow",
+ "pixels_per_inch", "proofing", "proofoffset", "proofrule", "proofrulethickness",
+ "rulepen", "screenchars", "screenrule", "screenstrokes", "screen_cols", "screen_rows",
+ "showit", "slantfont", "smode", "smoothing", "titlefont", "totalweight",
+ "tracingedges", "tracingpens", "turningcheck", "unitpixel", "vppp", "vround",
+ "xoffset", "yoffset",
+ },
+ disabled = {
+ "verbatimtex", "troffmode"
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua
new file mode 100644
index 00000000000..d9c432f7c66
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua
@@ -0,0 +1,1287 @@
+-- the tex table has overlap
+
+return {
+ ["aleph"]={
+ "AlephVersion",
+ "Alephminorversion",
+ "Alephrevision",
+ "Alephversion",
+ "Omegaminorversion",
+ "Omegarevision",
+ "Omegaversion",
+ "boxdir",
+ "pagebottomoffset",
+ "pagerightoffset",
+ },
+ ["etex"]={
+ "botmarks",
+ "clubpenalties",
+ "currentgrouplevel",
+ "currentgrouptype",
+ "currentifbranch",
+ "currentiflevel",
+ "currentiftype",
+ "detokenize",
+ "dimexpr",
+ "displaywidowpenalties",
+ "eTeXVersion",
+ "eTeXminorversion",
+ "eTeXrevision",
+ "eTeXversion",
+ "everyeof",
+ "firstmarks",
+ "fontchardp",
+ "fontcharht",
+ "fontcharic",
+ "fontcharwd",
+ "glueexpr",
+ "glueshrink",
+ "glueshrinkorder",
+ "gluestretch",
+ "gluestretchorder",
+ "gluetomu",
+ "ifcsname",
+ "ifdefined",
+ "iffontchar",
+ "interactionmode",
+ "interlinepenalties",
+ "lastlinefit",
+ "lastnodetype",
+ "marks",
+ "muexpr",
+ "mutoglue",
+ "numexpr",
+ "pagediscards",
+ "parshapedimen",
+ "parshapeindent",
+ "parshapelength",
+ "predisplaydirection",
+ "protected",
+ "readline",
+ "savinghyphcodes",
+ "savingvdiscards",
+ "scantokens",
+ "showgroups",
+ "showifs",
+ "showtokens",
+ "splitbotmarks",
+ "splitdiscards",
+ "splitfirstmarks",
+ "topmarks",
+ "tracingassigns",
+ "tracinggroups",
+ "tracingifs",
+ "tracingnesting",
+ "tracingscantokens",
+ "unexpanded",
+ "unless",
+ "widowpenalties",
+ },
+ ["luatex"]={
+ "Uchar",
+ "Udelcode",
+ "Udelcodenum",
+ "Udelimiter",
+ "Udelimiterover",
+ "Udelimiterunder",
+ "Uhextensible",
+ "Uleft",
+ "Umathaccent",
+--"Umathaccents",
+ "Umathaxis",
+ "Umathbinbinspacing",
+ "Umathbinclosespacing",
+ "Umathbininnerspacing",
+ "Umathbinopenspacing",
+ "Umathbinopspacing",
+ "Umathbinordspacing",
+ "Umathbinpunctspacing",
+ "Umathbinrelspacing",
+--"Umathbotaccent",
+ "Umathchar",
+ "Umathcharclass",
+ "Umathchardef",
+ "Umathcharfam",
+ "Umathcharnum",
+ "Umathcharnumdef",
+ "Umathcharslot",
+ "Umathclosebinspacing",
+ "Umathcloseclosespacing",
+ "Umathcloseinnerspacing",
+ "Umathcloseopenspacing",
+ "Umathcloseopspacing",
+ "Umathcloseordspacing",
+ "Umathclosepunctspacing",
+ "Umathcloserelspacing",
+ "Umathcode",
+ "Umathcodenum",
+ "Umathcodenumdef",
+ "Umathconnectoroverlapmin",
+ "Umathfractiondelsize",
+ "Umathfractiondenomdown",
+ "Umathfractiondenomvgap",
+ "Umathfractionnumup",
+ "Umathfractionnumvgap",
+ "Umathfractionrule",
+ "Umathinnerbinspacing",
+ "Umathinnerclosespacing",
+ "Umathinnerinnerspacing",
+ "Umathinneropenspacing",
+ "Umathinneropspacing",
+ "Umathinnerordspacing",
+ "Umathinnerpunctspacing",
+ "Umathinnerrelspacing",
+ "Umathlimitabovebgap",
+ "Umathlimitabovekern",
+ "Umathlimitabovevgap",
+ "Umathlimitbelowbgap",
+ "Umathlimitbelowkern",
+ "Umathlimitbelowvgap",
+ "Umathopbinspacing",
+ "Umathopclosespacing",
+ "Umathopenbinspacing",
+ "Umathopenclosespacing",
+ "Umathopeninnerspacing",
+ "Umathopenopenspacing",
+ "Umathopenopspacing",
+ "Umathopenordspacing",
+ "Umathopenpunctspacing",
+ "Umathopenrelspacing",
+ "Umathoperatorsize",
+ "Umathopinnerspacing",
+ "Umathopopenspacing",
+ "Umathopopspacing",
+ "Umathopordspacing",
+ "Umathoppunctspacing",
+ "Umathoprelspacing",
+ "Umathordbinspacing",
+ "Umathordclosespacing",
+ "Umathordinnerspacing",
+ "Umathordopenspacing",
+ "Umathordopspacing",
+ "Umathordordspacing",
+ "Umathordpunctspacing",
+ "Umathordrelspacing",
+ "Umathoverbarkern",
+ "Umathoverbarrule",
+ "Umathoverbarvgap",
+ "Umathoverdelimiterbgap",
+ "Umathoverdelimitervgap",
+ "Umathpunctbinspacing",
+ "Umathpunctclosespacing",
+ "Umathpunctinnerspacing",
+ "Umathpunctopenspacing",
+ "Umathpunctopspacing",
+ "Umathpunctordspacing",
+ "Umathpunctpunctspacing",
+ "Umathpunctrelspacing",
+ "Umathquad",
+ "Umathradicaldegreeafter",
+ "Umathradicaldegreebefore",
+ "Umathradicaldegreeraise",
+ "Umathradicalkern",
+ "Umathradicalrule",
+ "Umathradicalvgap",
+ "Umathrelbinspacing",
+ "Umathrelclosespacing",
+ "Umathrelinnerspacing",
+ "Umathrelopenspacing",
+ "Umathrelopspacing",
+ "Umathrelordspacing",
+ "Umathrelpunctspacing",
+ "Umathrelrelspacing",
+ "Umathskewedfractionhgap",
+ "Umathskewedfractionvgap",
+ "Umathspaceafterscript",
+ "Umathstackdenomdown",
+ "Umathstacknumup",
+ "Umathstackvgap",
+ "Umathsubshiftdown",
+ "Umathsubshiftdrop",
+ "Umathsubsupshiftdown",
+ "Umathsubsupvgap",
+ "Umathsubtopmax",
+ "Umathsupbottommin",
+ "Umathsupshiftdrop",
+ "Umathsupshiftup",
+ "Umathsupsubbottommax",
+ "Umathunderbarkern",
+ "Umathunderbarrule",
+ "Umathunderbarvgap",
+ "Umathunderdelimiterbgap",
+ "Umathunderdelimitervgap",
+ "Umiddle",
+ "Uoverdelimiter",
+ "Uradical",
+ "Uright",
+ "Uroot",
+ "Uskewed",
+ "Uskewedwithdelims",
+ "Ustack",
+ "Ustartdisplaymath",
+ "Ustartmath",
+ "Ustopdisplaymath",
+ "Ustopmath",
+ "Usubscript",
+ "Usuperscript",
+ "Uunderdelimiter",
+ "Uvextensible",
+ "adjustspacing",
+ "alignmark",
+ "aligntab",
+ "attribute",
+ "attributedef",
+ "bodydir",
+ "boundary",
+ "boxdir",
+ "catcodetable",
+ "clearmarks",
+ "copyfont",
+ "crampeddisplaystyle",
+ "crampedscriptscriptstyle",
+ "crampedscriptstyle",
+ "crampedtextstyle",
+ "draftmode",
+ "dviextension",
+ "dvifeedback",
+ "dvivariable",
+ "efcode",
+ "hjcode",
+ "firstvalidlanguage",
+ "fontid",
+ "formatname",
+ "gleaders",
+ "hyphenationmin",
+ "ifabsdim",
+ "ifabsnum",
+ "ifprimitive",
+ "ignoreligaturesinfont",
+ "initcatcodetable",
+ "insertht",
+ "lastsavedboxresourceindex",
+ "lastsavedimageresourceindex",
+ "lastsavedimageresourcepages",
+ "lastxpos",
+ "lastypos",
+ "latelua",
+ "leftghost",
+ "leftmarginkern",
+ "letcharcode",
+ "letterspacefont",
+ "localbrokenpenalty",
+ "localinterlinepenalty",
+ "localleftbox",
+ "localrightbox",
+ "lpcode",
+ "luaescapestring",
+ "luatexbanner",
+ "luatexrevision",
+ "luatexversion",
+ "luafunction",
+ "mathdir",
+ "mathdisplayskipmode",
+ "matheqnogapstep",
+ "mathoption",
+ "mathscriptsmode",
+ "mathstyle",
+ "mathsurroundskip",
+ "noboundary",
+ "nokerns",
+ "nohrule",
+ "noligs",
+ "nospaces",
+ "novrule",
+ "normaldeviate",
+ "outputbox",
+ "outputmode",
+ "pagedir",
+ "pageheight",
+ "pagebottomoffset",
+ "pageleftoffset",
+ "pagerightoffset",
+ "pagetopoffset",
+ "pagewidth",
+ "pardir",
+ "pdfextension",
+ "pdffeedback",
+ "pdfvariable",
+ "postexhyphenchar",
+ "posthyphenchar",
+ "preexhyphenchar",
+ "prehyphenchar",
+ "primitive",
+ "protrudechars",
+ "protrusionboundary",
+ "pxdimen",
+ "randomseed",
+ "rightghost",
+ "rightmarginkern",
+ "rpcode",
+ "saveboxresource",
+ "savecatcodetable",
+ "saveimageresource",
+ "savepos",
+ "scantextokens",
+ "setfontid",
+ "setrandomseed",
+ "suppressfontnotfounderror",
+ "suppressifcsnameerror",
+ "suppresslongerror",
+ "suppressoutererror",
+ "suppressmathparerror",
+ "synctex",
+ "tagcode",
+ "textdir",
+ "tracingfonts",
+ "uniformdeviate",
+ "useboxresource",
+ "useimageresource",
+ "wordboundary",
+ --
+ "vpack",
+ "hpack",
+ "tpack",
+ "csstring",
+ "begincsname",
+ "lastnamedcs",
+ "toksapp",
+ "tokspre",
+ "etoksapp",
+ "etokspre",
+ },
+ ["omega"]={
+ "OmegaVersion",
+ "bodydir",
+ "chardp",
+ "charht",
+ "charit",
+ "charwd",
+ "leftghost",
+ "localbrokenpenalty",
+ "localinterlinepenalty",
+ "localleftbox",
+ "localrightbox",
+ "mathdir",
+ "odelcode",
+ "odelimiter",
+ "omathaccent",
+ "omathchar",
+ "omathchardef",
+ "omathcode",
+ "oradical",
+ "pagedir",
+ "pageheight",
+ "pagewidth",
+ "pardir",
+ "rightghost",
+ "textdir",
+ },
+ ["pdftex"]={
+ "efcode",
+ "expanded",
+ "ifincsname",
+ "ifpdfabsdim",
+ "ifpdfabsnum",
+ "ifpdfprimitive",
+ "leftmarginkern",
+ "letterspacefont",
+ "lpcode",
+ "pdfadjustspacing",
+ "pdfannot",
+ "pdfcatalog",
+ "pdfcolorstack",
+ "pdfcolorstackinit",
+ "pdfcompresslevel",
+ "pdfcopyfont",
+ "pdfcreationdate",
+ "pdfdecimaldigits",
+ "pdfdest",
+ "pdfdestmargin",
+ "pdfdraftmode",
+ "pdfeachlineheight",
+ "pdfeachlinedepth",
+ "pdfendlink",
+ "pdfendthread",
+ "pdffirstlineheight",
+ "pdffontattr",
+ "pdffontexpand",
+ "pdffontname",
+ "pdffontobjnum",
+ "pdffontsize",
+ "pdfxformmargin",
+ "pdfgamma",
+ "pdfgentounicode",
+ "pdfglyphtounicode",
+ "pdfhorigin",
+ "pdfignoreddimen",
+ "pdfimageapplygamma",
+ "pdfimagegamma",
+ "pdfimagehicolor",
+ "pdfimageresolution",
+ "pdfincludechars",
+ "pdfinclusioncopyfonts",
+ "pdfignoreunknownimages",
+ "pdfinclusionerrorlevel",
+ "pdfignoreunknownimages",
+ "pdfinfo",
+ "pdfinfoomitdate",
+ "pdftrailerid",
+ "pdfinsertht",
+ "pdflastannot",
+ "pdflastlinedepth",
+ "pdflastlink",
+ "pdflastobj",
+ "pdflastxform",
+ "pdflastximage",
+ "pdflastximagepages",
+ "pdflastxpos",
+ "pdflastypos",
+ "pdflinkmargin",
+ "pdfliteral",
+ "pdfmapfile",
+ "pdfmapline",
+ "pdfminorversion",
+ "pdfnames",
+ "pdfnoligatures",
+ "pdfnormaldeviate",
+ "pdfobj",
+ "pdfobjcompresslevel",
+ "pdfoutline",
+ "pdfoutput",
+ "pdfpageattr",
+ "pdfpagebox",
+ "pdfpageheight",
+ "pdfpageref",
+ "pdfpageresources",
+ "pdfpagesattr",
+ "pdfpagewidth",
+ "pdfpkmode",
+ "pdfpkresolution",
+ "pdfpkfixeddpi",
+ "pdfprimitive",
+ "pdfprotrudechars",
+ "pdfpxdimen",
+ "pdfrandomseed",
+ "pdfrefobj",
+ "pdfrefxform",
+ "pdfrefximage",
+ "pdfreplacefont",
+ "pdfrestore",
+ "pdfretval",
+ "pdfsave",
+ "pdfsavepos",
+ "pdfsetmatrix",
+ "pdfsetrandomseed",
+ "pdfstartlink",
+ "pdfstartthread",
+ "pdftexbanner",
+ "pdftexrevision",
+ "pdftexversion",
+ "pdfsuppressptexinfo",
+ "pdfsuppressoptionalinfo",
+ "pdfthread",
+ "pdfthreadmargin",
+ "pdftracingfonts",
+ "pdftrailer",
+ "pdfuniformdeviate",
+ "pdfuniqueresname",
+ "pdfvorigin",
+ "pdfxform",
+ "pdfxformattr",
+ "pdfxformname",
+ "pdfxformresources",
+ "pdfximage",
+ "quitvmode",
+ "rightmarginkern",
+ "rpcode",
+ "tagcode",
+ },
+ ["tex"]={
+ "-",
+ "/",
+ "AlephVersion",
+ "Alephminorversion",
+ "Alephrevision",
+ "Alephversion",
+ "OmegaVersion",
+ "Omegaminorversion",
+ "Omegarevision",
+ "Omegaversion",
+ "Udelcode",
+ "Udelcodenum",
+ "Udelimiter",
+ "Udelimiterover",
+ "Udelimiterunder",
+ "Uhextensible",
+ "Uleft",
+ "Umathaccent",
+--"Umathaccents",
+ "Umathaxis",
+ "Umathbinbinspacing",
+ "Umathbinclosespacing",
+ "Umathbininnerspacing",
+ "Umathbinopenspacing",
+ "Umathbinopspacing",
+ "Umathbinordspacing",
+ "Umathbinpunctspacing",
+ "Umathbinrelspacing",
+--"Umathbotaccent",
+ "Umathchar",
+ "Umathcharclass",
+ "Umathchardef",
+ "Umathcharfam",
+ "Umathcharnum",
+ "Umathcharnumdef",
+ "Umathcharslot",
+ "Umathclosebinspacing",
+ "Umathcloseclosespacing",
+ "Umathcloseinnerspacing",
+ "Umathcloseopenspacing",
+ "Umathcloseopspacing",
+ "Umathcloseordspacing",
+ "Umathclosepunctspacing",
+ "Umathcloserelspacing",
+ "Umathcode",
+ "Umathcodenum",
+ "Umathcodenumdef",
+ "Umathconnectoroverlapmin",
+ "Umathfractiondelsize",
+ "Umathfractiondenomdown",
+ "Umathfractiondenomvgap",
+ "Umathfractionnumup",
+ "Umathfractionnumvgap",
+ "Umathfractionrule",
+ "Umathinnerbinspacing",
+ "Umathinnerclosespacing",
+ "Umathinnerinnerspacing",
+ "Umathinneropenspacing",
+ "Umathinneropspacing",
+ "Umathinnerordspacing",
+ "Umathinnerpunctspacing",
+ "Umathinnerrelspacing",
+ "Umathlimitabovebgap",
+ "Umathlimitabovekern",
+ "Umathlimitabovevgap",
+ "Umathlimitbelowbgap",
+ "Umathlimitbelowkern",
+ "Umathlimitbelowvgap",
+ "Umathopbinspacing",
+ "Umathopclosespacing",
+ "Umathopenbinspacing",
+ "Umathopenclosespacing",
+ "Umathopeninnerspacing",
+ "Umathopenopenspacing",
+ "Umathopenopspacing",
+ "Umathopenordspacing",
+ "Umathopenpunctspacing",
+ "Umathopenrelspacing",
+ "Umathoperatorsize",
+ "Umathopinnerspacing",
+ "Umathopopenspacing",
+ "Umathopopspacing",
+ "Umathopordspacing",
+ "Umathoppunctspacing",
+ "Umathoprelspacing",
+ "Umathordbinspacing",
+ "Umathordclosespacing",
+ "Umathordinnerspacing",
+ "Umathordopenspacing",
+ "Umathordopspacing",
+ "Umathordordspacing",
+ "Umathordpunctspacing",
+ "Umathordrelspacing",
+ "Umathoverbarkern",
+ "Umathoverbarrule",
+ "Umathoverbarvgap",
+ "Umathoverdelimiterbgap",
+ "Umathoverdelimitervgap",
+ "Umathpunctbinspacing",
+ "Umathpunctclosespacing",
+ "Umathpunctinnerspacing",
+ "Umathpunctopenspacing",
+ "Umathpunctopspacing",
+ "Umathpunctordspacing",
+ "Umathpunctpunctspacing",
+ "Umathpunctrelspacing",
+ "Umathquad",
+ "Umathradicaldegreeafter",
+ "Umathradicaldegreebefore",
+ "Umathradicaldegreeraise",
+ "Umathradicalkern",
+ "Umathradicalrule",
+ "Umathradicalvgap",
+ "Umathrelbinspacing",
+ "Umathrelclosespacing",
+ "Umathrelinnerspacing",
+ "Umathrelopenspacing",
+ "Umathrelopspacing",
+ "Umathrelordspacing",
+ "Umathrelpunctspacing",
+ "Umathrelrelspacing",
+ "Umathskewedfractionhgap",
+ "Umathskewedfractionvgap",
+ "Umathspaceafterscript",
+ "Umathstackdenomdown",
+ "Umathstacknumup",
+ "Umathstackvgap",
+ "Umathsubshiftdown",
+ "Umathsubshiftdrop",
+ "Umathsubsupshiftdown",
+ "Umathsubsupvgap",
+ "Umathsubtopmax",
+ "Umathsupbottommin",
+ "Umathsupshiftdrop",
+ "Umathsupshiftup",
+ "Umathsupsubbottommax",
+ "Umathunderbarkern",
+ "Umathunderbarrule",
+ "Umathunderbarvgap",
+ "Umathunderdelimiterbgap",
+ "Umathunderdelimitervgap",
+ "Umiddle",
+ "Uoverdelimiter",
+ "Uradical",
+ "Uright",
+ "Uroot",
+ "Uskewed",
+ "Uskewedwithdelims",
+ "Ustack",
+ "Ustartdisplaymath",
+ "Ustartmath",
+ "Ustopdisplaymath",
+ "Ustopmath",
+ "Usubscript",
+ "Usuperscript",
+ "Uunderdelimiter",
+ "Uvextensible",
+ "above",
+ "abovedisplayshortskip",
+ "abovedisplayskip",
+ "abovewithdelims",
+ "accent",
+ "adjdemerits",
+ "advance",
+ "afterassignment",
+ "aftergroup",
+ "alignmark",
+ "aligntab",
+ "atop",
+ "atopwithdelims",
+ "attribute",
+ "attributedef",
+ "badness",
+ "baselineskip",
+ "batchmode",
+ "begingroup",
+ "belowdisplayshortskip",
+ "belowdisplayskip",
+ "binoppenalty",
+ "bodydir",
+ "botmark",
+ "botmarks",
+ "boundary",
+ "box",
+ "boxdir",
+ "boxmaxdepth",
+ "brokenpenalty",
+ "catcode",
+ "catcodetable",
+ "char",
+ "chardef",
+--"chardp",
+--"charht",
+--"charit",
+--"charwd",
+ "cleaders",
+ "clearmarks",
+ "closein",
+ "closeout",
+ "clubpenalties",
+ "clubpenalty",
+ "copy",
+ "copyfont",
+ "count",
+ "countdef",
+ "cr",
+ "crampeddisplaystyle",
+ "crampedscriptscriptstyle",
+ "crampedscriptstyle",
+ "crampedtextstyle",
+ "crcr",
+ "csname",
+ "currentgrouplevel",
+ "currentgrouptype",
+ "currentifbranch",
+ "currentiflevel",
+ "currentiftype",
+ "day",
+ "deadcycles",
+ "def",
+ "defaulthyphenchar",
+ "defaultskewchar",
+ "delcode",
+ "delimiter",
+ "delimiterfactor",
+ "delimitershortfall",
+ "detokenize",
+ "dimen",
+ "dimendef",
+ "dimexpr",
+ "directlua",
+ "discretionary",
+ "displayindent",
+ "displaylimits",
+ "displaystyle",
+ "displaywidowpenalties",
+ "displaywidowpenalty",
+ "displaywidth",
+ "divide",
+ "doublehyphendemerits",
+ "dp",
+ "dump",
+ "dviextension",
+ "dvifeedback",
+ "dvivariable",
+ "eTeXVersion",
+ "eTeXminorversion",
+ "eTeXrevision",
+ "eTeXversion",
+ "edef",
+ "efcode",
+ "hjcode",
+ "else",
+ "emergencystretch",
+ "end",
+ "endcsname",
+ "endgroup",
+ "endinput",
+ "endlinechar",
+ "eqno",
+ "errhelp",
+ "errmessage",
+ "errorcontextlines",
+ "errorstopmode",
+ "escapechar",
+ "everycr",
+ "everydisplay",
+ "everyeof",
+ "everyhbox",
+ "everyjob",
+ "everymath",
+ "everypar",
+ "everyvbox",
+ "exhyphenchar",
+ "exhyphenpenalty",
+ "expandafter",
+ "expanded",
+ "expandglyphsinfont",
+ "fam",
+ "fi",
+ "finalhyphendemerits",
+ "firstmark",
+ "firstmarks",
+ "floatingpenalty",
+ "font",
+ "fontchardp",
+ "fontcharht",
+ "fontcharic",
+ "fontcharwd",
+ "fontdimen",
+ "firstvalidlanguage",
+ "fontid",
+ "fontname",
+ "formatname",
+ "futurelet",
+ "gdef",
+ "gleaders",
+ "global",
+ "globaldefs",
+ "glueexpr",
+ "glueshrink",
+ "glueshrinkorder",
+ "gluestretch",
+ "gluestretchorder",
+ "gluetomu",
+ "halign",
+ "hangafter",
+ "hangindent",
+ "hbadness",
+ "hbox",
+ "hfil",
+ "hfill",
+ "hfilneg",
+ "hfuzz",
+ "hoffset",
+ "holdinginserts",
+ "hrule",
+ "hsize",
+ "hskip",
+ "hss",
+ "ht",
+ "hyphenation",
+ "hyphenchar",
+ "hyphenpenalty",
+ "if",
+ "ifabsdim",
+ "ifabsnum",
+ "ifcase",
+ "ifcat",
+ "ifcsname",
+ "ifdefined",
+ "ifdim",
+ "ifeof",
+ "iffalse",
+ "iffontchar",
+ "ifhbox",
+ "ifhmode",
+ "ifincsname",
+ "ifinner",
+ "ifmmode",
+ "ifnum",
+ "ifodd",
+ "ifpdfabsdim",
+ "ifpdfabsnum",
+ "ifpdfprimitive",
+ "ifprimitive",
+ "iftrue",
+ "ifvbox",
+ "ifvmode",
+ "ifvoid",
+ "ifx",
+ "ignoreligaturesinfont",
+ "ignorespaces",
+ "immediate",
+ "indent",
+ "initcatcodetable",
+ "input",
+ "inputlineno",
+ "insert",
+ "insertpenalties",
+ "interactionmode",
+ "interlinepenalties",
+ "interlinepenalty",
+ "jobname",
+ "kern",
+ "language",
+ "lastbox",
+ "lastkern",
+ "lastlinefit",
+ "lastnodetype",
+ "lastpenalty",
+ "lastsavedboxresourceindex",
+ "lastsavedimageresourceindex",
+ "lastsavedimageresourcepages",
+ "lastskip",
+ "lastxpos",
+ "lastypos",
+ "latelua",
+ "lccode",
+ "leaders",
+ "left",
+ "leftghost",
+ "lefthyphenmin",
+ "leftmarginkern",
+ "leftskip",
+ "leqno",
+ "let",
+ "letcharcode",
+ "letterspacefont",
+ "limits",
+ "linepenalty",
+ "lineskip",
+ "lineskiplimit",
+ "localbrokenpenalty",
+ "localinterlinepenalty",
+ "localleftbox",
+ "localrightbox",
+ "long",
+ "looseness",
+ "lower",
+ "lowercase",
+ "lpcode",
+ "luaescapestring",
+ "luatexbanner",
+ "luatexrevision",
+ "luatexversion",
+ "mag",
+ "mark",
+ "marks",
+ "mathaccent",
+ "mathbin",
+ "mathchar",
+ "mathchardef",
+ "mathchoice",
+ "mathclose",
+ "mathcode",
+ "mathdir",
+ "mathdisplayskipmode",
+ "matheqnogapstep",
+ "mathinner",
+ "mathop",
+ "mathopen",
+ "mathoption",
+ "mathord",
+ "mathpunct",
+ "mathrel",
+ "mathscriptsmode",
+ "mathstyle",
+ "mathsurroundskip",
+ "mathsurround",
+ "maxdeadcycles",
+ "maxdepth",
+ "meaning",
+ "medmuskip",
+ "message",
+ "middle",
+ "mkern",
+ "month",
+ "moveleft",
+ "moveright",
+ "mskip",
+ "muexpr",
+ "multiply",
+ "muskip",
+ "muskipdef",
+ "mutoglue",
+ "newlinechar",
+ "noalign",
+ "noboundary",
+ "noexpand",
+ "noindent",
+ "nokerns",
+ "nohrule",
+ "noligs",
+ "nospaces",
+ "novrule",
+ "nolimits",
+ "nolocaldirs",
+ "nolocalwhatsits",
+ "nonscript",
+ "nonstopmode",
+ "normaldeviate",
+ "nulldelimiterspace",
+ "nullfont",
+ "number",
+ "numexpr",
+ "odelcode",
+ "odelimiter",
+ "omathaccent",
+ "omathchar",
+ "omathchardef",
+ "omathcode",
+ "omit",
+ "openin",
+ "openout",
+ "or",
+ "oradical",
+ "outer",
+ "output",
+ "outputbox",
+ "outputpenalty",
+ "over",
+ "overfullrule",
+ "overline",
+ "overwithdelims",
+ "pagebottomoffset",
+ "pagedepth",
+ "pagedir",
+ "pagediscards",
+ "pagefilllstretch",
+ "pagefillstretch",
+ "pagefilstretch",
+ "pagegoal",
+ "pageheight",
+ "pageleftoffset",
+ "pagerightoffset",
+ "pageshrink",
+ "pagestretch",
+ "pagetopoffset",
+ "pagetotal",
+ "pagewidth",
+ "par",
+ "pardir",
+ "parfillskip",
+ "parindent",
+ "parshape",
+ "parshapedimen",
+ "parshapeindent",
+ "parshapelength",
+ "parskip",
+ "patterns",
+ "pausing",
+ "pdfadjustspacing",
+ "pdfannot",
+ "pdfcatalog",
+ "pdfcolorstack",
+ "pdfcolorstackinit",
+ "pdfcompresslevel",
+ "pdfcopyfont",
+ "pdfcreationdate",
+ "pdfdecimaldigits",
+ "pdfdest",
+ "pdfdestmargin",
+ "pdfdraftmode",
+ "pdfeachlineheight",
+ "pdfeachlinedepth",
+ "pdfendlink",
+ "pdfendthread",
+ "pdfextension",
+ "pdfvariable",
+ "pdffirstlineheight",
+ "pdffontattr",
+ "pdffontexpand",
+ "pdffontname",
+ "pdffontobjnum",
+ "pdffontsize",
+ "pdfxformmargin",
+ "pdfgamma",
+ "pdfgentounicode",
+ "pdfglyphtounicode",
+ "pdfhorigin",
+ "pdfignoreddimen",
+ "pdfimageaddfilename",
+ "pdfimageapplygamma",
+ "pdfimagegamma",
+ "pdfimagehicolor",
+ "pdfimageresolution",
+ "pdfincludechars",
+ "pdfinclusioncopyfonts",
+ "pdfinclusionerrorlevel",
+ "pdfignoreunknownimages",
+ "pdfinfo",
+ "pdfinfoomitdate",
+ "pdftrailerid",
+ "pdfinsertht",
+ "pdflastannot",
+ "pdflastlinedepth",
+ "pdflastlink",
+ "pdflastobj",
+ "pdflastxform",
+ "pdflastximage",
+ "pdflastximagepages",
+ "pdflastxpos",
+ "pdflastypos",
+ "pdflinkmargin",
+ "pdfliteral",
+ "pdfmapfile",
+ "pdfmapline",
+ "pdfminorversion",
+ "pdfnames",
+ "pdfnoligatures",
+ "pdfnormaldeviate",
+ "pdfobj",
+ "pdfobjcompresslevel",
+ "pdfoutline",
+ "pdfoutput",
+ "pdfpageattr",
+ "pdfpagebox",
+ "pdfpageheight",
+ "pdfpageref",
+ "pdfpageresources",
+ "pdfpagesattr",
+ "pdfpagewidth",
+ "pdfpkmode",
+ "pdfpkresolution",
+ "pdfpkfixeddpi",
+ "pdfprimitive",
+ "pdfprotrudechars",
+ "pdfpxdimen",
+ "pdfrandomseed",
+ "pdfrefobj",
+ "pdfrefxform",
+ "pdfrefximage",
+ "pdfreplacefont",
+ "pdfrestore",
+ "pdfretval",
+ "pdfsave",
+ "pdfsavepos",
+ "pdfsetmatrix",
+ "pdfsetrandomseed",
+ "pdfstartlink",
+ "pdfstartthread",
+ "pdftexbanner",
+ "pdftexrevision",
+ "pdftexversion",
+ "pdfsuppressptexinfo",
+ "pdfsuppressoptionalinfo",
+ "pdfthread",
+ "pdfthreadmargin",
+ "pdftracingfonts",
+ "pdftrailer",
+ "pdfuniformdeviate",
+ "pdfuniqueresname",
+ "pdfvorigin",
+ "pdfxform",
+ "pdfxformattr",
+ "pdfxformname",
+ "pdfxformresources",
+ "pdfximage",
+ "penalty",
+ "postdisplaypenalty",
+ "postexhyphenchar",
+ "posthyphenchar",
+ "predisplaydirection",
+ "predisplaypenalty",
+ "predisplaysize",
+ "preexhyphenchar",
+ "prehyphenchar",
+ "pretolerance",
+ "prevdepth",
+ "prevgraf",
+ "primitive",
+ "protected",
+ "protrudechars",
+ "protrusionboundary",
+ "pxdimen",
+ "quitvmode",
+ "radical",
+ "raise",
+ "randomseed",
+ "read",
+ "readline",
+ "relax",
+ "relpenalty",
+ "right",
+ "rightghost",
+ "righthyphenmin",
+ "rightmarginkern",
+ "rightskip",
+ "romannumeral",
+ "rpcode",
+ "saveboxresource",
+ "saveimageresource",
+ "savepos",
+ "savecatcodetable",
+ "savinghyphcodes",
+ "savingvdiscards",
+ "scantextokens",
+ "scantokens",
+ "scriptfont",
+ "scriptscriptfont",
+ "scriptscriptstyle",
+ "scriptspace",
+ "scriptstyle",
+ "scrollmode",
+ "setbox",
+ "setfontid",
+ "setlanguage",
+ "setrandomseed",
+ "sfcode",
+ "shipout",
+ "show",
+ "showbox",
+ "showboxbreadth",
+ "showboxdepth",
+ "showgroups",
+ "showifs",
+ "showlists",
+ "showthe",
+ "showtokens",
+ "skewchar",
+ "skip",
+ "skipdef",
+--"skipexpr",
+ "spacefactor",
+ "spaceskip",
+ "span",
+ "special",
+ "splitbotmark",
+ "splitbotmarks",
+ "splitdiscards",
+ "splitfirstmark",
+ "splitfirstmarks",
+ "splitmaxdepth",
+ "splittopskip",
+ "string",
+ "suppressfontnotfounderror",
+ "suppressifcsnameerror",
+ "suppresslongerror",
+ "suppressoutererror",
+ "synctex",
+ "tabskip",
+ "tagcode",
+ "textdir",
+ "textfont",
+ "textstyle",
+ "the",
+ "thickmuskip",
+ "thinmuskip",
+ "time",
+ "toks",
+ "toksdef",
+ "tolerance",
+ "topmark",
+ "topmarks",
+ "topskip",
+ "tracingassigns",
+ "tracingcommands",
+ "tracingfonts",
+ "tracinggroups",
+ "tracingifs",
+ "tracinglostchars",
+ "tracingmacros",
+ "tracingnesting",
+ "tracingonline",
+ "tracingoutput",
+ "tracingpages",
+ "tracingparagraphs",
+ "tracingrestores",
+ "tracingscantokens",
+ "tracingstats",
+ "uccode",
+ "uchyph",
+ "underline",
+ "unexpanded",
+ "unhbox",
+ "unhcopy",
+ "uniformdeviate",
+ "unkern",
+ "unless",
+ "unpenalty",
+ "unskip",
+ "unvbox",
+ "unvcopy",
+ "uppercase",
+ "useboxresource",
+ "useimageresource",
+ "vadjust",
+ "valign",
+ "vbadness",
+ "vbox",
+ "vcenter",
+ "vfil",
+ "vfill",
+ "vfilneg",
+ "vfuzz",
+ "voffset",
+ "vrule",
+ "vsize",
+ "vskip",
+ "vsplit",
+ "vss",
+ "vtop",
+ "wd",
+ "widowpenalties",
+ "widowpenalty",
+ "wordboundary",
+ "write",
+ "xdef",
+ "xleaders",
+ "xspaceskip",
+ "year",
+ --
+ "vpack",
+ "hpack",
+ "tpack",
+ "csstring",
+ "begincsname",
+ "lastnamedcs",
+ "toksapp",
+ "tokspre",
+ "etoksapp",
+ "etokspre",
+ },
+ ["xetex"]={
+ "XeTeXversion",
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv
new file mode 100644
index 00000000000..e385341c2c6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv
@@ -0,0 +1,81 @@
+%D \module
+%D [ file=mult-prm,
+%D version=2011.09.18, % actually older
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Primitives,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is therefore
+%C copyrighted by \PRAGMA. See mreadme.pdf for details.
+
+%D This file is only a helper for generating files that can be used in an
+%D editor for syntax highlighting.
+
+\startluacode
+
+ context.starttext()
+
+ function table.sorted(t)
+ table.sort(t)
+ return t
+ end
+
+ local missing = {
+ tex = {
+ "def", "catcode", "futurelet", "chardef",
+ "voffset", "hoffset",
+ "numexpr", "dimexpr",
+ "write", "dump", "skipdef,"
+ },
+ etex = {
+ "savingvdiscards",
+ },
+ pdftex = {
+ },
+ luatex = {
+ },
+ aleph = {
+ "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion",
+ },
+ omega = {
+ "Omegaminorversion", "Omegarevision", "Omegaversion",
+ "omathcode", "odelcode", "omathchardef", "omathchar", "omathaccent", "odelimiter", "oradical",
+ },
+ xetex = {
+ "XeTeXversion",
+ },
+ plain = {
+ "TeX",
+ "bgroup", "egroup", "endgraf", "space", "empty", "null",
+ "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newhelp", "newread", "newwrite", "newfam", "newlanguage", "newinsert", "newif",
+ "maxdimen", "magstephalf", "magstep",
+ "frenchspacing", "nonfrenchspacing", "normalbaselines", "obeylines", "obeyspaces", "raggedright", "ttraggedright",
+ "thinspace", "negthinspace", "enspace", "enskip", "quad", "qquad",
+ "smallskip", "medskip", "bigskip", "removelastskip", "topglue", "vglue", "hglue",
+ "break", "nobreak", "allowbreak", "filbreak", "goodbreak", "smallbreak", "medbreak", "bigbreak",
+ "line", "leftline", "rightline", "centerline", "rlap", "llap", "underbar", "strutbox", "strut",
+ "cases", "matrix", "pmatrix", "bordermatrix", "eqalign", "displaylines", "eqalignno", "leqalignno",
+ "pageno", "folio", "tracingall", "showhyphens", "fmtname", "fmtversion",
+ "hphantom", "vphantom", "phantom", "smash",
+ },
+ }
+
+ local primitives = {
+ tex = table.sorted( table.merged( missing.tex , table.fromhash(tex.primitives()) ) ),
+ etex = table.sorted( table.merged( missing.etex , tex.extraprimitives('etex') ) ),
+ pdftex = table.sorted( table.merged( missing.pdftex, tex.extraprimitives('pdftex') ) ),
+ luatex = table.sorted( table.merged( missing.luatex, tex.extraprimitives('luatex') ) ),
+ aleph = table.sorted( table.merged( missing.aleph , tex.extraprimitives('aleph') ) ),
+ omega = table.sorted( table.merged( missing.omega , tex.extraprimitives('omega') ) ),
+ xetex = table.sorted( table.merged( missing.xetex , { } ) ),
+ }
+
+ -- table.remove(primitives.tex,1) -- get rid of \-
+
+ io.savedata("mult-prm.lua",table.serialize(primitives,true,{ reduce = true, inline = false }))
+
+ context.stoptext()
+
+\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv
new file mode 100644
index 00000000000..01a1674dced
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv
@@ -0,0 +1,713 @@
+%D \module
+%D [ file=mult-sys,
+%D version=1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In boring module we define a lot of obscure but useful system constants.
+%D By doing so we save lots of memory while at the same time we prevent
+%D ourself making typing errors.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / System}
+
+\unprotect
+
+%D This file is mostly the same as the \MKII\ variant but we keep extending
+%D \MKIV, so it was bout time to have a dedicated variant.
+%D
+%D The constants are grouped in such a way that there is a minimal change of
+%D conflicts.
+%D
+%D \starttyping
+%D \definesystemconstants {word}
+%D \definemessageconstant {word}
+%D \stoptyping
+%D
+%D This commands generate \type{\s!word} and \type{\m!word}.
+
+\definesystemconstant {hans}
+\definesystemconstant {taco}
+
+%D First we define some system constants used for both the multi||lingual
+%D interface and multi||linguag typesetting.
+
+\definesystemconstant {afrikaans} \definesystemconstant {af}
+\definesystemconstant {arabic} \definesystemconstant {ar}
+\definesystemconstant {catalan} \definesystemconstant {ca}
+\definesystemconstant {chinese} \definesystemconstant {cn}
+\definesystemconstant {croatian} \definesystemconstant {hr}
+\definesystemconstant {czech} \definesystemconstant {cs}
+ \definesystemconstant {cz}
+\definesystemconstant {danish} \definesystemconstant {da}
+\definesystemconstant {dutch} \definesystemconstant {nl}
+\definesystemconstant {english} \definesystemconstant {en}
+\definesystemconstant {finish} \definesystemconstant {fi}
+\definesystemconstant {french} \definesystemconstant {fr}
+\definesystemconstant {german} \definesystemconstant {de}
+\definesystemconstant {hungarian} \definesystemconstant {hu}
+\definesystemconstant {italian} \definesystemconstant {it}
+\definesystemconstant {latin} \definesystemconstant {la}
+\definesystemconstant {ancientlatin} \definesystemconstant {ala}
+\definesystemconstant {lithuanian} \definesystemconstant {lt}
+\definesystemconstant {bokmal} \definesystemconstant {nb}
+\definesystemconstant {malayalam} \definesystemconstant {ml}
+\definesystemconstant {norwegian} \definesystemconstant {no}
+\definesystemconstant {nynorsk} \definesystemconstant {nn}
+\definesystemconstant {polish} \definesystemconstant {pl}
+\definesystemconstant {persian} \definesystemconstant {pe}
+\definesystemconstant {portuguese} \definesystemconstant {pt}
+\definesystemconstant {romanian} \definesystemconstant {ro}
+\definesystemconstant {russian} \definesystemconstant {ru}
+\definesystemconstant {slovak} \definesystemconstant {sk}
+\definesystemconstant {slovenian} \definesystemconstant {sl}
+\definesystemconstant {slovene} % obsolete
+\definesystemconstant {spanish} \definesystemconstant {es}
+\definesystemconstant {swedish} \definesystemconstant {sv}
+\definesystemconstant {turkish} \definesystemconstant {tr}
+\definesystemconstant {turkmen} \definesystemconstant {tk}
+\definesystemconstant {gbenglish} \definesystemconstant {gb}
+\definesystemconstant {ukenglish} \definesystemconstant {uk}
+\definesystemconstant {usenglish} \definesystemconstant {us}
+\definesystemconstant {ukrainian} \definesystemconstant {ua}
+\definesystemconstant {greek} \definesystemconstant {gr}
+\definesystemconstant {ancientgreek} \definesystemconstant {agr}
+\definesystemconstant {vietnamese} \definesystemconstant {vi}
+ \definesystemconstant {vn}
+\definesystemconstant {chinese} \definesystemconstant {cn}
+\definesystemconstant {japanese} \definesystemconstant {ja}
+\definesystemconstant {korean} \definesystemconstant {kr}
+\definesystemconstant {thai} \definesystemconstant {th} % mojca mentioned it at BT2013 but we need more info
+
+%D For proper \UNICODE\ support we need a few font related constants.
+
+\definesystemconstant {BoldItalic}
+\definesystemconstant {BoldSlanted}
+\definesystemconstant {Bold}
+\definesystemconstant {Italic}
+\definesystemconstant {Regular}
+\definesystemconstant {Slanted}
+\definesystemconstant {Unicode}
+
+\definesystemconstant {Handwriting}
+\definesystemconstant {Calligraphy}
+\definesystemconstant {Casual}
+
+\definesystemconstant {Regular}
+\definesystemconstant {Support}
+\definesystemconstant {Type}
+
+\definesystemconstant {Math} % not used
+\definesystemconstant {MathBold} % not used
+
+\definesystemconstant {MathRoman}
+\definesystemconstant {MathRomanBold}
+
+\definesystemconstant {Serif}
+\definesystemconstant {SerifBold}
+\definesystemconstant {SerifItalic}
+\definesystemconstant {SerifBoldItalic}
+\definesystemconstant {SerifSlanted}
+\definesystemconstant {SerifBoldSlanted}
+\definesystemconstant {SerifCaps}
+%definesystemconstant {SerifCapsSlanted}
+
+\definesystemconstant {Sans}
+\definesystemconstant {SansBold}
+\definesystemconstant {SansItalic}
+\definesystemconstant {SansBoldItalic}
+\definesystemconstant {SansSlanted}
+\definesystemconstant {SansBoldSlanted}
+\definesystemconstant {SansCaps}
+%definesystemconstant {SansCapsSlanted}
+
+\definesystemconstant {Mono}
+\definesystemconstant {MonoBold}
+\definesystemconstant {MonoItalic}
+\definesystemconstant {MonoBoldItalic}
+\definesystemconstant {MonoSlanted}
+\definesystemconstant {MonoBoldSlanted}
+\definesystemconstant {MonoCaps}
+%definesystemconstant {MonoCapsSlanted}
+%definesystemconstant {MonoVariable}
+
+\definesystemconstant {DefaultFont}
+
+\definesystemconstant {Simple}
+\definesystemconstant {Normal}
+\definesystemconstant {Caps}
+
+\definesystemconstant {serif}
+\definesystemconstant {sans}
+\definesystemconstant {mono}
+\definesystemconstant {math}
+\definesystemconstant {handwriting}
+\definesystemconstant {calligraphy}
+\definesystemconstant {casual}
+\definesystemconstant {fax}
+
+\definesystemconstant {fallback}
+
+%definesystemconstant {mnem} % kind of generic short tag
+
+\definesystemconstant {otr}
+\definesystemconstant {box}
+
+\definesystemconstant {file}
+\definesystemconstant {name}
+\definesystemconstant {spec}
+
+\definesystemconstant {both}
+
+\definesystemconstant {internal}
+\definesystemconstant {external}
+
+\definesystemconstant {attribute}
+
+\definesystemconstant {none}
+\definesystemconstant {auto}
+\definesystemconstant {default}
+\definesystemconstant {smallcaps}
+
+\definesystemconstant {regular}
+\definesystemconstant {script}
+\definesystemconstant {fraktur}
+\definesystemconstant {blackboard}
+
+\definesystemconstant {mi} % maybe some day a special default vector
+\definesystemconstant {tf}
+\definesystemconstant {sl}
+\definesystemconstant {it}
+\definesystemconstant {bf}
+\definesystemconstant {bs}
+\definesystemconstant {bi}
+
+\definesystemconstant {rm}
+\definesystemconstant {ss}
+\definesystemconstant {tt}
+\definesystemconstant {hw}
+\definesystemconstant {cg}
+\definesystemconstant {mm}
+
+\definesystemconstant {x}
+\definesystemconstant {xx}
+\definesystemconstant {em}
+
+\definesystemconstant {a}
+\definesystemconstant {b}
+\definesystemconstant {c}
+\definesystemconstant {d}
+\definesystemconstant {e}
+\definesystemconstant {f}
+
+\definesystemconstant {mr}
+\definesystemconstant {mb}
+\definesystemconstant {mrlr}
+\definesystemconstant {mrrl}
+\definesystemconstant {mblr}
+\definesystemconstant {mbrl}
+
+\definesystemconstant {tf}
+\definesystemconstant {bf}
+\definesystemconstant {bs}
+\definesystemconstant {bi}
+\definesystemconstant {sl}
+\definesystemconstant {it}
+\definesystemconstant {sc}
+
+\definesystemconstant {small}
+\definesystemconstant {big}
+
+\definesystemconstant {first}
+\definesystemconstant {second}
+\definesystemconstant {third}
+
+%D Next come some \CONTEXT\ constants, used in the definition of private commands:
+
+\definesystemconstant {tex}
+\definesystemconstant {xml}
+\definesystemconstant {lua}
+
+\definesystemconstant {next}
+\definesystemconstant {pickup}
+\definesystemconstant {ascii}
+\definesystemconstant {default}
+\definesystemconstant {unknown}
+\definesystemconstant {action}
+\definesystemconstant {compare}
+\definesystemconstant {do}
+\definesystemconstant {dodo}
+\definesystemconstant {complex}
+\definesystemconstant {simple}
+\definesystemconstant {start}
+\definesystemconstant {stop}
+\definesystemconstant {dummy}
+\definesystemconstant {local}
+\definesystemconstant {global}
+\definesystemconstant {done}
+\definesystemconstant {font}
+\definesystemconstant {link}
+\definesystemconstant {parent}
+\definesystemconstant {child}
+\definesystemconstant {clone}
+\definesystemconstant {section}
+\definesystemconstant {handler}
+\definesystemconstant {counter}
+\definesystemconstant {single}
+\definesystemconstant {multi}
+\definesystemconstant {indeed}
+\definesystemconstant {internal}
+\definesystemconstant {current}
+\definesystemconstant {chain}
+
+% translating setups is asking for a mess so we keep them as-is:
+
+\definesystemconstant {setups}
+
+\definesystemconstant {cite}
+\definesystemconstant {nocite}
+\definesystemconstant {list}
+\definesystemconstant {register}
+\definesystemconstant {author}
+\definesystemconstant {numbering}
+
+% \def\s!parent{->} % 1% faster / => does not work in assignments
+% \def\s!child {<-} % 1% faster / <= does not work in assignments
+
+\definesystemconstant {hasnumber}
+\definesystemconstant {hastitle}
+\definesystemconstant {hascaption}
+\definesystemconstant {haslevel}
+\definesystemconstant {hasparent}
+\definesystemconstant {hassuffix}
+
+\definesystemconstant {mkiv}
+\definesystemconstant {mkii}
+
+\definesystemconstant {normal}
+\definesystemconstant {bold}
+\definesystemconstant {italic}
+\definesystemconstant {slanted}
+\definesystemconstant {smallcaps}
+\definesystemconstant {lcgreek}
+\definesystemconstant {ucgreek}
+\definesystemconstant {sygreek}
+\definesystemconstant {italics}
+
+\definesystemconstant {run}
+
+\definesystemconstant {default}
+
+\definesystemconstant {mode}
+\definesystemconstant {setup}
+\definesystemconstant {environment}
+\definesystemconstant {document}
+
+%definesystemconstant {fam}
+\definesystemconstant {display}
+\definesystemconstant {text}
+\definesystemconstant {script}
+\definesystemconstant {scriptscript}
+\definesystemconstant {uncramped}
+\definesystemconstant {cramped}
+
+\definesystemconstant {hyphenmin}
+\definesystemconstant {lefthyphenmin}
+\definesystemconstant {righthyphenmin}
+\definesystemconstant {lefthyphenchar}
+\definesystemconstant {righthyphenchar}
+
+\definesystemconstant {head}
+\definesystemconstant {symbol}
+\definesystemconstant {sub}
+\definesystemconstant {margin}
+\definesystemconstant {edge}
+
+\definesystemconstant {double}
+\definesystemconstant {decimal}
+\definesystemconstant {binary}
+
+%definesystemconstant {skewchar}
+%definesystemconstant {hyphenchar}
+\definesystemconstant {catcodes}
+%definesystemconstant {encoding}
+%definesystemconstant {entities}
+%definesystemconstant {resource}
+\definesystemconstant {mapping}
+\definesystemconstant {language}
+\definesystemconstant {patterns}
+\definesystemconstant {rname}
+\definesystemconstant {rscale}
+%definesystemconstant {handling}
+\definesystemconstant {features}
+\definesystemconstant {direction}
+\definesystemconstant {fallbacks}
+\definesystemconstant {goodies}
+\definesystemconstant {designsize}
+%definesystemconstant {background}
+%definesystemconstant {ucmap}
+\definesystemconstant {level}
+\definesystemconstant {integral}
+\definesystemconstant {insert} % maybe insertclass
+\definesystemconstant {marker}
+
+\definesystemconstant {mixedcolumn}
+
+%definesystemconstant {property}
+%definesystemconstant {overprint}
+%definesystemconstant {layer}
+\definesystemconstant {effect} % todo s
+%definesystemconstant {negative}
+%definesystemconstant {color}
+%definesystemconstant {transparency}
+
+\definesystemconstant {black}
+\definesystemconstant {white}
+
+\definesystemconstant {system} % not yet interfaces messages
+\definesystemconstant {user}
+\definesystemconstant {check}
+\definesystemconstant {reset}
+\definesystemconstant {set}
+\definesystemconstant {empty}
+
+\definesystemconstant {realpage}
+\definesystemconstant {userpage}
+\definesystemconstant {subpage}
+
+\definesystemconstant {page}
+\definesystemconstant {subpage}
+\definesystemconstant {leftpage}
+\definesystemconstant {rightpage}
+\definesystemconstant {somewhere}
+
+\definesystemconstant {userdata}
+\definesystemconstant {command}
+\definesystemconstant {simple}
+
+\definesystemconstant {full}
+\definesystemconstant {text}
+\definesystemconstant {paragraph}
+\definesystemconstant {margintext}
+\definesystemconstant {line}
+
+\definesystemconstant {number}
+\definesystemconstant {symbol}
+\definesystemconstant {format}
+\definesystemconstant {data}
+\definesystemconstant {float}
+\definesystemconstant {extensions}
+\definesystemconstant {initializations}
+
+\definesystemconstant {rgb}
+\definesystemconstant {cmyk}
+\definesystemconstant {gray}
+\definesystemconstant {spot}
+\definesystemconstant {all}
+\definesystemconstant {dtp}
+\definesystemconstant {none}
+
+\definesystemconstant {map}
+\definesystemconstant {special}
+\definesystemconstant {size}
+
+\definesystemconstant {depth}
+\definesystemconstant {height}
+\definesystemconstant {noheight}
+\definesystemconstant {nodepth}
+
+\definesystemconstant {rel}
+\definesystemconstant {ord}
+
+%D Just to be complete we define the standard \TEX\ units.
+
+\definesystemconstant {cm}
+\definesystemconstant {em}
+\definesystemconstant {ex}
+\definesystemconstant {mm}
+\definesystemconstant {pt}
+\definesystemconstant {sp}
+\definesystemconstant {bp}
+\definesystemconstant {in}
+\definesystemconstant {pc}
+\definesystemconstant {dd}
+\definesystemconstant {cc}
+\definesystemconstant {nd}
+\definesystemconstant {nc}
+
+\definesystemconstant {traditional}
+\definesystemconstant {left}
+\definesystemconstant {middle}
+\definesystemconstant {right}
+
+%D As the name of their define command states, the next set of constants is used in
+%D the message macro's.
+
+\definemessageconstant {check}
+\definemessageconstant {colors}
+\definemessageconstant {columns}
+\definemessageconstant {regimes}
+\definemessageconstant {figures}
+\definemessageconstant {fields}
+\definemessageconstant {files}
+\definemessageconstant {floatblocks}
+\definemessageconstant {fonts}
+\definemessageconstant {handlings}
+\definemessageconstant {interactions}
+\definemessageconstant {javascripts}
+\definemessageconstant {layouts}
+\definemessageconstant {languages}
+\definemessageconstant {references}
+\definemessageconstant {structures}
+\definemessageconstant {symbols}
+\definemessageconstant {system}
+\definemessageconstant {lua}
+\definemessageconstant {textblocks}
+\definemessageconstant {verbatims}
+\definemessageconstant {versions}
+\definemessageconstant {metapost}
+\definemessageconstant {chemicals}
+\definemessageconstant {publications}
+
+%D When we use numbers and dimensions the same applies as with the keywords like
+%D \type {width} and \type {plus} mentioned earlier.
+
+\def\!!ten {10}
+\def\!!twelve {12}
+\def\!!hundred {100}
+\def\!!thousand {1000}
+\def\!!tenthousand {10000}
+\def\!!maxcard {65536}
+\def\!!medcard {32768}
+
+\def\!!zeropoint {0pt}
+\def\!!onepoint {1pt}
+\def\!!twopoint {2pt}
+\def\!!threepoint {3pt}
+\def\!!fourpoint {4pt}
+\def\!!fivepoint {5pt}
+\def\!!sixpoint {6pt}
+\def\!!sevenpoint {7pt}
+\def\!!eightpoint {8pt}
+\def\!!ninepoint {9pt}
+\def\!!tenpoint {10pt}
+\def\!!elevenpoint {11pt}
+\def\!!twelvepoint {12pt}
+\def\!!fourteenpointfour {14.4pt}
+
+\def\!!plustoken {+}
+\def\!!minustoken {-}
+
+\def\__unknown__ {\string\\//} % unlikely value
+
+%D Variables are composed of a command specific tag and a user supplied variable
+%D (system constant). The tag \type {du} for instance is available as \type {\??du}
+%D and expands to \type {@@du} in composed variables.
+
+\definesystemvariable {du} % dummy, will stay
+
+% bibl:
+
+\definesystemvariable {pv} % PublicationVariable
+\definesystemvariable {pb} % PuBlication
+
+% needs checking (namespaces now)
+
+\definesystemvariable {fw} % simpleFonts by Wolfgang
+
+% old pragma
+
+\definesystemvariable {kt} % KonTakten
+\definesystemvariable {kw} % KontaktWaarde
+\definesystemvariable {st} % STickers
+\definesystemvariable {km} % KenMerk
+
+% mkii
+
+\definesystemvariable {xf} % XML File (xtag)
+\definesystemvariable {xp} % XML Processing (xtag, so still needed)
+\definesystemvariable {fo} % xml FO (xtag)
+\definesystemvariable {fx} % FoXet
+
+% mkiv
+
+%D Next we define some language independant one letter variables and keywords. We can
+%D actually make these system variables.
+
+\defineinterfaceconstant {x} {x}
+\defineinterfaceconstant {y} {y}
+\defineinterfaceconstant {w} {w}
+\defineinterfaceconstant {h} {h}
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {t} {t}
+
+\defineinterfaceconstant {a} {a} % can go
+\defineinterfaceconstant {b} {b} % can go
+\defineinterfaceconstant {c} {c} % can go
+\defineinterfaceconstant {d} {d} % can go
+\defineinterfaceconstant {e} {e} % can go
+\defineinterfaceconstant {f} {f} % can go
+
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {r} {r}
+\defineinterfaceconstant {g} {g}
+\defineinterfaceconstant {b} {b}
+\defineinterfaceconstant {c} {c}
+\defineinterfaceconstant {m} {m}
+\defineinterfaceconstant {y} {y}
+\defineinterfaceconstant {k} {k}
+\defineinterfaceconstant {a} {a} % alternative
+\defineinterfaceconstant {t} {t} % transparency
+\defineinterfaceconstant {p} {p} % percentage
+\defineinterfaceconstant {h} {h}
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {v} {v}
+
+\defineinterfaceconstant {rgb} {rgb}
+\defineinterfaceconstant {cmyk} {cmyk}
+\defineinterfaceconstant {mp} {mp}
+
+\defineinterfacevariable {rgb} {rgb}
+\defineinterfacevariable {cmyk} {cmyk}
+\defineinterfacevariable {mp} {mp}
+
+\defineinterfacevariable {s} {s}
+
+\defineinterfacevariable {a} {a}
+\defineinterfacevariable {b} {b}
+\defineinterfacevariable {c} {c}
+\defineinterfacevariable {d} {d}
+
+%D For tagging:
+
+\definesystemconstant {subtype}
+\definesystemconstant {top}
+\definesystemconstant {bottom}
+\definesystemconstant {both}
+
+%D Special purpose variables:
+
+\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi}
+
+%D The names of files and their extensions are fixed. \CONTEXT\ uses as less
+%D files as possible. Utility files can be recognized by the first two
+%D characters of the extension: \type {tu}.
+
+%definefileconstant {utilityfilename} {texutil}
+%definefileconstant {blockextension} {tub}
+%definefileconstant {figureextension} {tuf}
+%definefileconstant {inputextension} {tui}
+%definefileconstant {outputextension} {tuo} % tup for previous run
+%definefileconstant {optionextension} {top}
+%definefileconstant {temporaryextension} {tmp}
+%definefileconstant {patternsextension} {pat}
+%definefileconstant {hyphensextension} {hyp}
+%definefileconstant {fontmapextension} {map}
+\definefileconstant {bibextension} {bbl}
+
+%D These files are loaded at start||up. They may contain system specific setups (or
+%D calls to other files), old macro's, to garantee compatibility and new macro's noy
+%D yet present in the format.
+
+\definefileconstant {sysfilename} {cont-sys.mkiv}
+\definefileconstant {newfilename} {cont-new.mkiv}
+\definefileconstant {locfilename} {cont-loc.mkiv}
+\definefileconstant {expfilename} {cont-exp.mkiv}
+\definefileconstant {fntfilename} {cont-fnt.mkiv} % not yet used
+\definefileconstant {gdsfilename} {cont-fnt.lfg} % not yet used
+
+%D The setup files for the language, font, color and special subsystems have a common
+%D prefix. This means that we have at most three characters for unique filenames.
+
+\definefileconstant {colorprefix} {colo-}
+%definefileconstant {encodingprefix} {enco-}
+%definefileconstant {filterprefix} {filt-}
+\definefileconstant {fontprefix} {font-}
+%definefileconstant {handlingprefix} {hand-}
+%definefileconstant {javascriptprefix} {java-}
+%definefileconstant {languageprefix} {lang-}
+%definefileconstant {mathprefix} {math-}
+%definefileconstant {metapostprefix} {meta-}
+%definefileconstant {regimeprefix} {regi-}
+%definefileconstant {specialprefix} {spec-}
+\definefileconstant {symbolprefix} {symb-}
+\definefileconstant {typeprefix} {type-}
+%definefileconstant {xtagprefix} {xtag-}
+%definefileconstant {propprefix} {prop-}
+%definefileconstant {unicprefix} {unic-}
+%definefileconstant {sortprefix} {sort-}
+%definefileconstant {prettyprefix} {pret-}
+
+%definefileconstant {moduleprefix} {m-}
+%definefileconstant {styleprefix} {s-}
+%definefileconstant {xstyleprefix} {x-}
+%definefileconstant {privateprefix} {p-}
+%definefileconstant {thirdprefix} {t-}
+
+%definefileconstant {beforeprefix} {b-}
+%definefileconstant {afterprefix} {a-}
+
+% for old times sake:
+
+% \defineinterfaceconstant {x} {x}
+% \defineinterfaceconstant {xx} {xx}
+% \defineinterfaceconstant {em} {em} % will go
+
+% \defineinterfaceconstant {tf} {tf}
+% \defineinterfaceconstant {bf} {bf}
+% \defineinterfaceconstant {bs} {bs}
+% \defineinterfaceconstant {bi} {bi}
+% \defineinterfaceconstant {sl} {sl}
+% \defineinterfaceconstant {it} {it}
+% \defineinterfaceconstant {sc} {sc} % keep, used elsewhere (or define in mult-def)
+
+%D For figure inclusion we need(ed):
+
+%defineinterfaceconstant {tif} {tif}
+%defineinterfaceconstant {eps} {eps}
+%defineinterfaceconstant {mps} {mps}
+%defineinterfaceconstant {jpg} {jpg}
+%defineinterfaceconstant {pdf} {pdf}
+%defineinterfaceconstant {png} {png}
+%defineinterfaceconstant {avi} {avi}
+%defineinterfaceconstant {mov} {mov}
+%defineinterfaceconstant {svg} {svg}
+\defineinterfaceconstant {tex} {tex} % Also gone?
+%defineinterfaceconstant {tmp} {tmp}
+%defineinterfaceconstant {cld} {cld}
+
+%D A careful reader will have noticed that in the module \type {mult-ini} we defined
+%D \type {\selectinterface}. We were not yet able to actually select an interface,
+%D because we still had to define the constants and variables. Now we've done so,
+%D selection is permitted.
+
+\selectinterface
+
+%D Ok, here are some more, because we've got ouselves some extensions to \CONTEXT.
+
+\definemessageconstant {addresses}
+\definemessageconstant {documents}
+
+%D Nicer than being undefined:
+
+\let\p_align \empty
+\let\p_aligntitle\empty
+\let\p_continue \empty
+\let\p_footer \empty
+\let\p_label \empty
+\let\p_number \empty
+\let\p_page \empty
+\let\p_state \empty
+\let\p_strut \empty
+\let\p_text \empty
+\let\p_tolerance \empty
+
+% more will follow
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua b/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua
new file mode 100644
index 00000000000..ed34dbec939
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua
@@ -0,0 +1,178 @@
+if not modules then modules = { } end modules ['node-acc'] = {
+ 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 nodes, node = nodes, node
+
+local nodecodes = nodes.nodecodes
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local getid = nuts.getid
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local getlist = nuts.getlist
+local getchar = nuts.getchar
+local getnext = nuts.getnext
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setchar = nuts.setchar
+local setsubtype = nuts.setsubtype
+
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+local copy_node = nuts.copy
+local free_nodelist = nuts.flush_list
+local insert_after = nuts.insert_after
+
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local a_characters = attributes.private("characters")
+
+local threshold = 65536 -- not used
+local nofreplaced = 0
+
+-- todo: nbsp etc
+-- todo: collapse kerns
+
+-- p_id
+
+local function injectspaces(head)
+ local p, p_id
+ local n = head
+ while n do
+ local id = getid(n)
+ if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0)
+ -- if getfield(n,."width") > 0 then -- threshold
+ -- if p and p_id == glyph_code then
+ if p and getid(p) == glyph_code then
+ local g = copy_node(p)
+ local c = getfield(g,"components")
+ if c then -- it happens that we copied a ligature
+ free_nodelist(c)
+ setfield(g,"components",nil)
+ setsubtype(g,256)
+ end
+ local a = getattr(n,a_characters)
+ setchar(g,32)
+ setlink(p,g)
+ setlink(g,n)
+-- we could cache as we now create many nodes
+ setfield(n,"width",getfield(n,"width") - getfield(g,"width"))
+ if a then
+ setattr(g,a_characters,a)
+ end
+ setattr(n,a_characters,0)
+ nofreplaced = nofreplaced + 1
+ end
+ -- end
+ elseif id == hlist_code or id == vlist_code then
+ injectspaces(getlist(n),attribute)
+ -- elseif id == kern_code then -- the backend already collapses
+ -- local first = n
+ -- while true do
+ -- local nn = getnext(n)
+ -- if nn and getid(nn) == kern_code then
+ -- -- maybe we should delete kerns but who cares at this stage
+ -- setfield(first,"kern",getfield(first,"kern") + getfield(nn,"kern")
+ -- setfield(nn,"kern",0)
+ -- n = nn
+ -- else
+ -- break
+ -- end
+ -- end
+ end
+ p_id = id
+ p = n
+ n = getnext(n)
+ end
+ return head, true -- always done anyway
+end
+
+nodes.handlers.accessibility = function(head)
+ local head, done = injectspaces(tonut(head))
+ return tonode(head), done
+end
+
+statistics.register("inserted spaces in output",function()
+ if nofreplaced > 0 then
+ return nofreplaced
+ end
+end)
+
+-- todo:
+
+-- local a_hyphenated = attributes.private('hyphenated')
+--
+-- local hyphenated, codes = { }, { }
+--
+-- local function compact(n)
+-- local t = { }
+-- for n in traverse_id(glyph_code,n) do
+-- t[#t+1] = utfchar(getchar(n)) -- check for unicode
+-- end
+-- return concat(t,"")
+-- end
+--
+-- local function injectspans(head)
+-- local done = false
+-- for n in traverse_nodes(tonuts(head)) do
+-- local id = getid(n)
+-- if id == disc then
+-- local r = getfield(n,"replace")
+-- local p = getfield(n,"pre")
+-- if r and p then
+-- local str = compact(r)
+-- local hsh = hyphenated[str]
+-- if not hsh then
+-- hsh = #codes + 1
+-- hyphenated[str] = hsh
+-- codes[hsh] = str
+-- end
+-- setattr(n,a_hyphenated,hsh)
+-- done = true
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- injectspans(getlist(n))
+-- end
+-- end
+-- return tonodes(head), done
+-- end
+--
+-- nodes.injectspans = injectspans
+--
+-- tasks.appendaction("processors", "words", "nodes.injectspans")
+--
+-- local function injectspans(head)
+-- local done = false
+-- for n in traverse_nodes(tonut(head)) do
+-- local id = getid(n)
+-- if id == disc then
+-- local a = getattr(n,a_hyphenated)
+-- if a then
+-- local str = codes[a]
+-- local b = new_pdfliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str)))
+-- local e = new_pdfliteral("EMC")
+-- insert_before(head,n,b)
+-- insert_after(head,n,e)
+-- done = true
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- injectspans(getlist(n))
+-- end
+-- end
+-- return tonodes(head), done
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua
new file mode 100644
index 00000000000..ebe113fc67a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua
@@ -0,0 +1,563 @@
+if not modules then modules = { } end modules ['node-aux'] = {
+ 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"
+}
+
+-- todo: n1 .. n2 : __concat metatable
+
+local type, tostring = type, tostring
+
+local nodes, node = nodes, node
+
+local utfvalues = utf.values
+
+local nodecodes = nodes.nodecodes
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local attributelist_code = nodecodes.attributelist -- temporary
+local math_code = nodecodes.math
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local vianuts = nuts.vianuts
+
+local getbox = nuts.getbox
+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 getfield = nuts.getfield
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+local free_node = nuts.free
+local hpack_nodes = nuts.hpack
+local unset_attribute = nuts.unset_attribute
+local first_glyph = nuts.first_glyph
+local copy_node = nuts.copy
+local copy_node_list = nuts.copy_list
+local find_tail = nuts.tail
+local insert_node_after = nuts.insert_after
+local isnode = nuts.is_node
+local getbox = nuts.getbox
+
+local nodes_traverse_id = nodes.traverse_id
+local nodes_first_glyph = nodes.first_glyph
+
+local nodepool = nuts.pool
+local new_glue = nodepool.glue
+local new_glyph = nodepool.glyph
+
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local texsetbox = tex.setbox
+
+local report_error = logs.reporter("node-aux:error")
+
+-- At some point we figured that copying before using was the safest bet
+-- when dealing with boxes at the tex end. This is because tex also needs
+-- to manage the grouping (i.e. savestack). However, there is an easy
+-- solution that keeps the tex end happy as tex.setbox deals with this. The
+-- overhead of one temporary list node is neglectable.
+--
+-- function tex.takebox(id)
+-- local box = tex.getbox(id)
+-- if box then
+-- local copy = node.copy(box)
+-- local list = box.list
+-- copy.list = list
+-- box.list = nil
+-- tex.setbox(id,nil)
+-- return copy
+-- end
+-- end
+
+local function takebox(id)
+ local box = getbox(id)
+ if box then
+ local copy = copy_node(box)
+ local list = getlist(box)
+ if list then
+ setlist(copy,list)
+ setlist(box,nil)
+ end
+ texsetbox(id,nil)
+ return copy
+ end
+end
+
+function nodes.takebox(id)
+ local b = takebox(id)
+ if b then
+ return tonode(b)
+ end
+end
+
+local splitbox = tex.splitbox
+nodes.splitbox = splitbox
+
+function nuts.splitbox(id,height)
+ return tonut(splitbox(id,height))
+end
+
+-- function nodes.takelist(n)
+-- -- when we need it
+-- end
+
+function nuts.takelist(n)
+ local l = getlist(n)
+ setlist(n)
+ free_node(n)
+ return l
+end
+
+nuts.takebox = takebox
+tex.takebox = nodes.takebox -- sometimes more clear
+
+-- so far
+
+local function repackhlist(list,...)
+ local temp, b = hpack_nodes(list,...)
+ list = getlist(temp)
+ setlist(temp)
+ free_node(temp)
+ return list, b
+end
+
+nuts.repackhlist = repackhlist
+
+function nodes.repackhlist(list,...)
+ local list, b = repackhlist(tonut(list),...)
+ return tonode(list), b
+end
+
+local function set_attributes(head,attr,value)
+ for n in traverse_nodes(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
+ end
+end
+
+local function set_unset_attributes(head,attr,value)
+ for n in traverse_nodes(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
+ end
+end
+
+local function unset_attributes(head,attr)
+ for n in traverse_nodes(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
+ end
+end
+
+-- for old times sake
+
+nuts.setattribute = nuts.setattr nodes.setattribute = nodes.setattr
+nuts.getattribute = nuts.getattr nodes.getattribute = nodes.getattr
+nuts.unsetattribute = nuts.unset_attribute nodes.unsetattribute = nodes.unset_attribute
+nuts.has_attribute = nuts.has_attribute nodes.has_attribute = nodes.has_attribute
+nuts.firstglyph = nuts.first_glyph nodes.firstglyph = nodes.first_glyph
+
+nuts.setattributes = set_attributes nodes.setattributes = vianuts(set_attributes)
+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
+--
+-- if not node.end_of_math then
+-- function node.end_of_math(n)
+-- for n in traverse_id(math_code,getnext(next)) do
+-- return n
+-- end
+-- end
+-- end
+--
+-- nodes.endofmath = node.end_of_math
+--
+-- 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
+ return g
+ end
+ end
+end
+
+-- function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255
+-- if untagged then
+-- return nodes_first_glyph(n)
+-- else
+-- for g in nodes_traverse_id(glyph_code,n) do
+-- return g
+-- end
+-- end
+-- 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)
+ end
+ end
+ return 0
+end
+
+nuts .firstcharinbox = firstcharinbox
+nodes.firstcharinbox = firstcharinbox -- hm, ok ?
+nodes.firstcharacter = vianuts(firstcharacter)
+
+interfaces.implement {
+ name = "buildtextaccent",
+ arguments = "integer",
+ actions = function(n) -- Is this crap really used? Or was it an experiment?
+ local char = firstcharinbox(n)
+ if char > 0 then
+ -- context.accent(false,char)
+ context([[\accent%s\relax]],char)
+ end
+ end
+}
+
+-- this depends on fonts, so we have a funny dependency ... will be
+-- sorted out .. we could make tonodes a plugin into this
+
+local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-ini
+ if not str or str == "" then
+ return
+ end
+ local head, tail, space, fnt, template = nil, nil, nil, nil, nil
+ if not fnt then
+ fnt = current_font()
+ elseif type(fnt) ~= "number" and getid(fnt) == glyph_code then -- so it has to be a real node
+ fnt, template = nil, tonut(fnt)
+ end
+ for s in utfvalues(str) do
+ local n
+ if s == 32 then
+ if space then
+ n = copy_node(space)
+ elseif fonts then -- depedency
+ local parameters = fonts.hashes.identifiers[fnt].parameters
+ space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink)
+ n = space
+ end
+ elseif template then
+ n = copy_node(template)
+ setvalue(n,"char",s)
+ else
+ n = new_glyph(fnt,s)
+ end
+ if attr then -- normally false when template
+ -- setfield(n,"attr",copy_node_list(attr))
+ setfield(n,"attr",attr)
+ end
+ if head then
+ insert_node_after(head,tail,n)
+ else
+ head = n
+ end
+ tail = n
+ end
+ return head, tail
+end
+
+nuts.tonodes = tonodes
+
+nodes.tonodes = function(str,fnt,attr)
+ local head, tail = tonodes(str,fnt,attr)
+ return tonode(head), tonode(tail)
+end
+
+-- local function link(list,currentfont,currentattr,head,tail)
+-- for i=1,#list do
+-- local n = list[i]
+-- if n then
+-- local tn = isnode(n)
+-- if not tn then
+-- local tn = type(n)
+-- if tn == "number" then
+-- if not currentfont then
+-- currentfont = current_font()
+-- end
+-- local h, t = tonodes(tostring(n),currentfont,currentattr)
+-- if not h then
+-- -- skip
+-- elseif not head then
+-- head = h
+-- tail = t
+-- else
+-- setfield(tail,"next",h)
+-- setfield(h,"prev",t)
+-- tail = t
+-- end
+-- elseif tn == "string" then
+-- if #tn > 0 then
+-- if not currentfont then
+-- currentfont = current_font()
+-- end
+-- local h, t = tonodes(n,currentfont,currentattr)
+-- if not h then
+-- -- skip
+-- elseif not head then
+-- head, tail = h, t
+-- else
+-- setfield(tail,"next",h)
+-- setfield(h,"prev",t)
+-- tail = t
+-- end
+-- end
+-- elseif tn == "table" then
+-- if #tn > 0 then
+-- if not currentfont then
+-- currentfont = current_font()
+-- end
+-- head, tail = link(n,currentfont,currentattr,head,tail)
+-- end
+-- end
+-- elseif not head then
+-- head = n
+-- tail = find_tail(n)
+-- elseif getid(n) == attributelist_code then
+-- -- weird case
+-- report_error("weird node type in list at index %s:",i)
+-- for i=1,#list do
+-- local l = list[i]
+-- report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l)
+-- end
+-- os.exit()
+-- else
+-- setfield(tail,"next",n)
+-- setfield(n,"prev",tail)
+-- if getnext(n) then
+-- tail = find_tail(n)
+-- else
+-- tail = n
+-- end
+-- end
+-- else
+-- -- permitting nil is convenient
+-- end
+-- end
+-- return head, tail
+-- end
+
+local function link(list,currentfont,currentattr,head,tail) -- an oldie, might be replaced
+ for i=1,#list do
+ local n = list[i]
+ if n then
+ local tn = type(n)
+ if tn == "string" then
+ if #tn > 0 then
+ if not currentfont then
+ currentfont = current_font()
+ end
+ local h, t = tonodes(n,currentfont,currentattr)
+ if not h then
+ -- skip
+ elseif not head then
+ head, tail = h, t
+ else
+ setnext(tail,h)
+ setprev(h,t)
+ tail = t
+ end
+ end
+ elseif tn == "table" then
+ if #tn > 0 then
+ if not currentfont then
+ currentfont = current_font()
+ end
+ head, tail = link(n,currentfont,currentattr,head,tail)
+ end
+ elseif not head then
+ head = n
+ tail = find_tail(n)
+ elseif getid(n) == attributelist_code then
+ -- weird case
+ report_error("weird node type in list at index %s:",i)
+ for i=1,#list do
+ local l = list[i]
+ report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l)
+ end
+ os.exit()
+ else
+ setlink(tail,n)
+ if getnext(n) then
+ tail = find_tail(n)
+ else
+ tail = n
+ end
+ end
+ else
+ -- permitting nil is convenient
+ end
+ end
+ return head, tail
+end
+
+nuts.link = link
+
+nodes.link = function(list,currentfont,currentattr,head,tail)
+ local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail))
+ return tonode(head), tonode(tail)
+end
+
+local function locate(start,wantedid,wantedsubtype)
+ for n in traverse_nodes(start) do
+ local id = getid(n)
+ if id == wantedid then
+ if not wantedsubtype or getsubtype(n) == wantedsubtype then
+ return n
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local found = locate(getlist(n),wantedid,wantedsubtype)
+ if found then
+ return found
+ end
+ end
+ end
+end
+
+nuts.locate = locate
+
+function nodes.locate(start,wantedid,wantedsubtype)
+ local found = locate(tonut(start),wantedid,wantedsubtype)
+ return found and tonode(found)
+end
+
+-- I have no use for this yet:
+--
+-- \skip0=10pt plus 2pt minus 2pt
+-- \cldcontext{"\letterpercent p",tex.stretch_amount(tex.skip[0],1000)} -- 14.30887pt
+--
+-- local gluespec_code = nodes.nodecodes.gluespec
+--
+-- function tex.badness_to_ratio(badness)
+-- return (badness/100)^(1/3)
+-- end
+--
+-- function tex.stretch_amount(skip,badness) -- node no nut
+-- if skip.id == gluespec_code then
+-- return skip.width + (badness and (badness/100)^(1/3) or 1) * skip.stretch
+-- else
+-- return 0
+-- end
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua b/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua
new file mode 100644
index 00000000000..a095ac4c4d5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua
@@ -0,0 +1,194 @@
+if not modules then modules = { } end modules ['node-bck'] = {
+ version = 1.001,
+ comment = "companion to node-bck.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware, this one takes quite some runtime, so we need a status flag
+-- maybe some page related state
+
+local attributes, nodes, node = attributes, nodes, node
+
+local tasks = nodes.tasks
+
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local cell_code = listcodes.cell
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+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 setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+
+local traverse = nuts.traverse
+local traverse_id = nuts.traverse_id
+
+local new_rule = nodepool.rule
+local new_glue = nodepool.glue
+
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+local a_background = attributes.private('background')
+local a_alignbackground = attributes.private('alignbackground')
+
+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
+ end
+ local width = getfield(current,"width")
+ if width > 0 then
+ local background = getattr(current,a_background)
+ if background then
+ -- direct to hbox
+ -- colorspace is already set so we can omit that and stick to color
+ local mode = getattr(current,a_colorspace)
+ if mode then
+ local height = getfield(current,"height")
+ local depth = getfield(current,"depth")
+ 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_colorspace,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
+ end
+ end
+ current = getnext(current)
+ end
+ return head, true
+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
+ end
+ break
+ end
+ --
+ if background then
+ -- current has subtype 5 (cell)
+ local width = getfield(current,"width")
+ if width > 0 then
+ local mode = getattr(found,a_colorspace)
+ if mode then
+ local glue = new_glue(-width)
+ local rule = new_rule(width,getfield(current,"height"),getfield(current,"depth"))
+ local color = getattr(found,a_color)
+ local transparency = getattr(found,a_transparency)
+ setattr(rule,a_colorspace,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
+ end
+ else
+ add_alignbackgrounds(list)
+ end
+ elseif id == vlist_code then
+ local list = getlist(current)
+ if list then
+ add_alignbackgrounds(list)
+ end
+ end
+ current = getnext(current)
+ end
+ return head, true
+end
+
+-- nodes.handlers.backgrounds = add_backgrounds
+-- nodes.handlers.alignbackgrounds = add_alignbackgrounds
+
+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
+
+-- elsewhere: needs checking
+
+-- tasks.appendaction("shipouts","normalizers","nodes.handlers.backgrounds")
+-- tasks.appendaction("shipouts","normalizers","nodes.handlers.alignbackgrounds")
+
+interfaces.implement {
+ name = "enablebackgroundboxes",
+ onlyonce = true,
+ actions = nodes.tasks.enableaction,
+ arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
+}
+
+interfaces.implement {
+ name = "enablebackgroundalign",
+ onlyonce = true,
+ actions = nodes.tasks.enableaction,
+ arguments = { "'shipouts'", "'nodes.handlers.alignbackgrounds'" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv
new file mode 100644
index 00000000000..58edab6685c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=node-bck,
+%D version=2009.06.08,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Support / Backgrounds}
+
+%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}{1.001}
+
+% \backgroundvbox[green] {\input tufte } \par
+% \backgroundvbox[blue] {\input ward } \par
+% \backgroundvbox[red] {\input knuth } \par
+% \backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par
+
+\def\colorattr#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \node_backgrounds_thecolorattr{\currentcolorprefix#1}%
+ \else\ifcsname\??colorattribute#1\endcsname
+ \node_backgrounds_thecolorattr{#1}%
+ \fi\fi}
+
+\def\node_backgrounds_thecolorattr#1%
+ {attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \lastnamedcs
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\def\thecolorattr#1%
+ {attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \csname\??colorattribute#1\endcsname
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\def\backgroundcolorattr#1%
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \node_backgrounds_thebackgroundcolorattr{\currentcolorprefix#1}%
+ \else\ifcsname\??colorattribute#1\endcsname
+ \node_backgrounds_thebackgroundcolorattr{#1}%
+ \fi\fi}
+
+\def\thebackgroundcolorattr#1%
+ {attr \backgroundattribute \plusone
+ attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \csname\??colorattribute#1\endcsname
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\def\node_backgrounds_thebackgroundcolorattr#1%
+ {attr \backgroundattribute \plusone
+ attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \lastnamedcs
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\def\thealignbackgroundcolorattr#1%
+ {attr \alignbackgroundattribute \plusone
+ attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \csname\??colorattribute#1\endcsname
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\unexpanded\def\backgroundhbox{\node_backgrounds_boxes_add\hbox}
+\unexpanded\def\backgroundvbox{\node_backgrounds_boxes_add\vbox}
+\unexpanded\def\backgroundvtop{\node_backgrounds_boxes_add\vtop}
+
+% \def\node_backgrounds_boxes_add#1[#2]%
+% {\begingroup
+% \clf_enablebackgroundboxes
+% \dousecolorparameter{#2}%
+% \normalexpanded{\endgroup#1
+% attr \backgroundattribute \plusone
+% attr \colormodelattribute \the\attribute\colormodelattribute
+% attr \colorattribute \the\attribute\colorattribute
+% attr \transparencyattribute \the\attribute\transparencyattribute}}
+%
+% more efficient:
+
+\def\node_backgrounds_boxes_add#1[#2]%
+ {\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/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua
new file mode 100644
index 00000000000..6ee5cd4b860
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua
@@ -0,0 +1,309 @@
+if not modules then modules = { } end modules ['node-dir'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Taco Hoekwater and Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ 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 {
+ -- TLT = false,
+ -- TRT = false,
+ -- LTL = false,
+ RTT = true, ["+RTT"] = true,
+}
+
+nodes.textdir_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_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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ ["-TRT"] = true,
+ ["-TLT"] = true,
+ ["-LTL"] = true,
+ ["-RTT"] = true,
+}
+
+nodes.dir_negation = allocate {
+ ["-TRT"] = "+TRT",
+ ["-TLT"] = "+TLT",
+ ["-LTL"] = "+LTL",
+ ["-RTT"] = "+RTT",
+ ["+TRT"] = "-TRT",
+ ["+TLT"] = "-TLT",
+ ["+LTL"] = "-LTL",
+ ["+RTT"] = "-RTT",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ext.lua
new file mode 100644
index 00000000000..82ec04ee592
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ext.lua
@@ -0,0 +1,30 @@
+if not modules then modules = { } end modules ['node-ext'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Serializing nodes can be handy for tracing. Also, saving and
+loading node lists can come in handy as soon we are going to
+use external applications to process node lists.</p>
+--ldx]]--
+
+function nodes.show(stack)
+-- logs.writer(table.serialize(stack))
+end
+
+function nodes.save(stack,name) -- *.ltn : luatex node file
+-- if name then
+-- file.savedata(name,table.serialize(stack))
+-- else
+-- logs.writer(table.serialize(stack))
+-- end
+end
+
+function nodes.load(name)
+-- return file.loaddata(name)
+-- -- todo
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
new file mode 100644
index 00000000000..a2d63d38d45
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
@@ -0,0 +1,641 @@
+if not modules then modules = { } end modules ['node-fin'] = {
+ version = 1.001,
+ comment = "companion to node-fin.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- this module is being reconstructed
+-- local functions, only slightly slower
+--
+-- leaders are also triggers ... see colo-ext for an example (negate a box)
+
+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 getfield = nuts.getfield
+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 setlist = nuts.setlist
+local setleader = nuts.setleader
+
+local copy_node = nuts.copy
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+
+local nodecodes = nodes.nodecodes
+local whatcodes = nodes.whatcodes
+local rulecodes = nodes.rulecodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local rule_code = nodecodes.rule
+local whatsit_code = nodecodes.whatsit
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local normal_rule = rulecodes.normal
+
+local states = attributes.states
+local numbers = attributes.numbers
+local a_trigger = attributes.private('trigger')
+local triggering = false
+
+local implement = interfaces.implement
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local loadstripped = utilities.lua.loadstripped
+local unsetvalue = attributes.unsetvalue
+
+-- these two will be like trackers
+
+function states.enabletriggering () triggering = true end
+function states.disabletriggering() triggering = false end
+
+implement { name = "enablestatetriggering", actions = states.enabletriggering }
+implement { name = "disablestatetriggering", actions = states.disabletriggering }
+
+nodes.plugindata = nil
+
+-- inheritance: -0x7FFFFFFF -- we can best use nil and skip !
+
+local template = [[
+local plugin = nodes.plugindata
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local namespace = plugin.namespace
+local attribute = namespace.attribute or attributes.numbers[plugin.name]
+local processor = plugin.processor
+local initializer = plugin.initializer
+local resolver = plugin.resolver
+local finalizer = plugin.finalizer
+local flusher = plugin.flusher
+if not processor then
+ return function(head)
+ return head, false
+ end
+elseif initializer or finalizer or resolver then
+ return function(head)
+ starttiming(attributes)
+ local done, used, ok, inheritance = false, nil, false, nil
+ 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
+ end
+ done = true
+ end
+ stoptiming(attributes)
+ return head, done
+ end
+else
+ return function(head)
+ starttiming(attributes)
+ local head, done = processor(namespace,attribute,head)
+ stoptiming(attributes)
+ return head, done
+ end
+end
+nodes.plugindata = nil
+]]
+
+function nodes.installattributehandler(plugin)
+ nodes.plugindata = plugin
+ return loadstripped(template)()
+end
+
+-- for the moment:
+
+local function copied(n)
+ return copy_node(tonut(n))
+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 nsbegin, nsend, nsreset
+
+function states.initialize(namespace,attribute,head)
+ nsdata = namespace.data
+ nsnone = namespace.none
+ nsforced = namespace.forced
+ nsselector = namespace.selector
+ nslistwise = namespace.listwise
+ 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
+ nsbegin = namespace.resolve_begin
+ nsend = namespace.resolve_end
+ nspush = namespace.push
+ nspop = namespace.pop
+ end
+end
+
+function states.finalize(namespace,attribute,head) -- is this one ok?
+ 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)
+ if content then
+ local list = insert_node_before(content,content,copied(nsnone)) -- two return values
+ if list ~= content then
+ setlist(head,list)
+ end
+ end
+ else
+ head = insert_node_before(head,head,copied(nsnone))
+ end
+ return tonode(head), true, true
+ end
+ return head, false, false
+end
+
+-- we need to deal with literals too (reset as well as oval)
+-- if id == glyph_code or (id == whatsit_code and getsubtype(stack) == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then
+
+local function process(namespace,attribute,head,inheritance,default) -- one attribute
+ local stack = head
+ local done = false
+ local check = false
+ local leader = nil
+ while stack do
+ local id = getid(stack)
+ if id == glyph_code then
+ check = true
+ elseif id == disc_code then
+ check = true -- no longer needed as we flatten replace
+ elseif id == glue_code then
+ leader = getleader(stack)
+ if leader then
+ check = true
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local content = getlist(stack)
+ if content then
+ -- begin nested --
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
+ if outer ~= inheritance then
+ local list, ok = process(namespace,attribute,content,inheritance,outer)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ else
+ local list, ok = process(namespace,attribute,content,inheritance,default)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = process(namespace,attribute,content,inheritance,default)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ end
+ -- end nested --
+ end
+ elseif id == rule_code then
+-- if subtype(stack) == normal_rule then
+ check = getfield(stack,"width") ~= 0
+-- end
+ end
+ -- much faster this way than using a check() and nested() function
+ if check then
+ local c = getattr(stack,attribute)
+ if c then
+ if default and c == inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copied(nsdata[default]))
+ current = default
+ done = true
+ end
+ elseif current ~= c then
+ head = insert_node_before(head,stack,copied(nsdata[c]))
+ current = c
+ done = true
+ end
+ if leader then
+ local savedcurrent = current
+ local ci = getid(leader)
+ if ci == hlist_code or ci == vlist_code then
+ -- else we reset inside a box unneeded, okay, the downside is
+ -- that we trigger color in each repeated box, so there is room
+ -- for improvement here
+ current = 0
+ end
+ -- begin nested --
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
+ if outer ~= inheritance then
+ local list, ok = process(namespace,attribute,leader,inheritance,outer)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ else
+ local list, ok = process(namespace,attribute,leader,inheritance,default)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = process(namespace,attribute,leader,inheritance,default)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ end
+ -- end nested --
+ current = savedcurrent
+ leader = false
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copied(nsdata[default]))
+ current = default
+ done = true
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copied(nsnone))
+ current = 0
+ done = true
+ end
+ check = false
+ end
+ stack = getnext(stack)
+ end
+ return head, done
+end
+
+states.process = function(namespace,attribute,head,default)
+ local head, done = process(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
+
+-- we can force a selector, e.g. document wide color spaces, saves a little
+-- watch out, we need to check both the selector state (like colorspace) and
+-- the main state (like color), otherwise we get into troubles when a selector
+-- state changes while the main state stays the same (like two glyphs following
+-- each other with the same color but different color spaces e.g. \showcolor)
+
+local function selective(namespace,attribute,head,inheritance,default) -- two attributes
+ local stack = head
+ local done = false
+ local check = false
+ local leader = nil
+ while stack do
+ local id = getid(stack)
+ if id == glyph_code then
+ check = true
+ elseif id == disc_code then
+ check = true -- notneeded when we flatten replace
+ elseif id == glue_code then
+ leader = getleader(stack)
+ if leader then
+ check = true
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local content = getlist(stack)
+ if content then
+ -- begin nested
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
+ if outer ~= inheritance then
+ local list, ok = selective(namespace,attribute,content,inheritance,outer)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ else
+ local list, ok = selective(namespace,attribute,content,inheritance,default)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = selective(namespace,attribute,content,inheritance,default)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = done or ok
+ end
+ -- end nested
+ end
+ elseif id == rule_code then
+-- if subtype(stack) == normal_rule then
+ check = getfield(stack,"width") ~= 0
+-- end
+ end
+
+ if check then
+ local c = getattr(stack,attribute)
+ if c then
+ if default and c == inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ current = default
+ done = true
+ end
+ else
+ local s = getattr(stack,nsselector)
+ if current ~= c or current_selector ~= s then
+ local data = nsdata[c]
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ current = c
+ current_selector = s
+ done = true
+ end
+ end
+ if leader then
+ -- begin nested
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getatribute(stack,attribute)
+ if outer ~= inheritance then
+ local list, ok = selective(namespace,attribute,leader,inheritance,outer)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ else
+ local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ done = done or ok
+ end
+ -- end nested
+ leader = false
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ current = default
+ done = true
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copied(nsnone))
+ current, current_selector, done = 0, 0, true
+ end
+ check = false
+ end
+ stack = getnext(stack)
+ end
+ return head, done
+end
+
+states.selective = function(namespace,attribute,head,default)
+ local head, done = selective(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
+
+-- Ideally the next one should be merged with the previous but keeping it separate is
+-- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers
+-- (as used in the stepper). In the stepper we cannot use the box branch as it involves
+-- paragraph lines and then gets mixed up. A messy business (esp since we want to be
+-- efficient).
+--
+-- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not
+-- entirely trivial and a generic solution is nicer (compares to the exporter).
+
+local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+ local stack = head
+ local done = false
+ local current = default or 0
+ local depth = 0
+ local check = false
+ local leader = false
+ while stack do
+ local id = getid(stack)
+ if id == glyph_code then
+ check = true
+ elseif id == glue_code then
+ leader = getleader(stack)
+ if leader then
+ check = true
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local content = getlist(stack)
+ if content then
+ -- the problem is that broken lines gets the attribute which can be a later one
+ 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,copied(nsdata[a]))
+ local list = stacked(namespace,attribute,content,current) -- two return values
+ if content ~= list then
+ setlist(stack,list)
+ end
+ done = true
+ head, stack = insert_node_after(head,stack,copied(nsnone))
+ current = p
+ else
+ local list, ok = stacked(namespace,attribute,content,current)
+ if content ~= list then
+ setlist(stack,list) -- only if ok
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = stacked(namespace,attribute,content,current)
+ if content ~= list then
+ setlist(stack,list) -- only if ok
+ end
+ done = done or ok
+ end
+ end
+ elseif id == rule_code then
+-- if subtype(stack) == normal_rule then
+ check = getfield(stack,"width") ~= 0
+-- end
+ end
+
+ if check then
+ local a = getattr(stack,attribute)
+ if a then
+ if current ~= a then
+ head = insert_node_before(head,stack,copied(nsdata[a]))
+ depth = depth + 1
+ current, done = a, true
+ end
+ if leader then
+ local list, ok = stacked(namespace,attribute,content,current)
+ if leader ~= list then
+ setleader(stack,list) -- only if ok
+ end
+ done = done or ok
+ leader = false
+ end
+ elseif default > 0 then
+ --
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copied(nsnone))
+ depth = depth - 1
+ current, done = 0, true
+ end
+ check = false
+ end
+ stack = getnext(stack)
+ end
+ while depth > 0 do
+ head = insert_node_after(head,stack,copied(nsnone))
+ depth = depth - 1
+ end
+ return head, done
+end
+
+states.stacked = function(namespace,attribute,head,default)
+ local head, done = stacked(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
+
+-- experimental
+
+local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+
+-- nsbegin()
+ local stacked = false
+
+ local current = head
+ local previous = head
+ local done = false
+ local attrib = default or unsetvalue
+ local check = false
+ local leader = false
+
+ while current do
+ local id = getid(current)
+ 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 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,copied(nsdata[a]))
+ local list = stacker(namespace,attribute,content,a)
+ if list ~= content then
+ setlist(current,list)
+ end
+ done = true
+ head, current = insert_node_after(head,current,copied(nsnone))
+ else
+ local list, ok = stacker(namespace,attribute,content,attrib)
+ if content ~= list then
+ setlist(current,list)
+ end
+ done = done or ok
+ end
+ else
+ local list, ok = stacker(namespace,attribute,content,default)
+ if list ~= content then
+ setlist(current,list)
+ end
+ done = done or ok
+ end
+ elseif id == rule_code then
+-- if subtype(stack) == normal_rule then
+ check = getfield(current,"width") ~= 0
+-- end
+ 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,tonut(n)) -- a
+ end
+ attrib, done = a, true
+ if leader then
+ -- tricky as a leader has to be a list so we cannot inject before
+ local list, ok = stacker(namespace,attribute,leader,attrib)
+ done = done or ok
+ leader = false
+ end
+ end
+ check = false
+ end
+
+ previous = current
+ current = getnext(current)
+ end
+
+if stacked then
+
+ local n = nsend()
+ while n do
+ head = insert_node_after(head,previous,tonut(n))
+ n = nsend()
+ end
+
+end
+
+ return head, done
+end
+
+states.stacker = function(namespace,attribute,head,default)
+ local head, done = stacker(namespace,attribute,tonut(head),default)
+ nsreset()
+ return tonode(head), done
+end
+
+-- -- --
+
+statistics.register("attribute processing time", function()
+ return statistics.elapsedseconds(attributes,"front- and backend")
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv
new file mode 100644
index 00000000000..413a00722d3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv
@@ -0,0 +1,79 @@
+%D \module
+%D [ file=attr-ini,
+%D version=2007.06.06, % probably a bit older
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Finalizing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Support / Finalizing}
+
+% Objects are processed indepently \unknown\ actually we may
+% need a proper callback.
+
+\unprotect
+
+\registerctxluafile{node-shp}{1.001}
+\registerctxluafile{node-fin}{1.001} % we might generalize this one
+
+% we might have two variants at some point (efficiency)
+
+\unexpanded\def\finalizeobjectbox #1{\clf_finalizebox#1\relax}
+\unexpanded\def\finalizeshipoutbox#1{\clf_finalizebox#1\relax}
+
+% Experimental (for Aditya):
+
+\unexpanded\def\cleanupbox#1{\clf_cleanupbox#1\relax}
+
+% Tricky stuff: this might become obsolete.
+
+\definesystemattribute[trigger][public]
+
+\newcount\attributeboxcount
+
+\edef\startinheritattributes{\attribute\triggerattribute\plusone}
+\edef\stopinheritattributes {\attribute\triggerattribute\attributeunsetvalue}
+
+\def\doattributedcopy{\afterassignment\dodoattributedcopy\attributeboxcount}
+\def\doattributedbox {\afterassignment\dodoattributedbox \attributeboxcount}
+
+\def\dodoattributedcopy
+ {\startinheritattributes
+ \ifvbox\attributeboxcount
+ \vpack{\unvcopy\attributeboxcount}%
+ \else
+ \hpack{\unhcopy\attributeboxcount}%
+ \fi
+ \stopinheritattributes}
+
+\def\dodoattributedbox
+ {\startinheritattributes
+ \ifvbox\attributeboxcount
+ \vpack{\unvbox\attributeboxcount}%
+ \else
+ \hpack{\unhbox\attributeboxcount}%
+ \fi
+ \stopinheritattributes}
+
+\def\enableattributeinheritance
+ {\clf_enablestatetriggering
+ \let\attributedcopy\doattributedcopy
+ \let\attributedbox \doattributedbox}
+
+\def\disableattributeinheritance
+ {\clf_disablestatetriggering
+ \let\attributedcopy\copy
+ \let\attributedbox \box}
+
+\disableattributeinheritance
+
+% \appendtoks
+% \enableattributeinheritance % will become default
+% \to\everyjob
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua
new file mode 100644
index 00000000000..7f0d239979a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua
@@ -0,0 +1,514 @@
+if not modules then modules = { } end modules ['node-fnt'] = {
+ 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",
+}
+
+if not context then os.exit() end -- generic function in node-dum
+
+local next, type = next, type
+local concat, keys = table.concat, table.keys
+
+local nodes, node, fonts = nodes, node, fonts
+
+local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end)
+local trace_fontrun = false trackers.register("nodes.fontrun", function(v) trace_fontrun = v end)
+local trace_variants = false trackers.register("nodes.variants", function(v) trace_variants = v end)
+
+local force_discrun = true directives.register("nodes.discrun", function(v) force_discrun = v end)
+local force_boundaryrun = true directives.register("nodes.boundaryrun", function(v) force_boundaryrun = v end)
+local force_basepass = true directives.register("nodes.basepass", function(v) force_basepass = v end)
+
+local report_fonts = logs.reporter("fonts","processing")
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontvariants = fonthashes.variants
+local fontmodes = fonthashes.modes
+
+local otf = fonts.handlers.otf
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local nodecodes = nodes.nodecodes
+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
+----- getdisc = nuts.getdisc
+local setchar = nuts.setchar
+local setlink = nuts.setlink
+local setfield = nuts.setfield
+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 remove_node = nuts.remove
+local protect_glyph = nuts.protect_glyph
+local free_node = nuts.free
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local boundary_code = nodecodes.boundary
+local word_boundary = nodes.boundarycodes.word
+
+local setmetatableindex = table.setmetatableindex
+
+-- some tests with using an array of dynamics[id] and processes[id] demonstrated
+-- that there was nothing to gain (unless we also optimize other parts)
+--
+-- maybe getting rid of the intermediate shared can save some time
+
+-- potential speedup: check for subtype < 256 so that we can remove that test
+-- elsewhere, danger: injected nodes will not be dealt with but that does not
+-- happen often; we could consider processing sublists but that might need more
+-- checking later on; the current approach also permits variants
+
+local run = 0
+
+local setfontdynamics = { }
+local fontprocesses = { }
+
+-- setmetatableindex(setfontdynamics, function(t,font)
+-- local tfmdata = fontdata[font]
+-- local shared = tfmdata.shared
+-- local v = shared and shared.dynamics and otf.setdynamics or false
+-- t[font] = v
+-- return v
+-- end)
+
+setmetatableindex(setfontdynamics, function(t,font)
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared
+ local f = shared and shared.dynamics and otf.setdynamics or false
+ if f then
+ local v = { }
+ t[font] = v
+ setmetatableindex(v,function(t,k)
+ local v = f(font,k)
+ t[k] = v
+ return v
+ end)
+ return v
+ else
+ t[font] = false
+ return false
+ end
+end)
+
+setmetatableindex(fontprocesses, function(t,font)
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared -- we need to check shared, only when same features
+ local processes = shared and shared.processes
+ if processes and #processes > 0 then
+ t[font] = processes
+ return processes
+ else
+ t[font] = false
+ return false
+ end
+end)
+
+fonts.hashes.setdynamics = setfontdynamics
+fonts.hashes.processes = fontprocesses
+
+-- if we forget about basemode we don't need to test too much here and we can consider running
+-- over sub-ranges .. this involves a bit more initializations but who cares .. in that case we
+-- also need to use the stop criterium (we already use head too) ... we cannot use traverse
+-- then, so i'll test it on some local clone first ... the only pitfall is changed directions
+-- inside a run which means that we need to keep track of this which in turn complicates matters
+-- in a way i don't like
+
+-- we need to deal with the basemode fonts here and can only run over ranges as we
+-- otherwise get luatex craches due to all kind of asserts in the disc/lig builder
+
+local ligaturing = nuts.ligaturing
+local kerning = nuts.kerning
+
+local expanders
+
+function fonts.setdiscexpansion(v)
+ if v == nil or v == true then
+ expanders = languages and languages.expanders
+ elseif type(v) == "table" then
+ expanders = v
+ else
+ expanders = false
+ end
+end
+
+function fonts.getdiscexpansion()
+ return expanders and true or false
+end
+
+fonts.setdiscexpansion(true)
+
+function handlers.characters(head)
+ -- either next or not, but definitely no already processed list
+ starttiming(nodes)
+
+ local usedfonts = { }
+ local attrfonts = { }
+ local basefonts = { }
+ local a, u, b = 0, 0, 0
+ local basefont = nil
+ local prevfont = nil
+ local prevattr = 0
+ local mode = nil
+ local done = false
+ local variants = nil
+ local redundant = nil
+
+ if trace_fontrun then
+ run = run + 1
+ report_fonts()
+ report_fonts("checking node list, run %s",run)
+ report_fonts()
+ local n = tonut(head)
+ while n do
+ local char, id = isglyph(n)
+ if char then
+ local font = getfont(n)
+ 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"))
+ else
+ report_fonts("[%s]",nodecodes[id])
+ end
+ n = getnext(n)
+ end
+ end
+
+ local nuthead = tonut(head)
+
+ for n in traverse_char(nuthead) 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
+ mode = fontmodes[font] -- we can also avoid the attr check
+ variants = fontvariants[font]
+ if mode == "none" then
+ -- skip
+ protect_glyph(n)
+ else
+ if basefont then
+ basefont[2] = getprev(n)
+ end
+ if attr > 0 then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ local fd = setfontdynamics[font]
+ if fd then
+ used[attr] = fd[attr]
+ a = a + 1
+ elseif force_basepass then
+ b = b + 1
+ basefont = { n, nil }
+ basefonts[b] = basefont
+ end
+ end
+ else
+ local used = usedfonts[font]
+ if not used then
+ local fp = fontprocesses[font]
+ if fp then
+ usedfonts[font] = fp
+ u = u + 1
+ elseif force_basepass then
+ b = b + 1
+ basefont = { n, nil }
+ basefonts[b] = basefont
+ end
+ end
+ 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 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 not redundant then
+ redundant = { n }
+ else
+ redundant[#redundant+1] = n
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ 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)
+
+ for b in traverse_id(boundary_code,nuthead) do
+ if getsubtype(b) == word_boundary then
+ if redundant then
+ redundant[#redundant+1] = b
+ else
+ redundant = { b }
+ end
+ end
+ end
+
+ end
+
+ 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 b > 0 then
+ for i=1,b 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
+ free_node(r)
+ end
+ end
+
+ local e = 0
+
+ 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
+
+ -- local prevfont = nil
+ -- local prevattr = 0
+
+ for d in traverse_id(disc_code,nuthead) do
+ -- we could use first_glyph, only doing replace is good enough
+ local _, _, r = getdisc(d)
+ if r then
+ 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
+ if attr > 0 then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ local fd = setfontdynamics[font]
+ if fd then
+ used[attr] = fd[attr]
+ a = a + 1
+ end
+ end
+ else
+ local used = usedfonts[font]
+ if not used then
+ local fp = fontprocesses[font]
+ if fp then
+ usedfonts[font] = fp
+ u = u + 1
+ end
+ end
+ end
+ prevfont = font
+ prevattr = attr
+ end
+ end
+ break
+ elseif expanders then
+ local subtype = getsubtype(d)
+ if subtype == discretionary_code then
+ -- already done when replace
+ else
+ expanders[subtype](d)
+ e = e + 1
+ end
+ end
+ end
+
+ end
+
+ if trace_fontrun then
+ report_fonts()
+ report_fonts("statics : %s",u > 0 and concat(keys(usedfonts)," ") or "none")
+ report_fonts("dynamics: %s",a > 0 and concat(keys(attrfonts)," ") or "none")
+ report_fonts("built-in: %s",b > 0 and b or "none")
+ report_fonts("removed : %s",redundant and #redundant > 0 and #redundant or "none")
+ if expanders then
+ report_fonts("expanded: %s",e > 0 and e or "none")
+ end
+ report_fonts()
+ end
+ -- in context we always have at least 2 processors
+ if u == 0 then
+ -- skip
+ elseif u == 1 then
+ local font, processors = next(usedfonts)
+ for i=1,#processors do
+ local h, d = processors[i](head,font,0)
+ if d then
+ head = h or head
+ done = true
+ end
+ end
+ else
+ for font, processors in next, usedfonts do
+ for i=1,#processors do
+ local h, d = processors[i](head,font,0)
+ if d then
+ head = h or head
+ done = true
+ end
+ end
+ end
+ end
+ if a == 0 then
+ -- skip
+ elseif a == 1 then
+ local font, dynamics = next(attrfonts)
+ for attribute, processors in next, dynamics do -- attr can switch in between
+ for i=1,#processors do
+ local h, d = processors[i](head,font,attribute)
+ if d then
+ head = h or head
+ done = true
+ end
+ end
+ end
+ else
+ for font, dynamics in next, attrfonts do
+ for attribute, processors in next, dynamics do -- attr can switch in between
+ for i=1,#processors do
+ local h, d = processors[i](head,font,attribute)
+ if d then
+ head = h or head
+ done = true
+ end
+ 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, stop = ligaturing(start,stop)
+ start, stop = kerning(start,stop)
+ elseif start then -- safeguard
+ start = ligaturing(start)
+ start = kerning(start)
+ end
+ if front then
+ head = tonode(start)
+ end
+ end
+ else
+ -- multiple fonts
+ for i=1,b 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(nuthead)
+ end
+ end
+ end
+ end
+ stoptiming(nodes)
+ if trace_characters then
+ nodes.report(head,done)
+ end
+ return head, true
+end
+
+local d_protect_glyphs = nuts.protect_glyphs
+local d_unprotect_glyphs = nuts.unprotect_glyphs
+
+handlers.protectglyphs = function(n) return d_protect_glyphs (tonut(n)) end
+handlers.unprotectglyphs = function(n) return d_unprotect_glyphs(tonut(n)) end
+
+-- function handlers.protectglyphs(h)
+-- local h = tonut(h)
+-- for n in traverse_id(disc_code,h) do
+-- local pre, post, replace = getdisc(n)
+-- if pre then d_protect_glyphs(pre) end
+-- if post then d_protect_glyphs(post) end
+-- if replace then d_protect_glyphs(replace) end
+-- end
+-- return d_protect_glyphs(h)
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua
new file mode 100644
index 00000000000..bb8a7d33121
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua
@@ -0,0 +1,356 @@
+if not modules then modules = { } end modules ['node-ini'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Most of the code that had accumulated here is now separated in
+modules.</p>
+--ldx]]--
+
+-- this module is being reconstructed
+
+-- todo: query names with new node.subtypes
+
+local next, type, tostring = next, type, tostring
+local gsub = string.gsub
+local concat, remove = table.concat, table.remove
+local sortedhash, sortedkeys, swapped = table.sortedhash, table.sortedkeys, table.swapped
+
+--[[ldx--
+<p>Access to nodes is what gives <l n='luatex'/> its power. Here we
+implement a few helper functions. These functions are rather optimized.</p>
+--ldx]]--
+
+--[[ldx--
+<p>When manipulating node lists in <l n='context'/>, we will remove
+nodes and insert new ones. While node access was implemented, we did
+quite some experiments in order to find out if manipulating nodes
+in <l n='lua'/> was feasible from the perspective of performance.</p>
+
+<p>First of all, we noticed that the bottleneck is more with excessive
+callbacks (some gets called very often) and the conversion from and to
+<l n='tex'/>'s datastructures. However, at the <l n='lua'/> end, we
+found that inserting and deleting nodes in a table could become a
+bottleneck.</p>
+
+<p>This resulted in two special situations in passing nodes back to
+<l n='tex'/>: a table entry with value <type>false</type> is ignored,
+and when instead of a table <type>true</type> is returned, the
+original table is used.</p>
+
+<p>Insertion is handled (at least in <l n='context'/> as follows. When
+we need to insert a node at a certain position, we change the node at
+that position by a dummy node, tagged <type>inline</type> which itself
+has_attribute the original node and one or more new nodes. Before we pass
+back the list we collapse the list. Of course collapsing could be built
+into the <l n='tex'/> engine, but this is a not so natural extension.</p>
+
+<p>When we collapse (something that we only do when really needed), we
+also ignore the empty nodes. [This is obsolete!]</p>
+--ldx]]--
+
+-- local gf = node.direct.getfield
+-- local n = table.setmetatableindex("number")
+-- function node.direct.getfield(a,b) n[b] = n[b] + 1 print(b,n[b]) return gf(a,b) end
+
+nodes = nodes or { }
+local nodes = nodes
+nodes.handlers = nodes.handlers or { }
+
+local mark = utilities.storage.mark
+local allocate = utilities.storage.allocate
+local formatcolumns = utilities.formatters.formatcolumns
+
+local getsubtypes = node.subtypes
+
+-- local listcodes = allocate {
+-- [0] = "unknown",
+-- [1] = "line",
+-- [2] = "box",
+-- [3] = "indent",
+-- [4] = "alignment", -- row or column
+-- [5] = "cell",
+-- [6] = "equation",
+-- [7] = "equationnumber",
+-- }
+
+local listcodes = mark(getsubtypes("list"))
+
+-- local rulecodes = allocate {
+-- [0] = "normal",
+-- [1] = "box",
+-- [2] = "image",
+-- [3] = "empty",
+-- [4] = "user",
+-- }
+
+local rulecodes = mark(getsubtypes("rule"))
+
+-- local glyphcodes = allocate {
+-- [0] = "character",
+-- [1] = "glyph",
+-- [2] = "ligature",
+-- [3] = "ghost",
+-- [4] = "left",
+-- [5] = "right",
+-- }
+
+local glyphcodes = mark(getsubtypes("glyph"))
+
+-- local disccodes = allocate {
+-- [0] = "discretionary", -- \discretionary
+-- [1] = "explicit", -- \-
+-- [2] = "automatic", -- following a -
+-- [3] = "regular", -- by hyphenator: simple
+-- [4] = "first", -- by hyphenator: hard first item
+-- [5] = "second", -- by hyphenator: hard second item
+-- }
+
+local disccodes = mark(getsubtypes("disc"))
+
+-- local skipcodes = allocate {
+-- [ 0] = "userskip",
+-- [ 1] = "lineskip",
+-- [ 2] = "baselineskip",
+-- [ 3] = "parskip",
+-- [ 4] = "abovedisplayskip",
+-- [ 5] = "belowdisplayskip",
+-- [ 6] = "abovedisplayshortskip",
+-- [ 7] = "belowdisplayshortskip",
+-- [ 8] = "leftskip",
+-- [ 9] = "rightskip",
+-- [ 10] = "topskip",
+-- [ 11] = "splittopskip",
+-- [ 12] = "tabskip",
+-- [ 13] = "spaceskip",
+-- [ 14] = "xspaceskip",
+-- [ 15] = "parfillskip",
+-- [ 16] = "mathskip", -- experiment
+-- [ 17] = "thinmuskip",
+-- [ 18] = "medmuskip",
+-- [ 19] = "thickmuskip",
+-- [ 98] = "conditionalmathglue",
+-- [ 99] = "muskip",
+-- [100] = "leaders",
+-- [101] = "cleaders",
+-- [102] = "xleaders",
+-- [103] = "gleaders",
+-- }
+
+local skipcodes = mark(getsubtypes("glue"))
+
+-- local leadercodes = allocate {
+-- [100] = "leaders",
+-- [101] = "cleaders",
+-- [102] = "xleaders",
+-- [103] = "gleaders",
+-- }
+
+local leadercodes = mark(getsubtypes("leader"))
+
+-- local fillcodes = allocate {
+-- [0] = "stretch",
+-- [1] = "fi",
+-- [2] = "fil",
+-- [3] = "fill",
+-- [4] = "filll",
+-- }
+
+local fillcodes = mark(getsubtypes("fill"))
+
+-- for now:
+
+local boundarycodes = allocate {
+ [0] = "cancel",
+ [1] = "user",
+ [2] = "protrusion",
+ [3] = "word",
+}
+
+-- local boundarycodes = mark(getsubtypes("boundary"))
+
+-- local penaltycodes = allocate { -- unfortunately not used (yet)
+-- [ 0] = "userpenalty",
+-- }
+
+local penaltycodes = mark(getsubtypes("penalty"))
+
+table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
+
+-- local kerncodes = allocate {
+-- [0] = "fontkern",
+-- [1] = "userkern",
+-- [2] = "accentkern",
+-- [3] = "italiccorrection",
+-- }
+
+local kerncodes = mark(getsubtypes("kern"))
+
+-- local margincodes = allocate {
+-- [0] = "left",
+-- [1] = "right",
+-- }
+
+local margincodes = mark(getsubtypes("marginkern"))
+
+-- local mathcodes = allocate {
+-- [0] = "beginmath",
+-- [1] = "endmath",
+-- }
+
+local mathcodes = mark(getsubtypes("math"))
+
+-- local noadcodes = allocate { -- simple nodes
+-- [ 0] = "ord",
+-- [ 1] = "opdisplaylimits",
+-- [ 2] = "oplimits",
+-- [ 3] = "opnolimits",
+-- [ 4] = "bin",
+-- [ 5] = "rel",
+-- [ 6] = "open",
+-- [ 7] = "close",
+-- [ 8] = "punct",
+-- [ 9] = "inner",
+-- [10] = "under",
+-- [11] = "over",
+-- [12] = "vcenter",
+-- }
+
+local noadcodes = mark(getsubtypes("noad"))
+
+-- local radicalcodes = allocate {
+-- [0] = "radical",
+-- [1] = "uradical",
+-- [2] = "uroot",
+-- [3] = "uunderdelimiter",
+-- [4] = "uoverdelimiter",
+-- [5] = "udelimiterunder",
+-- [6] = "udelimiterover",
+-- }
+
+local radicalcodes = mark(getsubtypes("radical"))
+
+-- local accentcodes = allocate {
+-- [0] = "bothflexible",
+-- [1] = "fixedtop",
+-- [2] = "fixedbottom",
+-- [3] = "fixedboth",
+-- }
+
+local accentcodes = mark(getsubtypes("accent"))
+
+-- local fencecodes = allocate {
+-- [0] = "unset",
+-- [1] = "left",
+-- [2] = "middle",
+-- [3] = "right",
+-- }
+
+local fencecodes = mark(getsubtypes("fence"))
+
+-- maybe we also need fractioncodes
+
+local function simplified(t)
+ local r = { }
+ for k, v in next, t do
+ r[k] = gsub(v,"_","")
+ end
+ return r
+end
+
+local nodecodes = simplified(node.types())
+local whatcodes = simplified(node.whatsits())
+
+skipcodes = allocate(swapped(skipcodes,skipcodes))
+boundarycodes = allocate(swapped(boundarycodes,boundarycodes))
+noadcodes = allocate(swapped(noadcodes,noadcodes))
+radicalcodes = allocate(swapped(radicalcodes,radicalcodes))
+nodecodes = allocate(swapped(nodecodes,nodecodes))
+whatcodes = allocate(swapped(whatcodes,whatcodes))
+listcodes = allocate(swapped(listcodes,listcodes))
+glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
+kerncodes = allocate(swapped(kerncodes,kerncodes))
+penaltycodes = allocate(swapped(penaltycodes,penaltycodes))
+mathcodes = allocate(swapped(mathcodes,mathcodes))
+fillcodes = allocate(swapped(fillcodes,fillcodes))
+margincodes = allocate(swapped(margincodes,margincodes))
+disccodes = allocate(swapped(disccodes,disccodes))
+accentcodes = allocate(swapped(accentcodes,accentcodes))
+fencecodes = allocate(swapped(fencecodes,fencecodes))
+rulecodes = allocate(swapped(rulecodes,rulecodes))
+leadercodes = allocate(swapped(leadercodes,leadercodes))
+
+nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
+nodes.boundarycodes = boundarycodes
+nodes.noadcodes = noadcodes
+nodes.nodecodes = nodecodes
+nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
+nodes.listcodes = listcodes
+nodes.glyphcodes = glyphcodes
+nodes.kerncodes = kerncodes
+nodes.penaltycodes = penaltycodes
+nodes.mathcodes = mathcodes
+nodes.fillcodes = fillcodes
+nodes.margincodes = margincodes nodes.marginkerncodes = margincodes
+nodes.disccodes = disccodes nodes.discretionarycodes = disccodes
+nodes.accentcodes = accentcodes
+nodes.radicalcodes = radicalcodes
+nodes.fencecodes = fencecodes
+nodes.rulecodes = rulecodes
+nodes.leadercodes = leadercodes
+
+listcodes.row = listcodes.alignment
+listcodes.column = listcodes.alignment
+
+kerncodes.kerning = kerncodes.fontkern
+
+kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new
+
+nodes.codes = allocate { -- mostly for listing
+ glue = skipcodes,
+ boundary = boundarycodes,
+ noad = noadcodes,
+ node = nodecodes,
+ hlist = listcodes,
+ vlist = listcodes,
+ glyph = glyphcodes,
+ kern = kerncodes,
+ penalty = penaltycodes,
+ math = mathnodes,
+ fill = fillcodes,
+ margin = margincodes,
+ disc = disccodes,
+ whatsit = whatcodes,
+ accent = accentcodes,
+ fence = fencecodes,
+}
+
+local report_codes = logs.reporter("nodes","codes")
+
+function nodes.showcodes()
+ local t = { }
+ for name, codes in sortedhash(nodes.codes) do
+ local sorted = sortedkeys(codes)
+ for i=1,#sorted do
+ local s = sorted[i]
+ if type(s) ~= "number" then
+ t[#t+1] = { name, s, codes[s] }
+ end
+ end
+ end
+ formatcolumns(t)
+ for k=1,#t do
+ report_codes (t[k])
+ end
+end
+
+trackers.register("system.showcodes", nodes.showcodes)
+
+if not nodecodes.dir then
+ report_codes("use a newer version of luatex")
+ os.exit()
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv
new file mode 100644
index 00000000000..d04e647de42
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv
@@ -0,0 +1,61 @@
+%D \module
+%D [ file=node-ini,
+%D version=2006.08.20,
+%D title=\CONTEXT\ Node 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 Node Support / Initialization}
+
+\unprotect
+
+\newcount\filterstate \filterstate\plusone % hm, public
+
+\registerctxluafile{node-ini}{1.001}
+\registerctxluafile{node-met}{1.001}
+\registerctxluafile{node-nut}{1.001}
+\registerctxluafile{node-res}{1.001}
+\registerctxluafile{node-ppt}{1.001} % experimental
+\registerctxluafile{node-dir}{1.001}
+\registerctxluafile{node-aux}{1.001}
+\registerctxluafile{node-tst}{1.001}
+\registerctxluafile{node-tra}{1.001} % we might split it off (module)
+\registerctxluafile{node-snp}{1.001}
+\registerctxluafile{node-tsk}{1.001}
+\registerctxluafile{node-tex}{1.001}
+\registerctxluafile{node-pro}{1.001}
+\registerctxluafile{node-ser}{1.001}
+\registerctxluafile{node-ext}{1.001}
+\registerctxluafile{node-acc}{1.001} % experimental
+%registerctxluafile{node-prp}{1.001} % makes no sense (yet)
+
+\doifelsefile{node-ppt.lua}{\registerctxluafile{node-ppt}{1.001}}{}
+
+\newcount\c_node_tracers_show_box % box number
+
+\unexpanded\def\shownextnodes{\afterassignment\node_tracers_show_next\c_node_tracers_show_box}
+\unexpanded\def\showflatnodes{\afterassignment\node_tracers_show_flat\c_node_tracers_show_box}
+
+\def\node_tracers_show_next{\ctxlua{texio.write_nl('log',nodes.serializebox(\number\c_node_tracers_show_box,false,true))}}
+\def\node_tracers_show_flat{\ctxlua{texio.write_nl('log',nodes.serializebox(\number\c_node_tracers_show_box,true, true))}}
+
+\unexpanded\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}}
+\unexpanded\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}}
+
+\unexpanded\def\starttracingnodes[#1]{\ctxlua{nodes.tracers.characters.start("#1")}}
+\unexpanded\def\stoptracingnodes {\ctxlua{nodes.tracers.characters.stop()}}
+
+% \starttext
+% \starttracingnodes[characters]
+% \input tufte \par
+% \input tufte \par
+% \stoptracingnodes
+% \stoptext
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua
new file mode 100644
index 00000000000..ae17ab9ef00
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua
@@ -0,0 +1,3174 @@
+if not modules then modules = { } end modules ['node-par'] = {
+ version = 1.001,
+ comment = "companion to node-par.mkiv",
+ author = "Hans Hagen",
+ copyright = "ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "a translation of the built in parbuilder, initial convertsin by Taco Hoekwater",
+}
+
+-- todo: remove nest_stack from linebreak.w
+-- todo: use ex field as signal (index in ?)
+-- todo: attr driven unknown/on/off
+-- todo: permit global steps i.e. using an attribute that sets min/max/step and overloads the font parameters
+-- todo: split the three passes into three functions
+-- todo: simplify the direction stack, no copy needed
+-- todo: see if we can do without delta nodes (needs thinking)
+-- todo: add more mkiv like tracing
+-- todo: add a couple of plugin hooks
+-- todo: maybe split expansion code paths
+-- todo: fix line numbers (cur_list.pg_field needed)
+-- todo: check and improve protrusion
+-- todo: arabic etc (we could use pretty large scales there) .. marks and cursive
+-- todo: see: we need to check this with the latest patches to the tex kernel
+
+-- todo: optimize a bit more (less par.*)
+
+--[[
+
+ This code is derived from traditional TeX and has bits of pdfTeX, Aleph (Omega), and of course LuaTeX. So,
+ the basic algorithm for sure is not our work. On the other hand, the directional model in LuaTeX is cleaned
+ up as is other code. And of course there are hooks for callbacks.
+
+ The first version of the code below was a conversion of the C code that in turn was a conversion from the
+ original Pascal code. Around September 2008 we experimented with cq. discussed possible approaches to improved
+ typesetting of Arabic and as our policy is that extensions happen in Lua this means that we need a parbuilder
+ in Lua. Taco's first conversion still looked quite C-ish and in the process of cleaning up we uncovered some odd
+ bits and pieces in the original code as well. I did some first cleanup to get rid of C-artefacts, and Taco and I
+ spent the usual amount of Skyping to sort out problems. At that point we diverted to other LuaTeX issues.
+
+ A while later I decided to pick up this thread and decided to look into better ways to deal with font expansion
+ (aka hz). I got it running using a simpler method. One reason why the built-in mechanims is slow is that there is
+ lots of redudancy in calculations. Expanded widths are recalculated each time and because the hpakc routine does
+ it again that gives some overhead. In the process extra fonts are created with different dimensions so that the
+ backend can deal with it. The alternative method doesn't create fonts but passes an expansion factor to the
+ pdf generator. The small patch needed for the backend code worked more or less okay but was never intergated into
+ LuaTeX due to lack of time.
+
+ This all happened in 2010 while listening to Peter Gabriels "Scratch My Back" and Camels "Rayaz" so it was a
+ rather relaxed job.
+
+ In 2012 I picked up this thread. Because both languages are similar but also quite different it took some time
+ to get compatible output. Because the C code uses macros, careful checking was needed. Of course Lua's table model
+ and local variables brought some work as well. And still the code looks a bit C-ish. We could not divert too much
+ from the original model simply because it's well documented but future versions (or variants) might as well look
+ different.
+
+ Eventually I'll split this code into passes so that we can better see what happens, but first we need to reach
+ a decent level of stability. The current expansion results are not the same as the built-in but that was never
+ the objective. It all has to do with slightly different calculations.
+
+ The original C-code related to protrusion and expansion is not that efficient as many (redundant) function
+ calls take place in the linebreaker and packer. As most work related to fonts is done in the backend, we
+ can simply stick to width calculations here. Also, it is no problem at all that we use floating point
+ calculations (as Lua has only floats). The final result will look ok as the hpack will nicely compensate
+ for rounding errors as it will normally distribute the content well enough. And let's admit: most texies
+ won't see it anyway. As long as we're cross platform compatible it's fine.
+
+ We use the table checked_expansion to keep track of font related parameters (per paragraph). The table is
+ also the signal that we have adjustments > 1. In retrospect one might wonder if adjusting kerns is such a
+ good idea because other spacing is also not treated. If we would stick to the regular hpack routine
+ we do have to follow the same logic, but I decided to use a Lua hpacker so that constraint went away. And
+ anyway, instead of doing a lookup in the kern table (that we don't have in node mode) the set kern value
+ is used. Disabling kern scaling will become an option in Luatex some day. You can blame me for all errors
+ that crept in and I know that there are some.
+
+ To be honest, I slowly start to grasp the magic here as normally I start from scratch when implementing
+ something (as it's the only way I can understand things). This time I had a recently acquired stack of
+ Porcupine Tree disks to get me through, although I must admit that watching their dvd's is more fun
+ than coding.
+
+ Picking up this effort was inspired by discussions between Luigi Scarso and me about efficiency of Lua
+ code and we needed some stress tests to compare regular LuaTeX and LuajitTeX. One of the tests was
+ processing tufte.tex as that one has lots of hyphenations and is a tough one to get right.
+
+ tufte: boxed 1000 times, no flushing in backend:
+
+ \testfeatureonce{1000}{\setbox0\hbox{\tufte}}
+ \testfeatureonce{1000}{\setbox0\vbox{\tufte}}
+ \startparbuilder[basic]\testfeatureonce{1000}{\setbox0\vbox{\tufte}}\stopparbuilder
+
+ method normal hz comment
+
+ luatex tex hbox 9.64 9.64 baseline font feature processing, hyphenation etc: 9.74
+ tex vbox 9.84 10.16 0.20 linebreak / 0.52 with hz -> 0.32 hz overhead (150pct more)
+ lua vbox 17.28 18.43 7.64 linebreak / 8.79 with hz -> 1.33 hz overhead ( 20pct more)
+
+ new laptop | no nuts
+ 3.42 baseline
+ 3.63 0.21 linebreak
+ 7.38 3.96 linebreak
+
+ new laptop | most nuts
+ 2.45 baseline
+ 2.53 0.08 linebreak
+ 6.16 3.71 linebreak
+ ltp nuts 5.45 3.00 linebreak
+
+ luajittex tex hbox 6.33 6.33 baseline font feature processing, hyphenation etc: 6.33
+ tex vbox 6.53 6.81 0.20 linebreak / 0.48 with hz -> 0.28 hz overhead (expected 0.32)
+ lua vbox 11.06 11.81 4.53 linebreak / 5.28 with hz -> 0.75 hz overhead
+
+ new laptop | no nuts
+ 2.06 baseline
+ 2.27 0.21 linebreak
+ 3.95 1.89 linebreak
+
+ new laptop | most nuts
+ 1.25 baseline
+ 1.30 0.05 linebreak
+ 3.03 1.78 linebreak
+ ltp nuts 2.47 1.22 linebreak
+
+ Interesting is that the runtime for the built-in parbuilder indeed increases much when expansion
+ is enabled, but in the Lua variant the extra overhead is way less significant. This means that when we
+ retrofit the same approach into the core, the overhead of expansion can be sort of nilled.
+
+ In 2013 the expansion factor method became also used at the TeX end so then I could complete the code
+ here, and indeed, expansions works quite well now (not compatible of course because we use floats at the
+ Lua end. The Lua base variant is still slower but quite ok, especially if we go nuts.
+
+ A next iteration will provide plug-ins and more control. I will also explore the possibility to avoid the
+ redundant hpack calculations (easier now, although I've only done some quick and dirty experiments.)
+
+]]--
+
+local utfchar = utf.char
+local write, write_nl = texio.write, texio.write_nl
+local sub, format = string.sub, string.format
+local round, floor = math.round, math.floor
+local insert, remove = table.insert, table.remove
+
+local fonts, nodes, node = fonts, nodes, node
+
+local trace_basic = false trackers.register("builders.paragraphs.basic", function(v) trace_basic = v end)
+local trace_lastlinefit = false trackers.register("builders.paragraphs.lastlinefit", function(v) trace_lastlinefit = v end)
+local trace_adjusting = false trackers.register("builders.paragraphs.adjusting", function(v) trace_adjusting = v end)
+local trace_protruding = false trackers.register("builders.paragraphs.protruding", function(v) trace_protruding = v end)
+local trace_expansion = false trackers.register("builders.paragraphs.expansion", function(v) trace_expansion = v end)
+local trace_quality = false trackers.register("builders.paragraphs.quality", function(v) trace_quality = v end)
+
+local report_parbuilders = logs.reporter("nodes","parbuilders")
+local report_hpackers = logs.reporter("nodes","hpackers")
+
+local calculate_badness = tex.badness
+local texnest = tex.nest
+local texlists = tex.lists
+
+-- (t == 0 and 0) or (s <= 0 and 10000) or calculate_badness(t,s)
+
+-- local function calculate_badness(t,s)
+-- if t == 0 then
+-- return 0
+-- elseif s <= 0 then
+-- return 10000 -- infinite_badness
+-- else
+-- local r
+-- if t <= 7230584 then
+-- r = (t * 297) / s
+-- elseif s >= 1663497 then
+-- r = t / (s / 297)
+-- else
+-- r = t
+-- end
+-- if r > 1290 then
+-- return 10000 -- infinite_badness
+-- else
+-- return (r * r * r + 0x20000) / 0x40000
+-- end
+-- end
+-- end
+
+local parbuilders = builders.paragraphs
+local constructors = parbuilders.constructors
+
+local setmetatableindex = table.setmetatableindex
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
+local parameters = fonthashes.parameters
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getfield = nuts.getfield
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+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 isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setboth = nuts.setboth
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setdisc = nuts.setdisc
+local setsubtype = nuts.setsubtype
+
+local slide_nodelist = nuts.slide -- get rid of this, probably ok > 78.2
+local find_tail = nuts.tail
+local new_node = nuts.new
+local copy_node = nuts.copy
+local copy_nodelist = nuts.copy_list
+local flush_node = nuts.free
+local flush_nodelist = nuts.flush_list
+local hpack_nodes = nuts.hpack
+local xpack_nodes = nuts.hpack
+local replace_node = nuts.replace
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+local traverse_by_id = nuts.traverse_id
+
+local setnodecolor = nodes.tracers.colors.set
+
+local nodepool = nuts.pool
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+local glyphcodes = nodes.glyphcodes
+local gluecodes = nodes.gluecodes
+local margincodes = nodes.margincodes
+local disccodes = nodes.disccodes
+local mathcodes = nodes.mathcodes
+local fillcodes = nodes.fillcodes
+local boundarycodes = nodes.boundarycodes
+
+local temp_code = nodecodes.temp
+local glyph_code = nodecodes.glyph
+local ins_code = nodecodes.ins
+local mark_code = nodecodes.mark
+local adjust_code = nodecodes.adjust
+local penalty_code = nodecodes.penalty
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local unset_code = nodecodes.unset
+local marginkern_code = nodecodes.marginkern
+local dir_code = nodecodes.dir
+local boundary_code = nodecodes.boundary
+
+local protrusion_code = boundarycodes.protrusion
+
+local leaders_code = gluecodes.leaders
+
+local localpar_code = nodecodes.localpar
+
+local kerning_code = kerncodes.kerning -- font kern
+local userkern_code = kerncodes.userkern
+local italickern_code = kerncodes.italiccorrection
+
+local ligature_code = glyphcodes.ligature
+
+local stretch_orders = nodes.fillcodes
+
+local leftmargin_code = margincodes.left
+local 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 endmath_code = mathcodes.endmath
+
+local nosubtype_code = 0
+
+local unhyphenated_code = nodecodes.unhyphenated or 1
+local hyphenated_code = nodecodes.hyphenated or 2
+local delta_code = nodecodes.delta or 3
+local passive_code = nodecodes.passive or 4
+
+local maxdimen = number.maxdimen
+
+local max_halfword = 0x7FFFFFFF
+local infinite_penalty = 10000
+local eject_penalty = -10000
+local infinite_badness = 10000
+local awful_badness = 0x3FFFFFFF
+local ignore_depth = -65536000
+
+local fit_very_loose_class = 0 -- fitness for lines stretching more than their stretchability
+local fit_loose_class = 1 -- fitness for lines stretching 0.5 to 1.0 of their stretchability
+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_leftmarginkern = nodepool.leftmarginkern
+local new_rightmarginkern = nodepool.rightmarginkern
+local new_leftskip = nodepool.leftskip
+local new_rightskip = nodepool.rightskip
+local new_lineskip = nodepool.lineskip
+local new_baselineskip = nodepool.baselineskip
+local new_temp = nodepool.temp
+local new_rule = nodepool.rule
+
+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
+
+local a_fontkern = attributes.private('fontkern')
+
+-- helpers --
+
+-- It makes more sense to move the somewhat messy dir state tracking
+-- out of the main functions. First we create a stack allocator.
+
+local function new_dir_stack(dir) -- also use elsewhere
+ return { n = 0, dir }
+end
+
+-- The next function checks a dir node and returns the new dir state. By
+-- using s static table we are quite efficient. This function is used
+-- in the parbuilder.
+
+local function checked_line_dir(stack,current)
+ if not dir_pops[current] then
+ local n = stack.n + 1
+ stack.n = n
+ stack[n] = current
+ return getfield(current,"dir")
+ elseif n > 0 then
+ local n = stack.n
+ local dirnode = stack[n]
+ dirstack.n = n - 1
+ return getfield(dirnode,"dir")
+ 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
+-- that are currently needed (some day LuaTeX will be more tolerant). We use
+-- the negations for the next line.
+
+local function inject_dirs_at_end_of_line(stack,current,start,stop)
+ local e = start
+ local n = stack.n
+ local h = nil
+ while start and start ~= stop do
+ local id = getid(start)
+ if id == dir_code then
+ if not dir_pops[getfield(start,"dir")] then -- weird, what is this #
+ n = n + 1
+ stack[n] = start
+ elseif n > 0 then
+ n = n - 1
+ else
+ report_parbuilders("warning: missing pop node (%a)",2) -- in line ...
+ end
+ end
+ start = getnext(start)
+ end
+ for i=n,1,-1 do
+ h, current = insert_node_after(current,current,new_dir(dir_negations[getfield(stack[i],"dir")]))
+ end
+ stack.n = n
+ return current
+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]))
+ end
+ stack.n = 0
+ return current
+end
+
+-- diagnostics --
+
+local dummy = function() end
+
+local diagnostics = {
+ start = dummy,
+ stop = dummy,
+ current_pass = dummy,
+ break_node = dummy,
+ feasible_break = dummy,
+}
+
+-- statistics --
+
+local nofpars, noflines, nofprotrudedlines, nofadjustedlines = 0, 0, 0, 0
+
+local function register_statistics(par)
+ local statistics = par.statistics
+ nofpars = nofpars + 1
+ noflines = noflines + statistics.noflines
+ nofprotrudedlines = nofprotrudedlines + statistics.nofprotrudedlines
+ nofadjustedlines = nofadjustedlines + statistics.nofadjustedlines
+end
+
+-- expansion etc --
+
+local function calculate_fraction(x,n,d,max_answer)
+ local the_answer = x * n/d + 1/2 -- round ?
+ if the_answer > max_answer then
+ return max_answer
+ elseif the_answer < -max_answer then
+ return -max_answer
+ else
+ return the_answer
+ end
+end
+
+local function check_shrinkage(par,n)
+ -- called often, so maybe move inline -- use NORMAL
+ if getfield(n,"shrink_order") ~= 0 and getfield(n,"shrink") ~= 0 then
+ if par.no_shrink_error_yet then
+ par.no_shrink_error_yet = false
+ report_parbuilders("infinite glue shrinkage found in a paragraph and removed")
+ end
+ n = copy_node(n)
+ setfield(n,"shrink_order",0)
+ end
+ return n
+end
+
+-- It doesn't really speed up much but the additional memory usage is
+-- rather small so it doesn't hurt too much.
+
+local expansions = { }
+local nothing = { stretch = 0, shrink = 0 }
+
+setmetatableindex(expansions,function(t,font) -- we can store this in tfmdata if needed
+ local expansion = parameters[font].expansion -- can be an extra hash
+ if expansion and expansion.auto then
+ local factors = { }
+ local c = chardata[font]
+ setmetatableindex(factors,function(t,char)
+ local fc = c[char]
+ local ef = fc.expansion_factor
+ if ef and ef > 0 then
+ local stretch = expansion.stretch
+ local shrink = expansion.shrink
+ if stretch ~= 0 or shrink ~= 0 then
+ local factor = ef / 1000
+ local ef_quad = factor * quaddata[font] / 1000
+ local v = {
+ glyphstretch = stretch * ef_quad,
+ glyphshrink = shrink * ef_quad,
+ factor = factor,
+ stretch = stretch,
+ shrink = shrink,
+ }
+ t[char] = v
+ return v
+ end
+ end
+ t[char] = nothing
+ return nothing
+ end)
+ t[font] = factors
+ return factors
+ else
+ t[font] = false
+ return false
+ end
+end)
+
+local function kern_stretch_shrink(p,d)
+ local left = getprev(p)
+ if left then
+ local char = isglyph(left)
+ if char then
+ local data = expansions[getfont(left)][char]
+ if data then
+ local stretch = data.stretch
+ local shrink = data.shrink
+ if stretch ~= 0 then
+ -- stretch = data.factor * (d * stretch - d)
+ stretch = data.factor * d * (stretch - 1)
+ end
+ if shrink ~= 0 then
+ -- shrink = data.factor * (d * shrink - d)
+ shrink = data.factor * d * (shrink - 1)
+ end
+ return stretch, shrink
+ end
+ end
+ end
+ return 0, 0
+end
+
+local expand_kerns_mode = false
+local expand_kerns = false
+
+directives.register("builders.paragraphs.adjusting.kerns",function(v)
+ if not v then
+ expand_kerns_mode = false
+ elseif v == "stretch" or v == "shrink" then
+ expand_kerns_mode = v
+ elseif v == "both" then
+ expand_kerns_mode = true
+ else
+ expand_kerns_mode = toboolean(v,true) or false
+ end
+end)
+
+-- state:
+
+local function check_expand_pars(checked_expansion,f)
+ local expansion = parameters[f].expansion
+ if not expansion then
+ checked_expansion[f] = false
+ return false
+ end
+-- expansion.step = 1
+ local step = expansion.step or 0
+ local stretch = expansion.stretch or 0
+ local shrink = expansion.shrink or 0
+ if step == 0 or (stretch == 0 and schrink == 0) then
+ checked_expansion[f] = false
+ return false
+ end
+ local par = checked_expansion.par
+ if par.cur_font_step < 0 then
+ par.cur_font_step = step
+ elseif par.cur_font_step ~= step then
+ report_parbuilders("using fonts with different step of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if stretch == 0 then
+ -- okay
+ elseif par.max_stretch_ratio < 0 then
+ par.max_stretch_ratio = stretch -- expansion_factor
+ elseif par.max_stretch_ratio ~= stretch then
+ report_parbuilders("using fonts with different stretch limit of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if shrink == 0 then
+ -- okay
+ elseif par.max_shrink_ratio < 0 then
+ par.max_shrink_ratio = shrink -- - expansion_factor
+ elseif par.max_shrink_ratio ~= shrink then
+ report_parbuilders("using fonts with different shrink limit of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if trace_adjusting then
+ report_parbuilders("expanding font %a using step %a, shrink %a and stretch %a",f,step,stretch,shrink)
+ end
+ local e = expansions[f]
+ checked_expansion[f] = e
+ return e
+end
+
+local function check_expand_lines(checked_expansion,f)
+ local expansion = parameters[f].expansion
+ if not expansion then
+ checked_expansion[f] = false
+ return false
+ end
+-- expansion.step = 1
+ local step = expansion.step or 0
+ local stretch = expansion.stretch or 0
+ local shrink = expansion.shrink or 0
+ if step == 0 or (stretch == 0 and schrink == 0) then
+ checked_expansion[f] = false
+ return false
+ end
+ if trace_adjusting then
+ report_parbuilders("expanding font %a using step %a, shrink %a and stretch %a",f,step,stretch,shrink)
+ end
+ local e = expansions[f]
+ checked_expansion[f] = e
+ return e
+end
+
+-- protrusion
+
+local function find(head) -- do we really want to recurse into an hlist?
+ while head do
+ local id = getid(head)
+ if id == glyph_code then
+ return head
+ elseif id == hlist_code then
+ local found = find(getlist(head))
+ if found then
+ return found
+ else
+ head = getnext(head)
+ end
+ elseif id == protrusion_code then
+ local v = getfield(head,"value")
+ if v == 1 or v == 3 then
+ head = getnext(head)
+ if head then
+ head = getnext(head)
+ end
+ else
+ return head
+ end
+ elseif is_skipable(head) then
+ head = getnext(head)
+ else
+ return head
+ end
+ end
+ return nil
+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
+ end
+ -- if getid(l) == glyph_code then
+ -- return l
+ -- end
+ return find(l) or l
+end
+
+local function find(head,tail)
+ local tail = tail or find_tail(head)
+ while tail do
+ local id = getid(tail)
+ if id == glyph_code then
+ return tail
+ elseif id == hlist_code then
+ local found = find(getlist(tail))
+ if found then
+ return found
+ else
+ tail = getprev(tail)
+ end
+ elseif id == protrusion_code then
+ local v = getfield(tail,"value")
+ if v == 2 or v == 3 then
+ tail = getprev(tail)
+ if tail then
+ tail = getprev(tail)
+ end
+ else
+ return tail
+ end
+ elseif is_skipable(tail) then
+ tail = getprev(tail)
+ else
+ return tail
+ end
+ end
+ return nil
+end
+
+local function find_protchar_right(l,r)
+ return r and find(l,r) or r
+end
+
+local function left_pw(p)
+ local font = getfont(p)
+ local prot = chardata[font][getchar(p)].left_protruding
+ if not prot or prot == 0 then
+ return 0
+ end
+ return prot * quaddata[font] / 1000, p
+end
+
+local function right_pw(p)
+ local font = getfont(p)
+ local prot = chardata[font][getchar(p)].right_protruding
+ if not prot or prot == 0 then
+ return 0
+ end
+ return prot * quaddata[font] / 1000, p
+end
+
+-- par parameters
+
+local function reset_meta(par)
+ local active = {
+ id = hyphenated_code,
+ line_number = max_halfword,
+ }
+ active.next = par.active -- head of metalist
+ par.active = active
+ par.passive = nil
+end
+
+local function add_to_width(line_break_dir,checked_expansion,s) -- split into two loops (normal and expansion)
+ local size = 0
+ local adjust_stretch = 0
+ local adjust_shrink = 0
+ while s do
+ local char, id = isglyph(s)
+ if char then
+ if is_rotated[line_break_dir] then -- can be shared
+ size = size + getfield(s,"height") + getfield(s,"depth")
+ else
+ size = size + getfield(s,"width")
+ end
+ if checked_expansion then
+ local data = checked_expansion[getfont(s)]
+ if data then
+ data = data[char]
+ if data then
+ adjust_stretch = adjust_stretch + data.glyphstretch
+ adjust_shrink = adjust_shrink + data.glyphshrink
+ end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if is_parallel[getfield(s,"dir")][line_break_dir] then
+ size = size + getfield(s,"width")
+ else
+ size = size + getfield(s,"height") + getfield(s,"depth")
+ end
+ elseif id == kern_code then
+ local kern = getfield(s,"kern")
+ if kern ~= 0 then
+ if checked_expansion and expand_kerns and (getsubtype(s) == kerning_code or getattr(a_fontkern)) then
+ local stretch, shrink = kern_stretch_shrink(s,kern)
+ if expand_kerns == "stretch" then
+ adjust_stretch = adjust_stretch + stretch
+ elseif expand_kerns == "shrink" then
+ adjust_shrink = adjust_shrink + shrink
+ else
+ adjust_stretch = adjust_stretch + stretch
+ adjust_shrink = adjust_shrink + shrink
+ end
+ end
+ size = size + kern
+ end
+ elseif id == rule_code then
+ size = size + getfield(s,"width")
+ elseif trace_unsupported then
+ report_parbuilders("unsupported node at location %a",6)
+ end
+ s = getnext(s)
+ end
+ 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 order = stretch_orders[getfield(p,"stretch_order")]
+ break_width.size = break_width.size - getfield(p,"width")
+ break_width[order] = break_width[order] - getfield(p,"stretch")
+ break_width.shrink = break_width.shrink - getfield(p,"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 - getfield(p,"kern")
+ else
+ return
+ end
+ elseif id == math_code then
+ break_width.size = break_width.size - getfield(p,"surround")
+ else
+ return
+ end
+ p = getnext(p)
+ end
+end
+
+local function append_to_vlist(par, b)
+ local prev_depth = par.prev_depth
+ -- if prev_depth > par.ignored_dimen then
+ if prev_depth > ignore_depth then
+ if getid(b) == hlist_code then
+ local d = getfield(par.baseline_skip,"width") - prev_depth - getfield(b,"height") -- deficiency of space between baselines
+ local s = d < par.line_skip_limit and new_lineskip(par.lineskip) or new_baselineskip(d)
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_nodelist(head_field) -- todo: find_tail
+ setlink(n,s)
+ else
+ par.head_field = s
+ end
+ end
+ end
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_nodelist(head_field) -- todo: find_tail
+ setlink(n,b)
+ else
+ par.head_field = b
+ end
+ if getid(b) == hlist_code then
+ local pd = getfield(b,"depth")
+ 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_nodelist(head_field) -- todo: find_tail
+ setlink(n,b)
+ else
+ par.head_field = b
+ 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 (getfield(s,"width") ~= 0 or getfield(s,"stretch") ~= 0 or getfield(s,"shrink") ~= 0) and s or nil
+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_nodelist(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
+
+ }
+
+ -- optimizers
+
+ par.used_left_skip = used_skip(par.left_skip)
+ par.used_right_skip = used_skip(par.right_skip)
+
+ -- so far
+
+ 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
+ end
+ par.tolerance = hztolerance
+ end
+
+ expand_kerns = expand_kerns_mode or (adjust_spacing == 2)
+
+ end
+
+ -- we need par for the error message
+
+ local background = par.background
+
+ local l = check_shrinkage(par,left_skip)
+ local r = check_shrinkage(par,right_skip)
+ local l_order = stretch_orders[getfield(l,"stretch_order")]
+ local r_order = stretch_orders[getfield(r,"stretch_order")]
+
+ background.size = getfield(l,"width") + getfield(r,"width")
+ background.shrink = getfield(l,"shrink") + getfield(r,"shrink")
+ background[l_order] = getfield(l,"stretch")
+ background[r_order] = getfield(r,"stretch") + background[r_order]
+
+ -- 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
+ 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
+
+ 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")
+ end
+ end
+ end
+
+ if last_line_fit > 0 then
+ local spec = par.final_par_glue.spec
+ local stretch = spec.stretch
+ local stretch_order = spec.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)
+ end
+ par.fill_width[si] = stretch
+ end
+ 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)
+
+local function post_line_break(par)
+
+ 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 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 adapt_width = par.adapt_width
+
+ -- reverse the links of the relevant passive nodes, goto first breakpoint
+
+ 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 head = par.head
+
+ -- maybe : each_...
+
+ while current_break do
+
+ inject_dirs_at_begin_of_line(stack,head)
+
+ 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
+
+ if not lastnode then
+ -- only at the end
+ lastnode = slide_nodelist(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(r)
+ 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_nodelist(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_nodelist(pre)
+ end
+ if replace then
+ flush_nodelist(replace)
+ end
+ if post then
+ flush_nodelist(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)
+ end
+ setsubtype(nextlast,regular_disc_code)
+ setfield(nextlast,"replace",post)
+ setfield(lastnode,"post") -- nil
+ end
+ if replace then
+ flush_nodelist(replace)
+ end
+ if pre then
+ setlink(prevlast,pre)
+ setlink(pretail,lastnode)
+ end
+ if post then
+ setlink(lastnode,post)
+ setlink(posttail,nextlast)
+ post_disc_break = true
+ end
+ setdisc(lastnode) -- nil, nil, nil
+ disc_break = true
+ elseif id == kern_code then
+ setfield(lastnode,"kern",0)
+ elseif getid(lastnode) == math_code then
+ setfield(lastnode,"surround",0)
+ 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))
+ 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
+ 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))
+ 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
+ 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
+
+ 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
+ --
+ setfield(finished_line,"shift",cur_indent)
+ --
+ -- -- this is gone:
+ --
+ -- if par.each_line_height ~= ignored_dimen then
+ -- setfield(finished_line,"height",par.each_line_height)
+ -- end
+ -- if par.each_line_depth ~= ignored_dimen then
+ -- setfield(finished_line,"depth",par.each_line_depth)
+ -- end
+ -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
+ -- setfield(finished_line,"height",par.first_line_height)
+ -- end
+ -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
+ -- setfield(finished_line,"depth",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 = 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
+ else
+ pen = pen + par.widow_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
+ 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 or getid(next) == glyph_code then
+ break
+ end
+ local id = getid(next)
+ local subtype = getsubtype(next)
+ if id == localpar_code then
+ -- nothing
+ elseif id < math_code then
+ -- messy criterium
+ break
+ elseif id == math_code then
+ -- keep the math node
+ setfield(next,"surround",0)
+ break
+ elseif id == kern_code and (subtype ~= userkern_code and subtype ~= italickern_code and not getattr(next,a_fontkern)) then
+ -- fontkerns and accent kerns as well as otf injections
+ break
+ end
+ current = next
+ end
+ if current ~= head then
+ setnext(current)
+ flush_nodelist(getnext(head))
+ setlink(head,next)
+ 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
+ setfield(glue,"width",getfield(glue,"width") + 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
+ 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
+ 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
+ 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
+ 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
+ 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 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
+ 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,
+ 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
+ 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
+ line_width = par.second_width
+ elseif parshape then
+ line_width = parshape[line_number][2]
+ else
+ line_width = par.first_width
+ 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)
+ 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 l.post then
+ l = l.post -- TODO: first char could be a disc
+ else
+ l = find_protchar_left(l)
+ end
+ if l and getid(l) == glyph_code then
+ pw, lp = left_pw(l)
+ shortfall = shortfall + pw
+ end
+ end
+ 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 data = expansions[getfont(lp)][getchar(lp)]
+ if data then
+ margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+ end
+ 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
+ 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
+ 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
+ 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
+ local stretch = cur_active_width.stretch
+ if shortfall > 7230584 and stretch < 1663497 then
+ b = infinite_badness
+ fit_class = fit_very_loose_class
+ else
+ 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
+ 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
+ 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
+ end
+ else
+ prev_r = r
+ if b > par.threshold then
+ continue_only = true
+ 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
+ else
+ 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
+ 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)
+ end
+ end
+ if d < par.minimum_demerits then
+ par.minimum_demerits = d
+ 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" }
+
+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
+
+ 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 dirstack = new_dir_stack()
+
+ if tracing_paragraphs then
+ diagnostics.start()
+ if par.pretolerance >= 0 then
+ diagnostics.current_pass(par,"firstpass")
+ 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
+
+ par.passive = nil -- = 0
+ par.printed_node = temp_head -- only when tracing, shared
+ par.pass_number = 0
+-- par.auto_breaking = true
+
+ setnext(temp_head,head)
+
+ local current = head
+ local first_p = current
+
+ local auto_breaking = true
+
+ 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
+
+ -- 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
+
+ -- use an active local
+
+ 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
+
+ local p_active = par.active
+ local n_active = p_active and p_active.next
+ local second_pass = par.second_pass
+
+ trialcount = 0
+
+ while current and p_active ~= n_active do
+ local char, id = isglyph(current)
+ if char then
+ if is_rotated[par.line_break_dir] then
+ active_width.size = active_width.size + getfield(current,"height") + getfield(current,"depth")
+ else
+ active_width.size = active_width.size + getfield(current,"width")
+ 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
+ end
+ end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if is_parallel[getfield(current,"dir")][par.line_break_dir] then
+ active_width.size = active_width.size + getfield(current,"width")
+ else
+ active_width.size = active_width.size + getfield(current,"depth") + getfield(current,"height")
+ 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
+ check_shrinkage(par,current)
+ local order = stretch_orders[getfield(current,"stretch_order")]
+ active_width.size = active_width.size + getfield(current,"width")
+ active_width[order] = active_width[order] + getfield(current,"stretch")
+ active_width.shrink = active_width.shrink + getfield(current,"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 = getfield(current,"penalty")
+ --
+ 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
+ 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)
+ 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));
+ --
+ 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
+ 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
+ end
+ end
+ end
+ 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 + getfield(current,"kern")
+ else
+ local kern = getfield(current,"kern")
+ if kern ~= 0 then
+ active_width.size = active_width.size + kern
+ if checked_expansion and expand_kerns and (getsubtype(current) == kerning_code or getattr(current,a_fontkern)) 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
+ 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 + getfield(current,"surround")
+ elseif id == rule_code then
+ active_width.size = active_width.size + getfield(current,"width")
+ elseif id == penalty_code then
+ p_active, n_active = try_break(getfield(current,"penalty"), 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
+ 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
+ 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 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")
+ end
+ par.background.stretch = par.background.stretch + par.emergency_stretch
+ par.final_pass = true
+ end
+ end
+ return tonode(wrap_up(par))
+end
+
+-- standard tex logging .. will be adapted ..
+
+local function write_esc(cs)
+ local esc = tex.escapechar
+ if esc then
+ write("log",utfchar(esc),cs)
+ else
+ write("log",cs)
+ end
+end
+
+function diagnostics.start()
+end
+
+function diagnostics.stop()
+ write_nl("log",'')
+end
+
+function diagnostics.current_pass(par,what)
+ write_nl("log",format("@%s",what))
+end
+
+local verbose = false -- true
+
+local function short_display(target,a,font_in_short_display)
+ 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
+ end
+ if getsubtype(a) == ligature_code then
+ font_in_short_display = short_display(target,getfield(a,"components"),font_in_short_display)
+ else
+ write(target,utfchar(char))
+ end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(a)
+ font_in_short_display = short_display(target,pre,font_in_short_display)
+ font_in_short_display = short_display(target,post,font_in_short_display)
+ elseif verbose then
+ write(target,format("[%s]",nodecodes[id]))
+ elseif id == rule_code then
+ write(target,"|")
+ elseif id == glue_code then
+ write(target," ")
+ elseif id == kern_code then
+ local s = getsubtype(a)
+ if s == userkern_code or s == italickern_code or getattr(a,a_fontkern) then
+ if verbose then
+ write(target,"[|]")
+ -- else
+ -- write(target,"")
+ end
+ else
+ write(target,"[]")
+ end
+ elseif id == math_code then
+ write(target,"$")
+ else
+ write(target,"[]")
+ end
+ a = getnext(a)
+ end
+ return font_in_short_display
+end
+
+diagnostics.short_display = short_display
+
+function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ?
+ local passive = par.passive
+ local typ_ind = break_type == hyphenated_code and '-' or ""
+ if par.do_last_line_fit then
+ local s = number.toscaled(q.active_short)
+ local g = number.toscaled(q.active_glue)
+ if current then
+ write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s g=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ else
+ write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s a=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ end
+ else
+ write_nl("log",format("@@%d: line %d.%d%s t=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
+ end
+ if not passive.prev_break then
+ write("log"," -> @0")
+ else
+ write("log",format(" -> @%d", passive.prev_break.serial or 0))
+ end
+end
+
+function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits)
+ local printed_node = par.printed_node
+ if printed_node ~= current then
+ write_nl("log","")
+ if not current then
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ else
+ local save_link = getnext(current)
+ setnext(current)
+ write_nl("log","")
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ setnext(current,save_link)
+ end
+ par.printed_node = current
+ end
+ write_nl("log","@")
+ if not current then
+ write_esc("par")
+ else
+ local id = getid(current)
+ if id == glue_code then
+ -- print nothing
+ elseif id == penalty_code then
+ write_esc("penalty")
+ elseif id == disc_code then
+ write_esc("discretionary")
+ elseif id == kern_code then
+ write_esc("kern")
+ elseif id == math_code then
+ write_esc("math")
+ else
+ write_esc("unknown")
+ end
+ end
+ local via, badness, demerits = 0, '*', '*'
+ if r.break_node then
+ via = r.break_node.serial or 0
+ end
+ if b <= infinite_badness then
+ badness = tonumber(d) -- format("%d", b)
+ end
+ if not artificial_demerits then
+ demerits = tonumber(d) -- format("%d", d)
+ end
+ write("log",format(" via @%d b=%s p=%s d=%s", via, badness, pi, demerits))
+end
+
+-- reporting --
+
+statistics.register("alternative parbuilders", function()
+ if nofpars > 0 then
+ return format("%s paragraphs, %s lines (%s protruded, %s adjusted)", nofpars, noflines, nofprotrudedlines, nofadjustedlines)
+ end
+end)
+
+-- actually scaling kerns is not such a good idea and it will become
+-- configureable
+
+-- This is no way a replacement for the built in (fast) packer
+-- it's just an alternative for special (testing) purposes.
+--
+-- We could use two hpacks: one to be used in the par builder
+-- and one to be used for other purposes. The one in the par
+-- builder is much more simple as it does not need the expansion
+-- code but only need to register the effective expansion factor
+-- with the glyph.
+
+local function glyph_width_height_depth(curdir,pdir,p)
+ local wd = getfield(p,"width")
+ local ht = getfield(p,"height")
+ local dp = getfield(p,"depth")
+ 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 = getfield(p,"width")
+ local ht = getfield(p,"height")
+ local dp = getfield(p,"depth")
+ 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)
+--
+-- local expansion = method == "cal_expand_ratio"
+-- local natural = analysis.size
+-- local font_stretch = analysis.adjust_stretch
+-- local font_shrink = analysis.adjust_shrink
+-- local font_expand_ratio = 0
+-- local delta = width - natural
+--
+-- local hlist = new_node("hlist")
+--
+-- setlist(hlist,head)
+-- setfield(hlist,"dir",direction or tex.textdir)
+-- setfield(hlist,"width",width)
+-- setfield(hlist,"height",height)
+-- setfield(hlist,"depth",depth)
+--
+-- if delta == 0 then
+--
+-- setfield(hlist,"glue_sign",0)
+-- setfield(hlist,"glue_order",0)
+-- setfield(hlist,"glue_set",0)
+--
+-- else
+--
+-- local order = analysis.filll ~= 0 and fillcodes.filll or
+-- analysis.fill ~= 0 and fillcodes.fill or
+-- analysis.fil ~= 0 and fillcodes.fil or
+-- analysis.fi ~= 0 and fillcodes.fi or 0
+--
+-- if delta > 0 then
+--
+-- if expansion and order == 0 and font_stretch > 0 then
+-- font_expand_ratio = (delta/font_stretch) * 1000
+-- else
+-- local stretch = analysis.stretch
+-- if stretch ~= 0 then
+-- setfield(hlist,"glue_sign",1) -- stretch
+-- setfield(hlist,"glue_order",order)
+-- setfield(hlist,"glue_set",delta/stretch)
+-- else
+-- setfield(hlist,"glue_sign",0) -- nothing
+-- setfield(hlist,"glue_order",order)
+-- setfield(hlist,"glue_set",0)
+-- end
+-- end
+--
+-- else
+--
+-- if expansion and order == 0 and font_shrink > 0 then
+-- font_expand_ratio = (delta/font_shrink) * 1000
+-- else
+-- local shrink = analysis.shrink
+-- if shrink ~= 0 then
+-- setfield(hlist,"glue_sign",2) -- shrink
+-- setfield(hlist,"glue_order",order)
+-- setfield(hlist,"glue_set",-delta/stretch)
+-- else
+-- setfield(hlist,"glue_sign",0) -- nothing
+-- setfield(hlist,"glue_order",order)
+-- setfield(hlist,"glue_set",0)
+-- end
+-- end
+--
+-- end
+--
+-- end
+--
+-- if not expansion or font_expand_ratio == 0 then
+-- -- nothing
+-- elseif font_expand_ratio > 0 then
+-- if font_expand_ratio > 1000 then
+-- font_expand_ratio = 1000
+-- end
+-- local current = head
+-- while current do
+-- local id = getid(current)
+-- if id == glyph_code then
+-- local stretch, shrink = char_stretch_shrink(current) -- get only one
+-- if stretch then
+-- if trace_expansion then
+-- setnodecolor(g,"hz:positive")
+-- end
+-- current.expansion_factor = font_expand_ratio * stretch
+-- end
+-- elseif id == kern_code then
+-- local kern = getfield(current,"kern")
+-- if kern ~= 0 and getsubtype(current) == kerning_code then
+-- setfield(current,"kern",font_expand_ratio * kern)
+-- end
+-- end
+-- current = getnext(current)
+-- end
+-- elseif font_expand_ratio < 0 then
+-- if font_expand_ratio < -1000 then
+-- font_expand_ratio = -1000
+-- end
+-- local current = head
+-- while current do
+-- local id = getid(current)
+-- if id == glyph_code then
+-- local stretch, shrink = char_stretch_shrink(current) -- get only one
+-- if shrink then
+-- if trace_expansion then
+-- setnodecolor(g,"hz:negative")
+-- end
+-- current.expansion_factor = font_expand_ratio * shrink
+-- end
+-- elseif id == kern_code then
+-- local kern = getfield(current,"kern")
+-- if kern ~= 0 and getsubtype(current) == kerning_code then
+-- setfield(current,"kern",font_expand_ratio * kern)
+-- end
+-- end
+-- current = getnext(current)
+-- end
+-- end
+-- return hlist, 0
+-- end
+
+local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil
+
+ -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
+ -- with the glue mess it's less trivial as we lack detail .. challenge
+
+ local hlist = new_node("hlist")
+
+ setfield(hlist,"dir",direction)
+
+ if head == nil then
+ setfield(hlist,"width",width)
+ return hlist, 0
+ else
+ setlist(hlist,head)
+ end
+
+ local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font"
+
+ direction = direction or tex.textdir
+
+ local line = 0
+
+ local height = 0
+ local depth = 0
+ local natural = 0
+ local font_stretch = 0
+ local font_shrink = 0
+ local font_expand_ratio = 0
+ local last_badness = 0
+ local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
+ local expansion_index = 0
+ local total_stretch = { [0] = 0, 0, 0, 0, 0 }
+ local total_shrink = { [0] = 0, 0, 0, 0, 0 }
+
+ local hpack_dir = direction
+
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ local adjust_tail = adjust_head and slide_nodelist(adjust_head) -- todo: find_tail
+ local pre_adjust_tail = pre_adjust_head and slide_nodelist(pre_adjust_head) -- todo: find_tail
+
+ new_dir_stack(hpack_dir)
+
+ local checked_expansion = false
+
+ if cal_expand_ratio then
+ checked_expansion = { }
+ setmetatableindex(checked_expansion,check_expand_lines)
+ end
+
+ -- this one also needs to check the font, so in the end indeed we might end up with two variants
+
+ local fontexps, lastfont
+
+ local function process(current) -- called nested in disc replace
+
+ while current 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
+ end
+ if fontexps then
+ local expansion = fontexps[char]
+ if expansion then
+ font_stretch = font_stretch + expansion.glyphstretch
+ font_shrink = font_shrink + expansion.glyphshrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ end
+ end
+ -- use inline
+ local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ elseif id == kern_code then
+ local kern = getfield(current,"kern")
+ if kern == 0 then
+ -- no kern
+ elseif getsubtype(current) == kerning_code then -- check getfield(p,"kern")
+ if cal_expand_ratio then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ font_stretch = font_stretch + stretch
+ font_shrink = font_shrink + shrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ natural = natural + kern
+ else
+ natural = natural + kern
+ end
+ elseif id == disc_code then
+ local subtype = getsubtype(current)
+ if subtype ~= second_disc_code then
+ -- todo : local stretch, shrink = char_stretch_shrink(s)
+ local replace = getfield(current,"replace")
+ if replace then
+ process(replace)
+ end
+ end
+ elseif id == glue_code then
+ natural = natural + getfield(current,"width")
+ local op = getfield(current,"stretch_order")
+ local om = getfield(current,"shrink_order")
+ total_stretch[op] = total_stretch[op] + getfield(current,"stretch")
+ total_shrink [om] = total_shrink [om] + getfield(current,"shrink")
+ if getsubtype(current) >= leaders_code then
+ local leader = getleader(current)
+ local ht = getfield(leader,"height")
+ local dp = getfield(leader,"depth")
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local sh = getfield(current,"shift")
+ local wd, ht, dp = pack_width_height_depth(hpack_dir,getfield(current,"dir") or hpack_dir,current) -- added: or pack_dir
+ local hs, ds = ht - sh, dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == rule_code then
+ local wd = getfield(current,"width")
+ local ht = getfield(current,"height")
+ local dp = getfield(current,"depth")
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ elseif id == math_code then
+ natural = natural + getfield(current,"surround")
+ elseif id == unset_code then
+ local wd = getfield(current,"width")
+ local ht = getfield(current,"height")
+ local dp = getfield(current,"depth")
+ local sh = getfield(current,"shift")
+ local hs = ht - sh
+ local ds = dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == ins_code or id == mark_code then
+ local prev, next = getboth(current)
+ if adjust_tail then -- todo
+ setlink(prev,next)
+ setlink(adjust_tail,current)
+ setnext(current)
+ adjust_tail = current
+ else
+ adjust_head = current
+ adjust_tail = current
+ setboth(current)
+ end
+ elseif id == adjust_code then
+ local list = getlist(current)
+ if adjust_tail then
+ setnext(adjust_tail,list)
+ else
+ adjust_head = list
+ end
+ adjust_tail = slide_nodelist(list) -- find_tail(list)
+ elseif id == dir_code then
+ hpack_dir = checked_line_dir(stack,current) or hpack_dir
+ elseif id == marginkern_code then
+ local width = getfield(current,"width")
+ if cal_expand_ratio then
+ -- is this ok?
+ local glyph = getfield(current,"glyph")
+ local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw
+ font_stretch = font_stretch - width - char_pw(glyph)
+ font_shrink = font_shrink - width - char_pw(glyph)
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = glyph
+ end
+ natural = natural + width
+ end
+ current = getnext(current)
+ end
+
+ end
+
+ process(head)
+
+ if adjust_tail then
+ adjust_tail.next = nil -- todo
+ end
+ if pre_adjust_tail then
+ pre_adjust_tail.next = nil -- todo
+ end
+ if method == "additional" then
+ width = width + natural
+ end
+
+ setfield(hlist,"width",width)
+ setfield(hlist,"height",height)
+ setfield(hlist,"depth",depth)
+
+ local delta = width - natural
+ if delta == 0 then
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",0)
+ setfield(hlist,"glue_set",0)
+ elseif delta > 0 then
+ -- natural width smaller than requested width
+ local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
+ (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
+ if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch
+ font_expand_ratio = delta/font_stretch
+
+ if font_expand_ratio > 1 then
+ font_expand_ratio = 1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:positive")
+ end
+ e = font_expand_ratio * data.glyphstretch / 1000
+ else
+ local kern = getfield(g,"kern")
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * stretch / 1000
+ end
+ setfield(g,"expansion_factor",e)
+ end
+ end
+ local tso = total_stretch[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",1)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
+ end
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif order == 0 then -- and getlist(hlist) then
+ last_badness = calculate_badness(delta,total_stretch[0])
+ if last_badness > tex.hbadness then
+ if last_badness > 100 then
+ diagnostics.underfull_hbox(hlist,line,last_badness)
+ else
+ diagnostics.loose_hbox(hlist,line,last_badness)
+ end
+ end
+ end
+ else
+ -- natural width larger than requested width
+ local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
+ or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
+ if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink
+ font_expand_ratio = delta/font_shrink
+
+ if font_expand_ratio < 1 then
+ font_expand_ratio = -1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:negative")
+ end
+ e = font_expand_ratio * data.glyphshrink / 1000
+ else
+ local kern = getfield(g,"kern")
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * shrink / 1000
+ end
+ setfield(g,"expansion_factor",e)
+ end
+ end
+ local tso = total_shrink[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",2)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",-delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
+ end
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif tso < -delta and order == 0 then -- and getlist(hlist) then
+ last_badness = 1000000
+ setfield(hlist,"glue_set",1)
+ local fuzz = - delta - total_shrink[0]
+ local hfuzz = tex.hfuzz
+ if fuzz > hfuzz or tex.hbadness < 100 then
+ local overfullrule = tex.overfullrule
+ if fuzz > hfuzz and overfullrule > 0 then
+ -- weird, is always called and no rules shows up
+ setfield(slide_nodelist(list),"next",new_rule(overfullrule,nil,nil,hlist.dir)) -- todo: find_tail
+ end
+ diagnostics.overfull_hbox(hlist,line,-delta)
+ end
+ elseif order == 0 and getlist(hlist) and last_badness > tex.hbadness then
+ diagnostics.bad_hbox(hlist,line,last_badness)
+ end
+ end
+ return hlist, last_badness
+end
+
+xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess)
+
+constructors.methods.hpack = hpack
+
+local function common_message(hlist,line,str)
+ write_nl("")
+ if status.output_active then -- unset
+ write(str," has occurred while \\output is active")
+ end
+ local fileline = status.linenumber
+ if line > 0 then
+ write(str," in paragraph at lines ",fileline,"--",fileline+line-1)
+ elseif line < 0 then
+ write(str," in alignment at lines ",fileline,"--",fileline-line-1)
+ else
+ write(str," detected at line ",fileline)
+ end
+ write_nl("")
+ diagnostics.short_display(hlist.list,false)
+ write_nl("")
+ -- diagnostics.start()
+ -- show_box(hlist.list)
+ -- diagnostics.stop()
+end
+
+function diagnostics.overfull_hbox(hlist,line,d)
+ common_message(hlist,line,format("Overfull \\hbox (%spt too wide)",number.toscaled(d)))
+end
+
+function diagnostics.bad_hbox(hlist,line,b)
+ common_message(hlist,line,format("Tight \\hbox (badness %i)",b))
+end
+
+function diagnostics.underfull_hbox(hlist,line,b)
+ common_message(hlist,line,format("Underfull \\hbox (badness %i)",b))
+end
+
+function diagnostics.loose_hbox(hlist,line,b)
+ common_message(hlist,line,format("Loose \\hbox (badness %i)",b))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-met.lua b/Master/texmf-dist/tex/context/base/mkiv/node-met.lua
new file mode 100644
index 00000000000..272b1d1769a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-met.lua
@@ -0,0 +1,652 @@
+if not modules then modules = { } end modules ['node-nut'] = {
+ 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"
+}
+
+-- This is an experimental module. Don't use nuts for generic code, at least not till
+-- the regular code is proven stable. No support otherwise.
+
+-- luatex: todo: copylist should return h, t
+-- todo: see if using insert_before and insert_after makes sense here
+
+-- This file is a side effect of the \LUATEX\ speed optimization project of Luigi
+-- Scarso and me. As \CONTEXT\ spends over half its time in \LUA, we though that
+-- using \LUAJIT\ could improve performance. We've published some of our experiences
+-- elsewhere, but to summarize: \LUAJITTEX\ benefits a lot from the faster virtual
+-- machine, but when jit is turned of we loose some again. We experimented with
+-- ffi (without messing up the \CONTEXT\ code too much) but there we also lost more
+-- than we gained (mostly due to lack of compatible userdata support: it's all or
+-- nothing). This made us decide to look into the \LUA||\TEX\ interfacing and by
+-- profiling and careful looking at the (of course then still beta source code) we
+-- could come up with some improvements. The first showed up in 0.75 and we've more
+-- on the agenda for 0.80. Although some interfaces could be sped up significantly
+-- in practice we're only talking of 5||10\% on a \CONTEXT\ run and maybe more when
+-- complex and extensive node list manipulations happens (we're talking of hundreds
+-- of millions cross boundary calls then for documents of hundreds pages). One of the
+-- changes in the \CONTEXT\ code base is that we went from indexed access to nodes to
+-- function calls (in principle faster weren't it that the accessors need to do more
+-- checking which makes them slower) and from there to optimizing these calls as well
+-- as providing fast variants for well defined situations. At first optimizations were
+-- put in a separate \type {node.fast} table although some improvements could be
+-- ported to the main node functions. Because we got the feeling that more gain was
+-- possible (especially when using more complex fonts and \MKIV\ functionality) we
+-- eventually abandoned this approach and dropped the \type {fast} table in favour of
+-- another hack. In the process we had done lots of profiling and testing so we knew
+-- where time was wasted,
+--
+-- As lots of testing and experimenting was part of this project, I could not have
+-- done without stacks of new \CD s and \DVD s. This time Porcupine Tree, No-Man
+-- and Archive were came to rescue.
+
+local type, select = type, select
+local setmetatableindex = table.setmetatableindex
+
+-- First we get the metatable of a node:
+
+local metatable = nil
+
+do
+ local glyph = node.new("glyph",0)
+ metatable = getmetatable(glyph)
+ node.free(glyph)
+end
+
+-- statistics.tracefunction(node, "node", "getfield","setfield")
+-- statistics.tracefunction(node.direct,"node.direct","getfield","setfield")
+
+-- We start with some helpers and provide all relevant basic functions in the
+-- node namespace as well.
+
+nodes = nodes or { }
+local nodes = nodes
+
+----- gonuts = type(node.direct) == "table"
+-----.gonuts = gonuts
+
+local nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+nodes.tostring = node.tostring or tostring
+nodes.copy = node.copy
+nodes.copy_list = node.copy_list
+nodes.delete = node.delete
+nodes.dimensions = node.dimensions
+nodes.end_of_math = node.end_of_math
+nodes.flush_list = node.flush_list
+nodes.flush_node = node.flush_node
+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.first_glyph = node.first_glyph
+nodes.has_glyph = node.has_glyph or node.first_glyph
+
+nodes.current_attr = node.current_attr
+nodes.do_ligature_n = node.do_ligature_n
+nodes.has_field = node.has_field
+nodes.last_node = node.last_node
+nodes.usedlist = node.usedlist
+nodes.protrusion_skippable = node.protrusion_skippable
+nodes.write = node.write
+
+nodes.has_attribute = node.has_attribute
+nodes.set_attribute = node.set_attribute
+nodes.unset_attribute = node.unset_attribute
+
+nodes.protect_glyphs = node.protect_glyphs
+nodes.protect_glyph = node.protect_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.is_zero_glue = node.is_zero_glue
+nodes.getglue = node.getglue
+nodes.getglue = node.getglue
+
+-- if not gonuts or not node.getfield then
+-- node.getfield = metatable.__index
+-- node.setfield = metatable.__newindex
+-- end
+
+nodes.tonode = function(n) return n end
+nodes.tonut = function(n) return n end
+
+local getfield = node.getfield
+local setfield = node.setfield
+
+local getattr = node.get_attribute
+local setattr = setfield
+
+local n_getid = node.getid
+local n_getlist = node.getlist
+local n_getnext = node.getnext
+local n_getprev = node.getprev
+local n_getchar = node.getchar
+local n_getfont = node.getfont
+local n_getsubtype = node.getsubtype
+local n_setfield = node.setfield
+local n_getfield = node.getfield
+local n_setattr = node.setattr
+local n_getattr = node.getattr
+local n_getdisc = node.getdisc
+local n_getleader = node.getleader
+
+local n_setnext = node.setnext or
+ function(c,next)
+ setfield(c,"next",n)
+ end
+local n_setprev = node.setprev or
+ function(c,prev)
+ setfield(c,"prev",p)
+ end
+local n_setlink = node.setlink or
+ function(c1,c2)
+ if c1 then setfield(c1,"next",c2) end
+ if c2 then setfield(c2,"prev",c1) end
+ end
+local n_setboth = node.setboth or
+ function(c,p,n)
+ setfield(c,"prev",p)
+ setfield(c,"next",n)
+ end
+
+node.setnext = n_setnext
+node.setprev = n_setprev
+node.setlink = n_setlink
+node.setboth = n_setboth
+
+nodes.getfield = n_getfield
+nodes.setfield = n_setfield
+nodes.getattr = n_getattr
+nodes.setattr = n_setattr
+
+nodes.getnext = n_getnext
+nodes.getprev = n_getprev
+nodes.getid = n_getid
+nodes.getchar = n_getchar
+nodes.getfont = n_getfont
+nodes.getsubtype = n_getsubtype
+nodes.getlist = n_getlist
+nodes.getleader = n_getleader
+nodes.getdisc = n_getdisc
+-----.getpre = node.getpre or function(n) local h, _, _, t = n_getdisc(n,true) return h, t end
+-----.getpost = node.getpost or function(n) local _, h, _, _, t = n_getdisc(n,true) return h, t end
+-----.getreplace = node.getreplace or function(n) local _, _, h, _, _, t = n_getdisc(n,true) return h, t end
+
+nodes.is_char = node.is_char
+nodes.ischar = node.is_char
+
+nodes.is_glyph = node.is_glyph
+nodes.isglyph = node.is_glyph
+
+nodes.getbox = node.getbox or tex.getbox
+nodes.setbox = node.setbox or tex.setbox
+nodes.getskip = node.getskip or tex.get
+
+local n_new_node = nodes.new
+local n_free_node = nodes.free
+local n_copy_node = nodes.copy
+local n_copy_list = nodes.copy_list
+local n_find_tail = nodes.tail
+local n_insert_after = nodes.insert_after
+local n_insert_before = nodes.insert_before
+local n_slide = nodes.slide
+
+local n_remove_node = node.remove -- not yet nodes.remove
+
+local function remove(head,current,free_too)
+ local t = current
+ head, current = n_remove_node(head,current)
+ if not t then
+ -- forget about it
+ elseif free_too then
+ n_free_node(t)
+ t = nil
+ else
+ n_setboth(t)
+ end
+ return head, current, t
+end
+
+nodes.remove = remove
+
+function nodes.delete(head,current)
+ return remove(head,current,true)
+end
+
+-- local h, c = nodes.replace(head,current,new)
+-- local c = nodes.replace(false,current,new)
+-- local c = nodes.replace(current,new)
+--
+-- todo: check for new.next and find tail
+
+function nodes.replace(head,current,new) -- no head returned if false
+ if not new then
+ head, current, new = false, head, current
+-- current, new = head, current
+ end
+ local prev = n_getprev(current)
+ local next = n_getnext(current)
+ if next then
+ n_setlink(new,next)
+ end
+ if prev then
+ n_setlink(prev,new)
+ end
+ if head then
+ if head == current then
+ head = new
+ end
+ n_free_node(current)
+ return head, new
+ else
+ n_free_node(current)
+ return new
+ end
+end
+
+local function count(stack,flat)
+ local n = 0
+ while stack do
+ local id = n_getid(stack)
+ if not flat and id == hlist_code or id == vlist_code then
+ local list = n_getlist(stack)
+ if list then
+ n = n + 1 + count(list) -- self counts too
+ else
+ n = n + 1
+ end
+ else
+ n = n + 1
+ end
+ stack = n_getnext(stack)
+ end
+ return n
+end
+
+nodes.count = count
+
+function nodes.append(head,current,...)
+ for i=1,select("#",...) do
+ head, current = n_insert_after(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nodes.prepend(head,current,...)
+ for i=1,select("#",...) do
+ head, current = n_insert_before(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nodes.linked(...)
+ local head, last
+ for i=1,select("#",...) do
+ local next = select(i,...)
+ if next then
+ if head then
+ n_setlink(last,next)
+ else
+ head = next
+ end
+ last = n_find_tail(next) -- we could skip the last one
+ end
+ end
+ return head
+end
+
+function nodes.concat(list) -- consider tail instead of slide
+ local head, tail
+ for i=1,#list do
+ local li = list[i]
+ if li then
+ if head then
+ n_setlink(tail,li)
+ else
+ head = li
+ end
+ tail = n_slide(li)
+ end
+ end
+ return head, tail
+end
+
+--[[
+<p>At some point we ran into a problem that the glue specification
+of the zeropoint dimension was overwritten when adapting a glue spec
+node. This is a side effect of glue specs being shared. After a
+couple of hours tracing and debugging Taco and I came to the
+conclusion that it made no sense to complicate the spec allocator
+and settled on a writable flag. This all is a side effect of the
+fact that some glues use reserved memory slots (with the zeropoint
+glue being a noticeable one). So, next we wrap this into a function
+and hide it for the user. And yes, LuaTeX now gives a warning as
+well.</p>
+]]--
+
+function nodes.reference(n)
+ return n and tonut(n) or "<none>"
+end
+
+-- Here starts an experiment with metatables. Of course this only works with nodes
+-- wrapped in userdata with a metatable.
+--
+-- Nodes are kind of special in the sense that you need to keep an eye on creation
+-- and destruction. This is quite natural if you consider that changing the content
+-- of a node would also change any copy (or alias). As there are too many pitfalls
+-- we don't have this kind of support built in \LUATEX, which means that macro
+-- packages are free to provide their own. One can even use local variants.
+--
+-- n1 .. n2 : append nodes, no copies
+-- n1 * 5 : append 4 copies of nodes
+-- 5 + n1 : strip first 5 nodes
+-- n1 - 5 : strip last 5 nodes
+-- n1 + n2 : inject n2 after first of n1
+-- n1 - n2 : inject n2 before last of n1
+-- n1^2 : two copies of nodes (keep orginal)
+-- - n1 : reverse nodes
+-- n1/f : apply function to nodes
+
+-- local s = nodes.typesetters.tonodes
+--
+-- local function w(lst)
+-- context.dontleavehmode()
+-- context(lst)
+-- context.par()
+-- end
+--
+-- local n1 = s("a")
+-- local n2 = s("b")
+-- local n3 = s("c")
+-- local n4 = s("d")
+-- local n5 = s("e")
+-- local n6 = s("f")
+-- local n7 = s("g")
+--
+-- local n0 = n1 .. (n2 * 10).. n3 .. (5 * n4) .. n5 .. ( 5 * n6 ) .. n7 / function(n) n.char = string.byte("!") return n end
+--
+-- w(#n0)
+--
+-- w(n0)
+--
+-- local n1 = s("a") * 10
+-- local n2 = s("b") * 10
+--
+-- local n0 = ((5 + n1) .. (n2 - 5) )
+-- local n0 = - n0
+--
+-- local n0 = nil .. n0^3 .. nil
+--
+-- w(n0)
+--
+-- w ( s("a") + s("b") ) w ( s("a") + 4*s("b") ) w ( 4*s("a") + s("b") ) w ( 4*s("a") + 4*s("b") )
+-- w ( s("a") - s("b") ) w ( s("a") - 4*s("b") ) w ( 4*s("a") - s("b") ) w ( 4*s("a") - 4*s("b") )
+
+local n_remove_node = nodes.remove
+
+metatable.__concat = function(n1,n2) -- todo: accept nut on one end
+ if not n1 then
+ return n2
+ elseif not n2 then
+ return n1
+ elseif n1 == n2 then
+ -- or abort
+ return n2 -- or n2 * 2
+ else
+ local tail = n_find_tail(n1)
+ n_setlink(tail,n2)
+ return n1
+ end
+end
+
+metatable.__mul = function(n,multiplier)
+ if type(multiplier) ~= "number" then
+ n, multiplier = multiplier, n
+ end
+ if multiplier <= 1 then
+ return n
+ elseif n_getnext(n) then
+ local head
+ for i=2,multiplier do
+ local h = n_copy_list(n)
+ if head then
+ local t = n_find_tail(h)
+ n_setlink(t,head)
+ end
+ head = h
+ end
+ local t = n_find_tail(n)
+ n_setlink(t,head)
+ else
+ local head
+ for i=2,multiplier do
+ local c = n_copy_node(n)
+ if head then
+ n_setlink(c,head)
+ end
+ head = c
+ end
+ n_setlink(n,head)
+ end
+ return n
+end
+
+metatable.__sub = function(first,second)
+ if type(second) == "number" then
+ local tail = n_find_tail(first)
+ for i=1,second do
+ local prev = n_getprev(tail)
+ n_free_node(tail) -- can become flushlist/flushnode
+ if prev then
+ tail = prev
+ else
+ return nil
+ end
+ end
+ if tail then
+ n_setnext(tail)
+ return first
+ else
+ return nil
+ end
+ else
+ -- aaaaa - bbb => aaaabbba
+ local firsttail = n_find_tail(first)
+ local prev = n_getprev(firsttail)
+ if prev then
+ local secondtail = n_find_tail(second)
+ n_setlink(secondtail,firsttail)
+ n_setlink(prev,second)
+ return first
+ else
+ local secondtail = n_find_tail(second)
+ n_setlink(secondtail,first)
+ return second
+ end
+ end
+end
+
+metatable.__add = function(first,second)
+ if type(first) == "number" then
+ local head = second
+ for i=1,first do
+ local second = n_getnext(head)
+ n_free_node(head) -- can become flushlist/flushnode
+ if second then
+ head = second
+ else
+ return nil
+ end
+ end
+ if head then
+ n_setprev(head)
+ return head
+ else
+ return nil
+ end
+ else
+ -- aaaaa + bbb => abbbaaaa
+ local next = n_getnext(first)
+ if next then
+ local secondtail = n_find_tail(second)
+ n_setlink(first,second)
+ n_setlink(secondtail,next)
+ else
+ n_setlink(first,second)
+ end
+ return first
+ end
+end
+
+metatable.__len = function(current)
+ local length = 0
+ while current do
+ current = n_getnext(current)
+ length = length + 1
+ end
+ return length
+end
+
+metatable.__div = function(list,action)
+ return action(list) or list -- always a value
+end
+
+metatable.__pow = function(n,multiplier)
+ local tail = n
+ local head = nil
+ if n_getnext(n) then
+ if multiplier == 1 then
+ head = n_copy_list(n)
+ else
+ for i=1,multiplier do
+ local h = n_copy_list(n)
+ if head then
+ local t = n_find_tail(h)
+ n_setlink(t,head)
+ end
+ head = h
+ end
+ end
+ else
+ if multiplier == 1 then
+ head = n_copy_node(n)
+ else
+ for i=2,multiplier do
+ local c = n_copy_node(n)
+ if head then
+ n_setlink(head,c)
+ end
+ head = c
+ end
+ end
+ end
+ -- todo: tracing
+ return head
+end
+
+metatable.__unm = function(head)
+ local last = head
+ local first = head
+ local current = n_getnext(head)
+ while current do
+ local next = n_getnext(current)
+ n_setlink(current,first)
+ first = current
+ current = next
+ end
+ n_setprev(first)
+ n_setnext(last)
+ return first
+end
+
+-- see node-nut.lua for more info on going nuts
+
+-- if not gonuts then
+--
+-- local nuts = { }
+-- nodes.nuts = nuts
+--
+-- local function dummy(f) return f end
+--
+-- nodes.vianuts = dummy
+-- nodes.vianodes = dummy
+--
+-- for k, v in next, nodes do
+-- if type(v) == "function" then
+-- nuts[k] = v
+-- end
+-- end
+--
+-- end
+
+-- also handy
+
+local tonode = nodes.tonode
+local whatsit_code = nodecodes.whatsit
+local getfields = node.fields
+local sort = table.sort
+local whatsitkeys = { }
+local keys = { whatsit = whatsitkeys }
+local messyhack = table.tohash { -- temporary solution
+ nodecodes.attributelist,
+ nodecodes.attribute,
+ nodecodes.gluespec,
+ nodecodes.action,
+}
+
+table.setmetatableindex(keys,function(t,k)
+ local v = getfields(k)
+ if messyhack[k] then
+ for i=1,#v do
+ if v[i] == "subtype" then
+ remove(v,i)
+ break
+ end
+ end
+ end
+ if v[ 0] then v[#v+1] = "next" v[ 0] = nil end
+ if v[-1] then v[#v+1] = "prev" v[-1] = nil end
+ sort(v)
+ t[k] = v
+ return v
+end)
+
+table.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
+ sort(v)
+ t[k] = v
+ return v
+end)
+
+local function nodefields(n)
+ n = tonode(n)
+ local id = n.id
+ if id == whatsit_code then
+ return whatsitkeys[n.subtype]
+ else
+ return keys[id]
+ end
+end
+
+nodes.keys = keys -- [id][subtype]
+nodes.fields = nodefields -- (n)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua b/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua
new file mode 100644
index 00000000000..24bebb0ccb2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua
@@ -0,0 +1,165 @@
+if not modules then modules = { } end modules ['node-mig'] = {
+ version = 1.001,
+ comment = "companion to node-mig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: insert_after
+
+local format = string.format
+
+local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end)
+
+local report_nodes = logs.reporter("nodes","migrations")
+
+local attributes = attributes
+local nodes = nodes
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setprev = nuts.setprev
+local setnext = nuts.setnext
+
+local remove_node = nuts.remove
+
+local nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+
+local a_migrated = attributes.private("migrated")
+
+local migrate_inserts, migrate_marks, inserts_too
+
+local t_inserts, t_marks, t_sweeps = 0, 0, 0
+
+local function locate(head,first,last,ni,nm)
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == vlist_code or id == hlist_code then
+ local list = getlist(current)
+ if list then
+ list, first, last, ni, nm = locate(list,first,last,ni,nm)
+ setlist(current,list)
+ end
+ current = getnext(current)
+ elseif migrate_inserts and id == insert_code then
+ local insert
+ head, current, insert = remove_node(head,current)
+ setnext(insert)
+ if first then
+ setlink(last,insert)
+ else
+ setprev(insert)
+ first = insert
+ end
+ last = insert
+ ni = ni + 1
+ elseif migrate_marks and id == mark_code then
+ local mark
+ head, current, mark = remove_node(head,current)
+ setnext(mark)
+ if first then
+ setlink(last,mark)
+ else
+ setprev(mark)
+ first = mark
+ end
+ last = mark
+ nm = nm + 1
+ else
+ current = getnext(current)
+ end
+ end
+ return 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)
+ while current do
+ local id = getid(current)
+ -- inserts_too is a temp hack, we should only do them when it concerns
+ -- newly placed (flushed) inserts
+ if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not getattr(current,a_migrated) then
+ setattr(current,a_migrated,1)
+ t_sweeps = t_sweeps + 1
+ local h = getlist(current)
+ local first, last, ni, nm
+ while h do
+ local id = getid(h)
+ if id == vlist_code or id == hlist_code then
+ h, first, last, ni, nm = locate(h,first,last,0,0)
+ end
+ h = getnext(h)
+ end
+ if first then
+ t_inserts = t_inserts + ni
+ t_marks = t_marks + nm
+ if trace_migrations and (ni > 0 or nm > 0) then
+ report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a",
+ t_sweeps,nodecodes[id],ni,nm,where)
+ end
+ -- inserts after head, use insert_after
+ local n = getnext(current)
+ if n then
+ setlink(last,n)
+ end
+ setlink(current,first)
+ done = true
+ current = last
+ end
+ end
+ current = getnext(next)
+ end
+ return head, done
+ end
+end
+
+-- for the moment this way, this will disappear
+
+experiments.register("marks.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ migrate_marks = v
+end)
+
+experiments.register("inserts.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ migrate_inserts = v
+end)
+
+experiments.register("inserts.migrate.nested", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ inserts_too = v
+end)
+
+statistics.register("node migrations", function()
+ if trace_migrations and t_sweeps > 0 then
+ return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks)
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-mig.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-mig.mkiv
new file mode 100644
index 00000000000..143fd4466e5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-mig.mkiv
@@ -0,0 +1,61 @@
+%D \module
+%D [ file=node-mig,
+%D version=2010.01.19,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Inserts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Support / Migrations}
+
+%D This is very experimental and although it is used in a
+%D real project it mostly serves a testbed for Taco and me so
+%D as prelude to extending the inserts mechanism.
+%D
+%D \starttyping
+%D \automigrateinserts
+%D
+%D \hbox{\vbox{x\footnote{1}x\footnote{2}x\footnote{3}x}}
+%D \vbox{x\footnote{4}x}
+%D \hbox{\vbox{x\footnote{5}x}}
+%D
+%D \hbox{x}
+%D \hbox{x\footnote{6}x}
+%D \hbox{x}
+%D
+%D \starttabulate
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \stoptabulate
+%D \stoptyping
+
+\unprotect
+
+\registerctxluafile{node-mig}{1.001}
+
+\newtoks\everyautomigratefootnotes
+\newtoks\everyautomigratemarks
+
+\def\automigrateinserts{\the\everyautomigratefootnotes} % soon default but does not work (yet) for notes in captions (themselves inserts)
+\def\automigratemarks {\the\everyautomigratemarks}
+
+\appendtoks
+ \let\postponenotes\relax
+ \enableexperiments[inserts.migrate,inserts.migrate.nested]%
+\to \everyautomigratefootnotes
+
+\appendtoks
+ \writestatus\m!system{migration of marks is normally not needed}%
+ \enableexperiments[marks.migrate]%
+\to \everyautomigratemarks
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua b/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua
new file mode 100644
index 00000000000..1465a668019
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua
@@ -0,0 +1,759 @@
+if not modules then modules = { } end modules ['node-met'] = {
+ 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"
+}
+
+-- Here starts some more experimental code that Luigi and I use in a next stage of
+-- exploring and testing potential speedups in the engines. This code is not meant
+-- for users and can change (or be removed) any moment. During the experiments I'll
+-- do my best to keep the code as fast as possible by using two codebases. See
+-- about-fast.pdf for some more info about impacts. Although key based access has
+-- more charm, function based is somewhat faster and has more potential for future
+-- speedups.
+
+-- This next iteration is flagged direct because we avoid user data which has a price
+-- in allocation and metatable tagging. Although in this stage we pass numbers around
+-- future versions might use light user data, so never depend on what direct function
+-- return. Using the direct approach had some speed advantages but you loose the key
+-- based access. The speed gain is only measurable in cases with lots of access. For
+-- instance when typesettign arabic with advanced fonts, we're talking of many millions
+-- of function calls and there we can get a 30\% or more speedup. On average complex
+-- \CONTEXT\ runs the gain can be 10\% to 15\% percent. Because mixing the two models
+-- (here we call then nodes and nuts) is not possible you need to cast either way which
+-- has a penalty. Also, error messages in nuts mode are less clear and \LUATEX\ will
+-- often simply abort when you make mistakes of mix the models. So, development (at least
+-- in \CONTEXT) can be done in node mode and not in nuts mode. Only robust code will
+-- be turned nuts afterwards and quite likely not all code. The official \LUATEX\ api
+-- to nodes is userdata!
+--
+-- Listening to 'lunatic soul' at the same time helped wrapping my mind around the mixed
+-- usage of both models. Just for the record: the potential of the direct approach only
+-- became clear after experimenting for weeks and partly adapting code. It is one of those
+-- (sub)projects where you afterwards wonder if it was worth the trouble, but users that
+-- rely on lots of complex functionality and font support will probably notice the speedup.
+--
+-- luatex luajittex
+-- ------------- ----- -------------------- ---------------------------------
+-- name pages old new pct old new pct
+-- ------------- ----- -------------------- ---------------------------------
+-- fonts-mkiv 166 9.3 7.7/7.4 17.2 7.4 (37.5) 5.9/5.7 (55.6) 20.3
+-- about 60 3.3 2.7/2.6 20.4 2.5 (39.5) 2.1 (57.0) 23.4
+-- arabic-001 61 25.3 15.8 18.2 15.3 (46.7) 6.8 (54.7) 16.0
+-- torture-001 300 21.4 11.4 24.2 13.9 (35.0) 6.3 (44.7) 22.2
+--
+-- so:
+--
+-- - we run around 20% faster on documents of average complexity and gain more when
+-- dealing with scripts like arabic and such
+-- - luajittex benefits a bit more so a luajittex job can (in principle) now be much
+-- faster
+-- - if we reason backwards, and take luajittex as norm we get 1:2:3 on some jobs for
+-- luajittex direct:luatex direct:luatex normal i.e. we can be 3 times faster
+-- - keep in mind that these are tex/lua runs so the real gain at the lua end is much
+-- larger
+--
+-- Because we can fake direct mode a little bit by using the fast getfield and setfield
+-- at the cost of wrapped getid and alike, we still are running quite ok. As we could gain
+-- some 5% with fast mode, we can sacrifice some on wrappers when we use a few fast core
+-- functions. This means that simulated direct mode runs font-mkiv in 9.1 seconds (we could
+-- get down to 8.7 seconds in fast mode) and that we can migrate slowely to direct mode.
+--
+-- The following measurements are from 2013-07-05 after adapting some 47 files to nuts. Keep
+-- in mind that the old binary can fake a fast getfield and setfield but that the other
+-- getters are wrapped functions. The more we have, the slower it gets.
+--
+-- fonts about arabic
+-- old mingw, indexed plus some functions : 8.9 3.2 20.3
+-- old mingw, fake functions : 9.9 3.5 27.4
+-- new mingw, node functions : 9.0 3.1 20.8
+-- new mingw, indexed plus some functions : 8.6 3.1 19.6
+-- new mingw, direct functions : 7.5 2.6 14.4
+--
+-- \starttext \dorecurse{1000}{test\page} \stoptext :
+--
+-- luatex 560 pps
+-- luajittex 600 pps
+--
+-- \setupbodyfont[pagella]
+--
+-- \edef\zapf{\cldcontext{context(io.loaddata(resolvers.findfile("zapf.tex")))}}
+--
+-- \starttext \dorecurse{1000}{\zapf\par} \stoptext
+--
+-- luatex 3.9 sec / 54 pps
+-- luajittex 2.3 sec / 93 pps
+
+local type, rawget = type, rawget
+
+local nodes = nodes
+local direct = node.direct
+
+local fastcopy = table.fastcopy
+
+local texget = tex.get
+
+local nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local nuts = nodes.nuts or { }
+nodes.nuts = nuts
+
+nodes.is_node = direct.is_node or function() return true end
+nodes.is_direct = direct.is_direct or function() return false end
+nodes.is_nut = nodes.is_direct
+
+-- casters
+
+local tonode = direct.tonode or function(n) return n end
+local tonut = direct.todirect or function(n) return n end
+
+nuts.tonode = tonode
+nuts.tonut = tonut
+
+nodes.tonode = tonode
+nodes.tonut = tonut
+
+-- getters
+
+nuts.getfield = direct.getfield
+nuts.getnext = direct.getnext
+nuts.getprev = direct.getprev
+nuts.getid = direct.getid
+nuts.getattr = direct.get_attribute or direct.has_attribute or direct.getfield
+nuts.getchar = direct.getchar
+nuts.getfont = direct.getfont
+nuts.getsubtype = direct.getsubtype
+nuts.getlist = direct.getlist -- only hlist and vlist !
+nuts.getleader = direct.getleader
+
+-- local function track(name)
+-- local n = 0
+-- local f = nuts[name]
+-- function nuts[name](...)
+-- n = n + 1
+-- if n % 1000 == 0 then
+-- print(name,n)
+-- end
+-- return f(...)
+-- end
+-- end
+
+-- track("getfield")
+
+-- setters
+
+nuts.setfield = direct.setfield
+nuts.setattr = direct.set_attribute or setfield
+
+nuts.getbox = direct.getbox
+nuts.setbox = direct.setbox
+nuts.getskip = direct.getskip or function(s) return tonut(texget(s)) end
+
+-- helpers
+
+nuts.tostring = direct.tostring
+nuts.copy = direct.copy
+nuts.copy_list = direct.copy_list
+nuts.delete = direct.delete
+nuts.dimensions = direct.dimensions
+nuts.end_of_math = direct.end_of_math
+nuts.flush_list = direct.flush_list
+nuts.flush_node = direct.flush_node
+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.current_attr = direct.current_attr
+nuts.do_ligature_n = direct.do_ligature_n
+nuts.has_field = direct.has_field
+nuts.last_node = direct.last_node
+nuts.usedlist = direct.usedlist
+nuts.protrusion_skippable = direct.protrusion_skippable
+nuts.write = direct.write
+
+nuts.has_attribute = direct.has_attribute
+nuts.set_attribute = direct.set_attribute
+nuts.unset_attribute = direct.unset_attribute
+
+nuts.protect_glyphs = direct.protect_glyphs
+nuts.protect_glyph = direct.protect_glyph
+nuts.unprotect_glyphs = direct.unprotect_glyphs
+nuts.ligaturing = direct.ligaturing
+nuts.kerning = direct.kerning
+nuts.effective_glue = direct.effective_glue
+
+if not direct.mlist_to_hlist then -- needed
+
+ local n_mlist_to_hlist = node.mlist_to_hlist
+
+ function nuts.mlist_to_hlist(head)
+ return tonode(n_mlist_to_hlist(tonut(head)))
+ end
+
+end
+
+local is_zero_glue = direct.is_zero_glue
+local setglue = direct.setglue
+local getglue = direct.getglue
+
+if not is_zero_glue then
+ is_zero_glue = function(n)
+ return not n or (
+ getfield(n,"width") == 0 and
+ getfield(n,"stretch") == 0 and
+ getfield(n,"shrink") == 0
+ )
+ end
+ setglue = function(n,width,stretch,shrink,stretch_order,shrink_order)
+ setfield(n,"width", width or 0)
+ setfield(n,"stretch", stretch or 0)
+ setfield(n,"shrink", shrink or 0)
+ setfield(n,"stretch_order",stretch_order or 0)
+ setfield(n,"shrink_order", shrink_order or 0)
+ end
+ getglue = function(n)
+ return
+ getfield(n,"width"), getfield(n,"stretch"), getfield(n,"shrink"),
+ getfield(n,"stretch_order"), getfield(n,"shrink_order")
+ end
+end
+
+nuts.is_zero_glue = is_zero_glue
+nuts.setglue = setglue
+nuts.getglue = getglue
+
+
+-- if not direct.getpre then
+--
+-- local getfield = nuts.getfield
+--
+-- function direct.getpre (n) local h, _, _, t = getdisc(n,true) return h, t end
+-- function direct.getpost (n) local _, h, _, _, t = getdisc(n,true) return h, t end
+-- function direct.getreplace(n) local _, _, h, _, _, t = getdisc(n,true) return h, t end
+--
+-- end
+
+----.getpre = direct.getpre
+----.getpost = direct.getpost
+----.getreplace = direct.getreplace
+
+nuts.getdisc = direct.getdisc
+nuts.setdisc = direct.setdisc
+nuts.setchar = direct.setchar
+nuts.setnext = direct.setnext
+nuts.setprev = direct.setprev
+nuts.setboth = direct.setboth
+nuts.getboth = direct.getboth
+nuts.setlink = direct.setlink
+nuts.setlist = direct.setlist
+nuts.setleader = direct.setleader
+nuts.setsubtype = direct.setsubtype
+
+nuts.is_char = direct.is_char
+nuts.ischar = direct.is_char
+nuts.is_glyph = direct.is_glyph
+nuts.isglyph = direct.is_glyph
+
+local d_remove_node = direct.remove
+local d_free_node = direct.free
+local d_getfield = direct.getfield
+local d_setfield = direct.setfield
+local d_getnext = direct.getnext
+local d_getprev = direct.getprev
+local d_getid = direct.getid
+local d_getlist = direct.getlist
+local d_find_tail = direct.tail
+local d_insert_after = direct.insert_after
+local d_insert_before = direct.insert_before
+local d_slide = direct.slide
+----- d_copy_node = direct.copy
+local d_traverse = direct.traverse
+local d_setlink = direct.setlink
+local d_setboth = direct.setboth
+
+local function remove(head,current,free_too)
+ local t = current
+ head, current = d_remove_node(head,current)
+ if not t then
+ -- forget about it
+ elseif free_too then
+ d_free_node(t)
+ t = nil
+ else
+ d_setboth(t) -- (t,nil,nil)
+ end
+ return head, current, t
+end
+
+-- bad: we can have prev's being glue_spec
+
+nuts.remove = remove
+
+function nuts.delete(head,current)
+ return remove(head,current,true)
+end
+
+function nuts.replace(head,current,new) -- no head returned if false
+ if not new then
+ head, current, new = false, head, current
+ end
+ local prev, next = d_getboth(current)
+ if next then
+ d_setlink(new,next)
+ end
+ if prev then
+ d_setlink(new,prev)
+ end
+ if head then
+ if head == current then
+ head = new
+ end
+ d_free_node(current)
+ return head, new
+ else
+ d_free_node(current)
+ return new
+ end
+end
+
+local function count(stack,flat)
+ local n = 0
+ while stack do
+ local id = d_getid(stack)
+ if not flat and id == hlist_code or id == vlist_code then
+ local list = d_getlist(stack)
+ if list then
+ n = n + 1 + count(list) -- self counts too
+ else
+ n = n + 1
+ end
+ else
+ n = n + 1
+ end
+ stack = d_getnext(stack)
+ end
+ return n
+end
+
+nuts.count = count
+
+function nuts.append(head,current,...)
+ for i=1,select("#",...) do
+ head, current = d_insert_after(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nuts.prepend(head,current,...)
+ for i=1,select("#",...) do
+ head, current = d_insert_before(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nuts.linked(...)
+ local head, last
+ for i=1,select("#",...) do
+ local next = select(i,...)
+ if next then
+ if head then
+ d_setlink(last,next)
+ else
+ head = next
+ end
+ last = d_find_tail(next) -- we could skip the last one
+ end
+ end
+ return head
+end
+
+function nuts.concat(list) -- consider tail instead of slide
+ local head, tail
+ for i=1,#list do
+ local li = list[i]
+ if li then
+ if head then
+ d_setlink(tail,li)
+ else
+ head = li
+ end
+ tail = d_slide(li)
+ end
+ end
+ return head, tail
+end
+
+function nuts.reference(n)
+ return n or "<none>"
+end
+
+-- quick and dirty tracing of nuts
+
+-- for k, v in next, nuts do
+-- if string.find(k,"box") then
+-- nuts[k] = function(...) print(k,...) return v(...) end
+-- end
+-- end
+
+function nodes.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end
+function nodes.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end
+
+nuts.vianuts = nodes.vianuts
+nuts.vianodes = nodes.vianodes
+
+-- function nodes.insert_before(h,c,n)
+-- if c then
+-- if c == h then
+-- n_setfield(n,"next",h)
+-- n_setfield(n,"prev",nil)
+-- n_setfield(h,"prev",n)
+-- else
+-- local cp = n_getprev(c)
+-- n_setfield(n,"next",c)
+-- n_setfield(n,"prev",cp)
+-- if cp then
+-- n_setfield(cp,"next",n)
+-- end
+-- n_setfield(c,"prev",n)
+-- return h, n
+-- end
+-- end
+-- return n, n
+-- end
+
+-- function nodes.insert_after(h,c,n)
+-- if c then
+-- local cn = n_getnext(c)
+-- if cn then
+-- n_setfield(n,"next",cn)
+-- n_setfield(cn,"prev",n)
+-- else
+-- n_setfield(n,"next",nil)
+-- end
+-- n_setfield(c,"next",n)
+-- n_setfield(n,"prev",c)
+-- return h, n
+-- end
+-- return n, n
+-- end
+
+function nodes.insert_list_after(h,c,n)
+ local t = n_tail(n)
+ if c then
+ local cn = n_getnext(c)
+ if cn then
+ -- no setboth here yet
+ n_setfield(t,"next",cn)
+ n_setfield(cn,"prev",t)
+ else
+ n_setfield(t,"next",nil)
+ end
+ n_setfield(c,"next",n)
+ n_setfield(n,"prev",c)
+ return h, n
+ end
+ return n, t
+end
+
+-- function nuts.insert_before(h,c,n)
+-- if c then
+-- if c == h then
+-- d_setnext(n,h)
+-- d_setprev(n)
+-- d_setprev(h,n)
+-- else
+-- local cp = d_getprev(c)
+-- d_setnext(n,c)
+-- d_setprev(n,cp)
+-- if cp then
+-- d_setnext(cp,n)
+-- end
+-- d_setprev(c,n)
+-- return h, n
+-- end
+-- end
+-- return n, n
+-- end
+
+-- function nuts.insert_after(h,c,n)
+-- if c then
+-- local cn = d_getnext(c)
+-- if cn then
+-- d_setlink(n,cn)
+-- else
+-- d_setnext(n,nil)
+-- end
+-- d_setlink(c,n)
+-- return h, n
+-- end
+-- return n, n
+-- end
+
+function nuts.insert_list_after(h,c,n)
+ local t = d_tail(n)
+ if c then
+ local cn = d_getnext(c)
+ if cn then
+ d_setlink(t,cn)
+ else
+ d_setnext(t)
+ end
+ d_setlink(c,n)
+ return h, n
+ end
+ return n, t
+end
+
+-- test code only
+
+-- collectranges and mix
+
+local report = logs.reporter("sliding")
+
+local function message(detail,head,current,previous)
+ report("error: %s, current: %s:%s, previous: %s:%s, list: %s, text: %s",
+ detail,
+ nodecodes[d_getid(current)],
+ current,
+ nodecodes[d_getid(previous)],
+ previous,
+ nodes.idstostring(head),
+ nodes.listtoutf(head)
+ )
+ utilities.debugger.showtraceback(report)
+end
+
+local function warn()
+ report()
+ report("warning: the slide tracer is enabled")
+ report()
+ warn = false
+end
+
+local function tracedslide(head)
+ if head then
+ if warn then
+ warn()
+ end
+ local next = d_getnext(head)
+ if next then
+ local prev = head
+ for n in d_traverse(next) do
+ local p = d_getprev(n)
+ if not p then
+ message("unset",head,n,prev)
+ -- break
+ elseif p ~= prev then
+ message("wrong",head,n,prev)
+ -- break
+ end
+ prev = n
+ end
+ end
+ return d_slide(head)
+ end
+end
+
+local function nestedtracedslide(head,level) -- no sliding !
+ if head then
+ if warn then
+ warn()
+ end
+ local id = d_getid(head)
+ local next = d_getnext(head)
+ if next then
+ report("%whead:%s",level or 0,nodecodes[id])
+ local prev = head
+ for n in d_traverse(next) do
+ local p = d_getprev(n)
+ if not p then
+ message("unset",head,n,prev)
+ -- break
+ elseif p ~= prev then
+ message("wrong",head,n,prev)
+ -- break
+ end
+ prev = n
+ local id = d_getid(n)
+ if id == hlist_code or id == vlist_code then
+ nestedtracedslide(d_getlist(n),(level or 0) + 1)
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ report("%wlist:%s",level or 0,nodecodes[id])
+ nestedtracedslide(d_getlist(head),(level or 0) + 1)
+ end
+ -- return d_slide(head)
+ end
+end
+
+local function untracedslide(head)
+ if head then
+ if warn then
+ warn()
+ end
+ local next = d_getnext(head)
+ if next then
+ local prev = head
+ for n in d_traverse(next) do
+ local p = d_getprev(n)
+ if not p then
+ return "unset", d_getid(n)
+ elseif p ~= prev then
+ return "wrong", d_getid(n)
+ end
+ prev = n
+ end
+ end
+ return d_slide(head)
+ end
+end
+
+nuts.tracedslide = tracedslide
+nuts.untracedslide = untracedslide
+nuts.nestedtracedslide = nestedtracedslide
+
+-- nuts.slide = tracedslide
+
+-- this might move
+
+local propertydata = direct.get_properties_table and direct.get_properties_table()
+
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+
+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-inj.lua (unless we use an intermediate table)
+
+-- todo:
+--
+-- function direct.set_properties_mode()
+-- -- we really need the set modes
+-- end
+
+-- experimental code with respect to copying attributes has been removed
+-- as it doesn't pay of (most attributes are only accessed once anyway)
+
+nuts.getprop = function(n,k)
+ local p = propertydata[n]
+ if p then
+ return p[k]
+ end
+end
+
+nuts.rawprop = function(n,k)
+ local p = rawget(propertydata,n)
+ if p then
+ return p[k]
+ end
+end
+
+nuts.setprop = function(n,k,v)
+ local p = propertydata[n]
+ if p then
+ p[k] = v
+ else
+ propertydata[n] = { [k] = v }
+ end
+end
+
+nuts.theprop = function(n)
+ local p = propertydata[n]
+ if not p then
+ p = { }
+ propertydata[n] = p
+ end
+ return p
+end
+
+nodes.setprop = nodes.setproperty
+nodes.getprop = nodes.getproperty
+
+function nuts.copy_properties(source,target,what)
+ local newprops = propertydata[source]
+ if not newprops then
+ -- nothing to copy
+ return
+ end
+ if what then
+ -- copy one category
+ newprops = rawget(source,what)
+ if newprops then
+ newprops = fastcopy(newprops)
+ local p = rawget(propertydata,target)
+ if p then
+ p[what] = newprops
+ else
+ propertydata[target] = {
+ [what] = newprops,
+ }
+ end
+ end
+ else
+ -- copy all properties
+ newprops = fastcopy(newprops)
+ propertydata[target] = newprops
+ end
+ return newprops -- for checking
+end
+
+-- a bit special
+
+local getwidth = { }
+local setwidth = { }
+local getdimensions = { }
+local setdimensions = { }
+
+nodes.whatsitters = {
+ getters = { width = getwidth, dimensions = getdimensions },
+ setters = { width = setwidth, dimensions = setdimensions },
+}
+
+-- obsolete
+
+-- local function get_width(n,dir)
+-- n = tonut(n)
+-- return getfield(n,"width")
+-- end
+--
+-- local function get_dimensions(n,dir)
+-- n = tonut(n)
+-- return getfield(n,"width"), getfield(n,"height"), getfield(n,"depth")
+-- end
+--
+-- local whatcodes = nodes.whatcodes
+-- local pdfrefximage_code = whatcodes.pdfrefximage
+-- local pdfrefxform_code = whatcodes.pdfrefxform
+--
+-- if pdfrefxform_code then
+-- getwidth [pdfrefxform_code ] = get_width
+-- getdimensions[pdfrefxform_code ] = get_dimensions
+-- end
+--
+-- if pdfrefximage_code then
+-- getwidth [pdfrefximage_code] = get_width
+-- getdimensions[pdfrefximage_code] = get_dimensions
+-- end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/node-pag.lua
new file mode 100644
index 00000000000..9b8202042c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-pag.lua
@@ -0,0 +1,30 @@
+if not modules then modules = { } end modules ['node-pag'] = {
+ version = 1.001,
+ comment = "companion to node-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this callback might disappear and come back in the same way
+-- as par builders
+
+pagebuilders = pagebuilders or { }
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+local actions = nodes.tasks.actions("pagebuilders")
+
+local function processor(head,groupcode,size,packtype,maxdepth,direction)
+ starttiming(pagebuilders)
+ local _, done = actions(head,groupcode,size,packtype,maxdepth,direction)
+ stoptiming(pagebuilders)
+ return (done and head) or true
+-- return vpack(head)
+end
+
+--~ callbacks.register('pre_output_filter', processor, "preparing output box")
+
+--~ statistics.register("output preparation time", function()
+--~ return statistics.elapsedseconds(pagebuilders)
+--~ end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-pag.mkiv
new file mode 100644
index 00000000000..b8ed197fe64
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-pag.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=node-pag,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Page Building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Macros / Page Building}
+
+\unprotect
+
+\registerctxluafile{node-pag}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua
new file mode 100644
index 00000000000..2573e5f5cea
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua
@@ -0,0 +1,474 @@
+if not modules then modules = { } end modules ['node-ppt'] = {
+ 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"
+}
+
+-- This is all very exeperimental and likely to change.
+
+local next, type, unpack, load = next, type, table.unpack, load
+
+local serialize = table.serialize
+local formatters = string.formatters
+
+local report = logs.reporter("properties")
+local report_setting = logs.reporter("properties","setting")
+local trace_setting = false trackers.register("properties.setting", function(v) trace_setting = v end)
+
+-- report("using experimental properties")
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getsubtype = nuts.getsubtype
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local flushnode = nuts.flush
+local removenode = nuts.remove
+local traverse = nuts.traverse
+local traverse_id = nuts.traverse_id
+
+local nodecodes = nodes.nodecodes
+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 nodepool = nodes.pool
+local new_usernumber = nodepool.usernumber
+
+local nutpool = nuts.pool
+local nut_usernumber = nutpool.usernumber
+
+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
+local propertydata = properties.data
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+if not propertydata then
+ return
+end
+
+-- management
+
+local function register(where,data,...)
+ if not data then
+ data = where
+ 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)
+ end
+end
+
+local writenode = node.write
+local flushnode = context.flushnode
+
+function commands.deferredproperty(...)
+-- context(register(...))
+ flushnode(register(...))
+end
+
+
+function commands.immediateproperty(...)
+ writenode(register(...))
+end
+
+commands.attachproperty = commands.deferredproperty
+
+local actions = { } properties.actions = actions
+
+table.setmetatableindex(actions,function(t,k)
+ report("unknown property action %a",k)
+ local v = function() end
+ return v
+end)
+
+local f_delayed = formatters["return function(target,head,where,propdata,parent) %s end"]
+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
+
+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
+ delayed[#delayed+1] = { where, code, ... }
+ else
+ propdata.delayed = { { where, code, ... } }
+ nofdelayed = nofdelayed + 1
+ end
+ end
+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
+ delayed[#delayed+1] = { false, code, ... }
+ else
+ propdata.delayed = { { false, code, ... } }
+ nofdelayed = nofdelayed + 1
+ end
+ end
+end
+
+function actions.immediate(target,head,where,propdata,code,...) -- this one is used at the tex end
+ local kind = type(code)
+ if kind == "string" then
+ local f = f_immediate(code)
+ local okay, err = load(f)
+ if okay then
+ local h = okay()(target,head,where,propdata,...)
+ if h and h ~= head then
+ return h
+ end
+ end
+ elseif kind == "function" then
+ local h = code()(target,head,where,propdata,...)
+ if h and h ~= head then
+ return h
+ end
+ 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
+
+-- 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
+ 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))
+ end
+ end
+ p.delayed = nil
+ if nofdelayed == 1 then
+ nofdelayed = 0
+ return head
+ else
+ nofdelayed = nofdelayed - 1
+ end
+ end
+ -- end
+ end
+ local id = getid(target)
+ if id == hlist_code or id == vlist_code then
+ local list = getlist(target)
+ if list then
+ local done = delayed(list,parent)
+ if done then
+ setlist(target,done)
+ end
+ if nofdelayed == 0 then
+ return head
+ end
+ end
+ else
+ -- maybe also some more lists? but we will only use this for some
+ -- special cases .. who knows
+ end
+ end
+ return head
+end
+
+function properties.delayed(head) --
+ if nofdelayed > 0 then
+ -- if next(propertydata) then
+ starttiming(properties)
+ head = delayed(tonut(head))
+ stoptiming(properties)
+ return tonode(head), true -- done in shipout anyway
+ -- else
+ -- delayed = 0
+ -- end
+ end
+ return head, false
+end
+
+-- more explicit ones too
+
+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
+ -- continue
+ else
+ return n
+ end
+ end
+ end,
+ [v_after] = function(n)
+ while n do
+ 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
+ -- continue
+ else
+ return n
+ end
+ else
+ return n
+ end
+ end
+ end,
+ [v_here] = function(n)
+ -- todo
+ end,
+}
+
+table.setmetatableindex(anchored,function(t,k)
+ v = anchored[v_after]
+ t[k] = v
+ return v
+end)
+
+function properties.attach(head)
+
+ if nofslots <= 0 then
+ return head, false
+ 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
+ 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 data then
+ cache[slot] = nil
+ local where = data[1]
+ local target = anchored[where](source)
+ if target then
+ local first = data[2]
+ local method = type(first)
+ local p_target = propertydata[target]
+ local p_source = propertydata[source]
+ if p_target then
+ if p_source then
+ for k, v in next, p_source do
+ p_target[k] = v
+ end
+ end
+ if method == "table" then
+ for k, v in next, first do
+ p_target[k] = v
+ end
+ elseif method == "function" then
+ first(target,head,where,p_target,unpack(data,3))
+ elseif method == "string" then
+ actions[first](target,head,where,p_target,unpack(data,3))
+ end
+ elseif p_source then
+ if method == "table" then
+ propertydata[target] = p_source
+ for k, v in next, first do
+ p_source[k] = v
+ end
+ elseif method == "function" then
+ propertydata[target] = p_source
+ first(target,head,where,p_source,unpack(data,3))
+ elseif method == "string" then
+ propertydata[target] = p_source
+ actions[first](target,head,where,p_source,unpack(data,3))
+ end
+ else
+ if method == "table" then
+ propertydata[target] = first
+ elseif method == "function" then
+ local t = { }
+ propertydata[target] = t
+ first(target,head,where,t,unpack(data,3))
+ elseif method == "string" then
+ local t = { }
+ propertydata[target] = t
+ actions[first](target,head,where,t,unpack(data,3))
+ end
+ end
+ if trace_setting then
+ report_setting("node %i, id %s, data %s",
+ target,nodecodes[getid(target)],serialize(propertydata[target],false))
+ end
+ end
+ if nofslots == 1 then
+ nofslots = 0
+ last = source
+ break
+ else
+ nofslots = nofslots - 1
+ end
+ end
+ last = source
+ end
+ end
+ end
+
+ if last then
+ removenode(head,last,true)
+ end
+
+ stoptiming(properties)
+
+ return head, done
+
+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 function show(head,level,report)
+-- for target in traverse(head) do
+-- local p = propertydata[target]
+-- if p then
+-- report("level %i, node %i, id %s, data %s",
+-- level,target,nodecodes[getid(target)],serialize(propertydata[target],false))
+-- end
+-- local id = getid(target)
+-- if id == hlist_code or id == vlist_code then
+-- local list = getlist(target)
+-- if list then
+-- show(list,level+1,report)
+-- end
+-- else
+-- -- maybe more lists
+-- end
+-- end
+-- return head, false
+-- end
+--
+-- local report_shipout = logs.reporter("properties","shipout")
+-- local report_processors = logs.reporter("properties","processors")
+--
+-- function properties.showshipout (head) return tonode(show(tonut(head),1,report_shipout )), true end
+-- function properties.showprocessors(head) return tonode(show(tonut(head),1,report_processors)), true end
+--
+-- tasks.prependaction("shipouts","before","nodes.properties.showshipout")
+-- tasks.disableaction("shipouts","nodes.properties.showshipout")
+--
+-- trackers.register("properties.shipout",function(v)
+-- tasks.setaction("shipouts","nodes.properties.showshipout",v)
+-- end)
+--
+-- tasks.appendaction ("processors","after","nodes.properties.showprocessors")
+-- tasks.disableaction("processors","nodes.properties.showprocessors")
+--
+-- trackers.register("properties.processors",function(v)
+-- tasks.setaction("processors","nodes.properties.showprocessors",v)
+-- end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua b/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua
new file mode 100644
index 00000000000..36670eed2f9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['node-pro'] = {
+ 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 utfchar = utf.char
+local format, concat = string.format, table.concat
+
+local trace_callbacks = false trackers .register("nodes.callbacks", function(v) trace_callbacks = v end)
+local force_processors = false directives.register("nodes.processors.force", function(v) force_processors = v end)
+
+local report_nodes = logs.reporter("nodes","processors")
+
+local nodes = nodes
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local tasks = nodes.tasks
+local nuts = nodes.nuts
+
+local first_glyph = nodes.first_glyph
+local has_glyph = nodes.has_glyph
+
+nodes.processors = nodes.processors or { }
+local processors = nodes.processors
+
+-- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional
+-- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional
+
+local actions = tasks.actions("processors")
+
+do
+
+ local tonut = nuts.tonut
+ local isglyph = nuts.isglyph
+ local getnext = nuts.getnext
+
+ local n = 0
+
+ local function reconstruct(head) -- we probably have a better one
+ local t, n, h = { }, 0, tonut(head)
+ while h do
+ n = n + 1
+ local char, id = isglyph(h)
+ if char then -- todo: disc etc
+ t[n] = utfchar(char)
+ else
+ t[n] = "[]"
+ end
+ h = getnext(h)
+ end
+ return concat(t)
+ end
+
+ function processors.tracer(what,state,head,groupcode,before,after,show)
+ if not groupcode then
+ groupcode = "unknown"
+ elseif groupcode == "" then
+ groupcode = "mvl"
+ 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))
+ else
+ report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after)
+ end
+ end
+
+end
+
+local tracer = processors.tracer
+
+processors.enabled = true -- this will become a proper state (like trackers)
+
+function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction
+ -- local first, found = first_glyph(head) -- they really need to be glyphs
+ local found = force_processors or has_glyph(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
+ local after = nodes.count(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
+ else
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
+ return done and head or true
+ end
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("pre_linebreak","no chars",head,groupcode,n,n)
+ end
+ return true
+end
+
+local function hpack_filter(head,groupcode,size,packtype,direction,attributes)
+ -- local first, found = first_glyph(head) -- they really need to be glyphs
+ local found = force_processors or has_glyph(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode,size,packtype,direction,attributes)
+ local after = nodes.count(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
+ else
+ local head, done = actions(head,groupcode,size,packtype,direction,attributes)
+ return done and head or true
+ end
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("hpack","no chars",head,groupcode,n,n)
+ end
+ return true
+end
+
+processors.hpack_filter = hpack_filter
+
+do
+
+ local setfield = nodes.setfield
+ 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
+ end
+
+end
+
+do
+
+ local setboth = nuts.setboth
+ 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
+ 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)")
+
+local actions = tasks.actions("finalizers") -- head, where
+
+-- 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
+
+function processors.post_linebreak_filter(head,groupcode)
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode)
+ local after = nodes.count(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
+ else
+ local head, done = actions(head,groupcode)
+ return done and head or true
+ end
+end
+
+callbacks.register('post_linebreak_filter', processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)")
+
+statistics.register("h-node processing time", function()
+ return statistics.elapsedseconds(nodes,"including kernel") -- hm, ok here?
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua
new file mode 100644
index 00000000000..9f2d0918c0f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua
@@ -0,0 +1,941 @@
+if not modules then modules = { } end modules ['node-ref'] = {
+ version = 1.001,
+ comment = "companion to node-ref.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We supported pdf right from the start and in mkii this has resulted in
+-- extensive control over the links. Nowadays pdftex provides a lot more
+-- control over margins but as mkii supports multiple backends we stuck to
+-- our own mechanisms. In mkiv again we implement our own handling. Eventually
+-- we will even disable the pdf primitives.
+
+-- helper, will end up in luatex
+
+-- is grouplevel still used?
+
+local concat = table.concat
+
+local attributes, nodes, node = attributes, nodes, node
+
+local allocate = utilities.storage.allocate, utilities.storage.mark
+local mark = utilities.storage.allocate, utilities.storage.mark
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+
+local cleanupreferences = false
+local cleanupdestinations = true
+
+local transparencies = attributes.transparencies
+local colors = attributes.colors
+local references = structures.references
+local tasks = nodes.tasks
+
+local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
+local trace_areas = false trackers.register("nodes.areas", function(v) trace_areas = v end)
+local show_references = false trackers.register("nodes.references.show", function(v) show_references = tonumber(v) or (v and 2.25 or false) end)
+local show_destinations = false trackers.register("nodes.destinations.show", function(v) show_destinations = tonumber(v) or (v and 2.00 or false) end)
+
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_area = logs.reporter("backend","areas")
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+
+local hpack_list = nuts.hpack
+local vpack_list = nuts.vpack
+local list_dimensions = nuts.dimensions
+local traverse = nuts.traverse
+local find_node_tail = nuts.tail
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local listcodes = nodes.listcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+local rule_code = nodecodes.rule
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+
+local leftskip_code = skipcodes.leftskip
+local rightskip_code = skipcodes.rightskip
+local parfillskip_code = skipcodes.parfillskip
+
+local line_code = listcodes.line
+
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+
+local free_node = nuts.free
+
+local tosequence = nodes.tosequence
+
+local implement = interfaces.implement
+
+-- Normally a (destination) area is a box or a simple stretch if nodes but when it is
+-- a paragraph we have a problem: we cannot calculate the height well. This happens
+-- with footnotes or content broken across a page.
+
+local function hlist_dimensions(start,stop,parent)
+ local last = stop and getnext(stop)
+ if parent then
+ return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),start,last)
+ else
+ return list_dimensions(start,last)
+ end
+end
+
+local function vlist_dimensions(start,stop) -- also needs the stretch and so
+ local temp
+ if stop then
+ temp = getnext(stop)
+ setnext(stop,nil)
+ end
+ local v = vpack_list(start)
+ local w = getfield(v,"width")
+ local h = getfield(v,"height")
+ local d = getfield(v,"depth")
+ setlist(v) -- not needed
+ free_node(v)
+ if temp then
+ setnext(stop,temp)
+ end
+ return w, h, d
+end
+
+local function dimensions(parent,start,stop) -- in principle we could move some to the caller
+ local id = getid(start)
+ if start == stop then
+ if id == hlist_code or id == vlist_code or id == glyph_code or id == rule_code then
+ if trace_areas then
+ report_area("dimensions taken of %a",nodecodes[id])
+ end
+ -- hm, parent can be zero
+ local width = getfield(start,"width")
+ local height = getfield(parent,"height")
+ local depth = getfield(parent,"depth")
+ if height == 0 and depth == 0 then
+ height = getfield(start,"height")
+ depth = getfield(start,"depth")
+ end
+ return width, height, depth
+ else
+ if trace_areas then
+ report_area("dimensions calculated of %a",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop) -- one node only so simple
+ end
+ end
+ local last = stop and getnext(stop)
+ if parent then
+ -- todo: if no prev and no next and parent
+ -- todo: we need a a list_dimensions for a vlist
+ if getid(parent) == vlist_code then
+ if false then
+ local l = getlist(parent)
+ local c = l
+ local ok = false
+ while c do
+ if c == start then
+ ok = true
+ end
+ if ok and getid(c) == hlist_code then
+ break
+ else
+ c = getnext(c)
+ end
+ end
+ if ok and c then
+ if trace_areas then
+ report_area("dimensions taken of first line in vlist")
+ end
+ return getfield(c,"width"), getfield(c,"height"), getfield(c,"depth"), c
+ else
+ if trace_areas then
+ report_area("dimensions taken of vlist (probably wrong)")
+ end
+ return hlist_dimensions(start,stop,parent)
+ end
+ else
+ --
+ -- we can as well calculate here because we only have kerns and glue
+ --
+ local first = nil
+ local last = nil
+ local current = start
+ local noflines = 0
+ while current do
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code or id == rule_code then
+ if noflines == 0 then
+ first = current
+ noflines = 1
+ else
+ noflines = noflines + 1
+ end
+ last = current
+ end
+ if current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ if noflines > 1 then
+ if trace_areas then
+ report_area("dimensions taken of vlist")
+ end
+ local w, h, d = vlist_dimensions(first,last,parent)
+ local ht = getfield(first,"height")
+ return w, ht, d + h - ht, first
+ else
+ -- return hlist_dimensions(start,stop,parent)
+ if first then
+ if trace_areas then
+ report_area("dimensions taken of first line in vlist")
+ end
+ return getfield(first,"width"), getfield(first,"height"), getfield(first,"depth"), first
+ else
+ if trace_areas then
+ report_area("dimensions taken of vlist (probably wrong)")
+ end
+ return hlist_dimensions(start,stop,parent)
+ end
+ end
+ end
+ else
+ if trace_areas then
+ report_area("dimensions taken of range starting with %a using parent",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop,parent)
+ end
+ else
+ if trace_areas then
+ report_area("dimensions taken of range starting with %a",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop)
+ end
+end
+
+-- 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
+ width = - width
+ end
+ local result, resolved = make(width,height,depth,reference)
+ if result and resolved then
+ if line then
+ -- special case, we only treat the first line in a vlist
+ local l = getlist(line)
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p, c=%S","line",
+ reference,pardir or "---",txtdir or "---",
+ tosequence(l,nil,true),width,height,depth,resolved)
+ end
+ setlist(line,result)
+ setlink(result,l)
+ return head, last
+ else
+ if head == first then
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p, c=%S","head",
+ reference,pardir or "---",txtdir or "---",
+ tosequence(first,last,true),width,height,depth,resolved)
+ end
+ setlink(result,first)
+ return result, last
+ else
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p, c=%S","middle",
+ reference,pardir or "---",txtdir or "---",
+ tosequence(first,last,true),width,height,depth,resolved)
+ end
+ local prev = getprev(first)
+ if prev then
+ setlink(prev,result)
+ end
+ setlink(result,first)
+ return head, last
+ end
+ end
+ else
+ return head, last
+ end
+end
+
+local function inject_list(id,current,reference,make,stack,pardir,txtdir)
+ local width = getfield(current,"width")
+ local height = getfield(current,"height")
+ local depth = getfield(current,"depth")
+ local correction = 0
+ local moveright = false
+ local first = getlist(current)
+ if id == hlist_code then -- box_code line_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]
+ if first then
+ if sr and sr[2] then
+ local last = find_node_tail(first)
+ if getid(last) == glue_code and getsubtype(last) == rightskip_code then
+ local prev = getprev(last)
+ moveright = getid(first) == glue_code and getsubtype(first) == leftskip_code
+ if prev and getid(prev) == glue_code and getsubtype(prev) == parfillskip_code then
+ width = dimensions(current,first,getprev(prev)) -- maybe not current as we already take care of it
+ else
+ if moveright then
+ width = width - getfield(first,"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
+ end
+ width = width - getfield(last,"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
+ end
+ end
+ else
+ -- also weird
+ end
+ else
+ -- ok
+ end
+ correction = width
+ else
+ correction = height + depth
+ height, depth = depth, height -- ugly hack, needed because pdftex backend does something funny
+ end
+ if pardir == "TRT" then
+ width = - width
+ end
+ local result, resolved = make(width,height,depth,reference)
+ -- todo: only when width is ok
+ 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)
+ end
+ if not first then
+ setlist(current,result)
+ elseif moveright then -- brr no prevs done
+ -- result after first
+ local n = getnext(first)
+ setnext(result,n)
+ setlink(first,first)
+ if n then
+ setprev(n,result)
+ end
+ else
+ -- first after result
+ setlink(result,first)
+ setlist(current,result)
+ end
+ end
+end
+
+-- skip is somewhat messy
+
+-- todo: when line we can look at the next line
+
+-- see dimensions: this is tricky with split off boxes like inserts
+-- where we can end up with a first and last spanning lines so maybe
+-- we need to do vlists differently
+
+local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
+ if head then
+ local current, first, last, firstdir, reference = head, nil, nil, nil, nil
+ pardir = pardir or "==="
+ txtdir = txtdir or "==="
+ 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, ok
+ h, ok , 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
+ txtdir = getfield(current,"dir")
+ elseif id == localpar_code then
+ pardir = getfield(current,"dir")
+ 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
+ end
+ return head, true, pardir, txtdir
+end
+
+local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular !
+ if head then
+ pardir = pardir or "==="
+ txtdir = txtdir or "==="
+ 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)
+ end
+ local list = getlist(current)
+ if list then
+ local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir)
+ if h ~= current then
+ setlist(current,h)
+ end
+ end
+ elseif id == dir_code then
+ txtdir = getfield(current,"dir")
+ elseif id == localpar_code then
+ pardir = getfield(current,"dir")
+ 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)
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ return head, true
+end
+
+-- tracing: todo: use predefined colors
+
+local register_color = colors.register
+
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local a_transparency = attributes.private('transparency')
+local u_transparency = nil
+local u_colors = { }
+local force_gray = true
+
+local function addstring(what,str,shift) --todo make a pluggable helper (in font-ctx)
+ if str then
+ local typesetters = nuts.typesetters
+ if typesetters then
+ local hashes = fonts.hashes
+ local infofont = fonts.infofont()
+ local emwidth = hashes.emwidths [infofont]
+ local exheight = hashes.exheights[infofont]
+ if what == "reference" then
+ str = str .. " "
+ shift = - (shift or 2.25) * exheight
+ else
+ str = str .. " "
+ shift = (shift or 2) * exheight
+ end
+ local text = typesetters.tohpack(str,infofont)
+ local rule = new_rule(emwidth/5,4*exheight,3*exheight)
+ setfield(text,"shift",shift)
+ return hpack_list(nuts.linked(text,rule))
+ end
+ end
+end
+
+local function colorize(width,height,depth,n,reference,what,sr,offset)
+ if force_gray then n = 0 end
+ u_transparency = u_transparency or transparencies.register(nil,2,.65)
+ local ucolor = u_colors[n]
+ if not ucolor then
+ if n == 1 then
+ u_color = register_color(nil,'rgb',.75,0,0)
+ elseif n == 2 then
+ u_color = register_color(nil,'rgb',0,.75,0)
+ elseif n == 3 then
+ u_color = register_color(nil,'rgb',0,0,.75)
+ else
+ n = 0
+ u_color = register_color(nil,'gray',.5)
+ end
+ u_colors[n] = u_color
+ end
+ if width == 0 then
+ -- probably a strut as placeholder
+ report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"horizontal",width,height,depth)
+ width = 65536
+ end
+ if height + depth <= 0 then
+ report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"vertical",width,height,depth)
+ height = 65536/2
+ depth = height
+ end
+ local rule = new_rule(width,height,depth) -- todo: use tracer rule
+ setattr(rule,a_colormodel,1) -- gray color model
+ setattr(rule,a_color,u_color)
+ setattr(rule,a_transparency,u_transparency)
+ if width < 0 then
+ local kern = new_kern(width)
+ setfield(rule,"width",-width)
+ setnext(kern,rule)
+ setprev(rule,kern)
+ return kern
+ else
+
+if sr and sr ~= "" then
+ local text = addstring(what,sr,shift)
+ if text then
+ local kern = new_kern(-getfield(text,"width"))
+ setlink(kern,text)
+ setlink(text,rule)
+ return kern
+ end
+end
+
+ return rule
+ end
+end
+
+local function justadd(what,sr,shift)
+ if sr and sr ~= "" then
+ local text = addstring(what,sr,shift)
+ if text then
+ local kern = new_kern(-getfield(text,"width"))
+ setlink(kern,text)
+ setlink(text,rule)
+ return kern
+ end
+ end
+end
+
+-- references:
+
+local texsetattribute = tex.setattribute
+local texsetcount = tex.setcount
+
+local stack = { }
+local done = { }
+local attribute = attributes.private('reference')
+local nofreferences = 0
+local topofstack = 0
+
+nodes.references = {
+ attribute = attribute,
+ stack = stack,
+ done = done,
+}
+
+-- todo: get rid of n (n is just a number, can be used for tracing, obsolete)
+
+local function setreference(h,d,r)
+ 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) }
+ -- texsetattribute(attribute,topofstack) -- todo -> at tex end
+ texsetcount("lastreferenceattribute",topofstack)
+end
+
+function references.get(n) -- not public so functionality can change
+ local sn = stack[n]
+ return sn and sn[1]
+end
+
+local function makereference(width,height,depth,reference) -- height and depth are of parent
+ local sr = stack[reference]
+ if sr then
+ if trace_references then
+ report_reference("resolving attribute %a",reference)
+ end
+ local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5]
+ -- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth)
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ -- logs.report("temp","used: ht=%p dp=%p",height,depth)
+ local annot = nodeinjections.reference(width,height,depth,set)
+ if annot then
+ annot = tonut(annot) -- todo
+ nofreferences = nofreferences + 1
+ local result, current, texts
+ if show_references then
+ local d = sr[1]
+ if d then
+ local r = d.reference
+ local p = d.prefix
+ if r then
+ if p then
+ texts = p .. "|" .. r
+ else
+ texts = r
+ end
+ else
+ -- t[#t+1] = d.internal or "?"
+ end
+ end
+ end
+ if trace_references then
+ local step = 65536
+ result = hpack_list(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links
+ setfield(result,"width",0)
+ current = result
+ elseif texts then
+ texts = justadd("reference",texts,show_references)
+ if texts then
+ result = hpack_list(texts)
+ setfield(result,"width",0)
+ current = result
+ end
+ end
+ if current then
+ setlink(current,annot)
+ else
+ result = annot
+ end
+ references.registerpage(n)
+ result = hpack_list(result,0)
+ setfield(result,"width",0)
+ setfield(result,"height",0)
+ setfield(result,"depth",0)
+ if cleanupreferences then stack[reference] = nil end
+ return result, resolved
+ elseif trace_references then
+ report_reference("unable to resolve annotation %a",reference)
+ end
+ elseif trace_references then
+ report_reference("unable to resolve attribute %a",reference)
+ end
+end
+
+-- function nodes.references.handler(head)
+-- if topofstack > 0 then
+-- return inject_areas(head,attribute,makereference,stack,done)
+-- else
+-- return head, false
+-- end
+-- end
+
+function nodes.references.handler(head)
+ if topofstack > 0 then
+ head = tonut(head)
+ local head, done = inject_areas(head,attribute,makereference,stack,done)
+ return tonode(head), done
+ else
+ return head, false
+ end
+end
+
+-- destinations (we can clean up once set, unless tagging!)
+
+local stack = { }
+local done = { }
+local attribute = attributes.private('destination')
+local nofdestinations = 0
+local topofstack = 0
+
+nodes.destinations = {
+ attribute = attribute,
+ stack = stack,
+ done = done,
+}
+
+local function setdestination(n,h,d,name,view) -- n = grouplevel, name == table
+ topofstack = topofstack + 1
+ stack[topofstack] = { n, h, d, name, view }
+ return topofstack
+end
+
+local function makedestination(width,height,depth,reference)
+ local sr = stack[reference]
+ if sr then
+ if trace_destinations then
+ report_destination("resolving attribute %a",reference)
+ end
+ local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ local result, current, texts
+ if show_destinations then
+ if name and #name > 0 then
+ local t = { }
+ for i=1,#name do
+ local s = name[i]
+ if type(s) == "number" then
+ local d = references.internals[s]
+ if d then
+ d = d.references
+ local r = d.reference
+ local p = d.usedprefix
+ if r then
+ if p then
+ t[#t+1] = p .. "|" .. r
+ else
+ t[#t+1] = r
+ end
+ else
+ -- t[#t+1] = d.internal or "?"
+ end
+ end
+ else
+ -- in fact we have a prefix:name here
+ end
+ end
+ if #t > 0 then
+ texts = concat(t," & ")
+ end
+ end
+ end
+ if trace_destinations then
+ local step = 0
+ if width == 0 then
+ step = 4*65536
+ width, height, depth = 5*step, 5*step, 0
+ end
+ local rule = hpack_list(colorize(width,height,depth,3,reference,"destination",texts,show_destinations))
+ setfield(rule,"width",0)
+ if not result then
+ result, current = rule, rule
+ else
+ setlink(current,rule)
+ current = rule
+ end
+ width, height = width - step, height - step
+ elseif texts then
+ texts = justadd("destination",texts,show_destinations)
+ if texts then
+ result = hpack_list(texts)
+ if result then
+ setfield(result,"width",0)
+ current = result
+ end
+ end
+ end
+ nofdestinations = nofdestinations + 1
+ local annot = nodeinjections.destination(width,height,depth,name,view)
+ if annot then
+ annot = tonut(annot) -- obsolete soon
+ if result then
+ setlink(current,annot)
+ else
+ result = annot
+ end
+ current = find_node_tail(annot)
+ end
+ if result then
+ -- some internal error
+ result = hpack_list(result,0)
+ setfield(result,"width",0)
+ setfield(result,"height",0)
+ setfield(result,"depth",0)
+ end
+ if cleanupdestinations then stack[reference] = nil end
+ return result, resolved
+ elseif trace_destinations then
+ report_destination("unable to resolve attribute %a",reference)
+ end
+end
+
+-- function nodes.destinations.handler(head)
+-- if topofstack > 0 then
+-- return inject_area(head,attribute,makedestination,stack,done) -- singular
+-- else
+-- return head, false
+-- end
+-- end
+
+function nodes.destinations.handler(head)
+ if topofstack > 0 then
+ head = tonut(head)
+ local head, done = inject_areas(head,attribute,makedestination,stack,done)
+ return tonode(head), done
+ else
+ return head, false
+ end
+end
+
+
+-- will move
+
+function references.mark(reference,h,d,view)
+ return setdestination(tex.currentgrouplevel,h,d,reference,view)
+end
+
+function references.inject(prefix,reference,specification) -- todo: use currentreference is possible
+ local set, bug = references.identify(prefix,reference)
+ if bug or #set == 0 then
+ -- unknown ref, just don't set it and issue an error
+ else
+ set.highlight = specification.highlight
+ set.newwindow = specification.newwindow
+ set.layer = specification.layer
+ setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error
+ end
+end
+
+-- function references.injectinternal(internal,specification)
+-- references.inject("","internal("..internal..")",specification)
+-- if bug or #set == 0 then
+-- -- unknown ref, just don't set it and issue an error
+-- else
+-- -- nil prefix when ""
+-- -- check
+-- set.highlight = specification.highlight
+-- set.newwindow = specification.newwindow
+-- set.layer = specification.layer
+-- setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error
+-- end
+-- end
+
+function references.injectcurrentset(h,d) -- used inside doifelse
+ local currentset = references.currentset
+ if currentset then
+ setreference(h,d,currentset) -- sets attribute / todo: for set[*].error
+ end
+end
+
+implement {
+ name = "injectreference",
+ actions = references.inject,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "highlight", "boolean" },
+ { "newwindow", "boolean" },
+ { "layer" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "view" },
+ }
+ }
+}
+
+-- implement {
+-- name = "injectinternalreference",
+-- actions = references.injectinternal,
+-- arguments = {
+-- "integer",
+-- {
+-- { "highlight", "boolean" },
+-- { "newwindow", "boolean" },
+-- { "layer" },
+-- { "height", "dimen" },
+-- { "depth", "dimen" },
+-- { "view" },
+-- }
+-- }
+-- }
+
+implement {
+ name = "injectcurrentreference",
+ actions = references.injectcurrentset,
+}
+
+implement {
+ name = "injectcurrentreferencehtdp",
+ actions = references.injectcurrentset,
+ arguments = { "dimen", "dimen" },
+}
+
+--
+
+local function checkboth(open,close)
+ if open and open ~= "" then
+ local set, bug = references.identify("",open)
+ open = not bug and #set > 0 and set
+ end
+ if close and close ~= "" then
+ local set, bug = references.identify("",close)
+ close = not bug and #set > 0 and set
+ end
+ return open, close
+end
+
+-- end temp hack
+
+statistics.register("interactive elements", function()
+ if nofreferences > 0 or nofdestinations > 0 then
+ return string.format("%s references, %s destinations",nofreferences,nofdestinations)
+ else
+ return nil
+ end
+end)
+
+function references.enableinteraction()
+ tasks.enableaction("shipouts","nodes.references.handler")
+ tasks.enableaction("shipouts","nodes.destinations.handler")
+ function references.enableinteraction() end
+end
+
+implement {
+ name = "enableinteraction",
+ actions = references.enableinteraction,
+ onlyonce = true
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-res.lua b/Master/texmf-dist/tex/context/base/mkiv/node-res.lua
new file mode 100644
index 00000000000..4d25314ad85
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-res.lua
@@ -0,0 +1,690 @@
+if not modules then modules = { } end modules ['node-res'] = {
+ 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 gmatch, format = string.gmatch, string.format
+local tonumber, round = tonumber, math.round
+
+--[[ldx--
+<p>The next function is not that much needed but in <l n='context'/> we use
+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 whatsitcodes = nodes.whatsitcodes
+local skipcodes = nodes.skipcodes
+local kerncodes = nodes.kerncodes
+local rulecodes = nodes.rulecodes
+local nodecodes = nodes.nodecodes
+local boundarycodes = nodes.boundarycodes
+
+local glyph_code = nodecodes.glyph
+
+local allocate = utilities.storage.allocate
+
+local texgetcount = tex.getcount
+
+local reserved, nofreserved = { }, 0
+
+-- user nodes
+
+local userids = allocate()
+local lastid = 0
+
+setmetatable(userids, {
+ __index = function(t,k)
+ if type(k) == "string" then
+ lastid = lastid + 1
+ rawset(userids,lastid,k)
+ rawset(userids,k,lastid)
+ return lastid
+ else
+ rawset(userids,k,k)
+ return k
+ end
+ end,
+ __call = function(t,k)
+ return t[k]
+ end
+} )
+
+-- nuts overload
+
+local nuts = nodes.nuts
+local nutpool = { }
+nuts.pool = nutpool
+
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getbox = nuts.getbox
+local getfield = nuts.getfield
+local getid = nuts.getid
+local getlist = nuts.getlist
+
+local setfield = nuts.setfield
+local setchar = nuts.setchar
+local setlist = nuts.setlist
+
+local copy_nut = nuts.copy
+local new_nut = nuts.new
+local free_nut = nuts.free
+
+local copy_node = nodes.copy
+local new_node = nodes.new
+
+-- at some point we could have a dual set (the overhead of tonut is not much larger than
+-- metatable associations at the lua/c end esp if we also take assignments into account
+
+-- table.setmetatableindex(nodepool,function(t,k,v)
+-- -- report_nodes("defining nodepool[%s] instance",k)
+-- local f = nutpool[k]
+-- local v = function(...)
+-- return tonode(f(...))
+-- end
+-- t[k] = v
+-- return v
+-- end)
+--
+-- -- we delay one step because that permits us a forward reference
+-- -- e.g. in pdfsetmatrix
+
+table.setmetatableindex(nodepool,function(t,k,v)
+ -- report_nodes("defining nodepool[%s] instance",k)
+ local v = function(...)
+ local f = nutpool[k]
+ local v = function(...)
+ return tonode(f(...))
+ end
+ t[k] = v
+ return v(...)
+ end
+ t[k] = v
+ return v
+end)
+
+local function register_nut(n)
+ nofreserved = nofreserved + 1
+ reserved[nofreserved] = n
+ return n
+end
+
+local function register_node(n)
+ nofreserved = nofreserved + 1
+ if type(n) == "number" then -- isnut(n)
+ reserved[nofreserved] = n
+ else
+ reserved[nofreserved] = tonut(n)
+ end
+ return n
+end
+
+nodepool.userids = userids
+nodepool.register = register_node
+
+nutpool.userids = userids
+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 textdir = register_nut(new_nut("dir"))
+
+local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua))
+local special = register_nut(new_nut("whatsit",whatsitcodes.special))
+local user_n = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_n,"type",100) -- 44
+local user_l = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_l,"type",110) -- 44
+local user_s = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_s,"type",115) -- 44
+local user_t = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_t,"type",116) -- 44
+----- user_c = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_c,"type",108) -- 44
+
+local left_margin_kern = register_nut(new_nut("margin_kern",0))
+local right_margin_kern = register_nut(new_nut("margin_kern",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 temp = register_nut(new_nut("temp",0))
+
+local noad = register_nut(new_nut("noad"))
+
+local boundary = register_nut(new_nut("boundary",boundarycodes.user))
+local wordboundary = register_nut(new_nut("boundary",boundarycodes.word))
+
+-- the dir field needs to be set otherwise crash:
+
+local rule = register_nut(new_nut("rule")) setfield(rule, "dir","TLT")
+local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setfield(rule, "dir","TLT")
+local userrule = register_nut(new_nut("rule",rulecodes.user)) setfield(rule, "dir","TLT")
+local hlist = register_nut(new_nut("hlist")) setfield(hlist,"dir","TLT")
+local vlist = register_nut(new_nut("vlist")) setfield(vlist,"dir","TLT")
+
+function nutpool.zeroglue(n)
+ if n then
+ return
+ getfield(n,"width") == 0 and
+ getfield(n,"stretch") == 0 and
+ getfield(n,"shrink") == 0 and
+ getfield(n,"stretch_order") == 0 and
+ getfield(n,"shrink_order") == 0
+ else
+ return false
+ end
+end
+
+function nutpool.glyph(fnt,chr)
+ local n = copy_nut(glyph)
+ if fnt then setfield(n,"font",fnt) end
+ if chr then setchar(n,chr) end
+ return n
+end
+
+function nutpool.penalty(p)
+ local n = copy_nut(penalty)
+ if p and p ~= 0 then
+ setfield(n,"penalty",p)
+ end
+ return n
+end
+
+function nutpool.kern(k)
+ local n = copy_nut(kern)
+ if k and k ~= 0 then
+ setfield(n,"kern",k)
+ end
+ return n
+end
+
+function nutpool.boundary(v)
+ local n = copy_nut(boundary)
+ if v and v ~= 0 then
+ setfield(n,"value",v)
+ end
+ return n
+end
+
+function nutpool.wordboundary(v)
+ local n = copy_nut(wordboundary)
+ if v and v ~= 0 then
+ setfield(n,"value",v)
+ end
+ return n
+end
+
+function nutpool.fontkern(k)
+ local n = copy_nut(fontkern)
+ setfield(n,"kern",k)
+ return n
+end
+
+function nutpool.italickern(k)
+ local n = copy_nut(italickern)
+ if k and k ~= 0 then
+ setfield(n,"kern",k)
+ end
+ return n
+end
+
+function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
+ local s = copy_nut(glue_spec)
+ if width and width ~= 0 then
+ setfield(s,"width",width)
+ end
+ if stretch and stretch ~= 0 then
+ setfield(s,"stretch",stretch)
+ end
+ if shrink and shrink ~= 0 then
+ setfield(s,"shrink",shrink)
+ end
+ if stretch_order and stretch_order ~= 0 then
+ setfield(s,"stretch_order",stretch_order)
+ end
+ if shrink_order and shrink_order ~= 0 then
+ setfield(s,"shrink_order",shrink_order)
+ end
+ return s
+end
+
+local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
+ local n = copy_nut(skip)
+ if width and width ~= 0 then
+ setfield(n,"width",width)
+ end
+ if stretch and stretch ~= 0 then
+ setfield(n,"stretch",stretch)
+ end
+ if shrink and shrink ~= 0 then
+ setfield(n,"shrink",shrink)
+ end
+ if stretch_order and stretch_order ~= 0 then
+ setfield(n,"stretch_order",stretch_order)
+ end
+ if shrink_order and shrink_order ~= 0 then
+ setfield(n,"shrink_order",shrink_order)
+ end
+ return n
+end
+
+function nutpool.stretch(a,b)
+ local n = copy_nut(glue)
+ if b then
+ setfield(n,"stretch",a)
+ setfield(n,"stretch_order",b)
+ else
+ setfield(n,"stretch",1)
+ setfield(n,"stretch_order",a or 1)
+ end
+ return n
+end
+
+function nutpool.shrink(a,b)
+ local n = copy_nut(glue)
+ if b then
+ setfield(n,"shrink",a)
+ setfield(n,"shrink_order",b)
+ else
+ setfield(n,"shrink",1)
+ setfield(n,"shrink_order",a or 1)
+ end
+ return n
+end
+
+function nutpool.glue(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(glue,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.negatedglue(glue)
+ local n = copy_nut(glue)
+ local width = getfield(n,"width")
+ local stretch = getfield(n,"stretch")
+ local shrink = getfield(n,"shrink")
+ if width and width ~= 0 then
+ setfield(n,"width", -width)
+ end
+ if stretch and stretch ~= 0 then
+ setfield(n,"stretch",-stretch)
+ end
+ if shrink and shrink ~= 0 then
+ setfield(n,"shrink", -shrink)
+ end
+ return n
+end
+
+function nutpool.leftskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.rightskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.lineskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.baselineskip(width,stretch,shrink)
+ return someskip(baselineskip,width,stretch,shrink)
+end
+
+function nutpool.disc()
+ return copy_nut(disc)
+end
+
+function nutpool.textdir(dir)
+ local t = copy_nut(textdir)
+ setfield(t,"dir",dir)
+ return t
+end
+
+function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+ local n = copy_nut(rule)
+ if width then -- also 0 else adapt
+ setfield(n,"width",width)
+ end
+ if height then -- also 0 else adapt
+ setfield(n,"height",height)
+ end
+ if depth then -- also 0 else adapt
+ setfield(n,"depth",depth)
+ end
+ if dir then
+ setfield(n,"dir",dir)
+ end
+ return n
+end
+
+function nutpool.emptyrule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+ local n = copy_nut(emptyrule)
+ if width then -- also 0 else adapt
+ setfield(n,"width",width)
+ end
+ if height then -- also 0 else adapt
+ setfield(n,"height",height)
+ end
+ if depth then -- also 0 else adapt
+ setfield(n,"depth",depth)
+ end
+ if dir then
+ setfield(n,"dir",dir)
+ end
+ return n
+end
+
+function nutpool.userrule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+ local n = copy_nut(userrule)
+ if width then -- also 0 else adapt
+ setfield(n,"width",width)
+ end
+ if height then -- also 0 else adapt
+ setfield(n,"height",height)
+ end
+ if depth then -- also 0 else adapt
+ setfield(n,"depth",depth)
+ end
+ if dir then
+ setfield(n,"dir",dir)
+ end
+ return n
+end
+
+function nutpool.latelua(code)
+ local n = copy_nut(latelua)
+ setfield(n,"string",code)
+ return n
+end
+
+if context and _cldo_ then
+
+ -- a typical case where we have more nodes than nuts
+
+ local context = context
+
+ local f_cldo = string.formatters["_cldo_(%i)"]
+ local register = context.registerfunction
+
+ local latelua_node = register_node(new_node("whatsit",whatsitcodes.latelua))
+ local latelua_nut = register_nut (new_nut ("whatsit",whatsitcodes.latelua))
+
+ local setfield_node = nodes.setfield
+ local setfield_nut = nuts .setfield
+
+ -- function nodepool.lateluafunction(f)
+ -- local n = copy_node(latelua_node)
+ -- setfield_node(n,"string",f_cldo(register(f)))
+ -- return n
+ -- end
+
+ -- function nutpool.lateluafunction(f)
+ -- local n = copy_nut(latelua_nut)
+ -- setfield_nut(n,"string",f_cldo(register(f)))
+ -- return n
+ -- end
+
+ -- when function in latelua:
+
+ function nodepool.lateluafunction(f)
+ local n = copy_node(latelua_node)
+ setfield_node(n,"string",f)
+ return n
+ end
+
+ function nutpool.lateluafunction(f)
+ local n = copy_nut(latelua_nut)
+ setfield_nut(n,"string",f)
+ return n
+ end
+
+ local latefunction = nodepool.lateluafunction
+ local flushnode = context.flushnode
+
+ -- function context.lateluafunction(f)
+ -- flushnode(latefunction(f)) -- hm, quite some indirect calls
+ -- end
+
+ -- when function in latelua:
+
+ -- function context.lateluafunction(f)
+ -- local n = copy_node(latelua_node)
+ -- setfield_node(n,"string",f)
+ -- flushnode(n)
+ -- end
+
+ -- local contextsprint = context.sprint
+ -- local ctxcatcodes = tex.ctxcatcodes
+ -- local storenode = context.storenode
+
+ -- when 0.79 is out:
+
+ -- function context.lateluafunction(f)
+ -- contextsprint(ctxcatcodes,"\\cldl",storenode(latefunction(f))," ")
+ -- end
+
+ -- when function in latelua:
+
+ function context.lateluafunction(f)
+ local n = copy_node(latelua_node)
+ setfield_node(n,"string",f)
+ contextsprint(ctxcatcodes,"\\cldl",storenode(n)," ")
+ end
+
+end
+
+function nutpool.leftmarginkern(glyph,width)
+ local n = copy_nut(left_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to left margin glyph node")
+ elseif getid(glyph) ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left")
+ else
+ setfield(n,"glyph",glyph)
+ end
+ if width and width ~= 0 then
+ setfield(n,"width",width)
+ end
+ return n
+end
+
+function nutpool.rightmarginkern(glyph,width)
+ local n = copy_nut(right_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to right margin glyph node")
+ elseif getid(glyph) ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right")
+ else
+ setfield(n,"glyph",glyph)
+ end
+ if width and width ~= 0 then
+ setfield(n,"width",width)
+ end
+ return n
+end
+
+function nutpool.temp()
+ return copy_nut(temp)
+end
+
+function nutpool.noad()
+ return copy_nut(noad)
+end
+
+function nutpool.hlist(list,width,height,depth,shift)
+ local n = copy_nut(hlist)
+ if list then
+ setlist(n,list)
+ end
+ if width and width ~= 0 then
+ setfield(n,"width",width)
+ end
+ if height and height ~= 0 then
+ setfield(n,"height",height)
+ end
+ if depth and depth ~= 0 then
+ setfield(n,"depth",depth)
+ end
+ if shift and shift ~= 0 then
+ setfield(n,"shift",shift)
+ end
+ return n
+end
+
+function nutpool.vlist(list,width,height,depth,shift)
+ local n = copy_nut(vlist)
+ if list then
+ setlist(n,list)
+ end
+ if width and width ~= 0 then
+ setfield(n,"width",width)
+ end
+ if height and height ~= 0 then
+ setfield(n,"height",height)
+ end
+ if depth and depth ~= 0 then
+ setfield(n,"depth",depth)
+ end
+ if shift and shift ~= 0 then
+ setfield(n,"shift",shift)
+ end
+ return n
+end
+
+-- local num = userids["my id"]
+-- local str = userids[num]
+
+function nutpool.usernumber(id,num)
+ local n = copy_nut(user_n)
+ 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_l)
+ 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_s)
+ 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_t)
+ if tokens then
+ setfield(n,"user_id",id)
+ setfield(n,"value",tokens)
+ else
+ setfield(n,"value",id)
+ end
+ return n
+end
+
+-- function nutpool.usercode(id,code)
+-- local n = copy_nut(user_c)
+-- if code then
+-- setfield(n,"user_id",id)
+-- setfield(n,"value",code)
+-- else
+-- setfield(n,"value",id)
+-- end
+-- return n
+-- end
+
+function nutpool.special(str)
+ local n = copy_nut(special)
+ setfield(n,"data",str)
+ 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
+ end
+ local nl, nr = 0, nofreserved
+ for i=1,nofreserved do
+ local ri = reserved[i]
+ -- if not (getid(ri) == glue_spec and not getfield(ri,"is_writable")) then
+ free_nut(reserved[i])
+ -- end
+ end
+ if nofboxes then
+ for i=0,nofboxes do
+ local l = getbox(i)
+ if l then
+-- print(nodes.listtoutf(getlist(l)))
+ free_nut(l) -- also list ?
+ nl = nl + 1
+ end
+ end
+ end
+ reserved = { }
+ nofreserved = 0
+ return nr, nl, nofboxes -- can be nil
+end
+
+
+local function usage()
+ local t = { }
+ for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do
+ t[tag] = n
+ end
+ return t
+end
+
+nutpool .cleanup = cleanup
+nodepool.cleanup = cleanup
+
+nutpool .usage = usage
+nodepool.usage = usage
+
+-- end
+
+statistics.register("cleaned up reserved nodes", function()
+ return format("%s nodes, %s lists of %s", cleanup(texgetcount("c_syst_last_allocated_box")))
+end) -- \topofboxstack
+
+statistics.register("node memory usage", function() -- comes after cleanup !
+ local usage = status.node_mem_usage
+ if usage ~= "" then
+ return usage
+ end
+end)
+
+lua.registerfinalizer(cleanup, "cleanup reserved nodes")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua
new file mode 100644
index 00000000000..e0649e99b3e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua
@@ -0,0 +1,536 @@
+if not modules then modules = { } end modules ['node-rul'] = {
+ version = 1.001,
+ comment = "companion to node-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this will go to an auxiliary module
+-- beware: rules now have a dir field
+--
+-- todo: make robust for layers ... order matters
+
+
+local attributes, nodes, node = attributes, nodes, node
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setlink = nuts.setlink
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+
+local nodecodes = nodes.nodecodes
+local tasks = nodes.tasks
+
+local properties = nodes.properties
+local attribs = node.current_attr
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local rule_code = nodecodes.rule
+
+function nodes.striprange(first,last) -- todo: dir
+ if first and last then -- just to be sure
+ if first == last then
+ return first, last
+ end
+ while first and first ~= last do
+ local id = getid(first)
+ if id == glyph_code or id == disc_code then -- or id == rule_code
+ break
+ else
+ first = getnext(first)
+ end
+ end
+ if not first then
+ return nil, nil
+ elseif first == last then
+ return first, last
+ end
+ while last and last ~= first do
+ local id = getid(last)
+ if id == glyph_code or id == disc_code then -- or id == rule_code
+ break
+ else
+ local prev = getprev(last) -- luatex < 0.70 has italic correction kern not prev'd
+ if prev then
+ last = prev
+ else
+ break
+ end
+ end
+ end
+ if not last then
+ return nil, nil
+ end
+ end
+ return first, last
+end
+
+-- todo: order and maybe other dimensions
+
+local floor = math.floor
+
+local trace_ruled = false trackers.register("nodes.rules", function(v) trace_ruled = v end)
+local report_ruled = logs.reporter("nodes","rules")
+
+local n_tostring = nodes.idstostring
+local n_tosequence = nodes.tosequence
+
+local a_ruled = attributes.private('ruled')
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local list_dimensions = nuts.dimensions
+local hpack_nodes = nuts.hpack
+
+local striprange = nodes.striprange
+
+local fontdata = fonts.hashes.identifiers
+local variables = interfaces.variables
+local dimenfactor = fonts.helpers.dimenfactor
+local splitdimen = number.splitdimen
+
+local v_yes = variables.yes
+local v_all = variables.all
+local v_foreground = variables.foreground
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local rule_code = nodecodes.rule
+local dir_code = nodecodes.dir
+
+local userskip_code = skipcodes.userskip
+local spaceskip_code = skipcodes.spaceskip
+local xspaceskip_code = skipcodes.xspaceskip
+local leader_code = skipcodes.leaders
+
+local kerning_code = kerncodes.kern
+
+local nodepool = nuts.pool
+
+local new_rule = nodepool.rule
+local new_userrule = nodepool.userrule
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+
+-- we can use this one elsewhere too
+--
+-- todo: functions: word, sentence
+--
+-- glyph rule unset whatsit glue margin_kern kern math disc
+
+local checkdir = true
+
+-- we assume {glyphruns} and no funny extra kerning, ok, maybe we need
+-- a dummy character as start and end; anyway we only collect glyphs
+--
+-- this one needs to take layers into account (i.e. we need a list of
+-- critical attributes)
+
+-- omkeren class en level -> scheelt functie call in analyze
+
+-- todo: switching inside math
+
+-- handlers
+
+local function processwords(attribute,data,flush,head,parent) -- we have hlistdir and local dir
+ local n = head
+ if n then
+ local f, l, a, d, i, class
+ local continue, leaders, done, strip, level = false, false, false, true, -1
+ while n do
+ local id = getid(n)
+ if id == glyph_code or id == rule_code then
+ local aa = getattr(n,attribute)
+ if aa then
+ if aa == a then
+ if not f then -- ?
+ f = n
+ end
+ l = n
+ else
+ -- possible extensions: when in same class then keep spanning
+ local newlevel, newclass = floor(aa/1000), aa%1000
+ -- strip = not continue or level == 1 -- 0
+ if f then
+ if class == newclass then -- and newlevel > level then
+ head, done = flush(head,f,l,d,level,parent,false), true
+ else
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ end
+ f, l, a = n, n, aa
+ level, class = newlevel, newclass
+ d = data[class]
+ local c = d.continue
+ leaders = c == v_all
+ continue = leaders or c == v_yes
+ end
+ else
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ f, l, a = nil, nil, nil
+ end
+ elseif id == disc_code then
+ if f then
+ l = n
+ end
+ elseif id == kern_code and getsubtype(n) == kerning_code then
+ if f then
+ l = n
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ f, l, a = nil, nil, nil
+ end
+ local list = getlist(n)
+ if list then
+ setlist(n,(processwords(attribute,data,flush,list,n))) -- watch ()
+ end
+ elseif checkdir and id == dir_code then -- only changes in dir, we assume proper boundaries
+ if f and a then
+ l = n
+ end
+ elseif f then
+ if continue then
+ if id == penalty_code then
+ l = n
+ -- elseif id == kern_code then
+ -- l = n
+ 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
+ l = n
+ else
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ f, l, a = nil, nil, nil
+ end
+ end
+ else
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ f, l, a = nil, nil, nil
+ end
+ end
+ n = getnext(n)
+ end
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ return head, true -- todo: done
+ else
+ return head, false
+ end
+end
+
+-- nodes.processwords = processwords
+
+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
+end
+
+--
+
+local rules = nodes.rules or { }
+nodes.rules = rules
+rules.data = rules.data or { }
+
+storage.register("nodes/rules/data", rules.data, "nodes.rules.data")
+
+local data = rules.data
+
+-- we implement user rules here as it takes less code this way
+
+local function userrule(t)
+ local r = new_userrule(t.width or 0,t.height or 0,t.depth or 0)
+ setfield(r,"attr",attribs())
+ properties[r] = t
+ return tonode(r)
+end
+
+rules.userrule = userrule
+local ruleactions = { }
+rules.ruleactions = ruleactions
+
+callback.register("process_rule",function(n,h,v)
+ local n = tonut(n)
+ local p = properties[n]
+ local i = p.type or "draw"
+ local a = ruleactions[i]
+ if a then
+ a(p,h,v,i,n)
+ end
+end)
+
+--
+
+function rules.define(settings)
+ data[#data+1] = settings
+ context(#data)
+end
+
+local a_viewerlayer = attributes.private("viewerlayer")
+
+local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose
+ if getid(f) ~= glyph_code then
+ -- saveguard ... we need to deal with rules and so (math)
+ return head
+ end
+ local r, m
+ if strip then
+ if trace_ruled then
+ local before = n_tosequence(f,l,true)
+ f, l = striprange(f,l)
+ local after = n_tosequence(f,l,true)
+ report_ruled("range stripper, before %a, after %a",before,after)
+ else
+ f, l = striprange(f,l)
+ end
+ end
+ if not f then
+ return head
+ end
+ local w, ht, dp = list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),f,getnext(l))
+ local method = d.method
+ local offset = d.offset
+ local continue = d.continue
+ local dy = d.dy
+ local order = d.order
+ local max = d.max
+ local mp = d.mp
+ local rulethickness = d.rulethickness
+ local unit = d.unit
+ local ma = d.ma
+ local ca = d.ca
+ local ta = d.ta
+ local colorspace = ma > 0 and ma or getattr(f,a_colorspace) or 1
+ local color = ca > 0 and ca or getattr(f,a_color)
+ local transparency = ta > 0 and ta or getattr(f,a_transparency)
+ local foreground = order == v_foreground
+ local layer = getattr(f,a_viewerlayer)
+ local e = dimenfactor(unit,getfont(f)) -- what if no glyph node
+ local rt = tonumber(rulethickness)
+ if rt then
+ rulethickness = e * rulethickness / 2
+ else
+ local n, u = splitdimen(rulethickness)
+ if n and u then -- we need to intercept ex and em and % and ...
+ rulethickness = n * dimenfactor(u,fontdata[getfont(f)]) / 2
+ else
+ rulethickness = 1/5
+ end
+ end
+ --
+ if level > max then
+ level = max
+ end
+ if method == 0 then -- center
+ offset = 2*offset
+ m = (offset+(level-1)*dy)*e/2 + rulethickness/2
+ else
+ m = 0
+ end
+
+ local function inject(r,w,ht,dp)
+ if layer then
+ setattr(r,a_viewerlayer,layer)
+ end
+ local k = new_kern(-w)
+ if foreground then
+ insert_node_after(head,l,k)
+ insert_node_after(head,k,r)
+ l = r
+ else
+ head = insert_node_before(head,f,r)
+ insert_node_after(head,r,k)
+ end
+ if trace_ruled then
+ report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a",
+ level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true))
+ end
+ end
+
+ if mp and mp ~= "" then
+ local r = userrule {
+ width = w,
+ height = ht,
+ depth = dp,
+ type = "mp",
+ factor = e,
+ offset = offset,
+ line = rulethickness,
+ data = mp,
+ ma = colorspace,
+ ca = color,
+ ta = transparency,
+ }
+ inject(tonut(r),w,ht,dp)
+ else
+ for i=1,level do
+ local ht = (offset+(i-1)*dy)*e + rulethickness - m
+ local dp = -(offset+(i-1)*dy)*e + rulethickness + m
+ local r = new_rule(w,ht,dp)
+ if color then
+ setattr(r,a_colorspace,colorspace)
+ setattr(r,a_color,color)
+ end
+ if transparency then
+ setattr(r,a_transparency,transparency)
+ end
+ inject(r,w,ht,dp)
+ end
+ end
+ return head
+end
+
+local process = nodes.processwords
+
+rules.handler = function(head) return process(a_ruled,data,flush_ruled,head) end
+
+function rules.enable()
+ tasks.enableaction("shipouts","nodes.rules.handler")
+end
+
+-- elsewhere:
+--
+-- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.handler")
+-- tasks.disableaction("shipouts", "nodes.rules.handler") -- only kick in when used
+
+local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end)
+
+local report_shifted = logs.reporter("nodes","shifting")
+
+local a_shifted = attributes.private('shifted')
+
+nodes.shifts = nodes.shifts or { }
+nodes.shifts.data = nodes.shifts.data or { }
+
+storage.register("nodes/shifts/data", nodes.shifts.data, "nodes.shifts.data")
+
+local data = nodes.shifts.data
+
+function nodes.shifts.define(settings)
+ data[#data+1] = settings
+ context(#data)
+end
+
+local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose
+ if true then
+ first, last = striprange(first,last)
+ end
+ local prev = getprev(first)
+ local next = getnext(last)
+ setprev(first)
+ setnext(last)
+ local width, height, depth = list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),first,next)
+ local list = hpack_nodes(first,width,"exactly")
+ if first == head then
+ head = list
+ end
+ if prev then
+ setlink(prev,list)
+ end
+ if next then
+ setlink(next,list)
+ end
+ local raise = data.dy * dimenfactor(data.unit,fontdata[getfont(first)])
+ setfield(list,"shift",raise)
+ setfield(list,"height",height)
+ setfield(list,"depth",depth)
+ if trace_shifted then
+ report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true))
+ end
+ return head
+end
+
+local process = nodes.processwords
+
+nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end
+
+function nodes.shifts.enable()
+ tasks.enableaction("shipouts","nodes.shifts.handler")
+end
+
+-- interface
+
+local implement = interfaces.implement
+
+implement {
+ name = "definerule",
+ actions = { rules.define, context },
+ arguments = {
+ {
+ { "continue" },
+ { "unit" },
+ { "order" },
+ { "method", "integer" },
+ { "offset", "number" },
+ { "rulethickness", "string" },
+ { "dy", "number" },
+ { "max", "number" },
+ { "ma", "integer" },
+ { "ca", "integer" },
+ { "ta", "integer" },
+ { "mp", "string" },
+ }
+ }
+}
+
+implement {
+ name = "enablerules",
+ onlyonce = true,
+ actions = rules.enable
+}
+
+implement {
+ name = "defineshift",
+ actions = { nodes.shifts.define, context },
+ arguments = {
+ {
+ { "continue" },
+ { "unit" },
+ { "method", "integer" },
+ { "dy", "number" },
+ }
+ }
+}
+
+implement {
+ name = "enableshifts",
+ onlyonce = true,
+ actions = nodes.shifts.enable
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv
new file mode 100644
index 00000000000..8706b8ecf39
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv
@@ -0,0 +1,423 @@
+%D \module
+%D [ file=node-rul,
+%D version=2009.11.03, % 1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Bars,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: ex and and em traveling with attribute
+% todo: this will move to typo-rul + ctxcommands
+
+\writestatus{loading}{ConTeXt Core Macros / Bars}
+
+%D \macros
+%D {underbar,underbars,
+%D overbar,overbars,
+%D overstrike,overstrikes,
+%D setupbar}
+%D
+%D In the rare case that we need undelined words, for instance because all font
+%D alternatives are already in use, one can use \type {\underbar} and \type
+%D {\overstrike} and their plural forms.
+%D
+%D \startbuffer
+%D \underbars {drawing \underbar{bars} under words is a typewriter leftover}
+%D \overstrikes {striking words makes them \overstrike {unreadable} but
+%D sometimes even \overbar {top lines} come into view.}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The next macros are derived from the \PLAIN\ \TEX\ one, but also supports
+%D nesting. The \type{$} keeps us in horizontal mode and at the same time
+%D applies grouping.
+%D
+%D \showsetup{underbar}
+%D \showsetup{underbars}
+%D \showsetup{overbar}
+%D \showsetup{overbars}
+%D \showsetup{overstrike}
+%D \showsetup{overstrikes}
+%D
+%D \showsetup{setupunderbar}
+%D
+%D Nested bars can be configured by appending \type {:<index>} to the category.
+%D Normally units in combination with a unitless thickness specification but
+%D there units can be used too.
+%D
+%D \startbuffer
+%D \setupbars[unit=mm,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=ex,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=pt,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=pt,rulethickness=10pt] bar\startbar[underbar]foo\stopbar bar
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+%D
+%D As with many early usage of \LUA\ in \MKIV\ this mechanism explores a way
+%D to deal with local settings at the \TEX\ end and remembering parameters
+%D at the \LUA\ end. We might do things differently now, but as settings normally
+%D don't change that often, we're not in a hurry to do that now. The problem at
+%D the \LUA\ end is that we don't know when to clean up.
+
+\unprotect
+
+%definesystemattribute[ruled]
+%definesystemattribute[shifted]
+
+\registerctxluafile{node-rul}{1.001}
+
+\installcorenamespace{bar}
+\installcorenamespace{barindex}
+\installcorenamespace{barattribute}
+\installcorenamespace{barstack}
+
+\installcommandhandler \??bar {bar} \??bar
+
+\newtoks\t_node_rules_checklist
+
+\let\c_node_rules_index\relax % temporary synonym
+\let\p_node_rules_color\empty
+
+\let\setupbars\setupbar
+
+\appendtoks
+ \ifsecondargument
+ \node_rules_define
+ \else
+ \the\t_node_rules_checklist
+ \fi
+\to \everysetupbar
+
+\appendtoks
+ \ifcsname\??barindex\currentbar\endcsname
+ \lastnamedcs
+ \else
+ \expandafter\newcount\csname\??barindex\currentbar\endcsname
+ \fi
+ \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}%
+ \node_rules_define
+ \setuevalue\currentbar{\node_rules_direct{\currentbar}}%
+\to \everydefinebar
+
+\unexpanded\def\node_rules_define
+ {\edef\p_node_rules_color{\barparameter\c!color}%
+ \setevalue{\??barattribute\currentbar}{\number
+ \clf_definerule
+ continue {\barparameter\c!continue}%
+ unit {\barparameter\c!unit}%
+ order {\barparameter\c!order}%
+ rulethickness {\barparameter\c!rulethickness}%
+ method \barparameter\c!method
+ max \barparameter\c!max\space % number
+ mp {\includeMPgraphic{\barparameter\c!mp}}
+ ma \thecolormodelattribute
+ ca \thecolorattribute\p_node_rules_color
+ ta \thetransparencyattribute\p_node_rules_color
+ offset \barparameter\c!offset\space % number
+ dy \barparameter\c!dy\space % number
+ \relax}}
+
+\unexpanded\def\node_rules_redefine#1%
+ {\def\currentbar{#1}\node_rules_define}
+
+\unexpanded\def\node_rules_direct#1%
+ {\groupedcommand{\node_rules_set{#1}}\relax}
+
+% \unexpanded\def\node_rules_set
+% {\clf_enablerules % will be moved to lua
+% \glet\node_rules_set\node_rules_set_indeed
+% \node_rules_set}
+%
+%\unexpanded\def\node_rules_set_indeed#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
+
+\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
+ % todo: move this to lua .. we callout anyway
+ \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname
+ \advance\c_node_rules_index\plusone
+ \clf_enablerules % will be relaxed
+ \attribute\ruledattribute\numexpr
+ \plusthousand*\c_node_rules_index
+ % optimizing this one needs testing
+ +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_index\fi\endcsname
+ \relax}
+
+\unexpanded\def\startbar[#1]%
+ {\begingroup
+ \node_rules_set{#1}}
+
+\unexpanded\def\stopbar
+ {\endgroup}
+
+\unexpanded\def\setbar[#1]%
+ {\node_rules_set{#1}}
+
+\let\directsetbar\node_rules_set
+
+% ungrouped
+
+\newcount\c_node_rules_nesting % todo: same as colors
+
+\unexpanded\def\pushbar[#1]%
+ {\global\advance\c_node_rules_nesting\plusone
+ \expandafter\edef\csname\??barstack\number\c_node_rules_nesting\endcsname{\attribute\ruledattribute\the\attribute\ruledattribute}%
+ \node_rules_set{#1}}
+
+\unexpanded\def\popbar
+ {\csname\??barstack\number\c_node_rules_nesting\endcsname
+ \global\advance\c_node_rules_nesting\minusone}
+
+\setupbars
+ [\c!method=0, % new: 0=center nested, 1=stack nested
+ \c!continue=\v!no,
+ \c!offset=0, % upwards, replaces: topoffset bottomoffset
+ \c!dy=0,
+ \c!max=3,
+ \c!style=,
+ \c!rulethickness=.1,
+ \c!order=\v!foreground,
+ \c!unit=ex, % so now we are relative
+ \c!color=] % replaces: rulecolor
+
+% \definebar[touchbar] [\c!method=0,\c!dy=-0.4,\c!offset=-0.0]
+% \definebar[touchbars] [touchbar] [\c!continue=\v!yes]
+
+\let\normalmathoverbar \overbar
+\let\normalmathunderbar \underbar
+\let\normalmathoverstrike \overstrike
+\let\normalmathunderstrike\understrike
+
+\definebar[\v!overbar] [\c!method=1,\c!dy=0.4,\c!offset=1.8,\c!continue=\v!yes]
+\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
+\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes]
+
+\definebar
+ [\v!understrike]
+ [\c!method=0,
+ \c!offset=1.375,
+ \c!rulethickness=2.5,
+ \c!continue=\v!yes,
+ \c!order=\v!background,
+ \c!color=lightgray]
+
+\definebar[\v!overbars] [\v!overbar] [\c!continue=\v!no]
+\definebar[\v!underbars] [\v!underbar] [\c!continue=\v!no]
+\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no]
+\definebar[\v!understrikes][\v!understrike][\c!continue=\v!no]
+
+% \setupbar[\v!overstrike][continue=all]
+
+% we want these always so ...
+
+\ifdefined\normalmathunderbar
+ \expandafter\let\expandafter\normaltextunderbar\csname\v!underbar\endcsname
+ \unexpanded\def\underbar{\mathortext\normalmathunderbar\normaltextunderbar}
+\else
+ \expandafter\let\expandafter\underbar\csname\v!underbar\endcsname
+\fi
+
+\ifdefined\normalmathoverbar
+ \expandafter\let\expandafter\normaltextoverbar\csname\v!overbar\endcsname
+ \unexpanded\def\overbar{\mathortext\normalmathoverbar\normaltextoverbar}
+\else
+ \expandafter\let\expandafter\overbar\csname\v!overbar\endcsname
+\fi
+
+\ifdefined\normalmathunderstrike
+ \expandafter\let\expandafter\normaltextunderstrike\csname\v!understrike\endcsname
+ \unexpanded\def\understrike{\mathortext\normalmathunderstrike\normaltextunderstrike}
+\else
+ \expandafter\let\expandafter\understrike\csname\v!understrike\endcsname
+\fi
+
+\ifdefined\normalmathoverstrike
+ \expandafter\let\expandafter\normaltextoverstrike\csname\v!overstrike\endcsname
+ \unexpanded\def\overstrike{\mathortext\normalmathoverstrike \normaltextoverstrike}
+\else
+ \expandafter\let\expandafter\overstrike\csname\v!overstrike\endcsname
+\fi
+
+\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname
+\expandafter\let\expandafter\underbars \csname\v!underbars \endcsname
+\expandafter\let\expandafter\overbars \csname\v!overbars \endcsname
+
+\unexpanded\def\setupunderbar[#1]% too incompatible for the moment
+ {}
+
+%D An experimental new feature:
+%D
+%D \startbuffer
+%D test {\red\underrandoms{test me}} and \underrandom{test} or \underrandom{grep} \blank
+%D test {\red\underdashes {test me}} and \underdash {test} or \underdash {grep} \blank
+%D test {\red\underdots {test me}} and \underdot {test} or \underdot {grep} \blank
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\startuseMPgraphic{rules:under:random}
+ draw
+ ((0,RuleDepth) ... (RuleWidth,RuleDepth)) randomized (4*RuleThickness)
+ shifted (0,RuleFactor*RuleOffset)
+ withpen pencircle scaled RuleThickness
+ withcolor RuleColor ;
+ setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
+\stopuseMPgraphic
+
+\startuseMPgraphic{rules:under:dash}
+ draw
+ ((0,RuleDepth) ... (RuleWidth,RuleDepth))
+ shifted (0,RuleFactor*RuleOffset)
+ dashed dashpattern(on RuleFactor/2 off RuleFactor/2)
+ withpen pencircle scaled RuleThickness
+ withcolor RuleColor ;
+ setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
+\stopuseMPgraphic
+
+\startuseMPgraphic{rules:under:dots}
+ draw
+ ((0,RuleDepth) ... (RuleWidth,RuleDepth))
+ shifted (0,RuleFactor*RuleOffset)
+ dashed dashpattern(off 3/RuleFactor on 0 off 3/RuleFactor)
+ withpen pencircle scaled 2RuleThickness
+ withcolor RuleColor ;
+ setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
+\stopuseMPgraphic
+
+\definebar
+ [undergraphic]
+ [\c!mp=rules:under:dash,
+ \c!offset=-.2,
+ \c!order=\v!background]
+
+\definebar[underrandom] [undergraphic][\c!mp=rules:under:random]
+\definebar[underrandoms][underrandom] [\c!continue=\v!yes]
+
+\definebar[underdash] [undergraphic][\c!mp=rules:under:dash]
+\definebar[underdashes] [underdash] [\c!continue=\v!yes]
+
+\definebar[underdot] [undergraphic][\c!mp=rules:under:dots]
+\definebar[underdots] [underdot] [\c!continue=\v!yes]
+
+%D This will move: (a bit duplicated)
+
+\installcorenamespace{shift}
+\installcorenamespace{shiftindex}
+\installcorenamespace{shiftattribute}
+
+\installcommandhandler \??shift {shift} \??shift
+
+\newtoks\t_node_shifts_checklist
+
+\let\c_node_shifts_index\relax % temporary synonym
+
+\let\setupshifts\setupshift
+
+\appendtoks
+ \ifsecondargument
+ \node_shifts_define
+ \else
+ \the\t_node_shifts_checklist
+ \fi
+\to \everysetupshift
+
+\appendtoks
+ \ifcsname\??shiftindex\currentshift\endcsname
+ \lastnamedcs\zerocount
+ \else
+ \expandafter\newcount\csname\??shiftindex\currentshift\endcsname
+ \fi
+ \normalexpanded{\t_node_shifts_checklist{\node_shifts_redefine{\currentshift}\the\t_node_shifts_checklist}}%
+ \node_shifts_define
+ \setuevalue\currentshift{\node_shifts_direct{\currentshift}}%
+\to \everydefineshift
+
+\unexpanded\def\node_shifts_define
+ {\setevalue{\??shiftattribute\currentshift}{\number
+ \clf_defineshift
+ continue {\shiftparameter\c!continue}%
+ unit {\shiftparameter\c!unit}%
+ method \shiftparameter\c!method
+ dy \shiftparameter\c!dy % number
+ \relax}}
+
+\unexpanded\def\node_shifts_redefine#1%
+ {\def\currentshift{#1}\node_shifts_define}
+
+% \unexpanded\def\node_shifts_set
+% {\clf_enableshifts
+% \glet\node_shifts_set\node_shifts_set_indeed
+% \node_shifts_set}
+%
+% \def\node_shifts_set_indeed#1% todo: check parent !
+
+\unexpanded\def\node_shifts_set#1% todo: check parent ! todo: move attr etc to lua
+ {\def\currentshift{#1}%
+ \expandafter\let\expandafter\c_node_shifts_index\csname\??shiftindex#1\endcsname
+ \advance\c_node_shifts_index\plusone
+ \attribute\shiftedattribute\numexpr
+ \plusthousand*\c_node_shifts_index
+ +\csname\??shiftattribute#1\ifcsname\??shift#1:\number\c_node_shifts_index\s!parent\endcsname:\number\c_node_shifts_index\fi\endcsname
+ \relax
+ \useshiftstyleandcolor\c!style\c!color
+ \dosetupisolatedalign{\shiftparameter\c!align}}
+
+\unexpanded\def\startshift[#1]%
+ {\begingroup
+ \node_shifts_set{#1}}
+
+\unexpanded\def\stopshift
+ {\endgroup}
+
+% \unexpanded\def\node_shifts_direct#1%
+% {\doisolatedgroupedalign{\node_shifts_set{#1}}\donothing}
+
+\unexpanded\def\node_shifts_direct#1%
+ {\groupedcommand
+ {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}}
+ {\endgroup\dostopisolation\endgroup}}
+
+\setupshifts
+ [\c!method=0,
+ \c!continue=\v!no,
+ \c!dy=0,
+ \c!unit=ex,
+ \c!align=,
+ \c!style=,
+ \c!color=]
+
+\defineshift [\v!shiftup] [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
+\defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
+
+% we want these always so ...
+
+\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname
+\expandafter\let\expandafter\shiftdown \csname\v!shiftdown \endcsname
+
+% This is a weird helper:
+
+\unexpanded\def\dostartisolation{\signalcharacter}
+\unexpanded\def\dostopisolation {\signalcharacter}
+\unexpanded\def\doisolator {\signalcharacter}
+
+\unexpanded\def\dosetupisolatedalign#1%
+ {\doisolator
+ \setupalign[#1]\relax}
+
+\unexpanded\def\doisolatedgroupedalign#1#2%
+ {\groupedcommand
+ {\begingroup\dostartisolation\begingroup#1}
+ {#2\endgroup\dostopisolation\endgroup}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua
new file mode 100644
index 00000000000..2ad1242c533
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua
@@ -0,0 +1,342 @@
+if not modules then modules = { } end modules ['node-ser'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- 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 concat, tohash, sortedkeys, printtable = table.concat, table.tohash, table.sortedkeys, table.print
+local formatters, format, rep = string.formatters, string.format, string.rep
+
+local allocate = utilities.storage.allocate
+
+local context = context
+local nodes = nodes
+local node = node
+
+local traverse = nodes.traverse
+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 hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+----- utfchar = utf.char
+local f_char = formatters["%U"]
+----- fontchars = { } table.setmetatableindex(fontchars,function(t,k) fontchars = fonts.hashes.characters return fontchars[k] end)
+
+----- f_char = utilities.strings.chkuni -- formatters["%!chkuni!"]
+
+local expand = allocate ( tohash {
+ -- text:
+ "list", -- list_ptr & ins_ptr & adjust_ptr
+ "pre", --
+ "post", --
+ "top_skip", --
+ "attr", --
+ "replace", -- nobreak
+ "components", -- lig_ptr
+ "box_left", --
+ "box_right", --
+ "glyph", -- margin_char
+ "leader", -- leader_ptr
+ "action", -- action_ptr
+ "value", -- user_defined nodes with subtype 'a' en 'n'
+ "head",
+ -- math:
+ "nucleus",
+ "sup",
+ "sub",
+ "list",
+ "num",
+ "denom",
+ "left",
+ "right",
+ "display",
+ "text",
+ "script",
+ "scriptscript",
+ "delim",
+ "degree",
+ "accent",
+ "bot_accent",
+} )
+
+-- page_insert: "height", "last_ins_ptr", "best_ins_ptr"
+-- split_insert: "height", "last_ins_ptr", "best_ins_ptr", "broken_ptr", "broken_ins"
+
+local ignore = allocate ( tohash {
+ "page_insert",
+ "split_insert",
+ "ref_count",
+} )
+
+local dimension = allocate ( tohash {
+ "width", "height", "depth", "shift",
+ "stretch", "shrink",
+ "xoffset", "yoffset",
+ "surround",
+ "kern",
+ "box_left_width", "box_right_width"
+} )
+
+-- flat: don't use next, but indexes
+-- verbose: also add type
+-- can be sped up
+
+nodes.dimensionfields = dimension
+nodes.listablefields = expand
+nodes.ignorablefields = ignore
+
+-- not ok yet:
+
+local function astable(n,sparse) -- not yet ok, might get obsolete anyway
+ n = tonode(n)
+ local f, t = getfields(n), { }
+ for i=1,#f do
+ local v = f[i]
+ local d = n[v]
+ if d then
+ if ignore[v] or v == "id" then
+ -- skip
+ elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" or type(n[v]) ~= "table"
+ t[v] = "pointer to list"
+ elseif sparse then
+ if (type(d) == "number" and d ~= 0) or (type(d) == "string" and d ~= "") then
+ t[v] = d
+ end
+ else
+ t[v] = d
+ end
+ end
+ end
+ t.type = nodecodes[n.id]
+ return t
+end
+
+nodes.astable = astable
+
+setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end)
+
+-- under construction:
+
+local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true
+ local function to_table(n,flat,verbose,noattributes) -- no need to pass
+ local f = getfields(n)
+ local tt = { }
+ for k=1,#f do
+ local v = f[k]
+ local nv = v and n[v]
+ if nv then
+ if ignore[v] then
+ -- skip
+ elseif noattributes and v == "attr" then
+ -- skip
+ elseif expand[v] then
+ if type(nv) == "number" or type(nv) == "string" then
+ tt[v] = nv
+ else
+ tt[v] = totable(nv,flat,verbose,noattributes)
+ end
+ elseif type(nv) == "table" then
+ tt[v] = nv -- totable(nv,flat,verbose) -- data
+ else
+ tt[v] = nv
+ end
+ end
+ end
+ if verbose then
+ local subtype = tt.subtype
+ local id = tt.id
+ local nodename = nodecodes[id]
+ tt.id = nodename
+ local subtypes = subtcodes[nodename]
+ if subtypes then
+ tt.subtype = subtypes[subtype]
+ elseif subtype == 0 then
+ tt.subtype = nil
+ else
+ -- we need a table
+ end
+ if tt.char then
+ tt.char = f_char(tt.char)
+ end
+ if tt.small_char then
+ tt.small_char = f_char(tt.small_char)
+ end
+ if tt.large_char then
+ tt.large_char = f_char(tt.large_char)
+ end
+ end
+ return tt
+ end
+ if n then
+ if flat then
+ local t, tn = { }, 0
+ while n do
+ tn = tn + 1
+ local nt = to_table(n,flat,verbose,noattributes)
+ t[tn] = nt
+ nt.next = nil
+ nt.prev = nil
+ n = n.next
+ end
+ return t
+ else
+ local t = to_table(n,flat,verbose,noattributes)
+ local n = n.next
+ if n then
+ t.next = totable(n,flat,verbose,noattributes)
+ end
+ return t
+ end
+ else
+ return { }
+ end
+end
+
+nodes.totable = function(n,...) return totable(tonode(n),...) end
+nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list
+
+local function key(k)
+ return ((type(k) == "number") and "["..k.."]") or k
+end
+
+-- not ok yet; this will become a module
+
+-- todo: adapt to nodecodes etc .. use formatters
+
+local function serialize(root,name,handle,depth,m,noattributes)
+ handle = handle or print
+ if depth then
+ depth = depth .. " "
+ handle(format("%s%s={",depth,key(name)))
+ else
+ depth = ""
+ local tname = type(name)
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
+ else
+ handle(name .. "={")
+ end
+ elseif tname == "number" then
+ handle("[" .. name .. "]={")
+ else
+ handle("t={")
+ end
+ end
+ if root then
+ local fld
+ if root.id then
+ fld = getfields(root) -- we can cache these (todo)
+ else
+ fld = sortedkeys(root)
+ end
+ if type(root) == 'table' and root['type'] then -- userdata or table
+ handle(format("%s type=%q,",depth,root['type']))
+ end
+ for f=1,#fld do
+ local k = fld[f]
+ if k == "ref_count" then
+ -- skip
+ elseif noattributes and k == "attr" then
+ -- skip
+ elseif k == "id" then
+ local v = root[k]
+ handle(format("%s id=%s,",depth,nodecodes[v] or noadcodes[v] or v))
+ elseif k then
+ local v = root[k]
+ local t = type(v)
+ if t == "number" then
+ if v == 0 then
+ -- skip
+ else
+ handle(format("%s %s=%s,",depth,key(k),v))
+ end
+ elseif t == "string" then
+ if v == "" then
+ -- skip
+ else
+ handle(format("%s %s=%q,",depth,key(k),v))
+ end
+ elseif t == "boolean" then
+ handle(format("%s %s=%q,",depth,key(k),tostring(v)))
+ elseif v then -- userdata or table
+ serialize(v,k,handle,depth,m+1,noattributes)
+ end
+ end
+ end
+ if root['next'] then -- userdata or table
+ serialize(root['next'],'next',handle,depth,m+1,noattributes)
+ end
+ end
+ if m and m > 0 then
+ handle(format("%s},",depth))
+ else
+ handle(format("%s}",depth))
+ end
+end
+
+function nodes.serialize(root,name,noattributes)
+ local t, n = { }, 0
+ local function flush(s)
+ n = n + 1
+ t[n] = s
+ end
+ serialize(tonode(root),name,flush,nil,0,noattributes)
+ return concat(t,"\n")
+end
+
+function nodes.serializebox(n,flat,verbose,name)
+ return nodes.serialize(nodes.totable(tex.box[n],flat,verbose),name)
+end
+
+function nodes.visualizebox(...) -- to be checked .. will move to module anyway
+ context.starttyping()
+ context.pushcatcodes("verbatim")
+ context(nodes.serializebox(...))
+ context.stoptyping()
+ context.popcatcodes()
+end
+
+function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway
+ head = tonode(head)
+ if not n then
+ context.starttyping(true)
+ end
+ while head do
+ local id = head.id
+ context(rep(" ",n or 0) .. tostring(head) .. "\n")
+ if id == hlist_code or id == vlist_code then
+ nodes.list(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+ if not n then
+ context.stoptyping(true)
+ end
+end
+
+function nodes.print(head,n)
+ head = tonode(head)
+ while head do
+ local id = head.id
+ logs.writer(string.formatters["%w%S"],n or 0,head)
+ if id == hlist_code or id == vlist_code then
+ nodes.print(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua b/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua
new file mode 100644
index 00000000000..2f2af490566
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua
@@ -0,0 +1,241 @@
+if not modules then modules = { } end modules ['node-shp'] = {
+ 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 nodes, node = nodes, node
+
+local next, type = next, type
+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 tasks = nodes.tasks
+local handlers = nodes.handlers
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local disc_code = nodecodes.disc
+local mark_code = nodecodes.mark
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local whatsit_code = nodecodes.whatsit
+
+local fulldisc_code = disccodes.discretionary
+
+local texgetbox = tex.getbox
+
+local implement = interfaces.implement
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local free_node = nuts.free
+local remove_node = nuts.remove
+local traverse_nodes = nuts.traverse
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local setsetlink = nuts.setlink
+local setsetprev = nuts.setprev
+local setsetnext = 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 removables = {
+ [whatsitcodes.open] = true,
+ [whatsitcodes.close] = true,
+ [whatsitcodes.write] = true,
+ [whatsitcodes.savepos] = true,
+ [whatsitcodes.latelua] = true,
+ [whatsitcodes.pdfdest] = true,
+}
+
+-- About 10% of the nodes make no sense for the backend. By (at least)
+-- removing the replace disc nodes, we can omit extensive checking in
+-- the finalizer code (e.g. colors in disc nodes). Removing more nodes
+-- (like marks) is not saving much and removing empty boxes is even
+-- dangerous because we can rely on dimensions (e.g. in references).
+
+local wipedisc = false -- we can use them in the export ... can be option
+
+local function cleanup_redundant(head) -- better name is: flatten_page
+ local start = head
+ while start do
+ local id = getid(start)
+ if id == disc_code then
+ if getsubtype(start) == fulldisc_code then
+ local _, _, replace, _, _ tail = getdisc(start,true)
+ if replace then
+ local prev, next = getboth(start)
+ setfield(start,"replace",nil)
+ if start == head then
+ remove_node(head,start,true)
+ head = replace
+ else
+ remove_node(head,start,true)
+ end
+ if next then
+ setlink(tail,next)
+ end
+ if prev then
+ setlink(prev,replace)
+ else
+ setprev(replace) -- to be sure
+ end
+ start = next
+ elseif wipedisc then
+ -- pre and post can have values
+ head, start = remove_node(head,start,true)
+ else
+ start = getnext(start)
+ end
+ else
+ start = getnext(start)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local sl = getlist(start)
+ if sl then
+ local rl = cleanup_redundant(sl)
+ if rl ~= sl then
+ setlist(start,rl)
+ end
+ end
+ start = getnext(start)
+ else
+ start = getnext(start)
+ end
+ end
+ return head
+end
+
+local function cleanup_flushed(head) -- rough
+ local start = head
+ while start do
+ local id = getid(start)
+ if id == whatsit_code then
+ if removables[getsubtype(start)] then
+ head, start = remove_node(head,start,true)
+ else
+ start = getnext(start)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local sl = getlist(start)
+ if sl then
+ local rl = cleanup_flushed(sl)
+ if rl ~= sl then
+ setlist(start,rl)
+ end
+ end
+ start = getnext(start)
+ else
+ start = getnext(start)
+ end
+ end
+ 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
+end
+
+local actions = tasks.actions("shipouts") -- no extra arguments
+
+function handlers.finalize(head) -- problem, attr loaded before node, todo ...
+ return actions(head)
+end
+
+-- handlers.finalize = actions
+
+-- interface
+
+implement { name = "cleanupbox", actions = { texgetbox, cleanup_flushed }, arguments = "integer" }
+implement { name = "finalizebox", actions = { texgetbox, actions }, arguments = "integer" }
+
+-- just in case we want to optimize lookups:
+
+local frequencies = { }
+
+nodes.tracers.frequencies = frequencies
+
+local data = { }
+local done = false
+
+setmetatableindex(data,function(t,k)
+ local v = { }
+ setmetatableindex(v,function(t,k)
+ local v = { }
+ t[k] = v
+ setmetatableindex(v,function(t,k)
+ t[k] = 0
+ return 0
+ end)
+ return v
+ end)
+ t[k] = v
+ return v
+end)
+
+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)
+ 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
+ count(getlist(n),data,subcategory)
+ end
+ end
+end
+
+local function register(category,subcategory)
+ return function(head)
+ done = true
+ count(head,data[category],subcategory)
+ return head, false
+ end
+end
+
+frequencies.register = register
+frequencies.filename = nil
+
+trackers.register("nodes.frequencies",function(v)
+ if type(v) == "string" then
+ frequencies.filename = v
+ end
+ handlers.frequencies_shipouts_before = register("shipouts", "begin")
+ handlers.frequencies_shipouts_after = register("shipouts", "end")
+ handlers.frequencies_processors_before = register("processors", "begin")
+ handlers.frequencies_processors_after = register("processors", "end")
+ tasks.prependaction("shipouts", "before", "nodes.handlers.frequencies_shipouts_before")
+ tasks.appendaction ("shipouts", "after", "nodes.handlers.frequencies_shipouts_after")
+ tasks.prependaction("processors", "before", "nodes.handlers.frequencies_processors_before")
+ tasks.appendaction ("processors", "after", "nodes.handlers.frequencies_processors_after")
+end)
+
+statistics.register("node frequencies", function()
+ if done then
+ local filename = frequencies.filename or (tex.jobname .. "-frequencies.lua")
+ io.savedata(filename,table.serialize(data,true))
+ return format("saved in %q",filename)
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-snp.lua b/Master/texmf-dist/tex/context/base/mkiv/node-snp.lua
new file mode 100644
index 00000000000..31c7771ac92
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-snp.lua
@@ -0,0 +1,66 @@
+if not modules then modules = { } end modules ['node-snp'] = {
+ 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"
+}
+
+if not nodes then
+ nodes = { } -- also loaded in mtx-timing
+end
+
+local snapshots = { }
+nodes.snapshots = snapshots
+
+local nodeusage = nodes.pool and nodes.pool.usage
+local clock = os.gettimeofday or os.clock -- should go in environment
+local lasttime = clock()
+local samples = { }
+
+local parameters = {
+ "cs_count",
+ "dyn_used",
+ "elapsed_time",
+ "luabytecode_bytes",
+ "luastate_bytes",
+ "max_buf_stack",
+ "obj_ptr",
+ "pdf_mem_ptr",
+ "pdf_mem_size",
+ "pdf_os_cntr",
+-- "pool_ptr", -- obsolete
+ "str_ptr",
+}
+
+function snapshots.takesample(comment)
+ if nodeusage then
+ local c = clock()
+ local t = {
+ elapsed_time = c - lasttime,
+ node_memory = nodeusage(),
+ comment = comment,
+ }
+ for i=1,#parameters do
+ local parameter = parameters[i]
+ local ps = status[parameter]
+ if ps then
+ t[parameter] = ps
+ end
+ end
+ samples[#samples+1] = t
+ lasttime = c
+ end
+end
+
+function snapshots.getsamples()
+ return samples -- one return value !
+end
+
+function snapshots.resetsamples()
+ samples = { }
+end
+
+function snapshots.getparameters()
+ return parameters
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua
new file mode 100644
index 00000000000..c9d3091df23
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua
@@ -0,0 +1,40 @@
+if not modules then modules = { } end modules ['node-tex'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+builders = builders or { }
+local kernel = builders.kernel or { }
+builders.kernel = kernel
+
+local hyphenate = lang.hyphenate
+local ligaturing = node.ligaturing
+local kerning = node.kerning
+
+kernel.originals = {
+ hyphenate = hyphenate,
+ ligaturing = ligaturing,
+ kerning = kerning,
+}
+
+function kernel.hyphenation(head)
+ local done = hyphenate(head)
+ return head, done
+end
+
+function kernel.ligaturing(head)
+ local head, tail, done = ligaturing(head) -- we return 3 values indeed
+ return head, done
+end
+
+function kernel.kerning(head)
+ local head, tail, done = kerning(head) -- we return 3 values indeed
+ return head, done
+end
+
+callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere")
+callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere")
+callbacks.register('kerning' , false, "normal kerning routine, called elsewhere")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua
new file mode 100644
index 00000000000..d184620ef2e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua
@@ -0,0 +1,687 @@
+if not modules then modules = { } end modules ['node-tra'] = {
+ 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"
+}
+
+--[[ldx--
+<p>This is rather experimental. We need more control and some of this
+might become a runtime module instead. This module will be cleaned up!</p>
+--ldx]]--
+
+local utfchar = utf.char
+local format, match, gmatch, concat, rep = string.format, string.match, string.gmatch, table.concat, string.rep
+local lpegmatch = lpeg.match
+local clock = os.gettimeofday or os.clock -- should go in environment
+
+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 getfield = nuts.getfield
+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 isglyph = nuts.isglyph
+
+local flush_list = nuts.flush_list
+local count_nodes = nuts.count
+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 gluespec_code = nodecodes.gluespec
+
+local dimenfactors = number.dimenfactors
+local fillorders = nodes.fillcodes
+local formatters = string.formatters
+
+-- this will be reorganized:
+
+function nodes.showlist(head, message)
+ if message then
+ report_nodes(message)
+ end
+ for n in traverse_nodes(tonut(head)) do
+ report_nodes(d_tostring(n))
+ end
+end
+
+function nodes.handlers.checkglyphs(head,message)
+ local h = tonut(head)
+ local t = { }
+ for g in traverse_by_id(glyph_code,h) do
+ t[#t+1] = formatters["%U:%s"](getchar(g),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
+ end
+ return false
+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)])
+ l[s] = (l[s] or 0) + 1
+ end
+ flush_list(q)
+ for k, v in next, l do
+ report_nodes("%s * %s",v,k)
+ end
+end
+
+local f_sequence = formatters["U+%04X:%s"]
+
+local function tosequence(start,stop,compact)
+ if start then
+ start = tonut(start)
+ stop = stop and tonut(stop)
+ local t = { }
+ while start do
+ local c, id = isglyph(start)
+ if c then
+ if compact then
+ local components = getfield(start,"components")
+ if components then
+ t[#t+1] = tosequence(components,nil,compact)
+ else
+ t[#t+1] = utfchar(c)
+ end
+ else
+ t[#t+1] = f_sequence(c,utfchar(c))
+ end
+ 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] = "[" .. getfield(start,"dir") .. "]"
+ elseif compact then
+ t[#t+1] = "[]"
+ else
+ t[#t+1] = nodecodes[id]
+ end
+ if start == stop then
+ break
+ else
+ start = getnext(start)
+ end
+ end
+ if compact then
+ return concat(t)
+ else
+ return concat(t," ")
+ end
+ else
+ return "[empty]"
+ end
+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)))
+end
+
+function nodes.packlist(head)
+ local t = { }
+ for n in traverse_nodes(tonut(head)) do
+ t[#t+1] = d_tostring(n)
+ end
+ return t
+end
+
+function nodes.idstostring(head,tail)
+ head = tonut(head)
+ tail = tail and tonut(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)
+ if id == whatsit_code then
+ id = whatcodes[getsubtype(n)]
+ else
+ id = nodecodes[id]
+ end
+ if not last_id then
+ last_id = id
+ last_n = 1
+ elseif last_id == id then
+ last_n = last_n + 1
+ else
+ if last_n > 1 then
+ t[#t+1] = formatters["[%s*%s]"](last_n,last_id)
+ else
+ t[#t+1] = formatters["[%s]"](last_id)
+ end
+ last_id = id
+ last_n = 1
+ end
+ if n == tail then
+ break
+ end
+ end
+ if not last_id then
+ t[#t+1] = "no nodes"
+ else
+ if last_n > 1 then
+ t[#t+1] = formatters["[%s*%s]"](last_n,last_id)
+ else
+ t[#t+1] = formatters["[%s]"](last_id)
+ end
+ end
+ return concat(t," ")
+end
+
+-- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks
+-- head = tonut(head)
+-- tail = tonut(tail)
+-- local n = head
+-- while n.next do
+-- n = n.next
+-- end
+-- local t, last_id, last_n = { }, nil, 0
+-- while n do
+-- local id = n.id
+-- if not last_id then
+-- last_id, last_n = id, 1
+-- elseif last_id == id then
+-- last_n = last_n + 1
+-- else
+-- if last_n > 1 then
+-- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+-- else
+-- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+-- end
+-- last_id, last_n = id, 1
+-- end
+-- if n == head then
+-- break
+-- end
+-- n = getprev(n)
+-- end
+-- if not last_id then
+-- t[#t+1] = "no nodes"
+-- elseif last_n > 1 then
+-- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+-- else
+-- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+-- end
+-- return table.concat(table.reversed(t)," ")
+-- end
+
+local function showsimplelist(h,depth,n)
+ h = h and tonut(h)
+ while h do
+ report_nodes("% w%s",n,d_tostring(h))
+ if not depth or n < depth then
+ local id = getid(h)
+ if id == hlist_code or id == vlist_code then
+ showsimplelist(getlist(h),depth,n+1)
+ end
+ end
+ h = getnext(h)
+ end
+end
+
+-- \startluacode
+-- callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end)
+-- \stopluacode
+-- \vbox{b\footnote{n}a}
+-- \startluacode
+-- callback.register('buildpage_filter',nil)
+-- \stopluacode
+
+nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
+
+local function listtoutf(h,joiner,textonly,last,nodisc)
+ local w = { }
+ while h do
+ local c, id = isglyph(h)
+ if c then
+ w[#w+1] = c >= 0 and utfchar(c) or formatters["<%i>"](c)
+ if joiner then
+ w[#w+1] = joiner
+ end
+ elseif id == disc_code then
+ local pre, pos, rep = getdisc(h)
+ if not nodisc then
+ w[#w+1] = formatters["[%s|%s|%s]"] (
+ pre and listtoutf(pre,joiner,textonly) or "",
+ pos and listtoutf(pos,joiner,textonly) or "",
+ rep and listtoutf(rep,joiner,textonly) or ""
+ )
+ elseif rep then
+ w[#w+1] = listtoutf(rep,joiner,textonly) or ""
+ end
+ elseif textonly then
+ if id == glue_code then
+ if getfield(h,"width") > 0 then
+ w[#w+1] = " "
+ end
+ elseif id == hlist_code or id == vlist_code then
+ w[#w+1] = "[]"
+ end
+ else
+ w[#w+1] = "[-]"
+ end
+ if h == last then
+ break
+ else
+ h = getnext(h)
+ end
+ end
+ return concat(w)
+end
+
+function nodes.listtoutf(h,joiner,textonly,last,nodisc)
+ if h then
+ local joiner = joiner == true and utfchar(0x200C) or joiner -- zwnj
+ return listtoutf(tonut(h),joiner,textonly,last and tonut(last),nodisc)
+ else
+ return ""
+ end
+end
+
+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)
+ if id == hlist_code or id == vlist_code then
+ local s = getsubtype(n)
+ report_nodes(rep(symbol,depth) .. what[s] or s)
+ showboxes(getlist(n),symbol,depth+1)
+ end
+ end
+end
+
+nodes.showboxes = showboxes
+
+local ptfactor = dimenfactors.pt
+local bpfactor = dimenfactors.bp
+local stripper = lpeg.patterns.stripzeros
+
+local f_f_f = formatters["%0.5Fpt plus %0.5F%s minus %0.5F%s"]
+local f_f_m = formatters["%0.5Fpt plus %0.5F%s minus %0.5Fpt"]
+local f_p_f = formatters["%0.5Fpt plus %0.5Fpt minus %0.5F%s"]
+local f_p_m = formatters["%0.5Fpt plus %0.5Fpt minus %0.5Fpt"]
+local f_f_z = formatters["%0.5Fpt plus %0.5F%s"]
+local f_p_z = formatters["%0.5Fpt plus %0.5Fpt"]
+local f_z_f = formatters["%0.5Fpt minus %0.5F%s"]
+local f_z_m = formatters["%0.5Fpt minus %0.5Fpt"]
+local f_z_z = formatters["%0.5Fpt"]
+
+local tonut = nodes.tonut
+local getfield = nodes.nuts.getfield
+
+local function nodetodimen(n)
+ n = tonut(n)
+ local id = getid(n)
+ if id == kern_code then
+ local width = getfield(n,"width")
+ if width == 0 then
+ return "0pt"
+ else
+ return f_z_z(width)
+ end
+ elseif id ~= glue_code then
+ return "0pt"
+ end
+ local stretch_order = getfield(n,"stretch_order")
+ local shrink_order = getfield(n,"shrink_order")
+ local stretch = getfield(n,"stretch") / 65536
+ local shrink = getfield(n,"shrink") / 65536
+ local width = getfield(n,"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])
+ elseif shrink ~= 0 then
+ return f_f_m(width,stretch,fillorders[stretch_order],shrink)
+ else
+ return f_f_z(width,stretch,fillorders[stretch_order])
+ end
+ elseif shrink_order ~= 0 then
+ if stretch ~= 0 then
+ return f_p_f(width,stretch,shrink,fillorders[shrink_order])
+ else
+ return f_z_f(width,shrink,fillorders[shrink_order])
+ end
+ elseif stretch ~= 0 then
+ if shrink ~= 0 then
+ return f_p_m(width,stretch,shrink)
+ else
+ return f_p_z(width,stretch)
+ end
+ elseif shrink ~= 0 then
+ return f_z_m(width,shrink)
+ elseif width == 0 then
+ return "0pt"
+ else
+ return f_z_z(width)
+ end
+end
+
+
+-- number.todimen(123)
+-- number.todimen(123,"cm")
+-- number.todimen(123,false,"%F))
+
+local f_pt = formatters["%p"]
+local f_un = formatters["%F%s"]
+
+dimenfactors[""] = dimenfactors.pt
+
+local function numbertodimen(d,unit,fmt)
+ if not d or d == 0 then
+ if not unit or unit == "pt" then
+ return "0pt"
+ elseif fmt then
+ return formatters[fmt](0,unit)
+ else
+ return 0 .. unit
+ end
+ elseif fmt then
+ if not unit then
+ unit = "pt"
+ end
+ return formatters[fmt](d*dimenfactors[unit],unit)
+ elseif not unit or unit == "pt" then
+ return f_pt(d)
+ else
+ return f_un(d*dimenfactors[unit],unit)
+ end
+end
+
+number.todimen = numbertodimen
+nodes .todimen = nodetodimen
+
+function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end
+function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end
+function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
+function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
+function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
+function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
+function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
+function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
+function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
+function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
+
+function nodes.topoints (n,fmt) return nodetodimen(n,"pt",fmt) end
+function nodes.toinches (n,fmt) return nodetodimen(n,"in",fmt) end
+function nodes.tocentimeters (n,fmt) return nodetodimen(n,"cm",fmt) end
+function nodes.tomillimeters (n,fmt) return nodetodimen(n,"mm",fmt) end
+function nodes.toscaledpoints(n,fmt) return nodetodimen(n,"sp",fmt) end
+function nodes.toscaledpoints(n) return n .. "sp" end
+function nodes.tobasepoints (n,fmt) return nodetodimen(n,"bp",fmt) end
+function nodes.topicas (n,fmt) return nodetodimen(n "pc",fmt) end
+function nodes.todidots (n,fmt) return nodetodimen(n,"dd",fmt) end
+function nodes.tociceros (n,fmt) return nodetodimen(n,"cc",fmt) end
+function nodes.tonewdidots (n,fmt) return nodetodimen(n,"nd",fmt) end
+function nodes.tonewciceros (n,fmt) return nodetodimen(n,"nc",fmt) end
+
+-- stop redefinition
+
+local points = function(n)
+ if not n or n == 0 then
+ return "0pt"
+ elseif type(n) == "number" then
+ return lpegmatch(stripper,format("%.5fpt",n*ptfactor)) -- faster than formatter
+ else
+ return numbertodimen(n,"pt") -- also deals with nodes
+ end
+end
+
+local basepoints = function(n)
+ if not n or n == 0 then
+ return "0bp"
+ elseif type(n) == "number" then
+ return lpegmatch(stripper,format("%.5fbp",n*bpfactor)) -- faster than formatter
+ else
+ return numbertodimen(n,"bp") -- also deals with nodes
+ end
+end
+
+local pts = function(n)
+ if not n or n == 0 then
+ return "0pt"
+ elseif type(n) == "number" then
+ return format("%.5fpt",n*ptfactor) -- faster than formatter
+ else
+ return numbertodimen(n,"pt") -- also deals with nodes
+ end
+end
+
+local nopts = function(n)
+ if not n or n == 0 then
+ return "0"
+ else
+ return format("%.5f",n*ptfactor) -- faster than formatter
+ end
+end
+
+number.points = points
+number.basepoints = basepoints
+number.pts = pts
+number.nopts = nopts
+
+nodes.points = function(n) return numbertodimen(n,"pt") end
+nodes.basepoints = function(n) return numbertodimen(n,"bp") end
+nodes.pts = function(n) return numbertodimen(n,"pt") end
+nodes.nopts = function(n) return format("%.5f",n*ptfactor) end
+
+local colors = { }
+tracers.colors = colors
+
+local unsetvalue = attributes.unsetvalue
+
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local m_color = attributes.list[a_color] or { }
+
+function colors.set(n,c,s)
+ local mc = m_color[c]
+ local nn = tonut(n)
+ if mc then
+ local mm = s or texgetattribute(a_colormodel)
+ setattr(nn,a_colormodel,mm <= 0 and mm or 1)
+ setattr(nn,a_color,mc)
+ else
+ setattr(nn,a_color,unsetvalue)
+ end
+ return n
+end
+
+function colors.setlist(n,c,s)
+ local nn = tonut(n)
+ local mc = m_color[c] or unsetvalue
+ local mm = s or texgetattribute(a_colormodel)
+ if mm <= 0 then
+ mm = 1
+ end
+ while nn do
+ setattr(nn,a_colormodel,mm)
+ setattr(nn,a_color,mc)
+ nn = getnext(nn)
+ end
+ return n
+end
+
+function colors.reset(n)
+ setattr(tonut(n),a_color,unsetvalue)
+ return n
+end
+
+-- maybe
+
+local transparencies = { }
+tracers.transparencies = transparencies
+
+local a_transparency = attributes.private('transparency')
+local m_transparency = attributes.list[a_transparency] or { }
+
+function transparencies.set(n,t)
+ setattr(tonut(n),a_transparency,m_transparency[t] or unsetvalue)
+ return n
+end
+
+function transparencies.setlist(n,c,s)
+ local nn = tonut(n)
+ local mt = m_transparency[c] or unsetvalue
+ while nn do
+ setattr(nn,a_transparency,mt)
+ nn = getnext(nn)
+ end
+ return n
+end
+
+function transparencies.reset(n)
+ setattr(n,a_transparency,unsetvalue)
+ return n
+end
+
+-- for the moment here
+
+local visualizers = nodes.visualizers or { }
+nodes.visualizers = visualizers
+
+function visualizers.handler(head)
+ return head, false
+end
+
+-- we could cache attribute lists and set attr (copy will increment count) .. todo ..
+-- although tracers are used seldom
+
+local function setproperties(n,c,s)
+ local nn = tonut(n)
+ local mm = texgetattribute(a_colormodel)
+ setattr(nn,a_colormodel,mm > 0 and mm or 1)
+ setattr(nn,a_color,m_color[c])
+ setattr(nn,a_transparency,m_transparency[c])
+ return n
+end
+
+tracers.setproperties = setproperties
+
+function tracers.setlist(n,c,s)
+ local nn = tonut(n)
+ local mc = m_color[c]
+ local mt = m_transparency[c]
+ local mm = texgetattribute(a_colormodel)
+ if mm <= 0 then
+ mm = 1
+ end
+ while nn do
+ setattr(nn,a_colormodel,mm)
+ setattr(nn,a_color,mc)
+ setattr(nn,a_transparency,mt)
+ nn = getnext(nn)
+ end
+ return n
+end
+
+function tracers.resetproperties(n)
+ local nn = tonut(n)
+ setattr(nn,a_color,unsetvalue)
+ setattr(nn,a_transparency,unsetvalue)
+ return n
+end
+
+-- this one returns a nut
+
+local nodestracerpool = { }
+local nutstracerpool = { }
+
+tracers.pool = {
+ nodes = nodestracerpool,
+ nuts = nutstracerpool,
+}
+
+table.setmetatableindex(nodestracerpool,function(t,k,v)
+ local f = nutstracerpool[k]
+ local v = function(...)
+ return tonode(f(...))
+ end
+ t[k] = v
+ return v
+end)
+
+function nutstracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup)
+ return setproperties(new_rule(w,h,d),c,s)
+end
+
+tracers.rule = nodestracerpool.rule -- for a while
+
+-- local function show(head,n,message)
+-- print("START",message or "")
+-- local i = 0
+-- for current in traverse(head) do
+-- local prev = getprev(current)
+-- local next = getnext(current)
+-- i = i + 1
+-- print(i, prev and nodecodes[getid(prev)],nodecodes[getid(current)],next and nodecodes[getid(next)])
+-- if i == n then
+-- break
+-- end
+-- end
+-- print("STOP", message or "")
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua
new file mode 100644
index 00000000000..56a4b18ef24
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua
@@ -0,0 +1,420 @@
+if not modules then modules = { } end modules ['node-tsk'] = {
+ 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"
+}
+
+-- This might move to task-* and become less code as in sequencers
+-- we already have dirty flags as well. On the other hand, nodes are
+-- rather specialized and here we focus on node related tasks.
+
+local format = string.format
+
+local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end)
+
+local report_tasks = logs.reporter("tasks")
+
+local allocate = utilities.storage.allocate
+
+local context = context
+local nodes = nodes
+
+local tasks = nodes.tasks or { }
+nodes.tasks = tasks
+
+local tasksdata = { } -- no longer public
+
+local sequencers = utilities.sequencers
+local compile = sequencers.compile
+local nodeprocessor = sequencers.nodeprocessor
+
+local frozengroups = "no"
+
+function tasks.freeze(kind)
+ frozengroups = kind or "tolerant" -- todo: hook into jobname
+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 = sequencers.new {
+ -- we can move more to the sequencer now .. todo
+ }
+ tasksdata[name] = {
+ list = tasklist,
+ runner = false,
+ arguments = arguments,
+ -- sequence = sequence,
+ frozen = { },
+ processor = specification.processor or nodeprocessor
+ }
+ for l=1,#sequence do
+ sequencers.appendgroup(tasklist,sequence[l])
+ end
+ end
+end
+
+local function valid(name)
+ local data = tasksdata[name]
+ if not data then
+ report_tasks("unknown task %a",name)
+ else
+ return data
+ end
+end
+
+local function validgroup(name,group,what)
+ local data = tasksdata[name]
+ if not data then
+ report_tasks("unknown task %a",name)
+ else
+ local frozen = data.frozen[group]
+ if frozen then
+ if frozengroup == "no" then
+ -- default
+ elseif frozengroup == "strict" then
+ report_tasks("warning: group %a of task %a is frozen, %a applied but not supported",group,name,what)
+ return
+ else -- if frozengroup == "tolerant" then
+ report_tasks("warning: group %a of task %a is frozen, %a ignored",group,name,what)
+ end
+ end
+ return data
+ end
+end
+
+function tasks.freezegroup(name,group)
+ local data = valid(name)
+ if data then
+ data.frozen[group] = true
+ end
+end
+
+function tasks.restart(name)
+ local data = valid(name)
+ if data then
+ data.runner = false
+ end
+end
+
+function tasks.enableaction(name,action)
+ local data = valid(name)
+ if data then
+ sequencers.enableaction(data.list,action)
+ data.runner = false
+ end
+end
+
+function tasks.disableaction(name,action)
+ local data = valid(name)
+ if data then
+ sequencers.disableaction(data.list,action)
+ data.runner = false
+ end
+end
+
+function tasks.replaceaction(name,group,oldaction,newaction)
+ local data = valid(name)
+ if data then
+ sequencers.replaceaction(data.list,group,oldaction,newaction)
+ data.runner = false
+ end
+end
+
+function tasks.setaction(name,action,value)
+ if value then
+ tasks.enableaction(name,action)
+ else
+ tasks.disableaction(name,action)
+ end
+end
+
+function tasks.enablegroup(name,group)
+ local data = validgroup(name,"enable group")
+ if data then
+ sequencers.enablegroup(data.list,group)
+ data.runner = false
+ end
+end
+
+function tasks.disablegroup(name,group)
+ local data = validgroup(name,"disable group")
+ if data then
+ sequencers.disablegroup(data.list,group)
+ data.runner = false
+ end
+end
+
+function tasks.appendaction(name,group,action,where,kind)
+ local data = validgroup(name,"append action")
+ if data then
+ sequencers.appendaction(data.list,group,action,where,kind)
+ data.runner = false
+ end
+end
+
+function tasks.prependaction(name,group,action,where,kind)
+ local data = validgroup(name,"prepend action")
+ if data then
+ sequencers.prependaction(data.list,group,action,where,kind)
+ data.runner = false
+ end
+end
+
+function tasks.removeaction(name,group,action)
+ local data = validgroup(name,"remove action")
+ if data then
+ sequencers.removeaction(data.list,group,action)
+ data.runner = false
+ end
+end
+
+function tasks.showactions(name,group,action,where,kind)
+ local data = valid(name)
+ if data then
+ report_tasks("task %a, list:\n%s",name,nodeprocessor(data.list))
+ end
+end
+
+-- Optimizing for the number of arguments makes sense, but getting rid of
+-- the nested call (no problem but then we also need to register the
+-- callback with this mechanism so that it gets updated) does not save
+-- much time (24K calls on mk.tex).
+
+local created, total = 0, 0
+
+statistics.register("node list callback tasks", function()
+ if total > 0 then
+ return format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasksdata),created,total)
+ else
+ return nil
+ end
+end)
+
+function tasks.actions(name) -- we optimize for the number or arguments (no ...)
+ 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,...)
+ end
+ end
+ else
+ return nil
+ end
+end
+
+function tasks.table(name) --maybe move this to task-deb.lua
+ local tsk = tasksdata[name]
+ local lst = tsk and tsk.list
+ local HL, NC, NR, bold, type = context.HL, context.NC, context.NR, context.bold, context.type
+ if lst then
+ local list, order = lst.list, lst.order
+ if list and order then
+ context.starttabulate { "|l|l|" }
+ NC() bold("category") NC() bold("function") NC() NR()
+ for i=1,#order do
+ HL()
+ local o = order[i]
+ local l = list[o]
+ if #l == 0 then
+ NC() type(o) NC() context("unset") NC() NR()
+ else
+ local done = false
+ for k, v in table.sortedhash(l) do
+ NC() if not done then type(o) done = true end NC() type(v) NC() NR()
+ end
+ end
+ end
+ context.stoptabulate()
+ end
+ end
+end
+
+-- this will move
+
+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
+ "normalizers",
+ "characters",
+ "words",
+ "fonts",
+ "lists",
+ "after", -- for users
+ }
+}
+
+tasks.new {
+ name = "finalizers",
+ arguments = 1,
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- for users
+ "normalizers",
+-- "characters",
+-- "finishers",
+ "fonts",
+ "lists",
+ "after", -- for users
+ }
+}
+
+tasks.new {
+ name = "shipouts",
+ arguments = 0,
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- for users
+ "normalizers",
+ "finishers",
+ "after", -- for users
+ }
+}
+
+tasks.new {
+ name = "mvlbuilders",
+ arguments = 1,
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- for users
+ "normalizers",
+ "after", -- for users
+ }
+}
+
+tasks.new {
+ name = "vboxbuilders",
+ arguments = 5,
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- for users
+ "normalizers",
+ "after", -- for users
+ }
+}
+
+-- tasks.new {
+-- name = "parbuilders",
+-- arguments = 1,
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before", -- for users
+-- "lists",
+-- "after", -- for users
+-- }
+-- }
+
+-- tasks.new {
+-- name = "pagebuilders",
+-- arguments = 5,
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before", -- for users
+-- "lists",
+-- "after", -- for users
+-- }
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua
new file mode 100644
index 00000000000..4832c048c89
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua
@@ -0,0 +1,136 @@
+if not modules then modules = { } end modules ['node-tst'] = {
+ 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 nodes, node = nodes, node
+
+local chardata = characters.data
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+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 nuts = nodes.nuts
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getchar = nuts.getchar
+local getsubtype = nuts.getsubtype
+
+local find_node_tail = nuts.tail
+
+function nuts.leftmarginwidth(n) -- todo: three values
+ while n do
+ local id = getid(n)
+ if id == glue_code then
+ return getsubtype(n) == leftskip_code and getfield(n,"width") or 0
+ elseif id == whatsit_code then
+ n = getnext(n)
+ elseif id == hlist_code then
+ return getfield(n,"width")
+ else
+ break
+ end
+ end
+ return 0
+end
+
+function nuts.rightmarginwidth(n)
+ if n then
+ n = find_node_tail(n)
+ while n do
+ local id = getid(n)
+ if id == glue_code then
+ return getsubtype(n) == rightskip_code and getfield(n,"width") or 0
+ elseif id == whatsit_code then
+ n = getprev(n)
+ else
+ break
+ end
+ end
+ end
+ return false
+end
+
+function nuts.somespace(n,all)
+ if n then
+ local id = getid(n)
+ if id == glue_code then
+ return (all or ((getfield(n,"width") or 0) ~= 0)) and glue_code -- temp: or 0
+ -- return (all or (getfield(n,"width") ~= 0)) and glue_code
+ elseif id == kern_code then
+ return (all or (getfield(n,"kern") ~= 0)) and kern
+ elseif id == glyph_code then
+ local category = chardata[getchar(n)].category
+ -- maybe more category checks are needed
+ return (category == "zs") and glyph_code
+ end
+ end
+ return false
+end
+
+function nuts.somepenalty(n,value)
+ if n then
+ local id = getid(n)
+ if id == penalty_code then
+ if value then
+ return getfield(n,"penalty") == value
+ else
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function nuts.is_display_math(head)
+ local n = getprev(head)
+ while n do
+ local id = getid(n)
+ if id == penalty_code then
+ elseif id == glue_code then
+ if getsubtype(n) == abovedisplayshortskip_code then
+ return true
+ end
+ else
+ break
+ end
+ n = getprev(n)
+ end
+ n = getnext(head)
+ while n do
+ local id = getid(n)
+ if id == penalty_code then
+ elseif id == glue_code then
+ if getsubtype(n) == belowdisplayshortskip_code then
+ return true
+ end
+ else
+ break
+ end
+ n = getnext(n)
+ end
+ return false
+end
+
+nodes.leftmarginwidth = nodes.vianuts(nuts.leftmarginwidth)
+nodes.rightmarginwidth = nodes.vianuts(nuts.rightmarginwidth)
+nodes.somespace = nodes.vianuts(nuts.somespace)
+nodes.somepenalty = nodes.vianuts(nuts.somepenalty)
+nodes.is_display_math = nodes.vianuts(nuts.is_display_math)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-typ.lua b/Master/texmf-dist/tex/context/base/mkiv/node-typ.lua
new file mode 100644
index 00000000000..2d84e07a3fc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-typ.lua
@@ -0,0 +1,129 @@
+if not modules then modules = { } end modules ['node-typ'] = {
+ 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"
+}
+
+-- code has been moved to blob-ini.lua
+
+local typesetters = nodes.typesetters or { }
+nodes.typesetters = typesetters
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setchar = nuts.setchar
+
+local getfield = nuts.getfield
+local getfont = nuts.getfont
+
+local hpack_node_list = nuts.hpack
+local vpack_node_list = nuts.vpack
+local full_hpack_list = nuts.fullhpack
+local copy_node = nuts.copy
+
+local nodepool = nuts.pool
+local new_glyph = nodepool.glyph
+local new_glue = nodepool.glue
+
+local utfvalues = utf.values
+
+local currentfont = font.current
+local currentattr = node.current_attr
+local fontparameters = fonts.hashes.parameters
+
+local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty
+ local head, prev = nil, nil
+-- local attrid = nil
+ if not fontid then
+ if templateglyph then
+ fontid = getfont(templateglyph)
+-- attrid = getfield(templateglyph,"attr")
+ else
+ fontid = currentfont()
+-- attrid = currentattr()
+ end
+ end
+ local fp = fontparameters[fontid]
+ local s, p, m
+ if spacing then
+ s, p, m = spacing, 0, 0
+ else
+ s, p, m = fp.space, fp.space_stretch, fp.space_shrink
+ end
+ local spacedone = false
+ for c in utfvalues(str) do
+ local next
+ if c == 32 then
+ if not spacedone then
+ next = new_glue(s,p,m)
+ spacedone = true
+ end
+ elseif templateglyph then
+ next = copy_glyph(templateglyph)
+ setchar(next,c)
+ spacedone = false
+ else
+ next = new_glyph(fontid or 1,c)
+ spacedone = false
+ end
+ if not next then
+ -- nothing
+ elseif not head then
+-- setfield(next,"attr",attrid)
+ head = next
+ else
+-- setfield(next,"attr",attrid)
+ setlink(prev,next)
+ end
+ prev = next
+ end
+ return head
+end
+
+local function tohpack(str,fontid,spacing)
+ return hpack_node_list(tonodes(str,fontid,spacing),"exactly")
+end
+
+local function tohbox(str,fontid,spacing)
+ return full_hpack_list(tonodes(str,fontid,spacing),"exactly")
+end
+
+local function tovpack(str,fontid,spacing)
+ -- vpack is just a hack, and a proper implemtation is on the agenda
+ -- as it needs more info etc than currently available
+ return vpack_node_list(tonodes(str,fontid,spacing))
+end
+
+local tovbox = tovpack -- for now no vpack filter
+
+local tnuts = { }
+nuts.typesetters = tnuts
+
+tnuts.tonodes = tonodes
+tnuts.tohpack = tohpack
+tnuts.tohbox = tohbox
+tnuts.tovpack = tovpack
+tnuts.tovbox = tovbox
+
+typesetters.tonodes = function(...) local h, b = tonodes(...) return tonode(h), b end
+typesetters.tohpack = function(...) local h, b = tohpack(...) return tonode(h), b end
+typesetters.tohbox = function(...) local h, b = tohbox (...) return tonode(h), b end
+typesetters.tovpack = function(...) local h, b = tovpack(...) return tonode(h), b end
+typesetters.tovbox = function(...) local h, b = tovbox (...) return tonode(h), b end
+
+typesetters.hpack = typesetters.tohpack -- obsolete
+typesetters.hbox = typesetters.tohbox -- obsolete
+typesetters.vpack = typesetters.tovpack -- obsolete
+
+-- node.write(nodes.typesetters.tohpack("Hello World!"))
+-- node.write(nodes.typesetters.tohbox ("Hello World!"))
+-- node.write(nodes.typesetters.tohpack("Hello World!",1,100*1024*10))
+-- node.write(nodes.typesetters.tohbox ("Hello World!",1,100*1024*10))
+
+string.tonodes = function(...) return tonode(tonodes(...)) end -- quite convenient
diff --git a/Master/texmf-dist/tex/context/base/mkiv/norm-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/norm-ctx.mkiv
new file mode 100644
index 00000000000..6fc012c452e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/norm-ctx.mkiv
@@ -0,0 +1,87 @@
+%D \module
+%D [ file=norm-ctx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Normal Macros,
+%D subtitle=\CONTEXT,
+%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 A few more might end up here (like the weird ones in syst-ini).
+
+\let\normalreqno\normaleqno
+
+% more friendly in setups:
+
+\let\ordordspacing \Umathordordspacing
+\let\ordopspacing \Umathordopspacing
+\let\ordbinspacing \Umathordbinspacing
+\let\ordrelspacing \Umathordrelspacing
+\let\ordopenspacing \Umathordopenspacing
+\let\ordclosespacing \Umathordclosespacing
+\let\ordpunctspacing \Umathordpunctspacing
+\let\ordinnerspacing \Umathordinnerspacing
+\let\opordspacing \Umathopordspacing
+\let\opopspacing \Umathopopspacing
+\let\opbinspacing \Umathopbinspacing
+\let\oprelspacing \Umathoprelspacing
+\let\opopenspacing \Umathopopenspacing
+\let\opclosespacing \Umathopclosespacing
+\let\oppunctspacing \Umathoppunctspacing
+\let\opinnerspacing \Umathopinnerspacing
+\let\binordspacing \Umathbinordspacing
+\let\binopspacing \Umathbinopspacing
+\let\binbinspacing \Umathbinbinspacing
+\let\binrelspacing \Umathbinrelspacing
+\let\binopenspacing \Umathbinopenspacing
+\let\binclosespacing \Umathbinclosespacing
+\let\binpunctspacing \Umathbinpunctspacing
+\let\bininnerspacing \Umathbininnerspacing
+\let\relordspacing \Umathrelordspacing
+\let\relopspacing \Umathrelopspacing
+\let\relbinspacing \Umathrelbinspacing
+\let\relrelspacing \Umathrelrelspacing
+\let\relopenspacing \Umathrelopenspacing
+\let\relclosespacing \Umathrelclosespacing
+\let\relpunctspacing \Umathrelpunctspacing
+\let\relinnerspacing \Umathrelinnerspacing
+\let\openordspacing \Umathopenordspacing
+\let\openopspacing \Umathopenopspacing
+\let\openbinspacing \Umathopenbinspacing
+\let\openrelspacing \Umathopenrelspacing
+\let\openopenspacing \Umathopenopenspacing
+\let\openclosespacing \Umathopenclosespacing
+\let\openpunctspacing \Umathopenpunctspacing
+\let\openinnerspacing \Umathopeninnerspacing
+\let\closeordspacing \Umathcloseordspacing
+\let\closeopspacing \Umathcloseopspacing
+\let\closebinspacing \Umathclosebinspacing
+\let\closerelspacing \Umathcloserelspacing
+\let\closeopenspacing \Umathcloseopenspacing
+\let\closeclosespacing\Umathcloseclosespacing
+\let\closepunctspacing\Umathclosepunctspacing
+\let\closeinnerspacing\Umathcloseinnerspacing
+\let\punctordspacing \Umathpunctordspacing
+\let\punctopspacing \Umathpunctopspacing
+\let\punctbinspacing \Umathpunctbinspacing
+\let\punctrelspacing \Umathpunctrelspacing
+\let\punctopenspacing \Umathpunctopenspacing
+\let\punctclosespacing\Umathpunctclosespacing
+\let\punctpunctspacing\Umathpunctpunctspacing
+\let\punctinnerspacing\Umathpunctinnerspacing
+\let\innerordspacing \Umathinnerordspacing
+\let\inneropspacing \Umathinneropspacing
+\let\innerbinspacing \Umathinnerbinspacing
+\let\innerrelspacing \Umathinnerrelspacing
+\let\inneropenspacing \Umathinneropenspacing
+\let\innerclosespacing\Umathinnerclosespacing
+\let\innerpunctspacing\Umathinnerpunctspacing
+\let\innerinnerspacing\Umathinnerinnerspacing
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv
new file mode 100644
index 00000000000..06eeebd1411
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=pack-bar,
+%D version=2009.06.26,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Bars,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Bars}
+
+
+\unprotect
+
+%D This code has been moved from scrn-int to here (was some old
+%D experimental code). It could be in scrn-bar but it's static. In
+%D the meantime the interface has been adapted to a key|/|value one.
+%D
+%D \startbuffer
+%D \dorecurse{10}{
+%D \ruledhbox{\horizontalpositionbar[n=#1,min=1,max=10,text=!,color=red]}
+%D \par
+%D }
+%D \stopbuffer
+%D
+%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection
+%D
+%D \startbuffer
+%D \dorecurse{10}{
+%D \ruledhbox{\horizontalgrowingbar[n=#1,min=1,max=10,text=!,color=red]}
+%D \par
+%D }
+%D \stopbuffer
+%D
+%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection
+
+\installcorenamespace{positionbar}
+
+\installsimplecommandhandler \??positionbar {positionbar}
+
+\setuppositionbar
+ [\c!min=1,
+ \c!max=1,
+ \c!n=1,
+ \c!text=?,
+ \c!width=\emwidth,
+ \c!height=\strutheight,
+ \c!depth=\strutdepth]
+
+\unexpanded\def\horizontalpositionbar[#1]%
+ {\hbox to \hsize
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \hskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill
+ \hskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill
+ \positionbarparameter\c!text\relax
+ \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
+
+\unexpanded\def\verticalpositionbar[#1]%
+ {\vbox to \vsize
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \vskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill
+ \positionbarparameter\c!text\relax
+ \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
+
+\unexpanded\def\horizontalgrowingbar[#1]%
+ {\hbox 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
+ \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
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill
+ \hrule\s!width\positionbarparameter\c!width\s!height\zeropoint\s!depth\zeropoint
+ \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi b/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi
new file mode 100644
index 00000000000..346e7df575e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi
@@ -0,0 +1,262 @@
+%D \module
+%D [ file=pack-bck, % moved from pack-rul,
+%D version=20111115, % 1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Simple Backgrounds,
+%D author=Hans Hagen \& Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Simple Backgrounds}
+
+%D The code here is already pretty old and is used for simple
+%D backgrounds. As it is still used WS adapted the code to the
+%D new command handler methods so that it gets a second life. So
+%D it made sense to mkvi as well. Some more code is moved here
+%D too.
+
+%D \macros
+%D {setupbackground,startbackground,background}
+%D
+%D The section deals with backgrounds in the running text. This
+%D means that texts is to be collected and split over pages. To
+%D show what can be done, we provide this part of the
+%D documentation with some gray background and a red frame.
+%D Both the background and frame can have all characteristics
+%D of \type{\framed}.
+%D
+%D \starttyping
+%D \setupbackground
+%D [backgroundoffset=4pt,
+%D background=color,
+%D frame=on,
+%D framecolor=red,
+%D leftoffset=2pt]
+%D \stoptyping
+%D
+%D The implementation is not that sophisticated, but suffices.
+%D The main problem with this kind of functionality is to get
+%D the spacing all right.
+%D
+%D Specifying the background is more or less the same as
+%D specifying a framed box.
+%D
+%D \showsetup{setupbackground}
+%D
+%D {\em This mechanism is sort of obsolete and textbackgrounds should
+%D be used instead.}
+
+\unprotect
+
+\installcorenamespace {background}
+
+\installframedcommandhandler \??background {background} \??background
+
+% The mode is not that public an dmostlu an initial mode:
+%
+% 0 : no split
+% 1 : no split, honoring leftskip (messy)
+% 2 : split
+% 3 : split, honoring leftskip (messy)
+%
+% While processing the modes will change from 3->1 or 2->0. Don't
+% depend on the mode being public currently as it could become a
+% key.
+
+\setnewconstant\backgroundsplitmode\plusthree
+
+\appendtoks
+ \setuevalue{\e!start\currentbackground}{\pack_backgrounds_start [\currentbackground]}%
+ \setuevalue{\e!stop \currentbackground}{\pack_backgrounds_stop }%
+ \setuevalue {\currentbackground}{\pack_backgrounds_direct[\currentbackground]}%
+\to \everydefinebackground
+
+\unexpanded\def\pack_backgrounds_start[#tag]%
+ {\endgraf
+ \begingroup
+ \def\currentbackground{#tag}%
+ \doifelse{\backgroundparameter\c!state}\v!start
+ {\dosingleempty\pack_backgrounds_start_indeed}
+ {\dosingleempty\pack_backgrounds_start_ignore}}
+
+\def\pack_backgrounds_start_indeed[#settings]%
+ {\setupcurrentbackground[#settings,\c!state=\v!start,\c!offset=\v!overlay]%
+ \let\pack_backgrounds_stop\pack_backgrounds_stop_indeed
+ \setbox0\vbox\bgroup
+ \strut
+ \vskip-2\lineheight
+ \strut
+ \blank[\v!disable]
+ \leftskip \backgroundparameter\c!leftoffset
+ \rightskip\backgroundparameter\c!rightoffset}
+
+\def\pack_backgrounds_start_ignore[#settings]%
+ {\let\pack_backgrounds_stop\pack_backgrounds_stop_ignore}
+
+\let\pack_backgrounds_stop\relax
+
+\unexpanded\def\pack_backgrounds_stop_indeed % we shoul duse the fast background variant of framed
+ {\endgraf
+ \removelastskip
+ \strut
+ \vskip-2\lineheight
+ \strut
+ \egroup
+ \dimen2\leftskip % new **
+ \forgetall
+ \ifinsidefloat
+ \backgroundsplitmode\zerocount
+ \fi
+ \ifcase\backgroundsplitmode
+ \inheritedbackgroundframed{\box0}%
+ \or
+ \hskip\dimen2
+ \inheritedbackgroundframed{\box0}%
+ \else
+ \splitmaxdepth\boxmaxdepth
+ \splittopskip\topskip
+ \doloop
+ {\ifdim\pagetotal=\zeropoint % empty page
+ \scratchdimen\textheight
+ \backgroundsplitmode\plusone % split to max height
+ \else
+ \setbox2\vbox{\backgroundparameter\c!before}%
+ \scratchdimen\dimexpr\pagegoal-\ht2-\pagetotal\relax
+ \backgroundsplitmode\plustwo % split to partial height
+ \fi
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\pagegoal
+ \fi
+ \advance\scratchdimen\dimexpr
+ -\backgroundparameter\c!topoffset
+ -\backgroundparameter\c!bottomoffset
+ \relax
+ \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
+ \ifdim\ht0>\scratchdimen % larger than page
+ \setbox2\vsplit0 to \scratchdimen
+ \else
+ \setbox2\box0
+ \backgroundsplitmode\zerocount % no split
+ \fi
+ \setbox2\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split
+ {\vskip\backgroundparameter\c!topoffset
+ \unvcopy2
+ \prevdepth\dp2
+ \obeydepth
+ \vskip\backgroundparameter\c!bottomoffset
+ \vfill}
+ \backgroundparameter\c!before
+ \ifcase\backgroundsplitmode\or\or % partial split
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal=1.2\pagegoal % be a bit more tolerant
+ \fi
+ \fi
+ \startlinecorrection
+ \ifnum\backgroundsplitmode=\plusthree
+ \hskip\dimen2 % new **
+ \fi
+ \inheritedbackgroundframed{\box2}%
+ \stoplinecorrection
+ \ifcase\backgroundsplitmode % no split
+ \backgroundparameter\c!after
+ \else % some split
+ \page_otr_fill_and_eject_page % no \page !
+ \fi
+ \else
+ \page
+ \fi
+ \ifdim\ht0>\zeropoint \else
+ \exitloop
+ \fi}%
+ \fi
+ \endgroup
+ \endgraf}
+
+\unexpanded\def\pack_backgrounds_stop_ignore
+ {\endgroup
+ \endgraf}
+
+\unexpanded\def\pack_backgrounds_direct[#tag]%
+ {\begingroup
+ \def\currentbackground{#tag}%
+ \doifelse{\backgroundparameter\c!state}\c!start
+ \pack_backgrounds_direct_indeed
+ \pack_backgrounds_direct_ignore}
+
+\def\pack_backgrounds_direct_indeed
+ {\dowithnextboxcs\pack_backgrounds_direct_finish\vbox}
+
+\def\pack_backgrounds_direct_finish
+ {\setupcurrentbackground[\c!offset=\v!overlay]%
+ \inheritedbackgroundframed{\flushnextbox}%
+ \endgroup}
+
+\def\pack_backgrounds_direct_ignore
+ {\endgroup}
+
+\definebackground[\v!background]
+
+\ifdefined\startbackground \else
+ \expandafter\let\expandafter\startbackground\csname\e!start\v!background\endcsname
+ \expandafter\let\expandafter\stopbackground \csname\e!stop \v!background\endcsname
+ \expandafter\let\expandafter\background \csname \v!background\endcsname
+\fi
+
+\setupbackground
+ [\c!leftoffset=.5\bodyfontsize,
+ \c!rightoffset=\backgroundparameter\c!leftoffset,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\backgroundparameter\c!topoffset,
+ \c!state=\v!start,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!depth=\zeropoint,
+ % \c!color=,
+ \c!background=\v!color,
+ \c!backgroundcolor=lightgray,
+ \c!before=,
+ \c!after=]
+
+%D \startbuffer
+%D \setupbackground[state=start,frame=on]
+%D
+%D \startbackground
+%D \input ward
+%D \stopbackground
+%D
+%D \background{\input ward\par}
+%D
+%D \setupbackground[state=stop]
+%D
+%D \startbackground
+%D \input ward
+%D \stopbackground
+%D
+%D \background{\input ward\par}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {backgroundline}
+
+\unexpanded\def\backgroundline[#color]%
+ {\dontleavehmode
+ \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox}
+
+\unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper
+ {\hbox
+ {\dousecolorparameter{#color}%
+ \vrule
+ \!!width \nextboxwd
+ \!!height\nextboxht
+ \!!depth \nextboxdp
+ \hskip-\nextboxwd
+ \flushnextbox}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv
new file mode 100644
index 00000000000..fad7d6e18a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv
@@ -0,0 +1,1098 @@
+%D \module
+%D [ file=pack-box,
+%D version=2002.04.12,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Boxes}
+
+%D This module contains all kind of macros for moving content around. Many
+%D macros here come from other modules, but depencies made it more clear
+%D to isolate them. We invite users to document the macros. They can be
+%D handy shortcuts for otherwise complex tasks.
+
+\unprotect
+
+%D We need to set the size, else we get dimensions depending on the content,
+%D which in itself is ok, but can lead to loops due to rounding errors (happened
+%D in demo-obv).
+
+\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+
+\unexpanded\def\internaltextoverlay#1% will become more generic and installable
+ {\startoverlay % i.e. probably an overlay by itself
+ {\positionregionoverlay\textanchor{\v!text#1}}% see later
+ {\composedlayer {\v!text#1}}%
+ \stopoverlay}
+
+\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
+\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
+\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
+\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
+
+\installcorenamespace {anchor}
+
+\unexpanded\def\defineanchor
+ {\doquadrupleempty\pack_anchors_define}
+
+\def\pack_anchors_define[#1][#2][#3][#4]% name targetlayer layersetting framedsetting
+ {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}}
+
+\def\pack_anchors_process_defined#1#2#3%
+ {\def\pack_anchors_process_defined_indeed[##1][##2]%
+ {\ifsecondargument
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}%
+ \else\iffirstargument
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}%
+ \else
+ \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}%
+ \fi\fi
+ \next}%
+ \dodoubleempty\pack_anchors_process_defined_indeed}
+
+\unexpanded\def\anchor[#1]%
+ {\begingroup
+ \edef\currentanchor{#1}%
+ \ifcsname\??anchor\currentanchor\endcsname
+ \expandafter\pack_anchor_predefined
+ \else
+ \expandafter\pack_anchor_notdefined
+ \fi}
+
+\def\pack_anchor_predefined
+ {\csname\??anchor\currentanchor\endcsname}
+
+\def\pack_anchor_notdefined
+ {\dodoubleempty\pack_anchor_notdefined_indeed}
+
+\def\pack_anchor_notdefined_indeed
+ {\ifsecondargument
+ \expandafter\pack_anchor_notdefined_two
+ \else
+ \expandafter\pack_anchor_notdefined_one
+ \fi}
+
+\def\pack_anchor_notdefined_one[#1][#2]{\pack_anchors_process_indeed\currentanchor{#1}{#1}}
+\def\pack_anchor_notdefined_two[#1][#2]{\pack_anchors_process_indeed\currentanchor{#1}{#2}}
+
+\def\pack_anchors_process_indeed#1#2#3%
+ {\dowithnextbox{\pack_anchors_process_finish{#1}{#2}{#3}}\vbox}
+
+\newbox \b_pack_anchors
+\newdimen\d_pack_anchors_width
+\newdimen\d_pack_anchors_height
+\newdimen\d_pack_anchors_depth
+
+\definelayer[anchor] % \defineoverlay[anchor][\ruledhbox{\flushlayer[anchor]}]
+
+\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy
+ {\checkpositionoverlays
+ % for the moment we ignore the depth
+ \setbox\b_pack_anchors\box\nextbox
+ \d_pack_anchors_width \wd\b_pack_anchors
+ \d_pack_anchors_height\ht\b_pack_anchors
+ \d_pack_anchors_depth \dp\b_pack_anchors
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox\d_pack_anchors_width
+ \ht\scratchbox\d_pack_anchors_height
+ \dp\scratchbox\d_pack_anchors_depth
+ \setlayer
+ [anchor]
+ [\c!width=\d_pack_anchors_width,
+ \c!height=\d_pack_anchors_height,
+ \c!offset=\zeropoint,
+ #2,#3]
+ {\setlayer[#1]{\box\b_pack_anchors}}% % #1 uses ovelaywidth/height
+ \framed % could be a predefined framed
+ [\c!background=anchor,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ #3]
+ {\box\scratchbox}%
+ \endgroup}
+
+% collectors
+
+\installcorenamespace{collectorbox}
+\installcorenamespace{collector}
+
+\installcommandhandler \??collector {collector} \??collector
+
+\setupcollector
+ [\c!state=\v!start,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!offset=\zeropoint,
+ \c!rotation=, % geen 0 !
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!location=rb,
+ \c!corner=]
+
+\appendtoks
+ \ifcsname\??collectorbox\currentcollector\endcsname \else
+ \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname
+ \fi
+\to \everydefinecollector
+
+\unexpanded\def\resetcollector[#1]%
+ {\ifcsname\??collectorbox#1\endcsname
+ %\global\setbox\csname\??collectorbox#1\endcsname\emptybox
+ \global\setbox\lastnamedcs\emptybox
+ \fi}
+
+\newconditional\c_pack_boxes_collector_valid_box
+
+\let\b_pack_boxes_collector\scratchbox
+
+\def\pack_boxes_collector_check_box#1%
+ {\edef\currentcollector{#1}%
+ \ifcsname\??collectorbox\currentcollector\endcsname
+ \settrue\c_pack_boxes_collector_valid_box
+ %\expandafter\let\expandafter\b_pack_boxes_collector\csname\??collectorbox\currentcollector\endcsname
+ \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs
+ \else
+ \setfalse\c_pack_boxes_collector_valid_box
+ \writestatus{collector}{unknown collector \currentcollector}%
+ \fi}
+
+\unexpanded\def\setcollector
+ {\bgroup
+ \dodoubleargument\pack_boxes_collector}
+
+\def\pack_boxes_collector[#1][#2]% todo: keep reference point
+ {\pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \setupcurrentcollector[#2]%
+ \expandafter\pack_boxes_collector_yes
+ \else
+ \expandafter\pack_boxes_collector_nop
+ \fi}
+
+\def\pack_boxes_collector_yes
+ {\forgetall
+ \dontcomplain
+ \dowithnextboxcs\pack_boxes_collector_finish\hbox}
+
+\def\pack_boxes_collector_nop
+ {\egroup}
+
+\installcorenamespace{collectorcorners}
+
+\setvalue{\??collectorcorners\v!middle}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position.5\d_pack_layers_x_size
+ \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position.5\d_pack_layers_y_size
+ \fi}
+
+\setvalue{\??collectorcorners\v!bottom}%
+ {\ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position-\d_pack_layers_y_size
+ \d_pack_layers_y_position-\d_pack_layers_y_position
+ \fi}
+
+\setvalue{\??collectorcorners\v!right}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position-\d_pack_layers_x_size
+ \d_pack_layers_x_position-\d_pack_layers_x_position
+ \fi}
+
+\def\pack_boxes_collector_check_corner#1%
+ {\ifcsname\??collectorcorners#1\endcsname
+ \lastnamedcs
+ \fi}
+
+\def\pack_boxes_collector_finish
+ {\edef\p_collector_rotation{\collectorparameter\c!rotation}%
+ \edef\p_collector_corner {\collectorparameter\c!corner}%
+ \ifx\p_collector_rotation\empty \else
+ \setbox\nextbox\hpack
+ {\rotate
+ [\c!location=\v!high,
+ \c!rotation=\p_collector_rotation]
+ {\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax
+ \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax
+ \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner
+ \setbox\nextbox\hpack
+ {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}%
+ \boxmaxdepth\zeropoint % really needed, nice example
+ \global\advance\boxhdisplacement\d_pack_layers_x_position
+ \ifdim\boxhdisplacement<\zeropoint
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\kern-\boxhdisplacement
+ \box\b_pack_boxes_collector}%
+ \fi
+ \global\advance\boxvdisplacement\d_pack_layers_y_position
+ \ifdim\boxvdisplacement<\zeropoint
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\lower-\boxvdisplacement
+ \box\b_pack_boxes_collector}%
+ \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\box\b_pack_boxes_collector
+ \kern\dimexpr
+ -\d_pack_layers_x_size
+ +\d_pack_layers_x_position
+ \ifdim\boxhdisplacement<\zeropoint
+ -\boxhdisplacement
+ \fi
+ \relax
+ \lower\d_pack_layers_y_position\hpack
+ {\ifdim\boxvdisplacement<\zeropoint
+ \lower-\boxvdisplacement
+ \fi
+ \box\nextbox}}%
+ % combine height and depth into depth only (later flushed as height)
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}%
+ % just to be sure
+ \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size
+ \wd\b_pack_boxes_collector\d_pack_layers_x_size
+ \fi
+ \egroup}
+
+\unexpanded\def\flushcollector[#1]%
+ {\bgroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \edef\p_collector_state{\collectorparameter\c!state}%
+ \ifx\p_collector_state\v!stop \else
+ \vpack{\hpack{\raise
+ \dp\b_pack_boxes_collector
+ \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}%
+ \fi
+ \fi
+ \egroup}
+
+\unexpanded\def\composedcollector#1% no [], handy as argument
+ {\flushcollector[#1]}
+
+\unexpanded\def\adaptcollector
+ {\dodoubleargument\pack_boxes_collector_adapt}
+
+\def\pack_boxes_collector_adapt[#1][#2]% % a typical case where \global\wd looks better in the code
+ {\begingroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \letcollectorparameter\c!voffset\zeropoint
+ \letcollectorparameter\h!voffset\zeropoint
+ \ifsecondargument
+ \setupcurrentcollector[#2]%
+ \fi
+ \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax
+ \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax
+ \fi
+ \endgroup}
+
+%\definecollector[test]
+%\setcollector[test]
+% [location=rb]
+% {\externalfigure[koe][frame=on,width=3cm]}
+%\setcollector[test]
+% [corner={right,bottom},location={left,top}]
+% {\framed{gans}}
+%\composedcollector{test}
+
+\definecollector
+ [caption]
+
+\unexpanded\def\collectedtext % for captions
+ {\bgroup
+ \dodoubleempty\pack_boxes_collector_text}
+
+\def\pack_boxes_collector_text[#1][#2]#3%
+ {\dowithnextbox
+ {\setcollector
+ [caption]
+ {\box\nextbox}%
+ \setcollector
+ [caption][#1]
+ {\letdummyparameter\c!style\empty
+ \letdummyparameter\c!color\empty
+ \getdummyparameters[#2]%
+ \dousestyleparameter{\directdummyparameter\c!style}%
+ \setupinterlinespace
+ \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}%
+ \composedcollector{caption}%
+ \egroup}%
+ \hbox}
+
+% \collectedtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\installcorenamespace {layeredtext}
+\installcorenamespace {layeredtextlayer}
+\installcorenamespace {layeredtextframed}
+
+\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext
+
+\newdimen\d_pack_layeredtexts_width
+\newdimen\d_pack_layeredtexts_height
+
+\definelayer % private
+ [\??layeredtextlayer]
+
+\setuplayer % private
+ [\??layeredtextlayer]
+ [\c!width=\d_pack_layeredtexts_width,
+ \c!height=\d_pack_layeredtexts_height]
+
+\defineframed % private
+ [\??layeredtextframed]
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!background={\v!foreground,\??layeredtextlayer},
+ \c!width=\d_pack_layeredtexts_width,
+ \c!height=\d_pack_layeredtexts_height]
+
+\setuplayeredtext % public (the attached data, usually small stuff, not the main thing)
+ [\c!frame=\v!overlay,
+ \c!color=,
+ \c!style=,
+ \c!foregroundcolor=\layeredtextparameter\c!color,
+ \c!foregroundstyle=\layeredtextparameter\c!style]
+
+\unexpanded\def\layeredtext
+ {\bgroup
+ \let\currentlayeredtext\empty
+ \dodoubleempty\pack_layeredtexts_place}
+
+\unexpanded\def\placelayeredtext[#1]%
+ {\bgroup
+ \edef\currentlayeredtext{#1}%
+ \checklayeredtextparent % bonus
+ \dodoubleempty\pack_layeredtexts_place}
+
+\def\pack_layeredtexts_place[#1][#2]#3% layersettings content(framed)settings content
+ {\setupcurrentlayeredtext[#2]%
+ \dowithnextbox
+ {\d_pack_layeredtexts_width \wd\nextbox
+ \d_pack_layeredtexts_height\ht\nextbox
+ \begingroup % preserve \nextbox
+ \setlayer
+ [\??layeredtextlayer]%
+ [#1]%
+ {\setfalse\fontattributeisset
+ \uselayeredtextstyleparameter\c!style
+ \ifconditional\fontattributeisset
+ \setupinterlinespace
+ \fi
+ \inheritedlayeredtextframed{#3}}%
+ \endgroup
+ \placeframed[\??layeredtextframed]{\flushnextbox}%
+ \egroup}%
+ \hbox}
+
+% \layeredtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\unexpanded\def\ornamenttext
+ {\dodoubleempty\pack_ornament_text}
+
+\def\pack_ornament_text[#1][#2]%
+ {\bgroup
+ \doifelseassignment{#1}
+ {\letdummyparameter\c!alternative\v!a
+ \getdummyparameters[#1]%
+ \doifelse{\directdummyparameter\c!alternative}\v!a
+ {\egroup\collectedtext}%
+ {\egroup\layeredtext }%
+ [#1][#2]}%
+ {\egroup\getvalue{#1}}}
+
+\unexpanded\def\defineornament
+ {\dotripleempty\dodefineornament}
+
+\def\dodefineornament[#1][#2][#3]%
+ {\setuvalue{#1}{\pack_ornament_text[#2][#3]}}
+
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex,alternative=b]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=a]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{photo}{\externalfigure[molen][width=3cm]}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=b]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
+
+\newcount\c_pack_boxes_bleeds
+
+\installcorenamespace {bleeding}
+
+\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding
+
+\setupbleeding
+ [\c!location=l,
+ \c!stretch=\v!yes,
+ \c!width=3cm,
+ \c!height=3cm,
+ \c!offset=2mm,
+ \c!page=\v!no,
+ \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset
+ \c!hoffset=\scratchoffset] % which often saves one resolve
+
+\def\bleedwidth {\the\hsize} % these are global !
+\def\bleedheight{\the\vsize} % these are global !
+
+\newconditional\c_pack_boxes_l
+\newconditional\c_pack_boxes_r
+\newconditional\c_pack_boxes_t
+\newconditional\c_pack_boxes_b
+
+\unexpanded\def\bleed
+ {\hbox\bgroup
+ \dosingleempty\pack_boxes_bleed}
+
+\installcorenamespace{bleedinglocation}
+
+\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+
+\def\pack_boxes_bleed[#1]%
+ {\global\advance\c_pack_boxes_bleeds\plusone
+ %
+ \xdef\bleedwidth {\the\hsize}%
+ \xdef\bleedheight{\the\vsize}%
+ %
+ \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}%
+ \edef\currentpageposition{page:0}% todo: per page
+ %
+ \setupcurrentbleeding[#1]%
+ %
+ \scratchwidth \bleedingparameter\c!width
+ \scratchheight \bleedingparameter\c!height
+ \scratchoffset \bleedingparameter\c!offset
+ \scratchhoffset\bleedingparameter\c!hoffset
+ \scratchvoffset\bleedingparameter\c!voffset
+ %
+ \setfalse\c_pack_boxes_l % left
+ \setfalse\c_pack_boxes_r % right
+ \setfalse\c_pack_boxes_t % top
+ \setfalse\c_pack_boxes_b % bottom
+ %
+ \csname\??bleedinglocation\bleedingparameter\c!location\endcsname
+ %
+ \doifelse{\bleedingparameter\c!stretch}\v!yes\donetrue\donefalse
+ %
+ \xdef\bleedwidth{\the\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_l
+ \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition
+ \else\ifconditional\c_pack_boxes_r
+ \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked
+ \else
+ \scratchwidth
+ \fi\fi
+ \else
+ \scratchwidth
+ \fi+\scratchhoffset
+ \relax}%
+ \xdef\bleedheight{\the\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_t
+ \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked
+ \else\ifconditional\c_pack_boxes_b
+ \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition % not checked
+ \else
+ \scratchheight
+ \fi\fi
+ \else
+ \scratchheight
+ \fi+\scratchvoffset
+ \relax}%
+ \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox}
+
+\def\pack_boxes_bleed_settings
+ {\hsize\bleedwidth
+ \vsize\bleedheight}
+
+\def\pack_boxes_bleed_finish
+ {\doif{\bleedingparameter\c!page}\v!yes
+ {\setbox\nextbox\topskippedbox{\box\nextbox}}%
+ \setbox\nextbox\hpack to \scratchwidth
+ {\ifconditional\c_pack_boxes_l\hss\fi
+ \box\nextbox
+ \ifconditional\c_pack_boxes_r\hss\fi}%
+ \ifconditional\c_pack_boxes_b
+ \setbox\nextbox\hpack
+ {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}%
+ \fi
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\zeropoint
+ \ifdone
+ \hpos\currentbgposition{\box\nextbox}%
+ \else
+ \box\nextbox
+ \fi
+ \egroup}
+
+\defineexternalfigure
+ [bleed] % should be \v!bleed
+ [\c!width=\bleedwidth,
+ \c!height=\bleedheight]
+
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[right]{none}
+% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure
+% [top,none]
+% {} % no caption
+% {\bleed
+% [hoffset=-\backspace,
+% voffset=3mm,
+% width=0cm,
+% height=6\lineheight,
+% page=yes, % correct for topskip
+% location=lt]
+% {\externalfigure[koe][bleed][frame=on]}}
+
+% \setlayerframed[layer id][layer settings][framed setting]{data}
+% \setlayerframed[layer id][combined settings]{data}
+
+% tricky: offsets apply to both the layer and the framed; it makes sense to
+% only apply the offset to ...
+
+\unexpanded\def\setlayerframed
+ {\dotripleempty\pack_layers_set_framed}
+
+\def\pack_layers_set_framed
+ {\ifthirdargument
+ \singleexpandafter\pack_layers_set_framed_t
+ \else\ifsecondargument
+ \doubleexpandafter\pack_layers_set_framed_d
+ \else
+ \doubleexpandafter\pack_layers_set_framed_s
+ \fi\fi}
+
+\def\pack_layers_set_framed_s[#1][#2][#3]%
+ {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]%
+ \normalframedwithsettings[\c!location=\v!normal]} % different kind of location
+
+\def\pack_layers_set_framed_d[#1][#2][#3]%
+ {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]%
+ \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location
+
+\def\pack_layers_set_framed_t[#1][#2][#3]%
+ {\setlayer[#1][#2]%
+ \normalframedwithsettings[#3]}
+
+\unexpanded\def\setlayertext
+ {\dotripleempty\pack_layers_set_text}
+
+\def\pack_layers_set_text[#1][#2][#3]%
+ {\bgroup
+ \letdummyparameter\c!align\empty
+ \letdummyparameter\c!width\hsize
+ \letdummyparameter\c!color\empty
+ \letdummyparameter\c!style\empty
+ \getdummyparameters[#3]%
+ \dowithnextboxcontent
+ {\forgetall
+ \hsize\directdummyparameter\c!width
+ \usealignparameter\directdummyparameter
+ \dousestyleparameter{\directdummyparameter\c!style}}
+ {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color
+ \egroup}%
+ \vtop}
+
+% \setupbackgrounds
+% [page]
+% [background=pagefigures]
+%
+% \definelayer
+% [pagefigures]
+% [x=-2mm,
+% y=-2mm,
+% width=\paperwidth,
+% height=\paperheight]
+%
+% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}]
+% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}]
+% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}]
+% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
+% \definelayerpreset [middle] [corner=middle,location=middle]
+%
+% \setlayer[pagefigures][preset=lefttop]
+% \setlayer[pagefigures][preset=righttop]
+% \setlayer[pagefigures][preset=leftbottom]
+% \setlayer[pagefigures][preset=rightbottom]
+
+\definelayerpreset
+ [\v!left\v!top]
+ [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
+
+\definelayerpreset
+ [\v!right\v!top]
+ [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
+
+\definelayerpreset
+ [\v!left\v!bottom]
+ [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!bottom]
+ [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!middle]
+ [\c!corner=\v!middle,\c!location=\v!middle]
+
+\definelayerpreset
+ [\v!middle\v!top]
+ [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!bottom]
+ [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!left]
+ [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!right]
+ [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
+
+% left and right hanging:
+
+\definelayerpreset
+ [\v!left\v!top\v!left]
+ [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!top\v!right]
+ [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}]
+
+\installcorenamespace{alignedboxes}
+
+\unexpanded\def\alignedbox{\dosingleempty\pack_boxes_aligned_box}
+\unexpanded\def\aligned {\dosingleempty\pack_boxes_aligned}
+
+\def\pack_boxes_aligned_box[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
+\def\pack_boxes_aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
+
+% \def\pack_boxes_aligned_finish
+% {\csname\??alignedboxes
+% \ifcsname\??alignedboxes\serializedcommalist\endcsname\serializedcommalist\else\v!middle\fi
+% \endcsname{\flushnextbox}%
+% \egroup}
+
+\def\pack_boxes_aligned_finish
+ {\ifcsname\??alignedboxes\serializedcommalist\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\middlebox
+ \fi{\flushnextbox}%
+ \egroup}
+
+\letvalue{\??alignedboxes }\middlebox
+\letvalue{\??alignedboxes\v!middle }\middlebox
+\letvalue{\??alignedboxes\v!middle\v!middle}\middlebox
+\letvalue{\??alignedboxes\v!left }\leftbox
+\letvalue{\??alignedboxes\v!left \v!top }\lefttopbox
+\letvalue{\??alignedboxes\v!left \v!bottom}\leftbottombox
+\letvalue{\??alignedboxes\v!right }\rightbox
+\letvalue{\??alignedboxes\v!right \v!top }\righttopbox
+\letvalue{\??alignedboxes\v!right \v!bottom}\rightbottombox
+\letvalue{\??alignedboxes\v!bottom }\bottombox
+\letvalue{\??alignedboxes\v!bottom\v!left }\bottomleftbox
+\letvalue{\??alignedboxes\v!bottom\v!right }\bottomrightbox
+\letvalue{\??alignedboxes\v!top }\topbox
+\letvalue{\??alignedboxes\v!top \v!left }\topleftbox
+\letvalue{\??alignedboxes\v!top \v!right }\toprightbox
+\letvalue{\??alignedboxes\v!line }\baselinemiddlebox % \v!grid is taken
+\letvalue{\??alignedboxes\v!line \v!left }\baselineleftbox
+\letvalue{\??alignedboxes\v!line \v!middle}\baselinemiddlebox
+\letvalue{\??alignedboxes\v!line \v!right }\baselinerightbox
+\letvalue{\??alignedboxes c}\middlebox
+\letvalue{\??alignedboxes l}\leftbox
+\letvalue{\??alignedboxes r}\rightbox
+\letvalue{\??alignedboxes b}\bottombox
+\letvalue{\??alignedboxes t}\topbox
+\letvalue{\??alignedboxes lt}\lefttopbox
+\letvalue{\??alignedboxes lb}\leftbottombox
+\letvalue{\??alignedboxes rt}\righttopbox
+\letvalue{\??alignedboxes rb}\rightbottombox
+\letvalue{\??alignedboxes tl}\topleftbox
+\letvalue{\??alignedboxes bl}\bottomleftbox
+\letvalue{\??alignedboxes tr}\toprightbox
+\letvalue{\??alignedboxes br}\bottomrightbox
+\letvalue{\??alignedboxes m}\middlebox
+\letvalue{\??alignedboxes g}\baselinemiddlebox
+\letvalue{\??alignedboxes gl}\baselineleftbox
+\letvalue{\??alignedboxes gc}\baselinemiddlebox
+\letvalue{\??alignedboxes gr}\baselinerightbox
+
+% left/right/top/bottomoffset -> dimensions change
+% x/y | method=fixed -> dimensions don't change
+
+\installcorenamespace{offsetbox}
+
+\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox
+
+\setupoffsetbox
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\wd\nextbox,
+ \c!height=\ht\nextbox,
+ \c!depth=\dp\nextbox,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=]
+
+\let\setupoffset\setupoffsetbox
+
+\unexpanded\def\offsetbox{\dosingleempty\pack_boxes_offset_box}
+\unexpanded\def\offset {\dosingleempty\pack_boxes_offset}
+
+\def\pack_boxes_offset_box[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish}
+
+\def\pack_boxes_offset[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish\hbox}
+
+\newcount\c_pack_boxes_offset_level
+
+\def\pack_boxes_offset_check
+ {\advance\c_pack_boxes_offset_level\plusone
+ \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}%
+ \checkoffsetboxparent
+ \setupcurrentoffsetbox}
+
+\def\pack_boxes_offsetfinish
+ {\donefalse
+ \scratchxposition \offsetboxparameter\c!x
+ \scratchyposition \offsetboxparameter\c!y
+ \scratchleftoffset \offsetboxparameter\c!leftoffset
+ \scratchrightoffset \offsetboxparameter\c!rightoffset
+ \scratchtopoffset \offsetboxparameter\c!topoffset
+ \scratchbottomoffset\offsetboxparameter\c!bottomoffset
+ \relax % really needed
+ \ifdim\scratchleftoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchrightoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchtopoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchbottomoffset=\zeropoint\else\donetrue\fi
+ \ifdone
+ \edef\p_method{\offsetboxparameter\c!method}%
+ \ifx\p_method\v!fixed % new
+ \ifdim\scratchleftoffset=\zeropoint
+ \ifdim\scratchrightoffset=\zeropoint \else
+ \scratchxposition-\scratchrightoffset
+ \scratchrightoffset\zeropoint
+ \fi
+ \else
+ \scratchxposition\scratchleftoffset
+ \scratchleftoffset\zeropoint
+ \fi
+ \ifdim\scratchtopoffset=\zeropoint
+ \ifdim\scratchbottomoffset=\zeropoint \else
+ \scratchyposition-\scratchbottomoffset
+ \scratchbottomoffset\zeropoint
+ \fi
+ \else
+ \scratchyposition\scratchtopoffset
+ \scratchtopoffset\zeropoint
+ \fi
+ \donefalse
+ \fi
+ \fi
+ \ifdone
+ \setbox\nextbox\vpack
+ {\forgetall % already done
+ \offinterlineskip
+ \kern\scratchtopoffset
+ \hpack
+ {\kern\scratchleftoffset
+ \box\nextbox
+ \kern\scratchrightoffset}%
+ \kern\scratchbottomoffset}%
+ \ht\nextbox\htdp\nextbox
+ \dp\nextbox\zeropoint
+ \fi
+ \scratchwidth \offsetboxparameter\c!width
+ \scratchheight\offsetboxparameter\c!height
+ \scratchdepth \offsetboxparameter\c!depth
+ \edef\p_location{\offsetboxparameter\c!location}%
+ \setbox\nextbox\hpack
+ {\kern\scratchxposition
+ \lower\scratchyposition\hpack
+ {\ifx\p_location\empty
+ \box\nextbox
+ \else
+ \alignedbox[\p_location]\hpack{\box\nextbox}%
+ \fi}}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+%D \starttyping
+%D \framed[offset=overlay]{\offset[leftoffset=1cm]
+%D {\framed[offset=overlay]{\offset[rightoffset=1cm]
+%D {\externalfigure[koe][width=1cm]}}}}
+%D
+%D \blank
+%D
+%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank
+%D \stoptyping
+
+% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
+%
+% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte
+
+% Some old code:
+%
+% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+%
+% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+%
+% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+
+\def\pack_boxes_tabbed#1#2#3#4%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hpack{#3}%
+ \hpack to \wd\scratchbox{#1#4#2}%
+ \endgroup}
+
+\unexpanded\def\ltabbed{\pack_boxes_tabbed\relax\hss}
+\unexpanded\def\rtabbed{\pack_boxes_tabbed\hss \relax}
+\unexpanded\def\ctabbed{\pack_boxes_tabbed\hss \hss}
+
+\let\mtabbed\ctabbed
+
+% to be documented
+
+\unexpanded\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
+ {\hpack\bgroup
+ \letdummyparameter\c!width \zeropoint
+ \letdummyparameter\c!height\zeropoint
+ \letdummyparameter\c!depth \zeropoint
+ \getdummyparameters[#1]%
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox\directdummyparameter\c!width
+ \ht\scratchbox\directdummyparameter\c!height
+ \dp\scratchbox\directdummyparameter\c!depth
+ \box\scratchbox
+ \egroup}
+
+% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
+
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+%
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
+
+\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \scratchcounter#1\relax
+ \scratchwidth #2\relax
+ \scratchheight #3\relax
+ \dowithnextboxcs\pack_boxes_background_image\hbox}
+
+\def\pack_boxes_background_image
+ {\offinterlineskip
+ \ifcase\scratchcounter
+ % just one
+ \else
+ \scratchdimen\scratchwidth \divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax
+ \scratchdimen\scratchheight\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax
+ % to be considered: methods
+ \ifcase\scratchcounter
+ \or % x and y
+ \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
+ \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+ \or % x
+ \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
+ \or % y
+ \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+ \fi
+ \fi
+ \ifdim\wd\nextbox>\scratchwidth
+ \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}%
+ \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+ \fi
+ \ifdim\ht\nextbox>\scratchheight
+ \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}%
+ \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+ \fi
+ \box\nextbox
+ \egroup}
+
+\unexpanded\def\backgroundimagefill#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \scratchcounter#1\relax
+ \scratchwidth #2\relax
+ \scratchheight #3\relax
+ \dowithnextboxcs\pack_boxes_background_image_fill\hbox}
+
+\def\pack_boxes_background_image_fill
+ {\offinterlineskip
+ \setbox\nextbox\hpack\bgroup
+ \ifdim\scratchwidth>\scratchheight
+ \scale[\c!width=\the\scratchwidth]{\box\nextbox}%
+ \else
+ \scale[\c!height=\the\scratchheight]{\box\nextbox}%
+ \fi
+ \egroup
+ \ifdim\wd\nextbox>\scratchwidth
+ \setbox\nextbox\hpack to \scratchwidth
+ {\ifcase\scratchcounter
+ \hss\box\nextbox\hss
+ \or
+ \box\nextbox\hss
+ \or
+ \hss\box\nextbox
+ \else
+ \hss\box\nextbox\hss
+ \fi}%
+ \setbox\nextbox\hpack
+ {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+ \fi
+ \ifdim\ht\nextbox>\scratchheight
+ \setbox\nextbox\vpack to \scratchheight
+ {\ifcase\scratchcounter
+ \vss\box\nextbox\vss
+ \or
+ \box\nextbox\vss
+ \or
+ \vss\box\nextbox
+ \else
+ \vss\box\nextbox\vss
+ \fi}%
+ \setbox\nextbox\hpack
+ {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+ \fi
+ \box\nextbox
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv
new file mode 100644
index 00000000000..c9c3bab4b9e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv
@@ -0,0 +1,949 @@
+%D \module
+%D [ file=pack-com, % used to be in core-mis,
+%D version=20120111,
+%D title=\CONTEXT\ Packing Macros,
+%D subtitle=Combinations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Combinations}
+
+\unprotect
+
+% \startfloatcombination will be redone ... we can decouple the floatcontent
+% and caption and pass them to combinations so that we get better fit when the
+% caption is wider than the float, testcase:
+%
+% \startfloatcombination [2*2]
+% \placefigure[local]{alpha}{\externalfigure[cow.pdf][width=1cm]}%
+% \placefigure[local]{beta} {\externalfigure[cow.pdf][width=2cm]}%
+% \placefigure[local]{gamma}{\externalfigure[cow.pdf][width=3cm]}
+% \placefigure[local]{delta}{\externalfigure[cow.pdf][width=4cm]}
+% \stopfloatcombination
+
+%D We could of course map combinations onto one of the table
+%D mechanisms but as it has served us well for ages we keep
+%D this one. The code has been cleaned up a bit and mkiv'd.
+%D
+%D Okay ... I might luafy this one eventually.
+
+% \startcombination {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] \combination {alpha} {a} \combination{beta} {b} \stopcombination
+
+%D We do support some structure but the order matters and currently it's
+%D only window dressing:
+%D
+%D \starttyping
+%D \let\startcontent\bgroup
+%D \let\stopcontent \egroup
+%D \let\startcaption\bgroup
+%D \let\stopcaption \egroup
+%D \stoptyping
+%D
+%D Of course we should have started with more structure as it would
+%D simply the code.
+%D
+%D \starttyping
+%D \startcombination
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D Some cow.
+%D \stopcaption
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D The same cow.
+%D \stopcaption
+%D \stopcombination
+%D \stoptyping
+
+\ifdefined\dotagcombination \else \let\dotagcombination\relax \fi
+
+\newsystemmode{combination}
+
+\appendtoks
+ \global\resetsystemmode{combination}%
+\to \everyinsidefloat
+
+\newcount\c_pack_combinations_nesting % local
+\newcount\c_pack_combinations_x % global
+\newcount\c_pack_combinations_n % global
+\newcount\c_pack_combinations_max % global
+\newbox \b_pack_combinations_captions % global
+\newbox \b_pack_combinations_temp % global
+\newbox \b_pack_combinations_content % local
+\newbox \b_pack_combinations_caption % local
+
+\installcorenamespace{combination}
+
+\installcommandhandler \??combination {combination} \??combination
+
+\initializeboxstack{\??combination captions}
+\initializeboxstack{\??combination temp}
+
+\newcount\c_pack_combinations_x_saved
+\newcount\c_pack_combinations_n_saved
+\newcount\c_pack_combinations_max_saved
+\newbox \b_pack_combinations_captions_saved
+\newbox \b_pack_combinations_temp_saved
+\newbox \b_pack_combinations_content_saved
+\newbox \b_pack_combinations_caption_saved
+
+\setfalse\c_strc_constructions_define_commands
+
+\def\pack_combinations_push
+ {\advance\c_pack_combinations_nesting\plusone
+ \ifnum\c_pack_combinations_nesting>\plusone
+ \c_pack_combinations_x_saved \c_pack_combinations_x
+ \c_pack_combinations_n_saved \c_pack_combinations_n
+ \c_pack_combinations_max_saved\c_pack_combinations_max
+ \setbox\b_pack_combinations_captions_saved\box\b_pack_combinations_captions
+ \setbox\b_pack_combinations_temp_saved \box\b_pack_combinations_temp
+ \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content
+ \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption
+ \else
+ \global\setsystemmode{combination}% why global
+ \fi}
+
+\def\pack_combinations_pop
+ {\ifnum\c_pack_combinations_nesting>\plusone
+ \global\c_pack_combinations_x \c_pack_combinations_x_saved
+ \global\c_pack_combinations_n \c_pack_combinations_n_saved
+ \global\c_pack_combinations_max\c_pack_combinations_max_saved
+ \global\setbox\b_pack_combinations_captions\box\b_pack_combinations_captions_saved
+ \global\setbox\b_pack_combinations_temp \box\b_pack_combinations_temp_saved
+ \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved
+ \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved
+ \else
+ \global\resetsystemmode{combination}% why global
+ \fi
+ \advance\c_pack_combinations_nesting\minusone}
+
+\definelabel
+ [\v!combination] % handy for configuring
+ [\c!numberconversion=\v!character,
+ \c!text=]
+
+\settrue\c_strc_constructions_define_commands
+
+\setupcombination
+ [\c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!distance=\emwidth,
+ \c!location=\v!bottom, % can be something {top,left}
+ \c!before=\blank,
+ \c!after=,
+ \c!inbetween={\blank[\v!medium]},
+ %\c!style=,
+ %\c!color=,
+ \c!nx=2, % new
+ \c!ny=1, % new
+ \c!align=\v!middle]
+
+\let\setupcombinations\setupcombination % for the moment (we might distinguish)
+
+\installcorenamespace{combinationlocation}
+\installcorenamespace{combinationalternative}
+
+\appendtoks
+ \setfalse\c_strc_constructions_define_commands
+ \normalexpanded
+ {\definelabel
+ [\v!combination:\currentcombination]%
+ [\v!combination\ifx\currentcombinationparent\empty\else:\currentcombinationparent\fi]}%
+ [\s!counter=\currentcombination,\c!levels=1]%
+ \settrue\c_strc_constructions_define_commands
+\to \everydefinecombination
+
+\setvalue{\??combinationlocation\v!left }{\let\m_pack_combinations_leftfiller\relax}
+\setvalue{\??combinationlocation\v!right }{\let\m_pack_combinations_rightfiller\relax}
+\setvalue{\??combinationlocation\v!top }{\let\m_pack_combinations_valigner\depthonlybox}
+\setvalue{\??combinationlocation\v!middle}{\let\m_pack_combinations_valigner\halfwaybox}
+
+\def\pack_combinations_location_reset
+ {\let\m_pack_combinations_rightfiller\hfil
+ \let\m_pack_combinations_leftfiller \hfil
+ \let\m_pack_combinations_valigner \firstofoneargument}
+
+\pack_combinations_location_reset
+
+\def\pack_combinations_location_step#1%
+ {\csname\??combinationlocation#1\endcsname}
+
+\unexpanded\def\startcombination
+ {\bgroup % so we can grab a group
+ \pack_combinations_push
+ \dodoubleempty\pack_combinations_start}
+
+% formally ok:
+%
+% \unexpanded\def\stopcombination
+% {\egroup
+% \egroup}
+%
+% more robust:
+%
+% \unexpanded\def\stopcombination
+% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
+% \egroup
+% \egroup}
+%
+% even better:
+%
+% \unexpanded\def\stopcombination
+% {\bgroup
+% \scratchtoks{{}}%
+% \dorecurse\c_pack_combinations_n
+% {\scratchtoks\expandafter{\the\scratchtoks{}{}}}%
+% \expandafter\egroup\the\scratchtoks
+% \egroup
+% \dostoptagged
+% \egroup}
+%
+% faster
+
+\unexpanded\def\pack_common_content_start{\bgroup\ignorespaces}
+\unexpanded\def\pack_common_content_stop {\removeunwantedspaces\egroup}
+\unexpanded\def\pack_common_caption_start{\bgroup\ignorespaces}
+\unexpanded\def\pack_common_caption_stop {\removeunwantedspaces\egroup}
+
+\unexpanded\def\stopcombination
+ {\bgroup\normalexpanded{\egroup{}\ntimes{{}{}}\c_pack_combinations_n}% brr
+ \dostoptagged
+ \egroup
+ \pack_combinations_pop
+ \egroup}
+
+\newtoks\everycombination
+
+\def\pack_combinations_start[#1][#2]% needs a cleanup, also nx ny (pretty old, this one)
+ {\edef\currentcombination{#1}%
+ \edef\currentcombinationspec{#2}%
+ \ifx\currentcombinationspec\empty
+ \doifelseassignment{#1}%
+ {\let\currentcombination\empty
+ \setupcurrentcombination[#1]%
+ \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}
+ {\doifelseinstring{*}\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\doifelsenumber\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}}%
+ \else
+ \doifelseassignment{#2}%
+ {\setupcurrentcombination[#2]%
+ \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}
+ {\edef\currentcombinationspec{\currentcombinationspec*\plusone*}}%
+ \fi
+ %
+ \forgetall
+ %
+ \the\everycombination
+ %
+ \let\startcontent\pack_common_content_start
+ \let\stopcontent \pack_common_content_stop
+ \let\startcaption\pack_common_caption_start
+ \let\stopcaption \pack_common_caption_stop
+ %
+ \edef\p_height {\combinationparameter\c!height}%
+ \edef\p_width {\combinationparameter\c!width}%
+ \edef\p_location{\combinationparameter\c!location}%
+ \edef\p_distance{\combinationparameter\c!distance}%
+ %
+ \pack_combinations_location_reset
+ \rawprocesscommacommand[\p_location]\pack_combinations_location_step
+ %
+ \dostarttaggedchained\t!combination\currentcombination\??combination
+ \vbox \ifx\p_height\v!fit\else to \p_height \fi \bgroup
+ \let\combination\empty % permits \combination{}{} handy for cld
+ \normalexpanded{\pack_combinations_start_indeed[\currentcombinationspec]}}
+
+\unexpanded\def\pack_combinations_start_indeed[#1*#2*#3]%
+ {\global\c_pack_combinations_x#1\relax
+ \global\c_pack_combinations_n#2\relax
+ \dotagcombination
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \global\c_pack_combinations_max\c_pack_combinations_x
+ \multiply\c_pack_combinations_n\c_pack_combinations_x
+ \tabskip\zeropoint
+ \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup
+ \aligntab
+ \m_pack_combinations_leftfiller
+ \alignmark\alignmark
+ \m_pack_combinations_rightfiller
+ \aligntab
+ \tabskip\zeropoint \s!plus 1fill
+ \alignmark\alignmark
+ \cr
+ \pack_combinations_pickup}
+
+% \def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box
+% {\dostoptagged
+% \setbox\b_pack_combinations_content\box\nextbox
+% \dostarttagged\t!combinationcaption\empty
+% \dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+% \afterassignment\pack_combinations_caption_first
+% \let\nexttoken=}
+
+% I've first considered using a constructor directly but it's more overhead
+% and some settings conflict with already used combination settings so instead
+% we plug in labels. This also permits extensions later on.
+
+\appendtoks
+ \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}%
+\to \everydefinecombination
+
+\def\pack_combinations_pickup
+ {\dostarttagged\t!combinationpair\empty
+ \dostarttagged\t!combinationcontent\empty
+ \assumelongusagecs\pack_combinations_pickup_content_indeed}
+
+\def\pack_combinations_pickup_content_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_content\hbox}
+
+\def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box
+ {\dostoptagged
+ \setbox\b_pack_combinations_content\box\nextbox
+ \dostarttagged\t!combinationcaption\empty
+ \expandnamespacemacro\??combinationalternative\p_pack_combinations_alternative\v!text}
+
+\setvalue{\??combinationalternative\v!text}%
+ {\assumelongusagecs\pack_combinations_alternative_text_indeed}
+
+\setvalue{\??combinationalternative\v!label}%
+ {\assumelongusagecs\pack_combinations_alternative_label_indeed}
+
+\def\pack_combinations_alternative_text_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+ \afterassignment\pack_combinations_caption_first
+ \let\nexttoken=}
+
+\def\pack_combinations_alternative_label_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+ \hsize\wd\b_pack_combinations_content
+ \usealignparameter\combinationparameter
+ \usecombinationstyleandcolor\c!style\c!color
+ \begstrut
+ \normalexpanded{\strc_labels_command{\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi}}%
+ \endstrut
+ \egroup}
+
+\appendtoks
+ \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}%
+ \ifx\p_pack_combinations_alternative\v!label
+ \edef\p_continue{\combinationparameter\c!continue}%
+ \ifx\p_continue\v!yes \else
+ \normalexpanded{\strc_labels_reset{\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi}{1}}%
+ \fi
+ \fi
+\to \everycombination
+
+\def\pack_combinations_pickup_caption
+ {\dostoptagged
+ \dostoptagged
+ \setbox\b_pack_combinations_caption\box\nextbox
+ \pack_combinations_pickup_package_pair}
+
+\def\pack_combinations_caption_first
+ {\futurelet\nexttoken\pack_combinations_caption_second}
+
+\def\pack_combinations_caption_second
+ {\ifx\nexttoken\egroup
+ % the caption is empty
+ \else\ifx\nexttoken\stopcaption
+ % the caption is empty (new per 2014-05-24)
+ \else
+ % todo: \p_pack_combinations_alternative\v!none: no style, strut etc
+ \hsize\wd\b_pack_combinations_content
+ \usealignparameter\combinationparameter
+ \usecombinationstyleandcolor\c!style\c!color
+ \bgroup
+ \aftergroup\endstrut
+ \aftergroup\egroup
+ \begstrut
+ \fi\fi}
+
+\def\pack_combinations_pickup_package_pair % we need to store the caption row
+ {\vbox
+ {\forgetall
+ \m_pack_combinations_valigner{\box\b_pack_combinations_content}%
+ % we need to save the caption for a next alignment line
+ \pack_combinations_save_caption}%
+ \ifnum\c_pack_combinations_n>\plusone
+ \global\advance\c_pack_combinations_n\minusone
+ \global\advance\c_pack_combinations_x\minusone
+ \ifcase\c_pack_combinations_x
+ \doubleexpandafter\pack_combinations_pickup_package_pair_a
+ \else
+ \doubleexpandafter\pack_combinations_pickup_package_pair_b
+ \fi
+ \else
+ \singleexpandafter\pack_combinations_pickup_package_pair_c
+ \fi}
+
+\def\pack_combinations_pickup_package_pair_a
+ {\cr
+ \pack_combinations_flush_captions
+ \noalign
+ {\forgetall
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \nointerlineskip
+ \combinationparameter\c!after
+ \combinationparameter\c!before
+ \vss
+ \nointerlineskip}%
+ \global\c_pack_combinations_x\c_pack_combinations_max
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup_package_pair_b
+ {\aligntab
+ \aligntab
+ \aligntab
+ \kern\p_distance
+ \aligntab
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup_package_pair_c
+ {\cr
+ \pack_combinations_flush_captions
+ \egroup}
+
+\def\pack_combinations_save_caption
+ {\global\setbox\b_pack_combinations_captions\hpack
+ {\hpack{\box\b_pack_combinations_caption}%
+ \unhbox\b_pack_combinations_captions}}
+
+\def\pack_combinations_flush_captions
+ {\noalign
+ {\ifdim\ht\b_pack_combinations_captions>\zeropoint
+ \nointerlineskip % indeed
+ \combinationparameter\c!inbetween
+ \global\c_pack_combinations_x\c_pack_combinations_max
+ \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes
+ \else
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop
+ \fi}%
+ \pack_combinations_flush_captions_indeed
+ \crcr}
+
+\def\pack_combinations_flush_captions_yes
+ {\global\setbox\b_pack_combinations_captions\hpack
+ {\unhbox\b_pack_combinations_captions
+ \global\setbox\b_pack_combinations_temp\lastbox}%
+ \box\b_pack_combinations_temp
+ \global\advance\c_pack_combinations_x\minusone\relax
+ \ifnum\c_pack_combinations_x>\zerocount
+ \expandafter\pack_combinations_flush_captions_yes_followup
+ \else
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \fi}
+
+\let\pack_combinations_flush_captions_nop\donothing
+
+\def\pack_combinations_flush_captions_yes_followup
+ {\aligntab
+ \aligntab
+ \aligntab
+ \aligntab
+ \pack_combinations_flush_captions_indeed}
+
+%D \macros
+%D {startfloatcombination}
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \placefigure
+%D [left,none]
+%D {}
+%D {\startfloatcombination[2*2]
+%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]}
+%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]}
+%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]}
+%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]}
+%D \stopfloatcombination}
+%D
+%D \input tufte
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\startfloatcombination
+ {\dodoubleempty\pack_combinations_start_float}
+
+\let\stopfloatcombination\relax
+
+\def\pack_combinations_start_float[#1][#2]%
+ {\vbox\bgroup
+ %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
+ \postcenterfloatmethod\zerocount
+ \forcelocalfloats
+ \unexpanded\def\stopfloatcombination{\pack_combinations_stop_float{#1}}}
+
+\def\pack_combinations_stop_float#1%
+ {\scratchtoks\emptytoks
+ \dorecurse\noflocalfloats
+ {\appendetoks{\noexpand\getlocalfloat{\recurselevel}}{}\to\scratchtoks}% brrr
+ \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination
+ \resetlocalfloats
+ \egroup}
+
+%D \macros
+%D {definepairedbox, setuppairedbox, placepairedbox}
+%D
+%D Paired boxes, formally called legends, but from now on a
+%D legend is just an instance, are primarily meant for
+%D typesetting some text alongside an illustration. Although
+%D there is quite some variation possible, the functionality is
+%D kept simple, if only because in most cases such pairs are
+%D typeset sober.
+%D
+%D The location specification accepts a pair, where the first
+%D keyword specifies the arrangement, and the second one the
+%D alignment. The first key of the location pair is one of
+%D \type {left}, \type {right}, \type {top} or \type {bottom},
+%D while the second key can also be \type {middle}.
+%D
+%D The first box is just collected in an horizontal box, but
+%D the second one is a vertical box that gets passed the
+%D bodyfont and alignment settings.
+
+%D In many cases the table builders can be used instead, but as
+%D this mechanism is a traditional \CONTEXT\ one we keep it
+%D around.
+
+%D \macros
+%D {setuplegend, placelegend}
+%D
+%D It makes sense to typeset a legend to a figure in \TEX\
+%D and not in a drawing package. The macro \type {\placelegend}
+%D combines a figure (or something else) and its legend. This
+%D command is just a paired box.
+%D
+%D The legend is placed according to \type {location}, being
+%D \type {bottom} or \type {right}. The macro macro is used as
+%D follows.
+%D
+%D \starttyping
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulate[|l|l|l|l|]
+%D \NC 1 \NC head \NC 3 \NC tail \NC \NR
+%D \NC 2 \NC legs \NC \NC \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {head \par legs \par tail}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2,width=.8\hsize]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \def\MytTestTwo#1#2%
+%D {\placefigure
+%D {whow}
+%D {\placelegend[location={#1,#2}]
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}}
+%D
+%D \def\MytTestOne#1{\processcommalist[left,right,top,bottom]{\MytTestTwo{#1}}}
+%D
+%D \processcommalist[left,right,top,bottom,middle]\MytTestOne
+%D \stoptyping
+%D
+%D More structure is also possible (the order matters!):
+%D
+%D \starttyping
+%D \startplacefigure[title=whow]
+%D \startplacelegend[location={bottom,middle},color=red]
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D \starttabulate[|l|l|]
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate
+%D \stopcaption
+%D \stopplacelegend
+%D \stopplacefigure
+%D \stoptyping
+
+% todo: natural size
+
+\newsystemmode{pairedbox}
+
+\appendtoks
+ \global\resetsystemmode{pairedbox}%
+\to \everyinsidefloat
+
+\installcorenamespace {pairedbox}
+
+\installcommandhandler \??pairedbox {pairedbox} \??pairedbox
+
+\setuppairedbox
+ [\c!n=1,
+ \c!distance=\bodyfontsize,
+ %\c!before=,
+ %\c!after=,
+ %\c!color=,
+ %\c!style=,
+ \c!inbetween={\blank[\v!medium]},
+ \c!width=\hsize,
+ \c!height=\vsize,
+ \c!maxwidth=\textwidth, % \makeupwidth,
+ \c!maxheight=\textheight, % \makeupheight,
+ %\c!bodyfont=,
+ %\c!align=,
+ \c!location=\v!bottom]
+
+% watch the hsize/vsize tricks
+
+\newbox \b_pack_pairedboxes_first
+\newbox \b_pack_pairedboxes_second
+\newdimen\s_pack_pairedboxes_size
+
+\appendtoks
+ \setuevalue{\e!setup\currentpairedbox\e!endsetup}{\setuppairedbox [\currentpairedbox]}%
+ \setuevalue{\e!place\currentpairedbox }{\placepairedbox [\currentpairedbox]}% one argument is mandate anyway
+ \setuevalue{\e!start\e!place\currentpairedbox }{\startplacepairedbox[\currentpairedbox]}% one argument is mandate anyway
+ \setuevalue{\e!stop\e!place \currentpairedbox }{\stopplacepairedbox }%
+\to \everydefinepairedbox
+
+\unexpanded\def\placepairedbox[#1]%
+ {\bgroup
+ \edef\currentpairedbox{#1}%
+ \doifelsenextoptionalcs\pack_pairedboxes_place\pack_pairedboxes_place_indeed}
+
+\unexpanded\def\startplacepairedbox[#1]%
+ {\bgroup
+ \edef\currentpairedbox{#1}%
+ \doifelsenextoptionalcs\pack_pairedboxes_place\pack_pairedboxes_place_indeed}
+
+\unexpanded\def\stopplacepairedbox
+ {}
+
+\def\pack_pairedboxes_place[#1]%
+ {\setupcurrentpairedbox[#1]%
+ \pack_pairedboxes_place_indeed}
+
+\def\pack_pairedboxes_place_indeed
+ {\pairedboxparameter\c!before
+ \bgroup
+ \edef\p_location{\pairedboxparameter\c!location}%
+ \edef\p_n {\pairedboxparameter\c!n}%
+ %
+ \let\startcontent\pack_common_content_start
+ \let\stopcontent \pack_common_content_stop
+ \let\startcaption\pack_common_caption_start
+ \let\stopcaption \pack_common_caption_stop
+ %
+ \global\setsystemmode{pairedbox}%
+ \pack_pairedboxes_before
+ \assumelongusagecs\pack_pairedboxes_first_pickup}
+
+\def\pack_pairedboxes_first_pickup
+ {\dowithnextboxcs\pack_pairedboxes_first\hbox
+ \bgroup
+ \let\next=}
+
+\def\pack_pairedboxes_first
+ {\pack_pairedboxes_between
+ \assumelongusagecs\pack_pairedboxes_second_pickup}
+
+\def\pack_pairedboxes_second_pickup
+ {\dowithnextboxcs\pack_pairedboxes_second\vbox
+ \bgroup
+ \pack_pairedboxes_inside_second
+ \let\next=}
+
+\def\pack_pairedboxes_second
+ {\pack_pairedboxes_after
+ \egroup
+ \pairedboxparameter\c!after
+ \egroup}
+
+\newconditional\c_pack_pairedboxes_horizontal \settrue\c_pack_pairedboxes_horizontal
+
+\installcorenamespace{pairedboxnature}
+\installcorenamespace{pairedboxalign}
+
+\let\pack_pairedboxes_fill_top \relax
+\let\pack_pairedboxes_fill_bottom\relax
+
+\setvalue{\??pairedboxnature\v!left}%
+ {\settrue\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_left}
+
+\setvalue{\??pairedboxnature\v!right}%
+ {\settrue\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_right}
+
+\setvalue{\??pairedboxnature\v!top}%
+ {\setfalse\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_fill_top\relax
+ \let\pack_pairedboxes_fill_bottom\vss
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_top}
+
+\setvalue{\??pairedboxnature\v!bottom}%
+ {\setfalse\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_fill_top\vss
+ \let\pack_pairedboxes_fill_bottom\relax
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_bottom}
+
+\def\pack_pairedboxes_flush_left
+ {\box\b_pack_pairedboxes_second
+ \kern\pairedboxparameter\c!distance
+ \box\b_pack_pairedboxes_first}
+
+\def\pack_pairedboxes_flush_right
+ {\box\b_pack_pairedboxes_first
+ \kern\pairedboxparameter\c!distance
+ \box\b_pack_pairedboxes_second}
+
+\def\pack_pairedboxes_flush_top
+ {\box\b_pack_pairedboxes_second
+ \endgraf
+ \nointerlineskip
+ \pairedboxparameter\c!inbetween
+ \box\b_pack_pairedboxes_first}
+
+\def\pack_pairedboxes_flush_bottom
+ {\box\b_pack_pairedboxes_first
+ \endgraf
+ \nointerlineskip
+ \pairedboxparameter\c!inbetween
+ \box\b_pack_pairedboxes_second}
+
+\setvalue{\??pairedboxalign \v!left}% 0
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\hss
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign \v!right}% 1
+ {\let\pack_pairedboxes_align_l\hss
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign \v!high}% 2
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\vss}
+
+\setvalue{\??pairedboxalign \v!low}% 3
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\vss
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign\v!middle}% 4
+ {\let\pack_pairedboxes_align_l\hss
+ \let\pack_pairedboxes_align_r\hss
+ \let\pack_pairedboxes_align_t\vss
+ \let\pack_pairedboxes_align_b\vss}
+
+\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }}
+\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}}
+
+\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}}
+\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}}
+
+\def\pack_pairedboxes_before
+ {\ifx\p_location\empty
+ \csname\??pairedboxnature\v!left \endcsname
+ \csname\??pairedboxalign \v!middle\endcsname
+ \else
+ \getfromcommacommand[\p_location][1]%
+ \csname\??pairedboxnature
+ \ifcsname\??pairedboxnature\commalistelement\endcsname\commalistelement\else\v!left\fi
+ \endcsname
+ \getfromcommacommand[\p_location][2]%
+ \csname\??pairedboxalign
+ \ifcsname\??pairedboxalign\commalistelement\endcsname\commalistelement\else\v!middle\fi
+ \endcsname
+ \fi}
+
+\def\pack_pairedboxes_between
+ {\usebodyfontparameter\pairedboxparameter
+ \setbox\b_pack_pairedboxes_first\box\nextbox
+ \ifconditional\c_pack_pairedboxes_horizontal
+ \pack_pairedboxes_between_horizontal
+ \else
+ \pack_pairedboxes_between_vertical
+ \fi
+ \ifnum\p_n>\plusone
+ \setrigidcolumnhsize\hsize{\pairedboxparameter\c!distance}\p_n
+ \fi}
+
+% \def\pack_pairedboxes_between_horizontal
+% {\setlocalhsize
+% \hsize\wd\b_pack_pairedboxes_first % trick
+% \hsize\pairedboxparameter\c!width % can be \hsize
+% \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\pairedboxparameter\c!distance\relax
+% \ifdim\dimexpr\hsize+\scratchdimen\relax>\pairedboxparameter\c!maxwidth\relax
+% \hsize\dimexpr\pairedboxparameter\c!maxwidth-\scratchdimen\relax
+% \fi}
+
+\def\pack_pairedboxes_between_horizontal
+ {\scratchdistance\pairedboxparameter\c!distance
+ \scratchwidth\pairedboxparameter\c!maxwidth\relax
+ \setlocalhsize
+ \hsize\dimexpr\availablehsize-\wd\b_pack_pairedboxes_first-\scratchdistance\relax
+ \hsize\pairedboxparameter\c!width\relax % can be \hsize
+ \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\scratchdistance\relax
+ \ifdim\dimexpr\hsize+\scratchdimen\relax>\scratchwidth
+ \hsize\dimexpr\scratchwidth-\scratchdimen\relax
+ \fi}
+
+\def\pack_pairedboxes_between_vertical
+ {\scratchwidth\pairedboxparameter\c!maxwidth\relax
+ \hsize\wd\b_pack_pairedboxes_first
+ \hsize\pairedboxparameter\c!width\relax % can be \hsize
+ \ifdim\hsize>\scratchwidth\relax
+ \hsize\scratchwidth
+ \fi}
+
+\def\pack_pairedboxes_after
+ {\setbox\b_pack_pairedboxes_second\vpack
+ {\ifnum\p_n>\plusone
+ \rigidcolumnbalance\nextbox
+ \else
+ \box\nextbox
+ \fi}%
+ \ifconditional\c_pack_pairedboxes_horizontal
+ \pack_pairedboxes_pack_horizontal
+ \else
+ \pack_pairedboxes_pack_vertical
+ \fi}
+
+\def\pack_pairedboxes_pack_horizontal
+ {\dontleavehmode\hbox\bgroup
+ \forgetall
+ \s_pack_pairedboxes_size\ht
+ \ifdim\ht\b_pack_pairedboxes_first>\ht\b_pack_pairedboxes_second
+ \b_pack_pairedboxes_first
+ \else
+ \b_pack_pairedboxes_second
+ \fi
+ \vsize\s_pack_pairedboxes_size
+ \ifdim\s_pack_pairedboxes_size<\pairedboxparameter\c!height\relax % can be \vsize
+ \s_pack_pairedboxes_size\pairedboxparameter\c!height
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax
+ \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight
+ \fi
+ \pack_pairedbox_valign\b_pack_pairedboxes_first
+ \pack_pairedbox_valign\b_pack_pairedboxes_second
+ \pack_pairedboxes_flush
+ \egroup}
+
+\def\pack_pairedboxes_pack_vertical
+ {\dontleavehmode\vpack\bgroup
+ \forgetall
+ \s_pack_pairedboxes_size\wd
+ \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second
+ \b_pack_pairedboxes_first
+ \else
+ \b_pack_pairedboxes_second
+ \fi
+ \pack_pairedbox_halign\b_pack_pairedboxes_first
+ \pack_pairedbox_halign\b_pack_pairedboxes_second
+ \s_pack_pairedboxes_size\ht\b_pack_pairedboxes_second
+ \vsize\s_pack_pairedboxes_size
+ \ifdim\ht\b_pack_pairedboxes_second<\pairedboxparameter\c!height\relax % can be \vsize
+ \s_pack_pairedboxes_size\pairedboxparameter\c!height\relax % \relax needed
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax % todo: totale hoogte
+ \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second
+ \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size
+ {\pack_pairedboxes_fill_top
+ \box\b_pack_pairedboxes_second
+ \pack_pairedboxes_fill_bottom}% \kern\zeropoint
+ \fi
+ \pack_pairedboxes_flush
+ \egroup}
+
+\def\pack_pairedboxes_inside_second
+ {\forgetall
+ \setupalign[\pairedboxparameter\c!align]%
+ \usepairedboxstyleandcolor\c!style\c!color
+ \tolerantTABLEbreaktrue % hm.
+ \blank[\v!disable]% use fast one
+ \everypar{\begstrut}} % also flushers here (see bTABLE)
+
+\definepairedbox[\v!legend]
+
+\unexpanded\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox}
+\unexpanded\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox}
+
+\def\pack_topofeachother_one{\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox}
+\def\pack_sidebyside_one {\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox}
+
+\def\pack_topofeachother_two{\setbox\scratchboxtwo\box\nextbox
+ \halign{\hss\alignmark\alignmark\hss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}%
+ \egroup\egroup}
+\def\pack_sidebyside_two {\setbox\scratchboxtwo\box\nextbox
+ \valign{\vss\alignmark\alignmark\vss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}%
+ \egroup\egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv
new file mode 100644
index 00000000000..ffd0251d5ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv
@@ -0,0 +1,163 @@
+%D \module
+%D [ file=pack-cut, % comes from core-vis/trac-vis
+%D version=1996.06.01,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Cut boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+%D \macros
+%D {makecutbox, cuthbox, cutvbox, cutvtop}
+%D
+%D Although mainly used for marking the page, these macros can
+%D also serve local use.
+%D
+%D \startbuffer
+%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This marked \type{\vbox} shows up as:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D The alternative macros are used as:
+%D
+%D \startbuffer
+%D \cuthbox{a made cut box}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typeset as:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D By setting the next macros one can influence the length of
+%D the marks as well as the horizontal and vertical divisions.
+
+\newdimen\d_pack_cutmarks_width
+\newdimen\d_pack_cutmarks_height
+\newdimen\d_pack_cutmarks_depth
+
+\newcount\horizontalcutmarks \horizontalcutmarks \plustwo
+\newcount\verticalcutmarks \verticalcutmarks \plustwo
+\newcount\cutmarkoffset \cutmarkoffset \plusone
+
+\let\cutmarksymbol \relax
+\let\cutmarktoptext \empty
+\let\cutmarkbottomtext \empty
+\let\cutmarkhoffset \empty
+\let\cutmarkvoffset \empty
+\def\cutmarklength {2\bodyfontsize}
+\def\cutmarkrulethickness{\onepoint}
+
+\unexpanded\def\horizontalcuts
+ {\normalhbox to \d_pack_cutmarks_width
+ {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\normalhfill}%
+ \unskip}}
+
+\unexpanded\def\verticalcuts
+ {\normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ {\hsize\cutmarklength
+ \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\normalvfill}%
+ \unskip}}
+
+\unexpanded\def\baselinecuts
+ {\ifdim\d_pack_cutmarks_depth>\zeropoint
+ \normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ {\hsize\dimexpr\cutmarklength/2\relax
+ \normalvskip\zeropoint\s!plus\d_pack_cutmarks_height
+ \vrule\s!height\cutmarkrulethickness\s!width\hsize
+ \normalvskip\zeropoint\s!plus\d_pack_cutmarks_depth}%
+ \fi}
+
+\unexpanded\def\cutmarksymbols#1%
+ {\normalhbox to \d_pack_cutmarks_width
+ {\setbox\scratchbox\normalhbox to \cutmarklength
+ {\normalhss\infofont\cutmarksymbol\normalhss}%
+ \normalhss
+ \normalvbox to \cutmarklength
+ {\scratchdimen\dimexpr\cutmarklength/2\relax
+ \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
+ \normalvss
+ \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}}
+
+\unexpanded\def\makecutbox#1%
+ {\bgroup
+ \d_pack_cutmarks_height\ht#1%
+ \d_pack_cutmarks_depth \dp#1%
+ \d_pack_cutmarks_width \wd#1%
+ \setbox#1\normalhbox
+ {\dontcomplain
+ \forgetall
+ \boxmaxdepth\maxdimen
+ \offinterlineskip
+ \scratchdimen\dimexpr\cutmarklength/2\relax
+ \hsize\d_pack_cutmarks_width
+ \setbox\scratchbox\normalvbox
+ {\setbox\scratchbox\normalhbox{\horizontalcuts}%
+ \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+ \tlap{\copy\scratchbox\normalvskip\scratchskip}%
+ \hpack to \d_pack_cutmarks_width
+ {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
+ \setbox\scratchbox\normalhbox{\verticalcuts}%
+ \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \ifdim\d_pack_cutmarks_depth=\zeropoint
+ \normalhfill
+ \else
+ \bgroup
+ \setbox\scratchbox\normalhbox{\baselinecuts}%
+ \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \normalhfill
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}%
+ \egroup
+ \fi
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
+ \blap{\normalvskip\scratchskip\copy\scratchbox}}%
+ \ht\scratchbox\d_pack_cutmarks_height
+ \dp\scratchbox\d_pack_cutmarks_depth
+ \wd\scratchbox\zeropoint
+ \startcolor[\defaulttextcolor]%
+ \box\scratchbox
+ \ifx\cutmarksymbol\relax \else
+ \setbox\scratchbox\normalvbox
+ {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+ \vskip-\dimexpr\scratchskip+\cutmarklength\relax
+ \normalhbox{\cutmarksymbols\cutmarktoptext}%
+ \vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax
+ \normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
+ \ht\scratchbox\d_pack_cutmarks_height
+ \dp\scratchbox\d_pack_cutmarks_depth
+ \wd\scratchbox\zeropoint
+ \box\scratchbox
+ \fi
+ \stopcolor
+ \box#1}%
+ \wd#1\d_pack_cutmarks_width
+ \ht#1\d_pack_cutmarks_height
+ \dp#1\d_pack_cutmarks_depth
+ \egroup}
+
+\unexpanded\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox}
+\unexpanded\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox}
+\unexpanded\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-fen.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-fen.mkiv
new file mode 100644
index 00000000000..7bc8211440c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-fen.mkiv
@@ -0,0 +1,97 @@
+%D \module
+%D [ file=pack-fen,
+%D version=2011.07.21,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle= Fences for Ruled Content,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Fences for Ruled Content}
+
+%D \startbuffer
+%D \useMPlibrary[meta-imp-hooks.mkiv]
+%D
+%D \framed[frame=off,bottomframe=righthook]{Bottom right hook}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+
+\unprotect
+
+\def\installleftframerenderer#1#2%
+ {\setvalue{\??framedleft\v!on#1}{\whateverleftframe{#2}}%
+ \expandafter\let\csname\??framedleft\v!off#1\expandafter\endcsname\csname\??framedleft\v!on#1\endcsname}
+
+\def\installrightframerenderer#1#2%
+ {\setvalue{\??framedright\v!on#1}{\whateverrightframe{#2}}%
+ \expandafter\let\csname\??framedright\v!off#1\expandafter\endcsname\csname\??framedright\v!on#1\endcsname}
+
+\def\installtopframerenderer#1#2%
+ {\setvalue{\??framedtop\v!on#1}{\whatevertopframe{#2}}%
+ \expandafter\let\csname\??framedtop\v!off#1\expandafter\endcsname\csname\??framedtop\v!on#1\endcsname}
+
+\def\installbottomframerenderer#1#2%
+ {\setvalue{\??framedbottom\v!on#1}{\whateverbottomframe{#2}}%
+ \expandafter\let\csname\??framedbottom\v!off#1\expandafter\endcsname\csname\??framedbottom\v!on#1\endcsname}
+
+\ifdefined \pack_framed_overlay_initialize_indeed
+
+ \let\setinstalledframedimensions\pack_framed_overlay_initialize_indeed
+
+\else
+
+ \def\setinstalledframedimensions
+ {\d_overlay_width \frameddimenwd
+ \d_overlay_height \dimexpr\frameddimenht+\frameddimendp\relax
+ \d_overlay_depth \frameddimendp
+ \d_overlay_linewidth \ruledlinewidth
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}%
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}}
+
+\fi
+
+\newbox\b_framed_rendered
+
+\def\whateverleftframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\vpack to \d_overlay_height{\vss#1\vss}%
+ \setbox\b_framed_rendered\hpack to \zeropoint{\box\b_framed_rendered\hss}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\def\whateverrightframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\vpack to \d_overlay_height{\vss#1\vss}%
+ \setbox\b_framed_rendered\hpack to \zeropoint{\hss\box\b_framed_rendered}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\def\whatevertopframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\hpack to \d_overlay_width{\hss#1\hss}%
+ \setbox\b_framed_rendered\vpack to \zeropoint{\box\b_framed_rendered\vss}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered
+ \nointerlineskip}
+
+\def\whateverbottomframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\hpack to \d_overlay_width{\hss#1\hss}%
+ \setbox\b_framed_rendered\vpack to \zeropoint{\vss\box\b_framed_rendered}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv
new file mode 100644
index 00000000000..61ed1e64b75
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv
@@ -0,0 +1,749 @@
+%D \module
+%D [ file=pack-lyr,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Layers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Layers}
+
+% todo : first / last / next / +... => page key
+% test on left/right box when no doublesided option given
+% use \ifcsname instead of doifvalue
+
+\unprotect
+
+% When being backgrounds layers get the background offset
+% displacement. Should be an option, on by default
+% (compatibility).
+
+%D The layering mechanism implemented here is independent of
+%D the output routine, but future extensions may depend on a
+%D more close cooperation.
+
+%D First we overload a macro from \type {pack-rul}. From now on
+%D we accept a (optional) argument: the specific layer it
+%D will go in. This means that we can move an overlay from one
+%D background to the other using the dimensions of the parent.
+
+\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi
+
+\unexpanded\def\defineoverlay
+ {\dotripleempty\pack_framed_define_overlay}
+
+\def\pack_framed_define_overlay[#1][#2][#3]% overlay [layer] content
+ {\ifthirdargument
+ %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}%
+ \else
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
+ \fi
+ \processcommalist[#1]\pack_framed_define_overlay_indeed}
+
+%D We use the command handler code. The previous, more direct parameter
+%D handling was 25\% faster when no parameters were passed when adding
+%D content to a layer. However, when we pass for instance a preset, the
+%D new methos is some 10\% faster and it happens that in most cases we
+%D do pass some parameters. It would be interesting to see if we can push
+%D the preset in between the regular chain but it could also lead to
+%D unwanted side effects when nesting layer placement.
+
+\installcorenamespace{layer}
+\installcorenamespace{layerbox}
+\installcorenamespace{layerpreset}
+\installcorenamespace{layerposition} % brr, unreadable
+
+%D \macros
+%D {definelayer,setuplayer}
+%D
+%D Each layer gets its own (global) box. This also means that
+%D the data that goes into a layer, is typeset immediately.
+%D Each layer automatically gets an associated overlay,
+%D which can be used in any background assignment.
+%D
+%D After a layer is defined, you can change its
+%D characteristics.
+
+\installcommandhandler \??layer {layer} \??layer
+
+\setuplayer
+ [\c!state=\v!start,
+ %\c!doublesided=,
+ %\c!preset=,
+ %\c!option=,
+ %\c!corner=,
+ %\c!page=,
+ %\c!rotation=, % geen 0 !
+ \c!direction=\v!normal,
+ \c!position=\v!no,
+ \c!method=\v!overlay,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!line=0,
+ \c!column=0,
+ \c!width=\wd\nextbox, % don't change this globally
+ \c!height=\ht\nextbox, % don't change this globally
+ \c!offset=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!location=rb,
+ \c!sx=1,
+ \c!sy=1,
+ \c!region=\layeranchor]
+
+\def\layeranchor{\currentlayer:\the\realpageno}
+
+\let\p_pack_layers_doublesided\empty
+\let\p_pack_layers_state \empty
+\let\p_pack_layers_option \empty
+\let\p_pack_layers_method \empty
+\let\p_pack_layers_preset \empty
+\let\p_pack_layers_rotation \empty
+\let\p_pack_layers_position \empty
+\let\p_pack_layers_hoffset \empty
+\let\p_pack_layers_voffset \empty
+\let\p_pack_layers_offset \empty
+\let\p_pack_layers_dx \empty
+\let\p_pack_layers_dy \empty
+\let\p_pack_layers_sx \empty
+\let\p_pack_layers_sy \empty
+\let\p_pack_layers_x \empty
+\let\p_pack_layers_y \empty
+\let\p_pack_layers_corner \empty
+\let\p_pack_layers_location \empty
+\let\p_pack_layers_line \empty
+\let\p_pack_layers_column \empty
+\let\p_pack_layers_width \empty
+\let\p_pack_layers_height \empty
+\let\p_pack_layers_direction \empty
+\let\p_pack_layers_region \empty
+
+\let\m_pack_layers_page \empty
+\let\m_pack_layers_target \empty
+\let\m_pack_layers_region \empty
+\let\m_pack_layers_anchor \empty
+
+\newconditional\c_pack_layers_repeated
+\newconditional\c_pack_layers_trace
+\newcount \c_pack_layers_current_data
+
+\newbox\b_layers
+
+\newdimen\d_pack_layers_x_size
+\newdimen\d_pack_layers_y_size
+\newdimen\d_pack_layers_x_offset
+\newdimen\d_pack_layers_y_offset
+\newdimen\d_pack_layers_x_position
+\newdimen\d_pack_layers_y_position
+
+\newdimen\layerwidth
+\newdimen\layerheight
+
+\let\lastlayerxpos\!!zeropoint
+\let\lastlayerypos\!!zeropoint
+\let\lastlayerwd \!!zeropoint
+\let\lastlayerht \!!zeropoint
+\let\lastlayerdp \!!zeropoint
+
+\appendtoks
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \relateparameterhandlers{layer}{\v!left \currentlayer}{layer}\currentlayer % permits left*
+ \relateparameterhandlers{layer}{\v!right\currentlayer}{layer}\currentlayer % permits right*
+ \pack_layers_preset_box{\v!left \currentlayer}%
+ \pack_layers_preset_box{\v!right\currentlayer}%
+ \fi
+ \pack_layers_preset_box\currentlayer
+ \normalexpanded{\defineoverlay[\currentlayer][\noexpand\composedlayer{\currentlayer}]}%
+\to \everydefinelayer
+
+\def\pack_layers_preset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
+ \resetlayer[#1]%
+ \else
+ \expandafter\newbox\csname\??layerbox#1\endcsname
+ \fi}
+
+%D \macros
+%D {resetlayer}
+%D
+%D This macro hardly needs an explanation (but is seldom
+%D needed anyway).
+
+\def\pack_layers_reset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
+ %\global\setbox\csname\??layerbox#1\endcsname\emptybox
+ \global\setbox\lastnamedcs\emptybox
+ \fi}
+
+\def\resetlayer[#1]%
+ {\pack_layers_reset_box{#1}%
+ \pack_layers_reset_box{\v!left #1}%
+ \pack_layers_reset_box{\v!right#1}%
+ \pack_layers_reset_box{#1:\the\realpageno}}
+
+%D \macros
+%D {setlayer}
+%D
+%D Data is moved into a layer with the following macro. When
+%D \type {position} is set, relative positioning is used, with
+%D the current point as reference point. Otherwise the topleft
+%D corner is used as reference point.
+%D
+%D \starttyping
+%D \setlayer [identifier] [optional parameters] {data}
+%D \stoptyping
+
+\def\setcurrentlayerdimensions
+ {\dodoubleempty\pack_layers_set_current_dimensions}
+
+\def\pack_layers_set_current_dimensions[#1][#2]% name left|right
+ {\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
+ \edef\currentlayerheight{\thelayerheight{#2#1}}}
+
+\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
+\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
+
+\unexpanded\def\setlayer
+ {\dotripleempty\pack_layers_set}
+
+\def\pack_layers_set[#1][#2][#3]% #4 == box do \fi is ok
+ {\bgroup
+ \edef\currentlayer{#1}%
+ \edef\p_pack_layers_state{\layerparameter\c!state}%
+ \ifx\p_pack_layers_state\v!stop
+ \dowithnextboxcs\egroup\hbox % no pack ?
+ \else\ifthirdargument
+ \pack_layers_set_indeed[#1][#2][#3]%
+ \else
+ \doifelseassignment{#2}
+ {\pack_layers_set_indeed[#1][][#2]}%
+ {\pack_layers_set_indeed[#1][#2][]}%
+ \fi\fi}
+
+\def\pack_layers_set_indeed[#1][#2][#3]% #2 = links/rechts
+ {\page_backgrounds_recalculate % brrr
+ \global\advance\c_pack_layers_current_data\plusone
+ \forgetall
+ \dontcomplain
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
+ \traceboxplacementtrue
+ \fi
+ \edef\m_pack_layers_target{#2}%
+ \dowithnextbox{\pack_layers_set_finish{#3}}\hbox}
+
+\def\pack_layers_set_finish#1%
+ {\ifcsname\??layerbox\currentlayer\endcsname % can move up
+ \ifx\m_pack_layers_target\v!even
+ \ifodd\realpageno
+ % discard nextbox
+ \else
+ \let\m_pack_layers_target\v!left
+ \pack_layers_set_content{#1}%
+ \fi
+ \else\ifx\m_pack_layers_target\v!odd
+ \ifodd\realpageno
+ \let\m_pack_layers_target\v!right
+ \pack_layers_set_content{#1}%
+ \else
+ % discard nextbox
+ \fi
+ \else
+ \pack_layers_set_content{#1}%
+ \fi\fi
+ \else
+ \writestatus{layer}{unknown layer \currentlayer}%
+ \fi
+ \egroup}
+
+% todo left/right
+
+% todo: get position data in one go
+
+\def\pack_layers_set_last_position_yes % target: left|right
+ {% this will become one call
+ \edef\m_pack_layers_anchor{\??layerposition\the\c_pack_layers_current_data}%
+ \edef\m_pack_layers_page {\MPp\m_pack_layers_anchor}%
+ \edef\m_pack_layers_region{\MPr\m_pack_layers_anchor}%
+ \d_pack_layers_x_position \dimexpr-\MPx\m_pack_layers_region+\MPx\m_pack_layers_anchor\relax
+ \d_pack_layers_y_position \dimexpr \MPy\m_pack_layers_region-\MPy\m_pack_layers_anchor+\MPh\m_pack_layers_region\relax
+ \xdef\lastlayerxpos{\the\d_pack_layers_x_position}%
+ \xdef\lastlayerypos{\the\d_pack_layers_y_position}%
+ % \writestatus{region}{\m_pack_layers_region -> (\MPx\m_pack_layers_region,\MPy\m_pack_layers_region)}%
+ % \writestatus{self} {\m_pack_layers_anchor -> (\MPx\m_pack_layers_anchor,\MPy\m_pack_layers_anchor)}%
+ % \writestatus{delta} {(\lastlayerxpos,\lastlayerypos)}%
+ % \begingroup
+ % \edef\currentlayer{\currentlayer\m_pack_layers_page}%
+ % \global\letlayerparameter\c!position\v!yes
+ % \endgroup
+ \global\letlayerparameter\c!state\v!start % needed ?
+ \setbox\b_layers\vpack to \d_pack_layers_y_size
+ {\hpack to \d_pack_layers_x_size
+ {\xypos\m_pack_layers_anchor\hss}%
+ \vss}}
+
+\def\pack_layers_set_last_position_nop
+ {\setbox\b_layers\emptybox
+ \globallet\lastlayerxpos\!!zeropoint
+ \globallet\lastlayerypos\!!zeropoint
+ \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions
+ \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions
+ \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
+ \edef\m_pack_layers_page{\layerparameter\c!page}}
+
+\unexpanded\def\definelayerpreset
+ {\dodoubleargument\pack_layers_define_preset}
+
+\def\pack_layers_define_preset[#1][#2]%
+ {\doifelseassignment{#2}
+ {\setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}}
+ {\setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}}}
+
+\def\pack_layers_set_content#1%
+ {\layerwidth \layerparameter\c!width % global (local later)
+ \layerheight\layerparameter\c!height % global (local later)
+ \d_pack_layers_x_size\layerwidth
+ \d_pack_layers_y_size\layerheight
+ %
+ \setupcurrentlayer[#1]% preroll
+ %
+ \edef\p_pack_layers_preset {\layerparameter\c!preset }%
+ %
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \lastnamedcs
+ \setupcurrentlayer[#1]% postroll
+ \fi
+ %
+ \edef\p_pack_layers_rotation {\layerparameter\c!rotation }%
+ \edef\p_pack_layers_position {\layerparameter\c!position }%
+ \edef\p_pack_layers_hoffset {\layerparameter\c!hoffset }%
+ \edef\p_pack_layers_voffset {\layerparameter\c!voffset }%
+ \edef\p_pack_layers_offset {\layerparameter\c!offset }%
+ \edef\p_pack_layers_dx {\layerparameter\c!dx }%
+ \edef\p_pack_layers_dy {\layerparameter\c!dy }%
+ \edef\p_pack_layers_sx {\layerparameter\c!sx }%
+ \edef\p_pack_layers_sy {\layerparameter\c!sy }%
+ \edef\p_pack_layers_x {\layerparameter\c!x }%
+ \edef\p_pack_layers_y {\layerparameter\c!y }%
+ \edef\p_pack_layers_corner {\layerparameter\c!corner }%
+ \edef\p_pack_layers_location {\layerparameter\c!location }%
+ \edef\p_pack_layers_line {\layerparameter\c!line }%
+ \edef\p_pack_layers_column {\layerparameter\c!column }%
+ \edef\p_pack_layers_width {\layerparameter\c!width }% local ones
+ \edef\p_pack_layers_height {\layerparameter\c!height }% local ones
+ \edef\p_pack_layers_direction{\layerparameter\c!direction}%
+ %
+ \ifx\p_pack_layers_position\v!overlay
+ \let\p_pack_layers_width \zeropoint
+ \let\p_pack_layers_height \zeropoint
+ \let\p_pack_layers_position\v!yes
+ \fi
+ \ifx\p_pack_layers_rotation\empty \else
+ % use direct call
+ \setbox\nextbox\hpack
+ {\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_offset\p_pack_layers_sx\dimexpr
+ \ifx\p_pack_layers_hoffset\v!max\d_pack_layers_x_size\else\p_pack_layers_hoffset\fi+\p_pack_layers_offset+\p_pack_layers_dx
+ \relax
+ \d_pack_layers_y_offset\p_pack_layers_sy\dimexpr
+ \ifx\p_pack_layers_voffset\v!max\d_pack_layers_y_size\else\p_pack_layers_voffset\fi+\p_pack_layers_offset+\p_pack_layers_dy
+ \relax
+ \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax
+ \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax
+ \ifx\p_pack_layers_position\v!yes
+ \pack_layers_set_last_position_yes
+ \else
+ \pack_layers_set_last_position_nop
+ \fi
+ %
+ \ifx\m_pack_layers_page\empty \else % is expanded
+ \edef\m_pack_layers_page{:\m_pack_layers_page}%
+ \ifcsname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname \else
+ \expandafter\newbox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
+ \fi
+ \fi
+ \chardef\layerpagebox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
+ \ifvoid\layerpagebox
+ \gsetboxllx\layerpagebox\zeropoint
+ \gsetboxlly\layerpagebox\zeropoint
+ \fi
+ \global\setbox\layerpagebox\vpack %to \layerparameter\c!height % new, otherwise no negative y possible
+ {\offinterlineskip
+ \ifvoid\layerpagebox
+ \let\lastlayerwidth \zeropoint
+ \let\lastlayerheight\zeropoint
+ \else
+ \edef\lastlayerwidth {\the\wd\layerpagebox}%
+ \edef\lastlayerheight{\the\ht\layerpagebox}%
+ \ht\layerpagebox\zeropoint
+ \dp\layerpagebox\zeropoint
+ \wd\layerpagebox\zeropoint
+ \ifx\p_pack_layers_direction\v!reverse\else
+ \box\layerpagebox
+ \fi
+ \fi
+ % don't move
+ \xdef\lastlayerwd{\the\wd\nextbox}%
+ \xdef\lastlayerht{\the\ht\nextbox}% % not entirely ok when grid !
+ \xdef\lastlayerdp{\the\dp\nextbox}% % not entirely ok when grid !
+ % this code
+ \ifx\p_pack_layers_location\v!grid
+ \ht\nextbox\strutheight
+ \dp\nextbox\strutdepth
+ \else
+ \setbox\nextbox\hpack
+ {\alignedbox[\p_pack_layers_location]\vpack{\box\nextbox}}%
+ \fi
+ \ifnum\p_pack_layers_line=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_y_position\dimexpr\p_pack_layers_line\lineheight+\topskip-\lineheight-\ht\nextbox\relax
+ \fi
+ \ifnum\p_pack_layers_column=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_x_position\layoutcolumnoffset\p_pack_layers_column\relax
+ \fi
+ \ifx\p_pack_layers_location\v!grid
+ \setbox\nextbox\hpack
+ {\alignedbox[rb]\vpack{\box\nextbox}}%
+ \fi
+ % ll registration
+ \scratchdimen\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
+ \ifdim\scratchdimen<\getboxllx\layerpagebox
+ \gsetboxllx\layerpagebox\scratchdimen
+ \fi
+ \advance\scratchdimen\wd\nextbox
+ \wd\nextbox\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
+ \scratchdimen\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \ifdim\scratchdimen<\getboxlly\layerpagebox
+ \gsetboxlly\layerpagebox\scratchdimen
+ \fi
+ % ll compensation
+ \advance\scratchdimen\dimexpr\ht\nextbox+\dp\nextbox\relax
+ \ht\nextbox\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
+ \dp\nextbox\zeropoint
+ % placement
+ \hsize\p_pack_layers_width
+ \vpack to \p_pack_layers_height \bgroup
+ \smashbox\nextbox
+ \vskip\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \hskip\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
+ \box\nextbox
+ \ifvoid\layerpagebox
+ % already flushed
+ \else
+ % the reverse case % check !
+ \vskip-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \box\layerpagebox
+ \fi
+ \egroup}%
+ % when position is true, the layerbox holds the compensation and needs
+ % to be placed; never change this !
+ \ifvoid\b_layers \else
+ \box\b_layers
+ \fi}
+
+\def\pack_layers_set_bottom_positions
+ {\ifnum\p_pack_layers_line=\zerocount\else % can be < 0
+ \edef\p_pack_layers_line{\the\numexpr-\p_pack_layers_line+\layoutlines+\plusone\relax}% use counter instead ?
+ \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position-\d_pack_layers_y_size
+ \d_pack_layers_y_position-\d_pack_layers_y_position
+ \d_pack_layers_y_offset-\d_pack_layers_y_offset
+ \fi}
+
+\def\pack_layers_set_right_positions
+ {\ifnum\p_pack_layers_column=\zerocount\else % can be < 0
+ \edef\p_pack_layers_column{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}% use counter instead ?
+ \fi
+ \ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position-\d_pack_layers_x_size
+ \d_pack_layers_x_position-\d_pack_layers_x_position
+ \d_pack_layers_x_offset-\d_pack_layers_x_offset
+ \fi}
+
+\def\pack_layers_set_middle_positions
+ {\ifdim\d_pack_layers_x_size>\zeropoint \advance\d_pack_layers_x_position.5\d_pack_layers_x_size \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint \advance\d_pack_layers_y_position.5\d_pack_layers_y_size \fi}
+
+%D Given the task to be accomplished, the previous macro is
+%D not even that complicated. It mainly comes down to skipping
+%D to the right place and placing a box on top of or below the
+%D existing content. In the case of position tracking, another
+%D reference point is chosen.
+
+%D \macros
+%D {doifelselayerdata}
+
+\def\doifelselayerdata#1%
+ {\ifcsname\??layerbox#1\endcsname
+ %\ifvoid\csname\??layerbox#1\endcsname
+ \ifvoid\lastnamedcs
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflayerdataelse\doifelselayerdata
+
+%D \macros
+%D {flushlayer}
+%D
+%D When we flush a layer, we flush both the main one and the
+%D page dependent one (when defined). This feature is more
+%D efficient in \ETEX\ since there testing for an undefined
+%D macro does not takes hash space.
+
+% todo: setups before flush, handy hook
+
+\unexpanded\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
+ {\begingroup
+ \forgetall
+ \edef\currentlayer{#1}%
+ \edef\p_pack_layers_state{\layerparameter\c!state}%
+ \ifx\p_pack_layers_state\v!stop
+ % nothing
+ \else\ifx\p_pack_layers_state\v!next
+ \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up
+ \else\ifx\p_pack_layers_state\v!continue
+ \global\letlayerparameter\c!state\v!repeat % dangerous, stack-built-up
+ \else
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \ifcsname\??layerbox#1\endcsname
+ % we can make a dedicated one for this
+ \doifbothsidesoverruled
+ {\pack_layers_flush_double\v!left }%
+ {\pack_layers_flush_double\v!right}%
+ {\pack_layers_flush_double\v!left }%
+ \else
+ \pack_layers_flush_single
+ \fi
+ \else
+ \pack_layers_flush_single
+ \fi
+ \fi\fi\fi
+ \endgroup}
+
+% \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi
+
+% 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}
+
+\let\pack_layers_top_fill \relax
+\let\pack_layers_bottom_fill\vss
+
+\def\pack_layers_flush_indeed#1#2% quite core, so optimized
+ {\begingroup % already grouped
+ \offinterlineskip
+ \edef\p_pack_layers_preset{\layerparameter\c!preset}%
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \lastnamedcs
+ \fi
+ \edef\p_pack_layers_method{\layerparameter\c!method}%
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
+ \traceboxplacementtrue
+ \fi
+ \ifcase#1\relax
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_position{\layerparameter\c!position}%
+ \ifx\p_pack_layers_position\v!yes
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
+ \ifx\p_pack_layers_repeat\v!yes
+ \settrue\c_pack_layers_repeated
+ \else\ifx\p_pack_layers_state\v!repeat
+ \settrue\c_pack_layers_repeated
+ \else
+ \setfalse\c_pack_layers_repeated
+ \fi\fi
+ \fi
+ \fi
+ \chardef\b_layers\csname\??layerbox#2\endcsname % trick
+ % we need to copy in order to retain the negative offsets for a next
+ % stage of additions, i.e. llx/lly accumulate in repeat mode and the
+ % compensation may differ each flush depending on added content
+ \setbox\nextbox
+ \ifx\p_pack_layers_method\v!fit
+ \pack_layers_positioned_box_yes
+ \else
+ \pack_layers_positioned_box_nop
+ \fi
+ % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
+ \doifelseoverlay{#2}%
+ {\setlayoutcomponentattribute{\v!layer:#2}}%
+ \resetlayoutcomponentattribute
+ % we have conflicting demands: some mechanisms want ll anchoring .. I need to figure this out
+ % an dmaybe we will have 'origin=bottom' or so
+ \setbox\nextbox
+ \ifx\p_pack_layers_option\v!test \ruledvbox \else \vpack \fi \ifx\p_pack_layers_method\v!overlay to \d_overlay_height \fi \layoutcomponentboxattribute
+ {\pack_layers_top_fill
+ \hpack \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
+ {\box\nextbox
+ \hss}%
+ \pack_layers_bottom_fill}%
+ %
+ % \edef\currentlayer{#2}% :\the\realpageno}% local .. check \anchor
+ % \edef\p_pack_layers_position{\layerparameter\c!position}% local
+ \ifx\p_pack_layers_position\v!yes
+ \edef\p_pack_layers_region{\layerparameter\c!region}%
+ \ifx\p_pack_layers_region\empty \else
+ \anch_mark_tagged_box\nextbox\layeranchor
+ \fi
+ \fi
+ \box\nextbox
+ %
+ \ifconditional\c_pack_layers_repeated\else
+ \gsetboxllx\b_layers\zeropoint
+ \gsetboxlly\b_layers\zeropoint
+ \fi
+ \endgroup}
+
+\def\pack_layers_positioned_box_yes
+ {\vpack
+ {\vskip-\getboxlly\b_layers
+ \hskip-\getboxllx\b_layers
+ \hsize-\dimexpr\getboxllx\b_layers-\wd\b_layers\relax
+ \ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}}
+
+\def\pack_layers_positioned_box_nop
+ {\ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}
+
+% \definelayer[test][method=fit] \setupcolors[state=start,option=test]
+%
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test][x=-20pt]{cccccc}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{dd}\setlayer[test][x=-20pt,y=-3pt]{eeeeee}\flushlayer[test]}
+
+%D \macros
+%D {composedlayer,placelayer,tightlayer}
+%D
+%D This is a handy shortcut, which saves a couple of braces
+%D when we use it as parameter. This name also suits better
+%D to other layering commands.
+
+\unexpanded\def\composedlayer#1{\flushlayer[#1]}
+
+% \unexpanded\def\tightlayer[#1]%
+% {\hbox
+% {\def\currentlayer{#1}% todo: left/right
+% \setbox\nextbox\emptybox
+% \hsize\layerparameter\c!width
+% \vsize\layerparameter\c!height
+% \composedlayer{#1}}}
+
+\unexpanded\def\tightlayer[#1]%
+ {\hpack
+ {\def\currentlayer{#1}% todo: left/right
+ \setbox\nextbox\emptybox
+ \d_overlay_width \layerparameter\c!width
+ \d_overlay_height\layerparameter\c!height
+ \composedlayer{#1}}}
+
+\let\placelayer\flushlayer
+
+%D \macros
+%D {setMPlayer}
+%D
+%D The following layer macro uses the positions that are
+%D registered by \METAPOST.
+%D
+%D \starttyping
+%D \definelayer[test]
+%D
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \setMPlayer [test] [somepos-3] {\externalfigure[cow.mps][width=2cm]}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 10cm withcolor red ;
+%D register ("somepos-1",2cm,3cm,center currentpicture) ;
+%D register ("somepos-2",8cm,5cm,(-1cm,-2cm)) ;
+%D register ("somepos-3",0cm,0cm,(-2cm,2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \getMPlayer[test]{\useMPgraphic{oeps}}
+%D \stoptyping
+%D
+%D The last line is equivalent to
+%D
+%D \starttyping
+%D \framed
+%D [background={foreground,test},offset=overlay]
+%D {\useMPgraphic{oeps}}
+%D \stoptyping
+
+\unexpanded\def\setMPlayer
+ {\dotripleempty\pack_layers_set_MP}
+
+\def\MPlayerwidth {\hsize}
+\def\MPlayerheight{\vsize}
+
+\def\pack_layers_set_MP[#1][#2][#3]%
+ {\edef\MPlayerwidth {\MPw{#2}}%
+ \edef\MPlayerheight{\MPh{#2}}%
+ \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
+
+\unexpanded\def\getMPlayer
+ {\dodoubleempty\pack_layers_get_MP}
+
+\def\pack_layers_get_MP[#1][#2]%
+ {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument
+
+%D Watch out, a redefinition:
+
+\ifdefined\settextpagecontent \else
+ \writestatus\m!system{error in page-lyr.tex} \wait
+\fi
+
+\definelayer
+ [OTRTEXT]
+
+\setuplayer
+ [OTRTEXT]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight]
+
+\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
+
+\unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\doifelselayerdata{OTRTEXT}
+ {\setbox#1\hpack to \makeupwidth
+ {\startoverlay
+ {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
+ {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
+ \stopoverlay}%
+ \dp#1\zeropoint}%
+ {\normalsettextpagecontent{#1}{#2}{#3}}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-mis.mkvi b/Master/texmf-dist/tex/context/base/mkiv/pack-mis.mkvi
new file mode 100644
index 00000000000..420f9440a2f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-mis.mkvi
@@ -0,0 +1,112 @@
+%D \module
+%D [ file=pack-mis, % moved from e.g. core-mis
+%D version=1998.01.29,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Miscelaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packing Macros / Misc Commands}
+
+\unprotect
+
+% a quite old mechanism already (but inheritance added)
+%
+% \defineplacement[name][settings]
+% \setupplacement [name][settings]
+% \placement [name][settings]
+% \place<name> [settings]
+
+\installcorenamespace{placement}
+
+\installcommandhandler \??placement {placement} \??placement
+
+\appendtoks
+ \setuevalue{\e!place\currentplacement}{\pack_placement{\currentplacement}}%
+\to \everydefineplacement
+
+\setupplacement
+ [\c!left=\hss,
+ \c!right=\hss,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!grid=\v!middle,
+ %\c!before=,
+ %\c!after=,
+ \c!margin=\v!standard]
+
+\unexpanded\def\placement[#tag]%
+ {\pack_placement{#tag}}
+
+\unexpanded\def\pack_placement#tag%
+ {\bgroup
+ \edef\currentplacement{#tag}%
+ \doifelsenextoptionalcs\pack_placement_yes\pack_placement_nop}
+
+\def\pack_placement_yes[#settings]%
+ {\setupcurrentplacement[#settings]%
+ \pack_placement_nop}
+
+\def\pack_placement_nop
+ {\dowithnextboxcontentcs\forgetall\pack_placement_flush\vbox}
+
+\def\pack_placement_flush
+ {\setlocalhsize
+ \placementparameter\c!before
+ \begingroup
+ \disableparpositions
+ \setbox\nextbox\hbox to \localhsize
+ {\placementparameter\c!left
+ \flushnextbox
+ \placementparameter\c!right}%
+ %\ifinsidefloat \else
+ % \page_backgrounds_add_local_to_box\nextbox
+ %\fi
+\flushnotes % new per 2014-05-29 : todo: move them up in the mvl
+ \ifgridsnapping
+ \pack_placement_flush_grid_yes
+ \else
+ \pack_placement_flush_grid_nop
+ \fi
+ \endgroup
+ \placementparameter\c!after
+ \egroup}
+
+\def\pack_placement_flush_grid_yes
+ {\edef\p_grid{\placementparameter\c!grid}%
+ \ifx\p_grid\empty
+ \let\p_grid\v!middle
+ \fi
+ \pack_placement_flush_grid_noindent
+ \snaptogrid[\p_grid]\hbox{\box\nextbox}}
+
+\def\pack_placement_flush_grid_nop
+ {\edef\p_linecorrection {\placementparameter\c!linecorrection}%
+ \edef\p_depthcorrection{\placementparameter\c!depthcorrection}%
+ \ifx\p_linecorrection\v!on
+ \startbaselinecorrection
+ \fi
+ \pack_placement_flush_grid_noindent
+ \box\nextbox
+ \ifx\p_depthcorrection\v!on
+ \baselinecorrection
+ \fi
+ \ifx\p_linecorrection\v!on
+ \stopbaselinecorrection
+ \fi}
+
+\def\pack_placement_flush_grid_noindent
+ {\edef\p_margin{\placementparameter\c!margin}%
+ \ifx\p_margin\v!standard
+ \noindent
+ \else\ifx\p_margin\v!yes
+ \noindent
+ \fi\fi}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv
new file mode 100644
index 00000000000..649b29fa6e6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv
@@ -0,0 +1,853 @@
+%D \module
+%D [ file=pack-mrl, % was pack-rul/core-rul,
+%D version=1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=More Rules,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / More Rules}
+
+%D The (re)implementation of margin rules has been moved elsewhere.
+
+\unprotect
+
+%D \macros
+%D {setupblackrules,blackrule}
+%D
+%D The graphic capabilities of \TEX\ do not go beyond simple filled rules, except of
+%D course when using specials or, in \MKIV, manipulate node lists. Let's start with
+%D a warning: using this commands is far more slower than using the \TEX\ primitives
+%D \type {\hrule} and \type {\vrule}, but they save us some tokens. The
+%D characteristics of these rule drawing command can be set by:
+%D
+%D \showsetup{setupblackrules}
+%D
+%D The simple command draws only one rule. Its optional argument can be used to
+%D specify the dimensions. By setting the width, height or depth to \type {max}, one
+%D gets the natural dimensions.
+%D
+%D \showsetup{blackrule}
+
+\installcorenamespace{blackrules}
+
+\installsimplecommandhandler \??blackrules {blackrules}
+
+\unexpanded\def\blackrule
+ {\hbox\bgroup
+ \doifelsenextoptionalcs\pack_black_rule_pickup\pack_black_rule_indeed}
+
+\def\pack_black_rule_pickup[#1]%
+ {\setupcurrentblackrules[#1]%
+ \pack_black_rule_indeed}
+
+\def\pack_black_rule_indeed
+ {\edef\p_width {\directblackrulesparameter\c!width }%
+ \edef\p_height{\directblackrulesparameter\c!height}%
+ \edef\p_depth {\directblackrulesparameter\c!depth }%
+ \ifx\p_height\v!max
+ \setstrut
+ \else\ifx\p_depth\v!max
+ \setstrut
+ \fi\fi
+ \useblackrulesstyleandcolor\c!style\c!color
+ \vrule
+ \ifx\p_width \v!max\s!width \emwidth\else\ifx\p_width \empty\else\s!width \p_width \fi\fi
+ \ifx\p_height\v!max\s!height\strutht\else\ifx\p_height\empty\else\s!height\p_height\fi\fi
+ \ifx\p_depth \v!max\s!depth \strutdp\else\ifx\p_depth \empty\else\s!depth \p_depth \fi\fi
+ \egroup}
+
+\setupblackrules
+ [\c!width=\emwidth,
+ \c!height=\exheight,
+ \c!depth=\zeropoint,
+ \c!color=]
+
+%D \macros
+%D {blackrules}
+%D
+%D One can call for a sequence of black rules, if needed equally spaced over the
+%D given width.
+%D
+%D \showsetup{blackrules}
+%D
+%D The two alternative calls are therefore:
+%D
+%D \startbuffer
+%D Tell me, is this according to the \blackrules[n=6]?
+%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D We could of course have implemented this macro using \type {\leaders}, but this
+%D would probably have taken more tokens.
+
+\unexpanded\def\blackrules % probably never used
+ {\hbox\bgroup
+ \doifelsenextoptionalcs\pack_black_rules_pickup\pack_black_rules_indeed}
+
+\def\pack_black_rules_pickup[#1]%
+ {\setupcurrentblackrules[#1]%
+ \pack_black_rules_indeed}
+
+\def\pack_black_rules_indeed % no max handling here
+ {\scratchwidth \directblackrulesparameter\c!width
+ \scratchheight \directblackrulesparameter\c!height
+ \scratchdepth \directblackrulesparameter\c!depth
+ \scratchdistance\directblackrulesparameter\c!distance
+ \scratchcounter \directblackrulesparameter\c!n
+ \edef\p_alternative{\blackrulesparameter\c!alternative}%
+ \ifx\p_alternative\c!b
+ \ifnum\scratchcounter=\plusone
+ \scratchdistance\zeropoint
+ \else
+ \scratchwidth\dimexpr(\scratchwidth-\scratchcounter\scratchdistance+\scratchdistance)/\scratchcounter\relax
+ \fi
+ \fi
+ \useblackrulesstyleandcolor\c!style\c!color
+ \dorecurse\scratchcounter % a typical case of where we can use a simple loop
+ {\vrule
+ \s!width \scratchwidth
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hskip\scratchdistance}%
+ \unskip
+ \egroup}
+
+\setupblackrules
+ [\c!n=3,
+ \c!alternative=\c!a,
+ \c!distance=.25\emwidth,
+ \c!color=]
+
+%D \macros
+%D {vl, hl}
+%D
+%D The command \type {\vl} draws a vertical rule \vl\ with strut dimensions,
+%D multiplied with the factor specified in the optional argument. The height and
+%D depth are clipped \vl [3] to the baselinedistance. Its horizontal counterpart
+%D \type {\hl} draws a horizontal rule \hl\ with a width of 1em, multiplied with the
+%D optional factor. The horizontal rule is drawn on top of the baseline.
+%D
+%D \showsetup{vl}
+%D \showsetup{hl}
+
+\unexpanded\def\pack_rule_vl_indeed#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox
+ {\vrule
+ \s!width #1\linewidth
+ \s!height#2\strutht
+ \s!depth #3\strutdp}%
+ \dp\scratchbox\strutdp
+ \ht\scratchbox\strutht
+ \box\scratchbox
+ \endgroup}
+
+\def\pack_rule_vl[#1]%
+ {\pack_rule_vl_indeed{#1}{#1}{#1}}
+
+\def\pack_rule_hl[#1]%
+ {\dontleavehmode
+ \hbox
+ {\vrule
+ \s!width #1\emwidth
+ \s!height\linewidth
+ \s!depth \zeropoint}}
+
+\unexpanded\def\vl{\dosingleempty\pack_rule_vl}
+\unexpanded\def\hl{\dosingleempty\pack_rule_hl}
+
+\let\dovlwdhtdp\pack_rule_vl_indeed % used elsewhere
+
+%D \macros
+%D {hairline, thinrule, thinrules, setupthinrules}
+%D
+%D Drawing thin lines can of course easily be accomplished by the \TEX\
+%D primitives \type{\hrule} and \type{\vrule}. The next few macros however
+%D free us from some specifications.
+%D
+%D \startbuffer
+%D some text
+%D
+%D \hairline
+%D
+%D some more text
+%D
+%D \thinrule
+%D
+%D more and more text
+%D
+%D hi \thinrule\ there
+%D
+%D and then the final text
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D becomes
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D So we've got
+%D
+%D \showsetup{hairline}
+%D \showsetup{thinrule}
+%D
+%D Both can be set up with:
+%D
+%D \showsetup{setupthinrules}
+%D
+%D We also have
+%D
+%D \showsetup{thinrules}
+%D
+%D which looks like: \thinrules[n=2]
+
+\installcorenamespace{thinrules}
+\installcorenamespace{thinrulealternatives}
+
+\installdirectcommandhandler \??thinrules {thinrules}
+
+\setupthinrules
+ [\c!interlinespace=\v!small,
+ \c!n=3,
+ \c!before=,
+ \c!inbetween={\blank[\v!white]},
+ \c!after=,
+ \c!color=,
+ \c!height=.5\linewidth,
+ \c!depth=.5\linewidth,
+ \c!frame=\v!on, % compatible with textbackgrounds
+ \c!alternative=\v!b,
+ \c!backgroundcolor=,
+ \c!background=,
+ \c!rulethickness=\linewidth]
+
+\letvalue{\??thinrulealternatives\v!a }\zerocount
+\letvalue{\??thinrulealternatives\v!b }\plusone
+\letvalue{\??thinrulealternatives\v!c }\plustwo
+\letvalue{\??thinrulealternatives\v!none}\zerocount
+
+\newconstant\c_pack_thinrules_type
+
+\unexpanded\def\thinrule
+ {\strut
+ \bgroup
+ \edef\p_height {\directthinrulesparameter\c!height}%
+ \edef\p_depth {\directthinrulesparameter\c!depth}%
+ \edef\p_background{\directthinrulesparameter\c!background}%
+ \edef\p_frame {\directthinrulesparameter\c!frame}%
+ \linewidth\dimexpr\directthinrulesparameter\c!rulethickness/\plustwo\relax
+ \ifdim\linewidth=\zeropoint
+ \c_pack_thinrules_type\zerocount
+ \else\ifx\p_frame\v!on
+ \c_pack_thinrules_type\expandnamespaceparameter\??thinrulealternatives\directthinrulesparameter\c!alternative\v!b\relax
+ \else
+ \c_pack_thinrules_type\zerocount
+ \fi\fi
+ \ifnum\c_pack_thinrules_type=\plusone
+ \ifx\p_height\v!max
+ \scratchheight\strutht
+ \else
+ \setdimensionwithunit\scratchheight\p_height\strutht
+ \fi
+ \ifx\p_depth\v!max
+ \scratchdepth\strutdp
+ \else
+ \setdimensionwithunit\scratchdepth\p_depth\strutdp
+ \fi
+ \else
+ \scratchheight\strutht
+ \scratchdepth \strutdp
+ \fi
+ \ifx\p_background\v!color
+ \startcolor[\directthinrulesparameter\c!backgroundcolor]%
+ \ifnum\c_pack_thinrules_type=\plustwo % prevent overshoot due to rounding
+ \leaders
+ \hrule
+ \s!height\dimexpr\scratchheight-\linewidth\relax
+ \s!depth \dimexpr\scratchdepth -\linewidth\relax
+ \hfill
+ \else
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hfill
+ \fi
+ \stopcolor
+ \ifcase\c_pack_thinrules_type
+ % no rule
+ \or
+ \startcolor[\directthinrulesparameter\c!color]%
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\linewidth
+ \s!depth \linewidth
+ \hfill
+ \stopcolor
+ \or
+ \startcolor[\directthinrulesparameter\c!color]%
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\dimexpr-\scratchdepth+\linewidth\relax
+ \s!depth \scratchdepth
+ \hfill
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \dimexpr-\scratchheight+\linewidth\relax
+ \hfill
+ \stopcolor
+ \fi
+ \else
+ \ifcase\c_pack_thinrules_type
+ % no rule
+ \else
+ \startcolor[\directthinrulesparameter\c!color]%
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hfill
+ \stopcolor
+ \fi
+ \fi
+ \strut
+ \carryoverpar\egroup}
+
+\unexpanded\def\hairline
+ {\endgraf
+ \thinrule
+ \endgraf}
+
+\unexpanded\def\thinrules
+ {\dosingleempty\pack_thinrules}
+
+\def\pack_thinrules[#1]%
+ {\bgroup
+ \setupcurrentthinrules[#1]%
+ \scratchcounter\directthinrulesparameter\c!n\relax
+ \ifcase\scratchcounter
+ % nothing, not even before/after
+ \let\p_after\relax
+ \else
+ \assignvalue{\directthinrulesparameter\c!interlinespace}\m_pack_thinrules_interlinespace{1.0}{1.5}{2.0}%
+ \spacing\m_pack_thinrules_interlinespace
+ \edef\p_after {\directthinrulesparameter\c!after}%
+ \edef\p_inbetween{\directthinrulesparameter\c!inbetween}%
+ \directthinrulesparameter\c!before
+ \ifcase\scratchcounter\or
+ \thinrule
+ \else
+ \dorecurse\scratchcounter
+ {\ifnum\recurselevel=\scratchcounter \directvspacing\v!samepage \else % \penalty500
+ \ifnum\recurselevel=\plustwo \directvspacing\v!samepage \fi\fi % \penalty500
+ \thinrule
+ \ifnum\recurselevel<\scratchcounter\relax
+ % test needed, else messed up whitespace
+ \ifx\p_inbetween\empty
+ \softbreak % \ifhmode \hskip \parfillskip \break \fi
+ \else
+ \endgraf
+ \nowhitespace
+ \p_inbetween
+ \fi
+ \fi}%
+ \fi
+ \fi
+ \ifx\p_after\empty
+ \carryoverpar\egroup
+ \else
+ \p_after\egroup
+ \fi{}}
+
+%D A couple of examples are given below.
+%D
+%D \startbuffer
+%D \setupthinrules[n=3,inbetween=,color=gray]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [color=green] test test \par
+%D test test \thinrules [height=max, depth=max] test test \par
+%D
+%D \setupthinrules[height=.9,depth=.9]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [alternativevariant=b] test test \par
+%D test test \thinrules [alternativevariant=c] test test \par
+%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+%D
+%D There are a couple of alternative ways to visualize rules using backgrounds. At
+%D first sight these may look strange, but they make sense in educational settings.
+%D The alternatives are more or less compatible with the more advanced \METAPOST\
+%D based implementation.
+%D
+%D \startbuffer[a]
+%D \setupthinrules
+%D [n=2,
+%D backgroundcolor=gray ,
+%D rulethickness=1pt,
+%D colorkleur=donkerblauw,
+%D after=\blank,
+%D before=\blank]
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a]
+%D \thinrules[alternativevariant=b]
+%D \thinrules[alternativevariant=c]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,background=color]
+%D \thinrules[alternativevariant=b,background=color]
+%D \thinrules[alternativevariant=c,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+
+%D \macros
+%D {textrule, starttextrule, setuptextrules}
+%D
+%D Putting rules before and after a paragraph is very space sensitive, but the
+%D next command handles that quite well. It comes in two disguises:
+%D
+%D \startbuffer
+%D \textrule[top]{fragments}
+%D \input reich
+%D \textrule
+%D \stopbuffer
+%D
+%D \start \typebuffer \getbuffer \stop
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [width=90pt,distance=12pt,rulecolor=blue,
+%D bodyfont=small,style=\sc,color=red]
+%D
+%D \starttextrule{Ship Building Tools}
+%D \nl \setuptolerance[tolerant] \input materie
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [location=inmargin,
+%D bodyfont=small,style=slantedbold]
+%D
+%D \starttextrule{wonderful}
+%D \input tufte
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D The formal definition of these commands is:
+%D
+%D \showsetup{textrule}
+%D \showsetup{starttextrule}
+%D \showsetup{setuptextrules}
+%D
+%D The implementation looks a bit complicated due to the optional arguments.
+
+\installcorenamespace{textrules}
+\installcorenamespace{textrulealternatives}
+
+\installdirectcommandhandler \??textrules {textrules}
+
+\setuptextrules
+ [\c!location=\v!left,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=,
+ \c!width=2\emwidth,
+ \c!style=\v!bold,
+ \c!color=,
+ \c!rulecolor=,
+ \c!bodyfont=,
+ \c!depthcorrection=\v!on,
+ \c!rulethickness=\linewidth,
+ \c!distance=.5\emwidth]
+
+\unexpanded\def\textrule
+ {\dosingleempty\pack_textrule}
+
+\def\pack_textrule
+ {\iffirstargument
+ \expandafter\pack_textrule_yes
+ \else
+ \expandafter\pack_textrule_nop
+ \fi}
+
+\def\pack_textrule_yes[#1]%
+ {\expandnamespacevalue\??textrulealternatives{#1}\v!bottom}
+
+\def\pack_textrule_nop[#1]%
+ {\dosinglegroupempty\pack_textrule_nop_indeed}
+
+\def\pack_textrule_nop_indeed
+ {\iffirstargument
+ \expandafter\pack_textrule_nop_indeed_yes
+ \else
+ \expandafter\pack_textrule_nop_indeed_nop
+ \fi}
+
+\def\pack_textrule_nop_indeed_yes
+ {\csname\??textrulealternatives\v!top\endcsname}
+
+\def\pack_textrule_nop_indeed_nop
+ {\csname\??textrulealternatives\v!bottom\endcsname\empty}
+
+%D\startbuffer
+%D\showstruts
+%D
+%D\setupwhitespace[none]
+%D
+%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test}
+%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test}
+%D
+%D\setupwhitespace[big]
+%D
+%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test}
+%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test}
+%D\stoptyping
+%D
+%D \typebuffer \start \getbuffer \stop
+
+\setvalue{\??textrulealternatives\v!top}#1%
+ {\page[\v!preference] % interferes
+ \directtextrulesparameter\c!before\relax
+ \blank[\v!samepage,\v!nowhite]%
+ \pack_textrule_with_text{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \endgraf}
+
+\setvalue{\??textrulealternatives\v!bottom}#1%
+ {\blank[\v!samepage,\v!nowhite]%
+ \pack_textrule_following{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!after\relax
+ \page[\v!preference]}
+
+\setvalue{\??textrulealternatives\v!middle}#1%
+ {\blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \pack_textrule_following{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \page[\v!preference]}
+
+\def\pack_textrule_with_text#1%
+ {\bgroup
+ \setbox\scratchbox\hbox to \availablehsize
+ {\scratchwidth \directtextrulesparameter\c!rulethickness\relax
+ \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax
+ \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax
+ \doifsomething{#1}
+ {\doifelse{\directtextrulesparameter\c!location}\v!inmargin
+ {\llap
+ {\usetextrulesstyleandcolor\c!style\c!color
+ #1%
+ \hskip\leftmargindistance}}
+ {\color[\directtextrulesparameter\c!rulecolor]
+ {\vrule\s!height\scratchheight\s!depth\scratchdepth\s!width\directtextrulesparameter\c!width}%
+ \hbox spread 2\dimexpr\directtextrulesparameter\c!distance\relax
+ {\hss
+ \usetextrulesstyleandcolor\c!style\c!color
+ \strut#1%
+ \hss}}}%
+ \color[\directtextrulesparameter\c!rulecolor]
+ {\leaders\hrule\s!height\scratchheight\s!depth\scratchdepth\hfill}}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \noindent\box\scratchbox
+ \egroup}
+
+\def\pack_textrule_correct_depth_yes
+ {\vskip\dimexpr
+ \strutdp +.5\exheight
+ \ifdim\prevdepth>\strutdp\else
+ \ifdim\prevdepth>\zeropoint
+ -\prevdepth
+ \fi
+ \fi
+ \relax
+ \relax}
+
+\def\pack_textrule_correct_depth_nop
+ {\vskip\dimexpr
+ \strutdp +.5\exheight
+ \relax
+ \relax}
+
+\def\pack_textrule_following#1%
+ {\doifelsenothing{#1}
+ {\ifhmode
+ \endgraf
+ \fi
+ \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on\pack_textrule_correct_depth_yes\pack_textrule_correct_depth_nop
+ \nointerlineskip
+ \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}}%
+ \ifvmode
+ \prevdepth\zeropoint
+ \fi}
+
+%D The grouped commands also supports bodyfont switching:
+
+\unexpanded\def\starttextrule#1%
+ {\bgroup
+ \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}%
+ \csname\??textrulealternatives\v!top\endcsname{#1}%
+ \bgroup
+ \usebodyfontparameter\directtextrulesparameter}
+
+\unexpanded\def\stoptextrule
+ {\par
+ \egroup
+ \csname\??textrulealternatives\v!bottom\endcsname\empty
+ \egroup}
+
+%D \macros
+%D {fillinrules, setupfillinrules}
+%D
+%D The next few commands do not really deserve a place in a core module, because
+%D they deal with specific typography. Nevertheless I decided to make them part of
+%D the core, because they permit us to make questionaires. Let's start with some
+%D examples.
+%D
+%D \fillinrules[n=2,width=fit]{first}
+%D \fillinrules[n=2,width=broad]{first}
+%D \fillinrules[n=2,width=3cm]{first}
+%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first}
+%D \fillinrules[n=2]{first}{last}
+%D \fillintext{first}{last} \input reich \par
+%D
+%D The main command is \type{\fillinrules}. This command takes one and an optional
+%D second argument and sets a paragraph with empty visualized lines.
+%D
+%D \showsetup{fillinrules}
+%D \showsetup{setupfillinrules}
+
+
+\installcorenamespace{fillinrules}
+
+\installdirectcommandhandler \??fillinrules {fillinrules}
+
+\setupfillinrules
+ [\c!width=\v!broad,
+ \c!distance=\emwidth,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!n=\plusone,
+ \c!interlinespace=\v!small,
+ \c!separator=,
+ \c!style=,
+ \c!color=]
+
+\unexpanded\def\fillinrules
+ {\dosingleempty\pack_fillinrules}
+
+\def\pack_fillinrules[#1]%
+ {\endgraf
+ \begingroup
+ \setupcurrentfillinrules[#1]%
+ \let\pack_fillinrules_rule\thinrules
+ \dodoublegroupempty\pack_fillinrules_indeed}
+
+\def\pack_fillinrules_indeed#1#2%
+ {\directfillinrulesparameter\c!before
+ \setupcurrentthinrules
+ [\c!n=\directfillinrulesparameter\c!n,
+ \c!interlinespace=\directfillinrulesparameter\c!interlinespace,
+ \c!before=,
+ \c!after=]%
+ \scratchdistance\directfillinrulesparameter\c!distance\relax
+ \edef\m_fillinrules_one{#1}%
+ \edef\m_fillinrules_two{#2}%
+ \noindent
+ \ifx\m_fillinrules_one\empty \else
+ \edef\p_width{\directfillinrulesparameter\c!width}%
+ \ifx\p_width\v!fit
+ \scratchdistance\zeropoint
+ \hbox
+ \else\ifx\p_width\v!broad
+ \hbox
+ \else
+ \hbox to \directfillinrulesparameter\c!width
+ \fi\fi
+ \bgroup
+ \usefillinrulesstyleandcolor\c!style\c!color
+ \strut
+ \m_fillinrules_one
+ \hfill\directfillinrulesparameter\c!separator
+ \hskip\scratchdistance
+ \egroup
+ \fi
+ \setupwhitespace[\v!big]%
+ \ignorespaces
+ \pack_fillinrules_rule
+ \ifx\m_fillinrules_two\empty \else
+ \kern\scratchdistance
+ \usefillinrulesstyleandcolor\c!style\c!color
+ \m_fillinrules_two
+ \strut
+ \fi
+ \endgraf
+ \directfillinrulesparameter\c!after
+ \endgroup}
+
+%D \macros
+%D {fillintext}
+%D
+%D To provide compatible layouts when texts and lines are mixed, one can typeset
+%D a paragraph by using the command \type {\fillintext}.
+%D
+%D \showsetup{fillintext}
+
+\unexpanded\def\fillintext
+ {\dosingleempty\pack_fillintext}
+
+\def\pack_fillintext[#1]% ugly
+ {\endgraf
+ \begingroup
+ \setupcurrentfillinrules[#1]%
+ \dodoublegroupempty\pack_fillintext_indeed}
+
+\def\pack_fillintext_indeed#1#2%
+ {\def\pack_fillinrules_rule{\unhbox\nextbox\unskip}%
+ \dowithnextbox{\pack_fillinrules_indeed{#1}{\hfill#2}}%
+ \hbox\bgroup\let\par\egroup\ignorespaces}
+
+%D \macros
+%D {fillinline, setupfillinlines}
+%D
+%D Another member of the family takes care of putting a (often small) rule after
+%D a piece of text, like
+%D
+%D \startbuffer
+%D
+%D \stopbuffer\fillinline \input reich \par
+%D \fillinline[margin=0cm] \input reich \par
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D which was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D The two commands that take care of this are:
+%D
+%D \showsetup{fillinline}
+%D \showsetup{setupfillinlines}
+
+\installcorenamespace{fillinlines}
+
+\installdirectcommandhandler \??fillinlines {fillinlines}
+
+\setupfillinlines
+ [\c!width=8\emwidth, % was 3cm
+ \c!margin=\directfillinlinesparameter\c!width,
+ \c!rulethickness=\linewidth,
+ \c!color=,
+ \c!distance=\emwidth,
+ \c!before=\blank,
+ \c!after=\blank]
+
+\unexpanded\def\fillinline
+ {\dosingleempty\pack_fillinline}
+
+\ifdefined\endpar % experiment with \endpar
+
+ \def\pack_fillinline[#1]%
+ {% \endpar % no, as it interferes with \definedescription cum suis
+ \begingroup
+ \setupcurrentfillinlines[#1]%
+ \directfillinlinesparameter\c!before
+ \begingroup
+ \advance\rightskip \directfillinlinesparameter\c!margin\relax
+ \parfillskip\zeropoint
+ \pushmacro\endpar
+ \def\endpar
+ {\popmacro\endpar
+ \ifhmode\unskip\hfill\fi
+ \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax
+ \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi
+ {\kern\directfillinlinesparameter\c!distance
+ \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax
+ \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}%
+ \endpar
+ \endgroup
+ \endpar
+ \directfillinlinesparameter\c!after
+ \endgroup}} % carryover ?
+
+\else
+
+ \def\pack_fillinline[#1]%
+ {%\endgraf % no, as it interferes with \definedescription cum suis
+ \begingroup
+ \setupcurrentfillinlines[#1]%
+ \directfillinlinesparameter\c!before
+ \begingroup
+ \advance\rightskip \directfillinlinesparameter\c!margin\relax
+ \parfillskip\zeropoint
+ \def\par
+ {\let\par\endgraf
+ \ifhmode\unskip\hfill\fi
+ \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax
+ \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi
+ {\kern\directfillinlinesparameter\c!distance
+ \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax
+ \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}%
+ \endgraf
+ \endgroup
+ \endgraf
+ \directfillinlinesparameter\c!after
+ \endgroup}} % carryover ?
+
+\fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua
new file mode 100644
index 00000000000..8a1af2b7049
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua
@@ -0,0 +1,262 @@
+if not modules then modules = { } end modules ['pack-obj'] = {
+ version = 1.001,
+ comment = "companion to pack-obj.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>We save object references in the main utility table. jobobjects are
+reusable components.</p>
+--ldx]]--
+
+local context = context
+local codeinjections = backends.codeinjections
+
+local ctx_doifelse = commands.doifelse
+
+local nuts = nodes.nuts
+
+local setlink = nuts.setlink
+local getlist = nuts.getlist
+local setbox = nuts.setbox
+
+local new_latelua = nuts.pool.latelua
+
+local settexdimen = tokens.setters.dimen
+local settexcount = tokens.setters.count
+
+local gettexbox = tokens.getters.box
+local gettexdimen = tokens.getters.dimen
+local gettexcount = tokens.getters.count
+
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+
+local allocate = utilities.storage.allocate
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local jobobjects = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.objects = jobobjects
+
+local function initializer()
+ collected = jobobjects.collected
+ tobesaved = jobobjects.tobesaved
+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
+end
+
+local function setobject(tag,number,page)
+ collected[tag] = { number, page }
+end
+
+local function getobject(tag)
+ return collected[tag] or tobesaved[tag]
+end
+
+local function getobjectnumber(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ return o and o[1] or default
+end
+
+local function getobjectpage(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ return o and o[2] or default
+end
+
+jobobjects.save = saveobject
+jobobjects.set = setobject
+jobobjects.get = getobject
+jobobjects.number = getobjectnumber
+jobobjects.page = getobjectpage
+
+-- implement {
+-- name = "saveobject",
+-- actions = saveobject
+-- }
+--
+-- implement {
+-- name = "setobject",
+-- actions = setobject,
+-- arguments = { "string", "integer", "integer" }
+-- }
+--
+-- implement {
+-- name = "objectnumber",
+-- actions = { getobjectnumber, context },
+-- arguments = { "string", "string" },
+-- }
+--
+-- implement {
+-- name = "objectpage",
+-- actions = { getobjectpage, context },
+-- arguments = { "string", "string" },
+-- }
+--
+-- implement {
+-- name = "doifelseobjectreferencefound",
+-- actions = { getobject, commands.doifelse },
+-- arguments = "string"
+-- }
+
+-- if false then
+-- -- we can flush the inline ref ourselves now if we want
+-- local flush = new_latelua("pdf.flushxform("..index..")")
+-- flush.next = list
+-- next.prev = flush
+-- end
+
+local data = table.setmetatableindex("table")
+
+objects = {
+ data = data,
+ n = 0,
+}
+
+function objects.register(ns,id,b,referenced)
+ objects.n = objects.n + 1
+ nodes.handlers.finalize(gettexbox(b))
+ data[ns][id] = {
+ codeinjections.registerboxresource(b), -- a box number
+ gettexdimen("objectoff"),
+ referenced
+ }
+end
+
+function objects.restore(ns,id)
+ local d = data[ns][id]
+ if d then
+ local index = d[1]
+ local offset = d[2]
+ local status = d[3]
+ 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)
+ setlink(list,page)
+ end
+ setbox("objectbox",hbox)
+ settexdimen("objectoff",offset)
+ else
+ setbox("objectbox",nil)
+ settexdimen("objectoff",0)
+ end
+end
+
+function objects.dimensions(index)
+ local d = data[ns][id]
+ if d then
+ return codeinjections.boxresourcedimensions(d[1])
+ else
+ return 0, 0, 0
+ end
+end
+
+function objects.reference(ns,id)
+ local d = data[ns][id]
+ if d then
+ return d[1]
+ else
+ return getobjectnumber(ns .."::" .. id,0)
+ end
+end
+
+function objects.page(ns,id)
+ return getobjectpage(ns .."::" .. id,gettexcount("realpageno"))
+end
+
+function objects.found(ns,id)
+ return data[ns][id]
+end
+
+implement {
+ name = "registerreferencedobject",
+ arguments = { "string", "string", "integer", true },
+ actions = objects.register,
+}
+
+implement {
+ name = "registerobject",
+ arguments = { "string", "string", "integer" },
+ actions = objects.register,
+}
+
+implement {
+ name = "restoreobject",
+ arguments = { "string", "string" },
+ actions = objects.restore,
+}
+
+implement {
+ name = "doifelseobject",
+ arguments = { "string", "string" },
+ actions = function(ns,id)
+ ctx_doifelse(data[ns][id])
+ -- ctx_doifelse(objects.reference(ns,id))
+ end,
+}
+
+implement {
+ name = "doifelseobjectreference",
+ arguments = { "string", "string" },
+ actions = function(ns,id)
+ -- ctx_doifelse(data[ns][id])
+ ctx_doifelse(objects.reference(ns,id))
+ end,
+}
+
+implement {
+ name = "getobjectreference",
+ arguments = { "string", "string", "csname" },
+ actions = function(ns,id,target)
+ setmacro(target,objects.reference(ns,id),"global")
+ end
+}
+
+implement {
+ name = "getobjectreferencepage",
+ arguments = { "string", "string", "csname" },
+ actions = function(ns,id,target)
+ setmacro(target,objects.page(ns,id),"global")
+ end
+}
+
+implement {
+ name = "getobjectdimensions",
+ arguments = { "string", "string" },
+ actions = function(ns,id)
+ local o = data[ns][id]
+ local w, h, d = 0, 0, 0
+ if d then
+ w, h, d = codeinjections.boxresourcedimensions(o[1])
+ end
+ settexdimen("objectwd",w or 0)
+ settexdimen("objectht",h or 0)
+ settexdimen("objectdp",d or 0)
+ settexdimen("objectoff",o[2])
+ end
+}
+
+-- for the moment here:
+
+implement {
+ name = "registerbackendsymbol",
+ arguments = { "string", "integer" },
+ actions = function(...)
+ codeinjections.registersymbol(...)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv
new file mode 100644
index 00000000000..23608846d2d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv
@@ -0,0 +1,162 @@
+%D \module
+%D [ file=pack-obj,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Objects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Objects}
+
+\unprotect
+
+\registerctxluafile{pack-obj}{1.001}
+
+%D \macros
+%D {setobject,getobject,ifinobject}
+%D
+%D Boxes can be considered reuable objects. Traditionally once passed
+%D to the \DVI\ file, such objects cannot be reused. In \PDF\ however,
+%D reusing is possible and sometimes even a necessity. Therefore,
+%D \CONTEXT\ supports reusable objects and \LUATEX\ has native support
+%D for so called box resources.
+%D
+%D The first application of objects in \CONTEXT\ concerned \METAPOST\
+%D graphics and fill||in form fields. Reusing resources can save lots
+%D of bytes and sometimes also runtime.
+%D
+%D \starttyping
+%D \setobject{class}{name}\somebox{}
+%D \getobject{class}{name}
+%D \stoptyping
+%D
+%D Here \type {\somebox} can be whatever box specification suits \TEX.
+%D Although the implementation in \MKIV\ is somewhat different the
+%D principles have not changed.
+
+\installcorenamespace {objects}
+
+\newif \ifinobject
+\newbox \objectbox
+
+\def\objectoffset{1cm}
+
+\newdimen\objectoff \def\objectmargin{\the\objectoff}
+\newdimen\objectwd \def\objectwidth {\the\objectwd}
+\newdimen\objectht \def\objectheight{\the\objectht}
+\newdimen\objectdp \def\objectdepth {\the\objectdp}
+
+% If I have time I will use the unreferenced variant for e.g. mp reuse.
+
+% todo formmargin per obj
+
+\unexpanded\def\setreferencedobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
+\unexpanded\def\settightreferencedobject #1#2{\begingroup\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
+\unexpanded\def\setunreferencedobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}}
+\unexpanded\def\settightunreferencedobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}}
+
+\let\setobject \setreferencedobject
+\let\settightobject\settightreferencedobject
+
+\unexpanded\def\pack_objects_set_yes#1#2%
+ {\ifdim\objectoff>\zeropoint\relax
+ \pack_objects_package
+ \else
+ \setbox\objectbox\box\nextbox
+ \fi
+ \clf_registerreferencedobject{#1}{#2}\objectbox
+ \endgroup}
+
+\unexpanded\def\pack_objects_set_nop#1#2%
+ {\ifdim\objectoff>\zeropoint\relax
+ \pack_objects_package
+ \else
+ \setbox\objectbox\box\nextbox
+ \fi
+ \clf_registerobject{#1}{#2}\objectbox
+ \endgroup}
+
+\def\pack_objects_package
+ {\objectwd\dimexpr\wd\nextbox+2\objectoff\relax
+ \objectht\dimexpr\ht\nextbox+ \objectoff\relax
+ \objectdp\dimexpr\dp\nextbox+ \objectoff\relax
+ \setbox\objectbox\hpack
+ {\hskip\objectoff
+ \box\nextbox}%
+ \wd\objectbox\objectwd
+ \ht\objectbox\objectht
+ \dp\objectbox\objectdp}
+
+\def\pack_objects_repackage
+ {\objectwd\dimexpr\wd\objectbox-2\objectoff\relax
+ \objectht\dimexpr\ht\objectbox- \objectoff\relax
+ \objectdp\dimexpr\dp\objectbox- \objectoff\relax
+ \setbox\objectbox\hpack
+ {\hskip-\objectoff
+ \box\objectbox}%
+ \wd\objectbox\objectwd
+ \ht\objectbox\objectht
+ \dp\objectbox\objectdp}
+
+\unexpanded\def\getobject#1#2%
+ {\begingroup
+ \clf_restoreobject{#1}{#2}%
+ \ifdim\objectoff>\zeropoint
+ \pack_objects_repackage
+ \fi
+ \box\objectbox
+ \endgroup}
+
+%D If needed one can ask for the dimensions of an object with:
+%D
+%D \starttyping
+%D \getobjectdimensions{class}{name}
+%D \stoptyping
+%D
+%D The results are reported in \type {\objectwidth}, \type
+%D {\objectheight} and \type {\objectdepth}.
+
+\unexpanded\def\getobjectdimensions#1#2%
+ {\clf_getobjectdimensions{#1}{#2}}
+
+%D \macros
+%D {doifobjectfoundelse,doifobjectreferencefoundelse}
+%D
+%D To prevent redundant definition of objects, one can use
+%D the next tests:
+%D
+%D \starttyping
+%D \doifobjectfoundelse{class}{object}{do then}{do else}
+%D \doifobjectreferencefoundelse{class}{object}{do then}{do else}
+%D \stoptyping
+
+\def\defaultobjectreference{0}
+\def\defaultobjectpage {\realfolio}
+
+\unexpanded\def\dogetobjectreference {\clf_getobjectreference}
+\unexpanded\def\dogetobjectreferencepage {\clf_getobjectreferencepage}
+
+\unexpanded\def\doifelseobjectfound {\clf_doifelseobject}
+\unexpanded\def\doifelseobjectreferencefound{\clf_doifelseobjectreference}
+
+\let\doifobjectfoundelse \doifelseobjectfound
+\let\doifobjectreferencefoundelse\doifelseobjectreferencefound
+
+%D For the moment here:
+
+\let\lastpredefinedsymbol\empty % some day we can do more at the lua end
+
+\unexpanded\def\predefinesymbol[#1]%
+ {\begingroup
+ \xdef\lastpredefinedsymbol{#1}%
+ \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting
+ \dogetobjectreference{SYM}{#1}\m_back_object_reference
+ \clf_registerbackendsymbol{#1}\m_back_object_reference\relax
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-pos.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-pos.mkiv
new file mode 100644
index 00000000000..c52c01ca4b9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-pos.mkiv
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=pack-pos,
+%D version=2010.11.17 % real old code, updated a bit
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Positioning,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Positioning}
+
+\unprotect
+
+% An old but still usefull mechanism:
+%
+% \ruledvbox{\startpositioning
+% \position(1,1){test}
+% \position[xstep=relative](1,1){test}
+% \position[ystep=relative](3,-1){test}
+% \position(10,10){test}
+% \stoppositioning}
+%
+% watch out: rather global
+
+\installcorenamespace {positioning}
+
+\installcommandhandler \??positioning {positioning} \??positioning
+
+\setuppositioning
+ [\c!state=\v!start,
+ \c!unit=\s!cm,
+ \c!factor=\plusone,
+ \c!scale =\plusone,
+ \c!xfactor=\positioningparameter\c!factor,
+ \c!yfactor=\positioningparameter\c!factor,
+ \c!xscale=\positioningparameter\c!scale,
+ \c!yscale=\positioningparameter\c!scale,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!xoffset=\zeropoint,
+ \c!yoffset=\zeropoint]
+
+\newdimen\d_pack_positioning_x_position
+\newdimen\d_pack_positioning_y_position
+\newdimen\d_pack_positioning_x_dimension
+\newdimen\d_pack_positioning_y_dimension
+\newdimen\d_pack_positioning_x_offset
+\newdimen\d_pack_positioning_y_offset
+
+\newbox\b_pack_positioning
+
+\unexpanded\def\startpositioning
+ {\bgroup
+ \dodoubleempty\pack_positioning_start}
+
+\def\pack_positioning_start[#1][#2]%
+ {\ifsecondargument
+ \edef\currentpositioning{#1}%
+ \setupcurrentpositioning[#2]%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\let\currentpositioning\empty
+ \setupcurrentpositioning[#1]}%
+ {\edef\currentpositioning{#1}}%
+ \else
+ \let\currentpositioning\empty
+ \fi\fi
+ \d_pack_positioning_x_position \zeropoint
+ \d_pack_positioning_y_position \zeropoint
+ \d_pack_positioning_x_dimension\zeropoint
+ \d_pack_positioning_y_dimension\zeropoint
+ \d_pack_positioning_x_offset \zeropoint
+ \d_pack_positioning_y_offset \zeropoint
+ \hfuzz\paperwidth
+ \vfuzz\paperheight
+ \setbox\b_pack_positioning\hbox\bgroup
+ \ignorespaces}
+
+\unexpanded\def\stoppositioning
+ {\removeunwantedspaces
+ \doifnot{\positioningparameter\c!offset}\v!yes
+ {\global\d_pack_positioning_x_offset\zeropoint
+ \global\d_pack_positioning_y_offset\zeropoint}%
+ \global\advance\d_pack_positioning_x_dimension\d_pack_positioning_x_offset
+ \global\advance\d_pack_positioning_y_dimension\d_pack_positioning_y_offset
+ \egroup
+ \vbox to \d_pack_positioning_y_dimension
+ {\vskip\d_pack_positioning_y_offset
+ \hbox to \d_pack_positioning_x_dimension
+ {\hskip\d_pack_positioning_x_offset
+ \box\b_pack_positioning
+ \hfill}
+ \vfill}%
+ \egroup}
+
+\unexpanded\def\pack_positioning_calculate#1#2#3#4#5#6#7#8#9%
+ {\setdimensionwithunit\scratchdimen{#1}{\positioningparameter\c!unit}%
+ \scratchdimen\positioningparameter#8\scratchdimen
+ \scratchdimen\positioningparameter#9\scratchdimen
+ \advance\scratchdimen\positioningparameter#4\relax
+ % == \scratchdimen\dimexpr#8\dimexpr#9\scratchdimen\relax+#4\relax
+ \doif{\positioningparameter#2}\v!relative
+ {\advance\scratchdimen#3%
+ \letpositioningparameter#4\zeropoint}%
+ #3\scratchdimen
+ \doifnot{\positioningparameter\c!state}\v!overlay
+ {\scratchdimen\dimexpr#5\nextbox+#3\relax
+ \ifdim #3<-#7\relax \global#7-#3\relax \fi
+ \ifdim\scratchdimen> #6\relax \global#6\scratchdimen\fi}}
+
+\unexpanded\def\position
+ {\bgroup
+ \dosingleempty\pack_positioning_position}
+
+\def\pack_positioning_position[#1]#2(#3,#4)%
+ {\iffirstargument
+ \setupcurrentpositioning[#1]%
+ \fi
+ \removeunwantedspaces
+ \dowithnextbox{\pack_positioning_position_indeed{#3}{#4}}\hbox}
+
+\def\pack_positioning_position_indeed#1#2%
+ {\dontcomplain
+ \pack_positioning_calculate
+ {#1}%
+ \c!xstep
+ \d_pack_positioning_x_position
+ \c!xoffset
+ \wd
+ \d_pack_positioning_x_dimension
+ \d_pack_positioning_x_offset
+ \c!xscale
+ \c!xfactor
+ \pack_positioning_calculate
+ {#2}%
+ \c!ystep
+ \d_pack_positioning_y_position
+ \c!yoffset
+ \htdp
+ \d_pack_positioning_y_dimension
+ \d_pack_positioning_y_offset
+ \c!yscale
+ \c!yfactor
+ \vbox to \zeropoint
+ {\offinterlineskip % else we get an empty line
+ \vskip\d_pack_positioning_y_position
+ \hbox to \zeropoint
+ {\hskip\d_pack_positioning_x_position
+ \box\nextbox
+ \hss}
+ \vss}%
+ \normalexpanded
+ {\egroup
+ \d_pack_positioning_x_position\the\d_pack_positioning_x_position
+ \d_pack_positioning_y_position\the\d_pack_positioning_y_position
+ \setexpandedpositioningparameter\c!xoffset{\the\dimexpr\positioningparameter\c!xoffset}%
+ \setexpandedpositioningparameter\c!yoffset{\the\dimexpr\positioningparameter\c!yoffset}}%
+ \ignorespaces}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua
new file mode 100644
index 00000000000..427a2d11da0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua
@@ -0,0 +1,231 @@
+if not modules then modules = { } end modules ['pack-rul'] = {
+ version = 1.001,
+ comment = "companion to pack-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>An explanation is given in the history document <t>mk</t>.</p>
+--ldx]]--
+
+-- we need to be careful with display math as it uses shifts
+-- challenge: adapt glue_set
+-- setfield(h,"glue_set", getfield(h,"glue_set") * getfield(h,"width")/maxwidth -- interesting ... doesn't matter much
+
+-- \framed[align={lohi,middle}]{$x$}
+-- \framed[align={lohi,middle}]{$ $}
+-- \framed[align={lohi,middle}]{\hbox{ }}
+-- \framed[align={lohi,middle}]{\hbox{}}
+-- \framed[align={lohi,middle}]{$\hskip2pt$}
+
+local type = type
+
+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 texsetdimen = tex.setdimen
+local texsetcount = tex.setcount
+
+local implement = interfaces.implement
+
+local nuts = nodes.nuts
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+
+local hpack = nuts.hpack
+local traverse_id = nuts.traverse_id
+local node_dimensions = nuts.dimensions
+local free_node = nuts.free
+
+local function doreshapeframedbox(n)
+ local box = getbox(n)
+ local noflines = 0
+ local firstheight = nil
+ local lastdepth = nil
+ local lastlinelength = 0
+ local minwidth = 0
+ local maxwidth = 0
+ local totalwidth = 0
+ local averagewidth = 0
+ local boxwidth = getfield(box,"width")
+ if boxwidth ~= 0 then -- and h.subtype == vlist_code
+ local list = getlist(box)
+ if list then
+ local function check(n,repack)
+ if not firstheight then
+ firstheight = getfield(n,"height")
+ end
+ lastdepth = getfield(n,"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
+ -- used to be: hpack(copy(l)).width
+ lastlinelength = node_dimensions(l,getfield(n,"dir"))
+ else
+ lastlinelength = getfield(n,"width")
+ end
+ else
+ lastlinelength = getfield(n,"width")
+ end
+ if lastlinelength > maxwidth then
+ maxwidth = lastlinelength
+ end
+ if lastlinelength < minwidth or minwidth == 0 then
+ minwidth = lastlinelength
+ end
+ 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',getfield(h,"dir")) -- multiple return value
+ if false then
+ setlist(h,p)
+ setfield(h,"shift",0) -- needed for display math, so no width check possible
+ -- setfield(p,"attr",getfield(h,"attr"))
+ else
+ setfield(h,"glue_set",getfield(p,"glue_set"))
+ setfield(h,"glue_order",getfield(p,"glue_order"))
+ setfield(h,"glue_sign",getfield(p,"glue_sign"))
+ setlist(p)
+ free_node(p)
+ end
+ end
+ setfield(h,"width",maxwidth)
+ end
+ end
+ end
+ -- if vdone then
+ -- for v in traverse_id(vlist_code,list) do
+ -- local width = getfield(n,"width")
+ -- if width > maxwidth then
+ -- setfield(v,"width",maxwidth)
+ -- end
+ -- end
+ -- end
+ setfield(box,"width",maxwidth)
+ averagewidth = noflines > 0 and totalwidth/noflines or 0
+ else -- e.g. empty math {$ $} or \hbox{} or ...
+setfield(box,"width",0)
+ end
+ end
+ end
+ texsetcount("global","framednoflines",noflines)
+ texsetdimen("global","framedfirstheight",firstheight or 0) -- also signal
+ texsetdimen("global","framedlastdepth",lastdepth or 0)
+ texsetdimen("global","framedminwidth",minwidth)
+ texsetdimen("global","framedmaxwidth",maxwidth)
+ texsetdimen("global","framedaveragewidth",averagewidth)
+end
+
+local function doanalyzeframedbox(n)
+ local box = getbox(n)
+ local noflines = 0
+ local firstheight = nil
+ local lastdepth = nil
+ if getfield(box,"width") ~= 0 then
+ local list = getlist(box)
+ if list then
+ local function check(n)
+ if not firstheight then
+ firstheight = getfield(n,"height")
+ end
+ lastdepth = getfield(n,"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)
+ end
+ end
+ end
+ texsetcount("global","framednoflines",noflines)
+ texsetdimen("global","framedfirstheight",firstheight or 0)
+ texsetdimen("global","framedlastdepth",lastdepth or 0)
+end
+
+implement { name = "doreshapeframedbox", actions = doreshapeframedbox, arguments = "integer" }
+implement { name = "doanalyzeframedbox", actions = doanalyzeframedbox, arguments = "integer" }
+
+local function maxboxwidth(box)
+ local boxwidth = getfield(box,"width")
+ if boxwidth == 0 then
+ return 0
+ end
+ local list = getlist(box)
+ if not list then
+ return 0
+ end
+ if getid(box) == hlist_code then
+ return boxwidth
+ end
+ local lastlinelength = 0
+ local maxwidth = 0
+ local function check(n,repack)
+ local l = getlist(n)
+ if l then
+ if repack then
+ local subtype = getsubtype(n)
+ if subtype == box_code or subtype == line_code then
+ lastlinelength = node_dimensions(l,getfield(n,"dir"))
+ else
+ lastlinelength = getfield(n,"width")
+ end
+ else
+ lastlinelength = getfield(n,"width")
+ end
+ if lastlinelength > maxwidth then
+ maxwidth = lastlinelength
+ 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)
+ end
+ return maxwidth
+end
+
+nodes.maxboxwidth = maxboxwidth
+
+implement {
+ name = "themaxboxwidth",
+ actions = function(n) context("%isp",maxboxwidth(getbox(n))) end,
+ arguments = "integer"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv
new file mode 100644
index 00000000000..c8288586f4b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv
@@ -0,0 +1,3066 @@
+%D \module
+%D [ file=pack-rul, % was core-rul,
+%D version=1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Ruled Content,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content}
+
+%D The code here is expanded lots of time as framed is used in many places. This is
+%D why the code here is (and gets) optimized as much as possible. Also, by avoiding
+%D packaging and expansion we also keep tracing reasonable. For instance, multiple
+%D stacked backgrounds can slow down a run if not optimized this way.
+
+\registerctxluafile{pack-rul}{1.001}
+
+\unprotect
+
+% \definesystemvariable {ol} % OmLijnd -> check scrn-fld too
+
+%D \macros
+%D {linewidth, setuplinewidth}
+%D
+%D This module deals with rules (lines) in several ways. First we introduce two
+%D macros that can be used to set some common characteristics.
+%D
+%D \showsetup{setuplinewidth}
+%D
+%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals
+%D the default hard coded \TEX\ rule width.
+
+\newdimen\linewidth
+
+\unexpanded\def\setuplinewidth
+ {\dosingleargument\pack_framed_setup_line_width}
+
+\def\pack_framed_setup_line_width[#1]%
+ {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
+
+% %D \macros
+% %D {setupscreens}
+% %D
+% %D Sort of obsolete:
+% %D
+% %D \showsetup{setupscreens}
+%
+% \installcorenamespace{screens}
+%
+% \installsetuponlycommandhandler \??screens {screens}
+%
+% \appendtoks
+% \edef\defaultbackgroundscreen{\directscreensparameter\c!screen}
+% \to \everysetupscreens
+%
+% \setupscreens
+% [\c!screen=.90] % was .95 but that's hardly visible
+
+%D The parameter handler:
+
+\installcorenamespace{framed}
+\installcorenamespace{framedtop}
+\installcorenamespace{framedbottom}
+\installcorenamespace{framedleft}
+\installcorenamespace{framedright}
+
+\installcorenamespace{regularframed}
+\installcorenamespace{simplifiedframed}
+
+\installcommandhandler \??framed {framed} \??framed
+
+\let\pack_framed_framedparameter \framedparameter
+\let\pack_framed_framedparameterhash\framedparameterhash
+\let\pack_framed_setupcurrentframed \setupcurrentframed
+
+\def\pack_framed_initialize
+ {\let\framedparameter \pack_framed_framedparameter
+ \let\framedparameterhash\pack_framed_framedparameterhash
+ \let\setupcurrentframed \pack_framed_setupcurrentframed
+ \inframedtrue}
+
+%D A helper:
+
+\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
+
+%D Inheritance:
+
+\def\installinheritedframed#1%
+ {\normalexpanded{\doinstallinheritedframed
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname #1parameter\endcsname
+ \expandafter\noexpand\csname #1parameterhash\endcsname
+ \expandafter\noexpand\csname do#1parameter\endcsname
+ \expandafter\noexpand\csname do#1parentparameter\endcsname
+ \expandafter\noexpand\csname do#1rootparameter\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname
+ \expandafter\noexpand\csname inherited#1framed\endcsname
+ \expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new
+
+\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
+ {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
+ %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
+ \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
+ \unexpanded\def#8%
+ {\bgroup
+ \bgroup
+ \inframedtrue
+ \let\currentframed #1%
+ \let\framedparameter #2%
+ \let\framedparameterhash#3%
+ \let\setupcurrentframed #7%
+ \pack_framed_process_indeed}%
+ \unexpanded\def#9%
+ {\bgroup
+ \inframedtrue
+ \let\currentframed #1%
+ \let\framedparameter #2%
+ \let\framedparameterhash#3%
+ \let\setupcurrentframed #7%
+ \pack_framed_process_box_indeed}}
+
+\unexpanded\def\installframedcommandhandler#1#2#3%
+ {\installcommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installframedautocommandhandler#1#2#3%
+ {\installautocommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installsimpleframedcommandhandler#1#2#3%
+ {\installsimplecommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+% for regular framed
+
+\setupframed
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ %\c!lines=,
+ \c!offset=.25ex, % \defaultframeoffset
+ \c!empty=\v!no,
+ \c!frame=\v!on,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!depth=\zeropoint,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\zeropoint,
+ %\c!framecolor=,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ %\c!component=,
+ %\c!region=,
+ %\c!align=,
+ \c!bottom=\vss,
+ %\c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ %\c!orientation=,
+ \c!autowidth=\v!yes,
+ %\c!setups=
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+%D For backgrounds and such:
+
+\defineframed
+ [\??simplifiedframed]
+ [\c!frame=\v!off,
+ \c!depth=\zeropoint,
+ \c!offset=\v!overlay,
+ \c!component=,
+ \c!region=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!backgroundoffset=\zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ \c!location=\v!normal,
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+\unexpanded\def\definesimplifiedframed[#1]% no settings
+ {\defineframed[#1][\??simplifiedframed]%
+ \expandafter\let\csname#1\endcsname\undefined}
+
+\expandafter\let\csname\??simplifiedframed\endcsname\undefined
+
+%D We will communicate through module specific variables, current framed
+%D parameters and some reserved dimension registers.
+
+\newdimen\d_framed_target_wd
+\newdimen\d_framed_target_ht
+\newdimen\d_framed_target_dp
+\newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end
+
+\let\p_framed_frame \empty % \framedparameter\c!frame
+\let\p_framed_backgroundoffset\empty
+\let\p_framed_foregroundstyle \empty
+\let\p_framed_autostrut \empty
+\let\p_framed_location \empty
+\let\p_framed_orientation \empty
+\let\p_framed_autowidth \empty
+\let\p_framed_franalyze \empty
+\let\p_framed_backgroundcorner\empty
+\let\p_framed_backgroundradius\empty
+\let\p_framed_framecorner \empty
+\let\p_framed_frameradius \empty
+\let\p_framed_lines \empty
+\let\p_framed_empty \empty
+\let\p_framed_backgroundcolor \empty
+\let\p_framed_framecolor \empty
+\let\p_framed_component \empty
+\let\p_framed_region \empty
+\let\p_framed_background \empty
+\let\p_framed_rulethickness \empty
+\let\p_framed_foregroundcolor \empty
+\let\p_framed_setups \empty
+
+%D We don't have to stick to a \TEX\ drawn rule, but also can use rounded
+%D or even fancier shapes, as we will see later on.
+
+\def\pack_framed_filled_box
+ {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}%
+ \ifx\p_framed_backgroundcorner\v!rectangular
+ \pack_framed_filled_box_normal
+ \else
+ \pack_framed_filled_box_radius
+ \fi}
+
+\def\pack_framed_filled_box_normal
+ {\vrule
+ \s!width \d_framed_target_wd
+ \s!height\d_framed_target_ht
+ \s!depth \d_framed_target_dp
+ \relax}
+
+\def\pack_framed_filled_box_radius
+ {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}%
+ \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_filled_box_normal
+ \else
+ \pack_framed_filled_box_round
+ \fi}
+
+\def\pack_framed_filled_box_round
+ {\back_ovalbox
+ \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp
+ \d_framed_linewidth \p_framed_backgroundradius
+ \zerocount \plusone {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}}
+
+\def\pack_framed_stroked_box
+ {\edef\p_framed_framecorner{\framedparameter\c!framecorner}%
+ \ifx\p_framed_framecorner\v!rectangular
+ \pack_framed_stroked_box_normal
+ \else
+ \pack_framed_stroked_box_radius
+ \fi}
+
+\def\pack_framed_stroked_box_radius
+ {\edef\p_framed_frameradius{\framedparameter\c!frameradius}%
+ \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_stroked_box_normal
+ \else\ifx\p_framed_frame\v!on
+ \pack_framed_stroked_box_round
+ \fi\fi}
+
+% \pack_framed_stroked_box_normal % later
+
+\def\pack_framed_stroked_box_round
+ {\back_ovalbox
+ \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp
+ \d_framed_linewidth \p_framed_frameradius
+ \plusone \zerocount {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}}
+
+% a lot of weird corners
+%
+% \startTEXpage
+% \dontleavehmode\framed
+% [corner=0,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green,
+% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \vskip1em
+% \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed
+% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
+% \quad}
+% \stopTEXpage
+
+%D The oval box is drawn using a special macro, depending on
+%D the driver in use.
+
+% \def\pack_framed_background_box_gray % avoid black rules when no gray
+% {\edef\p_framed_backgroundscreen{\framedparameter\c!backgroundscreen}%
+% \ifx\p_framed_backgroundscreen\empty \else
+% \pack_framed_background_box_gray_indeed
+% \fi}
+%
+% \def\pack_framed_background_box_gray_indeed % can be more direct but who cares, just compatibility
+% {\colored[s=\p_framed_backgroundscreen]{\pack_framed_filled_box}}
+
+%D It won't be a surprise that we not only provide gray boxes, but also colored
+%D ones. Here it is:
+
+\def\pack_framed_background_box_color
+ {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}%
+ \ifx\p_framed_backgroundcolor\empty \else
+ \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed
+ \fi}
+
+\def\pack_framed_background_box_color_indeed
+ {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
+
+%D \macros
+%D {defineoverlay, doifoverlayelse, overlayoffset,
+%D overlaywidth, overlayheight, overlaydepth,
+%D overlaycolor, overlaylinecolor, overlaylinewidth}
+%D
+%D Before we define the macro that actually takes card of the backgrounds, we
+%D introduce overlays. An overlay is something that contrary to its name lays {\em
+%D under} the text. An example of an overlay definition is:
+%D
+%D \startbuffer[tmp-1]
+%D \defineoverlay
+%D [fancy]
+%D [{\externalfigure
+%D [mp-cont.502]
+%D [width=\overlaywidth,
+%D height=\overlayheight]}]
+%D \stopbuffer
+%D
+%D \typebuffer[tmp-1]
+%D
+%D That for instance can be uses in:
+%D
+%D \startbuffer[tmp-2]
+%D \framed[backgroundachtergrond=fancy]{How Fancy!}
+%D \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!}
+%D \stopbuffer
+%D
+%D and looks like:
+%D
+%D \startlinecorrection
+%D \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]}
+%D \stoplinecorrection
+%D
+%D The formal definition is:
+%D
+%D \showsetup{defineoverlay}
+%D
+%D This macro's definition is a bit obscure, due the many non||used arguments and
+%D the two step call that enable the setting of the width, height and depth
+%D variables. Multiple backgrounds are possible and are specified as:
+%D
+%D \starttyping
+%D \framed[background={one,two,three}]{Three backgrounds!}
+%D \stoptyping
+%D
+%D Most drawing packages only know width and height. Therefore the dimensions have a
+%D slightly different meaning here:
+%D
+%D \startitemize[packed]
+%D \item \type{\overlaywidth }: width of the overlay
+%D \item \type{\overlayheight}: height plus depth of the overlay
+%D \item \type{\overlaydepth }: depth of the overlay
+%D \stopitemize
+%D
+%D The resulting box is lowered to the right depth.
+
+%def\overlaywidth {\the\hsize\space} % We preset the variables
+%def\overlayheight {\the\vsize\space} % to some reasonable default
+%def\overlaydepth {0pt } % values. The attributes
+%let\overlayoffset \overlaydepth % of the frame can be (are)
+%let\overlaylinewidth \overlaydepth % set somewhere else.
+\let\overlaycolor \empty
+\let\overlaylinecolor \empty
+
+\def\overlayradius{\framedparameter\c!frameradius}
+
+\newdimen\d_overlay_width
+\newdimen\d_overlay_height
+\newdimen\d_overlay_depth
+\newdimen\d_overlay_offset
+\newdimen\d_overlay_linewidth
+
+% 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
+\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default
+\def\overlaydepth {\the\d_overlay_depth \space} % values.
+\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are)
+\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else.
+
+% public but kind of protected
+
+\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax}
+\def\usedoverlayheight {\dimexpr\d_overlay_height \relax}
+\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax}
+\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax}
+\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax}
+
+%D The next register is used to initialize overlays.
+
+\newtoks\everyoverlay
+
+%D An example of an initialization is the following (overlays can contain text
+%D and be executed under an regime where interlineskip is off).
+
+\installcorenamespace{overlay}
+\installcorenamespace{overlaybuiltin}
+
+\appendtoks
+ \oninterlineskip
+\to \everyoverlay
+
+\prependtoks
+ \hsize\d_overlay_width
+ \vsize\d_overlay_height
+\to \everyoverlay
+
+\unexpanded\def\defineoverlay
+ {\dodoubleargument\pack_framed_define_overlay}
+
+\def\pack_framed_define_overlay[#1][#2]%
+ {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
+ \processcommalist[#1]\pack_framed_define_overlay_indeed}
+
+\unexpanded\def\executedefinedoverlay#1#2% we can share the definitions
+ {\bgroup % redundant grouping
+ \setbox\scratchbox\hbox\bgroup
+ \ifzeropt\d_framed_target_dp
+ \the\everyoverlay#2% saves wrapping (and lua call)
+ \else
+ \lower\d_framed_target_dp
+ \hbox{\the\everyoverlay#2}%
+ \fi
+ \egroup
+ \setlayoutcomponentattribute{\v!overlay:#1}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute
+ {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width
+ \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \d_overlay_height !
+ \box\scratchbox}%
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {overlayfakebox}
+
+% \unexpanded\def\overlayfakebox
+% {\hpack
+% {\setbox\scratchbox\emptyhbox
+% \wd\scratchbox\d_overlay_width
+% \ht\scratchbox\d_overlay_height
+% \box\scratchbox}}
+
+\unexpanded\def\overlayfakebox
+ {\hpack % redundant but needs testing
+ {\novrule
+ \s!width \d_overlay_width
+ \s!height\d_overlay_height
+ \s!depth \zeropoint}}
+
+%D For testing we provide:
+
+\def\doifelseoverlay#1% only tests external overlays
+ {\ifcsname\??overlay#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifoverlayelse\doifelseoverlay
+
+%D The content of the box will be (temporary) saved in a box. We also have an
+%D extra box for backgrounds.
+
+\newbox\b_framed_normal
+\newbox\b_framed_extra
+
+\newtoks\everybackgroundbox
+
+\let\m_framed_background\empty % we might need a public name
+
+\def\pack_framed_process_background
+ {\ifcsname\??overlaybuiltin\m_framed_background\endcsname
+ \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs
+ \else\ifcsname\??overlay\m_framed_background\endcsname
+ \expandafter\pack_framed_process_background_indeed_external\lastnamedcs
+ \fi\fi}
+
+\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
+ \kern-\framedbackgroundoffset
+ %\hbox{\csname\??overlaybuiltin\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}
+
+\def\pack_framed_process_background_indeed_external#1%
+ {\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}
+
+\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground)
+ {\edef\m_framed_background{#1}%
+ \ifx\m_framed_background\s!unknown\else
+ \pack_framed_process_background
+ \expandafter\pack_framed_process_backgrounds
+ \fi#2}
+
+%D Beware, a backgroundbox can be empty which is another reason why we set the
+%D width to zero instead of back-skipping.
+
+\newdimen\framedbackgroundwidth
+\newdimen\framedbackgroundheight
+\newdimen\framedbackgrounddepth
+\newdimen\framedbackgroundoffset
+
+\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
+ {\anch_mark_region_box\b_framed_normal}
+
+\def\pack_framed_add_background
+ {\setbox\b_framed_normal\hbox % was vbox % see also *1*
+ {%\pack_framed_forgetall % can be relaxed
+ \boxmaxdepth\maxdimen
+ \framedbackgroundoffset\d_framed_backgroundoffset
+ \framedbackgroundwidth \wd\b_framed_normal
+ \framedbackgroundheight\ht\b_framed_normal
+ \framedbackgrounddepth \dp\b_framed_normal
+ \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax
+ \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax
+ \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
+ \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed
+ \ifx\p_framed_component\empty
+ \resetlayoutcomponentattribute
+ \else
+ \setlayoutcomponentattribute{\v!background:\p_framed_component}%
+ \fi
+ \let\foregroundbox\pack_framed_background_box_content
+ \hbox \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
+ \the\everybackgroundbox % moved
+ \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it
+ \box\b_framed_normal
+ \hss
+ \egroup}}
+
+% \def\pack_framed_overlay_initialize_indeed
+% {\edef\overlaywidth {\the\d_framed_target_wd\space}%
+% \edef\overlayheight {\the\dimexpr\d_framed_target_ht+\d_framed_target_dp\relax\space}%
+% \edef\overlaydepth {\the\d_framed_target_dp\space}%
+% \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ?
+% \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
+% \edef\overlaylinewidth{\the\d_framed_linewidth\space}%
+% %\edef\overlaycorner {\framedparameter\c!backgroundcorner}%
+% %\edef\overlayradius {\framedparameter\c!backgroundradius}%
+% \edef\overlayoffset {\the\framedbackgroundoffset\space}% \backgroundoffset % we steal this one
+% \let\pack_framed_overlay_initialize\relax}
+
+\def\pack_framed_overlay_initialize_indeed
+ {\d_overlay_width \d_framed_target_wd
+ \d_overlay_height \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax
+ \d_overlay_depth \d_framed_target_dp
+ \d_overlay_linewidth \d_framed_linewidth
+ \d_overlay_offset \framedbackgroundoffset\relax
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ?
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
+ %\edef\overlaycorner {\framedparameter\c!backgroundcorner}%
+ %\edef\overlayradius {\framedparameter\c!backgroundradius}%
+ \let\pack_framed_overlay_initialize\relax}
+
+%D One can explictly insert the foreground box. For that purpose we introduce the
+%D overlay \type {foreground}.
+%D
+%D We predefine two already familiar backgrounds:
+
+%letvalue{\??overlaybuiltin\v!screen }\pack_framed_background_box_gray
+\letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color
+\letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox]
+
+%D We can specify overlays as a comma separated list of overlays, a sometimes
+%D handy feature.
+%D
+%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled
+%D borders). Again we have to deal with square and round corners. The first category
+%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro
+%D also support a negative offset.
+
+\def\pack_framed_add_outline
+ {\setbox\b_framed_normal\hpack % rules on top of box
+ {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax
+ \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax
+ \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax
+ \ifdim\d_framed_target_dp<\zeropoint
+ \advance\d_framed_target_ht \d_framed_target_dp
+ \scratchdimen-\d_framed_target_dp
+ \d_framed_target_dp\zeropoint
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background
+ \setbox\b_framed_extra\hbox
+ {\kern-\d_framed_frameoffset
+ \raise\scratchdimen
+ \hbox{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
+ \wd\b_framed_extra\wd\b_framed_normal
+ \ht\b_framed_extra\ht\b_framed_normal
+ \dp\b_framed_extra\dp\b_framed_normal
+ \wd\b_framed_normal\zeropoint
+ \box\b_framed_normal
+ \box\b_framed_extra}}
+
+% \def\pack_framed_stroked_box_normal
+% {\setbox\scratchbox\emptyhbox
+% \wd\scratchbox\d_framed_target_wd
+% \ht\scratchbox\d_framed_target_ht
+% \dp\scratchbox\d_framed_target_dp
+% \setbox\scratchbox\vpack \bgroup
+% \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
+% \box\scratchbox
+% \csname \??framedright\p_framed_frame\framedparameter\c!rightframe \endcsname
+% \egroup
+% \nointerlineskip % new (needed for fences)
+% \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
+ {\setbox\scratchbox\vpack \bgroup
+ \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
+ \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
+ \egroup
+ \nointerlineskip % new (needed for fences)
+ \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_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth}
+\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth}
+\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth}
+\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
+
+\letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!on }\pack_framed_t_rule
+
+\letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!on }\pack_framed_b_rule
+
+\letvalue{\??framedleft \v!on \v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!off\v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!on }\pack_framed_l_rule
+
+\letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!on }\pack_framed_r_rule
+
+% no overlapping rules
+
+\def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth}
+\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}}
+\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth}
+\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
+
+\letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!small }\pack_framed_t_rules
+
+\letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!off \v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!small }\pack_framed_b_rules
+
+\letvalue{\??framedleft \v!small\v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!off \v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!small }\pack_framed_l_rules
+
+\letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!off \v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!small }\pack_framed_r_rules
+
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on]
+% {}
+
+%D The next few macros are probably the most misused ones in \CONTEXT. They deal
+%D with putting rules around boxes, provide backgrounds, offer alignment features,
+%D and some more. We start with defining some booleans. These give an impression of
+%D what we are going to take into account.
+
+% todo : \c_framed_hasoffset
+% faster : \let\c_framed_hasoffset\falseconditional
+
+\newconditional\c_framed_has_offset
+\newconditional\c_framed_has_width
+\newconditional\c_framed_has_height
+\newconditional\c_framed_has_format
+\newconditional\c_framed_has_strut
+\newconditional\c_framed_is_overlaid
+\newconditional\c_framed_has_frame
+\newconditional\c_framed_has_extra_offset
+\newconditional\c_framed_text_location_none
+
+%D \macros
+%D {framed, setupframed}
+%D
+%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile
+%D and, although some users will probably seldom use it, one cannot overlook its
+%D features.
+%D
+%D \showsetup{setupframed}
+%D \showsetup{framed}
+%D
+%D This general macro is a special version of an even more general case, that can
+%D easily be linked into other macros that need some kind of framing. The local
+%D version is called with an extra parameter: the variable identifier. The reason
+%D for passing this identifier between brackets lays in the mere fact that this way
+%D we can use the optional argument grabbers.
+
+\def\defaultframeoffset{.25ex}
+
+\installcorenamespace{regularframedlevel}
+
+\unexpanded\def\installregularframed#1%
+ {\defineframed[#1]}
+
+\unexpanded\def\presetlocalframed[#1]%
+ {\defineframed[#1]}
+
+% \presetlocalframed[\??framed]
+
+\newcount\c_pack_framed_nesting
+
+% to be tested (slightly more efficient):
+%
+% \unexpanded\def\pack_frame_common % #1 #2
+% {\bgroup
+% \advance\c_pack_framed_nesting\plusone
+% \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+% \edef\currentframed{>\the\c_pack_framed_nesting}%
+% \pack_framed_initialize
+% \bgroup
+% \doifnextoptionalcselse} % #1 #2
+%
+% \unexpanded\def\framed {\pack_frame_common\pack_framed_process_framed_pickup\pack_framed_process_indeed}
+% \unexpanded\def\startframed{\pack_frame_common\pack_framed_start_framed_pickup \pack_framed_start_indeed }
+%
+% \def\pack_framed_process_framed_pickup[#1]%
+% {\setupcurrentframed[#1]%
+% \pack_framed_process_indeed}
+%
+% \def\pack_framed_start_framed_pickup[#1]%
+% {\setupcurrentframed[#1]% here !
+% \secondargumenttrue % dirty trick
+% \pack_framed_start_framed_indeed}
+%
+% \def\pack_framed_start_framed_indeed
+% {\pack_framed_process_indeed
+% \bgroup}
+%
+% no longer .. we also accept \startframed[tag]
+
+\unexpanded\def\pack_framed_process_framed[#1]%
+ {\bgroup
+ \iffirstargument % faster
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\unexpanded\def\framed
+ {\bgroup
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_process_framed}
+
+% \unexpanded\def\startframed
+% {\dosingleempty\pack_framed_start_framed}
+%
+% \def\pack_framed_start_framed[#1]%
+% {\bgroup
+% \advance\c_pack_framed_nesting\plusone
+% \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+% \edef\currentframed{>\the\c_pack_framed_nesting}%
+% \pack_framed_initialize
+% \bgroup
+% \iffirstargument
+% \secondargumenttrue % dirty trick
+% \setupcurrentframed[#1]% here !
+% \fi
+% \pack_framed_process_indeed
+% \bgroup
+% \ignorespaces}
+
+\unexpanded\def\startframed
+ {\dosingleempty\pack_framed_start_framed}
+
+\def\pack_framed_start_framed[#1]%
+ {\bgroup
+ \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}}
+
+\def\pack_framed_start_framed_yes#1%
+ {\advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \iffirstargument\secondargumenttrue\fi % dirty trick
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \bgroup
+ \iffirstargument
+ \secondargumenttrue % dirty trick
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed
+ \bgroup
+ \ignorespaces}
+
+\def\pack_framed_start_framed_nop#1%
+ {\edef\currentframed{#1}%
+ \dosingleempty\pack_framed_start_framed_nop_indeed}
+
+\def\pack_framed_start_framed_nop_indeed[#1]%
+ {\pack_framed_initialize
+ \bgroup
+ \setupcurrentframed[#1]% here !
+ \pack_framed_process_indeed
+ \bgroup
+ \ignorespaces}
+
+% till here
+
+\unexpanded\def\stopframed
+ {\removeunwantedspaces
+ \egroup}
+
+\unexpanded\def\normalframedwithsettings[#1]%
+ {\bgroup
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \bgroup
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \setupcurrentframed[#1]%
+ \pack_framed_process_indeed}
+
+%D \startbuffer
+%D \setupframed [framecolor=yellow] \framed{A}
+%D \defineframed[myframed] [framecolor=blue] \myframed{B}
+%D \setupframed [myframed] [framecolor=red] \myframed{C}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \presetlocalframed[myframed]
+%D \localframed[myframed][framecolor=green]{oeps}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {ifinframed}
+%D
+%D The normal case first presets all parameters and next starts looking for the user
+%D supplied ones. The first step is omitted in the local case, because these are
+%D preset at declaration time and keep their values unless explictly changed. By
+%D presetting the variables everytime the normal command is called, we can use this
+%D command nested, without the unwanted side effect of inheritance. The boolean is
+%D used to speed up the color stack.
+
+\newif\ifinframed
+
+%D The next one is faster on multiple backgrounds per page. No
+%D dimensions can be set, only frames and backgrounds.
+
+\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
+ {\bgroup
+ \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
+ \fi
+ \setupcurrentframed[#3]%
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
+ \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
+ \edef\p_framed_frame{\framedparameter\c!frame}%
+ \edef\p_framed_background{\framedparameter\c!background}%
+ % not here, in calling macro: setups
+ \pack_framed_remove_depth
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \pack_framed_add_outline % real or invisible frame
+ \fi\fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
+ \pack_framed_restore_depth
+ \box\b_framed_normal
+ \egroup}
+
+%D The next macro uses a box and takes its natural width and height so these
+%D can better be correct.
+
+\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
+ {\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\v!yes % maybe later named
+ \pack_framed_add_region
+ \fi
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
+ \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
+ \edef\p_framed_frame{\framedparameter\c!frame}%
+ \edef\p_framed_background{\framedparameter\c!background}%
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty \else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \pack_framed_add_outline % real or invisible frame
+ \fi\fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{#1}%
+ \pack_framed_add_background
+ \fi
+ \box\b_framed_normal
+ \egroup}
+
+\unexpanded\def\localbackgroundframed#1% namespace component box
+ {\bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \pack_framed_process_box_indeed} % group ends here
+
+\let\postprocessframebox\relax
+
+%D A nice example by Aditya:
+%D
+%D \starttyping
+%D \setupframed
+%D [loffset=\framedparameter{hoffset},
+%D roffset=\framedparameter{hoffset},
+%D hoffset=\zeropoint]
+%D
+%D \defineframed[test][hoffset=1cm]
+%D \stoptyping
+
+\newdimen\d_framed_width
+\newdimen\d_framed_height
+\newdimen\d_framed_frameoffset
+\newdimen\d_framed_backgroundoffset
+\newdimen\d_framed_local_offset
+
+% todo: protect local \framednames
+
+\unexpanded\def\localframed
+ {\bgroup
+ \dodoubleempty\pack_framed_local}
+
+\unexpanded\def\pack_framed_local[#1][#2]%
+ {\bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \ifsecondargument % faster
+ \setupcurrentframed[#2]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\unexpanded\def\directlocalframed[#1]% no optional
+ {\bgroup
+ \bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \pack_framed_process_indeed}
+
+\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
+ {\bgroup
+ \bgroup
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \setupcurrentframed[#2]% here !
+ \pack_framed_process_indeed}
+
+% done
+
+\def\c!fr!analyze{fr:analyze} % private option
+
+\let\delayedbegstrut\relax
+\let\delayedendstrut\relax
+\let\delayedstrut \relax
+
+\unexpanded\def\pack_framed_process_indeed
+ {\d_framed_frameoffset\framedparameter\c!frameoffset
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ % new, experimental dirty hook
+ \framedparameter\c!extras
+ % to get the right spacing
+ \edef\p_framed_foregroundstyle{\framedparameter\c!foregroundstyle}%
+ \ifx\p_framed_foregroundstyle\empty\else\dousestyleparameter\p_framed_foregroundstyle\fi
+ % beware, both the frame and background offset can be overruled
+ %
+ \edef\p_framed_setups{\framedparameter\c!setups}%
+ % the next macros are visible
+ \edef\localoffset{\framedparameter\c!offset}%
+ \edef\localwidth {\framedparameter\c!width}%
+ \edef\localheight{\framedparameter\c!height}%
+ \edef\localformat{\framedparameter\c!align}%
+ \edef\localstrut {\framedparameter\c!strut}%
+ % these are not
+ \edef\p_framed_autostrut {\framedparameter\c!autostrut}%
+ \edef\p_framed_frame {\framedparameter\c!frame}%
+ \edef\p_framed_location {\framedparameter\c!location}%
+ \edef\p_framed_orientation{\framedparameter\c!orientation}%
+ %
+ \edef\p_framed_autowidth {\framedparameter\c!autowidth}%
+ \edef\p_framed_franalyze {\framedparameter\c!fr!analyze}% experimental option
+ %
+ \ifx\p_framed_frame\v!overlay % no frame, no offset, no framewidth
+ \setfalse\c_framed_has_frame
+ \let\localoffset\v!overlay
+ \else\ifx\p_framed_frame\v!none % no frame, no framewidth
+ \setfalse\c_framed_has_frame
+ \else
+ \settrue\c_framed_has_frame
+ \fi\fi
+ \ifconditional\c_framed_has_frame
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}%
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
+ \fi
+ \else
+ \d_framed_linewidth\zeropoint
+ \fi
+ % 2013/03/12: a change of order (sizes before align
+ \ifx\localwidth\v!local
+ \setlocalhsize
+ \fi
+ %
+ \forgetall % should happen after \localwidth but before align
+ %
+ \ifx\localformat\empty
+ \setfalse\c_framed_has_format
+ \else
+ \settrue\c_framed_has_format
+ \dosetraggedcommand\localformat % not that fast
+ \fi
+ %
+ \ifcsname\??framedoffsetalternative\localoffset\endcsname
+ \lastnamedcs
+ \else
+ \framed_offset_alternative_unknown
+ \fi
+ \ifcsname\??framedwidthalternative\localwidth\endcsname
+ \lastnamedcs
+ \else
+ \framed_width_alternative_unknown
+ \fi
+ \ifcsname\??framedheightalternative\localheight\endcsname
+ \lastnamedcs
+ \else
+ \framed_height_alternative_unknown
+ \fi
+ % the next check could move to heightalternative
+ \ifconditional\c_framed_has_height
+ % obey user set height, also downward compatible
+ \else
+ \edef\p_framed_lines{\framedparameter\c!lines}%
+ \ifx\p_framed_lines\empty\else
+ \ifcase\p_framed_lines\else
+ \d_framed_height\p_framed_lines\lineheight
+ \edef\localheight{\the\d_framed_height}%
+ \settrue\c_framed_has_height
+ \fi
+ \fi
+ \fi
+ % this is now an option: width=local
+ %
+ % \ifdim\d_framed_width=\hsize
+ % \parindent\zeropoint
+ % \setlocalhsize
+ % \d_framed_width\localhsize
+ % \fi
+ % i.e. disable (colsetbackgroundproblemintechniek)
+ \advance\d_framed_width -2\d_framed_local_offset
+ \advance\d_framed_height -2\d_framed_local_offset
+ \ifcsname\??framedstrutalternative\localstrut\endcsname
+ \lastnamedcs
+ \else
+ \framed_offset_alternative_unknown
+ \fi
+ % the next check could move to strutalternative
+ \ifconditional\c_framed_has_strut
+ \let\localbegstrut\begstrut
+ \let\localendstrut\endstrut
+ \let\localstrut \strut
+ \else
+ \let\localbegstrut\pseudobegstrut % was: \relax
+ \let\localendstrut\pseudoendstrut % was: \relax
+ \let\localstrut \pseudostrut % was: \relax
+ %\ifconditional\c_framed_has_height\ifdim\d_framed_height<\strutht % saveguard
+ % \let\localbegstrut\relax % but not that
+ % \let\localstrut \relax % save after all
+ %\fi\fi
+ \fi
+ \ifx\p_framed_autostrut\v!yes
+ \let\delayedbegstrut\relax
+ \let\delayedendstrut\relax
+ \let\delayedstrut \relax
+ \else
+ \let\delayedbegstrut\localbegstrut
+ \let\delayedendstrut\localendstrut
+ \let\delayedstrut \localstrut
+ \let\localbegstrut \relax
+ \let\localendstrut \relax
+ \let\localstrut \relax
+ \fi
+ \ifconditional\c_framed_has_height
+ \let\\\pack_framed_vboxed_newline
+ \ifconditional\c_framed_has_width
+ \let\hairline\pack_framed_vboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_yes
+ \else
+ \let\next\pack_framed_format_format_nop
+ \fi
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_height
+ \else
+ \let\next\pack_framed_format_format_vsize
+ \fi
+ \fi
+ \else
+ \ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_format
+ \let\hairline\pack_framed_vboxed_hairline
+ \let\\\pack_framed_vboxed_newline
+ \let\next\pack_framed_format_format_width
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_hsize
+ \fi
+ \else
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_no_size
+ \fi
+ \fi
+ \pack_framed_check_extra_offsets
+ \edef\p_framed_background{\framedparameter\c!background}%
+% \ifx\p_framed_background\empty
+% \let\pack_framed_forgetall\forgetall
+% \else
+% \let\pack_framed_forgetall\relax
+% \forgetall
+% \fi
+ \edef\framedwidth {\the\ifdim\d_framed_width >\zeropoint \d_framed_width \else\zeropoint\fi}% public
+ \edef\framedheight{\the\ifdim\d_framed_height>\zeropoint \d_framed_height\else\zeropoint\fi}% public
+ \edef\framedoffset{\the\dimexpr\ifconditional\c_framed_has_offset\localoffset \else\zeropoint\fi}% public
+ \ifx\p_framed_orientation\empty
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \pack_framed_start_orientation
+ \fi
+ \afterassignment\pack_framed_restart
+ \setbox\b_framed_normal\next}
+
+% alternatives for width, height, strut and offset
+
+\installcorenamespace{framedwidthalternative}
+\installcorenamespace{framedheightalternative}
+\installcorenamespace{framedstrutalternative}
+\installcorenamespace{framedoffsetalternative}
+
+% widths
+
+\setvalue{\??framedwidthalternative\empty}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fit}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!broad}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!max}% idem broad
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!local}%
+ {\settrue\c_framed_has_width
+ %\setlocalhsize
+ \d_framed_width\localhsize}
+
+\setvalue{\??framedwidthalternative\s!unknown}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\localwidth}
+
+\def\framed_width_alternative_unknown
+ {\settrue\c_framed_has_width
+ \d_framed_width\localwidth}
+
+% heights
+
+\setvalue{\??framedheightalternative\empty}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!fit}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!broad}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!max}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\vsize}
+
+\setvalue{\??framedheightalternative\s!unknown}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\localheight}
+
+\def\framed_height_alternative_unknown
+ {\settrue\c_framed_has_height
+ \d_framed_height\localheight}
+
+% struts (use let instead?)
+
+\setvalue{\??framedstrutalternative\v!no}%
+ {\setfalse\c_framed_has_strut}
+
+\setvalue{\??framedstrutalternative\v!global}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\v!local}%
+ {\setfontstrut}
+
+\setvalue{\??framedstrutalternative\v!yes}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\s!unknown}%
+ {\setstrut}
+
+\def\framed_strut_alternative_unknown
+ {\setstrut}
+
+% offsets
+
+\setvalue{\??framedoffsetalternative\v!none}%
+ {\setfalse\c_framed_has_offset
+ \setfalse\c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \d_framed_local_offset\d_framed_linewidth}
+
+\setvalue{\??framedoffsetalternative\v!overlay}%
+ {% \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first
+ \setfalse\c_framed_has_offset
+ \setfalse\c_framed_has_strut
+ \settrue \c_framed_is_overlaid
+ \d_framed_local_offset\zeropoint}
+
+% \setvalue{\??framedoffsetalternative\v!strut}%
+% {\setfalse\c_framed_has_offset
+% \settrue \c_framed_has_strut
+% \settrue \c_framed_is_overlaid
+% \d_framed_local_offset\zeropoint}
+
+\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000
+ {\settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \let\localoffset\defaultframeoffset
+ \letframedparameter\c!offset\defaultframeoffset % brrr
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+\setvalue{\??framedoffsetalternative\s!unknown}%
+ {\settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \let\defaultframeoffset\localoffset
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+\def\framed_offset_alternative_unknown
+ {\settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \let\defaultframeoffset\localoffset
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+% so far for alternatives
+
+\let\pack_framed_stop_orientation\relax
+
+\def\pack_framed_restart
+ {\aftergroup\pack_framed_finish}
+
+\def\pack_framed_do_top
+ {\raggedtopcommand
+ \framedparameter\c!top
+ \edef\p_blank{\framedparameter\c!blank}%
+ \ifx\p_blank\v!yes\else % auto or no
+ \doinhibitblank
+ \fi}
+
+\def\pack_framed_do_bottom
+ {\framedparameter\c!bottom
+ \raggedbottomcommand}
+
+%D Careful analysis of this macro will learn us that not all branches in the last
+%D conditionals can be encountered, that is, some assignments to \type{\next} will
+%D never occur. Nevertheless we implement the whole scheme, if not for future
+%D extensions.
+
+%D \macros
+%D {doassigncheckedframeoffset}
+%D
+%D Offset helper (see menus):
+
+\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname
+ {\edef\checkedframeoffset{#2}%
+ #1%
+ \ifx\checkedframeoffset\empty \zeropoint\else
+ \ifx\checkedframeoffset\v!overlay\zeropoint\else
+ \ifx\checkedframeoffset\v!none \zeropoint\else
+ \ifx\checkedframeoffset\v!frame \zeropoint\else
+ \ifx\checkedframeoffset\v!default\zeropoint\else
+ #2%
+ \fi\fi\fi\fi\fi
+ \relax}
+
+%D \macros
+%D {ifreshapeframebox}
+%D
+%D The last few lines tell what to do after the content of the box is collected and
+%D passed to the next macro. In the case of a fixed width and centered alignment,
+%D the content is evaluated and used to determine the most natural width. The rest
+%D of the code deals with backgrounds and frames.
+
+\newif\ifreshapeframebox \reshapeframeboxtrue
+
+%D Beware: setting \type {top} and \type {bottom} to nothing, may
+%D result in a frame that is larger that the given height! try:
+%D
+%D \starttyping
+%D \framed
+%D [height=3cm,top=,bottom=,offset=overlay]
+%D {\strut test \shapefill \strut test}
+%D \stoptyping
+%D
+%D This is intended behaviour and not a bug! One can always set
+%D
+%D \starttyping
+%D ...,bottom=\kern0pt,...
+%D \stoptyping
+
+% experiment ... \p_framed_franalyze -> we could support 'first' as location key
+% option but then we will always do an analysis and reimplement the location
+% options (btw, beware of location settings of derived functionality that bleed
+% into this
+
+\def\pack_framed_finish_a
+ {\ifreshapeframebox
+ \pack_framed_reshape_process
+ \else\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi\fi
+ \setfalse\c_framed_has_width}
+
+\def\pack_framed_finish_b
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi
+ \setfalse\c_framed_has_width}
+
+\def\pack_framed_finish_c
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
+ \else
+ \pack_framed_reshape_reset
+ \fi}
+
+\def\pack_framed_profile_box
+ {\profilegivenbox\p_profile\b_framed_normal
+ \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}}
+
+\unexpanded\def\pack_framed_finish
+ {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down
+ \pack_framed_locator_before\p_framed_location
+ \ifconditional\c_framed_has_format
+ %\ifconditional\c_framed_has_height \else
+ % \edef\p_profile{\framedparameter\c!profile}%
+ % \ifx\p_profile\empty\else
+ % \pack_framed_profile_box
+ % \fi
+ %\fi
+ \ifx\p_framed_autowidth\v!force
+ \pack_framed_finish_a
+ \else\ifx\localwidth\v!fit
+ \ifx\p_framed_autowidth\v!yes
+ \pack_framed_finish_a
+ \else
+ \pack_framed_finish_b
+ \fi
+ \else\ifx\localwidth\v!fixed
+ \pack_framed_finish_b
+ \else
+ \pack_framed_finish_c
+ \fi\fi\fi
+ \ifconditional\c_framed_has_height \else
+ \edef\p_profile{\framedparameter\c!profile}%
+ \ifx\p_profile\empty\else
+ \pack_framed_profile_box
+ \fi
+ \fi
+ \ifconditional\page_postprocessors_needed_box
+ % quite late
+ \page_postprocessors_linenumbers_box\b_framed_normal
+ \fi
+ \else
+ \pack_framed_finish_c
+ \fi
+ \ifconditional\c_framed_has_width
+ \wd\b_framed_normal\d_framed_width
+ \fi
+ \ifconditional\c_framed_has_height
+ \ht\b_framed_normal\d_framed_height
+ \fi
+ \edef\p_framed_empty{\framedparameter\c!empty}%
+ \ifx\p_framed_empty\v!yes
+ \pack_framed_fake_box
+ \fi
+ \pack_framed_stop_orientation % moved here at 2014-05-25
+ \iftrialtypesetting \else
+ \edef\p_framed_region{\framedparameter\c!region}%
+ \ifx\p_framed_region\v!yes % maybe later named
+ \pack_framed_add_region
+ \fi
+ \fi
+ \d_framed_applied_offset
+ \ifconditional\c_framed_is_overlaid
+ \zeropoint
+ \else
+ \d_framed_linewidth
+ \fi
+ \ifconditional\c_framed_has_offset
+ \advance\d_framed_applied_offset\localoffset
+ \fi
+ \ifconditional\c_framed_has_extra_offset
+ \pack_framed_apply_extra_offsets % includes \d_framed_applied_offset
+ \else
+ \ifzeropt\d_framed_applied_offset
+ \else
+ \pack_framed_widen_box
+ \fi
+ \fi
+ %
+ \ifx\postprocessframebox\relax \else
+ \let\next\postprocessframebox
+ \let\postprocessframebox\relax % prevent nesting
+ \next\b_framed_normal
+ \fi
+ \iftrialtypesetting
+ % new
+ \else
+ \ifconditional\c_framed_has_frame % real or invisible frame
+ \pack_framed_add_outline
+ \fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
+ \fi
+ \pack_framed_locator_after\p_framed_location
+ \box\b_framed_normal
+ \global\frameddimensionstate % global so to be used directly afterwards !
+ \ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_height \plusthree \else \plusone \fi
+ \else
+ \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi
+ \fi
+ \egroup
+ \egroup}
+
+\installcorenamespace{framedlocatorbefore}
+\installcorenamespace{framedlocatorafter}
+
+\newconstant\frameddimensionstate % global state: 0=unknown 1=width 2=height 3=both
+
+\def\pack_framed_fake_box
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\b_framed_normal
+ \ht\scratchbox\ht\b_framed_normal
+ \dp\scratchbox\dp\b_framed_normal
+ \setbox\b_framed_normal\box\scratchbox}
+
+\def\installframedlocator#1#2#3%
+ {\setvalue{\??framedlocatorbefore#1}{#2}%
+ \setvalue{\??framedlocatorafter #1}{#3}}
+
+\def\pack_framed_locator_before#1{\csname\??framedlocatorbefore#1\endcsname}
+\def\pack_framed_locator_after #1{\csname\??framedlocatorafter #1\endcsname}
+
+\newdimen\d_framed_locator_ht
+\newdimen\d_framed_locator_dp
+
+\def\pack_framed_locater_set#1%
+ {\d_framed_locator_ht\dimexpr
+ #1+\d_framed_linewidth
+ \ifconditional\c_framed_has_offset
+ +\framedparameter\c!offset
+ \fi
+ \relax
+ \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax}
+
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=hanging]{location\\equals\\hanging}
+% \framed[width=2cm,align=middle,location=depth] {location\\equals\\depth}
+% \framed[width=2cm,align=middle,location=height] {location\\equals\\height}
+% B}
+% \vskip2cm
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=low] {location\\equals\\low}
+% \framed[width=2cm,align=middle,location=line] {location\\equals\\line}
+% \framed[width=2cm,align=middle,location=high] {location\\equals\\high}
+% B}
+% \vskip2cm
+% \ruledhbox
+% {A
+% \framed[width=2cm,align=middle,location=top] {location\\equals\\top}
+% \framed[width=2cm,align=middle,location=bottom] {location\\equals\\bottom}
+% \framed[width=2cm,align=middle,location=lohi] {location\\equals\\lohi}
+% \framed[width=2cm,align=middle,location=middle] {location\\equals\\middle}
+% B}
+
+% \installframedlocator \v!hanging % best with strut=no
+% {}
+% {\dp\b_framed_normal\ht\b_framed_normal
+% \ht\b_framed_normal\zeropoint}
+%
+% \installframedlocator \v!depth
+% {}
+% {\ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
+% \dp\b_framed_normal\strutdp
+% \box\b_framed_normal}
+%
+% \installframedlocator \v!height
+% {}
+% {\dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
+% \ht\b_framed_normal\strutht
+% \box\b_framed_normal}
+
+\installframedlocator \v!hanging % best with strut=no *1* / see mail to list by SB
+ {}
+ {\scratchdimen\ht\b_framed_normal
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \dp\b_framed_normal\scratchdimen
+ \ht\b_framed_normal\zeropoint
+ \box\b_framed_normal}
+
+\installframedlocator \v!depth % *1*
+ {}
+ {\setbox\b_framed_normal\hpack{\lower\strutdp\box\b_framed_normal}%
+ \ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
+
+\installframedlocator \v!height % *1*
+ {}
+ {\scratchdimen\dimexpr \ht\b_framed_normal - \strutht \relax
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
+ \ht\b_framed_normal\strutht
+ \box\b_framed_normal}
+
+\installframedlocator \v!high
+ {}
+ {\pack_framed_locater_set\strutht
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \hpack{\box\b_framed_normal}}
+
+\installframedlocator \v!line
+ {}
+ {\setbox\b_framed_normal\hpack{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
+ \ht\b_framed_normal.5\lineheight
+ \dp\b_framed_normal.5\lineheight
+ \hpack{\box\b_framed_normal}}
+
+\installframedlocator \v!low
+ {}
+ {\pack_framed_locater_set\strutdp
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
+
+\installframedlocator \v!top
+ {}
+ {\pack_framed_locater_set\strutht
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_ht
+ \dp\b_framed_normal\d_framed_locator_dp
+ \hpack{\box\b_framed_normal}}
+
+\installframedlocator \v!middle
+ {}
+ {\scratchdimen.5\ht\b_framed_normal
+ \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
+ \ht\b_framed_normal\scratchdimen
+ \dp\b_framed_normal\scratchdimen
+ \hpack{\box\b_framed_normal}}
+
+\installframedlocator \v!lohi
+ {\pack_framed_locator_before\v!middle}
+ {\pack_framed_locator_after \v!middle}
+
+\installframedlocator \v!bottom
+ {}
+ {\pack_framed_locater_set\strutdp
+ \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_dp
+ \dp\b_framed_normal\d_framed_locator_ht
+ \hpack{\box\b_framed_normal}}
+
+\installframedlocator \v!keep % retains height/depth
+ {\pack_framed_remove_depth}
+ {\pack_framed_restore_depth}
+
+% also used in fastlocalframed
+
+\newdimen\d_framed_original_wd
+\newdimen\d_framed_original_ht
+\newdimen\d_framed_original_dp
+
+\def\pack_framed_remove_depth
+ {\d_framed_original_wd\wd\b_framed_normal
+ \d_framed_original_ht\ht\b_framed_normal
+ \d_framed_original_dp\dp\b_framed_normal
+ \ifzeropt\d_framed_original_dp\else
+ \setbox\b_framed_normal\hpack{\raise\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax
+ \dp\b_framed_normal\zeropoint}
+
+\def\pack_framed_restore_depth
+ {\ifzeropt\d_framed_original_dp \else
+ \setbox\b_framed_normal\hpack{\lower\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\d_framed_original_ht
+ \dp\b_framed_normal\d_framed_original_dp}
+
+% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=180]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=270]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-90]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax}
+% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax}
+
+% \def\pack_framed_start_orientation
+% {\ifcase\p_framed_orientation
+% \let\pack_framed_stop_orientation\relax
+% \else
+% \scratchcounter\p_framed_orientation % weird .. why
+% \divide\scratchcounter\plustwo
+% \ifodd\scratchcounter
+% \let\pack_framed_stop_orientation\pack_framed_stop_orientation_odd
+% \else
+% \let\pack_framed_stop_orientation\pack_framed_stop_orientation_even
+% \fi
+% \fi}
+%
+% \def\pack_framed_stop_orientation_odd
+% {\swapmacros\framedwidth\framedheight
+% \swapmacros\localwidth\localheight
+% \swapdimens\d_framed_height\d_framed_width
+% \pack_framed_stop_orientation_even}
+%
+% \def\pack_framed_stop_orientation_even
+% {\setbox\b_framed_normal\hbox{\dorotatebox\p_framed_orientation\hbox{\box\b_framed_normal}}%
+% \d_framed_height\ht\b_framed_normal
+% \d_framed_width \wd\b_framed_normal}
+
+\def\pack_framed_start_orientation
+ {\ifcase\p_framed_orientation
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \let\pack_framed_stop_orientation\pack_framed_stop_orientation_indeed
+ \fi}
+
+\def\pack_framed_stop_orientation_indeed
+ {\setbox\b_framed_normal\hpack{\dorotatebox\p_framed_orientation\hpack{\box\b_framed_normal}}%
+ \d_framed_height\ht\b_framed_normal
+ \d_framed_width \wd\b_framed_normal}
+
+%D The last conditional takes care of the special situation of in||line \inframed
+%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the
+%D running text.
+
+\unexpanded\def\inframed
+ {\dosingleempty\pack_framed_inline}
+
+% \def\pack_framed_inline[#1]%
+% {\framed[\c!location=\v!low,#1]}
+%
+% or:
+
+\def\pack_framed_inline[%
+ {\framed[\c!location=\v!low,}
+
+%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background,
+%D but no content, so actually we have a sort of phantom framed box.
+
+%D \macros
+%D {mframed, minframed}
+%D
+%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the
+%D next macro:
+%D
+%D \starttyping
+%D \def\mframed#1%
+%D {\relax
+%D \ifmmode
+%D \vcenter{\hbox{\framed{$\ifinner\else\displaystyle\fi#1$}}}%
+%D \else
+%D \framed{$#1$}%
+%D \fi}
+%D \stoptyping
+%D
+%D Because \type {\ifinner} does not (always) reports what one would expect, we move the
+%D test to the outer level. We also want to pass arguments,
+%D
+%D \starttyping
+%D \def\mframed%
+%D {\dosingleempty\domframed}
+%D
+%D \def\domframed[#1]#2% % tzt \dowithnextmathbox ?
+%D {\relax
+%D \ifmmode
+%D \ifinner
+%D \inframed[#1]{$#2$}%
+%D \else
+%D \vcenter{\hbox{\framed[#1]{$\displaystyle#2$}}}%
+%D \fi
+%D \else
+%D \inframed[#1]{$#2$}%
+%D \fi}
+%D \stoptyping
+%D
+%D Still better is the next alternative, if only because it takes care of setting the super-
+%D and subscripts styles
+
+\newcount\c_framed_mstyle
+
+\unexpanded\def\pack_framed_math_strut
+ {\Ustartmath
+ \triggermathstyle\c_framed_mstyle
+ \vphantom{(}%
+ \Ustopmath}
+
+\installcorenamespace{mathframed}
+
+\installframedcommandhandler \??mathframed {mathframed} \??mathframed
+
+\appendtoks
+ \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}%
+\to \everydefinemathframed
+
+\unexpanded\def\pack_framed_mathframed#1%
+ {\begingroup
+ \edef\currentmathframed{#1}%
+ \dosingleempty\pack_framed_mathframed_indeed}
+
+% \def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
+% {\iffirstargument
+% \setupcurrentmathframed[#1]%
+% \fi
+% \c_framed_mstyle\mathstyle
+% \doifnot{\mathframedparameter\c!location}\v!low{\let\normalstrut\pack_framed_math_strut}%
+% \inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
+% \endgroup}
+
+\newcount\c_pack_framed_mc
+
+\def\pack_framed_math_pos
+ {\global\advance\c_pack_framed_mc\plusone
+ \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mc}%
+ \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mc}%
+ \xypos\pack_framed_mc_two}
+
+\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
+ {\iffirstargument
+ \setupcurrentmathframed[#1]%
+ \fi
+ \c_framed_mstyle\mathstyle
+ \edef\m_framed_location{\mathframedparameter\c!location}%
+ \ifx\m_framed_location\v!mathematics
+ \let\normalstrut\pack_framed_math_pos
+ \else\ifx\m_framed_location\v!low\else
+ \let\normalstrut\pack_framed_math_strut
+ \fi\fi
+ \inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
+ \endgroup}
+
+\installframedlocator \v!mathematics
+ {}
+ {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax
+ \hpack{\xypos\pack_framed_mc_one\box\b_framed_normal}}
+
+\definemathframed[mframed]
+\definemathframed[inmframed][\c!location=\v!low]
+\definemathframed[mcframed] [\c!location=\v!mathematics]
+
+%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}:
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{z_z}
+%D x \times \inmframed{y} \times y^{z_z}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D And:
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D As usual, one can specify in what way the text should be framed. One should be
+%D aware of the fact that, inorder to preserve the proper spacing, the \type
+%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times y^{\mframed[framecolor=red]{z}_{z}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D For inline use, we also provide the \type {\inmframed} alternative: we want $x
+%D \times \inmframed{y}$ in inline math, right?
+
+%D This previous framing macros needs a lot of alternatives for putting rules around
+%D boxes, inserting offsets and aligning text. Each step is handled by separate macros.
+
+\newdimen\d_framed_applied_offset
+\newdimen\d_framed_loffset
+\newdimen\d_framed_roffset
+\newdimen\d_framed_toffset
+\newdimen\d_framed_boffset
+
+\def\pack_framed_check_extra_offsets % we could check h and v indepently
+ {\setfalse\c_framed_has_extra_offset
+ \d_framed_loffset\framedparameter\c!loffset\relax
+ \d_framed_roffset\framedparameter\c!roffset\relax
+ \d_framed_toffset\framedparameter\c!toffset\relax
+ \d_framed_boffset\framedparameter\c!boffset\relax
+ \ifzeropt\d_framed_loffset\else \advance\d_framed_width -\d_framed_loffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_roffset\else \advance\d_framed_width -\d_framed_roffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_toffset\else \advance\d_framed_height-\d_framed_toffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi}
+
+\def\pack_framed_apply_extra_offsets
+ {\setbox\b_framed_normal\vpack\bgroup
+ \advance\d_framed_toffset\d_framed_applied_offset
+ \advance\d_framed_boffset\d_framed_applied_offset
+ \advance\d_framed_loffset\d_framed_applied_offset
+ \advance\d_framed_roffset\d_framed_applied_offset
+ \kern\d_framed_toffset
+ \hpack\bgroup
+ \kern\d_framed_loffset
+ \box\b_framed_normal
+ \kern\d_framed_roffset
+ \egroup
+ \kern\d_framed_boffset
+ \egroup}
+
+\def\pack_framed_widen_box
+ {\setbox\b_framed_normal\vpack
+ {\kern\d_framed_applied_offset
+ \hpack{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
+ \kern\d_framed_applied_offset}}
+
+%D Let's hope that the next few examples show us enough of what needs to be
+%D done by the auxiliary macros.
+%D
+%D \startbuffer
+%D \framed[height=1cm,offset=.5cm] {rule based learning}
+%D \framed[height=1cm,offset=0cm] {rule based learning}
+%D \framed[height=1cm,offset=none] {rule based learning}
+%D \framed[height=1cm,offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[offset=.5cm] {rule based learning}
+%D \framed[offset=0cm] {rule based learning}
+%D \framed[offset=none] {rule based learning}
+%D \framed[offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[strut=no,offset=.5cm] {rule based learning}
+%D \framed[strut=no,offset=0cm] {rule based learning}
+%D \framed[strut=no,offset=none] {rule based learning}
+%D \framed[strut=no,offset=overlay]{rule based learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D \startbuffer
+%D \framed[width=3cm,align=left] {rule\\based\\learning}
+%D \framed[width=3cm,align=middle] {rule\\based\\learning}
+%D \framed[width=3cm,align=right] {rule\\based\\learning}
+%D \framed[width=fit,align=middle] {rule\\based\\learning}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\dontcomplain\getbuffer}
+%D \stoplinecorrection
+%D
+%D So now we're ready for the complicated stuff. We distinguish between borders with
+%D straight lines and those with round corners. When using the first alternative it
+%D is possible to turn off one or more lines. More fancy shapes are also possible by
+%D specifying dedicated backgrounds. Turning lines on and off is implemented as
+%D efficient as possible and as a result is interface language dependant. This next
+%D implementation evolved from simpler ones. It puts for instance the rules on top
+%D of the content and provides additional offset capabilities. The lot of calls to
+%D other macros makes this mechanism not that easy to comprehend.
+%D
+%D We handle left, right or middle alignment as well as fixed or free widths and
+%D heights. Each combination gets its own macro.
+%D
+%D The following code handles one-liners: \type {align={line,flushright}}. Beware,
+%D since we entered a group and either or not grab the next bgroup token, we need to
+%D finish the group in the oneliner mode.
+
+\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
+
+\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
+ {\ifconditional\raggedonelinerstate
+ \expandafter\dodoformatonelinerbox
+ \else
+ \expandafter\nodoformatonelinerbox
+ \fi}
+
+\def\dodoformatonelinerbox
+ {\afterassignment\redoformatonelinerbox
+ \setbox\nextbox\hbox} % maybe \hpack
+
+\def\redoformatonelinerbox
+ {\aftergroup\dododoformatonelinerbox
+ \ignorespaces}
+
+\def\dododoformatonelinerbox
+ {\hbox to \hsize % maybe \hpack
+ {\ifcase\raggedstatus\or\hss\or\hss \fi
+ \unhbox\nextbox \removeunwantedspaces
+ \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
+ \egroup}
+
+\def\nodoformatonelinerbox % grabs {
+ {\let\next=}
+
+%D The handlers:
+
+% Beware, we have a \noindent so an empty line is indeed an empty line and
+% the \synchronizeinlinedirection triggers a vbox instead of a line.
+%
+% \startTEXpage[offset=0.5ex,align={lohi,middle}]
+%
+% \vbox{\hbox{x}}
+% \stopTEXpage
+%
+% \startTEXpage[offset=0.5ex,align={lohi,middle}]
+% \vbox{\hbox{x}}
+% \stopTEXpage
+
+% \def\pack_framed_forgetall{\forgetall}
+
+\def\pack_framed_set_foregroundcolor
+ {\edef\p_framed_foregroundcolor{\framedparameter\c!foregroundcolor}%
+ \ifx\p_framed_foregroundcolor\empty\else\dousecolorparameter\p_framed_foregroundcolor\fi}
+
+\def\pack_framed_do_setups
+ {\ifx\p_framed_setups\empty \else
+ \setups[\p_framed_setups]% \texsetup (or only one!)
+ % \fastsetup\p_framed_setup % singular would have been better
+ \fi}
+
+\def\pack_framed_format_format_yes
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \raggedcommand
+ \pack_framed_do_top
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\pack_framed_do_bottom
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_nop
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \raggedcenter
+ \vss
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_height
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \pack_framed_do_setups
+ \raggedcommand
+ \vss
+ \bgroup
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_width
+ {\vbox
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \oninterlineskip
+ \hsize\d_framed_width
+ \pack_framed_do_setups
+ \raggedcommand
+ \pack_framed_do_top
+ \bgroup
+ \synchronizeinlinedirection
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\pack_framed_do_bottom
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_vsize
+ {\vbox to \d_framed_height
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \vsize\d_framed_height
+ \pack_framed_do_setups
+ \vss
+ \bgroup
+ \aftergroup\vss
+ \aftergroup\egroup
+ \hbox
+ \bgroup
+ \aftergroup\egroup
+ \synchronizeinlinedirection
+ \localstrut
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_hsize
+ {\hbox to \d_framed_width
+ \bgroup
+ \let\postprocessframebox\relax
+ % \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \pack_framed_do_setups
+ \hss
+ \synchronizeinlinedirection
+ \localstrut
+ \bgroup
+ \aftergroup\hss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\pack_framed_format_format_no_size
+ {\hbox
+ \bgroup
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \let\postprocessframebox\relax
+ \pack_framed_do_setups
+ \synchronizeinlinedirection
+ \localstrut
+ \doformatonelinerbox}
+
+%D On the next page we show some examples of how these macros come into action. The
+%D examples show us how \type {fit}, \type {broad} dimensions influence the
+%D formatting. Watch the visualized struts. \footnote {Here we used \type
+%D {\showstruts}.}
+%D
+%D \startpostponing
+%D \bgroup
+%D \showstruts
+%D \dontcomplain
+%D \starttabulate[|c|c|c|c|c|c|]
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \stoptabulate
+%D \egroup
+%D \stoppostponing
+
+%D \macros
+%D {framednoflines, framedlastlength}
+%D
+%D It is possible to let the frame macro calculate the width of a centered box
+%D automatically (\type {fit}). When doing so, we need to reshape the box:
+
+\newcount\framednoflines
+\newdimen\framedfirstheight
+\newdimen\framedlastdepth
+\newdimen\framedminwidth
+\newdimen\framedmaxwidth
+\newdimen\framedaveragewidth
+
+\def\pack_framed_reshape_reset
+ {\framednoflines \zerocount
+ \framedfirstheight \zeropoint
+ \framedlastdepth \zeropoint
+ \framedminwidth \zeropoint
+ \framedmaxwidth \zeropoint
+ \framedaveragewidth\zeropoint}
+
+\def\pack_framed_reshape_process{\ifvbox\b_framed_normal\clf_doreshapeframedbox\b_framed_normal\relax\fi}
+\def\pack_framed_reshape_analyze{\ifvbox\b_framed_normal\clf_doanalyzeframedbox\b_framed_normal\relax\fi}
+
+% torture test / strange case (much depth) / method 2 needed
+%
+% \startTEXpage[frame=on]
+% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
+% test outside formula
+% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
+% \blank[big]
+% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
+% test outside formula
+% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
+% \stopTEXpage
+
+%D The examples on the next page show how one can give the frame as well as the
+%D background an additional offset and even a bit more depth. The blue outline is
+%D the frame, the red box is the background and the small black outline is the
+%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to
+%D the result.
+%D
+%D \startpostponing
+%D \bgroup
+%D \unprotect
+%D \dontcomplain
+%D
+%D \startbuffer
+%D \vbox to \vsize
+%D \bgroup
+%D \startalignment[middle]
+%D \vss
+%D \dontleavehmode\vbox to .8\vsize
+%D \bgroup
+%D \hsize=300pt
+%D \setupframed
+%D [background=color,
+%D backgroundcolorachtergrondkleur=darkred,
+%D width=300pt,
+%D height=60pt,
+%D framecolorkaderkleur=DemoBlue,
+%D rulethickness=2pt]
+%D \def\status%
+%D {backgroundoffset=\the\dimexpr\framedparameter\c!backgroundoffset\relax\\
+%D frameoffset=\the\dimexpr\framedparameter\c!frameoffset\relax\\
+%D depth=\the\dimexpr\framedparameter\c!depth\relax}
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=0pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=0pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=5pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=2pt,frameoffset=5pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=2pt]{\status}}
+%D \vss
+%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=5pt]{\status}}
+%D \egroup
+%D \vss
+%D \stopalignment
+%D \egroup
+%D \stopbuffer
+%D
+%D \getbuffer \page
+%D
+%D {\setupframed[depth=4pt]\getbuffer} \page
+%D
+%D \protect
+%D \egroup
+%D \stoppostponing
+
+%D We can draw lines from left to right and top to bottom by using the normal \type
+%D {\hairline} command. Both directions need a different treatment.
+%D
+%D \startbuffer
+%D \framed[width=4cm] {alfa\hairline beta\hairline gamma}
+%D \framed[height=2cm] {alfa\hairline beta\hairline gamma}
+%D \framed[width=4cm,height=2cm]{alfa\hairline beta\hairline gamma}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \hbox{\getbuffer}
+%D \stoplinecorrection
+%D
+%D These macros try to adapt their behaviour as good as possible to the circumstances
+%D and act as natural as possible.
+
+\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
+ {\begingroup
+ \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \dontleavehmode
+ \hrule\s!height\d_framed_linewidth\s!depth\zeropoint
+ \par
+ \kern-\d_framed_linewidth
+ \dontleavehmode
+ \hpack to \zeropoint{\normalhss\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}%
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \nointerlineskip
+ \endgraf
+ \nointerlineskip
+ \localbegstrut
+ \endgroup}
+
+\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
+ {\bgroup
+ \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \ifconditional\c_framed_has_height
+ \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax
+ \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax
+ \else
+ \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax
+ \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax
+ \fi
+ \unskip
+ \setbox\scratchbox\hpack
+ {\kern\scratchoffset
+ \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth
+ \kern\scratchoffset}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \ignorespaces
+ \egroup}
+
+%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In
+%D horizontal boxes it expands to a space.
+
+\unexpanded\def\pack_framed_vboxed_newline
+ {\endgraf\ignorespaces}
+
+\unexpanded\def\pack_framed_hboxed_newline
+ {\unskip\normalspace\ignorespaces}
+
+%D We can set each rule on or off. The default setting is inherited from
+%D \type {frame}. An earlier implementation use a bit different approach, but the new
+%D one seems more natural:
+%D
+%D \bgroup
+%D \setuptyping[margin=0pt]
+%D \startlinecorrection
+%D \startbuffer
+%D \framed[offset=overlay,frame=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=on,bottomframe=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=on,bottomframe=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off,bottomframe=off]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D
+%D \startbuffer
+%D \framed[offset=overlay,frame=off,bottomframe=on]{\darkred\blackrule}
+%D \stopbuffer
+%D \hbox{\getbuffer\vbox{\typebuffer}}
+%D \stoplinecorrection
+%D \egroup
+
+%D \macros
+%D {startframedtext, setupframedtexts, defineframedtext}
+%D
+%D The general framing command we discussed previously, is not entirely suited for
+%D what we call framed texts, as for instance used in intermezzo's. The next
+%D examples show what we have in mind.
+%D
+%D \startbuffer[framed-0]
+%D \setupframedtexts
+%D [frame=off,
+%D width=\hsize,
+%D background=screen]
+%D
+%D \startframedtext
+%D By default the framed text is centered \dots
+%D \stopframedtext
+%D
+%D \startframedtext[right]
+%D \dots\ but we can also align left, middle and right.
+%D \stopframedtext
+%D \stopbuffer
+%D
+%D \startbuffer[framed-1]
+%D \defineframedtext
+%D [Example]
+%D [width=6cm,
+%D height=5cm]
+%D
+%D \startExample
+%D \typebuffer[framed-1]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-2]
+%D \defineframedtext
+%D [Example]
+%D [width=6cm]
+%D
+%D \startExample
+%D \typebuffer[framed-2]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-3]
+%D \defineframedtext
+%D [Example]
+%D [height=5cm]
+%D
+%D \startExample
+%D \typebuffer[framed-3]
+%D \stopExample
+%D \stopbuffer
+%D
+%D \startbuffer[framed-4]
+%D \defineframedtext
+%D [Example]
+%D [width=fit,height=broad]
+%D
+%D \Example{a very exciting example}
+%D \stopbuffer
+%D
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-0] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-1] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-2] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup
+%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup
+%D
+%D Here we can see that we have a predefined framed text class as well as the
+%D tools for defining our own. So we have:
+%D
+%D \showsetup{setupframedtexts}
+%D
+%D as well as the definition command:
+%D
+%D \showsetup{defineframedtext}
+%D
+%D that generates two commands:
+%D
+%D \showsetup{start<<framedtext>>}
+%D \showsetup{<<framedtext>>}
+%D
+%D The next definition shows the defaults.
+
+\installcorenamespace{framedtext}
+\installcorenamespace{framedtextlocation}
+
+\installframedcommandhandler \??framedtext {framedtext} \??framedtext
+
+\let\setupframedtexts\setupframedtext
+
+\setupframedtext
+ [\c!width=.75\hsize,
+ \c!height=\v!fit,
+ \c!align=\v!yes,
+ %\c!top=,
+ \c!bottom=\vfill,
+ \c!offset=1em,
+ %\c!bodyfont=,
+ %\c!style=,
+ %\c!color=,
+ %\c!left=,
+ \c!right=\hfill,
+ \c!before=\blank,
+ \c!after=\blank,
+ %\c!inner=,
+ \c!frame=\v!on,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ %\c!orientation=,
+ %\c!indenting=,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!linecorrection=\v!on,
+ \c!depthcorrection=\v!on,
+ \c!margin=\v!standard]
+
+\appendtoks
+ \setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}%
+ \setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }%
+ \setuevalue {\currentframedtext}{\pack_framed_text_direct{\currentframedtext}}%
+\to \everydefineframedtext
+
+\setvalue{\??framedtextlocation\v!left }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!right }{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\relax}
+
+\setvalue{\??framedtextlocation\v!middle}{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!none }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\relax
+ \settrue\c_framed_text_location_none}
+
+\unexpanded\def\pack_framed_text_start#1%
+ {\bgroup
+ \edef\currentframedtext{#1}%
+ \dodoubleempty\pack_framed_text_start_indeed}
+
+\def\pack_framed_text_start_indeed[#1][#2]%
+ {\doifelseassignment{#1}
+ {\pack_framed_text_start_continue\empty{#1}}
+ {\pack_framed_text_start_continue{#1}{#2}}}
+
+\def\pack_framed_text_start_continue#1#2%
+ {\setupframedtexts[\currentframedtext][#2]%
+ \doifsomething{#1}{\setframedtextparameter\c!location{#1}}% does not listen to #3
+ \setfalse\c_framed_text_location_none
+ \csname\??framedtextlocation\framedtextparameter\c!location\endcsname
+ \resetframedtextparameter\c!location
+ \pack_framed_text_check
+ \setbox\b_framed_normal\vbox
+ \startboxedcontent
+ \hsize\localhsize
+ % \insidefloattrue % ? better
+ \usebodyfontparameter\framedtextparameter
+ \letframedtextparameter\c!strut\v!no
+ \inheritedframedtextframed\bgroup
+ \let\\=\endgraf
+ \framedtextparameter\c!inner % oud spul
+ \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}%
+ \ifx\p_framed_text_depthcorrection\v!on
+ \pack_framed_text_start_depth_correction
+ \else
+ \bgroup
+ \fi
+ \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
+ \doinhibitblank
+ \useindentingparameter\framedtextparameter
+ \useframedtextstyleandcolor\c!style\c!color
+ \ignorespaces}
+
+% testcase 1:
+%
+% \showstruts
+% \startframedtext[align={normal,tolerant},offset=0pt] \input tufte \stopframedtext
+% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \input tufte \stopframedtext
+% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \inframed{x} \stopframedtext
+% \framed[align={normal,tolerant},offset=0pt]{\input tufte }
+
+%D The \type {none} option is handy for nested usage, as in the presentation
+%D styles, where we don't want interference.
+
+\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
+
+\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
+ {\endgraf
+ \removelastskip
+ \ifx\p_framed_text_depthcorrection\v!on
+ \pack_framed_text_stop_depth_correction
+ \else
+ \egroup
+ \fi
+ \stopboxedcontent
+ \ifconditional\c_framed_text_location_none
+ \egroup
+ \box\b_framed_normal
+ \else\ifinsidefloat
+ \egroup
+ \box\b_framed_normal
+ \else
+ \egroup
+ \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}%
+ \fi\fi
+ \egroup}
+
+%D We define the general (and original) case by just saying:
+
+\def\pack_framed_text_check % messy dependency
+ {\localhsize\hsize
+ \ifinsidefloat \else \ifdim\d_page_sides_vsize>\zeropoint % also possible: \c_page_sides_checks_done>\zeropoint
+ % \strut % rather clean way to invoke the sidefloat OTR
+ % \setbox0=\lastbox % and get the widths set, so from now on we
+ % \setlocalhsize % can have framed texts alongside sidefloats
+ \checksidefloat
+ \setlocalhsize
+ \fi \fi}
+
+\def\pack_framed_text_start_depth_correction
+ {\bgroup
+ \ifhmode
+ \par
+ \fi
+ \ifvmode
+ \verticalstrut
+ % we need \nowhitespace in case of setups setting whitespace
+ % nb, not safe, text vs \vbox as next
+ \vskip-\struttotal
+ \nowhitespace
+ \fi} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
+
+\def\pack_framed_text_stop_depth_correction
+ {\ifhmode
+ \par
+ \fi
+ \ifvmode
+ \forgetall
+ \vskip-\struttotal
+ \verticalstrut
+ \egroup
+ \forgetall % brrr too often
+ \vskip-\lineheight
+ \verticalstrut
+ \else
+ \egroup
+ \fi}
+
+%D Placement can be ignored:
+%D
+%D \starttyping
+%D \hbox to \hsize \bgroup
+%D \startframedtext[none][width=.5\textwidth] \input tufte \stopframedtext
+%D \startframedtext[none][width=.5\textwidth] \input zapf \stopframedtext
+%D \egroup
+%D
+%D \hbox to \hsize \bgroup
+%D \setupframedtexts[location=none]%
+%D \startframedtext[width=.5\textwidth] \input zapf \stopframedtext
+%D \startframedtext[width=.5\textwidth] \input tufte \stopframedtext
+%D \egroup
+%D \stoptyping
+
+%D The simple brace (or group) delimited case is typeset slightly different
+%D and is not aligned.
+
+\unexpanded\def\pack_framed_text_direct#1%
+ {\bgroup
+ \edef\currentframedtext{#1}%
+ \dosingleempty\pack_framed_text_start_direct}
+
+\def\pack_framed_text_start_direct[#1]%
+ {\usebodyfontparameter\framedtextparameter
+ \letframedtextparameter\c!strut\v!no
+ \iffirstargument
+ \setupcurrentframedtext[#1]%
+ \fi
+ \inheritedframedtextframed\bgroup
+ \blank[\v!disable]%
+ \let\\=\endgraf
+ \framedtextparameter\c!inner
+ \useframedtextstyleandcolor\c!style\c!color
+ \bgroup
+ \aftergroup\pack_framed_text_stop_direct
+ \let\next=}
+
+\def\pack_framed_text_stop_direct
+ {\removelastskip
+ \egroup
+ \egroup}
+
+\defineframedtext
+ [\v!framedtext]
+
+%D \macros
+%D {defineframed}
+%D
+%D One can also define simple framed texts, using:
+%D
+%D \showsetup{defineframed}
+%D
+%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead
+%D of passing a combination of arguments. This also also simplified the \type
+%D {\setupframed} command. There are certainly more places where such improvements
+%D can be made.
+
+\appendtoks
+ \ifcsname\??regularframedlevel\currentframed\endcsname
+ % already defined, keeps settings
+ \else
+ \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
+ \fi
+\to \everypresetframed
+
+\appendtoks
+ \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}%
+\to \everydefineframed
+
+\newcount\c_temp_framed_crap
+
+\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
+ {\bgroup
+ \ifcsname\??regularframedlevel#1\endcsname
+ %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
+ \expandafter\let\expandafter\c_pack_framed_temp\lastnamedcs
+ \else
+ \let\c_pack_framed_temp\c_temp_framed_crap
+ \fi
+ \advance\c_pack_framed_temp\plusone
+ \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
+ \bgroup
+ \edef\currentframed{#1>\the\c_pack_framed_temp}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_defined_process_indeed}
+
+\def\pack_framed_defined_process_indeed[#1]%
+ {\iffirstargument % faster
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed}
+
+\let\placeframed\pack_framed_defined_process % new per 2012/04/23
+
+%D We can do:
+%D
+%D \starttyping
+%D \defineframed[\v!framed]
+%D \stoptyping
+%D
+%D but the existing one is ok as well (less csname messy too).
+
+%D New, for the moment private; let's see when GB finds out about this one and its
+%D obscure usage. It's used in:
+%D
+%D \startbuffer
+%D \defineframedtext
+%D [tabulateframe]
+%D [offset=overlay,
+%D backgroundoffset=3pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \setuptabulate
+%D [tabulate]
+%D [frame=tabulateframe]
+%D
+%D \setuptables
+%D [frame=tabulateframe]
+%D
+%D \input tufte
+%D
+%D \starttabulate[|l|l|]
+%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
+%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
+%D \stoptabulate
+%D
+%D \input tufte
+%D
+%D \starttable[|l|l|]
+%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
+%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\installcorenamespace{framedcontent}
+
+\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent
+
+\setupframedcontent
+ [\c!leftoffset=\zeropoint,
+ %\c!rightoffset=\framedcontentparameter\c!leftoffset,
+ \c!rightoffset=\scratchleftoffset,
+ \c!topoffset=\zeropoint,
+ %\c!bottomoffset=\framedcontentparameter\c!topoffset,
+ \c!bottomoffset=\scratchtopoffset,
+ \c!strut=\v!no,
+ %\c!linecorrection=\v!no,
+ %\c!left=,
+ %\c!right=,
+ %\c!width=\v!fit,
+ \c!offset=\v!overlay]
+
+\unexpanded\def\startframedcontent
+ {\dosingleempty\pack_framed_start_content}
+
+\def\pack_framed_start_content[#1]%
+ {\bgroup
+ \edef\currentframedcontent{#1}%
+ \ifx\currentframedcontent\v!off
+ \let\stopframedcontent\egroup
+ \else
+ \let\stopframedcontent\pack_framed_stop_content_indeed
+ \expandafter\pack_framed_start_content_indeed
+ \fi}
+
+\def\pack_framed_start_content_indeed
+ {\setbox\b_framed_normal\hbox\bgroup % maybe \hpack
+ \setlocalhsize
+ \hsize\localhsize
+ \scratchleftoffset \framedcontentparameter\c!leftoffset \relax
+ \scratchrightoffset \framedcontentparameter\c!rightoffset \relax
+ \scratchtopoffset \framedcontentparameter\c!topoffset \relax
+ \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax
+ \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax
+ \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax
+ \kern\scratchleftoffset
+ \vbox\bgroup
+ \vskip\scratchtopoffset
+ \vbox\bgroup
+ \forgetall
+ \blank[\v!disable]}
+
+\def\pack_framed_stop_content_indeed
+ {\removelastskip
+ \egroup
+ \vskip\scratchbottomoffset
+ \egroup
+ \kern\scratchrightoffset
+ \egroup
+ \doif{\framedcontentparameter\c!width}\v!fit
+ {\letframedcontentparameter\c!width\v!fixed}% no shapebox
+ \ifinsidefloat
+ \donefalse
+ \else
+ \doifelse{\framedcontentparameter\c!linecorrection}\v!yes\donetrue\donefalse
+ \fi
+ % plaats ?
+ \ifdone\startlinecorrection\fi
+ \framedcontentparameter\c!left % new
+ \inheritedframedcontentframed{\box\b_framed_normal}% hm
+ \framedcontentparameter\c!right % new
+ \ifdone\stoplinecorrection\fi
+ \egroup}
+
+% A shared setting.
+
+\setuplinewidth
+ [\v!medium]
+
+%D A Goodie:
+
+\def\v!unframed{unframed}
+
+\defineframed
+ [\v!unframed]
+ [\c!frame=\v!off,
+ \c!rulethickness=\zeropoint,
+ \c!foregroundstyle=\framedparameter\c!style,
+ \c!foregroundcolor=\framedparameter\c!color]
+
+%D Bonus (as defined in \type {pack-rul.lua}):
+%D
+%D \starttyping
+%D \setbox\scratchbox\vbox{a\par aa\par aaa\par}
+%D \the\dimexpr\themaxboxwidth\scratchbox\relax
+%D \stoptyping
+
+\let\themaxboxwidth\clf_themaxboxwidth
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-app.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-app.mkiv
new file mode 100644
index 00000000000..cdb964ab06e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-app.mkiv
@@ -0,0 +1,219 @@
+%D \module
+%D [ file=page-app, % from meta-fig
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Independent page building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Applications}
+
+%D This needs an update with a proper define and inheritance.
+
+\unprotect
+
+\installcorenamespace{fittingpage}
+
+\installframedcommandhandler \??fittingpage {fittingpage} \??fittingpage
+
+\newdimen\d_page_fitting_width
+\newdimen\d_page_fitting_height
+\newbox \b_page_fitting
+
+\definepapersize
+ [fittingpage]
+ [\c!width=\d_page_fitting_width,
+ \c!height=\d_page_fitting_height]
+
+\definemakeup
+ [fittingpage]
+ [\c!textstate=\v!empty,
+ \c!doublesided=\v!no,
+ \c!location=\v!top, % no topskip
+ \c!pagestate=\fittingpageparameter\c!pagestate]%
+
+\definelayout
+ [fittingpage]
+ [\v!page]
+ [\c!width=\d_page_fitting_width,
+ \c!height=\d_page_fitting_height,
+ \c!location=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentfittingpage}{\startfittingpage[\currentfittingpage]}%
+ \setuevalue{\e!stop \currentfittingpage}{\stopfittingpage}%
+\to \everydefinefittingpage
+
+\unexpanded\def\startfittingpage
+ {\dodoubleempty\page_fitting_start}
+
+\def\page_fitting_start[#1][#2]%
+ {\page % this is kind of tricky! there can be preceding page refs
+ \autostarttext
+ \bgroup % resulting in a zero height page; test fig-make !
+ \setupinterlinespace[\v!top=0]% no topskip
+ \def\currentfittingpage{#1}%
+ \dontcomplain
+ % runs under current page regime, i.e. page variables passed to mp
+ \setupcurrentfittingpage[\c!paper=,#2]% auto or size or nothing
+ \doifelsenothing{\fittingpageparameter\c!command}
+ \page_fitting_start_normal
+ \page_fitting_start_command}
+
+\def\page_fitting_start_command
+ {\grabuntil{\e!stop\currentfittingpage}\page_fitting_stop_command}
+
+\def\page_fitting_stop_command#1%
+ {\page_fitting_start_normal
+ \fittingpageparameter\c!command{#1}%
+ \page_fitting_stop_normal}
+
+\def\page_fitting_start_normal
+ {\setbox\b_page_fitting\hbox
+ \bgroup
+ \inheritedfittingpageframed
+ \bgroup
+ \gobblespacetokens}
+
+\unexpanded\def\page_fitting_stop_normal % todo: figure out why a small mp image gets shifted
+ {\removeunwantedspaces
+ \egroup
+ \egroup
+ % finalize
+ \doif{\fittingpageparameter\c!margin}\v!page
+ {\setbox\b_page_fitting\hpack\bgroup
+ \offsetbox
+ [\c!leftoffset=\backspace,
+ \c!rightoffset=\cutspace,
+ \c!topoffset=\topspace,
+ \c!bottomoffset=\bottomspace]
+ {\box\b_page_fitting}%
+ \egroup}%
+ \doifsomething{\fittingpageparameter\c!scale}
+ {\setbox\b_page_fitting\hpack\bgroup
+ \scale[\c!scale=\fittingpageparameter\c!scale]{\box\b_page_fitting}%
+ \egroup}%
+ \ifdim\ht\b_page_fitting=\zeropoint
+ \ht\b_page_fitting\onepoint
+ \fi
+ \ifdim\wd\b_page_fitting=\zeropoint
+ \wd\b_page_fitting\onepoint
+ \fi
+ \d_page_fitting_width \wd\b_page_fitting
+ \d_page_fitting_height\ht\b_page_fitting
+ \startlocallayout % hm, we change the papersize so we still need it
+ \let\checkcurrentlayout\relax % else interference with odd/even layout
+ \processaction
+ [\fittingpageparameter\c!paper]
+ [ \v!auto=>\def\fittingpapersize{\printpapersize},
+ \s!unknown=>\let\fittingpapersize\commalistelement,
+ \s!default=>\def\fittingpapersize{fittingpage}]%
+ \expanded{\setuppapersize[fittingpage][\fittingpapersize]}%
+ \startmakeup[fittingpage]%
+ \box\b_page_fitting
+ \stopmakeup
+ \stoplocallayout % we need to get rid of this and use the built-in
+ \egroup
+ \autostoptext}
+
+\let\stopfittingpage\page_fitting_stop_normal
+
+\setupfittingpage
+ [%\c!scale=1000,
+ %\c!pagestate=,
+ \c!strut=\v!no,
+ \c!align=\v!normal,
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D \TEX\ pages (for \METAPOST\ pages, see \type {meta-fig}):
+
+\definefittingpage
+ [TEXpage]
+ [\c!align=\v!normal] % needed, else problems !
+
+\unexpanded\def\setupTEXpage
+ {\setupfittingpage[TEXpage]}
+
+%D For Mojca:
+%D
+%D \starttyping
+%D \startTEXstream \chapter{Bla} Hello world!\crlf Hello world! \stopTEXstream
+%D \startTEXpage \chapter{Bla} Hello world!\crlf Hello world! \stopTEXpage
+%D \stoptyping
+%D
+%D maybe I should support stream=yes in framed.
+
+\unexpanded\def\startTEXstream
+ {\dosingleempty\page_streams_TEX_start}
+
+\def\page_streams_TEX_start[#1]% old code, to be redone
+ {\page
+ \enableoutputstream[tex]}
+
+\unexpanded\def\stopTEXstream
+ {\disableoutputstream
+ \startTEXpage
+ \outputstreamunvbox[tex]%
+ \stopTEXpage}
+
+%D Application pages, a quick \MKIV\ hack:
+
+\definetypesetting[TEXapplication]
+\definebuffer[TEXapplication]
+
+% we could use a counter and saves runs on numbering them.
+
+\def\TEXapplicationfilename{\jobname-texapplication.tex}
+
+\unexpanded\def\stopTEXapplication
+ {\savebuffer[\thedefinedbuffer{TEXapplication}][\TEXapplicationfilename]%
+ \typesetfile[TEXapplication][\TEXapplicationfilename]\relax}
+
+%D \macros
+%D {startpagefigure}
+%D
+%D \starttyping
+%D \starttext \pagefigure[two.1] \stoptext
+%D \stoptyping
+
+\defineexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay] % we force a parent
+
+\unexpanded\def\startpagefigure
+ {\dodoubleempty\page_figures_start}
+
+% this one:
+%
+% \def\page_figures_start[#1][#2]%
+% {\bgroup
+% \def\currentexternalfigure{\v!page:\v!figure}%
+% \setupcurrentexternalfigure[\c!offset=\v!overlay,#2]%
+% \startTEXpage[\c!offset=\externalfigureparameter\c!offset]%
+% \externalfigure[#1]\ignorespaces} % so we can put some text below the graphic
+%
+% or this one:
+
+\def\page_figures_start[#1][#2]%
+ {\bgroup
+ \setupexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay,#2]%
+ \startTEXpage[\c!offset=\namedexternalfigureparameter{\v!page:\v!figure}\c!offset]%
+ \externalfigure[#1]\ignorespaces} % so we can put some text below the graphic
+
+\unexpanded\def\stoppagefigure
+ {\stopTEXpage
+ \egroup}
+
+\unexpanded\def\pagefigure
+ {\dodoubleempty\page_figure}
+
+\def\page_figure[#1][#2]%
+ {\page_figures_start[#1][#2]\stoppagefigure}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv
new file mode 100644
index 00000000000..b44910bbe6c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv
@@ -0,0 +1,701 @@
+%D \module
+%D [ file=page-bck, % copied from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% Currently the text cells are fakes and no (foreground) frames which makes sense
+% as order might matter e.g. is text sticks in other cells. The page, text etc
+% areas do support foreground order change.
+
+\writestatus{loading}{ConTeXt Page Macros / Backgrounds}
+
+\unprotect
+
+% maybe use \currentframedhash here
+
+%D For special purposes, users can question the \type {*background} mode. This mode
+%D is only available when typesetting the pagebody.
+%D
+%D \starttyping
+%D \startmode[*background] ...
+%D \stoptyping
+
+\newconditional\c_page_backgrounds_new
+\newconditional\c_page_backgrounds_new_right
+\newconditional\c_page_backgrounds_new_left
+\newconditional\c_page_backgrounds_some
+
+\appendtoks
+ \ifconditional\c_page_backgrounds_some
+ \ifconditional\c_page_backgrounds_new
+ \setsystemmode\v!background
+ \fi
+ \fi
+\to \everybeforepagebody
+
+\unexpanded\def\initializepagebackgrounds
+ {\setfalse\c_page_backgrounds_new
+ \setfalse\c_page_backgrounds_new_right
+ \setfalse\c_page_backgrounds_new_left
+ \setfalse\c_page_backgrounds_some}
+
+%D We keep calculations and checks to a minimum and also try to minimize
+%D the amount of tracing due to expansion.
+
+\let\currentotrbackground\empty
+
+%D This is the only spot where we hav ea low level dependency on the way
+%D parent chains are defined but we want the speed.
+
+\unexpanded\def\page_backgrounds_check_background
+ {\ifcsname\??framed\currentotrbackground:\c!background\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\empty
+ \expandafter\expandafter\expandafter\page_backgrounds_check_frame
+ \else
+ \page_backgrounds_set_yes
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_frame
+ \fi}
+
+\def\page_backgrounds_check_frame
+ {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_leftframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_leftframe
+ \fi}
+
+\def\page_backgrounds_check_leftframe
+ {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_rightframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_rightframe
+ \fi}
+
+\def\page_backgrounds_check_rightframe
+ {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_topframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_topframe
+ \fi}
+
+\def\page_backgrounds_check_topframe
+ {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_bottomframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_bottomframe
+ \fi}
+
+\def\page_backgrounds_check_bottomframe
+ {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \page_backgrounds_set_nop
+ \fi
+ \else
+ \page_backgrounds_set_nop
+ \fi}
+
+%D We don't use the commandhandler code as we want these multitude of backgrounds to be
+%D as fast as possible.
+
+\installcorenamespace{layoutbackgrounds}
+\installcorenamespace{layoutbackgroundcheck} % we need another hash as \??layoutbackgrounds<...> gets defined
+
+\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax }
+\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined}
+
+\unexpanded\def\page_backgrounds_check#1%
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \page_backgrounds_check_background}
+
+\def\doifelsesomebackground#1%
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifsomebackgroundelse\doifelsesomebackground
+
+\def\doifsomebackground#1%
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D The background mechanism falls back on the \type {\framed} macro. This means
+%D that all normal frame and overlay features can be used.
+
+\def\page_backgrounds_add_to_box#1% area
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\page_backgrounds_add_to_box_indeed
+ \else
+ \expandafter\gobblefourarguments
+ \fi#1}
+
+%D We don't need the dimensions here as this is a real framed but the question is:
+%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only
+%D for hidden).
+
+\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero
+ {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
+ \fi
+ % #2 has the right dimensions already
+ \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground)
+
+
+%D There are quite some backgrounds. At the bottom layer, there is the {\em
+%D paper} background. This one is only used for special purposes, like
+%D annotations to documents.
+
+\def\page_backgrounds_add_to_print#1%
+ {\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight}
+
+%D The page backgrounds can be put behind the {\em left page}, the {\em
+%D right page} or {\em each page}. As with the paper background, these are
+%D calculated on each page.
+
+\def\page_backgrounds_add_to_paper#1%
+ {\doifbothsidesoverruled
+ {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}%
+ {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}%
+ {\page_backgrounds_add_to_box\v!leftpage #1\paperwidth\paperheight}%
+ \page_backgrounds_add_to_box\v!page#1\paperwidth\paperheight}
+
+%D Then there are the 25 areas that make up the layout: {\em top, header, text,
+%D footer, bottom} times {\em left edge, left margin, text, right margin, right
+%D edge}. These are only recalculated when they change or when the \type {status}
+%D is set to \type {repeat}.
+
+\newbox\leftbackground % todo: rename
+\newbox\rightbackground % todo: rename
+
+%D Finaly there is an aditional {\em text} background, again useful for
+%D special purposes only. This one is calculated each time. The hidden
+%D backgrounds are not meant for users!
+
+\newconditional\c_page_backgrounds_hidden_enabled
+
+\def\page_backgrounds_add_to_text#1%
+ {\ifconditional\c_page_backgrounds_hidden_enabled
+ \page_backgrounds_add_to_box\v!hidden#1\makeupwidth\textheight % mine !
+ \fi
+ \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight}
+
+%D The next couple of macros implement the area backgrounds. As said, these
+%D are cached in dedicated boxes. The offsets and depth of the page are used
+%D for alignment purposes.
+
+%newdimen\pageoffset % bleed
+%newdimen\pagedepth % built-in
+
+%D We need a bit more clever mechanism in order to handle layers well.
+%D This means that we cannot calculate both background at the same time
+%D since something may have changed halfway a page.
+
+%D Margin swapping has been simplified: see mkii code in case of regression.
+%D Calculation is delayed till the page anyway so the state is known.
+
+\def\page_backgrounds_recalculate
+ {\global\settrue\c_page_backgrounds_new}
+
+\def\page_backgrounds_set_boxes
+ {\ifconditional\c_page_backgrounds_new
+ \page_backgrounds_set_boxes_r
+ \fi
+ \doifbothsides
+ \page_backgrounds_set_boxes_a
+ \page_backgrounds_set_boxes_b
+ \page_backgrounds_set_boxes_c
+ \ifx\p_page_backgrounds_state\v!repeat\else
+ \global\setfalse\c_page_backgrounds_new
+ \fi}
+
+\def\page_backgrounds_set_boxes_r
+ {\global\settrue\c_page_backgrounds_new_right
+ \global\settrue\c_page_backgrounds_new_left
+ \global\setbox\leftbackground\emptybox
+ \global\setbox\rightbackground\emptybox}
+
+\def\page_backgrounds_set_boxes_a
+ {\ifconditional\c_page_backgrounds_new_left
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\leftbackground % \conditionalfalse
+ \global\setfalse\c_page_backgrounds_new_left
+ \global\setfalse\c_page_backgrounds_new_right
+ \fi}
+
+\def\page_backgrounds_set_boxes_b
+ {\ifconditional\c_page_backgrounds_new_left
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\leftbackground % \conditionalfalse
+ \global\setfalse\c_page_backgrounds_new_left
+ \fi}
+
+\def\page_backgrounds_set_boxes_c
+ {\ifconditional\c_page_backgrounds_new_right
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\rightbackground % \conditionaltrue
+ \global\setfalse\c_page_backgrounds_new_right
+ \fi}
+
+\def\page_backgrounds_add_to_main#1% todo: dimension spec
+ {\ifconditional\c_page_backgrounds_some
+ \page_backgrounds_set_boxes
+ \setbox#1\vpack
+ {\offinterlineskip
+ \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}%
+ \box#1}%
+ \fi}
+
+\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE
+\newdimen\pagebackgroundvoffset
+\newdimen\pagebackgroundoffset % used elsewhere
+\newdimen\pagebackgrounddepth
+\newdimen\pagebackgroundcompensation
+
+\def\page_backgrounds_set_offsets % used in menus (we can use ifcsname's here)
+ {\ifconditional\c_page_backgrounds_some \ifconditional\c_page_backgrounds_new
+ \page_backgrounds_set_offsets_indeed % indirect, less tracing
+ \fi \fi}
+
+\def\page_backgrounds_set_offsets_indeed
+ {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \else\ifcsname\??layoutbackgrounds\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \else
+ \page_backgrounds_set_offsets_nop
+ \fi\fi}
+
+\def\page_backgrounds_set_offsets_nop
+ {\global\pagebackgroundhoffset \zeropoint
+ \global\pagebackgroundvoffset \zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \global\pagebackgroundcompensation\zeropoint}
+
+\def\page_backgrounds_set_offsets_yes
+ {\global\pagebackgroundoffset \d_page_backgrounds_depth
+ \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax
+ \ifzeropt\pagebackgroundcompensation
+ \page_backgrounds_set_offsets_nop
+ \else
+ \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \else\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \else
+ \global\pagebackgroundhoffset\pagebackgroundcompensation
+ \fi\fi
+ \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \else\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \else
+ \global\pagebackgroundvoffset\pagebackgroundcompensation
+ \global\pagebackgrounddepth \d_page_backgrounds_depth
+ \fi\fi
+ \fi}
+
+\appendtoks
+ \page_backgrounds_set_offsets
+\to \everybeforepagebody
+
+\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
+
+\def\page_backgrounds_set_box#1% #2%
+ {\global\setbox#1\vpack
+ {\dontcomplain
+ \swapmargins
+ \ifconditional\swapbackgroundmargins
+ \doifelsemarginswap \donothing
+ {\swapmacros\v!rightmargin\v!leftmargin
+ \swapmacros\v!rightedge \v!leftedge}%
+ \fi
+ \calculatereducedvsizes
+ \offinterlineskip
+ % \ifconditional#2\relax
+ % \doswapmargins % hm, this one gets nilled in \swapmargins anyway
+ % \fi
+ \ifdim\topheight>\zeropoint
+ \kern\dimexpr-\topheight-\topdistance\relax
+ \page_backgrounds_set_box_row\v!top\topheight
+ \kern\topdistance
+ \fi
+ \ifdim\headerheight>\zeropoint
+ \page_backgrounds_set_box_row\v!header\headerheight
+ \kern\headerdistance
+ \fi
+ \ifdim\textheight>\zeropoint
+ \page_backgrounds_set_box_row\v!text\textheight
+ \fi
+ \ifdim\footerheight>\zeropoint
+ \kern\footerdistance
+ \page_backgrounds_set_box_row\v!footer\footerheight
+ \fi
+ \ifdim\bottomheight>\zeropoint
+ \kern\bottomdistance
+ \page_backgrounds_set_box_row\v!bottom\bottomheight
+ \fi
+ \vfilll}%
+ \smashbox#1}
+
+\def\page_backgrounds_set_box_row#1#2% maybe helper
+ {\setbox\scratchbox\vpack to #2
+ \bgroup\hpack\bgroup
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2%
+ \else
+ \kern\leftedgewidth
+ \fi
+ \kern\leftedgedistance
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2%
+ \else
+ \kern\leftmarginwidth
+ \fi
+ \kern\leftmargindistance
+ \fi
+ \ifcsname\??layoutbackgrounds#1\v!text\endcsname
+ \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2%
+ \else
+ \kern\makeupwidth
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ \kern\rightmargindistance
+ \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname
+ \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2%
+ \else
+ \kern\rightmarginwidth
+ \fi
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \kern\rightedgedistance
+ \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname
+ \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2%
+ \else
+ \kern\rightedgewidth
+ \fi
+ \fi
+ \egroup\egroup
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\relax}
+
+% these are fake framed .. maybe it's nicer to honor foreground here as well
+% but it's probably a slow downer
+
+\def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height
+ {\begingroup
+ \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
+ \fi
+ \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}%
+ \ifx\p_page_backgrounds_command\empty
+ \expandafter\page_backgrounds_set_box_cell_nop
+ \else
+ \expandafter\page_backgrounds_set_box_cell_yes
+ \fi#3#4%
+ \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox
+ \endgroup}
+
+\def\page_backgrounds_set_box_cell_nop#1#2%
+ {\setbox\scratchbox\emptyvbox
+ \wd\scratchbox#1%
+ \ht\scratchbox#2}
+
+\def\page_backgrounds_set_box_cell_yes#1#2%
+ {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}%
+ \dp\scratchbox\zeropoint}
+
+%D The background mechanism is quite demanding in terms or resources. We used to
+%D delay these definitions till runtime usage, but since today's \TEX's are large,
+%D we now do the work on forehand.
+%D
+%D \starttyping
+%D \setupbackgrounds [settings]
+%D \setupbackgrounds [paper,page,text,..] [settings]
+%D \setupbackgrounds [top,...] [leftedge,...] [settings]
+%D \stoptyping
+%D
+%D \showsetup{setupbackgrounds}
+%D
+%D Because the number of arguments runs from one to three, we need to check
+%D for it.
+
+\newtoks\everybackgroundssetup
+
+\unexpanded\def\setupbackgrounds
+ {\dotripleempty\page_backgrounds_setup}
+
+\def\page_backgrounds_setup
+ {\ifthirdargument
+ \expandafter\page_backgrounds_setup_double
+ \else\ifsecondargument
+ \doubleexpandafter\page_backgrounds_setup_single
+ \else\iffirstargument
+ \tripleexpandafter\page_backgrounds_setup_basics
+ \fi\fi\fi}
+
+\newdimen\d_page_backgrounds_offset
+\newdimen\d_page_backgrounds_depth
+
+\appendtoks
+ \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}%
+ \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }%
+ \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }%
+ \global\d_page_backgrounds_offset\ifx\p_offset\empty\zeropoint\else\p_page_backgrounds_offset\fi
+ \global\d_page_backgrounds_depth \ifx\p_depth \empty\zeropoint\else\p_page_backgrounds_depth \fi
+ \global\pagebackgroundoffset\d_page_backgrounds_offset\relax
+ \global\pagebackgrounddepth \d_page_backgrounds_depth \relax
+ \ifx\p_page_backgrounds_state\v!stop
+ \global\setfalse\c_page_backgrounds_new
+ \else
+ \global\settrue \c_page_backgrounds_new
+ \fi
+\to \everybackgroundssetup
+
+\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage}
+\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
+\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge}
+
+\unexpanded\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up
+ {\global\settrue\c_page_backgrounds_some
+ \def\page_backgrounds_setup_step##1%
+ {\doifelseinset{##1}\v_page_backgrounds_double_set
+ {\page_backgrounds_setup_and_check{##1}{#3}}
+ {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}%
+ \processcommacommand[#2]\page_backgrounds_setup_step_nested}}%
+ \processcommacommand[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}
+
+\unexpanded\def\page_backgrounds_setup_single[#1][#2][#3]%
+ {\global\settrue\c_page_backgrounds_some
+ \doifelsecommon{#1}\v_page_backgrounds_single_set
+ {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}%
+ \processcommacommand[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}%
+ {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}}
+
+\unexpanded\def\page_backgrounds_setup_basics[#1][#2][#3]%
+ {\setupframed[\??layoutbackgrounds][#1]%
+ \the\everybackgroundssetup}
+
+\unexpanded\def\page_backgrounds_setup_and_check#1#2% tag settings
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \setupframed[\currentotrbackground][#2]%
+ \page_backgrounds_check_background}
+
+%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level
+%D framed object associated.
+
+\definesimplifiedframed[\??layoutbackgrounds\v!paper]
+\definesimplifiedframed[\??layoutbackgrounds\v!page]
+\definesimplifiedframed[\??layoutbackgrounds\v!leftpage]
+\definesimplifiedframed[\??layoutbackgrounds\v!rightpage]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!hidden]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge]
+
+\setupbackgrounds
+ [\v!page]
+ [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere
+ \c!depth=\zeropoint]
+
+%D General setup:
+
+\setupbackgrounds
+ [\c!state=\c!start]
+
+%D The hidden layer can be populated by extending the following comma separated
+%D list. This only happens in core modules.
+
+% todo page-2 .. page+2 achter pagina -> bleed
+% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
+
+\unexpanded\def\enablehiddenbackground
+ {\global\settrue\c_page_backgrounds_hidden_enabled
+ \global\settrue\c_page_backgrounds_some
+ \page_backgrounds_recalculate}
+
+\unexpanded\def\disablehiddenbackground
+ {\global\setfalse\c_page_backgrounds_hidden_enabled}
+
+\def\hiddenbackgroundlist
+ {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
+
+\defineoverlay[\v!text-2][\positionregionoverlay\textanchor{\v!text-2}] % no new anchor, we share text
+\defineoverlay[\v!text-1][\positionregionoverlay\textanchor{\v!text-1}]
+\defineoverlay[\v!text+1][\positionregionoverlay\textanchor{\v!text+1}]
+\defineoverlay[\v!text+2][\positionregionoverlay\textanchor{\v!text+2}]
+
+\setupbackgrounds
+ [\v!hidden]
+ [\c!background=\hiddenbackgroundlist]
+
+%D Because we haven't really set up backgrounds yet, we set the main efficiency
+%D switch to false.
+
+\setfalse\c_page_backgrounds_some
+
+%D Sometimes you have a document wide (page) background but need to overload it
+%D locally. In such case (at least in my experience) the only values that get set
+%D are the background and backgroundcolor (if set at all). A full inheritance chain
+%D would complicate things because then we need to use named backgrounds which in
+%D turn will make this mechanism slower. I considered independent local backgrounds
+%D but that also complicates the code (not that much) but isolation means that we
+%D need to set more parameters each time. The following simple approach proabbly
+%D suits most usage.
+%D
+%D \starttyping
+%D \starttext
+%D \setupbackgrounds[page][background=color,backgroundcolor=red]
+%D \input tufte \page
+%D \setupbackgrounds[page][background=,backgroundcolor=]
+%D \input tufte \page
+%D \setupbackgrounds[page][background=color,backgroundcolor=red]
+%D \input tufte \page
+%D \pushbackground[page]
+%D \setupbackgrounds[page][background=color,backgroundcolor=green]
+%D \input tufte \page
+%D \popbackground
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\pushbackground[#1]%
+ {\pushmacro\popbackground
+ \edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \unexpanded\edef\popbackground
+ {\setupframed
+ [\currentotrbackground]
+ [\c!background=\namedframedparameter{\currentotrbackground}\c!background,
+ \c!backgroundcolor=\namedframedparameter{\currentotrbackground}\c!backgroundcolor]%
+ \page_backgrounds_check_background
+ \popmacro\popbackground}%
+ \setupframed
+ [\currentotrbackground]
+ [\c!background=,\c!backgroundcolor=]%
+ \page_backgrounds_check_background}
+
+\let\popbackground\relax
+
+\protect \endinput
+
+% %D The next series is used in local (for instance floating) backgrounds.
+%
+% \installsimplifiedframed{\??layoutbackgrounds\v!local}
+%
+% \getparameters
+% [\??layoutbackgrounds\v!local]
+% [\c!component=local,
+% \c!background=\localbackgroundlist]
+%
+% \def\localbackgroundlist
+% {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2}
+%
+% \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] % todo share
+% \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}]
+% \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}]
+% \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}]
+%
+% \def\page_backgrounds_add_local_to_box
+% {\ifconditional\c_page_backgrounds_hidden_enabled
+% \expandafter\page_backgrounds_add_local_to_box_indeed
+% \else
+% \expandafter\gobbleoneargument
+% \fi}
+%
+% \def\page_backgrounds_add_local_to_box_indeed#1%
+% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}%
+% \global\advance\localpositionnumber\plusone} % afterwards !
+%
+% \let\page_backgrounds_add_local_to_box\gobbleoneargument
+
+% Test how previous macro behaves with depth:
+%
+% \startcolumnset
+% \input tufte
+% \placefigure{none}{\framed[lines=5]{xxx}}
+% \input tufte
+% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate}
+% \input tufte
+% \stopcolumnset
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi
new file mode 100644
index 00000000000..fa85aef6898
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi
@@ -0,0 +1,311 @@
+%D \module
+%D [ file=page-box,
+%D version=2011.12.05, % moved from other page-* files
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Boxing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Boxing}
+
+\unprotect
+
+%D The often two step approach (_indeed) saves skippign tokens
+%D which is nicer for tracing.
+
+%D Centering the paper area on the print area is determined
+%D by the \type {top}, \type {bottom}, \type {left} and \type
+%D {right} parameters.
+
+\def\page_boxes_apply_center#box% we could test for a difference (saves packing)
+ {\printpaperwidth \v_page_target_scale\printpaperwidth \relax
+ \printpaperheight\v_page_target_scale\printpaperheight\relax
+ \ifdim\printpaperheight>\ht#box\relax
+ \page_boxes_apply_center_indeed#box%
+ \else\ifdim\printpaperwidth>\wd#box\relax
+ \page_boxes_apply_center_indeed#box%
+ \fi\fi}
+
+\def\page_boxes_apply_center_indeed_l_r#box%
+ {\v_page_target_left
+ \v_page_target_left_fill
+ \box#box%
+ \v_page_target_right_fill
+ \v_page_target_right}
+
+\def\page_boxes_apply_center_indeed_r_l#box%
+ {\v_page_target_right
+ \v_page_target_right_fill
+ \box#box%
+ \v_page_target_left_fill
+ \v_page_target_left}
+
+\def\page_boxes_apply_center_indeed#box% we could test for a difference (saves packing)
+ {\setbox#box\vpack to \printpaperheight
+ {\v_page_target_top
+ \v_page_target_top_fill
+ \hpack to \printpaperwidth
+ {\ifconditional\c_page_target_print_doublesided
+ \doifbothsides
+ {\page_boxes_apply_center_indeed_l_r#box}%
+ {\page_boxes_apply_center_indeed_l_r#box}%
+ {\page_boxes_apply_center_indeed_r_l#box}%
+ \else
+ \page_boxes_apply_center_indeed_l_r#box%
+ \fi}%
+ \par
+ \v_page_target_bottom_fill
+ \v_page_target_bottom}}
+
+\def\page_boxes_apply_offset % #box
+ {\ifdim\topoffset=\zeropoint
+ \ifdim\backoffset=\zeropoint
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\page_boxes_apply_offset_indeed
+ \fi
+ \else
+ \expandafter\page_boxes_apply_offset_indeed
+ \fi}
+
+\def\page_boxes_apply_offset_indeed#box%
+ {\scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\vpack
+ {\offinterlineskip
+ \vskip\topoffset
+ \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
+ \box#box}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+\def\page_boxes_apply_replicate
+ {\ifnum\layoutparameter\c!nx>\plusone
+ \expandafter\page_boxes_apply_replicate_indeed
+ \else\ifnum\layoutparameter\c!ny>\plusone
+ \doubleexpandafter\page_boxes_apply_replicate_indeed
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+\def\page_boxes_apply_replicate_indeed#box%
+ {\setbox#box\vpack
+ {\offinterlineskip
+ \dorecurse{\layoutparameter\c!ny}
+ {\hpack{\dorecurse{\layoutparameter\c!nx}{\copy#box\kern\layoutparameter\c!dx}\unskip}%
+ \vskip\layoutparameter\c!dy}
+ \unskip}}
+
+\def\page_boxes_apply_orientate_paper#box%
+ {\ifnum\number\c_page_target_paper_orientation\number\c_page_target_paper_reverse>\zerocount
+ \page_boxes_apply_orientate_indeed\c_page_target_paper_orientation\c_page_target_paper_reverse{#box}%
+ \fi}
+
+\def\page_boxes_apply_orientate_print#box%
+ {\ifnum\number\c_page_target_print_orientation\number\c_page_target_print_reverse>\zerocount
+ \page_boxes_apply_orientate_indeed\c_page_target_print_orientation\c_page_target_print_reverse{#box}%
+ \fi}
+
+\def\page_boxes_apply_orientate_indeed#odd#even#box%
+ {\setbox#box\vpack
+ {\edef\somerotation{\number\ifdoublesided\ifodd\realpageno#odd\else#even\fi\else#odd\fi}%
+ \dorotatebox\somerotation\hpack{\box#box}}}
+
+\def\page_boxes_apply_mirror#box%
+ {\setbox#box\vpack{\mirror{\box#box}}}
+
+\def\page_boxes_apply_mirror_paper#box{\ifconditional\c_page_target_paper_mirror\page_boxes_apply_mirror{#box}\fi}
+\def\page_boxes_apply_mirror_print#box{\ifconditional\c_page_target_print_mirror\page_boxes_apply_mirror{#box}\fi}
+
+\let\page_boxes_apply_negate\negatecolorbox
+
+\def\page_boxes_apply_negate_print#box%
+ {\ifconditional\c_page_target_print_negate
+ \page_boxes_apply_negate#box%
+ \else\ifconditional\c_page_target_paper_negate
+ \page_boxes_apply_negate#box%
+ \fi\fi}
+
+\def\page_boxes_apply_scale#box%
+ {\edef\p_page_layouts_scale{\layoutparameter\c!scale}%
+ \ifdim\p_page_layouts_scale\points=\onepoint
+ \edef\p_page_layouts_sx{\layoutparameter\c!sx}%
+ \edef\p_page_layouts_sy{\layoutparameter\c!sy}%
+ \ifdim\p_page_layouts_sx\points=\onepoint
+ \ifdim\layoutparameter\c!sy\points=\onepoint
+ % no scaling done (and no copying either)
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
+ \fi
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
+ \fi
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_scale\p_page_layouts_scale{#box}%
+ \fi}
+
+\def\page_boxes_apply_scale_indeed#sx#sy#box%
+ {\setbox#box\vpack{\scale[\c!sx=#sx,\c!sy=#sy]{\box#box}}% can be a fast one
+ \paperwidth #sx\paperwidth
+ \paperheight#sy\paperheight}
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupcolors[state=start]
+% \setuppapersize[A4][A4,oversized]
+% \setuplayout[location=middle,clipoffset=5mm]
+% \setupbackgrounds
+% [page]
+% [frame=on,rulethickness=1mm,
+% backgroundoffset=10mm,background=color,backgroundcolor=red]
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+% best use private variables
+
+\newconditional\c_page_boxes_clip_print \settrue\c_page_boxes_clip_print
+
+\def\page_boxes_apply_clip_print_left % box
+ {\ifconditional\c_page_boxes_clip_print
+ \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionalfalse
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_print_right % box
+ {\ifconditional\c_page_boxes_clip_print
+ \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionaltrue
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_print_indeed#right#box% can be made more efficient, see other clipper
+ {\scratchoffset\pagebackgroundoffset % can be zero which is valid % maybe another variable
+ \scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\hpack
+ {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
+ \advance\scratchwidth \scratchoffset
+ \ifconditional#right\relax
+ \scratchdimen-\scratchoffset
+ \kern\scratchdimen
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \lower\scratchoffset\hpack
+ {\clip
+ [\c!hoffset=\scratchdimen,
+ \c!voffset=-\scratchoffset,
+ \c!width=\scratchwidth,
+ \c!height=\scratchheight]%
+ {\box#box}}}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+\def\page_boxes_apply_clip_paper
+ {\scratchoffset\layoutparameter\c!clipoffset\relax
+ \ifdim\scratchoffset>\zeropoint
+ \expandafter\page_boxes_apply_clip_paper_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_paper_indeed#box%
+ {\scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\hpack
+ {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
+ \advance\scratchwidth \scratchoffset
+ \doifbothsides
+ {\advance\scratchwidth\scratchoffset
+ \scratchdimen-\scratchoffset
+ \kern\scratchdimen}%
+ {\scratchdimen\zeropoint}
+ {\scratchdimen-\scratchoffset
+ \kern\scratchdimen}%
+ \lower\scratchoffset\hpack
+ {\clip
+ [\c!hoffset=\scratchdimen,
+ \c!voffset=-\scratchoffset,
+ \c!width=\scratchwidth,
+ \c!height=\scratchheight]%
+ {\box#box}}}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+% nearly always some displacement so no speedup test needed
+
+\def\page_boxes_apply_offsets#1%
+ {\setbox#1\vpack to \paperheight
+ {\hsize\paperwidth
+ \vskip\topspace
+ \doifbothsides
+ {\hskip\backspace}
+ {\hskip\backspace}
+ {\hskip\dimexpr\paperwidth-\backspace-\makeupwidth\relax}%
+ \box#1}%
+ \dp#1\zeropoint}
+
+% \let\page_boxes_apply_clip_paper \gobbleoneargument
+% \let\page_boxes_apply_clip_print_left \gobbleoneargument
+% \let\page_boxes_apply_clip_print_right\gobbleoneargument
+
+%D This is rather specialized:
+
+\newconditional\c_page_areas_enabled
+\newbox \b_page_areas_registered
+
+\def\enabletextarearegistration
+ {\global\settrue\c_page_areas_enabled}
+
+\def\page_areas_registered_box
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_areas_registered_box_indeed
+ \else
+ \expandafter\page_areas_registered_box_forget
+ \fi}
+
+\def\page_areas_registered_box_forget#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\box#3}
+
+\def\page_areas_registered_box_indeed#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\anch_mark_flow_box{#3}}
+
+\def\page_areas_register_boxed#1%
+ {\begingroup
+ \setbox\scratchbox\vpack{#1}%
+ \wd\scratchbox\makeupwidth % somehow a space creeps in
+ \vpack{\page_areas_registered_box00\scratchbox}% 0 0 will go
+ \endgroup}
+
+% \def\page_areas_register_direct#1%
+% {\xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
+% \endgraf
+% \begingroup
+% \scratchdimen\dimexpr\MPy{pbd:\realfolio:b}-\MPy{pbd:\realfolio:e}\relax
+% \setbox\scratchbox\emptyhbox
+% \wd\scratchbox\makeupwidth
+% \ht\scratchbox\scratchdimen
+% \vsmash{\page_areas_registered_box00\scratchbox}%
+% \endgroup
+% #1%
+% \endgraf
+% \xypos{pbd:\realfolio:e}}
+
+\def\page_areas_register_direct#1#2%
+ {\scratchdepth\dp#2%
+ \dp#2\strutdepth
+ \anch_mark_flow_only{#2}%
+ \dp#2\scratchdepth
+ #1#2}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-brk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-brk.mkiv
new file mode 100644
index 00000000000..eabcb74f877
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-brk.mkiv
@@ -0,0 +1,562 @@
+%D \module
+%D [ file=page-brk, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Breaks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Breaks}
+
+\unprotect
+
+\ifdefined\resetcurrentstructuremarkswithpage \else \let\resetcurrentstructuremarkswithpage\relax \fi
+\ifdefined\noheaderandfooterlines \else \let\noheaderandfooterlines \relax \fi
+
+%D Page breaks.
+
+% \definepagebreak
+% [chapter]
+% [yes,header,right]
+%
+% \setuphead
+% [chapter]
+% [page=chapter,
+% header=empty,
+% footer=chapter]
+%
+% \definepagebreak % untested
+% [lastpage]
+% [left,{empty,right},{empty,left}]
+
+% public page handler, beware: definepage already in use (core-ref)
+%
+% \definepagebreak[instance][forsure]
+% \definepagebreak[forsure][yes,+4]
+
+\newconditional\c_page_breaks_enabled \settrue\c_page_breaks_enabled
+\newcount \c_page_breaks_prevpage
+
+\newtoks\everybeforepagebreak
+\newtoks\everyafterpagebreak
+
+\let\page_breaks_current_option \empty
+\let\page_breaks_current_options\empty
+
+\installcorenamespace{pagebreakmethod}
+\installcorenamespace{pagebreaks}
+
+\def\page_breaks_handle#1%
+ {\edef\page_breaks_current_options{#1}% handy for tracing
+ \processcommacommand[\page_breaks_current_options]\page_breaks_handle_step}
+
+\def\page_breaks_handle_step#1%
+ {\edef\page_breaks_current_option{#1}% can be used in handler
+ \ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname
+ \lastnamedcs
+ \else\ifcsname\??pagebreaks\page_breaks_current_option\endcsname
+ \expandafter\page_breaks_handle\lastnamedcs
+ \else
+ \page_breaks_unknown
+ \fi\fi}
+
+\def\page_breaks_handle_direct#1%
+ %{\csname\??pagebreakmethod#1\endcsname}
+ {\begincsname\??pagebreakmethod#1\endcsname}
+
+\unexpanded\def\installpagebreakmethod#1#2% low level definer
+ {\setvalue{\??pagebreakmethod#1}{#2}}
+
+\let\installpagebreakhandler\installpagebreakmethod % will go
+
+\unexpanded\def\definepagebreak
+ {\dodoubleargument\page_breaks_define}
+
+\def\page_breaks_define[#1][#2]%
+ {\setvalue{\??pagebreaks#1}{#2}}
+
+\unexpanded\def\pagebreak
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_process}
+
+\let\page\pagebreak
+
+\appendtoks
+ \flushnotes
+\to \everybeforepagebreak
+
+\def\page_breaks_process[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\par % always before group so that we clear hangs etc (as in side floats)
+ \ifvmode % extra check
+ \begingroup
+ \the\everybeforepagebreak
+ \c_page_breaks_prevpage\realpageno
+ \ifcase\pageornamentstate \or
+ % disable reset after shipout
+ \global\pageornamentstate\plustwo
+ \fi
+ \iffirstargument % or if empty i.e. []
+ \page_breaks_handle{#1}%
+ \else % so, no pagebreak when \pagebreak[] ! ! !
+ \page_breaks_handle_direct\v!yes
+ \fi
+ \relax
+ \ifnum\c_page_breaks_prevpage<\realpageno
+ \global\pageornamentstate\zerocount
+ \fi
+ \the\everyafterpagebreak
+ \endgroup
+ \fi}
+
+\unexpanded\def\usepageparameter#1%
+ {\edef\m_page_breaks_asked{#1\c!page}%
+ \ifx\m_page_breaks_asked\empty\else
+ \firstargumenttrue
+ \page_breaks_process[\m_page_breaks_asked]%
+ \fi}
+
+\unexpanded\def\dousepageparameter#1%
+ {\edef\m_page_breaks_asked{#1}%
+ \ifx\m_spac_align_asked\empty\else
+ \firstargumenttrue
+ \page_breaks_process[\m_page_breaks_asked]%
+ \fi}
+
+\unexpanded\def\resetpagebreak % used elsewhere too
+ {\global\settrue\c_page_breaks_enabled}
+
+\unexpanded\def\simplifypagebreak % to be used grouped !
+ {\def\page_breaks_process[##1]{\goodbreak}}
+
+\unexpanded\def\disablepagebreaks % to be used grouped !
+ {\def\page_breaks_process[##1]{}}
+
+\installpagebreakmethod \s!dummy
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!frame
+ {\page
+ \begingroup
+ \showframe
+ \page[\v!empty]
+ \endgroup}
+
+\unexpanded\def\page_breaks_unknown % how often called ?
+ {\doifelseinstring{+}\page_breaks_current_option
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \dorecurse\page_breaks_current_option\page_otr_insert_dummy_page}
+ {\doifelsenumber\page_breaks_current_option
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \doloop
+ {\ifnum\userpageno<\page_breaks_current_option\relax
+ \page_otr_insert_dummy_page
+ \else
+ \exitloop
+ \fi}}
+ {}}}
+
+\installpagebreakmethod \s!unknown
+ {\page_breaks_unknown}
+
+\installpagebreakmethod \s!default
+ {} % do nothing if empty
+
+\installpagebreakmethod \v!reset
+ {% better not: \global\pageornamentstate\zerocount
+ \resetpagebreak}
+
+\installpagebreakmethod \v!disable
+ {\global\setfalse\c_page_breaks_enabled}
+
+\installpagebreakmethod \v!yes
+ {\ifconditional\c_page_breaks_enabled
+ \page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \ifinsidecolumns % this will move to MUL
+ \page_otr_eject_page % otherwise sometimes no change
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!makeup
+ {\ifconditional\c_page_breaks_enabled
+ \page_otr_fill_and_eject_page
+ \fi}
+
+\installpagebreakmethod \v!blank
+ {\ifcase\pageornamentstate
+ \global\pageornamentstate\plusone
+ \fi}
+
+% also needed: \page \doifoddpageelse\relax{\page[\v!blank,\v!right]
+
+\installpagebreakmethod \v!no
+ {\ifconditional\c_page_breaks_enabled
+ \dosomebreak\nobreak
+ \fi}
+
+\installpagebreakmethod \v!preference
+ {\ifconditional\c_page_breaks_enabled
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[3][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!bigpreference
+ {\ifconditional\c_page_breaks_enabled
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[5][\zeropoint]%
+ \fi
+ \fi}
+
+% \installpagebreakmethod \v!empty {} % defined in page-txt.mkiv
+% \installpagebreakmethod \v!header{} % defined in page-txt.mkiv
+% \installpagebreakmethod \v!footer{} % defined in page-txt.mkiv
+
+\def\page_reset_marks_and_insert_dummy
+ {\resetcurrentstructuremarkswithpage\page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!left
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \doifbothsidesoverruled\donothing\page_reset_marks_and_insert_dummy\donothing}
+
+\installpagebreakmethod \v!right
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \doifbothsidesoverruled\donothing\donothing\page_reset_marks_and_insert_dummy}
+
+\installpagebreakmethod \v!even
+ {\page
+ \doifelseoddpage\page_reset_marks_and_insert_dummy\donothing}
+
+\installpagebreakmethod \v!odd
+ {\page
+ \doifelseoddpage\donothing\page_reset_marks_and_insert_dummy}
+
+\installpagebreakmethod \v!quadruple % not yet ok inside columnsets
+ {\ifdoublesided
+ \ifnum\numexpr\realpageno/\plusfour\relax=\numexpr\realpageno/\plustwo\relax\else
+ \page_breaks_handle_direct\v!yes
+ \page_breaks_handle_direct\v!empty
+ \page_breaks_handle_direct\v!empty
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!last
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \relax
+ \doifbothsidesoverruled
+ \page_facings_flush % hm
+ \donothing
+ {\noheaderandfooterlines
+ \page_otr_insert_dummy_page}%
+ \filluparrangedpages}
+
+\installpagebreakmethod \v!lastpage % handy for backpage preceded by empty pages
+ {\page_breaks_handle_direct\v!yes
+ \ifdoublesided
+ \page_breaks_handle_direct\v!left
+ \page_breaks_handle_direct\v!empty
+ \page_breaks_handle_direct\v!empty
+ \fi}
+
+\installpagebreakmethod \v!start {\global\settrue \c_otr_shipout_enabled}
+\installpagebreakmethod \v!stop {\global\setfalse\c_otr_shipout_enabled}
+
+% Column breaks.
+
+\installcorenamespace{columnbreakmethod}
+\installcorenamespace{columnbreaks}
+
+\newtoks\everybeforecolumnbreak
+\newtoks\everyaftercolumnbreak
+\newtoks\everysynchronizecolumn
+
+\let\page_breaks_columns_current_option \empty
+\let\page_breaks_columns_current_options\empty
+
+\def\page_breaks_columns_handle#1%
+ {\edef\page_breaks_columns_current_options{#1}%
+ \processcommacommand[#1]\page_breaks_columns_handle_step}
+
+\def\page_breaks_columns_handle_step#1%
+ {\edef\page_breaks_columns_current_option{#1}%
+ \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
+ \lastnamedcs
+ \else\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname
+ %\expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
+ \lastnamedcs
+ \else\ifcsname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\def\page_breaks_columns_handle_direct#1%
+ %{\csname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
+ {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
+
+\unexpanded\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
+ {\setvalue{\??columnbreakmethod#1:#2}{#3}}
+
+\let\installcolumnbreakhandler\installcolumnbreakmethod % will go
+
+\unexpanded\def\definecolumnbreak
+ {\dodoubleargument\page_break_columns_define}
+
+\def\page_break_columns_define[#1][#2]%
+ {\setvalue{\??columnbreaks#1}{#2}}
+
+\unexpanded\def\columnbreak
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_columns_process}
+
+\let\column\columnbreak
+
+\def\page_breaks_columns_process[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\begingroup
+ \the\everybeforecolumnbreak
+ \iffirstargument
+ \page_breaks_columns_handle{#1}%
+ \else
+ \page_breaks_columns_handle_direct\v!yes
+ \fi
+ \relax
+ \the\everyaftercolumnbreak
+ \endgroup
+ % outside group e.g. setting hsize
+ \the\everysynchronizecolumn}
+
+\appendtoks
+ \page_otr_command_set_hsize
+\to \everysynchronizecolumn
+
+%D Test page breaks.
+
+% \newdimen \d_page_tests_test
+% \newconstant\c_page_tests_mode
+
+\newconstant\testpagemethod % old
+\newconstant\testpagetrigger % old
+
+% \unexpanded\def\testpage {\c_page_tests_mode\plusone \dodoubleempty\page_tests_test} %
+% \unexpanded\def\testpageonly{\c_page_tests_mode\plustwo \dodoubleempty\page_tests_test} % no penalties added to the mvl
+% \unexpanded\def\testpagesync{\c_page_tests_mode\plusthree\dodoubleempty\page_tests_test} % force sync
+%
+% \def\page_tests_test[#1][#2]% don't change, only add more methods
+% {\relax % needed before \if
+% \ifconditional\c_page_breaks_enabled
+% % new from here
+% \ifcase\testpagetrigger
+% \endgraf
+% \or\ifvmode
+% \dosomebreak\allowbreak
+% \else % indeed?
+% \vadjust{\allowbreak}%
+% \endgraf
+% \fi\fi
+% % till here
+% \ifdim\pagegoal<\maxdimen \relax
+% \ifdim\pagetotal<\pagegoal \relax
+% \d_page_tests_test\dimexpr
+% #1\lineheight
+% +\pagetotal
+% \ifdim\lastskip<\parskip+\parskip\fi
+% \ifsecondargument+#2\fi
+% \relax
+% \ifcase\testpagemethod
+% \ifdim\d_page_tests_test>.99\pagegoal
+% \penalty-\plustenthousand
+% \fi
+% \or
+% \ifdim\dimexpr\d_page_tests_test-\pagegoal\relax>-\lineheight
+% \penalty-\plustenthousand
+% \fi
+% \or
+% \getnoflines\pagegoal
+% \ifdim\dimexpr\d_page_tests_test-\noflines\lineheight\relax>-\lineheight
+% \penalty-\plustenthousand
+% \fi
+% \or % same as 0 but more accurate
+% \ifdim\dimexpr\d_page_tests_test-10\scaledpoint\relax>\pagegoal
+% \penalty-\plustenthousand
+% \fi
+% \fi
+% \else\ifnum\c_page_tests_mode=\plusthree
+% \page_tests_flush_so_far
+% \fi\fi
+% \else\ifnum\c_page_tests_mode=\plusone
+% \goodbreak
+% \fi\fi
+% \else
+% \endgraf
+% \fi}
+%
+% \def\page_tests_flush_so_far
+% {\endgraf
+% \ifdim\pagetotal>\pagegoal
+% \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
+% \goodbreak
+% \else
+% \page
+% \fi
+% \fi}
+
+\installcorenamespace {pagechecker}
+\installcorenamespace {pagecheckermethod}
+
+\installcommandhandler \??pagechecker {pagechecker} \??pagechecker
+
+\setuppagechecker
+ [\c!method=1,
+ \c!before=,
+ \c!after=,
+ \c!inbetween=,
+ \c!lines=\plusthree,
+ \c!offset=\zeropoint]
+
+\def\page_check_amount
+ {\dimexpr
+ \pagecheckerparameter\c!lines\lineheight
+ +\pagetotal
+ \ifdim\lastskip<\parskip+\parskip\fi
+ +\pagecheckerparameter\c!offset
+ \relax}
+
+\unexpanded\def\checkpage
+ {\dodoubleempty\page_check}
+
+\def\page_check[#1][#2]%
+ {\relax % needed before \if
+ \endgraf
+ \triggerpagebuilder
+ \relax
+ \ifconditional\c_page_breaks_enabled
+ \begingroup
+ \edef\currentpagechecker{#1}%
+ \ifsecondargument\setupcurrentpagechecker[#2]\fi
+ \csname\??pagecheckermethod\pagecheckerparameter\c!method\endcsname
+ \endgroup
+ \fi}
+
+\setvalue{\??pagecheckermethod 0}%
+ {\ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \ifdim\page_check_amount>.99\pagegoal
+ \pagecheckerparameter\c!before
+ \penalty-\plustenthousand
+ \pagecheckerparameter\c!after
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi}
+
+\setvalue{\??pagecheckermethod 1}%
+ {\ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \ifdim\dimexpr\page_check_amount-\pagegoal\relax>-\lineheight
+ \pagecheckerparameter\c!before
+ \penalty-\plustenthousand
+ \pagecheckerparameter\c!after
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \goodbreak
+ \pagecheckerparameter\c!inbetween
+ \fi}
+
+\setvalue{\??pagecheckermethod 2}%
+ {\ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \getnoflines\pagegoal
+ \ifdim\dimexpr\page_check_amount-\noflines\lineheight\relax>-\lineheight
+ \pagecheckparameter\c!before
+ \penalty-\plustenthousand
+ \pagecheckerparameter\c!after
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi}
+
+\setvalue{\??pagecheckermethod 3}%
+ {\ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \ifdim\dimexpr\page_check_amount-10\scaledpoint\relax>\pagegoal
+ \pagecheckerparameter\c!before
+ \penalty-\plustenthousand
+ \pagecheckerparameter\c!after
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \else
+ \ifdim\pagetotal>\pagegoal
+ \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
+ \goodbreak
+ \pagecheckerparameter\c!inbetween
+ \else
+ \pagecheckerparameter\c!before
+ \page
+ \pagecheckerparameter\c!after
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi
+ \fi
+ \else
+ \pagecheckerparameter\c!inbetween
+ \fi}
+
+\definepagechecker[\s!unknown:0] [\c!method=0,\c!before=,\c!after=,\c!inbetween=]
+\definepagechecker[\s!unknown:1][\s!unknown:0][\c!method=1]
+\definepagechecker[\s!unknown:2][\s!unknown:0][\c!method=2]
+\definepagechecker[\s!unknown:3][\s!unknown:0][\c!method=3]
+
+\def\page_tests_test_a[#1][#2]{\normalexpanded{\checkpage[\s!unknown:1][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}}
+\def\page_tests_test_b[#1][#2]{\normalexpanded{\checkpage[\s!unknown:2][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}}
+\def\page_tests_test_c[#1][#2]{\normalexpanded{\checkpage[\s!unknown:3][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}}
+
+\unexpanded\def\testpage {\dodoubleempty\page_tests_test_a} %
+\unexpanded\def\testpageonly{\dodoubleempty\page_tests_test_b} % no penalties added to the mvl
+\unexpanded\def\testpagesync{\dodoubleempty\page_tests_test_c} % force sync
+
+%D Test column breaks.
+
+\unexpanded\def\testcolumn
+ {\dodoubleempty\page_tests_columns_test}
+
+\def\page_tests_columns_test[#1][#2]%
+ {\ifdefined\page_otr_command_test_column
+ \ifsecondargument
+ \page_otr_command_test_column[#1][#2]%
+ \else
+ \page_otr_command_test_column[#1][\zeropoint]%
+ \fi
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-col.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-col.mkiv
new file mode 100644
index 00000000000..14b5124210f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-col.mkiv
@@ -0,0 +1,179 @@
+%D \module
+%D [ file=page-col, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Column Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Column Helpers}
+
+%D Here we implement a couple of helpers for dealing with columns. For
+%D the moment we keep the names. When the mul and set modules are redone
+%D these can be adapted or disappear.
+
+\unprotect
+
+%D We reserve a counter for the number of columns as well as the current
+%D column. Both are not to be changed by users!
+
+\newcount\nofcolumns \nofcolumns\plusone
+\newcount\mofcolumns \mofcolumns\plusone
+
+\newconstant\columndirection % 0:lr 1:rl
+
+\setnewconstant\maxnofcolumns 50
+\setnewconstant\allocatednofcolumns 0
+
+%D During initialization the temporary boxes are allocated. This enables us to
+%D use as much columns as we want, without exhausting the pool of boxes too
+%D fast. We could have packed them in one box, but we've got enough boxes.
+%D
+%D Two sets of boxes are declared, the txtboxes are used for the text, the
+%D topboxes are for moved column floats.
+
+\installcorenamespace{columntext}
+\installcorenamespace{columnfooter}
+\installcorenamespace{columntop}
+\installcorenamespace{columnbottom}
+
+\unexpanded\def\initializecolumns#1%
+ {\ifnum#1>\maxnofcolumns
+ \showmessage\m!columns1\maxnofcolumns
+ \nofcolumns\maxnofcolumns
+ \else
+ \nofcolumns#1\relax
+ \fi
+ \ifnum\nofcolumns>\allocatednofcolumns
+ \page_columns_allocate
+ \fi}
+
+\def\page_columns_allocate
+ {\dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ \ifcsname\??columntext\recurselevel\endcsname \else
+ \expandafter\newbox\csname\??columntext \recurselevel\endcsname % text
+ \expandafter\newbox\csname\??columnfooter\recurselevel\endcsname % footer
+ \expandafter\newbox\csname\??columntop \recurselevel\endcsname % top insert
+ \expandafter\newbox\csname\??columnbottom\recurselevel\endcsname % bottom insert
+ \fi
+ \fi}%
+ \global\allocatednofcolumns\nofcolumns}
+
+\def\currentcolumn {1}
+
+\def\firstcolumnbox {\columntextbox\plusone}
+\def\currentcolumnbox {\columntextbox\mofcolumns}
+\def\lastcolumnbox {\columntextbox\nofcolumns}
+
+\def\firsttopcolumnbox {\columntopbox \plusone}
+\def\currenttopcolumnbox {\columntopbox \mofcolumns}
+\def\lasttopcolumnbox {\columntopbox \nofcolumns}
+
+\def\columntextbox #1{\csname\??columntext \number#1\endcsname}
+\def\columnfootbox #1{\csname\??columnfooter\number#1\endcsname}
+\def\columntopbox #1{\csname\??columntop \number#1\endcsname}
+\def\columnbotbox #1{\csname\??columnbottom\number#1\endcsname}
+
+\unexpanded\def\columnsettextbox {\global\setbox\columntextbox}
+\unexpanded\def\columnsetfootbox {\global\setbox\columnfootbox}
+\unexpanded\def\columnsettopbox {\global\setbox\columntopbox}
+\unexpanded\def\columnsetbotbox {\global\setbox\columnbotbox}
+
+\unexpanded\def\columngettextbox {\copy\columntextbox}
+\unexpanded\def\columngetfootbox {\copy\columnfootbox}
+\unexpanded\def\columngettopbox {\copy\columntopbox}
+\unexpanded\def\columngetbotbox {\copy\columnbotbox}
+
+\unexpanded\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
+\unexpanded\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
+\unexpanded\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
+\unexpanded\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
+
+%D Without going in details we present two macro's which handle the columns. The
+%D action which is transfered by the the first and only parameter can do something
+%D with \type {\currentcolumnbox}. In case of the mid columns, \type
+%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled outside these macro's.
+
+% \unexpanded\def\dohandlecolumn#1%
+% {\mofcolumns\recurselevel
+% \let\currentcolumn\recurselevel
+% #1\relax}
+%
+% \unexpanded\def\dohandleallcolumns#1%
+% {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlerevcolumns#1%
+% {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlemidcolumns#1%
+% {\dohandleallcolumns
+% {\ifnum\recurselevel>\plusone
+% \ifnum\recurselevel<\nofcolumns
+% \dohandlecolumn{#1}%
+% \fi
+% \fi}}
+%
+% As we don't nest we can use a fast variant:
+
+\unexpanded\def\dohandleallcolumnscs#1{\let\page_columns_action #1\page_columns_all_indeed}
+\unexpanded\def\dohandleallcolumns #1{\def\page_columns_action{#1}\page_columns_all_indeed}
+
+\unexpanded\def\dohandlerevcolumnscs#1{\let\page_columns_action #1\page_columns_rev_indeed}
+\unexpanded\def\dohandlerevcolumns #1{\def\page_columns_action{#1}\page_columns_rev_indeed}
+
+\unexpanded\def\dohandlemidcolumnscs#1{\let\page_columns_action #1\page_columns_mid_indeed}
+\unexpanded\def\dohandlemidcolumns #1{\def\page_columns_action{#1}\page_columns_mid_indeed}
+
+\unexpanded\def\page_columns_all_indeed
+ {\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
+
+\unexpanded\def\page_columns_all_next
+ {\advance\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
+
+\unexpanded\def\page_columns_rev_indeed
+ {\mofcolumns\nofcolumns
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
+
+\unexpanded\def\page_columns_rev_prev
+ {\advance\mofcolumns\minusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
+
+\unexpanded\def\page_columns_mid_indeed
+ {\mofcolumns\plustwo
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
+
+\unexpanded\def\page_columns_mid_next
+ {\edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \advance\mofcolumns\plusone
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-com.mkiv
new file mode 100644
index 00000000000..dfec3e25d30
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-com.mkiv
@@ -0,0 +1,178 @@
+%D \module
+%D [ file=page-com, % moved from page-imp
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Comments,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This will become runtime loaded code.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Comments}
+
+\unprotect
+
+%D \macros
+%D {setuppagecomment,startpagecomment}
+%D
+%D This command is not yet documented. Usage:
+%D
+%D \starttyping
+%D \setuppagecomment[state=start,location=right]
+%D
+%D \startpagecomment
+%D \input knuth
+%D \stoppagecomment
+%D \stoptyping
+
+\installcorenamespace{pagecomment}
+\installcorenamespace{pagecommentlocations}
+\installcorenamespace{pagecommentstates}
+
+\newdimen\d_page_comments_offset
+\newdimen\d_page_comments_page_width
+\newdimen\d_page_comments_page_height
+\newdimen\d_page_comments_width
+\newdimen\d_page_comments_height
+\newdimen\d_page_comments_distance
+
+\newconditional\c_page_comment_enabled
+
+\let\p_page_commands_location\v!none
+\let\p_page_commands_state \v!stop
+
+\installsetuponlycommandhandler \??pagecomment {pagecomment}
+
+\appendtoks
+ \edef\p_page_commands_location{\directpagecommentparameter\c!location}%
+ \edef\p_page_commands_state {\directpagecommentparameter\c!state}%
+ \expandnamespacemacro\??pagecommentstates\p_page_commands_state\v!none
+\to \everysetuppagecomment
+
+% \ifdefined\scrn_canvas_synchronize_simple
+
+ \appendtoks
+ \ifx\p_page_commands_state\v!start
+ \scrn_canvas_synchronize_simple
+ \else
+ \scrn_canvas_synchronize_complex
+ \fi
+ \to \everyshipout
+
+% \fi
+
+\setvalue{\??pagecommentstates\v!start}%
+ {\d_page_comments_offset \directpagecommentparameter\c!offset \relax
+ \d_page_comments_distance\directpagecommentparameter\c!distance\relax
+ \d_page_comments_width \directpagecommentparameter\c!width \relax
+ \d_page_comments_height \directpagecommentparameter\c!height \relax
+ \expandnamespacemacro\??pagecommentlocations\p_page_commands_location\v!none
+ \definepapersize[\v!pagecomment][\c!height=\d_page_comments_page_height,\c!width=\d_page_comments_page_width]%
+ \setuppapersize[\papersize][\v!pagecomment]%
+ \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]} % maybe append if already set
+
+\setvalue{\??pagecommentstates\v!stop}%
+ {\setupbackgrounds[\v!paper][\c!background=]}
+
+\setvalue{\??pagecommentstates\v!none}%
+ {}
+
+\setvalue{\??pagecommentlocations\v!bottom}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=\vss,\c!left=\hskip\d_page_comments_offset,\c!right=]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax
+ \defineoverlay[\v!pagecomment][\page_comments_top_bottom]}
+
+\setvalue{\??pagecommentlocations\v!top}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vss,\c!bottom=\vskip\d_page_comments_offset,\c!left=\hskip\d_page_comments_offset,\c!right=]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax
+ \defineoverlay[\v!pagecomment][\page_comments_top_bottom]}
+
+\setvalue{\??pagecommentlocations\v!left}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hss,\c!right=\hskip\d_page_comments_offset]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax
+ \defineoverlay[\v!pagecomment][\page_comments_left_right]}
+
+\setvalue{\??pagecommentlocations\v!right}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hskip\d_page_comments_offset,\c!right =\hss]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax
+ \defineoverlay[\v!pagecomment][\page_comments_left_right]}
+
+\setvalue{\??pagecommentlocations\v!none}%
+ {}% \setuppapersize[\c!bottom=,\c!top=,\c!left=,\c!right=]}
+
+\unexpanded\def\page_comments_top_bottom
+ {\vpack to \printpaperheight
+ {%\forgetall
+ \hsize\printpaperwidth\relax
+ \ifx\p_page_commands_location\v!bottom
+ \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax
+ \else
+ \vskip\d_page_comments_offset
+ \vss
+ \fi
+ \hskip\d_page_comments_offset
+ \vbox to \d_page_comments_height
+ {%\forgetall
+ \hsize\paperwidth
+ \ifconditional\c_page_comment_enabled
+ \getbuffer[\v!pagecomment]%
+ \global\setfalse\c_page_comment_enabled
+ \fi}%
+ \hfill
+ \ifx\p_page_commands_location\v!bottom
+ \vss
+ \vskip\d_page_comments_offset
+ \else
+ \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax
+ \fi}}
+
+\unexpanded\def\page_comments_left_right
+ {\hpack to \printpaperwidth
+ {\ifx\p_page_commands_location\v!right
+ \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax
+ \else
+ \hskip\d_page_comments_offset
+ \hss
+ \fi
+ \vbox to \printpaperheight
+ {%\forgetall
+ \vskip\d_page_comments_offset
+ \hsize\d_page_comments_width
+ \ifconditional\c_page_comment_enabled
+ \getbuffer[\v!pagecomment]%
+ \global\setfalse\c_page_comment_enabled
+ \fi
+ \vss}%
+ \ifx\p_page_commands_location\v!right
+ \hss
+ \hskip\d_page_comments_offset
+ \else
+ \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax
+ \fi}}
+
+\setvalue{\e!start\v!pagecomment}%
+ {\global\settrue\c_page_comment_enabled
+ \grabbufferdatadirect\v!pagecomment{\e!start\v!pagecomment}{\e!stop\v!pagecomment}}
+
+\setuppagecomment
+ [\c!state=, % \v!stop would invoke background calculation
+ \c!location=\v!bottom,
+ \c!offset=.5cm,
+ \c!distance=.5cm,
+ \c!height=5cm,
+ \c!width=10cm]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua b/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua
new file mode 100644
index 00000000000..782bbebfce8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua
@@ -0,0 +1,1454 @@
+if not modules then modules = { } end modules ["page-cst"] = {
+ version = 1.001,
+ comment = "companion to page-cst.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: check what is used
+
+local next, type = next, type
+local ceil, floor, odd, round = math.ceil, math.floor, math.odd, math.round
+local lower = string.lower
+local copy = table.copy
+
+local trace_state = false trackers.register("columnsets.trace", function(v) trace_state = v end)
+local trace_detail = false trackers.register("columnsets.detail", function(v) trace_detail = v end)
+local trace_cells = false trackers.register("columnsets.cells", function(v) trace_cells = v end)
+
+local report = logs.reporter("column sets")
+
+local setmetatableindex = table.setmetatableindex
+
+local properties = nodes.properties
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+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 insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+local rule_code = nodecodes.rule
+
+local topskip_code = gluecodes.topskip
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local userskip_code = gluecodes.userskip
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local hpack = nuts.hpack
+local vpack = nuts.vpack
+local freenode = nuts.free
+local flushlist = nuts.flush_list
+local removenode = nuts.remove
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+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 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 getskip = nuts.getskip
+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_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_kern = nodepool.kern
+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_left = variables.left
+local v_right = variables.right
+local v_yes = variables.yes
+local v_page = variables.page
+local v_first = variables.first
+local v_last = variables.last
+local v_wide = variables.wide
+
+pagebuilders = pagebuilders or { } -- todo: pages.builders
+pagebuilders.columnsets = pagebuilders.columnsets or { }
+local columnsets = pagebuilders.columnsets
+
+local data = { [""] = { } }
+
+-- todo: use state
+
+local function setstate(t,start)
+ if start or not t.firstcolumn then
+ t.firstcolumn = odd(getcount("realpageno")) and 1 or 2
+ end
+ if t.firstcolumn > 1 then
+ t.firstcolumn = 1
+ t.lastcolumn = t.nofleft
+ t.state = "left"
+ else
+ t.firstcolumn = t.nofleft + 1
+ t.lastcolumn = t.firstcolumn + t.nofright - 1
+ t.state = "right"
+ end
+ t.currentcolumn = t.firstcolumn
+ t.currentrow = 1
+end
+
+function columnsets.define(t)
+ local name = t.name
+ local nofleft = t.nofleft or 1
+ local nofright = t.nofright or 1
+ local nofcolumns = nofleft + nofright
+ local dataset = data[name] or { }
+ data[name] = dataset
+ dataset.nofleft = nofleft
+ dataset.nofright = nofright
+ dataset.nofcolumns = nofcolumns
+ dataset.nofrows = t.nofrows or 1
+ dataset.distance = t.distance or getdimen("bodyfontsize")
+ dataset.maxwidth = t.maxwidth or getdimen("makeupwidth")
+ dataset.lineheight = t.lineheight or getdimen("globalbodyfontstrutheight")
+ dataset.linedepth = t.linedepth or getdimen("globalbodyfontstrutdepth")
+ --
+ dataset.cells = { }
+ dataset.currentcolumn = 1
+ dataset.currentrow = 1
+ --
+ dataset.lines = dataset.lines or setmetatableindex("table")
+ dataset.start = dataset.start or setmetatableindex("table")
+ --
+ dataset.page = 1
+ --
+ local distances = dataset.distances or setmetatableindex(function(t,k)
+ return dataset.distance
+ end)
+ dataset.distances = distances
+ --
+ local widths = dataset.widths or setmetatableindex(function(t,k)
+ return dataset.width
+ end)
+ dataset.widths = widths
+ --
+ local width = t.width
+ if not width or width == 0 then
+ local dl = 0
+ local dr = 0
+ for i=1,nofleft-1 do
+ dl = dl + distances[i]
+ end
+ for i=1,nofright-1 do
+ dr = dr + distances[nofleft+i]
+ end
+ local nl = nofleft
+ local nr = nofright
+ local wl = dataset.maxwidth
+ local wr = wl
+ for i=1,nofleft do
+ local w = rawget(widths,i)
+ if w then
+ nl = nl - 1
+ wl = wl - w
+ end
+ end
+ for i=1,nofright do
+ local w = rawget(widths,nofleft+i)
+ if w then
+ nr = nr - 1
+ wr = wr - w
+ end
+ end
+ dl = (wl - dl) / nl
+ dr = (wr - dr) / nr
+ if dl > dr then
+ report("using %s page column width %p in columnset %a","right",dr,name)
+ width = dr
+ elseif dl < dr then
+ report("using %s page column width %p in columnset %a","left",dl,name)
+ width = dl
+ else
+ width = dl
+ end
+ end
+ -- report("width %p, nleft %i, nright %i",width,nofleft,nofright)
+ width = round(width)
+ dataset.width = width
+ local spans = { }
+ dataset.spans = spans
+ for i=1,nofleft do
+ local s = { }
+ local d = 0
+ for j=1,nofleft-i+1 do
+ d = d + width
+ s[j] = round(d)
+ d = d + distances[j]
+ end
+ spans[i] = s
+ end
+ for i=1,nofright do
+ local s = { }
+ local d = 0
+ for j=1,nofright-i+1 do
+ d = d + width
+ s[j] = round(d)
+ d = d + distances[j]
+ end
+ spans[nofleft+i] = s
+ end
+ --
+ local spreads = copy(spans)
+ dataset.spreads = spreads
+ local gap = 2 * getdimen("backspace")
+ for l=1,nofleft do
+ local s = spreads[l]
+ local n = #s
+ local o = s[n] + gap
+ for r=1,nofright do
+ n = n + 1
+ s[n] = s[r] + o
+ end
+ end
+ --
+ texsetdimen("d_page_grid_column_width",dataset.width)
+ --
+ setstate(dataset,true)
+ --
+ return dataset
+end
+
+local function check(dataset)
+ local cells = dataset.cells
+ local page = dataset.page
+ local offset = odd(page) and dataset.nofleft or 0
+ local start = dataset.start
+ local list = rawget(start,page)
+ if list then
+ for c, n in next, list do
+ local column = cells[offset + c]
+ if column then
+ for r=1,n do
+ column[r] = true
+ end
+ end
+ end
+ start[page] = nil
+ end
+ local lines = dataset.lines
+ local list = rawget(lines,page)
+ local rows = dataset.nofrows
+ if list then
+ for c, n in next, list do
+ local column = cells[offset + c]
+ if column then
+ if n > 0 then
+ for r=n+1,rows do
+ column[r] = true
+ end
+ elseif n < 0 then
+ for r=rows,rows+n+1,-1 do
+ column[r] = true
+ end
+ end
+ end
+ end
+ lines[page] = nil
+ end
+end
+
+local function erase(dataset,all)
+ local cells = dataset.cells
+ local nofrows = dataset.nofrows
+ local first = 1
+ local last = dataset.nofcolumns
+ --
+ if not all then
+ first = dataset.firstcolumn or first
+ last = dataset.lastcolumn or last
+ end
+ for c=first,last do
+ local column = { }
+ for r=1,nofrows do
+ if column[r] then
+ report("slot (%i,%i) is not empty",c,r)
+ end
+ column[r] = false -- not used
+ end
+ cells[c] = column
+ end
+end
+
+function columnsets.reset(t)
+ local dataset = columnsets.define(t)
+ erase(dataset,true)
+ check(dataset)
+end
+
+function columnsets.prepareflush(name)
+ local dataset = data[name]
+ local cells = dataset.cells
+ local firstcolumn = dataset.firstcolumn
+ local lastcolumn = dataset.lastcolumn
+ local nofrows = dataset.nofrows
+ local lineheight = dataset.lineheight
+ local linedepth = dataset.linedepth
+ local widths = dataset.widths
+ local height = (lineheight+linedepth)*nofrows -- - linedepth
+ --
+ local columns = { }
+ dataset.columns = columns
+ --
+ for c=firstcolumn,lastcolumn do
+ local column = cells[c]
+ for r=1,nofrows do
+ local cell = column[r]
+ if (cell == false) or (cell == true) then
+ if trace_cells then
+ column[r] = new_trace_rule(65536*2,lineheight,linedepth)
+ else
+ column[r] = new_empty_rule(0,lineheight,linedepth)
+ end
+ end
+ end
+ for r=1,nofrows-1 do
+ setlink(column[r],column[r+1])
+ end
+ local v = new_vlist(column[1])
+ setfield(v,"height",height)
+-- setfield(v,"depth",linedepth)
+ setfield(v,"width",widths[c])
+ columns[c] = v
+ end
+ --
+ texsetcount("c_page_grid_first_column",firstcolumn)
+ texsetcount("c_page_grid_last_column",lastcolumn)
+end
+
+function columnsets.flushcolumn(name,column)
+ local dataset = data[name]
+ local columns = dataset.columns
+ local packed = columns[column]
+ setbox("b_page_grid_column",packed)
+ columns[column] = nil
+end
+
+function columnsets.finishflush(name)
+ local dataset = data[name]
+ local cells = dataset.cells
+ local firstcolumn = dataset.firstcolumn
+ local lastcolumn = dataset.lastcolumn
+ local nofrows = dataset.nofrows
+ for c=firstcolumn,lastcolumn do
+ local column = { }
+ for r=1,nofrows do
+ column[r] = false -- not used
+ end
+ cells[c] = column
+ end
+ dataset.page = dataset.page + 1
+ check(dataset)
+ setstate(dataset)
+end
+
+function columnsets.block(t)
+ local dataset = data[t.name]
+ local cells = dataset.cells
+ local nofcolumns = dataset.nofcolumns
+ local nofrows = dataset.nofrows
+ --
+ local c = t.c or 0
+ local r = t.r or 0
+ if c == 0 or r == 0 or c > nofcolumns or r > nofrows then
+ return
+ end
+ local nc = t.nc or 0
+ local nr = t.nr or 0
+ if nc == 0 then
+ return
+ end
+ if nr == 0 then
+ return
+ end
+ local rr = r + nr - 1
+ local cc = c + nc - 1
+ if rr > nofrows then
+ rr = nofrows
+ end
+ if cc > nofcolumns then
+ cc = nofcolumns
+ end
+ for i=c,cc do
+ local column = cells[i]
+ for j=r,rr do
+ column[j] = true
+ end
+ end
+end
+
+local function here(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ local rr = r + nr - 1
+ if rr > nofrows then
+ return false
+ end
+ local cc = 0
+ local wd = spans[c]
+ local wc = 0
+ local nc = 0
+ for i=c,nofcolumns do
+ nc = nc + 1
+ wc = wd[nc]
+ if not wc then
+ break
+ elseif wc >= width then
+ cc = i
+ break
+ end
+ end
+ if cc == 0 or cc > nofcolumns then
+ -- report("needed %p, no slot free at (%i,%i)",width,c,r)
+ return false
+ end
+ for i=c,cc do
+ local column = cells[i]
+ for j=r,rr do
+ if column[j] then
+ -- report("width %p, needed %p, checking (%i,%i) x (%i,%i), %s",width,wc,c,r,nc,nr,"quit")
+ return false
+ end
+ end
+ end
+ -- report("width %p, needed %p, checking (%i,%i) x (%i,%i), %s",width,wc,c,r,nc,nr,"match")
+ return c, r, nc
+end
+
+local methods = {
+ [v_here] = here,
+ [v_fixed] = here,
+ tblr = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for j=1,nofrows-nr+1 do
+ for i=c,nofcolumns do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ lrtb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=1,nofrows-nr+1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ tbrl = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for j=1,nofrows-nr+1 do
+ for i=nofcolumns,c,-1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ rltb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=nofcolumns,c,-1 do
+ for j=1,nofrows-nr+1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ btlr = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for j=nofrows-nr+1,1,-1 do
+ for i=c,nofcolumns do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ lrbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=nofrows-nr+1,1,-1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ btrl = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for j=nofrows-nr+1,1,-1 do
+ for i=nofcolumns,c,-1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ rlbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=nofcolumns,c,-1 do
+ for j=nofrows-nr+1,1,-1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ fxtb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=r,nofrows-nr+1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ r = 1
+ end
+ end
+ end,
+ fxbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=nofrows-nr+1,r,-1 do
+ if not cells[i][j] then
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ r = 1
+ end
+ end,
+ [v_top] = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=1,nofrows-nr+1 do
+ if cells[i][j] then
+ break
+ else
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+ [v_bottom] = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
+ for i=c,nofcolumns do
+ for j=1,nofrows-nr+1 do
+ if cells[i][j] then
+ break
+ else
+ local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
+ if c then
+ return c, r, cc
+ end
+ end
+ end
+ end
+ end,
+}
+
+local threshold = 50
+
+function columnsets.check(t)
+ local dataset = data[t.name]
+ local cells = dataset.cells
+ local nofcolumns = dataset.nofcolumns
+ local nofrows = dataset.nofrows
+ local widths = dataset.widths
+ local lineheight = dataset.lineheight
+ local linedepth = dataset.linedepth
+ local distances = dataset.distances
+ local spans = dataset.spans
+ --
+ local method = lower(t.method or "tblr")
+ local boxwidth = t.width or 0
+ local boxheight = t.height or 0
+ local boxnumber = t.box
+ local box = boxnumber and getbox(boxnumber)
+ --
+ if boxwidth > 0 and boxheight > 0 then
+ -- we're ok
+ elseif box then
+ boxwidth = getfield(box,"width")
+ boxheight = getfield(box,"height") + getfield(box,"depth")
+ else
+ report("empty box")
+ return
+ end
+ --
+ local c = t.c or 0
+ local r = t.r or 0
+ if c == 0 then
+ c = dataset.currentcolumn
+ end
+ if r == 0 then
+ r = dataset.currentrow
+ end
+ if c == 0 or r == 0 or c > nofcolumns or r > nofrows then
+ texsetcount("c_page_grid_reserved_state",5)
+ return
+ end
+-- report("checking width %p, height %p, depth %p, slot (%i,%i)",boxwidth,boxheight,boxdepth,c,r)
+ local nr = ceil(boxheight/(lineheight+linedepth))
+ --
+ local action = methods[method]
+ local cfound = false
+ local rfound = false
+ local lastcolumn = dataset.lastcolumn
+ -- if t.option == v_wide then
+ -- lastcolumn = nofcolumns
+ -- spans = dataset.spreads
+ -- end
+ if action then
+ cfound, rfound, nc = action(c,r,nr,lastcolumn,nofrows,cells,boxwidth-threshold,spans)
+ end
+ if not cfound and method ~= v_here then
+ cfound, rfound, nc = here(c,r,nr,lastcolumn,nofrows,cells,boxwidth-threshold,spans)
+ end
+ if cfound then
+ local ht = nr*(lineheight+linedepth)
+ local wd = spans[cfound][nc]
+ dataset.reserved_ht = ht
+ dataset.reserved_wd = wd
+ dataset.reserved_c = cfound
+ dataset.reserved_r = rfound
+ dataset.reserved_nc = nc
+ dataset.reserved_nr = nr
+ texsetcount("c_page_grid_reserved_state",0)
+ texsetdimen("d_page_grid_reserved_height",ht)
+ texsetdimen("d_page_grid_reserved_width",wd)
+ -- report("using (%i,%i) x (%i,%i) @ (%p,%p)",cfound,rfound,nc,nr,wd,ht)
+ else
+ dataset.reserved_ht = false
+ dataset.reserved_wd = false
+ dataset.reserved_c = false
+ dataset.reserved_r = false
+ dataset.reserved_nc = false
+ dataset.reserved_nr = false
+ texsetcount("c_page_grid_reserved_state",4)
+ -- texsetdimen("d_page_grid_reserved_height",0)
+ -- texsetdimen("d_page_grid_reserved_width",0)
+ -- report("no slot found")
+ end
+end
+
+function columnsets.put(t)
+ local dataset = data[t.name]
+ local cells = dataset.cells
+ local widths = dataset.widths
+ local lineheight = dataset.lineheight
+ local linedepth = dataset.linedepth
+ local boxnumber = t.box
+ local box = boxnumber and takebox(boxnumber)
+ --
+ local c = t.c or dataset.reserved_c
+ local r = t.r or dataset.reserved_r
+ if not c or not r then
+ -- report("no reserved slot (%i,%i)",c,r)
+ return
+ end
+ local lastc = c + dataset.reserved_nc - 1
+ local lastr = r + dataset.reserved_nr - 1
+ --
+ for i=c,lastc do
+ local column = cells[i]
+ for j=r,lastr do
+ column[j] = true
+ end
+ end
+ cells[c][r] = box
+ setfield(box,"height",lineheight)
+ setfield(box,"depth",linedepth)
+ setfield(box,"width",widths[c])
+ dataset.reserved_c = false
+ dataset.reserved_r = false
+ dataset.reserved_nc = false
+ dataset.reserved_nr = false
+ --
+end
+
+local function findgap(dataset)
+ local cells = dataset.cells
+ local nofcolumns = dataset.nofcolumns
+ local nofrows = dataset.nofrows
+ local currentrow = dataset.currentrow
+ local currentcolumn = dataset.currentcolumn
+ --
+ local foundc = 0
+ local foundr = 0
+ local foundn = 0
+ for c=currentcolumn,dataset.lastcolumn do
+ local column = cells[c]
+foundn = 0
+ for r=currentrow,nofrows do
+ if not column[r] then
+ if foundc == 0 then
+ foundc = c
+ foundr = r
+ end
+ foundn = foundn + 1
+ elseif foundn > 0 then
+ return foundc, foundr, foundn
+ end
+ end
+ if foundn > 0 then
+ return foundc, foundr, foundn
+ end
+ currentrow = 1
+ end
+end
+
+-- we can enforce grid snapping
+
+-- local function checkroom(head,available,row)
+-- if row == 1 then
+-- while head do
+-- local id = getid(head)
+-- if id == glue_code then
+-- head = getnext(head)
+-- else
+-- break
+-- end
+-- end
+-- end
+-- local used = 0
+-- local line = false
+-- while head do
+-- local id = getid(head)
+-- if id == hlist_code or id == vlist_code or id == rule_code then -- <= rule_code
+-- used = used + getfield(head,"height") + getfield(head,"depth")
+-- line = true
+-- elseif id == glue_code then
+-- if line then
+-- break
+-- end
+-- used = used + getfield(head,"width")
+-- elseif id == kern_code then
+-- used = used + getfield(head,"kern")
+-- elseif id == penalty_code then
+-- end
+-- if used > available then
+-- break
+-- end
+-- head = getnext(head)
+-- end
+-- return line, used
+-- end
+
+local function checkroom(head,available,row)
+ if row == 1 then
+ while head do
+ local id = getid(head)
+ if id == glue_code then
+ head = getnext(head)
+ else
+ break
+ end
+ end
+ end
+ local used = 0
+ local line = false
+ while head do
+ local id = getid(head)
+ if id == hlist_code or id == vlist_code or id == rule_code then -- <= rule_code
+ used = used + getfield(head,"height") + getfield(head,"depth")
+ line = true
+ if used > available then
+ break
+ end
+ elseif id == glue_code then
+ if line then
+ break
+ end
+ used = used + getfield(head,"width")
+ if used > available then
+ break
+ end
+ elseif id == kern_code then
+ used = used + getfield(head,"kern")
+ if used > available then
+ break
+ end
+ elseif id == penalty_code then
+ -- not good enough ... we need to look bakck too
+ if getfield(head,"penalty") >= 10000 then
+ line = false
+ else
+ break
+ end
+ end
+ head = getnext(head)
+ end
+ return line, used
+end
+
+-- we could preroll on a cheap copy .. in fact, a split loop normally works on
+-- a copy ... then we could also stepsise make the height smaller .. slow but nice
+
+-- local function findslice(dataset,head,available,column,row)
+-- local used = 0
+-- local first = nil
+-- local last = nil
+-- local line = false
+-- local lineheight = dataset.lineheight
+-- local linedepth = dataset.linedepth
+-- if row == 1 then
+-- while head do
+-- local id = getid(head)
+-- if id == glue_code then
+-- head = removenode(head,head,true)
+-- else
+-- break
+-- end
+-- end
+-- end
+-- while head do
+-- -- no direction yet, if so use backend code
+-- local id = getid(head)
+-- local hd = 0
+-- if id == hlist_code or id == vlist_code or id == rule_code then -- <= rule_code
+-- hd = getfield(head,"height") + getfield(head,"depth")
+-- elseif id == glue_code then
+-- hd = getfield(head,"width")
+-- elseif id == kern_code then
+-- hd = getfield(head,"kern")
+-- elseif id == penalty_code then
+-- end
+-- if used + hd > available then
+-- if first then
+-- setnext(last)
+-- setprev(head)
+-- return used, first, head
+-- else
+-- return 0
+-- end
+-- else
+-- if not first then
+-- first = head
+-- end
+-- used = used + hd
+-- last = head
+-- head = getnext(head)
+-- end
+-- end
+-- return used, first
+-- end
+
+-- todo
+--
+-- first = takelist(done)
+-- head = takelist(rest)
+-- local tail = nuts.tail(first)
+-- if false then
+-- local disc = tex.lists.split_discards_head
+-- if disc then
+-- disc = tonut(disc)
+-- setlink(tail,disc)
+-- tail = nuts.tail(disc)
+-- tex.lists.split_discards_head = nil
+-- end
+-- end
+-- setlink(tail,head)
+
+-- We work on a copy because we need to keep properties. We can make faster copies
+-- by only doing a one-level deep copy.
+
+local function findslice(dataset,head,available,column,row)
+ local first = nil
+ local lineheight = dataset.lineheight
+ local linedepth = dataset.linedepth
+ local linetotal = lineheight + linedepth
+ local slack = 65536 -- 1pt
+ local copy = copylist(head)
+ local attempts = 0
+ local usedsize = available
+ while true do
+ attempts = attempts + 1
+ texsetbox("scratchbox",tonode(new_vlist(copy)))
+ local done = splitbox("scratchbox",usedsize,"additional")
+ local used = getfield(done,"height")
+ local rest = takebox("scratchbox")
+ if used > (usedsize+slack) then
+ if trace_detail then
+ report("at (%i,%i) available %p, used %p, overflow %p",column,row,usedsize,used,used-usedsize)
+ end
+ -- flush copy
+ flushlist(takelist(done))
+ flushlist(takelist(rest))
+ -- check it we can try again
+ usedsize = usedsize - linetotal
+ if usedsize > linetotal then
+ copy = copylist(head)
+ else
+ return 0, nil, head
+ end
+ else
+ -- flush copied box
+ flushlist(takelist(done))
+ flushlist(takelist(rest))
+ -- deal with real data
+ texsetbox("scratchbox",tonode(new_vlist(head)))
+ done = splitbox("scratchbox",usedsize,"additional")
+ rest = takebox("scratchbox")
+ used = getfield(done,"height")
+ if attempts > 1 then
+ used = available
+ end
+ first = takelist(done)
+ head = takelist(rest)
+ -- return result
+ return used, first, head
+ end
+ end
+end
+
+local nofcolumngaps = 0
+
+function columnsets.add(name,box)
+ local dataset = data[name]
+ local cells = dataset.cells
+ local nofcolumns = dataset.nofcolumns
+ local nofrows = dataset.nofrows
+ local currentrow = dataset.currentrow
+ local currentcolumn = dataset.currentcolumn
+ local lineheight = dataset.lineheight
+ local linedepth = dataset.linedepth
+ local widths = dataset.widths
+ --
+ local b = getbox(box)
+ local l = getlist(b)
+-- dataset.rest = l
+ if l then
+ setlist(b,nil)
+ local hd = lineheight + linedepth
+ while l do
+ local foundc, foundr, foundn = findgap(dataset)
+ if foundc then
+ local available = foundn * hd
+ local used, first, last = findslice(dataset,l,available,foundc,foundr)
+ if first then
+ local v
+ if used == available or (foundr+foundn > nofrows) then
+ v = vpack(first,available,"exactly")
+ else
+ v = new_vlist(first)
+ end
+ nofcolumngaps = nofcolumngaps + 1
+ -- getmetatable(v).columngap = nofcolumngaps
+ properties[v] = { columngap = nofcolumngaps }
+ -- report("setting gap %a at (%i,%i)",nofcolumngaps,foundc,foundr)
+ setfield(v,"height",lineheight)
+ setfield(v,"depth",linedepth)
+ setfield(v,"width",widths[currentcolumn])
+ local column = cells[foundc]
+ --
+ column[foundr] = v
+ used = used - hd
+ if used > 0 then
+ for r=foundr+1,foundr+foundn-1 do
+ used = used - hd
+ foundr = foundr + 1
+ column[r] = true
+ if used <= 0 then
+ break
+ end
+ end
+ end
+ currentcolumn = foundc
+ currentrow = foundr
+ dataset.currentcolumn = currentcolumn
+ dataset.currentrow = currentrow
+ l = last
+ dataset.rest = l
+ else
+ local column = cells[foundc]
+ for i=foundr,foundr+foundn-1 do
+ column[i] = true
+ end
+ l = last
+ end
+ else
+ dataset.rest = l
+ return -- save and flush
+ end
+ end
+ end
+end
+
+do
+
+ -- A split approach is more efficient than a context(followup) inside
+ -- followup itself as we need less (internal) housekeeping.
+
+ local followup = nil
+ local splitter = lpeg.splitter("*",tonumber)
+
+ columnsets["noto"] = function(t)
+ return followup()
+ end
+
+ columnsets["goto"] = function(name,target)
+ local dataset = data[name]
+ local nofcolumns = dataset.nofcolumns
+ if target == v_yes or target == "" then
+ local currentcolumn = dataset.currentcolumn
+ followup = function()
+ context(dataset.currentcolumn == currentcolumn and 1 or 0)
+ end
+ return followup()
+ end
+ if target == v_first then
+ if dataset.currentcolumn > 1 then
+ target = v_page
+ else
+ return context(0)
+ end
+ end
+ if target == v_page then
+ if dataset.currentcolumn == 1 and dataset.currentrow == 1 then
+ return context(0)
+ else
+ local currentpage = dataset.page
+ followup = function()
+ context(dataset.page == currentpage and 1 or 0)
+ end
+ return followup()
+ end
+ end
+ if target == v_last then
+ target = dataset.nofcolumns
+ if dataset.currentcolumn ~= target then
+ followup = function()
+ context(dataset.currentcolumn ~= target and 1 or 0)
+ end
+ return followup()
+ end
+ return
+ end
+ local targetpage = tonumber(target)
+ if targetpage then
+ followup = function()
+ context(dataset.currentcolumn ~= targetpage and 1 or 0)
+ end
+ return followup()
+ end
+ local targetcolumn, targetrow = lpeg.match(splitter,target)
+ if targetcolumn and targetrow then
+ if dataset.currentcolumn ~= targetcolumn and dataset.currentrow ~= targetrow then
+ followup = function()
+ if dataset.currentcolumn ~= targetcolumn then
+ context(1)
+ return
+ end
+ if dataset.currentcolumn == targetcolumn then
+ context(dataset.currentrow ~= targetrow and 1 or 0)
+ else
+ context(0)
+ end
+ end
+ return followup()
+ end
+ end
+ end
+
+end
+
+function columnsets.currentcolumn(name)
+ local dataset = data[name]
+ context(dataset.currentcolumn)
+end
+
+function columnsets.flushrest(name,box)
+ local dataset = data[name]
+ local rest = dataset.rest
+ if rest then
+ dataset.rest = nil
+ setbox("global",box,new_vlist(rest))
+ end
+end
+
+function columnsets.setvsize(name)
+ local dataset = data[name]
+ local c, r, n = findgap(dataset)
+ if n then
+ dataset.currentcolumn = c
+ dataset.currentrow = r
+ else
+ dataset.currentcolumn = 1
+ dataset.currentrow = 1
+ n = 0
+ end
+ local gap = n*(dataset.lineheight+dataset.linedepth)
+ texsetdimen("d_page_grid_gap_height",gap)
+ -- can be integrated
+ -- report("state %a, n %a, column %a, row %a",dataset.state,n,dataset.currentcolumn,dataset.currentrow)
+end
+
+function columnsets.sethsize(name)
+ local dataset = data[name]
+ texsetdimen("d_page_grid_column_width",dataset.widths[dataset.currentcolumn])
+end
+
+function columnsets.sethspan(name,span)
+ -- no checking if there is really space, so we assume it can be
+ -- placed which makes spans a very explicit feature
+ local dataset = data[name]
+ local column = dataset.currentcolumn
+ local available = dataset.lastcolumn - column + 1
+ if span > available then
+ span = available
+ end
+ local width = dataset.spans[column][span]
+ texsetdimen("d_page_grid_span_width",width)
+end
+
+function columnsets.setlines(t)
+ local dataset = data[t.name]
+ dataset.lines[t.page][t.column] = t.value
+end
+
+function columnsets.setstart(t)
+ local dataset = data[t.name]
+ dataset.start[t.page][t.column] = t.value
+end
+
+function columnsets.setproperties(t)
+ local dataset = data[t.name]
+ local column = t.column
+ dataset.distances[column] = t.distance
+ dataset.widths[column] = t.width
+end
+
+local areas = { }
+
+function columnsets.registerarea(t)
+ -- maybe metatable with values
+ areas[#areas+1] = t
+end
+
+-- state : repeat | start
+
+local ctx_page_grid_set_area = context.protected.page_grid_set_area
+
+function columnsets.flushareas(name)
+ local nofareas = #areas
+ if nofareas == 0 then
+ return
+ end
+ local dataset = data[name]
+ local page = dataset.page
+ if odd(page) then
+ -- report("checking %i areas",#areas)
+ local kept = { }
+ for i=1,nofareas do
+ local area = areas[i]
+ -- local page = area.page -- maybe use page counter in columnset
+ -- local type = area.type
+ local okay = false
+ --
+ local nofcolumns = area.nc
+ local nofrows = area.nr
+ local column = area.c
+ local row = area.r
+ columnsets.block {
+ name = name,
+ c = column,
+ r = row,
+ nc = nofcolumns,
+ nr = nofrows,
+ }
+ local left = 0
+ local start = dataset.nofleft + 1
+ local overflow = (column + nofcolumns - 1) - dataset.nofleft
+ local height = nofrows * (dataset.lineheight + dataset.linedepth)
+ local width = dataset.spreads[column][nofcolumns]
+ -- report("span, width %p, overflow %i",width,overflow)
+ if overflow > 0 then
+ local used = nofcolumns - overflow
+ left = dataset.spreads[column][used] + getdimen("backspace")
+ end
+ ctx_page_grid_set_area(name,area.name,column,row,width,height,start,left) -- or via counters / dimens
+ if area.state ~= v_repeat then
+ area = nil
+ end
+ if area then
+ kept[#kept+1] = area
+ end
+ end
+ areas = kept
+ end
+end
+
+function columnsets.setarea(t)
+ local dataset = data[t.name]
+ local cells = dataset.cells
+ local box = takebox(t.box)
+ local column = t.c
+ local row = t.r
+ if column and row then
+ setfield(box,"height",dataset.lineheight)
+ setfield(box,"depth",dataset.linedepth)
+ setfield(box,"width",dataset.widths[column])
+ cells[column][row] = box
+ end
+end
+
+-- The interface.
+
+interfaces.implement {
+ name = "definecolumnset",
+ actions = columnsets.define,
+ arguments = { {
+ { "name", "string" },
+ } }
+}
+
+interfaces.implement {
+ name = "resetcolumnset",
+ actions = columnsets.reset,
+ arguments = { {
+ { "name", "string" },
+ { "nofleft", "integer" },
+ { "nofright", "integer" },
+ { "nofrows", "integer" },
+ { "lineheight", "dimension" },
+ { "linedepth", "dimension" },
+ { "width", "dimension" },
+ { "distance", "dimension" },
+ { "maxwidth", "dimension" },
+ } }
+}
+
+interfaces.implement {
+ name = "preparecolumnsetflush",
+ actions = columnsets.prepareflush,
+ arguments = { "string" },
+}
+
+interfaces.implement {
+ name = "finishcolumnsetflush",
+ actions = columnsets.finishflush,
+ arguments = { "string" },
+}
+
+interfaces.implement {
+ name = "flushcolumnsetcolumn",
+ actions = columnsets.flushcolumn,
+ arguments = { "string" ,"integer" },
+}
+
+interfaces.implement {
+ name = "setvsizecolumnset",
+ actions = columnsets.setvsize,
+ arguments = { "string" },
+}
+
+interfaces.implement {
+ name = "sethsizecolumnset",
+ actions = columnsets.sethsize,
+ arguments = { "string" },
+}
+
+interfaces.implement {
+ name = "sethsizecolumnspan",
+ actions = columnsets.sethspan,
+ arguments = { "string" ,"integer" },
+}
+
+interfaces.implement {
+ name = "flushcolumnsetrest",
+ actions = columnsets.flushrest,
+ arguments = { "string", "integer" },
+}
+
+interfaces.implement {
+ name = "blockcolumnset",
+ actions = columnsets.block,
+ arguments = { {
+ { "name", "string" },
+ { "c", "integer" },
+ { "r", "integer" },
+ { "nc", "integer" },
+ { "nr", "integer" },
+ { "box", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "checkcolumnset",
+ actions = columnsets.check,
+ arguments = { {
+ { "name", "string" },
+ { "method", "string" },
+ { "c", "integer" },
+ { "r", "integer" },
+ { "box", "integer" },
+ { "width", "dimension" },
+ { "height", "dimension" },
+ { "option", "string" },
+ } }
+}
+
+interfaces.implement {
+ name = "putincolumnset",
+ actions = columnsets.put,
+ arguments = { {
+ { "name", "string" },
+ { "c", "integer" },
+ { "r", "integer" },
+ { "box", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "addtocolumnset",
+ actions = columnsets.add,
+ arguments = { "string", "integer" },
+}
+
+interfaces.implement {
+ name = "setcolumnsetlines",
+ actions = columnsets.setlines,
+ arguments = { {
+ { "name", "string" },
+ { "page", "integer" },
+ { "column", "integer" },
+ { "value", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "setcolumnsetstart",
+ actions = columnsets.setstart,
+ arguments = { {
+ { "name", "string" },
+ { "page", "integer" },
+ { "column", "integer" },
+ { "value", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "setcolumnsetproperties",
+ actions = columnsets.setproperties,
+ arguments = { {
+ { "name", "string" },
+ { "column", "integer" },
+ { "distance", "dimension" },
+ { "width", "dimension" },
+ } }
+}
+
+interfaces.implement {
+ name = "registercolumnsetarea",
+ actions = columnsets.registerarea,
+ arguments = { {
+ { "name", "string" },
+ { "type", "string" },
+ { "page", "integer" },
+ { "state", "string" },
+ { "c", "integer" },
+ { "r", "integer" },
+ { "nc", "integer" },
+ { "nr", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "flushcolumnsetareas",
+ actions = columnsets.flushareas,
+ arguments = "string",
+}
+
+interfaces.implement {
+ name = "setcolumnsetarea",
+ actions = columnsets.setarea,
+ arguments = { {
+ { "name", "string" },
+ { "c", "integer" },
+ { "r", "integer" },
+ { "box", "integer" },
+ } }
+}
+
+interfaces.implement {
+ name = "columnsetgoto",
+ actions = columnsets["goto"],
+ arguments = { "string" , "string" },
+}
+
+interfaces.implement {
+ name = "columnsetnoto",
+ actions = columnsets["noto"],
+}
+
+interfaces.implement {
+ name = "columnsetcurrentcolumn",
+ actions = columnsets.currentcolumn,
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv
new file mode 100644
index 00000000000..4559ec33fdf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv
@@ -0,0 +1,778 @@
+%D \module
+%D [ file=page-cst,
+%D version=2016.12.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Grids (aka Column Sets),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo : markings per column
+
+%D This module is work in progress and in due time it will replace
+%D columnsets.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Grids}
+
+\registerctxluafile{page-cst}{1.001}
+
+\unprotect
+
+% maybe some protected def ([esc])
+
+%D Columnsets are kind of special. They are mostly meant for special products with
+%D magazine like properties. They are normally not mixed with single column layouts
+%D and not all features of \CONTEXT\ might cooperate well with a mechanism like
+%D this. We use the name page grid because (as with other reimplementations of
+%D \MKII\ features in \MKIV, we need another namespace in order to migrate stepwise.
+%D
+%D This implementation is not neccessarily better than the previous one but it might
+%D be easier to extend it. It should be a bit more efficient.
+%D
+%D When writing this code I occasionally needed a motivational musical time||out and
+%D watching the latest Snarky Puppy DVD brought me the musically and visually videos
+%D of Jacob Collier (Piano, voice, anything) on YouTube (and yes, music keeps amazing
+%D me). It's definitely more fun to watch that than to write code like this.
+
+\definesystemconstant{pagegrid}
+
+\installcorenamespace{pagegrid}
+
+\installframedcommandhandler \??pagegrid {pagegrid} \??pagegrid
+
+\setuppagegrid
+ [\c!distance=1.5\bodyfontsize,
+ \c!n=\plustwo,
+ \c!nleft=\pagegridparameter\c!n,
+ \c!nright=\pagegridparameter\c!n,
+ %\c!align=, % inherit
+ %\c!separator=\v!none,
+ %\c!setups=,
+ \c!lines=\layoutparameter\c!lines,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!alternative=\v!local,
+ \c!width=\v!auto,
+ \c!page=,
+ \c!direction=\v!normal, % todo
+ \c!maxheight=\textheight,
+ \c!maxwidth=\makeupwidth]
+
+\appendtoks % could become an option
+ \setuevalue{\e!start\currentpagegrid}{\startpagegrid[\currentpagegrid]}%
+ \setuevalue{\e!stop \currentpagegrid}{\stoppagegrid}%
+ \clf_definecolumnset {
+ name {\currentpagegrid}%
+ }%
+\to \everydefinepagegrid
+
+\newdimen \d_page_grid_column_width
+\newdimen \d_page_grid_max_height
+\newdimen \d_page_grid_max_width
+\newdimen \d_page_grid_distance
+
+\newdimen \d_page_grid_reserved_height
+\newdimen \d_page_grid_reserved_width
+\newcount \c_page_grid_reserved_state
+
+\newdimen \d_page_grid_gap_height
+
+\newcount \c_page_grid_n_of_left
+\newcount \c_page_grid_n_of_right
+\newcount \c_page_grid_n_of_rows
+\newcount \c_page_grid_first_column
+\newcount \c_page_grid_last_column
+
+\newbox \b_page_grid_collected
+\newbox \b_page_grid_column_rest
+\newbox \b_page_grid_column
+
+\unexpanded\def\setuppagegridlines{\doquadrupleempty\page_grid_setup_lines}
+\unexpanded\def\setuppagegridstart{\doquadrupleempty\page_grid_setup_start}
+
+\def\page_grid_setup_lines[#1][#2][#3][#4]% id page col value
+ {\clf_setcolumnsetlines{name {#1} page #2 column #3 value #4}}
+
+\def\page_grid_setup_start[#1][#2][#3][#4]% id page col value
+ {\clf_setcolumnsetstart{name {#1} page #2 column #3 value #4}}
+
+\unexpanded\def\page_grid_check
+ {\dorecurse{\numexpr\pagegridparameter\c!nleft+\pagegridparameter\c!nright}
+ {\page_grid_check_column{##1}}}
+
+\unexpanded\def\page_grid_check_column#1%
+ {\chaintocurrentpagegrid{\currentpagegrid:#1}%
+ \edef\p_distance{\namedpagegridparameter{\currentpagegrid:#1}\c!distance}%
+ \edef\p_width {\namedpagegridparameter{\currentpagegrid:#1}\c!width}%
+ \clf_setcolumnsetproperties {%
+ name {\currentpagegrid}
+ column \numexpr#1\relax
+ \ifx\p_distance\empty\else
+ distance \p_distance
+ \fi
+ \ifx\p_width\empty\else\ifx\p_width\v!auto\else
+ width \p_width
+ \fi\fi
+ }}
+
+\appendtoks
+ \dorecurse{\numexpr\pagegridparameter\c!nleft+\pagegridparameter\c!nright}
+ {\chaintocurrentpagegrid{\currentpagegrid:#1}}%
+\to \everydefinepagegrid
+
+\unexpanded\def\startpagegrid
+ {\bgroup
+ \dodoubleempty\page_grid_start}
+
+\def\page_grid_start_dummy[#1][#2]%
+ {\let\page_grid_stop\egroup}
+
+\def\page_grid_start[#1][#2]%
+ {\let\page_grid_start\page_grid_start_dummy
+ \ifsecondargument
+ \edef\currentpagegrid{#1}%
+ \setupcurrentpagegrid[#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\let\currentpagegrid\empty
+ \setupcurrentpagegrid[#1]}%
+ {\def\currentpagegrid{#1}}%
+ \else
+ \let\currentpagegrid\empty
+ \fi\fi
+ \usepageparameter\pagegridparameter
+ \c_page_grid_n_of_left \pagegridparameter\c!nleft\relax
+ \c_page_grid_n_of_right\pagegridparameter\c!nright\relax
+ \c_page_grid_n_of_rows \pagegridparameter\c!lines\relax
+ \d_page_grid_max_width \pagegridparameter\c!maxwidth\relax
+ \d_page_grid_max_height\pagegridparameter\c!maxheight\relax
+ \d_page_grid_distance \pagegridparameter\c!distance\relax
+ %
+ \ifcase\c_page_grid_n_of_rows
+ \getrawnoflines{\dimexpr\d_page_grid_max_height-\strutheight+\topskip\relax}%
+ \c_page_grid_n_of_rows\noflines
+ \fi
+ \edef\p_width{\pagegridparameter\c!width}%
+ \insidecolumnstrue % will be different flag in addition
+ \clf_resetcolumnset {
+ name {\currentpagegrid}
+ nofrows \c_page_grid_n_of_rows
+ nofleft \c_page_grid_n_of_left
+ nofright \c_page_grid_n_of_right
+ lineheight \strutht
+ linedepth \strutdp
+ \ifx\p_width\v!auto
+ % sets \d_page_grid_column_width
+ \else
+ width \p_width
+ \fi
+ distance \d_page_grid_distance
+ maxwidth \d_page_grid_max_width
+ }%
+ %
+ \page_grid_check
+ %
+ \clf_flushcolumnsetareas{\currentpagegrid}\relax
+ \setupoutputroutine[\s!pagegrid]%
+ \page_grid_command_set_hsize
+ \page_grid_command_set_vsize
+ }%\begingroup}
+
+\unexpanded\def\stoppagegrid
+ {\page_grid_stop}
+
+\def\page_grid_stop
+ {\endgraf % needed, else wrong vsize in one par case
+ \vfill % otherwise weird \placenotes[endnotes]
+ \page_otr_command_set_vsize % needed
+ \penalty\c_page_otr_eject_penalty
+ \page_grid_command_flush_page
+ \page_otr_fill_and_eject_page
+ \page_otr_command_set_vsize % needed
+ \egroup
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize}
+
+\unexpanded\def\reservepagegrid[#1]%
+ {\begingroup
+ \letdummyparameter\c!c\plusone
+ \letdummyparameter\c!r\plusone
+ \letdummyparameter\c!nc\plusone
+ \letdummyparameter\c!nr\plusone
+ \getdummyparameters[#1]%
+ \clf_blockcolumnset {
+ name {\currentpagegrid}
+ c \dummyparameter\c!c
+ r \dummyparameter\c!r
+ nc \dummyparameter\c!nc
+ nr \dummyparameter\c!nr
+ }%
+ \endgroup}
+
+\unexpanded\def\setpagegrid
+ {\dosingleempty\page_grid_set}
+
+\unexpanded\def\page_grid_set[#1]%
+ {\begingroup
+ \letdummyparameter\c!c\zerocount
+ \letdummyparameter\c!r\zerocount
+ \letdummyparameter\c!option\v!none
+ \getdummyparameters[#1]%
+ \dowithnextboxcs\page_grid_set_indeed\hbox}
+
+\def\page_grid_set_indeed
+ {\clf_checkcolumnset {
+ name {\currentpagegrid}
+ c \dummyparameter\c!c
+ r \dummyparameter\c!r
+ box \nextbox
+ option {\dummyparameter\c!option}
+ }%
+ \ifcase\c_page_grid_reserved_state
+ \setbox\nextbox\vpack to \d_page_grid_reserved_height \bgroup
+ \vss
+ \hpack to \d_page_grid_reserved_width \bgroup
+ \box\nextbox
+ \hss
+ \egroup
+ \vss
+ \egroup
+ \wd\nextbox\d_page_grid_reserved_width
+ \clf_putincolumnset {
+ name {\currentpagegrid}
+ box \nextbox
+ }%
+ \fi
+ \endgroup}
+
+\unexpanded\def\page_grid_command_set_vsize
+ {\clf_setvsizecolumnset{\currentpagegrid}%
+ \ifdim\d_page_grid_gap_height<\lineheight
+ \page_grid_command_flush_page
+ \page_otr_fill_and_eject_page
+ \fi
+ \global\vsize\d_page_grid_gap_height
+ \pagegoal\vsize}
+
+\unexpanded\def\page_grid_command_set_hsize
+ {\clf_sethsizecolumnset{\currentpagegrid}%
+ \hsize\d_page_grid_column_width
+ \textwidth\d_page_grid_column_width}
+
+\unexpanded\def\page_grid_command_routine
+ {\ifvoid\normalpagebox \else
+ \clf_addtocolumnset{\currentpagegrid}\normalpagebox
+ \fi
+ \page_grid_command_set_vsize
+ \page_grid_command_flush_saved_floats
+ \page_grid_command_set_vsize
+ \ifdim\d_page_grid_gap_height<\lineheight
+ \page_grid_command_flush_page
+ \fi
+ \page_grid_command_set_vsize
+ \clf_flushcolumnsetrest {\currentpagegrid}\normalpagebox
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \fi}
+
+\installoutputroutine\synchronizepagegrid
+ {\ifvoid\normalpagebox\else
+ \clf_addtocolumnset{\currentpagegrid}\normalpagebox
+ \page_grid_command_set_vsize
+ \clf_flushcolumnsetrest{\currentpagegrid}\normalpagebox
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \fi
+ \fi}
+
+% todo line numbers and marks
+
+\unexpanded\def\page_grid_command_flush_page_column#1%
+ {\scratchcounter#1\relax
+ \clf_flushcolumnsetcolumn{\currentpagegrid}\scratchcounter
+ \anch_mark_column_box\b_page_grid_column
+ \page_marks_synchronize_column\c_page_grid_first_column\c_page_grid_last_column\scratchcounter\b_page_grid_column
+ \ifnum\scratchcounter>\c_page_grid_n_of_left
+ \advance\scratchcounter-\c_page_grid_n_of_left
+ \page_lines_add_numbers_to_box\b_page_grid_column\scratchcounter\c_page_grid_n_of_right\plustwo
+ \else
+ \page_lines_add_numbers_to_box\b_page_grid_column\scratchcounter\c_page_grid_n_of_left\plustwo
+ \fi
+ \begingroup
+ \edef\currentpagegrid{\currentpagegrid:#1}%
+ \inheritedpagegridframedbox\box\b_page_grid_column
+ \endgroup}
+
+\unexpanded\def\page_grid_command_flush_page
+ {\deactivatecolor % puzzling, try ungrouped color \red or so
+ \setbox\b_page_grid_collected\hpack\bgroup
+ \clf_preparecolumnsetflush{\currentpagegrid}%
+ \letpagegridparameter\c!region\currentpagegrid
+ \doifelse{\pagegridparameter\c!direction}\v!reverse
+ {\dostepwiserecurse\c_page_grid_last_column\c_page_grid_first_column\minusone
+ {\page_grid_command_flush_page_column{##1}%
+ \ifnum##1>\plusone
+ \kern\namedpagegridparameter{\currentpagegrid:##1}\c!distance\relax
+ \fi}}%
+ {\dostepwiserecurse\c_page_grid_first_column\c_page_grid_last_column\plusone
+ {\page_grid_command_flush_page_column{##1}%
+ \ifnum##1<\c_page_grid_last_column
+ \kern\namedpagegridparameter{\currentpagegrid:##1}\c!distance\relax
+ \fi}}%
+ \clf_finishcolumnsetflush{\currentpagegrid}%
+ \egroup
+ \page_otr_construct_and_shipout\box\b_page_grid_collected
+ \clf_flushcolumnsetareas{\currentpagegrid}\relax
+ \page_grid_command_flush_saved_floats}
+
+% slow but robust
+
+\unexpanded\def\page_grid_command_next_progress
+ {\strut
+ \page_otr_flush_all_floats
+ \page_otr_eject_page
+ \ifcase\clf_columnsetnoto\else
+ \expandafter\page_grid_command_next_progress
+ \fi}
+
+\unexpanded\def\page_grid_command_handle_column
+ {\ifcase\clf_columnsetgoto{\currentpagegrid}{\page_breaks_columns_current_option}\relax\else
+ \expandafter\page_grid_command_next_progress
+ \fi}
+
+\installcolumnbreakmethod\s!pagegrid\s!unknown {\page_grid_command_handle_column}
+\installcolumnbreakmethod\s!pagegrid\v!yes {\page_grid_command_handle_column}
+
+\unexpanded\def\page_grid_command_next_page
+ {\ifcase\clf_columnsetgoto{\currentpagegrid}{\v!page}\relax\else
+ \page_grid_command_flush_page
+ \fi}
+
+\unexpanded\def\page_grid_command_next_page_and_inserts
+% {\page_otr_eject_page_and_flush_inserts}
+ {\page_otr_flush_all_floats
+ \page_grid_command_next_page}
+
+\let\page_grid_command_package_contents\page_one_command_package_contents
+
+\unexpanded\def\page_grid_command_flush_saved_floats
+ {\ifconditional\c_page_floats_flushing \else
+ \ifconditional\c_page_floats_some_waiting
+ \page_grid_command_flush_saved_floats_indeed
+ \fi
+ \fi}
+
+\unexpanded\def\page_grid_command_flush_saved_floats_indeed
+ {\page_floats_flush\s!text\plusone
+ \clf_checkcolumnset {
+ name {\currentpagegrid}
+ method {\floatmethod}
+ width \wd\floatbox
+ height \ht\floatbox
+ }%
+ \ifcase\c_page_grid_reserved_state
+ \page_grid_place_float_here_indeed
+ \page_grid_command_set_vsize % needed
+ \ifconditional\c_page_floats_some_waiting
+ \doubleexpandafter\page_grid_command_flush_saved_floats_indeed
+ \fi
+ \else
+ \page_floats_resave\s!text
+ \fi}
+
+% needs checking
+
+\unexpanded\def\page_grid_command_flush_floats
+ {\wait\global\settrue\c_page_floats_flushing
+ \ifconditional\c_page_floats_some_waiting
+ \par
+ \page_grid_command_flush_floats_indeed
+ \fi
+ \global\savednoffloats\zerocount
+ \global\setfalse\c_page_floats_some_waiting
+ \global\setfalse\c_page_floats_flushing}
+
+\def\page_grid_command_flush_floats_indeed % much in common with OTRSET
+ {\wait\ifconditional\c_page_floats_some_waiting
+ \ifconditional\c_page_floats_pack_flushed
+ \setfalse\c_page_floats_center_box % not needed as we do call directly
+ \page_floats_collect\s!text\hsize\emwidth
+ \global\setbox\floatbox\hbox to \hsize
+ {\hfil
+ \dorecurse\nofcollectedfloats
+ {\ifcase\columndirection % nog document wide
+ \page_floats_flush\s!text\plusone
+ \else
+ \page_floats_flush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
+ \fi
+ \ifdim\wd\floatbox>\makeupwidth % \hsize
+ \hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \else
+ \box\floatbox
+ \fi
+ \ifnum\recurselevel<\nofcollectedfloats
+ \hfil
+ \fi}%
+ \hfil}%
+ \else
+ \page_floats_get
+ \fi
+ \doplacefloatbox
+ \expandafter\page_grid_command_flush_floats_indeed
+ \fi}
+
+% so far
+
+\unexpanded\def\page_grid_command_check_if_float_fits
+ {\clf_checkcolumnset {
+ name {\currentpagegrid}
+ method {\floatmethod}
+ % c \zerocount
+ % r \zerocount
+ box \floatbox
+ }%
+ \ifcase\c_page_grid_reserved_state
+ \global\settrue\c_page_floats_room
+ \else
+ \global\setfalse\c_page_floats_room
+ \fi}
+
+\unexpanded\def\page_grid_place_float_here_indeed
+ {\setbox\floatbox\vpack to \d_page_grid_reserved_height \bgroup
+ \vss
+ \hpack to \d_page_grid_reserved_width \bgroup
+ % \hss % no
+ \box\floatbox
+ \hss
+ \egroup
+ \vss
+ \egroup
+ \clf_putincolumnset {
+ name {\currentpagegrid}
+ box \floatbox
+ }}
+
+\def\page_grid_place_float_slot
+ {% safeguard
+ \ifx\floatmethod\empty
+ \let\floatmethod\v!here
+ \fi
+ % synchronize
+ \penalty\c_page_otr_eject_penalty
+ % push
+ \setbox\savedfloatbox\box\floatbox
+ \page_grid_command_flush_saved_floats
+ \setbox\floatbox\box\savedfloatbox
+ % pop
+ \ifconditional\c_page_floats_some_waiting
+ \page_floats_save\s!text
+ \nonoindentation
+ \else
+ \clf_checkcolumnset {
+ name {\currentpagegrid}
+ method {\floatmethod}
+ \ifx\floatcolumn\empty \else
+ c \floatcolumn
+ \fi
+ \ifx\floatrow\empty \else
+ r \floatrow
+ \fi
+ box \floatbox
+ }%
+ \ifcase\c_page_grid_reserved_state
+ \page_grid_place_float_here_indeed
+ \else
+ \page_floats_save\s!text
+ \nonoindentation
+ \fi
+ \fi}
+
+\def\page_grid_place_float_fixed % todo: fallback on here
+ {\ifx\floatcolumn\empty
+ \let\floatmethod\v!here
+ \else\ifx\floatrow\empty
+ \let\floatmethod\v!here
+ \else
+ \let\floatmethod\v!fixed
+ \fi\fi
+ \page_grid_place_float_slot}
+
+\def\page_grid_place_float_force
+ {% synchronize
+ \penalty\c_page_otr_eject_penalty
+ \clf_checkcolumnset {
+ name {\currentpagegrid}
+ method {\floatmethod}
+ box \floatbox
+ }%
+ \ifcase\c_page_grid_reserved_state
+ \page_grid_place_float_here_indeed
+ \else
+ \page_floats_save\s!text
+ \nonoindentation
+ \fi}
+
+\def\page_grid_place_float_page {\page_grid_place_float_slot} % todo: fallback on here
+
+\def\page_grid_place_float_here {\let\floatmethod\v!here\page_grid_place_float_slot}
+\def\page_grid_place_float_top {\page_grid_place_float_slot}
+\def\page_grid_place_float_bottom{\page_grid_place_float_slot}
+
+\installfloatmethod \s!pagegrid \v!here \page_grid_place_float_here
+\installfloatmethod \s!pagegrid \v!force \page_grid_place_float_force % todo
+%installfloatmethod \s!pagegrid \v!left
+%installfloatmethod \s!pagegrid \v!right
+%installfloatmethod \s!pagegrid \v!text
+\installfloatmethod \s!pagegrid \v!top \page_grid_place_float_top
+\installfloatmethod \s!pagegrid \v!bottom \page_grid_place_float_bottom
+%installfloatmethod \s!pagegrid \v!auto
+%installfloatmethod \s!pagegrid \v!margin
+%installfloatmethod \s!pagegrid \v!opposite
+\installfloatmethod \s!pagegrid \v!page \page_grid_place_float_page
+%installfloatmethod \s!pagegrid \v!leftpage
+%installfloatmethod \s!pagegrid \v!rightpage
+%installfloatmethod \s!pagegrid \v!inmargin
+%installfloatmethod \s!pagegrid \v!inleft
+%installfloatmethod \s!pagegrid \v!inright
+%installfloatmethod \s!pagegrid \v!leftmargin
+%installfloatmethod \s!pagegrid \v!rightmargin
+%installfloatmethod \s!pagegrid \v!leftedge
+%installfloatmethod \s!pagegrid \v!rightedge
+%installfloatmethod \s!pagegrid \v!somewhere
+%installfloatmethod \s!pagegrid \v!backspace
+%installfloatmethod \s!pagegrid \v!cutspace
+\installfloatmethod \s!pagegrid \s!tblr \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!lrtb \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!tbrl \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!rltb \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!fxtb \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!btlr \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!lrbt \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!btrl \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!rlbt \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!fxbt \page_grid_place_float_slot
+\installfloatmethod \s!pagegrid \s!fixd \page_grid_place_float_fixed
+
+%
+
+\unexpanded\def\page_grid_command_side_float_output
+ {} % nothing, reset anyway
+
+\unexpanded\def\page_grid_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_grid_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_grid_command_synchronize_hsize
+ {\page_grid_command_set_hsize}
+
+\defineoutputroutine
+ [\s!pagegrid]
+ [\s!page_otr_command_routine =\page_grid_command_routine,
+ \s!page_otr_command_package_contents =\page_grid_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_grid_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_grid_command_set_hsize, % tricky, goes wrong
+ \s!page_otr_command_next_page =\page_grid_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_grid_command_next_page_and_inserts,
+ \s!page_otr_command_synchronize_hsize =\page_grid_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_grid_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_grid_command_set_bottom_insertions,
+ % \s!page_otr_command_flush_top_insertions =\page_grid_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions =\page_grid_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_grid_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_grid_command_check_if_float_fits,
+ % \s!page_otr_command_flush_float_box =\page_grid_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats =\page_grid_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_grid_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_grid_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_grid_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_grid_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_grid_command_flush_margin_blocks, % not used
+ ]
+
+% spans
+
+\installcorenamespace{pagegridspan}
+
+\installframedcommandhandler \??pagegridspan {pagegridspan} \??pagegridspan
+
+\setuppagegridspan
+ [\c!frame=\v!off,
+ \c!before=,
+ \c!after=,
+ \c!offset=\v!overlay,
+ \c!location=\v!left,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!n=\plustwo,
+ \c!nlines=\zerocount,
+ \c!align=\v!normal,
+ \c!width=\d_page_grid_span_width,
+ \c!indenting=,
+ \c!indentnext=\v!yes,
+ \c!default=\v!here,
+ \c!alternative=\v!a]
+
+\newdimen\d_page_grid_span_width
+
+\unexpanded\def\startpagegridspan
+ {\dotripleempty\page_grid_span_start}
+
+\def\page_grid_span_start[#1][#2][#3]% [#3] gobbles space
+ {\endgraf % else rubish output if forgotten
+ \synchronizepagegrid
+ \bgroup
+ \forgetall
+ \edef\currentpagegridspan{#1}%
+ \clf_sethsizecolumnspan{\currentpagegrid}\pagegridspanparameter\c!n\relax
+ \setbox\scratchbox\hbox\bgroup\inheritedpagegridspanframed\bgroup
+ \usepagegridspanstyleandcolor\c!style\c!color
+ \pagegridspanparameter\c!before
+ \ignorespaces}
+
+\unexpanded\def\stoppagegridspan
+ {\removeunwantedspaces
+ \par
+ \verticalstrut
+ \kern-2\struttotal
+ \verticalstrut
+ \endgraf
+ \pagegridspanparameter\c!after
+ \egroup\egroup
+ \setpagegrid{\box\scratchbox}%
+ % todo: push into slot
+ \egroup
+ \endgraf}
+
+\def\pagegridspanwidth#1% assumes equal distances
+ {\the\dimexpr
+ #1\d_page_grid_column_width
+ +#1\d_page_grid_distance
+ - \d_page_grid_distance
+ \relax}
+
+% areas
+
+\installcorenamespace{pagegridarea}
+
+\installframedcommandhandler \??pagegridarea {pagegridarea} \??pagegridarea
+
+\setuppagegridarea
+ [\c!x=\plusone,
+ \c!y=\plusone,
+ \c!nx=\plusone,
+ \c!ny=\plusone,
+ \c!clipoffset=2\lineheight,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!offset=\v!overlay,
+ \c!strut=\v!no,
+ \c!frame=\v!off,
+ %\c!type=\v!next,
+ \c!align=\v!normal,
+ \c!page=\plusone,
+ \c!state=\v!stop]
+
+% type: both fixed left right next (not now), then better
+% lefttext and righttext or so
+
+\appendtoks
+ % \edef\p_type{}%
+ % \ifx\p_type\v!next
+ % \doifelseoddpage
+ % {\letpagegridareaparameter\c!type\v!right}%
+ % {\letpagegridareaparameter\c!type\v!left}%
+ % \fi
+ \clf_registercolumnsetarea {
+ name {\currentpagegridarea}
+ % type {\p_type}
+ % page \pagegridareaparameter\c!page
+ state {\pagegridareaparameter\c!state}
+ c \pagegridareaparameter\c!x
+ r \pagegridareaparameter\c!y
+ nc \pagegridareaparameter\c!nx
+ nr \pagegridareaparameter\c!ny
+ }%
+\to \everydefinepagegridarea
+
+\unexpanded\def\setuppagegridareatext
+ {\dodoubleargument\page_grid_set_area_text}
+
+\def\page_grid_set_area_text[#1][#2]%
+ {\edef\currentpagegridarea{#1}%
+ \setpagegridareaparameter\c!text{#2}}
+
+% maybe move the left/right correction to the tex end or the offset to lua
+
+\unexpanded\def\page_grid_set_area#1#2#3#4#5#6#7#8% can be optimized
+ {\begingroup
+ \edef\currentpagegridarea{#2}%
+ \setpagegridareaparameter\c!width {#5\scaledpoint}%
+ \setpagegridareaparameter\c!height{#6\scaledpoint}%
+ \setbox\nextbox\hpack\bgroup\inheritedpagegridareaframed\bgroup
+ \usepagegridareastyleandcolor\c!style\c!color
+ \ignorespaces
+ \pagegridareaparameter\c!text
+ \egroup\egroup
+ %
+ \scratchdimen#8\scaledpoint
+ \ifdim\scratchdimen>\zeropoint
+ \setbox\scratchbox\vbox\bgroup
+ \clip
+ [ \c!offset=\pagegridareaparameter\c!clipoffset,%
+ \c!rightoffset=\pagegridareaparameter\c!rightoffset,%
+ \c!width=\scratchdimen,%
+ % \c!height=
+ ]%
+ {\copy\nextbox}%
+ \egroup
+ \clf_setcolumnsetarea{name {#1} box \scratchbox c #3 r #4}%
+ \setbox\scratchbox\vbox\bgroup
+ \hskip-\layoutparameter\c!backspace % todo: #9
+ \clip
+ [ \c!offset=\pagegridareaparameter\c!clipoffset,%
+ \c!leftoffset=\pagegridareaparameter\c!rightoffset,%
+ \c!hoffset=\scratchdimen,%
+ \c!width=\dimexpr\wd\nextbox-\scratchdimen\relax,%
+ % \c!height=
+ ]%
+ {\box\nextbox}%
+ \egroup
+ \clf_setcolumnsetarea{name {#1} box \scratchbox c #7 r #4}%
+ \else
+ \setbox\scratchbox\vbox\bgroup
+ \box\nextbox % wrapping needed
+ \egroup
+ \clf_setcolumnsetarea{name {#1} box \scratchbox c #3 r #4}%
+ \fi
+ \endgroup}
+
+\let\setpagegridarea\page_grid_set_area
+
+% state start | repeat
+
+% for now (transition)
+
+\let\definecolumnset \definepagegrid
+\let\setupcolumnset \setuppagegrid
+\let\setupcolumnsetlines \setuppagegridlines
+\let\setupcolumnsetstart \setuppagegridstart
+\let\startcolumnset \startpagegrid
+\let\stopcolumnset \stoppagegrid
+\let\definecolumnsetspan \definepagegridspan
+\let\setupcolumnsetspan \setuppagegridspan
+\let\startcolumnsetspan \startpagegridspan
+\let\stopcolumnsetspan \stoppagegridspan
+\let\columnsetspanwidth \pagegridspanwidth
+\let\definecolumnsetarea \definepagegridarea
+\let\setupcolumnsetarea \setuppagegridarea
+\let\setupcolumnsetareatext\setuppagegridareatext
+
+\protect
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-fac.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-fac.mkiv
new file mode 100644
index 00000000000..88789abe9fb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-fac.mkiv
@@ -0,0 +1,87 @@
+%D \module
+%D [ file=page-fac, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Facing Pages,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Facing Pages}
+
+\unprotect
+
+%D \macros
+%D {setupoppositeplacing,startopposite}
+%D
+%D \starttyping
+%D \starttext
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D \stoptext
+%D \stoptyping
+
+\newbox \b_page_facings_content
+\newconditional\c_page_facings_busy
+
+\installcorenamespace{oppositeplacing}
+
+\installsetuponlycommandhandler \??oppositeplacing {oppositeplacing}
+
+\unexpanded\def\startopposite
+ {\dowithnextboxcontent
+ {\hsize\makeupwidth}%
+ {\global\setbox\b_page_facings_content\vbox
+ {\ifvoid\b_page_facings_content
+ \directoppositeplacingparameter\c!before
+ \else
+ \directoppositeplacingparameter\c!inbetween
+ \unvbox\b_page_facings_content
+ \fi
+ \box\nextbox}}%
+ \vbox\bgroup}
+
+\unexpanded\def\stopopposite
+ {\egroup}
+
+\def\page_facings_finish
+ {\ifvoid\b_page_facings_content \else
+ \global\setbox\b_page_facings_content\vbox to \makeupheight
+ {\unvbox\b_page_facings_content
+ \directoppositeplacingparameter\c!after
+ \vss}%
+ \fi}
+
+\def\page_facings_flush
+ {\ifconditional\c_page_facings_busy
+ \ifvoid\b_page_facings_content \else
+ \page_facings_flush_indeed
+ \fi
+ \fi}
+
+\def\page_facings_flush_indeed
+ {\ifnum\realpageno>\plusone
+ \begingroup
+ \pageornamentstate\plusone % tricky
+ \page_facings_finish
+ \page_boxes_shipout{\page_boxes_constructed_page\box\b_page_facings_content}%
+ \endgroup
+ \else
+ \global\setbox\b_page_facings_content\emptybox
+ \fi}
+
+\appendtoks
+ \doifelse{\directoppositeplacingparameter\c!state}\v!start\settrue\setfalse\c_page_facings_busy
+\to \everysetupoppositeplacing
+
+\setupoppositeplacing
+ [\c!state=\v!start,
+ \c!before=,
+ \c!inbetween=\blank,
+ \c!after=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua b/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua
new file mode 100644
index 00000000000..caa8d490d19
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua
@@ -0,0 +1,383 @@
+if not modules then modules = { } end modules ['page-flt'] = {
+ version = 1.001,
+ comment = "companion to page-flt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- floats -> managers.floats
+-- some functions are a tex/lua mix so we need a separation
+
+local insert, remove = table.insert, table.remove
+local find = string.find
+
+local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change
+
+local report_floats = logs.reporter("structure","floats")
+
+local C, S, P, lpegmatch = lpeg.C, lpeg.S, lpeg.P, lpeg.match
+
+-- we use floatbox, floatwidth, floatheight
+-- text page leftpage rightpage (todo: top, bottom, margin, order)
+
+local flush_node_list = node.flush_list
+
+local setdimen = tex.setdimen
+local setcount = tex.setcount
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+local textakebox = nodes.takebox
+
+floats = floats or { }
+local floats = floats
+
+local context = context
+local commands = commands
+local interfaces = interfaces
+local showmessage = interfaces.showmessage
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+
+local noffloats = 0
+local last = nil
+local default = "text"
+local pushed = { }
+
+local function initialize()
+ return {
+ text = { },
+ page = { },
+ leftpage = { },
+ rightpage = { },
+ somewhere = { },
+ }
+end
+
+local stacks = initialize()
+
+-- list location
+
+function floats.stacked(which) -- floats.thenofstacked
+ return #stacks[which or default]
+end
+
+function floats.push()
+ insert(pushed,stacks)
+ stacks = initialize()
+ setcount("global","savednoffloats",0)
+end
+
+function floats.pop()
+ local popped = remove(pushed)
+ if popped then
+ for which, stack in next, stacks do
+ for i=1,#stack do
+ insert(popped[which],stack[i])
+ end
+ end
+ stacks = popped
+ setcount("global","savednoffloats",#stacks[default])
+ end
+end
+
+local function setdimensions(b)
+ local w, h, d = 0, 0, 0
+ if b then
+ w, h, d = b.width, b.height, b.depth
+ end
+ setdimen("global","floatwidth", w)
+ setdimen("global","floatheight", h+d)
+ return w, h, d
+end
+
+local function get(stack,n,bylabel)
+ if bylabel then
+ for i=1,#stack do
+ local s = stack[i]
+ local n = string.topattern(tostring(n)) -- to be sure
+ if find(s.data.label,n) then
+ return s, s.box, i
+ end
+ end
+ else
+ n = n or #stack
+ if n > 0 then
+ local t = stack[n]
+ if t then
+ return t, t.box, n
+ end
+ end
+ end
+end
+
+function floats.save(which,data)
+ which = which or default
+ local b = textakebox("floatbox")
+ if b then
+ local stack = stacks[which]
+ noffloats = noffloats + 1
+ local t = {
+ n = noffloats,
+ data = data or { },
+ box = b,
+ }
+ insert(stack,t)
+-- inspect(stacks)
+ setcount("global","savednoffloats",#stacks[default])
+ if trace_floats then
+ report_floats("%s, category %a, number %a, slot %a, width %p, height %p, depth %p","saving",
+ which,noffloats,#stack,b.width,b.height,b.depth)
+ else
+ showmessage("floatblocks",2,noffloats)
+ end
+ else
+ report_floats("ignoring empty, category %a, number %a",which,noffloats)
+ end
+end
+
+function floats.resave(which)
+ if last then
+ which = which or default
+ local stack = stacks[which]
+ local b = textakebox("floatbox")
+ last.box = b
+ insert(stack,1,last)
+-- inspect(stacks)
+ setcount("global","savednoffloats",#stacks[default])
+ if trace_floats then
+ report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","resaving",
+ which,noffloats,#stack,b.width,b.height,b.depth)
+ else
+ showmessage("floatblocks",2,noffloats)
+ end
+ else
+ report_floats("unable to resave float")
+ end
+end
+
+function floats.flush(which,n,bylabel)
+ which = which or default
+-- inspect(stacks)
+ local stack = stacks[which]
+ local t, b, n = get(stack,n or 1,bylabel)
+ if t then
+ if not b then
+ showmessage("floatblocks",1,t.n)
+ end
+ if trace_floats then
+ local w, h, d = setdimensions(b) -- ?
+ report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","flushing",
+ which,t.n,n,w,h,d)
+ else
+ showmessage("floatblocks",3,t.n)
+ end
+ texsetbox("floatbox",b)
+ last = remove(stack,n)
+ last.box = nil
+ setcount("global","savednoffloats",#stacks[default]) -- default?
+ else
+ setdimensions()
+ end
+end
+
+function floats.consult(which,n)
+ which = which or default
+ local stack = stacks[which]
+ local t, b, n = get(stack,n)
+ if t then
+ local w, h, d = setdimensions(b)
+ if trace_floats then
+ report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","consulting",
+ which,t.n,n,w,h,d)
+ end
+ return t, b, n
+ else
+ if trace_floats then
+ report_floats("nothing to consult")
+ end
+ setdimensions()
+ end
+end
+
+function floats.collect(which,maxwidth,distance)
+ which = which or default
+ local stack = stacks[which]
+ local n, m = #stack, 0
+ for i=1,n do
+ local t, b, n = get(stack,i)
+ if t then
+ local w, h, d = setdimensions(b)
+ if w + distance < maxwidth then
+ m = m + 1
+ maxwidth = maxwidth - w - distance
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if m == 0 then
+ m = 1
+ end
+ setcount("global","nofcollectedfloats",m)
+end
+
+function floats.getvariable(name,default)
+ local value = last and last.data[name] or default
+ return value ~= "" and value
+end
+
+function floats.checkedpagefloat(packed)
+ if structures.pages.is_odd() then
+ if #stacks.rightpage > 0 then
+ return "rightpage"
+ elseif #stacks.page > 0 then
+ return "page"
+ elseif #stacks.leftpage > 0 then
+ if packed then
+ return "leftpage"
+ end
+ end
+ else
+ if #stacks.leftpage > 0 then
+ return "leftpage"
+ elseif #stacks.page > 0 then
+ return "page"
+ elseif #stacks.rightpage > 0 then
+ if packed then
+ return "rightpage"
+ end
+ end
+ end
+end
+
+function floats.nofstacked(which)
+ return #stacks[which or default] or 0
+end
+
+function floats.hasstacked(which)
+ return (#stacks[which or default] or 0) > 0
+end
+
+-- todo: check for digits !
+
+local method = C((1-S(", :"))^1)
+local position = P(":") * C((1-S("*,"))^1) * (P("*") * C((1-S(","))^1))^0
+local label = P(":") * C((1-S(",*: "))^0)
+
+local pattern = method * (
+ label * position * C("")
+ + C("") * position * C("")
+ + label * C("") * C("")
+ + C("") * C("") * C("")
+) + C("") * C("") * C("") * C("")
+
+-- inspect { lpegmatch(pattern,"somewhere:blabla,crap") }
+-- inspect { lpegmatch(pattern,"somewhere:1*2") }
+-- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") }
+-- inspect { lpegmatch(pattern,"somewhere::1*2") }
+-- inspect { lpegmatch(pattern,"somewhere,") }
+-- inspect { lpegmatch(pattern,"somewhere") }
+-- inspect { lpegmatch(pattern,"") }
+
+function floats.analysemethod(str) -- will become a more extensive parser
+ return lpegmatch(pattern,str or "")
+end
+
+-- interface
+
+implement {
+ name = "flushfloat",
+ actions = floats.flush,
+ arguments = { "string", "integer" },
+}
+
+implement {
+ name = "flushlabeledfloat",
+ actions = floats.flush,
+ arguments = { "string", "string", true },
+}
+
+implement {
+ name = "savefloat",
+ actions = floats.save,
+ arguments = "string"
+}
+
+implement {
+ name = "savespecificfloat",
+ actions = floats.save,
+ arguments = {
+ "string",
+ {
+ { "specification" },
+ { "label" },
+ }
+ }
+}
+
+implement {
+ name = "resavefloat",
+ actions = floats.resave,
+ arguments = "string"
+}
+
+implement {
+ name = "pushfloat",
+ actions = floats.push
+}
+
+implement {
+ name = "popfloat",
+ actions = floats.pop
+}
+
+implement {
+ name = "consultfloat",
+ actions = floats.consult,
+ arguments = "string",
+}
+
+implement {
+ name = "collectfloat",
+ actions = floats.collect,
+ arguments = { "string", "dimen", "dimen" }
+}
+
+implement {
+ name = "getfloatvariable",
+ actions = { floats.getvariable, context },
+ arguments = "string"
+}
+
+implement {
+ name = "checkedpagefloat",
+ actions = { floats.checkedpagefloat, context },
+ arguments = "string"
+}
+
+implement {
+ name = "nofstackedfloats",
+ actions = { floats.nofstacked, context },
+ arguments = "string"
+}
+
+implement {
+ name = "doifelsestackedfloats",
+ actions = { floats.hasstacked, commands.doifelse },
+ arguments = "string"
+}
+
+implement {
+ name = "analysefloatmethod",
+ actions = function(str)
+ local method, label, column, row = floats.analysemethod(str)
+ setmacro("floatmethod",method or "")
+ setmacro("floatlabel", label or "")
+ setmacro("floatrow", row or "")
+ setmacro("floatcolumn",column or "")
+ end,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv
new file mode 100644
index 00000000000..c514496dfd4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv
@@ -0,0 +1,317 @@
+%D \module
+%D [ file=page-flt,
+%D version=2010.04.08,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Float Management,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Float Management}
+
+%D This module has code that previously was in other modules. There is
+%D also float related code in \type {strc-flt.mkiv}.
+
+\registerctxluafile{page-flt}{1.001}
+
+\unprotect
+
+\ifdefined\s!topfloat \else \def\s!topfloat {topfloat} \fi
+\ifdefined\s!bottomfloat \else \def\s!bottomfloat{bottomfloat} \fi
+
+\defineinsertion[\s!topfloat]
+\defineinsertion[\s!bottomfloat]
+
+\newdimen \d_page_floats_inserted_bottom
+\newdimen \d_page_floats_inserted_top
+\newcount \c_page_floats_n_of_top \c_page_floats_n_of_top \plustwo
+\newcount \c_page_floats_n_of_bottom \c_page_floats_n_of_bottom\zerocount
+
+\newconstant\c_page_floats_insertions_topskip_mode % 1 = no topskip
+
+%def\page_floats_report_saved {\showmessage\m!floatblocks2{\the\totalnoffloats}}
+\def\page_floats_report_total {\showmessage\m!floatblocks4{\the\totalnoffloats}}
+\def\page_floats_report_flushed{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}}
+
+%D Extra float registers.
+
+\newconditional\c_page_floats_room
+\newconditional\c_page_floats_some_waiting
+\newconditional\c_page_floats_not_permitted
+\newconditional\c_page_floats_flushing
+\newconditional\c_page_floats_center_box \settrue\c_page_floats_center_box
+\newconditional\c_page_floats_center_box_local
+\newconditional\c_page_floats_center_box_global
+\newconditional\c_page_floats_pack_flushed \settrue\c_page_floats_pack_flushed
+
+%D For the moment we keep this but they will become private too.
+
+\newcount\totalnoffloats % these will be redone ... handled at the lua end anyway
+\newcount\savednoffloats % these will be redone ... handled at the lua end anyway
+\newcount\nofcollectedfloats % communication channel
+
+\newcount\noffloatinserts % these will be redone ... handled at the lua end anyway
+
+\newbox \floattext
+
+\newdimen\floatwidth
+\newdimen\floatheight
+\newdimen\floatdepth
+\newdimen\floattextwidth
+\newdimen\floattextheight
+
+\newbox \floatbox
+\newbox \savedfloatbox
+
+%D From now on we manage the float stack at the \LUA\ end instead of packing
+%D them in a box and splitting off stacked floats. It's not so much less code
+%D but it's cleaner this way. It also opens op some posibilities as we can now
+%D more conveniently cary additional information around.
+
+\newtoks \everyfloatscheck
+
+\appendtoks
+ \ifcase\savednoffloats
+ \global\setfalse\c_page_floats_some_waiting
+ \else
+ \global\settrue\c_page_floats_some_waiting
+ \fi
+\to \everyfloatscheck
+
+\unexpanded\def\page_floats_flush#1#2%
+ {\clf_flushfloat{#1}#2\relax
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_flush_by_label#1#2%
+ {\clf_flushlabeledfloat{#1}{#2}\relax
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_save#1%
+ {\clf_savefloat{#1}\relax
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_resave#1%
+ {\clf_resavefloat{#1}\relax
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_push_saved
+ {\clf_pushfloat
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_pop_saved
+ {\clf_popfloat
+ \the\everyfloatscheck}
+
+\unexpanded\def\page_floats_get_info#1%
+ {\clf_consultfloat{#1}}
+
+\unexpanded\def\page_floats_if_else#1%
+ {\clf_doifelsestackedfloats{#1}}
+
+\unexpanded\def\page_floats_collect#1#2#3%
+ {\clf_collectfloat{#1}\dimexpr#2\relax\dimexpr#3\relax}
+
+\def\nofstackedfloatincategory#1%
+ {\clf_nofstackedfloats{#1}}
+
+\let\page_floats_column_push_saved\page_floats_push_saved % overloaded in page-mul
+\let\page_floats_column_pop_saved \page_floats_pop_saved % overloaded in page-mul
+
+\unexpanded\def\page_floats_save_page_float#1#2%
+ {\clf_savespecificfloat{#1}{specification{#2}}\relax}
+
+\unexpanded\def\page_floats_save_somewhere_float#1#2% #1=method
+ {\clf_savespecificfloat{#1}{specification{#2}label{\floatlabel}}\relax}
+
+%D This is an experimental new feature (for Alan Braslau), a prelude to more:
+%D
+%D \starttyping
+%D test \placefigure{}{}
+%D test \placefigure[somewhere:alpha][whatever]{}{}
+%D test \placefigure[somewhere:beta] [whatever]{}{}
+%D test \placefigure[somewhere:gamma][whatever]{}{}
+%D test \placefigure[somewhere:delta][whatever]{}{}
+%D test \placefigure{}{}
+%D
+%D in \in{figure}[whatever] bla bla
+%D
+%D \placenamedfloat[figure][*l*]
+%D \placenamedfloat[figure][gamma]
+%D \placenamedfloat[figure][beta]
+%D \stoptyping
+
+\unexpanded\def\placenamedfloat
+ {\dodoubleargument\page_floats_place_named}
+
+\def\page_floats_place_named[#1][#2]%
+ {\doloop
+ {\page_floats_flush_by_label\s!somewhere{#2}%
+ \ifvoid\floatbox
+ \exitloop
+ \else
+ \def\currentfloat{#1}%
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \box\floatbox
+ \blank[\rootfloatparameter\c!spaceafter]%
+ \fi}}
+
+% \setupcaption [figure] [align=flushleft]
+% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
+% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
+%
+% \startsetups somefigure
+% \ifdim\floatsetupwidth>\textwidth
+% \placesetupfloat[figure-2]
+% \else
+% \placesetupfloat[figure-1]
+% \fi
+% \stopsetups
+%
+% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}
+
+\unexpanded\def\placefloatwithsetups
+ {\dotripleempty\page_floats_place_with_setups}
+
+\def\page_floats_place_with_setups[#1][#2][#3]#4%
+ {\def\floatsetupcaption {#4}%
+ \def\floatsetupcontent {\copy\nextbox}%
+ \def\floatsetupwidth {\wd\nextbox}%
+ \def\floatsetupheight {\ht\nextbox}%
+ \def\placesetupfloat[##1]{\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (unexpanded)
+ \dowithnextbox{\setups[#1]}\vbox}
+
+%D The following code is in transition as we don't want to break the
+%D current single column, multi column, and columnset mechanism.
+%D
+%D First we reimplement some helpers.
+
+\unexpanded\def\page_floats_get
+ {\ifconditional\c_page_floats_some_waiting
+ \page_floats_flush\s!text\plusone
+ \ifconditional\c_page_floats_center_box
+ \ifdim\wd\globalscratchbox<\hsize
+ \global\setbox\floatbox\hpack to \hsize{\hss\box\floatbox\hss}%
+ \else
+ % retain special alignments
+ \ifinsidecolumns
+ \ifdim\wd\floatbox>\makeupwidth
+ \wd\floatbox\makeupwidth
+ \fi
+ \fi
+ \fi
+ \fi
+ \else
+ \global\savednoffloats\zerocount
+ \global\setbox\floatbox\emptybox
+ \fi}
+
+\unexpanded\def\page_floats_flush_saved
+ {\doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_floats_get
+ \doplacefloatbox
+ \else
+ \exitloop
+ \fi
+ \else
+ % \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit
+ % \page_otr_command_flush_margin_blocks
+ % \else
+ \exitloop
+ % \fi
+ \fi}}
+
+%D This is a future mechamism that will be integrated once we're sure about it:
+%D
+%D \starttyping
+%D \dorecurse{10}
+%D {\input thuan
+%D \placefigure{}{\framed[height=1.5cm]{test}}
+%D \placefloatplaceholder}
+%D \stoptyping
+
+\unexpanded\def\placefloatplaceholder
+ {\ifconditional\c_page_floats_room \else
+ \ifdim\dimexpr\pagegoal-\pagetotal-3\lineheight\relax>\zeropoint
+ \startlinecorrection[blank]
+ \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}%
+ \stoplinecorrection
+ \else
+ \allowbreak
+ \fi
+ \fi}
+
+\setuplabeltext
+ [placeholder={\Word{\lastplacedfloat}~, moved}]
+
+%D Page floats use different stacks.
+
+\newtoks\everybeforeflushedpagefloat
+
+\def\page_floats_flush_page_floats_indeed#1% future releases can do more clever things
+ {\page_floats_flush{#1}\plusone
+ \edef\floatspecification{\clf_getfloatvariable{specification}}% Is this okay?
+ \the\everybeforeflushedpagefloat
+ \vpack to \textheight
+ {\doifnotinset\v!high\floatspecification\vfill
+ \box\floatbox
+ \doifnotinset\v!low\floatspecification\vfill}%
+ \page_otr_fill_and_eject_page}
+
+\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
+ % nothing
+ \else\ifx\m_page_otf_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
+ \fi\fi}
+
+% temp hack, needed to prevent floatbox being forgotten during
+% output, this will change to using another box for flushing
+%
+% \dorecurse{700}{text } \placefigure[top][]{First} {\framed{bla 1}}
+% \placefigure[top][]{Second}{\framed{bla 2}}
+% \dorecurse {40}{text } \placefigure[top][]{Third} {\framed{bla 3}}
+
+\appendtoks
+ \global\setbox\savedfloatbox\box\floatbox
+\to \everybeforeoutput
+
+\appendtoks
+ \global\setbox\floatbox\box\savedfloatbox
+\to \everyafteroutput
+
+\protect \endinput
+
+% hm, where is this one used (was in save/restore, see old implementation)
+%
+% \unexpanded\def\uncenteredfloatbox
+% {\ifconditional\c_page_floats_center_box
+% \ifhbox\floatbox\relax % remove centering
+% \ifdim\wd\floatbox=\hsize
+% \ifhbox\floatbox
+% \setbox\scratchbox\hbox
+% {\unhbox\floatbox
+% \unskip\unskip
+% \global\setbox\globalscratchbox\lastbox}%
+% \box\globalscratchbox
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-flw.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-flw.mkiv
new file mode 100644
index 00000000000..56fe32e5b9e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-flw.mkiv
@@ -0,0 +1,143 @@
+%D \module
+%D [ file=page-flw,
+%D version=2003.04.19, % from test-002 (1997) profile experiment
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Text Flows,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Text Flows}
+
+%D This is high experimental and especially flushing may change (proper
+%D spacing is the driving force here). It's an old mechanism used for
+%D playing with stepping through document threads. As it's a simple and
+%D effective mechanism we keep it around. It's not to be confused with
+%D upcoming stream support.
+%D
+%D \starttyping
+%D \setuppapersize [S6]
+%D \setuptolerance [verytolerant,stretch]
+%D \setupfooter [strut=no]
+%D \setupwhitespace[big]
+%D
+%D \setuplayout
+%D [rightedge=5cm,width=fit,margin=0pt,edgedistance=1cm,
+%D footer=4cm,footerdistance=1cm,header=0cm]
+%D
+%D \setuptexttexts [edge][][\vbox{\flushtextflow{alpha}}]
+%D \setupfootertexts[edge][][\vbox{\flushtextflow{beta}}]
+%D \setupfootertexts [\vbox{\flushtextflow{gamma}}][]
+%D
+%D \definetextflow [alfa] [width=\rightedgewidth]
+%D \definetextflow [beta] [width=\rightedgewidth]
+%D \definetextflow [gamma] [width=\footerheight]
+%D
+%D \starttext
+%D
+%D \dorecurse{50}
+%D {\getrandomnumber{\funny}{0}{8}
+%D \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow
+%D \or \starttextflow[beta] \input knuth.tex \stoptextflow
+%D \or \starttextflow[gamma] \input materie.tex \stoptextflow
+%D \or {\bf TUFTE}\quad \input tufte \par
+%D \or {\bf TUFTE}\quad \input tufte \par
+%D \or {\bf KNUTH}\quad \input knuth \par
+%D \or {\bf KNUTH}\quad \input knuth \par
+%D \or {\bf MATERIE}\quad \input materie \par
+%D \else {\bf MATERIE}\quad \input materie \par
+%D \fi}
+%D
+%D \stoptext
+%D \stoptyping
+
+\unprotect
+
+\installcorenamespace{textflow}
+\installcorenamespace{textflowbox}
+
+\installcommandhandler \??textflow {textflow} \??textflow
+
+\setuptextflow
+ [%c!style=,
+ %c!color=,
+ \c!width=\availablehsize]
+
+\appendtoks
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \setbox\csname\??textflowbox\currenttextflow\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\??textflowbox\currenttextflow\endcsname
+ \fi
+\to \everydefinetextflow
+
+\let\b_page_textflow_box\zerocount
+
+\def\textflowcollector#1%
+ {\csname\??textflowbox#1\endcsname}
+
+\unexpanded\def\doifelsetextflowcollector#1%
+ {\ifcsname\??textflowbox#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelsetextflow#1%
+ {\ifcsname\??textflowbox#1\endcsname
+ \ifvoid\csname\??textflowbox#1\endcsname
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiftextflowcollectorelse\doifelsetextflowcollector
+\let\doiftextflowelse \doifelsetextflow
+
+% \unexpanded\def\doiftextflow#1%
+% {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument}
+
+\unexpanded\def\starttextflow[#1]%
+ {\begingroup
+ \edef\currenttextflow{#1}%
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname
+ \global\setbox\b_page_textflow_box\vbox
+ \bgroup
+ \dontcomplain
+ \ifvoid\b_page_textflow_box\else
+ \unvbox\b_page_textflow_box
+ \fi
+ \hsize\textflowparameter\c!width\relax
+ \usetextflowstyleandcolor\c!style\c!color
+ \unexpanded\def\stoptextflow{\endgraf\egroup\endgroup}%
+ \else
+ \let\stoptextflow\endgroup
+ \fi}
+
+\unexpanded\def\flushtextflow#1%
+ {\begingroup
+ \edef\currenttextflow{#1}%
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname
+ \ifvoid\b_page_textflow_box
+ % sorry
+ \else\ifdim\ht\b_page_textflow_box>\vsize
+ \setbox\scratchbox\vsplit\b_page_textflow_box to \vsize
+ \ifvoid\scratchbox\else
+ \unvbox\scratchbox
+ \fi
+ \else
+ \unvbox\b_page_textflow_box
+ \fi\fi
+ \fi
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-grd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-grd.mkiv
new file mode 100644
index 00000000000..4125eb46aea
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-grd.mkiv
@@ -0,0 +1,106 @@
+%D \module
+%D [ file=page-grd, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Grids,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Grids}
+
+\unprotect
+
+\newconstant\c_page_grids_location
+\newconstant\c_page_grids_line_mode
+\newconstant\c_page_grids_lineno_mode
+\newconstant\c_page_grids_columns_mode
+
+\unexpanded\def\showgrid
+ {\dosingleempty\page_grids_show}
+
+\def\page_grids_show[#1]%
+ {\c_page_grids_location \plusone % downward compatible default
+ \c_page_grids_line_mode \plusone
+ \c_page_grids_lineno_mode \plusone
+ \c_page_grids_columns_mode\plusone
+ \processallactionsinset
+ [#1]%
+ [ \v!reset=>\c_page_grids_location \zerocount
+ \c_page_grids_columns_mode\zerocount,
+ \v!bottom=>\c_page_grids_location \plusone,
+ \v!top=>\c_page_grids_location \plustwo,
+ \v!none=>\c_page_grids_line_mode \zerocount,
+ \v!all=>\c_page_grids_line_mode \plusone,
+ \v!lines=>\c_page_grids_line_mode \plustwo,
+ \v!frame=>\c_page_grids_line_mode \plusthree,
+ \v!nonumber=>\c_page_grids_lineno_mode \zerocount,
+ \v!right=>\c_page_grids_lineno_mode \plusone,
+ \v!left=>\c_page_grids_lineno_mode \plustwo,
+ \v!outer=>\c_page_grids_lineno_mode \plusthree,
+ \v!columns=>\c_page_grids_columns_mode\plusone]% new option
+ \ifcase\c_page_grids_location
+ \let\page_grids_add_to_box\gobbleoneargument
+ \else % 1=bottom 2=top
+ \let\page_grids_add_to_box\page_grids_add_to_box_indeed
+ \fi
+ \ifcase\c_page_grids_columns_mode
+ \let\page_grids_add_to_one\gobbleoneargument
+ \let\page_grids_add_to_mix\gobbleoneargument
+ \else
+ \let\page_grids_add_to_one\page_grids_add_to_one_indeed
+ \let\page_grids_add_to_mix\page_grids_add_to_mix_indeed
+ \fi}
+
+% if really needed for speed we can cache the grid
+
+\let\page_grids_add_to_box\gobbleoneargument
+\let\page_grids_add_to_one\gobbleoneargument
+\let\page_grids_add_to_mix\gobbleoneargument
+
+\def\page_grids_add_to_box_indeed#1% to be checked for color and layer ..... use mp
+ {\startcolor[layout:grid]%
+ \resetvisualizers
+ \gridboxlinemode \c_page_grids_line_mode
+ \gridboxlinenomode\c_page_grids_lineno_mode
+ \setgridbox\scratchbox\makeupwidth\textheight % todo: check color
+ \global\setbox#1\hbox % global ?
+ {\ifcase\c_page_grids_location\or\or\box#1\hskip-\makeupwidth\fi
+ \begingroup % color
+ \ifcase\layoutcolumns\else
+ \gray
+ \setlayoutcomponentattribute{\v!grid:\v!columns}%
+ \hbox \layoutcomponentboxattribute to \makeupwidth
+ {\dorecurse\layoutcolumns
+ {\hskip\layoutcolumnwidth
+ \ifnum\recurselevel<\layoutcolumns
+ \vrule
+ \s!height\ht\scratchbox
+ \s!depth \dp\scratchbox
+ \s!width \layoutcolumndistance
+ \fi}}%
+ \hskip-\makeupwidth
+ \fi
+ \setlayoutcomponentattribute{\v!grid:\v!lines}%
+ \hbox \layoutcomponentboxattribute{\box\scratchbox}%
+ \endgroup
+ \ifcase\c_page_grids_location\or\hskip-\makeupwidth\box#1\fi}%
+ \stopcolor}
+
+\def\page_grids_add_to_one_indeed#1%
+ {\begingroup
+ \resetvisualizers
+ \global\setbox#1\vpack{\backgroundline[layout:one]{\box#1}}%
+ \endgroup}
+
+\def\page_grids_add_to_mix_indeed#1%
+ {\begingroup
+ \resetvisualizers
+ \global\setbox#1\vpack{\backgroundline[layout:mix]{\box#1}}%
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv
new file mode 100644
index 00000000000..c08f9856fa7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv
@@ -0,0 +1,1369 @@
+%D \module
+%D [ file=page-imp, % was: core-pag,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Pagebody Building (Imposition),
+%D author=Hans Hagen & Willi Egger,
+%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.
+
+% much of this can more to run time loading !
+
+\writestatus{loading}{ConTeXt Page Macros / Pagebody Building}
+
+\unprotect
+
+%D \macros
+%D {starttextdata}
+%D
+%D This is a user macro (appending to every last shipout is not
+%D really user friendly).
+
+\newtoks\t_page_text_data
+
+\unexpanded\def\starttextdata#1\stoptextdata
+ {\global\let\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed
+ \globaladdtotoks\t_page_text_data{#1}}
+
+\let\stoptextdata\relax
+
+\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}
+
+\let\page_shipouts_flush_text_data\relax
+
+\prependtoks
+ \page_shipouts_flush_text_data
+\to \everylastshipout
+
+% Problem: we need to apply the finalizers to a to be shipped out page (as
+% we can have positioning involved). However, we can also add stuff in the
+% imposition, like cropmarks. Fortunately we do that with metapost so
+% colors etc are dealt with at that end.
+
+% \starttypen
+% \def\pagestoshipout{1,3,5}
+% \stoptypen
+
+\installcorenamespace{shipoutmethod}
+\installcorenamespace{layoutarranger}
+\installcorenamespace{layoutarrangeoption}
+
+\newcount \shippedoutpages
+\newcount \combinedpagescounter
+
+\let \pagestoshipout\empty % {1,3,6}
+\newconstant \whichpagetoshipout % 0=all 1=odd 2=even
+
+\newbox \shipoutscratchbox
+
+\setnewconstant\shipoutfinalizemethod\plusone % this will be default (we will have two finalizers)
+
+\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed
+ {\setgvalue{\??shipoutmethod#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package)
+
+\let\installpagehandler\installshipoutmethod % will go
+
+\unexpanded\def\invokepagehandler#1%
+ {\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
+ \else
+ \expandafter\page_shipouts_ignore
+ \fi}
+
+\installshipoutmethod \v!normal
+ {\ifarrangingpages
+ \expandafter\page_shipouts_arrange
+ \else
+ \expandafter\page_shipouts_normal
+ \fi}
+
+\installshipoutmethod \v!none
+ {\page_shipouts_ignore}
+
+% extension mechanism
+
+\newcount\c_page_boxes_flush_n % set at the lua end
+
+\let\page_boxes_flush_before\relax
+\let\page_boxes_flush_after \relax
+
+% used here:
+
+\def\page_boxes_shipout#1% or: \page_shipouts_apply
+ {\dontcomplain % redundant
+ \ifcase\c_page_boxes_flush_n\else
+ \page_boxes_flush_before
+ \fi
+ \the\everybeforeshipout
+ \ifcase\shipoutfinalizemethod
+ \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}%
+ \fi
+ \setnextrealpageno % so this comes before \everyaftershipout so in fact:
+ \the\everyaftershipout % at this point we're already on the next realpage
+ \ifcase\c_page_boxes_flush_n\else
+ \page_boxes_flush_after
+ \fi}
+
+\def\page_shipouts_ignore#1%
+ {\begingroup
+ \message
+ {[\ifarrangingpages arranged \fi page
+ \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
+ not flushed]}%
+ \setbox\scratchbox\hpack{#1}%
+ \deadcycles\zerocount
+ \endgroup}
+
+\def\page_otr_flush_every_stuff
+ {\begingroup
+ \setbox\scratchbox\hpack
+ {% before the main one !
+ \ifcase\realfolio \or
+ \the\everyfirstshipout
+ \global\everyfirstshipout\emptytoks
+ \fi
+ % the main one
+ \the\everyshipout\relax
+ % always last (and after the main one)
+ \ifnum\realpageno=\lastpage\relax
+ \the\everylastshipout
+ \global\everylastshipout\emptytoks
+ \fi}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\newdimen\d_page_shipouts_offset \d_page_shipouts_offset=-1in
+
+\def\page_shipouts_normal#1%
+ {\global\advance\shippedoutpages\plusone
+ % this is not resource safe!
+ \ifx\pagestoshipout\empty
+ \ifcase\whichpagetoshipout\relax
+ \donetrue
+ \or % 1
+ \ifodd\shippedoutpages\relax\donetrue\else\donefalse\fi
+ \or % 2
+ \ifodd\shippedoutpages\relax\donefalse\else\donetrue\fi
+ \else
+ \donetrue
+ \fi
+ \else % testen, aangepast / expanded nodig ?
+ \normalexpanded{\doifelseinset{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse
+ \fi
+ \ifdone
+ \setbox\shipoutscratchbox\hpack{#1}%
+ \ifcase\shipoutfinalizemethod
+ \finalizeshipoutbox\shipoutscratchbox
+ \fi
+ \normalshipout\vpack
+ {\offinterlineskip
+ \vskip\d_page_shipouts_offset
+ \hskip\d_page_shipouts_offset
+ \hpack
+ {\page_otr_flush_every_stuff
+ \page_otr_flush_special_content
+ \box\shipoutscratchbox}}%
+ \else
+ \page_shipouts_ignore{#1}%
+ \fi}
+
+\def\page_shipouts_arrange#1%
+ {% \global\advance\shippedoutpages\plusone
+ \begingroup
+ \setbox\scratchbox\hpack
+ {\page_otr_flush_every_stuff
+ \page_otr_flush_special_content
+ \box\shipoutscratchbox}%
+ \pusharrangedpage\scratchbox
+ \deadcycles\zerocount
+ \endgroup}
+
+%D We need a couple of boxes for duplex printing \unknown
+
+\newbox\arrangedpageA \newbox\arrangedpageB
+\newbox\arrangedpageC \newbox\arrangedpageD
+\newbox\arrangedpageE \newbox\arrangedpageF
+\newbox\arrangedpageG \newbox\arrangedpageH
+
+\newconditional\arrangedswapstate
+\newconditional\arrangednegatestate
+\newconditional\arrangedmirrorstate
+\newconditional\arrangeddoublestate
+\newconditional\arrangingdisabledstate
+\newconditional\arrangedbackgroundstate
+
+\def\arrangedrotationO{0}
+\def\arrangedrotationE{0}
+
+\newcount\arrangedpageN
+\newcount\arrangedpageM
+
+\newcount\arrangedpageT \arrangedpageT\plusone
+\newcount\arrangedpageX \arrangedpageX\plusone
+\newcount\arrangedpageY \arrangedpageY\plusone
+
+\def\page_paper_set_offsets
+ {\global\paperoffset\v_page_target_offset
+ \global\advance\paperwidth -2\dimexpr\paperoffset/\arrangedpageX\relax
+ \global\advance\paperheight-2\dimexpr\paperoffset/\arrangedpageY\relax}
+
+\def\doinstallarrangedoption#1#2%
+ {\setvalue{\??layoutarrangeoption#1}{#2}}
+
+\def\doinstalledarrangedoption#1%
+ {\ifcsname\??layoutarrangeoption#1\endcsname
+ \csname\??layoutarrangeoption#1\endcsname
+ \else
+ \checkinstalledpagearrangement{#1}% this installs the arranger
+ \fi}
+
+\doinstallarrangedoption\empty
+ {} % no default and check if empty, we can have ,,,
+
+\doinstallarrangedoption\v!disable
+ {\global\settrue\arrangingdisabledstate}
+
+\doinstallarrangedoption\v!mirrored
+ {\global\settrue\arrangedmirrorstate}
+
+\doinstallarrangedoption\v!doublesided
+ {\global\settrue\arrangeddoublestate}
+
+\doinstallarrangedoption\v!negative
+ {\global\settrue\arrangednegatestate}
+
+\doinstallarrangedoption\v!rotated
+ {\gdef\arrangedrotationO {90}%
+ \gdef\arrangedrotationE{270}%
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
+
+\doinstallarrangedoption{90}
+ {\gdef\arrangedrotationO {90}%
+ \gdef\arrangedrotationE{270}%
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
+
+\doinstallarrangedoption{180}
+ {\gdef\arrangedrotationO{180}%
+ \gdef\arrangedrotationE {0}}
+
+\doinstallarrangedoption{270}
+ {\gdef\arrangedrotationO{270}%
+ \gdef\arrangedrotationE {90}%
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
+
+\doinstallarrangedoption\s!reset
+ {\global\arrangingpagesfalse}
+
+\doinstallarrangedoption\v!background
+ {\global\settrue\arrangedbackgroundstate}
+
+\unexpanded\def\setuparranging[#1]%
+ {\ifconditional\arrangingdisabledstate \else
+ %global\setfalse\arrangingdisabledstate
+ \global\arrangingpagestrue % will be conditional
+ \global\setfalse\arrangednegatestate
+ \global\setfalse\arrangedmirrorstate
+ \global\setfalse\arrangeddoublestate
+ \global\setfalse\arrangedswapstate
+ \gdef\arrangedrotationO{0}%
+ \gdef\arrangedrotationE{180}%
+ \processcommalist[#1]\doinstalledarrangedoption
+ \ifx\handlearrangedpage\undefined
+ \global\arrangingpagesfalse
+ \fi
+ \setuppapersize
+ \ifarrangingpages
+ \clf_disablejobsave
+ %\disabledirective[job.save]%
+ \fi
+ \fi}
+
+\def\installpagearrangement #1 % will change, no space
+ {\setgvalue{\??layoutarranger#1}}
+
+\def\checkinstalledpagearrangement#1% can be empty: aaa,,bbb
+ {\begincsname\??layoutarranger#1\endcsname}
+
+\let\poparrangedpages\relax
+\let\pusharrangedpage\relax
+
+\def\dosetuparrangement#1#2#3#4#5#6#7#8%
+ {\global\arrangedpageX #1%
+ \global\arrangedpageY #2%
+ \global\arrangedpageT #3%
+ \global\c_page_marks_nx #4%
+ \global\c_page_marks_ny #5%
+ \global\let\pusharrangedpage #6%
+ \global\let\poparrangedpages #7%
+ \global\let\handlearrangedpage#8}
+
+\installpagearrangement {\v!normal}
+ {\global\arrangingpagesfalse}
+
+\installpagearrangement 2*16
+ {\dosetuparrangement{4}{4}{16}{5}{5}%
+ \pusharrangedpageTHIRTYTWO\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*8
+ {\dosetuparrangement{4}{2}{8}{5}{3}%
+ \pusharrangedpageSIXTEEN\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*4
+ {\dosetuparrangement{2}{2}{4}{3}{3}%
+ \pusharrangedpageEIGHT\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURA\poparrangedpagesAB\relax}
+
+\installpagearrangement 2**2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURB\poparrangedpagesAB\relax}
+
+\installpagearrangement 2SIDE
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageSIDE}
+
+\installpagearrangement 2TOP
+ {\dosetuparrangement{1}{2}{2}{2}{3}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageTOP}
+
+\installpagearrangement 2UP
+ {\dosetuparrangement{2}{1}{4}{3}{2}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWOUP}
+
+\installpagearrangement 2DOWN
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWODOWN}
+
+\installpagearrangement 2*4*2 % one defined by Willy Egger:
+ {\dosetuparrangement{2}{2}{4}{3}{3}%
+ \pusharrangedpageSIXTEENTWO\poparrangedpagesAtoD\relax}
+
+\installpagearrangement 2*2*4 % another one of Willy Egger
+ {\dosetuparrangement{2}{1}{8}{3}{2}%
+ \pusharrangedpageSIXTEENFOUR\poparrangedpagesAtoH\relax}
+
+\installpagearrangement 2TOPSIDE
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWOTOPSIDE\poparrangedpagesTWOTOPSIDE\handlearrangedpageTOP}
+
+\def\filluparrangedpages % beware: \realpageno is 1 ahead
+ {\ifarrangingpages
+ \scratchcounter\numexpr\realpageno-\plusone\relax
+ \dosetmodulo\scratchcounter\arrangedpageT\scratchcounter
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter \plusone
+ \dostepwiserecurse\scratchcounter\arrangedpageT\plusone
+ {\noheaderandfooterlines\page_otr_insert_dummy_page}%
+ \fi
+ \fi}
+
+\def\handlearrangedpageXandY#1#2#3#4#5%
+ {\global\setbox#5\hpack to \arrangedpageX\paperwidth
+ {\setbox\scratchbox\vpack to \arrangedpageY\paperheight
+ {\offinterlineskip
+ \vskip#4\paperheight
+ \hskip#3\paperwidth
+ \dorotatebox{\ifcase#2 0\else180\fi}\hpack{\box#1}%
+ \vfill}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\box#5\hss}}
+
+\def\gotonextarrangepage
+ {\global\advance\arrangeno \plusone
+ \def\pagecutmarksymbol{\the\arrangeno}}
+
+\def\outputarrangedbox#1%
+ {\begingroup
+ \forgetall % somehow we're back and need to redo this
+ \gotonextarrangepage
+ \ifnum\arrangedrotationO\arrangedrotationE>\zerocount
+ \setbox#1\vpack
+ {\ifconditional\arrangeddoublestate
+ \ifodd\arrangeno
+ \dorotatebox\arrangedrotationO\hpack{\box#1}%
+ \else
+ \dorotatebox\arrangedrotationE\hpack{\box#1}%
+ \fi
+ \else
+ \dorotatebox\arrangedrotationO\hpack{\box#1}%
+ \fi}%
+ \fi
+ \ifconditional\arrangedmirrorstate
+ \page_boxes_apply_mirror{#1}%
+ \fi
+ \ifconditional\arrangednegatestate
+ \page_boxes_apply_negate{#1}%
+ \fi
+ \page_marks_add_more #1%
+ \page_boxes_apply_center #1%
+ \page_boxes_apply_mirror_print #1%
+ \page_boxes_apply_orientate_print#1%
+ \page_boxes_apply_offset #1%
+ \page_boxes_apply_negate_print #1%
+ %
+ \ifconditional\arrangedbackgroundstate
+ \page_backgrounds_add_to_print#1%
+ \fi
+ %
+ \page_shipouts_normal{\box#1}%
+ \endgroup}
+
+%D The format file can be 16K smaller when we postpone the
+%D real arrangments. Some day ...
+
+\def\reportarrangedpage#1%
+ {\showmessage\m!system{23}{\the\realpageno.\the\pageno\ifnum\subpageno>0 .\the\subpageno\fi,\number#1}}
+
+\def\advancearrangedpageN
+ {\global\advance\arrangedpageN\plusone}
+
+% TOP
+
+% 32/16/8/4/SIDE
+
+\def\poparrangedpagesAB
+ {\ifnum\arrangedpageN>\zerocount
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \global\arrangedpageN\zerocount
+ \fi}
+
+\def\pusharrangedpageTHIRTYTWO#1% taco's challenge
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}033\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}003\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}033\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}003\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}102\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}132\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}102\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}132\arrangedpageA % 16
+ \or \handlearrangedpageXandY{#1}122\arrangedpageA % 17
+ \or \handlearrangedpageXandY{#1}112\arrangedpageB % 18
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 19
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 20
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 21
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 22
+ \or \handlearrangedpageXandY{#1}122\arrangedpageB % 23
+ \or \handlearrangedpageXandY{#1}112\arrangedpageA % 24
+ \or \handlearrangedpageXandY{#1}013\arrangedpageA % 25
+ \or \handlearrangedpageXandY{#1}023\arrangedpageB % 26
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 27
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 28
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 29
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 30
+ \or \handlearrangedpageXandY{#1}013\arrangedpageB % 31
+ \or \handlearrangedpageXandY{#1}023\arrangedpageA % 32
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIXTEEN#1% changed to match the official way of doing
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageEIGHT#1% changed to match the official way of doing
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageFOURA{\pusharrangedpageFOURdo01}
+\def\pusharrangedpageFOURB{\pusharrangedpageFOURdo10}
+
+\def\pusharrangedpageFOURdo#1#2#3%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#3}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#3}0{#1}0\arrangedpageB % 2/3 not {1}
+ \or \handlearrangedpageXandY{#3}0{#2}0\arrangedpageB % 3/2 not {1}
+ \or \handlearrangedpageXandY{#3}000\arrangedpageA % 4
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIDETOP#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \poparrangedpages
+ \fi}
+
+\def\handlearrangedpageSIDE
+ {\wd\arrangedpageA\paperwidth
+ \wd\arrangedpageB\paperwidth
+ \global\setbox\arrangedpageA\hpack
+ {\box\arrangedpageA\box\arrangedpageB}%
+ \ht\arrangedpageA\paperheight}
+
+\def\handlearrangedpageTOP
+ {\ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
+ \global\setbox\arrangedpageA\vpack
+ {\offinterlineskip\vskip\paperheight
+ \box\arrangedpageA\box\arrangedpageB}%
+ \global\setbox\arrangedpageB\box\scratchbox} % ?
+
+% 2UP/2DOWN / 1pt prevents overflow
+
+\def\splitoffarrangedpagesTWO
+ {\splittopskip\zeropoint
+ \global\setbox\arrangedpageA\vsplit\arrangedpageB to \onepoint
+ \scratchdimen\dimexpr\ht\arrangedpageB-\onepoint\relax
+ \ifdim\scratchdimen>\onepoint
+ \setbox\scratchbox\vsplit\arrangedpageB to \scratchdimen
+ \fi}
+
+\def\handlearrangedpageTWOUP
+ {\splitoffarrangedpagesTWO
+ \ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
+ \ifconditional\arrangedswapstate
+ \global\setbox\arrangedpageA\hpack
+ {\page_boxes_apply_clip_print_left \arrangedpageA
+ \box\arrangedpageA
+ \page_boxes_apply_clip_print_right\arrangedpageB
+ \box\arrangedpageB}%
+ \setfalse\arrangedswapstate
+ \else
+ \global\setbox\arrangedpageA\hpack
+ {\page_boxes_apply_clip_print_left \arrangedpageB
+ \box\arrangedpageB
+ \page_boxes_apply_clip_print_right\arrangedpageA
+ \box\arrangedpageA}%
+ \settrue\arrangedswapstate
+ \fi
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\handlearrangedpageTWODOWN
+ {\splitoffarrangedpagesTWO
+ \ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
+ \ifconditional\arrangedswapstate
+ \global\setbox\arrangedpageA\vpack
+ {\offinterlineskip
+ \vskip\paperheight
+ \box\arrangedpageA
+ \box\arrangedpageB}%
+ \setfalse\arrangedswapstate
+ \else
+ \global\setbox\arrangedpageA\vpack
+ {\offinterlineskip
+ \vskip\paperheight
+ \box\arrangedpageB
+ \box\arrangedpageA}%
+ \settrue\arrangedswapstate
+ \fi
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\poparrangedpagesTWO
+ {\ifnum\arrangedpageN>\zerocount
+ \setfalse\arrangedswapstate
+ \doloop
+ {\handlearrangedpage
+ \bgroup
+ \paperwidth \arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \ht\arrangedpageA\paperheight
+ \wd\arrangedpageA\paperwidth
+ \outputarrangedbox\arrangedpageA
+ \egroup
+ \ifdim\ht\arrangedpageB=\zeropoint
+ \exitloop
+ \fi}%
+ \global\arrangedpageN\zerocount
+ \fi}
+
+\def\pusharrangedpageTWO#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \global\setbox\arrangedpageB\vpack
+ {\offinterlineskip
+ \unvbox\arrangedpageB
+ \allowbreak
+ \setbox#1\vpack{\box#1}% really needed in order to keep real dimensions
+ \ht#1\onepoint
+ \dp#1\zeropoint
+ \vpack{\box#1}}}
+
+\def\poparrangedpagesTWOTOPSIDE
+ {\ifnum\arrangedpageN>\zerocount
+ \bgroup
+ \global\arrangedpageN\plustwo
+ \poparrangedpagesTWO
+ \let\arrangedpageA\arrangedpageC
+ \let\arrangedpageB\arrangedpageD
+ \global\arrangedpageN\plustwo
+ \poparrangedpagesTWO
+ \global\arrangedpageN\zerocount
+ \egroup
+ \fi}
+
+\def\pusharrangedpageTWOTOPSIDE#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 2
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 2
+ \poparrangedpages
+ \fi}
+
+%D Willy Egger's sheet simulations:
+
+\def\poparrangedpagesAtoH
+ {\ifnum\arrangedpageN>\zerocount
+ \paperwidth \arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \outputarrangedbox\arrangedpageE
+ \outputarrangedbox\arrangedpageF
+ \outputarrangedbox\arrangedpageG
+ \outputarrangedbox\arrangedpageH
+ \global\arrangedpageN\zerocount
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\poparrangedpagesAtoD
+ {\ifnum\arrangedpageN>\zerocount
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \global\arrangedpageN\zerocount
+ \fi}
+
+% to arrange 16 pages on 4 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENFOUR#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageE % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageF % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageG % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageH % 8
+ \or \handlearrangedpageXandY{#1}010\arrangedpageH % 9
+ \or \handlearrangedpageXandY{#1}000\arrangedpageG % 10
+ \or \handlearrangedpageXandY{#1}010\arrangedpageF % 11
+ \or \handlearrangedpageXandY{#1}000\arrangedpageE % 12
+ \or \handlearrangedpageXandY{#1}010\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENTWO#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}011\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageD % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageC % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}100\arrangedpageC % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageD % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+%D Might be used if a printer is printing from a roll or creating mini-books from A4:
+%D This section has 16 pages. The folding scheme is first a Z-fold and at the end
+%D a final fold in the spine.
+%D Coding: [2*8*Z]
+
+\installpagearrangement 2*8*Z
+ {\dosetuparrangement{2}{4}{8}{3}{5}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageSIXTEENZ\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageSIXTEENZ#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}101\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}111\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}012\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}002\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}103\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}113\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}103\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}113\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}012\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}002\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}101\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}111\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+%D Another Z-folded section with 12 pages
+%D Coding: [2*6*Z]
+
+\installpagearrangement 2*6*Z
+ {\dosetuparrangement{2}{3}{6}{3}{4}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageTWELVEZ\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageTWELVEZ#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1: rotation (0=upright),x (0=first column),y (0=first row)
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}101\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}111\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}012\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}002\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}012\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}002\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}101\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}111\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 12
+ \poparrangedpages
+ \fi}
+
+%D For Heinz' special greeting cards folding. This scheme is also used for the PocketDiary (module):
+%D Coding: [1*8]
+
+\installpagearrangement 1*8
+ {\dosetuparrangement{4}{2}{8}{5}{3}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageEIGHTSINGLESIDEDFOLDED\poparrangedpagesTWO\relax}
+
+\def\pusharrangedpageEIGHTSINGLESIDEDFOLDED#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 2
+ \or \handlearrangedpageXandY{#1}030\arrangedpageA % 3
+ \or \handlearrangedpageXandY{#1}131\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}121\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}111\arrangedpageA % 6
+ \or \handlearrangedpageXandY{#1}101\arrangedpageA % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+%D This is not a section. \CONTEXT\ places 4 pages on a sheet of paper, singlesided
+%D Coding: [1*4]
+
+\installpagearrangement 1*4
+ {\dosetuparrangement{2}{2}{4}{3}{3}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageFOURSINGLESIDEDFOLDED\poparrangedpagesTWO\relax}
+
+\def\pusharrangedpageFOURSINGLESIDEDFOLDED#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 2
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 3
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 4
+ \poparrangedpages
+ \fi}
+
+%D This imposition scheme was requested by Hraban Ramm, by Willi Egger 21-07-2003
+%D Coding: [3SIDE]
+
+\installpagearrangement 3SIDE
+ {\dosetuparrangement{3}{1}{3}{4}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageTHREESIDE\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageTHREESIDE#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 2
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 6
+ \poparrangedpages
+ \fi}
+
+%D FLYER in three parts and 6 pages 22-10-2010
+%D Coding: [TRYPTICHON]
+
+\installpagearrangement TRYPTICHON
+ {\dosetuparrangement{3}{1}{3}{4}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageFLYERSIX\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageFLYERSIX#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 6
+ \poparrangedpages
+ \fi}
+
+%D FLYER in Z-fold with 8 pages 22-01-2010
+%D Coding: [ZFLYER-8]
+
+\installpagearrangement ZFLYER-8
+ {\dosetuparrangement{4}{1}{4}{5}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageZFLYEREIGHT\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageZFLYEREIGHT#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}030\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}030\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 7
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+%D FLYER in Z-fold with 10 pages 04-08-2010
+%D Coding: [ZFLYER-10]
+
+\installpagearrangement ZFLYER-10
+ {\dosetuparrangement{5}{1}{5}{6}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageZFLYERTEN\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageZFLYERTEN#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}040\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}030\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}040\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 7
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}030\arrangedpageA % 10
+ \poparrangedpages
+ \fi}
+
+%D FLYER in Z-fold with 12 pages 04-08-2010
+%D Coding: [ZFLYER-12]
+
+\installpagearrangement ZFLYER-12
+ {\dosetuparrangement{6}{1}{6}{7}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageZFLYERTWELVE\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageZFLYERTWELVE#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}050\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}030\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}040\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}050\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 10
+ \or \handlearrangedpageXandY{#1}030\arrangedpageA % 11
+ \or \handlearrangedpageXandY{#1}040\arrangedpageA % 12
+ \poparrangedpages
+ \fi}
+
+%D FLYER folded as a map with 6 pages per side.
+%D Coding: [MAPFLYER-12]
+
+\installpagearrangement MAPFLYER-12
+ {\dosetuparrangement{3}{2}{6}{4}{3}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageMFLYERTWELVE\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageMFLYERTWELVE#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 10
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 11
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 12
+ \poparrangedpages
+ \fi}
+
+%D FLYER folded as double window with 4 pages per side.
+%D Coding: [DOUBLEWINDOW]
+
+\installpagearrangement DOUBLEWINDOW
+ {\dosetuparrangement{4}{1}{4}{5}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageDOUBLEWINDOWEIGHT\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageDOUBLEWINDOWEIGHT#1% Willi's approach
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}020\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}030\arrangedpageA % 2
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 4
+ \or \handlearrangedpageXandY{#1}020\arrangedpageB % 5
+ \or \handlearrangedpageXandY{#1}030\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 7
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+%D Imposition as requested by Jan Pohanka 26-08-2010, 4 pages, two verso, two recto,
+%D uneven pages upright and down, even pages top and rotated 180.
+%D Implementation with 2 pages for conference-name-display
+%D Coding: [1*2-Conference]
+
+\installpagearrangement 1*2-Conference
+ {\dosetuparrangement{1}{2}{4}{3}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageCONFERENCETWO\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageCONFERENCETWO#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 2
+ \poparrangedpages
+ \fi}
+
+%D Implementation with 4 pages for conference-name-display
+%D Coding: [1*4-Conference]
+
+\installpagearrangement 1*4-Conference
+ {\dosetuparrangement{1}{2}{4}{3}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageCONFERENCEFOUR\poparrangedpagesAB\relax}
+
+\def\pusharrangedpageCONFERENCEFOUR#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 2
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 4
+ \poparrangedpages
+ \fi}
+
+%D There should be arrangements for sections made of heavy and thick paper. i.e. the heavier the paper
+%D the fewer pages per section:
+%D Section with 8 pages put on two sheets of paper. Each sheet carries recto 2 and verso 2 pages.
+%D Coding: [2*2*2]
+
+\installpagearrangement 2*2*2
+ {\dosetuparrangement{2}{1}{2}{3}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageEIGHTTWO\poparrangedpagesAtoD\relax}
+
+\def\pusharrangedpageEIGHTTWO#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageD % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+%D Section with 12 pages, built from three sheets of paper.
+%D Each sheet carries 2 pages recto and verso.
+%D Coding: [2*2*3]
+
+\def\poparrangedpagesAtoF
+ {\ifnum\arrangedpageN>\zerocount
+ \paperwidth \arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \outputarrangedbox\arrangedpageE
+ \outputarrangedbox\arrangedpageF
+ \global\arrangedpageN\zerocount
+ \fi}
+
+\installpagearrangement 2*2*3
+ {\dosetuparrangement{2}{1}{2}{3}{2}% X,Y,Total,hcutmarks,vcutmarks
+ \pusharrangedpageTWELVETWO\poparrangedpagesAtoF\relax}
+
+\def\pusharrangedpageTWELVETWO#1%
+ {\advancearrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1 rot,hskip,vskip
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageE % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageF % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageF % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageE % 8
+ \or \handlearrangedpageXandY{#1}010\arrangedpageD % 9
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 10
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 12
+ \poparrangedpages
+ \fi}
+
+% % From Wolfgang for Mari (mail on list) ... yes or no in core .. time for
+% % delayed loading ...
+% %
+% % http://stamphenge.wordpress.com/minibooks/meander-accordion-folded-book/
+%
+% \installpagearrangement MEANDER16
+% {\dosetuparrangement{4}{4}{16}{5}{5}%
+% \pusharrangedpageMEANDERSIXTEEN\poparrangedpagesXY\relax}
+%
+% \def\pusharrangedpageMEANDERSIXTEEN#1%
+% {\advancearrangedpageN
+% \reportarrangedpage\arrangedpageN
+% \ifcase\arrangedpageN
+% \or \handlearrangedpageXandY{#1}000\arrangedpageA
+% \or \handlearrangedpageXandY{#1}010\arrangedpageA
+% \or \handlearrangedpageXandY{#1}020\arrangedpageA
+% \or \handlearrangedpageXandY{#1}030\arrangedpageA
+% \or \handlearrangedpageXandY{#1}131\arrangedpageA
+% \or \handlearrangedpageXandY{#1}121\arrangedpageA
+% \or \handlearrangedpageXandY{#1}111\arrangedpageA
+% \or \handlearrangedpageXandY{#1}101\arrangedpageA
+% \or \handlearrangedpageXandY{#1}002\arrangedpageA
+% \or \handlearrangedpageXandY{#1}012\arrangedpageA
+% \or \handlearrangedpageXandY{#1}022\arrangedpageA
+% \or \handlearrangedpageXandY{#1}032\arrangedpageA
+% \or \handlearrangedpageXandY{#1}133\arrangedpageA
+% \or \handlearrangedpageXandY{#1}123\arrangedpageA
+% \or \handlearrangedpageXandY{#1}113\arrangedpageA
+% \or \handlearrangedpageXandY{#1}103\arrangedpageA
+% \poparrangedpages
+% \fi}
+%
+% % \definepapersize[small][width=6cm,height=6cm]
+% % \definepapersize[big][width=30cm,height=30cm]
+% % \setuppapersize[small][big]
+% % \setuppagenumbering[location=]
+% % \setuparranging[MEANDER16]
+% % \setuplayout
+% % [location=middle,
+% % marking=on]
+% % \starttext
+% % \dorecurse{32}{\centerbox{\ssd\recurselevel}}
+% % \stoptext
+%
+% % By Willi:
+%
+% \installpagearrangement MEANDER9
+% {\dosetuparrangement{3}{3}{9}{4}{4}%
+% \pusharrangedpageMEANDERNINE\poparrangedpagesXY\relax}
+%
+% \def\pusharrangedpageMEANDERNINE#1%
+% {\advancearrangedpageN
+% \reportarrangedpage\arrangedpageN
+% \ifcase\arrangedpageN
+% \or \handlearrangedpageXandY{#1}000\arrangedpageA
+% \or \handlearrangedpageXandY{#1}010\arrangedpageA
+% \or \handlearrangedpageXandY{#1}020\arrangedpageA
+% \or \handlearrangedpageXandY{#1}121\arrangedpageA
+% \or \handlearrangedpageXandY{#1}111\arrangedpageA
+% \or \handlearrangedpageXandY{#1}101\arrangedpageA
+% \or \handlearrangedpageXandY{#1}002\arrangedpageA
+% \or \handlearrangedpageXandY{#1}012\arrangedpageA
+% \or \handlearrangedpageXandY{#1}022\arrangedpageA
+% \poparrangedpages
+% \fi}
+
+% % handy for stickers etc, this way we can treat them as page
+%
+% \setuppapersize [XY][A4]
+% \setuppaper [topspace=5mm,backspace=5mm,dx=1mm,dy=1mm,nx=2,ny=6]
+% \setuplayout [page] [topspace=5mm,backspace=5mm]
+% \setuplayout [page]
+% \setuplayout [location=middle]
+% \setuparranging [XY]
+% \showframe
+%
+% \starttext \dorecurse{30}{test \recurselevel \page} \stoptext
+
+\unexpanded\def\pusharrangedpageXY#1%
+ {\advancearrangedpageN
+ \global\advance\arrangedpageM\plusone
+ \reportarrangedpage\arrangedpageN
+ \global\setbox\arrangedpageB\hpack \ifdim\v_page_target_width>\zeropoint to \v_page_target_width \fi
+ {\ifvoid\arrangedpageB\else
+ \unhbox\arrangedpageB
+ \ifdim\v_page_target_dx>\zeropoint
+ \hskip\v_page_target_dx
+ \else
+ \hss
+ \hskip\v_page_target_dx
+ \hss
+ \fi
+ \fi
+ \box#1}%
+ \ifnum\arrangedpageM<\arrangedpageX\else
+ \global\setbox\arrangedpageA\vpack \ifdim\v_page_target_height>\zeropoint to \v_page_target_height \fi
+ {\offinterlineskip
+ \ifvoid\arrangedpageA\else
+ \unvbox\arrangedpageA
+ \ifdim\v_page_target_dy>\zeropoint
+ \vskip\v_page_target_dy
+ \else
+ \vss
+ \vskip\v_page_target_dy
+ \vss
+ \fi
+ \fi
+ \box\arrangedpageB}%
+ \global\arrangedpageM\zerocount
+ \fi
+ \ifnum\arrangedpageN<\arrangedpageT\else
+ \poparrangedpages
+ \fi}
+
+\unexpanded\def\poparrangedpagesXY
+ {\ifnum\arrangedpageN>\zerocount
+ \paperwidth \arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \global\arrangedpageN\zerocount
+ \global\arrangedpageM\zerocount
+ \fi}
+
+\installpagearrangement XY
+ {\dosetuparrangement
+ \v_page_target_nx
+ \v_page_target_ny
+ \v_page_target_xy
+ \zerocount
+ \zerocount
+ \pusharrangedpageXY\poparrangedpagesXY\relax}
+
+%D A crazy definition, don't guess who pushed me for the landscape option.
+
+\def\page_imposition_xy_height
+ {\dimexpr
+ \dimexpr
+ \v_page_target_height
+ -\numexpr\v_page_target_ny-1\relax\v_page_target_dy
+ \relax
+ /\v_page_target_ny
+ \relax}
+
+\def\page_imposition_xy_width
+ {\dimexpr
+ \dimexpr
+ \v_page_target_width
+ -\numexpr\v_page_target_nx-1\relax\v_page_target_dx
+ \relax
+ /\v_page_target_nx
+ \relax}
+
+\definepapersize
+ [XY]
+ [\c!height=\page_imposition_xy_height,
+ \c!width =\page_imposition_xy_width]
+
+\setuppaper
+ [\c!width =\dimexpr\printpaperwidth -2\v_page_target_backspace\relax,
+ \c!height=\dimexpr\printpaperheight-2\v_page_target_topspace \relax]
+
+% \definepageshift[test][horizontal][10pt,20pt,30pt,40pt,50pt]
+% \definepageshift[test][vertical] [10pt,20pt,30pt,40pt,50pt]
+%
+% \setuppageshift[test]
+% \setuppageshift[test][test]
+% \setuppageshift[test][none]
+% \setuppageshift[none][test]
+% \setuppageshift[paper][test][test] % arrange only
+% \setuppageshift[paper][test] % arrange only
+% \setuppageshift[print][test][test]
+%
+% \showframe \dorecurse{100}{\input tufte \par}
+
+% #1=name #2=horizontal|vertical #3=shiftlist
+
+% this will move to lua
+
+\installcorenamespace {pageshift}
+
+\unexpanded\def\definepageshift
+ {\dotripleargument\page_boxes_define_shift}
+
+\def\page_boxes_define_shift[#1][#2][#3]%
+ {\setvalue{\??pageshift#2:#1}{#3}}
+
+\let\page_boxes_h_shifts\empty
+\let\page_boxes_v_shifts\empty
+
+\newcount\c_page_boxes_h_shifts
+\newcount\c_page_boxes_v_shifts
+
+\newdimen\d_page_boxes_h_shifts
+\newdimen\d_page_boxes_v_shifts
+
+\let\page_boxes_apply_shift_print\gobbleoneargument
+\let\page_boxes_apply_shift_paper\gobbleoneargument
+
+\def\page_boxes_filter_shift#1#2#3% #1=\dimenx #2=\xpageshifts #3=\nofxpageshifts
+ {#1\zeropoint
+ \ifx#2\empty \else
+ \global\advance#3\plusone
+ \getfromcommacommand[#2][#3]%
+ \ifx\commalistelement\empty
+ \global#3\plusone % we cycle
+ \getfromcommacommand[#2][#3]%
+ \fi
+ \ifx\commalistelement\empty \else
+ #1\commalistelement\relax % the relax is really needed as there is an \if later on
+ \fi
+ \fi}
+
+\def\page_boxes_apply_shift#1%
+ {\page_boxes_filter_shift\d_page_boxes_h_shifts\page_boxes_h_shifts\c_page_boxes_h_shifts
+ \page_boxes_filter_shift\d_page_boxes_v_shifts\page_boxes_v_shifts\c_page_boxes_v_shifts
+ \ifzeropt\d_page_boxes_h_shifts
+ \ifzeropt\d_page_boxes_v_shifts
+ % nothing to shift
+ \else
+ \page_boxes_apply_shift_indeed#1%
+ \fi
+ \else
+ \page_boxes_apply_shift_indeed#1%
+ \fi}
+
+\def\page_boxes_apply_shift_indeed#1%
+ {\edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vpack
+ {\offinterlineskip
+ \vskip\d_page_boxes_v_shifts
+ \hskip\d_page_boxes_h_shifts
+ \box#1}%
+ \next}
+
+\unexpanded\def\setuppageshift
+ {\dotripleempty\page_boxes_setup_shift}
+
+\def\page_boxes_setup_shift[#1][#2][#3]% page|paper horizontal vertical
+ {\ifthirdargument % paper=arrange
+ %edef\page_boxes_h_shifts{\ifcsname\??pageshift\v!horizontal:#2\endcsname\csname\??pageshift\v!horizontal:#2\endcsname\fi}%
+ %edef\page_boxes_v_shifts{\ifcsname\??pageshift\v!vertical :#3\endcsname\csname\??pageshift\v!vertical :#3\endcsname\fi}%
+ \edef\page_boxes_h_shifts{\begincsname\??pageshift\v!horizontal:#2\endcsname}%
+ \edef\page_boxes_v_shifts{\begincsname\??pageshift\v!vertical :#3\endcsname}%
+ \doifelse{#1}\v!page {\let\page_boxes_apply_shift_print\page_boxes_apply_shift}{\let\page_boxes_apply_shift_print\gobbleoneargument}%
+ \doifelse{#1}\v!paper{\let\page_boxes_apply_shift_paper\page_boxes_apply_shift}{\let\page_boxes_apply_shift_paper\gobbleoneargument}%
+ \else\ifsecondargument
+ \doifelseinset{#1}{\v!page,\v!paper}
+ {\setuppageshift[#1][#2][#2]}
+ {\setuppageshift[\v!page][#1][#2]}%
+ \else\iffirstargument
+ \setuppageshift[\v!page][#1][#1]%
+ \fi\fi\fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv
new file mode 100644
index 00000000000..f60977e0c97
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv
@@ -0,0 +1,106 @@
+%D \module
+%D [ file=page-inf, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Tracing Info,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Tracing Info}
+
+% this needs a real cleanup .. will be a more detailed list
+
+\unprotect
+
+\installcorenamespace{layoutinfo}
+
+\newtoks\everyresetversion
+\newtoks\everysetupversion
+
+\let\currentversioninfo\empty
+
+\unexpanded\def\setupversion
+ {\dosingleargument\page_info_setup}
+
+\let\version\setupversion
+
+\let\page_info_add_to_box\gobbleoneargument
+
+\def\page_info_setup[#1]%
+ {\the\everyresetversion
+ \ifcsname\??layoutinfo#1\endcsname
+ \edef\currentversioninfo{#1}%
+ \let\page_info_add_to_box\page_info_add_to_box_indeed
+ \else
+ \let\currentversioninfo\empty
+ \let\page_info_add_to_box\gobbleoneargument
+ \fi
+ \the\everysetupversion}
+
+\unexpanded\def\page_info_place_info % at the bottom of the page
+ {\csname\??layoutinfo\currentversioninfo\endcsname}
+
+\unexpanded\def\installversioninfo#1#2%
+ {\setvalue{\??layoutinfo#1}{#2}}
+
+\unexpanded\def\includeversioninfo#1%
+ {\csname\??layoutinfo#1\endcsname}
+
+\installversioninfo\v!concept
+ {\vskip6\points
+ \hbox to \makeupwidth
+ {\infofont
+ \v!concept:\space\currentdate
+ \hss
+ \page_adapts_status_info}}
+
+\installversioninfo\v!file
+ {\vskip6\points
+ \hbox to \makeupwidth
+ {\infofont
+ \getmessage\m!system{27}:\space\currentdate\space
+ \donefalse
+ \ifx\currentproject \empty \else \space\v!project :\space\currentproject \space \donetrue \fi
+ \ifx\currentproduct \empty \else \space\v!product :\space\currentproduct \space \donetrue \fi
+ \ifx\currentcomponent\empty \else \space\v!component:\space\currentcomponent\space \donetrue \fi
+ \ifdone \else \space\v!file :\space\jobname \space \fi
+ \hss
+ \page_adapts_status_info}}
+
+\installversioninfo\v!temporary
+ {\includeversioninfo\v!file}
+
+\appendtoks
+ \overfullrule\zeropoint
+\to \everyresetversion
+
+\appendtoks
+ \ifx\currentversioninfo\v!temporary
+ \overfullrule5\points
+ \fi
+\to \everysetupversion
+
+\newbox\b_page_versions
+
+\def\page_info_add_to_box_indeed#1%
+ {\scratchdimen\wd#1%
+ \setbox\b_page_versions\vpack to \ht#1%
+ {\vfill
+ \settexthoffset
+ \hsize\dimexpr\scratchdimen-2\texthoffset\relax
+ \hskip\texthoffset % brrrr
+ \vbox to \zeropoint{\vss\page_info_place_info}%
+ \vskip\bodyfontsize}%
+ \dp\b_page_versions\zeropoint
+ \wd\b_page_versions\scratchdimen
+ \setbox#1\hpack{\box#1\hskip-\scratchdimen\box\b_page_versions}}
+
+\setupversion % resets
+ [\v!final]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv
new file mode 100644
index 00000000000..6f6cb7180ff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv
@@ -0,0 +1,270 @@
+%D \module
+%D [ file=page-ini,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Initializations}
+
+%D The \type {\processpage} command has become obsolete. It's original
+%D purpose was to flush only parts of a document but nowadays we have
+%D project structure and modes. This is just one of those very early
+%D features that no longer makes sense.
+
+%D The \type {\couplepage} command has become obsolete. It's original
+%D purpose was to provide hooks for printer directives (like choosing
+%D different paper trays).
+
+\unprotect
+
+%D Shipout control.
+
+\newcount\nofshipouts
+
+\appendtoks
+ \global\advance\nofshipouts\plusone
+\to \everyaftershipout
+
+\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled
+
+\unexpanded\def\page_otr_shipout
+ {\ifconditional\c_otr_shipout_enabled
+ \expandafter\page_otr_shipout_yes
+ \else
+ \expandafter\page_otr_shipout_nop
+ \fi}
+
+\let\page_otr_shipout_yes\normalshipout
+
+\unexpanded\def\page_otr_shipout_nop
+ {\writestatus\m!system{ignoring shipout of real page \the\realpageno}%
+ \global\advance\realpageno\minusone % else no flush of resources
+ \dowithnextbox{\deadcycles\zerocount}}
+
+% We don't support direct user \shipouts (weird: this does not work, bug?)
+%
+% \let\shipout\page_otr_shipout_nop
+
+%D Building pages.
+
+\newbox\pagebox
+
+\ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi
+\ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi
+\ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi
+
+%D Floats.
+
+\def\page_otr_flush_all_floats
+ {%\flushnotes already done
+ \ifconditional\c_page_floats_some_waiting
+ \begingroup
+ \c_page_floats_n_of_top\plusthousand
+ \c_page_floats_n_of_bottom\zerocount
+ % this is needed in case a float that has been stored
+ % ends up at the current page; this border case occurs when
+ % the calculated room is 'eps' smaller that the room available
+ % when just flushing; so now we have (maybe optional):
+ \pagebaselinecorrection % hm, needs checking, not needed when no floats
+ % alas, this is tricky but needed (first surfaced in prikkels)
+ \page_otr_command_flush_floats
+ \endgroup
+ \fi}
+
+\def\page_otr_insert_dummy_page
+ {\par
+ \ifvmode
+ \page_otr_flush_all_floats
+ \fixedspace
+ \vfill
+ \page_otr_command_next_page
+ \fi}
+
+\def\page_otr_flush_pending_content
+ {\vskip\zeropoint\relax % brrr .. get rid of this
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \penalty\outputpenalty
+ \fi}
+
+\def\page_otr_construct_and_shipout#1#2%
+ {\forgetall
+ \page_boxes_shipout{\page_boxes_constructed_page#1#2}% \hbox removed
+ \page_otr_flush_pending_content
+ % not really needed, replaced by \flushsavedfloats
+ \page_otr_check_for_pending_inserts
+ % but does not hurt either (we're still in the otr!)
+ \inpagebodytrue % needed for enabling \blank ! brrr
+ \pagebodymode\plusone % todo: \plustwo when spread
+ \page_otr_command_flush_saved_floats
+ \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns
+ \strc_pagenumbers_increment_counters % should hook into an every
+ \page_adapts_synchronize
+ \page_otr_check_for_pending_inserts
+ \page_floats_flush_page_floats % before postponed blocks
+ \page_spread_flush % defined later
+ \page_postponed_blocks_flush}
+
+% Can't we get rid of this hackery? It's used in some widgets
+% stuff so probably not.
+
+\newbox\b_page_otr_special
+
+\def\page_otr_flush_special_content
+ {\ifvoid\b_page_otr_special \else
+ \box\b_page_otr_special
+ \fi}
+
+\def\page_otr_add_special_content
+ {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox}
+
+\def\page_otr_add_special_content_indeed
+ {\wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \global\setbox\b_page_otr_special\hbox
+ {%\hskip-\maxdimen % not here, fails in acrobat (clips)
+ \box\b_page_otr_special\box\nextbox}}% was \unhbox, is now box again
+
+\let\flushatshipout\page_otr_add_special_content
+
+\maxdeadcycles=1000
+
+\newtoks\afterpage \newtoks\aftereverypage
+\newtoks\beforepage \newtoks\beforeeverypage
+
+\newif\ifarrangingpages \arrangingpagesfalse
+
+\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off
+
+% \appendtoks
+% \ifcase\pageornamentstate \or
+% \pageornamentstate\zerocount
+% \fi
+% \to \everyaftershipout
+
+\appendtoks
+ \ifcase\pageornamentstate \or
+ \global\pageornamentstate\zerocount
+ \fi
+\to \everyaftershipout
+
+% Mark synchronization
+
+\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages
+
+\def\page_marks_synchronize_page#1% box
+ {\strc_markings_synchronize[\v!page][#1][\ifconditional\c_page_marks_building_successive_pages\v!keep\fi]}
+
+\def\page_marks_synchronize_column#1#2#3#4% first last column box
+ {\ifnum#3=#1\relax
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!first,\v!column:\v!first][#4][]%
+ \else\ifnum#3=#2\relax
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!last, \v!column:\v!last ][#4][]%
+ \else
+ \strc_markings_synchronize[\number#3,\v!column:\number#3 ][#4][]%
+ \fi\fi}
+
+% Page body building
+
+\newconditional\c_page_boxes_save_page_body
+\newbox \b_page_boxes_saved_page_body
+
+\def\page_boxes_constructed_page_body#1#2%
+ {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup
+ \boxmaxdepth\maxdimen % new
+ \dontcomplain
+ \page_marks_synchronize_page {#2}% we could consider doing this for \pagebox (needs testing)
+ \page_boxes_construct_content \pagebox{#1}{#2}%
+ \page_backgrounds_add_to_main \pagebox
+ \page_boxes_apply_offsets \pagebox
+ \page_info_add_to_box \pagebox
+ \ifcase\pageornamentstate
+ \page_backgrounds_add_to_paper \pagebox
+ \fi
+ \anch_positions_register_page \pagebox
+ \ifarrangingpages
+ \page_boxes_apply_shift_paper \pagebox % \v!paper
+ \else
+ \page_boxes_apply_clip_paper \pagebox
+ \page_marks_add_page \pagebox
+ \page_boxes_apply_replicate \pagebox
+ \page_boxes_apply_scale \pagebox
+ \page_boxes_apply_mirror_paper \pagebox
+ \page_boxes_apply_orientate_paper \pagebox
+ \page_marks_add_more \pagebox
+ \page_boxes_apply_center \pagebox
+ \page_backgrounds_add_to_print \pagebox
+ \page_boxes_apply_mirror_print \pagebox
+ \page_boxes_apply_orientate_print \pagebox
+ \page_boxes_apply_shift_print \pagebox % \v!page
+ \page_boxes_apply_offset \pagebox
+ \page_boxes_apply_negate_print \pagebox
+ \fi
+ \box\pagebox
+ \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi}
+
+\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
+
+\ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed?
+
+\prependtoks
+ \let\nextbox\nestednextbox
+\to \everybeforepagebody
+
+\def\page_boxes_constructed_page#1#2%
+ {\vpack\bgroup % intercept spurious spaces
+ \the\everybeforepagebody
+ \starttextproperties
+ \checkmarginblocks
+ \the\beforeeverypage
+ \normalexpanded{\global\beforepage\emptytoks\the\beforepage}%
+ \inpagebodytrue
+ \pagebodymode\plusone % todo: \plustwo when spread
+ \page_boxes_constructed_page_body#1#2%
+ \normalexpanded{\global\afterpage \emptytoks\the\afterpage }%
+ \the\aftereverypage
+ \resetpagebreak
+ \resetlayouttextlines % will go to \aftereverypage
+ \stoptextproperties
+ \the\everyafterpagebody
+ \egroup}
+
+\def\doifelsetopofpage
+ {\ifdim\pagegoal=\maxdimen
+ \expandafter\firstoftwoarguments
+ \else\ifdim\pagegoal=\vsize
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\let\doiftopofpageelse\doifelsetopofpage
+
+% %D Idea:
+%
+% \newinsert\thispageinsert % <- installinsertion
+%
+% \def\flushatthispage
+% {\bgroup
+% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
+% \hbox}
+%
+% \appendtoks
+% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
+% \to \everyshipout
+%
+% %D Idea:
+%
+% \definemarkedpage[nobackgrounds]
+% \markpage[nobackgrounds]
+% \doifmarkedpageelse{nobackgrounds}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-inj.lua b/Master/texmf-dist/tex/context/base/mkiv/page-inj.lua
new file mode 100644
index 00000000000..fd66ead08d1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-inj.lua
@@ -0,0 +1,125 @@
+if not modules then modules = { } end modules ["page-inj"] = {
+ version = 1.000,
+ comment = "Page injections",
+ author = "Wolfgang Schuster & Hans Hagen",
+ copyright = "Wolfgang Schuster & Hans Hagen",
+ license = "see context related readme files",
+}
+
+-- Adapted a bit by HH: numbered states, tracking, delayed, order, etc.
+
+local type, tonumber = type, tonumber
+
+local injections = pagebuilders.injections or { }
+pagebuilders.injections = injections
+
+local report = logs.reporter("pagebuilder","injections")
+local trace = false trackers.register("pagebuilder.injections",function(v) trace = v end)
+
+local context = context
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+local texsetcount = tex.setcount
+
+local v_yes = variables.yes
+local v_previous = variables.previous
+local v_next = variables.next
+
+local order = 0
+local cache = { }
+
+function injections.save(specification) -- maybe not public, just commands.*
+ order = order + 1
+ cache[#cache+1] = {
+ order = order,
+ name = specification.name,
+ state = tonumber(specification.state) or specification.state,
+ parameters = specification.userdata,
+ }
+ texsetcount("global","c_page_boxes_flush_n",#cache)
+end
+
+function injections.flushbefore() -- maybe not public, just commands.*
+ if #cache > 0 then
+ local delayed = { }
+ context.unprotect()
+ for i=1,#cache do
+ local c = cache[i]
+ local oldstate = c.state
+ if oldstate == v_previous then
+ if trace then
+ report("entry %a, order %a, flushing due to state %a",i,c.order,oldstate)
+ end
+ context.page_injections_flush_saved(c.name,c.parameters)
+ elseif type(oldstate) == "number" and oldstate < 0 then
+ local newstate = oldstate + 1
+ if newstate >= 0 then
+ newstate = v_previous
+ end
+ if trace then
+ report("entry %a, order %a, changing state from %a to %a",i,c.order,oldstate,newstate)
+ end
+ c.state = newstate
+ delayed[#delayed+1] = c
+ else
+ delayed[#delayed+1] = c
+ end
+ end
+ context.unprotect()
+ cache = delayed
+ texsetcount("global","c_page_boxes_flush_n",#cache)
+ end
+end
+
+function injections.flushafter() -- maybe not public, just commands.*
+ if #cache > 0 then
+ local delayed = { }
+ context.unprotect()
+ for i=1,#cache do
+ local c = cache[i]
+ local oldstate = c.state
+ if oldstate == v_next then
+ if trace then
+ report("entry %a, order %a, flushing due to state %a",i,c.order,oldstate)
+ end
+ context.page_injections_flush_saved(c.name,c.parameters)
+ elseif type(oldstate) == "number" and oldstate> 0 then
+ local newstate = oldstate- 1
+ if newstate <= 0 then
+ newstate = v_next
+ end
+ if trace then
+ report("entry %a, order %a, changing state from %a to %a",i,c.order,oldstate,newstate)
+ end
+ c.state = newstate
+ delayed[#delayed+1] = c
+ end
+ end
+ context.protect()
+ cache = delayed
+ texsetcount("global","c_page_boxes_flush_n",#cache)
+ end
+end
+
+implement {
+ name = "savepageinjections",
+ actions = injections.save,
+ arguments = {
+ {
+ { "name" },
+ { "state" },
+ { "userdata" }
+ }
+ }
+}
+
+implement {
+ name = "flushpageinjectionsbefore",
+ actions = injections.flushbefore
+}
+
+implement {
+ name = "flushpageinjectionsafter",
+ actions = injections.flushafter
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi
new file mode 100644
index 00000000000..03472fe5593
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi
@@ -0,0 +1,217 @@
+%D \module
+%D [ file=page-inj,
+%D version=2013.02.10,
+%D title=\CONTEXT\ Page Module,
+%D subtitle=Injections,
+%D author=Wolfgang Schuster \& Hans Hagen,
+%D date=\currentdate,
+%D copyright=Wolfgang Schuster \& Hans Hagen,
+%D license=see context related readme files (gpl)]
+
+%D This module is based on an idea and prototype by Wolfgang but instead of
+%D injectioning into a page constructor we injection it into the regular shipout
+%D handler because that way we get page numbering. It's a sort of variation
+%D on postponing but the content does not end up in the regular page flow, so
+%D it's closer to page figures but without the usual page builder.
+%D
+%D This module is following the mkvi way of rendering setups and configuration
+%D and is somewhat experimental. Probably more alternatives will be added. This
+%D could become a delayed loaded module at some point (no real consequences).
+
+\unprotect
+
+\registerctxluafile{page-inj}{1.001}
+
+\installcorenamespace {pageinjection}
+\installcorenamespace {pageinjectionalternative}
+\installcorenamespace {pageinjectionrenderings}
+
+\installframedcommandhandler \??pageinjection {pageinjection} \??pageinjection
+\installcommandhandler \??pageinjectionalternative {pageinjectionalternative} \??pageinjectionalternative
+
+\let\page_boxes_flush_before\clf_flushpageinjectionsbefore
+\let\page_boxes_flush_after \clf_flushpageinjectionsafter
+
+\def\page_injections_flush_saved#name#parameters%
+ {\begingroup
+ \edef\currentpageinjection{#name}%
+ \getdummyparameters[#parameters]%
+ \edef\currentpageinjectionalternative {\pageinjectionparameter \c!alternative }%
+ \edef\p_page_injectionalternative_rederingsetup{\pageinjectionalternativeparameter\c!renderingsetup}%
+ \page_injections_nextpage
+ \invokepagehandler\v!normal{\inheritedpageinjectionframed{\texsetup\p_page_injectionalternative_rederingsetup}}%
+ \endgroup}
+
+\unexpanded\def\pageinjection
+ {\begingroup
+ \dodoubleempty\page_injections_direct}
+
+\def\page_injections_direct[#1][#2]% name parameters | settings parameters | name | parameters
+ {\doifelseassignment{#1}
+ {\doifelseassignment{#2}
+ {\page_injections_direct_settings_parameters{#1}{#2}}
+ {\page_injections_direct_parameters {#1}}}
+ {\doifelseassignment{#2}
+ {\page_injections_direct_name_parameters {#1}{#2}}
+ {\page_injections_direct_name {#1}}}}
+
+\def\page_injections_direct_settings_parameters#settings% #parameters%
+ {\let\currentpageinjection\empty
+ \checkpageinjectionparent
+ \setupcurrentpageinjection[#settings]%
+ \page_injections_direct_indeed}
+
+\def\page_injections_direct_parameters% #parameters%
+ {\let\currentpageinjection\empty
+ \checkpageinjectionparent
+ \page_injections_direct_indeed}
+
+\def\page_injections_direct_name_parameters#name% #parameters%
+ {\edef\currentpageinjection{#name}%
+ \checkpageinjectionparent
+ \page_injections_direct_indeed}
+
+\def\page_injections_direct_name#name%
+ {\edef\currentpageinjection{#name}%
+ \checkpageinjectionparent
+ \page_injections_direct_indeed{}}
+
+\def\page_injections_direct_indeed% #parameters%
+ {\edef\p_page_injections_state{\pageinjectionparameter\c!state}%
+ \edef\p_page_injections_delay{\pageinjectionparameter\c!delay}%
+ \edef\p_page_injections_page {\pageinjectionparameter\c!page }%
+ \ifx\p_page_injections_delay\v!yes
+ \expandafter\page_injections_direct_indeed_yes
+ \else
+ \expandafter\page_injections_direct_indeed_nop
+ \fi}
+
+\def\page_injections_direct_indeed_yes#parameters%
+ {\clf_savepageinjections
+ name {\currentpageinjection}%
+ state {\p_page_injections_state}%
+ userdata {\normalunexpanded{#parameters}}%
+ \relax
+ \endgroup}
+
+\def\page_injections_direct_indeed_nop#parameters%
+ {\ifx\p_page_injections_page\empty
+ \page
+ \else
+ \page[\p_page_injections_page]%
+ \fi
+ \getdummyparameters[#parameters]%
+ \page_injections_place
+ \endgroup}
+
+\def\page_injections_place
+ {\edef\currentpageinjectionalternative {\pageinjectionparameter \c!alternative }%
+ \edef\p_page_injectionalternative_rederingsetup{\pageinjectionalternativeparameter\c!renderingsetup}%
+ \page_injections_nextpage
+ \ifx\currentpageinjectionalternative\v!none \else % increment counter but don’t generate output
+ \invokepagehandler\v!normal{\inheritedpageinjectionframed{\texsetup\p_page_injectionalternative_rederingsetup}}%
+ \fi}
+
+\def\page_injections_nextpage
+ {\edef\p_page_injections_pagestate{\pageinjectionparameter\c!pagestate}%
+ \ifx\p_page_injections_pagestate\v!stop \else
+ \edef\p_page_injections_n{\pageinjectionparameter\c!n}%
+ \ifx\p_page_injections_n\empty
+ \let\p_page_injections_n\plusone
+ \fi
+ \dorecurse\p_page_injections_n
+ {\incrementcounter[\s!realpage]%
+ \incrementcounter[\s!userpage]}%
+ \fi}
+
+\definepageinjectionalternative[\v!figure][\c!renderingsetup=\??pageinjectionrenderings:\v!figure]
+\definepageinjectionalternative[\v!buffer][\c!renderingsetup=\??pageinjectionrenderings:\v!buffer]
+\definepageinjectionalternative[\v!setups][\c!renderingsetup=\??pageinjectionrenderings:\s!setup ]
+
+\startsetups[\??pageinjectionrenderings:\v!figure]
+ \dontleavehmode\externalfigure[\dummyparameter\c!name][\c!factor=\v!max]
+\stopsetups
+
+\startsetups[\??pageinjectionrenderings:\s!setup]
+ \setups[\dummyparameter\c!setup]% kind of redundant but fits in
+\stopsetups
+
+\startsetups[\??pageinjectionrenderings:\v!buffer]
+ \getbuffer[\dummyparameter\c!name]%
+\stopsetups
+
+% \setuppaper
+% [\c!method=\v!pageinjection]
+
+\setuppageinjection
+ [ \c!width=\paperwidth,
+ \c!height=\paperheight,
+ \c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!delay=\v!no,
+ \c!state=\v!next,
+ \c!alternative=\v!figure]
+
+\definepageinjection[\v!previouspage][\c!delay=\v!yes,\c!state=\v!previous]
+\definepageinjection[\v!nextpage] [\c!delay=\v!yes,\c!state=\v!next]
+\definepageinjection[\v!here] % direct
+\definepageinjection[\v!empty] [\c!alternative=\v!none]
+
+%definepageinjection[\v!chapter] [\v!previouspage][\c!pagestate=\v!stop]
+
+\protect \endinput
+
+% \enabletrackers[pagebuilder.injections]
+%
+% \setuppageinjection[offset=2em]
+%
+% \definepageinjection[chapter][previouspage][pagestate=stop]
+% \definepageinjection[later] [delay=yes,state=+2]
+%
+% \useMPlibrary[dum]
+%
+% \starttext
+%
+% \startchapter[title={Insert pages before/after the current page}]
+%
+% \dorecurse{10}{one: \input ward\par}
+%
+% \pageinjection[previouspage][name=dummy-1]
+%
+% \dorecurse{20}{two: \input ward\par} \page
+%
+% \pageinjection[nextpage][name=dummy-2]
+% \pageinjection[later] [name=dummy-4]
+% \pageinjection[delay=yes,state=+2][name=dummy-5]
+%
+% \dorecurse{100}{three: \input ward\par}
+%
+% \stopchapter
+%
+% \startbuffer[whatever]
+% \dorecurse{10}{whatever #1 }
+% \stopbuffer
+%
+% \startchapter[title={Insert pages at the current location}]
+%
+% \dorecurse{10}{\input ward\par}
+%
+% \pageinjection[direct][name=dummy-3]
+% \pageinjection[direct][alternative=buffer,name=whatever]
+%
+% \dorecurse{10}{\input ward\par}
+%
+% \stopchapter
+%
+% \setuphead
+% [chapter]
+% [beforesection={\pageinjection[empty]},
+% insidesection={\pageinjection[chapter][name=\structureuservariable{image}]}]
+%
+% \startchapter[title={Combine both mechanism}][name=dummy-4]
+%
+% \dorecurse{10}{\input ward\par}
+%
+% \stopchapter
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ins.lua b/Master/texmf-dist/tex/context/base/mkiv/page-ins.lua
new file mode 100644
index 00000000000..235f586c689
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-ins.lua
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['page-ins'] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local next = next
+
+structures = structures or { }
+structures.inserts = structures.inserts or { }
+local inserts = structures.inserts
+
+local report_inserts = logs.reporter("inserts")
+
+local allocate = utilities.storage.allocate
+
+inserts.stored = inserts.stored or allocate { } -- combining them in one is inefficient in the
+inserts.data = inserts.data or allocate { } -- bytecode storage pool
+
+local variables = interfaces.variables
+local v_page = variables.page
+local v_columns = variables.columns
+local v_firstcolumn = variables.firstcolumn
+local v_lastcolumn = variables.lastcolumn
+local v_text = variables.text
+
+local context = context
+local implement = interfaces.implement
+
+storage.register("structures/inserts/stored", inserts.stored, "structures.inserts.stored")
+
+local data = inserts.data
+local stored = inserts.stored
+
+for name, specification in next, stored do
+ data[specification.number] = specification
+ data[name] = specification
+end
+
+function inserts.define(name,specification)
+ specification.name= name
+ local number = specification.number or 0
+ data[name] = specification
+ data[number] = specification
+ -- only needed at runtime as this get stored in a bytecode register
+ stored[name] = specification
+ if not specification.location then
+ specification.location = v_page
+ end
+ return specification
+end
+
+function inserts.setup(name,settings)
+ local specification = data[name]
+ for k, v in next, settings do
+ -- maybe trace change
+ specification[k] = v
+ end
+ return specification
+end
+
+function inserts.setlocation(name,location) -- a practical fast one
+ data[name].location = location
+end
+
+function inserts.getlocation(name,location)
+ return data[name].location or v_page
+end
+
+function inserts.getdata(name) -- or number
+ return data[name]
+end
+
+function inserts.getname(number)
+ return data[name].name
+end
+
+function inserts.getnumber(name)
+ return data[name].number
+end
+
+-- interface
+
+implement {
+ name = "defineinsertion",
+ actions = inserts.define,
+ arguments = {
+ "string",
+ {
+ { "number", "integer" }
+ }
+ }
+}
+
+implement {
+ name = "setupinsertion",
+ actions = inserts.setup,
+ arguments = {
+ "string",
+ {
+ { "location" }
+ }
+ }
+}
+
+implement {
+ name = "setinsertionlocation",
+ actions = inserts.setlocation,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "insertionnumber",
+ actions = function(name) context(data[name].number or 0) end,
+ arguments = "string"
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ins.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-ins.mkiv
new file mode 100644
index 00000000000..c91073a143d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-ins.mkiv
@@ -0,0 +1,186 @@
+%D \module
+%D [ file=core-ins,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Insertion Macros,
+%D subtitle=Insertions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Insertions}
+
+%D Insertions are special data collections that are associated to \TEX's internal
+%D page builder. When multiple footnote classes were introduced, I decided to
+%D isolate some of the functionality in a module.
+
+\registerctxluafile{page-ins}{1.001}
+
+\unprotect
+
+%D Because we need to deal with inserts at the \LUA\ end as well,
+%D we provide a proper installer.
+
+% Not yet used as we need to adapt some code to this.
+
+\installcorenamespace{insertion}
+\installcorenamespace{insertionnumber}
+
+\installcommandhandler \??insertion {insertion} \??insertion
+
+\setupinsertion
+ [%c!n=\plusone,
+ %c!distance=\zeropoint,
+ %c!maxheight=\maxdimen,
+ %c!factor=\plusthousand,
+ \c!location=\v!page]
+
+\newcount\currentinsertionnumber % This is a count and not a macro !
+
+\newtoks\t_page_inserts_list
+
+\let\doprocessinsert\relax
+
+%D Maybe some day we will move settings here.
+
+\unexpanded\def\setcurrentinsertion#1%
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
+
+\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname}
+
+\unexpanded\def\page_inserts_synchronize_registers
+ {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
+
+% for practical reasone we still set these elsewhere but that might chaneg in the future
+%
+% \global\count\currentinsertionnumber\numexpr\insertionparameter\c!factor/\insertionparameter\c!n\relax
+% \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax
+% \global\dimen\currentinsertionnumber\insertionparameter\c!maxheight\relax}
+
+\appendtoks
+ \page_inserts_synchronize_registers
+\to \everysetupinsertion
+
+\unexpanded\def\page_inserts_process#1% beware, this addapts currentinsertion !
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
+ \doprocessinsert\currentinsertionnumber} % old method
+
+\unexpanded\def\processinsertions
+ {\the\t_page_inserts_list}
+
+\unexpanded\def\synchronizeinsertions
+ {\let\doprocessinsert\page_inserts_synchronize
+ \processinsertions}
+
+\unexpanded\def\page_inserts_synchronize#1% yes or no
+ {\ifvoid#1\else
+ \insert#1{\unvbox#1}%
+ \fi}
+
+\unexpanded\def\doifelseinsertion#1%
+ {\ifcsname\??insertionnumber#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifinsertionelse\doifelseinsertion
+
+% \unexpanded\def\startinsertion[#1]%
+% {\insert\csname\??insertionnumber#1\endcsname\bgroup}
+%
+% \unexpanded\def\stopinsertion
+% {\egroup}
+
+% For the moment we use the regular insertion allocator so that users can
+% still define their own insertions (not that they will play nicely with
+% all context mechanisms then). We can use the dimensions at the \LUA\ end
+% so we don't need to pass pass them explicitly. Actually, when we see an
+% insertion node at that end, we already know the number.
+
+\appendtoks
+ \ifx\currentinsertionparent\empty
+ \ifcsname\??insertionnumber\currentinsertion\endcsname
+ % bad news
+ \else
+ \expandafter\newinsert\csname\??insertionnumber\currentinsertion\endcsname
+ \page_inserts_synchronize_registers
+ \clf_defineinsertion
+ {\currentinsertion}%
+ {%
+ number \currentinsertionnumber
+ }%
+ \relax
+ \t_page_inserts_list\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_page_inserts_list
+ \expandafter\page_inserts_process\csname\??insertionnumber\currentinsertion\endcsname}%
+ \count\currentinsertionnumber\plusthousand
+ \skip \currentinsertionnumber\zeropoint
+ \dimen\currentinsertionnumber\maxdimen
+ \fi
+ \else
+ \expandafter\let\csname\??insertionnumber\currentinsertion\expandafter\endcsname
+ \csname\??insertionnumber\currentinsertionparent\endcsname
+ \fi
+\to \everydefineinsertion
+
+\appendtoks
+ \clf_setupinsertion
+ {\currentinsertion}
+ {%
+ location {\insertionparameter\c!location}%
+ }%
+ \relax
+\to \everysetupinsertion
+
+\unexpanded\def\page_inserts_set_location#1#2% fast one
+ {\clf_setinsertionlocation{#1}{#2}}
+
+%D Auxiliary macros:
+
+\def\page_insert_insertion_height#1%
+ {\dimexpr\expandafter\page_insert_insertion_height_indeed\csname\??insertionnumber#1\endcsname\relax}
+
+\def\page_insert_insertion_height_indeed#1%
+ {\ifvoid#1\zeropoint\else1\skip#1+\ht#1\fi}
+
+%D Obsolete:
+
+% \installcorenamespace{insertionbackup}
+%
+% \unexpanded\def\installbackupinsertion#1%
+% {\ifcsname\??insertionbackup\string#1\endcsname \else
+% \expandafter\newinsert\csname\??insertionbackup\string#1\endcsname
+% \count\csname\??insertionbackup\string#1\endcsname\zerocount
+% \skip \csname\??insertionbackup\string#1\endcsname\zeropoint
+% \dimen\csname\??insertionbackup\string#1\endcsname\maxdimen
+% \fi}
+%
+% \unexpanded\def\saveinsertionbox#1% hm, actually unknown
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname
+% \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi}
+%
+% \unexpanded\def\restoreinsertionbox#1%
+% {\ifvoid\backupinsertion#1\else % if void, we keep the content
+% \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname
+% \fi}
+%
+% \unexpanded\def\eraseinsertionbackup#1%
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox}
+%
+% \unexpanded\def\saveinsertiondata#1%
+% {\global\skip \csname\??insertionbackup\string#1\endcsname\skip #1%
+% \global\count\csname\??insertionbackup\string#1\endcsname\count#1%
+% \global\dimen\csname\??insertionbackup\string#1\endcsname\dimen#1}
+%
+% \unexpanded\def\restoreinsertiondata#1%
+% {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname
+% \global\count#1\count\csname\??insertionbackup\string#1\endcsname
+% \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv
new file mode 100644
index 00000000000..1fde9e9c9c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv
@@ -0,0 +1,1632 @@
+%D \module
+%D [ file=page-lay,
+%D version=2000.10.20, % copied from main-001
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Layout Specification,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Layout Specification}
+
+%D Before you start wondering why some of the page related
+%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.
+
+\unprotect
+
+%D The dimensions related to layout areas are represented by
+%D real dimensions.
+
+\newdimen\paperheight \paperheight = 297mm
+\newdimen\paperwidth \paperwidth = 210mm
+\newdimen\paperoffset \paperoffset = \zeropoint
+\newdimen\paperbleed \paperbleed = \zeropoint
+\newdimen\spinewidth \spinewidth = \zeropoint
+
+\newdimen\printpaperheight \printpaperheight = \paperheight
+\newdimen\printpaperwidth \printpaperwidth = \paperwidth
+
+\newdimen\makeupheight % calculated
+\newdimen\makeupwidth % calculated
+
+\newdimen\textheight % calculated
+\newdimen\textwidth % calculated
+
+\newdimen\topspace \topspace = 2cm
+\newdimen\backspace \backspace = \topspace
+\newdimen\cutspace \cutspace = \zeropoint
+\newdimen\bottomspace \bottomspace = \zeropoint
+
+\newdimen\headerheight \headerheight = 2cm
+\newdimen\footerheight \footerheight = \headerheight
+
+\newdimen\topoffset \topoffset = \zeropoint
+\newdimen\backoffset \backoffset = \topoffset
+
+\newdimen\leftmarginwidth \leftmarginwidth = 3cm
+\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth
+
+\newdimen\leftedgewidth \leftedgewidth = 3cm
+\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth
+
+\newdimen\topheight \topheight = \zeropoint
+\newdimen\bottomheight \bottomheight = \topheight
+
+\newcount\layoutlines \layoutlines = \zerocount
+\newcount\layoutcolumns \layoutcolumns = \zerocount
+\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint
+\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint
+
+\newdimen\totaltextwidth
+
+%D The next series of dimensions are complemented by left
+%D 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 The horizontal distances are:
+
+\newdimen\leftedgedistance
+\newdimen\rightedgedistance
+\newdimen\leftmargindistance
+\newdimen\rightmargindistance
+
+%D The vertical distances are:
+
+\newdimen\topdistance
+\newdimen\headerdistance
+\newdimen\footerdistance
+\newdimen\bottomdistance
+
+%D We need to calculate the extra distances:
+
+\newdimen\naturalmarginwidth
+\newdimen\naturaledgewidth
+\newdimen\naturalmargindistance
+\newdimen\naturaledgedistance
+\newdimen\naturalleftedgedistance
+\newdimen\naturalrightedgedistance
+\newdimen\naturalleftmargindistance
+\newdimen\naturalrightmargindistance
+\newdimen\naturaltopdistance
+\newdimen\naturalheaderdistance
+\newdimen\naturalfooterdistance
+\newdimen\naturalbottomdistance
+
+%D Now we've come to the setup and definition commands.
+
+\installcorenamespace{layout}
+\installcorenamespace{layoutlocation}
+\installcorenamespace{layoutalternative}
+\installcorenamespace{layoutcolumn}
+\installcorenamespace{layoutmethod}
+
+\installswitchcommandhandler \??layout {layout} \??layout
+
+\appendtoks
+ \doifnothing{\strictlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}%
+\to \everydefinelayout
+
+\appendtoks
+ \ifcase\layoutsetupmode
+ % can't happen
+ \or % \setuplayout[name][key=value]
+ \ifx\previouslayout\currentlayout
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \let\currentlayout\currentlayout
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \fi
+ \or % \setuplayout[key=value]
+ % we can inherit so we always synchronize
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \let\currentlayout\previouslayout
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \or % \setuplayout[name]
+ \ifx\currentlayout\v!reset
+ \let\currentlayout\empty
+ \fi
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \global\let\currentlayout\currentlayout % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \or % \setuplayout (reverts to main layout)
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \global\let\currentlayout\empty % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \fi
+\to \everysetuplayout
+
+\def\doifelselayoutdefined#1%
+ {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflayoutdefinedelse\doifelselayoutdefined
+
+\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi}
+
+\def\page_layouts_set_dimensions
+ {\global\naturalmarginwidth \layoutparameter\c!margin
+ \global\naturaledgewidth \layoutparameter\c!edge
+ \global\naturalmargindistance \layoutparameter\c!margindistance
+ \global\naturaledgedistance \layoutparameter\c!edgedistance
+ \global\naturalleftedgedistance \layoutparameter\c!leftedgedistance
+ \global\naturalrightedgedistance \layoutparameter\c!rightedgedistance
+ \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance
+ \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance
+ \global\naturaltopdistance \layoutparameter\c!topdistance
+ \global\naturalheaderdistance \layoutparameter\c!headerdistance
+ \global\naturalfooterdistance \layoutparameter\c!footerdistance
+ \global\naturalbottomdistance \layoutparameter\c!bottomdistance
+ %
+ \global\marginwidth \naturalmarginwidth
+ \global\edgewidth \naturaledgewidth
+ \global\margindistance \naturalmargindistance
+ \global\edgedistance \naturaledgedistance
+ %
+ \global\leftedgedistance \layoutdistance\leftedgewidth \naturalleftedgedistance
+ \global\rightedgedistance \layoutdistance\rightedgewidth \naturalrightedgedistance
+ \global\leftmargindistance \layoutdistance\leftmarginwidth \naturalleftmargindistance
+ \global\rightmargindistance \layoutdistance\rightmarginwidth\naturalrightmargindistance
+ \global\topdistance \layoutdistance\topheight \naturaltopdistance
+ \global\headerdistance \layoutdistance\headerheight \naturalheaderdistance
+ \global\footerdistance \layoutdistance\footerheight \naturalfooterdistance
+ \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance
+ }
+
+\def\page_layouts_set_distances % local in \setreducedvsize
+ {\headerdistance\layoutdistance\headerheight\naturalheaderdistance
+ \footerdistance\layoutdistance\footerheight\naturalfooterdistance}
+
+% these are wrong in the running text, assumes some swapping, needs a cleanup
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace\backspace}
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace}
+
+\newtoks\extralayoutcalculations
+
+\def\page_layouts_calculate_extras
+ {\the\extralayoutcalculations}
+
+\newtoks\everyswapmargins % watch the order !
+
+\appendtoks
+ \swapdimens\leftmargindistance\rightmargindistance
+ \swapdimens\leftedgedistance \rightedgedistance
+ \swapdimens\leftmarginwidth \rightmarginwidth
+ \swapdimens\leftedgewidth \rightedgewidth
+ %
+ \swapmacros\leftmargintotal \rightmargintotal
+ \swapmacros\leftedgetotal \rightedgetotal
+ \swapmacros\leftsidetotal \rightsidetotal
+ \swapmacros\leftcombitotal \rightcombitotal
+ \swapmacros\innermargintotal \outermargintotal
+ \swapmacros\inneredgetotal \outeredgetotal
+ \swapmacros\innercombitotal \outercombitotal
+ \swapmacros\innersidetotal \outersidetotal
+\to \everyswapmargins
+
+%D The papersize macros have a long history and we don't want
+%D to change the commands so they keep looking a bit complex.
+
+%D \macros
+%D {definepapersize}
+%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
+%D \showsetup{definepapersize}
+%D
+%D Yet undocumented, let's see if it gets noticed.
+%D
+%D \starttyping
+%D \definepapersize[main] [A4] [A4]
+%D \definepapersize[extra][A4,landscape][A4,landscape]
+%D
+%D \starttext
+%D \setuppapersize[main]
+%D Page 1. \page
+%D Page 2. \page
+%D \setuppapersize[extra]
+%D Page 2 \page
+%D \setuppapersize[main]
+%D Page 3. \page
+%D Page 4. \page
+%D \adaptpapersize[extra]
+%D Page 5. \page
+%D Page 6. \page
+%D \stoptext
+%D \stoptyping
+%D
+%D \macros
+%D {setuppaper,setuppapersize}
+%D
+%D When setting up the papersize on which to typeset and
+%D print, we can also determine some more characteristics.
+%D
+%D \showsetup{setuppapersize}
+%D
+%D We keep track of these features with the following
+%D variables.
+
+\installcorenamespace{layouttarget}
+\installcorenamespace{layoutpaper}
+\installcorenamespace{layoutprint}
+\installcorenamespace{layoutcurrent}
+
+\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler
+
+\newconditional\c_page_target_paper_mirror
+\newconstant \c_page_target_paper_orientation
+\newconstant \c_page_target_paper_reverse
+\newconditional\c_page_target_paper_landscape
+\newconditional\c_page_target_paper_negate
+
+\newconditional\c_page_target_print_mirror
+\newconstant \c_page_target_print_orientation
+\newconstant \c_page_target_print_reverse
+\newconditional\c_page_target_print_landscape
+\newconditional\c_page_target_print_negate
+\newconditional\c_page_target_print_doublesided
+
+\let\v_page_target_left_fill \relax
+\let\v_page_target_right_fill \relax
+\let\v_page_target_top_fill \relax
+\let\v_page_target_bottom_fill\relax
+
+\let\papersize \empty
+\let\printpapersize\empty
+
+\def\v_page_target_top {\namedlayouttargetparameter\papersize\c!top }
+\def\v_page_target_bottom {\namedlayouttargetparameter\papersize\c!bottom}
+\def\v_page_target_left {\namedlayouttargetparameter\papersize\c!left }
+\def\v_page_target_right {\namedlayouttargetparameter\papersize\c!right }
+\def\v_page_target_method {\rootlayouttargetparameter \c!method}
+\def\v_page_target_scale {\rootlayouttargetparameter \c!scale }
+\def\v_page_target_nx {\numexpr\rootlayouttargetparameter \c!nx \relax}
+\def\v_page_target_ny {\numexpr\rootlayouttargetparameter \c!ny \relax}
+\def\v_page_target_dx {\dimexpr\rootlayouttargetparameter \c!dx \relax}
+\def\v_page_target_dy {\dimexpr\rootlayouttargetparameter \c!dy \relax}
+\def\v_page_target_width {\dimexpr\rootlayouttargetparameter \c!width \relax}
+\def\v_page_target_height {\dimexpr\rootlayouttargetparameter \c!height \relax}
+\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter \c!topspace \relax}
+\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter \c!backspace\relax}
+\def\v_page_target_offset {\dimexpr\rootlayouttargetparameter \c!offset \relax}
+
+\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax}
+
+% Normally we will not use this command directly but for now it
+% works out okay. In the future we might use more of the related
+% commands.
+
+\setuplayouttarget
+ [% these are rather special
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!backspace=\zeropoint,
+ \c!width=\zeropoint,
+ \c!height=\zeropoint,
+ %
+ \c!method=\v!normal,
+ \c!option=\v!max,
+ \c!alternative=\v!normal,
+ %
+ \c!scale=1,
+ \c!offset=\zeropoint,
+ %
+ \c!top=,
+ \c!bottom=,
+ \c!left=,
+ \c!right=,
+ %
+ \c!location=]
+
+% \definepapersize[name][A4][A3]
+% \definepapersize[name][settings]
+
+\unexpanded\def\definepapersize
+ {\dotripleempty\page_paper_define_size}
+
+\def\page_paper_define_size[#1][#2][#3]%
+ {\edef\currentlayouttarget{#1}%
+ \ifx\currentlayouttarget\empty
+ % invalid target
+ \else
+ \doifelseassignment{#2}
+ {\definelayouttarget[#1][#2]}
+ {\setevalue{\??layoutpaper#1}{#2}%
+ \setevalue{\??layoutprint#1}{#3}}%
+ \fi}
+
+\appendtoks
+ \letvalue{\??layoutcurrent\currentlayouttarget}\relax
+\to \everydefinelayouttarget
+
+%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi}
+%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi}
+
+\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi}
+\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi}
+
+% \setuppaper [page=A4,paper=A3] % the k/v variant, changes the current page mapping
+% \setuppapersize[A4][a=b,c=d] % the k/v variant, changes nothing, just settings
+% \setuppapersize[A4][A3] % changes the current page mapping
+
+\let\page_paper_reinstate\relax
+\let\page_paper_restore \relax
+
+\unexpanded\def\setuppapersize
+ {\dodoubleempty\page_paper_setup_size}
+
+\unexpanded\def\page_paper_setup_size[#1][#2]%
+ {\iffirstargument
+ \doifelseassignment{#1}
+ {\page_paper_setup_size_settings[#1]}
+ {\doifelseassignment{#2}
+ {\page_paper_setup_size_settings_by_name[#1][#2]}
+ {\page_paper_setup_size_change_size[#1][#2]}}%
+ \else
+ \page_paper_restore
+ \fi}
+
+\unexpanded\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size
+ {\let\currentlayouttarget\empty
+ \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
+ \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
+ \setupcurrentlayouttarget[#1]%
+ \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
+ \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
+ \ifx\m_layouttarget_paper_saved\m_layouttarget_paper
+ \ifx\m_layouttarget_print_saved\m_layouttarget_print
+ % we didn't change the size, maybe only sx or sy or so
+ \else
+ \page_paper_setup_size_settings_recalibrate
+ \fi
+ \else
+ \page_paper_setup_size_settings_recalibrate
+ \fi}
+
+\def\page_paper_setup_size_settings_recalibrate
+ {\ifx\m_layouttarget_paper\empty
+ % forget about it
+ \else
+ \ifx\m_layouttarget_print\empty
+ \let\m_layouttarget_print\m_layouttarget_paper
+ \fi
+ \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]%
+ \fi
+ \letlayouttargetparameter\c!page \papersize
+ \letlayouttargetparameter\c!paper\printpapersize}
+
+\unexpanded\def\page_paper_setup_size_settings_by_name[#1][#2]%
+ {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}%
+ \setuplayouttarget[#2]}
+
+\unexpanded\def\page_paper_setup_size_change_size[#1][#2]%
+ {\doifelsenothing{#2}
+ {\page_paper_set_current[#1][#1]}
+ {\page_paper_set_current[#1][#2]}}
+
+\let\setuppaper\page_paper_setup_size_settings
+
+\unexpanded\def\adaptpapersize
+ {\global\let\page_paper_reinstate\page_paper_reinstate_indeed
+ \setuppapersize}
+
+\unexpanded\def\page_paper_reinstate_indeed
+ {\page_paper_restore
+ \global\let\page_paper_reinstate\relax}
+
+\appendtoks
+ \page_paper_reinstate
+\to \everyaftershipout
+
+\unexpanded\def\page_paper_set_restore#1#2%
+ {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}}
+
+\unexpanded\def\page_paper_set_current[#1][#2]%
+ {\normalexpanded{\page_paper_set_current_indeed
+ [\page_paper_the_paper_size{#1}]%
+ [\page_paper_the_print_size{#2}]}}
+
+\setvalue{\??layoutpaper\v!reset }{\global\setfalse\c_page_target_paper_landscape
+ \global\setfalse\c_page_target_paper_mirror
+ \global\setfalse\c_page_target_paper_negate
+ \global\c_page_target_paper_orientation\uprotationangle
+ \global\c_page_target_paper_reverse \uprotationangle}
+\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape}
+\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror}
+\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate}
+\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle
+ \global\c_page_target_paper_reverse \leftrotationangle}
+\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle
+ \global\c_page_target_paper_reverse \leftrotationangle}
+\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle
+ \global\c_page_target_paper_reverse \zerocount}
+\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle
+ \global\c_page_target_paper_reverse \rightrotationangle}
+
+\setvalue{\??layoutprint\v!reset }{\global\setfalse\c_page_target_print_landscape
+ \global\setfalse\c_page_target_print_mirror
+ \global\setfalse\c_page_target_print_negate
+ \global\c_page_target_print_orientation\uprotationangle
+ \global\c_page_target_print_reverse \uprotationangle}
+\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape}
+\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror}
+\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate}
+\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle
+ \global\c_page_target_print_reverse \leftrotationangle}
+\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle
+ \global\c_page_target_print_reverse \leftrotationangle}
+\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle
+ \global\c_page_target_print_reverse \zerocount}
+\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle
+ \global\c_page_target_print_reverse \rightrotationangle}
+
+%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi}
+%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi}
+
+\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname}
+\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname}
+
+\unexpanded\def\page_paper_identify_target#1%
+ {\ifcsname\??layoutcurrent#1\endcsname
+ \edef\currentlayouttarget{#1}%
+ \fi}
+
+\unexpanded\def\page_paper_set_current_indeed[#1][#2]%
+ {\edef\m_page_asked_paper{\v!reset,#1}% can be the restores
+ \edef\m_page_asked_print{\v!reset,#2}%
+ %
+ \page_paper_set_restore\m_page_asked_paper\m_page_asked_print
+ %
+ % locate page target
+ \let\currentlayouttarget\empty
+ \processcommacommand[\m_page_asked_paper]\page_paper_identify_target
+ \ifx\currentlayouttarget\empty
+ \let\currentlayouttarget\currentpage
+ \fi
+ \global\let\papersize\currentlayouttarget
+ \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option
+ \global\paperwidth \layouttargetparameter\c!width \relax
+ \global\paperheight\layouttargetparameter\c!height\relax
+ \ifdim\paperwidth<\onepoint
+ \global\paperwidth\onepoint
+ \fi
+ \ifdim\paperheight<\onepoint
+ \global\paperheight\onepoint
+ \fi
+ \ifconditional\c_page_target_paper_landscape
+ \doglobal\swapdimens\paperwidth\paperheight
+ \fi
+ \ifinpagebody % local freeze
+ \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}%
+ \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}%
+ \fi
+ %
+ \page_paper_set_offsets
+ % locate paper target
+ \processcommacommand[\m_page_asked_print]\page_paper_identify_target
+ \global\let\printpapersize\currentlayouttarget
+ \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option
+ \global\printpaperwidth \layouttargetparameter\c!width \relax
+ \global\printpaperheight\layouttargetparameter\c!height\relax
+ \ifdim\printpaperwidth<\onepoint
+ \global\printpaperwidth\paperwidth
+ \fi
+ \ifdim\printpaperheight<\onepoint
+ \global\printpaperheight\paperheight
+ \fi
+ \ifconditional\c_page_target_print_landscape
+ \globalswapdimens\printpaperwidth\printpaperheight
+ \fi
+ % this check can be confusing, so we've added the possibility
+ % to bypass this test: \setuppapersize[option=fit]
+ \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}%
+ \ifx\m_page_asked_option\v!max % \v!fit is
+ \begingroup
+ % we need to pre-swap else we get the wrong paper size
+ \ifnum\c_page_target_paper_orientation=\rightrotationangle
+ \swapdimens\paperwidth\paperheight
+ \else\ifnum\c_page_target_paper_orientation=\leftrotationangle
+ \swapdimens\paperwidth\paperheight
+ \fi\fi
+ \ifnum\c_page_target_print_orientation=\rightrotationangle
+ \swapdimens\printpaperwidth\printpaperheight
+ \else\ifnum\c_page_target_print_orientation=\leftrotationangle
+ \swapdimens\printpaperwidth\printpaperheight
+ \fi\fi
+ \ifdim\paperheight>\printpaperheight
+ \global\printpaperheight\paperheight
+ \writestatus\m!system{print height forced to paper height}%
+ \fi
+ \ifdim\paperwidth>\printpaperwidth
+ \global\printpaperwidth\paperwidth
+ \writestatus\m!system{print width forced to paper width}%
+ \fi
+ \endgroup
+ \fi
+ %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}%
+ \page_layouts_synchronize
+ % new but we assume \setuplayout
+ \scrn_canvas_synchronize_only}
+
+\ifdefined\scrn_canvas_synchronize_only \else
+ \let\scrn_canvas_synchronize_only\relax
+\fi
+
+\ifdefined\page_paper_set_offsets \else
+
+ \def\page_paper_set_offsets % will move
+ {\global\paperoffset\v_page_target_offset
+ \global\advance\paperwidth -2\paperoffset
+ \global\advance\paperheight-2\paperoffset}
+
+\fi
+
+\ifdefined\setups \else
+ \unexpanded\def\setups[#1]{\setdefaultpenalties} % still needed?
+\fi
+
+\ifdefined\synchronizegridsnapping \else
+ \let\synchronizegridsnapping\relax
+\fi
+
+\let\p_page_layouts_width \empty
+\let\p_page_layouts_height\empty
+
+\def\page_layouts_synchronize
+ {\setups[\layoutparameter\c!preset]\relax
+ \global\leftmarginwidth \layoutparameter\c!leftmargin
+ \global\rightmarginwidth\layoutparameter\c!rightmargin
+ \global\leftedgewidth \layoutparameter\c!leftedge
+ \global\rightedgewidth \layoutparameter\c!rightedge
+ \global\headerheight \layoutparameter\c!header
+ \global\footerheight \layoutparameter\c!footer
+ \global\bottomheight \layoutparameter\c!bottom
+ \global\topheight \layoutparameter\c!top
+ \global\backspace \layoutparameter\c!backspace
+ \global\topspace \layoutparameter\c!topspace
+ \page_layouts_set_dimensions
+ \synchronizegridsnapping
+ \usesetupsparameter\layoutparameter % depends on gridsnapping !
+ \synchronizewhitespace
+ \synchronizeblank
+ \setupinterlinespace[\v!reset]% \synchronizegloballinespecs
+ \global\cutspace\layoutparameter\c!cutspace\relax
+ \edef\p_page_layouts_width{\layoutparameter\c!width}%
+ \ifx\p_page_layouts_width\v!middle
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax
+ \else\ifx\p_page_layouts_width\v!fit
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax
+ \scratchdimen\dimexpr\backspace
+ -\leftedgewidth -\leftedgedistance
+ -\leftmarginwidth-\leftmargindistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupwidth\dimexpr
+ -\rightmargindistance-\rightmarginwidth
+ -\rightedgedistance -\rightedgewidth
+ -\scratchdimen\relax
+ \else
+ \global\makeupwidth\p_page_layouts_width\relax
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax
+ % \else
+ % A kind of inconsistent specification, but used
+ % in for instance s-pre-19.tex; the cutspace is
+ % used only for determining some kind of right
+ % margin; don't use this in doublesided mode
+ \fi
+ \fi\fi
+ \scratchdimen\layoutparameter\c!bottomspace\relax
+ %\ifdim\scratchdimen=\zeropoint
+ % \scratchdimen\topspace
+ %\fi
+ \global\bottomspace\layoutparameter\c!bottomspace\relax
+ \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
+ \ifcase\layoutlines
+ \edef\p_page_layouts_height{\layoutparameter\c!height}%
+ \ifx\p_page_layouts_height\v!middle
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax
+ \else\ifx\p_page_layouts_height\v!fit
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\bottomspace\relax
+ \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax
+ \else
+ \global\makeupheight\layoutparameter\c!height\relax
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
+ % \else
+ % inconsistent specification
+ \fi
+ \fi\fi
+ \else
+ % beware, when the bodyfont changes (switched) this will change as well; implementing
+ % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set
+ % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we
+ % stick to the current method (after a night of experimenting ...2003/10/13)
+ \global\makeupheight\dimexpr
+ \layoutparameter\c!lines\lineheight-\strutheight+\topskip+
+ \headerdistance+\headerheight+\footerdistance+\footerheight\relax
+ \fi
+ \backoffset\layoutparameter\c!horoffset\relax
+ \topoffset \layoutparameter\c!veroffset\relax
+ \ifdim\makeupwidth<\onepoint
+ \global\makeupwidth\onepoint
+ \fi
+ \ifdim\makeupheight<\onepoint
+ \global\makeupheight\onepoint
+ \fi
+ % handy in page builder
+ \global\totaltextwidth\dimexpr
+ \leftedgetotal
+ +\leftmargintotal
+ +\makeupwidth
+ +\rightmargintotal
+ +\rightedgetotal
+ \relax
+ % \page_layouts_check_next % here ?
+ \page_layouts_calculate_extras
+ \page_target_check_centering
+ \calculatehsizes
+ \calculatevsizes
+ \page_layouts_check_pseudo_columns
+ \page_backgrounds_recalculate}
+
+\def\page_layouts_check_pseudo_columns
+ {\global\layoutcolumns\layoutparameter\c!columns
+ \global\layoutcolumndistance\layoutparameter\c!columndistance
+ \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
+ \ifnum\layoutcolumns>\plusone
+ \global\divide\layoutcolumnwidth\layoutcolumns
+ \dorecurse\layoutcolumns\page_layouts_check_pseudo_column
+ \fi}
+
+\def\page_layouts_check_pseudo_column
+ {\setxvalue{\??layoutcolumn\recurselevel}%
+ {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}}
+
+\letvalue{\??layoutcolumn0}\zeropoint
+
+\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs
+ {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname}
+
+\def\page_layouts_synchronize_at_start
+ {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check
+ \page_layouts_synchronize
+ \fi}
+
+\appendtoks
+ \page_layouts_synchronize_at_start % still needed?
+\to \everystarttext
+
+% document:
+%
+% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page]
+%
+% \startstandardmakeup[page=blank] ... \stopstandardmakeup
+
+\ifdefined\lastpage \else \let\lastpage\!!plusone \fi
+
+\def\page_layouts_change#1%
+ {%\writestatus\m!layouts{changing to layout #1}%
+ \xdef\currentlayout{#1}%
+ \page_layouts_synchronize}
+
+\let\changetolayout\page_layouts_change % also public
+
+\def\v_real_page_normal {\the\realpageno}
+\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax}
+
+\def\v_real_page_odd_or_even
+ {\ifodd\pagenoshift
+ \ifodd\realpageno\v!even\else\v!odd \fi
+ \else
+ \ifodd\realpageno\v!odd \else\v!even\fi
+ \fi}
+
+\let\v_real_page_current\v!current
+
+\def\v_real_page_named
+ {\ifnum\lastpage=\realpageno
+ \v!last
+ \else\ifnum\plusone=\realpageno
+ \v!first
+ \else
+ \__unknown__
+ \fi\fi}
+
+\let\v_page_layouts_pre_check\relax
+
+\def\page_layouts_check_default_indeed#1%
+ {\edef\m_page_check{#1}
+ \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}%
+ \ifx\m_page_state\v!start
+ \global\let\v_page_layouts_pre_check\currentlayout
+ \global\let\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \else\ifx\m_page_state\v!repeat
+ \global\let\v_page_layouts_pre_check\relax
+ \global\let\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \fi\fi}
+
+\def\page_layouts_check_revert
+ {\global\let\currentlayout\v_page_layouts_pre_check
+ \global\let\v_page_layouts_pre_check\relax
+ \page_layouts_synchronize}
+
+\def\page_layouts_check_default
+ {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_normal
+ \else\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_reverse
+ \else\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_named
+ \else\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_current
+ \else\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_odd_or_even
+ \else\ifx\v_page_layouts_pre_check\relax
+ % okay
+ \else
+ \page_layouts_check_revert
+ \fi\fi\fi\fi\fi\fi}
+
+\unexpanded\def\installlayoutmethod#1#2%
+ {\setgvalue{\??layoutmethod#1}{#2}}
+
+\installlayoutmethod\v!default{\page_layouts_check_default}
+\installlayoutmethod\v!normal {\page_layouts_check_default}
+
+% \def\page_layouts_check_next
+% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+% \layoutparameter\c!method
+% \else
+% \v!normal
+% \fi\endcsname}
+
+\def\page_layouts_check_next
+ {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+ \lastnamedcs
+ \else
+ \page_layouts_check_default
+ \fi}
+
+\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay
+
+% inheritance
+%
+% \definelayout
+% [test]
+% [width=12cm,
+% height=10cm]
+%
+% \definelayout
+% [more]
+% [test]
+% [height=12cm]
+%
+% testcase
+%
+% \setuppagenumbering[alternative=doublesided]
+%
+% \setuplayout [width=11cm]
+% \definelayout [odd] [backspace=1cm]
+% \definelayout [even] [backspace=4cm]
+% \definelayout [5] [backspace=5cm]
+% \definelayout [6] [backspace=5cm]
+% \definelayout [-2] [backspace=0cm,cutspace=0cm]
+% \definelayout [last] [backspace=0cm,cutspace=0cm]
+%
+% \checkcurrentlayout \showframe
+%
+% \starttext
+% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
+% \stoptext
+
+% Because we want to keep the set parameters as they are we use some
+% helpers to communicate between the several page building related
+% mechanism.
+
+\appendtoks \page_layouts_check_next \to \everystarttext
+\appendtoks \page_layouts_check_next \to \everyaftershipout
+
+\newconditional\c_page_layouts_location_is_set
+\newconditional\c_page_layouts_location_is_middle
+
+\def\page_layouts_location_reset % we start in the left top and mirror right pages
+ {\setfalse\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \relax
+ \let\v_page_target_right_fill \hss % ? \relax
+ \let\v_page_target_top_fill \relax
+ \let\v_page_target_bottom_fill\vss} % \relax}
+
+\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \hss
+ \let\v_page_target_right_fill \relax}
+\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \relax
+ \let\v_page_target_right_fill \hss}
+\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_top_fill \vss
+ \let\v_page_target_bottom_fill\relax}
+\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_top_fill \relax
+ \let\v_page_target_bottom_fill\vss}
+\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set
+ \settrue\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \hss
+ \let\v_page_target_right_fill \hss
+ \let\v_page_target_top_fill \vss
+ \let\v_page_target_bottom_fill\vss}
+\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_right_fill \hss
+ \let\v_page_target_bottom_fill\hss}
+\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided}
+\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided}
+
+\def\page_target_check_centering_indeed#1%
+ % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi}
+ {\begincsname\??layoutlocation#1\endcsname}
+
+\unexpanded\def\page_target_check_centering
+ {\setfalse\c_page_target_print_doublesided
+ \page_layouts_location_reset
+ \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed}
+
+% installers
+
+\def\installlayoutalternative#1#2%
+ {\setgvalue{\??layoutalternative#1}{#2}}
+
+\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box
+ {\setbox#1\vbox
+ {\offinterlineskip
+ \begingroup % needed ?
+ \uselayoutstyleandcolor\c!style\c!color
+ \offinterlineskip
+ \page_layouts_insert_elements % zero size
+ \endgroup
+ \page_insert_body#2#3}}% including footnotes
+
+\installlayoutalternative\v!default{\page_boxes_construct_content_default}
+\installlayoutalternative\v!normal {\page_boxes_construct_content_default}
+
+% \def\page_boxes_construct_content % targetbox flusher box
+% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+% \layoutparameter\c!alternative
+% \else
+% \v!normal
+% \fi\endcsname}
+
+\def\page_boxes_construct_content % targetbox flusher box
+ {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\page_boxes_construct_content_default
+ \fi}
+
+%D \macros
+%D {adaptlayout}
+
+\installcorenamespace{adaptlayout}
+\installcorenamespace{pageadaptations}
+
+\installsetuponlycommandhandler \??adaptlayout {adaptlayout}
+
+\newdimen\d_page_adepts_pushed_text_height
+\newdimen\d_page_adepts_pushed_footer_height
+\newdimen\d_page_adepts_height
+
+\unexpanded\def\adaptlayout
+ {\dodoubleempty\page_adapts_layout}
+
+\def\page_adapts_layout[#1][#2]%
+ {\ifsecondargument
+ \processcommalist[#1]{\page_adapts_layout_register{#2}}%
+ \page_adapts_check
+ \else
+ \page_adapts_layout_indeed{#1}%
+ \fi}
+
+\def\page_adapts_layout_register#1#2%
+ {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}}
+
+\let\p_adapts_height\zeropoint
+\let\p_adapts_lines \zerocount
+
+\def\page_adapts_layout_indeed#1%
+ {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]%
+ \page_adepts_push
+ \edef\p_adapts_height{\adaptlayoutparameter\c!height}%
+ \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}%
+ \ifx\p_adapts_height\v!max
+ \global\d_page_adepts_height\footerheight
+ \else
+ \global\d_page_adepts_height\dimexpr
+ \ifnum\p_adapts_lines=\zerocount
+ \p_adapts_height
+ \else
+ \p_adapts_lines\openlineheight
+ \fi
+ \relax
+ \ifdim\d_page_adepts_height>\footerheight
+ \global\d_page_adepts_height\footerheight
+ \fi
+ \fi
+ \global\advance\textheight \d_page_adepts_height
+ \global\advance\footerheight-\d_page_adepts_height
+ \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}%
+ % this will become a better one (do we need insert correction?)
+ \page_otr_command_set_vsize
+ %
+ \page_backgrounds_recalculate
+ \global\let\page_adepts_push\relax
+ \global\let\page_adepts_pop\page_adepts_pop_indeed}
+
+% \def\page_adapts_check
+% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
+%
+% \def\page_adapts_reset
+% {\ifcsname\??pageadaptations\the\realpageno\endcsname
+% \global\undefinevalue{\??pageadaptations\the\realpageno}%
+% \fi}
+
+\def\page_adapts_check
+ {\begincsname\??pageadaptations\the\realpageno\endcsname}
+
+\def\page_adapts_reset
+ {\ifcsname\??pageadaptations\the\realpageno\endcsname
+ \expandafter\glet\csname\??pageadaptations\the\realpageno\endcsname\relax
+ \fi}
+
+\def\page_adepts_push_indeed
+ {\global\d_page_adepts_pushed_text_height \textheight
+ \global\d_page_adepts_pushed_footer_height\footerheight}
+
+\def\page_adepts_pop_indeed
+ {\global\textheight \d_page_adepts_pushed_text_height
+ \global\footerheight\d_page_adepts_pushed_footer_height
+ \page_layouts_synchronize
+ \global\let\page_adepts_push\page_adepts_push_indeed
+ \global\let\page_adepts_pop\relax}
+
+\appendtoks \page_adapts_check \to \everystarttext
+\appendtoks \page_adapts_reset \to \everyshipout
+
+\let\page_adepts_pop \relax
+\let\page_adepts_push\page_adepts_push_indeed
+
+\unexpanded\def\page_adapts_synchronize % used elsewhere
+ {\page_adepts_pop
+ \page_adapts_check}
+
+\def\page_adapts_status_info % used elsewhere
+ {\ifx\page_adepts_pop\relax \else
+ \space(adept: \the\d_page_adepts_height)\space
+ \fi
+ \the\realpageno}
+
+%D \macros
+%D {startlayout,stoplayout}
+
+\unexpanded\def\startlayout[#1]%
+ {\page
+ \globalpushmacro\currentlayout
+ \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}}
+
+\unexpanded\def\stoplayout
+ {\page
+ \globalpopmacro\currentlayout
+ \setuplayout[\currentlayout]}
+
+% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET
+
+\ifx\doifelselayoutsomeline\undefined % defined in page-txt
+ \let\doifelselayoutsomeline\secondofthreearguments
+\fi
+
+\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+
+\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances}
+\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances}
+
+\def\page_layouts_set_modes
+ {\ifzeropt\headerheight
+ \resetsystemmode\v!header
+ \else
+ \setsystemmode\v!header
+ \fi
+ \ifzeropt\footerheight
+ \resetsystemmode\v!footer
+ \else
+ \setsystemmode\v!footer
+ \fi}
+
+\def\calculatevsizes % name will change
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing
+ \page_layouts_set_modes
+ \resetglobal
+ \page_otr_command_set_vsize}
+
+\def\calculateglobalvsizes % name will change
+ {\global\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing
+ \page_layouts_set_modes
+ \page_otr_command_set_vsize}
+
+\def\calculatereducedvsizes % name will change
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero}
+
+\newdimen\innermakeupwidth % special purpose
+\newdimen\innermakeupmargin % special purpose
+
+\newconditional\innermakeupcompensation \settrue\innermakeupcompensation
+
+\def\compensatedinnermakeupmargin
+ {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax}
+
+\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth
+ {\textwidth\makeupwidth % which is a tricky but valid value
+ \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }%
+ \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}%
+ \ifx\m_currentlayout_text_width\empty \else
+ \textwidth\m_currentlayout_text_width % local
+ \fi
+ \global\innermakeupwidth\textwidth
+ \ifx\m_currentlayout_text_margin\empty
+ \global\innermakeupmargin\zeropoint
+ \else
+ \global\innermakeupmargin\m_currentlayout_text_margin\relax
+ \fi
+ \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax
+ \global\advance\innermakeupwidth-\scratchdimen
+ \advance\textwidth-\scratchdimen} % local
+
+\def\calculatehsizes % name will change
+ {\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.
+
+% #single #left #right
+
+\def\doifelseoddpage
+ {\ifodd\pagenoshift
+ \expandafter\page_layouts_if_odd_else_yes
+ \else
+ \expandafter\page_layouts_if_odd_else_nop
+ \fi}
+
+\let\doifoddpageelse\doifelseoddpage
+
+\def\page_layouts_if_odd_else_yes
+ {\ifodd\realpageno
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_layouts_if_odd_else_nop
+ {\ifodd\realpageno
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\page_layouts_if_odd_else_again#1{\doifelseoddpage}
+
+\def\doifbothsidesoverruled
+ {\ifdoublesided
+ \expandafter\page_layouts_if_odd_else_again
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\doifbothsides% #1 #2 #3
+ {\ifdoublesided
+ \expandafter\page_layouts_if_both_sides
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\page_layouts_if_both_sides
+ {\ifsinglesided
+ \expandafter\firstofthreearguments
+ \else
+ \expandafter\page_layouts_if_odd_else_again
+ \fi}
+
+\newdimen\texthoffset
+
+\def\settexthoffset % name will change
+ {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}
+
+% The next hack is too tricky as we may shipout more pages:
+%
+% \def\freezepagestatechecks
+% {\the\everyfreezepagestatechecks}
+%
+% \newtoks \everyfreezepagestatechecks
+%
+% \appendtoks
+% \doifbothsides
+% {\let\doifbothsides\firstofthreearguments}%
+% {\let\doifbothsides\secondofthreearguments}%
+% {\let\doifbothsides\thirdofthreearguments}%
+% \rightorleftpageaction
+% {\let\rightorleftpageaction\firstoftwoarguments}%
+% {\let\rightorleftpageaction\secondoftwoarguments}%
+% \doifmarginswapelse
+% {\let\doifmarginswapelse\firstoftwoarguments}%
+% {\let\doifmarginswapelse\secondoftwoarguments}%
+% \to \everyfreezepagestatechecks
+%
+% \prependtoks
+% \freezepagestatechecks
+% \to \everybeforeshipout
+
+\def\goleftonpage % name will change (we could cache)
+ {\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
+
+\def\doifelsemarginswap#1#2%
+ {\doifbothsides{#1}{#1}{#2}}
+
+\let\doifmarginswapelse\doifelsemarginswap
+
+\def\swapmargins % name will change
+ {\doifelsemarginswap\relax\doswapmargins}
+
+\def\doswapmargins % name will change
+ {\let\swapmargins \relax % to prevent local swapping
+ \let\doswapmargins\relax % to prevent local swapping
+ \the\everyswapmargins}
+
+\def\rightorleftpageaction
+ {\ifdoublesided
+ \expandafter\page_layouts_right_or_left_page_action
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_layouts_right_or_left_page_action
+ {\ifsinglesided
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\doifelseoddpage
+ \fi}
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace}
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace }
+
+\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax}
+\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax}
+\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax}
+\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax}
+
+\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax}
+\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax}
+\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax}
+\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax}
+
+\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax}
+\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax}
+\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax}
+\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax}
+
+\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax}
+\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax}
+\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax}
+\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax}
+
+%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.
+
+\unexpanded\def\startlocallayout
+ {\globalpushmacro\page_paper_restore
+ \globalpushmacro\currentlayout}
+
+\unexpanded\def\stoplocallayout
+ {\globalpopmacro\currentlayout
+ \globalpopmacro\page_paper_restore
+ \page_paper_restore
+ \setuplayout[\currentlayout]\relax} % explicit !
+
+%D \macros
+%D {showprint, showframe, showlayout, showsetups}
+%D
+%D We predefine a couple of tracing macros.
+%D
+%D \showsetup{showprint}
+%D \showsetup{showframe}
+%D \showsetup{showlayout}
+%D \showsetup{showsetups}
+%D %showsetup{showmargins}
+
+\fetchruntimecommand \showprint {page-run}
+\fetchruntimecommand \showframe {page-run}
+\fetchruntimecommand \showlayout {page-run}
+\fetchruntimecommand \showsetups {page-run}
+\fetchruntimecommand \showmargins {page-run}
+
+%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
+%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.
+
+\setuplayout
+ [ \c!topspace=.08417508418\paperheight, % 2.5cm
+ \c!top=\zeropoint,
+ \c!topdistance=\zeropoint,
+ \c!header=.06734006734\paperheight, % 2.0cm
+ \c!headerdistance=\zeropoint,
+ \c!height=.84175084175\paperheight, % 25.0cm
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=.06734006734\paperheight, % 2.0cm
+ \c!bottomdistance=\layoutparameter\c!topdistance,
+ \c!bottom=\zeropoint,
+ \c!backspace=.11904761905\paperwidth, % 2.5cm
+ \c!edge=\zeropoint,
+ \c!edgedistance=\layoutparameter\c!margindistance,
+ \c!margin=.12649983170\paperwidth, % snijwit-2*afstand
+ \c!margindistance=.02008341748\paperwidth, % 12.0pt
+ \c!leftedge=\layoutparameter\c!edge,
+ \c!leftedgedistance=\layoutparameter\c!edgedistance,
+ \c!leftmargin=\layoutparameter\c!margin,
+ \c!leftmargindistance=\layoutparameter\c!margindistance,
+ \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\
+ \c!rightmargindistance=\layoutparameter\c!margindistance,
+ \c!rightmargin=\layoutparameter\c!margin,
+ \c!rightedgedistance=\layoutparameter\c!edgedistance,
+ \c!rightedge=\layoutparameter\c!edge,
+ \c!veroffset=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!horoffset=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!textwidth=, % dangerous option -> centered / local
+ \c!textmargin=, % dangerous option -> both sides
+ \c!textdistance=\zeropoint, % shift down on grid
+ \c!style=,
+ \c!color=,
+ \c!marking=\v!off,
+ \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange)
+ \c!state=\v!start,
+ \c!scale=1,
+ \c!sx=1,
+ \c!sy=1,
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!grid=\v!no,
+ \c!preset=,
+ \c!setups=\systemsetupsprefix\s!default,
+ \c!clipoffset=\zeropoint,
+ \c!lines=0,
+ \c!paper=, % for foxet
+ \c!page=, % for foxet
+ \c!columns=\plusone,
+ \c!columndistance=\zeropoint]
+
+%D First we define a whole range of (DIN) papersizes,
+%D of which the A-series makes most sense. We enable checking.
+
+\definepapersize [A0] [\c!width=841mm,\c!height=1189mm]
+\definepapersize [A1] [\c!width=594mm,\c!height=841mm]
+\definepapersize [A2] [\c!width=420mm,\c!height=594mm]
+\definepapersize [A3] [\c!width=297mm,\c!height=420mm]
+\definepapersize [A4] [\c!width=210mm,\c!height=297mm]
+\definepapersize [A5] [\c!width=148mm,\c!height=210mm]
+\definepapersize [A6] [\c!width=105mm,\c!height=148mm]
+\definepapersize [A7] [\c!width=74mm,\c!height=105mm]
+\definepapersize [A8] [\c!width=52mm,\c!height=74mm]
+\definepapersize [A9] [\c!width=37mm,\c!height=52mm]
+\definepapersize [A10] [\c!width=26mm,\c!height=37mm]
+
+\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm
+%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide
+
+\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm]
+\definepapersize [B1] [\c!width=707mm,\c!height=1000mm]
+\definepapersize [B2] [\c!width=500mm,\c!height=707mm]
+\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm]
+\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm]
+\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm]
+\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm]
+\definepapersize [B7] [\c!width=88mm,\c!height=125mm]
+\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm]
+\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm]
+\definepapersize [B10] [\c!width=31mm,\c!height=44mm]
+
+\definepapersize [C0] [\c!width=917mm,\c!height=1297mm]
+\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm]
+\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm]
+\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm]
+\definepapersize [C4] [\c!width=229mm,\c!height=324mm]
+\definepapersize [C5] [\c!width=162mm,\c!height=229mm]
+\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm]
+\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm]
+\definepapersize [C8] [\c!width=57mm,\c!height=81mm]
+\definepapersize [C9] [\c!width=40mm,\c!height=57mm]
+\definepapersize [C10] [\c!width=28mm,\c!height=40mm]
+
+%D Per August 2004 the rounding of some (seldom used) sizes
+%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!
+
+\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.
+
+\definepapersize [S3] [\c!width=300pt,\c!height=225pt]
+\definepapersize [S4] [\c!width=400pt,\c!height=300pt]
+\definepapersize [S5] [\c!width=500pt,\c!height=375pt]
+\definepapersize [S6] [\c!width=600pt,\c!height=450pt]
+\definepapersize [S8] [\c!width=800pt,\c!height=600pt]
+\definepapersize [SL] [\c!width=640pt,\c!height=400pt] % low
+\definepapersize [SM] [\c!width=720pt,\c!height=450pt] % medium
+\definepapersize [SW] [\c!width=800pt,\c!height=450pt] % wide
+\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt]
+\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt]
+\definepapersize [HD-] [\c!width=960pt,\c!height=540pt]
+
+%D These are handy too:
+
+\definepapersize [S33] [\c!width=300pt,\c!height=300pt]
+\definepapersize [S44] [\c!width=400pt,\c!height=400pt]
+\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
+\definepapersize [S66] [\c!width=600pt,\c!height=600pt]
+
+%D One may wonder if \TEX\ should be used for typesetting
+%D \CDROM\ covers, but it does not hurt to have the paper size
+%D 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.
+
+\definepapersize [letter] [\c!width=8.5in,\c!height=11in]
+\definepapersize [ledger] [\c!width=11in,\c!height=17in]
+\definepapersize [tabloid] [\c!width=17in,\c!height=11in]
+
+\definepapersize [legal] [\c!width=8.5in,\c!height=14in]
+\definepapersize [folio] [\c!width=8.5in,\c!height=13in]
+\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in]
+
+\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet
+\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets
+\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets
+
+%D The next set is for Tobias Burnus, who gave me the sizes.
+
+\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in]
+\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in]
+\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in]
+\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in]
+\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in]
+\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in]
+\definepapersize [check] [\c!width=8.58in,\c!height=3.88in]
+\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm]
+\definepapersize [E4] [\c!width=280mm,\c!height=400mm]
+
+%D The next three sets are supplied by Taco:
+
+\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm]
+\definepapersize [RA1] [\c!width=610mm,\c!height=860mm]
+\definepapersize [RA2] [\c!width=430mm,\c!height=610mm]
+\definepapersize [RA3] [\c!width=305mm,\c!height=430mm]
+\definepapersize [RA4] [\c!width=215mm,\c!height=305mm]
+
+%D ISO SRA (supplementary raw A) sizes:
+
+\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm]
+\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm]
+\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm]
+\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm]
+\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm]
+
+%D Swedish thesis formats:
+
+\definepapersize [G5] [\c!width=169mm,\c!height=239mm]
+\definepapersize [E5] [\c!width=155mm,\c!height=220mm]
+
+%D Industry invention:
+
+\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm]
+
+%D For Alan:
+
+\definepapersize [business] [\c!width=85mm,\c!height=55mm]
+\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in]
+
+%D We can now default to a reasonable size. We match the print
+%D paper size with the typeset paper size. This setting should
+%D come after the first layout specification (already done).
+
+% \definepapersize
+% [\v!default]
+% [ \c!width=\paperwidth,
+% \c!height=\paperheight]
+
+% \definepapersize
+% [samesized]
+% [ \c!width=\paperwidth,
+% \c!height=\paperheight]
+
+\setuppapersize
+ [\c!distance=1.5cm] % offset is already taken
+
+\definepapersize
+ [oversized]
+ [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [undersized]
+ [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [doublesized]
+ [ \c!width=\dimexpr \paperwidth \relax,
+ \c!height=\dimexpr2\paperheight\relax]
+
+\definepapersize
+ [doubleoversized]
+ [ \c!width=\dimexpr \paperheight+\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr2\paperwidth +\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [doublewide]
+ [ \c!width=\dimexpr2\paperwidth \relax,
+ \c!height=\dimexpr \paperheight\relax]
+
+% \setuppapersize
+% [A4][A4]
+
+\setuppapersize
+ [A4] % [samesized]
+
+%D A few goodies:
+
+\definelayout
+ [\v!page]
+
+\setuplayout
+ [\v!page]
+ [\c!backspace=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!edge=\zeropoint,
+ \c!header=\zeropoint,
+ \c!footer=\zeropoint,
+ \c!top=\zeropoint,
+ \c!bottom=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!leftedge=\zeropoint,
+ \c!rightedge=\zeropoint,
+ \c!textdistance=\zeropoint,
+ \c!width=\v!middle,
+ \c!height=\v!middle,
+ \c!lines=0,
+ \c!grid=\v!no]
+
+\definelayout
+ [\v!middle]
+ [\c!width=\v!middle,
+ \c!height=\v!middle]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua b/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua
new file mode 100644
index 00000000000..5b18d982373
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua
@@ -0,0 +1,521 @@
+if not modules then modules = { } end modules ['page-lin'] = {
+ version = 1.001,
+ comment = "companion to page-lin.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- experimental -> will become builders
+
+-- if there is demand for it, we can support multiple numbering streams
+-- and use more than one attibute
+
+local next, tonumber = next, tonumber
+
+local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end)
+
+local report_lines = logs.reporter("lines")
+
+local attributes = attributes
+local nodes = nodes
+local context = context
+
+local implement = interfaces.implement
+
+nodes.lines = nodes.lines or { }
+local lines = nodes.lines
+
+lines.data = lines.data or { } -- start step tag
+local data = lines.data
+local last = #data
+
+lines.scratchbox = lines.scratchbox or 0
+
+storage.register("lines/data", data, "nodes.lines.data")
+
+local variables = interfaces.variables
+
+local v_next = variables.next
+local v_page = variables.page
+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 glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+local line_code = listcodes.line
+local leftskip_code = skipcodes.leftskip
+
+local a_displaymath = attributes.private('displaymath')
+local a_linenumber = attributes.private('linenumber')
+local a_linereference = attributes.private('linereference')
+local a_verbatimline = attributes.private('verbatimline')
+
+local current_list = { }
+local cross_references = { }
+local chunksize = 250 -- not used in boxed
+
+local nuts = nodes.nuts
+
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getnext = nuts.getnext
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getlist = nuts.getlist
+local getbox = nuts.getbox
+local getfield = nuts.getfield
+
+local setprop = nuts.setprop
+local getprop = nuts.getprop
+
+local setfield = nuts.setfield
+
+local traverse_id = nuts.traverse_id
+local traverse = nuts.traverse
+local copy_node = nuts.copy
+local hpack_nodes = nuts.hpack
+local linked_nodes = nuts.linked
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+local is_display_math = nuts.is_display_math
+local leftmarginwidth = nuts.leftmarginwidth
+
+local nodepool = nuts.pool
+local negated_glue = nodepool.negatedglue
+local new_hlist = nodepool.hlist
+local new_kern = nodepool.kern
+
+local ctx_convertnumber = context.convertnumber
+local ctx_makelinenumber = context.makelinenumber
+
+local paragraphs = typesetters.paragraphs
+local addtoline = paragraphs.addtoline
+local checkline = paragraphs.checkline
+local moveinline = paragraphs.moveinline
+
+-- cross referencing
+
+function lines.number(n)
+ n = tonumber(n)
+ local cr = cross_references[n] or 0
+ cross_references[n] = nil
+ return cr
+end
+
+local function resolve(n,m) -- we can now check the 'line' flag (todo)
+ while n do
+ local id = getid(n)
+ if id == whatsit_code then -- why whatsit
+ local a = getattr(n,a_linereference)
+ if a then
+ cross_references[a] = m
+ end
+ elseif id == hlist_code or id == vlist_code then
+ resolve(getlist(n),m)
+ end
+ n = getnext(n)
+ end
+end
+
+function lines.finalize(t)
+ local getnumber = lines.number
+ for _,p in next, t do
+ for _,r in next, p do
+ local m = r.metadata
+ if m and m.kind == "line" then
+ local e = r.entries
+ local u = r.userdata
+ e.linenumber = getnumber(e.text or 0) -- we can nil e.text
+ e.conversion = u and u.conversion
+ r.userdata = nil -- hack
+ end
+ end
+ end
+end
+
+local filters = structures.references.filters
+local helpers = structures.helpers
+
+structures.references.registerfinalizer(lines.finalize)
+
+filters.line = filters.line or { }
+
+function filters.line.default(data)
+-- helpers.title(data.entries.linenumber or "?",data.metadata)
+ ctx_convertnumber(data.entries.conversion or "numbers",data.entries.linenumber or "0")
+end
+
+function filters.line.page(data,prefixspec,pagespec) -- redundant
+ helpers.prefixpage(data,prefixspec,pagespec)
+end
+
+function filters.line.linenumber(data) -- raw
+ context(data.entries.linenumber or "0")
+end
+
+-- boxed variant, todo: use number mechanism
+
+lines.boxed = { }
+local boxed = lines.boxed
+
+-- todo: cache setups, and free id no longer used
+-- use interfaces.cachesetup(t)
+
+function boxed.register(configuration)
+ last = last + 1
+ data[last] = configuration
+ if trace_numbers then
+ report_lines("registering setup %a",last)
+ end
+ return last
+end
+
+implement {
+ name = "registerlinenumbering",
+ actions = { boxed.register, context },
+ arguments = {
+ {
+ { "continue" },
+ { "start", "integer" },
+ { "step", "integer" },
+ { "method" },
+ { "tag" },
+ }
+ }
+}
+
+function boxed.setup(n,configuration)
+ local d = data[n]
+ if d then
+ if trace_numbers then
+ report_lines("updating setup %a",n)
+ end
+ for k,v in next, configuration do
+ d[k] = v
+ end
+ else
+ if trace_numbers then
+ report_lines("registering setup %a (br)",n)
+ end
+ data[n] = configuration
+ end
+ return n
+end
+
+implement {
+ name = "setuplinenumbering",
+ actions = boxed.setup,
+ arguments = {
+ "integer",
+ {
+ { "continue" },
+ { "start", "integer" },
+ { "step", "integer" },
+ { "method" },
+ { "tag" },
+ }
+ }
+}
+
+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
+ current_list[#current_list+1] = { n, s }
+ if sameline then
+ skipflag = 0
+ if trace_numbers then
+ report_lines("skipping broken line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no)
+ end
+ elseif not skip and s % d.step == 0 then
+ skipflag, d.start = 1, s + 1 -- (d.step or 1)
+ if trace_numbers then
+ report_lines("making number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no)
+ end
+ else
+ skipflag, d.start = 0, s + 1 -- (d.step or 1)
+ if trace_numbers then
+ report_lines("skipping line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no)
+ end
+ end
+ local p = checkline(n)
+ if p then
+ ctx_makelinenumber(tag,skipflag,s,p.hsize,p.reverse and "TRT" or "TLT")
+ else
+ report_lines("needs checking")
+ end
+ end
+end
+
+-- print(nodes.idstostring(list))
+
+-- hlists of type line will only have an attribute when the line number attribute
+-- still set at par building time which is not always the case unless we explicitly
+-- do a par before we end the line
+
+-- todo: check for a: when <= 0 then false
+
+local function lineisnumbered(n)
+ local n = getlist(n)
+ while n do
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ -- this can hit fast as we inherit anchor attributes from parent
+ local a = getattr(n,a_linenumber)
+ if a and a > 0 then
+ return a
+ end
+ elseif id == glyph_code then
+ local a = getattr(n,a_linenumber)
+ if a and a > 0 then
+ return a
+ else
+ return false
+ end
+ end
+ n = getnext(n)
+ end
+end
+
+local function listisnumbered(list)
+ if list then
+ for n in traverse_id(hlist_code,list) do
+ if getsubtype(n) == line_code then
+ local a = getattr(n,a_linenumber)
+ if a then
+ -- a quick test for lines (only valid when \par before \stoplinenumbering)
+ return a > 0 and list or false
+ else
+ -- a bit slower one, assuming that we have normalized and anchored
+ if lineisnumbered(n) then
+ return list
+ end
+ end
+ end
+ end
+ end
+end
+
+local function findnumberedlist(list)
+ -- we assume wrapped boxes, only one with numbers
+ local n = list
+ while n do
+ local id = getid(n)
+ if id == hlist_code then
+ if getsubtype(n) == line_code then
+ local a = getattr(n,a_linenumber)
+ if a then
+ return a > 0 and list
+ end
+ return
+ else
+ local list = getlist(n)
+ if lineisnumbered(list) then
+ return n
+ end
+ local okay = findnumberedlist(list)
+ if okay then
+ return okay
+ end
+ end
+ elseif id == vlist_code then
+ local list = getlist(n)
+ if listisnumbered(list) then
+ return list
+ end
+ local okay = findnumberedlist(list)
+ if okay then
+ return okay
+ end
+ elseif id == glyph_code then
+ return
+ end
+ n = getnext(n)
+ end
+end
+
+-- reset ranges per page
+-- store first and last per page
+-- maybe just set marks directly
+
+local function findcolumngap(list)
+ -- we assume wrapped boxes, only one with numbers
+ local n = list
+ while n do
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ local p = properties[n]
+ if p and p.columngap then
+ if trace_numbers then
+ report_lines("first column gap %a",p.columngap)
+ end
+ return n
+ else
+ local list = getlist(n)
+ if list then
+ local okay = findcolumngap(list)
+ if okay then
+ return okay
+ end
+ end
+ end
+ end
+ n = getnext(n)
+ end
+end
+
+function boxed.stage_one(n,nested)
+ current_list = { }
+ local box = getbox(n)
+ if not box then
+ return
+ end
+ local list = getlist(box)
+ if not list then
+ return
+ end
+ local last_a = nil
+ local last_v = -1
+ 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
+ -- go on
+ elseif getfield(n,"height") == 0 and getfield(n,"depth") == 0 then
+ -- skip funny hlists -- todo: check line subtype
+ else
+ local a = lineisnumbered(n)
+ if a then
+ if last_a ~= a then
+ local da = data[a]
+ local ma = da.method
+ if ma == v_next then
+ skip = true
+ elseif ma == v_page then
+ da.start = 1 -- eventually we will have a normal counter
+ end
+ last_a = a
+ if trace_numbers then
+ report_lines("starting line number range %s: start %s, continue %s",a,da.start,da.continue or v_no)
+ end
+ end
+ if getattr(n,a_displaymath) then
+ if is_display_math(n) then
+ check_number(n,a,skip)
+ end
+ else
+ local v = getattr(list,a_verbatimline)
+ if not v or v ~= last_v then
+ last_v = v
+ check_number(n,a,skip)
+ else
+ check_number(n,a,skip,true)
+ end
+ end
+ skip = false
+ end
+ end
+ end
+ end
+
+ if nested == 0 then
+ if list then
+ check()
+ end
+ elseif nested == 1 then
+ local id = getid(box)
+ if id == vlist_code then
+ if listisnumbered(list) then
+ -- ok
+ else
+ list = findnumberedlist(list)
+ end
+ else -- hlist
+ list = findnumberedlist(list)
+ end
+ if list then
+ check()
+ end
+ elseif nested == 2 then
+ list = findcolumngap(list)
+ -- we assume we have a vlist
+ if not list then
+ return
+ end
+ for n in traverse_id(vlist_code,list) do
+ local p = properties[n]
+ if p and p.columngap then
+ if trace_numbers then
+ report_lines("found column gap %a",p.columngap)
+ end
+ list = getlist(n)
+ if list then
+ check()
+ end
+ end
+ end
+ else
+ -- bad call
+ end
+end
+
+-- column attribute
+
+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
+ 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]
+ if ti then
+ -- local d = getfield(n,"dir")
+ -- local l = getlist(n)
+ -- if d == "TRT" then
+ -- local w = getfield(n,"width")
+ -- ti = hpack_nodes(linked_nodes(new_kern(-w),ti,new_kern(w)))
+ -- end
+ -- setnext(ti,l)
+ -- setprev(l,ti)
+ -- setlist(n,ti)
+ addtoline(n,ti)
+ resolve(n,m)
+ else
+ report_lines("error in linenumbering (1)")
+ return
+ end
+ end
+ end
+end
+
+-- function boxed.stage_zero(n) -- not used
+-- return identify(getlist(getbox(n)))
+-- end
+
+implement {
+ name = "linenumbersstageone",
+ actions = boxed.stage_one,
+ arguments = { "integer", "integer" }
+}
+
+implement {
+ name = "linenumbersstagetwo",
+ actions = boxed.stage_two,
+ arguments = { "integer", "integer" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi
new file mode 100644
index 00000000000..5756d870b66
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi
@@ -0,0 +1,576 @@
+%D \module
+%D [ file=page-lin,
+%D version=2007.11.29,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% generic or not ... maybe not bother too much and simplify to mkiv only
+% get rid of \mk* (left over from experimental times)
+%
+% to be redone (was experiment) .. can be hooked into margin code
+% reshuffle arguments
+
+\writestatus{loading}{ConTeXt Core Macros / Line Numbering}
+
+\unprotect
+
+% todo: save settings
+%
+% low level interface
+%
+% we should use normal counters but then we need to sync settings
+
+% some line
+%
+% \startlocallinenumbering
+% some source code 1\par
+% some source code 2\par
+% some source code 3\par
+% \stoplocallinenumbering
+%
+% some line
+
+\registerctxluafile{page-lin}{1.001}
+
+\definesystemattribute[linenumber] [public]
+\definesystemattribute[linereference][public]
+
+\appendtoksonce
+ \attribute\linenumberattribute\attributeunsetvalue
+\to \everyforgetall
+
+\newcount \linenumber % not used
+\newbox \b_page_lines_scratch
+\newcount \c_page_lines_reference
+\newconstant\c_page_lines_nesting
+
+\newconditional\tracelinenumbering % we keep this for old times sake
+
+\installtextracker
+ {lines.numbers.show}
+ {\settrue \tracelinenumbering}
+ {\setfalse\tracelinenumbering}
+
+% id nr shift width leftskip dir
+
+\installcorenamespace{linenumberinginstance}
+
+% tag skipflag s getfield(n,"shift") getfield(n,"width") leftmarginwidth(getlist(n)) getfield(n,"dir"))
+
+\let\makelinenumber\gobblefivearguments % used at lua end
+
+\newconditional\page_postprocessors_needed_box
+
+\unexpanded\def\page_postprocessors_linenumbers_page #tag{\page_lines_add_numbers_to_box{#tag}\plusone \plusone \zerocount}
+\unexpanded\def\page_postprocessors_linenumbers_box #tag{\page_lines_add_numbers_to_box{#tag}\plusone \plusone \zerocount}
+\unexpanded\def\page_postprocessors_linenumbers_deepbox#tag{\page_lines_add_numbers_to_box{#tag}\plusone \plusone \plusone }
+\unexpanded\def\page_postprocessors_linenumbers_column #tag{\page_lines_add_numbers_to_box{#tag}\currentcolumn\nofcolumns\zerocount}
+
+\def\page_lines_start_define
+ {\setxvalue{\??linenumberinginstance\currentlinenumbering}%
+ {\clf_registerlinenumbering
+ continue {\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi}%
+ start \linenumberingparameter\c!start
+ step \linenumberingparameter\c!step
+ method {\linenumberingparameter\c!method}%
+ tag {\currentlinenumbering}%
+ }}
+
+\def\page_lines_start_update
+ {\clf_setuplinenumbering
+ \csname\??linenumberinginstance\currentlinenumbering\endcsname
+ {%
+ continue {\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi}%
+ }%
+ \relax}
+
+\def\page_lines_setup
+ {\ifcsname \??linenumberinginstance\currentlinenumbering\endcsname
+ \clf_setuplinenumbering
+ \lastnamedcs
+ {%
+ continue {\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi}%
+ start \linenumberingparameter\c!start
+ step \linenumberingparameter\c!step
+ method {\linenumberingparameter\c!method}%
+ tag {\currentlinenumbering}%
+ }%
+ \relax
+ \fi}
+
+% we could make this a bit more efficient by putting the end reference
+% in the same table as the start one but why make things complex ...
+
+\unexpanded\def\page_lines_some_reference#1#2#3%
+ {\dontleavehmode\begingroup
+ \global\advance\c_page_lines_reference\plusone
+ \attribute\linereferenceattribute\c_page_lines_reference
+ #3% todo: #3{#1} as there is no need to pass #1 as part of #3
+ % for the moment we use a simple system i.e. no prefixes etc .. todo: store as number
+ \c_strc_references_bind_state\zerocount % we don't want the prewordbreak and manage it here
+ \normalexpanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberingparameter\c!conversion}{\the\c_page_lines_reference}}% kind labels userdata text
+ \endgroup}
+
+% \def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{}} % reimplemented later
+% \def\page_lines_reference_stop #1{\page_lines_some_reference{#1}{lr:e:#1}{}} % reimplemented later
+
+% \def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced/ not used
+% \def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced/ not used
+
+\newif\ifnumberinglines % will change
+\newif\iftypesettinglines % will change
+
+\installcorenamespace{linenumbering}
+
+\installcommandhandler \??linenumbering {linenumbering} \??linenumbering
+
+\setnewconstant\c_page_lines_mode \plusone % 0=continue, 1=restart
+\setnewconstant\c_page_lines_location \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end
+\setnewconstant\c_page_lines_alignment\plusfive % 0=middle, 1=left, 2=right, 5=auto
+
+\newdimen\d_page_lines_width
+\newdimen\d_page_lines_distance
+
+\newevery \beforeeverylinenumbering \relax
+\newevery \aftereverylinenumbering \relax
+\newevery \everylinenumber \relax
+
+\appendtoks
+ \page_lines_setup
+\to \everysetuplinenumbering
+
+\appendtoks
+ \page_lines_start_define
+\to \everydefinelinenumbering
+
+\setuplinenumbering
+ [\c!conversion=\v!numbers,
+ \c!start=1,
+ \c!step=1,
+ \c!method=\v!first,
+ \c!continue=\v!no,
+ \c!style=,
+ \c!color=,
+ \c!width=2\emwidth,
+ \c!left=,
+ \c!right=,
+ \c!command=,
+ \c!margin=2.5\emwidth,
+ \c!distance=\zeropoint,
+ \c!location=\v!default, % depends on direction, columns etc
+ \c!align=\v!auto]
+
+\definelinenumbering
+ []
+
+% \startlinenumbering[<startvalue>|continue|settings|name]
+% \startlinenumbering[name][<startvalue>|continue|settings]
+
+\unexpanded\def\startlinenumbering
+ {\dodoubleempty\page_lines_start}
+
+\def\page_lines_start % we stay downward compatible
+ {\begingroup
+ \ifsecondargument
+ \expandafter\page_lines_start_two
+ \else\iffirstargument
+ \doubleexpandafter\page_lines_start_one
+ \else
+ \doubleexpandafter\page_lines_start_zero
+ \fi\fi}
+
+\def\page_lines_start_zero[#1][#2]%
+ {\edef\m_argument{\linenumberingparameter\c!continue}%
+ \ifx\m_argument\v!yes
+ \c_page_lines_mode\zerocount
+ \else
+ \c_page_lines_mode\plusone
+ \fi
+ \page_lines_start_followup}
+
+\def\page_lines_start_one[#1][#2]% [continue|<number>|settings] % historic
+ {\edef\m_argument{#1}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \let\currentlinenumbering\empty
+ \else
+ \c_page_lines_mode\plusone
+ \ifx\m_argument\v!empty
+ \let\currentlinenumbering\empty
+ \else
+ \doifelseassignment{#1}
+ {\let\currentlinenumbering\empty
+ \setupcurrentlinenumbering[#1]}
+ {\doifelsenumber\m_argument
+ {\let\currentlinenumbering\empty
+ \letlinenumberingparameter\c!start\m_argument}
+ {\let\currentlinenumbering\m_argument}}%
+ \fi
+ \edef\p_continue{\linenumberingparameter\c!continue}%
+ \ifx\p_continue\v!yes
+ \c_page_lines_mode\zerocount
+ \fi
+ \fi
+ \page_lines_start_followup}
+
+\def\page_lines_start_two[#1][#2]% [tag][continue|<number>|settings]
+ {\edef\currentlinenumbering{#1}%
+ \edef\m_argument{#2}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \else
+ \c_page_lines_mode\plusone
+ \ifx\m_argument\v!empty \else
+ \doifelseassignment{#2}
+ {\setupcurrentlinenumbering[#2]}
+ {\doifnumber\m_argument
+ {\letlinenumberingparameter\c!start\m_argument}}%
+ \fi
+ \edef\p_continue{\linenumberingparameter\c!continue}%
+ \ifx\p_continue\v!yes
+ \c_page_lines_mode\zerocount
+ \fi
+ \fi
+ \page_lines_start_followup}
+
+\newconditional\c_page_lines_auto_narrow
+
+\def\page_lines_start_followup
+ {\numberinglinestrue
+ \edef\p_location{\linenumberingparameter\c!location}%
+ \setfalse\c_page_lines_auto_narrow
+ \ifhmode \else
+ \ifx\p_location\v!text
+ \ifdim\leftskip>\zeropoint \else
+ \advance\leftskip\linenumberingparameter\c!margin
+ \settrue\c_page_lines_auto_narrow
+ \fi
+ \else\ifx\p_location\v!begin
+ \ifdim\leftskip>\zeropoint \else
+ \advance\leftskip\linenumberingparameter\c!margin
+ \settrue\c_page_lines_auto_narrow
+ \fi
+ \else\ifx\p_location\v!end
+ \ifdim\leftskip>\zeropoint \else
+ \advance\rightskip\linenumberingparameter\c!margin
+ \settrue\c_page_lines_auto_narrow
+ \fi
+ \fi\fi\fi
+ \fi
+ \the\beforeeverylinenumbering
+ \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page
+ \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column
+ \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv
+ \ifcase\c_page_lines_mode\relax
+ \page_lines_start_update % continue
+ \or
+ \page_lines_start_define % only when assignment
+ \fi
+ \attribute\linenumberattribute\csname\??linenumberinginstance\currentlinenumbering\endcsname\relax}
+
+\unexpanded\def\stoplinenumbering
+ {\attribute\linenumberattribute\attributeunsetvalue
+ \the\aftereverylinenumbering
+ \ifconditional\c_page_lines_auto_narrow\par\fi
+ \endgroup}
+
+% number placement .. will change into (the new) margin code
+
+\newconditional\c_page_lines_fake_number
+\newconstant \b_page_lines_number
+\newconstant \c_page_lines_column
+\newconstant \c_page_lines_last_column
+\newdimen \d_page_lines_line_width
+\settrue \c_page_lines_dir_left_to_right
+
+\installcorenamespace{linenumberinghandler}
+
+\def\page_line_swap_align % can become a helper
+ {\ifx\p_align\v!inner \let\p_align\v!outer \else
+ \ifx\p_align\v!outer \let\p_align\v!inner \else
+ \ifx\p_align\v!flushleft \let\p_align\v!flushright\else
+ \ifx\p_align\v!flushright\let\p_align\v!flushleft \else
+ \ifx\p_align\v!left \let\p_align\v!right \else
+ \ifx\p_align\v!right \let\p_align\v!left \fi\fi\fi\fi\fi\fi}
+
+\let\page_lines_make_number_indeed\relax
+
+% \def\page_lines_rlap{\ifconditional\c_page_lines_dir_left_to_right\expandafter\rlap\else\expandafter\llap\fi}
+% \def\page_lines_llap{\ifconditional\c_page_lines_dir_left_to_right\expandafter\llap\else\expandafter\rlap\fi}
+
+\def\page_lines_add_numbers_to_box#box#column#max#nesting%
+ {\bgroup
+ \b_page_lines_number #box\relax
+ \c_page_lines_column #column\relax
+ \c_page_lines_last_column#max\relax
+ \fullrestoreglobalbodyfont
+ \let\makelinenumber\page_lines_make_number % used at lua end
+ \setbox\b_page_lines_scratch\vbox
+ {\forgetall
+ \offinterlineskip
+ \clf_linenumbersstageone
+ \b_page_lines_number
+ #nesting%
+ \relax}%
+ \clf_linenumbersstagetwo
+ \b_page_lines_number
+ \b_page_lines_scratch
+ \relax
+ \egroup}
+
+\def\page_lines_make_number#tag#mode#linenumber#width#dir% with hang and parindent and skips we have to compensate for \hsize
+ {\naturalhbox to \zeropoint \bgroup
+ \ifcase#mode\relax
+ % \settrue \c_page_lines_fake_number
+ \else
+ % \setfalse\c_page_lines_fake_number
+ \edef\currentlinenumbering{#tag}%
+ \def\linenumber{#linenumber}% unsafe
+ \d_page_lines_line_width#width\scaledpoint\relax
+ \d_page_lines_distance\linenumberingparameter\c!distance\relax
+ \edef\p_align{\linenumberingparameter\c!align}%
+ \edef\p_location{\linenumberingparameter\c!location}%
+ \ifcase\istltdir#dir\relax
+ \settrue \c_page_lines_dir_left_to_right
+ \else
+ \setfalse\c_page_lines_dir_left_to_right
+ \fi
+ %
+ % maybe we also need an option to ignore columns, so that we renumber
+ % once but on the other hand this assumes aligned lines
+ %
+ \ifcase\c_page_lines_last_column\relax
+ \settrue \c_page_lines_fake_number % why
+ \or
+ % one column
+ \or
+ % two columns
+ \ifx\p_location\v!default % or just margin
+ \ifcase\c_page_lines_column\relax
+ \settrue \c_page_lines_fake_number % why
+ \or
+ % one
+ \let\p_location\v!left
+ \else
+ % two
+ \let\p_location\v!right
+ % can become a helper
+ \page_line_swap_align
+ \fi
+ \fi
+ \else
+ % too fuzzy
+ \fi
+ \ifx\p_location\v!default
+ \ifconditional\c_page_lines_dir_left_to_right
+ \let\p_location\v!left
+ \else
+ \let\p_location\v!right
+ \page_line_swap_align % yes or no
+ \fi
+ \fi
+ %
+ \begincsname\??linenumberinghandler\p_location\endcsname
+ \fi
+ \egroup}
+
+\def\page_lines_number_inject#align#width%
+ {\edef\p_width{\linenumberingparameter\c!width}%
+ \ifx\p_width\v!margin
+ \d_page_lines_width#width%
+ \else
+ \d_page_lines_width\p_width
+ \fi
+ \relax
+ \ifdim\d_page_lines_width>\zeropoint
+% \ifconditional\c_page_lines_dir_left_to_right\else
+% \let\simplealignedbox\simplereversealignedbox
+% \fi
+ \ifconditional\tracelinenumbering
+ \ruledhbox{\simplealignedbox\d_page_lines_width#align{\page_lines_number_inject_indeed}}%
+ \else
+ \simplealignedbox\d_page_lines_width#align{\page_lines_number_inject_indeed}%
+ \fi
+ \else
+ \ifconditional\tracelinenumbering
+ \ruledhbox
+ \else
+ % \hbox
+ \fi
+ {\page_lines_number_inject_indeed}%
+ \fi}
+
+\def\page_lines_number_inject_indeed
+ {\uselinenumberingstyleandcolor\c!style\c!color
+ \linenumberingparameter\c!command
+ {\linenumberingparameter\c!left
+ \convertnumber{\linenumberingparameter\c!conversion}\linenumber
+ \linenumberingparameter\c!right}}
+
+% \def\dodorlap{\hbox to \zeropoint{\box\nextbox\normalhss}\endgroup}
+% \def\dodollap{\hbox to \zeropoint{\normalhss\box\nextbox}\endgroup}
+
+\def\page_line_handle_left#align#width#distance%
+ {\llap
+ {\page_lines_number_inject#align#width%
+ \kern\dimexpr
+ #distance+\d_page_lines_distance
+ \ifconditional\c_page_lines_dir_left_to_right\else+\d_page_lines_line_width\fi
+ \relax
+ \the\everylinenumber
+ \hss}}
+
+\def\page_line_handle_right#align#width#distance%
+ {\rlap
+ {\kern\dimexpr
+ #distance+\d_page_lines_distance
+ \ifconditional\c_page_lines_dir_left_to_right+\d_page_lines_line_width\fi
+ \relax
+ \page_lines_number_inject#align#width%
+ \the\everylinenumber
+ \hss}}
+
+\setuvalue{\??linenumberinghandler\v!left}%
+ {\page_line_handle_left\p_align\leftmarginwidth\leftmargindistance}
+
+\setuvalue{\??linenumberinghandler\v!right}%
+ {\page_line_handle_right\p_align\rightmarginwidth\rightmargindistance}
+
+\setuvalue{\??linenumberinghandler\v!inner}%
+ {\ifodd\realpageno
+ \ifx\p_align\v!inner
+ \page_line_handle_left\v!flushleft\leftmarginwidth\leftmargindistance
+ \else\ifx\p_align\v!outer
+ \page_line_handle_left\v!flushright\leftmarginwidth\leftmargindistance
+ \else
+ \page_line_handle_left\p_align\leftmarginwidth\leftmargindistance
+ \fi\fi
+ \else
+ \ifx\p_align\v!inner
+ \page_line_handle_right\v!flushright\rightmarginwidth\rightmargindistance
+ \else\ifx\p_align\v!outer
+ \page_line_handle_right\v!flushleft\rightmarginwidth\rightmargindistance
+ \else
+ \page_line_handle_right\p_align\rightmarginwidth\rightmargindistance
+ \fi\fi
+ \fi}
+
+\setuvalue{\??linenumberinghandler\v!outer}%
+ {\ifodd\realpageno
+ \ifx\p_align\v!inner
+ \page_line_handle_right\v!flushleft\leftmarginwidth\leftmargindistance
+ \else\ifx\p_align\v!outer
+ \page_line_handle_right\v!flushright\leftmarginwidth\leftmargindistance
+ \else
+ \page_line_handle_right\p_align\leftmarginwidth\leftmargindistance
+ \fi\fi
+ \else
+ \ifx\p_align\v!inner
+ \page_line_handle_left\v!flushright\rightmarginwidth\rightmargindistance
+ \else\ifx\p_align\v!outer
+ \page_line_handle_left\v!flushleft\rightmarginwidth\rightmargindistance
+ \else
+ \page_line_handle_left\p_align\rightmarginwidth\rightmargindistance
+ \fi\fi
+ \fi}
+
+\def\page_line_handle_begin#align%
+ {\rlap
+ {\kern\d_page_lines_distance
+ \page_lines_number_inject#align\zeropoint
+ \the\everylinenumber}}
+
+\def\page_line_handle_end#align%
+ {\rlap
+ {\kern\d_page_lines_line_width\relax
+ \llap
+ {\page_lines_number_inject#align\zeropoint
+ \kern\d_page_lines_distance
+ \the\everylinenumber}}}
+
+\setuvalue{\??linenumberinghandler\v!begin}{\page_line_handle_begin\p_align}
+\setuvalue{\??linenumberinghandler\v!end }{\page_line_handle_end \p_align}
+\setuvalue{\??linenumberinghandler\v!text }{\page_line_handle_begin\p_align}
+
+\expandafter\let\csname\??linenumberinghandler\v!inleft \expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!inmargin\expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!margin \expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!inright \expandafter\endcsname\csname\??linenumberinghandler\v!right\endcsname
+
+% referencing: \permithyphenation, also removes leading spaces (new per 29-11-2013)
+
+\unexpanded\def\someline [#1]{\page_lines_reference_start{#1}\page_lines_reference_stop{#1}} % was just a def
+%unexpanded\def\startline[#1]{\page_lines_reference_start{#1}\ignorespaces}
+\unexpanded\def\startline[#1]{\page_lines_reference_start{#1}\permithyphenation\ignorespaces} %okay?
+\unexpanded\def\stopline [#1]{\removeunwantedspaces\permithyphenation\page_lines_reference_stop{#1}}
+
+\def\page_lines_reference_show_start
+ {\ifconditional\tracelinenumbering
+ \expandafter\page_lines_reference_show_start_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_lines_reference_show_stop
+ {\ifconditional\tracelinenumbering
+ \expandafter\page_lines_reference_show_stop_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_lines_reference_show_start_indeed#1%
+ {\setbox\scratchbox\hpack{\llap
+ {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hpack{\llap{\tt\txx#1}}}}%
+ \smashbox\scratchbox
+ \box\scratchbox}
+
+\def\page_lines_reference_show_stop_indeed#1%
+ {\setbox\scratchbox\hpack{\rlap
+ {\raise.85\strutht\hpack{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}%
+ \smashbox\scratchbox
+ \box\scratchbox}
+
+\def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{\page_lines_reference_show_start{#1}}}
+\def\page_lines_reference_stop #1{\page_lines_some_reference{#1}{lr:e:#1}{\page_lines_reference_show_stop {#1}}}
+
+% eventually we will do this in lua
+
+\def\currentreferencelinenumber{\clf_filterreference{linenumber}}
+
+\let\m_page_lines_from\empty
+\let\m_page_lines_to \empty
+
+\unexpanded\def\doifelsesamelinereference#1#2#3%
+ {\doifelsereferencefound{lr:b:#1}
+ {\edef\m_page_lines_from{\currentreferencelinenumber}%
+ \doifelsereferencefound{lr:e:#1}
+ {\edef\m_page_lines_to{\currentreferencelinenumber}%
+ %[\m_page_lines_from,\m_page_lines_to]
+ \ifx\m_page_lines_from\m_page_lines_to#2\else#3\fi}
+ {#2}}
+ {#2}}
+
+\let\doifsamelinereferenceelse\doifelsesamelinereference
+
+\unexpanded\def\inline#1[#2]%
+ {\doifelsenothing{#1}
+ {\doifelsesamelinereference{#2}
+ {\in{\leftlabeltext\v!line}{\rightlabeltext\v!line}[lr:b:#2]}
+ {\in{\leftlabeltext\v!lines}{}[lr:b:#2]--\in{}{\rightlabeltext\v!lines}[lr:e:#2]}}
+ {\doifelsesamelinereference{#2}
+ {\in{#1}[lr:b:#2]}
+ {\in{#1}[lr:b:#2]--\in[lr:e:#2]}}}
+
+\unexpanded\def\inlinerange[#1]%
+ {\doifelsesamelinereference{#1}
+ {\in[lr:b:#1]}
+ {\in[lr:b:#1]\endash\in[lr:e:#1]}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mak.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-mak.mkvi
new file mode 100644
index 00000000000..bbb7cc1488a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mak.mkvi
@@ -0,0 +1,269 @@
+%D \module
+%D [ file=page-mak, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Simple MakeUp,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / MakeUp}
+
+\unprotect
+
+%D \macros
+%D {definemakeup, setupmakeup, startmakeup}
+%D
+%D A makeup is a separate page, like a title page or colofon.
+%D There is one standard makeup page, but you can define more
+%D if needed.
+%D
+%D \starttyping
+%D \startstandardmakeup
+%D My Fancy Title
+%D \stopstandardmakeup
+%D \stoptyping
+%D
+%D The associated commands are:
+%D
+%D \showsetup{definemakeup}
+%D \showsetup{setupmakeup}
+%D \showsetup{startmakeup}
+
+%D New is that we have a layout with the same name so one can set
+%D up a special layout that then gets used.
+
+\installcorenamespace{makeup}
+\installcorenamespace{makeupdoublesided}
+
+\installcommandhandler \??makeup {makeup} \??makeup
+
+\appendtoks
+ \setuevalue{\e!start\currentmakeup\e!makeup}{\startmakeup[\currentmakeup]}%
+ \setuevalue{\e!stop \currentmakeup\e!makeup}{\stopmakeup}%
+ \doifelselayoutdefined\currentmakeup\donothing{\definelayout[\currentmakeup]}% new
+\to \everydefinemakeup
+
+%D The \type{\start}||\type{\stop} macros are used for both
+%D the direct and indirect way. The parameterless call will
+%D build a simple box.
+
+\unexpanded\def\startmakeup
+ {\dodoubleempty\page_makeup_start}
+
+\let\stopmakeup\relax
+
+\def\page_makeup_start
+ {\iffirstargument
+ \expandafter\page_makeup_start_yes
+ \else
+ \expandafter\page_makeup_start_nop
+ \fi}
+
+%D The simple case: just a box with text dimensions.
+
+\unexpanded\def\page_makeup_start_nop[#name][#settings]% dummies
+ {\page
+ \setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]%
+ \bgroup
+ \forgetall % else indented flush
+ \dontcomplain
+ \vbox to \textheight \bgroup
+ \setsystemmode\v!makeup
+ \hsize\textwidth
+ \let\stopmakeup\page_makeup_stop_nop}
+
+\unexpanded\def\page_makeup_stop_nop
+ {\egroup
+ \egroup
+ \page}
+
+%D The normal variant.
+
+\newbox \b_page_makeup
+\newtoks\t_page_makeup_every_setup
+
+\def\page_makeup_start_yes[#name]% [#settings]%
+ {\doifelsecommandhandler\??makeup{#name}\page_makeup_start_indeed\page_makeup_start_nop[#name]}%
+
+% case 1:
+%
+% \setuplayout[height=5cm]
+%
+% case 2:
+%
+% \definelayout[crap][height=10cm]
+% \definelayout[standard][crap]
+%
+% case 3:
+%
+% \setuplayout[standard][height=15cm]
+%
+% case 4:
+%
+% \definelayout[whatever][height=2cm]
+% \setuplayout[whatever]
+
+\def\page_makeup_start_indeed[#name][#settings]%
+ {% the next grouping hack is somewhat messy:
+ \begingroup
+ % we need to figure out the current layout
+ \xdef\m_page_makeup_name{#name}%
+ \let\currentmakeup\m_page_makeup_name
+ \let\currentlayout\m_page_makeup_name
+ \xdef\m_page_makeup_layout_parent{\layoutparameter\s!parent}%
+ \setupcurrentmakeup[#settings]%
+ \edef\p_page{\makeupparameter\c!page}%
+ \ifx\p_page\empty
+ \endgroup
+ \page % new, so best not have dangling mess here like references (we could capture then and flush embedded)
+ \else\ifx\p_page\v!no
+ % nothing
+ \endgroup
+ \else
+ \normalexpanded{\endgroup\page[\p_page]}%
+ \fi\fi
+ % some dirty trickery (sorry) for determining if we have
+ % - a layout definition at all
+ % - inherit from the parent of that definition
+ % - inherit from the current layout otherwise
+ \ifx\m_page_makeup_name\currentlayout
+ % we already use the layout
+ \else\ifx\m_page_makeup_layout_parent\??layout
+ % we inherit from the current layout
+ \normalexpanded{\setuplayout[#name][\s!parent=\??layout\currentlayout]}% is remembered but checked later anyway
+ % \else
+ % we have an inherited layout
+ \fi\fi
+ \startlayout[#name]% includes \page
+ \bgroup
+ %\edef\currentmakeup{#name}%
+ \let\currentmakeup\m_page_makeup_name
+ \setupcurrentmakeup[#settings]%
+ \setsystemmode\v!makeup
+ \the\t_page_makeup_every_setup
+ \makeupparameter\c!commands % hm, what is this one doing here ?
+ \forgetall % else indented flush
+ \dontcomplain
+ \global\setbox\b_page_makeup\vbox to \makeupparameter\c!height \bgroup
+ \usemakeupstyleandcolor\c!style\c!color
+ \hsize\makeupparameter\c!width
+ \usealignparameter\makeupparameter
+ \usesetupsparameter\makeupparameter % lua(..),xml(...,..),tex(..)
+ \makeupparameter\c!top
+ \let\stopmakeup\page_makeup_stop_yes}
+
+\unexpanded\def\page_makeup_stop_yes
+ {\endgraf
+ \makeupparameter\c!bottom
+ \egroup
+ \strc_pagenumbers_page_state_push % new
+ \makeupparameter\c!before\relax
+ \begingroup
+ \ifdim\ht\b_page_makeup>\vsize
+ \ht\b_page_makeup\vsize % is already set to \textheight (maybe set dp to 0)
+ \fi
+ \setuppagenumber[\c!state=\makeupparameter\c!pagestate]%
+ \doif{\makeupparameter\c!location}\v!top{\topskip\zeropoint}%
+ \edef\p_reference{\makeupparameter\c!reference}%
+ \dontleavehmode
+ \usereferenceparameter\makeupparameter
+ \box\b_page_makeup % could be whole box being destination
+ \the\t_page_makeup_every_setup
+ \page
+ \endgroup
+ \makeupparameter\c!after\relax
+ \ifdoublesided \ifodd\realpageno \else
+ \csname\??makeupdoublesided\makeupparameter\c!doublesided\endcsname
+ \fi \fi
+ \strc_pagenumbers_page_state_pop % new
+ \egroup
+ \stoplayout % includes \page
+ \ifx\m_page_makeup_name\currentlayout
+ \else\ifx\m_page_makeup_layout_parent\??layout
+ \normalexpanded{\setuplayout[\m_page_makeup_name][\s!parent=\??layout]}% is remembered but checked later anyway
+ % \else
+ \fi\fi}
+
+\setvalue{\??makeupdoublesided\v!yes}%
+ {\emptyhbox
+ \page}
+
+\setvalue{\??makeupdoublesided\v!empty}%
+ {\the\t_page_makeup_every_setup
+ % == \page[\v!dummy]
+ \page[\v!blank]%
+ \emptyhbox
+ \page}
+
+%D The text surrounding the main body text can be influenced
+%D by setting their associated status variables. The
+%D connection between them is made by the following macro
+
+\appendtoks % this might need a revision
+ \setupfooter[\c!state=\makeupparameter\c!footerstate]%
+ \setupheader[\c!state=\makeupparameter\c!headerstate]%
+ \setuptext [\c!state=\makeupparameter\c!textstate]%
+ \setupbottom[\c!state=\makeupparameter\c!bottomstate]%
+ \setuptop [\c!state=\makeupparameter\c!topstate]%
+\to \t_page_makeup_every_setup
+
+%D The standard page template is defined as follows:
+
+\setupmakeup
+ [\c!width=\innermakeupwidth, % example in manual / was \makeupwidth
+ \c!height=\textheight, % example in manual
+ %\c!commands=,
+ %\c!setups=,
+ %\c!color=,
+ %\c!align=,
+ %\c!before=,
+ %\c!after=,
+ %\c!location=,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty,
+ \c!top=\vss,
+ \c!bottom=\vss,
+ \c!bottomstate=\v!normal,
+ \c!topstate=\v!normal,
+ \c!textstate=\v!normal,
+ \c!headerstate=\v!stop,
+ \c!footerstate=\v!stop,
+ \c!pagestate=\v!stop] % in manual ! ! !
+% \c!pagestate=\v!start]
+
+\definemakeup
+ [\v!standard]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty]
+
+\definemakeup
+ [\v!text]
+ [\c!topstate=\v!start,
+ \c!headerstate=\v!start,
+ \c!textstate=\v!start,
+ \c!footerstate=\v!start,
+ \c!bottomstate=\v!start,
+ \c!doublesided=\v!no,
+ \c!page=\v!yes,
+ \c!top=\pseudostrut\ignorespaces,
+ \c!bottom=\obeydepth\vss]
+
+\definemakeup
+ [\v!page]
+
+\definemakeup
+ [\v!middle]
+ [\v!standard]
+
+% \definelayout[standard]
+% \definelayout[text]
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mbk.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-mbk.mkvi
new file mode 100644
index 00000000000..8038771d9c7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mbk.mkvi
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=page-mbk, % was part of page-mis.mkiv / 2008.11.17
+%D version=2011.11.23, % was part of page-flt.tex / 2000.10.20
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Margin Floats,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Margin Floats}
+
+\unprotect
+
+%D This is an old mechanism that is quite independent of other
+%D floats. There is for instance no save/restore used here. When
+%D there is need (and demand) we can use the float cache and then
+%D flush them in the text when they are left over. On the other
+%D hand, margin float are somewhat manual so it does not make too
+%D much sense to complicate the code. As an alternative users can
+%D fall back on margin texts: they do stack but don't float.
+%D
+%D \starttyping
+%D \dorecurse{9} {
+%D \placefigure[margin]{#1}{}
+%D \input ward
+%D }
+%D \page \null % will flush them
+%D \stoptyping
+
+% status=start: in margin
+% status=stop : in text
+%
+% todo: flush margin floats at end of text
+% todo: separate boxes for left and right
+
+\installcorenamespace{marginblock}
+\installcorenamespace{marginblocklocation}
+
+\installcommandhandler \??marginblock {marginblock} \??marginblock
+
+\let\setupmarginblocks\setupmarginblock
+
+\newconditional\c_page_margin_blocks_enabled % not really needed as we can check each time
+\newconditional\c_page_margin_blocks_present
+
+\newbox \b_page_margin_blocks
+\newbox \b_page_margin_blocks_prepared
+
+\appendtoks
+ \doifelse{\rootmarginblockparameter\c!state}\v!start
+ \settrue\setfalse\c_page_margin_blocks_enabled
+\to \everysetupmarginblock
+
+\setupmarginblocks
+ [\c!state=\v!start,
+ \c!location=\v!inmargin,
+ \c!width=\rightmarginwidth,
+ %\c!style=,
+ %\c!color=,
+ %\c!align=,
+ %\c!left=,
+ %\c!right=,
+ %\c!top=,
+ %\c!before=,
+ %\c!after=,
+ \c!inbetween=\blank,
+ \c!bottom=\vfill]
+
+\unexpanded\def\startmarginblock
+ {\dosingleempty\page_margin_blocks_start_block}
+
+\unexpanded\def\stopmarginblock
+ {\page_margin_blocks_stop_block}
+
+\def\page_margin_blocks_start_block[#tag]%
+ {\begingroup
+ \edef\currentmarginblock{#tag}%
+ \doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_start_block_yes
+ \page_margin_blocks_start_block_nop}
+
+\def\page_margin_blocks_stop_block
+ {\doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_stop_block_yes
+ \page_margin_blocks_stop_block_nop
+ \endgroup}
+
+\def\page_margin_blocks_start_block_yes % 2 maal \vbox ivm \unvbox elders
+ {\showmessage\m!layouts4\empty
+ \global\settrue\c_page_margin_blocks_present
+ \global\setbox\b_page_margin_blocks\vtop\bgroup\vbox\bgroup
+ \hsize\marginblockparameter\c!width
+ \ifvoid\b_page_margin_blocks\else
+ \unvbox\b_page_margin_blocks
+ \marginblockparameter\c!inbetween
+ \fi
+ \usealignparameter\marginblockparameter
+ \usemarginblockstyleandcolor\c!style\c!color
+ \begstrut
+ \ignorespaces}
+
+\def\page_margin_blocks_stop_block_yes
+ {\removeunwantedspaces
+ \endstrut
+ \egroup
+ \egroup}
+
+\def\page_margin_blocks_start_block_nop
+ {\showmessage\m!layouts5\empty
+ \marginblockparameter\c!before
+ \bgroup
+ \usemarginblockstyleandcolor\c!style\c!color}
+
+\def\page_margin_blocks_stop_block_nop
+ {\egroup
+ \marginblockparameter\c!after}
+
+\def\page_margin_blocks_reshape
+ {\ifdim\ht\b_page_margin_blocks_prepared>\zeropoint
+ \beginofshapebox
+ \unvbox\b_page_margin_blocks_prepared
+ \endofshapebox
+ \reshapebox
+ {\box\shapebox}%
+ \setbox\b_page_margin_blocks_prepared\vbox to \textheight
+ {\marginblockparameter\c!top
+ \flushshapebox
+ \marginblockparameter\c!bottom}%
+ \fi}
+
+\unexpanded\def\checkmarginblocks
+ {\ifvoid\b_page_margin_blocks
+ \global\setfalse\c_page_margin_blocks_present
+ \else
+ \page_margin_blocks_check_indeed
+ \fi}
+
+\def\page_margin_blocks_check_indeed
+ {\ifcsname\??marginblocklocation\marginblockparameter\c!location\endcsname
+ \page_margin_blocks_prepare_box
+ \csname\??marginblocklocation\marginblockparameter\c!location\endcsname
+ \else
+ \global\setbox\b_page_margin_blocks\emptybox
+ \global\setfalse\c_page_margin_blocks_present
+ \fi}
+
+\def\page_margin_blocks_prepare_box
+ {\setbox\b_page_margin_blocks_prepared\vbox
+ {\forgetall
+ \splittopskip\topskip
+ \ifvoid\b_page_margin_blocks\else
+ \ifdim\ht\b_page_margin_blocks>\textheight
+ \vsplit\b_page_margin_blocks to \textheight
+ \else
+ \unvbox\b_page_margin_blocks
+ \fi
+ \fi}%
+ \page_margin_blocks_reshape
+ \setbox\b_page_margin_blocks_prepared\vbox
+ {\marginblockparameter\c!before
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!after}}
+
+% inner outer
+
+\setvalue{\??marginblocklocation\v!left }{\page_margin_blocks_set_l_box}
+\setvalue{\??marginblocklocation\v!right }{\page_margin_blocks_set_r_box}
+\setvalue{\??marginblocklocation\v!inmargin}{\doifbothsidesoverruled
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_l_box}
+\setvalue{\??marginblocklocation\v!middle }{\doifbothsidesoverruled
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_l_box
+ \page_margin_blocks_set_r_box}
+
+\unexpanded\def\page_margin_blocks_place_r_yes
+ {\setbox\b_page_margin_blocks_prepared\hbox to \rightmarginwidth
+ {\marginblockparameter\c!left
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!right}%
+ \vsmashbox\b_page_margin_blocks_prepared
+ \box\b_page_margin_blocks_prepared}
+
+\unexpanded\def\page_margin_blocks_place_l_yes
+ {\setbox\b_page_margin_blocks_prepared\hbox to \leftmarginwidth
+ {\marginblockparameter\c!right
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!left}%
+ \vsmashbox\b_page_margin_blocks_prepared
+ \box\b_page_margin_blocks_prepared}
+
+\unexpanded\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth}
+\unexpanded\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth}
+
+\let\placerightmarginblock\page_margin_blocks_place_r_nop
+\let\placeleftmarginblock \page_margin_blocks_place_l_nop
+
+\def\page_margin_blocks_set_r_box{\let\placerightmarginblock\page_margin_blocks_place_r_yes}
+\def\page_margin_blocks_set_l_box{\let\placeleftmarginblock \page_margin_blocks_place_l_yes}
+
+% margin floats (keyword 'margin' in option list)
+
+\unexpanded\def\page_margin_blocks_process_float
+ {\doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_process_float_yes
+ \page_margin_blocks_process_float_nop}
+
+\def\page_margin_blocks_process_float_yes
+ {\global\setbox\b_page_margin_blocks\vbox
+ {\hsize\marginblockparameter\c!width
+ \unvcopy\b_page_margin_blocks
+ \ifvoid\b_page_margin_blocks\else
+ \expandafter\marginblockparameter\expandafter\c!inbetween
+ \fi
+ \box\floatbox
+ \filbreak}%
+ \ifdim\ht\b_page_margin_blocks>\textheight
+ % page_floats_report_saved % no saving done anyway
+ \else
+ \page_floats_report_total
+ \fi}
+
+\def\page_margin_blocks_process_float_nop
+ {\handlefloatmethod\v!here}
+
+\def\page_margin_blocks_float_before
+ {\ifconditional\c_page_margin_blocks_enabled
+ \doifinset\v!margin\floatlocation\endgraf
+ \fi}
+
+\def\page_margin_blocks_float_set_hsize
+ {\ifconditional\c_page_margin_blocks_enabled
+ \doifinset\v!margin\floatlocation{\hsize\rootmarginblockparameter\c!width}%
+ \fi}
+
+\appendtoks
+ \ifvoid\b_page_margin_blocks \else
+ \writestatus\m!layouts{beware: there are left-over margin floats!}%
+ \fi
+\to \everystoptext
+
+\unexpanded\def\flushmarginblocks
+ {\page_otr_command_flush_margin_blocks}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua b/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua
new file mode 100644
index 00000000000..c844bd32d00
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua
@@ -0,0 +1,1090 @@
+if not modules then modules = { } end modules ["page-mix"] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- inserts.getname(name)
+
+-- local node, tex = node, tex
+-- local nodes, interfaces, utilities = nodes, interfaces, utilities
+-- local trackers, logs, storage = trackers, logs, storage
+-- local number, table = number, table
+
+local next, type = next, type
+local concat = table.concat
+local ceil, floor = math.ceil, math.floor
+
+local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end)
+local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end)
+
+local report_state = logs.reporter("mixed columns")
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+local rule_code = nodecodes.rule
+
+local topskip_code = gluecodes.topskip
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local userskip_code = gluecodes.userskip
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local nodetostring = nuts.tostring
+local listtoutf = nodes.listtoutf
+
+local hpack = nuts.hpack
+local vpack = nuts.vpack
+local freenode = nuts.free
+local concatnodes = nuts.concat
+local slidenodes = nuts.slide -- ok here as we mess with prev links intermediately
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setbox = nuts.setbox
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local getskip = nuts.getskip
+local getattribute = nuts.getattribute
+
+local theprop = nuts.theprop
+
+local nodepool = nuts.pool
+
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_glue = nodepool.glue
+
+local points = number.points
+
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_columns = variables.columns
+local v_fixed = variables.fixed
+local v_auto = variables.auto
+local v_none = variables.none
+local v_more = variables.more
+local v_less = variables.less
+local v_halfline = variables.halfline
+
+local context = context
+local implement = interfaces.implement
+
+pagebuilders = pagebuilders or { }
+pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { }
+local mixedcolumns = pagebuilders.mixedcolumns
+
+local a_checkedbreak = attributes.private("checkedbreak")
+local forcedbreak = -123
+
+-- initializesplitter(specification)
+-- cleanupsplitter()
+
+-- Inserts complicate matters a lot. In order to deal with them well, we need to
+-- distinguish several cases.
+--
+-- (1) full page columns: firstcolumn, columns, lastcolumn, page
+-- (2) mid page columns : firstcolumn, columns, lastcolumn, page
+--
+-- We need to collect them accordingly.
+
+local function collectinserts(result,nxt,nxtid)
+ local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0
+ while nxt do
+ if nxtid == insert_code then
+ inserttotal = inserttotal + getfield(nxt,"height") + getfield(nxt,"depth")
+ local s = getsubtype(nxt)
+ local c = inserts[s]
+ if not c then
+ c = { }
+ inserts[s] = c
+ local width = getfield(getskip(s),"width")
+ if not result.inserts[s] then
+ currentskips = currentskips + width
+ end
+ nextskips = nextskips + width
+ end
+ c[#c+1] = nxt
+ if trace_detail then
+ report_state("insert of class %s found",s)
+ end
+ elseif nxtid == mark_code then
+ if trace_detail then
+ report_state("mark found")
+ end
+ else
+ break
+ end
+ nxt = getnext(nxt)
+ if nxt then
+ nxtid = getid(nxt)
+ else
+ break
+ end
+ end
+ return nxt, inserts, currentskips, nextskips, inserttotal
+end
+
+local function appendinserts(ri,inserts)
+ for class, collected in next, inserts do
+ local ric = ri[class]
+ if not ric then
+ -- assign to collected
+ ri[class] = collected
+ else
+ -- append to collected
+ for j=1,#collected do
+ ric[#ric+1] = collected[j]
+ end
+ end
+ end
+end
+
+local function discardtopglue(current,discarded)
+ local size = 0
+ while current do
+ local id = getid(current)
+ if id == glue_code then
+ size = size + getfield(current,"width")
+ discarded[#discarded+1] = current
+ current = getnext(current)
+ elseif id == penalty_code then
+ if getfield(current,"penalty") == forcedbreak then
+ discarded[#discarded+1] = current
+ current = getnext(current)
+ while current and getid(current) == glue_code do
+ size = size + getfield(current,"width")
+ discarded[#discarded+1] = current
+ current = getnext(current)
+ end
+ else
+ discarded[#discarded+1] = current
+ current = getnext(current)
+ end
+ else
+ break
+ end
+ end
+ if current then
+ setprev(current) -- prevent look back
+ end
+ return current, size
+end
+
+local function stripbottomglue(results,discarded)
+ local height = 0
+ for i=1,#results do
+ local r = results[i]
+ local t = r.tail
+ while t and t ~= r.head do
+ local prev = getprev(t)
+ if not prev then
+ break
+ end
+ local id = getid(t)
+ if id == penalty_code then
+ if getfield(t,"penalty") == forcedbreak then
+ break
+ else
+ discarded[#discarded+1] = t
+ r.tail = prev
+ t = prev
+ end
+ elseif id == glue_code then
+ discarded[#discarded+1] = t
+ local width = getfield(t,"width")
+ if trace_state then
+ report_state("columns %s, discarded bottom glue %p",i,width)
+ end
+ r.height = r.height - width
+ r.tail = prev
+ t = prev
+ else
+ break
+ end
+ end
+ if r.height > height then
+ height = r.height
+ end
+ end
+ return height
+end
+
+local function preparesplit(specification) -- a rather large function
+ local box = specification.box
+ if not box then
+ report_state("fatal error, no box")
+ return
+ end
+ local list = getbox(box)
+ if not list then
+ report_state("fatal error, no list")
+ return
+ end
+ local head = getlist(list) or specification.originalhead
+ if not head then
+ report_state("fatal error, no head")
+ return
+ end
+ slidenodes(head) -- we can have set prev's to nil to prevent backtracking
+ local discarded = { }
+ local originalhead = head
+ local originalwidth = specification.originalwidth or getfield(list,"width")
+ local originalheight = specification.originalheight or getfield(list,"height")
+ local current = head
+ local skipped = 0
+ local height = 0
+ local depth = 0
+ local skip = 0
+ local splitmethod = specification.splitmethod or false
+ if splitmethod == v_none then
+ splitmethod = false
+ end
+ local options = settings_to_hash(specification.option or "")
+ local stripbottom = specification.alternative == v_local
+ local cycle = specification.cycle or 1
+ local nofcolumns = specification.nofcolumns or 1
+ if nofcolumns == 0 then
+ nofcolumns = 1
+ end
+ local preheight = specification.preheight or 0
+ local extra = specification.extra or 0
+ local maxheight = specification.maxheight
+ local optimal = originalheight/nofcolumns
+ if specification.balance ~= v_yes then
+ optimal = maxheight
+ end
+ local topback = 0
+ local target = optimal + extra
+ local overflow = target > maxheight - preheight
+ local threshold = specification.threshold or 0
+ if overflow then
+ target = maxheight - preheight
+ end
+ if trace_state then
+ report_state("cycle %s, maxheight %p, preheight %p, target %p, overflow %a, extra %p",
+ cycle, maxheight, preheight , target, overflow, extra)
+ end
+ local results = { }
+ for i=1,nofcolumns do
+ results[i] = {
+ head = false,
+ tail = false,
+ height = 0,
+ depth = 0,
+ inserts = { },
+ delta = 0,
+ back = 0,
+ }
+ end
+
+ local column = 1
+ local line = 0
+ local result = results[1]
+ local lasthead = nil
+ local rest = nil
+ local lastlocked = nil
+ local lastcurrent = nil
+ local lastcontent = nil
+ local backtracked = false
+
+ if trace_state then
+ report_state("setting collector to column %s",column)
+ end
+
+ local function unlock(penalty)
+ if lastlocked then
+ if trace_state then
+ report_state("penalty %s, unlocking in column %s",penalty or "-",column)
+ end
+ lastlocked = nil
+ end
+ lastcurrent = nil
+ lastcontent = nil
+ end
+
+ local function lock(penalty,current)
+ if trace_state then
+ report_state("penalty %s, locking in column %s",penalty,column)
+ end
+ lastlocked = penalty
+ lastcurrent = current or lastcurrent
+ lastcontent = nil
+ end
+
+ local function backtrack(start)
+ local current = start
+ -- first skip over glue and penalty
+ while current do
+ local id = getid(current)
+ if id == glue_code then
+ if trace_state then
+ report_state("backtracking over %s in column %s","glue",column)
+ end
+ current = getprev(current)
+ elseif id == penalty_code then
+ if trace_state then
+ report_state("backtracking over %s in column %s","penalty",column)
+ end
+ current = getprev(current)
+ else
+ break
+ end
+ end
+ -- then skip over content
+ while current do
+ local id = getid(current)
+ if id == glue_code then
+ if trace_state then
+ report_state("quitting at %s in column %s","glue",column)
+ end
+ break
+ elseif id == penalty_code then
+ if trace_state then
+ report_state("quitting at %s in column %s","penalty",column)
+ end
+ break
+ else
+ current = getprev(current)
+ end
+ end
+ if not current then
+ if trace_state then
+ report_state("no effective backtracking in column %s",column)
+ end
+ current = start
+ end
+ return current
+ end
+
+ local function gotonext()
+ if lastcurrent then
+ if current ~= lastcurrent then
+ if trace_state then
+ report_state("backtracking to preferred break in column %s",column)
+ end
+ -- todo: also remember height/depth
+ current = backtrack(lastcurrent)
+ backtracked = true
+ end
+ lastcurrent = nil
+ if lastlocked then
+ if trace_state then
+ report_state("unlocking in column %s",column)
+ end
+ lastlocked = nil
+ end
+ end
+ if head == lasthead then
+ if trace_state then
+ report_state("empty column %s, needs more work",column)
+ end
+ rest = current
+ return false, 0
+ else
+ lasthead = head
+ result.head = head
+ if current == head then
+ result.tail = head
+ else
+ result.tail = getprev(current)
+ end
+ result.height = height
+ result.depth = depth
+ end
+ head = current
+ height = 0
+ depth = 0
+ if column == nofcolumns then
+ column = 0 -- nicer in trace
+ rest = head
+ return false, 0
+ else
+ local skipped
+ column = column + 1
+ result = results[column]
+ if trace_state then
+ report_state("setting collector to column %s",column)
+ end
+ current, skipped = discardtopglue(current,discarded)
+ if trace_detail and skipped ~= 0 then
+ report_state("check > column 1, discarded %p",skipped)
+ end
+ head = current
+ return true, skipped
+ end
+ end
+
+ local function checked(advance,where,locked)
+ local total = skip + height + depth + advance
+ local delta = total - target
+-- - 65536*3
+ local state = "same"
+ local okay = false
+ local skipped = 0
+ local curcol = column
+ if delta > threshold then
+ result.delta = delta
+ okay, skipped = gotonext()
+ if okay then
+ state = "next"
+ else
+ state = "quit"
+ end
+ end
+ if trace_detail then
+ report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p => %a (height %p, depth %p, skip %p)",
+ where,curcol,delta,threshold,advance,total,target,state,skipped,height,depth,skip)
+ end
+ return state, skipped
+ end
+
+ current, skipped = discardtopglue(current,discarded)
+ if trace_detail and skipped ~= 0 then
+ report_state("check > column 1, discarded %p",skipped)
+ end
+
+ -- problem: when we cannot break after a list (and we only can expect same-page situations as we don't
+ -- care too much about weighted breaks here) we should sort of look ahead or otherwise be able to push
+ -- back inserts and so
+ --
+ -- ok, we could use vsplit but we don't have that one opened up yet .. maybe i should look into the c-code
+ -- .. something that i try to avoid so let's experiment more before we entry dirty trick mode
+
+ head = current
+
+ local function process_skip(current,nxt)
+ local advance = getfield(current,"width")
+ if advance ~= 0 then
+ local state, skipped = checked(advance,"glue")
+ if trace_state then
+ report_state("%-7s > column %s, state %a, advance %p, height %p","glue",column,state,advance,height)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","glue",column,skipped)
+ end
+ end
+ if state == "quit" then
+ return true
+ end
+ height = height + depth + skip
+ depth = 0
+if advance < 0 then
+ height = height + advance
+ skip = 0
+ if height < 0 then
+ height = 0
+ end
+else
+ skip = height > 0 and advance or 0
+end
+ if trace_state then
+ report_state("%-7s > column %s, height %p, depth %p, skip %p","glue",column,height,depth,skip)
+ end
+ else
+ -- what else? ignore? treat as valid as usual?
+ end
+ if lastcontent then
+ unlock()
+ end
+ end
+
+ local function process_kern(current,nxt)
+ local advance = getfield(current,"kern")
+ if advance ~= 0 then
+ local state, skipped = checked(advance,"kern")
+ if trace_state then
+ report_state("%-7s > column %s, state %a, advance %p, height %p, state %a","kern",column,state,advance,height)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","kern",column,skipped)
+ end
+ end
+ if state == "quit" then
+ return true
+ end
+ height = height + depth + skip + advance
+ depth = 0
+ skip = 0
+ if trace_state then
+ report_state("%-7s > column %s, height %p, depth %p, skip %p","kern",column,height,depth,skip)
+ end
+ end
+ end
+
+ local function process_rule(current,nxt)
+ -- simple variant of h|vlist
+ local advance = getfield(current,"height") -- + getfield(current,"depth")
+ if advance ~= 0 then
+ local state, skipped = checked(advance,"rule")
+ if trace_state then
+ report_state("%-7s > column %s, state %a, rule, advance %p, height %p","rule",column,state,advance,inserttotal,height)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","rule",column,skipped)
+ end
+ end
+ if state == "quit" then
+ return true
+ end
+ height = height + depth + skip + advance
+ -- if state == "next" then
+ -- height = height + nextskips
+ -- else
+ -- height = height + currentskips
+ -- end
+ depth = getfield(current,"depth")
+ skip = 0
+ end
+ lastcontent = current
+ end
+
+ -- okay, here we could do some badness like magic but we want something
+ -- predictable and even better: strategies .. so eventually this will
+ -- become installable
+ --
+ -- [chapter] [penalty] [section] [penalty] [first line]
+
+ local function process_penalty(current,nxt)
+ local penalty = getfield(current,"penalty")
+ if penalty == 0 then
+ unlock(penalty)
+ elseif penalty == forcedbreak then
+ local needed = getattribute(current,a_checkedbreak)
+ local proceed = not needed or needed == 0
+ if not proceed then
+ local available = target - height
+ proceed = needed >= available
+ if trace_state then
+ report_state("cycle: %s, column %s, available %p, needed %p, %s break",cycle,column,available,needed,proceed and "forcing" or "ignoring")
+ end
+ end
+ if proceed then
+ unlock(penalty)
+ local okay, skipped = gotonext()
+ if okay then
+ if trace_state then
+ report_state("cycle: %s, forced column break, same page",cycle)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","penalty",column,skipped)
+ end
+ end
+ else
+ if trace_state then
+ report_state("cycle: %s, forced column break, next page",cycle)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","penalty",column,skipped)
+ end
+ end
+ return true
+ end
+ end
+ elseif penalty < 0 then
+ -- we don't care too much
+ unlock(penalty)
+ elseif penalty >= 10000 then
+ if not lastcurrent then
+ lock(penalty,current)
+ elseif penalty > lastlocked then
+ lock(penalty)
+ end
+ else
+ unlock(penalty)
+ end
+ end
+
+ local function process_list(current,nxt)
+ local nxtid = nxt and getid(nxt)
+ line = line + 1
+ local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0
+ local advance = getfield(current,"height")
+ if trace_state then
+ report_state("%-7s > column %s, content: %s","line",column,listtoutf(getlist(current),true,true))
+ end
+ if nxt and (nxtid == insert_code or nxtid == mark_code) then
+ nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid)
+ end
+ local state, skipped = checked(advance+inserttotal+currentskips,"line",lastlocked)
+ if trace_state then
+ report_state("%-7s > column %s, state %a, line %s, advance %p, insert %p, height %p","line",column,state,line,advance,inserttotal,height)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","line",column,skipped)
+ end
+ end
+ if state == "quit" then
+ return true
+ end
+-- if state == "next" then -- only when profile
+-- local unprofiled = theprop(current).unprofiled
+-- if unprofiled then
+-- local h = unprofiled.height
+-- local s = unprofiled.strutht
+-- local t = s/2
+-- print("profiled",h,s)
+-- local snapped = theprop(current).snapped
+-- if snapped then
+-- inspect(snapped)
+-- end
+-- if h < s + t then
+-- result.back = - (h - s)
+-- advance = s
+-- end
+-- end
+-- end
+ height = height + depth + skip + advance + inserttotal
+ if state == "next" then
+ height = height + nextskips
+ else
+ height = height + currentskips
+ end
+ depth = getfield(current,"depth")
+ skip = 0
+ if inserts then
+ -- so we already collect them ... makes backtracking tricky ... alternatively
+ -- we can do that in a separate loop ... no big deal either
+ appendinserts(result.inserts,inserts)
+ end
+ if trace_state then
+ report_state("%-7s > column %s, height %p, depth %p, skip %p","line",column,height,depth,skip)
+ end
+ lastcontent = current
+ end
+
+local kept = head
+
+ while current do
+
+ local id = getid(current)
+ local nxt = getnext(current)
+
+ backtracked = false
+
+ -- print("process",nodetostring(current))
+
+ if id == hlist_code or id == vlist_code then
+ if process_list(current,nxt) then break end
+ elseif id == glue_code then
+ if process_skip(current,nxt) then break end
+ elseif id == kern_code then
+ if process_kern(current,nxt) then break end
+ elseif id == penalty_code then
+ if process_penalty(current,nxt) then break end
+ elseif id == rule_code then
+ if process_rule(current,nxt) then break end
+ else
+ end
+
+ if backtracked then
+ -- print("pickup",nodetostring(current))
+ nxt = current
+ else
+ -- print("move on",nodetostring(current))
+ end
+
+ if nxt then
+ current = nxt
+ elseif head == lasthead then
+ -- to be checked but break needed as otherwise we have a loop
+ if trace_state then
+ report_state("quit as head is lasthead")
+ end
+ break
+ else
+ local r = results[column]
+ r.head = head
+ r.tail = current
+ r.height = height
+ r.depth = depth
+ break
+ end
+ end
+
+ if not current then
+ if trace_state then
+ report_state("nothing left")
+ end
+ -- needs well defined case
+ -- rest = nil
+ elseif rest == lasthead then
+ if trace_state then
+ report_state("rest equals lasthead")
+ end
+ -- test case: x\index{AB} \index{AA}x \blank \placeindex
+ -- makes line disappear: rest = nil
+ end
+
+ if stripbottom then
+ local height = stripbottomglue(results,discarded)
+ if height > 0 then
+ target = height
+ end
+ end
+
+ specification.results = results
+ specification.height = target
+ specification.originalheight = originalheight
+ specification.originalwidth = originalwidth
+ specification.originalhead = originalhead
+ specification.targetheight = target or 0
+ specification.rest = rest
+ specification.overflow = overflow
+ specification.discarded = discarded
+
+ setlist(getbox(specification.box),nil)
+
+ return specification
+end
+
+local function finalize(result)
+ if result then
+ local results = result.results
+ local columns = result.nofcolumns
+ local maxtotal = 0
+ for i=1,columns do
+ local r = results[i]
+ local h = r.head
+ if h then
+ setprev(h)
+if r.back then
+ local k = new_glue(r.back)
+ setlink(k,h)
+ h = k
+ r.head = h
+end
+ local t = r.tail
+ if t then
+ setnext(t,nil)
+ else
+ setnext(h,nil)
+ r.tail = h
+ end
+ for c, list in next, r.inserts do
+ local t = { }
+ for i=1,#list do
+ local l = list[i]
+ local h = new_hlist()
+ t[i] = h
+ setlist(h,getfield(l,"head"))
+ setfield(h,"height",getfield(l,"height"))
+ setfield(h,"depth",getfield(l,"depth"))
+ setfield(l,"head",nil)
+ end
+ setprev(t[1]) -- needs checking
+ setnext(t[#t]) -- needs checking
+ r.inserts[c] = t
+ end
+ end
+ local total = r.height + r.depth
+ if total > maxtotal then
+ maxtotal = total
+ end
+ r.total = total
+ end
+ result.maxtotal = maxtotal
+ for i=1,columns do
+ local r = results[i]
+ r.extra = maxtotal - r.total
+ end
+ end
+end
+
+local splitruns = 0
+
+local function report_deltas(result,str)
+ local t = { }
+ for i=1,result.nofcolumns do
+ t[#t+1] = points(result.results[i].delta or 0)
+ end
+ report_state("%s, cycles %s, deltas % | t",str,result.cycle or 1,t)
+end
+
+local function setsplit(specification)
+ splitruns = splitruns + 1
+ if trace_state then
+ report_state("split run %s",splitruns)
+ end
+ local result = preparesplit(specification)
+ if result then
+ if result.overflow then
+ if trace_state then
+ report_deltas(result,"overflow")
+ end
+ -- we might have some rest
+ elseif result.rest and specification.balance == v_yes then
+ local step = specification.step or 65536*2
+ local cycle = 1
+ local cycles = specification.cycles or 100
+ while result.rest and cycle <= cycles do
+ specification.extra = cycle * step
+ result = preparesplit(specification) or result
+ if trace_state then
+ report_state("cycle: %s.%s, original height %p, total height %p",
+ splitruns,cycle,result.originalheight,result.nofcolumns*result.targetheight)
+ end
+ cycle = cycle + 1
+ specification.cycle = cycle
+ end
+ if cycle > cycles then
+ report_deltas(result,"too many balancing cycles")
+ elseif trace_state then
+ report_deltas(result,"balanced")
+ end
+ elseif trace_state then
+ report_deltas(result,"done")
+ end
+ return result
+ elseif trace_state then
+ report_state("no result")
+ end
+end
+
+local function getsplit(result,n)
+ if not result then
+ report_state("flush, column %s, no result",n)
+ return
+ end
+ local r = result.results[n]
+ if not r then
+ report_state("flush, column %s, empty",n)
+ end
+ local h = r.head
+ if not h then
+ return new_glue(result.originalwidth)
+ end
+
+ setprev(h) -- move up
+ local strutht = result.strutht
+ local strutdp = result.strutdp
+ local lineheight = strutht + strutdp
+ local isglobal = result.alternative == v_global
+
+ local v = new_vlist()
+ setlist(v,h)
+
+ -- local v = vpack(h,"exactly",height)
+
+ if isglobal then -- option
+ result.height = result.maxheight
+ end
+
+ local ht = 0
+ local dp = 0
+ local wd = result.originalwidth
+
+ local grid = result.grid
+ local internalgrid = result.internalgrid
+ local httolerance = .25
+ local dptolerance = .50
+ local lineheight = internalgrid == v_halfline and lineheight/2 or lineheight
+
+ local function amount(r,s,t)
+ local l = ceil((r-t)/lineheight)
+ local a = lineheight * l
+ if a > s then
+ return a - s
+ else
+ return s
+ end
+ end
+
+ if grid then
+ -- print(n,result.maxtotal,r.total,r.extra)
+ if isglobal then
+ local rh = r.height
+ -- ht = (lineheight * ceil(result.height/lineheight) - strutdp
+ ht = amount(rh,strutdp,0)
+ dp = strutdp
+ else
+ -- natural dimensions
+ local rh = r.height
+ local rd = r.depth
+ if rh > ht then
+ ht = amount(rh,strutdp,httolerance*strutht)
+ end
+ if rd > dp then
+ dp = amount(rd,strutht,dptolerance*strutdp)
+ end
+ -- forced dimensions
+ local rh = result.height or 0
+ local rd = result.depth or 0
+ if rh > ht then
+ ht = amount(rh,strutdp,httolerance*strutht)
+ end
+ if rd > dp then
+ dp = amount(rd,strutht,dptolerance*strutdp)
+ end
+ -- always one line at least
+ if ht < strutht then
+ ht = strutht
+ end
+ if dp < strutdp then
+ dp = strutdp
+ end
+ end
+ else
+ ht = result.height
+ dp = result.depth
+ end
+
+ setfield(v,"width",wd)
+ setfield(v,"height",ht)
+ setfield(v,"depth",dp)
+
+ if trace_state then
+ local id = getid(h)
+ if id == hlist_code then
+ report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"top line",listtoutf(getlist(h)))
+ else
+ report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"head node",nodecodes[id])
+ end
+ end
+
+ for c, list in next, r.inserts do
+ local l = concatnodes(list)
+ local b = vpack(l) -- multiple arguments, todo: fastvpack
+ -- setbox("global",c,b)
+ setbox(c,b)
+ r.inserts[c] = nil
+ end
+
+ return v
+end
+
+local function getrest(result)
+ local rest = result and result.rest
+ result.rest = nil -- to be sure
+ return rest
+end
+
+local function getlist(result)
+ local originalhead = result and result.originalhead
+ result.originalhead = nil -- to be sure
+ return originalhead
+end
+
+local function cleanup(result)
+ local discarded = result.discarded
+ for i=1,#discarded do
+ freenode(discarded[i])
+ end
+ result.discarded = { }
+end
+
+mixedcolumns.setsplit = setsplit
+mixedcolumns.getsplit = getsplit
+mixedcolumns.finalize = finalize
+mixedcolumns.getrest = getrest
+mixedcolumns.getlist = getlist
+mixedcolumns.cleanup = cleanup
+
+-- interface --
+
+local result
+
+implement {
+ name = "mixsetsplit",
+ actions = function(specification)
+ if result then
+ for k, v in next, specification do
+ result[k] = v
+ end
+ result = setsplit(result)
+ else
+ result = setsplit(specification)
+ end
+ end,
+ arguments = {
+ {
+ { "box", "integer" },
+ { "nofcolumns", "integer" },
+ { "maxheight", "dimen" },
+ { "step", "dimen" },
+ { "cycles", "integer" },
+ { "preheight", "dimen" },
+ { "prebox", "integer" },
+ { "strutht", "dimen" },
+ { "strutdp", "dimen" },
+ { "threshold", "dimen" },
+ { "splitmethod" },
+ { "balance" },
+ { "alternative" },
+ { "internalgrid" },
+ { "grid", "boolean" },
+ }
+ }
+}
+
+implement {
+ name = "mixgetsplit",
+ arguments = "integer",
+ actions = function(n)
+ if result then
+ context(tonode(getsplit(result,n)))
+ end
+ end,
+}
+
+implement {
+ name = "mixfinalize",
+ actions = function()
+ if result then
+ finalize(result)
+ end
+ end
+}
+
+implement {
+ name = "mixflushrest",
+ actions = function()
+ if result then
+ context(tonode(getrest(result)))
+ end
+ end
+}
+
+implement {
+ name = "mixflushlist",
+ actions = function()
+ if result then
+ context(tonode(getlist(result)))
+ end
+ end
+}
+
+implement {
+ name = "mixstate",
+ actions = function()
+ context(result and result.rest and 1 or 0)
+ end
+}
+
+implement {
+ name = "mixcleanup",
+ actions = function()
+ if result then
+ cleanup(result)
+ result = nil
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv
new file mode 100644
index 00000000000..0e329ce098b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv
@@ -0,0 +1,959 @@
+%D \module
+%D [ file=page-mix,
+%D version=2012.07.12,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Mixed Columns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Mixed Columns}
+
+%D This is a very experimental module. Eventually it will replace the current
+%D multi column mechanism (that then will be an instance). The \LUA\ part of
+%D the interface will quite probably change so don't use that one directly
+%D (yet).
+
+% todo:
+%
+% consult note class
+% notes per page
+% notes in each column
+% notes in last column
+% notes local/global
+% top and bottom inserts
+% wide floats
+% move floats
+% offsets (inner ones, so we change the hsize ... needed with backgrounds
+% when no content we currently loose the page
+
+% luatex buglet:
+%
+% \ctxlua{tex.setbox("global",0,node.hpack(nodes.pool.glyph("a",font.current())))}\box0
+
+\registerctxluafile{page-mix}{1.001}
+
+\unprotect
+
+%D The mixed output routine replaces the traditional multi column handler that
+%D started out in \MKII. One of the complications of a routine is that it needs
+%D to align nicely when mixed in a single column layout. Instead of using all
+%D kind of shift juggling in this mechanism we simply switch to grid mode
+%D locally. After all, columns don't look nice when not on a. As the grid
+%D snapper in \MKIV\ is more advanced not that much extra code is needed.
+
+%D We use the command handler but the parent settings are not to be changed.
+%D Instead we could have used a dedicated root setup, but it's not worth the
+%D trouble.
+
+\installcorenamespace{mixedcolumns}
+
+\installframedcommandhandler \??mixedcolumns {mixedcolumns} \??mixedcolumns
+
+\setupmixedcolumns
+ [\c!distance=1.5\bodyfontsize,
+ \c!n=\plustwo,
+ %\c!align=, % inherit
+ %\c!before=,
+ %\c!after=,
+ %\c!separator=\v!none,
+ %\c!setups=,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!alternative=\v!local,
+ \c!maxheight=\textheight,
+ \c!maxwidth=\makeupwidth,
+ \c!grid=\v!tolerant,
+ \c!internalgrid=\v!line,
+ \c!step=.25\lineheight, % needs some experimenting
+ %\c!splitmethod=\v!fixed, % will be default
+ \c!direction=\v!normal, % new (also todo in the new columnsets)
+ \c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS
+
+\let\startmixedcolumns\relax % defined later
+\let\stopmixedcolumns \relax % defined later
+
+\appendtoks % could become an option
+ \setuevalue{\e!start\currentmixedcolumns}{\startmixedcolumns[\currentmixedcolumns]}%
+ \setuevalue{\e!stop \currentmixedcolumns}{\stopmixedcolumns}%
+\to \everydefinemixedcolumns
+
+%D In order to avoid a mixup we use quite some local registers.
+
+\newdimen \d_page_mix_column_width
+\newdimen \d_page_mix_max_height
+\newdimen \d_page_mix_max_width
+\newdimen \d_page_mix_distance
+\newcount \c_page_mix_n_of_columns
+\newdimen \d_page_mix_threshold
+\newdimen \d_page_mix_leftskip
+\newdimen \d_page_mix_rightskip
+
+\newdimen \d_page_mix_balance_step
+\setnewconstant\c_page_mix_balance_cycles 500
+
+\setnewconstant\c_page_mix_break_forced -123
+
+\newbox \b_page_mix_preceding
+\newdimen \d_page_mix_preceding_height
+
+\newbox \b_page_mix_collected
+
+\newconstant \c_page_mix_routine
+
+\setnewconstant\c_page_mix_routine_regular \zerocount
+\setnewconstant\c_page_mix_routine_intercept\plusone
+\setnewconstant\c_page_mix_routine_continue \plustwo
+\setnewconstant\c_page_mix_routine_balance \plusthree
+\setnewconstant\c_page_mix_routine_error \plusfour
+
+%D The main environment is called as follows:
+%D
+%D \starttyping
+%D \startmixedcolumns[instance][settings]
+%D \startmixedcolumns[instance]
+%D \startmixedcolumns[settings]
+%D \stoptyping
+%D
+%D However, best is not to use this one directly but define an instance and
+%D use that one.
+
+% % For the moment only on my machine:
+%
+% \definemixedcolumns
+% [\v!columns]
+%
+% \unexpanded\def\setupcolumns
+% {\setupmixedcolumns[\v!columns]}
+
+%D In itemizations we also need columns, so let's define a apecial instance
+%D for them. These need to work well in situations like this:
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two,packed][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\ifdefined\s!itemgroupcolumns \else \def\s!itemgroupcolumns{itemgroupcolumns} \fi
+
+\definemixedcolumns
+ [\s!itemgroupcolumns]
+ [\c!n=\itemgroupparameter\c!n,
+ \c!direction=\itemgroupparameter\c!direction,
+ \c!separator=\v!none,
+ \c!splitmethod=\v!none,
+ \c!grid=\v!tolerant,
+ \c!internalgrid=\v!halfline, % new, we may still revert to \v!line
+ \c!balance=\v!yes]
+
+% better
+
+\setupmixedcolumns
+ [\s!itemgroupcolumns]
+ [\c!splitmethod=\v!fixed,
+ \c!grid=\v!yes,
+ \c!internalgrid=\v!line]
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one
+
+\unexpanded\def\strc_itemgroups_stop_columns
+ {\stopmixedcolumns}
+
+%D The mixed output routine can be in different states. First we need to intercept
+%D the already present content. This permits mixed single and multi column usage.
+%D Then we have the continuous routine, one that intercepts pages in sequence.
+%D Finally, when we finish the mixed columns mode, we can (optionally) balance the
+%D last page.
+
+\unexpanded\def\page_mix_command_routine
+ {\ifcase\c_page_mix_routine
+ \page_one_command_routine
+ \or
+ \page_mix_routine_intercept
+ \or
+ \page_mix_routine_continue
+ \or
+ \page_mix_routine_balance
+ \or
+ \page_mix_routine_error
+ \fi}
+
+%D The interceptor is quite simple, at least for the moment.
+
+\def\page_mix_routine_intercept
+ {\ifdim\pagetotal>\pagegoal
+ % testcase: preceding-001 ... if we don't do this, text can disappear as
+ % preceding is overwritten ... needs to be figured out some day
+ \page_one_command_routine
+ \fi
+ \global\setbox\b_page_mix_preceding\vbox % pack ?
+ {\page_otr_command_flush_top_insertions
+ \ifdim\htdp\b_page_mix_preceding=\zeropoint \else
+ \writestatus\m!columns{preceding error}%
+ \unvbox\b_page_mix_preceding
+ \fi
+ \unvbox\normalpagebox}}
+
+%D The error routine is there but unlikely to be called. It is a left-over from
+%D the traditional routine that might come in handy some day.
+
+\def\page_mix_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+%D Some settings (and actions) depend on the current output routine and setting the
+%D hsize and vsize is among them. The calculation of the hsize is done elsewhere.
+
+\unexpanded\def\page_mix_command_set_hsize
+ {\hsize\d_page_mix_column_width
+ \textwidth\d_page_mix_column_width}
+
+%D When setting the vsize we make sure that we collect a few more lines than needed
+%D so that we have enough to split over the columns. Collecting too much is somewhat
+%D tricky as they will spill over to the next page.
+
+\unexpanded\def\page_mix_command_set_vsize
+ {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax
+ \pagegoal\vsize}
+
+%D As we use \LUA\ there is the usual amount of tracing at that end. At the tex end
+%D we only visualize boxes.
+
+\let\page_mix_hbox\hbox
+\let\page_mix_vbox\vbox
+
+\installtextracker
+ {mixedcolumns.boxes}
+ {\let\page_mix_hbox\ruledhbox
+ \let\page_mix_vbox\ruledvbox}
+ {\let\page_mix_hbox\hbox
+ \let\page_mix_vbox\vbox}
+
+%D We provide a few column break options. Interesting is that while forcing a new
+%D column in the traditional mechanism was a pain, here it works quite well.
+
+\installcolumnbreakmethod \s!mixedcolumn \v!preference
+ {\goodbreak}
+
+\installcolumnbreakmethod \s!mixedcolumn \v!yes
+ {\par
+ \penalty\c_page_mix_break_forced\relax}
+
+%D As we operate in grid snapping mode, we use a dedicated macro to enable this
+%D mechamism.
+
+\def\page_mix_enable_grid_snapping
+ {\edef\p_grid{\mixedcolumnsparameter\c!grid}%
+ \ifx\p_grid\empty
+ % just follow the default grid settings
+ \else
+ \gridsnappingtrue
+ \setsystemmode\v!grid
+ \spac_grids_snap_value_set\p_grid
+ \fi}
+
+%D Between columns there is normally just spacing unless one enforces a rule.
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startmixedcolumns[n=2,background=color,backgroundcolor=red,rulethickness=1mm,rulecolor=green,separator=rule]
+%D \input zapf
+%D \stopmixedcolumns
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\installcorenamespace{mixedcolumnsseparator}
+
+\unexpanded\def\installmixedcolumnseparator#1#2%
+ {\setvalue{\??mixedcolumnsseparator#1}{#2}}
+
+\installmixedcolumnseparator\v!rule
+ {\vrule
+ \s!width \mixedcolumnsparameter\c!rulethickness
+ \s!height\mixedcolumnseparatorheight
+ \s!depth \mixedcolumnseparatordepth
+ \relax}
+
+\unexpanded\def\page_mix_command_inject_separator
+ {\begingroup
+ \setbox\scratchbox\hbox to \zeropoint \bgroup
+ \hss
+ \starttextproperties
+ \usemixedcolumnscolorparameter\c!rulecolor
+ \begincsname\??mixedcolumnsseparator\p_separator\endcsname % was \c!rule
+ \stoptextproperties
+ \hss
+ \egroup
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \hss
+ \box\scratchbox
+ \hss
+ \endgroup}
+
+%D We've now arrived at the real code. The start command mostly sets up the
+%D environment and variables that are used in the splitter. One of the last
+%D things happening at the start is switching over to the mixed continuous
+%D routine.
+
+\installcorenamespace{mixedcolumnsbefore}
+\installcorenamespace{mixedcolumnsstart}
+\installcorenamespace{mixedcolumnsstop}
+\installcorenamespace{mixedcolumnsafter}
+
+%D For practical reasons there is always a first argument needed that
+%D indicates the class.
+%D
+%D \starttyping
+%D \startmixedcolumns[n=3,alternative=global]
+%D \dorecurse{200}{Zomaar wat #1 met een footnote\footnote{note #1}. }
+%D \stopmixedcolumns
+%D \stoptyping
+
+\let\currentmixedcolumnsmethod\empty
+
+\unexpanded\def\startmixedcolumns
+ {\dodoubleempty\page_mix_start_columns}
+
+\unexpanded\def\page_mix_start_columns
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \ifsecondargument
+ \singleexpandafter\page_mix_start_columns_a
+ \else\iffirstargument
+ \doubleexpandafter\page_mix_start_columns_b
+ \else
+ \doubleexpandafter\page_mix_start_columns_c
+ \fi\fi}
+
+\def\page_mix_start_columns_a[#1][#2]%
+ {\edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \setupcurrentmixedcolumns[#2]%
+ \page_mix_initialize_columns
+ \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\def\page_mix_start_columns_b[#1][#2]%
+ {\doifelseassignment{#1}%
+ {\let\currentmixedcolumns\empty
+ \page_mix_error_b}
+ {\edef\currentmixedcolumns{#1}%
+ \firstargumentfalse}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings !
+ \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \iffirstargument
+ \setupcurrentmixedcolumns[#1]%
+ \fi
+ \page_mix_initialize_columns
+ \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+\def\page_mix_error_b
+ {\writestatus\m!columns{best use an instance of mixed columns}}
+
+\def\page_mix_start_columns_c[#1][#2]%
+ {\let\currentmixedcolumns\empty
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\unexpanded\def\page_mix_fast_columns_start#1%
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings !
+ \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+%D When we stop, we switch over to the balancing routine. After we're done we
+%D make sure to set the sizes are set, a somewhat redundant action when we
+%D already have flushed but better be safe.
+
+\unexpanded\def\stopmixedcolumns
+ {\begincsname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax
+ \endgroup
+ \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
+ \mixedcolumnsparameter\c!after\relax
+ \popmacro\currentmixedcolumnsmethod
+ \popmacro\currentmixedcolumns}
+
+% \unexpanded\def\stopmixedcolumns
+% {\begincsname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax
+% \endgroup
+% \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
+% \mixedcolumnsparameter\c!after\relax
+% \ifx\currentmixedcolumnsmethod\s!otr
+% \popmacro\currentmixedcolumnsmethod
+% \popmacro\currentmixedcolumns
+% \synchronizeoutput % brrr, otherwise sometimes issues in itemize
+% \else
+% \popmacro\currentmixedcolumnsmethod
+% \popmacro\currentmixedcolumns
+% \fi
+% }
+
+\let\page_mix_fast_columns_stop\stopmixedcolumns
+
+%D This is how the fast one is used:
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\page_mix_fast_columns_start\s!itemgroupcolumns}
+
+\let\strc_itemgroups_stop_columns\page_mix_fast_columns_stop
+
+\setupmixedcolumns
+ [\s!itemgroupcolumns]
+ [\c!grid=\itemgroupparameter\c!grid]
+
+% better
+
+%D The common initialization:
+
+\def\page_mix_initialize_columns
+ {\page_mix_enable_grid_snapping
+ %
+ \d_page_mix_distance \mixedcolumnsparameter\c!distance
+ \c_page_mix_n_of_columns\mixedcolumnsparameter\c!n
+ \d_page_mix_max_height \mixedcolumnsparameter\c!maxheight
+ \d_page_mix_max_width \mixedcolumnsparameter\c!maxwidth
+ \d_page_mix_balance_step\mixedcolumnsparameter\c!step
+ %
+ \d_page_mix_max_width\dimexpr\d_page_mix_max_width-\leftskip-\rightskip\relax
+ \d_page_mix_leftskip \leftskip
+ \d_page_mix_rightskip\rightskip
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ %
+ \d_page_mix_threshold\zeropoint
+ %
+ \d_page_mix_column_width\dimexpr(\d_page_mix_max_width-\d_page_mix_distance*\numexpr(\c_page_mix_n_of_columns-\plusone)\relax)/\c_page_mix_n_of_columns\relax
+ %
+ \usemixedcolumnscolorparameter\c!color
+ %
+ \insidecolumnstrue % new
+ %
+ \useprofileparameter\mixedcolumnsparameter % new
+ %
+ \nofcolumns\c_page_mix_n_of_columns} % public
+
+%D The otr method related hooks are defined next:
+
+% \setvalue{\??mixedcolumnsbefore\s!otr}%
+% {\par
+% \ifdim\pagetotal=\zeropoint \else
+% \verticalstrut % probably no longer needed
+% \vskip-\struttotal % probably no longer needed
+% \fi}
+
+\newcount\c_page_mix_otr_nesting
+
+% \setvalue{\??mixedcolumnsbefore\s!otr}%
+% {\par
+% \global\advance\c_page_mix_otr_nesting\plusone
+% \ifcase\c_page_mix_otr_nesting\or
+% \ifdim\pagetotal=\zeropoint \else
+% \obeydepth % we could handle this in pre material
+% \fi
+% \fi}
+
+\setvalue{\??mixedcolumnsbefore\s!otr}%
+ {\par
+ \global\advance\c_page_mix_otr_nesting\plusone
+ \ifcase\c_page_mix_otr_nesting\or
+ \ifdim\pagetotal=\zeropoint \else
+ % make sure that whitespace an dblanks are done
+ \strut
+ \vskip-\lineheight
+ % no, bad spacing: \obeydepth % we could handle this in pre material
+ \fi
+ \fi}
+
+\setvalue{\??mixedcolumnsstart\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \scratchwidth\textwidth
+ \setupoutputroutine[\s!mixedcolumn]%
+ \c_page_mix_routine\c_page_mix_routine_intercept
+ \page_otr_trigger_output_routine
+ %
+ \holdinginserts\maxdimen
+ %
+ \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\vpack{\box\b_page_mix_preceding}%
+ \wd\b_page_mix_preceding\scratchwidth % \makeupwidth
+ \page_grids_add_to_one\b_page_mix_preceding
+ \fi
+ \global\d_page_mix_preceding_height\ht\b_page_mix_preceding
+ \c_page_mix_routine\c_page_mix_routine_continue
+ %
+ \page_mix_command_set_vsize
+ \page_mix_command_set_hsize
+ \fi
+ \usealignparameter\mixedcolumnsparameter
+ \usesetupsparameter\mixedcolumnsparameter}
+
+% \setvalue{\??mixedcolumnsstop\s!otr}%
+% {\par
+% \ifcase\c_page_mix_otr_nesting\or
+% \c_page_mix_routine\c_page_mix_routine_balance
+% \page_otr_trigger_output_routine
+% \fi}
+
+\setvalue{\??mixedcolumnsstop\s!otr}%
+ {\par
+ \ifcase\c_page_mix_otr_nesting\or
+ \doifelse{\mixedcolumnsparameter\c!balance}\v!yes
+ {\c_page_mix_routine\c_page_mix_routine_balance}%
+ {\penalty-\plustenthousand}% weird hack, we need to trigger the otr sometimes (new per 20140306, see balancing-001.tex)
+ \page_otr_trigger_output_routine
+ \ifvoid\b_page_mix_preceding \else
+ % empty columns so we need to make sure pending content is flushed
+ \unvbox\b_page_mix_preceding % new per 2014.10.25
+ \fi
+ \fi}
+
+\setvalue{\??mixedcolumnsafter\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \prevdepth\strutdp
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \fi
+ \global\advance\c_page_mix_otr_nesting\minusone}
+
+%D The splitting and therefore balancing is done at the \LUA\ end. This gives
+%D more readable code and also makes it easier to deal with insertions like
+%D footnotes. Eventually we will have multiple strategies available.
+
+\unexpanded\def\page_mix_routine_construct#1%
+ {\d_page_mix_max_height\mixedcolumnsparameter\c!maxheight % can have changed due to header=high
+ \clf_mixsetsplit
+ box \b_page_mix_collected
+ nofcolumns \c_page_mix_n_of_columns
+ maxheight \d_page_mix_max_height
+ step \d_page_mix_balance_step
+ cycles \c_page_mix_balance_cycles
+ preheight \d_page_mix_preceding_height
+ prebox \b_page_mix_preceding
+ strutht \strutht
+ strutdp \strutdp
+ threshold \d_page_mix_threshold
+ splitmethod {\mixedcolumnsparameter\c!splitmethod}%
+ balance {#1}%
+ alternative {\mixedcolumnsparameter\c!alternative}%
+ internalgrid {\mixedcolumnsparameter\c!internalgrid}%
+ grid \ifgridsnapping true\else false\fi
+ \relax
+ \deadcycles\zerocount}
+
+\newdimen\mixedcolumnseparatorheight
+\newdimen\mixedcolumnseparatordepth
+\newdimen\mixedcolumnseparatorwidth
+
+\def\page_mix_routine_package_step
+ {% needs packaging anyway
+ \setbox\scratchbox\page_mix_command_package_column
+ \page_lines_add_numbers_to_box\scratchbox\recurselevel\c_page_mix_n_of_columns\plusone % new
+ \page_marks_synchronize_column\plusone\c_page_mix_n_of_columns\recurselevel\scratchbox
+ % backgrounds
+ \anch_mark_column_box\scratchbox
+ % for the moment a quick and dirty patch .. we need to go into the box (hence the \plusone) .. a slowdowner
+ % moved to start: \page_lines_add_numbers_to_box\scratchbox\recurselevel\c_page_mix_n_of_columns\plusone
+ % the framed needs a reset of strut, align, setups etc
+ \mixedcolumnseparatorheight\ht\scratchbox
+ \mixedcolumnseparatordepth \dp\scratchbox
+ \inheritedmixedcolumnsframedbox\currentmixedcolumns\scratchbox}
+
+\def\page_mix_routine_package_separate
+ {\ifcsname\??mixedcolumnsseparator\p_separator\endcsname
+ \page_mix_command_inject_separator
+ \else
+ \hss
+ \fi}
+
+\unexpanded\def\page_mix_routine_package
+ {\clf_mixfinalize
+ \setbox\b_page_mix_collected\vbox \bgroup
+ \ifvoid\b_page_mix_preceding \else
+ % \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding % already done
+ \vpack\bgroup
+ \box\b_page_mix_preceding
+ \egroup
+ \global\d_page_mix_preceding_height\zeropoint
+ \nointerlineskip
+ % no no:
+ % \prevdepth\strutdepth
+ \fi
+ \hskip\d_page_mix_leftskip
+ \page_mix_hbox to \d_page_mix_max_width \bgroup
+ \edef\p_separator{\mixedcolumnsparameter\c!separator}%
+ \mixedcolumnseparatorwidth\d_page_mix_distance % \mixedcolumnsparameter\c!rulethickness\relax
+ \edef\p_direction{\mixedcolumnsparameter\c!direction}%
+ \ifx\p_direction\v!reverse
+ \dostepwiserecurse\c_page_mix_n_of_columns\plusone\minusone
+ {\page_mix_routine_package_step
+ \ifnum\recurselevel>\plusone
+ \page_mix_routine_package_separate
+ \fi}%
+ \else
+ \dorecurse\c_page_mix_n_of_columns
+ {\page_mix_routine_package_step
+ \ifnum\recurselevel<\c_page_mix_n_of_columns
+ \page_mix_routine_package_separate
+ \fi}%
+ \fi
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_command_package_column
+ {\page_mix_hbox to \d_page_mix_column_width \bgroup
+ % maybe intercept empty
+ \clf_mixgetsplit\recurselevel\relax
+ \hskip-\d_page_mix_column_width
+ \page_mix_hbox to \d_page_mix_column_width \bgroup
+ \placenoteinserts
+ \hss
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_routine_continue
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vpack{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \page_mix_routine_construct\v!no
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \clf_mixflushrest
+ \clf_mixcleanup
+ \egroup}
+
+\unexpanded\def\page_mix_routine_balance
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vpack{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \doloop
+ {%writestatus\m!columns{construct continue (\the\htdp\b_page_mix_collected)}%
+ \page_mix_routine_construct\v!no
+ \ifcase\clf_mixstate\relax
+ % 0 = okay, we can balance
+ \setbox\b_page_mix_collected\vpack{\clf_mixflushlist}% we could avoid this
+ %writestatus\m!columns{construct balance}%
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \c_page_mix_routine\c_page_mix_routine_regular
+ % \setupoutputroutine[\s!singlecolumn]%
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \par
+ %writestatus\m!columns{flush balance}%
+ \page_grids_add_to_mix\b_page_mix_collected % no linenumbers here
+ \box\b_page_mix_collected
+ \vskip\zeropoint % triggers recalculation of page stuff (weird that this is needed but it *is* needed, see mixed-001.tex)
+ \par
+ \nointerlineskip
+ \prevdepth\strutdp
+ \clf_mixflushrest% rubish
+ \clf_mixcleanup % rubish
+ \exitloop
+ \or
+ % 1 = we have stuff left, so flush and rebalance
+ %writestatus\m!columns{flush continue}%
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \setbox\b_page_mix_collected\vpack{\clf_mixflushrest}% we could avoid this
+ \clf_mixcleanup
+ \ifdim\ht\b_page_mix_collected=\zeropoint
+ \exitloop
+ \fi
+ \fi}%
+ \egroup}
+
+%D We also implement a variant compatible with the so called simple columns
+%D mechanism:
+%D
+%D \starttyping
+%D \startboxedcolumns
+%D \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+%D
+%D This is a rather mininimalistic variant.
+
+% Maybe we also need a variant with obeydepth before and prevdepth after so
+% that we get a nice spacing.
+
+\definemixedcolumns
+ [boxedcolumns]
+ [\c!balance=\v!yes,
+ \c!n=2,
+ \c!method=\s!box,
+ \c!strut=\v!yes,
+ \c!maxwidth=\availablehsize]
+
+%D Boxed columns can be used nested:
+%D
+%D \starttyping
+%D \setupmixedcolumns
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=darkred,
+%D color=white,
+%D backgroundoffset=1mm]
+%D
+%D \definemixedcolumns
+%D [nestedboxedcolumns]
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=white,
+%D color=darkred,
+%D strut=yes,
+%D backgroundoffset=0mm]
+%D
+%D \startboxedcolumns
+%D \input zapf \par \input ward \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+
+%D Next we define the hooks:
+
+\letvalue{\??mixedcolumnsbefore\s!box}\donothing
+\letvalue{\??mixedcolumnsafter \s!box}\donothing
+
+% \setvalue{\??mixedcolumnsstart\s!box}%
+% {\edef\p_page_mix_strut{\mixedcolumnsparameter\c!strut}%
+% \setbox\b_page_mix_collected\vbox\bgroup
+% \let\currentoutputroutine\s!mixedcolumn % makes \column work
+% \forgetall
+% \page_mix_command_set_hsize
+% \ifx\p_page_mix_strut\v!yes
+% \begstrut
+% \ignorespaces
+% \fi}
+%
+% \setvalue{\??mixedcolumnsstop\s!box}%
+% {\ifx\p_page_mix_strut\v!yes
+% \removeunwantedspaces
+% \endstrut
+% \fi
+% \egroup
+% \page_mix_box_balance}
+
+\setvalue{\??mixedcolumnsstart\s!box}%
+ {\edef\p_page_mix_strut{\mixedcolumnsparameter\c!strut}%
+ \setbox\b_page_mix_collected\vbox \bgroup
+ \let\currentoutputroutine\s!mixedcolumn % makes \column work
+ \forgetall
+ \usegridparameter\mixedcolumnsparameter
+ % \useprofileparameter\mixedcolumnsparameter
+ \page_mix_command_set_hsize
+ \ifx\p_page_mix_strut\v!yes
+ \begstrut
+ \ignorespaces
+ \fi}
+
+\setvalue{\??mixedcolumnsstop\s!box}%
+ {\ifx\p_page_mix_strut\v!yes
+ \removeunwantedspaces
+ \endstrut
+ \fi
+ \egroup
+ \edef\p_profile{\mixedcolumnsparameter\c!profile}%
+ \ifx\p_profile\empty \else
+ % this can never be ok because we cheat with depth and height
+ % and glue in between and when we're too large we run into issues
+ % so mayb best limit correction to one line
+ \profilegivenbox\p_profile\b_page_mix_collected
+ \setbox\b_page_mix_collected\vpack{\unvbox\b_page_mix_collected}%
+ % tracing
+ % \addprofiletobox\b_page_mix_collected
+ \fi
+ \page_mix_box_balance}
+
+%D The related balancer is only a few lines:
+
+\unexpanded\def\page_mix_box_balance
+ {\bgroup
+ \dontcomplain
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \dontleavehmode\box\b_page_mix_collected
+ \clf_mixflushrest
+ \clf_mixcleanup
+ \egroup}
+
+%D As usual, floats complicates matters and this is where experimental code
+%D starts.
+
+\let\page_mix_command_package_contents\page_one_command_package_contents
+\let\page_mix_command_flush_float_box \page_one_command_flush_float_box
+
+\unexpanded\def\page_mix_command_check_if_float_fits
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+% \bgroup
+% \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+% \page_floats_get_info\s!text
+% \setbox\scratchbox\vbox % tricky met objecten ?
+% {\blank[\rootfloatparameter\c!spacebefore]
+% \snaptogrid\vbox{\vskip\floatheight}}% copy?
+% \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+% \ifdim\dimen0>\dimen2
+% \global\setfalse\c_page_floats_room
+% \else
+ \global\settrue\c_page_floats_room
+ \fi\fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi}
+
+\unexpanded\def\page_mix_command_flush_floats
+ {\page_one_command_flush_floats}
+
+\unexpanded\def\page_mix_command_flush_saved_floats
+ {\page_one_command_flush_saved_floats}
+
+% \unexpanded\def\page_mix_command_flush_top_insertions
+% {\page_one_command_flush_top_insertions}
+
+\unexpanded\def\page_mix_place_float_top
+ {\showmessage\m!columns4\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_bottom
+ {\showmessage\m!columns5\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_here
+ {\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_force
+ {\page_one_place_float_force}
+
+\unexpanded\def\page_mix_command_side_float_output % hm
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mix_command_synchronize_side_floats % hm
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mix_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+%D Moved here and dedicated:
+
+\unexpanded\def\page_mix_command_test_column
+ {\dodoubleempty\page_mix_command_test_column_indeed}
+
+\unexpanded\def\page_mix_command_test_column_indeed[#1][#2]% works on last column
+ {\par
+ \begingroup
+ \scratchdimen\dimexpr#1\lineheight\ifsecondargument+#2\fi\relax
+ \ifdim\scratchdimen>\zeropoint
+ \attribute\checkedbreakattribute\number\scratchdimen
+ \penalty\c_page_mix_break_forced\relax
+ \fi
+ \endgroup}
+
+%D We need to hook some handlers into the output routine and we define
+%D a dedicated one:
+
+\defineoutputroutine
+ [\s!mixedcolumn]
+ [\s!page_otr_command_routine =\page_mix_command_routine,
+ \s!page_otr_command_package_contents =\page_mix_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mix_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mix_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mix_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mix_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mix_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mix_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mix_command_set_bottom_insertions,
+ % \s!page_otr_command_flush_top_insertions =\page_mix_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mix_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mix_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mix_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mix_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mix_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mix_command_flush_saved_floats,
+ % \s!page_otr_command_flush_margin_blocks =\page_mix_command_flush_margin_blocks, % not used
+ \s!page_otr_command_test_column =\page_mix_command_test_column
+ ]
+
+%D Only a few float placement options are supported:
+
+\installfloatmethod \s!mixedcolumn \v!here \page_mix_place_float_here
+\installfloatmethod \s!mixedcolumn \v!force \page_mix_place_float_force
+\installfloatmethod \s!mixedcolumn \v!top \page_mix_place_float_top
+\installfloatmethod \s!mixedcolumn \v!bottom \page_mix_place_float_bottom
+
+\installfloatmethod \s!mixedcolumn \v!local \somelocalfloat
+
+%D It ends here.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mrk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-mrk.mkiv
new file mode 100644
index 00000000000..0cd615f8acc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mrk.mkiv
@@ -0,0 +1,206 @@
+%D \module
+%D [ file=page-mrk,
+%D version=2011.05.23, % moved from page-lay
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Cutmarks and Colorbars,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Cutmarks and Colorbars}
+
+%D This module depends on \METAPOST.
+
+\unprotect
+
+% \def\pagecutmarksymbol {\the\realpageno}
+% \let\pagecutmarktoptext \empty
+% \let\pagecutmarkbottomtext \empty
+
+\def\pagecutmarklength {5mm}
+\def\pagecutmarkoffset {3mm} % slightly larger than before, and now a fixed size
+\def\pagecutmarkmargin{10cm}
+
+\newconditional\c_page_marks_add_more_color
+\newconditional\c_page_marks_add_more_marking
+\newconditional\c_page_marks_add_more_lines
+\newconditional\c_page_marks_add_page_lines
+\newconditional\c_page_marks_add_more_number
+
+\newcount\c_page_marks_nx
+\newcount\c_page_marks_ny
+
+\startuniqueMPgraphic{print:color}{w,h,l,o}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_color(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ;
+\stopuniqueMPgraphic
+
+\startuniqueMPgraphic{print:marking}{w,h,l,o}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_marking(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ;
+\stopuniqueMPgraphic
+
+\startuniqueMPgraphic{print:lines}{w,h,l,o,x,y}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_lines(\MPvar w,\MPvar h,\MPvar l,\MPvar o,\MPvar x,\MPvar y) ;
+\stopuniqueMPgraphic
+
+\startuseMPgraphic{print:number}{w,h,l,o,n}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_number(\MPvar w,\MPvar h,\MPvar l,\MPvar o,\MPvar n) ;
+\stopuseMPgraphic
+
+\def\page_marks_add_color
+ {\setlayoutcomponentattribute{\v!print:\v!color}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:color}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_marking
+ {\setlayoutcomponentattribute{\v!print:\v!marking}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:marking}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_lines
+ {\setlayoutcomponentattribute{\v!print:\v!lines}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:lines}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset,%
+ x=\the\c_page_marks_nx,y=\the\c_page_marks_ny}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_number
+ {\setlayoutcomponentattribute{\v!print:\v!number}%
+ \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
+ \useMPgraphic
+ {print:number}%
+ {w=\the\scratchwidth ,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset,%
+ n=\number\ifcase\arrangeno\realpageno\else\arrangeno\fi}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_page_indeed#1%
+ {\setbox#1\hpack\bgroup
+ \resetvisualizers
+ \let\objectoffset\pagecutmarkmargin
+ %\infofont
+ \scratchwidth \wd#1%
+ \scratchheight\ht#1%
+ \scratchdepth \dp#1%
+ \box#1\relax
+ \ifconditional\c_page_marks_add_page_lines
+ \page_marks_add_lines
+ \fi
+ \egroup}
+
+\def\page_marks_add_more_indeed#1%
+ {\setbox#1\hbox\bgroup
+ \resetvisualizers
+ \let\objectoffset\pagecutmarkmargin
+ \infofont
+ \scratchwidth \wd#1% these can move out
+ \scratchheight\ht#1%
+ \scratchdepth \dp#1%
+ \box#1\relax
+ \ifconditional\c_page_marks_add_more_color
+ \page_marks_add_color
+ \fi
+ \ifconditional\c_page_marks_add_more_marking
+ \page_marks_add_marking
+ \fi
+ \ifconditional\c_page_marks_add_more_lines
+ \page_marks_add_lines
+ \fi
+ \ifconditional\c_page_marks_add_more_number
+ \page_marks_add_number
+ \fi
+ \egroup}
+
+\let\page_marks_add_page\gobbleoneargument
+\let\page_marks_add_more\gobbleoneargument
+
+\installcorenamespace{layoutmarking}
+
+\unexpanded\def\installpagecutmark#1#2%
+ {\setvalue{\??layoutmarking#1}{#2}}
+
+% \installpagecutmark\v!off
+% {}
+
+% \installpagecutmark\v!text
+% {\settrue\c_page_marks_add_more_lines
+% \settrue\c_page_marks_add_more_number
+% \let\pagecutmarksymbol\empty
+% \let\pagecutmarkbottomtext\extrapagecutmarkbottomtext}
+
+\installpagecutmark\v!on
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_number}
+
+\installpagecutmark\v!page % todo
+ {\settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_number}
+
+\installpagecutmark\v!empty
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines}
+
+\installpagecutmark\v!color
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_color
+ \settrue\c_page_marks_add_more_marking
+ \settrue\c_page_marks_add_more_number}
+
+\appendtoks
+ \setfalse\c_page_marks_add_page_lines
+ \setfalse\c_page_marks_add_more_color
+ \setfalse\c_page_marks_add_more_marking
+ \setfalse\c_page_marks_add_more_lines
+ \setfalse\c_page_marks_add_more_number
+ \begincsname\??layoutmarking\layoutparameter\c!marking\endcsname
+ \ifconditional\c_page_marks_add_page_lines
+ \let\page_marks_add_page\page_marks_add_page_indeed
+ \else
+ \let\page_marks_add_page\gobbleoneargument
+ \fi
+ % we can get a double set of (overlayed) lines .. needs to be redone (too many objects anyway)
+ \ifconditional\c_page_marks_add_more_lines
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_color
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_marking
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_number
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else
+ \let\page_marks_add_more\gobbleoneargument
+ \fi\fi\fi\fi
+\to \everysetuplayout
+
+\setuplayout
+ [\c!marking=\v!off]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv
new file mode 100644
index 00000000000..6312323685a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv
@@ -0,0 +1,1824 @@
+%D \module
+%D [ file=page-mul, % was: core-mul
+%D version=1998.03.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=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.
+
+% todo: basecolumns as parent for columns and itemize
+
+% !!! there are some issues with hsize an vsize as well as flushing
+% !!! floats but this module will be redone anyway
+
+\writestatus{loading}{ConTeXt Page Macros / Simple Multi Column}
+
+%D This module is mostly a copy from the original multi column routine as
+%D implemented in \type {core-mul}. When the main OTR macro's were
+%D isolated in modules and column sets were introduced, this module became
+%D part of the OTR modules. As a result this module is no longer generic.
+
+\unprotect
+
+\definesystemvariable {ks} % KolomSpan
+
+% check \count<insert> multiplications
+
+%D The following macro's implement a multi||column output routine. The original
+%D implementation was based on Donald Knuth's implementation, which was adapted by
+%D Craig Platt to support balancing of the last page. I gradually adapted Platt's
+%D version to our needs but under certain circumstances things still went wrong. I
+%D considered all calls to Platt's \type{\page_mul_routine_error} as undesirable.
+%D
+%D This completely new implementation can handle enough situations for everyday
+%D documents, but is still far from perfect. While at the moment the routine doesn't
+%D support all kind of floats, it does support:
+%D
+%D \startitemize[packed]
+%D \item an unlimitted number of columns
+%D \item ragged or not ragged bottoms
+%D \item optional balancing without \type{\page_mul_routine_errors}
+%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
+%D \type {\maxdepth}
+%D \item left- and right indentation, e.g. within lists
+%D \item moving columns floats to the next column or page
+%D \item handling of floats that are to wide for a columns
+%D \stopitemize
+%D
+%D One could wonder why single and multi||columns modes are still separated. One
+%D reason for this is that \TeX\ is not suited well for handling multi||columns. As
+%D a result, the single columns routines are more robust. Handling one column as a
+%D special case of multi||columns is posible but at the cost of worse float
+%D handling, worse page breaking, worse etc. Complicated multi||column page handling
+%D should be done in \cap{DTP}||systems anyway.
+
+\installcorenamespace {columns}
+
+\installcommandhandler \??columns {columns} \??columns
+
+%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
+%D following definition does not always work.
+
+ \unexpanded\def\ejectcolumn % not good enough
+ {\goodbreak
+ \showmessage\m!columns2\empty}
+
+%D The output routines plug into a more generic mechanism as can be seen at the
+%D end of this file. So, occasionally we need to define some plugin code.
+
+\unexpanded\def\page_mul_place_float_top
+ {\showmessage\m!columns4\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_bottom
+ {\showmessage\m!columns5\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_here
+ {\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_force
+ {\page_one_place_float_force}
+
+\unexpanded\def\page_mul_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mul_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mul_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+\let\page_mul_initialize_floats\relax
+\let\page_mul_flush_floats \relax
+\let\page_mul_flush_float \relax
+
+%D A hook:
+
+ \let\finishcolumnbox\relax
+
+%D This will change to a local one:
+
+\ifdefined\nofcolumns \else \newcount\nofcolumn \fi
+\ifdefined\mofcolumns \else \newcount\mofcolumn \fi
+
+\appendtoks
+ \nofcolumns\columnsparameter\c!n\relax
+\to \everysetupcolumns
+
+%D Columns are separated by spacing or rules or whatever suits.
+
+\installcorenamespace{columnseparators}
+
+\setvalue{\??columnseparators\v!on }{\let\page_mul_between_columns\page_mul_between_columns_rule}
+\setvalue{\??columnseparators\v!off }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators\s!unknown}{\let\page_mul_between_columns\p_page_mul_rule}
+
+\def\page_mul_between_columns_rule
+ {\bgroup
+ \starttextproperties
+ \scratchdistance\dimexpr\columnsparameter\c!distance/2\relax
+ \hskip\scratchdistance\relax
+ \vrule
+ \s!width\linewidth
+ \ifnum\bottomraggednessmode=\plustwo % baselinebottom
+ \s!depth\strutdepth
+ \fi
+ \hskip\scratchdistance\relax
+ \stoptextproperties
+ \egroup}
+
+\def\page_mul_between_columns_space
+ {\hskip\columnsparameter\c!distance\relax}
+
+\let\page_mul_between_columns\page_mul_between_columns_space
+
+%D We declare some registers:
+
+\newdimen \d_page_mul_available_width
+\newdimen \d_page_mul_distance
+\newdimen \d_page_mul_leftskip
+\newdimen \d_page_mul_rightskip
+\newdimen \d_page_mul_offset
+\newdimen \d_page_mul_forced_height
+\newdimen \d_page_mul_used_width
+\newdimen \d_page_mul_temp
+
+\newcount \c_page_mul_balance_minimum
+\newcount \c_page_mul_n_of_lines
+
+\newbox \b_page_mul_preceding
+\newdimen \d_page_mul_preceding_height
+\newdimen \d_page_mul_preceding_depth
+\newconditional\c_page_mul_preceding_present
+
+\newbox \b_page_mul_preceding_rest_of_page
+
+\newconditional\c_page_mul_reverse
+
+\newconditional\c_page_mul_trace
+
+%D The next dimensions reports the final column height .. todo
+
+ \newdimen\finalcolumnheights
+ \newcount\finalcolumnlines
+
+ \newdimen\savedpagetotal % brrr
+
+ \newif\ifstretchcolumns \stretchcolumnsfalse
+ \newif\ifheightencolumns \heightencolumnsfalse
+ \newif\ifinheritcolumns \inheritcolumnsfalse
+ \newif\ifbalancecolumns %\balancecolumnstrue
+
+%D An important one:
+
+\unexpanded\def\page_mul_command_set_hsize % beware, this one is available for use in macros
+ {\setbox\scratchbox\hbox{\page_mul_between_columns}%
+ \d_page_mul_distance\wd\scratchbox
+ \d_page_mul_available_width\dimexpr
+ \makeupwidth
+ -\d_page_mul_leftskip
+ -\d_page_mul_rightskip
+ -\nofcolumns\d_page_mul_distance
+ +\d_page_mul_distance
+ \relax
+ \d_page_mul_used_width\dimexpr
+ \d_page_mul_available_width/\nofcolumns
+ -\d_page_mul_offset*\plustwo
+ \relax
+ \textwidth\d_page_mul_used_width % needs thinking ... grouping etc
+ \hsize\d_page_mul_used_width}
+
+%D Torture test:
+%D
+%D \startbuffer
+%D \startbuffer[b]
+%D \startcolumns
+%D \input tufte
+%D \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower
+%D \input tufte
+%D \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower[left]
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D \stopbuffer
+%D
+%D \start
+%D \def\postprocesscolumnline#1{\ruledhbox{\strut\box#1}\hss}
+%D \getbuffer
+%D \stop
+
+%D One should be aware that when font related dimensions are used in typesetting the
+%D in||between material, these dimensions are influenced by bodyfont switches inside
+%D multi||column mode.
+
+\setnewconstant\multicolumnlinemethod\zerocount % 0=normal 1=raw
+
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+
+\unexpanded\def\page_mul_set_n_of_lines
+ {\settotalinsertionheight
+ \d_page_mul_temp\dimexpr
+ -\d_page_mul_offset*\plustwo
+ +\textheight
+ \ifdim\d_page_mul_preceding_height>\zeropoint -\d_page_mul_preceding_height \fi
+ -\totalinsertionheight
+ \relax
+ \ifcase\multicolumnlinemethod
+ \getnoflines \d_page_mul_temp \or
+ \getrawnoflines\d_page_mul_temp \else
+ \getrawnoflines\d_page_mul_temp
+ \fi
+ % added 30/7/2004
+ \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
+ \noflines\layoutlines
+ \fi \fi
+ \c_page_mul_n_of_lines\noflines}
+
+\unexpanded\def\page_mul_command_set_vsize
+ {\page_one_command_set_vsize % indeed?
+ \page_mul_set_n_of_lines
+ \d_page_mul_temp\nofcolumns\dimexpr
+ \c_page_mul_n_of_lines\openlineheight
+ +\multicolumnovershootratio\openlineheight % collect enough data
+ \relax
+ \global\vsize\d_page_mul_temp
+ \pagegoal \d_page_mul_temp} % let's do it only here
+
+%D It really starts here. After some checks and initializations we change the output
+%D routine to continous multi||column mode. This mode handles columns that fill the
+%D current and next full pages. The method used is (more or less) multiplying \type
+%D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be
+%D found in the \TeX book. We save the top of the current page in box
+%D \type {\b_page_mul_preceding}.
+%D
+%D We manipulate \type {\topskip} a bit, just to be shure that is has no
+%D flexibility. This has te be done every time a font switch takles place, because
+%D \type {\topskip} can depend on this.
+
+\newconstant\c_page_mul_routine
+
+\setnewconstant\c_page_mul_routine_regular \zerocount
+\setnewconstant\c_page_mul_routine_intercept \plusone
+\setnewconstant\c_page_mul_routine_continue \plustwo
+\setnewconstant\c_page_mul_routine_balance \plusthree
+\setnewconstant\c_page_mul_routine_error \plusfour
+
+\unexpanded\def\page_mul_command_routine
+ {\ifcase\c_page_mul_routine
+ \page_one_command_routine
+ \or
+ \page_mul_routine_intercept
+ \or
+ \page_mul_routine_continue
+ \or
+ \page_mul_routine_balance
+ \or
+ \page_mul_routine_error
+ \fi}
+
+\def\page_mul_routine_intercept
+ {\global\setbox\b_page_mul_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
+
+\def\page_mul_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+%D When we leave the multi||column mode, we have to process the not yet shipped out
+%D part of the columns. When we don't balance, we simply force a continuous output,
+%D but a balanced output is more tricky.
+%D
+%D First we try to fill up the page and when all or something is left we try to
+%D balance things. This is another useful adaption of the ancesters of these
+%D macro's. It takes some reasoning to find out what happens and maybe I'm making
+%D some mistake, but it works.
+%D
+%D Voiding box \type {\b_page_mul_preceding} is sometimes necessary, e.g. when there is no
+%D text given between \type {\begin..} and \type {\end..}. The \type {\par} is
+%D needed!
+
+%D Because some initializations happen three times, we defined a macro for
+%D them. Erasing \type{\everypar} is needed because we don't want anything
+%D to interfere.
+
+\unexpanded\def\page_mul_initialize_variables
+ {\reseteverypar
+ \dontcomplain
+ \settopskip
+ \setmaxdepth
+ \topskip 1\topskip
+ \splittopskip \topskip
+ \splitmaxdepth \maxdepth
+ \boxmaxdepth \maxdepth % dangerous
+ \emergencystretch\zeropoint
+ \relax} % sometimes needed !
+
+%D Flushing the page comes to pasting the columns together and appending the result
+%D to box \type {\b_page_mul_preceding}, if not void. I've seen a lot of implementations in
+%D which some skip was put between normal text and multi||column text. When we don't
+%D want this, the baselines can be messed up. I hope the seemingly complicated
+%D calculation of a correction \type {\kern} is adequate to overcome this. Although
+%D not watertight, spacing is taken into account and even multiple mode changes on
+%D one page go well. But cross your fingers and don't blame me.
+%D
+%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding}
+%D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the
+%D page when using \type {\raggedbottom}. It took a lot of time before these kind of
+%D problems were overcome. Using \type {\unvbox} at the wrong moment can generate
+%D \type {\page_mul_routine_error}'s.
+%D
+%D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when
+%D generating material between columns as well as postprocessing column lines.
+
+\newdimen\maxcolumnheight
+\newdimen\maxcolumndepth
+
+\newbox\columnpagebox
+
+\def\page_mul_calculate_column_result_dimensions
+ {\maxcolumnheight\zeropoint
+ \maxcolumndepth \zeropoint
+ \dohandleallcolumnscs\page_mul_calculate_column_result_dimensions_step}
+
+\def\page_mul_calculate_column_result_dimensions_step
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \maxcolumnheight\ht\currentcolumnbox
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \maxcolumndepth\dp\currentcolumnbox
+ \fi}
+
+\setnewconstant\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
+\setnewconstant\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
+
+\def\page_mul_flush_preceding_normal
+ {\unvbox\b_page_mul_preceding}
+
+\def\page_mul_flush_preceding_ongrid
+ {\scratchdimen\dimexpr
+ \savedpagetotal
+ -\d_page_mul_preceding_height
+ -\d_page_mul_preceding_depth
+ -\topskip
+ \relax
+ \box\b_page_mul_preceding
+ \kern\scratchdimen}
+
+\def\page_mul_flush_packaged_columns_continued
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_flush_packaged_columns_balanced
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \ifgridsnapping
+ % quick hack (at least it works with itemize)
+ \else
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \fi
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_synchronize_marks
+ {\dohandleallcolumns{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}}
+
+\def\page_mul_flush_packaged_columns_indeed
+ {\ifvoid\b_page_mul_preceding
+ \setfalse\c_page_mul_preceding_present % will be set elsewhere
+ \else
+ \settrue\c_page_mul_preceding_present
+ \page_postprocessors_box\b_page_mul_preceding
+ \fi
+ \forgetall
+ \page_mul_initialize_variables
+ \page_mul_calculate_column_result_dimensions
+ \page_mul_postprocess_linenumbers
+ \page_mul_synchronize_marks
+ \page_mul_postprocess_lines
+ \page_mul_postprocess_columns
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width
+ {\box\currentcolumnbox}%
+ \wd\currentcolumnbox\d_page_mul_used_width
+ \ifheightencolumns
+ \ht\currentcolumnbox\d_page_mul_forced_height
+ \fi}%
+ \page_mul_calculate_column_result_dimensions
+ \overlaycolumnfootnotes
+ \setbox\columnpagebox\vbox
+ {\hbox to \makeupwidth
+ {\hskip\d_page_mul_leftskip\relax % new, \relax needed
+ \ifconditional\c_page_mul_reverse
+ \expandafter\dohandlerevcolumns
+ \else
+ \expandafter\dohandleallcolumns
+ \fi
+ {\finishcolumnbox
+ {\setbox\scratchbox\hbox
+ {\ifx\finishcolumnbox\relax\else\strut\fi
+ \box\currentcolumnbox}% hm, why strut
+ \anch_mark_column_box\scratchbox
+ \box\scratchbox}%
+ \hfil}%
+ \unskip
+ \hskip\d_page_mul_rightskip}}% new
+ \scratchdimen\zeropoint
+ \dohandleallcolumns
+ {\ifdim-\ht\currenttopcolumnbox<\scratchdimen
+ \scratchdimen-\ht\currenttopcolumnbox
+ \fi
+ \global\setbox\currenttopcolumnbox\emptybox}%
+ \advance\scratchdimen \ht\columnpagebox
+ \setbox\scratchbox\hbox to \makeupwidth
+ {\vrule
+ \s!width\zeropoint
+ \s!height\scratchdimen
+ \s!depth\dp\columnpagebox
+ \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}%
+ \setbox\columnpagebox\hbox
+ {\box\columnpagebox
+ \hskip-\makeupwidth
+ \box\scratchbox}%
+ \page_mul_postprocess_page
+ \ifconditional\c_page_mul_preceding_present
+ \settrue\c_page_mul_preceding_present
+ % next some incredible crappy code
+ \ifcase\multicolumntopalignmethod
+ \page_mul_flush_preceding_normal % not on grid
+ \or
+ \page_mul_flush_preceding_ongrid % force on grid
+ \else\ifgridsnapping
+ \page_mul_flush_preceding_ongrid % obey grid settings, force on grid
+ \else
+ \page_mul_flush_preceding_normal % ignore grid settings, not on grid
+ \fi \fi
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \page_otr_command_set_vsize
+ \dosomebreak\nobreak % hm, only needed when topstuff
+ \ifgridsnapping
+ \else
+ \ifcase\multicolumntopflushmethod
+ % sometimes method 1 goes wrong, so we need a way out; best sort this out
+ % when we run into it again
+ \or
+ % \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
+ \ifconditional\c_page_mul_preceding_present
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \fi
+ \or
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \or
+ % untested but maybe handy
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ % \vskip-\lineheight
+ % \vbox{\strut}%
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip-\lineheight\relax
+ \vbox{\strut}%
+ \fi
+ \fi
+ \prevdepth\openstrutdepth
+ \nointerlineskip
+ \dp\columnpagebox\zeropoint
+ \global\finalcolumnheights\ht\columnpagebox
+ \getnoflines\finalcolumnheights
+ \global\finalcolumnlines\noflines}
+
+%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
+%D all boxes. One can use these hooks for special purposes.
+%D
+%D Once upon a time I wanted to manipulate the individual lines in a column.
+%D This feature is demonstrated in the two examples below.
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
+%D {\ruledhbox{\box#1}\hss}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line: \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we show the natural width of the lines:
+%D
+%D {\getbuffer}
+%D
+%D The next example does a bit more advanced manipulation:
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1%
+%D {\ifodd\currentcolumn
+%D \hfill\unhbox#1\relax
+%D \else
+%D \relax\unhbox#1\hfill
+%D \fi}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we also see an application of \type{\currentcolumn}:
+%D
+%D {\getbuffer}
+%D
+%D This feature is implemented using the reshape macros presented
+%D in \type{supp-box}.
+
+\ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box
+\ifdefined\postprocesscolumnline \else\let\postprocesscolumnline \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnbox \else\let\postprocesscolumnbox \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnpagebox \else\let\postprocesscolumnpagebox \relax\fi % operates on passed box
+
+\def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi}
+\def\page_mul_postprocess_lines {\ifx\postprocesscolumnline \relax\else\page_mul_postprocess_lines_indeed \fi}
+\def\page_mul_postprocess_columns {\ifx\postprocesscolumnbox \relax\else\page_mul_postprocess_columns_indeed \fi}
+\def\page_mul_postprocess_page {\ifx\postprocesscolumnpagebox \relax\else\page_mul_postprocess_page_indeed \fi}
+
+\def\page_mul_postprocess_linenumbers_indeed
+ {\dohandleallcolumns{\page_postprocessors_column\currentcolumnbox}}
+
+\def\page_mul_postprocess_lines_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_lines_step}
+
+\def\page_mul_postprocess_lines_step % TODO: use lua solution instead
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\scratchheight\ht\shapebox
+ \scratchdepth \dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\scratchheight
+ \dp\shapebox\scratchdepth
+ \box\shapebox}%
+ \flushshapebox
+ \reseteverypar
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}
+
+\def\page_mul_postprocess_columns_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_columns_step}
+
+\def\page_mul_postprocess_columns_step
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+
+\def\page_mul_postprocess_page_indeed
+ {\postprocesscolumnpagebox\columnpagebox}
+
+%D Here comes the simple splitting routine. It's a bit longer than expected because
+%D of ragging bottoms or not. This part can be a bit shorter but I suppose that I
+%D will forget what happens. The splitting takes some already present material
+%D (think of floats) into account!
+%D
+%D First we present some auxiliary routines. Any material, like for instance floats,
+%D that is already present in the boxes is preserved.
+
+\newdimen\d_page_mul_split_height_used
+\newdimen\d_page_mul_split_height_max
+
+\def\page_mul_split_column#1#2#3#4% copy or box
+ {\bgroup
+ \ifdim\ht#4>\zeropoint
+ \d_page_mul_split_height_used#3\relax
+ \d_page_mul_split_height_max\d_page_mul_split_height_used
+ \advance\d_page_mul_split_height_used -\ht#4%
+ \columnfootnotecorrection{#1}\d_page_mul_split_height_used
+ \setbox\scratchbox\vsplit#2 to \d_page_mul_split_height_used
+ \global\setbox#1\vbox to \d_page_mul_split_height_max
+ {\ifgridsnapping
+ \scratchdimen\dimexpr\topskip-\openstrutheight\relax
+ \vskip\scratchdimen
+ \copy#4%
+ \vskip-\scratchdimen
+ \else
+ \unvcopy#4%
+ \fi
+ \fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \else\ifcase\c_strc_notes_page_location
+ \global\setbox#1\vsplit#2 to #3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
+ \else
+ \columnfootnotecorrection{#1}{#3}%
+ \setbox\scratchbox\vsplit#2 to #3%
+ \global\setbox#1\vbox to #3%
+ {\fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \fi \fi
+ \egroup}
+
+\def\page_mul_split_current_column#1#2%
+ {\page_mul_split_column\currentcolumnbox{#1}{#2}\currenttopcolumnbox}
+
+\def\page_mul_split_first_column#1#2%
+ {\page_mul_split_column\firstcolumnbox{#1}{#2}\firsttopcolumnbox}
+
+\def\page_mul_split_last_column#1#2%
+ {\global\setbox\lastcolumnbox\vbox
+ {\unvcopy\lasttopcolumnbox
+ \fuzzysnappedbox\unvbox{#1}%
+ \fakecolumnfootnotes\lastcolumnbox}}
+
+%D NEW: still to be documented.
+
+ \def\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\c_strc_notes_page_location\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+ \def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+ \def\overlaycolumnfootnotes
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi
+ \fi}
+
+ \newbox\b_page_mul_notes
+
+ \def\page_mul_notes_flush_first_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ \page_mul_set_n_of_lines
+ \advance\c_page_mul_n_of_lines \minustwo
+ \scratchdimen\dimexpr\c_page_mul_n_of_lines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+ \def\page_mul_notes_flush_last_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ % maybe here also \page_mul_set_n_of_lines
+ \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+%D Here comes the routine that splits the long box in columns. The macro \type
+%D {\page_mul_flush_floats} can be used to flush either floats that were present before
+%D the multi||column mode was entered, or floats that migrate to next columns.
+%D Flushing floats is a delicate process.
+
+\def\page_mul_routine_continue
+ {\bgroup
+ \forgetall
+ \page_mul_initialize_variables
+ % \dimen0=\makeupheight
+ % \advance\dimen0 -\d_page_mul_preceding_height
+ % \settotalinsertionheight
+ % \advance\dimen0 -\totalinsertionheight
+ % \ifgridsnapping % evt altijd, nog testen
+ % \getnoflines{\dimen0}
+ % \dimen0=\noflines\openlineheight
+ % \fi
+ \page_mul_set_n_of_lines
+ \d_page_mul_balance_target\c_page_mul_n_of_lines\openlineheight
+ \ifconditional\c_page_mul_trace
+ \writestatus\m!columns{continue: lines=\the\c_page_mul_n_of_lines, target=\the\d_page_mul_balance_target, textheight=\the\textheight}%
+ \fi
+ \dohandleallcolumns
+ {\page_mul_split_current_column\normalpagebox\d_page_mul_balance_target}%
+ \setbox\b_page_mul_preceding_rest_of_page\vbox{\unvbox\normalpagebox}%
+ \ifinheritcolumns
+ \ifcase\bottomraggednessmode
+ % 0 = ragged
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\scratchdepth\dp\currentcolumnbox
+ \unvbox\currentcolumnbox
+ \vskip\dimexpr\openstrutdepth-\scratchdepth\relax
+ \prevdepth\openstrutdepth % \strutdp
+ \vfill}}%
+ \strc_notes_check_if_bottom_present
+ %\ifconditional\c_notes_bottom_present \else
+ % \dimen0\ht\firstcolumnbox % ??
+ %\fi
+ \or
+ % 1 = normal
+ \advance\d_page_mul_balance_target\maxdepth
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox}}%
+ \or
+ % 2 = baseline
+ % the columns are on top of the baseline
+ \fi
+ \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \unvbox\currentcolumnbox % wel of niet \unvbox ?
+ \vfill
+ \fi}}%
+ \dohandleallcolumns
+ {\ht\currentcolumnbox\d_page_mul_balance_target}% redundant
+ \fi
+ \setbox\b_page_mul_preceding\vbox{\page_mul_flush_packaged_columns_continued}%
+ \page_otr_construct_and_shipout\box\b_page_mul_preceding
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize
+ \page_mul_flush_floats
+ \unvbox\b_page_mul_preceding_rest_of_page
+ % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
+ \egroup}
+
+%D And this is the balancing stuff. Again, part of the routine is dedicated to
+%D handling ragged bottoms, but here we also see some handling concerning the
+%D stretching of columns. We set \type {\widowpenalty} at~0, which enables us to
+%D balance columns with few lines. The use of \type {\box2} and \type {\box4}
+%D garantees a more robust check when skips are used.
+
+\newbox \b_page_mul_balance_content
+\newbox \b_page_mul_balance_first_column
+\newbox \b_page_mul_balance_column
+\newconstant \c_page_mul_balance_tries_max
+\newcount \c_page_mul_balance_tries
+\newdimen \d_page_mul_balance_target
+\newdimen \d_page_mul_balance_target_less
+\newdimen \d_page_mul_balance_natural_height
+\newdimen \d_page_mul_balance_regular_height
+\newdimen \d_page_mul_balance_step
+\newdimen \d_page_mul_balance_fuzzyness
+\newdimen \d_page_mul_balance_threshold
+\newconditional\c_page_mul_balance_possible
+
+\c_page_mul_balance_tries_max 250 % 100 is too small when floats are involved
+
+\def\page_mul_routine_balance
+ {\bgroup
+ \page_mul_initialize_variables
+ \widowpenalty\zerocount
+ \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}%
+ \ifdim\ht\b_page_mul_balance_content>\openlineheight % at least one line
+ \ifnum\c_page_mul_balance_minimum<\plustwo % balance anyway
+ \settrue\c_page_mul_balance_possible
+ \else % check criterium to available lines
+ \getnoflines{\ht\b_page_mul_balance_content}%
+ \divide\noflines \nofcolumns \relax
+ \ifnum\noflines<\c_page_mul_balance_minimum \relax
+ \ifdim\dimexpr\ht\b_page_mul_balance_content+\ht\firsttopcolumnbox+\openlineheight\relax>\makeupheight
+ \settrue\c_page_mul_balance_possible % column exceeding text height
+ \else
+ \setfalse\c_page_mul_balance_possible % it seems to fit
+ \fi
+ \else
+ \settrue\c_page_mul_balance_possible % balance indeed
+ \fi
+ \fi
+ \else
+ \setfalse\c_page_mul_balance_possible % balancing does not make sense
+ \fi
+ \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight
+ \page_mul_balance_try_one
+ \ifinheritcolumns
+ \page_mul_balance_try_two
+ \else
+ \page_mul_balance_try_three
+ \fi
+ \else
+ % a one liner is not properly handled here, so best rewrite the text then
+ \showmessage\m!columns{10}\empty
+ \global\setbox\firstcolumnbox\vbox{\unvbox\b_page_mul_balance_content}%
+ \fi
+ \c_page_mul_routine\c_page_mul_routine_error
+ \baselinebottom % forces depth in separation rule
+ \page_mul_flush_packaged_columns_balanced
+ \page_mul_eject_page
+ \egroup}
+
+\def\page_mul_eject_page
+ {%\ifdim\pagetotal>\textheight
+ % \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
+ %\else
+ \allowbreak
+ }%\fi}
+
+\def\page_mul_balance_try_one
+ {\d_page_mul_balance_target\dimexpr\ht\b_page_mul_balance_content+\topskip-\baselineskip\relax
+ \dohandleallcolumns
+ {\advance\d_page_mul_balance_target \ht\currenttopcolumnbox}%
+ \divide\d_page_mul_balance_target \nofcolumns
+ \vbadness\plustenthousand
+ \c_page_mul_balance_tries\zerocount
+ \bgroup
+ \ifgridsnapping
+ \d_page_mul_balance_step\lineheight
+ \else
+ \d_page_mul_balance_step\spacingfactor\onepoint % rubish
+ \fi
+ \doloop\page_mul_balance_try_one_attempt
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}%
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\c_page_mul_balance_tries}%
+ \fi
+ \egroup}
+
+\def\page_mul_balance_try_one_attempt
+ {\advance\c_page_mul_balance_tries \plusone
+ \global\setbox\b_page_mul_preceding_rest_of_page\copy\b_page_mul_balance_content\relax
+ \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \dohandlemidcolumns
+ {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}%
+ \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \setbox\b_page_mul_balance_first_column\vbox{\unvcopy\firstcolumnbox}%
+ \d_page_mul_balance_natural_height\zeropoint
+ \dohandleallcolumns\page_mul_balance_try_one_attempt_step
+ \advance\d_page_mul_balance_natural_height -.0005pt % (33sp) get rid of accurracy problem, pretty new
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \exitloop
+ \else\ifdim\d_page_mul_balance_natural_height>\ht\b_page_mul_balance_first_column
+ \advance\d_page_mul_balance_target \d_page_mul_balance_step\relax
+ \else
+ \exitloop
+ \fi\fi}
+
+\def\page_mul_balance_try_one_attempt_step
+ {\setbox\b_page_mul_balance_column\vbox
+ {\unvcopy\currentcolumnbox
+ \unpenalty
+ \unskip
+ \unpenalty
+ \unskip}% maybe better in main splitter
+ \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height
+ \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column
+ \fi}
+
+% We cannot assume that the first column is the tallest, if only because we may
+% have an aborted balance (one line in the first column and a graphic in the
+% second one).
+
+\def\page_mul_balance_try_two
+ {\d_page_mul_balance_target\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\d_page_mul_balance_target
+ \d_page_mul_balance_target\ht\currentcolumnbox
+ \fi}%
+ \d_page_mul_balance_target_less\dimexpr\d_page_mul_balance_target-\openlineheight\relax
+ \dohandleallcolumnscs\page_mul_balance_try_two_step}
+
+\def\page_mul_balance_try_two_step
+ {\d_page_mul_balance_regular_height\ht\currentcolumnbox
+ \d_page_mul_balance_threshold\plusten\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_threshold
+ \ifdim\d_page_mul_balance_regular_height<\d_page_mul_balance_target
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_target_less
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}
+
+\def\page_mul_balance_try_three
+ {\bgroup
+ \ifstretchcolumns
+ \d_page_mul_balance_target\ht\firstcolumnbox
+ \d_page_mul_balance_fuzzyness\bottomtolerance\ht\firstcolumnbox
+ \setbox\b_page_mul_balance_content\vbox{\unvcopy\lastcolumnbox}%
+ \advance\d_page_mul_balance_target-\htdp\b_page_mul_balance_content\relax
+ \ifdim\d_page_mul_balance_target>\openlineheight\relax
+ \ifdim\d_page_mul_balance_target>\d_page_mul_balance_fuzzyness\relax
+ % \stretchcolumnsfalse % beter good bad than bad good
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumnscs\page_mul_balance_try_three_step
+ \egroup}
+
+\def\page_mul_balance_try_three_step
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}
+
+%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
+%D which acts like:
+%D
+%D \starttyping
+%D \startcolumns[n=4,balance=no]
+%D some text
+%D \stopcolumns
+%D \stoptyping
+%D
+%D The setup is optional. The default behaviour of columns can be set
+%D up with:
+%D
+%D \starttyping
+%D \setupcolumns
+%D [n=2,
+%D balance=yes]
+%D \stoptyping
+%D
+%D In this case, stretching is according to the way it's done outside columns
+%D (\type{\inheritcolumnstrue}). Also we can setup the \type{tolerance} within a
+%D column, the \type{distance} between columns and the fixed \type{height} of a
+%D column.
+%D
+%D Here come the routines that handle the placement of column floats. Floats that
+%D are to big migrate to the next column. Floats that are too wide, migrate to the
+%D top of the next page, where they span as much columns as needed. Floats that are
+%D left over from outside the multi||column mode are flushed first. In macro
+%D \type{\page_otr_construct_and_shipout} the topfloats that are left from previous
+%D text should be set.
+%D
+%D When there are some floats in the queue, we inhibit the flushing of floats on top
+%D of columns. The number of waiting floats is preswent in \type{\savednoftopfloats}
+%D and is saved. As long as there are floats waiting, the topfloats are places as if
+%D we are outside multi||column mode. This is neccessary for e.g. multicolumn lists.
+%D
+%D When all those floats are flushed, we switch to the local flushing routine.
+
+% \newbox \floatlist
+% \newbox \savedfloatlist
+%
+% \def\page_floats_column_push_saved
+% {\ifconditional\c_page_floats_some_waiting
+% \showmessage\m!columns6{\the\savednoffloats}%
+% \global\setbox\savedfloatlist\box\floatlist
+% \xdef\page_floats_column_pop_saved
+% {\global\savednoffloats\the\savednoffloats
+% \global\setbox\floatlist\box\savedfloatlist
+% \global\noexpand\settrue\c_page_floats_some_waiting}%
+% \global\savednoffloats\zerocount
+% \global\setfalse\c_page_floats_some_waiting
+% \else
+% \global\let\page_floats_column_pop_saved\relax
+% \fi}
+%
+% \let\page_floats_column_pop_saved\relax
+
+% \def\page_mul_initialize_floats % messy as it adapts everypar
+% {\xdef\globalsavednoffloats{\the\savednoffloats}%
+% \ifnum\globalsavednoffloats>\zerocount
+% \setglobalcolumnfloats % hm, we always push so this never happens
+% \else
+% \setlocalcolumnfloats
+% \fi}
+
+ \def\page_mul_initialize_floats % messy as it adapts everypar, we need to adapt this
+ {\setlocalcolumnfloats}
+
+ \newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+ \newtoks \everylocalcolumnfloatspar
+
+ \unexpanded\def\page_mul_command_flush_floats
+ {\ifconditional\onlylocalcolumnfloats
+ \doflushcolumnfloats
+ \else
+ \page_one_command_flush_floats
+ \fi}
+
+ \unexpanded\def\page_mul_command_check_if_float_fits
+ {\ifconditional\onlylocalcolumnfloats
+ \docolumnroomfloat
+ \fi}
+
+ \unexpanded\def\page_mul_command_flush_saved_floats
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_saved_floats
+ \fi}
+
+ \unexpanded\def\page_mul_command_flush_top_insertions
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_top_insertions
+ \fi}
+
+ \appendtoks
+ \flushnotes
+ \page_mul_flush_float
+ %\flushmargincontents
+ \checkindentation
+ \to \everylocalcolumnfloatspar
+
+ \def\setlocalcolumnfloats
+ {\settrue\onlylocalcolumnfloats
+ \everypar\everylocalcolumnfloatspar
+ \let\page_mul_flush_float \doflushcolumnfloat
+ \let\page_mul_flush_floats\doflushcolumnfloats}
+
+ \def\setglobalcolumnfloats
+ {\setfalse\onlylocalcolumnfloats
+ \reseteverypar
+ \let\page_mul_flush_float \relax
+ \let\page_mul_flush_floats\noflushcolumnfloats}
+
+ % \def\noflushcolumnfloats
+ % {\bgroup
+ % \xdef\localsavednoffloats{\the\savednoffloats}%
+ % \global\savednoffloats\globalsavednoffloats
+ % \page_otr_command_flush_top_insertions
+ % \xdef\globalsavenoffloats{\the\savednoffloats}%
+ % \ifnum\globalsavednoffloats=\zerocount
+ % \setlocalcolumnfloats
+ % \fi
+ % \global\savednoffloats\localsavednoffloats
+ % \egroup}
+ %
+ \def\noflushcolumnfloats{\doflushcolumnfloats} % not yet redone
+
+%D We need to calculate the amount of free space in a columns. When there is not
+%D enough room, we migrate the float to the next column. These macro's are
+%D alternatives (and look||alikes) of \type {\doroomfloat}. When a float is to wide,
+%D for one column, it is moved to the top of the next page. Of course such moved
+%D floats have to be taken into account when we calculate the available space. It's
+%D a pitty that such things are no integral part of \TEX.
+
+ \def\getcolumnstatus#1#2#3%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\makeupheight
+ \advance\dimen8 -\d_page_mul_preceding_height
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+ \def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\makeupheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+ \def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+ \bgroup
+ \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+ \page_floats_get_info\s!text
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}% copy?
+ \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+ \ifdim\dimen0>\dimen2
+ \global\setfalse\c_page_floats_room
+ \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi
+ \egroup
+ \fi\fi}
+
+%D Flushing one float is done as soon as possible, i.e. \type {\everypar}.
+%D This means that (at the moment) sidefloats are not supported (overulled)!
+
+ \newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+ \def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting
+ \doflushcolumnfloatindeed
+ \fi\fi\fi}
+
+ \def\doflushcolumnfloatindeed
+ {\bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus{\mofcolumns}{\dimen0}{\dimen2}%
+ \ifdim\dimen0>\zeropoint
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ % dropped ?
+ \else
+ \setbox2\vbox
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \page_floats_flush\s!text\plusone
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \fi
+ \else
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\rootfloatparameter\c!spacebefore]
+ \nobreak
+ \fi
+ \page_floats_flush\s!text\plusone
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+%D This one looks complicated. Upto \type{\nofcolumns} floats are placed,
+%D taking the width of a float into account. This routine can be improved
+%D on different ways:
+%D
+%D \startitemize[intro,packed]
+%D \item taking into account some imaginary baseline, just to get the
+%D captions in line
+%D \item multipass flushing until as many floats are displaced as possible
+%D \stopitemize
+%D
+%D When handling lots of (small) floats spacing can get worse because of
+%D lining out the columns.
+
+ \def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifconditional\c_page_floats_some_waiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \else
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ \dimen0\dimexpr\floatwidth+\d_page_mul_distance+.5pt\relax
+ \dimen2\dimexpr\hsize +\d_page_mul_distance+.5pt\relax
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \count0\zerocount
+ \else
+ \dimen0\dimexpr\count0\hsize+\count0\d_page_mul_distance-\d_page_mul_distance\relax
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \global\setbox\floatbox\hbox to \dimen0
+ {\processaction[\rootfloatparameter\c!location] % how easy to forget
+ [ \v!left=>\box\floatbox\hss,
+ \v!right=>\hss\box\floatbox,
+ \s!default=>\hss\box\floatbox\hss,
+ \s!unknown=>\hss\box\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\box\currenttopcolumnbox % was copy
+ \box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \fi
+ \dimen6\htdp\currenttopcolumnbox
+ \fi
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \page_otr_command_set_vsize
+ \global\advance\vsize -\dimen8
+ \pagegoal\vsize
+ \else
+ % \page_mul_command_flush_floats % does not snap!
+ \fi
+ \egroup
+ \fi}
+
+%D The next macro can be used to flush floats in the current stream. No
+%D width checking is (yet) done.
+
+ \def\insertcolumnfloats
+ {\doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \page_floats_get
+ \blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\rootfloatparameter\c!spaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
+
+%D This were the multi||column routines. They can and need to be improved
+%D but at the moment their behaviour is acceptable.
+%D
+%D One inprovement can be to normalize the height of floats to $ n \times $
+%D \type {\lineheight} with a macro like:
+%D
+%D \starttyping
+%D \normalizevbox{...}
+%D \stoptyping
+
+% border case, should fit on one page
+%
+% \startcolumns
+% 1 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{1}}
+% 2 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{2}}
+% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
+% \stopcolumns
+
+ % \def\backgroundfinishcolumnbox
+ % {\doifelseinset\@@kloffset{\v!none,\v!overlay}
+ % {\let\@@kloffset\!!zeropoint}
+ % {\scratchdimen\@@kloffset
+ % \advance\scratchdimen -\@@klrulethickness
+ % \edef\@@kloffset{\the\scratchdimen}}%
+ % \localframed
+ % [\??kl]
+ % [\c!strut=\v!no,
+ % \c!width=\v!fit,
+ % \c!height=\v!fit,
+ % \c!align=]}
+
+ \def\backgroundfinishcolumnbox
+ {}
+
+% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
+
+\unexpanded\def\page_columns_align_option_yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_text{\stretchcolumnsfalse\inheritcolumnstrue }%
+
+\newtoks\t_page_mul_initialize
+
+\unexpanded\def\startcolumns
+ {\dosingleempty\page_mul_start}
+
+\def\page_mul_start[#1]% %% \startcolumns
+ {\bgroup
+ \ifinsidecolumns
+ \page_mul_start_nop
+ \else
+ \iffirstargument
+ \setupcolumns[#1]%
+ \fi
+ \nofcolumns\columnsparameter\c!n\relax
+ \ifnum\nofcolumns>\plusone
+ \page_mul_start_yes
+ \else
+ \page_mul_start_nop
+ \fi
+ \fi}
+
+\unexpanded\def\page_mul_start_nop
+ {\let\stopcolumns\page_mul_stop_nop}
+
+\unexpanded\def\page_mul_stop_nop
+ {\egroup}
+
+\unexpanded\def\page_mul_start_yes
+ {\whitespace
+ \begingroup
+ \let\stopcolumns\page_mul_stop_indeed
+ \global\insidecolumnstrue
+ \the\t_page_mul_initialize
+ %
+ \flushnotes
+ \begingroup
+ %
+ \d_page_mul_leftskip\leftskip
+ \d_page_mul_rightskip\rightskip
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \widowpenalty\zerocount % will become option
+ \clubpenalty \zerocount % will become option
+ %
+ \page_floats_column_push_saved
+ %
+ \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
+ \allowbreak
+ \else
+ \break % sometimes fails
+ \fi
+ \appendtoks
+ \topskip1\topskip % best a switch
+ \to \everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ %
+ \initializecolumns\nofcolumns
+ %
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \reseteverypar
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \setupoutputroutine[\s!multicolumn]%
+ \c_page_mul_routine\c_page_mul_routine_intercept
+ \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear !
+ \global\d_page_mul_preceding_height\ht\b_page_mul_preceding
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \page_mul_initialize_floats
+ \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize}
+
+\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
+
+\unexpanded\def\page_mul_stop_indeed
+ {\relax
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't collapse these
+ \vskip \lineheight
+ \vskip-\lineheight % take footnotes into account
+ \fi
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \goodbreak
+ \fi
+ \c_page_mul_routine\c_page_mul_routine_balance
+ \else
+ \goodbreak
+ \fi
+ % still the multi column routine
+ \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in
+ \prevdepth\zeropoint % columns before some noncolumned text text
+ %
+ \c_page_mul_routine\c_page_mul_routine_regular
+ %
+ \ifvoid\b_page_mul_preceding\else
+ \unvbox\b_page_mul_preceding
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \page_otr_command_set_vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \page_floats_column_pop_saved
+ %
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+
+\appendtoks
+ \edef\p_option{\columnsparameter\c!option}%
+ \ifx\p_option\v!background
+ \let\finishcolumnbox\backgroundfinishcolumnbox
+ \fi
+ \d_page_mul_offset\columnsparameter\c!offset\relax
+ \edef\p_command{\columnsparameter\c!command}%
+ \ifx\p_command\empty \else
+ \let\postprocesscolumnline\p_command
+ \fi
+ \edef\p_height{\columnsparameter\c!height}%
+ \ifx\p_height\empty
+ \d_page_mul_forced_height\textheight
+ \heightencolumnsfalse
+ \else
+ \d_page_mul_forced_height\p_height\relax
+ \heightencolumnstrue
+ \fi
+ \edef\p_direction{\columnsparameter\c!direction}%
+ \ifx\p_direction\v!right
+ \setfalse\c_page_mul_reverse
+ \else
+ \settrue\c_page_mul_reverse
+ \fi
+ \edef\p_balance{\columnsparameter\c!balance}%
+ \ifx\p_balance\v!yes
+ \balancecolumnstrue
+ \else
+ \balancecolumnsfalse
+ \fi
+ % % this won't work (blocked by check for overloading; too fuzzy anyway)
+ % \installalign\v!yes {\page_columns_align_option_yes }% \stretchcolumnstrue \inheritcolumnsfalse
+ % \installalign\v!no {\page_columns_align_option_no }% \stretchcolumnsfalse\inheritcolumnsfalse
+ % \installalign\v!text{\page_columns_align_option_text}% \stretchcolumnsfalse\inheritcolumnstrue
+ % %
+ \stretchcolumnsfalse
+ \inheritcolumnstrue
+ \edef\p_align{\columnsparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\columnsparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_blank{\columnsparameter\c!blank}%
+ \ifx\p_blank\empty \else
+ \setupblank[\p_blank]%
+ \fi
+ \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
+ \setupwhitespace[\p_blank]%
+ \fi
+ \c_page_mul_balance_minimum\columnsparameter\c!ntop\relax
+ \edef\p_page_mul_rule{\columnsparameter\c!rule}%
+ \expandnamespacemacro\??columnseparators\p_page_mul_rule\s!unknown
+\to \t_page_mul_initialize
+
+%D Columns breaks
+
+\installcolumnbreakmethod \s!multicolumn \v!preference
+ {\goodbreak}
+
+% \installcolumnbreakmethod \s!multicolumn \v!yes
+% {\vskip\textheight
+% \penalty-200 % we can mark and intercept this
+% \vskip-\textheight}
+
+\installcolumnbreakmethod \s!multicolumn \v!yes
+ {\vskip .5\pagegoal
+ \penalty-200 % we can mark and intercept this
+ \vskip-.5\pagegoal}
+
+%D Next we initialize the lot:
+
+\setupcolumns
+ [\c!n=2,
+ \c!ntop=1,
+ \c!command=,
+ \c!direction=\v!right,
+ \c!rule=\v!off,
+ \c!tolerance=\v!tolerant,
+ \c!distance=1.5\bodyfontsize, % influenced by switching
+ \c!height=,
+ \c!balance=\v!yes,
+ \c!align=\v!text,
+ \c!blank={\v!line,\v!fixed},
+ \c!option=,
+ \c!rulethickness=\linewidth,
+ \c!offset=.5\bodyfontsize]
+
+%D New: only at start of columns; may change ! Rather interwoven and therefore
+%D to be integrated when the multi column modules are merged.
+
+ \unexpanded\def\setupcolumnspan[#1]%
+ {\getparameters[\??ks][#1]}
+
+ \presetlocalframed
+ [\??ks]
+
+ \setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+ \newbox\b_page_columns_span \let\page_mul_postprocess_spanbox\gobbleoneargument
+
+ \unexpanded\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+ \unexpanded\def\stopcolumnspan
+ {\egroup}
+
+ \def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \d_page_mul_distance
+ \hsize\@@ksn\hsize
+ \advance\hsize -\d_page_mul_distance
+ \fi
+ \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+ \def\dofinishcolumnsetspan
+ {\setbox\b_page_columns_span\flushnextbox
+ \ifinsidecolumns\wd\b_page_columns_span\hsize\fi
+ \page_mul_postprocess_spanbox\b_page_columns_span
+ \scratchdimen\ht\b_page_columns_span
+ \setbox\b_page_columns_span\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}%
+ \ht\b_page_columns_span\scratchdimen
+ \dp\b_page_columns_span\strutdp
+ \wd\b_page_columns_span\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \page_otr_command_set_vsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\b_page_columns_span}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
+
+%D Undocumented and still under development.\ifdefined\startsimplecolumns \else
+
+\unexpanded\def\startsimplecolumns
+ {\dosingleempty\page_mul_simple_start}
+
+\def\page_mul_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}}
+
+%D Moved here:
+
+\unexpanded\def\page_mul_command_test_column
+ {\dodoubleempty\page_mul_command_test_column_indeed}
+
+\unexpanded\def\page_mul_command_test_column_indeed[#1][#2]% works on last column
+ {\page_otr_command_flush_top_insertions\endgraf
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \d_page_tests_test\dimexpr
+ \pagegoal
+ -\pagetotal
+ \ifdim\lastskip<\parskip+\parskip\fi
+ \ifsecondargument+#2\fi
+ \relax
+ \getrawnoflines\d_page_tests_test % (raw)
+ \ifnum#1>\noflines
+ \column
+ \fi
+ \else
+ \penalty-\plustenthousand % (untested)
+ \fi
+ \fi}
+
+%D but fragile anyway.
+
+\let\page_mul_command_package_contents\page_one_command_package_contents
+\let\page_mul_command_flush_float_box \page_one_command_flush_float_box
+
+\defineoutputroutine
+ [\s!multicolumn]
+ [\s!page_otr_command_routine =\page_mul_command_routine,
+ \s!page_otr_command_package_contents =\page_mul_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mul_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mul_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mul_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mul_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mul_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mul_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mul_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats,
+ % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
+ \s!page_otr_command_test_column =\page_mul_command_test_column
+ ]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-not.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-not.mkiv
new file mode 100644
index 00000000000..d7602bd2658
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-not.mkiv
@@ -0,0 +1,71 @@
+%D \module
+%D [ file=page-nnt,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Footnotes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Footnotes}
+
+%D This is an old mechanism that will be replaced as soon as the multicolumn
+%D code is redone.
+
+%D We've moved some footnote handling to a separate page module. The macros below
+%D are used in the single and multi column page handlers and permit mixed usage of
+%D column and page notes.
+
+\unprotect
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\c_strc_notes_page_location
+ \erasenotebackup
+ \else
+ \flushnotes
+ \savenotecontent
+ \fi
+ \savenotedata}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata
+ \ifcase\c_strc_notes_page_location\else
+ \restorenotecontent
+ \fi}
+
+\let\checksinglecolumnfootnotes\relax
+
+\newdimen\totalinsertionheight
+
+\unexpanded\def\settotalinsertionheight
+ {\calculatetotalnoteheight
+ \totalinsertionheight\dimexpr
+ \totalnoteheight
+ +\page_insert_insertion_height\s!topfloat
+ +\page_insert_insertion_height\s!bottomfloat
+ \relax}
+
+% hm
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\c_strc_notes_page_location
+ \erasenotebackup
+ \else
+ \flushnotes
+ \savenotecontent
+ \fi
+ \savenotedata}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata
+ \ifinsidecolumns
+ \ifcase\c_strc_notes_page_location\else
+ \restorenotecontent
+ \fi
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv
new file mode 100644
index 00000000000..a4178713394
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv
@@ -0,0 +1,624 @@
+ %D \module
+%D [ file=page-one,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Default Routine,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Default Routine}
+
+%D This is just the good old \CONTEXT\ output routine, which
+%D has been there right from the start.
+
+\unprotect
+
+% OTRONE: basic single column
+
+\newconstant \c_page_one_float_method
+
+\unexpanded\def\page_one_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_one_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+\unexpanded\def\page_one_command_set_hsize
+ {\global\hsize\textwidth}
+
+\unexpanded\def\page_one_command_set_float_hsize
+ {\global\hsize\textwidth}
+
+% \newdimen\d_page_one_saved_vsize
+%
+% \unexpanded\def\page_one_command_set_vsize
+% {\ifgridsnapping
+% \ifcase\layoutlines
+% \getrawnoflines\textheight
+% \else
+% \noflines\layoutlines
+% \fi
+% \global\vsize\noflines\openlineheight
+% \else
+% \global\vsize\textheight
+% \fi
+% \ifdim\pagegoal<\maxdimen
+% \ifdim\d_page_one_saved_vsize=\vsize
+% % let's assume that the layout didn't change
+% \else
+% \global\d_page_one_saved_vsize\vsize
+% \pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax
+% % \bgroup
+% % \global\d_page_one_saved_vsize\vsize
+% % \advance\vsize-\d_page_floats_inserted_top
+% % \advance\vsize-\d_page_floats_inserted_bottom
+% % \pagegoal\vsize
+% % \egroup
+% \fi
+% \fi}
+
+\unexpanded\def\page_one_command_set_vsize
+ {\ifgridsnapping
+ \ifcase\layoutlines
+ \getrawnoflines\textheight
+ \else
+ \noflines\layoutlines
+ \fi
+ \global\vsize\noflines\openlineheight
+ \else
+ \global\vsize\textheight
+ \fi
+ % alternatively we could set it in builders.buildpage_filter
+ % \ifdim\pagegoal<\maxdimen .. \fi
+ \global\pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax}
+
+
+% 1 = partial page, 2 = whole page, 3 = partial page
+
+\setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day
+
+\def\page_one_registered_text_area_a % two arguments: (un)vbox n
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_one_registered_text_area_a_indeed
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\page_one_registered_text_area_b % one arguments: content
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_one_registered_text_area_b_indeed
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\page_one_registered_text_area_a_indeed % two arguments: (un)vbox n
+ {\ifcase\kindofpagetextareas
+ \expandafter\firstofoneargument
+ \or % partial page (experimental)
+ \expandafter\page_areas_register_direct
+ \or % whole page (default)
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\page_one_registered_text_area_b_indeed % one arguments: content
+ {\ifcase\kindofpagetextareas
+ % \expandafter\firstofoneargument
+ \or % partial page (experimental)
+ % \expandafter\firstofoneargument
+ \or % whole page (default)
+ \expandafter\page_areas_register_boxed
+ \else
+ % \expandafter\firstofoneargument
+ \fi}
+
+\newdimen\d_page_one_natural_depth
+\newbox \b_page_one_bottom_notes
+\newbox \b_page_one_contents
+
+\let\page_one_command_package_show_state\relax
+
+% \fakepagenotes ... needs checking
+%
+% we can also have bottom notes on top of bottom insertions
+
+\unexpanded\def\page_one_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
+ {\bgroup
+ \strc_notes_check_if_bottom_present
+ \d_page_one_natural_depth\dp#2\relax
+ % we need to set the height as otherwise the shrink will not kick in so the following
+ % no longer applies:
+ %
+ % \setbox\b_page_one_contents\vbox \ifconditional\c_notes_bottom_present to \textheight \fi
+ %
+ \setbox\b_page_one_contents\vbox to \textheight % probably no pack
+ {\page_otr_command_flush_top_insertions
+ % this is messy ... we will provide a more tight area (no big deal as we can
+ % do that at the lua end)
+ \page_one_registered_text_area_a#1#2% \unvbox <box>
+ %
+ \ifgridsnapping
+ \vskip\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
+ \prevdepth\openstrutdepth
+ \page_otr_command_flush_bottom_insertions
+ \vfil
+ \or
+ % align (normal)
+ \page_otr_command_flush_bottom_insertions
+ \or
+ % baseline
+ \kern\dimexpr\maxdepth-\d_page_one_natural_depth\relax
+ \page_otr_command_flush_bottom_insertions
+ \fi\fi
+ \fakepagenotes}%
+ \page_one_command_package_show_state
+ \ifconditional\c_notes_bottom_present
+ \ifgridsnapping
+ \ifcase\layoutlines
+ \getrawnoflines\textheight
+ \else
+ \noflines\layoutlines
+ \fi
+ \scratchoffset\dimexpr\numexpr\noflines-\plusone\relax\lineheight+\topskip\relax
+ \else
+ \scratchoffset\ht\b_page_one_contents
+ \fi
+ \setbox\b_page_one_bottom_notes\hpack
+ {\checksinglecolumnfootnotes % why this check? ***
+ \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% kerns makes notes sit on bottom % pack ?
+ \smashbox\b_page_one_bottom_notes
+ \ht\b_page_one_contents\zeropoint
+ \page_one_registered_text_area_b
+ {\vpack to \textheight
+ {\box\b_page_one_contents
+ \box\b_page_one_bottom_notes}}%
+ \else
+ \ht\b_page_one_contents\textheight
+ \page_one_registered_text_area_b
+ {\box\b_page_one_contents}%
+ \fi
+ \egroup}
+
+\unexpanded\def\page_one_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_one_command_routine
+ {\page_sides_output_routine}
+
+%D Insertions
+
+\newconditional\c_page_one_top_of_insert
+\newconditional\c_page_one_correct_top_insert \settrue\c_page_one_correct_top_insert % false moves up (tight)
+\newskip \s_page_one_between_top_insert
+
+\def\page_one_prepare_top_float
+ {\ifdim\d_page_floats_inserted_top=\zeropoint
+ \settrue\c_page_one_top_of_insert
+ \else
+ \setfalse\c_page_one_top_of_insert
+ \fi
+ \s_page_one_between_top_insert\ifdim\d_strc_floats_top>\d_strc_floats_bottom\d_strc_floats_top\else\d_strc_floats_bottom\fi\relax
+ \global\advance\d_page_floats_inserted_top\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax}
+
+\def\page_one_insert_top_float % maybe remember last beforeskip
+ {\insert\namedinsertionnumber\s!topfloat\bgroup
+ \forgetall
+ \ifconditional\c_page_one_top_of_insert
+ \ifconditional\c_page_one_correct_top_insert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip
+ \par
+ \prevdepth\maxdimen
+ \fi
+ \fi
+ \page_otr_command_flush_float_box
+ \vskip\s_page_one_between_top_insert
+ \egroup}
+
+\unexpanded\def\page_one_command_set_top_insertions
+ {\bgroup
+ \ifconditional\c_page_floats_some_waiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \page_one_command_set_top_insertions_indeed
+ \ifnum\rootfloatparameter\c!nbottom=\zerocount
+ \ifnum\rootfloatparameter\c!nlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \ifdim\dimexpr\rootfloatparameter\c!nlines\lineheight+\totaltopinserted\relax>\textheight
+ \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
+ \page_otr_fill_and_eject_page % was tripple: vfilll
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\page_one_command_set_top_insertions_indeed
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_top
+ \page_floats_get
+ \page_one_prepare_top_float
+ \ifdim\d_page_floats_inserted_top<\textheight\relax
+ \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
+ \page_one_insert_top_float
+ \ifconditional\c_page_floats_some_waiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\c_page_floats_n_of_top\relax
+ \fi
+ \page_floats_report_flushed
+ \else
+ \page_floats_resave\s!text
+ \noffloatinserts\c_page_floats_n_of_top\relax
+ \fi
+ \else
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
+ \fi
+ \let\page_one_command_set_top_insertions_indeed\relax
+ \fi
+ \page_one_command_set_top_insertions_indeed}
+
+\unexpanded\def\page_one_command_set_bottom_insertions
+ {\bgroup
+ \ifconditional\c_page_floats_some_waiting
+ \noffloatinserts\zerocount
+ \page_one_command_set_bottom_insertions_indeed
+ \fi
+ \egroup}
+
+\def\page_one_command_set_bottom_insertions_indeed
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax
+ \page_floats_get
+ \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\c_page_floats_n_of_bottom
+ \fi
+ \page_floats_report_flushed
+ \else
+ \page_floats_resave\s!text
+ \noffloatinserts\c_page_floats_n_of_bottom\relax
+ \fi
+ \global\settrue\c_page_floats_not_permitted % vgl topfloats s!
+ \else
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}%
+ \fi
+ \let\page_one_command_set_bottom_insertions_indeed\relax
+ \fi
+ \page_one_command_set_bottom_insertions_indeed}
+
+\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
+ \fi
+ \global\d_page_floats_inserted_top\zeropoint}
+
+\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
+ \fi
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \global\setfalse\c_page_floats_not_permitted}
+
+\unexpanded\def\page_one_command_flush_floats
+ {\global\settrue\c_page_floats_flushing
+ \ifconditional\c_page_floats_some_waiting
+ \par
+ % if kept, then option and definitely off in gridmode ! ! ! !
+ % \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests
+ \page_one_command_flush_floats_indeed
+ \fi
+ \global\savednoffloats\zerocount
+ \global\setfalse\c_page_floats_some_waiting
+ \global\setfalse\c_page_floats_flushing}
+
+\unexpanded\def\page_one_command_flush_float_box
+ {\ifconditional\c_page_floats_center_box \ifdim\wd\floatbox<\hsize
+ \global\setbox\floatbox\hpack to \hsize{\hss\box\floatbox\hss}%
+ \fi \fi
+ \snaptogrid\hpack{\box\floatbox}} % was copy
+
+\def\page_one_command_flush_floats_indeed % much in common with OTRSET
+ {\ifconditional\c_page_floats_some_waiting
+ \ifconditional\c_page_floats_pack_flushed
+ \setfalse\c_page_floats_center_box % not needed as we do call directly
+ \page_floats_collect\s!text\hsize\emwidth
+ %% no longer (interferes with footnotes):
+ %%
+ %% \page_one_command_set_vsize % test 2011.06.24.001
+ %%
+ \global\setbox\floatbox\hbox to \hsize
+ {\hfil
+ \dorecurse\nofcollectedfloats
+ {\ifcase\columndirection % nog document wide
+ \page_floats_flush\s!text\plusone
+ \else
+ \page_floats_flush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
+ \fi
+ \ifdim\wd\floatbox>\makeupwidth % \hsize
+ \hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \else
+ \box\floatbox
+ \fi
+ \ifnum\recurselevel<\nofcollectedfloats
+ \hfil
+ \fi}%
+ \hfil}%
+ \else
+ \page_floats_get
+ \fi
+ % there is a chance that due to rounding errors, the float
+ % fits on a page where it was first rejected, in which case
+ % the prevdepth is -maxdimen and we cannot obey the grid
+ \doplacefloatbox
+ \expandafter\page_one_command_flush_floats_indeed
+ \fi}
+
+\unexpanded\def\page_one_command_flush_margin_blocks
+ {\ifconditional\c_page_margin_blocks_present % \ifvoid\b_page_margin_blocks \else
+ \ifdim\pagetotal=\zeropoint
+ \null % \fixedspace
+ \fi
+ \page_otr_command_next_page % \page
+ \ifvoid\b_page_margin_blocks
+ \global\setfalse\c_page_margin_blocks_present
+ \else
+ \doubleexpandafter\page_one_command_flush_margin_blocks
+ \fi
+ \fi}
+
+\unexpanded\def\page_one_command_check_if_float_fits
+ {\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+ % new per 31/5/2004, should be an option, only one column mode
+ \begingroup
+ \scratchdimen\dimexpr\pagetotal+\lineheight\relax
+ \ifdim\scratchdimen>\pagegoal
+ \goodbreak % hack ?
+ \fi
+ % should be an option
+ \endgroup
+ \dimen0\dimexpr\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink\relax
+ \dimen2\pagegoal
+ \relax % needed
+ \ifcase\c_page_one_float_method
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\setfalse\c_page_floats_room
+ \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \fi}
+
+\unexpanded\def\page_one_command_flush_saved_floats
+ {\global\d_page_floats_inserted_top\zeropoint
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \ifconditional\c_page_floats_flushing \else
+ \page_one_command_set_top_insertions
+ \page_one_command_set_bottom_insertions
+ \ifconditional\c_page_floats_some_waiting
+ \doif{\rootfloatparameter\c!cache}\v!no\page_one_command_flush_floats % could be _otr_
+ \else\ifconditional\c_page_margin_blocks_present
+ \page_one_command_flush_floats
+ \fi\fi
+ \fi}
+
+
+\def\page_one_place_float_here_indeed
+ {\ifgridsnapping
+ % otherwise real bad outcome
+ \else
+ \baselinecorrection % this has to be done better (and definitely not in column mode)
+ \fi
+ \doplacefloatbox
+ \page_floats_report_total
+ \dohandlenextfloatindent}
+
+\def\page_one_place_float_force
+ {\showmessage\m!floatblocks9\empty
+ \page_one_place_float_here_indeed}
+
+\def\page_one_place_float_side_indeed#1%
+ {\setbox\floatbox\vpack{\box\floatbox}% ? can go
+ \wd\floatbox\floatwidth
+ #1{\box\floatbox}%
+ \doifinset\v!tall\floatlocationmethod\page_sides_flush_floats_after_par}
+
+\def\page_one_place_float_left {\page_one_place_float_side_indeed\page_sides_process_float_left\presetindentation}
+\def\page_one_place_float_right {\page_one_place_float_side_indeed\page_sides_process_float_right}
+\def\page_one_place_float_leftmargin {\page_one_place_float_side_indeed\page_sides_process_float_leftmargin}
+\def\page_one_place_float_rightmargin{\page_one_place_float_side_indeed\page_sides_process_float_rightmargin}
+\def\page_one_place_float_leftedge {\page_one_place_float_side_indeed\page_sides_process_float_leftedge}
+\def\page_one_place_float_rightedge {\page_one_place_float_side_indeed\page_sides_process_float_rightedge}
+\def\page_one_place_float_inmargin {\page_one_place_float_side_indeed\page_sides_process_float_cutspace}
+\def\page_one_place_float_backspace {\page_one_place_float_side_indeed\page_sides_process_float_backspace}
+\def\page_one_place_float_cutspace {\page_one_place_float_side_indeed\page_sides_process_float_cutspace}
+
+%def\page_one_place_float_margin {\page_one_place_float_side_indeed\page_sides_process_float_margin\nonoindentation} % wil be overloaded
+\def\page_one_place_float_margin {\page_margin_blocks_process_float}
+
+\def\page_one_place_float_page {\page_floats_save_page_float \s!page \floatlocationmethod}
+\def\page_one_place_float_leftpage {\page_floats_save_page_float \s!leftpage \floatlocationmethod}
+\def\page_one_place_float_rightpage {\page_floats_save_page_float \s!rightpage\floatlocationmethod}
+\def\page_one_place_float_somewhere {\page_floats_save_somewhere_float\s!somewhere\floatlocationmethod}
+
+\def\page_one_place_float_here {\page_one_place_float_otherwise_here}
+\def\page_one_place_float_auto {\page_one_place_float_otherwise}
+\def\page_one_place_float_top {\page_one_place_float_otherwise\nonoindentation}
+\def\page_one_place_float_bottom {\page_one_place_float_otherwise}
+
+\def\page_one_place_float_otherwise
+ {\doifelseinset\v!here\floatlocationmethod
+ \page_one_place_float_otherwise_here
+ \page_one_place_float_otherwise_else}
+
+\def\page_one_place_float_otherwise_here
+ {\doifelseinset\v!always\floatlocationmethod
+ {\page[\v!preference]%
+ \page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_here_indeed
+ \else
+ \showmessage\m!floatblocks9\empty
+ \page_floats_resave\s!text
+ \fi}
+ {\ifconditional\c_page_floats_some_waiting
+ \page_floats_save\s!text
+ \nonoindentation
+ \else
+ \page[\v!preference]%
+ \page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_here_indeed
+ \else
+ \page_floats_save\s!text
+ \nonoindentation
+ \fi
+ \fi}}
+
+\def\page_one_place_float_otherwise_else
+ {\doifelseinset\v!always\floatlocationmethod
+ {\page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_auto_top_bottom
+ \else
+ \showmessage\m!floatblocks9\empty
+ \page_floats_resave\s!text
+ \fi}
+ {\page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_auto_top_bottom
+ \else
+ \page_floats_save\s!text
+ \nonoindentation
+ \fi}}
+
+\def\floatautofactor{.5}
+
+\def\page_one_place_float_auto_top_bottom
+ {\ifx\floatmethod\v!auto
+ \ifdim\pagetotal<\floatautofactor\pagegoal % when empty page, maxdimen
+ \page_one_place_float_top_indeed
+ \else
+ \page_one_place_float_bottom_indeed
+ \fi
+ \else
+ \ifx\floatmethod\v!top
+ \page_one_place_float_top_indeed
+ \else\ifx\floatmethod\v!bottom
+ \page_one_place_float_bottom_indeed
+ \else
+ \page_one_place_float_here_indeed
+ \fi\fi
+ \fi}
+
+\def\page_one_place_float_top_indeed % maybe remember last beforeskip
+ {\page_one_prepare_top_float
+ \page_one_insert_top_float
+ \page_floats_report_total}
+
+\def\page_one_place_float_bottom_indeed
+ {\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \page_floats_report_total}
+
+\def\page_one_place_float_face % links, rechts, midden, hoog, midden, laag
+ {%\checkwaitingfloats{#1}%
+ \startopposite
+ \page_otr_command_flush_float_box
+ \stopopposite
+ }%\page_floats_report_total}
+
+\unexpanded\def\page_one_command_flush_side_floats
+ {\page_sides_flush_floats}
+
+\unexpanded\def\page_one_command_synchronize_side_floats
+ {\page_sides_synchronize_floats}
+
+\unexpanded\def\page_one_command_test_page
+ {\testpage}
+
+\defineoutputroutine
+ [\s!singlecolumn]
+ [\s!page_otr_command_routine =\page_one_command_routine,
+ \s!page_otr_command_package_contents =\page_one_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_one_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_one_command_set_hsize,
+ \s!page_otr_command_next_page =\page_one_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_one_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_one_command_synchronize_hsize,
+ \s!page_otr_command_set_top_insertions =\page_one_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions =\page_one_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_one_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions=\page_one_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_one_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_one_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_one_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_one_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_one_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_one_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_one_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_one_command_flush_saved_floats,
+ \s!page_otr_command_flush_margin_blocks =\page_one_command_flush_margin_blocks,
+ \s!page_otr_command_test_column =\page_one_command_test_page
+ ]
+
+% \setupoutputroutine
+% [\s!singlecolumn]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-otr.lua b/Master/texmf-dist/tex/context/base/mkiv/page-otr.lua
new file mode 100644
index 00000000000..30715868426
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-otr.lua
@@ -0,0 +1,12 @@
+if not modules then modules = { } end modules ['page-otr'] = {
+ version = 1.001,
+ comment = "companion to page-otr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interfaces.implement {
+ name = "triggerpagebuilder",
+ actions = tex.triggerbuildpage,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi
new file mode 100644
index 00000000000..ec38a06c1d9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi
@@ -0,0 +1,296 @@
+%D \module
+%D [ file=page-otr,
+%D version=2012.01.25,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Output Routines,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Output Routines}
+
+%D This module will get some of the code from other modules. At the
+%D same time we provide a bit more control.
+
+% When issuing two \par\penalty-\plustenthousand's, only the first
+% triggers the otr. Is this an obscure feature or an optimization?
+
+\registerctxluafile{page-otr}{1.001}
+
+\unprotect
+
+\let\triggerpagebuilder\clf_triggerpagebuilder
+
+\def\m!otr{otr} % todo
+
+\installcorenamespace{outputroutine}
+
+\installswitchcommandhandler \??outputroutine {outputroutine} \??outputroutine
+
+\newtoks\t_page_otr_commands
+\newtoks\t_page_otr_tracers
+
+\unexpanded\def\defineoutputroutinecommand[#name]% doing multiple on one go saves syncing
+ {\processcommalist[#name]\page_otr_commands_define}
+
+\unexpanded\def\page_otr_commands_define#name%
+ {\ifcsname#name\endcsname \else
+ \expandafter\let\csname#name\endcsname\relax
+ \normalexpanded{\t_page_otr_commands{\the\t_page_otr_commands\noexpand\page_otr_commands_process{#name}}}%
+ \fi}
+
+\let\page_otr_commands_process\gobbleoneargument
+
+\appendtoks
+ \let\page_otr_commands_process\page_otr_specifics_preset
+ \the\t_page_otr_commands
+ \let\page_otr_commands_process\gobbleoneargument
+\to \everyswitchoutputroutine
+
+\unexpanded\def\page_otr_specifics_preset#name%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#name}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \writestatus{\currentoutputroutine}{- \expandafter\strippedcsname\csname#name\endcsname}%
+ \expandafter\let\csname#name\endcsname\relax
+ \else
+ \writestatus{\currentoutputroutine}{+ \expandafter\strippedcsname\csname#name\endcsname}%
+ \expandafter\let\csname#name\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\unexpanded\def\page_otr_specifics_preset_normal#name%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#name}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \expandafter\let\csname#name\endcsname\relax
+ \else
+ \expandafter\let\csname#name\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\unexpanded\def\page_otr_specifics_preset_traced#name%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#name}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \writestatus{\currentoutputroutine}{preset: - \expandafter\strippedcsname\csname#name\endcsname}%
+ \expandafter\let\csname#name\endcsname\relax
+ \else
+ \writestatus{\currentoutputroutine}{preset: + \expandafter\strippedcsname\csname#name\endcsname}%
+ \expandafter\let\csname#name\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\let\page_otr_specifics_preset\page_otr_specifics_preset_normal
+
+\unexpanded\def\traceoutputroutines
+ {\the\t_page_otr_tracers}
+
+\appendtoks
+ \let\page_otr_specifics_preset\page_otr_specifics_preset_traced
+\to \t_page_otr_tracers
+
+%D We have a couple of output routines and the default one is
+%D the single column routine. Then there is a multicolumn variant
+%D that can be used mixed, and a columnset variant that is more
+%D exclusive.
+
+\installcorenamespace{otrtriggers}
+
+\newconstant\c_page_otr_eject_penalty \c_page_otr_eject_penalty -\plustenthousand
+\newconstant\c_page_otr_super_penalty \c_page_otr_super_penalty -\plustwentythousand
+\newcount \c_page_otf_trigger_penalty \c_page_otf_trigger_penalty -100010
+
+\newif \ifinotr % we keep this (name) for old times sake
+
+\unexpanded\def\page_otr_message_b{\page_otr_message_s+}
+\unexpanded\def\page_otr_message_e{\page_otr_message_s-}
+
+\unexpanded\def\page_otr_message_s#sign#what%
+ {\writestatus
+ \currentoutputroutine
+ {#sign\space \space
+ #what\space \space
+ p:\the\outputpenalty,\space
+ r:\the\realpageno ,\space
+ c:\number\mofcolumns,\space
+ v:\the\vsize ,\space
+ g:\the\pagegoal ,\space
+ t:\the\pagetotal ,\space
+ \ifdim\pagetotal>\pagegoal
+ d:\the\dimexpr\pagetotal-\pagegoal\relax
+ \fi}}
+
+\unexpanded\def\page_otr_trigger#penalty%
+ {\begingroup
+ \par
+ \penalty#penalty%
+ \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}}
+
+\unexpanded\def\page_otr_triggered_output_routine_traced
+ {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
+ \page_otr_message_b{special}%
+ \csname\??otrtriggers\the\outputpenalty\endcsname % \lastnamedcs can be gone
+ \page_otr_message_e{special}%
+ \else
+ \page_otr_message_b{normal}%
+ \page_otr_command_routine
+ \page_otr_message_e{normal}%
+ \fi}
+
+\unexpanded\def\page_otr_triggered_output_routine_normal
+ {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
+ \lastnamedcs
+ \else
+ \page_otr_command_routine
+ \fi}
+
+\let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_normal
+
+\appendtoks
+ \let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_traced
+\to \t_page_otr_tracers
+
+%D The real routine handler:
+
+\ifdefined\everybeforeoutput \else \newtoks\everybeforeoutput \fi
+\ifdefined\everyafteroutput \else \newtoks\everyafteroutput \fi
+
+\def\page_otf_set_engine_output_routine#content%
+ {\global\output
+ {\inotrtrue
+ \the\everybeforeoutput
+ #content\relax
+ \the\everyafteroutput}}
+
+\page_otf_set_engine_output_routine\page_otr_triggered_output_routine
+
+\installoutputroutine\synchronizeoutput
+ {\ifvoid\normalpagebox\else
+ \unvbox\normalpagebox
+ \pagediscards
+ \fi}
+
+\installoutputroutine\discardpage
+ {\setbox\scratchbox\box\normalpagebox}
+
+% todo: \resetpagebreak -> everyejectpage
+
+\def\page_otr_trigger_output_routine
+ {\par
+ \ifvmode
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_fill_and_eject_page
+ {\par
+ \ifvmode
+ \vfill
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_eject_page
+ {\par
+ \ifvmode
+ \ifdim\pagetotal>\pagegoal \else
+ \normalvfil
+ \fi
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_eject_page_and_flush_inserts % can be an installed one
+ {\par
+ \ifvmode
+ \ifdim\pagetotal>\pagegoal \else
+ \normalvfil
+ \fi
+ \penalty\c_page_otr_super_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_check_for_pending_inserts
+ {\ifnum\outputpenalty>\c_page_otr_super_penalty \else
+ \ifnum\insertpenalties>\zerocount
+ % something is being held over so we force a new page
+ \page_otr_force_another_page
+ \fi
+ \fi}
+
+\def\page_otr_force_another_page
+ {% we should actually remove the dummy line in the otr
+ \hpack to \hsize{}%
+ \kern-\topskip
+ \nobreak
+ \vfill
+ \penalty\c_page_otr_super_penalty
+ \resetpagebreak}
+
+%D For those who've read the plain \TEX\ book, we provide the next
+%D macro:
+
+\unexpanded\def\bye
+ {\writestatus\m!system{Sorry, you're not done yet, so no goodbye!}}
+
+%D We define a few constants because that (1) provides some checking
+%D and (2) is handier when aligning definitions (checks nicer).
+
+\definesystemconstant{page_otr_command_routine}
+\definesystemconstant{page_otr_command_package_contents}
+\definesystemconstant{page_otr_command_set_vsize}
+\definesystemconstant{page_otr_command_set_hsize}
+\definesystemconstant{page_otr_command_synchronize_hsize}
+\definesystemconstant{page_otr_command_next_page}
+\definesystemconstant{page_otr_command_next_page_and_inserts}
+\definesystemconstant{page_otr_command_set_top_insertions}
+\definesystemconstant{page_otr_command_set_bottom_insertions}
+\definesystemconstant{page_otr_command_flush_top_insertions}
+\definesystemconstant{page_otr_command_flush_bottom_insertions}
+\definesystemconstant{page_otr_command_check_if_float_fits}
+\definesystemconstant{page_otr_command_set_float_hsize}
+\definesystemconstant{page_otr_command_flush_float_box}
+\definesystemconstant{page_otr_command_side_float_output}
+\definesystemconstant{page_otr_command_synchronize_side_floats}
+\definesystemconstant{page_otr_command_flush_floats}
+\definesystemconstant{page_otr_command_flush_side_floats}
+\definesystemconstant{page_otr_command_flush_saved_floats}
+\definesystemconstant{page_otr_command_flush_margin_blocks}
+\definesystemconstant{page_otr_command_test_column}
+
+\definesystemconstant{singlecolumn}
+\definesystemconstant{multicolumn} % will move
+\definesystemconstant{columnset} % will move
+
+\defineoutputroutinecommand
+ [\s!page_otr_command_routine,
+ \s!page_otr_command_package_contents,
+ \s!page_otr_command_set_vsize,
+ \s!page_otr_command_set_hsize,
+ \s!page_otr_command_synchronize_hsize, % for columns of different width
+ \s!page_otr_command_next_page,
+ \s!page_otr_command_next_page_and_inserts,
+ \s!page_otr_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions,
+ \s!page_otr_command_check_if_float_fits,
+ \s!page_otr_command_set_float_hsize,
+ \s!page_otr_command_flush_float_box,
+ \s!page_otr_command_side_float_output, % name will change as will hooks
+ \s!page_otr_command_synchronize_side_floats,
+ \s!page_otr_command_flush_floats,
+ \s!page_otr_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats,
+ \s!page_otr_command_flush_margin_blocks,
+ \s!page_otr_command_test_column]
+
+\appendtoks
+ \setupoutputroutine[\s!singlecolumn]%
+\to \everydump
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-par.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-par.mkiv
new file mode 100644
index 00000000000..588065d6563
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-par.mkiv
@@ -0,0 +1,73 @@
+%D \module
+%D [ file=page-par, % copied from page-lin
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Paragraph Numbering}
+
+\unprotect
+
+\installcorenamespace {paragraphnumbering}
+\installcorenamespace {paragraphnumberingvariants}
+
+\installsimplecommandhandler \??paragraphnumbering {paragraphnumbering} \??paragraphnumbering
+
+\definecounter[\v!paragraph]
+
+\let\showparagraphnumber\relax
+
+\appendtoks
+ \page_par_check_state
+\to \everysetupparagraphnumbering
+
+\unexpanded\def\page_par_check_state
+ {\rawprocesscommacommand[\paragraphnumberingparameter\c!state]\page_par_check_state_step}
+
+\def\page_par_check_state_step#1%
+ {\ifcsname\??paragraphnumberingvariants#1\endcsname
+ \csname\??paragraphnumberingvariants#1\endcsname
+ \fi}
+
+\setvalue{\??paragraphnumberingvariants\v!start}%
+ {\let\showparagraphnumber\page_par_show_number_normal}
+
+\setvalue{\??paragraphnumberingvariants\v!stop}%
+ {\let\showparagraphnumber\relax}
+
+\setvalue{\??paragraphnumberingvariants\v!line}%
+ {\let\showparagraphnumber\page_par_show_number_lines}
+
+\setvalue{\??paragraphnumberingvariants\v!reset}%
+ {\strc_counters_reset\v!paragraph
+ \let\showparagraphnumber\page_par_show_number_normal}
+
+\unexpanded\def\page_par_show_number_normal
+ {\strc_counters_increment\v!paragraph
+ \inleftmargin % todo: \c!location, only a few make sense
+ {\hfill % no complaints
+ \tf % \tf normalizes em
+ \useparagraphnumberingstyleandcolor\c!style\c!color
+ \convertedcounter[\v!paragraph]%
+ \kern\paragraphnumberingparameter\c!distance}}
+
+\unexpanded\def\page_par_show_number_lines
+ {\ifnumberinglines
+ \page_par_show_number_normal
+ \fi}
+
+\setupparagraphnumbering
+ [\c!state=\v!stop,
+ %\c!location,
+ %\c!style=,
+ %\c!color=,
+ \c!distance=\ifcase\c_page_lines_location2\emwidth\else\zeropoint\fi] % will change
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-plg.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-plg.mkiv
new file mode 100644
index 00000000000..b59a05a9454
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-plg.mkiv
@@ -0,0 +1,215 @@
+%D \module
+%D [ file=page-pls,
+%D version=2003.03.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Setup,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Extra Page Building}
+
+%D This still needs some work, especially the dimensions need to be
+%D checked cq.\ optimized. Beware: method has become alternative!
+
+%D This feature has been present for a while but has never been
+%D exploited: pluggable pagebuilders. The next example code
+%D demonstrates the application of one such a plug-in. This variant
+%D support \type {page}, \type {leftpage} and \type {rightpage}
+%D definitions where specific areas are placed with the \type
+%D {\pagearea} command.
+%D
+%D \starttyping
+%D \setupheadertexts[the header text]
+%D \setupfootertexts[a pretty long left footer text][something right]
+%D \setupbottomtexts[a not so long bottom text][another right thing]
+%D \setuptexttexts [margin][something marginal][indeed]
+%D
+%D \startpagelayout[leftpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \setupTABLE[c][2][width=\textwidth]
+%D \setupTABLE[c][3][width=\rightmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3,background=color,backgroundcolor=green]
+%D \pagearea[header][text][middle]
+%D \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE
+%D \bTR
+%D \bTD \pagearea[footer][text][left] \eTD
+%D \bTD \pagearea[bottom][text][left] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \startpagelayout[rightpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \setupTABLE[c][2][width=\textwidth]
+%D \setupTABLE[c][3][width=\rightmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3] \pagearea[header][text][middle] \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE
+%D \bTR
+%D \bTD \pagearea[bottom][text][right] \eTD
+%D \bTD \pagearea[footer][text][right] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \setupcolors[state=start]
+%D
+%D \setuppagenumbering[alternative=doublesided,location=]
+%D
+%D \setuplayout[alternative=makeup]
+%D
+%D \definetextbackground
+%D [test]
+%D [state=start,
+%D background=color,
+%D backgroundcolor=yellow]
+%D
+%D \starttext
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \input tufte \starttest \input tufte \stoptest \input tufte
+%D
+%D \starttabulate
+%D \NC test \NC \starttest \input tufte \stoptest \NC \NR
+%D \stoptabulate
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \stoptext
+%D \stoptyping
+
+\unprotect
+
+\installcorenamespace{layoutmakeupalternative}
+
+\def\page_boxes_construct_content_makeup#1#2#3% targetbox flusher box
+ {\setbox#1\hbox
+ {\vbox to \textheight
+ {\offinterlineskip
+ \vskip\dimexpr-1\topskip+\strutheight\relax % could be an option
+ \textwidth\makeupwidth
+ \hsize\textwidth
+ \boxmaxdepth\maxdepth
+ \noindent
+ \page_otr_command_package_contents#2#3}}%
+ \wd#1\makeupwidth
+ \ht#1\textheight
+ \dp#1\zeropoint
+ \hsize\paperwidth
+ \vsize\paperheight
+ \setbox#1\vbox{\csname\??layoutmakeupalternative\doifbothsidesoverruled\v!page\v!rightpage\v!leftpage\endcsname}%
+ \wd#1\paperwidth
+ \ht#1\paperheight
+ \dp#1\zeropoint}
+
+\installlayoutalternative\v!makeup{\page_boxes_construct_content_makeup}
+
+\newbox\b_page_area
+
+\unexpanded\def\pagearea
+ {\dotripleempty\page_area}
+
+\def\page_area
+ {\ifthirdargument
+ \expandafter\page_area_three
+ \else\ifsecondargument
+ \doubleexpandafter\page_area_two
+ \else
+ \doubleexpandafter\page_area_one
+ \fi\fi}
+
+\def\page_area_three[#1][#2][#3]%
+ {\edef\m_page_area_three{#3}%
+ \ifx\m_page_area_three\v!left
+ \let\m_page_area_three\c!lefttext
+ \else\ifx\m_page_area_three\v!right
+ \let\m_page_area_three\c!righttext
+ \else
+ \let\m_page_area_three\c!middletext
+ \fi\fi
+ \page_area_indeed{#1}{#2}\m_page_area_three}
+
+\def\page_area_two[#1][#2][#3]%
+ {\edef\m_page_area_three{\doifbothsidesoverruled\c!righttext\c!righttext\c!lefttext}%
+ \page_area_indeed{#1}{#2}\m_page_area_three}
+
+\def\page_area_one[#1][#2][#3]%
+ {\edef\m_page_area_one{#1}
+ \ifx\m_page_area_one\v!text % copy due to trial runs in TABLE
+ \iftrialtypesetting
+ \fakebox\pagebox
+ \else
+ \page_backgrounds_add_to_text\pagebox
+ \page_grids_add_to_box\pagebox
+ \box\pagebox
+ \fi
+ \fi}
+
+\def\page_area_indeed#1#2#3%
+ {\setbox\b_page_area\vbox{\getspecificlayouttext{#1}{#2}{#3}}%
+ \iftrialtypesetting
+ \fakebox\b_page_area
+ \else\ifcsname\??layoutbackgrounds#1#2\endcsname
+ \page_area_indeed_yes{#1}{#2}%
+ \else
+ \box\b_page_area
+ \fi\fi}
+
+\def\page_area_indeed_yes#1#2%
+ {% todo: \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}
+ \localframed % todo:
+ [\??layoutbackgrounds#1#2]
+ [\c!width=\wd\b_page_area,
+ \c!height=\ht\b_page_area,
+ \c!offset=\v!overlay]
+ {\box\b_page_area}}
+
+% to be done nicely (proper namespacing)
+
+\setvalue{\??layoutmakeupalternative\v!leftpage }{\csname\??layoutmakeupalternative\v!page\endcsname}
+\setvalue{\??layoutmakeupalternative\v!rightpage}{\csname\??layoutmakeupalternative\v!page\endcsname}
+
+\unexpanded\def\startpagelayout
+ {\bgroup
+ \catcode\endoflineasciicode\ignorecatcode
+ \page_layouts_start_layout}
+
+\let\stoppagelayout\relax
+
+\def\page_layouts_start_layout[#1]#2\stoppagelayout
+ {\egroup
+ \setvalue{\??layoutmakeupalternative#1}{#2}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-pst.lua b/Master/texmf-dist/tex/context/base/mkiv/page-pst.lua
new file mode 100644
index 00000000000..472bdbabed5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-pst.lua
@@ -0,0 +1,105 @@
+if not modules then modules = { } end modules ['page-pst'] = {
+ version = 1.001,
+ comment = "companion to page-pst.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: adapt message
+
+local tonumber, next, type = tonumber, next, type
+local find, validstring = string.find, string.valid
+
+local context = context
+local implement = interfaces.implement
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
+local sortedkeys = table.sortedkeys
+local formatters = string.formatters
+
+local cache = { }
+
+local function flush(page)
+ local c = cache[page]
+ if c then
+ for i=1,#c do
+ -- characters.showstring(c[i])
+ context.viafile(c[i],formatters["page.%s"](validstring(page,"nopage")))
+ end
+ cache[page] = nil
+ end
+end
+
+local function setnextpage()
+ local n = next(cache) and sortedkeys(cache)[1]
+ if not n then
+ n = 0 -- nothing in the cache
+ elseif n == 0 then
+ n = -1 -- generic buffer (0)
+ elseif n > 0 then
+ -- upcoming page (realpageno)
+ end
+ texsetcount("global","c_page_postponed_blocks_next_page",n)
+end
+
+local function flushpostponedblocks(specification)
+ -- we need to flush previously pending pages as well and the zero
+ -- slot is the generic one so that one is always flushed
+ local t = sortedkeys(cache)
+ local p = tonumber(specification.page) or texgetcount("realpageno") or 0
+ for i=1,#t do
+ local ti = t[i]
+ if ti <= p then
+ flush(ti)
+ else
+ break
+ end
+ end
+ setnextpage()
+end
+
+implement {
+ name = "flushpostponedblocks",
+ actions = flushpostponedblocks,
+ arguments = {
+ {
+ { "page" }
+ }
+ }
+}
+
+local function registerpostponedblock(page)
+ if type(page) == "string" then
+ if find(page,"^+") then
+ page = texgetcount("realpageno") + (tonumber(page) or 1) -- future delta page
+ else
+ page = tonumber(page) or 0 -- preferred page or otherwise first possible occasion
+ end
+ end
+ if not page then
+ page = 0
+ end
+ local c = cache[page]
+ if not c then
+ c = { }
+ cache[page] = c
+ end
+ c[#c+1] = buffers.raw("postponedblock")
+ buffers.erase("postponedblock")
+ if page == 0 then
+ interfaces.showmessage("layouts",3,#c)
+ else
+ interfaces.showmessage("layouts",3,formatters["%s (realpage: %s)"](#c,page))
+ end
+ setnextpage()
+end
+
+implement {
+ name = "registerpostponedblock",
+ actions = registerpostponedblock,
+ arguments = "string"
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-pst.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-pst.mkiv
new file mode 100644
index 00000000000..f12663f6665
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-pst.mkiv
@@ -0,0 +1,104 @@
+%D \module
+%D [ file=page-mis,
+%D version=2008.11.17, % was part of page-flt.tex / 2000.10.20
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Postponing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Postponing}
+
+\registerctxluafile{page-pst}{1.001}
+
+\unprotect
+
+% postponing
+
+\newevery\everytopofpage\relax
+
+\appendtoks
+ \the\everytopofpage
+\to \everystarttext
+
+\appendtoks
+ \global\everytopofpage\emptytoks
+\to \everystoptext
+
+% \startpostponing [pagenumber] [+pageoffset]
+%
+% \startpostponing[2]
+% PAGE 2 \blank
+% \stoppostponing
+%
+% \startpostponing[+1]
+% PAGE +1 \blank
+% \stoppostponing
+%
+% \startpostponing[+2]
+% PAGE +2 \blank
+% \stoppostponing
+%
+% \starttext \dorecurse{4}{\input tufte \page} \stoptext
+
+%D There is no real need to use \LUA\ here but the bookkeeping
+%D is somewhat easier and we also can erase buffers easier when
+%D we keep a local cache, especially as we can flush per page.
+
+%newif \ifinpostponing % prevents nesting
+
+\newcount \c_page_postponed_blocks_next_page % set at the lua end
+\newconditional\c_page_postponed_busy
+
+\unexpanded\setvalue{\e!start\v!postponing}%
+ {\bgroup
+ \obeylines
+ \doifelsenextoptional{\egroup\page_postponed_blocks_start}{\egroup\page_postponed_blocks_start[0]}}
+
+\unexpanded\setvalue{\e!stop\v!postponing}%
+ {\clf_registerpostponedblock{\currentpostponedpage}\relax}
+
+\def\page_postponed_blocks_start[#1]%
+ {\edef\currentpostponedpage{#1}%
+ \grabbufferdatadirect{postponedblock}{\e!start\v!postponing}{\e!stop\v!postponing}}
+
+% officially we should flush again after a flush as there can be new future pages
+% but that will be looked into when we run into it
+
+\unexpanded\def\page_postponed_blocks_flush_indeed
+ {\begingroup
+ \setsystemmode\v!postponing
+ \settrue\c_page_postponed_busy
+ \pagetotal\zeropoint % here? still needed? (was after flush pagefloats)
+ \the\everytopofpage\relax
+ %\flushrestfloats
+ \page_floats_flush_page_floats
+ \setnormalcatcodes % postponing in verbatim
+ \uncatcodespacetokens % postponing in startlines
+ \restoreglobalbodyfont % otherwise problems inside split verbatim
+ \clf_flushpostponedblocks
+ % page {123}
+ \relax
+ \page_otr_command_flush_floats % new but potential dangerous, maybe we need a classification
+ \endgroup} % of blocks: with and without flush
+
+\unexpanded\def\page_postponed_blocks_flush
+ {\ifconditional\c_page_postponed_busy
+ % probably a nested flush
+ \else\ifnum\c_page_postponed_blocks_next_page=\zerocount
+ % nothing in cache
+ \else\ifnum\c_page_postponed_blocks_next_page<\zerocount
+ % generic cache
+ \page_postponed_blocks_flush_indeed
+ \else\ifnum\c_page_postponed_blocks_next_page>\realpageno
+ % future content
+ \else
+ % pending content
+ \page_postponed_blocks_flush_indeed
+ \fi\fi\fi\fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv
new file mode 100644
index 00000000000..9adcb23c7b3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv
@@ -0,0 +1,310 @@
+%D \module
+%D [ file=page-run,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Runtime Macros}
+
+\unprotect
+
+\gdef\showprint
+ {\dotripleempty\page_layouts_show_print}
+
+\gdef\page_layouts_show_print[#1][#2][#3]% only english
+ {\setbuffer[crap]%
+ \unprotect
+ \definepapersize[X][\c!width=4em, \c!height=6em]
+ \definepapersize[Y][\c!width=12em,\c!height=14em]
+ \setuppapersize[X,#1][Y,#2]
+ \setuplayout[#3]
+ \setuplayout[\v!page]
+ \framed
+ [\c!offset=\v!overlay,\c!strut=\v!no,
+ \c!width=\paperwidth,\c!height=\paperheight]
+ {\ss ABC\par DEF}%
+ \protect
+ \endbuffer
+ \framed[\c!offset=\v!overlay,\c!strut=\v!no]{\typesetbuffer[crap]}}
+
+% \switchtobodyfont[8pt]
+%
+% \startcombination[4*4]
+% {\showprint} {\strut}
+% {\showprint[][][location=middle]} {\type{location=middle}}
+% {\showprint[][][location=middle,marking=on]} {\type{markering=aan}\break\type{location=middle}}
+% {\showprint[][][location=middle,marking=on,nx=2]} {\type{markering=aan}\break\type{location=middle}\break\type{nx=2}}
+% {\showprint[][][location=left]} {\type{location=left}}
+% {\showprint[][][location=right]} {\type{location=right}}
+% {\showprint[][][location={left,bottom}]} {\type{location={left,bottom}}}
+% {\showprint[][][location={right,bottom}]} {\type{location={right,bottom}}}
+% {\showprint[][][nx=2,ny=1]} {\type{nx=2,ny=1}}
+% {\showprint[][][nx=1,ny=2]} {\type{nx=1,ny=2}}
+% {\showprint[][][nx=2,ny=2]} {\type{nx=2,ny=2}}
+% {\showprint[][][nx=2,ny=2,location=middle]} {\type{nx=2,ny=2}\break\type{location=middle}}
+% {\showprint[][][backoffset=3pt]} {\type{rugoffset=.5cm}}
+% {\showprint[][][topoffset=3pt]} {\type{kopoffset=.5cm}}
+% {\showprint[][][scale=1.5]} {\type{schaal=1.5}}
+% {\showprint[][][scale=0.8]} {\type{schaal=0.8}}
+% \stopcombination
+%
+% \startcombination[3*4]
+% {\showprint[landscape][] [location=middle]} {\type{landscape}}
+% {\showprint[] [landscape][location=middle]} {\strut\break\type{landscape}}
+% {\showprint[landscape][landscape][location=middle]} {\type{landscape}\break\type{landscape}}
+% {\showprint[90] [] [location=middle]} {\type{90}}
+% {\showprint[] [90] [location=middle]} {\strut\break\type{90}}
+% {\showprint[90] [90] [location=middle]} {\type{90}\break\type{90}}
+% {\showprint[180] [] [location=middle]} {\type{180}}
+% {\showprint[] [180] [location=middle]} {\strut\break\type{180}}
+% {\showprint[180] [180] [location=middle]} {\type{180}\break\type{180}}
+% {\showprint[mirrored] [] [location=middle]} {\type{mirrored}}
+% {\showprint[] [mirrored] [location=middle]} {\strut\break\type{mirrored}}
+% {\showprint[mirrored] [mirrored] [location=middle]} {\type{mirrored}\break\type{mirrored}}
+% \stopcombination
+
+% maybe we will have page-run.lua
+
+\startluacode
+local format, concat = string.format, table.concat
+local todimen = number.todimen
+local texdimen = tex.dimen
+
+local function asdimen(name,unit)
+ return todimen(texdimen[name],unit,"%0.4f") -- 4 is more than enough, even 3 would be okay
+end
+
+local function checkedoptions(options)
+ if type(options) == "table" then
+ return options
+ elseif not options or options == "" then
+ options = "pt,cm"
+ end
+ options = utilities.parsers.settings_to_hash(options)
+ local n = 4
+ for k, v in table.sortedhash(options) do
+ local m = tonumber(k)
+ if m then
+ n = m
+ end
+ end
+ options.n = n
+ return options
+end
+
+function commands.showlayoutvariables(options)
+
+ options = checkedoptions(options)
+
+ local dimensions = { "pt", "bp", "cm", "mm", "dd", "cc", "pc", "nd", "nc", "sp", "in" }
+
+ local n = 0
+ for i=1,#dimensions do
+ if options[dimensions[i]] then
+ n = n + 1
+ end
+ end
+
+ if n == 0 then
+ options.pt = true
+ n = 1
+ end
+
+ local function showdimension(name)
+ context.NC()
+ context.tex(interfaces.interfacedcommand(name))
+ context.NC()
+ for i=1,#dimensions do
+ local d = dimensions[i]
+ if options[d] then
+ context("%s%s",asdimen(name,d),d)
+ context.NC()
+ end
+ end
+ context.NR()
+ end
+
+ local function showmacro(name)
+ context.NC()
+ context.tex(interfaces.interfacedcommand(name))
+ context.NC()
+ context.getvalue(name)
+ context.NC()
+ context.NR()
+ end
+
+ local function reportdimension(name)
+ local result = { }
+ for i=1,#dimensions do
+ local d = dimensions[i]
+ if options[d] then
+ result[#result+1] = format("%12s%s",asdimen(name,d),d)
+ end
+ end
+ commands.writestatus("layout",format("%-24s %s",interfaces.interfacedcommand(name),concat(result," ")))
+ end
+
+ if tex.count.textlevel == 0 then
+
+ -- especially for Luigi:
+
+ reportdimension("paperheight")
+ reportdimension("paperwidth")
+ reportdimension("printpaperheight")
+ reportdimension("printpaperwidth")
+ reportdimension("topspace")
+ reportdimension("backspace")
+ reportdimension("makeupheight")
+ reportdimension("makeupwidth")
+ reportdimension("topheight")
+ reportdimension("topdistance")
+ reportdimension("headerheight")
+ reportdimension("headerdistance")
+ reportdimension("textheight")
+ reportdimension("footerdistance")
+ reportdimension("footerheight")
+ reportdimension("bottomdistance")
+ reportdimension("bottomheight")
+ reportdimension("leftedgewidth")
+ reportdimension("leftedgedistance")
+ reportdimension("leftmarginwidth")
+ reportdimension("leftmargindistance")
+ reportdimension("textwidth")
+ reportdimension("rightmargindistance")
+ reportdimension("rightmarginwidth")
+ reportdimension("rightedgedistance")
+ reportdimension("rightedgewidth")
+ reportdimension("bodyfontsize")
+ reportdimension("lineheight")
+
+ else
+
+ context.starttabulate { "|l|" .. string.rep("Tr|",n) }
+
+ showdimension("paperheight")
+ showdimension("paperwidth")
+ showdimension("printpaperheight")
+ showdimension("printpaperwidth")
+ showdimension("topspace")
+ showdimension("backspace")
+ showdimension("makeupheight")
+ showdimension("makeupwidth")
+ showdimension("topheight")
+ showdimension("topdistance")
+ showdimension("headerheight")
+ showdimension("headerdistance")
+ showdimension("textheight")
+ showdimension("footerdistance")
+ showdimension("footerheight")
+ showdimension("bottomdistance")
+ showdimension("bottomheight")
+ showdimension("leftedgewidth")
+ showdimension("leftedgedistance")
+ showdimension("leftmarginwidth")
+ showdimension("leftmargindistance")
+ showdimension("textwidth")
+ showdimension("rightmargindistance")
+ showdimension("rightmarginwidth")
+ showdimension("rightedgedistance")
+ showdimension("rightedgewidth")
+ context.NR()
+ showdimension("bodyfontsize")
+ showdimension("lineheight")
+ context.NR()
+ showmacro("strutheightfactor")
+ showmacro("strutdepthfactor")
+ showmacro("topskipfactor")
+ showmacro("maxdepthfactor")
+
+ context.stoptabulate()
+
+ end
+
+end
+
+function commands.showlayout(options)
+
+ options = checkedoptions(options)
+
+ if tex.count.textlevel == 0 then
+
+ commands.showlayoutvariables(options)
+
+ else
+
+ context.page()
+ context.bgroup()
+ context.showframe()
+ context.setuplayout { marking = interfaces.variables.on }
+ for i=1,(options.n or 4) do
+ commands.showlayoutvariables(options)
+ context.page()
+ end
+ context.egroup()
+
+ end
+
+end
+\stopluacode
+
+\gdef\page_layouts_show_frame[#1][#2]%
+ {\ifsecondargument
+ \setupbackgrounds
+ [\v!page]
+ [\c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\zeropoint,
+ \c!framedepth=\zeropoint,
+ \c!framecolor=layout:page]
+ \setupbackgrounds
+ [#1][#2]
+ [\c!background=,
+ \c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\zeropoint,
+ \c!framedepth=\zeropoint,
+ \c!framecolor=]
+ \else\iffirstargument
+ \showframe
+ [\v!header,\v!text,\v!footer]
+ [#1]
+ \else
+ \showframe
+ [\v!top,\v!header,
+ \v!text,
+ \v!footer,\v!bottom]
+ [\v!leftedge,\v!leftmargin,
+ \v!text,
+ \v!rightmargin,\v!rightedge]
+ \fi\fi
+ \setupbackgrounds
+ [\c!state=\v!repeat]}
+
+\gdef\page_layouts_show_setups[#1]%
+ {\ctxcommand{showlayoutvariables("#1")}}
+
+\gdef\page_layouts_show_layout[#1]%
+ {\ctxcommand{showlayout("#1")}}
+
+\unexpanded\gdef\showframe {\dodoubleempty\page_layouts_show_frame }
+\unexpanded\gdef\showsetups{\dosingleempty\page_layouts_show_setups}
+\unexpanded\gdef\showlayout{\dosingleempty\page_layouts_show_layout}
+
+\unexpanded\gdef\showmargins
+ {\starttabulate
+ \NC asynchrone \NC \doifelseoddpage {odd} {even} \NC \NR
+ \NC synchrone \NC \doifelserightpage {right} {left} \NC \NR
+ \NC right margin \NC \the\rightmarginwidth \NC \NR
+ \NC left margin \NC \the\leftmarginwidth \NC \NR
+ \NC outer margin \NC \the\outermarginwidth \NC \NR
+ \NC inner margin \NC \the\innermarginwidth \NC \NR
+ \stoptabulate}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi
new file mode 100644
index 00000000000..eb83890328e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi
@@ -0,0 +1,405 @@
+%D \module
+%D [ file=page-sel, % moved from page-imp
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Selection,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This code relates to old texexec features and one can wonder if it needs
+%D to be in the core. So, this could become runtime loaded code. Some of
+%D the alternatives need checking.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Selection}
+
+\unprotect
+
+%D One can (mis)use this mechanism to (re)arrange pages of already produced
+%D files.
+%D
+%D \starttyping
+%D \insertpages[file.pdf][1,3][n=30,width=18cm]
+%D \stoptyping
+%D
+%D The pages are inserted in the text area, and even pages are repositioned
+%D according to the width. In this example empty pages are added after page
+%D 1 and 3.
+%D
+%D Selecting pages can be accomplished by:
+%D
+%D \starttyping
+%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
+%D \stoptyping
+%D
+%D One may pass \type {odd} or \type {even} instead of a comma separated list. A
+%D third alternative is:
+%D
+%D \starttyping
+%D \copypages[file.pdf][n=30,scale=950]
+%D \stoptyping
+%D
+%D This macros inserts the page, according to the settings provided.
+
+\installcorenamespace{withpages}
+
+\installsetuponlycommandhandler \??withpages {withpages}
+% \installdirectcommandhandler \??withpages {withpages}
+
+\newcount\c_page_selectors_n
+
+\unexpanded\def\insertpages
+ {\dotripleempty\page_selectors_insert}
+
+\def\page_selectors_insert[#filename][#emptylist][#settings]%
+ {\doifelseassignment{#emptylist}
+ {\page_selectors_insert_indeed[#filename][][#emptylist]}
+ {\page_selectors_insert_indeed[#filename][#emptylist][#settings]}}
+
+\def\page_selectors_insert_indeed[#filename][#emptylist][#settings]%
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \setupcurrentwithpages[\c!width=\zeropoint,\c!n=\noffigurepages,#settings]%
+ \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
+ \scratchwidth\directwithpagesparameter\c!width\relax
+ \doifinset0{#emptylist}
+ {\emptyhbox\page}%
+ \dorecurse\c_page_selectors_n
+ {\page_selectors_filter_a_page{#filename}\recurselevel
+ \doifinset\recurselevel{#emptylist}
+ {\emptyhbox\page}}%
+ \egroup}
+
+\unexpanded\def\filterpages
+ {\dotripleempty\page_selectors_filter}
+
+\def\page_selectors_filter[#filename][#selection][#settings]% % \noffigurepages not yet supported
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \setupcurrentwithpages[\c!width=\zeropoint,\c!n=\noffigurepages,#settings]%
+ \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
+ \scratchwidth\directwithpagesparameter\c!width\relax
+ \edef\p_selection{#selection}%
+ \ifx\p_selection\v!even
+ \dorecurse\c_page_selectors_n
+ {\ifodd\recurselevel\else
+ \page_selectors_filter_a_page{#filename}\recurselevel
+ \fi}%
+ \else\ifx\p_selection\v!odd
+ \dorecurse\c_page_selectors_n
+ {\ifodd\recurselevel\relax
+ \page_selectors_filter_a_page{#filename}\recurselevel
+ \fi}%
+ \else
+ \def\page_selectors_filter_step_indeed#page%
+ {\ifnum#page>\c_page_selectors_n\else
+ \page_selectors_filter_a_page{#filename}{#page}%
+ \fi}%
+ \def\page_selectors_filter_step#step%
+ {\dowithrange{#step}\page_selectors_filter_step_indeed}%
+ \processcommacommand[\p_selection]\page_selectors_filter_step
+ \fi\fi
+ \egroup}
+
+\def\page_selectors_filter_a_page#filename#page%
+ {\hbox to \textwidth
+ {\ifdim\scratchwidth>\zeropoint
+ \rightorleftpageaction{\scratchwidth\zeropoint}{\hfill}%
+ \fi
+ \setbox\scratchbox\hbox
+ {\hskip-\scratchwidth
+ \externalfigure[#filename][\c!page=#page,\c!height=\textheight]\hss}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox}
+ \page}
+
+\unexpanded\def\copypages
+ {\dotripleempty\page_selectors_copy}
+
+\def\page_selectors_copy[#filename][#settings][#figuresettings]%
+ {\bgroup
+ \getfiguredimensions[#filename]%
+ \setupcurrentwithpages[\c!marking=\v!off,\c!offset=\zeropoint,\c!n=\noffigurepages,#settings]%
+ \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
+ \scratchoffset\directwithpagesparameter\c!offset\relax
+ \dorecurse\c_page_selectors_n
+ {\vbox to \textheight
+ {\hsize\textwidth
+ \centeredbox
+ {\doifelse{\directwithpagesparameter\c!marking}\v!on\cuthbox\hbox % only place where cuthbox is used
+ {\ifdim\scratchoffset>\zeropoint\relax
+ \advance\vsize -2\scratchoffset
+ \advance\hsize -2\scratchoffset
+ \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
+ \else
+ \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!offset=\v!overlay]%
+ \fi}}}
+ \page}
+ \egroup}
+
+%D \macros
+%D {combinepages}
+%D
+%D Yet another way of postprocessing is handles by \type {\combinepages}. This macro
+%D builds a matrix of pages from a file, for example:
+%D
+%D \starttyping
+%D \setuppapersize
+%D [A4][A4] % or [A4,landscape][A4,landscape]
+%D
+%D \setuplayout
+%D [header=0pt,footer=1cm,
+%D backspace=1cm,topspace=1cm,
+%D width=middle,height=middle]
+%D
+%D \setupfootertexts
+%D [presentation---\currentdate\space---\space\pagenumber]
+%D
+%D \starttext
+%D \combinepages[slides][nx=2,ny=3,frame=on]
+%D \stoptext
+%D \stoptyping
+%D
+%D One can influence the way the pages are combined. (This will be explained some
+%D time.)
+
+\installcorenamespace{combinepagesalternative}
+
+\unexpanded\def\combinepages
+ {\dodoubleempty\page_selectors_combine}
+
+\def\page_selectors_combine[#filename][#settings]% a=perpag b=free
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \setupcurrentwithpages
+ [\c!alternative=\v!a,
+ \c!n=\noffigurepages,\c!nx=\plustwo,\c!ny=\plustwo,
+ \c!start=\plusone,\c!stop=\maxcard,
+ \c!distance=\bodyfontsize,
+ \c!bottom=\vfill,\c!top=\vss,\c!left=\hss,\c!right=\hss,
+ \c!before=\page,\c!after=\page,\c!inbetween=\blank,
+ \c!frame=,\c!background=,\c!backgroundcolor=,
+ \c!name={#filename},
+ #settings]%
+ \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
+ \directwithpagesparameter\c!before
+ \scratchnx\directwithpagesparameter\c!nx
+ \scratchny\directwithpagesparameter\c!ny
+ \scratchdistance\directwithpagesparameter\c!distance\relax
+ \scratchwidth\dimexpr(\textwidth-\scratchnx\scratchdistance+\scratchdistance)/\scratchnx\relax
+ \scratchheight\dimexpr(\textheight-\scratchny\scratchdistance+\scratchdistance)/\scratchny\relax
+ \expandnamespaceparameter\??combinepagesalternative\directwithpagesparameter\c!alternative\v!b
+ \directwithpagesparameter\c!after
+ \egroup}
+
+\setvalue{\??combinepagesalternative\v!a}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\vbox to \textheight
+ {\dorecurse\scratchny
+ {\hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\vbox to \scratchheight
+ {\hsize\scratchwidth
+ \vsize\scratchheight
+ \directwithpagesparameter\c!top
+ \hbox to \hsize
+ {\directwithpagesparameter\c!left
+ \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
+ \global\c_page_selectors_n\zerocount
+ \else\ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!object=\v!no,
+ \c!page=\number\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]%
+ \fi\fi
+ \directwithpagesparameter\c!right}
+ \directwithpagesparameter\c!bottom}%
+ \global\advance\combinedpagescounter\plusone
+ \hfil}%
+ \hfilneg}
+ \vfil}%
+ \vfilneg}%
+ \page
+ \ifnum\combinedpagescounter>\c_page_selectors_n
+ \exitloop
+ \fi}}
+
+\setvalue{\??combinepagesalternative\v!c}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\vbox to \textheight
+ {\hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\directwithpagesparameter\c!left
+ \vbox to \textheight
+ {\hsize\scratchwidth
+ \dorecurse\scratchny
+ {\directwithpagesparameter\c!top
+ \hbox to \hsize
+ {\vbox to \scratchheight
+ {\hsize\scratchwidth
+ \vsize\scratchheight
+ \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
+ \global\c_page_selectors_n\zerocount
+ \else\ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!object=\v!no,
+ \c!page=\number\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]%
+ \fi\fi}}
+ \global\advance\combinedpagescounter\plusone
+ \directwithpagesparameter\c!bottom}}%
+ \hfil}%
+ \hfilneg}}%
+ \page
+ \ifnum\combinedpagescounter>\c_page_selectors_n
+ \exitloop
+ \fi}}
+
+\expandafter\let\csname\??combinepagesalternative\v!horizontal\expandafter\endcsname\csname\??combinepagesalternative\v!a\endcsname
+\expandafter\let\csname\??combinepagesalternative\v!vertical \expandafter\endcsname\csname\??combinepagesalternative\v!c\endcsname
+
+\setvalue{\??combinepagesalternative\v!b}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\startbaselinecorrection
+ \hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\global\advance\combinedpagescounter\plusone
+ \ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \normalexpanded{\externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!page=\number\combinedpagescounter,
+ \c!width=\the\scratchwidth,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]}%
+ \hfill
+ \fi}%
+ \hfillneg}%
+ \stopbaselinecorrection
+ \ifnum\combinedpagescounter<\c_page_selectors_n\relax
+ \directwithpagesparameter\c!inbetween
+ \else
+ \exitloop
+ \fi}}
+
+% This macro cuts a page into n parts that can be pasted together.
+
+\unexpanded\def\slicepages
+ {\dotripleempty\page_selectors_slice}
+
+\def\page_selectors_slice[#filename][#oddsettings][#evensettings]%
+ {\ifthirdargument
+ \page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
+ \else
+ \page_selectors_slice_indeed[#filename][#oddsettings][#oddsettings]%
+ \fi}
+
+\let\slicedpagenumber\!!zerocount
+\let\slicedpagestepx \!!zerocount
+\let\slicedpagestepy \!!zerocount
+
+\def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
+ {\bgroup
+ \dontcomplain
+ \global\let\slicedpagenumber\!!zerocount
+ \getfiguredimensions[#filename]%
+ \setupcurrentwithpages
+ [\c!offset=\zeropoint,\c!hoffset=\zeropoint,\c!voffset=\zeropoint,
+ \c!width=\figurewidth,\c!height=\figureheight,\c!n=\noffigurepages,#oddsettings]%
+ \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
+ \ifnum\c_page_selectors_n>\zerocount
+ \definepapersize
+ [\s!dummy][\c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width]%
+ \setuppapersize
+ [\s!dummy][\s!dummy]%
+ \setuplayout
+ [\c!backspace=\zeropoint,\c!topspace=\zeropoint,
+ \c!height=\v!middle,\c!width=\v!middle,
+ \c!textdistance=\zeropoint,
+ \c!header=\zeropoint,\c!footer=\zeropoint]%
+ \fi
+ \dorecurse\noffigurepages
+ {\global\let\slicedpagenumber\recurselevel
+ \ifnum\c_page_selectors_n>\plusone
+ \dorecurse\c_page_selectors_n
+ {\let\slicedpagestepx\recurselevel
+ \dorecurse\c_page_selectors_n
+ {\let\slicedpagestepy\recurselevel
+ \clip
+ [\c!nx=\c_page_selectors_n,\c!ny=\c_page_selectors_n,\c!x=\slicedpagestepx,\c!y=\slicedpagestepy]
+ {\scale
+ [\c!scale=\number\c_page_selectors_n000]
+ {\externalfigure[#filename][\c!page=\slicedpagenumber]}}%
+ \page}}%
+ \else
+ \ifodd\slicedpagenumber\relax
+ \setupcurrentwithpages[#oddsettings]%
+ \else
+ \setupcurrentwithpages[#evensettings]%
+ \fi
+ \hskip\directwithpagesparameter\c!offset\relax
+ \clip
+ [\c!hoffset=\directwithpagesparameter\c!hoffset,\c!voffset=\directwithpagesparameter\c!voffset,
+ \c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width]
+ {\externalfigure[#filename][\c!page=\slicedpagenumber]}%
+ \page
+ \fi}
+ \egroup}
+
+% \starttext \slicepages[slice1.pdf][n=3] \stoptext
+
+\unexpanded\def\trimpages[#1]% was for a over decade in p-pdf-51.tex
+ {\begingroup
+ \getdummyparameters
+ [\c!file=dummy,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!width=17cm,
+ \c!height=24cm,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ #1]
+ \getfiguredimensions
+ [\dummyparameter\c!file]
+ [\c!object=\v!no]
+ \dorecurse\noffigurepages
+ {\scale
+ [\c!width=\paperwidth,
+ \c!height=\paperheight]
+ {\offset
+ [\c!x=\dummyparameter\c!x,
+ \c!y=\dummyparameter\c!y]
+ {\clip
+ [\c!hoffset=\dummyparameter\c!hoffset,
+ \c!voffset=\dummyparameter\c!voffset,
+ \c!width=\dummyparameter\c!width,
+ \c!height=\dummyparameter\c!height]
+ {% we correct by default, if not needed, introduce option
+ \setbox\nextbox\hbox
+ {\externalfigure[\dummyparameter\c!file][\c!page=##1]}%
+ \ifdim\wd\nextbox>\ht\nextbox
+ \rotate[\c!rotation=90]{\box\nextbox}%
+ \else
+ \box\nextbox
+ \fi}}}}%
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv
new file mode 100644
index 00000000000..6e6759208ce
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv
@@ -0,0 +1,2729 @@
+%D \module
+%D [ file=page-set,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Column Sets,
+%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.
+
+% not yet mkiv! probably namespace issues with localframed (only one left)
+%
+% getnoflines vs getrawnoflines
+
+% This is a rather old mechanism and we can best keep it as it is. If it gets
+% replaced by a more modern solution, it will be an extra mechanism. So, we
+% only do some basic cleanup.
+
+\writestatus{loading}{ConTeXt Page Macros / Column Sets}
+
+% todo : last longer than previous
+% todo : block span over last column if footnotes
+% todo : diagnosis balancing run
+% todo : separate footnote placement
+% todo : go on on same page with colset
+% todo : test page areas per page
+% todo : leftmargin/rightmargin (better than afstand(1))
+
+% use the OTRSET layer for more purposes, like the footnotes !
+
+\unprotect
+
+\newcount\tofcolumns % total
+\newcount\lofcolumns % left
+\newcount\rofcolumns % right
+
+\newcount\columnfirstcell \columnfirstcell=1
+\newcount\columnlastcell
+\newcount\columnfreecells
+\newcount\currenthcell
+\newcount\currentvcell
+\newcount\columnhcells
+\newcount\columnvcells
+
+\newif\ifenoughcolumncells
+\newif\ifsomefreecolumncells
+\newif\ifcolumnspread
+\newif\iftracecolumnset
+
+\newif\ifforcecolumnsetgrid \forcecolumnsetgridtrue
+\newif\ifcollectingsetcontent % never set
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes % never set \lastcolumnfootnotestrue
+\newif\ifintermediatefootnotes
+
+\newbox \b_page_set_preceding
+\newbox \b_page_set_trailing
+
+\newdimen \d_page_set_local_hsize
+\newconditional\c_page_set_width_set
+
+\installcorenamespace{columnsetgrid}
+
+\def\columnmaxcells {75} % runtime
+\def\columnmaxfreecells {0} % runtime
+\def\columngaplimit {0} % {5}
+
+\def\page_set_cell #1#2{\csname \??columnsetgrid:\number#1:\number#2\endcsname}
+\def\page_set_cell_get#1#2{\box\csname \??columnsetgrid:\number#1:\number#2\endcsname}
+\def\page_set_cell_set#1#2{\global\setbox\csname\??columnsetgrid:\number#1:\number#2\endcsname}
+
+\def\page_set_cell_doifelse#1#2%
+ {\relax
+ \ifvoid\csname\??columnsetgrid:\number#1:\number#2\endcsname
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_set_cell_erase_grid % maybe dedicated loops ... make another loop when max's have changed
+ {\bgroup
+ \increment\columnmaxcells\relax
+ \ifodd\realpageno \else
+ \columnspreadfalse
+ \fi
+ \ifcolumnspread
+ \page_set_cell_erase_grid_spread
+ \else
+ \page_set_cell_erase_grid_page
+ \fi
+ \page_set_cell_erase_grid_top
+ \global\columnfirstcell\zerocount
+ \global\columnlastcell \columnfirstcell
+ \global\columnfreecells\columnfirstcell
+ \egroup}
+
+\let\m_page_column_l\relax
+\let\m_page_column_r\relax
+
+\def\page_set_cell_erase_grid_spread
+ {\dorecurse\nofcolumns
+ {\let \m_page_column_l\recurselevel
+ \edef\m_page_column_r{\the\numexpr\recurselevel+\lofcolumns}%
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \else
+ \emptyhbox
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \fi
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \fi
+ \fi}}}
+
+\def\page_set_cell_erase_grid_page
+ {\dorecurse \tofcolumns
+ {\let\m_page_column_l\recurselevel
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \fi}}}
+
+\def\page_set_cell_erase_grid_top
+ {\dorecurse\tofcolumns
+ {\global\setbox\csname\??columnsetgrid:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}}
+
+% % % %
+
+\def\OTRSETmakeupwidth{\innermakeupwidth}
+
+\unexpanded\def\page_set_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_set_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+% The following two macros are used to compensate for a switch in body fonts
+% as in:
+%
+% \definecolumnset [two] [n=2,balancing=yes]
+% \definecolumnset [three] [n=3,balancing=yes]
+%
+% \setupcolumnsetlines[two][1][1][7]
+% \setupcolumnsetlines[two][1][2][10]
+%
+% \setupcolumnsetlines[three][1][1][40]
+% \setupcolumnsetlines[three][1][2][40]
+% \setupcolumnsetlines[three][1][3][40]
+%
+% \setupcolumnsetstart[three][1][1][15]
+% \setupcolumnsetstart[three][1][2][20]
+% \setupcolumnsetstart[three][1][3][20]
+%
+% \starttext
+% \startcolumnset [two] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \switchtobodyfont[small]
+% \startcolumnset [three] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+%D Marks in columnsets:
+%D
+%D \starttyping
+%D \definemarking[M]
+%D \setupheadertexts[\setups{show-M-marks}]
+%D \definecolumnset[test][n=3]
+%D
+%D \startsetups show-M-marks
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][1][last]\quad
+%D \getmarking[M][2][previous]/\getmarking[M][2][first]/\getmarking[M][2][last]\quad
+%D \getmarking[M][3][previous]/\getmarking[M][3][first]/\getmarking[M][3][last]\quad
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][last]\quad
+%D \getsavedmarking[M][previous]/\getsavedmarking[M][first]/\getsavedmarking[M][last]
+%D \stopsetups
+%D
+%D \startbuffer
+%D \section{Knuth} [K1]\marking[M]{k1} [K2]\marking[M]{k2} \input knuth
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \section{Douglas} [O]\marking[M]{o} \input douglas
+%D \stopbuffer
+%D
+%D \starttext
+%D \startcolumnset[test]
+%D \dorecurse{5}{\getbuffer}
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D % \column % sometimes needed
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+%D test case of Vit Zika (context list):
+%D
+%D \starttyping
+%D \setuplayout[height=middle,width=middle,grid=yes]
+%D
+%D \starttext
+%D \startcolumnset
+%D \dorecurse{10}
+%D {\input thuan \endgraf
+%D \bgroup
+%D \ss\restoreinterlinespace
+%D \dorecurse{3}{\input hawking \endgraf}
+%D \egroup
+%D \input bryson \endgraf}
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+\def\OTRSETsetcorrectnofcells#1%
+ {\bgroup
+ \!!counta#1\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \!!dimena-\!!counta\lineheight
+ \restoreglobalbodyfont % slow, we need a fast one
+ \advance\!!dimena\!!counta\lineheight
+ \getnoflines\!!dimena
+ \advance\!!counta\noflines
+ \ifnum\!!counta<#1\else
+ \!!counta#1\relax
+ \fi
+ \fi
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\scratchcounter\the\!!counta\relax}
+
+\def\OTRSETsetcorrectcellht
+ {\bgroup
+ \!!dimena-\strutht\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \restoreglobalbodyfont
+ \fi
+ \advance\!!dimena\strutht
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\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
+ \!!counte#3\advance\!!counte#5\advance\!!counte\minusone
+ \dostepwiserecurse{#2}\!!countd\plusone
+ {\!!countf\recurselevel
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\page_set_cell_set\!!countf\recurselevel#1}}%
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\wd\page_set_cell{#2}\recurselevel\hsize}%
+ \page_set_cell_set{#2}\!!counte#6}
+
+\def\OTRSETsetgridcells
+ {\doOTRSETsetgridcells{\copy\placeholderboxb}}
+
+\def\OTRSETerasegridcells#1#2#3#4%
+ {\doOTRSETsetgridcells{\emptybox}{#1}{#2}{#3}{#4}{\emptybox}}
+
+\unexpanded\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]}
+\unexpanded\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]}
+
+\installcorenamespace{columnsettag} % temp hack
+
+\def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value
+ {\iffifthargument
+ \setevalue{\??columnsettag:#1:#2:\number#3:\number#4}{\number#5}%
+ \else
+ \setevalue{\??columnsettag:#1:#2:\number#3:0}{\number#4}%
+ \fi}
+
+\def\currentcolumnmaxcellstag #1{\??columnsettag:l:\OTRSETidentifier:\columnsetpage:\number#1}
+\def\currentcolumnstartcelltag#1{\??columnsettag:s:\OTRSETidentifier:\columnsetpage:\number#1}
+
+\def\doresetcolumnsetlines#1%
+ {\ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi
+ \ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi}
+
+\def\currentcolumnsomecells#1#2%
+ {\ifcsname#1\mofcolumns\endcsname
+ \ifnum\csname#1\mofcolumns\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#1\mofcolumns\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#1\mofcolumns\endcsname\relax
+ \fi
+ \else\ifcsname#10\endcsname
+ \ifnum\csname#10\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#10\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#10\endcsname\relax
+ \fi
+ \else
+ #2%
+ \fi\fi}
+
+\def\currentcolumnmaxcells {\currentcolumnsomecells\currentcolumnmaxcellstag \columnmaxcells}
+\def\currentcolumnstartcell{\currentcolumnsomecells\currentcolumnstartcelltag\plusone}
+
+\def\OTRSETsetfreecells#1#2% col start
+ {\bgroup
+ \global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
+ \OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+ \ifnum\scratchcounter<\columnmaxcells\relax
+ \edef\columnmaxcells{\the\scratchcounter}% added 2013.04.19
+ \fi
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells a}%
+ \else
+ \doloop
+ {\ifnum\columnfirstcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \page_set_cell_doifelse{#1}\columnfirstcell
+ {\global\advance\columnfirstcell\plusone}\exitloop
+ \fi}%
+ \global\columnlastcell\columnfirstcell
+ \doloop
+ {\ifnum\columnlastcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \page_set_cell_doifelse{#1}\columnlastcell
+ {\global\advance\columnlastcell \minusone \exitloop}
+ {\global\advance\columnlastcell \plusone }%
+ \fi}%
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells b}%
+ \else
+ \ifnum\columnlastcell>\columnmaxcells
+ \global\columnlastcell\columnmaxcells
+ \fi
+ \global\columnfreecells\numexpr\columnlastcell-\columnfirstcell+\plusone\relax
+ \global\somefreecolumncellstrue
+ %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETgetmaxfreecells#1#2% col start
+ {\let\columnmaxfreecells\!!zerocount
+ \let\columnfrmfreecells\!!zerocount
+ \pushmacro \columnmaxcells
+\OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+\edef\columnmaxcells{\the\scratchcounter}%
+ \scratchcounter\zerocount
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\page_set_cell_doifelse{#1}\recurselevel
+ {\ifnum\columnmaxfreecells<\scratchcounter
+ \edef\columnmaxfreecells{\the\scratchcounter}%
+ \let\columnfrmfreecells\recurselevel
+ \fi
+ \scratchcounter\zerocount}
+ {\advance\scratchcounter\plusone}}%
+ \popmacro\columnmaxcells}
+
+\def\OTRSETrecurseRL#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone
+ {#1\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}}
+
+\def\OTRSETmakegridbox
+ {\ifcase\columndirection
+ \OTRSETdomakegridbox\plusone\nofcolumns\plusone
+ \else
+ \OTRSETdomakegridbox\nofcolumns\plusone\minusone
+ \fi}
+
+\def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness
+
+\def\page_set_make_background_box
+ {\begingroup
+ \mofcolumns\recurselevel % used to signal mp
+ \d_page_set_local_hsize\OTRSETlocalwidth\recurselevel
+ \scratchdistance\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\relax
+ \edef\currentcolumnset{\currentcolumnset:\recurselevel}%
+ \letcolumnsetparameter\c!width \d_page_set_local_hsize
+ \letcolumnsetparameter\c!height\!!heighta
+ \letcolumnsetparameter\c!lines \empty
+ \letcolumnsetparameter\c!region\currentcolumnset
+ \setbox\scratchbox\hbox\inheritedcolumnsetframed{}% maybe \fastlocalframed
+ \wd\scratchbox\d_page_set_local_hsize
+ \ht\scratchbox\!!heighta
+ \ifcase\columndirection
+ \hskip\scratchdistance
+ \box\scratchbox
+ \else
+ \box\scratchbox
+ \hskip\scratchdistance
+ \fi
+ \endgroup}
+
+\def\OTRSETdomakegridbox#1#2#3%
+ {\hbox\bgroup
+ \dontcomplain
+ \forgetall % can go once in \flush
+ \!!heighta \textheight
+ % test first !
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}\page_set_make_background_box}%
+ \hskip-\OTRSETmakeupwidth
+ % main text
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}
+ {\mofcolumns\recurselevel
+ \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
+ \offinterlineskip
+ \setbox\scratchbox\vbox to \!!heighta
+ {%\topskipcorrection % not needed
+ \ifcase\OTRSETbalancemethod
+ % no
+ \or
+ % yes
+ \doifelselayerdata{OTRTEXT}\vfill\relax % temp hack
+ \or
+ % top
+ \or
+ % bottom
+ \vfill
+ \fi
+ \dorecurse\columnmaxcells
+ {\setbox\scratchbox\hbox{\page_set_cell_get\mofcolumns\recurselevel}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \ifcase\columndirection
+ \box\scratchbox
+ \else
+ \hbox to \d_page_set_local_hsize
+ {\hskip\d_page_set_local_hsize\llap{\box\scratchbox}}%
+ \fi
+ \par}%
+ \ifcase\OTRSETbalancemethod
+ % no
+ \else
+ % yes, top, bottom
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \removedepth
+ \restoreglobalbodyfont
+ \vskip\strutdepth
+ \fi
+ \kern\zeropoint
+ \vss
+ \fi}%
+ \wd\scratchbox\d_page_set_local_hsize % \textwidth
+ \page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox
+ \ifcase\columndirection
+ \hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\box\scratchbox
+ \else
+ \box\scratchbox\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance
+ \fi}}%
+ \egroup}
+
+\let\OTRSETbalht\zeropoint
+
+\def\OTRSETreducegridbox % for the moment no difference between methods
+ {\globallet\OTRSETbalht\zeropoint
+ \ifcase\OTRSETbalancemethod
+ % no balancing
+ \else
+ \bgroup
+ \!!counta\columnmaxcells
+ \donetrue
+ \doloop
+ {\dorecurse\nofcolumns{\page_set_cell_doifelse\recurselevel\!!counta\donefalse\donothing}%
+ \ifdone
+ \ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi
+ \else
+ \exitloop
+ \fi}%
+ \ifnum\!!counta>\plusone
+ \!!heighta\lineheight
+ \multiply\!!heighta \!!counta
+ \advance\!!heighta \topskip
+ \advance\!!heighta -\lineheight
+ \else
+ \!!heighta\zeropoint
+ \fi
+ \xdef\OTRSETbalht{\the\!!heighta}%
+ \egroup
+ \fi}
+
+\def\OTRSETflushfinalfootnotes
+ {\ifcase\lastcolumnlastcell \else
+ \setbox\scratchbox\hbox
+ {\placebottomnotes}%
+ \ifdim\ht\scratchbox>\zeropoint
+ \setbox\scratchbox\hbox
+ {\hbox to \zeropoint{\page_set_cell_get\nofcolumns\lastcolumnlastcell}%
+ \box\scratchbox}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \page_set_cell_set\nofcolumns\lastcolumnlastcell\box\scratchbox
+ \fi
+ \global\lastcolumnlastcell\zerocount
+ \fi}
+
+\def\OTRSETdoflush
+ {\ifcollectingsetcontent
+ \global\mofcolumns\plusone
+ \else
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \ifnum\columnsetpage>\zerocount
+ \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
+ \fi
+ \doglobal\increment\columnsetpage
+ \OTRSETinitializecolumns
+ \OTRSETstartnextpage
+ \initializecolumntextareas
+ \fi}
+
+\newbox\OTRfinalpagebox
+
+\def\OTRSETdofinalflush % see \OTRSETdoflush
+ {\OTRSETflushfinalfootnotes
+ \placecolumntextareas
+ \OTRSETcentergridcells
+ \bgroup % we want to keep the reduction local
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \egroup % otherwise we get the wrong number of free cells
+ %\gdef\localcolumnmaxcells{0}% here ?
+ \global\mofcolumns\nofcolumns} % otherwise problems in finaloutput
+
+\def\OTRSETdofinaloutput
+ {\ifdim\ht\OTRfinalpagebox=\textheight
+ \bgroup
+ \ifcase\OTRSETbalancemethod
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
+ \else\ifdim\OTRSETbalht>\zeropoint
+ % catch a bordercase
+ \scratchdimen\OTRSETbalht
+ \advance\scratchdimen\lineheight\relax
+ \ifdim\scratchdimen>\textheight
+ % full page
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
+ \else
+ % same page
+ \global\setbox\OTRfinalpagebox \iftracecolumnset\ruledvbox\else\vbox\fi to \OTRSETbalht
+ {\box\OTRfinalpagebox\vss}%
+ \setlayer[OTRTEXT]{\box\OTRfinalpagebox}%
+ \snaptogrid\vbox{\vskip\OTRSETbalht}% hack
+ \fi
+ \else
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
+ \fi \fi
+ \globallet\OTRSETbalht\zeropoint
+ \egroup
+ \fi}
+
+\definesystemconstant {colset}
+
+\definetwopasslist\s!colset
+
+\newdimen \OTRSETtextswidth
+\newdimen \OTRSETtextsheight
+\let \OTRSETidentifier=\empty
+
+\def\OTRSETskipstart
+ {\doifelsenothing{\columnsetparameter\c!start}
+ {\scratchcounter\zerocount}%
+ {\scratchcounter\columnsetparameter\c!start}%
+ \relax % needed !
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter\plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\scratchcounter
+ \emptybox
+ \fi}
+
+\unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?)
+ {\ifcollectingsetcontent \else % can be assigndimen
+ \OTRSETsetcolumnmaxcells % layout can be changed
+ \OTRSETskipstart % not that well tested
+ \OTRSETcheckinsert % added
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \global\vsize\columnfreecells\lineheight
+ \ifinotr % else problems with floats, see extreme
+ \pagegoal\vsize % niet nodig, tenzij binnen otr
+ \fi
+ \synchronizeoutput % fails on example
+ % \allowbreak % hm
+ \fi
+ \synchronizenotes
+ \fi}
+
+\def\page_set_command_set_hsize % of course this does not migrate outside the otr
+ {\d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
+ \textwidth\d_page_set_local_hsize
+ \hsize\d_page_set_local_hsize}
+
+\unexpanded\def\page_set_command_synchronize_hsize
+ {\ifconditional\c_page_set_width_set
+ \bgroup
+ \scratchdimen\OTRSETlocalwidth\mofcolumns
+ \ifdim\scratchdimen=\textwidth
+ \egroup
+ \else
+ % only if change in width and \column/\break
+ \egroup
+ \page_set_command_set_hsize
+ \fi
+ \fi}
+
+\def\OTRSETcheckfreelines
+ {\page_set_command_set_vsize}
+
+\def\doOTRSETcolumnseparator
+ {\hbox to \zeropoint{\hss\red\vl\hss}}
+
+\let\OTRSETcolumnseparator\relax
+
+\def\showbreaks
+ {\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}
+
+\def\OTRSETcolumnhbreak
+ {\ifhmode
+ \bgroup
+ \removeunwantedspaces
+ \parfillskip\zeropoint
+ \OTRSETcolumnseparator
+ \par
+ \egroup
+ \fi}
+
+\installcolumnbreakmethod \s!columnset \v!local
+ {\OTRSETcolumnhbreak
+ \page_otr_flush_all_floats
+ \page_otr_eject_page
+ % no \page_set_command_set_hsize, can be mid smaller (like tabulate)
+ % also, this one should be executed at the outer level
+ % (setting hsize inside otr does not work)
+ \page_set_command_synchronize_hsize}
+
+% We need to make sure that we really leave the column; mid
+% column we may end up in an empty gap, and we don't want to
+% stay there (basically such a gap is a small empty page
+% then).
+
+\installcolumnbreakmethod \s!columnset \v!yes
+ {\OTRSETcolumnhbreak
+ \edef\savedmofcolumns{\the\mofcolumns}%
+ \edef\savedrealpageno{\the\realpageno}%
+ \page_otr_flush_all_floats
+ \page_otr_eject_page
+ \doloop
+ {\ifnum\savedmofcolumns=\mofcolumns
+ \ifnum\savedrealpageno=\realpageno
+ \OTRSETdummycolumn
+ \else
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \page_set_command_synchronize_hsize}
+
+\installcolumnbreakmethod \s!columnset \s!unknown
+ {\expanded{\OTRSETgotocolumn[\@@columnspecification]}}
+
+\installcolumnbreakmethod \s!columnset \v!page
+ {\page_otr_fill_and_eject_page}
+
+\newtoks\OTRSETeverystartofcolumn
+
+\newbox\OTRSETsavedfootnotes
+
+% \installoutputroutine\OTRSETflushtextsofar % spacing goes wrong
+
+%\def\OTRSETflushtextsofar
+% {\ifvoid\normalpagebox \else
+% \setbox\scratchbox\vbox{\unvbox\normalpagebox}%
+% \OTRSETsavenotes
+% \OTRSEThandleflushedtext0
+% \fi}
+
+% The complication is in the fact that when the HERE float
+% is placed, the otr is not invoked when there is not yet
+% enough content; this can lead to a change in order (turning
+% on the tracer with option 0 is very instructive, watch the
+% small numbers in the margin)
+%
+% 0 = no flushing, so no interference but user should handle
+% border cases of placement
+% 1 = the normal otr, rather untested
+% 2 = a solution that works ok, is experimental and above
+% all messy
+
+\newconstant\OTRSETflushtextmode % will be replaced
+
+\def\OTRSETflushtextsofar % needs renaming
+ {\ifcase\OTRSETflushtextmode
+ % don't mess around
+ \or
+ % the normal one
+ \ifvoid\normalpagebox\else
+ \OTRSETnaturalflush
+ \OTRSETcheckfreelines
+ \fi
+ \or
+ % way to complicated, but kind of ok
+ \doOTRSETflushtextsofar
+ \fi}
+
+\newskip\lastskipinotr
+
+\installoutputroutine\doOTRSETflushtextsofar % experimental
+ {\ifvoid\normalpagebox\else
+ \scratchdimen\dp\normalpagebox
+ \setbox\scratchbox\vbox
+ {\forgetall
+ \unvbox\normalpagebox
+ \global\lastskipinotr\lastskip\relax
+ \ifdim\lastskipinotr>\zeropoint\relax
+ \removelastskip
+ \else
+ \kern-\scratchdimen % handle depth
+ \fi}%
+ \ifdim\lastskipinotr>\zeropoint
+ \scratchskip\ht\scratchbox
+ \setbox\scratchbox\hbox
+ {\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\scratchdimen
+ \ht\scratchbox\scratchskip
+ \fi
+ \OTRSETsavenotes
+ \OTRSEThandleflushedtext\zerocount
+ \ifdim\lastskipinotr>\zeropoint
+ %\vskip \lastskipinotr % hm, gets lost anyway
+ \else
+ % we should not discard skips after here; tricky
+ \fi
+ \page_set_command_set_vsize
+ \fi}
+
+\def\OTRSETplacebottomnotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \ifintermediatefootnotes \placebottomnotes \fi
+ \fi
+ \else
+ \placebottomnotes
+ \fi}
+
+\def\OTRSETflushsavednotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \flushsavednotes
+ \fi
+ \else
+ \flushsavednotes
+ \fi}
+
+\def\OTRSETsavenotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns \else
+ \savenotes
+ \fi
+ \fi}
+
+\appendtoks \OTRSETflushsavednotes \to \OTRSETeverystartofcolumn
+
+\def\OTRSETnaturalflush
+ {\bgroup
+ \forgetall % new, needed !
+ \setbox0\vbox to \columnfreecells\lineheight
+ {\vskip-\topskip
+ \vskip\lineheight
+ \prevdepth\strutdp
+ \unvbox\normalpagebox
+ \vfill}%
+ \setbox2\hbox
+ {\OTRSETplacebottomnotes}%
+ \setbox\scratchbox\hbox
+ {\wd0\zeropoint\box0\box2}%
+ \dp\scratchbox\strutdp
+ \OTRSEThandleflushedtext\plusone
+ \egroup}
+
+\newcount\lastcolumnlastcell
+
+\def\OTRSEThandleflushedtext#1%
+ {\getnoflines{\ht\scratchbox}%
+ %\wd\scratchbox\textwidth % geen \hsize kan < zijn in bv split tabulate
+ \wd\scratchbox\OTRSETlocalwidth\mofcolumns
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxf}
+ \mofcolumns\columnfirstcell\plusone\noflines
+ {\page_areas_registered_box1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
+ \global\columnlastcell\columnfirstcell
+ \global\advance\columnlastcell \noflines
+ \global\lastcolumnlastcell\columnlastcell
+ \global\advance\lastcolumnlastcell \minusone
+ % find next (acceptable) gap, todo: deadcycle
+ \ifcase#1\else
+ \OTRSETfillgapsbetweencells\mofcolumns\columnlastcell
+ \fi
+ \OTRSETfindnextgap
+ % \message{\the\mofcolumns,\the\columnfirstcell,\the\columnfreecells}%
+ % \wait
+ % we cannot adapt the hsize since it may have changed (like
+ % inside a tabulate) so we only change it when there is a
+ % reason to do so
+ \page_set_command_synchronize_hsize
+ \page_set_command_set_vsize}
+
+\def\OTRSETfindnextgap
+ {\OTRSETsetfreecells\mofcolumns\columnlastcell
+ \ifsomefreecolumncells
+ % okay
+ \else
+ \global\advance\mofcolumns \plusone
+ \ifnum\mofcolumns>\nofcolumns
+ \OTRSETdoflush
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \page_set_command_flush_floats
+ \else
+ \the\OTRSETeverystartofcolumn
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \fi
+ \fi}
+
+\let\OTRSETcheckfreelines\donothing
+
+\def\OTRSETfillgapsbetweencells#1#2% col
+ {\ifnum\columngaplimit>\zerocount
+ \donefalse
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\page_set_cell_doifelse{#1}\recurselevel
+ {\ifdone
+ \!!countb\recurselevel \advance\!!countb -\!!counta\relax
+ \ifnum\!!countb>\plusone
+ \advance\!!countb \minusone
+ \ifnum\!!countb<\columngaplimit\relax
+ \!!countb\recurselevel \advance\!!countb \minusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\page_set_cell_set{#1}\recurselevel\copy\placeholderboxc}%
+ %\message{[gap]}%
+ \fi
+ \fi
+ \fi
+ \donefalse}
+ {\ifdone \else
+ \donetrue
+ \!!counta\recurselevel
+ \fi}}%
+ \fi}
+
+\appendtoks
+ \OTRSETfillgapsbetweencells\mofcolumns\plusone
+\to \OTRSETeverystartofcolumn
+
+\newif\ifspancolumnslots \spancolumnslotstrue
+\newif\ifcheckcolumnspan \checkcolumnspantrue
+
+\def\OTRSETcheckwidthgap#1#2% box size
+ {\ifcheckcolumnspan
+ \bgroup
+ \scratchdimen#2%
+ \advance\scratchdimen-\wd#1\relax
+ \ifdim-10\scaledpoint>\scratchdimen
+ \egroup
+ \else\ifdim10\scaledpoint<\scratchdimen
+ \egroup
+ \else
+ \egroup
+ \wd#1=#2%
+ \fi\fi
+ \fi}
+
+\def\OTRSETcheckcolumnslot#1%
+ {\enoughcolumncellstrue
+ \ifspancolumnslots\else
+ \OTRSETcheckwidthgap#1\hsize
+ \ifdim\wd#1>\hsize
+ \enoughcolumncellsfalse
+ \fi
+ \fi
+ \ifenoughcolumncells
+ \getnoflines\pagetotal
+ \scratchcounter\noflines
+ \getnoflines{\ht#1}%
+ \columnvcells\noflines
+ \columnhcells\plusone
+ \advance\scratchcounter \columnvcells \relax
+ \ifnum\scratchcounter>\columnfreecells
+ \enoughcolumncellsfalse
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotPAGE#1%
+ {\ifenoughcolumncells
+ % to do
+ \OTRSETsavebox{#1}%
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotTOPS#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
+ {\hbox{\copy#1}}%
+ \page_set_command_set_vsize
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotBOTS#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \edef\savedcolumnlastcell{\the\columnlastcell}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \advance\columnlastcell -\columnvcells \advance\columnlastcell \plusone
+% \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \OTRSETcheckcolumnspace\mofcolumns\columnlastcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells{\copy#1}%
+ \OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
+ \page_set_command_set_vsize
+ \else
+ \columnlastcell\savedcolumnlastcell
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\newdimen\totalcolumnspace
+
+\def\columnspacetopoffset{0}
+\def\columnspacebotoffset{0}
+
+\def\OTRSETcheckcolumnspace#1#2#3% col row box
+ {\columnhcells\plusone
+ \totalcolumnspace\zeropoint
+ \scratchcounter#1%
+ \enoughcolumncellstrue
+ \doloop
+ {\advance\totalcolumnspace \OTRSETlocalwidth\scratchcounter\relax % needed
+\OTRSETcheckwidthgap#3\totalcolumnspace
+ \ifnum\wd#3>\totalcolumnspace\relax
+ \ifnum\scratchcounter=\nofcolumns
+ \enoughcolumncellsfalse
+ \exitloop
+ \else
+ \advance\columnhcells \plusone
+ \advance\scratchcounter \plusone
+ \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\number\scratchcounter}\c!distance
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \ifenoughcolumncells
+ \getnoflines{\ht#3}%
+ \columnvcells\noflines
+ \OTRSETcheckcolumncells{#1}{#2}\columnhcells\columnvcells
+ \fi}
+
+\def\OTRSETcheckcolumncells#1#2#3#4% col row wid hei
+ {\!!countd#1\advance\!!countd#3\advance\!!countd\minusone
+ \!!counte#2\advance\!!counte#4\advance\!!counte\minusone
+ \ifnum\!!counte>\columnmaxcells\relax
+ \enoughcolumncellsfalse
+ \else
+ \enoughcolumncellstrue
+%\let\columnspacetopoffset\zerocount
+%\scratchcounter#2\advance\scratchcounter\minusone
+%\ifnum\scratchcounter>0
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacetopoffset \relax
+% \advance\columnvcells \columnspacetopoffset \relax
+%\fi
+%\let\columnspacebotoffset\zerocount
+%\scratchcounter\!!counte
+%\advance\scratchcounter \columnvcells \relax
+%\ifnum\scratchcounter>\columnmaxcells\else
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacebotoffset \relax
+% \advance\columnvcells \columnspacebotoffset \relax
+%\fi
+ \dostepwiserecurse{#1}\!!countd\plusone % cols
+ {\ifenoughcolumncells
+ \!!countf\recurselevel\relax
+ \dostepwiserecurse{#2}\!!counte\plusone % rows
+ {\ifenoughcolumncells
+ \page_set_cell_doifelse\!!countf\recurselevel
+ {\enoughcolumncellsfalse}{}%
+ \fi}%
+ \fi}%
+ \fi}
+
+\let\pofcolumns\mofcolumns
+\let\qofcolumns\mofcolumns
+
+\newif\ifquitincurrentcolumn
+
+\def\OTRSETstoreincolumnslotLRTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotLRBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBLR#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBRL#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTLR#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTRL#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXTB#1% fixed column
+ {\OTRSETcheckprefered
+ \page_set_cell_doifelse\pofcolumns\plusone
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns +\currenthcell
+ \floatrow\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXBT#1% fixed column
+ {\OTRSETcheckprefered
+ \page_set_cell_doifelse\pofcolumns\columnmaxcells
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns+\currenthcell
+ \columnmaxcells\floatrow -\currentvcell{#1}}
+
+\newconstant\OTRSETforcefixedfloats
+
+\def\OTRSETstoreincolumnslotHERE#1% fixed column
+ {\ifcase\OTRSETforcefixedfloats
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ \OTRSETstoreincolumnslotFIXD{#1}%
+ \fi}
+
+% this one looses too wide graphics
+%
+% \def\OTRSETstoreincolumnslotFIXD#1% fixed column
+% {\OTRSETprepareforcolumnslot2{#1}%
+% % no flush text sofar here, beware: no width test
+% \snaptogrid\vbox{\box#1}}
+%
+% still imperfect
+
+\def\OTRSETstoreincolumnslotFIXD#1% fixed column
+ {\OTRSETflushtextsofar
+ \ifdim\wd#1>\textwidth
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ % crappy test / needed for o-pbu-f / will be replaced
+ \getnoflines{\ht#1}%
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen\lineheight
+ \advance\scratchdimen\pagetotal\relax
+ \ifdim\scratchdimen<\pagegoal
+ %OTRSETprepareforcolumnslot3{#1}%
+ %ruledvskip\columnslotspacing\lineheight
+ \blank[\number\columnslotspacing*\v!line]%
+ \snaptogrid\hbox to \hsize{\hss\box#1\hss}% strange, why the centering
+ \blank[\number\columnslotspacing*\v!line]%
+ \else
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotSOMEWHERE#1#2%
+ {\OTRSETprepareforcolumnslot{#1}{#2}%
+ \OTRSETflushtextsofar
+ \getnoflines\pagetotal \advance\noflines\columnfirstcell
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\mofcolumns+\currenthcell
+ \noflines\columnmaxcells+\currentvcell{#2}%
+ \page_set_command_set_vsize}
+
+\def\OTRSETcheckprefered
+ {\ifx\floatcolumn\empty
+ \let\pofcolumns\nofcolumns
+ \else\ifnum\floatcolumn<\mofcolumns
+ \let\pofcolumns\mofcolumns
+ \else
+ \let\pofcolumns\floatcolumn
+ \fi\fi
+ \ifx\floatrow\empty
+ \let\pofcolumns\plusone
+ \fi
+ \ifquitincurrentcolumn
+ \ifnum\mofcolumns=\nofcolumns
+ \def\qofcolumns{\mofcolumns}%
+ \else
+ \scratchcounter\mofcolumns
+ \advance\scratchcounter \plusone
+ \edef\qofcolumns{\the\scratchcounter}%
+ \fi
+ \else
+ \let\qofcolumns\mofcolumns
+ \fi}
+
+\def\OTRSETstoreincolumnslotindeed#1#2#3#4#5#6#7#8#9%
+ {\OTRSETcheckprefered
+ \enoughcolumncellsfalse
+ \donefalse
+ \dostepwiserecurse{#1}{#2}{#3#4}
+ {\ifdone
+ \exitloop
+ \else
+ #4=\recurselevel
+ \dostepwiserecurse{#5}{#6}{#7#8}
+ {\ifdone
+ \exitloop
+ \else
+ #8=\recurselevel
+ \OTRSETcheckcolumnspace\currenthcell\currentvcell{#9}%
+ \ifenoughcolumncells \donetrue \fi
+ \fi}%
+ \fi}%
+ \ifdone
+ \enoughcolumncellstrue
+ \else
+ \enoughcolumncellsfalse
+ \fi
+ \ifenoughcolumncells
+% \ifnum\columnspacetopoffset>0\message{[+++]}\fi
+% \ifnum\columnspacebotoffset>0\message{[---]}\fi
+% \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+% {\vbox
+% {\ifcase\columnspacetopoffset\else\ruledvskip\columnspacetopoffset\lineheight\fi
+% \copy#9
+% \ifcase\columnspacebotoffset\else\ruledvskip\columnspacebotoffset\lineheight\fi}}%
+ \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ {\copy#9}%
+ \ifnum\currenthcell=\mofcolumns\relax
+ \ifdim\ht\OTRSETsavedfootnotes>\zeropoint
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \getnoflines{\ht\OTRSETsavedfootnotes}\relax
+ \ifnum\columnfreecells<\noflines
+ \global\somefreecolumncellsfalse
+ \else
+ %\message{[flt]}% float
+ \fi
+ \fi
+ \ifsomefreecolumncells
+ % ok, enough room for notes
+ %\message{[flt]}% float
+ \else % ?
+ \OTRSETsavebox{#9}%
+ \OTRSETerasegridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ %\message{[clr]}% save box
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \page_set_command_set_vsize
+ %\message{[fnt]}% float
+ \else
+ %\message{[rej]}% save box
+ \OTRSETsavebox{#9}%
+ \fi}
+
+\setnewconstant\columnslotspacing\plusone
+
+\def\OTRSETstoreincolumnslot#1% #2 % {method} {box} % alleen last
+ {% no messing around here
+ % \dp#2=\zeropoint
+ % \ifcase\columnslotspacing\else
+ % \setbox#2=\vbox spread \columnslotspacing\lineheight
+ % {\vss\box#2\vss}%
+ % \fi
+ % and don't change this any more
+% \doifdefinedelse{\csstring\OTRSETstoreincolumnslot#1}
+% {\getvalue{\csstring\OTRSETstoreincolumnslot#1}{#2}}
+% {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
+ \executeifdefined{\csstring\OTRSETstoreincolumnslot#1}
+ \OTRSETstoreincolumnslotUNKNOWN} % {#2}}
+
+\def\OTRSETstoreincolumnslotUNKNOWN#1%
+ {\OTRSETprepareforcolumnslot2{#1}\copy#1} % {} ?
+
+\def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
+ {\dp#2\zeropoint
+ \ifcase\columnslotspacing\else
+ \scratchdimen\columnslotspacing\lineheight
+ \ifnum#1=2 \scratchdimen2\scratchdimen \fi
+ \begingroup
+ \advance\scratchdimen\ht#2\relax
+ \ifdim\scratchdimen<\columnmaxcells\lineheight
+ \endgroup \setbox#2\vbox spread \scratchdimen \bgroup
+ \else
+ \endgroup \setbox#2\vbox to \columnmaxcells\lineheight \bgroup
+ \vskip\strutdepth
+ \fi
+ \ifnum#1>1\vss\fi
+ \box#2\relax
+ \ifnum#1<3\vss\fi
+ \egroup
+ \fi}
+
+\unexpanded\def\page_set_command_check_if_float_fits
+ {\global\ifconditional\c_page_floats_not_permitted\setfalse\c_page_floats_room\else\settrue\c_page_floats_room\fi}
+
+\def\OTRSETunpreparebox#1%
+ {\ifhbox#1% spans and so
+ \global\setbox\floatbox\vbox{\box#1}%
+ \else
+ \setbox\scratchbox\vbox
+ {\unvbox#1\unskip\unskip\unskip
+ \global\setbox\floatbox\lastbox}%
+ \fi}
+
+% for the moment resave is still needed here
+
+\def\OTRSETsavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \page_floats_save\s!text}
+
+\def\OTRSETresavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \page_floats_resave\s!text}
+
+\unexpanded\def\page_set_command_flush_float_box
+ {\box\floatbox}
+
+\unexpanded\def\page_set_command_flush_floats
+ {\bgroup
+ \def\OTRSETsavebox##1{\!!doneafalse}%
+ \doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \OTRSETskipstart
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\zeropoint
+ \!!doneatrue
+ \page_floats_flush\s!text\plusone
+%
+% a quick hack ... will be redone
+%
+\ifdim\wd\floatbox<\floatwidth \ifhbox\floatbox
+ \global\setbox\floatbox\hbox{\unhbox\floatbox}%
+\fi \fi
+%
+ \dp\floatbox\zeropoint
+ \OTRSETstoreincolumnslot{TBLR}\floatbox
+ \if!!donea
+ %\message{[flu]}%
+ \else
+ \OTRSETresavebox\floatbox
+ \exitloop
+ \fi
+ \else
+ %\message{[err]}% happens but why?
+ \fi
+ \else
+ \exitloop
+ \fi}
+ \egroup}
+
+\newif\ifcentergridcells \centergridcellstrue
+\newif\ifcentergridcellonly \centergridcellonlyfalse
+\newif\ifautocentergridcellonly \autocentergridcellonlytrue
+
+\def\OTRSETcentergridcells
+ {\ifcentergridcells
+ \dorecurse\nofcolumns
+ {\currenthcell\recurselevel
+ \ifautocentergridcellonly
+ % we prevent centering when the next column is empty
+ % to be checked ! ! ! !
+ \advance\currenthcell \plusone
+ \centergridcellonlytrue
+ \ifnum\currenthcell>\nofcolumns
+ % ok already
+ \else
+ % only span if there is a next column with content
+ \dorecurse\columnmaxcells
+ {\ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \else\ifdim\dp\page_set_cell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \fi\fi}%
+ \fi
+ \fi
+ \currenthcell\recurselevel
+ \dorecurse\columnmaxcells
+ {\currentvcell\recurselevel\relax
+ \ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
+ \ifdim\dp\page_set_cell\currenthcell\currentvcell=\zeropoint
+ \bgroup
+ \setbox\scratchbox\page_set_cell_get\currenthcell\currentvcell
+ \getnoflines{\ht\scratchbox}%
+ \!!counta\currentvcell
+ \advance\!!counta -\noflines
+ \advance\!!counta \plusone
+ % first col always ok
+ \!!countb\currenthcell
+ \!!countc\currenthcell
+ \advance\!!countc \plusone
+ \!!donebtrue
+ \ifcentergridcellonly
+ \!!countc\maxdimen
+ \fi
+ \dostepwiserecurse\!!countc\nofcolumns\plusone
+ {\if!!doneb
+ \let\xrecurselevel\recurselevel
+ \dostepwiserecurse\!!counta\currentvcell\plusone
+ {\ifdim\ht\page_set_cell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \else\ifdim\wd\page_set_cell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \fi\fi}%
+ \if!!doneb
+ \!!countb\xrecurselevel
+ \fi
+ \fi}%
+ \totalcolumnspace\OTRSETlocalwidth\currenthcell
+ \dostepwiserecurse\!!countc\!!countb\plusone
+ {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
+ \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
+ \ifdim\totalcolumnspace>\wd\scratchbox
+ \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
+ \fi
+ \page_set_cell_set\currenthcell\currentvcell\box\scratchbox
+ \egroup
+ \fi
+ \fi}}%
+ \fi}
+
+\def\OTRSETinitializecolumns% once per page
+ {\columnspreadtrue % todo
+ \ifcolumnspread
+ \global\rofcolumns\columnsetparameter\c!nright
+ \global\lofcolumns\columnsetparameter\c!nleft
+ \global\tofcolumns\rofcolumns \relax
+ \ifodd\realpageno\relax
+ \global\nofcolumns\rofcolumns
+ \else
+ \global\advance\tofcolumns\lofcolumns
+ \global\nofcolumns\lofcolumns
+ \fi
+ \else
+ \global\nofcolumns\columnsetparameter\c!n
+ \global\rofcolumns\nofcolumns
+ \global\lofcolumns\nofcolumns
+ \global\tofcolumns\nofcolumns
+ \fi
+ \OTRSETassignwidths
+ \global\mofcolumns\plusone
+ \page_set_cell_erase_grid}
+
+% this is a first step in upgrading
+
+\installcorenamespace{columnset}
+
+\installframedcommandhandler \??columnset {columnset} \??columnset
+
+\setupcolumnset % todo, use the rather basic backgroundframed
+ [\c!direction=\v!right,
+ \c!balance=\v!no,
+ \c!distance=1.5\bodyfontsize,
+ \c!n=2,
+ \c!nleft=\columnsetparameter\c!n,
+ \c!nright=\columnsetparameter\c!n,
+ \c!width=\v!fit,
+ \c!lines=0,
+ \c!start=0,
+ \c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!align=]
+
+\let\page_set_setup_saved\setupcolumnset
+
+\newconditional\c_page_set_defining
+
+\appendtoks
+ \ifconditional\c_page_set_defining \else
+ \settrue\c_page_set_defining
+ \dorecurse{\columnsetparameter\c!nleft}
+ {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
+ \dorecurse{\columnsetparameter\c!nright}
+ {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
+ \normalexpanded{\page_set_setup_saved[\currentcolumnset:1][\c!distance=\zeropoint]}%
+ \setfalse\c_page_set_defining
+ \fi
+\to \everydefinecolumnset
+
+\unexpanded\def\setupcolumnset
+ {\dotripleargument\page_set_setup}
+
+\def\page_set_setup[#1][#2][#3]%
+ {\ifthirdargument
+ \unexpanded\def\page_set_setup_step##1%
+ {\doifelse{##1}\v!each
+ {\dorecurse{\namedcolumnsetparameter{#1}\c!n}{\page_set_setup_step\recurselevel}}
+ {\normalexpanded{\page_set_setup_saved[#1:##1]}[#3]}}%
+ \processcommalist[#2]\page_set_setup_step
+ \else
+ \page_set_setup_saved[#1][#2]%
+ \fi}
+
+\definecolumnset
+ [\s!default]
+
+\unexpanded\def\page_set_command_next_page
+ {\page_otr_fill_and_eject_page
+ \relax\ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!last]%
+ \ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!force]%
+ \fi
+ \fi}
+
+\let\page_set_command_next_page_and_inserts\page_set_command_next_page
+
+\def\OTRSETgotocolumn
+ {\dosingleempty\doOTRSETgotocolumn}
+
+\def\doOTRSETgotoCOLROW#1% <number>|<number>*<number>
+ {\bgroup % really needed
+ \splitstring#1\at*\to\column\and\row
+ \bgroup
+ \ifx\column\empty\else\expanded{\doOTRSETgotoCOLUMN{\column}}\fi
+ \egroup
+ \bgroup
+ \ifx\row \empty\else\expanded{\doOTRSETgotoROW {\row }}\fi
+ \egroup
+ \egroup}
+
+\def\doOTRSETgotoCOLUMN#1%
+ {\ifnum\mofcolumns=#1\else
+ \page_otr_fill_and_eject_page
+ \doloop
+ {\ifnum\mofcolumns=#1\relax
+ \exitloop \else \OTRSETdummycolumn
+ \fi}%
+ \fi}
+
+\def\doOTRSETgotoROW#1%
+ {\ifnum#1>1
+ \scratchcounter\zerocount
+ \currenthcell\mofcolumns
+ \currentvcell#1\advance\currentvcell \minusone
+ \dorecurse\currentvcell
+ {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
+ {\advance\scratchcounter\plusone}}
+ \getnoflines\pagetotal
+ \advance\scratchcounter-\noflines
+ \ifnum\scratchcounter>\zerocount
+ \dorecurse\scratchcounter{\line{\strut}}%
+ \fi
+ \fi
+ \page_set_command_set_vsize}
+
+\def\doOTRSETgotocolumn[#1]% yes|force|first|last|<number>|<number>*<number>
+ {\processallactionsinset
+ [#1]
+ [ \v!yes=>\OTRSETdummycolumn,
+ \v!no=>,% not supported
+ \v!force=>\OTRSETdummycolumn,
+ \v!first=>\expanded{\doOTRSETgotoCOLUMN{1}},
+ \v!last=>\expanded{\doOTRSETgotoCOLUMN{\the\nofcolumns}},
+ \s!default=>\OTRSETdummycolumn,
+ \s!unknown=>\expanded{\doOTRSETgotoCOLROW{\commalistelement}}]}
+
+% to be documented and tested, not yet that robust
+
+% \def\OTRSETgotocell#1#2%
+% {\endgraf
+% \gdef\gotocellcounter{0}%
+% \doloop
+% {\ifnum\mofcolumns<#1\relax
+% \doglobal\increment\gotocellcounter\relax
+% \ifnum\gotocellcounter>#1\relax
+% \line{\strut}\crlf
+% \line{\strut}\crlf
+% \column
+% \writestatus{columnset}{quitting goto cell}%
+% \exitloop
+% \else
+% \column
+% \fi
+% \else
+% \exitloop
+% \fi}%
+% \ifnum\mofcolumns=#1\relax
+% \ifnum#2>1
+% \scratchcounter\zerocount
+% \currenthcell\mofcolumns
+% \currentvcell#2\advance\currentvcell \minusone
+% \dorecurse\currentvcell
+% {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
+% {\advance\scratchcounter\plusone}}
+% \getnoflines\pagetotal
+% \advance\scratchcounter-\noflines
+% \ifnum\scratchcounter>\zerocount
+% \dorecurse\scratchcounter{\line{\strut}}%
+% \fi
+% \fi
+% \fi
+% \page_set_command_set_vsize}
+
+\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
+ {\endgraf
+ \doOTRSETgotoCOLUMN{#1}%
+ \doOTRSETgotoROW {#2}}
+
+\def\OTRSETdummycolumn
+ {\verticalstrut
+ \vskip-\struttotal
+ \page_otr_fill_and_eject_page}
+
+\newcounter\columnsetlevel
+\let\currentcolumnset\empty
+
+\newconditional\OTRSETfinish % never checked
+
+\unexpanded\def\startcolumnset
+ {\dodoubleempty\dostartcolumnset}
+
+\def\dostartcolumnset[#1][#2]%
+ {\increment\columnsetlevel\relax
+ \global\let\localcolumnmaxcells\!!zerocount
+ \global\setfalse\OTRSETfinish
+ \ifnum\columnsetlevel=\plusone
+ \bgroup
+ \saveinterlinespace
+ \globallet\columnsetpage\!!plusone
+ \def\currentcolumnset{#2}%
+ \insidecolumnstrue % will be different flag in addition
+ \setupoutputroutine[\s!columnset]%
+ \doifelsenothing{#1}
+ {\globallet\OTRSETlist\s!default}
+ {\xdef\OTRSETlist{#1}}%
+ \OTRSETstartnextpage
+ \OTRSETassignwidths
+ \page_set_command_set_hsize
+ \else
+ \bgroup
+ \fi
+ \begingroup} % extra grouping needed ... else weird issue with ungrouped font switch (e.g. \ss)
+
+% \setuplayout[grid=yes] \definecolumnset[example] \showgrid
+
+% \starttext
+% \startcolumnset[example]
+% \input knuth \endgraf \input knuth
+% \placetable{table}{\framed[width=\makeupwidth,height=4cm]{Hello}}
+% \input knuth \endgraf \input knuth
+% \stopcolumnset
+% \input knuth \endgraf \input knuth
+% \stoptext
+
+\def\OTRSETflushleftovers % new per 13/4/2006
+ {\page_set_cell_doifelse\plusone\plusone
+ {\bgroup
+ \OTRSETcentergridcells
+ \OTRSETbalancemethod\plusone
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \ht\OTRfinalpagebox\textheight % signals output that there is content
+ \OTRSETdofinaloutput
+ \globallet\OTRSETbalht\zeropoint
+ \egroup}
+ {}}
+
+\unexpanded\def\stopcolumnset
+ {\endgraf
+ \endgroup % ends extra grouping
+ \ifnum\columnsetlevel=\plusone
+ \endgraf % needed, else wrong vsize in one par case
+ \global\settrue\OTRSETfinish
+ % no, extra page \pagebreak % (test on pascal toc)
+ \dostopcolumnset
+ \egroup
+ \global\notelimittrue % brrr, untested and fuzzy
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \ifvoid\OTRfinalpagebox\else
+ % probably balanced
+ \ifdim\ht\OTRfinalpagebox<\textheight
+ \snaptogrid[\v!page]\hbox{\box\OTRfinalpagebox}%
+ \else
+ \box\OTRfinalpagebox
+ \fi
+ \fi
+ \global\setfalse\OTRSETfinish
+ \ifconditional\c_page_floats_some_waiting
+ \page_otr_command_set_vsize
+ \pagebreak
+ \page_otr_command_set_vsize
+ \fi
+ \OTRSETflushleftovers
+ \else
+ \egroup
+ \fi
+ \decrement\columnsetlevel\relax}
+
+\newconstant\OTRSETbalancemethod
+
+\def\dostopcolumnset
+ {%\OTRSETdofinalflushfloats % yes/no
+ \ifcase\OTRSETbalancemethod
+ \OTRSETnobalance
+ \else
+ \OTRSETdobalance
+ \fi}
+
+\def\OTRSETdobalance
+ {\OTRSETnobalance}
+
+\def\localcolumnmaxcells{0}
+
+% currently line represents real line, i.e. on the grid, and
+% not something noflines (also, watch out for switching from
+% 2-3 columns on one page with both sets balanced: the
+% second set does not see the first set
+
+% don't loose empty 1page/1column with area (example **)
+%
+% \definecolumntextarea[title][x=1,y=4,nx=2,ny=7,state=start]
+% \setupcolumntextareatext[title][\vtop to 5cm{a\\b\\b\\d}]
+%
+% \starttext
+% \startcolumnset \dorecurse{1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+% better:
+
+\unexpanded\def\definecolumnsetarea {\definecolumntextarea}
+\unexpanded\def\setupcolumnsetarea {\setupcolumntextarea}
+\unexpanded\def\setupcolumnsetareatext{\setupcolumntextareatext}
+
+% so this will be changed
+
+\def\OTRSETnobalance
+ {\iflastcolumnfootnotes % testen ! optie
+ % inhibit flush of floats !
+ % todo: nothing if no footnotes, else empty page
+ \dostepwiserecurse\mofcolumns\nofcolumns\plusone
+ {\vskip-\struttotal\verticalstrut\page_otr_fill_and_eject_page}%
+ \else
+ \ifnum\mofcolumns>\plusone
+ \donetrue
+ \else\ifdim\pagetotal>\zeropoint % too dangerous, we loose data
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdone
+ \ifnum\mofcolumns=\nofcolumns
+ \OTRSETflushfinalfootnotes
+ \else
+ % probably todo
+ \fi
+ \page_otr_fill_and_eject_page
+ % brr, may result in empty page after nicely fit text
+ % or if left, then lost of first column only text
+ \ifnum\mofcolumns>\plusone
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \fi
+ \fi
+ \fi}
+
+\def\OTRSETstartnextpage
+ {\doifsomething\OTRSETlist
+ {\getfromcommacommand[\OTRSETlist][1]%
+ \global\let\OTRSETidentifier\commalistelement
+ \xdef\currentcolumnset{\commalistelement}%
+ \checkcolumnsetparent
+ \let\newcommalistelement\empty
+ \doglobal\replaceincommalist\OTRSETlist1%
+ \OTRSETrestart}}
+
+\def\OTRSETrestart % weed
+ {\OTRSETinitializefeatures
+ \OTRSETflushpreposttext
+ \OTRSETinitializecolumns
+ \OTRSETcheckinsert
+ \OTRSETcheckgrid
+ \page_set_command_set_vsize
+ \page_set_command_set_hsize % or local ?
+ \OTRSETsetplaceholders
+ \OTRSEThandlepreposttext
+ \initializecolumntextareas % name !
+ \OTRSETcheckstartcells
+ \page_set_command_set_vsize}
+
+\def\OTRSETcheckstartcells
+ {\dorecurse\nofcolumns
+ {\bgroup
+ \mofcolumns\recurselevel
+\OTRSETsetcorrectnofcells\currentcolumnstartcell
+\advance\scratchcounter \minusone
+ \dorecurse\scratchcounter
+ {\page_set_cell_doifelse\mofcolumns\recurselevel
+ \donothing{\page_set_cell_set\mofcolumns\recurselevel\copy\placeholderboxe}}%
+ \egroup}}
+
+\unexpanded\def\page_set_command_routine
+ {\dontcomplain % new, get rid of overfull message (to be sorted out)
+ \doloop
+ {\OTRSETnaturalflush
+ %\OTRSETstartnextpage % no
+ \page_set_command_flush_floats
+ \OTRSETcheckfreelines
+ \ifsomefreecolumncells
+ \exitloop
+ \else
+ % flush page and get rid of more floats if present
+ \fi}%
+ \OTRSETchecksidefloat}
+
+\def\OTRSETsetcolumnmaxcells
+ {\getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}}
+
+\def\OTRSETinitializefeatures
+ {% number of lines
+ % new: raw
+ \OTRSETsetcolumnmaxcells
+ % direction
+ \doifelse{\columnsetparameter\c!direction}\v!right
+ {\columndirection\zerocount}
+ {\columndirection\plusone}%
+ % balancing
+ \OTRSETbalancemethod\zerocount
+ \processaction
+ [\columnsetparameter\c!balance]
+ [ \v!yes=>\OTRSETbalancemethod\plusone,
+ \v!top=>\OTRSETbalancemethod\plustwo,
+ \v!bottom=>\OTRSETbalancemethod\plusthree]}
+
+% test:
+%
+% \definecolumnset[test-1] %[balance=yes]
+% \definecolumnset[test-2] %[balance=yes]
+%
+% \setupcolumnsetlines[test-1][1][1] [4]
+% \setupcolumnsetlines[test-1][1][2][10]
+%
+% \startcolumnset [test-1] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \startcolumnset [test-2] \dorecurse {2}{\input ward \par} \stopcolumnset
+
+\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
+
+\installoutputroutine\OTRSETflushpreposttext
+ {\global\setbox\b_page_set_preceding\vbox
+ {\unvbox\normalpagebox
+ \global\lastskipinotr\lastskip}%
+ \ifdim\lastskipinotr>\zeropoint
+ \global\setbox\b_page_set_preceding\hbox
+ {\lower\strutdepth\box\b_page_set_preceding}%
+ \fi
+ \dp\b_page_set_preceding\strutdepth
+ \ifcarryoverfootnotes \else
+ \global\setbox\b_page_set_trailing\vbox{\placebottomnotes}%
+ \fi}
+
+\let\precolumnlines \!!zerocount
+\let\postcolumnlines\!!zerocount
+
+\def\OTRSEThandlepreposttext
+ {\ifdim\ht\b_page_set_preceding>\zeropoint % new
+ \getnoflines{\ht\b_page_set_preceding}%
+ \edef\precolumnlines{\the\noflines}%
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\noflines
+ % normal version (single column set)
+ % {\box\b_page_set_preceding}%
+ % compensated for bodyfont change
+ {\hbox
+ {\OTRSETsetcorrectcellht
+ \raise\scratchdimen\box\b_page_set_preceding}}%
+ \else
+ \let\precolumnlines\!!zerocount
+ \fi
+ \ifdim\ht\b_page_set_trailing>\zeropoint % new, otherwise empty bottom line
+ \getnoflines{\ht\b_page_set_trailing}%
+ \edef\postcolumnlines{\the\noflines}%
+ \advance\columnfreecells -\noflines
+ \advance\columnfreecells \plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\columnfreecells\nofcolumns\noflines
+ {\box\b_page_set_trailing}%
+ \else
+ \let\postcolumnlines\!!zerocount
+ \fi}
+
+\def\OTRSETchecksidefloat
+ {} % {\sidefloatoutput}
+
+\unexpanded\def\page_set_command_side_float_output
+ {} % nothing, reset anyway
+
+\def\OTRSETcheckgrid
+ {\topskip1\topskip
+ \ifforcecolumnsetgrid
+ \widowpenalty\zerocount
+ \clubpenalty\zerocount
+ \brokenpenalty\zerocount
+ \fi}
+
+\def\OTRSETcheckinsert
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \OTRSETforceinserts
+ \else
+ \OTRSETinhibitinserts
+ \fi
+ \else
+ \OTRSETforceinserts
+ \fi}
+
+\def\OTRSETforceinserts
+ {\enablenotes}
+
+\def\OTRSETinhibitinserts
+ {\disablenotes}
+
+% undocumented goodie
+
+\def\definecolumnsethsize#1#2#3#4% will be improved/speed up
+ {\bgroup
+ \def\OTRSETidentifier{#1}%
+ \ifcase\columnsetlevel\relax
+ \mofcolumns\plusone
+ \OTRSETinitializecolumns
+ \OTRSETassignwidths % already done
+ \page_set_command_set_hsize
+ \fi
+ \!!counta#2\!!countb#3\docalculatecolumnsetspan
+ \expandafter\egroup\expandafter\edef\expandafter#4\expandafter{\the\!!widtha}}
+
+% interface to footnotes
+
+\installcorenamespace{columnsetwidth}
+
+\def\OTRSETassignwidths
+ {%\scratchdimen\makeupwidth
+ \freezetextwidth \scratchdimen\textwidth
+ %
+ \scratchcounter\zerocount
+ \dorecurse\nofcolumns
+ {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
+ {\advance\scratchcounter \plusone}
+ {\advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
+ \advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
+ \ifcase\scratchcounter\else
+ \divide\scratchdimen \scratchcounter
+ \fi
+ \global\setfalse\c_page_set_width_set
+ \dorecurse\nofcolumns
+ {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
+ {\dimen0=\scratchdimen}
+ {\global\settrue\c_page_set_width_set
+ \dimen0=\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
+ \setxvalue{\??columnsetwidth\recurselevel}{\the\dimen0}}}
+
+\def\OTRSETlocalwidth#1%
+ {\getvalue{\??columnsetwidth\number#1}}
+
+\newbox\placeholderboxa
+\newbox\placeholderboxb
+\newbox\placeholderboxc
+\newbox\placeholderboxd
+\newbox\placeholderboxe
+\newbox\placeholderboxf
+
+\def\columnplaceholder#1#2%
+ {\hbox
+ {\setbox\scratchbox\hbox to \hsize
+ {\iftracecolumnset
+ \hskip-.5ex%
+ \startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor
+ \fi
+ \hss}%
+ \ifcase#1\relax
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\zeropoint
+ \else
+ \wd\scratchbox\hsize
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \fi
+ \box\scratchbox}}
+
+\definepalet
+ [columnset]
+ [a=cyan,b=green,c=blue,d=red,e=magenta,f=darkgray]
+
+\def\OTRSETsetplaceholders
+ {\global\setbox\placeholderboxa\columnplaceholder0a%
+ \global\setbox\placeholderboxb\columnplaceholder0b%
+ \global\setbox\placeholderboxc\columnplaceholder0c%
+ \global\setbox\placeholderboxd\columnplaceholder0d%
+ \global\setbox\placeholderboxe\columnplaceholder0e%
+ \global\setbox\placeholderboxf\columnplaceholder1f}
+
+\def\doOTRSETshowstatus
+ {\llap{\tt\tfxx
+ \startcolor[blue](\the\vsize->\number\columnfirstcell\#\number\columnfreecells)\stopcolor
+ \hskip\leftskip}}
+
+\installtextracer{OTRSET} % low level
+
+\def\enabletextracerOTRSET {\tracecolumnsettrue \let\OTRSETshowstatus\doOTRSETshowstatus}
+\def\disabletextracerOTRSET{\tracecolumnsetfalse\let\OTRSETshowstatus\relax}
+
+\disabletextracerOTRSET
+
+% \appendtoks \OTRSETshowstatus \to \everypar
+
+% page contents
+
+% \def\OTRSETdopagecontents#1#2% takes two args: \box<n> \unvbox<n>
+\unexpanded\def\page_set_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
+ {\vbox to \textheight{\forgetall#1#2}}
+
+\def\page_set_place_float_page {\def\floatmethod{PAGE}\page_set_place_float_slot} % check
+\def\page_set_place_float_here {\def\floatmethod{HERE}\page_set_place_float_slot} % check
+\def\page_set_place_float_else {\def\floatmethod{HERE}\page_set_place_float_slot} % check / not used
+\def\page_set_place_float_force {\def\floatmethod{FIXD}\page_set_place_float_slot} % check
+\def\page_set_place_float_top {\def\floatmethod{TOPS}\page_set_place_float_slot} % check
+\def\page_set_place_float_bottom{\def\floatmethod{BOTS}\page_set_place_float_slot} % check
+
+\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\box\floatbox}
+
+\def\page_set_place_float_slot
+ {\setbox\floatbox\vbox{\page_otr_command_flush_float_box}%
+ \dp\floatbox\strutdp
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ \OTRSETstoreincolumnslot\floatmethod\floatbox
+ \page_floats_report_total}
+
+% kind of new, looks much like OTRONE, but not entirely
+
+\newconditional\c_page_set_top_of_insert
+
+\unexpanded\def\page_set_command_set_top_insertions
+ {\bgroup
+ \ifconditional\c_page_floats_some_waiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \OTRSETdodosettopinserts
+ \ifnum\rootfloatparameter\c!nbottom=\zerocount
+ \ifnum\rootfloatparameter\c!nlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \scratchdimen\dimexpr\rootfloatparameter\c!nlines\lineheight+\totaltopinserted\relax
+ \ifdim\scratchdimen>\textheight % \vsize %%%%%%%%% \textheight
+ \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
+ \page_otr_fill_and_eject_page % was triple: vfilll
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETdodosettopinserts
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_top
+ \page_floats_get
+ \ifdim\d_page_floats_inserted_top=\zeropoint\relax
+ \settrue\c_page_set_top_of_insert
+ \else
+ \setfalse\c_page_set_top_of_insert
+ \fi
+ \setbox\scratchbox\vbox % kan beter !
+ {\forgetall
+ \ifconditional\c_page_set_top_of_insert
+ %\ifdim\OTRSETtopoffset=\zeropoint
+ % \moveongrid[\v!top]
+ %\fi
+ \else
+ \betweenfloatblanko % inserts can't look back
+ \fi
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \global\advance\d_page_floats_inserted_top \ht\scratchbox\relax
+ \ifdim\d_page_floats_inserted_top>\vsize % was \textheight\relax
+ \OTRSETresavebox\scratchbox
+ \noffloatinserts\c_page_floats_n_of_top\relax
+ \global\advance\d_page_floats_inserted_top -\ht\scratchbox
+ \let\OTRSETdodosettopinserts\relax % to be tested
+ \else
+ \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
+ \insert\namedinsertionnumber\s!topfloat\bgroup
+ \forgetall
+ \box\scratchbox
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\c_page_floats_n_of_top\relax
+ \fi
+ \page_floats_report_flushed
+ \fi
+ \else
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
+ \fi
+ \let\OTRSETdodosettopinserts\relax
+ \fi
+ \OTRSETdodosettopinserts}
+
+\unexpanded\def\page_set_command_set_bottom_insertions
+ {\bgroup
+ \ifconditional\c_page_floats_some_waiting
+ \noffloatinserts\zerocount
+ \OTRSETdodosetbotinserts
+ \fi
+ \egroup}
+
+\def\OTRSETdodosetbotinserts
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax
+ \page_floats_get
+ \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\c_page_floats_n_of_bottom
+ \fi
+ \page_floats_report_flushed
+ \else
+ \OTRSETresavebox\floatbox
+ \noffloatinserts\c_page_floats_n_of_bottom\relax
+ \fi
+ \global\settrue\c_page_floats_not_permitted % vgl topfloats s!
+ \else
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}%
+ \fi
+ \let\OTRSETdodosetbotinserts\relax
+ \fi
+ \OTRSETdodosetbotinserts}
+
+\unexpanded\def\page_set_command_flush_top_insertions
+ {\ifvoid\namedinsertionnumber\s!topfloat\else
+ \ifvoid\columntopbox\mofcolumns
+ \columnsettopbox\mofcolumns\box\namedinsertionnumber\s!topfloat
+ \else
+ \columnsettopbox\mofcolumns\vbox % temp, must be better
+ {\forgetall
+ \offinterlineskip
+ \box\columntopbox\mofcolumns
+ \box\namedinsertionnumber\s!topfloat}
+ \fi
+ \fi
+ \global\d_page_floats_inserted_top\zeropoint\relax} % goes away
+
+\unexpanded\def\page_set_command_flush_bottom_insertions
+ {\ifvoid\namedinsertionnumber\s!bottomfloat \else
+ \columnsetbotbox\mofcolumns\box\namedinsertionnumber\s!bottomfloat
+% \else
+% \columnsetbotbox\mofcolumns\vbox % temp, must be better
+% {\forgetall
+% \offinterlineskip
+% \box\namedinsertionnumber\s!bottomfloat
+% \box\columnbotbox\mofcolumns}
+ \fi
+ \global\d_page_floats_inserted_bottom\zeropoint\relax} % goes away
+
+% set ipv text
+
+% left right 1 2 3 +1 +2 +3
+
+\let\columnleftareas \empty
+\let\columnrightareas\empty
+
+% links rechts => odd, even, n, named
+
+\installcorenamespace{columnsetarea}
+
+\unexpanded\def\definecolumntextarea
+ {\dotripleempty\dodefinecolumntextarea}
+
+\def\dodefinecolumntextarea[#1][#2][#3]% y=0 is mogelijke en handig !
+ {\ifthirdargument
+ \doifelseinset{#2}{\v!both,\v!fixed}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]%
+ \definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\doifelse{#2}\v!next
+ {\doifelseoddpage
+ {\definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]}}
+ {\presetlocalframed
+ [\??columnsetarea#1#2]%
+ \processaction[#2] % \doglobal voorkomt stack build up
+ [ \v!left=>\doglobal\addtocommalist{#1}\columnleftareas,
+ \v!right=>\doglobal\addtocommalist{#1}\columnrightareas]%
+ \getparameters[\??columnsetarea#1#2]
+ [\c!x=1,\c!y=1,\c!nx=1,\c!ny=1,\c!clipoffset=2\lineheight,
+ \c!leftoffset=\zeropoint,\c!rightoffset=\zeropoint,
+ \c!offset=\v!overlay,\c!strut=\v!no,\c!frame=\v!off,
+ \c!type=#2,\c!page=1,\c!state=\v!stop,#3]}}%
+ \else
+ \definecolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\unexpanded\def\setupcolumntextarea
+ {\dotripleempty\dosetupcolumntextarea}
+
+\def\dosetupcolumntextarea[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setupcolumntextarea[#1][\v!left ][#3]%
+ \setupcolumntextarea[#1][\v!right][#3]}
+ {\doifelse{#2}\v!next
+ {\doifelseoddpage
+ {\setupcolumntextarea[#1][\v!right][#3]}
+ {\setupcolumntextarea[#1][\v!left][#3]}}
+ {\getparameters[\??columnsetarea#1#2][#3]}}%
+ \else
+ \setupcolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\def\docheckcolumnsetareapage#1#2%
+ {\ifnum\getvalue{\??columnsetarea#1\c!page}>\plusone
+ \doifelsevalue{\??columnsetarea#1\c!type}\v!fixed
+ {\ifnum\columnsetpage=\getvalue{\??columnsetarea#1\c!page}\relax
+ \donetrue\else\donefalse
+ \fi}
+ {\ifnum\columnsetpage<\getvalue{\??columnsetarea#1\c!page}\relax
+ \donefalse\else\donetrue
+ \fi}%
+ \else
+ \donetrue
+ \fi}
+
+\def\initializecolumntextareas
+ {\ifodd\realpageno
+ \doinitializecolumntextareas\columnrightareas\v!right
+ \else
+ \doinitializecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doinitializecolumntextareas#1#2%
+ {\def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\plusone
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??columnsetarea##1#2\c!state}]
+ [ \v!start=>\donetrue,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone\dodoinitializecolumntextareas{##1}{#2}\fi
+ \fi}%
+ \processcommacommand[#1]\docommand}
+
+\def\dodoinitializecolumntextareas#1#2%
+ {\doOTRSETsetgridcells
+ {\copy\placeholderboxd}
+ {\getvalue{\??columnsetarea#1#2\c!x }}{\getvalue{\??columnsetarea#1#2\c!y }}
+ {\getvalue{\??columnsetarea#1#2\c!nx}}{\getvalue{\??columnsetarea#1#2\c!ny}}
+ {\copy\placeholderboxd}}
+
+\unexpanded\def\placecolumntextareas
+ {\ifodd\realpageno
+ \doplacecolumntextareas\columnrightareas\v!right
+ \else
+ \doplacecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doplacecolumntextareas#1#2% global ?
+ {\bgroup
+ \forgetall
+ \def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\zerocount
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??columnsetarea##1#2\c!state}]
+ [ \v!start=>\donetrue\doglobal\removefromcommalist{##1}#1,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone
+ \dodoplacecolumntextareas{##1}{#2}%
+ \else
+ \doglobal\removefromcommalist{##1}#1%
+ \fi
+ \fi}%
+ \processcommacommand[#1]\docommand
+ \egroup}
+
+% \page[left]
+% \definecolumntextarea[intro][left][x=1,y=1,nx=4,ny=20,state=start,background=introlayer]
+% \setupcolumntextareatext[intro][left][\setups{intro}]
+% \flushcolumntextareas
+
+\def\flushcolumntextareas
+ {\initializecolumntextareas
+ \page_otr_command_set_vsize} % set ?
+
+\def\columntextlastbackspace{\backspace}
+
+% beware, we have clipping offsets of 2\lineheight by default
+
+\def\columntextareaparameter#1%
+ {\csname\??columnsetarea\currentcolumntestarea#1\endcsname}
+
+\def\dodoplacecolumntextareas#1#2%
+ {\def\currentcolumntestarea{#1#2}%
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!nx
+ \docalculatecolumnsetspan
+ \!!heighta\columntextareaparameter\c!ny\lineheight
+ % wrong
+ % \ifnum\columntextareaparameter\c!y=\zerocount
+ % \advance\!!heighta -\lineheight
+ % \advance\!!heighta \topskip
+ % \fi
+ % \advance\!!heighta -\lineheight % option
+ \ifnum\columntextareaparameter\c!y=\plusone
+ \advance\!!heighta -\lineheight
+ \advance\!!heighta \topskip
+ \fi
+ %
+ \setbox\scratchbox\vbox
+ {\donetrue\localframed
+ [\??columnsetarea\currentcolumntestarea]
+ [\c!location=,% new (*)
+ \c!width=\!!widtha,\c!height=\!!heighta,\c!lines=]
+ {\columntextareaparameter\empty{}}}% messy
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!y
+ \advance\!!countb \columntextareaparameter\c!ny
+ \advance\!!countb \minusone
+ % new (*)
+ \doif{\columntextareaparameter\c!location}\v!depth
+ {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\zeropoint
+ \ht\scratchbox\!!heighta}%
+ %
+ \setbox0\hbox
+ {\ifcase\!!countc
+ \copy\scratchbox % \box
+ \else
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!leftoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!rightoffset=\columntextareaparameter\c!rightoffset,%
+ \c!width=\!!widthb,%
+ \c!height=\!!heighta]%
+ {\copy\scratchbox}%
+ \fi}%
+ \page_set_cell_set\!!counta\!!countb\box0
+ \ifcase\!!countc\else
+ \advance\!!counta \columntextareaparameter\c!nx
+ \advance\!!counta -\!!countc
+ \advance\!!widtha -\!!widthb
+ \setbox0\hbox
+% {\hskip-\namedlayoutparameter\v!odd\c!backspace
+ {\hskip-\layoutparameter\c!backspace
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!rightoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!leftoffset=\columntextareaparameter\c!leftoffset,%
+ \c!width=\!!widtha,%
+ \c!height=\!!heighta,%
+ \c!hoffset=\!!widthb]%
+ {\copy\scratchbox}}%
+ \page_set_cell_set\!!counta\!!countb\box0%
+ \fi}
+
+\unexpanded\def\setupcolumntextareatext
+ {\dotripleempty\dosetupcolumntextareatext}
+
+\def\dosetupcolumntextareatext[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setvalue{\??columnsetarea#1\v!left }{#3}%
+ \setvalue{\??columnsetarea#1\v!right}{#3}}
+ {\doifelse{#2}\v!next
+ {\doifelseoddpage
+ {\setvalue{\??columnsetarea#1\v!right}{#3}}%
+ {\setvalue{\??columnsetarea#1\v!left }{#3}}}%
+ {\setvalue{\??columnsetarea#1#2}{#3}}}%
+ \else
+ \setupcolumntextareatext[#1][\v!next][{#2}]%
+ \fi}
+
+\def\docalculatecolumnsetspan
+ {% \!!counta <= x
+ % \!!countb <= nx
+ % \!!widtha => total width
+ % \!!widthb => left width
+ % \!!countc => left cols
+ \!!widtha\!!countb\textwidth % we assume equal widths
+ \advance\!!countb \!!counta
+ \advance\!!countb \minusone
+ \ifnum\!!countb>\nofcolumns
+ \!!countc\!!countb
+ \advance\!!countc -\nofcolumns
+ \!!countb\nofcolumns
+ \else
+ \!!countc\zerocount
+ \fi
+ \advance\!!counta \plusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
+ \!!widthb\!!widtha
+ \advance\!!widthb -\!!countc\textwidth
+ \ifodd\realpageno \else % tricky, assumes that we keep there
+ \ifcase\!!countc\else
+ % nog niet ok voor enkel/doublesided
+% \advance\!!widtha \namedlayoutparameter\v!even\c!backspace
+% \advance\!!widtha \namedlayoutparameter\v!odd \c!backspace
+% \advance\!!widthb \namedlayoutparameter\v!even\c!backspace
+ \advance\!!widtha \layoutparameter\c!backspace
+ \advance\!!widtha \layoutparameter\c!backspace
+ \advance\!!widthb \layoutparameter\c!backspace
+ \dorecurse\!!countc
+ {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
+ \fi
+ \fi}
+
+\def\columnsetspanhsize{\textwidth}
+
+\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
+ {\!!counta#1\!!countb#2\docalculatecolumnsetspan
+ \edef\columnsetspanhsize{\the\!!widtha}}
+
+\unexpanded\def\page_set_command_set_float_hsize % this helper has to be moved to strc-flt
+ {\hsize % maybe checking optional
+ \ifdim\d_strc_float_temp_width>\makeupwidth
+ \makeupwidth
+ \else
+ \d_strc_float_temp_width
+ \fi}
+
+\installcorenamespace{columnsetspan}
+
+\unexpanded\def\definecolumnsetspan
+ {\dodoubleempty\dodefinecolumnsetspan}
+
+\def\dodefinecolumnsetspan[#1][#2]%
+ {%\ifsecondargument
+ \defineframedtext % we can have a parent
+ [\??columnsetspan#1]
+ [\c!frame=\v!off,
+ \c!before=,
+ \c!after=,
+ \c!offset=\v!overlay,
+ \c!location=\v!left,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!n=2,
+ \c!nlines=0,
+ \c!indenting=,
+ \c!indentnext=\v!yes,
+ \c!default=HERE,
+ \c!alternative=\v!a,
+ #2]%
+ %\else
+ % \definecolumnspan[][#1]%
+ }%\fi}
+
+\definecolumnsetspan[\s!default]
+
+\unexpanded\def\setupcolumnsetspan
+ {\dodoubleempty\dosetupcolumnsetspan}
+
+\def\dosetupcolumnsetspan[#1][#2]%
+ {\ifsecondargument
+ \setupframedtexts[\??columnsetspan#1][#2]%
+ \else
+ \setupcolumnsetspan[\s!default][#1]%
+ \fi}
+
+\unexpanded\def\startcolumnsetspan
+ {\dotripleempty\dostartcolumnsetspan}
+
+%%%%%%%%%%%%%%%% TODO
+
+\def\dostartcolumnsetspan[#1][#2][#3]% [#3] gobbles space
+ {\endgraf % else rubish output if forgotten
+ \vskip \zeropoint % make sure otr is done, otherwise last line problems
+ \bgroup
+ \forgetall
+ \ifnum\columnsetlevel>\zerocount\else
+ % of course we needed a one-column fall back for tm
+ \columnsetspanhsize\hsize
+ \nofcolumns\plusone
+ \mofcolumns\plusone
+ \fi
+ \setupframedtexts[\??columnsetspan#1]
+ [\c!width=\columnsetspanhsize,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ #2]%
+ % determine widths
+ \!!countc\namedframedtextparameter{\??columnsetspan#1}\c!n
+ % \!!countd\numexpr(\nofcolumns-\mofcolumns+\plusone)%
+ \!!countd\nofcolumns
+ % n <= n of columns
+ \ifnum\!!countc>\!!countd \!!countc\!!countd \fi
+ \advance\!!countd -\mofcolumns
+ \advance\!!countd \plusone
+ % n <= n of available columns (alternative a)
+ \doif{\namedframedtextparameter{\??columnsetspan#1}\c!alternative}\v!a
+ {\ifnum\!!countc>\!!countd \!!countc\!!countd \fi}%
+ % here it all starts
+ \setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
+ \hsize\columnsetspanhsize
+ \setbox\scratchbox\vbox\bgroup
+ \pack_framed_text_start{\??columnsetspan#1}[\v!none]% geen nils placement
+ % spoils spacing : \vskip-\struttotal\par\verticalstrut\par
+ \ifnum\columnsetlevel>\zerocount
+ \namedframedtextparameter{\??columnsetspan#1}\c!before
+ \fi
+ \unexpanded\def\stopcolumnsetspan{\dostopcolumnsetspan{#1}}}
+
+\def\dostopcolumnsetspan#1%
+ {\par
+ \verticalstrut
+ \kern-2\struttotal
+ \verticalstrut
+ \ifnum\columnsetlevel>\zerocount
+ \doifsomething{\namedframedtextparameter{\??columnsetspan#1}\c!after}
+ {\namedframedtextparameter{\??columnsetspan#1}\c!after
+ \kern\zeropoint}% otherwise blanks disappear, better be a switch
+ \else
+ \endgraf
+ \fi
+ \pack_framed_text_stop
+ \egroup
+ \setbox\scratchbox\frozenhbox to \hsize
+ {\dontcomplain
+ \alignedline{\namedframedtextparameter{\??columnsetspan#1}\c!location}\v!middle{\lower\strutdepth\box\scratchbox}}%
+ \dp\scratchbox\zeropoint % else wrong snap insidefloat
+%
+% to be tested first (strange in grid mode)
+%
+% \setbox\scratchbox\frozenhbox to \hsize
+% {\dontcomplain
+% \alignstrutmode\zerocount
+% \alignedline{\namedframedtextparameter{\??columnsetspan#1}\c!plaats}\v!midden
+% {\box\scratchbox}}%
+%
+ \ifinsidefloat
+ \box\scratchbox
+ \else\ifnum\columnsetlevel>\zerocount
+ % we only set \columnsetspacing when asked for, else bottom problems
+ % don't change this any more (test naw)
+ \columnslotspacing\namedframedtextparameter{\??columnsetspan#1}\c!nlines\relax
+ % todo: nboven/onder
+ %\OTRSETstoreincolumnslotHERE\scratchbox
+ \edef\floatmethod{\namedframedtextparameter{\??columnsetspan#1}\c!default}%
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ % todo : \v!here -> here enzovoorts
+ \OTRSETstoreincolumnslot\floatmethod\scratchbox
+ \checknextindentation[\namedframedtextparameter{\??columnsetspan#1}\c!indentnext]%
+ \else
+ % of course we needed a one-column fall back for tm; brrr, the box has now too
+ % much height (try \ruledvbox); don't change this without testing techniek
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen-\strutdp
+ \ht\scratchbox\scratchdimen
+ \namedframedtextparameter{\??columnsetspan#1}\c!before
+ \snaptogrid\vbox{\box\scratchbox}%
+ \namedframedtextparameter{\??columnsetspan#1}\c!after
+ \fi\fi
+ \egroup
+ \endgraf}
+
+% \startcolumnset[two]
+% \input tufte
+% \startcolumnsetspan[two][width=20cm,location=middle] \input tufte \stopcolumnsetspan
+% \startcolumnsetspan[two][default=btlr] \input tufte \stopcolumnsetspan
+% \input tufte \par
+% \input tufte \par
+% \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
+% \startcolumnsetspan[two] \input tufte \stopcolumnsetspan
+% \stopcolumnset
+
+\unexpanded\def\page_set_command_flush_saved_floats % rather similar to _one_ ut this might change
+ {\global\d_page_floats_inserted_top\zeropoint
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \ifconditional\c_page_floats_flushing \else
+ \page_set_command_set_top_insertions
+ \page_set_command_set_bottom_insertions
+ \ifconditional\c_page_floats_some_waiting
+ \doif{\rootfloatparameter\c!cache}\v!no\page_set_command_flush_floats % could be _otr_
+ \fi
+ \fi}
+
+\defineoutputroutine
+ [\s!columnset]
+ [\s!page_otr_command_routine =\page_set_command_routine,
+ \s!page_otr_command_package_contents =\page_set_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_set_command_set_vsize,
+ % \s!page_otr_command_set_hsize =\page_one_command_set_hsize, % tricky, goes wrong
+ \s!page_otr_command_next_page =\page_set_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_set_command_next_page_and_inserts,
+ \s!page_otr_command_synchronize_hsize =\page_set_command_synchronize_hsize,
+ \s!page_otr_command_set_top_insertions =\page_set_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions =\page_set_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_set_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions =\page_set_command_flush_bottom_insertions,
+ \s!page_otr_command_set_float_hsize =\page_set_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_set_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_set_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats =\page_set_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_set_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_set_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_set_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_set_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_set_command_flush_margin_blocks, % not used
+ ]
+
+\protect \endinput
+
+% extreme examples (1)
+%
+% \setupfloats[numbering=nocheck]
+%
+% \definecolumnset [first] [n=2,start=0]
+% \definecolumnset [next] [n=2,start=3]
+%
+% \setuptexttexts[\vbox to \textheight{\topskipcorrection \hsize\makeupwidth left \hfill right\vfill}]
+%
+% \setuphead[chapter][text=empty]
+%
+% \starttext
+%
+% \startcolumnset[first,next]
+% \placefigure[btrl]{}{}
+% \placefigure[tblr]{}{}
+% \chapter{thuan} \dorecurse{25}{\recurselevel: \input thuan \endgraf}
+% \stopcolumnset
+%
+% \startcolumnset[first,next]
+% \chapter{thuan} \dorecurse{25}{\input thuan \endgraf\placefigure{}{}}
+% \stopcolumnset
+
+% only in columnsets
+
+% \def\cornerfigure
+% {\dotripleempty\docornerfigure}
+%
+% \def\docornerfigure[#1][#2][#3]% [layer] [location] [settings]
+% {\bgroup
+% \dowithnextbox
+% {\!!doneafalse
+% \!!donebfalse
+% \processallactionsinset
+% [\v!left,\v!bottom,#2]
+% [ \v!left=>\!!doneatrue ,
+% \v!right=>\!!doneafalse,
+% \v!top=>\!!donebtrue ,
+% \v!bottom=>\!!donebfalse]%
+% \!!widtha\nextboxwd
+% \if!!donea
+% % unchecked
+% \advance\!!widtha-\backspace
+% \else
+% % unchecked
+% \advance\!!widtha-\backspace
+% \fi
+% \!!widtha\textwidth % could be an option
+% \!!heighta\nextboxht
+% % zou een macro moeten zijn \getnoflayoutlines
+% \ifnum\layoutparameter\c!lines=\zerocount
+% \getnoflines\textheight
+% \else
+% \noflines\layoutparameter\c!lines
+% \fi
+% %
+% \advance\noflines \plusone % wordt default, instelbaar
+% \!!heightb\noflines\lineheight\relax
+% \if!!doneb % boven
+% % unchecked
+% \advance\!!heighta-\topspace
+% \advance\!!heighta-\headerheight
+% \advance\!!heighta-\headerdistance
+% \else % onder
+% % checked
+% \advance\!!heighta-\paperheight
+% \advance\!!heighta+\!!heightb
+% \advance\!!heighta+\topspace
+% \advance\!!heighta+\headerheight
+% \advance\!!heighta+\headerdistance
+% \advance\!!heighta-\footerdistance
+% \advance\!!heighta-\footerheight
+% \fi
+% \getnoflines\!!heighta
+% \!!heighta\noflines\lineheight\relax
+% \def\docornerfigure[####1]%
+% {\expanded{\plaatsfiguur[####1,\v!none]{}
+% {\noexpand\phantombox[\c!width=\the\!!widtha,\c!height=\the\!!heighta]}}}%
+% \if!!donea
+% \if!!doneb % links boven / rb
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!top},\c!location=rb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tblr]%
+% \else % links onder / rt
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!bottom},\c!location=rt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btlr]%
+% \fi
+% \else
+% \if!!doneb % rechts boven / lt
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!top},\c!location=lb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tbrl]%
+% \else % rechts onder / lb
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!bottom},\c!location=lt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btrl]%
+% \fi
+% \fi
+% \egroup}
+% \vbox}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv
new file mode 100644
index 00000000000..2c1c624df38
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv
@@ -0,0 +1,866 @@
+%D \module
+%D [ file=page-sid,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Side Floats,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Side Floats}
+
+\unprotect
+
+% These macro deal with side floats. We started with Daniel Comenetz macros as published
+% in TUGBoat Volume 14 (1993), No.\ 1: Anchored Figures at Either Margin. I extended and
+% patched the macros to suite our needs which results in a messy module. Therefore, this
+% module badly needs an update because it's now a mixture of old and new macros.
+
+% Interesting cases where it goes wrong:
+%
+% \placefigure[left]{}{} \dorecurse{3}{\input ward } {\par} \input ward
+%
+% Here we get an unwanted carried over hangindent and parindent. A solution is to associate
+% it with the local par node instead. This is something to discuss with Taco as it could be
+% a new luatex/mkiv feature: explicitly set par properties.
+
+% Maybe I should just rewrite the lot.
+
+\newdimen \d_page_sides_height % includes the topskip
+\newdimen \d_page_sides_width
+\newdimen \d_page_sides_hsize
+\newdimen \d_page_sides_vsize
+\newdimen \d_page_sides_vsize_reset \d_page_sides_vsize_reset -\onepoint % could be a \let
+\newdimen \d_page_sides_progress
+\newdimen \d_page_sides_page_total
+\newdimen \d_page_sides_saved_depth
+\newdimen \d_page_sides_grid_shift
+
+\newbox \b_page_sides_bottom
+
+\newcount \c_page_sides_lines_done
+\newcount \c_page_sides_checks_done
+\newcount \c_page_sides_n_of_lines
+\newcount \c_page_sides_n_of_hang
+\newconstant \c_page_sides_float_type
+
+\newconditional \c_page_sides_short % needs checking .. best write this from scratch
+\newconditional \c_page_sides_flag
+
+\newconditional \c_page_sides_r_eq % messy, needs checking anyway
+\newconditional \c_page_sides_l_eq % messy, needs checking anyway
+
+\newdimen \d_page_sides_shift
+\newdimen \d_page_sides_extrashift
+\newdimen \d_page_sided_leftshift
+\newdimen \d_page_sided_rightshift
+\newdimen \d_page_sides_leftskip
+\newdimen \d_page_sides_rightskip
+\newdimen \d_page_sides_maximum
+\newdimen \d_page_sides_topskip
+\newdimen \d_page_sides_bottomskip
+\newdimen \d_page_sides_downshift
+
+\setnewconstant \c_page_sides_method \plusone % 0=raw 1=safe (.99) 2=tight (-1pt)
+\setnewconstant \c_page_sides_align \zerocount
+
+\def\page_sides_process_float_backspace {\global\c_page_sides_float_type\plusone \page_sides_handle_float}
+\def\page_sides_process_float_leftedge {\global\c_page_sides_float_type\plustwo \page_sides_handle_float}
+\def\page_sides_process_float_leftmargin {\global\c_page_sides_float_type\plusthree\page_sides_handle_float}
+\def\page_sides_process_float_left {\global\c_page_sides_float_type\plusfour \page_sides_handle_float}
+\def\page_sides_process_float_right {\global\c_page_sides_float_type\plusfive \page_sides_handle_float}
+\def\page_sides_process_float_rightmargin{\global\c_page_sides_float_type\plussix \page_sides_handle_float}
+\def\page_sides_process_float_rightedge {\global\c_page_sides_float_type\plusseven\page_sides_handle_float}
+\def\page_sides_process_float_cutspace {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
+\def\page_sides_process_float_margin {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
+
+\let\logsidefloat \relax
+
+\newif\iftracesidefloats % public (might change)
+
+% end of public variables
+
+\def\page_sides_insert_info
+ {\page_floats_report_total}
+
+\def\page_sides_apply_horizontal_shift
+ {\ifdim\d_page_sides_maximum>\zeropoint
+ \ifcase\c_page_sides_float_type
+ % invalid
+ \or
+ % backspace
+ \or
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % left
+ \or
+ % right
+ \or
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % cutspace
+ \fi
+ \fi
+ \ifdim\d_page_sides_shift=\zeropoint \relax
+ \ifnum\c_page_sides_float_type=\plusfour
+ \global\advance\d_page_sides_shift\d_page_sides_extrashift
+ \global\d_page_sides_extrashift\zeropoint
+ \else\ifnum\c_page_sides_float_type=\plusfive
+ \global\advance\d_page_sides_shift\d_page_sides_extrashift
+ \global\d_page_sides_extrashift\zeropoint
+ \fi\fi
+ \else
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\c_page_sides_float_type\plusfour
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\c_page_sides_float_type\plusfive
+ \fi\fi
+ \fi}
+
+\def\page_sides_set_skips
+ {\global\d_page_sides_rightskip\zeropoint
+ \global\d_page_sides_leftskip \zeropoint
+ \ifcase\c_page_sides_float_type
+ \or % backspace
+ \global\d_page_sides_leftskip\dimexpr
+ +\rightorleftpageaction \backspace \cutspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftedge
+ \global\d_page_sides_leftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ +\rightorleftpageaction \leftedgedistance \rightedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftmargin
+ \global\d_page_sides_leftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftside
+ \or % rightside
+ \or % rightmargin
+ \global\d_page_sides_rightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % rightedge
+ \global\d_page_sides_rightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\rightorleftpageaction \rightmarginwidth \leftmarginwidth
+ +\rightorleftpageaction \rightedgedistance \leftedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % cutspace
+ \global\d_page_sides_rightskip\dimexpr
+ +\rightorleftpageaction \cutspace \backspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \fi
+ \ifdim\d_page_sides_rightskip>\zeropoint \global\advance\d_page_sides_rightskip\rightskip \fi
+ \ifdim\d_page_sides_leftskip >\zeropoint \global\advance\d_page_sides_leftskip \leftskip \fi}
+
+\def\page_sides_flush_floats
+ {\par
+ \ifnum\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+ \page_sides_flush_floats_indeed
+ \fi
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\d_page_sides_vsize\d_page_sides_vsize_reset
+ \global\setfalse\c_page_sides_short
+ \global\setfalse\c_page_sides_flag}
+
+\unexpanded\def\doifelsesidefloat
+ {\par
+ \ifnum\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifsidefloatelse\doifelsesidefloat
+
+% \def\page_sides_flush_floats_indeed
+% {\global\advance\d_page_sides_vsize-\d_page_sides_bottomskip
+% \begingroup
+% \let\page_sides_flush_floats\relax
+% \forgetall
+% \doloop
+% {\strut
+% \iftracesidefloats
+% \color[darkgray]{\ruledhbox{\strut\kern\d_page_sides_width}}%
+% \fi
+% \par
+% % \ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+% \ifdim\dimexpr\d_page_sides_vsize-\d_page_sides_bottomskip-\pagetotal\relax>\zeropoint
+% \ifnum\recurselevel>\plushundred % safeguard, sort of deadcycles
+% \exitloop
+% \fi
+% \else
+% \exitloop
+% \fi}%
+% \endgroup
+% \ifdim\parskip>\zeropoint % why this test ?
+% \ifdim\d_page_sides_bottomskip>\parskip
+% % \nowhitespace
+% % \vskip\d_page_sides_bottomskip
+% \blank[\v!nowhite,\the\dimexpr\d_page_sides_bottomskip]
+% \fi
+% \else
+% \blank[\the\d_page_sides_bottomskip]% new, so needs checking
+% \fi}
+
+\installcorenamespace{sidefloatsteps}
+
+\setvalue{\??sidefloatsteps\v!line }{\strut}
+\setvalue{\??sidefloatsteps\v!big }{\strut}
+\setvalue{\??sidefloatsteps\v!medium}{\halfstrut}
+\setvalue{\??sidefloatsteps\v!small }{\quarterstrut}
+\setvalue{\??sidefloatsteps\v!depth }{\depthstrut}
+
+% we don't officially know what kind of float we flush
+
+\def\page_sides_flush_floats_indeed
+ {\global\advance\d_page_sides_vsize-\d_page_sides_bottomskip
+ \begingroup
+ \let\page_sides_flush_floats\relax
+ \edef\m_pages_strut{\executeifdefined{\??sidefloatsteps\rootfloatparameter\c!step}\strut}%
+ \forgetall
+ \doloop
+ {\iftracesidefloats
+ \dontleavehmode
+ \ruledhpack{\m_pages_strut\kern\d_page_sides_width}%
+ \else
+ \m_pages_strut
+ \fi
+ \par
+ \nointerlineskip
+ % \ifdim\dimexpr\d_page_sides_vsize-\d_page_sides_bottomskip-\pagetotal\relax>\zeropoint
+ \ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+ \ifnum\recurselevel>\plushundred % safeguard, sort of deadcycles
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \endgroup
+ \ifdim\parskip>\zeropoint % why this test ?
+ \ifdim\d_page_sides_bottomskip>\parskip
+ % \nowhitespace
+ % \vskip\d_page_sides_bottomskip
+% \blank[\v!nowhite,\the\dimexpr\d_page_sides_bottomskip]
+ \blank[\v!nowhite,\rootfloatparameter\c!sidespaceafter]
+ \fi
+ \else
+% \blank[\the\d_page_sides_bottomskip]% new, so needs checking
+ \blank[\rootfloatparameter\c!sidespaceafter]% new, so needs checking
+ \fi}
+
+% alternative method (unsnapped)
+%
+% \def\page_sides_flush_floats_indeed
+% {\scratchdimen\dimexpr\d_page_sides_vsize-\d_page_sides_bottomskip-\pagetotal\relax
+% \ifdim\parskip>\zeropoint % why this test ?
+% \ifdim\scratchdimen>\parskip
+% \blank[\v!nowhite,\the\scratchdimen] % better in stages
+% \fi
+% \else
+% \blank[\the\scratchdimen]
+% \fi}
+
+\def\page_sides_check_floats_after_par
+ {\page_sides_check_floats_indeed
+ \ifdim\oldpagetotal=\pagetotal \else
+ \global\let\page_sides_check_floats\page_sides_check_floats_indeed
+ \page_sides_flush_floats
+ \global\c_page_sides_n_of_lines\zerocount % here !
+ \fi}
+
+\unexpanded\def\page_sides_flush_floats_after_par
+ {\xdef\oldpagetotal{\the\pagetotal}%
+ \global\let\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
+ \global\c_page_sides_n_of_lines\zerocount
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\setfalse\c_page_sides_short
+ \global\setfalse\c_page_sides_flag}
+
+\let\page_otr_sides_pop_penalties \relax
+\let\page_otr_sides_push_penalties\relax
+
+% \def\page_otr_sides_push_penalties % needed ? and right
+% {\widowpenalty\plusone
+% \clubpenalty\plustwo
+% \brokenpenalty\plusone
+% \let\page_otr_sides_push_penalties\relax
+% \edef\page_otr_sides_pop_penalties
+% {\widowpenalty \the\widowpenalty
+% \clubpenalty \the\clubpenalty
+% \brokenpenalty\the\brokenpenalty
+% \let\page_otr_sides_pop_penalties\relax}}
+%
+% shouldn't that be:
+%
+% \def\page_otr_sides_push_penalties % needed?
+% {\let\page_otr_sides_push_penalties\relax
+% \edef\page_otr_sides_pop_penalties
+% {\widowpenalty \the\widowpenalty
+% \clubpenalty \the\clubpenalty
+% \brokenpenalty\the\brokenpenalty
+% \let\page_otr_sides_pop_penalties\relax}%
+% \widowpenalty\plusone
+% \clubpenalty\plustwo
+% \brokenpenalty\plusone}
+
+\def\page_sides_restore_output_penalty
+ {\ifnum\outputpenalty=\plustenthousand \else
+ \penalty\outputpenalty
+ \fi}
+
+\def\page_sides_output_routine
+ {\ifconditional\c_page_sides_short
+ \page_sides_output_routine_yes
+ \else
+ \page_sides_output_routine_nop
+ \fi}
+
+\def\page_sides_output_routine_nop
+ {\page_otr_command_side_float_output % otr specific
+ \global\d_page_sides_vsize\d_page_sides_vsize_reset
+ \global\c_page_sides_n_of_lines\zerocount
+ % we can end up in fig lock, so \global\holdinginserts\zerocount here too ?
+ \page_otr_sides_pop_penalties}
+
+\def\page_sides_output_routine_yes % we need to rework this ... add pagediscards and such
+ {\unvbox\normalpagebox % bah, and the discards?
+ \setbox\b_page_sides_bottom\lastbox
+ \ifdim\wd\b_page_sides_bottom>\d_page_sides_hsize
+ \penalty-201 % hm, i really need to write this from scatch
+ \box\b_page_sides_bottom
+ \else\ifvoid\b_page_sides_bottom
+ \else
+ \page_sides_restore_left_indent
+ \ifdim\wd\b_page_sides_bottom<\d_page_sides_hsize
+ \parskip\zeropoint
+ %\noindent
+ \ifinner\else
+ \vadjust{\penalty\minusone}%
+ \fi
+ \ifconditional\c_page_sides_l_eq
+ \global\setfalse\c_page_sides_l_eq
+ \else
+ \global\advance\d_page_sides_hsize -\wd\b_page_sides_bottom
+ \ifconditional\c_page_sides_r_eq
+ \global\setfalse\c_page_sides_r_eq
+ \else
+ \global\divide\d_page_sides_hsize \plustwo
+ \fi
+ \hskip\d_page_sides_hsize % \kern
+ \fi
+ \fi
+ \box\b_page_sides_bottom
+ \page_sides_restore_output_penalty
+ \fi\fi
+ % why was this \global\holdinginserts\zerocount
+ \global\setfalse\c_page_sides_short}
+
+\def\page_sides_restore_left_indent
+ {\relax
+ \ifnum\c_page_sides_float_type>\plusfour \else
+ \parskip\zeropoint % here ?
+ \ifdim\d_page_sides_width>\zeropoint % new, see prikkels
+ \noindent
+ \ifinner \else
+ \vadjust{\penalty\minusone}%
+ \fi
+ \hskip\d_page_sides_width\relax % \kern
+ %\else
+ % we have a margin or edge float
+ \fi
+ \fi}
+
+% The clean way:
+%
+% \global\setbox\floatbox\hbox
+% {\ifcase\c_page_sides_float_type
+% \vbox{#1}%
+% \or % 1
+% \kern\d_page_sided_leftshift
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 2
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 3
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 4
+% \kern\d_page_sided_leftshift
+% \kern\d_page_sides_shift
+% \vbox{#1\removedepth}%
+% \kern-\d_page_sides_extrashift
+% \or % 5
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \kern\d_page_sided_rightshift
+% \or % 6
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \or % 7
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \or % 8
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \kern\d_page_sided_rightshift
+% \fi}
+%
+% The compact way:
+
+\def\page_sides_relocate_float#1%
+ {\global\setbox\floatbox\hpack
+ {\ifnum\c_page_sides_float_type=\plusfour
+ \kern\d_page_sided_leftshift
+ \else\ifnum\c_page_sides_float_type=\plusone
+ \kern\d_page_sided_leftshift
+ \fi\fi
+ \ifnum\c_page_sides_float_type>\plusfour
+ \kern-\d_page_sides_extrashift
+ \else
+ \kern\d_page_sides_shift
+ \fi
+ \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth \fi}%
+ \ifnum\c_page_sides_float_type>\plusfour
+ \kern\d_page_sides_shift
+ \else
+ \kern-\d_page_sides_extrashift
+ \fi
+ \ifnum\c_page_sides_float_type=\pluseight
+ \kern\d_page_sided_rightshift
+ \else\ifnum\c_page_sides_float_type=\plusfive
+ \kern\d_page_sided_rightshift
+ \fi\fi}}
+
+\def\page_sides_apply_vertical_shift
+ {\ifnum\c_page_sides_align=\plusfour
+ \getnoflines{\ht\floatbox}%
+ \scratchdimen\dimexpr\noflines\lineheight-\strutdepth\relax
+ \getrawnoflines\d_page_sides_topskip
+ \advance\scratchdimen\noflines\lineheight
+ % todo: maybe rounding problem here
+ % \global\setbox\floatbox\hbox{\lower\lineheight\box\floatbox}%
+ \global\setbox\floatbox\hpack{\lower\strutdepth\box\floatbox}%
+ \ht\floatbox\scratchdimen
+ \dp\floatbox\zeropoint
+ \fi
+ \ifcase\c_page_sides_align \else
+ \global\d_page_sides_topskip\zeropoint
+ \fi
+ \scratchdimen
+ \ifnum\c_page_sides_float_type<\plusfour
+ \d_page_sides_topskip
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \d_page_sides_topskip
+ \else
+ \zeropoint
+ \fi\fi
+ % the top of the box is at the previous baseline
+ \ifcase\c_page_sides_align
+ % 0 normal
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
+ \or % 1 height
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
+ \or % 2 line
+ \or % 3 depth
+ \advance\scratchdimen\lineheight % or \openlineheight
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
+ \or % 4 grid
+ \scratchdimen\zeropoint
+ \or
+ \advance\scratchdimen\strutheight % or \openstrutheight
+ \fi
+ % new
+ \global\c_page_sides_lines_done\zerocount
+ \ifnum\c_page_sides_n_of_lines>\zerocount
+ \advance\scratchdimen\c_page_sides_n_of_lines\lineheight
+ \fi
+ \global\setbox\floatbox\hpack % why extra box
+ {\vbox
+ {\vskip\scratchdimen
+ \nointerlineskip
+ \box\floatbox
+ \ifnum\c_page_sides_align=\plusfive \vskip-\lineheight \fi}}%
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\d_page_sides_topskip\zeropoint
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\d_page_sides_topskip\zeropoint
+ \fi\fi
+ \global\d_page_sides_downshift\zeropoint}
+
+\def\page_sides_place_float
+ {\ifnum\c_page_sides_float_type=\plusfour \kern\d_page_sides_topskip \fi
+ \ifnum\c_page_sides_float_type=\plusfive \kern\d_page_sides_topskip \fi
+ \d_page_sides_saved_depth\prevdepth
+ \nointerlineskip
+ \ifgridsnapping
+ \page_sides_place_float_grid
+ \else
+ \page_sides_place_float_normal
+ \fi
+ \par
+ \kern-\d_page_sides_height
+ \penalty10001 % oeps, this will change
+ \normalbaselines
+ \prevdepth\d_page_sides_saved_depth}
+
+\def\page_sides_place_float_normal
+ {\d_page_sides_grid_shift\zeropoint % be nice
+ \page_sides_push_float_inline\firstofoneargument}
+
+% The following needs some more work .. consider this a quick hack. We
+% probably need an mkiv hanging grid option.
+
+\def\page_sides_place_snap_to_grid#1%
+ {\snaptogrid[\v!line,\v!offset:\the\d_page_sides_grid_shift]\hbox{#1}}
+
+% this will be a grid option in float placement:
+
+\newconstant\c_page_sides_place_grid_shift \c_page_sides_place_grid_shift\plustwo
+
+\def\page_sides_place_float_grid
+ {\getrawnoflines\d_page_sides_height % raw ?
+ \d_page_sides_height\noflines\lineheight
+ \d_page_sides_grid_shift\the\dimexpr \plustwo\lineheight
+ \ifcase\c_page_sides_place_grid_shift
+ -3\lineheight % high
+ \or
+ -2.5\lineheight % half (does not work currently)
+ \else
+ -2\lineheight % low
+ \fi
+ \relax
+ \page_sides_push_float_inline\page_sides_place_snap_to_grid}
+
+\def\page_sides_push_float_inline#1%
+ {\begingroup
+ \reseteverypar % needed !
+ \parskip\zeropoint % needed !
+ \page_sides_set_skips
+ \page_sides_insert_info
+ \relax
+ \lefttoright % \textdir TLT\relax % or \ifconditional\displaylefttoright below (more work)
+ \ifcase\c_page_sides_float_type
+ % invalid
+ \or % backspace
+ \noindent#1{\llap{\rlap{\box\floatbox}\kern\d_page_sides_leftskip}}\hfill
+ \or % leftedge
+ \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
+ \or % leftmargin
+ \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
+ \or % leftside
+ \noindent#1{\box\floatbox}\hfill
+ \or % rightside
+ \hfill#1{\box\floatbox}%
+ \or % rightmargin
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
+ \or % rightedge
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
+ \or % cutspace
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\llap{\box\floatbox}}}%
+ \fi
+ \endgroup}
+
+\def\page_sides_analyse_progress
+ {\d_page_sides_progress\d_page_sides_vsize
+ \ifconditional\c_page_sides_flag
+ \advance\d_page_sides_progress-\d_page_sides_page_total
+ \global\setfalse\c_page_sides_flag
+ \else
+ \advance\d_page_sides_progress-\pagetotal
+ \fi}
+
+\def\page_sides_analyse_space
+ {\global\settrue\c_page_sides_flag
+ \global\d_page_sides_page_total \pagetotal % global
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\d_page_sides_width \zeropoint
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\d_page_sides_width\zeropoint
+ \else
+ \global\d_page_sides_width\dimexpr\wd\floatbox+\d_strc_floats_margin\relax
+ \fi\fi
+ \ifdim\d_page_sides_width<\zeropoint
+ \global\d_page_sides_width\zeropoint
+ \fi
+ \global\d_page_sides_hsize \dimexpr\hsize-\d_page_sides_width\relax
+ \global\d_page_sides_height\dimexpr\ht\floatbox+\dp\floatbox+\d_page_sides_topskip\relax
+ \global\d_page_sides_vsize \dimexpr\d_page_sides_height+\d_page_sides_page_total\relax
+ \dimen0\d_page_sides_vsize
+ \dimen2\pagegoal
+ \relax
+ \ifcase\c_page_sides_method
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\setfalse\c_page_floats_room
+ \else
+ \ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomskip
+ \global\advance\d_page_sides_vsize \dimen0
+ \global\settrue\c_page_sides_short
+ \page_otr_sides_push_penalties
+ % why was this \global\holdinginserts\plusone
+ \else
+ \global\advance\d_page_sides_vsize \d_page_sides_bottomskip
+ \global\setfalse\c_page_sides_short
+ \fi
+ \global\settrue\c_page_floats_room
+ \fi}
+
+% \def\page_sides_prepare_space
+% {\par
+% % no longer needed \whitespace
+% \begingroup
+% \forgetall
+% \reseteverypar
+% \verticalstrut
+% \vskip-\struttotal
+% \endgroup}
+
+\installtextracker
+ {sidefloats.anchor}
+ {\let\page_sides_anchor\page_sides_anchor_yes}
+ {\let\page_sides_anchor\page_sides_anchor_nop}
+
+\def\page_sides_anchor_yes
+ {\darkred
+ \hskip-5\emwidth
+ \vrule\s!height.05\exheight\s!depth.05\exheight\s!width10\emwidth}
+
+\def\page_sides_anchor_nop
+ {\strut}
+
+\let\page_sides_anchor\page_sides_anchor_nop
+
+\def\page_sides_prepare_space
+ {\par
+ \begingroup
+ \reseteverypar
+ \dontleavehmode\hpack to \zeropoint{\page_sides_anchor\hss\strut}%
+ \vskip-\parskip
+ \vskip-\struttotal
+ \inhibitblank
+ \endgroup}
+
+\def\page_sides_handle_float#1% grid (4) is rather experimental
+ {\page_sides_prepare_space
+ \page_sides_apply_horizontal_shift
+ \page_sides_check_previous_float
+ \page_sides_inject_dummy_lines
+ \page_sides_relocate_float{#1}%
+ \page_sides_apply_vertical_shift
+ \page_sides_analyse_space
+ \ifconditional\c_page_floats_room \else
+ \page_otr_fill_and_eject_page
+ \page_sides_analyse_space
+ \page_sides_inject_dummy_lines
+ \fi
+ \page_sides_place_float
+ \page_sides_check_floats_reset
+ \ignorespaces} % not really needed
+
+\def\page_sides_check_floats_indeed
+ {\page_sides_analyse_progress
+ \ifdim\d_page_sides_progress>\zeropoint
+ \page_sides_check_floats_set
+ \else
+ \page_sides_check_floats_reset
+ \fi
+ \parskip\s_spac_whitespace_parskip}
+
+\let\page_sides_check_floats\page_sides_check_floats_indeed
+
+\unexpanded\def\page_sides_check_floats_set
+ {\scratchdimen\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax
+ \c_page_sides_n_of_hang\scratchdimen
+ \divide\c_page_sides_n_of_hang \baselineskip\relax
+ \ifnum\c_page_sides_n_of_hang>\zerocount
+ % new from here (needs test case, old code)
+ \ifcase\c_page_sides_n_of_lines
+ \else
+ \ifcase\c_page_sides_lines_done
+ \global\c_page_sides_lines_done\c_page_sides_n_of_hang
+ \else
+ \scratchcounter\c_page_sides_lines_done
+ \advance\scratchcounter-\c_page_sides_n_of_hang
+ \global\advance\c_page_sides_n_of_lines-\scratchcounter
+ \fi
+ \fi
+ % hm, when do we get the parshape branch? needs testing
+ \ifnum\c_page_sides_n_of_lines>\zerocount
+ \scratchtoks\emptytoks
+ \scratchcounter\c_page_sides_n_of_lines
+ \scratchdimen\dimexpr\hsize-\d_page_sides_width\relax
+ \dorecurse\c_page_sides_n_of_lines
+ {\appendtoks \zeropoint \hsize \to \scratchtoks}%
+ \ifnum\c_page_sides_n_of_hang>\c_page_sides_n_of_lines
+ \advance\c_page_sides_n_of_hang -\c_page_sides_n_of_lines\relax
+ \advance\scratchcounter\c_page_sides_n_of_hang
+ \dorecurse\c_page_sides_n_of_hang % weird, shouldn't that be scratchcounter
+ {\ifnum\c_page_sides_float_type>\plusfour
+ \appendtoks \zeropoint \scratchdimen \to \scratchtoks
+ \else
+ \appendtoks \d_page_sides_width\scratchdimen \to \scratchtoks
+ \fi}%
+ \fi
+ \parshape
+ \numexpr\scratchcounter+\plusone\relax
+ \the\scratchtoks % \scratchcounter
+ \zeropoint \hsize % \plusone
+ \relax
+ \else
+ % new till here
+ \hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width
+ \hangafter-\c_page_sides_n_of_hang
+ \fi
+ \fi
+ \global\advance\c_page_sides_checks_done \plusone
+ \iftracesidefloats
+ \hskip-\d_page_sides_width % kern
+ \color[darkgray]%
+ {\vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width
+ \llap{\showstruts\strut\kern.25\bodyfontsize}}%
+ \fi}
+
+\unexpanded\def\page_sides_check_floats_reset
+ {\global\c_page_sides_checks_done\zerocount}
+
+\unexpanded\def\page_sides_synchronize_floats
+ {\ifinner \else
+ \page_sides_check_floats
+ \fi}
+
+\unexpanded\def\page_sides_check_previous_float
+ {\page_sides_analyse_progress
+ \ifdim\d_page_sides_progress>\zeropoint \relax
+ \ifconditional\c_page_sides_short
+ \global\setfalse\c_page_sides_short
+ \page_otr_fill_and_eject_page
+ \else
+ \kern\d_page_sides_progress
+ \fi
+ \fi}
+
+\def\page_sides_inject_dummy_lines
+ {\begingroup
+ \scratchcounter\pageshrink
+ \divide\scratchcounter \baselineskip
+ \advance\scratchcounter \plusone
+ \parskip\zeropoint
+ \dorecurse\scratchcounter{\hpack to \hsize{}}%
+ \kern-\scratchcounter\baselineskip
+ \penalty\zerocount
+ \endgroup}
+
+% Display math
+%
+% If we need this, it will be redone but redefining
+% these macros does not really work out in the current
+% situation.
+%
+% \ifx\normalleqno\undefined
+%
+% \let\floatrighteqo=\eqno
+% \let\floatleftleqo=\leqno
+%
+% \else
+%
+% \let\floatrighteqo=\normaleqno
+% \let\floatleftleqo=\normalleqno
+%
+% \fi
+%
+% \ifx\normaleqno\undefined
+%
+% \def\normaleqno
+% {\ifconditional\c_page_sides_short
+% \global\settrue\c_page_sides_r_eq
+% \fi
+% \floatrighteqo}
+%
+% \else
+%
+% \def\eqno
+% {\ifconditional\c_page_sides_short
+% \global\settrue\c_page_sides_r_eq
+% \fi
+% \floatrighteqo}
+%
+% \fi
+
+\def\adjustsidefloatdisplaylines % public, will change
+ {\aftergroup\page_sides_adjust_display_lines}
+
+\def\page_sides_adjust_display_lines
+ {\par
+ \noindent
+ \ignorespaces}
+
+% We need to hook it into the other otr's. This code will be adapted
+% once we rename the callers.
+
+% \def as they can be redefined!
+
+% some will become obsolete
+
+\def\checksidefloat {\page_sides_check_floats}
+\def\flushsidefloats {\page_sides_flush_floats}
+\def\flushsidefloatsafterpar{\page_sides_flush_floats_after_par}
+\def\forgetsidefloats {\page_sides_forget_floats}
+%def\synchronizesidefloats {\page_sides_synchronize_floats}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv
new file mode 100644
index 00000000000..dc1e013d50d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv
@@ -0,0 +1,131 @@
+%D \module
+%D [ file=page-spr,
+%D version=2002.11.11,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Spreading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Spreading}
+
+% This module is experimental and not yet official!
+
+\unprotect
+
+\newbox \b_page_spread_content
+\newconditional\c_page_spread_busy
+\newconditional\c_page_spread_once % when true only one flush (writes etc)
+
+% 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_normal#1%
+ {\setbox#1\hbox to \makeupwidth
+ {\hss\box#1\hss}} % never change the \hss's
+
+\def\normalsettextpagecontent_spread#1%
+ {\setbox#1\hbox to \makeupwidth
+ {\ifvoid\b_page_spread_content
+ \ifconditional\c_page_spread_once
+ \box#1%
+ \else
+ \global\setbox\b_page_spread_content\box#1%
+ \copy\b_page_spread_content
+ \fi
+ \hss % left page
+ \else
+ \hss % right page
+ \ifarrangingpages
+ % writes don't matter anyway
+ \else\ifconditional\c_page_spread_once
+ \global\setbox\b_page_spread_content\emptyhbox
+ \wd\b_page_spread_content\makeupwidth
+ \ht\b_page_spread_content\textheight
+ \else
+ % writes can interfere (todo: write stripper, but how about hyperlinks)
+ \fi \fi
+ \box\b_page_spread_content
+ \fi}}
+
+\unexpanded\def\page_spread_flush
+ {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else
+ % this page will be discarded later
+ \emptyhbox \page
+ \fi \fi }
+
+\unexpanded\def\startspread
+ {\ifdoublesided
+ \ifconditional\c_page_spread_busy
+ \doubleexpandafter\page_spread_start_nop
+ \else
+ \doubleexpandafter\page_spread_start_yes
+ \fi
+ \else
+ \expandafter\page_spread_start_nop
+ \fi}
+
+\let\stopspread\relax
+
+\unexpanded\def\page_spread_start_yes
+ {\bgroup
+ \page[\v!left]%
+ %\setsystemmode{spread}%
+ \settrue\c_page_spread_busy
+ \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}%
+ \let\stopspread\page_spread_stop_yes}
+
+\unexpanded\def\page_spread_stop_yes
+ {\kern\zeropoint
+ \page
+ \setuplayout[\c!textwidth=\textwidth]
+ \page[\v!left]
+ \egroup}
+
+\unexpanded\def\page_spread_start_nop
+ {\bgroup
+ \let\stopspread\page_spread_stop_nop}
+
+\unexpanded\def\page_spread_stop_nop
+ {\egroup}
+
+\protect \endinput
+
+% texexec --arr --pdf test
+%
+% \setuplayout[width=middle]
+% \setuppapersize[A4][A3,landscape]
+% \setuppagenumbering[alternative=doublesided]
+% \setuparranging[2UP]
+%
+% \starttext
+%
+% \dorecurse{3}{\input tufte }
+%
+% \startspread
+% \dorecurse{10}{\input tufte }
+% \stopspread
+%
+% \dorecurse{3}{\input tufte }
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-str.lua b/Master/texmf-dist/tex/context/base/mkiv/page-str.lua
new file mode 100644
index 00000000000..56c6167aa56
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-str.lua
@@ -0,0 +1,296 @@
+if not modules then modules = { } end modules ['page-str'] = {
+ version = 1.001,
+ comment = "companion to page-str.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- streams -> managers.streams
+
+-- work in progresss .. unfinished
+
+local concat, insert, remove = table.concat, table.insert, table.remove
+
+local nodes, node = nodes, node
+
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+
+local implement = interfaces.implement
+
+local new_kern = nodepool.kern
+local new_glyph = nodepool.glyph
+
+local slide_nodelist = node.slide
+local write_node = node.write
+local free_node = node.free
+local copy_nodelist = node.copy_list
+local vpack_nodelist = node.vpack
+local hpack_nodelist = node.hpack
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local texgetdimen = tex.getdimen
+local 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)
+
+local report_streams = logs.reporter("streams")
+
+streams = streams or { } -- might move to the builders namespace
+local streams = streams
+
+local data, name, stack = { }, nil, { }
+
+function streams.enable(newname)
+ if newname == "default" then
+ name = nil
+ else
+ name = newname
+ end
+end
+
+function streams.disable()
+ name = stack[#stack]
+end
+
+function streams.start(newname)
+ insert(stack,name)
+ name = newname
+end
+
+function streams.stop(newname)
+ name = remove(stack)
+end
+
+function streams.collect(head,where)
+ if name and head and name ~= "default" then
+ local tail = node.slide(head)
+ local dana = data[name]
+ if not dana then
+ dana = { }
+ data[name] = dana
+ end
+ local last = dana[#dana]
+ if last then
+ local tail = slide_nodelist(last)
+ tail.next, head.prev = head, tail
+ elseif last == false then
+ dana[#dana] = head
+ else
+ dana[1] = head
+ end
+ if trace_collecting then
+ report_streams("appending snippet %a to slot %s",name,#dana)
+ end
+ return nil, true
+ else
+ return head, false
+ end
+end
+
+function streams.push(thename)
+ if not thename or thename == "" then
+ thename = name
+ end
+ if thename and thename ~= "" then
+ local dana = data[thename]
+ if dana then
+ dana[#dana+1] = false
+ if trace_collecting then
+ report_streams("pushing snippet %a",thename)
+ end
+ end
+ end
+end
+
+function streams.flush(name,copy) -- problem: we need to migrate afterwards
+ local dana = data[name]
+ if dana then
+ local dn = #dana
+ if dn == 0 then
+ -- nothing to flush
+ elseif copy then
+ if trace_flushing then
+ report_streams("flushing copies of %s slots of %a",dn,name)
+ end
+ for i=1,dn do
+ local di = dana[i]
+ if di then
+ write_node(copy_nodelist(di.list)) -- list, will be option
+ end
+ end
+ if copy then
+ data[name] = nil
+ end
+ else
+ if trace_flushing then
+ report_streams("flushing %s slots of %a",dn,name)
+ end
+ for i=1,dn do
+ local di = dana[i]
+ if di then
+ write_node(di.list) -- list, will be option
+ di.list = nil
+ free_node(di)
+ end
+ end
+ end
+ end
+end
+
+function streams.synchronize(list) -- this is an experiment !
+ -- we don't optimize this as we want to trace in detail
+ list = settings_to_array(list)
+ local max = 0
+ if trace_flushing then
+ report_streams("synchronizing list: % t",list)
+ end
+ for i=1,#list do
+ local dana = data[list[i]]
+ if dana then
+ local n = #dana
+ if n > max then
+ max = n
+ end
+ end
+ end
+ if trace_flushing then
+ report_streams("maximum number of slots: %s",max)
+ end
+ for m=1,max do
+ local height, depth = 0, 0
+ for i=1,#list do
+ local name = list[i]
+ local dana = data[name]
+ local slot = dana[m]
+ if slot then
+ local vbox = vpack_nodelist(slot)
+ local ht, dp = vbox.height, vbox.depth
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ dana[m] = vbox
+ if trace_flushing then
+ report_streams("slot %s of %a is packed to height %p and depth %p",m,name,ht,dp)
+ end
+ end
+ end
+ if trace_flushing then
+ report_streams("slot %s has max height %p and max depth %p",m,height,depth)
+ end
+ local strutht = texgetdimen("globalbodyfontstrutheight")
+ local strutdp = texgetdimen("globalbodyfontstrutdepth")
+ local struthtdp = strutht + strutdp
+ for i=1,#list do
+ local name = list[i]
+ local dana = data[name]
+ local vbox = dana[m]
+ if vbox then
+ local delta_height = height - vbox.height
+ local delta_depth = depth - vbox.depth
+ 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
+ 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_nodelist(vbox.list)
+ local n, delta = 0, delta_height -- for tracing
+ while delta > 0 do
+ -- we need to add some interline penalties
+ local line = copy_nodelist(texgetbox("strutbox"))
+ line.height, line.depth = strutht, strutdp
+ if tail then
+ tail.next, line.prev = line, tail
+ end
+ tail = line
+ n, delta = n +1, delta - struthtdp
+ end
+ dana[m] = vpack_nodelist(vbox.list)
+ vbox.list = nil
+ free_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)
+ end
+ end
+ end
+ else
+ -- make dummy
+ end
+ end
+ end
+end
+
+tasks.appendaction("mvlbuilders", "normalizers", "streams.collect")
+
+tasks.disableaction("mvlbuilders", "streams.collect")
+
+function streams.initialize()
+ tasks.enableaction ("mvlbuilders", "streams.collect")
+ function streams.initialize() end
+end
+
+-- todo: remove empty last { }'s
+-- todo: better names, enable etc
+
+implement {
+ name = "initializestream",
+ actions = streams.initialize,
+ onlyonce = true,
+}
+
+implement {
+ name = "enablestream",
+ actions = streams.enable,
+ arguments = "string"
+}
+
+implement {
+ name = "disablestream",
+ actions = streams.disable
+}
+
+implement {
+ name = "startstream",
+ actions = streams.start,
+ arguments = "string"
+}
+
+implement {
+ name = "stopstream",
+ actions = streams.stop
+}
+
+implement {
+ name = "flushstream",
+ actions = streams.flush,
+ arguments = "string"
+}
+
+implement {
+ name = "flushstreamcopy",
+ actions = streams.flush,
+ arguments = { "string", true }
+}
+
+implement {
+ name = "synchronizestream",
+ actions = streams.synchronize,
+ arguments = "string"
+}
+
+implement {
+ name = "pushstream",
+ actions = streams.push,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv
new file mode 100644
index 00000000000..e4b2fa22980
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv
@@ -0,0 +1,153 @@
+%D \module
+%D [ file=page-str,
+%D version=2010.03.13, % 2006.03.21,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Streams,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Streams}
+
+%D The first version of this component of \CONTEXT\ was written
+%D for Thomas Schmitz who asked for parallel page streams. While
+%D playing with the code, I decided to make it into a component
+%D that can be used to construct all kind of stream related
+%D mechanisms. Because I could apply this feature in a project,
+%D there is some additional code here (related to graphics).
+%D
+%D These macros were written while listening to and watching the DVD
+%D \quotation {Rush In Rio}.
+%D
+%D The reimplementation (or rather experimenting with the complete
+%D rewrite) was done while looping over \quotation {Wende Snijders
+%D No.9}.
+%D
+%D Remark: marknotes are gone, at least for a while.
+
+\registerctxluafile{page-str}{1.001}
+
+\unprotect
+
+\let \currentoutputstream \empty
+\newif \ifinoutputstream % will become a conditional or mode
+\newtoks \everyenableoutputstream
+
+\appendtoks
+ \page_otr_command_flush_side_floats
+\to \everyenableoutputstream
+
+\unexpanded\def\initializeoutputstreams
+ {\clf_initializestream
+ \glet\initializeoutputstreams\relax}
+
+\unexpanded\def\enableoutputstream[#1]% could be \startoutputsubstream
+ {\initializeoutputstreams
+ \the\everyenableoutputstream
+ \inoutputstreamtrue
+ \xdef\currentoutputstream{#1}%
+ \clf_enablestream{#1}}
+
+\unexpanded\def\disableoutputstream
+ {\inoutputstreamfalse
+ \global\let\currentoutputstream\s!default
+ \clf_disablestream}
+
+\unexpanded\def\startoutputstream[#1]%
+ {\begingroup
+ \initializeoutputstreams
+ \the\everyenableoutputstream
+ \inoutputstreamtrue
+ \xdef\currentoutputstream{#1}%
+ \clf_startstream{#1}}
+
+\unexpanded\def\stopoutputstream
+ {\clf_stopstream
+ \endgroup}
+
+\unexpanded\def\startoutputsubstream[#1]% just push/pop instead
+ {\globalpushmacro\currentoutputstream
+ \enableoutputstream[#1]}
+
+\unexpanded\def\stopoutputsubstream
+ {\globalpopmacro\currentoutputstream
+ \enableoutputstream[\currentoutputstream]}
+
+\def\flushoutputstream [#1]{\clf_flushstream{#1}}
+\def\outputstreambox [#1]{\vbox{\clf_flushstream{#1}}}
+\def\outputstreamcopy [#1]{\vbox{\clf_flushstreamcopy{#1}}}
+\def\outputstreamunvbox [#1]{\clf_flushstream{#1}}
+\def\outputstreamunvcopy[#1]{\clf_flushstreamcopy{#1}}
+\def\synchronizestreams [#1]{\clf_synchronizestream{#1}}
+\def\dopushoutputstream [#1]{\clf_pushstream{#1}}
+
+\unexpanded\def\pushoutputstream
+ {\dosingleempty\dopushoutputstream}
+
+% \unexpanded\def\defineoutputstream[#1]%
+% {\doifundefined{otrs:#1}{\expandafter\newbox\csname otrs:#1\endcsname}}
+%
+% \def\useoutputstream[#1]%
+% {\writestatus{otr}{using output stream #1}%
+% \xdef\currentoutputstream{#1}}
+%
+% \directsetup{stream:\firstoutputstream:set}
+% \directsetup{stream:\firstoutputstream:top}
+% \directsetup{stream:\firstoutputstream:bottom}
+% \directsetup{stream:\firstoutputstream:reset}
+
+% Obsolete in \MKIV:
+%
+% \unexpanded\def\definemarknote
+% {\dodoubleempty\dodefinemarknote}
+%
+% \def\dodefinemarknote[#1][#2]{}
+% \def\setmarknote [#1]{\gobbleoneargument}
+% \def\flushmarknotes [#1]{}
+% \def\erasemarknotes [#1]{}
+
+\protect \endinput
+
+% \enabletrackers[streams.flushing]
+%
+% \setuplayout[grid=yes] \showgrid
+%
+% \starttext
+%
+% \input tufte
+%
+% \startoutputstream[nl]
+%
+% Wat doen we hier?
+%
+% \enableoutputstream[en]
+%
+% Are you sleeping, brother John?\footnote{xxx}
+%
+% \dorecurse{4}{x \footnote{note \recurselevel}\input tufte \par \pushoutputstream}
+%
+% \enableoutputstream[de]
+%
+% Bruder Jakob, schläfst du noch?\footnote{yyy}
+%
+% \dorecurse{4}{x \footnote{note \recurselevel}\input ward \par \pushoutputstream}
+%
+% \disableoutputstream
+%
+% \stopoutputstream
+%
+% Vader Jacob, slaap je nog?\footnote{zzz}
+%
+% \input tufte
+%
+% \synchronizestreams[en,de,nl]
+%
+% \page \flushoutputstream[en] \input knuth
+% \page \flushoutputstream[de] \input knuth
+% \page \flushoutputstream[nl] \input knuth
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi
new file mode 100644
index 00000000000..515d16e135b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi
@@ -0,0 +1,1000 @@
+% macros=mkvi
+
+%D \module
+%D [ file=page-txt, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Texts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Texts}
+
+\unprotect
+
+\newtoks\toptextcontent \newtoks\leftedgetextcontent
+\newtoks\headertextcontent \newtoks\leftmargintextcontent
+\newtoks\footertextcontent \newtoks\rightmargintextcontent
+\newtoks\bottomtextcontent \newtoks\rightedgetextcontent
+
+\newtoks\texttextcontent
+
+%D \macros
+%D {setuptop, setupheader, setuptext,
+%D setupfooter, setupbottom}
+%D
+%D The macros in this module sometimes look a bit more complicated
+%D than needed, which is a direct result of the fact that their
+%D ancestors are quite old and upward compatibility is a must.
+%D
+%D \showsetup{setuptop}
+%D \showsetup{setupheader}
+%D \showsetup{setuptext}
+%D \showsetup{setupfooter}
+%D \showsetup{setupbottom}
+
+\installcorenamespace{layouttexts}
+\installcorenamespace{layouttextsline}
+\installcorenamespace{layouttextsreset}
+\installcorenamespace{layouttextssynchronize}
+\installcorenamespace{layouttextstrut}
+\installcorenamespace{layouttextspecial}
+\installcorenamespace{layouttextcontent}
+
+\installcommandhandler \??layouttexts {layoutelement} \??layouttexts
+
+% \appendtoks
+% \resetlayoutelementparameter\c!lefttext % resolves better
+% \resetlayoutelementparameter\c!middletext
+% \resetlayoutelementparameter\c!righttext
+% \to \everydefinelayoutelement
+
+\definelayoutelement[\v!top ]
+\definelayoutelement[\v!header]
+\definelayoutelement[\v!text ]
+\definelayoutelement[\v!footer]
+\definelayoutelement[\v!bottom]
+
+\definelayoutelement[\v!top :\v!text] [\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!text] [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!text] [\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!footer:\v!text] [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!bottom:\v!text] [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
+
+\definelayoutelement[\v!top :\v!margin][\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!margin][\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!margin][\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!footer:\v!margin][\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!bottom:\v!margin][\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
+
+\definelayoutelement[\v!top :\v!edge] [\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!edge] [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!edge] [\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!footer:\v!edge] [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!bottom:\v!edge] [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
+
+\unexpanded\def\setuplayouttext
+ {\dotripleempty\page_layouts_setup_text}
+
+\def\page_layouts_setup_text[#vertical][#horizontal][#settings]%
+ {\ifthirdargument
+ \setuplayoutelement[#vertical:#horizontal][#settings]%
+ \else
+ \setuplayoutelement[#vertical][#horizontal]%
+ \fi}
+
+\appendtoks
+ \ifx\currentlayoutelement\empty\else
+ \page_layouts_synchronize_element\currentlayoutelement % brr, can be vertical:horizontal
+ \fi
+\to \everysetuplayoutelement
+
+\def\page_layouts_reset_element_status#vertical%
+ {\expandafter\normalgdef\csname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}}
+
+\def\page_layouts_set_element_status_normal#vertical%
+ {\global\expandafter\let\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
+ \global\expandafter\let\csname\??layouttextsreset#vertical\endcsname\relax
+ \page_layouts_synchronize_element{#vertical}}
+
+\def\page_layouts_synchronize_element#vertical%
+ {\xdef\previoustextstate{\csname\??layouttextssynchronize#vertical\endcsname}% can be a let
+ \edef\currenttextstate {\namedlayoutelementparameter{#vertical}\c!state}%
+ %\writestatus{>>}{[#vertical:\currenttextstate/\previoustextstate]}%
+ \ifx\currenttextstate\previoustextstate \else
+ \page_layouts_synchronize_element_indeed{#vertical}%
+ \fi}
+
+\def\page_layouts_synchronize_element_indeed#vertical%
+ {\ifx\currenttextstate \v!high \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi\fi\fi\fi
+ \letgvalue{\??layouttextssynchronize#vertical}\currenttextstate}
+
+\unexpanded\def\setuptop {\dotripleempty\page_layouts_setup_text[\v!top ]}
+\unexpanded\def\setupheader{\dotripleempty\page_layouts_setup_text[\v!header]}
+\unexpanded\def\setuptext {\dotripleempty\page_layouts_setup_text[\v!text ]}
+\unexpanded\def\setupfooter{\dotripleempty\page_layouts_setup_text[\v!footer]}
+\unexpanded\def\setupbottom{\dotripleempty\page_layouts_setup_text[\v!bottom]}
+
+%D We inherit some settings:
+
+\setuplayoutelement
+ [ \c!leftstyle=\layoutelementparameter\c!style,
+ \c!rightstyle=\layoutelementparameter\c!style,
+ \c!leftcolor=\layoutelementparameter\c!color,
+ \c!rightcolor=\layoutelementparameter\c!color,
+ \c!leftwidth=\layoutelementparameter\c!width,
+ \c!rightwidth=\layoutelementparameter\c!width]
+
+%D \macros
+%D {noheaderandfooterlines,notopandbottomlines}
+%D
+%D Although not really needed, the following shortcuts
+%D sometimes come in handy.
+%D
+%D \showsetup{noheaderandfooterlines}
+%D \showsetup{notopandbottomlines}
+
+\unexpanded\def\noheaderandfooterlines
+ {\setuplayoutelement[\v!header][\c!state=\v!empty]%
+ \setuplayoutelement[\v!footer][\c!state=\v!empty]}
+
+\unexpanded\def\notopandbottomlines
+ {\setuplayoutelement[\v!top ][\c!state=\v!empty]%
+ \setuplayoutelement[\v!bottom][\c!state=\v!empty]}
+
+%D \macros
+%D {setuptoptexts, setupheadertexts, setuptexttexts,
+%D setupfootertexts, setupbottomtexts}
+%D
+%D The next macros take one or more arguments. The exact setup
+%D depends on the number of arguments. Although not that
+%D intuitive, the current scheme evolved out of the original.
+%D When margin and edge texts as well as middle texts showed
+%D up, the current odd|/|even scheme surfaced.
+%D
+%D \showsetup{setuptoptexts}
+%D \showsetup{setupheadertexts}
+%D \showsetup{setuptexttexts}
+%D \showsetup{setupfootertexts}
+%D \showsetup{setupbottomtexts}
+
+\unexpanded\def\setuptoptexts {\dosixtupleempty\page_layouts_setup_texts[\v!top ]}
+\unexpanded\def\setupheadertexts{\dosixtupleempty\page_layouts_setup_texts[\v!header ]}
+\unexpanded\def\setuptexttexts {\dosixtupleempty\page_layouts_setup_texts[\v!text ]}
+\unexpanded\def\setupfootertexts{\dosixtupleempty\page_layouts_setup_texts[\v!footer ]}
+\unexpanded\def\setupbottomtexts{\dosixtupleempty\page_layouts_setup_texts[\v!bottom ]}
+
+% todo: \setuplayoutelementtext
+
+% An alternative approach is to have more variables but that does not
+% make the code less complex (probably more).
+
+% \unexpanded\def\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]%
+% {\ifsixthargument
+% \edef\currentlayoutelement{#vertical:#horizontal}%
+% \setlayoutelementparameter\c!lefttext
+% {\page_layouts_process_element_double
+% \c!leftstyle \c!leftcolor \c!leftwidth {#a}%
+% \c!rightstyle\c!rightcolor\c!rightwidth{#d}}%
+% \setlayoutelementparameter\c!righttext
+% {\page_layouts_process_element_double
+% \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+% \c!leftstyle \c!leftcolor \c!leftwidth {#c}}%
+% \else\iffifthargument
+% \edef\currentlayoutelement{#vertical:\v!text}%
+% \setlayoutelementparameter\c!lefttext
+% {\page_layouts_process_element_double
+% \c!leftstyle \c!leftcolor \c!leftwidth {#horizontal}%
+% \c!rightstyle\c!rightcolor\c!rightwidth{#c}}%
+% \setlayoutelementparameter\c!righttext
+% {\page_layouts_process_element_double
+% \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+% \c!leftstyle \c!leftcolor \c!leftwidth {#b}}%
+% \else\iffourthargument
+% \edef\currentlayoutelement{#vertical:#horizontal}%
+% \doifelsenothing{\detokenize{#a}}
+% {\resetlayoutelementparameter\c!lefttext}
+% {\setlayoutelementparameter\c!lefttext
+% {\page_layouts_process_element_double
+% \c!leftstyle\c!leftcolor\c!leftwidth{#a}%
+% \c!leftstyle\c!leftcolor\c!leftwidth{#a}}}%
+% \doifelsenothing{\detokenize{#b}}
+% {\resetlayoutelementparameter\c!righttext}
+% {\setlayoutelementparameter\c!righttext
+% {\page_layouts_process_element_double
+% \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+% \c!rightstyle\c!rightcolor\c!rightwidth{#b}}}%
+% \else\ifthirdargument
+% \edef\currentlayoutelement{#vertical:\v!text}%
+% \doifelsenothing{\detokenize{#horizontal}}
+% {\resetlayoutelementparameter\c!lefttext}
+% {\setlayoutelementparameter\c!lefttext
+% {\page_layouts_process_element_double
+% \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}%
+% \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}}}%
+% \doifelsenothing{\detokenize{#a}}
+% {\resetlayoutelementparameter\c!righttext}
+% {\setlayoutelementparameter\c!righttext
+% {\page_layouts_process_element_double
+% \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+% \c!rightstyle\c!rightcolor\c!rightwidth{#a}}}%
+% \else\ifsecondargument
+% \edef\currentlayoutelement{#vertical:\v!text}%
+% \resetlayoutelementparameter\c!lefttext
+% \resetlayoutelementparameter\c!righttext
+% \doifelsenothing{\detokenize{#horizontal}}
+% {\resetlayoutelementparameter\c!middletext}
+% {\setlayoutelementparameter\c!middletext
+% {\page_layouts_process_element_single\c!style\c!color\c!width{#horizontal}}}%
+% \else
+% \edef\currentlayoutelement{#vertical:\v!text}%
+% \resetlayoutelementparameter\c!lefttext
+% \resetlayoutelementparameter\c!righttext
+% \resetlayoutelementparameter\c!middletext
+% \edef\currentlayoutelement{#vertical:\v!margin}%
+% \resetlayoutelementparameter\c!lefttext
+% \resetlayoutelementparameter\c!righttext
+% \resetlayoutelementparameter\c!middletext
+% \edef\currentlayoutelement{#vertical:\v!edge}%
+% \resetlayoutelementparameter\c!lefttext
+% \resetlayoutelementparameter\c!righttext
+% \resetlayoutelementparameter\c!middletext
+% \fi\fi\fi\fi\fi}
+
+\unexpanded\def\page_layouts_setup_text_six#vertical#horizontal#a#b#c#d%
+ {\edef\currentlayoutelement{#vertical:#horizontal}%
+ \setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#a}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#d}}%
+ \setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+ \c!leftstyle \c!leftcolor \c!leftwidth {#c}}}
+
+\unexpanded\def\page_layouts_setup_text_five#vertical#horizontal#a#b#c%
+ {\edef\currentlayoutelement{#vertical:\v!text}%
+ \setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#horizontal}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#c}}%
+ \setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+ \c!leftstyle \c!leftcolor \c!leftwidth {#b}}}
+
+\unexpanded\def\page_layouts_setup_text_four#vertical#horizontal#a#b%
+ {\edef\currentlayoutelement{#vertical:#horizontal}%
+ \doifelsenothing{\detokenize{#a}}
+ {\resetlayoutelementparameter\c!lefttext}
+ {\setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle\c!leftcolor\c!leftwidth{#a}%
+ \c!leftstyle\c!leftcolor\c!leftwidth{#a}}}%
+ \doifelsenothing{\detokenize{#b}}
+ {\resetlayoutelementparameter\c!righttext}
+ {\setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}}}}
+
+\unexpanded\def\page_layouts_setup_text_three#vertical#horizontal#a%
+ {\edef\currentlayoutelement{#vertical:\v!text}%
+ \doifelsenothing{\detokenize{#horizontal}}
+ {\resetlayoutelementparameter\c!lefttext}
+ {\setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}%
+ \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}}}%
+ \doifelsenothing{\detokenize{#a}}
+ {\resetlayoutelementparameter\c!righttext}
+ {\setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}}}}
+
+\unexpanded\def\page_layouts_setup_text_two#vertical#horizontal%
+ {\edef\currentlayoutelement{#vertical:\v!text}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \doifelsenothing{\detokenize{#horizontal}}
+ {\resetlayoutelementparameter\c!middletext}
+ {\setlayoutelementparameter\c!middletext
+ {\page_layouts_process_element_single\c!style\c!color\c!width{#horizontal}}}}
+
+\unexpanded\def\page_layouts_setup_text_one#vertical%
+ {\edef\currentlayoutelement{#vertical:\v!text}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext
+ \edef\currentlayoutelement{#vertical:\v!margin}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext
+ \edef\currentlayoutelement{#vertical:\v!edge}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext}
+
+\unexpanded\def\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]%
+ {\ifsixthargument \page_layouts_setup_text_six {#vertical}{#horizontal}{#a}{#b}{#c}{#d}\else
+ \iffifthargument \page_layouts_setup_text_five {#vertical}{#horizontal}{#a}{#b}{#c}\else
+ \iffourthargument\page_layouts_setup_text_four {#vertical}{#horizontal}{#a}{#b}\else
+ \ifthirdargument \page_layouts_setup_text_three{#vertical}{#horizontal}{#a}\else
+ \ifsecondargument\page_layouts_setup_text_two {#vertical}{#horizontal}\else
+ \page_layouts_setup_text_one {#vertical}\fi\fi\fi\fi\fi}
+
+%D Left and right texts are swapped on odd and even pages, but
+%D only when double sided typesetting is enabled.
+
+\unexpanded\def\page_layouts_process_element_double
+ {\doifelseoddpage
+ \page_layouts_process_element_double_odd
+ \page_layouts_process_element_double_even}
+
+\def\page_layouts_process_element_double_odd #lstyle#lcolor#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
+ {\page_layouts_process_element_single#lstyle#lcolor#lwidth{#lcontent}}
+
+\def\page_layouts_process_element_double_even#lstyle#color#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
+ {\page_layouts_process_element_single#rstyle#rcolor#rwidth{#rcontent}}
+
+%D The next macro will be cleaned up and made less messy and
+%D dependent.
+
+\let\m_page_layouts_element_content\empty
+
+\unexpanded\def\page_layouts_process_element_single#style#color#width#content%
+ {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx
+ \ifx\m_page_layouts_element_content\empty
+ % should not happen too often
+ \else
+ \page_layouts_process_element_single_indeed#style#color#width{#content}%
+ \fi}
+
+\setvalue{\??layouttextstrut\v!yes}{\setstrut\strut} % maybe more variants
+
+\def\page_layouts_process_element_single_indeed#style#color#width#content%
+ {\begingroup
+ \uselayoutelementstyleandcolor#style#color%
+ \csname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
+ \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
+ \lastnamedcs
+ \else
+ \edef\currentlayoutelementwidth{\layoutelementparameter#width}%
+ \ifx\currentlayoutelementwidth\empty
+ \expandafter\page_layouts_process_element_single_normal
+ \else
+ \expandafter\page_layouts_process_element_single_limited
+ \fi{#content}%
+ \fi
+ \endgroup}
+
+% {}{}{} prevents lookahead issues ... this will go away
+
+\def\page_layouts_process_element_single_normal#content%
+ {\doifelsemarking\m_page_layouts_element_content
+ {\getmarking[\m_page_layouts_element_content][\v!first]}
+ {\ignorecrlf#content{}{}{}}}
+
+\def\page_layouts_process_element_single_limited#content%
+ {\doifelsemarking\m_page_layouts_element_content
+ {\limitatetext{\getmarking[\m_page_layouts_element_content][\v!first]}\currentlayoutelementwidth\unknown}
+ {\ignorecrlf\limitatetext{#content{}{}{}}\currentlayoutelementwidth\unknown}}
+
+\setvalue{\??layouttextspecial\v!pagenumber}{\page_layouts_place_page_number}
+\setvalue{\??layouttextspecial\v!date }{\currentdate}
+
+%D When specified, the texts are automatically limited in
+%D length.
+
+% % where used ?
+%
+% \def\page_layouts_limitate_element_text#width%
+% {\edef\currentlayoutelementwidth{\layoutelementparameter#width}%
+% \ifx\currentlayoutelementwidth\empty
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\page_layouts_limitate_element_text_indeed
+% \fi}
+%
+% \def\page_layouts_limitate_element_text_indeed#content%
+% {\limitatetext{#content}\currentlayoutelementwidth\unknown}
+
+%D The placement of text is hooked into the token lists
+%D associated to the area at hand.
+
+\appendtoks \page_layouts_place_text_line\v!top \topheight \to \toptextcontent
+\appendtoks \page_layouts_place_text_line\v!header\headerheight \to \headertextcontent
+\appendtoks \page_layouts_place_text_line\v!text \textheight \to \texttextcontent
+\appendtoks \page_layouts_place_text_line\v!footer\footerheight \to \footertextcontent
+\appendtoks \page_layouts_place_text_line\v!bottom\bottomheight \to \bottomtextcontent
+
+%D Texts can be disabled, moved up and ignored, depending in
+%D the \type {status} variable. This is handled by the next
+%D couple of macros.
+
+\newcount\c_page_layouts_element_state_n
+
+\def\page_layouts_set_element_status#vertical%
+ {\c_page_layouts_element_state_n=0\namedlayoutelementparameter#vertical\c!n\relax
+ \ifcase\c_page_layouts_element_state_n
+ \edef\textlinestatus{\namedlayoutelementparameter#vertical\c!state}%
+ \else
+ \setxvalue{\namedlayoutelementhash#vertical\c!n}{\the\numexpr\c_page_layouts_element_state_n+\minusone}%
+ \let\textlinestatus\v!stop
+ \fi}
+
+\appendtoks
+ \doifinset\v!header\floatspecification{\setxvalue{\namedlayoutelementhash\v!header\c!n}{1}}%
+ \doifinset\v!footer\floatspecification{\setxvalue{\namedlayoutelementhash\v!footer\c!n}{1}}%
+\to \everybeforeflushedpagefloat
+
+\unexpanded\def\page_layouts_place_text_line#vertical%
+ {\page_layouts_set_element_status#vertical\relax
+ \ifcsname\??layouttextsline\textlinestatus\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\page_layouts_place_text_line_unknown
+ \fi#vertical}
+
+\unexpanded\def\doifelselayouttextline#vertical% shown or not
+ {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
+ \ifx\currentlayoutelementstate\v!normal
+ \expandafter\firstoftwoarguments
+ \else\ifx\currentlayoutelementstate\v!start
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\unexpanded\def\doifelselayoutsomeline#vertical% present or not
+ {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
+ \ifx\currentlayoutelementstate\v!none
+ \expandafter\secondoftwoarguments
+ \else\ifx\currentlayoutelementstate\v!high
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi\fi}
+
+\let\doiflayouttextlineelse\doifelselayouttextline
+\let\doiflayoutsomelineelse\doifelselayoutsomeline
+
+\newconditional\resyncaftertextline
+
+\setvalue{\??layouttextsline\v!normal}{\page_layouts_place_text_line_indeed}
+\setvalue{\??layouttextsline\empty }{\page_layouts_place_text_line_indeed}
+
+\letvalue{\??layouttextsline\v!none}\gobbletwoarguments
+\letvalue{\??layouttextsline\v!stop}\gobbletwoarguments
+
+\setvalue{\??layouttextsline\v!high}#vertical#height%
+ {\global\settrue\resyncaftertextline
+ \page_layouts_reset_element_status#vertical}
+
+\setvalue{\??layouttextsline\v!empty}#vertical#height%
+ {\page_layouts_reset_element_status#vertical}
+
+\setvalue{\??layouttextsline\v!start}#vertical#height%
+ {\page_layouts_reset_element_status#vertical%
+ \page_layouts_place_text_line_indeed#vertical#height}
+
+\setvalue{\??layouttextsline\v!nomarking}#vertical#height%
+ {\bgroup
+ \page_layouts_reset_element_status#vertical%
+ \settrue\inhibitgetmarking
+ \page_layouts_place_text_line_indeed#vertical#height%
+ \egroup}
+
+\def\page_layouts_place_text_line_unknown#vertical#height%
+ {\global\settrue\resyncaftertextline
+ \begingroup % new
+ \page_layouts_reset_element_status#vertical%
+ \csname\namedlayoutelementhash#vertical\textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!text \textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!margin\textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!edge \textlinestatus\endcsname
+ \page_layouts_place_text_line_indeed#vertical#height%
+ \endgroup}
+
+\letvalue{\??layouttextsline\s!unknown}\page_layouts_place_text_line_unknown
+
+%D The following macro has to be called after a page
+%D is flushed.
+
+\unexpanded\def\resetlayouttextlines % public
+ {\csname\??layouttextsreset\v!top \endcsname
+ \csname\??layouttextsreset\v!header\endcsname
+ \csname\??layouttextsreset\v!text \endcsname
+ \csname\??layouttextsreset\v!footer\endcsname
+ \csname\??layouttextsreset\v!bottom\endcsname
+ \ifconditional\resyncaftertextline
+ \calculateglobalvsizes
+ \page_backgrounds_recalculate
+ \global\setfalse\resyncaftertextline
+ \fi}
+
+\def\getspecificlayouttext#vertical#horizontal#what%
+ {\csname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname}
+
+% \settext[header][text][middle][xxx][yyy]
+
+\unexpanded\def\settextcontent
+ {\doquintupleempty\page_layouts_set_text_content}
+
+\def\page_layouts_set_text_content[#vertical][#horizontal][#one][#two][#three]% header text middle text/text
+ {\iffifthargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\executeifdefined{\??layouttextcontent\v!text:#one}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#three}}%
+ \else\iffourthargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\executeifdefined{\??layouttextcontent\v!text:#one}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#two}}%
+ \else\ifthirdargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#one}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#one}}%
+ \fi\fi\fi}
+
+\unexpanded\def\resettextcontent
+ {\dotripleempty\page_layouts_reset_text_content}
+
+\def\page_layouts_reset_text_content[#vertical][#horizontal][#tag]% header text middle
+ {\edef\currentlayoutelement{#vertical:#horizontal}%
+ \ifthirdargument
+ \letvalueempty{\layoutelementhash\executeifdefined{\??layouttextcontent\v!text:#tag}\c!middletext}%
+ \else\ifsecondargument
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!middletext
+ \resetlayoutelementparameter\c!righttext
+ \fi\fi}
+
+\letvalue{\??layouttextcontent\v!text:\c!middle}\c!middletext
+\letvalue{\??layouttextcontent\v!text:\c!left }\c!lefttext
+\letvalue{\??layouttextcontent\v!text:\c!right }\c!righttext
+
+%D The placement of a whole line is handled by the next two
+%D macros. These are hooked into the general purpose token
+%D list registers mentioned before.
+
+\def\page_layouts_place_text_line_indeed#vertical#height%
+ {\let\currentlayouttextline#vertical%
+ \ifdim#height>\zeropoint\relax % prevents pagenumbers when zero height
+ \page_layouts_place_text_line_left_or_right{#height}%
+ \fi}
+
+\def\page_layouts_place_text_line_left_or_right#height%
+ {\goleftonpage
+ \setbox\b_page_layouts_element\vbox to #height
+ {\vsize#height\relax
+ %\hsize\zeropoint % hack so that e.g. after=\hairline gives predictable results
+ \hsize\totaltextwidth
+ \normalbaselines
+ \let\\\ignoredlinebreak
+ \let\crlf\ignoredlinebreak
+ \namedlayoutelementparameter\currentlayouttextline\c!before
+ \doifbothsidesoverruled
+ \page_layouts_place_text_line_right
+ \page_layouts_place_text_line_right
+ \page_layouts_place_text_line_left
+ \namedlayoutelementparameter\currentlayouttextline\c!after
+ \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+ \dp\b_page_layouts_element\zeropoint
+ \box\b_page_layouts_element
+ \vskip-#height\relax}
+
+\let\page_layouts_extra_at_margin_left \plusone
+\let\page_layouts_extra_at_margin_right\plustwo
+
+\let\page_layouts_place_extra_text_left \relax % historic
+\let\page_layouts_place_extra_text_right\relax % historic
+
+\def\page_layouts_place_text_line_right
+ {\hpack
+ {\ifdim\leftedgewidth>\zeropoint
+ \page_layouts_left_edge_element\c!lefttext
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ %\page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_left
+ \page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \page_layouts_text_body_element\c!lefttext\c!middletext\c!righttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ %\page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_left
+ \page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ %\page_layouts_right_edge_element\c!lefttext
+ \page_layouts_right_edge_element\c!righttext
+ \fi}}
+
+\def\page_layouts_place_text_line_left
+ {\hpack
+ {\ifdim\leftedgewidth>\zeropoint
+ \page_layouts_left_edge_element\c!righttext
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ %\page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_right
+ \page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \page_layouts_text_body_element\c!righttext\c!middletext\c!lefttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ %\page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_right
+ \page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ %\page_layouts_right_edge_element\c!righttext
+ \page_layouts_right_edge_element\c!lefttext
+ \fi}}
+
+\def\page_layouts_left_edge_element#parameter%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
+ \page_layouts_place_element_indeed\leftedgewidth
+ {\hss\layoutelementparameter#parameter}%
+ \kern\leftedgedistance}
+
+\def\page_layouts_left_margin_element#parameter#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
+ \page_layouts_place_element_indeed\leftmarginwidth
+ {\hbox to \leftmarginwidth{\hss\layoutelementparameter#parameter}%
+ \ifnum#extrastate=\page_layouts_extra_at_margin_left
+ \kern-\leftmarginwidth
+ \hbox to \leftmarginwidth{\hss\layoutelementparameter\c!margintext}%
+ \fi}%
+ \kern\leftmargindistance}
+
+\def\page_layouts_text_body_element#left#middle#right#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!text}%
+ \page_layouts_place_element_indeed\makeupwidth
+ {\hbox to \makeupwidth{\ifnum#extrastate=\page_layouts_extra_at_margin_left\page_layouts_place_extra_text_left\fi\layoutelementparameter#left\hss}%
+ \kern-\makeupwidth
+ \hbox to \makeupwidth{\hss\layoutelementparameter#middle\hss}%
+ \kern-\makeupwidth
+ \hbox to \makeupwidth{\hss\layoutelementparameter#right\ifnum#extrastate=\page_layouts_extra_at_margin_right\page_layouts_place_extra_text_right\fi}}}
+
+\def\page_layouts_right_margin_element#parameter#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
+ \kern\rightmargindistance
+ \page_layouts_place_element_indeed\rightmarginwidth
+ {\hbox to \rightmarginwidth{\layoutelementparameter#parameter\hss}%
+ \ifnum#extrastate=\page_layouts_extra_at_margin_right
+ \kern-\rightmarginwidth
+ \hbox to \rightmarginwidth{\layoutelementparameter\c!margintext\hss}%
+ \fi}}
+
+\def\page_layouts_right_edge_element#parameter%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
+ \kern\rightedgedistance
+ \page_layouts_place_element_indeed\rightedgewidth
+ {\layoutelementparameter#parameter\hss}}
+
+\def\page_layouts_place_element_indeed#width#content%
+ {\vbox % to \vsize
+ {\hsize#width\relax
+ \layoutelementparameter\c!before
+ \setlayoutcomponentattribute\currentlayoutelement
+ \hbox \layoutcomponentboxattribute to #width{#content}%
+ \layoutelementparameter\c!after}}
+
+%D Although it is far better to use backgrounds for this
+%D purpose, one can add a rule in the following way. This
+%D method makes the rules disappear in case of an empty text
+%D line. Consider this a feature.
+%D
+%D \starttyping
+%D \setupheadertexts[left][right]
+%D
+%D \setupheader[text][after=\hrule,style=bold]
+%D
+%D \starttext
+%D \input tufte \page
+%D \setupheader[state=empty]
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+%D This code will move to \type {page-flt.tex}.
+
+\appendtoks \placerightmarginblock \kern-\rightmarginwidth \to \rightmargintextcontent
+\appendtoks \placeleftmarginblock \kern-\leftmarginwidth \to \leftmargintextcontent
+
+%D \macros
+%D {definetext}
+%D
+%D Some macros ago, we implemented the \type {status} option
+%D \type {unknown}. This one is used to take care of
+%D symbolic texts handlers.
+%D
+%D \showsetup{definetext}
+%D
+%D The next example demonstrates how we can use this
+%D mechanism to provide page (event) dependent text lines.
+%D
+%D \starttyping
+%D \definetext[chapter][footer][pagenumber]
+%D \setuphead[chapter][header=high,footer=chapter]
+%D \setupheadertexts[pagenumber]
+%D \setupfootertexts[left][right]
+%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
+%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
+%D \stoptyping
+
+\unexpanded\def\definetext
+ {\doseventupleempty\page_layouts_define_text}
+
+% \def\page_layouts_define_text[#tag][#vertical][#horizontal][#a][#b][#c][#d]%
+% {\ifseventhargument
+% \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}%
+% {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]}%
+% \else\ifsixthargument
+% \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+% {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c]}%
+% \else\iffifthargument
+% \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}%
+% {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b]}%
+% \else\iffourthargument
+% \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+% {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a]}%
+% \else
+% \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+% {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal]}%
+% \fi\fi\fi\fi}
+
+\def\page_layouts_define_text[#tag][#vertical][#horizontal][#a][#b][#c][#d]%
+ {\ifseventhargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_six {#vertical}{#horizontal}{#a}{#b}{#c}{#d}}%
+ \else\ifsixthargument
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_five {#vertical}{#horizontal}{#a}{#b}{#c}}%
+ \else\iffifthargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_four {#vertical}{#horizontal}{#a}{#b}}%
+ \else\iffourthargument
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_three{#vertical}{#horizontal}{#a}}%
+ \else
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_two {#vertical}{#horizontal}}%
+ \fi\fi\fi\fi}
+
+%D A few more page breakers:
+
+\installpagebreakmethod \v!empty
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}%
+ \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}%
+ \page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!header
+ {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}}
+
+\installpagebreakmethod \v!footer
+ {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}}
+
+%D While the header and footer lines are moved away from the
+%D main text, the top and bottom lines are centered.
+
+\setuplayoutelement[\v!top ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setuplayoutelement[\v!header][\c!state=\v!normal,\c!n=0,\c!before=, \c!after=\vss,\c!strut=\v!yes]
+\setuplayoutelement[\v!text ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setuplayoutelement[\v!footer][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=, \c!strut=\v!yes]
+\setuplayoutelement[\v!bottom][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+
+%D Moved here from strc-pag:
+
+% We reset a previous location but only when it has a pagenumber
+% associated. This is a rather messy test but better than the MkII
+% way where we use states and keep settings.
+
+\let\m_page_layouts_page_number_location \relax
+\let\m_page_layouts_page_number_location_v\relax
+\let\m_page_layouts_page_number_location_h\relax
+\let\m_page_layouts_page_number_location_x\relax
+
+\def\page_layouts_place_page_number % also elsewhere .. beware, not \unexpanded else
+ {\strc_pagenumbers_place_location} % test below fails
+
+\def\page_layouts_reset_page_number_location
+ {\ifx\m_page_layouts_page_number_location_v\relax\else
+ \edef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}%
+ \edef\page_layouts_previous_page_number_locator{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location_x}%
+ \doif{\meaning\page_layouts_previous_page_number_locator}{\meaning\page_layouts_place_page_number}
+ {\resetlayoutelementparameter\m_page_layouts_page_number_location_x}%
+ \fi}
+
+\def\page_layouts_set_page_number_location
+ {\edef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}%
+ \letlayoutelementparameter\m_page_layouts_page_number_location_x\page_layouts_place_page_number
+ \ifx\m_page_layouts_page_number_location_x\c!marginedgetext
+ \let\page_layouts_place_extra_text_left \page_layouts_place_page_number_left
+ \let\page_layouts_place_extra_text_right\page_layouts_place_page_number_right
+ \else
+ \let\page_layouts_place_extra_text_left \relax
+ \let\page_layouts_place_extra_text_right\relax
+ \fi}
+
+\def\page_layouts_identify_page_number_location
+ {\let\m_page_layouts_page_number_location_v\v!footer
+ \let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!middletext
+ \processallactionsinset[\directpagenumberingparameter\c!location]
+ [ \v!header=>\let\m_page_layouts_page_number_location_v\v!header,
+ \v!footer=>\let\m_page_layouts_page_number_location_v\v!footer,
+ \v!middle=>\let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!middletext,
+ \v!left=>\let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!lefttext,
+ \v!right=>\let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!righttext,
+ \v!inleft=>\let\m_page_layouts_page_number_location_h\v!margin
+ \let\m_page_layouts_page_number_location_x\c!lefttext,
+ \v!inright=>\let\m_page_layouts_page_number_location_h\v!margin
+ \let\m_page_layouts_page_number_location_x\c!righttext,
+ \v!inmargin=>\let\m_page_layouts_page_number_location_h\v!margin
+ \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi},
+ \v!margin=>\let\m_page_layouts_page_number_location_h\v!margin
+ \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi},
+ \v!atmargin=>\let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!marginedgetext,
+ \v!marginedge=>\let\m_page_layouts_page_number_location_h\v!text
+ \let\m_page_layouts_page_number_location_x\c!marginedgetext]}
+
+\unexpanded\def\strc_pagenumbers_set_location
+ {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}%
+ \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location
+ % unchanged
+ \else
+ \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location
+ \page_layouts_reset_page_number_location
+ \ifx\p_strc_pagenumbers_location\empty
+ % set otherwise
+ \else\ifx\p_strc_pagenumbers_location\v!none
+ % set otherwise
+ \else
+ \page_layouts_identify_page_number_location
+ \page_layouts_set_page_number_location
+ \fi\fi
+ \fi}
+
+\def\page_layouts_place_page_number_left % historic
+ {\begingroup
+ \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
+ \ifx\p_strc_pagenumbers_width\empty
+ \box\scratchbox\tfskip
+ \else
+ \hbox to \p_strc_pagenumbers_width{\box\scratchbox\hss}%
+ \fi
+ \fi
+ \endgroup}
+
+\def\page_layouts_place_page_number_right % historic
+ {\begingroup
+ \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
+ \ifx\p_strc_pagenumbers_width\empty
+ \tfskip\box\scratchbox
+ \else
+ \hbox to \p_strc_pagenumbers_width{\hss\box\scratchbox}%
+ \fi
+ \fi
+ \endgroup}
+
+\strc_pagenumbers_set_location % initializes
+
+% will go to page-box.mkiv
+
+% the next macros will be redone (less boxing)
+
+\newbox\b_page_layouts_element
+
+\def\page_layouts_insert_elements
+ {\ifcase\pageornamentstate
+ \page_layouts_place_elements_indeed
+ \fi}
+
+\def\page_layouts_place_elements_indeed
+ {\setbox\b_page_layouts_element\vpack
+ {\dontcomplain
+ \calculatereducedvsizes
+ \swapmargins
+ \offinterlineskip
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \the\toptextcontent
+ \vskip\dimexpr\topheight+\topdistance\relax
+ \the\headertextcontent
+ \vskip\dimexpr\headerheight+\headerdistance\relax
+ \anch_positions_place_anchors
+ \vskip-\textheight
+ \the\texttextcontent
+ \vskip\textheight
+ \the\everyendoftextbody
+ \vskip\footerdistance
+ \the\footertextcontent
+ \vskip\dimexpr\footerheight+\bottomdistance\relax
+ \the\bottomtextcontent
+ \vskip\bottomheight
+ \vfilll}%
+ \smashbox\b_page_layouts_element
+ \box\b_page_layouts_element}
+
+\def\page_insert_body#1#2%
+ {\setbox\b_page_layouts_element\vpack
+ {\offinterlineskip
+ \calculatereducedvsizes
+ \calculatehsizes
+ \swapmargins
+ \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
+ \dontleavehmode
+ \hbox to \makeupwidth
+ {\begingroup
+ \swapmargins
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \the\leftedgetextcontent
+ \kern\dimexpr\leftedgewidth+\leftedgedistance\relax
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \the\leftmargintextcontent
+ \kern\dimexpr\leftmarginwidth+\leftmargindistance\relax
+ \fi
+ \endgroup
+ \page_postprocessors_page{#2}%
+ \settextpagecontent\b_page_layouts_element{#1}{#2}%
+ \page_backgrounds_add_to_text\b_page_layouts_element
+ \page_grids_add_to_box\b_page_layouts_element
+ \box\b_page_layouts_element
+ \begingroup
+ \ifdim\rightmarginwidth>\zeropoint
+ \kern\rightmargindistance
+ \the\rightmargintextcontent
+ \kern\rightmarginwidth
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \kern\rightedgedistance
+ \the\rightedgetextcontent
+ \kern\rightedgewidth
+ \fi
+ \endgroup
+ \hss}}%
+ \smashbox\b_page_layouts_element
+ \box\b_page_layouts_element}
+
+%D The main text area has to be combined with some additional
+%D (tracing) information.
+
+% will be stored as normal and overloaded in page-lyr and later in
+% page-spr we overload the the stored version .. evenatually i will
+% clear up the experimental mess
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded
+ {\setbox#1\hbox to \makeupwidth % maybe \hpack
+ {\hss % so don't change this
+ \setlayoutcomponentattribute{\v!page:\v!text}%
+ \vbox \layoutcomponentboxattribute to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize <<< in columns?
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \page_otr_command_package_contents#2#3}%
+ \hss}%
+ \dp#1\zeropoint}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-var.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-var.mkiv
new file mode 100644
index 00000000000..1c7fd5b252d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-var.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=page-var,
+%D version=2011.12.05, % moved from other page-* files
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Variables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Variables}
+
+\unprotect
+
+% just for temporary moved variables
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/phys-dim.lua b/Master/texmf-dist/tex/context/base/mkiv/phys-dim.lua
new file mode 100644
index 00000000000..71c9b0bd40e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/phys-dim.lua
@@ -0,0 +1,969 @@
+if not modules then modules = { } end modules ['phys-dim'] = {
+ version = 1.001,
+ comment = "companion to phys-dim.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is pretty old code that I found back, but let's give it a try
+-- in practice. It started out as m-units.lua but as we want to keep that
+-- module around we moved the code to the dimensions module.
+--
+-- todo: maybe also an sciunit command that converts to si units (1 inch -> 0.0254 m)
+-- etc .. typical something to do when listening to a news whow or b-movie
+--
+-- todo: collect used units for logging (and list of units, but then we need
+-- associations too).
+
+-- The lists have been checked and completed by Robin Kirkham.
+
+-- dubious/wrong
+
+-- Atom = [[u]], -- should be amu (atomic mass unit)
+-- Bell = [[B]], -- should be bel
+-- Sterant = [[sr]], -- should be steradian
+-- Equivalent = [[eql]], -- qualifier?
+-- At = [[at]], -- qualifier?
+-- Force = [[f]], -- qualifier?
+-- eVolt = [[eV]],
+-- -- AC or DC voltages should be qualified in the text
+-- VoltAC = [[V\unitsbackspace\unitslower{ac}]],
+-- VoltDC = [[V\unitsbackspace\unitslower{dc}]],
+-- AC = [[V\unitsbackspace\unitslower{ac}]],
+-- DC = [[V\unitsbackspace\unitslower{dc}]],
+-- -- probably not harmful but there are better alternatives
+-- -- e.g., revolution per second (rev/s)
+-- RPS = [[RPS]],
+-- RPM = [[RPM]],
+-- RevPerSec = [[RPS]],
+-- RevPerMin = [[RPM]],
+
+local rawset, next = rawset, next
+local V, P, S, R, C, Cc, Cs, matchlpeg = lpeg.V, lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.match
+local format, lower = string.format, string.lower
+local appendlpeg = lpeg.append
+local utfchartabletopattern = lpeg.utfchartabletopattern
+local mergetable, mergedtable, keys, loweredkeys = table.merge, table.merged, table.keys, table.loweredkeys
+local setmetatablenewindex = table.setmetatablenewindex
+local utfchar = utf.char
+
+physics = physics or { }
+physics.units = physics.units or { }
+
+local allocate = utilities.storage.allocate
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local trace_units = false
+local report_units = logs.reporter("units")
+
+trackers.register("physics.units", function(v) trace_units = v end)
+
+-- digits parser (todo : use patterns)
+
+local math_one = Cs((P("$") /"") * (1-P("$"))^1 * (P("$")/"")) / context.m
+local math_two = Cs((P("\\m {")/"") * (1-P("}"))^1 * (P("}")/"")) / context.m -- watch the space after \m
+
+local digit = R("09")
+local sign = S("+-")
+local power = S("^e")
+local digitspace = S("~@_")
+local comma = P(",")
+local period = P(".")
+local semicolon = P(";")
+local colon = P(":")
+local signspace = P("/")
+local positive = P("++") -- was p
+local negative = P("--") -- was n
+local highspace = P("//") -- was s
+local padding = P("=")
+local plus = P("+")
+local minus = P("-")
+local space = P(" ")
+local lparent = P("(")
+local rparent = P(")")
+
+local lbrace = P("{")
+local rbrace = P("}")
+
+local digits = digit^1
+
+local powerdigits = plus * C(digits) / context.digitspowerplus
+ + minus * C(digits) / context.digitspowerminus
+ + C(digits) / context.digitspower
+
+local ddigitspace = digitspace / "" / context.digitsspace
+local ddigit = digits / context.digitsdigit
+local dsemicomma = semicolon / "" / context.digitsseparatorspace
+local dsemiperiod = colon / "" / context.digitsseparatorspace
+local dfinalcomma = comma / "" / context.digitsfinalcomma
+local dfinalperiod = period / "" / context.digitsfinalperiod
+local dintercomma = comma / "" / context.digitsintermediatecomma
+local dinterperiod = period / "" / context.digitsintermediateperiod
+local dskipcomma = comma / "" / context.digitsseparatorspace
+local dskipperiod = period / "" / context.digitsseparatorspace
+local dsignspace = signspace / "" / context.digitssignspace
+local dpositive = positive / "" / context.digitspositive
+local dnegative = negative / "" / context.digitsnegative
+local dhighspace = highspace / "" / context.digitshighspace
+local dsomesign = plus / "" / context.digitsplus
+ + minus / "" / context.digitsminus
+local dpower = power / "" * ( powerdigits + lbrace * powerdigits * rbrace )
+
+local dpadding = padding / "" / context.digitszeropadding -- todo
+
+local dleader = (dpositive + dnegative + dhighspace + dsomesign + dsignspace)^0
+local dtrailer = dpower^0
+local dfinal = P(-1) + #P(1 - comma - period - semicolon - colon)
+local dnumber = (ddigitspace + ddigit)^1
+
+-- ___,000,000 ___,___,000 ___,___,__0 000,000,000 000.00 000,000,000.00 000,000,000.==
+
+-- : ; for the moment not used, maybe for invisible fraction . , when no leading number
+
+-- local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___,
+-- * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000,
+-- * ddigitspace^0 * ddigit^0 -- _00 000
+-- * (
+-- dfinalperiod * ddigit -- .00
+-- + dskipperiod * dpadding^1 -- .==
+-- + dsemiperiod * ddigit -- :00
+-- + dsemiperiod * dpadding^1 -- :==
+-- )^0
+-- + ddigit -- 00
+--
+-- local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___.
+-- * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000.
+-- * ddigitspace^0 * ddigit^0 -- _00 000
+-- * (
+-- dfinalcomma * ddigit -- ,00
+-- + dskipcomma * dpadding^1 -- ,==
+-- + dsemicomma * ddigit -- :00
+-- + dsemicomma * dpadding^1 -- :==
+-- )^0
+-- + ddigit -- 00
+--
+-- fix by WS/SB (needs further testing)
+
+local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___,
+ * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000,
+ * ddigitspace^0 * ddigit^0 -- _00 000
+ * (
+ dfinalperiod * ddigit * (dintercomma * ddigit)^0 -- .00
+ + dskipperiod * dpadding^1 -- .==
+ + dsemiperiod * ddigit * (dintercomma * ddigit)^0 -- :00
+ + dsemiperiod * dpadding^1 -- :==
+ )^0
+ + ddigit -- 00
+
+local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___.
+ * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000.
+ * ddigitspace^0 * ddigit^0 -- _00 000
+ * (
+ dfinalcomma * ddigit * (dinterperiod * ddigit)^0 -- 00
+ + dskipcomma * dpadding^1 -- ,==
+ + dsemicomma * ddigit * (dinterperiod * ddigit)^0 -- :00
+ + dsemicomma * dpadding^1 -- :==
+ )^0
+ + ddigit -- 00
+
+local p_c_dparser = math_one + math_two + dleader * p_c * dtrailer * dfinal
+local c_p_dparser = math_one + math_two + dleader * c_p * dtrailer * dfinal
+
+local function makedigits(str,reverse)
+ if reverse then
+ matchlpeg(p_c_dparser,str)
+ else
+ matchlpeg(c_p_dparser,str)
+ end
+end
+
+-- tables:
+
+local long_prefixes = {
+
+ -- Le Système international d'unités (SI) 8e édition (Table 5)
+
+ Yocto = "yocto", -- 10^{-24}
+ Zepto = "zepto", -- 10^{-21}
+ Atto = "atto", -- 10^{-18}
+ Femto = "femto", -- 10^{-15}
+ Pico = "pico", -- 10^{-12}
+ Nano = "nano", -- 10^{-9}
+ Micro = "micro", -- 10^{-6}
+ Milli = "milli", -- 10^{-3}
+ Centi = "centi", -- 10^{-2}
+ Deci = "deci", -- 10^{-1}
+
+ Deca = "deca", -- 10^{1}
+ Hecto = "hecto", -- 10^{2}
+ Kilo = "kilo", -- 10^{3}
+ Mega = "mega", -- 10^{6}
+ Giga = "giga", -- 10^{9}
+ Tera = "tera", -- 10^{12}
+ Peta = "peta", -- 10^{15}
+ Exa = "exa", -- 10^{18}
+ Zetta = "zetta", -- 10^{21}
+ Yotta = "yotta", -- 10^{24}
+
+ -- IEC 60027-2: 2005, third edition, Part 2
+
+ Kibi = "kibi", -- 2^{10} (not ki)
+ Mebi = "mebi", -- 2^{20}
+ Gibi = "gibi", -- 2^{30}
+ Tebi = "tebi", -- 2^{40}
+ Pebi = "pebi", -- 2^{50}
+ Exbi = "exbi", -- 2^{60}
+
+ -- not standard
+
+ Zebi = "zebi", -- binary
+ Yobi = "yobi", -- binary
+
+ Micro = "micro",
+ Root = "root",
+}
+
+local long_units = {
+
+ -- Le Système international d'unités (SI) 8e édition (except synonyms)
+ -- SI base units (Table 1)
+
+ Meter = "meter",
+ Gram = "gram",
+ Second = "second",
+ Ampere = "ampere",
+ Kelvin = "kelvin",
+ Mole = "mole",
+ Candela = "candela",
+
+ -- synonyms
+
+ Mol = "mole",
+ Metre = "meter",
+
+ -- SI derived units with special names (Table 3)
+
+ Radian = "radian",
+ Steradian = "steradian",
+ Hertz = "hertz",
+ Newton = "newton",
+ Pascal = "pascal",
+ Joule = "joule",
+ Watt = "watt",
+ Coulomb = "coulomb",
+ Volt = "volt",
+ Farad = "farad",
+ Ohm = "ohm",
+ Siemens = "siemens",
+ Weber = "weber",
+ Tesla = "tesla",
+ Henry = "henry",
+ Celsius = "celsius",
+ Lumen = "lumen",
+ Lux = "lux",
+ Bequerel = "bequerel",
+ Gray = "gray",
+ Sievert = "sievert",
+ Katal = "katal",
+
+ -- non SI units accepted for use with SI (Table 6)
+
+ Minute = "minute",
+ Hour = "hour",
+ Day = "day",
+
+ -- (degree, minute, second of arc are treated specially later)
+
+ Gon = "gon",
+ Grad = "grad",
+ Hectare = "hectare",
+ Liter = "liter",
+
+ Tonne = "tonne",
+
+ -- synonyms
+
+ MetricTon = "tonne",
+ Litre = "liter",
+
+ ["Metric Ton"] = "tonne",
+
+ -- non-SI units whose values must be obtained experimentally (Table 7)
+
+ AtomicMassUnit = "atomicmassunit",
+ AstronomicalUnit = "astronomicalunit",
+ ElectronVolt = "electronvolt",
+ Dalton = "dalton",
+
+ ["Atomic Mass Unit"] = "atomicmassunit",
+ ["Astronomical Unit"] = "astronomicalunit",
+ ["Electron Volt"] = "electronvolt",
+
+ -- special cases (catch doubles, okay, a bit over the top)
+
+ DegreesCelsius = "celsius",
+ DegreesFahrenheit = "fahrenheit",
+ DegreeCelsius = "celsius",
+ DegreeFahrenheit = "fahrenheit",
+
+ ["Degrees Celsius"] = "celsius",
+ ["Degrees Fahrenheit"] = "fahrenheit",
+ ["Degree Celsius"] = "celsius",
+ ["Degree Fahrenheit"] = "fahrenheit",
+
+ -- too late as we already have connected symbols catched:
+ --
+ -- ["° Celsius"] = "celsius",
+ -- ["° Fahrenheit"] = "fahrenheit",
+ -- ["°Celsius"] = "celsius",
+ -- ["°Fahrenheit"] = "fahrenheit",
+
+ -- the "natural units" and "atomic units" are omitted for now
+ -- synonyms
+
+ eV = "electronvolt",
+ AMU = "atomicmassunit",
+
+ -- other non-SI units (Table 8)
+
+ Bar = "bar",
+ Hg = "mercury",
+ -- ["Millimetre Of Mercury"] = [[mmHg]],
+ Angstrom = "angstrom", -- strictly Ångström
+ NauticalMile = "nauticalmile",
+ Barn = "barn",
+ Knot = "knot",
+ Neper = "neper",
+ Bel = "bel", -- in practice only decibel used
+
+ ["Nautical Mile"] = "nauticalmile",
+
+ -- other non-SI units from CGS system (Table 9)
+
+ Erg = "erg",
+ Dyne = "dyne",
+ Poise = "poise",
+ Stokes = "stokes",
+ Stilb = "stilb",
+ Phot = "phot",
+ Gal = "gal",
+ Maxwell = "maxwell",
+ Gauss = "gauss",
+ Oersted = "oersted",
+
+ -- end of SI
+
+ -- data: for use with the binary prefixes (except Erlang)
+
+ Bit = "bit",
+ Byte = "byte" ,
+ Baud = "baud",
+ Erlang = "erlang",
+
+ -- common units, not part of SI
+
+ Atmosphere = "atmosphere",
+ Revolution = "revolution",
+
+ -- synonyms
+
+ Atm = "atmosphere",
+ Rev = "revolution",
+
+ -- imperial units (very incomplete)
+
+ Fahrenheit = "fahrenheit",
+ Foot = "foot",
+ Inch = "inch",
+ Calorie = "calorie",
+
+ -- synonyms
+
+ Cal = "calorie",
+
+}
+
+local long_operators = {
+
+ Times = "times",
+ Solidus = "solidus",
+ Per = "per",
+ OutOf = "outof",
+
+}
+
+local long_suffixes = {
+
+ Linear = "linear",
+ Square = "square",
+ Cubic = "cubic",
+ Quadratic = "quadratic",
+ Inverse = "inverse",
+ ILinear = "ilinear",
+ ISquare = "isquare",
+ ICubic = "icubic",
+ IQuadratic = "iquadratic",
+
+}
+
+local short_prefixes = {
+
+ y = "yocto",
+ z = "zetto",
+ a = "atto",
+ f = "femto",
+ p = "pico",
+ n = "nano",
+ u = "micro",
+ m = "milli",
+ c = "centi",
+ d = "deci",
+ da = "deca",
+ h = "hecto",
+ k = "kilo",
+ M = "mega",
+ G = "giga",
+ T = "tera",
+ P = "peta",
+ E = "exa",
+ Z = "zetta",
+ Y = "yotta",
+
+}
+
+local short_units = { -- I'm not sure about casing
+
+ m = "meter",
+ Hz = "hertz",
+ hz = "hertz",
+ B = "bel",
+ b = "bel",
+ lx = "lux",
+ -- da = "dalton",
+ h = "hour",
+ s = "second",
+ g = "gram",
+ n = "newton",
+ v = "volt",
+ t = "tonne",
+ l = "liter",
+ -- w = "watt",
+ W = "watt",
+ -- a = "ampere",
+ A = "ampere",
+
+ min = "minute",
+
+ [utfchar(0x2103)] = "celsius",
+ [utfchar(0x2109)] = "fahrenheit",
+}
+
+local short_operators = {
+ ["."] = "times",
+ ["*"] = "times",
+ ["/"] = "solidus",
+ [":"] = "outof",
+}
+
+local short_suffixes = { -- maybe just raw digit match
+ ["1"] = "linear",
+ ["2"] = "square",
+ ["3"] = "cubic",
+ ["4"] = "quadratic",
+ ["+1"] = "linear",
+ ["+2"] = "square",
+ ["+3"] = "cubic",
+ ["+4"] = "quadratic",
+ ["-1"] = "inverse",
+ ["-1"] = "ilinear",
+ ["-2"] = "isquare",
+ ["-3"] = "icubic",
+ ["-4"] = "iquadratic",
+ ["^1"] = "linear",
+ ["^2"] = "square",
+ ["^3"] = "cubic",
+ ["^4"] = "quadratic",
+ ["^+1"] = "linear",
+ ["^+2"] = "square",
+ ["^+3"] = "cubic",
+ ["^+4"] = "quadratic",
+ ["^-1"] = "inverse",
+ ["^-1"] = "ilinear",
+ ["^-2"] = "isquare",
+ ["^-3"] = "icubic",
+ ["^-4"] = "iquadratic",
+}
+
+local symbol_units = {
+ Degrees = "degree",
+ Degree = "degree",
+ -- Deg = "degree",
+ ["°"] = "degree",
+ ArcMinute = "arcminute",
+ ["′"] = "arcminute", -- 0x2032
+ ArcSecond = "arcsecond",
+ ["″"] = "arcsecond", -- 0x2033
+ Percent = "percent",
+ ["%"] = "percent",
+ Promille = "permille",
+ Permille = "permille",
+}
+
+local packaged_units = {
+ Micron = "micron",
+ mmHg = "millimetermercury",
+}
+
+-- rendering:
+
+local ctx_unitsPUS = context.unitsPUS
+local ctx_unitsPU = context.unitsPU
+local ctx_unitsPS = context.unitsPS
+local ctx_unitsP = context.unitsP
+local ctx_unitsUS = context.unitsUS
+local ctx_unitsU = context.unitsU
+local ctx_unitsS = context.unitsS
+local ctx_unitsO = context.unitsO
+local ctx_unitsN = context.unitsN
+local ctx_unitsC = context.unitsC
+local ctx_unitsQ = context.unitsQ
+local ctx_unitsNstart = context.unitsNstart
+local ctx_unitsNstop = context.unitsNstop
+local ctx_unitsNspace = context.unitsNspace
+
+local labels = languages.data.labels
+
+labels.prefixes = allocate {
+ yocto = { labels = { en = [[y]] } }, -- 10^{-24}
+ zepto = { labels = { en = [[z]] } }, -- 10^{-21}
+ atto = { labels = { en = [[a]] } }, -- 10^{-18}
+ femto = { labels = { en = [[f]] } }, -- 10^{-15}
+ pico = { labels = { en = [[p]] } }, -- 10^{-12}
+ nano = { labels = { en = [[n]] } }, -- 10^{-9}
+ micro = { labels = { en = [[\mu]] } }, -- 10^{-6}
+ milli = { labels = { en = [[m]] } }, -- 10^{-3}
+ centi = { labels = { en = [[c]] } }, -- 10^{-2}
+ deci = { labels = { en = [[d]] } }, -- 10^{-1}
+ deca = { labels = { en = [[da]] } }, -- 10^{1}
+ hecto = { labels = { en = [[h]] } }, -- 10^{2}
+ kilo = { labels = { en = [[k]] } }, -- 10^{3}
+ mega = { labels = { en = [[M]] } }, -- 10^{6}
+ giga = { labels = { en = [[G]] } }, -- 10^{9}
+ tera = { labels = { en = [[T]] } }, -- 10^{12}
+ peta = { labels = { en = [[P]] } }, -- 10^{15}
+ exa = { labels = { en = [[E]] } }, -- 10^{18}
+ zetta = { labels = { en = [[Z]] } }, -- 10^{21}
+ yotta = { labels = { en = [[Y]] } }, -- 10^{24}
+ kibi = { labels = { en = [[Ki]] } }, -- 2^{10} (not ki)
+ mebi = { labels = { en = [[Mi]] } }, -- 2^{20}
+ gibi = { labels = { en = [[Gi]] } }, -- 2^{30}
+ tebi = { labels = { en = [[Ti]] } }, -- 2^{40}
+ pebi = { labels = { en = [[Pi]] } }, -- 2^{50}
+ exbi = { labels = { en = [[Ei]] } }, -- 2^{60}
+ zebi = { labels = { en = [[Zi]] } }, -- binary
+ yobi = { labels = { en = [[Yi]] } }, -- binary
+ micro = { labels = { en = [[µ]] } }, -- 0x00B5 \textmu
+ root = { labels = { en = [[√]] } }, -- 0x221A
+}
+
+labels.units = allocate {
+ meter = { labels = { en = [[m]] } },
+ gram = { labels = { en = [[g]] } }, -- strictly kg is the base unit
+ second = { labels = { en = [[s]] } },
+ ampere = { labels = { en = [[A]] } },
+ kelvin = { labels = { en = [[K]] } },
+ mole = { labels = { en = [[mol]] } },
+ candela = { labels = { en = [[cd]] } },
+ mol = { labels = { en = [[mol]] } },
+ radian = { labels = { en = [[rad]] } },
+ steradian = { labels = { en = [[sr]] } },
+ hertz = { labels = { en = [[Hz]] } },
+ newton = { labels = { en = [[N]] } },
+ pascal = { labels = { en = [[Pa]] } },
+ joule = { labels = { en = [[J]] } },
+ watt = { labels = { en = [[W]] } },
+ coulomb = { labels = { en = [[C]] } },
+ volt = { labels = { en = [[V]] } },
+ farad = { labels = { en = [[F]] } },
+ ohm = { labels = { en = [[Ω]] } }, -- 0x2126 \textohm
+ siemens = { labels = { en = [[S]] } },
+ weber = { labels = { en = [[Wb]] } },
+ mercury = { labels = { en = [[Hg]] } },
+ millimetermercury = { labels = { en = [[mmHg]] } }, -- connected
+ tesla = { labels = { en = [[T]] } },
+ henry = { labels = { en = [[H]] } },
+ celsius = { labels = { en = [[\checkedtextcelsius]] } }, -- 0x2103
+ lumen = { labels = { en = [[lm]] } },
+ lux = { labels = { en = [[lx]] } },
+ bequerel = { labels = { en = [[Bq]] } },
+ gray = { labels = { en = [[Gy]] } },
+ sievert = { labels = { en = [[Sv]] } },
+ katal = { labels = { en = [[kat]] } },
+ minute = { labels = { en = [[min]] } },
+ hour = { labels = { en = [[h]] } },
+ day = { labels = { en = [[d]] } },
+ gon = { labels = { en = [[gon]] } },
+ grad = { labels = { en = [[grad]] } },
+ hectare = { labels = { en = [[ha]] } },
+ liter = { labels = { en = [[l]] } }, -- symbol l or L
+ tonne = { labels = { en = [[t]] } },
+ electronvolt = { labels = { en = [[eV]] } },
+ dalton = { labels = { en = [[Da]] } },
+ atomicmassunit = { labels = { en = [[u]] } },
+ astronomicalunit = { labels = { en = [[au]] } },
+ bar = { labels = { en = [[bar]] } },
+ angstrom = { labels = { en = [[Å]] } }, -- strictly Ångström
+ nauticalmile = { labels = { en = [[M]] } },
+ barn = { labels = { en = [[b]] } },
+ knot = { labels = { en = [[kn]] } },
+ neper = { labels = { en = [[Np]] } },
+ bel = { labels = { en = [[B]] } }, -- in practice only decibel used
+ erg = { labels = { en = [[erg]] } },
+ dyne = { labels = { en = [[dyn]] } },
+ poise = { labels = { en = [[P]] } },
+ stokes = { labels = { en = [[St]] } },
+ stilb = { labels = { en = [[sb]] } },
+ phot = { labels = { en = [[phot]] } },
+ gal = { labels = { en = [[gal]] } },
+ maxwell = { labels = { en = [[Mx]] } },
+ gauss = { labels = { en = [[G]] } },
+ oersted = { labels = { en = [[Oe]] } }, -- strictly Œrsted
+ bit = { labels = { en = [[bit]] } },
+ byte = { labels = { en = [[B]] } },
+ baud = { labels = { en = [[Bd]] } },
+ erlang = { labels = { en = [[E]] } },
+ atmosphere = { labels = { en = [[atm]] } },
+ revolution = { labels = { en = [[rev]] } },
+ fahrenheit = { labels = { en = [[\checkedtextfahrenheit]] } }, -- 0x2109
+ foot = { labels = { en = [[ft]] } },
+ inch = { labels = { en = [[inch]] } },
+ calorie = { labels = { en = [[cal]] } },
+ --
+ degree = { labels = { en = [[°]]} },
+ arcminute = { labels = { en = [[\checkedtextprime]] } }, -- ′ 0x2032
+ arcsecond = { labels = { en = [[\checkedtextdoubleprime]] } }, -- ″ 0x2033
+ percent = { labels = { en = [[\percent]] } },
+ permille = { labels = { en = [[\promille]] } },
+ --
+ micron = { labels = { en = [[\textmu m]] } },
+}
+
+labels.operators = allocate {
+ times = { labels = { en = [[\unitsTIMES]] } },
+ solidus = { labels = { en = [[\unitsSOLIDUS]] } },
+ per = { labels = { en = [[\unitsSOLIDUS]] } },
+ outof = { labels = { en = [[\unitsOUTOF]] } },
+}
+
+labels.suffixes = allocate {
+ linear = { labels = { en = [[1]] } },
+ square = { labels = { en = [[2]] } },
+ cubic = { labels = { en = [[3]] } },
+ quadratic = { labels = { en = [[4]] } },
+ inverse = { labels = { en = [[\mathminus1]] } },
+ ilinear = { labels = { en = [[\mathminus1]] } },
+ isquare = { labels = { en = [[\mathminus2]] } },
+ icubic = { labels = { en = [[\mathminus3]] } },
+ iquadratic = { labels = { en = [[\mathminus4]] } },
+}
+
+local function dimpus(p,u,s)
+ if trace_units then
+ report_units("prefix %a, unit %a, suffix %a",p,u,s)
+ end --
+ if p ~= "" then
+ if u ~= "" then
+ if s ~= "" then
+ ctx_unitsPUS(p,u,s)
+ else
+ ctx_unitsPU(p,u)
+ end
+ elseif s ~= "" then
+ ctx_unitsPS(p,s)
+ else
+ ctx_unitsP(p)
+ end
+ else
+ if u ~= "" then
+ if s ~= "" then
+ ctx_unitsUS(u,s)
+ -- elseif c then
+ -- ctx_unitsC(u)
+ else
+ ctx_unitsU(u)
+ end
+ elseif s ~= "" then
+ ctx_unitsS(s)
+ else
+ ctx_unitsP(p)
+ end
+ end
+end
+
+local function dimspu(s,p,u)
+ return dimpus(p,u,s)
+end
+
+local function dimop(o)
+ if trace_units then
+ report_units("operator %a",o)
+ end
+ if o then
+ ctx_unitsO(o)
+ end
+end
+
+local function dimsym(s)
+ if trace_units then
+ report_units("symbol %a",s)
+ end
+ s = symbol_units[s] or s
+ if s then
+ ctx_unitsC(s)
+ end
+end
+
+local function dimpre(p)
+ if trace_units then
+ report_units("prefix [%a",p)
+ end
+ p = packaged_units[p] or p
+ if p then
+ ctx_unitsU(p)
+ end
+end
+
+-- patterns:
+--
+-- space inside Cs else funny captures and args to function
+--
+-- square centi meter per square kilo seconds
+
+-- todo 0x -> rm
+
+local function update_parsers() -- todo: don't remap utf sequences
+
+ local all_long_prefixes = { }
+ local all_long_units = { }
+ local all_long_operators = { }
+ local all_long_suffixes = { }
+ local all_symbol_units = { }
+ local all_packaged_units = { }
+
+ for k, v in next, long_prefixes do all_long_prefixes [k] = v all_long_prefixes [lower(k)] = v end
+ for k, v in next, long_units do all_long_units [k] = v all_long_units [lower(k)] = v end
+ for k, v in next, long_operators do all_long_operators[k] = v all_long_operators[lower(k)] = v end
+ for k, v in next, long_suffixes do all_long_suffixes [k] = v all_long_suffixes [lower(k)] = v end
+ for k, v in next, symbol_units do all_symbol_units [k] = v all_symbol_units [lower(k)] = v end
+ for k, v in next, packaged_units do all_packaged_units[k] = v all_packaged_units[lower(k)] = v end
+
+ local somespace = P(" ")^0/""
+
+ local p_long_prefix = appendlpeg(all_long_prefixes,nil,true)
+ local p_long_unit = appendlpeg(all_long_units,nil,true)
+ local p_long_operator = appendlpeg(all_long_operators,nil,true)
+ local p_long_suffix = appendlpeg(all_long_suffixes,nil,true)
+ local p_symbol = appendlpeg(all_symbol_units,nil,true)
+ local p_packaged = appendlpeg(all_packaged_units,nil,true)
+
+ local p_short_prefix = appendlpeg(short_prefixes)
+ local p_short_unit = appendlpeg(short_units)
+ local p_short_operator = appendlpeg(short_operators)
+ local p_short_suffix = appendlpeg(short_suffixes)
+
+ -- more efficient but needs testing
+
+-- local p_long_prefix = utfchartabletopattern(all_long_prefixes) / all_long_prefixes
+-- local p_long_unit = utfchartabletopattern(all_long_units) / all_long_units
+-- local p_long_operator = utfchartabletopattern(all_long_operators) / all_long_operators
+-- local p_long_suffix = utfchartabletopattern(all_long_suffixes) / all_long_suffixes
+-- local p_symbol = utfchartabletopattern(all_symbol_units) / all_symbol_units
+-- local p_packaged = utfchartabletopattern(all_packaged_units) / all_packaged_units
+
+-- local p_short_prefix = utfchartabletopattern(short_prefixes) / short_prefixes
+-- local p_short_unit = utfchartabletopattern(short_units) / short_units
+-- local p_short_operator = utfchartabletopattern(short_operators) / short_operators
+-- local p_short_suffix = utfchartabletopattern(short_suffixes) / short_suffixes
+
+ -- we can can cleanup some space issues here (todo)
+
+ local unitparser = P { "unit",
+ --
+ longprefix = Cs(V("somespace") * p_long_prefix),
+ shortprefix = Cs(V("somespace") * p_short_prefix),
+ longsuffix = Cs(V("somespace") * p_long_suffix),
+ shortsuffix = Cs(V("somespace") * p_short_suffix),
+ shortunit = Cs(V("somespace") * p_short_unit),
+ longunit = Cs(V("somespace") * p_long_unit),
+ longoperator = Cs(V("somespace") * p_long_operator),
+ shortoperator = Cs(V("somespace") * p_short_operator),
+ packaged = Cs(V("somespace") * p_packaged),
+ --
+ nothing = Cc(""),
+ somespace = somespace,
+ nospace = (1-somespace)^1, -- was 0
+ -- ignore = P(-1),
+ --
+ qualifier = Cs(V("somespace") * (lparent/"") * (1-rparent)^1 * (rparent/"")),
+ --
+ somesymbol = V("somespace")
+ * (p_symbol/dimsym)
+ * V("somespace"),
+ somepackaged = V("somespace")
+ * (V("packaged") / dimpre)
+ * V("somespace"),
+ -- someunknown = V("somespace")
+ -- * (V("nospace")/ctx_unitsU)
+ -- * V("somespace"),
+ --
+ combination = V("longprefix") * V("longunit") -- centi meter
+ + V("nothing") * V("longunit")
+ + V("shortprefix") * V("shortunit") -- c m
+ + V("nothing") * V("shortunit")
+ + V("longprefix") * V("shortunit") -- centi m
+ + V("shortprefix") * V("longunit"), -- c meter
+
+-- combination = ( V("longprefix") -- centi meter
+-- + V("nothing")
+-- ) * V("longunit")
+-- + ( V("shortprefix") -- c m
+-- + V("nothing")
+-- + V("longprefix")
+-- ) * V("shortunit") -- centi m
+-- + ( V("shortprefix") -- c meter
+-- ) * V("longunit"),
+
+
+ dimension = V("somespace")
+ * (
+ V("packaged") / dimpre
+ + (V("longsuffix") * V("combination")) / dimspu
+ + (V("combination") * (V("shortsuffix") + V("nothing"))) / dimpus
+ )
+ * (V("qualifier") / ctx_unitsQ)^-1
+ * V("somespace"),
+ operator = V("somespace")
+ * ((V("longoperator") + V("shortoperator")) / dimop)
+ * V("somespace"),
+ snippet = V("dimension")
+ + V("somesymbol"),
+ unit = ( V("snippet") * (V("operator") * V("snippet"))^0
+ + V("somepackaged")
+ )^1,
+ }
+
+
+ -- local number = lpeg.patterns.number
+
+ local number = Cs( P("$") * (1-P("$"))^1 * P("$")
+ + P([[\m{]]) * (1-P("}"))^1 * P("}")
+ + (1-R("az","AZ")-P(" "))^1 -- todo: catch { } -- not ok
+ ) / ctx_unitsN
+
+ local start = Cc(nil) / ctx_unitsNstart
+ local stop = Cc(nil) / ctx_unitsNstop
+ local space = Cc(nil) / ctx_unitsNspace
+
+ -- todo: avoid \ctx_unitsNstart\ctx_unitsNstop (weird that it can happen .. now catched at tex end)
+
+ local p_c_combinedparser = P { "start",
+ number = start * dleader * (p_c_dparser + number) * stop,
+ rule = V("number")^-1 * unitparser,
+ space = space,
+ start = V("rule") * (V("space") * V("rule"))^0 + V("number")
+ }
+
+ local c_p_combinedparser = P { "start",
+ number = start * dleader * (c_p_dparser + number) * stop,
+ rule = V("number")^-1 * unitparser,
+ space = space,
+ start = V("rule") * (V("space") * V("rule"))^0 + V("number")
+ }
+
+ return p_c_combinedparser, c_p_combinedparser
+end
+
+local p_c_parser = nil
+local c_p_parser = nil
+local dirty = true
+
+local function makeunit(str,reverse)
+ if dirty then
+ if trace_units then
+ report_units("initializing parser")
+ end
+ p_c_parser, c_p_parser = update_parsers()
+ dirty = false
+ end
+ local ok
+ if reverse then
+ ok = matchlpeg(p_c_parser,str)
+ else
+ ok = matchlpeg(c_p_parser,str)
+ end
+ if not ok then
+ report_units("unable to parse: %s",str)
+ context(str)
+ end
+end
+
+local function trigger(t,k,v)
+ rawset(t,k,v)
+ dirty = true
+end
+
+local t_units = {
+ prefixes = setmetatablenewindex(long_prefixes,trigger),
+ units = setmetatablenewindex(long_units,trigger),
+ operators = setmetatablenewindex(long_operators,trigger),
+ suffixes = setmetatablenewindex(long_suffixes,trigger),
+ symbols = setmetatablenewindex(symbol_units,trigger),
+ packaged = setmetatablenewindex(packaged_units,trigger),
+}
+
+local t_shortcuts = {
+ prefixes = setmetatablenewindex(short_prefixes,trigger),
+ units = setmetatablenewindex(short_units,trigger),
+ operators = setmetatablenewindex(short_operators,trigger),
+ suffixes = setmetatablenewindex(short_suffixes,trigger),
+}
+
+physics.units.tables = allocate {
+ units = t_units,
+ shortcuts = t_shortcuts,
+}
+
+local mapping = {
+ prefix = "prefixes",
+ unit = "units",
+ operator = "operators",
+ suffixe = "suffixes",
+ symbol = "symbols",
+ packaged = "packaged",
+}
+
+local function registerunit(category,list)
+ if not list or list == "" then
+ list = category
+ category = "unit"
+ end
+ local t = t_units[mapping[category]]
+ if t then
+ for k, v in next, utilities.parsers.settings_to_hash(list or "") do
+ t[k] = v
+ end
+ end
+ -- inspect(tables)
+end
+
+physics.units.registerunit = registerunit
+
+implement { name = "digits_normal", actions = makedigits, arguments = "string" }
+implement { name = "digits_reverse", actions = makedigits, arguments = { "string", true } }
+implement { name = "unit_normal", actions = makeunit, arguments = "string"}
+implement { name = "unit_reverse", actions = makeunit, arguments = { "string", true } }
+implement { name = "registerunit", actions = registerunit, arguments = { "string", "string" } }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/phys-dim.mkiv b/Master/texmf-dist/tex/context/base/mkiv/phys-dim.mkiv
new file mode 100644
index 00000000000..3ea042b0570
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/phys-dim.mkiv
@@ -0,0 +1,810 @@
+%D \module
+%D [ file=phys-dim,
+%D version=2011-06-13, % was digits and units 1997.03.19,
+%D title=\CONTEXT\ Physics,
+%D subtitle=Digits and Units,
+%D author={Hans Hagen},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{phys-dim}{}
+
+% TAGGING NEEDS CHECKING ... WILL DO WHEN PARSER IS OK
+
+\unprotect
+
+%D \macros
+%D {digits, setdigitmode, setdigitsign}
+%D
+%D This is an update of the \MKII\ digits mechanism. Beware,
+%D space delimited mode is now resticted!
+%D
+%D Depending on the digit mode the command \type {\digits}
+%D normalizes number patterns depending on the language set.
+%D
+%D \starttyping
+%D This will never be a \digits{1.000.000} seller.
+%D \stoptyping
+%D
+%D We still support the space delimited case but this is only for special
+%D purposes. When used in the text, you'd better use the argument variant.
+%D
+%D \startbuffer
+%D 1 \setdigitmode {1} \setdigitorder{0} \digits {12.345,90}
+%D 2 \setdigitmode {2} \setdigitorder{0} \digits {12.345,90}
+%D 3 \setdigitmode {3} \setdigitorder{0} \digits {12.345,90}
+%D 4 \setdigitmode {4} \setdigitorder{0} \digits {12.345,90}
+%D 5 \setdigitmode {5} \setdigitorder{0} \digits {12.345,90}
+%D 6 \setdigitmode {6} \setdigitorder{0} \digits {12.345,90}
+%D 1 \setdigitmode {1} \setdigitorder{1} \digits {12.345,90}
+%D 2 \setdigitmode {2} \setdigitorder{1} \digits {12.345,90}
+%D 3 \setdigitmode {3} \setdigitorder{1} \digits {12.345,90}
+%D 4 \setdigitmode {4} \setdigitorder{1} \digits {12.345,90}
+%D 5 \setdigitmode {5} \setdigitorder{1} \digits {12.345,90}
+%D 6 \setdigitmode {6} \setdigitorder{1} \digits {12.345,90}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typeset as:
+%D
+%D \startlines \getbuffer \stoplines
+%D
+%D The sign can be typeset as is or within the space of a
+%D digit.
+%D
+%D \startbuffer
+%D \setdigitsign 0 \digits {+12.345,90}
+%D \setdigitsign 1 \digits {+12.345,90}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typset as:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The digit modes are:
+%D
+%D \startitemize[n,packed]
+%D \item periods/comma
+%D \item commas/period
+%D \item thinmuskips/comma
+%D \item thinmuskips/period
+%D \item thickmuskips/comma
+%D \item thickmuskips/period
+%D \stopitemize
+%D
+%D The digit parser handles a bunch of special characters as
+%D well as different formats. We strongly suggest you to use
+%D the grouped call.
+%D
+%D \starttabulate[|l|l|l|]
+%D \starttabulate[|l|l|l|]
+%D \NC \type{.} \NC , . \NC comma or period \NC \NR
+%D \NC \type{,} \NC , . \NC comma or period \NC \NR
+%D \NC \type{:} \NC \NC invisible period \NC \NR
+%D \NC \type{;} \NC \NC invisible comma \NC \NR
+%D \NC \type{_} \NC \NC invisible space \NC \NR
+%D \NC \type{/} \NC \NC invisible sign \NC \NR
+%D \NC \type{-} \NC $-$ \NC minus sign \NC \NR
+%D \NC \type{+} \NC $+$ \NC plus sign \NC \NR
+%D \NC \type{//} \NC \NC invisible high sign \NC \NR
+%D \NC \type{--} \NC $\negative$ \NC high minus sign \NC \NR
+%D \NC \type{++} \NC $\positive$ \NC high plus sign \NC \NR
+%D \NC \type{=} \NC $\zeroamount$ \NC zero padding \NC \NR
+%D \stoptabulate
+%D \stoptabulate
+%D
+%D These triggers are used in the following examples.
+%D
+%D \starttabulate[|l|r|]
+%D \NC \type{1} \NC \ruledhbox{\strut\digits{1}} \NC \NR
+%D \NC \type{12} \NC \ruledhbox{\strut\digits{12}} \NC \NR
+%D \NC \type{12.34} \NC \ruledhbox{\strut\digits{12.34}} \NC \NR
+%D \NC \type{123,456} \NC \ruledhbox{\strut\digits{123,456}} \NC \NR
+%D \NC \type{123,456.78} \NC \ruledhbox{\strut\digits{123,456.78}} \NC \NR
+%D \NC \type{12,34} \NC \ruledhbox{\strut\digits{12,34}} \NC \NR
+%D \NC \type{.1234} \NC \ruledhbox{\strut\digits{.1234}} \NC \NR
+%D \NC \type{1234} \NC \ruledhbox{\strut\digits{1234}} \NC \NR
+%D \NC \type{123,456.78^9} \NC \ruledhbox{\strut\digits{123,456.78^9}} \NC \NR
+%D \NC \type{123,456.78e9} \NC \ruledhbox{\strut\digits{123,456.78e9}} \NC \NR
+%D \NC \type{/123,456.78e-9} \NC \ruledhbox{\strut\digits{/123,456.78e-9}} \NC \NR
+%D \NC \type{-123,456.78e-9} \NC \ruledhbox{\strut\digits{-123,456.78e-9}} \NC \NR
+%D \NC \type{+123,456.78e-9} \NC \ruledhbox{\strut\digits{+123,456.78e-9}} \NC \NR
+%D \NC \type{//123,456.78e-9} \NC \ruledhbox{\strut\digits{//123,456.78e-9}} \NC \NR
+%D \NC \type{--123,456.78e-9} \NC \ruledhbox{\strut\digits{--123,456.78e-9}} \NC \NR
+%D \NC \type{++123,456.78e-9} \NC \ruledhbox{\strut\digits{++123,456.78e-9}} \NC \NR
+%D \NC \type{___,___,123,456,789.00} \NC \ruledhbox{\strut\digits{___,___,123,456,789.00}} \NC \NR
+%D \NC \type{___,___,_12,345,678.==} \NC \ruledhbox{\strut\digits{___,___,_12,345,678.==}} \NC \NR
+%D \stoptabulate
+
+\newconstant\c_phys_digits_order
+\newconstant\c_phys_digits_method
+\newconstant\c_phys_digits_sign % we has sized (text script scriptscript)
+
+\unexpanded\def\setdigitmethod#1{\c_phys_digits_method #1\relax}
+\unexpanded\def\setdigitsign #1{\c_phys_digits_sign #1\relax}
+\unexpanded\def\setdigitorder #1{\c_phys_digits_order #1\relax}
+
+\let\setdigitmode\setdigitmethod % compatibility
+
+\def\phys_digits_normalized % we could calculate once and remember
+ {\ifcase\c_phys_digits_sign
+ \expandafter\secondoftwoarguments
+ \else\ifmmode
+ \expandafter\expandafter\expandafter\phys_digits_normalized_math
+ \else
+ \expandafter\expandafter\expandafter\phys_digits_normalized_text
+ \fi\fi}
+
+\def\phys_digits_normalized_math#1#2%
+ {\setbox\scratchbox\hbox{\normalstartimath\Ustack{#1}\normalstopimath}%
+ \hbox to \wd\scratchbox{\hss{\normalstartimath\Ustack{#2}\normalstopimath}\hss}}
+
+\def\phys_digits_normalized_text#1#2%
+ {\setbox\scratchbox\hbox{#1}%
+ \hbox to \wd\scratchbox{\hss#2\hss}}
+
+\def\phys_digits_raised
+ {\ifmmode
+ \expandafter\normalsuperscript
+ \else
+ \expandafter\unitshigh
+ \fi}
+
+% we could use a symbolset but how many symbols are there ?
+
+% \definesymbol[units][times][\times]
+% \definesymbol[units][times][\cdots]
+
+% \def\digitstimessymbol{\symbol[units][times]}
+
+% \definesymbol[units][times][\times]
+% \definesymbol[units][times][\cdots]
+% \definesymbol[units][times][\invisibletimes]
+% \definesymbol[units][times][\ifmmode\cdot\else\kern.2\emwidth\cdot\kern.2\emwidth\fi]
+
+\unexpanded\def\digitstextbinop#1% assumes preceding
+ {\fourperemspace\nobreak\times\fourperemspace}
+
+%def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi}
+\def\digitstimessymbol{\ifmmode\times\else\digitstextbinop\times\fi}
+
+\unexpanded\def\digitszeropadding {\hphantom{0}}
+\unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}}
+\unexpanded\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}}
+\unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\mathematics{\negative}}}
+\unexpanded\def\digitspositive {\phys_digits_normalized{0}{\mathematics{\positive}}}
+%unexpanded\def\digitsminus {\phys_digits_normalized{0}{\mathematics{-}}}
+%unexpanded\def\digitsplus {\phys_digits_normalized{0}{\mathematics{+}}}
+\unexpanded\def\digitsminus {\phys_digits_normalized{0}{\mathminus}}
+\unexpanded\def\digitsplus {\phys_digits_normalized{0}{\mathplus }}
+\unexpanded\def\digitsspace {\hphantom{0}}
+\unexpanded\def\digitsseparatorspace{\hphantom{.}}
+\unexpanded\def\digitssignspace {\hphantom{\digitsminus}}
+\unexpanded\def\digitshighspace {\hphantom{\digitspositive}}
+\unexpanded\def\digitspower #1{\digitstimessymbol10\phys_digits_raised{#1}}
+\unexpanded\def\digitspowerplus #1{\digitstimessymbol10\phys_digits_raised{\digitsplus#1}}
+\unexpanded\def\digitspowerminus #1{\digitstimessymbol10\phys_digits_raised{\digitsminus#1}}
+\unexpanded\def\digitsdigit #1{#1}
+
+\unexpanded\def\normaldigitscommasymbol {,}
+\unexpanded\def\normaldigitsperiodsymbol{.}
+
+\let\normaldigitsseparatorspace\digitsseparatorspace
+
+\installcorenamespace{digitscomma}
+\installcorenamespace{digitsperiod}
+\installcorenamespace{digitsspace}
+
+\letvalue{\??digitscomma 0}\normaldigitscommasymbol
+\letvalue{\??digitsperiod0}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 0}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 1}\normaldigitsperiodsymbol
+\letvalue{\??digitsperiod1}\normaldigitscommasymbol
+\letvalue{\??digitsspace 1}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 2}\normaldigitscommasymbol
+\letvalue{\??digitsperiod2}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 2}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 3}\thinspace
+\letvalue{\??digitsperiod3}\normaldigitscommasymbol
+\letvalue{\??digitsspace 3}\thinspace
+
+\letvalue{\??digitscomma 4}\thinspace
+\letvalue{\??digitsperiod4}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 4}\thinspace
+
+\letvalue{\??digitscomma 5}\thickspace
+\letvalue{\??digitsperiod5}\normaldigitscommasymbol
+\letvalue{\??digitsspace 5}\thickspace
+
+\letvalue{\??digitscomma 6}\thickspace
+\letvalue{\??digitsperiod6}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 6}\thickspace
+
+\unexpanded\def\digitscommasymbol {\csname\??digitscomma \number\c_phys_digits_method\endcsname}
+\unexpanded\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname}
+\unexpanded\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname}
+
+% \unexpanded\def\digitsfinalcomma {\digitscommasymbol } % more for tracing
+% \unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing
+% \unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing
+% \unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing
+
+\unexpanded\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing
+\unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing
+\unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing
+\unexpanded\def\digitsintermediateperiod {\digitscommasymbol } % more for tracing
+
+%D The user macro:
+
+\unexpanded\def\phys_digits_indeed#1%
+ {\dontleavehmode
+ \begingroup
+ \ifcase\c_phys_digits_order\expandafter\clf_digits_normal\else\expandafter\clf_digits_reverse\fi{\detokenize{#1}}%
+ \endgroup
+ \settrue\c_phys_units_dospace}
+
+\unexpanded\def\digits
+ {\doifelsenextbgroup\phys_digits_argument\phys_digits_spaced}
+
+\def\phys_digits_argument#1%
+ {\phys_digits_indeed{#1}}
+
+\def\phys_digits_spaced#1 % space delimited
+ {\phys_digits_indeed{#1}}
+
+%D \macros
+%D {unit}
+%D
+%D We have been using the units module (and its predecessor) for over a decade
+%D now but when we moved on to \LUATEX\ a variant was prototyped that permits a
+%D less texie coding. I finally picked up that thread and cleaned up the code a
+%D bit so users can now play with it. (The main reason was that I wanted to
+%D test exporting.)
+%D
+%D \startbuffer
+%D 01: $10\unit{km/h}$
+%D 02: $\unit{10 km/h}$
+%D 03: \unit{km/h}
+%D 04: \unit{10 km/h}
+%D 05: \unit{10 km/h}
+%D 06: \unit{~1 km/h}
+%D 07: 10\unit{km/h}
+%D 08: 10 \unit{km/h}
+%D 09: $10 \unit{km/h}$
+%D 10: 10 \unit{KiloMeter/Hour}
+%D 11: 10 \unit{kilometer/hour}
+%D 12: 10 \unit{km/h}
+%D 13: 10 \unit{kilometer per hour}
+%D 14: 10 \unit{km / h}
+%D 15: 10 \unit{ km / h }
+%D 16: 10 \unit{km/ms2}
+%D 17: 10 \unit{meter per second}
+%D 18: 10 \unit{cubic meter}
+%D 19: 10 \unit{cubic meter per second}
+%D 21: 10 \unit{cubic meter / second}
+%D 22: $10 \unit{cubic meter / second}$
+%D 23: 30 \unit{kilo pascal }
+%D 24: 30 \unit{kilo pascal square meter / second}
+%D 25: 30 \unit{kilo pascal square meter / kelvin second}
+%D 26: \unit{30 kilo pascal square meter / kelvin second}
+%D 27: $30 \unit{kilo pascal square meter / kelvin second }$
+%D 28: 30 \unit{crap}
+%D 29: 30 \unit{AC}
+%D 30: $\frac{10 \unit{m/s}}{20 \unit{m/s}} $
+%D 31: {\ss 30 \unit{kilo pascal square meter / second kelvin}}
+%D 32: \unit{123.22^-3 km/s}
+%D 33: \unit{123.22e-3 km/s}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Result: \startlines \getbuffer \stoplines
+%D
+%D Depending on needs we can add more tweaks (also depends on to what
+%D extent we need to be compatible with \MKII.
+%D
+%D Formatting is supported too:
+%D
+%D \startbuffer
+%D \starttabulate[|l|l|l|]
+%D \HL
+%D \NC \unit{10 kilo gram} \NC \digits{10} \NC \unit{10} \NC \NR
+%D \NC \unit{1 kilogram} \NC \digits{1} \NC \unit{1} \NC \NR
+%D \NC \unit{0.1 kilogram} \NC \digits{0.1} \NC \unit{0.1} \NC \NR
+%D \NC \unit{1.1 kilogram} \NC \digits{1.1} \NC \unit{1.1} \NC \NR
+%D \NC \unit{11 kilogram} \NC \digits{11} \NC \unit{11} \NC \NR
+%D \HL
+%D \NC \unit{00,000.10 kilogram} \NC \digits{00,000.10} \NC \unit{00,000.10} \NC \NR
+%D \NC \unit{@@,@@0.10 kilogram} \NC \digits{@@,@@0.10} \NC \unit{@@,@@0.10} \NC \NR
+%D \NC \unit{__,___.10 kilogram} \NC \digits{__,___.10} \NC \unit{__,___.10} \NC \NR
+%D \NC \unit{__,__0:10 kilogram} \NC \digits{__,__0:10} \NC \unit{__,__0:10} \NC \NR
+%D \NC \unit{__,___:10 kilogram} \NC \digits{__,___:10} \NC \unit{__,___:10} \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Punctuation can be configures usiing \type {method}:
+%D
+%D \startbuffer
+%D \starttabulate[|l|l|l|]
+%D \HL
+%D \NC \NC \setupunits[method=0]\unit{00,000.10 kilogram} \NC \setupunits[method=0]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 1 \NC \setupunits[method=1]\unit{00,000.10 kilogram} \NC \setupunits[method=1]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 2 \NC \setupunits[method=2]\unit{00,000.10 kilogram} \NC \setupunits[method=2]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 3 \NC \setupunits[method=3]\unit{00,000.10 kilogram} \NC \setupunits[method=3]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 4 \NC \setupunits[method=4]\unit{00,000.10 kilogram} \NC \setupunits[method=4]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 5 \NC \setupunits[method=5]\unit{00,000.10 kilogram} \NC \setupunits[method=5]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 6 \NC \setupunits[method=6]\unit{00,000.10 kilogram} \NC \setupunits[method=6]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% only a space when a number is part of the unit
+
+\installcorenamespace {unit}
+\installcorenamespace {unitseparator}
+\installcorenamespace {unitspace}
+
+\installcommandhandler \??unit {unit} \??unit
+
+\setupunit
+ [\c!alternative=, % done: text
+ \c!separator=\v!normal, % done: cdot|big|medium|space
+ \s!language=\currentlanguage, % done: (no interface yet)
+ \c!order=\v!normal, % ,. (reverse: .,)
+ \c!method=0,
+ %\c!grid=\v!yes, % (maybe)
+ %\c!style=..., % done
+ %\c!color=..., % done
+ %\c!space=..., % (maybe) small medium big
+ ]
+
+\definehigh[unitshigh][\c!style=\txx]
+\definelow [unitslow] [\c!style=\txx]
+
+\let\setupunits\setupunit
+
+\newconstant \c_phys_units_mode % 0=text 1=math 2=textinmath 3=mathintext
+\newconstant \c_phys_units_state % 0=start 1=suffix 2=operator 3=unit 4=prefix 5=number
+\newconditional\c_phys_units_quantity
+\newconditional\c_phys_units_number
+\newconditional\c_phys_units_dospace
+
+% [\unit {micro ohm}]\par % no space before unit
+% [10\unit {micro ohm}]\par % no space before unit
+% [10 \unit{micro ohm}]\par % space before unit
+% [ \unit {micro ohm}]\par % space before unit
+% [\unit{10 micro ohm}]\par % space before unit
+
+\unexpanded\def\unitssmallspace {\thinspace}
+\unexpanded\def\unitsmediumspace{\medspace}
+\unexpanded\def\unitsbigspace {\thickspace}
+\unexpanded\def\unitsbackspace {\negthinspace}
+
+\unexpanded\def\installunitsseparator#1#2%
+ {\setvalue{\??unitseparator#1}{#2}}
+
+% \unexpanded\def\phys_units_separator
+% {\edef\currentunitsseparator{\unitparameter\c!separator}%
+% \csname\??unitseparator
+% \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi
+% \endcsname}
+
+\unexpanded\def\phys_units_separator
+ {\edef\currentunitsseparator{\unitparameter\c!separator}% no longer needed
+ \ifcsname\??unitseparator\currentunitsseparator\endcsname\lastnamedcs\else\cdot\fi}
+
+\installunitsseparator\v!normal {\cdot}
+\installunitsseparator\v!big {\unitsbigspace}
+\installunitsseparator\v!medium {\unitsmediumspace}
+\installunitsseparator\v!small {\unitssmallspace}
+\installunitsseparator\v!none {}
+
+\unexpanded\def\installunitsspace#1#2%
+ {\setvalue{\??unitspace#1}{#2}}
+
+% \unexpanded\def\phys_units_space
+% {\unskip % weird, why is unskip needed
+% \edef\currentunitsspace{\unitparameter\c!space}%
+% \csname\??unitspace
+% \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi
+% \endcsname}
+
+\unexpanded\def\phys_units_space
+ {\unskip % weird, why is unskip needed
+ \edef\currentunitsspace{\unitparameter\c!space}%
+ \ifcsname\??unitspace\currentunitsspace\endcsname\lastnamedcs\else\unitsmediumspace\fi}
+
+\installunitsspace\v!normal {\unitsmediumspace}
+\installunitsspace\v!big {\unitsbigspace}
+\installunitsspace\v!medium {\unitsmediumspace}
+\installunitsspace\v!small {\unitssmallspace}
+\installunitsspace\v!none {}
+
+\newtoks \everyunits % we keep the old \units command so we need a longer one
+
+\appendtoks
+ \disablemathpunctuation
+\to \everyunits
+
+\appendtoks
+ \setuevalue\currentunit{\phys_units_direct{\currentunit}}
+\to \everydefineunit
+
+\unexpanded\def\phys_units_direct#1%
+ {\begingroup
+ \ifdim\lastskip>\zeropoint
+ \settrue\c_phys_units_dospace
+ \removelastskip
+ \fi
+ \c_phys_digits_method\unitparameter\c!method\relax
+ \ifmmode\else\dontleavehmode\fi
+ \edef\currentunit{#1}%
+ \edef\unitlanguage{\unitparameter\s!language}%
+ \let\prefixlanguage\unitlanguage
+ \let\operatorlanguage\unitlanguage
+ \the\everyunits
+ %\removeunwantedspaces % not ok yet
+ \useunitstyleandcolor\c!style\c!color
+ \edef\currentunitsalternative{\unitparameter\c!alternative}%
+ \ifmmode
+ \ifx\currentunitsalternative\v!text
+ \expandafter\expandafter\expandafter\phys_units_direct_text_in_math
+ \else
+ \expandafter\expandafter\expandafter\phys_units_direct_math
+ \fi
+ \else
+ \ifx\currentunitsalternative\v!mathematics
+ \expandafter\expandafter\expandafter\phys_units_direct_math_in_text
+ \else
+ \expandafter\expandafter\expandafter\phys_units_direct_text
+ \fi
+ \fi}
+
+\unexpanded\def\phys_units_direct_text_in_math#1%
+ {\mathtext{%
+ \c_phys_units_mode\plustwo
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ }%
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_math#1%
+ {\c_phys_units_mode\plusone
+ \rm\tf % slow
+ \mathtf
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_text#1%
+ {\phys_units_indeed{#1}%
+ \phys_units_finish
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_math_in_text#1%
+ {\removeunwantedspaces % brr
+ \startimath
+ \c_phys_units_mode\plusthree
+ \rm\tf
+ \mathtf
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ \stopimath
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_nested#1#2%
+ {\phys_units_indeed{#2}}
+
+\appendtoks
+ \let\phys_units_direct\phys_units_direct_nested
+\to \everyunits
+
+\unexpanded\def\phys_units_indeed#1%
+ {\edef\p_order{\unitparameter\c!order}%
+ \ifx\p_order\v!reverse\expandafter\clf_unit_reverse\else\expandafter\clf_unit_normal\fi{\detokenize{#1}}}
+
+\unexpanded\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsPU #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree} % unit
+\unexpanded\def\unitsPS #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsUS #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsP #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour} % prefix
+\unexpanded\def\unitsU #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree} % unit
+\unexpanded\def\unitsS #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsO #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo} % operator
+\unexpanded\def\unitsN #1{\phys_units_start#1\c_phys_units_state\plusfive} % number
+\unexpanded\def\unitsC #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix} % connected
+\unexpanded\def\unitsQ #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount} %
+
+% Fonts can have a celsius and lack a fahrenheit symbol and as we want
+% to be consistent so we check for the counterparts as well. It's slow
+% but ok. Of course we could go virtual instead.
+
+\def\phys_units_text_prime {\textacute}
+\def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute}
+\def\phys_units_text_celsius {°C}
+\def\phys_units_text_fahrenheit {°F}
+
+\unexpanded\def\checkedtextprime
+ {\iffontchar\font"2032\relax\iffontchar\font"2033\relax
+ ′\else\phys_units_text_prime\fi\else\phys_units_text_prime
+ \fi}
+
+\unexpanded\def\checkedtextdoubleprime
+ {\iffontchar\font"2033\relax\iffontchar\font"2032\relax
+ ″\else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime
+ \fi}
+
+% \unexpanded\def\checkedtextcelsius
+% {\ifmmode
+% \phys_units_text_celsius
+% \else\iffontchar\font"2103\relax
+% ℃\else\phys_units_text_celsius
+% \fi\fi}
+%
+% \unexpanded\def\checkedtextfahrenheit
+% {\ifmmode
+% \phys_units_text_fahrenheit
+% \else\iffontchar\font"2109\relax
+% ℉\else\phys_units_text_fahrenheit
+% \fi\fi}
+%
+% % but, as users don't like this ...
+
+\let\checkedtextcelsius \phys_units_text_celsius
+\let\checkedtextfahrenheit\phys_units_text_fahrenheit
+
+\setelementnature[unit] [mixed]
+\setelementnature[quantity][mixed]
+
+\let\phys_units_finish\relax
+
+\unexpanded\def\unitsNstart
+ {\ifmmode \else
+ \settrue\c_phys_units_quantity
+ \dostarttagged\t!quantity\empty
+ \settrue\c_phys_units_number
+ \dostarttagged\t!number\empty
+ \fi}
+
+\unexpanded\def\unitsNstop
+ {\ifconditional\c_phys_units_number
+ \setfalse\c_phys_units_number
+ \dostoptagged
+ \fi
+ \c_phys_units_state\plusfive}
+
+% This is a hack: for some reason \unit{micro meter} like patterns give
+% \unitsNstart\unitsNstop so there is a buglet in the parser
+
+\let\unitsNstartindeed\unitsNstart
+
+\unexpanded\def\unitsNstart
+ {\doifelsenextchar\unitsNstop\gobbleoneargument\unitsNstartindeed}
+
+% End of hack.
+
+\unexpanded\def\unitsNspace
+ {\space}
+
+\unexpanded\def\unitsN#1%
+ {\unitsNstart#1\unitsNstop}
+
+\def\phys_units_start
+ {\ifmmode
+ \dostarttagged\t!mathaction\t!unit
+ \bgroup % make an mrow
+ \else
+ \dostarttagged\t!unit\empty
+ \fi
+ \let\phys_units_finish\phys_units_stop
+ \let\phys_units_start\relax}
+
+\def\phys_units_stop
+ {\ifconditional\c_phys_units_number
+ \setfalse\c_phys_units_number
+ \dostoptagged
+ \fi
+ \ifconditional\c_phys_units_quantity
+ \setfalse\c_phys_units_quantity
+ \dostoptagged
+ \fi
+ \dostoptagged
+ \ifmmode
+ \egroup
+ \fi}
+
+\def\unitsraise
+ {\ifcase\c_phys_units_mode
+ \expandafter\unitshigh
+ \or
+ \expandafter\normalsuperscript
+ \or
+ \expandafter\unitshigh
+ \or
+ \expandafter\normalsuperscript
+ \fi}
+
+\def\unitslower
+ {\ifcase\c_phys_units_mode
+ \expandafter\unitslow
+ \or
+ \expandafter\normalsubscript
+ \or
+ \expandafter\unitslow
+ \or
+ \expandafter\normalsubscript
+ \fi}
+
+\unexpanded\def\phys_units_next
+ {\ifcase\c_phys_units_state % start
+ \ifconditional\c_phys_units_dospace
+ % \ifdim\lastskip=\zeropoint
+ \phys_units_space
+ % \else
+ % % too tricky ... we could remove and add
+ % \fi
+ \fi
+ \or % 1: suffix
+ {\phys_units_separator}%
+ \or % 2: operator
+ \or % 3: unit
+ {\phys_units_separator}%
+ \or % 4: prefix
+ \or % 5: number
+ \phys_units_space
+ \or % 6: symbol (connected)
+ \fi
+ \setfalse\c_phys_units_dospace
+ \phys_units_start}
+
+\unexpanded\def\unitsTIMES
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \else
+ \unitssmallspace
+ \fi
+ \cdot} % or \times
+
+\unexpanded\def\unitsOUTOF
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \else
+ \unitssmallspace
+ \fi
+ :}
+
+\unexpanded\def\unitsSOLIDUS
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \unitsbackspace
+ \fi
+ {/}%
+ }%\unitsbackspace}
+
+\definelabelclass [unit] [2]
+\definelabelclass [operator] [2]
+\definelabelclass [prefix] [2]
+\definelabelclass [suffix] [2] % This is only a label because we want to show them in a table.
+
+\clf_definelabels{prefix}{prefixes}\s!false\relax
+\clf_definelabels{unit}{units}\s!false\relax
+\clf_definelabels{operator}{operators}\s!false\relax
+\clf_definelabels{suffix}{suffixes}\s!false\relax
+
+%D You can define additional units:
+%D
+%D \starttyping
+%D \registerunit
+%D [unit]
+%D [point=point,
+%D basepoint=basepoint,
+%D scaledpoint=scaledpoint,
+%D didot=didot,
+%D cicero=cicero]
+%D \stoptyping
+%D
+%D Possible categories are: \type {prefix}, \type {unit}, \type {operator},
+%D \type {suffix}, \type {symbol},\type {packaged}. You also need to define
+%D labels:
+%D
+%D \starttyping
+%D \setupunittext
+%D [point=pt,
+%D basepoint=bp,
+%D scaledpoint=sp,
+%D didot=dd,
+%D cicero=cc]
+%D \stoptyping
+
+\unexpanded\def\registerunit
+ {\dodoubleempty\phys_units_register}
+
+\def\phys_units_register[#1][#2]%
+ {\clf_registerunit{#1}{#2}}
+
+%D You can generate a list as follows:
+%D
+%D \starttyping
+%D \usemodule[phy-01]
+%D
+%D \ShowUnitsTable % [prefixes]
+%D \stoptyping
+
+%D Now we define the standard units command:
+
+\defineunit
+ [unit]
+
+%D Example:
+%D
+%D \startbuffer[definitions]
+%D \startluacode
+%D languages.data.labels.prefixes.whatever = {
+%D Kilo = "olik"
+%D }
+%D
+%D languages.data.labels.units.whatever = {
+%D Meter = "retem",
+%D Second = "dnoces",
+%D }
+%D
+%D languages.data.labels.operators.whatever = {
+%D Solidus = " rep "
+%D }
+%D \stopluacode
+%D \stopbuffer
+%D
+%D \startbuffer[sample]
+%D \startlines
+%D \lunit{10 km/s}
+%D \lunit{10 Kilo Meter/s}
+%D \lunit{10 kilo Meter/s}
+%D \lunit{10 Kilo m/s}
+%D \lunit{10 k Meter/s}
+%D \stoplines
+%D \stopbuffer
+%D
+%D \typebuffer[definitions] \getbuffer[definitions]
+%D
+%D \startbuffer
+%D \typebuffer[sample]
+%D
+%D \defineunits[lunit] \getbuffer[sample]
+%D \defineunits[lunit][label=test] \getbuffer[sample]
+%D \defineunits[lunit][label=whatever] \getbuffer[sample]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Another example:
+%D
+%D \starttyping
+%D \startluacode
+%D languages.data.labels.units.foo = {
+%D Liter = "l"
+%D }
+%D languages.data.labels.units.bar = {
+%D Liter = "L"
+%D }
+%D \stopluacode
+%D
+%D \defineunits[lunit] \lunit{10 l/s}\par
+%D \defineunits[funit][label=foo] \funit{10 l/s}\par
+%D \defineunits[bunit][label=bar] \bunit{10 l/s}\par
+%D \stoptyping
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/prop-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/prop-ini.mkiv
new file mode 100644
index 00000000000..3b1c59b245c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/prop-ini.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=prop-ini,
+%D version=2003.04.20,
+%D title=\CONTEXT\ Property 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 Property Macros / Initialization}
+
+%D This module is replaced by dedicated mechanisms. Originally properties were
+%D a sort of attributes in \MKII, but now we do things different anyway. We keep
+%D a surrogate mechanism around for compatibility reasons but even this will
+%D become obsolete some day.
+
+\unprotect
+
+\installcorenamespace{propertytypes}
+\installcorenamespace{propertydefiners}
+\installcorenamespace{propertystarters}
+
+\def\properties_obsolete_message
+ {\writestatus\m!system{properties are obsolete, use dedicated commands}%
+ \glet\properties_obsolete_message\donothing}
+
+\setvalue{\??propertydefiners\v!layer }[#1][#2][#3]{\defineviewerlayer[#1][#3]}
+\setvalue{\??propertydefiners\s!effect }[#1][#2][#3]{\defineeffect [#1][#3]}
+\setvalue{\??propertydefiners\v!negative}[#1][#2][#3]{}
+
+\unexpanded\def\defineproperty
+ {\dotripleempty\properties_define}
+
+\def\properties_define[#1][#2][#3]%
+ {\properties_obsolete_message
+ \setevalue{\??propertytypes#1}{#2}%
+ \getvalue{\??propertydefiners#2}[#1][#2][#3]}
+
+\setvalue{\??propertystarters\v!layer }#1{\let\properties_stop\stopviewerlayer\startviewerlayer[#1]}
+\setvalue{\??propertystarters\s!effect }#1{\let\properties_stop\stopeffect \starteffect [#1]}
+\setvalue{\??propertystarters\v!negative}#1{\let\properties_stop\stopnegative \startnegative }
+
+\unexpanded\def\property[#1]%
+ {\groupedcommand{\properties_start{#1}}\properties_stop}
+
+\unexpanded\def\startproperty[#1]%
+ {\properties_start{#1}}
+
+\unexpanded\def\stopproperty
+ {\properties_stop}
+
+\unexpanded\def\properties_start#1%
+ {\pushmacro\properties_stop
+ \getvalue{\??propertystarters\getvalue{\??propertytypes#1}}{#1}}
+
+\unexpanded\def\properties_stop
+ {\properties_stop
+ \popmacro\properties_stop}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua
new file mode 100644
index 00000000000..5ed25f288c3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua
@@ -0,0 +1,876 @@
+if not modules then modules = { } end modules ['publ-aut'] = {
+ 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"
+}
+
+if not characters then
+ dofile(resolvers.findfile("char-def.lua"))
+ dofile(resolvers.findfile("char-ini.lua"))
+end
+
+local lpeg = lpeg
+
+local type, next, tostring = type, next, tostring
+local concat = table.concat
+local utfchar = utf.char
+local utfsub = utf.sub
+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
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local context = context
+----- commands = commands
+
+local implement = interfaces.implement
+local ctx_setmacro = interfaces.setmacro
+
+local publications = publications
+
+local datasets = publications.datasets
+local getcasted = publications.getcasted
+
+local allocate = utilities.storage.allocate
+
+local chardata = characters.data
+
+local trace_hashing = false trackers.register("publications.authorhash", function(v) trace_hashing = v end)
+
+local report = logs.reporter("publications","authors")
+local report_cite = logs.reporter("publications","cite")
+
+local v_last = interfaces.variables.last
+
+-- local function makesplitter(separator)
+-- return Ct { "start",
+-- start = (Cs((V("outer") + (1-separator))^1) + separator^1)^1,
+-- start = Cs(V("outer")) + (Cs((V("inner") + (1-separator))^1) + separator^1)^1,
+-- outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^0) * (P("}")/""),
+-- inner = P("{") * ((V("inner") + P(1-P("}")))^0) * P("}"),
+-- }
+-- end
+
+-- authorlist = { authorspec and authorspec and authorspec }
+-- authorspec = composedname
+-- authorspec = surnames, firstnames
+-- authorspec = von, surnames, firstnames
+-- authorspec = von, surnames, jr, firstnames
+-- authorspec = von, surnames, jr, firstnames, initials
+
+local space = lpegpatterns.whitespace
+local comma = P(",")
+local period = P(".")
+local dash = P("-")
+local firstcharacter = lpegpatterns.utf8byte
+local utf8character = lpegpatterns.utf8character
+local p_and = space^1 * (P("and") + P("&&") + P("++")) * space^1
+local p_comma = space^0 * comma * space^0
+local p_space = space^1
+local p_shortone = C((utf8character -dash-period)^1)
+local p_longone = C( utf8character) * (1-dash-period)^0
+
+local p_empty = P("{}")/"" * #(p_space^0 * (P(-1) + P(",")))
+
+local andsplitter = Ct { "start",
+ start = (Cs((V("inner") + (1-p_and))^1) + p_and)^1,
+ inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"),
+}
+
+local commasplitter = Ct { "start",
+ start = Cs(V("outer")) + (p_empty + Cs((V("inner") + (1-p_comma))^1) + p_comma)^1,
+ outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^1) * (P("}")/""),
+ inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"),
+}
+
+local spacesplitter = Ct { "start",
+ start = Cs(V("outer")) + (Cs((V("inner") + (1-p_space))^1) + p_space)^1,
+ outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^1) * (P("}")/""),
+ inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"),
+}
+
+local p_initial = p_shortone * period * dash^0
+ + p_longone * (period + dash + P(-1))
+local initialsplitter = p_initial * P(-1) + Ct((p_initial)^1)
+
+local optionsplitter = Cf(Ct("") * Cg(C((1-space)^1) * space^0 * Cc(true))^1,rawset)
+
+local function is_upper(str)
+ local first = lpegmatch(firstcharacter,str)
+ local okay = chardata[first]
+ return okay and okay.category == "lu"
+end
+
+-- local cleaner = Cs( ( P("{}")/"" + P(1) )^1 )
+
+local cache = allocate() -- 33% reuse on tugboat.bib
+local nofhits = 0
+local nofused = 0
+
+publications.authorcache = cache
+
+local function makeinitials(firstnames)
+ if firstnames and #firstnames > 0 then
+ local initials = { }
+ for i=1,#firstnames do
+ initials[i] = lpegmatch(initialsplitter,firstnames[i])
+ end
+ return initials
+ end
+end
+
+local authormap = allocate()
+publications.authormap = authormap
+
+local function splitauthor(author)
+ local detail = cache[author]
+ if detail then
+ return detail
+ end
+ local remapped = authormap[author]
+ if remapped then
+ report("remapping %a to %a",author,remapped)
+ local detail = cache[remapped]
+ if detail then
+ cache[author] = detail
+ return detail
+ end
+ end
+ local author = remapped or author
+ local firstnames, vons, surnames, initials, juniors, options
+ local split = lpegmatch(commasplitter,author)
+ local n = #split
+ detail = {
+ original = author,
+ snippets = n,
+ }
+ if n == 1 then
+ -- {First Middle von Last}
+ local words = lpegmatch(spacesplitter,author)
+ firstnames, vons, surnames = { }, { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ if i <= n then
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ elseif #vons == 0 then
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ else
+ -- mess
+ end
+ if #surnames == 0 then
+ -- safeguard
+ firstnames = { }
+ vons = { }
+ surnames = { author }
+ else
+ initials = makeinitials(firstnames)
+ end
+ elseif n == 2 then
+ -- {Last, First}
+ -- {von Last, First}
+ firstnames, vons, surnames = { }, { }, { }
+ local words = lpegmatch(spacesplitter,split[1])
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ --
+ local words = lpegmatch(spacesplitter,split[2])
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ vons[#vons+1], i = words[i], i + 1
+ end
+ if surnames and firstnames and #surnames == 0 then
+ -- safeguard
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ end
+ initials = makeinitials(firstnames)
+ elseif n == 3 then
+ -- {von Last, First, Jr}
+ surnames = lpegmatch(spacesplitter,split[1])
+ juniors = lpegmatch(spacesplitter,split[2])
+ firstnames = lpegmatch(spacesplitter,split[3])
+ initials = makeinitials(firstnames)
+ elseif n == 4 then
+ -- {Von, Last, First, Jr}
+ vons = lpegmatch(spacesplitter,split[1])
+ surnames = lpegmatch(spacesplitter,split[2])
+ juniors = lpegmatch(spacesplitter,split[3])
+ firstnames = lpegmatch(spacesplitter,split[4])
+ initials = makeinitials(firstnames)
+ elseif n >= 5 then
+ -- {Von, Last, First, Jr, F.}
+ -- {Von, Last, First, Jr, Fr., options}
+ vons = lpegmatch(spacesplitter,split[1])
+ surnames = lpegmatch(spacesplitter,split[2])
+ juniors = lpegmatch(spacesplitter,split[3])
+ firstnames = lpegmatch(spacesplitter,split[4])
+ initials = lpegmatch(spacesplitter,split[5])
+ options = split[6]
+ if options then
+ options = lpegmatch(optionsplitter,options)
+ end
+ end
+ if firstnames and #firstnames > 0 then detail.firstnames = firstnames end
+ if vons and #vons > 0 then detail.vons = vons end
+ if surnames and #surnames > 0 then detail.surnames = surnames end
+ if initials and #initials > 0 then detail.initials = initials end
+ if juniors and #juniors > 0 then detail.juniors = juniors end
+ if options and next(options) then detail.options = options end
+ cache[author] = detail
+ nofhits = nofhits + 1
+ return detail
+end
+
+local function splitauthorstring(str)
+ if not str or str == "" then
+ return
+ end
+ nofused = nofused + 1
+
+ local remapped = authormap[str]
+ if remapped then
+ local detail = cache[remapped]
+ if detail then
+ cache[str] = detail
+ return { detail }
+ end
+ end
+
+ local authors = cache[str]
+ if authors then
+ return { authors } -- we assume one author
+ end
+
+ -- we could cache these too but it can become messy .. leave that for later
+
+ local authors = lpegmatch(andsplitter,str) or { } -- maybe fake an author
+ local nofauthors = #authors
+ for i=1,nofauthors do
+ authors[i] = splitauthor(authors[i])
+ end
+ if nofauthors > 1 and authors[nofauthors].original == "others" then
+ -- only the last one is looked at
+ authors[nofauthors] = nil
+ authors.others = true
+ end
+ return authors
+end
+
+publications.splitoneauthor = splitauthor
+publications.splitauthor = splitauthorstring
+
+local function the_initials(initials,symbol,connector)
+ if not symbol then
+ symbol = "."
+ end
+ if not connector then
+ connector = "-"
+ end
+ local result, r = { }, 0
+ for i=1,#initials do
+ local initial = initials[i]
+ if type(initial) == "table" then
+ local set, s = { }, 0
+ for i=1,#initial do
+ if i > 1 then
+ s = s + 1 ; set[s] = connector
+ end
+ s = s + 1 ; set[s] = initial[i]
+ s = s + 1 ; set[s] = symbol
+ end
+ r = r + 1 ; result[r] = concat(set)
+ else
+ r = r + 1 ; result[r] = initial .. symbol
+ end
+ end
+ return result
+end
+
+local ctx_btxsetconcat = context.btxsetconcat
+local ctx_btxsetoverflow = context.btxsetoverflow
+local ctx_btxsetinitials = context.btxsetinitials
+local ctx_btxsetfirstnames = context.btxsetfirstnames
+local ctx_btxsetvons = context.btxsetvons
+local ctx_btxsetsurnames = context.btxsetsurnames
+local ctx_btxsetjuniors = context.btxsetjuniors
+local ctx_btxciteauthorsetup = context.btxciteauthorsetup
+local ctx_btxlistauthorsetup = context.btxlistauthorsetup
+local ctx_btxsetauthorvariant = context.btxsetauthorvariant
+local ctx_btxstartauthor = context.btxstartauthor
+local ctx_btxstopauthor = context.btxstopauthor
+
+local concatstate = publications.concatstate
+local f_invalid = formatters["<invalid %s: %s>"]
+
+local currentauthordata = nil
+local currentauthorsymbol = nil
+
+local manipulators = typesetters.manipulators
+local splitmanipulation = manipulators.splitspecification
+local applymanipulation = manipulators.applyspecification
+local manipulatormethods = manipulators.methods
+
+local function value(i,field)
+ if currentauthordata then
+ local entry = currentauthordata[i]
+ if entry then
+ local value = entry[field]
+ if value and #value > 0 then
+ return value
+ end
+ end
+ end
+end
+
+implement { name = "btxcurrentfirstnames", arguments = "integer", actions = function(i) local v = value(i,"firstnames") if v then context(concat(v," ")) end end }
+implement { name = "btxcurrentinitials", arguments = "integer", actions = function(i) local v = value(i,"initials") if v then context(concat(the_initials(v,currentauthorsymbol))) end end }
+implement { name = "btxcurrentjuniors", arguments = "integer", actions = function(i) local v = value(i,"juniors") if v then context(concat(v," ")) end end }
+implement { name = "btxcurrentsurnames", arguments = "integer", actions = function(i) local v = value(i,"surnames") if v then context(concat(v," ")) end end }
+implement { name = "btxcurrentvons", arguments = "integer", actions = function(i) local v = value(i,"vons") if v then context(concat(v," ")) end end }
+
+local function btxauthorfield(i,field)
+ if currentauthordata then
+ local entry = currentauthordata[i]
+ if entry then
+ local manipulator, field = splitmanipulation(field)
+ local value = entry[field]
+ if not value or #value == 0 then
+ -- value, no need for message
+ elseif manipulator then
+ for i=1,#value do
+ if i > 1 then
+ context(" ")
+ end
+ context(applymanipulation(manipulator,value) or value)
+ end
+ elseif field == "initials" then
+ context(concat(the_initials(value,currentauthorsymbol)))
+ else
+ context(concat(value," "))
+ end
+ end
+ end
+end
+
+-- This is somewhat tricky: an author is not always an author but
+-- can also be a title or key, depending on the (optional) set it's
+-- in. Also, authors can be combined with years and so and they
+-- might be called upon mixed with other calls.
+
+local function btxauthor(dataset,tag,field,settings)
+ local split, usedfield, kind = getcasted(dataset,tag,field)
+ if kind == "author" then
+ local max = split and #split or 0
+ if max == 0 then
+ return
+ -- error
+ end
+ local absmax = max
+ local etallimit = tonumber(settings.etallimit) or 1000
+ local etaldisplay = tonumber(settings.etaldisplay) or etallimit
+ local etaloption = settings_to_hash(settings.etaloption or "")
+ local etallast = etaloption[v_last]
+ local combiner = settings.combiner
+ local symbol = settings.symbol
+ local index = settings.index
+ if not combiner or combiner == "" then
+ combiner = "normal"
+ end
+ if not symbol then
+ symbol = "."
+ end
+ local ctx_btxsetup = settings.kind == "cite" and ctx_btxciteauthorsetup or ctx_btxlistauthorsetup
+ if max > etallimit and (etaldisplay+(etallast and 1 or 0)) < max then
+ max = etaldisplay
+ else
+ etallast = false
+ end
+ currentauthordata = split
+ currentauthorsymbol = symbol
+
+ local function oneauthor(i,last,justone)
+ local author = split[i]
+ if index then
+ ctx_btxstartauthor(i,1,0)
+ elseif last then
+ ctx_btxstartauthor(i,1,0)
+ ctx_btxsetconcat(0)
+ ctx_btxsetauthorvariant(combiner)
+ else
+ local state = author.state or 0
+ ctx_btxstartauthor(i,max,state)
+ ctx_btxsetconcat(concatstate(i,max))
+ ctx_btxsetauthorvariant(combiner)
+ end
+ local initials = author.initials
+ if initials and #initials > 0 then
+ ctx_btxsetinitials() -- (concat(the_initials(initials,symbol)," "))
+ end
+ local firstnames = author.firstnames
+ if firstnames and #firstnames > 0 then
+ ctx_btxsetfirstnames() -- (concat(firstnames," "))
+ end
+ local vons = author.vons
+ if vons and #vons > 0 then
+ ctx_btxsetvons() -- (concat(vons," "))
+ end
+ local surnames = author.surnames
+ if surnames and #surnames > 0 then
+ ctx_btxsetsurnames() -- (concat(surnames," "))
+ end
+ local juniors = author.juniors
+ if juniors and #juniors > 0 then
+ ctx_btxsetjuniors() -- (concat(juniors," "))
+ end
+ if not index and i == max then
+ if split.others then
+ ctx_btxsetoverflow(1)
+ else
+ local overflow = #split - max
+ if overflow > 0 then
+ ctx_btxsetoverflow(overflow)
+ end
+ end
+ end
+ ctx_btxsetup(combiner)
+ ctx_btxstopauthor()
+ end
+ if index then
+ oneauthor(index)
+ elseif max == 1 then
+ oneauthor(1,false,true)
+ else
+ for i=1,max do
+ oneauthor(i)
+ end
+ if etallast then
+ oneauthor(absmax,true)
+ end
+ end
+ else
+ report("ignored field %a of tag %a, used field %a is no author",field,tag,usedfield)
+ end
+end
+
+implement {
+ name = "btxauthorfield",
+ actions = btxauthorfield,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "btxauthor",
+ actions = btxauthor,
+ arguments = {
+ "string",
+ "string",
+ "string",
+ {
+ { "combiner" },
+ { "kind" },
+ { "etallimit" },
+ { "etaldisplay" },
+ { "etaloption" },
+ { "symbol" },
+ }
+ }
+}
+
+local function components(snippet,short)
+ local vons = snippet.vons
+ local surnames = snippet.surnames
+ local initials = snippet.initials
+ local firstnames = not short and snippet.firstnames
+ local juniors = snippet.juniors
+ return
+ vons and #vons > 0 and concat(vons," ") or "",
+ surnames and #surnames > 0 and concat(surnames," ") or "",
+ initials and #initials > 0 and concat(the_initials(initials)," ") or "",
+ firstnames and #firstnames > 0 and concat(firstnames," ") or "",
+ juniors and #juniors > 0 and concat(juniors, " ") or ""
+end
+
+local collapsers = allocate { }
+
+publications.authorcollapsers = collapsers
+
+local function default(author) -- one author
+ local hash = author.hash
+ if hash then
+ return hash
+ end
+ local original = author.original
+ local vons = author.vons
+ local surnames = author.surnames
+ local initials = author.initials
+ local firstnames = author.firstnames
+ local juniors = author.juniors
+ local result = { }
+ local nofresult = 0
+ if vons and #vons > 0 then
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
+ end
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ if initials and #initials > 0 then
+ initials = the_initials(initials)
+ for j=1,#initials do
+ nofresult = nofresult + 1
+ result[nofresult] = initials[j]
+ end
+ end
+ if firstnames and #firstnames > 0 then
+ for j=1,#firstnames do
+ nofresult = nofresult + 1
+ result[nofresult] = firstnames[j]
+ end
+ end
+ if juniors and #juniors > 0 then
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
+ local hash = concat(result," ")
+ if trace_hashing then
+ report("hash: %s -> %s",original,hash)
+ end
+ author.hash = hash
+ return hash
+end
+
+local authorhashers = { }
+publications.authorhashers = authorhashers
+
+-- todo: some hashing
+
+local function name(authors)
+ if type(authors) == "table" then
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local surnames = author.surnames
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ end
+ return concat(result," ")
+ else
+ return authors
+ end
+end
+
+table.setmetatableindex(authorhashers,function(t,k)
+ t[k] = name
+ return name
+end)
+
+authorhashers.normal = function(authors)
+ if type(authors) == "table" then
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local vons = author.vons
+ local surnames = author.surnames
+ local firstnames = author.firstnames
+ local juniors = author.juniors
+ if vons and #vons > 0 then
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
+ end
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ if firstnames and #firstnames > 0 then
+ for j=1,#firstnames do
+ nofresult = nofresult + 1
+ result[nofresult] = firstnames[j]
+ end
+ end
+ if juniors and #juniors > 0 then
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
+ end
+ return concat(result," ")
+ else
+ return authors
+ end
+end
+
+authorhashers.normalshort = function(authors)
+ if type(authors) == "table" then
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local vons = author.vons
+ local surnames = author.surnames
+ local initials = author.initials
+ local juniors = author.juniors
+ if vons and #vons > 0 then
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
+ end
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ if initials and #initials > 0 then
+ initials = the_initials(initials)
+ for j=1,#initials do
+ nofresult = nofresult + 1
+ result[nofresult] = initials[j]
+ end
+ end
+ if juniors and #juniors > 0 then
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
+ end
+ return concat(result," ")
+ else
+ return authors
+ end
+end
+
+authorhashers.normalinverted = authorhashers.normal
+authorhashers.invertedshort = authorhashers.normalshort
+
+local p_clean = Cs ( (
+ P("\\btxcmd") / "" -- better keep the argument
+ + S("`~!@#$%^&*()_-+={}[]:;\"\'<>,.?/|\\") / ""
+ + lpeg.patterns.utf8character
+ )^1)
+
+authorhashers.short = function(authors)
+ -- a short is a real dumb hardcodes 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
+ local n = #authors
+ if n == 0 then
+ return "unk"
+ elseif n == 1 then
+ local surnames = authors[1].surnames
+ if not surnames or #surnames == 0 then
+ return "err"
+ else
+ local s = surnames[1]
+ local c = lpegmatch(p_clean,s)
+ if trace_hashing and s ~= c then
+ report_cite("name %a cleaned to %a for short construction",s,c)
+ end
+ return utfsub(c,1,3)
+ end
+ else
+ local t = { }
+ for i=1,n do
+ if i > 3 then
+ t[#t+1] = "+" -- indeed
+ break
+ end
+ local surnames = authors[i].surnames
+ if not surnames or #surnames == 0 then
+ t[#t+1] = "?"
+ else
+ local s = surnames[1]
+ local c = lpegmatch(p_clean,s)
+ if s ~= c then
+ report_cite("name %a cleaned to %a for short construction",s,c)
+ end
+ t[#t+1] = utfsub(c,1,1)
+ end
+ end
+ return concat(t)
+ end
+ else
+ return utfsub(authors,1,3)
+ end
+end
+
+collapsers.default = default
+
+local function authorwriter(key,index)
+ if not key then
+ return ""
+ end
+ if type(key) == "string" then
+ return key
+ end
+ local n = #key
+ if n == 0 then
+ return ""
+ end
+ if index then
+ if not key[index] then
+ return ""
+ end
+ elseif n == 1 then
+ index = 1
+ end
+ if index then
+ local author = key[index]
+ local options = author.options
+ if options then
+ for option in next, options do
+ local collapse = collapsers[option]
+ if collapse then
+ return collapse(author)
+ end
+ end
+ end
+ local hash = default(author)
+ -- if trace_hashing then
+ -- report("hash: %s",hash)
+ -- end
+ return hash
+ end
+ local t = { }
+ local s = 0
+ for i=1,n do
+ local author = key[i]
+ local options = author.options
+ s = s + 1
+ if options then
+ local done = false
+ for option in next, options do
+ local collapse = collapsers[option]
+ if collapse then
+ t[s] = collapse(author)
+ done = true
+ end
+ end
+ if not done then
+ t[s] = default(author)
+ end
+ else
+ t[s] = default(author)
+ end
+ end
+ local hash = concat(t," & ")
+ -- if trace_hashing then
+ -- report("hash: %s",hash)
+ -- end
+ return hash
+end
+
+local function writer(key)
+ return authorwriter(key) -- discard extra arguments in the caller
+end
+
+publications.writers .author = writer
+publications.casters .author = splitauthorstring
+publications.components.author = components
+
+-- sharedmethods.author = {
+-- { field = "key", default = "", unknown = "" },
+-- { field = "author", default = "", unknown = "" },
+-- { field = "title", default = "", unknown = "" },
+-- }
+
+-- Analysis of the APA by Alan:
+--
+-- first : key author editor publisher title journal volume number pages
+-- second: year suffix title month day journal volume number
+
+publications.sortmethods.authoryear = {
+ sequence = {
+ -- { field = "key", default = "ZZZZ", unknown = "ZZZZ" },
+ { field = "author", default = "", unknown = "" },
+ { field = "year", default = "9998", unknown = "9999" },
+ -- { field = "suffix", default = " ", unknown = " " },
+ { field = "month", default = "13", unknown = "14" },
+ { field = "day", default = "32", unknown = "33" },
+ { field = "journal", default = "", unknown = "" },
+ { field = "volume", default = "", unknown = "" },
+ -- { field = "number", default = "", unknown = "" },
+ { field = "pages", default = "", unknown = "" },
+ { field = "title", default = "", unknown = "" },
+ { field = "index", default = "", unknown = "" },
+ },
+}
+
+implement {
+ name = "btxremapauthor",
+ arguments = { "string", "string" },
+ actions = function(k,v)
+ publications.authormap[k] = v
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua
new file mode 100644
index 00000000000..b9c43ac4486
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua
@@ -0,0 +1,1210 @@
+if not modules then modules = { } end modules ['publ-dat'] = {
+ 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"
+}
+
+-- todo: strip the @ in the lpeg instead of on do_definition and do_shortcut
+-- todo: store bibroot and bibrootdt
+-- todo: dataset = datasets[dataset] => current = datasets[dataset]
+-- todo: maybe split this file
+
+--[[ldx--
+<p>This is a prelude to integrated bibliography support. This file just loads
+bibtex files and converts them to xml so that the we access the content
+in a convenient way. Actually handling the data takes place elsewhere.</p>
+--ldx]]--
+
+if not characters then
+ dofile(resolvers.findfile("char-utf.lua"))
+ dofile(resolvers.findfile("char-tex.lua"))
+end
+
+local chardata = characters.data
+local lowercase = characters.lower
+
+local lower, find, sub = string.lower, string.find, string.sub
+local concat, copy, tohash = table.concat, table.copy, table.tohash
+local next, type, rawget = next, type, rawget
+local utfchar = utf.char
+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 xmlcollected, xmltext, xmlconvert = xml.collected, xml.text, xml.convert
+local setmetatableindex = table.setmetatableindex
+
+-- todo: more allocate
+
+local P, R, S, V, C, Cc, Cs, Ct, Carg, Cmt, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg, lpeg.Cmt, lpeg.Cp
+
+local p_whitespace = lpegpatterns.whitespace
+local p_utf8character = lpegpatterns.utf8character
+
+local trace = false trackers.register("publications", function(v) trace = v end)
+local trace_duplicates = true trackers.register("publications.duplicates", function(v) trace = v end)
+
+local report = logs.reporter("publications")
+local report_duplicates = logs.reporter("publications","duplicates")
+
+local allocate = utilities.storage.allocate
+
+local commands = commands
+local implement = interfaces and interfaces.implement
+
+publications = publications or { }
+local publications = publications
+
+local datasets = publications.datasets or { }
+publications.datasets = datasets
+
+local writers = publications.writers or { }
+publications.writers = writers
+
+local tables = publications.tables or { }
+publications.tables = tables
+
+publications.statistics = publications.statistics or { }
+local publicationsstats = publications.statistics
+
+local loaders = publications.loaders or { }
+publications.loaders = loaders
+
+local casters = { }
+publications.casters = casters
+
+-- local sorters = { }
+-- publications.sorters = sorters
+--
+-- local indexers = { }
+-- publications.indexers = indexers
+
+local components = { }
+publications.components = components -- register components
+
+local enhancers = publications.enhancers or { }
+publications.enhancers = enhancers
+
+local enhancer = publications.enhancer or utilities.sequencers.new { arguments = "dataset" }
+publications.enhancer = enhancer
+
+utilities.sequencers.appendgroup(enhancer,"system") -- private
+
+publicationsstats.nofbytes = 0
+publicationsstats.nofdefinitions = 0
+publicationsstats.nofshortcuts = 0
+publicationsstats.nofdatasets = 0
+
+local privates = allocate {
+ category = true,
+ tag = true,
+ index = true,
+ suffix = true,
+ specification = true,
+}
+
+local specials = allocate {
+ key = true,
+ crossref = true,
+ keywords = true,
+ language = true,
+ comment = true,
+}
+
+local implicits = allocate {
+ category = "implicit",
+ tag = "implicit",
+ key = "implicit",
+ keywords = "implicit",
+ language = "implicit",
+ crossref = "implicit",
+}
+
+local origins = allocate {
+ "optional",
+ "extra",
+ "required",
+ "virtual",
+}
+
+local virtuals = allocate {
+ "authoryear",
+ "authoryears",
+ "authornum",
+ "num",
+ "suffix",
+}
+
+local defaulttypes = allocate {
+ author = "author",
+ editor = "author",
+ publisher = "author",
+ page = "pagenumber",
+ pages = "pagenumber",
+ keywords = "keyword",
+ doi = "url",
+ url = "url",
+}
+
+local defaultsets = allocate {
+ page = { "page", "pages" },
+}
+
+tables.implicits = implicits
+tables.origins = origins
+tables.virtuals = virtuals
+tables.types = defaulttypes
+tables.sets = defaultsets
+tables.privates = privates
+tables.specials = specials
+
+local variables = interfaces and interfaces.variables or setmetatableindex("self")
+
+local v_all = variables.all
+local v_default = variables.default
+
+if not publications.usedentries then
+ function publications.usedentries()
+ return { }
+ end
+end
+
+local xmlplaceholder = "<?xml version='1.0' standalone='yes'?>\n<bibtex></bibtex>"
+
+local defaultshortcuts = allocate {
+ jan = "1",
+ feb = "2",
+ mar = "3",
+ apr = "4",
+ may = "5",
+ jun = "6",
+ jul = "7",
+ aug = "8",
+ sep = "9",
+ oct = "10",
+ nov = "11",
+ dec = "12",
+}
+
+local space = p_whitespace^0
+local separator = space * "+" * space
+local l_splitter = lpeg.tsplitat(separator)
+local d_splitter = lpeg.splitat (separator)
+
+local unknownfield = function(t,k)
+ local v = "extra"
+ t[k] = v
+ return v
+end
+
+local unknowncategory = function(t,k)
+ local v = {
+ required = false,
+ optional = false,
+ virtual = false,
+ fields = setmetatableindex(unknownfield), -- this will remember them
+ types = unknowntypes,
+ sets = setmetatableindex(defaultsets), -- new, but rather small
+ }
+ t[k] = v
+ return v
+end
+
+local unknowntype = function(t,k)
+ local v = "string"
+ t[k] = v
+ return v
+end
+
+local default = {
+ name = name,
+ version = "1.00",
+ comment = "unknown specification.",
+ author = "anonymous",
+ copyright = "no one",
+ categories = setmetatableindex(unknowncategory),
+ types = setmetatableindex(defaulttypes,unknowntype),
+}
+
+-- maybe at some point we can have a handlers table with per field
+-- a found, fetch, ... method
+
+local function checkfield(specification,category,data)
+ local list = setmetatableindex({},implicits)
+ data.fields = list
+ data.category = category
+ local sets = data.sets or { }
+ for i=1,#origins do
+ local t = origins[i]
+ local d = data[t]
+ if d then
+ for i=1,#d do
+ local di = d[i]
+ di = sets[di] or di
+ if type(di) == "table" then
+ for i=1,#di do
+ list[di[i]] = t
+ end
+ else
+ list[di] = t
+ end
+ end
+ else
+ data[t] = { }
+ end
+ end
+ return data
+end
+
+local specifications = setmetatableindex(function(t,name)
+ if not name then
+ return default -- initializer
+ end
+ local filename = formatters["publ-imp-%s.lua"](name)
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname == "" then
+ report("no data definition file %a for %a",filename,name)
+ return default
+ end
+ local specification = table.load(fullname)
+ if not specification then
+ report("invalid data definition file %a for %a",fullname,name)
+ return default
+ end
+ --
+ local categories = specification.categories
+ if not categories then
+ categories = { }
+ specification.categories = categories
+ end
+ setmetatableindex(categories,unknowncategory)
+ --
+ local types = specification.types
+ if not types then
+ types = defaulttypes
+ specification.types = types
+ end
+ setmetatableindex(types,unknowntype)
+ --
+ local fields = setmetatableindex(unknownfield)
+ specification.fields = fields
+ --
+ local virtual = specification.virtual
+ if virtual == nil then -- so false is valid
+ virtual = { }
+ elseif virtual == false then
+ virtual = { }
+ elseif type(virtual) ~= table then
+ virtual = virtuals
+ end
+ specification.virtual = virtual
+ specification.virtualfields = tohash(virtual)
+ --
+ for category, data in next, categories do
+ categories[category] = checkfield(specification,category,copy(data)) -- we make sure we have no clones
+ end
+ --
+ t[name] = specification
+ --
+ return specification
+end)
+
+publications.specifications = specifications
+
+function publications.setcategory(target,category,data)
+ local specification = specifications[target]
+ specification.categories[category] = checkfield(specification,category,data)
+end
+
+function publications.parenttag(dataset,tag)
+ if not dataset or not tag then
+ report("error in specification, dataset %a, tag %a",dataset,tag)
+ elseif find(tag,"%+") then
+ local tags = lpegmatch(l_splitter,tag)
+ local parent = tags[1]
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local details = current.details
+ local first = luadata[parent]
+ if first then
+ local detail = details[parent]
+ local children = detail.children
+ if not children then
+ children = { }
+ detail.children = children
+ end
+ -- add new ones but only once
+ for i=2,#tags do
+ local tag = tags[i]
+ for j=1,#children do
+ if children[j] == tag then
+ tag = false
+ end
+ end
+ if tag then
+ local entry = luadata[tag]
+ if entry then
+ local detail = details[tag]
+ children[#children+1] = tag
+ if detail.parent then
+ report("error in combination, dataset %a, tag %a, parent %a, ignored %a",dataset,tag,detail.parent,parent)
+ else
+ report("combining, dataset %a, tag %a, parent %a",dataset,tag,parent)
+ detail.parent = parent
+ end
+ end
+ end
+ end
+ return parent
+ end
+ end
+ return tag or ""
+end
+
+function publications.new(name)
+ publicationsstats.nofdatasets = publicationsstats.nofdatasets + 1
+ local dataset = {
+ name = name or "dataset " .. publicationsstats.nofdatasets,
+ nofentries = 0,
+ shortcuts = { },
+ luadata = { },
+ suffixes = { },
+ xmldata = xmlconvert(xmlplaceholder),
+ details = { },
+ ordered = { },
+ nofbytes = 0,
+ entries = nil, -- empty == all
+ sources = { },
+ loaded = { },
+ fields = { },
+ userdata = { },
+ used = { },
+ commands = { }, -- for statistical purposes
+ citestate = { },
+ status = {
+ resources = false,
+ userdata = false,
+ },
+ specifications = {
+ -- used specifications
+ },
+ suffixed = false,
+ }
+ -- we delay details till we need it (maybe we just delay the
+ -- individual fields but that is tricky as there can be some
+ -- depedencies)
+ return dataset
+end
+
+setmetatableindex(datasets,function(t,k)
+ if type(k) == "table" then
+ return k -- so we can use this accessor as checker
+ else
+ local v = publications.new(k)
+ datasets[k] = v
+ return v
+ end
+end)
+
+local function getindex(dataset,luadata,tag)
+ local found = luadata[tag]
+ if found then
+ local index = found.index or 0
+ dataset.ordered[tag] = index
+ return index
+ else
+ local index = dataset.nofentries + 1
+ dataset.nofentries = index
+ dataset.ordered[index] = tag
+ return index
+ end
+end
+
+publications.getindex = getindex
+
+do
+
+ -- we apply some normalization
+
+ local space = S(" \t\n\r\f") -- / " "
+ local collapsed = space^1/" "
+ local csletter = lpegpatterns.csletter or R("az","AZ")
+
+ ----- command = P("\\") * Cc("btxcmd{") * (R("az","AZ")^1) * Cc("}")
+ ----- command = P("\\") * (Carg(1) * C(R("az","AZ")^1) / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end)
+ ----- 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
+ local somemath = P("$") * ((1-P("$"))^1) * P("$") -- let's not assume nested math
+ ----- character = lpegpatterns.utf8character
+ local any = P(1)
+ local done = P(-1)
+ -- local one_l = P("{") / ""
+ -- local one_r = P("}") / ""
+ -- local two_l = P("{{") / ""
+ -- local two_r = P("}}") / ""
+ local zero_l_r = P("{}") / "" * #P(1)
+ local special = P("#") / "\\letterhash "
+
+ local filter_0 = S('\\{}#')
+ local filter_1 = (1-filter_0)^0 * filter_0
+ local filter_2 = Cs(
+ -- {{...}} ... {{...}}
+ -- two_l * (command + special + any - two_r - done)^0 * two_r * done +
+ -- one_l * (command + special + any - one_r - done)^0 * one_r * done +
+ (
+ somemath +
+ whatever +
+ command +
+ special +
+ collapsed +
+ zero_l_r +
+ any
+ )^0
+ )
+
+ -- Currently we expand shortcuts and for large ones (like the acknowledgements
+ -- in tugboat.bib) this is not that efficient. However, eventually strings get
+ -- hashed again.
+
+ local function do_shortcut(key,value,dataset)
+ publicationsstats.nofshortcuts = publicationsstats.nofshortcuts + 1
+ dataset.shortcuts[key] = value
+ end
+
+ -- todo: categories : metatable that lowers and also counts
+ -- todo: fields : metatable that lowers
+
+ local tags = table.setmetatableindex("table")
+
+ local function do_definition(category,tag,tab,dataset)
+ publicationsstats.nofdefinitions = publicationsstats.nofdefinitions + 1
+ if tag == "" then
+ tag = "no-tag-set"
+ end
+ local fields = dataset.fields
+ local luadata = dataset.luadata
+ local hashtag = tag
+ if luadata[tag] then
+ local t = tags[tag]
+ local d = dataset.name
+ local n = (t[d] or 0) + 1
+ t[d] = n
+ hashtag = tag .. "-" .. n
+ if trace_duplicates then
+ local p = { }
+ for k, v in sortedhash(t) do
+ p[#p+1] = formatters["%s:%s"](k,v)
+ end
+ report_duplicates("tag %a is present multiple times: % t, assigning hashtag %a",tag,p,hashtag)
+ end
+ end
+ local index = getindex(dataset,luadata,hashtag)
+ local entries = {
+ category = lower(category),
+ tag = tag,
+ index = index,
+ }
+ for i=1,#tab,2 do
+ local original = tab[i]
+ local normalized = fields[original]
+ if not normalized then
+ normalized = lower(original) -- we assume ascii fields
+ fields[original] = normalized
+ end
+ -- if entries[normalized] then
+ if rawget(entries,normalized) then
+ if trace_duplicates then
+ report_duplicates("redundant field %a is ignored for tag %a in dataset %a",normalized,tag,dataset.name)
+ end
+ else
+ local value = tab[i+1]
+ value = textoutf(value)
+ if lpegmatch(filter_1,value) then
+ 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)
+ else
+ -- warning
+ end
+ end
+ entries[normalized] = value
+ end
+ end
+ luadata[hashtag] = entries
+ end
+
+ local function resolve(s,dataset)
+ return dataset.shortcuts[s] or defaultshortcuts[s] or s -- can be number
+ end
+
+ local pattern = p_whitespace^0
+ * C(P("message") + P("warning") + P("error") + P("comment")) * p_whitespace^0 * P(":")
+ * p_whitespace^0
+ * C(P(1)^1)
+
+ local function do_comment(s,dataset)
+ local how, what = lpegmatch(pattern,s)
+ if how and what then
+ local t = string.splitlines(utilities.strings.striplines(what))
+ local b = file.basename(dataset.fullname or dataset.name or "unset")
+ for i=1,#t do
+ report("%s > %s : %s",b,how,t[i])
+ end
+ end
+ end
+
+ local percent = P("%")
+ local start = P("@")
+ local comma = P(",")
+ local hash = P("#")
+ local escape = P("\\")
+ local single = P("'")
+ local double = P('"')
+ local left = P('{')
+ local right = P('}')
+ local both = left + right
+ local lineending = S("\n\r")
+ local space = S(" \t\n\r\f") -- / " "
+ local spacing = space^0
+ local equal = P("=")
+ ----- collapsed = (space^1)/ " "
+ local collapsed = p_whitespace^1/" "
+ local nospaces = p_whitespace^1/""
+
+ local p_left = (p_whitespace^0 * left) / ""
+ local p_right = (right * p_whitespace^0) / ""
+
+ local balanced = P {
+ [1] = ((escape * (left+right)) + (collapsed + 1 - (left+right))^1 + V(2))^0,
+ [2] = left * V(1) * right,
+ }
+
+ -- local unbalanced = P {
+ -- [1] = left * V(2) * right,
+ -- [2] = ((escape * (left+right)) + (collapsed + 1 - (left+right))^1 + V(1))^0,
+ -- }
+
+ local unbalanced = (left/"") * balanced * (right/"") * P(-1)
+
+ local keyword = C((R("az","AZ","09") + S("@_:-"))^1)
+ local key = C((1-space-equal)^1)
+ local tag = C((1-space-comma)^0)
+ local reference = keyword
+ local category = C((1-space-left)^1)
+ local s_quoted = ((escape*single) + collapsed + (1-single))^0
+ local d_quoted = ((escape*double) + collapsed + (1-double))^0
+
+ local b_value = p_left * balanced * p_right
+ -- local u_value = p_left * unbalanced * p_right -- get rid of outer { }
+ -- local s_value = (single/"") * (u_value + s_quoted) * (single/"")
+ -- local d_value = (double/"") * (u_value + d_quoted) * (double/"")
+ local s_value = (single/"") * (unbalanced + s_quoted) * (single/"")
+ local d_value = (double/"") * (unbalanced + d_quoted) * (double/"")
+ local r_value = reference * Carg(1) /resolve
+
+ local somevalue = d_value + b_value + s_value + r_value
+ local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0))
+
+ value = value / function(s) return lpegmatch(lpegpatterns.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 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 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)
+
+ local bibtotable = (space + forget + P("@") * (casecrap + definition) + 1)^0
+
+ -- todo \%
+
+ -- loadbibdata -> dataset.luadata
+ -- loadtexdata -> dataset.luadata
+ -- loadluadata -> dataset.luadata
+
+ -- converttoxml -> dataset.xmldata from dataset.luadata
+
+ function publications.loadbibdata(dataset,content,source,kind)
+ if not source then
+ report("invalid source for dataset %a",dataset)
+ return
+ end
+ local current = datasets[dataset]
+ local size = #content
+ if size == 0 then
+ report("empty source %a for dataset %a",source,current.name)
+ else
+ report("adding bib data to set %a from source %a",current.name,source)
+ end
+ statistics.starttiming(publications)
+ publicationsstats.nofbytes = publicationsstats.nofbytes + size
+ current.nofbytes = current.nofbytes + size
+ 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
+ lpegmatch(bibtotable,content or "",1,current)
+ statistics.stoptiming(publications)
+ end
+
+end
+
+do
+
+ -- we could use xmlescape again
+
+ local cleaner_0 = S('<>&')
+ local cleaner_1 = (1-cleaner_0)^0 * cleaner_0
+ local cleaner_2 = Cs ( (
+ P("<") / "&lt;" +
+ P(">") / "&gt;" +
+ P("&") / "&amp;" +
+ P(1)
+ )^0)
+
+ 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 !
+ 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()
+ --
+ r = r + 1 ; result[r] = "<?xml version='1.0' standalone='yes'?>"
+ r = r + 1 ; result[r] = "<bibtex>"
+ --
+ 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>"]
+ 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)
+ for key, value in sortedhash(entry) do
+ if key ~= "tag" and key ~= "category" and key ~= "index" then
+ if lpegmatch(cleaner_1,value) then
+ value = lpegmatch(cleaner_2,value)
+ end
+ if value ~= "" then
+ r = r + 1 ; result[r] = f_field(key,value)
+ end
+ end
+ end
+ r = r + 1 ; result[r] = s_entry_stop
+ n = n + 1
+ end
+ end
+ else
+ 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>"]
+ for tag, entry in next, luadata do
+ if not usedonly or usedonly[tag] then
+ r = r + 1 ; result[r] = f_entry_start(entry.tag,entry.category,entry.index)
+ for key, value in next, entry do
+ if key ~= "tag" and key ~= "category" and key ~= "index" then
+ if lpegmatch(cleaner_1,value) then
+ value = lpegmatch(cleaner_2,value)
+ end
+ if value ~= "" then
+ r = r + 1 ; result[r] = f_field(key,value)
+ end
+ end
+ end
+ r = r + 1 ; result[r] = s_entry_stop
+ n = n + 1
+ end
+ end
+ end
+ --
+ r = r + 1 ; result[r] = "</bibtex>"
+ --
+ result = concat(result,nice and "\n" or nil)
+ --
+ if dontstore then
+ -- indeed
+ else
+ statistics.starttiming(xml)
+ current.xmldata = xmlconvert(result, {
+ resolve_entities = true,
+ resolve_predefined_entities = true, -- in case we have escaped entities
+ -- unify_predefined_entities = true, -- &#038; -> &amp;
+ utfize_entities = true,
+ } )
+ statistics.stoptiming(xml)
+ if lxml then
+ lxml.register(formatters["btx:%s"](current.name),current.xmldata)
+ end
+ end
+ statistics.stoptiming(publications)
+ return result, n
+ end
+ end
+
+end
+
+do
+
+ local function resolvedname(dataset,filename)
+ local current = datasets[dataset]
+ if type(filename) ~= "string" then
+ report("invalid filename %a",tostring(filename))
+ end
+ local fullname = resolvers.findfile(filename,"bib")
+ if fullname == "" then
+ fullname = resolvers.findfile(filename) -- let's not be too picky
+ end
+ if not fullname or fullname == "" then
+ report("no file %a",filename)
+ current.fullname = filename
+ return current, false
+ else
+ current.fullname = fullname
+ return current, fullname
+ end
+ end
+
+ publications.resolvedname = resolvedname
+
+ local cleaner = false
+ local cleaned = false
+
+ function loaders.registercleaner(what,fullname)
+ if not fullname or fullname == "" then
+ report("no %s file %a",what,fullname)
+ return
+ end
+ local list = table.load(fullname)
+ if not list then
+ report("invalid %s file %a",what,fullname)
+ return
+ end
+ list = list.replacements
+ if not list then
+ report("no replacement table in %a",fullname)
+ return
+ end
+ if cleaned then
+ report("adding replacements from %a",fullname)
+ for k, v in next, list do
+ cleaned[k] = v
+ end
+ else
+ report("using replacements from %a",fullname)
+ cleaned = list
+ end
+ cleaner = true
+ end
+
+ function loaders.bib(dataset,filename,kind)
+ local dataset, fullname = resolvedname(dataset,filename)
+ if not fullname then
+ return
+ end
+ local data = io.loaddata(fullname) or ""
+ if data == "" then
+ report("empty file %a, nothing loaded",fullname)
+ return
+ end
+ if cleaner == true then
+ cleaner = Cs((lpeg.utfchartabletopattern(keys(cleaned)) / cleaned + p_utf8character)^1)
+ end
+ if cleaner ~= false then
+ data = lpegmatch(cleaner,data)
+ end
+ if trace then
+ report("loading file %a",fullname)
+ end
+ publications.loadbibdata(dataset,data,fullname,kind)
+ end
+
+ function loaders.lua(dataset,filename) -- if filename is a table we load that one
+ local current, data, fullname
+ if type(filename) == "table" then
+ current = datasets[dataset]
+ data = filename
+ else
+ dataset, fullname = resolvedname(dataset,filename)
+ if not fullname then
+ return
+ end
+ current = datasets[dataset]
+ data = table.load(fullname)
+ end
+ if data then
+ local luadata = current.luadata
+ -- we want the same index each run
+ for tag, entry in sortedhash(data) do
+ if type(entry) == "table" then
+ entry.index = getindex(current,luadata,tag)
+ entry.tag = tag
+ luadata[tag] = entry -- no cleaning yet
+ end
+ end
+ end
+ end
+
+ function loaders.buffer(dataset,name) -- if filename is a table we load that one
+ local current = datasets[dataset]
+ local barename = file.removesuffix(name)
+ local data = buffers.getcontent(barename) or ""
+ if data == "" then
+ report("empty buffer %a, nothing loaded",barename)
+ return
+ end
+ if trace then
+ report("loading buffer",barename)
+ end
+ publications.loadbibdata(current,data,barename,"bib")
+ end
+
+ function loaders.xml(dataset,filename)
+ local dataset, fullname = resolvedname(dataset,filename)
+ if not fullname then
+ return
+ end
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local root = xml.load(fullname)
+ for bibentry in xmlcollected(root,"/bibtex/entry") do
+ local attributes = bibentry.at
+ local tag = attributes.tag
+ local entry = {
+ category = attributes.category,
+ tag = tag, -- afterwards also set, to prevent overload
+ index = 0, -- prelocated
+ }
+ for field in xmlcollected(bibentry,"/field") do
+ entry[field.at.name] = field.dt[1] -- no cleaning yet | xmltext(field)
+ end
+ entry.index = getindex(current,luadata,tag)
+ entry.tag = tag
+ luadata[tag] = entry
+ end
+ end
+
+ setmetatableindex(loaders,function(t,filetype)
+ local v = function(dataset,filename)
+ report("no loader for file %a with filetype %a",filename,filetype)
+ end
+ t[filetype] = v
+ return v
+ end)
+
+ local done = setmetatableindex("table")
+
+ function publications.load(specification)
+ local name = specification.dataset or v_default
+ local current = datasets[name]
+ local files = settings_to_array(specification.filename)
+ local kind = specification.kind
+ local dataspec = specification.specification
+ statistics.starttiming(publications)
+ local somedone = false
+ for i=1,#files do
+ local filetype, filename = string.splitup(files[i],"::")
+ if not filename then
+ filename = filetype
+ filetype = file.suffix(filename)
+ end
+ if filename then
+ if not filetype or filetype == "" then
+ filetype = "bib"
+ end
+ if file.suffix(filename) == "" then
+ file.addsuffix(filename,filetype)
+ end
+ if done[current][filename] then
+ report("file %a is already loaded in dataset %a",filename,name)
+ else
+ loaders[filetype](current,filename)
+ done[current][filename] = true
+ somedone = true
+ end
+ if kind then
+ current.loaded[current.fullname or filename] = kind
+ end
+ if dataspec then
+ current.specifications[dataspec] = true
+ end
+ end
+ end
+ if somedone then
+ local runner = enhancer.runner
+ if runner then
+ runner(current)
+ end
+ end
+ statistics.stoptiming(publications)
+ return current
+ end
+
+end
+
+do
+
+ function enhancers.order(dataset)
+ local luadata = dataset.luadata
+ local ordered = dataset.ordered
+ for i=1,#ordered do
+ local tag = ordered[i]
+ if type(tag) == "string" then
+ ordered[i] = luadata[tag]
+ end
+ end
+ end
+
+ function enhancers.details(dataset)
+ local luadata = dataset.luadata
+ local details = dataset.details
+ for tag, entry in next, luadata do
+ if not details[tag] then
+ details[tag] = { }
+ end
+ end
+ end
+
+ utilities.sequencers.appendaction(enhancer,"system","publications.enhancers.order")
+ utilities.sequencers.appendaction(enhancer,"system","publications.enhancers.details")
+
+end
+
+do
+
+ local checked = function(s,d) d[s] = (d[s] or 0) + 1 end
+ local checktex = ( (1-P("\\"))^1 + P("\\") * ((C(R("az","AZ")^1) * Carg(1))/checked))^0
+
+ function publications.analyze(dataset)
+ local current = datasets[dataset]
+ local data = current.luadata
+ local categories = { }
+ local fields = { }
+ local commands = { }
+ for k, v in next, data do
+ categories[v.category] = (categories[v.category] or 0) + 1
+ for k, v in next, v do
+ fields[k] = (fields[k] or 0) + 1
+ lpegmatch(checktex,v,1,commands)
+ end
+ end
+ current.analysis = {
+ categories = categories,
+ fields = fields,
+ commands = commands,
+ }
+ end
+
+end
+
+function publications.tags(dataset)
+ return sortedkeys(datasets[dataset].luadata)
+end
+
+function publications.sortedentries(dataset)
+ return sortedhash(datasets[dataset].luadata)
+end
+
+-- a helper:
+
+function publications.concatstate(i,n)
+ if i == 0 then
+ return 0
+ elseif i == 1 then
+ return 1
+ elseif i == 2 and n == 2 then
+ return 4
+ elseif i == n then
+ return 3
+ else
+ return 2
+ end
+end
+
+-- savers
+
+do
+
+ local savers = { }
+
+ local s_preamble = [[
+% this is an export from context mkiv
+
+@preamble{
+ \ifdefined\btxcmd
+ % we're probably in context
+ \else
+ \def\btxcmd#1{\csname#1\endcsname}
+ \fi
+}
+
+]]
+
+ function savers.bib(dataset,filename,tobesaved)
+ 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
+ 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
+ if not privates[key] then
+ r = r + 1 ; result[r] = f_field(key,value)
+ end
+ end
+ 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))
+ end
+
+ function savers.lua(dataset,filename,tobesaved)
+ local list = { }
+ local n = 0
+ for tag, data in next, tobesaved do
+ local t = { }
+ for key, value in next, data do
+ if not privates[key] then
+ d[key] = value
+ end
+ end
+ list[tag] = t
+ n = n + 1
+ end
+ report("%s entries from dataset %a saved in %a",n,dataset,filename)
+ table.save(filename,list)
+ end
+
+ function savers.xml(dataset,filename,tobesaved)
+ local result, n = publications.converttoxml(dataset,true,true,false,tobesaved)
+ report("%s entries from dataset %a saved in %a",n,dataset,filename)
+ io.savedata(filename,result)
+ end
+
+ function publications.save(specification)
+ local dataset = specification.dataset
+ local filename = specification.filename
+ local filetype = specification.filetype
+ local criterium = specification.criterium
+ statistics.starttiming(publications)
+ if not filename or filename == "" then
+ report("no filename for saving given")
+ return
+ end
+ if not filetype or filetype == "" then
+ filetype = file.suffix(filename)
+ end
+ if not criterium or criterium == "" then
+ criterium = v_all
+ end
+ local saver = savers[filetype]
+ if saver then
+ local current = datasets[dataset]
+ local luadata = current.luadata or { }
+ local tobesaved = { }
+ local result = structures.lists.filter({criterium = criterium, names = "btx"}) or { }
+ for i=1,#result do
+ local userdata = result[i].userdata
+ if userdata then
+ local set = userdata.btxset or v_default
+ if set == dataset then
+ local tag = userdata.btxref
+ if tag then
+ tobesaved[tag] = luadata[tag]
+ end
+ end
+ end
+ end
+ saver(dataset,filename,tobesaved)
+ else
+ report("unknown format %a for saving %a",filetype,dataset)
+ end
+ statistics.stoptiming(publications)
+ return dataset
+ end
+
+ if implement then
+
+ implement {
+ name = "btxsavedataset",
+ actions = publications.save,
+ arguments = {
+ {
+ { "dataset" },
+ { "filename" },
+ { "filetype" },
+ { "criterium" },
+ }
+ }
+ }
+
+ end
+
+end
+
+-- casters
+
+do
+
+ publications.detailed = setmetatableindex(function(detailed,kind)
+ local values = setmetatableindex(function(values,value)
+ local caster = casters[kind]
+ local cast = caster and caster(value) or value
+ values[value] = cast
+ return cast
+ end)
+ detailed[kind] = values
+ return values
+ end)
+
+ local keywordsplitter = utilities.parsers.groupedsplitat(";,")
+
+ casters.keyword = function(str)
+ return lpegmatch(keywordsplitter,str)
+ end
+
+
+ writers.keyword = function(k)
+ if type(k) == "table" then
+ return concat(p,";")
+ else
+ return k
+ end
+ end
+
+ local pagessplitter = lpeg.splitat(P("-")^1)
+
+ casters.range = function(str)
+ local first, last = lpegmatch(pagessplitter,str)
+ return first and last and { first, last } or str
+ end
+
+ writers.range = function(p)
+ if type(p) == "table" then
+ return concat(p,"-")
+ else
+ return p
+ end
+ end
+
+ casters.pagenumber = casters.range
+ writers.pagenumber = writers.range
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-fnd.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-fnd.lua
new file mode 100644
index 00000000000..32d0c11beed
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-fnd.lua
@@ -0,0 +1,298 @@
+if not modules then modules = { } end modules ['publ-fnd'] = {
+ 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"
+}
+
+if not characters then
+ dofile(resolvers.findfile("char-def.lua"))
+ dofile(resolvers.findfile("char-utf.lua"))
+end
+
+-- this tracker is only for real debugging and not for the average user
+
+local trace_match = false trackers.register("publications.match", function(v) trace_match = v end)
+
+local publications = publications
+
+local tonumber, next, type = tonumber, next, type
+local find = string.find
+local P, R, S, C, Cs, Cp, Cc, Carg, Ct, V = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Carg, lpeg.Ct, lpeg.V
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local concat = table.concat
+
+local formatters = string.formatters
+local lowercase = characters.lower
+local topattern = string.topattern
+
+publications = publications or { } -- for testing
+
+local report = logs.reporter("publications","match")
+
+local colon = P(":")
+local dash = P("-")
+local lparent = P("(")
+local rparent = P(")")
+local space = lpegpatterns.whitespace
+local utf8char = lpegpatterns.utf8character
+local valid = 1 - colon - space - lparent - rparent
+----- key = C(valid^1)
+local key = C(R("az","AZ")^1)
+local wildcard = C("*")
+local word = Cs(lpegpatterns.unquoted + lpegpatterns.argument + valid^1)
+local simple = C(valid^1)
+local number = C(valid^1)
+
+local key = C(R("az","AZ")^1)
+local contains = S(":~")
+local exact = P("=")
+local valid = (1 - space - lparent -rparent)^1
+local wildcard = P("*") / ".*"
+local single = P("?") / "."
+local dash = P("-") / "%."
+local percent = P("-") / "%%"
+local word = Cs(lpegpatterns.unquoted + lpegpatterns.argument + valid)
+local range = P("<") * space^0 * C((1-space)^1) * space^1 * C((1-space- P(">"))^1) * space^0 * P(">")
+
+local f_key_fld = formatters[" local kf_%s = get(entry,%q) \n if kf_%s then kf_%s = lower(kf_%s) end"]
+local f_key_set = formatters[" local ks_%s = get(entry,%q,categories)\n if ks_%s then ks_%s = lower(ks_%s) end"]
+local f_number_fld = formatters[" local nf_%s = tonumber(get(entry,%q))"]
+local f_number_set = formatters[" local ns_%s = tonumber(get(entry,%q,categories))"]
+
+local f_fld_exact = formatters["(kf_%s == %q)"]
+local f_set_exact = formatters["(ks_%s == %q)"]
+local f_fld_contains = formatters["(kf_%s and find(kf_%s,%q))"]
+local f_set_contains = formatters["(ks_%s and find(ks_%s,%q))"]
+local f_fld_between = formatters["(nf_%s and nf_%s >= %s and nf_%s <= %s)"]
+local f_set_between = formatters["(ns_%s and ns_%s >= %s and ns_%s <= %s)"]
+
+local f_all_match = formatters["anywhere(entry,%q)"]
+
+local function test_key_value(keys,where,key,first,last)
+ if not key or key == "" then
+ return "(false)"
+ elseif key == "*" then
+ last = "^.*" .. topattern(lowercase(last)) .. ".*$" -- todo: make an lpeg
+ return f_all_match(last)
+ elseif first == false then
+ -- exact
+ last = lowercase(last)
+ if where == "set" then
+ keys[key] = f_key_set(key,key,key,key,key)
+ return f_set_exact(key,last)
+ else
+ keys[key] = f_key_fld(key,key,key,key,key)
+ return f_fld_exact(key,last)
+ end
+ elseif first == true then
+ -- contains
+ last = "^.*" .. topattern(lowercase(last)) .. ".*$"
+ if where == "set" then
+ keys[key] = f_key_set(key,key,key,key,key)
+ return f_set_contains(key,key,last)
+ else
+ keys[key] = f_key_fld(key,key,key,key,key)
+ return f_fld_contains(key,key,last)
+ end
+ else
+ -- range
+ if where == "set" then
+ keys[key] = f_number_set(key,key)
+ return f_set_between(key,key,tonumber(first),key,tonumber(last))
+ else
+ keys[key] = f_number_fld(key,key)
+ return f_fld_between(key,key,tonumber(first),key,tonumber(last))
+ end
+ end
+end
+
+local p_compare = P { "all",
+ all = (V("one") + V("operator") + V("nested") + C(" "))^1,
+ nested = C("(") * V("all") * C(")"), -- C really needed?
+ operator = C("and")
+ + C("or")
+ + C("not"),
+ one = Carg(1)
+ * V("where")
+ * V("key")
+ * (V("how") * V("word") + V("range"))
+ / test_key_value,
+ key = key
+ + C("*"),
+ where = C("set") * P(":")
+ + Cc(""),
+ how = contains * Cc(true)
+ + exact * Cc(false),
+ word = word,
+ range = range,
+}
+
+-- local p_combine = space^0 * (P(",")/" or ") * space^0
+
+-- local pattern = Cs((P("match")/"" * space^0 * p_compare + p_combine)^1)
+
+local comma = P(",")
+local p_spaces = space^0
+local p_combine = p_spaces * comma * p_spaces / " or "
+local p_expression = P("match")/"" * Cs(p_compare)
+ + Carg(1)
+ * Cc("")
+ * Cc("tag")
+ * Cc(false)
+ * (
+ P("tag") * p_spaces * P("(") * Cs((1-S(")")-space)^1) * p_spaces * P(")")
+ + p_spaces * Cs((1-space-comma)^1) * p_spaces
+ ) / test_key_value
+
+local pattern = Cs {
+ [1] = V(2) * (p_combine * V(2))^0,
+ [2] = p_expression,
+}
+
+-- -- -- -- -- -- -- -- -- -- -- -- --
+-- -- -- -- -- -- -- -- -- -- -- -- --
+
+function publications.anywhere(entry,str) -- helpers
+ for k, v in next, entry do
+ if find(lowercase(v),str) then
+ return true
+ end
+ end
+end
+
+-- todo: use an environment instead of
+
+-- table={
+-- { "match", "((kf_editor and find(kf_editor,\"^.*braslau.*$\")))" },
+-- { "hash", "foo1234" },
+-- { "tag", "bar5678" },
+-- }
+
+local f_template = formatters[ [[
+local find = string.find
+local lower = characters.lower
+local anywhere = publications.anywhere
+local get = publications.getfuzzy
+local specification = publications.currentspecification
+local categories = specification and specification.categories
+return function(entry)
+%s
+ return %s and true or false
+end
+]] ]
+
+local function compile(dataset,expr)
+ local keys = { }
+ -- local expression = lpegmatch(pattern,expr,start,keys)
+ local expression = lpegmatch(pattern,expr,1,keys)
+ if trace_match then
+ report("compiling expression: %s",expr)
+ end
+ local definitions = { }
+ for k, v in next, keys do
+ definitions[#definitions+1] = v
+ end
+ if #definitions == 0 then
+ report("invalid expression: %s",expr)
+ elseif trace_match then
+ for i=1,#definitions do
+ report("% 3i : %s",i,definitions[i])
+ end
+ end
+ definitions = concat(definitions,"\n")
+ local code = f_template(definitions,expression)
+ if trace_match then
+ report("generated code: %s",code)
+ end
+ local finder = loadstring(code) -- use an environment
+ if type(finder) == "function" then
+ finder = finder()
+ if type(finder) == "function" then
+ return finder, code
+ end
+ end
+ report("invalid expression: %s",expr)
+ return false
+end
+
+-- local function test(str)
+-- local keys = { }
+-- local definitions = { }
+-- local expression = lpegmatch(pattern,str,1,keys)
+-- for k, v in next, keys do
+-- definitions[#definitions+1] = v
+-- end
+-- definitions = concat(definitions,"\n")
+-- print(f_template(definitions,expression))
+-- end
+
+-- test("match(foo:bar and (foo:bar or foo:bar))")
+-- test("match(foo=bar and (foo=bar or foo=bar))")
+-- test("match(set:foo:bar),match(set:foo:bar)")
+-- test("match(set:foo=bar)")
+-- test("match(foo:{bar bar})")
+-- test("match(foo={bar bar})")
+-- test("match(set:foo:'bar bar')")
+-- test("match(set:foo='bar bar')")
+-- test("match(set:foo<1000 2000>)")
+-- test("match(set:foo<1000 2000>)")
+-- test("match(*:foo)")
+-- test("match(*:*)")
+
+local trigger = (P("match") + P("tag")) * p_spaces * P("(")
+local check = (1-trigger)^0 * trigger
+
+local function finder(dataset,expression)
+ local found = lpegmatch(check,expression) and compile(dataset,expression) or false
+ if found then
+ local okay, message = pcall(found,{})
+ if not okay then
+ found = false
+ report("error in match: %s",message)
+ end
+ end
+ return found
+end
+
+-- finder("match(author:foo)")
+-- finder("match(author:foo and author:bar)")
+-- finder("match(author:foo or (author:bar and page:123))")
+-- finder("match(author:foo),match(author:foo)")
+
+publications.finder = finder
+
+function publications.search(dataset,expression)
+ local find = finder(dataset,expression)
+ if find then
+ local ordered = dataset.ordered
+ local target = { }
+ for i=1,#ordered do
+ local entry = ordered[i]
+ if find(entry) then
+ local tag = entry.tag
+ if not target[tag] then
+ -- we always take the first
+ target[tag] = entry
+ end
+ end
+ end
+ return target
+ else
+ return { } -- { dataset.luadata[expression] } -- ?
+ end
+end
+
+-- local d = publications.datasets.default
+--
+-- local d = publications.load {
+-- dataset = "default",
+-- filename = "t:/manuals/mkiv/hybrid/tugboat.bib"
+-- }
+--
+-- inspect(publications.search(d,[[match(author:hagen)]]))
+-- inspect(publications.search(d,[[match(author:hagen and author:hoekwater and year:1990-2010)]]))
+-- inspect(publications.search(d,[[match(author:"Bogusław Jackowski")]]))
+-- inspect(publications.search(d,[[match(author:"Bogusław Jackowski" and (tonumber(field:year) or 0) > 2000)]]))
+-- inspect(publications.search(d,[[Hagen:TB19-3-304]]))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.lua
new file mode 100644
index 00000000000..f2e7f11e107
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.lua
@@ -0,0 +1,544 @@
+local specification = {
+ --
+ -- metadata
+ --
+ name = "apa",
+ version = "1.00",
+ comment = "APA specification",
+ author = "Alan Braslau and Hans Hagen",
+ copyright = "ConTeXt development team",
+ --
+ -- derived (combinations of) fields (all share the same default set)
+ --
+ virtual = {
+ "authoryear",
+ "authoryears",
+ "authornum",
+ "num",
+ "suffix",
+ },
+ --
+ -- special datatypes
+ --
+ types = {
+ --
+ -- list of fields that are interpreted as names: "NAME [and NAME]" where
+ -- NAME is one of the following:
+ --
+ -- First vons Last
+ -- vons Last, First
+ -- vons Last, Jrs, First
+ -- Vons, Last, Jrs, First
+ --
+ author = "author", -- interpreted as name(s)
+ withauthor = "author",
+ editor = "author",
+ translator = "author",
+ artist = "author",
+ composer = "author",
+ producer = "author",
+ director = "author",
+ doi = "url", -- an external link
+ url = "url",
+ page = "pagenumber", -- number or range: f--t
+ pages = "pagenumber",
+ volume = "range",
+ number = "range",
+ keywords = "keyword", -- comma|-|separated list
+ year = "number",
+ },
+ --
+ -- categories with their specific fields
+ --
+ categories = {
+ --
+ -- categories are added below
+ --
+ },
+}
+
+local generic = {
+ --
+ -- A set returns the first field (in order of position below) that is found
+ -- present in an entry. A set having the same name as a field conditionally
+ -- allows the substitution of an alternate field.
+ --
+ -- note that anything can get assigned a doi or be available online.
+ doi = { "doi", "url" },
+ editionset = { "edition", "volume", "number", "pages" },
+}
+
+-- Definition of recognized categories and the fields that they contain.
+-- Required fields should be present; optional fields may also be rendered;
+-- all other fields will be ignored.
+
+-- Sets contain either/or in order of precedence.
+--
+-- For a category *not* defined here yet present in the dataset, *all* fields
+-- are taken as optional. This allows for flexibility in the addition of new
+-- categories.
+
+local categories = specification.categories
+
+-- an article from a journal
+
+categories.article = {
+ sets = {
+ author = { "author", "editor", "title" },
+ doi = generic.doi,
+ },
+ required = {
+ "author"
+ },
+ optional = {
+ "withauthor", "translator",
+ "year",
+ "subtitle", "type", "file",
+ "journal", "volume", "number", "pages",
+ "doi", "note",
+ },
+}
+
+-- an article from a magazine
+
+categories.magazine = {
+ sets = categories.article.sets,
+ required = {
+ "author",
+ "year",
+ "journal",
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "type", "file",
+ "number",
+ "month", "day",
+ "doi", "note",
+ },
+}
+
+categories.newspaper = categories.magazine
+
+-- (from jabref) to be identified and setup ...
+
+categories.periodical = {
+ sets = {
+ author = { "editor", "publisher" },
+ doi = generic.doi,
+ },
+ required = {
+ "title",
+ "year",
+ },
+ optional = {
+ "author", "withauthor", "translator",
+ "subtitle", "file",
+ "series", "volume", "number", "month",
+ "organization",
+ "doi", "note",
+ },
+}
+
+-- (from jabref) to be identified and setup ...
+
+categories.standard = {
+ sets = {
+ author = { "author", "institution", "organization" },
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "year",
+ "title", "subtitle",
+ "doi", "note",
+ },
+ optional = {
+ "withauthor", "translator",
+ },
+}
+
+-- a book with an explicit publisher.
+
+categories.book = {
+ sets = {
+ author = { "author", "editor", "publisher", "title" },
+ editionset = generic.editionset,
+ doi = generic.doi,
+ },
+ required = { "author" },
+ optional = {
+ "withauthor", "translator",
+ "year", "month", "day",
+ "subtitle", "type", "file",
+ "editionset", "series",
+ "address",
+ "doi", "note",
+ },
+}
+
+-- a part of a book, which may be a chapter (or section or whatever) and/or a range of pages.
+
+categories.inbook = {
+ sets = {
+ author = { "author", "editor", "publisher", "title", },
+ editionset = generic.editionset,
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "year" ,
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "type", "file",
+ "booktitle",
+ -- APA ignores this: "chapter",
+ "editionset", "series",
+ "month",
+ "address",
+ "doi", "note",
+ },
+}
+
+-- a book having its own title as part of a collection.
+-- (like inbook, but we here make booktitle required)
+
+categories.incollection = {
+ sets = {
+ author = { "author", "editor", "publisher", "title", },
+ editionset = generic.editionset,
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "booktitle",
+ "year",
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "type", "file",
+ "editionset", "series",
+ -- APA ignores this: "chapter",
+ "month",
+ "address",
+ "doi", "note",
+ },
+}
+
+-- a work that is printed and bound, but without a named publisher or sponsoring institution.
+
+categories.booklet = {
+ sets = {
+ author = { "author", "title", },
+ publisher = { "howpublished" }, -- no "publisher"!
+ doi = generic.doi,
+ },
+ required = {
+ "author"
+ },
+ optional = {
+ "withauthor", "translator",
+ "publisher",
+ "year", "month",
+ "subtitle", "type", "file",
+ "address",
+ "doi", "note",
+ },
+}
+
+-- the proceedings of a conference.
+
+categories.proceedings = {
+ sets = {
+ author = { "editor", "organization", "publisher", "title" }, -- no "author"!
+ publisher = { "publisher", "organization" },
+ editionset = generic.editionset,
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "year"
+ },
+ optional = {
+ "withauthor", "translator",
+ "publisher",
+ "subtitle", "file",
+ "editionset", "series",
+ "month",
+ "address",
+ "doi", "note",
+ },
+}
+
+-- an article in a conference proceedings.
+
+categories.inproceedings = {
+ sets = categories.incollection.sets,
+ required = categories.incollection.required,
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "type", "file",
+ "month",
+ "edition", "series",
+ "address", "organization",
+ "doi", "note",
+ },
+}
+
+categories.conference = categories.inproceedings
+
+-- a thesis (of course).
+
+categories.thesis = {
+ sets = {
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "title",
+ "school",
+ "year",
+ "type"
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "file",
+ "month",
+ "address",
+ "doi", "note",
+ },
+}
+
+categories.mastersthesis = {
+ sets = categories.thesis.sets,
+ required = {
+ "author",
+ "title",
+ "school",
+ "year"
+ },
+ optional = {
+ "withauthor", "translator",
+ "type",
+ "subtitle", "file",
+ "month",
+ "address",
+ "doi", "note",
+ },
+}
+categories.phdthesis = categories.mastersthesis
+
+-- a report published by a school or other institution, usually numbered within a series.
+
+categories.techreport = {
+ sets = {
+ author = { "author", "institution", "publisher", "title" },
+ publisher = { "publisher", "institution", },
+ editionset = { "type", "volume", "number", "pages" }, -- no "edition"!
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "title",
+ "institution",
+ "year"
+ },
+ optional = {
+ "withauthor", "translator",
+ "publisher",
+ "address",
+ "subtitle", "file",
+ "editionset",
+ "month",
+ "doi", "note",
+ },
+}
+
+-- technical documentation.
+
+categories.manual = {
+ sets = {
+ author = { "author", "organization", "publisher", "title" },
+ publisher = { "publisher", "organization", },
+ editionset = generic.editionset,
+ doi = generic.doi,
+ },
+ required = {
+ "title"
+ },
+ optional = {
+ "author", "publisher",
+ "withauthor", "translator",
+ "address",
+ "subtitle", "file",
+ "editionset", "month", "year",
+ "doi", "note",
+-- "abstract",
+ },
+}
+
+-- a patent (of course).
+
+categories.patent = {
+ sets = {
+ author = { "author", "assignee", },
+ publisher = { "publisher", "assignee", },
+ year = { "year", "yearfiled", },
+ month = { "month", "monthfiled", },
+ day = { "day", "dayfiled", },
+ doi = generic.doi,
+ },
+ required = {
+ "nationality",
+ "number",
+ "year",
+ },
+ optional = {
+ "type",
+ --check this: "language",
+ "author", "publisher",
+ "withauthor", "translator",
+ "title", "subtitle", "file",
+ "address",
+ "day", "month",
+ "doi", "note"
+ },
+}
+
+-- a document having an author and title, but not formally published.
+
+categories.unpublished = {
+ sets = {
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "title",
+ "note"
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "file",
+ "year", "month",
+ "doi"
+ },
+}
+
+-- like misc below but includes organization.
+
+categories.electronic = {
+ sets = {
+ doi = generic.doi,
+ },
+ required = {
+ "title"
+ },
+ optional = {
+ "subtitle", "type", "file",
+ "year", "month",
+ "author", "withauthor", "translator",
+ "address",
+ "organization",
+ "howpublished",
+ "doi", "note"
+ },
+}
+
+-- not bibtex categories...
+
+categories.film = {
+ sets = {
+ doi = generic.doi,
+ author = { "producer", "director", },
+ },
+ required = {
+ "author",
+ "title",
+ "year",
+ "address", "publisher", -- aka studio
+ },
+ optional = {
+ "withauthor", "translator",
+ "type",
+ "note",
+ "doi",
+ },
+}
+
+categories.music = {
+ sets = {
+ doi = generic.doi,
+ author = { "composer", "artist", "title", "album" },
+ title = { "title", "album", },
+ },
+ required = {
+ "author",
+ "title",
+ "year",
+ "address", "publisher", -- aka label
+ },
+ optional = {
+ "withauthor", "translator",
+ "type",
+ "note",
+ "doi",
+ },
+}
+
+-- use this type when nothing else fits.
+
+categories.misc = {
+ sets = {
+ doi = generic.doi,
+ },
+ required = {
+ -- nothing is really important here
+ },
+ optional = {
+ "author", "withauthor", "translator",
+ "title", "subtitle", "file",
+ "year", "month",
+ "howpublished",
+ "doi", "note",
+ },
+}
+
+-- other (whatever jabref does not know!)
+
+categories.other = {
+ sets = {
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "title",
+ "year"
+ },
+ optional = {
+ "withauthor", "translator",
+ "subtitle", "file",
+ "doi", "note",
+ },
+}
+
+-- if all else fails to match:
+
+categories.literal = {
+ sets = {
+ author = { "key" },
+ doi = generic.doi,
+ },
+ required = {
+ "author",
+ "text"
+ },
+ optional = {
+ "withauthor", "translator",
+ "doi", "note"
+ },
+ virtual = false,
+}
+
+-- done
+
+return specification
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi
new file mode 100644
index 00000000000..5600b572238
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi
@@ -0,0 +1,1523 @@
+%D \module
+%D [ file=publ-imp-apa,
+%D version=2013.12.12,
+%D title=APA bibliography style,
+%D subtitle=Publications,
+%D author=Alan Braslau and Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted
+%D by \PRAGMA. See mreadme.pdf for details.
+
+\startbtxrenderingdefinitions[apa]
+
+\ifdefined\c!translate \else \def\c!translate{translate} \fi
+
+%D Reference:
+%D \startTEX
+%D @Book{APA2010,
+%D title ={Publication Manual of the American Psychological Association},
+%D year ={2010},
+%D edition ={Sixth},
+%D address ={Washington, DC},
+%D publisher={American Psychological Association},
+%D Xpages ={291},
+%D url ={http://www.apa.org/books/},
+%D }
+%D \stopTEX
+
+% set ALL specific APA compliant values
+
+\definebtx
+ [apa]
+ [\c!default=default,
+ \c!specification=apa,
+ \c!otherstext={\btxspace\btxlabeltext{apa:others}},
+ %c!journalconversion=\v!normal,
+ \c!monthconversion=\v!month]
+
+% First, define list and rendering parameters
+
+% The APA style sorts the unnumbered rendered list by authoryear
+
+\definebtxrendering
+ [apa]
+ [\c!specification=apa,
+ \c!sorttype=authoryear,
+ \c!numbering=\v!no]
+
+\setupbtxlist
+ [apa]
+ [\c!alternative=\v!paragraph,
+ %\c!width=\v!fit,
+ %\c!distance=.5\emwidth,
+ \c!margin=3.5\emwidth]
+
+\definebtx
+ [apa:\s!list]
+ [apa]
+ [\c!otherstext={\btxcomma\btxnobreakspace\textellipsis\space},
+ \c!etallimit=7,
+ \c!etaldisplay=6,
+ \c!etaloption=last,
+ \c!authorconversion=invertedshort,
+ \c!separator:names:2={\btxcomma}, % aka namesep - in this namespace
+ \c!separator:names:3={\btxcomma\btxnobreakspace\textampersand\space}, % comma separated list
+ \c!separator:names:4={\btxnobreakspace\textampersand\space}] % last of two, no comma!
+
+% First, we define a namespace for a few special fields
+
+\definebtx
+ [apa:\s!list:author]
+ [apa:\s!list]
+
+\definebtx
+ [apa:\s!list:withauthor]
+ [apa:\s!list:author]
+
+\definebtx
+ [apa:\s!list:editor]
+ [apa:\s!list:author]
+
+\definebtx
+ [apa:\s!list:translator]
+ [apa:\s!list:author]
+ [\c!authorconversion=normalshort]
+
+\definebtx
+ [apa:\s!list:suffix]
+ [apa:\s!list]
+
+\definebtx
+ [apa:\s!list:url]
+ [apa:\s!list]
+
+\definebtx
+ [apa:\s!list:doi]
+ [apa:\s!list]
+
+\definebtx
+ [apa:\s!list:\s!page]
+ [apa:\s!list]
+ [\c!separator:2={\btxcomma},
+ \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{apa:and}\space},
+ \c!left={\btxleftparenthesis},
+ \c!right={\btxrightparenthesis},
+ \c!command={\wordright}]
+
+\definebtx
+ [apa:\s!list:numbering]
+ [apa:\s!list]
+ [\c!right={\btxspace}]
+
+\definebtx
+ [apa:\s!list:numbering:default]
+ [apa:\s!list:numbering]
+
+\definebtx
+ [apa:\s!list:numbering:num]
+ [apa:\s!list:numbering]
+ [\c!stopper={.}]
+
+\definebtx
+ [apa:\s!list:numbering:short]
+ [apa:\s!list:numbering]
+
+\definebtx
+ [apa:\s!list:numbering:tag]
+ [apa:\s!list:numbering]
+
+\definebtx
+ [apa:\s!list:numbering:index]
+ [apa:\s!list:numbering]
+
+% Next, we define a namespace for each category
+
+%D In order to be able to get journals expanded (or normalized or abbreviated) you need
+%D to load a list:
+%D
+%D \starttyping
+%D \btxloadjournallist[journals.txt] % the jabref list
+%D \stoptyping
+
+\definebtx
+ [apa:\s!list:journal]
+ [apa:\s!list]
+ [\c!style=\v!italic]
+ %command=\btxexpandedjournal] % btxabbreviatedjournal
+
+\definebtx
+ [apa:\s!list:volume]
+ [apa:\s!list]
+ [\c!style=\v!italic]
+
+\definebtx
+ [apa:\s!list:title]
+ [apa:\s!list]
+ [\c!style=\v!italic,
+ \c!command=\Word,
+ \c!translate=\v!yes]
+
+\definebtx
+ [apa:\s!list:title:article]
+ [apa:\s!list:title]
+ [\c!style=] % journal is set in italics
+
+\definebtx
+ [apa:\s!list:title:magazine]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:newspaper]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:periodical]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:standard]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:book]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:inbook]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:incollection]
+ [apa:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [apa:\s!list:title:proceedings]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:inproceedings]
+ [apa:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [apa:\s!list:title:conference]
+ [apa:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [apa:\s!list:title:thesis]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:phdthesis]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:mastersthesis]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:booklet]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:manual]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:techreport]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:unpublished]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:patent]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:electronic]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:music]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:film]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:other]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:misc]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:title:literal]
+ [apa:\s!list:title]
+
+\definebtx
+ [apa:\s!list:type]
+ [\c!command=\Word]
+
+% Then define and set cite parameters.
+
+\definebtx
+ [apa:\s!cite]
+ [apa]
+ [\c!alternative=authoryear,
+ \c!otherstext={\btxcomma\btxlabeltext{apa:others}},
+ \c!etallimit=5,
+ \c!etaldisplay=1, % TODO: when 2-4, show all first time, etaldisplay subsequently...
+ \c!authorconversion=\v!name,
+ \c!sorttype=normal,
+ \c!compress=\v!yes, % note that cite sorts only work with compress=yes.
+ \c!separator:names:2={\btxcomma},
+ \c!separator:names:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+ \c!separator:names:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
+
+\definebtx
+ [apa:\s!cite:name]
+ [apa:\s!cite]
+ [\c!authorconversion=\v!name]
+
+\definebtx
+ [apa:\s!cite:inverted]
+ [apa:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [apa:\s!cite:invertedshort]
+ [apa:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [apa:\s!cite:normalshort]
+ [apa:\s!cite]
+ [\c!authorconversion=\v!normalshort]
+
+\definebtx
+ [apa:\s!cite:normal]
+ [apa:\s!cite]
+ [\c!authorconversion=\v!normal]
+
+\definebtx
+ [apa:\s!cite:author]
+ [apa:\s!cite]
+
+\definebtx
+ [apa:\s!cite:authoryear]
+ [apa:\s!cite:author]
+ [\c!left={(},
+ \c!right={)},
+ \c!inbetween={\btxcomma}]
+
+\definebtx
+ [apa:\s!cite:default]
+ [apa:\s!cite:authoryear]
+
+\definebtx
+ [apa:\s!cite:authoryears]
+ [apa:\s!cite:authoryear]
+ [\c!left=,
+ \c!right=,
+ \c!inbetween={\btxspace}]
+
+\definebtx
+ [apa:\s!cite:authornum]
+ [apa:\s!cite:author]
+ [\c!left={(},
+ \c!right={)}]
+
+\definebtx
+ [apa:\s!cite:author:num] % todo
+ [apa:\s!cite:authornum]
+ [\c!left={\btxspace[},
+ \c!right={]}]
+
+\definebtx
+ [apa:\s!cite:author:year] % todo
+ [apa:\s!cite]
+
+\definebtx
+ [apa:\s!cite:author:years] % todo
+ [apa:\s!cite:authoryears]
+ [\c!inbetween=,
+ \c!left={\btxspace(},
+ \c!right={)}]
+
+\definebtx
+ [apa:\s!cite:year]
+ [apa:\s!cite]
+ [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+ \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+ \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
+
+\definebtx
+ [apa:\s!cite:title]
+ [apa:\s!cite]
+ [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+ \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+ \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}, % not \textampersand
+ \c!command={\language[\currentbtxlanguage]}, % BAH
+ \c!sorttype=none,
+ \c!style=\v!italic]
+
+\definebtx
+ [apa:\s!cite:booktitle]
+ [apa:\s!cite:title]
+
+\definebtx
+ [apa:\s!cite:tag]
+ [apa:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+
+\definebtx
+ [apa:\s!cite:index]
+ [apa:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [apa:\s!cite:page]
+ [apa:\s!cite]
+ [\c!left=,
+ \c!right=,
+ \c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+ \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+ \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
+
+\definebtx
+ [apa:\s!cite:pages]
+ [apa:\s!cite:page]
+
+\definebtx
+ [apa:\s!cite:keywords]
+ [apa:\s!cite]
+
+\definebtx
+ [apa:\s!cite:short]
+ [apa:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [apa:\s!cite:category]
+ [apa:\s!cite]
+
+\definebtx
+ [apa:\s!cite:url]
+ [apa:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [apa:\s!cite:doi]
+ [apa:\s!cite:url]
+
+\definebtx
+ [apa:\s!cite:num]
+ [apa:\s!cite]
+ [\c!left={[},
+ \c!right={]},
+ \c!separator:2={,}, % no space
+ \c!separator:3=\btxparameter{\c!separator:2},
+ \c!separator:4=\btxparameter{\c!separator:2}]
+
+\definebtx
+ [apa:\s!cite:textnum]
+ [apa:\s!cite:num]
+ [\c!left={Ref.\nbsp},
+ \c!right=,
+ \c!separator:2={\btxcomma},
+ \c!separator:3={\btxspace\btxlabeltext{apa:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}]
+
+\definebtx
+ [apa:\s!cite:entry]
+ [apa:\s!cite]
+ [\c!left=,
+ \c!right=,
+ \c!inbetween={\btxspace},
+ \c!separator:2={\btxsemicolon},
+ \c!separator:3=\btxparameter{\c!separator:2},
+ \c!separator:4=\btxparameter{\c!separator:2}]
+
+% Now we setup for the details of the renderings
+
+%D Sometimes we have verbose injections in an entry and these can be language
+%D dependent, so we use labels.
+%D
+%D Because we want to mix rendering (in the manual) we need a namespace in label
+%D texts:
+
+\setupbtxlabeltext
+ [en]
+ [apa:and=and,
+ apa:number={no.},
+ apa:edition={ed.},
+ apa:Editor={Ed.},
+ apa:Editors={Eds.},
+ apa:Volume={Vol.},
+ apa:Volumes={Vols.},
+ apa:others={et al.},
+ apa:with=with,
+ apa:page={p.},
+ apa:pages={pp.},
+ apa:nd={n.d.}, % no date
+ apa:mastersthesis={Master's thesis},
+ apa:phdthesis={Doctoral dissertation},
+ apa:technicalreport={Tech. Rep.}, % Technical report
+ apa:supplement={Suppl.}, % Supplement (not used?)
+ apa:patent=Patent,
+ apa:MotionPicture={Motion picture},
+ apa:Producer=Producer,
+ apa:Producers=Producers,
+ apa:Director=Director,
+ apa:Directors=Directors,
+ apa:Recordedby={Recorded by},
+ apa:Author=Author,
+ apa:Translator={Trans.}, % Translator(s)
+ apa:Advanced={Advanced online publication},
+ apa:Retrieved={Available from}, % {Retrieved from},
+ apa:In=In]
+
+\setupbtxlabeltext
+ [nl]
+ [apa:and=en,
+ apa:number={nr.},
+ apa:edition={ed.}, % editie
+ apa:Editor=Editor, % Ed./Eds.
+ apa:Editors=Editors,
+ apa:Volume={Vol.},
+ apa:Volumes={Vols.},
+ apa:others={et al.},
+ apa:with=met,
+ apa:page={p.},
+ apa:pages={pp.},
+ apa:nd={g.d.} % geen datum
+ apa:mastersthesis=Masterproef,
+ apa:phdthesis=Proefschrift,
+ apa:technicalreport={Technisch rapport}, % Technical report
+ apa:supplement=Supplement,
+ apa:patent=Octrooi,
+ apa:MotionPicture=Film, % ?
+ apa:Producer=Producent, % ?
+ apa:Producers=Producents, % ?
+ apa:Director=Directeur,
+ apa:Directors=Directeurs,
+ apa:Recordedby={Opgenomen door}, % ?
+ apa:Author=Auteur,
+ apa:Translator=Vertaler,
+ apa:Advanced={Geavanceerde online publicatie},
+ apa:Retrieved={Beschikbaar vanaf}, % {Ontvangen van},
+ apa:In=In]
+
+\setupbtxlabeltext
+ [fr]
+ [apa:and=et,
+ apa:number={n\high{o}},
+ apa:edition={édition},
+ apa:Editor=Éditeur,
+ apa:Editors=Éditeurs,
+ apa:Volume=Volume,
+ apa:Volumes=Volumes,
+ apa:others={et al.},
+ apa:with=avec,
+ apa:page={p.},
+ apa:pages={pp.},
+ apa:nd={s.d.} % sans date
+ apa:mastersthesis={Thèse de master (DEA, DESS, master)},
+ apa:phdthesis={Thèse de doctorat},
+ apa:technicalreport={Rapport technique},
+ apa:supplement=Supplément,
+ apa:patent=Brevet,
+ apa:MotionPicture={Film cinématographique},
+ apa:Producer=Producteur,
+ apa:Producers=Producteurs,
+ apa:Director=Réalisateur,
+ apa:Directors=Réalisateurs,
+ apa:Recordedby={Enregistré par},
+ apa:Author=Auteur,
+ apa:Translator=Traducteur,
+ apa:Advanced={Publication en ligne anticipée},
+ apa:Retrieved={Disponible à}, % {Téléchargé de},
+ apa:In=Dans]
+
+\setupbtxlabeltext
+ [de]
+ [apa:and=und,
+ apa:number={nr.},
+ apa:edition=Auf\/lage,
+ apa:Editor=Herausgeber, % Hrsg./Hg.
+ apa:Editors=Herausgeber,
+ apa:Volume=Band, % Bd.
+ apa:Volumes={Bände},
+ apa:others={et al.},
+ apa:with=mit,
+ apa:page={S.},
+ apa:pages={S.},
+ apa:nd={o.D.}, % ohne Datum (mostly: o.J. / ohne Jahr)
+ apa:mastersthesis={Masterarbeit},
+ apa:phdthesis={Dissertation},
+ apa:technicalreport={Technischer Bericht},
+ apa:supplement={Beilage}, % Supplement
+ apa:patent=Patent,
+ apa:MotionPicture=Kinofilm, % ?
+ apa:Producer=Producer, % ?
+ apa:Producers=Produzenten, % ?
+ apa:Director=Director, % ?
+ apa:Directors=Directors, % ?
+ apa:Recordedby={per Einschreiben}, % ?
+ apa:Author=Autor,
+ apa:Translator={Übersetzer}, % Übers.
+ apa:Advanced={Erweiterte Online-Publikation},
+ apa:Retrieved={heruntergeladen von},
+ apa:In=In]
+
+% thanks: Andrea Valle
+
+\setupbtxlabeltext
+ [it]
+ [apa:and=e,
+ apa:number={nº},
+ apa:edition={ed.}, % edizione
+ apa:Editor={A cura di},
+ apa:Editors={A cura di},
+ apa:Volume={Vol.}, % Volume
+ apa:Volumes={Vol.}, % Volumi
+ apa:others={et al.},
+ apa:with=con,
+ apa:page={p.},
+ apa:pages={pp.},
+ apa:nd={s.d.}, % senza data
+ apa:mastersthesis={Tesi di laurea},
+ apa:phdthesis={Tesi di dottorato},
+ apa:technicalreport={Relazione tecnica},
+ apa:supplement={Supplemento},
+ apa:patent=Brevetto,
+ apa:MotionPicture=Film, % ?
+ apa:Producer=Produttore,
+ apa:Producers=Produttori,
+ apa:Director=Direttore,
+ apa:Directors=Direttori,
+ apa:Recordedby={Registrato da},
+ apa:Author=Autore,
+ apa:Translator={Trad.}, % Translator(s)
+ apa:Advanced={Pre-pubblicazione on line},
+ apa:Retrieved={Accessible online},
+ apa:In=In]
+
+\setupbtxlabeltext
+ [es]
+ [apa:and=y,
+ apa:number={nº},
+ apa:edition={ed.}, % edición
+ apa:Editor=Editor, % Ed./Eds.
+ apa:Editors=Editores,
+ apa:Volume={Vol.}, % Volumen
+ apa:Volumes={Vols.}, % Volúmenes
+ apa:others={et al.},
+ apa:with=con,
+ apa:page={p.},
+ apa:pages={pp.},
+ apa:nd={s.f.}, % sin fecha
+ apa:mastersthesis={Tesis de maestría},
+ apa:phdthesis={Tesis doctoral},
+ apa:technicalreport={Informe técnico},
+ apa:supplement=Suplemento,
+ apa:patent=Patente,
+ apa:MotionPicture=Cinematográfica,
+ apa:Producer=Productor,
+ apa:Producers=Productores,
+ apa:Director=Director,
+ apa:Directors=Directores,
+ apa:Recordedby={Grabada por},
+ apa:Author=Autor,
+ apa:Translator=Traductor,
+ apa:Advanced={Publicación en línea avanzada},
+ apa:Retrieved={Disponible desde}, % {Obtenido de},
+ apa:In=En]
+
+% cite setups
+
+% The following differs from the default returning n.d. if year is empty
+
+\startsetups btx:apa:nd
+ \btxlabeltext{apa:nd}
+\stopsetups
+
+\startsetups btx:apa:cite:author:year
+ \texdefinition{\s!btx:\s!cite:concat}
+ %\btxparameter\c!left
+ \ifx\currentbtxfirst\empty
+ \fastsetup{btx:apa:nd}
+ \else
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \currentbtxfirst
+ }
+ \ifx\currentbtxsecond\empty \else
+ \btxparameter\c!range
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \currentbtxsecond
+ }
+ \fi
+ \btxflushsuffix
+ \fi
+ %\btxparameter\c!right
+\stopsetups
+
+\startsetups btx:apa:cite:author:years
+ \fastsetup{btx:apa:cite:author:year}
+\stopsetups
+
+% used in publ-imp-page.mkvi
+
+\startsetups [btx:apa:list:page-or-pages]
+ \ifx\currentbtxlastpage\empty
+ \btxlabeltext{apa:page}
+ \else
+ \btxlabeltext{apa:pages}
+ \fi
+ \btxnbsp
+\stopsetups
+
+% The sameauthor feature may not be APA compliant
+% (there is nothing in the manual cited above).
+% It can be removed using the command:
+% \resetsetups [apa:list:sameauthor]
+
+% :rule, :empty or :ditto ...
+
+\startsetups apa:list:sameauthor
+ \fastsetup{apa:list:sameauthor:rule}
+\stopsetups
+
+\startsetups apa:list:sameauthor:rule
+ \blackrule
+ [\c!width=\dimexpr\listparameter\c!margin-\interwordspace\relax,
+ \c!height=1.5\linewidth]% \linewidth is just too thin with respect to font strokes...
+\stopsetups
+
+\startsetups [apa:list:sameauthor:\v!empty]
+ \kern\dimexpr\listparameter\c!margin-\interwordspace\relax
+\stopsetups
+
+% horrible !
+
+\startsetups apa:list:sameauthor:ditto
+ \inframed
+ [\c!width=\dimexpr\listparameter\c!margin-\interwordspace\relax,
+ \c!frame=\v!off,
+ \c!align=\v!middle]
+ {\doubleprime}
+\stopsetups
+
+%D Instead of texdefinitions without arguments, we could have used setups but in my
+%D editor (hh, scite) the commands stand out better. It also saves an additional
+%D component in the name (e.g. common:) because commands and setups have a different
+%D namespace, so similar calls don't clash. Performance of definitions is somewhat
+%D better.
+
+%D We use "texdefinitions" (with eventual arguments) for helpers that are used
+%D in the rendering "setups" defined for each category below.
+
+%D Note that \btxdoif... and \btxflush rely on the definitions in
+%D publ-imp-apa.lua: fields that are not listed as required nor optional are
+%D IGNORED. We also make heavy use of the notion of sets - comma-separated lists
+%D of alternative fields to be used in hierarchal order. For example:
+%D author = { "author", "editor", "publisher", "title" }, will return the
+%D author field if it exists; if not, the editor field will be returned, if it
+%D exists; if not, the publisher field will be returned, if it exists; if not,
+%D the title field will be returned, it it exists; if not, nothing will be
+%D returned. In lua syntax, it can be understood as
+%D author or editor or publisher or title or ""
+
+% #title can be title or booktitle
+
+\starttexdefinition unexpanded btx:apa:translated-title #title
+ \ifx\currentbtxlanguage\empty
+ % no need for an extra
+ \else\ifx\mainbtxlanguage\currentbtxlanguage
+ % no need for an extra
+ \else
+ \btxdoif {#title:\mainbtxlanguage} {
+ \begingroup
+ \language[\mainbtxlanguage]
+ \btxleftbracket
+ \btxusecommand [apa:\s!list:title:\currentbtxcategory] {
+ \btxflush{#title:\mainbtxlanguage}
+ }
+ \btxrightbracket
+ \endgroup
+ }
+ \fi\fi
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:composed-title #title
+ \btxstartstyleandcolor[apa:\s!list:title:\currentbtxcategory]
+ \begingroup
+ \language[\currentbtxlanguage]
+ \btxusecommand [apa:\s!list:title:\currentbtxcategory] {
+ \btxflush{#title}
+ \btxdoif {sub#title} {
+ \btxcolon
+ \btxflush{sub#title}
+ }
+ }
+ \endgroup
+ % which namespace?
+ %\doif{\btxparameter{translate}}\v!yes {
+ \texdefinition{btx:apa:translated-title}{#title}
+ %}
+ \btxstopstyleandcolor
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:title
+ \setmode{btx:apa:title-placed}
+ % we make the title active, opening "file"
+ \btxdoifelse {file} {
+ \texdefinition{btx:format:inject}
+ {url(file:\btxflush{file})}
+ {
+ \texdefinition{btx:apa:composed-title}{title}
+ }
+ } {
+ \texdefinition{btx:apa:composed-title}{title}
+ }
+ \btxdoif {title} {
+ \btxdoif {translator} {
+ \btxleftparenthesis
+ \btxflush{translator}
+ \btxcomma
+ \btxlabeltext{apa:Translator}
+ \btxrightparenthesis
+ }
+ \btxperiod
+ % TODO: this period may NOT be wanted, as in: Title (2nd ed.).
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:title-if-not-placed
+ \doifelsemode {btx:apa:title-placed} {
+ \resetmode{btx:apa:title-placed}
+ } {
+ \btxdoif {title} {
+ \btxspace
+ \texdefinition {btx:apa:title}
+ }
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:suffixedyear
+ \btxdoifelse {year} {
+ \btxflush{year}
+ \btxflushsuffix
+ } {
+ \fastsetup{btx:apa:nd}
+ % Hans: the following won't work but should.
+ \btxdoif {suffix} {
+ \btxspace
+ \btxflushsuffix
+ % Hans: similarly, why can't \btxflush{suffix} be made to work?
+ }
+ }
+\stoptexdefinition
+
+% #author may be author(set) or editor
+
+\starttexdefinition unexpanded btx:apa:author-or-editor #author
+ \btxdoif {#author} {
+ \btxflush{#author}
+ \doifelse {\btxfoundname{#author}} {editor} {
+ \btxleftparenthesis
+ \btxsingularorplural {editor} {
+ \btxlabeltext{apa:Editor}
+ } {
+ \btxlabeltext{apa:Editors}
+ }
+ \btxrightparenthesis
+ } {
+ \doifelse {\btxfoundname{#author}} {producer} {
+ \btxleftparenthesis
+ \btxsingularorplural {producer} {
+ \btxlabeltext{apa:Producer}
+ } {
+ \btxlabeltext{apa:Producers}
+ }
+ \btxrightparenthesis
+ \btxdoif {director} {
+ \removeunwantedspaces
+ \btxparameter{\c!separator:names:3}
+ \btxflush{director}
+ \btxleftparenthesis
+ \btxsingularorplural {director} {
+ \btxlabeltext{apa:Director}
+ } {
+ \btxlabeltext{apa:Directors}
+ }
+ \btxrightparenthesis
+ }
+ } {
+ \doif {\btxfoundname{#author}} {director} {
+ \btxleftparenthesis
+ \btxsingularorplural {director} {
+ \btxlabeltext{apa:Director}
+ } {
+ \btxlabeltext{apa:Directors}
+ }
+ \btxrightparenthesis
+ }
+ }
+ }
+ \btxdoif {withauthor} {
+ \btxleftparenthesis
+ \btxlabeltext{apa:with}
+ \btxspace
+ \btxflush{withauthor}
+ \btxrightparenthesis
+ }
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:authoryear
+ % we make the authoryear active, pointing to the citation
+ \texdefinition{btx:format:inject}
+ {internal(\currentbtxinternal)}
+ {
+ \doifelsesetups{apa:list:sameauthor} {
+ \btxdoifelsesameasprevious {author} {
+ \fastsetup{apa:list:sameauthor}
+ } {
+ \texdefinition{btx:apa:author-or-editor} {author}
+ }
+ } {
+ \texdefinition{btx:apa:author-or-editor} {author}
+ }
+ \btxleftparenthesis
+ \texdefinition{btx:apa:suffixedyear}
+ \btxrightparenthesis
+ }
+ % outside of interaction
+ \btxperiod
+ \doif {\btxfoundname{author}} {title} {
+ \setmode{btx:apa:title-placed}
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:editor-in
+ \btxdoif {booktitle} {
+ \btxlabeltext{apa:In}
+ \doifnot {\btxfoundname{author}} {editor} {
+ \btxspace
+ \texdefinition{btx:apa:author-or-editor} {editor}
+ }
+ \btxspace
+ \texdefinition{btx:apa:composed-title}{booktitle}
+ \btxperiod
+ }
+\stoptexdefinition
+
+% TODO: The title is terminated with period. However,
+% we probably don't want this before the parenthesis.
+
+\starttexdefinition unexpanded btx:apa:leftparenthesis-or-comma
+ \doifelsemode {btx:apa:editionset-is-empty} {
+ \btxleftparenthesis
+ \resetmode{btx:apa:editionset-is-empty}
+ } {
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:editionset
+ \setmode{btx:apa:editionset-is-empty}
+ \doif {\currentbtxcategory} {techreport} {
+ \texdefinition{btx:apa:leftparenthesis-or-comma}
+ \btxdoifelse {type} {
+ \btxusecommand [apa:\s!list:type] {
+ \btxflush{type}
+ }
+ } {
+ \btxlabeltext{apa:technicalreport}
+ }
+ }
+ \btxdoif {volume} {
+ \texdefinition{btx:apa:leftparenthesis-or-comma}
+ \btxoneorrange {volume} {
+ \btxlabeltext{apa:Volume}
+ } {
+ \btxlabeltext{apa:Volumes}
+ }
+ \btxspace
+ \btxflush{volume}
+ }
+ \btxdoif {number} {
+ \texdefinition{btx:apa:leftparenthesis-or-comma}
+ \btxlabeltext{apa:number}
+ \btxspace
+ \btxflush{number}
+ }
+ \btxdoif {edition} {
+ \texdefinition{btx:apa:leftparenthesis-or-comma}
+ \btxflush{edition}
+ \btxspace
+ \btxlabeltext{apa:edition}
+ }
+ \btxdoif {pages} {
+ \texdefinition{btx:apa:leftparenthesis-or-comma}
+ \btxoneorrange {pages} {
+ \btxlabeltext{apa:page}
+ } {
+ \btxlabeltext{apa:pages}
+ }
+ \btxnbsp
+ \btxflush{pages}
+ }
+ \doifnotmode {btx:apa:editionset-is-empty} {
+ \btxrightparenthesisperiod
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:journal
+ \btxstartstyleandcolor[apa:\s!list:journal]
+ \btxusecommand [apa:\s!list:journal] {
+ \btxflush{journal}
+ }
+ \btxstopstyleandcolor
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:volume
+ \btxstartstyleandcolor[apa:\s!list:volume]
+ \btxflush{volume}
+ \btxstopstyleandcolor
+\stoptexdefinition
+
+ % this could be simplified!
+
+\starttexdefinition unexpanded btx:apa:journal-volume-number-pages
+ \btxdoif {journal} {
+ \btxspace
+ \texdefinition{btx:apa:journal}
+ \btxdoifelse {volume} {
+ \btxcomma
+ \texdefinition{btx:apa:volume}
+ \btxdoif {number} {
+ %\btxleftparenthesis
+ (\btxflush{number}
+ \btxrightparenthesis
+ }
+ } {
+ \btxdoif {number} {
+ \btxcomma
+ \btxleftparenthesis
+ \btxflush{number}
+ \btxrightparenthesis
+ }
+ }
+ \btxdoif {pages} {
+ \btxcomma
+ \doif {\currentbtxcategory} {newspaper} {
+ \btxoneorrange {pages} {
+ \btxlabeltext{apa:page}
+ } {
+ \btxlabeltext{apa:pages}
+ }
+ \btxnbsp
+ }
+ \btxflush{pages}
+ }
+ \btxperiod
+ \doifnot {\currentbtxcategory} {newspaper} {
+ \btxdoifnot {volume} {
+ \btxdoifnot {number} {
+ \btxdoifnot {pages} {
+ \btxdoif {doi} {%set: doi or url
+ \btxspace
+ \btxlabeltext{apa:Advanced}
+ \btxperiod
+ }
+ }
+ }
+ }
+ }
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:wherefrom-publisher
+ \btxdoifelse {address} {
+ \btxflush{address}
+ \btxdoif {country} {
+ \btxcomma
+ \btxflush{country}
+ }
+ \btxcolon
+ } {
+ \btxdoif {country} {
+ \btxflush{country}
+ \btxcolon
+ }
+ }
+ \doifelse {\btxfoundname{author}} {\btxfoundname{publisher}} {
+ \btxlabeltext{apa:Author}
+ } {
+ \btxdoifelse {publisher} {
+ \btxflush{publisher}
+ } {
+ \btxlabeltext{apa:Author}
+ }
+ }
+ \btxperiod
+\stoptexdefinition
+
+\definebreakpoints[doi]
+\definebreakpoint [doi][:][nleft=3,type=1]
+\definebreakpoint [doi][/][nleft=3,type=1]
+\definebreakpoint [doi][-][nleft=3,type=1]
+\definebreakpoint [doi][.][nleft=3,type=1]
+
+% use \btxentry here?
+
+\starttexdefinition unexpanded btx:apa:url
+ \btxspace
+ \btxlabeltext{apa:Retrieved}
+ \btxspace
+ \begingroup
+ \setbreakpoints[doi]
+ \ifconditional\btxinteractive
+ \goto {
+ \hyphenatedurl{\btxflush{url}}
+ } [
+ url(\btxflush{url})
+ ]
+ \else
+ \hyphenatedurl{\btxflush{url}}
+ \fi
+ \endgroup
+\stoptexdefinition
+
+% use \btxentry here?
+
+\starttexdefinition unexpanded btx:apa:doi
+ \btxspace
+ \begingroup
+ \setbreakpoints[doi]
+ \ifconditional\btxinteractive
+ \goto {
+ \hyphenatedurl{doi:\btxflush{doi}}
+ } [
+ url(http://dx.doi.org/\btxflush{doi})
+ ]
+ \else
+ \hyphenatedurl{doi:\btxflush{doi}}
+ \fi
+ \endgroup
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:note
+ \btxdoif {note} {
+ \btxleftparenthesis
+ \btxflush{note}
+ \btxrightparenthesis
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:apa:url-doi-note
+ \doif {\btxfoundname{doi}} {url} {
+ \texdefinition{btx:apa:url}
+ }
+ \doif {\btxfoundname{doi}} {doi} {
+ \texdefinition{btx:apa:doi}
+ }
+ \texdefinition{btx:apa:note}
+ \removeunwantedspaces
+\stoptexdefinition
+
+% Then setups, by category
+
+% An article from a journal
+% Required fields: author or editor or title, journal, (year).
+% Optional fields: volume, number, pages, type, doi, url, note.
+% Note that bibtex (and tools) do not include editor (e.g. special issue or section)
+
+\startsetups btx:apa:list:article
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \btxdoif {type} {
+ \btxleftbracket
+ \btxflush{type}
+ \btxrightbracketperiod
+ }
+ \texdefinition{btx:apa:journal-volume-number-pages}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% An article from a magazine.
+% Required fields: author or title, journal, (year).
+% Optional fields: number, pages, type, month, day, doi, url, note.
+
+\startsetups btx:apa:list:magazine
+ \fastsetup{btx:apa:list:article}
+\stopsetups
+
+% An article from a newspaper.
+% Required fields: author or title, journal, (year).
+% Optional fields: volume, number, pages, type, month, day, doi, url, note.
+
+\startsetups btx:apa:list:newspaper
+ \fastsetup{btx:apa:list:article}
+\stopsetups
+
+% A complete issue of a periodical, such as a special issue of a journal.
+% Required fields: title, year
+% Optional fields: editor, publisher, subtitle, series, volume, number, month, organization, doi, url, issn, note
+
+% needs to be tuned...
+
+\startsetups btx:apa:list:periodical
+ \fastsetup{btx:apa:list:article}
+\stopsetups
+
+% National and international standards issued by a standards body
+% Required fields: author, institution, or organization, year, title
+% Optional fields: subtitle, doi, url, note
+
+\startsetups btx:apa:list:standard
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% A book with an explicit publisher.
+% Required fields: author or editor or publisher, title, (year).
+% Optional fields: volume or number, series, address, edition, month, day, note.
+% APA ignores: month, day
+
+% todo: series?
+
+\startsetups btx:apa:list:book
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \texdefinition{btx:apa:editionset}
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% There is some debate about how inbook should differ from incollection
+
+% A part of a book, which may be a chapter (or section or whatever) and/or a range of pages.
+% (note that inbook is handled differently by bibtex and biblatex)
+% Required fields: author or editor, title, chapter and/or pages, publisher, year.
+% Optional fields: volume or number, series, type, address, edition, month, note.
+% We add optional: booktitle.
+% APA ignores: chapter, month
+
+\startsetups btx:apa:list:inbook
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \texdefinition{btx:apa:editor-in}
+ \texdefinition{btx:apa:editionset}
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% A part of a book having its own title.
+% Required fields: author, title, booktitle, publisher, year.
+% Optional fields: editor, volume or number, series, type, chapter, pages, address, edition, month, note.
+% APA ignores: chapter, month
+
+\startsetups btx:apa:list:incollection
+ \fastsetup{btx:apa:list:inbook}
+\stopsetups
+
+% The proceedings of a conference.
+% Required fields: title, year.
+% Optional fields: editor, volume or number, series, address, month, organization, publisher, note.
+% todo: series?
+
+\startsetups btx:apa:list:proceedings
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% An article in a conference proceedings.
+% Required fields: author, title, booktitle, year.
+% Optional fields: editor, volume or number, series, pages, address, month, organization, publisher, note.
+
+\startsetups btx:apa:list:inproceedings
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \texdefinition{btx:apa:editor-in}
+ \texdefinition{btx:apa:editionset}
+ \btxdoif {organization} {
+ \btxspace
+ \btxflush{organization}
+ \btxcomma
+ }
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+\startsetups btx:apa:list:conference
+ \fastsetup{btx:apa:list:inproceedings}
+\stopsetups
+
+% A thesis.
+% Required fields: author, title, school, year.
+% Optional fields: type, address, month, note.
+
+\startsetups btx:apa:list:thesis
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \btxleftparenthesis
+ \btxdoifelse {type} {
+ \btxusecommand [apa:\s!list:type] {
+ \btxflush{type}
+ }
+ } {
+ \btxlabeltext{apa:\currentbtxcategory}
+ }
+ \btxrightparenthesis
+ \btxdoif {school} {
+ \btxperiod
+ \btxflush{school}
+ }
+ \btxdoif {address} {
+ \btxdoifelse {school} {
+ \btxcomma
+ } {
+ \btxperiod
+ }
+ \btxflush{address}
+ \btxdoif {country} {
+ \btxcomma
+ \btxflush{country}
+ }
+ }
+ \btxperiod
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+\startsetups btx:apa:list:phdthesis
+ \fastsetup{btx:apa:list:thesis}
+\stopsetups
+
+\startsetups btx:apa:list:mastersthesis
+ \fastsetup{btx:apa:list:thesis}
+\stopsetups
+
+% A work that is printed and bound, but without a named publisher or sponsoring institution.
+% Required field: title.
+% Optional fields: author, howpublished, address, month, year, note.
+
+\startsetups btx:apa:list:booklet
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% Technical documentation.
+% Required field: title.
+% Optional fields: author, organization, address, edition, month, year, note.
+
+\startsetups btx:apa:list:manual
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% A report published by a school or other institution, usually numbered within a series.
+% Required fields: author, title, institution, year.
+% Optional fields: type, number, address, month, note.
+
+\startsetups btx:apa:list:techreport
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% A document having an author and title, but not formally published.
+% Required fields: author, title, note.
+% Optional fields: month, year.
+
+\startsetups btx:apa:list:unpublished
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% A patent. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: nationality, number, year, yearfiled
+% Optional fields: author, title, assignee, address, type, number, day, dayfiled, month, monthfiled, note, url
+% Also optional: publisher
+
+% todo: yearfiled, monthfiled, dayfiled
+
+\startsetups btx:apa:list:patent
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \begingroup
+ \it
+ \btxdoif {nationality} {
+ \btxspace
+ \btxflush{nationality}
+ }
+ \btxspace
+ \btxlabeltext{apa:patent}
+ \btxdoif {number} {
+ \btxspace
+ \btxlabeltext{apa:number}
+ \btxspace
+ \btxflush{number}
+ }
+ \btxperiod
+ \italiccorrection
+ \endgroup
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url}
+ \texdefinition{btx:apa:note}
+\stopsetups
+
+% Electronic. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: title
+% Optional fields: address, author, howpublished, month, note, organization, url, year, doi
+% Also optional: type
+
+% Like Misc below but includes organization.
+
+\startsetups btx:apa:list:electronic
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \btxdoif {organization} {
+ \btxspace
+ \btxflush{organization}
+ \btxperiod
+ }
+ \btxdoif {howpublished} {
+ \btxspace
+ \btxflush{howpublished}
+ \btxperiod
+ }
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% Film. Note that this category was not defined with BIBTEX.
+% Required fields: producer, director, title, year, address, publisher
+% Optional fields: subtitle, type, note, url, doi
+
+\startsetups btx:apa:list:film
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition {btx:apa:title}
+ \btxleftbracket
+ \btxdoifelse {type} {
+ \btxflush{type}
+ } {
+ \btxlabeltext{apa:MotionPicture}
+ }
+ \btxrightbracketperiod
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% Music. Note that this category was not defined with BIBTEX.
+% Required fields: composer, artist, title, album, year, address, publisher
+% Optional fields: subtitle, type, note, url, doi
+
+\startsetups btx:apa:list:music
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \doifnot {\btxfoundname{author}} {artist} {
+ \btxdoif {artist} {
+ \btxleftbracket
+ \btxlabeltext{apa:Recordedby}
+ \btxspace
+ \btxflush{artist}
+ \btxrightbracketperiod
+ }
+ }
+ \doifnot {\btxfoundname{title}} {album} {
+ \btxdoif {album} {
+ \btxlabeltext{apa:In}
+ \btxspace
+ \btxflush{album}
+ \btxperiod
+ }
+ }
+ \btxdoif {type} {
+ \btxleftbracket
+ \btxflush{type}
+ \btxrightbracketperiod
+ }
+ \texdefinition{btx:apa:wherefrom-publisher}
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% Other. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: author or title, year
+% Optional fields: note, doi, url
+
+\startsetups btx:apa:list:other
+ \fastsetup{btx:apa:list:book}
+\stopsetups
+
+% Use this type when nothing else fits.
+% Required fields: none.
+% Optional fields: author, title, howpublished, month, year, note.
+
+\startsetups btx:apa:list:misc
+ \texdefinition{btx:apa:authoryear}
+ \texdefinition{btx:apa:title-if-not-placed}
+ \btxdoif {howpublished} {
+ \btxspace
+ \btxflush{howpublished}
+ \btxperiod
+ }
+ \texdefinition{btx:apa:url-doi-note}
+\stopsetups
+
+% If all else fails to match:
+
+\startsetups btx:apa:list:literal
+ %\btxleftparenthesis
+ \removeunwantedspaces(
+ \btxflush{tag}
+ \btxrightparenthesis
+ \btxdoif {text} {
+ \btxflush{text}
+ }
+\stopsetups
+
+% HH: an example of setting up translations using a sub rendering. Keep it here
+% till we find another spot as otherwise I forget about it and I don't want to
+% waste hours reinventing a wheel when something like this is needed.
+%
+% \definebtx
+% [apa:cite:title:translated]
+% [apa:cite:title]
+% [left=\btxleftbracket,
+% right=\btxrightbracket,
+% style=\v!bolditalic]
+%
+% \startsetups btx:apa:cite:title
+% % need to add concat, etc.
+% \btxcitereference
+% \currentbtxfirst
+% \doifmode {btx:apa:translatedtitles} {
+% \ifx\currentbtxlanguage\empty
+% % no need for an extra
+% \else\ifx\mainbtxlanguage\currentbtxlanguage
+% % no need for an extra
+% \else
+% \btxdoif {title:\mainbtxlanguage} {
+% \btxstartciterendering[title:translated]
+% \language[\mainbtxlanguage]
+% \btxflush{title:\mainbtxlanguage}
+% \btxstopciterendering
+% }
+% \fi\fi
+% }
+% \stopsetups
+
+\stopbtxrenderingdefinitions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.lua
new file mode 100644
index 00000000000..c15ffe918e9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.lua
@@ -0,0 +1,479 @@
+local specification = {
+ --
+ -- metadata
+ --
+ name = "aps",
+ version = "1.00",
+ comment = "APS specification",
+ author = "Alan Braslau and Hans Hagen",
+ copyright = "ConTeXt development team",
+ --
+ -- derived (combinations of) fields (all share the same default set)
+ --
+ virtual = {
+ "authoryear",
+ "authoryears",
+ "authornum",
+ "num",
+ "suffix",
+ },
+ --
+ -- special datatypes
+ --
+ types = {
+ --
+ -- list of fields that are interpreted as names: "NAME [and NAME]" where
+ -- NAME is one of the following:
+ --
+ -- First vons Last
+ -- vons Last, First
+ -- vons Last, Jrs, First
+ -- Vons, Last, Jrs, First
+ --
+ author = "author", -- interpreted as name(s)
+ editor = "author",
+ doi = "url", -- an external link
+ url = "url",
+ page = "pagenumber", -- number or range: f--t
+ pages = "pagenumber",
+ volume = "range",
+ number = "range",
+ keywords = "keyword", -- comma|-|separated list
+ year = "number",
+ },
+ --
+ -- categories with their specific fields
+ --
+ categories = {
+ --
+ -- categories are added below
+ --
+ },
+}
+
+local generic = {
+ --
+ -- A set returns the first field (in order of position below) that is found
+ -- present in an entry. A set having the same name as a field conditionally
+ -- allows the substitution of an alternate field.
+ --
+ -- note that anything can get assigned a doi or be available online.
+ editionset = { "edition", "volume", "number", "pages" },
+}
+
+-- Note that the APS specification allows an additional field "collaboration"
+-- to be rendered following the author list (if the collaboration name appears
+-- in the byline of the cited article).
+
+-- Definition of recognized categories and the fields that they contain.
+-- Required fields should be present; optional fields may also be rendered;
+-- all other fields will be ignored.
+
+-- Sets contain either/or in order of precedence.
+--
+-- For a category *not* defined here yet present in the dataset, *all* fields
+-- are taken as optional. This allows for flexibility in the addition of new
+-- categories.
+
+local categories = specification.categories
+
+-- an article from a journal
+
+categories.article = {
+ sets = {
+ author = { "author", "editor" },
+ },
+ required = {
+ "author",
+ },
+ optional = {
+ "collaboration",
+ "year",
+ "title", "subtitle", "type", "file",
+ "journal", "volume", "number", "pages",
+ "doi", "url", "note",
+ },
+}
+
+-- an article from a magazine
+
+categories.magazine = {
+ sets = categories.article.sets,
+ required = {
+ "author",
+ "year",
+ "journal",
+ },
+ optional = {
+ "collaboration",
+ "title", "subtitle", "type", "file",
+ "number", "pages",
+ "month", "day",
+ "doi", "url", "note",
+ },
+}
+
+categories.newspaper = categories.magazine
+
+-- (from jabref) to be identified and setup ...
+
+categories.periodical = {
+ sets = {
+ author = { "editor", "publisher" },
+ },
+ required = {
+ "title",
+ "year",
+ },
+ optional = {
+ "author",
+ "collaboration",
+ "subtitle", "file",
+ "series", "volume", "number", "month",
+ "organization",
+ "doi", "url", "note",
+ },
+}
+
+-- (from jabref) to be identified and setup ...
+
+categories.standard = {
+ sets = {
+ author = { "author", "institution", "organization" },
+ },
+ required = {
+ "author",
+ "year",
+ "title", "subtitle",
+ "doi", "note",
+ },
+ optional = {
+ "collaboration",
+ "url",
+ },
+}
+
+-- a book with an explicit publisher.
+
+categories.book = {
+ sets = {
+ author = { "author", "editor", "publisher" },
+ editionset = generic.editionset,
+ },
+ required = {
+ "author",
+ "title",
+ },
+ optional = {
+ "collaboration",
+ "year", "month", "day",
+ "title", "subtitle", "type", "file",
+ "editionset", "series",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+-- a part of a book, which may be a chapter (or section or whatever) and/or a range of pages.
+
+categories.inbook = {
+ sets = {
+ author = { "author", "editor", "publisher", },
+ editionset = generic.editionset,
+ },
+ required = {
+ "author",
+ "year" ,
+ "title",
+ },
+ optional = {
+ "collaboration",
+ "subtitle", "type", "file",
+ "booktitle",
+ -- "chapter",
+ "editionset", "series",
+ "month",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+-- a book having its own title as part of a collection.
+-- (like inbook, but we here make booktitle required)
+
+categories.incollection = {
+ sets = {
+ author = { "author", "editor", "publisher" },
+ editionset = generic.editionset,
+ },
+ required = {
+ "author",
+ "booktitle",
+ "year",
+ },
+ optional = {
+ "collaboration",
+ "title", "subtitle", "type", "file",
+ "editionset", "series",
+ "chapter",
+ "month",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+-- a work that is printed and bound, but without a named publisher or sponsoring institution.
+
+categories.booklet = {
+ sets = {
+ publisher = { "howpublished" }, -- no "publisher"!
+ },
+ required = {
+ "author",
+ "title",
+ },
+ optional = {
+ "publisher",
+ "collaboration",
+ "year", "month",
+ "subtitle", "type", "file",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+-- the proceedings of a conference.
+
+categories.proceedings = {
+ sets = {
+ author = { "editor", "organization", "publisher" }, -- no "author"!
+ publisher = { "publisher", "organization" },
+ editionset = generic.editionset,
+ },
+ required = {
+ "author",
+ "year"
+ },
+ optional = {
+ "collaboration",
+ "publisher",
+ "title", "subtitle", "file",
+ "editionset", "series",
+ "month",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+-- an article in a conference proceedings.
+
+categories.inproceedings = {
+ sets = categories.incollection.sets,
+ required = categories.incollection.required,
+ optional = {
+ "collaboration",
+ "title", "subtitle", "type", "file",
+ "month",
+ "edition", "series",
+ "address", "organization",
+ "doi", "url", "note",
+ },
+}
+
+categories.conference = categories.inproceedings
+
+-- a thesis (of course).
+
+categories.thesis = {
+ required = {
+ "author",
+ "title",
+ "school",
+ "year",
+ "type"
+ },
+ optional = {
+ "collaboration",
+ "subtitle", "file",
+ "month",
+ "address",
+ "doi", "url", "note",
+ },
+}
+
+categories.mastersthesis = {
+ sets = categories.thesis.sets,
+ required = {
+ "author",
+ "title",
+ "school",
+ "year"
+ },
+ optional = {
+ "collaboration",
+ "type",
+ "subtitle", "file",
+ "month",
+ "address",
+ "doi", "url", "note",
+ },
+}
+categories.phdthesis = categories.mastersthesis
+
+-- a report published by a school or other institution, usually numbered within a series.
+
+categories.techreport = {
+ sets = {
+ author = { "author", "institution", "publisher" },
+ publisher = { "publisher", "institution", },
+ editionset = { "type", "volume", "number", "pages" }, -- no "edition"!
+ },
+ required = {
+ "author",
+ "title",
+ "institution",
+ "year"
+ },
+ optional = {
+ "collaboration",
+ "publisher",
+ "address",
+ "subtitle", "file",
+ "editionset",
+ "month",
+ "doi", "url", "note",
+ },
+}
+
+-- technical documentation.
+
+categories.manual = {
+ sets = {
+ author = { "author", "organization", "publisher" },
+ publisher = { "publisher", "organization", },
+ editionset = generic.editionset,
+ },
+ required = {
+ "title"
+ },
+ optional = {
+ "author", "publisher",
+ "collaboration",
+ "address",
+ "subtitle", "file",
+ "editionset", "month", "year",
+ "doi", "url", "note",
+ },
+}
+
+-- a patent (of course).
+
+categories.patent = {
+ sets = {
+ author = { "author", "assignee", },
+ publisher = { "publisher", "assignee", },
+ year = { "year", "yearfiled", },
+ month = { "month", "monthfiled", },
+ day = { "day", "dayfiled", },
+ },
+ required = {
+ "nationality",
+ "number",
+ "year",
+ },
+ optional = {
+ "type",
+ --check this: "language",
+ "author", "publisher",
+ "collaboration",
+ "title", "subtitle", "file",
+ "address",
+ "day", "month",
+ "doi", "url", "note",
+ },
+}
+
+-- a document having an author and title, but not formally published.
+
+categories.unpublished = {
+ required = {
+ "author",
+ "title",
+ "note"
+ },
+ optional = {
+ "collaboration",
+ "subtitle", "file",
+ "year", "month",
+ "doi", "url",
+ },
+}
+
+-- like misc below but includes organization.
+
+categories.electronic = {
+ required = {
+ "title"
+ },
+ optional = {
+ "subtitle", "type", "file",
+ "year", "month",
+ "author",
+ "collaboration",
+ "address",
+ "organization",
+ "howpublished",
+ "doi", "url", "note",
+ },
+}
+
+-- use this type when nothing else fits.
+
+categories.misc = {
+ required = {
+ -- nothing is really important here
+ },
+ optional = {
+ "author",
+ "collaboration",
+ "title", "subtitle", "file",
+ "year", "month",
+ "howpublished",
+ "doi", "url", "note",
+ },
+}
+
+-- other (whatever jabref does not know!)
+
+categories.other = {
+ required = {
+ "author",
+ "title",
+ "year"
+ },
+ optional = {
+ "collaboration",
+ "subtitle", "file",
+ "doi", "url", "note",
+ },
+}
+
+-- if all else fails to match:
+
+categories.literal = {
+ sets = {
+ author = { "tag" }, -- need to check this!
+ },
+ required = {
+ "text"
+ },
+ optional = {
+ "author",
+ "doi", "url", "note"
+ },
+ virtual = false,
+}
+
+-- done
+
+return specification
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.mkvi
new file mode 100644
index 00000000000..6742457146b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-aps.mkvi
@@ -0,0 +1,1135 @@
+%D \module
+%D [ file=publ-imp-aps,
+%D version=2015.03.22,
+%D title=APS bibliography style,
+%D subtitle=Publications,
+%D author=Alan Braslau and Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted
+%D by \PRAGMA. See mreadme.pdf for details.
+
+\startbtxrenderingdefinitions[aps]
+
+%D Reference:
+%D \startTEX
+%D @Book{APS2011,
+%D title ={Physical Review Style and Notation Guide}
+%D year ={2011},
+%D month ={June}
+%D edition ={Revised},
+%D editor ={Waldron, A and Judd, P. and Miller, V.},
+%D address ={Ridge, NY},
+%D publisher={American Physical Society},
+%D Xpages ={26},
+%D url ={http://journals.aps.org/files/styleguide-pr.pdf}
+%D }
+%D \stopTEX
+
+% set ALL specific APS compliant values
+
+\definebtx
+ [aps]
+ [\c!default=default,
+ \c!specification=aps,
+ \c!otherstext={\btxspace{\it\btxlabeltext{aps:others}}},
+ \c!etallimit=10,
+ \c!etaldisplay=\btxparameter\c!etallimit,
+ %c!journalconversion=\v!normal,
+ \c!monthconversion=\v!month,
+ \c!title=\v!yes,
+ \c!separator:names:2={\btxcomma},
+ \c!separator:names:3={\btxcomma\btxlabeltext{aps:and}\space},
+ \c!separator:names:4={\btxspace\btxlabeltext{aps:and}\space}]
+
+% First, define and set list and rendering parameters
+
+\definebtxrendering
+ [aps]
+ [\c!specification=aps,
+ \c!sorttype=\v!default,
+ \c!numbering=num]
+
+\setupbtxlist
+ [aps]
+ [\c!alternative=b] % spaces
+
+\definebtx
+ [aps:\s!list]
+ [aps]
+ [\c!authorconversion=normalshort]
+
+\definebtx
+ [aps:\s!list:author]
+ [aps:\s!list]
+
+\definebtx
+ [aps:\s!list:editor]
+ [aps:\s!list:author]
+
+\definebtx
+ [aps:\s!list:suffix]
+ [aps:\s!list]
+
+\definebtx
+ [aps:\s!list:url]
+ [aps:\s!list]
+
+\definebtx
+ [aps:\s!list:doi]
+ [aps:\s!list]
+
+\definebtx
+ [aps:\s!list:\s!page]
+ [aps:\s!list]
+ [\c!separator:2={\btxcomma},
+ \c!separator:3={\btxcomma\btxlabeltext{aps:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{aps:and}\space},
+ \c!left={\btxleftparenthesis},
+ \c!right={\btxrightparenthesis},
+ \c!command={\wordright}]
+
+\definebtx
+ [aps:\s!list:numbering]
+ [aps:\s!list]
+ [left={[},
+ right={]}]
+
+\definebtx
+ [aps:\s!list:numbering:default]
+ [aps:\s!list:numbering]
+
+\definebtx
+ [aps:\s!list:numbering:num]
+ [aps:\s!list:numbering]
+
+\definebtx
+ [aps:\s!list:numbering:short]
+ [aps:\s!list:numbering]
+
+\definebtx
+ [aps:\s!list:numbering:tag]
+ [aps:\s!list:numbering]
+
+\definebtx
+ [aps:\s!list:numbering:index]
+ [aps:\s!list:numbering]
+
+%D In order to be able to get journals expanded (or normalized or abbreviated) you need
+%D to load a list:
+%D
+%D \starttyping
+%D \btxloadjournallist[journals.txt] % the jabref list
+%D \stoptyping
+
+% TODO
+
+\definebtx
+ [aps:\s!list:journal]
+ [aps:\s!list]
+ [\c!style=\v!italic]
+ %command=\btxexpandedjournal] % btxabbreviatedjournal
+
+\definebtx
+ [aps:\s!list:volume]
+ [aps:\s!list]
+ [\c!style=\v!bold]
+
+\definebtx
+ [aps:\s!list:title]
+ [aps:\s!list]
+ [\c!style=\v!italic,
+ \c!command=\Word]
+
+\definebtx
+ [aps:\s!list:title:article]
+ [aps:\s!list:title]
+ [\c!style=] % journal is set in italics
+
+\definebtx
+ [aps:\s!list:title:magazine]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:newspaper]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:periodical]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:standard]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:book]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:inbook]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:incollection]
+ [aps:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [aps:\s!list:title:proceedings]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:inproceedings]
+ [aps:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [aps:\s!list:title:conference]
+ [aps:\s!list:title]
+ [\c!style=] % booktitle is set in italics
+
+\definebtx
+ [aps:\s!list:title:thesis]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:phdthesis]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:mastersthesis]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:booklet]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:manual]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:techreport]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:unpublished]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:patent]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:electronic]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:other]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:misc]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:title:literal]
+ [aps:\s!list:title]
+
+\definebtx
+ [aps:\s!list:type]
+ [\c!command=\Word]
+
+% Then define and set all cite parameters
+
+\definebtx
+ [aps:\s!cite]
+ [aps]
+ [\c!alternative=num,
+ \c!authorconversion=\v!name,
+ \c!compress=\v!yes,
+ \c!sorttype=normal]
+
+\definebtx
+ [aps:\s!cite:name]
+ [aps:\s!cite]
+ [\c!authorconversion=\v!name]
+
+\definebtx
+ [aps:\s!cite:inverted]
+ [aps:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [aps:\s!cite:invertedshort]
+ [aps:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [aps:\s!cite:normalshort]
+ [aps:\s!cite]
+ [\c!authorconversion=\v!normalshort]
+
+\definebtx
+ [aps:\s!cite:normal]
+ [aps:\s!cite]
+ [\c!authorconversion=\v!normal]
+
+\definebtx
+ [aps:\s!cite:author]
+ [aps:\s!cite]
+
+\definebtx
+ [aps:\s!cite:authoryear]
+ [aps:\s!cite:author]
+ [\c!left={(},
+ \c!right={)},
+ \c!inbetween={\btxcomma}]
+
+\definebtx
+ [aps:\s!cite:authoryears]
+ [aps:\s!cite:authoryear]
+ [\c!left=,
+ \c!right=,
+ \c!inbetween={\btxspace}]
+
+\definebtx
+ [aps:\s!cite:authornum]
+ [aps:\s!cite:author]
+ [\c!left={(},
+ \c!right={)}]
+
+\definebtx
+ [aps:\s!cite:author:num] % todo
+ [aps:\s!cite:authornum]
+ [\c!left={\btxspace[},
+ \c!right={]}]
+
+\definebtx
+ [aps:\s!cite:author:year] % todo
+ [aps:\s!cite:authoryear]
+ [\c!left=,
+ \c!right=]
+
+\definebtx
+ [aps:\s!cite:author:years] % todo
+ [aps:\s!cite:authoryears]
+ [\c!inbetween=,
+ \c!left={\btxspace(},
+ \c!right={)}]
+
+\definebtx
+ [aps:\s!cite:year]
+ [aps:\s!cite]
+
+\definebtx
+ [aps:\s!cite:title]
+ [aps:\s!cite]
+ [\c!command={\language[\currentbtxlanguage]}, % BAH
+ \c!sorttype=none,
+ \c!style=\v!italic]
+
+\definebtx
+ [aps:\s!cite:booktitle]
+ [aps:\s!cite:title]
+
+\definebtx
+ [aps:\s!cite:tag]
+ [aps:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [aps:\s!cite:index]
+ [aps:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [aps:\s!cite:page]
+ [aps:\s!cite]
+ [\c!left=,
+ \c!right=,
+ \c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+ \c!separator:3={\btxcomma\btxlabeltext{aps:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{aps:and}\space}]
+
+\definebtx
+ [aps:\s!cite:pages]
+ [aps:\s!cite:page]
+
+\definebtx
+ [aps:\s!cite:keywords]
+ [aps:\s!cite]
+ [\c!left={(},
+ \c!right={)}]
+
+\definebtx
+ [aps:\s!cite:short]
+ [aps:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [aps:\s!cite:category]
+ [aps:\s!cite]
+
+\definebtx
+ [aps:\s!cite:url]
+ [aps:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [aps:\s!cite:doi]
+ [aps:\s!cite:url]
+
+\definebtx
+ [aps:\s!cite:num]
+ [aps:\s!cite]
+ [\c!left={[},
+ \c!right={]},
+ %\c!left=, % TODO: PRB uses superscript references...
+ %\c!right=, % and after punctuation, PRA, C, D, E, and L are before!
+ %\c!command={\high},
+ \c!separator:2={\btxcommabreak},
+ \c!separator:3=\btxparameter{\c!separator:2},
+ \c!separator:4=\btxparameter{\c!separator:2}]
+
+\definebtx
+ [aps:\s!cite:default]
+ [aps:\s!cite:num]
+
+\definebtx
+ [aps:\s!cite:textnum]
+ [aps:\s!cite:num]
+ [\c!left={Ref.\nbsp},
+ \c!command=,
+ \c!separator:2={\btxcomma},
+ \c!separator:3={\btxspace\btxlabeltext{aps:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{aps:and}\space}]
+
+\definebtx
+ [aps:\s!cite:entry]
+ [aps:\s!cite]
+ [\c!left=,
+ \c!right=,
+ \c!inbetween={\btxspace},
+ \c!separator:2={\btxsemicolon},
+ \c!separator:3=\btxparameter{\c!separator:2},
+ \c!separator:4=\btxparameter{\c!separator:2}]
+
+%D Sometimes we have verbose injections in an entry and these can be language
+%D dependent, so we use labels.
+%D
+%D Because we want to mix rendering (in the manual) we need a namespace in label
+%D texts:
+
+\setupbtxlabeltext
+ [en]
+ [aps:and=and,
+ aps:number={no.},
+ aps:edition={ed.},
+ aps:Editor={Ed.},
+ aps:Editors={Eds.},
+ aps:Volume={Vol.},
+ aps:Volumes={Vols.},
+ aps:others={et al.},
+ aps:page={p.},
+ aps:pages={pp.},
+ aps:mastersthesis={Master's thesis},
+ aps:phdthesis={Doctoral dissertation},
+ aps:technicalreport={Tech. Rep.}, % Technical report
+ aps:supplement={Suppl.}, % Supplement (not used?)
+ aps:patent=Patent,
+ aps:inpress={in press},
+ aps:tobe={to be published},
+ aps:unpublished={unpublished},
+ aps:In=In]
+
+% Check this (google translate!!):
+
+\setupbtxlabeltext
+ [nl]
+ [aps:and=en,
+ aps:number={nr.},
+ aps:edition={ed.}, % editie
+ aps:Editor=Editor, % Ed./Eds.
+ aps:Editors=Editors,
+ aps:Volume={Vol.},
+ aps:Volumes={Vols.},
+ aps:others={et al.},
+ aps:page={p.},
+ aps:pages={pp.},
+ aps:mastersthesis=Masterproef,
+ aps:phdthesis=Proefschrift,
+ aps:technicalreport={Technisch rapport}, % Technical report
+ aps:supplement=Supplement,
+ aps:patent=Octrooi,
+ aps:inpress={in press}, % CHECK THESE!
+ aps:tobe={worden gepubliceerd},
+ aps:unpublished={onuitgegeven},
+ aps:In=In]
+
+\setupbtxlabeltext
+ [fr]
+ [aps:and=et,
+ aps:number={n\high{o}},
+ aps:edition={édition},
+ aps:Editor=Éditeur,
+ aps:Editors=Éditeurs,
+ aps:Volume=Volume,
+ aps:Volumes=Volumes,
+ aps:others={et al.},
+ aps:page={p.},
+ aps:pages={pp.},
+ aps:mastersthesis={Thèse de master (DEA, DESS, master)},
+ aps:phdthesis={Thèse de doctorat},
+ aps:technicalreport={Rapport technique},
+ aps:supplement=Supplément,
+ aps:patent=Brevet,
+ aps:inpress={sous impression},
+ aps:tobe={à paraître},
+ aps:unpublished={inédit}, % pour un livre
+ aps:In=Dans]
+
+\setupbtxlabeltext
+ [de]
+ [aps:and=und,
+ aps:number={nr.},
+ aps:edition=Auf\/lage,
+ aps:Editor=Herausgeber, % Hrsg./Hg.
+ aps:Editors=Herausgeber,
+ aps:Volume=Band, % Bd.
+ aps:Volumes={Bände},
+ aps:others={et al.},
+ aps:page={S.},
+ aps:pages={S.},
+ aps:mastersthesis={Masterarbeit},
+ aps:phdthesis={Dissertation},
+ aps:technicalreport={Technischer Bericht},
+ aps:supplement={Beilage}, % Supplement
+ aps:patent=Patent,
+ aps:inpress={in der Presse}, % CHECK THESE!
+ aps:tobe={veröffentlicht werden},
+ aps:unpublished={unveröffentlicht},
+ aps:In=In]
+
+% thanks: Andrea Valle
+
+\setupbtxlabeltext
+ [it]
+ [aps:and=e,
+ aps:number={nº},
+ aps:edition={ed.}, % edizione
+ aps:Editor={A cura di},
+ aps:Editors={A cura di},
+ aps:Volume={Vol.}, % Volume
+ aps:Volumes={Vol.}, % Volumi
+ aps:others={et al.},
+ aps:page={p.},
+ aps:pages={pp.},
+ aps:mastersthesis={Tesi di laurea},
+ aps:phdthesis={Tesi di dottorato},
+ aps:technicalreport={Relazione tecnica},
+ aps:supplement={Supplemento},
+ aps:patent=Brevetto,
+ aps:inpress={in press}, % CHECK THESE!
+ aps:tobe={da pubblicare},
+ aps:unpublished={inedito},
+ aps:In=In]
+
+\setupbtxlabeltext
+ [es]
+ [aps:and=y,
+ aps:number={nº},
+ aps:edition={ed.}, % edición
+ aps:Editor=Editor, % Ed./Eds.
+ aps:Editors=Editores,
+ aps:Volume={Vol.}, % Volumen
+ aps:Volumes={Vols.}, % Volúmenes
+ aps:others={et al.},
+ aps:page={p.},
+ aps:pages={pp.},
+ aps:mastersthesis={Tesis de maestría},
+ aps:phdthesis={Tesis doctoral},
+ aps:technicalreport={Informe técnico},
+ aps:supplement=Suplemento,
+ aps:patent=Patente,
+ aps:inpress={en prensa}, % CHECK THESE!
+ aps:tobe={que se publicará},
+ aps:unpublished={inédito},
+ aps:In=En]
+
+% cite setups
+
+\startsetups btx:aps:nd
+ \doifelse {\currentbtxcategory} {article} {
+ \btxlabeltext{aps:tobe}
+ } {
+ \doifelse {\currentbtxcategory} {book} {
+ \btxlabeltext{aps:inpress}
+ } {
+ \btxlabeltext{aps:unpublished}
+ }
+ }
+\stopsetups
+
+\startsetups btx:aps:cite:author:year
+ \texdefinition{\s!btx:\s!cite:concat}
+ \ifx\currentbtxfirst\empty
+ \fastsetup{btx:aps:nd}
+ \else
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \currentbtxfirst
+ }
+ \ifx\currentbtxsecond\empty \else
+ \btxparameter\c!inbetween
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \currentbtxsecond
+ }
+ \fi
+ \btxflushsuffix
+ \fi
+\stopsetups
+
+\startsetups btx:aps:cite:author:years
+ \fastsetup{btx:aps:cite:author:year}
+\stopsetups
+
+% used in publ-imp-page.mkvi
+
+\startsetups [btx:aps:list:page-or-pages]
+ \ifx\currentbtxlastpage\empty
+ \btxlabeltext{aps:page}
+ \else
+ \btxlabeltext{aps:pages}
+ \fi
+ \btxnbsp
+\stopsetups
+
+%D Instead of texdefinitions without arguments, we could have used setups but in my
+%D editor (hh, scite) the commands stand out better. It also saves an additional
+%D component in the name (e.g. common:) because commands and setups have a different
+%D namespace, so similar calls don't clash. Performance of definitions is somewhat
+%D better.
+
+%D We use "texdefinitions" (with eventual arguments) for helpers that are used
+%D in the rendering "setups" defined for each category below.
+
+%D Note that \btxdoif... and \btxflush rely on the definitions in
+%D publ-imp-aps.lua: fields that are not listed as required nor optional are
+%D IGNORED. We also make heavy use of the notion of sets - comma-separated lists
+%D of alternative fields to be used in hierarchal order. For example:
+%D author = { "author", "editor", "publisher", "title" }, will return the
+%D author field if it exists; if not, the editor field will be returned, if it
+%D exists; if not, the publisher field will be returned, if it exists; if not,
+%D the title field will be returned, it it exists; if not, nothing will be
+%D returned. In lua syntax, it can be understood as
+%D author or editor or publisher or title or ""
+
+\starttexdefinition unexpanded btx:aps:composed-title #title
+ \btxstartstyleandcolor [aps:\s!list:title:\currentbtxcategory]
+ \begingroup
+ \language[\currentbtxlanguage]
+ \btxusecommand [aps:\s!list:title:\currentbtxcategory] {
+ \btxflush{#title}
+ \btxdoif {sub#title} {
+ \btxcolon
+ \btxflush{sub#title}
+ }
+ }
+ \endgroup
+ \btxstopstyleandcolor
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:title
+ \btxdoif {title} {
+ % we make the title active, opening file
+ \btxdoifelse {file} {
+ \texdefinition{btx:format:inject}
+ {url(file:\btxflush{file})}
+ {
+ \texdefinition{btx:aps:composed-title}{title}
+ }
+ } {
+ \texdefinition{btx:aps:composed-title}{title}
+ }
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:optional-title
+ \doif{\btxparameter{\c!title}}\v!yes {
+ \texdefinition {btx:aps:title}
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:year
+ \btxdoifelse {year} {
+ \btxflush{year}
+ } {
+ \fastsetup{btx:aps:nd}
+ }
+\stoptexdefinition
+
+% #author may be author(set) or editor
+
+\starttexdefinition unexpanded btx:aps:author-or-editor #author
+ \btxdoif {#author} {
+ \btxflush{#author}
+ \doifelse {\btxfoundname{#author}} {editor} {
+ \btxleftparenthesis
+ \btxsingularorplural {editor} {
+ \btxlabeltext{aps:Editor}
+ } {
+ \btxlabeltext{aps:Editors}
+ }
+ \btxrightparenthesis
+ } {
+ \btxdoif {collaboration} {
+ \btxleftparenthesis
+ \btxflush{collaboration}
+ \btxrightparenthesis
+ }
+ }
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:author
+ \btxflush{author}
+ \btxcomma
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:editor-in
+ \btxdoif {booktitle} {
+ \btxlabeltext{aps:In}
+ \doifnot {\btxfoundname{author}} {editor} {
+ \btxspace
+ \texdefinition{btx:aps:author-or-editor} {editor}
+ }
+ \btxspace
+ \texdefinition{btx:aps:composed-title}{booktitle}
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:editionset
+ \doif {\currentbtxcategory} {techreport} {
+ \btxdoifelse {type} {
+ \btxusecommand [\currentbtx:type] {
+ \btxflush{type}
+ }
+ } {
+ \btxlabeltext{aps:technicalreport}
+ }
+ \btxcomma
+ }
+ \btxdoif {volume} {
+ \btxoneorrange {volume} {
+ \btxlabeltext{aps:Volume}
+ } {
+ \btxlabeltext{aps:Volumes}
+ }
+ \btxspace
+ \btxflush{volume}
+ \btxcomma
+ }
+ \btxdoif {number} {
+ \btxlabeltext{aps:number}
+ \btxspace
+ \btxflush{number}
+ \btxcomma
+ }
+ \btxdoif {edition} {
+ \btxflush{edition}
+ \btxspace
+ \btxlabeltext{aps:edition}
+ \btxcomma
+ }
+ \btxdoif {pages} {
+ \btxoneorrange {pages} {
+ \btxlabeltext{aps:page}
+ } {
+ \btxlabeltext{aps:pages}
+ }
+ \btxnbsp
+ \btxflush{pages}
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:journal-volume-year
+ \btxdoif {journal} {
+ \btxstartstyleandcolor [aps:\s!list:journal]
+ % expandedjournal abbreviatedjournal
+ \btxflush{expandedjournal -> journal}
+ \btxstopstyleandcolor
+ \btxdoifelse {volume} {
+ \btxspace
+ \btxstartstyleandcolor [aps:\s!list:volume]
+ \btxflush{volume}
+ \btxstopstyleandcolor
+ \btxdoif {number} {
+ \removeunwantedspaces(
+ \btxflush{number}
+ \btxrightparenthesiscomma
+ }
+ } {
+ \btxdoif {number} {
+ \btxspace
+ \btxflush{number}
+ \btxcomma
+ }
+ }
+ \btxdoif {pages} {
+ \btxspace
+ \btxflush{pages}
+ }
+ }
+ \btxleftparenthesis
+ \texdefinition{btx:aps:year}
+ \btxrightparenthesis
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:publisher-wherefrom-year
+ \removeunwantedspaces
+ \removepunctuation
+ \btxleftparenthesis
+ \btxflush{publisher}
+ \btxdoifelse {address} {
+ \btxdoif {publisher} {
+ \btxcomma
+ }
+ \btxflush{address}
+ \btxdoif {country} {
+ \btxcomma
+ \btxflush{country}
+ }
+ \btxcomma
+ } {
+ \btxdoif {publisher} {
+ \btxcomma
+ }
+ }
+ \texdefinition{btx:aps:year}
+ \btxrightparenthesis
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:note
+ \btxperiod
+ \btxdoif {note} {
+ \btxleftparenthesis
+ \btxflush{note}
+ \btxrightparenthesis
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:aps:doi-url #text
+ \ifconditional\btxinteractive
+ \btxdoifelse {doi} {
+ \goto {#text} [url(http://dx.doi.org/\btxflush{doi})]
+ } {
+ \btxdoifelse {url} {
+ \goto {#text} [url(\btxflush{url})]
+ } {
+ #text
+ }
+ }
+ \else
+ #text
+ \fi
+\stoptexdefinition
+
+% Then setups, by category
+
+% An article from a journal
+% Required fields: author or editor or title, journal, (year).
+% Optional fields: volume, number, pages, type, doi, url, note.
+% Note that bibtex (and tools) do not include editor (e.g. special issue or section)
+
+\startsetups btx:aps:list:article
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:optional-title}
+ \texdefinition{btx:aps:doi-url} {\texdefinition{btx:aps:journal-volume-year}}
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+% An article from a magazine.
+% Required fields: author or title, journal, (year).
+% Optional fields: number, pages, type, month, day, doi, url, note.
+
+\startsetups btx:aps:list:magazine
+ \fastsetup{btx:aps:list:article}
+\stopsetups
+
+% An article from a newspaper.
+% Required fields: author or title, journal, (year).
+% Optional fields: number, pages, type, month, day, doi, url, note.
+
+\startsetups btx:aps:list:newspaper
+ \fastsetup{btx:aps:list:article}
+\stopsetups
+
+% A complete issue of a periodical, such as a special issue of a journal.
+% Required fields: title, year
+% Optional fields: editor, publisher, subtitle, series, volume, number, month, organization, doi, url, issn, note
+
+% needs to be tuned...
+\startsetups btx:aps:list:periodical
+ \fastsetup{btx:aps:list:article}
+\stopsetups
+
+% National and international standards issued by a standards body
+% Required fields: author, institution, or organization, year, title
+% Optional fields: subtitle, doi, url, note
+
+\startsetups btx:aps:list:standard
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \texdefinition{btx:aps:note}
+\stopsetups
+% year?
+
+% A book with an explicit publisher.
+% Required fields: author or editor or publisher, title, (year).
+% Optional fields: volume or number, series, address, edition, month, day, note.
+% APS? ignores: month, day
+
+% todo: series?
+
+\startsetups btx:aps:list:book
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \texdefinition{btx:aps:editionset}
+ \texdefinition{btx:aps:doi-url} {\texdefinition{btx:aps:publisher-wherefrom-year}}
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+% There is some debate about how inbook should differ from incollection
+
+% A part of a book, which may be a chapter (or section or whatever) and/or a range of pages.
+% (note that inbook is handled differently by bibtex and biblatex)
+% Required fields: author or editor, title, chapter and/or pages, publisher, year.
+% Optional fields: volume or number, series, type, address, edition, month, note.
+% We add optional: booktitle.
+% APS? ignores: chapter, month
+
+\startsetups btx:aps:list:inbook
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \texdefinition{btx:aps:editor-in}
+ \texdefinition{btx:aps:editionset}
+ \texdefinition{btx:aps:doi-url} {\texdefinition{btx:aps:publisher-wherefrom-year}}
+ \texdefinition{btx:aps:note}
+\stopsetups
+% chapter?
+
+% A part of a book having its own title.
+% Required fields: author, title, booktitle, publisher, year.
+% Optional fields: editor, volume or number, series, type, chapter, pages, address, edition, month, note.
+% APS? ignores: chapter, month
+
+\startsetups btx:aps:list:incollection
+ \fastsetup{btx:aps:list:inbook}
+\stopsetups
+
+% The proceedings of a conference.
+% Required fields: title, year.
+% Optional fields: editor, volume or number, series, address, month, organization, publisher, note.
+% todo: series?
+
+\startsetups btx:aps:list:proceedings
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% An article in a conference proceedings.
+% Required fields: author, title, booktitle, year.
+% Optional fields: editor, volume or number, series, pages, address, month, organization, publisher, note.
+
+\startsetups btx:aps:list:inproceedings
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \texdefinition{btx:aps:editor-in}
+ \texdefinition{btx:aps:editionset}
+ \btxdoif {organization} {
+ \btxspace
+ \btxflush{organization}
+ \btxcomma
+ }
+ \texdefinition{btx:aps:doi-url} {\texdefinition{btx:aps:publisher-wherefrom-year}}
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+\startsetups btx:aps:list:conference
+ \fastsetup{btx:aps:list:inproceedings}
+\stopsetups
+
+% A thesis.
+% Required fields: author, title, school, year.
+% Optional fields: type, address, month, note.
+
+\startsetups btx:aps:list:thesis
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \btxleftparenthesis
+ \btxdoifelse {type} {
+ \btxusecommand [aps:list:type] {
+ \btxflush{type}
+ }
+ } {
+ \btxlabeltext{aps:\currentbtxcategory}
+ }
+ \btxrightparenthesis
+ \btxdoif {school} {
+ \btxperiod
+ \btxflush{school}
+ }
+ \btxdoif {address} {
+ \btxdoifelse {school} {
+ \btxcomma
+ } {
+ \btxperiod
+ }
+ \btxflush{address}
+ \btxdoif {country} {
+ \btxcomma
+ \btxflush{country}
+ }
+ }
+ \btxleftparenthesis
+ \texdefinition{btx:aps:year}
+ \btxrightparenthesis
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+\startsetups btx:aps:list:phdthesis
+ \fastsetup{btx:aps:list:thesis}
+\stopsetups
+
+\startsetups btx:aps:list:mastersthesis
+ \fastsetup{btx:aps:list:thesis}
+\stopsetups
+
+% A work that is printed and bound, but without a named publisher or sponsoring institution.
+% Required field: title.
+% Optional fields: author, howpublished, address, month, year, note.
+
+\startsetups btx:aps:list:booklet
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% Technical documentation.
+% Required field: title.
+% Optional fields: author, organization, address, edition, month, year, note.
+
+\startsetups btx:aps:list:manual
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% A report published by a school or other institution, usually numbered within a series.
+% Required fields: author, title, institution, year.
+% Optional fields: type, number, address, month, note.
+
+\startsetups btx:aps:list:techreport
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% A document having an author and title, but not formally published.
+% Required fields: author, title, note.
+% Optional fields: month, year.
+
+\startsetups btx:aps:list:unpublished
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% A patent. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: nationality, number, year, yearfiled
+% Optional fields: author, title, assignee, address, type, number, day, dayfiled, month, monthfiled, note, url
+% Also optional: publisher
+
+% todo: yearfiled, monthfiled, dayfiled
+
+\startsetups btx:aps:list:patent
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \begingroup
+ \it
+ \btxdoif {nationality} {
+ \btxspace
+ \btxflush{nationality}
+ }
+ \btxspace
+ \btxlabeltext{aps:patent}
+ \btxdoif {number} {
+ \btxspace
+ \btxlabeltext{aps:number}
+ \btxspace
+ \btxflush{number}
+ }
+ \btxperiod
+ \italiccorrection
+ \endgroup
+ \texdefinition{btx:aps:doi-url} {\texdefinition{btx:aps:publisher-wherefrom-year}}
+ \texdefinition{btx:aps:url}
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+% Electronic. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: title
+% Optional fields: address, author, howpublished, month, note, organization, url, year, doi
+% Also optional: type
+
+% Like Misc below but includes organization.
+
+\startsetups btx:aps:list:electronic
+ \texdefinition{btx:aps:author}
+ \texdefinition{btx:aps:title}
+ \btxdoif {organization} {
+ \btxspace
+ \btxflush{organization}
+ \btxperiod
+ }
+ \btxdoif {howpublished} {
+ \btxspace
+ \btxflush{howpublished}
+ }
+ \btxleftparenthesis
+ \texdefinition{btx:aps:year}
+ \btxrightparenthesis
+ \texdefinition{btx:aps:note}
+\stopsetups
+
+% Other. Note that this category was not defined with BIBTEX. Below from JabRef:
+% Required fields: author or title, year
+% Optional fields: note, doi, url
+
+\startsetups btx:aps:list:other
+ \fastsetup{btx:aps:list:book}
+\stopsetups
+
+% Use this type when nothing else fits.
+% Required fields: none.
+% Optional fields: author, title, howpublished, month, year, note.
+
+\startsetups btx:aps:list:misc
+ \fastsetup{btx:aps:list:electronic}
+ % Note that organization is an "ignored" field.
+\stopsetups
+
+% If all else fails to match:
+
+\startsetups btx:aps:list:literal
+ %\btxleftparenthesis
+ \removeunwantedspaces(
+ \btxflush{tag}
+ \btxrightparenthesis
+ \btxdoif {text} {
+ \btxflush{text}
+ }
+\stopsetups
+
+\stopbtxrenderingdefinitions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-author.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-author.mkvi
new file mode 100644
index 00000000000..b524331867c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-author.mkvi
@@ -0,0 +1,303 @@
+% TODO: MAKE default
+
+%D \module
+%D [ file=publ-imp-author,
+%D version=2014.06.23,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Authors,
+%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
+
+% these can be used instead of the macros and they accept manipulator prefixes
+%
+% \currentbtxinitials : \btxauthorfield{initials}
+% \currentbtxfirstnames : \btxauthorfield{firstnames}
+% \currentbtxvons : \btxauthorfield{vons}
+% \currentbtxsurnames : \btxauthorfield{surnames}
+% \currentbtxjuniors : \btxauthorfield{juniors}
+
+\starttexdefinition unexpanded \s!btx:\s!cite:\s!author:\s!de
+ \ifx\currentbtxlanguage\s!de
+ \setmode{\s!btx:\s!de}
+ \fi
+\stoptexdefinition
+
+\startsetups \s!btx:\s!cite:\s!author:concat
+ \ifcase\currentbtxoverflow
+ \btxparameter{\c!separator:names:\number\currentbtxconcat}
+ \else\ifnum\currentbtxauthorindex>\plusone
+ \btxparameter{\c!separator:names:2}
+ \fi\fi
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:others
+ \ifcase\currentbtxoverflow \else
+ \btxparameter\c!otherstext
+ \fi
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:normal
+ \fastsetup{\s!btx:\s!cite:\s!author:concat}
+ \ifx\currentbtxfirstnames\empty \else
+ \currentbtxfirstnames
+ \btxparameter{\c!separator:firstnames}
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \ifx\currentbtxsurnames\empty \else
+ \btxparameter{\c!separator:vons}
+ \fi
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \fastsetup{\s!btx:\s!cite:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:normalshort
+ \fastsetup{\s!btx:\s!cite:\s!author:concat}
+ \ifx\currentbtxinitials\empty \else
+ \currentbtxinitials
+ \btxparameter{\c!separator:initials}
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \ifx\currentbtxsurnames\empty \else
+ \btxparameter{\c!separator:vons}
+ \fi
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \fastsetup{\s!btx:\s!cite:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:inverted
+ \fastsetup{\s!btx:\s!cite:\s!author:concat}
+ \ifx\currentbtxvons\empty \else
+ \texdefinition{\s!btx:\s!cite:\s!author:\s!de}
+ \doifmode {\s!btx:\s!de} {
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ }
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \ifx\currentbtxfirstnames\empty
+ % firstnames are optional
+ \else
+ \btxparameter{\c!separator:invertedfirstnames}
+ \currentbtxfirstnames
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \doifnotmode {\s!btx:\s!de} {
+ \btxparameter{\c!separator:vons}
+ \currentbtxvons
+ }
+ \fi
+ \fastsetup{\s!btx:\s!cite:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:invertedshort
+ \fastsetup{\s!btx:\s!cite:\s!author:concat}
+ \ifx\currentbtxvons\empty \else
+ \texdefinition{\s!btx:\s!cite:\s!author:\s!de}
+ \doifnotmode {\s!btx:\s!de} {
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ }
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \ifx\currentbtxinitials\empty
+ % initials are optional
+ \else
+ \btxparameter{\c!separator:invertedinitials}
+ \currentbtxinitials
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \doifmode {\s!btx:\s!de} {
+ \btxparameter{\c!separator:vons}
+ \currentbtxvons
+ }
+ \fi
+ \fastsetup{\s!btx:\s!cite:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!cite:\s!author:name
+ \fastsetup{\s!btx:\s!cite:\s!author:concat}
+ % is this treated differently in german?
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ \fi
+ \currentbtxsurnames
+ \ifcase\currentbtxauthorstate \else
+ % potential clash of names so we force initials
+ \ifx\currentbtxinitials\empty \else
+ \btxparameter{\c!separator:invertedinitials}
+ \currentbtxinitials
+ \fi
+ \fi
+ \fastsetup{\s!btx:\s!cite:\s!author:others}
+\stopsetups
+
+% list (mostly the same)
+
+\startsetups \s!btx:\s!list:\s!author:concat
+ \ifcase\currentbtxoverflow
+ \btxparameter{\c!separator:names:\number\currentbtxconcat}
+ \else\ifnum\currentbtxauthorindex>\plusone
+ \btxparameter{\c!separator:names:2}
+ \fi\fi
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:others
+ \ifcase\currentbtxoverflow \else
+ \btxparameter\c!otherstext
+ \fi
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:normal
+ \fastsetup{\s!btx:\s!list:\s!author:concat}
+ \ifx\currentbtxfirstnames\empty \else
+ \currentbtxfirstnames
+ \btxparameter{\c!separator:firstnames}
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \ifx\currentbtxsurnames\empty \else
+ \btxparameter{\c!separator:vons}
+ \fi
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \fastsetup{\s!btx:\s!list:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:normalshort
+ \fastsetup{\s!btx:\s!list:\s!author:concat}
+ \ifx\currentbtxinitials\empty \else
+ \currentbtxinitials
+ \btxparameter{\c!separator:initials}
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \ifx\currentbtxsurnames\empty \else
+ \btxparameter{\c!separator:vons}
+ \fi
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \fastsetup{\s!btx:\s!list:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:inverted
+ \fastsetup{\s!btx:\s!list:\s!author:concat}
+ \ifx\currentbtxvons\empty \else
+ \texdefinition{\s!btx:\s!cite:\s!author:\s!de}
+ \doifnotmode {\s!btx:\s!de} {
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ }
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \ifx\currentbtxfirstnames\empty
+ % firstnames are optional
+ \else
+ \btxparameter{\c!separator:invertedfirstnames}
+ \currentbtxfirstnames
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \doifmode {\s!btx:\s!de} {
+ \btxparameter{\c!separator:vons}
+ \currentbtxvons
+ }
+ \fi
+ \fastsetup{\s!btx:\s!list:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:invertedshort
+ \fastsetup{\s!btx:\s!list:\s!author:concat}
+ \ifx\currentbtxvons\empty \else
+ \texdefinition{\s!btx:\s!cite:\s!author:\s!de}
+ \doifnotmode {\s!btx:\s!de} {
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ }
+ \fi
+ \ifx\currentbtxsurnames\empty \else
+ \currentbtxsurnames
+ \ifx\currentbtxjuniors\empty \else
+ \btxparameter{\c!separator:juniors}
+ \currentbtxjuniors
+ \fi
+ \fi
+ \ifx\currentbtxinitials\empty
+ % initials are optional
+ \else
+ \btxparameter{\c!separator:invertedinitials}
+ \currentbtxinitials
+ \fi
+ \ifx\currentbtxvons\empty \else
+ \doifmode {\s!btx:\s!de} {
+ \btxparameter{\c!separator:vons}
+ \currentbtxvons
+ }
+ \fi
+ \fastsetup{\s!btx:\s!list:\s!author:others}
+\stopsetups
+
+\startsetups \s!btx:\s!list:\s!author:name
+ \fastsetup{\s!btx:\s!list:\s!author:concat}
+ % is this treated differently in german?
+ \ifx\currentbtxvons\empty \else
+ \currentbtxvons
+ \btxparameter{\c!separator:vons}
+ \fi
+ \currentbtxsurnames
+ \fastsetup{\s!btx:\s!list:\s!author:others}
+\stopsetups
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi
new file mode 100644
index 00000000000..cb1c46fe480
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi
@@ -0,0 +1,280 @@
+%D \module
+%D [ file=publ-imp-cite,
+%D version=2013.12.24,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Citations,
+%D author=Alan Braslau and 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
+
+\starttexdefinition unexpanded btx:cite:inject #content
+ \ifconditional\btxinteractive
+ \ifx\currentbtxinternal\empty
+ #content
+ \else
+ \goto {
+ #content
+ } [
+ \s!internal(\currentbtxinternal)
+ ]
+ \fi
+ \else
+ #content
+ \fi
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:cite:checkconcat
+ \ifnum\currentbtxcount>\zerocount
+ \let\currentbtxinternal\empty
+ \let\currentbtxbacklink\empty
+ \fi
+\stoptexdefinition
+
+% The null case:
+
+\startsetups btx:cite:none
+ \btxcitereference
+ % dummy
+\stopsetups
+
+\startsetups btx:cite:nocite
+ \dontleavehmode
+ \btxcitereference
+\stopsetups
+
+\startsetups btx:cite:unknown
+ \begingroup
+ \tttf
+ \btxcitereference
+ \currentbtxfirst
+ \endgroup
+\stopsetups
+
+\startsetups btx:cite:empty
+ \btxcitereference
+ <empty>
+\stopsetups
+
+\startsetups btx:cite:invalid
+ \btxcitereference
+ {\tt <\currentbtxreference>}
+\stopsetups
+
+\starttexdefinition unexpanded btx:cite:concat
+ \btxparameter{\c!separator:\number\currentbtxconcat}
+\stoptexdefinition
+
+% when we have an author-year combination, the first and seconds is not
+% fields data but something more complex (that itself calls for a setup)
+
+% \startsetups btx:cite:normal
+% \texdefinition{\s!btx:\s!cite:concat}
+% \currentbtxlefttext
+% \ifx\currentbtxfirst\empty
+% \fastsetup{\s!btx:\s!cite:\s!empty}
+% \else
+% \texdefinition {\s!btx:\s!cite:inject} {
+% \btxcitereference
+% \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+% \currentbtxfirst
+% }
+% }
+% \ifx\currentbtxsecond\empty
+% \btxflushsuffix
+% \else
+% \btxparameter\c!inbetween
+% \texdefinition {\s!btx:\s!cite:inject} {
+% \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+% \currentbtxsecond
+% }
+% }
+% % quite likely an error
+% \btxflushsuffix
+% \fi
+% \fi
+% \currentbtxrighttext
+% \stopsetups
+
+\startsetups btx:cite:normal
+ \texdefinition{\s!btx:\s!cite:concat}
+ \currentbtxlefttext
+ \ifx\currentbtxfirst\empty
+ \fastsetup{\s!btx:\s!cite:\s!empty}
+ \else\ifx\currentbtxsecond\empty
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+ \currentbtxfirst
+ \btxflushsuffix
+ }
+ }
+ \else
+ % \texdefinition {\s!btx:\s!cite:inject} {
+ % \btxcitereference
+ % \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+ % \currentbtxfirst
+ % }
+ % }
+ % \btxparameter\c!inbetween
+ % \texdefinition {\s!btx:\s!cite:inject} {
+ % \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+ % \currentbtxsecond
+ % }
+ % }
+ % \btxflushsuffix
+ %
+ % probably better:
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+ \currentbtxfirst
+ \btxparameter\c!inbetween
+ \currentbtxsecond
+ \btxflushsuffix
+ }
+ }
+ \fi\fi
+ \currentbtxrighttext
+\stopsetups
+
+\startsetups btx:cite:range
+ \texdefinition{\s!btx:\s!cite:concat}
+ \currentbtxlefttext
+ \ifx\currentbtxfirst\empty
+ \fastsetup{\s!btx:\s!cite:\s!empty}
+ \else
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \btxusecommand [\currentbtxspecification:cite:\currentbtxcitealternative] {
+ \currentbtxfirst
+ \ifx\currentbtxsecond\empty \else
+ \btxparameter\c!range
+ \currentbtxsecond
+ \fi
+ \btxflushsuffix
+ }
+ }
+ \fi
+ \currentbtxrighttext
+\stopsetups
+
+% somehow related to keywords:
+
+\startsetups btx:cite:listelement
+ \texdefinition{\s!btx:\s!cite:concat}
+ \currentbtxlefttext
+ \ifx\currentbtxfirst\empty
+ \fastsetup{\s!btx:\s!cite:\s!empty}
+ \else
+ \texdefinition {\s!btx:\s!cite:inject} {
+ \btxcitereference
+ \currentbtxfirst
+ }
+ \fi
+ \currentbtxrighttext
+\stopsetups
+
+\startsetups \s!btx:\s!cite:entry
+ \texdefinition{\s!btx:\s!cite:concat}
+ \currentbtxlefttext
+ \btxhandleciteentry
+ \currentbtxrighttext
+\stopsetups
+
+% these three are goodies to get something but are not set up as it makes no
+% sense to have something root for combinations like this (esp not because one
+% gets default anyway
+
+% AB: not so sure about that. Why define them in default rather than here?
+
+\startsetups \s!btx:\s!cite:author
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:authoryear
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:authoryears
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:authornum
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:num
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+\startsetups \s!btx:\s!cite:default
+ \fastsetup{\s!btx:\s!cite:num}
+\stopsetups
+\startsetups \s!btx:\s!cite:textnum
+ \fastsetup{\s!btx:\s!cite:num}
+\stopsetups
+\startsetups \s!btx:\s!cite:year
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+\startsetups \s!btx:\s!cite:author:num
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+\startsetups \s!btx:\s!cite:author:year
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+\startsetups \s!btx:\s!cite:author:years
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+
+\startsetups \s!btx:\s!cite:index
+ \fastsetup{\s!btx:\s!cite:range}
+\stopsetups
+\startsetups \s!btx:\s!cite:category
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:short
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:tag
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+% the following correspond to fields, but can be used in many renderings
+
+\startsetups \s!btx:\s!cite:keywords
+ \fastsetup{\s!btx:\s!cite:list}
+\stopsetups
+\startsetups \s!btx:\s!cite:title
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+\startsetups \s!btx:\s!cite:pages
+ \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
+
+\startsetups \s!btx:\s!cite:page
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+% the following is kind of specific, but can be used in many renderings
+
+\startsetups btx:cite:url
+ \ifx\currentbtxfirst\empty
+ \fastsetup{\s!btx:\s!cite:\s!empty}
+ \else\ifconditional\btxinteractive
+ \goto {
+ \btxcitereference
+ \hyphenatedurl{\doif{\currentbtxcitealternative}{doi}{doi:}\currentbtxfirst}
+ } [
+ url(\doif{\currentbtxcitealternative}{doi}{http://dx.doi.org/}\currentbtxfirst)
+ ]
+ \else
+ \btxcitereference
+ \hyphenatedurl{\doif{\currentbtxcitealternative}{doi}{doi:}\currentbtxfirst}
+ \fi\fi
+\stopsetups
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-commands.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-commands.mkvi
new file mode 100644
index 00000000000..14e2dbae12d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-commands.mkvi
@@ -0,0 +1,15 @@
+\unprotect
+
+% for tugboat
+
+\definebtxcommand\hbox {\hbox}
+\definebtxcommand\vbox {\vbox}
+\definebtxcommand\llap {\llap}
+\definebtxcommand\rlap {\rlap}
+\definebtxcommand\url #1{\hyphenatedurl{#1}}
+\definebtxcommand\acro #1{\dontleavehmode{\smallcaps#1}}
+
+\let\<<
+\let\<>
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.lua
new file mode 100644
index 00000000000..61b08f30cef
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.lua
@@ -0,0 +1,124 @@
+-- For the moment I put this here as example. When writing the publication modules we
+-- explored several approached: pure tex, pure lua, a mix with xml, etc. In the end
+-- each has advantages and drawbacks so we ended up with readable tex plus helpers in
+-- lua. Anyway here is a lua variant of a setup ... it doesn't look nicer. An alternative
+-- can be to build a table with characters but then we need to pass left, right and
+-- other separators so again no real gain.
+
+-- function publications.maybe.default.journal(currentdataset,currenttag)
+-- if publications.okay(currentdataset,currenttag,"journal") then
+-- context.btxspace()
+-- context.startbtxstyle("italic")
+-- commands.btxflush(currentdataset,currenttag,"expandedjournal -> journal")
+-- context.stopbtxstyle()
+-- if publications.okay(currentdataset,currenttag,"volume") then
+-- context.btxspace()
+-- commands.btxflush(currentdataset,currenttag,"volume")
+-- if publications.okay(currentdataset,currenttag,"number") then
+-- context.ignorespaces()
+-- context.btxleftparenthesis()
+-- commands.btxflush(currentdataset,currenttag,"number")
+-- context.btxrightparenthesis()
+-- end
+-- elseif publications.okay(currentdataset,currenttag,"number") then
+-- context.btxlabeltext("default:number")
+-- context.btxspace()
+-- commands.btxflush(currentdataset,currenttag,"number")
+-- end
+-- if publications.okay(currentdataset,currenttag,"pages") then
+-- context.btxcomma()
+-- commands.btxflush(currentdataset,currenttag,"pages")
+-- end
+-- context.btxcomma()
+-- end
+-- end
+
+return {
+ --
+ -- metadata
+ --
+ name = "default",
+ version = "1.00",
+ comment = "DEFAULT specification",
+ author = "Alan Braslau and Hans Hagen",
+ copyright = "ConTeXt development team",
+ --
+ -- derived (combinations of) fields (all share the same default set)
+ --
+ virtual = {
+ "authoryear",
+ "authoryears",
+ "authornum",
+ "num",
+ "suffix",
+ },
+ --
+ -- special datatypes
+ --
+ types = {
+ author = "author", -- interpreted as name(s)
+ editor = "author", -- interpreted as name(s)
+ page = "pagenumber", -- number or range: f--t -- maybe just range
+ pages = "pagenumber", -- number or range: f--t -- maybe just range
+ volume = "range", -- number or range: f--t
+ number = "range", -- number or range: f--t
+ keywords = "keyword", -- comma|-|separated list
+ },
+ --
+ -- categories with their specific fields
+ --
+ categories = {
+ --
+ -- the following fields are for documentation and testing purposes
+ --
+ ["demo-a"] = {
+ sets = {
+ author = { "author", "institution", "organization" },
+ },
+ required = { "author", "title", "year" },
+ optional = { "subtitle" },
+ },
+ ["demo-b"] = {
+ sets = {
+ authors = { "author", "institution", "organization" },
+ },
+ required = { "authors", "title", "year" },
+ optional = { "subtitle" },
+ },
+ --
+ -- we only provide article and book (maybe a few more later) and we keep it
+ -- real simple. See the apa and aps definitions for more extensive examples
+ --
+ article = {
+ sets = {
+ author = { "author", "editor" },
+ },
+ required = {
+ "author", -- a set
+ "year",
+ },
+ optional = {
+ "title",
+ "keywords",
+ "journal", "volume", "number", "pages",
+ },
+ },
+ book = {
+ sets = {
+ author = { "author", "editor", },
+ editionset = { "edition", "volume", "number" },
+ },
+ required = {
+ "author", -- a set
+ "title",
+ "year",
+ },
+ optional = {
+ "subtitle",
+ "keywords",
+ "publisher", "address",
+ "editionset",
+ },
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.mkvi
new file mode 100644
index 00000000000..f5c99ac1817
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-default.mkvi
@@ -0,0 +1,507 @@
+%D \module
+%D [ file=publ-imp-default,
+%D version=2014.02.06,
+%D title=Default bibliography style,
+%D subtitle=Publications,
+%D author=Alan Braslau and Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted
+%D by \PRAGMA. See mreadme.pdf for details.
+
+%D This default style defines only a few categories: book and article.
+%D If you want more, you need to load a more complete style such as \type {apa},
+%D \type {aps}, etc. The default style is used in the manuals that ship with
+%D \CONTEXT. This file is always loaded.
+
+\startbtxrenderingdefinitions[\s!default]
+
+\definebtxrendering
+ [\s!default]
+ [\c!specification=\s!default,
+ \c!sorttype=\v!default,
+ \c!numbering=num]
+
+\definebtx
+ [\s!default]
+ [\c!default=, % we do not want to fall|-|back on ourself.
+ \c!otherstext={\btxspace\btxlabeltext{default:others}},
+ %c!journalconversion=\v!normal,
+ \c!monthconversion=\v!number,
+ \c!separator:names:2={\btxcomma},
+ \c!separator:names:3={\btxspace\btxlabeltext{default:and}\space},
+ \c!separator:names:4={\btxspace\btxlabeltext{default:and}\space}]
+
+\definebtx
+ [\s!default:\s!list]
+ [\s!default]
+ [\c!authorconversion=normalshort]
+
+\definebtx
+ [\s!default:\s!cite]
+ [\s!default]
+ [\c!alternative=num,
+ [\c!compress=\v!yes,
+ \c!sorttype=normal,
+ \c!authorconversion=\v!name]
+
+\definebtx
+ [\s!default:\s!cite:name]
+ [\s!default:\s!cite]
+ [\c!authorconversion=\v!name]
+
+\definebtx
+ [\s!default:\s!cite:inverted]
+ [\s!default:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [\s!default:\s!cite:invertedshort]
+ [\s!default:\s!cite]
+ [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+ [\s!default:\s!cite:normalshort]
+ [\s!default:\s!cite]
+ [\c!authorconversion=\v!normalshort]
+
+\definebtx
+ [\s!default:\s!cite:normal]
+ [\s!default:\s!cite]
+ [\c!authorconversion=\v!normal]
+
+% List variants, some having specific settings:
+
+\definebtx
+ [\s!default:\s!list:\s!page]
+ [\s!default:\s!list]
+ [\c!separator:2={\btxcomma},
+ \c!separator:3={\btxcomma\btxlabeltext{default:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{default:and}\space},
+ \c!left={\btxleftparenthesis},
+ \c!right={\btxrightparenthesis}]
+
+\definebtx
+ [\s!default:\s!list:numbering]
+ [\s!default:\s!list]
+
+\definebtx
+ [\s!default:\s!list:numbering:default]
+ [\s!default:\s!list:numbering]
+
+\definebtx
+ [\s!default:\s!list:numbering:num]
+ [\s!default:\s!list:numbering]
+
+\definebtx
+ [\s!default:\s!list:numbering:short]
+ [\s!default:\s!list:numbering:num]
+
+\definebtx
+ [\s!default:\s!list:numbering:tag]
+ [\s!default:\s!list:numbering:num]
+
+\definebtx
+ [\s!default:\s!list:numbering:index]
+ [\s!default:\s!list:numbering:num]
+
+\definebtx
+ [\s!default:\s!list:author]
+ [\s!default:\s!list]
+
+\definebtx
+ [\s!default:\s!list:editor]
+ [\s!default:\s!list:author]
+
+\definebtx
+ [\s!default:\s!list:url]
+ [\s!default:\s!list]
+
+\definebtx
+ [\s!default:\s!list:doi]
+ [\s!default:\s!list]
+
+\definebtx
+ [\s!default:\s!list:short]
+ [\s!default:\s!list]
+
+\definebtx
+ [\s!default:\s!list:journal]
+ [\s!default:\s!list]
+ [\c!style=\v!italic]
+
+\definebtx
+ [\s!default:\s!list:title]
+ [\s!default:\s!list]
+ [\c!style=\v!italic,
+ \c!command=\Word]
+
+\definebtx
+ [\s!default:\s!list:title:article]
+ [\s!default:\s!list:title]
+ [\c!style=, % journal is set in italics
+ \c!command=\quotation] % alan, you can't do \quotation\Word
+
+\definebtx
+ [\s!default:\s!list:title:book]
+ [\s!default:\s!list:title]
+
+% Citation variants, some having specific settings :
+
+\definebtx
+ [\s!default:\s!cite:author]
+ [\s!default:\s!cite]
+
+\definebtx
+ [\s!default:\s!cite:authornum]
+ [\s!default:\s!cite:author]
+ [\c!left={(},
+ \c!right={)}]
+
+\definebtx
+ [\s!default:\s!cite:authoryear]
+ [\s!default:\s!cite:author]
+ [\c!left={(},
+ \c!right={)},
+ \c!inbetween={\btxcomma}]
+
+\definebtx
+ [\s!default:\s!cite:authoryears]
+ [\s!default:\s!cite:author]
+
+\definebtx
+ [\s!default:\s!cite:author:num] % todo
+ [\s!default:\s!cite:authornum]
+ [\c!left={\btxleftbracket},
+ \c!right={]}]
+
+\definebtx
+ [\s!default:\s!cite:author:year] % todo
+ [\s!default:\s!cite:authoryear]
+ [\c!left=,
+ \c!right=]
+
+\definebtx
+ [\s!default:\s!cite:author:years] % todo
+ [\s!default:\s!cite:authoryears]
+ [\c!inbetween=,
+ \c!left={\btxleftparenthesis},
+ \c!right={)}]
+
+\definebtx
+ [\s!default:\s!cite:year]
+ [\s!default:\s!cite]
+
+\definebtx
+ [\s!default:\s!cite:title]
+ [\s!default:\s!cite]
+ [\c!command={\language[\currentbtxlanguage]}, % BAH
+ \c!style=\v!italic]
+
+\definebtx
+ [\s!default:\s!cite:tag]
+ [\s!default:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [\s!default:\s!cite:index]
+ [\s!default:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [\s!default:\s!cite:page]
+ [\s!default:\s!cite]
+ [\c!left=,
+ \c!right=]
+
+\definebtx
+ [\s!default:\s!cite:pages]
+ [\s!default:\s!cite:page]
+
+\definebtx
+ [\s!default:\s!cite:keywords]
+ [\s!default:\s!cite]
+ [\c!left={(},
+ \c!right={)}]
+
+\definebtx
+ [\s!default:\s!cite:short]
+ [\s!default:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [\s!default:\s!cite:category]
+ [\s!default:\s!cite]
+
+\definebtx
+ [\s!default:\s!cite:url]
+ [\s!default:\s!cite]
+ [\c!left={[},
+ \c!right={]}]
+
+\definebtx
+ [\s!default:\s!cite:doi]
+ [\s!default:\s!cite:url]
+
+\definebtx
+ [\s!default:\s!cite:num]
+ [\s!default:\s!cite]
+ [\c!left={[},
+ \c!right={]},
+ \c!separator:2=\btxcommabreak,
+ \c!separator:3=\btxparameter{\c!separator:2},
+ \c!separator:4=\btxparameter{\c!separator:2}]
+
+\definebtx
+ [\s!default:\s!cite:default]
+ [\s!default:\s!cite:num]
+
+\definebtx
+ [\s!default:\s!cite:textnum]
+ [\s!default:\s!cite:num]
+ [\c!left=, % in apa: {Ref.\nbsp} or so
+ \c!right=,
+ \c!separator:2={\btxcomma},
+ \c!separator:3={\btxcomma\btxlabeltext{default:and}\space},
+ \c!separator:4={\btxspace\btxlabeltext{default:and}\space}]
+
+\definebtx
+ [\s!default:\s!cite:entry]
+ [\s!default:\s!cite]
+ [\c!left={(},
+ \c!right={)}]
+
+% Multilingual text strings
+
+\setupbtxlabeltext
+ [en]
+ [\s!default:and=and,
+ \s!default:number={no.},
+ \s!default:edition={ed.},
+ \s!default:Editor=Editor, % Ed./Eds.
+ \s!default:Editors=Editors,
+ \s!default:Volume={Vol.},
+ \s!default:Volumes={Vols.},
+ \s!default:others={et al.}]
+
+\setupbtxlabeltext
+ [nl]
+ [\s!default:and=en,
+ \s!default:number={nr.},
+ \s!default:edition={ed.}, % editie
+ \s!default:Editor=Editor, % Ed./Eds.
+ \s!default:Editors=Editors,
+ \s!default:Volume={Vol.},
+ \s!default:Volumes={Vols.},
+ \s!default:others={et al.}]
+
+\setupbtxlabeltext
+ [fr]
+ [\s!default:and=et,
+ \s!default:others={et al.},
+ \s!default:number={n\high{o}},
+ \s!default:edition={édition},
+ \s!default:Editor=Éditeur,
+ \s!default:Editors=Éditeurs,
+ \s!default:Volume=Volume,
+ \s!default:Volumes=Volumes,
+ \s!default:others={et al.}]
+
+\setupbtxlabeltext
+ [de]
+ [\s!default:and=und,
+ \s!default:number={nr.},
+ \s!default:edition=Auf\/lage,
+ \s!default:Editor=Herausgeber, % Hrsg./Hg.
+ \s!default:Editors=Herausgeber,
+ \s!default:Volume=Band, % Bd.
+ \s!default:Volumes={Bände},
+ \s!default:others={et al.}]
+
+\setupbtxlabeltext
+ [it]
+ [\s!default:and=e,
+ \s!default:number={nº},
+ \s!default:edition={ed.}, % edizione
+ \s!default:Editor={A cura di},
+ \s!default:Editors={A cura di},
+ \s!default:Volume={Vol.}, % Volume
+ \s!default:Volumes={Vol.}, % Volumi
+ \s!default:others={et al.}]
+
+\setupbtxlabeltext
+ [es]
+ [\s!default:and=y,
+ \s!default:number={nº},
+ \s!default:edition={ed.}, % edición
+ \s!default:Editor=Editor, % Ed./Eds.
+ \s!default:Editors=Editores,
+ \s!default:Volume={Vol.}, % Volumen
+ \s!default:Volumes={Vols.}, % Volúmenes
+ \s!default:others={et al.}]
+
+% First some helpers:
+
+\starttexdefinition btx:default:composed-title
+ \begingroup
+ \language[\currentbtxlanguage]
+ \btxflush{title}
+ \btxdoif {subtitle} {
+ \btxcolon
+ \btxflush{subtitle}
+ }
+ \endgroup
+\stoptexdefinition
+
+\starttexdefinition btx:default:title
+ \btxdoif {title} {
+ \btxspace
+ \btxstartstyleandcolor [default:list:title:\currentbtxcategory]
+ \btxusecommand [default:list:title:\currentbtxcategory] {
+ \texdefinition{btx:default:composed-title}
+ }
+ \btxstopstyleandcolor
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition btx:default:author
+ \btxdoif {author} {
+ \btxflush{author}
+ \doif {\btxfoundname{author}} {editor} {
+ \btxcomma
+ \btxsingularorplural {editor} {
+ \btxlabeltext{default:Editor}
+ } {
+ \btxlabeltext{default:Editors}
+ }
+ }
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition btx:default:year
+ \btxflush{year}
+ \btxflushsuffix
+\stoptexdefinition
+
+\starttexdefinition btx:default:journal
+ \btxdoif {journal} {
+ \btxspace
+ \btxstartstyleandcolor [default:list:journal]
+ \btxusecommand [default:list:journal] {
+ \btxflush{journal}
+ }
+ \btxstopstyleandcolor
+ \btxdoifelse {volume} {
+ \btxspace
+ \btxflush{volume}
+ \btxdoif {number} {
+ \ignorespaces % brrr
+ \btxleftparenthesis
+ \btxflush{number}
+ \btxrightparenthesis
+ }
+
+ } {
+ \btxdoif {number} {
+ \btxlabeltext{default:number}
+ \btxspace
+ \btxflush{number}
+ }
+ }
+ \btxdoif {pages} {
+ \btxcomma
+ \btxflush{pages}
+ }
+ \btxcomma
+ }
+\stoptexdefinition
+
+\starttexdefinition btx:default:editionset
+ \btxdoif {editionset} {
+ \removeunwantedspaces
+ \removepunctuation
+ \btxleftparenthesis
+ \doif {\btxfoundname{editionset}} {edition} {
+ \btxflush{edition}
+ \btxspace
+ \btxlabeltext{default:edition}
+ \btxcomma
+ }
+ \btxdoif {volume} {
+ \btxoneorrange {volume} {
+ \btxlabeltext{default:Volume}
+ } {
+ \btxlabeltext{default:Volumes}
+ }
+ \btxspace
+ \btxflush{volume}
+ \btxcomma
+ }
+ \btxdoifelse {number} {
+ \btxlabeltext{default:number}
+ \btxspace
+ \btxflush{number}
+ } {
+ \removeunwantedspaces
+ \removepunctuation
+ }
+ \btxrightparenthesiscomma
+ }
+\stoptexdefinition
+
+\starttexdefinition btx:default:publisher
+ \btxdoif {publisher} {
+ \btxflush{publisher}
+ \btxcomma
+ }
+ \btxdoif {address} {
+ \btxflush{address}
+ \btxcomma
+ }
+\stoptexdefinition
+
+% Then a minimal number of setups:
+
+\startsetups btx:default:list:article
+ \texdefinition{btx:default:author}
+ \texdefinition{btx:default:title}
+ \texdefinition{btx:default:journal}
+ \texdefinition{btx:default:year}
+ \removeunwantedspaces
+ \removepunctuation
+ \btxperiod
+\stopsetups
+
+\startsetups btx:default:list:book
+ \texdefinition{btx:default:author}
+ \texdefinition{btx:default:title}
+ \texdefinition{btx:default:editionset}
+ \texdefinition{btx:default:publisher}
+ \texdefinition{btx:default:year}
+ \removeunwantedspaces
+ \removepunctuation
+ \btxperiod
+\stopsetups
+
+\startsetups btx:default:list:unknown
+ \currentbtxcategory\btxcolon
+ \btxshowentryinline
+\stopsetups
+
+%D Experiment:
+
+\startsetups btx:default:lefttext
+ \currentbtxlefttext
+\stopsetups
+
+\startsetups btx:default:righttext
+ \currentbtxrighttext
+\stopsetups
+
+\stopbtxrenderingdefinitions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-definitions.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-definitions.mkvi
new file mode 100644
index 00000000000..295586f60fb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-definitions.mkvi
@@ -0,0 +1,123 @@
+%D \module
+%D [ file=publ-imp-def,
+%D version=2013.12.24,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Here we collect some helper setups. We assume that checking of a field
+%D happens in the calling setup, if only because that is the place where
+%D fences are also dealt with.
+
+% These will become texdefinitions
+
+\unprotect
+
+\startxmlsetups btx:format:crossref
+ \cite[\btxfield{crossref}]
+\stopxmlsetups
+
+\startxmlsetups btx:format:key
+ \btxfield{short}
+\stopxmlsetups
+
+\starttexdefinition unexpanded btx:format:inject #link #content
+ \ifx\currentbtxinternal\empty
+ #content
+ \else\ifconditional\btxinteractive
+ \goto {#content} [#link]
+ \else
+ #content
+ \fi\fi
+\stoptexdefinition
+
+\startxmlsetups btx:format:doi
+ \edef\currentbtxfielddoi{\btxfield{doi}}
+ \ifx\currentbtxfielddoi\empty
+ {\tttf no-doi}
+ \else\ifconditional\btxinteractive
+ \goto{\hyphenatedurl{\currentbtxfielddoi}}[url(http://dx.doi.org/\currentbtxfielddoi)]
+ \else
+ \hyphenatedurl{\currentbtxfielddoi}
+ \fi\fi
+\stopxmlsetups
+
+\startxmlsetups btx:format:url
+ \edef\currentbtxfieldurl{\btxfield{url}}
+ \ifx\currentbtxfieldurl\empty
+ {\tttf no-url}
+ \else\ifconditional\btxinteractive
+ \goto{\hyphenatedurl{\currentbtxfieldurl}}[url(\currentbtxfieldurl)]
+ \else
+ \hyphenatedurl{\currentbtxfieldurl}
+ \fi\fi
+\stopxmlsetups
+
+\startxmlsetups btx:format:year
+ \edef\currentbtxfieldyear{\btxfield{year}}
+ \ifx\currentbtxfieldyear\empty
+ \btxlabeltext{\currentbtxspecification:nd}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups btx:format:month
+ \edef\currentbtxfieldmonth{\btxfield{month}}
+ \ifx\currentbtxfieldmonth\empty
+ {\tttf no-month}
+ \else
+ \edef\p_monthconversion{\btxparameter\c!monthconversion}
+ \ifx\p_monthconversion\empty % month month:mnem
+ \currentbtxfieldmonth
+ \else
+ \doifelsenumber \currentbtxfieldmonth {
+ \convertnumber\p_monthconversion\currentbtxfieldmonth
+ } {
+ \currentbtxfieldmonth
+ }
+ \fi
+ \fi
+\stopxmlsetups
+
+% macros:
+
+\starttexdefinition unexpanded btx:style:italic #content
+ \dontleavehmode
+ \begingroup
+ \it
+ #content
+ \italiccorrection
+ \endgroup
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:style:bold #content
+ \dontleavehmode
+ \begingroup
+ \bf
+ #content
+ \endgroup
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:style:quote #content
+ \dontleavehmode
+ \startquote
+ #content
+ \stopquote
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:style #style #content
+ \doifelsedefined {btx:style:#style} {
+ \texdefinition{btx:style:#style} {
+ #content
+ }
+ } {
+ #content
+ }
+\stoptexdefinition
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-list.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-list.mkvi
new file mode 100644
index 00000000000..68ccaef01f1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-list.mkvi
@@ -0,0 +1,96 @@
+%D \module
+%D [ file=publ-imp-list,
+%D version=2014.06.16,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Lists,
+%D author=Alan Braslau and 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
+
+\starttexdefinition unexpanded btx:list:inject #content
+ \ifconditional\btxinteractive
+ \ifx\currentbtxinternal\empty
+ #content
+ \else
+ \goto {
+ #content
+ } [
+ \s!internal(\currentbtxinternal)
+ ]
+ \fi
+ \else
+ #content
+ \fi
+\stoptexdefinition
+
+\starttexdefinition unexpanded btx:list:helpers:concat
+ \space
+\stoptexdefinition
+
+\startsetups[\s!btx:\s!list:\s!page]
+ \texdefinition{\s!btx:\s!list:concat}
+ \texdefinition{\s!btx:\s!list:inject} {
+ % real pagenumber: todo, userpage
+ \currentbtxfirst
+ % order
+ \high{\currentbtxsecond}
+ }
+\stopsetups
+
+\startsetups[\s!btx:\s!list:\s!numbering]
+ \texdefinition {\s!btx:\s!list:inject} {
+ \currentbtxfirst
+ \btxparameter\c!stopper
+ }
+\stopsetups
+
+% Hans: can the following setups be condensed to one using some variable?
+
+\startsetups[\s!btx:\s!list:\s!numbering:default]
+ \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:default]
+ \btxusecommand[\currentbtxspecification:\s!list:\s!numbering:default] {
+ \fastsetup{\s!btx:\s!list:\s!numbering}
+ }
+ \btxstopstyleandcolor
+\stopsetups
+
+\startsetups[\s!btx:\s!list:\s!numbering:num]
+ \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:num]
+ \btxusecommand[\currentbtxspecification:\s!list:\s!numbering:num] {
+ \fastsetup{\s!btx:\s!list:\s!numbering}
+ }
+ \btxstopstyleandcolor
+\stopsetups
+
+\startsetups[\s!btx:\s!list:\s!numbering:short]
+ \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:short]
+ \btxusecommand [\currentbtxspecification:\s!list:\s!numbering:short] {
+ \fastsetup{\s!btx:\s!list:\s!numbering}
+ \btxflushsuffix
+ }
+ \btxstopstyleandcolor
+\stopsetups
+
+\startsetups[\s!btx:\s!list:\s!numbering:tag]
+ \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:tag]
+ \btxusecommand [\currentbtxspecification:\s!list:\s!numbering:tag] {
+ \fastsetup{\s!btx:\s!list:\s!numbering}
+ }
+ \btxstopstyleandcolor
+\stopsetups
+
+\startsetups[\s!btx:\s!list:\s!numbering:index]
+ \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:index]
+ \btxusecommand [\currentbtxspecification:\s!list:\s!numbering:index] {
+ \fastsetup{\s!btx:\s!list:\s!numbering}
+ }
+ \btxstopstyleandcolor
+\stopsetups
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-page.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-page.mkvi
new file mode 100644
index 00000000000..2d9040b105a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-page.mkvi
@@ -0,0 +1,51 @@
+%D \module
+%D [ file=publ-imp-page,
+%D version=2014.11.05,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Page numbers,
+%D author=Alan Braslau and 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
+
+\startsetups \s!btx:\s!list:\s!page:concat
+ \ifcase\currentbtxoverflow
+ \btxparameter{\c!separator:\number\currentbtxconcat}
+ \fi
+\stopsetups
+
+% for the moment we have only one variant
+
+\startsetups [\s!btx:\s!list:\s!page]
+ \fastsetup{\s!btx:\s!list:\s!page:concat}
+ \fastsetup{\s!btx:\currentbtxspecification:\s!list:page-or-pages}
+ \ifconditional\btxinteractive
+ \goto {
+ \currentbtxfirstpage
+ } [
+ internal(\currentbtxfirstinternal)
+ ]
+ \ifx\currentbtxlastpage\empty \else
+ %\btxparameter\c!pageconnector
+ \btxparameter\c!range
+ \goto {
+ \currentbtxlastpage
+ } [
+ internal(\currentbtxlastinternal)
+ ]
+ \fi
+ \else
+ \currentbtxfirstpage
+ \ifx\currentbtxlastpage\empty \else
+ \btxparameter\c!range
+ \currentbtxlastpage
+ \fi
+ \fi
+\stopsetups
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-replacements.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-replacements.lua
new file mode 100644
index 00000000000..e0ac249fc0d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-replacements.lua
@@ -0,0 +1,23 @@
+-- Many bibtex databases are poluted. This is a side effect of 7 bit encoding on the
+-- one hand and tweaking the outcome at the other. The worst examples are the use
+-- of \rlap on whole names. We found that trying to cope with all can one drive insane
+-- so we stopped at some point. Clean up your mess or pay the price. But, you can load
+-- this file (and similar ones) to help you out. There is simply no reward in trying
+-- to deal with it ourselves.
+
+return {
+ name = "replacements",
+ version = "1.00",
+ comment = "Good riddance",
+ author = "Alan Braslau and Hans Hagen",
+ copyright = "ConTeXt development team",
+ replacements = {
+ [ [[\emdash]] ] = "—",
+ [ [[\endash]] ] = "–",
+ [ [[{\emdash}]] ] = "—",
+ [ [[{\endash}]] ] = "–",
+ [ [[Th\^e\llap{\raise 0.5ex\hbox{\'{\relax}}}]] ] = "Thánh",
+ [ [[Th{\^e}\llap{\raise0.5ex\hbox{\'{\relax}}}]] ] = "Thánh",
+ [ [[Th{\^e}\llap{\raise 0.5ex\hbox{\'{\relax}}}]] ] = "Thánh",
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-test.bib b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-test.bib
new file mode 100644
index 00000000000..0d81b49ff08
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-test.bib
@@ -0,0 +1,294 @@
+% This is a test bibliography for developing publ-impl-XXX files. Although
+% meant for testing apa styles, it can also be used for other styles.
+%
+% All publication categories have an example entry here. Most have an entry
+% with a "-min" key, containing only the minimal set of fields.
+%
+% Maintained by: Alan Braslau, Hans Hagen, Robin Kirkham
+
+@article {test-article-min,
+ author = "An Author",
+ title = "Title-article",
+ journal = "Journal",
+ year = "Year"
+}
+
+@article {test-article,
+ author = "An Author",
+ title = "Title-article",
+ journal = "Journal",
+ year = "Year",
+ volume = "Volume",
+ number = "Number",
+ pages = "Pages",
+ month = "Month",
+ note = "Note"
+}
+
+% author, editor, or both
+
+@book {test-book-min,
+ author = "An Author",
+ title = "Title-book",
+ publisher = "Publisher",
+ year = "Year"
+}
+
+% author, editor, or both
+% volume, number, or both
+
+@book {test-book,
+ author = "An Author",
+ editor = "An Editor",
+ title = "Title-book",
+ publisher = "Publisher",
+ year = "Year",
+ volume = "Volume",
+ number = "Number",
+ series = "Series",
+ address = "Address",
+ edition = "Edition",
+ month = "Month",
+ note = "Note"
+}
+
+% no author
+
+@book {test-book-edited,
+ editor = "An Editor",
+ title = "Title-book-edited",
+ publisher = "Publisher",
+ year = "Year"
+}
+
+@booklet {test-booklet-min,
+ title = "Title-booklet"
+}
+
+@booklet {test-booklet,
+ title = "Title-booklet",
+ author = "An Author",
+ howpublished = "How-published",
+ address = "Address",
+ month = "Month",
+ year = "Year",
+ note = "Note"
+}
+
+% author, editor, or both
+% chapter, pages, or both
+
+@inbook {test-inbook-min,
+ author = "An Author",
+ editor = "An Editor",
+ title = "Title-inbook",
+ chapter = "Chapter",
+ pages = "Pages",
+ publisher = "Publisher",
+ year = "Year"
+}
+
+% author, editor, or both
+% chapter, pages, or both
+% volume, number, or both
+
+@inbook {test-inbook,
+ author = "An Author",
+ editor = "An Editor",
+ title = "Title-inbook",
+ chapter = "Chapter",
+ pages = "Pages",
+ publisher = "Publisher",
+ year = "Year",
+ volume = "Volume",
+ number = "Number",
+ series = "Series",
+ type = "Type",
+ address = "Address",
+ edition = "Edition",
+ month = "Month",
+ note = "Note"
+}
+
+@incollection {test-incollection-min,
+ author = "An Author",
+ title = "Title-incollection",
+ booktitle = "Booktitle",
+ publisher = "Publisher",
+ year = "Year"
+}
+
+% volume, number, or both
+
+@incollection {test-incollection,
+ author = "An Author",
+ title = "Title-incollection",
+ booktitle = "Booktitle",
+ publisher = "Publisher",
+ year = "Year",
+ editor = "An Editor",
+ volume = "Volume",
+ number = "Number",
+ series = "Series",
+ type = "Type",
+ chapter = "Chapter",
+ pages = "Pages",
+ address = "Address",
+ edition = "Edition",
+ month = "Month",
+ note = "Note"
+}
+
+@inproceedings {test-inproceedings-min,
+ author = "An Author",
+ title = "Title-inproceedings",
+ booktitle = "Booktitle",
+ year = "Year"
+}
+
+% volume, number, or both
+
+@inproceedings {test-inproceedings,
+ author = "An Author",
+ title = "Title-inproceedings",
+ booktitle = "Booktitle",
+ year = "Year",
+ editor = "An Editor",
+ volume = "Volume",
+ number = "Number",
+ series = "Series",
+ pages = "Pages",
+ address = "Address",
+ month = "Month",
+ organization = "Organization",
+ publisher = "Publisher",
+ note = "Note"
+}
+
+@manual {test-manual-min,
+ title = "Title-manual"
+}
+
+@manual {test-manual,
+ title = "Title-manual",
+ author = "An Author",
+ organization = "Organization",
+ address = "Address",
+ edition = "Edition",
+ month = "Month",
+ year = "Year"
+ note = "Note"
+}
+
+
+@mastersthesis {test-mastersthesis-min,
+ author = "An Author",
+ title = "Title-mastersthesis",
+ school = "School",
+ year = "Year",
+}
+
+@mastersthesis {test-mastersthesis,
+ author = "An Author",
+ title = "Title-mastersthesis",
+ school = "School",
+ year = "Year",
+ type = "Type",
+ address = "Address",
+ month = "Month",
+ note = "Note"
+}
+
+@proceedings {test-proceedings-min,
+ title = "Title-proceedings",
+ year = "Year",
+}
+
+% volume, number, or both
+
+@proceedings {test-proceedings,
+ title = "Title-proceedings",
+ year = "Year",
+ editor = "An Editor",
+ volume = "Volume",
+ number = "Number",
+ series = "Series",
+ address = "Address",
+ month = "Month",
+ organization = "Organization",
+ publisher = "Publisher",
+ note = "Note"
+}
+
+@phdthesis {test-phdthesis-min,
+ author = "An Author",
+ title = "Title-phdthesis",
+ school = "School",
+ year = "Year",
+}
+
+@phdthesis {test-phdthesis,
+ author = "An Author",
+ title = "Title-phdthesis",
+ school = "School",
+ year = "Year",
+ type = "Type",
+ address = "Address",
+ month = "Month",
+ note = "Note"
+}
+
+@techreport {test-techreport-min,
+ author = "An Author",
+ title = "Title-techreport",
+ institution = "Institution",
+ year = "Year",
+}
+
+@techreport {test-techreport,
+ author = "An Author",
+ title = "Title-techreport",
+ institution = "Institution",
+ year = "Year",
+ type = "Type",
+ number = "Number",
+ address = "Address",
+ month = "Month",
+ note = "Note"
+}
+
+@misc {test-misc,
+ author = "An Author",
+ title = "Title-misc",
+ howpublished = "How-published",
+ month = "Month",
+ year = "Year",
+ note = "Note"
+}
+
+@unpublished {test-unpublished-min,
+ author = "An Author",
+ title = "Title-unpublished",
+ note = "Note"
+}
+
+@unpublished {test-unpublished,
+ author = "An Author",
+ title = "Title-unpublished",
+ note = "Note",
+ month = "Month",
+ year = "Year"
+}
+
+% some other test entries
+
+@misc {test-manyauthor,
+ author = "A Author and B Author and C Author and D Author and
+ E Author and F Author and G Author and H Author and
+ I Author and J Author and K Author and L Author and
+ M Author and N Author and O Author and P Author and
+ Q Author and R Author and S Author and T Author and
+ U Author and V Author and W Author and X Author and
+ Y Author and Z Author",
+ title = "Title-Many Authors"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua
new file mode 100644
index 00000000000..c30f780f188
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua
@@ -0,0 +1,3342 @@
+if not modules then modules = { } end modules ['publ-ini'] = {
+ 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"
+}
+
+-- bah .. this 200 locals limit again ... so we need to split it as adding more
+-- do ... ends makes it messier
+
+-- plug the list sorted in the list mechanism (specification.sortorder)
+
+-- If we define two datasets with the same bib file we can consider
+-- sharing the data but that means that we need to have a parent which
+-- in turn makes things messy if we start manipulating entries in
+-- different ways (future) .. not worth the trouble as we will seldom
+-- load big bib files many times and even then ... fonts are larger.
+
+-- A potential optimization is to work with current_dataset, current_tag when
+-- fetching fields but the code become real messy that way (many currents). The
+-- gain is not that large anyway because not much publication stuff is flushed.
+
+local next, rawget, type, tostring, tonumber = next, rawget, type, tostring, tonumber
+local match, find, gsub = string.match, string.find, string.gsub
+local concat, sort, tohash = table.concat, table.sort, table.tohash
+local utfsub = utf.sub
+local mod = math.mod
+local formatters = string.formatters
+local allocate = utilities.storage.allocate
+local settings_to_array, settings_to_set = utilities.parsers.settings_to_array, utilities.parsers.settings_to_set
+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 report = logs.reporter("publications")
+local report_cite = logs.reporter("publications","cite")
+local report_list = logs.reporter("publications","list")
+local report_reference = logs.reporter("publications","reference")
+local report_suffix = logs.reporter("publications","suffix")
+
+local trace = false trackers.register("publications", function(v) trace = v end)
+local trace_cite = false trackers.register("publications.cite", function(v) trace_cite = v end)
+local trace_missing = false trackers.register("publications.cite.missing", function(v) trace_missing = v end)
+local trace_references = false trackers.register("publications.cite.references", function(v) trace_references = v end)
+local trace_detail = false trackers.register("publications.detail", function(v) trace_detail = v end)
+local trace_suffixes = false trackers.register("publications.suffixes", function(v) trace_suffixes = v end)
+
+publications = publications or { }
+local datasets = publications.datasets
+local writers = publications.writers
+local casters = publications.casters
+local detailed = publications.detailed
+local enhancer = publications.enhancer
+local enhancers = publications.enhancers
+
+local tracers = publications.tracers or { }
+publications.tracers = tracers
+
+local variables = interfaces.variables
+
+local v_local = variables["local"]
+local v_global = variables["global"]
+
+local v_force = variables.force
+local v_normal = variables.normal
+local v_reverse = variables.reverse
+local v_none = variables.none
+local v_yes = variables.yes
+local v_no = variables.no
+local v_all = variables.all
+local v_always = variables.always
+local v_hidden = variables.hidden
+local v_list = variables.list
+local v_text = variables.text
+local v_doublesided = variables.doublesided
+local v_default = variables.default
+local v_dataset = variables.dataset
+
+local conditionals = tex.conditionals
+
+local numbertochar = converters.characters
+
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+
+local isdefined = tex.isdefined
+
+----- basicsorter = sorters.basicsorter -- (a,b)
+----- sortstripper = sorters.strip
+----- sortsplitter = sorters.splitters.utf
+
+local manipulators = typesetters.manipulators
+local splitmanipulation = manipulators.splitspecification
+local applymanipulation = manipulators.applyspecification
+local manipulatormethods = manipulators.methods
+
+-- this might move elsewhere
+
+manipulatormethods.Word = converters.Word
+manipulatormethods.WORD = converters.WORD
+manipulatormethods.Words = converters.Words
+manipulatormethods.WORDS = converters.WORDS
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+local ctx_setmacro = interfaces.setmacro
+
+local ctx_doifelse = commands.doifelse
+local ctx_doif = commands.doif
+local ctx_doifnot = commands.doifnot
+local ctx_gobbletwoarguments = context.gobbletwoarguments
+
+local ctx_btxdirectlink = context.btxdirectlink
+local ctx_btxhandlelistentry = context.btxhandlelistentry
+local ctx_btxhandlelisttextentry = context.btxhandlelisttextentry
+local ctx_btxhandlecombientry = context.btxhandlecombientry
+local ctx_btxchecklistentry = context.btxchecklistentry
+local ctx_btxchecklistcombi = context.btxchecklistcombi
+
+local ctx_btxsetdataset = context.btxsetdataset
+local ctx_btxsettag = context.btxsettag
+local ctx_btxsetnumber = context.btxsetnumber
+local ctx_btxsetlanguage = context.btxsetlanguage
+local ctx_btxsetcombis = context.btxsetcombis
+local ctx_btxsetcategory = context.btxsetcategory
+local ctx_btxcitesetup = context.btxcitesetup
+local ctx_btxsubcitesetup = context.btxsubcitesetup
+local ctx_btxnumberingsetup = context.btxnumberingsetup
+local ctx_btxpagesetup = context.btxpagesetup
+local ctx_btxsetfirst = context.btxsetfirst
+local ctx_btxsetsecond = context.btxsetsecond
+----- ctx_btxsetthird = context.btxsetthird
+local ctx_btxsetsuffix = context.btxsetsuffix
+local ctx_btxsetinternal = context.btxsetinternal
+local ctx_btxsetlefttext = context.btxsetlefttext
+local ctx_btxsetrighttext = context.btxsetrighttext
+local ctx_btxsetbefore = context.btxsetbefore
+local ctx_btxsetafter = context.btxsetafter
+local ctx_btxsetbacklink = context.btxsetbacklink
+local ctx_btxsetbacktrace = context.btxsetbacktrace
+local ctx_btxsetcount = context.btxsetcount
+local ctx_btxsetconcat = context.btxsetconcat
+local ctx_btxsetoveflow = context.btxsetoverflow
+local ctx_btxsetfirstpage = context.btxsetfirstpage
+local ctx_btxsetlastpage = context.btxsetlastpage
+local ctx_btxsetfirstinternal = context.btxsetfirstinternal
+local ctx_btxsetlastinternal = context.btxsetlastinternal
+local ctx_btxstartcite = context.btxstartcite
+local ctx_btxstopcite = context.btxstopcite
+local ctx_btxstartciteauthor = context.btxstartciteauthor
+local ctx_btxstopciteauthor = context.btxstopciteauthor
+local ctx_btxstartsubcite = context.btxstartsubcite
+local ctx_btxstopsubcite = context.btxstopsubcite
+local ctx_btxstartlistentry = context.btxstartlistentry
+local ctx_btxstoplistentry = context.btxstoplistentry
+local ctx_btxstartcombientry = context.btxstartcombientry
+local ctx_btxstopcombientry = context.btxstopcombientry
+local ctx_btxlistsetup = context.btxlistsetup
+local ctx_btxflushauthor = context.btxflushauthor
+local ctx_btxsetnoflistentries = context.btxsetnoflistentries
+local ctx_btxsetcurrentlistentry = context.btxsetcurrentlistentry
+local ctx_btxsetcurrentlistindex = context.btxsetcurrentlistindex
+
+local trialtypesetting = context.trialtypesetting
+
+languages.data = languages.data or { }
+local data = languages.data
+
+local specifications = publications.specifications
+local currentspecification = specifications[false]
+local ignoredfields = { }
+publications.currentspecification = currentspecification
+
+local function setspecification(name)
+ currentspecification = specifications[name]
+ if trace then
+ report("setting specification %a",type(name) == "string" and name or "anything")
+ end
+ publications.currentspecification = currentspecification
+end
+
+publications.setspecification = setspecification
+
+implement {
+ name = "btxsetspecification",
+ actions = setspecification,
+ arguments = "string",
+}
+
+local optionalspace = lpeg.patterns.whitespace^0
+local prefixsplitter = optionalspace * lpeg.splitat(optionalspace * P("::") * optionalspace)
+
+statistics.register("publications load time", function()
+ local publicationsstats = publications.statistics
+ local nofbytes = publicationsstats.nofbytes
+ if nofbytes > 0 then
+ return string.format("%s seconds, %s bytes, %s definitions, %s shortcuts",
+ statistics.elapsedtime(publications),
+ nofbytes,
+ publicationsstats.nofdefinitions or 0,
+ publicationsstats.nofshortcuts or 0
+ )
+ else
+ return nil
+ end
+end)
+
+luatex.registerstopactions(function()
+ local done = false
+ for name, dataset in sortedhash(datasets) do
+ for command, n in sortedhash(dataset.commands) do
+ if not done then
+ logspushtarget("logfile")
+ logsnewline()
+ report("start used btx commands")
+ logsnewline()
+ done = true
+ end
+ if isdefined[command] then
+ report("%-20s %-20s % 5i %s",name,command,n,"known")
+ elseif isdefined[upper(command)] then
+ report("%-20s %-20s % 5i %s",name,command,n,"KNOWN")
+ else
+ report("%-20s %-20s % 5i %s",name,command,n,"unknown")
+ end
+ end
+ end
+ if done then
+ logsnewline()
+ report("stop used btx commands")
+ logsnewline()
+ logspoptarget()
+ end
+end)
+
+-- multipass, we need to sort because hashing is random per run and not per
+-- version (not the best changed feature of lua)
+
+local collected = allocate()
+local tobesaved = allocate()
+
+do
+
+ local function serialize(t)
+ local f_key_table = formatters[" [%q] = {"]
+ local f_key_string = formatters[" %s = %q,"]
+ local r = { "return {" }
+ local m = 1
+ for tag, entry in sortedhash(t) do
+ m = m + 1
+ r[m] = f_key_table(tag)
+ local s = sortedkeys(entry)
+ for i=1,#s do
+ local k = s[i]
+ m = m + 1
+ r[m] = f_key_string(k,entry[k])
+ end
+ m = m + 1
+ r[m] = " },"
+ end
+ r[m] = "}"
+ return concat(r,"\n")
+ end
+
+ local function finalizer()
+ local prefix = tex.jobname -- or environment.jobname
+ local setnames = sortedkeys(datasets)
+ for i=1,#setnames do
+ local name = setnames[i]
+ local dataset = datasets[name]
+ local userdata = dataset.userdata
+ local checksum = nil
+ local username = file.addsuffix(file.robustname(formatters["%s-btx-%s"](prefix,name)),"lua")
+ if userdata and next(userdata) then
+ if job.passes.first then
+ local newdata = serialize(userdata)
+ checksum = md5.HEX(newdata)
+ io.savedata(username,newdata)
+ end
+ else
+ os.remove(username)
+ username = nil
+ end
+ local loaded = dataset.loaded
+ local sources = dataset.sources
+ local used = { }
+ for i=1,#sources do
+ local source = sources[i]
+ -- if loaded[source.filename] ~= "previous" then -- needs checking
+ if loaded[source.filename] ~= "previous" or loaded[source.filename] == "current" then
+ used[#used+1] = source
+ end
+ end
+ tobesaved[name] = {
+ usersource = {
+ filename = username,
+ checksum = checksum,
+ },
+ datasources = used,
+ }
+ end
+ end
+
+ local function initializer()
+ statistics.starttiming(publications)
+ for name, state in sortedhash(collected) do
+ local dataset = datasets[name]
+ local datasources = state.datasources
+ local usersource = state.usersource
+ if datasources then
+ for i=1,#datasources do
+ local filename = datasources[i].filename
+ publications.load {
+ dataset = dataset,
+ filename = filename,
+ kind = "previous"
+ }
+ end
+ end
+ if usersource then
+ dataset.userdata = table.load(usersource.filename) or { }
+ end
+ end
+ statistics.stoptiming(publications)
+ function initializer() end -- will go, for now, runtime loaded
+ end
+
+ job.register('publications.collected',tobesaved,initializer,finalizer)
+
+end
+
+-- we want to minimize references as there can be many (at least
+-- when testing)
+
+local nofcitations = 0
+local usedentries = nil
+local citetolist = nil
+local listtocite = nil
+local listtolist = nil
+
+do
+
+ local initialize = nil
+
+ initialize = function(t)
+ usedentries = allocate { }
+ citetolist = allocate { }
+ listtocite = allocate { }
+ listtolist = allocate { }
+ local names = { }
+ local internals = structures.references.internals
+ local p_collect = (C(R("09")^1) * Carg(1) / function(s,entry) listtocite[tonumber(s)] = entry end + P(1))^0
+ local nofunique = 0
+ local nofreused = 0
+ for i=1,#internals do
+ local entry = internals[i]
+ if entry then
+ local metadata = entry.metadata
+ if metadata then
+ local kind = metadata.kind
+ if kind == "full" then
+ -- reference (in list)
+ local userdata = entry.userdata
+ if userdata then
+ local tag = userdata.btxref
+ if tag then
+ local set = userdata.btxset or v_default
+ local s = usedentries[set]
+ if s then
+ local u = s[tag]
+ if u then
+ u[#u+1] = entry
+ else
+ s[tag] = { entry }
+ end
+ nofreused = nofreused + 1
+ else
+ usedentries[set] = { [tag] = { entry } }
+ nofunique = nofunique + 1
+ end
+ -- alternative: collect prev in group
+ local bck = userdata.btxbck
+ if bck then
+ lpegmatch(p_collect,bck,1,entry) -- for s in string.gmatch(bck,"[^ ]+") do listtocite[tonumber(s)] = entry end
+ local lst = tonumber(userdata.btxlst)
+ if lst then
+ listtolist[lst] = entry
+ end
+ else
+ local int = tonumber(userdata.btxint)
+ if int then
+ listtocite[int] = entry
+ end
+ end
+ local detail = datasets[set].details[tag]
+-- todo: these have to be pluggable
+ if detail then
+ local author = detail.author
+ if author then
+ for i=1,#author do
+ local a = author[i]
+ local s = a.surnames
+ if s then
+ local c = concat(s,"+")
+ local n = names[c]
+ if n then
+ n[#n+1] = a
+ break
+ else
+ names[c] = { a }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif kind == "btx" or kind == "userdata" then -- will go: kind == "userdata"
+ -- list entry (each cite)
+ local userdata = entry.userdata
+ if userdata then
+ local int = tonumber(userdata.btxint)
+ if int then
+ citetolist[int] = entry
+ end
+ end
+ end
+ end
+ else
+ -- weird
+ end
+ end
+ for k, v in sortedhash(names) do
+ local n = #v
+ if n > 1 then
+ local original = v[1].original
+ for i=2,n do
+ if original ~= v[i].original then
+ report("potential clash in name %a",k)
+ for i=1,n do
+ v[i].state = 1
+ end
+ break
+ end
+ end
+ end
+ end
+ if trace_detail then
+ report("%s unique bibentries: %s reused entries",nofunique,nofreused)
+ end
+ initialize = nil
+ end
+
+ usedentries = setmetatableindex(function(_,k) if initialize then initialize() end return usedentries[k] end)
+ citetolist = setmetatableindex(function(_,k) if initialize then initialize() end return citetolist [k] end)
+ listtocite = setmetatableindex(function(_,k) if initialize then initialize() end return listtocite [k] end)
+ listtolist = setmetatableindex(function(_,k) if initialize then initialize() end return listtolist [k] end)
+
+ function publications.usedentries()
+ if initialize then
+ initialize()
+ end
+ return usedentries
+ end
+
+end
+
+-- match:
+--
+-- [current|previous|following] section
+-- [current|previous|following] block
+-- [current|previous|following] component
+--
+-- by prefix
+-- by dataset
+
+local findallused do
+
+ local reported = { }
+ local finder = publications.finder
+
+ findallused = function(dataset,reference,internal,forcethem)
+ local current = datasets[dataset]
+ local finder = publications.finder -- for the moment, not yet in all betas
+ local find = finder and finder(current,reference)
+ local tags = not find and settings_to_array(reference)
+ local todo = { }
+ local okay = { } -- only if mark
+ local allused = usedentries[dataset] or { }
+ local luadata = current.luadata
+ local details = current.details
+ local ordered = current.ordered
+ if allused then
+ local registered = { }
+ local function register(tag)
+ local entry = forcethem and luadata[tag]
+ if entry then
+ if registered[tag] then
+ return
+ end
+ okay[#okay+1] = entry
+ -- todo[tag] = true
+ registered[tag] = true
+ return tag
+ end
+ entry = allused[tag]
+ if not entry then
+ local parent = details[tag].parent
+ if parent then
+ entry = allused[parent]
+ end
+ if entry then
+ report("using reference of parent %a for %a",parent,tag)
+ tag = parent
+ end
+ end
+ if registered[tag] then
+ return
+ end
+ if entry then
+ -- only once in a list but at some point we can have more (if we
+ -- decide to duplicate)
+ if #entry == 1 then
+ entry = entry[1]
+ else
+ -- same block and section
+ local done = false
+ if internal and internal > 0 then
+ -- first following in list
+ for i=1,#entry do
+ local e = entry[i]
+ if e.references.internal > internal then
+ done = e
+ break
+ end
+ end
+ if not done then
+ -- last preceding in list
+ for i=1,#entry do
+ local e = entry[i]
+ if e.references.internal < internal then
+ done = e
+ else
+ break
+ end
+ end
+ end
+ end
+ if done then
+ entry = done
+ else
+ entry = entry[1]
+ end
+ end
+ okay[#okay+1] = entry
+ end
+ todo[tag] = true
+ registered[tag] = true
+ return tag
+ end
+ if reference == "*" then
+ tags = { }
+ for i=1,#ordered do
+ local tag = ordered[i].tag
+ tag = register(tag)
+ tags[#tags+1] = tag
+ end
+ elseif find then
+ tags = { }
+ for i=1,#ordered do
+ local entry = ordered[i]
+ if find(entry) then
+ local tag = entry.tag
+ tag = register(tag)
+ tags[#tags+1] = tag
+ end
+ end
+ if #tags == 0 and not reported[reference] then
+ tags[1] = reference
+ reported[reference] = true
+ end
+ else
+ for i=1,#tags do
+ local tag = tags[i]
+ if luadata[tag] then
+ tag = register(tag)
+ tags[i] = tag
+ elseif not reported[tag] then
+ reported[tag] = true
+ report_cite("non-existent entry %a in %a",tag,dataset)
+ end
+ end
+ end
+ else
+ if find then
+ tags = { }
+ for i=1,#ordered do
+ local entry = ordered[i]
+ if find(entry) then
+ local tag = entry.tag
+ local parent = details[tag].parent
+ if parent then
+ tag = parent
+ end
+ tags[#tags+1] = tag
+ todo[tag] = true
+ end
+ end
+ if #tags == 0 and not reported[reference] then
+ tags[1] = reference
+ reported[reference] = true
+ end
+ else
+ for i=1,#tags do
+ local tag = tags[i]
+ local parent = details[tag].parent
+ if parent then
+ tag = parent
+ tags[i] = tag
+ end
+ if luadata[tag] then
+ todo[tag] = true
+ elseif not reported[tag] then
+ reported[tag] = true
+ report_cite("non-existent entry %a in %a",tag,dataset)
+ end
+ end
+ end
+ end
+ return okay, todo, tags
+ end
+
+end
+
+local function unknowncite(reference)
+ ctx_btxsettag(reference)
+ if trace_detail then
+ report("expanding %a cite setup %a","unknown","unknown")
+ end
+ ctx_btxcitesetup("unknown")
+end
+
+local concatstate = publications.concatstate
+
+-- hidden : mark for list, don't show in text
+-- list : mark for list, show in text only when in list
+-- text : not to list, show in text
+-- always : mark for list, show in text
+
+local marked_todo = false -- keeps track or not yet flushed
+local marked_dataset = false
+local marked_list = false -- the sequential list (we flush in order, not by unordered hash)
+local marked_method = false
+
+local function marknocite(dataset,tag,nofcitations,setup)
+ ctx_btxstartcite()
+ ctx_btxsetdataset(dataset)
+ ctx_btxsettag(tag)
+ ctx_btxsetbacklink(nofcitations)
+ if trace_detail then
+ report("expanding cite setup %a",setup)
+ end
+ ctx_btxcitesetup(setup)
+ ctx_btxstopcite()
+end
+
+local function markcite(dataset,tag,flush)
+ if not marked_todo then
+ return 0
+ end
+ local citation = marked_todo[tag]
+ if not citation then
+ return 0
+ end
+ if citation == true then
+ nofcitations = nofcitations + 1
+ if trace_cite then
+ report_cite("mark, dataset: %s, tag: %s, number: %s, state: %s",dataset,tag,nofcitations,"cited")
+ end
+ if flush then
+ marknocite(dataset,tag,nofcitations,"nocite")
+ end
+ marked_todo[tag] = nofcitations -- signal that it's marked
+ return nofcitations
+ else
+ return citation
+ end
+end
+
+local function btxflushmarked()
+ if marked_list and marked_todo then
+ for i=1,#marked_list do
+ -- keep order
+ local tag = marked_list[i]
+ local tbm = marked_todo[tag]
+ if tbm == true or not tbm then
+ nofcitations = nofcitations + 1
+ local setup = (tbm or marked_method == v_always) and "nocite" or "invalid"
+ marknocite(marked_dataset,tag,nofcitations,setup)
+ if trace_cite then
+ report_cite("mark, dataset: %s, tag: %s, number: %s, setup: %s",marked_dataset,tag,nofcitations,setup)
+ end
+ else
+ -- a number signaling being marked
+ end
+ end
+ end
+ marked_todo = false
+ marked_dataset = false
+ marked_list = false
+ marked_method = false
+end
+
+implement { name = "btxflushmarked", actions = btxflushmarked }
+
+-- basic access
+
+local function getfield(dataset,tag,name) -- for the moment quick and dirty
+ local d = datasets[dataset].luadata[tag]
+ return d and d[name]
+end
+
+local function getdetail(dataset,tag,name) -- for the moment quick and dirty
+ local d = datasets[dataset].details[tag]
+ return d and d[name]
+end
+
+local function getcasted(dataset,tag,field,specification)
+ local current = datasets[dataset]
+ if current then
+ local data = current.luadata[tag]
+ if data then
+ local category = data.category
+ if not specification then
+ specification = currentspecification
+ end
+ local catspec = specification.categories[category]
+ if not catspec then
+ return false
+ end
+ local fields = catspec.fields
+ if fields then
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ for i=1,#set do
+ local field = set[i]
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ local kind = specification.types[field]
+ return detailed[kind][value], field, kind
+ end
+ end
+ end
+ end
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ local kind = specification.types[field]
+ return detailed[kind][value], field, kind
+ end
+ end
+ local data = current.details[tag]
+ if data then
+ local kind = specification.types[field]
+ return data[field], field, kind -- no check
+ end
+ end
+ end
+end
+
+local function getfaster(current,data,details,field,categories,types)
+ local category = data.category
+ local catspec = categories[category]
+ if not catspec then
+ return false
+ end
+ local fields = catspec.fields
+ if fields then
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ for i=1,#set do
+ local field = set[i]
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ local kind = types[field]
+ return detailed[kind][value], field, kind
+ end
+ end
+ end
+ end
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ local kind = types[field]
+ return detailed[kind][value]
+ end
+ end
+ if details then
+ local kind = types[field]
+ return details[field]
+ end
+end
+
+local function getdirect(dataset,data,field,catspec) -- no field check, no dataset check
+ local catspec = (catspec or currentspecification).categories[data.category]
+ if not catspec then
+ return false
+ end
+ local fields = catspec.fields
+ if fields then
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ for i=1,#set do
+ local field = set[i]
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ return value
+ end
+ end
+ end
+ end
+ return fields[field] and data[field] or nil -- redundant check
+ end
+end
+
+local function getfuzzy(data,field,categories) -- no field check, no dataset check
+ local catspec
+ if categories then
+ local category = data.category
+ if category then
+ catspec = categories[data.category]
+ end
+ end
+ if not field then
+ return
+ elseif not catspec then
+ return data[field]
+ end
+ local fields = catspec.fields
+ if fields then
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ for i=1,#set do
+ local field = set[i]
+ local value = fields[field] and data[field] -- redundant check
+ if value then
+ return value
+ end
+ end
+ end
+ end
+ return fields[field] and data[field] or nil -- redundant check
+ end
+end
+
+publications.getfield = getfield
+publications.getdetail = getdetail
+publications.getcasted = getcasted
+publications.getfaster = getfaster
+publications.getdirect = getdirect
+publications.getfuzzy = getfuzzy
+
+-- this needs to be checked: a specific type should have a checker
+
+-- author pagenumber keyword url
+
+-- function commands.btxsingularorplural(dataset,tag,name)
+-- local d = getcasted(dataset,tag,name)
+-- if type(d) == "table" then
+-- d = #d <= 1
+-- else
+-- d = true
+-- end
+-- ctx_doifelse(d)
+-- end
+
+-- function commands.oneorrange(dataset,tag,name)
+-- local d = datasets[dataset].luadata[tag] -- details ?
+-- if d then
+-- d = d[name]
+-- end
+-- if type(d) == "string" then
+-- d = find(d,"%-")
+-- else
+-- d = false
+-- end
+-- ctx_doifelse(not d) -- so singular is default
+-- end
+
+-- function commands.firstofrange(dataset,tag,name)
+-- local d = datasets[dataset].luadata[tag] -- details ?
+-- if d then
+-- d = d[name]
+-- end
+-- if type(d) == "string" then
+-- context(match(d,"([^%-]+)"))
+-- end
+-- end
+
+local inspectors = allocate()
+local nofmultiple = allocate()
+local firstandlast = allocate()
+
+publications.inspectors = inspectors
+inspectors.nofmultiple = nofmultiple
+inspectors.firstandlast = firstandlast
+
+function nofmultiple.author(d)
+ return type(d) == "table" and #d or 0
+end
+
+function publications.singularorplural(dataset,tag,name)
+ local data, field, kind = getcasted(dataset,tag,name)
+ if data then
+ local test = nofmultiple[kind]
+ if test then
+ local n = test(data)
+ return not n or n < 2
+ end
+ end
+ return true
+end
+
+function firstandlast.range(d)
+ if type(d) == "table" then
+ return d[1], d[2]
+ end
+end
+
+firstandlast.pagenumber = firstandlast.range
+
+function publications.oneorrange(dataset,tag,name)
+ local data, field, kind = getcasted(dataset,tag,name)
+ if data then
+ local test = firstandlast[kind]
+ if test then
+ local first, last = test(data)
+ return not (first and last)
+ end
+ end
+ return nil -- nothing at all
+end
+
+function publications.firstofrange(dataset,tag,name)
+ local data, field, kind = getcasted(dataset,tag,name)
+ if data then
+ local test = firstandlast[kind]
+ if test then
+ local first = test(data)
+ if first then
+ return first
+ end
+ end
+ end
+end
+
+function publications.lastofrange(dataset,tag,name)
+ local data, field, kind = getcasted(dataset,tag,name)
+ if data then
+ local test = firstandlast[kind]
+ if test then
+ local first, last = test(data)
+ if last then
+ return last
+ end
+ end
+ end
+end
+
+local three_strings = { "string", "string", "string" }
+
+implement {
+ name = "btxsingularorplural",
+ actions = { publications.singularorplural, ctx_doifelse },
+ arguments = three_strings
+}
+
+implement {
+ name = "btxoneorrange",
+ actions = { publications.oneorrange, function(b) if b == nil then ctx_gobbletwoarguments() else ctx_doifelse(b) end end },
+ arguments = three_strings
+}
+
+implement {
+ name = "btxfirstofrange",
+ actions = { publications.firstofrange, context },
+ arguments = three_strings
+}
+
+implement {
+ name = "btxlastofrange",
+ actions = { publications.lastofrange, context },
+ arguments = three_strings
+}
+
+-- basic loading
+
+function publications.usedataset(specification)
+ specification.kind = "current"
+ publications.load(specification)
+end
+
+implement {
+ name = "btxusedataset",
+ actions = publications.usedataset,
+ arguments = {
+ {
+ { "specification" },
+ { "dataset" },
+ { "filename" },
+ }
+ }
+}
+
+implement {
+ name = "convertbtxdatasettoxml",
+ arguments = { "string", true },
+ actions = publications.converttoxml
+}
+
+-- enhancing
+
+do
+
+ -- maybe not redo when already done
+
+ local function shortsorter(a,b)
+ local ay, by = a[2], b[2] -- year
+ if ay ~= by then
+ return ay < by
+ end
+ local ay, by = a[3], b[3] -- suffix
+ if ay ~= by then
+ -- bah, bah, bah
+ local an, bn = tonumber(ay), tonumber(by)
+ if an and bn then
+ return an < bn
+ else
+ return ay < by
+ end
+ end
+ return a[4] < b[4]
+ end
+
+ -- We could avoid loops by combining enhancers but that makes it only
+ -- more messy and for documents that use publications the few extra milli
+ -- seconds are irrelevant (there is for sure more to gain by proper coding
+ -- of the source and or style).
+
+ local f_short = formatters["%s%02i"]
+
+ function publications.enhancers.suffixes(dataset)
+ if not dataset then
+ return -- bad news
+ else
+ report("analyzing previous publication run for %a",dataset.name)
+ end
+ dataset.suffixed = true
+ --
+ local used = usedentries[dataset.name]
+ if not used then
+ return -- probably a first run
+ end
+ local luadata = dataset.luadata
+ local details = dataset.details
+ local ordered = dataset.ordered
+ if not luadata or not details or not ordered then
+ report("nothing to be analyzed in %a",dataset.name)
+ return -- also bad news
+ end
+ -- we have two suffixes: author (dependent of type) and short
+ local kind = dataset.authorconversion or "name"
+ local fields = { "author", "editor" } -- will be entry in data definition
+ local shorts = { }
+ local authors = { }
+ local hasher = publications.authorhashers[kind]
+ local shorter = publications.authorhashers.short
+ for i=1,#ordered do
+ local entry = ordered[i]
+ if entry then
+ local tag = entry.tag
+ if tag then
+ local use = used[tag]
+ if use then
+ -- use is a table of used list entries (so there can be more) and we just look at
+ -- the first one for btx properties
+ local listentry = use[1]
+ local userdata = listentry.userdata
+ local btxspc = userdata and userdata.btxspc
+ if btxspc then
+ -- we could act on the 3rd arg returned by getcasted but in general any string will do
+ -- so we deal with it in the author hashers ... maybe some day ...
+ local done = false
+ for i=1,#fields do
+ local field = fields[i]
+ local author = getcasted(dataset,tag,field,specifications[btxspc])
+ local kind = type(author)
+ if kind == "table" or kind == "string" then
+ if u then
+ u = listentry.entries.text -- hm
+ else
+ u = "0"
+ end
+ local year = tonumber(entry.year) or 9999
+ local data = { tag, year, u, i }
+ -- authors
+ local hash = hasher(author)
+ local found = authors[hash]
+ if not found then
+ authors[hash] = { data }
+ else
+ found[#found+1] = data
+ end
+ -- shorts
+ local hash = shorter(author)
+ local short = f_short(hash,mod(year,100))
+ local found = shorts[short]
+ if not found then
+ shorts[short] = { data }
+ else
+ found[#found+1] = data
+ end
+ done = true
+ break
+ end
+ end
+ if not done then
+ report("unable to create short for %a, needs one of [%,t]",tag,fields)
+ end
+ else
+ --- no spec so let's forget about it
+ end
+ end
+ end
+ end
+ end
+ local function addsuffix(hashed,key,suffixkey)
+ for hash, tags in sortedhash(hashed) do -- ordered ?
+ local n = #tags
+ if n == 0 then
+ -- skip
+ elseif n == 1 then
+ local tagdata = tags[1]
+ local tag = tagdata[1]
+ local detail = details[tag]
+ local entry = luadata[tag]
+ local year = entry.year
+ detail[key] = hash
+ elseif n > 1 then
+ sort(tags,shortsorter) -- or take first -- todo: proper utf sorter
+ local lastyear = nil
+ local suffix = nil
+ local previous = nil
+ for i=1,n do
+ local tagdata = tags[i]
+ local tag = tagdata[1]
+ local detail = details[tag]
+ local entry = luadata[tag]
+ local year = entry.year
+ detail[key] = hash
+ if not year or year ~= lastyear then
+ lastyear = year
+ suffix = 1
+ else
+ if previous and suffix == 1 then
+ previous[suffixkey] = suffix
+ end
+ suffix = suffix + 1
+ detail[suffixkey] = suffix
+ end
+ previous = detail
+ end
+ end
+ if trace_suffixes then
+ for i=1,n do
+ local tag = tags[i][1]
+ local year = luadata[tag].year
+ local suffix = details[tag].suffix
+ if suffix then
+ report_suffix("%s: tag %a, hash %a, year %a, suffix %a",key,tag,hash,year or '',suffix or '')
+ else
+ report_suffix("%s: tag %a, hash %a, year %a",key,tag,hash,year or '')
+ end
+ end
+ end
+ end
+ end
+ addsuffix(shorts, "shorthash", "shortsuffix") -- todo: shorthash
+ addsuffix(authors,"authorhash","authorsuffix")
+ end
+
+ -- utilities.sequencers.appendaction(enhancer,"system","publications.enhancers.suffixes")
+
+end
+
+implement {
+ name = "btxaddentry",
+ actions = function(name,settings,content)
+ local dataset = datasets[name]
+ if dataset then
+ publications.addtexentry(dataset,settings,content)
+ end
+ end,
+ arguments = { "string", "string", "string" }
+}
+
+function publications.checkeddataset(name,default)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ return name
+ elseif default and default ~= "" then
+ return default
+ else
+ report("unknown dataset %a, forcing %a",name,v_default)
+ return v_default
+ end
+end
+
+implement {
+ name = "btxsetdataset",
+ actions = { publications.checkeddataset, context },
+ arguments = { "string", "string"}
+}
+
+implement {
+ name = "btxsetentry",
+ actions = function(name,tag)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ if dataset.luadata[tag] then
+ context(tag)
+ else
+ report("unknown tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown dataset %a",name)
+ end
+ end,
+ arguments = { "string", "string" },
+}
+
+-- rendering of fields
+
+do
+
+ local typesetters = { }
+ publications.typesetters = typesetters
+
+ local function defaulttypesetter(field,value,manipulator)
+ if value and value ~= "" then
+ value = tostring(value)
+ context(manipulator and applymanipulation(manipulator,value) or value)
+ end
+ end
+
+ setmetatableindex(typesetters,function(t,k)
+ local v = defaulttypesetter
+ t[k] = v
+ return v
+ end)
+
+ function typesetters.string(field,value,manipulator)
+ if value and value ~= "" then
+ context(manipulator and applymanipulation(manipulator,value) or value)
+ end
+ end
+
+ function typesetters.author(field,value,manipulator)
+ ctx_btxflushauthor(field)
+ end
+
+ -- function typesetters.url(field,value,manipulator)
+ -- ....
+ -- end
+
+ -- if there is no specification then we're in trouble but there is
+ -- always a default anyway
+ --
+ -- there's also always a fields table but it can be empty due to
+ -- lack of specifications
+ --
+ -- then there can be cases where we have no specification for instance
+ -- when we have a special kind of database
+
+ local splitter = lpeg.splitat(":")
+
+ local function permitted(category,field)
+ local catspec = currentspecification.categories[category]
+ if not catspec then
+ report("invalid category %a, %s",category,"no specification") -- can't happen
+ return false
+ end
+ local fields = catspec.fields
+ if not fields then
+ report("invalid category %a, %s",category,"no fields") -- can't happen
+ return false
+ end
+ if ignoredfields and ignoredfields[field] then
+ return false
+ end
+ local virtualfields = currentspecification.virtualfields
+ if virtualfields and virtualfields[field] then
+ return true
+ end
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ return set
+ end
+ end
+ if fields[field] then
+ return true
+ end
+ local f, l = lpegmatch(splitter,field)
+ if f and l and fields[f] then
+ return true -- language specific one
+ end
+ end
+
+ local function found(dataset,tag,field,valid,fields)
+ if valid == true then
+ -- local fields = dataset.luadata[tag]
+ local okay = fields[field]
+ if okay then
+ return field, okay
+ end
+ local details = dataset.details[tag]
+ local value = details[field]
+ if value then
+ return field, value
+ end
+ elseif valid then
+ -- local fields = dataset.luadata[tag]
+ for i=1,#valid do
+ local field = valid[i]
+ local value = fields[field]
+ if value then
+ return field, value
+ end
+ end
+ local details = dataset.details[tag]
+ for i=1,#valid do
+ local value = details[field]
+ if value then
+ return field, value
+ end
+ end
+ end
+ end
+
+ local function get(dataset,tag,field,what,check,catspec) -- somewhat more extensive
+ local current = rawget(datasets,dataset)
+ if current then
+ local data = current.luadata[tag]
+ if data then
+ local category = data.category
+ local catspec = (catspec or currentspecification).categories[category]
+ if not catspec then
+ return false
+ end
+ local fields = catspec.fields
+ if fields then
+ local sets = catspec.sets
+ if sets then
+ local set = sets[field]
+ if set then
+ if check then
+ for i=1,#set do
+ local field = set[i]
+ local kind = (not check or data[field]) and fields[field]
+ if kind then
+ return what and kind or field
+ end
+ end
+ elseif what then
+ local t = { }
+ for i=1,#set do
+ t[i] = fields[set[i]] or "unknown"
+ end
+ return concat(t,",")
+ else
+ return concat(set,",")
+ end
+ end
+ end
+ local kind = (not check or data[field]) and fields[field]
+ if kind then
+ return what and kind or field
+ end
+ end
+ end
+ end
+ return ""
+ end
+
+ publications.permitted = permitted
+ publications.found = found
+ publications.get = get
+
+ local function btxflush(name,tag,field)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ local fields = dataset.luadata[tag]
+ if fields then
+ local manipulator, field = splitmanipulation(field)
+ local category = fields.category
+ local valid = permitted(category,field)
+ if valid then
+ local name, value = found(dataset,tag,field,valid,fields)
+ if value then
+ typesetters[currentspecification.types[name]](field,value,manipulator)
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","unknown","entry",field,category,tag,name)
+ end
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","invalid","entry",field,category,tag,name)
+ end
+ else
+ report("unknown tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown dataset %a",name)
+ end
+ end
+
+ local function btxfield(name,tag,field)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ local fields = dataset.luadata[tag]
+ if fields then
+ local category = fields.category
+ local manipulator, field = splitmanipulation(field)
+ if permitted(category,field) then
+ local value = fields[field]
+ if value then
+ typesetters[currentspecification.types[field]](field,value,manipulator)
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","unknown","field",field,category,tag,name)
+ end
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","invalid","field",field,category,tag,name)
+ end
+ else
+ report("unknown tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown dataset %a",name)
+ end
+ end
+
+ local function btxdetail(name,tag,field)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ local fields = dataset.luadata[tag]
+ if fields then
+ local details = dataset.details[tag]
+ if details then
+ local category = fields.category
+ local manipulator, field = splitmanipulation(field)
+ if permitted(category,field) then
+ local value = details[field]
+ if value then
+ typesetters[currentspecification.types[field]](field,value,manipulator)
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","unknown","detail",field,category,tag,name)
+ end
+ elseif trace_detail then
+ report("%s %s %a in category %a for tag %a in dataset %a","invalid","detail",field,category,tag,name)
+ end
+ else
+ report("no details for tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown dataset %a",name)
+ end
+ end
+
+ local function btxdirect(name,tag,field)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ local fields = dataset.luadata[tag]
+ if fields then
+ local manipulator, field = splitmanipulation(field)
+ local value = fields[field]
+ if value then
+ context(typesetters.default(field,value,manipulator))
+ elseif trace_detail then
+ report("field %a of tag %a in dataset %a has no value",field,tag,name)
+ end
+ else
+ report("unknown tag %a in dataset %a",tag,name)
+ end
+ else
+ report("unknown dataset %a",name)
+ end
+ end
+
+ local function okay(name,tag,field)
+ local dataset = rawget(datasets,name)
+ if dataset then
+ local fields = dataset.luadata[tag]
+ if fields then
+ local category = fields.category
+ local valid = permitted(category,field)
+ if valid then
+ local value, field = found(dataset,tag,field,valid,fields)
+ return value and value ~= ""
+ end
+ end
+ end
+ end
+
+ publications.okay = okay
+
+ implement { name = "btxfield", actions = btxfield, arguments = { "string", "string", "string" } }
+ implement { name = "btxdetail", actions = btxdetail, arguments = { "string", "string", "string" } }
+ implement { name = "btxflush", actions = btxflush, arguments = { "string", "string", "string" } }
+ implement { name = "btxdirect", actions = btxdirect, arguments = { "string", "string", "string" } }
+
+ implement { name = "btxfieldname", actions = { get, context }, arguments = { "string", "string", "string", false, false } }
+ implement { name = "btxfieldtype", actions = { get, context }, arguments = { "string", "string", "string", true, false } }
+ implement { name = "btxfoundname", actions = { get, context }, arguments = { "string", "string", "string", false, true } }
+ implement { name = "btxfoundtype", actions = { get, context }, arguments = { "string", "string", "string", true, true } }
+
+ implement { name = "btxdoifelse", actions = { okay, ctx_doifelse }, arguments = { "string", "string", "string" } }
+ implement { name = "btxdoif", actions = { okay, ctx_doif }, arguments = { "string", "string", "string" } }
+ implement { name = "btxdoifnot", actions = { okay, ctx_doifnot }, arguments = { "string", "string", "string" } }
+
+end
+
+-- -- alternative approach: keep data at the tex end
+
+function publications.singularorplural(singular,plural)
+ if lastconcatsize and lastconcatsize > 1 then
+ context(plural)
+ else
+ context(singular)
+ end
+end
+
+-- loading
+
+do
+
+ local patterns = {
+ "publ-imp-%s.mkvi",
+ "publ-imp-%s.mkiv",
+ "publ-imp-%s.tex",
+ }
+
+ local function failure(name)
+ report("unknown library %a",name)
+ end
+
+ local function action(name,foundname)
+ context.input(foundname)
+ end
+
+ function publications.loaddefinitionfile(name) -- a more specific name
+ resolvers.uselibrary {
+ name = gsub(name,"^publ%-",""),
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+ end
+
+ local patterns = {
+ "publ-imp-%s.lua",
+ }
+
+ function publications.loadreplacementfile(name) -- a more specific name
+ resolvers.uselibrary {
+ name = gsub(name,"^publ%-",""),
+ patterns = patterns,
+ action = publications.loaders.registercleaner,
+ failure = failure,
+ onlyonce = true,
+ }
+ end
+
+ implement { name = "btxloaddefinitionfile", actions = publications.loaddefinitionfile, arguments = "string" }
+ implement { name = "btxloadreplacementfile", actions = publications.loadreplacementfile, arguments = "string" }
+
+end
+
+-- lists
+
+do
+
+ publications.lists = publications.lists or { }
+ local lists = publications.lists
+
+ local context = context
+ local structures = structures
+
+ local references = structures.references
+ local sections = structures.sections
+
+ -- per rendering
+
+ local renderings = { } --- per dataset
+
+ setmetatableindex(renderings,function(t,k)
+ local v = {
+ list = { },
+ done = { },
+ alldone = { },
+ used = { },
+ registered = { },
+ ordered = { },
+ shorts = { },
+ method = v_none,
+ texts = setmetatableindex("table"),
+ currentindex = 0,
+ }
+ t[k] = v
+ return v
+ end)
+
+ -- helper
+
+ function lists.register(dataset,tag,short) -- needs checking now that we split
+ local r = renderings[dataset]
+ if not short or short == "" then
+ short = tag
+ end
+ if trace then
+ report("registering publication entry %a with shortcut %a",tag,short)
+ end
+ local top = #r.registered + 1
+ -- do we really need these
+ r.registered[top] = tag
+ r.ordered [tag] = top
+ r.shorts [tag] = short
+ end
+
+ function lists.nofregistered(dataset)
+ return #renderings[dataset].registered
+ end
+
+ local function validkeyword(dataset,tag,keyword,specification) -- todo: pass specification
+ local kw = getcasted(dataset,tag,"keywords",specification)
+ if kw then
+ for i=1,#kw do
+ if keyword[kw[i]] then
+ return true
+ end
+ end
+ end
+ end
+
+ local function registerpage(pages,tag,result,listindex)
+ local p = pages[tag]
+ local r = result[listindex].references
+ if p then
+ local last = p[#p][2]
+ local real = last.realpage
+ if real ~= r.realpage then
+ p[#p+1] = { listindex, r }
+ end
+ else
+ pages[tag] = { { listindex, r } }
+ end
+ end
+
+
+ -- tag | listindex | reference | userdata | dataindex
+
+ local methods = { }
+ lists.methods = methods
+
+ methods[v_dataset] = function(dataset,rendering,keyword)
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local list = rendering.list
+ for tag, data in sortedhash(luadata) do
+ if not keyword or validkeyword(dataset,tag,keyword) then
+ local index = data.index or 0
+ list[#list+1] = { tag, index, 0, false, index }
+ end
+ end
+ end
+
+ -- todo: names = { "btx" }
+
+ methods[v_force] = function (dataset,rendering,keyword)
+ -- only for checking, can have duplicates, todo: collapse page numbers, although
+ -- we then also needs deferred writes
+ local result = structures.lists.filter(rendering.specifications) or { }
+ local list = rendering.list
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ for listindex=1,#result do
+ local r = result[listindex]
+ local u = r.userdata -- better check on metadata.kind == "btx"
+ if u then
+ local set = u.btxset or v_default
+ if set == dataset then
+ local tag = u.btxref
+ if tag and (not keyword or validkeyword(dataset,tag,keyword)) then
+ local data = luadata[tag]
+ list[#list+1] = { tag, listindex, 0, u, data and data.index or 0 }
+ end
+ end
+ end
+ end
+ lists.result = result
+ end
+
+ -- local : if tag and done[tag] ~= section then ...
+ -- global : if tag and not alldone[tag] and done[tag] ~= section then ...
+
+ methods[v_local] = function(dataset,rendering,keyword)
+ local result = structures.lists.filter(rendering.specifications) or { }
+ local section = sections.currentid()
+ local list = rendering.list
+ local repeated = rendering.repeated == v_yes
+ local r_done = rendering.done
+ local r_alldone = rendering.alldone
+ local done = repeated and { } or r_done
+ local alldone = repeated and { } or r_alldone
+ local doglobal = rendering.method == v_global
+ local traced = { } -- todo: only if interactive (backlinks) or when tracing
+ local pages = { }
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ -- handy for tracing :
+ rendering.result = result
+ --
+ for listindex=1,#result do
+ local r = result[listindex]
+ local u = r.userdata
+ if u then -- better check on metadata.kind == "btx"
+ local set = u.btxset or v_default
+ if set == dataset then
+-- inspect(structures.references.internals[tonumber(u.btxint)])
+ local tag = u.btxref
+ if not tag then
+ -- problem
+ elseif done[tag] == section then -- a bit messy for global and all and so
+ -- skip
+ elseif doglobal and alldone[tag] then
+ -- skip
+ elseif not keyword or validkeyword(dataset,tag,keyword) then
+ if traced then
+ local l = traced[tag]
+ if l then
+ l[#l+1] = u.btxint
+ else
+ local data = luadata[tag]
+ local l = { tag, listindex, 0, u, data and data.index or 0 }
+ list[#list+1] = l
+ traced[tag] = l
+ end
+ else
+ done[tag] = section
+ alldone[tag] = true
+ local data = luadata[tag]
+ list[#list+1] = { tag, listindex, 0, u, data and data.index or 0 }
+ end
+ end
+ if tag then
+ registerpage(pages,tag,result,listindex)
+ end
+ end
+ end
+ end
+ if traced then
+ for tag in next, traced do
+ done[tag] = section
+ alldone[tag] = true
+ end
+ end
+ lists.result = result
+ structures.lists.result = result
+ rendering.pages = pages -- or list.pages
+ end
+
+ methods[v_global] = methods[v_local]
+
+ function lists.collectentries(specification)
+ local dataset = specification.dataset
+ if not dataset then
+ return
+ end
+ local rendering = renderings[dataset]
+ if not rendering then
+ return
+ end
+ local method = specification.method or v_none
+ local ignored = specification.ignored or ""
+ rendering.method = method
+ rendering.ignored = ignored ~= "" and settings_to_set(ignored) or nil
+ rendering.list = { }
+ rendering.done = { }
+ rendering.sorttype = specification.sorttype or v_default
+ rendering.criterium = specification.criterium or v_none
+ rendering.repeated = specification.repeated or v_no
+ rendering.group = specification.group or ""
+ rendering.specifications = specification
+ local filtermethod = methods[method]
+ if not filtermethod then
+ report_list("invalid method %a",method or "")
+ return
+ end
+ report_list("collecting entries using method %a and sort order %a",method,rendering.sorttype)
+ lists.result = { } -- kind of reset
+ local keyword = specification.keyword
+ if keyword and keyword ~= "" then
+ keyword = settings_to_set(keyword)
+ else
+ keyword = nil
+ end
+ filtermethod(dataset,rendering,keyword)
+ local list = rendering.list
+ ctx_btxsetnoflistentries(list and #list or 0)
+ end
+
+ -- for determining width
+
+ local groups = setmetatableindex("number")
+
+ function lists.prepareentries(dataset)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ local used = rendering.used
+ local forceall = rendering.criterium == v_all
+ local repeated = rendering.repeated == v_yes
+ local sorttype = rendering.sorttype or v_default
+ local group = rendering.group or ""
+ local sorter = lists.sorters[sorttype]
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local details = current.details
+ local newlist = { }
+ local lastreferencenumber = groups[group] -- current.lastreferencenumber or 0
+ for i=1,#list do
+ local li = list[i]
+ local tag = li[1]
+ local entry = luadata[tag]
+ if entry then
+ if forceall or repeated or not used[tag] then
+ newlist[#newlist+1] = li
+ -- already here:
+ if not repeated then
+ used[tag] = true -- beware we keep the old state (one can always use criterium=all)
+ end
+ end
+ end
+ end
+ if type(sorter) == "function" then
+ list = sorter(dataset,rendering,newlist,sorttype) or newlist
+ else
+ list = newlist
+ end
+ local newlist = { }
+ local tagtolistindex = { }
+ rendering.tagtolistindex = tagtolistindex
+ for i=1,#list do
+ local li = list[i]
+ local tag = li[1]
+ local entry = luadata[tag]
+ if entry then
+ local detail = details[tag]
+ if not detail then
+ -- fatal error
+ report("fatal error, missing details for tag %a in dataset %a (enhanced: %s)",tag,dataset,current.enhanced and "yes" or "no")
+ -- lastreferencenumber = lastreferencenumber + 1
+ -- details[tag] = { referencenumber = lastreferencenumber }
+ -- li[3] = lastreferencenumber
+ -- tagtolistindex[tag] = i
+ -- newlist[#newlist+1] = li
+ elseif detail.parent then
+ -- skip this one
+ else
+ local referencenumber = detail.referencenumber
+ if not referencenumber then
+ lastreferencenumber = lastreferencenumber + 1
+ referencenumber = lastreferencenumber
+ detail.referencenumber = lastreferencenumber
+ end
+ li[3] = referencenumber
+ tagtolistindex[tag] = i
+ newlist[#newlist+1] = li
+ end
+ end
+ end
+ groups[group] = lastreferencenumber
+ rendering.list = newlist
+ end
+
+ function lists.fetchentries(dataset)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ if list then
+ for i=1,#list do
+ local li = list[i]
+ ctx_btxsettag(li[1])
+ ctx_btxsetnumber(li[3])
+ ctx_btxchecklistentry()
+ end
+ end
+ end
+
+ -- for rendering
+
+ -- setspecification
+
+ local function btxflushpages(dataset,tag)
+ -- todo: interaction
+ local rendering = renderings[dataset]
+ local pages = rendering.pages
+ if not pages then
+ return
+ else
+ pages = pages[tag]
+ end
+ if not pages then
+ return
+ end
+ local nofpages = #pages
+ if nofpages == 0 then
+ return
+ end
+ local first_p = nil
+ local first_r = nil
+ local last_p = nil
+ local last_r = nil
+ local ranges = { }
+ local nofdone = 0
+ local function flush()
+ if last_r and first_r ~= last_r then
+ ranges[#ranges+1] = { first_p, last_p }
+ else
+ ranges[#ranges+1] = { first_p }
+ end
+ end
+ for i=1,nofpages do
+ local next_p = pages[i]
+ local next_r = next_p[2].realpage
+ if not first_r then
+ first_p = next_p
+ first_r = next_r
+ elseif last_r + 1 == next_r then
+ -- continue
+ elseif first_r then
+ flush()
+ first_p = next_p
+ first_r = next_r
+ end
+ last_p = next_p
+ last_r = next_r
+ end
+ if first_r then
+ flush()
+ end
+ local nofranges = #ranges
+ for i=1,nofranges do
+ local r = ranges[i]
+ ctx_btxsetconcat(concatstate(i,nofranges))
+ local first, last = r[1], r[2]
+ ctx_btxsetfirstinternal(first[2].internal)
+ ctx_btxsetfirstpage(first[1])
+ if last then
+ ctx_btxsetlastinternal(last[2].internal)
+ ctx_btxsetlastpage(last[1])
+ end
+ if trace_detail then
+ report("expanding page setup")
+ end
+ ctx_btxpagesetup("") -- nothing yet
+ end
+ end
+
+ implement {
+ name = "btxflushpages",
+ actions = btxflushpages,
+ arguments = { "string", "string" }
+ }
+
+ function lists.sameasprevious(dataset,i,name,order,method)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ local n = tonumber(i)
+ if n and n > 1 and n <= #list then
+ local luadata = datasets[dataset].luadata
+ local p_index = list[n-1][1]
+ local c_index = list[n ][1]
+ local previous = getdirect(dataset,luadata[p_index],name)
+ local current = getdirect(dataset,luadata[c_index],name)
+
+ -- authors are a special case
+
+ -- if not order then
+ -- order = gettexcounter("c_btx_list_reference")
+ -- end
+ if order and order > 0 and (method == v_always or method == v_doublesided) then
+ local clist = listtolist[order]
+ local plist = listtolist[order-1]
+ if clist and plist then
+ local crealpage = clist.references.realpage
+ local prealpage = plist.references.realpage
+ if crealpage ~= prealpage then
+ if method == v_always or not conditionals.layoutisdoublesided then
+ if trace_detail then
+ report("previous %a, current %a, different page",previous,current)
+ end
+ return false
+ elseif crealpage % 2 == 0 then
+ if trace_detail then
+ report("previous %a, current %a, different page",previous,current)
+ end
+ return false
+ end
+ end
+ end
+ end
+ local sameentry = false
+ if current and current == previous then
+ sameentry = true
+ else
+ local p_casted = getcasted(dataset,p_index,name)
+ local c_casted = getcasted(dataset,c_index,name)
+ if c_casted and c_casted == p_casted then
+ sameentry = true
+ elseif type(c_casted) == "table" and type(p_casted) == "table" then
+ sameentry = table.identical(c_casted,p_casted)
+ end
+ end
+ if trace_detail then
+ if sameentry then
+ report("previous %a, current %a, same entry",previous,current)
+ else
+ report("previous %a, current %a, different entry",previous,current)
+ end
+ end
+ return sameentry
+ else
+ return false
+ end
+ end
+
+ function lists.combiinlist(dataset,tag)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ local toindex = rendering.tagtolistindex
+ return toindex and toindex[tag]
+ end
+
+ function lists.flushcombi(dataset,tag)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ local toindex = rendering.tagtolistindex
+ local listindex = toindex and toindex[tag]
+ if listindex then
+ local li = list[listindex]
+ if li then
+ local data = datasets[dataset]
+ local luadata = data.luadata
+ local details = data.details
+ local tag = li[1]
+ local listindex = li[2]
+ local n = li[3]
+ local entry = luadata[tag]
+ local detail = details[tag]
+ ctx_btxstartcombientry()
+ ctx_btxsetcurrentlistindex(listindex)
+ ctx_btxsetcategory(entry.category or "unknown")
+ ctx_btxsettag(tag)
+ ctx_btxsetnumber(n)
+ local language = entry.language
+ if language then
+ ctx_btxsetlanguage(language)
+ end
+ local authorsuffix = detail.authorsuffix
+ if authorsuffix then
+ ctx_btxsetsuffix(authorsuffix)
+ end
+ ctx_btxhandlecombientry()
+ ctx_btxstopcombientry()
+ end
+ end
+ end
+
+ function lists.flushentry(dataset,i,textmode)
+ local rendering = renderings[dataset]
+ local list = rendering.list
+ local li = list[i]
+ if li then
+ local data = datasets[dataset]
+ local luadata = data.luadata
+ local details = data.details
+ local tag = li[1]
+ local listindex = li[2]
+ local n = li[3]
+ local entry = luadata[tag]
+ local detail = details[tag]
+ --
+ ctx_btxstartlistentry()
+ ctx_btxsetcurrentlistentry(i) -- redundant
+ ctx_btxsetcurrentlistindex(listindex or 0)
+ local children = detail.children
+ local language = entry.language
+ if children then
+ ctx_btxsetcombis(concat(children,","))
+ end
+ ctx_btxsetcategory(entry.category or "unknown")
+ ctx_btxsettag(tag)
+ ctx_btxsetnumber(n)
+ if language then
+ ctx_btxsetlanguage(language)
+ end
+ local userdata = li[4]
+ if userdata then
+ local b = userdata.btxbtx
+ local a = userdata.btxatx
+ if b then
+ ctx_btxsetbefore(b)
+ end
+ if a then
+ ctx_btxsetafter(a)
+ end
+ local bl = userdata.btxint
+ if bl and bl ~= "" then
+ ctx_btxsetbacklink(bl)
+ end
+ end
+ local authorsuffix = detail.authorsuffix
+ if authorsuffix then
+ ctx_btxsetsuffix(authorsuffix)
+ end
+ rendering.userdata = userdata
+ if textmode then
+ ctx_btxhandlelisttextentry()
+ else
+ ctx_btxhandlelistentry()
+ end
+ ctx_btxstoplistentry()
+ --
+ -- context(function()
+ -- -- wrapup
+ -- rendering.ignoredfields = nil
+ -- end)
+ end
+ end
+
+ local function getuserdata(dataset,key)
+ local rendering = renderings[dataset]
+ if rendering then
+ local userdata = rendering.userdata
+ if userdata then
+ local value = userdata[key]
+ if value and value ~= "" then
+ return value
+ end
+ end
+ end
+ end
+
+ lists.uservariable = getuserdata
+
+ function lists.filterall(dataset)
+ local r = renderings[dataset]
+ local list = r.list
+ local registered = r.registered
+ for i=1,#registered do
+ list[i] = { registered[i], i, 0, false, false }
+ end
+ end
+
+ implement {
+ name = "btxuservariable",
+ actions = { getuserdata, context },
+ arguments = { "string", "string" }
+ }
+
+ implement {
+ name = "btxdoifelseuservariable",
+ actions = { getuserdata, ctx_doifelse },
+ arguments = { "string", "string" }
+ }
+
+ -- implement {
+ -- name = "btxresolvelistreference",
+ -- actions = lists.resolve,
+ -- arguments = { "string", "string" }
+ -- }
+
+ implement {
+ name = "btxcollectlistentries",
+ actions = lists.collectentries,
+ arguments = {
+ {
+ { "names" },
+ { "criterium" },
+ { "reference" },
+ { "method" },
+ { "dataset" },
+ { "keyword" },
+ { "sorttype" },
+ { "repeated" },
+ { "ignored" },
+ { "group" },
+ }
+ }
+ }
+
+ implement {
+ name = "btxpreparelistentries",
+ actions = lists.prepareentries,
+ arguments = { "string" },
+ }
+
+ implement {
+ name = "btxfetchlistentries",
+ actions = lists.fetchentries,
+ arguments = { "string" },
+ }
+
+ implement {
+ name = "btxflushlistentry",
+ actions = lists.flushentry,
+ arguments = { "string", "integer" }
+ }
+
+ implement {
+ name = "btxflushlistcombi",
+ actions = lists.flushcombi,
+ arguments = { "string", "string" }
+ }
+
+ implement {
+ name = "btxdoifelsesameasprevious",
+ actions = { lists.sameasprevious, ctx_doifelse },
+ arguments = { "string", "integer", "string", "integer", "string" }
+ }
+
+ implement {
+ name = "btxdoifelsecombiinlist",
+ actions = { lists.combiinlist, ctx_doifelse },
+ arguments = { "string", "string" }
+ }
+
+end
+
+do
+
+ local citevariants = { }
+ publications.citevariants = citevariants
+
+ local function btxhandlecite(specification)
+ local dataset = specification.dataset or v_default
+ local reference = specification.reference
+ local variant = specification.variant
+ if not variant or variant == "" then
+ variant = "default"
+ end
+ if not reference or reference == "" then
+ return
+ end
+ --
+ local data = datasets[dataset]
+ if not data.suffixed then
+ data.authorconversion = specification.authorconversion
+ publications.enhancers.suffixes(data)
+ end
+ --
+ specification.variant = variant
+ specification.compress = specification.compress
+ specification.markentry = specification.markentry ~= false
+ --
+ if specification.sorttype == v_yes then
+ specification.sorttype = v_normal
+ end
+ --
+ local prefix, rest = lpegmatch(prefixsplitter,reference)
+ if prefix and rest then
+ dataset = prefix
+ specification.dataset = prefix
+ specification.reference = rest
+ end
+ --
+ if trace_cite then
+ report_cite("inject, dataset: %s, tag: %s, variant: %s, compressed",
+ specification.dataset or "-",
+ specification.reference,
+ specification.variant
+ )
+ end
+ --
+ ctx_btxsetdataset(dataset)
+ --
+ citevariants[variant](specification) -- we always fall back on default
+ end
+
+ local function btxhandlenocite(specification)
+ if trialtypesetting() then
+ return
+ end
+ local dataset = specification.dataset or v_default
+ local reference = specification.reference
+ if not reference or reference == "" then
+ return
+ end
+ --
+ local method = specification.method
+ local internal = specification.internal or ""
+ --
+ local prefix, rest = lpegmatch(prefixsplitter,reference)
+ if rest then
+ dataset = prefix
+ reference = rest
+ end
+ --
+ if trace_cite then
+ report_cite("mark, dataset: %s, tags: %s",dataset or "-",reference)
+ end
+ --
+ local reference = publications.parenttag(dataset,reference)
+ --
+ local found, todo, list = findallused(dataset,reference,internal)
+ --
+ if todo then
+ marked_todo = todo
+ marked_dataset = dataset
+ marked_list = list
+ marked_method = method
+ btxflushmarked() -- here (could also be done in caller)
+ else
+ marked_todo = false
+ end
+ end
+
+ implement {
+ name = "btxhandlecite",
+ actions = btxhandlecite,
+ arguments = {
+ {
+ { "dataset" },
+ { "reference" },
+ { "method" },
+ { "variant" },
+ { "sorttype" },
+ { "compress" },
+ { "authorconversion" },
+ { "author" },
+ { "lefttext" },
+ { "righttext" },
+ { "before" },
+ { "after" },
+ }
+ }
+ }
+
+ implement {
+ name = "btxhandlenocite",
+ actions = btxhandlenocite,
+ arguments = {
+ {
+ { "dataset" },
+ { "reference" },
+ { "method" },
+ }
+ }
+ }
+
+ -- sorter
+
+ local keysorter = function(a,b)
+ local ak = a.sortkey
+ local bk = b.sortkey
+ if ak == bk then
+ local as = a.suffix -- numeric
+ local bs = b.suffix -- numeric
+ if as and bs then
+ return (as or 0) < (bs or 0)
+ else
+ return false
+ end
+ else
+ return ak < bk
+ end
+ end
+
+ local revsorter = function(a,b)
+ return keysorter(b,a)
+ end
+
+ local function compresslist(source,specification)
+ if specification.sorttype == v_normal then
+ sort(source,keysorter)
+ elseif specification.sorttype == v_reverse then
+ sort(source,revsorter)
+ end
+ if specification and specification.compress == v_yes and specification.numeric then
+ local first, last, firstr, lastr
+ local target, noftarget, tags = { }, 0, { }
+ local oldvalue = nil
+ local function flushrange()
+ noftarget = noftarget + 1
+ if last > first + 1 then
+ target[noftarget] = {
+ first = firstr,
+ last = lastr,
+ tags = tags,
+ }
+ else
+ target[noftarget] = firstr
+ if last > first then
+ noftarget = noftarget + 1
+ target[noftarget] = lastr
+ end
+ end
+ tags = { }
+ end
+ for i=1,#source do
+ local entry = source[i]
+ local current = entry.sortkey -- so we need a sortkey !
+ if entry.suffix then
+ if not first then
+ first, last, firstr, lastr = current, current, entry, entry
+ else
+ flushrange()
+ first, last, firstr, lastr = current, current, entry, entry
+ end
+ else
+ if not first then
+ first, last, firstr, lastr = current, current, entry, entry
+ elseif current == last + 1 then
+ last, lastr = current, entry
+ else
+ flushrange()
+ first, last, firstr, lastr = current, current, entry, entry
+ end
+ end
+ tags[#tags+1] = entry.tag
+ end
+ if first and last then
+ flushrange()
+ end
+ return target
+ else
+ local target, noftarget = { }, 0
+ for i=1,#source do
+ local entry = source[i]
+ noftarget = noftarget + 1
+ target[noftarget] = {
+ first = entry,
+ tags = { entry.tag },
+ }
+ end
+ return target
+ end
+ end
+
+ -- local source = {
+ -- { tag = "one", internal = 1, value = "foo", page = 1 },
+ -- { tag = "two", internal = 2, value = "bar", page = 2 },
+ -- { tag = "three", internal = 3, value = "gnu", page = 3 },
+ -- }
+ --
+ -- local target = compresslist(source)
+
+ local numberonly = R("09")^1 / tonumber + P(1)^0
+ local f_missing = formatters["<%s>"]
+
+ -- maybe also sparse (e.g. pages)
+
+ -- a bit redundant access to datasets
+
+ local function processcite(presets,specification)
+ --
+ if specification then
+ setmetatableindex(specification,presets)
+ else
+ specification = presets
+ end
+ --
+ local dataset = specification.dataset
+ local reference = specification.reference
+ local internal = specification.internal
+ local setup = specification.variant
+ local compress = specification.compress
+ local sorttype = specification.sorttype
+ local getter = specification.getter
+ local setter = specification.setter
+ local compressor = specification.compressor
+ local method = specification.method
+ --
+ local reference = publications.parenttag(dataset,reference)
+ --
+ local found, todo, list = findallused(dataset,reference,internal,method == v_text or method == v_always) -- also when not in list
+ --
+-- inspect(found)
+-- inspect(todo)
+-- inspect(list)
+ if not found or #found == 0 then
+ report("no entry %a found in dataset %a",reference,dataset)
+ elseif not setup then
+ report("invalid reference for %a",reference)
+ else
+ if trace_cite then
+ report("processing reference %a",reference)
+ end
+ local source = { }
+ local luadata = datasets[dataset].luadata
+ for i=1,#found do
+ local entry = found[i]
+ local userdata = entry.userdata
+ local references = entry.references
+ local tag = userdata and userdata.btxref or entry.tag -- no need for userdata
+ if tag then
+ local ldata = luadata[tag]
+ local data = {
+ internal = references and references.internal,
+ language = ldata.language,
+ dataset = dataset,
+ tag = tag,
+ -- combis = entry.userdata.btxcom,
+ -- luadata = ldata,
+ }
+ setter(data,dataset,tag,entry)
+ if type(data) == "table" then
+ source[#source+1] = data
+ else
+ report("error in cite rendering %a",setup or "?")
+ end
+ end
+ end
+
+ local lefttext = specification.lefttext
+ local righttext = specification.righttext
+ local before = specification.before
+ local after = specification.after
+
+ if lefttext and lefttext ~= "" then lefttext = settings_to_array(lefttext) end
+ if righttext and righttext ~= "" then righttext = settings_to_array(righttext) end
+ if before and before ~= "" then before = settings_to_array(before) end
+ if after and after ~= "" then after = settings_to_array(after) end
+
+ local function flush(i,n,entry,last)
+ local tag = entry.tag
+ local currentcitation = markcite(dataset,tag)
+ --
+ ctx_btxstartcite()
+ ctx_btxsettag(tag)
+ ctx_btxsetcategory(entry.category or "unknown")
+ --
+ if lefttext then local text = lefttext [i] ; if text and text ~= "" then ctx_btxsetlefttext (text) end end
+ if righttext then local text = righttext[i] ; if text and text ~= "" then ctx_btxsetrighttext(text) end end
+ if before then local text = before [i] ; if text and text ~= "" then ctx_btxsetbefore (text) end end
+ if after then local text = after [i] ; if text and text ~= "" then ctx_btxsetafter (text) end end
+ --
+ if method ~= v_text then
+ ctx_btxsetbacklink(currentcitation)
+ local bl = listtocite[currentcitation]
+ if bl then
+ -- we refer to a coming list entry
+ ctx_btxsetinternal(bl.references.internal or "")
+ else
+ -- we refer to a previous list entry
+ ctx_btxsetinternal(entry.internal or "")
+ end
+ end
+ local language = entry.language
+ if language then
+ ctx_btxsetlanguage(language)
+ end
+ -- local combis = entry.combis
+ -- if combis then
+ -- ctx_btxsetcombis(combis)
+ -- end
+ if not getter(entry,last,nil,specification) then
+ ctx_btxsetfirst("") -- (f_missing(tag))
+ end
+ ctx_btxsetconcat(concatstate(i,n))
+ if trace_detail then
+ report("expanding cite setup %a",setup)
+ end
+ ctx_btxcitesetup(setup)
+ ctx_btxstopcite()
+ end
+ if sorttype == v_normal or sorttype == v_reverse then
+ local target = (compressor or compresslist)(source,specification)
+ local nofcollected = #target
+ if nofcollected == 0 then
+ local nofcollected = #source
+ if nofcollected == 0 then
+ unknowncite(reference)
+ else
+ for i=1,nofcollected do
+ flush(i,nofcollected,source[i])
+ end
+ end
+ else
+ for i=1,nofcollected do
+ local entry = target[i]
+ local first = entry.first
+ if first then
+ flush(i,nofcollected,first,entry.last)
+ else
+ flush(i,nofcollected,entry)
+ end
+ end
+ end
+ else
+ local nofcollected = #source
+ if nofcollected == 0 then
+ unknowncite(reference)
+ else
+ for i=1,nofcollected do
+ flush(i,nofcollected,source[i])
+ end
+ end
+ end
+ end
+ if trialtypesetting() then
+ marked_todo = false
+ elseif method ~= v_text then
+ marked_todo = todo
+ marked_dataset = dataset
+ marked_list = list
+ marked_method = method
+ btxflushmarked() -- here (could also be done in caller)
+ else
+ marked_todo = false
+ end
+ end
+
+ --
+
+ local function simplegetter(first,last,field,specification)
+ local value = first[field]
+ if value then
+ ctx_btxsetfirst(value)
+ if last then
+ ctx_btxsetsecond(last[field])
+ end
+ return true
+ end
+ end
+
+ local setters = setmetatableindex({},function(t,k)
+ local v = function(data,dataset,tag,entry)
+ local value = getcasted(dataset,tag,k)
+ data.value = value -- not really needed
+ data[k] = value
+ data.sortkey = value
+ data.sortfld = k
+ end
+ t[k] = v
+ return v
+ end)
+
+ local getters = setmetatableindex({},function(t,k)
+ local v = function(first,last,_,specification)
+ return simplegetter(first,last,k,specification) -- maybe _ or k
+ end
+ t[k] = v
+ return v
+ end)
+
+ setmetatableindex(citevariants,function(t,k)
+ local p = defaultvariant or "default"
+ local v = rawget(t,p)
+ report_cite("variant %a falls back on %a setter and getter with setup %a",k,p,k)
+ t[k] = v
+ return v
+ end)
+
+ function citevariants.default(presets)
+ local variant = presets.variant
+ processcite(presets,{
+ setup = variant,
+ setter = setters[variant],
+ getter = getters[variant],
+ })
+ end
+
+ -- category
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ data.category = getfield(dataset,tag,"category")
+ end
+
+ local function getter(first,last,_,specification)
+ return simplegetter(first,last,"category",specification)
+ end
+
+ function citevariants.category(presets)
+ processcite(presets,{
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+
+ -- entry (we could provide a generic one)
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ -- nothing
+ end
+
+ local function getter(first,last,_,specification) -- last not used
+ ctx_btxsetfirst(first.tag)
+ end
+
+ function citevariants.entry(presets)
+ processcite(presets,{
+ compress = false,
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- short
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ local short = getdetail(dataset,tag,"shorthash")
+ local suffix = getdetail(dataset,tag,"shortsuffix")
+ data.short = short
+ data.sortkey = short
+ data.suffix = suffix
+ end
+
+ local function getter(first,last,_,specification) -- last not used
+ local short = first.short
+ if short then
+ local suffix = first.suffix
+ ctx_btxsetfirst(short)
+ if suffix then
+ ctx_btxsetsuffix(suffix) -- watch out: third
+ end
+ return true
+ end
+ end
+
+ function citevariants.short(presets)
+ processcite(presets,{
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- pages (no compress)
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ data.pages = getcasted(dataset,tag,"pages")
+ end
+
+ local function getter(first,last,_,specification)
+ local pages = first.pages
+ if pages then
+ if type(pages) == "table" then
+ ctx_btxsetfirst(pages[1])
+ ctx_btxsetsecond(pages[2])
+ else
+ ctx_btxsetfirst(pages)
+ end
+ return true
+ end
+ end
+
+ function citevariants.page(presets)
+ processcite(presets,{
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- num
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ local entries = entry.entries
+ local text = entries and entries.text or "?"
+ data.num = text
+ data.sortkey = tonumber(text) or text
+ end
+
+ local function getter(first,last,tag,specification)
+ return simplegetter(first,last,"num",specification)
+ end
+
+ function citevariants.num(presets)
+ processcite(presets,{
+ numeric = true,
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ citevariants.textnum = citevariants.num -- should not be needed
+
+ end
+
+ -- year
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ local year = getfield (dataset,tag,"year")
+ local suffix = getdetail(dataset,tag,"authorsuffix")
+ data.year = year
+ data.suffix = suffix
+ data.sortkey = tonumber(year) or 9999
+ end
+
+ local function getter(first,last,_,specification)
+ return simplegetter(first,last,"year",specification)
+ end
+
+ function citevariants.year(presets)
+ processcite(presets,{
+ numeric = true,
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- index
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ local index = getfield(dataset,tag,"index")
+ data.index = index
+ data.sortkey = index
+ end
+
+ local function getter(first,last,_,specification)
+ return simplegetter(first,last,"index",specification)
+ end
+
+ function citevariants.index(presets)
+ processcite(presets,{
+ setter = setter,
+ getter = getter,
+ numeric = true,
+ })
+ end
+
+ end
+
+ -- tag
+
+ do
+
+ local function setter(data,dataset,tag,entry)
+ data.tag = tag
+ data.sortkey = tag
+ end
+
+ local function getter(first,last,_,specification)
+ return simplegetter(first,last,"tag",specification)
+ end
+
+ function citevariants.tag(presets)
+ return processcite(presets,{
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- keyword
+
+ do
+
+ local function listof(list)
+ local size = type(list) == "table" and #list or 0
+ if size > 0 then
+ return function()
+ for i=1,size do
+ ctx_btxsetfirst(list[i])
+ ctx_btxsetconcat(concatstate(i,size))
+ ctx_btxcitesetup("listelement")
+ end
+ return true
+ end
+ else
+ return "?" -- unknown
+ end
+ end
+
+ local function setter(data,dataset,tag,entry)
+ data.keywords = getcasted(dataset,tag,"keywords")
+ end
+
+ local function getter(first,last,_,specification)
+ context(listof(first.keywords))
+ end
+
+ function citevariants.keywords(presets)
+ return processcite(presets,{
+ variant = "keywords",
+ setter = setter,
+ getter = getter,
+ })
+ end
+
+ end
+
+ -- authors
+
+ do
+
+ -- is this good enough?
+
+ local keysorter = function(a,b)
+ local ak = a.authorhash
+ local bk = b.authorhash
+ if ak == bk then
+ local as = a.authorsuffix -- numeric
+ local bs = b.authorsuffix -- numeric
+ if as and bs then
+ return (as or 0) < (bs or 0)
+ else
+ return false
+ end
+ elseif ak and bk then
+ return ak < bk
+ else
+ return false
+ end
+ end
+
+ local revsorter = function(a,b)
+ return keysorter(b,a)
+ end
+
+ local currentbtxciteauthor = function()
+ context.currentbtxciteauthor()
+ return true -- needed?
+ end
+
+ local function authorcompressor(found,specification)
+ -- HERE
+ if specification.sorttype == v_normal then
+ sort(found,keysorter)
+ elseif specification.sorttype == v_reverse then
+ sort(found,revsorter)
+ end
+ local result = { }
+ local entries = { }
+ for i=1,#found do
+ local entry = found[i]
+ local author = entry.authorhash
+ if author then
+ local aentries = entries[author]
+ if aentries then
+ aentries[#aentries+1] = entry
+ else
+ entries[author] = { entry }
+ end
+ end
+ end
+ -- beware: we use tables as hash so we get a cycle when inspecting (unless we start
+ -- hashing with strings)
+ for i=1,#found do
+ local entry = found[i]
+ local author = entry.authorhash
+ if author then
+ local aentries = entries[author]
+ if not aentries then
+ result[#result+1] = entry
+ elseif aentries == true then
+ -- already done
+ else
+ result[#result+1] = entry
+ entry.entries = aentries
+ entries[author] = true
+ end
+ end
+ end
+ return result
+ end
+
+ local function authorconcat(target,key,setup)
+ ctx_btxstartsubcite(setup)
+ local nofcollected = #target
+ if nofcollected == 0 then
+ unknowncite(tag)
+ else
+ for i=1,nofcollected do
+ local entry = target[i]
+ local first = entry.first
+ local tag = entry.tag
+ local currentcitation = markcite(entry.dataset,tag)
+ ctx_btxstartciteauthor()
+ ctx_btxsettag(tag)
+ ctx_btxsetbacklink(currentcitation)
+ local bl = listtocite[currentcitation]
+ ctx_btxsetinternal(bl and bl.references.internal or "")
+ if first then
+ ctx_btxsetfirst(first[key] or "") -- f_missing(first.tag))
+ local suffix = entry.suffix
+ local last = entry.last
+ local value = last and last[key]
+ if value then
+ ctx_btxsetsecond(value)
+ end
+ if suffix then
+ ctx_btxsetsuffix(suffix)
+ end
+ else
+ local suffix = entry.suffix
+ local value = entry[key] or "" -- f_missing(tag)
+ ctx_btxsetfirst(value)
+ if suffix then
+ ctx_btxsetsuffix(suffix)
+ end
+ end
+ ctx_btxsetconcat(concatstate(i,nofcollected))
+ if trace_detail then
+ report("expanding %a cite setup %a","multiple author",setup)
+ end
+ ctx_btxsubcitesetup(setup)
+ ctx_btxstopciteauthor()
+ end
+ end
+ ctx_btxstopsubcite()
+ end
+
+ local function authorsingle(entry,key,setup)
+ ctx_btxstartsubcite(setup)
+ ctx_btxstartciteauthor()
+ local tag = entry.tag
+ ctx_btxsettag(tag)
+ -- local currentcitation = markcite(entry.dataset,tag)
+ -- ctx_btxsetbacklink(currentcitation)
+ -- local bl = listtocite[currentcitation]
+ -- ctx_btxsetinternal(bl and bl.references.internal or "")
+ ctx_btxsetfirst(entry[key] or "") -- f_missing(tag)
+ if suffix then
+ ctx_btxsetsuffix(entry.suffix)
+ end
+ if trace_detail then
+ report("expanding %a cite setup %a","single author",setup)
+ end
+ ctx_btxcitesetup(setup)
+ ctx_btxstopciteauthor()
+ ctx_btxstopsubcite()
+ end
+
+ local partialinteractive = false
+
+ local function authorgetter(first,last,key,specification) -- only first
+ -- ctx_btxsetfirst(first.author) -- unformatted
+ -- ctx_btxsetfirst(currentbtxciteauthor) -- formatter (much slower)
+ if first.type == "author" then
+ ctx_btxsetfirst(currentbtxciteauthor) -- formatter (much slower)
+ else
+ ctx_btxsetfirst(first.author) -- unformatted
+ end
+ local entries = first.entries
+ -- alternatively we can use a concat with one ... so that we can only make the
+ -- year interactive, as with the concat
+ if partialinteractive and not entries then
+ entries = { first }
+ end
+ if entries then
+ -- happens with year
+ local c = compresslist(entries,specification)
+ local f = function() authorconcat(c,key,specification.setup or "author") return true end -- indeed return true?
+ ctx_btxsetcount(#c)
+ ctx_btxsetsecond(f)
+ elseif first then
+ -- happens with num
+ local f = function() authorsingle(first,key,specification.setup or "author") return true end -- indeed return true?
+ ctx_btxsetcount(0)
+ ctx_btxsetsecond(f)
+ end
+ return true
+ end
+
+ -- author
+
+ local function setter(data,dataset,tag,entry)
+ data.author, data.field, data.type = getcasted(dataset,tag,"author")
+ data.sortkey = text and lpegmatch(numberonly,text)
+ data.authorhash = getdetail(dataset,tag,"authorhash") -- todo let getcasted return
+ end
+
+ local function getter(first,last,_,specification)
+ if first.type == "author" then
+ ctx_btxsetfirst(currentbtxciteauthor) -- formatter (much slower)
+ else
+ ctx_btxsetfirst(first.author) -- unformatted
+ end
+ return true
+ end
+
+ function citevariants.author(presets)
+ processcite(presets,{
+ variant = "author",
+ setup = "author",
+ setter = setter,
+ getter = getter,
+ compressor = authorcompressor,
+ })
+ end
+
+ -- authornum
+
+ local function setter(data,dataset,tag,entry)
+ local entries = entry.entries
+ local text = entries and entries.text or "?"
+ data.author, data.field, data.type = getcasted(dataset,tag,"author")
+ data.authorhash = getdetail(dataset,tag,"authorhash") -- todo let getcasted return
+ data.num = text
+ data.sortkey = text and lpegmatch(numberonly,text)
+ end
+
+ local function getter(first,last,_,specification)
+ authorgetter(first,last,"num",specification)
+ return true
+ end
+
+ function citevariants.authornum(presets)
+ processcite(presets,{
+ variant = "authornum",
+ setup = "author:num",
+ numeric = true,
+ setter = setter,
+ getter = getter,
+ compressor = authorcompressor,
+ })
+ end
+
+ -- authoryear | authoryears
+
+ local function setter(data,dataset,tag,entry)
+ data.author, data.field, data.type = getcasted(dataset,tag,"author")
+ data.authorhash = getdetail(dataset,tag,"authorhash") -- todo let getcasted return
+ local year = getfield (dataset,tag,"year")
+ local suffix = getdetail(dataset,tag,"authorsuffix")
+ data.year = year
+ data.suffix = suffix
+ data.sortkey = tonumber(year) or 9999
+ end
+
+ local function getter(first,last,_,specification)
+ authorgetter(first,last,"year",specification)
+ return true
+ end
+
+ function citevariants.authoryear(presets)
+ processcite(presets,{
+ variant = "authoryear",
+ setup = "author:year",
+ numeric = true,
+ setter = setter,
+ getter = getter,
+ compressor = authorcompressor,
+ })
+ end
+
+ local function getter(first,last,_,specification)
+ authorgetter(first,last,"year",specification)
+ return true
+ end
+
+ function citevariants.authoryears(presets)
+ processcite(presets,{
+ variant = "authoryears",
+ setup = "author:years",
+ numeric = true,
+ setter = setter,
+ getter = getter,
+ compressor = authorcompressor,
+ })
+ end
+
+ end
+
+end
+
+-- List variants
+
+do
+
+ local listvariants = { }
+ publications.listvariants = listvariants
+
+ local function btxlistvariant(dataset,block,tag,variant,listindex)
+ local action = listvariants[variant] or listvariants.default
+ if action then
+ action(dataset,block,tag,variant,tonumber(listindex) or 0)
+ end
+ end
+
+ implement {
+ name = "btxlistvariant",
+ actions = btxlistvariant,
+ arguments = { "string", "string", "string", "string", "string" } -- not integer here
+ }
+
+ function listvariants.default(dataset,block,tag,variant)
+ ctx_btxsetfirst("?")
+ if trace_detail then
+ report("expanding %a list setup %a","default",variant)
+ end
+ ctx_btxnumberingsetup("default")
+ end
+
+ function listvariants.num(dataset,block,tag,variant,listindex)
+ ctx_btxsetfirst(listindex)
+ if trace_detail then
+ report("expanding %a list setup %a","num",variant)
+ end
+ ctx_btxnumberingsetup(variant or "num")
+ end
+
+ -- listvariants[v_yes] = listvariants.num
+
+ function listvariants.index(dataset,block,tag,variant,listindex)
+ local index = getdetail(dataset,tag,"index")
+ ctx_btxsetfirst(index or "?")
+ if trace_detail then
+ report("expanding %a list setup %a","index",variant)
+ end
+ ctx_btxnumberingsetup(variant or "index")
+ end
+
+ function listvariants.tag(dataset,block,tag,variant,listindex)
+ ctx_btxsetfirst(tag)
+ if trace_detail then
+ report("expanding %a list setup %a","tag",variant)
+ end
+ ctx_btxnumberingsetup(variant or "tag")
+ end
+
+ function listvariants.short(dataset,block,tag,variant,listindex)
+ local short = getdetail(dataset,tag,"shorthash")
+ local suffix = getdetail(dataset,tag,"shortsuffix")
+ if short then
+ ctx_btxsetfirst(short)
+ end
+ if suffix then
+ ctx_btxsetsuffix(suffix)
+ end
+ if trace_detail then
+ report("expanding %a list setup %a","short",variant)
+ end
+ ctx_btxnumberingsetup(variant or "short")
+ end
+
+ function listvariants.page(dataset,block,tag,variant,listindex)
+ local rendering = renderings[dataset]
+ local specification = rendering.list[listindex]
+ for i=3,#specification do
+ local backlink = tonumber(specification[i])
+ if backlink then
+ local citation = citetolist[backlink]
+ if citation then
+ local references = citation.references
+ if references then
+ local internal = references.internal
+ local realpage = references.realpage
+ if internal and realpage then
+ ctx_btxsetconcat(i-2)
+ ctx_btxsetfirst(realpage)
+ ctx_btxsetsecond(backlink)
+ if trace_detail then
+ report("expanding %a list setup %a","page",variant)
+ end
+ ctx_btxlistsetup(variant)
+ end
+ end
+ end
+ end
+ end
+ end
+
+end
+
+-- a helper
+
+do
+
+ -- local context = context
+ -- local lpegmatch = lpeg.match
+ local splitter = lpeg.tsplitat(":")
+
+ interfaces.implement {
+ name = "checkinterfacechain",
+ arguments = { "string", "string" },
+ actions = function(str,command)
+ local chain = lpegmatch(splitter,str)
+ if #chain > 0 then
+ local command = context[command]
+ local parent = ""
+ local child = chain[1]
+ command(child,parent)
+ for i=2,#chain do
+ parent = child
+ child = child .. ":" .. chain[i]
+ command(child,parent)
+ end
+ end
+ end
+ }
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv
new file mode 100644
index 00000000000..cf51b831a81
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv
@@ -0,0 +1,1855 @@
+%D \module
+%D [ file=publ-ini,
+%D version=2013.05.12,
+%D title=\CONTEXT\ Publication 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.
+
+% TODO: s! vs v! for default and neutral key/values
+% todo: too many refs in list
+
+% todo: no need for all these %'s
+
+% todo: tagging
+% todo: we cannot use 'default' as this wipes metadata names (maybe no longer do that)
+% todo: \v!cite => \s!cite
+% todo: interface with (ml)bibtex (export -> call -> import)
+% todo: check if 'all' etc are ok ... either use list or use other criterium
+% todo: \the\everysetupbtxciteplacement probably too often
+
+% \definecolor[btx:field] [darkred]
+% \definecolor[btx:crossref][darkblue]
+% \definecolor[btx:key] [darkgreen]
+% \definecolor[btx:todo] [darkyellow]
+
+%D We operate on several axis:
+%D
+%D \startitemize[packed]
+%D \startitem we can have several databases (or combinations) \stopitem
+%D \startitem we can add entries to them if needed (coded in tex) \stopitem
+%D \startitem we can have several lists each using one of the databases \stopitem
+%D \startitem we can render each list or citation independently \stopitem
+%D \stopitemize
+%D
+%D We assume that the rendering of a list entry is consistent in a document,
+%D although one can redefine properties if needed. Adding more granularity would
+%D complicate the user interface beyond comprehension.
+
+\writestatus{loading}{ConTeXt Publication Support / Initialization}
+
+\registerctxluafile{publ-dat}{1.001}
+\registerctxluafile{publ-ini}{1.001}
+\registerctxluafile{publ-sor}{1.001}
+\registerctxluafile{publ-aut}{1.001}
+\registerctxluafile{publ-usr}{1.001}
+\registerctxluafile{publ-oth}{1.001} % this could become an option
+\registerctxluafile{publ-fnd}{1.001} % new method (for the moment only local)
+\registerctxluafile{publ-jrn}{1.001}
+\registerctxluafile{publ-reg}{1.001}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+\def\s!btx {btx}
+
+\def\v!btxcite {btxcite}
+\def\v!btxlist {btxlist}
+\def\v!btxrendering {btxrendering}
+
+\def\s!btxset {btxset}
+\def\s!btxref {btxref}
+\def\s!btxint {btxint}
+\def\s!btxbck {btxbck}
+\def\s!btxltx {btxltx}
+\def\s!btxrtx {btxrtx}
+\def\s!btxatx {btxatx}
+\def\s!btxbtx {btxbtx}
+\def\s!btxspc {btxspc}
+\def\s!btxlst {btxlst}
+\def\s!btxcom {btxcom}
+
+\definelabelclass[btxlabel][2]
+
+% It is not that trivial to come up with a proper organization of setup
+% and control commands for publications. This is because we have complex
+% inline as well as extensive list rendering. The rules are partially
+% driven by somewhat archaic bibtex specifications and evolving journal
+% (or field) specific demands. The logic in the standards is often so
+% complex that it looks like manual rendering is assumed. But, we want to
+% automate the process as much as possible.
+%
+% Another complication is that in manuals we want to demonstrate different
+% properties of the implementation and therefore we need a way to handle
+% independent standards, databases, etc. This has resulted in the following
+% organization:
+%
+% - general setup (rather minimal)
+% - list setup (rendering)
+% - cite setup
+% - dataset setup
+%
+% The rendering is mostly driven by setups. In there we can call for fields
+% in the database but also for virtual fields or combinations.
+
+% The main rendering style (standard driven).
+
+%D We assume that a specification is global or used grouped. It doesn't make much sense
+%D to split between cite and list here as it only complicates matters (timing) and is
+%D not clear either.
+
+\let\currentbtxspecification\empty
+
+\unexpanded\def\startbtxrenderingdefinitions[#1]%
+ {\unprotect
+ \pushmacro\currentbtxspecification
+ \edef\currentbtxspecification{#1}}
+
+\unexpanded\def\stopbtxrenderingdefinitions
+ {\popmacro\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
+ \edef\currentbtxspecification{#1}%
+ \edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}%
+ \ifx\currentbtxspecificationfallback\currentbtxspecification
+ \let\currentbtxspecificationfallback\empty
+ \fi
+ \clf_btxsetspecification{\currentbtxspecification}}
+
+\unexpanded\def\publ_specification_pop
+ {\popmacro\currentbtxspecificationfallback
+ \popmacro\currentbtxspecification
+ \clf_btxsetspecification{\currentbtxspecification}}
+
+\unexpanded\def\publ_specification_set#1% beware: is global
+ {\edef\currentbtxspecification{#1}%
+ \edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}%
+ \ifx\currentbtxspecificationfallback\currentbtxspecification
+ \let\currentbtxspecificationfallback\empty
+ \fi
+ % has to be done explicitly: \loadbtxdefinitionfile[\currentbtxspecification]%
+ \ifx\currentbtxspecification\empty
+ % we set default at the end
+ \else
+ \clf_btxsetspecification{\currentbtxspecification}%
+ \fi}% todo: ,true == also load
+
+\installcorenamespace {btx}
+
+\installswitchcommandhandler \??btx {btx} \??btx
+
+% because we have lots of setups we provide a checker for sloppy users
+
+\unexpanded\def\btx_check_chain#1#2#3%
+ {\doifelsesomething{#3}
+ {\writestatus{btx #1}{defining\space"#2"\space as\space descendant\space of\space"#3"}% we're in definition regime (no space)
+ \definebtx[#2][#3]}
+ {\writestatus{btx #1}{defining\space"#2"}%
+ \definebtx[#2]}}
+
+% \unexpanded\def\btxcheckdefine#1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain{define}{#1}{#2}}}
+% \unexpanded\def\btxchecksetup #1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain {setup}{#1}{#2}}}
+
+\unexpanded\def\btxcheckdefine#1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain{define}{#1}}} % {#2}
+\unexpanded\def\btxchecksetup #1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain {setup}{#1}}} % {#2}
+
+% for the moment experimental:
+
+\unexpanded\def\btxenableautodefine
+ {\prependtoks
+ \clf_checkinterfacechain{\currentbtx}{btxcheckdefine}%
+ \to \everydefinebtx
+ \prependtoks
+ \ifnum\btxsetupmode=\doingrootsetupnamed
+ \clf_checkinterfacechain{\currentbtx}{btxchecksetup}%
+ \fi
+ \to \everysetupbtx
+ \let\btxenableautodefine\relax}
+
+\appendtoks
+ \ifnum\btxsetupmode=\doingrootsetuproot
+ \publ_specification_set{\btxparameter\c!specification}%
+ \else\ifnum\btxsetupmode=\doingrootsetupnamed
+ \doifelsecommandhandler\??btx\currentbtx
+ {\publ_specification_set{\btxparameter\c!specification}}%
+ {}% maybe a warning
+ \fi\fi
+\to \everysetupbtx
+
+\appendtoks
+ \ifnum\btxsetupmode=\doingrootsetuproot
+ \edef\currentbtxdataset{\clf_btxsetdataset{\btxparameter\c!dataset}{\currentbtxdataset}}%
+ \fi
+\to \everysetupbtx
+
+\appendtoks
+ \publ_specification_set{\btxparameter\c!specification}%
+\to \everyjob
+
+\unexpanded\def\startusingbtxspecification[#1]%
+ {\publ_specification_push{#1}}
+
+\let\stopusingbtxspecification\publ_specification_pop
+
+% \setupbtxlist[alternative=paragraph,width=auto,distance=\emwidth]
+% \setupbtxlist[alternative=paragraph,width=auto,distance=\emwidth,margin=2em] % useless
+% \setupbtxlist[alternative=paragraph,width=fit,distance=\emwidth]
+% \setupbtxlist[alternative=paragraph,width=fit,distance=\emwidth,margin=2em]
+
+% here starts the bib stuff
+
+\installcorenamespace {btxdataset}
+\installcorenamespace {btxrendering}
+\installcorenamespace {btxregister}
+\installcorenamespace {btxcommand}
+\installcorenamespace {btxrenderingdefinition}
+
+\installcommandhandler \??btxdataset {btxdataset} \??btxdataset
+\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
+ \currentbtxspecification:%
+ \else\ifx\currentbtxspecificationfallback\empty
+ \else\ifcsname\??btx\currentbtxspecificationfallback:#1:#2:\s!parent\endcsname
+ \currentbtxspecificationfallback:%
+ \fi\fi\fi#1:#2}}
+
+\unexpanded\def\setbtxparametersetroot#1%
+ {\edef\currentbtx
+ {\ifcsname\??btx\currentbtxspecification:#1:\s!parent\endcsname
+ \currentbtxspecification:#1%
+ \else\ifx\currentbtxspecificationfallback\empty
+ \else\ifcsname\??btx\currentbtxspecificationfallback:#1:\s!parent\endcsname
+ \currentbtxspecificationfallback:#1%
+ \fi\fi\fi}}
+
+\unexpanded\def\setbtxrendering
+ {\edef\currentbtxrendering
+ {\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname
+ \currentbtxspecification
+ \else\ifx\currentbtxspecificationfallback\empty
+ \else\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname
+ \currentbtxspecificationfallback
+ \fi\fi\fi}}
+
+\unexpanded\def\setbtxlist % maybe simplify this one, always list=rendering?
+ {\edef\currentbtxlist
+ {\ifcsname\??btx\currentbtxrendering:\s!parent\endcsname
+ \currentbtxrendering
+ \else\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname
+ \currentbtxspecification
+ \else\ifx\currentbtxspecificationfallback\empty
+ \else\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname
+ \currentbtxspecificationfallback
+ \fi\fi\fi\fi}%
+ \edef\currentlist{\s!btx:\currentbtxlist}}
+
+\unexpanded\def\usebtxdataset
+ {\begingroup
+ \dotripleempty\publ_use_dataset}
+
+\def\publ_use_dataset[#1][#2][#3]%
+ {\getdummyparameters[\c!specification=\currentbtxspecification,#3]%
+ \ifsecondargument
+ \clf_btxusedataset
+ specification {\dummyparameter\c!specification}%
+ dataset {#1}%
+ filename {#2}%
+ \relax
+ \else\iffirstargument
+ \clf_btxusedataset
+ specification {\dummyparameter\c!specification}%
+ dataset {\v!default}%
+ filename {#1}%
+ \relax
+ \fi\fi
+ \endgroup}
+
+\definebtxdataset
+ [\v!default]
+% [\c!language=] % nothing set so use current
+
+% \usebtxdataset
+% [default]
+% [mybibs.bib]
+
+\let\startpublication\relax
+\let\stoppublication \relax
+
+\unexpanded\def\startpublication
+ {\dodoubleempty\publ_set_publication}
+
+\def\publ_set_publication[#1][#2]%
+ {\begingroup
+ \catcode\commentasciicode\othercatcode
+ \ifsecondargument
+ \expandafter\publ_set_publication_indeed
+ \else\iffirstargument
+ \doubleexpandafter\publ_set_publication_checked
+ \else
+ \doubleexpandafter\publ_set_publication_default
+ \fi\fi{#1}{#2}}
+
+\def\publ_set_publication_default#1#2%
+ {\publ_set_publication_indeed\v!default{#1}}
+
+\def\publ_set_publication_checked#1#2%
+ {\doifelseassignment{#1}
+ {\publ_set_publication_indeed\v!default{#1}}
+ {\publ_set_publication_indeed{#1}{}}}
+
+\def\publ_set_publication_indeed#1#2#3\stoppublication
+ {\clf_btxaddentry{#1}{#2}{\detokenize{#3}}%
+ \endgroup
+ \ignorespaces}
+
+% commands
+
+\unexpanded\def\btxcommand#1%
+ {\ifcsname\??btxcommand#1\endcsname
+ \expandafter\publ_command_yes
+ \else
+ \expandafter\publ_command_nop
+ \fi{#1}}
+
+\let\btxcmd\btxcommand
+
+\def\publ_command_yes#1%
+ {\csname\??btxcommand#1\endcsname}
+
+\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
+ \else\ifcsname\utfupper{#1}\endcsname
+ \showmessage\m!publications{10}{#1}{\utfupper{#1}}%
+ \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname
+ \else
+ \showmessage\m!publications{11}{#1}%
+ \setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}%
+ \fi\fi
+ \publ_command_yes{#1}}
+
+\unexpanded\def\definebtxcommand#1% {body} #1..#n{body}
+ {\setuvalue{\??btxcommand\csstring#1}}%
+
+% tracing
+
+\installtextracker
+ {publications.crosslinks}
+ {\let\btx_trace_list_cross\strc_references_tracer}
+ {\let\btx_trace_list_cross\gobbletwoarguments}
+
+\let\btx_trace_list_cross\gobbletwoarguments
+
+% access
+
+\let\currentbtxtag \empty
+\let\currentbtxdataset\v!default
+
+\unexpanded\def\setbtxentry[#1]% or maybe btxsetentry
+ {\edef\currentbtxtag{\clf_btxsetentry{\currentbtxdataset}{#1}}}
+
+% \let\btxsetdataset\setbtxdataset
+% \let\btxsetentry \setbtxentry
+
+% todo: no need for the currents as we can keep them at the lua end so we will have
+%
+% \btxfield : current
+% \btxspecificfield : dataset,tag,key
+
+\def\btxfield #1{\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxdetail #1{\clf_btxdetail {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxflush #1{\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxdirect #1{\clf_btxdirect {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxfieldname #1{\clf_btxfieldname {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxfieldtype #1{\clf_btxfieldtype {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxfoundname #1{\clf_btxfoundname {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxfoundtype #1{\clf_btxfoundtype {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxauthorfield#1{\clf_btxauthorfield \currentbtxauthorindex{#1}}
+\def\btxdoifelse #1{\clf_btxdoifelse {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxdoif #1{\clf_btxdoif {\currentbtxdataset}{\currentbtxtag}{#1}}
+\def\btxdoifnot #1{\clf_btxdoifnot {\currentbtxdataset}{\currentbtxtag}{#1}}
+
+\let\btxsetup\fastsetup
+
+%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.
+
+%D Rendering.
+
+\unexpanded\def\btxspace {\removeunwantedspaces\space}
+\unexpanded\def\btxnobreakspace {\removeunwantedspaces\nobreakspace} % these two are
+\unexpanded\def\btxnbsp {\removeunwantedspaces\nbsp} % the same anyway
+\unexpanded\def\btxperiod {\removeunwantedspaces.\space}
+\unexpanded\def\btxcomma {\removeunwantedspaces,\space}
+\unexpanded\def\btxcommabreak {\removeunwantedspaces,\hskip\zeropoint plus .5\emwidth\relax}
+\unexpanded\def\btxcolon {\removeunwantedspaces:\space}
+\unexpanded\def\btxsemicolon {\removeunwantedspaces;\space}
+\unexpanded\def\btxlparent {\removeunwantedspaces\space(} % obsolete
+\unexpanded\def\btxrparent {\removeunwantedspaces)\space} % obsolete
+\unexpanded\def\btxleftparenthesis {\removeunwantedspaces\space(}
+\unexpanded\def\btxrightparenthesis {\removeunwantedspaces)\space}
+\unexpanded\def\btxrightparenthesisperiod{\removeunwantedspaces).\space}
+\unexpanded\def\btxrightparenthesiscomma {\removeunwantedspaces),\space}
+\unexpanded\def\btxleftbracket {\removeunwantedspaces\space[}
+\unexpanded\def\btxrightbracket {\removeunwantedspaces]\space}
+\unexpanded\def\btxrightbracketperiod {\removeunwantedspaces].\space}
+\unexpanded\def\btxrightbracketcomma {\removeunwantedspaces],\space}
+
+%D Variables:
+
+\let\currentbtxbacklink \empty \unexpanded\def\btxsetbacklink {\def\currentbtxbacklink}
+\let\currentbtxbacktrace \empty \unexpanded\def\btxsetbacktrace {\def\currentbtxbacktrace}
+\let\currentbtxcategory \empty \unexpanded\def\btxsetcategory {\def\currentbtxcategory}
+\let\currentbtxcombis \empty \unexpanded\def\btxsetcombis {\def\currentbtxcombis}
+\let\currentbtxdataset \empty \unexpanded\def\btxsetdataset {\def\currentbtxdataset}
+\let\currentbtxfirst \empty \unexpanded\def\btxsetfirst {\def\currentbtxfirst}
+\let\currentbtxsecond \empty \unexpanded\def\btxsetsecond {\def\currentbtxsecond}
+%let\currentbtxthird \empty \unexpanded\def\btxsetthird {\def\currentbtxthird}
+\let\currentbtxsuffix \empty \unexpanded\def\btxsetsuffix {\def\currentbtxsuffix}
+\let\currentbtxinternal \empty \unexpanded\def\btxsetinternal {\def\currentbtxinternal}
+\let\currentbtxlefttext \empty \unexpanded\def\btxsetlefttext {\def\currentbtxlefttext}
+\let\currentbtxrighttext \empty \unexpanded\def\btxsetrighttext {\def\currentbtxrighttext}
+\let\currentbtxbefore \empty \unexpanded\def\btxsetbefore {\def\currentbtxbefore}
+\let\currentbtxafter \empty \unexpanded\def\btxsetafter {\def\currentbtxafter}
+\let\currentbtxlanguage \empty \unexpanded\def\btxsetlanguage {\def\currentbtxlanguage}
+\let\currentbtxtag \empty \unexpanded\def\btxsettag {\def\currentbtxtag}
+\let\currentbtxnumber \empty \unexpanded\def\btxsetnumber {\def\currentbtxnumber}
+\let\currentbtxauthorvariant\v!normal \unexpanded\def\btxsetauthorvariant{\def\currentbtxauthorvariant}
+
+\let\currentbtxfirstnames \empty \unexpanded\def\btxsetfirstnames{\let\currentbtxfirstnames\currentbtxfirstnames_indeed}
+\let\currentbtxinitials \empty \unexpanded\def\btxsetinitials {\let\currentbtxinitials \currentbtxinitials_indeed }
+\let\currentbtxjuniors \empty \unexpanded\def\btxsetjuniors {\let\currentbtxjuniors \currentbtxjuniors_indeed }
+\let\currentbtxsurnames \empty \unexpanded\def\btxsetsurnames {\let\currentbtxsurnames \currentbtxsurnames_indeed }
+\let\currentbtxvons \empty \unexpanded\def\btxsetvons {\let\currentbtxvons \currentbtxvons_indeed }
+
+\newconstant\currentbtxoverflow \unexpanded\def\btxsetoverflow #1{\currentbtxoverflow #1\relax}
+\newconstant\currentbtxconcat \unexpanded\def\btxsetconcat #1{\currentbtxconcat #1\relax}
+\newconstant\currentbtxcount \unexpanded\def\btxsetcount #1{\currentbtxcount #1\relax}
+\newconstant\currentbtxauthorindex %unexpanded\def\btxsetauthorindex#1{\currentbtxauthorindex#1\relax} % passed directly
+\newconstant\currentbtxauthorcount %unexpanded\def\btxsetauthorcount#1{\currentbtxauthorcount#1\relax} % passed directly
+\newconstant\currentbtxauthorstate \unexpanded\def\btxsetauthorstate#1{\currentbtxauthorstate#1\relax}
+
+\unexpanded\def\currentbtxfirstnames_indeed{\clf_btxcurrentfirstnames\numexpr\currentbtxauthorindex\relax}
+\unexpanded\def\currentbtxinitials_indeed {\clf_btxcurrentinitials \numexpr\currentbtxauthorindex\relax}
+\unexpanded\def\currentbtxjuniors_indeed {\clf_btxcurrentjuniors \numexpr\currentbtxauthorindex\relax}
+\unexpanded\def\currentbtxsurnames_indeed {\clf_btxcurrentsurnames \numexpr\currentbtxauthorindex\relax}
+\unexpanded\def\currentbtxvons_indeed {\clf_btxcurrentvons \numexpr\currentbtxauthorindex\relax}
+
+\let\currentbtxfirstpage \empty \unexpanded\def\btxsetfirstpage #1{\def\currentbtxfirstpage{\btx_page_number{#1}}}
+\let\currentbtxlastpage \empty \unexpanded\def\btxsetlastpage #1{\def\currentbtxlastpage {\btx_page_number{#1}}}
+\let\currentbtxfirstinternal\empty \unexpanded\def\btxsetfirstinternal {\def\currentbtxfirstinternal}
+\let\currentbtxlastinternal \empty \unexpanded\def\btxsetlastinternal {\def\currentbtxlastinternal}
+
+\def\currentbtxauthorvariant{normal}
+
+\unexpanded\def\btx_reset_list % not needed as we're grouped
+ {\let\currentbtxcombis \empty
+ \let\currentbtxcategory \empty
+ \let\currentbtxinternal \empty
+ \let\currentbtxlefttext \empty
+ \let\currentbtxrighttext\empty
+ \let\currentbtxbefore \empty
+ \let\currentbtxafter \empty
+ \let\currentbtxbacklink \empty
+ \let\currentbtxbacktrace\empty
+ \let\currentbtxlanguage \empty
+ \let\currentbtxsuffix \empty
+ %\let\currentbtxdataset \empty % will always be set
+ %\let\currentbtxtag \empty % will always be set
+ \let\currentbtxnumber \empty}
+
+\unexpanded\def\btx_reset_cite % check for less .. not all resets needed when we're grouped (only subcites)
+ {\let \currentbtxfirst \empty
+ \let \currentbtxsecond \empty
+ \let \currentbtxsuffix \empty
+ \let \currentbtxinternal \empty
+ \let \currentbtxlefttext \empty
+ \let \currentbtxrighttext \empty
+ \let \currentbtxbefore \empty
+ \let \currentbtxafter \empty
+ \let \currentbtxbacklink \empty
+ \let \currentbtxbacktrace \empty % not used here
+ \let \currentbtxlanguage \empty
+ %\let \currentbtxdataset \empty % will always be set, beware of local reset ~
+ %\let \currentbtxtag \empty % will always be set, beware of local reset ~
+ \let \currentbtxnumber \empty
+ \setconstant\currentbtxoverflow \zerocount
+ \setconstant\currentbtxconcat \zerocount
+ \setconstant\currentbtxcount \zerocount}
+
+\unexpanded\def\btx_reset_page % probably not needed
+ {\let \currentbtxfirstpage \empty
+ \let \currentbtxlastpage \empty
+ \let \currentbtxfirstinternal\empty
+ \let \currentbtxlastinternal \empty
+ \setconstant\currentbtxoverflow \zerocount
+ \setconstant\currentbtxconcat \zerocount
+ \setconstant\currentbtxcount \zerocount}
+
+\unexpanded\def\btx_reset_numbering % probably not needed
+ {\let \currentbtxfirst \empty
+ \let \currentbtxsecond\empty
+ \let \currentbtxsuffix\empty
+ \setconstant\currentbtxconcat\zerocount}
+
+%D Pages:
+
+\unexpanded\def\btx_page_number#1%
+ {\def\currentlistindex{#1}%
+ \structurelistpagenumber}
+
+%D Language:
+
+\def\mainbtxlanguage{\currentmainlanguage}
+
+\unexpanded\def\btx_check_language
+ {\let\mainbtxlanguage\currentlanguage
+ \ifx\currentbtxlanguage\empty
+ \let\currentbtxlanguage\currentlanguage
+ \else
+ \btx_check_language_indeed
+ \fi}
+
+\unexpanded\def\btx_check_language_indeed
+ {\edef\currentbtxlanguage{\reallanguagetag\currentbtxlanguage}%
+ \ifx\currentbtxlanguage\empty
+ \let\currentbtxlanguage\currentlanguage
+ \else\ifx\currentbtxlanguage\currentlanguage\else
+ \setcurrentlanguage\currentmainlanguage\currentbtxlanguage
+ \fi\fi}
+
+%D Tracing
+
+\newconditional\c_btx_trace % not used yet
+
+\installtextracker
+ {btxrendering}
+ {\settrue \c_btx_trace}
+ {\setfalse\c_btx_trace}
+
+%D Rendering lists and citations.
+
+\unexpanded\def\btxtodo#1%
+ {[#1]}
+
+%D Lists:
+
+\newdimen\d_publ_number_width
+
+\ifdefined\btxblock \else \newcount\btxblock \fi \btxblock\plusone
+\ifdefined\btxcitecounter \else \newcount\btxcitecounter \fi % maybe pass this to lua
+
+\newtoks \everysetupbtxlistplacement % name will change
+\newtoks \everysetupbtxciteplacement % name will change
+
+\definelist % only used for selecting
+ [\s!btx]
+
+\setuplist
+ [\s!btx]
+ [\c!prefixstopper=:,
+ \c!state=\v!start,
+ \c!alternative=a,
+ %\c!alternative=\v!paragraph,
+ %\c!width=\v!auto,
+ %\c!distance=\emwidth,
+ \c!before=\blank,
+ \c!after=\blank]
+
+\unexpanded\def\setupbtxlist
+ {\dodoubleempty\publ_setup_list}
+
+\unexpanded\def\publ_setup_list[#1][#2]%
+ {\ifsecondargument
+ \setuplist[\s!btx:#1][#2]%
+ \else\iffirstargument
+ \setuplist[\s!btx][#1]%
+ \fi\fi}
+
+\appendtoks
+ \ifx\currentbtxrenderingparent\empty
+ \definelist
+ [\s!btx:\currentbtxrendering]%
+ [\s!btx]%
+ \else\ifx\currentbtxrenderingparent\s!btx
+ \definelist
+ [\s!btx:\currentbtxrendering]%
+ [\s!btx]%
+ \else
+ \definelist
+ [\s!btx:\currentbtxrendering]%
+ [\s!btx:\currentbtxrenderingparent]%
+ \fi\fi
+\to \everydefinebtxrendering
+
+\newconditional\c_btx_list_texts
+
+\appendtoks
+ \doifelse{\btxrenderingparameter\c!textstate}\v!start
+ \settrue\setfalse\c_btx_list_texts
+\to \everysetupbtxlistplacement
+
+\newconditional\c_btx_list_pages
+
+\appendtoks
+ \doifelse{\btxrenderingparameter\c!pagestate}\v!start
+ \settrue\setfalse\c_btx_list_pages
+\to \everysetupbtxlistplacement
+
+\unexpanded\def\btx_entry_inject_pages % for the moment only normal
+ {\dontleavehmode
+ \begingroup
+ \setbtxlist % probably already set
+ \btx_reset_page
+ \setbtxparameterset\s!list\s!page
+ \btxparameter\c!command
+ {\usebtxstyleandcolor\c!style\c!color
+ \btxparameter\c!left
+ \clf_btxflushpages{\currentbtxdataset}{\currentbtxtag}%
+ \btxparameter\c!right}%
+ \endgroup}
+
+\unexpanded\def\btxpagesetup#1% there will b eno left|right|command|style at this inner level
+ {\begingroup
+ \publ_fast_setup\plusfive\s!list\s!page
+ \endgroup
+ \btx_reset_page} % probably not needed
+
+\unexpanded\def\btxnumberingsetup#1%
+ {\begingroup
+ \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
+ \endgroup
+ \btx_reset_numbering} % probably not needed
+
+% end of page stuff
+
+\unexpanded\def\btx_entry_inject
+ {\begingroup
+ \redoconvertfont % see (**) in strc-lst, this will become an configuration option
+ \edef\currentbtxcategory{\btxfield{category}}%
+ \ignorespaces
+ \ifconditional\c_btx_list_texts
+ \currentbtxbefore
+ \fi
+ \begingroup
+ \usebtxstyleandcolor\c!style\c!color
+ \ignorespaces
+ \publ_fast_setup\plusfour\s!list\currentbtxcategory
+ \removeunwantedspaces
+ \endgroup
+ \ifx\currentbtxcombis\empty \else
+ \btxrenderingparameter\c!separator
+ % maybe move this loop to lua
+ \begingroup
+ \processcommacommand[\currentbtxcombis]\btx_entry_inject_combi
+ \endgroup
+ \fi
+ \ifconditional\c_btx_list_pages
+ \btx_entry_inject_pages
+ \fi
+ \ifconditional\c_btx_list_texts
+ \currentbtxafter
+ \fi
+ \endgroup}
+
+\unexpanded\def\btxshowentryinline
+ {\dodoubleempty\btx_entry_show_inline}
+
+\unexpanded\def\btx_entry_show_inline[#1][#2]%
+ {\ifsecondargument
+ \ctxcommand{showbtxentry("#1","#2")}
+ \else\iffirstargument
+ \ctxcommand{showbtxentry("\currentbtxdataset","#1")}
+ \else
+ \ctxcommand{showbtxentry("\currentbtxdataset","\currentbtxtag")}
+ \fi\fi}
+
+\unexpanded\def\btxstartcombientry
+ {\begingroup}
+
+\unexpanded\def\btxstopcombientry
+ {\endgroup}
+
+\unexpanded\def\btxhandlecombientry
+ {\btx_reference_indeed}
+
+\def\btx_entry_inject_combi#1%
+ {\begingroup
+ \def\currentbtxtag{#1}%
+ \ignorespaces
+ \publ_fast_setup\plusfour\s!list\currentbtxcategory
+ \removeunwantedspaces
+ \endgroup}
+
+% uses reference when set
+
+% \def\btx_entry_inject_combi#1%
+% {\begingroup
+% \def\currentbtxtag{#1}%
+% \ignorespaces
+% \btxdoifelsecombiinlist\currentbtxdataset\currentbtxtag
+% {\clf_btxflushlistcombi{\currentbtxdataset}{\currentbtxtag}}
+% {\publ_fast_setup\plusfour\s!list\currentbtxcategory}%
+% \removeunwantedspaces
+% \endgroup}
+
+\unexpanded\def\completebtxrendering{\dodoubleempty\publ_place_list_complete}
+\unexpanded\def\placebtxrendering {\dodoubleempty\publ_place_list_standard}
+
+\let\completelistofpublications\completebtxrendering
+\let\placelistofpublications \placebtxrendering
+
+\newtoks\everybtxlistrendering
+
+\appendtoks
+ \setbtxlist
+ %
+ \edef\currentbtxcriterium{\btxrenderingparameter\c!criterium}% \v!cite will become \s!cite
+ \ifx\currentbtxcriterium\empty
+ \let\currentbtxcriterium\v!previous
+ \else\ifx\currentbtxcriterium\v!cite
+ \let\currentbtxcriterium\v!here
+ \fi\fi
+ %
+ \iflocation
+ \letinteractionparameter\c!style\empty
+ \fi
+\to \everybtxlistrendering
+
+\def\nofbtxlistentries {0}
+\def\currentbtxlistentry{0}
+\def\currentbtxlistindex{0} % only for internal use (points back to big list)
+
+\newconditional\c_publ_prefixed
+
+\unexpanded\def\btxsetnoflistentries #1{\edef\nofbtxlistentries {#1}}
+\unexpanded\def\btxsetcurrentlistentry#1{\edef\currentbtxlistentry{#1}}
+\unexpanded\def\btxsetcurrentlistindex#1{\edef\currentbtxlistindex{#1}}
+
+\unexpanded\def\btxdoifelsesameaspreviouschecked#1#2% #1 == always | doublesided
+ {\clf_btxdoifelsesameasprevious
+ {\currentbtxdataset}%
+ \currentbtxlistentry%
+ {#2}%
+ \c_btx_list_reference
+ {#1}}
+
+\unexpanded\def\btxdoifelsesameasprevious
+ {\btxdoifelsesameaspreviouschecked\v!doublesided}
+
+\unexpanded\def\btxdoifelsecombiinlist#1#2%
+ {\clf_btxdoifelsecombiinlist{#1}{#2}}
+
+\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked
+\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious
+\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist
+
+\def\publ_place_list_indeed#1[#2][#3]%
+ {\begingroup
+ \ifsecondargument
+ % [rendering] [settings]
+ \edef\currentbtxrendering{#2}%
+ \setupcurrentbtxrendering[#3]%
+ \edef\p_specification{\btxrenderingparameter\c!specification}%
+ \ifx\p_specification\empty\else
+ \let\currentbtxspecification\p_specification
+ \fi
+ \else\iffirstargument
+ \doifelseassignment{#2}
+ {% [settings]
+ \let\currentbtxrendering\currentbtxspecification
+ \setupcurrentbtxrendering[#2]%
+ \edef\p_specification{\btxrenderingparameter\c!specification}%
+ \ifx\p_specification\empty\else
+ \let\currentbtxspecification\p_specification
+ \let\currentbtxrendering\currentbtxspecification % tricky
+ \fi}
+ {\edef\currentbtxrendering{#2}%
+ \edef\p_specification{\btxrenderingparameter\c!specification}%
+ \ifx\p_specification\empty\else
+ \let\currentbtxspecification\p_specification
+ \fi}%
+ \else
+ \let\currentbtxrendering\currentbtxspecification
+ \fi\fi
+ \setbtxparameterset\currentbtxspecification\s!list
+ \the\everybtxlistrendering
+ \ifconditional#1\relax
+ \edef\currentbtxrenderingtitle{\btxrenderingparameter\c!title}%
+ \ifx\currentbtxrenderingtitle\empty
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\headtext{\currentbtxrendering}}]}%
+ \else
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\currentbtxrenderingtitle}]}%
+ \fi
+ \fi
+ \ifx\currentbtxrendering\empty
+ \setbtxrendering % hm
+ \fi
+ \btxrenderingparameter\c!before
+ \edef\currentbtxdataset{\btxrenderingparameter\c!dataset}%
+ \uselanguageparameter\btxdatasetparameter % new
+ \setbtxlist
+ \the\everystructurelist
+ \the\everysetupbtxlistplacement
+ \forgetall
+ % why not pass this with collect .. todo
+ % here we just collect items
+ \clf_btxcollectlistentries
+ names {\s!btx}%
+ criterium {\currentbtxcriterium}%
+ reference {\btxrenderingparameter\c!reference}%
+ method {\btxrenderingparameter\c!method}%
+ dataset {\currentbtxdataset}%
+ keyword {\btxrenderingparameter\c!keyword}%
+ sorttype {\btxrenderingparameter\c!sorttype}%
+ repeated {\btxrenderingparameter\c!repeat}%
+ ignored {\btxrenderingparameter\c!ignore}%
+ group {\btxrenderingparameter\c!group}%
+ \relax
+ \ifnum\nofbtxlistentries>\zerocount
+ \startpacked[\v!blank]%
+ % sorting and so
+ \clf_btxpreparelistentries{\currentbtxdataset}% could be put in collect
+ % next we analyze the width
+ \ifx\currentbtxnumbering\empty \else
+ \edef\p_width{\listparameter\c!width}%
+ \ifx\p_width\v!auto
+ \setbox\scratchbox\vbox \bgroup
+ \settrialtypesetting
+ \clf_btxfetchlistentries{\currentbtxdataset}%
+ \egroup
+ \d_publ_number_width\wd\scratchbox
+ \letlistparameter\c!width\d_publ_number_width
+ \fi
+ \fi
+ \doifelse{\listparameter\c!prefix}\v!yes\settrue\setfalse\c_publ_prefixed
+ % this actually typesets them, we loop here as otherwise the whole
+ % bunch gets flushed at once
+ \dorecurse\nofbtxlistentries
+ {\let\currentbtxlistentry\recurselevel
+ \clf_btxflushlistentry{\currentbtxdataset}\currentbtxlistentry\relax}%
+ \stoppacked
+ \fi
+ \btxrenderingparameter\c!after
+ \global\advance\btxblock\plusone
+ \ifconditional#1\relax
+ \stopnamedsection
+ \fi
+ \endgroup}
+
+\def\publ_place_list_complete{\publ_place_list_indeed\conditionaltrue}
+\def\publ_place_list_standard{\publ_place_list_indeed\conditionalfalse}
+
+\def\currentbtxblock{\number\btxblock}
+
+% called at the lua end, for determining the width
+
+\unexpanded\def\btxchecklistentry
+ {\begingroup
+ % todo, switch to font
+ \hbox{\btx_reference_checked}%
+ \par
+ \endgroup}
+
+% called at the lua end, the real rendering
+
+% we could have a yes and no where o nils the btx_reference_indeed ... saves a check there
+
+\installstructurelistprocessor{\s!btx}
+ {\let\currentlistentrynumber \btx_reference_indeed
+ \let\currentlistentrytitle \btx_entry_indeed
+ \let\currentlistentrypagenumber\btx_page_indeed
+ \strc_lists_apply_renderingsetup}
+
+\def\btx_entry_indeed
+ {\btx_list_reference_inject
+ \btx_entry_inject}
+
+\def\btx_page_indeed
+ {}
+
+\unexpanded\def\btxhandlelistentry
+ {\strc_lists_entry_process}
+
+\unexpanded\def\btxstartlistentry % maybe pass i
+ {\begingroup
+ \global\advance\c_btx_list_reference\plusone}
+
+\unexpanded\def\btxstoplistentry
+ {\iftrialtypesetting
+ \global\advance\c_btx_list_reference\minusone
+ \fi
+ \endgroup}
+
+\newtoks\everybtxlistentry
+
+\unexpanded\def\btxlistsetup#1% used for the reference in the list
+ {\the\everybtxlistentry
+ \everybtxlistentry\emptytoks % so only once per entry to be sure
+ \publ_fast_setup\plusfour\s!list{#1}}
+
+\appendtoks
+ \btx_check_language
+\to \everybtxlistentry
+
+\unexpanded\def\btx_reference_indeed
+ {\begingroup
+ % redundantm will go away:
+ \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering
+ %
+ \ifx\currentbtxnumbering\empty
+ % nothing
+ \else\ifx\currentbtxnumbering\v!no
+ % nothing
+ \else
+ \usebtxstyleandcolor\c!style\c!color % new, needed?
+ \ifconditional\c_publ_prefixed\btxlistprefixednumber\fi
+ \clf_btxlistvariant % some can go
+ {\currentbtxdataset}%
+ {\currentbtxblock}%
+ {\currentbtxtag}%
+ {\currentbtxnumbering}%
+ {\currentbtxnumber}%
+ \relax
+ \fi\fi
+ \endgroup}
+
+\unexpanded\def\btxlistprefixednumber % hack but alan needs it
+ {\clf_listprefixednumber
+ {\currentlist}%
+ \currentbtxlistindex
+ {%
+ prefix {\listparameter\c!prefix}%
+ separatorset {\listparameter\c!prefixseparatorset}%
+ conversionset {\listparameter\c!prefixconversionset}%
+ starter {\listparameter\c!prefixstarter}%
+ stopper {\listparameter\c!prefixstopper}%
+ set {\listparameter\c!prefixset}%
+ segments {\listparameter\c!prefixsegments}%
+ connector {\listparameter\c!prefixconnector}%
+ }%
+ \relax}
+
+\unexpanded\def\btx_reference_checked
+ {\dontleavehmode\hbox\bgroup
+ \btx_reference_indeed
+ \egroup}
+
+\newcount\c_btx_list_reference
+
+\unexpanded\def\btx_list_reference_inject
+ {\dontleavehmode\begingroup % no box
+ \iftrialtypesetting\else
+ \btx_list_reference_inject_now
+ \fi
+ % \btx_reference_indeed % else double entry in list
+ \endgroup}
+
+\def\btx_list_reference_inject_now
+ {\btx_trace_list_cross\empty\currentbtxbacktrace
+ \strc_references_direct_full_user
+ {\ifx\currentbtxdataset\v!default\else\s!btxset=\currentbtxdataset,\fi%
+ \s!btxref=\currentbtxtag,%
+ \s!btxspc=\currentbtxspecification,%
+ \s!btxlst=\number\c_btx_list_reference,% check if needed
+ %\ifx\currentbtxcombis\empty\else\s!btxcom={\currentbtxcombis},\fi%
+ \ifx\currentbtxbefore\empty\else\s!btxbtx={\currentbtxbefore},\fi%
+ \ifx\currentbtxafter \empty\else\s!btxatx={\currentbtxafter },\fi%
+ \ifx\currentbtxbacklink\currentbtxbacktrace\s!btxint=\currentbtxbacklink\else\s!btxbck=\currentbtxbacktrace\fi}%
+ {\s!btx::\v!list::\number\c_btx_list_reference}%
+ {\currentbtxnumber}}
+
+\newconditional\c_btx_cite_reference_injected
+
+\unexpanded\def\btx_cite_reference_inject
+ {\ifconditional\c_btx_cite_reference_injected
+ \else
+ \dontleavehmode
+ \iftrialtypesetting \else
+ \ifx\currentbtxbacklink\empty
+ % can be made empty when combining author / year
+ \else
+ \btx_cite_reference_inject_indeed
+ \settrue\c_btx_cite_reference_injected
+ \fi
+ \fi
+ \fi}
+
+\newtoks\t_btx_reference_inject
+
+\def\btx_cite_reference_inject_indeed
+ {\btx_trace_list_cross\currentbtxbacklink\empty
+ \the\t_btx_reference_inject
+ \strc_lists_inject_direct % todo: make like \btx_list_reference_inject_now with { }
+ [\s!btx]%
+ [\c!type=\s!btx]% \c!location=\v!none
+ [\ifx\currentbtxdataset\v!default\else\s!btxset=\currentbtxdataset,\fi%
+ \s!btxref=\currentbtxtag,%
+ %\ifx\currentbtxcombis\empty\else\s!btxcom={\currentbtxcombis},\fi%
+ \ifx\currentbtxbefore\empty\else\s!btxbtx={\currentbtxbefore},\fi%
+ \ifx\currentbtxafter \empty\else\s!btxatx={\currentbtxafter },\fi%
+ \s!btxint=\number\currentbtxbacklink
+ \ifx\currentbtxciteuservariables\empty\else,\currentbtxciteuservariables\fi]}
+
+\def\currentbtxuservariable #1{\clf_btxuservariable {\currentbtxdataset}{#1}}
+\def\btxdoifelseuservariable#1{\clf_btxdoifelseuservariable{\currentbtxdataset}{#1}}
+
+\let\btxdoifuservariableelse\btxdoifelseuservariable
+
+\let\btxcitereference\btx_cite_reference_inject
+
+\let\currentbtxnumbering\empty
+
+\appendtoks
+ \edef\currentbtxnumbering{\btxrenderingparameter\c!numbering}%
+ \ifx\currentbtxnumbering\v!yes
+ \def\currentbtxnumbering{num}% convenient alias
+ \letbtxrenderingparameter\c!numbering\currentbtxnumbering
+ \letlistparameter\c!headnumber\v!always
+ \else\ifx\currentbtxnumbering\v!no
+ \letlistparameter\c!headnumber\v!no
+ \let\currentbtxnumbering\empty
+ % \letlistparameter\c!textcommand\outdented % needed? we can use titlealign
+ \letlistparameter\c!symbol \v!none
+ \letlistparameter\c!aligntitle \v!yes
+ \letlistparameter\c!numbercommand\firstofoneargument % for the moment, no doubling needed
+ \else
+ \letlistparameter\c!headnumber\v!always
+ \fi\fi
+ \let\currentlistmethod\s!btx
+\to \everysetupbtxlistplacement
+
+\unexpanded\def\btxremapauthor
+ {\dodoubleargument\btx_remap_author}
+
+\def\btx_remap_author[#1][#2]%
+ {\clf_btxremapauthor{#1}{#2}}
+
+\unexpanded\def\btxflushauthor
+ {\doifelsenextoptionalcs\btx_flush_author_yes\btx_flush_author_nop}
+
+\unexpanded\def\btxflushsuffix
+ {\ifx\currentbtxsuffix\empty
+ % nothing
+ \else
+ \characters{\currentbtxsuffix}% todo : rendering specific converter
+ \fi}
+
+\def\btx_flush_author_yes[#1]{\btx_flush_author{#1}}
+\def\btx_flush_author_nop {\btx_flush_author{\btxparameter\c!authorconversion}}
+
+\unexpanded\def\btx_flush_author#1#2%
+ {\begingroup
+ \edef\currentbtxfield{#2}%
+ \setbtxparameterset\s!list\currentbtxfield
+% \let\currentbtxlistvariant\currentbtxfield
+ \clf_btxauthor
+ {\currentbtxdataset}%
+ {\currentbtxtag}%
+ {\currentbtxfield}%
+ {%
+ combiner {#1}%
+ kind {list}%
+ etallimit {\btxparameter\c!etallimit}%
+ etaldisplay {\btxparameter\c!etaldisplay}%
+ etaloption {\btxparameter\c!etaloption}%
+ symbol {\btxparameter{\c!stopper:initials}}%
+ }%
+ \relax
+ \endgroup}
+
+% yes or no: maybe just \flushauthor{...}{...}
+
+\unexpanded\def\btxflushauthorname {\btx_flush_author{name}} % #1
+\unexpanded\def\btxflushauthornormal {\btx_flush_author{normal}} % #1
+\unexpanded\def\btxflushauthornormalshort {\btx_flush_author{normalshort}} % #1
+\unexpanded\def\btxflushauthorinverted {\btx_flush_author{inverted}} % #1
+\unexpanded\def\btxflushauthorinvertedshort{\btx_flush_author{invertedshort}} % #1
+
+\unexpanded\def\currentbtxciteauthor % always author
+ {\begingroup
+ \setbtxparameterset\s!cite\s!author
+ \clf_btxauthor
+ {\currentbtxdataset}%
+ {\currentbtxtag}%
+ {\s!author}%
+ {%
+ combiner {\btxparameter\c!authorconversion}%
+ kind {cite}%
+ etallimit {\btxparameter\c!etallimit}%
+ etaldisplay {\btxparameter\c!etaldisplay}%
+ etaloption {\btxparameter\c!etaloption}%
+ symbol {\btxparameter{\c!stopper:initials}}%
+ }%
+ \relax
+ \endgroup}
+
+\unexpanded\def\btxstartauthor#1#2#3% a state > 0 signals that some authors can clash
+ {\begingroup
+ \currentbtxauthorindex#1\relax
+ \currentbtxauthorcount#2\relax
+ \currentbtxauthorstate#3\relax}
+
+\unexpanded\def\btxstopauthor
+ {\endgroup}
+
+\unexpanded\def\btxciteauthorsetup#1{\fastsetup{\s!btx:\s!cite:\s!author:#1}}
+\unexpanded\def\btxlistauthorsetup#1{\fastsetup{\s!btx:\s!list:\s!author:#1}}
+
+% \btxflushauthor{author}
+% \btxflushauthor{editor}
+%
+% \btxflushauthor[name]{author}
+% \btxflushauthor[normal]{author}
+% \btxflushauthor[normalshort]{author}
+% \btxflushauthor[inverted]{author}
+% \btxflushauthor[invertedshort]{author}
+
+% \btxflushauthor{author}
+% \btxflushauthor{editor}
+%
+% \btxflushauthor[name]{author}
+% \btxflushauthor[normal]{author}
+% \btxflushauthor[normalshort]{author}
+% \btxflushauthor[inverted]{author}
+% \btxflushauthor[invertedshort]{author}
+
+% Interaction
+
+\newconditional\btxinteractive
+\newconditional\btx_interactive
+
+% of maybe modes?
+
+\appendtoks
+ \iflocation
+ \edef\p_interaction{\btxparameter\c!interaction}%
+ \ifx\p_interaction\v!stop
+ \setfalse\btxinteractive
+ \else
+ \settrue\btxinteractive
+ \ifx\p_interaction\v!all
+ \settrue\btx_interactive
+ \else
+ \setfalse\btx_interactive
+ \fi
+ \fi
+ \else
+ \setfalse\btxinteractive
+ \setfalse\btx_interactive
+ \fi
+\to \everysetupbtxlistplacement
+
+\appendtoks
+ \iflocation
+ \edef\p_interaction{\btxparameter\c!interaction}%
+ \ifx\p_interaction\v!stop
+ \setfalse\btxinteractive
+ \else
+ \settrue\btxinteractive
+ \fi
+ \else
+ \setfalse\btxinteractive
+ \fi
+\to \everysetupbtxciteplacement
+
+%D When a publication is cited, we need to signal that somehow. This is done with the
+%D following (not user) command. We could tag without injecting a node but this way
+%D we also store the location, which makes it possible to ask local lists.
+
+%D \macros{cite,nocite,citation,nocitation,usecitation}
+%D
+%D The inline \type {\cite} command creates a (often) short reference to a publication
+%D and for historic reasons uses a strict test for brackets. This means, at least
+%D in the default case that spaces are ignored in the argument scanner. The \type
+%D {\citation} commands is more liberal but also gobbles following spaces. Both
+%D commands insert a reference as well as a visual clue.
+%D
+%D The \type {no} commands all do the same (they are synonyms): they make sure that
+%D a reference is injected but show nothing. However, they do create a node so best
+%D attach them to some text in order to avoid spacing interferences. A slightly
+%D less efficient alternative is \type {\cite[none][tag]}.
+
+% [tags]
+% [settings|variant][tags]
+% [base::tags]
+% [settings|variant][base::tags]
+
+% these need to be sort of protected:
+
+% methods:
+%
+% hidden : mark for list, don't show in text
+% list : mark for list, show in text only when in list
+% text : not to list, show in text
+% always : mark for list, show in text
+
+\let\p_publ_cite_before \empty
+\let\p_publ_cite_after \empty
+\let\p_publ_cite_lefttext \empty
+\let\p_publ_cite_righttext\empty
+
+\let\currentbtxciteuservariables\empty
+
+\unexpanded\def\btxhybridcite % so one can alias the old
+ {\dontleavehmode
+ \begingroup
+ \strictdoifelsenextoptional\publ_cite_tags_options\publ_cite_tags_indeed}
+
+\unexpanded\def\publ_cite_tags_options[#1]%
+ {\strictdoifelsenextoptional{\publ_cite_tags_options_indeed{#1}}{\publ_cite_tags_indeed{#1}}}
+
+\unexpanded\def\publ_cite_tags_indeed#1%
+ {\letinteractionparameter\c!style\empty
+ \setbtxparametersetroot\s!cite % we need to get the default
+ \edef\currentbtxcitealternative{\btxparameter\c!alternative}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \edef\currentbtxcitetag{#1}%
+ \the\everysetupbtxciteplacement
+ \publ_cite_variant
+ \endgroup}
+
+\unexpanded\def\publ_cite_tags_options_indeed#1%
+ {\doifelseassignment{#1}\publ_cite_tags_settings_indeed\publ_cite_tags_variants_indeed{#1}}
+
+\def\publ_cite_tags_settings_indeed#1[#2]%
+ {\letinteractionparameter\c!style\empty
+ %\letinteractionparameter\c!color\empty
+ \letdummyparameter\c!reference \empty
+ \letdummyparameter\c!alternative\empty
+ \letdummyparameter\c!before \empty
+ \letdummyparameter\c!after \empty
+ \letdummyparameter\c!lefttext \empty
+ \letdummyparameter\c!righttext \empty
+ \getdummyparameters[#1]%
+ \edef\p_reference{\dummyparameter\c!reference}%
+ \ifx\p_reference\empty
+ \edef\currentbtxcitetag{#2}%
+ \else
+ \let\currentbtxcitetag\p_reference
+ \edef\currentbtxciteuservariables{#2}%
+ \fi
+ \edef\p_alternative{\dummyparameter\c!alternative}%
+ \ifx\p_alternative\empty
+ \setbtxparametersetroot\s!cite
+ \edef\currentbtxcitealternative{\btxparameter\c!alternative}%
+ \else
+ \let\currentbtxcitealternative\p_alternative
+ \fi
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \setupcurrentbtx[#1]%
+ %
+ \edef\p_publ_cite_before {\dummyparameter\c!before}%
+ \edef\p_publ_cite_after {\dummyparameter\c!after}%
+ \edef\p_publ_cite_lefttext {\dummyparameter\c!lefttext}%
+ \edef\p_publ_cite_righttext{\dummyparameter\c!righttext}%
+ %
+ \the\everysetupbtxciteplacement
+ \publ_cite_variant
+ \endgroup}
+
+\def\publ_cite_tags_variants_indeed#1[#2]%
+ {\letinteractionparameter\c!style\empty
+ \edef\currentbtxcitealternative{#1}%
+ \edef\currentbtxcitetag{#2}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \the\everysetupbtxciteplacement
+ \publ_cite_variant
+ \endgroup}
+
+\newconditional\btxcitecompress
+
+\let\currentbtxreference\empty
+\let\currentbtxcitemethod\v!hidden
+
+\def\publ_cite_variant
+ {\begingroup
+ \publ_cite_handle_variant_indeed[\currentbtxcitetag]}
+
+\unexpanded\def\publ_cite_handle_variant#1%
+ {\begingroup
+ \edef\currentbtxcitealternative{#1}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \the\everysetupbtxciteplacement
+ \dosingleargument\publ_cite_handle_variant_indeed}
+
+\unexpanded\def\publ_cite_handle_variant_blob
+ {\clf_btxhandlecite
+ dataset {\currentbtxdataset}%
+ reference {\currentbtxreference}%
+ method {\currentbtxcitemethod}%
+ variant {\currentbtxcitealternative}%
+ sorttype {\btxparameter\c!sorttype}%
+ compress {\btxparameter\c!compress}%
+ author {\btxparameter\c!author}%
+ authorconversion {\c!authorconversion}%
+ lefttext {\p_publ_cite_lefttext}%
+ righttext {\p_publ_cite_righttext}%
+ before {\p_publ_cite_before}%
+ after {\p_publ_cite_after}%
+ \relax
+ \iftrialtypesetting\else
+ %\clf_btxflushmarked
+ \fi}
+
+\let\dobtxcitevariantblob\publ_cite_handle_variant_blob % command can use it via lua
+
+\def\publ_cite_handle_variant_indeed[#1]%
+ {\letbtxparameter\c!alternative\currentbtxcitealternative
+ \edef\currentbtxreference{#1}%
+ \usebtxstyleandcolor\c!style\c!color
+ \uselanguageparameter\btxdatasetparameter % new
+ \btxparameter\c!left
+ \btxparameter\c!command{\dobtxcitevariantblob}% {\publ_cite_handle_variant_blob}%
+ \btxparameter\c!right
+ \endgroup}
+
+\unexpanded\def\btxlistcitation
+ {\dontleavehmode
+ \begingroup
+ \let\currentbtxcitemethod\v!list
+ \dodoubleempty\publ_citation}
+
+\unexpanded\def\btxtextcitation
+ {\dontleavehmode
+ \begingroup
+ \let\btxcitereference\relax % a bit of a hack but ok
+ \let\currentbtxcitemethod\v!text
+ \dodoubleempty\publ_citation}
+
+\unexpanded\def\btxalwayscitation
+ {\dontleavehmode
+ \begingroup
+ \let\currentbtxcitemethod\v!always
+ \dodoubleempty\publ_citation}
+
+\def\publ_citation[#1][#2]% could be made more efficient but not now
+ {\ifsecondargument
+ \publ_cite_tags_options_indeed{#1}[#2]%
+ \else
+ \publ_cite_tags_indeed{#1}%
+ \fi}
+
+\unexpanded\def\btxhiddencitation
+ {\dosingleempty\publ_cite_hidden}
+
+\unexpanded\def\publ_cite_hidden[#1]%
+ {\iftrialtypesetting \else
+ \begingroup
+ \let\currentbtxcitemethod\v!hidden
+ \edef\currentbtxreference{#1}%
+ \clf_btxhandlenocite
+ method {\currentbtxcitemethod}%
+ dataset {\currentbtxdataset}%
+ reference {\currentbtxreference}%
+ \relax
+ %\clf_btxflushmarked
+ \endgroup
+ \fi}
+
+\unexpanded\def\btxmissing#1%
+ {\dontleavehmode{\tttf<#1>}}
+
+%D Compatibility:
+
+\let\hiddencitation\btxhiddencitation \let\hiddencite\hiddencitation
+\let\listcitation \btxlistcitation \let\listcite \listcitation
+\let\textcitation \btxtextcitation \let\textcite \textcitation
+\let\alwayscitation\btxalwayscitation \let\alwayscite\alwayscitation
+
+\unexpanded\def\citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite}
+\unexpanded\def\nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite}
+
+\let\cite \citation
+\let\nocite\nocitation
+
+\unexpanded\def\publ_entry_citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite}
+\unexpanded\def\publ_entry_nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite}
+
+\appendtoks
+ \let\cite \publ_entry_citation
+ \let\nocite\publ_entry_nocitation
+\to \everybtxlistrendering
+
+\unexpanded\def\btxdirectlistcite #1{\btxlistcitation [#1]\relax} % no optional arguments
+\unexpanded\def\btxdirecthiddencite#1{\btxhiddencitation[#1]\relax} % no optional arguments
+
+%D Setup helpers, beware, we need to wrap this .. now we need to know
+%D how setups are implemented.
+
+\setvalue{\??setup:\s!btx:\s!unknown}#1{\inframed{\tttf#1}}
+
+\def\publ_fast_setup_yes#1#2%
+ {\csname\??setup:\s!btx:%
+ \ifcsname\??setup:\s!btx:\currentbtxspecification:#1:#2\endcsname
+ \currentbtxspecification:#1:#2%
+ \else\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:#2\endcsname
+ \currentbtxspecificationfallback:#1:#2%
+ \else\ifcsname\??setup:\s!btx:#1:#2\endcsname
+ #1:#2%
+ \else\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname
+ \currentbtxspecification:#1:\s!unknown
+ \else\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:\s!unknown\endcsname
+ \currentbtxspecificationfallback:#1:\s!unknown
+ \else
+ #1:\s!unknown
+ \fi\fi\fi\fi\fi
+ \endcsname{#2}}
+
+\def\publ_fast_setup_nop#1#2%
+ {\csname\??setup:\s!btx:%
+ \ifcsname\??setup:\s!btx:\currentbtxspecification:#1:#2\endcsname
+ \currentbtxspecification:#1:#2%
+ \else\ifcsname\??setup:\s!btx:#1:#2\endcsname
+ #1:#2%
+ \else\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname
+ \currentbtxspecification:#1:\s!unknown
+ \else
+ #1:\s!unknown
+ \fi\fi\fi
+ \endcsname{#2}}
+
+\newconstant\btxsetuptype
+
+% 0 = unknown darkred
+% 1 = cite darkblue
+% 2 = subcite darkgreen
+% 3 = numbering darkorange
+% 4 = list darkcyan
+% 5 = page darkmagenta
+% 6 = unknown darkred
+
+\unexpanded\def\publ_fast_btx_setup_chain_inbetween
+ {\allowbreak->\allowbreak}
+
+\unexpanded\def\publ_fast_btx_setup_colon_inbetween
+ {\allowbreak:\allowbreak}
+
+\unexpanded\def\publ_fast_btx_setup_chain_yes#1#2%
+ {\dontleavehmode\begingroup
+ \let\:\publ_fast_btx_setup_colon_inbetween
+ \infofont
+ \ifcase\btxsetuptype\darkred\or\darkblue\or\darkgreen\or\darkcyan\or\darkmagenta\else\darkred\fi
+ [\prewordbreak
+ \currentbtxspecification \:#1\:#2\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:#2\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ \currentbtxspecificationfallback\:#1\:#2\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:#2\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ #1\:#2\ifcsname\??setup:\s!btx:#1:#2\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ \currentbtxspecification \:#1\:\s!unknown\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ \currentbtxspecificationfallback\:#1\:\s!unknown\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:\s!unknown\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ unset\fi\fi\fi\fi\fi
+ \space @\space
+ \currentbtx
+ \prewordbreak]%
+ \endgroup}
+
+\unexpanded\def\publ_fast_btx_setup_chain_nop#1#2%
+ {\dontleavehmode\begingroup
+ \let\:\publ_fast_btx_setup_colon_inbetween
+ \infofont
+ \darkred
+ [\prewordbreak
+ \currentbtxspecification\:#1\:#2\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:#2\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ #1\:#2\ifcsname\??setup:\s!btx:#1:#2\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ \currentbtxspecification\:#1\:\s!unknown\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname\else
+ \publ_fast_btx_setup_chain_inbetween
+ unset\fi\fi\fi
+ \space @\space
+ \currentbtx
+ \prewordbreak]%
+ \endgroup}
+
+\unexpanded\def\publ_fast_btx_setup_normal#1%
+ {\btxsetuptype#1\relax
+ \ifx\currentbtxspecificationfallback\empty
+ \expandafter\publ_fast_setup_nop
+ \else
+ \expandafter\publ_fast_setup_yes
+ \fi}
+
+\unexpanded\def\publ_fast_btx_setup_visual#1#2#3%
+ {\btxsetuptype#1\relax
+ \ifx\currentbtxspecificationfallback\empty
+ \expandafter\publ_fast_btx_setup_chain_nop
+ \else
+ \expandafter\publ_fast_btx_setup_chain_yes
+ \fi{#2}{#3}%
+ \ifx\currentbtxspecificationfallback\empty
+ \expandafter\publ_fast_setup_nop
+ \else
+ \expandafter\publ_fast_setup_yes
+ \fi{#2}{#3}}
+
+\installtextracker
+ {publications.setups}
+ {\let\publ_fast_setup\publ_fast_btx_setup_visual}
+ {\let\publ_fast_setup\publ_fast_btx_setup_normal}
+
+\let\publ_fast_setup\publ_fast_btx_setup_normal
+
+%D Cite helpers:
+
+\newtoks\everybtxciteentry
+
+\prependtoks
+ \setfalse\c_btx_cite_reference_injected
+\to \everybtxciteentry
+
+\unexpanded\def\btxcitesetup#1%
+ {\the\everybtxciteentry
+ \everybtxciteentry\emptytoks % tricky maybe not when subcites
+ \publ_fast_setup\plusone\s!cite{#1}} % no \btxcitereset as we loose dataset and such
+
+\unexpanded\def\btxsubcitesetup#1%
+ {\the\everybtxciteentry
+ \everybtxciteentry\emptytoks % tricky maybe not when subcites
+ \publ_fast_setup\plustwo\s!cite{#1}} % no \btxcitereset as we loose dataset and such
+
+\appendtoks
+ \btx_check_language
+\to \everybtxciteentry
+
+\unexpanded\def\btxstartsubcite#1%
+ {\begingroup
+ \btx_reset_cite % todo: limited set
+ \def\currentbtxcitealternative{#1}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \usebtxstyleandcolor\c!style\c!color
+ \btxparameter\c!left
+ \relax}
+
+\unexpanded\def\btxstopsubcite
+ {\relax
+ \btxparameter\c!right
+ \endgroup}
+
+\unexpanded\def\btxstartciterendering[#1]%
+ {\begingroup
+ \edef\currentbtxcitealternative{#1}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \usebtxstyleandcolor\c!style\c!color
+ \btxparameter\c!left
+ \relax}
+
+\unexpanded\def\btxstopciterendering
+ {\relax
+ \btxparameter\c!right
+ \endgroup}
+
+\let\btxstartciteauthor\begingroup
+\let\btxstopciteauthor \endgroup
+
+\unexpanded\def\btxstartcite{\begingroup\btx_reset_cite}
+ \let\btxstopcite \endgroup
+
+%D Whatever helpers:
+
+\unexpanded\def\btxsingularplural#1{\clf_btxsingularorplural{\currentbtxdataset}{\currentbtxtag}{#1}}
+\unexpanded\def\btxoneorrange #1{\clf_btxoneorrange {\currentbtxdataset}{\currentbtxtag}{#1}}
+\unexpanded\def\btxfirstofrange #1{\clf_btxfirstofrange {\currentbtxdataset}{\currentbtxtag}{#1}}
+
+\let\btxsingularorplural\btxsingularplural
+
+\stopcontextdefinitioncode
+
+%D Journals
+
+\unexpanded\def\btxloadjournallist [#1]{\clf_btxloadjournallist{#1}}
+\unexpanded\def\btxsavejournallist [#1]{\clf_btxsavejournallist{#1}}
+\unexpanded\def\btxaddjournal [#1][#2]{\clf_btxaddjournal{#1}{#2}}
+ \def\btxexpandedjournal #1{\clf_btxexpandedjournal{#1}} % \unexpanded ?
+ \def\btxabbreviatedjournal#1{\clf_btxabbreviatedjournal{#1}} % \unexpanded ?
+
+% \installcorenamespace{btxjournal}
+%
+% \letvalue{\s!btxjournal\v!long }\btxexpandedjournal
+% \letvalue{\s!btxjournal\v!short }\btxabbreviatedjournal
+% \letvalue{\s!btxjournal\v!normal}\firstofoneargument
+%
+% \unexpanded\def\btxcheckedjournal
+% {\expandnamespaceparameter\s!btxjournal\btxrenderingparameter\c!journalconversion}
+
+% \btxloadjournallist[list.txt] % Foo Journal of Bars = FBJ \n ....
+%
+% \btxexpandedjournal[fbj]
+% \btxabbreviatedjournal[foo journal of bars]
+
+%D Saving data:
+
+\unexpanded\def\savebtxdataset
+ {\dotripleargument\publ_save_dataset}
+
+\unexpanded\def\publ_save_dataset[#1][#2][#3]%
+ {\ifthirdargument
+ \publ_save_dataset_indeed[#1][#2][#3]%
+ \else\ifsecondargument
+ \doifelseassignment{#2}%
+ {\publ_save_dataset_indeed[\s!default][#1][#2]}%
+ {\publ_save_dataset_indeed[#1][#2][]}%
+ \else\iffirstargument
+ \doifelseassignment{#1}%
+ {\publ_save_dataset_indeed[\s!default][\jobname-saved.bib][#1]}%
+ {\publ_save_dataset_indeed[\s!default][#1][]}%
+ % \else
+ % % bad news
+ \fi\fi\fi}
+
+\unexpanded\def\publ_save_dataset_indeed[#1][#2][#3]%
+ {\begingroup
+ \getdummyparameters
+ [\c!criterium=\v!all,%
+ \c!type=,%
+ \c!dataset=#1,%
+ \c!file=#2,%
+ #3]% % all or used
+ \clf_btxsavedataset
+ dataset {\dummyparameter\c!dataset}%
+ filename {\dummyparameter\c!file}%
+ filetype {\dummyparameter\c!type}%
+ criterium {\dummyparameter\c!criterium}%
+ \relax
+ \endgroup}
+
+% \savebtxdataset[default][e:/tmp/foo.bib]
+% \savebtxdataset[default][e:/tmp/foo.lua]
+% \savebtxdataset[default][e:/tmp/foo.xml]
+
+%D In-text entries:
+
+\unexpanded\def\placecitation{\citation[entry]} % [#1]
+
+\unexpanded\def\btxhandleciteentry
+ {\dontleavehmode
+ \begingroup
+ \def\currentbtxcitealternative{entry}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative % needs checking
+ \btxcitereference
+ \btx_entry_inject
+ \endgroup}
+
+%D Registers
+
+% \setupbtxregister
+% [\c!state=\v!start,
+% \c!dataset=\v!all,
+% \c!method=\v!always]
+
+\unexpanded\def\publ_registers_set
+ {\ifx\currentbtxregister\empty \else
+ \clf_btxsetregister
+ specification {\currentbtxspecification}%
+ name {\currentbtxregister}%
+ state {\btxregisterparameter\c!state}%
+ dataset {\btxregisterparameter\c!dataset}%
+ field {\btxregisterparameter\c!field}%
+ register {\btxregisterparameter\c!register}%
+ method {\btxregisterparameter\c!method}%
+ alternative {\btxregisterparameter\c!alternative}%
+ \relax
+ \fi}
+
+\appendtoks
+ \publ_registers_set
+\to \everydefinebtxregister
+
+\appendtoks
+ \publ_registers_set
+\to \everysetupbtxregister
+
+\appendtoks
+ \normalexpanded{%
+ \defineprocessor
+ [\s!btx:r:\currentbtxregister]%
+ [\c!style=\noexpand\namedbtxregisterparameter{\currentbtxregister}\noexpand\c!style,
+ \c!color=\noexpand\namedbtxregisterparameter{\currentbtxregister}\noexpand\c!color]}%
+\to \everydefinebtxregister
+
+\appendtoks
+ \clf_btxtoregister{\currentbtxdataset}{\currentbtxtag}%
+\to \t_btx_reference_inject
+
+\unexpanded\def\btxindexedauthor#1#2#3#4#5#6% alternative von last initials first junior
+ {\begingroup
+ \def\currentbtxcitealternative{#1}%
+ \ifx\currentbtxcitealternative\empty
+ \edef\currentbtxcitealternative{invertedshort}% maybe we need some default here too?
+ \fi
+ %let\currentbtxlistvariant\currentbtxcitealternative % we inherit
+ \the\everysetupbtxciteplacement
+ \def\currentbtxvons {#2}%
+ \def\currentbtxsurnames {#3}%
+ \def\currentbtxinitials {#4}%
+ \def\currentbtxfirstnames {#5}%
+ \def\currentbtxjuniors {#6}%
+ \setbtxparameterset\s!cite\currentbtxcitealternative
+ \fastsetup{\s!btx:\s!cite:\s!author:\currentbtxcitealternative}%
+ \endgroup}
+
+\unexpanded\def\btxregisterauthor
+ {\doifelsenextoptionalcs\publ_register_author_yes\publ_register_author_nop}
+
+\def\publ_register_author_yes[#1]#2%
+ {\clf_btxauthortoregister{#1}{#2}\relax}
+
+\def\publ_register_author_nop#1%
+ {\clf_btxauthortoregister{\currentbtxdataset}{#1}\relax}
+
+
+%D We hook some setters in the definition sets:
+
+% \installdefinitionsetmember \??btx {btxspecification} \??btxcitevariant {btxcitevariant}
+% \installdefinitionsetmember \??btx {btxspecification} \??btxlistvariant {btxlistvariant}
+% \installdefinitionsetmember \??btx {btxspecification} \??btxlist {btxlist}
+% \installdefinitionsetmember \??btx {btxspecification} \??btxrendering {btxrendering}
+% \installdefinitionsetmember \??btx {btxspecification} \??btx {btx}
+
+%D And more helpers ... a never ending story these publications:
+
+% \definebtx
+% [btx:apa:list:article:title]
+% [style=bolditalic,
+% command=\WORD]
+%
+% \btxstartstyle[btx:apa:list:article:title]
+% \btxusecommand[btx:apa:list:article:title]{foo}
+% \btxstopstyle
+
+\let\savedcurrentbtx\empty
+
+\unexpanded\def\btxstartstyle[#1]%
+ {\begingroup
+ \let\savedcurrentbtx\currentbtx
+ \def\currentbtx{#1}%
+ \usebtxstyle\c!style
+ \let\currentbtx\savedcurrentbtx}
+
+\unexpanded\def\btxstartcolor[#1]%
+ {\begingroup
+ \let\savedcurrentbtx\currentbtx
+ \def\currentbtx{#1}%
+ \usebtxcolor\c!color
+ \let\currentbtx\savedcurrentbtx}
+
+\unexpanded\def\btxstartstyleandcolor[#1]%
+ {\begingroup
+ \let\savedcurrentbtx\currentbtx
+ \def\currentbtx{#1}%
+ \usebtxstyleandcolor\c!style\c!color
+ \let\currentbtx\savedcurrentbtx}
+
+\let\btxstopstyle \endgroup
+\let\btxstopcolor \endgroup
+\let\btxstopstyleandcolor\endgroup
+
+\unexpanded\def\btxusecommand[#1]#2% using #2 permits space after []
+ {\namedbtxparameter{#1}\c!command{#2}}
+
+%D Defaults:
+
+\setupbtxrendering
+ [\c!interaction=\v!start, % \v!all
+ \c!specification=\btxparameter\c!specification,
+ \c!dataset=\v!default,
+ \c!repeat=\v!no,
+ \c!continue=\v!no,
+ \c!method=\v!global,
+ % \c!setups=btx:\btxrenderingparameter\c!alternative:initialize, % not the same usage as cite !
+ \c!sorttype=\v!default,
+ \c!criterium=\v!text,
+ \c!refcommand=authoryears, % todo
+ \c!numbering=\v!yes,
+ %\c!saveinlist=\v!no, % maybe for before/after
+ \c!pagestate=\v!stop,
+ \c!textstate=\v!start,
+ \c!width=\v!auto,
+ \c!separator={\btxsemicolon},
+ \c!distance=1.5\emwidth]
+
+% Quite some interpunction and labels are the same of at least consistent within
+% a standard when citations and list entries are involved. We assume that each
+% standard defines its own set but it can fall back on these defaults.
+
+\setupbtx
+ [\c!interaction=\v!start,
+ \c!alternative=num, % default cite form, normally defined in the cite namespace
+ \c!inbetween=\btxspace,
+ \c!range=\endash, % separator:range?
+ \c!compress=\v!yes, % was no?
+ \c!authorconversion=normal,
+ \c!sorttype=normal, % normal, reverse or none
+ \c!etallimit=3,
+ \c!etaldisplay=\btxparameter\c!etallimit,
+ \c!otherstext={\btxspace et al.},
+ \c!separator:firstnames={\btxspace},
+ \c!separator:juniors={\btxspace},
+ \c!separator:vons={\btxspace},
+ \c!separator:initials={\btxspace},
+ \c!stopper:initials={.},
+ %\c!surnamesep={\btxcomma}, % is this used anywhere?
+ \c!separator:invertedinitials={\btxcomma},
+ \c!separator:invertedfirstnames={\btxcomma},
+ \c!separator:names:2={\btxcomma}, % separates multiple names
+ \c!separator:names:3=\btxparameter{\c!separator:2}, % before last name in a list
+ \c!separator:names:4=\btxparameter{\c!separator:2}, % between only two names
+ \c!separator:2={\btxsemicolon}, % aka pubsep - separates multiple objects
+ \c!separator:3=\btxparameter{separator:2}, % before last object in a list
+ \c!separator:4=\btxparameter{separator:2}] % between only two objects
+
+% Do we want these in the format? Loading them delayed is somewhat messy.
+
+\loadbtxdefinitionfile[commands]
+\loadbtxdefinitionfile[definitions]
+
+\loadbtxdefinitionfile[cite]
+\loadbtxdefinitionfile[list]
+\loadbtxdefinitionfile[page]
+\loadbtxdefinitionfile[author]
+
+% we assume that the users sets up the right specification and if not ... well,
+% hope for the best that something shows up and consult the manual otherwise
+
+\unexpanded\def\usebtxdefinitions[#1]%
+ {\loadbtxdefinitionfile[#1]% % for hh
+ \setupbtx[\c!specification=#1]} % for ab
+
+\setupbtx
+ [\c!specification=\s!default,
+ \c!dataset=\v!default,
+ \c!default=\v!default]
+
+\loadbtxdefinitionfile
+ [\s!default]
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-jrn.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-jrn.lua
new file mode 100644
index 00000000000..0cc41862f53
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-jrn.lua
@@ -0,0 +1,189 @@
+if not modules then modules = { } end modules ['publ-jrn'] = {
+ 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"
+}
+
+-- http://jabref.sourceforge.net/journals/journal_abbreviations_general.txt
+--
+-- <full name> = <abbreviation> [;shortest unique abbreviation[;frequency]].
+
+-- require("char-utf")
+
+-- Abhandlungen aus dem Westfälischen Museum für Naturkunde = Abh. Westfäl. Mus. Nat.kd.
+-- Abhandlungen der Naturforschenden Gesellschaft in Zürich = Abh. Nat.forsch. Ges. Zür.
+-- Abhandlungen des Naturwissenschaftlichen Vereins zu Bremen = Abh. Nat.wiss. Ver. Bremen
+
+local context = context
+local commands = commands
+
+local type = type
+local find = string.find
+local P, C, S, Cs, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cs, lpeg.match, lpeg.patterns
+
+local report_journals = logs.reporter("publications","journals")
+
+local publications = publications
+local journals = { }
+publications.journals = journals
+
+local lowercase = characters.lower
+
+local expansions = { }
+local abbreviations = { }
+local nofexpansions = 0
+local nofabbreviations = 0
+
+local valid = 1 - S([[ ."':;,-]])
+local pattern = Cs((valid^1 + P(1)/"")^1)
+
+local function simplify(name)
+ -- we have utf but it doesn't matter much if we lower the bytes
+ return name and lowercase(lpegmatch(pattern,name)) or name
+end
+
+local function add(expansion,abbreviation)
+ if expansion and abbreviation then
+ local se = simplify(expansion)
+ local sa = simplify(abbreviation)
+ if not expansions[sa] then
+ expansions[sa] = expansion
+ nofexpansions = nofexpansions + 1
+ end
+ if not abbreviations[se] then
+ abbreviations[se] = abbreviation
+ nofabbreviations = nofabbreviations + 1
+ end
+ end
+end
+
+-- [#%-] comment
+-- meaning = abbreviations [;.....]
+
+local whitespace = lpegpatterns.whitespace^0
+local assignment = whitespace * P("=") * whitespace
+local separator = P(";")
+local newline = lpegpatterns.newline
+local endofline = lpegpatterns.space^0 * (newline + P(-1) + separator)
+local restofline = (1-newline)^0
+local splitter = whitespace * C((1-assignment)^1) * assignment * C((1-endofline)^1) * restofline
+local comment = S("#-%") * restofline
+local pattern = (comment + splitter / add)^0
+
+function journals.load(filename)
+ if not filename then
+ return
+ end-- error
+ if file.suffix(filename,"txt") then
+ local data = io.loaddata(filename)
+ if type(data) ~= "string" then
+ return
+ elseif find(data,"=") then
+ -- expansion = abbreviation
+ lpegmatch(pattern,data)
+ end
+ elseif file.suffix(filename,"lua") then
+ local data = table.load(filename)
+ if type(data) ~= "table" then
+ return
+ else
+ local de = data.expansions
+ local da = data.abbreviations
+ if de and da then
+ -- { expansions = { a = e }, abbreviations = { e = a } }
+ if next(expansions) then
+ table.merge(expansions,de)
+ else
+ expansions = de
+ end
+ if next(abbreviations) then
+ table.merge(abbreviations,da)
+ else
+ abbreviations = da
+ end
+ elseif #data > 0 then
+ -- { expansion, abbreviation }, ... }
+ for i=1,#data do
+ local d = d[i]
+ add(d[1],d[2])
+ end
+ else
+ -- { expansion = abbreviation, ... }
+ for expansion, abbreviation in data do
+ add(expansion,abbreviation)
+ end
+ end
+ end
+ end
+ report_journals("file %a loaded, %s expansions, %s abbreviations",filename,nofexpansions,nofabbreviations)
+end
+
+function journals.save(filename)
+ table.save(filename,{ expansions = expansions, abbreviations = abbreviations })
+end
+
+function journals.add(expansion,abbreviation)
+ add(expansion,abbreviation)
+end
+
+function journals.expanded(name)
+ local s = simplify(name)
+ return expansions[s] or expansions[simplify(abbreviations[s])] or name
+end
+
+function journals.abbreviated(name)
+ local s = simplify(name)
+ return abbreviations[s] or abbreviations[simplify(expansions[s])] or name
+end
+
+local implement = interfaces and interfaces.implement
+
+if implement then
+
+ implement {
+ name = "btxloadjournallist",
+ arguments = "string",
+ actions = journals.load
+ }
+
+ implement {
+ name = "btxsavejournallist",
+ arguments = "string",
+ actions = journals.save
+ }
+
+ implement {
+ name = "btxaddjournal",
+ arguments = { "string", "string" },
+ actions = { journals.add, context }
+ }
+
+ implement {
+ name = "btxexpandedjournal",
+ arguments = "string",
+ actions = { journals.expanded, context },
+ }
+
+ implement {
+ name = "btxabbreviatedjournal",
+ arguments = "string",
+ actions = { journals.abbreviated, context },
+ }
+
+end
+
+-- journals.load("e:/tmp/journals.txt")
+-- journals.save("e:/tmp/journals.lua")
+
+-- inspect(journals.expanded ("Z. Ökol. Nat.schutz"))
+-- inspect(journals.abbreviated("Z. Ökol. Nat. schutz"))
+
+if typesetters then
+ typesetters.manipulators.methods.expandedjournal = journals.expanded
+ typesetters.manipulators.methods.abbreviatedjournal = journals.abbreviated
+end
+
+-- journals.load("t:/manuals/publications-mkiv/journals.txt")
+-- journals.save("t:/manuals/publications-mkiv/journals.lua")
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-old.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-old.mkiv
new file mode 100644
index 00000000000..f616428e6df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-old.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=publ-old,
+%D version=2013.12.24,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Old Fashioned \BIBTEX,
+%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
+
+% we could use runtime commands instead
+
+\unexpanded\def\setupbibtex {\usemodule[oldbibtex]\setupbibtex}
+\unexpanded\def\setuppublications {\usemodule[oldbibtex]\setuppublications}
+\unexpanded\def\setuppublicationlist{\usemodule[oldbibtex]\setuppublicationlist}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-oth.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-oth.lua
new file mode 100644
index 00000000000..55c62c31eba
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-oth.lua
@@ -0,0 +1,154 @@
+if not modules then modules = { } end modules ['publ-oth'] = {
+ 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 P, S, C, Ct, Cf, Cg, Cmt, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.Cmt, lpeg.Carg
+local lpegmatch = lpeg.match
+
+local p_endofline = lpeg.patterns.newline
+
+local publications = publications
+
+local loaders = publications.loaders
+local getindex = publications.getindex
+
+local function addfield(t,k,v,fields)
+ k = fields[k]
+ if k then
+ local tk = t[k]
+ if tk then
+ t[k] = tk .. " and " .. v
+ else
+ t[k] = v
+ end
+ end
+ return t
+end
+
+local function checkfield(_,_,t,categories,all)
+ local tag = t.tag
+ if tag then
+ local category = t.category
+ t.tag = nil
+ t.category = categories[category] or category
+ all[tag] = t
+ end
+ return true
+end
+
+-- endnotes --
+
+local fields = {
+ ["@"] = "tag",
+ ["0"] = "category",
+ ["A"] = "author",
+ ["E"] = "editor",
+ ["T"] = "title",
+ ["D"] = "year",
+ ["I"] = "publisher",
+}
+
+local categories = {
+ ["Journal Article"] = "article",
+}
+
+local entry = P("%") * Cg(C(1) * (S(" \t")^1) * C((1-p_endofline)^0) * Carg(1)) * p_endofline
+local record = Cf(Ct("") * (entry^1), addfield)
+local records = (Cmt(record * Carg(2) * Carg(3), checkfield) * P(1))^1
+
+function publications.endnotes_to_btx(data)
+ local all = { }
+ lpegmatch(records,data,1,fields,categories,all)
+ return all
+end
+
+function loaders.endnote(dataset,filename)
+ -- we could combine the next into checkfield but let's not create too messy code
+ local dataset, fullname = publications.resolvedname(dataset,filename)
+ if fullname then
+ loaders.lua(dataset,publications.endnotes_to_btx(io.loaddata(fullname) or ""))
+ end
+end
+
+-- refman --
+
+local entry = Cg(C((1-lpeg.S(" \t")-p_endofline)^1) * (S(" \t-")^1) * C((1-p_endofline)^0) * Carg(1)) * p_endofline
+local record = Cf(Ct("") * (entry^1), addfield)
+local records = (Cmt(record * Carg(2) * Carg(3), checkfield) * P(1))^1
+
+local fields = {
+ ["SN"] = "tag",
+ ["TY"] = "category",
+ ["A1"] = "author",
+ ["E1"] = "editor",
+ ["T1"] = "title",
+ ["Y1"] = "year",
+ ["PB"] = "publisher",
+}
+
+local categories = {
+ ["JOUR"] = "article",
+}
+
+function publications.refman_to_btx(data)
+ local all = { }
+ lpegmatch(records,data,1,fields,categories,all)
+ return all
+end
+
+function loaders.refman(dataset,filename)
+ -- we could combine the next into checkfield but let's not create too messy code
+ local dataset, fullname = publications.resolvedname(dataset,filename)
+ if fullname then
+ loaders.lua(dataset,publications.refman_to_btx(io.loaddata(fullname) or ""))
+ end
+end
+
+-- test --
+
+-- local endnote = [[
+-- %0 Journal Article
+-- %T Scientific Visualization, Overviews, Methodologies, and Techniques
+-- %A Nielson, Gregory M
+-- %A Hagen, Hans
+-- %A Müller, Heinrich
+-- %@ 0818677776
+-- %D 1994
+-- %I IEEE Computer Society
+--
+-- %0 Journal Article
+-- %T Scientific Visualization, Overviews, Methodologies, and Techniques
+-- %A Nielson, Gregory M
+-- %A Hagen, Hans
+-- %A Müller, Heinrich
+-- %@ 0818677775
+-- %D 1994
+-- %I IEEE Computer Society
+-- ]]
+--
+-- local refman = [[
+-- TY - JOUR
+-- T1 - Scientific Visualization, Overviews, Methodologies, and Techniques
+-- A1 - Nielson, Gregory M
+-- A1 - Hagen, Hans
+-- A1 - Müller, Heinrich
+-- SN - 0818677776
+-- Y1 - 1994
+-- PB - IEEE Computer Society
+--
+-- TY - JOUR
+-- T1 - Scientific Visualization, Overviews, Methodologies, and Techniques
+-- A1 - Nielson, Gregory M
+-- A1 - Hagen, Hans
+-- A1 - Müller, Heinrich
+-- SN - 0818677775
+-- Y1 - 1994
+-- PB - IEEE Computer Society
+-- ]]
+--
+-- inspect(publications.endnotes_to_btx(endnote))
+-- inspect(publications.refman_to_btx(refman))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-reg.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-reg.lua
new file mode 100644
index 00000000000..3f276b49abc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-reg.lua
@@ -0,0 +1,227 @@
+if not modules then modules = { } end modules ['publ-reg'] = {
+ 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 formatters = string.formatters
+local concat = table.concat
+local sortedhash = table.sortedhash
+local lpegmatch = lpeg.match
+
+local context = context
+
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+local v_once = variables.once
+local v_stop = variables.stop
+local v_all = variables.all
+
+local publications = publications
+local datasets = publications.datasets
+local specifications = publications.specifications
+local writers = publications.writers
+local getcasted = publications.getcasted
+
+local registrations = { }
+local sequence = { }
+local flushers = table.setmetatableindex(function(t,k) local v = t.default t[k] = v return v end)
+
+local function btxsetregister(specification)
+ local name = specification.name
+ local register = specification.register
+ local dataset = specification.dataset
+ local field = specification.field
+ if not field or field == "" or not register or register == "" then
+ return
+ end
+ if not dataset or dataset == "" then
+ dataset = v_all
+ end
+ -- could be metatable magic
+ local s = registrations[register]
+ if not s then
+ s = { }
+ registrations[register] = s
+ end
+ local processors = name ~= register and name or ""
+ if processor == "" then
+ processor = nil
+ elseif processor then
+ processor = "btx:r:" .. processor
+ end
+ local datasets = utilities.parsers.settings_to_array(dataset)
+ for i=1,#datasets do
+ local dataset = datasets[i]
+ local d = s[dataset]
+ if not d then
+ d = { }
+ s[dataset] = d
+ end
+ --
+ -- check all
+ --
+ d.active = specification.state ~= v_stop
+ d.once = specification.method == v_once or false
+ d.field = field
+ d.processor = processor
+ d.alternative = d.alternative or specification.alternative
+ d.register = register
+ d.dataset = dataset
+ d.done = d.done or { }
+ end
+ --
+ sequence = { }
+ for register, s in sortedhash(registrations) do
+ for dataset, d in sortedhash(s) do
+ if d.active then
+ sequence[#sequence+1] = d
+ end
+ end
+ end
+end
+
+local function btxtoregister(dataset,tag)
+ local current = datasets[dataset]
+ for i=1,#sequence do
+ local step = sequence[i]
+ local dset = step.dataset
+ if dset == v_all or dset == dataset then
+ local done = step.done
+ if not done[tag] then
+ local value, field, kind = getcasted(current,tag,step.field,specifications[step.specification])
+ if value then
+ flushers[kind](step,field,value)
+ end
+ done[tag] = true
+ end
+ end
+ end
+end
+
+implement {
+ name = "btxsetregister",
+ actions = btxsetregister,
+ arguments = {
+ {
+ { "specification" },
+ { "name" },
+ { "state" },
+ { "dataset" },
+ { "field" },
+ { "register" },
+ { "method" },
+ { "alternative" },
+ }
+ }
+}
+
+implement {
+ name = "btxtoregister",
+ actions = btxtoregister,
+ arguments = { "string", "string" }
+}
+
+-- context.setregisterentry (
+-- { register },
+-- {
+-- ["entries:1"] = value,
+-- ["keys:1"] = value,
+-- }
+-- )
+
+local ctx_dosetfastregisterentry = context.dosetfastregisterentry -- register entry key
+
+----- p_keywords = lpeg.tsplitat(lpeg.patterns.whitespace^0 * lpeg.P(";") * lpeg.patterns.whitespace^0)
+local components = publications.components.author
+local f_author = formatters[ [[\btxindexedauthor{%s}{%s}{%s}{%s}{%s}{%s}]] ]
+
+function flushers.string(step,field,value)
+ if type(value) == "string" and value ~= "" then
+ ctx_dosetfastregisterentry(step.register,value or "","",step.processor or "","")
+ end
+end
+
+flushers.default = flushers.string
+
+local shorts = {
+ normalshort = "normalshort",
+ invertedshort = "invertedshort",
+}
+
+function flushers.author(step,field,value)
+ if type(value) == "string" then
+ value = publications.authorcache[value]
+ end
+ if type(value) == "table" and #value > 0 then
+ local register = step.register
+ local processor = step.processor
+ local alternative = shorts[step.alternative or "invertedshort"] or "invertedshort"
+ for i=1,#value do
+ local a = value[i]
+ local k = writers[field] { a }
+ local e = f_author(alternative,components(a))
+ ctx_dosetfastregisterentry(register,e,k,processor or "","")
+ end
+ end
+end
+
+function flushers.keyword(step,field,value)
+ if type(value) == "table" and #value > 0 then
+ local register = step.register
+ local processor = step.processor
+ for i=1,#value do
+ ctx_dosetfastregisterentry(register,value[i],"",processor or "","")
+ end
+ end
+end
+
+-- publications.registerflushers = flushers
+
+local function btxtoregister(dataset,tag)
+ local current = datasets[dataset]
+ for i=1,#sequence do
+ local step = sequence[i]
+ local dset = step.dataset
+ if dset == v_all or dset == dataset then
+ local done = step.done
+ if not done[tag] then
+ local value, field, kind = getcasted(current,tag,step.field,specifications[step.specification])
+ if value then
+ flushers[kind](step,field,value)
+ end
+ done[tag] = true
+ end
+ end
+ end
+end
+
+local function authortoregister(dataset,hash)
+ local author = publications.authorcache[hash]
+ if author then
+ local current = datasets[dataset]
+ for i=1,#sequence do
+ local step = sequence[i]
+ local dset = step.dataset
+ if dset == v_all or dset == dataset then
+ local register = step.register
+ local processor = step.processor
+ local alternative = shorts[step.alternative or "invertedshort"] or "invertedshort"
+ local k = writers.author { author }
+ local e = f_author(alternative,components(author,short))
+ ctx_dosetfastregisterentry(register,e,k,processor or "","")
+ end
+ end
+ end
+end
+
+publications.authortoregister = authortoregister
+
+implement {
+ name = "btxauthortoregister",
+ actions = authortoregister,
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-sor.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-sor.lua
new file mode 100644
index 00000000000..218d1109356
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-sor.lua
@@ -0,0 +1,377 @@
+if not modules then modules = { } end modules ['publ-sor'] = {
+ 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"
+}
+
+-- if needed we can optimize this one: chekc if it's detail or something else
+-- and use direct access, but in practice it's fast enough
+
+local type = type
+local concat = table.concat
+local formatters = string.formatters
+local compare = sorters.comparers.basic -- (a,b)
+local sort = table.sort
+
+local toarray = utilities.parsers.settings_to_array
+local utfchar = utf.char
+
+local publications = publications
+local writers = publications.writers
+
+local variables = interfaces.variables
+local v_short = variables.short
+local v_default = variables.default
+local v_reference = variables.reference
+local v_dataset = variables.dataset
+local v_list = variables.list
+local v_index = variables.index
+local v_cite = variables.cite
+local v_used = variables.used
+
+local report = logs.reporter("publications","sorters")
+
+local trace_sorters = false trackers.register("publications.sorters",function(v) trace_sorters = v end)
+
+-- authors(s) | year | journal | title | pages
+
+local template = [[
+local type, tostring = type, tostring
+
+local writers = publications.writers
+local datasets = publications.datasets
+local getter = publications.getfaster -- (current,data,details,field,categories,types)
+local strip = sorters.strip
+local splitter = sorters.splitters.utf
+
+local function newsplitter(splitter)
+ return table.setmetatableindex({},function(t,k) -- could be done in the sorter but seldom that many shared
+ local v = splitter(k,true) -- in other cases
+ t[k] = v
+ return v
+ end)
+end
+
+return function(dataset,list,method) -- indexer
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local details = current.details
+ local specification = publications.currentspecification
+ local categories = specification.categories
+ local types = specification.types
+ local splitted = newsplitter(splitter) -- saves mem
+ local snippets = { } -- saves mem
+ local result = { }
+
+%helpers%
+
+ for i=1,#list do
+ -- either { tag, tag, ... } or { { tag, index }, { tag, index } }
+ local li = list[i]
+ local tag = type(li) == "string" and li or li[1]
+ local index = tostring(i)
+ local entry = luadata[tag]
+ if entry then
+ -- maybe optional: if entry.key then push the keygetter
+ -- in slot 1 and ignore (e.g. author)
+ local detail = details[tag]
+ result[i] = {
+ index = i,
+ split = {
+
+%getters%
+
+ },
+ }
+ else
+ result[i] = {
+ index = i,
+ split = {
+
+%unknowns%
+
+ },
+ }
+ end
+ end
+ return result
+end
+]]
+
+local f_getter = formatters["splitted[strip(getter(current,entry,detail,%q,categories,types) or %q)], -- %s"]
+local f_writer = formatters["splitted[strip(writer_%s(getter(current,entry,detail,%q,categories,types) or %q,snippets))], -- %s"]
+local f_helper = formatters["local writer_%s = writers[%q] -- %s: %s"]
+local f_value = formatters["splitted[%q], -- %s"]
+local s_index = "splitted[index], -- the order in the list, always added"
+
+-- there is no need to cache this in specification
+
+local sharedmethods = { }
+publications.sortmethods = sharedmethods
+
+local function sortsequence(dataset,list,sorttype)
+
+ if not list or #list == 0 then
+ return
+ end
+
+ local specification = publications.currentspecification
+ local types = specification.types
+ local sortmethods = specification.sortmethods
+ local method = sortmethods and sortmethods[sorttype] or sharedmethods[sorttype]
+ local sequence = method and method.sequence
+
+ local s_default = "<before end>"
+ local s_unknown = "<at the end>"
+
+ local c_default = utfchar(0xFFFE)
+ local c_unknown = utfchar(0xFFFF)
+
+ if not sequence and type(sorttype) == "string" then
+ local list = toarray(sorttype)
+ if #list > 0 then
+ local indexdone = false
+ sequence = { }
+ for i=1,#list do
+ local entry = toarray(list[i])
+ local field = entry[1]
+ local default = entry[2]
+ local unknown = entry[3] or default
+ sequence[i] = {
+ field = field,
+ default = default == s_default and c_default or default or c_default,
+ unknown = unknown == s_unknown and c_unknown or unknown or c_unknown,
+ }
+ if field == "index" then
+ indexdone = true
+ end
+ end
+ if not indexdone then
+ sequence[#sequence+1] = {
+ field = "index",
+ default = 0,
+ unknown = 0,
+ }
+ end
+ end
+ if trace_sorters then
+ report("creating sequence from method %a",sorttype)
+ end
+ end
+
+ if sequence then
+
+ local getters = { }
+ local unknowns = { }
+ local helpers = { }
+
+ if trace_sorters then
+ report("initializing method %a",sorttype)
+ end
+
+ for i=1,#sequence do
+ local step = sequence[i]
+ local field = step.field or "?"
+ local default = step.default or c_default
+ local unknown = step.unknown or c_unknown
+ local fldtype = types[field]
+ local fldwriter = step.writer or fldtype
+ local writer = fldwriter and writers[fldwriter]
+
+ if trace_sorters then
+ report("% 3i : field %a, type %a, default %a, unknown %a",i,field,fldtype,
+ default == c_default and s_default or default,
+ unknown == c_unknown and s_unknown or unknown
+ )
+ end
+
+ if writer then
+ local h = #helpers + 1
+ getters[i] = f_writer(h,field,default,field)
+ helpers[h] = f_helper(h,fldwriter,field,fldtype)
+ else
+ getters[i] = f_getter(field,default,field)
+ end
+ unknowns[i] = f_value(unknown,field)
+ end
+
+ unknowns[#unknowns+1] = s_index
+ getters [#getters +1] = s_index
+
+ local code = utilities.templates.replace(template, {
+ helpers = concat(helpers, "\n"),
+ getters = concat(getters, "\n"),
+ unknowns = concat(unknowns,"\n"),
+ })
+
+ -- print(code)
+
+ local action, error = loadstring(code)
+ if type(action) == "function" then
+ action = action()
+ else
+ report("error when compiling sort method %a: %s",sorttype,error or "unknown")
+ end
+ if type(action) == "function" then
+ local valid = action(dataset,list,method)
+ if valid and #valid > 0 then
+ sorters.sort(valid,compare)
+ return valid
+ else
+ report("error when applying sort method %a",sorttype)
+ end
+ else
+ report("error in sort method %a",sorttype)
+ end
+ else
+ report("invalid sort method %a",sorttype)
+ end
+
+end
+
+-- tag | listindex | reference | userdata | dataindex
+
+-- short : short + tag index
+-- dataset : index + tag
+-- list : list + index
+-- reference : tag + index
+-- used : reference + dataset
+-- authoryear : complex sort
+
+local sorters = { }
+
+sorters[v_short] = function(dataset,rendering,list) -- should we store it
+ local shorts = rendering.shorts
+ local function compare(a,b)
+ if a and b then
+ local taga = a[1]
+ local tagb = b[1]
+ if taga and tagb then
+ local shorta = shorts[taga]
+ local shortb = shorts[tagb]
+ if shorta and shortb then
+ -- assumes ascii shorts ... no utf yet
+ return shorta < shortb
+ end
+ -- fall back on tag order
+ return taga < tagb
+ end
+ -- fall back on dataset order
+ local indexa = a[5]
+ local indexb = b[5]
+ if indexa and indexb then
+ return indexa < indexb
+ end
+ end
+ return false
+ end
+ sort(list,compare)
+end
+
+sorters[v_dataset] = function(dataset,rendering,list) -- dataset index
+ local function compare(a,b)
+ if a and b then
+ local indexa = a[5]
+ local indexb = b[5]
+ if indexa and indexb then
+ return indexa < indexb
+ end
+ local taga = a[1]
+ local tagb = b[1]
+ if taga and tagb then
+ return taga < tagb
+ end
+ end
+ return false
+ end
+ sort(list,compare)
+end
+
+sorters[v_list] = function(dataset,rendering,list) -- list index (normally redundant)
+ local function compare(a,b)
+ if a and b then
+ local lista = a[2]
+ local listb = b[2]
+ if lista and listb then
+ return lista < listb
+ end
+ local indexa = a[5]
+ local indexb = b[5]
+ if indexa and indexb then
+ return indexa < indexb
+ end
+ end
+ return false
+ end
+ sort(list,compare)
+end
+
+sorters[v_reference] = function(dataset,rendering,list) -- tag
+ local function compare(a,b)
+ if a and b then
+ local taga = a[1]
+ local tagb = b[1]
+ if taga and tagb then
+ return taga < tagb
+ end
+ local indexa = a[5]
+ local indexb = b[5]
+ if indexa and indexb then
+ return indexa < indexb
+ end
+ end
+ return false
+ end
+ sort(list,compare)
+end
+
+sorters[v_used] = function(dataset,rendering,list) -- tag
+ local function compare(a,b)
+ if a and b then
+ local referencea = a[2]
+ local referenceb = b[2]
+ if referencea and referenceb then
+ return referencea < referenceb
+ end
+ local indexa = a[5]
+ local indexb = b[5]
+ if indexa and indexb then
+ return indexa < indexb
+ end
+ end
+ return false
+ end
+ sort(list,compare)
+end
+
+sorters[v_default] = sorters[v_list]
+sorters[""] = sorters[v_list]
+sorters[v_cite] = sorters[v_list]
+sorters[v_index] = sorters[v_dataset]
+
+local function anything(dataset,rendering,list,sorttype)
+ local valid = sortsequence(dataset,list,sorttype) -- field order
+ if valid and #valid > 0 then
+ -- hm, we have a complication here because a sortsequence doesn't know if there's a field
+ -- so there is no real catch possible here .., anyway, we add a index as last entry when no
+ -- one is set so that should be good enough (needs testing)
+ for i=1,#valid do
+ local v = valid[i]
+ valid[i] = list[v.index]
+ end
+ return valid
+ end
+end
+
+table.setmetatableindex(sorters,function(t,k) return anything end)
+
+publications.lists.sorters = sorters
+
+-- publications.sortmethods.key = {
+-- sequence = {
+-- { field = "key", default = "", unknown = "" },
+-- { field = "index", default = "", unknown = "" },
+-- },
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-tra.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-tra.lua
new file mode 100644
index 00000000000..4b03307acc2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-tra.lua
@@ -0,0 +1,504 @@
+if not modules then modules = { } end modules ['publ-tra'] = {
+ 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"
+}
+
+-- todo: use context.tt .. more efficient, less code
+
+local next, type = next, type
+
+local sortedhash = table.sortedhash
+local sortedkeys = table.sortedkeys
+local settings_to_array = utilities.parsers.settings_to_array
+local formatters = string.formatters
+local concat = table.concat
+
+local context = context
+local commands = commands
+
+local v_default = interfaces.variables.default
+
+local publications = publications
+local tracers = publications.tracers
+local tables = publications.tables
+local datasets = publications.datasets
+local specifications = publications.specifications
+local citevariants = publications.citevariants
+
+local getfield = publications.getfield
+local getcasted = publications.getcasted
+
+local ctx_NC, ctx_NR, ctx_HL, ctx_FL, ctx_ML, ctx_LL, ctx_EQ = context.NC, context.NR, context.HL, context.FL, context.ML, context.LL, context.EQ
+
+local ctx_starttabulate = context.starttabulate
+local ctx_stoptabulate = context.stoptabulate
+
+local ctx_formatted = context.formatted
+local ctx_bold = ctx_formatted.monobold
+local ctx_monobold = ctx_formatted.monobold
+local ctx_verbatim = ctx_formatted.verbatim
+
+local ctx_rotate = context.rotate
+local ctx_llap = context.llap
+local ctx_rlap = context.rlap
+local ctx_page = context.page
+
+local privates = tables.privates
+local specials = tables.specials
+
+local report = logs.reporter("publications","tracers")
+
+function tracers.showdatasetfields(settings)
+ local dataset = settings.dataset
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local specification = settings.specification
+ local fielddata = specification and specifications[specification] or specifications.apa
+ local categories = fielddata.categories
+ if next(luadata) then
+ ctx_starttabulate { "|lT|lT|pTl|" }
+ ctx_NC() ctx_bold("tag")
+ ctx_NC() ctx_bold("category")
+ ctx_NC() ctx_bold("fields")
+ ctx_NC() ctx_NR()
+ ctx_FL()
+ for tag, entry in sortedhash(luadata) do
+ local category = entry.category
+ local catedata = categories[category]
+ local fields = catedata and catedata.fields or { }
+ ctx_NC() context(tag)
+ ctx_NC() context(category)
+ ctx_NC() -- grouping around colors needed
+ for key, value in sortedhash(entry) do
+ if privates[key] then
+ -- skip
+ elseif specials[key] then
+ context("{\\darkblue %s} ",key)
+ else
+ local kind = fields[key]
+ if kind == "required" then
+ context("{\\darkgreen %s} ",key)
+ elseif kind == "optional" then
+ context("%s ",key)
+ else
+ context("{\\darkyellow %s} ",key)
+ end
+ end
+ end
+ ctx_NC() ctx_NR()
+ end
+ ctx_stoptabulate()
+ end
+end
+
+function tracers.showdatasetcompleteness(settings)
+ local dataset = settings.dataset
+ local current = datasets[dataset]
+ local luadata = current.luadata
+ local specification = settings.specification
+ local fielddata = specification and specifications[specification] or specifications.apa
+ local categories = fielddata.categories
+
+ -- local lpegmatch = lpeg.match
+ -- local texescape = lpeg.patterns.texescape
+
+ local preamble = { "|lTBw(5em)|lBTp(10em)|plT|" }
+
+ local function identified(tag,category,crossref,index)
+ ctx_NC() ctx_monobold(index)
+ ctx_NC() ctx_monobold(category)
+ ctx_NC() if crossref then
+ ctx_monobold("%s\\hfill\\darkblue => %s",tag,crossref)
+ else
+ ctx_monobold(tag)
+ end
+ ctx_NC() ctx_NR()
+ end
+
+ local function required(done,foundfields,key,value,indirect)
+ ctx_NC() if not done then ctx_monobold("required") end
+ ctx_NC() context(key)
+ ctx_NC()
+ if indirect then
+ if value then
+ context("\\darkblue")
+ ctx_verbatim(value)
+ else
+ context("\\darkred\\tttf [missing crossref]")
+ end
+ elseif value then
+ ctx_verbatim(value)
+ else
+ context("\\darkred\\tttf [missing value]")
+ end
+ ctx_NC() ctx_NR()
+ foundfields[key] = nil
+ return done or true
+ end
+
+ local function optional(done,foundfields,key,value,indirect)
+ ctx_NC() if not done then ctx_monobold("optional") end
+ ctx_NC() context(key)
+ ctx_NC()
+ if indirect then
+ context("\\darkblue")
+ ctx_verbatim(value)
+ elseif value then
+ ctx_verbatim(value)
+ end
+ ctx_NC() ctx_NR()
+ foundfields[key] = nil
+ return done or true
+ end
+
+ local function special(done,key,value)
+ ctx_NC() if not done then ctx_monobold("special") end
+ ctx_NC() context(key)
+ ctx_NC() ctx_verbatim(value)
+ ctx_NC() ctx_NR()
+ return done or true
+ end
+
+ local function extra(done,key,value)
+ ctx_NC() if not done then ctx_monobold("extra") end
+ ctx_NC() context(key)
+ ctx_NC() ctx_verbatim(value)
+ ctx_NC() ctx_NR()
+ return done or true
+ end
+
+ if next(luadata) then
+ for tag, entry in sortedhash(luadata) do
+ local category = entry.category
+ local fields = categories[category]
+ local foundfields = { }
+ for k, v in next, entry do
+ foundfields[k] = true
+ end
+ ctx_starttabulate(preamble)
+ identified(tag,category,entry.crossref,entry.index)
+ ctx_FL()
+ if fields then
+ local requiredfields = fields.required
+ local sets = fields.sets or { }
+ local done = false
+ if requiredfields then
+ for i=1,#requiredfields do
+ local r = requiredfields[i]
+ local r = sets[r] or r
+ if type(r) == "table" then
+ local okay = false
+ for i=1,#r do
+ local ri = r[i]
+ if rawget(entry,ri) then
+ done = required(done,foundfields,ri,entry[ri])
+ okay = true
+ elseif entry[ri] then
+ done = required(done,foundfields,ri,entry[ri],true)
+ okay = true
+ end
+ end
+ if not okay then
+ done = required(done,foundfields,table.concat(r," {\\letterbar} "))
+ end
+ elseif rawget(entry,r) then
+ done = required(done,foundfields,r,entry[r])
+ elseif entry[r] then
+ done = required(done,foundfields,r,entry[r],true)
+ else
+ done = required(done,foundfields,r)
+ end
+ end
+ end
+ local optionalfields = fields.optional
+ local done = false
+ if optionalfields then
+ for i=1,#optionalfields do
+ local o = optionalfields[i]
+ local o = sets[o] or o
+ if type(o) == "table" then
+ for i=1,#o do
+ local oi = o[i]
+ if rawget(entry,oi) then
+ done = optional(done,foundfields,oi,entry[oi])
+ elseif entry[oi] then
+ done = optional(done,foundfields,oi,entry[oi],true)
+ end
+ end
+ elseif rawget(entry,o) then
+ done = optional(done,foundfields,o,entry[o])
+ elseif entry[o] then
+ done = optional(done,foundfields,o,entry[o],true)
+ end
+ end
+ end
+ end
+ local done = false
+ for k, v in sortedhash(foundfields) do
+ if privates[k] then
+ -- skip
+ elseif specials[k] then
+ done = special(done,k,entry[k])
+ end
+ end
+ local done = false
+ for k, v in sortedhash(foundfields) do
+ if privates[k] then
+ -- skip
+ elseif not specials[k] then
+ done = extra(done,k,entry[k])
+ end
+ end
+ ctx_stoptabulate()
+ end
+ end
+
+end
+
+function tracers.showfields(settings)
+ local rotation = settings.rotation
+ local specification = settings.specification
+ local fielddata = specification and specifications[specification] or specifications.apa
+ local categories = fielddata.categories
+ local validfields = { }
+ for category, data in next, categories do
+ local sets = data.sets
+ local fields = data.fields
+ for name, list in next, fields do
+ validfields[name] = true
+ end
+ end
+ local s_categories = sortedkeys(categories)
+ local s_fields = sortedkeys(validfields)
+ ctx_starttabulate { "|l" .. string.rep("|c",#s_categories) .. "|" }
+ ctx_FL()
+ ctx_NC()
+ if rotation then
+ rotation = { rotation = rotation }
+ end
+ for i=1,#s_categories do
+ ctx_NC()
+ local txt = formatters["\\bf %s"](s_categories[i])
+ if rotation then
+ ctx_rotate(rotation,txt)
+ else
+ context(txt)
+ end
+ end
+ ctx_NC() ctx_NR()
+ ctx_FL()
+ for i=1,#s_fields do
+ local field = s_fields[i]
+ ctx_NC()
+ ctx_bold(field)
+ for j=1,#s_categories do
+ ctx_NC()
+ local kind = categories[s_categories[j]].fields[field]
+ if kind == "required" then
+ context("\\darkgreen*")
+ elseif kind == "optional" then
+ context("*")
+ end
+ end
+ ctx_NC() ctx_NR()
+ end
+ ctx_LL()
+ ctx_stoptabulate()
+end
+
+function tracers.showtables(settings)
+ for name, list in sortedhash(tables) do
+ ctx_starttabulate { "|Tl|Tl|" }
+ ctx_FL()
+ ctx_NC()
+ ctx_rlap(function() ctx_bold(name) end)
+ ctx_NC()
+ ctx_NC()
+ ctx_NR()
+ ctx_FL()
+ for k, v in sortedhash(list) do
+ ctx_NC()
+ context(k)
+ ctx_NC()
+ if type(v) == "table" then
+ context("% t",v)
+ else
+ context(tostring(v))
+ end
+ ctx_NC()
+ ctx_NR()
+ end
+ ctx_LL()
+ ctx_stoptabulate()
+ end
+end
+
+function tracers.showdatasetauthors(settings)
+
+ local dataset = settings.dataset
+ local field = settings.field
+
+ local sortkey = publications.writers.author
+
+ if not dataset or dataset == "" then dataset = v_default end
+ if not field or field == "" then field = "author" end
+
+ local function row(i,k,v)
+ ctx_NC()
+ if i then
+ ctx_verbatim(i)
+ end
+ ctx_NC()
+ ctx_verbatim(k)
+ ctx_EQ()
+ if type(v) == "table" then
+ local t = { }
+ for i=1,#v do
+ local vi = v[i]
+ if type(vi) == "table" then
+ t[i] = concat(vi,"-")
+ else
+ t[i] = vi
+ end
+ end
+ ctx_verbatim(concat(t, " | "))
+ else
+ ctx_verbatim(v)
+ end
+ ctx_NC()
+ ctx_NR()
+ end
+
+ local function authorrow(ai,k,i)
+ local v = ai[k]
+ if v then
+ row(i,k,v)
+ end
+ end
+
+ local function commonrow(key,value)
+ ctx_NC() ctx_rlap(function() ctx_verbatim(key) end)
+ ctx_NC()
+ ctx_EQ() ctx_verbatim(value)
+ ctx_NC() ctx_NR()
+ end
+
+ local d = datasets[dataset].luadata
+
+ local trialtypesetting = context.trialtypesetting()
+
+ for tag, entry in sortedhash(d) do
+
+ local a, f, k = getcasted(dataset,tag,field)
+
+ if type(a) == "table" and #a > 0 and k == "author" then
+ context.start()
+ context.tt()
+ ctx_starttabulate { "|B|Bl|p|" }
+ ctx_FL()
+ local original = getfield(dataset,tag,field)
+ commonrow("tag",tag)
+ commonrow("field",field)
+ commonrow("original",original)
+ commonrow("sortkey",sortkey(a))
+ for i=1,#a do
+ ctx_ML()
+ local ai = a[i]
+ if ai then
+ authorrow(ai,"original",i)
+ authorrow(ai,"snippets")
+ authorrow(ai,"initials")
+ authorrow(ai,"firstnames")
+ authorrow(ai,"vons")
+ authorrow(ai,"surnames")
+ authorrow(ai,"juniors")
+ local options = ai.options
+ if options then
+ row(false,"options",sortedkeys(options))
+ end
+ elseif not trialtypesetting then
+ report("bad author name: %s",original or "?")
+ end
+ end
+ ctx_LL()
+ ctx_stoptabulate()
+ context.stop()
+ end
+
+ end
+
+end
+
+function tracers.showentry(dataset,tag)
+ local dataset = datasets[dataset]
+ if dataset then
+ local entry = dataset.luadata[tag]
+ local done = false
+ for k, v in sortedhash(entry) do
+ if not privates[k] then
+ ctx_verbatim("%w[%s: %s]",done and 1 or 0,k,v)
+ done = true
+ end
+ end
+ end
+end
+
+local skipped = { index = true, default = true }
+
+function tracers.showvariants(dataset,pages)
+ local variants = sortedkeys(citevariants)
+ for tag in publications.sortedentries(dataset or v_default) do
+ if pages then
+ ctx_page()
+ end
+ ctx_starttabulate { "|T||" }
+ for i=1,#variants do
+ local variant = variants[i]
+ if not skipped[variant] then
+ ctx_NC() context(variant)
+ -- ctx_EQ() citevariants[variant] { dataset = v_default, reference = tag, variant = variant }
+ ctx_EQ() context.cite({variant},{dataset .. "::" .. tag})
+ ctx_NC() ctx_NR()
+ end
+ end
+ ctx_stoptabulate()
+ if pages then
+ ctx_page()
+ end
+ end
+end
+
+function tracers.showhashedauthors(dataset,pages)
+ local components = publications.components.author
+ ctx_starttabulate { "|T|T|T|T|T|T|" }
+ ctx_NC() ctx_bold("hash")
+ ctx_NC() ctx_bold("vons")
+ ctx_NC() ctx_bold("surnames")
+ ctx_NC() ctx_bold("initials")
+ ctx_NC() ctx_bold("firstnames")
+ ctx_NC() ctx_bold("juniors")
+ ctx_NC() ctx_NR() ctx_HL()
+ for hash, data in sortedhash(publications.authorcache) do
+ local vons, surnames, initials, firstnames, juniors = components(data)
+ ctx_NC() context(hash)
+ ctx_NC() context(vons)
+ ctx_NC() context(surnames)
+ ctx_NC() context(initials)
+ ctx_NC() context(firstnames)
+ ctx_NC() context(juniors)
+ ctx_NC() ctx_NR()
+ end
+ ctx_stoptabulate()
+end
+
+commands.showbtxdatasetfields = tracers.showdatasetfields
+commands.showbtxdatasetcompleteness = tracers.showdatasetcompleteness
+commands.showbtxfields = tracers.showfields
+commands.showbtxtables = tracers.showtables
+commands.showbtxdatasetauthors = tracers.showdatasetauthors
+commands.showbtxhashedauthors = tracers.showhashedauthors
+commands.showbtxentry = tracers.showentry
+commands.showbtxvariants = tracers.showvariants
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-tra.mkiv
new file mode 100644
index 00000000000..6ef86ca5944
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-tra.mkiv
@@ -0,0 +1,87 @@
+%D \module
+%D [ file=publ-tra,
+%D version=2013.12.24,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=Tracing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: make this a runtime module
+% todo: use the module interface
+
+\writestatus{loading}{ConTeXt Publication Support / Tracing}
+
+\registerctxluafile{publ-tra}{1.001}
+
+\unprotect
+
+\unexpanded\def\showbtxdatasetfields {\dosingleempty\publ_show_dataset_fields}
+\unexpanded\def\showbtxdatasetcompleteness{\dosingleempty\publ_show_dataset_completeness}
+\unexpanded\def\showbtxdatasetauthors {\dosingleempty\publ_show_dataset_authors}
+\unexpanded\def\showbtxhashedauthors {\dosingleempty\publ_show_hashed_authors}
+\unexpanded\def\showbtxfields {\dosingleempty\publ_show_fields}
+\unexpanded\def\showbtxtables {\dosingleempty\publ_show_tables}
+
+\def\publ_show_dataset_whatever#1[#2]%
+ {\begingroup
+ \letdummyparameter\c!specification\currentbtxspecification
+ \setdummyparameter\c!dataset {\currentbtxdataset}%
+ \letdummyparameter\c!field \empty
+ \iffirstargument
+ \doifelseassignment{#2}
+ {\getdummyparameters[#2]}%
+ {\setdummyparameter\c!dataset{#2}}%
+ \else
+ \getdummyparameters[#2]%
+ \fi
+ \ctxcommand{#1{
+ dataset = "\dummyparameter\c!dataset",
+ specification = "\dummyparameter\c!specification",
+ field = "\dummyparameter\c!field",
+ }}%
+ \endgroup}
+
+\def\publ_show_dataset_fields {\publ_show_dataset_whatever{showbtxdatasetfields}}
+\def\publ_show_dataset_completeness{\publ_show_dataset_whatever{showbtxdatasetcompleteness}}
+\def\publ_show_dataset_authors {\publ_show_dataset_whatever{showbtxdatasetauthors}}
+
+\def\publ_show_fields[#1]%
+ {\begingroup
+ \setdummyparameter\c!rotation{90}%
+ \doifelseassignment{#1}%
+ {\letdummyparameter\c!specification\currentbtxspecification
+ \getdummyparameters[#1]}%
+ {\doifelsenothing{#1}%
+ {\letdummyparameter\c!specification\currentbtxspecification}%
+ {\setdummyparameter\c!specification{#1}}}%
+ \ctxcommand{showbtxfields{
+ rotation = "\dummyparameter\c!rotation",
+ specification = "\dummyparameter\c!specification"
+ }}%
+ \endgroup}
+
+\def\publ_show_tables[#1]%
+ {\begingroup
+ \ctxcommand{showbtxtables{}}%
+ \endgroup}
+
+\def\publ_show_hashed_authors[#1]%
+ {\ctxcommand{showbtxhashedauthors{}}}
+
+\protect
+
+\continueifinputfile{publ-tra.mkiv}
+
+\starttext
+
+ \showbtxfields[rotation=85] \page
+ \showbtxfields[rotation=90] \page
+
+ \showbtxtables \page
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-usr.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-usr.lua
new file mode 100644
index 00000000000..901f116296c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-usr.lua
@@ -0,0 +1,128 @@
+if not modules then modules = { } end modules ['publ-usr'] = {
+ 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 P, Cs, R, Cc, C, Carg = lpeg.P, lpeg.Cs, lpeg.R, lpeg.Cc, lpeg.C, lpeg.Carg
+local lpegmatch = lpeg.match
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local publications = publications
+local datasets = publications.datasets
+
+local report = logs.reporter("publications")
+local trace = false trackers.register("publications",function(v) trace = v end)
+
+-- local str = [[
+-- \startpublication[k=Berdnikov:TB21-2-129,t=article,a={{Berdnikov},{}},y=2000,n=2257,s=BHHJ00]
+-- \artauthor[]{Alexander}[A.]{}{Berdnikov}
+-- \artauthor[]{Hans}[H.]{}{Hagen}
+-- \artauthor[]{Taco}[T.]{}{Hoekwater}
+-- \artauthor[]{Bogus{\l}aw}[B.]{}{Jackowski}
+-- \pubyear{2000}
+-- \arttitle{{Even more MetaFun with \MP: A request for permission}}
+-- \journal{TUGboat}
+-- \issn{0896-3207}
+-- \volume{21}
+-- \issue{2}
+-- \pages{129--130}
+-- \month{6}
+-- \stoppublication
+-- ]]
+
+local lists = {
+ author = true,
+ editor = true,
+ -- artauthor = true,
+ -- arteditor = true,
+}
+
+local function registervalue(target,key,value)
+ target[key] = value
+end
+
+-- Instead of being generic we just hardcode the old stuff:
+
+local function registerauthor(target,key,juniors,firstnames,initials,vons,surnames)
+ local value = target[key]
+ target[key]= ((value and value .. " and {") or "{") ..
+ vons .. "},{" ..
+ surnames .. "},{" ..
+ juniors .. "},{" ..
+ firstnames .. "},{" ..
+ initials .. "}"
+end
+
+local leftbrace = P("{")
+local rightbrace = P("}")
+local leftbracket = P("[")
+local rightbracket = P("]")
+local backslash = P("\\")
+local letter = R("az","AZ")
+
+local skipspaces = lpeg.patterns.whitespace^0
+local key = Cs(letter^1)
+local value = leftbrace * Cs(lpeg.patterns.balanced) * rightbrace
+local optional = leftbracket * Cs((1-rightbracket)^0) * rightbracket
+
+local authorkey = (P("artauthor") + P("author")) / "author"
+ + (P("arteditor") + P("editor")) / "editor"
+local authorvalue = (optional + Cc("{}")) * skipspaces -- [juniors]
+ * (value + Cc("{}")) * skipspaces -- {firstnames}
+ * (optional + Cc("{}")) * skipspaces -- [initials]
+ * (value + Cc("{}")) * skipspaces -- {vons}
+ * (value + Cc("{}")) * skipspaces -- {surnames}
+
+local keyvalue = Carg(1) * authorkey * skipspaces * authorvalue / registerauthor
+ + Carg(1) * key * skipspaces * value / registervalue
+
+local pattern = (backslash * keyvalue + P(1))^0
+
+local function addtexentry(dataset,settings,content)
+ local current = datasets[dataset]
+ local settings = settings_to_hash(settings)
+ local data = {
+ tag = settings.tag or settings.k or "no tag",
+ category = settings.category or settings.t or "article",
+ }
+ lpegmatch(pattern,content,1,data) -- can set tag too
+ local tag = data.tag
+ local index = publications.getindex(dataset,current.luadata,tag)
+ current.ordered[index] = data
+ current.luadata[tag] = data
+ current.userdata[tag] = data
+ current.details[tag] = nil
+ return data
+end
+
+local pattern = ( Carg(1)
+ * P("\\startpublication")
+ * skipspaces
+ * optional
+ * C((1 - P("\\stoppublication"))^1)
+ * P("\\stoppublication") / addtexentry
+ + P("%") * (1-lpeg.patterns.newline)^0
+ + P(1)
+)^0
+
+function publications.loaders.bbl(dataset,filename)
+ local dataset, fullname = publications.resolvedname(dataset,filename)
+ if not fullname then
+ return
+ end
+ local data = io.loaddata(filename) or ""
+ if data == "" then
+ report("empty file %a, nothing loaded",fullname)
+ return
+ end
+ if trace then
+ report("loading file %a",fullname)
+ end
+ lpegmatch(pattern,data,1,dataset)
+end
+
+publications.addtexentry = addtexentry
+commands.addbtxentry = addtexentry
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-usr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-usr.mkiv
new file mode 100644
index 00000000000..cb078f424d5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-usr.mkiv
@@ -0,0 +1,2 @@
+% todo
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-xml.mkiv
new file mode 100644
index 00000000000..96375b9cc61
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/publ-xml.mkiv
@@ -0,0 +1,114 @@
+%D \module
+%D [ file=publ-xml,
+%D version=2013.12.24,
+%D title=\CONTEXT\ Publication Support,
+%D subtitle=XML,
+%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 Support / XML}
+
+\unprotect
+
+\unexpanded\def\convertbtxdatasettoxml
+ {\dosingleempty\publ_convert_to_xml}
+
+\def\publ_convert_to_xml[#1]%
+ {\clf_convertbtxdatasettoxml{\iffirstargument#1\else\s!default\fi}} % or current when not empty
+
+% \startxmlsetups btx:initialize
+% \xmlregistereddocumentsetups{#1}{}
+% \xmlsetsetup{#1}{bibtex|entry|field}{btx:*}
+% \xmlmain{#1}
+% \stopxmlsetups
+
+\startxmlsetups btx:initialize
+ \xmlsetsetup{#1}{bibtex|entry|field}{btx:*}
+ \xmlmain{#1}
+\stopxmlsetups
+
+% \startxmlsetups btx:entry
+% \xmlflush{#1}
+% \stopxmlsetups
+
+\startxmlsetups btx:field
+ \xmlflushcontext{#1}
+\stopxmlsetups
+
+\protect \endinput
+
+% \startxmlsetups bibtex:entry:getkeys
+% \xmladdsortentry{bibtex}{#1}{\xmlfilter{#1}{/field[@name='author']/text()}}
+% \xmladdsortentry{bibtex}{#1}{\xmlfilter{#1}{/field[@name='year' ]/text()}}
+% \xmladdsortentry{bibtex}{#1}{\xmlatt{#1}{tag}}
+% \stopxmlsetups
+
+% \startbuffer
+% \startxmlsetups xml:bibtex:sorter
+% \xmlresetsorter{bibtex}
+% % \xmlfilter{#1}{entry/command(bibtex:entry:getkeys)}
+% \xmlfilter{#1}{
+% bibtex
+% /entry[@category='article']
+% /field[@name='author' and find(text(),'Knuth')]
+% /../command(bibtex:entry:getkeys)}
+% \xmlsortentries{bibtex}
+% \xmlflushsorter{bibtex}{bibtex:entry:flush}
+% \stopxmlsetups
+% \stopbuffer
+
+% \bgroup
+% \setups[bibtex-commands]
+% \getbuffer
+% \egroup
+
+% \startxmlsetups bibtex:entry:flush
+% \xmlfilter{#1}{/field[@name='author']/context()} / %
+% \xmlfilter{#1}{/field[@name='year' ]/context()} / %
+% \xmlatt{#1}{tag}\par
+% \stopxmlsetups
+
+% \startpacked
+% \getbuffer
+% \stoppacked
+
+
+% \unexpanded\def\btx_xml_list_handle_entry
+% {\begingroup
+% \ignorespaces
+% \xmlfilter{btx:\currentbtxrendering}{/bibtex/entry[@tag='\currentbtxtag']/command(btx:format)}%
+% \removeunwantedspaces
+% \endgroup}
+
+% \startxmlsetups btx:format
+% \btxlistparameter\c!before\relax % prevents lookahead
+% \edef\currentbibxmlnode {#1}
+% \edef\currentbibxmltag {\xmlatt{#1}{tag}}
+% \edef\currentbtxcategory{\xmlatt{#1}{category}}
+% \ignorespaces
+% \xmlcommand{#1}{.}{btx:\currentbtxformat:\currentbibxmlcategory}
+% \removeunwantedspaces
+% \btxlistparameter\c!after\relax % prevents lookahead
+% \stopxmlsetups
+
+% \startxmlsetups btx:list
+% \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)}
+% \stopxmlsetups
+
+% \startxmlsetups btx:btx
+% \xmlfilter{#1}{/entry/command(btx:format)}
+% \stopxmlsetups
+
+% \unexpanded\def\btx_xml_doifelse#1{\xmldoifelse\currentbibxmlnode{/field[@name='#1']}}
+% \unexpanded\def\btx_xml_doif #1{\xmldoif \currentbibxmlnode{/field[@name='#1']}}
+% \unexpanded\def\btx_xml_doifnot #1{\xmldoifnot \currentbibxmlnode{/field[@name='#1']}}
+% \def\btx_xml_flush #1{\xmlcontext \currentbibxmlnode{/field[@name='#1']}}
+% \def\btx_xml_setup {\xmlsetup \currentbibxmlnode} % {#1}
+% \unexpanded\def\btx_xml_todo #1{[#1]}
+
+% \xmlfilter{#1}{/field[@name='\currentbtxfield']/btxconcat('\currentbtxfield')}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-1.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-1.lua
new file mode 100644
index 00000000000..ff2182afa2c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-1.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-1'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-10.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-10.lua
new file mode 100644
index 00000000000..f23744b4a24
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-10.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-10'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
+ 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-11.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-11.lua
new file mode 100644
index 00000000000..54e5626c28f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-11.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-11'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+ 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+ 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+ 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
+ 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+ 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-13.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-13.lua
new file mode 100644
index 00000000000..1646133b5ae
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-13.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-13'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-14.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-14.lua
new file mode 100644
index 00000000000..2b0c6881445
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-14.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-14'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
+ 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-15.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-15.lua
new file mode 100644
index 00000000000..48861f39690
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-15.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-15'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-16.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-16.lua
new file mode 100644
index 00000000000..e122a2042a4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-16.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-16'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
+ 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-2.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-2.lua
new file mode 100644
index 00000000000..affd6c3ca20
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-2.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-2'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
+ 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-3.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-3.lua
new file mode 100644
index 00000000000..4b5c54b4fbb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-3.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-3'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
+ 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-4.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-4.lua
new file mode 100644
index 00000000000..774ec2e1056
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-4.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-4'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
+ 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
+ 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
+ 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-5.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-5.lua
new file mode 100644
index 00000000000..1137f37bb2e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-5.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-5'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-6.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-6.lua
new file mode 100644
index 00000000000..651ae79ffe6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-6.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-6'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0000, 0x0000, 0x0000, 0x00A4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060C, 0x00AD, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061B, 0x0000, 0x0000, 0x0000, 0x061F,
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
+ 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-7.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-7.lua
new file mode 100644
index 00000000000..08cbbab6edf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-7.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-7'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-8.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-8.lua
new file mode 100644
index 00000000000..b6960999174
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-8.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-8'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-8859-9.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-9.lua
new file mode 100644
index 00000000000..773307fff09
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-8859-9.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-8859-9'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1250.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1250.lua
new file mode 100644
index 00000000000..00d55d1b83f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1250.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1250'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
+ 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
+ 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1251.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1251.lua
new file mode 100644
index 00000000000..7bb72e0ccab
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1251.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1251'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
+ 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
+ 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
+ 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1252.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1252.lua
new file mode 100644
index 00000000000..86954c9af36
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1252.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1252'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1253.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1253.lua
new file mode 100644
index 00000000000..31a411efeec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1253.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1253'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1254.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1254.lua
new file mode 100644
index 00000000000..73b9927c6ca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1254.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1254'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1255.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1255.lua
new file mode 100644
index 00000000000..2abb16b54e7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1255.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1255'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1256.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1256.lua
new file mode 100644
index 00000000000..a0697c321c4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1256.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1256'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
+ 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
+ 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
+ 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643,
+ 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
+ 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1257.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1257.lua
new file mode 100644
index 00000000000..6e39c10d4bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1257.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1257'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
+ 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-cp1258.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1258.lua
new file mode 100644
index 00000000000..cf64d2ab629
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-cp1258.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-cp1258'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-demo.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-demo.lua
new file mode 100644
index 00000000000..689f44e32c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-demo.lua
@@ -0,0 +1,22 @@
+if not modules then modules = { } end modules ['regi-demo'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- digits -> *
+
+return {
+ [0x0030] = 0x002A,
+ [0x0031] = 0x002A,
+ [0x0032] = 0x002A,
+ [0x0033] = 0x002A,
+ [0x0034] = 0x002A,
+ [0x0035] = 0x002A,
+ [0x0036] = 0x002A,
+ [0x0037] = 0x002A,
+ [0x0038] = 0x002A,
+ [0x0039] = 0x002A,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-ini.lua
new file mode 100644
index 00000000000..37a88fd5f96
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-ini.lua
@@ -0,0 +1,436 @@
+if not modules then modules = { } end modules ['regi-ini'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>Regimes take care of converting the input characters into
+<l n='utf'/> sequences. The conversion tables are loaded at
+runtime.</p>
+--ldx]]--
+
+local commands, context = commands, context
+
+local utfchar = utf.char
+local P, Cs, Cc, lpegmatch = lpeg.P, lpeg.Cs, lpeg.Cc, lpeg.match
+local char, gsub, format, gmatch, byte, match = string.char, string.gsub, string.format, string.gmatch, string.byte, string.match
+local next = next
+local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
+local concat = table.concat
+local totable = string.totable
+
+local allocate = utilities.storage.allocate
+local sequencers = utilities.sequencers
+local textlineactions = resolvers.openers.helpers.textlineactions
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+
+--[[ldx--
+<p>We will hook regime handling code into the input methods.</p>
+--ldx]]--
+
+local trace_translating = false trackers.register("regimes.translating", function(v) trace_translating = v end)
+
+local report_loading = logs.reporter("regimes","loading")
+local report_translating = logs.reporter("regimes","translating")
+
+regimes = regimes or { }
+local regimes = regimes
+
+local mapping = allocate {
+ utf = false
+}
+
+local backmapping = allocate {
+}
+
+-- regimes.mapping = mapping
+
+local synonyms = { -- backward compatibility list
+
+ ["windows-1250"] = "cp1250",
+ ["windows-1251"] = "cp1251",
+ ["windows-1252"] = "cp1252",
+ ["windows-1253"] = "cp1253",
+ ["windows-1254"] = "cp1254",
+ ["windows-1255"] = "cp1255",
+ ["windows-1256"] = "cp1256",
+ ["windows-1257"] = "cp1257",
+ ["windows-1258"] = "cp1258",
+
+ ["il1"] = "8859-1",
+ ["il2"] = "8859-2",
+ ["il3"] = "8859-3",
+ ["il4"] = "8859-4",
+ ["il5"] = "8859-9",
+ ["il6"] = "8859-10",
+ ["il7"] = "8859-13",
+ ["il8"] = "8859-14",
+ ["il9"] = "8859-15",
+ ["il10"] = "8859-16",
+
+ ["iso-8859-1"] = "8859-1",
+ ["iso-8859-2"] = "8859-2",
+ ["iso-8859-3"] = "8859-3",
+ ["iso-8859-4"] = "8859-4",
+ ["iso-8859-9"] = "8859-9",
+ ["iso-8859-10"] = "8859-10",
+ ["iso-8859-13"] = "8859-13",
+ ["iso-8859-14"] = "8859-14",
+ ["iso-8859-15"] = "8859-15",
+ ["iso-8859-16"] = "8859-16",
+
+ ["latin1"] = "8859-1",
+ ["latin2"] = "8859-2",
+ ["latin3"] = "8859-3",
+ ["latin4"] = "8859-4",
+ ["latin5"] = "8859-9",
+ ["latin6"] = "8859-10",
+ ["latin7"] = "8859-13",
+ ["latin8"] = "8859-14",
+ ["latin9"] = "8859-15",
+ ["latin10"] = "8859-16",
+
+ ["utf-8"] = "utf",
+ ["utf8"] = "utf",
+ [""] = "utf",
+
+ ["windows"] = "cp1252",
+
+ ["pdf"] = "pdfdoc",
+
+}
+
+local currentregime = "utf"
+
+local function loadregime(mapping,regime)
+ local name = resolvers.findfile(format("regi-%s.lua",regime)) or ""
+ local data = name ~= "" and dofile(name)
+ if data then
+ vector = { }
+ for eightbit, unicode in next, data do
+ vector[char(eightbit)] = utfchar(unicode)
+ end
+ report_loading("vector %a is loaded",regime)
+ else
+ vector = false
+ report_loading("vector %a is unknown",regime)
+ end
+ mapping[regime] = vector
+ return vector
+end
+
+local function loadreverse(t,k)
+ local t = { }
+ for k, v in next, mapping[k] do
+ t[v] = k
+ end
+ backmapping[k] = t
+ return t
+end
+
+setmetatableindex(mapping, loadregime)
+setmetatableindex(backmapping,loadreverse)
+
+local function fromregime(regime,line)
+ if line and #line > 0 then
+ local map = mapping[regime and synonyms[regime] or regime or currentregime]
+ if map then
+ line = gsub(line,".",map)
+ end
+ end
+ return line
+end
+
+-- local remappers = { }
+--
+-- local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?")
+-- local t = backmapping[vector]
+-- local remapper = remappers[vector]
+-- if not remapper then
+-- remapper = utf.remapper(t)
+-- remappers[t] = remapper
+-- end
+-- local m = getmetatable(t)
+-- setmetatableindex(t, function(t,k)
+-- local v = default or "?"
+-- t[k] = v
+-- return v
+-- end)
+-- str = remapper(str)
+-- setmetatable(t,m)
+-- return str
+-- end
+--
+-- -- much faster (but only matters when we have > 10K calls
+
+local cache = { } -- if really needed we can copy vectors and hash defaults
+
+setmetatableindex(cache, function(t,k)
+ local v = { remappers = { } }
+ t[k] = v
+ return v
+end)
+
+local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?")
+ local d = default or "?"
+ local c = cache[vector].remappers
+ local r = c[d]
+ if not r then
+ local t = fastcopy(backmapping[vector])
+ -- r = utf.remapper(t) -- not good for defaults here
+ local pattern = Cs((lpeg.utfchartabletopattern(t)/t + lpeg.patterns.utf8character/d + P(1)/d)^0)
+ r = function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end
+ c[d] = r
+ end
+ return r(str)
+end
+
+local function disable()
+ currentregime = "utf"
+ sequencers.disableaction(textlineactions,"regimes.process")
+ return currentregime
+end
+
+local function enable(regime)
+ regime = synonyms[regime] or regime
+ if mapping[regime] == false then
+ disable()
+ else
+ currentregime = regime
+ sequencers.enableaction(textlineactions,"regimes.process")
+ end
+ return currentregime
+end
+
+regimes.toregime = toregime
+regimes.fromregime = fromregime
+regimes.translate = function(str,regime) return fromregime(regime,str) end
+regimes.enable = enable
+regimes.disable = disable
+
+-- The following function can be used when we want to make sure that
+-- utf gets passed unharmed. This is needed for modules.
+
+local level = 0
+
+function regimes.process(str,filename,currentline,noflines,coding)
+ if level == 0 and coding ~= "utf-8" then
+ str = fromregime(currentregime,str)
+ if trace_translating then
+ report_translating("utf: %s",str)
+ end
+ end
+ return str
+end
+
+local function push()
+ level = level + 1
+ if trace_translating then
+ report_translating("pushing level %s",level)
+ end
+end
+
+local function pop()
+ if level > 0 then
+ if trace_translating then
+ report_translating("popping level %s",level)
+ end
+ level = level - 1
+ end
+end
+
+regimes.push = push
+regimes.pop = pop
+
+if sequencers then
+
+ sequencers.prependaction(textlineactions,"system","regimes.process")
+ sequencers.disableaction(textlineactions,"regimes.process")
+
+end
+
+-- interface:
+
+implement {
+ name = "enableregime",
+ arguments = "string",
+ actions = function(regime) setmacro("currentregime",enable(regime)) end
+}
+
+implement {
+ name = "disableregime",
+ actions = function() setmacro("currentregime",disable()) end
+}
+
+implement {
+ name = "pushregime",
+ actions = push
+}
+
+implement {
+ name = "popregime",
+ actions = pop
+}
+
+local stack = { }
+
+implement {
+ name = "startregime",
+ arguments = "string",
+ actions = function(regime)
+ insert(stack,currentregime)
+ if trace_translating then
+ report_translating("start using %a",regime)
+ end
+ setmacro("currentregime",enable(regime))
+ end
+}
+
+implement {
+ name = "stopregime",
+ actions = function()
+ if #stack > 0 then
+ local regime = remove(stack)
+ if trace_translating then
+ report_translating("stop using %a",regime)
+ end
+ setmacro("currentregime",enable(regime))
+ end
+ end
+}
+
+-- Next we provide some hacks. Unfortunately we run into crappy encoded
+-- (read : mixed) encoded xml files that have these ë ä ö ü sequences
+-- instead of ë ä ö ü
+
+local patterns = { }
+
+-- function regimes.cleanup(regime,str)
+-- local p = patterns[regime]
+-- if p == nil then
+-- regime = regime and synonyms[regime] or regime or currentregime
+-- local vector = regime ~= "utf" and mapping[regime]
+-- if vector then
+-- local list = { }
+-- for k, uchar in next, vector do
+-- local stream = totable(uchar)
+-- for i=1,#stream do
+-- stream[i] = vector[stream[i]]
+-- end
+-- list[concat(stream)] = uchar
+-- end
+-- p = lpeg.append(list,nil,true)
+-- p = Cs((p+1)^0)
+-- -- lpeg.print(p) -- size 1604
+-- else
+-- p = false
+-- end
+-- patterns[vector] = p
+-- end
+-- return p and lpegmatch(p,str) or str
+-- end
+--
+-- twice as fast and much less lpeg bytecode
+
+-- function regimes.cleanup(regime,str)
+-- if not str or str == "" then
+-- return str
+-- end
+-- local p = patterns[regime]
+-- if p == nil then
+-- regime = regime and synonyms[regime] or regime or currentregime
+-- local vector = regime ~= "utf" and regime ~= "utf-8" and mapping[regime]
+-- if vector then
+-- local utfchars = { }
+-- local firsts = { }
+-- for k, uchar in next, vector do
+-- local stream = { }
+-- local split = totable(uchar)
+-- local nofsplits = #split
+-- if nofsplits > 1 then
+-- local first
+-- for i=1,nofsplits do
+-- local u = vector[split[i]]
+-- if not first then
+-- first = firsts[u]
+-- if not first then
+-- first = { }
+-- firsts[u] = first
+-- end
+-- end
+-- stream[i] = u
+-- end
+-- local nofstream = #stream
+-- if nofstream > 1 then
+-- first[#first+1] = concat(stream,2,nofstream)
+-- utfchars[concat(stream)] = uchar
+-- end
+-- end
+-- end
+-- p = P(false)
+-- for k, v in next, firsts do
+-- local q = P(false)
+-- for i=1,#v do
+-- q = q + P(v[i])
+-- end
+-- p = p + P(k) * q
+-- end
+-- p = Cs(((p+1)/utfchars)^1)
+-- -- lpeg.print(p) -- size: 1042
+-- else
+-- p = false
+-- end
+-- patterns[regime] = p
+-- end
+-- return p and lpegmatch(p,str) or str
+-- end
+--
+-- 5 times faster:
+
+function regimes.cleanup(regime,str)
+ if not str or str == "" then
+ return str
+ end
+ local p = patterns[regime]
+ if p == nil then
+ regime = regime and synonyms[regime] or regime or currentregime
+ local vector = regime ~= "utf" and regime ~= "utf-8" and mapping[regime]
+ if vector then
+ local mapping = { }
+ for k, v in next, vector do
+ local split = totable(v)
+ for i=1,#split do
+ split[i] = utfchar(byte(split[i]))
+ end
+ split = concat(split)
+ if v ~= split then
+ mapping[split] = v
+ end
+ end
+ p = Cs((lpeg.utfchartabletopattern(mapping)/mapping+P(1))^0)
+ else
+ p = false
+ end
+ patterns[regime] = p
+ end
+ return p and lpegmatch(p,str) or str
+end
+
+-- local old = [[test ë ä ö ü crap]]
+-- local new = regimes.cleanup("cp1252",old)
+-- report_translating("%s -> %s",old,new)
+-- local old = "Pozn" .. char(0xE1) .. "mky"
+-- local new = fromregime("cp1250",old)
+-- report_translating("%s -> %s",old,new)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/regi-ini.mkiv
new file mode 100644
index 00000000000..6190393d804
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-ini.mkiv
@@ -0,0 +1,33 @@
+%D \module
+%D [ file=regi-ini,
+%D version=2005.04.25,
+%D title=\CONTEXT\ Regime Macros,
+%D subtitle=Regime 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.
+
+\registerctxluafile{regi-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {enableregime,disableregime,
+%D startregime,stopregime,
+%D currentregime}
+%D
+%D Beware, the enable and disable commands are global switches, so
+%D best use the start|/|stop commands.
+
+\let\currentregime\empty
+
+\unexpanded\def\enableregime[#1]{\clf_enableregime{#1}}
+\unexpanded\def\disableregime {\clf_disableregime}
+\unexpanded\def\startregime [#1]{\clf_startregime{#1}}
+\unexpanded\def\stopregime {\clf_stopregime}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/regi-pdfdoc.lua b/Master/texmf-dist/tex/context/base/mkiv/regi-pdfdoc.lua
new file mode 100644
index 00000000000..363d3ae0da3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/regi-pdfdoc.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['regi-pdfdoc'] = {
+ version = 1.001,
+ comment = "companion to regi-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return { [0] =
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x02D8, 0x02C7, 0x02C6, 0x02D9, 0x02DD, 0x02DB, 0x02DA, 0x02DC, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018,
+ 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017D, 0x0131, 0x0142, 0x0153, 0x0161, 0x017E, 0x009F,
+ 0x20AC, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0xFFFD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi
new file mode 100644
index 00000000000..2f21b00040e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi
@@ -0,0 +1,410 @@
+%D \module
+%D [ file=scrn-bar, % was part of scrn-int
+%D version=1995.01.01,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Progress Bars,
+%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 Screen Macros / Progress Bars}
+
+\unprotect
+
+%D The code is a bit upgraded to \MKIV\ but the output is mostly the
+%D same. In retrospect this should have been a module. We can move
+%D some definitions to scrn-run-bar.mkiv if needed. We can also make
+%D the code a bit more efficient.
+
+% todo: replace blackrule by stupid rules
+
+%D \starttyping
+%D \setupinteraction
+%D [state=start]
+%D
+%D \setupsubpagenumber
+%D [state=start]
+%D
+%D \setuplayout
+%D [middle]
+%D
+%D \setuppapersize
+%D [S4][S4]
+%D
+%D \startsetups bars
+%D \ruledvbox to \textheight \bgroup
+%D a \ruledhbox{\interactionbar[a]}\vss
+%D b \ruledhbox{\interactionbar[b]}\vss
+%D c \ruledhbox{\interactionbar[c]}\vss
+%D d \ruledhbox{\interactionbar[d]}\vss
+%D e \ruledhbox{\interactionbar[e]}\vss
+%D f \ruledhbox{\interactionbar[f]}\vss
+%D g \ruledhbox{\interactionbar[g]}\vss
+%D \egroup
+%D \stopsetups
+%D
+%D \setuptexttexts[\setups{bars}]
+%D
+%D \starttext
+%D \dorecurse {12} {
+%D \startstandardmakeup
+%D \stopstandardmakeup
+%D }
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{interactionbar}
+
+\installframedcommandhandler \??interactionbar {interactionbar} \??interactionbar
+
+\unexpanded\def\interactionbar
+ {\dodoubleempty\scrn_bar_direct}
+
+\def\scrn_bar_direct[#tag][#settings]% somewhat messy
+ {\iflocation
+ \begingroup
+ \doifelseassignment{#tag}
+ {\let\currentinteractionbar\empty
+ \setupcurrentinteractionbar[#tag]%
+ \edef\currentinteractionbar{\interactionbarparameter\c!alternative}}%
+ {\edef\currentinteractionbar{#tag}%
+ \ifsecondargument\setupcurrentinteractionbar[#settings]\fi}%
+ \doif{\interactionbarparameter\c!state}\v!start
+ {\interactionbarparameter\c!command}%
+ \endgroup
+ \fi}
+
+\newdimen\d_scrn_bar_width
+\newdimen\d_scrn_bar_height
+\newdimen\d_scrn_bar_depth
+\newdimen\d_scrn_bar_distance
+
+%D Interaction buttons, in fact a row of tiny buttons, are
+%D typically only used for navigational purposed. The next
+%D macro builds such a row based on a specification list.
+%D
+%D \startbuffer
+%D \interactionbuttons[width=\hsize][page,PreviousJump,ExitViewer]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \getbuffer
+%D
+%D Apart from individual entries, one can use \type{page} and
+%D \type {subpage} as shortcuts to their four associated buttons.
+%D The symbols are derived from the symbols linked to the
+%D entries.
+
+\unexpanded\def\interactionbuttons
+ {\dodoubleempty\scrn_bar_buttons}
+
+\def\scrn_bar_buttons
+ {\iflocation
+ \expandafter\scrn_bar_buttons_status
+ \else
+ \expandafter\scrn_bar_buttons_ignore
+ \fi}
+
+\def\scrn_bar_buttons_status[#settings][#list]%
+ {\doif{\interactionbarparameter\c!state}\v!start
+ {\ifsecondargument
+ \scrn_bar_buttons_indeed[#settings][#list]%
+ \else
+ \scrn_bar_buttons_indeed[][#settings]%
+ \fi}}
+
+\def\scrn_bar_buttons_ignore[#settings][#list]% \gobbletwooptionals
+ {}
+
+\def\scrn_bar_buttons_indeed[#settings][#list]%
+ {\begingroup
+ %\let\menuparameter\interactionbarparameter
+ \setupcurrentinteractionbar[#settings]%
+ \d_scrn_bar_width\interactionbarparameter\c!width
+ \ifdim\d_scrn_bar_width=\zeropoint
+ \d_scrn_bar_width1.5\emwidth
+ \fi
+ \doifnothing{\interactionbarparameter\c!height}{\letinteractionbarparameter\c!height\v!broad}%
+ \doifnothing{\interactionbarparameter\c!depth }{\letinteractionbarparameter\c!depth\zeropoint}%%%
+ \letinteractionbarparameter\c!background\empty
+ \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
+ \scratchcounterone\zerocount % new, was 1
+ \processallactionsinset
+ [#list]
+ [ \v!page=>\advance\scratchcounterone\plusfour,
+ \v!subpage=>\advance\scratchcounterone\plusfour,
+ \s!unknown=>\advance\scratchcounterone\plusone]%
+ \ifdim\d_scrn_bar_width=\zeropoint
+ \scratchdimenone\dimexpr2\emwidth+\d_scrn_bar_distance\relax
+ \scratchdimentwo\dimexpr\scratchcounterone\scratchdimenone-\d_scrn_bar_distance\relax
+ \else
+ \scratchdimenone\d_scrn_bar_width
+ \scratchdimentwo\dimexpr\scratchcounterone\d_scrn_bar_distance-\d_scrn_bar_distance\relax
+ \advance\scratchdimenone -\scratchdimentwo
+ \divide\scratchdimenone \scratchcounterone
+ \scratchdimentwo\d_scrn_bar_width
+ \fi
+ \hbox to \scratchdimentwo
+ {\setnostrut
+ \startsymbolset[\interactionparameter\c!symbolset]%
+ \processallactionsinset
+ [#list]
+ [ \v!page=>\scrn_bar_goto\v!firstpage
+ \scrn_bar_goto\v!nextpage
+ \scrn_bar_goto\v!previouspage
+ \scrn_bar_goto\v!lastpage,
+ \v!subpage=>\scrn_bar_goto\v!firstsubpage
+ \scrn_bar_goto\v!nextsubpage
+ \scrn_bar_goto\v!previoussubpage
+ \scrn_bar_goto\v!lastsubpage,
+ \s!unknown=>\scrn_bar_goto\commalistelement]%
+ \unskip
+ \stopsymbolset}%
+ \endgroup}
+
+\def\scrn_bar_goto#action%
+ {\button
+ [\c!height=\the\scratchheight,\c!width=\the\scratchdimenone]%
+ {\symbol[#action]}% we could expand this one once only
+ [#action]%
+ \hss}
+
+% todo: this will be \letblackruleparameter\c!width\scratchdimenone (faster)
+
+\def\scrn_bar_alternative_a
+ {\d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \noindent\hbox to \d_scrn_bar_width \bgroup
+ \dontcomplain
+ \setupblackrules[\c!height=\v!max,\c!depth=\v!max]%
+ \scratchdimentwo\dimexpr\d_scrn_bar_width-4\emwidth\relax
+ \processaction
+ [\interactionbarparameter\c!step]
+ [ \v!small=>\scratchcounter 20,
+ \v!medium=>\scratchcounter 10,
+ \v!big=>\scratchcounter 5,
+ \s!unknown=>\scratchcounter 10]%
+ \scratchdimenone\dimexpr\scratchdimentwo/\scratchcounter\relax
+ \setupblackrules[\c!width=\scratchdimenone]%
+ \setbox\scratchbox\hbox to \d_scrn_bar_width
+ {\hskip2\emwidth
+ \setbox\scratchbox\hbox{\blackrule[\c!color=\interactionbarparameter\c!backgroundcolor]}%
+ \dorecurse\scratchcounter
+ {\hss\normalexpanded{\directgotodumbbox{\copy\scratchbox}[page(\the\numexpr\recurselevel*\lastpage/\scratchcounter\relax)]}}%
+ \hss
+ \hskip2\emwidth}%
+ \wd\scratchbox\zeropoint
+ \box \scratchbox
+ \setupblackrules[\c!width=\emwidth]%
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\blackrule}[\v!firstpage]}%
+ \hskip\emwidth
+ \ifnum\realpageno>\plusone
+ \hskip\zeropoint\s!plus\numexpr\realpageno-\plustwo\relax \s!sp\relax % cm gives overflow
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\blackrule}[\v!previouspage)]}%
+ \fi
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\blackrule}[page(\number\realpageno)]}% todo: \v!currentpage
+ \ifnum\realpageno<\lastpage\relax
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\blackrule}[\v!nextpage]}%
+ \hskip\zeropoint\s!plus\numexpr\lastpage-\realpageno-\plusone\relax \s!sp\relax % cm gives overflow
+ \fi
+ \hskip\emwidth
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\blackrule}[\v!lastpage]}%
+ \egroup}
+
+\def\scrn_bar_alternative_b
+ {\ifnum\lastpage>\firstpage\relax
+ \interactionbuttons[\v!firstpage,\v!previouspage,\v!nextpage,\v!lastpage]%
+ \fi}
+
+\def\scrn_bar_alternative_c
+ {\ifnum\lastpage>\plusone
+ \d_scrn_bar_width\interactionbarparameter\c!width
+ \hbox to \d_scrn_bar_width
+ {\setupblackrules[\c!height=\interactionbarparameter\c!height,\c!depth=\interactionbarparameter\c!depth,\c!width=\emwidth]%
+ \scratchdimen\dimexpr(\d_scrn_bar_width-4\emwidth)/\numexpr\lastpage+\minusone\relax\relax
+ \scratchdimenone\numexpr\realpageno+\minusone\relax\scratchdimen
+ \scratchdimentwo\numexpr\lastpage-\realpageno\relax\scratchdimen
+ \directgotospecbox\interactionbarparameter{\blackrule}[\v!firstpage]%
+ \hss
+ \directgotospecbox\interactionbarparameter{\blackrule[\c!width=\scratchdimenone]}[\v!previouspage]%
+ \blackrule[\c!color=\interactionbarparameter\c!contrastcolor]%
+ \directgotospecbox\interactionbarparameter{\blackrule[\c!width=\scratchdimentwo]}[\v!nextpage]%
+ \hss
+ \directgotospecbox\interactionbarparameter{\blackrule}[\v!lastpage]}%
+ \fi}
+
+\unexpanded\def\scrn_bar_goto_a#whereto%
+ {\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!next\fi]}
+
+\unexpanded\def\scrn_bar_goto_b#whereto%
+ {\vrule\s!height\d_scrn_bar_height\s!depth\d_scrn_bar_depth\s!width\scratchdimenone\relax}
+
+\unexpanded\def\scrn_bar_goto_c#whereto%
+ {\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!somewhere\or\v!somewhere\or\v!next\fi}
+
+\unexpanded\def\scrn_bar_goto_d#whereto%
+ {\vrule \s!width\scratchdimenone \ifcase#whereto%
+ \s!height \d_scrn_bar_height \s!depth \d_scrn_bar_depth \or
+ \s!height.5\d_scrn_bar_height \s!depth.5\d_scrn_bar_depth \or
+ \s!height \d_scrn_bar_height \s!depth \d_scrn_bar_depth \or
+ \s!height.5\d_scrn_bar_height \s!depth.5\d_scrn_bar_depth \else
+ \s!height \d_scrn_bar_height \s!depth \d_scrn_bar_depth \fi}
+
+\newconstant\c_scrn_bar_mode
+
+\unexpanded\def\scrn_bar_goto_x#command%
+ {\doifelse{\interactionbarparameter\c!symbol}\v!yes
+ {\setupsymbolset[\interactionparameter\c!symbolset]%
+ \let\scrn_bar_goto_indeed\scrn_bar_goto_a}
+ {\let\scrn_bar_goto_indeed\scrn_bar_goto_b}%
+ \dorecurse\nofsubpages
+ %{\scratchcounter\numexpr\recurselevel+\firstsubpage+\minusone\relax
+ {\scratchcounter\therealsubpageno\recurselevel
+ \c_scrn_bar_mode
+ \ifnum\scratchcounter<\realpageno \zerocount \else
+ \ifnum\scratchcounter=\realpageno \plusone \else
+ \plustwo \fi\fi
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\c_scrn_bar_mode}[page(\the\scratchcounter)]}%
+ #command}%
+ \unskip}
+
+\def\scrn_bar_alternative_d
+ {\ifnum\nofsubpages>\plusone \doif{\namedcounterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \scratchdimenone\d_scrn_bar_width
+ \noindent\hbox{\scrn_bar_goto_x{\hskip\d_scrn_bar_distance}}%
+ }\fi}
+
+\def\scrn_bar_alternative_e
+ {\ifnum\nofsubpages>\plusone \doif{\namedcounterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \scratchdimentwo\dimexpr\nofsubpages\d_scrn_bar_distance-\d_scrn_bar_distance\relax % (n-1)
+ \scratchdimenone\dimexpr(\d_scrn_bar_width-\scratchdimentwo)/\nofsubpages\relax
+ \ifdim\scratchdimenone<\d_scrn_bar_distance
+ \scrn_bar_alternative_f
+ \else
+ \noindent\hbox to \d_scrn_bar_width{\scrn_bar_goto_x{\hss}\unskip}%
+ \fi
+ }\fi}
+
+\def\scrn_bar_alternative_f
+ {\ifnum\nofsubpages>\plusone \doif{\namedcounterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \noindent \hbox to \d_scrn_bar_width \bgroup
+ \doloop
+ {\scratchcounterthree\numexpr(\nofsubpages/\recurselevel)+\plusone\relax % rounding
+ \scratchdimentwo\d_scrn_bar_distance
+ \multiply\scratchdimentwo \scratchcounterthree
+ \advance\scratchdimentwo -\d_scrn_bar_distance
+ \scratchdimenone\d_scrn_bar_width
+ \advance\scratchdimenone -\scratchdimentwo
+ \divide\scratchdimenone \scratchcounterthree
+ \ifdim\scratchdimenone<\d_scrn_bar_distance\else
+ \scratchcountertwo\recurselevel
+ \exitloop
+ \fi}%
+ \ifnum\scratchcounterthree>\plusone
+ % this is not that well tested
+ \advance\scratchcounterthree \minustwo
+ \scratchdimenone-\d_scrn_bar_distance
+ \scratchdimenone\scratchcounterthree\scratchdimenone
+ \advance\scratchdimenone \d_scrn_bar_width
+ \advance\scratchcounterthree \plusone
+ \divide\scratchdimenone \scratchcounterthree
+ \fi
+ \doifelse{\interactionbarparameter\c!symbol}\v!yes
+ {\setupsymbolset[\interactionparameter\c!symbolset]%
+ \let\scrn_bar_goto_indeed\scrn_bar_goto_c}%
+ {\let\scrn_bar_goto_indeed\scrn_bar_goto_d}%
+ \scratchcounterthree\numexpr\realpageno-\plustwo\relax
+ \scratchcounterfour\numexpr\realpageno+\plustwo\relax
+ \ifnum\scratchcounterthree<\plusone \scratchcounterthree\plusone \fi
+ \scratchcounterfive\zerocount
+ \dostepwiserecurse\firstsubpage\lastsubpage\plusone
+ {\!!doneafalse
+ \advance\scratchcounterfive \plusone
+ \ifnum\recurselevel=\firstsubpage\relax \!!doneatrue \fi
+ \ifnum\recurselevel=\lastsubpage \relax \!!doneatrue \fi
+ \c_scrn_bar_mode
+ \if!!donea
+ \ifnum\recurselevel<\realpageno
+ \zerocount
+ \else\ifnum\recurselevel>\realpageno
+ \plustwo
+ \else
+ \plusfour
+ \fi\fi
+ \else
+ \ifnum\scratchcounterfive=\scratchcountertwo
+ \ifnum\recurselevel<\realpageno
+ \plusone
+ \else\ifnum\recurselevel>\realpageno
+ \plusthree
+ \else
+ \plustwo
+ \fi\fi
+ \else
+ \plusthree
+ \fi
+ \fi
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\c_scrn_bar_mode}[page(\therealsubpageno\recurselevel)]}%
+ \hss
+ \scratchcounterfive\zerocount}%
+ \unskip
+ \egroup
+ }\fi}
+
+\def\scrn_bar_alternative_g
+ {\ifnum\lastsubpage>\firstsubpage\relax % no test for state?
+ \interactionbuttons[\v!firstsubpage,\v!previoussubpage,\v!nextsubpage,\v!lastsubpage]%
+ \fi}
+
+\setupinteractionbar
+ [\c!state=\v!start,
+ \c!alternative=a,
+ \c!symbol=\v!no,
+ \c!width=10\emwidth,
+ \c!height=.5\emwidth,
+ \c!depth=\zeropoint,
+ \c!distance=.5\emwidth,
+ \c!step=\v!medium,
+ \c!foregroundcolor=\interactionbarparameter\c!color,
+ \c!foregroundstyle=\interactionbarparameter\c!style,
+ \c!color=\interactionparameter\c!color,
+ \c!contrastcolor=\interactionparameter\c!contrastcolor,
+ \c!style=,
+ \c!frame=\v!on,
+ \c!background=color,
+ \c!backgroundcolor=gray,
+ \c!samepage=\v!yes]
+
+\defineinteractionbar[a][\c!command=\scrn_bar_alternative_a]
+\defineinteractionbar[b][\c!command=\scrn_bar_alternative_b,\c!height=\v!broad]
+\defineinteractionbar[c][\c!command=\scrn_bar_alternative_c,\c!height=\v!max,\c!depth=\v!max]
+\defineinteractionbar[d][\c!command=\scrn_bar_alternative_d,\c!width=.5\emwidth]
+\defineinteractionbar[e][\c!command=\scrn_bar_alternative_e]
+\defineinteractionbar[f][\c!command=\scrn_bar_alternative_f]
+\defineinteractionbar[g][\c!command=\scrn_bar_alternative_g,\c!height=\v!broad]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-but.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.lua
new file mode 100644
index 00000000000..85cbf0b3973
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['scrn-but'] = {
+ version = 1.001,
+ comment = "companion to scrn-but.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local context = context
+local f_two_colon = string.formatters["%s:%s"]
+
+local function registerbuttons(tag,register,language)
+ local data = sorters.definitions[language]
+ local orders = data and data.orders or sorters.definitions.default.orders
+ local tag = tag == "" and { "" } or { tag }
+ for i=1,#orders do
+ local order = orders[i]
+ context.menubutton(tag,f_two_colon(register,order),order)
+ end
+end
+
+interfaces.implement {
+ name = "registerbuttons",
+ actions = registerbuttons,
+ arguments = { "string", "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi
new file mode 100644
index 00000000000..1d5ffe6f3d6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi
@@ -0,0 +1,1036 @@
+%D \module
+%D [ file=scrn-but, % moved code
+%D version=1995.01.01,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Interaction,
+%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.
+
+% \restorestandardblank
+% better namespace for pos
+
+\writestatus{loading}{ConTeXt Screen Macros / Buttons}
+
+\registerctxluafile{scrn-but}{1.001}
+
+\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
+%D \startbuffer
+%D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \getbuffer
+%D
+%D This command is formally specified as:
+%D
+%D \showsetup{button}
+%D
+%D The characteristics can be set with:
+%D
+%D \showsetup{setupbuttons}
+
+\installcorenamespace{button}
+\installcorenamespace{buttonlocation}
+
+\installframedcommandhandler \??button {button} \??button
+
+\let\setupbuttons\setupbutton
+
+\appendtoks
+ \setuevalue\currentbutton{\scrn_button_direct{\currentbutton}}%
+\to \everydefinebutton
+
+\unexpanded\def\scrn_button_direct#tag%
+ {\begingroup
+ \edef\currentbutton{#tag}%
+ \doifelselocation
+ {\dosingleempty\scrn_button_direct_status}%
+ {\dosingleempty\scrn_button_direct_ignore}}
+
+\def\scrn_button_direct_status
+ {\doifelse{\buttonparameter\c!state}\v!start
+ \scrn_button_direct_indeed
+ \scrn_button_direct_ignore}
+
+% empty=yes
+%
+% \button[settings]{}[action] % normally used at the tex end
+
+\def\scrn_button_direct_indeed[#settings]#text[#action]%
+ {\iffirstargument
+ \setupcurrentbutton[#settings]%
+ \fi
+ \scrn_button_make
+ \buttonparameter
+ \inheritedbuttonframed
+ \letbuttonparameter
+ \setbuttonparameter
+ {#text}%
+ {#action}%
+ \endgroup}
+
+\def\scrn_button_direct_ignore[#settings]#text[#destination]%
+ {\endgroup}
+
+\definebutton[button] % english
+
+\setupbuttons
+ [\c!state=\v!start,
+ \c!width=\v!fit,
+ \c!height=\v!broad,
+ \c!offset=0.25\emwidth,
+ \c!frame=\v!on,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!foregroundstyle=\buttonparameter\c!style,
+ \c!foregroundcolor=\buttonparameter\c!color,
+ \c!style=\interactionparameter\c!style,
+ \c!color=\interactionparameter\c!color,
+ \c!contrastcolor=\interactionparameter\c!contrastcolor,
+ \c!samepage=\v!yes,
+ \c!unknownreference=\v!yes,
+ \c!distance=\zeropoint] % for menubuttons
+
+%D \macros
+%D {overlaybutton}
+%D
+%D For converience we provide:
+%D
+%D \starttyping
+%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
+%D \starttyping
+%D \defineoverlay[PrevPage][\overlaybutton{PrevPage}]
+%D \setupbackgrounds[page][background=PrevPage]
+%D \setuptexttexts[\overlaybutton{NextPage}]
+%D \stoptyping
+%D
+%D For practical reasons, this macro accepts square brackets
+%D as well as braces.
+
+\unexpanded\def\overlaybutton
+ {\dosingleempty\scrn_button_overlay}
+
+\def\scrn_button_overlay[#1]%
+ {\iffirstargument
+ \scrn_button_overlay_indeed{#1}%
+ \else
+ \expandafter\scrn_button_overlay_indeed
+ \fi}
+
+\def\scrn_button_overlay_indeed#1%
+ {\iflocation
+ \gotobox{\overlayfakebox}[#1]%
+ \fi}
+
+%D The renderers:
+
+\expandafter\let\csname\??buttonlocation\v!yes \endcsname\zerocount
+\expandafter\let\csname\??buttonlocation\v!empty \endcsname\plusone
+\expandafter\let\csname\??buttonlocation\v!no \endcsname\plustwo
+\expandafter\let\csname\??buttonlocation\v!none \endcsname\plusthree
+\expandafter\let\csname\??buttonlocation\v!normal \endcsname\plusone % default
+\expandafter\let\csname\??buttonlocation\s!default\endcsname\plusone % default
+\expandafter\let\csname\??buttonlocation\s!empty \endcsname\plusone % default
+
+\newconditional\c_scrn_button_skipped
+
+\def\scrn_button_make#currentparameter#inheritedframed#letparameter#setparameter#text#action%
+ {\begingroup
+ \attribute\referenceattribute\attributeunsetvalue
+ \global\setfalse\c_scrn_button_skipped
+ \chardef\locationboxpagestate\csname\??buttonlocation#currentparameter\c!samepage\endcsname % ?? bt: todo
+ \doifelsereferencefound{#action}\scrn_button_make_yes\scrn_button_make_nop
+ #currentparameter%
+ #inheritedframed%
+ #letparameter%
+ #setparameter
+ {#text}%
+ \endgroup}
+
+\def\scrn_button_make_yes
+ {\scratchcounter\referencerealpage\relax % called in otr
+ \ifcase\scratchcounter
+ \expandafter\scrn_button_make_normal % no state : something else than a page reference
+ \else\ifnum\scratchcounter=\realpageno
+ \expandafter\expandafter\expandafter\scrn_button_make_yes_same
+ \else
+ \expandafter\expandafter\expandafter\scrn_button_make_yes_other
+ \fi\fi}
+
+\def\scrn_button_make_yes_same
+ {\ifcase\locationboxpagestate\relax
+ \expandafter\scrn_button_make_contrast % same page: yes: same page or not ... todo
+ \or
+ \expandafter\scrn_button_make_empty % same page: empty but frame: no click
+ \or
+ \expandafter\scrn_button_make_nothing % same page: empty no frame: no
+ \else
+ \expandafter\scrn_button_make_skipped % same page: nothing at all
+ \fi}
+
+\def\scrn_button_make_yes_other
+ {\ifcase\locationboxpagestate\relax
+ \expandafter\scrn_button_make_normal % other page: yes: same page or not ... todo
+ \or
+ \expandafter\scrn_button_make_normal % other page: empty but frame: no click
+ \or
+ \expandafter\scrn_button_make_normal % other page: empty no frame: no
+ \else
+ \expandafter\scrn_button_make_skipped % other page: nothing at all
+ \fi}
+
+\def\scrn_button_make_nop
+ {\ifcase\locationboxpagestate\relax
+ \expandafter\scrn_button_make_framed
+ \or
+ \expandafter\scrn_button_make_empty
+ \or
+ \expandafter\scrn_button_make_nothing
+ \or
+ \expandafter\scrn_button_make_skipped
+ \fi}
+
+\def\scrn_button_make_framed#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}
+
+\def\scrn_button_make_skipped#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {\global\settrue\c_scrn_button_skipped}
+
+\def\scrn_button_make_normal#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {\clf_injectcurrentreference
+ \hbox attr \referenceattribute \lastreferenceattribute
+ {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
+
+\def\scrn_button_make_contrast#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {\clf_injectcurrentreference
+ \hbox attr \referenceattribute \lastreferenceattribute
+ {#setparameter\c!foregroundcolor{#currentparameter\c!contrastcolor}%
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
+
+\def\scrn_button_make_empty#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#letparameter\c!empty\v!yes
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
+
+\def\scrn_button_make_nothing#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#letparameter\c!empty\v!yes
+ #letparameter\c!frame\empty
+ #letparameter\c!background\empty
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
+
+%D Menus:
+%D
+%D \starttyping
+%D \setuppapersize
+%D [S6][S6]
+%D
+%D \setuplayout
+%D [backspace=6cm, cutspace=6cm,
+%D leftedge=3cm, rightedge=3cm,
+%D leftmargin=1cm, rightmargin=1cm,
+%D margindistance=5mm, edgedistance=5mm,
+%D topspace=4cm, bottomspace=4cm,
+%D header=0pt, footer=0pt,
+%D top=1cm, bottom=1cm,
+%D topdistance=5mm, bottomdistance=5mm,
+%D width=middle, height=middle]
+%D
+%D \setupinteraction
+%D [state=start,
+%D menu=on]
+%D
+%D \setupinteractionmenu
+%D [right]
+%D [state=start,background=color,frame=off,backgroundcolor=red,color=white,contrastcolor=blue]
+%D \setupinteractionmenu
+%D [left]
+%D [state=start,background=color,frame=off,backgroundcolor=green,color=white]
+%D \setupinteractionmenu
+%D [top]
+%D [state=start,background=color,frame=off,backgroundcolor=blue,color=white]
+%D \setupinteractionmenu
+%D [bottom]
+%D [state=start,background=color,frame=off,backgroundcolor=yellow,color=white]
+%D
+%D \setupinteractionmenu
+%D [left]
+%D [state=local]
+%D \setupinteractionmenu
+%D [bottom]
+%D [state=local]
+%D
+%D \startinteractionmenu[right]
+%D \startbut [page(2)] Page 2 \stopbut
+%D \startbut [page(1)] Page 1 \stopbut
+%D \includemenu[left]
+%D \includemenu[bottom]
+%D \stopinteractionmenu
+%D
+%D \startinteractionmenu[left]
+%D \startbut [page(1)] Page 1 \stopbut
+%D \startbut [page(2)] Page 2 \stopbut
+%D \stopinteractionmenu
+%D
+%D \startinteractionmenu[top]
+%D \startbut [page(1)] Page 1 \stopbut
+%D \startbut [page(2)] Page 2 \stopbut
+%D \stopinteractionmenu
+%D
+%D \startinteractionmenu[bottom]
+%D \startbut [page(2)] Page 2 \stopbut
+%D \startbut [page(1)] Page 1 \stopbut
+%D \stopinteractionmenu
+%D \stoptyping
+%D
+%D \starttyping
+%D \startinteractionmenu[rechts]
+%D \startbut [eerste] eerste \stopbut
+%D \starttxt hello world \stoptxt
+%D \startbut [tweede] tweede \stopbut
+%D \startnop \stopnop
+%D \startbut [tweede] tweede \stopbut
+%D \startrul whow \stoprul
+%D \startbut [tweede] tweede \stopbut
+%D \startraw hello world \stopraw
+%D \startbut [tweede] tweede \stopbut
+%D \startcom \vfill \stopcom
+%D \startbut [derde] derde \stopbut
+%D \stopinteractionmenu
+%D \stoptyping
+%D
+%D \starttyping
+%D \setupinteractionmenu[right][samepage=yes, unknownreference=yes]
+%D \setupinteractionmenu[right][samepage=empty,unknownreference=empty]
+%D \setupinteractionmenu[right][samepage=no, unknownreference=no]
+%D \setupinteractionmenu[right][samepage=none, unknownreference=none]
+%D \stoptyping
+
+\installcorenamespace{menu}
+\installcorenamespace{menutoks}
+\installcorenamespace{menustate}
+\installcorenamespace{menupacker}
+\installcorenamespace{menualign}
+
+\installframedcommandhandler \??menu {interactionmenu} \??menu
+
+\let\setupinteractionmenus\setupinteractionmenu
+
+\let\scrn_menu_action\relax
+
+\let\scrn_menu_define_original\defineinteractionmenu
+
+\unexpanded\def\defineinteractionmenu
+ {\dotripleempty\scrn_menu_define}
+
+\def\scrn_menu_define[#tag][#category][#settings]% category reflects location, settings can be parent
+ {\ifthirdargument
+ \doifelseassignment{#settings}%
+ {\scrn_menu_define_original[#tag][#category][\c!category=#category,#settings]}% child definition
+ {\scrn_menu_define_original[#tag][#settings][\c!category=#category]}% % child definition
+ \scrn_menu_register{#tag}{#category}%
+ \else\ifsecondargument
+ \doifelseassignment{#category}%
+ {\scrn_menu_define_original[#tag][#category]}% % root definition
+ {\scrn_menu_define_original[#tag][#category][\c!category=#category]% % child definition
+ \scrn_menu_register{#tag}{#category}}%
+ \else
+ \scrn_menu_define_original[#tag]% % root definition
+ \fi\fi}
+
+\def\scrn_menu_register#tag#category%
+ {\ifcsname\??menutoks#category\endcsname \else
+ \expandafter\newtoks \csname\??menutoks#category\endcsname
+ \expandafter\setfalse\csname\??menustate#category\endcsname
+ \fi
+ \normalexpanded{\csname\??menutoks#category\endcsname{\the\csname\??menutoks#category\endcsname\scrn_menu_action{#tag}}}}
+
+\def\scrn_menu_actions#category%
+ {\the\csname\??menutoks#category\endcsname}
+
+%D Fill menus:
+
+\normalexpanded{\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}%
+ {\def\currentinteractionmenu{#tag}%
+ \expandafter\settrue\csname\??menustate\interactionmenuparameter\c!category\endcsname
+ \setinteractionmenuparameter\c!menu{#content}}
+
+\def\resetinteractionmenu[#tag]%
+ {\def\currentinteractionmenu{#tag}%
+ \resetinteractionmenuparameter\c!menu}
+
+%D Placement of menus:
+%D
+%D The offset mechanism is not the same as in in \MKII. There we
+%D adapted automatically to offsets in the text backgrounds. Here we
+%D have a bit more (but manual) control.
+%D
+%D \starttyping
+%D \setupbackgrounds
+%D [text][text]
+%D [background=color,backgroundcolor=gray,backgroundoffset=2mm]
+%D
+%D \setupbackgrounds
+%D [text]
+%D [rightedge,leftedge]
+%D [background=color,backgroundcolor=gray]
+%D
+%D \setupbackgrounds
+%D [top,bottom]
+%D [text]
+%D [background=color,backgroundcolor=gray]
+%D
+%D \setupinteractionmenu
+%D [right]
+%D [topoffset=0mm,bottomoffset=0mm]
+%D
+%D \setupinteractionmenu
+%D [top]
+%D [topoffset=2mm,bottomoffset=2mm,rightoffset=2mm,leftoffset=2mm]
+%D \stoptyping
+%D
+%D The no longer hard coded text areas offset compensation makes tuning
+%D easier. After all, menus need some setup anyway.
+
+\newbox \b_scrn_menu
+
+\newdimen\d_scrn_menu_next_distance
+\newdimen\d_scrn_menu_final_width
+\newdimen\d_scrn_menu_final_height
+\newdimen\d_scrn_menu_used_width
+\newdimen\d_scrn_menu_used_height
+\newdimen\d_scrn_menu_asked_width
+\newdimen\d_scrn_menu_asked_height
+\newdimen\d_scrn_menu_offset_top
+\newdimen\d_scrn_menu_offset_bottom
+\newdimen\d_scrn_menu_offset_left
+\newdimen\d_scrn_menu_offset_right
+
+\newconditional\c_scrn_menu_zerodimensions
+
+\def\scrn_menu_set_used
+ {\doassigncheckedframeoffset\d_scrn_menu_offset_left {\interactionmenuparameter\c!leftoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_right {\interactionmenuparameter\c!rightoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_top {\interactionmenuparameter\c!topoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_bottom{\interactionmenuparameter\c!bottomoffset}%
+ \d_scrn_menu_asked_width \interactionmenuparameter\c!maxwidth
+ \d_scrn_menu_asked_height \interactionmenuparameter\c!maxheight
+ \d_scrn_menu_used_width\dimexpr
+ \d_scrn_menu_asked_width + \d_scrn_menu_offset_left + \d_scrn_menu_offset_right
+ \relax
+ \d_scrn_menu_used_height\dimexpr
+ \d_scrn_menu_asked_height + \d_scrn_menu_offset_top + \d_scrn_menu_offset_bottom
+ \relax}
+
+\def\scrn_menu_set_final
+ {\d_scrn_menu_final_width \namedinteractionmenuparameter\askedinteractionmenulocation\c!maxwidth
+ \d_scrn_menu_final_height\namedinteractionmenuparameter\askedinteractionmenulocation\c!maxheight}
+
+\def\scrn_menu_apply_final
+ {\ifconditional\c_scrn_menu_zerodimensions
+ \wd\b_scrn_menu\zeropoint
+ \ht\b_scrn_menu\zeropoint
+ \else
+ \wd\b_scrn_menu\d_scrn_menu_final_width
+ \ht\b_scrn_menu\d_scrn_menu_final_height
+ \fi
+ \dp\b_scrn_menu\zeropoint}
+
+\def\scrn_menu_apply_used
+ {\ifdim\d_scrn_menu_offset_left=\zeropoint \else
+ \setbox\b_scrn_menu\hbox{\hskip-\d_scrn_menu_offset_left \box\b_scrn_menu}%
+ \fi
+ \ifdim\d_scrn_menu_offset_bottom=\zeropoint \else
+ \setbox\b_scrn_menu\hbox{\lower \d_scrn_menu_offset_bottom \box\b_scrn_menu}%
+ \fi
+ \wd\b_scrn_menu\d_scrn_menu_asked_width
+ \ht\b_scrn_menu\d_scrn_menu_asked_height
+ \dp\b_scrn_menu\zeropoint}
+
+\setvalue{\??menualign\v!right }{\let\scrn_menu_left_align\raggedright}
+\setvalue{\??menualign\v!left }{\let\scrn_menu_left_align\raggedleft}
+\setvalue{\??menualign\v!flushright}{\let\scrn_menu_left_align\raggedleft}
+\setvalue{\??menualign\v!flushleft }{\let\scrn_menu_left_align\raggedright}
+\setvalue{\??menualign\v!middle }{\let\scrn_menu_left_align\raggedcenter}
+\setvalue{\??menualign\v!low }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\relax}
+\setvalue{\??menualign\v!high }{\let\scrn_menu_top_align\relax\let\scrn_menu_bottom_align\vss}
+\setvalue{\??menualign\v!lohi }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\vss}
+
+\let\scrn_menu_left_align \relax
+\let\scrn_menu_right_align \relax
+\let\scrn_menu_top_align \relax
+\let\scrn_menu_bottom_align\relax
+
+\def\scrn_menu_set_align
+ {\csname\??menualign\interactionmenuparameter\c!itemalign\endcsname}
+
+%D Hook into the pagebuilder (as less testing as possible):
+
+\def\scrn_menu_insert
+ {\iflocation
+ \expandafter\scrn_menu_insert_checked
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\scrn_menu_insert_checked#location%
+ {\ifconditional\csname\??menustate#location\endcsname
+ \scrn_menu_insert_indeed{#location}%
+ \fi}
+
+\def\scrn_menu_insert_indeed#location%
+ {\begingroup
+ \xdef\askedinteractionmenulocation{#location}%
+ \scrn_menu_set_final
+ \ifcase\d_scrn_menu_final_width \else \ifcase\d_scrn_menu_final_height \else
+ \forgetall
+ \global\d_scrn_menu_next_distance\zeropoint
+ \let\scrn_menu_action\scrn_menu_package_indeed
+ \the\everysetmenucommands
+ \csname\??menupacker\namedinteractionmenuparameter\askedinteractionmenulocation\c!alternative\endcsname
+ \fi \fi
+ \endgroup}
+
+%D This calls: % can be \c!command for vertical/horizontal
+
+\setvalue{\??menupacker\v!vertical}% all menus
+ {\let\scrn_menu_packager\scrn_menu_packager_vertical
+ \setbox\b_scrn_menu\hbox{\scrn_menu_actions\askedinteractionmenulocation}%
+ \scrn_menu_apply_final
+ \box\b_scrn_menu}
+
+\setvalue{\??menupacker\v!horizontal}% all menus
+ {\let\scrn_menu_packager\scrn_menu_packager_horizontal
+ \setbox\b_scrn_menu\vbox{\scrn_menu_actions\askedinteractionmenulocation}%
+ \scrn_menu_apply_final
+ \box\b_scrn_menu}
+
+% stop : skipped
+% start: processed
+% local: skipped but can be included
+% empty: processed but invisible
+
+\unexpanded\def\scrn_menu_package_indeed#tag% one menu
+ {\begingroup
+ \edef\currentinteractionmenu{#tag}%
+ \edef\currentinteractionmenustate{\interactionmenuparameter\c!state}%
+ \ifx\currentinteractionmenustate\v!start
+ \scrn_menu_packager
+ \else\ifx\currentinteractionmenustate\v!empty
+ \scrn_menu_packager
+ \fi\fi
+ \endgroup}
+
+%D With the packager being one of:
+
+\let\currentinteractionmenudistance\!!zeropoint
+
+\def\scrn_menu_packager_vertical
+ {\scrn_menu_set_used
+ \hskip\d_scrn_menu_next_distance
+ \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width
+ {\ifx\currentinteractionmenustate\v!empty \else
+ \interactionmenuparameter\c!left
+ \scrn_menu_package_vertical{\strictinteractionmenuparameter\c!menu}%
+ \interactionmenuparameter\c!right
+ \fi}%
+ \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
+ \ifx\currentinteractionmenudistance\v!overlay
+ \global\d_scrn_menu_next_distance\zeropoint
+ \wd\b_scrn_menu\zeropoint
+ \else
+ \global\d_scrn_menu_next_distance\currentinteractionmenudistance
+ \scrn_menu_apply_used
+ \fi
+ \box\b_scrn_menu}
+
+\def\scrn_menu_packager_horizontal
+ {\scrn_menu_set_used
+ \vskip\d_scrn_menu_next_distance
+ \scrn_menu_set_align
+ \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height
+ {\ifx\currentinteractionmenustate\v!none \else
+ \scrn_menu_top_align
+ \interactionmenuparameter\c!before
+ \scrn_menu_package_horizontal{\strictinteractionmenuparameter\c!menu}%
+ \interactionmenuparameter\c!after
+ \scrn_menu_bottom_align
+ \fi}%
+ \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
+ \ifx\currentinteractionmenudistance\v!overlay
+ \global\d_scrn_menu_next_distance\zeropoint
+ \offinterlineskip
+ \dp\b_scrn_menu\zeropoint
+ \ht\b_scrn_menu\zeropoint
+ \else
+ \global\d_scrn_menu_next_distance\currentinteractionmenudistance
+ \scrn_menu_apply_used
+ \fi
+ \box\b_scrn_menu}
+
+%D For a right menu, a sequence of calls to \type
+%D {right_menu_button} is generated.
+%D
+%D \starttyping
+%D right_menu_button (n, p, s=0/1/2, x, y, w, h, d) ;
+%D \stoptyping
+%D
+%D Here, n is the number of the button, s a status variable,
+%D while the rest is positional info. The status variable is
+%D 0, 1 or~2: not found, found and found but current page.
+
+\newcount \c_scrn_menu_position
+\newconstant \c_scrn_menu_page_mode % 0=notfound 1=found 2=currentpage
+\newconditional\c_scrn_menu_positioning
+\newtoks \t_scrn_menu_meta_data
+
+\def\scrn_menu_button_meta_template
+ {\askedinteractionmenulocation _menu_button(%
+ \number\c_scrn_menu_position,%
+ \number\c_scrn_menu_page_mode,%
+ \MPpos{\askedinteractionmenulocation:\number\c_scrn_menu_position}%
+ );}
+
+\def\MPmenubuttons#1{\the\t_scrn_menu_meta_data}
+
+\appendtoks
+ \global\t_scrn_menu_meta_data\emptytoks
+\to \everyshipout
+
+\def\scrn_menu_whole_position % cannot happen in previous due to align
+ {\setbox\b_scrn_menu\hbox \bgroup
+ \hpos{menu:\askedinteractionmenulocation:\the\realpageno}{\box\b_scrn_menu}%
+ \egroup}
+
+% removed: \restorestandardblank (vspacing) ... should happen elsewhere
+
+\def\scrn_menu_package_vertical#content%
+ {\begingroup
+ \global\c_scrn_menu_position\zerocount
+ \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!inbetween}%
+ \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
+ \scrn_menu_set_align
+ \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height \bgroup
+ \hsize\d_scrn_menu_used_width
+ \scrn_menu_left_align
+ \interactionmenuparameter\c!before\relax
+ \ignorespaces#content\unskip
+ \interactionmenuparameter\c!after
+ \scrn_menu_right_align
+ \egroup
+ \ifconditional\c_scrn_menu_positioning
+ \scrn_menu_whole_position
+ \fi
+ \box\b_scrn_menu
+ \endgroup}
+
+\def\scrn_menu_package_horizontal#content%
+ {\begingroup
+ \global\c_scrn_menu_position\zerocount
+ \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!middle}%
+ \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
+ \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width \bgroup
+ \interactionmenuparameter\c!left\relax
+ \ignorespaces#content\unskip
+ \interactionmenuparameter\c!right
+ \egroup
+ \ifconditional\c_scrn_menu_positioning
+ \scrn_menu_whole_position
+ \fi
+ \box\b_scrn_menu
+ \endgroup}
+
+\def\scrn_menu_action_start
+ {\dontleavehmode
+ \begingroup}
+
+\def\scrn_menu_action_stop
+ {\ifconditional\c_scrn_button_skipped \else
+ \scrn_menu_between_action_indeed
+ \fi
+ \endgroup
+ \ignorespaces}
+
+\unexpanded\def\scrn_menu_raw_start[#action]#text\stopraw
+ {\scrn_menu_action_start
+ \gotobox{\ignorespaces#text\unskip}[#action]%
+ \scrn_menu_action_stop}
+
+\unexpanded\def\scrn_menu_but_start[#action]#text\stopbut
+ {\scrn_menu_action_start
+ \ifconditional\c_scrn_menu_positioning
+ \expandafter\scrn_button_make_position
+ \else
+ \expandafter\scrn_button_make
+ \fi
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
+ \scrn_menu_action_stop}
+
+\def\scrn_button_make_position#currentparameter#inheritedframed#letparameter#setparameter#text#action%
+ {\global\advance\c_scrn_menu_position\plusone
+ \doifelsereferencefound{#action}% 0=not found, 1=same page, >1=elsewhere
+ {\c_scrn_menu_page_mode\ifnum\currentreferencerealpage=\realpageno\plusone\else\plustwo\fi}%
+ {\c_scrn_menu_page_mode\plustwo}%
+ \doglobal\appendetoks
+ \scrn_menu_button_meta_template
+ \to \t_scrn_menu_meta_data
+ \hpos
+ {\askedinteractionmenulocation:\number\c_scrn_menu_position}%
+ {\scrn_button_make
+ #currentparameter%
+ #inheritedframed%
+ #letparameter%
+ #setparameter%
+ {#text}%
+ {#action}}}
+
+\unexpanded\def\scrn_menu_got_start[#action]#text\stopgot
+ {\scrn_menu_action_start
+ \letinteractionmenuparameter\c!frame\v!off
+ \letinteractionmenuparameter\c!background\empty
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
+ \scrn_menu_action_stop}
+
+\unexpanded\def\scrn_menu_nop_start#text\stopnop
+ {\scrn_menu_action_start
+ \letinteractionmenuparameter\c!frame\v!off
+ \letinteractionmenuparameter\c!background\empty
+ \letinteractionmenuparameter\c!empty\v!yes
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
+ \scrn_menu_action_stop}
+
+\unexpanded\def\scrn_menu_txt_start#text\stoptxt
+ {\scrn_menu_action_start
+ \letinteractionmenuparameter\c!frame\v!off
+ \letinteractionmenuparameter\c!background\empty
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
+ \scrn_menu_action_stop}
+
+\unexpanded\def\scrn_menu_rul_start#text\stoprul
+ {\scrn_menu_action_start
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
+ \scrn_menu_action_stop}
+
+\unexpanded\def\scrn_menu_com_start#text\stopcom
+ {\ignorespaces#text\removeunwantedspaces
+ \ignorespaces}
+
+\unexpanded\def\scrn_menu_raw#content\\{\scrn_menu_raw_start#content\stopraw} \let\stopraw\relax
+\unexpanded\def\scrn_menu_but#content\\{\scrn_menu_but_start#content\stopbut} \let\stopbut\relax
+\unexpanded\def\scrn_menu_got#content\\{\scrn_menu_got_start#content\stopgot} \let\stopgot\relax
+\unexpanded\def\scrn_menu_nop#content\\{\scrn_menu_nop_start#content\stopnop} \let\stopnop\relax
+\unexpanded\def\scrn_menu_txt#content\\{\scrn_menu_txt_start#content\stoptxt} \let\stoptxt\relax
+\unexpanded\def\scrn_menu_rul#content\\{\scrn_menu_rul_start#content\stoprul} \let\stoprul\relax
+\unexpanded\def\scrn_menu_com#content\\{\scrn_menu_com_start#content\stopcom} \let\stopcom\relax
+
+\newtoks\everysetmenucommands % public
+
+\appendtoks
+ \let\raw\scrn_menu_raw \let\startraw\scrn_menu_raw_start \let\stopraw\relax
+ \let\but\scrn_menu_but \let\startbut\scrn_menu_but_start \let\stopbut\relax
+ \let\got\scrn_menu_got \let\startgot\scrn_menu_got_start \let\stopgot\relax
+ \let\nop\scrn_menu_nop \let\startnop\scrn_menu_nop_start \let\stopnop\relax
+ \let\txt\scrn_menu_txt \let\starttxt\scrn_menu_txt_start \let\stoptxt\relax
+ \let\rul\scrn_menu_rul \let\startrul\scrn_menu_rul_start \let\stoprul\relax
+ \let\com\scrn_menu_com \let\startcom\scrn_menu_com_start \let\stopcom\relax
+\to \everysetmenucommands
+
+%D Sometimes handy:
+%D
+%D \starttyping
+%D \setupinteractionmenu
+%D [left]
+%D [state=local]
+%D
+%D \startinteractionmenu[right]
+%D ...
+%D \includemenu[left]
+%D ...
+%D \stopinteractionmenu
+%D \stoptyping
+
+\unexpanded\def\includemenu[#tag]%
+ {\begingroup
+ \edef\currentinteractionmenu{#tag}%
+ \doif{\interactionmenuparameter\c!state}\v!local
+ {\letinteractionmenuparameter\c!state\v!start
+ \strictinteractionmenuparameter\c!menu}%
+ \endgroup}
+
+%D Direct call (todo):
+
+\unexpanded\def\interactionmenu
+ {\dodoubleempty\scrn_menu_interaction_menu}
+
+\def\scrn_menu_interaction_menu[#tag][#settings]%
+ {\begingroup
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \scrn_menu_insert{#tag}%
+ \endgroup}
+
+%D Plugin handler:
+
+\unexpanded\def\scrn_menu_insert_content_indeed
+ {\iflocation % here as we can have a fast turn-off
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\let\scrn_menu_insert_content_ignore\gobbleoneargument
+
+\appendtoks
+ \doifelse{\interactionparameter\c!menu}\v!on
+ {\let\scrn_menu_insert_content\scrn_menu_insert_content_indeed}%
+ {\let\scrn_menu_insert_content\scrn_menu_insert_content_ignore}%
+\to \everysetupinteraction
+
+%D Plugs into the page builder:
+
+\unexpanded\def\scrn_menu_leftedge
+ {\hbox to \leftedgewidth \bgroup
+ \hsize\leftedgewidth
+ \settrue\c_scrn_menu_zerodimensions
+ \scrn_menu_insert\v!left
+ \egroup
+ \hskip-\leftedgewidth}
+
+\unexpanded\def\scrn_menu_rightedge
+ {\hbox to \rightedgewidth \bgroup
+ \hsize\rightedgewidth
+ \settrue\c_scrn_menu_zerodimensions
+ \scrn_menu_insert\v!right
+ \egroup
+ \hskip-\rightedgewidth}
+
+\unexpanded\def\scrn_menu_top
+ {\vbox to \topheight \bgroup
+ \vsize\topheight
+ \settrue\c_scrn_menu_zerodimensions
+ \scrn_menu_insert\v!top
+ \kern\zeropoint
+ \egroup
+ \vskip-\topheight}
+
+\unexpanded\def\scrn_menu_bottom
+ {\vbox to \bottomheight \bgroup
+ \vsize\bottomheight
+ \settrue\c_scrn_menu_zerodimensions
+ \scrn_menu_insert\v!bottom
+ \kern\zeropoint
+ \egroup
+ \vskip-\bottomheight}
+
+\appendtoks \scrn_menu_insert_content\scrn_menu_leftedge \to \leftedgetextcontent
+\appendtoks \scrn_menu_insert_content\scrn_menu_rightedge \to \rightedgetextcontent
+\appendtoks \scrn_menu_insert_content\scrn_menu_top \to \toptextcontent
+\appendtoks \scrn_menu_insert_content\scrn_menu_bottom \to \bottomtextcontent
+
+%D Initialization (root definitions, main builders):
+
+\defineinteractionmenu [\v!vertical] [\c!alternative=\v!vertical]
+\defineinteractionmenu [\v!horizontal] [\c!alternative=\v!horizontal]
+
+%D Initialization (parent definitions, 4 area builders):
+
+\defineinteractionmenu [\v!right ] [\v!right ] [\v!vertical ]
+\defineinteractionmenu [\v!left ] [\v!left ] [\v!vertical ]
+\defineinteractionmenu [\v!top ] [\v!top ] [\v!horizontal]
+\defineinteractionmenu [\v!bottom] [\v!bottom] [\v!horizontal]
+
+\setupinteraction
+ [\c!menu=\v!off]
+
+\setupinteractionmenu
+ [\c!offset=.25em,
+ \c!position=\v!no,
+ \c!frame=\v!on,
+ \c!maxwidth=\hsize,
+ \c!maxheight=\vsize,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!foregroundstyle=\interactionmenuparameter\c!style,
+ \c!foregroundcolor=\interactionmenuparameter\c!color,
+ \c!style=\interactionparameter\c!style,
+ \c!color=\interactionparameter\c!color,
+ \c!contrastcolor=\interactionparameter\c!contrastcolor,
+ \c!state=\v!start,
+ \c!samepage=\v!yes,
+ \c!unknownreference=\v!empty,
+ \c!distance=\bodyfontsize,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint]
+
+\setupinteractionmenu
+ [\v!vertical] % not really a menu
+ [\c!inbetween=\blank,
+ \c!before=,
+ \c!after=\vfil,
+ %\c!width=\v!fit,
+ \c!height=\v!broad]
+
+\setupinteractionmenu
+ [\v!horizontal] % not really a menu
+ [\c!middle=\hfil,
+ %\c!left=\hss,
+ %\c!right=\hss,
+ \c!width=\v!fit,
+ \c!height=\v!broad]
+
+\setupinteractionmenu
+ [\v!left]
+ [\c!itemalign=\v!flushright,
+ \c!maxwidth=\leftedgewidth,
+ \c!maxheight=\makeupheight]
+
+\setupinteractionmenu
+ [\v!right]
+ [\c!itemalign=\v!flushleft,
+ \c!maxwidth=\rightedgewidth,
+ \c!maxheight=\makeupheight]
+
+\setupinteractionmenu
+ [\v!top]
+ [\c!itemalign=\v!high,
+ \c!maxwidth=\makeupwidth,
+ \c!maxheight=\topheight]
+
+\setupinteractionmenu
+ [\v!bottom]
+ [\c!itemalign=\v!low,
+ \c!maxwidth=\makeupwidth,
+ \c!maxheight=\bottomheight]
+
+%D Lists:
+
+\definelistalternative [\v!left ] [\c!renderingsetup=strc:lists:rendering:menu]
+\definelistalternative [\v!right ] [\c!renderingsetup=strc:lists:rendering:menu]
+\definelistalternative [\v!top ] [\c!renderingsetup=strc:lists:rendering:menu]
+\definelistalternative [\v!bottom] [\c!renderingsetup=strc:lists:rendering:menu]
+
+\startsetups[strc:lists:rendering:menu]
+ \startbut[internal(\currentlistentrylocation)]
+ \limitatetext\currentlistentrytitle{\listparameter\c!maxwidth}\unknown
+ \stopbut
+\stopsetups
+
+%D Sometimes handy:
+
+\unexpanded\def\menubutton % tag settings text action
+ {\dodoubleempty\scrn_menu_menu_button}
+
+\def\scrn_button_direct_status
+ {\doifelse{\buttonparameter\c!state}\v!start
+ {\dosingleempty\scrn_button_direct_indeed}%
+ {\dosingleempty\scrn_button_direct_ignore}}
+
+\def\scrn_menu_menu_button
+ {\iflocation
+ \expandafter\scrn_menu_menu_button_indeed
+ \else
+ \expandafter\scrn_menu_menu_button_ignore
+ \fi}
+
+\def\scrn_menu_menu_button_indeed[#menutag][#settings]#text[#action]%
+ {\ifsecondargument
+ \scrn_menu_menu_button_a
+ {#menutag}{#settings}{#text}{#action}%
+ \else
+ \doifelseassignment{#menutag}\scrn_menu_menu_button_b\scrn_menu_menu_button_c
+ {#menutag}{#text}{#action}%
+ \fi}
+
+\def\scrn_menu_menu_button_ignore[#menutag][#settings]#text[#action]%
+ {}
+
+\def\scrn_menu_menu_button_a#tag#settings#text#action%
+ {\doif{\interactionmenuparameter\c!state}\v!start
+ {\dontleavehmode \begingroup
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
+ \endgroup}}
+
+\def\scrn_menu_menu_button_b#settings#text#action%
+ {\doif{\buttonparameter\c!state}\v!start
+ {\dontleavehmode \begingroup
+ \let\currentbutton\empty
+ \setupcurrentbutton[#settings]%
+ \scrn_button_make
+ \buttonparameter
+ \inheritedbuttonframed
+ \letbuttonparameter
+ \setbuttonparameter
+ {#text}%
+ {#action}%
+ \endgroup}}
+
+\def\scrn_menu_menu_button_c#tag#text#action%
+ {\doif{\interactionmenuparameter\c!state}\v!start
+ {\dontleavehmode \begingroup
+ \edef\currentinteractionmenu{#tag}%
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
+ \endgroup}}
+
+%D Untested:
+
+\unexpanded\def\registermenubuttons
+ {\dodoubleempty\scrn_menu_register_menu_buttons}
+
+\def\scrn_menu_register_menu_buttons[#menu][#register]%
+ {\ifsecondargument
+ \clf_registerbuttons{menu}{#register}{\currentlanguage}%
+ \else
+ \clf_registerbuttons{}{#menu}{\currentlanguage}%
+ \fi}
+
+% or less readable:
+%
+% \def\scrn_menu_register_menu_buttons[#menu][#register]%
+% {\clf_registerbuttons\ifsecondargument{menu}{#register}\else{}{#menu}\fi{\currentlanguage}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.lua
new file mode 100644
index 00000000000..f68cc039dce
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.lua
@@ -0,0 +1,191 @@
+if not modules then modules = { } end modules ['scrn-fld'] = {
+ version = 1.001,
+ comment = "companion to scrn-fld.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we should move some code from lpdf-fld to here
+
+local context = context
+local ctx_doifelse = commands.doifelse
+local implement = interfaces.implement
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+
+local report = logs.reporter("widgets")
+
+local texsetbox = tex.setbox
+
+local fields = { }
+interactions.fields = fields
+
+local codeinjections = backends.codeinjections
+local nodeinjections = backends.nodeinjections
+
+local function define(specification)
+ codeinjections.definefield(specification)
+end
+
+local function defineset(name,set)
+ codeinjections.definefield(name,set)
+end
+
+local function clone(specification)
+ codeinjections.clonefield(specification)
+end
+
+local function insert(name,specification)
+ return nodeinjections.typesetfield(name,specification)
+end
+
+fields.define = define
+fields.defineset = defineset
+fields.clone = clone
+fields.insert = insert
+
+-- codeinjections are not yet defined
+
+implement {
+ name = "definefield",
+ actions = define,
+ arguments = {
+ {
+ { "name" },
+ { "alternative" },
+ { "type" },
+ { "category" },
+ { "values" },
+ { "default" },
+ }
+ }
+}
+
+implement {
+ name = "definefieldset",
+ actions = defineset,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "clonefield",
+ actions = clone,
+ arguments = {
+ {
+ { "children" },
+ { "alternative" },
+ { "parent" },
+ { "category" },
+ { "values" },
+ { "default" },
+ }
+ }
+}
+
+implement {
+ name = "insertfield",
+ actions = function(name,specification)
+ local b = insert(name,specification)
+ if b then
+ texsetbox("b_scrn_field_body",b)
+ else
+ report("unknown field %a",name)
+ end
+ end,
+ arguments = {
+ "string",
+ {
+ { "title" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "align" },
+ { "length" },
+ { "fontstyle" },
+ { "fontalternative" },
+ { "fontsize" },
+ { "fontsymbol" },
+ { "colorvalue", "integer" },
+ { "color" },
+ { "backgroundcolorvalue", "integer" },
+ { "backgroundcolor" },
+ { "framecolorvalue", "integer" },
+ { "framecolor" },
+ { "layer" },
+ { "option" },
+ { "align" },
+ { "clickin" },
+ { "clickout" },
+ { "regionin" },
+ { "regionout" },
+ { "afterkey" },
+ { "format" },
+ { "validate" },
+ { "calculate" },
+ { "focusin" },
+ { "focusout" },
+ { "openpage" },
+ { "closepage" },
+ }
+ }
+}
+
+-- (for the monent) only tex interface
+
+implement {
+ name = "getfieldcategory",
+ arguments = "string",
+ actions = function(name)
+ local g = codeinjections.getfieldcategory(name)
+ if g then
+ context(g)
+ end
+ end
+}
+
+implement {
+ name = "getdefaultfieldvalue",
+ arguments = "string",
+ actions = function(name)
+ local d = codeinjections.getdefaultfieldvalue(name)
+ if d then
+ context(d)
+ end
+ end
+}
+
+implement {
+ name = "exportformdata",
+ arguments = "string",
+ actions = function(export)
+ if export == v_yes then
+ codeinjections.exportformdata()
+ end
+ end
+}
+
+implement {
+ name = "setformsmethod",
+ arguments = "string",
+ actions = function(method)
+ codeinjections.setformsmethod(method)
+ end
+}
+
+implement {
+ name = "doifelsefieldcategory",
+ arguments = "string",
+ actions = function(name)
+ ctx_doifelse(codeinjections.validfieldcategory(name))
+ end
+}
+
+implement {
+ name = "doiffieldsetelse",
+ arguments = "string",
+ actions = function(name)
+ ctx_doifelse(codeinjections.validfieldset(name))
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi
new file mode 100644
index 00000000000..a92abebc51e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi
@@ -0,0 +1,1038 @@
+%D \module
+%D [ file=scrn-fld,
+%D version=1997.05.18,
+%D title=\CONTEXT\ Screen Macros,
+%D subtitle=Fields,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% There is still some leftover code from mkii, where we need to
+% be sparse with hash entries and so have a somewhat complex
+% setup mechanism.
+
+% interaction checking
+
+\writestatus{loading}{ConTeXt Screen Macros / Fields}
+
+\unprotect
+
+\registerctxluafile{scrn-fld}{1.001}
+
+%D In \MKII\ we had to cheat a bit with setups in order not to run
+%D out of memory with thousands of fields, which we happen to need at
+%D that time. In \MKIV\ we can store some data at the \LUA\ end and
+%D use a somewhat slower but quite okay inheritance mechanism. For
+%D this reason we now have split definitions, although the old method
+%D is still somewhat supported. The clone and copy commands are
+%D somewhat obsolete for several reasons: we can now use inheritance
+%D and autocloning has been supported for a while. In most cases
+%D cloning (especially with check boxes) the acrobat browser is not
+%D stable enough with respect to appearance handling.
+%D
+%D A fieldcategory is nothing more than a collection of settings.
+%D
+%D \starttyping
+%D \definefieldcategory
+%D [all-email]
+%D [height=1cm,
+%D width=14cm,
+%D style=sstf]
+%D \stoptyping
+%D
+%D A definition can refer to this category:
+%D
+%D \starttyping
+%D \definefieldbody [email] [type=line,category=all-email,default=pragma@wxs.nl]
+%D \stoptyping
+%D
+%D A copy of a field is made as follows:
+%D
+%D \starttyping
+%D \definefieldbody [xmail] [email]
+%D \stoptyping
+%D
+%D You can also be more specific:
+%D
+%D \starttyping
+%D \definefieldbody[buttona][type=check,values={one,two}]
+%D \definefieldbody[buttonb][type=check,values={three,four}]
+%D \definefieldbody[buttonc][buttona][values={three,four}]
+%D \stoptyping
+%D
+%D Actually typesetting a field happens this way:
+%D
+%D \starttyping
+%D \fieldbody [Email]
+%D \fieldbody [Email] [width=6cm]
+%D \fieldbody [eMAIL]
+%D \fieldbody [eMAIL] [width=7cm]
+%D
+%D \fieldbody [buttona]
+%D \fieldbody [buttona]
+%D \fieldbody [buttonb]
+%D \fieldbody [buttonb]
+%D \fieldbody [buttonc]
+%D \fieldbody [buttonc]
+%D \stoptyping
+%D
+%D So, you can call up a field many times and quite some parameters
+%D can be set.
+%D
+%D Because there are persistent problems with acrobat rendering
+%D associated appearance streams (some messy /MK interferende) we
+%D also support native (built-in dingbat) symbols: check, circle,
+%D cross, diamond, square and star.
+%D
+%D \starttyping
+%D \definefield[test1][check]
+%D \definefield[test2][check]
+%D
+%D \fieldbody[test1][width=1em,height=\strutht,depth=\strutdp,symbol=check]
+%D \fieldbody[test1][width=1em,height=\strutht,depth=\strutdp,symbol=circle]
+%D \fieldbody[test2][width=1em,height=\strutht,depth=\strutdp,symbol=square]
+%D \stoptyping
+%D
+%D When submitting a form, we need to tell the driver module
+%D that we want \FDF\ or \HTML.
+
+\installcorenamespace {forms}
+
+\installdirectcommandhandler \??forms {forms}
+
+\appendtoks
+ \clf_setformsmethod{\formsparameter\c!method}%
+\to \everysetupforms
+
+\setupforms
+ [\c!method=XML] % no need for everyjob initialization as this is the default
+
+\appendtoks
+ \iflocation
+ \clf_exportformdata{\formsparameter\c!export}%
+ \fi
+\to \everystoptext
+
+%D We need to initialize symbols in a special way so that they
+%D can be used as rendering for a widget.
+
+\unexpanded\def\presetfieldsymbols[#list]% slow
+ {\processcommacommand[#list]\scrn_symbols_preset}
+
+\def\scrn_symbols_preset#set%
+ {\processcommalist[#set]\scrn_symbols_preset_indeed}%
+
+\def\scrn_symbols_preset_indeed#tag%
+ {\doifelseobjectfound{SYM}{#tag}
+ {}
+ {\settightobject{SYM}{#tag}\hbox{\symbol[#tag]}% % todo: set this as immediate xform
+ \page_otr_add_special_content{\hskip-\maxdimen\getobject{SYM}{#tag}}}} % and then force it into the file
+
+\let\dosetfieldsymbol\scrn_symbols_preset_indeed
+
+\def\dogetfieldsymbol#tag%
+ {\getobject{SYM}{#tag}}
+
+\unexpanded\def\definedefaultsymbols % used ?
+ {\definesymbol[defaultyes][\mathematics{\times}]%
+ \definesymbol[defaultno] [\mathematics{\cdot }]}
+
+%D Now comes the real code:
+
+\installcorenamespace{fieldcategory}
+\installcorenamespace{fieldbody}
+
+\installcommandhandler \??fieldcategory {fieldcategory} \??fieldcategory
+\installcommandhandler \??fieldbody {fieldbody} \??fieldbody
+
+\newbox\b_scrn_field_body
+
+\setupfieldcategory
+ [\c!alternative=\v!normal, % normal clone copy
+ \c!type=\v!line, % line text ...
+ \c!width=5em,
+ \c!height=1em,
+ \c!depth=\zeropoint,
+ \c!align=\v!flushleft,
+ \c!option=\v!printable, % maybe we need a globaloptions and marge them
+ \c!n=1024]
+
+\def\scrn_field_check_category
+ {\edef\currentfieldbodycategory{\fieldbodyparameter\c!category}%
+ \ifx\currentfieldbodycategory\empty
+ \letfieldbodyparameter\s!parent\??fieldcategory
+ %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\empty}% to WS: not hash !
+ \else
+ \normalexpanded{\setfieldbodyparameter{\s!parent}{\??fieldcategory\currentfieldbodycategory}}%
+ %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\currentfieldbodycategory}% to WS: not hash !
+ \fi}
+
+\appendtoks % we cannot use parent .. maybe s!parent has to change
+ \ifx\currentfieldbodyparent\empty
+ \scrn_field_check_category
+ \clf_definefield
+ name {\currentfieldbody}%
+ alternative {normal}%
+ type {\fieldbodyparameter\c!type}%
+ category {\fieldbodyparameter\c!category}%
+ values {\fieldbodyparameter\c!values}%
+ default {\fieldbodyparameter\c!default}%
+ \relax
+ \else
+ \clf_clonefield
+ children {\currentfieldbody}%
+ alternative {clone}%
+ parent {\currentfieldbodyparent}%
+ category {\fieldbodyparameter\c!category}%
+ values {\fieldbodyparameter\c!values}%
+ default {\fieldbodyparameter\c!default}%
+ \relax
+ \fi
+\to \everydefinefieldbody
+
+\unexpanded\def\fieldbody
+ {\dodoubleempty\scrn_field_body}
+
+\def\scrn_field_body[#tag][#settings]%
+ {\iflocation
+ \hbox\bgroup
+ \edef\currentfieldbody{#tag}%
+ \ifsecondargument
+ \setupcurrentfieldbody[#settings]%
+ \fi
+ \scrn_field_body_typeset
+ \box\b_scrn_field_body
+ \egroup
+ \fi}
+
+\def\scrn_field_body_typeset % todo: fieldsymbol (checkfields /MK mess)
+ {\edef\currentfieldframecolor{\fieldbodyparameter\c!fieldframecolor}%
+ \ifx\currentfieldframecolor\empty\else
+ \getcolorattributevalue\currentfieldframecolor\currentfieldframecolorvalue
+ % == \edef\currentfieldframecolorvalue{\thecolorattribute\currentfieldframecolor}%
+ \fi
+ \edef\currentfieldbackgroundcolor{\fieldbodyparameter\c!fieldbackgroundcolor}%
+ \ifx\currentfieldbackgroundcolor\empty\else
+ \getcolorattributevalue\currentfieldbackgroundcolor\currentfieldbackgroundcolorvalue
+ % == \edef\currentfieldbackgroundcolorvalue{\thecolorattribute\currentfieldbackgroundcolor}%
+ \fi
+ \usefieldbodystyleandcolor\c!style\c!color
+ \clf_insertfield
+ {\currentfieldbody}%
+ {%
+ title {\currentfieldbody}
+ width \dimexpr\fieldbodyparameter\c!width \relax
+ height \dimexpr\fieldbodyparameter\c!height\relax
+ depth \dimexpr\fieldbodyparameter\c!depth \relax
+ align {\fieldbodyparameter\c!align}%
+ length {\fieldbodyparameter\c!n}%
+ fontstyle {\fontstyle}%
+ fontalternative {\fontalternative}%
+ fontsize {\fontbody}%
+ fontsymbol {\fieldbodyparameter\c!symbol}%
+ color {\fieldbodyparameter\c!color}%
+ colorvalue \attribute\colorattribute
+ \ifx\currentfieldbackgroundcolor\empty \else
+ backgroundcolor {\currentfieldbackgroundcolor}%
+ backgroundcolorvalue \numexpr\currentfieldbackgroundcolorvalue\relax
+ \fi
+ \ifx\currentfieldframecolor\empty \else
+ framecolor {\currentfieldframecolor}%
+ framecolorvalue \numexpr\currentfieldframecolorvalue\relax
+ \fi
+ layer {\fieldbodyparameter\c!fieldlayer}%
+ option {\fieldbodyparameter\c!option}%
+ align {\fieldbodyparameter\c!align}%
+ clickin {\fieldbodyparameter\c!clickin}%
+ clickout {\fieldbodyparameter\c!clickout}%
+ regionin {\fieldbodyparameter\c!regionin}%
+ regionout {\fieldbodyparameter\c!regionout}%
+ afterkey {\fieldbodyparameter\c!afterkey}%
+ format {\fieldbodyparameter\c!format}%
+ validate {\fieldbodyparameter\c!validate}%
+ calculate {\fieldbodyparameter\c!calculate}%
+ focusin {\fieldbodyparameter\c!focusin}%
+ focusout {\fieldbodyparameter\c!focusout}%
+ openpage {\fieldbodyparameter\c!openpage}%
+ closepage {\fieldbodyparameter\c!closepage}%
+ }%
+ \relax}
+
+%D The sets are used in grouped calculations.
+%D
+%D [name] [set]
+
+\unexpanded\def\definefieldbodyset
+ {\dodoubleempty\scrn_field_define_set}
+
+\def\scrn_field_define_set[#tag][#list]%
+ {\clf_definefieldset{#tag}{#list}}
+
+\let\dodefinefieldset\definefieldbodyset % compatibility
+
+%D A few testing macros:
+
+\def\doifelsefieldbody #tag{\clf_doifelsefield{#tag}}
+\def\doifelsefieldcategory#tag{\clf_doifelsefieldcategory{#tag}}
+
+\let\doiffieldbodyelse \doifelsefieldbody
+\let\doiffieldcategoryelse\doifelsefieldcategory
+
+\let\doiffieldelse \doifelsefieldbody % compatibility / will be dropped
+\let\doifelsefield \doifelsefieldbody % compatibility / will be dropped
+
+%D We still support the traditional method of defining fields:
+%D
+%D \starttyping
+%D \definefield [name] [type] [category] [values] [default]
+%D
+%D \definefield [WWWW] [text] [textsetup] [default text]
+%D \definefield [XXXX] [push] [pushsetup] [yes,no] [yes]
+%D \definefield [XXXX] [check] [checksetup] [yes,no] [yes]
+%D \definefield [YYYY] [combo] [combosetup] [a,b,c,d] [b]
+%D \definefield [ZZZZ] [radio] [radiosetup] [W,X,Y,Z] [Y]
+%D
+%D \definesubfield [W] [subsetup] [p,q]
+%D \definesubfield [X,Y] [subsetup] [p,r]
+%D \definesubfield [Z] [subsetup] [y,z]
+%D
+%D evt \definemainfield ... wanneer geplaatst voor subs gegeven
+%D
+%D \clonefield [XXXX] [XX,YY] [mysetup] [on,off]
+%D \clonefield [Z] [AA,BB] [somesetup] [true,false]
+%D \clonefield [Z] [CC,DD] [anothersetup]
+%D
+%D \copyfield [XXXX] [PP,QQ,RR]
+%D \stoptyping
+%D
+%D Keep in mind that you can also use \type {\definefieldbody} to
+%D achieve the same.
+
+\unexpanded\def\definefield {\doquintupleempty\scrn_field_define_field}
+\unexpanded\def\definesubfield{\dotripleempty \scrn_field_define_subfield}
+\unexpanded\def\clonefield {\doquadrupleempty\scrn_field_clone_field}
+\unexpanded\def\copyfield {\dodoubleempty \scrn_field_copy_field}
+
+\let\definemainfield\definefield % obsolete !
+
+\def\scrn_field_define_field[#tag][#type][#category][#values][#default]%
+ {\definefieldbody[#tag][\c!type=#type,\c!category=#category,\c!values={#values},\c!default={#default}]}
+
+\def\scrn_field_define_subfield[#tag][#category][#values]%
+ {\definefieldbody[#tag][\c!type=sub,\c!category=#category,\c!values={#values}]}
+
+\def\scrn_field_clone_field[#parent][#tag][#category][#values]%
+ {\definefieldbody[#tag][#parent][\c!category=#category,\c!values={#values}]}
+
+\def\scrn_field_copy_field[#parent][#tag]%
+ {\definefieldbody[#tag][#parent]}
+
+%D We hook fields into the (viewer based) layering mechanism
+%D (implemented as properties).
+
+\appendtoks
+ \let\currentfieldcategory\empty
+ \doifelse{\interactionparameter\c!fieldlayer}\v!auto
+ {\setupcurrentfieldcategory[\c!fieldlayer=\currentviewerlayer]}%
+ {\setupcurrentfieldcategory[\c!fieldlayer=]}%
+\to \everysetupinteraction
+
+\setupinteraction
+ [\c!fieldlayer=\v!auto] % auto by default
+
+%D The \type {\fieldbody} is the more bare one. One step further goes
+%D \type {\fitfield}, in fact it (now) uses a dedicated instance of
+%D framed: \type {fitfieldframed}.
+%D
+%D \starttyping
+%D \ruledhbox{\fieldbody[Email][height=\strutht,depth=\strutdp,style=normal]}
+%D \ruledhbox{\fitfield[Email][height=\strutht,depth=\strutdp,style=normal]}
+%D \ruledhbox{\fitfield[buttona]}
+%D \stoptyping
+
+\newbox\b_scrn_field_fit_symbol
+
+\defineframed
+ [fitfieldframed]
+ [\c!strut=\v!no,
+ \c!frame=off,
+ \c!offset=\v!overlay,
+ \c!align=]
+
+\unexpanded\def\fitfield
+ {\dodoubleempty\scrn_field_fit}
+
+\def\scrn_field_fit[#tag][#settings]%
+ {\iflocation
+ \begingroup
+ \edef\currentdefaultfieldvalue{\clf_getdefaultfieldvalue{#tag}}%
+ \setbox\b_scrn_field_fit_symbol\hbox{\symbol[\currentdefaultfieldvalue]}%
+ \fitfieldframed
+ {\fieldbody[#tag]
+ [\c!width=\wd\b_scrn_field_fit_symbol,
+ \c!height=\ht\b_scrn_field_fit_symbol,
+ \c!depth=\dp\b_scrn_field_fit_symbol,
+ #settings]}%
+ \endgroup
+ \fi}
+
+%D The traditional field command does some labeling and
+%D boxing:
+
+\installcorenamespace{fieldlabel}
+\installcorenamespace{fieldcontent}
+\installcorenamespace{fieldtotal}
+
+\installparameterhandler \??fieldlabel {fieldlabelframed}
+\installparameterhandler \??fieldcontent {fieldcontentframed}
+\installparameterhandler \??fieldtotal {fieldtotalframed}
+
+\installsetuphandler \??fieldlabel {fieldlabelframed}
+\installsetuphandler \??fieldcontent {fieldcontentframed}
+\installsetuphandler \??fieldtotal {fieldtotalframed}
+
+\installinheritedframed {fieldlabelframed}
+\installinheritedframed {fieldcontentframed}
+\installinheritedframed {fieldtotalframed}
+
+\unexpanded\def\setupfield {\doquintupleempty\scrn_field_setup_field}
+\unexpanded\def\setupfields{\doquadrupleempty\scrn_field_setup_fields}
+
+\setupfieldcontentframed
+ [\c!align=\v!flushleft,
+ \c!strut=\v!no,
+ \s!parent=\??regularframed] % needs checking
+
+\setupfieldcontentframed % independent
+ [\c!alternative=\v!normal,
+ \c!type=\v!line,
+ \c!width=5em,
+ \c!height=\lineheight,
+ \c!depth=\zeropoint,
+ \c!align=\v!flushleft,
+ \c!option=\v!printable,
+ \c!n=1024]
+
+\setupfieldlabelframed
+ [\c!style=,
+ \c!color=,
+ \c!align=\v!flushleft,
+ \s!parent=\??regularframed] % needs checking
+
+\setupfieldtotalframed
+ [%\c!alternative={\v!label,\v!frame,\v!horizontal},
+ \c!strut=\v!no,
+ \c!align=,
+ \s!parent=\??regularframed] % needs checking
+
+% \setupcurrent
+
+\def\scrn_field_setup_field[#tag][#variant][#totalsettings][#labelsettings][#fieldsettings]%
+ {\iffifthargument
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#fieldsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel,#labelsettings]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#fieldsettings]%
+ \else\iffourthargument
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#labelsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#labelsettings]%
+ \else\ifthirdargument
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#totalsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant}]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#totalsettings]%
+ \else\ifsecondargument
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#variant]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#variant]%
+ \fi\fi\fi\fi}
+
+\def\scrn_field_setup_fields[#variant][#totalsettings][#labelsettings][#fieldsettings]%
+ {\iffourthargument
+ \setupfieldtotalframed [\c!alternative={#variant},#totalsettings]%
+ \setupfieldlabelframed [#labelsettings]%
+ \setupfieldcontentframed[#fieldsettings]%
+ \else\ifthirdargument
+ \setupfieldtotalframed [#variant]%
+ \setupfieldlabelframed [#totalsettings]%
+ \setupfieldcontentframed[#labelsettings]%
+ \else\ifsecondargument
+ \setupfieldtotalframed [#variant]%
+ \setupfieldcontentframed[#totalsettings]%
+ \else
+ \setupfieldtotalframed [#variant]%
+ \fi\fi\fi}
+
+% just to get the chain right for no category:
+
+\definefieldcategory [][\s!parent=\??fieldcontent]
+%setupfieldtotalframed [][\s!parent=\??fieldtotal]
+%setupfieldlabelframed [][\s!parent=\??fieldlabel]
+%setupfieldcontentframed[][\s!parent=\??fieldcontent]
+
+% no longer supported:
+
+\let\resetfields\relax
+
+\def\scrn_field_load_scripts{\useJSscripts[fld]\globallet\scrn_field_load_scripts\relax}
+
+\newconditional\fieldlabelshown
+\newconditional\fieldframeshown
+\newconditional\fieldisvertical
+\newconditional\fieldishorizontal
+
+\unexpanded\def\field
+ {\dodoubleempty\scrn_field_direct}
+
+\def\scrn_field_direct[#tag][#label]% can be sped up with \setupcurrentfieldtotalframed etc
+ {\iflocation
+ \dontleavehmode
+ \begingroup
+ \scrn_field_load_scripts
+ \edef\currentfieldbody {#tag}%
+ \edef\currentfieldlabel {#label}%
+ \edef\currentfieldcategory{\clf_getfieldcategory{#tag}}%
+ \ifx\currentfieldlabel\empty
+ \let\currentfieldlabel\currentfieldbody
+ \fi
+ \ifx\currentfieldcategory\empty
+ \setupfieldtotalframed [\currentfieldbody][\s!parent=\??fieldtotal]%
+ \setupfieldlabelframed [\currentfieldbody][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[\currentfieldbody][\s!parent=\??fieldcontent]%
+ \definefieldcategory [\currentfieldbody]%
+ \setupfieldbody [\currentfieldbody][\c!category=\currentfieldbody]%
+ \let\currentfieldcategory\currentfieldbody
+ \fi
+ \let\currentfieldtotalframed \currentfieldcategory
+ \let\currentfieldlabelframed \currentfieldcategory
+ \let\currentfieldcontentframed\currentfieldcategory
+ \scrn_field_analyze_setups
+ \ifconditional\fieldframeshown
+ \inheritedfieldtotalframedframed % lower framedoffset
+ \bgroup
+ \else
+ \vbox
+ \bgroup
+ \fi
+ \dontcomplain
+ \ifconditional\fieldlabelshown
+ \scrn_field_set_label_box
+ \fi
+ \scrn_field_set_content_box
+ \ifconditional\fieldlabelshown
+ \ifconditional\fieldisvertical
+ \scrn_field_flush_vertical
+ \else
+ \scrn_field_flush_horizontal
+ \fi
+ \else
+ \scrn_field_flush_content
+ \fi
+ \egroup
+ \endgroup
+ \fi}
+
+% opties: veld, label, kader, vertikaal/horizontaal
+
+\newbox\b_scrn_field_label
+\newbox\b_scrn_field_content
+
+% lower framedoffset
+
+\def\scrn_field_set_label_box
+ {\setbox\b_scrn_field_label\hbox
+ {\reshapeframeboxtrue % else wrong dimensions % still needed?
+ \inheritedfieldlabelframedframed
+ {\currentfieldlabel}}}
+
+% \c!fieldoffset=-\framedoffset,\c!fieldbackgroundcolor=,
+% \hbox{\lower\@@fdfieldoffset\hbox{\typesetfield}}
+
+\def\scrn_field_set_content_box
+ {\setbox\b_scrn_field_content\hbox
+ {\reshapeframeboxtrue % else wrong dimensions (to be checked)
+ \doifnothing{\fieldcontentframedparameter\c!height}
+ {\ifconditional\fieldisvertical
+ \setfieldcontentframedparameter\c!height{6ex}%
+ \else\ifconditional\fieldishorizontal
+ \setfieldcontentframedparameter\c!height{\vsize}%
+ \else
+ \setfieldcontentframedparameter\c!height{2cm}%
+ \fi\fi}%
+ \doifnothing{\fieldcontentframedparameter\c!width}
+ {\ifconditional\fieldisvertical
+ \setfieldcontentframedparameter\c!width{\hsize}%
+ \else\ifconditional\fieldishorizontal
+ \setfieldcontentframedparameter\c!width{20em}%
+ \else
+ \setfieldcontentframedparameter\c!width{2cm}%
+ \fi\fi}%
+ \inheritedfieldcontentframedframed % lower framedoffset
+ {\fieldbody
+ [\currentfieldbody]
+ [\c!width=\framedwidth,\c!height=\framedheight]}}}
+
+
+\def\scrn_field_flush_vertical
+ {\vbox
+ {\copy\b_scrn_field_label
+ \fieldtotalframedparameter\c!inbetween
+ \copy\b_scrn_field_content}}
+
+\def\scrn_field_flush_horizontal
+ {\hbox
+ {\vbox \ifdim\ht\b_scrn_field_content>\ht\b_scrn_field_label to \ht\b_scrn_field_content \fi
+ {\fieldtotalframedparameter\c!before
+ \copy\b_scrn_field_label
+ \fieldtotalframedparameter\c!after}%
+ \hskip\fieldtotalframedparameter\c!distance
+ \vbox \ifdim\ht\b_scrn_field_label>\ht\b_scrn_field_content to \ht\b_scrn_field_label \fi
+ {\fieldtotalframedparameter\c!before
+ \box\b_scrn_field_content
+ \fieldtotalframedparameter\c!after}}}
+
+\def\scrn_field_flush_content
+ {\box\b_scrn_field_content}
+
+%D todo: replace \processallactionsinset
+
+\def\scrn_field_analyze_setups
+ {\setfalse\fieldlabelshown
+ \setfalse\fieldframeshown
+ \setfalse\fieldishorizontal
+ \setfalse\fieldisvertical
+ \normalexpanded{\processallactionsinset[\fieldtotalframedparameter\c!alternative]}
+ [ \v!reset=>\setfalse\fieldlabelshown
+ \setfalse\fieldframeshown
+ \setfalse\fieldishorizontal
+ \setfalse\fieldisvertical,
+ \v!label=>\settrue\fieldlabelshown,
+ \v!frame=>\settrue\fieldframeshown,
+ \v!horizontal=>\settrue\fieldishorizontal,
+ \v!vertical=>\settrue\fieldisvertical]%
+ \ifconditional\fieldisvertical
+ \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\d_framed_local_offset,\c!align=\v!right,\c!width=20em]%
+ \else\ifconditional\fieldishorizontal
+ \setupfieldtotalframed[\c!distance=\d_framed_local_offset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]%
+ \else
+ \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=,\c!align=\c!left]%
+ \fi\fi
+ \setupfieldtotalframed[\c!n=,\c!before=,\c!after=\vss,\c!style=,\c!color=]}
+
+%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}}
+
+%D \CONTEXT\ had tooltips right from the moment that it
+%D supported fields. Due to the at that moment somewhat
+%D limited \PDF\ specification, they were implemented
+%D using \JAVASCRIPT, but nowadays more kind of actions
+%D are supported, so we can do without. The \MKIV\ version
+%D also supports definition of tooltips and configuration.
+%D
+%D \starttyping
+%D before \tooltip[right]{inbetween}{a very nice tip} after\par
+%D before \tooltip[align=normal]{inbetween}{a very\\nice tip} after\par
+%D before \tooltip[middle]{inbetween}{a very nice tip} after\par
+%D before \tooltip[left]{inbetween}{a very nice tip} after\par
+%D \stoptyping
+
+\newbox \b_scrn_tooltip_anchor
+\newbox \b_scrn_tooltip_text
+\newcount\c_scrn_tooltip_n
+
+\installcorenamespace{tooltip}
+
+\installframedcommandhandler \??tooltip {tooltip} \??tooltip
+
+\setuptooltip
+ [\c!location=\v!right,
+ \c!frame=\v!off,
+ \c!offset=.1ex,
+ \c!background=\v!color,
+ \c!backgroundcolor=gray]
+
+\appendtoks
+ \setuevalue\currenttooltip{\scrn_tooltip_direct{\currenttooltip}}%
+\to \everydefinetooltip
+
+\unexpanded\def\scrn_tooltip_direct#tag%
+ {\def\currenttooltip{#tag}%
+ \doifelselocation
+ {\dosingleempty\scrn_tooltip_indeed}
+ {\dosingleempty\scrn_tooltip_ignore}}
+
+\def\scrn_tooltip_ignore[#settings]#anchortext#tiptext%
+ {#anchortext}
+
+\def\scrn_tooltip_indeed[#settings]#anchortext#tiptext% a more modern aproach (push buttons)
+ {\dontleavehmode \hbox \bgroup
+ \dontcomplain
+ \global\advance\c_scrn_tooltip_n\plusone
+ \edef\currenttooltipname{tooltip:\number\c_scrn_tooltip_n}%
+ \setbox\b_scrn_tooltip_anchor\hbox
+ {\strut#anchortext}%
+ \doifelseassignment{#settings}
+ {\setupcurrenttooltip[#settings]}%
+ {\setupcurrenttooltip[\c!location=#settings]}%
+ \setbox\b_scrn_tooltip_text\hbox
+ {\lettooltipparameter\c!location\empty
+ \inheritedtooltipframed{#tiptext}}%
+ \definesymbol
+ [\currenttooltipname:txt]
+ [\copy\b_scrn_tooltip_text]%
+ \definefieldbody
+ [\currenttooltipname:txt]
+ [\c!type=push,
+ \c!width=\wd\b_scrn_tooltip_text,
+ \c!height=\ht\b_scrn_tooltip_text,
+ \c!depth=\dp\b_scrn_tooltip_text,
+ \c!option=\v!hidden,
+ \c!values=\currenttooltipname:txt]%
+ \setbox\b_scrn_tooltip_text\hbox
+ {\fieldbody[\currenttooltipname:txt]}%
+ \setbox\b_scrn_tooltip_text\hbox
+ {\strut\lower\dimexpr.25ex+\ht\b_scrn_tooltip_text\relax\box\b_scrn_tooltip_text}%
+ \edef\currenttooltiplocation{\tooltipparameter\c!location}%
+ \ifx\currenttooltiplocation\v!left
+ \hsmashed{\hskip\wd\b_scrn_tooltip_anchor\llap{\box\b_scrn_tooltip_text}}%
+ \else\ifx\currenttooltiplocation\v!middle
+ \hsmashed to \wd\b_scrn_tooltip_anchor{\hss\box\b_scrn_tooltip_text\hss}%
+ \else
+ \hsmashed{\box\b_scrn_tooltip_text}%
+ \fi\fi
+ \definesymbol
+ [\currenttooltipname:but]
+ [\hphantom{\copy\b_scrn_tooltip_anchor}]%
+ \definefieldbody
+ [\currenttooltipname:but]
+ [\c!type=push,
+ \c!regionin=action(show{\currenttooltipname:txt}),
+ \c!regionout=action(hide{\currenttooltipname:txt}),
+ \c!width=\wd\b_scrn_tooltip_anchor,
+ \c!height=\ht\b_scrn_tooltip_anchor,
+ \c!depth=\dp\b_scrn_tooltip_anchor]%
+ \hsmashed{\fieldbody[\currenttooltipname:but]}%
+ \egroup
+ #anchortext}% when hyphenated the text wil stick out ... such are fields and we cannot use a link here
+
+\definetooltip[tooltip]
+
+%D From messages on the mailing list we can conclude that
+%D fieldstacks are used so we keep them in the core:
+%D
+%D \starttyping
+%D \definesymbol[one] [one]
+%D \definesymbol[two] [two]
+%D \definesymbol[three][three]
+%D
+%D \definefieldstack[mine][one,two,three]
+%D \fieldstack[mine]
+%D \fieldstack[mine]
+%D
+%D \goto{walk field}[Walk{mine}]
+%D \stoptyping
+
+% todo: expand #symbols
+
+\installcorenamespace {fieldstack}
+
+\unexpanded\def\definefieldstack
+ {\dotripleargument\scrn_fieldstack_define}
+
+\def\scrn_fieldstack_define[#tag][#symbols][#settings]%
+ {\ifcsname\??fieldstack#tag\endcsname
+ % already done
+ \else
+ \setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
+ \fi}
+
+\unexpanded\def\fieldstack
+ {\dotripleempty\scrn_fieldstack_direct}
+
+\def\scrn_fieldstack_direct[#tag][#symbols][#settings]%
+ {\ifsecondargument
+ \scrn_fieldstack_define[#tag][#symbols][#settings]%
+ \fi
+ \csname\??fieldstack#tag\endcsname}
+
+\newbox\b_scrn_fieldstack_box
+
+\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}]%
+ \else
+ \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default=]%
+ \fi
+ \setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}%
+ \setcollector
+ [fieldstack]
+ {\fieldbody
+ [\currentfieldstackname]
+ [\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
+ {\iflocation
+ \dontleavehmode
+ \begingroup
+ \setupfieldcategory[\c!start=1,#settings]% was just \??fieldcategory
+ \scrn_field_load_scripts
+ \definecollector
+ [fieldstack]%
+ [\c!corner=\v!middle,
+ \c!location=\v!middle]%
+ \scratchcounter\zerocount
+ \processcommalist[#symbols]{\scrn_fieldstack_add{#tag}{#settings}}%
+ \flushcollector[fieldstack]%
+ \endgroup
+ \fi}
+
+%D Another goodie. Two actions can be hookes into an overlay.
+%D
+%D \starttyping
+%D \defineviewerlayer[test]
+%D
+%D \startviewerlayer[test]Hide Me\stopviewerlayer
+%D
+%D \defineoverlay
+%D [WithTest]
+%D [{\overlayrollbutton[HideLayer{test}][VideLayer{test}]}]
+%D
+%D \framed[background=WithTest]{toggle}
+%D \stoptyping
+
+\newcount\c_scrn_rollbutton_n
+
+\unexpanded\def\overlayrollbutton
+ {\dodoubleargument\scrn_rollbutton_overlay}
+
+\def\scrn_rollbutton_overlay[#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}
+
+% \protect \endinput % THE FOLLOWING CODE IS NOT CHECKED
+
+%D I will redo these when I need them.
+
+% \setupinteraction[state=start]
+%
+% \definepushbutton [reset]
+%
+% \startuniqueMPgraphic{whatever}{color}
+% fill fullcircle xysized (OverlayWidth,OverlayHeight) withcolor \MPvar{color} ;
+% \stopuniqueMPgraphic
+%
+% \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=red}]
+% \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=green}]
+% \definepushsymbol [reset] [d] [\uniqueMPgraphic{whatever}{color=blue}]
+%
+% \starttext
+% \startTEXpage
+% \pushbutton [reset] [page(2)]
+% \stopTEXpage
+% \startTEXpage
+% \pushbutton [reset] [page(1)]
+% \stopTEXpage
+% \stoptext
+
+\newcount\c_scrn_pushbutton_n
+
+\unexpanded\def\definepushbutton % name optional setup
+ {\dodoubleempty\scrn_pushbutton_define}
+
+\def\scrn_pushbutton_define[#tag][#settings]%
+ {\scrn_pushbutton_define_variant{#tag}{n}{push}%
+ \scrn_pushbutton_define_variant{#tag}{r}{\symbol[pushsymbol:#tag:n]}%
+ \scrn_pushbutton_define_variant{#tag}{d}{\symbol[pushsymbol:#tag:r]}%
+ \setvalue{pushbutton:#tag}{\scrn_pushbutton_handle{#tag}{#settings}}}
+
+\def\scrn_pushbutton_define_variant#tag#variant#content%
+ {\doifelsesymboldefined{pushsymbol:#tag:#variant}
+ \donothing
+ {\definesymbol[pushsymbol:#tag:#variant][{#content}]}}
+
+\def\scrn_pushbutton_handle#tag#settings#reference%
+ {\bgroup
+ \global\advance\c_scrn_pushbutton_n\plusone
+ \setupfield
+ [pushbutton]%
+ [\c!frame=\v!overlay,%
+ \c!offset=\v!overlay,%
+ \c!clickout={#reference},%
+ #settings]%
+ \definefield
+ [pushbutton:\number\c_scrn_pushbutton_n]%
+ [push]%
+ [pushbutton]%
+ [pushsymbol:#tag:n,pushsymbol:#tag:r,pushsymbol:#tag:d]%
+ \fitfield
+ [pushbutton:\number\c_scrn_pushbutton_n]%
+ \egroup}
+
+\unexpanded\def\definepushsymbol
+ {\dotripleargument\scrn_pushsymbol_define}
+
+\def\scrn_pushsymbol_define[#tag][#variant]% [#reference]
+ {\definesymbol[pushsymbol:#tag:#variant]}
+
+\def\pushbutton
+ {\dodoubleargument\scrn_pushbutton_direct}
+
+\def\scrn_pushbutton_direct[#tag][#variant]%
+ {\executeifdefined{pushbutton:#tag}\gobbleoneargument{#variant}}
+
+%D We plug into the menu system
+
+\unexpanded\def\scrn_menu_psh_start[#reference]#text\stoppsh
+ {\starttxt\pushbutton[\currentmenu][#reference]\stoptxt}
+
+\unexpanded\def\scrn_menu_psh_direct[#reference]#text\\
+ {\scrn_menu_psh_start[#reference]\stoprob}
+
+\appendtoks
+ \let\startpsh\scrn_menu_psh_start
+ \let\stoppsh \relax
+ \let\psh \scrn_menu_psh_direct
+\to \everysetmenucommands
+
+%D Another goodie: (unchecked in \MKIV)
+
+% calls:
+% {..} [JS..]
+% [left] {..} [JS..]
+% [a=b] {..} [JS..]
+% [left] [a=b] {..} [JS..]
+%
+% \setupbuttons[offset=0pt,frame=off] % alternative=hidden
+%
+% \rollbutton {Manuals} [JS(Goto_File{show-man.pdf})]
+% \rollbutton {Articles} [JS(Goto_File{show-art.pdf})]
+% \rollbutton {Papers} [JS(Goto_File{show-pap.pdf})]
+% \rollbutton {Presentations} [JS(Goto_File{show-pre.pdf})]
+% \rollbutton {Resources} [JS(Goto_File{show-res.pdf})]
+%
+% \rob [JS(...)] bla bla \\
+
+% \definecolor[rollover:n][red]
+% \definecolor[rollover:r][green]
+% \definecolor[rollover:d][blue]
+
+\definepalet
+ [rollover]
+ [n=red,
+ r=green,
+ d=blue]
+
+\newcount\c_scrn_rollbutton_n_button
+\newcount\c_scrn_rollbutton_n_symbol
+
+\unexpanded\def\rollbutton
+ {\dodoubleempty\scrn_rollbutton}
+
+\def\scrn_rollbutton_symbol_m
+ {\scrn_rollbutton_symbol_indeed
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \setinteractionmenuparameter
+ \useinteractionmenustyleandcolor}
+
+\def\scrn_rollbutton_symbol_b
+ {\scrn_rollbutton_symbol_indeed
+ \buttonparameter
+ \inheritedbuttonframed
+ \setbuttonparameter
+ \usebuttonstyleandcolor}
+
+\def\scrn_rollbutton[#tag][#settings]#text[#reference]%
+ {\dontleavehmode
+ \bgroup
+ \advance\c_scrn_rollbutton_n_button\plusone
+ \advance\c_scrn_rollbutton_n_symbol\plusone
+ \iffirstargument
+ \ifsecondargument
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m
+ \else
+ \doifelseassignment{#tag}
+ {\let\currentbutton\empty
+ \setupcurrentbutton[#tag]%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b}%
+ {\edef\currentinteractionmenu{#tag}%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m}%
+ \fi
+ \else
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b
+ \fi
+ % todo: share symbols, tricky since different dimensions
+ \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]%
+ \egroup}
+
+\unexpanded\def\scrn_rollbutton_symbol_indeed#getparameter#inheritedframed#setparameter#usestyleandcolor#what#text%
+ {\definecolor[rollover][rollover:#what]%
+ \doifelse{#what}{n}% ?
+ {\doifelse{#getparameter\c!alternative}\v!hidden\phantom\hbox}\hbox
+ {#setparameter\c!framecolor {rollover}%
+ #setparameter\c!backgroundcolor{rollover}%
+ #setparameter\c!color {rollover}%
+ #inheritedframed{#usestyleandcolor\c!style\c!color{#text}}}}
+
+%D We plug into the menu system
+
+\unexpanded\def\scrn_menu_rob_start[#reference]#text\stoprob
+ {\starttxt\rollbutton[\currentmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt}
+
+\unexpanded\def\scrn_menu_rob_direct[#reference]#text\\
+ {\scrn_menu_rob_start[#reference]#text\stoprob}
+
+\appendtoks
+ \let\startrob\scrn_menu_rob_start
+ \let\stoprob \relax
+ \let\rob \scrn_menu_rob_direct
+\to \everysetmenucommands
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.lua
new file mode 100644
index 00000000000..99c0565a8b7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.lua
@@ -0,0 +1,157 @@
+if not modules then modules = { } end modules ['scrn-hlp'] = {
+ version = 1.001,
+ comment = "companion to scrn-hlp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+
+local help = { }
+interactions.help = help
+
+local context = context
+local implement = interfaces.implement
+
+local formatters = string.formatters
+
+local a_help = attributes.private("help")
+
+local copy_nodelist = node.copy_list
+local hpack_nodelist = node.hpack
+
+local register_list = nodes.pool.register
+
+local texgetbox = tex.getbox
+
+local nodecodes = nodes.nodecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local data, references = { }, { }
+
+local helpscript = [[
+ function Hide_All_Help(prefix) {
+ var n = 0
+ while (true) {
+ n += 1 ;
+ v = this.getField(prefix + n) ;
+ if (v) {
+ v.hidden = true ;
+ this.dirty = false ;
+ } else {
+ return ;
+ }
+ }
+ }
+]]
+
+local template = "javascript(Hide_All_Help{help:}),action(show{help:%s})"
+
+local function register(specification)
+ local number = specification.number
+ local name = specification.name
+ local box = specification.box
+ if number and name and box then
+ if helpscript then
+ interactions.javascripts.setpreamble("HelpTexts",helpscript)
+ helpscript = false
+ end
+ local b = copy_nodelist(texgetbox(box))
+ register_list(b)
+ data[number] = b
+ if name and name ~= "" then
+ references[name] = number
+ structures.references.define("",name,formatters[template](number))
+ end
+ end
+end
+
+local function collectused(head,used)
+ while head do
+ local id = head.id
+ if id == hlist_code then
+ local a = head[a_help]
+ if a then
+ if not used then
+ used = { a }
+ else
+ used[#used+1] = a
+ end
+ else
+ used = collectused(head.list,used)
+ end
+ elseif id == vlist_code then
+ used = collectused(head.list,used)
+ end
+ head = head.next
+ end
+ return used
+end
+
+local function collect(box)
+ if next(data) then
+ return collectused(texgetbox(box).list)
+ end
+end
+
+local function reference(name)
+ return references[name] or tonumber(name) or 0
+end
+
+help.register = register
+help.collect = collect
+help.reference = reference
+
+implement {
+ name = "registerhelp",
+ actions = register,
+ arguments = {
+ {
+ { "number", "integer" },
+ { "name" },
+ { "box" , "integer" }
+ }
+ }
+}
+
+implement {
+ name = "collecthelp",
+ arguments = "integer",
+ actions = function(box)
+ local used = collect(box)
+ if used then
+ local done = { }
+ context.startoverlay()
+ for i=1,#used do
+ local d = data[used[i]]
+ if d and not done[d] then
+ local box = hpack_nodelist(copy_nodelist(d))
+ context(false,box)
+ done[d] = true
+ else
+ -- error
+ end
+ end
+ context.stopoverlay()
+ end
+ end
+}
+
+implement {
+ name = "helpreference",
+ arguments = "string",
+ actions = function(name)
+ context(reference(name))
+ end
+}
+
+implement {
+ name = "helpaction",
+ arguments = "string",
+ actions = function(name)
+ context(template,reference(name))
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.mkvi
new file mode 100644
index 00000000000..7466e5687b7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-hlp.mkvi
@@ -0,0 +1,167 @@
+%D \module
+%D [ file=scrn-hlp,
+%D version=1998.10.10,
+%D title=\CONTEXT\ Screen Macros,
+%D subtitle=Help (Experimental),
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Screen Macros / Help popups}
+
+%D As this functionality was in the core and as I don't know
+%D how often it is used, we'll keep it around. However, it is
+%D upgraded and usage has changed a bit. We also use some
+%D \LUA\ magic in order to avoid multiple passes.
+
+\registerctxluafile{scrn-hlp}{1.001}
+
+%D Using help boils down to plugging the placement macro
+%D someplace visible, like:
+%D
+%D \starttyping
+%D \setuptexttexts[\centerbox{\placehelp}]
+%D \stoptyping
+%D
+%D When this is done, the following should work out okay:
+%D
+%D \starttyping
+%D test \helptext{word}{tip top 1 is somewhat longer} test
+%D test \helptext{word}{tip top 2} test
+%D
+%D \starthelptext[oeps]
+%D \input tufte
+%D \stophelptext
+%D
+%D test test \showhelp{some help}[oeps] test
+%D test test \button[location=depth]{\helpsignal{oeps}OEPS}[oeps] test
+%D
+%D test test \button[location=depth]{next}[page(2)] test
+%D
+%D \page
+%D
+%D test \helptext{word}{tip top one} test
+%D test \helptext{word}{tip top two} test
+%D \stoptyping
+%D
+%D Currently you need to use the signal in custom macros but
+%D that might change at some point.
+
+\unprotect
+
+% also status
+
+\newbox \b_scrn_help_box
+\newcount\c_scrn_help_n
+
+\definesystemattribute[help][public]
+
+\installcorenamespace{popuphelp}
+
+\installframedcommandhandler \??popuphelp {help} \??popuphelp
+
+\setuphelp
+ [\c!frame=\v!off,
+ \c!align=\v!normal,
+ \c!background=\v!color,
+ \c!backgroundcolor=gray]
+
+\appendtoks
+ \setuevalue \currenthelp {\scrn_help_argument{\currenthelp}}%
+ \setuevalue{\e!start\currenthelp}{\scrn_help_start {\currenthelp}}%
+ \setuevalue{\e!stop \currenthelp}{\scrn_help_stop }%
+\to \everydefinehelp
+
+\unexpanded\def\scrn_help_argument#category%
+ {\def\currenthelp{#category}%
+ \global\advance\c_scrn_help_n\plusone
+ \edef\currenthelpname{help:\number\c_scrn_help_n}%
+ \doifelselocation
+ {\dosingleempty\scrn_help_argument_indeed}
+ {\dosingleempty\scrn_help_argument_ignore}}
+
+\def\scrn_help_argument_indeed[#reference]#text#target%
+ {\edef\currenthelpreference{#reference}%
+ \dontleavehmode \hbox \bgroup
+ \dontcomplain
+ \setbox\b_scrn_help_box\hbox{\strut#text}%
+ \scrn_help_register{#target}%
+ \egroup % can be usernode instead
+ \goto
+ {\helpsignal{\number\c_scrn_help_n}#target}%
+ [\helpaction{\number\c_scrn_help_n}]}
+
+\def\scrn_help_argument_ignore[#reference]#text#target%
+ {#target}
+
+\unexpanded\def\scrn_help_start#category%
+ {\def\currenthelp{#category}%
+ \global\advance\c_scrn_help_n\plusone
+ \edef\currenthelpname{help:\number\c_scrn_help_n}%
+ \dosingleempty\scrn_help_start_indeed}
+
+\def\scrn_help_start_indeed[#reference]%
+ {\edef\currenthelpreference{#reference}%
+ \grabbufferdatadirect\currenthelp{\e!start\currenthelp}{\e!stop\currenthelp}}
+
+\unexpanded\def\scrn_help_stop
+ {\iflocation
+ \scrn_help_register{\getbuffer[\currenthelp]}%
+ \fi}
+
+\def\scrn_help_register#text%
+ {\setbox\b_scrn_help_box\hbox{\inheritedhelpframed{#text}}%
+ \definesymbol
+ [\currenthelpname]
+ [\copy\b_scrn_help_box]%
+ \definefieldbody
+ [\currenthelpname]
+ [\c!type=push,
+ \c!width=\wd\b_scrn_help_box,
+ \c!height=\ht\b_scrn_help_box,
+ \c!depth=\dp\b_scrn_help_box,
+ \c!option=\v!hidden,
+ \c!clickin=action(hide{\currenthelpname}),
+ \c!closepage=action(hide{\currenthelpname}),
+ \c!values=\currenthelpname]%
+ \setbox\b_scrn_help_box\hbox
+ {\fieldbody[\currenthelpname]}%
+ \clf_registerhelp
+ number \c_scrn_help_n
+ name {\currenthelpreference}%
+ box \b_scrn_help_box
+ \relax}
+
+\unexpanded\def\doifelsehelp
+ {\ifcase\c_scrn_help_n
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifhelpelse\doifelsehelp
+
+\unexpanded\def\placehelp % was \helpdata
+ {\ifinpagebody\ifcase\c_scrn_help_n\else
+ \clf_collecthelp\normalpagebox
+ \fi\fi}
+
+\def\helpreference#category%
+ {\clf_helpreference{#category}}
+
+\def\helpaction#category%
+ {\clf_helpaction{#category}}
+
+\unexpanded\def\helpsignal#category%
+ {\hbox attr \helpattribute \helpreference{#category}{}}
+
+\unexpanded\def\showhelp#target[#category]%
+ {\goto{\helpsignal{#category}#target}[#category]}
+
+\definehelp[\v!helptext]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.lua
new file mode 100644
index 00000000000..ce9f9f71b06
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.lua
@@ -0,0 +1,43 @@
+if not modules then modules = { } end modules ['scrn-ini'] = {
+ version = 1.001,
+ comment = "companion to scrn-int.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+interactions = { }
+interactions.general = interactions.general or { }
+local general = interactions.general
+
+local codeinjections = backends.codeinjections
+
+local identitydata = { }
+
+function general.setupidentity(specification)
+ for k, v in next, specification do
+ identitydata[k] = v
+ end
+ codeinjections.setupidentity(specification)
+end
+
+function general.getidentity()
+ return identitydata
+end
+
+interfaces.implement {
+ name = "setupidentity",
+ actions = general.setupidentity,
+ arguments = {
+ {
+ { "title" },
+ { "subtitle" },
+ { "author" },
+ { "creator" },
+ { "date" },
+ { "keywords" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi
new file mode 100644
index 00000000000..0e00fb456b4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi
@@ -0,0 +1,210 @@
+%D \module
+%D [ file=scrn-ini,
+%D version=2011.02.27,
+%D title=\CONTEXT\ Interaction 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 Interaction Macros / Initialization}
+
+\unprotect
+
+\registerctxluafile{scrn-ini}{1.001}
+
+%D There is no interaction at all unless enabled by saying:
+%D
+%D \starttyping
+%D \setupinteraction[state=start]
+%D \stoptyping
+%D
+%D The other settings are:
+%D
+%D \showsetup{setupinteraction}
+
+\installcorenamespace{interaction}
+
+\installswitchcommandhandler \??interaction {interaction} \??interaction
+
+\appendtoks
+ \ifx\previousinteraction\empty
+ \checkinteractionstate
+ \else\ifx\currentinteraction\previousinteraction
+ \checkinteractionstate
+ \fi\fi
+\to \everysetupinteraction
+
+\unexpanded\def\checkinteractionstate
+ {\doifelse{\interactionparameter\c!state}\v!start
+ {\locationtrue \setsystemmode \v!interaction}%
+ {\locationfalse \resetsystemmode\v!interaction}}
+
+\def\doifelselocation % expandable
+ {\iflocation
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflocationelse\doifelselocation
+
+\setupinteraction
+ [\c!state=\v!stop]
+
+\appendtoks
+ \setupinteraction % todo: remember info at the lua end (already possible)
+\to \everyjob
+
+% it makes no sense to create an environment as we will seldom have structured
+% interactionso a general start-stop will do
+%
+% \appendtoks
+% \setuevalue \currentinteraction {\scrn_interaction_direct{\currentinteraction}}%
+% \setuevalue{\e!start\currentinteraction}{\scrn_interaction_start {\currentinteraction}}%
+% \setuevalue{\e!stop \currentinteraction}{\scrn_interaction_stop }%
+% \to \everydefineinteraction
+%
+% \unexpanded\def\scrn_interaction_direct#1%
+% {\edef\currentinteraction{#1}}
+%
+% \unexpanded\def\scrn_interaction_start#1%
+% {\pushmacro\currentinteraction
+% \edef\currentinteraction{#1}}
+%
+% \unexpanded\def\scrn_interaction_stop
+% {\popmacro\currentinteraction}
+%
+% \unexpanded\def\setinteraction[#1]%
+% {\def\currentinteraction{#1}}
+%
+% \defineinteraction[\v!interaction]
+
+\unexpanded\def\startinteraction[#1]%
+ {\pushmacro\currentinteraction
+ \edef\currentinteraction{#1}}
+
+\unexpanded\def\stopinteraction
+ {\popmacro\currentinteraction}
+
+\unexpanded\def\setinteraction[#1]%
+ {\def\currentinteraction{#1}}
+
+\defineinteraction % keep it simple
+ [\v!hidden]
+
+\setupinteraction
+ [\v!hidden]
+ [\c!state=\v!start,
+ \c!color=,
+ \c!contrastcolor=,
+ \c!style=,
+ \c!click=\v!off]
+
+%D As long as there a natural feeling of what can be considered
+%D hyper active or not, we have to tell users where they can
+%D possibly click. We've already seen a few macros that deal
+%D with this visualization, something we definitely do not let
+%D up to the viewer. One way of telling is using a distinctive
+%D typeface, another way is using color.
+%D
+%D There are two colors involved: one for normal hyperlinks,
+%D and one for those that point to the currentpage, the
+%D contrast color.
+
+\definecolor [interactioncolor] [r=0, g=.6, b=0]
+\definecolor [interactioncontrastcolor] [r=.8, g=0, b=0]
+
+%D The next few macros are responsible for highlighting hyper
+%D links. The first one, \type{\showlocation}, is used in those
+%D situations where the typeface is handled by the calling
+%D macro.
+
+%D When we're dealing with pure page references, contrast
+%D colors are used when we are already at the page mentioned.
+
+\unexpanded\def\setlocationcolorspecified#1% not grouped !
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{\interactionparameter\c!contrastcolor}%
+ \ifx\askedcontrastcolor\empty
+ \useinteractioncolorparameter\c!color
+ \else
+ \useinteractioncolorparameter\c!contrastcolor
+ \fi
+ \else % we could just set and if > 0 set again
+ \useinteractioncolorparameter\c!color
+ \fi}
+
+\unexpanded\def\setlocationattributesspecified#1% not grouped !
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{\interactionparameter\c!contrastcolor}%
+ \ifx\askedcontrastcolor\empty
+ \useinteractionstyleandcolor\c!style\c!color
+ \else
+ \useinteractionstyleandcolor\c!style\c!contrastcolor
+ \fi
+ \else % we could just set and if > 0 set again
+ \useinteractionstyleandcolor\c!style\c!color
+ \fi}
+
+\unexpanded\def\setlocationcolorspecspecified#1#2% \resolver
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{#2\c!contrastcolor}%
+ \ifx\askedcontrastcolor\empty
+ \colo_helpers_activate{#2\c!color}%
+ \else
+ \colo_helpers_activate\askedcontrastcolor
+ \fi
+ \else
+ \colo_helpers_activate{#2\c!color}%
+ \fi}
+
+\unexpanded\def\setlocationcolor {\setlocationcolorspecified \referencepagestate}
+\unexpanded\def\setlocationattributes{\setlocationattributesspecified\referencepagestate}
+\unexpanded\def\setlocationcolorspec {\setlocationcolorspecspecified \referencepagestate}
+
+\unexpanded\def\setlocationfont % not grouped !
+ {\useinteractionstyleparameter\c!style}
+
+\setupinteraction
+ [\c!style=\v!bold,
+ \c!color=interactioncolor,
+ \c!contrastcolor=interactioncontrastcolor]
+
+%D Identity
+
+\def\scrn_identity_synchronize
+ {\clf_setupidentity
+ title {\interactionparameter\c!title}%
+ subtitle {\interactionparameter\c!subtitle}%
+ author {\interactionparameter\c!author}%
+ creator {ConTeXt - \contextversion}%
+ date {\interactionparameter\c!date}%
+ keywords {\interactionparameter\c!keyword}%
+ \relax}
+
+\appendtoks
+ \scrn_identity_synchronize
+\to \everysetupinteraction
+
+% this comes before starttext
+
+\appendtoks % not interfaced i.e. english
+ \doifvariable{document}{metadata:author} {\setupinteraction [\c!author=\documentvariable{metadata:author}]}%
+ \doifvariable{document}{metadata:title} {\setupinteraction [\c!title=\documentvariable{metadata:title}]}%
+ \doifvariable{document}{metadata:subject} {\setupinteraction[\c!subject=\documentvariable{metadata:subject}]}%
+ \doifvariable{document}{metadata:keywords}{\setupinteraction[\c!keyword=\documentvariable{metadata:keywords}]}%
+\to \everysetupdocument
+
+\setupinteraction
+ [\c!title=,
+ \c!subtitle=,
+ \c!author=,
+ \c!keyword=,
+ \c!date=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.lua
new file mode 100644
index 00000000000..dba5b4786c4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.lua
@@ -0,0 +1,56 @@
+if not modules then modules = { } end modules ['scrn-pag'] = {
+ version = 1.001,
+ comment = "companion to scrn-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interactions = interactions or { }
+interactions.pages = interactions.pages or { }
+local pages = interactions.pages
+
+local implement = interfaces.implement
+
+local codeinjections = backends.codeinjections
+
+function pages.setupcanvas(specification)
+ codeinjections.setupcanvas(specification)
+end
+
+function pages.setpagetransition(specification)
+ codeinjections.setpagetransition(specification)
+end
+
+implement {
+ name = "setupcanvas",
+ actions = pages.setupcanvas,
+ arguments = {
+ {
+ { "mode" },
+ { "singlesided", "boolean" },
+ { "doublesided", "boolean" },
+ { "leftoffset", "dimen" },
+ { "topoffset", "dimen" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "paperwidth", "dimen" },
+ { "paperheight", "dimen" },
+ { "cropoffset", "dimen" },
+ { "bleedoffset", "dimen" },
+ { "artoffset", "dimen" },
+ { "trimoffset", "dimen" },
+ }
+ }
+}
+
+implement {
+ name = "setpagetransition",
+ actions = pages.setpagetransition,
+ arguments = {
+ {
+ { "n" },
+ { "delay", "integer" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi
new file mode 100644
index 00000000000..7a7effdc40a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi
@@ -0,0 +1,308 @@
+%D \module
+%D [ file=scrn-pag,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Screen Macros,
+%D subtitle=Pages, % moved code
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% pagecomments will be done differently
+
+\writestatus{loading}{ConTeXt Screen Macros / Pages}
+
+\registerctxluafile{scrn-pag}{1.001}
+
+\unprotect
+
+\installcorenamespace{interactionscreen}
+
+\installparameterhandler \??interactionscreen {interactionscreen}
+\installsetuphandler \??interactionscreen {interactionscreen}
+
+\newdimen\canvaswidth
+\newdimen\canvasheight
+\newdimen\canvasbackoffset
+\newdimen\canvastopoffset
+\newdimen\canvasmaxwidth
+\newdimen\canvasmaxheight
+\newdimen\canvascropoffset
+\newdimen\canvastrimoffset
+\newdimen\canvasbleedoffset
+\newdimen\canvasartoffset
+
+\newconditional\c_scrn_canvas_tight_page
+
+\def\scrn_canvas_calculate
+ {\begingroup
+ \edef\currentinteractionscreenwidth {\interactionscreenparameter\c!width }%
+ \edef\currentinteractionscreenheight{\interactionscreenparameter\c!height}%
+ \canvasbackoffset\backspace
+ \canvastopoffset\topspace
+ \donetrue
+ \ifx\currentinteractionscreenwidth\v!max
+ \global\canvaswidth\printpaperwidth
+ \else\ifx\currentinteractionscreenwidth\v!fit
+ \donefalse
+ \global\canvaswidth\dimexpr
+ \leftcombitotal
+ + \makeupwidth
+ + \rightcombitotal
+ + 2\dimexpr
+ \interactionscreenparameter\c!backspace
+ + \interactionscreenparameter\c!horoffset
+ \relax
+ \relax
+ \else\ifx\currentinteractionscreenwidth\v!tight
+ \donefalse
+ \ifdim\backspace>\canvaswidth
+ \ifdim\backspace>\zeropoint\relax
+ \global\advance\canvasbackoffset -\canvaswidth
+ \fi
+ \fi
+ \global\advance\canvaswidth\dimexpr
+ \makeupwidth
+ + \rightcombitotal
+ + 2\dimexpr
+ \interactionscreenparameter\c!backspace
+ + \interactionscreenparameter\c!horoffset
+ \relax
+ \relax
+ \else
+ \donefalse
+ \global\canvaswidth\currentinteractionscreenwidth
+ \fi\fi\fi
+ \ifx\currentinteractionscreenheight\v!max
+ \global\canvasheight\printpaperheight
+ \else\ifx\currentinteractionscreenheight\v!fit
+ \donefalse
+ \global\canvasheight\dimexpr
+ \topheight
+ + \topdistance
+ + \makeupheight
+ + \bottomdistance
+ + \bottomheight
+ + 2\dimexpr
+ \interactionscreenparameter\c!topspace
+ + \interactionscreenparameter\c!veroffset
+ \relax
+ \relax
+ \else\ifx\currentinteractionscreenheight\v!tight
+ \donefalse
+ \global\canvasheight\dimexpr\topheight+\topdistance\relax
+ \ifdim\topspace>\canvasheight
+ \ifdim\topspace>\zeropoint\relax
+ \global\advance\canvastopoffset -\canvasheight
+ \fi
+ \fi
+ \global\advance\canvasheight\dimexpr
+ \makeupheight
+ + \bottomdistance
+ + \bottomheight
+ + 2\dimexpr
+ \interactionscreenparameter\c!topspace
+ + \interactionscreenparameter\c!veroffset
+ \relax
+ \relax
+ \else
+ \donefalse
+ \global\canvasheight\currentinteractionscreenheight
+ \fi\fi\fi
+ \ifconditional\c_page_layouts_location_is_set
+ \global\setfalse\c_scrn_canvas_tight_page
+ \fi
+ \ifconditional\c_scrn_canvas_tight_page
+ \global\canvasmaxwidth \paperwidth
+ \global\canvasmaxheight\paperheight
+ \else
+ \global\canvasmaxwidth \printpaperwidth
+ \global\canvasmaxheight\printpaperheight
+ \fi
+ % new:
+ \ifdone
+ \global\canvascropoffset \layoutcropoffset
+ \global\canvastrimoffset \layouttrimoffset
+ \global\canvasbleedoffset\layoutbleedoffset
+ \global\canvasartoffset \layoutartoffset
+ \else
+ \global\canvascropoffset \zeropoint
+ \global\canvastrimoffset \zeropoint
+ \global\canvasbleedoffset\zeropoint
+ \global\canvasartoffset \zeropoint
+ \fi
+ \endgroup}
+
+\newdimen\layoutcropoffset
+\newdimen\layouttrimoffset
+\newdimen\layoutbleedoffset
+\newdimen\layoutartoffset
+
+\appendtoks
+ \edef\p_cropoffset{\layoutparameter\c!cropoffset}%
+ \ifx\p_cropoffset\v!auto
+ \ifconditional\c_page_layouts_location_is_middle
+ \scratchheight\dimexpr(\printpaperheight-\paperheight)/2\relax
+ \scratchwidth \dimexpr(\printpaperwidth -\paperwidth )/2\relax
+ \layoutcropoffset\ifdim\scratchheight>\scratchwidth\scratchheight\else\scratchwidth\fi
+ \layouttrimoffset \layoutparameter\c!trimoffset
+ \layoutbleedoffset\layoutparameter\c!bleedoffset
+ \layoutartoffset \layoutparameter\c!artoffset
+ \else
+ \writestatus\m!system{auto crop etc only supported when location=middle}%
+ \layoutcropoffset \zeropoint
+ \layouttrimoffset \zeropoint
+ \layoutbleedoffset\zeropoint
+ \layoutartoffset \zeropoint
+ \fi
+ \else
+ \layoutcropoffset \layoutparameter\c!cropoffset
+ \layouttrimoffset \layoutparameter\c!trimoffset
+ \layoutbleedoffset\layoutparameter\c!bleedoffset
+ \layoutartoffset \layoutparameter\c!artoffset
+ \fi
+ \relax
+\to \everysetuplayout
+
+\setuplayout
+ [\c!cropoffset=\zeropoint,
+ \c!trimoffset=\zeropoint,
+ \c!bleedoffset=\zeropoint,
+ \c!artoffset=\zeropoint]
+
+% test the next when something is changed here:
+%
+% \setuppapersize[A5][A3] \showframe
+%
+% % \setuplayout[location=middle] \setupinteractionscreen[option=fit]
+% % \setuplayout[location=middle] \setupinteractionscreen[option=auto]
+% % \setupinteractionscreen[option=fit]
+% % \setupinteractionscreen[option=auto]
+%
+% \starttext \input ward \stoptext
+
+\let\scrn_canvas_synchronize_simple \relax
+\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
+\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
+\to \everysetuplayouttarget
+
+\def\scrn_canvas_synchronize_only
+ {\clf_setupcanvas
+ paperwidth \printpaperwidth
+ paperheight \printpaperheight
+ \relax}
+
+\def\scrn_canvas_synchronize_simple_indeed
+ {\clf_setupcanvas
+ paperwidth \printpaperwidth
+ paperheight \printpaperheight
+ \relax
+ %\global\let\scrn_canvas_synchronize_simple \relax
+ \global\let\scrn_canvas_synchronize_complex\relax}
+
+\def\scrn_canvas_synchronize_complex_indeed
+ {\scrn_canvas_calculate % otherwise we need to hook it into setuppage etc
+ \clf_setupcanvas
+ mode {\interactionscreenparameter\c!option}%
+ singlesided \ifsinglesided true\else false\fi\space
+ doublesided \ifdoublesided true\else false\fi\space
+ leftoffset \canvasbackoffset
+ topoffset \canvastopoffset
+ width \canvaswidth
+ height \canvasheight
+ paperwidth \canvasmaxwidth
+ paperheight \canvasmaxheight
+ cropoffset \canvascropoffset
+ trimoffset \canvastrimoffset
+ bleedoffset \canvasbleedoffset
+ artoffset \canvasartoffset
+ \relax
+ %\global\let\scrn_canvas_synchronize_simple \relax
+ \global\let\scrn_canvas_synchronize_complex\relax}
+
+\appendtoks
+ \begingroup
+ \edef\p_option{\interactionscreenparameter\c!option}%
+ \ifx\p_option\v!max
+ \global\settrue \c_scrn_canvas_tight_page
+ \else\ifx\p_option\v!fit
+ \global\settrue \c_scrn_canvas_tight_page
+ \else
+ \global\setfalse\c_scrn_canvas_tight_page
+ \fi\fi
+ \endgroup
+\to \everysetupinteractionscreen
+
+\setupinteractionscreen
+ [\c!width=\printpaperwidth,
+ \c!height=\printpaperheight,
+ \c!horoffset=\zeropoint,
+ \c!veroffset=\zeropoint,
+ \c!backspace=\backspace,
+ \c!topspace=\topspace,
+ \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
+\to \everysetupinteractionscreen
+
+%D Conditional page breaks:
+
+\unexpanded\def\screen
+ {\dosingleempty\scrn_screen}
+
+\def\scrn_screen[#list]%
+ {\iflocation
+ \page[#list]%
+ \fi}
+
+%D Page transitions:
+
+\let\scrn_transitions_list\empty
+
+\unexpanded\def\setuppagetransitions
+ {\dosingleempty\scrn_transitions_setup}
+
+\def\scrn_transitions_setup[#list]%
+ {\edef\scrn_transitions_list{#list}%
+ \ifx\scrn_transitions_list\v!reset
+ \let\scrn_transitions_list\empty
+ \fi}
+
+\def\scrn_transitions_set
+ {\iflocation \ifx\scrn_transitions_list\empty \else
+ \scrn_transitions_set_indeed
+ \fi \fi}
+
+\def\scrn_transitions_set_indeed
+ {\begingroup
+ \edef\currentinteractionscreendelay{\interactionscreenparameter\c!delay}%
+ \clf_setpagetransition
+ n {\scrn_transitions_list}%
+ delay \ifx\currentinteractionscreendelay\v!none \zerocount\else\currentinteractionscreendelay\fi
+ \relax
+ \endgroup}
+
+\prependtoks
+ \scrn_transitions_set
+\to \everyshipout
+
+\setupinteractionscreen
+ [\c!delay=\v!none]
+
+\setuppagetransitions
+ [\v!reset]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.lua
new file mode 100644
index 00000000000..c1fc9487138
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.lua
@@ -0,0 +1,67 @@
+if not modules then modules = { } end modules ['scrn-ref'] = {
+ version = 1.001,
+ comment = "companion to scrn-int.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interactions = interactions or { }
+interactions.references = interactions.references or { }
+local references = interactions.references
+
+local codeinjections = backends.codeinjections
+
+local expandcurrent = structures.references.expandcurrent
+local identify = structures.references.identify
+
+local implement = interfaces.implement
+
+local function check(what)
+ if what and what ~= "" then
+ local set, bug = identify("",what)
+ return not bug and #set > 0 and set
+ end
+end
+
+local function setopendocumentaction(open)
+ local opendocument = check(open)
+ if opendocument then
+ codeinjections.registerdocumentopenaction(opendocument)
+ expandcurrent()
+ end
+end
+
+local function setclosedocumentaction(close)
+ local closedocument = check(close)
+ if closedocument then
+ codeinjections.registerdocumentcloseaction(closedocument)
+ expandcurrent()
+ end
+end
+
+local function setopenpageaction(open)
+ local openpage = check(open)
+ if openpage then
+ codeinjections.registerpageopenaction(openpage)
+ expandcurrent()
+ end
+end
+
+local function setclosepageaction(close)
+ local closepage = check(close)
+ if closepage then
+ codeinjections.registerpagecloseaction(closepage)
+ expandcurrent()
+ end
+end
+
+references.setopendocument = setopendocumentaction
+references.setclosedocument = setclosedocumentaction
+references.setopenpage = setopenpageaction
+references.setclosepage = setclosepageaction
+
+implement { name = "setopendocumentaction", arguments = "string", actions = setopendocumentaction }
+implement { name = "setclosedocumentaction", arguments = "string", actions = setclosedocumentaction }
+implement { name = "setopenpageaction", arguments = "string", actions = setopenpageaction }
+implement { name = "setclosepageaction", arguments = "string", actions = setclosepageaction }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi
new file mode 100644
index 00000000000..c165e9131c2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi
@@ -0,0 +1,102 @@
+%D \module
+%D [ file=scrn-ref,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Screen Macros,
+%D subtitle=References, % moved code
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Screen Macros / References}
+
+\registerctxluafile{scrn-ref}{1.001}
+
+\unprotect
+
+\appendtoks
+ \doifsomething{\interactionparameter\c!calculate}%
+ {\clf_setfieldcalculationset{\interactionparameter\c!calculate}}%
+ \doifelse{\interactionparameter\c!click }\v!yes
+ \settrue\setfalse\highlighthyperlinks
+ \doifelse{\interactionparameter\c!display}\v!new
+ \settrue\setfalse\gotonewwindow
+ \doifnot {\interactionparameter\c!page}\v!no
+ \scrn_reference_enable_page_destinations
+\to \everysetupinteraction
+
+\def\scrn_reference_enable_page_destinations % no reset
+ {\clf_setinnerreferencemethod{\interactionparameter\c!page}}
+
+\setupinteraction % start fit page and reset form
+ [\c!page=\v!no,
+ \c!click=\v!yes,
+ \c!display=\v!normal,
+ \c!focus=\v!fit,
+ %\c!focusoffset=\zeropoint, % when tested with al views it will become 5\points
+ \c!focusoffset=5\points,
+ \c!calculate=,
+ % rendering:
+ \c!width=\emwidth,
+ \c!height=\zeropoint,
+ \c!depth=\zeropoint,
+ \c!symbolset=]
+
+% for now here, might become per link
+
+\appendtoks
+ \enabledirectives[destinations.offset=\the\dimexpr\interactionparameter\c!focusoffset\relax]%
+\to \everysetupinteraction
+
+%D We have to make sure of some settings:
+
+\def\scrn_reference_set_text_actions
+ {\iflocation
+ \edef\currentinteractionopenaction {\interactionparameter\c!openaction }%
+ \edef\currentinteractioncloseaction{\interactionparameter\c!closeaction}%
+ \ifx\currentinteractionopenaction\empty \else
+ \clf_setopendocumentaction{\currentinteractionopenaction}%
+ \fi
+ \ifx\currentinteractioncloseaction\empty \else
+ \clf_setclosedocumentaction{\currentinteractioncloseaction}%
+ \fi
+ \glet\scrn_reference_set_text_actions\relax
+ \fi}
+
+\def\scrn_reference_set_page_actions
+ {\iflocation
+ \edef\currentinteractionopenpageaction {\interactionparameter\c!openpageaction }%
+ \edef\currentinteractionclosepageaction{\interactionparameter\c!closepageaction}%
+ \ifx\currentinteractionopenpageaction\empty \else
+ \clf_setopenpageaction{\currentinteractionopenpageaction}%
+ \fi
+ \ifx\currentinteractionclosepageaction\empty \else
+ \clf_setclosepageaction{\currentinteractionclosepageaction}%
+ \fi
+ \fi}
+
+\appendtoks \scrn_reference_set_text_actions \to \everyshipout
+\appendtoks \scrn_reference_set_page_actions \to \everyshipout
+
+%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
+
+\setupinteraction % start fit page and reset form
+ [\c!openaction=,
+ \c!closeaction=,
+ \c!openpageaction=,
+ \c!closepageaction=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.lua b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.lua
new file mode 100644
index 00000000000..b9855546e1a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.lua
@@ -0,0 +1,345 @@
+if not modules then modules = { } end modules ['scrn-wid'] = {
+ version = 1.001,
+ comment = "companion to scrn-wid.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interactions = interactions or { }
+local interactions = interactions
+
+local context = context
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+
+local attachments = allocate()
+local comments = allocate()
+local soundclips = allocate()
+local renderings = allocate()
+local linkedlists = allocate()
+
+interactions.attachments = attachments
+interactions.soundclips = soundclips
+interactions.renderings = renderings
+interactions.linkedlists = linkedlists
+
+local texsetbox = tex.setbox
+
+local jobpasses = job.passes
+
+local texgetcount = tex.getcount
+
+local codeinjections = backends.codeinjections
+local nodeinjections = backends.nodeinjections
+
+local variables = interfaces.variables
+local v_auto = variables.auto
+
+local trace_attachments = false trackers.register("widgets.attachments", function(v) trace_attachments = v end)
+
+local report_attachments = logs.reporter("widgets","attachments")
+
+-- Symbols
+
+implement {
+ name = "presetsymbollist",
+ arguments = "string",
+ actions = function(list)
+ codeinjections.presetsymbollist(list)
+ end
+}
+
+-- Attachments
+--
+-- registered : unique id
+-- tag : used at the tex end
+-- file : name that the file has on the filesystem
+-- name : name that the file will get in the output
+-- title : up to the backend
+-- subtitle : up to the backend
+-- author : up to the backend
+-- method : up to the backend (hidden == no rendering)
+
+local nofautoattachments, lastregistered = 0, nil
+
+local function checkregistered(specification)
+ local registered = specification.registered
+ if not registered or registered == "" or registered == v_auto then
+ nofautoattachments = nofautoattachments + 1
+ lastregistered = "attachment-" .. nofautoattachments
+ specification.registered = lastregistered
+ return lastregistered
+ else
+ return registered
+ end
+end
+
+local function checkbuffer(specification)
+ local buffer = specification.buffer
+ if buffer ~= "" then
+ specification.data = buffers.getcontent(buffer) or "<no data>"
+ end
+end
+
+function attachments.register(specification) -- beware of tag/registered mixup(tag is namespace)
+ local registered = checkregistered(specification)
+ checkbuffer(specification)
+ attachments[registered] = specification
+ if trace_attachments then
+ report_attachments("registering %a",registered)
+ end
+ return specification
+end
+
+function attachments.insert(specification)
+ local registered = checkregistered(specification)
+ local r = attachments[registered]
+ if r then
+ if trace_attachments then
+ report_attachments("including registered %a",registered)
+ end
+ for k, v in next, r do
+ local s = specification[k]
+ if s == "" then
+ specification[k] = v
+ end
+ end
+ elseif trace_attachments then
+ report_attachments("including unregistered %a",registered)
+ end
+ checkbuffer(specification)
+ return nodeinjections.attachfile(specification)
+end
+
+implement {
+ name = "registerattachment",
+ actions = attachments.register,
+ arguments = {
+ {
+ { "tag" },
+ { "registered" },
+ { "title" },
+ { "subtitle" },
+ { "author" },
+ { "file" },
+ { "name" },
+ { "buffer" },
+ }
+ }
+}
+
+implement {
+ name = "insertattachment",
+ actions = function(specification)
+ texsetbox("b_scrn_attachment_link",(attachments.insert(specification)))
+ end,
+ arguments = {
+ {
+ { "tag" },
+ { "registered" },
+ { "method" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "colormodel", "integer" },
+ { "colorvalue", "integer" },
+ { "color" },
+ { "transparencyvalue", "integer" },
+ { "symbol" },
+ { "layer" },
+ { "title" },
+ { "subtitle" },
+ { "author" },
+ { "file" },
+ { "name" },
+ { "buffer" },
+ }
+ }
+}
+
+-- Comment
+
+function comments.insert(specification)
+ local buffer = specification.buffer
+ if buffer ~= "" then
+ specification.data = buffers.getcontent(buffer) or ""
+ end
+ return nodeinjections.comment(specification)
+end
+
+implement {
+ name = "insertcomment",
+ actions = function(specification)
+ texsetbox("b_scrn_comment_link",(comments.insert(specification)))
+ end,
+ arguments = {
+ {
+ { "tag" },
+ { "title" },
+ { "subtitle" },
+ { "author" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "nx" },
+ { "ny" },
+ { "colormodel", "integer" },
+ { "colorvalue", "integer" },
+ { "transparencyvalue", "integer" },
+ { "option" },
+ { "symbol" },
+ { "buffer" },
+ { "layer" },
+ }
+ }
+}
+
+-- Soundclips
+
+function soundclips.register(specification)
+ local tag = specification.tag
+ if tag and tag ~= "" then
+ local filename = specification.file
+ if not filename or filename == "" then
+ filename = tag
+ specification.file = filename
+ end
+ soundclips[tag] = specification
+ return specification
+ end
+end
+
+function soundclips.insert(tag)
+ local sc = soundclips[tag]
+ if not sc then
+ -- todo: message
+ return soundclips.register { tag = tag }
+ else
+ return sc
+ end
+end
+
+implement {
+ name = registersoundclip,
+ actions = soundclips.register,
+ arguments = {
+ {
+ { "tag" },
+ { "file" }
+ }
+ }
+}
+
+implement {
+ name = insertsoundclip,
+ actions = soundclips.insert,
+ arguments = {
+ {
+ { "tag" },
+ { "repeat" }
+ }
+ }
+}
+
+-- Renderings
+
+function renderings.register(specification)
+ if specification.label then
+ renderings[specification.label] = specification
+ return specification
+ end
+end
+
+function renderings.rendering(label)
+ local rn = renderings[label]
+ if not rn then
+ -- todo: message
+ return renderings.register { label = label }
+ else
+ return rn
+ end
+end
+
+function renderings.var(label,key)
+ local rn = renderings[label]
+ return rn and rn[key] or ""
+end
+
+implement {
+ name = "renderingvar",
+ actions = { renderings.var, context },
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "registerrendering",
+ actions = renderings.register,
+ arguments = {
+ {
+ { "type" },
+ { "label" },
+ { "mime" },
+ { "filename" },
+ { "option" },
+ }
+ }
+}
+
+-- Rendering:
+
+implement {
+ name = "insertrenderingwindow",
+ actions = function(specification)
+ codeinjections.insertrenderingwindow(specification)
+ end,
+ arguments = {
+ {
+ { "label" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "option" },
+ { "page", "integer" },
+ }
+ }
+}
+
+-- Linkedlists (only a context interface)
+
+implement {
+ name = "definelinkedlist",
+ arguments = "string",
+ actions = function(tag)
+ -- no need
+ end
+}
+
+implement {
+ name = "enhancelinkedlist",
+ arguments = { "string", "integer" },
+ actions = function(tag,n)
+ local ll = jobpasses.gettobesaved(tag)
+ if ll then
+ ll[n] = texgetcount("realpageno")
+ end
+ end
+}
+
+implement {
+ name = "addlinklistelement",
+ arguments = "string",
+ actions = function(tag)
+ local tobesaved = jobpasses.gettobesaved(tag)
+ local collected = jobpasses.getcollected(tag) or { }
+ local currentlink = #tobesaved + 1
+ local noflinks = #collected
+ tobesaved[currentlink] = 0
+ local f = collected[1] or 0
+ local l = collected[noflinks] or 0
+ local p = collected[currentlink-1] or f
+ local n = collected[currentlink+1] or l
+ context.setlinkedlistproperties(currentlink,noflinks,f,p,n,l)
+ -- context.ctxlatelua(function() commands.enhancelinkedlist(tag,currentlink) end)
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi
new file mode 100644
index 00000000000..f4679684c21
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi
@@ -0,0 +1,721 @@
+%D \module
+%D [ file=scrn-int,
+%D version=2011.02.27, % moved from scrn-int
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Widgets,
+%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 Interaction Macros / Widgets}
+
+\registerctxluafile{scrn-wid}{1.001}
+
+% todo: expansion in comments (default is expanded)
+% todo: check renderings ... acrobat crashes too easily on missing one
+
+\unprotect
+
+%D Attachments (mkiv upgraded):
+%D
+%D As usual in \CONTEXT\ we separate the general definition (frontend)
+%D and the rendering (backend).
+
+% old but stil valid method:
+%
+% \useattachment[test.tex]
+% \useattachment[whatever][test.tex]
+% \useattachment[whatever][newname][test.tex]
+% \useattachment[whatever][title][newname][test.tex]
+%
+% new method:
+%
+% \registerattachment[sometag][specification] % name file author title subtitle
+%
+% \attachment[sometag][extra specs]
+% \attachment[test.tex]
+% \attachment[file=test.tex]
+% \attachment[file=test.tex,method=hidden]
+% \attachment[name=newname,file=test.tex]
+% \attachment[title=mytitle,name=newname,file=test.tex]
+%
+% indirect
+%
+% \defineattachment[whatever5][file=test.tex] \attachment[whatever5][method=hidden]
+% \defineattachment[whatever5][file=test.tex,method=hidden] \attachment[whatever5]
+%
+% direct (no definitions)
+%
+% \attachment[test][file=oeps.tex,title=Oeps,author=Hans,subtitle=TeX File,method=hidden]
+% \attachment[label=test,file=oeps.tex,title=Oeps,author=Hans,subtitle=TeX File,method=hidden]
+%
+% autolabel:
+%
+% \attachment[file=oeps.tex,title=Oeps,author=Hans,subtitle=TeX File,method=hidden]
+%
+% % \setupattachments[\c!symbol={symbol-normal,symbol-down}]
+
+% startattachment -> temp file
+
+\newbox\b_scrn_attachment_collect
+\newbox\b_scrn_attachment_link
+\newbox\b_scrn_attachment_symbol
+
+\installcorenamespace{attachment}
+\installcorenamespace{attachmentlocation}
+\installcorenamespace{attachmentmethod}
+
+\installcommandhandler \??attachment {attachment} \??attachment
+
+\let\setupattachments\setupattachment % convenience and compatibility
+
+\setupattachment
+ [\c!state=\v!start,
+ \c!color=\interactionparameter\c!color,
+ %\c!textlayer=,
+ %\c!symbol=,
+ %\c!title=,
+ %\c!subtitle=,
+ %\c!file=, % input filename
+ %\c!name=, % new filename
+ %\c!author=,
+ %\c!method=, % \v!hidden = not in menu
+ %\c!buffer=
+ \c!symbol=,
+ \c!distance=1em,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!depth=\v!fit,
+ \c!location=\v!high]
+
+\unexpanded\def\registerattachment
+ {\dodoubleempty\scrn_attachment_register}
+
+\def\scrn_attachment_register[#tag][#settings]% we save (globally) at the lua end
+ {\ifsecondargument
+ \begingroup
+ \def\currentattachment{_}%
+ \setupcurrentattachment[#settings,\s!parent=\??attachment]%
+ \clf_registerattachment
+ tag {#tag}%
+ registered {#tag}%
+ title {\attachmentparameter\c!title}%
+ subtitle {\attachmentparameter\c!subtitle}%
+ author {\attachmentparameter\c!author}%
+ file {\attachmentparameter\c!file}%
+ name {\attachmentparameter\c!name}%
+ buffer {\attachmentparameter\c!buffer}%
+ \relax
+ \endgroup
+ \else
+ % todo
+ \fi}
+
+\appendtoks
+ \setuevalue \currentattachment {\scrn_attachment_direct{\currentattachment}}%
+ \setuevalue{\e!start\currentattachment}{\scrn_attachment_start {\currentattachment}}%
+ \setuevalue{\e!stop \currentattachment}{\scrn_attachment_stop }%
+\to \everydefineattachment
+
+\unexpanded\def\scrn_attachment_direct#tag%
+ {\edef\currentattachment{#tag}%
+ \doifelselocation
+ {\dodoubleempty\scrn_attachment_direct_status}
+ {\dodoubleempty\scrn_attachment_direct_ignore}}
+
+\def\scrn_attachment_direct_status
+ {\doifelse{\attachmentparameter\c!state}\v!start
+ \scrn_attachment_direct_indeed
+ \scrn_attachment_direct_ignore}
+
+\def\scrn_attachment_direct_indeed[#registered][#settings]%
+ {\bgroup
+ \doifelsenothing{#registered}
+ {\scrn_attachment_inject[\v!auto][]}
+ {\doifelseassignment{#registered}
+ {\scrn_attachment_inject[\v!auto][#registered]}
+ {\scrn_attachment_inject[#registered][#settings]}}%
+ \egroup}
+
+\def\scrn_attachment_direct_ignore[#tag][#settings]%
+ {}
+
+\unexpanded\def\scrn_attachment_start#tag%
+ {\edef\currentattachment{#tag}%
+ \doifelselocation
+ {\dodoubleempty\scrn_attachment_start_indeed}
+ {\dodoubleempty\scrn_attachment_start_ignore}}
+
+\unexpanded\def\scrn_attachment_stop
+ {}
+
+\def\scrn_attachment_start_indeed
+ {\doif{\attachmentparameter\c!state}\v!start
+ {\scrn_attachment_start_indeed}
+ {\scrn_attachment_start_ignore}}
+
+\def\scrn_attachment_start_indeed[#registered][#settings]%
+ {\bgroup
+ \doifelsenothing{#registered}
+ {\def\scrn_attachment_stop{\scrn_attachment_inject[\v!auto][\c!buffer=\v!attachment]\egroup}}%
+ {\doifelseassignment{#registered}
+ {\def\scrn_attachment_stop{\scrn_attachment_inject[\v!auto][\c!buffer=\v!attachment,#registered]\egroup}}%
+ {\def\scrn_attachment_stop{\scrn_attachment_inject[#registered][\c!buffer=\v!attachment,#settings]\egroup}}}%
+ \grabbufferdatadirect\v!attachment{\e!start\currentattachment}{\e!stop\currentattachment}}
+
+\def\scrn_attachment_start_ignore
+ {\expandafter\gobbleuntil\csname\e!stop\currentattachment\endcsname}
+
+\def\scrn_attachment_inject[#registered][#settings]%
+ {\edef\currentattachmentregistered{#registered}%
+ \setupattachment[\currentattachment][#settings]%
+ \expandnamespaceparameter\??attachmentmethod\attachmentparameter\c!method\v!normal}
+
+\setvalue{\??attachmentmethod\v!normal}%
+ {\edef\currentattachmentsymbol{\attachmentparameter\c!symbol}%
+ \edef\currentattachmentwidth {\attachmentparameter\c!width }%
+ \edef\currentattachmentheight{\attachmentparameter\c!height}%
+ \edef\currentattachmentdepth {\attachmentparameter\c!depth }%
+ \ifx\currentattachmentsymbol\empty
+ \ifx\currentattachmentwidth \v!fit\edef\currentattachmentwidth {.5\emwidth}\fi
+ \ifx\currentattachmentheight\v!fit\edef\currentattachmentheight{.5\emwidth}\fi
+ \ifx\currentattachmentdepth \v!fit\let \currentattachmentdepth \zeropoint\fi
+ \else
+ \clf_presetsymbollist{\attachmentparameter\c!symbol}%
+ % we cannot yet ask for the wd/ht/dp of an xform else we could use those
+ \setbox\b_scrn_attachment_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
+ \ifx\currentattachmentwidth \v!fit\edef\currentattachmentwidth {\wd\b_scrn_attachment_symbol}\fi
+ \ifx\currentattachmentheight\v!fit\edef\currentattachmentheight{\ht\b_scrn_attachment_symbol}\fi
+ \ifx\currentattachmentdepth \v!fit\edef\currentattachmentdepth {\dp\b_scrn_attachment_symbol}\fi
+ \fi
+ \clf_insertattachment
+ tag {\currentattachment}%
+ registered {\currentattachmentregistered}%
+ width \dimexpr\currentattachmentwidth \relax
+ height \dimexpr\currentattachmentheight\relax
+ depth \dimexpr\currentattachmentdepth \relax
+ color {\attachmentparameter\c!color}%
+ colormodel \attribute\colormodelattribute
+ colorvalue \numexpr\thecolorattribute{\attachmentparameter\c!color}\relax % or are these chardefs
+ transparencyvalue \numexpr\thetransparencyattribute{\attachmentparameter\c!color}\relax % or are these chardefs
+ symbol {\currentattachmentsymbol}%
+ layer {\attachmentparameter\c!textlayer}%
+ % these will be overloaded by registered when available
+ title {\attachmentparameter\c!title}%
+ subtitle {\attachmentparameter\c!subtitle}%
+ author {\attachmentparameter\c!author}%
+ file {\attachmentparameter\c!file}%
+ 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}
+
+\setvalue{\??attachmentmethod\v!hidden}%
+ {\clf_insertattachment
+ tag {\currentattachment}%
+ registered {\currentattachmentregistered}%
+ method {\v!hidden}%
+ \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%
+ {\global\setbox\b_scrn_attachment_collect\hbox\bgroup
+ \ifvoid\b_scrn_attachment_collect\else
+ \box\b_scrn_attachment_collect
+ \hskip\attachmentparameter\c!distance
+ \fi
+ #content%
+ \egroup}
+
+\unexpanded\def\placeattachments
+ {\ifvoid\b_scrn_attachment_collect\else
+ \box\b_scrn_attachment_collect
+ \fi}
+
+\defineattachment[attachment]
+
+% \ifx\currentinterface\defaultinterface \else
+% \defineattachment[\v!attachment]
+% \fi
+
+% backward compatible:
+
+\unexpanded\def\useattachment
+ {\doquadrupleempty\scrn_attachment_use}
+
+\def\scrn_attachment_use[#tag][#title][#name][#file]%
+ {\iffourthargument
+ \registerattachment[#tag][title=#title,name=#name,file=#file]%
+ \else\ifthirdargument
+ \registerattachment[#tag][title=#title,name=#title,file=#name]%
+ \else\ifsecondargument
+ \registerattachment[#tag][title=#title,name=#title,file=#title]%
+ \else
+ \registerattachment[#tag][title=#tag,name=#tag,file=#tag]%
+ \fi\fi\fi}
+
+%D Comments:
+
+% test
+%
+% \startcomment
+% hello beautiful\\world
+% \stopcomment
+%
+% test
+%
+% \startcomment[hello]
+% hello << eerste >>
+% beautiful
+% world
+% \stopcomment
+%
+% test
+%
+% \startcomment[hello][color=green,width=10cm,height=3cm]
+% hello
+% beautiful
+% world
+% \stopcomment
+%
+% test
+%
+% \startcomment[hello][color=red,width=4cm,height=3cm]
+% hello
+%
+% beautiful
+%
+% world
+% \stopcomment
+%
+% test
+%
+% \startcomment[symbol=Balloon]
+% Do we want this kind of rubish?
+% \stopcomment
+%
+% test
+%
+% \definesymbol [comment-normal][{\externalfigure[cow.pdf]}]
+% \definesymbol [comment-down] [{\externalfigure[cow.pdf]}]
+%
+% \def\CowSymbol#1#2%
+% {\scale
+% [\c!height=#1]
+% {\startMPcode
+% loadfigure "koe.mp" number 1 ;
+% refill currentpicture withcolor #2 ;
+% \stopMPcode}}
+%
+% \definesymbol [comment-normal]
+% [\CowSymbol{4ex}{red}]
+%
+% \definesymbol [comment-down]
+% [\CowSymbol{4ex}{green}]
+%
+% \setupcomment
+% [\c!symbol={comment-normal,comment-down},
+% \c!option=\v!buffer]
+%
+% \startcomment[hello]
+% oeps
+% \stopcomment
+%
+% test
+%
+% \setupcomment
+% [\c!symbol=normal,
+% \c!option=max,width=10cm]
+%
+% \startcomment[hello]
+% oeps
+% \stopcomment
+%
+% test
+
+\installcorenamespace{comment}
+\installcorenamespace{commentlocation}
+
+\installcommandhandler \??comment {comment} \??comment
+
+\newbox\b_scrn_comment_collect
+\newbox\b_scrn_comment_rendering
+\newbox\b_scrn_comment_link
+\newbox\b_scrn_comment_symbol
+
+\setupcomment
+ [\c!state=\v!start,
+ \c!distance=1em,
+ \c!color=\interactionparameter\c!color,
+ \c!space=\v!no,
+ \c!symbol=,
+ %\c!title=,
+ %\c!option=,
+ %\c!textlayer=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!depth=\v!fit,
+ \c!nx=40,
+ \c!ny=10,
+ \c!location=\v!high]
+
+\appendtoks
+ \setuevalue \currentcomment {\scrn_comment_argument{\currentcomment}}%
+ \setuevalue{\e!start\currentcomment}{\scrn_comment_start {\currentcomment}}%
+ \setuevalue{\e!stop \currentcomment}{\scrn_comment_stop }%
+\to \everydefinecomment
+
+\unexpanded\def\scrn_comment_argument#category%
+ {\def\currentcomment{#category}%
+ \doifelselocation
+ {\dodoubleempty\scrn_comment_argument_status}
+ {\dodoubleempty\scrn_comment_argument_ignore}}
+
+\def\scrn_comment_argument_status
+ {\doifelse{\commentparameter\c!state}\v!start
+ \scrn_comment_argument_indeed
+ \scrn_comment_argument_ignore}
+
+\def\scrn_comment_argument_indeed[#title][#settings]#text%
+ {\doifelseassignment{#title}
+ {\setupcurrentcomment[#title]}
+ {\setupcurrentcomment[\c!title=#title,#settings]}%
+ \clf_assignbuffer{\v!comment}{#text}\catcodetable\relax% todo: expansion control, but expanded by default (xml)
+ \scrn_comment_inject
+ \ignorespaces}
+
+\def\scrn_comment_argument_ignore[#title][#settings]#text%
+ {\ignorespaces}
+
+\unexpanded\def\scrn_comment_start#category%
+ {\def\currentcomment{#category}%
+ \doifelselocation
+ {\dodoubleempty\scrn_comment_start_status}
+ {\dodoubleempty\scrn_comment_start_ignore}}
+
+\def\scrn_comment_start_status
+ {\doifelse{\commentparameter\c!state}\v!start
+ {\scrn_comment_start_indeed}
+ {\scrn_comment_start_ignore}}
+
+\def\scrn_comment_start_indeed[#title][#settings]%
+ {\bgroup
+ \doifelseassignment{#title}
+ {\setupcurrentcomment[#title]}
+ {\setupcurrentcomment[\c!title=#title,#settings]}%
+ \unexpanded\def\scrn_comment_stop{\scrn_comment_inject\egroup}%
+ \grabbufferdatadirect\v!comment{\e!start\currentcomment}{\e!stop\currentcomment}}
+
+\def\scrn_comment_start_ignore
+ {\expandafter\gobbleuntil\csname\e!stop\currentcomment\endcsname}
+
+\unexpanded\def\scrn_comment_stop
+ {}
+
+\installcorenamespace{commentmethods}
+
+\unexpanded\def\scrn_comment_inject
+ {\expandnamespaceparameter\??commentmethods\commentparameter\c!method\v!normal}
+
+%D Beware: comments symbols don't scale in acrobat (cf. spec but somewhat
+%D weird, esp because for instance attachment symbols do scale).
+
+\setvalue{\??commentmethods\v!normal}%
+ {\edef\currentcommentsymbol{\commentparameter\c!symbol}%
+ \edef\currentcommentwidth {\commentparameter\c!width }%
+ \edef\currentcommentheight{\commentparameter\c!height}%
+ \edef\currentcommentdepth {\commentparameter\c!depth }%
+ \ifx\currentcommentsymbol\empty
+ \ifx\currentcommentwidth \v!fit\edef\currentcommentwidth {.5\emwidth}\fi
+ \ifx\currentcommentheight\v!fit\edef\currentcommentheight{.5\emwidth}\fi
+ \ifx\currentcommentdepth \v!fit\let \currentcommentdepth \zeropoint\fi
+ \else
+ \clf_presetsymbollist{\commentparameter\c!symbol}%
+ % we cannot yet ask for the wd/ht/dp of an xform else we could use those
+ \setbox\b_scrn_comment_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
+ \ifx\currentcommentwidth \v!fit\edef\currentcommentwidth {\wd\b_scrn_comment_symbol}\fi
+ \ifx\currentcommentheight\v!fit\edef\currentcommentheight{\ht\b_scrn_comment_symbol}\fi
+ \ifx\currentcommentdepth \v!fit\edef\currentcommentdepth {\dp\b_scrn_comment_symbol}\fi
+ \fi
+ \clf_insertcomment
+ tag {\currentcomment}%
+ title {\commentparameter\c!title}%
+ subtitle {\commentparameter\c!subtitle}%
+ author {\commentparameter\c!author}%
+ width \dimexpr\currentcommentwidth\relax
+ height \dimexpr\currentcommentheight\relax
+ depth \dimexpr\currentcommentdepth\relax
+ nx {\commentparameter\c!nx}%
+ ny {\commentparameter\c!ny}%
+ colormodel \attribute\colormodelattribute
+ colorvalue \numexpr\thecolorattribute{\commentparameter\c!color}\relax
+ transparencyvalue \numexpr\thetransparencyattribute{\commentparameter\c!color}\relax
+ option {\commentparameter\c!option}% % todo
+ symbol {\commentparameter\c!symbol}%
+ buffer {\v!comment}%
+ layer {\commentparameter\c!textlayer}%
+ \relax
+ \wd\b_scrn_comment_link\currentcommentwidth
+ \ht\b_scrn_comment_link\currentcommentheight
+ \dp\b_scrn_comment_link\currentcommentdepth
+ \expandnamespaceparameter\??commentlocation\commentparameter\c!location\s!unknown}
+
+\setvalue{\??commentmethods\v!hidden}%
+ {}
+
+% 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!none}%
+ {\global\setbox\b_scrn_comment_collect\hbox\bgroup
+ \ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
+ \hskip\commentparameter\c!distance
+ \fi
+ \box\b_scrn_comment_link
+ \egroup}
+
+\setvalue{\??commentlocation\s!unknown}%
+ {\ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
+ \fi}
+
+\unexpanded\def\placecomments
+ {\ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
+ \fi}
+
+\definecomment[comment]
+
+% \ifx\currentinterface\defaultinterface \else
+% \definecomment[\v!comment]
+% \fi
+
+%D Soundclips:
+%D
+%D Defining sound tracks:
+%D
+%D \starttyping
+%D \useexternalsoundtrack[label][file]
+%D \stoptyping
+%D
+%D associated actions: StartSound StopSound PauseSound ResumeSound
+%D
+%D Todo: like external figures, also search on path,
+%D although, they need to be present ar viewing time, so ...
+
+\installcorenamespace{externalsoundtracks}
+
+\installsetuponlycommandhandler \??externalsoundtracks {externalsoundtracks}
+
+\setupexternalsoundtracks
+ [\c!option=]
+
+\unexpanded\def\useexternalsoundtrack
+ {\dodoubleargument\scrn_soundtrack_indeed}
+
+\def\scrn_soundtrack_indeed[#tag][#filename]%
+ {\clf_registersoundclip
+ tag {#tag}%
+ file {#filename}%
+ \relax}
+
+\def\checksoundtrack#tag% yet untested in mkiv (also move management to lua)
+ {\iflocation
+ \clf_insertsoundclip
+ tag {#tag}%
+ repeat {\directexternalsoundtrackparameter\c!option}%
+ \relax
+ \fi}
+
+%D Renderings (not yet tested in mkvi):
+
+% Todo: multiple instances and inheritance .. will be done when
+% needed i.e. when I see usage.
+
+\let\currentrendering\empty
+
+\definereference[StartCurrentRendering] [\v!StartRendering {\currentrendering}]
+\definereference[StopCurrentRendering] [\v!StopRendering {\currentrendering}]
+\definereference[PauseCurrentRendering] [\v!PauseRendering {\currentrendering}]
+\definereference[ResumeCurrentRendering][\v!ResumeRendering{\currentrendering}]
+
+\unexpanded\def\useexternalrendering{\doquadrupleempty\scrn_rendering_use}
+\unexpanded\def\setinternalrendering{\dodoubleempty \scrn_rendering_set}
+
+\def\scrn_rendering_use[#tag][#mime][#file][#option]%
+ {\clf_registerrendering
+ type {external}%
+ label {#tag}%
+ mime {#mime}%
+ filename {#file}%
+ option {#option}%
+ \relax}
+
+\def\scrn_rendering_set[#tag][#option]% {content} % crappy
+ {\bgroup
+ \dowithnextbox
+ {\clf_registerrendering
+ type {internal}%
+ label {#tag}%
+ mime {IRO}% brrr
+ filename {#tag}%
+ option {#option}%
+ \relax
+ \let\objectoffset\zeropoint
+ \setobject{IRO}{#tag}\hbox{\box\nextbox}%
+ \egroup}%
+ \hbox}
+
+\def\renderingtype #tag{\clf_renderingvar{#tag}{type}}
+\def\renderingoption#tag{\clf_renderingvar{#tag}{option}}
+
+\newdimen\d_scrn_rendering_width \d_scrn_rendering_width 8cm
+\newdimen\d_scrn_rendering_height \d_scrn_rendering_height 6cm
+
+\let\m_scrn_rendering_page\!!zerocount
+
+\installcorenamespace{renderingwindow}
+
+\installframedcommandhandler \??renderingwindow {renderingwindow} \??renderingwindow
+
+\appendtoks
+ \letrenderingwindowparameter\c!openpageaction \empty
+ \letrenderingwindowparameter\c!closepageaction\empty
+ \setrenderingwindowparameter\c!width {\d_scrn_rendering_width }%
+ \setrenderingwindowparameter\c!height {\d_scrn_rendering_height}%
+\to \everypresetrenderingwindow
+
+\unexpanded\def\placerenderingwindow
+ {\dodoubleempty\scrn_rendering_place_window}
+
+\def\scrn_rendering_place_window[#window][#rendering]% do all in lua
+ {\bgroup
+ \edef\currentrendering{\ifsecondargument#rendering\else#window\fi}%
+ % create fall back if needed
+ \edef\currentrenderingwindow{\namedrenderingwindowparameter{#window}\c!width}% stupid test, we need a proper one here
+ \ifx\currentrenderingwindow\empty
+ \let\currentrenderingwindow\s!default
+ \definerenderingwindow[\currentrenderingwindow]% why not global
+ \else
+ \edef\currentrenderingwindow{#window}%
+ \fi
+ \edef\currentrenderingtype{\renderingtype\currentrendering}%
+ \ifx\currentrenderingtype\s!internal
+ \getobjectdimensions{IRO}\currentrendering
+ \d_scrn_rendering_height\dimexpr\objectheight+\objectdepth\relax
+ \d_scrn_rendering_width\objectwidth\relax
+ \dogetobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page
+ \else\ifx\currentrenderingwindow\s!default
+ \d_scrn_rendering_height\vsize
+ \d_scrn_rendering_width \hsize
+ \let\m_scrn_rendering_page\realpageno
+ \else
+ \d_scrn_rendering_height\renderingwindowparameter\c!height
+ \d_scrn_rendering_width \renderingwindowparameter\c!width
+ \let\m_scrn_rendering_page\realpageno
+ \fi\fi
+ % todo:
+ % \handlereferenceactions{\renderingwindowparameter\c!openpageaction }\dosetuprenderingopenpageaction
+ % \handlereferenceactions{\renderingwindowparameter\c!closepageaction}\dosetuprenderingclosepageaction
+ \letrenderingwindowparameter\c!offset\v!overlay
+ \inheritedrenderingwindowframed
+ {\vfill
+ \clf_insertrenderingwindow
+ label {\currentrendering}%
+ width \d_scrn_rendering_width
+ height \d_scrn_rendering_height
+ option {\renderingoption\currentrendering}%
+ page \m_scrn_rendering_page
+ \relax
+ \hfill}%
+ \egroup}
+
+%D Linkedlists (not tested in mkvi):
+
+% %D The next mechanism, linked lists, is quite old and
+% %D is \MKIV'd for completeness. I will finish the
+% %D configuration part when I need it.
+% %D
+% %D \starttyping
+% %D \setupinteraction[state=start]
+% %D \definelinkedlist[demo]
+% %D \dorecurse{10}{\linkedlistelement[demo]{link \recurselevel} \page}
+% %D \stoptyping
+%
+% \definesystemvariable {lk} % LinK
+%
+% \installcommandhandler\??lk{linkedlist}\??lk
+%
+% \let\setupbutton\setuplinkedlists\setuplinkedlist
+%
+% \appendtoks
+% \clf_definelinkedlist{\currentlinkedlist}%
+% \to \everydefinelinkedlist
+%
+% \def\setlinkedlistproperties#1#2#3#4#5#6%
+% {\def\currentlink {#1}%
+% \def\noflinks {#2}%
+% \def\firstlink {#3}%
+% \def\previouslink{#4}%
+% \def\nextlink {#5}%
+% \def\lastlink {#6}}
+%
+% \def\linkedlistelement[#1]#2% currently no view support
+% {\dontleavehmode\hbox\bgroup
+% #2%
+% \iflocation
+% \edef\currentlinkedlist{#1}%
+% \ifcsname\??lk\currentlinkedlist\s!parent\endcsname
+% \hskip\linkedlistparameter\c!distance
+% \clf_addlinklistelement{\currentlinkedlist}%
+% \expanded{\ctxlatecommand{enhancelinkedlist("\currentlinkedlist",\currentlink)}}% can also be done at the lua end
+% \dogotosomepage {\??lk\currentlinkedlist}\gotobegincharacter \firstlink
+% \ifnum\noflinks>\plustwo
+% \dogotosomepage{\??lk\currentlinkedlist}\gobackwardcharacter\previouslink
+% \dogotosomepage{\??lk\currentlinkedlist}\goforwardcharacter \nextlink
+% \fi
+% \dogotosomepage {\??lk\currentlinkedlist}\gotoendcharacter \lastlink
+% \else
+% \writestatus\m!interactions{no such linked list: \currentlinkedlist}%
+% \fi
+% \fi
+% \egroup}
+%
+% \setuplinkedlists
+% [\c!distance=.25em,
+% \c!width=\v!fit,
+% \c!location=\v!low,
+% \c!color=\interactionparameter\c!color,
+% \c!frame=\v!off,
+% \c!background=,
+% \c!backgroundcolor=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua
new file mode 100644
index 00000000000..77c58b18a95
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua
@@ -0,0 +1,1008 @@
+if not modules then modules = { } end modules ['scrp-cjk'] = {
+ 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"
+}
+
+-- 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.
+
+local utfchar = utf.getchar
+
+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 getnext = nuts.getnext
+local getprev = nuts.getprev
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local getid = nuts.getid
+local getattr = nuts.getattr
+local getsubtype = nuts.getsubtype
+local getfield = nuts.getfield
+
+local setchar = nuts.setchar
+
+local nodepool = nuts.pool
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_penalty = nodepool.penalty
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+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 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 fontdata = fonthashes.identifiers
+local quaddata = fonthashes.quads
+local spacedata = fonthashes.spaces
+
+local decomposed = characters.hangul.decomposed
+
+local trace_details = false trackers.register("scripts.details", function(v) trace_details = v end)
+
+local report_details = logs.reporter("scripts","detail")
+
+-- raggedleft is controlled by leftskip and we might end up with a situation where
+-- the intercharacter spacing interferes with this; the solution is to patch the
+-- nodelist but better is to use veryraggedleft
+
+local inter_char_shrink = 0
+local inter_char_stretch = 0
+local inter_char_half_shrink = 0
+local inter_char_half_stretch = 0
+local inter_char_quarter_shrink = 0
+local inter_char_quarter_stretch = 0
+
+local full_char_width = 0
+local half_char_width = 0
+local quarter_char_width = 0
+
+local inter_char_hangul_penalty = 0
+
+local function set_parameters(font,data)
+ -- beware: parameters can be nil in e.g. punk variants
+ local quad = quaddata[font]
+ full_char_width = quad
+ half_char_width = quad/2
+ quarter_char_width = quad/4
+ inter_char_shrink = data.inter_char_shrink_factor * quad
+ inter_char_stretch = data.inter_char_stretch_factor * quad
+ inter_char_half_shrink = data.inter_char_half_shrink_factor * quad
+ inter_char_half_stretch = data.inter_char_half_stretch_factor * quad
+ inter_char_quarter_shrink = data.inter_char_quarter_shrink_factor * quad
+ inter_char_quarter_stretch = data.inter_char_quarter_stretch_factor * quad
+ inter_char_hangul_penalty = data.inter_char_hangul_penalty
+end
+
+-- a test version did compensate for crappy halfwidth but we can best do that
+-- at font definition time and/or just assume a correct font
+
+local function trace_detail(current,what)
+ local prev = getprev(current)
+ local c_id = getid(current)
+ local p_id = prev and getid(prev)
+ if c_id == glyph_code then
+ local c_ch = getchar(current)
+ if p_id == glyph_code then
+ local p_ch = p_id and getchar(prev)
+ report_details("[%C %a] [%s] [%C %a]",p_ch,hash[p_ch],what,c_ch,hash[c_ch])
+ else
+ report_details("[%s] [%C %a]",what,c_ch,hash[c_ch])
+ end
+ else
+ if p_id == glyph_code then
+ local p_ch = p_id and getchar(prev)
+ report_details("[%C %a] [%s]",p_ch,hash[p_ch],what)
+ else
+ report_details("[%s]",what)
+ end
+ end
+end
+
+local function trace_detail_between(p,n,what)
+ local p_ch = getchar(p)
+ local n_ch = getchar(n)
+ report_details("[%C %a] [%s] [%C %a]",p_ch,hash[p_ch],what,n_ch,hash[n_ch])
+end
+
+local function nobreak(head,current)
+ if trace_details then
+ trace_detail(current,"break")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+end
+
+local function stretch_break(head,current)
+ if trace_details then
+ trace_detail(current,"stretch break")
+ end
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function shrink_break(head,current)
+ if trace_details then
+ trace_detail(current,"shrink break")
+ end
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"no break stretch")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function korean_break(head,current)
+ if trace_details then
+ trace_detail(current,"korean break")
+ end
+ insert_node_before(head,current,new_penalty(inter_char_hangul_penalty))
+end
+
+local function nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_stretch_nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch nobreak shrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_stretch_nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch nobreak autoshrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_shrink_nobreak_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink nobreak stretch")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function nobreak_autoshrink_nobreak_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink nobreak stretch")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function nobreak_shrink_break_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function nobreak_autoshrink_break_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function nobreak_shrink_break_stretch_nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch nobreak shrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function japanese_between_full_close_open(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese between full close open")
+ end
+ insert_node_before(head,current,new_kern(-half_char_width))
+ insert_node_before(head,current,new_glue(half_char_width,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_kern(-half_char_width))
+end
+
+local function japanese_between_full_close_full_close(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese between full close full close")
+ end
+ insert_node_before(head,current,new_kern(-half_char_width))
+ -- insert_node_before(head,current,new_glue(half_char_width,0,inter_char_half_shrink))
+end
+
+local function japanese_before_full_width_punct(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese before full width punct")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(quarter_char_width,0,inter_char_quarter_shrink))
+ insert_node_before(head,current,new_kern(-quarter_char_width))
+end
+
+local function japanese_after_full_width_punct(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese after full width punct")
+ end
+ insert_node_before(head,current,new_kern(-quarter_char_width))
+ insert_node_before(head,current,new_glue(quarter_char_width,0,inter_char_quarter_shrink))
+end
+
+local function nobreak_autoshrink_break_stretch_nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch nobreak autoshrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_autoshrink_break_stretch_nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch nobreak shrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_shrink_break_stretch_nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch nobreak autoshrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+end
+
+local function nobreak_stretch_break_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch break shrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+local function nobreak_stretch_break_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch break autoshrink")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+end
+
+-- Korean: hangul
+
+local korean_0 = {
+}
+
+local korean_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = korean_break,
+ hiragana = korean_break,
+ katakana = korean_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = korean_break,
+ other = korean_break,
+}
+
+local korean_2 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = stretch_break,
+ other = stretch_break,
+}
+
+local korean_3 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+ other = nobreak,
+}
+
+local korean_4 = {
+ jamo_initial = nobreak,
+ korean = nobreak,
+ chinese = nobreak,
+ hiragana = nobreak,
+ katakana = nobreak,
+ half_width_open = nobreak,
+ half_width_close = nobreak,
+ full_width_open = nobreak,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+ hyphen = nobreak,
+ non_starter = nobreak,
+ other = nobreak,
+}
+
+local korean_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak_stretch,
+ full_width_open = stretch_break,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local injectors = { -- [previous] [current]
+ jamo_final = korean_1,
+ korean = korean_1,
+ chinese = korean_1,
+ hiragana = korean_1,
+ katakana = korean_1,
+ hyphen = korean_2,
+ start = korean_0,
+ other = korean_2,
+ non_starter = korean_3,
+ full_width_open = korean_4,
+ half_width_open = korean_4,
+ full_width_close = korean_5,
+ full_width_punct = korean_5,
+ half_width_close = korean_5,
+}
+
+local function process(head,first,last)
+ if first ~= last then
+ local lastfont, previous, last = nil, "start", nil
+ while true do
+ local upcoming, id = getnext(first), getid(first)
+ if id == glyph_code then
+ local a = getattr(first,a_scriptstatus)
+ local current = numbertocategory[a]
+ local action = injectors[previous]
+ if action then
+ action = action[current]
+ if action then
+ local font = getfont(first)
+ if font ~= lastfont then
+ lastfont = font
+ set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)])
+ end
+ action(head,first)
+ end
+ end
+ previous = current
+ else -- glue
+ local p, n = getprev(first), upcoming
+ if p and n then
+ local pid, nid = getid(p), 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]
+ if not pcjk or not ncjk
+ or pcjk == "korean" or ncjk == "korean"
+ or pcjk == "other" or ncjk == "other"
+ or pcjk == "jamo_final" or ncjk == "jamo_initial" then
+ previous = "start"
+ else -- if head ~= first then
+ remove_node(head,first,true)
+ previous = pcjk
+ -- else
+ -- previous = pcjk
+ end
+ else
+ previous = "start"
+ end
+ else
+ previous = "start"
+ end
+ end
+ if upcoming == last then -- was stop
+ break
+ else
+ first = upcoming
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "hangul",
+ injector = process,
+ datasets = { -- todo: metatables
+ default = {
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.50, -- of quad
+ inter_char_quarter_stretch_factor = 0.50, -- of quad
+ inter_char_hangul_penalty = 50,
+ },
+ },
+}
+
+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))
+ if lead_consonant then
+ setchar(current,lead_consonant)
+ local m = copy_node(current)
+ setchar(m,medial_vowel)
+ head, current = insert_node_after(head,current,m)
+ if tail_consonant then
+ local t = copy_node(current)
+ setchar(t,tail_consonant)
+ head, current = insert_node_after(head,current,t)
+ end
+ done = true
+ end
+ end
+ return tonode(head), done
+end
+
+-- nodes.tasks.prependaction("processors","normalizers","scripts.decomposehangul")
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+registerotffeature {
+ name = "decomposehangul",
+ description = "decompose hangul",
+ processors = {
+ position = 1,
+ node = scripts.decomposehangul,
+ }
+}
+
+-- Chinese: hanzi
+
+local chinese_0 = {
+}
+
+local chinese_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_2 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_3 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_4 = {
+-- jamo_initial = nil,
+-- korean = nil,
+-- chinese = nil,
+-- hiragana = nil,
+-- katakana = nil,
+ half_width_open = nobreak_autoshrink,
+ half_width_close = nil,
+ full_width_open = nobreak_shrink,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+-- other = nil,
+}
+
+local chinese_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_6 = {
+ jamo_initial = nobreak_stretch,
+ korean = nobreak_stretch,
+ chinese = nobreak_stretch,
+ hiragana = nobreak_stretch,
+ katakana = nobreak_stretch,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = nobreak_stretch,
+}
+
+local chinese_7 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_shrink_break_stretch,
+ chinese = stretch_break, -- nobreak_shrink_break_stretch,
+ hiragana = stretch_break, -- nobreak_shrink_break_stretch,
+ katakana = stretch_break, -- nobreak_shrink_break_stretch,
+ half_width_open = nobreak_shrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_open = nobreak_shrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_punct = nobreak_shrink_nobreak_stretch,
+ hyphen = nobreak_shrink_break_stretch,
+ non_starter = nobreak_shrink_break_stretch,
+ other = nobreak_shrink_break_stretch,
+}
+
+local chinese_8 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_autoshrink_break_stretch,
+ chinese = stretch_break, -- nobreak_autoshrink_break_stretch,
+ hiragana = stretch_break, -- nobreak_autoshrink_break_stretch,
+ katakana = stretch_break, -- nobreak_autoshrink_break_stretch,
+ half_width_open = nobreak_autoshrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_open = nobreak_autoshrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_punct = nobreak_autoshrink_nobreak_stretch,
+ hyphen = nobreak_autoshrink_break_stretch,
+ non_starter = nobreak_autoshrink_break_stretch,
+ other = nobreak_autoshrink_break_stretch,
+}
+
+local injectors = { -- [previous] [current]
+ jamo_final = chinese_1,
+ korean = chinese_1,
+ chinese = chinese_2,
+ hiragana = chinese_2,
+ katakana = chinese_2,
+ hyphen = chinese_3,
+ start = chinese_4,
+ other = chinese_5,
+ non_starter = chinese_5,
+ full_width_open = chinese_6,
+ half_width_open = chinese_6,
+ full_width_close = chinese_7,
+ full_width_punct = chinese_7,
+ half_width_close = chinese_8,
+}
+
+local function process(head,first,last)
+ if first ~= last then
+ local lastfont, previous, last = nil, "start", nil
+ while true do
+ local upcoming, id = getnext(first), getid(first)
+ if id == glyph_code then
+ local a = getattr(first,a_scriptstatus)
+ local current = numbertocategory[a]
+ local action = injectors[previous]
+ if action then
+ action = action[current]
+ if action then
+ local font = getfont(first)
+ if font ~= lastfont then
+ lastfont = font
+ set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)])
+ end
+ action(head,first)
+ end
+ end
+ previous = current
+ else -- glue
+ local p, n = getprev(first), upcoming
+ if p and n then
+ local pid, nid = getid(p), 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]
+ if not pcjk or not ncjk
+ or pcjk == "korean" or ncjk == "korean"
+ or pcjk == "other" or ncjk == "other"
+ or pcjk == "jamo_final" or ncjk == "jamo_initial"
+ or pcjk == "half_width_close" or ncjk == "half_width_open" then -- extra compared to korean
+ previous = "start"
+ else -- if head ~= first then
+ remove_node(head,first,true)
+ previous = pcjk
+ -- else
+ -- previous = pcjk
+ end
+ else
+ previous = "start"
+ end
+ else
+ previous = "start"
+ end
+ end
+ if upcoming == last then -- was stop
+ break
+ else
+ first = upcoming
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "hanzi",
+ injector = process,
+ datasets = {
+ default = {
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.50, -- of quad
+ inter_char_quarter_stretch_factor = 0.50, -- of quad
+ inter_char_hangul_penalty = 50,
+ },
+ },
+}
+
+-- Japanese: idiographic, hiragana, katakana, romanji / jis
+
+local japanese_0 = {
+}
+
+local japanese_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_2 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = japanese_before_full_width_punct, -- nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_3 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_4 = {
+-- jamo_initial = nil,
+-- korean = nil,
+-- chinese = nil,
+-- hiragana = nil,
+-- katakana = nil,
+ half_width_open = nobreak_autoshrink,
+ half_width_close = nil,
+ full_width_open = nobreak_shrink,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+-- other = nil,
+}
+
+local japanese_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_6 = {
+ jamo_initial = nobreak_stretch,
+ korean = nobreak_stretch,
+ chinese = nobreak_stretch,
+ hiragana = nobreak_stretch,
+ katakana = nobreak_stretch,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = nobreak_stretch,
+}
+
+local japanese_7 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_shrink_break_stretch,
+ chinese = japanese_after_full_width_punct, -- stretch_break
+ hiragana = japanese_after_full_width_punct, -- stretch_break
+ katakana = japanese_after_full_width_punct, -- stretch_break
+ half_width_open = nobreak_shrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_open = japanese_between_full_close_open, -- !!
+ full_width_close = japanese_between_full_close_full_close, -- nobreak_shrink_nobreak_stretch,
+ full_width_punct = nobreak_shrink_nobreak_stretch,
+ hyphen = nobreak_shrink_break_stretch,
+ non_starter = nobreak_shrink_break_stretch,
+ other = nobreak_shrink_break_stretch,
+}
+
+local japanese_8 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_autoshrink_break_stretch,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_autoshrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_open = nobreak_autoshrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_punct = nobreak_autoshrink_nobreak_stretch,
+ hyphen = nobreak_autoshrink_break_stretch,
+ non_starter = nobreak_autoshrink_break_stretch,
+ other = nobreak_autoshrink_break_stretch,
+}
+
+local injectors = { -- [previous] [current]
+ jamo_final = japanese_1,
+ korean = japanese_1,
+ chinese = japanese_2,
+ hiragana = japanese_2,
+ katakana = japanese_2,
+ hyphen = japanese_3,
+ start = japanese_4,
+ other = japanese_5,
+ non_starter = japanese_5,
+ full_width_open = japanese_6,
+ half_width_open = japanese_6,
+ full_width_close = japanese_7,
+ full_width_punct = japanese_7,
+ half_width_close = japanese_8,
+}
+
+local function process(head,first,last)
+ if first ~= last then
+ local lastfont, previous, last = nil, "start", nil
+ while true do
+ local upcoming, id = getnext(first), getid(first)
+ if id == glyph_code then
+ local a = getattr(first,a_scriptstatus)
+ local current = numbertocategory[a]
+ local action = injectors[previous]
+ if action then
+ action = action[current]
+ if action then
+ local font = getfont(first)
+ if font ~= lastfont then
+ lastfont = font
+ set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)])
+ end
+ action(head,first)
+ end
+ end
+ previous = current
+ -- elseif id == math_code then
+ -- upcoming = getnext(end_of_math(current))
+ -- previous = "start"
+ else -- glue
+ local p, n = getprev(first), upcoming -- we should remember prev
+ if p and n then
+ local pid, nid = getid(p), 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]
+ if not pcjk or not ncjk
+ or pcjk == "korean" or ncjk == "korean"
+ or pcjk == "other" or ncjk == "other"
+ or pcjk == "jamo_final" or ncjk == "jamo_initial"
+ or pcjk == "half_width_close" or ncjk == "half_width_open" then -- extra compared to korean
+ previous = "start"
+ else -- if head ~= first then
+ if id == glue_code then
+ -- also scriptstatus check?
+ local subtype = getsubtype(first)
+ if subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code then
+ -- for the moment no distinction possible between space and userskip
+ local w = getfield(first,"width")
+ local s = spacedata[getfont(p)]
+ if w == s then -- could be option
+ if trace_details then
+ trace_detail_between(p,n,"space removed")
+ end
+ remove_node(head,first,true)
+ end
+ end
+ end
+ previous = pcjk
+ -- else
+ -- previous = pcjk
+ end
+ else
+ previous = "start"
+ end
+ else
+ previous = "start"
+ end
+ end
+ if upcoming == last then -- was stop
+ break
+ else
+ first = upcoming
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "nihongo", -- what name to use?
+ injector = process,
+ datasets = {
+ default = {
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.25, -- of quad
+ inter_char_quarter_stretch_factor = 0.25, -- of quad
+ inter_char_hangul_penalty = 50,
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua
new file mode 100644
index 00000000000..43cb2ff6a4e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua
@@ -0,0 +1,157 @@
+if not modules then modules = { } end modules ['scrp-eth'] = {
+ 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"
+}
+
+-- at some point I will review the script code but for the moment we
+-- do it this way; so space settings like with cjk yet
+
+local nuts = nodes.nuts
+
+local getnext = nuts.getnext
+local getfont = nuts.getfont
+local getid = nuts.getid
+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
+
+-- syllable [zerowidthspace] syllable
+-- syllable [zerowidthspace] word
+-- syllable [zerowidthspace] sentence
+-- word [nobreakspace] syllable
+-- word [space] word
+-- word [space] sentence
+-- sentence [nobreakspace] syllable
+-- 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_word = {
+ ethiopic_syllable = insert_space,
+ ethiopic_word = insert_space,
+ ethiopic_sentence = insert_space,
+ },
+ ethiopic_sentence = {
+ ethiopic_syllable = insert_space,
+ ethiopic_word = insert_space,
+ ethiopic_sentence = insert_space,
+ },
+}
+
+local function process(head,first,last)
+ if first ~= last then
+ local injector = false
+ local current = first
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ local scriptstatus = getattr(current,a_scriptstatus)
+ local category = numbertocategory[scriptstatus]
+ if injector then
+ local action = injector[category]
+ if action then
+ action(head,current)
+ end
+ end
+ injector = injectors[category]
+ else
+ -- nothing yet
+ end
+ if current == last then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "ethiopic",
+ 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/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua
new file mode 100644
index 00000000000..02b2891378e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua
@@ -0,0 +1,978 @@
+if not modules then modules = { } end modules ['scrp-ini'] = {
+ 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"
+}
+
+-- We need to rewrite this a bit ... rather old code ... will be done when japanese
+-- is finished.
+
+local attributes, nodes, node = attributes, nodes, node
+
+local trace_analyzing = false trackers.register("scripts.analyzing", function(v) trace_analyzing = v end)
+local trace_injections = false trackers.register("scripts.injections", function(v) trace_injections = v end)
+local trace_splitting = false trackers.register("scripts.splitting", function(v) trace_splitting = v end)
+local trace_splitdetail = false trackers.register("scripts.splitting.detail", function(v) trace_splitdetail = v end)
+
+local report_preprocessing = logs.reporter("scripts","preprocessing")
+local report_splitting = logs.reporter("scripts","splitting")
+
+local utfbyte, utfsplit = utf.byte, utf.split
+local gmatch = string.gmatch
+
+local texsetattribute = tex.setattribute
+
+local nodecodes = nodes.nodecodes
+local unsetvalue = attributes.unsetvalue
+
+local implement = interfaces.implement
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+
+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 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 nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+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 nodepool = nuts.pool
+
+local new_glue = nodepool.glue
+local new_rule = nodepool.rule
+local new_penalty = nodepool.penalty
+
+scripts = scripts or { }
+local scripts = scripts
+
+scripts.hash = scripts.hash or { }
+local hash = scripts.hash
+
+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
+ --
+ -- half width opening parenthesis
+ --
+ [0x0028] = "half_width_open",
+ [0x005B] = "half_width_open",
+ [0x007B] = "half_width_open",
+ [0x2018] = "half_width_open", -- ‘
+ [0x201C] = "half_width_open", -- “
+ --
+ -- full width opening parenthesis
+ --
+ [0x3008] = "full_width_open", -- 〈 Left book quote
+ [0x300A] = "full_width_open", -- 《 Left double book quote
+ [0x300C] = "full_width_open", -- 「 left quote
+ [0x300E] = "full_width_open", -- 『 left double quote
+ [0x3010] = "full_width_open", -- 【 left double book quote
+ [0x3014] = "full_width_open", -- 〔 left book quote
+ [0x3016] = "full_width_open", --〖 left double book quote
+ [0x3018] = "full_width_open", -- left tortoise bracket
+ [0x301A] = "full_width_open", -- left square bracket
+ [0x301D] = "full_width_open", -- reverse double prime qm
+ [0xFF08] = "full_width_open", -- ( left parenthesis
+ [0xFF3B] = "full_width_open", -- [ left square brackets
+ [0xFF5B] = "full_width_open", -- { left curve bracket
+ --
+ -- half width closing parenthesis
+ --
+ [0x0029] = "half_width_close",
+ [0x005D] = "half_width_close",
+ [0x007D] = "half_width_close",
+ [0x2019] = "half_width_close", -- ’ right quote, right
+ [0x201D] = "half_width_close", -- ” right double quote
+ --
+ -- full width closing parenthesis
+ --
+ [0x3009] = "full_width_close", -- 〉 book quote
+ [0x300B] = "full_width_close", -- 》 double book quote
+ [0x300D] = "full_width_close", -- 」 right quote, right
+ [0x300F] = "full_width_close", -- 』 right double quote
+ [0x3011] = "full_width_close", -- 】 right double book quote
+ [0x3015] = "full_width_close", -- 〕 right book quote
+ [0x3017] = "full_width_close", -- 〗 right double book quote
+ [0x3019] = "full_width_close", -- right tortoise bracket
+ [0x301B] = "full_width_close", -- right square bracket
+ [0x301E] = "full_width_close", -- double prime qm
+ [0x301F] = "full_width_close", -- low double prime qm
+ [0xFF09] = "full_width_close", -- ) right parenthesis
+ [0xFF3D] = "full_width_close", -- ] right square brackets
+ [0xFF5D] = "full_width_close", -- } right curve brackets
+ --
+ [0xFF62] = "half_width_open", -- left corner bracket
+ [0xFF63] = "half_width_close", -- right corner bracket
+ --
+ -- vertical opening vertical
+ --
+ -- 0xFE35, 0xFE37, 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47,
+ --
+ -- vertical closing
+ --
+ -- 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42, 0xFE44, 0xFE48,
+ --
+ -- half width opening punctuation
+ --
+ -- <empty>
+ --
+ -- full width opening punctuation
+ --
+ -- 0x2236, -- ∶
+ -- 0xFF0C, -- ,
+ --
+ -- half width closing punctuation_hw
+ --
+ [0x0021] = "half_width_close", -- !
+ [0x002C] = "half_width_close", -- ,
+ [0x002E] = "half_width_close", -- .
+ [0x003A] = "half_width_close", -- :
+ [0x003B] = "half_width_close", -- ;
+ [0x003F] = "half_width_close", -- ?
+ [0xFF61] = "half_width_close", -- hw full stop
+ --
+ -- full width closing punctuation
+ --
+ [0x3001] = "full_width_close", -- 、
+ [0x3002] = "full_width_close", -- 。
+ [0xFF0C] = "full_width_close", -- ,
+ [0xFF0E] = "full_width_close", --
+ --
+ -- depends on font
+ --
+ [0xFF01] = "full_width_close", -- !
+ [0xFF1F] = "full_width_close", -- ?
+ --
+ [0xFF1A] = "full_width_punct", -- :
+ [0xFF1B] = "full_width_punct", -- ;
+ --
+ -- non starter
+ --
+ [0x3005] = "non_starter", [0x3041] = "non_starter", [0x3043] = "non_starter", [0x3045] = "non_starter", [0x3047] = "non_starter",
+ [0x3049] = "non_starter", [0x3063] = "non_starter", [0x3083] = "non_starter", [0x3085] = "non_starter", [0x3087] = "non_starter",
+ [0x308E] = "non_starter", [0x3095] = "non_starter", [0x3096] = "non_starter", [0x309B] = "non_starter", [0x309C] = "non_starter",
+ [0x309D] = "non_starter", [0x309E] = "non_starter", [0x30A0] = "non_starter", [0x30A1] = "non_starter", [0x30A3] = "non_starter",
+ [0x30A5] = "non_starter", [0x30A7] = "non_starter", [0x30A9] = "non_starter", [0x30C3] = "non_starter", [0x30E3] = "non_starter",
+ [0x30E5] = "non_starter", [0x30E7] = "non_starter", [0x30EE] = "non_starter", [0x30F5] = "non_starter", [0x30F6] = "non_starter",
+ [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31F0] = "non_starter", [0x31F1] = "non_starter",
+ [0x30F2] = "non_starter", [0x30F3] = "non_starter", [0x30F4] = "non_starter", [0x31F5] = "non_starter", [0x31F6] = "non_starter",
+ [0x30F7] = "non_starter", [0x30F8] = "non_starter", [0x30F9] = "non_starter", [0x31FA] = "non_starter", [0x31FB] = "non_starter",
+ [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31FF] = "non_starter",
+ --
+ -- hyphenation
+ --
+ [0x2026] = "hyphen", -- … ellipsis
+ [0x2014] = "hyphen", -- — hyphen
+ --
+ [0x1361] = "ethiopic_word",
+ [0x1362] = "ethiopic_sentence",
+ --
+}
+
+local function provide(t,k)
+ local v
+ if not tonumber(k) then v = false
+ elseif (k >= 0x03040 and k <= 0x030FF)
+ or (k >= 0x031F0 and k <= 0x031FF)
+ or (k >= 0x032D0 and k <= 0x032FE)
+ or (k >= 0x0FF00 and k <= 0x0FFEF) then v = "katakana"
+ elseif (k >= 0x03400 and k <= 0x04DFF)
+ or (k >= 0x04E00 and k <= 0x09FFF)
+ or (k >= 0x0F900 and k <= 0x0FAFF)
+ or (k >= 0x20000 and k <= 0x2A6DF)
+ or (k >= 0x2F800 and k <= 0x2FA1F) then v = "chinese"
+ elseif (k >= 0x0AC00 and k <= 0x0D7A3) then v = "korean"
+ elseif (k >= 0x01100 and k <= 0x0115F) then v = "jamo_initial"
+ elseif (k >= 0x01160 and k <= 0x011A7) then v = "jamo_medial"
+ elseif (k >= 0x011A8 and k <= 0x011FF) then v = "jamo_final"
+ elseif (k >= 0x01200 and k <= 0x0139F) then v = "ethiopic_syllable"
+ else v = false
+ end
+ t[k] = v
+ return v
+end
+
+setmetatableindex(hash,provide) -- should come from char-def
+
+scripts.hash = hash
+
+local numbertodataset = allocate()
+local numbertohandler = allocate()
+
+--~ storage.register("scripts/hash", hash, "scripts.hash")
+
+scripts.numbertodataset = numbertodataset
+scripts.numbertohandler = numbertohandler
+
+local defaults = {
+ inter_char_shrink_factor = 0,
+ inter_char_shrink_factor = 0,
+ inter_char_stretch_factor = 0,
+ inter_char_half_shrink_factor = 0,
+ inter_char_half_stretch_factor = 0,
+ inter_char_quarter_shrink_factor = 0,
+ inter_char_quarter_stretch_factor = 0,
+ inter_char_hangul_penalty = 0,
+
+ inter_word_stretch_factor = 0,
+}
+
+scripts.defaults = defaults -- so we can add more
+
+function scripts.installmethod(handler)
+ local name = handler.name
+ handlers[name] = handler
+ local attributes = { }
+ local datasets = handler.datasets
+ if not datasets or not datasets.default then
+ 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
+ setmetatable(attributes, {
+ __index = function(t,k)
+ local v = datasets[k] or datasets.default
+ local a = unsetvalue
+ if v then
+ v.name = name -- for tracing
+ a = #numbertodataset + 1
+ numbertodataset[a] = v
+ numbertohandler[a] = handler
+ end
+ t[k] = a
+ return a
+ end
+ } )
+ handler.attributes = attributes
+end
+
+function scripts.installdataset(specification) -- global overload
+ local method = specification.method
+ local name = specification.name
+ local dataset = specification.dataset
+ if method and name and dataset then
+ local parent = specification.parent or ""
+ local handler = handlers[method]
+ if handler then
+ local datasets = handler.datasets
+ if datasets then
+ local defaultset = datasets.default
+ if defaultset then
+ if parent ~= "" then
+ local p = datasets[parent]
+ if p then
+ defaultset = p
+ else
+ report_preprocessing("dataset, unknown parent %a for method %a",parent,method)
+ end
+ end
+ setmetatable(dataset,defaultset)
+ local existing = datasets[name]
+ if existing then
+ for k, v in next, existing do
+ existing[k] = dataset
+ end
+ else
+ datasets[name] = dataset
+ end
+ else
+ report_preprocessing("dataset, no default for method %a",method)
+ end
+ else
+ report_preprocessing("dataset, no datasets for method %a",method)
+ end
+ else
+ report_preprocessing("dataset, no method %a",method)
+ end
+ else
+ report_preprocessing("dataset, invalid specification") -- maybe report table
+ end
+end
+
+local injectorenabled = false
+local splitterenabled = false
+
+function scripts.set(name,method,preset)
+ local handler = handlers[method]
+ if handler then
+ if handler.injector then
+ if not injectorenabled then
+ enableaction("processors","scripts.injectors.handler")
+ injectorenabled = true
+ end
+ texsetattribute(a_scriptinjection,handler.attributes[preset] or unsetvalue)
+ end
+ if handler.splitter then
+ if not splitterenabled then
+ enableaction("processors","scripts.splitters.handler")
+ splitterenabled = true
+ end
+ texsetattribute(a_scriptsplitting,handler.attributes[preset] or unsetvalue)
+ end
+ if handler.initializer then
+ handler.initializer(handler)
+ handler.initializer = nil
+ end
+ else
+ texsetattribute(a_scriptinjection,unsetvalue)
+ texsetattribute(a_scriptsplitting,unsetvalue)
+ end
+end
+
+function scripts.reset()
+ texsetattribute(a_scriptinjection,unsetvalue)
+ texsetattribute(a_scriptsplitting,unsetvalue)
+end
+
+-- the following tables will become a proper installer (move to cjk/eth)
+--
+-- 0=gray 1=red 2=green 3=blue 4=yellow 5=magenta 6=cyan 7=x-yellow 8=x-magenta 9=x-cyan
+
+local scriptcolors = allocate { -- todo: just named colors
+ korean = "trace:0",
+ chinese = "trace:0",
+ katakana = "trace:0",
+ hiragana = "trace:0",
+ full_width_open = "trace:1",
+ full_width_close = "trace:2",
+ half_width_open = "trace:3",
+ half_width_close = "trace:4",
+ full_width_punct = "trace:5",
+ hyphen = "trace:5",
+ non_starter = "trace:6",
+ jamo_initial = "trace:7",
+ jamo_medial = "trace:8",
+ jamo_final = "trace:9",
+ ethiopic_syllable = "trace:1",
+ ethiopic_word = "trace:2",
+ ethiopic_sentence = "trace:3",
+}
+
+scripts.colors = scriptcolors
+
+local numbertocategory = allocate { -- rather bound to cjk ... will be generalized
+ "korean",
+ "chinese",
+ "katakana",
+ "hiragana",
+ "full_width_open",
+ "full_width_close",
+ "half_width_open",
+ "half_width_close",
+ "full_width_punct",
+ "hyphen",
+ "non_starter",
+ "jamo_initial",
+ "jamo_medial",
+ "jamo_final",
+ "ethiopic_syllable",
+ "ethiopic_word",
+ "ethiopic_sentence",
+}
+
+local categorytonumber = allocate(table.swapped(numbertocategory)) -- could be one table
+
+scripts.categorytonumber = categorytonumber
+scripts.numbertocategory = numbertocategory
+
+local function colorize(start,stop)
+ for n in traverse_id(glyph_code,start) do
+ local kind = numbertocategory[getattr(n,a_scriptstatus)]
+ if kind then
+ local ac = scriptcolors[kind]
+ if ac then
+ setnodecolor(n,ac)
+ end
+ end
+ if n == stop then
+ break
+ end
+ end
+end
+
+local function traced_process(head,first,last,process,a)
+ if start ~= last then
+ local f, l = first, last
+ local name = numbertodataset[a]
+ name = name and name.name or "?"
+ report_preprocessing("before %s: %s",name,nodes.tosequence(f,l))
+ process(head,first,last)
+ report_preprocessing("after %s: %s", name,nodes.tosequence(f,l))
+ end
+end
+
+-- eventually we might end up with more extensive parsing
+-- todo: pass t[start..stop] == original
+--
+-- one of the time consuming functions:
+
+-- 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
+ else
+ local last_a, normal_process, lastfont, originals = nil, nil, nil, nil
+ local done, first, last, ok = false, nil, nil, false
+ while start do
+ local char, id = isglyph(start)
+ if char then
+ local a = getattr(start,a_scriptinjection)
+ if a then
+ if a ~= last_a then
+ if first then
+ if ok then
+ if trace_analyzing then
+ colorize(first,last)
+ end
+ if trace_injections then
+ traced_process(head,first,last,normal_process,last_a)
+ else
+ normal_process(head,first,last)
+ end
+ ok, done = false, true
+ end
+ first, last = nil, nil
+ end
+ last_a = a
+ local handler = numbertohandler[a]
+ 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
+ if resources then
+ originals = resources.originals
+ else
+ originals = nil -- can't happen
+ end
+ lastfont = font
+ end
+ if originals and type(originals) == "number" then
+ char = originals[char] or char
+ end
+ local h = hash[char]
+ if h then
+ setattr(start,a_scriptstatus,categorytonumber[h])
+ if not first then
+ first, last = start, start
+ else
+ last = start
+ end
+ -- if cjk == "chinese" or cjk == "korean" then -- we need to prevent too much ( ) processing
+ ok = true
+ -- end
+ elseif first then
+ if ok then
+ if trace_analyzing then
+ colorize(first,last)
+ end
+ if trace_injections then
+ traced_process(head,first,last,normal_process,last_a)
+ else
+ normal_process(head,first,last)
+ end
+ ok, done = false, true
+ end
+ first, last = nil, nil
+ end
+ end
+ elseif first then
+ if ok then
+ if trace_analyzing then
+ colorize(first,last)
+ end
+ if trace_injections then
+ traced_process(head,first,last,normal_process,last_a)
+ else
+ normal_process(head,first,last)
+ end
+ ok, done = false, true
+ end
+ first, last = nil, nil
+ end
+ elseif id == glue_code then
+ if ok then
+ -- continue
+ elseif first then
+ -- no chinese or korean
+ first, last = nil, nil
+ end
+ elseif first then
+ if ok then
+ -- some chinese or korean
+ if trace_analyzing then
+ colorize(first,last)
+ end
+ if trace_injections then
+ traced_process(head,first,last,normal_process,last_a)
+ else
+ normal_process(head,first,last)
+ end
+ first, last, ok, done = nil, nil, false, true
+ elseif first then
+ first, last = nil, nil
+ end
+ end
+ start = getnext(start)
+ end
+ if ok then
+ if trace_analyzing then
+ colorize(first,last)
+ end
+ if trace_injections then
+ traced_process(head,first,last,normal_process,last_a)
+ else
+ normal_process(head,first,last)
+ end
+ done = true
+ end
+ return tonode(head), done
+ end
+end
+
+-- kind of experimental .. might move to it's own module
+
+-- function scripts.splitters.handler(head)
+-- return head, false
+-- end
+
+local function addwords(tree,data)
+ if not tree then
+ tree = { }
+ end
+ for word in gmatch(data,"%S+") do
+ local root = tree
+ local list = utfsplit(word,true)
+ for i=1,#list do
+ local l = utfbyte(list[i])
+ local r = root[l]
+ if not r then
+ r = { }
+ root[l] = r
+ end
+ if i == #list then
+ r.final = word -- true -- could be something else, like word in case of tracing
+ else
+ root = r
+ end
+ end
+ end
+ return tree
+end
+
+local loaded = { }
+
+function splitters.load(handler,files)
+ local files = handler.files
+ local tree = handler.tree or { }
+ handler.tree = tree
+ if not files then
+ return
+ elseif type(files) == "string" then
+ files = { files }
+ handler.files = files
+ end
+ if trace_splitting then
+ report_splitting("loading splitter data for language/script %a",handler.name)
+ end
+ loaded[handler.name or "unknown"] = (loaded[handler.name or "unknown"] or 0) + 1
+ statistics.starttiming(loaded)
+ for i=1,#files do
+ local filename = files[i]
+ local fullname = resolvers.findfile(filename)
+ if fullname == "" then
+ fullname = resolvers.findfile(filename .. ".gz")
+ end
+ if fullname ~= "" then
+ if trace_splitting then
+ report_splitting("loading file %a",fullname)
+ end
+ local suffix, gzipped = gzip.suffix(fullname)
+ if suffix == "lua" then
+ local specification = table.load(fullname,gzipped and gzip.load)
+ if specification then
+ local lists = specification.lists
+ if lists then
+ for i=1,#lists do
+ local entry = lists[i]
+ local data = entry.data
+ if data then
+ if entry.compression == "zlib" then
+ data = zlib.decompress(data)
+ if entry.length and entry.length ~= #data then
+ report_splitting("compression error in file %a",fullname)
+ end
+ end
+ if data then
+ addwords(tree,data)
+ end
+ end
+ end
+ end
+ end
+ else
+ local data = gzipped and io.loadgzip(fullname) or io.loaddata(fullname)
+ if data then
+ addwords(tree,data)
+ end
+ end
+ else
+ report_splitting("unknown file %a",filename)
+ end
+ end
+ statistics.stoptiming(loaded)
+ return tree
+end
+
+statistics.register("loaded split lists", function()
+ if next(loaded) then
+ return string.format("%s, load time: %s",table.sequenced(loaded),statistics.elapsedtime(loaded))
+ end
+end)
+
+-- function splitters.addlist(name,filename)
+-- local handler = scripts.handlers[name]
+-- if handler and filename then
+-- local files = handler.files
+-- if not files then
+-- files = { }
+-- elseif type(files) == "string" then
+-- files = { files }
+-- end
+-- handler.files = files
+-- if type(filename) == "string" then
+-- filename = utilities.parsers.settings_to_array(filename)
+-- end
+-- if type(filename) == "table" then
+-- for i=1,#filename do
+-- files[#files+1] = filenames[i]
+-- end
+-- end
+-- end
+-- end
+--
+-- commands.setscriptsplitterlist = splitters.addlist
+
+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
+ local lastfinal = false
+ while current do
+ local char = isglyph(current)
+ if char then
+ 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
+ else
+ break
+ end
+ end
+ if lastrun then
+ return lastrun, lastfinal
+ end
+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)
+ if a then
+ if a ~= attr then
+ local handler = numbertohandler[a]
+ tree = handler.tree or { }
+ attr = a
+ proc = handler.splitter
+ end
+ if proc then
+ local root = tree[getchar(current)]
+ if root then
+ -- we don't check for attributes in the hitter (yet)
+ local last, final = hit(root,current)
+ if last then
+ local next = getnext(last)
+ if next then
+ local nextchar = isglyph(next)
+ if not nextchar then
+ -- we're done
+ elseif tree[nextchar] then
+ if trace_splitdetail then
+ if type(final) == "string" then
+ report_splitting("advance %s processing between <%s> and <%c>","with",final,nextchar)
+ else
+ report_splitting("advance %s processing between <%c> and <%c>","with",char,nextchar)
+ end
+ end
+ head, current = proc(handler,head,current,last,1)
+ done = true
+ else
+ if trace_splitdetail then
+ -- could be punctuation
+ if type(final) == "string" then
+ report_splitting("advance %s processing between <%s> and <%c>","without",final,nextchar)
+ else
+ report_splitting("advance %s processing between <%c> and <%c>","without",char,nextchar)
+ end
+ end
+ head, current = proc(handler,head,current,last,2)
+ done = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ return tonode(head), done
+end
+
+local function marker(head,current,font,color) -- could become: nodes.tracers.marker
+ local ex = exheights[font]
+ local em = emwidths [font]
+ head, current = insert_node_after(head,current,new_penalty(10000))
+ head, current = insert_node_after(head,current,new_glue(-0.05*em))
+ head, current = insert_node_after(head,current,new_rule(0.05*em,1.5*ex,0.5*ex))
+ setnodecolor(current,color)
+ return head, current
+end
+
+local last_a, last_f, last_s, last_q
+
+function splitters.insertafter(handler,head,first,last,detail)
+ local a = getattr(first,a_scriptsplitting)
+ local f = getfont(first)
+ if a ~= last_a or f ~= last_f then
+ last_s = emwidths[f] * numbertodataset[a].inter_word_stretch_factor
+ last_a = a
+ last_f = f
+ end
+ if trace_splitting then
+ head, last = marker(head,last,f,detail == 2 and "trace:r" or "trace:g")
+ end
+ if ignore then
+ return head, last
+ else
+ return insert_node_after(head,last,new_glue(0,last_s))
+ end
+end
+
+-- word-xx.lua:
+--
+-- return {
+-- comment = "test",
+-- copyright = "not relevant",
+-- language = "en",
+-- timestamp = "2013-05-20 14:15:21",
+-- version = "1.00",
+-- lists = {
+-- {
+-- -- data = "we thrive information in thick worlds because of our marvelous and everyday capacity to select edit single out structure highlight group pair merge harmonize synthesize focus organize condense reduce boil down choose categorize catalog classify list abstract scan look into idealize isolate discriminate distinguish screen pigeonhole pick over sort integrate blend inspect filter lump skip smooth chunk average approximate cluster aggregate outline summarize itemize review dip into flip through browse glance into leaf through skim refine enumerate glean synopsize winnow the wheat from the chaff and separate the sheep from the goats",
+-- data = "abstract aggregate and approximate average because blend boil browse capacity catalog categorize chaff choose chunk classify cluster condense dip discriminate distinguish down edit enumerate everyday filter flip focus from glance glean goats group harmonize highlight idealize in information inspect integrate into isolate itemize leaf list look lump marvelous merge of organize our out outline over pair pick pigeonhole reduce refine review scan screen select separate sheep single skim skip smooth sort structure summarize synopsize synthesize the thick thrive through to we wheat winnow worlds",
+-- },
+-- },
+-- }
+
+scripts.installmethod {
+ name = "test",
+ splitter = splitters.insertafter,
+ initializer = splitters.load,
+ files = {
+ -- "scrp-imp-word-test.lua",
+ "word-xx.lua",
+ },
+ datasets = {
+ default = {
+ inter_word_stretch_factor = 0.25, -- of quad
+ },
+ },
+}
+
+-- new plugin:
+
+local registercontext = fonts.specifiers.registercontext
+local mergecontext = fonts.specifiers.mergecontext
+
+local otfscripts = characters.otfscripts
+
+local report_scripts = logs.reporter("scripts","auto feature")
+local trace_scripts = false trackers.register("scripts.autofeature",function(v) trace_scripts = v end)
+
+local autofontfeature = scripts.autofontfeature or { }
+scripts.autofontfeature = autofontfeature
+
+local cache_yes = { }
+local cache_nop = { }
+
+setmetatableindex(cache_yes,function(t,k) local v = { } t[k] = v return v end)
+setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end)
+
+-- beware: we need to tag a done (otherwise too many extra instances ... but how
+-- often unpack? wait till we have a bitmap
+--
+-- we can consider merging this in handlers.characters(head) at some point as there
+-- already check for the dynamic attribute so it saves a pass, however, then we also
+-- need to check for a_scriptinjection there which nils the benefit
+--
+-- we can consider cheating: set all glyphs in a word as the first one but it's not
+-- playing nice
+
+function autofontfeature.handler(head)
+ for n in traverse_char(tonut(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]
+ if not attr then
+ attr = mergecontext(dynamic,name,2)
+ slot[script] = attr
+ if trace_scripts then
+ report_scripts("script: %s, trigger %C, dynamic: %a, variant: %a",script,char,attr,"extended")
+ end
+ end
+ if attr ~= 0 then
+ n[0] = attr
+ -- maybe set scriptinjection when associated
+ end
+ else
+ local slot = cache_nop[font]
+ local attr = slot[script]
+ if not attr then
+ attr = registercontext(font,script,2)
+ slot[script] = attr
+ if trace_scripts then
+ report_scripts("script: %s, trigger %C, dynamic: %s, variant: %a",script,char,attr,"normal")
+ end
+ end
+ if attr ~= 0 then
+ setattr(n,0,attr)
+ -- maybe set scriptinjection when associated
+ end
+ end
+ end
+ -- end
+ end
+ return head
+end
+
+function autofontfeature.enable()
+ report_scripts("globally enabled")
+ enableaction("processors","scripts.autofontfeature.handler")
+end
+
+function autofontfeature.disable()
+ report_scripts("globally disabled")
+ disableaction("processors","scripts.autofontfeature.handler")
+end
+
+implement {
+ name = "enableautofontscript",
+ actions = autofontfeature.enable
+}
+
+implement {
+ name = "disableautofontscript",
+ actions = autofontfeature.disable }
+
+implement {
+ name = "setscript",
+ actions = scripts.set,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "resetscript",
+ actions = scripts.reset
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv
new file mode 100644
index 00000000000..cd060c02bbd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv
@@ -0,0 +1,95 @@
+%D \module
+%D [ file=scrp-ini,
+%D version=2009.02.06,
+%D title=\CONTEXT\ Script 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.
+
+% here we collect code from other places (was organized differently)
+
+\registerctxluafile{scrp-ini}{1.001}
+\registerctxluafile{scrp-cjk}{1.001}
+\registerctxluafile{scrp-eth}{1.001}
+\registerctxluafile{scrp-tha}{1.001}
+
+\definesystemattribute[scriptinjection][public]
+\definesystemattribute[scriptsplitting][public]
+\definesystemattribute[scriptstatus] [public]
+
+%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
+%D proper define macro too.
+
+\unprotect
+
+\installcorenamespace{script}
+
+\installcommandhandler \??script {script} \??script
+
+\let\setupscripts\setupscript % be nice
+
+% presets are global and are currently defined in lua
+
+\appendtoks
+ \setuevalue\currentscript{\setscript[\currentscript]}%
+\to \everydefinescript
+
+\unexpanded\def\scripts_basics_set
+ {\clf_setscript{\currentscript}{\scriptparameter\c!method}{\scriptparameter\c!preset}}
+
+\unexpanded\def\setscript[#1]%
+ {\edef\currentscript{#1}%
+ \scripts_basics_set}
+
+\unexpanded\def\resetscript
+ {\clf_resetscript}
+
+\unexpanded\def\startscript[#1]%
+ {\begingroup
+ \edef\currentscript{#1}%
+ \scripts_basics_set}
+
+\unexpanded\def\stopscript
+ {\endgroup}
+
+% % todo:
+%
+% \unexpanded\def\setscriptsplitterlist
+% {\dodoubleargument\scripts_basics_set_splitter_list}
+%
+% \def\scripts_basics_set_splitter_list[#1][#2]%
+% {\ctxcommand{setscriptsplitterlist("#1","#2")}
+
+% \setscript[hangul] \hangul \startscript[hangul]
+
+\definescript [hangul] [\c!method=hangul]
+\definescript [hanzi] [\c!method=hanzi]
+\definescript [nihongo] [\c!method=nihongo]
+\definescript [ethiopic] [\c!method=ethiopic]
+\definescript [thai] [\c!method=thai]
+
+\definescript [latin] [\c!method=] % resets the attribute (also currentscript)
+
+\definescript [test] [\c!method=test]
+
+% a new trick (at some point we will predefine more scripts and consider a link with the above)
+
+\appendtoks
+ \ifx\currentscript\empty
+ \doifelse{\scriptparameter\s!features}\v!auto\enableautofontscript\disableautofontscript
+ \fi
+\to \everysetupscript
+
+\unexpanded\def\enableautofontscript {\clf_enableautofontscript }
+\unexpanded\def\disableautofontscript{\clf_disableautofontscript}
+
+\definefontfeature[latn][script=latn]
+\definefontfeature[grek][script=grek]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-tha.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-tha.lua
new file mode 100644
index 00000000000..ec5df07c075
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-tha.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['scrp-tha'] = {
+ 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"
+}
+
+-- This module needs dictionary files that looks as follows. At some point
+-- we will add these files to the distribution.
+--
+-- word-th.lua:
+--
+-- return {
+-- comment = "The data is taken from http://thailinux.gits.net.th/websvn/wsvn/software.swath by Phaisarn Charoenpornsawat and Theppitak Karoonboonyanan.",
+-- copyright = "gnu general public license",
+-- language = "th",
+-- compiling = "mtxrun --script patterns --words --update --compress word-th.lua",
+-- timestamp = "0000-00-00 00:00:00",
+-- version = "1.00",
+-- lists = {
+-- { filename = "tdict-city.txt" },
+-- { filename = "tdict-collection.txt" },
+-- { filename = "tdict-common.txt" },
+-- { filename = "tdict-country.txt" },
+-- { filename = "tdict-district.txt" },
+-- { filename = "tdict-geo.txt" },
+-- { filename = "tdict-history.txt" },
+-- { filename = "tdict-ict.txt" },
+-- { filename = "tdict-lang-ethnic.txt" },
+-- { filename = "tdict-proper.txt" },
+-- { filename = "tdict-science.txt" },
+-- { filename = "tdict-spell.txt" },
+-- { filename = "tdict-std-compound.txt" },
+-- { filename = "tdict-std.txt" },
+-- },
+-- }
+
+-- Currently there is nothing additional special here, first we need a
+-- ConTeXt user who uses it. It's a starting point.
+
+local splitters = scripts.splitters
+
+scripts.installmethod {
+ name = "thai",
+ splitter = splitters.insertafter,
+ initializer = splitters.load,
+ files = {
+ -- "scrp-imp-word-thai.lua",
+ "word-th.lua",
+ },
+ datasets = {
+ default = {
+ inter_word_stretch_factor = 0.25, -- of quad
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua
new file mode 100644
index 00000000000..3266425cbf4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua
@@ -0,0 +1,796 @@
+if not modules then modules = { } end modules ['sort-ini'] = {
+ version = 1.001,
+ comment = "companion to sort-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- It took a while to get there, but with Fleetwood Mac's "Don't Stop"
+-- playing in the background we sort of got it done.
+
+--[[<p>The code here evolved from the rather old mkii approach. There
+we concatinate the key and (raw) entry into a new string. Numbers and
+special characters get some treatment so that they sort ok. In
+addition some normalization (lowercasing, accent stripping) takes
+place and again data is appended ror prepended. Eventually these
+strings are sorted using a regular string sorter. The relative order
+of character is dealt with by weighting them. It took a while to
+figure this all out but eventually it worked ok for most languages,
+given that the right datatables were provided.</p>
+
+<p>Here we do follow a similar approach but this time we don't append
+the manipulated keys and entries but create tables for each of them
+with entries being tables themselves having different properties. In
+these tables characters are represented by numbers and sorting takes
+place using these numbers. Strings are simplified using lowercasing
+as well as shape codes. Numbers are filtered and after getting an offset
+they end up at the right end of the spectrum (more clever parser will
+be added some day). There are definitely more solutions to the problem
+and it is a nice puzzle to solve.</p>
+
+<p>In the future more methods can be added, as there is practically no
+limit to what goes into the tables. For that we will provide hooks.</p>
+
+<p>Todo: decomposition with specific order of accents, this is
+relatively easy to do.</p>
+
+<p>Todo: investigate what standards and conventions there are and see
+how they map onto this mechanism. I've learned that users can come up
+with any demand so nothing here is frozen.</p>
+
+<p>Todo: I ran into the Unicode Collation document and noticed that
+there are some similarities (like the weights) but using that method
+would still demand extra code for language specifics. One option is
+to use the allkeys.txt file for the uc vectors but then we would also
+use the collapsed key (sq, code is now commented). In fact, we could
+just hook those into the replacer code that we reun beforehand.</p>
+
+<p>In the future index entries will become more clever, i.e. they will
+have language etc properties that then can be used.</p>
+]]--
+
+local gsub, rep, sub, sort, concat, tohash, format = string.gsub, string.rep, string.sub, table.sort, table.concat, table.tohash, string.format
+local utfbyte, utfchar, utfcharacters, utfvalues = utf.byte, utf.char, utf.characters, utf.values
+local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset
+local P, Cs, R, S, lpegmatch = lpeg.P, lpeg.Cs, lpeg.R, lpeg.S, lpeg.match
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local trace_tests = false trackers.register("sorters.tests", function(v) trace_tests = v end)
+local trace_methods = false trackers.register("sorters.methods", function(v) trace_methods = v end)
+local trace_orders = false trackers.register("sorters.orders", function(v) trace_orders = v end)
+
+local report_sorters = logs.reporter("languages","sorters")
+
+local comparers = { }
+local splitters = { }
+local definitions = allocate()
+local tracers = allocate()
+local ignoredoffset = 0x10000 -- frozen
+local replacementoffset = 0x10000 -- frozen
+local digitsoffset = 0x20000 -- frozen
+local digitsmaximum = 0xFFFFF -- frozen
+
+local lccodes = characters.lccodes
+local uccodes = characters.uccodes
+local lcchars = characters.lcchars
+local ucchars = characters.ucchars
+local shchars = characters.shchars
+local fscodes = characters.fscodes
+local fschars = characters.fschars
+
+local decomposed = characters.decomposed
+
+local variables = interfaces.variables
+
+local v_numbers = variables.numbers
+local v_default = variables.default
+local v_before = variables.before
+local v_after = variables.after
+local v_first = variables.first
+local v_last = variables.last
+
+local validmethods = tohash {
+ "ch", -- raw character (for tracing)
+ "mm", -- minus mapping
+ "zm", -- zero mapping
+ "pm", -- plus mapping
+ "mc", -- lower case - 1
+ "zc", -- lower case
+ "pc", -- lower case + 1
+ "uc", -- unicode
+}
+
+local predefinedmethods = {
+ [v_default] = "zc,pc,zm,pm,uc",
+ [v_before] = "mm,mc,uc",
+ [v_after] = "pm,mc,uc",
+ [v_first] = "pc,mm,uc",
+ [v_last] = "mc,mm,uc",
+}
+
+sorters = {
+ comparers = comparers,
+ splitters = splitters,
+ definitions = definitions,
+ tracers = tracers,
+ constants = {
+ ignoredoffset = ignoredoffset,
+ replacementoffset = replacementoffset,
+ digitsoffset = digitsoffset,
+ digitsmaximum = digitsmaximum,
+ defaultlanguage = v_default,
+ defaultmethod = v_default,
+ defaultdigits = v_numbers,
+ validmethods = validmethods,
+ }
+}
+
+local sorters = sorters
+local constants = sorters.constants
+
+local data, language, method, digits
+local replacements, m_mappings, z_mappings, p_mappings, entries, orders, lower, upper, method, sequence, usedinsequence
+local thefirstofsplit
+
+local mte = { -- todo: assign to t
+ __index = function(t,k)
+ if k and k ~= "" and utfbyte(k) < digitsoffset then -- k check really needed (see s-lan-02)
+ local el
+ if k then
+ local l = lower[k] or lcchars[k]
+ el = rawget(t,l)
+ end
+ if not el then
+ local l = shchars[k]
+ if l and l ~= k then
+ if #l > 1 then
+ l = sub(l,1,1) -- todo
+ end
+ el = rawget(t,l)
+ if not el then
+ l = lower[k] or lcchars[l]
+ if l then
+ el = rawget(t,l)
+ end
+ end
+ end
+ el = el or k
+ end
+ -- rawset(t,k,el)
+ return el
+ else
+ -- rawset(t,k,k)
+ end
+ end
+}
+
+local noorder = false
+local nothing = { 0 }
+
+local function preparetables(data)
+ local orders, lower, m_mappings, z_mappings, p_mappings = data.orders, data.lower, { }, { }, { }
+ for i=1,#orders do
+ local oi = orders[i]
+ local n = { 2 * i }
+ m_mappings[oi], z_mappings[oi], p_mappings[oi] = n, n, n
+ end
+ local mtm = {
+ __index = function(t,k)
+ local n, nn
+ if k then
+ if trace_orders then
+ report_sorters("simplifing character %C",k)
+ end
+ local l = lower[k] or lcchars[k]
+ if l then
+ if trace_orders then
+ report_sorters(" 1 lower: %C",l)
+ end
+ local ml = rawget(t,l)
+ if ml then
+ n = { }
+ nn = 0
+ for i=1,#ml do
+ nn = nn + 1
+ n[nn] = ml[i] + (t.__delta or 0)
+ end
+ if trace_orders then
+ report_sorters(" 2 order: % t",n)
+ end
+ end
+ end
+ if not n then
+ local s = shchars[k] -- maybe all components?
+ if s and s ~= k then
+ if trace_orders then
+ report_sorters(" 3 shape: %C",s)
+ end
+ n = { }
+ nn = 0
+ for l in utfcharacters(s) do
+ local ml = rawget(t,l)
+ if ml then
+ if trace_orders then
+ report_sorters(" 4 keep: %C",l)
+ end
+ if ml then
+ for i=1,#ml do
+ nn = nn + 1
+ n[nn] = ml[i]
+ end
+ end
+ else
+ l = lower[l] or lcchars[l]
+ if l then
+ if trace_orders then
+ report_sorters(" 5 lower: %C",l)
+ end
+ local ml = rawget(t,l)
+ if ml then
+ for i=1,#ml do
+ nn = nn + 1
+ n[nn] = ml[i] + (t.__delta or 0)
+ end
+ end
+ end
+ end
+ end
+ else
+ -- this is a kind of last resort branch that we might want to revise
+ -- one day
+ --
+ -- local b = utfbyte(k)
+ -- n = decomposed[b] or { b }
+ -- if trace_tests then
+ -- report_sorters(" 6 split: %s",utf.tostring(b)) -- todo
+ -- end
+ --
+ -- we need to move way above valid order (new per 2014-10-16) .. maybe we
+ -- need to move it even more up to get numbers right (not all have orders)
+ --
+ if k == "\000" then
+ n = nothing -- shared
+ if trace_orders then
+ report_sorters(" 6 split: space") -- todo
+ end
+ else
+ local b = 2 * #orders + utfbyte(k)
+ n = decomposed[b] or { b } -- could be shared tables
+ if trace_orders then
+ report_sorters(" 6 split: %s",utf.tostring(b)) -- todo
+ end
+ end
+ end
+ if n then
+ if trace_orders then
+ report_sorters(" 7 order: % t",n)
+ end
+ else
+ n = noorder
+ if trace_orders then
+ report_sorters(" 8 order: 0")
+ end
+ end
+ end
+ else
+ n = noorder
+ if trace_orders then
+ report_sorters(" 9 order: 0")
+ end
+ end
+ rawset(t,k,n)
+ return n
+ end
+ }
+ data.m_mappings = m_mappings
+ data.z_mappings = z_mappings
+ data.p_mappings = p_mappings
+ m_mappings.__delta = -1
+ z_mappings.__delta = 0
+ p_mappings.__delta = 1
+ setmetatable(data.entries,mte)
+ setmetatable(data.m_mappings,mtm)
+ setmetatable(data.z_mappings,mtm)
+ setmetatable(data.p_mappings,mtm)
+ thefirstofsplit = data.firstofsplit
+end
+
+local function update() -- prepare parent chains, needed when new languages are added
+ for language, data in next, definitions do
+ local parent = data.parent or "default"
+ if language ~= "default" then
+ setmetatableindex(data,definitions[parent] or definitions.default)
+ end
+ data.language = language
+ data.parent = parent
+ data.m_mappings = { } -- free temp data
+ data.z_mappings = { } -- free temp data
+ data.p_mappings = { } -- free temp data
+ end
+end
+
+local function setlanguage(l,m,d,u) -- this will become a specification table (also keep this one as it's used in manuals)
+ language = (l ~= "" and l) or constants.defaultlanguage
+ data = definitions[language or constants.defaultlanguage] or definitions[constants.defaultlanguage]
+ method = (m ~= "" and m) or (data.method ~= "" and data.method) or constants.defaultmethod
+ digits = (d ~= "" and d) or (data.digits ~= "" and data.digits) or constants.defaultdigits
+ if trace_tests then
+ report_sorters("setting language %a, method %a, digits %a",language,method,digits)
+ end
+ replacements = data.replacements
+ entries = data.entries
+ orders = data.orders
+ lower = data.lower
+ upper = data.upper
+ preparetables(data)
+ m_mappings = data.m_mappings
+ z_mappings = data.z_mappings
+ p_mappings = data.p_mappings
+ --
+ method = predefinedmethods[variables[method]] or method
+ data.method = method
+ --
+ data.digits = digits
+ --
+ local seq = utilities.parsers.settings_to_array(method or "") -- check the list
+ sequence = { }
+ local nofsequence = 0
+ for i=1,#seq do
+ local s = seq[i]
+ if validmethods[s] then
+ nofsequence = nofsequence + 1
+ sequence[nofsequence] = s
+ else
+ report_sorters("invalid sorter method %a in %a",s,method)
+ end
+ end
+ usedinsequence = tohash(sequence)
+ data.sequence = sequence
+ data.usedinsequence = usedinsequence
+-- usedinsequence.ch = true -- better just store the string
+ if trace_tests then
+ report_sorters("using sort sequence: % t",sequence)
+ end
+ --
+ return data
+end
+
+function sorters.update()
+ update()
+ setlanguage(language,method,numberorder) -- resync current language and method
+end
+
+function sorters.setlanguage(language,method,numberorder)
+ update()
+ setlanguage(language,method,numberorder) -- new language and method
+end
+
+-- tricky: { 0, 0, 0 } vs { 0, 0, 0, 0 } => longer wins and mm, pm, zm can have them
+
+-- inlining and checking first slot first doesn't speed up (the 400K complex author sort)
+
+local function basicsort(sort_a,sort_b)
+ if sort_a and sort_b then
+ local na = #sort_a
+ local nb = #sort_b
+ if na > nb then
+ na = nb
+ end
+ if na > 0 then
+ for i=1,na do
+ local ai, bi = sort_a[i], sort_b[i]
+ if ai > bi then
+ return 1
+ elseif ai < bi then
+ return -1
+ end
+ end
+ end
+ end
+ return 0
+end
+
+-- todo: compile compare function
+
+local function basic(a,b) -- trace ea and eb
+ if a == b then
+ -- hashed (shared) entries
+ return 0
+ end
+ local ea, eb = a.split, b.split
+ local na, nb = #ea, #eb
+ if na == 0 and nb == 0 then
+ -- simple variant (single word)
+ local result = 0
+ for j=1,#sequence do
+ local m = sequence[j]
+ result = basicsort(ea[m],eb[m])
+ if result ~= 0 then
+ return result
+ end
+ end
+ if result == 0 then
+ local la, lb = #ea.uc, #eb.uc
+ if la > lb then
+ return 1
+ elseif lb > la then
+ return -1
+ else
+ return 0
+ end
+ else
+ return result
+ end
+ else
+ -- 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]
+ for j=1,#sequence do
+ local m = sequence[j]
+ result = basicsort(eai[m],ebi[m])
+ if result ~= 0 then
+ return result
+ end
+ end
+ if result == 0 then
+ local la, lb = #eai.uc, #ebi.uc
+ if la > lb then
+ return 1
+ elseif lb > la then
+ return -1
+ end
+ else
+ return result
+ end
+ end
+ if result ~= 0 then
+ return result
+ elseif na > nb then
+ return 1
+ elseif nb > na then
+ return -1
+ else
+ return 0
+ end
+ end
+end
+
+-- if we use sq:
+--
+-- local function basic(a,b) -- trace ea and eb
+-- local ea, eb = a.split, b.split
+-- local na, nb = #ea, #eb
+-- if na == 0 and nb == 0 then
+-- -- simple variant (single word)
+-- return basicsort(ea.sq,eb.sq)
+-- else
+-- -- 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]
+-- result = basicsort(ea.sq,eb.sq)
+-- if result ~= 0 then
+-- return result
+-- end
+-- end
+-- if result ~= 0 then
+-- return result
+-- elseif na > nb then
+-- return 1
+-- elseif nb > na then
+-- return -1
+-- else
+-- return 0
+-- end
+-- end
+-- end
+
+comparers.basic = basic
+
+function sorters.basicsorter(a,b)
+ return basic(a,b) == -1
+end
+
+local function numify(old)
+ if digits == v_numbers then -- was swapped, fixed 2014-11-10
+ local new = digitsoffset + tonumber(old) -- alternatively we can create range
+ if new > digitsmaximum then
+ new = digitsmaximum
+ end
+ return utfchar(new)
+ else
+ return old
+ end
+end
+
+local pattern = nil
+
+local function prepare() -- todo: test \Ux{hex}
+ pattern = Cs( (
+ characters.tex.toutfpattern()
+ + lpeg.patterns.whitespace / "\000"
+ + (P("\\Ux{") / "" * ((1-P("}"))^1/function(s) return utfchar(tonumber(s,16)) end) * (P("}")/""))
+ + (P("\\") / "") * R("AZ")^0 * (P(-1) + #(1-R("AZ")))
+ + (P("\\") * P(1) * R("az","AZ")^0) / ""
+ + S("[](){}$\"'") / ""
+ + R("09")^1 / numify
+ + P(1)
+ )^0 )
+ return pattern
+end
+
+function sorters.strip(str) -- todo: only letters and such
+ if str and str ~= "" then
+ return lpegmatch(pattern or prepare(),str)
+ else
+ return ""
+ end
+end
+
+local function firstofsplit(entry)
+ -- numbers are left padded by spaces
+ local split = entry.split
+ if #split > 0 then
+ split = split[1].ch
+ else
+ split = split.ch
+ end
+ local first = split and split[1] or ""
+ if thefirstofsplit then
+ return thefirstofsplit(first,data,entry) -- normally the first one is needed
+ else
+ return first, entries[first] or "\000" -- tag
+ end
+end
+
+sorters.firstofsplit = firstofsplit
+
+-- for the moment we use an inefficient bunch of tables but once
+-- we know what combinations make sense we can optimize this
+
+function splitters.utf(str,checked) -- we could append m and u but this is cleaner, s is for tracing
+ if #replacements > 0 then
+ -- todo make an lpeg for this
+ for k=1,#replacements do
+ local v = replacements[k]
+ str = gsub(str,v[1],v[2])
+ 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
+ for sc in utfcharacters(str) do
+ local b = utfbyte(sc)
+ if b >= digitsoffset then
+ if n == 0 then
+ -- we need to force number to the top
+ z_case[1] = 0
+ m_case[1] = 0
+ p_case[1] = 0
+ char[1] = sc
+ byte[1] = 0
+ m_mapping[1] = 0
+ z_mapping[1] = 0
+ p_mapping[1] = 0
+ n = 2
+ else
+ n = n + 1
+ end
+ z_case[n] = b
+ m_case[n] = b
+ p_case[n] = b
+ char[n] = sc
+ byte[n] = b
+ nm = nm + 1
+ nz = nz + 1
+ np = np + 1
+ m_mapping[nm] = b
+ z_mapping[nz] = b
+ p_mapping[np] = b
+ else
+ n = n + 1
+ local l = lower[sc]
+ l = l and utfbyte(l) or lccodes[b] or b
+ -- local u = upper[sc]
+ -- u = u and utfbyte(u) or uccodes[b] or b
+ if type(l) == "table" then
+ l = l[1] -- there are currently no tables in lccodes but it can be some, day
+ end
+ -- if type(u) == "table" then
+ -- u = u[1] -- there are currently no tables in lccodes but it can be some, day
+ -- end
+ z_case[n] = l
+ if l ~= b then
+ m_case[n] = l - 1
+ p_case[n] = l + 1
+ else
+ m_case[n] = l
+ p_case[n] = l
+ end
+ char[n], byte[n] = sc, b
+ local fs = fscodes[b] or b
+ local msc = m_mappings[sc]
+ if msc ~= noorder then
+ if not msc then
+ msc = m_mappings[fs]
+ end
+ for i=1,#msc do
+ nm = nm + 1
+ m_mapping[nm] = msc[i]
+ end
+ end
+ local zsc = z_mappings[sc]
+ if zsc ~= noorder then
+ if not zsc then
+ zsc = z_mappings[fs]
+ end
+ for i=1,#zsc do
+ nz = nz + 1
+ z_mapping[nz] = zsc[i]
+ end
+ end
+ local psc = p_mappings[sc]
+ if psc ~= noorder then
+ if not psc then
+ psc = p_mappings[fs]
+ end
+ for i=1,#psc do
+ np = np + 1
+ p_mapping[np] = psc[i]
+ end
+ end
+ end
+ end
+ -- -- only those needed that are part of a sequence
+ --
+ -- local b = byte[1]
+ -- if b then
+ -- -- we set them to the first split code (korean)
+ -- local fs = fscodes[b] or b
+ -- if #m_mapping == 0 then
+ -- m_mapping = { m_mappings[fs][1] }
+ -- end
+ -- if #z_mapping == 0 then
+ -- z_mapping = { z_mappings[fs][1] }
+ -- end
+ -- if #p_mapping == 0 then
+ -- p_mapping = { p_mappings[fs][1] }
+ -- end
+ -- end
+ local result
+ if checked then
+ result = {
+ ch = trace_tests and char or nil, -- not in sequence
+ uc = usedinsequence.uc and byte or nil,
+ mc = usedinsequence.mc and m_case or nil,
+ zc = usedinsequence.zc and z_case or nil,
+ pc = usedinsequence.pc and p_case or nil,
+ mm = usedinsequence.mm and m_mapping or nil,
+ zm = usedinsequence.zm and z_mapping or nil,
+ pm = usedinsequence.pm and p_mapping or nil,
+ }
+ else
+ result = {
+ ch = char,
+ uc = byte,
+ mc = m_case,
+ zc = z_case,
+ pc = p_case,
+ mm = m_mapping,
+ zm = z_mapping,
+ pm = p_mapping,
+ }
+ end
+ -- local sq, n = { }, 0
+ -- for i=1,#byte do
+ -- for s=1,#sequence do
+ -- n = n + 1
+ -- sq[n] = result[sequence[s]][i]
+ -- end
+ -- end
+ -- result.sq = sq
+ return result
+end
+
+local function packch(entry)
+ local split = entry.split
+ if split and #split > 0 then -- useless test
+ local t = { }
+ for i=1,#split do
+ local tt = { }
+ local ch = split[i].ch
+ for j=1,#ch do
+ local chr = ch[j]
+ local byt = utfbyte(chr)
+ if byt > ignoredoffset then
+ tt[j] = "[]"
+ elseif byt == 0 then
+ tt[j] = " "
+ else
+ tt[j] = chr
+ end
+ end
+ t[i] = concat(tt)
+ end
+ return concat(t," + ")
+ else
+ local t = { }
+ local ch = (split and split.ch) or entry.ch or entry
+ if ch then
+ for i=1,#ch do
+ local chr = ch[i]
+ local byt = utfbyte(chr)
+ if byt > ignoredoffset then
+ t[i] = "[]"
+ elseif byt == 0 then
+ t[i] = " "
+ else
+ t[i] = chr
+ end
+ end
+ return concat(t)
+ else
+ return ""
+ end
+ end
+end
+
+local function packuc(entry)
+ local split = entry.split
+ if split and #split > 0 then -- useless test
+ local t = { }
+ for i=1,#split do
+ t[i] = concat(split[i].uc, " ") -- sq
+ end
+ return concat(t," + ")
+ else
+ local uc = (split and split.uc) or entry.uc or entry
+ if uc then
+ return concat(uc," ") -- sq
+ else
+ return ""
+ end
+ end
+end
+
+sorters.packch = packch
+sorters.packuc = packuc
+
+function sorters.sort(entries,cmp)
+ if trace_methods then
+ local nofentries = #entries
+ report_sorters("entries: %s, language: %s, method: %s, digits: %s",nofentries,language,method,tostring(digits))
+ for i=1,nofentries do
+ report_sorters("entry %s",table.serialize(entries[i].split,i,true,true,true))
+ end
+ end
+ if trace_tests then
+ sort(entries,function(a,b)
+ local r = cmp(a,b)
+ local e = (not r and "?") or (r<0 and "<") or (r>0 and ">") or "="
+ report_sorters("%s %s %s | %s %s %s",packch(a),e,packch(b),packuc(a),e,packuc(b))
+ return r == -1
+ end)
+ local s
+ for i=1,#entries do
+ local entry = entries[i]
+ local letter, first = firstofsplit(entry)
+ if first == s then
+ first = " "
+ else
+ s = first
+ if first and letter then
+ report_sorters(">> %C (%C)",first,letter)
+ end
+ end
+ report_sorters(" %s | %s",packch(entry),packuc(entry))
+ end
+ else
+ sort(entries,function(a,b)
+ return cmp(a,b) == -1
+ end)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/sort-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.mkiv
new file mode 100644
index 00000000000..b7b49025561
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.mkiv
@@ -0,0 +1,19 @@
+%D \module
+%D [ file=sort-ini,
+%D version=2005.08.08,
+%D title=\CONTEXT\ Sort 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 Sorting Macros / Initialization}
+
+\registerctxluafile{sort-ini}{1.001}
+\registerctxluafile{sort-lan}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua b/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua
new file mode 100644
index 00000000000..e84692afc52
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua
@@ -0,0 +1,926 @@
+if not modules then modules = { } end modules ['sort-lan'] = {
+ version = 1.001,
+ comment = "companion to sort-lan.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+-- todo: look into uts#10 (2012) ... some experiments ... something
+-- to finish in winter.
+-- todo: U+1E9E (german SS)
+
+-- Many vectors were supplied by Wolfgang Schuster and Philipp
+-- Gesang. However this is a quite adapted and reformatted variant
+-- so it needs some checking. Other users provides tables and
+-- corrections as well.
+
+local utfchar, utfbyte = utf.char, utf.byte
+local sorters = sorters
+local definitions = sorters.definitions
+local replacementoffset = sorters.constants.replacementoffset
+local variables = interfaces.variables
+
+definitions["default"] = {
+ method = variables.before,
+ replacements = {
+ -- no replacements
+ },
+ entries = {
+ ["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", ["t"] = "t",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["z"] = "z",
+ },
+ orders = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z",
+ },
+ lower = {
+ -- no replacements
+ },
+ upper = {
+ -- no replacements
+ }
+}
+
+sorters.setlanguage("default")
+
+-- english
+
+definitions["en"] = { parent = "default" }
+
+-- dutch
+
+definitions['nl'] = {
+ parent = 'default',
+ replacements = {
+ { "ij", 'y' }, { "IJ", 'Y' }, -- hm
+ },
+}
+
+-- French
+
+definitions['fr'] = { parent = 'default' }
+
+-- German (by Wolfgang Schuster)
+
+-- DIN 5007-1
+
+definitions['DIN 5007-1'] = { parent = 'default' }
+
+-- DIN 5007-2
+
+definitions['DIN 5007-2'] = {
+ parent = 'default',
+ replacements = {
+ { "ä", 'ae' }, { "Ä", 'Ae' },
+ { "ö", 'oe' }, { "Ö", 'Oe' },
+ { "ü", 'ue' }, { "Ü", 'Ue' },
+ },
+}
+
+-- Duden
+
+definitions['Duden'] = {
+ parent = 'default',
+ replacements = { { "ß", 's' } },
+}
+
+-- definitions['de'] = { parent = 'default' } -- new german
+
+definitions['de'] = {
+ parent = 'default',
+ replacements = {
+ { "ä", 'ae' }, { "Ä", 'Ae' },
+ { "ö", 'oe' }, { "Ö", 'Oe' },
+ { "ü", 'ue' }, { "Ü", 'Ue' },
+ { "ß", 's' },
+ },
+}
+
+definitions['deo'] = { parent = 'de' } -- old german
+
+definitions['de-DE'] = { parent = 'de' } -- german - Germany
+definitions['de-CH'] = { parent = 'de' } -- german - Swiss
+
+-- german - Austria
+
+definitions['de-AT'] = {
+ entries = {
+ ["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", ["t"] = "t", ["u"] = "u", ["ü"] = "ü", ["v"] = "v",
+ ["w"] = "w", ["x"] = "x", ["y"] = "y", ["z"] = "z",
+ },
+ orders = {
+ "a", "ä", "b", "c", "d", "e", "f", "g", "h", "i",
+ "j", "k", "l", "m", "n", "o", "ö", "p", "q", "r",
+ "s", "t", "u", "ü", "v", "w", "x", "y", "z",
+ },
+}
+
+-- finish (by Wolfgang Schuster)
+
+definitions['fi'] = {
+ entries = {
+ ["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", ["t"] = "t",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["z"] = "z", ["å"] = "å", ["ä"] = "ä", ["ö"] = "ö",
+ },
+ orders = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z", "å", "ä", "ö",
+ }
+}
+
+-- slovenian by MM: this will change since we need to add accented vowels
+
+definitions['sl'] = {
+ entries = {
+ ["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", ["š"] = "š", ["t"] = "t",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y", ["z"] = "z",
+ ["ž"] = "ž",
+ },
+ orders = {
+ "a", "b", "c", "č", "ć", "d", "đ", "e", "f", "g", "h", "i",
+ "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "š", "t",
+ "u", "v", "w", "x", "y", "z", "ž",
+ }
+}
+
+-- The following data was provided by Philipp Gesang.
+
+definitions["ru"] = {
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["д"] = "д",
+ ["е"] = "е", ["ё"] = "е", ["ж"] = "ж", ["з"] = "з", ["и"] = "и",
+ ["і"] = "и", ["й"] = "й", ["к"] = "к", ["л"] = "л", ["м"] = "м",
+ ["н"] = "н", ["о"] = "о", ["п"] = "п", ["р"] = "р", ["с"] = "с",
+ ["т"] = "т", ["у"] = "у", ["ф"] = "ф", ["х"] = "х", ["ц"] = "ц",
+ ["ч"] = "ч", ["ш"] = "ш", ["щ"] = "щ", ["ъ"] = "ъ", ["ы"] = "ы",
+ ["ь"] = "ь", ["ѣ"] = "ѣ", ["э"] = "э", ["ю"] = "ю", ["я"] = "я",
+ ["ѳ"] = "ѳ", ["ѵ"] = "ѵ",
+ },
+ orders = {
+ "а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и",
+ "і", "й", "к", "л", "м", "н", "о", "п", "р", "с",
+ "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы",
+ "ь", "ѣ", "э", "ю", "я", "ѳ", "ѵ",
+ }
+}
+
+--- Basic Ukrainian
+
+definitions["uk"] = {
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["ґ"] = "ґ",
+ ["д"] = "д", ["е"] = "е", ["є"] = "є", ["ж"] = "ж", ["з"] = "з",
+ ["и"] = "и", ["і"] = "і", ["ї"] = "ї", ["й"] = "й", ["к"] = "к",
+ ["л"] = "л", ["м"] = "м", ["н"] = "н", ["о"] = "о", ["п"] = "п",
+ ["р"] = "р", ["с"] = "с", ["т"] = "т", ["у"] = "у", ["ф"] = "ф",
+ ["х"] = "х", ["ц"] = "ц", ["ч"] = "ч", ["ш"] = "ш", ["щ"] = "щ",
+ ["ь"] = "ь", ["ю"] = "ю", ["я"] = "я",
+ },
+ orders = {
+ "а", "б", "в", "г", "ґ", "д", "е", "є", "ж", "з", "и", "і",
+ "ї", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у",
+ "ф", "х", "ц", "ч", "ш", "щ", "ь", "ю", "я",
+ }
+}
+
+--- Belarusian
+
+definitions["be"] = {
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["д"] = "д",
+ ["е"] = "е", ["ё"] = "е", ["ж"] = "ж", ["з"] = "з", ["і"] = "і",
+ ["й"] = "й", ["к"] = "к", ["л"] = "л", ["м"] = "м", ["н"] = "н",
+ ["о"] = "о", ["п"] = "п", ["р"] = "р", ["с"] = "с", ["т"] = "т",
+ ["у"] = "у", ["ў"] = "ў", ["ф"] = "ф", ["х"] = "х", ["ц"] = "ц",
+ ["ч"] = "ч", ["ш"] = "ш", ["ы"] = "ы", ["ь"] = "ь", ["э"] = "э",
+ ["ю"] = "ю", ["я"] = "я",
+ },
+ orders = {
+ "а", "б", "в", "г", "д", "е", "ё", "ж", "з", "і",
+ "й", "к", "л", "м", "н", "о", "п", "р", "с", "т",
+ "у", "ў", "ф", "х", "ц", "ч", "ш", "ы", "ь", "э",
+ "ю", "я",
+ }
+}
+
+--- Bulgarian
+
+definitions["bg"] = {
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["д"] = "д",
+ ["е"] = "е", ["ж"] = "ж", ["з"] = "з", ["и"] = "и", ["й"] = "й",
+ ["к"] = "к", ["a"] = "a", ["л"] = "л", ["a"] = "a", ["м"] = "м",
+ ["н"] = "н", ["о"] = "о", ["п"] = "п", ["р"] = "р", ["с"] = "с",
+ ["т"] = "т", ["у"] = "у", ["ф"] = "ф", ["х"] = "х", ["ц"] = "ц",
+ ["ч"] = "ч", ["ш"] = "ш", ["щ"] = "щ", ["ъ"] = "ъ", ["ь"] = "ь",
+ ["ю"] = "ю", ["я"] = "я",
+ },
+ orders = {
+ "а", "б", "в", "г", "д", "е", "ж", "з","и", "й",
+ "к", "a", "л", "a", "м", "н", "о", "п", "р", "с",
+ "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ь",
+ "ю", "я",
+ }
+}
+
+--- Old Church Slavonic
+
+-- The language symbol “cu” is taken from the Wikipedia subdomain
+-- cu.wikipedia.org.
+
+local uk, UK = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+
+definitions["cu"] = {
+ replacements = {
+ { "оу", uk }, { "ОУ", UK },
+ },
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["д"] = "д",
+ ["є"] = "є", ["ж"] = "ж", ["ѕ"] = "ѕ", ["ꙃ"] = "ѕ", ["з"] = "з",
+ ["ꙁ"] = "з", ["и"] = "и", ["і"] = "и", ["ї"] = "и", ["ћ"] = "ћ",
+ ["к"] = "к", ["л"] = "л", ["м"] = "м", ["н"] = "н", ["о"] = "о",
+ ["п"] = "п", ["р"] = "р", ["с"] = "с", ["т"] = "т", ["у"] = "у",
+ ["ѹ"] = "у", ["ꙋ"] = "у", [uk] = "у", ["ф"] = "ф", ["х"] = "х",
+ ["ѡ"] = "ѡ", ["ѿ"] = "ѡ", ["ѽ"] = "ѡ", ["ꙍ"] = "ѡ", ["ц"] = "ц",
+ ["ч"] = "ч", ["ш"] = "ш", ["щ"] = "щ", ["ъ"] = "ъ", ["ы"] = "ы",
+ ["ꙑ"] = "ы", ["ь"] = "ь", ["ѣ"] = "ѣ", ["ю"] = "ю", ["ꙗ"] = "ꙗ",
+ ["ѥ"] = "ѥ", ["ѧ"] = "ѧ", ["ѩ"] = "ѩ", ["ѫ"] = "ѫ", ["ѭ"] = "ѭ",
+ ["ѯ"] = "ѯ", ["ѱ"] = "ѱ", ["ѳ"] = "ѳ", ["ѵ"] = "ѵ", ["ѷ"] = "ѵ",
+ },
+ orders = {
+ "а", "б", "в", "г", "д", "є", "ж", "ѕ", "ꙃ", "з", -- Dzělo, U+0292, alternative: dz U+01f3
+ "ꙁ", "и", "і", "ї", "ћ", "к", "л", "м", "н", "о", -- Zemlja
+ "п", "р", "с", "т", "у", "ѹ", "ꙋ", uk, "ф", "х", -- U+0478 uk, horizontal ligature, U+0479 uk, vertical ligature
+ "ѡ", "ѿ", "ѽ", "ꙍ", "ц", "ч", "ш", "щ", "ъ", "ы", -- "ō", U+047f \, U+047d > Omega variants, U+064D /
+ "ꙑ", "ь", "ѣ", "ю", "ꙗ", "ѥ", "ѧ", "ѩ", "ѫ", "ѭ", -- Old jery (U+a651) as used e.g. by the OCS Wikipedia. IOTIFIED A
+ "ѯ", "ѱ", "ѳ", "ѵ", "ѷ",
+ },
+ upper = {
+ uk = UK,
+ },
+ lower = {
+ UK = uk,
+ }
+}
+
+--- Polish (including the letters q, v, x) Cf. ftp://ftp.gust.org.pl/pub/GUST/bulletin/03/02-bl.pdf.
+
+definitions["pl"] = {
+ entries = {
+ ["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",
+ ["ś"] = "ś", ["t"] = "t", ["u"] = "u", ["v"] = "v", ["w"] = "w",
+ ["x"] = "x", ["y"] = "y", ["z"] = "z", ["ź"] = "ź", ["ż"] = "ż",
+ },
+ orders = {
+ "a", "ą", "b", "c", "ć", "d", "e", "ę", "f", "g",
+ "h", "i", "j", "k", "l", "ł", "m", "n", "ń", "o",
+ "ó", "p", "q", "r", "s", "ś", "t", "u", "v", "w",
+ "x", "y", "z", "ź", "ż",
+ },
+}
+
+-- Czech, modified to treat quantities and other secondary characteristics indifferently. Cf.
+-- http://racek.vlada.cz/usneseni/usneseni_webtest.nsf/WebGovRes/0AD8FEF4CC04B7A4C12571B6006D69D0?OpenDocument
+-- (2.4.3; via <http://cs.wikipedia.org/wiki/Abecední_řazení#.C4.8Ce.C5.A1tina>)
+
+local ch, CH = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+
+definitions["cz"] = {
+ replacements = {
+ { "ch", ch }, { "Ch", ch }, { "CH", ch }
+ },
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č",
+ ["d"] = "d", ["ď"] = "d", ["e"] = "e", ["é"] = "e", ["ě"] = "e",
+ ["f"] = "f", ["g"] = "g", ["h"] = "h", [ch] = "ch", ["i"] = "i",
+ ["í"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l", ["m"] = "m",
+ ["n"] = "n", ["ň"] = "n", ["o"] = "o", ["ó"] = "o", ["p"] = "p",
+ ["q"] = "q", ["r"] = "r", ["ř"] = "ř", ["s"] = "s", ["š"] = "š",
+ ["t"] = "t", ["ť"] = "t", ["u"] = "u", ["ú"] = "u", ["ů"] = "u",
+ ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y", ["ý"] = "y",
+ ["z"] = "z", ["ž"] = "ž",
+ },
+ orders = {
+ "a", "á", "b", "c", "č", "d", "ď", "e", "é", "ě",
+ "f", "g", "h", ch, "i", "í", "j", "k", "l", "m",
+ "n", "ň", "o", "ó", "p", "q", "r", "ř", "s", "š",
+ "t", "ť", "u", "ú", "ů", "v", "w", "x", "y", "ý",
+ "z", "ž",
+ },
+ upper = {
+ ch = CH,
+ },
+ lower = {
+ CH = ch,
+ }
+}
+
+definitions["cs"] = { parent = "cz" }
+
+--- Slovak.
+
+-- Vowel and consonant quantities, "ď", "ľ", "ň", "ť", "ô", and "ä" are treated
+-- indifferently as their base character, as in my dictionary. If you prefer them
+-- to affect collation order, then use the values given in the comments. We could
+-- define an additional vector for that.
+
+local dz, DZ = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+local dzh, DZH = utfchar(replacementoffset + 2), utfchar(replacementoffset + 12)
+local ch, CH = utfchar(replacementoffset + 3), utfchar(replacementoffset + 13)
+
+definitions["sk"] = {
+ replacements = {
+ { "dz", dz }, { "dz", DZ },
+ { "dž", dzh }, { "dž", DZH },
+ { "ch", ch }, { "ch", CH },
+ },
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["ä"] = "a", ["b"] = "b", ["c"] = "c",
+ ["č"] = "č", ["d"] = "d", ["ď"] = "d", [dz] = "dz", [dzh] = "dž",
+ ["e"] = "e", ["é"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h",
+ [ch] = "ch", ["i"] = "i", ["í"] = "i", ["j"] = "j", ["k"] = "k",
+ ["l"] = "l", ["ĺ"] = "l", ["ľ"] = "l", ["m"] = "m", ["n"] = "n",
+ ["ň"] = "n", ["o"] = "o", ["ó"] = "o", ["ô"] = "o", ["p"] = "p",
+ ["q"] = "q", ["r"] = "r", ["ŕ"] = "r", ["s"] = "s", ["š"] = "š",
+ ["t"] = "t", ["ť"] = "t", ["u"] = "u", ["ú"] = "u", ["v"] = "v",
+ ["w"] = "w", ["x"] = "x", ["y"] = "y", ["ý"] = "y", ["z"] = "z",
+ ["ž"] = "ž",
+ },
+ orders = {
+ "a", "á", "ä", "b", "c", "č", "d", "ď", dz, dzh,
+ "e", "é", "f", "g", "h", ch, "i", "í", "j", "k",
+ "l", "ĺ", "ľ", "m", "n", "ň", "o", "ó", "ô", "p",
+ "q", "r", "ŕ", "s", "š", "t", "ť", "u", "ú", "v",
+ "w", "x", "y", "ý", "z", "ž",
+ },
+ upper = {
+ dz = DZ, dzh = DZH, ch = CH,
+ },
+ lower = {
+ DZ = dz, DZH = dzh, CH = ch,
+ }
+}
+
+--- Croatian
+
+local dzh, DZH = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+local lj, LJ = utfchar(replacementoffset + 2), utfchar(replacementoffset + 12)
+local nj, NJ = utfchar(replacementoffset + 3), utfchar(replacementoffset + 13)
+
+definitions["hr"] = {
+ replacements = {
+ { "dž", dzh }, { "DŽ", DZH },
+ { "lj", lj }, { "LJ", LJ },
+ { "nj", nj }, { "NJ", NJ },
+ },
+ entries = {
+ ["a"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č", ["ć"] = "ć",
+ ["d"] = "d", [dzh] = "dž", ["đ"] = "đ", ["e"] = "e", ["f"] = "f",
+ ["g"] = "g", ["h"] = "h", ["i"] = "i", ["j"] = "j", ["k"] = "k",
+ ["l"] = "l", [lj] = "lj", ["m"] = "m", ["n"] = "n", [nj] = "nj",
+ ["o"] = "o", ["p"] = "p", ["r"] = "r", ["s"] = "s", ["š"] = "š",
+ ["t"] = "t", ["u"] = "u", ["v"] = "v", ["z"] = "z", ["ž"] = "ž",
+ },
+ orders = {
+ "a", "b", "c", "č", "ć", "d", dzh, "đ", "e", "f",
+ "g", "h", "i", "j", "k", "l", lj, "m", "n", nj,
+ "o", "p", "r", "s", "š", "t", "u", "v", "z", "ž",
+ },
+ upper = {
+ dzh = DZH, lj = LJ, nj = NJ,
+ },
+ lower = {
+ DZH = dzh, LJ = lj, NJ = nj,
+ }
+}
+
+
+--- Serbian
+
+definitions["sr"] = {
+ entries = {
+ ["а"] = "а", ["б"] = "б", ["в"] = "в", ["г"] = "г", ["д"] = "д",
+ ["ђ"] = "ђ", ["е"] = "е", ["ж"] = "ж", ["з"] = "з", ["и"] = "и",
+ ["ј"] = "ј", ["к"] = "к", ["л"] = "л", ["љ"] = "љ", ["м"] = "м",
+ ["н"] = "н", ["њ"] = "њ", ["о"] = "о", ["п"] = "п", ["р"] = "р",
+ ["с"] = "с", ["т"] = "т", ["ћ"] = "ћ", ["у"] = "у", ["ф"] = "ф",
+ ["х"] = "х", ["ц"] = "ц", ["ч"] = "ч", ["џ"] = "џ",
+ ["ш"] = "ш",
+ },
+ orders = {
+ "а", "б", "в", "г", "д", "ђ", "е", "ж", "з", "и",
+ "ј", "к", "л", "љ", "м", "н", "њ", "о", "п", "р",
+ "с", "т", "ћ", "у", "ф", "х", "ц", "ч", "џ", "ш",
+ }
+}
+
+--- Transliteration: Russian|ISO9-1995
+
+-- Keeping the same collation order as Russian (v.s.).
+-- Matches the tables from:
+-- http://bitbucket.org/phg/transliterator/src/tip/tex/context/third/transliterator/trans_tables_iso9.lua
+
+local yer = utfchar(replacementoffset + 1)
+
+definitions["ru-iso9"] = {
+ replacements = {
+ { "''", yer },
+ },
+ entries = {
+ ["a"] = "a", ["b"] = "b", ["v"] = "v", ["g"] = "g", ["d"] = "d",
+ ["e"] = "e", ["ë"] = "ë", ["ž"] = "ž", ["z"] = "z", ["i"] = "i",
+ ["ì"] = "ì", ["j"] = "j", ["k"] = "k", ["l"] = "l", ["m"] = "m",
+ ["n"] = "n", ["o"] = "o", ["p"] = "p", ["r"] = "r", ["s"] = "s",
+ ["t"] = "t", ["u"] = "u", ["f"] = "f", ["h"] = "h", ["c"] = "c",
+ ["č"] = "č", ["š"] = "š", ["ŝ"] = "ŝ", ["ʺ"] = "ʺ", [yer] = "ʺ",
+ ["y"] = "y", ["ʹ"] = "ʹ", ["'"] = "ʹ", ["ě"] = "ě", ["è"] = "è",
+ ["û"] = "û", ["â"] = "â", ["û"] = "û", ["â"] = "â",
+ },
+ orders = {
+ "a", "b", "v", "g", "d", "e", "ë", "ž", "z", "i",
+ "ì", "j", "k", "l", "m", "n", "o", "p", "r", "s",
+ "t", "u", "f", "h", "c", "č", "š", "ŝ", "ʺ", yer,
+ "y", "ʹ", "'", "ě", "è", "û", "â", "û", "â",
+ }
+}
+
+--- Transliteration: Old Slavonic|scientific
+
+-- Matches the tables from:
+-- http://bitbucket.org/phg/transliterator/src/tip/tex/context/third/transliterator/trans_tables_scntfc.lua
+
+local uk, UK = utfchar(replacementoffset + 1), utfchar(replacementoffset + 21)
+local tshe, TSHE = utfchar(replacementoffset + 2), utfchar(replacementoffset + 22)
+local sht, SHT = utfchar(replacementoffset + 3), utfchar(replacementoffset + 23)
+local ju, JU = utfchar(replacementoffset + 4), utfchar(replacementoffset + 24)
+local ja, JA = utfchar(replacementoffset + 5), utfchar(replacementoffset + 25)
+local je, JE = utfchar(replacementoffset + 6), utfchar(replacementoffset + 26)
+local ijus, IJUS = utfchar(replacementoffset + 7), utfchar(replacementoffset + 27)
+local ibigjus, IBIGJUS = utfchar(replacementoffset + 8), utfchar(replacementoffset + 28)
+local xi, XI = utfchar(replacementoffset + 9), utfchar(replacementoffset + 29)
+local psi, PSI = utfchar(replacementoffset + 10), utfchar(replacementoffset + 30)
+local theta, THETA = utfchar(replacementoffset + 11), utfchar(replacementoffset + 31)
+local shch, SHCH = utfchar(replacementoffset + 12), utfchar(replacementoffset + 32)
+
+definitions["ocs-scn"] = {
+ replacements = {
+ { "ou", uk }, { "OU", UK },
+ { "g’", tshe }, { "G’", TSHE },
+ { "št", sht }, { "ŠT", SHT },
+ { "ju", ju }, { "JU", JU },
+ { "ja", ja }, { "JA", JA },
+ { "je", je }, { "JE", JE },
+ { "ję", ijus }, { "JĘ", IJUS },
+ { "jǫ", ibigjus }, { "JǪ", IBIGJUS },
+ { "ks", xi }, { "KS", XI },
+ { "ps", psi }, { "PS", PSI },
+ { "th", theta }, { "TH", THETA },
+ { "šč", shch }, { "ŠČ", SHCH },
+ },
+ entries = {
+ ["a"] = "a", ["b"] = "b", ["v"] = "v", ["g"] = "g", ["d"] = "d",
+ ["e"] = "e", ["ž"] = "ž", ["ʒ"] = "ʒ", ["z"] = "z", ["i"] = "i",
+ ["ï"] = "ï", [tshe] = "g’", ["k"] = "k", ["l"] = "l", ["m"] = "m",
+ ["n"] = "n", ["o"] = "o", ["p"] = "p", ["r"] = "r", ["s"] = "s",
+ ["t"] = "t", ["u"] = "u", ["f"] = "f", ["x"] = "x", ["o"] = "o",
+ ["c"] = "c", ["č"] = "č", ["š"] = "š", [sht] = "št", [shch] = "šč",
+ ["ъ"] = "ъ", ["y"] = "y", [uk] = "y", ["ь"] = "ь", ["ě"] = "ě",
+ [ju] = "ju", [ja] = "ja", [je] = "je", ["ę"] = "ę", [ijus] = "ję",
+ ["ǫ"] = "ǫ", [ibigjus] = "jǫ", [xi] = "ks", [psi] = "ps", [theta] = "th",
+ ["ü"] = "ü",
+ },
+ orders = {
+ "a", "b", "v", "g", "d", "e", "ž", "ʒ", "z", "i", "ï",
+ tshe, "k", "l", "m", "n", "o", "p", "r", "s", "t", "u",
+ "f", "x", "o", "c", "č", "š", sht, shch, "ъ", "y", uk,
+ "ь", "ě", ju, ja, je, "ę", ijus, "ǫ", ibigjus, xi, psi,
+ theta, "ü",
+ },
+ upper = {
+ uk = UK, tshe = TSHE, sht = SHT, ju = JU, ja = JA, je = JE, ijus = IJUS, ibigjus = IBIGJUS, xi = XI, psi = PSI, theta = THETA, shch = SHCH,
+ },
+ lower = {
+ UK = uk, TSHE = tshe, SHT = sht, JU = ju, JA = ja, JE = je, IJUS = ijus, IBIGJUS = ibigjus, XI = xi, PSI = psi, THETA = theta, SHCH = shch,
+ },
+}
+
+
+--- Norwegian (bokmål).
+
+definitions["no"] = {
+ entries = {
+ ["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", ["t"] = "t",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["z"] = "z", ["æ"] = "æ", ["ø"] = "ø", ["å"] = "å",
+ },
+ orders = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z", "æ", "ø", "å",
+ }
+}
+
+--- Danish (-> Norwegian).
+
+definitions["da"] = { parent = "no" }
+
+--- Swedish
+
+definitions["sv"] = {
+ entries = {
+ ["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", ["t"] = "t",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["z"] = "z", ["å"] = "å", ["ä"] = "ä", ["ö"] = "ö",
+ },
+ orders = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z", "å", "ä", "ö",
+ }
+}
+
+--- Icelandic
+
+-- Treating quantities as allographs.
+
+definitions["is"] = {
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["b"] = "b", ["d"] = "d", ["ð"] = "ð",
+ ["e"] = "e", ["é"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h",
+ ["i"] = "i", ["í"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l",
+ ["m"] = "m", ["n"] = "n", ["o"] = "o", ["ó"] = "o", ["p"] = "p",
+ ["r"] = "r", ["s"] = "s", ["t"] = "t", ["u"] = "u", ["ú"] = "u",
+ ["v"] = "v", ["x"] = "x", ["y"] = "y", ["ý"] = "y", ["þ"] = "þ",
+ ["æ"] = "æ", ["ö"] = "ö",
+ },
+ orders = {
+ "a", "á", "b", "d", "ð", "e", "é", "f", "g", "h",
+ "i", "í", "j", "k", "l", "m", "n", "o", "ó", "p",
+ "r", "s", "t", "u", "ú", "v", "x", "y", "ý", "þ",
+ "æ", "ö",
+ },
+}
+
+--- Greek
+
+definitions["gr"] = {
+ entries = {
+ ["α"] = "α", ["ά"] = "α", ["ὰ"] = "α", ["ᾶ"] = "α", ["ᾳ"] = "α",
+ ["ἀ"] = "α", ["ἁ"] = "α", ["ἄ"] = "α", ["ἂ"] = "α", ["ἆ"] = "α",
+ ["ἁ"] = "α", ["ἅ"] = "α", ["ἃ"] = "α", ["ἇ"] = "α", ["ᾁ"] = "α",
+ ["ᾴ"] = "α", ["ᾲ"] = "α", ["ᾷ"] = "α", ["ᾄ"] = "α", ["ᾂ"] = "α",
+ ["ᾅ"] = "α", ["ᾃ"] = "α", ["ᾆ"] = "α", ["ᾇ"] = "α", ["β"] = "β",
+ ["γ"] = "γ", ["δ"] = "δ", ["ε"] = "ε", ["έ"] = "ε", ["ὲ"] = "ε",
+ ["ἐ"] = "ε", ["ἔ"] = "ε", ["ἒ"] = "ε", ["ἑ"] = "ε", ["ἕ"] = "ε",
+ ["ἓ"] = "ε", ["ζ"] = "ζ", ["η"] = "η", ["η"] = "η", ["ή"] = "η",
+ ["ὴ"] = "η", ["ῆ"] = "η", ["ῃ"] = "η", ["ἠ"] = "η", ["ἤ"] = "η",
+ ["ἢ"] = "η", ["ἦ"] = "η", ["ᾐ"] = "η", ["ἡ"] = "η", ["ἥ"] = "η",
+ ["ἣ"] = "η", ["ἧ"] = "η", ["ᾑ"] = "η", ["ῄ"] = "η", ["ῂ"] = "η",
+ ["ῇ"] = "η", ["ᾔ"] = "η", ["ᾒ"] = "η", ["ᾕ"] = "η", ["ᾓ"] = "η",
+ ["ᾖ"] = "η", ["ᾗ"] = "η", ["θ"] = "θ", ["ι"] = "ι", ["ί"] = "ι",
+ ["ὶ"] = "ι", ["ῖ"] = "ι", ["ἰ"] = "ι", ["ἴ"] = "ι", ["ἲ"] = "ι",
+ ["ἶ"] = "ι", ["ἱ"] = "ι", ["ἵ"] = "ι", ["ἳ"] = "ι", ["ἷ"] = "ι",
+ ["ϊ"] = "ι", ["ΐ"] = "ι", ["ῒ"] = "ι", ["ῗ"] = "ι", ["κ"] = "κ",
+ ["λ"] = "λ", ["μ"] = "μ", ["ν"] = "ν", ["ξ"] = "ξ", ["ο"] = "ο",
+ ["ό"] = "ο", ["ὸ"] = "ο", ["ὀ"] = "ο", ["ὄ"] = "ο", ["ὂ"] = "ο",
+ ["ὁ"] = "ο", ["ὅ"] = "ο", ["ὃ"] = "ο", ["π"] = "π", ["ρ"] = "ρ",
+ ["ῤ"] = "ῤ", ["ῥ"] = "ῥ", ["σ"] = "σ", ["ς"] = "ς", ["τ"] = "τ",
+ ["υ"] = "υ", ["ύ"] = "υ", ["ὺ"] = "υ", ["ῦ"] = "υ", ["ὐ"] = "υ",
+ ["ὔ"] = "υ", ["ὒ"] = "υ", ["ὖ"] = "υ", ["ὑ"] = "υ", ["ὕ"] = "υ",
+ ["ὓ"] = "υ", ["ὗ"] = "υ", ["ϋ"] = "υ", ["ΰ"] = "υ", ["ῢ"] = "υ",
+ ["ῧ"] = "υ", ["φ"] = "φ", ["χ"] = "χ", ["ψ"] = "ω", ["ω"] = "ω",
+ ["ώ"] = "ω", ["ὼ"] = "ω", ["ῶ"] = "ω", ["ῳ"] = "ω", ["ὠ"] = "ω",
+ ["ὤ"] = "ω", ["ὢ"] = "ω", ["ὦ"] = "ω", ["ᾠ"] = "ω", ["ὡ"] = "ω",
+ ["ὥ"] = "ω", ["ὣ"] = "ω", ["ὧ"] = "ω", ["ᾡ"] = "ω", ["ῴ"] = "ω",
+ ["ῲ"] = "ω", ["ῷ"] = "ω", ["ᾤ"] = "ω", ["ᾢ"] = "ω", ["ᾥ"] = "ω",
+ ["ᾣ"] = "ω", ["ᾦ"] = "ω", ["ᾧ"] = "ω",
+ },
+ orders = {
+ "α", "ά", "ὰ", "ᾶ", "ᾳ", "ἀ", "ἁ", "ἄ", "ἂ", "ἆ",
+ "ἁ", "ἅ", "ἃ", "ἇ", "ᾁ", "ᾴ", "ᾲ", "ᾷ", "ᾄ", "ᾂ",
+ "ᾅ", "ᾃ", "ᾆ", "ᾇ", "β", "γ", "δ", "ε", "έ", "ὲ",
+ "ἐ", "ἔ", "ἒ", "ἑ", "ἕ", "ἓ", "ζ", "η", "η", "ή",
+ "ὴ", "ῆ", "ῃ", "ἠ", "ἤ", "ἢ", "ἦ", "ᾐ", "ἡ", "ἥ",
+ "ἣ", "ἧ", "ᾑ", "ῄ", "ῂ", "ῇ", "ᾔ", "ᾒ", "ᾕ", "ᾓ",
+ "ᾖ", "ᾗ", "θ", "ι", "ί", "ὶ", "ῖ", "ἰ", "ἴ", "ἲ",
+ "ἶ", "ἱ", "ἵ", "ἳ", "ἷ", "ϊ", "ΐ", "ῒ", "ῗ", "κ",
+ "λ", "μ", "ν", "ξ", "ο", "ό", "ὸ", "ὀ", "ὄ", "ὂ",
+ "ὁ", "ὅ", "ὃ", "π", "ρ", "ῤ", "ῥ", "σ", "ς", "τ",
+ "υ", "ύ", "ὺ", "ῦ", "ὐ", "ὔ", "ὒ", "ὖ", "ὑ", "ὕ",
+ "ὓ", "ὗ", "ϋ", "ΰ", "ῢ", "ῧ", "φ", "χ", "ψ", "ω",
+ "ώ", "ὼ", "ῶ", "ῳ", "ὠ", "ὤ", "ὢ", "ὦ", "ᾠ", "ὡ",
+ "ὥ", "ὣ", "ὧ", "ᾡ", "ῴ", "ῲ", "ῷ", "ᾤ", "ᾢ", "ᾥ",
+ "ᾣ", "ᾦ", "ᾧ",
+ },
+}
+
+--- Latin
+
+-- Treating the post-classical fricatives “j” and “v” as “i” and “u”
+-- respectively.
+
+definitions["la"] = {
+ replacements = {
+ { "æ", "ae" }, { "Æ", "AE" },
+ },
+ entries = {
+ ["a"] = "a", ["ā"] = "a", ["ă"] = "a", ["b"] = "b", ["c"] = "c",
+ ["d"] = "d", ["e"] = "e", ["ē"] = "e", ["ĕ"] = "e", ["f"] = "f",
+ ["g"] = "g", ["h"] = "h", ["i"] = "i", ["ī"] = "i", ["ĭ"] = "i",
+ ["j"] = "i", ["k"] = "k", ["l"] = "l", ["m"] = "m", ["n"] = "n",
+ ["o"] = "o", ["ō"] = "o", ["ŏ"] = "o", ["p"] = "p", ["q"] = "q",
+ ["r"] = "r", ["s"] = "s", ["t"] = "t", ["u"] = "u", ["ū"] = "u",
+ ["ŭ"] = "u", ["v"] = "u", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["ȳ"] = "y", ["y̆"] = "y", ["z"] = "z",
+ },
+ orders = {
+ "a", "ā", "ă", "b", "c", "d", "e", "ē", "ĕ", "f",
+ "g", "h", "i", "ī", "ĭ", "j", "k", "l", "m", "n",
+ "o", "ō", "ŏ", "p", "q", "r", "s", "t", "u", "ū",
+ "ŭ", "v", "w", "x", "y", "ȳ", "y̆", "z",
+ }
+}
+
+--- Italian
+
+definitions["it"] = {
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["b"] = "b", ["c"] = "c", ["d"] = "d",
+ ["e"] = "e", ["é"] = "e", ["è"] = "e", ["f"] = "f", ["g"] = "g",
+ ["h"] = "h", ["i"] = "i", ["í"] = "i", ["ì"] = "i", ["j"] = "i",
+ ["k"] = "k", ["l"] = "l", ["m"] = "m", ["n"] = "n", ["o"] = "o",
+ ["ó"] = "o", ["ò"] = "o", ["p"] = "p", ["q"] = "q", ["r"] = "r",
+ ["s"] = "s", ["t"] = "t", ["u"] = "u", ["ú"] = "u", ["ù"] = "u",
+ ["v"] = "u", ["w"] = "w", ["x"] = "x", ["y"] = "y", ["z"] = "z",
+ },
+ orders = {
+ "a", "á", "b", "c", "d", "e", "é", "è", "f", "g",
+ "h", "i", "í", "ì", "j", "k", "l", "m", "n", "o",
+ "ó", "ò", "p", "q", "r", "s", "t", "u", "ú", "ù",
+ "v", "w", "x", "y", "z",
+ }
+}
+
+--- Romanian
+
+definitions["ro"] = {
+ entries = {
+ ["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", ["ș"] = "ș", ["t"] = "t", ["ț"] = "ț",
+ ["u"] = "u", ["v"] = "v", ["w"] = "w", ["x"] = "x", ["y"] = "y",
+ ["z"] = "z",
+ },
+ orders = {
+ "a", "ă", "â", "b", "c", "d", "e", "f", "g", "h",
+ "i", "î", "j", "k", "l", "m", "n", "o", "p", "q",
+ "r", "s", "ș", "t", "ț", "u", "v", "w", "x", "y",
+ "z",
+ }
+}
+
+--- Spanish
+
+definitions["es"] = {
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["b"] = "b", ["c"] = "c", ["d"] = "d",
+ ["e"] = "e", ["é"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h",
+ ["i"] = "i", ["í"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l",
+ ["m"] = "m", ["n"] = "n", ["ñ"] = "ñ", ["o"] = "o", ["ó"] = "o",
+ ["p"] = "p", ["q"] = "q", ["r"] = "r", ["s"] = "s", ["t"] = "t",
+ ["u"] = "u", ["ú"] = "u", ["ü"] = "u", ["v"] = "v", ["w"] = "w",
+ ["x"] = "x", ["y"] = "y", ["z"] = "z",
+ },
+ orders = {
+ "a", "á", "b", "c", "d", "e", "é", "f", "g", "h",
+ "i", "í", "j", "k", "l", "m", "n", "ñ", "o", "ó",
+ "p", "q", "r", "s", "t", "u", "ú", "ü", "v", "w",
+ "x", "y", "z",
+ }
+}
+
+--- Portuguese
+
+definitions["pt"] = {
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["â"] = "a", ["ã"] = "a", ["à"] = "a",
+ ["b"] = "b", ["c"] = "c", ["ç"] = "c", ["d"] = "d", ["e"] = "e",
+ ["é"] = "e", ["ê"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h",
+ ["i"] = "i", ["í"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l",
+ ["m"] = "m", ["n"] = "n", ["o"] = "o", ["ó"] = "o", ["ô"] = "o",
+ ["õ"] = "o", ["p"] = "p", ["q"] = "q", ["r"] = "r", ["s"] = "s",
+ ["t"] = "t", ["u"] = "u", ["ú"] = "u", ["ü"] = "u", ["v"] = "v",
+ ["w"] = "w", ["x"] = "x", ["y"] = "y", ["z"] = "z",
+ },
+ orders = {
+ "a", "á", "â", "ã", "à", "b", "c", "ç", "d", "e",
+ "é", "ê", "f", "g", "h", "i", "í", "j", "k", "l",
+ "m", "n", "o", "ó", "ô", "õ", "p", "q", "r", "s",
+ "t", "u", "ú", "ü", "v", "w", "x", "y", "z",
+ }
+}
+
+--- Lithuanian
+
+local ch, CH = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+
+definitions["lt"] = {
+ replacements = {
+ { "ch", ch }, { "CH", CH}
+ },
+ entries = {
+ ["a"] = "a", ["ą"] = "a", ["b"] = "b", ["c"] = "c", [ch ] = "c",
+ ["č"] = "č", ["d"] = "d", ["e"] = "e", ["ę"] = "e", ["ė"] = "e",
+ ["f"] = "f", ["g"] = "g", ["h"] = "h", ["i"] = "i", ["į"] = "i",
+ ["y"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l", ["m"] = "m",
+ ["n"] = "n", ["o"] = "o", ["p"] = "p", ["r"] = "r", ["s"] = "s",
+ ["š"] = "š", ["t"] = "t", ["u"] = "u", ["ų"] = "u", ["ū"] = "u",
+ ["v"] = "v", ["z"] = "z", ["ž"] = "ž",
+ },
+ orders = {
+ "a", "ą", "b", "c", ch, "č", "d", "e", "ę", "ė",
+ "f", "g", "h", "i", "į", "y", "j", "k", "l", "m",
+ "n", "o", "p", "r", "s", "š", "t", "u", "ų", "ū",
+ "v", "z", "ž",
+ },
+ lower = {
+ ch = CH,
+ },
+ upper = {
+ CH = ch,
+ },
+}
+
+--- Latvian
+
+definitions["lv"] = {
+ entries = {
+ ["a"] = "a", ["ā"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č",
+ ["d"] = "d", ["e"] = "e", ["ē"] = "e", ["f"] = "f", ["g"] = "g",
+ ["ģ"] = "ģ", ["h"] = "h", ["i"] = "i", ["ī"] = "i", ["j"] = "j",
+ ["k"] = "k", ["ķ"] = "ķ", ["l"] = "l", ["ļ"] = "ļ", ["m"] = "m",
+ ["n"] = "n", ["ņ"] = "ņ", ["o"] = "o", ["ō"] = "o", ["p"] = "p",
+ ["r"] = "r", ["ŗ"] = "ŗ", ["s"] = "s", ["š"] = "š", ["t"] = "t",
+ ["u"] = "u", ["ū"] = "u", ["v"] = "v", ["z"] = "z", ["ž"] = "ž",
+ },
+ orders = {
+ "a", "ā", "b", "c", "č", "d", "e", "ē", "f", "g",
+ "ģ", "h", "i", "ī", "j", "k", "ķ", "l", "ļ", "m",
+ "n", "ņ", "o", "ō", "p", "r", "ŗ", "s", "š", "t",
+ "u", "ū", "v", "z", "ž",
+ }
+}
+
+--- Hungarian
+
+-- Helpful but disturbing:
+-- http://en.wikipedia.org/wiki/Hungarian_alphabet#Alphabetical_ordering_.28collation.29
+-- (In short: you'd have to analyse word-compounds to realize a correct order
+-- for sequences like “nny”, “ssz”, and “zsz”. This is left as an exercise to
+-- the reader…)
+
+local cs, CS = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11)
+local dz, DZ = utfchar(replacementoffset + 2), utfchar(replacementoffset + 12)
+local dzs, DZS = utfchar(replacementoffset + 3), utfchar(replacementoffset + 13)
+local gy, GY = utfchar(replacementoffset + 4), utfchar(replacementoffset + 14)
+local ly, LY = utfchar(replacementoffset + 5), utfchar(replacementoffset + 15)
+local ny, NY = utfchar(replacementoffset + 6), utfchar(replacementoffset + 16)
+local sz, SZ = utfchar(replacementoffset + 7), utfchar(replacementoffset + 17)
+local ty, TY = utfchar(replacementoffset + 8), utfchar(replacementoffset + 18)
+local zs, ZS = utfchar(replacementoffset + 9), utfchar(replacementoffset + 19)
+
+definitions["hu"] = {
+ replacements = {
+ { "cs", cs }, { "CS", CS },
+ { "dz", dz }, { "DZ", DZ },
+ { "dzs", dzs }, { "DZS", DZS },
+ { "gy", gy }, { "GY", GY },
+ { "ly", ly }, { "LY", LY },
+ { "ny", ny }, { "NY", NY },
+ { "sz", sz }, { "SZ", SZ },
+ { "ty", ty }, { "TY", TY },
+ { "zs", zs }, { "ZS", ZS },
+ },
+ entries = {
+ ["a"] = "a", ["á"] = "a", ["b"] = "b", ["c"] = "c", [cs ] = "cs",
+ ["d"] = "d", [dz ] = "dz", [dzs] = "dzs", ["e"] = "e", ["é"] = "e",
+ ["f"] = "f", ["g"] = "g", [gy ] = "gy", ["h"] = "h", ["i"] = "i",
+ ["í"] = "i", ["j"] = "j", ["k"] = "k", ["l"] = "l", [ly ] = "ly",
+ ["m"] = "m", ["n"] = "n", [ny ] = "ny", ["o"] = "o", ["ó"] = "o",
+ ["ö"] = "ö", ["ő"] = "ö", ["p"] = "p", ["q"] = "q", ["r"] = "r",
+ ["s"] = "s", [sz ] = "sz", ["t"] = "t", [ty ] = "ty", ["u"] = "u",
+ ["ú"] = "u", ["ü"] = "ü", ["ű"] = "ü", ["v"] = "v", ["w"] = "w",
+ ["x"] = "x", ["y"] = "y", ["z"] = "z", [zs ] = "zs",
+ },
+ orders = {
+ "a", "á", "b", "c", cs, "d", dz, dzs, "e", "é",
+ "f", "g", gy, "h", "i", "í", "j", "k", "l", ly,
+ "m", "n", ny, "o", "ó", "ö", "ő", "p", "q", "r",
+ "s", sz, "t", ty, "u", "ú", "ü", "ű", "v", "w",
+ "x", "y", "z", zs,
+ },
+ lower = {
+ CS = cs, DZ = dz, DZS = dzs, GY = gy, LY = ly, NY = ny, SZ = sz, TY = ty, ZS = zs,
+ },
+ upper = {
+ cs = CS, dz = DZ, dzs = DZS, gy = GY, ly = LY, ny = NY, sz = SZ, ty = TY, zs = ZS,
+ },
+}
+
+--- 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",
+ },
+ 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",
+ }
+}
+
+--- Korean
+
+local fschars = characters.fschars
+
+local function firstofsplit(first)
+ local fs = fschars[first] or first -- leadconsonant
+ return fs, fs -- entry, tag
+end
+
+definitions["kr"] = {
+ firstofsplit = firstofsplit,
+ orders = {
+ "ㄱ", "ㄴ", "ㄷ", "ㄹ", "ㅁ", "ㅂ", "ㅅ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ",
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
+ "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
+ }
+}
+
+-- Japanese
+
+definitions["jp"] = {
+ replacements = {
+ { "ぁ", "あ" }, { "ぃ", "い" },
+ { "ぅ", "う" }, { "ぇ", "え" },
+ { "ぉ", "お" }, { "っ", "つ" },
+ { "ゃ", "や" }, { "ゅ", "ゆ" },
+ { "ょ", "よ" },
+ },
+ entries = {
+ ["あ"] = "あ", ["い"] = "い", ["う"] = "う", ["え"] = "え", ["お"] = "お",
+ ["か"] = "か", ["き"] = "き", ["く"] = "く", ["け"] = "け", ["こ"] = "こ",
+ ["さ"] = "さ", ["し"] = "し", ["す"] = "す", ["せ"] = "せ", ["そ"] = "そ",
+ ["た"] = "た", ["ち"] = "ち", ["つ"] = "つ", ["て"] = "て", ["と"] = "と",
+ ["な"] = "な", ["に"] = "に", ["ぬ"] = "ぬ", ["ね"] = "ね", ["の"] = "の",
+ ["は"] = "は", ["ひ"] = "ひ", ["ふ"] = "ふ", ["へ"] = "へ", ["ほ"] = "ほ",
+ ["ま"] = "ま", ["み"] = "み", ["む"] = "む", ["め"] = "め", ["も"] = "も",
+ ["や"] = "や", ["ゆ"] = "ゆ", ["よ"] = "よ",
+ ["ら"] = "ら", ["り"] = "り", ["る"] = "る", ["れ"] = "れ", ["ろ"] = "ろ",
+ ["わ"] = "わ", ["ゐ"] = "ゐ", ["ゑ"] = "ゑ", ["を"] = "を", ["ん"] = "ん",
+ },
+ orders = {
+ "あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ",
+ "さ", "し", "す", "せ", "そ", "た", "ち", "つ", "て", "と",
+ "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ",
+ "ま", "み", "む", "め", "も", "や", "ゆ", "よ",
+ "ら", "り", "る", "れ", "ろ", "わ", "ゐ", "ゑ", "を", "ん",
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua
new file mode 100644
index 00000000000..cdf9b505119
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua
@@ -0,0 +1,66 @@
+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 vpack_node = node.vpack
+
+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()
+ nodes.tasks.enableaction("finalizers","nodes.handlers.graphicvadjust")
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv
new file mode 100644
index 00000000000..ad0f92a1f2e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv
@@ -0,0 +1,51 @@
+%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}{1.001}
+
+\definesystemattribute [graphicvadjust] [public]
+
+\unexpanded\def\enablegraphicvadjust
+ {\writestatus\m!systems{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/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua
new file mode 100644
index 00000000000..a67a3013333
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua
@@ -0,0 +1,149 @@
+if not modules then modules = { } end modules ['spac-ali'] = {
+ version = 1.001,
+ comment = "companion to spac-ali.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local div = math.div
+local format = string.format
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+
+local hpack_nodes = nuts.hpack
+local linked_nodes = nuts.linked
+
+local unsetvalue = attributes.unsetvalue
+
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local line_code = listcodes.line
+
+local new_stretch = nodepool.stretch
+
+local a_realign = attributes.private("realign")
+
+local texsetattribute = tex.setattribute
+local texgetcount = tex.getcount
+
+local isleftpage = layouts.status.isleftpage
+
+typesetters = typesetters or { }
+local alignments = { }
+typesetters.alignments = alignments
+
+local report_realign = logs.reporter("typesetters","margindata")
+local trace_realign = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
+
+local nofrealigned = 0
+
+-- leftskip rightskip parfillskip
+-- raggedleft 0 + 0 -
+-- raggedright 0 0 fil
+-- raggedcenter 0 + 0 + -
+
+local function handler(head,leftpage,realpageno)
+ local current = head
+ local done = false
+ while current do
+ local id = getid(current)
+ if id == hlist_code then
+ if getsubtype(current) == line_code then
+ local a = getattr(current,a_realign)
+ if not a or a == 0 then
+ -- skip
+ else
+ local align = a % 10
+ local pageno = div(a,10)
+ if pageno == realpageno then
+ -- already ok
+ else
+ local action = 0
+ if align == 1 then -- flushright
+ action = leftpage and 1 or 2
+ elseif align == 2 then -- flushleft
+ action = leftpage and 2 or 1
+ end
+ if action == 1 then
+ setlist(current,hpack_nodes(linked_nodes(getlist(current),new_stretch(3)),getfield(current,"width"),"exactly"))
+ if trace_realign then
+ report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ elseif action == 2 then
+ setlist(current,hpack_nodes(linked_nodes(new_stretch(3),getlist(current)),getfield(current,"width"),"exactly"))
+ if trace_realign then
+ report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ elseif trace_realign then
+ report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ done = true
+ nofrealigned = nofrealigned + 1
+ end
+ setattr(current,a_realign,unsetvalue)
+ end
+ end
+ handler(getlist(current),leftpage,realpageno)
+ elseif id == vlist_code then
+ handler(getlist(current),leftpage,realpageno)
+ end
+ current = getnext(current)
+ end
+ return head, done
+end
+
+function alignments.handler(head)
+ local leftpage = isleftpage(true,false)
+ local realpageno = texgetcount("realpageno")
+ local head, done = handler(tonut(head),leftpage,realpageno)
+ return tonode(head), done
+end
+
+local enabled = false
+
+function alignments.set(n)
+ if not enabled then
+ enableaction("shipouts","typesetters.alignments.handler")
+ enabled = true
+ if trace_realign then
+ report_realign("enabled")
+ end
+ end
+ texsetattribute(a_realign,texgetcount("realpageno") * 10 + n)
+end
+
+interfaces.implement {
+ name = "setrealign",
+ actions = alignments.set,
+ arguments = "integer",
+}
+
+statistics.register("realigning", function()
+ if nofrealigned > 0 then
+ return format("%s processed",nofrealigned)
+ else
+ return nil
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv
new file mode 100644
index 00000000000..21714f07c36
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv
@@ -0,0 +1,1238 @@
+%D \module
+%D [ file=spac-ali,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Alignments,
+%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 / Alignments}
+
+\unprotect
+
+%D The \type {new} and \type {old} methods are gone as we now have \type
+%D {flush*} variants. Starting at the last day of 2011 both methods are
+%D merged into one and caching has been added, which makes switching
+%D twice as fast.
+
+% Todo: find a way to force last lines to have some distance from the right
+% edge (problem: keywords or presets), maybe a plugin
+%
+% \setupalign[...,myoption] % last
+%
+% but that also means myoption gets frozen due to caching.
+
+\registerctxluafile{spac-ali}{1.001}
+
+\definesystemattribute[realign] [public] % might be combined with the next one
+\definesystemattribute[alignstate][public] % will make a single attributes for several states
+
+\appendtoks
+ \attribute\realignattribute \attributeunsetvalue
+ \attribute\alignstateattribute\attributeunsetvalue
+\to \everyforgetall
+
+\unexpanded\def\resetrealignsignal{\attribute\realignattribute\attributeunsetvalue}
+\unexpanded\def\signalinnerrealign{\clf_setrealign\plustwo}
+\unexpanded\def\signalouterrealign{\clf_setrealign\plusone}
+
+\installcorenamespace{aligncommand}
+\installcorenamespace{alignhorizontal}
+\installcorenamespace{alignvertical}
+
+\installcorenamespace{alignmentnormalcache}
+\installcorenamespace{alignmentraggedcache}
+
+% nasty hack:
+
+\installcorenamespace{alignmentnormalcacheodd}
+\installcorenamespace{alignmentnormalcacheeven}
+
+\installcorenamespace{alignmentraggedcacheodd}
+\installcorenamespace{alignmentraggedcacheeven}
+
+\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi}
+\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi}
+
+\newtoks\everyresetalign % todo
+
+% We will not use bodydir and pagedir so we disable them. That way we get
+% normal hyperlink support.
+
+\let\spac_directions_normal_body_dir\normalbodydir
+\let\spac_directions_normal_page_dir\normalpagedir
+
+\unexpanded\def\bodydir{\afterassignment\spac_directions_bodydir_indeed\spac_directions_normal_body_dir} \let\normalbodydir\bodydir
+\unexpanded\def\pagedir{\afterassignment\spac_directions_pagedir_indeed\spac_directions_normal_page_dir} \let\normalpagedir\pagedir
+
+\def\spac_directions_bodydir_indeed{\spac_directions_normal_body_dir TLT\relax}
+\def\spac_directions_pagedir_indeed{\spac_directions_normal_page_dir TLT\relax}
+
+% This will become a more advanced layout controller soon:
+
+\newconditional\layoutlefttoright \settrue\layoutlefttoright
+\newconditional\displaylefttoright \settrue\displaylefttoright
+\newconditional\inlinelefttoright \settrue\inlinelefttoright
+
+\unexpanded\def\lefttoright
+ {\ifvmode
+ \spac_directions_lefttoright_vmode
+ \else
+ \spac_directions_lefttoright_hmode
+ \fi}
+
+\unexpanded\def\spac_directions_lefttoright_vmode
+ {\settrue\displaylefttoright
+ \settrue\inlinelefttoright
+ \textdir TLT\relax
+ \pardir TLT\relax}
+
+\unexpanded\def\spac_directions_lefttoright_hmode
+ {\settrue\inlinelefttoright
+ \textdir TLT\relax}
+
+\unexpanded\def\righttoleft
+ {\ifvmode
+ \spac_directions_righttoleft_vmode
+ \else
+ \spac_directions_righttoleft_hmode
+ \fi}
+
+\unexpanded\def\spac_directions_righttoleft_vmode
+ {\setfalse\displaylefttoright
+ \setfalse\inlinelefttoright
+ \textdir TRT\relax
+ \pardir TRT\relax}
+
+\unexpanded\def\spac_directions_righttoleft_hmode
+ {\textdir TRT\relax
+ \setfalse\inlinelefttoright}
+
+% \def\currentdirectionparameters
+% {\ifconditional\inlinelefttoright \else
+% idir {r2l}%
+% \fi
+% \ifconditional\displaylefttoright \else
+% ddir {r2l}%
+% \fi}
+
+\unexpanded\def\synchronizelayoutdirection
+ {\ifconditional\layoutlefttoright
+ \spac_directions_synchronize_lr
+ \else
+ \spac_directions_synchronize_rl
+ \fi}
+
+\unexpanded\def\synchronizedisplaydirection
+ {\ifconditional\displaylefttoright
+ \spac_directions_synchronize_lr
+ \else
+ \spac_directions_synchronize_rl
+ \fi}
+
+\def\spac_directions_synchronize_lr
+ {\settrue\inlinelefttoright
+ \textdir TLT\relax
+ \pardir TLT\relax}
+
+\def\spac_directions_synchronize_rl
+ {\setfalse\inlinelefttoright
+ \textdir TRT\relax
+ \pardir TRT\relax}
+
+\unexpanded\def\synchronizeinlinedirection
+ {\textdir T\ifconditional\inlinelefttoright L\else R\fi T\relax}
+
+% 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
+ ]\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\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next}
+\unexpanded\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox
+\unexpanded\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop
+
+\unexpanded\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi}
+\unexpanded\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi}
+\unexpanded\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi}
+
+% Tolerance and hyphenation
+
+\ifdefined\lesshyphens \else \let\lesshyphens\relax \fi
+\ifdefined\morehyphens \else \let\morehyphens\relax \fi
+\ifdefined\nohyphens \else \let\nohyphens \relax \fi
+\ifdefined\dohyphens \else \let\dohyphens \relax \fi
+
+\newconstant\c_spac_tolerance_default \c_spac_tolerance_default 1500 % shouldn't that be 200
+\newconstant\c_spac_tolerance_minimum \c_spac_tolerance_minimum 1500
+\newconstant\c_spac_tolerance_normal \c_spac_tolerance_normal 3000
+\newconstant\c_spac_tolerance_extreme \c_spac_tolerance_extreme 4500
+
+\def\spac_align_set_raggedness_left {\plustwo\bodyfontsize}
+\def\spac_align_set_raggedness_right {\plustwo\bodyfontsize}
+\def\spac_align_set_raggedness_middle{\plussix\bodyfontsize} % overloaded below
+
+% oeps, hsize can be 0pt in which case we get a strange division
+% was: 6\bodyfontsize, fails on: \placefigure{x $x=x$ x}{}
+
+\def\spac_align_set_raggedness_middle{\ifdim\hsize=\zeropoint\plussix\bodyfontsize\else.5\hsize\fi}
+
+\unexpanded\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered
+ {\ifnum\tolerance<\c_spac_tolerance_minimum
+ \tolerance\c_spac_tolerance_minimum % small values have unwanted side effects
+ \else
+ % todo: take set value or none .. better done elsewhere (200 is normal)
+ \fi
+ \ifx\dohyphens\relax % was 2.5 in old implementation using scratch registers
+ \hyphenpenalty\dimexpr2.8\hsize/\dimexpr#1\relax\relax % 50 in raggedright/raggedleft
+ \fi}
+
+\unexpanded\def\spac_align_set_tolerant
+ {\tolerance\c_spac_tolerance_normal}
+
+\unexpanded\def\spac_align_set_very_tolerant
+ {\tolerance\c_spac_tolerance_extreme}
+
+\unexpanded\def\spac_align_set_stretch
+ {\emergencystretch\bodyfontsize}
+
+\unexpanded\def\spac_align_set_extreme_stretch
+ {\emergencystretch10\bodyfontsize}
+
+% Vertical
+
+\newconstant\c_spac_align_state_vertical
+
+\unexpanded\def\spac_align_set_vertical_none
+ {\let\raggedtopcommand \relax
+ \let\raggedbottomcommand\relax}
+
+\unexpanded\def\spac_align_set_vertical_lohi
+ {\let\raggedtopcommand \vfilll
+ \let\raggedbottomcommand\vfilll}
+
+\unexpanded\def\spac_align_set_vertical_low
+ {\let\raggedtopcommand \vfilll
+ \let\raggedbottomcommand\relax}
+
+\unexpanded\def\spac_align_set_vertical_high
+ {\let\raggedtopcommand \relax
+ \let\raggedbottomcommand\vfilll}
+
+\def\spac_align_flush_vertical
+ {\ifcase\c_spac_align_state_vertical
+ \spac_align_set_vertical_none
+ \or
+ \spac_align_set_vertical_lohi
+ \or
+ \spac_align_set_vertical_low
+ \or
+ \spac_align_set_vertical_high
+ \fi}
+
+% Horizontal
+
+\ifdefined\raggedonelinerstate \else
+ \newconditional\raggedonelinerstate % public
+\fi
+
+% \appendtoks
+% \setfalse\raggedonelinerstate
+% \to \everyforgetall
+
+\newconstant\raggedstatus % public
+
+\newconstant\c_spac_align_state_horizontal
+\newconstant\c_spac_align_state_broad
+\newconstant\c_spac_align_state_par_fill
+
+\def\v_spac_align_fill_amount {\plusone fil}
+\def\v_spac_align_fill_amount_negative {\minusone fil}
+\def\v_spac_align_fill_amount_double {\plustwo fil}
+\def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key
+\def\v_spac_align_fill_amount_half {.5fil}
+\let\v_spac_align_space_amount \interwordspace
+\def\v_spac_align_space_amount_x {.5\emwidth}
+
+\newskip\s_zero_plus_one_fil \s_zero_plus_one_fil = 0pt plus 1fil
+\newskip\s_zero_plus_zero \s_zero_plus_zero = 0pt plus 0pt
+
+% \s!plus ... slower than inline
+
+\unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips
+ {\raggedstatus\zerocount
+ \attribute\alignstateattribute\attributeunsetvalue
+ \leftskip \plusone\leftskip
+ \rightskip \plusone\rightskip
+ \spaceskip \zeropoint
+ \xspaceskip \zeropoint
+ \parfillskip\s_zero_plus_one_fil % new
+ \setfalse\raggedonelinerstate % now here
+ \let\updateraggedskips\relax} % no need for adaption
+
+\unexpanded\def\spac_align_set_horizontal_left
+ {\setraggedness\spac_align_set_raggedness_left
+ \raggedstatus\plusone
+ \attribute\alignstateattribute\plusone
+ \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_left
+ \rightskip \plusone\rightskip\s!plus\zeropoint
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_center
+ {\setraggedness\spac_align_set_raggedness_middle
+ \raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_middle
+ \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_middle
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_right
+ {\setraggedness\spac_align_set_raggedness_right
+ \raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \s!plus\zeropoint
+ \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_right
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_one_fil
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_left
+ {\raggedstatus\plusone
+ \attribute\alignstateattribute\plusone
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\s!plus\zeropoint
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_center
+ {\raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_right
+ {\raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \s!plus\zeropoint
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_wide_center
+ {\setraggedness\spac_align_set_raggedness_middle
+ \raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount_half
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_half
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_centered_last_line
+ {\raggedstatus\zerocount
+ \attribute\alignstateattribute\attributeunsetvalue
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax
+ \spaceskip \zeropoint\relax
+ \xspaceskip \zeropoint\relax
+ \parfillskip\zeropoint\s!plus\v_spac_align_fill_amount_double\relax
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_right_tt % a plain command
+ {\tttf % brrr
+ \raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \s!plus\zeropoint\relax
+ \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_right\relax
+ \spaceskip \zeropoint\relax
+ \xspaceskip \zeropoint\relax
+ \parfillskip\s_zero_plus_zero
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_extra
+ {\xspaceskip\zeropoint\s!plus\v_spac_align_fill_amount_space\relax}
+
+\def\spac_align_flush_horizontal
+ {\ifcase\c_spac_align_state_horizontal
+ % 0
+ \spac_align_set_horizontal_none
+ \or
+ % 1 center
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_center
+ \or
+ \spac_align_set_horizontal_very_center
+ \or
+ \spac_align_set_horizontal_wide_center
+ \fi
+ \or
+ % 2 flush left
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_right
+ \else
+ \spac_align_set_horizontal_very_right
+ \fi
+ \or
+ % 3 flush right
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_left
+ \else
+ \spac_align_set_horizontal_very_left
+ \fi
+ \or
+ % 4 inner
+ \ifdoublesided
+ \signalinnerrealign
+ \fi
+ \rightorleftpageaction\spac_align_set_horizontal_right\spac_align_set_horizontal_left
+ \or
+ % 5 outer
+ \ifdoublesided
+ \signalouterrealign
+ \fi
+ \rightorleftpageaction\spac_align_set_horizontal_left\spac_align_set_horizontal_right
+ \or
+ % 6 oneliner
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_right
+ \else
+ \spac_align_set_horizontal_very_right
+ \fi
+ \parfillskip\zeropoint
+ \or
+ % 7 centered last line
+ \spac_align_set_horizontal_centered_last_line
+ \or
+ \parfillskip\zeropoint
+ \fi
+ \relax}
+
+% Page spacing:
+
+\newconstant\c_spac_align_state_page
+
+\def\bottomalignlimit{\plusthree\lineheight}
+
+\newconstant\bottomraggednessmode % 0=ragged 1=normal/align 2=baseline
+
+\unexpanded\def\raggedbottom
+ {\bottomraggednessmode\zerocount
+ \settopskip}
+
+\unexpanded\def\alignbottom
+ {\bottomraggednessmode\plusone
+ \settopskip}
+
+\unexpanded\def\baselinebottom
+ {\bottomraggednessmode\plustwo
+ \settopskip}
+
+\let\normalbottom\alignbottom % downward compatible
+
+\unexpanded\def\setbottomalignmode#1%
+ {\bottomraggednessmode#1%
+ \settopskip}
+
+\def\spac_align_flush_page
+ {\ifcase\c_spac_align_state_page
+ % keep state
+ \or
+ \raggedbottom
+ \or
+ \alignbottom
+ \or
+ \baselinebottom
+ \fi}
+
+% Directions
+
+\newconstant\c_spac_align_state_direction
+
+\def\spac_align_flush_direction
+ {\ifcase\c_spac_align_state_direction
+ % keep state
+ \or
+ \lefttoright
+ \or
+ \righttoleft
+ \fi}
+
+% Interesting is that the non cached version is also pretty efficient
+% and as we cache we seldom call that one now so one can debate the
+% speedup.
+
+\newtoks\t_spac_align_collected
+
+\let\raggedcommand \relax
+\let\updateraggedskips\relax
+
+\def\spac_align_add_to_cache
+ {\let\raggedbox\relax % why
+ % we inherit hyphenation and tolerance
+ \t_spac_align_collected \emptytoks
+ \c_spac_align_state_broad \zerocount
+ \c_spac_align_state_horizontal\zerocount
+ \c_spac_align_state_vertical \zerocount
+ \c_spac_align_state_direction \zerocount % what is default ?
+ \c_spac_align_state_page \zerocount
+ \c_spac_align_state_par_fill \zerocount
+ \ifcsname\??aligncommand\m_spac_align_asked\endcsname
+ \lastnamedcs
+ \else
+ \rawprocesscommacommand[\m_spac_align_asked]\spac_align_collect
+ \fi
+ \normalexpanded{\t_spac_align_collected
+ {% \resetrealignsignal % can go as it is always set
+ \setfalse\raggedonelinerstate % bad
+ \the\t_spac_align_collected
+ \spac_align_flush_horizontal
+ \spac_align_flush_vertical
+ \spac_align_flush_direction
+ \spac_align_flush_page
+ \spac_align_flush_parfill
+ }}% 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}
+
+\def\spac_align_collect#1%
+ {\csname\??aligncommand#1\endcsname}
+
+% The local (key driven) setter:
+
+\unexpanded\def\spac_align_prepare#1% deferred
+ {\edef\m_spac_align_asked{#1}%
+ \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align_asked\endcsname
+ \fi}
+
+\let\dosetraggedcommand\spac_align_prepare % sort of public
+
+% The regular align setter:
+
+\unexpanded\def\setupalign
+ {\dosingleempty\spac_align_setup}
+
+\def\spac_align_setup[#1]% immediate
+ {\edef\m_spac_align_asked{#1}%
+ \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align_asked\endcsname
+ \fi
+ \raggedcommand}
+
+\unexpanded\def\usealignparameter#1% faster local variant
+ {\edef\m_spac_align_asked{#1\c!align}%
+ \ifx\m_spac_align_asked\empty\else
+ \spac_align_use_indeed
+ \fi}
+
+\unexpanded\def\dousealignparameter#1% faster local variant
+ {\edef\m_spac_align_asked{#1}%
+ \ifx\m_spac_align_asked\empty\else
+ \spac_align_use_indeed
+ \fi}
+
+\def\spac_align_use_indeed
+ {\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align_asked\endcsname
+ \fi
+ \raggedcommand}
+
+% experiment
+
+\unexpanded\def\spac_align_use_later#1%
+ {\begingroup
+ \edef\m_spac_align_asked{#1}%
+ \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache
+ \fi
+ \endgroup}
+
+\unexpanded\def\spac_align_use_now#1%
+ {\csname\??alignmentnormalcache#1\endcsname}
+
+% Maybe we need something different in columns.
+
+\unexpanded\def\installalign#1#2% beware: commands must be unexpandable!
+ {\ifcsname\??aligncommand#1\endcsname \else
+ \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}%
+ \fi}
+
+% beware, toks stuff and states are set at a differt time, so installalign is
+% only for special options
+%
+% \setvalue{\??aligncommand whatever}%
+% {\c_spac_align_state_horizontal\plushundred
+% \toksapp\t_spac_align_collected{.....}}
+%
+% this one could deal with both
+%
+% \unexpanded\def\installalignoption#1#2%
+% {\ifcsname\??aligncommand#1\endcsname \else
+% \setvalue{\??aligncommand#1}%
+% {\spac_align_set_horizontal_none
+% \c_spac_align_state_horizontal\plushundred % don't set
+% \toksapp\t_spac_align_collected{#2}}%
+% \fi}
+%
+% \installalignoption
+% {whatever}
+% {}
+
+% The keywords:
+
+\letvalue{\??aligncommand\empty }\empty
+\setvalue{\??aligncommand\v!broad }{\c_spac_align_state_broad \plusone }
+\setvalue{\??aligncommand\v!wide }{\c_spac_align_state_broad \plustwo }
+
+\setvalue{\??aligncommand\v!bottom }{\c_spac_align_state_page \plusone }
+\setvalue{\??aligncommand\v!height }{\c_spac_align_state_page \plustwo }
+\setvalue{\??aligncommand\v!line }{\c_spac_align_state_page \plusthree
+ % this will become another keyword (undocumented anyway)
+ \toksapp\t_spac_align_collected{\settrue\raggedonelinerstate}}
+
+\setvalue{\??aligncommand\v!high }{\c_spac_align_state_vertical \plusthree}
+\setvalue{\??aligncommand\v!low }{\c_spac_align_state_vertical \plustwo }
+\setvalue{\??aligncommand\v!lohi }{\c_spac_align_state_vertical \plusone }
+
+\setvalue{\??aligncommand\v!flushright }{\c_spac_align_state_horizontal\plusthree}
+\setvalue{\??aligncommand\v!flushleft }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!middle }{\c_spac_align_state_horizontal\plusone }
+\setvalue{\??aligncommand\v!no }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!yes }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!width }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!normal }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!reset }{\c_spac_align_state_page \zerocount
+ \c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!inner }{\c_spac_align_state_horizontal\plusfour }
+\setvalue{\??aligncommand\v!outer }{\c_spac_align_state_horizontal\plusfive }
+\setvalue{\??aligncommand\v!flushinner }{\c_spac_align_state_horizontal\plusfive }
+\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfour }
+\setvalue{\??aligncommand\v!right }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plusthree}
+\setvalue{\??aligncommand\v!center }{\c_spac_align_state_horizontal\plusone
+ \c_spac_align_state_broad \plustwo }
+\setvalue{\??aligncommand\v!disable }{\c_spac_align_state_horizontal\plussix }
+\setvalue{\??aligncommand\v!last }{\c_spac_align_state_horizontal\plusseven}
+\setvalue{\??aligncommand\v!paragraph }{\c_spac_align_state_horizontal\pluseight}
+
+
+\setvalue{\??aligncommand\v!lefttoright }{\c_spac_align_state_direction \plusone }
+\setvalue{\??aligncommand\v!righttoleft }{\c_spac_align_state_direction \plustwo }
+\setvalue{\??aligncommand l2r}{\c_spac_align_state_direction \plusone }
+\setvalue{\??aligncommand r2l}{\c_spac_align_state_direction \plustwo }
+
+\setvalue{\??aligncommand\v!table }{\c_spac_align_state_vertical \plusthree
+ \c_spac_align_state_broad \plusone
+ \c_spac_align_state_horizontal\plustwo }
+
+\setvalue{\??aligncommand\v!lesshyphenation}{\toksapp\t_spac_align_collected{\lesshyphens}}
+\setvalue{\??aligncommand\v!morehyphenation}{\toksapp\t_spac_align_collected{\morehyphens}}
+
+\setvalue{\??aligncommand\v!hanging }{\toksapp\t_spac_align_collected{\font_protruding_enable }}
+\setvalue{\??aligncommand\v!nothanging }{\toksapp\t_spac_align_collected{\font_protruding_disable}}
+\setvalue{\??aligncommand\v!hz }{\toksapp\t_spac_align_collected{\font_expansion_enable }}
+\setvalue{\??aligncommand\v!fullhz }{\toksapp\t_spac_align_collected{\font_expansion_enable_k}}
+\setvalue{\??aligncommand\v!nohz }{\toksapp\t_spac_align_collected{\font_expansion_disable }}
+%setvalue{\??aligncommand\v!spacing }{\toksapp\t_spac_align_collected{\normalspacing\zerocount}} % not yet
+%setvalue{\??aligncommand\v!nospacing }{\toksapp\t_spac_align_collected{\normalspacing\plusone}} % not yet
+\setvalue{\??aligncommand\v!hyphenated }{\toksapp\t_spac_align_collected{\dohyphens}}
+\setvalue{\??aligncommand\v!nothyphenated }{\toksapp\t_spac_align_collected{\nohyphens}}
+
+\setvalue{\??aligncommand\v!tolerant }{\toksapp\t_spac_align_collected{\spac_align_set_tolerant}}
+\setvalue{\??aligncommand\v!verytolerant }{\toksapp\t_spac_align_collected{\spac_align_set_very_tolerant}}
+\setvalue{\??aligncommand\v!stretch }{\toksapp\t_spac_align_collected{\spac_align_set_stretch}}
+\setvalue{\??aligncommand\v!extremestretch }{\toksapp\t_spac_align_collected{\spac_align_set_extreme_stretch}}
+
+\setvalue{\??aligncommand \v!final}{\c_spac_align_state_par_fill\plusone}
+\setvalue{\??aligncommand2*\v!final}{\c_spac_align_state_par_fill\plustwo} % hardcoded multiplier
+\setvalue{\??aligncommand3*\v!final}{\c_spac_align_state_par_fill\plusthree}
+\setvalue{\??aligncommand4*\v!final}{\c_spac_align_state_par_fill\plusfour}
+
+\definehspace [\v!final] [\emspaceamount]
+
+\def\spac_align_flush_parfill
+ {\ifcase\c_spac_align_state_par_fill\else
+ \spac_align_flush_parfill_indeed{\number\c_spac_align_state_par_fill}%
+ \fi}
+
+\unexpanded\def\spac_align_flush_parfill_indeed#1%
+ {\parfillskip
+ #1\directhspaceamount\v!final
+ % plus \dimexpr\availablehsize-#1\directhspaceamount\v!final\relax
+ plus 1fill
+ \relax}
+
+%D For Wolfgang:
+
+\newtoks \t_spac_every_swap_align
+
+\appendtoks
+ \setvalue{\??aligncommand\v!right}{\c_spac_align_state_horizontal\plusthree}%
+ \setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plustwo }%
+\to \t_spac_every_swap_align
+
+\unexpanded\def\enablereversealignment
+ {\the\t_spac_every_swap_align
+ \t_spac_every_swap_align\emptytoks}
+
+% Visible commands:
+
+\let\notragged \spac_align_set_horizontal_none
+\let\raggedleft \spac_align_set_horizontal_left
+\let\raggedcenter \spac_align_set_horizontal_center
+\let\raggedright \spac_align_set_horizontal_right
+\let\veryraggedleft \spac_align_set_horizontal_very_left
+\let\veryraggedcenter\spac_align_set_horizontal_very_center
+\let\veryraggedright \spac_align_set_horizontal_very_right
+\let\raggedwidecenter\spac_align_set_horizontal_wide_center
+\let\centeredlastline\spac_align_set_horizontal_centered_last_line
+\let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command
+
+\let\forgetragged \spac_align_set_horizontal_none
+
+\appendtoks
+ \spac_align_set_horizontal_none
+\to \everyforgetall
+
+% Box commands.
+
+\unexpanded\def\ibox
+ {\vbox\bgroup
+ \forgetall
+ \let\\=\endgraf
+ \ifdoublesided\signalinnerrealign\fi
+ \doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left
+ \let\next}
+
+\unexpanded\def\obox
+ {\vbox\bgroup
+ \forgetall
+ \let\\=\endgraf
+ \ifdoublesided\signalouterrealign\fi
+ \doifelserightpage\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right
+ \let\next}
+
+\let\raggedbox\relax
+
+\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used)
+ {\let\raggedbox\vbox
+ \processcommacommand[#1]\spac_align_set_ragged_vbox}
+
+\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used)
+ {\let\raggedbox\hbox
+ \processcommacommand[#1]\spac_align_set_ragged_hbox}
+
+\def\spac_align_set_ragged_vbox#1%
+ {\ifcsname\??alignvertical#1\endcsname
+ \lastnamedcs
+ \quitcommalist
+ \fi}
+
+\def\spac_align_set_ragged_hbox#1%
+ {\ifcsname\??alignhorizontal#1\endcsname
+ \lastnamedcs
+ \quitcommalist
+ \fi}
+
+% \def\usealignparametersethbox#1%
+% {\edef\p_spac_align{#1\c!align}%
+% \let\raggedbox\hbox
+% \ifx\p_spac_align\empty \else
+% \processcommacommand[\p_spac_align]\spac_align_set_ragged_hbox
+% \fi}
+%
+% \def\usealignparametersetvbox#1%
+% {\edef\p_spac_align{#1\c!align}%
+% \let\raggedbox\vbox
+% \ifx\p_spac_align\empty \else
+% \processcommacommand[\p_spac_align]\spac_align_set_ragged_vbox
+% \fi}
+
+\setvalue{\??alignvertical \v!left }{\let\raggedbox\lbox}
+\setvalue{\??alignvertical \v!right }{\let\raggedbox\rbox}
+\setvalue{\??alignvertical \v!middle }{\let\raggedbox\cbox}
+\setvalue{\??alignvertical \v!inner }{\let\raggedbox\ibox}
+\setvalue{\??alignvertical \v!outer }{\let\raggedbox\obox}
+\setvalue{\??alignvertical \v!flushleft }{\let\raggedbox\rbox}
+\setvalue{\??alignvertical \v!flushright}{\let\raggedbox\lbox}
+\setvalue{\??alignvertical \v!center }{\let\raggedbox\cbox}
+\setvalue{\??alignvertical \v!no }{\def\raggedbox{\vbox\bgroup\spac_align_set_horizontal_right\let\next=}]}
+
+% maybe \let's
+
+\setvalue{\??alignhorizontal\v!left }{\def\raggedbox{\doalignedline\v!left }}
+\setvalue{\??alignhorizontal\v!right }{\def\raggedbox{\doalignedline\v!right }}
+\setvalue{\??alignhorizontal\v!middle }{\def\raggedbox{\doalignedline\v!middle}}
+\setvalue{\??alignhorizontal\v!inner }{\def\raggedbox{\doalignedline\v!inner }}
+\setvalue{\??alignhorizontal\v!outer }{\def\raggedbox{\doalignedline\v!outer }}
+\setvalue{\??alignhorizontal\v!flushleft }{\def\raggedbox{\doalignedline\v!right }}
+\setvalue{\??alignhorizontal\v!flushright}{\def\raggedbox{\doalignedline\v!left }}
+\setvalue{\??alignhorizontal\v!center }{\def\raggedbox{\doalignedline\v!middle}}
+
+% The next one can be in use so we keep it around but oen should
+% be aware of possible interference.
+
+\unexpanded\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall)
+ {\unexpanded\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
+ \updateraggedskips}
+
+\def\dosetraggedskips#1#2#3#4#5#6#7%
+ {\raggedstatus #1\relax
+ \leftskip 1\leftskip \s!plus#2\relax
+ \rightskip 1\rightskip\s!plus#3\relax
+ \spaceskip #4\relax
+ \xspaceskip #5\relax
+ \parfillskip \zeropoint\s!plus#6\relax
+ \parindent #7\relax
+ \attribute\alignstateattribute\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi}
+
+% older (context) names:
+
+\let\spaceamount \interwordspace
+\let\emspaceamount\emwidth
+
+% tracing:
+
+\def\spac_show_par_data#1%
+ {\ifx#1\relax\else
+ \hbox{\string#1: \the#1}\endgraf
+ \expandafter\spac_show_par_data
+ \fi}
+
+\unexpanded\def\showpardata
+ {\edef\thepardata
+ {\hbox{font: \fontname\font}\endgraf
+ \spac_show_par_data
+ \interwordspace \interwordstretch \interwordshrink \emwidth \exheight \extraspace
+ \hsize \vsize
+ \leftskip \rightskip
+ \spaceskip \xspaceskip
+ \parindent \parfillskip
+ \hyphenpenalty \exhyphenpenalty
+ \displaywidowpenalty \widowpenalty \clubpenalty \brokenpenalty
+ \doublehyphendemerits \finalhyphendemerits \adjdemerits
+ \relax}%
+ \dontleavehmode
+ \begingroup
+ \inleftmargin{\vsmash{\infofont\framed[\c!align=\v!right]{\thepardata}}}%
+ \endgroup}
+
+\unexpanded\def\startshowpardata
+ {\begingroup
+ \showstruts
+ \tracingparagraphs\maxdimen
+ \appendtoksonce\showpardata\let\showpardata\relax\to\everypar}
+
+\unexpanded\def\stopshowpardata
+ {\endgraf
+ \endgroup}
+
+% Structure:
+
+\unexpanded\def\startalignment
+ {\par
+ \begingroup
+ \setupalign}
+
+\unexpanded\def\stopalignment
+ {\par
+ \endgroup}
+
+\setnewconstant\alignstrutmode\plusone
+
+% see later for the real definition, which in the simple case is:
+
+\newtoks \everyleftofalignedline
+\newtoks \everyrightofalignedline
+
+\unexpanded\def\shiftalignedline#1#2#3#4% left, right, inner, outer
+ {\rightorleftpageaction
+ {\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}%
+ \everyrightofalignedline{\hskip\dimexpr#2+#4\relax}}
+ {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}%
+ \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}}
+
+\def\doalignline#1#2% \\ == newline
+ {\noindentation % was \noindent
+ \dontleavehmode % added in marrakesch at TUG 2006\begingroup
+ \begingroup
+ \setlocalhsize % new
+ \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
+ \dowithnextbox
+ {\hbox to \localhsize
+ {\ifcase\alignstrutmode\or\strut\fi
+ \the\everyleftofalignedline
+ #1\unhbox\nextbox#2\relax
+ \the\everyrightofalignedline}%
+ \endgroup}
+ \hbox}
+
+% plain commands
+
+\ifdefined\line \else \def\line {\hbox to\hsize} \fi
+\ifdefined\leftline \else \def\leftline #1{\line{#1\hss}} \fi
+\ifdefined\rightline \else \def\rightline #1{\line{\hss#1}} \fi
+\ifdefined\centerline \else \def\centerline#1{\line{\hss#1\hss}} \fi
+
+% direct commands
+
+\installcorenamespace{alignwrapper}
+
+\setuvalue{\??alignwrapper\v!left }{\doalignline\relax \hss }
+\setuvalue{\??alignwrapper\v!middle}{\doalignline\hss \hss }
+\setuvalue{\??alignwrapper\v!right }{\doalignline\hss \relax}
+\setuvalue{\??alignwrapper\v!max }{\doalignline\relax \relax}
+
+\def\spac_align_wrapper_middle {\doalignline\hss \hss}
+
+\def\spac_align_wrapper_handle#1%
+ %{\csname\??alignwrapper\ifcsname\??alignwrapper#1\endcsname#1\else\v!middle\fi\endcsname}
+ {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi}
+
+\unexpanded\def\spac_align_wrapper_start[#1]%
+ {\spac_align_wrapper_handle{#1}%
+ \bgroup\ignorespaces}
+
+\unexpanded\def\spac_align_wrapper_stop
+ {\removeunwantedspaces\egroup}
+
+\unexpanded\def\startlinealignment
+ {\dosingleempty\spac_align_wrapper_start}
+
+\let\stoplinealignment\spac_align_wrapper_stop
+
+\unexpanded\def\startleftaligned {\spac_align_wrapper_start[\v!left ]} \let\stopleftaligned \spac_align_wrapper_stop
+\unexpanded\def\startmiddlealigned{\spac_align_wrapper_start[\v!middle]} \let\stopmiddlealigned\spac_align_wrapper_stop
+\unexpanded\def\startrightaligned {\spac_align_wrapper_start[\v!right ]} \let\stoprightaligned \spac_align_wrapper_stop
+\unexpanded\def\startmaxaligned {\spac_align_wrapper_start[\v!max ]} \let\stopmaxaligned \spac_align_wrapper_stop
+
+\let\startmidaligned \startmiddlealigned \let\stopmidaligned \stopmiddlealigned
+\let\startcenteraligned\startmiddlealigned \let\stopcenteraligned\stopmiddlealigned
+
+\unexpanded\def\leftaligned {\spac_align_wrapper_handle\v!left }
+\unexpanded\def\middlealigned{\spac_align_wrapper_handle\v!middle}
+\unexpanded\def\rightaligned {\spac_align_wrapper_handle\v!right }
+\unexpanded\def\maxaligned {\spac_align_wrapper_handle\v!max }
+
+\let\midaligned \middlealigned
+\let\centeraligned\middlealigned
+
+\installcorenamespace{alignline}
+
+\letvalue{\??alignline\v!left }\leftaligned
+\letvalue{\??alignline\v!right }\rightaligned
+\letvalue{\??alignline\v!middle }\midaligned
+\letvalue{\??alignline\v!flushleft }\rightaligned % beware, makes no sense in locations / we will have a special locations handler
+\letvalue{\??alignline\v!flushright}\leftaligned % beware, makes no sense in locations / we will have a special locations handler
+\letvalue{\??alignline\v!center }\midaligned
+\letvalue{\??alignline\v!max }\maxaligned
+
+\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname}
+
+%D Experimental (will be redone when floats are redone as it's real messy
+%D now). It can also be made faster (if needed).
+
+\def\doxalignline#1#2#3#4#5#6%
+ {\noindentation % was \noindent
+ \dontleavehmode % added in marrakesch at TUG 2006\begingroup
+ \begingroup
+ \setlocalhsize
+ \def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient
+ \dowithnextbox
+ {\hbox to \localhsize
+ {#1\hskip\ifdone#2\else#3\fi#4%
+ \hbox to \localhsize
+ {\the\everyleftofalignedline
+ \ifcase\alignstrutmode\or\strut\fi
+ \ifdone#5\unhbox\nextbox#6\else#6\unhbox\nextbox#5\fi
+ \the\everyrightofalignedline}%
+ \hss}%
+ \endgroup}
+ \hbox}
+
+\def\doxcheckline % used for floats so multipass anyway
+ {\signalrightpage\doifelserightpage\donetrue\donefalse}
+
+\setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss }
+\setvalue{\??alignline\v!outer }{\doxalignline\doxcheckline++\zeropoint \hss \relax}
+\setvalue{\??alignline\v!innermargin}{\doxalignline\doxcheckline-+\innermargintotal\relax\hss }
+\setvalue{\??alignline\v!outermargin}{\doxalignline\doxcheckline+-\outermargintotal\hss \relax}
+\setvalue{\??alignline\v!inneredge }{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss }
+\setvalue{\??alignline\v!outeredge }{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax}
+\setvalue{\??alignline\v!backspace }{\doxalignline\doxcheckline-+\backspace \relax\hss }
+\setvalue{\??alignline\v!cutspace }{\doxalignline\doxcheckline+-\cutspace \hss \relax}
+
+\setvalue{\??alignline\v!leftmargin }{\doxalignline\donefalse --\leftmargintotal \hss \relax}
+\setvalue{\??alignline\v!rightmargin}{\doxalignline\donefalse ++\rightmargintotal\relax\hss }
+\setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax}
+\setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
+
+\def\doalignedline#1% unchecked
+ {\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
+
+\def\alignedline#1#2% setting default
+ % {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname}
+ {\ifcsname\??alignline#1\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \csname\??alignline#2\expandafter\endcsname
+ \fi}
+
+% beware: \wordright{whatever\kern-\rightskip} should work!
+% so, no funny boxing here
+
+\unexpanded\def\wordright
+ {\dosingleempty\spac_word_right}
+
+\def\spac_word_right[#1]%
+ {% don't change
+ \groupedcommand
+ {\removeunwantedspaces
+ \hfill
+ \allowbreak % changed back from \hskip\zeropoint
+ \strut
+ \hfill
+ \quad % decent spacing
+ \hbox}
+ {\doifelse{#1}\v!right{\kern-\rightskip}{\doifsomething{#1}{\kern-#1}}%
+ \parfillskip\zeropoint
+ \finalhyphendemerits\zerocount % yes or no (see hyhenation/specialcases-001.tex)
+ \par}}
+
+% \dorecurse{5}{something} \wordright{--someone} \endgraf
+% \dorecurse{6}{something} \wordright{--someone} \endgraf
+% \dorecurse{7}{something} \wordright{--someone} \endgraf
+%
+% \dorecurse{5}{something} \wordright{--someone else entirely} \endgraf
+% \dorecurse{6}{something} \wordright{--someone else entirely} \endgraf
+% \dorecurse{7}{something} \wordright{--someone else entirely} \endgraf
+%
+% \wordright[\rightskip]{whatever}
+
+% Trick posted by WS on mailing list, generalized a bit. The bottom text only shows
+% op when there is one line space available. We could add some extra space if needed.
+
+% \unexpanded\def\bottomword
+% {\par
+% \dowithnextbox
+% {\leaders\box\nextbox\vfil\page}
+% \vbox to \lineheight}
+%
+% \unexpanded\def\bottomword
+% {\par
+% \groupedcommand
+% {\leaders
+% \vbox to \lineheight\bgroup}
+% {\egroup
+% \vfil
+% \page}}
+
+% \simplealignedbox{2cm}{right}{x}
+
+\installcorenamespace{alignsimple}
+\installcorenamespace{alignsimplereverse}
+
+% todo: also handle \bgroup ... \egroup
+
+\unexpanded\def\spac_align_simple_left #1{{#1\hss}}
+\unexpanded\def\spac_align_simple_right #1{{\hss#1}}
+\unexpanded\def\spac_align_simple_middle#1{{\hss#1\hss}}
+
+\letvalue{\??alignsimple \v!right }\spac_align_simple_left
+\letvalue{\??alignsimple \v!outer }\spac_align_simple_left % not managed! see linenumbers
+\letvalue{\??alignsimple \v!flushleft }\spac_align_simple_left
+\letvalue{\??alignsimple \v!left }\spac_align_simple_right
+\letvalue{\??alignsimple \v!inner }\spac_align_simple_right % not managed! see linenumbers
+\letvalue{\??alignsimple \v!flushright}\spac_align_simple_right
+\letvalue{\??alignsimple \v!middle }\spac_align_simple_middle
+
+\letvalue{\??alignsimplereverse\v!right }\spac_align_simple_right
+\letvalue{\??alignsimplereverse\v!outer }\spac_align_simple_right % not managed! see linenumbers
+\letvalue{\??alignsimplereverse\v!flushleft }\spac_align_simple_right
+\letvalue{\??alignsimplereverse\v!left }\spac_align_simple_left
+\letvalue{\??alignsimplereverse\v!inner }\spac_align_simple_left % not managed! see linenumbers
+\letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left
+\letvalue{\??alignsimplereverse\v!middle }\spac_align_simple_middle
+
+% \unexpanded\def\simplealignedbox#1#2%
+% {\hbox \ifdim#1>\zeropoint to #1
+% \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+% \fi}
+
+% \unexpanded\def\simplealignedboxplus#1#2#3%
+% {\hbox #3 \ifdim#1>\zeropoint to #1
+% \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+% \fi}
+
+% \unexpanded\def\simplealignedbox#1#2%
+% {\hbox \ifdim#1>\zeropoint to #1
+% \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+% \fi}
+%
+% \unexpanded\def\simplealignedboxplus#1#2#3%
+% {\hbox #3 \ifdim#1>\zeropoint to #1
+% \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+% \fi}
+
+\unexpanded\def\simplealignedbox#1#2%
+ {\hbox \ifdim#1>\zeropoint to #1
+ \ifcsname\??alignsimple#2\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\spac_align_simple_left
+ \fi
+ \fi}
+
+\unexpanded\def\simplealignedspreadbox#1#2%
+ {\hbox \ifdim#1>\zeropoint spread #1
+ \ifcsname\??alignsimple#2\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\spac_align_simple_left
+ \fi
+ \fi}
+
+\unexpanded\def\simplealignedboxplus#1#2#3%
+ {\hbox #3 \ifdim#1>\zeropoint to #1
+ \ifcsname\??alignsimple#2\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\spac_align_simple_left
+ \fi
+ \fi}
+
+\newconditional\alignsimplelefttoright \settrue\alignsimplelefttoright
+
+% \unexpanded\def\simplereversealignedbox#1#2%
+% {\hbox \ifdim#1>\zeropoint to #1
+% \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+% \fi}
+%
+% \unexpanded\def\simplereversealignedboxplus#1#2#3%
+% {\hbox #3 \ifdim#1>\zeropoint to #1
+% \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+% \fi}
+
+\unexpanded\def\simplereversealignedbox#1#2%
+ {\hbox \ifdim#1>\zeropoint to #1
+ \ifcsname\??alignsimplereverse#2\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\spac_align_simple_left
+ \fi
+ \fi}
+
+\unexpanded\def\simplereversealignedboxplus#1#2#3%
+ {\hbox #3 \ifdim#1>\zeropoint to #1
+ \ifcsname\??alignsimplereverse#2\endcsname
+ \doubleexpandafter\lastnamedcs
+ \else
+ \doubleexpandafter\spac_align_simple_left
+ \fi
+ \fi}
+
+% \installnamespace{alignsets}
+%
+% \setvalue{\??alignsets\v!right }#1#2{\let#1\relax\let#2\hss }
+% \setvalue{\??alignsets\v!left }#1#2{\let#1\hss \let#2\relax}
+% \setvalue{\??alignsets\v!flushright}#1#2{\let#1\hss \let#2\relax}
+% \setvalue{\??alignsets\v!flushleft }#1#2{\let#1\relax\let#2\hss }
+% \setvalue{\??alignsets\v!middle }#1#2{\let#1\hss \let#2\hss }
+% \setvalue{\??alignsets\v!low }#1#2{\let#1\vss \let#2\relax}
+% \setvalue{\??alignsets\v!high }#1#2{\let#1\relax\let#2\vss }
+% \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss }
+% \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax}
+%
+% \unexpanded\def\spac_align_set_ss#1%
+% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname}
+
+% Some obsolete (old) helpers:
+
+\def\dodefinehbox[#1][#2]%
+ {\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}}
+
+\unexpanded\def\definehbox
+ {\dodoubleargument\dodefinehbox}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua
new file mode 100644
index 00000000000..97b32c36613
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua
@@ -0,0 +1,313 @@
+if not modules then modules = { } end modules ['spac-chr'] = {
+ version = 1.001,
+ comment = "companion to spac-chr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte, lower = string.byte, string.lower
+
+-- beware: attribute copying is bugged ... there will be a proper luatex helper
+-- for this
+
+-- to be redone: characters will become tagged spaces instead as then we keep track of
+-- spaceskip etc
+
+-- todo: only setattr when export / use properties
+
+local next = next
+
+local trace_characters = false trackers.register("typesetters.characters", function(v) trace_characters = v end)
+local trace_nbsp = false trackers.register("typesetters.nbsp", function(v) trace_nbsp = v end)
+
+local report_characters = logs.reporter("typesetting","characters")
+
+local nodes, node = nodes, node
+
+local nuts = nodes.nuts
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local setsubtype = nuts.setsubtype
+local isglyph = nuts.isglyph
+
+local setcolor = nodes.tracers.colors.set
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+local copy_node_list = nuts.copy_list
+local traverse_id = nuts.traverse_id
+
+local tasks = nodes.tasks
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_rule = nodepool.rule
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+
+local space_skip_code = skipcodes["spaceskip"]
+
+local chardata = characters.data
+local is_punctuation = characters.is_punctuation
+
+local typesetters = typesetters
+
+local unicodeblocks = characters.blocks
+
+local characters = typesetters.characters or { } -- can be predefined
+typesetters.characters = characters
+
+local fonthashes = fonts.hashes
+local fontparameters = fonthashes.parameters
+local fontcharacters = fonthashes.characters
+local fontquads = fonthashes.quads
+
+local setmetatableindex = table.setmetatableindex
+
+local a_character = attributes.private("characters")
+local a_alignstate = attributes.private("alignstate")
+
+local c_zero = byte('0')
+local c_period = byte('.')
+
+local function inject_quad_space(unicode,head,current,fraction)
+ local attr = getfield(current,"attr")
+ if fraction ~= 0 then
+ fraction = fraction * fontquads[getfont(current)]
+ end
+ local glue = new_glue(fraction)
+ setfield(glue,"attr",attr)
+ setfield(current,"attr",nil)
+ setattr(glue,a_character,unicode)
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+end
+
+local function inject_char_space(unicode,head,current,parent)
+ local attr = getfield(current,"attr")
+ local font = getfont(current)
+ local char = fontcharacters[font][parent]
+ local glue = new_glue(char and char.width or fontparameters[font].space)
+ setfield(glue,"attr",attr)
+ setfield(current,"attr",nil)
+ setattr(glue,a_character,unicode)
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+end
+
+local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink)
+ local attr = getfield(current,"attr")
+ local glue = new_glue(space,spacestretch,spaceshrink)
+ local penalty = new_penalty(10000)
+ setfield(glue,"attr",attr)
+ setfield(current,"attr",nil)
+ setattr(glue,a_character,unicode) -- bombs
+ head, current = insert_node_after(head,current,penalty)
+ if trace_nbsp then
+ local rule = new_rule(space)
+ local kern = new_kern(-space)
+ local penalty = new_penalty(10000)
+ setcolor(rule,"orange")
+ head, current = insert_node_after(head,current,rule)
+ head, current = insert_node_after(head,current,kern)
+ head, current = insert_node_after(head,current,penalty)
+ end
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+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)
+ else
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink)
+ end
+ return head, current
+end
+
+-- assumes nuts or nodes, depending on callers .. so no tonuts here
+
+function characters.replacenbsp(head,original)
+ local head, current = nbsp(head,original)
+ head = remove_node(head,original,true)
+ return head, current
+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
+
+-- 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)
+ for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end
+ for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end
+ setmetatableindex(nbsphash,nil)
+ return nbsphash[k]
+end)
+
+local methods = {
+
+ -- The next one uses an attribute assigned to the character but still we
+ -- don't have the 'local' value.
+
+ [0x001F] = function(head,current)
+ local next = getnext(current)
+ if next then
+ local char = isglyph(next)
+ if char then
+ head, current = remove_node(head,current,true)
+ if not is_punctuation[char] then
+ local p = fontparameters[getfont(next)]
+ head, current = insert_node_before(head,current,new_glue(p.space,p.space_stretch,p.space_shrink))
+ end
+ end
+ end
+ end,
+
+ [0x00A0] = function(head,current) -- nbsp
+ local next = getnext(current)
+ if next then
+ local char = isglyph(current)
+ if not char then
+ -- move on
+ elseif char == 0x200C or char == 0x200D then -- nzwj zwj
+ next = getnext(next)
+ if next then
+ char = isglyph(next)
+ if char and nbsphash[char] then
+ return false
+ end
+ end
+ elseif nbsphash[char] then
+ return false
+ end
+ end
+ local prev = getprev(current)
+ if prev then
+ local char = isglyph(prev)
+ if char and nbsphash[char] then
+ return false
+ end
+ end
+ return nbsp(head,current)
+ end,
+
+ [0x2000] = function(head,current) -- enquad
+ return inject_quad_space(0x2000,head,current,1/2)
+ end,
+
+ [0x2001] = function(head,current) -- emquad
+ return inject_quad_space(0x2001,head,current,1)
+ end,
+
+ [0x2002] = function(head,current) -- enspace
+ return inject_quad_space(0x2002,head,current,1/2)
+ end,
+
+ [0x2003] = function(head,current) -- emspace
+ return inject_quad_space(0x2003,head,current,1)
+ end,
+
+ [0x2004] = function(head,current) -- threeperemspace
+ return inject_quad_space(0x2004,head,current,1/3)
+ end,
+
+ [0x2005] = function(head,current) -- fourperemspace
+ return inject_quad_space(0x2005,head,current,1/4)
+ end,
+
+ [0x2006] = function(head,current) -- sixperemspace
+ return inject_quad_space(0x2006,head,current,1/6)
+ end,
+
+ [0x2007] = function(head,current) -- figurespace
+ return inject_char_space(0x2007,head,current,c_zero)
+ end,
+
+ [0x2008] = function(head,current) -- punctuationspace
+ return inject_char_space(0x2008,head,current,c_period)
+ end,
+
+ [0x2009] = function(head,current) -- breakablethinspace
+ return inject_quad_space(0x2009,head,current,1/8) -- same as next
+ end,
+
+ [0x200A] = function(head,current) -- hairspace
+ return inject_quad_space(0x200A,head,current,1/8) -- same as previous (todo)
+ end,
+
+ [0x200B] = function(head,current) -- zerowidthspace
+ return inject_quad_space(0x200B,head,current,0)
+ end,
+
+ [0x202F] = function(head,current) -- narrownobreakspace
+ return inject_nobreak_space(0x202F,head,current,fontquads[getfont(current)]/8)
+ end,
+
+ [0x205F] = function(head,current) -- math thinspace
+ return inject_nobreak_space(0x205F,head,current,fontparameters[getfont(current)].space/8)
+ end,
+
+ -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace
+ -- return head, current
+ -- end,
+
+}
+
+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
+ local next = getnext(current)
+ local method = methods[char]
+ if method then
+ if trace_characters then
+ report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
+ end
+ local h = method(head,current)
+ if h then
+ head = remove_node(h,current,true)
+ end
+ done = true
+ end
+ current = next
+ else
+ current = getnext(current)
+ end
+ end
+ return tonode(head), done
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv
new file mode 100644
index 00000000000..562fb940ce1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv
@@ -0,0 +1,95 @@
+%D \module
+%D [ file=spac-chr,
+%D version=2011.05.24, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Characters,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Characters}
+
+\unprotect
+
+\registerctxluafile{spac-chr}{1.001}
+
+\definesystemattribute[characters][public]
+
+%D The nobreakspace is special as it needs to keep track of the space being
+%D flexible. Another option is to use space (glue) nodes and tag them as characters
+%D instead. No big deal but takes a moment of coding. So, as a prelude we
+%D tag the nobreakspace only. Interesting is that it also fits better in the
+%D tagging mechanism.
+%D
+%D But we need to do some checking as from then on we no longer can compare
+%D them in a string. So this needs thinking. Not that we can compare the
+%D nobreakspace now anyway.
+
+% \unexpanded\def\specialspacecharacter#1{\begingroup\attribute\charactersattribute#1\ \endgroup}
+%
+% \unexpanded\edef\nobreakspace {\specialspacecharacter{"00A0}} % 1 = left
+% \unexpanded\edef\ideographicspace {\specialspacecharacter{"2000}}
+% \unexpanded\edef\ideographichalffillspace{\specialspacecharacter{"2001}}
+% \unexpanded\edef\twoperemspace {\specialspacecharacter{"2002}}
+% \unexpanded\edef\threeperemspace {\specialspacecharacter{"2004}}
+% \unexpanded\edef\fourperemspace {\specialspacecharacter{"2005}}
+% \unexpanded\edef\sixperemspace {\specialspacecharacter{"2006}}
+% \unexpanded\edef\figurespace {\specialspacecharacter{"2007}}
+% \unexpanded\edef\punctuationspace {\specialspacecharacter{"2008}}
+% \unexpanded\edef\breakablethinspace {\specialspacecharacter{"2009}}
+% \unexpanded\edef\hairspace {\specialspacecharacter{"200A}}
+% \unexpanded\edef\zerowidthspace {\specialspacecharacter{"200B}}
+% \unexpanded\edef\zwnj {\specialspacecharacter{"200C}}
+% \unexpanded\edef\zwj {\specialspacecharacter{"200D}}
+% \unexpanded\edef\narrownobreakspace {\specialspacecharacter{"202F}}
+
+% This does not work as spaceskip is only inserted in the case of raggedleft
+% and we need to be able to figure out all of them. Which makes me wonder ...
+% can't we just always set spaceskip to some value?
+
+% Making them active is also not an option unless we do that in every
+% catcode vector.
+
+% \nobreakspace {\begingroup\setalignstateattribute\normalUchar"00A0\endgroup} % 1 = left
+\edef\nobreakspace {\normalUchar"00A0} % space
+\edef\ideographicspace {\normalUchar"2000} % quad/2
+\edef\ideographichalffillspace{\normalUchar"2001} % quad
+\edef\twoperemspace {\normalUchar"2002} % quad/2
+% % "2003 % quad == \quad == \hskip\emwidth
+\edef\threeperemspace {\normalUchar"2004} % quad/3
+\edef\fourperemspace {\normalUchar"2005} % quad/4
+\edef\sixperemspace {\normalUchar"2006} % quad/6
+\edef\figurespace {\normalUchar"2007} % width of zero
+\edef\punctuationspace {\normalUchar"2008} % width of period
+\edef\breakablethinspace {\normalUchar"2009} % quad/8
+\edef\hairspace {\normalUchar"200A} % quad/8
+\edef\zerowidthspace {\normalUchar"200B} % 0
+\edef\zerowidthnonjoiner {\normalUchar"200C} % 0
+\edef\zerowidthjoiner {\normalUchar"200D} % 0
+\edef\narrownobreakspace {\normalUchar"202F} % quad/8
+% % "205F % space/8 (math)
+% \zerowidthnobreakspace {\normalUchar"FEFF}
+\udef\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint}
+
+\let\zwnj\zerowidthnonjoiner
+\let\zwj \zerowidthjoiner
+\let\nbsp\nobreakspace
+
+\chardef\optionalspace"1F % will be space unless before punctuation
+
+% Shortcuts:
+
+% unexpanded as otherwise we need to intercept / cleanup a lot
+
+\unexpanded\def~{\nobreakspace}
+
+% Goodies:
+
+\unexpanded\def\fiveperemspace{\hskip\dimexpr\emwidth/5\relax}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-def.mkiv
new file mode 100644
index 00000000000..7ead3c63e21
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-def.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=spac-def,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Definitions}
+
+% Ideally these definitions should be moved to where they first appear and
+% this will happen at some point.
+
+\unprotect
+
+% maybe \everysynchronizeglobalspacing
+% maybe \everysynchronizelocalspacing
+
+\appendtoks
+ \forgetverticalstretch
+ \presetnormallineheight
+ \setnormalbaselines % check if redundant (\forgetverticalstretch does it too)
+ \setstrut % check if redundant (\forgetverticalstretch does it too)
+ \settopskip % factors set in \forgetverticalstretch
+ \setmaxdepth % factors set in \forgetverticalstretch
+ \synchronizeindenting
+ \synchronizeblank
+ \synchronizewhitespace
+ \synchronizespacecodes % not needed, frozen factors
+ \setrelativeinterlinespace
+\to \everybodyfont
+
+% why exception
+
+\appendtoks
+ \updateraggedskips % under test
+\to \everyfontswitch
+
+% maybe more
+
+\prependtoks
+ \let\par\normalpar
+\to \everybeforepagebody % see \fillinline (was endgraf)
+
+% needs checking:
+
+\appendtoks
+ \synchronizespacecodes
+\to \everydefinedfont % not needed, frozen factors
+
+\setupinterlinespace
+ [\c!minheight=\zeropoint, % only special purpose
+ \c!mindepth=\zeropoint, % only special purpose
+ \c!height=.72,
+ \c!depth=.28,
+ \c!top=1.0,
+ \c!bottom=0.4,
+ \c!distance=\onepoint, % \dimexpr\openlineheight/10\relax
+ \c!line=2.8\exheight,
+ \c!stretch=\zerocount,
+ \c!shrink=\zerocount]
+
+\setupblank
+ [\v!big]
+
+\setuptolerance
+ [\v!horizontal,\v!verystrict]
+
+\setuptolerance
+ [\v!vertical,\v!strict]
+
+\setupalign
+ [\v!bottom,
+ \v!width]
+
+\setupspacing
+ [\v!packed]
+
+\indenting
+ [\v!never]
+
+\setupindenting
+ [\v!none]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv
new file mode 100644
index 00000000000..29351a3dd46
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv
@@ -0,0 +1,154 @@
+%D \module
+%D [ file=spac-fil,
+%D version=2013.01.13,
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Fillers,
+%D author={Hans Hagen and 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 Spacing Macros / Fillers}
+
+\unprotect
+
+%D A bit more extensive variant of a prototype posted by Wolfgang to the
+%D development list. Instead of dealing with a few leader types it makes
+%D sense to support them all as well as simple rule fillers. Eventually we
+%D can also use in for the mathfillers. We distinguish between alternatives
+%D and with them methods, and a checker is provided for use in applying
+%D e.g.\ fillers in lists.
+
+\installcorenamespace{filler}
+\installcorenamespace{filleralternative}
+\installcorenamespace{fillerleadermethod}
+
+\installcommandhandler \??filler {filler} \??filler
+
+\let\setupfillers\setupfiller
+
+\unexpanded\def\filler
+ {\dosingleempty\spac_fillers_indeed}
+
+\unexpanded\def\checkedfiller#1%
+ {\ifcsname\namedfillerhash{#1}\s!parent\endcsname
+ \spac_fillers_indeed[#1]%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi{#1}}
+
+\def\spac_fillers_indeed[#1]%
+ {\removeunwantedspaces
+ \begingroup
+ \edef\currentfiller{#1}%
+ \usefillerstyleandcolor\c!style\c!color
+ \scratchdimen\fillerparameter\c!leftmargin\relax
+ \ifdim\scratchdimen=\zeropoint\else
+ \hskip\scratchdimen
+ \fi
+ \fillerparameter\c!left\relax
+ \expandnamespaceparameter\??filleralternative\fillerparameter\c!alternative\s!unknown\relax
+ \fillerparameter\c!right\relax
+ \scratchdimen\fillerparameter\c!rightmargin\relax
+ \ifdim\scratchdimen=\zeropoint\else
+ \hskip\scratchdimen
+ \fi
+ \endgroup
+ \ignorespaces}
+
+\setvalue{\??filleralternative\s!unknown}%
+ {}
+
+\setvalue{\??filleralternative\v!symbol}%
+ {\expandnamespaceparameter\??fillerleadermethod\fillerparameter\c!method\v!local
+ \ifdim\fillerparameter\c!offset>\zeropoint
+ \simplealignedspreadbox
+ {2\dimexpr\fillerparameter\c!offset\relax}%
+ {\fillerparameter\c!align}%
+ {\fillerparameter\c!symbol}%
+ \else
+ \simplealignedbox
+ {\fillerparameter\c!width}%
+ {\fillerparameter\c!align}%
+ {\fillerparameter\c!symbol}%
+ \fi
+ \hfill}
+
+\setvalue{\??filleralternative\v!stretch}%
+ {\hfill}
+
+\setvalue{\??filleralternative\v!space}%
+ {\hskip\fillerparameter\c!distance\relax}
+
+\setvalue{\??filleralternative\v!rule}%
+ {\expandnamespaceparameter\??fillerleadermethod\fillerparameter\c!method\v!local
+ \hrule
+ \!!height\fillerparameter\c!height
+ \!!depth \fillerparameter\c!depth
+ \hfill}
+
+\letvalue{\??fillerleadermethod\s!local }\normalleaders % overflow ends up inbetween (current box)
+\letvalue{\??fillerleadermethod\v!global}\normalgleaders % overflow ends up inbetween (outermost box)
+\letvalue{\??fillerleadermethod\v!middle}\normalcleaders % overflow ends up before, after (current box)
+\letvalue{\??fillerleadermethod\v!broad }\normalxleaders % overflow ends up before, inbetween, after (current box)
+
+\setupfillers
+ [\c!width=\emwidth,
+ \c!symbol=.,
+ \c!distance=\emwidth,
+ \c!offset=\zeropoint,
+ \c!align=\v!middle,
+ \c!height=.1\exheight,
+ \c!depth=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!alternative=\v!symbol,
+ \c!method=\s!local]
+
+\definefiller
+ [\v!sym]
+ [\c!method=\v!global,
+ \c!width=.5\emwidth,
+ \c!leftmargin=.5\emwidth,
+ \c!rightmargin=.5\emwidth]
+
+\definefiller
+ [\v!symbol]
+ [\c!method=\v!global,
+ \c!offset=.125\emwidth,
+ \c!leftmargin=.5\emwidth,
+ \c!rightmargin=.5\emwidth]
+
+\definefiller
+ [\v!rule]
+ [\c!alternative=\v!rule,
+ \c!leftmargin=.5\emwidth,
+ \c!rightmargin=.5\emwidth]
+
+\definefiller
+ [\v!width]
+ [\c!alternative=\v!stretch]
+
+\definefiller
+ [\v!space]
+ [\c!alternative=\v!space,
+ \c!distance=3\emwidth]
+
+% maybe box -> symbol
+
+\protect \endinput
+
+% \definefiller[test-a][alternative=stretch]
+% \definefiller[test-b][alternative=symbol,symbol=!]
+% \definefiller[test-c][alternative=rule,height=.1ex,leftmargin=.5em,rightmargin=.25em]
+
+% \starttext
+% text\filler[test-a]text \par
+% text\filler[test-b]text \par
+% text\filler[test-c]text \par
+% text\checkedfiller{<nothing>}text \par
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv
new file mode 100644
index 00000000000..7b3ee6d6ce2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv
@@ -0,0 +1,303 @@
+%D \module
+%D [ file=spac-grd,
+%D version=2009.10.16, % 1998.03.10, was core-grd.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Grid Snapping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module will be merged into spac-ver.mkiv.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Grid Snapping}
+
+\unprotect
+
+%D A rather crappy macro that we need to avoid and as such it will probably
+%D disappear:
+
+\installcorenamespace{lastnodepusher}
+
+\let\poplastnode\relax
+
+\unexpanded\def\pushlastnode
+ {\csname\??lastnodepusher
+ \ifcsname\??lastnodepusher\the\lastnodetype\endcsname
+ \the\lastnodetype
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\setvalue{\??lastnodepusher\number\kernnodecode}%
+ {\unexpanded\edef\poplastnode{\kern\the\lastkern\relax}%
+ \kern-\lastkern}
+
+\setvalue{\??lastnodepusher\number\gluenodecode}%
+ {\unexpanded\edef\poplastnode{\vskip\the\lastskip\relax}%
+ \vskip-\lastskip}
+
+\setvalue{\??lastnodepusher\number\penaltynodecode}%
+ {\unexpanded\edef\poplastnode{\penalty\the\lastpenalty\relax}%
+ \nobreak}
+
+\setvalue{\??lastnodepusher\s!unknown}%
+ {\let\poplastnode\relax}
+
+%D Moved from supp-box:
+
+%D \macros
+%D {startbaselinecorrection,baselinecorrection,
+%D showbaselinecorrection,offbaselinecorrection}
+%D
+%D Spacing around ruled boxes can get pretty messed up. The
+%D next macro tries as good as possible to fix this.
+%D
+%D \startbuffer[1]
+%D \startbaselinecorrection
+%D \ruledhbox{Rule Brittanica}
+%D \stopbaselinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer[1]
+%D
+%D The macros put some white space around the box:
+%D
+%D \getbuffer[1]
+%D
+%D A simple alternative is \type {\baselinecorrection}, which
+%D only looks at the previous line.
+%D
+%D \startbuffer[2]
+%D \baselinecorrection
+%D \ruledhbox{Rule Brittanica}
+%D \baselinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer[2]
+%D
+%D This time the last preceding line gets a correction,%
+%D dependant on the depth.
+%D
+%D \getbuffer[2]
+%D
+%D One can make the correction visible by saying \type
+%D {\showbaselinecorrection}. Part of the correction is
+%D calculated from the dimensions of a~(. One can disble the
+%D correction by calling \type {\offbaselinecorrection}.
+%D
+%D When visualize the first example looks like:
+%D
+%D {\showbaselinecorrection\getbuffer[1]}
+%D
+%D and the second one comes out as:
+%D
+%D {\showbaselinecorrection\getbuffer[2]}
+
+% \definecolor[GridLineColor][red]
+% \definecolor[GridTextColor][blue]
+
+\newdimen\d_spac_lines_correction_before
+\newdimen\d_spac_lines_correction_after
+
+\newbox \b_spac_lines_correction_before
+\newbox \b_spac_lines_correction_after
+
+\def\spac_lines_initialize_corrections
+ {\setbox\b_spac_lines_correction_before\hbox{\setstrut\strut}%
+ \setbox\b_spac_lines_correction_after \hbox{(}%
+ \d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax
+ \d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax
+ \ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi
+ \ifdim\d_spac_lines_correction_after <\zeropoint\d_spac_lines_correction_after \zeropoint\fi}
+
+%unexpanded\def\dotopbaselinecorrection{\kern\d_spac_lines_correction_before}
+%unexpanded\def\dobotbaselinecorrection{\kern\d_spac_lines_correction_after }
+
+% experiment, todo: proper mkiv mechanism
+%
+% \input ward \par
+% \startframedtext test \stopframedtext
+% \input ward \par
+% \startlinecorrection \framed{xxx} \stoplinecorrection
+% \input ward \par
+%
+% \setupwhitespace[big]
+%
+% \input ward \par
+% \startframedtext test \stopframedtext
+% \input ward \par
+% \startlinecorrection \framed{xxx} \stoplinecorrection
+% \input ward \par
+
+% to be redone:
+
+\unexpanded\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]}
+\unexpanded\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]}
+
+\def\showbaselinecorrection
+ {\def\dobaselinecorrection % visualization is not watertight!
+ {\bgroup
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox\hsize
+ \dp\scratchbox\strutdp
+ \nointerlineskip
+ \forgetall
+ \ruledvbox{\box\scratchbox}%
+ \egroup
+ \prevdepth\strutdp}%
+ \def\dotopbaselinecorrection
+ {\hrule\s!height\d_spac_lines_correction_before}%
+ \def\dobotbaselinecorrection
+ {\hrule\s!height\d_spac_lines_correction_after}}
+
+\def\dobaselinecorrection % beware, this one is redefined / used locally elsewhere
+ {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi
+ \kern\strutdp
+ \prevdepth\strutdp}
+
+\def\baselinecorrection
+ {\endgraf
+ \ifvmode
+ \ifdim\prevdepth<\maxdimen
+ \ifdim\prevdepth<\zeropoint \else
+ \ifdim\prevdepth<\strutdepth \relax
+ \pushlastnode
+ \dobaselinecorrection
+ \poplastnode
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def\pagebaselinecorrection
+ {\ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal>\lineheight % or \topskip
+ \scratchdimen\pagetotal
+ \advance\scratchdimen\lineheight
+ \ifdim\scratchdimen<\pagegoal
+ \baselinecorrection
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\startbaselinecorrection
+ {\bgroup
+ \let\stopbaselinecorrection\egroup
+ \ifcase\baselinecorrectionmode
+ \or % normal
+ \baselinecorrection
+ \ifvmode
+ \setbox\scratchbox\vbox\bgroup\ignorespaces
+ \let\stopbaselinecorrection\donormalstopbaselinecorrection
+ \fi
+ \or % off
+ \or % force
+ \baselinecorrection
+ \ifvmode
+ \setbox\scratchbox\vbox\bgroup\ignorespaces
+ \let\stopbaselinecorrection\doforcedstopbaselinecorrection
+ \fi
+ \fi}
+
+\let\stopbaselinecorrection\relax
+
+\def\donormalstopbaselinecorrection % I have to check columns yet.
+ {\egroup
+ \topbaselinecorrection
+ \box\scratchbox
+ \botbaselinecorrection
+ \egroup}
+
+\def\doforcedstopbaselinecorrection % I have to check columns yet.
+ {\egroup
+ \forcedtopbaselinecorrection
+ \box\scratchbox
+ \forcedbotbaselinecorrection
+ \egroup}
+
+%D We do a bit more checking than needed. The pageborder check
+%D is not needed, but I want to look the visualization as good
+%D as possible too.
+
+\setnewconstant\baselinecorrectionmode\plusone
+
+\def\onbaselinecorrection {\baselinecorrectionmode\plusone }
+\def\offbaselinecorrection {\baselinecorrectionmode\plustwo }
+\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree}
+
+%D \macros
+%D {topbaselinecorrection,botbaselinecorrection}
+%D
+%D The actual top and bottom corrections are implemented as:
+
+\def\topbaselinecorrection
+ {\ifvmode \ifdim\pagegoal<\maxdimen
+ \forcedtopbaselinecorrection
+ \fi \fi}
+
+\def\forcedtopbaselinecorrection
+ {\ifvmode
+ \bgroup
+ \spac_lines_initialize_corrections
+ \whitespace % no longer ok
+ \nointerlineskip
+ \dotopbaselinecorrection
+ \egroup
+ \fi}
+
+\def\botbaselinecorrection
+ {\ifvmode
+ \bgroup
+ \spac_lines_initialize_corrections
+ \dobotbaselinecorrection
+ \allowbreak % new, otherwise problems when many in a row
+ \prevdepth\strutdp
+ \egroup
+ \fi}
+
+\let\forcedbotbaselinecorrection\botbaselinecorrection
+
+% nointerlineskip
+%
+% startpacked
+% \startlinecorrection \framed{test} \stoplinecorrection
+% \startlinecorrection \framed{test} \stoplinecorrection
+% \stoppacked
+
+\def\forcedtopbaselinecorrection
+ {\ifvmode
+ \bgroup
+ \spac_lines_initialize_corrections
+ \vspacing[\v!white]
+% \nointerlineskip %
+ \dotopbaselinecorrection
+ \egroup
+\fi}
+
+\def\dobaselinecorrection
+ {\ifdim\prevdepth>\zeropoint
+ \vspacing[\the\dimexpr-\prevdepth+\strutdp\relax]%
+ \else
+ \vspacing[\the\dimexpr\strutdp\relax]%
+ \fi
+ \prevdepth\strutdp}
+
+\let\normalstartbaselinecorrection\startbaselinecorrection
+
+\unexpanded\def\startbaselinecorrection
+ {\ifgridsnapping
+ \snaptogrid[\v!normal]\vbox\bgroup
+ \let\stopbaselinecorrection\egroup
+ \else
+ \normalstartbaselinecorrection
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-hor.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.lua
new file mode 100644
index 00000000000..5d5a43e311c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.lua
@@ -0,0 +1,44 @@
+if not modules then modules = { } end modules ['spac-hor'] = {
+ version = 1.001,
+ comment = "companion to spac-hor.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfbyte = utf.byte
+local lpegmatch, P, C = lpeg.match, lpeg.P, lpeg.C
+
+local context = context
+
+local chardata = characters.data
+
+local p_check = P("the ") * (P("letter") + P("character")) * P(" ") * lpeg.patterns.utf8byte -- is a capture already
+
+local can_have_space = table.tohash {
+ "lu", "ll", "lt", "lm", "lo", -- letters
+ -- "mn", "mc", "me", -- marks
+ "nd", "nl", "no", -- numbers
+ "ps", "pi", -- initial
+ -- "pe", "pf", -- final
+ -- "pc", "pd", "po", -- punctuation
+ "sm", "sc", "sk", "so", -- symbols
+ -- "zs", "zl", "zp", -- separators
+ -- "cc", "cf", "cs", "co", "cn", -- others
+}
+
+local function autonextspace(str) -- todo: make a real not intrusive lookahead
+ local b = lpegmatch(p_check,str)
+ if b then
+ local d = chardata[b]
+ if d and can_have_space[d.category] then
+ context.space()
+ end
+ end
+end
+
+interfaces.implement {
+ name = "autonextspace",
+ actions = autonextspace,
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv
new file mode 100644
index 00000000000..7c5358c5135
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv
@@ -0,0 +1,1207 @@
+%D \module
+%D [ file=spac-hor,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Horizontal,
+%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 / Horizontal}
+
+\unprotect
+
+\registerctxluafile{spac-hor}{1.001}
+
+\let\v_spac_indentation_current\empty % amount/keyword
+
+\newdimen \d_spac_indentation_par
+\parindent\d_spac_indentation_par % for the show
+
+\newconditional\c_spac_indentation_indent_first \settrue\c_spac_indentation_indent_first
+\newconstant \c_spac_indentation_toggle_state
+
+%D After a blank or comparable situation (left side floats) we
+%D need to check if the next paragraph has to be indented.
+
+\unexpanded\def\presetindentation
+ {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}}
+
+\unexpanded\def\setupindenting
+ {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size}
+
+\unexpanded\def\spac_indentation_setup_size
+ {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}}
+
+\let\synchronizeindenting\spac_indentation_setup_size
+
+\let\m_spac_indentation_options\empty
+
+\def\spac_indentation_setup_options[#1]%
+ {\edef\m_spac_indentation_options{#1}% comma separated list
+ \ifx\m_spac_indentation_options\empty \else
+ \spac_indentation_setup_indeed
+ \fi}
+
+\def\spac_indentation_setup_indeed
+ {% not here: \settrue\c_spac_indentation_indent_first
+ % not here: \parindent\d_spac_indentation_par
+ % not here: \c_spac_indentation_toggle_state\zerocount
+ \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_one % catch small, medium, etc
+ \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_two % catch rest
+ \ifzeropt\parindent\else
+ \doifemptytoks\everypar\spac_indentation_set_everypar
+ \fi
+ \ifconditional\c_spac_indentation_indent_first\else
+ \spac_indentation_variant_no
+ \fi
+ \spac_indentation_check_toggle}
+
+\def\spac_indentation_set_everypar
+ {\everypar{\checkindentation}}
+
+\unexpanded\def\useindentingparameter#1% faster local variant
+ {\edef\m_spac_indentation_options{#1\c!indenting}%
+ \ifx\m_spac_indentation_options\empty \else
+ \spac_indentation_setup_indeed
+ \fi}
+
+% \def\spac_indentation_apply_step_one#1%
+% {\ifcsname\??indentingmethod#1\endcsname
+% % case two
+% \else
+% \edef\v_spac_indentation_current{#1}% single entry in list
+% \let\normalindentation\v_spac_indentation_current
+% \spac_indentation_setup_size
+% \fi}
+%
+% \def\spac_indentation_apply_step_two#1%
+% {\ifcsname\??indentingmethod#1\endcsname
+% \csname\??indentingmethod#1\endcsname
+% \else
+% % case one
+% \fi}
+
+% \defineindenting[whatever][yes,2cm]
+% %defineindenting[whatever][yes,-2cm]
+%
+% \setupindenting[yes,-2em] \input ward \par
+% \setupindenting[yes,2em] \input ward \par
+% \setupindenting[whatever] \input ward \par
+
+\installcorenamespace {indentingpreset}
+
+\unexpanded\def\defineindenting
+ {\dodoubleargument\spac_indenting_define}
+
+\def\spac_indenting_define[#1][#2]% todo: mixes
+ {\setevalue{\??indentingpreset#1}{#2}}
+
+% \def\spac_indentation_apply_step_one_nested#1%
+% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one}
+%
+% \def\spac_indentation_apply_step_two_nested#1%
+% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two}
+%
+% \def\spac_indentation_apply_step_one#1%
+% {\ifcsname\??indentingpreset#1\endcsname
+% \spac_indentation_apply_step_one_nested{#1}%
+% \else\ifcsname\??indentingmethod#1\endcsname
+% % case two
+% \else
+% \edef\v_spac_indentation_current{#1}% single entry in list
+% \let\normalindentation\v_spac_indentation_current
+% \spac_indentation_setup_size
+% \fi\fi}
+%
+% \def\spac_indentation_apply_step_two#1%
+% {\ifcsname\??indentingpreset#1\endcsname
+% \spac_indentation_apply_step_two_nested{#1}%
+% \else\ifcsname\??indentingmethod#1\endcsname
+% \lastnamedcs
+% \else
+% % case one
+% \fi\fi}
+
+\def\spac_indentation_apply_step_one_nested
+ {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one}
+
+\def\spac_indentation_apply_step_two_nested
+ {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_two}
+
+\def\spac_indentation_apply_step_one#1%
+ {\ifcsname\??indentingpreset#1\endcsname
+ \spac_indentation_apply_step_one_nested
+ \else\ifcsname\??indentingmethod#1\endcsname
+ % case two
+ \else
+ \edef\v_spac_indentation_current{#1}% single entry in list
+ \let\normalindentation\v_spac_indentation_current
+ \spac_indentation_setup_size
+ \fi\fi}
+
+\def\spac_indentation_apply_step_two#1%
+ {\ifcsname\??indentingpreset#1\endcsname
+ \spac_indentation_apply_step_two_nested
+ \else\ifcsname\??indentingmethod#1\endcsname
+ \lastnamedcs
+ \else
+ % case one
+ \fi\fi}
+
+\unexpanded\def\indenting % kind of obsolete
+ {\doifelsenextoptionalcs\spac_indentation_setup_options\relax}
+
+% use \noindentation to suppress next indentation
+
+\installcorenamespace{indentingmethod}
+
+\unexpanded\def\installindentingmethod#1#2%
+ {\setvalue{\??indentingmethod#1}{#2}}
+
+\installindentingmethod \v!no {\parindent\zeropoint}
+\installindentingmethod \v!not {\parindent\zeropoint}
+
+\installindentingmethod \v!first {\settrue\c_spac_indentation_indent_first}
+\installindentingmethod \v!next {\setfalse\c_spac_indentation_indent_first}
+
+\installindentingmethod \v!yes {\parindent\d_spac_indentation_par\relax} % not \indent !
+\installindentingmethod \v!always{\parindent\d_spac_indentation_par\relax} % not \indent !
+
+\installindentingmethod \v!never {\parindent\zeropoint\relax % no \indent !
+ \c_spac_indentation_toggle_state\zerocount}
+
+\installindentingmethod \v!odd {\c_spac_indentation_toggle_state\plusone}
+\installindentingmethod \v!even {\c_spac_indentation_toggle_state\plustwo}
+
+\installindentingmethod \v!normal{\ifx\normalindentation\empty\else
+ \let\v_spac_indentation_current\normalindentation
+ \spac_indentation_setup_size
+ \fi}
+
+\installindentingmethod \v!reset {\settrue\c_spac_indentation_indent_first
+ \parindent\zeropoint
+ \c_spac_indentation_toggle_state\zerocount}
+
+\installindentingmethod \v!toggle{\parindent\ifdim\parindent=\zeropoint
+ \d_spac_indentation_par
+ \else
+ \zeropoint
+ \fi\relax}
+
+\unexpanded\def\noindenting{\indenting[\v!no, \v!next ]}
+\unexpanded\def\doindenting{\indenting[\v!yes,\v!first]}
+
+%D Here come the handlers (still rather messy ... we need states).
+
+\newif\ifindentation \indentationtrue % will become a mode
+
+\let\checkindentation\relax
+
+\def\spac_indentation_remove
+ {\ifdim\parindent=\zeropoint \else
+ \begingroup
+ \setbox\scratchbox\lastbox
+ \endgroup
+ \fi}
+
+\def\spac_indentation_kill_indeed
+ {\global\indentationfalse
+ \spac_indentation_remove}
+
+\def\spac_indentation_do_toggle_indeed
+ {\global\indentationfalse
+ \global\let\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}
+
+\def\spac_indentation_do_indeed
+ {\global\indentationtrue}
+
+\def\spac_indentation_do_toggle
+ {\global\let\checkindentation\spac_indentation_do_toggle_indeed}
+
+\def\spac_indentation_no_toggle
+ {\global\let\checkindentation\spac_indentation_no_toggle_indeed}
+
+\def\spac_indentation_check_toggle
+ {\ifcase\c_spac_indentation_toggle_state
+ % nothing
+ \or
+ \spac_indentation_no_toggle
+ \or
+ \spac_indentation_do_toggle
+ \fi}
+
+\def\spac_indentation_variant_yes
+ {\global\let\checkindentation\spac_indentation_do_indeed}
+
+\def\spac_indentation_no_next_check
+ {\spac_indentation_remove
+ \global\let\checkindentation\spac_indentation_do_indeed}
+
+\def\spac_indentation_variant_no % made global
+ {\ifinpagebody \else
+ \global\indentationfalse
+ \global\let\checkindentation\spac_indentation_no_next_check
+ \fi}
+
+\def\nonoindentation % bv bij floats
+ {\ifinpagebody \else
+ \global\indentationtrue
+ \global\let\checkindentation\spac_indentation_do_indeed
+ \fi}
+
+\def\spac_indentation_variant_force
+ {\ifvmode \ifdim\parindent=\zeropoint \else
+ % was : \hskip\parindent
+ % can be: \indent
+ % but we test:
+ \noindent\hskip\parindent
+ \fi \fi}
+
+\appendtoks
+ \pushmacro\checkindentation
+ \pushmacro\ifindentation
+\to \everypushsomestate
+
+\appendtoks
+ \popmacro\ifindentation
+ \popmacro\checkindentation
+\to \everypopsomestate
+
+% public:
+
+\let\indentation \spac_indentation_variant_force
+\let\noindentation\spac_indentation_variant_no % public
+\let\doindentation\spac_indentation_variant_yes % public
+
+\def\dontrechecknextindentation % public (in macros)
+ {\global\let\dorechecknextindentation\relax}
+
+\let\dorechecknextindentation\relax % public (in macros)
+
+\unexpanded\def\spac_indentation_check_next_indentation
+ {\global\let\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}
+
+%D This one sets up the local indentation behaviour (i.e. either or not
+%D a next paragraph will be indented).
+
+\installcorenamespace{indentnext}
+
+\unexpanded\def\checknextindentation[#1]%
+ {\begincsname\??indentnext#1\endcsname}
+
+\unexpanded\def\useindentnextparameter#1% new, the more efficient variant
+ {\edef\p_indentnext{#1\c!indentnext}%
+ \ifx\p_indentnext\empty\else
+ \begincsname\??indentnext\p_indentnext\endcsname
+ \fi}
+
+\letvalue{\??indentnext }\donothing
+\letvalue{\??indentnext\v!yes }\spac_indentation_variant_yes
+\letvalue{\??indentnext\v!no }\spac_indentation_variant_no
+\letvalue{\??indentnext\v!auto}\spac_indentation_variant_auto
+
+%D An example of usage:
+%D
+%D \starttyping
+%D \setupindenting[small,yes]
+%D
+%D \setupitemize [indentnext=auto]
+%D \setuptyping [indentnext=auto]
+%D \setupformulas[indentnext=auto]
+%D
+%D \input tufte \startitemize \item itemize \stopitemize
+%D \input tufte \startitemize \item itemize \stopitemize
+%D \input tufte \startitemize \item itemize \stopitemize
+%D
+%D \page
+%D
+%D \input tufte
+%D \starttyping
+%D verbatim
+%D \stoptyping
+%D
+%D \input tufte
+%D \starttyping
+%D verbatim
+%D \stoptyping
+%D
+%D \input tufte
+%D \starttyping
+%D verbatim
+%D \stoptyping
+%D
+%D \page
+%D
+%D \input tufte \startformula a = b \stopformula
+%D \input tufte \startformula a = b \stopformula
+%D \input tufte \startformula a = b \stopformula
+%D \stoptyping
+
+% maybe an everyforgetparindent
+
+\unexpanded\def\forgetparindent
+ {\settrue\c_spac_indentation_indent_first % recently added
+ \d_spac_indentation_par\zeropoint
+ \parindent\zeropoint
+ \let\v_spac_indentation_current\v!none}
+
+\appendtoks
+ \forgetparindent
+\to \everyforgetall
+
+\unexpanded\def\forgethorizontalstretch
+ {\emergencystretch\zeropoint}
+
+\appendtoks
+ \forgethorizontalstretch
+\to \everyforgetall % needed in pagebody
+
+%D Helper:
+
+\unexpanded\def\softbreak
+ {\relax\ifhmode\hskip\parfillskip\break\fi}
+
+%D \macros
+%D {frenchspacing,nonfrenchspacing}
+%D
+%D Somehow \type{\frenchspacing} can lead to hyphenation between
+%D dashes so we now have \type {\newfrenchspacing} (moved from
+%D \type {syst-chr}).
+
+%D Hm ... todo:
+
+\installcorenamespace{spacecodemethod}
+
+\sfcode`\)=\zerocount
+\sfcode`\'=\zerocount
+\sfcode`\]=\zerocount
+
+\def\spac_spacecodes_set_fixed#1%
+ {\sfcode`\.#1\relax \sfcode`\,#1\relax
+ \sfcode`\?#1\relax \sfcode`\!#1\relax
+ \sfcode`\:#1\relax \sfcode`\;#1\relax}
+
+\def\spac_spacecodes_set_stretch
+ {\sfcode`\.3000 \sfcode`\,1250
+ \sfcode`\?3000 \sfcode`\!3000
+ \sfcode`\:2000 \sfcode`\;1500 }
+
+\unexpanded\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand}
+\unexpanded\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}}
+\unexpanded\def\nonfrenchspacing{\spac_spacecodes_set_stretch}
+
+\unexpanded\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}}
+
+\installspacingmethod \empty {} % keep values
+\installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere
+\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation
+\installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation
+
+\unexpanded\def\setupspacing
+ {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop}
+
+\def\spac_spacecodes_setup_yes[#1]%
+ {\begincsname\??spacecodemethod#1\endcsname
+ \updateraggedskips}
+
+\def\spac_spacecodes_setup_nop
+ {\updateraggedskips}
+
+%D Here's a tweak .. if needed one can configure it in the configuration
+%D so that initialization happens more efficient.
+%D
+%D \starttyping
+%D \startoverlay
+%D {
+%D \green
+%D \enabledirectives[characters.spaceafteruppercase=normal]%
+%D \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par}
+%D } {
+%D \blue
+%D \enabledirectives[characters.spaceafteruppercase=traditional]%
+%D \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par}
+%D }
+%D \stopoverlay
+%D \stoptyping
+
+% This is not needed, as \updateraggedskips is taking care of it:
+
+\let\synchronizespacecodes\spac_spacecodes_setup_nop % \relax
+
+% \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par
+% \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par
+% \dorecurse{100}{\recurselevel\spacefactor 800 \normalspaceprimitive} \par
+% \dorecurse{100}{\recurselevel\spacefactor1200 \normalspaceprimitive} \par
+
+% When we don't add the % here, we effectively get \<endlinechar> and
+% since we have by default \def\^^M{\ } we get into a loop.
+
+\let\normalspaceprimitive=\ % space-comment is really needed
+
+%D As the \type{\ } is convenient in:
+%D
+%D \starttyping
+%D \TEX\space x\crlf
+%D \TEX\ x\crlf
+%D \TEX{} x\crlf
+%D \stoptyping
+%D
+%D from now on we treat it as a normal space and not as a space with \type
+%D {sfcode} 1000.
+
+\unexpanded\def\specialspaceprimitive
+ {\begingroup
+ % so, no fancy extra spacing after: foo i.e.\ bar
+ \nonfrenchspacing\normalspaceprimitive
+ \endgroup}
+
+\unexpanded\def\normalnotobeyedspace
+ {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing)
+
+\let\ =\normalnotobeyedspace
+
+% Because I strip spaces at the end of lines (in the editor) we need a bit of
+% a trick to define slash+newline, so \space and \<newline> are the same
+
+% We need to be careful with \ and \space and the definition of ~ which uses \ as
+% we need to associate unicode spacing with it. There is some messy aspect that
+% I forgot to note down so I will revision the \ once I ran into it again.
+
+% \ruledhbox spread 10pt {\frenchspacing xx xx\ X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx xx\ X}
+% \ruledhbox spread 10pt {\frenchspacing xx xx X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx xx X}
+% \ruledhbox spread 10pt {\frenchspacing xx xx~X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx xx~X}
+
+% \ruledhbox spread 10pt {\frenchspacing xx dr.\ X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx dr.\ X}
+% \ruledhbox spread 10pt {\frenchspacing xx dr. X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx dr. X}
+% \ruledhbox spread 10pt {\frenchspacing xx dr.~X}
+% \ruledhbox spread 10pt {\nonfrenchspacing xx dr.~X}
+
+\unexpanded\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math
+
+\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later
+
+ \def\space { }
+\unexpanded\def\removelastspace{\ifhmode\unskip\fi}
+\unexpanded\def\nospace {\removelastspace\ignorespaces}
+
+\ifdefined\nospaces
+ \unexpanded\def\nospacing{\normalnospaces\plusone}
+ \unexpanded\def\dospacing{\normalnospaces\zerocount}
+\else
+ \unexpanded\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint}
+ \unexpanded\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what
+\fi
+
+\ifdefined\softhyphen \else
+ \let\softhyphen\-
+\fi
+
+\cldcontext{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"}
+%cldcontext{"\string\\let\string\\\string\n=\string\\space"}
+
+% in tables we need:
+%
+% \def\fixedspace {\hskip.5em\relax}
+%
+% but, since not all fonts have .5em digits:
+
+\unexpanded\def\fixedspace
+ {\setbox\scratchbox\hbox{\mathortext{0}{0}}%
+ \hskip\wd\scratchbox\relax}
+
+\unexpanded\def\fixedspaces
+ {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace
+ \let~\fixedspace} % we need to renew it
+
+\appendtoks
+ \let~\space
+ \let\ \space
+\to \everysimplifycommands
+
+\newsignal\s_spac_keep_unwanted_space
+
+\unexpanded\def\keepunwantedspaces
+ {\ifhmode
+ \ifdim\lastskip=\s_spac_keep_unwanted_space\else
+ \hskip\s_spac_keep_unwanted_space\relax
+ \fi
+ \fi}
+
+\unexpanded\def\removeunwantedspaces
+ {\ifhmode
+ \expandafter \spac_helpers_remove_unwantedspace
+ \fi}
+
+\def\spac_helpers_remove_unwantedspace
+ {\ifnum\lastnodetype=\gluenodecode
+ \ifdim\lastskip=\s_spac_keep_unwanted_space\relax
+ \unskip
+ \else
+ \unskip
+ \doubleexpandafter\spac_helpers_remove_unwantedspace
+ \fi
+ \fi}
+
+% \startbuffer
+% \startlines \tt \fixedspaces
+% 0~1~~2~~~3~~~~4~~~~~5
+% 0~~~~~~~~~~~~~~~~~~~5
+% $0~1~~2~~~3~~~~4~~~~~5$
+% $0~~~~~~~~~~~~~~~~~~~5$
+% \stoplines
+%
+% \starttabulate[|~|]
+% \NC 0~1~~2~~~3~~~~4~~~~~5 \NC \NR \NC 0~~~~~~~~~~~~~~~~~~~5 \NC \NR
+% \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \NR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \NR
+% \stoptabulate
+%
+% \starttable[||]
+% \NC 0~1~~2~~~3~~~~4~~~~~5 \NC \AR \NC 0~~~~~~~~~~~~~~~~~~~5 \NC \AR
+% \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \AR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \AR
+% \stoptable
+% \stopbuffer
+%
+% \setupbodyfont[cmr] \getbuffer
+% \setupbodyfont[lbr] \getbuffer
+
+%D A couple of plain macros:
+
+\ifdefined\thinspace \else
+
+ \unexpanded\def\thinspace {\kern .16667\emwidth}
+ \unexpanded\def\negthinspace{\kern-.16667\emwidth}
+ \unexpanded\def\enspace {\kern .5\emwidth}
+
+\fi
+
+\ifdefined\quad \else
+
+ \unexpanded\def\enskip{\hskip.5\emwidth}
+ \unexpanded\def\quad {\hskip \emwidth}
+ \unexpanded\def\qquad {\hskip 2\emwidth}
+
+\fi
+
+\let\emspace\quad
+
+% Suggested by GB (not the name -):
+
+\def\rapfillskip{.5\hsize plus .092\hsize minus .5\hsize} % D.A.'s value
+
+% Bovendien definieren we enkele extra \fill's:
+
+\unexpanded\def\hfilll {\hskip\zeropoint\s!plus1\s!filll\relax}
+\unexpanded\def\vfilll {\vskip\zeropoint\s!plus1\s!filll\relax}
+
+%unexpanded\def\hfilneg {\hskip\zeropoint\s!plus-1\s!fil\relax}
+\unexpanded\def\hfillneg {\hskip\zeropoint\s!plus-1\s!fill\relax}
+\unexpanded\def\hfilllneg{\hskip\zeropoint\s!plus-1\s!filll\relax}
+%unexpanded\def\vfilneg {\vskip\zeropoint\s!plus-1\s!fil\relax}
+\unexpanded\def\vfillneg {\vskip\zeropoint\s!plus-1\s!fill\relax}
+\unexpanded\def\vfilllneg{\vskip\zeropoint\s!plus-1\s!filll\relax}
+
+\unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup}
+\unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere
+
+% maybe we should hash the analysis
+
+\installcorenamespace{narrower}
+\installcorenamespace{narrowermethod}
+
+\newskip\s_spac_narrower_left
+\newskip\s_spac_narrower_right
+\newskip\s_spac_narrower_mid
+
+\installcommandhandler \??narrower {narrower} \??narrower
+
+\setupnarrower
+ [\c!before=\endgraf,
+ \c!after=\endgraf,
+ \c!left=1.5\emwidth,
+ \c!right=1.5\emwidth,
+ \c!middle=1.5\emwidth,
+ \c!default=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentnarrower}{\spac_narrower_start{\currentnarrower}}%
+ \setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}%
+\to \everydefinenarrower
+
+\unexpanded\def\installnarrowermethod#1#2%
+ {\setvalue{\??narrowermethod#1}{#2}}
+
+\unexpanded\def\spac_narrower_method_analyze#1%
+ {\ifcsname\??narrowermethod#1\endcsname
+ \lastnamedcs
+ \else
+ \global\advance\s_spac_narrower_mid#1\relax
+ \fi}
+
+\def\spac_narrower_initialize[#1]% hm, can be dorepeat directly
+ {\dorepeatwithcommand[#1]\spac_narrower_method_analyze}
+
+\installnarrowermethod \v!left {\global\advance\s_spac_narrower_left \narrowerparameter\c!left \relax}
+\installnarrowermethod \v!middle {\global\advance\s_spac_narrower_mid \narrowerparameter\c!middle\relax}
+\installnarrowermethod \v!right {\global\advance\s_spac_narrower_right \narrowerparameter\c!right \relax}
+\installnarrowermethod{-\v!left }{\global\advance\s_spac_narrower_left -\narrowerparameter\c!left \relax}
+\installnarrowermethod{-\v!middle}{\global\advance\s_spac_narrower_mid -\narrowerparameter\c!middle\relax}
+\installnarrowermethod{-\v!right }{\global\advance\s_spac_narrower_right-\narrowerparameter\c!right \relax}
+\installnarrowermethod \v!reset {\global \s_spac_narrower_left \zeropoint
+ \global \s_spac_narrower_mid \zeropoint
+ \global \s_spac_narrower_right \zeropoint\relax}
+\installnarrowermethod \v!none {}
+
+\unexpanded\def\spac_narrower_start#1%
+ {\begingroup
+ \edef\currentnarrower{#1}%
+ \dosingleempty\spac_narrower_start_indeed}
+
+\unexpanded\def\spac_narrower_start_indeed[#1]%
+ {\iffirstargument
+ \spac_narrower_start_apply{#1}%
+ \else
+ \spac_narrower_start_apply{\narrowerparameter\v!default}%
+ \fi}
+
+\def\spac_narrower_start_apply#1%
+ {\narrowerparameter\c!before
+ \global\s_spac_narrower_left \zeropoint
+ \global\s_spac_narrower_right\zeropoint
+ \global\s_spac_narrower_mid \zeropoint
+ \processcommalistwithparameters[#1]\spac_narrower_initialize
+ \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_mid\relax
+ \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_mid\relax
+ \seteffectivehsize}
+
+\unexpanded\def\spac_narrower_stop
+ {\narrowerparameter\c!after
+ \endgroup}
+
+\unexpanded\def\startnarrower
+ {\dosingleempty\spac_narrower_start_basic}
+
+\unexpanded\def\spac_narrower_start_basic[#1]%
+ {\begingroup
+ \let\currentnarrower\empty
+ \iffirstargument
+ \spac_narrower_start_apply{#1}%
+ \else
+ \spac_narrower_start_apply{\narrowerparameter\v!default}%
+ \fi}
+
+\let\stopnarrower\spac_narrower_stop
+
+\unexpanded\def\startnarrow % current how
+ {\begingroup
+ \dodoubleempty\spac_narrower_start_named}
+
+% \def\spac_narrower_start_named[#1][#2]%
+% {\edef\currentnarrower{#1}%
+% \ifsecondargument
+% \spac_narrower_start_apply{#2}%
+% \else
+% \spac_narrower_start_apply{\narrowerparameter\v!default}%
+% \fi}
+
+\def\spac_narrower_start_named
+ {\ifsecondargument
+ \expandafter\spac_narrower_start_named_two
+ \else
+ \expandafter\spac_narrower_start_named_one
+ \fi}
+
+\def\spac_narrower_start_named_one[#1]%
+ {\doifelseassignment{#1}\spac_narrower_start_named_one_yes\spac_narrower_start_named_one_nop[#1]}
+
+\def\spac_narrower_start_named_one_yes[#1][#2]% [settings] []
+ {\setupcurrentnarrower[#1]%
+ \spac_narrower_start_apply{\narrowerparameter\v!default}}
+
+\def\spac_narrower_start_named_one_nop[#1][#2]% [tag] []
+ {\edef\currentnarrower{#1}%
+ \spac_narrower_start_apply{\narrowerparameter\v!default}}
+
+\def\spac_narrower_start_named_two[#1]%
+ {\doifelseassignment{#1}\spac_narrower_start_named_settings_how\spac_narrower_start_named_tag_unknown[#1]}
+
+\def\spac_narrower_start_named_settings_how[#1][#2]% [settings] [how]
+ {\setupcurrentnarrower[#1]%
+ \spac_narrower_start_apply{#2}}
+
+\def\spac_narrower_start_named_tag_unknown[#1][#2]% [tag] [...]
+ {\doifelseassignment{#2}\spac_narrower_start_named_tag_settings\spac_narrower_start_named_tag_how[#1][#2]}
+
+\def\spac_narrower_start_named_tag_settings[#1][#2]% [tag] [settings]
+ {\edef\currentnarrower{#1}%
+ \setupcurrentnarrower[#2]%
+ \spac_narrower_start_apply{\narrowerparameter\v!default}}
+
+\def\spac_narrower_start_named_tag_how[#1][#2]% [tag] [how]
+ {\edef\currentnarrower{#1}%
+ \spac_narrower_start_apply{#2}}
+
+\let\stopnarrow\spac_narrower_stop
+
+\newdimen\d_spac_effective_hsize \def\effectivehsize {\hsize}
+\newdimen\d_spac_effective_leftskip \def\effectiveleftskip {\leftskip}
+\newdimen\d_spac_effective_rightskip \def\effectiverightskip{\rightskip}
+
+\unexpanded\def\seteffectivehsize
+ {\setlocalhsize
+ \d_spac_effective_hsize \localhsize
+ \d_spac_effective_leftskip \leftskip
+ \d_spac_effective_rightskip\rightskip
+ \let\effectivehsize \d_spac_effective_hsize
+ \let\effectiveleftskip \d_spac_effective_leftskip
+ \let\effectiverightskip\d_spac_effective_rightskip}
+
+\installcorenamespace{skipadaptionleft}
+\installcorenamespace{skipadaptionright}
+
+\newskip\leftskipadaption
+\newskip\rightskipadaption
+
+\setvalue{\??skipadaptionleft \v!standard}{\ifdim\d_spac_indentation_par=\zeropoint\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
+\setvalue{\??skipadaptionleft \v!yes }{\ifdim\d_spac_indentation_par=\zeropoint\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
+\letvalue{\??skipadaptionleft \v!no }\zeropoint
+\letvalue{\??skipadaptionleft \empty }\zeropoint
+\setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right}
+\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right}
+\letvalue{\??skipadaptionright\v!no }\zeropoint
+\letvalue{\??skipadaptionright\empty }\zeropoint
+
+% \unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
+% \unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
+
+\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax}
+\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax}
+
+\unexpanded\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\advance\leftskip \leftskipadaption }
+\unexpanded\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\advance\rightskip\rightskipadaption}
+
+\unexpanded\def\forgetbothskips
+ {\leftskip\zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+\appendtoks
+ \forgetbothskips
+\to \everyforgetall
+
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
+
+\appendtoks
+ \forgetparskip
+\to \everyforgetall
+
+%D Tolerance (can also be set with align):
+
+\installcorenamespace{tolerancemethods}
+
+\unexpanded\def\installtolerancemethod#1#2#3%
+ {\setvalue{\??tolerancemethods#1:#2}{#3}}
+
+\installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty}
+\installtolerancemethod \v!vertical \v!strict {\def\bottomtolerance{.050}}
+\installtolerancemethod \v!vertical \v!tolerant {\def\bottomtolerance{.075}}
+\installtolerancemethod \v!vertical \v!verytolerant {\def\bottomtolerance{.100}}
+
+\installtolerancemethod \v!horizontal \v!stretch {\emergencystretch\bodyfontsize}
+\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\s!plus.25em\s!minus.25em\relax}
+\installtolerancemethod \v!horizontal \v!verystrict {\tolerance\plustwohundred}
+\installtolerancemethod \v!horizontal \v!strict {\tolerance1500 }
+\installtolerancemethod \v!horizontal \v!tolerant {\tolerance3000 }
+\installtolerancemethod \v!horizontal \v!verytolerant {\tolerance4500 }
+
+\appendetoks
+ \pretolerance\plushundred
+ \tolerance \plustwohundred
+\to\everyforgetall
+
+\def\spac_tolerances_step_vertical #1{\csname\??tolerancemethods\v!vertical :#1\endcsname}
+\def\spac_tolerances_step_horizontal#1{\csname\??tolerancemethods\v!horizontal:#1\endcsname}
+
+\unexpanded\def\setuptolerance
+ {\dosingleargument\spac_tolerances_setup}
+
+\def\spac_tolerances_setup[#1]%
+ {\doifelseinset\v!vertical{#1}%
+ {\processcommacommand[#1]\spac_tolerances_step_vertical }
+ {\processcommacommand[#1]\spac_tolerances_step_horizontal}}
+
+%D \macros
+%D {pushindentation,popindentation}
+%D
+%D The pushing and popping is done by:
+
+\newbox\b_spac_indentations_a
+\newbox\b_spac_indentations_b
+
+\unexpanded\def\pushindentation
+ {\begingroup
+ \ifhmode
+ \unskip
+ \setbox\b_spac_indentations_a\lastbox % get \strut if present
+ \unskip
+ \setbox\b_spac_indentations_b\lastbox % get \indent generated box
+ \unskip
+ \else
+ \dontleavehmode % was \hskip\zeropoint % switch to horizontal mode
+ \unskip
+ \setbox\b_spac_indentations_a\lastbox % get \indent generated box
+ \setbox\b_spac_indentations_b\emptybox
+ \fi}
+
+\unexpanded\def\popindentation
+ {\box\b_spac_indentations_b
+ \box\b_spac_indentations_a
+ \endgroup}
+
+%D The only complication lays in \type{\strut}. In \PLAIN\
+%D \TEX\ a \type{\strut} is defined as:
+%D
+%D \starttyping
+%D \def\strut%
+%D {\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+%D \stoptyping
+%D
+%D But what is a \type{\strut}? Normally it's a rule of width
+%D zero, but when made visual, it's a rule and a negative skip.
+%D The mechanism for putting things in the margins described
+%D here cannot handle this situation very well. One
+%D characteristic of \type{\strut} is that the \type{\unhcopy}
+%D results in entering horizontal mode, which in return leads
+%D to some indentation.
+%D
+%D To serve our purpose a bit better, the macro \type{\strut}
+%D can be redefined as:
+%D
+%D \starttyping
+%D \def\strut
+%D {\relax\ifmmode\else\hskip0pt\fi\copy\strutbox}
+%D \stoptyping
+%D
+%D Or more compatible:
+%D
+%D \starttyping
+%D \def\strut
+%D {\relax\ifmmode
+%D \copy\strutbox
+%D \else
+%D \bgroup\setbox\strutbox=\hbox{\box\strutbox}\unhcopy\strutbox\egroup
+%D \fi}
+%D \stoptyping
+%D
+%D In \CONTEXT\ however we save some processing time by putting
+%D an extra \type{\hbox} around the \type{\strutbox}.
+
+%D \starttyping
+%D % \setuplayout[gridgrid=yes] \showgrid
+%D
+%D \startbuffer
+%D test 1\crlf
+%D test 2\crlf
+%D
+%D \crlf test 3
+%D
+%D test 4\crlf
+%D test 5
+%D
+%D \crlf
+%D \crlf
+%D \crlf
+%D test 6
+%D \stopbuffer
+%D
+%D \hbox
+%D {\hsize5em
+%D \ruledvtop{\getbuffer}\enspace
+%D \ruledvtop{\showstruts\getbuffer}\enspace
+%D \hsize15em \setuptyping[before=,after=]%
+%D \ruledvtop{\typebuffer}}
+%D \stoptyping
+
+\unexpanded\def\justonespace{\removeunwantedspaces\space}
+%unexpanded\def\justaperiod {\removeunwantedspaces.}
+%unexpanded\def\justacomma {\removeunwantedspaces,}
+
+\installcorenamespace{hspace}
+
+\unexpanded\def\ignorecrlf
+ {\let\crlf\justonespace\let\\\crlf}
+
+\unexpanded\def\definehspace
+ {\dotripleempty\spac_hspaces_define}
+
+\def\spac_hspaces_define[#1][#2][#3]% #1 = optional namespace
+ {\ifthirdargument
+ \setvalue{\??hspace#1:#2}{#3}%
+ \else
+ \setvalue{\??hspace:#1}{#2}%
+ \fi}
+
+\unexpanded\def\hspace
+ {\dodoubleempty\spac_hspaces_insert}
+
+\def\spac_hspaces_insert[#1][#2]%
+ {\ifhmode
+ \removeunwantedspaces
+ \hskip % always a skip even when 0pt
+ \ifsecondargument
+ \hspaceamount{#1}{#2}%
+ \else\iffirstargument
+ \hspaceamount\empty{#1}%
+ \else
+ \hspaceamount\empty\s!default
+ \fi\fi
+ \expandafter\ignorespaces
+ \fi}
+
+\def\hspaceamount#1#2%
+ {\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+
+\def\directhspaceamount#1%
+ {\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+
+% no installhspace here (this is already an old command)
+
+\definehspace [\v!small] [.25\emspaceamount]
+\definehspace [\v!medium] [.5\emspaceamount]
+\definehspace [\v!big] [1\emspaceamount]
+\definehspace [\v!normal] [1\spaceamount]
+\definehspace [\v!default] [\spaceamount]
+\definehspace [\v!none] [\zeropoint]
+
+%D Taken from Taco's math module (cq. \AMS\ macros), but
+%D adapted to \type {\hspace}:
+
+\unexpanded\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax}
+\unexpanded\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax}
+
+\newmuskip\hairmuskip \hairmuskip=.15mu
+
+\unexpanded\def\hairspace {\textormathspace+\hairmuskip{.5}}
+\unexpanded\def\thinspace {\textormathspace+\thinmuskip 1}
+\unexpanded\def\medspace {\textormathspace+\medmuskip 2}
+\unexpanded\def\thickspace {\textormathspace+\thickmuskip3}
+\unexpanded\def\neghairspace {\textormathspace-\thinmuskip{.5}}
+\unexpanded\def\negthinspace {\textormathspace-\thinmuskip 1}
+\unexpanded\def\negmedspace {\textormathspace-\medmuskip 2}
+\unexpanded\def\negthickspace{\textormathspace-\thickmuskip3}
+
+% needed for unicode:
+
+%unexpanded\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1}
+%unexpanded\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace
+%unexpanded\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax}
+%unexpanded\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax}
+%unexpanded\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie
+%unexpanded\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax}
+%unexpanded\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this
+%unexpanded\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup}
+%unexpanded\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax}
+%unexpanded\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax}
+%unexpanded\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace}
+%unexpanded\def\narrownobreakspace {\penalty\plustenthousand\thinspace}
+%unexpanded\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint}
+%unexpanded\def\zerowidthspace {\hskip\zeropoint}
+
+\definehspace[.5][.1250\emspaceamount] % could also be [.1250\spaceamount]
+\definehspace[1] [.1667\emspaceamount]
+\definehspace[2] [.2222\emspaceamount]
+\definehspace[3] [.2777\emspaceamount]
+
+\let \, \thinspace
+\let \: \medspace
+\let \; \thickspace
+\let \! \negthinspace
+
+% plain ...
+%
+% \ifdefined\> \else \unexpanded\def\>{\mskip \medmuskip } \fi
+% \ifdefined\* \else \unexpanded\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
+
+\def\flexiblespaceamount#1#2#3%
+ {#1\interwordspace
+ \s!plus#2\interwordstretch
+ \s!minus#3\interwordshrink}
+
+\def\fixedspaceamount#1%
+ {#1\interwordspace}
+
+% moved from page-lin
+%
+% the following code is used in startlines\stoplines
+%
+% do we need \normalspaceprimitive here?
+
+\installcorenamespace{spacemethods}
+
+\unexpanded\def\installspacemethod#1#2% needs to set \obeyedspace
+ {\setvalue{\??spacemethods#1}{#2}}
+
+\def\activatespacehandler#1%
+ {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname}
+
+\unexpanded\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}%
+\unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}%
+\unexpanded\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}%
+
+\installspacemethod \v!on
+ {\obeyspaces
+ \let\obeyedspace\spac_spaces_checked_control
+ \let\ =\obeyedspace}
+
+\installspacemethod \v!yes
+ {\obeyspaces
+ \let\obeyedspace\spac_spaces_checked_normal
+ \let\ =\obeyedspace}
+
+\installspacemethod \v!off % == default
+ {\normalspaces
+ \let\obeyedspace\normalspace
+ \let\ =\normalspaceprimitive} % was \normalspace
+
+\installspacemethod \v!fixed
+ {\obeyspaces
+ \let\obeyedspace\spac_spaces_checked_fixed
+ \let\ =\obeyedspace}
+
+\appendtoks
+ \normalspaces % to be sure
+\to \everybeforeoutput
+
+%D A more robust variant of the \MKII\ one:
+%D
+%D \startbuffer
+%D bla \TEX\autoinsertnextspace bla
+%D bla \TEX\autoinsertnextspace (bla)
+%D bla (\TEX\autoinsertnextspace) bla
+%D bla \TEX\autoinsertnextspace\ bla
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\autoinsertnextspace
+ {\futurelet\nexttoken\spac_spaces_auto_insert_next}
+
+\def\spac_spaces_auto_insert_next
+ {\clf_autonextspace{\meaning\nexttoken}} % todo, just consult nexttoken at the lua end
+
+%D Moved from bib module:
+
+\unexpanded\def\outdented#1%
+ {\hskip-\hangindent#1\relax}
+
+%D Beware: due to char-def this becomes an active character but that
+%D might change sometime when we will replace all these specials to
+%D node insertions. We might even expand it to utf then as it then
+%D can be used in string comparison (not that much needed anyway).
+
+% \chardef\zwnj="200C
+% \chardef\zwj ="200D
+
+% TODO (but used in languages):
+
+\unexpanded\def\spac_glues_text_or_math#1#2%
+ {\begingroup
+ \ifmmode
+ \mskip#1%
+ \else
+ \scratchdimen#1\hspaceamount\empty{#2}%
+ \scratchskip\scratchdimen\s!plus.5\scratchdimen\s!minus.3\scratchdimen
+ \hskip\scratchskip
+ \fi
+ \endgroup}
+
+\unexpanded\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small}
+\unexpanded\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium}
+\unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big}
+
+%D A rather unknown one:
+
+\unexpanded\def\widened % moved from cont-new
+ {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop}
+
+\def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}}
+\def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}}
+
+\definecomplexorsimple\widened
+
+%D For the moment here (used in page-txt):
+
+\unexpanded\def\ignoredlinebreak{\unskip\space\ignorespaces}
+
+%D \macros
+%D {startignorespaces}
+%D
+%D I'll probably forget that this one exists:
+%D
+%D \starttyping
+%D \ruledhbox
+%D {\startignorespaces
+%D \def\oeps{a}
+%D \startignorespaces
+%D \def\oeps{a}
+%D \stopignorespaces
+%D \def\oeps{a}
+%D \stopignorespaces
+%D \oeps}
+%D \stoptyping
+
+\newsignal\s_spac_ignore_spaces
+\newcount \c_spac_ignore_spaces
+
+\unexpanded\def\startignorespaces
+ {\advance\c_spac_ignore_spaces\plusone
+ \ifcase\c_spac_ignore_spaces\or \ifhmode
+ \hskip\s_spac_ignore_spaces
+ \fi \fi
+ \ignorespaces}
+
+\unexpanded\def\stopignorespaces
+ {\ifcase\c_spac_ignore_spaces \or
+ \ifhmode
+ \doloop\spac_ignore_spaces_body
+ \fi
+ \fi
+ \advance\c_spac_ignore_spaces\minusone}
+
+\def\spac_ignore_spaces_body
+ {\ifdim\lastskip=\zeropoint
+ \exitloop
+ \else\ifdim\lastskip=\s_spac_ignore_spaces
+ \unskip
+ \exitloop
+ \else
+ \unskip
+ \fi\fi}
+
+%D \macros
+%D {obeyfollowingtoken}
+
+\def\obeyfollowingtoken{{}} % end \cs scanning
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv
new file mode 100644
index 00000000000..c4c6eb6d9eb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv
@@ -0,0 +1,159 @@
+%D \module
+%D [ file=spac-lin,
+%D version=2012.01.08, % 2009.10.16 (core-ver) 1997.03.31 (core-spa)
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Vertical,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Lines}
+
+\unprotect
+
+%D When spacing is active we need to handle commands in
+%D a special way:
+%D
+%D \starttyping
+%D \setuplines[space=on]
+%D
+%D \startlines
+%D Let's talk about this{\ttsl\gobbleoneargument or}that.
+%D \stoplines
+%D
+%D \startlines
+%D Let's talk about this{\getvalue{ttsl}or}that.
+%D \stoplines
+%D \stoptyping
+%D
+%D One can indent in several ways:
+%D
+%D \starttyping
+%D \setupindenting[medium] \setuplines[indenting=odd] % no yes odd even
+%D
+%D \startlines
+%D first
+%D second
+%D third
+%D fourth
+%D \stoplines
+%D \stoptyping
+
+%D Contrary to \MKII\ we can now define classes of lines (generalized by
+%D Wolfgang). I will probably rewrite bits in \LUA.
+
+\installcorenamespace{lines}
+
+\installcommandhandler \??lines {lines} \??lines
+
+\setuplines
+ [\c!option=,
+ \c!command=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=\blank,
+ \c!indenting=\v!no,
+ \c!space=\v!default]
+
+\appendtoks
+ \setuevalue{\e!start\currentlines}{\spac_lines_start[\currentlines]}%
+ \setuevalue{\e!stop \currentlines}{\spac_lines_stop}%
+\to \everydefinelines
+
+\unexpanded\def\spac_lines_start[#1]%
+ {\bgroup
+ \edef\currentlines{#1}%
+ \obeylines
+ \dosingleempty\spac_lines_start_indeed}
+
+\let\p_lines_option\empty
+
+\let\spac_lines_break \relax
+\let\spac_after_first_obeyed_line\relax
+
+\def\spac_lines_start_indeed[#1]% new: optional second argument (WS)
+ {\iffirstargument
+ \setupcurrentlines[#1]%
+ \fi
+ \edef\p_lines_option{\linesparameter\c!option}%
+ \ifx\p_lines_option\v!packed
+ \let\spac_lines_break\nobreak
+ \else
+ \let\spac_lines_break\relax
+ \fi
+ \linesparameter\c!before
+ \pushmacro\checkindentation
+ \whitespace
+ \dostarttaggedchained\t!lines\currentlines\??lines
+ \begingroup
+ \uselinesstyleandcolor\c!style\c!color
+ \useindentingparameter\linesparameter
+ \usealignparameter\linesparameter
+ \typesettinglinestrue
+ \setupwhitespace[\v!none]% todo use fast variant
+ %\obeylines % move upwards to keep spaces in the first line due to optional argument
+ \ignorespaces
+ \glet\spac_after_first_obeyed_line\spac_lines_after_first_obeyed_line_a
+ \let\obeyedline\spac_lines_obeyed_line
+ \activatespacehandler{\linesparameter\c!space}%
+ \dostarttagged\t!line\empty
+ \GotoPar} % this will become a nice lowercased helper
+
+% we could have states instead and handle option in there
+
+\def\spac_lines_after_first_obeyed_line_a % tzt two pass, like itemize
+ {\linesparameter\c!command
+ \glet\spac_after_first_obeyed_line\spac_lines_after_first_obeyed_line_b}
+
+\def\spac_lines_after_first_obeyed_line_b
+ {\spac_lines_break
+ \linesparameter\c!command}
+
+\def\spac_lines_obeyed_line
+ {\dostoptagged
+ \par
+ \dostarttagged\t!line\empty
+ \futurelet\next\spac_lines_between}
+
+\unexpanded\def\spac_lines_stop
+ {\dostoptagged
+ \endgroup
+ \dostoptagged
+ \popmacro\checkindentation
+ \linesparameter\c!after
+ \egroup}
+
+\def\spac_lines_between
+ {\doifelsemeaning\next\obeyedline % brrr
+ {\linesparameter\c!inbetween}
+ {\spac_after_first_obeyed_line}}
+
+\definelines[\v!lines]
+
+\unexpanded\def\emptylines
+ {\dosingleempty\spac_lines_empty}
+
+% \def\spac_lines_empty[#1]%
+% {\endgraf
+% \dorecurse{\iffirstargument#1\else3\fi}\crlf}
+
+\def\spac_lines_empty[#1]%
+ {\endgraf
+ \begingroup
+ %\forgetall % debatable
+ \ifhmode
+ \crlf % finish the current line
+ \fi
+ \dorecurse{\iffirstargument#1\else3\fi}{\strut\crlf}%
+ \endgroup}
+
+\ifdefined\startlines \else
+ \expandafter\let\expandafter\startlines\csname\e!start\v!lines\endcsname
+ \expandafter\let\expandafter\stoplines \csname\e!stop \v!lines\endcsname
+\fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv
new file mode 100644
index 00000000000..c7d22f0e0c5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv
@@ -0,0 +1,183 @@
+%D \module
+%D [ file=spac-pag,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Pages,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Pages}
+
+\unprotect
+
+%D The code here has evolved over time and might not be the best
+%D around. Maybe much will be gone a some point.
+
+\installcorenamespace {alignswitch}
+
+\letvalue{\??alignswitch\v!left }\zerocount
+\letvalue{\??alignswitch\v!middle}\plusone
+\letvalue{\??alignswitch\v!right }\plustwo
+
+\def\setalignmentswitch#1%
+ {\chardef\alignmentswitch\csname\??alignswitch\ifcsname\??alignswitch#1\endcsname#1\else\v!left\fi\endcsname}
+
+\newif \ifpagestatemismatch
+\newcount \realpagestateno
+\newconstant\frozenpagestate
+
+\def\dotrackpagestate#1#2%
+ {\ifdoublesided \ifinpagebody \else
+ \doforcedtrackpagestate{#1}{#2}%
+ \fi \fi}
+
+\def\doforcedtrackpagestate#1#2%
+ {\ifcase\frozenpagestate
+ \global\advance#2\plusone
+ \setpagestate[#1][\number#2]%
+ \fi}
+
+\let\m_spac_pagestates_realpage\empty
+
+\newconditional\c_spac_pagestates_found
+
+\unexpanded\def\docheckpagestate#1#2%
+ {\ifcase\frozenpagestate
+ \setpagestaterealpageno{#1}{\number#2}%
+ \fi}
+
+\unexpanded\def\doifelserightpagestate#1#2% not expandable !
+ {\ifcase\frozenpagestate
+ \pagestatemismatchfalse
+ \realpagestateno\realfolio
+ \ifinpagebody
+ \ifdoublesided
+ \ifodd\realpageno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \else
+ \settrue\c_spac_pagestates_found
+ \fi
+ \else\ifdoublesided
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}%
+ \ifx\m_spac_pagestates_realpage\empty
+ \ifodd\realpageno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \else
+ \realpagestateno\m_spac_pagestates_realpage\relax
+ \ifnum\realpagestateno=\realpageno \else
+ \pagestatemismatchtrue
+ \fi
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \fi
+ \else
+ \settrue\c_spac_pagestates_found
+ \fi\fi
+ \else
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \fi
+ \ifconditional\c_spac_pagestates_found
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelseforcedrightpagestate#1#2%
+ {\ifcase\frozenpagestate
+ \pagestatemismatchfalse
+ \realpagestateno\realfolio
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}%
+ \ifx\m_spac_pagestates_realpage\empty
+ \ifodd\realpageno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \else
+ \realpagestateno\m_spac_pagestates_realpage\relax
+ \ifnum\realpagestateno=\realpageno \else
+ \pagestatemismatchtrue
+ \fi
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \fi
+ \else
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
+ \fi
+ \fi
+ \ifconditional\c_spac_pagestates_found
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifrightpagestateelse \doifelserightpagestate
+\let\doifforcedrightpagestateelse\doifelseforcedrightpagestate
+
+\unexpanded\def\freezepagestate {\frozenpagestate\plusone }
+\unexpanded\def\defrostpagestate{\frozenpagestate\zerocount}
+
+% we can make more of these on top, but how to deal with mixed frozen states
+
+% \dorecurse{500}{\dontleavehmode\signalrightpage\doifrightpageelse{right}{left}\par} % given doublesided
+
+\newcount\nofraggedparagraphs
+
+\definepagestate[\s!paragraph]
+
+\unexpanded\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs} % use \dontleavehmode if needed
+\unexpanded\def\doifelserightpage{\doifelserightpagestate\s!paragraph\nofraggedparagraphs}
+
+\let\doifrightpageelse\doifelserightpage
+
+\installcorenamespace{pagechanges}
+
+\newif\ifpagechanged \let\lastchangedpage\empty
+
+\def\spac_pagechanges_check#1#2#3%
+ {\pagechangedfalse
+ \doforcedtrackpagestate{#2}{#3}%
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#2}{\number#3}}%
+ \ifx\m_spac_pagestates_realpage\empty \else
+ \ifnum\m_spac_pagestates_realpage>0\csname\??pagechanges#2:#1\endcsname\relax
+ \pagechangedtrue
+ \fi
+ \fi
+ \ifpagechanged
+ \letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage
+ \globallet\lastchangedpage\m_spac_pagestates_realpage
+ \else
+ \globallet\lastchangedpage\realfolio
+ \fi}
+
+\def\changedpagestate#1#2%
+ {\executeifdefined{\??pagechanges#2:#1}0}
+
+\def\checkpagechange#1{\spac_pagechanges_check{#1}\s!paragraph\nofraggedparagraphs}
+\def\changedpage #1{\changedpagestate{#1}\s!paragraph}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv
new file mode 100644
index 00000000000..4dd3db24338
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv
@@ -0,0 +1,243 @@
+%D \module
+%D [ file=spac-par,
+%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 / Paragraphs}
+
+\unprotect
+
+%D The dreadful sequence \type {\bgroup} \unknown\
+%D \type {\carryoverpar} \unknown\ \type {\egroup} is needed
+%D when for instance sidefloats are used in combination with
+%D something that starts with a group. This is because
+%D otherwise the indentation as set (by the output routine)
+%D inside the group are forgotten afterwards. (I must
+%D not forget its existence).
+
+\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable !
+ {\normalexpanded
+ {\noexpand#1%
+ \hangindent\the\hangindent
+ \hangafter \the\hangafter
+ \parskip \the\parskip
+ \leftskip \the\leftskip
+ \rightskip \the\rightskip}}
+
+\unexpanded\def\pushparagraphproperties
+ {\edef\currentparagraphproperties{\carryoverpar\relax}%
+ \pushmacro\currentparagraphproperties}
+
+\unexpanded\def\popparagraphproperties
+ {\popmacro\currentparagraphproperties
+ \currentparagraphproperties}
+
+\unexpanded\def\flushparagraphproperties
+ {\popmacro\currentparagraphproperties}
+
+% Beware, changing this will break some code (like pos/backgrounds) but
+% it has been changed anyway so let's see where things go wrong.
+
+\installcorenamespace{paragraphintro}
+
+\let\insertparagraphintro\relax % hook into everypar
+
+\newtoks\t_spac_paragraphs_intro_first
+\newtoks\t_spac_paragraphs_intro_next
+\newtoks\t_spac_paragraphs_intro_each
+
+\newconditional\c_spac_paragraphs_intro_first
+\newconditional\c_spac_paragraphs_intro_next
+\newconditional\c_spac_paragraphs_intro_each
+
+\unexpanded\def\setupparagraphintro
+ {\dodoubleempty\spac_paragraphs_intro}
+
+\unexpanded\def\spac_paragraphs_intro[#1][#2]%
+ {\def\spac_paragraphs_intro_step##1%
+ {\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}%
+ \processcommacommand[#1]\spac_paragraphs_intro_step}
+
+\letvalue{\??paragraphintro\empty}\gobbleoneargument
+
+\setvalue{\??paragraphintro\v!reset}#1%
+ {\global\setfalse\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_next
+ \global\setfalse\c_spac_paragraphs_intro_each
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \global\t_spac_paragraphs_intro_next \emptytoks
+ \global\t_spac_paragraphs_intro_each \emptytoks
+ \glet\insertparagraphintro\relax}
+
+\setvalue{\??paragraphintro\v!first}#1%
+ {\global\settrue\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+\setvalue{\??paragraphintro\v!next}#1%
+ {\global\settrue\c_spac_paragraphs_intro_next
+ \global\t_spac_paragraphs_intro_next\expandafter{\the\t_spac_paragraphs_intro_next#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+\setvalue{\??paragraphintro\v!each}#1%
+ {\global\settrue\c_spac_paragraphs_intro_each
+ \global\t_spac_paragraphs_intro_each\expandafter{\the\t_spac_paragraphs_intro_each#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+%D We can say:
+%D
+%D \starttyping
+%D \setupparagraphintro[first][\index{Knuth}]
+%D \stoptyping
+%D
+%D Maybe more convenient is:
+%D
+%D \starttyping
+%D \flushatparagraph{\index{Zapf}}
+%D \stoptyping
+%D
+%D \starttyping
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt FIRST \hss}]
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt TSRIF \hss}]
+%D \setupparagraphintro[next] [\hbox to 3.5em{\tt NEXT \hss}]
+%D \setupparagraphintro[next] [\hbox to 3.5em{\tt TXEN \hss}]
+%D \setupparagraphintro[each] [\hbox to 3.0em{\tt EACH \hss}]
+%D \setupparagraphintro[each] [\hbox to 3.0em{\tt HCEA \hss}]
+%D
+%D some paragraph \par
+%D some paragraph \par
+%D some paragraph \par
+%D some paragraph \par
+%D
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt FIRST \hss}]
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt TSRIF \hss}]
+%D
+%D some paragraph \par
+%D some paragraph \par
+%D
+%D \setupparagraphintro[reset]
+%D
+%D some paragraph \par
+%D \stoptyping
+
+\unexpanded\def\flushatparagraph#1%
+ {\global\c_spac_paragraphs_intro_first\plusone
+ \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+%D Here comes the flusher (we misuse the one level expansion of token
+%D registers to feed a nice stream into the paragraph.)
+
+\unexpanded\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly after another
+ {\normalexpanded{% % so the first code is there twice
+ \ifconditional\c_spac_paragraphs_intro_each
+ \ifconditional\c_spac_paragraphs_intro_next
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_next
+ \else
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_each
+ \fi
+ \ifconditional\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \the\t_spac_paragraphs_intro_first
+ \fi
+ \the\t_spac_paragraphs_intro_each
+ \else
+ \ifconditional\c_spac_paragraphs_intro_next
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_next
+ \fi
+ \ifconditional\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \the\t_spac_paragraphs_intro_first
+ \fi
+ \fi}}
+
+\unexpanded\def\spac_paragraphs_flush_intro_next
+ {\normalexpanded{%
+ \global\setfalse\c_spac_paragraphs_intro_next
+ \global\t_spac_paragraphs_intro_next\emptytoks
+ \ifconditional\c_spac_paragraphs_intro_each
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_each
+ \the\t_spac_paragraphs_intro_next
+ \the\t_spac_paragraphs_intro_each
+ \else
+ \glet\insertparagraphintro\relax
+ \the\t_spac_paragraphs_intro_next
+ \fi}}
+
+\unexpanded\def\spac_paragraphs_flush_intro_each
+ {\the\t_spac_paragraphs_intro_each}
+
+%D \macros
+%D {flushatnextpar}
+%D
+%D This macro collects data that will be flushed at the next paragraph.
+%D By using this macro you can avoid interfering nodes (writes, etc).
+
+\let\flushpostponednodedata\relax % hook into everypar
+
+\newbox \b_spac_postponed_data
+%newcount\c_spac_postponed_data
+
+% \installcorenamespace {postponednodesstack}
+%
+% \initializeboxstack\??postponednodesstack
+%
+% \unexpanded\def\pushpostponednodedata
+% {\global\advance\c_spac_postponed_data\plusone
+% \savebox\??postponednodesstack{\the\c_spac_postponed_data}{\box\b_spac_postponed_data}}
+%
+% \unexpanded\def\poppostponednodedata
+% {\global\setbox\b_spac_postponed_data\hbox{\foundbox\??postponednodesstack{\the\c_spac_postponed_data}}%
+% \global\advance\c_spac_postponed_data\minusone
+% \ifvoid\b_spac_postponed_data\else
+% \glet\flushpostponednodedata\spac_postponed_data_flush
+% \fi}
+
+\newtoks\everyflushatnextpar
+
+\unexpanded\def\pushpostponednodedata
+ {\globalpushbox\b_spac_postponed_data}
+
+\unexpanded\def\poppostponednodedata
+ {\globalpopbox\b_spac_postponed_data
+ \ifvoid\b_spac_postponed_data\else
+ \glet\flushpostponednodedata\spac_postponed_data_flush
+ \fi}
+
+\unexpanded\def\flushatnextpar
+ {\begingroup
+ \the\everyflushatnextpar
+ \glet\flushpostponednodedata\spac_postponed_data_flush
+ \dowithnextboxcs\spac_postponed_data_finish\hbox}
+
+\def\spac_postponed_data_finish
+ {\global\setbox\b_spac_postponed_data\hbox % 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
+ \fi
+ \glet\flushpostponednodedata\relax
+ }%\fi}
+
+\unexpanded\def\doflushatpar
+ {\ifvmode
+ \expandafter\flushatnextpar
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua
new file mode 100644
index 00000000000..39d90794cce
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua
@@ -0,0 +1,943 @@
+ if not modules then modules = { } end modules ['spac-prf'] = {
+ version = 1.001,
+ comment = "companion to spac-prf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is a playground, a byproduct of some experiments in a project where
+-- we needed something like this where it works ok, but nevertheless it's
+-- still experimental code. It is very likely to change (or extended).
+
+local unpack, rawget = unpack, rawget
+
+local formatters = string.formatters
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local listcodes = nodes.listcodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local unset_code = nodecodes.unset
+local math_code = nodecodes.math
+local rule_code = nodecodes.rule
+local marginkern_code = nodecodes.marginkern
+
+local leaders_code = gluecodes.leaders
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local line_code = listcodes.line
+local parskip_code = listcodes.parskip
+
+local texlists = tex.lists
+local gettexdimen = tex.getdimen
+local settexattribute = tex.setattribute
+local settexbox = tex.setbox
+local taketexbox = tex.takebox
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nuts.tonode
+
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local gettexbox = nuts.getbox
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setattr = nuts.setattr
+
+local theprop = nuts.theprop
+
+local floor = math.floor
+local ceiling = math.ceil
+
+local new_rule = nuts.pool.rule
+local new_glue = nuts.pool.glue
+local new_kern = nuts.pool.kern
+local hpack_nodes = nuts.hpack
+local link_nodes = nuts.link
+local find_node_tail = nuts.tail
+local setglue = nuts.setglue
+
+local properties = nodes.properties.data
+
+local a_visual = attributes.private("visual")
+local a_snapmethod = attributes.private("snapmethod")
+local a_profilemethod = attributes.private("profilemethod")
+local a_specialcontent = attributes.private("specialcontent")
+
+local variables = interfaces.variables
+local v_none = variables.none
+local v_fixed = variables.fixed
+local v_strict = variables.strict
+
+local setcolor = nodes.tracers.colors.set
+local settransparency = nodes.tracers.transparencies.set
+
+local profiling = { }
+builders.profiling = profiling
+
+local report = logs.reporter("profiling")
+
+local show_profile = false trackers.register("profiling.show", function(v) show_profile = v end)
+local trace_profile = false trackers.register("profiling.trace",function(v) trace_profile = v end)
+
+local function getprofile(line,step)
+
+ -- only l2r
+ -- no hz yet
+
+ local line = tonut(line)
+ local current = getlist(line)
+
+ if not current then
+ return
+ end
+
+ local glue_sign = getfield(line,"glue_sign")
+ local glue_order = getfield(line,"glue_order")
+ local glue_set = getfield(line,"glue_set")
+
+ local heights = { }
+ local depths = { }
+ local width = 0
+ local position = 0
+ local step = step or 65536 -- * 2 -- 2pt
+ local margin = step / 4
+ local min = 0
+ local max = ceiling(getfield(line,"width")/step) + 1
+
+ for i=min,max do
+ heights[i] = 0
+ depths [i] = 0
+ end
+
+ -- remember p
+
+ local wd, ht, dp = 0, 0, 0
+
+ local function progress()
+ position = width
+ width = position + wd
+ p = floor((position - margin)/step + 0.5)
+ w = floor((width + margin)/step - 0.5)
+ if p < 0 then
+ p = 0
+ end
+ if w < 0 then
+ w = 0
+ end
+ if p > w then
+ w, p = p, w
+ end
+ if w > max then
+ for i=max+1,w+1 do
+ heights[i] = 0
+ depths [i] = 0
+ end
+ max = w
+ end
+ for i=p,w do
+ if ht > heights[i] then
+ heights[i] = ht
+ end
+ if dp > depths[i] then
+ depths[i] = dp
+ end
+ end
+ end
+
+ local function process(current) -- called nested in disc replace
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ wd = getfield(current,"width")
+ ht = getfield(current,"height")
+ dp = getfield(current,"depth")
+ progress()
+ elseif id == kern_code then
+ wd = getfield(current,"kern")
+ ht = 0
+ dp = 0
+ progress()
+ elseif id == disc_code then
+ local replace = getfield(current,"replace")
+ if replace then
+ process(replace)
+ end
+ elseif id == glue_code then
+ wd = getfield(current,"width")
+ if glue_sign == 1 then
+ if getfield(current,"stretch_order") == glue_order then
+ wd = wd + getfield(current,"stretch") * glue_set
+ end
+ elseif glue_sign == 2 then
+ if getfield(current,"shrink_order") == glue_order then
+ wd = wd - getfield(current,"shrink") * glue_set
+ end
+ end
+ if getsubtype(current) >= leaders_code then
+ local leader = getleader(current)
+ ht = getfield(leader,"height")
+ dp = getfield(leader,"depth")
+ else
+ ht = 0
+ dp = 0
+ end
+ progress()
+ elseif id == hlist_code then
+ -- we could do a nested check .. but then we need to push / pop glue
+ local shift = getfield(current,"shift")
+ wd = getfield(current,"width")
+ if getattr(current,a_specialcontent) then
+ -- like a margin note, maybe check for wd
+ ht = 0
+ dp = 0
+ else
+ ht = getfield(current,"height") - shift
+ dp = getfield(current,"depth") + shift
+ end
+ progress()
+ elseif id == vlist_code or id == unset_code then
+ local shift = getfield(current,"shift") -- todo
+ wd = getfield(current,"width")
+ ht = getfield(current,"height") -- - shift
+ dp = getfield(current,"depth") -- + shift
+ progress()
+ elseif id == rule_code then
+ wd = getfield(current,"width")
+ ht = getfield(current,"height")
+ dp = getfield(current,"depth")
+ progress()
+ elseif id == math_code then
+ wd = getfield(current,"surround")
+ ht = 0
+ dp = 0
+ progress()
+ elseif id == marginkern_code then
+ wd = getfield(current,"width")
+ ht = 0
+ dp = 0
+ progress()
+ else
+-- print(nodecodes[id])
+ end
+ current = getnext(current)
+ end
+ end
+
+ process(current)
+
+ return {
+ heights = heights,
+ depths = depths,
+ min = min, -- not needed
+ max = max,
+ step = step,
+ }
+
+end
+
+profiling.get = getprofile
+
+local function getpagelist()
+ local pagehead = texlists.page_head
+ if pagehead then
+ pagehead = tonut(texlists.page_head)
+ pagetail = find_node_tail(pagehead)
+ else
+ pagetail = nil
+ end
+ return pagehead, pagetail
+end
+
+local function setprofile(n,step)
+ local p = rawget(properties,n)
+ if p then
+ local pp = p.profile
+ if not pp then
+ pp = getprofile(n,step)
+ p.profile = pp
+ end
+ return pp
+ else
+ local pp = getprofile(n,step)
+ properties[n] = { profile = pp }
+ return pp
+ end
+end
+
+local function hasprofile(n)
+ local p = rawget(properties,n)
+ if p then
+ return p.profile
+ end
+end
+
+local function addstring(height,depth)
+ local typesetters = nuts.typesetters
+ local hashes = fonts.hashes
+ local infofont = fonts.infofont()
+ local emwidth = hashes.emwidths [infofont]
+ local exheight = hashes.exheights[infofont]
+ local httext = height
+ local dptext = depth
+ local httext = typesetters.tohpack(height,infofont)
+ local dptext = typesetters.tohpack(depth,infofont)
+ setfield(httext,"shift",- 1.2 * exheight)
+ setfield(dptext,"shift", 0.6 * exheight)
+ local text = nuts.hpack(
+ nuts.linked(
+ new_kern(-getfield(httext,"width")-emwidth),
+ httext,
+ new_kern(-getfield(dptext,"width")),
+ dptext
+ )
+ )
+ setfield(text,"height",0)
+ setfield(text,"depth",0)
+ setfield(text,"width",0)
+ return text
+end
+
+local function addprofile(node,profile,step)
+
+ local line = tonut(node)
+
+ if not profile then
+ profile = setprofile(line,step)
+ end
+
+ if not profile then
+ report("some error")
+ return node
+ end
+
+ if profile.shown then
+ return node
+ end
+
+ local list = getlist(line)
+ profile.shown = true
+
+ local heights = profile.heights
+ local depths = profile.depths
+ local step = profile.step
+
+ local head = nil
+ local tail = nil
+
+ local lastht = 0
+ local lastdp = 0
+ local lastwd = 0
+
+ local visual = "f:s:t" -- this can change !
+
+ local function progress()
+ if lastwd == 0 then
+ return
+ end
+ local what = nil
+ if lastht == 0 and lastdp == 0 then
+ what = new_kern(lastwd)
+ else
+ what = new_rule(lastwd,lastht,lastdp)
+ setcolor(what,visual)
+ settransparency(what,visual)
+ end
+ if tail then
+ setlink(tail,what)
+ else
+ head = what
+ end
+ tail = what
+ end
+
+-- inspect(profile)
+
+ for i=profile.min,profile.max do
+ local ht = heights[i]
+ local dp = depths[i]
+ if ht ~= lastht or dp ~= lastdp and lastwd > 0 then
+ progress()
+ lastht = ht
+ lastdp = dp
+ lastwd = step
+ else
+ lastwd = lastwd + step
+ end
+ end
+ if lastwd > 0 then
+ progress()
+ end
+
+ local rule = hpack_nodes(head)
+
+ setfield(rule,"width", 0)
+ setfield(rule,"height",0)
+ setfield(rule,"depth", 0)
+
+ -- if texttoo then
+ --
+ -- local text = addstring(
+ -- formatters["%0.4f"](getfield(rule,"height")/65536),
+ -- formatters["%0.4f"](getfield(rule,"depth") /65536)
+ -- )
+ --
+ -- setlink(text,rule)
+ --
+ -- rule = text
+ --
+ -- end
+
+ setlink(rule,list)
+ setlist(line,rule)
+
+end
+
+profiling.add = addprofile
+
+local methods = { }
+
+local function getdelta(t_profile,b_profile)
+ local t_heights = t_profile.heights
+ local t_depths = t_profile.depths
+ local t_max = t_profile.max
+ local b_heights = b_profile.heights
+ local b_depths = b_profile.depths
+ local b_max = b_profile.max
+
+ local max = t_max
+ local delta = 0
+
+ if t_max > b_max then
+ for i=b_max+1,t_max do
+ b_depths [i] = 0
+ b_heights[i] = 0
+ end
+ max = t_max
+ elseif b_max > t_max then
+ for i=t_max+1,b_max do
+ t_depths [i] = 0
+ t_heights[i] = 0
+ end
+ max = b_max
+ end
+
+ for i=0,max do
+ local ht = b_heights[i]
+ local dp = t_depths[i]
+ local hd = ht + dp
+ if hd > delta then
+ delta = hd
+ end
+ end
+
+ return delta
+end
+
+-- local properties = theprop(bot)
+-- local unprofiled = properties.unprofiled
+-- if not unprofiled then -- experiment
+-- properties.unprofiled = {
+-- height = height,
+-- strutht = strutht,
+-- }
+-- end
+
+-- lineskip | lineskiplimit
+
+local function inject(top,bot,amount) -- todo: look at penalties
+ local glue = new_glue(amount)
+ --
+ setattr(glue,a_profilemethod,0)
+ setattr(glue,a_visual,getattr(top,a_visual))
+ --
+ setlink(glue,bot)
+ setlink(top,glue)
+end
+
+methods[v_none] = function()
+ return false
+end
+
+methods[v_strict] = function(top,bot,t_profile,b_profile,specification)
+
+ local top = tonut(top)
+ local bot = tonut(bot)
+
+ local strutht = specification.height or texdimen.strutht
+ local strutdp = specification.depth or texdimen.strutdp
+ local lineheight = strutht + strutdp
+
+ local depth = getfield(top,"depth")
+ local height = getfield(bot,"height")
+ local total = depth + height
+ local distance = specification.distance or 0
+ local delta = lineheight - total
+
+ -- there is enough room between the lines so we don't need
+ -- to add extra distance
+
+ if delta >= distance then
+ inject(top,bot,delta)
+ return true
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+ local skip = delta - total + distance
+
+ -- we don't want to be too tight so we limit the skip and
+ -- make sure we have at least lineheight
+
+ inject(top,bot,skip)
+ return true
+
+end
+
+-- todo: also set ht/dp of first / last (but what is that)
+
+methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
+
+ local top = tonut(top)
+ local bot = tonut(bot)
+
+ local strutht = specification.height or texdimen.strutht
+ local strutdp = specification.depth or texdimen.strutdp
+ local lineheight = strutht + strutdp
+
+ local depth = getfield(top,"depth")
+ local height = getfield(bot,"height")
+ local total = depth + height
+ local distance = specification.distance or 0
+ local delta = lineheight - total
+
+ local snapmethod = getattr(top,a_snapmethod)
+
+ if snapmethod then
+
+ -- no distance (yet)
+
+ if delta < lineheight then
+ setfield(top,"depth",strutdp)
+ setfield(bot,"height",strutht)
+ return true
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+
+ local dp = strutdp
+ while depth > lineheight - strutdp do
+ depth = depth - lineheight
+ dp = dp + lineheight
+ end
+ setfield(top,"depth",dp)
+ local ht = strutht
+ while height > lineheight - strutht do
+ height = height - lineheight
+ ht = ht + lineheight
+ end
+ setfield(bot,"height",ht)
+ local lines = floor(delta/lineheight)
+ if lines > 0 then
+ inject(top,bot,-lines * lineheight)
+ end
+
+ return true
+
+ end
+
+ if total < lineheight then
+ setfield(top,"depth",strutdp)
+ setfield(bot,"height",strutht)
+ return true
+ end
+
+ if depth < strutdp then
+ setfield(top,"depth",strutdp)
+ total = total - depth + strutdp
+ end
+ if height < strutht then
+ setfield(bot,"height",strutht)
+ total = total - height + strutht
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+
+ local target = total - delta
+ local factor = specification.factor or 1
+ local step = lineheight / factor
+ local correction = 0
+ local nofsteps = 0
+ while correction < target - step - distance do -- a loop is more accurate, for now
+ correction = correction + step
+ nofsteps = nofsteps + 1
+ end
+
+ if trace_profile then
+ report("top line : %s %05i > %s",t_profile.shown and "+" or "-",top,nodes.toutf(getlist(top)))
+ report("bottom line : %s %05i > %s",b_profile.shown and "+" or "-",bot,nodes.toutf(getlist(bot)))
+ report(" depth : %p",depth)
+ report(" height : %p",height)
+ report(" total : %p",total)
+ report(" lineheight : %p",lineheight)
+ report(" delta : %p",delta)
+ report(" target : %p",target)
+ report(" factor : %i",factor)
+ report(" distance : %p",distance)
+ report(" step : %p",step)
+ report(" nofsteps : %i",nofsteps)
+ -- report(" max lines : %s",lines == 0 and "unset" or lines)
+ report(" correction : %p",correction)
+ end
+
+ inject(top,bot,-correction) -- we could mess with the present glue (if present)
+
+ return true -- remove interlineglue
+
+end
+
+function profiling.distance(top,bot,specification)
+ local step = specification.step
+ local method = specification.method
+ local ptop = getprofile(top,step)
+ local pbot = getprofile(bot,step)
+ local action = methods[method or v_strict] or methods[v_strict]
+ return action(top,bot,ptop,pbot,specification)
+end
+
+local specifications = { } -- todo: save these !
+
+function profiling.fixedprofile(current)
+ local a = getattr(current,a_profilemethod)
+ if a then
+ local s = specifications[a]
+ if s then
+ return s.method == v_fixed
+ end
+ end
+ return false
+end
+
+local function profilelist(line,mvl)
+
+ local current = tonut(line)
+
+ local top = nil
+ local bot = nil
+
+ local t_profile = nil
+ local b_profile = nil
+
+ local specification = nil
+ local lastattr = nil
+ local method = nil
+ local action = nil
+
+ local distance = 0
+ local lastglue = nil
+
+ local pagehead = nil
+ local pagetail = nil
+
+ if mvl then
+
+ pagehead, pagetail = getpagelist()
+
+ if pagetail then
+ local current = pagetail
+ while current do
+ local id = getid(current)
+ if id == hlist_code then
+ local subtype = getsubtype(current)
+ if subtype == line_code then
+ t_profile = hasprofile(current)
+ if t_profile then
+ top = current
+ end
+ end
+ break
+ elseif id == glue_code then
+ local wd = getfield(current,"width")
+ if not wd or wd == 0 then
+ -- go on
+ else
+ break
+ end
+ elseif id == penalty_code then
+ -- ok
+ else
+ break
+ end
+ current = getnext(current)
+ end
+ end
+
+ end
+
+ while current do
+
+ local attr = getattr(current,a_profilemethod)
+
+ if attr then
+
+ if attr ~= lastattr then
+ specification = specifications[attr]
+ method = specification and specification.method
+ action = method and methods[method] or methods[v_strict]
+ lastattr = attr
+ end
+
+ local id = getid(current)
+
+ if id == hlist_code then -- check subtype
+ local subtype = getsubtype(current)
+ if subtype == line_code then
+ if top == current then
+ -- skip
+ bot = nil -- to be sure
+ elseif top then
+ bot = current
+ b_profile = setprofile(bot)
+ if show_profile then
+ addprofile(bot,b_profile)
+ end
+ if not t_profile.done then
+ if action then
+ local ok = action(top,bot,t_profile,b_profile,specification)
+ if ok and lastglue and distance ~= 0 then
+ setglue(lastglue)
+ end
+ end
+ t_profile.done = true
+ end
+ top = bot
+ bot = nil
+ t_profile = b_profile
+ b_profile = nil
+ distance = 0
+ else
+ top = current
+ t_profile = setprofile(top)
+ bot = nil
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == glue_code then
+ if top then
+ local subtype = getsubtype(current)
+ -- if subtype == lineskip_code or subtype == baselineskip_code then
+ local wd = getfield(current,"width")
+ if wd > 0 then
+ distance = wd
+ lastglue = current
+ elseif wd < 0 then
+ top = nil
+ bot = nil
+ else
+ -- ok
+ end
+ -- else
+ -- top = nil
+ -- bot = nil
+ -- end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == penalty_code then
+ -- okay
+ else
+ top = nil
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ current = getnext(current)
+ end
+ if top then
+ t_profile = setprofile(top)
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+end
+
+profiling.list = profilelist
+
+local enabled = false
+
+function profiling.set(specification)
+ if not enabled then
+ nodes.tasks.enableaction("mvlbuilders", "builders.profiling.pagehandler")
+ -- too expensive so we expect that this happens explicitly, we keep for reference:
+ -- nodes.tasks.enableaction("vboxbuilders","builders.profiling.vboxhandler")
+ enabled = true
+ end
+ local n = #specifications + 1
+ specifications[n] = specification
+ settexattribute(a_profilemethod,n)
+end
+
+function profiling.profilebox(specification)
+ local boxnumber = specification.box
+ local current = getlist(gettexbox(boxnumber))
+ local top = nil
+ local bot = nil
+ local t_profile = nil
+ local b_profile = nil
+ local method = specification and specification.method
+ local action = method and methods[method] or methods[v_strict]
+ local lastglue = nil
+ local distance = 0
+ while current do
+ local id = getid(current)
+ if id == hlist_code then
+ local subtype = getsubtype(current)
+ if subtype == line_code then
+ if top then
+ bot = current
+ b_profile = setprofile(bot)
+ if show_profile then
+ addprofile(bot,b_profile)
+ end
+ if not t_profile.done then
+ if action then
+ local ok = action(top,bot,t_profile,b_profile,specification)
+ if ok and lastglue and distance ~= 0 then
+ setglue(lastglue)
+ end
+ end
+ t_profile.done = true
+ end
+ top = bot
+ t_profile = b_profile
+ b_profile = nil
+ distance = 0
+ else
+ top = current
+ t_profile = setprofile(top)
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == glue_code then
+ local subtype = getsubtype(current)
+ if subtype == lineskip_code or subtype == baselineskip_code then
+ if top then
+ local wd = getfield(current,"width")
+ if wd > 0 then
+ distance = wd
+ lastglue = current
+ elseif wd < 0 then
+ top = nil
+ bot = nil
+ else
+ -- ok
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == penalty_code then
+ -- okay
+ else
+ top = nil
+ bot = nil
+ end
+ current = getnext(current)
+ end
+
+ if top then
+ t_profile = setprofile(top) -- not needed
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+
+end
+
+local ignore = table.tohash {
+ "split_keep",
+ "split_off",
+ -- "vbox",
+}
+
+-- function profiling.vboxhandler(head,where)
+-- if head and not ignore[where] then
+-- local h = tonut(head)
+-- if getnext(h) then
+-- profilelist(h)
+-- end
+-- end
+-- return head
+-- end
+
+function profiling.pagehandler(head)
+ if head then
+ profilelist(head,true)
+ end
+ return head, true
+end
+
+interfaces.implement {
+ name = "setprofile",
+ actions = profiling.set,
+ arguments = {
+ {
+ { "name" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "distance", "dimen" },
+ { "factor", "integer" },
+ { "lines", "integer" },
+ { "method" }
+ }
+ }
+}
+
+interfaces.implement {
+ name = "profilebox",
+ actions = profiling.profilebox,
+ arguments = {
+ {
+ { "box", "integer" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "distance", "dimen" },
+ { "factor", "integer" },
+ { "lines", "integer" },
+ { "method" }
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-prf.mkvi b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.mkvi
new file mode 100644
index 00000000000..8d150f58d4d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.mkvi
@@ -0,0 +1,117 @@
+%D \module
+%D [ file=spac-prf,
+%D version=2015.11.16, % moved from test module mathplus
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Profiling,
+%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 / Profiling}
+
+%D This is experimental code that we need for a project. The interface and
+%D details can change. I moved it into the core because that way we can use
+%D it on servers.
+
+% framed: first reflow then profile
+
+\unprotect
+
+\registerctxluafile{spac-prf}{1.001}
+
+\definesystemattribute[profilemethod][public]
+
+\installcorenamespace {profile} % beware, profiles are not like in mkii at all
+\installcorenamespace {profiles}
+
+\installcommandhandler \??profile {profile} \??profile
+
+\setupprofile
+ [\c!height=\strutht,
+ \c!depth=\strutdp,
+ \c!distance=\normallineskip,
+ \c!lines=\zerocount,
+ \c!factor=\plusone]
+
+\defineprofile
+ [\v!strict]
+ [\c!method=\v!strict]
+
+\defineprofile
+ [\v!fixed]
+ [\c!method=\v!fixed]
+
+\defineprofile
+ [\v!none]
+ [\c!method=\v!none,
+ \c!height=\zeropoint,
+ \c!depth=\zeropoint,
+ \c!distance=\zeropoint,
+ \c!factor=\plusone]
+
+\defineprofile[halffixed] [\v!fixed][\c!factor=\plustwo]
+\defineprofile[quarterfixed][\v!fixed][\c!factor=\plusfour]
+\defineprofile[eightsfixed] [\v!fixed][\c!factor=\pluseight]
+
+\unexpanded\def\setprofile[#profile]%
+ {\edef\currentprofile{#profile}%
+ \clf_setprofile
+ name {\currentprofile}%
+ height \dimexpr\profileparameter\c!height\relax
+ depth \dimexpr\profileparameter\c!depth\relax
+ distance \dimexpr\profileparameter\c!distance\relax
+ factor \numexpr\profileparameter\c!factor\relax
+ lines \numexpr\profileparameter\c!lines\relax
+ method {\profileparameter\c!method}%
+ \relax}
+
+\unexpanded\def\resetprofile
+ {\attribute\profilemethodattribute\attributeunsetvalue}
+
+\unexpanded\def\useprofileparameter#getparameter%
+ {\edef\m_spac_profile_asked{#getparameter\c!profile}%
+ \ifx\m_spac_profile_asked\empty
+ \resetprofile
+ \else
+ \setprofile[\m_spac_profile_asked]%
+ \fi}
+
+\unexpanded\def\profiledbox
+ {\vbox\bgroup
+ \dodoubleempty\spac_profiling_box}
+
+\def\spac_profiling_box[#profile][#settings]%
+ {\ifsecondargument
+ \edef\currentprofile{#profile}%
+ \setupcurrentprofile[#settings]%
+ \else
+ \doifassignmentelse{#profile}
+ {\let\currentprofile\v!none
+ \setupcurrentprofile[#profile]}%
+ {\edef\currentprofile{#profile}}%
+ \fi
+ \dowithnextbox
+ {\profilegivenbox\currentprofile\nextbox
+ \unvbox\nextbox
+ \egroup}%
+ \vbox}
+
+\unexpanded\def\profilegivenbox#profile#box%
+ {\begingroup
+ \edef\currentprofile{#profile}%
+ \clf_profilebox
+ box \numexpr#box\relax
+ height \dimexpr\profileparameter\c!height\relax
+ depth \dimexpr\profileparameter\c!depth\relax
+ distance \dimexpr\profileparameter\c!distance\relax
+ factor \numexpr\profileparameter\c!factor\relax
+ lines \numexpr\profileparameter\c!lines\relax
+ method {\profileparameter\c!method}%
+ \relax
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua
new file mode 100644
index 00000000000..e81e8b81d16
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua
@@ -0,0 +1,2028 @@
+if not modules then modules = { } end modules ['spac-ver'] = {
+ version = 1.001,
+ comment = "companion to spac-ver.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we also need to call the spacer for inserts!
+
+-- somehow lists still don't always have proper prev nodes so i need to
+-- check all of the luatex code some day .. maybe i should replece the
+-- whole mvl handler by lua code .. why not
+
+-- todo: use lua nodes with lua data (>0.79)
+-- see ** can go when 0.79
+
+-- needs to be redone, too many calls and tests now ... still within some
+-- luatex limitations
+
+-- this code dates from the beginning and is kind of experimental; it
+-- will be optimized and improved soon .. it's way too complex now but
+-- dates from less possibilities
+--
+-- the collapser will be redone with user nodes; also, we might get make
+-- parskip into an attribute and appy it explicitly thereby getting rid
+-- of automated injections; eventually i want to get rid of the currently
+-- still needed tex -> lua -> tex > lua chain (needed because we can have
+-- expandable settings at the tex end
+
+-- todo: strip baselineskip around display math
+
+local next, type, tonumber = next, type, tonumber
+local gmatch, concat = string.gmatch, table.concat
+local ceil, floor = math.ceil, math.floor
+local lpegmatch = lpeg.match
+local unpack = unpack or table.unpack
+local allocate = utilities.storage.allocate
+local todimen = string.todimen
+local formatters = string.formatters
+
+local P, C, R, S, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Carg
+
+local nodes = nodes
+local node = node
+local trackers = trackers
+local attributes = attributes
+local context = context
+local tex = tex
+
+local texlists = tex.lists
+local texgetdimen = tex.getdimen
+local texsetdimen = tex.setdimen
+local texnest = tex.nest
+
+local variables = interfaces.variables
+local implement = interfaces.implement
+
+-- vertical space handler
+
+local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end)
+local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end)
+local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end)
+local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end)
+local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end)
+local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end)
+local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end)
+
+local report_vspacing = logs.reporter("vspacing","spacing")
+local report_collapser = logs.reporter("vspacing","collapsing")
+local report_snapper = logs.reporter("vspacing","snapping")
+local report_specials = logs.reporter("vspacing","specials")
+local report_page_builder = logs.reporter("builders","page")
+
+local a_skipcategory = attributes.private('skipcategory')
+local a_skippenalty = attributes.private('skippenalty')
+local a_skiporder = attributes.private('skiporder')
+----- snap_category = attributes.private('snapcategory')
+local a_snapmethod = attributes.private('snapmethod')
+local a_snapvbox = attributes.private('snapvbox')
+local a_profilemethod = attributes.private("profilemethod")
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+local ntostring = nuts.tostring
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local setlink = nuts.setlink
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+
+local find_node_tail = nuts.tail
+local free_node = nuts.free
+local free_node_list = nuts.flush_list
+local traverse_nodes = nuts.traverse
+local traverse_nodes_id = nuts.traverse_id
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+local count_nodes = nuts.count
+local hpack_node = nuts.hpack
+local vpack_node = nuts.vpack
+----- writable_spec = nuts.writable_spec
+local nodereference = nuts.reference
+
+local theprop = nuts.theprop
+
+local listtoutf = nodes.listtoutf
+local nodeidstostring = nodes.idstostring
+
+local nodepool = nuts.pool
+
+local new_penalty = nodepool.penalty
+local new_kern = nodepool.kern
+local new_rule = nodepool.rule
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local localpar_code = nodecodes.localpar
+
+local userskip_code = skipcodes.userskip
+local lineskip_code = skipcodes.lineskip
+local baselineskip_code = skipcodes.baselineskip
+local parskip_code = skipcodes.parskip
+local abovedisplayskip_code = skipcodes.abovedisplayskip
+local belowdisplayskip_code = skipcodes.belowdisplayskip
+local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip
+local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip
+local topskip_code = skipcodes.topskip
+local splittopskip_code = skipcodes.splittopskip
+
+local vspacing = builders.vspacing or { }
+builders.vspacing = vspacing
+
+local vspacingdata = vspacing.data or { }
+vspacing.data = vspacingdata
+
+local snapmethods = vspacingdata.snapmethods or { }
+vspacingdata.snapmethods = snapmethods
+
+storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods")
+
+local default = {
+ maxheight = true,
+ maxdepth = true,
+ strut = true,
+ hfraction = 1,
+ dfraction = 1,
+ bfraction = 0.25,
+}
+
+local fractions = {
+ minheight = "hfraction", maxheight = "hfraction",
+ mindepth = "dfraction", maxdepth = "dfraction",
+ box = "bfraction",
+ top = "tlines", bottom = "blines",
+}
+
+local values = {
+ offset = "offset"
+}
+
+local colonsplitter = lpeg.splitat(":")
+
+local function listtohash(str)
+ local t = { }
+ for s in gmatch(str,"[^, ]+") do
+ local key, detail = lpegmatch(colonsplitter,s)
+ local v = variables[key]
+ if v then
+ t[v] = true
+ if detail then
+ local k = fractions[key]
+ if k then
+ detail = tonumber("0" .. detail)
+ if detail then
+ t[k] = detail
+ end
+ else
+ k = values[key]
+ if k then
+ detail = todimen(detail)
+ if detail then
+ t[k] = detail
+ end
+ end
+ end
+ end
+ else
+ detail = tonumber("0" .. key)
+ if detail then
+ t.hfraction, t.dfraction = detail, detail
+ end
+ end
+ end
+ if next(t) then
+ t.hfraction = t.hfraction or 1
+ t.dfraction = t.dfraction or 1
+ return t
+ else
+ return default
+ end
+end
+
+function vspacing.definesnapmethod(name,method)
+ local n = #snapmethods + 1
+ local t = listtohash(method)
+ snapmethods[n] = t
+ t.name, t.specification = name, method
+ context(n)
+end
+
+-- local rule_id = nodecodes.rule
+-- local vlist_id = nodecodes.vlist
+-- function nodes.makevtop(n)
+-- if getid(n) == vlist_id then
+-- local list = getlist(n)
+-- local height = (list and getid(list) <= rule_id and getfield(list,"height")) or 0
+-- setfield(n,"depth",getfield(n,"depth") - height + getfield(n,"height")
+-- setfield(n,"height",height
+-- end
+-- 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
+ 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)
+ if id == vlist_code or id == hlist_code then
+ if done then
+ return nil
+ else
+ done = n
+ end
+ elseif id == glue_code or id == penalty_code then
+ -- go on
+ else
+ return nil -- whatever
+ end
+ end
+ if done then
+ local id = getid(done)
+ if id == hlist_code then
+ return validvbox(id,getlist(done))
+ end
+ end
+ return done -- only one vbox
+ end
+end
+
+local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped
+ -- problem: any snapped vbox ends up in a line
+ if list and parentid == hlist_code then
+ local id = getid(list)
+ if id == localpar_code then -- check for initial par subtype
+ list = getnext(list)
+ if not next then
+ return false
+ end
+ end
+--~ local i = 0
+ for n in traverse_nodes(list) do
+ local id = getid(n)
+--~ i = i + 1 print(i,nodecodes[id],getattr(n,a_snapmethod))
+ if id == hlist_code or id == vlist_code then
+ local a = getattr(n,a_snapmethod)
+ if not a then
+ -- return true -- not snapped at all
+ elseif a == 0 then
+ return true -- already snapped
+ end
+ elseif id == glue_code or id == penalty_code then
+ -- go on
+ else
+ return false -- whatever
+ end
+ end
+ end
+ return false
+end
+
+
+-- quite tricky: ceil(-something) => -0
+
+local function ceiled(n)
+ if n < 0 or n < 0.01 then
+ return 0
+ else
+ return ceil(n)
+ end
+end
+
+local function floored(n)
+ if n < 0 or n < 0.01 then
+ return 0
+ else
+ return floor(n)
+ end
+end
+
+-- check variables.none etc
+
+local function fixedprofile(current)
+ local profiling = builders.profiling
+ return profiling and profiling.fixedprofile(current)
+end
+
+local function snap_hlist(where,current,method,height,depth) -- method.strut is default
+ if fixedprofile(current) then
+ return
+ end
+ local list = getlist(current)
+ local t = trace_vsnapping and { }
+ if t then
+ t[#t+1] = formatters["list content: %s"](listtoutf(list))
+ t[#t+1] = formatters["parent id: %s"](nodereference(current))
+ t[#t+1] = formatters["snap method: %s"](method.name)
+ t[#t+1] = formatters["specification: %s"](method.specification)
+ end
+ local snapht, snapdp
+ if method["local"] then
+ -- snapping is done immediately here
+ snapht = texgetdimen("bodyfontstrutheight")
+ snapdp = texgetdimen("bodyfontstrutdepth")
+ if t then
+ t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ elseif method["global"] then
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
+ if t then
+ t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ else
+ -- maybe autolocal
+ -- snapping might happen later in the otr
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
+ local lsnapht = texgetdimen("bodyfontstrutheight")
+ local lsnapdp = texgetdimen("bodyfontstrutdepth")
+ if snapht ~= lsnapht and snapdp ~= lsnapdp then
+ snapht, snapdp = lsnapht, lsnapdp
+ end
+ if t then
+ t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ end
+
+ local h = (method.noheight and 0) or height or getfield(current,"height")
+ local d = (method.nodepth and 0) or depth or getfield(current,"depth")
+ local hr = method.hfraction or 1
+ local dr = method.dfraction or 1
+ local br = method.bfraction or 0
+ local ch = h
+ local cd = d
+ local tlines = method.tlines or 1
+ local blines = method.blines or 1
+ local done = false
+ local plusht = snapht
+ local plusdp = snapdp
+ local snaphtdp = snapht + snapdp
+
+-- local properties = theprop(current)
+-- local unsnapped = properties.unsnapped
+-- if not unsnapped then -- experiment
+-- properties.unsnapped = {
+-- height = h,
+-- depth = d,
+-- snapht = snapht,
+-- snapdp = snapdp,
+-- }
+-- end
+
+ if method.box then
+ local br = 1 - br
+ if br < 0 then
+ br = 0
+ elseif br > 1 then
+ br = 1
+ end
+ local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ elseif method.max then
+ local n = ceiled((h+d)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ elseif method.min then
+ local n = floored((h+d)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ elseif method.none then
+ plusht, plusdp = 0, 0
+ if t then
+ t[#t+1] = "none: plusht 0pt plusdp 0pt"
+ end
+ end
+ if method.halfline then -- extra halfline
+ plusht = plusht + snaphtdp/2
+ plusdp = plusdp + snaphtdp/2
+ if t then
+ t[#t+1] = formatters["halfline: plusht %p plusdp %p"](plusht,plusdp)
+ end
+ end
+ if method.line then -- extra line
+ plusht = plusht + snaphtdp
+ plusdp = plusdp + snaphtdp
+ if t then
+ t[#t+1] = formatters["line: plusht %p plusdp %p"](plusht,plusdp)
+ end
+ end
+
+ if method.first then
+ local thebox = current
+ local id = getid(thebox)
+ if id == hlist_code then
+ thebox = validvbox(id,getlist(thebox))
+ id = thebox and getid(thebox)
+ end
+ if thebox and id == vlist_code then
+ local list = getlist(thebox)
+ local lh, ld
+ for n in traverse_nodes_id(hlist_code,list) do
+ lh = getfield(n,"height")
+ ld = getfield(n,"depth")
+ break
+ end
+ if lh then
+ local ht = getfield(thebox,"height")
+ local dp = getfield(thebox,"depth")
+ if t then
+ t[#t+1] = formatters["first line: height %p depth %p"](lh,ld)
+ t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
+ end
+ local delta = h - lh
+ ch, cd = lh, delta + d
+ h, d = ch, cd
+ local shifted = hpack_node(getlist(current))
+ setfield(shifted,"shift",delta)
+ setlist(current,shifted)
+ done = true
+ if t then
+ t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta)
+ end
+ elseif t then
+ t[#t+1] = "first: not done, no content"
+ end
+ elseif t then
+ t[#t+1] = "first: not done, no vbox"
+ end
+ elseif method.last then
+ local thebox = current
+ local id = getid(thebox)
+ if id == hlist_code then
+ thebox = validvbox(id,getlist(thebox))
+ id = thebox and getid(thebox)
+ end
+ if thebox and id == vlist_code then
+ local list = getlist(thebox)
+ local lh, ld
+ for n in traverse_nodes_id(hlist_code,list) do
+ lh = getfield(n,"height")
+ ld = getfield(n,"depth")
+ end
+ if lh then
+ local ht = getfield(thebox,"height")
+ local dp = getfield(thebox,"depth")
+ if t then
+ t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld)
+ t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
+ end
+ local delta = d - ld
+ cd, ch = ld, delta + h
+ h, d = ch, cd
+ local shifted = hpack_node(getlist(current))
+ setfield(shifted,"shift",delta)
+ setlist(current,shifted)
+ done = true
+ if t then
+ t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta)
+ end
+ elseif t then
+ t[#t+1] = "last: not done, no content"
+ end
+ elseif t then
+ t[#t+1] = "last: not done, no vbox"
+ end
+ end
+ if method.minheight then
+ ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht
+ if t then
+ t[#t+1] = formatters["minheight: %p"](ch)
+ end
+ elseif method.maxheight then
+ ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht
+ if t then
+ t[#t+1] = formatters["maxheight: %p"](ch)
+ end
+ else
+ ch = plusht
+ if t then
+ t[#t+1] = formatters["set height: %p"](ch)
+ end
+ end
+ if method.mindepth then
+ cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp
+ if t then
+ t[#t+1] = formatters["mindepth: %p"](cd)
+ end
+ elseif method.maxdepth then
+ cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp
+ if t then
+ t[#t+1] = formatters["maxdepth: %p"](cd)
+ end
+ else
+ cd = plusdp
+ if t then
+ t[#t+1] = formatters["set depth: %p"](cd)
+ end
+ end
+ if method.top then
+ ch = ch + tlines * snaphtdp
+ if t then
+ t[#t+1] = formatters["top height: %p"](ch)
+ end
+ end
+ if method.bottom then
+ cd = cd + blines * snaphtdp
+ if t then
+ t[#t+1] = formatters["bottom depth: %p"](cd)
+ end
+ end
+
+ local offset = method.offset
+ if offset then
+ -- we need to set the attr
+ if t then
+ t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width") or 0,getfield(current,"height"),getfield(current,"depth"))
+ end
+ local shifted = hpack_node(getlist(current))
+ setfield(shifted,"shift",offset)
+ setlist(current,shifted)
+ if t then
+ t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width") or 0,getfield(current,"height"),getfield(current,"depth"))
+ end
+ setattr(shifted,a_snapmethod,0)
+ setattr(current,a_snapmethod,0)
+ end
+ if not height then
+ setfield(current,"height",ch)
+ if t then
+ t[#t+1] = formatters["forced height: %p"](ch)
+ end
+ end
+ if not depth then
+ setfield(current,"depth",cd)
+ if t then
+ t[#t+1] = formatters["forced depth: %p"](cd)
+ end
+ end
+ local lines = (ch+cd)/snaphtdp
+ if t then
+ local original = (h+d)/snaphtdp
+ local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth"))
+ t[#t+1] = formatters["final lines: %s -> %s (%s)"](original,lines,whatever)
+ t[#t+1] = formatters["final height: %p -> %p"](h,ch)
+ t[#t+1] = formatters["final depth: %p -> %p"](d,cd)
+ end
+-- todo:
+--
+-- if h < 0 or d < 0 then
+-- h = 0
+-- d = 0
+-- end
+ if t then
+ report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t)
+ end
+ return h, d, ch, cd, lines
+end
+
+local function snap_topskip(current,method)
+ local w = getfield(current,"width") or 0
+ setfield(current,"width",0)
+ return w, 0
+end
+
+local categories = allocate {
+ [0] = 'discard',
+ [1] = 'largest',
+ [2] = 'force' ,
+ [3] = 'penalty',
+ [4] = 'add' ,
+ [5] = 'disable',
+ [6] = 'nowhite',
+ [7] = 'goback',
+ [8] = 'together', -- not used (?)
+ [9] = 'overlay',
+ [10] = 'notopskip',
+}
+
+vspacing.categories = categories
+
+function vspacing.tocategories(str)
+ local t = { }
+ for s in gmatch(str,"[^, ]") do -- use lpeg instead
+ local n = tonumber(s)
+ if n then
+ t[categories[n]] = true
+ else
+ t[b] = true
+ end
+ end
+ return t
+end
+
+function vspacing.tocategory(str) -- can be optimized
+ if type(str) == "string" then
+ return set.tonumber(vspacing.tocategories(str))
+ else
+ return set.tonumber({ [categories[str]] = true })
+ end
+end
+
+vspacingdata.map = vspacingdata.map or { } -- allocate ?
+vspacingdata.skip = vspacingdata.skip or { } -- allocate ?
+
+storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map")
+storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip")
+
+do -- todo: interface.variables
+
+ vspacing.fixed = false
+
+ local map = vspacingdata.map
+ local skip = vspacingdata.skip
+
+ local multiplier = C(S("+-")^0 * R("09")^1) * P("*")
+ local separator = S(", ")
+ local category = P(":") * C((1-separator)^1)
+ local keyword = C((1-category-separator)^1)
+ local splitter = (multiplier + Cc(1)) * keyword * (category + Cc(false))
+
+ local k_fixed = variables.fixed
+ local k_flexible = variables.flexible
+ local k_category = "category"
+ local k_penalty = "penalty"
+ local k_order = "order"
+
+ -- This will change: just node.write and we can store the values in skips which
+ -- then obeys grouping .. but .. we miss the amounts then as they live at the tex
+ -- end so we then also need to change that bit ... it would be interesting if we
+ -- could store in properties
+
+ local ctx_fixedblankskip = context.fixedblankskip
+ local ctx_flexibleblankskip = context.flexibleblankskip
+ local ctx_setblankcategory = context.setblankcategory
+ local ctx_setblankorder = context.setblankorder
+ local ctx_setblankpenalty = context.setblankpenalty
+ ----- ctx_setblankhandling = context.setblankhandling
+ local ctx_flushblankhandling = context.flushblankhandling
+ local ctx_addpredefinedblankskip = context.addpredefinedblankskip
+ local ctx_addaskedblankskip = context.addaskedblankskip
+
+ local ctx_pushlogger = context.pushlogger
+ local ctx_startblankhandling = context.startblankhandling
+ local ctx_stopblankhandling = context.stopblankhandling
+ local ctx_poplogger = context.poplogger
+
+ --
+
+ -- local function analyze(str,oldcategory) -- we could use shorter names
+ -- for s in gmatch(str,"([^ ,]+)") do
+ -- local amount, keyword, detail = lpegmatch(splitter,s) -- the comma splitter can be merged
+ -- if not keyword then
+ -- report_vspacing("unknown directive %a",s)
+ -- else
+ -- local mk = map[keyword]
+ -- if mk then
+ -- category = analyze(mk,category) -- category not used .. and we pass crap anyway
+ -- elseif keyword == k_fixed then
+ -- ctx_fixedblankskip()
+ -- elseif keyword == k_flexible then
+ -- ctx_flexibleblankskip()
+ -- elseif keyword == k_category then
+ -- local category = tonumber(detail)
+ -- if category then
+ -- ctx_setblankcategory(category)
+ -- if category ~= oldcategory then
+ -- ctx_flushblankhandling()
+ -- oldcategory = category
+ -- end
+ -- end
+ -- elseif keyword == k_order and detail then
+ -- local order = tonumber(detail)
+ -- if order then
+ -- ctx_setblankorder(order)
+ -- end
+ -- elseif keyword == k_penalty and detail then
+ -- local penalty = tonumber(detail)
+ -- if penalty then
+ -- ctx_setblankpenalty(penalty)
+ -- end
+ -- else
+ -- amount = tonumber(amount) or 1
+ -- local sk = skip[keyword]
+ -- if sk then
+ -- ctx_addpredefinedblankskip(amount,keyword)
+ -- else -- no check
+ -- ctx_addaskedblankskip(amount,keyword)
+ -- end
+ -- end
+ -- end
+ -- end
+ -- return category
+ -- end
+
+ -- local function analyze(str) -- we could use shorter names
+ -- for s in gmatch(str,"([^ ,]+)") do
+ -- local amount, keyword, detail = lpegmatch(splitter,s) -- the comma splitter can be merged
+ -- if not keyword then
+ -- report_vspacing("unknown directive %a",s)
+ -- else
+ -- local mk = map[keyword]
+ -- if mk then
+ -- analyze(mk) -- category not used .. and we pass crap anyway
+ -- elseif keyword == k_fixed then
+ -- ctx_fixedblankskip()
+ -- elseif keyword == k_flexible then
+ -- ctx_flexibleblankskip()
+ -- elseif keyword == k_category then
+ -- local category = tonumber(detail)
+ -- if category then
+ -- ctx_setblankcategory(category)
+ -- ctx_flushblankhandling()
+ -- end
+ -- elseif keyword == k_order and detail then
+ -- local order = tonumber(detail)
+ -- if order then
+ -- ctx_setblankorder(order)
+ -- end
+ -- elseif keyword == k_penalty and detail then
+ -- local penalty = tonumber(detail)
+ -- if penalty then
+ -- ctx_setblankpenalty(penalty)
+ -- end
+ -- else
+ -- amount = tonumber(amount) or 1
+ -- local sk = skip[keyword]
+ -- if sk then
+ -- ctx_addpredefinedblankskip(amount,keyword)
+ -- else -- no check
+ -- ctx_addaskedblankskip(amount,keyword)
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+
+ -- function vspacing.analyze(str)
+ -- if trace_vspacing then
+ -- ctx_pushlogger(report_vspacing)
+ -- ctx_startblankhandling()
+ -- analyze(str,1)
+ -- ctx_stopblankhandling()
+ -- ctx_poplogger()
+ -- else
+ -- ctx_startblankhandling()
+ -- analyze(str,1)
+ -- ctx_stopblankhandling()
+ -- end
+ -- end
+
+ -- alternative
+
+ local pattern = nil
+
+ local function handler(amount, keyword, detail)
+ if not keyword then
+ report_vspacing("unknown directive %a",s)
+ else
+ local mk = map[keyword]
+ if mk then
+ lpegmatch(pattern,mk)
+ elseif keyword == k_fixed then
+ ctx_fixedblankskip()
+ elseif keyword == k_flexible then
+ ctx_flexibleblankskip()
+ elseif keyword == k_category then
+ local category = tonumber(detail)
+ if category then
+ ctx_setblankcategory(category)
+ ctx_flushblankhandling()
+ end
+ elseif keyword == k_order and detail then
+ local order = tonumber(detail)
+ if order then
+ ctx_setblankorder(order)
+ end
+ elseif keyword == k_penalty and detail then
+ local penalty = tonumber(detail)
+ if penalty then
+ ctx_setblankpenalty(penalty)
+ end
+ else
+ amount = tonumber(amount) or 1
+ local sk = skip[keyword]
+ if sk then
+ ctx_addpredefinedblankskip(amount,keyword)
+ else -- no check
+ ctx_addaskedblankskip(amount,keyword)
+ end
+ end
+ end
+ end
+
+ local splitter = ((multiplier + Cc(1)) * keyword * (category + Cc(false))) / handler
+ pattern = (splitter + separator^1)^0
+
+ function vspacing.analyze(str)
+ if trace_vspacing then
+ ctx_pushlogger(report_vspacing)
+ ctx_startblankhandling()
+ lpegmatch(pattern,str)
+ ctx_stopblankhandling()
+ ctx_poplogger()
+ else
+ ctx_startblankhandling()
+ lpegmatch(pattern,str)
+ ctx_stopblankhandling()
+ end
+ end
+
+ --
+
+ function vspacing.setmap(from,to)
+ map[from] = to
+ end
+
+ function vspacing.setskip(key,value,grid)
+ if value ~= "" then
+ if grid == "" then grid = value end
+ skip[key] = { value, grid }
+ end
+ end
+
+end
+
+-- implementation
+
+local trace_list, tracing_info, before, after = { }, false, "", ""
+
+local function nodes_to_string(head)
+ local current, t = head, { }
+ while current do
+ local id = getid(current)
+ local ty = nodecodes[id]
+ if id == penalty_code then
+ t[#t+1] = formatters["%s:%s"](ty,getfield(current,"penalty"))
+ elseif id == glue_code then
+ t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getfield(current,"width"))
+ elseif id == kern_code then
+ t[#t+1] = formatters["%s:%p"](ty,getfield(current,"kern"))
+ else
+ t[#t+1] = ty
+ end
+ current = getnext(current)
+ end
+ return concat(t," + ")
+end
+
+local function reset_tracing(head)
+ trace_list, tracing_info, before, after = { }, false, nodes_to_string(head), ""
+end
+
+local function trace_skip(str,sc,so,sp,data)
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getfield(data,"width"), sc or "-", so or "-", sp or "-") }
+ tracing_info = true
+end
+
+local function trace_natural(str,data)
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getfield(data,"width")) }
+ tracing_info = true
+end
+
+local function trace_info(message, where, what)
+ trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) }
+end
+
+local function trace_node(what)
+ local nt = nodecodes[getid(what)]
+ local tl = trace_list[#trace_list]
+ if tl and tl[1] == "node" then
+ trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) }
+ else
+ trace_list[#trace_list+1] = { "node", nt }
+ end
+end
+
+local function trace_done(str,data)
+ if getid(data) == penalty_code then
+ trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getfield(data,"penalty")) }
+ else
+ trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getfield(data,"width")) }
+ end
+ tracing_info = true
+end
+
+local function show_tracing(head)
+ if tracing_info then
+ after = nodes_to_string(head)
+ for i=1,#trace_list do
+ local tag, text = unpack(trace_list[i])
+ if tag == "info" then
+ report_collapser(text)
+ else
+ report_collapser(" %s: %s",tag,text)
+ end
+ end
+ report_collapser("before: %s",before)
+ report_collapser("after : %s",after)
+ end
+end
+
+-- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display
+
+function vspacing.snapbox(n,how)
+ local sv = snapmethods[how]
+ if sv then
+ local box = getbox(n)
+ local list = getlist(box)
+ if list then
+ local s = getattr(list,a_snapmethod)
+ if s == 0 then
+ if trace_vsnapping then
+ -- report_snapper("box list not snapped, already done")
+ end
+ else
+ local ht = getfield(box,"height")
+ local dp = getfield(box,"depth")
+ if false then -- todo: already_done
+ -- assume that the box is already snapped
+ if trace_vsnapping then
+ report_snapper("box list already snapped at (%p,%p): %s",
+ ht,dp,listtoutf(list))
+ end
+ else
+ local h, d, ch, cd, lines = snap_hlist("box",box,sv,ht,dp)
+ setfield(box,"height",ch)
+ setfield(box,"depth",cd)
+ if trace_vsnapping then
+ report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
+ h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list))
+ end
+ setattr(box,a_snapmethod,0) --
+ setattr(list,a_snapmethod,0) -- yes or no
+ end
+ end
+ end
+ end
+end
+
+-- I need to figure out how to deal with the prevdepth that crosses pages. In fact,
+-- prevdepth is often quite interfering (even over a next paragraph) so I need to
+-- figure out a trick. Maybe use something other than a rule. If we visualize we'll
+-- see the baselineskip in action:
+--
+-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
+-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
+-- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page
+
+-- We can register and copy the rule instead.
+
+local w, h, d = 0, 0, 0
+----- w, h, d = 100*65536, 65536, 65536
+
+local function forced_skip(head,current,width,where,trace)
+ if head == current then
+ if getsubtype(head) == baselineskip_code then
+ width = width - (getfield(head,"width") or 0)
+ end
+ end
+ if width == 0 then
+ -- do nothing
+ elseif where == "after" then
+ head, current = insert_node_after(head,current,new_rule(w,h,d))
+ head, current = insert_node_after(head,current,new_kern(width))
+ head, current = insert_node_after(head,current,new_rule(w,h,d))
+ else
+ local c = current
+ head, current = insert_node_before(head,current,new_rule(w,h,d))
+ head, current = insert_node_before(head,current,new_kern(width))
+ head, current = insert_node_before(head,current,new_rule(w,h,d))
+ current = c
+ end
+ if trace then
+ report_vspacing("inserting forced skip of %p",width)
+ end
+ return head, current
+end
+
+-- penalty only works well when before skip
+
+local discard = 0
+local largest = 1
+local force = 2
+local penalty = 3
+local add = 4
+local disable = 5
+local nowhite = 6
+local goback = 7
+local together = 8 -- not used (?)
+local overlay = 9
+
+-- [whatsits][hlist][glue][glue][penalty]
+
+local special_penalty_min = 32250
+local special_penalty_max = 35000
+local special_penalty_xxx = 0
+
+-- this is rather messy and complex: we want to make sure that successive
+-- header don't break but also make sure that we have at least a decent
+-- break when we have succesive ones (often when testing)
+
+-- todo: mark headers as such so that we can recognize them
+
+local specialmethods = { }
+local specialmethod = 1
+
+local properties = nodes.properties.data
+
+specialmethods[1] = function(pagehead,pagetail,start,penalty)
+ --
+ if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then
+ return
+ end
+ local current = pagetail
+ --
+ -- nodes.showsimplelist(pagehead,0)
+ --
+ if trace_specials then
+ report_specials("checking penalty %a",penalty)
+ end
+ while current do
+ local id = getid(current)
+ if id == penalty_code then
+ local p = properties[current]
+ if p then
+ local p = p.special_penalty
+ if not p then
+ if trace_specials then
+ report_specials(" regular penalty, continue")
+ end
+ elseif p == penalty then
+ if trace_specials then
+ report_specials(" context penalty %a, same level, overloading",p)
+ end
+ return special_penalty_xxx
+ elseif p > special_penalty_min and p < special_penalty_max then
+ if penalty < p then
+ if trace_specials then
+ report_specials(" context penalty %a, lower level, overloading",p)
+ end
+ return special_penalty_xxx
+ else
+ if trace_specials then
+ report_specials(" context penalty %a, higher level, quitting",p)
+ end
+ return
+ end
+ elseif trace_specials then
+ report_specials(" context penalty %a, higher level, continue",p)
+ end
+ else
+ local p = getfield(current,"penalty")
+ if p < 10000 then
+ -- assume some other mechanism kicks in so we seem to have content
+ if trace_specials then
+ report_specials(" regular penalty %a, quitting",p)
+ end
+ break
+ else
+ if trace_specials then
+ report_specials(" regular penalty %a, continue",p)
+ end
+ end
+ end
+ end
+ current = getprev(current)
+ end
+ -- none found, so no reson to be special
+ if trace_specials then
+ if pagetail then
+ report_specials(" context penalty, discarding, nothing special")
+ else
+ report_specials(" context penalty, discarding, nothing preceding")
+ end
+ end
+ return special_penalty_xxx
+end
+
+-- specialmethods[2] : always put something before and use that as to-be-changed
+--
+-- we could inject a vadjust to force a recalculation .. a mess
+--
+-- So, the next is far from robust and okay but for the moment this overlaying
+-- has to do. Always test this with the examples in spec-ver.mkvi!
+
+local function check_experimental_overlay(head,current)
+ local p = nil
+ local c = current
+ local n = nil
+ local function overlay(p,n,mvl)
+ local p_ht = getfield(p,"height")
+ local p_dp = getfield(p,"depth")
+ local n_ht = getfield(n,"height")
+ local skips = 0
+ --
+ -- We deal with this at the tex end .. we don't see spacing .. enabling this code
+ -- is probably harmless btu then we need to test it.
+ --
+ local c = getnext(p)
+ while c and c ~= n do
+ local id = getid(c)
+ if id == glue_code then
+ skips = skips + (getfield(c,"width") or 0)
+ elseif id == kern_code then
+ skips = skips + getfield(c,"kern")
+ end
+ c = getnext(c)
+ end
+ --
+ local delta = n_ht + skips + p_dp
+ texsetdimen("global","d_spac_overlay",-delta) -- for tracing
+ local k = new_kern(-delta)
+ if n_ht > p_ht then
+ -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak
+ setfield(p,"height",n_ht)
+ end
+ insert_node_before(head,n,k)
+ if p == head then
+ head = k
+ end
+ if trace_vspacing then
+ report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta)
+ end
+ return remove_node(head,current,true)
+ end
+
+ -- goto next line
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code or id == kern_code then
+ -- skip (actually, remove)
+ c = getnext(c)
+ elseif id == hlist_code then
+ n = c
+ break
+ else
+ break
+ end
+ end
+ if n then
+ -- we have a next line, goto prev line
+ c = current
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code then
+ c = getprev(c)
+ elseif id == hlist_code then
+ p = c
+ break
+ else
+ break
+ end
+ end
+ if not p then
+ if a_snapmethod == a_snapvbox then
+ -- quit, we're not on the mvl
+ else
+ local c = tonut(texlists.page_head)
+ while c and c ~= n do
+ local id = getid(c)
+ if id == hlist_code then
+ p = c
+ end
+ c = getnext(c)
+ end
+ if p and p ~= n then
+ return overlay(p,n,true)
+ end
+ end
+ elseif p ~= n then
+ return overlay(p,n,false)
+ end
+ end
+ -- in fact, we could try again later ... so then no remove (a few tries)
+ return remove_node(head, current, true)
+end
+
+-- This will be replaced after 0.80+ when we have a more robust look-back and
+-- can look at the bigger picture.
+
+-- todo: look back and when a special is there before a list is seen penalty keep ut
+
+-- we now look back a lot, way too often
+
+-- userskip
+-- lineskip
+-- baselineskip
+-- parskip
+-- abovedisplayskip
+-- belowdisplayskip
+-- abovedisplayshortskip
+-- belowdisplayshortskip
+-- topskip
+-- splittopskip
+
+local experiment = false directives.register("vspacing.experiment",function(v) experiment = v end)
+
+local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail
+ 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
+ --
+ -- todo: keep_together: between headers
+ --
+ local pagehead = nil
+ local pagetail = nil
+
+ local function getpagelist()
+ if not pagehead then
+ pagehead = texlists.page_head
+ if pagehead then
+ pagehead = tonut(texlists.page_head)
+ pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet
+ end
+ end
+ end
+ --
+ local function flush(why)
+ if penalty_data then
+ local p = new_penalty(penalty_data)
+ if trace then
+ trace_done("flushed due to " .. why,p)
+ end
+ if penalty_data >= 10000 then -- or whatever threshold?
+ local prev = getprev(current)
+ if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue
+ -- tricky case: spacing/grid-007.tex: glue penalty glue
+ head = insert_node_before(head,prev,p)
+ else
+ head = insert_node_before(head,current,p)
+ end
+ else
+ head = insert_node_before(head,current,p)
+ end
+ -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
+ local props = properties[p]
+ if props then
+ props.special_penalty = special_penalty or penalty_data
+ else
+ properties[p] = {
+ special_penalty = special_penalty or penalty_data
+ }
+ end
+ -- end
+ end
+ if glue_data then
+ if force_glue then
+ if trace then
+ trace_done("flushed due to forced " .. why,glue_data)
+ end
+ head = forced_skip(head,current,getfield(glue_data,"width") or 0,"before",trace)
+ free_node(glue_data)
+ else
+ local w = getfield(glue_data,"width")
+ if w ~= 0 then
+ if trace then
+ trace_done("flushed due to non zero " .. why,glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ elseif getfield(glue_data,"stretch") ~= 0 or getfield(glue_data,"shrink") ~= 0 then
+ if trace then
+ trace_done("flushed due to stretch/shrink in" .. why,glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ else
+ -- report_vspacing("needs checking (%s): %p",skipcodes[getsubtype(glue_data)],w)
+ free_node(glue_data)
+ end
+ end
+ end
+
+ if trace then
+ trace_node(current)
+ end
+ glue_order, glue_data, force_glue = 0, nil, false
+ penalty_order, penalty_data, natural_penalty = 0, nil, nil
+ parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false
+ end
+ --
+
+-- quick hack, can be done nicer
+-- local nobreakfound = nil
+-- local function checknobreak()
+-- local pagehead, pagetail = getpagelist()
+-- local current = pagetail
+-- while current do
+-- local id = getid(current)
+-- if id == hlist_code or id == vlist_code then
+-- return false
+-- elseif id == penalty_code then
+-- return getfield(current,"penalty") >= 10000
+-- end
+-- current = getprev(current)
+-- end
+-- return false
+-- end
+
+ --
+ if trace_vsnapping then
+ report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p",
+ texgetdimen("globalbodyfontstrutheight"), texgetdimen("globalbodyfontstrutdepth"),
+ texgetdimen("bodyfontstrutheight"), texgetdimen("bodyfontstrutdepth")
+ )
+ end
+ if trace then
+ trace_info("start analyzing",where,what)
+ end
+
+-- local headprev = getprev(head)
+
+ while current do
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code then
+-- if nobreakfound == nil then
+-- nobreakfound = false
+-- end
+ -- needs checking, why so many calls
+ if snap then
+ local list = getlist(current)
+ local s = getattr(current,a_snapmethod)
+ if not s then
+ -- if trace_vsnapping then
+ -- report_snapper("mvl list not snapped")
+ -- end
+ elseif s == 0 then
+ if trace_vsnapping then
+ report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list))
+ end
+ else
+ local sv = snapmethods[s]
+ if sv then
+ -- check if already snapped
+ if list and already_done(id,list,a_snapmethod) then
+ local ht = getfield(current,"height")
+ local dp = getfield(current,"depth")
+ -- assume that the box is already snapped
+ if trace_vsnapping then
+ report_snapper("mvl list already snapped at (%p,%p): %s",ht,dp,listtoutf(list))
+ end
+ else
+ local h, d, ch, cd, lines = snap_hlist("mvl",current,sv)
+ if trace_vsnapping then
+ report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
+ nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list))
+ end
+ end
+ elseif trace_vsnapping then
+ report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list))
+ end
+ setattr(current,a_snapmethod,0)
+ end
+ else
+ --
+ end
+ -- tex.prevdepth = 0
+ flush("list")
+ current = getnext(current)
+ elseif id == penalty_code then
+ -- natural_penalty = getfield(current,"penalty")
+ -- if trace then
+ -- trace_done("removed penalty",current)
+ -- end
+ -- head, current = remove_node(head, current, true)
+
+-- if nobreakfound == nil then
+-- nobreakfound = checknobreak()
+-- end
+-- if nobreakfound and getfield(current,"penalty") <= 10000 then
+-- -- if trace then
+-- trace_done("removed penalty",current)
+-- -- end
+-- head, current = remove_node(head, current, true)
+-- end
+
+ current = getnext(current)
+ elseif id == kern_code then
+ if snap and trace_vsnapping and getfield(current,"kern") ~= 0 then
+ report_snapper("kern of %p kept",getfield(current,"kern"))
+ end
+ flush("kern")
+ current = getnext(current)
+ elseif id == glue_code then
+ local subtype = getsubtype(current)
+ if subtype == userskip_code then
+ local sc = getattr(current,a_skipcategory) -- has no default, no unset (yet)
+ local so = getattr(current,a_skiporder) or 1 -- has 1 default, no unset (yet)
+ local sp = getattr(current,a_skippenalty) -- has no default, no unset (yet)
+ if sp and sc == penalty then
+ if where == "page" then
+ getpagelist()
+ local p = specialmethods[specialmethod](pagehead,pagetail,current,sp)
+ if p then
+ -- todo: other tracer
+ --
+ -- if trace then
+ -- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod)
+ -- end
+ special_penalty = sp
+ sp = p
+ end
+
+-- else
+-- if nobreakfound == nil then
+-- nobreakfound = checknobreak()
+-- end
+
+ end
+ if not penalty_data then
+ penalty_data = sp
+ elseif penalty_order < so then
+ penalty_order, penalty_data = so, sp
+ elseif penalty_order == so and sp > penalty_data then
+ penalty_data = sp
+ end
+ if trace then
+ trace_skip("penalty in skip",sc,so,sp,current)
+ end
+
+-- if nobreakfound then
+-- penalty_data = 10000
+-- if trace then
+-- trace_skip("nobreak found before penalty in skip",sc,so,sp,current)
+-- end
+-- end
+
+ head, current = remove_node(head, current, true)
+ elseif not sc then -- if not sc then
+ if glue_data then
+ if trace then
+ trace_done("flush",glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ if trace then
+ trace_natural("natural",current)
+ end
+ current = getnext(current)
+ else
+ -- not look back across head
+ -- todo: prev can be whatsit (latelua)
+ local previous = getprev(current)
+ if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then
+ if getfield(previous,"stretch_order") == 0 and getfield(previous,"shrink_order") == 0 and
+ getfield(current, "stretch_order") == 0 and getfield(current, "shrink_order") == 0 then
+ setfield(previous,"width", (getfield(previous,"width") or 0) + (getfield(current,"width") or 0))
+ setfield(previous,"stretch",(getfield(previous,"stretch") or 0) + (getfield(current,"stretch") or 0))
+ setfield(previous,"shrink", (getfield(previous,"shrink") or 0) + (getfield(current,"shrink") or 0))
+ if trace then
+ trace_natural("removed",current)
+ end
+ head, current = remove_node(head, current, true)
+ if trace then
+ trace_natural("collapsed",previous)
+ end
+ else
+ if trace then
+ trace_natural("filler",current)
+ end
+ current = getnext(current)
+ end
+ else
+ if trace then
+ trace_natural("natural (no prev)",current)
+ end
+ current = getnext(current)
+ end
+ end
+ glue_order, glue_data = 0, nil
+ elseif sc == disable then
+local next = getnext(current)
+if not experiment or next then
+ ignore_following = true
+ if trace then
+ trace_skip("disable",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+else
+ current = next
+end
+ elseif sc == together then
+local next = getnext(current)
+if not experiment or next then
+ keep_together = true
+ if trace then
+ trace_skip("together",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+else
+ current = next
+end
+ elseif sc == nowhite then
+local next = getnext(current)
+if not experiment or next then
+ ignore_whitespace = true
+ head, current = remove_node(head, current, true)
+else
+ current = next
+end
+ elseif sc == discard then
+ if trace then
+ trace_skip("discard",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+ elseif sc == overlay then
+ -- todo (overlay following line over previous
+ if trace then
+ trace_skip("overlay",sc,so,sp,current)
+ end
+ -- beware: head can actually be after the affected nodes as
+ -- we look back ... some day head will the real head
+ head, current = check_experimental_overlay(head,current,a_snapmethod)
+ elseif ignore_following then
+ if trace then
+ trace_skip("disabled",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+ elseif not glue_data then
+ if trace then
+ trace_skip("assign",sc,so,sp,current)
+ end
+ glue_order = so
+ head, current, glue_data = remove_node(head, current)
+ elseif glue_order < so then
+ if trace then
+ trace_skip("force",sc,so,sp,current)
+ end
+ glue_order = so
+ free_node(glue_data)
+ head, current, glue_data = remove_node(head, current)
+ elseif glue_order == so then
+ -- is now exclusive, maybe support goback as combi, else why a set
+ if sc == largest then
+ local cw = getfield(current,"width") or 0
+ local gw = getfield(glue_data,"width") or 0
+ if cw > gw then
+ if trace then
+ trace_skip("largest",sc,so,sp,current)
+ end
+ free_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ else
+ if trace then
+ trace_skip("remove smallest",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+ end
+ elseif sc == goback then
+ if trace then
+ trace_skip("goback",sc,so,sp,current)
+ end
+ free_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ elseif sc == force then
+ -- last one counts, some day we can provide an accumulator and largest etc
+ -- but not now
+ if trace then
+ trace_skip("force",sc,so,sp,current)
+ end
+ free_node(glue_data)
+ head, current, glue_data = remove_node(head, current)
+ elseif sc == penalty then
+ if trace then
+ trace_skip("penalty",sc,so,sp,current)
+ end
+ free_node(glue_data)
+ glue_data = nil
+ head, current = remove_node(head, current, true)
+ elseif sc == add then
+ if trace then
+ trace_skip("add",sc,so,sp,current)
+ end
+ setfield(old,"width", (getfield(glue_data,"width") or 0) + (getfield(current,"width") or 0))
+ setfield(old,"stretch",(getfield(glue_data,"stretch") or 0) + (getfield(current,"stretch") or 0))
+ setfield(old,"shrink", (getfield(glue_data,"shrink") or 0) + (getfield(current,"shrink") or 0))
+ -- toto: order
+ head, current = remove_node(head, current, true)
+ else
+ if trace then
+ trace_skip("unknown",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+ end
+ else
+ if trace then
+ trace_skip("unknown",sc,so,sp,current)
+ end
+ head, current = remove_node(head, current, true)
+ end
+ if sc == force then
+ force_glue = true
+ end
+ elseif subtype == lineskip_code then
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ setfield(current,"width",0)
+ if trace_vsnapping then
+ report_snapper("lineskip set to zero")
+ end
+ else
+ if trace then
+ trace_skip("lineskip",sc,so,sp,current)
+ end
+ flush("lineskip")
+ end
+ else
+ if trace then
+ trace_skip("lineskip",sc,so,sp,current)
+ end
+ flush("lineskip")
+ end
+ current = getnext(current)
+ elseif subtype == baselineskip_code then
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ setfield(current,"width",0)
+ if trace_vsnapping then
+ report_snapper("baselineskip set to zero")
+ end
+ else
+ if trace then
+ trace_skip("baselineskip",sc,so,sp,current)
+ end
+ flush("baselineskip")
+ end
+ else
+ if trace then
+ trace_skip("baselineskip",sc,so,sp,current)
+ end
+ flush("baselineskip")
+ end
+ current = getnext(current)
+ elseif subtype == parskip_code then
+ -- parskip always comes later
+ if ignore_whitespace then
+ if trace then
+ trace_natural("ignored parskip",current)
+ end
+ head, current = remove_node(head, current, true)
+ elseif glue_data then
+ local wp = getfield(current,"width") or 0
+ if ((w ~= 0) and (w > (getfield(glue_data,"width") or 0))) then
+ glue_data = current
+ head, current = remove_node(head, current)
+ if trace then
+ trace_natural("taking parskip",current)
+ end
+ else
+ head, current = remove_node(head, current, true)
+ if trace then
+ trace_natural("removed parskip",current)
+ end
+ end
+ else
+ if trace then
+ trace_natural("honored parskip",current)
+ end
+ head, current, glue_data = remove_node(head, current)
+ end
+ elseif subtype == topskip_code or subtype == splittopskip_code then
+ local next = getnext(current)
+ if next and getattr(next,a_skipcategory) == 10 then -- no top skip
+ nuts.setglue(current) -- zero
+ end
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ local sv = snapmethods[s]
+ local w, cw = snap_topskip(current,sv)
+ if trace_vsnapping then
+ report_snapper("topskip snapped from %p to %p for %a",w,cw,where)
+ end
+ else
+ if trace then
+ trace_skip("topskip",sc,so,sp,current)
+ end
+ flush("topskip")
+ end
+ else
+ if trace then
+ trace_skip("topskip",sc,so,sp,current)
+ end
+ flush("topskip")
+ end
+ current = getnext(current)
+ elseif subtype == abovedisplayskip_code then
+ --
+ if trace then
+ trace_skip("above display skip (normal)",sc,so,sp,current)
+ end
+ flush("above display skip (normal)")
+ current = getnext(current)
+ --
+ elseif subtype == belowdisplayskip_code then
+ --
+ if trace then
+ trace_skip("below display skip (normal)",sc,so,sp,current)
+ end
+ flush("below display skip (normal)")
+ current = getnext(current)
+ --
+ elseif subtype == abovedisplayshortskip_code then
+ --
+ if trace then
+ trace_skip("above display skip (short)",sc,so,sp,current)
+ end
+ flush("above display skip (short)")
+ current = getnext(current)
+ --
+ elseif subtype == belowdisplayshortskip_code then
+ --
+ if trace then
+ trace_skip("below display skip (short)",sc,so,sp,current)
+ end
+ flush("below display skip (short)")
+ current = getnext(current)
+ --
+ else -- other glue
+ if snap and trace_vsnapping then
+ local w = getfield(current,"width") or 0
+ if w ~= 0 then
+ report_snapper("glue %p of type %a kept",w,skipcodes[subtype])
+ end
+ end
+ if trace then
+ trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current)
+ end
+ flush("some glue")
+ current = getnext(current)
+ end
+ else
+ flush(formatters["node with id %a"](id))
+ current = getnext(current)
+ end
+ end
+ if trace then
+ trace_info("stop analyzing",where,what)
+ end
+ -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then
+ -- penalty_data = natural_penalty
+ -- end
+ if trace and (glue_data or penalty_data) then
+ trace_info("start flushing",where,what)
+ end
+ local tail
+ if penalty_data then
+ tail = find_node_tail(head)
+ local p = new_penalty(penalty_data)
+ if trace then
+ trace_done("result",p)
+ end
+ head, tail = insert_node_after(head,tail,p)
+ -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
+ local props = properties[p]
+ if props then
+ props.special_penalty = special_penalty or penalty_data
+ else
+ properties[p] = {
+ special_penalty = special_penalty or penalty_data
+ }
+ end
+ -- end
+ end
+ if glue_data then
+ if not tail then tail = find_node_tail(head) end
+ if trace then
+ trace_done("result",glue_data)
+ end
+ if force_glue then
+ head, tail = forced_skip(head,tail,getfield(glue_data,"width") or 0,"after",trace)
+ free_node(glue_data)
+ glue_data = nil
+ else
+ head, tail = insert_node_after(head,tail,glue_data)
+ end
+ texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler
+ end
+ if trace then
+ if glue_data or penalty_data then
+ trace_info("stop flushing",where,what)
+ end
+ show_tracing(head)
+ if oldhead ~= head then
+ trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)])
+ end
+ end
+
+-- if headprev then
+-- setprev(head,headprev)
+-- setnext(headprev,head)
+-- end
+-- print("C HEAD",tonode(head))
+
+ return head, true
+end
+
+-- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display
+-- \par -> vmode_par
+--
+-- status.best_page_break
+-- tex.lists.best_page_break
+-- tex.lists.best_size (natural size to best_page_break)
+-- tex.lists.least_page_cost (badness of best_page_break)
+-- tex.lists.page_head
+-- tex.lists.contrib_head
+
+local stackhead, stacktail, stackhack = nil, nil, false
+
+local function report(message,where,lst)
+ if lst and where then
+ report_vspacing(message,where,count_nodes(lst,true),nodeidstostring(lst))
+ else
+ report_vspacing(message,count_nodes(lst,true),nodeidstostring(lst))
+ end
+end
+
+-- ugly code: we get partial lists (check if this stack is still okay) ... and we run
+-- into temp nodes (sigh)
+
+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)
+ if id ~= glue_code then
+ flush = true
+ elseif getsubtype(n) == userskip_code then
+ if getattr(n,a_skipcategory) then
+ stackhack = true
+ else
+ flush = true
+ end
+ else
+ -- tricky
+ end
+ 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
+ end
+ if stackhack then
+ stackhack = false
+ if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end
+ -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
+ newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
+ else
+ if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end
+ -- texlists.contrib_head = newhead
+ end
+ return tonode(newhead)
+ else
+ if stackhead then
+ if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end
+ setlink(stacktail,newhead)
+ else
+ if trace_collect_vspacing then report("%s > storing %s nodes in stack (initial): %s",where,newhead) end
+ stackhead = newhead
+ end
+ stacktail = newtail
+ -- texlists.contrib_head = nil
+ -- newhead = nil
+ end
+ end
+ return nil
+end
+
+local ignore = table.tohash {
+ "split_keep",
+ "split_off",
+ -- "vbox",
+}
+
+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)
+ end
+ end
+ return head
+end
+
+function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod
+ local box = getbox(n)
+ if box then
+ local list = getlist(box)
+ if list then
+ list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)
+ if aslist then
+ setlist(box,list) -- beware, dimensions of box are wrong now
+ else
+ setlist(box,vpack_node(list))
+ end
+ end
+ end
+end
+
+-- This one is needed to prevent bleeding of prevdepth to the next page
+-- which doesn't work well with forced skips.
+
+local outer = texnest[0]
+
+function vspacing.resetprevdepth()
+ if texlists.hold_head then
+ outer.prevdepth = 0
+ end
+end
+
+-- interface
+
+implement {
+ name = "vspacing",
+ actions = vspacing.analyze,
+ scope = "private",
+ arguments = "string"
+}
+
+implement {
+ name = "resetprevdepth",
+ actions = vspacing.resetprevdepth,
+ scope = "private"
+}
+
+implement {
+ name = "vspacingsetamount",
+ actions = vspacing.setskip,
+ scope = "private",
+ arguments = "string",
+}
+
+implement {
+ name = "vspacingdefine",
+ actions = vspacing.setmap,
+ scope = "private",
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "vspacingcollapse",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = "integer"
+}
+
+implement {
+ name = "vspacingcollapseonly",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = { "integer", true }
+}
+
+implement {
+ name = "vspacingsnap",
+ actions = vspacing.snapbox,
+ scope = "private",
+ arguments = { "integer", "integer" }
+}
+
+implement {
+ name = "definesnapmethod",
+ actions = vspacing.definesnapmethod,
+ scope = "private",
+ arguments = { "string", "string" }
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv
new file mode 100644
index 00000000000..bbe53fb2aa3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv
@@ -0,0 +1,2373 @@
+%D \module
+%D [ file=spac-ver,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Vertical,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Vertical}
+
+\unprotect
+
+\registerctxluafile{spac-ver}{1.001}
+
+% todo: use usernodes ?
+
+% todo: itemize : intro ... only when there is one or two lines preceding and then
+% keep these together i.e. \blank[intro]
+
+% Isn't it about time to get rid of topskip i.e. make it equivalent to
+% \openstrutheight so that we can remove delta code.
+%
+% There might be more namespace protection.
+
+%D There are two ways to influence the interline spacing. The
+%D most general and often most consistent way is using
+%D
+%D \showsetup{setupinterlinespace}
+%D
+%D For instance
+%D
+%D \starttyping
+%D \setupinterlinespace[line=2.8ex]
+%D \stoptyping
+%D
+%D This setting adapts itself to the bodyfontsize, while for
+%D instance saying
+%D
+%D \starttyping
+%D \setupinterlinespace[line=12pt]
+%D \stoptyping
+%D
+%D sets things fixed for all sizes, which is definitely not
+%D what we want. Therefore one can also say:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[9pt][interlinespace=11pt]
+%D \stoptyping
+%D
+%D One can still use \type{\setupinterlinespace} (without
+%D arguments) to set the interline space according to the
+%D current font, e.g. a \type{\bfa}.
+
+% will be cleaned up but it will stay messy because we accept so
+% many variants
+
+\newif\iflocalinterlinespace
+
+\newskip\s_spac_vspacing_temp \s_spac_vspacing_temp\bigskipamount
+
+\def\skipfactor {.75}
+\def\skipgluefactor{.25}
+
+\def\normalskipamount
+ {\openlineheight
+ \ifgridsnapping \else \ifblankflexible
+ \s!plus \skipgluefactor\openlineheight
+ \s!minus\skipgluefactor\openlineheight
+ \fi \fi
+ \relax}
+
+\ifdefined\bodyfontinterlinespace \else
+ \let\bodyfontinterlinespace\empty
+\fi
+
+\unexpanded\def\presetnormallineheight % each bodyfont
+ {\edef\normallineheight{\interlinespaceparameter\c!line}%
+ \iflocalinterlinespace \else
+ \edef\m_spac_normallineheight{\bodyfontinterlinespace}%
+ \ifx\m_spac_normallineheight\empty \else
+ \let\normallineheight\m_spac_normallineheight
+ \fi
+ \fi}
+
+\unexpanded\def\setupspecifiedinterlinespace[#1]%
+ {\setupcurrentinterlinespace[#1]%
+ \spac_linespacing_setup_specified_interline_space}
+
+\def\spac_linespacing_setup_specified_interline_space
+ {\edef\strutheightfactor {\interlinespaceparameter\c!height }%
+ \edef\strutdepthfactor {\interlinespaceparameter\c!depth }%
+ \edef\minimumstrutheight {\interlinespaceparameter\c!minheight}%
+ \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth }%
+ \edef\minimumlinedistance {\interlinespaceparameter\c!distance }%
+ \edef\normallineheight {\interlinespaceparameter\c!line }%
+ \edef\topskipfactor {\interlinespaceparameter\c!top }%
+ \edef\maxdepthfactor {\interlinespaceparameter\c!bottom }%
+ \edef\m_spac_vertical_baseline_stretch_factor{\interlinespaceparameter\c!stretch }%
+ \edef\m_spac_vertical_baseline_shrink_factor {\interlinespaceparameter\c!shrink }%
+ % often topskip does more bad than good, so:
+ \ifx\topskipfactor\v!height
+ \let\topskipfactor\strutheightfactor
+ \fi
+ \setfontparameters % redundant, can be \setstrut, test first
+ \updateraggedskips} % yes indeed
+
+\installcorenamespace{interlinespacerelative}
+
+\let\setrelativeinterlinespace \relax % used elsewhere
+\let\currentrelativeinterlinespace\empty
+
+\setvalue{\??interlinespacerelative\v!on }{\oninterlineskip}
+\setvalue{\??interlinespacerelative\v!off }{\offinterlineskip}
+\setvalue{\??interlinespacerelative\v!reset}{\let\currentrelativeinterlinespace\empty
+ \let\setrelativeinterlinespace\relax
+ \setfontparameters}
+\setvalue{\??interlinespacerelative\v!auto }{\let\setrelativeinterlinespace\spac_linespacing_set_relative_interlinespace}
+
+\def\spac_linespacing_set_specified_relative_interlinespace#1% fragile?
+ {\doifelsedimenstring{#1}
+ {\setupspecifiedinterlinespace[\c!line=#1]}
+ {\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
+ \spacing\currentrelativeinterlinespace}}
+
+\unexpanded\def\setuprelativeinterlinespace[#1]%
+ {\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace}
+
+\def\spac_linespacing_setup_relative_interlinespace#1%
+ {\ifcsname\??interlinespacerelative#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_linespacing_set_specified_relative_interlinespace{#1}%
+ \fi}
+
+\def\spac_linespacing_set_relative_interlinespace
+ {\ifx\currentrelativeinterlinespace\empty\else
+ \spacing\currentrelativeinterlinespace
+ \fi}
+
+\unexpanded\def\spac_linespacing_setup_use
+ {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname
+ \let\currentinterlinespace\m_spac_interlinespace
+ \spac_linespacing_setup_specified_interline_space
+ % \else
+ % we only support named interlinespaces
+ \fi}
+
+\unexpanded\def\useinterlinespaceparameter#1% see footnotes
+ {\edef\m_spac_interlinespace{#1\c!interlinespace}%
+ \ifx\m_spac_interlinespace\empty \else
+ \spac_linespacing_setup_use
+ \fi}
+
+\newtoks\everysetupglobalinterlinespace
+\newtoks\everysetuplocalinterlinespace
+
+\newconditional\interlinespaceisset
+
+\installcorenamespace{interlinespace}
+
+\installcommandhandler \??interlinespace {interlinespace} \??interlinespace
+
+\unexpanded\def\setupinterlinespace
+ {\dodoubleempty\spac_linespacing_setup}
+
+\ifdefined\setupinterlinespace_double \else
+ \let\setupinterlinespace_double\setup_interlinespace % for a while
+\fi
+
+\def\spac_linespacing_setup[#1][#2]%
+ {\settrue\interlinespaceisset % reset has to be done when needed
+ \ifsecondargument
+ \setupinterlinespace_double[#1][#2]%
+ \else\iffirstargument
+ \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname
+ \edef\currentinterlinespace{#1}%
+ \spac_linespacing_setup_specified_interline_space
+ %\dosetupspecifiedinterlinespaceindeed
+ \else
+ \spac_linespacing_setup_specified_or_relative[#1]%
+ \fi
+ \else
+ \let\currentinterlinespace\empty
+ \spac_linespacing_synchronize_local
+ \fi\fi}
+
+\def\spac_linespacing_setup_specified_or_relative[#1]%
+ {\doifelseassignment{#1}\setupspecifiedinterlinespace\setuprelativeinterlinespace[#1]%
+ \the\iflocalinterlinespace\everysetuplocalinterlinespace\else\everysetupglobalinterlinespace\fi}
+
+\def\spac_linespacing_synchronize_local % adapts to the font
+ {\localinterlinespacetrue
+ \setfontparameters
+ \updateraggedskips % funny one here
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse}
+
+\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain
+ {\edef\p_spac_checked_interlinespace{#1}%
+ \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
+ \let\currentinterlinespace\p_spac_checked_interlinespace
+ \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
+ \iflocalinterlinespace
+ \the\everysetuplocalinterlinespace
+ \else
+ \localinterlinespacetrue
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse
+ \fi
+ \popmacro\currentinterlinespace
+ \else
+ \normalexpanded{\noexpand\doifelseassignment{\p_spac_checked_interlinespace}%
+ \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}%
+ \iflocalinterlinespace
+ \the\everysetuplocalinterlinespace
+ \else
+ \localinterlinespacetrue
+ \the\everysetuplocalinterlinespace
+ \localinterlinespacefalse
+ \fi
+ \fi\fi}
+
+\unexpanded\def\setuplocalinterlinespace[#1]%
+ {\localinterlinespacetrue
+ \pushmacro\currentinterlinespace
+ \setupinterlinespace[#1]%
+ \popmacro\currentinterlinespace
+ \localinterlinespacefalse}
+
+\let\switchtointerlinespace\setuplocalinterlinespace
+
+%D Helpers
+
+\newskip \s_spac_lastskip
+\newdimen\d_spac_prevdepth
+\newcount\c_spac_spacefactor
+
+\unexpanded\def\removelastskip
+ {\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
+
+\def\doifoutervmode
+ {\ifvmode
+ \ifinner
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\firstofoneargument
+ \fi
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\dosomebreak#1%
+ {\doifoutervmode
+ {\s_spac_lastskip\lastskip
+ \removelastskip
+ #1\relax
+ \ifdim\s_spac_lastskip=\zeropoint
+ % avoid interference with footnotes
+ \else
+ \vskip\s_spac_lastskip
+ \fi}}
+
+\unexpanded\def\packed
+ {\nointerlineskip}
+
+\unexpanded\def\godown[#1]%
+ {\relax
+ \ifhmode\endgraf\fi
+ \ifvmode\nointerlineskip\vskip#1\relax\fi}
+
+\unexpanded\def\smallskip{\vskip\smallskipamount}
+\unexpanded\def\medskip {\vskip\medskipamount}
+\unexpanded\def\bigskip {\vskip\bigskipamount}
+
+\unexpanded\def\smallbreak
+ {\par
+ \ifdim\lastskip<\smallskipamount
+ \removelastskip
+ \penalty-50
+ \smallskip
+ \fi}
+
+\unexpanded\def\medbreak
+ {\par
+ \ifdim\lastskip<\medskipamount
+ \removelastskip
+ \penalty-100
+ \medskip
+ \fi}
+
+\unexpanded\def\bigbreak
+ {\par
+ \ifdim\lastskip<\bigskipamount
+ \removelastskip
+ \penalty-200
+ \bigskip
+ \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
+
+%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}
+
+\def\spac_helpers_vglue_indeed
+ {\par
+ \d_spac_prevdepth\prevdepth
+ \hrule\s!height\zeropoint
+ \nobreak
+ \vskip\s_spac_lastskip
+ \prevdepth\d_spac_prevdepth}
+
+\def\spac_helpers_hglue_indeed
+ {\dontleavehmode
+ \c_spac_spacefactor\spacefactor
+ \vrule\s!width\zeropoint
+ \nobreak
+ \hskip\s_spac_lastskip
+ \spacefactor\c_spac_spacefactor}
+
+%D We adapt plain's \type {\removelastskip} a bit:
+
+\unexpanded\def\removelastskip % also in supp-box
+ {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+
+% The whitespace handler. We could cache settings but normally there are not
+% that many in a set.
+
+\installcorenamespace{whitespacemethod}
+
+\newskip \s_spac_whitespace_parskip \s_spac_whitespace_parskip\zeropoint
+\newconditional\c_spac_whitespace_flexible \settrue\c_spac_whitespace_flexible
+\newconstant \c_spac_whitespace_grid_mode % option in layout / 1=permit_half_lines
+
+%def\v_spac_whitespace_current{\zeropoint}
+\let\v_spac_whitespace_current\v!none
+
+\unexpanded\def\setupwhitespace
+ {\doifelsenextoptionalcs\spac_whitespace_setup_yes\spac_whitespace_setup_nop}
+
+\def\spac_whitespace_setup_nop
+ {\ifx\v_spac_whitespace_current\v!none\else
+ \spac_whitespace_setup
+ \fi}
+
+\let\synchronizewhitespace\spac_whitespace_setup_nop
+
+\def\spac_whitespace_setup_yes[#1]%
+ {\edef\m_spac_whitespace_asked{#1}%
+ \ifx\m_spac_whitespace_asked\empty
+ \spac_whitespace_setup_nop
+ \else
+ \let\v_spac_whitespace_current\m_spac_whitespace_asked
+ \spac_whitespace_setup
+ \fi}
+
+\def\spac_whitespace_setup % quick test for no list
+ {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
+ \lastnamedcs
+ \else
+ \expandafter\processcommalist\expandafter[\v_spac_whitespace_current]\spac_whitespace_setup_method % can be raw
+ \fi\relax
+ \ifgridsnapping
+ \spac_whitespace_setup_grid
+ \else
+ \spac_whitespace_setup_normal
+ \fi
+ \parskip\s_spac_whitespace_parskip}
+
+\def\spac_whitespace_setup_normal
+ {\ifconditional\c_spac_whitespace_flexible \else
+ \s_spac_whitespace_parskip\plusone\s_spac_whitespace_parskip
+ \fi}
+
+\def\spac_whitespace_setup_grid
+ {\setfalse\c_spac_whitespace_flexible
+ \ifdim\s_spac_whitespace_parskip>\zeropoint
+ \s_spac_whitespace_parskip
+ \ifcase\c_spac_whitespace_grid_mode
+ \baselineskip
+ \or
+ \ifdim\scratchdimen=\baselineskip % maybe range
+ \baselineskip
+ \else
+ \numexpr\s_spac_whitespace_parskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
+ \fi
+ \else
+ \baselineskip
+ \fi
+ \fi}
+
+\unexpanded\def\installwhitespacemethod#1#2%
+ {\setvalue{\??whitespacemethod#1}{#2}}
+
+\installwhitespacemethod \v!fix {}
+\installwhitespacemethod \v!fixed {\setfalse\c_spac_whitespace_flexible}
+\installwhitespacemethod \v!flexible {\settrue \c_spac_whitespace_flexible}
+
+\installwhitespacemethod \v!line {\s_spac_whitespace_parskip \baselineskip}
+\installwhitespacemethod \v!halfline {\s_spac_whitespace_parskip .5\baselineskip}
+\installwhitespacemethod \v!quarterline {\s_spac_whitespace_parskip.25\baselineskip}
+\installwhitespacemethod \v!none {\s_spac_whitespace_parskip \zeropoint}
+\installwhitespacemethod \v!big {\s_spac_whitespace_parskip \bigskipamount}
+\installwhitespacemethod \v!medium {\s_spac_whitespace_parskip \medskipamount}
+\installwhitespacemethod \v!small {\s_spac_whitespace_parskip \smallskipamount}
+
+\installwhitespacemethod \s!default {\spac_whitespace_setup_nop} % also covers none
+
+\def\spac_whitespace_setup_method#1%
+ {\ifcsname\??whitespacemethod#1\endcsname
+ \lastnamedcs
+ \else
+ \s_spac_whitespace_parskip#1\fi
+ \relax}
+
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
+
+\appendtoks
+ \forgetparskip
+\to \everyforgetall
+
+% \installwhitespacemethod \s!unknown {\s_spac_whitespace_parskip\commalistelement\relax}
+%
+% \def\spac_whitespace_setup_method#1%
+% {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
+
+\unexpanded\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
+\unexpanded\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]}
+
+\setupwhitespace
+ [\v!none]
+
+% Packed:
+
+% todo: when packed blocks blank, we need to enable forced
+
+\newconditional\c_spac_packed_blank \settrue\c_spac_packed_blank
+\newcount \c_spac_packed_level
+
+\unexpanded\def\startpacked
+ {\dosingleempty\spac_packed_start}
+
+\def\spac_packed_start[#1]% nesting afvangen
+ {\global\advance\c_spac_packed_level\plusone
+ \par
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \begingroup
+ \whitespace % not combined
+ \directcheckedvspacing\v!disable % \blank[\v!disable]% or \inhibitblank
+ \doifelse{#1}\v!blank\settrue\setfalse\c_spac_packed_blank
+ \setupwhitespace[\v!none]% or \forgetparskip
+ \fi \fi}
+
+\unexpanded\def\stoppacked
+ {\par
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \endgroup
+ \fi \fi
+ \global\advance\c_spac_packed_level\minusone}
+
+\unexpanded\def\startunpacked
+ {\directdefaultvspacing % \blank
+ \begingroup}
+
+\unexpanded\def\stopunpacked
+ {\endgroup
+ \directdefaultvspacing}% \blank}
+
+% \prevdepth crosses pageboundaries!
+%
+% todo: a version that works ok inside a box
+
+% global : outer hsize + keep skips
+% local : inner hsize + reset skips
+
+\installcorenamespace{linesaround}
+
+\let\spac_lines_vbox\vbox
+
+\installtextracker
+ {linecorrection.boxes}
+ {\let\spac_lines_vbox\ruledvbox}
+ {\let\spac_lines_vbox\vbox}
+
+\let\v_spac_lines_around_action_set\relax
+\let\m_spac_lines_around \empty
+
+\newconstant\c_spac_lines_correction_mode
+
+\setvalue{\??linesaround\v!blank }{\blank}
+\letvalue{\??linesaround\empty }\relax
+\setvalue{\??linesaround\s!unknown}{\directcheckedvspacing\m_spac_lines_around} % \blank[\m_spac_lines_around]}
+
+\def\spac_lines_action_around % we used to let this one but it's cleaner this way
+ {\csname\??linesaround % i.e. do it twice
+ \ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi
+ \endcsname}
+
+\unexpanded\def\startlinecorrection
+ {\endgraf
+ \begingroup
+ \setconstant\c_spac_lines_correction_mode\plusone
+ \dosingleempty\spac_lines_start_correction}
+
+\unexpanded\def\startlocallinecorrection
+ {\endgraf
+ \begingroup
+ \setconstant\c_spac_lines_correction_mode\plustwo
+ \dosingleempty\spac_lines_start_correction}
+
+\unexpanded\def\spac_lines_start_correction[#1]%
+ {\edef\m_spac_lines_around{#1}%
+ \spac_lines_action_around
+ \d_spac_prevdepth\prevdepth
+ \spac_lines_initialize_corrections
+ \offbaselinecorrection % ???
+ \setbox\scratchbox\spac_lines_vbox\bgroup
+ \ifcase\c_spac_lines_correction_mode
+ % nothing
+ \or
+ % global
+ \or
+ % local
+ \setlocalhsize
+ \hsize\localhsize
+ \forgetbothskips
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\spac_lines_stop_correction
+ {\removeunwantedspaces
+ \egroup
+ \ifgridsnapping
+ \spac_lines_stop_correction_ongrid
+ \else
+ \spac_lines_stop_correction_normal
+ \fi
+ \endgroup}
+
+\unexpanded\def\spac_lines_stop_correction_ongrid
+ {\directcheckedvspacing\v!white % \blank[\v!white]%
+ \snaptogrid\hpack{\box\scratchbox}}
+
+\unexpanded\def\spac_lines_stop_correction_normal
+ {\directcheckedvspacing\v!nowhite % \blank[\v!nowhite]%
+ \ifdim\parskip>\zeropoint
+ % too fuzzy otherwise
+ \else
+ % doesn't like whitespace
+ \ifdim\d_spac_prevdepth<\maxdimen
+ \unless\ifdim\d_spac_prevdepth<\zeropoint
+ \ifdim\d_spac_prevdepth<\strutdp \relax
+ \pushlastnode
+ \ifdim\d_spac_prevdepth>\zeropoint
+ \kern-\d_spac_prevdepth
+ \fi
+ \kern\strutdp
+ \prevdepth\strutdp
+ \poplastnode
+ \fi
+ \fi
+ \fi
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ % \blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
+ \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_before}% \blank[\v!white]\dotopbaselinecorrection
+ \fi
+ \nointerlineskip % new
+ \noindent % not \dontleavehmode !
+ \ifcase\c_spac_lines_correction_mode
+ % nothing
+ \or
+ % global
+ \hskip-\leftskip % more tricky would be hangindent so we ignore that one
+ \or
+ % local
+ \fi
+ \box\scratchbox
+ \endgraf
+ %
+ % eventually i'll get it right ... (i also need to check all whitespace code elsewhere)
+ %
+ % \blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
+ % \directcheckedvspacing{\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
+ \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
+ % \allowbreak % new, otherwise problems when many in a row
+ \prevdepth\strutdp
+ \spac_lines_action_around}
+
+\let\stoplinecorrection \spac_lines_stop_correction
+\let\stoplocallinecorrection\spac_lines_stop_correction
+
+% todo:
+
+\unexpanded\def\correctwhitespace
+ {\dowithnextboxcs\correctwhitespacefinish\vbox}
+
+\unexpanded\def\correctwhitespacefinish
+ {\startbaselinecorrection
+ \flushnextbox
+ \stopbaselinecorrection}
+
+\unexpanded\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}}
+\unexpanded\def\horizontalstrut{\hpack {\strut}}
+
+% Hieronder volgen enkele instellingen en macro's ten behoeve
+% van de interlinie en \strut. De waarden 2.8, 0.07, 0.72 en
+% 0.28 zijn ooit eens ontleend aan INRS-TEX en moeten wellicht
+% nog eens instelbaar worden.
+%
+% \lineheight : de hoogte van een regel
+% \spacing{getal} : instellen interlinie
+% \normalbaselines : instellen regelafstend
+%
+% \setstrut : instellen \strut
+% \setnostrut : resetten \strut, \endstrut, \begstrut
+% \setnonestrut : resetten \strut (fast one)
+%
+% \setteststrut : instellen zichtbare struts
+% \resetteststrut : instellen onzichtbare struts
+%
+% \setfontparameters : instellen na fontset
+%
+% De hoogte van een regel (\lineheight) is gelijk aan de
+% som van de hoogte (\ht) en diepte (\dp) van \strutbox.
+%
+% \strut : denkbeeldig blokje met hoogte en diepte
+%
+% Een \hbox kan als deze aan het begin van een regel staat
+% een breedte \hsize krijgen. Dit is soms te voorkomen met het
+% commando \leavevmode. Binnen een \vbox geeft dit echter
+% niet altijd het gewenste resultaat, vandaar het commando
+%
+% \dontleavehmode
+
+% Pas op: niet zomaar \topskip en \baselineskip aanpassen
+% en zeker niet \widowpenalty. Dit kan ernstige gevolgen
+% hebben voor kolommen.
+%
+% Enige glue kan op zich geen kwaad, echter als blanko=vast,
+% dan moet ook de rek 0 zijn. Binnen kolommen is rek ook
+% niet bepaald mooi. Een hele kleine waarde (0.025) voldoet,
+% omdat een positieve glue eindeloos rekbaar is.
+
+% more of the next will become private:
+
+\newdimen\strutdimen
+\newdimen\lineheight
+\newdimen\openlineheight
+\newdimen\openstrutheight
+\newdimen\openstrutdepth
+\newdimen\topskipgap
+\newdimen\struttotal
+
+\def\strutheightfactor {.72}
+\def\strutdepthfactor {.28}
+
+\def\baselinefactor {2.8}
+
+\let\m_spac_vertical_baseline_stretch_factor \zerocount
+\let\m_spac_vertical_baseline_shrink_factor \zerocount
+
+\def\minimumstrutheight {\zeropoint}
+\def\minimumstrutdepth {\zeropoint}
+
+\def\normallineheight {\baselinefactor\exheight}
+\def\minimumlinedistance {\lineskip}
+
+\def\strutheight {\zeropoint}
+\def\strutdepth {\zeropoint}
+\def\strutwidth {\zeropoint}
+
+\let\spacingfactor \plusone
+
+\def\topskipfactor {1.0}
+\def\maxdepthfactor {0.5}
+
+\def\systemtopskipfactor {\topskipfactor}
+\def\systemmaxdepthfactor {\maxdepthfactor}
+
+\ifdefined\globalbodyfontsize \else
+ \newdimen\globalbodyfontsize
+ \globalbodyfontsize=12pt
+\fi
+
+\ifdefined\normalizedbodyfontsize \else
+ \def\normalizedbodyfontsize{12pt}
+\fi
+
+\unexpanded\def\topskipcorrection
+ {\simpletopskipcorrection
+ \vskip-\struttotal
+ \verticalstrut}
+
+\unexpanded\def\simpletopskipcorrection
+ {\ifdim\topskip>\openstrutheight
+ % == \vskip\topskipgap
+ \vskip\topskip
+ \vskip-\openstrutheight
+ \fi}
+
+\unexpanded\def\settopskip % the extra test is needed for the lbr family
+ {\topskip
+ \ifgridsnapping
+ \zeropoint
+ \else
+ \systemtopskipfactor\globalbodyfontsize
+ \ifcase\bottomraggednessmode % ragged bottom
+ \s!plus5\globalbodyfontsize
+ \fi
+ \fi
+ %\relax
+ \topskipgap\topskip
+ \advance\topskipgap -\openstrutheight\relax
+ \ifdim\minimumstrutheight>\zeropoint
+ \ifdim\topskip<\minimumstrutheight
+ \topskip\minimumstrutheight\relax
+ \fi
+ \else
+ \ifdim\topskip<\strutheightfactor\openlineheight
+ \topskip\strutheightfactor\openlineheight\relax
+ \fi
+ \fi}
+
+\unexpanded\def\setmaxdepth
+ {\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
+
+\let\normalbaselineskip \relax \newskip \normalbaselineskip % these got lost in the transition to mkiv due
+\let\normallineskip \relax \newskip \normallineskip % to auto-\normal* definitions and registers
+\let\normallineskiplimit\relax \newdimen\normallineskiplimit % being protected
+
+\unexpanded\def\normalbaselines
+ {\baselineskip \normalbaselineskip
+ \lineskip \normallineskip
+ \lineskiplimit\normallineskiplimit}
+
+\unexpanded\def\flexiblebaselines
+ {\baselineskip \normalbaselineskip
+ \lineskip 1\normallineskip \s!plus 1\s!fill
+ \lineskiplimit\normallineskiplimit}
+
+\unexpanded\def\setnormalbaselines
+ {\ifdim\normallineheight>\zeropoint
+ \lineheight\normallineheight
+ \fi
+ \openlineheight\spacingfactor\lineheight
+ \openstrutheight \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight % new
+ \else
+ \strutheightfactor\openlineheight
+ \fi
+ \openstrutdepth \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth % new
+ \else
+ \strutdepthfactor \openlineheight
+ \fi
+ \ifdim\dimexpr\minimumstrutdepth+\minimumstrutheight\relax>\zeropoint
+ \openlineheight\dimexpr\openstrutheight+\openstrutdepth\relax % new
+ \fi
+ \normalbaselineskip\openlineheight
+ \ifgridsnapping\else
+ \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight
+ \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight
+ \fi
+ \normallineskip\minimumlinedistance\relax % \onepoint\relax
+ \normallineskiplimit\zeropoint\relax
+ \normalbaselines}
+
+\unexpanded\def\spacing#1% vertical
+ {\ifgridsnapping
+ \let\spacingfactor\plusone
+ \else
+ \edef\spacingfactor{#1}%
+ \fi
+ \edef\systemtopskipfactor {\withoutpt\the\dimexpr#1\dimexpr\topskipfactor \points}%
+ \edef\systemmaxdepthfactor{\withoutpt\the\dimexpr#1\dimexpr\maxdepthfactor\points}%
+ \setnormalbaselines
+ \setstrut}
+
+% \unexpanded\def\forgetverticalstretch % \forgetspacing
+% {\spacing\plusone}
+
+\unexpanded\def\forgetverticalstretch
+ {\let\spacingfactor \plusone
+ \let\systemtopskipfactor \topskipfactor
+ \let\systemmaxdepthfactor\maxdepthfactor
+ \setnormalbaselines
+ \setstrut}
+
+\appendtoks
+ \forgetverticalstretch
+\to \everyforgetall % needed in otr
+
+%D Sometimes one needs to freeze the interlinespacing
+%D
+%D \starttyping
+%D \rm \saveinterlinespace .... {\ss \restoreinterlinespace .... \endgraf}
+%D \stoptyping
+
+\let\restoreinterlinespace\relax
+
+\unexpanded\def\saveinterlinespace
+ {\unexpanded\edef\restoreinterlinespace
+ {\lineheight \the\lineheight
+ \openstrutheight \the\openstrutheight
+ \openstrutdepth \the\openstrutdepth
+ \openlineheight \the\openlineheight
+ \normalbaselineskip \the\normalbaselineskip
+ \normallineskip \the\normallineskip
+ \normallineskiplimit\the\normallineskiplimit
+ \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}%
+ \noexpand\normalbaselines}}
+
+% plain definition:
+%
+% \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+%
+% could be:
+%
+% \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+
+\newbox\strutbox
+
+\setbox\strutbox\hpack{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start
+
+\def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+
+% \unexpanded\def\strut
+% {\relax
+% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
+
+\let\normalstrut\strut
+
+% The double \hbox construction enables us to \backtrack
+% boxes.
+
+\let\strutht\undefined \newdimen\strutht
+\let\strutdp\undefined \newdimen\strutdp
+
+\unexpanded\def\setstrut
+ {\ifgridsnapping
+ \setstrutgridyes
+ \else
+ \setstrutgridnop
+ \fi}
+
+\unexpanded\def\setstrutgridyes
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \normallineheight-\strutht
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setstrutgridnop
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\spacingfactor\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \strutdepthfactor\dimexpr\normallineheight
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setcharstrut#1%
+ {\setbox\strutbox\hbox{#1}% hm, maybe hpack i.e. why apply fonts .. conceptual choice
+ \strutht\ht\strutbox
+ \strutdp\dp\strutbox
+ \dosetstrut}
+
+\unexpanded\def\setfontstrut
+ {\setcharstrut{(gplQT}}
+
+\unexpanded\def\setcapstrut% could be M, but Q has descender
+ {\setcharstrut{Q}}
+
+%D Handy for math (used in mathml):
+
+\unexpanded\def\charhtstrut
+ {\begingroup
+ \setcharstrut{GJY}%
+ \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht
+ \endgroup}
+
+\unexpanded\def\chardpstrut
+ {\begingroup
+ \setcharstrut{gjy}%
+ \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint
+ \endgroup}
+
+% because of all the callbacks in mkiv, we avoid unnecessary boxes ...
+% maybe use an attribute so that we can tag boxes that don't need a
+% treatment; tests with using an attribute so far have shown that
+% it's slower because testing the attribute takes time too
+
+\unexpanded\def\dosetstrut
+ {\let\strut\normalstrut
+ \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo
+ % compensate rounding error /- 1sp to avoid too many
+ % 1sp baselineskips in for instance verbatim
+ % \strutht\dimexpr\lineheight-\strutdp\relax
+ % better:
+ \strutdp\dimexpr\lineheight-\strutht\relax
+ \struttotal\lineheight
+ \else
+ \struttotal\dimexpr\strutht+\strutdp\relax
+ \fi
+ \edef\strutheight{\the\strutht}%
+ \edef\strutdepth {\the\strutdp}%
+ \ifdim\strutwidth=\zeropoint
+ \spac_struts_set_hide
+ \else
+ \spac_struts_set_vide
+ \fi}
+
+\def\spac_struts_set_hide
+ {\setbox\strutbox\hpack
+ {\vrule
+ \s!width \zeropoint
+ \s!height\strutht
+ \s!depth \strutdp}}
+
+\newconstant\c_strut_visual_mode
+
+\def\spac_struts_set_vide
+ {\setbox\strutbox\hpack % at some time this extra wrapping was needed
+ {\spac_struts_vide_hbox to \zeropoint
+ {\ifcase\c_strut_visual_mode
+ \spac_struts_black
+ \or
+ \spac_struts_color
+ \else
+ \spac_struts_black
+ \fi}}}
+
+\def\spac_struts_black
+ {\vrule
+ \s!width \strutwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \hss}
+
+\def\spac_struts_color
+ {\hss % new, will be option
+ \scratchwidth.1\struthtdp
+ \begingroup
+ \directcolor[f:b:t]%
+ \vrule
+ \s!width \scratchwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \kern-\scratchwidth
+ \vrule
+ \s!width \scratchwidth
+ \s!height\zeropoint
+ \s!depth \strutdp
+ \endgroup
+ \kern-.625\scratchwidth
+ \vrule
+ \s!width .25\scratchwidth
+ \s!height\strutht
+ \s!depth \strutdp
+ \hss}
+
+\let\spac_struts_vide_hbox\hbox % overloaded in trac-vis.mkiv
+
+%D The dimen \type {\struttotal} holds the exact size of the
+%D strut; occasionally a one scaled point difference can show
+%D up with the lineheight.
+
+% This is more efficient (less callbacks):
+
+\newbox\b_spac_struts_empty \setbox\b_spac_struts_empty\emptyhbox
+
+\def\spac_struts_set_hide
+ {\setbox\strutbox\copy\b_spac_struts_empty
+ \ht\strutbox\strutht
+ \dp\strutbox\strutdp}
+
+\unexpanded\def\strut % still callbacks for \hbox{\strut}
+ {\relax
+ \dontleavehmode
+ \copy\strutbox}
+
+% \unexpanded\def\strut % slightly faster
+% {\relax
+% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
+
+\let\normalstrut\strut
+
+\unexpanded\def\halfstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht/\plustwo\relax
+ \dp\scratchbox\dimexpr\strutdp/\plustwo\relax
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\quarterstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht/\plusfour\relax
+ \dp\scratchbox\dimexpr\strutdp/\plusfour\relax
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\depthstrut
+ {\relax
+ \dontleavehmode
+ \begingroup
+ \setbox\scratchbox\copy\strutbox
+ \ht\scratchbox\dimexpr\strutht-\struthtdp/\plustwo\relax % assumes that ht > lineheight/2
+ \box\scratchbox
+ \endgroup}
+
+%D Sometimes a capstrut comes in handy
+%D
+%D \starttabulate[|Tl|l|l|]
+%D \NC yes \NC normal strut \NC {\showstruts\setupstrut[yes]\strut} \NC \NR
+%D \NC no \NC no strut \NC {\showstruts\setupstrut[no]\strut} \NC \NR
+%D \NC kap \NC a capital strut (i.e. Q) \NC {\showstruts\setupstrut[cap]\strut} \NC \NR
+%D \NC A B \unknown \NC a character strut (e.g. A) \NC {\showstruts\setupstrut[A]\strut} \NC \NR
+%D \NC \NC a normal strut \NC {\showstruts\setupstrut\strut} \NC \NR
+%D \stoptabulate
+
+%D Beware: using an unknown value results in char struts.
+
+\installcorenamespace{struts}
+
+\unexpanded\def\setupstrut
+ {\dosingleempty\spac_struts_setup}
+
+\def\spac_struts_setup[#1]%
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut\m_strut
+ \fi}
+
+\unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut\m_strut
+ \fi}
+
+\unexpanded\def\dosynchronizestrut#1% no [] parsing, faster for internal
+ {\ifcsname\??struts#1\endcsname
+ \lastnamedcs
+ \else
+ \setcharstrut{#1}%
+ \fi}
+
+\unexpanded\def\showstruts % adapts .. is wrong
+ {\c_strut_visual_mode\zerocount
+ \setteststrut
+ \settestcrlf}
+
+\unexpanded\def\showcolorstruts % adapts .. is wrong
+ {\c_strut_visual_mode\plusone
+ \setteststrut
+ \settestcrlf}
+
+\unexpanded\def\setteststrut
+ {\def\strutwidth{.8pt}%
+ \setstrut}
+
+\unexpanded\def\dontshowstruts
+ {\unsetteststrut
+ \settestcrlf}
+
+\unexpanded\def\unsetteststrut
+ {\let\strutwidth\zeropoint
+ \setstrut}
+
+\def\autostrutfactor{1.1}
+
+\unexpanded\def\setautostrut
+ {\begingroup
+ \setbox\scratchbox\copy\strutbox
+ \setstrut
+ \ifdim\strutht>\autostrutfactor\ht\scratchbox
+ \endgroup \setstrut
+ \else\ifdim\strutdp>\autostrutfactor\dp\scratchbox
+ \endgroup \setstrut
+ \else
+ \endgroup
+ \fi\fi}
+
+\newbox\nostrutbox \setbox\nostrutbox\emptyhbox
+
+\newtoks\everysetnostrut
+
+\unexpanded\def\setnostrut
+ {\the\everysetnostrut}
+
+\appendtoks
+ \setbox\strutbox\copy\nostrutbox
+ \let\strut\empty
+ \let\endstrut\empty
+ \let\begstrut\empty
+\to \everysetnostrut
+
+% when enabled, sigstruts will remove themselves if nothing
+% goes inbetween
+
+%D For poractical reasons we define some boundary characters here.
+
+\unexpanded\def\leftboundary {\protrusionboundary\plusone}
+\unexpanded\def\rightboundary {\protrusionboundary\plustwo}
+\unexpanded\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals
+
+\newsignal\strutsignal \setfalse\sigstruts
+
+\unexpanded\def\begstrut
+ {\relax\ifcase\strutht
+ % \ignorespaces % maybe
+ \else
+ \spac_struts_beg
+ \fi}
+
+\def\spac_struts_beg
+ {\ifconditional\sigstruts
+ \spac_struts_beg_signal
+ \else
+ \spac_struts_beg_normal
+ \fi
+ \ignorespaces}
+
+\def\spac_struts_beg_signal
+ {\noindent\horizontalstrut
+ \penalty\plustenthousand
+ \hskip-\strutsignal
+ \hskip\strutsignal}
+
+% \def\spac_struts_beg_normal
+% {\strut
+% \penalty\plustenthousand
+% \hskip\zeropoint}
+
+\def\spac_struts_beg_normal
+ {\boundary\plusone
+ \strut
+ %\boundary\plusone
+ \penalty\plustenthousand
+ %\boundary\plusone
+ \hskip\zeropoint}
+
+\unexpanded\def\endstrut
+ {\relax\ifhmode
+ \ifcase\strutht
+ % \removeunwantedspaces % maybe
+ \else
+ \spac_struts_end
+ \fi
+ \fi}
+
+\def\spac_struts_end
+ {\ifconditional\sigstruts
+ \spac_struts_end_signal
+ \else
+ \spac_struts_end_normal
+ \fi}
+
+\def\spac_struts_end_signal
+ {\ifdim\lastskip=\strutsignal
+ \unskip
+ \unskip
+ \unpenalty
+ \setbox\scratchbox\lastbox
+ \else
+ \penalty\plustenthousand
+ \hskip\zeropoint
+ \strut
+ \fi}
+
+% \def\spac_struts_end_normal
+% {\removeunwantedspaces
+% \penalty\plustenthousand
+% \hskip\zeropoint
+% \strut}
+
+\def\spac_struts_end_normal
+ {\removeunwantedspaces
+ \penalty\plustenthousand
+ %\boundary\plustwo
+ \hskip\zeropoint
+ %\boundary\plustwo
+ \strut
+ \boundary\plustwo}
+
+% unsave:
+%
+% \def\pseudostrut
+% {\bgroup
+% \setnostrut
+% \normalstrut
+% \egroup}
+%
+% try:
+%
+% \startchemie
+% \chemie[ONE,Z0,SB15,MOV1,SB15,Z0][C,C]
+% \stopchemie
+%
+% so:
+
+\unexpanded\def\pseudostrut
+ {\noindent} % better: \dontleavehmode
+
+\let\pseudobegstrut\pseudostrut
+\let\pseudoendstrut\removeunwantedspaces
+
+\unexpanded\def\resetteststrut
+ {\def\strutwidth{\zeropoint}% no let
+ \setstrut}
+
+\ifdefined\setfontparameters \else
+ \def\setfontparameters{\the\everybodyfont}
+\fi
+
+%D Keyword based strutting:
+
+\letvalue{\??struts\v!yes }\setstrut % \setvalue{\??struts\v!yes }{\setstrut}
+\letvalue{\??struts\v!auto }\setautostrut % \setvalue{\??struts\v!auto }{\setautostrut}
+\letvalue{\??struts\v!no }\setnostrut % \setvalue{\??struts\v!no }{\setnostrut}
+\letvalue{\??struts\v!cap }\setcapstrut % \setvalue{\??struts\v!cap }{\setcapstrut}
+\letvalue{\??struts\v!fit }\setfontstrut % \setvalue{\??struts\v!fit }{\setfontstrut}
+\letvalue{\??struts\v!line }\setstrut % \setvalue{\??struts\v!line }{\setstrut}
+\letvalue{\??struts\s!default}\setstrut % \setvalue{\??struts\s!default}{\setstrut}
+\letvalue{\??struts\empty }\setstrut % \setvalue{\??struts\empty }{\setstrut}
+
+%D Handy:
+
+\def\baselinedistance{\the\lineheight}
+
+%D We need \type{\normaloffinterlineskip} because the new
+%D definition contains an assignment, and |<|don't ask me
+%D why|>| this assignment gives troubles in for instance the
+%D visual debugger.
+
+\unexpanded\def\offinterlineskip
+ {\baselineskip-\thousandpoint
+ \lineskip \zeropoint
+ \lineskiplimit\maxdimen
+ % We also need this here now; thanks to taco for figuring that out!
+ \def\minimumlinedistance{\zeropoint}}
+
+\unexpanded\def\nointerlineskip
+ {\prevdepth-\thousandpoint}
+
+\let\normaloffinterlineskip\offinterlineskip % knuth's original
+
+\appendtoks
+ \ifvmode\clf_resetprevdepth\fi % a nasty hack (tested for a while now)
+\to \everyafteroutput
+
+%D My own one:
+
+\unexpanded\def\spac_helpers_push_interlineskip_yes
+ {\edef\oninterlineskip
+ {\baselineskip \the\baselineskip
+ \lineskip \the\lineskip
+ \lineskiplimit\the\lineskiplimit
+ \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}%
+ \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
+
+\unexpanded\def\spac_helpers_push_interlineskip_nop
+ {\let\oninterlineskip\setnormalbaselines}
+
+\unexpanded\def\offinterlineskip
+ {\ifdim\baselineskip>\zeropoint
+ \spac_helpers_push_interlineskip_yes
+ \else
+ \spac_helpers_push_interlineskip_nop
+ \fi
+ \normaloffinterlineskip}
+
+\let\oninterlineskip\relax
+
+\unexpanded\def\leaveoutervmode
+ {\ifvmode\ifinner\else
+ \leavevmode
+ \fi\fi}
+
+\unexpanded\def\resetpenalties#1%
+ {\ifdefined#1%
+ #1\minusone
+ \fi}
+
+\unexpanded\def\setpenalties#1#2#3%
+ {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text
+ #1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax
+ \fi}
+
+%D \macros
+%D {keeplinestogether}
+%D
+%D Dirty hack, needed in margin content that can run of a page.
+
+% just before margintexts ... will eventually be done differently in mkiv using
+% attributes
+
+\newcount\c_spac_keep_lines_together
+\let\restoreinterlinepenalty\relax
+
+\unexpanded\def\spac_penalties_restore
+ {\global\let\restoreinterlinepenalty\relax
+ \global\resetpenalties\interlinepenalties
+ \global\c_spac_keep_lines_together\zerocount}
+
+\unexpanded\def\keeplinestogether#1%
+ {\ifnum#1>\c_spac_keep_lines_together
+ \global\c_spac_keep_lines_together#1%
+ \global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
+ \global\let\restoreinterlinepenalty\spac_penalties_restore
+ \fi}
+
+\newif\ifgridsnapping % to be sure
+
+\def\defaultwidowpenalty {2000} % was: 1000
+\def\defaultclubpenalty {2000} % was: 800
+\def\defaultdisplaywidowpenalty {50}
+\def\defaultbrokenpenalty {100}
+
+\def\defaultgridwidowpenalty {0}
+\def\defaultgridclubpenalty {0}
+\def\defaultgriddisplaywidowpenalty {0}
+\def\defaultgridbrokenpenalty {0}
+
+\unexpanded\def\nopenalties
+ {\widowpenalty \zerocount
+ \clubpenalty \zerocount
+ \brokenpenalty \zerocount
+ \doublehyphendemerits\zerocount
+ \finalhyphendemerits \zerocount
+ \adjdemerits \zerocount}
+
+\unexpanded\def\setdefaultpenalties
+ {\directsetup{\systemsetupsprefix\s!default}}
+
+\startsetups [\systemsetupsprefix\s!reset]
+ \resetpenalties\widowpenalties
+ \resetpenalties\clubpenalties
+ \resetpenalties\interlinepenalties
+\stopsetups
+
+% we use \directsetup because it's faster and we know there is no csl
+
+\startsetups [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultwidowpenalty
+ \clubpenalty \defaultclubpenalty
+ \displaywidowpenalty\defaultdisplaywidowpenalty
+ \brokenpenalty \defaultbrokenpenalty
+
+\stopsetups
+
+\startsetups [\v!grid] [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultgridwidowpenalty
+ \clubpenalty \defaultgridclubpenalty
+ \displaywidowpenalty\defaultgriddisplaywidowpenalty
+ \brokenpenalty \defaultgridbrokenpenalty
+
+\stopsetups
+
+% as an illustration:
+
+\startsetups [\systemsetupsprefix\v!strict]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \setpenalties\widowpenalties\plustwo\maxdimen
+ \setpenalties\clubpenalties \plustwo\maxdimen
+ \brokenpenalty \maxdimen
+
+\stopsetups
+
+\setdefaultpenalties % will happen later in \setuplayout
+
+%D To be checked:
+
+\newbox\b_spac_struts_saved
+
+\unexpanded\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox}
+\unexpanded\def\savedstrut{\copy \b_spac_struts_saved}
+
+%D Good old blank redone:
+
+%definesystemattribute[kernchars] [public]
+\definesystemattribute[skipcategory] [public]
+\definesystemattribute[skippenalty] [public]
+\definesystemattribute[skiporder] [public]
+\definesystemattribute[snapmethod] [public]
+\definesystemattribute[snapvbox] [public]
+%definesystemattribute[snapcategory] [public]
+
+% TODO: NAMED SNAPPERS
+
+\installcorenamespace{gridsnappers}
+\installcorenamespace{gridsnapperattributes}
+
+\newskip \bodyfontlineheight
+\newdimen \bodyfontstrutheight
+\newdimen \bodyfontstrutdepth
+
+\newskip \globalbodyfontlineheight
+\newdimen \globalbodyfontstrutheight
+\newdimen \globalbodyfontstrutdepth
+
+\def\snappedvboxattribute{\ifgridsnapping attr \snapvboxattribute \attribute\snapmethodattribute\fi}
+\def\setlocalgridsnapping{\ifgridsnapping \attribute \snapvboxattribute \attribute\snapmethodattribute\fi}
+
+\def\spac_grids_set_local_snapping#1%
+ {\ifgridsnapping
+ \doifsomething{#1}%
+ {\spac_grids_snap_value_set{#1}%
+ \attribute \snapvboxattribute \attribute\snapmethodattribute}%
+ \fi}
+
+\unexpanded\def\installsnapvalues#1#2% todo: a proper define
+ {\edef\currentsnapper{#1:#2}%
+ \ifcsname\??gridsnapperattributes\currentsnapper\endcsname \else
+ \setevalue{\??gridsnapperattributes\currentsnapper}{\clf_definesnapmethod{#1}{#2}}%
+ \fi
+ \setevalue{\??gridsnappers#1}{\attribute\snapmethodattribute\csname\??gridsnapperattributes\currentsnapper\endcsname\space}}
+
+\unexpanded\def\usegridparameter#1% no checking here
+ {\edef\m_spac_grid_asked{#1\c!grid}%
+ \ifx\m_spac_grid_asked\empty
+ \attribute \snapvboxattribute\attributeunsetvalue
+ \else
+ \spac_grids_snap_value_set\m_spac_grid_asked
+ \attribute \snapvboxattribute\attribute\snapmethodattribute
+ \fi}
+
+
+\unexpanded\def\definegridsnapping
+ {\dodoubleargument\spac_grids_define}
+
+\def\spac_grids_define[#1][#2]%
+ {\installsnapvalues{#1}{#2}}
+
+\edef\spac_grids_snap_value_reset
+ {%\gridsnappingfalse
+ \attribute\snapmethodattribute\attributeunsetvalue}
+
+\def\spac_grids_snap_value_set#1%
+ {%\gridsnappingtrue
+ \begincsname\??gridsnappers#1\endcsname}
+
+\def\spac_grids_snap_value_auto#1%
+ {\ifcsname\??gridsnappers#1\endcsname
+ \lastnamedcs
+ \else
+ \installsnapvalues\s!dummy{#1}%
+ \csname\??gridsnappers\s!dummy\endcsname
+ \fi}
+
+% \installsnapvalues{loose} {\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut}
+% \installsnapvalues{normal}{\v!maxdepth:1.0,\v!maxheight:1.0,\v!strut}
+% \installsnapvalues{tight} {\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut}
+
+% none don't enlarge
+% halfline enlarge by halfline/halfline
+% line enlarge by line/line
+% strut enlarge by ht/dp (default)
+% first align to top line
+% last align to bottom line
+% mindepth round depth down
+% maxdepth round depth up
+% minheight round height down
+% maxheight round height up
+% local use local interline space
+% offset:-3tp vertical shift within box
+% bottom:lines
+% top:lines
+
+%D We're not downward compatible with \MKII !
+
+\definegridsnapping[\v!normal] [\v!maxheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!standard] [\v!maxheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!yes] [\v!maxheight,\v!maxdepth,\v!strut]
+
+\definegridsnapping[\v!strict] [\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut]
+\definegridsnapping[\v!tolerant] [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut]
+
+\definegridsnapping[\v!top] [\v!minheight,\v!maxdepth,\v!strut]
+\definegridsnapping[\v!bottom] [\v!maxheight,\v!mindepth,\v!strut]
+\definegridsnapping[\v!both] [\v!minheight,\v!mindepth,\v!strut]
+
+\definegridsnapping[\v!broad] [\v!maxheight,\v!maxdepth,\v!strut,0.8] % maybe 0.85
+\definegridsnapping[\v!fit] [\v!maxheight,\v!maxdepth,\v!strut,1.2] % tight 0.15
+
+\definegridsnapping[\v!first] [\v!first]
+\definegridsnapping[\v!last] [\v!last]
+\definegridsnapping[\v!high] [\v!minheight,\v!maxdepth,\v!none]
+\definegridsnapping[\v!one] [\v!minheight,\v!mindepth]
+\definegridsnapping[\v!low] [\v!maxheight,\v!mindepth,\v!none]
+\definegridsnapping[\v!none] [\v!none]
+\definegridsnapping[\v!line] [\v!line]
+\definegridsnapping[\v!strut] [\v!strut]
+\definegridsnapping[\v!box] [\v!box] % centers a box rounded upwards (box:.5 -> tolerance)
+\definegridsnapping[\v!min] [\v!min] % centers a box rounded downwards
+\definegridsnapping[\v!max] [\v!max] % centers a box rounded upwards
+
+\definegridsnapping[\v!max] [\v!maxdepth,\v!maxheight,\v!strut]
+\definegridsnapping[\v!min] [\v!mindepth,\v!minheight,\v!strut]
+
+\definegridsnapping[\v!middle] [\v!maxheight,\v!maxdepth] % used in placement
+
+\unexpanded\def\synchronizelocallinespecs
+ {\bodyfontlineheight \normallineheight
+ \bodyfontstrutheight\strutht
+ \bodyfontstrutdepth \strutdp}
+
+\unexpanded\def\synchronizegloballinespecs
+ {\global\globalbodyfontlineheight \normallineheight
+ \global\globalbodyfontstrutheight\strutht
+ \global\globalbodyfontstrutdepth \strutdp}
+
+\appendtoks
+ \synchronizegloballinespecs
+ \synchronizelocallinespecs
+\to \everysetupglobalinterlinespace
+
+\appendtoks
+ \synchronizelocallinespecs
+\to \everysetuplocalinterlinespace
+
+%D We still have to synchronize these:
+
+\unexpanded\def\synchronizeskipamounts
+ {\bigskipamount
+ \skipfactor\baselineskip
+ plus\skipgluefactor\baselineskip
+ minus\skipgluefactor\baselineskip
+ \relax
+ \medskipamount \bigskipamount \divide\medskipamount \plustwo
+ \smallskipamount\bigskipamount \divide\smallskipamount\plusfour}
+
+\appendtoks
+ \synchronizeskipamounts
+\to \everysetupglobalinterlinespace
+
+\appendtoks
+ \synchronizeskipamounts
+\to \everysetuplocalinterlinespace
+
+%D Snapping.
+
+\newif\ifgridsnapping
+
+\let\showgridsnapping\relax
+
+%unexpanded\def\moveongrid {\dosingleempty\spac_grids_move_on}
+\unexpanded\def\snaptogrid {\dosingleempty\spac_grids_snap_to}
+\unexpanded\def\placeongrid{\dosingleempty\spac_grids_place_on}
+
+\unexpanded\def\startgridsnapping
+ {\dosingleempty\spac_grids_start_snapping}
+
+\unexpanded\def\spac_grids_start_snapping[#1]%
+ {\snaptogrid[#1]\vbox\bgroup}
+
+\unexpanded\def\stopgridsnapping
+ {\egroup}
+
+% \def\spac_grids_move_on[#1]%
+% {[obsolete]} % gone, unless we set an attribute
+
+\def\spac_grids_place_on[#1]%
+ {\snaptogrid[#1]\vbox} % mark as done
+
+\def\spac_grids_snap_to[#1]% list or predefined
+ {\ifgridsnapping
+ \expandafter\spac_grids_snap_to_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi{#1}}
+
+\def\spac_grids_snap_to_indeed#1%
+ {\bgroup
+ \spac_grids_snap_value_reset
+ \dowithnextbox{\spac_grids_snap_to_finish{#1}}}
+
+% eventually there will always be a line snap
+
+\def\spac_grids_snap_to_finish#1%
+ {\ifvbox\nextbox % this will go away
+ \clf_vspacingcollapse\nextbox\relax % isn't that already done?
+ \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 ?
+ \egroup}
+
+\def\spac_grids_check_nop
+ {\gridsnappingfalse
+ \resetsystemmode\v!grid
+ \spac_grids_snap_value_reset}
+
+\def\spac_grids_check_yes
+ {\gridsnappingtrue
+ \setsystemmode\v!grid
+ \spac_grids_snap_value_set\askedgridmode}
+
+\unexpanded\def\synchronizegridsnapping
+ {\edef\askedgridmode{\layoutparameter\c!grid}%
+ \ifx\askedgridmode\v!no % official
+ \spac_grids_check_nop
+ \else\ifx\askedgridmode\v!off % for taco and luigi
+ \spac_grids_check_nop
+ \else\ifx\askedgridmode\empty % to be sure
+ \spac_grids_check_nop
+ \else
+ \spac_grids_check_yes
+ \fi\fi\fi}
+
+%D Visualization:
+
+\definepalet
+ [grid]
+ [ one=red,
+ two=green,
+ three=blue,
+ four=gray]
+
+\unexpanded\def\setgridtracebox#1[#2]% % maybe reverse the order
+ {\setbox\nextbox#1%
+ {\hbox
+ {\hbox to \zeropoint
+ {\setlayoutcomponentattribute{\v!grid:\v!test}%
+ \color[grid:#2]{\ruledhbox \layoutcomponentboxattribute {\fakebox\nextbox}}%
+ \hss}%
+ \flushnextbox}}}
+
+\setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r
+\setnewconstant\gridboxlinemode \plusone
+
+\unexpanded\def\gridboxvbox
+ {\ifcase\gridboxlinemode
+ \vbox
+ \or
+ \ruledvbox
+ \or
+ \vbox
+ \or
+ \ruledvbox
+ \else
+ \ruledvbox
+ \fi}
+
+\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
+
+\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
+ {\setbox#1\gridboxvbox to #3 % given size
+ {\forgetall
+ \resetvisualizers
+ \resetteststrut
+ \offinterlineskip
+ \hsize#2%
+ \ifnum\gridboxlinenomode=\plusthree
+ \gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi
+ \fi
+ \topskipcorrection
+ \gridboxvbox % calculated size
+ {\getrawnoflines{#3}% \getnoflines{#3}%
+ \scratchdimen\dimexpr#2+\lineheight\relax
+ \dorecurse\noflines
+ {\strut
+ \hskip-.5\lineheight\relax
+ \ifcase\gridboxlinenomode\or
+ \rlap
+ {\hskip\dimexpr.2\bodyfontsize+\scratchdimen\relax
+ \infofont\hbox to \emwidth{\hss\recurselevel}}%
+ \or
+ \llap
+ {\infofont\hbox to \emwidth{\hss\recurselevel}%
+ \hskip.2\bodyfontsize}%
+ \fi
+ \vrule
+ \s!height \gridboxwidth
+ \s!depth \gridboxwidth
+ \s!width \scratchdimen
+ \par}}
+ \vfill}}
+
+%D This has become obsolete:
+
+\def\fuzzysnappedbox#1#2% \box<n> \unvbox<n>
+ {#1#2}
+
+\def\moveboxontogrid#1#2#3% will become obsolete, but it needs checking
+ {}
+
+%D Helper:
+
+\unexpanded\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
+ {\doifelse{#2}\v!line
+ {#1\ifgridsnapping
+ \bodyfontlineheight
+ \else
+ \openlineheight
+ \fi}
+ {\ifgridsnapping
+ \assigndimension{#2}{#1}{.25\bodyfontlineheight}{.5\bodyfontlineheight}\bodyfontlineheight
+ \else
+ \assigndimension{#2}{#1}\smallskipamount\medskipamount\bigskipamount
+ \fi}%
+ \relax}
+
+% \start \dosetstretch{.25em} \setuptolerance[tolerant,stretch] \input tufte \endgraf \stop
+% \start \dosetstretch{.5em} effe flink doorfietsen \stop
+
+% experimental code, not yet interfaced:
+
+% category:
+%
+% 0 == discard discard
+% 1 == only if larger largest
+% 2 == force even if smaller force
+% 3 == only take penalty component penalty
+% 4 == add to existing skip add
+% 5 == disable (ignore following) disable
+% 6 == kill whitespace nowhite
+% 7 == discard previous back
+% 10 == no topskip
+%
+% penalty: larger wins
+% order: larger wins
+% category:2,order:5,penalty:10000,skip:value|kw
+%
+% \defineblankmethod [\v!joinedup] {\ifvmode\nointerlineskip\fi}
+
+% todo, in grid mode: builders.vspacing.fixed = false
+%
+% \ifgridsnapping will go
+
+\installcorenamespace{vspacingamount}
+
+\unexpanded\def\definevspacingamount
+ {\dotripleempty\spac_vspacing_define_amount}
+
+\def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
+ {\ifthirdargument
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}%
+ \else\ifsecondargument
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}%
+ \else
+ \setvalue{\??vspacingamount#1}{\lineheight}%
+ \fi\fi
+ \clf_vspacingsetamount{#1}}
+
+\def\spac_vspacing_no_topskip % use grouped
+ {\attribute\skipcategoryattribute\plusten}
+
+% \installcorenamespace{vspacingamountnormal}
+% \installcorenamespace{vspacingamountgrid}
+
+% \def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
+% {\ifcsname n>#1\endcsname\else
+% \expandafter\newtoks\csname n>#1\endcsname
+% \expandafter\newtoks\csname g>#1\endcsname
+% \fi
+% \csname n>#1\endcsname{#2}%
+% \csname g>#1\endcsname{#3}%
+% \clf_vspacingsetamount{#1}}
+
+\unexpanded\def\definevspacing
+ {\dodoubleempty\spac_vspacing_define}
+
+\def\spac_vspacing_define[#1][#2]%
+ {\clf_vspacingdefine{#1}{#2}}
+
+%D The injector code (generated at the \LUA\ end):
+
+\newtoks\everybeforeblankhandling
+\newtoks\everyafterblankhandling
+
+\newconditional\c_space_vspacing_done
+\newconditional\c_space_vspacing_fixed
+
+\appendtoks
+ \s_spac_vspacing_temp\zeropoint
+ \attribute\skipcategoryattribute\plusone
+ \attribute\skippenaltyattribute \attributeunsetvalue
+ \attribute\skiporderattribute \attributeunsetvalue
+ \ifgridsnapping
+ \settrue\c_space_vspacing_fixed
+ \else
+ \setfalse\c_space_vspacing_fixed
+ \fi
+\to \everybeforeblankhandling
+
+\appendtoks
+ \s_spac_vspacing_temp\plusone\s_spac_vspacing_temp
+ \ifconditional\c_space_vspacing_fixed \else
+ \s!plus \skipgluefactor\s_spac_vspacing_temp
+ \s!minus\skipgluefactor\s_spac_vspacing_temp
+ \fi
+ \relax
+\to \everyafterblankhandling
+
+\unexpanded\def\setblankcategory#1%
+ {\settrue\c_space_vspacing_done
+ \attribute\skipcategoryattribute#1\relax}
+
+\unexpanded\def\setblankorder#1%
+ {\attribute\skiporderattribute#1\relax}
+
+\unexpanded\def\fixedblankskip
+ {\settrue\c_space_vspacing_fixed}
+
+\unexpanded\def\flexibleblankskip
+ {\setfalse\c_space_vspacing_fixed}
+
+% \unexpanded\def\addblankskip#1#2#3%
+% {\settrue\c_space_vspacing_done
+% \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
+
+\unexpanded\def\setblankpenalty#1%
+ {\flushblankhandling
+ \settrue\c_space_vspacing_done
+ \attribute\skipcategoryattribute \plusthree
+ \attribute\skippenaltyattribute #1\relax
+ \flushblankhandling}
+
+\unexpanded\def\startblankhandling % move this to \vspacing
+ {\par
+ \ifvmode
+ \expandafter\dostartblankhandling
+ \else
+ \expandafter\nostartblankhandling
+ \fi}
+
+\def\nostartblankhandling#1\stopblankhandling
+ {}
+
+\def\dostartblankhandling
+ {\begingroup
+ \setfalse\c_space_vspacing_done
+ \the\everybeforeblankhandling}
+
+\unexpanded\def\stopblankhandling
+ {\the\everyafterblankhandling
+ \ifconditional\c_space_vspacing_done
+ \vskip\s_spac_vspacing_temp
+ \fi
+ \endgroup}
+
+\unexpanded\def\flushblankhandling
+ {\the\everyafterblankhandling
+ \ifconditional\c_space_vspacing_done
+ \vskip\s_spac_vspacing_temp
+ \fi
+ \setfalse\c_space_vspacing_done
+ \the\everybeforeblankhandling}
+
+\def\addpredefinedblankskip#1#2%
+ {\settrue\c_space_vspacing_done
+ \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
+
+% \unexpanded\def\addpredefinedblankskip#1#2%
+% {\settrue\c_space_vspacing_done
+% \advance\s_spac_vspacing_temp#1\dimexpr\the\csname\ifgridsnapping g\else n\fi>#2\endcsname\relax}
+
+\unexpanded\def\addaskedblankskip#1#2%
+ {\settrue\c_space_vspacing_done
+ \advance\s_spac_vspacing_temp#1\dimexpr#2\relax}
+
+% The main spacer:
+
+\unexpanded\def\vspacing
+ {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop}
+
+\def\spac_vspacing_yes
+ {\ifinpagebody % somewhat weird
+ \singleexpandafter\spac_vspacing_yes_indeed
+ \else\ifconditional\c_spac_packed_blank
+ \doubleexpandafter\spac_vspacing_yes_indeed
+ \else
+ \doubleexpandafter\spac_vspacing_yes_ignore
+ \fi\fi}
+
+\def\spac_vspacing_nop
+ {\ifinpagebody % somewhat weird
+ \singleexpandafter\spac_vspacing_nop_indeed
+ \else\ifconditional\c_spac_packed_blank
+ \doubleexpandafter\spac_vspacing_nop_indeed
+ \else
+ \doubleexpandafter\spac_vspacing_nop_ignore
+ \fi\fi}
+
+\def\spac_vspacing_yes_indeed[#1]%
+ {\ifmmode\else\par\clf_vspacing{#1}\fi}
+
+\def\spac_vspacing_yes_ignore[#1]%
+ {\ifmmode\else\par\fi}
+
+\def\spac_vspacing_nop_indeed
+ {\ifmmode\else\par\clf_vspacing{\currentvspacing}\fi}
+
+\def\spac_vspacing_nop_ignore
+ {\ifmmode\else\par\fi}
+
+\def\directvspacing#1%
+ {\par\clf_vspacing{#1}}
+
+\def\directcheckedvspacing
+ {\ifinpagebody % somewhat weird
+ \expandafter\directvspacing
+ \else\ifconditional\c_spac_packed_blank
+ \doubleexpandafter\directvspacing
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+\def\directdefaultvspacing
+ {\ifinpagebody % somewhat weird
+ \clf_vspacing{\currentvspacing}%
+ \else\ifconditional\c_spac_packed_blank
+ \clf_vspacing{\currentvspacing}%
+ \fi\fi}
+
+% handy (and faster):
+
+\unexpanded\def\directvpenalty#1%
+ {\begingroup
+ \attribute\skipcategoryattribute \plusthree
+ \attribute\skippenaltyattribute #1\relax
+ \attribute\skiporderattribute \attributeunsetvalue
+ \vskip\zeropoint
+ \endgroup}
+
+\unexpanded\def\directvskip#1%
+ {\begingroup
+ \attribute\skipcategoryattribute \plusone
+ \attribute\skippenaltyattribute \attributeunsetvalue
+ \attribute\skiporderattribute \attributeunsetvalue
+ \vskip#1\relax
+ \endgroup}
+
+% these depend on bigskipamount cum suis so we'd better sync them
+
+\unexpanded\def\setupvspacing
+ {\doifelsenextoptionalcs\setupvspacing_yes\setupvspacing_nop}
+
+\let\currentvspacing\s!default % hm, default, standard ...
+
+\def\setupvspacing_yes[#1]%
+ {\edef\currentvspacing{#1}%
+ \spac_whitespace_setup_nop % yes or no, was forgotten
+ }
+
+\def\setupvspacing_nop
+ {\ifx\empty\currentvspacing % mistakenly had an \else
+ \let\currentvspacing\s!default
+ \fi
+ \spac_whitespace_setup_nop}
+
+\unexpanded\def\restorestandardblank % or default ?
+ {\let\currentvspacing\v!standard}
+
+\let\synchronizevspacing\setupvspacing_nop
+
+% category:4 is default
+
+% this interface might change (into an \install, but we will then keep this one hidden)
+
+\definevspacingamount[\v!none] [\zeropoint] [\zeropoint]
+\definevspacingamount[\v!big] [\bigskipamount] [\bodyfontlineheight]
+\definevspacingamount[\v!medium] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!small] [\smallskipamount] [.25\bodyfontlineheight]
+\definevspacingamount[\v!line] [\openlineheight] [\bodyfontlineheight]
+\definevspacingamount[\v!halfline] [.5\openlineheight] [.5\bodyfontlineheight]
+\definevspacingamount[\v!quarterline] [.25\openlineheight] [.25\bodyfontlineheight]
+\definevspacingamount[\v!formula] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!white] [\parskip] [\bodyfontwhitespace]
+\definevspacingamount[\v!height] [\strutht] [\bodyfontstrutheight]
+\definevspacingamount[\v!depth] [\strutdp] [\bodyfontstrutdepth]
+
+\definevspacingamount[-\v!line] [-\openlineheight] [-\bodyfontlineheight]
+\definevspacingamount[-\v!halfline] [-.5\openlineheight] [-.5\bodyfontlineheight]
+\definevspacingamount[-\v!quarterline][-.25\openlineheight][-.25\bodyfontlineheight]
+
+\definevspacingamount[\v!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible
+
+\def\bodyfontwhitespace
+ {\dimexpr
+ \ifdim\parskip=\zeropoint
+ \zeropoint
+ \else\ifgridsnapping
+ \bodyfontlineheight
+ \else
+ \parskip
+ \fi\fi
+ \relax}
+
+% used in itemize ... always test this
+
+\newdimen\d_spac_overlay
+
+\def\spac_overlay_lines
+ {\directcheckedvspacing{\v!back,\v!overlay}% \blank[\v!back,\v!overlay]%
+ \nointerlineskip}
+
+% \startitemize[n]
+% \item \input zapf
+% \item \startitemize[a]
+% \item \input knuth
+% \stopitemize
+% \stopitemize
+%
+% \strut \hfill first line \blank[overlay] second line \hfill \strut
+%
+% \ruledvbox {
+% \strut \hfill line 1 \blank[overlay]
+% line 2 \hfill \strut \blank[overlay]
+% \strut \hfill line 3 \hfill \strut
+% }
+%
+% \dorecurse{50}
+% {\startitemize[n] \startitem \startitemize[a] \item #1 \stopitemize \stopitem \stopitemize}
+
+\definevspacing[\v!preference][penalty:-500] % goodbreak
+\definevspacing[\v!samepage] [penalty:10000] % nobreak
+\definevspacing[\v!max] [category:1]
+\definevspacing[\v!force] [category:2]
+\definevspacing[\v!disable] [category:5]
+\definevspacing[\v!nowhite] [category:6]
+\definevspacing[\v!back] [category:7]
+% together [category:8]
+\definevspacing[\v!overlay] [category:9]
+\definevspacing[\v!always] [category:0] % hm, internally it's discard
+\definevspacing[\v!weak] [order:0]
+\definevspacing[\v!strong] [order:100]
+
+\definevspacing[\s!default] [\v!white] % was big for a while
+
+% \dorecurse{10} % todo: other values < 4000
+% {\normalexpanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr4000+250*\recurselevel\relax]}}
+
+\newcount\c_spac_vspacing_special_base \c_spac_vspacing_special_base = 32250 % 4000
+\newcount\c_spac_vspacing_special_step \c_spac_vspacing_special_step = 10 % 250
+
+\dorecurse{10}
+ {\normalexpanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\recurselevel\relax]}}
+
+\definevspacing[\v!default] [\v!big] % todo: needs to adapt to \setupblank
+\definevspacing[\v!before] [\v!default] % but we need to avoid circular references
+\definevspacing[\v!inbetween][\v!default] % then
+\definevspacing[\v!after] [\v!before]
+
+\setupvspacing
+ [\v!big] % alternatively [\v!standard]
+
+%D Maybe at some point we will differ between \type {\vspacing} and
+%D \type {\blank} (we needed the first one while playing with the
+%D new code).
+
+% We keep this one as reference
+%
+% \unexpanded\def\inhibitblank
+% {\vspacing[\v!disable]}
+%
+% but use the following more efficient variant instead:
+
+\unexpanded\def\inhibitblank
+ {\ifvmode
+ \begingroup
+ \attribute\skipcategoryattribute\plusfive
+ \vskip\zeropoint
+ \endgroup
+ \fi}
+
+\let\doinhibitblank\inhibitblank % keep this command, used in styles
+
+\let\defineblank \definevspacing
+\let\setupblank \setupvspacing
+\let\blank \vspacing
+\let\synchronizeblank \synchronizevspacing
+\let\defineblankmethod\definevspacingamount
+
+%D The following command is for Wolfgang. It has to be used with
+%D care as it does {\em not} work in tandem with the other spacing
+%D commands.
+
+\installcorenamespace{vspace}
+
+\unexpanded\def\definevspace
+ {\dotripleempty\spac_vspace_define}
+
+\def\spac_vspace_define[#1][#2][#3]%
+ {\ifthirdargument
+ \setvalue{\??vspace#1:#2}{#3}%
+ \else
+ \setvalue{\??vspace:#1}{#2}%
+ \fi}
+
+\letvalue{\??vspace:\s!unknown}\zeropoint
+
+\unexpanded\def\vspace
+ {\dodoubleempty\spac_vspace_inject}
+
+% \def\spac_vspace_inject[#1][#2]% use \lastnamedcs
+% {\par
+% \ifvmode
+% \removelastskip
+% \vskip
+% \csname\??vspace
+% \ifsecondargument
+% \ifcsname\??vspace#1:#2\endcsname
+% #1:#2%
+% \else\ifcsname\??vspace:#2\endcsname
+% :#2%
+% \else
+% :\s!unknown
+% \fi\fi
+% \else\iffirstargument
+% \ifcsname\??vspace:#1\endcsname
+% :#1%
+% \else
+% :\s!unknown
+% \fi
+% \else
+% \ifcsname\??vspace:\s!default\endcsname
+% :\s!default
+% \else
+% :\s!unknown
+% \fi
+% \fi\fi
+% \endcsname
+% \relax
+% \fi}
+
+\def\spac_vspace_unknown
+ {\csname\??vspace:\s!unknown\endcsname}
+
+\def\spac_vspace_inject[#1][#2]% use \lastnamedcs
+ {\par
+ \ifvmode
+ \removelastskip
+ \vskip
+ \ifsecondargument
+ \ifcsname\??vspace#1:#2\endcsname
+ \lastnamedcs
+ \else\ifcsname\??vspace:#2\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi\fi
+ \else\iffirstargument
+ \ifcsname\??vspace:#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi
+ \else
+ \ifcsname\??vspace:\s!default\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspace_unknown
+ \fi
+ \fi\fi
+ \relax
+ \fi}
+
+%D Some preliminary code: a simple and fast hanger, for usage in
+%D macros (moved from cont-new).
+
+\installcorenamespace {hanging}
+
+\installdirectcommandhandler \??hanging {hanging}
+
+\setuphanging
+ [\c!distance=.5\emwidth,
+ \c!location=\v!left,
+ \c!n=\zerocount]
+
+\unexpanded\def\starthanging
+ {\dontleavehmode\bgroup
+ \dosingleempty\spac_hanging_start}
+
+\unexpanded\def\stophanging
+ {\endgraf
+ \egroup}
+
+\let\m_spac_hanging_location\empty
+
+\def\spac_hanging_start[#1]%
+ {\doifelseassignment{#1}
+ {\let\m_spac_hanging_location\empty
+ \setupcurrenthanging[#1]}%
+ {\edef\m_spac_hanging_location{#1}}%
+ \ifx\m_spac_hanging_location\empty
+ \edef\m_spac_hanging_location{\directhangingparameter\c!location}%
+ \fi
+ \dowithnextboxcs\spac_hanging_finish\hbox}
+
+\def\spac_hanging_finish
+ {\scratchdistance\directhangingparameter\c!distance\relax
+ \ifdim\ht\nextbox>\strutht
+ \setbox\nextbox\tbox{\box\nextbox}%
+ \fi
+ \scratchcounter\directhangingparameter\c!n\relax
+ \ifnum\scratchcounter>\zerocount
+ \hangafter-\scratchcounter
+ \else
+ \getboxheight\scratchdimen\of\box\nextbox
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \fi
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \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}%
+ \else
+ \hangindent\ifconditional\displaylefttoright\else-\fi\scratchwidth
+ \llap{\box\nextbox\hskip\scratchdistance}%
+ \fi
+ \ignorespaces}
+
+%D \macros
+%D {startfixed}
+%D
+%D \starttyping
+%D \startitemize
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D
+%D \startitem \startfixed \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[high]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[low] \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[lohi]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D
+%D \startitem test \par \startfixed \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[high]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[low] \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[lohi]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{fixedalternatives}
+
+\unexpanded\def\startfixed
+ {\bgroup
+ \dosingleempty\typo_fixed_start}
+
+\def\typo_fixed_start
+ {\ifhmode
+ \expandafter\typo_fixed_start_h
+ \else
+ \expandafter\typo_fixed_start_v
+ \fi}
+
+\def\typo_fixed_start_h[#1]%
+ {\let\stopfixed\typo_fixed_stop_h
+ \dowithnextbox{\typo_fixed_finish{#1}}%
+ \vbox\bgroup
+ %ignorespaces
+ \setlocalhsize}
+
+\unexpanded\def\typo_fixed_stop_h
+ {%removeunwantedspaces
+ \egroup
+ \egroup}
+
+\def\typo_fixed_start_v[#1]%
+ {\let\stopfixed\typo_fixed_stop_v
+ \startbaselinecorrection}
+
+\unexpanded\def\typo_fixed_stop_v
+ {\stopbaselinecorrection
+ \egroup}
+
+\letvalue{\??fixedalternatives \v!high}\bbox
+\letvalue{\??fixedalternatives \v!low}\tbox
+\letvalue{\??fixedalternatives \v!middle}\vcenter
+\letvalue{\??fixedalternatives \v!lohi}\vcenter
+\letvalue{\??fixedalternatives\s!unknown}\tbox
+\letvalue{\??fixedalternatives\s!default}\tbox
+
+\unexpanded\def\typo_fixed_finish#1%
+ {\expandnamespacevalue\??fixedalternatives{#1}\s!default{\box\nextbox}}
+
+% %D Forgotten already:
+%
+% \def\shapefill{\vskip\zeropoint\s!plus\lineheight\s!minus\lineheight\relax}
+
+%D Nasty:
+
+% \writestatus{1}{\the\prevdepth} \blank[force,5*big] { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{2}{\the\prevdepth} \blank[force,5*big] { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{3}{\the\prevdepth} \blank[force,5*big] { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
+% \writestatus{4}{\the\prevdepth} \input tufte \page
+% \writestatus{5}{\the\prevdepth} \input tufte \page
+% \writestatus{6}{\the\prevdepth} \blank[force,5*big] { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+
+% \writestatus{1}{\the\prevdepth} \null\vskip4cm { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{2}{\the\prevdepth} \null\vskip4cm { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+% \writestatus{3}{\the\prevdepth} \null\vskip4cm { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
+% \writestatus{4}{\the\prevdepth} \input tufte \page
+% \writestatus{5}{\the\prevdepth} \input tufte \page
+% \writestatus{6}{\the\prevdepth} \null\vskip4cm { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
+
+\appendtoks
+ \ifvmode\prevdepth\zeropoint\fi % consistent, else first page -1000pt .. needed for fixed,3*big first/successive pages consistency
+\to \everystarttext
+
+\prevdepth\zeropoint
+
+% not ok, so we need to figure out another way to fix this messy prevdepth-across-page issue
+% as encountered in forced blank skips (see lua code)
+%
+% \appendtoks
+% \ifvmode\clf_resetprevdepth\fi
+% \to \everyafteroutput
+%
+% this should only happen when there is nothing left over (how to detemine that) .. testcase:
+%
+% \dorecurse{41}{line\par}
+% \starttyping
+% line 1
+% line 2
+% line 3
+% \stoptyping
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf
new file mode 100644
index 00000000000..f5692f2c4f1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf
new file mode 100644
index 00000000000..65ec9e7c7ed
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.lua b/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.lua
new file mode 100644
index 00000000000..3fe9e0d8e30
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.lua
@@ -0,0 +1,6386 @@
+return {
+ todo = {
+ category = "lua",
+ filename = "core-run",
+ status = "idea",
+ },
+ main = {
+ {
+ category = "mkiv",
+ filename = "context",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "lus",
+ comment = "stub file for context",
+ filename = "context",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "metatex",
+ loading = "parent",
+ status = "pending",
+ },
+ {
+ category = "lus",
+ comment = "stub file for metatex",
+ filename = "metatex",
+ loading = "parent",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-cs",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-de",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-en",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-fr",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-gb",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-it",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-nl",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-pe",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-ro",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe more delayed loading",
+ filename = "metafun",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "we keep this around for historic reasons",
+ filename = "ppchtex",
+ loading = "never",
+ status = "okay",
+ },
+ },
+ core = {
+ {
+ category = "mkiv",
+ filename = "syst-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "norm-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-mes",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "luat-cod",
+ loading = "luat-cod",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (3)",
+ filename = "luat-bas",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (3)",
+ filename = "luat-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "forward dependency",
+ filename = "catc-act",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-sym",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-xml",
+ loading = "module",
+ status = "okay",
+ comment = "only needed for mkii xml parser",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "cldf-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-lua",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-fnt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-rtp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe combine (2)",
+ filename = "file-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe combine (2)",
+ filename = "file-res",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-dir",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-utf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "forward dependency",
+ filename = "char-act",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-sys",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-chk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "mult-dim",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-int",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "luat-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "toks-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-mkr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move from here",
+ filename = "core-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more redoing",
+ filename = "core-env",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "in due time more might move to here",
+ filename = "layo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe this becomes a runtime module",
+ filename = "node-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe use context.generics/context.sprint here",
+ filename = "cldf-bas",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more redoing",
+ filename = "node-fin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs integration and configuration",
+ filename = "node-mig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-bld",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-sus",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "node-pag",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "back-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-lay",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-neg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-eff",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs more usage",
+ filename = "trac-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-deb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-ran",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be moved to the math-* modules",
+ filename = "supp-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will grow",
+ filename = "typo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-syn",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-mod",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-fil",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-nop",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-yes",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "regi-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "enco-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "hand-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "namespace should be languages",
+ filename = "lang-lab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-hyp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "unic-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-uti",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe rename to core-two",
+ filename = "core-two",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-dat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-ext",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-grp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "node-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-cut",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-url",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-hyp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-frq",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-frd",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-wrd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "might need more redoing",
+ filename = "file-job",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "sort-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "pack-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-rul",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "endpar experimental code",
+ filename = "pack-mrl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "pack-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-fen",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-sor",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "typo-prc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-tag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module might go away when code has been moved",
+ filename = "strc-doc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "still some rough edges",
+ filename = "strc-num",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-mar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-sbe",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-lst",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some of the local current and synchronization macros will be renamed",
+ filename = "strc-sec",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "(support for) setups might get improved",
+ filename = "strc-ren",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module might go away",
+ filename = "strc-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "some more low level names might change",
+ filename = "strc-ref",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "use setups for rendering",
+ filename = "strc-reg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-lev",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some tuning is needed / will happen",
+ filename = "spac-ali",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "probably needs some more work",
+ filename = "spac-hor",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some changes will happen",
+ filename = "spac-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "could be improved if needed",
+ filename = "spac-lin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this needs to be checked occasionally",
+ filename = "spac-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-def",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "needs thinking and redoing",
+ filename = "spac-grd",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "in transition",
+ filename = "anch-pos",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe change locationattribute names",
+ filename = "scrn-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-ref",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will change when we have objects at lua end",
+ filename = "pack-obj",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-itm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe more common counter code here and setups need to be improved",
+ filename = "strc-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-des",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "(interactive) coupling is not yet working",
+ filename = "strc-enu",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-ind",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs to be adapted when strc-con/des/enu changes",
+ filename = "strc-lab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-syn",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "a funny mix",
+ filename = "core-sys",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-var",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-otr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might end up elsewhere",
+ filename = "page-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "dealing with insertions might change",
+ filename = "page-ins",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-fac",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "otr commands will be redone",
+ filename = "page-brk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "helpers for columns",
+ filename = "page-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "room for improvement and extension",
+ filename = "page-inf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-grd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be extended when columns are redone",
+ filename = "page-flt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-not",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "can probably be improved",
+ filename = "page-one",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-lay",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "a few things left",
+ filename = "page-txt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-sid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "in due time we need a further cleanup",
+ filename = "strc-flt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-pst",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "might be extended",
+ filename = "page-mbk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be reimplemented",
+ filename = "page-mul",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "work in progress",
+ filename = "page-mix",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "will be reimplemented",
+ filename = "page-set",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-lyr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-pos",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-mak",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will probably be overhauled some day",
+ filename = "page-lin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might get extended",
+ filename = "page-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-mar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-itm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "check other modules for buffer usage",
+ filename = "buff-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "check obsolete processbuffer",
+ filename = "buff-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "experimental code",
+ filename = "buff-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-mp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-lua",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-parsed-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-default",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-escaped",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-nested",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-blk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-imp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe some extensions and delayed loading, needs checking",
+ filename = "page-sel",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "functionality needs checking",
+ filename = "scrn-wid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-but",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-bkm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-tal",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "somewhat weird",
+ filename = "tabl-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "unchecked",
+ filename = "tabl-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-tab",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "can probably be improved (names and such)",
+ filename = "tabl-tbl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "frozen functionaly so no drastic cleanup",
+ filename = "tabl-ntb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-nte",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be redone when needed",
+ filename = "tabl-ltb",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "will be adapted when needed (and rest is done)",
+ filename = "tabl-tsp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "tabl-xtb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "tabl-xnt",
+ loading = "module",
+ status = "okay",
+ loading = "always",
+ comment = "only when natural tables need a replacement",
+ },
+ {
+ category = "mkiv",
+ filename = "java-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-fld",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-hlp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-enc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-fil",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-var",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-fea",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "needs occasional checking and upgrading",
+ filename = "font-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-sym",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-sty",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-set",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-emp",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-col",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "font-pre",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "font-unk",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "likely this will become a module",
+ filename = "font-tra",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this could become a module",
+ filename = "font-chk",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this one might be merged",
+ filename = "font-uni",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-gds",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-lan",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this is work in progress",
+ filename = "lxml-css",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-chr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "work in progress",
+ filename = "blob-ini",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-vis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-jus",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "trac-vis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-cln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-spa",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "do we keep the style and color or not",
+ filename = "typo-krn",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "typo-itc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe singular setup",
+ filename = "typo-dir",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-brk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-cap",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-dig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-rep",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe there will be a nicer interface",
+ filename = "typo-txt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-drp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-fln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "type-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-set",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-def",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-fbk",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-lua",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-one",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-otf",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-siz",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-tmf",
+ loading = "never",
+ status = "okay",
+ comment = "placeholder to prevent other loading",
+ },
+ {
+ category = "mkiv",
+ filename = "scrp-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module is obsolete",
+ filename = "prop-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "metapost code is always evolving",
+ filename = "meta-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code used in a project",
+ filename = "meta-lua",
+ loading = "experimental",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-fnt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe this one will be merged",
+ filename = "meta-fun",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might get updated when mp code gets cleaned up",
+ filename = "meta-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-grd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-mrk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-flw",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-spr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be made better",
+ filename = "page-plg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs more work (and thinking)",
+ filename = "page-str",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "in transition",
+ filename = "anch-pgr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "in transition",
+ filename = "anch-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will stay experimental for a while",
+ filename = "anch-tab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "anch-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "interesting old mechanism to keep around (module?)",
+ filename = "anch-snc",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "math-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this file might merge into others",
+ filename = "math-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-for",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "eventually this will be split and spread",
+ filename = "math-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be checked and improved",
+ filename = "math-ali",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs testing",
+ filename = "math-arr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "math-stc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "math-acc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "at least for the moment",
+ filename = "math-frc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-scr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-int",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code get replaced (by autodelimiters)",
+ filename = "math-del",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-fen",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-rad",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move to here",
+ filename = "math-inl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move to here",
+ filename = "math-dis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "phys-dim",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some more functionality will end up here",
+ filename = "strc-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "chem-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "chem-str",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-scr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some cleanup is needed",
+ filename = "node-rul",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs testing",
+ filename = "font-sol",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvI",
+ filename = "strc-not",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkvi",
+ comment = "will be extended as part of crited",
+ filename = "strc-lnt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-del",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-trf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-inc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-fig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-raw",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-app",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-fig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "more or less obsolete",
+ filename = "lang-spa",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "bibl-bib",
+ loading = "on demand",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "bibl-tra",
+ loading = "on demand",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "not needed",
+ filename = "meta-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-log",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "task-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will always be messy",
+ filename = "core-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "object related code might move or change",
+ filename = "back-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "back-swf",
+ loading = "never",
+ status = "okay",
+ comment = "no code, just an example of usage",
+ },
+ {
+ category = "mkiv",
+ filename = "back-u3d",
+ loading = "never",
+ status = "okay",
+ comment = "no code, just an example of usage",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-pps",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more work",
+ filename = "grph-epd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some parameters might move from export to backend",
+ filename = "back-exp",
+ loading = "always",
+ status = "okay",
+ },
+ },
+ extras = {
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-arrange",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-combine",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-common",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-ideas",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-listing",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-markdown",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-select",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-timing",
+ loading = "on demand",
+ status = "okay",
+ },
+ },
+ implementations = {
+ {
+ category = "mkiv",
+ filename = "colo-imp-dem",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-ema",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-rgb",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-x11",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-xwi",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-exa",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-fil",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-fld",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-rhh",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-stp",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-clp",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-dum",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-fen",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-nav",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-pre",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-txt",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-cow",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-eur",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-jmn",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-mvs",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-nav",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-antykwa",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-antykwapoltawskiego",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-asana",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-averia",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-buy",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cambria",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-charter",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cleartype",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-computer-modern-unicode",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cow",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-dejavu",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-euler",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-ghz",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-hgz",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-husayni",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-hvmath",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-inconsolata",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-informal",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-iwona",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-kurier",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-latinmodern",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-liberation",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-libertine",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lmnames",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lucida-opentype",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lucida-typeone",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mathdesign",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mathtimes",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mscore",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-osx",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-postscript",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-punknova",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-texgyre",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-unfonts",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-xits",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-xitsbidi",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-ini",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-old",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-tra",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-usr",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-jrn",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-xml",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-imp-apa",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-imp-cite",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-imp-definitions",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "publ-imp-commands",
+ loading = "always",
+ status = "pending",
+ },
+ },
+ lua = {
+ {
+ category = "lua",
+ filename = "anch-pos",
+ loading = "anch-pos",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-col",
+ loading = "attr-col",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-eff",
+ loading = "attr-eff",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-ini",
+ loading = "attr-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-lay",
+ loading = "attr-lay",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-neg",
+ loading = "attr-neg",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-mkr",
+ loading = "attr-mkr",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experimental code, maybe some will move elsewhere",
+ filename = "back-exp",
+ loading = "back-exp",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "back-ini",
+ loading = "back-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "back-pdf",
+ loading = "back-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "bibl-bib",
+ loading = "on demand",
+ },
+ {
+ category = "lua",
+ filename = "bibl-tra",
+ loading = "on demand",
+ },
+ {
+ category = "lua",
+ filename = "blob-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-default",
+ loading = "buff-imp-default",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-escaped",
+ loading = "buff-imp-escaped",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-lua",
+ loading = "buff-imp-lua",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-mp",
+ loading = "buff-imp-mp",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-nested",
+ loading = "buff-imp-nested",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-parsed-xml",
+ loading = "buff-imp-parsed-xml",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-tex",
+ loading = "buff-imp-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-xml",
+ loading = "buff-imp-xml",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-par",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe we will provide a few more (nesting) methods",
+ filename = "buff-ver",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "catc-ini",
+ loading = "catc-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-cjk",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-def",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe dataonly",
+ filename = "char-enc",
+ loading = "char-enc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-ent",
+ loading = "char-ent",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe move blocks table to separate (dataonly) file",
+ filename = "char-ini",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-map",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-tex",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-utf",
+ loading = "char-utf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "chem-ini",
+ loading = "chem-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "chem-str",
+ loading = "chem-str",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be extended and can be optimized if needed",
+ filename = "cldf-bas",
+ loading = "cldf-bas",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "might change or even go away",
+ filename = "cldf-com",
+ loading = "cldf-com",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "cldf-ini",
+ loading = "cldf-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "cldf-int",
+ loading = "cldf-int",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "maybe this code can be redone more efficiently/robust",
+ filename = "cldf-ver",
+ loading = "cldf-ver",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "also used in mtx-*",
+ filename = "colo-icc",
+ loading = "colo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "colo-ini",
+ loading = "colo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this code might move to a module",
+ filename = "colo-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-con",
+ loading = "core-con",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-ctx",
+ loading = "core-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-dat",
+ loading = "core-dat",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe abusing the tex namespace is wrong",
+ filename = "core-env",
+ loading = "core-env",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-sys",
+ loading = "core-sys",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ commands = "this is in fact replaced by core-dat",
+ filename = "core-two",
+ loading = "core-two",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "some code will move to better places",
+ filename = "core-uti",
+ loading = "core-uti",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "data-aux",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-bin",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-con",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-crl",
+ loading = "never",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-ctx",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-env",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-exp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-fil",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-gen",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-ini",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-inp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-lst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-lua",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-met",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-out",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-pre",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-res",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-sch",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tex",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tmf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tmp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tre",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-use",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-vir",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-zip",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "file-ini",
+ loading = "file-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-job",
+ loading = "file-job",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-lib",
+ loading = "file-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-mod",
+ loading = "file-mod",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-res",
+ loading = "file-res",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-syn",
+ loading = "file-syn",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-afm",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-afk",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "only used in luatex-fonts",
+ filename = "font-age",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-agl",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "needs some documentation in usage",
+ filename = "font-aux",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "move more to the commands namespace",
+ filename = "font-chk",
+ loading = "font-chk",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-cid",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-col",
+ loading = "font-col",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-con",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be improved over time",
+ filename = "font-ctx",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-def",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "part of this code is obsolete",
+ filename = "font-enc",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "needs documentation at the tex end",
+ filename = "font-enh",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe some data tables can be be external",
+ filename = "font-ext",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "okay but can be improved",
+ filename = "font-fbk",
+ loading = "font-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "font-gds",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-hsh",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ini",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-inj",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ldr",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-log",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "currently rather minimalistic",
+ filename = "font-lua",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "the lum file support will be dropped / no map files anyway",
+ filename = "font-map",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-nod",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "when more scripts are supported we might end up with imp files",
+ filename = "font-ota",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otb",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otc",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otd",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otf",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-oth",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-oti",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otn",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otp",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ott",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "is mostly replaced by lfg files",
+ filename = "font-pat",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-sol",
+ loading = "font-sol",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "also loaded on demand",
+ filename = "font-syn",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-tfm",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-trt",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-vf",
+ loading = "font-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "grph-epd",
+ loading = "grph-epd",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-fil",
+ loading = "grph-inc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-inc",
+ loading = "grph-inc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "grph-raw",
+ loading = "grph-raw",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-swf",
+ loading = "grph-swf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-u3d",
+ loading = "grph-u3d",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experiment with graphic magick library",
+ filename = "grph-wnd",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "java-ini",
+ loading = "java-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "l-boolean",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-file",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-function",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-io",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-lpeg",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-math",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-md5",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-number",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-os",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-pdfview",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-set",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-string",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-table",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-unicode",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-url",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-xml",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lang-def",
+ loading = "lang-def",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-dis",
+ loading = "lang-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-hyp",
+ loading = "lang-hyp",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-ini",
+ loading = "lang-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-lab",
+ loading = "lang-lab",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-hyp",
+ loading = "lang-hyp",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-txt",
+ loading = "lang-lab",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe another approach is nicer",
+ filename = "lang-url",
+ loading = "lang-url",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "lang-wrd",
+ loading = "lang-wrd",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "more will end up here",
+ filename = "layo-ini",
+ loading = "layo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ano",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-res",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-col",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-enc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-epa",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-epd",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-fld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-fmt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-grp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-mis",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-mov",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-nod",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ren",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-swf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-tag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-u3d",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-wid",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-xmp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "replacement code for wd/ht/dp",
+ filename = "luat-bwc",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-cbk",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-cnf",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe some code should move",
+ filename = "luat-cod",
+ loading = "luat-cod",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-env",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-exe",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-fio",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-fmt",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be upgraded when we have Lua 5.2",
+ filename = "luat-ini",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "will be upgraded when we have Lua 5.2",
+ filename = "util-env",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "luat-iop",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is likely to change some day",
+ filename = "luat-lua",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-mac",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-run",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "related to the socket code",
+ filename = "luat-soc",
+ loading = "on demand",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "luat-sta",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-sto",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lxml-aux",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-css",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-ctx",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-ent",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-inf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-lpt",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-mis",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-sor",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-tab",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-tex",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-xml",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-chart",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-database",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "m-nodechart",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "m-markdown",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-pstricks",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-spreadsheet",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-steps",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "math-act",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-frc",
+ loading = "math-frc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "could be made look nicer, but who cares",
+ filename = "math-dim",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "the code is related to math-vfu",
+ filename = "math-ext",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-fbk",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-frc",
+ loading = "math-frc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "okay, but we might have a few more low level definers some day",
+ filename = "math-ini",
+ loading = "math-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "math-map",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-noa",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-ren",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-tag",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-ttv",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-vfu",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is just a first version",
+ filename = "meta-fun",
+ loading = "meta-fun",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-ini",
+ loading = "meta-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-lua",
+ loading = "meta-lua",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-fnt",
+ loading = "meta-fnt",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "could be done nicer nowadays but who needs it",
+ filename = "meta-pdf",
+ loading = "meta-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-pdh",
+ loading = "meta-pdh",
+ status = "okay",
+ loading = "never",
+ comment = "this is historic code that we keep around",
+ },
+ {
+ category = "lua",
+ filename = "meta-tex",
+ loading = "meta-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-ctx",
+ loading = "mlib-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-pdf",
+ loading = "mlib-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-pps",
+ loading = "mlib-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-run",
+ loading = "mlib-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is an experiment, namespaces need to be dealt with properly",
+ filename = "mult-aux",
+ loading = "mult-aux",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "this is an experiment",
+ filename = "mult-chk",
+ loading = "mult-chk",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "mult-def",
+ loading = "mult-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-fun",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mult-ini",
+ loading = "mult-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-low",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "all messages need to be checked",
+ filename = "mult-mes",
+ loading = "mult-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-mps",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-prm",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "node-acc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-aux",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-bck",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ext",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-fin",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-fnt",
+ loading = "font-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-inj",
+ loading = "font-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-mig",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ppt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-pro",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-res",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-rul",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ser",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-shp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tex",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tra",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-snp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tsk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-typ",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "will be extended when we have opened up pdf objects",
+ filename = "pack-obj",
+ loading = "pack-obj",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "pack-rul",
+ loading = "pack-rul",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "page-otr",
+ loading = "page-otr",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "page-flt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-ins",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-lin",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-mix",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-pst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-str",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "phys-dim",
+ loading = "phys-dim",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-1",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-10",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-11",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-13",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-14",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-15",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-16",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-2",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-3",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-4",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-5",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-6",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-7",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-8",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-9",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1250",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1251",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1252",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1253",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1254",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1255",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1256",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1257",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1258",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "just a demo file",
+ filename = "regi-demo",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-ini",
+ loading = "regi-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-coverage",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-features",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-missing",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-shapes",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-system",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-tables",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-vectors",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-counters",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-frequencies",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-hyphenation",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-sorting",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-system",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-math-characters",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-math-coverage",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-math-extensibles",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-goodies",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-math-parameters",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-physics-units",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-pre-71",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "s-sql-tables",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "scrn-but",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-fld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-hlp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-wid",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "we can speed this up",
+ filename = "scrp-cjk",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "we can speed this up",
+ filename = "scrp-eth",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "scrp-ini",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "sort-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "sort-lan",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-adj",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-ali",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-chr",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-hor",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-ver",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "status-mkiv",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-bkm",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-blk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-con",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-doc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-flt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-itm",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-lev",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-lst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-mar",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-mat",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-not",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-num",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-reg",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-rsc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-syn",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-tag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "supp-box",
+ loading = "supp-box",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "supp-ran",
+ loading = "supp-ran",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "symb-ini",
+ loading = "symb-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "there will be more in here",
+ filename = "syst-aux",
+ loading = "syst-aux",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "do some tests with speedups (sprint)",
+ filename = "syst-con",
+ loading = "syst-con",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "do some tests with speedups (less tokens)",
+ filename = "syst-lua",
+ loading = "syst-lua",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "tabl-tbl",
+ loading = "tabl-tbl",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "work in progress",
+ filename = "tabl-xtb",
+ loading = "tabl-xtb",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "we need a well defined defintion moment",
+ filename = "task-ini",
+ loading = "task-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "toks-ini",
+ loading = "toks-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "toks-scn",
+ loading = "toks-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "must be applied in more places",
+ filename = "trac-ctx",
+ loading = "trac-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-deb",
+ loading = "trac-deb",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "for the moment somewhat private",
+ filename = "trac-fil",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-inf",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be redone and extended",
+ filename = "trac-lmx",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "trac-log",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-xml",
+ loading = "mtxrun",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-exp",
+ loading = "mtxrun",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experimental code, will be redone when lua 5.2",
+ filename = "trac-pro",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "some code can better be in util-set",
+ filename = "trac-set",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "trac-tex",
+ loading = "trac-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-tim",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-vis",
+ loading = "trac-vis",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-jus",
+ loading = "trac-jus",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "type-ini",
+ loading = "type-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-bld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-sus",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-brk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-cap",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-cln",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-dig",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-dir",
+ loading = "typo-dir",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "work in progress",
+ filename = "typo-dha",
+ loading = "typo-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-dua",
+ loading = "typo-dir",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "work in progress",
+ filename = "typo-dub",
+ loading = "typo-dir",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-ini",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-tal",
+ loading = "typo-tal",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-itc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-krn",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-mar",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-drp",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-fln",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-man",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-prc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-lan",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-rep",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-spa",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "unic-ini",
+ loading = "unic-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "util-deb",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-dim",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-fmt",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-jsn",
+ loading = "m-json",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-lua",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "util-lib",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "util-mrg",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-pck",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-prs",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-seq",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sql",
+ loading = "m-sql",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sta",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sto",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-str",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-tab",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-tpl",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-asciimath",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-calcmath",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-cals",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-ct",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "publ-ini",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-aut",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-dat",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-oth",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-fnd",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-tra",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "publ-usr",
+ loading = "publ-ini.mkiv",
+ status = "pending",
+ },
+ },
+ metafun = {
+ {
+ category = "mpiv",
+ filename = "mp-base",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-tool",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-mlib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "sort of obsolete",
+ filename = "mp-core",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some nicer synonyms",
+ filename = "mp-page",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-butt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-shap",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-grph",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-grid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "a hack anyway",
+ filename = "mp-form",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-figs",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-func",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-text",
+ loading = "on demand",
+ status = "todo",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-crop",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "follows m-chart",
+ filename = "mp-char",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "follows m-steps",
+ filename = "mp-step",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-chem",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some namespace changes",
+ filename = "mp-abck",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some namespace changes",
+ filename = "mp-apos",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "will be done when needed",
+ filename = "mp-asnc",
+ loading = "on demand",
+ status = "todo",
+ },
+ },
+ modules = {
+ {
+ category = "mkiv",
+ comment = "best use m-zint instead",
+ filename = "m-barcodes",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "m-chart",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this is a placeholder (chemistry is built-in)",
+ filename = "m-chemic",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-cweb",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-database",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-nodechart",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-datastrc",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-directives",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-educat",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-fields",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-format",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-graph",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-ipsum",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-json",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-layout",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-logcategories",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-markdown",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mathcrap",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mkii",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mkivhacks",
+ status = "todo",
+ },
+ {
+ category = "mkvi",
+ filename = "m-morse",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-narrowtt",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-newmat",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-ntb-to-xtb",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-obsolete",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-oldfun",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-oldnum",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-pictex",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-pstricks",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "keep an eye on changes in lua code",
+ filename = "m-punk",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-r",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-spreadsheet",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "m-steps",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-streams",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-subsub",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-sql",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-timing",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-trackers",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-translate",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-units",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-visual",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-zint",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-03",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-04",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-art-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-cdr-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-def-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-00",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-10",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-20",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-21",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-24",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-30",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-coverage",
+ loading = "s-fonts-coverage",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-features",
+ loading = "s-fonts-features",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-goodies",
+ loading = "s-fonts-goodies",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-missing",
+ loading = "s-fonts-missing",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-shapes",
+ loading = "s-fonts-shapes",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-system",
+ loading = "s-fonts-system",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-tables",
+ loading = "s-fonts-tables",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-vectors",
+ loading = "s-fonts-vectors",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "s-inf-01",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-02",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-04",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-counters",
+ loading = "s-languages-counters",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-frequencies",
+ loading = "s-languages-frequencies",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-languages-hyphenation",
+ loading = "s-languages-hyphenation",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-languages-sorting",
+ loading = "s-languages-sorting",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-languages-system",
+ loading = "s-languages-system",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-lan-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-lan-04",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-lan-06",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "s-mag-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-map-10",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-math-characters",
+ loading = "s-math-characters",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-math-coverage",
+ loading = "s-math-coverage",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-math-extensibles",
+ loading = "s-math-extensibles",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-math-parameters",
+ loading = "s-math-parameters",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-math-repertoire",
+ loading = "s-math-repertoire",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-00",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-02",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pages-statistics",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-physics-units",
+ loading = "s-physics-units",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-00",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-03",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-04",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-05",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-06",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-07",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-08",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-09",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-10",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-11",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-12",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-13",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-14",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-15",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-16",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-17",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-18",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-19",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-22",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-23",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-26",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-27",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-30",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-present-tiles",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-50",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-60",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-61",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-62",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-63",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-64",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-66",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-67",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-68",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-69",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-70",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-71",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-93",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-96",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-ptj-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-reg-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-set-31",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-syn-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-sql-tables",
+ loading = "s-sql-tables",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-asciimath",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-calcmath",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-cals",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-ct",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "x-dir-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-dir-05",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-entities",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-foxet",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-newmml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "pfsense xml configuration rendering",
+ filename = "x-pfs-01",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-physml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-res-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-res-50",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-set-11",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-set-12",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-udhr",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-xtag",
+ status = "todo",
+ },
+ },
+ optional = {
+ {
+ category = "mkiv",
+ filename = "bxml-apa",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "always needs some work",
+ filename = "cont-new",
+ loading = "runtime",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "font-run",
+ loading = "on demand",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-ctx",
+ status = "okay",
+ comment = "this is an experimental module",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-pdh",
+ loading = "never",
+ status = "okay",
+ comment = "this is historic code that we keep around",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-prm",
+ loading = "never",
+ status = "okay",
+ comment = "this is just a helper for generating files",
+ },
+ {
+ category = "mkiv",
+ filename = "page-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-adj",
+ loading = "never",
+ status = "obsolete",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-vis",
+ loading = "never",
+ status = "obsolete",
+ comment = "replaced by a more modern variant",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-run",
+ loading = "on demand",
+ status = "todo",
+ },
+ },
+ resources = {
+ {
+ category = "ori",
+ comment = "template for a user configuration file (with suffix mkiv)",
+ filename = "cont-sys",
+ loading = "runtime",
+ status = "okay",
+ },
+ {
+ category = "lmx",
+ filename = "context-base",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-characters",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-debug",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-error",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-fonttest",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-help",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-timing",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "context-version",
+ status = "todo",
+ },
+ {
+ category = "png",
+ filename = "context-version",
+ status = "todo",
+ },
+ {
+ category = "css",
+ comment = "layout specification for debug and error pages and web services",
+ filename = "context",
+ status = "okay",
+ },
+ {
+ category = "rme",
+ comment = "readme file",
+ filename = "context",
+ status = "okay",
+ },
+ {
+ category = "ctx",
+ comment = "example of a ctx file (for mtx-context)",
+ filename = "core-ctx",
+ status = "okay",
+ },
+ {
+ category = "css",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "rng",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "xml",
+ comment = "this file is auto-generated by mtx-language",
+ filename = "lang-all",
+ status = "okay",
+ },
+ {
+ category = "xml",
+ filename = "lpdf-pda",
+ status = "todo",
+ },
+ {
+ category = "xml",
+ filename = "lpdf-pdx",
+ status = "todo",
+ },
+ {
+ category = "rlx",
+ filename = "rlxcache",
+ status = "todo",
+ },
+ {
+ category = "rlx",
+ filename = "rlxtools",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ filename = "s-mod",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "status-files",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "status-lua",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "status-mkiv",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-contml",
+ status = "todo",
+ },
+ {
+ category = "rng",
+ filename = "x-corres",
+ status = "todo",
+ },
+ {
+ category = "dtd",
+ filename = "x-fig-00",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-fig-00",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-om2cml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-openmath",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ comment = "runner for x-pfs-01",
+ filename = "x-pfsense",
+ status = "okay",
+ },
+ {
+ category = "xsd",
+ filename = "x-physml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-sm2om",
+ status = "todo",
+ },
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.tex b/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.tex
new file mode 100644
index 00000000000..8685c97ad3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-mkiv.tex
@@ -0,0 +1,328 @@
+\usemodule[abr-02]
+
+\setupbodyfont
+ [dejavu,9pt]
+
+\setuppapersize
+ [A4,landscape]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ backspace=.5cm,
+ topspace=.5cm,
+ footer=0pt,
+ header=1.25cm]
+
+\setuphead
+ [title]
+ [style=\bfa,
+ page=yes,
+ after={\blank[line]}]
+
+\setuppagenumbering
+ [location=]
+
+\setupheadertexts
+ [\currentdate]
+ [MkIV Status / Page \pagenumber]
+
+% \showmakeup
+% \showallmakeup
+
+\starttext
+
+% logs.report (immediate) versus logs.messenger (in flow)
+
+\starttitle[title=Todo]
+
+\startitemize[packed]
+ \startitem currently the new namespace prefixes are not consistent but this
+ will be done when we're satisfied with one scheme \stopitem
+ \startitem there will be additional columns in the table, like for namespace
+ so we need another round of checking then \stopitem
+ \startitem the lua code will be cleaned up upgraded as some is quite old
+ and experimental \stopitem
+ \startitem we need a proper dependency tree and better defined loading order \stopitem
+ \startitem all dotag.. will be moved to the tags_.. namespace \stopitem
+ \startitem we need to check what messages are gone (i.e.\ clean up mult-mes) \stopitem
+ \startitem some commands can go from mult-def (and the xml file) \stopitem
+ \startitem check for setuphandler vs simplesetuphandler \stopitem
+ \startitem for the moment we will go for \type {xxxx_} namespaces that (mostly) match
+ the filename but later we can replace these by longer names (via a script) so
+ module writers should {\bf not} use the core commands with \type{_} in the
+ name \stopitem
+ \startitem the message system will be unified \stopitem
+ \startitem maybe rename dowhatevertexcommand to fromluawhatevertexcommand \stopitem
+ \startitem consider moving setups directly to lua end (e.g. in characterspacing, breakpoint, bitmaps etc.) \stopitem
+ \startitem more local temporary \type {\temp...} will become \type {\p_...} \stopitem
+ \startitem check all ctxlua calls for ctxcommand \stopitem
+ \startitem rename all those \type {\current<whatever>}s in strc \stopitem
+ \startitem check \type {option} vs \type {options} \stopitem
+ \startitem check \type {type} vs \type {kind} \stopitem
+ \startitem check \type {label} vs \type {name} vs \type {tag} \stopitem
+ \startitem check \type {limop}, different limops should should be classes \stopitem
+ \startitem too many positions in simple files (itemize etc) \stopitem
+ \startitem math domains/dictionaries \stopitem
+ \startitem xtables don't span vertically with multilines (yet) \stopitem
+ \startitem notes in mixed columns \stopitem
+ \startitem floats in mixed columns \stopitem
+ \startitem check return values \type {os.execute} \stopitem
+ \startitem more r, d, k in xml code \stopitem
+ \startitem mathml, more in \LUA \stopitem
+ \startitem style: font-size, font, color handling in \HTML\ (lxml-css) \stopitem
+ \startitem a \type {\name {A.B.C DEF}} auto-nobreakspace \stopitem
+ \startitem redo \CWEB\ module with \LUA \stopitem
+ \startitem maybe move characters.blocks to its own file \stopitem
+ \startitem more local context = context in \LUA\ files \stopitem
+ \startitem check and optimize all storage.register and locals (cosmetics) \stopitem
+ \startitem check all used modules in \LUA\ (and local them) \stopitem
+ \startitem environment and basic lua helpers are now spread over too many files \stopitem
+ \startitem isolate tracers and showers \stopitem
+ \startitem check all possible usage of ctxcommand \stopitem
+ \startitem there are more s-* modules, like s-fnt-41 \stopitem
+ \startitem check (un)marked tables \stopitem
+\stopitemize
+
+\stoptitle
+
+\starttitle[title=To keep an eye on]
+
+\startitemize[packed]
+ \startitem Currently lpeg replacements interpret the percent sign so we need to escape it. \stopitem
+ \startitem Currently numbers and strings are cast in comparisons bu tthat might change in the future. \stopitem
+\stopitemize
+
+\stoptitle
+
+\definehighlight[notabenered] [color=darkred, style=bold]
+\definehighlight[notabeneblue] [color=darkblue, style=bold]
+\definehighlight[notabeneyellow] [color=darkyellow, style=bold]
+\definehighlight[notabenemagenta][color=darkmagenta,style=bold]
+
+\startluacode
+
+ local coremodules = dofile("status-mkiv.lua")
+
+ local valid = table.tohash {
+ "toks", "attr", "page", "buff", "font", "colo", "phys", "supp", "typo", "strc",
+ "syst", "tabl", "spac", "scrn", "lang", "lxml", "mlib", "java", "pack", "math",
+ "symb", "grph", "anch", "luat", "mult", "back", "node", "meta", "norm", "catc",
+ "cldf", "file", "char", "core", "layo", "trac", "cont", "regi", "enco", "hand",
+ "unic", "sort", "blob", "type", "scrp", "prop", "chem", "bibl", "task",
+ "whatever", "mp", "s", "x", "m", "mtx",
+ }
+
+ local specialcategories = {
+ mkvi = true,
+ }
+
+ local what = {
+ "main", "core", "lua", "optional", "implementations", "extra", "extras", "metafun", "modules", "resources"
+ }
+
+ local totaltodo = 0
+ local totalpending = 0
+ local totalobsolete = 0
+ local totalloaded = 0
+
+ local function summary(nofloaded,noftodo,nofpending,nofobsolete)
+
+ local nofdone = nofloaded - noftodo - nofpending - nofobsolete
+
+ context.starttabulate { "|B|r|" }
+ context.HL()
+ context.NC() context("done") context.NC() context(nofdone) context.NC() context.NR()
+ context.NC() context("todo") context.NC() context(noftodo) context.NC() context.NR()
+ context.NC() context("pending") context.NC() context(nofpending) context.NC() context.NR()
+ context.NC() context("obsolete") context.NC() context(nofobsolete) context.NC() context.NR()
+ context.HL()
+ context.NC() context("loaded") context.NC() context(nofloaded) context.NC() context.NR()
+ context.HL()
+ context.stoptabulate()
+
+ end
+
+ if coremodules then
+
+ local function tabelize(loaded,what)
+
+ if loaded then
+
+ local noftodo = 0
+ local nofpending = 0
+ local nofobsolete = 0
+ local nofloaded = #loaded
+ local categories = { }
+
+ for k, v in next, valid do
+ categories[k] = { }
+ end
+
+ for i=1,nofloaded do
+ local l = loaded[i]
+ l.order = i
+ local category = string.match(l.filename,"([^%-]+)%-") or "whatever"
+ local c = categories[category]
+ if c then
+ c[#c+1] = l
+ end
+ end
+
+ for k, loaded in table.sortedhash(categories) do
+
+ local nofloaded = #loaded
+
+ if nofloaded > 0 then
+
+ table.sort(loaded,function(a,b) return a.filename < b.filename end) -- in place
+
+ context.starttitle { title = string.format("%s: %s",what,k) }
+
+ context.starttabulate { "|Tr|Tlw(3em)|Tlw(12em)|Tlw(12em)|Tlw(4em)|Tl|Tl|Tl|Tp|" }
+ context.NC() context.bold("order")
+ context.NC() context.bold("kind")
+ context.NC() context.bold("file")
+ context.NC() context.bold("loading")
+ context.NC() context.bold("status")
+ context.NC() context.bold("reference")
+ context.NC() context.bold("manual")
+ context.NC() context.bold("wiki")
+ context.NC() context.bold("comment")
+ context.NC() context.NR()
+ context.HL()
+ for i=1,nofloaded do
+ local module = loaded[i]
+ local status = module.status
+ local category = module.category
+ local filename = module.filename
+ context.NC()
+ context(module.order)
+ context.NC()
+ if specialcategories[category] then
+ context.notabeneblue(category)
+ else
+ context(category)
+ end
+ context.NC()
+ if #filename>20 then
+ context(string.sub(filename,1,18) .. "..")
+ else
+ context(filename)
+ end
+ context.NC()
+ context(module.loading)
+ context.NC()
+ if status == "todo" then
+ context.notabenered(status)
+ noftodo = noftodo + 1
+ elseif status == "pending" then
+ context.notabeneyellow(status)
+ nofpending = nofpending + 1
+ elseif status == "obsolete" then
+ context.notabenemagenta(status)
+ nofobsolete = nofobsolete + 1
+ else
+ context(status)
+ end
+ context.NC() context(module.reference)
+ context.NC() context(module.manual)
+ context.NC() context(module.wiki)
+ context.NC() context(module.comment)
+ context.NC() context.NR()
+ end
+ context.stoptabulate()
+
+ context.stoptitle()
+
+ end
+
+ end
+
+ context.starttitle { title = string.format("summary of %s modules",what) }
+
+ summary(nofloaded,noftodo,nofpending,nofobsolete)
+
+ context.stoptitle()
+
+ totaltodo = totaltodo + noftodo
+ totalpending = totalpending + nofpending
+ totalobsolete = totalobsolete + nofobsolete
+ totalloaded = totalloaded + nofloaded
+
+ end
+
+ end
+
+ for i=1,#what do
+ tabelize(coremodules[what[i]],what[i])
+ end
+
+ end
+
+ -- context.starttitle { title = "Valid prefixes" }
+ --
+ -- for namespace, data in table.sortedhash(namespaces) do
+ -- if valid[namespace] then
+ -- context.type(namespace)
+ -- end
+ -- context.par()
+ -- end
+ --
+ -- context.stoptitle()
+
+ context.starttitle { title = string.format("summary of all",what) }
+
+ summary(totalloaded,totaltodo,totalpending,totalobsolete)
+
+ context.stoptitle()
+
+ if io.exists("status-namespaces.lua") then
+
+ context.starttitle { title = "messy namespaces" }
+
+ local namespaces = dofile("status-namespaces.lua")
+
+ for namespace, data in table.sortedhash(namespaces) do
+ if valid[namespace] then
+ else
+ context(namespace)
+ end
+ context.par()
+ end
+
+ context.stoptitle()
+
+ end
+
+ if io.exists("status-registers.lua") then
+
+ context.starttitle { title = "messy registers" }
+
+ local registers = dofile("status-registers.lua")
+
+ for register, data in table.sortedhash(registers) do
+ context(register)
+ context.par()
+ for name in table.sortedhash(data) do
+ context.quad()
+ context.type(name)
+ context.par()
+ end
+ context.par()
+ end
+
+ context.stoptitle()
+
+ end
+
+ context.starttitle { title = "callbacks" }
+
+ commands.showcallbacks()
+
+ context.stoptitle()
+
+\stopluacode
+
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.lua
new file mode 100644
index 00000000000..a055a97a1c4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.lua
@@ -0,0 +1,516 @@
+if not modules then modules = { } end modules ['strc-bkm'] = {
+ version = 0.200,
+ comment = "companion to strc-bkm.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Future version will support adding arbitrary bookmarks with
+-- associated complex actions (rather trivial to implement).
+
+-- this should become proper separated backend code
+
+-- we should hook the placement into everystoptext ... needs checking
+
+-- todo: make an lpeg for stripped
+
+local next, type = next, type
+local gsub, lower = string.gsub, string.lower
+local concat = table.concat
+local utfvalues = utf.values
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end)
+local report_bookmarks = logs.reporter("structure","bookmarks")
+
+local structures = structures
+
+structures.bookmarks = structures.bookmarks or { }
+
+local bookmarks = structures.bookmarks
+local sections = structures.sections
+local lists = structures.lists
+local levelmap = sections.levelmap
+local variables = interfaces.variables
+local implement = interfaces.implement
+local codeinjections = backends.codeinjections
+
+bookmarks.method = "internal" -- or "page"
+
+local names = { }
+local opened = { }
+local forced = { }
+local numbered = { }
+
+function bookmarks.register(settings)
+ local force = settings.force == variables.yes
+ local number = settings.number == variables.yes
+ local allopen = settings.opened == variables.all
+ for k, v in next, settings_to_hash(settings.names or "") do
+ names[k] = true
+ if force then
+ forced[k] = true
+ if allopen then
+ opened[k] = true
+ end
+ end
+ if number then
+ numbered[k] = true
+ end
+ end
+ if not allopen then
+ for k, v in next, settings_to_hash(settings.opened or "") do
+ opened[k] = true
+ end
+ end
+end
+
+function bookmarks.overload(name,text)
+ local l, ls = lists.tobesaved, nil
+ if #l == 0 then
+ -- no entries
+ elseif name == "" then
+ ls = l[#l]
+ else
+ for i=#l,0,-1 do
+ local li = l[i]
+ local metadata = li.metadata
+ if metadata and not metadata.nolist and metadata.name == name then
+ ls = li
+ break
+ end
+ end
+ end
+ if ls then
+ local titledata = ls.titledata
+ if titledata then
+ titledata.bookmark = text
+ end
+ end
+ -- last resort
+ -- context.writetolist({name},text,"")
+end
+
+local function stripped(str) -- kind of generic
+ str = gsub(str,"\\([A-Z]+)","%1") -- \LOGO
+ str = gsub(str,"\\ "," ") -- \
+ str = gsub(str,"\\([A-Za-z]+) *{(.-)}","%2") -- \bla{...}
+ str = gsub(str," +"," ") -- spaces
+ return str
+end
+
+-- todo: collect specs and collect later i.e. multiple places
+
+local numberspec = { }
+
+function bookmarks.setup(spec)
+ -- table.merge(numberspec,spec)
+ for k, v in next, spec do
+ numberspec[k] = v
+ end
+end
+
+function bookmarks.place()
+ if next(names) then
+ local levels = { }
+ local noflevels = 0
+ local lastlevel = 1
+ local nofblocks = #lists.sectionblocks -- always >= 1
+ local showblocktitle = toboolean(numberspec.showblocktitle,true)
+ for i=1,nofblocks do
+ local block = lists.sectionblocks[i]
+ local blockdone = nofblocks == 1
+ local list = lists.filter {
+ names = names,
+ criterium = block .. ":all",
+ forced = forced,
+ }
+ for i=1,#list do
+ local li = list[i]
+ local metadata = li.metadata
+ local name = metadata.name
+ if not metadata.nolist or forced[name] then -- and levelmap[name] then
+ local titledata = li.titledata
+ --
+ if not titledata then
+ local userdata = li.userdata
+ if userdata then
+ local first = userdata.first
+ local second = userdata.second
+ if first then
+ if second then
+ titledata = { title = first .. " " .. second }
+ else
+ titledata = { title = first }
+ end
+ elseif second then
+ titledata = { title = second }
+ else
+ -- ignoring (command and so)
+ end
+ end
+ end
+ --
+ if titledata then
+ if not blockdone then
+ if showblocktitle then
+ -- add block entry
+ local blockdata = sections.sectionblockdata[block]
+ noflevels = noflevels + 1
+ local references = li.references
+ levels[noflevels] = {
+ level = 1, -- toplevel
+ title = stripped(blockdata.bookmark ~= "" and blockdata.bookmark or block),
+ reference = references,
+ opened = allopen or opened[name], -- same as first entry
+ realpage = references and references.realpage or 0, -- handy for later
+ usedpage = true,
+ }
+ end
+ blockdone = true
+ end
+ local structural = levelmap[name]
+ lastlevel = structural or lastlevel
+ if nofblocks > 1 then
+ -- we have a block so increase the level
+ lastlevel = lastlevel + 1
+ end
+ local title = titledata.bookmark
+ if not title or title == "" then
+ -- We could typeset the title and then convert it.
+ -- if not structural then
+ -- title = titledata.title or "?")
+ -- else
+ title = titledata.title or "?"
+ -- end
+ end
+ if numbered[name] then
+ local sectiondata = sections.collected[li.references.section]
+ local numberdata = li.numberdata
+ if sectiondata and numberdata then
+ if not numberdata.hidenumber then
+ -- we could typeset the number and convert it
+ local number = sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata)
+ if number and #number > 0 then
+ title = concat(number) .. " " .. title
+ end
+ end
+ end
+ end
+ noflevels = noflevels + 1
+ local references = li.references
+ levels[noflevels] = {
+ level = lastlevel,
+ title = stripped(title), -- can be replaced by converter
+ reference = references, -- has internal and realpage
+ opened = allopen or opened[name],
+ realpage = references and references.realpage or 0, -- handy for later
+ usedpage = true,
+ structural = structural,
+ name = name,
+ }
+ end
+ end
+ end
+ end
+-- inspect(levels)
+ bookmarks.finalize(levels)
+ function bookmarks.place() end -- prevent second run
+ end
+end
+
+function bookmarks.flatten(levels)
+ if not levels then
+ -- a plugin messed up
+ return { }
+ end
+ -- This function promotes leading structurelements with a higher level
+ -- to the next lower level. Such situations are the result of lack of
+ -- structure: a subject preceding a chapter in a sectionblock. So, the
+ -- following code runs over section blocks as well. (bookmarks-007.tex)
+ local noflevels = #levels
+ if noflevels > 1 then
+ local function showthem()
+ for i=1,noflevels do
+ local level = levels[i]
+ -- if level.structural then
+ -- report_bookmarks("%i > %s > %s",level.level,level.reference.block,level.title)
+ -- else
+ report_bookmarks("%i > %s > %s > %s",level.level,level.reference.block,level.name,level.title)
+ -- end
+ end
+ end
+ if trace_bookmarks then
+ report_bookmarks("checking structure")
+ showthem()
+ end
+ local skip = false
+ local done = 0
+ local start = 1
+ local one = levels[1]
+ local first = one.level
+ local block = one.reference.block
+ for i=2,noflevels do
+ local current = levels[i]
+ local new = current.level
+ local reference = current.reference
+ local newblock = type(reference) == "table" and current.reference.block or block
+ if newblock ~= block then
+ first = new
+ block = newblock
+ start = i
+ skip = false
+ elseif skip then
+ -- go on
+ elseif new > first then
+ skip = true
+ elseif new < first then
+ for j=start,i-1 do
+ local previous = levels[j]
+ local old = previous.level
+ previous.level = new
+ if trace_bookmarks then
+ report_bookmarks("promoting entry %a from level %a to %a: %s",j,old,new,previous.title)
+ end
+ done = done + 1
+ end
+ skip = true
+ end
+ end
+ if trace_bookmarks then
+ if done > 0 then
+ report_bookmarks("%a entries promoted")
+ showthem()
+ else
+ report_bookmarks("nothing promoted")
+ end
+ end
+ end
+ return levels
+end
+
+local extras = { }
+local lists = { }
+local names = { }
+
+bookmarks.extras = extras
+
+local function cleanname(name)
+ return lower(file.basename(name))
+end
+
+function extras.register(name,levels)
+ if name and levels then
+ name = cleanname(name)
+ local found = names[name]
+ if found then
+ lists[found].levels = levels
+ else
+ lists[#lists+1] = {
+ name = name,
+ levels = levels,
+ }
+ names[name] = #lists
+ end
+ end
+end
+
+function extras.get(name)
+ if name then
+ local found = names[cleanname(name)]
+ if found then
+ return lists[found].levels
+ end
+ else
+ return lists
+ end
+end
+
+function extras.reset(name)
+ local l, n = { }, { }
+ if name then
+ name = cleanname(name)
+ for i=1,#lists do
+ local li = lists[i]
+ local ln = li.name
+ if name == ln then
+ -- skip
+ else
+ local m = #l + 1
+ l[m] = li
+ n[ln] = m
+ end
+ end
+ end
+ lists, names = l, n
+end
+
+local function checklists()
+ for i=1,#lists do
+ local levels = lists[i].levels
+ for j=1,#levels do
+ local entry = levels[j]
+ local pageindex = entry.pageindex
+ if pageindex then
+ entry.reference = figures.getrealpage(pageindex)
+ entry.pageindex = nil
+ end
+ end
+ end
+end
+
+function extras.tosections(levels)
+ local sections = { }
+ local noflists = #lists
+ for i=1,noflists do
+ local levels = lists[i].levels
+ local data = { }
+ sections[i] = data
+ for j=1,#levels do
+ local entry = levels[j]
+ if entry.usedpage then
+ local section = entry.section
+ local d = data[section]
+ if d then
+ d[#d+1] = entry
+ else
+ data[section] = { entry }
+ end
+ end
+ end
+ end
+ return sections
+end
+
+function extras.mergesections(levels,sections)
+ if not sections or #sections == 0 then
+ return levels
+ elseif not levels then
+ return { }
+ else
+ local merge = { }
+ local noflists = #lists
+ if #levels == 0 then
+ local level = 0
+ local section = 0
+ for i=1,noflists do
+ local entries = sections[i][0]
+ if entries then
+ for i=1,#entries do
+ local entry = entries[i]
+ merge[#merge+1] = entry
+ entry.level = entry.level + level
+ end
+ end
+ end
+ else
+ for j=1,#levels do
+ local entry = levels[j]
+ merge[#merge+1] = entry
+ local section = entry.reference.section
+ local level = entry.level
+ entry.section = section -- for tracing
+ for i=1,noflists do
+ local entries = sections[i][section]
+ if entries then
+ for i=1,#entries do
+ local entry = entries[i]
+ merge[#merge+1] = entry
+ entry.level = entry.level + level
+ end
+ end
+ end
+ end
+ end
+ return merge
+ end
+end
+
+function bookmarks.merge(levels,mode)
+ return extras.mergesections(levels,extras.tosections())
+end
+
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+
+local bookmarkactions = sequencers.new {
+ arguments = "levels,method",
+ returnvalues = "levels",
+ results = "levels",
+}
+
+appendgroup(bookmarkactions,"before") -- user
+appendgroup(bookmarkactions,"system") -- private
+appendgroup(bookmarkactions,"after" ) -- user
+
+appendaction(bookmarkactions,"system",bookmarks.flatten)
+appendaction(bookmarkactions,"system",bookmarks.merge)
+
+function bookmarks.finalize(levels)
+ local method = bookmarks.method or "internal"
+ checklists() -- so that plugins have the adapted page number
+ levels = bookmarkactions.runner(levels,method)
+ if levels and #levels > 0 then
+ -- normally this is not needed
+ local purged = { }
+ for i=1,#levels do
+ local l = levels[i]
+ if l.usedpage ~= false then
+ purged[#purged+1] = l
+ end
+ end
+ --
+ codeinjections.addbookmarks(purged,method)
+ else
+ -- maybe a plugin messed up
+ end
+end
+
+function bookmarks.installhandler(what,where,func)
+ if not func then
+ where, func = "after", where
+ end
+ if where == "before" or where == "after" then
+ sequencers.appendaction(bookmarkactions,where,func)
+ else
+ report_tex("installing bookmark %a handlers in %a is not possible",what,tostring(where))
+ end
+end
+
+-- interface
+
+implement {
+ name = "setupbookmarks",
+ actions = bookmarks.setup,
+ arguments = {
+ {
+ { "separatorset" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ { "segments" },
+ { "showblocktitle" },
+ }
+ }
+}
+
+implement {
+ name = "registerbookmark",
+ actions = bookmarks.register,
+ arguments = {
+ {
+ { "names" },
+ { "opened" },
+ { "force" },
+ { "number" },
+ }
+ }
+}
+
+implement {
+ name = "overloadbookmark",
+ actions = bookmarks.overload,
+ arguments = { "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.mkiv
new file mode 100644
index 00000000000..5a8dba562f5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-bkm.mkiv
@@ -0,0 +1,188 @@
+%D \module
+%D [ file=strc-bkm,
+%D version=2009.04.01,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Bookmarks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Bookmarks}
+
+\registerctxluafile{strc-bkm}{1.001}
+
+% \enabledirectives[references.bookmarks.preroll]
+
+\unprotect
+
+%D Bookmarks are a very viewer dependent feature. They are mostly used
+%D as additional table of contents and therefore relate directly to lists.
+%D
+%D A bookmark list is added to the document only when interaction is
+%D enabled. The given lists are bookmarked and a second argument specifies
+%D the opened bookmark trees.
+%D
+%D \starttyping
+%D \placebookmarks
+%D [chapter,section,subsection,mylist]
+%D [chapter]
+%D \stoptyping
+%D
+%D You can overloads the last set bookmark in a sectioning command:
+%D
+%D \starttyping
+%D \chapter {the first chapter}
+%D \bookmark {the first bookmark}
+%D \stoptyping
+%D
+%D However, in practice you can better use \type {\startchapter} and set the
+%D \type {bookmark} parameter.
+%D
+%D You can add entries to the bookmarklist:
+%D
+%D \starttyping
+%D \bookmark[mylist]{whatever}
+%D \stoptyping
+%D
+%D Use force to get titles in the bookmarklist. This is somewhat tricky as
+%D one does not want "Contents" in a table of contents but it has to be in
+%D the bookmark list.
+
+\installcorenamespace{bookmark}
+
+\installsetuponlycommandhandler \??bookmark {bookmark} % installdirectparametersethandler
+
+\setupbookmark
+ [\c!force=\v!no, % it's easier to force that to inhibit
+ \c!number=\v!yes, % might become v!no
+ \c!sectionblock=\v!no] % show sectionblock level + title
+
+\let\setupbookmarks\setupbookmark
+
+\unexpanded\def\bookmark
+ {\dosingleempty\strc_bookmarks_bookmark}
+
+\def\strc_bookmarks_bookmark
+ {\iflocation
+ \expandafter\strc_bookmarks_bookmark_yes
+ \else
+ \expandafter\strc_bookmarks_bookmark_nop
+ \fi}
+
+\def\strc_bookmarks_bookmark_yes[#1]#2%
+ {\begingroup
+ \simplifycommands
+ \ifnum\thenamedheadlevel{#1}>\zerocount
+ \clf_overloadbookmark{#1}{\detokenize\expandafter{\normalexpanded{#2}}}%
+ \else
+ \strc_lists_write_to[#1][]{#2}{}% todo: a dedicated bookmark writer
+ \fi
+ \endgroup}
+
+\def\strc_bookmarks_bookmark_nop[#1]#2%
+ {}
+
+\unexpanded\def\placebookmarks
+ {\dotripleempty\strc_bookmarks_place}
+
+\def\strc_bookmarks_place
+ {\iflocation
+ \expandafter\strc_bookmarks_place_yes
+ \else
+ \expandafter\gobblethreeoptionals
+ \fi}
+
+\let\m_bookmarks_names \empty
+\let\m_bookmarks_opened\empty
+
+\def\strc_bookmarks_place_yes[#1][#2][#3]%
+ {\begingroup
+ \edef\m_bookmarks_names{#1}%
+ \edef\m_bookmarks_opened{#2}%
+ \ifx\m_bookmarks_names\empty
+ \edef\m_bookmarks_names{\namedlistparameter\v!content\c!list}%
+ \fi
+ \ifx\m_bookmarks_names\empty
+ \let\m_bookmarks_names\v!all
+ \fi
+ \ifthirdargument
+ \setupcurrentbookmark[#3]% no every so not all possible
+ \else\ifsecondargument
+ \doifelseassignment{#2}{\let\m_bookmarks_opened\empty\setupcurrentbookmark[#2]}\donothing
+ \fi\fi
+ \clf_registerbookmark
+ names {\m_bookmarks_names}%
+ opened {\m_bookmarks_opened}%
+ force {\bookmarkparameter\c!force}%
+ number {\bookmarkparameter\c!number}%
+ \relax
+ \endgroup}
+
+\appendtoks
+ \clf_setupbookmarks
+ separatorset {\bookmarkparameter\c!numberseparatorset}%
+ conversionset {\bookmarkparameter\c!numberconversionset}%
+ starter {\bookmarkparameter\c!numberstarter}%
+ stopper {\bookmarkparameter\c!numberstopper}%
+ segments {\bookmarkparameter\c!numbersegments}%
+ showblocktitle {\bookmarkparameter\c!sectionblock}%
+ \relax
+\to \everysetupbookmark
+
+%D There is a plugin mechanism but this is for experts only. The intermediate
+%D data structures are stable.
+%D
+%D \starttyping
+%D \startluacode
+%D structures.bookmarks.installhandler("check before","before",function(levels)
+%D logs.report("extra bookmarks","before (normal bookmarks)")
+%D inspect(levels)
+%D logs.report("extra bookmarks","before (extra bookmarks)")
+%D inspect(structures.bookmarks.extras.get())
+%D return levels
+%D end)
+%D structures.bookmarks.installhandler("check after", "after", function(levels)
+%D logs.report("extra bookmarks","after (merged bookmarks)")
+%D inspect(levels)
+%D return levels
+%D end)
+%D \stopluacode
+%D \starttyping
+%D
+%D This mechanism was added when bookmark inclusion became (optional) part of graphic
+%D inclusion (which is needed by Taco).
+%D
+%D \starttyping
+%D \getfiguredimensions[somefile.pdf]
+%D \dorecurse {\noffigurepages} {
+%D \startTEXpage
+%D \externalfigure[somefile.pdf][interaction=bookmark,page=\recurselevel]
+%D \stopTEXpage
+%D }
+%D \starttyping
+
+\protect \endinput
+
+% \starttext
+% \setupinteraction[state=start]\setupinteractionscreen[option=bookmark]
+% \placebookmarks[chapter,section,subsection][chapter]
+% \chapter{First}
+% \bookmark{The First Indeed}
+% \section{alpha}
+% \bookmark[chapter]{The First Indeed Again}
+% \section{beta}
+% \chapter{Second}
+% \bookmark{The Second Indeed}
+% \section{gamma \tex{radiation}}
+% \subsection{a}
+% \subsection{b}
+% \section{delta}
+% \section{epsilon}
+% \chapter{Third \relax}
+% \chapter{我〈能吞下玻璃而不傷身〉體。} % whatever that means
+% \chapter{Idris Samawi Hamid ادريس سماوي حامد}
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua
new file mode 100644
index 00000000000..0ababcfc09c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua
@@ -0,0 +1,162 @@
+if not modules then modules = { } end modules ['strc-blk'] = {
+ version = 1.001,
+ comment = "companion to strc-blk.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this one runs on top of buffers and structure
+
+local type = type
+local find, format, validstring = string.find, string.format, string.valid
+local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array
+local allocate = utilities.storage.allocate
+
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local structures = structures
+
+structures.blocks = structures.blocks or { }
+
+local blocks = structures.blocks
+local sections = structures.sections
+local lists = structures.lists
+
+local collected = allocate()
+local tobesaved = allocate()
+local states = allocate()
+
+blocks.collected = collected
+blocks.tobesaved = tobesaved
+blocks.states = states
+
+local function initializer()
+ collected = blocks.collected
+ tobesaved = blocks.tobesaved
+end
+
+job.register('structures.blocks.collected', tobesaved, initializer)
+
+local listitem = utilities.parsers.listitem
+
+function blocks.print(name,data,hide)
+ if hide then
+ context.dostarthiddenblock(name)
+ else
+ context.dostartnormalblock(name)
+ end
+ context.viafile(data,format("block.%s",validstring(name,"noname")))
+ if hide then
+ context.dostophiddenblock()
+ else
+ context.dostopnormalblock()
+ end
+end
+
+function blocks.define(name)
+ states[name] = { all = "hide" }
+end
+
+function blocks.setstate(state,name,tag)
+ local all = tag == ""
+ local tags = not all and settings_to_array(tag)
+ for n in listitem(name) do
+ local sn = states[n]
+ if not sn then
+ -- error
+ elseif all then
+ sn.all = state
+ else
+ for _, tag in next, tags do
+ sn[tag] = state
+ end
+ end
+ end
+end
+
+function blocks.select(state,name,tag,criterium)
+ criterium = criterium or "text"
+ if find(tag,"=",1,true) then
+ tag = ""
+ end
+ local names = settings_to_set(name)
+ local all = tag == ""
+ local tags = not all and settings_to_set(tag)
+ local hide = state == "process"
+ local result = lists.filter {
+ names = "all",
+ criterium = criterium,
+ number = sections.numberatdepth(criterium), -- not needed
+ collected = collected,
+ }
+ for i=1,#result do
+ local ri = result[i]
+ local metadata = ri.metadata
+ if names[metadata.name] then
+ if all then
+ blocks.print(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)
+ break
+ end
+ end
+ end
+ end
+ 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,
+ minus = minus,
+ },
+ references = {
+ 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)
+ elseif plus then
+ blocks.print(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)
+ break
+ end
+ elseif sn[tag] ~= "hide" then
+ blocks.print(name,data)
+ break
+ end
+ end
+ end
+ buffers.erase(buffer)
+end
+
+-- interface
+
+implement { name = "definestructureblock", actions = blocks.define, arguments = "string" }
+implement { name = "savestructureblock", actions = blocks.save, arguments = { "string", "string" ,"string" } }
+implement { name = "selectstructureblock", actions = blocks.select, arguments = { "string", "string" ,"string", "string" } }
+implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = { "string", "string" ,"string" } }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv
new file mode 100644
index 00000000000..fe259d223ce
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv
@@ -0,0 +1,100 @@
+%D \module
+%D [ file=strc-blk,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Blockmoves,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Blockmoves}
+
+\registerctxluafile{strc-blk}{1.001}
+
+\unprotect
+
+% we run on top of buffers and sections
+%
+% todo: prefix numbers (needs further integration elsewhere)
+% check functionality
+% alternative files (needs further integration elsewhere)
+%
+% order matters: \c!before (think of: \c!before=\startitemize)
+%
+% no \endgroups
+
+\installcorenamespace {block}
+\installcorenamespace {blocktemp}
+
+\installcommandhandler \??block {block} \??block
+
+\appendtoks
+ \clf_definestructureblock{\currentblock}%
+ \setuevalue{\e!begin\currentblock}{\dodoubleempty\strc_blocks_begin[\currentblock]}%
+ \setuevalue{\e!end \currentblock}{}%
+\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
+
+\let\strc_blocks_setup\relax
+
+\unexpanded\def\dostarthiddenblock % called at lua end
+ {\startnointerference
+ \dostartnormalblock}
+
+\unexpanded\def\dostophiddenblock % called at lua end
+ {\dostopnormalblock
+ \stopnointerference}
+
+\unexpanded\def\dostartnormalblock#1% called at lua end
+ {\bgroup
+ \visibletrue % will change
+ \edef\currentblock{#1}%
+ \strc_blocks_setup
+ \let\strc_blocks_setup\relax
+ \blockparameter\c!before
+ \useblockstyleandcolor\c!style\c!color % maybe moev one line up (font spacing)
+ \blockparameter\c!inner % better \c!setups
+ \ignorespaces}
+
+\unexpanded\def\dostopnormalblock % called at lua end
+ {\removeunwantedspaces
+ \blockparameter\c!after
+ \par % todo: alternative = text, paragraph
+ \egroup}
+
+\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
+ \doifelseassignment{#3}
+ {\getparameters[\??blocktemp][\c!criterium=\v!text,#3]%
+ \def\strc_blocks_setup{\setupcurrentblock[#3]}%
+ \clf_selectstructureblock{#1}{#2}{}{\csname\??blocktemp\c!criterium\endcsname}}
+ {\getparameters[\??blocktemp][\c!criterium=\v!text,#4]%
+ \def\strc_blocks_setup{\setupcurrentblock[#4]}%
+ \clf_selectstructureblock{#1}{#2}{#3}{\csname\??blocktemp\c!criterium\endcsname}}%
+ \egroup}
+
+% hide : save, if [+] also hidden execute
+% keep : save and normal execute
+% use : normal execute unless [-]
+% process: hidden execute unless [-]
+% select : idem use
+
+\unexpanded\def\hideblocks {\dotripleempty \strc_blocks_set_state[hide]}
+\unexpanded\def\keepblocks {\dotripleempty \strc_blocks_set_state[keep]}
+\unexpanded\def\useblocks {\doquadrupleempty\strc_blocks_select [use]}
+\unexpanded\def\processblocks{\doquadrupleempty\strc_blocks_select [process]}
+\unexpanded\def\selectblocks {\doquadrupleempty\strc_blocks_select [use]}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-con.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-con.lua
new file mode 100644
index 00000000000..29a1c0cb36d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-con.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['strc-con'] = {
+ version = 1.001,
+ comment = "companion to strc-con.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- empty
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi
new file mode 100644
index 00000000000..25e26bf7369
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi
@@ -0,0 +1,1049 @@
+%D \module
+%D [ file=strc-con,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Constructions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Constructions}
+
+\registerctxluafile{strc-con}{1.001}
+
+% todo: check why \copy .. probably mkii leftover
+%
+% todo: check if commands similar to lists
+% todo: \strc_constructions_setup_counter\strc_constructions_setup_counter{#1} in setup ... synchronization
+%
+% ? : \def\showdnlisttext{\constructionparameter\c!listtext} % space in default
+%
+% maybe: pickup text and store in buffer ...
+%
+% \@@notemakeconstruction[##1]{}{##2}%
+% \expandafter\endgroup\noteparameter\c!next}}
+%
+% todo: \currentconstructionattribute : can be a counter instead
+
+%D Constructions are just descriptions but a bit more abstract so that we can
+%D conveniently build upon them. They are not really meant for users but module
+%D writers might find them useful. We mention a couple of parameters but these are
+%D only mentioned because in the shared code we map all resolvers to constructions.
+%D
+%D On top of constructions we build descriptions, enumerations, notes, labels and
+%D maybe some day more.
+
+\unprotect
+
+%D Todo:
+
+\installcorenamespace{construction}
+
+\installcommandhandler \??construction {construction} \??construction
+
+\let\setupconstructions\setupconstruction
+
+\setupconstructions[%
+ %c!title=,
+ %c!text=,
+ %
+ %c!style=,
+ %c!color=,
+ %c!command=,
+ %c!align=,
+ %
+ %c!headstyle=,
+ %c!headcolor=,
+ %c!headalign=,
+ %
+ %c!titlestyle=,
+ %c!titlecolor=,
+ %c!titlecommand=,
+ %c!titleleft=,
+ %c!titleright=,
+ %
+ %c!closesymbol=,
+ %c!closecommand=,
+ %
+ \c!alternative=\v!left,
+ \c!display=\v!yes,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %c!hang=,
+ %c!sample=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %c!indentnext=,
+ %c!indenting=,
+ %
+ \c!expansion=\v!no,
+ %c!xmlsetup=,
+ %s!catcodes=,
+]
+
+%D Constructions and alike uses similar structures. In order to prevent issues
+%D we freeze some states. There is some overhead in the intermediate define
+%D step (as we could set them directly) but this is more flexible (and looks
+%D nicer). Keep in mind that descriptions, enumeration and notations are all
+%D independent and that we just remap the resolvers.
+
+% \defineconstruction[test][handler=description,level=1]
+% \defineconstruction[test][parent][handler=description,level=3]
+
+\installcorenamespace{constructionmain} % frozen after definition
+\installcorenamespace{constructionlevel} % frozen after definition
+\installcorenamespace{constructionclass} % frozen after definition
+
+\let\currentconstructionmain \empty
+\let\currentconstructionlevel \empty
+\let\currentconstructionhandler\empty
+
+\settrue\c_strc_constructions_define_commands % use with care, might become a proper key
+
+\appendtoks
+ \ifx\currentconstructionparent\empty
+ \letvalue{\??constructionmain\currentconstruction}\currentconstruction
+ \definelist[\currentconstruction]% goodie
+ \else
+ \letvalue{\??constructionmain\currentconstruction}\currentconstructionparent
+ \definelist[\currentconstruction][\currentconstructionparent]% goodie
+ \fi
+ \setevalue{\??constructionlevel\currentconstruction}{\number\constructionparameter\c!level}%
+ \setevalue{\??constructionclass\currentconstruction}{\constructionparameter\s!handler}%
+\to \everydefineconstruction
+
+\appendtoks
+ \ifconditional\c_strc_constructions_define_commands
+ \setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}%
+ \setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}%
+ \fi
+\to \everydefineconstruction
+
+%D Just a basic environment (mostly for testing). We will provide a 'setup' based
+%D plugin once the rest is sorted out.
+
+\unexpanded\def\strc_constructions_start#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \dodoubleempty\strc_constructions_start_regular}
+
+\unexpanded\def\strc_constructions_start_regular[#1][#2]%
+ {\strc_constructions_register[#2][\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_constructions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname
+ \endgroup}
+
+%D As we will build on top of the generic construction mechanism we have handlers
+%D as a sort of plug in mechanism. In order to have some consistency we share
+%D some namespaces.
+
+\installcorenamespace{constructioninitializer}
+\installcorenamespace{constructionfinalizer}
+
+\installcorenamespace{constructionmainhandler}
+\installcorenamespace{constructioncommandhandler}
+\installcorenamespace{constructionstarthandler}
+\installcorenamespace{constructionstophandler}
+
+\installcorenamespace{constructiontexthandler}
+\installcorenamespace{constructionnotehandler}
+
+\unexpanded\def\strc_constructions_initialize#1% class instance
+ {\edef\currentconstruction{#1}%
+ \let\currentconstructionhash\??construction
+ \let\currentconstructionlistentry\!!zerocount
+ \expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname
+ \expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname
+ \expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname
+ \csname\??constructioninitializer\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_constructions_finalize
+ {\csname\??constructionfinalizer\currentconstructionhandler\endcsname
+ \strc_constructions_discard}
+
+\newconditional\c_strc_constructions_number_state
+\newconditional\c_strc_constructions_title_state
+
+\unexpanded\setvalue{\??constructioninitializer\v!construction}%
+ {\setfalse\c_strc_constructions_number_state
+ \setfalse\c_strc_constructions_title_state}
+
+\unexpanded\setvalue{\??constructionfinalizer\v!construction}%
+ {}
+
+%D We keep the command variant around but rather would move to the start-stop one.
+%D Also, passing the title as argument has some history so we need to keep that as
+%D well.
+
+% \ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi
+
+\newtoks\everyconstruction
+
+\unexpanded\def\currentconstructiontext
+ {\begstrut
+ \csname\??constructiontexthandler\currentconstructionhandler\endcsname
+ \endstrut}
+
+\unexpanded\def\currentconstructionsample
+ {\begstrut
+ \constructionparameter\c!text
+ \p_strc_constructions_sample
+ \endstrut}
+
+\unexpanded\setvalue{\??constructionmainhandler\v!construction}#1%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize % reinstated
+ \attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#1}
+
+\unexpanded\setvalue{\??constructiontexthandler\v!construction}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext
+ \the\everyconstruction
+ \constructionparameter\c!headcommand
+ {\strut
+ \constructionparameter\c!text
+ \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}%
+ \endgroup}
+
+\unexpanded\def\strc_constructions_stored_start
+ {\begingroup % brrr \endgroup elsewhere ... will be sorted out
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_constructions_stored_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname}
+
+\newconstant\c_strc_constructions_nested_state % to be redone
+
+\def\resetconstructions % to be used in e.g. footnotes
+ {\c_strc_constructions_nested_state\zerocount}
+
+\unexpanded\setvalue{\??constructioncommandhandler\v!construction}%
+ {\endgroup}
+
+\let\p_strc_constructions_sample \empty
+\let\p_strc_constructions_align \empty
+\let\p_strc_constructions_indenting \empty
+\let\p_strc_constructions_width \empty
+\let\p_strc_constructions_aligntitle \empty
+\let\p_strc_constructions_renderingsetup\empty
+\let\p_strc_constructions_headalign \empty
+\let\p_strc_constructions_hang \empty
+\let\p_strc_constructions_inbetween \empty
+\let\p_strc_constructions_closesymbol \empty
+\let\p_strc_constructions_distance \empty
+
+\newconditional\c_strc_constructions_distance_none
+
+\def\strc_constructions_set_width_and_distance
+ {\assignwidth
+ \p_strc_constructions_width
+ \constructionsheadwidth
+ {\unhcopy\constructionheadbox}
+ \constructionsheaddistance}
+
+\def\strc_constructions_preroll_head#content%
+ {\setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \settrialtypesetting
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname#content}}
+
+\def\strc_constructions_ignore_head
+ {\constructionsheaddistance\zeropoint
+ \constructionsheadwidth \zeropoint
+ % we also need to make sure that no stretch creeps in (new per 2015-02-02, for Alan)
+ \settrue\c_strc_constructions_distance_none}
+
+\let\currentconstructionhash\??construction
+
+\unexpanded\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing
+ {\dostarttaggedchained\t!construction\currentconstruction\currentconstructionhash
+% \dotagsetconstruction
+ \constructionparameter\c!before
+ \begingroup
+ \edef\currentconstructionalternative{\constructionparameter\c!alternative}%
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}%
+ % catch fuzzyness
+ \ifx\p_strc_constructions_renderingsetup\empty
+ \letconstructionparameter\c!alternative\v!left
+ \let\currentconstructionalternative\v!left
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}%
+ \else
+ \doifnotsetups\p_strc_constructions_renderingsetup
+ {\letconstructionparameter\c!alternative\v!left
+ \let\currentconstructionalternative\v!left
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}}%
+ \fi
+ %
+ \doadaptleftskip{\constructionparameter\c!margin}%
+ \setlocalhsize % so we can use \localhsize in width assignments
+ \edef\p_strc_constructions_distance{\constructionalternativeparameter\c!distance}%
+ \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}%
+ \ifx\p_strc_constructions_distance\v!none
+ \settrue\c_strc_constructions_distance_none
+ \constructionsheaddistance\zeropoint
+ \else
+ \setfalse\c_strc_constructions_distance_none
+ \constructionsheaddistance\p_strc_constructions_distance\relax
+ \ifdim\constructionsheaddistance=\zeropoint
+ \ifx\p_strc_constructions_width\v!broad
+ \constructionsheaddistance\emwidth
+ \else\ifx\p_strc_constructions_width\v!line
+ \constructionsheaddistance\emwidth
+ \fi\fi
+ \fi
+ \fi
+ % inefficient and not always needed, for instance not with margins so we will make checkers
+ % per alternative some day (especially in labels this is unwanted overhead)
+ %
+ % maybe we should have an option as i cannot oversee the consequences now
+ %
+ % \edef\p_strc_constructions_sample{\constructionparameter\c!sample}%
+ % \ifx\p_strc_constructions_sample\empty
+ % \strc_constructions_preroll_head\currentconstructiontext
+ % \else
+ % \strc_constructions_preroll_head\currentconstructiontextsample
+ % \fi
+ % \strc_constructions_set_width_and_distance
+ %
+ \strc_constructions_preroll_head\currentconstructiontext
+ \ifzeropt\wd\constructionheadbox
+ \strc_constructions_ignore_head
+ \else
+ \edef\p_strc_constructions_sample{\constructionparameter\c!sample}%
+ \ifx\p_strc_constructions_sample\empty
+ \strc_constructions_set_width_and_distance
+ \else
+ \strc_constructions_preroll_head\currentconstructionsample
+ \ifzeropt\wd\constructionheadbox
+ \strc_constructions_ignore_head
+ \else
+ \strc_constructions_set_width_and_distance
+ \fi
+ \fi
+ \fi
+ %
+ \dostarttagged\t!constructiontag\empty % todo
+ \setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \ifx\currentconstructionalternative\v!serried % brrr, hack, will change
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext
+ \else
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}%
+ \fi}%
+ \edef\p_strc_constructions_aligntitle{\constructionparameter\c!aligntitle}%
+ \ifx\p_strc_constructions_aligntitle\v!no
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \else
+ \ifcase\c_strc_constructions_nested_state
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \fi
+ \fi
+ \edef\p_strc_constructions_align{\constructionparameter\c!align}%
+ \ifx\p_strc_constructions_align\empty \else
+ \setupalign[\p_strc_constructions_align]% \use...
+ \fi
+ \ifcase\c_strc_constructions_nested_state
+ \c_strc_constructions_nested_state\plusone
+ \or
+ \c_strc_constructions_nested_state\plustwo
+ \fi
+ \strc_constructions_close_symbol_reset
+ %
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ %
+ \directsetup\p_strc_constructions_renderingsetup\relax
+ % moved to here 2014-07-03
+ \edef\p_strc_constructions_indenting{\constructionparameter\c!indenting}%
+ \ifx\p_strc_constructions_indenting\empty \else
+ \indenting[\p_strc_constructions_indenting]% \use...
+ \fi
+ %
+ \dostoptagged % tag
+ \dostarttagged\t!constructioncontent\empty
+ \ignorespaces} % args not needed
+
+\unexpanded\setvalue{\??constructionstophandler\v!construction}%
+ {\strc_constructions_close_symbol_place
+ \doifnot{\constructionparameter\c!display}\v!no\par
+ \dostoptagged % content
+ \dostoptagged % construction
+ \endgroup
+ \constructionparameter\c!after
+ \useindentnextparameter\constructionparameter
+ \strc_constructions_finalize
+% \endgroup
+ \dorechecknextindentation}
+
+\unexpanded\def\boxedconstructionhead#1%
+ {\vtop
+ {\hsize\constructionsheadwidth
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ \ifx\p_strc_constructions_headalign\empty \else
+ \setupalign[\p_strc_constructions_headalign]% \use...
+ \fi
+ #1}}
+
+\installcorenamespace{constructionalternative}
+\installcorenamespace{constructionrenderings}
+
+% see lists: alternativemethods ... todo
+%
+% there will be a proper interface to variables
+
+\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative
+
+\setupconstructionalternative
+ [\c!width=\constructionparameter\c!width,
+ \c!distance=\constructionparameter\c!distance]
+
+\defineconstructionalternative
+ [\v!left]
+ [%\c!width=7em,
+ %\c!distance=1em,
+ \c!renderingsetup=\??constructionrenderings:\v!left]
+
+\defineconstructionalternative
+ [\v!right]
+ [%\c!width=7em,
+ %\c!distance=1em,
+ \c!renderingsetup=\??constructionrenderings:\v!right]
+
+\defineconstructionalternative
+ [\v!inmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!inmargin]
+
+\defineconstructionalternative
+ [\v!inleft]
+ [\c!renderingsetup=\??constructionrenderings:\v!inleft]
+
+\defineconstructionalternative
+ [\v!inright]
+ [\c!renderingsetup=\??constructionrenderings:\v!inright]
+
+\defineconstructionalternative
+ [\v!margin]
+ [\c!renderingsetup=\??constructionrenderings:\v!margin]
+
+\defineconstructionalternative
+ [\v!leftmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!leftmargin]
+
+\defineconstructionalternative
+ [\v!rightmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!rightmargin]
+
+\defineconstructionalternative
+ [\v!innermargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!innermargin]
+
+\defineconstructionalternative
+ [\v!outermargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!outermargin]
+
+\defineconstructionalternative
+ [\v!serried]
+ [\c!renderingsetup=\??constructionrenderings:\v!serried]
+
+\defineconstructionalternative
+ [\v!hanging]
+ [%\c!width=\v!fit,
+ \c!renderingsetup=\??constructionrenderings:\v!hanging]
+
+\defineconstructionalternative
+ [\v!top]
+ [\c!renderingsetup=\??constructionrenderings:\v!top,
+ \c!width=\localhsize]
+
+\defineconstructionalternative
+ [\v!command]
+ [\c!renderingsetup=\??constructionrenderings:\v!command]
+
+\newbox \constructionheadbox
+\newskip \leftconstructionskip
+\newskip \rightconstructionskip
+\newdimen \constructionsheadwidth % replaces \!!widtha % TODO: proper namespace dimens
+\newdimen \constructionsheaddistance % replaces \!!widthb % TODO: proper namespace dimens
+
+\def\strc_constructions_set_hang_box#1% messy left/rightskip
+ {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang
+ {\forgetall
+ \dontcomplain
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_strc_constructions_headalign]% use fast one
+ \fi
+ \ifconditional\c_strc_constructions_distance_none \else
+ \advance\ifx#1\v!flushleft\rightskip\else\leftskip\fi\constructionsheaddistance % only difference and wrong anyway
+ \fi
+ \flushconstructionheadbox}%
+ \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
+ \ht\constructionheadbox\strutht
+ \dp\constructionheadbox\strutdp}
+
+\def\strc_constructions_set_pure_box#1% default ... better set up differently
+ {\setbox\constructionheadbox\vtop
+ {\forgetall
+ \dontcomplain
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_strc_constructions_headalign]% use fast one
+ \fi
+ \flushconstructionheadbox}%
+ \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
+ \ht\constructionheadbox\strutht
+ \dp\constructionheadbox\strutdp}
+
+\def\strc_constructions_set_hang#1%
+ {\ifx\p_strc_constructions_hang\empty
+ % nothing
+ \else\ifx\p_strc_constructions_hang\v!fit
+ \scratchdimen\htdp\constructionheadbox
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \else\ifx\p_strc_constructions_hang\v!broad
+ \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \else
+ \hangafter-\p_strc_constructions_hang
+ \fi\fi\fi
+ \relax
+ \hangindent\ifx#1\v!right-\fi\constructionsheadwidth}
+
+% \unexpanded\def\flushconstructionheadbox
+% {\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}
+
+\unexpanded\def\flushconstructionheadbox
+ {\ifhbox\constructionheadbox\unhbox\else\box\fi\constructionheadbox}
+
+% The setups. These only deal with placement of the descriptor and initializing the
+% environment. The wrapping happens elsewhere.
+
+% todo: optimize the setups with
+%
+% \ifconditional\c_strc_constructions_distance_none : no need for skip
+% \ifzeropt\wd\constructionheadbox : no need for box and skips
+
+\startsetups[\??constructionrenderings:\v!left]
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}%
+ \doifelsesetups{\??constructionrenderings:\v!left:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!left:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right]
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}
+ \doifelsesetups{\??constructionrenderings:\v!right:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!right:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!none]
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
+ \rightskip\rightconstructionskip\relax
+ \llap {
+ \hpack to \leftskip {
+ \hskip\leftconstructionskip
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:0]
+ \directsetup{\??constructionrenderings:\v!left:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:]
+ \directsetup{\??constructionrenderings:\v!left:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!none]
+ \let\\=\crlf
+ \noindent
+ \leftskip\leftconstructionskip
+ \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax
+ %\strc_constructions_pure_hang_box\raggedleft
+ \strc_constructions_set_pure_box\v!flushright
+ \rlap {
+ \hskip\dimexpr\hsize-\leftskip-\rightskip\relax
+ \copy\constructionheadbox
+ \hskip\rightconstructionskip
+ }
+ \nobreak
+ \advance\rightskip \constructionsheaddistance
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:0]
+ \directsetup{\??constructionrenderings:\v!right:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:]
+ \directsetup{\??constructionrenderings:\v!right:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!margin]%
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \llap {
+ \hpack to \constructionsheadwidth {
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ \hskip\constructionsheaddistance
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!margin]%
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushright
+ \rlap {
+ \hskip\constructionsheaddistance
+ \hpack to \constructionsheadwidth {
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!hanging]%
+ \let\\=\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushleft
+ \strc_constructions_set_hang\v!left
+ \noindent
+ \llap {
+ \tpack to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!hanging]%
+ \let\\=\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushright
+ \strc_constructions_set_hang\v!right
+ \noindent
+ \rlap {
+ \hpack to \dimexpr\hsize-\leftskip-\rightskip\relax {
+ \hss
+ \tpack to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!top]
+ \strc_sectioning_prevent_page_break\plusone
+ \let\\=\space
+ \noindent
+ \copy\constructionheadbox % why copy ?
+ \par
+ \nobreak
+ \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}%
+ \ifx\p_strc_constructions_inbetween\empty \else
+ \p_strc_constructions_inbetween
+ \par
+ \nobreak
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+% why copy? historic reason?
+
+\startsetups[\??constructionrenderings:\v!margin]
+ \let\\=\crlf
+ \noindent
+ \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!leftmargin]
+ \let\\=\crlf
+ \noindent
+ \inleft[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!rightmargin]
+ \let\\=\crlf
+ \noindent
+ \inright[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!innermargin]
+ \let\\=\crlf
+ \noindent
+ \ininner[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!outermargin]
+ \let\\=\crlf
+ \noindent
+ \inouter[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inmargin]
+ \directsetup{\??constructionrenderings:\v!margin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inleft]
+ \directsetup{\??constructionrenderings:\v!leftmargin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inright]
+ \directsetup{\??constructionrenderings:\v!rightmargin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried]
+ % already set?
+ \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace
+ \doifelsesetups{\??constructionrenderings:\v!serried:\p_strc_constructions_width} {
+ \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width}
+ } {
+ \directsetup{\??constructionrenderings:\v!serried:\v!wide}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!fit]
+ \let\\=\crlf
+ \noindent
+ \flushconstructionheadbox
+ \nobreak
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!broad]
+ \let\\=\crlf
+ \noindent
+ \flushconstructionheadbox
+ \ifconditional\c_strc_constructions_distance_none \else
+ \nobreak
+ \hskip\constructionsheaddistance \s!plus .5\constructionsheaddistance \s!minus .25\constructionsheaddistance\relax
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:]
+ \directsetup{\??constructionrenderings:\v!serried:\v!broad}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!wide]
+ \let\\=\crlf
+ \noindent
+ \hbox to \constructionsheadwidth {
+ \flushconstructionheadbox
+ \hss
+ }
+ \nobreak
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!hanging]
+ % tricky: leftskipadaption is somewhat unpredictable
+ \let\\=\crlf
+ \noindent
+ \advance\leftskip-\leftskipadaption\relax
+ \ifdim\leftskipadaption=\zeropoint
+ \leftskipadaption1.5\emwidth\relax % just some default
+ \ifnum\c_strc_constructions_nested_state=\plusone
+ \ifdim\leftskip>\zeropoint \relax
+ \leftskipadaption\leftskip
+ \fi
+ \fi
+ \fi
+ \ifnum\c_strc_constructions_nested_state>\zerocount % was \ifnum\c_strc_constructions_nested_state=\plusone
+ \advance\leftskip\leftskipadaption % but we're already further on
+ \fi
+ \hskip-\leftskipadaption\relax
+ \ifhbox\constructionheadbox \unhbox\else\box\fi\constructionheadbox
+ \ifconditional\c_strc_constructions_distance_none \else
+ % we used to have just a kern, but long lines look bad then
+ \scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi
+ \hskip \scratchdistance
+ \s!plus .25\scratchdistance
+ \s!minus.25\scratchdistance
+ \fi
+ \ifhmode
+ \ifx\p_strc_constructions_width\v!line
+ \hfill\break
+ \else
+ \allowbreak
+ \fi
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+%D \starttyping
+%D \setupfootnotation[location=command,headcommand=\llap]
+%D \stoptyping
+
+\startsetups[\??constructionrenderings:\v!command]
+ \noindent
+ \constructionparameter\c!headcommand{\flushconstructionheadbox}
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+% you can use \placeclosesymbol or \qed to place a symbol at the end of a
+% construction
+
+\installcorenamespace{constructionclosesymbol}
+
+\let\placeclosesymbol\donothing
+\let\qed \donothing
+
+\def\strc_constructions_close_symbol_reset % no need for global
+ {\global\expandafter\settrue\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \let\placeclosesymbol\strc_constructions_close_symbol_place
+ \let\qed \strc_constructions_close_symbol_place}
+
+\unexpanded\def\strc_constructions_close_symbol_place
+ {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}%
+ \ifx\p_strc_constructions_closesymbol\empty \else
+ \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected
+ \fi
+ \fi}
+
+\newif\ifnoconstructioncaption
+
+%D The storage macros:
+
+\let\currentconstructionlistentry\!!zerocount
+
+\unexpanded\def\strc_constructions_register
+ {\clf_doifelselisthasentry\numexpr\currentconstructionlistentry\relax
+ \strc_constructions_register_nop
+ \strc_constructions_register_yes}
+
+% \def\strc_constructions_register{\strc_constructions_register_yes}
+
+\def\strc_constructions_register_nop[#1][#2]% #1=optional user data #2=interfaced-settings
+ %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}}
+ {}
+
+\def\strc_constructions_discard
+ {\iftrialtypesetting
+ % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}%
+ \clf_discardfromlist\currentconstructionlistentry\relax
+ \fi}
+
+\let\currentconstructionlistnumber \!!zerocount
+\let\currentconstructionsynchronize\relax
+\let\currentconstructionattribute \attributeunsetvalue
+
+\def\strc_constructions_register_yes[#1][#2]% #1=optional user data #2=interfaced-settings
+ {\begingroup % similar to structure so we might generalize this
+ \setupcurrentconstruction[#2]% % xdef's will become edef's
+ \xdef\currentconstructionexpansion {\constructionparameter\c!expansion}%
+ \xdef\currentconstructionxmlsetup {\constructionparameter\c!xmlsetup}%
+ \xdef\currentconstructioncatcodes {\constructionparameter\s!catcodes}%
+ \xdef\currentconstructionlabel {\constructionparameter\c!label}%
+ \xdef\currentconstructionreference {\constructionparameter\c!reference}%
+ \xdef\currentconstructionreferenceprefix{\constructionparameter\c!referenceprefix}%
+ %xdef\currentconstructionshownumber {\constructionparameter\c!number}%
+ \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}%
+ %
+ \ifx\currentconstructionexpansion\empty
+ \global\let\currentconstructionexpansion\v!no
+ \fi
+ %
+ \ifx\currentconstructionexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentconstructiontitle {\constructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\constructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\constructionparameter\c!list}%
+ \xmlstopraw
+ \ifx\currentconstructionlist\empty
+ \global\let\currentconstructionlist\currentconstructiontitle
+ \fi
+ \global\let\currentconstructioncoding\s!xml
+ \else
+ \ifx\currentconstructionexpansion\v!yes
+ \xdef\currentconstructiontitle {\constructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\constructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\constructionparameter\c!list}%
+ \else
+ \xdef\currentconstructiontitle {\detokenizedconstructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\detokenizedconstructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\detokenizedconstructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\detokenizedconstructionparameter\c!list}%
+ \iflocation \ifx\currentconstructionbookmark\empty
+ \begingroup
+ \simplifycommands
+ \xdef\currentconstructionbookmark{\detokenize\expandafter{\normalexpanded{\constructionparameter\c!title}}}%
+ \endgroup
+ \fi \fi
+ \fi
+ \ifx\currentconstructionlist\empty
+ \globallet\currentconstructionlist\currentconstructiontitle
+ \fi
+ \globallet\currentconstructioncoding\s!tex
+ \fi
+ %
+ \ifx\currentconstructiontitle\v!none % will become obsolete
+ \global\noconstructioncaptiontrue\global\noconstructionnumbertrue
+ \fi
+ %
+ \ifnoconstructioncaption % then why analyze anyway?
+ \endgroup
+ \let\currentconstructionlistnumber \relax
+ \let\currentconstructionsynchronize\relax
+ \let\currentconstructionattribute \relax
+ \else
+ \setnextinternalreferences{construction}\currentconstructionmain % plural
+ \relax
+ \scratchcounter\clf_addtolist
+ metadata {
+ kind {construction}
+ name {\currentconstructionmain}
+ % level structures.sections.currentlevel()
+ catcodes \catcodetable
+ }
+ references {
+ internal \nextinternalreference
+ order \nextinternalorderreference
+ reference {\currentconstructionreference}
+ prefix {\referenceprefix}
+ % block {\currentsectionblock}
+ % section structures.sections.currentid(),
+ }
+ titledata {
+ label {\detokenize\expandafter{\currentconstructionlabel}}
+ title {\detokenize\expandafter{\currentconstructiontitle}}
+ \ifx\currentconstructionbookmark\currentconstructiontitle \else
+ bookmark {\detokenize\expandafter{\currentconstructionbookmark}}
+ \fi
+ \ifx\currentconstructionlist\currentconstructiontitle \else
+ list {\detokenize\expandafter{\currentconstructionlist}}
+ \fi
+ }
+ \ifconditional\c_strc_constructions_number_state
+ prefixdata {
+ prefix {\constructionparameter\c!prefix}
+ separatorset {\constructionparameter\c!prefixseparatorset}
+ conversion {\constructionparameter\c!prefixconversion}
+ conversionset {\constructionparameter\c!prefixconversionset}
+ set {\constructionparameter\c!prefixset}
+ segments {\constructionparameter\c!prefixsegments}
+ connector {\constructionparameter\c!prefixconnector}
+ }
+ numberdata {
+ numbers {\currentconstructionnumber}
+ separatorset {\constructionparameter\c!numberseparatorset}
+ conversion {\constructionparameter\c!numberconversion}
+ conversionset {\constructionparameter\c!numberconversionset}
+ starter {\constructionparameter\c!numberstarter}
+ stopper {\constructionparameter\c!numberstopper}
+ segments {\constructionparameter\c!numbersegments}
+ }
+ \or
+ % symbol
+ \fi
+ userdata {\detokenize{#1}}
+ \relax
+ % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}%
+ \clf_setinternalreference
+ prefix {\referenceprefix}%
+ reference {\currentconstructionreference}%
+ internal \nextinternalreference
+ view {\interactionparameter\c!focus}%
+ \relax
+ \normalexpanded{%
+ \endgroup
+ \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}%
+ \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}%
+ \edef\noexpand\currentconstructionsynchronize{\ctxlatecommand{enhancelist(\the\scratchcounter)}}%
+ }%
+ \fi}
+
+% This is not so nice, some day I'll just store the number with the entry
+% and deal with all at the Lua end, but first we need to be able to set
+% macros.
+
+\def\reinstateconstructionnumberentry#1% was xdef
+ {\edef\currentconstructionattribute {\clf_getinternallistreference#1}%
+ \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#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)}}}
+
+\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}}
+
+% Helpers:
+
+\def\currentconstructionnumber{\constructionparameter\s!counter}
+
+\unexpanded\def\strc_constructions_next_indeed #get#tag#level{\strc_counters_increment_sub{#get{#tag}\s!counter}{#level}}
+\unexpanded\def\strc_constructions_reset_indeed#get#tag#level{\strc_counters_reset_sub {#get{#tag}\s!counter}{#level}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv
new file mode 100644
index 00000000000..962c46b485b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv
@@ -0,0 +1,250 @@
+%D [ file=strc-def,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Definitions}
+
+%registerctxluafile{strc-def}{1.001}
+
+\unprotect
+
+% \setupsectionblock[appendix][sectionconversionset=appendix]
+% \setuphead[chapter][sectionconversionset=\sectionblockparameter\c!sectionconversionset] % \sectionblockparameter]
+
+% \defineresetset[default][0,1,1,0][1] % this will not reset parts and subsections
+% \setuphead[part][sectionresetset=default]
+% \starttext
+% \placelist[chapter,section,subsection][criterium=all,width=3cm]
+% \part{first} \chapter{alpha} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{beta}
+% \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta}
+% \stoptext
+
+\defineseparatorset [\s!default] [] [.]
+\defineconversionset [\s!default] [] [numbers]
+\defineresetset [\s!default] [] [1] % each level
+\defineprefixset [\s!default] [section-1,section-2,section-3] []
+
+\defineconversionset [\v!number] [] [numbers]
+\defineconversionset [\v!pagenumber] [] [numbers]
+
+\defineprefixset [\v!all] [section-1,section-2,section-3,section-4,section-5,section-6,section-7,section-8] []
+\defineprefixset [\v!none] [] []
+
+\defineprefixset [\v!part] [section-1] []
+\defineprefixset [\v!chapter] [section-2] []
+
+\defineseparatorset [\v!appendix:\s!default] [] [.]
+\defineconversionset [\v!appendix:\s!default] [Romannumerals,Characters] [numbers]
+\defineresetset [\v!appendix:\s!default] [] [1] % why was this 0
+
+\setupuserpagenumber
+ [\c!numberconversionset=\v!pagenumber]
+
+\setupcounters
+ [\c!numberconversionset=\v!number]
+
+% \startsetups defaults:frontpart:pagenumbers:roman
+% \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
+% \setupuserpagenumber[\c!way=\v!by\v!block]
+% \stopsetups
+
+% \definesectionblock
+
+\definesectionblock [\v!frontpart] [\v!frontmatter] [\c!number=\v!no]
+\definesectionblock [\v!bodypart] [\v!bodymatter] [\c!number=\v!yes]
+\definesectionblock [\v!appendix] [\v!appendices] [\c!number=\v!yes]
+\definesectionblock [\v!backpart] [\v!backmatter] [\c!number=\v!no]
+
+\setsectionblock [\v!bodypart] % default
+
+% \appendtoks
+% \setsectionblock[\v!bodypart]% default
+% \to \everyjob
+%
+% \appendtoks
+% \clf_setinitialsectionblock{\v!bodypart}%
+% \to \everystarttext
+
+\appendtoks
+ \clf_setinitialsectionblock{\v!bodypart}%
+\to \everyjob
+
+% \definesection (could become \definehead with one parameter)
+
+\definesection[\s!section-1] % part
+\definesection[\s!section-2] % chapter
+\definesection[\s!section-3] % section
+\definesection[\s!section-4] % subsection
+\definesection[\s!section-5] % subsubsection
+\definesection[\s!section-6] % subsubsubsection
+\definesection[\s!section-7] % subsubsubsubsection
+
+% \definehead
+
+\definehead
+ [\v!part]
+ [\c!section=\s!section-1]
+
+\definehead
+ [\v!chapter]
+ [\c!section=\s!section-2]
+
+\definehead
+ [\v!section]
+ [\c!section=\s!section-3]
+
+\definehead
+ [\v!subsection]
+ [\c!section=\s!section-4,
+ \c!default=\v!section]
+
+\definehead
+ [\v!subsubsection]
+ [\c!section=\s!section-5,
+ \c!default=\v!subsection]
+
+\definehead
+ [\v!subsubsubsection]
+ [\c!section=\s!section-6,
+ \c!default=\v!subsubsection]
+
+\definehead
+ [\v!subsubsubsubsection]
+ [\c!section=\s!section-7,
+ \c!default=\v!subsubsubsection]
+
+\definehead
+ [\v!title]
+ [\c!coupling=\v!chapter,
+ \c!default=\v!chapter,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subject]
+ [\c!coupling=\v!section,
+ \c!default=\v!section,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubject]
+ [\c!coupling=\v!subsection,
+ \c!default=\v!subsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubject]
+ [\c!coupling=\v!subsubsection,
+ \c!default=\v!subsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubject]
+ [\c!coupling=\v!subsubsubsection,
+ \c!default=\v!subsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsection,
+ \c!default=\v!subsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\setuphead
+ [\v!part]
+ [\c!placehead=\v!no]
+
+\setuphead
+ [\v!chapter]
+ [\v!appendix\c!label=\v!appendix,
+ \v!bodypart\c!label=\v!chapter] % bijlageconversie=\Character
+
+\setuphead
+ [\v!section]
+ [\v!appendix\c!label=\v!section,
+ \v!bodypart\c!label=\v!section] % bijlageconversie=\Character
+
+\setuphead
+ [\v!subsection]
+ [\v!appendix\c!label=\v!subsection,
+ \v!bodypart\c!label=\v!subsection] % bijlageconversie=\Character
+
+\setuphead
+ [\v!subsubsection]
+ [\v!appendix\c!label=\v!subsubsection,
+ \v!bodypart\c!label=\v!subsubsection] % bijlageconversie=\Character
+
+% \setuphead
+
+\setuphead
+ [\v!part,\v!chapter]
+ [%\c!align=,
+ %\c!indentnext=\v!no,
+ \c!continue=\v!no,
+ \c!page=\v!right,
+ \c!marking=\v!page,
+ \c!header=,
+ \c!style=\tfc,
+ \c!distance=.75\emwidth,
+ \c!before={\blank[2*\v!big]},
+ \c!after={\blank[2*\v!big]}]
+
+\setuphead
+ [\v!section]
+ [%\c!align=,
+ %\c!indentnext=\v!no,
+ \c!style=\tfa,
+ \c!distance=.75\emwidth,
+ \c!before={\blank[2*\v!big]},
+ \c!after=\blank]
+
+\setuphead % nieuw
+ [\v!subsection]
+ [\c!page=]
+
+% brrr
+
+% \definecounter[\v!page][\c!start=1] % todo: setup
+
+% lists
+
+\definecombinedlist
+ [\v!content]
+ [\v!part,
+ \v!chapter,
+ \v!section,
+ \v!subsection,
+ \v!subsubsection,
+ \v!subsubsubsection,
+ \v!subsubsubsubsection]
+ [\c!level=\v!subsubsubsubsection,
+ \c!criterium=\v!local]
+
+\setuplist
+ [\v!part]
+ [\c!before={\blank[\v!preference,\v!big]}, % sort of mkii compatible, watch columns
+ \c!after=\blank,
+ \c!label=\v!yes,
+ \c!distance=\emwidth]
+
+\setuplist
+ [\v!chapter]
+ [\c!before={\blank[\v!preference,\v!big]}, % sort of mkii compatible, watch columns
+ \c!after=]
+
+\setuplist [\v!part] [\c!width=0\emwidth]
+\setuplist [\v!chapter] [\c!width=2\emwidth]
+\setuplist [\v!section] [\c!width=3\emwidth]
+\setuplist [\v!subsection] [\c!width=4\emwidth]
+\setuplist [\v!subsubsection] [\c!width=5\emwidth]
+\setuplist [\v!subsubsubsection] [\c!width=6\emwidth]
+\setuplist [\v!subsubsubsubsection] [\c!width=7\emwidth]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-des.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-des.mkvi
new file mode 100644
index 00000000000..4376d9cdcd5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-des.mkvi
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Descriptions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Descriptions}
+
+\unprotect
+
+\installcorenamespace{description}
+
+\installcommandhandler \??description {description} \??description
+
+\let\setupdescriptions\setupdescription
+
+% \setupdescriptions % check with old
+% [\c!alternative=\descriptionparameter\c!location,
+% \c!location=\v!left]
+
+\setupdescriptions % check with old
+ [\c!alternative=\v!left,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ \c!title=\v!yes,
+ %\c!text=,
+ ]
+
+\appendtoks
+ \ifx\currentdescriptionparent\empty
+ \defineconstruction[\currentdescription][\currentdescriptionparent][\s!handler=\v!description,\c!level=1]%
+ \else
+ \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]%
+ \fi
+ \setuevalue {\currentdescription}{\strc_descriptions_command{\currentdescription}}%
+ \setuevalue{\e!start\currentdescription}{\strc_descriptions_start {\currentdescription}}%
+ \setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}%
+\to \everydefinedescription
+
+\let\p_strc_constructions_title \empty
+
+\unexpanded\setvalue{\??constructioninitializer\v!description}%
+ {\let\currentdescription \currentconstruction
+ \let\constructionparameter \descriptionparameter
+ \let\constructionnamespace \??description
+ \let\detokenizedconstructionparameter\detokenizeddescriptionparameter
+ \let\letconstructionparameter \letdescriptionparameter
+ \let\useconstructionstyleandcolor \usedescriptionstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentdescription
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+% We keep the command variant around but rather would move to the
+% start-stop one. Also, passing the title as argument has some
+% history so we need to keep that as well.
+
+% \startdescription [reference] text \stopdescription
+% \startdescription [reference]{title} text \stopdescription
+% \startdescription [title=,title=,reference=] text \stopdescription
+
+% A bit over the top, the optional title but mkii has it too.
+
+\unexpanded\def\strc_descriptions_start#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \doifelsenextoptionalcs\strc_descriptions_start_yes\strc_descriptions_start_nop}
+
+\unexpanded\def\strc_descriptions_start_yes[#1]%
+ {\doifelseassignment{#1}\strc_descriptions_start_yes_assignment\strc_descriptions_start_yes_reference[#1]}
+
+\unexpanded\def\strc_descriptions_start_yes_assignment[#1]% todo userdata
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_yes_reference
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_start_yes_titled
+ \else
+ \expandafter\strc_descriptions_start_yes_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_start_yes_titled[#1]%
+ {\doifelsenextbgroup
+ {\strc_descriptions_start_yes_titled_indeed[#1]}%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_descriptions_start_yes_normal[#1]}}
+
+\unexpanded\def\strc_descriptions_start_yes_titled_indeed[#1]#2% todo userdata
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_yes_normal[#1]% todo userdata
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_nop
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_start_nop_titled
+ \else
+ \expandafter\strc_descriptions_start_nop_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_start_nop_titled
+ {\doifelsenextbgroup
+ {\strc_descriptions_start_nop_titled_indeed}%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_descriptions_start_nop_normal}}%
+
+\unexpanded\def\strc_descriptions_start_nop_titled_indeed#1%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_nop_normal
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname}
+
+% \description [reference] text \par
+% \description [reference] {title} text \par
+
+\unexpanded\def\strc_descriptions_command#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \doifelsenextoptionalcs\strc_descriptions_yes\strc_descriptions_nop}
+
+\unexpanded\def\strc_descriptions_yes
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_yes_titled
+ \else
+ \expandafter\strc_descriptions_yes_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_yes_titled[#1]#2%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_yes_titled[#1]%
+ {\doifelsenextbgroup
+ {\strc_descriptions_yes_titled_indeed[#1]}%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_descriptions_yes_normal[#1]}}
+
+\unexpanded\def\strc_descriptions_yes_titled_indeed[#1]#2%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_yes_normal[#1]%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_nop
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_nop_titled
+ \else
+ \expandafter\strc_descriptions_nop_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_nop_titled
+ {\doifelsenextbgroup
+ {\strc_descriptions_nop_titled_indeed}%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_descriptions_nop_normal}}
+
+\unexpanded\def\strc_descriptions_nop_titled_indeed#1%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_nop_normal
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+%D Handlers:
+
+\expandafter\let\csname\??constructionmainhandler \v!description\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!description\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname
+\expandafter\let\csname\??constructiontexthandler \v!description\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname
+
+\unexpanded\setvalue{\??constructioncommandhandler\v!description}%
+ {\dowithpar
+ {\csname\??constructionstarthandler\v!construction\endcsname}%
+ {\csname\??constructionstophandler \v!construction\endcsname\endgroup}}
+
+\unexpanded\setvalue{\??constructionstarthandler\v!description}%
+ {\BeforePar{\csname\??constructionstarthandler\v!construction\endcsname}%
+ \GotoPar}
+
+\unexpanded\setvalue{\??constructionstophandler\v!description}%
+ {\csname\??constructionstophandler\v!construction\endcsname
+ \endgroup}
+
+%D For historic reasons we have (from now on undocumented):
+
+\definedescription
+ [tab]
+ [\c!alternative=\v!left,
+ \c!headstyle=\v!normal,
+ \c!headcolor=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!width=\v!broad,
+ \c!sample=\kern4\emwidth, % was \hskip but that no longer is okay
+ \c!before=,
+ \c!after=]
+
+\unexpanded\def\setuptab
+ {\setupdescription[tab]}
+
+%D Maybe we should remove this definition.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua
new file mode 100644
index 00000000000..885e2de0ba3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua
@@ -0,0 +1,1135 @@
+if not modules then modules = { } end modules ['strc-doc'] = {
+ version = 1.001,
+ comment = "companion to strc-doc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: associate counter with head
+-- we need to better split the lua/tex end
+-- we need to freeze and document this module
+
+-- keep this as is:
+--
+-- in section titles by default a zero aborts, so there we need: sectionset=bagger with \definestructureprefixset [bagger] [section-2,section-4] []
+-- in lists however zero's are ignored, so there numbersegments=2:4 gives result
+
+local next, type, tonumber, select = next, type, tonumber, select
+local format, gsub, find, gmatch, match = string.format, string.gsub, string.find, string.gmatch, string.match
+local concat, fastcopy, insert, remove = table.concat, table.fastcopy, table.insert, table.remove
+local max, min = math.max, math.min
+local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable
+local setmetatableindex = table.setmetatableindex
+local lpegmatch, P, C = lpeg.match, lpeg.P, lpeg.C
+
+local catcodenumbers = catcodes.numbers
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local variables = interfaces.variables
+
+local implement = interfaces.implement
+
+local v_last = variables.last
+local v_first = variables.first
+local v_previous = variables.previous
+local v_next = variables.next
+local v_auto = variables.auto
+local v_strict = variables.strict
+local v_all = variables.all
+local v_positive = variables.positive
+local v_by = variables.by
+
+local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end)
+local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end)
+
+local report_structure = logs.reporter("structure","sectioning")
+
+local context = context
+local commands = commands
+
+local structures = structures
+local helpers = structures.helpers
+local documents = structures.documents
+local sections = structures.sections
+local lists = structures.lists
+local counters = structures.counters
+local sets = structures.sets
+local tags = structures.tags
+
+local processors = typesetters.processors
+local applyprocessor = processors.apply
+local startapplyprocessor = processors.startapply
+local stopapplyprocessor = processors.stopapply
+local strippedprocessor = processors.stripped
+
+local convertnumber = converters.convert
+
+local a_internal = attributes.private('internal')
+
+local ctx_convertnumber = context.convertnumber
+local ctx_sprint = context.sprint
+local ctx_finalizeauto = context.finalizeautostructurelevel
+
+-- -- -- document -- -- --
+
+local data -- the current state
+
+function documents.initialize()
+ data = allocate { -- whole data is marked
+ numbers = { },
+ forced = { },
+ ownnumbers = { },
+ status = { },
+ checkers = { },
+ depth = 0,
+ blocks = { },
+ block = "",
+ }
+ documents.data = data
+end
+
+function documents.reset()
+ data.numbers = { }
+ data.forced = { }
+ data.ownnumbers = { }
+ data.status = { }
+ -- data.checkers = { }
+ data.depth = 0
+end
+
+documents.initialize()
+
+-- -- -- components -- -- --
+
+function documents.preset(numbers)
+ local nofnumbers = #numbers
+ local ownnumbers = { }
+ data.numbers = numbers
+ data.ownnumbers = ownnumbers
+ data.depth = nofnumbers
+ for i=1,nofnumbers do
+ ownnumbers[i] = ""
+ end
+ sections.setnumber(nofnumbers,"-1")
+end
+
+-- -- -- sections -- -- --
+
+-- This is just a quick way to have access to prefixes and the numbers (section entry in a ref)
+-- is not the list entry. An alternative is to use the list index of the last numbered section. In
+-- that case we should check a buse of the current structure.
+
+local collected = allocate()
+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)
+
+sections.registered = sections.registered or allocate()
+local registered = sections.registered
+
+storage.register("structures/sections/registered", registered, "structures.sections.registered")
+
+local function update(name,level,section)
+ for k, v in next, registered do
+ if k ~= name and v.coupling == name then
+ report_structure("updating section level %a to level of %a",k,name)
+ context.doredefinehead(k,name)
+ update(k,level,section)
+ end
+ end
+end
+
+function sections.register(name,specification)
+ registered[name] = specification
+ local level = specification.level
+ local section = specification.section
+ update(name,level,section)
+end
+
+function sections.currentid()
+ return #tobesaved
+end
+
+local lastsaved = 0
+
+function sections.save(sectiondata)
+-- local sectionnumber = helpers.simplify(section.sectiondata) -- maybe done earlier
+ local numberdata = sectiondata.numberdata
+ local ntobesaved = #tobesaved
+ if not numberdata or sectiondata.metadata.nolist then
+ -- stay
+ else
+ ntobesaved = ntobesaved + 1
+ tobesaved[ntobesaved] = numberdata
+ if not collected[ntobesaved] then
+ collected[ntobesaved] = numberdata
+ end
+ end
+ lastsaved = ntobesaved
+ return ntobesaved
+end
+
+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)
+
+--
+
+sections.verbose = true
+
+local sectionblockdata = sections.sectionblockdata or { }
+sections.sectionblockdata = sectionblockdata
+
+local levelmap = sections.levelmap or { }
+sections.levelmap = levelmap
+levelmap.block = -1
+
+storage.register("structures/sections/levelmap", sections.levelmap, "structures.sections.levelmap")
+
+function sections.setlevel(name,level) -- level can be number or parent (=string)
+ local l = tonumber(level)
+ if not l then
+ l = levelmap[level]
+ end
+ if l and l > 0 then
+ levelmap[name] = l
+ else
+ -- error
+ end
+end
+
+function sections.getlevel(name)
+ return levelmap[name] or 0
+end
+
+table.setmetatableindex(sectionblockdata,"table")
+
+function sections.setblock(name,settings)
+ local block = name or data.block or "unknown" -- can be used to set the default
+ data.block = block
+ sectionblockdata[block] = settings
+ return block
+end
+
+local jobvariables = job.variables
+local pushed_order = { }
+local pushed_done = { }
+
+jobvariables.tobesaved.sectionblockorder = pushed_order
+
+-- function sections.order()
+-- return jobvariables.collected.sectionblockorder or pushed_order -- so we have a first pass list too
+-- end
+
+function sections.setinitialblock(default)
+ local order = jobvariables.collected.sectionblockorder or pushed_order
+ local name = #order > 0 and order[1] or default or "bodypart"
+ context.setsectionblock { name }
+ -- interfaces.setmacro("currentsectionblock",name)
+ -- sections.setblock(name,{})
+end
+
+function sections.pushblock(name,settings)
+ counters.check(0) -- we assume sane usage of \page between blocks
+ local block = name or data.block
+ insert(data.blocks,block)
+ data.block = block
+ sectionblockdata[block] = settings
+ documents.reset()
+ if not pushed_done[name] then
+ pushed_done[name] = true
+ local nofpushed = #pushed_order + 1
+ pushed_order[nofpushed] = name
+ end
+ return block
+end
+
+function sections.popblock()
+ local block = remove(data.blocks) or data.block
+ data.block = block
+ documents.reset()
+ return block
+end
+
+local function getcurrentblock()
+ return data.block or data.blocks[#data.blocks] or "unknown"
+end
+
+sections.currentblock = getcurrentblock
+
+function sections.currentlevel()
+ return data.depth
+end
+
+function sections.getcurrentlevel()
+ context(data.depth)
+end
+
+local saveset = { } -- experiment, see sections/tricky-001.tex
+
+function sections.setentry(given)
+ -- old number
+ local numbers = data.numbers
+ --
+ local metadata = given.metadata
+ local numberdata = given.numberdata
+ local references = given.references
+ local directives = given.directives
+ local userdata = given.userdata
+
+ if not metadata then
+ metadata = { }
+ given.metadata = metadata
+ end
+ if not numberdata then
+ numberdata = { }
+ given.numberdata = numberdata
+ end
+ if not references then
+ references = { }
+ given.references = references
+ end
+
+ local ownnumbers = data.ownnumbers
+ local forced = data.forced
+ local status = data.status
+ local olddepth = data.depth
+ local givenname = metadata.name
+ local mappedlevel = levelmap[givenname]
+ local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-*
+ local resetset = directives and directives.resetset or ""
+ -- local resetter = sets.getall("structure:resets",data.block,resetset)
+ -- a trick to permit userdata to overload title, ownnumber and reference
+ -- normally these are passed as argument but nowadays we provide several
+ -- interfaces (we need this because we want to be compatible)
+ if trace_detail then
+ report_structure("name %a, mapped level %a, old depth %a, new depth %a, reset set %a",
+ givenname,mappedlevel,olddepth,newdepth,resetset)
+ end
+ if userdata then
+ -- kind of obsolete as we can pass them directly anyway ... NEEDS CHECKING !
+ if userdata.reference and userdata.reference ~= "" then given.metadata.reference = userdata.reference ; userdata.reference = nil end
+ if userdata.ownnumber and userdata.ownnumber ~= "" then given.numberdata.ownnumber = userdata.ownnumber ; userdata.ownnumber = nil end
+ if userdata.title and userdata.title ~= "" then given.titledata.title = userdata.title ; userdata.title = nil end
+ if userdata.bookmark and userdata.bookmark ~= "" then given.titledata.bookmark = userdata.bookmark ; userdata.bookmark = nil end
+ if userdata.label and userdata.label ~= "" then given.titledata.label = userdata.label ; userdata.label = nil end
+ end
+ -- so far for the trick
+ if saveset then
+ saveset[newdepth] = (resetset ~= "" and resetset) or saveset[newdepth] or ""
+ end
+ if newdepth > olddepth then
+ for i=olddepth+1,newdepth do
+ local s = tonumber(sets.get("structure:resets",data.block,saveset and saveset[i] or resetset,i))
+ if trace_detail then
+ report_structure("new depth %s, old depth %s, reset set %a, reset value %a, current %a",olddepth,newdepth,resetset,s,numbers[i])
+ end
+ if not s or s == 0 then
+ numbers[i] = numbers[i] or 0
+ ownnumbers[i] = ownnumbers[i] or ""
+ else
+ numbers[i] = s - 1
+ ownnumbers[i] = ""
+ end
+ status[i] = { }
+ end
+ elseif newdepth < olddepth then
+ for i=olddepth,newdepth+1,-1 do
+ local s = tonumber(sets.get("structure:resets",data.block,saveset and saveset[i] or resetset,i))
+ if trace_detail then
+ report_structure("new depth %s, old depth %s, reset set %a, reset value %a, current %a",olddepth,newdepth,resetset,s,numbers[i])
+ end
+ if not s or s == 0 then
+ numbers[i] = numbers[i] or 0
+ ownnumbers[i] = ownnumbers[i] or ""
+ else
+ numbers[i] = s - 1
+ ownnumbers[i] = ""
+ end
+ status[i] = nil
+ end
+ end
+ counters.check(newdepth)
+ ownnumbers[newdepth] = numberdata.ownnumber or ""
+ numberdata.ownnumber = nil
+ data.depth = newdepth
+ -- new number
+ olddepth = newdepth
+ if metadata.increment then
+ local oldn, newn = numbers[newdepth] or 0, 0
+ local fd = forced[newdepth]
+ if fd then
+ if fd[1] == "add" then
+ newn = oldn + fd[2] + 1
+ else
+ newn = fd[2] + 1
+ end
+ if newn < 0 then
+ newn = 1 -- maybe zero is nicer
+ end
+ forced[newdepth] = nil
+ if trace_detail then
+ report_structure("old depth %a, new depth %a, old n %a, new n %a, forced %t",olddepth,newdepth,oldn,newn,fd)
+ end
+ else
+ newn = oldn + 1
+ if trace_detail then
+ report_structure("old depth %a, new depth %a, old n %a, new n %a, increment",olddepth,newdepth,oldn,newn)
+ end
+ end
+ numbers[newdepth] = newn
+ end
+ status[newdepth] = given or { }
+ for k, v in next, data.checkers do
+ if v[1] == newdepth and v[2] then
+ v[2](k)
+ end
+ end
+ local n = { }
+ for i=1,newdepth do
+ n[i] = numbers[i]
+ end
+ numberdata.numbers = n
+ if not numberdata.block then
+ numberdata.block = getcurrentblock() -- also in references
+ end
+ if #ownnumbers > 0 then
+ numberdata.ownnumbers = fastcopy(ownnumbers)
+ end
+ if trace_detail then
+ report_structure("name %a, numbers % a, own numbers % a",givenname,numberdata.numbers,numberdata.ownnumbers)
+ end
+ if not references.block then
+ references.block = getcurrentblock() -- also in numberdata
+ end
+ local tag = references.tag or tags.getid(metadata.kind,metadata.name)
+ if tag and tag ~= "" and tag ~= "?" then
+ references.tag = tag
+ end
+ local setcomponent = structures.references.setcomponent
+ if setcomponent then
+ setcomponent(given) -- might move to the tex end
+ end
+ references.section = sections.save(given)
+ -- given.numberdata = nil
+end
+
+function sections.reportstructure()
+ if sections.verbose then
+ local numbers, ownnumbers, status, depth = data.numbers, data.ownnumbers, data.status, data.depth
+ local d = status[depth]
+ local o = concat(ownnumbers,".",1,depth)
+ local n = (numbers and concat(numbers,".",1,min(depth,#numbers))) or 0
+ local l = d.titledata.title or ""
+ local t = (l ~= "" and l) or d.titledata.title or "[no title]"
+ local m = d.metadata.name
+ if o and not find(o,"^%.*$") then
+ report_structure("%s @ level %i : (%s) %s -> %s",m,depth,n,o,t)
+ elseif d.directives and d.directives.hidenumber then
+ report_structure("%s @ level %i : (%s) -> %s",m,depth,n,t)
+ else
+ report_structure("%s @ level %i : %s -> %s",m,depth,n,t)
+ end
+ end
+end
+
+function sections.setnumber(depth,n)
+ local forced, depth, new = data.forced, depth or data.depth, tonumber(n)
+ if type(n) == "string" then
+ if find(n,"^[%+%-]") then
+ forced[depth] = { "add", new }
+ else
+ forced[depth] = { "set", new }
+ end
+ else
+ forced[depth] = { "set", new }
+ end
+end
+
+function sections.numberatdepth(depth)
+ return data.numbers[tonumber(depth) or sections.getlevel(depth) or 0] or 0
+end
+
+function sections.numbers()
+ return data.numbers
+end
+
+function sections.matchingtilldepth(depth,numbers,parentnumbers)
+ local dn = parentnumbers or data.numbers
+ local ok = false
+ for i=1,depth do
+ if dn[i] == numbers[i] then
+ ok = true
+ else
+ return false
+ end
+ end
+ return ok
+end
+
+function sections.getnumber(depth) -- redefined later ...
+ context(data.numbers[depth] or 0)
+end
+
+function sections.set(key,value)
+ data.status[data.depth][key] = value -- may be nil for a reset
+end
+
+function sections.cct()
+ local metadata = data.status[data.depth].metadata
+ context(metadata and metadata.catcodes or ctxcatcodes)
+end
+
+-- this one will become: return catcode, d (etc)
+
+function sections.structuredata(depth,key,default,honorcatcodetable) -- todo: spec table and then also depth
+ if depth then
+ depth = levelmap[depth] or tonumber(depth)
+ end
+ if not depth or depth == 0 then
+ depth = data.depth
+ end
+ local data = data.status[depth]
+ local d
+ if data then
+ if find(key,".",1,true) then
+ d = accesstable(key,data)
+ else
+ d = data.titledata
+ d = d and d[key]
+ end
+ end
+ if d and type(d) ~= "table" then
+ if honorcatcodetable == true or honorcatcodetable == v_auto then
+ local metadata = data.metadata
+ local catcodes = metadata and metadata.catcodes
+ if catcodes then
+ ctx_sprint(catcodes,d)
+ else
+ context(d)
+ end
+ elseif not honorcatcodetable or honorcatcodetable == "" then
+ context(d)
+ else
+ local catcodes = catcodenumbers[honorcatcodetable]
+ if catcodes then
+ ctx_sprint(catcodes,d)
+ else
+ context(d)
+ end
+ end
+ elseif default then
+ context(default)
+ end
+end
+
+function sections.userdata(depth,key,default)
+ if depth then
+ depth = levelmap[depth] or tonumber(depth)
+ end
+ if not depth or depth == 0 then
+ depth = data.depth
+ end
+ if depth > 0 then
+ local userdata = data.status[depth]
+ userdata = userdata and userdata.userdata
+ userdata = (userdata and userdata[key]) or default
+ if userdata then
+ context(userdata)
+ end
+ end
+end
+
+function sections.setchecker(name,level,command) -- hm, checkers are not saved
+ data.checkers[name] = (name and command and level >= 0 and { level, command }) or nil
+end
+
+function sections.current()
+ return data.status[data.depth]
+end
+
+local function depthnumber(n)
+ local depth = data.depth
+ if not n or n == 0 then
+ n = depth
+ elseif n < 0 then
+ n = depth + n
+ end
+ return data.numbers[n] or 0
+end
+
+sections.depthnumber = depthnumber
+
+function sections.autodepth(numbers)
+ for i=#numbers,1,-1 do
+ if numbers[i] ~= 0 then
+ return i
+ end
+ end
+ return 0
+end
+
+--
+
+function structures.currentsectionnumber() -- brr, namespace wrong
+ local sc = sections.current()
+ return sc and sc.numberdata
+end
+
+-- \dorecurse{3} {
+-- \chapter{Blabla} \subsection{bla 1 1} \subsection{bla 1 2}
+-- \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2}
+-- }
+
+-- sign=all => also zero and negative
+-- sign=positive => also zero
+-- sign=hang => llap sign
+
+-- this can be a local function
+
+local function process(index,numbers,ownnumbers,criterium,separatorset,conversion,conversionset,entry,result,preceding,done,language)
+ -- todo: too much (100 steps)
+ local number = numbers and (numbers[index] or 0)
+ local ownnumber = ownnumbers and ownnumbers[index] or ""
+ if number > criterium or (ownnumber ~= "") then
+ local block = (entry.block ~= "" and entry.block) or sections.currentblock() -- added
+ if preceding then
+ local separator = sets.get("structure:separators",block,separatorset,preceding,".")
+ if separator then
+ if result then
+ result[#result+1] = strippedprocessor(separator)
+ else
+ applyprocessor(separator)
+ end
+ end
+ preceding = false
+ end
+ if result then
+ if ownnumber ~= "" then
+ result[#result+1] = ownnumber
+ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups) .. inherited!
+ result[#result+1] = convertnumber(conversion,number,language)
+ else
+ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers")
+ result[#result+1] = convertnumber(theconversion,number,language)
+ end
+ else
+ if ownnumber ~= "" then
+ applyprocessor(ownnumber)
+ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups)
+ ctx_convertnumber(conversion,number)
+ else
+ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers")
+ local data = startapplyprocessor(theconversion)
+ ctx_convertnumber(data or "numbers",number)
+ stopapplyprocessor()
+ end
+ end
+ return index, true
+ else
+ return preceding or false, done
+ end
+end
+
+function sections.typesetnumber(entry,kind,...) -- kind='section','number','prefix'
+ if entry and entry.hidenumber ~= true then -- can be nil
+ local separatorset = ""
+ local conversionset = ""
+ local conversion = ""
+ local groupsuffix = ""
+ local stopper = ""
+ local starter = ""
+ local connector = ""
+ local set = ""
+ local segments = ""
+ local criterium = ""
+ local language = ""
+ for d=1,select("#",...) do
+ local data = select(d,...) -- can be multiple parametersets
+ if data then
+ if separatorset == "" then separatorset = data.separatorset or "" end
+ if conversionset == "" then conversionset = data.conversionset or "" end
+ if conversion == "" then conversion = data.conversion or "" end
+ if groupsuffix == "" then groupsuffix = data.groupsuffix or "" end
+ if stopper == "" then stopper = data.stopper or "" end
+ if starter == "" then starter = data.starter or "" end
+ if connector == "" then connector = data.connector or "" end
+ if set == "" then set = data.set or "" end
+ if segments == "" then segments = data.segments or "" end
+ if criterium == "" then criterium = data.criterium or "" end
+ if language == "" then language = data.language or "" end
+ end
+ end
+ if separatorset == "" then separatorset = "default" end
+ if conversionset == "" then conversionset = "default" end -- not used
+ if conversion == "" then conversion = nil end
+ if groupsuffix == "" then groupsuffix = nil end
+ if stopper == "" then stopper = nil end
+ if starter == "" then starter = nil end
+ if connector == "" then connector = nil end
+ if set == "" then set = "default" end
+ if segments == "" then segments = nil end
+ if language == "" then language = nil end
+ --
+ if criterium == v_strict then
+ criterium = 0
+ elseif criterium == v_positive then
+ criterium = -1
+ elseif criterium == v_all then
+ criterium = -1000000
+ else
+ criterium = 0
+ end
+ --
+ local firstprefix, lastprefix = 0, 16 -- too much, could max found level
+ if segments then
+ local f, l = match(tostring(segments),"^(.-):(.+)$")
+ if l == "*" or l == v_all then
+ l = 100 -- new
+ end
+ if f and l then
+ -- 0:100, chapter:subsubsection
+ firstprefix = tonumber(f) or sections.getlevel(f) or 0
+ lastprefix = tonumber(l) or sections.getlevel(l) or 100
+ else
+ -- 3, section
+ local fl = tonumber(segments) or sections.getlevel(segments) -- generalize
+ if fl then
+ firstprefix = fl
+ lastprefix = fl
+ end
+ end
+ end
+ --
+ local numbers, ownnumbers = entry.numbers, entry.ownnumbers
+ if numbers then
+ local done, preceding = false, false
+ --
+ local result = kind == "direct" and { }
+ if result then
+ connector = false
+ end
+ --
+ local prefixlist = set and sets.getall("structure:prefixes","",set) -- "" == block
+ if starter then
+ if result then
+ result[#result+1] = strippedprocessor(starter)
+ else
+ applyprocessor(starter)
+ end
+ end
+ 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
+ -- find last valid number
+ for k=e,b,-1 do
+ local prefix = prefixlist[k]
+ local index = sections.getlevel(prefix) or k
+ if index >= firstprefix and index <= lastprefix then
+ local number = numbers and numbers[index]
+ if number then
+ local ownnumber = ownnumbers and ownnumbers[index] or ""
+ if number > 0 or (ownnumber ~= "") then
+ break
+ else
+ e = k -1
+ end
+ end
+ end
+ end
+ -- find valid range
+ for k=b,e do
+ local prefix = prefixlist[k]
+ local index = sections.getlevel(prefix) or k
+ if index >= firstprefix and index <= lastprefix then
+ local number = numbers and numbers[index]
+ if number then
+ local ownnumber = ownnumbers and ownnumbers[index] or ""
+ if number > 0 or (ownnumber ~= "") then
+ if bb == 0 then bb = k end
+ ee = k
+ else
+ bb, ee = 0, 0
+ end
+ else
+ break
+ end
+ end
+ end
+ -- print valid range
+ for k=bb,ee do
+ local prefix = prefixlist[k]
+ local index = sections.getlevel(prefix) or k
+ if index >= firstprefix and index <= lastprefix then
+ preceding, done = process(index,numbers,ownnumbers,criterium,separatorset,conversion,conversionset,entry,result,preceding,done,language)
+ end
+ end
+ else
+ -- also holes check
+ for index=firstprefix,lastprefix do
+ preceding, done = process(index,numbers,ownnumbers,criterium,separatorset,conversion,conversionset,entry,result,preceding,done,language)
+ end
+ end
+ --
+ if done then
+ if connector and kind == 'prefix' then
+ if result then
+ -- can't happen as we're in 'direct'
+ else
+ applyprocessor(connector)
+ end
+ else
+ if groupsuffix and kind ~= "prefix" then
+ if result then
+ result[#result+1] = strippedprocessor(groupsuffix)
+ else
+ applyprocessor(groupsuffix)
+ end
+ end
+ if stopper then
+ if result then
+ result[#result+1] = strippedprocessor(stopper)
+ else
+ applyprocessor(stopper)
+ end
+ end
+ end
+ end
+ return result -- a table !
+ else
+ -- report_structure("error: no numbers")
+ end
+ end
+end
+
+function sections.title()
+ local sc = sections.current()
+ if sc then
+ helpers.title(sc.titledata.title,sc.metadata)
+ end
+end
+
+function sections.findnumber(depth,what) -- needs checking (looks wrong and slow too)
+ local data = data.status[depth or data.depth]
+ if not data then
+ return
+ end
+ local references = data.references
+ if not references then
+ return
+ end
+ local index = references.section
+ local collected = sections.collected
+ local sectiondata = collected[index]
+ if sectiondata and sectiondata.hidenumber ~= true then -- can be nil
+ local quit = what == v_previous or what == v_next
+ if what == v_first or what == v_previous then
+ for i=index,1,-1 do
+ local s = collected[i]
+ if s then
+ local n = s.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ sectiondata = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ elseif what == v_last or what == v_next then
+ for i=index,#collected do
+ local s = collected[i]
+ if s then
+ local n = s.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ sectiondata = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ end
+ return sectiondata
+ end
+end
+
+function sections.finddata(depth,what)
+ local data = data.status[depth or data.depth]
+ if not data then
+ return
+ end
+ local references = data.references
+ if not references then
+ return
+ end
+ local index = references.listindex
+ if not index then
+ return
+ end
+ local collected = structures.lists.collected
+ local quit = what == v_previous or what == v_next
+ if what == v_first or what == v_previous then
+ for i=index-1,1,-1 do
+ local s = collected[i]
+ if not s then
+ break
+ elseif s.metadata.kind == "section" then -- maybe check on name
+ local n = s.numberdata.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ data = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ elseif what == v_last or what == v_next then
+ for i=index+1,#collected do
+ local s = collected[i]
+ if not s then
+ break
+ elseif s.metadata.kind == "section" then -- maybe check on name
+ local n = s.numberdata.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ data = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ end
+ return data
+end
+
+function sections.internalreference(sectionname,what) -- to be used in pagebuilder (no marks used)
+ local r = type(sectionname) == "number" and sectionname or registered[sectionname]
+ if r then
+ local data = sections.finddata(r.level,what)
+ return data and data.references and data.references.internal
+ end
+end
+
+function sections.fullnumber(depth,what)
+ local sectiondata = sections.findnumber(depth,what)
+ if sectiondata then
+ sections.typesetnumber(sectiondata,'section',sectiondata)
+ end
+end
+
+function sections.getnumber(depth,what) -- redefined here
+ local sectiondata = sections.findnumber(depth,what)
+ local askednumber = 0
+ if sectiondata then
+ local numbers = sectiondata.numbers
+ if numbers then
+ askednumber = numbers[depth] or 0
+ end
+ end
+ context(askednumber)
+end
+
+-- experimental
+
+local levels = { }
+
+local function autonextstructurelevel(level)
+ if level > #levels then
+ for i=#levels+1,level do
+ levels[i] = false
+ end
+ else
+ for i=level,#levels do
+ if levels[i] then
+ ctx_finalizeauto()
+ levels[i] = false
+ end
+ end
+ end
+ levels[level] = true
+end
+
+local function autofinishstructurelevels()
+ for i=1,#levels do
+ if levels[i] then
+ ctx_finalizeauto()
+ end
+ end
+ levels = { }
+end
+
+implement {
+ name = "autonextstructurelevel",
+ actions = autonextstructurelevel,
+ arguments = "integer",
+}
+
+implement {
+ name = "autofinishstructurelevels",
+ actions = autofinishstructurelevels,
+}
+
+-- interface (some are actually already commands, like sections.fullnumber)
+
+implement {
+ name = "depthnumber",
+ actions = { depthnumber, context },
+ arguments = "integer",
+}
+
+implement { name = "structurenumber", actions = sections.fullnumber }
+implement { name = "structuretitle", actions = sections.title }
+
+implement { name = "structurevariable", actions = sections.structuredata, arguments = { false, "string" } }
+implement { name = "structureuservariable", actions = sections.userdata, arguments = { false, "string" } }
+implement { name = "structurecatcodedget", actions = sections.structuredata, arguments = { false, "string", false, true } }
+implement { name = "structuregivencatcodedget", actions = sections.structuredata, arguments = { false, "string", false, "integer" } }
+implement { name = "structureautocatcodedget", actions = sections.structuredata, arguments = { false, "string", false, "string" } }
+
+implement { name = "namedstructurevariable", actions = sections.structuredata, arguments = { "string", "string" } }
+implement { name = "namedstructureuservariable", actions = sections.userdata, arguments = { "string", "string" } }
+
+implement { name = "setstructurelevel", actions = sections.setlevel, arguments = { "string", "string" } }
+implement { name = "getstructurelevel", actions = sections.getcurrentlevel, arguments = { "string" } }
+implement { name = "setstructurenumber", actions = sections.setnumber, arguments = { "integer", "string" } }
+implement { name = "getstructurenumber", actions = sections.getnumber, arguments = { "integer" } }
+implement { name = "getsomestructurenumber", actions = sections.getnumber, arguments = { "integer", "string" } }
+implement { name = "getfullstructurenumber", actions = sections.fullnumber, arguments = { "integer" } }
+implement { name = "getsomefullstructurenumber", actions = sections.fullnumber, arguments = { "integer", "string" } }
+implement { name = "getspecificstructuretitle", actions = sections.structuredata, arguments = { "string", "'titledata.title'",false,"string" } }
+
+implement { name = "reportstructure", actions = sections.reportstructure }
+
+implement {
+ name = "registersection",
+ actions = sections.register,
+ arguments = {
+ "string",
+ {
+ { "coupling" },
+ { "section" },
+ { "level", "integer" },
+ { "parent" },
+ }
+ }
+}
+
+implement {
+ name = "setsectionentry",
+ actions = sections.setentry,
+ arguments = {
+ {
+ { "references", {
+ { "internal", "integer" },
+ { "block" },
+ { "backreference" },
+ { "prefix" },
+ { "reference" },
+ }
+ },
+ { "directives", {
+ { "resetset" }
+ }
+ },
+ { "metadata", {
+ { "kind" },
+ { "name" },
+ { "catcodes", "integer" },
+ { "coding" },
+ { "xmlroot" },
+ { "xmlsetup" },
+ { "nolist", "boolean" },
+ { "increment" },
+ }
+ },
+ { "titledata", {
+ { "label" },
+ { "title" },
+ { "bookmark" },
+ { "marking" },
+ { "list" },
+ }
+ },
+ { "numberdata", {
+ { "block" },
+ { "hidenumber", "boolean" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "starter" },
+ { "stopper" },
+ { "set" },
+ { "segments" },
+ { "ownnumber" },
+ { "language" },
+ },
+ },
+ { "userdata" },
+ }
+ }
+}
+
+-- os.exit()
+
+implement {
+ name = "setsectionblock",
+ actions = sections.setblock,
+ arguments = { "string", { { "bookmark" } } }
+}
+
+implement {
+ name = "setinitialsectionblock",
+ actions = sections.setinitialblock,
+ arguments = "string",
+ -- onlyonce = true,
+}
+
+implement {
+ name = "pushsectionblock",
+ actions = sections.pushblock,
+ arguments = { "string", { { "bookmark" } } }
+}
+
+implement {
+ name = "popsectionblock",
+ actions = sections.popblock,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv
new file mode 100644
index 00000000000..c453f199ef8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv
@@ -0,0 +1,32 @@
+%D \module
+%D [ file=strc-doc,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Document Structure,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Document Structure}
+
+\registerctxluafile{strc-doc}{1.001}
+
+\unprotect
+
+%D This will move:
+
+\unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext
+ {\clf_setinternalreference
+ prefix {\currentstructurereferenceprefix}%
+ reference {\currentstructurereference}
+ internal \nextinternalreference
+ view {\interactionparameter\c!focus}%
+ \relax
+ \xdef\currentstructureattribute {\the\lastdestinationattribute}%
+ \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\nextinternalreference}}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-enu.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-enu.mkvi
new file mode 100644
index 00000000000..832bdaf82af
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-enu.mkvi
@@ -0,0 +1,376 @@
+%D \module
+%D [ file=strc-enu, % moved from strc-des
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Enumerations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Enumerations}
+
+\unprotect
+
+% command -> headcommand
+
+%D Enumerations are just super descriptions. Therefore we implement
+%D them as an extension. After all, the keys don't clash. In order
+%D to be able to differentiate between specific settings we use
+%D some flags. Unfortunately we have some historic differences
+%D in default values. Therefore we push an extra step in the
+%D parent chain (we might do the same for regular descriptions).
+
+%D In order to be more flexible with theorems Aditya Mahajan added
+%D support for titles and endsymbols. At the same time we added more
+%D flexible support for inheriting numbers.
+%D
+%D \startbuffer
+%D \defineenumeration[one]
+%D \defineenumeration[two] [one] % clone one
+%D \defineenumeration[three] [counter=one,style=slanted] % only use counter of one
+%D \defineenumeration[four] [three] % clone three
+%D \defineenumeration[five] [three] [counter=five] % clone three and use own counter
+%D \defineenumeration[six] [three] [counter=four] % clone tree and use counter four (undefined)
+%D
+%D \startone test test 6 \stopone
+%D \starttwo test test 7 \stoptwo
+%D \startthree test test 8 \stopthree
+%D \startfour test test 9 \stopfour
+%D \startfive test test 2 \stopfive
+%D \startsix test test 10 \stopsix
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+%D
+%D \starttyping
+%D \setupenumerations[one] [prefix=yes,prefixsegments=section]
+%D \setupenumerations[two] [prefix=yes,prefixsegments=section]
+%D \setupenumerations[three][prefix=yes,prefixsegments=section]
+%D \setupenumerations[four] [prefix=yes,prefixsegments=chapter:section]
+%D \setupenumerations[five] [prefix=yes,prefixsegments=chapter:section]
+%D \setupenumerations[six] [prefix=yes,prefixsegments=chapter:section]
+%D \stoptyping
+
+% list and titles are experimental
+%
+% \definedescription[test] [location=left,hang=4,headalign={right},distance=1em,list=test]
+% \defineenumeration[lemma][title=yes,right=:,textdistance=1em, location=top, titlestyle=\bs,list=lemma]
+% \defineenumeration[ammel][title=yes,right=:,textdistance=.5em,location=left,titlestyle=\it,width=9em]
+%
+% \placelist[enumeration:lemma]
+% \placelist[description:test][width=0pt]
+%
+% \starttest {something something something} \input zapf \stoptest
+% \startlemma {with a title of a certain length} \input tufte \stoplemma
+% \startammel {with a title} \input zapf \stopammel
+%
+% \defineenumeration[lemma][...]
+% \defineenumeration[titledlemma][lemma][title=yes,right=:,text=lemma,list=lemma]
+
+\installcorenamespace{enumeration}
+
+\installcommandhandler \??enumeration {enumeration} \??enumeration
+
+\installcounterassociation{enumeration}
+
+\let\setupenumerations\setupenumeration
+
+\setupenumerations % check with old
+ [\c!alternative=\v!top,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!width=8\emwidth,
+ \c!distance=\zeropoint,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ %
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ %\c!starter=,
+ %\c!stopper=,
+ \c!text=\currentenumeration,
+ \c!number=\v!yes, % else description
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=4]
+
+% to be considered:
+%
+% \let\??construction\??enumeration
+%
+% with push/pop (also at definition time)
+
+\unexpanded\def\strc_define_commands_enumeration#tag#level#parent%
+ {\doifelsenothing{#parent}
+ {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}%
+ \setevalue{\??enumeration#tag:\s!parent}{\??enumeration}}%
+ {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}%
+ \setevalue{\??enumeration#tag:\s!parent}{\??enumeration#parent}}%
+ \setuevalue{\e!next #tag}{\strc_enumerations_next {#tag}{\number#level}}% obsolete
+ \setuevalue{\c!reset#tag}{\strc_enumerations_reset {#tag}{\number#level}}% obsolete
+ %setuevalue{\c!set #tag}{\strc_enumerations_set {#tag}{\number#level}}% obsolete
+ \setuevalue {#tag}{\strc_enumerations_command{#tag}}% we could pass level here as well (faster)
+ \setuevalue{\e!start#tag}{\strc_enumerations_start {#tag}}% we could pass level here as well (faster)
+ \setuevalue{\e!stop #tag}{\strc_enumerations_stop }}
+
+\appendtoks
+ \ifx\currentenumerationparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentenumerationsub\empty
+ \strc_define_commands_enumeration
+ {\currentenumerationsub\currentenumeration}%
+ \plusone
+ \empty
+ \edef\p_levels{\enumerationparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_enumeration
+ {\v!sub\currentenumerationsub\currentenumeration}%
+ \recurselevel
+ {\currentenumerationsub\currentenumeration}%
+ \edef\currentenumerationsub{\v!sub\currentenumerationsub}}%
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentenumerationsub\empty
+ \edef\p_levels{\enumerationparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_enumeration
+ {\currentenumerationsub\currentenumeration}%
+ \recurselevel
+ {\currentenumerationsub\currentenumerationparent}%
+ \edef\currentenumerationsub{\v!sub\currentenumerationsub}}%
+ \fi
+ \edef\p_counter{\enumerationparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentenumeration
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_enumerations_define_counter\p_counter}%
+ \letenumerationparameter\s!counter\p_counter
+ %\strc_enumerations_setup_counter\currentenumeration
+\to \everydefineenumeration
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\unexpanded\setvalue{\??constructioninitializer\v!enumeration}%
+ {\let\currentenumeration \currentconstruction
+ \let\constructionparameter \enumerationparameter
+ \let\constructionnamespace \??enumeration
+ \let\detokenizedconstructionparameter\detokenizedenumerationparameter
+ \let\letconstructionparameter \letenumerationparameter
+ \let\useconstructionstyleandcolor \useenumerationstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentenumeration
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\unexpanded\setvalue{\??constructionfinalizer\v!enumeration}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Interfaces:
+
+\let\strc_enumerations_command\strc_descriptions_command
+\let\strc_enumerations_start \strc_descriptions_start
+\let\strc_enumerations_stop \strc_descriptions_stop
+
+\unexpanded\def\strc_enumerations_next {\strc_constructions_next_indeed \namedenumerationparameter} % #1#2
+\unexpanded\def\strc_enumerations_reset{\strc_constructions_reset_indeed\namedenumerationparameter} % #1#2
+%unexpanded\def\strc_enumerations_set {\strc_constructions_set_indeed \namedenumerationparameter} % #1#2
+
+%D Counters (maybe we can share this code): (not ok yet, messy with notes)
+
+% Maybe we should move counters to the construction level as more derived mechanisms
+% use it \unknown\ so don't depend on names here!
+
+\def\strc_enumerations_define_counter#tag% todo: move inline
+ {\definecounter[#tag]%
+ \registerenumerationcounter{#tag}}
+
+\appendtoks
+ \synchronizeenumerationcounters
+\to \everysetupenumeration
+
+\appendtoks
+ \synchronizeenumerationcounters
+\to \everydefineenumeration
+
+%D Initializer:
+
+%D The handlers.
+
+\newtoks\everyenumeration
+
+\appendtoks
+ \disablepseudocaps % sorry, uppercase causes troubles
+\to \everyenumeration
+
+\expandafter\let\csname\??constructionmainhandler \v!enumeration\expandafter\endcsname\csname\??constructionmainhandler \v!description\endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!enumeration\expandafter\endcsname\csname\??constructioncommandhandler\v!description\endcsname
+\expandafter\let\csname\??constructionstarthandler \v!enumeration\expandafter\endcsname\csname\??constructionstarthandler \v!description\endcsname
+\expandafter\let\csname\??constructionstophandler \v!enumeration\expandafter\endcsname\csname\??constructionstophandler \v!description\endcsname
+
+\unexpanded\setvalue{\??constructiontexthandler\v!enumeration}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+\unexpanded\def\strc_enumerations_text
+ {\the\everyenumeration % will become obsolete
+ \ifconditional\c_strc_constructions_number_state
+ \ifx\currentconstructionreference\!!plustoken
+ \strc_enumerations_full_number_symbol
+ \else\ifx\currentconstructionreference\!!minustoken
+ \strc_enumerations_full_number_nop
+ \else
+ \strc_enumerations_full_number_coupling
+ \fi\fi
+ \else
+ \strc_enumerations_full_number_nop
+ \fi}
+
+\unexpanded\def\strc_enumerations_inject_text_with_space
+ {\edef\p_text{\constructionparameter\c!text}%
+ \ifx\p_text\empty \else
+ \p_text
+ \removeunwantedspaces
+ \nobreakspace
+ \fi}
+
+\unexpanded\def\strc_enumerations_inject_extra_text
+ {\ifconditional\c_strc_constructions_title_state
+ \clf_doifelselisthastitle{\currentconstructionmain}\numexpr\currentconstructionlistentry\relax
+ \strc_enumerations_inject_extra_text_indeed
+ \donothing
+ \fi}
+
+\unexpanded\def\strc_enumerations_inject_text
+ {\constructionparameter\c!numbercommand
+ {\constructionparameter\c!text}}
+
+% head ( number title )
+
+\unexpanded\def\strc_enumerations_inject_extra_text_indeed
+ {\begingroup
+ \hskip\constructionparameter\c!titledistance % we listen to the headstyle
+ \useconstructionstyleandcolor\c!titlestyle\c!titlecolor
+ \constructionparameter\c!titlecommand
+ {\constructionparameter\c!titleleft
+ \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax
+ \constructionparameter\c!titleright}%
+ \endgroup}
+
+\unexpanded\def\strc_enumerations_inject_symbol % todo check
+ {\constructionparameter\c!left
+ \constructionparameter\c!symbol
+ \constructionparameter\c!right}
+
+\unexpanded\def\strc_enumerations_inject_number
+ {\constructionparameter\c!left
+ \constructionparameter\c!starter
+ \clf_savedlistprefixednumber{\currentconstructionmain}\currentconstructionlistentry\relax
+ \constructionparameter\c!stopper
+ \constructionparameter\c!right}
+
+\unexpanded\def\strc_enumerations_inject_text_and_number
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_number}}
+
+\unexpanded\def\strc_enumerations_inject_text_and_symbol
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_symbol}}
+
+\unexpanded\def\strc_enumerations_full_number_yes
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text_and_number
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\unexpanded\def\strc_enumerations_full_number_nop
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\unexpanded\def\strc_enumerations_full_number_symbol
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text_and_symbol
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+% to be used in for instance:
+%
+% coupling=questions .... coupling=answers
+%
+% we will provide some more control, like skipping etc or reference relates
+
+% to do / to be checked
+
+\unexpanded\def\strc_enumerations_full_number_coupling
+ {\iflocation
+ \strc_enumerations_full_number_yes
+ \else
+ \iftrialtypesetting \else
+ % \doenumerationregistercoupling
+ \fi
+ \strc_enumerations_full_number_yes
+ \edef\p_coupling{\constructionparameter\c!coupling}%
+ \ifx\p_coupling\empty \else
+ \symbolreference[order(construction:\p_coupling:\nextinternalorderreference)]%
+ \fi
+ \fi}
+
+\unexpanded\def\strc_enumerations_skip_number_coupling[#tag]% e.g. for questions with no answer
+ {\clf_setnextreferenceorder{construction}{#tag}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua
new file mode 100644
index 00000000000..466fd515e04
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['strc-flt'] = {
+ version = 1.001,
+ comment = "companion to strc-flt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- nothing
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi
new file mode 100644
index 00000000000..e83e036fa75
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi
@@ -0,0 +1,2310 @@
+%D \module
+%D [ file=strc-flt,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Float Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module will be redone with conditionals and everythings
+
+\writestatus{loading}{ConTeXt Structure Macros / Float Numbering}
+
+\registerctxluafile{strc-flt}{1.001}
+
+\unprotect
+
+% todo: a keyword for this (and then a settings->hash for speed)
+%
+% \setuplayout[width=middle,backspace=3cm]
+%
+% \appendtoks
+% \settrue\inhibitmargindata
+% \to \everyinsidefloat
+%
+% \starttext
+% \dorecurse{20}{
+% \par \inleft{\red\infofont<#1>} \par
+% \placefigure[leftmargin]{}{\framed[height=1cm,width=2cm]{}}
+% % \placefigure{#1}{\framed[height=1cm,width=2cm]{}}
+% \par line #1.1 \par line #1.2 \par
+% }
+% \stoptext
+
+% todo: delay caption creation and make setups for each method instead
+% so that we can have a list of methods and redo them as we can
+% keep the list or even better: recreate it
+%
+% todo: strc_floats_analyze_variables_two could trigger a setup
+% and we could have nofmethods of them
+%
+% todo: move variables from page-flt to strc-flt
+%
+% todo: p_name etc
+%
+% todo: less globals!
+%
+% todo: do all options in lua
+
+%D This module is being converted into a mkvi one.
+%D
+%D - rename macros
+%D - get rid of dead code
+%D - less gobal mess
+%D - more mkiv-ish
+
+\installcorenamespace{float}
+\installcorenamespace{floatbuilder}
+\installcorenamespace{floatcaption}
+
+\installframedcommandhandler \??float {float} \??float
+\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption
+
+\let\setupfloats \setupfloat
+\let\setupcaption \setupfloatcaption
+\let\setupcaptions\setupfloatcaption
+
+\unexpanded\def\dohandlenextfloatindent
+ {\useindentnextparameter\floatparameter
+ \dorechecknextindentation}
+
+\setupcaptions
+ [\c!location=\v!bottom,
+ \c!grid=,
+ \c!before=, % not used (yet)
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=, % not used (yet)
+ \c!spacebefore=,
+ \c!spaceinbetween=, % replaces fuzzy inbetween dual usage
+ \c!spaceafter=,
+ \c!width=\v!fit,
+ \c!minwidth=\v!fit, % id est: the width of the floatbox in some cases
+ \c!headstyle=\v!bold,
+ \c!headcolor=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!outermargin=\zeropoint,
+ \c!innermargin=\zeropoint,
+ \c!setups=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!textstyle=,
+ \c!textcolor=,
+ \c!align=,
+ \c!number=\v!yes,
+ % \c!expansion=\v!no
+ % \c!prefix=\v!no,
+ % \c!prefixconnector=.,
+ % \c!way=\v!by\v!chapter,
+ % \c!prefixsegments=2:2,
+ % \c!way=\@@nrway,
+ % \c!blockway=\@@nrblockway,
+ % \c!sectionnumber=\@@nrsectionnumber,
+ % \c!separator=\@@koseparator,
+ % \c!starter=\@@kostarter,
+ % \c!stopper=\@@kostopper,
+ \c!suffixseparator=, % currently rather hard coded
+ \c!suffix=\floatcaptionsuffix,
+ \c!distance=\emwidth,
+ \c!conversion=\v!numbers,
+ \c!maxwidth=\hsize,
+ \c!command=]
+
+% we can comment some of these
+
+\setupfloats
+ [\c!location=\v!middle,
+ \c!width=8\lineheight,
+ \c!height=6\lineheight,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\!!zeropoint,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!frameoffset=\!!zeropoint,
+ %\c!before=,
+ %\c!after=,
+ \c!spacebefore=\v!big,
+ \c!spaceafter=\v!big,
+ \c!sidespacebefore=\rootfloatparameter\c!spacebefore,
+ \c!sidespaceafter=\rootfloatparameter\c!spaceafter,
+ \c!sidealign=\v!normal,
+ \c!textmethod=\ifgridsnapping2\else0\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
+ \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
+ \c!indentnext=\v!no,
+ \c!margin=1\emwidth,
+ \c!method=1,
+ \c!cache=\v!yes, % when no, then intermediate flush
+ \c!leftmargin=\zeropoint, % displacement in 'normal floats'
+ \c!rightmargin=\zeropoint, % idem
+ \c!innermargin=\zeropoint, % idem
+ \c!outermargin=\zeropoint, % idem
+ \c!leftmargindistance=\zeropoint,
+ \c!rightmargindistance=\floatparameter\c!leftmargindistance,
+ \c!step=\v!big, % the flish side float step (big=line, medium=halfline, small=quarterline, depth=halfline with normaldepth)
+ \c!ntop=2,
+ \c!nbottom=0,
+ \c!nlines=4, % used?
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ %\c!local=,
+ %\c!bottombefore=, % e.g. \vfill
+ %\c!bottomafter=,
+ %\c!default=, % default location
+ \c!numbering=\v!yes]
+
+%D Individial settings:
+
+\installcounterassociation{floatcaption}
+
+\appendtoks
+ \let\currentfloat\currentfloatcaption % ?
+ \synchronizefloatcaptioncounters
+\to \everysetupfloatcaption
+
+\appendtoks
+ \let\currentfloat\currentfloatcaption % ?
+ \synchronizefloatcaptioncounters
+\to \everydefinefloatcaption
+
+%D Definitions:
+
+\let\strc_floats_define_saved\definefloat
+
+\unexpanded\def\definefloat
+ {\dotripleempty\strc_floats_define}
+
+\def\strc_floats_define[#1][#2][#3]% name+plural+parent | name+parent+settings
+ {\ifthirdargument
+ \doifassignmentelse{#3}
+ {\strc_floats_define_b[#1][#2][#3]}%
+ {\strc_floats_define_a[#1][#2][#3]}%
+ \else\ifsecondargument
+ \doifelsecommandhandler\??float{#2}%
+ {\strc_floats_define_a[#1][#1][#2]}%
+ {\strc_floats_define_c[#1][#2]}%
+ \else
+ \strc_floats_define_c[#1][#1]%
+ \fi\fi}
+
+\def\strc_floats_define_a[#1][#2][#3]% name names parent
+ {\definefloatcaption[#1][#3]%
+ \definecounter[#1][#3]%
+ \definelist[#1][#3]%
+ \copylabeltext[#1=#3]%
+ \strc_floats_define_saved[#1][#3]%
+ \strc_floats_define_commands{#1}{#2}}
+
+\def\strc_floats_define_b[#1][#2][#3]% name parent settings
+ {\definefloatcaption[#1][#2]%
+ \definecounter[#1][#2]%
+ \definelist[#1][#2]%
+ \copylabeltext[#1=#2]%
+ \strc_floats_define_saved[#1][#2][#3]%
+ \strc_floats_define_commands{#1}{#1}}
+
+\def\strc_floats_define_c[#1][#2]% name names
+ {\registerfloatcaptioncounter{#1}%
+ \definefloatcaption[#1]%
+ \definecounter[#1]%
+ \definelist[#1]%
+ \presetlabeltext[#1=\Word{#1}~]%
+ \presetheadtext[#2=\Word{#2}]%
+ \strc_floats_define_saved[#1]%
+ \strc_floats_define_commands{#1}{#2}}
+
+\def\strc_floats_define_commands#1#2%
+ {\setuvalue {\e!place\e!listof#2}{\dodoubleempty\strc_lists_place[#1]}% call will change
+ \setuvalue {\e!complete\e!listof#2}{\dotripleempty\strc_lists_complete_indeed[#1][#2]}% call will change
+ \setuevalue {\e!place#1}{\strc_floats_place{#1}}%
+ \setuevalue {\e!start\e!place#1}{\strc_floats_start_place{#1}}%
+ \setuevalue {\e!stop\e!place#1}{\strc_floats_stop_place}%
+ \setuevalue {\e!start#1\e!text}{\strc_floats_start_text{#1}}%
+ \setuevalue {\e!stop#1\e!text}{\strc_floats_stop_text}%
+ % these will become obsolete:
+ \setuevalue {\e!reserve#1}{\strc_floats_reserve{#1}}%
+ \setuevalue{\e!start\e!reserve#1\e!text}{\strc_floats_start_reserve_text{#1}}%
+ \setuevalue {\e!stop\e!reserve#1\e!text}{\strc_floats_stop_reserve_text}}
+
+%D Fallback float body:
+
+\unexpanded\def\strc_floats_place_empty_box % \inheritedfloatframed
+ {\framed
+ [\c!frame=\v!on,
+ \c!width=\rootfloatparameter\c!width,
+ \c!height=\rootfloatparameter\c!height,
+ \c!location=\v!normal,
+ \c!offset=\rootfloatparameter\c!offset]%
+ {\getmessage\m!floatblocks{12}\empty}}
+
+%D Data. We can generalize this to lists.
+
+\newif\ifnofloatcaption
+\newif\ifnofloatnumber
+\newif\ifemptyfloatcaption
+
+\installstructurelistprocessor\s!float{\usestructurelistprocessor{number+title}}
+
+\unexpanded\def\thecurrentfloatnumbersuffix
+ {\doifsomething{\floatcaptionparameter\c!suffix}
+ {\floatcaptionparameter\c!suffixseparator
+ \floatcaptionparameter\c!suffix
+ \floatcaptionparameter\c!suffixstopper}}
+
+\unexpanded\def\thecurrentfloatnumber
+ {\ifnofloatcaption \else \ifnofloatnumber \else
+ \ifx\currentfloatnumber\relax\else
+ \namedtaggedlabeltexts
+ \t!floatlabel \currentfloat
+ \t!floatnumber\currentfloat
+ {\begstrut
+ \floatcaptionparameter\c!numbercommand
+ {\clf_savedlistprefixednumber{\currentfloat}\currentfloatnumber\relax
+ \thecurrentfloatnumbersuffix}%
+ \endstrut}%
+ \fi
+ \fi \fi}
+
+\unexpanded\def\thecurrentfloatcaption
+ {\ifnofloatcaption \else \ifemptyfloatcaption \else
+ \ifx\currentfloatnumber\relax\else
+ \dostarttagged\t!floattext\empty
+ \begstrut
+ \floatcaptionparameter\c!textcommand
+ {\clf_savedlisttitle{\currentfloat}\numexpr\currentfloatnumber\relax}%
+ \endstrut
+ \dostoptagged
+ \fi
+ \fi \fi}
+
+%D Captions.
+
+\let\floatcaptionsuffix\empty % an optional suffix
+\let\floatcaptionnumber\empty % a logical counter
+
+% the split is needed when for instance the float goes into
+% a multi page field and the list of figs becomes larger than
+% one page: cycle between 'only flush when object ref ok'
+% and 'one/many page fig list'; see "uguide finometer"
+%
+% potential sync bug with sectionblocks, see uguide.tex
+
+% begin of todo
+
+\unexpanded\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption}
+\unexpanded\def\setfloatcaption {\dodoubleempty\strc_floats_set_caption}
+
+\def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]}
+\def\strc_floats_set_caption [#tag][#reference]#caption{[not supported]}
+
+\unexpanded\def\placefloatcaptiontext [#tag]{[not suported yet]}
+\unexpanded\def\placefloatcaptionnumber [#tag]{[not suported yet]}
+\unexpanded\def\placefloatcaptionreference[#tag]{[not suported yet]}
+
+\let\placefloatlabel \placefloatcaption
+\let\placefloatlabeltext \placefloatcaptiontext
+\let\placefloatlabelreference\placefloatcaptionreference
+
+% end of todo
+
+\newbox \b_strc_floats_caption
+\newbox \b_strc_floats_content
+\newdimen\d_strc_floats_caption_height
+\newdimen\d_strc_floats_caption_depth
+
+\def\strc_floats_make_complete_caption
+ {\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}%
+ \synchronizedisplaydirection % temp hack, till we have a proper model
+ \noindent
+ \gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking
+ \begingroup
+ \usefloatcaptionstyleandcolor\c!style\c!color
+ \clf_doifelselisthastitle{\currentfloat}\numexpr\currentfloatnumber\relax
+ \donothing
+ \emptyfloatcaptiontrue
+ \ifnofloatnumber
+ \else
+ \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}%
+ \ifnofloatcaption \else \ifemptyfloatcaption \else
+ \doifelsenothing{\floatcaptionparameter\c!spaceinbetween}
+ {\scratchskip\floatcaptionparameter\c!distance\relax
+ \dotfskip\scratchskip\emergencystretch.5\scratchskip}
+ {\blank[\floatcaptionparameter\c!spaceinbetween]}%
+ \fi \fi
+ \fi
+ \ifnofloatcaption
+ \global\d_strc_floats_caption_height\zeropoint
+ \global\d_strc_floats_caption_depth \zeropoint
+ \else
+ \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor
+ \global\d_strc_floats_caption_height\strutheight
+ \global\d_strc_floats_caption_depth \strutdepth
+ \thecurrentfloatcaption\endgraf
+ \fi
+ \endgroup
+ \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}}
+
+% \newif\iftracecaptions
+%
+% \def\settracedcaptionbox
+% {\iftracecaptions\setbox\b_strc_floats_caption\ruledhbox{\box\b_strc_floats_caption}\fi}
+
+% \definefloat [figure-1] [figure]
+% \definefloat [figure-2] [figure]
+% \setupfloat [figure-1] [location=left,leftmargin=10mm]
+% \setupfloat [figure-2] [location=left,leftmargin=-5mm]
+% \setupcaption [figure-1] [align=flushleft]
+% \setupcaption [figure-2] [align=flushleft,leftmargin=15mm]
+%
+% \startsetups somefigure
+% \ifdim\wd\nextbox>\textwidth
+% \placefloat[figure-2][][]{}{\box\nextbox}
+% \else
+% \placefloat[figure-1][][]{}{\box\nextbox}
+% \fi
+% \stopsetups
+%
+% \unexpanded\def\setupswithbox[#1]{\dowithnextbox{\setups[#1]}\vbox}
+%
+% test \setupswithbox[somefigure]{\framed[width=3cm] {}} test
+% test \setupswithbox[somefigure]{\framed[width=\dimexpr\textwidth+3cm\relax]{}} test
+
+% temporary removed ... was not applied systematically
+%
+% \def\dosetcaptionthings
+% {\usesetupsparameter\floatcaptionparameter}
+
+\def\strc_floats_check_caption_content
+ {\ifnofloatcaption
+ \else
+ \setbox\b_strc_floats_caption\hbox
+ {\settrialtypesetting
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ % new, \placefigure{\xmlfirst{#1}{somecaption}}{} passes earlier empty check
+ % so here we misuse the scratch box; actually this means that the previous
+ % test can go away (some day, when i redo this module)
+ \ifdim\wd\b_strc_floats_caption=\zeropoint
+ \global\emptyfloatcaptiontrue
+ \ifnofloatnumber
+ \global\nofloatcaptiontrue
+ \fi
+ \else
+ \global\emptyfloatcaptionfalse
+ \setbox\b_strc_floats_caption\hpack{\hskip\leftskip\box\b_strc_floats_caption}%
+ \fi
+ \fi}
+
+% The tricky part of getting float related two pass data is
+% that we should fetch is early but can only save it with
+% the composed float box; this determines the order: get it
+% before saving it.
+
+% We had this:
+%
+% \definetwopasslist{\s!float\s!data} \newcounter\noffloatdata
+%
+% \let\strc_float_realpage\realpageno % used for odd/even determination, can be combined with nodelocation
+%
+% \def\strc_float_save_data % \expanded ... will change in mkiv
+% {\doglobal\increment\noffloatdata
+% \lazysavetaggedtwopassdata{\s!float\s!data}{\noffloatdata}{\noffloatpages}{\noexpand\realfolio}}% later {}{}{}{} and \getfirst...
+%
+% \def\strc_float_load_data % precedes save !
+% {\doglobal\increment\noffloatpages
+% \findtwopassdata{\s!float\s!data}{\noffloatpages}%
+% \ifconditional\twopassdatafound
+% \globallet\strc_float_realpage\twopassdata
+% \else
+% \globallet\strc_float_realpage\realpageno % \realfolio
+% \fi}
+
+%D We can do this ...
+%D
+%D \starttyping
+%D \newcount\c_strc_floats_n
+%D
+%D \definedataset[\s!float][\c!delay=\v!yes]
+%D
+%D \let\strc_float_realpage\realpageno
+%D
+%D \def\strc_float_save_data
+%D {\setdataset[\s!float][\number\c_strc_floats_n][]}
+%D
+%D \def\strc_float_load_data % precedes save !
+%D {\global\advance\c_strc_floats_n\plusone
+%D \xdef\strc_float_realpage{\datasetvariable\s!float{\number\c_strc_floats_n}\s!page}%
+%D \ifx\strc_float_realpage\empty
+%D \globallet\strc_float_realpage\realpageno % \realfolio
+%D \fi}
+%D \stoptyping
+%D
+%D ... but this is more efficient:
+
+\definepagestate[\s!float][\c!delay=\v!yes]
+
+\newcount\c_strc_floats_n
+
+\let\strc_float_realpage\realpageno
+
+\def\strc_float_save_data
+ {\setpagestate[\s!float][\number\c_strc_floats_n]}
+
+\def\strc_float_load_data % precedes save !
+ {\global\advance\c_strc_floats_n\plusone
+ \xdef\strc_float_realpage{\pagestaterealpage\s!float{\number\c_strc_floats_n}}%
+ \ifx\strc_float_realpage\empty
+ \globallet\strc_float_realpage\realpageno % \realfolio
+ \fi}
+
+%D test case:
+%D
+%D \starttyping
+%D \setupfloat[figure][criterium=\marginwidth,fallback=bottom]
+%D \dorecurse{3}{
+%D \chapter{test}
+%D \placefigure[bottom]{1}{\framed{bottom}}
+%D test
+%D \placetable[bottom]{1}{\framed{table}}
+%D test
+%D \placetable{2}{\framed{table}}
+%D test
+%D \placefigure[left]{2}{\framed{left but way too wide}}
+%D \input tufte
+%D \placefigure[left]{3}{\framed{left but ok}}
+%D \input tufte }
+%D \stoptyping
+
+% A complication is that we may have to handle a pagebreak
+% first, which in turn may issue a (postponed) float.
+% Therefore we may not trust on variable assignments before
+% we're really dealing with the float. Some day I'll root out
+% the global settings.
+
+\let\lastplacedfloat\empty
+
+\def\strc_floats_set_current_tag#tag%
+ {\edef\currentfloat{#tag}%
+ \ifx\currentfloat\empty
+ \let\currentfloat\v!figure % a bit of a hack
+ \fi
+ \doifelsecommandhandler\??float\currentfloat
+ \donothing
+ {\writestatus\m!floatblocks{unknown float type '\currentfloat'}%
+ \let\currentfloat\v!figure}% also a hack
+ \global\let\lastplacedfloat\currentfloat
+ \let\m_strc_floats_saved_userdata\empty
+ \let\currentfloatcaption\currentfloat}
+
+\def\strc_floats_reset_variables
+ {\global\emptyfloatcaptionfalse
+ \global\nofloatcaptionfalse
+ \global\nofloatnumberfalse}
+
+% place
+
+\def\strc_floats_analyze_location
+ {% moved here, will do more
+ \let\floatlabel \empty
+ \let\floatcolumn\empty
+ \let\floatrow \empty
+ \setfloatmethodvariables\floatlocation}
+
+\unexpanded\def\strc_floats_place#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dodoubleempty\strc_floats_place_indeed}
+
+\newtoks\c_floats_every_table_float
+
+\appendtoks
+ \edef\floatlocation{\v!force,\v!always,\floatlocation}%
+ \setupfloat[\c!spacebefore=\v!none,\c!spaceafter=\v!none]%
+\to \c_floats_every_table_float
+
+\def\strc_floats_place_indeed[#location][#reference]#caption%
+ {\strc_floats_reset_variables
+ \edef\floatlocation{#location}%
+ \ifx\floatlocation\empty
+ \edef\floatlocation{\floatparameter\c!default}% beware of a clash between alignment locations
+ \fi
+ \ifintable
+ \the\c_floats_every_table_float
+ \fi
+ \strc_floats_analyze_location
+ % todo: use \lets
+ \setupcurrentfloatcaption[\c!reference={#reference},\c!title={#caption},\c!marking=,\c!list=,\c!bookmark=]%
+ \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal}
+
+\unexpanded\def\placefloat
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \dotripleempty\strc_floats_place_float}
+
+\def\strc_floats_place_float[#tag]%
+ {\strc_floats_set_current_tag{#tag}%
+ \strc_floats_place_indeed}
+
+% start-stop
+
+% \startplacefigure[title=oeps][subtitle=whatever]
+% \framed[width=10cm,height=5cm]{\floatuserdataparameter{subtitle}}
+% \stopplacefigure
+
+\installcorenamespace{floatuserdata}
+
+\installsetuponlycommandhandler \??floatuserdata {floatuserdata}
+
+\let\m_strc_floats_saved_userdata\empty % todo: reset this in non start|stop cases
+
+\unexpanded\def\strc_floats_start_place#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dodoubleempty\strc_floats_start_place_indeed}
+
+\def\strc_floats_start_place_indeed[#settings][#userdata]%
+ {\strc_floats_reset_variables
+ \edef\savedfloatlocation{\floatcaptionparameter\c!location}%
+ \setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}%
+ \setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}%
+ \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}%
+ \def\m_strc_floats_saved_userdata{#2}%
+ \edef\floatlocation{\floatcaptionparameter\c!location}%
+ \setfloatcaptionparameter\c!location{\savedfloatlocation}% not expanded
+ \ifx\floatlocation\empty
+ \edef\floatlocation{\floatparameter\c!default}%
+ \fi
+ \ifsecondargument
+ \setupcurrentfloatuserdata[#userdata]%
+ \fi
+ \strc_floats_analyze_location
+ \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal
+ \bgroup
+ \ignorespaces}
+
+\unexpanded\def\strc_floats_stop_place
+ {\removeunwantedspaces
+ \egroup}
+
+\unexpanded\def\startplacefloat
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \dotripleempty\strc_floats_start_place_float}
+
+\def\strc_floats_start_place_float[#tag]%
+ {\strc_floats_set_current_tag{#tag}%
+ \strc_floats_start_place_indeed}
+
+\let\stopplacefloat\strc_floats_stop_place
+
+% reserve
+
+\unexpanded\def\strc_floats_reserve#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dotripleempty\strc_floats_reserve_indeed}
+
+\def\strc_floats_reserve_indeed[#settings][#location][#reference]#caption% maybe check for #settings
+ {\strc_floats_place_indeed[#location][#reference]{#caption}{\strc_floats_reserve_box{#settings}}}
+
+\def\strc_floats_reserve_box#settings%
+ {\begingroup
+ \setupcurrentfloat[\c!frame=\v!on,#settings]%
+ \inheritedfloatframed{}%
+ \endgroup}
+
+% text
+
+\unexpanded\def\strc_floats_start_text#tag%
+ {\flushnotes % Here indeed?
+ \page_otr_command_flush_side_floats % Here indeed?
+ \strc_floats_begin_text_group
+ \strc_floats_set_current_tag{#tag}%
+ \dodoubleempty\strc_floats_start_text_indeed}
+
+\def\strc_floats_start_text_indeed[#location][#reference]%
+ {\strc_floats_place_indeed[\v!text,#location,\v!left][#reference]}
+
+\unexpanded\def\strc_floats_stop_text
+ {\strc_floats_stop_text_indeed}
+
+% reserved text
+
+\unexpanded\def\strc_floats_start_reserve_text#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats
+ \strc_floats_begin_text_group
+ \strc_floats_set_current_tag{#tag}%
+ \dotripleempty\strc_floats_start_reserve_text_indeed}
+
+\def\strc_floats_start_reserve_text_indeed[#settings][#location][#reference]#caption%
+ {\strc_floats_place_indeed[\v!text,#location,\v!left][#reference]{#caption}{\strc_floats_reserve_box{#settings}}}
+
+\unexpanded\def\strc_floats_stop_reserve_text
+ {\strc_floats_stop_text_indeed}
+
+% special hack
+
+\def\strc_floats_begin_group {\begingroup}
+\def\strc_floats_end_group {\carryoverpar\endgroup}
+\def\strc_floats_end_split_group {\endgroup}
+\def\strc_floats_begin_text_group{\begingroup\let\strc_floats_end_group\relax}
+\def\strc_floats_end_text_group {\endgroup}
+
+% implementation
+
+%setnewconstant\c_page_one_float_method \zerocount % 0=raw 1=safe (.99) 2=tight (-1pt) / belongs in page-one
+\setnewconstant\c_strc_floats_rotation \zerocount % 0 90 180 270
+\newconditional\c_strc_floats_par_float
+
+\ifdefined\page_margin_strc_floats_before \else \let\page_margin_strc_floats_before \relax \fi
+\ifdefined\page_margin_strc_floats_set_hsize \else \let\page_margin_strc_floats_set_hsize\relax \fi
+
+\def\flushfloatslist
+ {\v!left,\v!right,\v!inner,\v!outer,%
+ \v!backspace,\v!cutspace,%
+ \v!inleft,\v!inright,\v!inmargin,%
+ \v!leftmargin,\v!rightmargin,\v!leftedge,\v!rightedge,%
+ \v!innermargin,\v!outermargin,\v!inneredge,\v!outeredge,%
+ \v!text,\v!opposite}% \v!page
+
+\unexpanded\def\strc_floats_place_next_box_split
+ {\let\splitfloatfinalizer\strc_floats_end_split_group
+ \let\strc_floats_end_group\relax
+ \splitfloat{\strc_floats_place_next_box_normal}}
+
+\unexpanded\def\strc_floats_place_next_box_normal
+ {\ifconditional\c_page_floats_some_waiting
+ % this was \checkwaitingfloats spread all over
+ \doifelseinset\v!always\floatlocation
+ {\showmessage\m!floatblocks5\empty}
+ {\doifelsecommon\floatlocation\flushfloatslist\page_otr_command_flush_floats\donothing}%
+ % but which should be done before using box \floatbox
+ \fi
+ \page_margin_strc_floats_before % todo: each float handler gets a before
+ \global\insidefloattrue
+ \dostarttaggedchained\t!float\currentfloat\??float
+ \page_margin_strc_floats_set_hsize % todo: each float handler gets a set_hsize
+ \the\everyinsidefloat
+ \strc_floats_analyze_variables_one
+ \dostarttagged\t!floatcontent\empty
+ \dowithnextboxcontent
+ {\strc_floats_set_local_hsize
+ \floatparameter\c!inner
+ \postponenotes} % new
+ {\dostoptagged
+ \strc_floats_finish_placement}
+ \vbox}
+
+\def\strc_floats_finish_placement
+ {\doifsomething{\floatparameter\c!criterium}
+ {\ifdim\wd\nextbox>\floatparameter\c!criterium\relax
+ \edef\forcedfloatmethod{\floatparameter\c!fallback}%
+ \ifx\forcedfloatmethod\empty\let\forcedfloatmethod\v!here\fi
+ \fi}%
+ \strc_floats_check_extra_actions
+ \strc_floats_analyze_variables_two
+ \strc_floats_place_packaged_boxes
+ \dostoptagged % tricky .... needs checking
+ % we need to carry over the par because of side floats
+ \global\d_page_sides_downshift \zeropoint
+ \global\d_page_sides_extrashift\zeropoint
+ \ifconditional\c_strc_floats_par_float
+ \doifinset\v!reset\floatlocation\page_sides_forget_floats
+ \doinhibitblank
+ \fi
+ \strc_floats_end_group}
+
+% nicer is a bunch of states and one loop that sets those states
+
+\def\strc_floats_analyze_variables_two
+ {\ifinsidecolumns
+ \global\setfalse\c_strc_floats_par_float
+ \else
+ \doifelsecommon\floatlocation\flushfloatslist
+ {\global\settrue \c_strc_floats_par_float}
+ {\global\setfalse\c_strc_floats_par_float}%
+ \fi
+ \global\d_page_sides_shift \zeropoint
+ \global\d_page_sides_maximum \zeropoint
+ \global\c_page_sides_method \floatparameter\c!sidemethod
+ \global\c_page_one_float_method \floatparameter\c!textmethod
+ \global\c_page_sides_align \zerocount
+ \global\c_strc_floats_rotation \zerocount
+ \strc_floats_calculate_skips
+ \ifconditional\c_strc_floats_par_float
+ \processaction
+ [\floatparameter\c!sidealign]
+ [\v!height=>\global\c_page_sides_align\plusone ,%
+ \v!line=>\global\c_page_sides_align\plustwo ,% (***)
+ \v!depth=>\global\c_page_sides_align\plusthree,%
+ \v!grid=>\global\c_page_sides_align\plusfour ,%
+ \v!halfline=>\global\c_page_sides_align\plusfive ]%
+ \ifcase\c_page_sides_align\relax % todo: optie v!lokaal => \else
+ \doifinset\v!height \floatlocation{\global\c_page_sides_align\plusone }%
+ \doifinset\v!line \floatlocation{\global\c_page_sides_align\plustwo }%
+ \doifinset\v!depth \floatlocation{\global\c_page_sides_align\plusthree}%
+ \doifinset\v!grid \floatlocation{\global\c_page_sides_align\plusfour }%
+ \doifinset\v!halfline\floatlocation{\global\c_page_sides_align\plusfive }% meant for 'none'
+ \fi
+ \doifinset\v!high\floatlocation{\global\d_page_sides_topskip \zeropoint}%
+ \doifinset\v!low \floatlocation{\global\d_page_sides_bottomskip\zeropoint}%
+ \doifinset\v!fit \floatlocation
+ {\global\d_page_sides_topskip \zeropoint
+ \global\d_page_sides_bottomskip\zeropoint
+ \global\d_strc_floats_margin \zeropoint}%
+ \global\advance\d_page_sides_topskip \floatparameter\c!topoffset
+ \global\advance\d_page_sides_bottomskip\floatparameter\c!bottomoffset
+ \else
+ \processallactionsinset
+ [\floatlocation]
+ [ 90=>\global\c_strc_floats_rotation\commalistelement\relax,%
+ 180=>\global\c_strc_floats_rotation\commalistelement\relax,%
+ 270=>\global\c_strc_floats_rotation\commalistelement\relax]%
+ \fi
+ \doifelseinset\v!nonumber\floatlocation
+ {\global\nofloatnumbertrue}
+ {\doifelse{\floatcaptionparameter\c!number}\v!yes
+ {\global\nofloatnumberfalse}
+ {\global\nofloatnumbertrue}}%
+ \doifelseinset\v!none\floatlocation
+ {\global\nofloatcaptiontrue}
+ {\global\nofloatcaptionfalse}%
+ \doif{\floatcaptionparameter\c!number}\v!none % new
+ {\global\nofloatcaptiontrue}%
+ \ifemptyfloatcaption \ifnofloatnumber
+ \global\nofloatcaptiontrue
+ \fi \fi}
+
+% documenteren in details
+
+\def\strc_floats_analyze_variables_one
+ {\doifelse{\floatparameter\c!local}\v!yes\settrue\setfalse\c_page_floats_center_box_global % fout keyword
+ \ifconditional\c_page_floats_center_box_global
+ \settrue\c_page_floats_center_box_local
+ \else
+ \doifelseinset\v!local\floatlocation\settrue\setfalse\c_page_floats_center_box_local
+ \fi
+ \doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! !
+ {\setfalse\c_page_floats_center_box_global
+ \setfalse\c_page_floats_center_box_local}}
+
+\let\naturalfloatheight\!!zeropoint
+\let\naturalfloatwidth \!!zeropoint
+\let\naturalfloatdepth \!!zeropoint
+
+\def\strc_floats_set_natural_dimensions#box%
+ {\xdef\naturalfloatheight{\the\ht#box}%
+ \xdef\naturalfloatwidth {\the\wd#box}%
+ \xdef\naturalfloatdepth {\the\dp#box}}
+
+\def\doifelsemainfloatbody
+ {\ifinsidesplitfloat
+ \ifconditional\splitfloatfirstdone
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifmainfloatbodyelse\doifelsemainfloatbody
+
+% todo: optional user pars
+
+\let\currentfloatattribute\empty % to be checked
+
+\def\floatcaptionattribute
+ {\iflocation
+ %\ifnofloatnumber
+ %\else
+ \ifnofloatcaption
+ \else
+ \ifinsidesplitfloat
+ \ifconditional\splitfloatfirstdone
+ \else
+ attr \destinationattribute \currentfloatattribute
+ \fi
+ \else
+ attr \destinationattribute \currentfloatattribute
+ \fi
+ \fi
+ %\fi
+ \fi}
+
+\newconditional\usesamefloatnumber
+
+% \startplacefigure[location=here,reference=first, title=first, group=alpha,groupsuffix=.a]
+% \externalfigure[dummy][height=2cm]
+% \stopplacefigure
+% \startplacefigure[location=here,reference=second,title=second,group=alpha,groupsuffix=.b]
+% \externalfigure[dummy][height=2cm]
+% \stopplacefigure
+%
+% uses:
+
+\def\strc_floats_group_index
+ {\numexpr\clf_listgroupindex{\currentfloat}{\currentfloatgroup}\relax}
+
+\def\strc_floats_place_packaged_boxes
+ {\expandafter\strc_floats_place_packaged_boxes_indeed\expandafter{\m_strc_floats_saved_userdata}}
+
+\def\strc_floats_place_packaged_boxes_indeed#userdata%
+ {\bgroup
+ \ifconditional\usesamefloatnumber
+ \globallet\currentfloatnumber \previousfloatnumber
+ \globallet\currentfloatattribute \empty
+ \globallet\currentfloatsynchronize\relax
+ \else
+ \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}%
+ \edef\currentfloatgroup {\floatcaptionparameter\c!group}%
+ \ifnofloatnumber \else \ifnofloatcaption \else
+ \ifx\currentfloatgroup\empty
+ % independent
+ \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi
+ \strc_counters_increment\currentfloatcounter
+ \else\ifcase\strc_floats_group_index
+ % first in group
+ \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi
+ \strc_counters_increment\currentfloatcounter
+ \else
+ % next in group
+ \fi \fi
+ \fi \fi
+ % *1* as an alternative we could set counter parameters here if needed
+ \strc_counters_register_component
+ \s!float
+ \setupcurrentfloatcaption
+ \floatcaptionparameter
+ \detokenizedfloatcaptionparameter
+ \relax
+ \relax
+ \relax
+ [\s!name=\currentfloat,% was c!name
+ \s!counter=\currentfloatcounter,%
+ \s!hascaption=\ifnofloatcaption \v!no\else\v!yes\fi,%
+ \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,%
+ \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]%
+ [#userdata]%
+ \globallet\previousfloatnumber \m_strc_counters_last_registered_index
+ \globallet\currentfloatnumber \m_strc_counters_last_registered_index
+ \globallet\currentfloatattribute \m_strc_counters_last_registered_attribute
+ \globallet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize
+ \fi
+ %
+ \global\setfalse\usesamefloatnumber % one shot
+ % check float box
+ \strc_floats_set_natural_dimensions\nextbox
+ \global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}% can be anything so no pack
+ \strc_floats_set_natural_dimensions\floatbox
+ \ifdim\htdp\floatbox=\zeropoint
+ \showmessage\m!floatblocks{11}\empty
+ \global\setbox\floatbox\vpack
+ {\dostarttagged\t!floatcontent\empty
+ \strc_floats_place_empty_box
+ \dostoptagged}%
+ \fi
+ % deal with lack of caption
+ \global\setbox\floatbox\vpack \floatcaptionattribute
+ {\doifelsemainfloatbody\currentfloatsynchronize\donothing
+ \unvbox\floatbox
+ \ifnofloatcaption
+ \vss
+ \fi}% gets rid of the depth (unless tabulate)
+ \iftrialtypesetting\strc_counters_restore\currentfloatcounter\fi
+ \egroup
+ % place the float
+ \strc_floats_set_box
+ \strc_floats_get_box
+ \global\insidefloatfalse}
+
+\newdimen\availablefloatwidth
+\newdimen\availablefloatheight
+
+\def\strc_floats_set_local_hsize
+ {\ifconditional\c_page_floats_center_box_local
+ % also available check here?
+ \seteffectivehsize
+ \hsize\localhsize
+ \else
+ \doifinset\v!margin\floatlocation % brr, really needed! see wm will be redone
+ {\hsize\namedmarginblockparameter\empty\c!width}%
+ \fi
+ \edef\p_availablewidth {\floatparameter\c!availablewidth }%
+ \edef\p_availableheight{\floatparameter\c!availableheight}%
+ \availablefloatwidth \ifx\p_availablewidth \empty\hsize\else\p_availablewidth \relax\fi
+ \availablefloatheight\ifx\p_availableheight\empty\vsize\else\p_availableheight\relax\fi}
+
+\ifdefined\everyinsidefloat \else \newevery \everyinsidefloat \relax \fi
+
+\appendtoks
+ \everyinsidefloat\emptytoks % in case it's called earlier
+ \strc_float_load_data
+\to \everyinsidefloat
+
+\def\doifelserightpagefloat
+ {\ifdoublesided
+ \ifsinglesided
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\doifelseoddpagefloat
+ \fi
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifelseoddpagefloat
+ {\ifodd\purenumber\strc_float_realpage\space
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifrightpagefloatelse\doifelserightpagefloat
+\let\doifoddpagefloatelse \doifelseoddpagefloat
+
+\appendtoks
+ \let\rightorleftpageaction\doifelserightpagefloat
+\to \everyinsidefloat
+
+% \let\movesidefloat\gobbleoneargument
+
+% new : \place...[leftmargin,-2*line]; we need to catch fxtb:2*3
+% watch out: line alone aligns on the line ! ! !
+
+\unexpanded\def\movesidefloat[#settings]% (-)n*line|x=,y=
+ {\global\d_page_sides_downshift \zeropoint
+ \global\d_page_sides_extrashift\zeropoint
+ \doifelseassignment{#settings}%
+ {\begingroup
+ \setupcurrentfloat[\c!x=\zeropoint,\c!y=\zeropoint,#settings]%
+ \ifgridsnapping
+ \getnoflines{\floatparameter\c!y}%
+ \global\d_page_sides_downshift\noflines\lineheight
+ \else
+ \global\d_page_sides_downshift\floatparameter\c!y
+ \fi
+ \global\d_page_sides_extrashift\floatparameter\c!x
+ \endgroup}
+ {\movedownsidefloat[#settings]}}
+
+\installcorenamespace{floatmovement}
+
+\setvalue{\??floatmovement \v!line}{\strc_floats_move_down_line+}
+\setvalue{\??floatmovement+\v!line}{\strc_floats_move_down_line+}
+\setvalue{\??floatmovement-\v!line}{\strc_floats_move_down_line-}
+\setvalue{\??floatmovement \v!hang}{\strc_floats_move_down_hang\plusone}
+\setvalue{\??floatmovement+\v!hang}{\strc_floats_move_down_hang\plusone}
+\setvalue{\??floatmovement-\v!hang}{\strc_floats_move_down_hang\minusone}
+
+\setvalue{\??floatmovement-2*\v!line}{\strc_floats_move_down_line{-2}}
+\setvalue{\??floatmovement+2*\v!line}{\strc_floats_move_down_line{2}}
+\setvalue{\??floatmovement 2*\v!line}{\strc_floats_move_down_line{2}}
+
+\unexpanded\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}}
+
+\def\strc_floats_move_down#setting%
+ {\csname\??floatmovement
+ \ifcsname\??floatmovement#setting\endcsname#setting\fi
+ \endcsname}
+
+\def\strc_floats_move_down_line#sign%
+ {\if!!donea \else
+ \global\d_page_sides_downshift\zeropoint
+ \!!doneatrue
+ \fi
+ \global\advance\d_page_sides_downshift#sign\lineheight}
+
+\def\strc_floats_move_down_hang#lines%
+ {\if!!doneb \else
+ \global\c_page_sides_n_of_lines\zerocount
+ \!!donebtrue
+ \fi
+ \global\advance\c_page_sides_n_of_lines#lines\relax}
+
+\unexpanded\def\movedownsidefloat[#settings]% already in core
+ {\doifnotinstring{:}{#settings}
+ {\begingroup
+ \!!doneafalse
+ \!!donebfalse
+ \normalexpanded{\dorepeatwithcommand[#settings]}\strc_floats_move_down
+ \endgroup}}
+
+\unexpanded\def\hangsidefloat[#number]%
+ {\global\c_page_sides_n_of_lines#number\relax}
+
+\def\strc_floats_set_extra_action#rightpagelocation#leftpagelocation%
+ {\rightorleftpageaction
+ {\let\extrafloatlocation#rightpagelocation}%
+ {\let\extrafloatlocation#leftpagelocation}}
+
+\let\extrafloatlocation\empty
+
+\installcorenamespace{extrafloataction}
+
+\setvalue{\??extrafloataction \v!inner}#1{\strc_floats_set_extra_action\v!left \v!right}
+\setvalue{\??extrafloataction \v!outer}#1{\strc_floats_set_extra_action\v!right \v!left}
+\setvalue{\??extrafloataction\v!innermargin}#1{\strc_floats_set_extra_action\v!leftmargin \v!rightmargin}
+\setvalue{\??extrafloataction\v!outermargin}#1{\strc_floats_set_extra_action\v!rightmargin\v!leftmargin}
+\setvalue{\??extrafloataction \v!inneredge}#1{\strc_floats_set_extra_action\v!leftedge \v!rightedge}
+\setvalue{\??extrafloataction \v!outeredge}#1{\strc_floats_set_extra_action\v!rightedge \v!leftedge}
+\setvalue{\??extrafloataction \v!backspace}#1{\strc_floats_set_extra_action\v!backspace \v!cutspace}
+\setvalue{\??extrafloataction \v!cutspace}#1{\strc_floats_set_extra_action\v!cutspace \v!backspace}
+%setvalue{\??extrafloataction \v!margin}#1{\strc_floats_set_extra_action\v!cutspace \v!backspace}
+\setvalue{\??extrafloataction \v!left}#1{\strc_floats_set_extra_action\v!left \v!left}
+\setvalue{\??extrafloataction \v!right}#1{\strc_floats_set_extra_action\v!right \v!right}
+\setvalue{\??extrafloataction \v!line}#1{} % only -n*line is handled (see ***)
+\setvalue{\??extrafloataction \s!unknown}#1{\movedownsidefloat[#1]}
+
+\def\strc_floats_check_extra_actions % less tracingthis way ....
+ {\doifnotinset\v!text\floatlocation % fuzzy, text overloads left, since then it's a directive
+ {\let\extrafloatlocation\empty
+ % \d_page_sides_downshift will be reset afterwards, and can
+ % already be set at this point
+ \processcommacommand[\floatlocation]\strc_floats_check_extra_actions_step
+ \ifx\extrafloatlocation\empty \else
+ \edef\floatlocation{\extrafloatlocation,\floatlocation}%
+ \setfloatmethodvariables\floatlocation
+ \fi}}
+
+\def\strc_floats_check_extra_actions_step#step%
+ {\csname\??extrafloataction
+ \ifcsname\??extrafloataction#step\endcsname#step\else\s!unknown\fi
+ \endcsname{#step}}
+
+% pas op, maxbreedte niet instellen als plaats=links/rechts
+
+\def\strc_floats_set_local_dimensions
+ {\global\d_page_sides_shift \zeropoint % duplicate
+ \global\d_page_sides_maximum\zeropoint\relax % duplicate
+ \ifdim\d_page_sides_downshift=\zeropoint\else
+ \global\setbox\floatbox\vpack
+ {\vskip\d_page_sides_downshift
+ \nointerlineskip
+ \box\floatbox}%
+ \fi
+ \edef\p_minwidth{\floatparameter\c!minwidth}%
+ \ifx\p_minwidth\empty
+ % nothing
+ \else
+ \scratchwidth\p_minwidth\relax
+ \ifdim\wd\floatbox<\scratchwidth
+ \strc_floats_realign_floatbox_horizontal_two
+ \fi
+ \fi
+ % we can also support edges .. in that case no common but a fast loop
+ \doifelseinset\v!hanging\floatlocation
+ {\doifelsecommon{\v!inleft,\v!leftmargin}\floatlocation
+ {\let\p_maxwidth\leftmarginwidth}%
+ {\doifelsecommon{\v!inright,\v!rightmargin}\floatlocation
+ {\let\p_maxwidth\rightmarginwidth}%
+ {\edef\p_maxwidth{\floatparameter\c!maxwidth}}}}%
+ {\edef\p_maxwidth{\floatparameter\c!maxwidth}}%
+ \ifx\p_maxwidth\empty
+ % nothing
+ \else
+ \scratchwidth\p_maxwidth\relax
+ \ifdim\wd\floatbox>\scratchwidth
+ \doifelsecommon{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}\floatlocation
+ {\global\d_page_sides_maximum\scratchwidth}
+ {\doifelsecommon{\v!right,\v!left}\floatlocation
+ \strc_floats_realign_floatbox_horizontal_one
+ \strc_floats_realign_floatbox_horizontal_two}%
+ \fi
+ \fi}
+
+\def\strc_floats_realign_floatbox_horizontal_one
+ {\global\setbox\floatbox\hpack to \scratchwidth
+ {\doifnotinset\v!right\floatlocation\hss
+ \box\floatbox
+ \doifnotinset\v!left \floatlocation\hss}}
+
+\def\strc_floats_realign_floatbox_horizontal_two
+ {\global\setbox\floatbox\hpack to \scratchwidth
+ {\doifnot{\floatparameter\c!location}\v!left \hss
+ \box\floatbox
+ \doifnot{\floatparameter\c!location}\v!right\hss}}
+
+\unexpanded\def\placefloats
+ {\page_otr_command_flush_floats}
+
+\newdimen\d_strc_floats_margin
+\newdimen\d_strc_floats_top
+\newdimen\d_strc_floats_bottom
+
+\def\strc_floats_calculate_skip#target#skip%
+ {\edef\askedfloatskip{#skip}%
+ \ifx\askedfloatskip\empty
+ \global#target\zeropoint
+ \else\ifx\askedfloatskip\v!none
+ \global#target\zeropoint
+ \else
+ \setbox\scratchbox\vbox{\whitespace\blank[\askedfloatskip]}% todo: move whitespace inside blank
+ \global#target\ht\scratchbox
+ \fi\fi}
+
+\def\strc_floats_calculate_skips
+ {\begingroup
+ \strc_floats_calculate_skip\d_strc_floats_top {\rootfloatparameter\c!spacebefore }%
+ \strc_floats_calculate_skip\d_strc_floats_bottom {\rootfloatparameter\c!spaceafter }%
+ \strc_floats_calculate_skip\d_page_sides_topskip {\rootfloatparameter\c!sidespacebefore}%
+ \strc_floats_calculate_skip\d_page_sides_bottomskip{\rootfloatparameter\c!sidespaceafter }%
+ \global\d_strc_floats_margin \rootfloatparameter\c!margin
+ \global\d_page_sided_leftshift \floatparameter \c!leftmargindistance
+ \global\d_page_sided_rightshift \floatparameter \c!rightmargindistance
+ \global\c_page_floats_n_of_top \rootfloatparameter\c!ntop
+ \global\c_page_floats_n_of_bottom\rootfloatparameter\c!nbottom
+ \endgroup}
+
+\unexpanded\def\betweenfloatblanko % assumes that spaceafter is present
+ {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,....
+
+% keep as old 1
+%
+% \unexpanded\def\doplacefloatbox % used elsewhere
+% {%\forgetall % NO
+% \whitespace
+% \blank[\rootfloatparameter\c!spacebefore]
+% \page_otr_command_flush_float_box
+% \blank[\rootfloatparameter\c!spaceafter]}
+%
+% keep as old 2
+%
+% \unexpanded\def\doplacefloatbox % used elsewhere
+% {%\forgetall % NO
+% \whitespace
+% \blank[\rootfloatparameter\c!spacebefore]
+% \nointerlineskip
+% \flushnotes % new per 2014-05-29 : todo: move them up in the mvl
+% \nointerlineskip
+% \page_otr_command_flush_float_box
+% \nointerlineskip
+% \blank[\rootfloatparameter\c!spaceafter]}
+
+\def\strc_floats_apply_skip#1%
+ {\edef\m_space{\rootfloatparameter#1}%
+ \ifx\m_space\empty \else\ifx\m_space\v!none \else
+ \directvspacing\m_space
+ \fi\fi}
+
+\unexpanded\def\doplacefloatbox % used elsewhere
+ {%\forgetall % NO
+ \whitespace
+ \strc_floats_apply_skip\c!spacebefore
+ \nointerlineskip
+ \flushnotes % new per 2014-05-29 : todo: move them up in the mvl
+ \nointerlineskip
+ \page_otr_command_flush_float_box
+ % \nointerlineskip % interferes with depth of caption
+ \strc_floats_apply_skip\c!spaceafter}
+
+% test case:
+%
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=0.9\textheight,color=green]}
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.0\textheight,color=green]}
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.1\textheight,color=green]}
+
+% the [#1] will go away
+
+\def\page_one_place_float_text % this macro should be defined elsewhere
+ {%\checkwaitingfloats\floatlocationmethod
+ % todo: check if #1 is indeed \floatlocation or maybe more
+ \global\floatwidth \wd\floatbox
+ \global\floatheight \ht\floatbox % forget about the depth
+ \global\floattextwidth\dimexpr\hsize-\floatwidth-\rootfloatparameter\c!margin\relax
+ \edef\floatlocation{\floatlocationmethod}% to be sure .. why
+ \doifelseinset\v!tall\floatlocationmethod
+ {\floattextheight\dimexpr\pagegoal-\pagetotal-\bigskipamount\relax % ugly, this bigskip
+ \ifdim\floattextheight>\textheight
+ \floattextheight\textheight
+ \fi
+ \boxmaxdepth\zeropoint\relax % toegevoegd
+ \ifdim\floattextheight<\floatheight
+ \floattextheight\floatheight
+ \fi
+ \setbox\floattext\vbox to \floattextheight}
+ {\setbox\floattext\vbox}%
+ \bgroup
+ \forgetall
+ \setupblank
+ \setupwhitespace % new, also needed for footnotes
+ \blank[\v!disable]
+ \hsize\floattextwidth
+ \ignorespaces}
+
+\def\strc_floats_stop_text_indeed
+ {\egroup
+ \doifnotinset\v!tall\floatlocation
+ {\floattextheight\ifdim\ht\floattext<\floatheight\floatheight\else\ht\floattext\fi}%
+ \setbox\floatbox\vpack to \floattextheight
+ {\hsize\floatwidth
+ \doifelseinset\v!both\floatlocation
+ {\doifelseinset\v!low\floatlocation
+ {\vfill\box\floatbox}
+ {\doifelseinset\v!middle\floatlocation
+ {\vfill\box\floatbox\vfill}
+ {\box\floatbox\vfill}}}
+ {\box\floatbox\vfill}}%
+ \setbox\floattext\vpack to \floattextheight
+ {\hsize\floattextwidth
+ \doifelseinset\v!low\floatlocation
+ {\vfill
+ \box\floattext
+ \doifinset\c!offset\floatlocation{\whitespace\blank}}
+ {\doifelseinset\v!middle\floatlocation
+ {\vfill
+ \box\floattext
+ \vfill}
+ {\doifinset\v!offset\floatlocation{\whitespace\blank}%
+ \box\floattext
+ \vfill}}}%
+ \doifelseinset\v!right\floatlocation
+ {\setbox\floatbox\hpack to \hsize
+ {\box\floattext
+ \hfill
+ \box\floatbox}}
+ {\setbox\floatbox\hpack to \hsize
+ {\box\floatbox
+ \hfill
+ \box\floattext}}%
+ \baselinecorrection
+ \whitespace
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \doifnotinset\v!tall\floatlocation
+ {\dp\floatbox\openstrutdepth}% dp\strutbox}% % toegevoegd
+ \box\floatbox
+ \dostoptagged
+ \blank[\rootfloatparameter\c!spaceafter]%
+ \strc_floats_end_text_group
+ \page_floats_report_total}
+
+\def\borderedfloatbox
+ {\begingroup
+ \setupcurrentfloat[\c!location=\v!normal,\c!width=\v!fit,\c!height=\v!fit]%
+ \inheritedfloatframed{\box\floatbox}%
+ \endgroup}
+
+% minwidth=fit,width=max : no overshoot, as wide as graphic
+
+\def\strc_floats_align_content_indeed
+ {\alignstrutmode\zerocount
+ \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
+ {\shiftalignedline
+ {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}%
+ {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}}%
+ \alignedline{\floatparameter\c!location}\v!middle}
+
+\def\strc_floats_align_caption_indeed
+ {\alignstrutmode\zerocount
+ \shiftalignedline
+ {\floatcaptionparameter\c!leftmargin }{\floatcaptionparameter\c!rightmargin}%
+ {\floatcaptionparameter\c!innermargin}{\floatcaptionparameter\c!outermargin}%
+ \alignedline{\floatparameter\c!location}\v!middle}
+
+\newdimen\d_strc_floats_content
+\newdimen\d_strc_float_temp_height
+\newdimen\d_strc_float_temp_width
+
+\def\captionminwidth {15\bodyfontsize}
+\def\captionovershoot{2\emwidth}
+
+\def\strc_floats_set_page_variant
+ {\bgroup
+ \strc_floats_set_local_hsize
+ \ifcase\c_strc_floats_rotation\else
+ \swapdimens\hsize\vsize
+ \fi
+ \forgetall
+ \postponenotes
+ \dontcomplain
+ \setbox\b_strc_floats_content\vpack{\borderedfloatbox}%
+ \let\strc_floats_align_content\strc_floats_align_content_indeed
+ \let\strc_floats_align_caption\strc_floats_align_caption_indeed
+ \strc_floats_check_caption_content
+ \d_strc_floats_content\wd\b_strc_floats_content
+ \ifcase\floatparameter\c!method
+ % nothing
+ \or
+ % automatic
+ \ifnofloatcaption
+ \strc_floats_prepare_no_caption
+ %\page_backgrounds_add_local_to_box\floatbox % was \doglobal but not needed
+ \else
+ % todo: installable maken, variant/method=auto vs macro
+ \strc_floats_prepare_page_caption
+ %\page_backgrounds_add_local_to_box\b_strc_floats_content
+ \setbox\b_strc_floats_caption\hbox % text
+ {\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}%
+ \moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
+ %\page_backgrounds_add_local_to_box\b_strc_floats_caption
+ \strc_floats_build_box
+ \fi
+ \or
+ % semi automatic
+ \or
+ % manual
+ \fi
+ \ifcase\c_strc_floats_rotation
+ \doifnotinset\v!margin\floatlocation % brr, really needed! see wm
+ {\postcenterfloatbox\d_strc_floats_content}%
+ \else
+ \global\setbox\floatbox\vpack
+ {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\box\floatbox}}%
+ \fi
+ \egroup}
+
+\def\strc_floats_prepare_no_caption
+ {\global\setbox\floatbox\vpack % pas op als wd groter dan hsize
+ {\ifinsidecolumns\ifdim\wd\b_strc_floats_content>\hsize
+ \let\strc_floats_align_content\relax
+ \fi\fi
+ \strc_floats_align_content{\copy\b_strc_floats_content}}}
+
+\def\strc_floats_prepare_page_caption
+ {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}%
+ \edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}%
+ \edef\p_strc_floats_caption_minwidth{\floatcaptionparameter\c!minwidth}%
+ \edef\p_strc_floats_caption_align {\floatcaptionparameter\c!align}%
+ \dostarttagged\t!floatcaption\empty
+ \ifx\p_strc_floats_caption_location\v!top
+ \strc_floats_prepare_page_caption_top_bottom
+ \else\ifx\p_strc_floats_caption_location\v!bottom
+ \strc_floats_prepare_page_caption_top_bottom
+ \else\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_side_auto_caption
+ \else\ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_side_auto_caption
+ \else
+ \strc_floats_prepare_side_width_caption
+ \fi\fi\fi\fi
+ \dostoptagged}
+
+\def\strc_floats_prepare_page_caption_top_bottom
+ {\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_page_caption_top_bottom_fit_max
+ \else\ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_page_caption_top_bottom_fit_max
+ \else
+ \strc_floats_prepare_side_width_caption % new, special effects (see icare)
+ \fi\fi}
+
+\def\strc_floats_prepare_page_caption_top_bottom_fit_max
+ {\ifx\p_strc_floats_caption_minwidth\v!fit
+ \ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_stack_caption_max
+ \else\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption
+ \ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_stack_caption_auto
+ \else
+ \strc_floats_prepare_stack_caption_width
+ \fi
+ \else
+ \strc_floats_prepare_stack_caption_min
+ \fi\fi
+ \else
+ \strc_floats_prepare_stack_caption_fixed
+ \fi}
+
+\def\strc_floats_caption_set_align
+ {\normalexpanded{\setupalign[\v!reset,\p_strc_floats_caption_align]}}
+
+\def\strc_floats_prepare_side_auto_caption
+ {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax
+ \ifdim\wd\b_strc_floats_caption>\scratchdimen
+ \ifdim\wd\b_strc_floats_caption<1.3\scratchdimen
+ \scratchdimen0.8\scratchdimen
+ \fi
+ \fi
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\scratchdimen
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_side_width_caption
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!width
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_stack_caption_fixed
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!minwidth % special effects
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_stack_caption_max
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_stack_caption_width
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!width
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_stack_caption_min
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \ifx\p_strc_floats_caption_align\empty
+ \raggedcenter % on purpose overloads align !
+ \fi
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_stack_caption_auto
+ {\ifx\p_strc_floats_caption_align\empty \else
+ \doifnotinset\v!middle\p_strc_floats_caption_align{\let\captionovershoot\!!zeropoint}%
+ \fi
+ \edef\captionhsize{\the\wd\b_strc_floats_content}%
+ \scratchwidth\floatcaptionparameter\c!maxwidth\relax
+ \ifdim\captionhsize>\scratchwidth
+ % float is wider than \hsize
+ \setbox\b_strc_floats_caption\vbox
+ {\settrialtypesetting
+ \strc_floats_caption_set_align
+ \hsize\scratchwidth
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ \ifdim\ht\scratchbox>\lineheight % more lines
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\dimexpr\captionhsize-\captionovershoot\relax
+ \ifdim\hsize<\captionminwidth\relax
+ \hsize\scratchwidth
+ \fi
+ \strc_floats_make_complete_caption}%
+ \else
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\scratchwidth
+ \strc_floats_make_complete_caption}%
+ \fi
+ \else
+ % float is smaller of equal to \hsize
+ \ifdim\captionhsize<\captionminwidth\relax
+ \scratchdimen\captionminwidth % float smaller than min width
+ \edef\captionhsize{\the\scratchdimen}%
+ \fi
+ \setbox\scratchbox\vbox % test with overshoot
+ {\settrialtypesetting
+ \scratchdimen\dimexpr\captionhsize+\captionovershoot+3\emwidth\relax % 3em is an average word length
+ \ifdim\scratchdimen<\hsize
+ \hsize\scratchdimen
+ \fi
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ \ifdim\ht\scratchbox>\lineheight
+ % at least an average word longer than a line
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \scratchdimen\dimexpr\captionhsize+\captionovershoot\relax
+ \ifdim\scratchdimen<\hsize
+ \hsize\scratchdimen
+ \fi
+ \strc_floats_make_complete_caption}%
+ \else\ifx\p_strc_floats_caption_align\empty
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \raggedcenter % overloads
+ \strc_floats_make_complete_caption}%
+ \else
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \strc_floats_make_complete_caption}%
+ \fi\fi
+ \fi}
+
+\def\strc_floats_between_stack
+ {\endgraf
+ \nointerlineskip
+ \floatcaptionparameter\c!inbetween
+ \endgraf}
+
+\def\strc_floats_build_box_default % done
+ {\strc_floats_align_content{\box\b_strc_floats_content}}
+
+\def\strc_floats_build_box_next_right#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \doifnotinset\v!hang{\floatcaptionparameter\c!location}
+ {\dotfskip{\floatcaptionparameter\c!distance}}%
+ \vbox to\d_strc_float_temp_height{#1}}}
+
+\def\strc_floats_build_box_next_left#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % 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}
+ {\dotfskip{\floatcaptionparameter\c!distance}}%
+ \box\b_strc_floats_content}}
+
+\def\strc_floats_build_box_next_outer
+ {\doifelserightpagefloat\strc_floats_build_box_next_right\strc_floats_build_box_next_left}
+
+\def\strc_floats_build_box_next_inner
+ {\doifelserightpagefloat\strc_floats_build_box_next_left\strc_floats_build_box_next_right}
+
+\def\strc_floats_build_box_next_right_hang#1%
+ {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \vbox to\d_strc_float_temp_height{#1}}}
+
+\def\strc_floats_build_box_next_left_hang#1%
+ {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
+ \vbox to\d_strc_float_temp_height{#1}%
+ \box\b_strc_floats_content}}
+
+\def\strc_floats_build_box_next_right_margin_indeed#1#2%
+ {\ifconditional\c_strc_floats_par_float
+ \hpack\bgroup
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}%
+ \egroup
+ \else
+ \begingroup
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \everyrightofalignedline{\hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}}%
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \endgroup
+ \fi}
+
+\def\strc_floats_build_box_next_left_margin_indeed#1#2%
+ {\ifconditional\c_strc_floats_par_float
+ \hpack\bgroup
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}%
+ \box\b_strc_floats_content
+ \egroup
+ \else
+ \begingroup
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}}%
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \endgroup
+ \fi}
+
+\def\strc_floats_build_box_next_right_margin
+ {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}
+
+\def\strc_floats_build_box_next_left_margin
+ {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance }
+
+\def\strc_floats_build_box_next_outer_margin
+ {\doifelserightpagefloat
+ {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}
+ {\strc_floats_build_box_next_left_margin_indeed \rightmargindistance}}
+
+\def\strc_floats_build_box_next_inner_margin
+ {\doifelserightpagefloat
+ {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance}
+ {\strc_floats_build_box_next_right_margin_indeed\leftmargindistance}}
+
+\def\strc_floats_build_box_next % beware, we first check on left/rightmargin because there can be left/right also
+ {\let\next\strc_floats_build_box_next_left
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin,
+ \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin,
+ \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin,
+ \v!rightmargin=>\let\next\strc_floats_build_box_next_right_margin,
+ \v!lefthanging=>\let\next\strc_floats_build_box_next_left_hang,
+ \v!righthanging=>\let\next\strc_floats_build_box_next_right_hang,
+ \v!outer=>\let\next\strc_floats_build_box_next_outer,
+ \v!inner=>\let\next\strc_floats_build_box_next_inner,
+ \v!left=>\let\next\strc_floats_build_box_next_left,
+ \v!right=>\let\next\strc_floats_build_box_next_right]%
+ \next}
+
+\def\strc_floats_build_box_side
+ {\ifconditional\c_strc_floats_par_float
+ \let\next\strc_floats_build_box_high
+ \else
+ \let\next\strc_floats_build_box_middle
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!low=>\let\next\strc_floats_build_box_low,
+ \v!middle=>\let\next\strc_floats_build_box_middle,
+ \v!high=>\let\next\strc_floats_build_box_high]%
+ \fi
+ \next}
+
+\def\strc_floats_flush_right_caption_hang
+ {\hsmash{\rlap{\dotfskip{\floatcaptionparameter\c!distance}\box\b_strc_floats_caption}}}
+
+\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
+ {\strc_floats_flush_right_caption_hang}
+ {\doifelseinset\v!lefthanging\p_strc_floats_caption_location
+ {\strc_floats_flush_left_caption_hang}
+ {\doifelseinset\v!hang\p_strc_floats_caption_location
+ {\doifelseinset\v!outer\p_strc_floats_caption_location
+ {\doifelserightpagefloat{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}}
+ {\doifelseinset\v!right\floatcaptiondirectives
+ {\strc_floats_flush_right_caption_hang}
+ {\strc_floats_flush_left_caption_hang}}}
+ {\box\b_strc_floats_caption}}}}
+
+\def\strc_floats_build_box_high
+ {\strc_floats_build_box_next{\strc_floats_between_stack\strc_floats_flush_caption_hang\vfill}}
+
+\def\strc_floats_build_box_low
+ {\strc_floats_build_box_next{\vfill\strc_floats_flush_caption_hang\strc_floats_between_stack}}
+
+\def\strc_floats_build_box_middle
+ {\strc_floats_build_box_next{\vfill\box\b_strc_floats_caption\vfill}}
+
+% \definefloat
+% [lefty][lefties][figure]
+% \setupfloat
+% [lefty]
+% [default=left,
+% rightmargindistance=-2cm,
+% leftmargindistance=-2cm]
+% \setupcaption
+% [lefty]
+% [location={bottom,overlay}]
+%
+% \starttext
+% \placelefty{}{} \input tufte \input tufte
+% \placelefty{}{} \input tufte \input tufte
+% \stoptext
+
+\def\strc_floats_build_box_top_stack_normal_overlay
+ {\vbox to \ht\b_strc_floats_content{\vss\strc_floats_build_box_top_stack_normal_content}}
+
+\def\strc_floats_build_box_top_stack_normal_content
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+ \strc_floats_between_stack
+ \hpack{\hbox{\box\b_strc_floats_content}}%
+ \else
+ \page_otr_command_set_float_hsize
+ \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}
+ \strc_floats_between_stack
+ \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
+ \fi}
+
+\def\strc_floats_build_box_bottom_stack_normal_overlay
+ {\vbox to \ht\b_strc_floats_content{\strc_floats_build_box_bottom_stack_normal_content\vss}}
+
+\def\strc_floats_build_box_bottom_stack_normal_content
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \hpack{\hpack{\box\b_strc_floats_content}}%
+ \strc_floats_between_stack
+ \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+ \else
+ \page_otr_command_set_float_hsize
+ \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
+ \strc_floats_between_stack
+ \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
+ \fi}
+
+\def\strc_floats_build_box_top_stack_normal
+ {\doifelseinset\v!overlay{\floatcaptionparameter\c!location}
+ \strc_floats_build_box_top_stack_normal_overlay
+ \strc_floats_build_box_top_stack_normal_content}
+
+\def\strc_floats_build_box_bottom_stack_normal
+ {\doifinset\v!overlay{\floatcaptionparameter\c!location}
+ \strc_floats_build_box_bottom_stack_normal_overlay
+ \strc_floats_build_box_bottom_stack_normal_content}
+
+\def\strc_floats_build_box_top_stack_grid
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vbox
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \vss\strc_floats_between_stack
+ \hpack{\box\b_strc_floats_content}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \vss\strc_floats_between_stack
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \fi}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight{\unvbox\scratchbox}}
+
+\def\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
+ \ifconditional\c_strc_floats_par_float
+ \hpack{\box\b_strc_floats_content}%
+ \vss\strc_floats_between_stack
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \vss\strc_floats_between_stack
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \fi}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight{\unvbox\scratchbox}}
+
+\def\strc_floats_build_box_top_stack_stretch
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vpack
+ {\strc_floats_align_caption{\copy\b_strc_floats_caption}%
+ \strc_floats_align_content{\copy\b_strc_floats_content}}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight % pack ?
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \vss\strc_floats_between_stack\vss
+ \hpack{\box\b_strc_floats_content}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \vss\strc_floats_between_stack\vss
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \fi}}
+
+\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 }%
+ \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
+ \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}
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \vss\strc_floats_between_stack\vss
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \fi}}
+
+\def\strc_floats_build_box_top
+ {\let\next\strc_floats_build_box_top_stack_normal
+ \processfirstactioninset[\floatcaptionparameter\c!location]
+ [ \v!grid=>\let\next\strc_floats_build_box_top_stack_grid,
+ \v!stretch=>\let\next\strc_floats_build_box_top_stack_stretch]%
+ \next}
+
+\def\strc_floats_build_box_bottom
+ {\let\next\strc_floats_build_box_bottom_stack_normal
+ \processfirstactioninset[\floatcaptionparameter\c!location]
+ [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid,
+ \v!stretch=>\let\next\strc_floats_build_box_bottom_stack_stretch]%
+ \next}
+
+\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}}
+\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}}
+
+\unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}}
+
+\def\strc_floats_build_box
+ {\global\setbox\floatbox\vbox % pack ? probably not
+ {\strc_floats_set_local_hsize
+ \forgetall
+ \let\floatcaptionarrangement\s!default
+ \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step
+ \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname
+ \lastnamedcs
+ \else
+ \strc_floats_build_box_default
+ \fi}}
+
+% \def\strc_floats_build_box_step#1%
+% {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}
+
+\def\strc_floats_build_box_step#1%
+ {\ifcsname\??floatbuilder#1\endcsname
+ \def\floatcaptionarrangement{#1}% \let\floatcaptionarrangement\commalistelement
+ \quitcommalist
+ \fi}
+
+\def\strc_floats_locate_text_float
+ {\let\next\strc_floats_align_caption
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!left=>\let\next\strc_floats_relocate_caption_left,
+ \v!right=>\let\next\strc_floats_relocate_caption_right,
+ \v!inner=>\doifelserightpagefloat{\let\next\strc_floats_relocate_caption_left }{\let\next\strc_floats_relocate_caption_right},
+ \v!outer=>\doifelserightpagefloat{\let\next\strc_floats_relocate_caption_right}{\let\next\strc_floats_relocate_caption_left }]%
+ \next}
+
+\installfloatboxbuilder \v!none \strc_floats_build_box_default
+\installfloatboxbuilder \s!default \strc_floats_build_box_default
+\installfloatboxbuilder \v!high \strc_floats_build_box_high
+\installfloatboxbuilder \v!low \strc_floats_build_box_low
+\installfloatboxbuilder \v!middle \strc_floats_build_box_middle
+
+\installfloatboxbuilder \v!left \strc_floats_build_box_side
+\installfloatboxbuilder \v!right \strc_floats_build_box_side
+
+\installfloatboxbuilder \v!top \strc_floats_build_box_top
+\installfloatboxbuilder \v!bottom \strc_floats_build_box_bottom
+
+% \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=]
+%
+% \starttext
+% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
+% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
+% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
+% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
+% \stoptext
+
+% This might move to page-flt:
+
+\newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change
+
+\setnewconstant\postcenterfloatmethod\plusone
+
+\def\postcenterfloatbox#1%
+ {\scratchdimen
+ \ifcase\postcenterfloatmethod
+ #1% \wd\floatbox
+ \or\ifinsidecolumns
+ \ifpostponecolumnfloats\makeupwidth\else#1\fi
+ \else\ifdim#1>\hsize
+ \hsize
+ \else
+ \wd\floatbox
+ \fi\fi\fi
+ \global\setbox\floatbox\hbox to \scratchdimen
+ % {\hfill\box\floatbox\hfill}} % geen \hss, gaat mis in kolommen !
+ % {\hss \box\floatbox\hss }} % wel \hss, anders mis in colset
+ {\ifconditional\c_page_floats_center_box_global
+ \donetrue
+ \else\ifconditional\c_page_floats_center_box_local
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdim\scratchdimen>\effectivehsize
+ \donefalse
+ \fi
+ \hss\ifdone\hskip\effectiveleftskip\fi
+ \box\floatbox
+ \ifdone\hskip\effectiverightskip\fi\hss}}
+
+\def\strc_floats_set_paragraph_variant
+ {\bgroup
+ \forgetall
+ \postponenotes
+ \dontcomplain
+ \setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
+ %\page_backgrounds_add_local_to_box\b_strc_floats_content
+ \ifnofloatcaption
+ \global\setbox\floatbox\vpack{\box\b_strc_floats_content}%
+ \else
+ \strc_floats_check_caption_content
+ \strc_floats_prepare_side_caption
+ \setbox\b_strc_floats_caption\hbox{\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}%
+ \moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
+ %\page_backgrounds_add_local_to_box\b_strc_floats_caption
+ \strc_floats_build_side_box
+ \fi
+ \egroup}
+
+\def\strc_floats_prepare_side_caption
+ {\dostarttagged\t!floatcaption\empty
+ \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
+ \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
+ \ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_side_caption_max
+ \else\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_side_caption_fit
+ \else
+ \strc_floats_prepare_side_caption_width
+ \fi\fi
+ \dostoptagged}
+
+% these could be \??floatpreparesidecaption
+
+% \setupfloat[figure][location=left]
+% \setupcaption[figure][width=max]
+%
+% \placefigure{my figure caption my figure caption}{\framed[width=4cm,height=1cm]{}} \input tufte
+% \placefigure{my figure caption} {\framed[width=4cm,height=1cm]{}} \input tufte
+
+\def\strc_floats_prepare_side_caption_max
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_side_caption_fit % or center when smaller
+ {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
+ \setbox\b_strc_floats_caption\vbox
+ {\forgetall % needed?
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}%
+ \else
+ \setbox\b_strc_floats_caption\hpack to \wd\b_strc_floats_content
+ {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
+ \fi}
+
+\def\strc_floats_prepare_side_caption_width
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+% % maybe (but then also prepare_page that way):
+%
+% \installcorenamespace{floatpreparesidecaption}
+%
+% \def\strc_floats_prepare_side_caption
+% {\dostarttagged\t!floatcaption\empty
+% \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
+% \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
+% \expandnamespacemacro\??floatpreparesidecaption\p_strc_floats_caption_width\s!unknown
+% \dostoptagged}
+%
+% \setvalue{\??floatpreparesidecaption\v!max}%
+% {\setbox\b_strc_floats_caption\vbox
+% {\strc_floats_caption_set_align
+% \hsize\wd\b_strc_floats_content
+% \strc_floats_make_complete_caption}}
+%
+% \setvalue{\??floatpreparesidecaption\v!fit}%
+% {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
+% \setbox\b_strc_floats_caption\vbox
+% {\forgetall % needed?
+% \hsize\wd\b_strc_floats_content
+% \strc_floats_make_complete_caption}%
+% \else
+% \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content
+% {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
+% \fi}
+%
+% \setvalue{\??floatpreparesidecaption\s!unknown}%
+% {\setbox\b_strc_floats_caption\vbox
+% {\strc_floats_caption_set_align
+% \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content
+% \strc_floats_make_complete_caption}}
+
+\def\strc_floats_locate_side_float#1%
+ {\begingroup
+ \alignstrutmode\zerocount
+ \hsize\d_strc_float_temp_width \forgetall
+ \alignedline{\floatparameter\c!location}\v!middle{#1}%
+ \endgroup}
+
+\def\strc_floats_build_side_box
+ {\let\strc_floats_align_content\relax
+ \let\strc_floats_align_caption\relax
+ \strc_floats_build_box}
+
+\def\strc_floats_set_box % todo : \global\setbox, currently messy
+ {\ifvisible
+ \par
+ \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}%
+ \ifconditional\c_strc_floats_par_float
+ \strc_floats_set_paragraph_variant
+ \else
+ \strc_floats_set_page_variant
+ \fi
+ \strc_floats_set_local_dimensions
+ \global\advance\totalnoffloats\plusone
+ \setbox\floatbox\hpack{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently
+ \global\floatheight\htdp\floatbox
+ \global\floatwidth\wd\floatbox
+ \doifnotinset\v!margin\floatlocation % gaat namelijk nog fout
+ {\setbox\floatbox\vpack
+ {\parindent\zeropoint
+ \box\floatbox}}%
+ \wd\floatbox\floatwidth
+ \ifdim\dimexpr\floatheight+\lineheight\relax<\textheight \else
+ \global\floatheight\dimexpr\textheight-\lineheight\relax
+ \ht\floatbox\floatheight
+ \dp\floatbox\zeropoint
+ \showmessage\m!floatblocks{10}{\the\totalnoffloats}%
+ \fi
+ \fi}
+
+% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput
+
+\definefloat
+ [\v!figure]
+ [\v!figures]
+
+\definefloat
+ [\v!table]
+ [\v!tables]
+
+\setupfloat
+ [\v!table]
+ [\c!frame=\v!off]
+
+\definefloat
+ [\v!intermezzo]
+ [\v!intermezzi]
+
+\definefloat
+ [\v!graphic]
+ [\v!graphics]
+
+% float strategy, replaces some of the above macros
+
+\installcorenamespace{floatmethods}
+
+\let\floatmethod \empty % set by lua
+\let\floatlabel \empty % set by lua
+\let\floatcolumn \empty % set by lua
+\let\floatrow \empty % set by lua
+\let\forcedfloatmethod\empty % set by lua
+
+\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn
+ {\clf_analysefloatmethod{#1}}
+
+\def\somesomewherefloat[#1]%
+ {\page_floats_save_somewhere_float\s!somewhere{#1}}
+
+\def\strc_floats_get_box
+ {\ifvisible
+% \let\floatlabel \empty
+% \let\floatcolumn\empty
+% \let\floatrow \empty
+% \setfloatmethodvariables\floatlocation
+ % todo: nog algemeen otr
+% \ifdefined\OTRSETsetpreferedcolumnslot
+% \OTRSETsetpreferedcolumnslot\floatcolumn\floatrow
+% \fi
+ \ifcsname\??floatmethods\currentoutputroutine:\floatmethod\endcsname \else
+ \let\floatmethod\v!here
+ \fi
+ \ifx\forcedfloatmethod\empty \else
+ \let\floatmethod\forcedfloatmethod
+ \fi
+ % [] will go
+ \edef\floatlocationmethod{\floatmethod,\floatlocation}%
+ \csname\??floatmethods\currentoutputroutine:\floatmethod\endcsname
+ \fi}
+
+\installcorenamespace{floatsettings}
+
+\unexpanded\def\installfloatmethod#1#2#3% routine keyword handler
+ {\setvalue{\??floatmethods#1:#2}{#3}}
+
+\unexpanded\def\handlefloatmethod#1%
+ {\csname\??floatmethods\currentoutputroutine:#1\endcsname}
+
+% \unexpanded\def\installfloatmethod#1#2#3% routine keyword handler
+% {\ifcsname\??floatsettings#1:#2\endcsname \else
+% \expandafter\newtoks\csname\??floatsettings#1:#2\endcsname
+% \fi
+% \setvalue{\??floatmethods#1:#2}{#3}}
+%
+% \unexpanded\def\startfloatmethodsettings#1#2 #3\stopfloatmethodsettings
+% {\csname\??floatsettings#1:#2\endcsname\expandafter{\the\csname\??floatsettings#1:#2\endcsname#3}}
+%
+% \let\stopfloatmethodsettings\relax
+%
+% \unexpanded\def\applyfloatmethodsettings#1#2{\the\??floatsettings#1:#2\endcsname}
+
+\definesystemconstant{tblr}
+\definesystemconstant{lrtb}
+\definesystemconstant{tbrl}
+\definesystemconstant{rltb}
+\definesystemconstant{btlr}
+\definesystemconstant{lrbt}
+\definesystemconstant{btrl}
+\definesystemconstant{rlbt}
+\definesystemconstant{fxtb}
+\definesystemconstant{fxbt}
+\definesystemconstant{fixd}
+
+\installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here
+\installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force
+\installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left
+\installfloatmethod \s!singlecolumn \v!right \page_one_place_float_right
+\installfloatmethod \s!singlecolumn \v!text \page_one_place_float_text
+\installfloatmethod \s!singlecolumn \v!top \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \v!bottom \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \v!auto \page_one_place_float_auto
+\installfloatmethod \s!singlecolumn \v!margin \page_one_place_float_margin
+\installfloatmethod \s!singlecolumn \v!opposite \page_one_place_float_face
+\installfloatmethod \s!singlecolumn \v!page \page_one_place_float_page
+\installfloatmethod \s!singlecolumn \v!leftpage \page_one_place_float_leftpage
+\installfloatmethod \s!singlecolumn \v!rightpage \page_one_place_float_rightpage
+\installfloatmethod \s!singlecolumn \v!inmargin \page_one_place_float_inmargin
+\installfloatmethod \s!singlecolumn \v!inleft \page_one_place_float_leftmargin
+\installfloatmethod \s!singlecolumn \v!inright \page_one_place_float_rightmargin
+\installfloatmethod \s!singlecolumn \v!leftmargin \page_one_place_float_leftmargin
+\installfloatmethod \s!singlecolumn \v!rightmargin \page_one_place_float_rightmargin
+\installfloatmethod \s!singlecolumn \v!leftedge \page_one_place_float_leftedge
+\installfloatmethod \s!singlecolumn \v!rightedge \page_one_place_float_rightedge
+\installfloatmethod \s!singlecolumn \v!somewhere \page_one_place_float_somewhere
+\installfloatmethod \s!singlecolumn \v!backspace \page_one_place_float_backspace
+\installfloatmethod \s!singlecolumn \v!cutspace \page_one_place_float_cutspace
+\installfloatmethod \s!singlecolumn \s!tblr \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!lrtb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!tbrl \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!fxtb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!rltb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!btlr \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!lrbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!btrl \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!rlbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!fxbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!fixd \page_one_place_float_force
+
+\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here
+\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force
+%installfloatmethod \s!multicolumn \v!left
+%installfloatmethod \s!multicolumn \v!right
+%installfloatmethod \s!multicolumn \v!text
+\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top
+\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom
+%installfloatmethod \s!multicolumn \v!auto
+%installfloatmethod \s!multicolumn \v!margin
+%installfloatmethod \s!multicolumn \v!opposite
+%installfloatmethod \s!multicolumn \v!page
+%installfloatmethod \s!multicolumn \v!leftpage
+%installfloatmethod \s!multicolumn \v!rightpage
+%installfloatmethod \s!multicolumn \v!inmargin
+%installfloatmethod \s!multicolumn \v!inleft
+%installfloatmethod \s!multicolumn \v!inright
+%installfloatmethod \s!multicolumn \v!leftmargin
+%installfloatmethod \s!multicolumn \v!rightmargin
+%installfloatmethod \s!multicolumn \v!leftedge
+%installfloatmethod \s!multicolumn \v!rightedge
+%installfloatmethod \s!multicolumn \v!somewhere
+%installfloatmethod \s!multicolumn \v!backspace
+%installfloatmethod \s!multicolumn \v!cutspace
+%installfloatmethod \s!multicolumn \s!tblr
+%installfloatmethod \s!multicolumn \s!lrtb
+%installfloatmethod \s!multicolumn \s!tbrl
+%installfloatmethod \s!multicolumn \s!rltb
+%installfloatmethod \s!multicolumn \s!fxtb
+%installfloatmethod \s!multicolumn \s!btlr
+%installfloatmethod \s!multicolumn \s!lrbt
+%installfloatmethod \s!multicolumn \s!btrl
+%installfloatmethod \s!multicolumn \s!rlbt
+%installfloatmethod \s!multicolumn \s!fxbt
+%installfloatmethod \s!multicolumn \s!fixd
+
+\installfloatmethod \s!columnset \v!here \page_set_place_float_here
+\installfloatmethod \s!columnset \v!force \page_set_place_float_force
+%installfloatmethod \s!columnset \v!left
+%installfloatmethod \s!columnset \v!right
+%installfloatmethod \s!columnset \v!text
+\installfloatmethod \s!columnset \v!top \page_set_place_float_top
+\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom
+%installfloatmethod \s!columnset \v!auto
+%installfloatmethod \s!columnset \v!margin
+%installfloatmethod \s!columnset \v!opposite
+\installfloatmethod \s!columnset \v!page \page_set_place_float_page
+%installfloatmethod \s!columnset \v!leftpage
+%installfloatmethod \s!columnset \v!rightpage
+%installfloatmethod \s!columnset \v!inmargin
+%installfloatmethod \s!columnset \v!inleft
+%installfloatmethod \s!columnset \v!inright
+%installfloatmethod \s!columnset \v!leftmargin
+%installfloatmethod \s!columnset \v!rightmargin
+%installfloatmethod \s!columnset \v!leftedge
+%installfloatmethod \s!columnset \v!rightedge
+%installfloatmethod \s!columnset \v!somewhere
+%installfloatmethod \s!columnset \v!backspace
+%installfloatmethod \s!columnset \v!cutspace
+\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force
+
+%D Local floats:
+
+\installcorenamespace{localfloats}
+\installcorenamespace{localfloatstack}
+
+\installsetuponlycommandhandler \??localfloats {localfloats}
+
+\setuplocalfloats
+ [%\c!before=\blank,
+ %\c!after=\blank,
+ \c!inbetween=\blank]
+
+\initializeboxstack\??localfloatstack
+
+\newcount\c_strc_localfloats_n \let\noflocalfloats\c_strc_localfloats_n
+
+\unexpanded\def\resetlocalfloats
+ {\global\c_strc_localfloats_n\zerocount
+ \initializeboxstack\??localfloatstack}
+
+\unexpanded\def\somelocalfloat
+ {\global\advance\c_strc_localfloats_n\plusone
+ \savebox\??localfloatstack{\number\c_strc_localfloats_n}{\box\floatbox}}
+
+\unexpanded\def\getlocalfloats
+ {\dorecurse\c_strc_localfloats_n
+ {\ifnum\recurselevel=\plusone % 1\relax
+ \directlocalfloatsparameter\c!before
+ \else
+ \directlocalfloatsparameter\c!inbetween
+ \fi
+ \dontleavehmode\hpack{\foundbox\??localfloatstack\recurselevel}% \restorebox...
+ \ifnum\recurselevel=\c_strc_localfloats_n\relax
+ \directlocalfloatsparameter\c!after
+ \fi}}
+
+\unexpanded\def\flushlocalfloats
+ {\getlocalfloats
+ \resetlocalfloats}
+
+% \unexpanded\def\getlocalfloat#1%
+% {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}}% \vbox{\restorebox...}
+
+\unexpanded\def\getlocalfloat#1%
+ {\foundbox\??localfloatstack{\number#1}} % \vbox{\restorebox...}
+
+\unexpanded\def\forcelocalfloats
+ {\let\forcedfloatmethod\v!local}
+
+\installfloatmethod \s!singlecolumn \v!local \somelocalfloat
+\installfloatmethod \s!multicolumn \v!local \somelocalfloat
+\installfloatmethod \s!mixedcolumn \v!local \somelocalfloat
+\installfloatmethod \s!columnset \v!local \somelocalfloat
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ind.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-ind.mkiv
new file mode 100644
index 00000000000..2748fd684ac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ind.mkiv
@@ -0,0 +1,131 @@
+%D \module
+%D [ file=strc-ind, % was part of strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Indented Text,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Indented Text}
+
+\unprotect
+
+%D \macros
+%D {defineindentedtext,
+%D setupindentedtext}
+%D
+%D Ok, we keep it but with a different command as it all looks too
+%D much like indentation and indenting. We also assume start/stop
+%D usage or some explicit par.
+
+\installcorenamespace{indentedtext}
+
+\installcommandhandler \??indentedtext {indentedtext} \??indentedtext
+
+%D \startbuffer
+%D \defineindentedtext[one][text=one]
+%D \defineindentedtext[two][text=two]
+%D
+%D \one test test \par
+%D \subone test test \par
+%D \subtwo test test \par
+%D \subsubone test test \par
+%D
+%D \startone
+%D test test
+%D \startone
+%D test test
+%D \startone
+%D test test
+%D \stopone
+%D \starttwo
+%D test test
+%D \startone
+%D test test
+%D \stopone
+%D \stoptwo
+%D \stopone
+%D \stopone
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\newcount\c_strc_indentedtexts_nesting
+\newdimen\d_strc_indentedtexts_width
+\newdimen\d_strc_indentedtexts_distance
+
+\appendtoks
+ \setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}%
+ \setuevalue {\e!stop \currentindentedtext}{\strc_indentedtexts_stop}%
+ % to be avoided ... might go away
+ \setuevalue {\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{0}}%
+ \setuevalue {\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{1}}%
+ \setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}%
+\to \everydefineindentedtext
+
+\unexpanded\def\strc_indentedtexts_start#1#2% we need to get rid of \spr
+ {\par
+ \begingroup
+ \edef\currentindentedtext{#1}%
+ \c_strc_indentedtexts_nesting#2\relax
+ \indentedtextparameter\c!before
+ \d_strc_indentedtexts_distance\indentedtextparameter\c!distance\relax
+ \doifnothing{\indentedtextparameter\c!sample}
+ {\setindentedtextparameter\c!sample{\indentedtextparameter\c!text}}%
+ \assignwidth
+ {\indentedtextparameter\c!width}
+ {\d_strc_indentedtexts_width}
+ {\useindentedtextstyleandcolor\c!headstyle\c!headcolor
+ \indentedtextparameter\c!sample
+ \spr{\indentedtextparameter\c!separator}}
+ {\d_strc_indentedtexts_distance}%
+ \advance\d_strc_indentedtexts_width \d_strc_indentedtexts_distance
+ \setbox\scratchbox\hbox to \d_strc_indentedtexts_width
+ {\useindentedtextstyleandcolor\c!headstyle\c!headcolor
+ \strut
+ \indentedtextparameter\c!text
+ \hss
+ \spr{\indentedtextparameter\c!separator}%
+ \hskip\d_strc_indentedtexts_distance}%
+ \parindent\zeropoint
+ \hskip\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width
+ \advance\c_strc_indentedtexts_nesting\plusone
+ \dontleavehmode\box\scratchbox
+ \hangindent\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width
+ \useindentedtextstyleandcolor\c!style\c!color}
+
+\unexpanded\def\strc_indentedtexts_stop
+ {\indentedtextparameter\c!after
+ \par
+ \endgroup}
+
+\unexpanded\def\startindentedtext
+ {\dosingleempty\strc_indentedtexts_start_direct}
+
+\def\strc_indentedtexts_start_direct[#1]%
+ {\strc_indentedtexts_start{#1}\c_strc_indentedtexts_nesting}
+
+\let\stopindentedtext\strc_indentedtexts_stop
+
+\unexpanded\def\strc_indentedtexts_direct#1#2#3\par % no longer clever grabpar trickery
+ {\strc_indentedtexts_start{#1}{#2}#3\strc_indentedtexts_stop}
+
+\setupindentedtext
+ [\c!style=\v!normal,
+ \c!headstyle=\v!normal,
+ %\c!color=,
+ %\c!headcolor=,
+ \c!width=\v!fit,
+ \c!text=\unknown,
+ %\c!sample=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=1em,
+ \c!separator={ :}]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-ini.lua
new file mode 100644
index 00000000000..dffbe3fcd8f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ini.lua
@@ -0,0 +1,405 @@
+if not modules then modules = { } end modules ['strc-ini'] = {
+ version = 1.001,
+ comment = "companion to strc-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+The restructuring is the (intermediate) result of quite some experiments. I started
+with the basic structure, followed by lists, numbers, enumerations, itemgroups
+and floats. All these have something in common, like pagenumbers and section
+prefixes. I played with some generic datastructure (in order to save space) but
+the code at both the lua and tex end then quickly becomes messy due to the fact
+that access to variables is too different. So, eventually I ended up with
+dedicated structures combined with sharing data. In lua this is quite efficient
+because tables are referenced. However, some precautions are to be taken in
+order to keep the utility file small. Utility data and process data share much
+but it does not make sense to store all processdata.
+
+]]--
+
+local lpegmatch = lpeg.match
+local type, next, tonumber, select = type, next, tonumber, select
+
+local formatters = string.formatters
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+local allocate = utilities.storage.allocate
+
+local catcodenumbers = catcodes.numbers -- better use the context(...) way to switch
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local xmlcatcodes = catcodenumbers.xmlcatcodes
+local notcatcodes = catcodenumbers.notcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+
+local context = context
+local commands = commands
+
+local trace_processors = false
+local report_processors = logs.reporter("processors","structure")
+
+trackers.register("typesetters.processors", function(v) trace_processors = v end)
+
+local xmlconvert = lxml.convert
+local xmlstore = lxml.store
+
+local ctx_pushcatcodes = context.pushcatcodes
+local ctx_popcatcodes = context.popcatcodes
+local ctx_xmlsetup = context.xmlsetup
+local ctx_xmlprocessbuffer = context.xmlprocessbuffer
+
+-- -- -- namespace -- -- --
+
+-- This is tricky: we have stored and initialized already some of
+-- the job.registered tables so we have a forward reference!
+
+structures = structures or { }
+local structures = structures
+
+structures.blocks = structures.blocks or { }
+structures.sections = structures.sections or { }
+structures.pages = structures.pages or { }
+structures.registers = structures.registers or { }
+structures.references = structures.references or { }
+structures.lists = structures.lists or { }
+structures.helpers = structures.helpers or { }
+structures.documents = structures.documents or { }
+structures.notes = structures.notes or { }
+structures.descriptions = structures.descriptions or { }
+structures.itemgroups = structures.itemgroups or { }
+structures.specials = structures.specials or { }
+structures.counters = structures.counters or { }
+structures.tags = structures.tags or { }
+structures.formulas = structures.formulas or { } -- not used but reserved
+structures.sets = structures.sets or { }
+structures.marks = structures.marks or { }
+structures.floats = structures.floats or { }
+structures.synonyms = structures.synonyms or { }
+
+--~ table.print(structures)
+
+local processors = typesetters.processors
+
+-- -- -- specials -- -- --
+
+-- we can store information and get back a reference; this permits
+-- us to store rather raw data in references
+
+local specials = structures.specials
+
+local collected = allocate()
+local tobesaved = allocate()
+
+specials.collected = collected
+specials.tobesaved = tobesaved
+
+local function initializer()
+ collected = specials.collected
+ tobesaved = specials.tobesaved
+end
+
+if job then
+ job.register('structures.specials.collected', tobesaved, initializer)
+end
+
+function specials.store(class,data)
+ if class and data then
+ local s = tobesaved[class]
+ if not s then
+ s = { }
+ tobesaved[class] = s
+ end
+ s[#s+1] = data
+ context(#s)
+ else
+ context(0)
+ end
+end
+
+function specials.retrieve(class,n)
+ if class and n then
+ local c = collected[class]
+ return c and c[n]
+ end
+end
+
+-- -- -- helpers -- -- --
+
+local helpers = structures.helpers
+
+-- function helpers.touserdata(str)
+-- local hash = str and str ~= "" and settings_to_hash(str)
+-- if hash and next(hash) then
+-- return hash
+-- end
+-- end
+
+function helpers.touserdata(data)
+ if type(data) == "string" then
+ if data == "" then
+ return nil
+ else
+ data = settings_to_hash(data)
+ end
+ end
+ if data and next(data) then
+ return data
+ end
+end
+
+local function simplify(d,nodefault)
+ if d then
+ local t = { }
+ for k, v in next, d do
+ local tv = type(v)
+ if tv == "table" then
+ if next(v) then
+ t[k] = simplify(v)
+ end
+ elseif tv == "string" then
+ if v ~= "" then
+ t[k] = v
+ end
+ elseif tv == "boolean" then
+ if v then
+ t[k] = v
+ end
+ else
+ t[k] = v
+ end
+ end
+ return next(t) and t
+ elseif nodefault then
+ return nil
+ else
+ return { }
+ end
+end
+
+-- we only care about the tuc file so this would do too:
+--
+-- local function simplify(d,nodefault)
+-- if d then
+-- for k, v in next, d do
+-- local tv = type(v)
+-- if tv == "string" then
+-- if v == "" or v == "default" then
+-- d[k] = nil
+-- end
+-- elseif tv == "table" then
+-- if next(v) then
+-- simplify(v)
+-- end
+-- elseif tv == "boolean" then
+-- if not v then
+-- d[k] = nil
+-- end
+-- end
+-- end
+-- return d
+-- elseif nodefault then
+-- return nil
+-- else
+-- return { }
+-- end
+-- end
+
+helpers.simplify = simplify
+
+function helpers.merged(...)
+ local t = { }
+ for k=1, select("#",...) do
+ local v = select(k,...)
+ if v and v ~= "" and not t[k] then
+ t[k] = v
+ end
+ end
+ return t
+end
+
+local tags = {
+ generic = "ctx:genericentry",
+ section = "ctx:sectionentry",
+ entry = "ctx:registerentry",
+}
+
+-- We had the following but it overloads the main document so it's a no-go as we
+-- no longer push and pop. So now we use the tag as buffername, namespace and also
+-- (optionally) as a setups to be applied but keep in mind that document setups
+-- also get applied (when they use #1's).
+--
+-- local command = formatters["\\xmlprocessbuffer{%s}{%s}{}"](metadata.xmlroot or "main",tag)
+
+local overload_catcodes = true
+
+directives.register("typesetters.processors.overloadcatcodes",function(v)
+ -- number | true | false | string
+ overload_catcodes = v
+end)
+
+local experiment = true
+
+function helpers.title(title,metadata) -- coding is xml is rather old and not that much needed now
+ if title and title ~= "" then -- so it might disappear
+ if metadata then
+ local xmlsetup = metadata.xmlsetup
+ if metadata.coding == "xml" then
+ -- title can contain raw xml
+ local tag = tags[metadata.kind] or tags.generic
+ local xmldata = formatters["<?xml version='1.0'?><%s>%s</%s>"](tag,title,tag)
+ if not experiment then
+ buffers.assign(tag,xmldata)
+ end
+ if trace_processors then
+ report_processors("putting xml data in buffer: %s",xmldata)
+ report_processors("processing buffer with setup %a and tag %a",xmlsetup,tag)
+ end
+ if experiment then
+ -- the question is: will this be forgotten ... better store in a via file
+ local xmltable = xmlconvert("temp",xmldata or "")
+ xmlstore("temp",xmltable)
+ ctx_xmlsetup("temp",xmlsetup or "")
+ else
+ ctx_xmlprocessbuffer("dummy",tag,xmlsetup or "")
+ end
+ elseif xmlsetup then -- title is reference to node (so \xmlraw should have been used)
+ if trace_processors then
+ report_processors("feeding xmlsetup %a using node %a",xmlsetup,title)
+ end
+ ctx_xmlsetup(title,metadata.xmlsetup)
+ else
+ local catcodes = metadata.catcodes
+ if overload_catcodes == false then
+ if trace_processors then
+ report_processors("catcodetable %a, text %a",catcodes,title)
+ end
+ --
+ -- context.sprint(catcodes,title)
+ --
+ -- doesn't work when a newline is in there \section{Test\ A} so we do
+ -- it this way:
+ --
+ ctx_pushcatcodes(catcodes)
+ context(title)
+ ctx_popcatcodes()
+ elseif overload_catcodes == true then
+ if catcodes == notcatcodes or catcodes == xmlcatcodes then
+ -- when was this needed
+ if trace_processors then
+ report_processors("catcodetable %a, overloads %a, text %a",ctxcatcodes,catcodes,title)
+ end
+ context(title)
+ else
+ ctx_pushcatcodes(catcodes)
+ context(title)
+ ctx_popcatcodes()
+ end
+ else
+ if trace_processors then
+ report_processors("catcodetable %a, overloads %a, text %a",catcodes,overload_catcodes,title)
+ end
+ ctx_pushcatcodes(overload_catcodes)
+ context(title)
+ ctx_popcatcodes()
+ end
+ end
+ else
+ -- no catcode switch, was: texsprint(title)
+ context(title)
+ end
+ end
+end
+
+-- -- -- sets -- -- --
+
+local sets = structures.sets
+
+sets.setlist = sets.setlist or { }
+
+storage.register("structures/sets/setlist", structures.sets.setlist, "structures.sets.setlist")
+
+local setlist = sets.setlist
+
+function sets.define(namespace,name,values,default,numbers)
+ local dn = setlist[namespace]
+ if not dn then
+ dn = { }
+ setlist[namespace] = dn
+ end
+ if values == "" then
+ dn[name] = { { }, default }
+ else
+ local split = settings_to_array(values)
+ if numbers then
+ -- convert to numbers (e.g. for reset)
+ for i=1,#split do
+ split[i] = tonumber(split[i]) or 0
+ end
+ end
+ dn[name] = { split, default }
+ end
+end
+
+function sets.getall(namespace,block,name)
+ local ds = setlist[namespace]
+ if not ds then
+ return { }
+ else
+ local dn
+ if block and block ~= "" then
+ dn = ds[block..":"..name] or ds[name] or ds[block] or ds.default
+ else
+ dn = ds[name] or ds.default
+ end
+ return (dn and dn[1]) or { }
+ end
+end
+
+-- messy (will be another keyword, fixedconversion) .. needs to be documented too
+-- maybe we should cache
+
+local splitter = lpeg.splitat("::")
+
+function sets.get(namespace,block,name,level,default) -- check if name is passed
+ --fixed::R:a: ...
+ local kind, rest = lpegmatch(splitter,name)
+ if rest and kind == "fixed" then -- fixed::n,a,i
+ local s = settings_to_array(rest)
+ return s[level] or s[#s] or default
+ end
+ --
+ local ds = setlist[namespace]
+ if not ds then
+ return default
+ end
+ local dn
+ if name and name ~= "" then
+ if block and block ~= "" then
+ dn = ds[block..":"..name] or ds[name] or ds[block] or ds.default
+ else
+ dn = ds[name] or ds.default
+ end
+ else
+ if block and block ~= "" then
+ dn = ds[block] or ds[block..":default"] or ds.default
+ else
+ dn = ds.default
+ end
+ end
+ if not dn then
+ return default
+ end
+ local dl = dn[1][level]
+ return dl or dn[2] or default
+end
+
+-- interface
+
+interfaces.implement {
+ name = "definestructureset",
+ actions = sets.define,
+ arguments = { "string", "string", "string", "string", "boolean" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-ini.mkvi
new file mode 100644
index 00000000000..ad83cbc58c2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ini.mkvi
@@ -0,0 +1,89 @@
+%D \module
+%D [ file=strc-flt,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Initialization \& Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Initialization & Helpers}
+
+\registerctxluafile{strc-ini}{1.001}
+
+\unprotect
+
+% segments: 0:100 2:3 chapter:subsection 3 (=self+2) (alternative: sectionset)
+
+% section : [sectionnumber(s)]
+% sectionseparatorset (default) sectionconversionset (default) sectionstopper () sectionset sectionsegments
+
+% lists : [sectionnumber(s)] [text] [prefix(es)[separator][pagenumber(s)]
+% sectionseparatorset (default) sectionconversionset (default) sectionstopper sectionset sectionsegments
+% prefixseparatorset (default) prefixconversionset (default) prefixstopper (.) prefixset prefixsegments
+% pageseparatorset (default) pageconversionset (default) pagestopper () pagesegments
+% prefix (no)
+
+% counter : [prefix(es)[separator]][number(s)]
+% prefixseparatorset (default) prefixconversionset (default) prefixstopper (.) prefixset prefixsegments
+% numberseparatorset (default) numberconversionset (default) numberstopper () numbersegments
+% prefix (no)
+
+% pagenumber: [prefix(es)[separator]][pagenumber(s)]
+% prefixseparatorset (default) prefixconversionset (default) prefixstopper (.) prefixset prefixsegments
+% pageseparatorset (default) pageconversionset (default) pagestopper ()
+% prefix (no)
+
+% text mark reference list
+% section P P P P
+% float P.N P.N P.N
+% itemize P.N P.N
+% enumerate P.N P.N P.N
+% formula P.N P.N
+% footnote P.N P.N P.N
+% number P.N P.N
+
+% number prefix section page
+
+% [text|marking|reference|list]:[number|prefix|pagenumber|pageprefix]:[separatorset|conversionset|conversion|stopper|set|segments|resetset|order]
+
+% figure caption : text:number:* text:prefix:* -> \setupcaption[figure][...]; stores defaults
+% figure list : list:number:* list:prefix:* list:pagenumber:* list:pageprefix:* -> \setuplist[figure][...]; takes stored defaults for number and pagenumber]
+% figure reference: reference:number:* reference:prefix:* reference:pagenumber:* reference:pageprefix:* -> \setupreference[figure]]...]; takes stored defaults
+
+% This module deals with structure: section headers, list and
+% numbering and eventually cross referencing. These components are
+% rather interwoven and therefore an inbetween layer is used.
+% Eventually this will replace the corresponding code in core-sec,
+% core-lst, core-num and core-ref.
+
+% We collect operations that deal with things like formatting on each
+% level of a number in sets. This is all handles at the \LUA\ end.
+% References to such sets travel with the multipass information.
+
+\unexpanded\def\defineresetset {\dotripleempty\strc_sets_define_reset_set}
+\unexpanded\def\defineseparatorset {\dotripleempty\strc_sets_define_separator_set}
+\unexpanded\def\defineconversionset{\dotripleempty\strc_sets_define_conversion_set}
+\unexpanded\def\defineprefixset {\dotripleempty\strc_sets_define_prefix_set}
+
+% Low level versions (no optional checking). The detokenize might go away.
+
+\unexpanded\def\strc_sets_define_reset_set [#name][#set][#default]{\clf_definestructureset{structure:resets} {#name}{\detokenize{#set}}{\detokenize{#default}}true\relax}
+\unexpanded\def\strc_sets_define_separator_set [#name][#set][#default]{\clf_definestructureset{structure:separators} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax}
+\unexpanded\def\strc_sets_define_conversion_set[#name][#set][#default]{\clf_definestructureset{structure:conversions}{#name}{\detokenize{#set}}{\detokenize{#default}}false\relax}
+\unexpanded\def\strc_sets_define_prefix_set [#name][#set][#default]{\clf_definestructureset{structure:prefixes} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax}
+
+\let\definestructureresetset \defineresetset
+\let\definestructureseparatorset \defineseparatorset
+\let\definestructureconversionset\defineconversionset
+\let\definestructureprefixset \defineprefixset
+
+% \defineseparatorset [weird][!,?,*][:] % tex content
+% \defineconversionset[weird][numbers,characters,romannumerals][numbers] % symbolic names
+% \defineresetset [weird][0,0,1][0] % numbers
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-itm.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.lua
new file mode 100644
index 00000000000..adec591c1c1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.lua
@@ -0,0 +1,63 @@
+if not modules then modules = { } end modules ['strc-itm'] = {
+ version = 1.001,
+ comment = "companion to strc-itm.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local structures = structures
+local itemgroups = structures.itemgroups
+local jobpasses = job.passes
+
+local implement = interfaces.implement
+
+local setvariable = jobpasses.save
+local getvariable = jobpasses.getfield
+
+local texsetcount = tex.setcount
+local texsetdimen = tex.setdimen
+
+local f_stamp = string.formatters["itemgroup:%s:%s"]
+local counts = table.setmetatableindex("number")
+
+-- We keep the counter at the Lua end so we can group the items within
+-- an itemgroup which in turn makes for less passes when one itemgroup
+-- entry is added or removed.
+
+local trialtypesetting = context.trialtypesetting
+
+local function analyzeitemgroup(name,level)
+ local n = counts[name]
+ if level == 1 then
+ n = n + 1
+ counts[name] = n
+ end
+ local stamp = f_stamp(name,n)
+ local n = getvariable(stamp,level,1,0)
+ local w = getvariable(stamp,level,2,0)
+ texsetcount("local","c_strc_itemgroups_max_items",n)
+ texsetdimen("local","d_strc_itemgroups_max_width",w)
+end
+
+local function registeritemgroup(name,level,nofitems,maxwidth)
+ local n = counts[name]
+ if not trialtypesetting() then
+ -- no trialtypsetting
+ setvariable(f_stamp(name,n), { nofitems, maxwidth }, level)
+ elseif level == 1 then
+ counts[name] = n - 1
+ end
+end
+
+implement {
+ name = "analyzeitemgroup",
+ actions = analyzeitemgroup,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "registeritemgroup",
+ actions = registeritemgroup,
+ arguments = { "string", "integer", "integer", "dimen" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi
new file mode 100644
index 00000000000..48c8e1a302e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi
@@ -0,0 +1,1790 @@
+%D \module
+%D [ file=strc-itm,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Itemgroups,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Itemgroups}
+
+\registerctxluafile{strc-itm}{1.001}
+
+%D As we analyze/register widths and such we could as well push and pop the
+%D numbers at the \LUA\ end (which saves a few calls).
+
+%D Cleaning up this module happened around the time when Kate Bush came up
+%D with the nicest numbered list of words: 50 Words For Snow. It's therefore
+%D no surprise that I had that cd running several times when updating this
+%D code. One of the highlights of 2011.
+
+% todo: check breaks
+% todo: check grouping
+% todo: fixedconversion
+
+% \startitemize[n,packed]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse] \item test \item test \stopitemize
+% \startitemize[continue]
+% \item test \startitemize[n,packed] \item test \item test \stopitemize
+% \item test
+% \item test
+% \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \startitemize[n,packed] \item test \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \setupwhitespace[big]
+% \starttext
+% test \startitemize[joinedup] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,before] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,after] \item test \item test \stopitemize test \par
+% \stoptext
+%
+% test / example
+%
+% \startnarrower[left] \startcolumns[n=3] \startitemize
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopcolumns\stopnarrower \blank
+%
+% \startnarrower[left] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopnarrower \blank
+%
+% \setupitemize[leftmargin=1.5em] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \blank
+%
+% beware, we don't group (yet) as we want to keep the left/right skip
+%
+% \startitemize
+% \startitem \stopitem
+% some intermediate text that will properly indent
+% \startitem \stopitem
+% \stopitem
+%
+% so we need to keep that property
+%
+% \startitemize
+% \starthead {xx} test \stophead
+% \startitem test \stopitem
+% \startitem test \stopitem
+% \stopitemize
+%
+% Sometimes the user demands get pretty weird:
+%
+% \startitemize
+% \item test
+% \item test
+% \headsym{xx} test \par test
+% \stopitemize
+%
+% aligned items
+%
+% \startitemize[n,fit,broad][itemalign=flushright]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \setupitemgroup[itemize][each][fit]
+% \setupitemgroup[itemize][each][distance=.5em,factor=1,itemalign=flushright]
+%
+% \startitemize[n]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \defineitemgroup[gbitemize]
+% \setupitemgroup[gbitemize][each][headstyle=bold]
+%
+% \startgbitemize
+% \txt{italian} some italians like this kind of cross||breed between
+% an itemize and a description
+% \txt{sicilians} i wonder how many sicilian mathematicians do a thesis
+% on the math involved in predicting the next big bang of the vulcano
+% \stopgbitemize
+%
+% \startitemize[n,repeat]
+% \noitem \startitemize[a] \item Item 1.a. \item Item 1.b. \stopitemize
+% \noitem \startitemize[a] \item Item 2.a. \item Item 2.b. \stopitemize
+% \stopitemize
+%
+% \startbuffer
+% \item
+% \startitemize[n]
+% \item item 1.1
+% \item item 1.2
+% \startitemize[n] \item item 1.2.1 \item item 1.2.2 \stopitemize
+% \item item 1.3
+% \stopitemize
+% \item
+% \startitemize[n] \item item 2.1 \item item 2.2 \stopitemize
+% \item item 3
+% \startitemize[n] \item item 3.1 \item item 3.2 \stopitemize
+% \item
+% \startitemize[n] \item item 4.1 \item item 4.2 \stopitemize
+% \stopbuffer
+%
+% \startitemize[n,repeat,6*broad,packed] \getbuffer \stopitemize \blank[3*big]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize \blank[3*big]
+% \setupitemize[each][atmargin][width=3em]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize
+%
+% todo: assume startitem ... stopitem and do an autostopitem .. cleaner for
+% elements
+%
+% \startitemize[text][space=medium]
+% \item one \item two \item three
+% \stopitemize
+%
+% For Giuseppe "Oblomov" Bilotta, inspired on a suggestion by Taco
+% Hoekwater.
+%
+% \def\MyItemCommand#1{{\bf#1}\quad}
+% \setupitemgroup[itemize][command=\MyItemCommand]
+%
+% \startitemize
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \stopitemize
+
+\unprotect
+
+\newconditional\c_strc_itemgroups_sub
+\newconditional\c_strc_itemgroups_head
+\newconditional\c_strc_itemgroups_intro
+\newconditional\c_strc_itemgroups_randomize
+\newconditional\c_strc_itemgroups_horizontal
+\newconditional\c_strc_itemgroups_collecting
+\newconditional\c_strc_itemgroups_auto_intro
+\newconditional\c_strc_itemgroups_pack
+\newconditional\c_strc_itemgroups_paragraph
+\newconditional\c_strc_itemgroups_text
+\newconditional\c_strc_itemgroups_text_saved
+\newconditional\c_strc_itemgroups_first
+\newconditional\c_strc_itemgroups_before
+\newconditional\c_strc_itemgroups_after
+\newconditional\c_strc_itemgroups_nowhite
+\newconditional\c_strc_itemgroups_joined
+\newconditional\c_strc_itemgroups_reverse
+\newconditional\c_strc_itemgroups_continue
+\newconditional\c_strc_itemgroups_fitting
+\newconditional\c_strc_itemgroups_indented_first
+\newconditional\c_strc_itemgroups_inline
+\newconditional\c_strc_itemgroups_columns
+\newconditional\c_strc_itemgroups_concat
+\newconditional\c_strc_itemgroups_txt
+\newconditional\c_strc_itemgroups_extra
+\newconditional\c_strc_itemgroups_repeat
+
+% 0 = before/after
+% 1 = between unless before
+% 2 = between
+
+\newconstant \c_strc_itemgroups_spacing_mode \c_strc_itemgroups_spacing_mode\plustwo
+\newconditional\c_strc_itemgroups_optimize \settrue\c_strc_itemgroups_optimize
+\newconditional\c_strc_itemgroups_auto_concat \settrue\c_strc_itemgroups_auto_concat
+
+\newsignal \d_strc_itemgroups_signal
+
+\newbox \b_strc_itemgroups
+
+\newdimen \d_strc_itemgroups_list_width
+\newdimen \d_strc_itemgroups_asked_width
+
+\newdimen \d_strc_itemgroups_max_width % multipass
+\newcount \c_strc_itemgroups_max_items % multipass
+
+\newcount \c_strc_itemgroups_n_of_items
+\newcount \c_strc_itemgroups_nesting
+\newcount \c_strc_itemgroups_column_depth
+
+\def \v_strc_itemgroups_counter {itemgroup:\currentparentitemgroup}
+
+\let \m_strc_itemgroups_repeat_start \empty
+\def \v_strc_itemgroups_unknown_symbol {?}
+
+\let \m_strc_itemgroups_indenting \empty
+\let \m_strc_itemgroups_destination \empty
+
+\let \currentitemlevel \!!zerocount % public
+\def \currentnofitems {\the\c_strc_itemgroups_max_items}
+\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public
+
+\newtoks \itemgroupcommands % maybe public
+
+\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name
+\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name
+\let \currentitemgroupsegments \empty
+
+\def\strc_itemgroups_register_status
+ {\clf_registeritemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\c_strc_itemgroups_n_of_items\dimexpr\itemgroupparameter\c!maxwidth\relax}
+
+\def\strc_itemgroups_check_n_of_items % we could do this at the lua end and save a call (i.e. will be dimen and counter)
+ {\clf_analyzeitemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\relax
+ \edef\currentnofitems{\the\c_strc_itemgroups_max_items}}
+
+% todo: \dodosetreference -> \strc_counters_register_component (to be checked)
+
+\def\strc_itemgroups_insert_reference % we will make a decent number helper
+ {\iftrialtypesetting \else \ifx\currentitemreference \empty \else
+ \strc_itemgroups_insert_reference_indeed
+ \fi \fi}
+
+\def\strc_itemgroups_insert_extra_reference
+ {\iftrialtypesetting \else \ifx\currentitemreference \empty \else
+ \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}%
+ \fi \fi}
+
+\def\strc_itemgroups_insert_reference_indeed % maybe we need a 'frozen counter' numberdata blob / quick hack .. .mive this to strc-ref
+ {% needs testing, gave problems:
+ \setnextinternalreference
+ % no need to collect nodes in \b_strc_destination_nodes here ... maybe at some point
+ \strc_references_start_destination_nodes
+ % this is somewhat over the top ... we should use the counter's reference
+ \clf_setdestinationattribute
+ {%
+ metadata {%
+ kind {item}% was item, why?
+ \ifx\currentreferencecoding\s!xml
+ xmlroot {\xmldocument}% only useful when text
+ \fi
+ catcodes \catcodetable
+ }%
+ references {%
+ internal \nextinternalreference % no: this spoils references
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {\currentitemreference}%
+ }%
+ prefixdata {%
+ prefix {\namedcounterparameter\v_strc_itemgroups_counter\c!prefix}%
+ separatorset {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixseparatorset}%
+ conversion {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconversion}%
+ conversionset {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconversionset}%
+ set {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixset}%
+ segments {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixsegments}%
+ % segments {\askedprefixsegments}%
+ connector {\namedcounterparameter\v_strc_itemgroups_counter\c!prefixconnector}%
+ }%
+ numberdata {%
+ numbers {\v_strc_itemgroups_counter}%
+ separatorset {\namedcounterparameter\v_strc_itemgroups_counter\c!numberseparatorset}%
+ % conversion {\namedcounterparameter\v_strc_itemgroups_counter\c!numberconversion}%
+ % conversionset {\namedcounterparameter\v_strc_itemgroups_counter\c!numberconversionset}%
+ % fixedconversion {\currentitemgroupconversionset}%
+ conversionset {fixed::\currentitemgroupconversionset}% temp hack
+ %
+ % for the moment no stopper, we need to make references configurable first
+ % stopper {\namedcounterparameter\v_strc_itemgroups_counter\c!numberstopper}%
+ segments {\namedcounterparameter\v_strc_itemgroups_counter\c!numbersegments}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \fi}
+
+%D Defining and setup:
+
+\installcorenamespace{itemgroup}
+\installcorenamespace{itemgroupoption}
+\installcorenamespace{itemgroupsetting}
+\installcorenamespace{itemgroupkeyword}
+\installcorenamespace{itemgroupalign}
+\installcorenamespace{itemgrouplocal}
+\installcorenamespace{itemgroupglobal}
+\installcorenamespace{itemgroupdistance}
+\installcorenamespace{itemgroupstack}
+\installcorenamespace{itemgroupfirst}
+\installcorenamespace{itemgroupstart}
+
+\installcommandhandler \??itemgroup {itemgroup} \??itemgroup
+
+\let\setupitemgroups\setupitemgroup
+
+\appendtoks
+ \setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}%
+ \setuevalue{\e!stop \currentitemgroup}{\stopitemgroup}%
+ \setuevalue{\e!setup\currentitemgroup\e!endsetup}{\setupitemgroup[\currentitemgroup]}% obsolete
+ \let\currentparentitemgroup\currentitemgroup
+ \definecounter[\v_strc_itemgroups_counter]%
+ % beware ... we cannot use _ as the conversion set is not expanded
+ % \defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]%
+\to \everydefineitemgroup
+
+%D Global states
+
+\def\strc_itemgroups_store_continue_state#options#settings%
+ {\setxvalue{\??itemgroupoption \currentitemgroup}{\strc_itemgroups_process_options{#options}}%
+ \setgvalue{\??itemgroupsetting\currentitemgroup}{\setupcurrentitemgroup[#settings]}}
+
+\def\strc_itemgroups_fetch_continue_state
+ {\csname\??itemgroupoption \currentitemgroup\endcsname
+ \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}
+
+% These will become keywords. We will also add a feature to keep the while set
+% together.
+
+\definevspacing[\v!item @0] [penalty:0] % allow
+\definevspacing[\v!item @10000] [penalty:10000] % no
+\definevspacing[\v!item @-5] [penalty:-5]
+\definevspacing[\v!item @5] [penalty:5]
+\definevspacing[\v!item @500] [penalty:500] % discourage .. too low, 5000 is better
+
+\def\strc_itemgroups_insert_break_when_needed#break%
+ {\ifconditional\c_strc_itemgroups_optimize
+ \ifconditional\c_strc_itemgroups_text \else
+ #break\relax
+ \fi
+ \fi}
+
+\def\strc_itemgroups_insert_breakallow {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakallow_indeed}
+\def\strc_itemgroups_insert_breakno {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakno_indeed }
+\def\strc_itemgroups_insert_break {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_break_indeed }
+\def\strc_itemgroups_insert_nobreak {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_nobreak_indeed }
+
+\def\strc_itemgroups_insert_breakallow_indeed{\vspacing[\v!item @0]}
+\def\strc_itemgroups_insert_breakno_indeed {\vspacing[\v!item @10000]}
+\def\strc_itemgroups_insert_break_indeed {\flushnotes
+ \vspacing[\v!item @-5]}
+\def\strc_itemgroups_insert_nobreak_indeed {\flushnotes
+ \ifinsidecolumns % todo
+ \vspacing[\v!item @5]%
+ \else
+ \vspacing[\v!item @500]%
+ \fi}
+
+\unexpanded\def\strc_itemgroups_process_options#options%
+ {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml
+
+\def\strc_itemgroups_process_option#option%
+ {\edef\itemgroupconstantvalue{#option}%
+ \ifx\itemgroupconstantvalue\empty\else
+ \splitstring\itemgroupconstantvalue\at*\to\itemgroupfirst\and\itemgroupsecond
+ \ifx\itemgroupsecond\empty
+ \let\itemgroupsecond\itemgroupfirst
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \ifcsname\??itemgroupkeyword\itemgroupsecond\endcsname
+ \lastnamedcs
+ \else
+ \strc_itemgroups_set_symbol\itemgroupconstantvalue
+ \fi
+ \fi}
+
+\def\strc_itemgroups_process_set_option_pack
+ {\ifcase\c_strc_itemgroups_nesting \else
+ \settrue\c_strc_itemgroups_pack
+ \fi}
+
+\setvalue{\??itemgroupkeyword\!!zerocount}{} % ignore 0
+\setvalue{\??itemgroupkeyword\v!packed }{\strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!intro }{\settrue\c_strc_itemgroups_intro} % here? not set to false
+\setvalue{\??itemgroupkeyword\v!autointro}{\settrue\c_strc_itemgroups_auto_intro}
+\setvalue{\??itemgroupkeyword\v!broad }{\ifx\itemgroupfirst\empty
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!text }{\settrue\c_strc_itemgroups_text
+ \settrue\c_strc_itemgroups_inline
+ \settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!before }{\settrue\c_strc_itemgroups_before}
+\setvalue{\??itemgroupkeyword\v!after }{\settrue\c_strc_itemgroups_after}
+\setvalue{\??itemgroupkeyword\v!nowhite }{\settrue\c_strc_itemgroups_nowhite}
+\setvalue{\??itemgroupkeyword\v!margin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!inmargin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!atmargin }{\ifnum\c_strc_itemgroups_nesting>\plusone
+ \setitemgroupparameter\c!width{0em}%
+ \fi} % signal
+\setvalue{\??itemgroupkeyword\v!intext }{\settrue\c_strc_itemgroups_inline}
+\setvalue{\??itemgroupkeyword\v!loose }{\setfalse\c_strc_itemgroups_optimize}
+\setvalue{\??itemgroupkeyword\v!fit }{\settrue\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!nofit }{\setfalse\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!paragraph}{\settrue\c_strc_itemgroups_paragraph
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!joinedup }{\settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!serried }{\edef\itemgroupfirst{-\ifx\itemgroupfirst\empty1\else\itemgroupfirst\fi}%
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!stopper }{\letitemgroupparameter\c!placestopper\v!yes} % keep {}
+\setvalue{\??itemgroupkeyword\v!unpacked }{\setfalse\c_strc_itemgroups_pack}
+\setvalue{\??itemgroupkeyword\v!repeat }{\settrue\c_strc_itemgroups_repeat}
+\setvalue{\??itemgroupkeyword\v!norepeat }{\setfalse\c_strc_itemgroups_repeat}
+\setvalue{\??itemgroupkeyword\v!reverse }{\settrue\c_strc_itemgroups_reverse}
+\setvalue{\??itemgroupkeyword\v!columns }{\settrue\c_strc_itemgroups_columns}
+\setvalue{\??itemgroupkeyword\v!one }{\letitemgroupparameter\c!n\plusone}
+\setvalue{\??itemgroupkeyword\v!two }{\letitemgroupparameter\c!n\plustwo}
+\setvalue{\??itemgroupkeyword\v!three }{\letitemgroupparameter\c!n\plusthree}
+\setvalue{\??itemgroupkeyword\v!four }{\letitemgroupparameter\c!n\plusfour}
+\setvalue{\??itemgroupkeyword\v!five }{\letitemgroupparameter\c!n\plusfive}
+\setvalue{\??itemgroupkeyword\v!six }{\letitemgroupparameter\c!n\plussix}
+\setvalue{\??itemgroupkeyword\v!seven }{\letitemgroupparameter\c!n\plusseven}
+\setvalue{\??itemgroupkeyword\v!eight }{\letitemgroupparameter\c!n\pluseight}
+\setvalue{\??itemgroupkeyword\v!nine }{\letitemgroupparameter\c!n\plusnine}
+%setvalue{\??itemgroupkeyword\v!standard }{\setupcurrentitemgroup
+% [\c!width =1.5\emwidth,%
+% \c!distance =.5\emwidth,%
+% \c!factor =0,%
+% \c!inner =,%
+% \c!beforehead=,%
+% \c!afterhead =\blank,%
+% \c!before =\blank,%
+% \c!inbetween =\blank,%
+% \c!after =\blank]}
+\setvalue{\??itemgroupkeyword\v!standard }{\setitemgroupparameter\c!width {1.5\emwidth}%
+ \setitemgroupparameter\c!distance {.5\emwidth}%
+ \letitemgroupparameter\c!factor \!!zerocount
+ \letitemgroupparameter\c!inner \empty
+ \letitemgroupparameter\c!beforehead\empty
+ \letitemgroupparameter\c!afterhead \blank
+ \letitemgroupparameter\c!before \blank
+ \letitemgroupparameter\c!inbetween \blank
+ \letitemgroupparameter\c!after \blank}
+
+
+\def\strc_itemgroups_initialize_local
+ {\setfalse\c_strc_itemgroups_inline
+ \setfalse\c_strc_itemgroups_concat
+ \setfalse\c_strc_itemgroups_txt
+ %
+ \setfalse\c_strc_itemgroups_reverse
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_auto_intro
+ \setfalse\c_strc_itemgroups_before
+ \setfalse\c_strc_itemgroups_after
+ \setfalse\c_strc_itemgroups_nowhite
+ \setfalse\c_strc_itemgroups_randomize
+ \setfalse\c_strc_itemgroups_horizontal
+ \setfalse\c_strc_itemgroups_collecting
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_continue
+ % this will be a constant
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \setfalse\c_strc_itemgroups_symbol
+ \setfalse\c_strc_itemgroups_columns
+ % to be checked
+ \let\m_strc_itemgroups_destination\empty
+ \let\strc_itemgroups_used_symbol\empty % ** start value
+ \let\strc_itemgroups_margin_symbol\empty
+ \let\strc_itemgroups_extra_symbol\empty
+ %
+ \global\letitemgroupparameter\c!maxwidth\!!zeropoint
+ }
+
+\setvalue{\??itemgroupfirst\v!intro }{\settrue\c_strc_itemgroups_intro}
+\setvalue{\??itemgroupfirst\v!continue }{\settrue\c_strc_itemgroups_continue}
+\setvalue{\??itemgroupfirst\v!random }{\settrue\c_strc_itemgroups_randomize
+ \settrue\c_strc_itemgroups_collecting}
+\setvalue{\??itemgroupkeyword\v!horizontal}{\settrue\c_strc_itemgroups_horizontal
+ \settrue\c_strc_itemgroups_collecting
+ \settrue\c_strc_itemgroups_inline
+ \settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+
+\def\strc_itemgroups_preset_stage_one#options%
+ {\processcommacommand[#options]\strc_itemgroups_preset_stage_one_indeed}
+
+\def\strc_itemgroups_preset_stage_one_indeed#option%
+ {\ifcsname\??itemgroupfirst#option\endcsname
+ \lastnamedcs
+ \fi}
+
+\ifdefined\dotagsetitemgroup \else \let\dotagsetitemgroup\relax \fi
+\ifdefined\dotagsetitem \else \let\dotagsetitem \gobbleoneargument \fi
+
+\def\strc_itemgroups_tag_start_group
+ {\dostarttaggedchained\t!itemgroup\currentparentitemgroup\??itemgroup
+ \dotagsetitemgroup}
+
+\def\strc_itemgroups_tag_stop_group
+ {\dostoptagged}
+
+\def\strc_itemgroups_before_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_before
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!before\fi
+ \else
+ \nowhitespace
+ \fi
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!before
+ \fi\fi}
+
+\def\strc_itemgroups_after_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_after
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!after\fi
+ \else
+ \nowhitespace
+ \fi
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!after
+ \fi\fi}
+
+\def\strc_itemgroups_between_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!inbetween
+ \fi\fi}
+
+\def\strc_itemgroups_before_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!beforehead
+ \fi\fi}
+
+\def\strc_itemgroups_after_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!afterhead
+ \fi\fi}
+
+% compatible setup command:
+
+\let\strc_itemgroups_normal_setup\setupitemgroup
+
+\unexpanded\def\setupitemgroup
+ {\doquadrupleempty\strc_itemgroups_setup}
+
+\def\strc_itemgroups_setup[#category][#levels][#options][#settings]% category level|each options|settings settings|options
+ {\edef\strc_itemgroups_setup_what{#levels}%
+ \iffourthargument
+ \ifx\strc_itemgroups_setup_what\v!each
+ \strc_itemgroups_setup_each{#category}{#options}%
+ \strc_itemgroups_setup_each{#category}{#settings}%
+ \else
+ \strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \strc_itemgroups_setup_list{#levels}{#category}{#settings}%
+ \fi
+ \else\ifthirdargument
+ \ifx\strc_itemgroups_setup_what\v!each
+ \strc_itemgroups_setup_each{#category}{#options}%
+ \else
+ \strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \fi
+ \else\ifsecondargument
+ \strc_itemgroups_setup_each{#category}{#levels}%
+ \else
+ \strc_itemgroups_normal_setup[#category]% == settings
+ \fi\fi\fi}
+
+% can be made a bit faster
+
+\def\strc_itemgroups_setup_each#category#whatever%
+ {\doifelseassignment{#whatever}
+ {\strc_itemgroups_normal_setup[#category][#whatever]}
+ {\strc_itemgroups_normal_setup[#category][\c!option={#whatever}]}}
+
+\def\strc_itemgroups_setup_list_level_a#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][#whatever]}
+
+\def\strc_itemgroups_setup_list_level_b#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][\c!option={#whatever}]}
+
+\def\strc_itemgroups_setup_list#subcategories#category#whatever%
+ {\doifelseassignment{#whatever}
+ {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}}
+ {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}}}
+
+\def\strc_itemgroups_increment_item_counter
+ {\ifconditional\c_strc_itemgroups_sub \else
+ \ifconditional\c_strc_itemgroups_symbol \else % \ifx\strc_itemgroups_extra_symbol\empty
+ \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel
+ \fi
+ \fi}
+
+\unexpanded\def\strc_itemgroups_insert_item_counter
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifcase\c_strc_itemgroups_nesting
+ % skip
+ \or
+ \strc_itemgroups_insert_item_counter_indeed % this could become an option
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_item_counter_indeed % quite slow ... every time this setup .. but it
+ {\begingroup % can be optimized ... best move some to strc-num
+ \setupcounter
+ [\v_strc_itemgroups_counter]%
+ [\c!prefix=\itemgroupparameter\c!prefix,
+ \c!prefixstopper=\itemgroupparameter\c!prefixstopper,
+ \c!prefixseparatorset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixconversion=\itemgroupparameter\c!prefixconversion,
+ \c!prefixconversionset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixset=\itemgroupparameter\c!prefixset,
+ \c!prefixsegments=\itemgroupparameter\c!prefixsegments,
+ \c!prefixconnector=\itemgroupparameter\c!prefixconnector,
+ \c!criterium=\itemgroupparameter\c!criterium,
+ \c!numberorder=\ifconditional\c_strc_itemgroups_reverse\v!reverse\else\v!normal\fi,
+ \c!numberstopper=\expdoif{\itemgroupparameter\c!placestopper}\v!yes{\itemgroupparameter\c!stopper},
+ \c!numberconversionset=\v_strc_itemgroups_counter,
+ \c!numbersegments=\currentitemgroupsegments]%
+ % there will be a fixedconversion key
+ %\normalexpanded{\defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ \normalexpanded{\strc_sets_define_conversion_set[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ %
+ \convertedcounter[\v_strc_itemgroups_counter]% [\number\currentitemlevel]%
+ \strc_itemgroups_insert_reference
+ \endgroup}
+
+% needs testing (maybe it need to happen later)
+%
+% \appendtoks
+% \setupcounter
+% [\v_strc_itemgroups_counter]%
+% [\c!prefix=\itemgroupparameter\c!prefix,
+% \c!prefixstopper=\itemgroupparameter\c!prefixstopper,
+% \c!prefixseparatorset=\itemgroupparameter\c!prefixseparatorset,
+% \c!prefixconversion=\itemgroupparameter\c!prefixconversion,
+% \c!prefixconversionset=\itemgroupparameter\c!prefixseparatorset,
+% \c!prefixset=\itemgroupparameter\c!prefixset,
+% \c!prefixsegments=\itemgroupparameter\c!prefixsegments,
+% \c!prefixconnector=\itemgroupparameter\c!prefixconnector,
+% \c!criterium=\itemgroupparameter\c!criterium,
+% \c!numberorder=\ifconditional\c_strc_itemgroups_reverse\v!reverse\else\v!normal\fi,
+% \c!numberstopper=\expdoif{\itemgroupparameter\c!placestopper}\v!yes{\itemgroupparameter\c!stopper},
+% \c!numberconversionset=\v_strc_itemgroups_counter,
+% \c!numbersegments=\currentitemgroupsegments]%
+% \to\itemgroupcommands
+%
+% \def\strc_itemgroups_insert_item_counter_indeed % quite slow ... every time this setup .. but it
+% {\begingroup % can be optimized ... best move some to strc-num
+% % there will be a fixedconversion key
+% %\normalexpanded{\defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+% \normalexpanded{\strc_sets_define_conversion_set[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+% %
+% \convertedcounter[\v_strc_itemgroups_counter]% [\number\currentitemlevel]%
+% \strc_itemgroups_insert_reference
+% \endgroup}
+
+\def\strc_itemgroups_set_symbol#symbol%
+ {\edef\strc_itemgroups_tmp_symbol{#symbol}%
+ \ifx\strc_itemgroups_tmp_symbol\empty \else
+ \doifelsesymboldefined\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_symbol
+ {\doifelseconversiondefined\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_conversion
+ \donothing}%
+ \fi}
+
+\def\strc_itemgroups_set_symbol_symbol
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\v_strc_itemgroups_unknown_symbol
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_symbol_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_conversion
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\strc_itemgroups_insert_item_counter
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_conversion_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_symbol_item
+ {\symbol[\currentitemgroupsymbol]}
+
+\def\strc_itemgroups_set_symbol_conversion_item
+ {\ifconditional\c_strc_itemgroups_text
+ % maybe block stopper here, but one can as well clone an itemgroup then
+ \itemgroupparameter\c!lefttext
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!righttext
+ \else
+ \itemgroupparameter\c!left
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!right
+ \fi}
+
+\def\strc_itemgroups_calculate_list_width#level%
+ {\let\savedcurrentitemgroup\currentitemgroup
+ \edef\currentitemgroup{\currentparentitemgroup:\number#level}%
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \d_strc_itemgroups_list_width\d_strc_itemgroups_max_width
+ \else\ifnum\itemgroupparameter\c!factor>\zerocount
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!step\relax
+ \ifdim\d_strc_itemgroups_list_width=\zeropoint \d_strc_itemgroups_list_width=.5em\fi
+ \multiply\d_strc_itemgroups_list_width \itemgroupparameter\c!factor
+ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \else
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \fi\fi
+ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax
+ \let\currentitemgroup\savedcurrentitemgroup}
+
+\unexpanded\def\startitemgroup
+ {\dotripleempty\strc_itemgroups_start}
+
+\def\strc_itemgroups_start[#category][#options][#settings]%
+ {\begingroup % (1)
+ \def\currentitemgroup{#category}% no nested mixing of itemgroups
+ \let\currentparentitemgroup\currentitemgroup
+ \global\advance\c_strc_itemgroups_nesting\plusone
+ \def\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}%
+ \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}%
+ %
+ \ifthirdargument
+ \strc_itemgroups_start_indeed[#options][#settings]%
+ \else\ifsecondargument
+ \doifelseassignment{#options}
+ {\strc_itemgroups_start_indeed[][#options]}
+ {\strc_itemgroups_start_indeed[#options][]}%
+ \else
+ \strc_itemgroups_start_indeed[][]%
+ \fi\fi}
+
+\def\strc_itemgroups_start_indeed[#options][#settings]%
+ {\edef\itemgroupoptions{\itemgroupparameter\c!option}%
+ \edef\itemgroupextraoptions{#options}%
+ \ifx\itemgroupoptions\empty
+ \let\itemgroupoptions\itemgroupextraoptions
+ \else\ifx\itemgroupextraoptions\empty
+ % ok
+ \else
+ \edef\itemgroupoptions{\itemgroupoptions,\itemgroupextraoptions}%
+ \fi\fi
+ \begingroup % (2)
+ \the\itemgroupcommands
+ \let\c_strc_itemgroups_text_saved\c_strc_itemgroups_text
+ \strc_itemgroups_initialize_local
+ \strc_itemgroups_preset_stage_one\itemgroupoptions
+%
+% \ifhmode
+% \ifconditional\c_strc_itemgroups_auto_concat
+% \ifdim\lastskip=\d_strc_itemgroups_signal
+% \settrue\c_strc_itemgroups_concat
+% \fi
+% \fi
+% \ifconditional\c_strc_itemgroups_text_saved \else
+% \ifconditional\c_strc_itemgroups_text \else
+% \par
+% \fi
+% \fi
+% \fi
+%
+ \iftrialtypesetting
+ \strc_counters_save\v_strc_itemgroups_counter
+ \fi
+ \c_strc_itemgroups_n_of_items\zerocount
+ \strc_itemgroups_check_n_of_items
+ \ifx\itemgroupoptions\empty
+ \strc_itemgroups_setup_symbol_default
+ \strc_itemgroups_reset_continue_state
+ \setupcurrentitemgroup[#settings]%
+ \else
+ \strc_itemgroups_process_options\itemgroupoptions
+ \setupcurrentitemgroup[#settings]%
+ \ifconditional\c_strc_itemgroups_continue
+ \strc_itemgroups_setup_symbol_continue
+ \strc_itemgroups_fetch_continue_state
+ \else
+ \strc_itemgroups_setup_symbol_asked
+ \strc_itemgroups_store_continue_state\itemgroupoptions{#settings}%
+ \fi
+ \fi
+ %
+ \ifhmode
+ \ifconditional\c_strc_itemgroups_auto_concat
+ \ifdim\lastskip=\d_strc_itemgroups_signal
+ \settrue\c_strc_itemgroups_concat
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_text_saved \else
+ \ifconditional\c_strc_itemgroups_text \else
+ \par
+ \fi
+ \fi
+ \fi
+ %
+ \ifnum\c_strc_itemgroups_nesting=\plusone % NIEUW
+ \doadaptleftskip {\itemgroupparameter\c!margin}%
+ \doadaptleftskip {\itemgroupparameter\c!leftmargin}%
+ \doadaptrightskip{\itemgroupparameter\c!rightmargin}%
+ \fi
+ \usealignparameter\itemgroupparameter
+ \edef\m_strc_itemgroups_indenting{\itemgroupparameter\c!indenting}%
+ \ifnum\c_strc_itemgroups_nesting>\zerocount
+ \settrue\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_continue \else
+ \strc_counters_restart_sub\v_strc_itemgroups_counter\currentitemlevel{\numexpr\itemgroupparameter\c!start-\plusone\relax}%
+ \fi
+ \fi
+ \ifx\strc_itemgroups_used_symbol\empty
+ \strc_itemgroups_set_symbol\strc_itemgroups_asked_symbol % ** default value
+ \ifx\strc_itemgroups_used_symbol\empty
+ \let\currentitemgroupsymbol\currentitemlevel % ** fall back
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_auto_intro\ifnum\prevgraf<\plusthree
+ \settrue\c_strc_itemgroups_intro
+ \fi\fi
+ \ifconditional\c_strc_itemgroups_paragraph
+ \ifnum\c_strc_itemgroups_nesting>\plusone
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_pack
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \ifconditional\c_strc_itemgroups_columns
+ \ifinsidecolumns\else\ifcase\c_strc_itemgroups_column_depth
+ \global\c_strc_itemgroups_column_depth\c_strc_itemgroups_nesting % global ?
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \strc_itemgroups_start_columns
+ \fi\fi
+ \fi
+ \ifconditional\c_strc_itemgroups_fitting
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \letitemgroupparameter\c!width\d_strc_itemgroups_max_width
+ \fi
+ \fi
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \ifdim\d_strc_itemgroups_list_width>\zeropoint\relax
+ \ifconditional\c_strc_itemgroups_inline\else
+ \advance\leftskip\d_strc_itemgroups_list_width\relax
+ \fi
+ \fi
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \let\currentitemgroupconversionset \currentitemgroupsymbol
+ \edef\currentitemgroupsegments {\currentitemlevel}%
+ \else
+ \edef\currentitemgroupconversionset{\currentitemgroupconversionset,\currentitemgroupsymbol}%
+ \edef\currentitemgroupsegments {\m_strc_itemgroups_repeat_start:\currentitemlevel}%
+ \fi
+ \d_strc_itemgroups_asked_width\itemgroupparameter\c!width\relax
+ \startcollectitems}
+
+\let\startcollectitems\relax
+\let\stopcollectitems \relax
+
+\letvalue{\??itemgroupalign\v!flushleft }\relax
+\letvalue{\??itemgroupalign\v!right }\relax
+\letvalue{\??itemgroupalign\v!flushright}\hfill
+\letvalue{\??itemgroupalign\v!left }\hfill
+\letvalue{\??itemgroupalign\v!middle }\hfil
+\letvalue{\??itemgroupalign\v!center }\hfil
+
+\def\strc_itemgroups_left_sym_filler
+ {\csname\??itemgroupalign\itemgroupparameter\c!symalign\endcsname}
+
+% symbols + states
+
+\def\strc_itemgroups_store_global_symbol#symbol%
+ {\letgvalue{\??itemgroupglobal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_store_local_symbol#symbol%
+ {\letgvalue{\??itemgrouplocal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_fetch_global_symbol
+ {\csname\??itemgroupglobal\currentitemlevel\endcsname}
+
+\def\strc_itemgroups_fetch_local_symbol
+ {\csname\??itemgrouplocal\currentitemlevel\endcsname}
+
+\def\strc_itemgroups_setup_symbol_default
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}%
+ \strc_itemgroups_store_global_symbol\empty}
+
+\def\strc_itemgroups_setup_symbol_continue
+ {\ifcsname\??itemgroupglobal\currentitemlevel\endcsname
+ \let\strc_itemgroups_asked_symbol\strc_itemgroups_fetch_global_symbol
+ \else
+ \let\strc_itemgroups_asked_symbol\currentitemlevel
+ \fi}
+
+\def\strc_itemgroups_setup_symbol_asked
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}}
+
+\ifdefined\strc_itemgroups_start_columns
+
+ % already defined in page-mix
+
+\else
+
+ % will be redefined in page-mix
+
+ \ifdefined\startcolumns \else
+ \unexpanded\def\startcolumns[#settings]{}
+ \unexpanded\def\stopcolumns {}
+ \fi
+
+ \def\strc_itemgroups_start_columns
+ {\startcolumns
+ [\c!n=\itemgroupparameter\c!n,
+ \c!height=,
+ \c!rule=\v!off,
+ \c!balance=\v!yes,
+ \c!align=\v!no]}
+
+ \def\strc_itemgroups_stop_columns
+ {\stopcolumns}
+
+\fi
+
+\unexpanded\def\stopitemgroup
+ {\stopcollectitems
+ \ifconditional\c_strc_itemgroups_text
+ \removeunwantedspaces
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_register_status
+ \ifconditional\c_strc_itemgroups_first \else
+ \dostoptagged
+ \dostoptagged
+ % \endgroup % (3)
+ \fi
+ \ifnum\c_strc_itemgroups_column_depth=\c_strc_itemgroups_nesting\relax
+ \strc_itemgroups_stop_columns
+ \global\c_strc_itemgroups_column_depth\zerocount % global ?
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \dontrechecknextindentation
+ \else\ifnum\c_strc_itemgroups_nesting=\plusone
+ \strc_itemgroups_insert_breakallow
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \useindentnextparameter\itemgroupparameter
+ \else
+ % nieuw, not yet nobreak handling
+ \strc_itemgroups_tag_stop_group
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_after_command
+ \or
+ \strc_itemgroups_after_command
+ \fi
+ \dontrechecknextindentation
+ \fi\fi
+ % new test, needed in sidefloats (surfaced in volker's proceedings)
+ \iftrialtypesetting
+ \strc_counters_restore\v_strc_itemgroups_counter % could happen in LUA
+ \fi
+ \global\advance\c_strc_itemgroups_nesting\minusone
+ \xdef\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ %\ifconditional\c_strc_itemgroups_text
+ \endgroup % (2)
+ \endgroup % (1)
+ %\else
+ % \endgroup % (2)
+ % \endgroup % (1)
+ % \par % hm, already done, and dangerous as \c_strc_itemgroups_text is already forgotten
+ %\fi
+ \dorechecknextindentation}
+
+% The items.
+
+\unexpanded\def\startitemgroupitem
+ {\dosingleempty\strc_itemgroups_start_item}
+
+\def\strc_itemgroups_start_item_first
+ {\setfalse\c_strc_itemgroups_first
+ % \begingroup % (3)
+ \ifcase\c_strc_itemgroups_nesting
+ % 0
+ \or
+ \strc_itemgroups_start_item_first_one % 1
+ \else
+ \strc_itemgroups_start_item_first_two % 2+
+ \fi}
+
+\def\strc_itemgroups_start_item_first_one
+ {\ifcase\c_strc_itemgroups_column_depth
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \fi}
+
+\def\strc_itemgroups_start_item_first_two
+ {\ifconditional\c_strc_itemgroups_paragraph\else
+ \edef\previtemlevel{\the\numexpr\c_strc_itemgroups_nesting-\plusone}%
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_before_command
+ \or
+ \doifelsenothing\strc_itemgroups_before_command % should possibly expand to empty
+ {\nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween}%
+ \strc_itemgroups_before_command
+ \else
+ \nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween
+ \fi
+ \strc_itemgroups_tag_start_group
+ \fi}
+
+\def\strc_itemgroups_start_item_next
+ {\dostoptagged % ok? what do we stop here?
+ \dostoptagged % ok? what do we stop here?
+ \ifconditional\c_strc_itemgroups_text
+ \ifhmode
+ % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex
+ \strc_itemgroups_set_text_item_distance% HH: moved out and made configurable (sort of)
+ \removeunwantedspaces
+ \hskip\m_strc_itemgroups_text_distance\relax
+ \fi
+ \else
+ \strc_itemgroups_between_command
+ \fi}
+
+% c_strc_itemgroups_concat:
+%
+% the problem is that we use leftskip so concat cannot reliable take the height into
+% account; it's .. rather tricky when white space in there anyway (due to \par) .. so
+% we rely on a special blank method
+%
+% \startitemize[n]
+% \item bla
+% \item \startitemize[a]
+% \item bla $\displaystyle\int^{x^{y^4}}$ \item bla
+% \stopitemize
+% \stopitemize
+
+\unexpanded\def\strc_itemgroups_start_item[#reference]% we can reuse more
+ {\def\currentitemreference{#reference}%
+ \ifconditional\c_strc_itemgroups_text
+ % begin of item
+ \else
+ \par
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ \strc_itemgroups_insert_breakno
+ \fi
+ \strc_itemgroups_increment_item_counter
+ \ifconditional\c_strc_itemgroups_first
+ \strc_itemgroups_start_item_first
+ \else
+ \strc_itemgroups_start_item_next
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ \spac_overlay_lines % see spac-ver.mkvi ... a typical potential problem
+ \setfalse\c_strc_itemgroups_concat
+ \fi
+ \dostarttagged\t!item\empty
+ % \dotagsetitem\empty
+ \dostarttagged\t!itemtag\empty
+ \strc_itemgroups_insert_item
+ \dostoptagged
+ \ifconditional\c_strc_itemgroups_pack
+ \setupwhitespace[\v!none]%
+ \fi
+ \itemgroupparameter\c!inner % will become obsolete (better use setups)
+ \strc_itemgroups_margin_symbol
+ \let\strc_itemgroups_margin_symbol\relax
+ \dostarttagged\t!itemcontent\empty
+ \strut
+ \nobreak % else problems with intext items
+ \hskip\d_strc_itemgroups_signal % concat
+ \itemgroupparameter\c!command}
+
+\unexpanded\def\stopitemgroupitem
+ {\ifconditional\c_strc_itemgroups_text
+ % nothing
+ \else
+ \endgraf
+ \fi}
+
+\unexpanded\def\startitemgrouphead
+ {\dosingleempty\strc_itemgroups_start_head}
+
+\unexpanded\def\strc_itemgroups_start_head[#reference]%
+ {\ifconditional\c_strc_itemgroups_first \else
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \ifconditional\c_strc_itemgroups_pack \else
+ \strc_itemgroups_before_head_command
+ \fi
+ \ifconditional\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_intro \else
+ \ifcase\c_strc_itemgroups_nesting
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \fi
+ \fi
+ \strc_itemgroups_start_item[#reference]%
+ \pickupgroupedcommand
+ \strc_itemgroups_start_head_indeed
+ \strc_itemgroups_stop_head_indeed
+ \strc_itemgroups_head_body_indeed}
+
+\unexpanded\def\stopitemgrouphead
+ {\dostoptagged
+ \stopitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_head_indeed
+ {\settrue\c_strc_itemgroups_head
+ \dotagsetitem\s!head% % weird place
+ \dostarttagged\t!itemhead\empty
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces}
+
+\unexpanded\def\strc_itemgroups_stop_head_indeed
+ {\removeunwantedspaces
+ \dostoptagged
+ \ifconditional\c_strc_itemgroups_text
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_insert_breakno
+ \ifconditional\c_strc_itemgroups_pack\else\strc_itemgroups_after_head_command\fi
+ \strc_itemgroups_insert_breakno}
+
+\unexpanded\def\strc_itemgroups_head_body_indeed
+ {\dostarttagged\t!itembody\empty
+ \noindentation}
+
+% Simple commands.
+
+\unexpanded\def\strc_itemgroups_start_do_item
+ {\startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_no_item % ?
+ {\startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_button[#destination]%
+ {\edef\m_strc_itemgroups_destination{#destination}%
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_symbol#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \startitemgroupitem
+ \dotagsetitem\s!symbol}
+
+\unexpanded\def\strc_itemgroups_start_dummy
+ {\strc_itemgroups_start_symbol\strut\strut} % two ?
+
+\unexpanded\def\strc_itemgroups_start_subitem
+ {\settrue\c_strc_itemgroups_sub
+ \startitemgroupitem
+ \dotagsetitem\s!sub}
+
+\unexpanded\def\strc_itemgroups_start_edge#text%
+ {\strc_itemgroups_start_symbol
+ {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \dostarttagged\t!ignore\empty % for the moment, maybe an attribute
+ \hbox to \d_strc_itemgroups_list_width
+ {#text\hskip\itemgroupparameter\c!distance}%
+ \dostoptagged}}
+
+\unexpanded\def\strc_itemgroups_start_margin#text%
+ {\def\strc_itemgroups_margin_symbol % brrr
+ {\dostarttagged\t!ignore\empty % for the moment, maybe an attribute
+ \llap
+ {\begingroup
+ \useitemgroupstyleandcolor\c!marstyle\c!marcolor
+ #text% keep em/ex local
+ \endgroup
+ \hskip\dimexpr\leftskip+\leftmargindistance\relax}%
+ \dostoptagged}%
+ \startitemgroupitem
+ \dotagsetitem\s!margin}
+
+\unexpanded\def\strc_itemgroups_start_text#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \settrue\c_strc_itemgroups_txt
+ \startitemgroupitem}
+
+% \unexpanded\def\strc_itemgroups_start_head
+% {\settrue\c_strc_itemgroups_head
+% \startitemgrouphead}
+
+\unexpanded\def\strc_itemgroups_start_items
+ {\dosingleempty\strc_itemgroups_start_items_indeed}
+
+\unexpanded\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost
+ {\strc_itemgroups_start_edge
+ {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}%
+ \unskip}}
+
+% \unexpanded\def\startspecialitemgroupitem[#name]%
+% {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname}
+
+\unexpanded\def\startspecialitemgroupitem[#name]%
+ {\ifcsname\??itemgroupstart#name\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\strc_itemgroups_start_do_item
+ \fi}
+
+\unexpanded\def\stopspecialitemgroupitem
+ {\stopitemgroupitem}
+
+\letvalue{\??itemgroupstart\v!item}\strc_itemgroups_start_do_item
+\letvalue{\??itemgroupstart\v!sub }\strc_itemgroups_start_subitem
+\letvalue{\??itemgroupstart\v!sym }\strc_itemgroups_start_symbol
+\letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge
+\letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items
+\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
+
+\def\optimizelistitemsbreak
+ {\ifcase\c_strc_itemgroups_column_depth \ifconditional\c_strc_itemgroups_optimize
+ \ifcase \c_strc_itemgroups_max_items \else
+ \ifnum\c_strc_itemgroups_max_items=\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items>\plusone
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \else\ifnum\c_strc_itemgroups_max_items>\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items=\plustwo
+ \ifconditional\c_strc_itemgroups_intro
+ \strc_itemgroups_insert_breakno
+ \else
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \else\ifnum\c_strc_itemgroups_max_items=\c_strc_itemgroups_n_of_items\relax
+ \strc_itemgroups_insert_nobreak
+ \else\ifnum\c_strc_itemgroups_n_of_items>\plustwo
+ \strc_itemgroups_insert_break
+ \else
+ \ifconditional\c_strc_itemgroups_intro\else\strc_itemgroups_insert_break\fi
+ \fi\fi\fi
+ \fi\fi
+ \fi
+ \fi\fi}
+
+\def\strc_itemgroups_handle_text_item
+ {\scratchdimen\wd\b_strc_itemgroups
+ \advance \scratchdimen \itemgroupparameter\c!distance\relax
+ \ifdim\scratchdimen>\d_strc_itemgroups_list_width
+ \advance\scratchdimen -\d_strc_itemgroups_list_width
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \llap{\hbox to \d_strc_itemgroups_list_width{\ifconditional\c_strc_itemgroups_sub\llap{+\enspace}\fi\box\b_strc_itemgroups\hss}}% was: \hfill
+ \hskip\scratchdimen}
+
+\def\strc_itemgroups_handle_lapped_item_positive
+ {\llap
+ {\dontcomplain
+ \hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \strc_itemgroups_left_sym_filler
+ \box\b_strc_itemgroups % can already have a forced widt, only factor handled here
+ \hfil
+ \hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_handle_lapped_item_negative
+ {\llap
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\leftmargindistance}}
+
+\def\strc_itemgroups_handle_groups_text_item
+ {\hbox
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ +\enspace
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\interwordspace}%
+ \nobreak}
+
+\def\strc_itemgroups_handle_groups_inline_item
+ {\hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \dostarttagged\t!ignore\empty
+ \llap{+\enspace}%
+ \dostoptagged
+ \fi
+ \box\b_strc_itemgroups
+ \hss}} % was: \hfill
+
+\unexpanded\def\strc_itemgroups_start_head_sym#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
+ \settrue\c_strc_itemgroups_head
+ \strc_itemgroups_start_head}
+
+\def\strc_itemgroups_make_symbol_box
+ {\setbox\b_strc_itemgroups\autodirhbox
+ {\ifconditional\c_strc_itemgroups_head
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor
+ \strc_itemgroups_used_symbol
+ \fi
+ \else
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol
+ \fi
+ \fi}%
+ \let\strc_itemgroups_extra_symbol\empty
+ \setfalse\c_strc_itemgroups_symbol}
+
+\def\strc_itemgroups_make_fitting_box
+ {\ifdim\wd\b_strc_itemgroups>\itemgroupparameter\c!maxwidth\relax
+ \normalexpanded{\global\setitemgroupparameter{\c!maxwidth}{\the\wd\b_strc_itemgroups}}%
+ \fi
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_max_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}%
+ \fi}
+
+\def\strc_itemgroups_make_aligned_box
+ {\doifsomething{\itemgroupparameter\c!itemalign}
+ {\setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_asked_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_make_destination_box
+ {\iftrialtypesetting \else \ifx\m_strc_itemgroups_destination\empty \else
+ \setbox\b_strc_itemgroups\hbox{\directgotobox{\box\b_strc_itemgroups}[\m_strc_itemgroups_destination]}%
+ \fi\fi}
+
+\def\strc_itemgroups_check_indenting
+ {\setfalse\c_strc_itemgroups_indented_first
+ \ifx\m_strc_itemgroups_indenting\empty \else
+ \normalexpanded{\setupindenting[\v!reset,\v!yes,\m_strc_itemgroups_indenting]}%
+ \ifconditional\c_spac_indentation_indent_first % better is to have a mode
+ \doifnot{\itemgroupparameter\c!alignsymbol}\v!yes
+ {\settrue\c_strc_itemgroups_indented_first}%
+ \fi
+ \fi}
+
+\def\strc_itemgroups_check_for_repeated
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \edef\m_strc_itemgroups_repeat_start{\currentitemlevel}%
+ \fi
+ \else
+ \let\m_strc_itemgroups_repeat_start\empty
+ \fi}
+
+\def\strc_itemgroups_insert_item
+ {\ifconditional\c_strc_itemgroups_text % again?
+ % begin of item
+ \else
+ \par % done twice?
+ \fi
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \optimizelistitemsbreak
+ \strc_itemgroups_check_indenting
+ \dontleavehmode
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip-\parindent
+ \fi
+ \strc_itemgroups_make_symbol_box
+ \strc_itemgroups_make_destination_box
+ \ifconditional\c_strc_itemgroups_fitting
+ \strc_itemgroups_make_fitting_box
+ \else\ifdim\d_strc_itemgroups_asked_width>\zeropoint
+ \strc_itemgroups_make_aligned_box
+ \fi\fi
+ \let\m_strc_itemgroups_destination\empty
+ \ht\b_strc_itemgroups\strutheight % just in case a symbols is not yet available in
+ \dp\b_strc_itemgroups\strutdepth % the current run (more a mkii mp side artifact)
+ \strc_itemgroups_check_for_repeated
+ \ifdim\d_strc_itemgroups_asked_width<\zeropoint\relax
+ \strc_itemgroups_handle_lapped_item_negative
+ \else
+ \ifdim\d_strc_itemgroups_asked_width=\zeropoint\relax
+ \strc_itemgroups_calculate_list_width\plusone
+ \else
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \fi
+ \ifconditional\c_strc_itemgroups_text
+ \strc_itemgroups_handle_groups_text_item
+ \else\ifconditional\c_strc_itemgroups_inline
+ \strc_itemgroups_handle_groups_inline_item
+ \else\ifconditional\c_strc_itemgroups_txt
+ \strc_itemgroups_handle_text_item
+ \else
+ \strc_itemgroups_handle_lapped_item_positive
+ \fi\fi\fi
+ \fi
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip\parindent
+ \fi
+ \ignorespaces}
+
+\def\strc_itemgroups_start_item_nop
+ {\let\currentitemreference\empty
+ \strc_itemgroups_increment_item_counter
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \setbox\b_strc_itemgroups\hbox
+ {\useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol}%
+ \strc_itemgroups_check_for_repeated
+ \ignorespaces}
+
+\setvalue{\??itemgroupdistance\v!none}%
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\setvalue{\??itemgroupdistance\v!space}%
+ {\def\m_strc_itemgroups_text_distance{\interwordspace\!!plus\interwordstretch\!!minus\interwordshrink}}
+
+\setvalue\??itemgroupdistance % catches empty value
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\unexpanded\def\strc_itemgroups_set_text_item_distance
+ {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}%
+ \ifx\m_strc_itemgroups_text_distance\empty
+ %
+ \else\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+ \lastnamedcs
+ \else
+ \strc_itemgroups_set_text_item_distance_indeed
+ \fi\fi}
+
+\def\strc_itemgroups_set_text_item_distance_indeed
+ {\assignvalue
+ \m_strc_itemgroups_text_distance
+ \m_strc_itemgroups_text_distance
+ {.5\interwordspace\!!plus.5\emwidth}%
+ {\interwordspace \!!plus \emwidth}%
+ {\emwidth \!!plus \interwordstretch\!!minus\interwordshrink}}
+
+% \unexpanded\def\strc_itemgroups_default_command
+% {\EveryPar{\ignorespaces}% needed ?
+% \ignorespaces}
+
+\unexpanded\def\strc_itemgroups_default_command
+ {\ignorespaces}
+
+%D Special case:
+
+\unexpanded\def\strc_itemgroups_head#text\par
+ {\startitemgrouphead{#text}}
+
+%D The local commands:
+
+\appendtoks
+ \let\item \strc_itemgroups_start_do_item
+ \let\noitem \strc_itemgroups_start_no_item
+ \let\itm \strc_itemgroups_start_do_item
+ \let\but \strc_itemgroups_start_button
+ \let\nop \strc_itemgroups_start_dummy
+ \let\txt \strc_itemgroups_start_text
+ \let\head \strc_itemgroups_head
+ \let\headsym \strc_itemgroups_start_head_sym
+ \let\startitem \startitemgroupitem
+ \let\stopitem \stopitemgroupitem
+ \let\starthead \startitemgrouphead
+ \let\stophead \stopitemgroupitemhead
+ \let\startspecialitem\startspecialitemgroupitem
+ \let\stopspecialitem \stopspecialitemgroupitem
+\to \itemgroupcommands
+
+\ifx\currentinterface \v!english \else
+
+ \appendtoks
+ \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item
+ \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem
+ \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol
+ \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge
+ \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head
+ \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items
+ \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin
+ \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text
+ \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem
+ \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem
+ \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead
+ \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead
+ \to \itemgroupcommands
+
+\fi
+
+\relaxvalueifundefined \v!item
+\relaxvalueifundefined \v!sub
+\relaxvalueifundefined \v!sym
+\relaxvalueifundefined \v!ran
+\relaxvalueifundefined \v!head
+\relaxvalueifundefined \v!its
+\relaxvalueifundefined \v!mar
+\relaxvalueifundefined \v!txt
+\relaxvalueifundefined {\e!start\v!item}
+\relaxvalueifundefined {\e!stop \v!item}
+\relaxvalueifundefined {\e!start\v!head}
+\relaxvalueifundefined {\e!stop \v!head}
+
+%D A nice example of a plugin:
+%D
+%D \startbuffer
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% better collectitems als conditional and a real plugin mechanism (some day)
+
+\newcount\c_strc_itemgroups_collected_stored
+\newcount\c_strc_itemgroups_collected_done
+\newcount\c_strc_itemgroups_collected_current
+
+% \expandafter\def\expandafter\strc_itemgroups_collected_store\expandafter#\expandafter1\csname\e!stop\v!item\endcsname % use grabuntil
+% {\advance\c_strc_itemgroups_collected_stored\plusone
+% \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}}
+
+\let\strc_itemgroups_collected_store\relax
+
+\normalexpanded{\def\strc_itemgroups_collected_store#1\csname\e!stop\v!item\endcsname}%
+ {\advance\c_strc_itemgroups_collected_stored\plusone
+ \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}}
+
+\def\strc_itemgroups_collected_flush_randomize
+ {\collecteditemgroupitem}
+
+\def\strc_itemgroups_collected_flush_horizontal
+ {\begingroup
+ \scratchcounter\itemgroupparameter\c!n\relax
+ \ifnum\c_strc_itemgroups_collected_done>\plusone
+ \ifcase\modulonumber\scratchcounter\c_strc_itemgroups_collected_done\relax
+ % compensate for rounding errors
+ \hfill % \hskip\zeropoint plus \scaledpoint minus \scaledpoint
+ \allowbreak
+ \fi
+ \fi
+ \noindent % no \dontleavehmode
+ \hbox to \dimexpr\availablehsize/\scratchcounter\relax{\collecteditemgroupitem\hss}%
+ \endgroup}
+
+% \def\strc_itemgroups_collected_flush_indeed
+% {\collecteditemgroupitem
+% \iftrialtypesetting
+% \undefinevalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+% \fi}
+
+\def\strc_itemgroups_collected_flush_indeed
+ {\collecteditemgroupitem
+ \undefinevalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}}
+
+\def\strc_itemgroups_collected_flush
+ {\ifconditional\c_strc_itemgroups_randomize
+ \getrandomcount\c_strc_itemgroups_collected_current\plusone\c_strc_itemgroups_collected_stored
+ \else
+ \advance\c_strc_itemgroups_collected_current\plusone
+ \fi
+ \ifcsname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname
+ \edef\collecteditemgroupitem{\lastnamedcs}%
+ \ifconditional\c_strc_itemgroups_horizontal
+ \strc_itemgroups_collected_flush_horizontal
+ \else
+ \strc_itemgroups_collected_flush_indeed
+ \fi
+ \advance\c_strc_itemgroups_collected_done\plusone
+ \fi
+ \ifnum\c_strc_itemgroups_collected_done<\c_strc_itemgroups_collected_stored
+ \expandafter\strc_itemgroups_collected_flush
+ \fi}
+
+\unexpanded\def\stopcollectitems
+ {\ifconditional\c_strc_itemgroups_collecting
+ \c_strc_itemgroups_collected_done \zerocount
+ \c_strc_itemgroups_collected_current\zerocount
+ \ifnum\c_strc_itemgroups_collected_stored>\zerocount
+ \doubleexpandafter\strc_itemgroups_collected_flush
+ \fi
+ \fi}
+
+\unexpanded\def\startcollectitems
+ {\ifconditional\c_strc_itemgroups_collecting
+ \c_strc_itemgroups_collected_stored\zerocount
+ \letvalue{\e!start\v!item}\strc_itemgroups_collected_store
+ \fi}
+
+%D Left-overs:
+
+\unexpanded\def\item
+ {\strc_itemgroups_item_alone}
+
+\def\strc_itemgroups_item_alone[#category]#text\par
+ {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \startitem#text\stopitem
+ \stopitemgroup}
+
+\unexpanded\def\head
+ {\strc_itemgroups_head_alone}
+
+\def\strc_itemgroups_head_alone[#category]#head\par#body\par
+ {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \starthead{#head}#body\stophead
+ \stopitemgroup}
+
+\setuvalue{\e!start\v!item}%
+ {\startitemgroup[\v!itemize]%
+ \startitemgroupitem
+ \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}}
+
+% \def\sym#text%
+% {\noindent
+% \begingroup
+% \setbox\scratchbox\hbox{\settrialtypesetting#text}%
+% \setbox\scratchbox\hbox\ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#text\hfil}%
+% \normalexpanded{\box\scratchbox\endgroup\hangindent\the\wd\scratchbox}%
+% \ignorespaces}
+
+%D End of plugin.
+
+%D Something for tables:
+
+\unexpanded\def\itemtag
+ {\dosingleempty\strc_itemgroups_item_tag}
+
+\unexpanded\def\strc_itemgroups_item_tag[#reference]% we can reuse more
+ {\def\currentitemreference{#reference}%
+ \iftrialtypesetting
+ \strc_counters_save\v_strc_itemgroups_counter
+ \strc_itemgroups_increment_item_counter
+ \strc_itemgroups_insert_item_tag_indeed
+ \strc_counters_restore\v_strc_itemgroups_counter
+ \else
+ \strc_itemgroups_increment_item_counter
+ \strc_itemgroups_insert_item_tag_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_item_tag_indeed
+ {\letitemgroupparameter\c!distance\zeropoint
+ %letitemgroupparameter\c!width\zeropoint
+ \strc_itemgroups_make_symbol_box
+ \strc_itemgroups_make_destination_box
+ \let\m_strc_itemgroups_destination\empty
+ \ht\b_strc_itemgroups\strutheight
+ \dp\b_strc_itemgroups\strutdepth
+ \box\b_strc_itemgroups
+ \ignorespaces}
+
+%D Done again.
+
+\setupitemgroup
+ [\c!margin=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!indentnext=\v!yes,
+ \c!width=1.5\emwidth,
+ \c!factor=0,
+ %\c!distance=.5em, % is now:
+ \c!step=.5\emwidth, % deals with broad
+ \c!distance=\zeropoint,
+ %\c!align=\v!normal, % definitely not \v!normal !
+ %\c!symalign=,
+ %\c!color=,
+ %\c!indenting=, % untouched if empty
+ %\c!style=,
+ \c!marstyle=\v!type,
+ %\c!symstyle=,
+ %\c!headstyle=,
+ %\c!marcolor=,
+ %\c!symcolor=,
+ %\c!headcolor=,
+ %\c!beforehead=,
+ \c!symcolor=\itemgroupparameter\c!color, % new per 2012.01.17
+ \c!symstyle=\itemgroupparameter\c!style, % new per 2012.01.17
+ \c!afterhead=\blank,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %\c!stopper=.,
+ \c!placestopper=\v!yes,
+ \c!stopper=.,
+ %\c!inner=,
+ \c!n=2,
+ \c!items=4,
+ \c!levels=10,
+ \c!lefttext=(,
+ \c!righttext=),
+ \c!start=1,
+ \c!criterium=\v!all, % permits 0 and negative numbers
+ %\c!option=,
+ \c!textdistance=\v!space, % none big medium small <dimension>
+ \c!command=\strc_itemgroups_default_command,
+ \c!indenting=\v!next,
+ %\c!alignsymbol=v!no,
+ \c!symbol=\currentitemlevel,
+ \c!prefix=\v!no,
+ %\c!prefixstopper=.,
+ %\c!prefixseparatorset=,
+ %\c!prefixconversion=,
+ %\c!prefixconversionset=,
+ %\c!prefixset=,
+ %\c!prefixsegments=1:100,
+ \c!prefixconnector=.,
+ \c!numberseparatorset=,
+ \c!numberconversionset=,
+ \c!numberstopper=.,
+ \c!numbersegments=1]
+
+\defineitemgroup
+ [\v!itemize]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-lab.mkiv
new file mode 100644
index 00000000000..ac49941aaee
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lab.mkiv
@@ -0,0 +1,198 @@
+%D \module
+%D [ file=strc-lab, % was part of strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Labels,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Labels}
+
+\unprotect
+
+% todo: reset and increment will go
+
+%D Labels are implemented somewhat inefficient but have the advantage that they
+%D can be controlled like other constructions. Who knows when that comes in
+%D handy?
+
+\installcorenamespace{labels}
+
+\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one)
+
+\installcounterassociation{label}
+
+\let\setuplabels\setuplabel
+
+\setuplabel
+ [\c!alternative=\v!intext,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ \c!distance=\zeropoint,
+ \c!width=\v!fit,
+ \c!titledistance=.5\emwidth,
+ \c!margin=\v!no,
+ \c!titleleft=(,
+ \c!titleright=),
+ \c!display=\v!no,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ \c!text=\currentlabel,
+ \c!number=\v!yes, % else description
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=3]
+
+\unexpanded\def\strc_define_commands_label#1#2#3% current level parent
+ {\doifelsenothing{#3}
+ {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label}}%
+ {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label#3}}%
+ \ifconditional\c_strc_constructions_define_commands
+ \setuevalue{\e!next #1}{\strc_labels_next {#1}{\number#2}}% obsolete
+ \setuevalue{\v!reset #1}{\strc_labels_reset {#1}{\number#2}}% obsolete % should be \e!reset anyway
+ %setuevalue{\c!set #1}{\strc_labels_set {#1}{\number#2}}% obsolete
+ \ifcsname\v!current#1\endcsname
+ % we play safe
+ \else
+ \setuevalue{\v!current#1}{\strc_labels_current{#1}}% % obsolete % should be \e!current anyway
+ \fi
+ \setuevalue {#1}{\strc_labels_command{#1}}%
+ \fi}
+
+% todo: \strc_labels_command for user
+
+\appendtoks
+ \ifx\currentlabelparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentlabelsub\empty
+ \strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \plusone
+ \empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_label
+ {\v!sub\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabel}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentlabelsub\empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabelparent}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
+ \fi
+ \edef\p_counter{\labelparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentlabel
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_labels_define_counter\p_counter}%
+ \letlabelparameter\s!counter\p_counter
+\to \everydefinelabel
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\newconditional\c_strc_constructions_number_keep
+
+\setvalue{\??constructioninitializer\v!label}%
+ {\let\currentlabel \currentconstruction
+ \let\constructionparameter \labelparameter
+ \let\constructionnamespace \??label
+ \let\detokenizedconstructionparameter\detokenizedlabelparameter
+ \let\letconstructionparameter \letlabelparameter
+ \let\useconstructionstyleandcolor \uselabelstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentlabel
+ % shared with enumerations
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ \ifconditional\c_strc_constructions_number_keep \else
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\setvalue{\??constructionfinalizer\v!label}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Interfaces:
+
+\unexpanded\def\strc_labels_command{\setfalse\c_strc_constructions_number_keep\strc_descriptions_command}
+\unexpanded\def\strc_labels_current{\settrue \c_strc_constructions_number_keep\strc_descriptions_command}
+
+\unexpanded\def\strc_labels_next {\strc_constructions_next_indeed \namedlabelparameter} % #1#2
+\unexpanded\def\strc_labels_reset {\strc_constructions_reset_indeed\namedlabelparameter} % #1#2
+%unexpanded\def\strc_labels_set {\strc_constructions_set_indeed \namedlabelparameter} % #1#2
+
+% similar to enumerations
+
+\def\strc_labels_define_counter#1%
+ {\definecounter[#1]%
+ \registerlabelcounter{#1}}
+
+\appendtoks
+ \synchronizelabelcounters
+\to \everysetuplabel
+
+\appendtoks
+ \synchronizelabelcounters
+\to \everydefinelabel
+
+% no start stop here
+
+\expandafter\let\csname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname
+
+\unexpanded\setevalue{\??constructioncommandhandler\v!label}%
+ {\csname\??constructionstarthandler\v!construction\endcsname
+ \csname\??constructionstophandler \v!construction\endcsname
+ \endgroup}
+
+\unexpanded\setvalue{\??constructiontexthandler\v!label}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_labels_text
+ \endgroup}
+
+\let\strc_labels_text\strc_enumerations_text
+
+% inline variant
+
+\defineconstructionalternative
+ [\v!intext]
+ [\c!renderingsetup=\??constructionrenderings:\v!intext]
+
+\startsetups[\??constructionrenderings:\v!intext]
+ \dontleavehmode\box\constructionheadbox
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lev.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-lev.lua
new file mode 100644
index 00000000000..d7ffd6af434
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lev.lua
@@ -0,0 +1,75 @@
+if not modules then modules = { } end modules ['strc-lev'] = {
+ version = 1.001,
+ comment = "companion to strc-lev.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove = table.insert, table.remove
+
+local context = context
+local interfaces = interfaces
+
+local sections = structures.sections
+local implement = interfaces.implement
+
+local v_default = interfaces.variables.default
+
+sections.levels = sections.levels or { }
+
+local level = 0
+local levels = sections.levels
+local categories = { }
+
+local f_two_colon = string.formatters["%s:%s"]
+
+storage.register("structures/sections/levels", levels, "structures.sections.levels")
+
+local function definesectionlevels(category,list)
+ levels[category] = utilities.parsers.settings_to_array(list)
+end
+
+local function startsectionlevel(category)
+ category = category ~= "" and category or v_default
+ level = level + 1
+ local lc = levels[category]
+ if not lc or level > #lc then
+ context.nostarthead { f_two_colon(category,level) }
+ else
+ context.dostarthead { lc[level] }
+ end
+ insert(categories,category)
+end
+
+local function stopsectionlevel()
+ local category = remove(categories)
+ if category then
+ local lc = levels[category]
+ if not lc or level > #lc then
+ context.nostophead { f_two_colon(category,level) }
+ else
+ context.dostophead { lc[level] }
+ end
+ level = level - 1
+ else
+ -- error
+ end
+end
+
+implement {
+ name = "definesectionlevels",
+ actions = definesectionlevels,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "startsectionlevel",
+ actions = startsectionlevel,
+ arguments = "string"
+}
+
+implement {
+ name = "stopsectionlevel",
+ actions = stopsectionlevel,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lev.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-lev.mkvi
new file mode 100644
index 00000000000..dae3f28e30e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lev.mkvi
@@ -0,0 +1,96 @@
+%D \module
+%D [ file=strc-lev,
+%D version=2010.09.23,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Automatic Levels,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Automatic Levels}
+
+%D This module is the result of a discussion between Alan Braslau and
+%D me. I used to have a private (\MKII) module for this but the new
+%D structure code in \MKIV\ is more suitable for this so now we have
+%D it as core functionality. For the moment this an experiment that
+%D Alan and I conduct so it might evolve.
+
+\registerctxluafile{strc-lev}{1.001}
+
+\unprotect
+
+\unexpanded\def\definesectionlevels{\dodoubleargument\strc_levels_define}
+\unexpanded\def\startsectionlevel {\dosingleempty \strc_levels_start }
+
+\unexpanded\def\strc_levels_define[#category][#list]{\clf_definesectionlevels{#category}{#list}}
+\unexpanded\def\strc_levels_start [#category]{\clf_startsectionlevel{#category}}
+\unexpanded\def\stopsectionlevel {\clf_stopsectionlevel}
+
+\unexpanded\def\nostarthead{\dotripleargument\strc_levels_start_nop} % used at the lua end
+\unexpanded\def\nostophead {\dosingleargument\strc_levels_stop_nop } % used at the lua end
+
+\unexpanded\def\strc_levels_start[#category]%
+ {\doifelseassignment{#category}
+ {\clf_startsectionlevel{\v!default}[#category]}
+ {\clf_startsectionlevel{#category}}}
+
+\unexpanded\def\strc_levels_start_nop[#category][#settings][#userdata]%
+ {\blank
+ \noindentation{\tttf[start missing section level #category]}
+ \blank}
+
+\unexpanded\def\strc_levels_stop_nop[#category]%
+ {\blank
+ \noindentation{\tttf[stop missing section level #category]}
+ \blank}
+
+\definesectionlevels
+ [\v!default]
+ [\v!chapter,
+ \v!section,
+ \v!subsection,
+ \v!subsubsection,
+ \v!subsubsubsection,
+ \v!subsubsubsubsection]
+
+
+\let\definestructurelevels\definesectionlevels
+\let\startstructurelevel \startsectionlevel
+\let\stopstructurelevel \stopsectionlevel
+
+\protect \endinput
+
+% \starttext
+%
+% \definehead[xxxxxxsection][subsubsection]
+% \setuphead [xxxxxxsection][color=red]
+%
+% \definesectionlevels[main][chapter,section,subsection,subsubsection]
+% \definesectionlevels[next][chapter,section,subsection,xxxxxxsection]
+%
+% \startsectionlevel [main] [title=first top level]
+%
+% \startsectionlevel [main] [title=first lower level]
+% \startsectionlevel [main] [title=second lower level]
+% \startsectionlevel [main] [title=third lower level]
+% test
+% \stopsectionlevel
+% \stopsectionlevel
+% \stopsectionlevel
+%
+% \startsectionlevel [main] [title=first lower level]
+% \startsectionlevel [main] [title=second lower level]
+% \startsectionlevel [next] [title=third lower level]
+% test
+% \stopsectionlevel
+% \stopsectionlevel
+% \stopsectionlevel
+%
+% \stopsectionlevel
+%
+% \stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi
new file mode 100644
index 00000000000..cd10c9def20
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi
@@ -0,0 +1,369 @@
+%D \module
+%D [ file=strc-lnt,
+%D version=2002.05.10,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Line Notes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: mkvi #
+
+\writestatus{loading}{ConTeXt Structure Macros / Line Notes}
+
+%D This module loads on top of the footnote and line numbering macros.
+
+\unprotect
+
+\installcorenamespace{linenote}
+
+\let\setuplinenote\setupnote
+
+\newcount\c_strc_linenotes
+\newtoks\everydefinelinenote
+
+\unexpanded\def\definelinenote
+ {\dotripleempty\strc_linenotes_define}
+
+\def\strc_linenotes_define[#1][#2][#3]%
+ {\ifcsname\??linenote#1\endcsname
+ % there might be files that define the default 'linenote'
+ \ifthirdargument
+ \setupnote[#1][#3]%
+ \else\ifsecondargument
+ \setupnote[#1][#2]%
+ \fi\fi
+ \else
+ \ifthirdargument
+ \definenote[#1][#2][#3]%
+ \else\ifsecondargument
+ \definenote[#1][#2]%
+ \else
+ \definenote[#1]%
+ \fi\fi
+ \pushmacro\currentnote
+ \edef\currentnote{#1}
+ \expandafter\let\csname\??linenote\currentnote\expandafter\endcsname\csname\currentnote\endcsname % use copy command
+ \setuevalue {\currentnote}{\strc_linenotes_direct{\currentnote}}%
+ \setuevalue{\e!start\currentnote}{\strc_linenotes_start {\currentnote}}%
+ \setuevalue{\e!stop \currentnote}{\strc_linenotes_stop }%
+ \the\everydefinelinenote
+ \popmacro\currentnote
+ \fi}
+
+\unexpanded\def\strc_linenotes_direct#1#2%
+ {\global\advance\c_strc_linenotes\plusone
+ \strc_linenotes_indeed{#1}{\the\c_strc_linenotes}{#2}%
+ \strc_linenotes_traced\empty
+ \normalexpanded{\someline[\the\c_strc_linenotes]}}
+
+\unexpanded\def\strc_linenotes_start#1[#2]#3%
+ {\global\advance\c_strc_linenotes\plusone
+ \keepunwantedspaces
+ \strc_linenotes_indeed{#1}{#2}{#3}%
+ \strc_linenotes_traced{#2}%
+ \startline[#2]}
+
+\unexpanded\def\strc_linenotes_stop[#1]%
+ {\stopline[#1]}
+
+\let\m_page_lines_previous_to \relax
+\let\m_page_lines_previous_from\relax
+
+\let\m_page_lines_current_to \relax
+\let\m_page_lines_current_from \relax
+
+\newconditional\c_page_lines_current_to
+\newconditional\c_page_lines_current_from
+
+\installcorenamespace{linenotespreviousfrom}
+\installcorenamespace{linenotespreviousto}
+
+\letvalue\??linenotespreviousfrom\empty
+\letvalue\??linenotespreviousto \empty
+
+% maybe do this in lua
+
+\def\page_lines_in_from{\in[lr:b:\currentlinenotereference]}
+\def\page_lines_in_to {\in[lr:e:\currentlinenotereference]}
+
+\unexpanded\def\strc_linenotes_range_normal#1% order
+ {\doifelsereferencefound{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from
+ \ifconditional\c_page_lines_current_from
+ \xdef\m_page_lines_current_from{\currentreferencelinenumber}%
+ \doifelsereferencefound{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to
+ \ifconditional\c_page_lines_current_to
+ \xdef\m_page_lines_current_to{\currentreferencelinenumber}%
+ \page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to \else
+ \endash
+ \page_lines_in_to
+ \fi
+ \else
+ \page_lines_in_from
+ \fi
+ \else
+ \page_lines_in_from
+ \fi}
+
+\unexpanded\def\strc_linenotes_range_sparse#1% order
+ {\doifelsereferencefound{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from
+ \ifconditional\c_page_lines_current_from
+ \xdef\m_page_lines_current_from{\currentreferencelinenumber}%
+ \doifelsereferencefound{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to
+ \ifconditional\c_page_lines_current_to
+ \xdef\m_page_lines_current_to{\currentreferencelinenumber}%
+ \ifx\m_page_lines_previous_from\m_page_lines_current_from
+ \ifx\m_page_lines_previous_to\m_page_lines_current_to \else
+ \page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to\else\endash\page_lines_in_to\fi
+ \fi
+ \else
+ \page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to\else\endash\page_lines_in_to\fi
+ \fi
+ \else
+ \page_lines_in_from
+ \fi
+ \else
+ \ifx\m_page_lines_previous_from\m_page_lines_current_from \else
+ \page_lines_in_from
+ \fi
+ \fi}
+
+\let\currentlinenotereference\empty
+
+\unexpanded\def\strc_linenotes_indeed#1#2#3%
+ {\begingroup
+ % we keep things local so we can use it as regular note too
+ \edef\currentnotation{#1}%
+ \edef\currentlinenotereference{#2}%
+ \xdef\m_page_lines_previous_from{\begincsname\??linenotespreviousfrom\currentnotation\endcsname}%
+ \xdef\m_page_lines_previous_to {\begincsname\??linenotespreviousto \currentnotation\endcsname}%
+ \strc_linenotes_check_compression
+ \let\currentnote\currentnotation
+ \letnotationparameter\c!numbercommand\linenotelinenumber% todo: deep hook
+ \letnoteparameter \c!textcommand \gobbleoneargument % todo: deep hook
+ \csname\??linenote\currentnotation\endcsname{#3}%
+ \expandafter\glet\csname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from
+ \expandafter\glet\csname\??linenotespreviousto \currentnotation\endcsname\m_page_lines_current_to
+ \endgroup}
+
+% compression
+
+\installcorenamespace{linenotescompressmethod}
+
+% compress=yes|no
+% compressmethod=separator|stopper
+
+\def\c!compressdistance{compressdistance}
+\def\c!compressmethod {compressmethod}
+\def\c!compressstopper {compressstopper} % c
+\def\v!compressstopper {compressstopper} % v
+
+\def\v!separator {separator} % v
+
+\setvalue{\??linenotescompressmethod\v!separator}%
+ {\edef\p_compressseparator{\noteparameter\c!compressseparator}%
+ \scratchskip\noteparameter\c!compressdistance\relax
+ \ifx\p_compressseparator\empty
+ \hskip\scratchskip
+ \else
+ \hskip.5\scratchskip
+ \p_compressseparator
+ \hskip.5\scratchskip
+ \fi}
+
+\setvalue{\??linenotescompressmethod\v!stopper}%
+ {\edef\p_compressstopper{\noteparameter\c!compressstopper}%
+ \scratchskip\noteparameter\c!compressdistance\relax
+ \ifx\p_compressstopper\empty
+ \hskip\scratchskip
+ \else
+ \p_compressstopper
+ \hskip.5\scratchskip
+ \fi}
+
+\setvalue{\??linenotescompressmethod\v!space}%
+ {\hskip\noteparameter\c!compressdistance\relax}
+
+\def\strc_linenotes_check_compression
+% {\edef\p_linenotes_compress {\notationparameter\c!compress}%
+% \edef\p_linenotes_compressmethod{\notationparameter\c!compressmethod}%
+ {\edef\p_linenotes_compress {\noteparameter\c!compress}%
+ \edef\p_linenotes_compressmethod{\noteparameter\c!compressmethod}%
+ \ifx\p_linenotes_compress\v!yes
+ \let\linenotelinenumber\strc_linenotes_range_sparse
+ \else
+ \let\linenotelinenumber\strc_linenotes_range_normal
+ \fi
+ \ifcsname\??linenotescompressmethod\p_linenotes_compressmethod\endcsname \else
+ \let\p_linenotes_compressmethod\v!space
+ \fi}
+
+\def\strc_linenotes_inbetween % \ifcsname\??linenote\currentnote\expandafter\endcsname
+ {\csname\??linenotescompressmethod\p_linenotes_compressmethod\endcsname}
+
+\def\strc_notes_compress_distance{\emwidth \s!plus .5\emwidth \s!minus .25\emwidth}
+
+\setupnotes
+ [%c\compress=\v!no,
+ \c!compressdistance=\strc_notes_compress_distance,
+ \c!compressseparator=\symbol{\v!compressseparator},
+ \c!compressstopper=\symbol{\v!compressstopper}]
+
+\appendtoks
+ \letnoteparameter\c!inbetween\strc_linenotes_inbetween
+\to \everydefinelinenote
+
+% where to hook this one in? resetcounter has no hook:
+
+\unexpanded\def\doresetlinenotecompression#1% \strc_linenotes_reset_previous
+ {\expandafter\glet\csname\??linenotespreviousfrom#1\endcsname\empty
+ \expandafter\glet\csname\??linenotespreviousto #1\endcsname\empty}
+
+\definesymbol
+ [\v!compressseparator]
+ [\hbox{\vl\thinspace\vl}] % \space removed
+
+\definesymbol
+ [\v!compressstopper]
+ [,]
+
+% \setupnotations
+% [%c\compress=\v!no,
+% \c!compressseparator=\symbol\v!compressseparator]
+
+\let\strc_linenotes_traced\gobbleoneargument
+
+\def\strc_linenotes_traced_indeed#1%
+ {\iftracelinenotes
+ \hbox to \zeropoint
+ {\forgetall
+ \hsize\zeropoint
+ \hss
+ \vbox to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}%
+ {\color[blue]{\vl}}%
+ \vbox to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}%
+ \hss}%
+ \prewordbreak
+ \fi}
+
+\unexpanded\def\tracelinenotes
+ {\let\strc_linenotes_traced\strc_linenotes_traced_indeed}
+
+% We predefine one, namely \type {\linenote} cum suis.
+
+\definelinenote[\v!linenote]
+
+%D Use these when not properly nested:
+
+\let\fromlinenote\startlinenote
+\let\tolinenote \stoplinenote
+
+% beware: line numbers are added later on so grouping setups is a bad idea
+%
+% \startbuffer[test]
+% \startlinenumbering[100]
+% test \linenote {oeps 1} test test test test test test
+% test \startlinenote [well] {oeps X} test test test test test test
+% test \linenote {oeps 2} test test test test test test
+% test \linenote {oeps 3} test test test test test test
+% test \linenote {oeps 4} test test test test test test
+% test \linenote {oeps 5} test test test test test test
+% test \stoplinenote [well] test test test test test test
+% \stoplinenumbering
+% \stopbuffer
+%
+% \typebuffer[test] \getbuffer[test] \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [align=flushleft]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup,test] \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [width=4em,
+% distance=1em,
+% align=flushright]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup,test] \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [width=4em,
+% align=flushleft]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup,test] \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [width=2em,
+% distance=.5em,
+% align=middle]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup,test] \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [conversion=romannumerals,
+% start=1,
+% step=1,
+% location=text,
+% style=slanted,
+% color=blue,
+% width=1.5em]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup] \startnarrower\getbuffer[test]\stopnarrower \page
+%
+% \startbuffer[setup]
+% \setuplinenumbering
+% [width=4em,
+% left=--,
+% right=--,
+% align=middle]
+% \stopbuffer
+%
+% \typebuffer[setup] \getbuffer[setup,test] \page
+%
+% \startbuffer[setup-1]
+% \setuplinenumbering
+% [style=\bfxx,
+% command=\WatchThis]
+% \stopbuffer
+%
+% \startbuffer[setup-2]
+% \def\WatchThis#1%
+% {\ifodd\linenumber
+% \definecolor[linecolor][red]%
+% \else
+% \definecolor[linecolor][green]%
+% \fi
+% \inframed
+% [offset=1pt,frame=off,background=color,backgroundcolor=linecolor]
+% {#1}}
+% \stopbuffer
+%
+% \typebuffer[setup-1,setup-2] \getbuffer[setup-1,setup-2,test] \page
+%
+% \startbuffer[setup-1]
+% \setuplinenumbering
+% [location=inright,
+% style=\bfxx,
+% command=\WatchThis]
+% \stopbuffer
+%
+% \typebuffer[setup-1] \getbuffer[setup-1,setup-2,test] \page
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua
new file mode 100644
index 00000000000..0f5d8e0d7b8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua
@@ -0,0 +1,1340 @@
+if not modules then modules = { } end modules ['strc-lst'] = {
+ version = 1.001,
+ comment = "companion to strc-lst.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- when all datastructures are stable a packer will be added which will
+-- bring down memory consumption a bit; we can use for instance a pagenumber,
+-- section, metadata cache (internal then has to move up one level) or a
+-- shared cache [we can use a fast and stupid serializer]
+
+-- todo: tag entry in list is crap
+--
+-- move more to commands
+
+local tonumber, type = tonumber, type
+local concat, insert, remove, sort = table.concat, table.insert, table.remove, table.sort
+local lpegmatch = lpeg.match
+
+local setmetatableindex = table.setmetatableindex
+local sortedkeys = table.sortedkeys
+
+local settings_to_set = utilities.parsers.settings_to_set
+local allocate = utilities.storage.allocate
+local checked = utilities.storage.checked
+
+local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end)
+
+local report_lists = logs.reporter("structure","lists")
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+local conditionals = tex.conditionals
+
+local structures = structures
+local lists = structures.lists
+local sections = structures.sections
+local helpers = structures.helpers
+local documents = structures.documents
+local tags = structures.tags
+local counters = structures.counters
+local references = structures.references
+
+local collected = allocate()
+local tobesaved = allocate()
+local cached = allocate()
+local pushed = allocate()
+local kinds = allocate()
+local names = allocate()
+
+lists.collected = collected
+lists.tobesaved = tobesaved
+
+lists.enhancers = lists.enhancers or { }
+-----.internals = allocate(lists.internals or { }) -- to be checked
+lists.ordered = allocate(lists.ordered or { }) -- to be checked
+lists.cached = cached
+lists.pushed = pushed
+lists.kinds = kinds
+lists.names = names
+
+local sorters = sorters
+local sortstripper = sorters.strip
+local sortsplitter = sorters.splitters.utf
+local sortcomparer = sorters.comparers.basic
+
+local sectionblocks = allocate()
+lists.sectionblocks = sectionblocks
+
+references.specials = references.specials or { }
+
+local matchingtilldepth = sections.matchingtilldepth
+local numberatdepth = sections.numberatdepth
+local getsectionlevel = sections.getlevel
+local typesetnumber = sections.typesetnumber
+local autosectiondepth = sections.autodepth
+
+local variables = interfaces.variables
+
+local v_all = variables.all
+local v_reference = variables.reference
+local v_title = variables.title
+local v_number = variables.reference
+local v_command = variables.command
+local v_text = variables.text
+local v_current = variables.current
+local v_previous = variables.previous
+local v_next = variables.next
+local v_intro = variables.intro
+local v_here = variables.here
+local v_component = variables.component
+local v_reference = variables.reference
+local v_local = variables["local"]
+local v_default = variables.default
+
+-- for the moment not public --
+
+local function zerostrippedconcat(t,separator)
+ local f, l = 1, #t
+ for i=f,l do
+ if t[i] == 0 then
+ f = f + 1
+ end
+ end
+ for i=l,f,-1 do
+ if t[i] == 0 then
+ l = l - 1
+ end
+ end
+ return concat(t,separator,f,l)
+end
+
+-- -- -- -- -- --
+
+local function initializer()
+ -- create a cross reference between internal references
+ -- and list entries
+ local collected = lists.collected
+ local internals = checked(references.internals)
+ local ordered = lists.ordered
+ local usedinternals = references.usedinternals
+ local blockdone = { }
+ local lastblock = nil
+ for i=1,#collected do
+ local c = collected[i]
+ local m = c.metadata
+ local r = c.references
+ if m then
+ -- access by internal reference
+ if r then
+ local internal = r.internal
+ if internal then
+ internals[internal] = c
+ usedinternals[internal] = r.used
+ end
+ local block = r.block
+ if not block then
+ -- shouldn't happen
+ elseif lastblock == block then
+ -- we're okay
+ elseif lastblock then
+ if blockdone[block] then
+ report_lists("out of order sectionsblocks, maybe use \\setsectionblock")
+ else
+ blockdone[block] = true
+ sectionblocks[#sectionblocks+1] = block
+ end
+ lastblock = block
+ elseif not blockdone[block] then
+ blockdone[block] = true
+ sectionblocks[#sectionblocks+1] = block
+ lastblock = block
+ end
+ end
+ -- access by order in list
+ local kind = m.kind
+ local name = m.name
+ if kind and name then
+ local ok = ordered[kind]
+ if ok then
+ local on = ok[name]
+ if on then
+ on[#on+1] = c
+ else
+ ok[name] = { c }
+ end
+ else
+ ordered[kind] = { [name] = { c } }
+ end
+ kinds[kind] = true
+ names[name] = true
+ elseif kind then
+ kinds[kind] = true
+ elseif name then
+ names[name] = true
+ end
+ end
+ if r then
+ r.listindex = i -- handy to have
+ end
+ end
+end
+
+local function finalizer()
+ local flaginternals = references.flaginternals
+ local usedviews = references.usedviews
+ for i=1,#tobesaved do
+ local r = tobesaved[i].references
+ if r then
+ local i = r.internal
+ local f = flaginternals[i]
+ if f then
+ r.used = usedviews[i] or true
+ end
+ end
+ end
+end
+
+job.register('structures.lists.collected', tobesaved, initializer, finalizer)
+
+local groupindices = setmetatableindex("table")
+
+function lists.groupindex(name,group)
+ local groupindex = groupindices[name]
+ return groupindex and groupindex[group] or 0
+end
+
+-- we could use t (as hash key) in order to check for dup entries
+
+function lists.addto(t) -- maybe more more here (saves parsing at the tex end)
+ local metadata = t.metadata
+ local userdata = t.userdata
+ local numberdata = t.numberdata
+ if userdata and type(userdata) == "string" then
+ t.userdata = helpers.touserdata(userdata)
+ end
+ if not metadata.level then
+ metadata.level = structures.sections.currentlevel() -- this is not used so it will go away
+ end
+ --
+ -- if not conditionals.inlinelefttoright then
+ -- metadata.idir = "r2l"
+ -- end
+ -- if not conditionals.displaylefttoright then
+ -- metadata.ddir = "r2l"
+ -- end
+ --
+ if numberdata then
+ local numbers = numberdata.numbers
+ if type(numbers) == "string" then
+ numberdata.numbers = counters.compact(numbers,nil,true)
+ end
+ end
+ local group = numberdata and numberdata.group
+ local name = metadata.name
+ local kind = metadata.kind
+ if not group then
+ -- forget about it
+ elseif group == "" then
+ group, numberdata.group = nil, nil
+ else
+ local groupindex = groupindices[name][group]
+ if groupindex then
+ numberdata.numbers = cached[groupindex].numberdata.numbers
+ end
+ end
+ local setcomponent = references.setcomponent
+ if setcomponent then
+ setcomponent(t) -- can be inlined
+ end
+ local r = t.references
+ if r and not r.section then
+ r.section = structures.sections.currentid()
+ end
+ local i = r and r.internal or 0 -- brrr
+ if r and kind and name then
+ local tag = tags.getid(kind,name)
+ if tag and tag ~= "?" then
+ r.tag = tag -- todo: use internal ... is unique enough
+ end
+ end
+ local p = pushed[i]
+ if not p then
+ p = #cached + 1
+ cached[p] = helpers.simplify(t)
+ pushed[i] = p
+ if r then
+ r.listindex = p
+ end
+ end
+ if group then
+ groupindices[name][group] = p
+ end
+ if trace_lists then
+ report_lists("added %a, internal %a",name,p)
+ end
+ return p
+end
+
+function lists.discard(n)
+ n = tonumber(n)
+ if not n then
+ -- maybe an error message
+ elseif n == #cached then
+ cached[n] = nil
+ n = n - 1
+ while n > 0 and cached[n] == false do
+ cached[n] = nil -- collect garbage
+ n = n - 1
+ end
+ else
+ cached[n] = false
+ end
+end
+
+function lists.iscached(n)
+ return cached[tonumber(n)]
+end
+
+-- this is the main pagenumber enhancer
+
+local enhanced = { }
+
+local synchronizepage = function(r) -- bah ... will move
+ synchronizepage = references.synchronizepage
+ return synchronizepage(r)
+end
+
+function lists.enhance(n)
+ local l = cached[n]
+ if not l then
+ report_lists("enhancing %a, unknown internal",n)
+ elseif enhanced[n] then
+ if trace_lists then
+ report_lists("enhancing %a, name %a, duplicate ignored",n,name)
+ end
+ else
+ local metadata = l.metadata
+ local references = l.references
+ --
+ l.directives = nil -- might change
+ -- save in the right order (happens at shipout)
+ lists.tobesaved[#lists.tobesaved+1] = l
+ -- default enhancer (cross referencing)
+ synchronizepage(references)
+ -- tags
+ local kind = metadata.kind
+ local name = metadata.name
+ if trace_lists then
+ report_lists("enhancing %a, name %a, page %a",n,name,references.realpage or 0)
+ end
+-- if references then
+-- -- is this used ?
+-- local tag = tags.getid(kind,name)
+-- if tag and tag ~= "?" then
+-- references.tag = tag
+-- end
+-- end
+ -- specific enhancer (kind of obsolete)
+ local enhancer = kind and lists.enhancers[kind]
+ if enhancer then
+ enhancer(l)
+ end
+ --
+ enhanced[n] = true
+ return l
+ end
+end
+
+-- we can use level instead but we can also decide to remove level from the metadata
+
+local nesting = { }
+
+function lists.pushnesting(i)
+ local parent = lists.result[i]
+ local name = parent.metadata.name
+ local numberdata = parent and parent.numberdata
+ local numbers = numberdata and numberdata.numbers
+ local number = numbers and numbers[getsectionlevel(name)] or 0
+ insert(nesting, {
+ number = number,
+ name = name,
+ result = lists.result,
+ parent = parent
+ })
+end
+
+function lists.popnesting()
+ local old = remove(nesting)
+ if old then
+ lists.result = old.result
+ else
+ report_lists("nesting error")
+ end
+end
+
+-- Historically we had blocks but in the mkiv approach that could as well be a level
+-- which would simplify things a bit.
+
+local splitter = lpeg.splitat(":") -- maybe also :: or have a block parameter
+
+local listsorters = {
+ [v_command] = function(a,b)
+ if a.metadata.kind == "command" or b.metadata.kind == "command" then
+ return a.references.internal < b.references.internal
+ else
+ return a.references.order < b.references.order
+ end
+ end,
+ [v_all] = function(a,b)
+ return a.references.internal < b.references.internal
+ end,
+ [v_title] = function(a,b)
+ local da = a.titledata
+ local db = b.titledata
+ if da and db then
+ local ta = da.title
+ local tb = db.title
+ if ta and tb then
+ local sa = da.split
+ if not sa then
+ sa = sortsplitter(sortstripper(ta))
+ da.split = sa
+ end
+ local sb = db.split
+ if not sb then
+ sb = sortsplitter(sortstripper(tb))
+ db.split = sb
+ end
+ return sortcomparer(da,db) == -1
+ end
+ end
+ return a.references.internal < b.references.internal
+ end
+}
+
+-- was: names, criterium, number, collected, forced, nested, sortorder
+
+local filters = setmetatableindex(function(t,k) return t[v_default] end)
+
+local function filtercollected(specification)
+ --
+ local names = specification.names or { }
+ local criterium = specification.criterium or v_default
+ local number = 0 -- specification.number
+ local reference = specification.reference or ""
+ local collected = specification.collected or lists.collected
+ local forced = specification.forced or { }
+ local nested = specification.nested or false
+ local sortorder = specification.sortorder or specification.order
+ --
+ local numbers = documents.data.numbers
+ local depth = documents.data.depth
+ local block = false -- all
+ local wantedblock, wantedcriterium = lpegmatch(splitter,criterium) -- block:criterium
+ if wantedblock == "" or wantedblock == v_all or wantedblock == v_text then
+ criterium = wantedcriterium ~= "" and wantedcriterium or criterium
+ elseif not wantedcriterium then
+ block = documents.data.block
+ else
+ block, criterium = wantedblock, wantedcriterium
+ end
+ if block == "" then
+ block = false
+ end
+ if type(names) == "string" then
+ names = settings_to_set(names)
+ end
+ local all = not next(names) or names[v_all] or false
+ --
+ specification.names = names
+ specification.criterium = criterium
+ specification.number = 0 -- obsolete
+ specification.reference = reference -- new
+ specification.collected = collected
+ specification.forced = forced -- todo: also on other branched, for the moment only needed for bookmarks
+ specification.nested = nested
+ specification.sortorder = sortorder
+ specification.numbers = numbers
+ specification.depth = depth
+ specification.block = block
+ specification.all = all
+ --
+ if trace_lists then
+ report_lists("filtering names %,t, criterium %a, block %a",sortedkeys(names), criterium, block or "*")
+ end
+ local result = filters[criterium](specification)
+ if trace_lists then
+ report_lists("criterium %a, block %a, found %a",specification.criterium, specification.block or "*", #result)
+ end
+ --
+ if sortorder then -- experiment
+ local sorter = listsorters[sortorder]
+ if sorter then
+ if trace_lists then
+ report_lists("sorting list using method %a",sortorder)
+ end
+ for i=1,#result do
+ result[i].references.order = i
+ end
+ sort(result,sorter)
+ end
+ end
+ --
+ return result
+end
+
+filters[v_intro] = function(specification)
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local all = specification.all
+ local names = specification.names
+ for i=1,#collected do
+ local v = collected[i]
+ local metadata = v.metadata
+ if metadata and (all or names[metadata.name or false]) then
+ local r = v.references
+ if r and r.section == 0 then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ return result
+end
+
+filters[v_reference] = function(specification)
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local names = specification.names
+ local sections = sections.collected
+ local reference = specification.reference
+ if reference ~= "" then
+ local prefix, rest = lpegmatch(references.prefixsplitter,reference) -- p::r
+ local r = prefix and rest and references.derived[prefix][rest] or references.derived[""][reference]
+ local s = r and r.numberdata -- table ref !
+ if s then
+ local depth = getsectionlevel(r.metadata.name)
+ local numbers = s.numbers
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r and (not block or not r.block or block == r.block) then
+ local metadata = v.metadata
+ if metadata and names[metadata.name or false] then
+ local sectionnumber = (r.section == 0) or sections[r.section]
+ if sectionnumber then
+ if matchingtilldepth(depth,numbers,sectionnumber.numbers) then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ else
+ report_lists("unknown reference %a specified",reference)
+ end
+ else
+ report_lists("no reference specified")
+ end
+ return result
+end
+
+filters[v_all] = function(specification)
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local block = specification.block
+ local all = specification.all
+ local forced = specification.forced
+ local names = specification.names
+ local sections = sections.collected
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r and (not block or not r.block or block == r.block) then
+ local metadata = v.metadata
+ if metadata then
+ local name = metadata.name or false
+ local sectionnumber = (r.section == 0) or sections[r.section]
+ if forced[name] or (sectionnumber and not metadata.nolist and (all or names[name])) then -- and not sectionnumber.hidenumber then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ return result
+end
+
+filters[v_text] = filters[v_all]
+
+filters[v_current] = function(specification)
+ if specification.depth == 0 then
+ specification.nested = false
+ specification.criterium = v_intro
+ return filters[v_intro](specification)
+ end
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local depth = specification.depth
+ local block = specification.block
+ local all = specification.all
+ local names = specification.names
+ local numbers = specification.numbers
+ local sections = sections.collected
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r and (not block or not r.block or block == r.block) then
+ local sectionnumber = sections[r.section]
+ if sectionnumber then -- and not sectionnumber.hidenumber then
+ local cnumbers = sectionnumber.numbers
+ local metadata = v.metadata
+ if cnumbers then
+ if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers > depth then
+ local ok = true
+ for d=1,depth do
+ local cnd = cnumbers[d]
+ if not (cnd == 0 or cnd == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ return result
+end
+
+filters[v_here] = function(specification)
+ -- this is quite dirty ... as cnumbers is not sparse we can misuse #cnumbers
+ if specification.depth == 0 then
+ specification.nested = false
+ specification.criterium = v_intro
+ return filters[v_intro](specification)
+ end
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local depth = specification.depth
+ local block = specification.block
+ local all = specification.all
+ local names = specification.names
+ local numbers = specification.numbers
+ local sections = sections.collected
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r then -- and (not block or not r.block or block == r.block) then
+ local sectionnumber = sections[r.section]
+ if sectionnumber then -- and not sectionnumber.hidenumber then
+ local cnumbers = sectionnumber.numbers
+ local metadata = v.metadata
+ if cnumbers then
+ if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then
+ local ok = true
+ for d=1,depth do
+ local cnd = cnumbers[d]
+ if not (cnd == 0 or cnd == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ return result
+end
+
+filters[v_previous] = function(specification)
+ if specification.depth == 0 then
+ specification.nested = false
+ specification.criterium = v_intro
+ return filters[v_intro](specification)
+ end
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local block = specification.block
+ local all = specification.all
+ local names = specification.names
+ local numbers = specification.numbers
+ local sections = sections.collected
+ local depth = specification.depth
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r and (not block or not r.block or block == r.block) then
+ local sectionnumber = sections[r.section]
+ if sectionnumber then -- and not sectionnumber.hidenumber then
+ local cnumbers = sectionnumber.numbers
+ local metadata = v.metadata
+ if cnumbers then
+ if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then
+ local ok = true
+ for d=1,depth-1 do
+ local cnd = cnumbers[d]
+ if not (cnd == 0 or cnd == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ return result
+end
+
+filters[v_local] = function(specification)
+ local numbers = specification.numbers
+ local nested = nesting[#nesting]
+ if nested then
+ return filtercollected {
+ names = specification.names,
+ criterium = nested.name,
+ collected = specification.collected,
+ forced = specification.forced,
+ nested = nested,
+ sortorder = specification.sortorder,
+ }
+ else
+ specification.criterium = autosectiondepth(numbers) == 0 and v_all or v_current
+ specification.nested = false
+ return filtercollected(specification) -- rechecks, so better (for determining all)
+ end
+end
+
+
+filters[v_component] = function(specification)
+ -- special case, no structure yet
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ local all = specification.all
+ local names = specification.names
+ local component = resolvers.jobs.currentcomponent() or ""
+ if component ~= "" then
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ local m = v.metadata
+ if r and r.component == component and (m and names[m.name] or all) then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ return result
+end
+
+-- local number = tonumber(number) or numberatdepth(depth) or 0
+-- if number > 0 then
+-- ...
+-- end
+
+filters[v_default] = function(specification) -- is named
+ local collected = specification.collected
+ local result = { }
+ local nofresult = #result
+ ----- depth = specification.depth
+ local block = specification.block
+ local criterium = specification.criterium
+ local all = specification.all
+ local names = specification.names
+ local numbers = specification.numbers
+ local sections = sections.collected
+ local reference = specification.reference
+ local nested = specification.nested
+ --
+ if reference then
+ reference = tonumber(reference)
+ end
+ --
+ local depth = getsectionlevel(criterium)
+ local pnumbers = nil
+ local pblock = block
+ local parent = nested and nested.parent
+ --
+ if parent then
+ pnumbers = parent.numberdata.numbers or pnumbers -- so local as well as nested
+ pblock = parent.references.block or pblock
+ if trace_lists then
+ report_lists("filtering by block %a and section %a",pblock,criterium)
+ end
+ end
+ --
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r and (not block or not r.block or pblock == r.block) then
+ local sectionnumber = sections[r.section]
+ if sectionnumber then
+ local metadata = v.metadata
+ local cnumbers = sectionnumber.numbers
+ if cnumbers then
+ if all or names[metadata.name or false] then
+ if reference then
+ -- filter by number
+ if reference == cnumbers[depth] then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ else
+ if #cnumbers >= depth and matchingtilldepth(depth,cnumbers,pnumbers) then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return result
+end
+
+-- names, criterium, number, collected, forced, nested, sortorder) -- names is hash or string
+
+lists.filter = filtercollected
+
+lists.result = { }
+
+function lists.getresult(r)
+ return lists.result[r]
+end
+
+function lists.process(specification)
+ lists.result = filtercollected(specification)
+ local specials = settings_to_set(specification.extras or "")
+ specials = next(specials) and specials or nil
+ for i=1,#lists.result do
+ local r = lists.result[i]
+ local m = r.metadata
+ local s = specials and r.numberdata and specials[zerostrippedconcat(r.numberdata.numbers,".")] or ""
+ context.strclistsentryprocess(m.name,m.kind,i,s)
+ end
+end
+
+function lists.analyze(specification)
+ lists.result = filtercollected(specification)
+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 str = userdata and userdata[tag]
+ if str then
+ return str, 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]
+ return str or default
+end
+
+function lists.size()
+ return #lists.result
+end
+
+function lists.location(n)
+ local l = lists.result[n]
+ return l and l.references.internal or n
+end
+
+function lists.label(n,default)
+ local l = lists.result[n]
+ local t = l.titledata
+ return t and t.label or default or ""
+end
+
+function lists.sectionnumber(name,n,spec)
+ local data = lists.result[n]
+ local sectiondata = sections.collected[data.references.section]
+ -- hm, prefixnumber?
+ typesetnumber(sectiondata,"prefix",spec,sectiondata) -- data happens to contain the spec too
+end
+
+-- some basics (todo: helpers for pages)
+
+function lists.title(name,n,tag) -- tag becomes obsolete
+ local data = lists.result[n]
+ if data then
+ local titledata = data.titledata
+ if titledata then
+ helpers.title(titledata[tag] or titledata.list or titledata.title or "",data.metadata)
+ end
+ end
+end
+
+function lists.hastitledata(name,n,tag)
+ local data = cached[tonumber(n)]
+ if data then
+ local titledata = data.titledata
+ if titledata then
+ return (titledata[tag] or titledata.title or "") ~= ""
+ end
+ end
+ return false
+end
+
+function lists.haspagedata(name,n)
+ local data = lists.result[n]
+ if data then
+ local references = data.references
+ if references and references.realpage then -- or references.pagedata
+ return true
+ end
+ end
+ return false
+end
+
+function lists.hasnumberdata(name,n)
+ local data = lists.result[n]
+ if data then
+ local numberdata = data.numberdata
+ if numberdata and not numberdata.hidenumber then -- the hide number is true
+ return true
+ end
+ end
+ return false
+end
+
+function lists.prefix(name,n,spec)
+ helpers.prefix(lists.result[n],spec)
+end
+
+function lists.page(name,n,pagespec)
+ helpers.page(lists.result[n],pagespec)
+end
+
+function lists.prefixedpage(name,n,prefixspec,pagespec)
+ helpers.prefixpage(lists.result[n],prefixspec,pagespec)
+end
+
+function lists.realpage(name,n)
+ local data = lists.result[n]
+ if data then
+ local references = data.references
+ return references and references.realpage or 0
+ else
+ return 0
+ end
+end
+
+-- numbers stored in entry.numberdata + entry.numberprefix
+
+function lists.number(name,n,spec)
+ local data = lists.result[n]
+ if data then
+ local numberdata = data.numberdata
+ if numberdata then
+ typesetnumber(numberdata,"number",spec or false,numberdata or false)
+ end
+ end
+end
+
+function lists.prefixednumber(name,n,prefixspec,numberspec,forceddata)
+ local data = lists.result[n]
+ if data then
+ helpers.prefix(data,prefixspec)
+ local numberdata = data.numberdata or forceddata
+ if numberdata then
+ typesetnumber(numberdata,"number",numberspec or false,numberdata or false)
+ end
+ end
+end
+
+-- todo, do this in references namespace ordered instead (this is an experiment)
+--
+-- also see lpdf-ano (maybe move this there)
+
+local splitter = lpeg.splitat(":")
+
+function references.specials.order(var,actions) -- references.specials !
+ local operation = var.operation
+ if operation then
+ local kind, name, n = lpegmatch(splitter,operation)
+ local order = lists.ordered[kind]
+ order = order and order[name]
+ local v = order[tonumber(n)]
+ local r = v and v.references.realpage
+ if r then
+ actions.realpage = r
+ var.operation = r -- brrr, but test anyway
+ return references.specials.page(var,actions)
+ end
+ end
+end
+
+-- interface (maybe strclistpush etc)
+
+if not lists.reordered then
+ function lists.reordered(data)
+ return data.numberdata
+ end
+end
+
+implement { name = "pushlist", actions = lists.pushnesting, arguments = "integer" }
+implement { name = "poplist", actions = lists.popnesting }
+
+implement {
+ name = "addtolist",
+ actions = { lists.addto, context },
+ arguments = {
+ {
+ { "references", {
+ { "internal", "integer" },
+ { "block" },
+ { "section", "integer" },
+ { "location" },
+ { "prefix" },
+ { "reference" },
+ { "view" },
+ { "order", "integer" },
+ }
+ },
+ { "metadata", {
+ { "kind" },
+ { "name" },
+ { "level", "integer" },
+ { "catcodes", "integer" },
+ { "coding" },
+ { "xmlroot" },
+ { "setup" },
+ }
+ },
+ { "userdata" },
+ { "titledata", {
+ { "label" },
+ { "title" },
+ { "bookmark" },
+ { "marking" },
+ { "list" },
+ }
+ },
+ { "prefixdata", {
+ { "prefix" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ }
+ },
+ { "numberdata", {
+ { "numbers" },
+ { "groupsuffix" },
+ { "group" },
+ { "counter" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "starter" },
+ { "stopper" },
+ { "segments" },
+ }
+ }
+ }
+ }
+}
+
+implement {
+ name = "enhancelist",
+ actions = lists.enhance,
+ arguments = "integer"
+}
+
+implement {
+ name = "processlist",
+ actions = lists.process,
+ arguments = {
+ {
+ { "names" },
+ { "criterium" },
+ { "reference" },
+ { "extras" },
+ { "order" },
+ }
+ }
+}
+
+implement {
+ name = "analyzelist",
+ actions = lists.analyze,
+ arguments = {
+ {
+ { "names" },
+ { "criterium" },
+ { "reference" },
+ }
+ }
+}
+
+implement {
+ name = "listtitle",
+ actions = lists.title,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "listprefixednumber",
+ actions = lists.prefixednumber,
+ arguments = {
+ "string",
+ "integer",
+ {
+ { "prefix" },
+ { "separatorset" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ },
+ {
+ { "separatorset" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ { "segments" },
+ }
+ }
+}
+
+implement {
+ name = "listprefixedpage",
+ actions = lists.prefixedpage,
+ arguments = {
+ "string",
+ "integer",
+ {
+ { "separatorset" },
+ { "conversionset" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ },
+ {
+ { "prefix" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ }
+ }
+}
+
+implement { name = "listsize", actions = { lists.size, context } }
+implement { name = "listlocation", actions = { lists.location, context }, arguments = "integer" }
+implement { name = "listlabel", actions = { lists.label, context }, arguments = { "integer", "string" } }
+implement { name = "listrealpage", actions = { lists.realpage, context }, arguments = { "string", "integer" } }
+implement { name = "listgroupindex", actions = { lists.groupindex, context }, arguments = { "string", "string" } }
+
+implement {
+ name = "currentsectiontolist",
+ actions = { sections.current, lists.addto, context }
+}
+
+local function userdata(name,r,tag)
+ local str, metadata = lists.userdata(name,r,tag)
+ if str then
+ -- local catcodes = metadata and metadata.catcodes
+ -- if catcodes then
+ -- context.sprint(catcodes,str)
+ -- else
+ -- context(str)
+ -- end
+ helpers.title(str,metadata)
+ end
+end
+
+implement {
+ name = "listuserdata",
+ actions = userdata,
+ arguments = { "string", "integer", "string" }
+}
+
+-- we could also set variables .. names will change (when this module is done)
+-- maybe strc_lists_savedtitle etc
+
+implement { name = "doifelselisthastitle", actions = { lists.hastitledata, commands.doifelse }, arguments = { "string", "integer" } }
+implement { name = "doifelselisthaspage", actions = { lists.haspagedata, commands.doifelse }, arguments = { "string", "integer" } }
+implement { name = "doifelselisthasnumber", actions = { lists.hasnumberdata, commands.doifelse }, arguments = { "string", "integer" } }
+implement { name = "doifelselisthasentry", actions = { lists.iscached, commands.doifelse }, arguments = { "integer" } }
+
+local function savedlisttitle(name,n,tag)
+ local data = cached[tonumber(n)]
+ if data then
+ local titledata = data.titledata
+ if titledata then
+ helpers.title(titledata[tag] or titledata.title or "",data.metadata)
+ end
+ end
+end
+
+local function savedlistnumber(name,n)
+ local data = cached[tonumber(n)]
+ if data then
+ local numberdata = data.numberdata
+ if numberdata then
+ typesetnumber(numberdata,"number",numberdata or false)
+ end
+ end
+end
+
+local function savedlistprefixednumber(name,n)
+ local data = cached[tonumber(n)]
+ if data then
+ local numberdata = lists.reordered(data)
+ if numberdata then
+ helpers.prefix(data,data.prefixdata)
+ typesetnumber(numberdata,"number",numberdata or false)
+ end
+ end
+end
+
+lists.savedlisttitle = savedlisttitle
+lists.savedlistnumber = savedlistnumber
+lists.savedlistprefixednumber = savedlistprefixednumber
+
+implement {
+ name = "savedlistnumber",
+ actions = savedlistnumber,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "savedlisttitle",
+ actions = savedlisttitle,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "savedlistprefixednumber",
+ actions = savedlistprefixednumber,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "discardfromlist",
+ actions = lists.discard,
+ arguments = { "integer" }
+}
+
+-- new and experimental and therefore off by default
+
+lists.autoreorder = false -- true
+
+local function addlevel(t,k)
+ local v = { }
+ setmetatableindex(v,function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+ end)
+ t[k] = v
+ return v
+end
+
+local internals = setmetatableindex({ }, function(t,k)
+
+ local sublists = setmetatableindex({ },addlevel)
+
+ local collected = lists.collected or { }
+
+ for i=1,#collected do
+ local entry = collected[i]
+ local numberdata = entry.numberdata
+ if numberdata then
+ local metadata = entry.metadata
+ if metadata then
+ local references = entry.references
+ if references then
+ local kind = metadata.kind
+ local name = numberdata.counter or metadata.name
+ local internal = references.internal
+ if kind and name and internal then
+ local sublist = sublists[kind][name]
+ sublist[#sublist + 1] = { internal, numberdata }
+ end
+ end
+ end
+ end
+ end
+
+ for k, v in next, sublists do
+ for k, v in next, v do
+ local tmp = { }
+ for i=1,#v do
+ tmp[i] = v[i]
+ end
+ sort(v,function(a,b) return a[1] < b[1] end)
+ for i=1,#v do
+ t[v[i][1]] = tmp[i][2]
+ end
+ end
+ end
+
+ setmetatableindex(t,nil)
+
+ return t[k]
+
+end)
+
+function lists.reordered(entry)
+ local numberdata = entry.numberdata
+ if lists.autoreorder then
+ if numberdata then
+ local metadata = entry.metadata
+ if metadata then
+ local references = entry.references
+ if references then
+ local kind = metadata.kind
+ local name = numberdata.counter or metadata.name
+ local internal = references.internal
+ if kind and name and internal then
+ return internals[internal] or numberdata
+ end
+ end
+ end
+ end
+ else
+ function lists.reordered(entry)
+ return entry.numberdata
+ end
+ end
+ return numberdata
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi
new file mode 100644
index 00000000000..e7ed0f1f2ff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi
@@ -0,0 +1,1603 @@
+%D \module
+%D [ file=strc-lst,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Lists,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Lists}
+
+\registerctxluafile{strc-lst}{1.001}
+
+% clean up in progress ...
+%
+% also (long term) todo:
+%
+% autocrossdocument
+% auto refs to lists (chain)
+%
+% TODO: strut=yes|no
+%
+% \lists -> strc_lists
+
+\unprotect
+
+%D Lists are mostly used for tables of contents but are in fact a rather generic
+%D feature of \CONTEXT. We seperate between storage and rendering and the current
+%D implementation is a reworked version of all that was added in steps. As lists
+%D are used frequently compatibility is an important aspect. A couple of rendering
+%D alternatives are provided here but more are possible.
+
+\installcorenamespace{list}
+
+\installframedcommandhandler \??list {list} \??list
+
+\let\setuplists\setuplist % yes or no
+
+\setuplist
+ [\c!height=\v!broad,
+ \c!depth=\v!broad,
+ \c!offset=.25\emwidth,
+ \c!state=\v!start,
+ \c!coupling=\v!off,
+ \c!criterium=\v!local,
+ \c!reference=,% was number which was sort of obsolete
+ \c!width=3\emwidth,
+ %\c!maxwidth=,
+ \c!distance=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!alternative=\c!b,
+ \c!style=\v!normal,
+ %\c!color=,
+ \c!textstyle=\listparameter\c!style, % \currentliststyleparameter (but then we need to set it in every ...)
+ \c!numberstyle=\listparameter\c!style, % \currentliststyleparameter
+ \c!pagestyle=\listparameter\c!style, % \currentliststyleparameter
+ \c!textcolor=\listparameter\c!color, % \currentlistcolorparameter (but then we need to set it in every ...)
+ \c!numbercolor=\listparameter\c!color, % \currentlistcolorparameter
+ \c!pagecolor=\listparameter\c!color, % \currentlistcolorparameter
+ \c!numbercommand=\firstofoneargument,
+ \c!textcommand=\firstofoneargument,
+ \c!pagecommand=\firstofoneargument,
+ \c!pagenumber=\v!yes, % better: 'first'
+ \c!headnumber=\v!yes, % better: 'second'
+% \c!sectionnumber=\listparameter\c!headnumber, % use this instead
+ \c!interaction=\v!all, % was \v!sectionnumber, % or make this headnumber (or accept both)
+ \c!label=\v!no,
+ %\c!extras=,
+ %\c!aligntitle=,
+ %\c!before=,
+ %\c!after=,
+ %\c!inbetween=,
+ %\c!symbol=,
+ %\c!expansion=,
+ \c!limittext=\languageparameter\c!limittext] % not used currently
+
+%D Helpers:
+
+\unexpanded\def\usenestedliststyleandcolor#style#color% will change
+ {\useliststyleandcolor#style#color%
+ \ifx\currentcolorparameter\empty \else
+ \resetinteractionparameter\c!color
+ \resetinteractionparameter\c!contrastcolor
+ \fi}
+
+\unexpanded\def\doifelselist#tag% can also move to \installcommandhandler
+ {\ifcsname\namedlisthash{#tag}\s!parent\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflistelse\doifelselist
+
+%D Regular list entries are bound to a specific location in order to
+%D get the right pagenumber etc.\ associated. When pushing something
+%D inbetween (in mkiv) it ends up directtly in the list. This is the
+%D default because otherwise users will wonder why spacing might get
+%D messed up (due to an unseen but present node). It is possible to
+%D force a location by explicitly setting \type {location} to \type
+%D {here}.
+%D
+%D Another way to force a certain order is to set the \type {order}
+%D variable when placing a list. The \type {command} option only
+%D pushes commands into the right order, and \type {all} orders all
+%D entries (which might be too much). In this case no specific
+%D location is needed with the inbetween method. Maybe additional
+%D mechanisms show up some day. See \type {inbetween-001.tex} for an
+%D example.
+
+% command : location=none
+% userdata : location=none
+% simple : location=here
+
+\installcorenamespace {listlocations}
+
+\unexpanded\def\doifelseinlistentry#1%
+ {\ifcsname\??listlocations#1\endcsname
+ \ifnum\lastnamedcs=\structurelistlocation\relax
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelseincurrentlistentry
+ {\doifelseinlistentry\currentlist}
+
+\unexpanded\def\structurelistinject
+ {\dotripleempty\strc_lists_inject}
+
+\def\strc_lists_inject[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\listparameter\c!state}\v!start\strc_lists_inject_yes\strc_lists_inject_nop}
+
+\def\strc_lists_inject_nop[#dummya][#dummyb]%
+ {\endgroup}
+
+\unexpanded\def\strc_lists_inject_enhance#listindex#internal%
+ {\normalexpanded{\ctxlatecommand{enhancelist(#listindex)}}}
+
+\unexpanded\def\strc_lists_inject_yes[#settings][#userdata]% can be used directly
+ {\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let...
+ \edef\p_location{\listparameter\c!location}%
+ \setnextinternalreference
+ \scratchcounter\clf_addtolist
+ references {
+ internal \nextinternalreference
+ % block {\currentsectionblock}
+ % section structures.sections.currentid()
+ % location {\p_location}
+ }
+ metadata {
+ kind {\listparameter\c!type}
+ name {\currentlist}
+ % level structures.sections.currentlevel()
+ catcodes \catcodetable
+ }
+ userdata {\detokenize\expandafter{\normalexpanded{#userdata}}}
+ \relax
+ \edef\currentlistnumber{\the\scratchcounter}%
+\setxvalue{\??listlocations\currentlist}{\nextinternalreference}%
+ \ifx\p_location\v!here
+ % this branch injects nodes !
+ \strc_lists_inject_enhance{\currentlistnumber}{\nextinternalreference}%
+ \clf_setinternalreference
+ internal \nextinternalreference
+ view {\interactionparameter\c!focus}%
+ \relax % this will change
+ \xdef\currentstructurelistattribute{\the\lastdestinationattribute}%
+ \dontleavehmode\hbox attr \destinationattribute \lastdestinationattribute{}% todo
+ \else
+ % and this one doesn't
+ \clf_enhancelist\currentlistnumber\relax
+ \fi
+ \endgroup}
+
+% todo: make like \strc_references_direct_full_user ... with {}{}{}
+
+\unexpanded\def\strc_lists_inject_direct[#tag]% [#settings][#userdata]
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \strc_lists_inject_yes} % [#settings][#userdata]
+
+\unexpanded\def\writebetweenlist{\dodoubleempty \strc_lists_write_between}
+\unexpanded\def\writedatatolist {\dotripleargument\strc_lists_write_data_to}
+\unexpanded\def\writetolist {\dodoubleempty \strc_lists_write_to}
+
+\def\strc_lists_write_between[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_between_yes
+ \strc_lists_write_between_nop}
+
+\def\strc_lists_write_between_yes[#settings]#command%
+ {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]}
+
+\def\strc_lists_write_between_nop[#settings]#command%
+ {\endgroup}
+
+\def\strc_lists_write_data_to[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_data_to_yes
+ \strc_lists_write_data_to_nop}
+
+\def\strc_lists_write_data_to_yes[#settings][#userdata]%
+ {\ifthirdargument % no need to have an extra step ... used seldom
+ \strc_lists_inject_yes[#settings,\c!type=\s!userdata][#userdata]%
+ \else
+ \strc_lists_inject_yes[\c!type=\s!userdata][#settings]%
+ \fi}
+
+\def\strc_lists_write_data_to_nop[#settings][#userdata]%
+ {\endgroup}
+
+\def\strc_lists_write_to[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_to_yes
+ \strc_lists_write_to_nop}
+
+\def\strc_lists_write_to_yes[#settings]#first#second% no \s!first because we don't expand user settings
+ {\strc_lists_inject_yes[\c!location=\v!here,#settings,\c!type=\s!simple][first={#first},second={#second}]}
+
+\def\strc_lists_write_to_nop[#settings]#first#second%
+ {\endgroup} % \strc_lists_inject_nop[][]
+
+%D When placing a list either one or a set can be giving. This makes
+%D it possible to flush for instance an nested (or merged) table of
+%D contents. Keep in mind that placing a list is what we do most (think
+%D of tables of contents, figures, etc.\ but other usag eis also possible
+%D in which case low level commands have to be used.
+
+\newtoks\everystructurelist
+
+\unexpanded\def\placelist
+ {\dodoubleempty\strc_lists_place}
+
+\unexpanded\def\placerawlist
+ {\dodoubleempty\strc_lists_place_raw}
+
+\def\strc_lists_place[#taglist][#settings]%
+ {\begingroup
+ \startpacked[\v!blank]%
+ \edef\m_list {#taglist}%
+ \edef\m_first{\firststructureelementinlist{#taglist}}%
+ \ifx\m_list\m_first
+ % use settings of first
+ \else
+ % use settings of root
+ \let\m_first\empty
+ \fi
+ \strc_lists_place_indeed\m_first\m_list{#settings}%
+ \stoppacked
+ \endgroup}
+
+\def\strc_lists_place_raw[#tag][#settings]% just one list
+ {\strc_lists_place_indeed\empty{#tag}{#settings}}
+
+\def\strc_lists_place_indeed#tag#list#settings%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \setupcurrentlist[#settings]%
+ \the\everystructurelist
+ % \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#tag}}%
+ \strc_lists_place_current % maybe inline
+ {#list}%
+ {\listparameter\c!criterium}%
+ {\listparameter\c!reference}%
+ {\listparameter\c!extras}%
+ {\listparameter\c!order}%
+ % \stoplistreferences
+ \par % todo: only when vertical list mode
+ \endgroup
+ \strc_lists_set_mode}
+
+\def\strc_lists_set_mode
+ {\ifcase\structurelistsize\relax
+ \resetsystemmode\v!list
+ \else
+ \setsystemmode \v!list
+ \fi}
+
+%D Complete lists are just lists but with a title. They were
+%D originally introduced to minimize the number for commands in
+%D a document source but nowadays that is less an issue in the
+%D sense that the extra few lines are neglectable to the rest.
+
+\unexpanded\def\systemsuppliedchapter {\csname\v!chapter\endcsname} % obsolete
+\unexpanded\def\systemsuppliedtitle {\csname\v!title \endcsname} % obsolete
+
+\unexpanded\def\completelist
+ {\dodoubleempty\strc_lists_complete}
+
+\def\strc_lists_complete[#tag][#settings]%
+ {\strc_lists_complete_indeed[#tag][#tag][#settings]}
+
+\def\strc_lists_complete_indeed[#singular][#plural][#settings]%
+ {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}%
+ \strc_lists_place[#singular][#settings]%
+ \stopnamedsection}
+
+%D Combined list provide a nice level of abstraction.
+%D
+%D \starttyping
+%D \definecombinedlist[whatever][a,b,c][settings]
+%D \stoptyping
+
+\unexpanded\def\definecombinedlist
+ {\dotripleempty\strc_lists_combined_define}
+
+\def\strc_lists_combined_define[#tag][#list][#settings]%
+ {\definelist[#tag][\c!criterium=\v!local,\c!reference=,\c!alternative=,\c!list={#list},#settings]% inherits from root
+ \setvalue{\e!setup #tag\e!endsetup}{\dodoubleempty\strc_lists_combined_setup [#tag]}%
+ \setvalue{\e!place #tag}{\dodoubleempty\strc_lists_combined_place [#tag]}%
+ \setvalue{\e!complete #tag}{\dodoubleempty\strc_lists_combined_complete[#tag]}}
+
+\unexpanded\def\setupcombinedlist
+ {\dodoubleargument\strc_lists_combined_setup}
+
+\def\strc_lists_combined_setup[#tag][#settings]%
+ {\ifsecondargument
+ \setuplist[#tag][#settings]% we don't want to mess up the parent
+ \fi}
+
+\unexpanded\def\placecombinedlist
+ {\dodoubleempty\strc_lists_combined_place}
+
+\def\strc_lists_combined_place[#tag][#settings]% i.e. no list set in settings
+ {\begingroup
+ %
+ \edef\currentlist{#tag}%
+ \setupcurrentlist[#settings]%
+ \edef\m_strc_list_alternative{\listparameter\c!alternative}% we only inherit alternative
+ %
+ \strc_lists_place_indeed{#tag}{\listparameter\c!list}{#settings}%
+ \endgroup}
+
+\def\strc_lists_combined_complete[#tag][#settings]%
+ {\normalexpanded{\startnamedsection[\v!title][\c!title={\headtext{#tag}},\c!reference=#tag]}%
+ \strc_lists_combined_place[#tag][#settings]%
+ \stopnamedsection}
+
+%D Given that some variables are set, we can ask for some properties of
+%D an entry.
+
+\def\currentstructurelistnumber{0} % injection
+\def\currentlistmethod {entry} % typesetting
+\def\currentlistindex {0} % typesetting (maybe also a real counter)
+
+\unexpanded\def\savedlistnumber #1#2{\clf_savedlistnumber {#1}\numexpr#2\relax}
+\unexpanded\def\savedlisttitle #1#2{\clf_savedlisttitle {#1}\numexpr#2\relax}
+\unexpanded\def\savedlistprefixednumber#1#2{\clf_savedlistprefixednumber{#1}\numexpr#2\relax}
+
+\def\structurelistlocation
+ {\clf_listlocation\numexpr\currentlistindex\relax}
+
+\def\structurelistrealpagenumber
+ {\clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax}
+
+\unexpanded\def\structurelistpagenumber
+ {\dostarttagged\t!listpage\empty
+ \clf_listprefixedpage
+ {\currentlist}%
+ \currentlistindex
+ {
+ separatorset {\listparameter\c!pageprefixseparatorset}
+ conversionset {\listparameter\c!pageprefixconversionset}
+ set {\listparameter\c!pageprefixset}
+ segments {\listparameter\c!pageprefixsegments}
+ connector {\listparameter\c!pageprefixconnector}
+ }%
+ {
+ prefix {\listparameter\c!pageprefix}
+ conversionset {\listparameter\c!pageconversionset}
+ starter {\listparameter\c!pagestarter}
+ stopper {\listparameter\c!pagestopper}
+ }%
+ \relax
+ \dostoptagged}
+
+\unexpanded\def\structurelistuservariable#name%
+ {\dostarttagged\t!listdata{#name}%
+ \clf_listuserdata{\currentlist}\currentlistindex{#name}%
+ \dostoptagged}
+
+\def\rawstructurelistuservariable#name%
+ {\clf_listuserdata{\currentlist}\currentlistindex{#name}}
+
+\unexpanded\def\structurelistfirst {\structurelistuservariable\s!first } % s!
+\unexpanded\def\structurelistsecond {\structurelistuservariable\s!second} % s!
+
+\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! % was \unexpanded
+\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! % was \unexpanded
+
+\unexpanded\def\doifelsestructurelisthaspage
+ {\clf_doifelselisthaspage{\currentlist}\numexpr\currentlistindex\relax}
+
+\unexpanded\def\doifelsestructurelisthasnumber
+ {\clf_doifelselisthasnumber{\currentlist}\numexpr\currentlistindex\relax}
+
+\let\doifstructurelisthaspageelse \doifelsestructurelisthaspage
+\let\doifstructurelisthasnumberelse\doifelsestructurelisthasnumber
+
+\unexpanded\def\structurelistgenerictitle
+ {\dostarttagged\t!listcontent\empty
+ \clf_listtitle{\currentlist}\currentlistindex\relax
+ \dostoptagged}
+
+\unexpanded\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls
+ {\dostarttagged\t!listtag\empty
+ \clf_listprefixednumber
+ {\currentlist}%
+ \currentlistindex
+ {%
+ prefix {\listparameter\c!prefix}%
+ separatorset {\listparameter\c!prefixseparatorset}%
+ conversionset {\listparameter\c!prefixconversionset}%
+ starter {\listparameter\c!prefixstarter}%
+ stopper {\listparameter\c!prefixstopper}%
+ set {\listparameter\c!prefixset}%
+ segments {\listparameter\c!prefixsegments}%
+ connector {\listparameter\c!prefixconnector}%
+ }%
+ {%
+ separatorset {\listparameter\c!numberseparatorset}%
+ conversionset {\listparameter\c!numberconversionset}%
+ starter {\listparameter\c!numberstarter}%
+ stopper {\listparameter\c!numberstopper}%
+ segments {\listparameter\c!numbersegments}%
+ }%
+ \relax
+ \dostoptagged}
+
+% TODO: pass extra tag name (contents, figures, bibliography ...)
+
+\unexpanded\def\strc_lists_place_current#list#criterium#reference#extras#order% beware, not a user command
+ {\dostarttaggedchained\t!list\empty\??list
+ \clf_processlist
+ names {#list}
+ criterium {#criterium}
+ reference {#reference}
+ extras {#extras}
+ order {#order}
+ \relax
+ \dostoptagged}
+
+\unexpanded\def\strc_lists_analyze#list#criterium#reference%
+ {\clf_analyzelist
+ names {#list}
+ criterium {#criterium}
+ reference {#reference}
+ \relax}
+
+\def\firststructureelementinlist#list% expandable
+ {\clf_firstinset{#list}}
+
+\def\structurelistsize
+ {\clf_listsize}
+
+%D Depending on what kind of list we have (e.g.\ a section related one)
+%D processors can be defined.
+
+% push pop test:
+%
+% \starttext
+% \placelist[chapter] [after={\placelist[section][criterium=local]}]
+% \chapter{One} \section{Alpha} \section{Beta}
+% \chapter{Two} \section{First} \section{Second}
+% \stoptext
+
+\installcorenamespace{structurelistprocessor} % the topmost list handler
+\installcorenamespace{listextra} % control of that handler
+
+\installcommandhandler \??listextra {listextra} \??listextra
+
+\definelistextra % example
+ [\v!page]
+ [\c!before={\showmessage\m!system{14}{\currentlist/\currentlistindex}\page}]
+
+\unexpanded\def\installstructurelistprocessor#tag#meaning%
+ {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}}
+
+\def\usestructurelistprocessor#tag%
+ {\csname\??structurelistprocessor#tag\endcsname}
+
+\let\dotaglistlocation\relax
+
+\def\strc_lists_entry_process_default
+ {no list method}
+
+% \def\strc_lists_entry_process % assume things to be set up
+% {\listextraparameter\c!before
+% \dostarttagged\t!listitem\currentlist
+% \dotaglistlocation
+% \csname\??structurelistprocessor
+% \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else
+% \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\currentlistmethod \else
+% \ifcsname\??structurelistprocessor\currentlist \endcsname\currentlist \else
+% \s!default \fi\fi\fi
+% \endcsname
+% \dostoptagged
+% \listextraparameter\c!after}
+
+\def\strc_lists_entry_process % assume things to be set up
+ {\listextraparameter\c!before
+ \dostarttagged\t!listitem\currentlist
+ \dotaglistlocation
+ \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\else
+ \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\lastnamedcs\else
+ \ifcsname\??structurelistprocessor\currentlist \endcsname\lastnamedcs\else
+ \strc_lists_entry_process_default\fi\fi\fi
+ \dostoptagged
+ \listextraparameter\c!after}
+
+\unexpanded\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end!
+ {\clf_pushlist#index\relax
+ \edef\currentlist {#tag}%
+ \edef\currentlistmethod{#method}%
+ \edef\currentlistindex {#index}%
+ \edef\currentlistextra {#extra}%
+ \strc_lists_entry_process
+ \clf_poplist}
+
+% lists that have a number/title are kind of generic and can share code
+
+\installstructurelistprocessor\s!default
+ {\strc_lists_entry_process_default}
+
+\installstructurelistprocessor\s!simple
+ {\let\currentlistentrynumber \structurelistfirst
+ \let\currentlistentrytitle \structurelistsecond
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+\installstructurelistprocessor\s!command
+ {\clf_listuserdata{\currentlist}\currentlistindex{\s!command}}
+
+\installstructurelistprocessor{section}
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+\installstructurelistprocessor{number+title}
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+% example of usage elsewhere:
+%
+% \installstructcurelistprocessor{pubs:userdata}
+% {\clf_listuserdata{\currentlist}\currentlistindex{bibref}}
+
+%D List symbols are used in interactive documents where no numbers
+%D are used but nevertheless structure is present. Beware, the list
+%D symbol macro gets an argument passed, i.e. when this argument is
+%D not picked up, the symbol becomes a kind of prefix. It's not really
+%D a user command (and might even get protected).
+
+\unexpanded\def\listsymbol[#tag]#number%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \def\currentlistentrynumber{#number}% no edef else tag problems
+ \currentlistsymbol
+ \endgroup}
+
+% For historical reasons we're stuck to symbols, so in order to generalize,
+% we have to hook it into the symbol handle. One way to deal with this is
+% to use a different key and as it makes sense to use setups instead of
+% def's we use a new key 'renderingsetup' which is the name of a setup.
+
+\def\strc_lists_assign_dimen#dimension#key#default%
+ {\edef\m_strc_list_dimen{\listparameter#key}%
+ \doifelseinset\m_strc_list_dimen{\v!fit,\v!broad}{#dimension#default}{#dimension\m_strc_list_dimen}\relax}
+
+\definesymbol[\v!list][\v!none ][\strc_lists_symbol_none]
+\definesymbol[\v!list][\v!one ][\strc_lists_symbol_one]
+\definesymbol[\v!list][\v!two ][\strc_lists_symbol_two]
+\definesymbol[\v!list][\v!three ][\strc_lists_symbol_three]
+\definesymbol[\v!list][\s!default][\strc_lists_symbol_default]
+\definesymbol[\v!list][\s!unknown][\strc_lists_symbol_unknown]
+
+\unexpanded\def\currentlistsymbol
+ {\edef\p_symbol{\listparameter\c!symbol}%
+ \doifelseinsymbolset\v!list\p_symbol
+ {\directsymbol\v!list\p_symbol}
+ {\directsymbol\v!list\s!default}}
+
+\unexpanded\def\strc_lists_symbol_none
+ {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}%
+ \hpack to \scratchwidth{}}
+
+\unexpanded\def\strc_lists_symbol_one
+ {\strut\symbol[bullet]}
+
+\unexpanded\def\strc_lists_symbol_two
+ {\vrule\!!width\emwidth\!!height\exheight\!!depth\zeropoint}
+
+\unexpanded\def\strc_lists_symbol_three
+ {\begingroup
+ \strc_lists_assign_dimen\scratchwidth \c!width {1.5\emwidth}%
+ \strc_lists_assign_dimen\scratchheight\c!height\exheight
+ \strc_lists_assign_dimen\scratchdepth \c!depth \zeropoint
+ \vrule\!!width\scratchwidth\!!height\scratchheight\!!depth\scratchdepth
+ \endgroup}
+
+\unexpanded\def\strc_lists_symbol_unknown
+ {\listparameter\c!symbol}
+
+\installcorenamespace{listsymbollabels}
+
+\def\strc_lists_symbol_label_unknown
+ {\leftlabeltext\currentlistlabel
+ \listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper
+ \rightlabeltext\currentlistlabel}
+
+\unexpanded\def\strc_lists_symbol_default
+ {\dontleavehmode
+ \strut
+ \begingroup
+ \edef\currentlistlabel{\listparameter\c!label}% can be used in label
+% \csname\??listsymbollabels
+% \ifcsname\??listsymbollabels\currentlistlabel\endcsname\currentlistlabel\else\s!unknown\fi
+% \endcsname
+ \ifcsname\??listsymbollabels\currentlistlabel\endcsname
+ \lastnamedcs
+ \else
+ \strc_lists_symbol_label_unknown
+ \fi
+ \endgroup}
+
+\letvalue{\??listsymbollabels\s!unknown}\strc_lists_symbol_default
+
+\setvalue{\??listsymbollabels}% default (empty)
+ {\listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper}
+
+\setvalue{\??listsymbollabels\v!no}% also default
+ {\listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper}
+
+\setvalue{\??listsymbollabels\v!none}% real minimal (as suggested by WS)
+ {\currentlistentrynumber}
+
+\setvalue{\??listsymbollabels\v!yes}% auto (use value stored in tuc file)
+ {\edef\currentlistlabel{\clf_listlabel\currentlistindex{\currentlistlabel}}%
+ \leftlabeltext\currentlistlabel
+ \listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper
+ \rightlabeltext\currentlistlabel}
+
+% a : nr - tit - pag
+% b : nr - tit - fill - pag
+% c : nr - tit - dots - pag
+% d : inline
+% e : interaction
+% f : interaction
+% g : interaction
+
+\installcorenamespace{listalternative} % specific ways of rendering a list
+\installcorenamespace{listrenderings} % a namespace for setups (rather local)
+
+\installcommandhandler \??listalternative {listalternative} \??listalternative
+
+% Commands are bound to specific list instances as often these are
+% quite special and don't apply to multiple. So, being strict saves
+% us resets.
+
+% \installcorenamespace{listfiller}
+%
+% \unexpanded\def\installlistfiller#1#2%
+% {\setuvalue{\??listfiller#1}{#2}}
+%
+% \unexpanded\def\listfiller#1%
+% {\begincsname\??listfiller#1\endcsname}
+%
+% \unexpanded\def\currentlistfiller
+% {\begingroup
+% \edef\p_filler{\listalternativeparameter\c!filler}%
+% \ifcsname\??listfiller\p_filler\endcsname
+% \lastnamedcs
+% \else
+% \p_filler
+% \fi
+% \endgroup}
+%
+% \installlistfiller\v!sym % original one
+% {\begingroup
+% \scratchdimen.5\emwidth
+% \hskip\scratchdimen
+% \gleaders
+% \hbox to \scratchdimen
+% {\hss
+% \uselistalternativestyleandcolor\c!symstyle\c!symcolor
+% \listalternativeparameter\c!symbol
+% \hss}%
+% \hfill
+% \hskip\scratchdimen
+% \endgroup}
+%
+% \installlistfiller\v!symbol % new one (make that default?)
+% {\begingroup
+% \scratchdimen.5\emwidth
+% \hskip\scratchdimen
+% \gleaders
+% \hbox spread .5\scratchdimen
+% {\hss
+% \uselistalternativestyleandcolor\c!symstyle\c!symcolor
+% \listalternativeparameter\c!symbol
+% \hss}%
+% \hfill
+% \hskip\scratchdimen
+% \endgroup}
+%
+% \installlistfiller\v!width
+% {\hfill}
+%
+% \installlistfiller\v!space
+% {\hskip.25\emwidth\relax}
+
+\setuplistalternative
+ [\c!command=\strictlistparameter\c!command,
+ \c!symbol=.]
+
+\unexpanded\def\currentlistfiller
+ {\checkedfiller{\listalternativeparameter\c!filler}}
+
+\definelistalternative
+ [a]
+ [\c!distance=0pt,
+ \c!width=2em,
+ \c!stretch=10em,
+ \c!filler=\hskip.25em\relax,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [b]
+ [\c!distance=5em,
+ \c!width=2em,
+ \c!stretch=10em,
+ \c!filler=\hfill,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [c]
+ [\c!distance=5em,
+ \c!width=0pt,
+ \c!stretch=10em,
+ \c!filler=\hskip.5em\gleaders\hbox to .5em{\hss.\hss}\hfill\hskip.5em\relax,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [d]
+ [\c!renderingsetup=\??listrenderings:d]
+
+\definelistalternative
+ [e]
+ [\c!renderingsetup=\??listrenderings:e]
+
+\definelistalternative
+ [f]
+ [\c!renderingsetup=\??listrenderings:f]
+
+\definelistalternative
+ [g]
+ [\c!renderingsetup=\??listrenderings:g]
+
+\definelistalternative
+ [\v!command]
+ [\c!renderingsetup=\??listrenderings:command]
+
+\definelistalternative
+ [\v!none]
+ [\c!renderingsetup=\??listrenderings:none]
+
+\definelistalternative
+ [\v!vertical]
+ [\c!before=\ifvmode\nointerlineskip\fi,
+ \c!after=\ifvmode\nointerlineskip\fi\endgraf\allowbreak,
+ \c!renderingsetup=\??listrenderings:generic]
+
+\definelistalternative
+ [\v!horizontal]
+ [\c!before=\noindent,
+ \c!after=,
+ \c!renderingsetup=\??listrenderings:generic]
+
+% \setuplist
+% [section]
+% [alternative=MyListItem,
+% after=\blank,
+% before=\blank]
+%
+% \definelistplacement[MyListItem][command]#1#2#3{(#1) (#2) (#3)}
+% \definelistplacement[MyListItem][command]{\whatever}
+%
+% this is a compatibility command, best use the regular
+% defined with command= either set in the alternative or
+% in the list
+
+\installcorenamespace{listelementcommand} % the old plugin model
+
+\unexpanded\def\definelistplacement
+ {\dodoubleempty\strc_lists_define_placement}
+
+\def\strc_lists_define_placement[#tag][#method]%
+ {\edef\p_method{#method}%
+ \ifx\p_method\empty
+ \let\p_method\v!command
+ \fi
+ \normalexpanded{\definelistalternative[#tag][\p_method]}[\c!command=\strc_lists_placement_command]%
+ \doifelsenextbgroup
+ {\strc_lists_define_placement_yes{#tag}}
+ {\strc_lists_define_placement_nop{#tag}}}
+
+% indirect definition: <three ignore arguments>: {\bla}
+
+\def\strc_lists_define_placement_yes#tag%
+ {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname##1##2##3}
+
+% direct definition: <three arguments>{\bla}
+
+\def\strc_lists_define_placement_nop#tag%
+ {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname}
+
+\def\strc_lists_placement_command
+ {\csname\??listelementcommand\currentlistalternative\endcsname}
+
+%D The rendering macros.
+
+\newbox \b_strc_lists_number
+\newbox \b_strc_lists_text
+\newbox \b_strc_lists_page
+
+\newtoks \t_lists_every_renderingsetup
+\newtoks \t_lists_every_renderingtext
+\newtoks \t_lists_every_renderingsynchronize
+\newtoks \t_lists_every_renderingcleanup
+
+\newconditional\c_lists_has_number
+\newconditional\c_lists_has_page
+\newconditional\c_lists_show_number
+\newconditional\c_lists_show_page
+
+\let\currentlistentrylocation \empty % watch the 'entry' in the name
+\let\currentlistentrynumber \empty % watch the 'entry' in the name
+\let\currentlistentrytitle \empty % watch the 'entry' in the name
+\let\currentlistentrypagenumber\empty % watch the 'entry' in the name
+
+\appendtoks
+ \dontcomplain
+ \letinteractionparameter\c!width\zeropoint % a weird one
+\to \t_lists_every_renderingsetup
+
+\appendtoks
+ % better is to use a special list entry but we keep this for compatibility
+ \let\\=\space
+ % so expanding this token register has to come *after* the font switch
+ \dontconvertfont % (**) this has to become an option (see publ)
+\to \t_lists_every_renderingtext
+
+\appendtoks
+ % because we want to avoid redundant lua calls we expand the
+ % location beforehand
+ \ifx\currentlistentrylocation\empty
+ \edef\currentlistentrylocation{\structurelistlocation}% needs attention
+ \fi
+ % because these tests happen often and because we're dealing with
+ % rather complex composed data we have special conditionals; keep
+ % in mind that testing for empty fails do to tagging being applied
+ \edef\p_pagenumber{\listparameter\c!pagenumber}%
+ \ifx\p_pagenumber\v!always
+ \settrue\c_lists_has_page
+ \settrue\c_lists_show_page
+ \else
+ \doifelsestructurelisthaspage\settrue\setfalse\c_lists_has_page
+ \ifx\p_pagenumber\v!yes
+ \settrue\c_lists_show_page
+ \else
+ \setfalse\c_lists_show_page
+ \fi
+ \fi
+ % always forces number placement (in bib we use a forced number)
+ \edef\p_headnumber{\listparameter\c!headnumber}%
+ \ifx\p_headnumber\v!always
+ \settrue\c_lists_has_number
+ \settrue\c_lists_show_number
+ \else
+ \doifelsestructurelisthasnumber\settrue\setfalse\c_lists_has_number
+ \ifx\p_headnumber\v!yes
+ \settrue\c_lists_show_number
+ \else
+ \setfalse\c_lists_show_number
+ \fi
+ \fi
+ \strc_lists_interaction_check
+\to \t_lists_every_renderingsetup
+
+\appendtoks
+ \strc_references_flush_destination_nodes
+\to \t_lists_every_renderingsynchronize
+
+\appendtoks
+ % as we don't want any interference we clear some variables
+ % afterwards
+ \let\currentlistentrylocation \empty
+ \let\currentlistentrynumber \empty
+ \let\currentlistentrytitle \empty
+ \let\currentlistentrypagenumber\empty
+ \setfalse\c_lists_has_page
+ \setfalse\c_lists_has_number
+ \setfalse\c_lists_show_page
+ \setfalse\c_lists_show_number
+\to \t_lists_every_renderingcleanup
+
+\let\m_strc_list_alternative\empty % combined
+
+\unexpanded\def\strc_lists_apply_renderingsetup
+ {\the\t_lists_every_renderingsetup
+ % now we group
+ \begingroup
+ \ifx\m_strc_list_alternative\empty
+ \edef\currentlistalternative{\listparameter\c!alternative}%
+ \else
+ \let\currentlistalternative\m_strc_list_alternative
+ \fi
+ \directsetup{\listalternativeparameter\c!renderingsetup}\relax
+ \endgroup
+ % till here, where we reset locals
+ \the\t_lists_every_renderingcleanup}
+
+% todo: provide packager via attributes
+
+\doinstallinjector\s!list
+
+\installcorenamespace{listalternativemethods} % the general wrapper of a rendering
+
+\startsetups[\??listrenderings:none]
+ % nothing, nb we use the [] syntax here because we end with a \cs
+\stopsetups
+
+\unexpanded\def\currentlistentrytitlesynchronize
+ {\the\t_lists_every_renderingsynchronize}
+
+\unexpanded\def\currentlistentrytitlerendered
+ {\currentlistentrytitlesynchronize\currentlistentrytitle}
+
+\startsetups[\??listrenderings:command]
+ \edef\p_command{\listalternativeparameter\c!command}%
+ \ifx\p_command\empty
+ [\currentlist: \currentlistentrynumber\space -- \currentlistentrytitle\space -- \currentlistentrypagenumber]%
+ \else
+ \p_command
+ \currentlistentrynumber
+ \currentlistentrytitlerendered % {\currentlistentrytitlesynchronize\currentlistentrytitle}
+ \currentlistentrypagenumber
+ \fi
+\stopsetups
+
+% \startsetups[\??listrenderings:\v!vertical]
+% \directsetup{\??listrenderings:generic}
+% \stopsetups
+
+% \startsetups[\??listrenderings:\v!horizontal]
+% \directsetup{\??listrenderings:generic}
+% \stopsetups
+
+\startsetups[\??listrenderings:generic]
+ \typo_injectors_check_list
+ \listparameter\c!before % can be \hskip
+ \edef\p_command{\listalternativeparameter\c!command}
+ \ifx\p_command\empty
+ \listalternativeparameter\c!before
+ \vbox {
+ \forgetall
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all {
+ \ifconditional\c_lists_show_number
+ % \ifconditional\c_lists_has_page
+ \hbox \strc_lists_get_reference_attribute\v!number {
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!numbercommand\currentlistsymbol
+ }
+ % \fi
+ \fi
+ \hbox \strc_lists_get_reference_attribute\v!text {
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \listparameter\c!textcommand\currentlistentrytitle
+ }
+ \ifconditional\c_lists_show_page
+ \ifconditional\c_lists_has_page
+ \hbox \strc_lists_get_reference_attribute\v!pagenumber {
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ }
+ \fi
+ \fi
+ }
+ }
+ \listalternativeparameter\c!after
+ \else
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
+ }
+ \fi
+ \listparameter\c!after
+\stopsetups
+
+% to be documented: align, hang
+
+\startsetups[\??listrenderings:abc]
+ \endgraf % are we grouped?
+ \typo_injectors_check_list
+ % \advance % yes or no ... \rightskip is also honored
+ \leftskip\listparameter\c!margin % after \endgraf !
+ \listparameter\c!before
+ \endgraf
+ \edef\p_width{\listparameter\c!width}
+ \scratchdistance\listparameter\c!distance\relax
+ \ifx\p_width\v!fit
+ \scratchwidth\zeropoint
+ \else\ifconditional\c_lists_has_number
+ \scratchwidth\p_width
+ \else
+ \edef\p_aligntitle{\listparameter\c!aligntitle}
+ \ifx\p_aligntitle\v!yes
+ \scratchwidth\zeropoint
+ \scratchdistance\zeropoint
+ \else
+ \scratchwidth\p_width
+ \fi
+ \fi\fi
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \setlocalhsize
+ \hsize\localhsize
+ \hbox to \hsize {
+ \forgetall
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \scratchhsize\hsize
+ \ifconditional\c_lists_has_number
+ \ifconditional\c_lists_show_number
+ \setbox\b_strc_lists_number
+% \hbox
+% \strc_lists_get_reference_attribute\v!number
+% \ifdim\scratchwidth>\zeropoint to \scratchwidth \fi
+ \simplealignedboxplus
+ \scratchwidth
+ {\listparameter\c!numberalign}
+ {\strc_lists_get_reference_attribute\v!number}
+ {
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!numbercommand\currentlistsymbol
+% \hfill
+ }
+ \else
+ \setbox\b_strc_lists_number\emptyhbox
+ \fi
+ \else
+ \scratchwidth\zeropoint
+ \scratchdistance\zeropoint
+ \setbox\b_strc_lists_number\emptyhbox
+ \fi
+ \ifconditional\c_lists_has_page
+ \ifconditional\c_lists_show_page
+ \setbox\b_strc_lists_page\hbox {
+ \scratchdimen\listalternativeparameter\c!width
+ \hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi {
+ \hfill
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \strut
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ }
+ }
+ \else
+ \setbox\b_strc_lists_page\emptyhbox
+ \fi
+ \else
+ \setbox\b_strc_lists_page\emptyhbox
+ \fi
+ \vbox {
+ \hsize\scratchhsize
+ \usealignparameter\listparameter
+ \ifdim\scratchwidth<\hsize
+ % we have leftskip so we'd better just skip back instead of messing
+ % with hang*
+ \edef\p_hang{\listparameter\c!hang}
+ \hangindent\dimexpr\wd\b_strc_lists_number+\scratchdistance\relax
+ \hangafter\ifx\p_hang\v!no\zerocount\else\plusone\fi
+ \scratchdimen\listalternativeparameter\c!distance\relax
+ \ifdim\wd\b_strc_lists_page=\zeropoint \else\ifdim\scratchdimen>\zeropoint\relax
+ \rightskip\scratchdimen\!!plus\listalternativeparameter\c!stretch\relax
+ \parfillskip-\rightskip
+ \fi \fi
+ \else
+ \scratchdistance\zeropoint
+ \fi
+ \parindent\zeropoint
+ \dontleavehmode % this nils hang: i need to figure out why
+ % % topaligned
+ %
+ % \scratchdimen\wd\b_strc_lists_number
+ % \setbox\b_strc_lists_number\hbox to \hsize{\box\b_strc_lists_number\hss\box\b_strc_lists_page}%
+ % \wd\b_strc_lists_number\scratchdimen
+ %
+ \box\b_strc_lists_number
+ \hskip\scratchdistance\relax
+ \begingroup
+ \strc_lists_set_reference_attribute\v!text
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut % needs checking, new here
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ \endgroup
+ \ifdim\wd\b_strc_lists_page=\zeropoint\else
+ \nobreak
+ \currentlistfiller
+ \box\b_strc_lists_page
+ \fi
+ }
+ \hss
+ }
+ }% new
+ \endgraf % new, else problems with nointerlinespace and prevdepth
+ \nointerlineskip % anders verkeerde spatiering bij multi-line
+ \endgraf
+ \allowbreak
+ \listparameter\c!after
+\stopsetups
+
+% % example from the context list
+%
+% \setuphead [part] [page=right,placehead=yes]
+% \setuplist [chapter] [alternative=d,before=\blank,after=\blank]
+% \setuplist [part] [before=\blank,after=\blank]
+%
+% \starttext
+% \startnarrower[2*right] \placecontent \stopnarrower
+% \blank[4*big]
+% \startsetups chapter
+% \blank \startnarrower[3*middle] \placecontent[criterium=local] \stopnarrower
+% \stopsetups
+% \placelist[part][criterium=text,after=\setups{chapter}]
+%
+% \part{First part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \part{Second part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \part{Third part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \stoptext
+
+\startsetups[\??listrenderings:d]
+ \ifvmode
+ \advance\leftskip\listparameter\c!margin
+ \fi
+ \begingroup
+ \ifvmode
+ \noindent
+ \fi
+ \begingroup
+ \strc_lists_set_reference_attribute\v!all
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \strc_lists_get_destination_attribute
+ \begingroup
+ \ifconditional\c_lists_show_number
+ \donetrue
+ \ifconditional\c_lists_has_number \else
+ \edef\p_symbol{\listparameter\c!symbol}
+ \ifx\p_symbol\empty
+ \donefalse
+ \fi
+ \fi
+ \ifdone
+ \begingroup
+ \strc_lists_set_reference_attribute\v!number
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!left
+ \listparameter\c!numbercommand\currentlistsymbol
+ \listparameter\c!right
+ \endgroup
+ \kern.5\emwidth\relax
+ \nobreak
+ \fi
+ \fi
+ \endgroup
+ \begingroup
+ \strc_lists_set_reference_attribute\v!text
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut % needs checking, new here
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ \endgroup
+ \begingroup
+ \ifconditional\c_lists_has_page
+ \ifconditional\c_lists_show_page
+ \nobreak
+ \hskip.75\emwidth\relax
+ \nobreak
+ \strc_lists_set_reference_attribute\v!pagenumber
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \strut
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ \fi
+ \fi
+ \endgroup
+ \scratchdistance\listparameter\c!distance\relax
+ \ifdim\scratchdistance<\emwidth
+ \hskip\emwidth\!!plus\emwidth\!!minus.25\emwidth\relax
+ \else
+ \hskip\scratchdistance\!!plus.5\scratchdistance\!!minus.25\scratchdistance\relax
+ \fi
+ \endgroup
+ \endgroup
+\stopsetups
+
+\startsetups[\??listrenderings:e]
+ \typo_injectors_check_list
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \letlistparameter\c!depth\zeropoint
+ \letlistparameter\c!color\empty
+ \inheritedlistframed {
+ \letinteractionparameter\c!strut\v!no % still needed?
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+\startsetups[\??listrenderings:f]
+ \typo_injectors_check_list
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \dosetraggedhbox{\listparameter\c!align}%
+ \raggedbox {
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+\startsetups[\??listrenderings:g]
+ \typo_injectors_check_list
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \midaligned {
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+%D This is a new one, similar to vertical and horizontal but better suited when
+%D no command is set (WS):
+
+\definelistalternative
+ [\v!interactive]
+ [\c!renderingsetup=\??listrenderings:interactive,
+ \c!before=\endgraf, % new per 2014-11-08
+ \c!after=\endgraf] % new per 2014-11-08
+
+\startsetups[\??listrenderings:interactive]
+ \edef\p_command{\listalternativeparameter\c!command}%
+ \typo_injectors_check_list
+ \listparameter\c!before
+ \noindent % otherwise annotations are mirrored up
+ \typo_injectors_mark_list
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \ifx\p_command\empty
+ [
+ \currentlist:\space
+ \currentlistentrynumber
+ \space\emdash\space
+ \currentlistentrytitle
+ \space\emdash\space
+ \currentlistentrypagenumber
+ ]
+ \else
+ \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
+ \fi
+ }
+ \listparameter\c!after
+\stopsetups
+
+%D One special for publications (as Alan loves to hangindent). No fonts and
+%D such (for now). No interaction either as that is dealt with elsewhere.
+%D
+%D \currentlistsymbol
+%D \currentlistentry
+%D \currentlistentrypagenumber % not really used
+
+\definelistalternative
+ [\v!paragraph]
+ [\c!filler=\v!space,
+ \c!renderingsetup=\??listrenderings:\v!paragraph]
+
+\startsetups[\??listrenderings:\v!paragraph]
+ \endgraf % are we grouped?
+ \typo_injectors_check_list % ?
+ \listparameter\c!before
+ \endgraf
+ \begingroup
+ \forgetall
+ \noindent
+ \parindent\zeropoint
+ \edef\p_width{\listparameter\c!width}%
+ \edef\p_distance{\listparameter\c!distance}% we are nice for bib users
+ \edef\p_margin{\listparameter\c!margin}% we are nice for bib users
+ \ifx\p_distance\v!none
+ \scratchdistance\zeropoint
+ \else
+ \scratchdistance\p_distance
+ \fi
+ \ifx\p_margin\v!none
+ \scratchoffset\zeropoint
+ \else
+ \scratchoffset\p_margin
+ \fi
+ \ifx\p_width\v!fit
+ \scratchwidth\zeropoint
+ \leftskip\scratchoffset
+ \else
+ \scratchwidth\p_width
+ \ifdim\scratchoffset=\zeropoint
+ \leftskip\dimexpr\scratchwidth+\scratchdistance\relax
+ \else
+ \leftskip\scratchoffset
+ \fi
+ \fi
+ \usealignparameter\listparameter
+ \hskip-\leftskip
+ \ifconditional\c_lists_has_number
+ \ifconditional\c_lists_show_number
+ \setbox\scratchbox
+ \simplealignedbox\scratchwidth{\listparameter\c!numberalign}
+ \bgroup
+ \useliststyleandcolor\c!numberstyle\c!numbercolor
+ \currentlistsymbol
+ \egroup
+ \ifdim\wd\scratchbox>\zeropoint
+ \box\scratchbox
+ \hskip\scratchdistance\relax
+ \fi
+ \fi
+ \fi
+ \begingroup
+ \useliststyleandcolor\c!textstyle\c!textcolor
+ \setstrut
+ \begstrut
+ \currentlistentrytitle
+ \endstrut
+ \endgroup
+ \ifconditional\c_lists_has_page
+ \ifconditional\c_lists_show_page
+ \nobreak
+ \currentlistfiller
+ \begingroup
+ \useliststyleandcolor\c!pagestyle\c!pagecolor
+ \currentlistentrypagenumber
+ \endgroup
+ \fi
+ \fi
+ \endgraf
+ \endgroup
+ \allowbreak
+ \listparameter\c!after
+\stopsetups
+
+%D List elements are packaged in such a way that we can click on them
+%D in an interactive document. Here are a few helpers.
+
+\newconstant\a_strc_lists_reference
+\newconstant\a_strc_lists_destination
+
+\installcorenamespace{listinteractions}
+
+\letvalue{\??listinteractions\v!number }\v!number
+\letvalue{\??listinteractions\v!sectionnumber}\v!number
+\letvalue{\??listinteractions\v!text }\v!text
+\letvalue{\??listinteractions\v!title }\v!text
+\letvalue{\??listinteractions\v!page }\v!pagenumber
+\letvalue{\??listinteractions\v!pagenumber }\v!pagenumber
+\letvalue{\??listinteractions\v!all }\v!all
+\letvalue{\??listinteractions\v!yes }\v!all
+
+\def\listboxproperties {\strc_lists_get_reference_attribute}
+\def\listrenderingsetup {\the\t_lists_every_renderingtext}
+\def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize}
+
+\unexpanded\def\strc_lists_interaction_check
+ {\iflocation
+ \strc_lists_interaction_check_yes
+ \else
+ \strc_lists_interaction_check_nop
+ \fi}
+
+% \def\strc_lists_interaction_check_yes
+% {\edef\p_interaction_forward{\listparameter\c!interaction}%
+% \ifcsname\??listinteractions\p_interaction_forward\endcsname
+% \expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+% \strc_references_get_simple_reference{internal(\currentlistentrylocation)}%
+% \a_strc_lists_reference\currentreferenceattribute
+% \else
+% \a_strc_lists_reference\attributeunsetvalue
+% \fi
+% \ifnum\a_strc_lists_reference=\attributeunsetvalue
+% \let\strc_lists_get_reference_attribute\gobbleoneargument
+% \let\strc_lists_set_reference_attribute\gobbleoneargument
+% \let\strc_lists_set_style_color \strc_lists_set_style_color_normal
+% \else
+% \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
+% \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
+% \let\strc_lists_set_style_color \strc_lists_set_style_color_special
+% \fi
+% \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
+% \ifx\p_interaction_backward\v!list
+% \strc_references_set_simple_reference{*\currentlistentrylocation}%
+% \a_strc_lists_destination\currentdestinationattribute
+% \else
+% \a_strc_lists_destination\attributeunsetvalue
+% \fi
+% \ifnum\a_strc_lists_destination=\attributeunsetvalue
+% \let\strc_lists_get_destination_attribute\empty
+% \let\strc_lists_set_destination_attribute\empty
+% \else
+% \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
+% \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
+% \fi}
+
+\def\strc_lists_interaction_check_yes
+ {\edef\p_interaction_forward{\listparameter\c!interaction}%
+ \ifcsname\??listinteractions\p_interaction_forward\endcsname
+ %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+ \expandafter\let\expandafter\p_interaction_forward\lastnamedcs
+ \strc_references_get_simple_reference{internal(\currentlistentrylocation)}%
+ \a_strc_lists_reference\currentreferenceattribute
+ \else
+ \a_strc_lists_reference\attributeunsetvalue
+ \fi
+ \ifnum\a_strc_lists_reference=\attributeunsetvalue
+ \let\strc_lists_get_reference_attribute\gobbleoneargument
+ \let\strc_lists_set_reference_attribute\gobbleoneargument
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_normal
+ \else
+ \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
+ \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_special
+ \fi
+ \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
+ \ifx\p_interaction_backward\v!list
+ \strc_references_set_simple_reference{*\currentlistentrylocation}%
+ \a_strc_lists_destination\currentdestinationattribute
+ \else
+ \a_strc_lists_destination\attributeunsetvalue
+ \fi
+ \ifnum\a_strc_lists_destination=\attributeunsetvalue
+ \let\strc_lists_get_destination_attribute\empty
+ \let\strc_lists_set_destination_attribute\empty
+ \else
+ \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
+ \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
+ \fi}
+
+\def\strc_lists_interaction_check_nop
+ {\let\strc_lists_get_reference_attribute \gobbleoneargument
+ \let\strc_lists_set_reference_attribute \gobbleoneargument
+ \let\strc_lists_get_destination_attribute\empty
+ \let\strc_lists_set_destination_attribute\empty
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_normal}
+
+\strc_lists_interaction_check_nop
+
+\def\strc_lists_get_reference_attribute_indeed#element%
+ {\ifx#element\p_interaction_forward
+ attr \referenceattribute\a_strc_lists_reference
+ \fi}
+
+\def\strc_lists_set_reference_attribute_indeed#element%
+ {\ifx#element\p_interaction_forward
+ \attribute\referenceattribute\a_strc_lists_reference
+ \fi}
+
+\def\strc_lists_get_destination_attribute_indeed
+ {attr \destinationattribute\number\a_strc_lists_destination}
+
+\def\strc_lists_set_destination_attribute_indeed
+ {\attribute\destinationattribute\a_strc_lists_destination}
+
+\unexpanded\def\strc_lists_set_style_color_normal#style#color#element%
+ {\useliststyleandcolor#style#color}
+
+\unexpanded\def\strc_lists_set_style_color_special#style#color#element%
+ {\useliststyleandcolor#style#color%
+ \ifx\currentcolorparameter\empty
+ \ifx#element\p_interaction_forward
+ \setlocationcolor
+ \fi
+ % \else
+ % \resetinteractionparameter\c!color
+ % \resetinteractionparameter\c!contrastcolor
+ \fi}
+
+\let\strc_lists_set_style_color\strc_lists_set_style_color_normal
+
+%D A helper:
+
+\def\strc_lists_limitated_text#text%
+ {\edef\p_maxwidth{\listparameter\c!maxwidth}%
+ \ifx\p_maxwidth\empty
+ \listparameter\c!textcommand{#text}%
+ \else
+ \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}%
+ \fi}
+
+% public helpers
+
+\unexpanded\def\startcurrentlistentrywrapper
+ {\hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute\bgroup}
+
+\let\stopcurrentlistentrywrapper\egroup
+
+\let\currentlistentryreferenceattribute \strc_lists_get_reference_attribute
+\let\currentlistentrydestinationattribute\strc_lists_get_destination_attribute
+\let\currentlistentrylimitedtext \strc_lists_limitated_text
+
+% todo:
+
+\def\utilitylistlength{\listlength} % old name ... uses in styles
+
+\let\listlength\!!zerocount % better use listmode
+
+\unexpanded\def\determinelistcharacteristics
+ {\dodoubleempty\strc_lists_determine_characteristics}
+
+\def\strc_lists_determine_characteristics[#list][#settings]%
+ {\begingroup
+ \edef\currentlist{\firststructureelementinlist{#list}}%
+ \ifx\currentlist\empty
+ \endgroup
+ \let\listlength\!!zerocount
+ \else
+ \setupcurrentlist[#settings]%
+ \strc_lists_analyze{#list}{\listparameter\c!criterium}{\listparameter\c!reference}%
+ \normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}%
+ \fi
+ \strc_lists_set_mode}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua
new file mode 100644
index 00000000000..8b30e85143e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua
@@ -0,0 +1,731 @@
+if not modules then modules = { } end modules ['strc-mar'] = {
+ version = 1.001,
+ comment = "companion to strc-mar.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: cleanup stack (structures.marks.reset(v_all) also does the job)
+-- todo: only commands.* print to tex, native marks return values
+
+local insert, concat = table.insert, table.concat
+local tostring, next, rawget, type = tostring, next, rawget, type
+local lpegmatch = lpeg.match
+
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getbox = nuts.getbox
+
+local traverse_nodes = nuts.traverse
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local texsetattribute = tex.setattribute
+
+local a_marks = attributes.private("structure","marks")
+
+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 report_marks = logs.reporter("structure","marks")
+
+local variables = interfaces.variables
+
+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 v_nocheck_suffix = ":" .. variables.nocheck
+
+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 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()
+
+storage.register("structures/marks/data", marks.data, "structures.marks.data")
+
+local data = marks.data
+local stack, topofstack = { }, 0
+
+local ranges = {
+ [v_page] = {
+ first = 0,
+ last = 0,
+ },
+}
+
+local function resolve(t,k)
+ if k then
+ if trace_marks_set or trace_marks_get then
+ report_marks("undefined mark, name %a",k)
+ end
+ local crap = { autodefined = true } -- maybe set = 0 and reset = 0
+ t[k] = crap
+ return crap
+ else
+ -- weird: k is nil
+ end
+end
+
+setmetatableindex(data, resolve)
+
+function marks.exists(name)
+ return rawget(data,name) ~= nil
+end
+
+-- identify range
+
+local function sweep(head,first,last)
+ for n in traverse_nodes(head) do
+ local id = getid(n)
+ if id == glyph_code then
+ local a = getattr(n,a_marks)
+ if not a then
+ -- next
+ elseif first == 0 then
+ first, last = a, a
+ elseif a > last then
+ last = a
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if boxes_too then
+ local a = getattr(n,a_marks)
+ if not a then
+ -- next
+ elseif first == 0 then
+ first, last = a, a
+ elseif a > last then
+ last = a
+ end
+ end
+ local list = getlist(n)
+ if list then
+ first, last = sweep(list,first,last)
+ end
+ end
+ end
+ return first, last
+end
+
+local classes = { }
+
+setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end)
+
+local lasts = { }
+
+function marks.synchronize(class,n,option)
+ local box = getbox(n)
+ if box then
+ local first, last = sweep(getlist(box),0,0)
+ if option == v_keep and first == 0 and last == 0 then
+ if trace_marks_get or trace_marks_set then
+ report_marks("action %a, class %a, box %a","retain at synchronize",class,n)
+ end
+ -- todo: check if still valid firts/last in range
+ first = lasts[class] or 0
+ last = first
+ else
+ lasts[class] = last
+ local classlist = classes[class]
+ for i=1,#classlist do
+ local class = classlist[i]
+ local range = ranges[class]
+ if range then
+ range.first = first
+ range.last = last
+ else
+ range = {
+ first = first,
+ last = last,
+ }
+ ranges[class] = range
+ end
+ if trace_marks_get or trace_marks_set then
+ report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last)
+ end
+ end
+ end
+ elseif trace_marks_get or trace_marks_set then
+ report_marks("action %s, class %a, box %a","synchronize without content",class,n)
+ end
+end
+
+-- define etc
+
+local function resolve(t,k)
+ if k == "fullchain" then
+ local fullchain = { }
+ local chain = t.chain
+ while chain and chain ~= "" do
+ insert(fullchain,1,chain)
+ chain = data[chain].chain
+ end
+ t[k] = fullchain
+ return fullchain
+ elseif k == "chain" then
+ t[k] = ""
+ return ""
+ elseif k == "reset" or k == "set" then
+ t[k] = 0
+ return 0
+ elseif k == "parent" then
+ t[k] = false
+ return false
+ end
+end
+
+function marks.define(name,settings)
+ if not settings then
+ settings = { }
+ elseif type(settings) == "string" then
+ settings = { parent = settings }
+ end
+ data[name] = settings
+ local parent = settings.parent
+ if parent == nil or parent == "" or parent == name then
+ settings.parent = false
+ else
+ local dp = data[parent]
+ if not dp then
+ settings.parent = false
+ elseif dp.parent then
+ settings.parent = dp.parent
+ end
+ end
+ setmetatableindex(settings, resolve)
+end
+
+for k, v in next, data do
+ setmetatableindex(v,resolve) -- runtime loaded table
+end
+
+local function parentname(name)
+ local dn = data[name]
+ return dn and dn.parent or name
+end
+
+function marks.relate(name,chain)
+ local dn = data[name]
+ if dn and not dn.parent then
+ if chain and chain ~= "" then
+ dn.chain = chain
+ local dc = data[chain]
+ if dc then
+ local children = dc.children
+ if not children then
+ children = { }
+ dc.children = children
+ end
+ children[#children+1] = name
+ end
+ elseif trace_marks_set then
+ report_marks("error: invalid relation, name %a, chain %a",name,chain)
+ end
+ end
+end
+
+local function resetchildren(new,name)
+ local dn = data[name]
+ if dn and not dn.parent then
+ local children = dn.children
+ if children then
+ for i=1,#children do
+ local ci = children[i]
+ new[ci] = false
+ if trace_marks_set then
+ report_marks("action %a, parent %a, child %a","reset",name,ci)
+ end
+ resetchildren(new,ci)
+ end
+ end
+ end
+end
+
+function marks.set(name,value)
+ local dn = data[name]
+ if dn then
+ local child = name
+ local parent = dn.parent
+ if parent then
+ name = parent
+ dn = data[name]
+ end
+ dn.set = topofstack
+ if not dn.reset then
+ dn.reset = 0 -- in case of selfdefined
+ end
+ local top = stack[topofstack]
+ local new = { }
+ if top then
+ for k, v in next, top do
+ local d = data[k]
+ local r = d.reset or 0
+ local s = d.set or 0
+ if r <= topofstack and s < r then
+ new[k] = false
+ else
+ new[k] = v
+ end
+ end
+ end
+ resetchildren(new,name)
+ new[name] = value
+ topofstack = topofstack + 1
+ stack[topofstack] = new
+ if trace_marks_set then
+ if name == child then
+ report_marks("action %a, name %a, index %a, value %a","set",name,topofstack,value)
+ else
+ report_marks("action %a, parent %a, child %a, index %a, value %a","set",parent,child,topofstack,value)
+ end
+ end
+ texsetattribute("global",a_marks,topofstack)
+ end
+end
+
+local function reset(name)
+ if v_all then
+ if trace_marks_set then
+ report_marks("action %a","reset all")
+ end
+ stack = { }
+ for name, dn in next, data do
+ local parent = dn.parent
+ if parent then
+ dn.reset = 0
+ dn.set = 0
+ end
+ end
+ else
+ local dn = data[name]
+ if dn then
+ local parent = dn.parent
+ if parent then
+ name = parent
+ dn = data[name]
+ end
+ if trace_marks_set then
+ report_marks("action %a, name %a, index %a","reset",name,topofstack)
+ end
+ dn.reset = topofstack
+ local children = dn.children
+ if children then
+ for i=1,#children do
+ local ci = children[i]
+ reset(ci)
+ end
+ end
+ end
+ end
+end
+
+marks.reset = reset
+
+function marks.get(n,name,value)
+ local dn = data[name]
+ if dn then
+ name = dn.parent or name
+ local top = stack[n]
+ if top then
+ context(top[name])
+ end
+ end
+end
+
+function marks.show(first,last)
+ if first and last then
+ for k=first,last do
+ local v = stack[k]
+ if v then
+ report_marks("% 4i: %s",k,table.sequenced(v))
+ end
+ end
+ else
+ for k, v in table.sortedpairs(stack) do
+ report_marks("% 4i: %s",k,table.sequenced(v))
+ end
+ end
+end
+
+local function resolve(name,first,last,strict,quitonfalse,notrace)
+ local dn = data[name]
+ if dn then
+ local child = name
+ local parent = dn.parent
+ name = parent or child
+ dn = data[name]
+ local step, method
+ if first > last then
+ step, method = -1, "bottom-up"
+ else
+ step, method = 1, "top-down"
+ end
+ if trace_marks_get and not notrace then
+ report_marks("action %a, strategy %a, name %a, parent %a, strict %a","request",method,child,parent,strict or false)
+ end
+ if trace_marks_all and not notrace then
+ marks.show(first,last)
+ end
+ local r = dn.reset
+ local s = dn.set
+ if first <= last and first <= r then
+ if trace_marks_get and not notrace then
+ report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset first",name,first,last,r,first)
+ end
+ elseif first >= last and last <= r then
+ if trace_marks_get and not notrace then
+ report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset last",name,first,last,r,last)
+ end
+ elseif not stack[first] or not stack[last] then
+ if trace_marks_get and not notrace then
+ -- a previous or next method can give an out of range, which is valid
+ report_marks("error: out of range, name %a, reset %a, index %a",name,r,first)
+ end
+ elseif strict then
+ local top = stack[first]
+ local fullchain = dn.fullchain
+ if not fullchain or #fullchain == 0 then
+ if trace_marks_get and not notrace then
+ report_marks("warning: no full chain, trying again, name %a, first %a, last %a",name,first,last)
+ end
+ return resolve(name,first,last)
+ else
+ if trace_marks_get and not notrace then
+ report_marks("found chain [ % => T ]",fullchain)
+ end
+ local chaindata, chainlength = { }, #fullchain
+ for i=1,chainlength do
+ local cname = fullchain[i]
+ if data[cname].set > 0 then
+ local value = resolve(cname,first,last,false,false,true)
+ if value == "" then
+ if trace_marks_get and not notrace then
+ report_marks("quitting chain, name %a, reset %a, start %a",name,r,first)
+ end
+ return ""
+ else
+ chaindata[i] = value
+ end
+ end
+ end
+ if trace_marks_get and not notrace then
+ report_marks("using chain [ % => T ]",chaindata)
+ end
+ local value, index, found = resolve(name,first,last,false,false,true)
+ if value ~= "" then
+ if trace_marks_get and not notrace then
+ report_marks("following chain [ % => T ]",chaindata)
+ end
+ for i=1,chainlength do
+ local cname = fullchain[i]
+ if data[cname].set > 0 and chaindata[i] ~= found[cname] then
+ if trace_marks_get and not notrace then
+ report_marks("quiting chain, name %a, reset %a, index %a",name,r,first)
+ end
+ return ""
+ end
+ end
+ if trace_marks_get and not notrace then
+ report_marks("found in chain, name %a, reset %a, start %a, index %a, value %a",name,r,first,index,value)
+ end
+ return value, index, found
+ elseif trace_marks_get and not notrace then
+ report_marks("not found, name %a, reset %a",name,r)
+ end
+ end
+ else
+ for i=first,last,step do
+ local current = stack[i]
+ local value = current and current[name]
+ if value == nil then
+ -- search on
+ elseif value == false then
+ if quitonfalse then
+ return ""
+ end
+ elseif value == true then
+ if trace_marks_get and not notrace then
+ report_marks("quitting steps, name %a, reset %a, start %a, index %a",name,r,first,i)
+ end
+ return ""
+ elseif value ~= "" then
+ if trace_marks_get and not notrace then
+ report_marks("found in steps, name %a, reset %a, start %a, index %a, value %a",name,r,first,i,value)
+ end
+ return value, i, current
+ end
+ end
+ if trace_marks_get and not notrace then
+ report_marks("not found in steps, name %a, reset %a",name,r)
+ end
+ end
+ end
+ return ""
+end
+
+-- todo: column:first column:last
+
+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
+ 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)
+ end
+ if swap then
+ first, last = last + df, first + dl
+ else
+ first, last = first + df, last + dl
+ end
+ local value, index, found = resolve(name,first,last,strict)
+ -- maybe something more
+ return value, index, found
+end
+
+-- previous : last before sync
+-- next : first after sync
+
+-- top : first in sync
+-- bottom : last in sync
+
+-- first : first not top in sync
+-- last : last not bottom in sync
+
+methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict
+methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict
+methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict
+methods[v_next] = function(name,range) return doresolve(name,range,true , 0,1,true ) end -- strict
+
+methods[v_previous_nocheck] = function(name,range) return doresolve(name,range,false,-1,0,false) end
+methods[v_top_nocheck] = function(name,range) return doresolve(name,range,false, 0,0,false) end
+methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end
+methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end
+
+local function do_first(name,range,check)
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a","resolving first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if f_found then
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a","resolving last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
+ if l_found and l_index > f_index then
+ local name = parentname(name)
+ for i=f_index,l_index,1 do
+ local si = stack[i]
+ local sn = si[name]
+ if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+ end
+ return sn, i, si
+ end
+ end
+ end
+ end
+ if trace_marks_get then
+ report_marks("resolved, name %a, range %a, using first",name,range)
+ end
+ return f_value, f_index, f_found
+end
+
+local function do_last(name,range,check)
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a","resolving last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
+ if l_found then
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a","resolving first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if f_found and l_index > f_index then
+ local name = parentname(name)
+ for i=l_index,f_index,-1 do
+ local si = stack[i]
+ local sn = si[name]
+ if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then
+ if trace_marks_get then
+ report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+ end
+ return sn, i, si
+ end
+ end
+ end
+ end
+ if trace_marks_get then
+ report_marks("resolved, name %a, range %a, using first",name,range)
+ end
+ return l_value, l_index, l_found
+end
+
+methods[v_first ] = function(name,range) return do_first(name,range,true ) end
+methods[v_last ] = function(name,range) return do_last (name,range,true ) end
+methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end
+methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end
+
+methods[v_current] = function(name,range) -- range is ignored here
+ local top = stack[topofstack]
+ return top and top[parentname(name)] or ""
+end
+
+local function fetched(name,range,method)
+ local value = (methods[method] or methods[v_first])(name,range) or ""
+ if not trace_marks_get then
+ -- no report
+ elseif value == "" then
+ report_marks("nothing fetched, name %a, range %a, method %a",name,range,method)
+ else
+ report_marks("marking fetched, name %a, range %a, method %a, value %a",name,range,method,value)
+ end
+ return value or ""
+end
+
+-- can be used at the lua end:
+
+marks.fetched = fetched
+
+-- this will move to a separate runtime modules
+
+marks.tracers = marks.tracers or { }
+
+function marks.tracers.showtable()
+ context.starttabulate { "|l|l|l|lp|lp|" }
+ 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 { }
+ table.sort(children) -- in-place but harmless
+ context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," "))
+ end
+ context.stoptabulate()
+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 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
+
+function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first
+ if trace_marks_get then
+ report_marks("marking requested, name %a, range %a, method %a",name,range,method)
+ end
+ if method == "" or method == v_default then
+ fetchonemark(name,range,v_first)
+ elseif method == v_both then
+ fetchtwomarks(name,range)
+ elseif method == v_all then
+ fetchallmarks(name,range)
+ else
+ fetchonemark(name,range,method)
+ end
+end
+
+function marks.fetchonemark (name,range,method) fetchonemark (name,range,method) end
+function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end
+function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end
+
+-- here we have a few helpers .. will become commands.*
+
+local pattern = lpeg.afterprefix("li::")
+
+function marks.title(tag,n)
+ local listindex = lpegmatch(pattern,n)
+ if listindex then
+ commands.savedlisttitle(tag,listindex,"marking")
+ else
+ context(n)
+ end
+end
+
+function marks.number(tag,n) -- no spec
+ local listindex = lpegmatch(pattern,n)
+ if listindex then
+ commands.savedlistnumber(tag,listindex)
+ else
+ -- no prefix (as it is the prefix)
+ context(n)
+ end
+end
+
+-- interface
+
+implement { name = "markingtitle", actions = marks.title, arguments = { "string", "string" } }
+implement { name = "markingnumber", actions = marks.number, arguments = { "string", "string" } }
+
+implement { name = "definemarking", actions = marks.define, arguments = { "string", "string" } }
+implement { name = "relatemarking", actions = marks.relate, arguments = { "string", "string" } }
+implement { name = "setmarking", actions = marks.set, arguments = { "string", "string" } }
+implement { name = "resetmarking", actions = marks.reset, arguments = { "string" } }
+implement { name = "synchronizemarking", actions = marks.synchronize, arguments = { "string", "integer", "string" } }
+implement { name = "getmarking", actions = marks.fetch, arguments = { "string", "string", "string" } }
+implement { name = "fetchonemark", actions = marks.fetchonemark, arguments = { "string", "string", "string" } }
+implement { name = "fetchtwomarks", actions = marks.fetchtwomarks, arguments = { "string", "string" } }
+implement { name = "fetchallmarks", actions = marks.fetchallmarks, arguments = { "string", "string" } }
+
+implement { name = "doifelsemarking", actions = { marks.exists, commands.doifelse }, arguments = "string" }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.mkiv
new file mode 100644
index 00000000000..4e8df5f5dbe
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.mkiv
@@ -0,0 +1,155 @@
+%D \module
+%D [ file=strc-mar,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Markings,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Markings}
+
+\registerctxluafile{strc-mar}{1.001}
+
+\unprotect
+
+%D Synchronizing marks is a rather tricky and messy business. When
+%D setting a mark, a node is added to the list in order for to \TEX\
+%D be able to figure out the 3 current marks when a page is made
+%D (last mark on previous page, first on current page, last on
+%D current page; in \LUATEX\ we might at one point have the first on
+%D the next page as well).
+%D
+%D Resetting a mark is not easy. An empty one will not erase the last
+%D one on the previous page for instance. In \LUATEX\ we can clear a
+%D marks state register with \type {\clearmarks} but since this is an
+%D immediate operation it might have unwanted side effects when \TEX\
+%D has collected several pages of text and finishing off these pages
+%D uses marks.
+%D
+%D In \MKIV\ we provide an alternative model that permits some more
+%D control over the way marks are used. It is not entirely compatible
+%D with \MKII\ or previous \MKIV\ implementations but in practice this
+%D is not a real problem. It's also easier now to extend this mechanism.
+
+% if global has side effects we will need to nil it selectively
+% and optionally enable it in for instance postponed content
+
+\definesystemattribute [marks] [global]
+
+\installcorenamespace{marking}
+
+\installcommandhandler \??marking {marking} \??marking
+
+\newconditional\inhibitgetmarking % will become private
+\newconditional\inhibitsetmarking % will become private
+
+\newtoks \everymarking
+
+\unexpanded\def\relatemarking {\dodoubleempty \strc_markings_relate }
+\unexpanded\def\setmarking {\dosingleargument\strc_markings_set } \let\marking\setmarking
+\unexpanded\def\resetmarking {\dosingleargument\strc_markings_reset }
+\unexpanded\def\synchronizemarking{\dotripleargument\strc_markings_synchronize}
+
+\appendtoks
+ \clf_definemarking{\currentmarking}{\currentmarkingparent}%
+\to \everydefinemarking
+
+\def\strc_markings_relate[#1][#2]%
+ {\clf_relatemarking{#1}{#2}}
+
+\def\strc_markings_set[#1]#2%
+ {\ifconditional\inhibitsetmarking
+ % nothing
+ \else
+ \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes
+ {\clf_setmarking{#1}{#2}}
+ {\clf_setmarking{#1}{\detokenize{#2}}}%
+ \fi}
+
+\def\strc_markings_reset[#1]%
+ {\clf_resetmarking{#1}}
+
+\def\strc_markings_synchronize[#1][#2][#3]% #1=class #2=boxnumber (some day also name) #3=options, maybe second argument table
+ {\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi}
+
+\def\doifelsemarking#1% no \noexpanded
+ {\clf_doifelsemarking{#1}}
+
+\let\doifmarkingelse \doifelsemarking
+
+% \appendtoks
+% \strc_markings_synchronize[\v!page][\normalpagebox][\v!keep]% keep if no marks
+% \to \everybeforepagebody
+
+% defaults
+
+\setupmarking
+ [\c!expansion=\v!no,
+ \c!separator=\space\emdash\space,
+ \c!filtercommand=\firstofoneargument,
+ \c!state=\v!start]
+
+% fetching, regular interface
+
+\unexpanded\def\getmarking
+ {\ifconditional\inhibitgetmarking
+ \expandafter\dotripleargument\expandafter\strc_markings_get_nop
+ \else
+ \expandafter\dotripleargument\expandafter\strc_markings_get_yes
+ \fi}
+
+\def\strc_markings_get_nop[#1][#2][#3]%
+ {}
+
+\def\strc_markings_get_yes[#1][#2][#3]%
+ {\doif{\namedmarkingparameter{#1}\c!state}\v!start
+ {\begingroup
+ \setsystemmode\v!marking
+ \the\everymarking
+ \ifthirdargument
+ \clf_getmarking{#1}{#2}{#3}%
+ \else
+ \clf_getmarking{#1}{\v!page}{#2}%
+ \fi
+ \endgroup}}
+
+% the fetchers are fully expandable: [name][method]
+
+\def\fetchonemark[#1]#2[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#3}\fi}
+\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi}
+\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi}
+
+\let\fetchmark\fetchonemark
+
+% also fully expandable but here we have: [name][range][method]
+
+\def\fetchonemarking[#1]#2[#3]#4[#5]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#3}{#5}\fi}
+\def\fetchtwomarkings [#1]#2[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#3}\fi}
+\def\fetchallmarkings [#1]#2[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#3}\fi}
+
+\let\fetchmarking\fetchonemarking
+
+\def\markingseparator#1{\namedmarkingparameter{#1}\c!separator}
+\def\markingcommand #1{\namedmarkingparameter{#1}\c!filtercommand}
+
+%D Experimental:
+%D
+%D \starttyping
+%D \definemarking[boxmark]
+%D
+%D \setbox0\ruledvbox{
+%D \marking[boxmark]{tufte} \input tufte \par
+%D \marking[boxmark]{ward} \input ward \par
+%D }
+%D
+%D \synchronizemarking[zerobox][0] \box0
+%D
+%D marks: (\getmarking[boxmark][zerobox][first],\getmarking[boxmark][zerobox][last])
+%D \stoptyping
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mat.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.lua
new file mode 100644
index 00000000000..87f35ed1d3a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.lua
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['strc-mat'] = {
+ version = 1.001,
+ comment = "companion to strc-mat.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+----- copytable = table.copy
+
+local structures = structures
+
+local lists = structures.lists
+local sections = structures.sections
+local floats = structures.floats
+local helpers = structures.helpers
+local formulas = structures.formulas -- not used but reserved
+
+----- context = context
+----- simplify = helpers.simplify
+
+-- maybe we want to do clever things with formulas, the store might go away
+
+-- local formuladata = { }
+--
+-- function formulas.store(data)
+-- formuladata[#formuladata+1] = data
+-- context(#formuladata)
+-- end
+--
+-- function formulas.current()
+-- return formuladata[#formuladata]
+-- end
+
+-- function formulas.simplify(entry)
+-- return simplify(copytable(entry or formuladata[#formuladata]))
+-- end
+
+function helpers.formulanumber(data,spec)
+ if data then
+ local formulanumber = data.formulanumber
+ if formulanumber then
+ sections.number(data,spec,"formulanumber","formulanumber",'number')
+ end
+ end
+end
+
+function lists.formulanumber(name,n,spec)
+ local result = lists.result
+ if result then
+ helpers.formulanumber(result[n])
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv
new file mode 100644
index 00000000000..85870d54769
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv
@@ -0,0 +1,1045 @@
+%D \module
+%D \module
+%D [ file=strc-mat,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Math Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Math Numbering}
+
+\registerctxluafile{strc-mat}{1.001}
+
+% -- we have potential for captions
+% -- this module will use the commandhandler
+% -- key/value pairs will be added (I have no time now)
+
+\unprotect
+
+\setupformulas
+ [%\c!way=,
+ %\c!blockway=,
+ %\c!sectionnumber=,
+ %\c!conversion=\v!numbers,
+ %\c!numberstyle=,
+ %\c!numbercolor=,
+ %\c!numbercommand=,
+ %\c!margin=,
+ %\c!align=,
+ %\c!separator=,
+ %\c!grid=,
+ \c!location=\v!right,
+ \c!left=(,
+ \c!right=),
+ \c!expansion=\v!yes, % maybe automatically
+ \c!spacebefore=\v!big,
+ \c!spaceafter=\formulaparameter\c!spacebefore,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!indentnext=\v!no,
+ \c!alternative=\s!default,
+ \c!strut=\v!no,
+ \c!distance=2\emwidth]
+
+\ifdefined\matheqnogapstep
+ % we're ok, now we have that quad in the distance which is
+ % more consistent and not depending on the text font in math
+ \matheqnogapstep\zerocount
+\else
+ % we will keep this for a while
+ \setupformulas[\c!distance=\emwidth]
+\fi
+
+% \ifdefined\mathdisplayskipmode
+% \mathdisplayskipmode\plustwo % only when not zero / needs adapted space handler
+% \fi
+
+% \mathdisplayskipmode\plusthree
+%
+% \hbox\bgroup
+% \setbox0\vbox\bgroup
+% xxxxxxxxx\par
+% \vskip-\baselineskip
+% $$a^2_2$$\par
+% xxxxxxxxx\par
+% \egroup
+% \box0
+% \vbox\bgroup
+% xxxxxxxxx\par
+% \vskip-\baselineskip
+% $$a^2$$\par
+% xxxxxxxxx\par
+% \egroup
+% \vbox\bgroup
+% xxxxxxxxx
+% \vskip-\baselineskip
+% $$a_2$$
+% xxxxxxxxx
+% \egroup
+% \egroup
+%
+% \hbox\bgroup
+% \setbox0\vbox\bgroup
+% xxxxxxxxx\par
+% \ctxlua{tex.prevdepth=-1000 *65536}
+% $$a^2_2$$\par
+% xxxxxxxxx\par
+% \egroup
+% \box0
+% \vbox\bgroup
+% xxxxxxxxx\par
+% \ctxlua{tex.prevdepth=-1000 *65536}
+% $$a^2$$\par
+% xxxxxxxxx\par
+% \egroup
+% \vbox\bgroup
+% xxxxxxxxx
+% \ctxlua{tex.prevdepth=-1000 *65536}
+% $$a_2$$
+% xxxxxxxxx
+% \egroup
+% \egroup
+
+\setupsubformulas % subformulas could be last in chain
+ [\c!indentnext=\formulaparameter\c!indentnext]
+
+\definecounter % one ?
+ [\v!formula]
+
+\defineconversionset
+ [\v!formula]
+ [numbers,characters] % no \v! ?
+
+\installcounterassociation{formula} \registerformulacounter\v!formula % currently we only have one
+
+\appendtoks
+ \synchronizeformulacounters
+\to \everysetupformula
+
+% \appendtoks
+% \synchronizeformulacounters
+% \to \everydefineformula
+
+\setupformulas
+ [\c!numberconversionset=\v!formula] % why forgotten
+
+\appendtoks
+ \normalexpanded{\definelist[\currentformula]}% is expansion needed?
+ \setuevalue{\e!start\currentformula\v!formula}{\strc_formulas_start_formula{\currentformula}}%
+ \setuevalue{\e!stop \currentformula\v!formula}{\strc_formulas_stop_formula}%
+\to \everydefineformula
+
+\definelist[\v!formula]
+
+\setuvalue{\e!start\v!formula}{\strc_formulas_start_formula{}}
+\setuvalue{\e!stop \v!formula}{\strc_formulas_stop_formula}
+
+\let\strc_formulas_start_formula\relax % defined later
+\let\strc_formulas_stop_formula \relax % defined later
+
+\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys
+ {\dotripleargument\strc_formulas_define_alternative} % to the general define .. s!startcommand
+
+\def\strc_formulas_define_alternative[#1][#2][#3]%
+ {\setvalue{\e!start#1\v!formula}{#2}%
+ \setvalue{\e!stop #1\v!formula}{#3}}
+
+% sp = single line paragraph sd = single line display
+% mp = multi line paragraph md = multy line display
+
+\defineformulaalternative[\s!default][\startdisplaymath][\stopdisplaymath]
+\defineformulaalternative[\s!single] [\startdisplaymath][\stopdisplaymath]
+\defineformulaalternative[\s!multi] [\startdisplaymath][\stopdisplaymath]
+
+\defineformula
+ [sp]
+ [\c!spacebefore=\v!none,
+ \c!spaceafter=\v!none,
+ \c!indentnext=\v!no,
+ \c!alternative=\s!single]
+
+\defineformula
+ [sd]
+ [\c!spacebefore=\v!none,
+ \c!spaceafter=\v!none,
+ \c!indentnext=\v!yes,
+ \c!alternative=\s!single]
+
+\defineformula
+ [mp]
+ [\c!indentnext=\v!no,
+ \c!alternative=\s!multi]
+
+\defineformula
+ [md]
+ [\c!indentnext=\v!yes,
+ \c!alternative=\s!multi]
+
+\newtoks\everyresetformulas
+
+\appendtoks
+ \let\currentformula\empty % to be checked:
+\to \everyresetformulas
+
+% implementation
+
+\unexpanded\def\strc_formulas_store_number#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float)
+ {\settrue\c_strc_formulas_handle_number
+ \strc_counters_register_component
+ {formula}%
+ \setupcurrentformula \formulaparameter \detokenizedformulaparameter
+ \relax \relax \relax
+ [\c!name=\v!formula,\s!counter=\v!formula,%
+ \s!hascaption=\v!yes,\s!hastitle=\v!yes,\s!hasnumber=\v!yes,%\s!haslevel=#6,%
+ \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}
+
+% modes: 0=unset, 1=forced, 2=none, 3=reference
+
+\newconstant\c_strc_formulas_place_number_mode
+\newconstant\c_strc_formulas_number_mode
+\newconstant\c_strc_formulas_sub_number_mode
+\newconstant\c_strc_formulas_nested_number_mode
+
+\appendtoks
+ \c_strc_formulas_place_number_mode \zerocount
+ \c_strc_formulas_number_mode \zerocount
+ \c_strc_formulas_sub_number_mode \zerocount
+ \c_strc_formulas_nested_number_mode\zerocount
+\to \everyresetformulas
+
+\newconditional\c_strc_formulas_handle_number
+\newconditional\c_strc_formulas_increment
+\newconditional\c_strc_formulas_inside_place
+\newconditional\c_strc_formulas_inside_place_sub
+\newconditional\c_strc_formulas_inside_formulas
+\newconditional\c_strc_formulas_inside_formulas_sub
+
+\appendtoks
+ \global\setfalse\c_strc_formulas_inside_place
+ \global\setfalse\c_strc_formulas_inside_place_sub
+\to \everyresetformulas
+
+% \def\strc_formulas_place_numbering % place formula
+% {\settrue\c_strc_formulas_handle_number
+% \strc_formulas_check_reference\c_strc_formulas_place_number_mode\currentplaceformulareference
+% \glet\strc_formulas_place_number\strc_formulas_place_number_indeed
+% \glet\strc_formulas_place_number_nested\strc_formulas_place_number_nested_indeed}
+
+\def\strc_formulas_place_numbering % place formula
+ {\settrue\c_strc_formulas_handle_number
+ \strc_formulas_check_reference\c_strc_formulas_place_number_mode\currentplaceformulareference
+ \ifnum\c_strc_formulas_place_number_mode=\plustwo
+ \glet\strc_formulas_place_number\relax
+ \else
+ \glet\strc_formulas_place_number\strc_formulas_place_number_indeed
+ \fi
+ \glet\strc_formulas_place_number_nested\strc_formulas_place_number_nested_indeed}
+
+\def\strc_formulas_handle_number % formulas
+ {\strc_formulas_check_reference\c_strc_formulas_number_mode\currentformulasreference}
+
+\def\strc_formulas_handle_sub_number_indeed % sub formulas
+ {\strc_formulas_check_reference\c_strc_formulas_sub_number_mode\currentsubformulasreference
+ \strc_counters_increment\v!formula
+ \strc_formulas_store_number
+ \currentsubformulasreference
+ \empty
+ \currentsubformulasnumber
+ \currentsubformulassynchronize
+ \currentsubformulasattribute}
+
+\def\strc_formulas_handle_sub_number % sub formulas
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_sub_number_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_sub_number_indeed
+ \fi}
+
+\let\strc_formulas_reference_trace\relax
+\let\strc_formulas_reference_show \relax
+
+% \def\strc_formulas_reference_trace
+% {\rlap{\hbox{\quad\tt\txx[%
+% \number\c_strc_formulas_place_number_mode,%
+% \number\c_strc_formulas_number_mode,%
+% \number\c_strc_formulas_sub_number_mode,%
+% \number\c_strc_formulas_nested_number_mode
+% ]}}}
+
+% \def\strc_formulas_reference_show
+% {\writestatus{\v!formula}%
+% {place: \number\c_strc_formulas_place_number_mode,\space
+% formula: \number\c_strc_formulas_number_mode,\space
+% subformula: \number\c_strc_formulas_sub_number_mode,\space
+% nested: \number\c_strc_formulas_nested_number_mode]}}
+
+\unexpanded\def\placecurrentformulanumber
+ {\begingroup
+ \rm % determines the distance and main font
+ \edef\p_location{\formulaparameter\c!location}%
+ \ifx\p_location\v!right
+ \hskip\formulaparameter\c!distance
+ \fi
+ \begingroup
+ \useformulastyleandcolor\c!numberstyle\c!numbercolor
+ \formulaparameter\c!numbercommand
+ {\strut
+ \formulaparameter\c!left
+ \namedtaggedlabeltexts
+ \t!formulalabel \v!formula
+ \t!formulanumber\v!formula
+ {\ignorespaces\strc_formulas_place_current_number\removeunwantedspaces}%
+ \formulaparameter\c!right}%
+ \endgroup
+ \ifx\p_location\v!left
+ \hskip\formulaparameter\c!distance
+ \fi
+ \endgroup}
+
+\unexpanded\def\strc_formulas_place_current_number
+ {\strc_formulas_handle_current_references
+ \labeltexts\currentformula{\convertedcounter[\v!formula][]}}
+
+% \def\theboxdestinationattribute#1{\iflocation\ifx#1\relax\else\ifx#1\empty\else attr \destinationattribute#1\fi\fi\fi}
+% \def\thedestinationattribute #1{\iflocation\ifx#1\relax\else\ifx#1\empty\else \attribute\destinationattribute#1\fi\fi\fi}
+
+\def\theformuladestinationattribute#1%
+ {\iflocation\ifx#1\relax\else\ifx#1\empty\else
+ \attribute\destinationattribute#1%
+ \glet#1\relax
+ \fi\fi\fi}
+
+\let\currentplaceformulaattribute\relax
+\let\currentformulaattribute \relax
+\let\currentsubformulaattribute \relax
+\let\currentformulasattribute \relax
+
+\let\currentplaceformulanumber\relax
+\let\currentformulanumber \relax
+\let\currentsubformulanumber \relax
+\let\currentformulasnumber \relax
+
+\let\currentformulasreference \empty
+\let\currentformulareference \empty
+\let\currentsubformulareference \empty
+\let\currentnestedformulareference\empty
+
+\appendtoks
+ \glet\currentformulasreference \empty
+ \glet\currentformulareference \empty
+ \glet\currentsubformulareference \empty
+ \glet\currentnestedformulareference\empty
+\to \everyresetformulas
+
+\let\currentformulassuffix \empty
+\let\currentformulasuffix \empty
+\let\currentsubformulasuffix \empty
+\let\currentnestedformulasuffix\empty
+
+\appendtoks
+ \glet\currentformulassuffix \empty
+ \glet\currentformulasuffix \empty
+ \glet\currentsubformulasuffix \empty
+ \glet\currentnestedformulasuffix\empty
+\to \everyresetformulas
+
+\let\currentplaceformulasynchronize\relax
+\let\currentformulasynchronize \relax
+\let\currentsubformulasynchronize \relax
+\let\currentformulassynchronize \relax
+
+\appendtoks
+ \glet\currentplaceformulasynchronize \relax
+ \glet\currentformulassynchronize \relax
+ \glet\currentsubformulassynchronize \relax
+ \glet\currentnestedformulasynchronize\relax
+\to \everyresetformulas
+
+% currently we do the number, some day we will do the (sub) formula
+
+\def\strc_formulas_handle_current_references
+ {\strc_formulas_reference_show
+ \ifnum\c_strc_formulas_place_number_mode=\plusthree
+ \strc_formulas_store_number
+ \currentplaceformulareference
+ \empty
+ \currentplaceformulanumber
+ \currentplaceformulasynchronize
+ \currentplaceformulaattribute
+ \currentplaceformulasynchronize
+ \glet\currentplaceformulasynchronize\relax
+ \theformuladestinationattribute\currentplaceformulaattribute
+ \fi
+ \ifnum\c_strc_formulas_number_mode=\plusthree
+ \strc_formulas_store_number
+ \currentformulasreference
+ \empty
+ \currentformulasnumber
+ \currentformulassynchronize
+ \currentformulasattribute
+ \currentformulassynchronize
+ \glet\currentformulassynchronize\relax
+ \theformuladestinationattribute\currentformulasattribute
+ \fi
+ \ifnum\c_strc_formulas_sub_number_mode=\plusthree
+ \currentsubformulassynchronize
+ \glet\currentsubformulassynchronize\relax
+ \fi
+ \ifnum\c_strc_formulas_nested_number_mode=\plusthree
+ \strc_formulas_store_number
+ \currentnestedformulareference
+ \empty
+ \currentnestedformulanumber
+ \currentnestedformulasynchronize
+ \currentnestedformulaattribute
+ \currentnestedformulasynchronize
+ \glet\currentnestedformulasynchronize\relax
+ \theformuladestinationattribute\currentnestedformulaattribute
+ \fi}
+
+% needs checking ... too many:
+
+\def\strc_formulas_handle_numbering_indeed
+ {\strc_counters_increment\v!formula
+ \doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}%
+ \placecurrentformulanumber}
+
+\def\strc_formulas_handle_numbering
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_numbering_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_numbering_indeed
+ \fi}
+
+\def\strc_formulas_handle_sub_numbering_indeed
+ {\let\strc_formulas_handle_sub_numbering\relax % else error: see math/numbering-001.tex
+ \doifelsetext\currentsubformulasuffix
+ {\strc_counters_setown_sub\v!formula\plustwo\currentsubformulasuffix}
+ {\strc_counters_increment_sub\v!formula\plustwo}%
+ \placecurrentformulanumber}
+
+\def\strc_formulas_handle_sub_numbering
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_sub_numbering_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_sub_numbering_indeed
+ \fi}
+
+\def\strc_formulas_number_indeed
+ {\ifconditional\c_strc_formulas_handle_number
+ \hbox\bgroup
+ % main counter
+ \ifconditional\c_strc_formulas_inside_formulas_sub
+ % nothing
+ \else
+ \ifcase\c_strc_formulas_number_mode
+ \ifcase\c_strc_formulas_place_number_mode
+ \strc_formulas_handle_numbering
+ \or
+ \strc_formulas_handle_numbering
+ \or
+ % nothing
+ \or
+ \strc_formulas_handle_numbering
+ \fi
+ \or
+ \strc_formulas_handle_numbering
+ \or
+ % nothing
+ \or
+ \strc_formulas_handle_numbering
+ \fi
+ \fi
+ % subcounter
+ \ifconditional\c_strc_formulas_inside_formulas_sub
+ \ifcase\c_strc_formulas_sub_number_mode
+ \strc_formulas_handle_sub_numbering % was nothing
+ \or
+ \strc_formulas_handle_sub_numbering
+ \or
+ % nothing
+ \or
+ \strc_formulas_handle_sub_numbering
+ \fi
+ \fi
+ \strc_formulas_reference_trace
+ \egroup
+ \fi}
+
+\installstructurelistprocessor\v!formula % to be checked ...
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+\newif\ifinformula
+
+%D We need a hook into the plain math alignment macros
+%D
+%D \starttyping
+%D \displaylines
+%D \eqalignno
+%D \eqalignno
+%D \stoptyping
+%D
+%D Otherwise we get a missing \type {$$} error reported.
+
+\let\reqno\eqno
+
+\unexpanded\def\resetdisplaymatheq % when used?
+ {\let\normalleqno\gobbleoneargument \let\leqno\gobbleoneargument
+ \let\normalreqno\gobbleoneargument \let\eqno \gobbleoneargument
+ \let\strc_formulas_place_number\relax}
+
+%D \macros
+%D {startsubformulas}
+
+% \placeformula
+% \startsubformulas[Maxwell]
+% \startformulas
+% \startformula \startalign
+% \NC \nabla\cdot\bf E \NC = \frac{\rho}{\varepsilon_0} \NR[Maxwell 1]
+% \NC \nabla\times\bf E \NC = - \frac{\partial\bf B}{\partial t} \NR[Maxwell II]
+% \stopalign \stopformula
+% \startformula \startalign
+% \NC \nabla\cdot \bf B \NC = 0 \NR[Maxwell III]
+% \NC \nabla\times\bf B \NC = \mu_0{\bf j}+\varepsilon_0\mu_0\frac{\partial\bf E}{\partial t} \NR[Maxwell IV]
+% \stopalign \stopformula
+% \stopformulas
+% \stopsubformulas
+%
+% Maxwell : \in [Maxwell] and II : \in [Maxwell II]
+
+%D Tricky stuff:
+
+\newdimen\lastlinewidth
+
+\abovedisplayskip \zeropoint
+\abovedisplayshortskip \zeropoint % evt. 0pt minus 3pt
+\belowdisplayskip \zeropoint
+\belowdisplayshortskip \zeropoint % evt. 0pt minus 3pt
+
+\predisplaypenalty \zerocount
+\postdisplaypenalty \zerocount % -5000 gaat mis, zie penalty bij \paragraaf
+
+% we don't use the skip's
+
+\unexpanded\def\strc_formulas_forget_display_skips
+ {\abovedisplayskip \zeropoint
+ \belowdisplayskip \zeropoint
+ \abovedisplayshortskip\zeropoint
+ \belowdisplayshortskip\zeropoint}
+
+% \def\predisplaysizethreshhold{2\emwidth} % was 3\emwidth
+
+\newdimen\d_strc_formulas_display_skip_left
+\newdimen\d_strc_formulas_display_skip_right
+\newdimen\d_strc_formulas_display_margin_left
+\newdimen\d_strc_formulas_display_margin_right
+\newdimen\d_strc_formulas_display_pre_threshold
+\newskip \d_strc_formulas_display_skip_par
+
+\unexpanded\def\beforedisplayspace
+ {\edef\p_spacebefore{\formulaparameter\c!spacebefore}%
+ \ifx\p_spacebefore\v!none \else
+ \blank[\p_spacebefore]%
+ \fi}
+
+\unexpanded\def\afterdisplayspace
+ {\edef\p_spaceafter{\formulaparameter\c!spaceafter}%
+ \ifx\p_spaceafter\v!none \else
+ \blank[\p_spaceafter]%
+ \fi}
+
+\unexpanded\def\setdisplaydimensions
+ {\displayindent\d_strc_formulas_display_skip_left
+ \advance\displayindent\d_strc_formulas_display_margin_left
+ \displaywidth\hsize
+ %\setlocalhsize
+ %\displaywidth\localhsize
+ \ifdim\hangindent>\zeropoint
+ \advance\displayindent\hangindent
+ \else
+ \advance\displaywidth\hangindent
+ \fi
+ \advance\displaywidth\dimexpr-\displayindent-\d_strc_formulas_display_skip_right-\d_strc_formulas_display_margin_right\relax
+ \hsize\displaywidth} % new, else overfull in itemize
+
+\unexpanded\def\strc_formulas_start_formula#1%
+ {\dodoubleempty\strc_formulas_start_formula_indeed[#1]}
+
+% \newskip\formulastrutht
+% \newskip\formulastrutdp
+
+%D \startbuffer
+%D \startformula[9pt] x = 1 \stopformula
+%D \startformula[7pt] x = 1 \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\strc_formulas_start_formula_indeed[#1][#2]% setting leftskip adaption is slow !
+ {\bgroup % HERE
+ \def\currentformula{#1}%
+ \dostarttaggedchained\t!formula\currentformula\??formula
+ \the\everybeforedisplayformula
+ \d_strc_formulas_display_skip_par\parskip\relax
+ %\formulastrutdp\strutdepth
+ %\formulastrutht\strutheight
+ \edef\p_option {\formulaparameter\c!option}%
+ \edef\p_margin {\formulaparameter\c!margin}%
+ \edef\p_bodyfont{#2}%
+ %\ifx\p_bodyfont\empty
+ % \edef\p_bodyfont{\formulaparameter\c!bodyfont}%
+ %\fi
+ \ifx\p_bodyfont\empty \else
+ \switchtoformulabodyfont[#2]%
+ \fi
+ \parskip\d_strc_formulas_display_skip_par\relax
+ \ifx\p_option\v!middle
+ \d_strc_formulas_display_skip_left \zeropoint
+ \d_strc_formulas_display_skip_right\zeropoint
+ \else
+ \d_strc_formulas_display_skip_left \leftskip
+ \d_strc_formulas_display_skip_right\rightskip
+ \fi
+ \d_strc_formulas_display_margin_left \formulaparameter\c!leftmargin \relax
+ \d_strc_formulas_display_margin_right\formulaparameter\c!rightmargin\relax
+ \ifx\p_margin\empty \else
+ \dosetleftskipadaption\p_margin
+ \d_strc_formulas_display_margin_left\leftskipadaption
+ \fi
+ \let\strc_formulas_start_formula\strc_formulas_start_formula_nested
+ %\freezedimenmacro\predisplaysizethreshhold
+ \strc_formulas_forget_display_skips
+ \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname}
+
+\unexpanded\def\strc_formulas_start_formula_nested#1%
+ {\bgroup
+ \let\strc_formulas_stop_formula\strc_formulas_stop_formula_nested
+ \dostarttagged\t!subformula\empty}
+
+\unexpanded\def\strc_formulas_stop_formula_nested
+ {\dostoptagged
+ \egroup}
+
+% tagging of formulanumbers is not ok (we get two display maths blobs)
+
+\unexpanded\def\strc_formulas_stop_formula
+ {\dostarttagged\t!formulacaption\empty
+ \strc_formulas_place_number
+ \dostoptagged
+ \dostarttagged\t!formulacontent\empty
+ \csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname
+ \dostoptagged
+ \dostoptagged
+ \nonoindentation
+ \useindentnextparameter\formulaparameter
+ \egroup
+ \hangafter\minusone % added for side floats
+ \hangindent\zeropoint % added for side floats
+ \setfalse\c_strc_formulas_handle_number
+ \the\everyresetformulas
+ \dorechecknextindentation} % here ?
+
+% experiment:
+
+\appendtoks
+ \edef\p_grid{\formulaparameter\c!grid}%
+ \ifx\p_grid\empty \else
+ \spac_grids_snap_value_auto\p_grid
+ \fi
+\to \everybeforedisplayformula
+
+\unexpanded\def\switchtoformulabodyfont
+ {\switchtobodyfont}
+
+\setuvalue{\v!formula}{\dosingleempty\strc_formulas_formula}
+
+\def\strc_formulas_formula[#1]#2% todo: tagged
+ {\begingroup
+ \edef\p_bodyfont{#1}%
+ \ifx\p_bodyfont\empty \else
+ \switchtoformulabodyfont[\p_bodyfont]%
+ \fi
+ % not : \def\strc_formulas_formula[##1]##2{\mathematics{##2}}%
+ \mathematics{#2}%
+ \endgroup}
+
+%D \starttyping
+%D % test \par % no preceding hlist
+%D % $$x$$ % preceding hlist
+%D % \noindent $$x$$ % no preceding hlist
+%D \startformula x \stopformula % now has \noindent (in mkii we messed with baselineskip)
+%D \stoptyping
+
+% \unexpanded\def\startdisplaymath
+% {\bgroup
+% \par
+% \informulatrue
+% \beforedisplayspace
+% \par
+% \ifvmode
+% \prevdepth-\maxdimen % texbook pagina 79-80
+% \fi
+% \noindent % else funny hlist with funny baselineskip
+% $$% \Ucheckedstartdisplaymath
+% \setdisplaydimensions
+% \startinnermath}
+%
+% \unexpanded\def\stopdisplaymath
+% {\stopinnermath
+% $$% \Ucheckedstopdisplaymath
+% \par
+% \afterdisplayspace
+% \par
+% \egroup}
+
+\newconstant\c_strc_formulas_space_model
+
+\c_strc_formulas_space_model\plusone
+%c_strc_formulas_space_model\plustwo % needs chdcking with spac-ver
+
+\unexpanded\def\startdisplaymath
+ {\bgroup
+ \par
+ \informulatrue
+ \beforedisplayspace
+ \par
+ \ifvmode
+ \ifcase\c_strc_formulas_space_model
+ % nothing
+ \or
+ % nothing yet
+ \or
+ \prevdepth-\maxdimen % texbook pagina 79-80
+ \fi
+ \fi
+ \noindent % else funny hlist with funny baselineskip
+ \Ucheckedstartdisplaymath
+ \setdisplaydimensions
+ \startinnermath}
+
+\unexpanded\def\stopdisplaymath
+ {\stopinnermath
+ \Ucheckedstopdisplaymath
+ \par
+ \ifvmode
+ \ifcase\c_strc_formulas_space_model
+ % nothing
+ \or
+ \prevdepth .5\strutdp
+ \or
+ \prevdepth\lineheight
+ \fi
+ \fi
+ \afterdisplayspace
+ \par
+ \egroup}
+
+% already defined
+%
+% \let\startinnermath\empty
+% \let\stopinnermath \empty
+
+% \defineformulaalternative[multi][\begindmath][\enddmath]
+%
+% \fakewords{20}{40}\epar
+% \placeformula {a} $$ \fakespacingformula $$
+% \fakewords{20}{40}\epar
+% \placeformula {b} \startformule \fakespacingformula \stopformule
+% \placeformula {b} \startformule \fakespacingformula \stopformule
+% \fakewords{20}{40}\epar
+% \placeformula {c} \startmdformule \fakespacingformula \stopmdformule
+% \placeformula {c} \startmdformule \fakespacingformula \stopmdformule
+% \fakewords{20}{40}\epar
+% \placeformula {d} \startmpformule \fakespacingformula \stopmpformule
+% \placeformula {d} \startmpformule \fakespacingformula \stopmpformule
+% \fakewords{20}{40}\epar
+% \placeformula {e} \startsdformule \fakespacingformula \stopsdformule
+% \placeformula {e} \startsdformule \fakespacingformula \stopsdformule
+% \fakewords{20}{40}\epar
+% \placeformula {f} \startspformule \fakespacingformula \stopspformule
+% \placeformula {f} \startspformule \fakespacingformula \stopspformule
+% \fakewords{20}{40}
+
+\unexpanded\def\startsubformulas
+ {\dosingleempty\strc_formulas_start_sub_formulas}
+
+\def\strc_formulas_start_sub_formulas[#1]%
+ {\edef\currentsubformulasreference{#1}%
+ \global\settrue\c_strc_formulas_inside_formulas_sub
+ \strc_formulas_handle_sub_number}
+
+\unexpanded\def\stopsubformulas
+ {\nonoindentation
+ \useindentnextparameter\subformulaparameter
+ \the\everyresetformulas % to be checked
+ \global\setfalse\c_strc_formulas_inside_formulas_sub
+ \dorechecknextindentation} % here ?
+
+%D Named subformulas (to be redone)
+
+\unexpanded\def\startnamedsubformulas
+ {\dosingleempty\strc_formulas_start_named_sub_formulas}
+
+\def\strc_formulas_start_named_sub_formulas[#1]#2%
+ {\setformulalistentry{#2}%
+ \startsubformulas[#1]}
+
+\unexpanded\def\stopnamedsubformulas
+ {\stopsubformulas}
+
+%D Experimental goodie:
+%D
+%D \startbuffer
+%D \placelist[formula][criterium=text] \blank[2*big]
+%D \placenamedformula[one]{first} \startformula a = 1 \stopformula \endgraf
+%D \placeformula \startformula a = 2 \stopformula \endgraf
+%D \placenamedformula {second} \startformula a = 3 \stopformula \endgraf
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\startformulas
+ {\dosingleempty\strc_formulas_start_formulas}
+
+\def\strc_formulas_start_formulas[#1]#2\stopformulas % new / to be internationalized
+ {\bgroup
+ \dostarttagged\t!formulaset\empty
+ \global\settrue\c_strc_formulas_inside_formulas
+ \edef\currentformulasreference{#1}%
+ \strc_formulas_handle_number
+ \let\currentformula\empty
+ \strc_formulas_forget_display_skips
+ \startdisplaymath
+ \setlocalhsize
+ \unexpanded\def\startformula##1\stopformula
+ {\advance\scratchcounter\plusone}%
+ \scratchcounter\zerocount
+ #2% preroll
+ \ifcase\scratchcounter\else
+ \divide \hsize \scratchcounter
+ \fi
+ \hbox to \localhsize \bgroup
+ \hss
+ \let\startformula\strc_formulas_nested_formula_start
+ \let\stopformula \strc_formulas_nested_formula_stop
+ #2%
+ \egroup
+ \stopdisplaymath
+ \global\setfalse\c_strc_formulas_inside_formulas
+ \dostoptagged
+ \egroup
+ \the\everyresetformulas
+ \hangafter\minusone % added for side floats
+ \hangindent\zeropoint} % added for side floats
+
+\unexpanded\def\strc_formulas_nested_formula_start
+ {\Ustartmath
+ \vcenter\bgroup
+ \vskip-\strutdepth
+ \Ustartdisplaymath}
+
+\unexpanded\def\strc_formulas_nested_formula_stop
+ {\Ustopdisplaymath
+ \egroup
+ \Ustopmath
+ \hss}
+
+% place
+
+\def\m_strc_formulas_flag_inhibit{-}
+\def\m_strc_formulas_flag_force {+}
+
+\def\strc_formulas_check_reference#1#2%
+ {#1\unless\ifx\namedformulaentry\empty % \relax % new 29/8/2010
+ \plusthree
+ \else\ifx#2\empty
+ \zerocount
+ \else\ifx#2\m_strc_formulas_flag_force
+ \plusone
+ \else\ifx#2\m_strc_formulas_flag_inhibit
+ \plustwo
+ \else
+ \plusthree
+ \fi\fi\fi\fi}
+
+\unexpanded\def\formulanumber
+ {\strc_formulas_number} % for the moment
+
+\unexpanded\def\strc_formulas_number
+ {\dosingleempty\strc_formulas_number_again}
+
+\unexpanded\def\strc_formulas_number_again[#1]%
+ {\def\currentformulareference{#1}%
+ \strc_formulas_number_indeed}
+
+\unexpanded\def\placeformula
+ {\global\settrue\c_strc_formulas_inside_place
+ \settrue\c_strc_formulas_increment
+ \dosingleempty\strc_formulas_place}
+
+\unexpanded\def\placesubformula
+ {\global\settrue\c_strc_formulas_inside_place_sub
+ \setfalse\c_strc_formulas_increment
+ \dosingleempty\strc_formulas_place}
+
+\unexpanded\def\strc_formulas_place[#1]%
+ {\def\currentplaceformulareference{#1}%
+ \let\currentplaceformulasuffix\empty
+ \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{}
+
+\unexpanded\def\strc_formulas_place_yes#1%
+ {\def\currentplaceformulasuffix{#1}%
+ \strc_formulas_place_nop}
+
+\unexpanded\def\strc_formulas_place_nop
+ {\doifelsenextchar$\strc_formulas_place_pickup\strc_formulas_place_indeed} % [ref]$$ [ref]\start
+
+\unexpanded\def\strc_formulas_place_indeed
+ {\strc_formulas_place_numbering}
+
+\unexpanded\def\strc_formulas_place_pickup$$#1$$%
+ {\strc_formulas_place_numbering
+ \strc_formulas_start_formula{}#1\strc_formulas_stop_formula}
+
+% \let\startplaceformula\placeformula
+% \let\stopplaceformula \relax
+
+% \startplaceformula \startformula e=mc^2 \stopformula \stopplaceformula
+% \startplaceformula[-] \startformula e=mc^2 \stopformula \stopplaceformula
+% \startplaceformula[x] \startformula e=mc^2 \stopformula \stopplaceformula
+% \startplaceformula[reference=foo] \startformula e=mc^2 \stopformula \stopplaceformula
+% \startplaceformula[title=whatever] \startformula e=mc^2 \stopformula \stopplaceformula
+% \startplaceformula[suffix=x] \startformula e=mc^2 \stopformula \stopplaceformula
+
+\unexpanded\def\startplaceformula{\dosingleempty\strc_formulas_start_place}
+\unexpanded\def\stopplaceformula {\strc_formulas_stop_place}
+
+\let\currentplaceformulareference\empty
+\let\currentplaceformulasuffix \empty
+
+\def\strc_formulas_start_place
+ {\begingroup
+ \global\settrue\c_strc_formulas_inside_place
+ \iffirstargument
+ \expandafter\strc_formulas_start_place_yes
+ \else
+ \expandafter\strc_formulas_start_place_nop
+ \fi}
+
+\def\strc_formulas_start_place_yes[#1]%
+ {\doifassignmentelse{#1}\strc_formulas_start_place_parameters\strc_formulas_start_place_reference[#1]}
+
+\def\strc_formulas_start_place_nop[#1]%
+ {\let\currentplaceformulareference\empty
+ \let\currentplaceformulasuffix \empty
+ \strc_formulas_place_nop}
+
+\def\strc_formulas_start_place_reference[#1]%
+ {\edef\currentplaceformulareference{#1}%
+ \let\currentplaceformulasuffix\empty
+ %\doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{}
+ \strc_formulas_place_nop}
+
+\def\strc_formulas_start_place_parameters[#1]%
+ {\letdummyparameter\c!title \empty
+ \letdummyparameter\c!reference\empty
+ \letdummyparameter\c!suffix \empty
+ \getdummyparameters[#1]%
+ \edef\currentplaceformulatitle {\dummyparameter\c!title}%
+ \edef\currentplaceformulareference{\dummyparameter\c!reference}%
+ \edef\currentplaceformulasuffix {\dummyparameter\c!suffix}%
+ \ifx\currentplaceformulatitle\empty\else
+ \normalexpanded{\setformulalistentry{\currentplaceformulatitle}}%
+ \fi
+ \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{}
+
+\def\strc_formulas_stop_place
+ {\relax
+ \endgroup}
+
+% to be checked
+
+\let\strc_formulas_place_number \relax
+\let\strc_formulas_place_number_nested\gobbletwoarguments
+
+\def\strc_formulas_place_number_nested_indeed#1#2%
+ {\def\currentnestedformulareference{#1}%
+ \def\currentnestedformulasuffix{#2}%
+ \glet\strc_formulas_place_number\relax
+ \strc_formulas_check_reference\c_strc_formulas_nested_number_mode\currentnestedformulareference
+ \ifcase\c_strc_formulas_nested_number_mode
+ % nothing
+ \or
+ \strc_formulas_number % hm, looks ahead for []
+ \or
+ % nothing
+ \or
+ \strc_formulas_number % hm, looks ahead for []
+ \fi}
+
+\def\strc_formulas_place_number_indeed
+ {\glet\strc_formulas_place_number\relax
+ \doifelse{\formulaparameter\c!location}\v!left
+ {\normalleqno{\strc_formulas_number_indeed}}
+ {\normalreqno{\strc_formulas_number_indeed}}}
+
+% todo
+
+\unexpanded\def\placenamedformula
+ {\dosingleempty\strc_formulase_place_named}
+
+\unexpanded\def\strc_formulase_place_named
+ {\iffirstargument
+ \expandafter\strc_formulase_place_named_yes
+ \else
+ \expandafter\strc_formulase_place_named_nop
+ \fi}
+
+\def\strc_formulase_place_named_yes[#1]#2%
+ {\setformulalistentry{#2}%
+ \placeformula[#1]}
+
+\def\strc_formulase_place_named_nop[#1]#2%
+ {\setformulalistentry{#2}%
+ \placeformula}
+
+\let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks
+
+\unexpanded\def\setformulalistentry#1%
+ {\gdef\namedformulaentry{#1}}
+
+\protect \endinput
+
+% \abovedisplayshortskip0pt \belowdisplayshortskip0pt \abovedisplayskip0pt \belowdisplayskip0pt \forgetall
+%
+% test \par $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test \par $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test plus \par \prevdepth \maxdimen $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test minus \par \prevdepth-\maxdimen $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+%
+% \parskip\baselineskip
+%
+% test \par $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test \par $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test plus \par \prevdepth \maxdimen $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
+% test minus \par \prevdepth-\maxdimen $$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$$ \par test \par
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua
new file mode 100644
index 00000000000..ddbd2ae06eb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua
@@ -0,0 +1,450 @@
+if not modules then modules = { } end modules ['strc-not'] = {
+ version = 1.001,
+ comment = "companion to strc-not.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local next = next
+
+local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end)
+local trace_references = false trackers.register("structures.notes.references", function(v) trace_references = v end)
+
+local report_notes = logs.reporter("structure","notes")
+
+local structures = structures
+local helpers = structures.helpers
+local lists = structures.lists
+local sections = structures.sections
+local counters = structures.counters
+local notes = structures.notes
+local references = structures.references
+local counterspecials = counters.specials
+
+local texgetcount = tex.getcount
+local texgetbox = tex.getbox
+
+notes.states = notes.states or { }
+lists.enhancers = lists.enhancers or { }
+
+storage.register("structures/notes/states", notes.states, "structures.notes.states")
+
+local notestates = notes.states
+local notedata = table.setmetatableindex("table")
+
+local variables = interfaces.variables
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+-- state: store, insert, postpone
+
+local function store(tag,n)
+ -- somewhat weird but this is a cheap hook spot
+ if not counterspecials[tag] then
+ counterspecials[tag] = function(tag)
+ context.doresetlinenotecompression(tag) -- maybe flag that controls it
+ end
+ end
+ --
+ local nd = notedata[tag]
+ local nnd = #nd + 1
+ nd[nnd] = n
+ local state = notestates[tag]
+ if not state then
+ report_notes("unknown state for %a",tag)
+ elseif state.kind ~= "insert" then
+ if trace_notes then
+ report_notes("storing %a with state %a as %a",tag,state.kind,nnd)
+ end
+ state.start = state.start or nnd
+ end
+ return nnd
+end
+
+notes.store = store
+
+implement {
+ name = "storenote",
+ actions = { store, context },
+ arguments = { "string", "integer" }
+}
+
+local function get(tag,n) -- tricky ... only works when defined
+ local nd = notedata[tag]
+ if not n then
+ n = #nd
+ end
+ nd = nd[n]
+ if nd then
+ if trace_notes then
+ report_notes("getting note %a of %a with listindex %a",n,tag,nd)
+ end
+ -- is this right?
+ local newdata = lists.cached[nd]
+ return newdata
+ end
+end
+
+local function getn(tag)
+ return #notedata[tag]
+end
+
+notes.get = get
+notes.getn = getn
+
+-- we could make a special enhancer
+
+local function listindex(tag,n)
+ local ndt = notedata[tag]
+ return ndt and ndt[n]
+end
+
+notes.listindex = listindex
+
+implement {
+ name = "notelistindex",
+ actions = { listindex, context },
+ arguments = { "string", "integer" }
+}
+
+local function setstate(tag,newkind)
+ local state = notestates[tag]
+ if trace_notes then
+ report_notes("setting state of %a from %s to %s",tag,(state and state.kind) or "unset",newkind)
+ end
+ if not state then
+ state = {
+ kind = newkind
+ }
+ notestates[tag] = state
+ elseif newkind == "insert" then
+ if not state.start then
+ state.kind = newkind
+ end
+ else
+-- if newkind == "postpone" and state.kind == "store" then
+-- else
+ state.kind = newkind
+-- end
+ end
+ -- state.start can already be set and will be set when an entry is added or flushed
+ return state
+end
+
+local function getstate(tag)
+ local state = notestates[tag]
+ return state and state.kind or "unknown"
+end
+
+notes.setstate = setstate
+notes.getstate = getstate
+
+implement {
+ name = "setnotestate",
+ actions = setstate,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "getnotestate",
+ actions = { getstate, context },
+ arguments = "string"
+}
+
+function notes.define(tag,kind,number)
+ local state = setstate(tag,kind)
+ state.number = number
+end
+
+implement {
+ name = "definenote",
+ actions = notes.define,
+ arguments = { "string", "string", "integer" }
+}
+
+function notes.save(tag,newkind)
+ local state = notestates[tag]
+ if state and not state.saved then
+ if trace_notes then
+ report_notes("saving state of %a, old: %a, new %a",tag,state.kind,newkind or state.kind)
+ end
+ state.saveddata = notedata[tag]
+ state.savedkind = state.kind
+ state.kind = newkind or state.kind
+ state.saved = true
+ notedata[tag] = { }
+ end
+end
+
+function notes.restore(tag,forcedstate)
+ local state = notestates[tag]
+ if state and state.saved then
+ if trace_notes then
+ report_notes("restoring state of %a, old: %a, new: %a",tag,state.kind,state.savedkind)
+ end
+ notedata[tag] = state.saveddata
+ state.kind = forcedstate or state.savedkind
+ state.saveddata = nil
+ state.saved = false
+ end
+end
+
+implement { name = "savenote", actions = notes.save, arguments = { "string", "string" } }
+implement { name = "restorenote", actions = notes.restore, arguments = { "string", "string" } }
+
+local function hascontent(tag)
+ local ok = notestates[tag]
+ if ok then
+ if ok.kind == "insert" then
+ ok = texgetbox(ok.number)
+ if ok then
+ ok = tbs.list
+ ok = lst and lst.next
+ end
+ else
+ ok = ok.start
+ end
+ end
+ return ok and true or false
+end
+
+notes.hascontent = hascontent
+
+implement {
+ name = "doifnotecontent",
+ actions = { hascontent, commands.doif },
+ arguments = "string",
+}
+
+local function internal(tag,n)
+ local nd = get(tag,n)
+ if nd then
+ local r = nd.references
+ if r then
+ local i = r.internal
+ return i and references.internals[i] -- dependency on references
+ end
+ end
+ return nil
+end
+
+local function ordered(kind,name,n)
+ local o = lists.ordered[kind]
+ o = o and o[name]
+ return o and o[n]
+end
+
+notes.internal = internal
+notes.ordered = ordered
+
+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
+ end
+ return same and true or false
+end
+
+notes.doifonsamepageasprevious = onsamepageasprevious
+
+implement {
+ name = "doifnoteonsamepageasprevious",
+ actions = { onsamepageasprevious, commands.doifelse },
+ arguments = "string",
+}
+
+function notes.checkpagechange(tag) -- called before increment !
+ local nd = notedata[tag] -- can be unset at first entry
+ if nd then
+ local current = ordered("note",tag,#nd)
+ local nextone = ordered("note",tag,#nd+1)
+ if nextone then
+ -- we can use data from the previous pass
+ if nextone.pagenumber.number > current.pagenumber.number then
+ counters.reset(tag)
+ end
+ elseif current then
+ -- we need to locate the next one, best guess
+ if texgetcount("realpageno") > current.pagenumber.number then
+ counters.reset(tag)
+ end
+ end
+ end
+end
+
+function notes.postpone()
+ if trace_notes then
+ report_notes("postponing all insert notes")
+ end
+ for tag, state in next, notestates do
+ if state.kind ~= "store" then
+ setstate(tag,"postpone")
+ end
+ end
+end
+
+implement {
+ name = "postponenotes",
+ actions = notes.postpone
+}
+
+local function getinternal(tag,n)
+ local li = internal(tag,n)
+ if li then
+ local references = li.references
+ if references then
+ return references.internal or 0
+ end
+ end
+ return 0
+end
+
+local function getdeltapage(tag,n)
+ -- 0:unknown 1:textbefore, 2:textafter, 3:samepage
+ local li = internal(tag,n)
+ if li then
+ local references = li.references
+ if references then
+ -- local symb = structures.references.collected[""]["symb:"..tag..":"..n]
+ local rymb = structures.references.collected[""]
+ local symb = rymb and rymb["*"..(references.internal or 0)]
+ local notepage = references.realpage or 0
+ local symbolpage = symb and symb.references.realpage or -1
+ if trace_references then
+ report_notes("note number %a of %a points from page %a to page %a",n,tag,symbolpage,notepage)
+ end
+ if notepage < symbolpage then
+ return 3 -- after
+ elseif notepage > symbolpage then
+ return 2 -- before
+ elseif notepage > 0 then
+ return 1 -- same
+ end
+ else
+ -- might be a note that is not flushed due to to deep
+ -- nesting in a vbox
+ end
+ end
+ return 0
+end
+
+notes.getinternal = getinternal
+notes.getdeltapage = getdeltapage
+
+implement { name = "noteinternal", actions = { getinternal, context }, arguments = { "string", "integer" } }
+implement { name = "notedeltapage", actions = { getdeltapage, context }, arguments = { "string", "integer" } }
+
+local function flushnotes(tag,whatkind,how) -- store and postpone
+ local state = notestates[tag]
+ local kind = state.kind
+ if kind == whatkind then
+ local nd = notedata[tag]
+ local ns = state.start -- first index
+ if kind == "postpone" then
+ if nd and ns then
+ if trace_notes then
+ report_notes("flushing state %a of %a from %a to %a",whatkind,tag,ns,#nd)
+ end
+ for i=ns,#nd do
+ context.handlenoteinsert(tag,i)
+ end
+ end
+ state.start = nil
+ state.kind = "insert"
+ elseif kind == "store" then
+ if nd and ns then
+ if trace_notes then
+ report_notes("flushing state %a of %a from %a to %a",whatkind,tag,ns,#nd)
+ end
+ -- todo: as registers: start, stop, inbetween
+ for i=ns,#nd do
+ -- tricky : trialtypesetting
+ if how == variables.page then
+ local rp = get(tag,i)
+ rp = rp and rp.references
+ rp = rp and rp.symbolpage or 0
+ if rp > texgetcount("realpageno") then
+ state.start = i
+ return
+ end
+ end
+ if i > ns then
+ context.betweennoteitself(tag)
+ end
+ context.handlenoteitself(tag,i)
+ end
+ end
+ state.start = nil
+ elseif kind == "reset" then
+ if nd and ns then
+ if trace_notes then
+ report_notes("flushing state %a of %a from %a to %a",whatkind,tag,ns,#nd)
+ end
+ end
+ state.start = nil
+ elseif trace_notes then
+ report_notes("not flushing state %a of %a",whatkind,tag)
+ end
+ elseif trace_notes then
+ report_notes("not flushing state %a of %a",whatkind,tag)
+ end
+end
+
+local function flushpostponednotes()
+ if trace_notes then
+ report_notes("flushing all postponed notes")
+ end
+ for tag, _ in next, notestates do
+ flushnotes(tag,"postpone")
+ end
+end
+
+implement {
+ name = "flushpostponednotes",
+ actions = flushpostponednotes
+}
+
+implement {
+ name = "flushnotes",
+ actions = flushnotes,
+ arguments = { "string", "string", "string" }
+}
+
+function notes.resetpostponed()
+ if trace_notes then
+ report_notes("resetting all postponed notes")
+ end
+ for tag, state in next, notestates do
+ if state.kind == "postpone" then
+ state.start = nil
+ state.kind = "insert"
+ end
+ end
+end
+
+implement {
+ name = "notetitle",
+ actions = function(tag,n) lists.savedlisttitle(tag,notedata[tag][n]) end,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "noteprefixednumber",
+ actions = function(tag,n) lists.savedlistprefixednumber(tag,notedata[tag][n]) end,
+ arguments = { "string", "integer" }
+}
+
+function notes.internalid(tag,n)
+ local nd = get(tag,n)
+ if nd then
+ local r = nd.references
+ return r.internal
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi
new file mode 100644
index 00000000000..edbbf92b3fc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi
@@ -0,0 +1,1933 @@
+%D \module
+%D [ file=strc-not,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Note Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Note Handling}
+
+\registerctxluafile{strc-not}{1.001}
+
+\unprotect
+
+% todo: finish local rendering
+% todo: more p_strc_notations_* (outside trial loop)
+% todo: see if we can now use \insertpenalties (>0 == some left)
+
+\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi
+\ifdefined\dotagsetnotation \else \let\dotagsetnotation \relax \fi
+
+\unexpanded\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often
+\unexpanded\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often
+
+%D Notes have two handlers: notations and notes. Although notations can
+%D be defined independently it makes not much sense. In principle we can
+%D treat notes as lists but they are currently done as a variant on
+%D enumerations. I will provide a list variant as well. One complication is
+%D that for page related notes inserts are used and therefore notes are
+%D typeset immediately and descriptions are better suited for that. For
+%D instance endnotes can as well be typeset using lists.
+
+% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number
+
+%D \macros
+%D {setupnote,setupnotation}
+%D
+%D We can influence footnote typesetting with the setup
+%D command:
+%D
+%D \showsetup{setupnotation}
+%D \showsetup{setupnote}
+%D
+%D The definition command indicate that we can frame the footnote
+%D area. The footnotes themselves are treated as descriptions.
+%D
+%D \showsetup{definenote}
+%D
+%D It's sort of a custom to precede footnotes by a horizontal
+%D rule and although fancy rules like
+%D
+%D \starttyping
+%D \hbox to 10em{\hskip-3em\dotfill}
+%D \stoptyping
+%D
+%D Are quite ligitimate, we default to a simple one 20\% of the
+%D text width.
+
+% \c!headstyle=\noteparameter\c!style,
+% \c!headcolor=\noteparameter\c!color,
+
+\installcorenamespace{notation}
+
+\installcommandhandler \??notation {notation} \??notation
+
+\installcounterassociation{notation}
+
+\let\setupnotations\setupnotation
+
+\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}]
+\definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}]
+
+\setupnotations % check with old
+ [\c!alternative=\v!note,
+ %\c!headstyle=,
+ %\c!titlestyle=,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!numbercommand=\high,
+ %\c!symbolcommand=\lowllap, % experiment
+ %\c!indicator=\v!no, % was \v!yes in mkii for page notes
+ \c!width=\v!fit,
+ \c!titledistance=.5em,
+ \c!distance=.5em,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=,
+ \c!inbetween=,
+ \c!after=,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ %\c!starter=,
+ %\c!stopper=,
+ \c!number=\v!yes,
+ \c!text=,
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=3]
+
+%D The code here is mostly the same as enumersations but we want to keep them
+%D isolated and at some point we might differentiate.
+
+% \installcorenamespace{noteclass}
+
+\unexpanded\def\strc_define_commands_notation#tag#level#parent%
+ {\doifelsenothing{#parent}
+ {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??notation#tag:\s!parent}{\??notation}}%
+ {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??note#tag:\s!parent}{\??note#parent}% see later for \s!note
+ \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}%
+ \setuevalue{\e!next #tag}{\strc_notations_next {#tag}{\number#level}}% obsolete
+ \setuevalue{\c!reset#tag}{\strc_notations_reset {#tag}{\number#level}}% obsolete
+ %setuevalue{\c!set #tag}{\strc_notations_set {#tag}{\number#level}}% obsolete
+ \setuevalue {#tag}{\strc_notations_command{#tag}}%
+ \setuevalue{\e!start#tag}{\strc_notations_start {#tag}{#tag}}% okay?
+ \setuevalue{\e!stop #tag}{\strc_notations_stop }}
+
+\appendtoks
+ \ifx\currentnotationparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentnotationsub\empty
+ \strc_define_commands_notation
+ {\currentnotationsub\currentnotation}%
+ \plusone
+ \empty
+ \edef\p_levels{\notationparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_notation
+ {\v!sub\currentnotationsub\currentnotation}%
+ \recurselevel
+ {\currentnotationsub\currentnotation}%
+ \edef\currentnotationsub{\v!sub\currentnotationsub}}%
+ \definelist[\currentnotation]% goodie
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentnotationsub\empty
+ \edef\p_levels{\notationparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_notation
+ {\currentnotationsub\currentnotation}%
+ \recurselevel
+ {\currentnotationsub\currentnotationparent}%
+ \edef\currentnotationsub{\v!sub\currentnotationsub}}%
+ \definelist[\currentnotation][\currentnotationparent]% goodie
+ \fi
+ \edef\p_counter{\notationparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentnotation
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}%
+ \letnotationparameter\s!counter\p_counter
+ %\strc_notes_setup_counter\currentnotation
+\to \everydefinenotation
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\unexpanded\setvalue{\??constructioninitializer\v!notation}%
+ {\let\currentnotation \currentconstruction
+ \let\constructionparameter \notationparameter
+ \let\constructionnamespace \??notation
+ \let\detokenizedconstructionparameter\detokenizednotationparameter
+ \let\letconstructionparameter \letnotationparameter
+ \let\useconstructionstyleandcolor \usenotationstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentnotation
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+% \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\unexpanded\setvalue{\??constructionfinalizer\v!notation}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Notations (we simply needed a word that relates to notes and is
+%D and sounds like description and enumeration) are a special case
+%D in the sense that they are stored, rendered elsewhere and referered
+%D to from where they are specified. For that reason they have a different
+%D set op main commands.
+
+% \notation[ref]{title}
+% \notation[reference=,title=]
+% \startnotation[ref] title \stopnotation
+
+\unexpanded\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2
+\unexpanded\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2
+%unexpanded\def\strc_notations_set {\strc_constructions_set_indeed \namednotationparameter} % #1#2
+
+\newconditional\c_strc_notations_anchored_next
+
+\def\strc_notations_finalize
+ {\ifconditional\c_strc_notations_anchored_next
+ \expandafter\strc_notations_finalize_next
+ \else
+ \expandafter\strc_notations_finalize_previous
+ \fi}
+
+\def\strc_notations_finalize_previous
+ {\normalexpanded{\endgroup\noteparameter\c!next}}
+
+\def\strc_notations_finalize_next
+ {\endgroup\ignorespaces}
+
+\unexpanded\def\strc_notations_command#tag%
+ {\begingroup
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \edef\p_next{\noteparameter\c!anchor}%
+ \ifx\p_next\v!next % for now only two states
+ \settrue \c_strc_notations_anchored_next
+ \else
+ \setfalse\c_strc_notations_anchored_next
+ \fi
+ \ifnotesenabled
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \doifelsenextoptionalcs\strc_notations_command_yes\strc_notations_command_nop}
+
+\unexpanded\def\strc_notations_command_nop#title%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\unexpanded\def\strc_notations_command_yes[#optional]%
+ {\doifelseassignment{#optional}\strc_notations_command_assignment\strc_notations_command_argument[#optional]}
+
+\unexpanded\def\strc_notations_command_assignment[#settings]%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#settings]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\unexpanded\def\strc_notations_command_argument[#reference]#title%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\unexpanded\def\strc_notations_start#tag#stoptag%
+ {\begingroup
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \ifnotesenabled
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \normalexpanded % not that efficient but also not that frequently used (\normaldef for parser)
+ {\def\noexpand\strc_pickup_yes[#one]#two\csname\e!stop#stoptag\endcsname{\strc_notations_command_yes[#one]{#two}}%
+ \def\noexpand\strc_pickup_nop #one\csname\e!stop#stoptag\endcsname{\strc_notations_command_nop {#one}}}%
+ \doifelsenextoptionalcs\strc_pickup_yes\strc_pickup_nop}
+
+\unexpanded\def\strc_notations_start_yes[#reference]#title%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\unexpanded\def\strc_notations_start_nop#title%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\unexpanded\def\strc_notations_stop
+ {}
+
+%D A complication is that we need to set up rather specific properties
+%D of e.g. footnotes. It is for this reason that we introduce an extra
+%D level of indirectness. This way notations don't bark on undefined
+%D macros when used in combination.
+
+\unexpanded\setvalue{\??constructionnotehandler\v!notation}%
+ {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname}
+
+\unexpanded\setvalue{\??constructionnotehandler\v!notation:}% empty case
+ {[\currentconstructionhandler:\currentconstruction]}
+
+%D Here is a simple renderer for notes
+
+\defineconstructionalternative
+ [\v!note]
+ [\c!renderingsetup=\??constructionrenderings:\v!note]
+
+\startsetups[\??constructionrenderings:\v!note]
+ \noindent
+ \leftboundary % experiment, to be done in more places
+ \llap{\box\constructionheadbox\hskip\constructionparameter\c!distance}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+%D We now implement the note definer.
+
+\installcorenamespace{note}
+
+\installframedcommandhandler \??note {note} \??note
+
+\let\setupnotes\setupnote
+
+% These only concern the inline symbol/number and wrapping of the
+% whole list.
+
+\setupnotes % not all make sense here
+ [\c!location=\v!page,
+ %\c!conversion=,
+ \c!rule=\v!on,
+ \c!before=\blank,
+ \c!bodyfont=\v!small,
+ \c!anchor=, % can also be v!next
+ %\c!style=,
+ %\c!color=,
+ %\c!after=,
+ %\c!rulecolor=,
+ %\c!rulecommand=,
+ \c!rulethickness=\linewidth,
+ \c!frame=\v!off,
+ \c!distance=.125em, % in the text between symbols
+ % \c!textseparator={,}, % optional separator
+ \c!columndistance=1em,
+ % \c!margindistance=.5em,
+ \c!align=, % also use instead of \c!tolerance
+ \c!split=\v!tolerant,
+ \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi
+ \c!height=\textheight,
+ \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice
+ \c!separator=,%
+ \c!textcommand=\high,
+ \c!textstyle=\tx,
+ %\c!textcolor=,
+ \c!interaction=\v!yes,
+ %\c!factor=,
+ %\c!scope=, % \v!text \v!page
+ \c!prefixconnector=.,
+ %\c!next=\autoinsertnextspace,
+ \c!prefix=\v!no,
+ %\c!continue=\v!no,
+ \c!paragraph=\v!no,
+ \c!inbetween=\hskip\emwidth,
+ \c!symbol=\mathematics{*},
+ \c!n=1]
+
+\setupnotes
+ [\c!expansion=\v!no,
+ \c!xmlsetup=,
+ \s!catcodes=]
+
+%D Insertions are part of notes.
+
+% \installcorenamespace{noteinsertion}
+
+\def\currentnoteinsertion {\noteparameter\s!insert}
+\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}}
+
+\appendtoks
+ \ifx\currentnoteparent\empty
+ \doifelseinsertion\currentnote
+ \donothing
+ {\defineinsertion[\currentnote]% could be an option
+ \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}%
+ \letnoteparameter\s!insert\currentnote
+ \definenotation[\currentnote][\c!type=\v!note]%
+ \else
+ \setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}%
+ \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
+ \fi
+ \clf_definenote{\currentnote}{insert}\currentnoteinsertionnumber\relax
+\to \everydefinenote
+
+% maybe we will share this at some point:
+
+\def\strc_notes_define_counter#tag% todo: move inline
+ {\definecounter[#tag]%
+ \registerenumerationcounter{#tag}}
+
+\appendtoks
+ \synchronizenotationcounters
+\to \everysetupnotation
+
+\appendtoks
+ \synchronizenotationcounters
+\to \everydefinenotation
+
+% so far
+
+%expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname
+\expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess
+\expandafter\let\csname\??constructionstophandler \v!notation\expandafter\endcsname\csname\??constructionstophandler \v!enumeration \endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname
+\expandafter\let\csname\??constructiontexthandler \v!notation\expandafter\endcsname\csname\??constructiontexthandler \v!enumeration \endcsname
+
+\unexpanded\setvalue{\??constructionmainhandler\v!notation}#following%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize
+ \attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#following}
+
+\unexpanded\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text
+ {\ifnotesenabled
+ % do be done elsewhere
+ %
+ %let\currentnote\currentconstructionmain
+ \let\currentnote\currentconstruction % else wrong inheritance
+ %
+ \iftrialtypesetting
+ \strc_notes_inject_dummy
+ \else
+ \begingroup
+ \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}%
+ \settrue\processingnote
+ \ifconditional\c_strc_notes_skip
+ \globallet\lastnotesymbol\strc_notes_inject_symbol_nop
+ \else
+ \iftypesettinglines % otherwise problems with \type <crlf> {xxx}
+ \ignorelines % makes footnotes work in \startlines ... \stoplines
+ \fi
+ \ifconditional\c_strc_notes_symbol
+ \strc_notes_inject_symbol_yes
+ \else
+ \unskip\unskip
+ \globallet\lastnotesymbol\strc_notes_inject_symbol_yes
+ \fi
+ \fi
+ \ifconditional\postponingnotes % todo: per note class
+ \global\settrue\postponednote
+ \else\ifconditional\inlocalnotes % todo: per note class
+ \global\settrue\postponednote
+ \else\ifconditional\c_strc_notes_delayed
+ % probably end notes
+ \else
+ \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed
+ \fi\fi\fi
+ \endgroup
+ \fi
+ \fi
+ \ifconditional\c_strc_notes_skip
+ \global\setfalse\c_strc_notes_skip
+ \else
+ \kern\notesignal\relax % \relax is needed to honor spaces
+ \fi}
+
+%D Interaction in notes is somewhat complex due to the way notes get
+%D flushed. In principle it is more or less the same as lists but where
+%D in lists we pack whole entries, in notes this doesn't happen. Okay,
+%D in retrospect we could have made descriptions lists but that will be
+%D a backward compatibility mess. At some point a completely new mechanism
+%D might show up, but not now. Also, as notes are inserts there is some
+%D extra mess to be kept in mind and it's easier to maintain two mechanisms
+%D than to combine too much.
+%D
+%D Interaction is also complicated because we want to provide several variants.
+%D For simple reference there is no need for anything special, as page references
+%D will do and we store them in the list anyway. But if we want a destination with
+%D dimensions we will use an additional destination because we can have only
+%D one with the same name and we always have the number as one.
+
+% interaction:
+%
+% all : text and number
+% number|yes: only number
+% text : only text
+%
+% \dogetsimple : injects
+
+\installcorenamespace{noteinteractioninline}
+\installcorenamespace{noteinteractiondisplay}
+
+\newconstant\a_strc_notes_symbol_reference
+\newconstant\a_strc_notes_number_reference
+\newconstant\a_strc_notes_text_reference
+\newconstant\a_strc_notes_text_destination
+
+\let\strc_notes_get_reference_attribute_symbol \empty
+\let\strc_notes_get_destination_attribute_symbol\empty
+
+\def\strc_notes_interaction_check_inline
+ {\edef\p_interaction{\noteparameter\c!interaction}%
+ \csname\??noteinteractioninline
+ \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi
+ \endcsname}
+
+\def\strc_notes_interaction_check_display
+ {\edef\p_interaction{\noteparameter\c!interaction}%
+ \csname\??noteinteractiondisplay
+ \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi
+ \endcsname}
+
+\def\currentnotenumber{0}
+
+\let\strc_notes_get_reference_attribute_symbol \empty
+\let\strc_notes_get_destination_attribute_symbol\empty
+
+\let\strc_notes_set_reference_attribute_number\donothing
+\let\strc_notes_set_reference_attribute_text \donothing
+\let\strc_notes_set_destination_attribute_text\donothing
+
+% inline
+
+\def\strc_references_prepare_inline_references_nop
+ {\let\strc_notes_get_reference_attribute_symbol\empty
+ \let\strc_notes_get_destination_attribute_symbol\empty
+ \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop}
+
+% \def\strc_references_prepare_inline_references_yes
+% {\strc_references_set_simple_reference{symb:\currentnote:\currentnotenumber}% destination
+% \strc_references_get_simple_reference{internal(\clf_noteinternal{\currentnote}\currentnotenumber)}% reference
+% \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
+% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+% \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
+
+\def\strc_references_prepare_inline_references_yes
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \strc_references_set_simple_reference{*\currentnoteinternal}% destination
+ \strc_references_get_simple_reference{internal(\currentnoteinternal)}% reference
+ \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
+ \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
+
+\letvalue{\??noteinteractioninline\v!no }\strc_references_prepare_inline_references_nop
+\letvalue{\??noteinteractioninline\v!all }\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!number}\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!text }\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!yes }\strc_references_prepare_inline_references_yes
+
+% display (for 'all' we need unique text and number attributes so we resolve twice
+% as we otherwise don't get the number one which is lapped in the margin so we need
+% to explicitly visit it)
+
+\def\strc_references_prepare_display_references_nop
+ {\let\strc_notes_set_reference_attribute_number\donothing
+ \let\strc_notes_set_reference_attribute_text\donothing
+ \let\strc_notes_set_destination_attribute_text\donothing
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop}
+
+% \def\strc_references_prepare_display_references_yes_number
+% {\let\strc_notes_set_reference_attribute_text\donothing
+% \strc_references_get_simple_reference{symb:\currentnote:\currentnotenumber}% reference
+% \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}%
+% \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes}
+
+% \def\strc_references_prepare_display_references_yes_text
+% {\strc_references_get_simple_reference{symb:\currentnote:\currentnotenumber}% reference
+% \edef\strc_notes_set_reference_attribute_text{\attribute\referenceattribute\currentreferenceattribute}%
+% \let\strc_notes_set_reference_attribute_number\donothing
+% \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes}
+
+% \def\strc_references_prepare_display_references_yes_all
+% {\strc_references_get_simple_reference{symb:\currentnote:\currentnotenumber}% reference
+% \edef\strc_notes_set_reference_attribute_text{\attribute\referenceattribute\currentreferenceattribute}%
+% \strc_references_get_simple_reference{symb:\currentnote:\currentnotenumber}% reference
+% \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}%
+% \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes}
+
+\def\strc_references_prepare_display_references_yes_number
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \let\strc_notes_set_reference_attribute_text\donothing
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\def\strc_references_prepare_display_references_yes_text
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_text{\attribute\referenceattribute\currentreferenceattribute}%
+ \let\strc_notes_set_reference_attribute_number\donothing
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\def\strc_references_prepare_display_references_yes_all
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_text{\attribute\referenceattribute\currentreferenceattribute}%
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\letvalue{\??noteinteractiondisplay\v!no }\strc_references_prepare_display_references_nop
+\letvalue{\??noteinteractiondisplay\v!all }\strc_references_prepare_display_references_yes_all
+\letvalue{\??noteinteractiondisplay\v!number}\strc_references_prepare_display_references_yes_number
+\letvalue{\??noteinteractiondisplay\v!text }\strc_references_prepare_display_references_yes_text
+\letvalue{\??noteinteractiondisplay\v!yes }\strc_references_prepare_display_references_yes_number
+
+\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor
+\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor
+
+\unexpanded\def\strc_notes_set_style_color_inline_yes#style#color%
+ {\usenotestyleandcolor#style#color%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\unexpanded\def\strc_notes_set_style_color_display_yes#style#color%
+ {\usenotationstyleandcolor#style#color%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\def\strc_notes_set_style_color_special
+ {\iftrialtypesetting
+ % keep
+ \else\ifx\currentcolorparameter\empty
+ \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once
+ \setlocationcolorspecified\scratchcounter
+ \fi\fi}
+
+\setvalue{\??constructiontexthandler\v!notation}%
+ {\begingroup
+ % we need to retrigger the reference as otherwise it gets lost because we don't do nested
+ % references with the same id ... maybe some day if we can figure out a nice heuristic ...
+ % the problem is that normally it's no issue but here we lap into the margin, so maybe that's
+ % a criterium
+ % \strc_notes_interaction_check_display
+ \strc_notes_set_reference_attribute_number
+ \dotagsetnotation
+ \strc_notes_set_style_color_display\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+% in mkii the pointer only showed up in pagewise notes
+
+\unexpanded\def\strc_notes_inject_pointer % todo calculate once
+ {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax
+ % unknown
+ \or
+ % same page
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}%
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}%
+ \fi}
+
+\unexpanded\def\strc_notes_inject_symbol_yes
+ {\strc_notes_inject_symbol_indeed\conditionaltrue}
+
+\unexpanded\def\strc_notes_inject_symbol_nop
+ {\strc_notes_inject_symbol_indeed\conditionalfalse}
+
+\definemargindata
+ [strc_notes_destination_margin]
+ [\v!left]
+ [\c!margin=\zeropoint,
+ \c!width=\zeropoint,
+ \c!style=,
+ \c!color=]
+
+% \unexpanded\def\strc_notes_destination_hack
+% {\ifx\strc_notes_get_destination_attribute_symbol\empty\else
+% \strc_notes_destination_hack_indeed
+% \fi}
+%
+% \unexpanded\def\strc_notes_destination_hack_indeed % can be a helper
+% {\strc_notes_destination_margin
+% {\setbox\scratchbox\hpack \strc_notes_get_destination_attribute_symbol{}%
+% \wd\scratchbox\makeupwidth
+% \ht\scratchbox\strutht
+% \dp\scratchbox\strutdp
+% \hpack to \zeropoint{\box\scratchbox\hss}}}
+
+\unexpanded\def\strc_notes_inject_symbol_indeed#synchronize%
+ {\ifconditional\c_strc_notations_anchored_next\else
+ \removeunwantedspaces
+ \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
+ \fi
+ \ifdim\lastkern=\notesignal
+ % \kern\noteparameter\c!distance % yes or no note font? or main text
+ \strc_notes_inject_separator
+ \fi
+ \nobreak
+ \begingroup
+ \strc_notes_interaction_check_inline
+ \strc_notes_set_style_color_inline\c!textstyle\c!textcolor
+ \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup
+ % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack
+ \strc_references_flush_destination_nodes % a bit late but ok
+ \dostarttagged\t!descriptionsymbol\currentnote
+ \dotagsetnotesymbol
+ \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}%
+ % the next one can cycle so we need to make sure it has no advance width
+ \doif{\noteparameter\c!indicator}\v!yes\strc_notes_inject_pointer
+ \dostoptagged
+ \egroup
+ \endgroup
+ \globallet\lastnotesymbol\relax}
+
+\unexpanded\def\strc_notes_inject_dummy % temp hack
+ {\removeunwantedspaces
+ \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
+ \ifdim\lastkern=\notesignal
+ % \kern\noteparameter\c!distance % yes or no note font? or main text
+ \strc_notes_inject_separator
+ \fi
+ \nobreak
+ \hpack to .5\emwidth{}%
+ \globallet\lastnotesymbol\relax}
+
+\unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list
+ {\edef\p_textseparator{\noteparameter\c!textseparator}%
+ \ifx\p_textseparator\empty
+ \kern\noteparameter\c!distance
+ \else
+ % skip or kern
+ \nobreak
+ \hbox\bgroup
+ \strc_notes_interaction_check_inline
+ \strc_notes_set_style_color_inline\c!textstyle\c!textcolor
+ \noteparameter\c!textcommand{\p_textseparator}%
+ \kern\noteparameter\c!distance
+ \egroup
+ \nobreak
+ \fi}
+
+% this needs a further cleanup ... soon as it's a slow mechanism
+%
+% -- set breakpoint in descriptions
+% -- reset after trialtypesetting
+% -- that way we can trick the symbol space
+
+% removed:
+%
+% \pushsomestates
+%
+% core-ins -> obsolete
+%
+% saveinsertiondata
+% restoreinsertiondata
+% saveinsertionbox
+% eraseinsertionbackup
+% restoreinsertionbackup
+
+\def\savenotedata {} % \writestatus{todo}{save note data}}
+\def\restorenotedata {} % \writestatus{todo}{restore note data}}
+\def\savenotecontent {} % \writestatus{todo}{save note content}}
+\def\restorenotecontent{} % \writestatus{todo}{restore note content}}
+\def\erasenotebackup {} % \writestatus{todo}{erase note backup}}
+
+% page-set:
+
+\def\enablenotes {\writestatus{todo}{enable notes}}
+\def\disablenotes {\writestatus{todo}{disable notes}}
+\def\savenotes {\writestatus{todo}{save notes}}
+\def\flushsavednotes{\writestatus{todo}{flush notes}}
+
+% experiment: (compare scope=text and scope=page)
+%
+% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0]
+% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
+
+%D Footnotes are can be characterized by three components:
+%D
+%D \startitemize[packed]
+%D \item a small number \footnote {a footnote number} or
+%D symbol {\setupfootnotes [conversion=set 2]\footnote
+%D {a footnote}}
+%D \item and a similar mark at the bottom of the page
+%D \item followed by some additional text
+%D \stopitemize
+%D
+%D Because footnotes are declared at the location of their
+%D reference they can be seen as a special kind of
+%D floating bodies. Their placement is postponed but has to be
+%D taken into account in the pagebreak calculations. This kind
+%D of calculations are forced by using \type{\insert}s and dealing
+%D with all cases is not trivial.
+
+%D \macros
+%D {notesenabled}
+%D
+%D We need a couple of states because at some moments we don't want
+%D to mess around with inserts at all. Take for instance a table
+%D of contents. And so we can temporary disable footnotes by saying
+%D
+%D \starttyping
+%D \notesenabledfalse
+%D \stoptyping
+
+\newif\ifnotesenabled \notesenabledtrue
+
+% better mark a note .. once flushed no more flushing
+
+%appendtoks \notesenabledfalse \to \everymarking
+\appendtoks \notesenabledfalse \to \everybeforepagebody
+\appendtoks \notesenabledfalse \to \everystructurelist % quick hack
+\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack
+\appendtoks \notesenabledfalse \to \everypreroll % quick hack
+
+%D Often we need to process the whole set of notes and to make that
+%D fast, we use a token register:
+
+% we have several synchronizers:
+%
+% - after a definition
+% - after a specific setup
+% - after a general setup (inheritance of dimensions)
+% - just before a note is typeset
+
+\newtoks\t_strc_notes
+
+\let\strc_notes_process_list\gobbleoneargument
+
+\unexpanded\def\strc_notes_process#action% argument is a \macro that uses \currentnote
+ {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}%
+ \the\t_strc_notes}
+
+\newtoks\everychecknote % just before a note is typeset
+\newtoks\everysynchronizenote % after a general setup has happened
+
+\appendtoks
+ \ifx\currentnote\empty \else
+ \setupnotations[\currentnote][]% also a synchronize
+ \fi
+\to \everysynchronizenote
+
+\def\strc_notes_synchronize
+ {\the\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist
+
+\appendtoks
+ \strc_notes_process\strc_notes_synchronize
+\to \everysetupnoteroot
+
+\appendtoks
+ \the\everysynchronizenote
+\to \everydefinenote
+
+% \starttext
+% text \startfootnote Test.\stopfootnote
+% test \footnote{xxxx} \subfootnote{xxxx}
+% test \footnote{xxxx} \subfootnote{xxxx}
+% \stoptext
+
+\installcorenamespace{notecommand}
+\installcorenamespace{notealign}
+\installcorenamespace{notepenalty}
+\installcorenamespace{noterule}
+
+\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname}
+\def\currentnoterulealign {\begincsname\??notealign \currentnote\endcsname}
+
+\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand}
+\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards
+%def\currentnoterulecommandunknown{\noteparameter\c!rule}
+
+\def\letcurrentnoterulecommand{\expandafter\let\csname\??notecommand\currentnote\endcsname}
+\def\letcurrentnoterulealign {\expandafter\let\csname\??notealign \currentnote\endcsname}
+
+\appendtoks
+ \letvalue{\??notecommand\currentnote}\currentnoterulecommandnormal
+ \letvalue{\??notealign \currentnote}\lefttoright
+\to \everysynchronizenote
+
+\def\strc_notes_set_rule
+ {\letcurrentnoterulecommand\relax % so we default to nothing
+ \letcurrentnoterulealign \relax
+ \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step}
+
+\def\strc_notes_set_rule_step#alternative%
+ {\begincsname\??noterule#alternative\endcsname}
+
+\def\strc_notes_set_rule_autodir
+ {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright}
+
+\setvalue{\??noterule \v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand}
+\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!left}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \lefttoright}
+\setvalue{\??noterule \v!right}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \righttoleft}
+\setvalue{\??noterule\v!paragraph}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \strc_notes_set_rule_autodir}
+\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax}
+
+\appendtoks
+ \strc_notes_set_rule
+\to \everysynchronizenote
+
+\def\currentnotepenalty
+ {\ifcsname\??notepenalty\noteparameter\c!split\endcsname
+ \lastnamedcs
+ \else
+ \numexpr\noteparameter\c!split\relax
+ \fi}
+
+\setnewconstant\notepenaltytolerant \zerocount
+\setnewconstant\notepenaltystrict 9999
+\setnewconstant\notepenaltyverystrict\maxdimen
+
+\letvalue{\??notepenalty\v!tolerant }\notepenaltytolerant
+\letvalue{\??notepenalty\v!strict }\notepenaltystrict
+\letvalue{\??notepenalty\v!verystrict}\notepenaltyverystrict
+\letvalue{\??notepenalty }\notepenaltytolerant
+
+\def\strc_notes_set_width
+ {\edef\p_width{\noteparameter\c!width}%
+ \ifx\p_width\empty
+ \setnoteparameter\c!width{\hsize}%
+ \fi}
+
+\appendtoks
+ \strc_notes_set_width
+\to \everysynchronizenote
+
+%D The following switch can be used to disable limiting the height of the footnote
+%D area, something that is needed in multi column balancing. Use this switch with
+%D care.
+
+\newif\ifnotelimit \notelimittrue % shared
+
+\def\strc_notes_set_factor
+ {\edef\p_factor{\noteparameter\c!factor}%
+ \ifx\p_factor\empty \else
+ \ifnum\p_factor<\zerocount \else
+% \global
+ \count\currentnoteinsertionnumber\p_factor % new: global
+ \fi
+ \fi}
+
+\appendtoks
+ \strc_notes_set_factor
+\to \everysynchronizenote
+
+% locations:
+
+\installcorenamespace{notelocationvariant}
+\installcorenamespace{notepositionvariant}
+\installcorenamespace{notedelayedvariant}
+\installcorenamespace{notelocation}
+
+\newconditional\c_strc_notes_delayed
+
+\unexpanded\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed}
+\unexpanded\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed}
+
+\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page}
+\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns}
+\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn}
+\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn}
+\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none}
+\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text}
+\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high}
+\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom}
+
+\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let
+\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let
+\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let
+
+\unexpanded\def\strc_notes_set_delayed
+ {\csname\??notedelayedvariant
+ \ifcsname\??notedelayedvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notedelayedvariant
+ \fi
+ \endcsname}
+
+% \let\strc_notes_set_delayed_yes\truecondition
+% \let\strc_notes_set_delayed_nop\falsecondition
+%
+% \def\c_strc_notes_delayed
+% {\csname\??notedelayedvariant
+% \ifcsname\??notedelayedvariant\currentnote\endcsname
+% \currentnote
+% \else
+% \??notedelayedvariant
+% \fi
+% \endcsname}
+
+\unexpanded\def\strc_notes_set_position
+ {\csname\??notepositionvariant
+ \ifcsname\??notepositionvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notepositionvariant
+ \fi
+ \endcsname}
+
+\unexpanded\def\strc_notes_set_location
+ {\csname\??notelocationvariant
+ \ifcsname\??notelocationvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notelocationvariant
+ \fi
+ \endcsname}
+
+\unexpanded\def\strc_notes_set_variants
+ {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
+
+\unexpanded\def\strc_notes_set_location_step#alternative% the insert related one
+ %{\ifcsname\??notelocation#alternative\endcsname\csname\??notelocation#alternative\endcsname\fi}
+ {\begincsname\??notelocation#alternative\endcsname}
+
+\appendtoks
+ \strc_notes_set_variants
+ \strc_notes_set_delayed
+\to \everysynchronizenote
+
+\newskip \s_strc_notes_distance % we need to implement stretch
+\newcount\c_strc_notes_columns
+
+\def\strc_notes_set_distance
+ {\begingroup
+ \setbox\scratchbox\vbox % no reuse as it can mirror
+ {\forgetall
+ % \strc_notes_set_bodyfont
+ \dontcomplain
+ \noteparameter\c!before
+ \placenoterule
+ \noteparameter\c!after}%
+ \expandafter\endgroup\expandafter
+ \s_strc_notes_distance\the\ht\scratchbox\relax}
+
+\def\strc_notes_set_columns
+ {\c_strc_notes_columns\noteparameter\c!n\relax
+ \ifcase\c_strc_notes_columns
+ \c_strc_notes_columns\plusone
+ \fi}
+
+\def\strc_notes_set_location_page
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]%
+ \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_columns
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \ifnum\currentnofcolumns=\zerocount
+ \c_strc_notes_columns\plusone
+ \fi
+ \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]%
+ \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_somecolumn#whatcolumn%
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]%
+ \global\count\currentnoteinsertionnumber\plusthousand
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn}
+\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn }
+
+\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
+ {\settrue\c_strc_notes_delayed
+ \clf_setnotestate{\currentnote}{store}%
+ \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]%
+ \global\count\currentnoteinsertionnumber\zerocount
+ \global\dimen\currentnoteinsertionnumber\maxdimen
+ \global\skip \currentnoteinsertionnumber\zeropoint}
+
+\let\strc_notes_set_location_none\strc_notes_set_location_text
+
+\def\strc_notes_set_properties
+ {\strc_notes_set_columns
+ \strc_notes_set_distance
+ \strc_notes_set_location
+ \strc_notes_set_delayed}
+
+\let\strc_notes_set_position_high\relax
+
+\def\strc_notes_set_position_bottom
+ {\settrue\c_notes_bottom_present}
+
+\appendtoks
+ \strc_notes_set_properties
+\to \everysynchronizenote
+
+%D A fast checker for bottom notes being used:
+
+\newconditional\c_notes_bottom_present
+
+\def\strc_notes_check_if_bottom_present_indeed % in otr !
+ {\ifvoid\currentnoteinsertionnumber\else
+ \strc_notes_set_position
+ \fi}
+
+\def\strc_notes_check_if_bottom_present_step
+ {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi}
+
+\def\strc_notes_check_if_bottom_present
+ {\setfalse\c_notes_bottom_present
+ \strc_notes_process\strc_notes_check_if_bottom_present_step}
+
+% Example of using factor:
+%
+% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0]
+% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle]
+% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
+% \starttext
+% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} }
+% \stoptext
+
+%D The noterule can be a graphic and therefore calling this
+%D setup macro at every skipswitch is tricky (many many MP
+%D runs). Let's just reserve a few points, that probably match
+%D those of the stretch component.
+
+%D A bit messy:
+
+\unexpanded\def\placenoterule
+ {\begingroup
+ \currentnoterulealign
+ \currentnoterulecommand
+ \par
+ \endgroup}
+
+\unexpanded\def\normalnoterule
+ {\ifvmode
+ \dontleavehmode \blackrule
+ [\c!color=\noteparameter\c!rulecolor,
+ \c!width=.2\hsize,
+ \c!height=\noteparameter\c!rulethickness,
+ \c!depth=\zeropoint]%
+ \endgraf
+ \kern\strutdepth
+ \fi}
+
+\ifdefined\setnotehsize \else
+
+ \unexpanded\def\setnotehsize{\hsize\noteparameter\c!width\relax} % can be overloaded
+
+\fi
+
+%D The formatting depends on the width of the table, so we
+%D have to set \type {n} to zero.
+%D
+%D \starttyping
+%D \startbuffer
+%D \bTABLE
+%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR
+%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \startlocalfootnotes[n=0,location={text,none}]
+%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes}
+%D \stoplocalfootnotes
+%D \stoptyping
+
+%D \macros
+%D {footnote}
+%D
+%D A footnote can have a reference as optional argument and
+%D therefore its formal specification looks like:
+%D
+%D \showsetup{footnote}
+%D
+%D This command has one optional command: the reference. By
+%D saying \type{[-]} the number is omitted. The footnote
+%D command is not that sensitive to spacing, so it's quite
+%D legal to say:
+%D
+%D \startbuffer
+%D Users of \CONTEXT\ must keep both feet \footnote{Given they
+%D have two.} on the ground and not get confused \footnote{Or
+%D even crazy.} by all those obscure \footnote{But fortunately
+%D readable.} parameters.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D When setting the \type{conversion} to \type{set 2} we get
+%D something like:
+%D
+%D \bgroup
+%D \startnarrower
+%D \setupfootnotes[conversion=set 1]
+%D \getbuffer
+%D \stopnarrower
+%D \egroup
+%D
+%D Typesetting footnotes is, at least for the moment, disabled
+%D when reshaping boxes.
+%D
+%D The additional macro \type {\footnotetext} and the
+%D associated \type {\note} macro were implemented at
+%D request of users on the mailing list and a suggestion by
+%D taco to split of the symbol placement. I decided to
+%D merge this functionality with the existing \type {\note}
+%D functionality.
+
+\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used
+\newconditional\c_strc_notes_skip
+
+\unexpanded\def\setnote [#tag]{\csname#tag\endcsname}
+\unexpanded\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname}
+
+\unexpanded\def\handlenoteinsert#tag#id%
+ {\begingroup
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \the\everybeforenoteinsert
+ \insert\currentnoteinsertionnumber\bgroup
+ \the\everyinsidenoteinsert\relax
+ \usesetupsparameter\noteparameter % experimental
+ \useinterlinespaceparameter\noteparameter
+ \doifelse{\noteparameter\c!paragraph}\v!yes
+ {\nointerlineskip
+ \startvboxtohboxseparator
+ \noteparameter\c!inbetween
+ \stopvboxtohboxseparator
+ \startvboxtohbox
+ \handlenoteitself{#tag}{#id}%
+ \stopvboxtohbox}
+ {\handlenoteitself{#tag}{#id}}%
+ \egroup
+ \the\everyafternoteinsert
+ \endgroup}
+
+\unexpanded\def\betweennoteitself#tag% used ?
+ {\edef\currentnote{#tag}%
+ \doif{\noteparameter\c!paragraph}\v!yes{\noteparameter\c!inbetween}}
+
+\unexpanded\def\handlenoteitself#tag#id%
+ {\edef\currentnotenumber{#id}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache
+ % as we can have collected notes (e.g. in tables) we need to recover
+ % \currentdescriptionattribute and \currentdescriptionsynchronize
+ %
+ \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table)
+ %
+ \dontcomplain
+ %begingroup
+ \strc_notes_interaction_check_display
+ \strc_notes_set_reference_attribute_text
+ \strc_constructions_stored_start
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \strc_notes_set_destination_attribute_text
+ \strc_notes_inject_text\relax
+ \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10
+ \strc_constructions_stored_stop
+ %endgroup
+ }
+
+\unexpanded\def\strc_notes_inject_text % hm main?
+ {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}
+
+\let\startpushnote\relax
+\let\stoppushnote \relax
+
+\newsignal\notesignal
+
+\newconditional\processingnote
+\newconditional\postponednote
+
+\newtoks\everybeforenoteinsert
+\newtoks\everyinsidenoteinsert
+\newtoks\everyafternoteinsert
+
+\appendtoks
+ \let\flushnotes\relax
+ \let\postponenotes\relax
+ \forgetall
+ \resetallattributes % new, we don't want color bleed into notes
+\to \everybeforenoteinsert
+
+\appendtoks
+ \doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment
+ \penalty\currentnotepenalty
+ %\interlinepenalty\maxdimen % todo
+ \forgetall
+ \strc_notes_set_bodyfont
+ \redoconvertfont % to undo \undo calls in in headings etc
+ \splittopskip\strutht % not actually needed here
+ \splitmaxdepth\strutdp % not actually needed here
+ % brrr
+% \leftmargindistance \noteparameter\c!margindistance
+% \rightmargindistance\leftmargindistance
+% \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
+% \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
+% \fi
+\to \everyinsidenoteinsert
+
+\appendtoks % only needed when columns
+ \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+\to \everyinsidenoteinsert
+
+% not: \appendtoks \setnotehsize \to \everyinsidenoteinsert (spoils columns)
+
+%D Normally footnotes are saved as inserts that are called upon
+%D as soon as the pagebody is constructed. The footnote
+%D insertion routine looks just like the \PLAIN\ \TEX\ one,
+%D except that we check for the end note state.
+
+% testcase for split bottom alignment see (a) below
+%
+% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}}
+
+\unexpanded\def\placenoteinserts
+ {\strc_notes_process\strc_notes_place_inserts}
+
+\def\strc_notes_place_inserts
+ {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
+ \ifconditional\c_strc_notes_delayed \else
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test
+ \strc_notes_place_inserts_indeed
+ \fi
+ \fi}
+
+\def\strc_notes_place_inserts_indeed
+ {\relax
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint
+ \endgraf
+ \ifvmode
+ \whitespace
+ \noteparameter\c!before
+ \fi
+ \placenoterule
+ \bgroup
+ \strc_notes_set_bodyfont
+ \setbox\scratchbox\hbox
+ {\strc_notes_flush_inserts}%
+ \page_postprocessors_linenumbers_deepbox\scratchbox
+ \setbox\scratchbox\hbox
+ {\setupcurrentnote
+ [\c!location=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay]%
+ \inheritednoteframed
+ {\ifdim\dp\scratchbox=\zeropoint % this hack is needed because \vadjust
+ \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement
+ \else % hides the (always) present depth
+ \box\scratchbox
+ \fi}}%
+ \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth
+ \ifvmode
+ \nointerlineskip % else sometimes empty line
+ \fi
+ \box\scratchbox
+ \egroup
+ \endgraf
+ \ifvmode
+ \noteparameter\c!after
+ \fi
+ \fi}
+
+\def\strc_notes_flush_inserts
+ {\ifcase\noteparameter\c!n\relax
+ % should not happen
+ \or
+ \strc_notes_flush_inserts_normal
+ \else
+ \strc_notes_flush_inserts_columns
+ \fi}
+
+\def\strc_notes_flush_inserts_normal
+ {\strc_notes_flush_global
+ \obeydepth} % (a) added , since split footnotes will not align properly
+
+\def\strc_notes_flush_inserts_columns
+ {\startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+ \strc_notes_flush_global
+ \stopsimplecolumns}
+
+% idea: tag with attr and then just flush them again
+
+\def\strc_notes_flush_global
+ {\begingroup
+ \useinterlinespaceparameter\noteparameter
+ \doifelse{\noteparameter\c!paragraph}\v!yes
+ {\leftorrightvbox % cf mail from ws to list
+ {\starthboxestohbox
+ \iftrialtypesetting\unvcopy\else\unvbox\fi\currentnoteinsertionnumber
+ \stophboxestohbox}}
+ {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}%
+ \endgroup}
+
+%D Supporting end notes is surprisingly easy. Even better, we
+%D can combine this feature with solving the common \TEX\
+%D problem of disappearing inserts when they're called for in
+%D deeply nested boxes. The general case looks like:
+%D
+%D \starttyping
+%D \postponenotes
+%D \.box{whatever we want with footnotes}
+%D \flushnotes
+%D \stoptyping
+%D
+%D This alternative can be used in headings, captions, tables
+%D etc. The latter one sometimes calls for notes local to
+%D the table, which can be realized by saying
+%D
+%D \starttyping
+%D \setlocalfootnotes
+%D some kind of table with local footnotes
+%D \placelocalfootnotes
+%D \stoptyping
+%D
+%D Postponing is accomplished by simply redefining the (local)
+%D insert operation. A not too robust method uses the
+%D \type{\insert} primitive when possible. This method fails in
+%D situations where it's not entirely clear in what mode \TEX\
+%D is. Therefore the auto method can is to be overruled when
+%D needed.
+
+\newconditional\postponingnotes
+
+% we need a proper state: normal, postponing, flushing
+
+\unexpanded\def\postponenotes
+ {\ifconditional\postponingnotes\else
+ \global\settrue\postponingnotes
+ \global\let\flushnotes\doflushnotes
+ \clf_postponenotes
+ \fi}
+
+\let\flushnotes\relax
+
+\unexpanded\def\doflushnotes
+ {\ifconditional\postponingnotes
+ \begingroup
+ \let\flushnotes \relax
+ \let\postponenotes\relax
+ \clf_flushpostponednotes% this also resets the states !
+ \global\setfalse\postponednote
+ \global\setfalse\postponingnotes
+ \global\let\flushnotes\relax
+ \endgroup
+ \fi}
+
+%D \macros
+%D {startlocalfootnotes,placelocalfootnotes}
+%D
+%D The next two macros can be used in for instance tables, as
+%D we'll demonstrate later on.
+%D
+%D \showsetup{startlocalfootnotes}
+%D \showsetup{placelocalfootnotes}
+
+% todo: compatibility mode: when first arg is assignment or missing, then all
+
+\newtoks\everyplacelocalnotes
+
+\appendtoks
+ \let\flushnotes \relax
+ \let\postponenotes\relax
+\to \everyplacelocalnotes
+
+\newconditional\inlocalnotes
+
+\unexpanded\def\startlocalnotes
+ {\dosingleempty\strc_notes_local_start}
+
+\def\strc_notes_local_start[#list]% grouping ? (we used to have a second argument ... settings)
+ {\def\localnoteslist{#list}%
+ \settrue\inlocalnotes
+ \processcommacommand[\localnoteslist]\strc_notes_local_start_step}
+
+\unexpanded\def\stoplocalnotes
+ {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step
+ \setfalse\inlocalnotes}
+
+\let\p_strc_notes_continue\empty
+
+\def\strc_notes_local_start_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_save{#tag}%
+ \strc_counters_reset{#tag}%
+ \fi
+ \clf_savenote{#tag}{store}}
+
+\def\strc_notes_local_stop_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_restore{#tag}%
+ \fi
+ \clf_restorenote{#tag}}
+
+\unexpanded\def\placelocalnotes
+ {\dodoubleempty\strc_notes_local_place}
+
+\def\strc_notes_local_place[#tag][#settings]%
+ {\doif{\clf_getnotestate{#tag}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}}
+
+\def\strc_notes_local_place_indeed#settings#tag%
+ {\begingroup
+ \edef\currentnote{#tag}% is already set?
+ \the\everyplacelocalnotes
+ % beware, we cannot trust setting \currentnote here
+ \setupcurrentnote[#settings]% later we set height etc for framed
+ \strc_notes_place_local_alternative
+ \strc_notes_set_properties % restore globals (if needed)
+ \endgroup
+ }% TODO: just restore properties \the\everychecknote} % we need to restore the old state
+
+%D These commands can be used like:
+%D
+%D \startbuffer
+%D \startlocalnotes[footnote]
+%D \placetable
+%D {Some Table}
+%D \placeontopofeachother
+%D {\starttable[|l|r|]
+%D \HL
+%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR
+%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR
+%D \HL
+%D \stoptable}
+%D {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]%
+%D \placelocalnotes[footnote]}
+%D \stoplocalnotes
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Because this table placement macro expect box content, and
+%D thanks to the grouping of the local footnotes, we don't need
+%D additional braces.
+%D
+%D \getbuffer
+
+%D \macros
+%D {placefootnotes}
+%D
+%D We still have no decent command for placing footnotes
+%D somewhere else than at the bottom of the page (for which no
+%D user action is needed). Footnotes (endnotes) can be
+%D placed by using
+%D
+%D \showsetup{placefootnotes}
+
+\unexpanded\def\placebottomnotes
+ {\strc_notes_process\strc_notes_place_inserts}
+
+\unexpanded\def\placenotes
+ {\dodoubleempty\strc_notes_place}
+
+\def\strc_notes_place[#list][#settings]%
+ {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}}
+
+\def\strc_notes_place_indeed#settings#tag% settings note
+ {\edef\currentnote{#tag}% grouping ?
+ \doifelse{\clf_getnotestate{#tag}}{store}
+ \strc_notes_local_place_indeed
+ \strc_notes_global_place_indeed
+ {#settings}{#tag}}
+
+\def\strc_notes_global_place_indeed#settings#tag%
+ {\begingroup
+ \setupnote[#tag][#settings]%
+ \strc_notes_place_inserts
+ \endgroup
+ \the\everysetupnote} % to be checked .. synchronize
+
+%D Placement
+
+\installcorenamespace{notealternative}
+
+\unexpanded\def\installnotealternative#alternative#command%
+ {\setvalue{\??notealternative#alternative}{#command}}
+
+\unexpanded\def\doifnotescollected#tag%
+ {\clf_doifnotecontent{#tag}}
+
+\def\strc_notes_place_local_alternative % will be a setup (wrapper)
+ {\doifnotescollected\currentnote
+ {\endgraf
+ \ifvmode
+ \whitespace
+ \noteparameter\c!before
+ \fi
+ \begingroup
+ \strc_notes_set_bodyfont
+ \csname\??notealternative\noteparameter\c!alternative\endcsname
+ \endgroup
+ \ifvmode
+ \noteparameter\c!after
+ \fi}}
+
+%D A stupid alternative is also provided:
+%D
+%D \starttyping
+%D \setupfootnotes[location=text,alternative=none]
+%D \stoptyping
+
+% setups ?
+
+\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}}
+
+\installnotealternative \v!none
+ {\flushlocalnotes\currentnote}
+
+\installnotealternative \empty
+ {\flushlocalnotes\currentnote}
+
+\installnotealternative \v!grid % test if n > 0
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \snaptogrid\hbox
+ {\inheritednoteframed
+ {\flushlocalnotes\currentnote}}%
+ \endgroup}
+
+\installnotealternative \v!fixed % test if n > 0
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \inheritednoteframed
+ {\flushlocalnotes\currentnote}%
+ \endgroup}
+
+\installnotealternative \v!columns % redundant
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \inheritednoteframed
+ {\edef\currentnotewidth{\noteparameter\c!width}%
+ \doifelsedimension\currentnotewidth\donothing
+ {\edef\currentnotewidth{\the\hsize}}%
+ \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]%
+ \flushlocalnotes\currentnote
+ \stopsimplecolumns}%
+ \endgroup}
+
+% 0:page 1:firstcolumn 2:lastcolumn
+
+\newconstant\c_strc_notes_page_location
+
+\unexpanded\def\strc_notes_check_locations
+ {\edef\p_strc_notes_location{\rootnoteparameter\c!location}%
+ \c_strc_notes_page_location
+ \ifx\p_strc_notes_location\v!firstcolumn\plusone \else
+ \ifx\p_strc_notes_location\v!lastcolumn \plustwo \else
+ \zerocount\fi\fi}
+
+\appendtoks
+ \strc_notes_check_locations
+\to \everysynchronizenote
+
+% still semi public (but will change)
+
+\newif\ifnotespresent
+
+\unexpanded\def\checknotepresence
+ {\notespresentfalse
+ \strc_notes_process\strc_notes_check_presence}
+
+\def\strc_notes_check_presence
+ {\ifdim\ht\currentnoteinsertionnumber>\zeropoint
+ \notespresenttrue
+ \fi}
+
+%D \macros
+%D {fakenotes}
+
+ % used in page-mul
+
+ \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
+
+ \unexpanded\def\fakenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalclevernoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ \unexpanded\def\fakepagenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalpagenoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ % used in page-not but not yet ok
+
+ \newdimen\totalnoteheight
+
+ \unexpanded\def\additionaltotalnoteheight#insert% temp hacks anyway
+ {\dimexpr
+ \ifdim\ht#insert>\zeropoint
+ \ifcase\count#insert %
+ \zeropoint
+ \else % todo: divide by count
+ \ht#insert+\skip#insert% hm, no stretch but a dimen anyway
+ \fi
+ \else
+ \zeropoint
+ \fi
+ \relax}
+
+ \def\docalculatetotalnoteheight
+ {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
+
+ \def\docalculatetotalclevernoteheight
+ {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
+
+ \def\docalculatetotalpagenoteheight
+ {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}}
+
+ \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
+ \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
+ \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight}
+
+%D Now how can this mechanism be hooked into \CONTEXT\ without
+%D explictly postponing footnotes? The solution turned out to
+%D be rather simple:
+%D
+%D \starttyping
+%D \everypar {...\flushnotes...}
+%D \neverypar {...\postponenotes}
+%D \stoptyping
+%D
+%D We can use \type{\neverypar} because in most commands
+%D sensitive to footnote gobbling we disable \type{\everypar}
+%D in favor for \type{\neverypar}. In fact, this footnote
+%D implementation is the first to use this scheme.
+
+%D This is a nasty and new secondary footnote flusher. It
+%D can be hooked into \type {\everypar} like:
+%D
+%D \starttyping
+%D \appendtoks \synchronizenotes \to \everypar
+%D \stoptyping
+
+% \def\dosynchronizenotes
+% {\ifvoid\currentnoteinsertionnumber\else\insert\currentnoteinsertionnumber{\unvbox\currentnoteinsertionnumber}\fi}
+%
+% \def\synchronizenotes
+% {\strc_notes_process\dosynchronizenotes}
+
+\let\synchronizenotes\relax
+
+%D When typesetting footnotes, we have to return to the
+%D footnote specific bodyfont size, which is in most cases derived
+%D from the global document bodyfont size. In the previous macros
+%D we already used a footnote specific font setting macro.
+
+\def\strc_notes_set_bodyfont
+ {\let\strc_notes_set_bodyfont\relax
+ \restoreglobalbodyfont
+ \usebodyfontparameter\noteparameter
+ \usealignparameter\noteparameter}
+
+%D The footnote mechanism defaults to a traditional one
+%D column way of showing them. By default we precede them by
+%D a small line.
+
+\definenote [\v!footnote]
+\definenote [\v!endnote ] [\c!location=\v!none] % else no break
+
+%D Compatibility macros:
+
+\unexpanded\def\setupfootnotedefinition{\setupnotation [\v!footnote]}
+\unexpanded\def\setupfootnotes {\setupnote [\v!footnote]}
+ \def\footnotetext {\setnotetext [\v!footnote]}
+\unexpanded\def\placefootnotes {\dodoubleempty\strc_notes_place_footnotes [\v!footnote]}
+\unexpanded\def\placelocalfootnotes {\dodoubleempty\strc_notes_place_local_footnotes[\v!footnote]}
+\unexpanded\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote
+\unexpanded\def\stoplocalfootnotes {\stoplocalnotes }
+
+\def\strc_notes_place_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placenotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placenotes[#list][\c!height=\textheight]%
+ \fi}
+
+\def\strc_notes_place_local_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placelocalnotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placelocalnotes[#list][\c!height=\textheight]%
+ \fi}
+
+%D Goodies:
+%D
+%D \starttyping
+%D \dorecurse {100} {
+%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
+%D }
+%D \stoptyping
+
+\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}}
+
+\let\doifnoteonsamepageelse\doifelsenoteonsamepage
+
+%D New trickery:
+
+%D \macros
+%D {note}
+%D
+%D Refering to a note is accomplished by the rather short
+%D command:
+%D
+%D \showsetup{note}
+%D
+%D This command is implemented rather straightforward as:
+
+\installcorenamespace{notesymbol}
+
+\let\lastnotesymbol\relax % todo: per class
+
+\unexpanded\def\notesymbol
+ {\dodoubleempty\strc_notes_symbol}
+
+\def\strc_notes_symbol[#tag][#reference]%
+ {\ifnotesenabled
+ \dontleavehmode
+ \begingroup
+ \edef\currentnote{#tag}%
+ \usenotestyleandcolor\c!textstyle\c!textcolor
+ \ifsecondargument
+ \unskip
+ \noteparameter\c!textcommand{\in[#reference]}% command here?
+ \else
+ \noteparameter\c!textcommand\lastnotesymbol % check if command double
+ \fi
+ \endgroup
+ \fi}
+
+\unexpanded\def\note
+ {\dodoubleempty\strc_notes_note}
+
+\def\strc_notes_note[#tag][#reference]%
+ {\ifsecondargument
+ \strc_notes_symbol[#tag][#reference]%
+ \else
+ \secondargumenttrue
+ \strc_notes_symbol[\v!footnote][#tag]%
+ \fi}
+
+% will be redone if needed
+%
+% \def\ownnotesymbol#1% #1 gets number passed
+% {\executeifdefined{\??notesymbol\currentnote}\empty}
+%
+% \unexpanded\def\setnotesymbol[#1]#2#3%
+% {\prewordbreak % prevent lookback
+% \setgvalue{\??notesymbol#1}{#3}
+% \strc_notes_inject_symbol}
+%
+% \unexpanded\def\ownnote[#1]#2#3#4%
+% {\setnotesymbol[#1]{#2}{#3}%
+% \setnotetext [#1]{#4}}
+%
+% \defineconversion
+% [ownnote]
+% [\ownnotesymbol]
+
+% tricky:
+%
+% \enabletrackers[nodes.areas]
+% \enabletrackers[nodes.references]
+% \enabletrackers[nodes.destinations]
+%
+% \setupnotes[interaction=all,rule=no]
+% \setupinteraction[state=start,focus=standard]
+%
+% \starttext
+% \goto{\input tufte\relax}[page(2)] \par
+% \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par
+% \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par
+% % \completecontent
+% % \chapter{Chapter}
+% % \dorecurse{5}{\input knuth}
+% a\footnote{\input tufte\par\input ward\relax}
+% \stoptext
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua
new file mode 100644
index 00000000000..0203334fff6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua
@@ -0,0 +1,718 @@
+if not modules then modules = { } end modules ['strc-num'] = {
+ version = 1.001,
+ comment = "companion to strc-num.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local next, type = next, type
+local min, max = math.min, math.max
+local texsetcount = tex.setcount
+
+-- Counters are managed here. They can have multiple levels which makes it easier to synchronize
+-- them. Synchronization is sort of special anyway, as it relates to document structuring.
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local trace_counters = false trackers.register("structures.counters", function(v) trace_counters = v end)
+local report_counters = logs.reporter("structure","counters")
+
+local implement = interfaces.implement
+
+local structures = structures
+local helpers = structures.helpers
+local sections = structures.sections
+local counters = structures.counters
+local documents = structures.documents
+
+local variables = interfaces.variables
+local v_start = variables.start
+local v_page = variables.page
+local v_reverse = variables.reverse
+local v_first = variables.first
+local v_next = variables.next
+local v_previous = variables.previous
+local v_prev = variables.prev
+local v_last = variables.last
+----- v_no = variables.no
+local v_backward = variables.backward
+local v_forward = variables.forward
+----- v_subs = variables.subs or "subs"
+
+-- states: start stop none reset
+
+-- specials are used for counters that are set and incremented in special ways, like
+-- pagecounters that get this treatment in the page builder
+
+counters.specials = counters.specials or { }
+local counterspecials = counters.specials
+
+local counterranges, tbs = { }, 0
+
+counters.collected = allocate()
+counters.tobesaved = counters.tobesaved or { }
+counters.data = counters.data or { }
+
+storage.register("structures/counters/data", counters.data, "structures.counters.data")
+storage.register("structures/counters/tobesaved", counters.tobesaved, "structures.counters.tobesaved")
+
+local collected = counters.collected
+local tobesaved = counters.tobesaved
+local counterdata = counters.data
+
+local function initializer() -- not really needed
+ collected = counters.collected
+ tobesaved = counters.tobesaved
+ counterdata = counters.data
+end
+
+local function finalizer()
+ for name, cd in next, counterdata do
+ local cs = tobesaved[name]
+ local data = cd.data
+ for i=1,#data do
+ local d = data[i]
+ local r = d.range
+ cs[i][r] = d.number
+ d.range = r + 1
+ end
+ end
+end
+
+job.register('structures.counters.collected', tobesaved, initializer, finalizer)
+
+local constructor = { -- maybe some day we will provide an installer for more variants
+
+ last = function(t,name,i)
+ local cc = collected[name]
+ local stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only
+ t.stop = stop
+ if t.offset then
+ return stop - t.step
+ else
+ return stop
+ end
+ end,
+
+ first = function(t,name,i)
+ local start = t.start
+ if start > 0 then
+ return start -- brrr
+ elseif t.offset then
+ return start + t.step + 1
+ else
+ return start + 1
+ end
+ end,
+
+ prev = function(t,name,i)
+ return max(t.first,t.number-1) -- todo: step
+ end,
+
+ previous = function(t,name,i)
+ return max(t.first,t.number-1) -- todo: step
+ end,
+
+ next = function(t,name,i)
+ return min(t.last,t.number+1) -- todo: step
+ end,
+
+ backward =function(t,name,i)
+ if t.number - 1 < t.first then
+ return t.last
+ else
+ return t.previous
+ end
+ end,
+
+ forward = function(t,name,i)
+ if t.number + 1 > t.last then
+ return t.first
+ else
+ return t.next
+ end
+ end,
+
+ subs = function(t,name,i)
+ local cc = collected[name]
+ t.subs = (cc and cc[i+1] and cc[i+1][t.range]) or 0
+ return t.subs
+ end,
+
+}
+
+local function dummyconstructor(t,name,i)
+ return nil -- was 0, but that is fuzzy in testing for e.g. own
+end
+
+setmetatableindex(constructor,function(t,k)
+ -- if trace_counters then
+ -- report_counters("unknown constructor %a",k)
+ -- end
+ return dummyconstructor
+end)
+
+local function enhance()
+ for name, cd in next, counterdata do
+ local data = cd.data
+ for i=1,#data do
+ local ci = data[i]
+ setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end)
+ end
+ end
+ enhance = nil
+end
+
+local function allocate(name,i) -- can be metatable
+ local cd = counterdata[name]
+ if not cd then
+ cd = {
+ level = 1,
+ -- block = "", -- todo
+ numbers = nil,
+ state = v_start, -- true
+ data = { },
+ saved = { },
+ }
+ tobesaved[name] = { }
+ counterdata[name] = cd
+ end
+ cd = cd.data
+ local ci = cd[i]
+ if not ci then
+ ci = {
+ number = 0,
+ start = 0,
+ saved = 0,
+ step = 1,
+ range = 1,
+ offset = false,
+ stop = 0, -- via metatable: last, first, stop only for tracing
+ }
+ setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end)
+ cd[i] = ci
+ tobesaved[name][i] = { }
+ else
+ if enhance then enhance() end -- not stored in bytecode
+ end
+ return ci
+end
+
+local pattern = lpeg.P(variables.by)^-1 * lpeg.C(lpeg.P(1)^1)
+local lpegmatch = lpeg.match
+
+function counters.way(way)
+ if not way or way == "" then
+ return ""
+ else
+ return lpegmatch(pattern,way)
+ end
+end
+
+implement {
+ name = "way",
+ actions = { counters.way, context },
+ arguments = "string"
+}
+
+
+function counters.record(name,i)
+ return allocate(name,i or 1)
+end
+
+local function savevalue(name,i)
+ if name then
+ local cd = counterdata[name].data[i]
+ local cs = tobesaved[name][i]
+ local cc = collected[name]
+ if trace_counters then
+ report_counters("action %a, counter %s, value %s","save",name,cd.number)
+ end
+ local cr = cd.range
+ local old = (cc and cc[i] and cc[i][cr]) or 0
+ local number = cd.number
+ if cd.method == v_page then
+ -- we can be one page ahead
+ number = number - 1
+ end
+ cs[cr] = (number >= 0) and number or 0
+ cd.range = cr + 1
+ return old
+ else
+ return 0
+ end
+end
+
+function counters.define(specification)
+ local name = specification.name
+ if name and name ~= "" then
+ -- todo: step
+ local d = allocate(name,1)
+ d.start = tonumber(specification.start) or 0
+ d.state = v_state or ""
+ local counter = specification.counter
+ if counter and counter ~= "" then
+ d.counter = counter -- only for special purposes, cannot be false
+ d.method = specification.method -- frozen at define time
+ end
+ end
+end
+
+function counters.raw(name)
+ return counterdata[name]
+end
+
+function counters.compact(name,level,onlynumbers)
+ local cd = counterdata[name]
+ if cd then
+ local data = cd.data
+ local compact = { }
+ for i=1,level or #data do
+ local d = data[i]
+ if d.number ~= 0 then
+ compact[i] = (onlynumbers and d.number) or d
+ end
+ end
+ return compact
+ end
+end
+
+-- depends on when incremented, before or after (driven by d.offset)
+
+function counters.previous(name,n)
+ return allocate(name,n).previous
+end
+
+function counters.next(name,n)
+ return allocate(name,n).next
+end
+
+counters.prev = counters.previous
+
+function counters.currentvalue(name,n)
+ return allocate(name,n).number
+end
+
+function counters.first(name,n)
+ return allocate(name,n).first
+end
+
+function counters.last(name,n)
+ return allocate(name,n).last
+end
+
+function counters.subs(name,n)
+ return counterdata[name].data[n].subs or 0
+end
+
+local function setvalue(name,tag,value)
+ local cd = counterdata[name]
+ if cd then
+ cd[tag] = value
+ end
+end
+
+counters.setvalue = setvalue
+
+function counters.setstate(name,value) -- true/false
+ value = variables[value]
+ if value then
+ setvalue(name,"state",value)
+ end
+end
+
+function counters.setlevel(name,value)
+ setvalue(name,"level",value)
+end
+
+function counters.setoffset(name,value)
+ setvalue(name,"offset",value)
+end
+
+local function synchronize(name,d)
+ local dc = d.counter
+ if dc then
+ if trace_counters then
+ report_counters("action %a, name %a, counter %a, value %a","synchronize",name,dc,d.number)
+ end
+ texsetcount("global",dc,d.number)
+ end
+ local cs = counterspecials[name]
+ if cs then
+ if trace_counters then
+ report_counters("action %a, name %a, counter %a","synccommand",name,dc)
+ end
+ cs(name)
+ end
+end
+
+local function reset(name,n)
+ local cd = counterdata[name]
+ if cd then
+ for i=n or 1,#cd.data do
+ local d = cd.data[i]
+ savevalue(name,i)
+ local number = d.start or 0
+ d.number = number
+ d.own = nil
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, value %a","reset",name,i,number)
+ end
+ synchronize(name,d)
+ end
+ cd.numbers = nil
+ else
+ end
+end
+
+local function set(name,n,value)
+ local cd = counterdata[name]
+ if cd then
+ local d = allocate(name,n)
+ local number = value or 0
+ d.number = number
+ d.own = nil
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, value %a","set",name,"no",number)
+ end
+ synchronize(name,d)
+ end
+end
+
+local function check(name,data,start,stop)
+ for i=start or 1,stop or #data do
+ local d = data[i]
+ savevalue(name,i)
+ local number = d.start or 0
+ d.number = number
+ d.own = nil
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, value %a","check",name,i,number)
+ end
+ synchronize(name,d)
+ end
+end
+
+
+local function setown(name,n,value)
+ local cd = counterdata[name]
+ if cd then
+ local d = allocate(name,n)
+ d.own = value
+ d.number = (d.number or d.start or 0) + (d.step or 0)
+ local level = cd.level
+ if not level or level == -1 then
+ -- -1 is signal that we reset manually
+ elseif level > 0 or level == -3 then
+ check(name,d,n+1)
+ elseif level == 0 then
+ -- happens elsewhere, check this for block
+ end
+ synchronize(name,d)
+ end
+end
+
+local function restart(name,n,newstart,noreset)
+ local cd = counterdata[name]
+ if cd then
+ newstart = tonumber(newstart)
+ if newstart then
+ local d = allocate(name,n)
+ d.start = newstart
+ if not noreset then -- why / when needed ?
+ reset(name,n) -- hm
+ end
+ end
+ end
+end
+
+function counters.save(name) -- or just number
+ local cd = counterdata[name]
+ if cd then
+ table.insert(cd.saved,table.copy(cd.data))
+ end
+end
+
+function counters.restore(name)
+ local cd = counterdata[name]
+ if cd and cd.saved then
+ cd.data = table.remove(cd.saved)
+ end
+end
+
+local function add(name,n,delta)
+ local cd = counterdata[name]
+ if cd and (cd.state == v_start or cd.state == "") then
+ local data = cd.data
+ local d = allocate(name,n)
+ d.number = (d.number or d.start or 0) + delta*(d.step or 0)
+ -- d.own = nil
+ local level = cd.level
+ if not level or level == -1 then
+ -- -1 is signal that we reset manually
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, how %a","add",name,"no","no checking")
+ end
+ elseif level == -2 then
+ -- -2 is signal that we work per text
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, how %a","add",name,"text","checking")
+ end
+ check(name,data,n+1)
+ elseif level > 0 or level == -3 then
+ -- within countergroup
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, how %a","add",name,level,"checking within group")
+ end
+ check(name,data,n+1)
+ elseif level == 0 then
+ -- happens elsewhere
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, how %a","add",name,level,"no checking")
+ end
+ else
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, how %a","add",name,"unknown","no checking")
+ end
+ end
+ synchronize(name,d)
+ return d.number -- not needed
+ end
+ return 0
+end
+
+function counters.check(level)
+ for name, cd in next, counterdata do
+ if level > 0 and cd.level == -3 then -- could become an option
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, detail %a","reset",name,level,"head")
+ end
+ reset(name)
+ elseif cd.level == level then
+ if trace_counters then
+ report_counters("action %a, name %a, sub %a, detail %a","reset",name,level,"normal")
+ end
+ reset(name)
+ end
+ end
+end
+
+local function get(name,n,key)
+ local d = allocate(name,n)
+ d = d and d[key]
+ if not d then
+ return 0
+ elseif type(d) == "function" then
+ return d()
+ else
+ return d
+ end
+end
+
+counters.reset = reset
+counters.set = set
+counters.add = add
+counters.get = get
+counters.setown = setown
+counters.restart = restart
+
+function counters.value(name,n) -- what to do with own
+ return get(name,n or 1,'number') or 0
+end
+
+function counters.converted(name,spec) -- name can be number and reference to storage
+ local cd
+ if type(name) == "number" then
+ cd = specials.retrieve("counter",name)
+ cd = cd and cd.counter
+ 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
+ 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
+ else
+ if kind == v_first then
+ vn = v.first
+ elseif kind == v_next then
+ vn = v.next
+ elseif kind == v_prev or kind == v_previous then
+ vn = v.prev
+ elseif kind == v_last then
+ vn = v.last
+ else
+ vn = v.number
+ if reverse then
+ local vf = v.first
+ local vl = v.last
+ if vl > 0 then
+ -- vn = vl - vn + 1 + vf
+ vn = vl - vn + vf -- see testbed for test
+ end
+ end
+ end
+ numbers[k], ownnumbers[k] = vn or v.number, nil
+ end
+ end
+ cd.numbers = numbers
+ cd.ownnumbers = ownnumbers
+ sections.typesetnumber(cd,'number',spec)
+ cd.numbers = nil
+ cd.ownnumbers = nil
+ end
+end
+
+-- interfacing
+
+local function showcounter(name)
+ local cd = counterdata[name]
+ if cd then
+ context("[%s:",name)
+ local data = cd.data
+ for i=1,#data do
+ local d = data[i]
+ context(" (%s: %s,%s,%s s:%s r:%s)",i,d.start or 0,d.number or 0,d.last,d.step or 0,d.range or 0)
+ end
+ context("]")
+ end
+end
+
+-- the noreset is somewhat messy ... always false messes up e.g. itemize but true the pagenumbers
+--
+-- if this fails i'll clean up this still somewhat experimental mechanism (but i need use cases)
+
+local function checkcountersetup(name,level,start,state)
+ local noreset = true -- level > 0 -- was true
+ counters.restart(name,1,start,noreset) -- was true
+ counters.setstate(name,state)
+ counters.setlevel(name,level)
+ sections.setchecker(name,level,counters.reset)
+end
+
+--
+
+implement { name = "addcounter", actions = add, arguments = { "string", "integer", "integer" } }
+implement { name = "setcounter", actions = set, arguments = { "string", 1, "integer" } }
+implement { name = "setowncounter", actions = setown, arguments = { "string", 1, "string" } }
+implement { name = "restartcounter", actions = restart, arguments = { "string", 1, "integer" } }
+implement { name = "resetcounter", actions = reset, arguments = { "string", 1 } }
+implement { name = "incrementcounter", actions = add, arguments = { "string", 1, 1 } }
+implement { name = "decrementcounter", actions = add, arguments = { "string", 1, -1 } }
+
+implement { name = "setsubcounter", actions = set, arguments = { "string", "integer", "integer" } }
+implement { name = "setownsubcounter", actions = setown, arguments = { "string", "integer", "string" } }
+implement { name = "restartsubcounter", actions = restart, arguments = { "string", "integer", "integer" } }
+implement { name = "resetsubcounter", actions = reset, arguments = { "string", "integer" } }
+implement { name = "incrementsubcounter", actions = add, arguments = { "string", "integer", 1 } }
+implement { name = "decrementsubcounter", actions = add, arguments = { "string", "integer", -1 } }
+
+implement { name = "rawcountervalue", actions = { counters.raw , context }, arguments = { "string", 1 } }
+implement { name = "countervalue", actions = { counters.value , context }, arguments = { "string", 1 } }
+implement { name = "lastcountervalue", actions = { counters.last , context }, arguments = { "string", 1 } }
+implement { name = "firstcountervalue", actions = { counters.first , context }, arguments = { "string", 1 } }
+implement { name = "nextcountervalue", actions = { counters.next , context }, arguments = { "string", 1 } }
+implement { name = "prevcountervalue", actions = { counters.previous, context }, arguments = { "string", 1 } }
+implement { name = "subcountervalues", actions = { counters.subs , context }, arguments = { "string", 1 } }
+
+implement { name = "rawsubcountervalue", actions = { counters.raw , context }, arguments = { "string", "integer" } }
+implement { name = "subcountervalue", actions = { counters.value , context }, arguments = { "string", "integer" } }
+implement { name = "lastsubcountervalue", actions = { counters.last , context }, arguments = { "string", "integer" } }
+implement { name = "firstsubcountervalue", actions = { counters.first , context }, arguments = { "string", "integer" } }
+implement { name = "nextsubcountervalue", actions = { counters.next , context }, arguments = { "string", "integer" } }
+implement { name = "previoussubcountervalue", actions = { counters.previous, context }, arguments = { "string", "integer" } }
+implement { name = "subsubcountervalues", actions = { counters.subs , context }, arguments = { "string", "integer" } }
+
+implement { name = "savecounter", actions = counters.save, arguments = "string" }
+implement { name = "restorecounter", actions = counters.restore, arguments = "string" }
+
+implement { name = "incrementedcounter", actions = { add, context }, arguments = { "string", 1, 1 } }
+implement { name = "decrementedcounter", actions = { add, context }, arguments = { "string", 1, -1 } }
+
+implement { name = "showcounter", actions = showcounter, arguments = "string" } -- todo
+implement { name = "checkcountersetup", actions = checkcountersetup, arguments = { "string", "integer", "integer", "string" } }
+
+table.setmetatablecall(counterdata,function(t,k) return t[k] end)
+
+implement { name = "doifelsecounter", actions = { counterdata, commands.doifelse }, arguments = "string" }
+implement { name = "doifcounter", actions = { counterdata, commands.doif }, arguments = "string" }
+implement { name = "doifnotcounter", actions = { counterdata, commands.doifnot }, arguments = "string" }
+
+implement {
+ name = "definecounter",
+ actions = counters.define,
+ arguments = {
+ {
+ { "name" } ,
+ { "start", "integer" },
+ { "counter" },
+ { "method" },
+ }
+ }
+}
+
+------------------------------------------------------------------
+------------------------------------------------------------------
+
+-- -- move to strc-pag.lua
+--
+-- function counters.analyze(name,counterspecification)
+-- local cd = counterdata[name]
+-- -- safeguard
+-- if not cd then
+-- return false, false, "no counter data"
+-- end
+-- -- section data
+-- local sectiondata = sections.current()
+-- if not sectiondata then
+-- return cd, false, "not in section"
+-- end
+-- local references = sectiondata.references
+-- if not references then
+-- return cd, false, "no references"
+-- end
+-- local section = references.section
+-- if not section then
+-- return cd, false, "no section"
+-- end
+-- sectiondata = sections.collected[references.section]
+-- if not sectiondata then
+-- return cd, false, "no section data"
+-- end
+-- -- local preferences
+-- local no = v_no
+-- if counterspecification and counterspecification.prefix == no then
+-- return cd, false, "current spec blocks prefix"
+-- end
+-- -- stored preferences (not used)
+-- if cd.prefix == no then
+-- return cd, false, "entry blocks prefix"
+-- end
+-- -- sectioning
+-- -- if sectiondata.prefix == no then
+-- -- return false, false, "sectiondata blocks prefix"
+-- -- end
+-- -- final verdict
+-- return cd, sectiondata, "okay"
+-- end
+--
+-- function counters.prefixedconverted(name,prefixspec,numberspec)
+-- local cd, prefixdata, result = counters.analyze(name,prefixspec)
+-- if cd then
+-- if prefixdata then
+-- sections.typesetnumber(prefixdata,"prefix",prefixspec or false,cd or false)
+-- end
+-- counters.converted(name,numberspec)
+-- end
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv
new file mode 100644
index 00000000000..2418130f952
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv
@@ -0,0 +1,826 @@
+%D \module
+%D [ file=strc-num,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Basic Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Basic Numbering}
+
+\registerctxluafile{strc-num}{1.001}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+% work in progress
+% to be checked: can we use the command handler code here?
+% all settings will move to lua
+
+\installcorenamespace{counter}
+
+\installcommandhandler \??counter {counter} \??counter
+
+\let\setupcounters\setupcounter
+
+\let\setupstructurecounting\setupcounter % will disappear
+
+\setupcounter
+ [\c!way=\v!by\v!chapter,
+% \c!blockway=,
+% \c!prefixstarter=,
+% \c!prefixstopper=,
+ \c!prefixconnector=.,
+ \c!prefixsegments=\autostructureprefixsegments\rootcounterparameter,
+ \c!start=\zerocount,
+ \c!prefix=\v!yes,
+ \c!state=\v!start]
+
+\def\autostructureprefixsegments#1% todo: \c!prefixsegments=\v!auto
+ {2:\thenamedheadlevel{\clf_way{#1\c!way}}}
+
+\appendtoks
+ \resetcounterparameter\s!counter
+\to \everypresetcounter
+
+\appendtoks
+ \ifx\currentcounterparent\empty
+ \edef\p_start{\counterparameter\c!start}%
+ \clf_definecounter
+ name {\currentcounter}%
+ start \ifx\p_start\empty\zerocount\else\numexpr\p_start\relax\fi
+ counter {\counterparameter\s!counter}%
+ method {\counterparameter\c!method}%
+ \relax
+ \letcounterparameter\s!name\currentcounter
+ \else
+ % \letcounterparameter\s!name\currentcounterparent % we need a chained clone
+ \setexpandedcounterparameter\s!name{\namedcounterparameter\currentcounterparent\s!name}%
+ \fi
+ \strc_counters_check_setup
+\to \everydefinecounter
+
+\appendtoks
+ \ifx\currentcounter\empty \else
+ \edef\p_number{\counterparameter\c!number}%
+ \ifx\p_number\empty \else
+ \clf_setcounter{\counterparameter\s!name}\numexpr\p_number\relax
+ \letcounterparameter\c!number\empty
+ \fi
+ \edef\p_start{\counterparameter\c!start}%
+ \setexpandedcounterparameter\c!start{\ifx\p_start\empty0\else\number\p_start\fi}%
+ \strc_counters_check_setup
+ \fi
+\to \everysetupcounter
+
+% % % %
+
+\def\strc_counters_way#1{\clf_way{\namedcounterparameter{#1}\c!way}}
+
+\def\thenamedcounterlevel#1%
+ {\xthenamedheadlevel{\clf_way{\namedcounterparameter{#1}\c!way}}}
+
+\unexpanded\def\strc_counters_check_setup
+ {\edef\p_name{\directcounterparameter\s!name}%
+ \ifx\currentcounter\p_name
+ \edef\currentcounterlevel{\thenamedcounterlevel\currentcounter}%
+ \edef\p_start{\counterparameter\c!start}%
+ \clf_checkcountersetup
+ {\currentcounter}%
+ \numexpr\currentcounterlevel\relax
+ \numexpr\ifx\p_start\empty\zerocount\else\p_start\fi\relax % bug in scanner
+ {\counterparameter\c!state}%
+ \fi}
+
+\unexpanded\def\doifelsecounter #1{\clf_doifelsecounter{\namedcounterparameter{#1}\s!name}}
+\unexpanded\def\doifcounter #1{\clf_doifcounter {\namedcounterparameter{#1}\s!name}}
+\unexpanded\def\doifnotcounter #1{\clf_doifnotcounter {\namedcounterparameter{#1}\s!name}}
+
+\let\doifcounterelse\doifelsecounter
+
+\unexpanded\def\setcounter {\dotripleempty \strc_counters_set_interfaced}
+\unexpanded\def\setcounterown {\dotripleempty \strc_counters_setown_interfaced}
+\unexpanded\def\restartcounter {\dotripleempty \strc_counters_restart_interfaced}
+\unexpanded\def\resetcounter {\dodoubleempty \strc_counters_reset_interfaced}
+\unexpanded\def\incrementcounter {\dodoubleempty \strc_counters_increment_interfaced}
+\unexpanded\def\decrementcounter {\dodoubleempty \strc_counters_decrement_interfaced}
+
+\unexpanded\def\rawcounter {\dodoubleargument\strc_counters_raw_interfaced}
+\unexpanded\def\lastcounter {\dodoubleargument\strc_counters_last_interfaced}
+\unexpanded\def\firstcounter {\dodoubleargument\strc_counters_first_interfaced}
+\unexpanded\def\nextcounter {\dodoubleargument\strc_counters_next_interfaced}
+\unexpanded\def\prevcounter {\dodoubleargument\strc_counters_prev_interfaced}
+\unexpanded\def\countersubs {\dodoubleargument\strc_counters_subs_interfaced}
+
+\unexpanded\def\savecounter {\dosingleempty \strc_counters_save_interfaced}
+\unexpanded\def\restorecounter {\dosingleempty \strc_counters_restore_interfaced}
+
+\def\strc_counters_set_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_set_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_set_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
+
+\def\strc_counters_setown_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_setown_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_setown_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
+
+\def\strc_counters_restart_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_restart_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_restart_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
+
+\def\strc_counters_reset_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_reset_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_reset_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_increment_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_increment_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_increment_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_decrement_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_decrement_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_decrement_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_raw_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_raw_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_raw_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_last_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_last_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_last_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_first_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_first_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_first_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_prev_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_prev_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_prev_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_next_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_next_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_next_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_subs_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_subs_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_subs_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_save_interfaced
+ {\iffirstargument
+ \expandafter\strc_counters_save_one
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
+
+\def\strc_counters_restore_interfaced
+ {\iffirstargument
+ \expandafter\strc_counters_restore_one
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
+
+\def\strc_counters_set_two [#1][#2][#3]{\clf_setsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
+\def\strc_counters_setown_two [#1][#2][#3]{\clf_setownsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}}
+\def\strc_counters_restart_two [#1][#2][#3]{\clf_restartsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
+\def\strc_counters_reset_two [#1][#2]{\clf_resetsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+%def\strc_counters_increment_two [#1][#2]{\clf_incrementsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_decrement_two [#1][#2]{\clf_decrementsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+
+\def\strc_counters_raw_two [#1][#2]{\clf_subcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_last_two [#1][#2]{\clf_lastsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_first_two [#1][#2]{\clf_firstsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_next_two [#1][#2]{\clf_nextsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_prev_two [#1][#2]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_subs_two [#1][#2]{\clf_subsubcountervalues {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+
+\def\strc_counters_set_one [#1][#2][#3]{\clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_setown_one [#1][#2][#3]{\clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}}
+\def\strc_counters_restart_one [#1][#2][#3]{\clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\def\strc_counters_reset_one [#1][#2]{\clf_resetcounter {\namedcounterparameter{#1}\s!name}}
+%def\strc_counters_increment_one [#1][#2]{\clf_incrementcounter {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_decrement_one [#1][#2]{\clf_decrementcounter {\namedcounterparameter{#1}\s!name}}
+
+\def\strc_counters_raw_one [#1][#2]{\clf_countervalue {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_last_one [#1][#2]{\clf_lastcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_first_one [#1][#2]{\clf_firstcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_next_one [#1][#2]{\clf_nextcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_prev_one [#1][#2]{\clf_previouscountervalue {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_subs_one [#1][#2]{\clf_subcountervalues {\namedcounterparameter{#1}\s!name}}
+
+\def\strc_counters_save_one [#1]{\clf_savecounter {\namedcounterparameter{#1}\s!name}}
+\def\strc_counters_restore_one [#1]{\clf_restorecounter {\namedcounterparameter{#1}\s!name}}
+
+\unexpanded\def\strc_counters_set #1#2{\clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\unexpanded\def\strc_counters_setown #1#2{\clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}}
+\unexpanded\def\strc_counters_restart #1#2{\clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\unexpanded\def\strc_counters_reset #1{\clf_resetcounter {\namedcounterparameter{#1}\s!name}}
+%unexpanded\def\strc_counters_increment #1{\clf_incrementcounter {\namedcounterparameter{#1}\s!name}}
+\unexpanded\def\strc_counters_decrement #1{\clf_decrementcounter {\namedcounterparameter{#1}\s!name}}
+
+ \def\strc_counters_raw #1{\clf_countervalue {\namedcounterparameter{#1}\s!name}}
+ \def\strc_counters_last #1{\clf_lastcountervalue {\namedcounterparameter{#1}\s!name}}
+ \def\strc_counters_first #1{\clf_firstcountervalue {\namedcounterparameter{#1}\s!name}}
+ \def\strc_counters_next #1{\clf_nextcountervalue {\namedcounterparameter{#1}\s!name}}
+ \def\strc_counters_prev #1{\clf_previouscountervalue {\namedcounterparameter{#1}\s!name}}
+ \def\strc_counters_subs #1{\clf_subcountervalues {\namedcounterparameter{#1}\s!name}}
+
+\unexpanded\def\strc_counters_set_sub #1#2#3{\clf_setsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
+\unexpanded\def\strc_counters_setown_sub #1#2#3{\clf_setownsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}}
+\unexpanded\def\strc_counters_restart_sub #1#2#3{\clf_restartsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
+\unexpanded\def\strc_counters_reset_sub #1#2{\clf_resetsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+%unexpanded\def\strc_counters_increment_sub #1#2{\clf_incrementsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+\unexpanded\def\strc_counters_decrement_sub #1#2{\clf_decrementsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+
+ \def\strc_counters_raw_sub #1#2{\clf_subcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} % maybe raw
+ \def\strc_counters_last_sub #1#2{\clf_lastsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+ \def\strc_counters_first_sub #1#2{\clf_firstsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+ \def\strc_counters_next_sub #1#2{\clf_nextsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+ \def\strc_counters_prev_sub #1#2{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+ \def\strc_counters_subs_sub #1#2{\clf_subsubcountervalues {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+
+\unexpanded\def\strc_counters_save #1{\clf_savecounter {\namedcounterparameter{#1}\s!name}}
+\unexpanded\def\strc_counters_restore #1{\clf_restorecounter {\namedcounterparameter{#1}\s!name}}
+
+\unexpanded\def\strc_counters_incremented #1{\clf_incrementedcounter {\namedcounterparameter{#1}\s!name}}
+\unexpanded\def\strc_counters_decremented #1{\clf_decrementedcounter {\namedcounterparameter{#1}\s!name}}
+
+\unexpanded\def\showcounter [#1]{\clf_showcounter {\namedcounterparameter{#1}\s!name}}
+
+\unexpanded\def\incrementedcounter [#1]{\clf_incrementedcounter {\namedcounterparameter{#1}\s!name}} % no \dosingleargument
+\unexpanded\def\decrementedcounter [#1]{\clf_decrementedcounter {\namedcounterparameter{#1}\s!name}} % no \dosingleargument
+
+% public variants ... beware, for old cases, from now on the value variants are the
+% ones that are expandable
+
+\def\rawcountervalue [#1]{\clf_countervalue {\namedcounterparameter{#1}\s!name}}
+\def\lastcountervalue [#1]{\clf_lastcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\firstcountervalue [#1]{\clf_firstcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\nextcountervalue [#1]{\clf_nextcountervalue {\namedcounterparameter{#1}\s!name}}
+\def\prevcountervalue [#1]{\clf_previouscountervalue{\namedcounterparameter{#1}\s!name}}
+
+\def\rawsubcountervalue [#1]#2[#3]{\clf_subcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\lastsubcountervalue [#1]#2[#3]{\clf_lastsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\firstsubcountervalue[#1]#2[#3]{\clf_firstsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\nextsubcountervalue [#1]#2[#3]{\clf_nextsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\prevsubcountervalue [#1]#2[#3]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+
+% The bypage check needs a multipass reference and therefore we only check for it when we increment
+% and know that some content will be placed. We could also check for spreads.
+
+\unexpanded\def\strc_counters_increment_sub#1#2%
+ {% this will be combined into one lua call
+ \edef\m_strc_counters_way{\strc_counters_way{#1}}%
+ \ifx\m_strc_counters_way\v!page
+ \checkpagechange{#1}%
+ \ifpagechanged
+ \strc_counters_reset{#1}%
+ \fi
+ \fi
+ \clf_incrementsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
+
+% We also need to redefine these because of the page check:
+
+ \def\strc_counters_increment_two [#1][#2]{\strc_counters_increment_sub{#1}{#2}}
+ \def\strc_counters_increment_one [#1][#2]{\strc_counters_increment_sub{#1}\plusone}
+\unexpanded\def\strc_counters_increment #1{\strc_counters_increment_sub{#1}\plusone}
+
+% so far for the hack
+
+\unexpanded\def\convertedcounter
+ {\dodoubleempty\strc_counters_converted}
+
+\def\strc_counters_converted[#1][#2]%
+ {\begingroup
+ \edef\currentcounter{#1}%
+ \ifsecondargument\setupcurrentcounter[#2]\fi
+ \clf_prefixedconverted
+ {\counterparameter\s!name}
+ {
+ prefix {\counterparameter\c!prefix}
+ separatorset {\counterparameter\c!prefixseparatorset}
+ conversion {\counterparameter\c!prefixconversion}
+ conversionset {\counterparameter\c!prefixconversionset}
+ starter {\counterparameter\c!prefixstarter}
+ stopper {\counterparameter\c!prefixstopper}
+ set {\counterparameter\c!prefixset}
+ segments {\counterparameter\c!prefixsegments}
+ connector {\counterparameter\c!prefixconnector}
+ }
+ {
+ order {\counterparameter\c!numberorder}
+ separatorset {\counterparameter\c!numberseparatorset}
+ conversion {\counterparameter\c!numberconversion}
+ conversionset {\counterparameter\c!numberconversionset}
+ starter {\counterparameter\c!numberstarter}
+ stopper {\counterparameter\c!numberstopper}
+ segments {\counterparameter\c!numbersegments}
+ type {\counterparameter\c!type}
+ criterium {\counterparameter\c!criterium}
+ }
+ \relax
+ \endgroup}
+
+\def\directconvertedcounter#1#2% name, type
+ {\clf_prefixedconverted
+ {\namedcounterparameter{#1}\s!name}
+ {
+ prefix {\namedcounterparameter{#1}\c!prefix}
+ separatorset {\namedcounterparameter{#1}\c!prefixseparatorset}
+ conversion {\namedcounterparameter{#1}\c!prefixconversion}
+ conversionset {\namedcounterparameter{#1}\c!prefixconversionset}
+ % starter {\namedcounterparameter{#1}\c!prefixstarter}
+ % stopper {\namedcounterparameter{#1}\c!prefixstopper}
+ set {\namedcounterparameter{#1}\c!prefixset}
+ segments {\namedcounterparameter{#1}\c!prefixsegments}
+ connector {\namedcounterparameter{#1}\c!prefixconnector}
+ }
+ {
+ order {\namedcounterparameter{#1}\c!numberorder}
+ separatorset {\namedcounterparameter{#1}\c!numberseparatorset}
+ conversion {\namedcounterparameter{#1}\c!numberconversion}
+ conversionset {\namedcounterparameter{#1}\c!numberconversionset}
+ starter {\namedcounterparameter{#1}\c!numberstarter}
+ stopper {\namedcounterparameter{#1}\c!numberstopper}
+ segments {\namedcounterparameter{#1}\c!numbersegments}
+ type {#2}
+ }
+ \relax}
+
+\unexpanded\def\convertedsubcounter
+ {\dotripleempty\strc_counters_converted_sub}
+
+\def\strc_counters_converted_sub[#1][#2][#3]% #2 can be n or n:m
+ {\ifsecondargument
+ \strc_counters_converted[#1][\c!numbersegments=#2,#3]%
+ \else
+ \secondargumentfalse\strc_counters_converted[#1][]%
+ \fi}
+
+% \unexpanded\def\doifdefinedcounter#1%
+% {\ifcsname\namedcounterhash{#1}\s!name\endcsname
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\gobbleoneargument
+% \fi}
+%
+% \unexpanded\def\doifundefinedcounter#1%
+% {\ifcsname\namedcounterhash{#1}\s!name\endcsname
+% \expandafter\gobbleoneargument
+% \else
+% \expandafter\firstofoneargument
+% \fi}
+%
+% \unexpanded\def\doifdefinedcounterelse#1%
+% {\ifcsname\namedcounterhash{#1}\s!name\endcsname
+% \expandafter\firstoftwoarguments
+% \else
+% \expandafter\secondoftwoarguments
+% \fi}
+
+\unexpanded\def\doifdefinedcounter {\doifcommandhandler \??counter}
+\unexpanded\def\doifundefinedcounter {\doifnotcommandhandler \??counter}
+\unexpanded\def\doifelsedefinedcounter{\doifelsecommandhandler\??counter}
+
+\let\doifdefinedcounterelse\doifelsedefinedcounter
+
+%D What follows is a compatibility layer.
+
+\let \numberparameter \namedcounterparameter % {name}\c!key
+
+\let \definenumber \definecounter % [name]
+\let \setupnumber \setupcounter % [name][setups]
+
+\let \setnumber \setcounter % [name]{value}
+\let \resetnumber \resetcounter % [name]
+\let \savenumber \savecounter % [name]
+\let \restorenumber \restorecounter % [name]
+\let \incrementnumber \incrementcounter % [name]
+\let \decrementnumber \decrementcounter % [name]
+\let \rawnumber \rawcounter % [name]
+\let \getnumber \convertedcounter % [name]
+\let \convertednumber \convertedcounter % [name]
+
+\let \doifdefinednumber \doifdefinedcounter % {number}{true}
+\let \doifundefinednumber \doifnotdefinedcounter % {number}{true}
+\let \doifelsedefinednumber \doifelsedefinedcounter % {number}{true}{false}
+\let \doifdefinednumberelse \doifelsedefinedcounter % {number}{true}{false}
+
+\let \setupnumbering \setupcounter
+
+%D Helpers:
+
+% call:
+%
+% \strc_counters_register_component
+% \currentfloat
+% \getfloatparameters \floatparameter \detokenizedfloatparameter
+% \hascaption \hastitle \hasnumber
+% [settings][userdata]
+%
+% sets:
+%
+% \m_strc_counters_last_registered_index
+% \m_strc_counters_last_registered_attribute
+% \m_strc_counters_last_registered_synchronize
+
+% currentstructurecomponent => \strc_current_ or just \m_strc_
+
+\unexpanded\def\strc_counters_register_component#1#2#3#4#5#6#7[#8][#9]% maybe also nolist
+ {\begingroup
+ %
+ #2[\s!haslevel=1,#8]%
+ \edef\p_haslevel {#3\s!haslevel}%
+ \edef\p_hascaption{#3\s!hascaption}%
+ \edef\p_hastitle {#3\s!hastitle}%
+ \edef\p_hasnumber {#3\s!hasnumber}%
+ %
+ \edef\p_prefixsegments{#3\c!prefixsegments}%
+ \ifx\p_prefixsegments\v!auto
+ \edef\p_prefixsegments{\autostructureprefixsegments#3}%
+ \fi
+ %
+ \edef\currentname{#3\s!name}%
+ \ifx\currentname\empty
+ \edef\currentname{#1}%
+ \fi
+ \edef\currentcounter{#3\s!counter}%
+ \ifx\currentcounter\empty
+ \let\currentcounter\currentname
+ \fi
+ %
+ \ifx\p_hascaption\v!yes
+ \strc_counters_register_component_list{#1}{#3}{#4}{#9}%
+ \else\ifx\currentstructurecomponentreference\empty
+ \strc_counters_register_component_none
+ \else
+ \strc_counters_register_component_page{#3}%
+ \fi\fi
+ \endgroup}
+
+\def\strc_counters_register_component_none
+ {\glet\m_strc_counters_last_registered_index \relax
+ \glet\m_strc_counters_last_registered_attribute \attributeunsetvalue
+ \glet\m_strc_counters_last_registered_synchronize\relax}
+
+\def\strc_counters_register_component_check_prefix
+ {\ifx\currentstructurecomponentreferenceprefix\empty
+ \let\currentstructurecomponentreferenceprefix\currentstructurereferenceprefix
+ \fi
+ \ifx\currentstructurecomponentreferenceprefix\empty
+ \let\currentstructurecomponentreferenceprefix\referenceprefix
+ \fi
+ \ifdefined\currentstructurecomponentreferenceprefix\else
+ \let\currentstructurecomponentreferenceprefix\empty
+ \fi}
+
+\def\strc_counters_register_component_page#1%
+ {\xdef\currentstructurecomponentreference {#1\c!reference}%
+ \xdef\currentstructurecomponentreferenceprefix{#1\c!referenceprefix}%
+ \strc_counters_register_component_check_prefix
+ \setnextinternalreference
+ \clf_setdestinationattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}% move to lua
+ view {\interactionparameter\c!focus}%
+ prefix {\currentstructurecomponentreferenceprefix}%
+ reference {\currentstructurecomponentreference}%
+ }%
+ metadata {%
+ kind {\s!page}%
+ }%
+ }%
+ \relax
+ \xdef\m_strc_counters_last_registered_attribute {\the\lastdestinationattribute}%
+ \glet\m_strc_counters_last_registered_index \relax
+ \glet\m_strc_counters_last_registered_synchronize\relax}
+
+\def\strc_counters_register_component_list#1#2#3#4%
+ {\xdef\currentstructurecomponentname {#2\s!name}%
+ \xdef\currentstructurecomponentlevel {#2\c!level}%
+ \edef\currentstructurecomponentexpansion {#2\c!expansion}%
+ \xdef\currentstructurecomponentxmlsetup {#2\c!xmlsetup}%
+ \xdef\currentstructurecomponentcatcodes {#2\s!catcodes}%
+ \xdef\currentstructurecomponentlabel {#2\c!label}%
+ \xdef\currentstructurecomponentreference {#2\c!reference}%
+ \xdef\currentstructurecomponentreferenceprefix{#2\c!referenceprefix}%
+ \strc_counters_register_component_check_prefix
+ \ifx\currentstructurecomponentexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentstructurecomponenttitle {#2\c!title}%
+ \xdef\currentstructurecomponentbookmark{#2\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#2\c!marking}%
+ \xdef\currentstructurecomponentlist {#2\c!list}%
+ \xmlstopraw
+ \ifx\currentstructurecomponentlist\empty
+ \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
+ \fi
+ \globallet\currentstructurecomponentcoding\s!xml
+ \else
+ \ifx\currentstructurecomponentexpansion\v!yes
+ \xdef\currentstructurecomponenttitle {#2\c!title}%
+ \xdef\currentstructurecomponentbookmark{#2\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#2\c!marking}%
+ \xdef\currentstructurecomponentlist {#2\c!list}%
+ \else
+ \xdef\currentstructurecomponenttitle {#3\c!title}%
+ \xdef\currentstructurecomponentbookmark{#3\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#3\c!marking}%
+ \xdef\currentstructurecomponentlist {#3\c!list}%
+ \iflocation \ifx\currentstructurecomponentbookmark\empty
+ \begingroup
+ \simplifycommands
+ \xdef\currentstructurecomponentbookmark{\detokenize\expandafter{\normalexpanded{#2\c!title}}}%
+ \endgroup
+ \fi \fi
+ \fi
+ \ifx\currentstructurecomponentlist\empty
+ \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
+ \fi
+ \globallet\currentstructurecomponentcoding\s!tex
+ \fi
+ %
+ \setnextinternalreference
+ \scratchcounter\clf_addtolist %{
+ metadata {
+ kind {#1}
+ name {\currentname}
+ % level structures.sections.currentlevel()
+ catcodes \ifx\currentstructurecomponentcatcodes\empty\catcodetable\else\csname\currentstructurecomponentcatcodes\endcsname\fi
+ coding {\currentstructurecomponentcoding}
+ \ifx\currentstructurecomponentcoding\s!xml
+ xmlroot {\xmldocument}
+ \fi
+ \ifx\currentstructurecomponentxmlsetup\empty \else
+ xmlsetup {\currentstructurexmlsetup}
+ \fi
+ }
+ references {
+ internal \nextinternalreference
+ % block {\currentsectionblock}
+ reference {\currentstructurecomponentreference}
+ prefix {\currentstructurecomponentreferenceprefix}
+ % section structures.sections.currentid()
+ view {\interactionparameter\c!focus}%
+ }
+ titledata {
+ label {\detokenize\expandafter{\currentstructurecomponentlabel}}
+ title {\detokenize\expandafter{\currentstructurecomponenttitle}}
+ \ifx\currentstructurecomponentbookmark\currentstructurecomponenttitle \else
+ bookmark {\detokenize\expandafter{\currentstructurecomponentbookmark}}
+ \fi
+ \ifx\currentstructurecomponentmarking\currentstructurecomponenttitle \else
+ marking {\detokenize\expandafter{\currentstructurecomponentmarking}}
+ \fi
+ \ifx\currentstructurecomponentlist\currentstructurecomponenttitle \else
+ list {\detokenize\expandafter{\currentstructurecomponentlist}}
+ \fi
+ }
+ \ifx\p_hasnumber\v!yes
+ prefixdata {
+ prefix {#2\c!prefix}
+ separatorset {#2\c!prefixseparatorset}
+ conversion {#2\c!prefixconversion}
+ conversionset {#2\c!prefixconversionset}
+ set {#2\c!prefixset}
+ % segments {#2\c!prefixsegments}
+ segments {\p_prefixsegments}
+ connector {#2\c!prefixconnector}
+ }
+ numberdata { % more helpers here, like compact elsewhere
+ numbers {\currentcounter}
+ group {#2\c!group}
+ groupsuffix {#2\c!groupsuffix}
+ counter {\currentcounter}
+ separatorset {#2\c!numberseparatorset}
+ conversion {#2\c!numberconversion}
+ conversionset {#2\c!numberconversionset}
+ starter {#2\c!numberstarter}
+ stopper {#2\c!numberstopper}
+ segments {#2\c!numbersegments}
+ }
+ \fi
+ userdata {\detokenize{#4}}
+ %}
+ \relax
+ \xdef\m_strc_counters_last_registered_index{\the\scratchcounter}%
+ \clf_setinternalreference
+ internal \nextinternalreference
+ \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}{\nextinternalreference}}}
+
+\let\m_strc_counters_last_registered_index \relax
+\let\m_strc_counters_last_registered_attribute \relax
+\let\m_strc_counters_last_registered_synchronize\relax
+
+% This can be improved as we don't need to pas all these variables
+% each time (we can set them up once).
+
+\unexpanded\def\strc_counter_preset_using_parameter#1#2% \setupcommand \someparameter
+ {#1%
+ [\c!way =#2\c!way,
+ \c!prefix =#2\c!prefix,
+ \c!prefixseparatorset =#2\c!prefixseparatorset,
+ \c!prefixconversion =#2\c!prefixconversion,
+ \c!prefixconversionset=#2\c!prefixconversionset,
+ \c!prefixstarter =#2\c!prefixstarter,
+ \c!prefixstopper =#2\c!prefixstopper,
+ \c!prefixsegments =#2\c!prefixsegments,
+ \c!prefixset =#2\c!prefixset,
+ \c!prefixconnector =#2\c!prefixconnector,
+ \c!numberseparatorset =#2\c!numberseparatorset,
+ \c!numberconversion =#2\c!numberconversion,
+ \c!numberconversionset=#2\c!numberconversionset,
+ \c!numberstarter =#2\c!numberstarter,
+ \c!numberstopper =#2\c!numberstopper,
+ \c!numbersegments =#2\c!numbersegments]}
+
+% \unexpanded\def\strc_counter_setup_using_parameter#1#2% name \someparameter
+% {\setupcounter
+% [#1]
+% [ \c!start=#2\c!start,
+% \c!state=#2\c!state, % beware, "" == start
+% \c!way=#2\c!way,
+% %
+% \c!prefix=#2\c!prefix,
+% \c!prefixseparatorset=#2\c!prefixseparatorset,
+% \c!prefixconversion=#2\c!prefixconversion,
+% \c!prefixconversionset=#2\c!prefixconversionset,
+% \c!prefixstarter=#2\c!prefixstarter,
+% \c!prefixstopper=#2\c!prefixstopper,
+% \c!prefixset=#2\c!prefixset,
+% \c!prefixsegments=#2\c!prefixsegments,
+% \c!prefixset=#2\c!prefixset,
+% \c!prefixconnector=#2\c!prefixconnector,
+% %
+% \c!numberseparatorset=#2\c!numberseparatorset,
+% \c!numberconversion=#2\c!numberconversion,
+% \c!numberconversionset=#2\c!numberconversionset,
+% \c!numberstarter=#2\c!numberstarter,
+% \c!numberstopper=#2\c!numberstopper,
+% \c!numbersegments=#2\c!numbersegments]}
+
+\unexpanded\def\strc_counter_setup_using_parameter#1#2% name \someparameter
+ {\edef\currentcounter{#1}%
+ %
+ \setcounterparameter \c!start{#2\c!start}%
+ \setcounterparameter \c!state{#2\c!state}% % beware, "" == start
+ \setcounterparameter \c!way{#2\c!way}%
+ %
+ \setcounterparameter \c!prefix{#2\c!prefix}%
+ \setcounterparameter \c!prefixseparatorset{#2\c!prefixseparatorset}%
+ \setcounterparameter \c!prefixconversion{#2\c!prefixconversion}%
+ \setcounterparameter\c!prefixconversionset{#2\c!prefixconversionset}%
+ \setcounterparameter \c!prefixstarter{#2\c!prefixstarter}%
+ \setcounterparameter \c!prefixstopper{#2\c!prefixstopper}%
+ \setcounterparameter \c!prefixset{#2\c!prefixset}%
+ \setcounterparameter \c!prefixsegments{#2\c!prefixsegments}%
+ \setcounterparameter \c!prefixset{#2\c!prefixset}%
+ \setcounterparameter \c!prefixconnector{#2\c!prefixconnector}%
+ %
+ \setcounterparameter \c!numberseparatorset{#2\c!numberseparatorset}%
+ \setcounterparameter \c!numberconversion{#2\c!numberconversion}%
+ \setcounterparameter\c!numberconversionset{#2\c!numberconversionset}%
+ \setcounterparameter \c!numberstarter{#2\c!numberstarter}%
+ \setcounterparameter \c!numberstopper{#2\c!numberstopper}%
+ \setcounterparameter \c!numbersegments{#2\c!numbersegments}%
+ %
+ \the\everysetupcounter}
+
+\unexpanded\def\mult_interfaces_counter_association#1#2#3#4#5#6#7% tag current setup parameter list sync register
+ {\strc_counter_preset_using_parameter#3\rootcounterparameter
+ \newtoks#5%
+ \unexpanded\def #6{\ifx#2\empty\the#5\else\strc_counter_setup_using_parameter#2#4\fi}% sync
+ \unexpanded\def#7##1{\normalexpanded{#5{\the#5\strc_counter_setup_using_parameter{##1}\noexpand#4}}}} % register
+
+\unexpanded\def\installcounterassociation#1% => synchronize#1counters register#1counter
+ {\normalexpanded
+ {\mult_interfaces_counter_association
+ {#1}% not \??xx but xx
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname setup#1\endcsname
+ \expandafter\noexpand\csname #1parameter\endcsname
+ \expandafter\noexpand\csname counter_association_list_#1\endcsname
+ \expandafter\noexpand\csname synchronize#1counters\endcsname
+ \expandafter\noexpand\csname register#1counter\endcsname}}
+
+% needs testing:
+%
+% \unexpanded\def\strc_counter_setup_push#1#2#3% \someparameter \directsomeparameter \setexpandedsomeparameter
+% {\let\savedcounterparameter \counterparameter
+% \let\saveddirectcounterparameter \directcounterparameter
+% \let\savedsetexpandedcounterparameter\setexpandedcounterparameter
+% % remap
+% \let\counterparameter #1%
+% \let\directcounterparameter #2%
+% \let\setexpandedcounterparameter #3}
+%
+% \unexpanded\def\strc_counter_setup_pop
+% {\let\counterparameter \savedcounterparameter
+% \let\directcounterparameter \saveddirectcounterparameter
+% \let\setexpandedcounterparameter \savedsetexpandedcounterparameter}
+%
+% \unexpanded\def\mult_interfaces_counter_association#1#2#3#4#5#6#7% tag current setup parameter list sync register
+% {\strc_counter_preset_using_parameter#3\rootcounterparameter
+% \newtoks#5%
+% \unexpanded\def#6% sync
+% {\strc_counter_setup_push
+% \ifx#2\empty
+% \the#5%
+% \else
+% \let\currentcounter\empty
+% \the\everysetupcounter
+% \fi
+% \strc_counter_setup_pop}%
+% \unexpanded\def#7##1% register
+% {\normalexpanded{#5{\the#5\edef\noexpand\currentcounter{##1}\noexpand\the\everysetupcounter}}}}
+
+%D For good old times (easier to explain in manuals):
+%D
+%D \starttyping
+%D \setcounter[userpage][9]
+%D \setupcounter[userpage][number=9]
+%D \setupuserpagenumber[number=9]
+%D \stoptyping
+
+% needs testing: we might have conflicts with mixins
+%
+% \appendtoks
+% \ifx\currentcounter\empty \else
+% \edef\p_number{\counterparameter\c!number}%
+% \ifx\p_number\empty \else
+% \strc_counters_set\currentcounter\p_number
+% \letcounterparameter\c!number\empty
+% \fi
+% \fi
+% \to \everysetupcounter
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua
new file mode 100644
index 00000000000..96d26e6f666
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua
@@ -0,0 +1,401 @@
+if not modules then modules = { } end modules ['strc-pag'] = {
+ version = 1.001,
+ comment = "companion to strc-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+
+local trace_pages = false trackers.register("structures.pages", function(v) trace_pages = v end)
+
+local report_pages = logs.reporter("structure","pages")
+
+local structures = structures
+
+local helpers = structures.helpers
+local sections = structures.sections
+local pages = structures.pages
+local sets = structures.sets
+local counters = structures.counters
+
+local counterdata = counters.data
+
+local variables = interfaces.variables
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local processors = typesetters.processors
+local applyprocessor = processors.apply
+local startapplyprocessor = processors.startapply
+local stopapplyprocessor = processors.stopapply
+
+local texsetcount = tex.setcount
+local texgetcount = tex.getcount
+
+local ctx_convertnumber = context.convertnumber
+
+-- storage
+
+local collected, tobesaved = allocate(), allocate()
+
+pages.collected = collected
+pages.tobesaved = tobesaved
+pages.nofpages = 0
+
+local function initializer()
+ collected = pages.collected
+ tobesaved = pages.tobesaved
+ pages.nofpages = #collected
+end
+
+job.register('structures.pages.collected', tobesaved, initializer)
+
+local specification = { } -- to be checked
+
+function pages.save(prefixdata,numberdata,extradata)
+ local realpage = texgetcount("realpageno")
+ local userpage = texgetcount("userpageno")
+ if realpage > 0 then
+ if trace_pages then
+ report_pages("saving page %s.%s",realpage,userpage)
+ end
+ local viewerprefix = extradata.viewerprefix
+ local state = extradata.state
+ local data = {
+ number = userpage,
+ viewerprefix = viewerprefix ~= "" and viewerprefix or nil,
+ state = state ~= "" and state or nil, -- maybe let "start" be default
+ block = sections.currentblock(),
+ prefixdata = prefixdata and helpers.simplify(prefixdata),
+ numberdata = numberdata and helpers.simplify(numberdata),
+ }
+ tobesaved[realpage] = data
+ if not collected[realpage] then
+ collected[realpage] = data
+ end
+ elseif trace_pages then
+ report_pages("not saving page %s.%s",realpage,userpage)
+ end
+end
+
+-- We can set the pagenumber but as it only get incremented in the page
+-- builder we have to make sure it starts at least at 1.
+
+function counters.specials.userpage()
+ local r = texgetcount("realpageno")
+ if r > 0 then
+ local t = tobesaved[r]
+ if t then
+ t.number = texgetcount("userpageno")
+ if trace_pages then
+ report_pages("forcing pagenumber of realpage %s to %s",r,t.number)
+ end
+ return
+ end
+ end
+ local u = texgetcount("userpageno")
+ if u == 0 then
+ if trace_pages then
+ report_pages("forcing pagenumber of realpage %s to %s (probably a bug)",r,1)
+ end
+ counters.setvalue("userpage",1)
+ texsetcount("userpageno",1) -- not global ?
+ end
+end
+
+-- local f_convert = string.formatters["\\convertnumber{%s}{%s}"]
+--
+-- local function convertnumber(str,n)
+-- return f_convert(str or "numbers",n)
+-- end
+
+function pages.number(realdata,pagespec)
+ local userpage, block = realdata.number, 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 ""
+ local stopper = (pagespec and pagespec.stopper ~= "" and pagespec.stopper ) or (numberspec and numberspec.stopper ~= "" and numberspec.stopper ) or ""
+ if starter ~= "" then
+ applyprocessor(starter)
+ end
+ if conversion ~= "" then
+ ctx_convertnumber(conversion,userpage)
+ else
+ if conversionset == "" then conversionset = "default" end
+ local theconversion = sets.get("structure:conversions",block,conversionset,1,"numbers") -- to be checked: 1
+ local data = startapplyprocessor(theconversion)
+ ctx_convertnumber(data or "number",userpage)
+ stopapplyprocessor()
+ end
+ if stopper ~= "" then
+ applyprocessors(stopper)
+ end
+end
+
+-- (pagespec.prefix == yes|unset) and (pages.prefix == yes) => prefix
+
+function pages.analyze(entry,pagespecification)
+ -- safeguard
+ if not entry then
+ return false, false, "no entry"
+ end
+ local references = entry.references
+ if not references then
+ return false, false, "no references"
+ end
+ local pagedata = references.pagedata -- sometimes resolved (external)
+ if not pagedata then
+ local realpage = references.realpage
+ if realpage then
+ pagedata = collected[realpage]
+ else
+ return false, false, "no realpage"
+ end
+ end
+ if not pagedata then
+ return false, false, "no pagedata"
+ end
+ local sectiondata = references.sectiondata -- sometimes resolved (external)
+ if not sectiondata then
+ local section = references.section
+ if section then
+ sectiondata = sections.collected[section]
+ else
+ return pagedata, false, "no section"
+ end
+ end
+ if not sectiondata then
+ return pagedata, false, "no sectiondata"
+ end
+ local no = variables.no
+ -- local preferences
+ if pagespecification and pagespecification.prefix == no then
+ return pagedata, false, "current spec blocks prefix"
+ end
+ -- stored preferences
+ -- if entry.prefix == no then
+ -- return pagedata, false, "entry blocks prefix"
+ -- end
+ -- stored page state
+ pagespecification = pagedata.prefixdata
+ if pagespecification and pagespecification.prefix == no then
+ return pagedata, false, "pagedata blocks prefix"
+ end
+ -- final verdict
+ return pagedata, sectiondata, "okay"
+end
+
+function helpers.page(data,pagespec)
+ if data then
+ local pagedata = pages.analyze(data,pagespec)
+ if pagedata then
+ pages.number(pagedata,pagespec)
+ end
+ end
+end
+
+function helpers.prefixpage(data,prefixspec,pagespec)
+ if data then
+ local pagedata, prefixdata, e = pages.analyze(data,pagespec)
+ if pagedata then
+ if prefixdata then
+ sections.typesetnumber(prefixdata,"prefix",prefixspec or false,prefixdata or false,pagedata.prefixdata or false)
+ end
+ pages.number(pagedata,pagespec)
+ end
+ end
+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
+ helpers.prefixpage(data,prefixspec,pagespec)
+ r.section, r.realpage = ls, lr
+ end
+end
+
+--
+
+function helpers.analyze(entry,specification)
+ -- safeguard
+ if not entry then
+ return false, false, "no entry"
+ end
+ local yes, no = variables.yes, variables.no
+ -- section data
+ local references = entry.references
+ if not references then
+ return entry, false, "no references"
+ end
+ local section = references.section
+ if not section then
+ return entry, false, "no section"
+ end
+ local sectiondata = sections.collected[references.section]
+ if not sectiondata then
+ return entry, false, "no section data"
+ end
+ -- local preferences
+ if specification and specification.prefix == no then
+ return entry, false, "current spec blocks prefix"
+ end
+ -- stored preferences (not used)
+ local prefixdata = entry.prefixdata
+ if prefixdata and prefixdata.prefix == no then
+ return entry, false, "entry blocks prefix"
+ end
+ -- final verdict
+ return entry, sectiondata, "okay"
+end
+
+function helpers.prefix(data,prefixspec)
+ if data then
+ local _, prefixdata, status = helpers.analyze(data,prefixspec)
+ if prefixdata then
+ sections.typesetnumber(prefixdata,"prefix",prefixspec or false,data.prefixdata or false,prefixdata or false)
+ end
+ end
+end
+
+function pages.is_odd(n)
+ n = n or texgetcount("realpageno")
+ if texgetcount("pagenoshift") % 2 == 0 then
+ return n % 2 == 0
+ else
+ return n % 2 ~= 0
+ end
+end
+
+function pages.on_right(n)
+ local pagemode = texgetcount("pageduplexmode")
+ if pagemode == 2 or pagemode == 1 then
+ n = n or texgetcount("realpageno")
+ if texgetcount("pagenoshift") % 2 == 0 then
+ return n % 2 == 0
+ else
+ return n % 2 ~= 0
+ end
+ else
+ return true
+ end
+end
+
+function pages.in_body(n)
+ return texgetcount("pagebodymode") > 0
+end
+
+-- move to strc-pag.lua
+
+function counters.analyze(name,counterspecification)
+ local cd = counterdata[name]
+ -- safeguard
+ if not cd then
+ return false, false, "no counter data"
+ end
+ -- section data
+ local sectiondata = sections.current()
+ if not sectiondata then
+ return cd, false, "not in section"
+ end
+ local references = sectiondata.references
+ if not references then
+ return cd, false, "no references"
+ end
+ local section = references.section
+ if not section then
+ return cd, false, "no section"
+ end
+ sectiondata = sections.collected[references.section]
+ if not sectiondata then
+ return cd, false, "no section data"
+ end
+ -- local preferences
+ local no = variables.no
+ if counterspecification and counterspecification.prefix == no then
+ return cd, false, "current spec blocks prefix"
+ end
+ -- stored preferences (not used)
+ if cd.prefix == no then
+ return cd, false, "entry blocks prefix"
+ end
+ -- sectioning
+ -- if sectiondata.prefix == no then
+ -- return false, false, "sectiondata blocks prefix"
+ -- end
+ -- final verdict
+ return cd, sectiondata, "okay"
+end
+
+function sections.prefixedconverted(name,prefixspec,numberspec)
+ local cd, prefixdata, result = counters.analyze(name,prefixspec)
+ if cd then
+ if prefixdata then
+ sections.typesetnumber(prefixdata,"prefix",prefixspec or false,cd or false)
+ end
+ counters.converted(name,numberspec)
+ end
+end
+
+--
+
+implement {
+ name = "savepagedata",
+ actions = pages.save,
+ arguments = {
+ {
+ { "prefix" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ },
+ {
+ { "conversionset" },
+ { "conversion" },
+ { "starter" },
+ { "stopper" },
+ },
+ {
+ { "viewerprefix" },
+ { "state" },
+ }
+ }
+}
+
+implement { -- weird place
+ name = "prefixedconverted",
+ actions = sections.prefixedconverted,
+ arguments = {
+ "string",
+ {
+ { "prefix" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "starter" },
+ { "stopper" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ },
+ {
+ { "order" },
+ { "separatorset" },
+ { "conversionset" },
+ { "conversion" },
+ { "starter" },
+ { "stopper" },
+ { "segments" },
+ { "type" },
+ { "criterium" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv
new file mode 100644
index 00000000000..0a55fb45f33
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv
@@ -0,0 +1,492 @@
+%D \module
+%D [ file=strc-pag,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Pagenumbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Pagenumbering}
+
+\registerctxluafile{strc-pag}{1.001}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+% Allocation:
+
+\countdef\realpageno \zerocount \realpageno \plusone
+\countdef\userpageno \plusone \userpageno \plusone
+\countdef\subpageno \plustwo \subpageno \zerocount % !
+\countdef\arrangeno \plusthree \arrangeno \zerocount % !
+\countdef\pagenoshift\plusfour \pagenoshift\zerocount % !
+\countdef\lastpageno \plusfive \lastpageno \zerocount % !
+
+\let\pageno\userpageno
+
+\def\realfolio{\the\realpageno}
+\def\userfolio{\the\userpageno}
+\def\subfolio {\the\subpageno }
+\def\lastfolio{\the\lastpageno}
+
+\newtoks\everyinitializepagecounters
+
+\unexpanded\def\initializepagecounters
+ {\the\everyinitializepagecounters}
+
+\appendtoks
+ \initializepagecounters
+\to \everyjob
+
+% Page numbers are kind of independent of each other and therefore they
+% all get their own counter. After all, it's easier to combine them in
+% a pseudo counterset than to deal with a complex set itself.
+
+% \defineprefixset [mine][section-1,section-2]
+% \defineseparatorset[mine][:]
+%
+% \setupuserpagenumber
+% [way=bypart,
+% prefix=yes,
+% prefixset=mine,
+% prefixseparatorset=mine]
+
+% \defineconversionset[frontpart:pagenumber][][romannumerals]
+% \defineconversionset[bodypart:pagenumber] [][numbers]
+%
+% \setupuserpagenumber[way=byblock]
+% \setupuserpagenumber[way=bychapter]
+% \setupuserpagenumber[numberconversionset=pagenumber]
+%
+% \starttext
+% \startfrontmatter
+% \completecontent[criterium=all]
+% \chapter{tufte} \section{one} \input tufte \page \section{two} \input tufte \page
+% \chapter{tufte} \section{one} \input tufte \page \section{two} \input tufte \page
+% \stopfrontmatter
+% \startbodymatter
+% \chapter{knuth} \section{one} \input knuth \page \section{two} \input knuth \page \section{three} \input knuth \page
+% \chapter{knuth} \section{one} \input knuth \page \section{two} \input knuth \page \section{three} \input knuth \page
+% \stopbodymatter
+% \stoptext
+
+\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
+\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
+\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page]
+
+\newtoks\everysetuprealpagenumber % todo: set state: none, start, stop, reset
+\newtoks\everysetupuserpagenumber % todo: set state: none, start, stop, reset
+\newtoks\everysetupsubpagenumber % todo: set state: none, start, stop, reset
+
+\unexpanded\def\setuprealpagenumber{\dosingleargument\strc_pagenumbers_setup_realpage}
+\unexpanded\def\setupuserpagenumber{\dosingleargument\strc_pagenumbers_setup_userpage}
+\unexpanded\def\setupsubpagenumber {\dosingleargument\strc_pagenumbers_setup_subpage }
+
+\let\m_strc_pagenumbers_state_old\zerocount
+\let\m_strc_pagenumbers_state_new\zerocount
+
+\def\strc_pagenumbers_save_state#1{\edef\m_strc_pagenumbers_state_old{\namedcounterparameter#1\c!state}}
+
+\def\strc_pagenumbers_setup_realpage[#1]{\strc_pagenumbers_save_state\s!realpage\setupcounter[\s!realpage][#1]\the\everysetuprealpagenumber}
+\def\strc_pagenumbers_setup_userpage[#1]{\strc_pagenumbers_save_state\s!userpage\setupcounter[\s!userpage][#1]\the\everysetupuserpagenumber}
+\def\strc_pagenumbers_setup_subpage [#1]{\strc_pagenumbers_save_state\s!subpage \setupcounter[\s!subpage ][#1]\the\everysetupsubpagenumber }
+
+\unexpanded\def\resetrealpagenumber {} % not permitted
+\unexpanded\def\resetuserpagenumber {\strc_counters_reset\s!userpage}
+\unexpanded\def\resetsubpagenumber {\strc_counters_reset\s!subpage}
+
+\appendtoks
+ \strc_counters_set\s!realpage\realpageno
+ \strc_counters_set\s!userpage\userpageno
+ \strc_counters_set\s!subpage \subpageno
+ \lastpageno\lastcountervalue[\s!realpage]\relax
+\to \everyinitializepagecounters
+
+\let\setuppagenumber\setupuserpagenumber
+\let\resetpagenumber\resetuserpagenumber
+
+% invisible =
+
+\def\strc_pagenumbers_page_state_save % \normalexpanded?
+ {\clf_savepagedata
+ {
+ prefix {\namedcounterparameter\s!userpage\c!prefix}
+ separatorset {\namedcounterparameter\s!userpage\c!prefixseparatorset}
+ conversion {\namedcounterparameter\s!userpage\c!prefixconversion}
+ conversionset {\namedcounterparameter\s!userpage\c!prefixconversionset}
+ set {\namedcounterparameter\s!userpage\c!prefixset}
+ segments {\namedcounterparameter\s!userpage\c!prefixsegments}
+ connector {\namedcounterparameter\s!userpage\c!prefixconnector}
+ }{
+ conversion {\namedcounterparameter\s!userpage\c!numberconversion}
+ conversionset {\namedcounterparameter\s!userpage\c!numberconversionset}
+ starter {\namedcounterparameter\s!userpage\c!numberstarter}
+ stopper {\namedcounterparameter\s!userpage\c!numberstopper}
+ }{
+ viewerprefix {\namedcounterparameter\s!userpage\c!viewerprefix}
+ state {\namedcounterparameter\s!userpage\c!state}
+ }%
+ \relax}
+
+\prependtoks
+ \strc_pagenumbers_page_state_save
+\to \everyshipout
+
+\installcorenamespace{pagestatestack} % no level yet
+
+\unexpanded\def\strc_pagenumbers_page_state_push{\setxvalue{\??pagestatestack\c!state}{\namedcounterparameter\s!userpage\c!state}}
+\unexpanded\def\strc_pagenumbers_page_state_pop {\normalexpanded{\setuppagenumber[\c!state=\getvalue{\??pagestatestack\c!state}]}}
+
+\setuppagenumber
+ [\c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixset=\v!part,
+ \c!prefixconnector=\endash,
+ \c!state=\v!start]
+
+\setupsubpagenumber
+ [\c!way=\v!by\v!part,
+ \c!state=\v!stop]
+
+% Counters
+
+\def\firstrealpagenumber{\convertedcounter[\s!realpage][\c!type=\v!first]}
+\def\firstuserpagenumber{\convertedcounter[\s!userpage][\c!type=\v!first]}
+\def\firstsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!first]}
+
+\def\lastrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!last]}
+\def\lastuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!last]}
+\def\lastsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!last]}
+
+\def\prevrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!previous]}
+\def\prevuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!previous]}
+\def\prevsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!previous]}
+
+\def\nextrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!next]}
+\def\nextuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!next]}
+\def\nextsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!next]}
+
+\def\firstrealpage{\strc_counters_first\s!realpage}
+\def\firstuserpage{\strc_counters_first\s!userpage}
+\def\firstsubpage {\strc_counters_first\s!subpage }
+
+\def\prevrealpage {\strc_counters_prev \s!realpage}
+\def\prevuserpage {\strc_counters_prev \s!userpage}
+\def\prevsubpage {\strc_counters_prev \s!subpage }
+
+\def\nextrealpage {\strc_counters_next \s!realpage}
+\def\nextuserpage {\strc_counters_next \s!userpage}
+\def\nextsubpage {\strc_counters_next \s!subpage }
+
+\def\lastrealpage {\strc_counters_last \s!realpage}
+\def\lastuserpage {\strc_counters_last \s!userpage}
+\def\lastsubpage {\strc_counters_last \s!subpage }
+
+\let\firstpage\firstrealpage
+\let\prevpage \prevrealpage
+\let\nextpage \nextrealpage
+\let\lastpage \lastrealpage
+
+% Compatibility counters:
+
+\def\nofrealpages {\lastrealpage} \def\totalnumberofpages{\lastrealpage}
+\def\nofuserpages {\lastuserpage} \def\lastpagenumber {\lastuserpage}
+\def\nofsubpages {\lastsubpage }
+
+% Renderers:
+
+\def\pagenumber {\strc_counters_raw\s!userpage}
+\def\prefixedpagenumber {\directconvertedcounter\s!userpage\empty} % \userpagenumber
+
+\def\realpagenumber {\directconvertedcounter\s!realpage\empty}
+\def\userpagenumber {\directconvertedcounter\s!userpage\empty}
+\def\subpagenumber {\directconvertedcounter\s!subpage \empty}
+
+\def\firstrealpagenumber{\directconvertedcounter\s!realpage\v!first}
+\def\firstuserpagenumber{\directconvertedcounter\s!userpage\v!first}
+\def\firstsubpagenumber {\directconvertedcounter\s!subpage \v!first}
+
+\def\lastrealpagenumber {\directconvertedcounter\s!realpage\v!last}
+\def\lastuserpagenumber {\directconvertedcounter\s!userpage\v!last}
+\def\lastsubpagenumber {\directconvertedcounter\s!subpage \v!last}
+
+\def\prevrealpagenumber {\directconvertedcounter\s!realpage\v!previous}
+\def\prevuserpagenumber {\directconvertedcounter\s!userpage\v!previous}
+\def\prevsubpagenumber {\directconvertedcounter\s!subpage \v!previous}
+
+\def\nextrealpagenumber {\directconvertedcounter\s!realpage\v!next}
+\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next}
+\def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next}
+
+\unexpanded\def\strc_pagenumbers_decrement_counters % only at the end
+ {\strc_counters_decrement\s!realpage
+ \strc_counters_decrement\s!userpage
+ \strc_counters_decrement\s!subpage}
+
+\unexpanded\def\strc_pagenumbers_increment_counters
+ {\incrementpagenumber
+ \incrementsubpagenumber}
+
+\appendtoks
+ \strc_pagenumbers_decrement_counters
+\to \everygoodbye
+
+\newcount\c_strc_subpage_first_real \c_strc_subpage_first_real\plusone
+
+\appendtoks
+ \ifcase\subpageno\relax
+ \global\c_strc_subpage_first_real\realpageno
+ \or
+ \global\c_strc_subpage_first_real\realpageno
+ \fi
+\to \everybeforepagebody
+
+\def\therealsubpageno#1% new helper
+ {\the\numexpr\c_strc_subpage_first_real+#1+\minusone\relax}
+
+% Equivalents (compatibility):
+%
+% todo: maybe leave lastpage etc lua calls
+
+\def\realpage{\the\realpageno}
+\def\userpage{\the\userpageno}
+\def\subpage {\the\subpageno}
+
+% Hooks:
+
+\def\currentpage{\the\realpageno}% rather useless
+
+\appendtoks
+ \ifnum\realpageno>\lastpage \globallet\lastpage\lastrealpage \fi
+\to \everyinitializepagecounters
+
+% States:
+
+\newif\ifdoublesided \newconditional\layoutisdoublesided
+\newif\ifsinglesided \newconditional\layoutissinglesided
+
+% Realpage and subpage numbers:
+
+\unexpanded\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax}
+\unexpanded\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax}
+
+% Page numbers: (can move to lua) ... inconsistent names
+
+\installcorenamespace{pagenumberinc}
+\installcorenamespace{pagenumberdec}
+
+\unexpanded\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax}
+\unexpanded\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax}
+
+\unexpanded\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax}
+\unexpanded\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax}
+
+\unexpanded\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible
+
+\unexpanded\def\decrementpagenumber{\csname\??pagenumberdec\namedcounterparameter\s!userpage\c!state\endcsname}
+\unexpanded\def\incrementpagenumber{\csname\??pagenumberinc\namedcounterparameter\s!userpage\c!state\endcsname}
+
+\letvalue{\??pagenumberdec\v!start}\strc_pagenumbers_decrement_userpage
+\letvalue{\??pagenumberdec\v!none }\strc_pagenumbers_decrement_userpage
+\letvalue{\??pagenumberdec\v!empty}\strc_pagenumbers_decrement_userpage
+
+\letvalue{\??pagenumberinc\v!start}\strc_pagenumbers_increment_userpage
+\letvalue{\??pagenumberinc\v!none }\strc_pagenumbers_increment_userpage
+\setvalue{\??pagenumberinc\v!empty}{\strc_pagenumbers_increment_userpage\strc_pagenumbers_synchronize_userpage}
+\letvalue{\??pagenumberinc\v!keep }\strc_pagenumbers_synchronize_userpage
+
+% Setup general page numbering
+
+\installcorenamespace{pagenumbering}
+
+\installdirectcommandhandler \??pagenumbering {pagenumbering}
+
+\appendtoks
+ \singlesidedfalse \setfalse\layoutisdoublesided
+ \doublesidedfalse \setfalse\layoutissinglesided
+ \processallactionsinset[\directpagenumberingparameter\c!alternative]
+ [ \v!singlesided=>\singlesidedtrue\settrue\layoutissinglesided,
+ \v!doublesided=>\doublesidedtrue\settrue\layoutisdoublesided]%
+ \ifdefined\trackingmarginnotestrue
+ \ifdoublesided
+ \trackingmarginnotestrue
+ \else
+ \trackingmarginnotesfalse
+ \fi
+ \fi
+ \pageduplexmode
+ \ifsinglesided
+ \ifdoublesided\plustwo\else\zerocount\fi
+ \else
+ \ifdoublesided\plusone\else\zerocount\fi
+ \fi
+ \page_backgrounds_recalculate
+ \strc_pagenumbers_set_location
+\to \everysetuppagenumbering
+
+\ifdefined \page_backgrounds_recalculate \else
+ \let\page_backgrounds_recalculate\relax
+\fi
+
+\ifdefined \strc_pagenumbers_set_location \else
+ \let\strc_pagenumbers_set_location\relax
+\fi
+
+\unexpanded\def\strc_pagenumbers_flush_final_page
+ {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}%
+ \ifx\p_strc_pagenumbers_page\empty \else
+ \ifx\p_strc_pagenumbers_page\v!no \else
+ \page[\p_strc_pagenumbers_page]%
+ \fi
+ \fi}
+
+% The numbered location handler is there because we need to be downward
+% compatible. So, in fact there can be multiple handlers active at the
+% same time, but only the current one does something.
+
+% Rendering:
+
+\unexpanded\def\strc_pagenumbers_place_location
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
+ \doif{\directpagenumberingparameter\c!strut}\v!yes\strut
+ \begingroup
+ \usepagenumberingstyleandcolor\c!style\c!color
+ \directpagenumberingparameter\c!command
+ {\directpagenumberingparameter\c!left
+ \labeltexts\v!pagenumber\prefixedpagenumber
+ \directpagenumberingparameter\c!right}%
+ \endgroup
+ \fi
+ \fi}
+
+\unexpanded\def\completepagenumber
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
+ \directpagenumberingparameter\c!left
+ \labeltexts\v!pagenumber\prefixedpagenumber
+ \directpagenumberingparameter\c!right
+ \fi
+ \fi}
+
+\unexpanded\def\placepagenumber
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
+ \labeltexts\v!pagenumber\pagenumber
+ \fi
+ \fi}
+
+\unexpanded\def\referencepagenumber[#1]%
+ {\doifelsenothing{#1}{?}{}}
+
+% The numbered location handler is there because we need to be downward
+% compatible. So, in fact there can be multiple handlers active at the
+% same time, but only the current one does something.
+
+\setnewconstant\c_strc_pagenumbers_state_realpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state_userpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state_subpage \plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state \plusone % general number: 0=invisible, 1=visible
+
+\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}%
+ \fi}
+
+\appendtoks % todo: set state: none, start, stop, reset
+ \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage
+\to \everysetuprealpagenumber
+
+\appendtoks % todo: set state: none, start, stop, reset
+ \strc_pagenumbers_check_state_change\s!userpage\c_strc_pagenumbers_state_userpage
+\to \everysetupuserpagenumber
+
+\appendtoks % todo: set state: none, start, stop, reset
+ \strc_pagenumbers_check_state_change\s!subpage\c_strc_pagenumbers_state_subpage
+\to \everysetupsubpagenumber
+
+\appendtoks % todo: set state: none, start, stop, reset
+ \doifelse{\directpagenumberingparameter\c!state}\v!start
+ {\c_strc_pagenumbers_state\plusone }%
+ {\c_strc_pagenumbers_state\zerocount}%
+\to \everysetuppagenumbering
+
+% Done
+
+% \c!way=\v!by\v!part
+% \c!text=
+% \v!chapter\v!number=\v!no
+% \v!part\v!number=\v!yes
+% \c!numberseparator=--
+% \c!conversion=\v!numbers
+
+\setuppagenumbering
+ [\c!alternative=\v!singlesided,
+ \c!location={\v!header,\v!middle},
+ \c!width=, % in geval van \v!marginedge
+ \c!left=,
+ \c!right=,
+ \c!page=\v!last,
+ \c!textseparator=\tfskip,
+ \c!state=\v!start,
+ \c!command=,
+ \c!strut=\v!yes,
+ \c!style=, % empty, otherwise conflict
+ \c!color=]
+
+% just for downward compatbility
+
+\appendtoks
+ \edef\askeduserpagenumber{\namedcounterparameter\s!userpage\c!number}%
+ \ifx\askeduserpagenumber\empty \else
+ \normalexpanded{\setuppagenumber[\c!start=\askeduserpagenumber,\c!number=]}%
+ \userpageno\strc_counters_raw\s!userpage
+ \fi
+\to \everysetupuserpagenumber % todo: set state: none, start, stop, reset
+
+\appendtoks
+ \edef\askedsubpagenumber{\namedcounterparameter\s!subpage\c!number}%
+ \ifx\askedsubpagenumber\empty \else
+ \normalexpanded{\setupsubpagenumber[\c!start=\askedsubpagenumber,\c!number=]}%
+ \subpageno\strc_counters_raw\s!subpage\relax
+ \fi
+\to \everysetupsubpagenumber % todo: set state: none, start, stop, reset
+
+% \setuplayout[width=300pt,backspace=4cm]
+% \setuppagenumbering [alternative=doublesided]
+% \setupuserpagenumber[start=2]
+% \starttext \dorecurse{20}{\input knuth \par} \stoptext
+
+\unexpanded\def\strc_pagenumbers_check_change_shift
+ {\userpageno\strc_counters_raw\s!userpage\relax
+ \ifnum\realpageno=\plusone
+ \ifodd\userpageno
+ \else
+ \global\pagenoshift\plusone
+ \fi
+ \fi}
+
+\appendtoks % todo: set state: none, start, stop, reset
+ % this makes starting at an even page possible
+ \strc_pagenumbers_check_change_shift
+\to \everysetupuserpagenumber
+
+\appendtoks % todo: set state: none, start, stop, reset
+ % this makes starting at an even page possible
+ \strc_pagenumbers_check_change_shift
+\to \everysetuppagenumbering
+
+\initializepagecounters
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua
new file mode 100644
index 00000000000..c3b852e8917
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua
@@ -0,0 +1,2795 @@
+if not modules then modules = { } end modules ['strc-ref'] = {
+ version = 1.001,
+ comment = "companion to strc-ref.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware, this is a first step in the rewrite (just getting rid of
+-- the tuo file); later all access and parsing will also move to lua
+
+-- the useddata and pagedata names might change
+-- todo: pack exported data
+
+-- todo: autoload components when :::
+
+local format, find, gmatch, match, strip = string.format, string.find, string.gmatch, string.match, string.strip
+local floor = math.floor
+local rawget, tonumber, type = rawget, tonumber, type
+local lpegmatch = lpeg.match
+local insert, remove, copytable = table.insert, table.remove, table.copy
+local formatters = string.formatters
+
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+local setmetatableindex = table.setmetatableindex
+
+local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end)
+local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end)
+local trace_identifying = false trackers.register("structures.referencing.identifying", function(v) trace_identifying = v end)
+local trace_importing = false trackers.register("structures.referencing.importing", function(v) trace_importing = v end)
+local trace_empty = false trackers.register("structures.referencing.empty", function(v) trace_empty = v end)
+
+local check_duplicates = true
+
+directives.register("structures.referencing.checkduplicates", function(v)
+ check_duplicates = v
+end)
+
+local report_references = logs.reporter("references")
+local report_unknown = logs.reporter("references","unknown")
+local report_identifying = logs.reporter("references","identifying")
+local report_importing = logs.reporter("references","importing")
+local report_empty = logs.reporter("references","empty")
+
+local variables = interfaces.variables
+local v_default = variables.default
+local v_url = variables.url
+local v_file = variables.file
+local v_unknown = variables.unknown
+local v_page = variables.page
+local v_auto = variables.auto
+local v_yes = variables.yes
+local v_name = variables.name
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+local texconditionals = tex.conditionals
+
+local productcomponent = resolvers.jobs.productcomponent
+local justacomponent = resolvers.jobs.justacomponent
+
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+
+local settings_to_array = utilities.parsers.settings_to_array
+local process_settings = utilities.parsers.process_stripped_settings
+local unsetvalue = attributes.unsetvalue
+
+local structures = structures
+local helpers = structures.helpers
+local sections = structures.sections
+local references = structures.references
+local lists = structures.lists
+local counters = structures.counters
+
+local jobpositions = job.positions
+
+-- some might become local
+
+references.defined = references.defined or allocate()
+
+local defined = references.defined
+local derived = allocate()
+local specials = allocate()
+local functions = allocate()
+local runners = allocate()
+local internals = allocate()
+local filters = allocate()
+local executers = allocate()
+local handlers = allocate()
+local tobesaved = allocate()
+local collected = allocate()
+local tobereferred = allocate()
+local referred = allocate()
+local usedinternals = allocate()
+local flaginternals = allocate()
+local usedviews = allocate()
+
+references.derived = derived
+references.specials = specials
+references.functions = functions
+references.runners = runners
+references.internals = internals
+references.filters = filters
+references.executers = executers
+references.handlers = handlers
+references.tobesaved = tobesaved
+references.collected = collected
+references.tobereferred = tobereferred
+references.referred = referred
+references.usedinternals = usedinternals
+references.flaginternals = flaginternals
+references.usedviews = usedviews
+
+local splitreference = references.splitreference
+local splitprefix = references.splitcomponent -- replaces: references.splitprefix
+local prefixsplitter = references.prefixsplitter
+local componentsplitter = references.componentsplitter
+
+local currentreference = nil
+
+local txtcatcodes = catcodes.numbers.txtcatcodes -- or just use "txtcatcodes"
+local context_delayed = context.delayed
+
+local ctx_pushcatcodes = context.pushcatcodes
+local ctx_popcatcodes = context.popcatcodes
+local ctx_dofinishreference = context.dofinishreference
+local ctx_dofromurldescription = context.dofromurldescription
+local ctx_dofromurlliteral = context.dofromurlliteral
+local ctx_dofromfiledescription = context.dofromfiledescription
+local ctx_dofromfileliteral = context.dofromfileliteral
+local ctx_expandreferenceoperation = context.expandreferenceoperation
+local ctx_expandreferencearguments = context.expandreferencearguments
+local ctx_getreferencestructureprefix = context.getreferencestructureprefix
+local ctx_convertnumber = context.convertnumber
+local ctx_emptyreference = context.emptyreference
+
+storage.register("structures/references/defined", references.defined, "structures.references.defined")
+
+local initializers = { }
+local finalizers = { }
+
+function references.registerinitializer(func) -- we could use a token register instead
+ initializers[#initializers+1] = func
+end
+
+function references.registerfinalizer(func) -- we could use a token register instead
+ finalizers[#finalizers+1] = func
+end
+
+local function initializer() -- can we use a tobesaved as metatable for collected?
+ tobesaved = references.tobesaved
+ collected = references.collected
+ for i=1,#initializers do
+ initializers[i](tobesaved,collected)
+ end
+ for prefix, list in next, collected do
+ for tag, data in next, list do
+ local r = data.references
+ local i = r.internal
+ if i then
+ internals[i] = data
+ usedinternals[i] = r.used
+ end
+ end
+ end
+end
+
+local function finalizer()
+ for i=1,#finalizers do
+ finalizers[i](tobesaved)
+ end
+ for prefix, list in next, tobesaved do
+ for tag, data in next, list do
+ local r = data.references
+ local i = r.internal
+ local f = flaginternals[i]
+ if f then
+ r.used = usedviews[i] or true
+ end
+ end
+ end
+end
+
+job.register('structures.references.collected', tobesaved, initializer, finalizer)
+
+local maxreferred = 1
+local nofreferred = 0
+
+local function initializer() -- can we use a tobesaved as metatable for collected?
+ tobereferred = references.tobereferred
+ referred = references.referred
+ nofreferred = #referred
+end
+
+-- no longer done this way
+
+-- references.resolvers = references.resolvers or { }
+-- local resolvers = references.resolvers
+--
+-- function resolvers.section(var)
+-- local vi = lists.collected[var.i[2]]
+-- if vi then
+-- var.i = vi
+-- var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1
+-- else
+-- var.i = nil
+-- var.r = 1
+-- end
+-- end
+--
+-- resolvers.float = resolvers.section
+-- resolvers.description = resolvers.section
+-- resolvers.formula = resolvers.section
+-- resolvers.note = resolvers.section
+--
+-- function resolvers.reference(var)
+-- local vi = var.i[2]
+-- if vi then
+-- var.i = vi
+-- var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1
+-- else
+-- var.i = nil
+-- var.r = 1
+-- end
+-- end
+
+-- We make the array sparse (maybe a finalizer should optionally return a table) because
+-- there can be quite some page links involved. We only store one action number per page
+-- which is normally good enough for what we want (e.g. see above/below) and we do
+-- a combination of a binary search and traverse backwards. A previous implementation
+-- always did a traverse and was pretty slow on a large number of links (given that this
+-- methods was used). It took me about a day to locate this as a bottleneck in processing
+-- a 2500 page interactive document with 60 links per page. In that case, traversing
+-- thousands of slots per link then brings processing to a grinding halt (especially when
+-- there are no slots at all, which is the case in a first run).
+
+local sparsetobereferred = { }
+
+local function finalizer()
+ local lastr, lasti
+ local n = 0
+ for i=1,maxreferred do
+ local r = tobereferred[i]
+ if not lastr then
+ lastr = r
+ lasti = i
+ elseif r ~= lastr then
+ n = n + 1
+ sparsetobereferred[n] = { lastr, lasti }
+ lastr = r
+ lasti = i
+ end
+ end
+ if lastr then
+ n = n + 1
+ sparsetobereferred[n] = { lastr, lasti }
+ end
+end
+
+job.register('structures.references.referred', sparsetobereferred, initializer, finalizer)
+
+local function referredpage(n)
+ local max = nofreferred
+ if max > 0 then
+ -- find match
+ local min = 1
+ while true do
+ local mid = floor((min+max)/2)
+ local r = referred[mid]
+ local m = r[2]
+ if n == m then
+ return r[1]
+ elseif n > m then
+ min = mid + 1
+ else
+ max = mid - 1
+ end
+ if min > max then
+ break
+ end
+ end
+ -- find first previous
+ for i=min,1,-1 do
+ local r = referred[i]
+ if r and r[2] < n then
+ return r[1]
+ end
+ end
+ end
+ -- fallback
+ return texgetcount("realpageno")
+end
+
+references.referredpage = referredpage
+
+function references.registerpage(n) -- called in the backend code
+ if not tobereferred[n] then
+ if n > maxreferred then
+ maxreferred = n
+ end
+ tobereferred[n] = texgetcount("realpageno")
+ end
+end
+
+-- todo: delay split till later as in destinations we split anyway
+
+local orders, lastorder = { }, 0
+
+local function setnextorder(kind,name)
+ lastorder = 0
+ if kind and name then
+ local ok = orders[kind]
+ if not ok then
+ ok = { }
+ orders[kind] = ok
+ end
+ lastorder = (ok[name] or 0) + 1
+ ok[name] = lastorder
+ end
+ texsetcount("global","locationorder",lastorder)
+end
+
+
+local function setnextinternal(kind,name)
+ setnextorder(kind,name) -- always incremented with internal
+ local n = texgetcount("locationcount") + 1
+ texsetcount("global","locationcount",n)
+ return n
+end
+
+local function currentorder(kind,name)
+ return orders[kind] and orders[kind][name] or lastorder
+end
+
+local function setcomponent(data)
+ -- we might consider doing this at the tex end, just like prefix
+ local component = productcomponent()
+ if component then
+ local references = data and data.references
+ if references then
+ references.component = component
+ if references.prefix == component then
+ references.prefix = nil
+ end
+ end
+ return component
+ end
+ -- but for the moment we do it here (experiment)
+end
+
+references.setnextorder = setnextorder
+references.setnextinternal = setnextinternal
+references.currentorder = currentorder
+references.setcomponent = setcomponent
+
+implement {
+ name = "setnextreferenceorder",
+ actions = setnextorder,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setnextinternalreference",
+ actions = setnextinternal,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "currentreferenceorder",
+ actions = { currentorder, context },
+ arguments = { "string", "string" }
+}
+
+function references.set(data)
+ local references = data.references
+ local reference = references.reference
+ if not reference or reference == "" then
+ -- report_references("invalid reference") -- harmless
+ return 0
+ end
+ local prefix = references.prefix or ""
+ local pd = tobesaved[prefix] -- nicer is a metatable
+ if not pd then
+ pd = { }
+ tobesaved[prefix] = pd
+ end
+ local n = 0
+ local function action(ref)
+ 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)
+ end
+ else
+ n = n + 1
+ pd[ref] = data
+ local r = data.references
+ ctx_dofinishreference(prefix or "",ref or "",r and r.internal or 0)
+ end
+ end
+ process_settings(reference,action)
+ return n > 0
+end
+
+-- function references.enhance(prefix,tag)
+-- local l = tobesaved[prefix][tag]
+-- if l then
+-- l.references.realpage = texgetcount("realpageno")
+-- 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
+ reference.x, reference.y = getpos()
+ end
+end
+
+references.synchronizepage = synchronizepage
+
+function references.enhance(prefix,tag)
+ local l = tobesaved[prefix][tag]
+ if l then
+ synchronizepage(l.references)
+ end
+end
+
+implement {
+ name = "enhancereference",
+ actions = references.enhance,
+ arguments = { "string", "string" }
+}
+
+-- -- -- related to strc-ini.lua -- -- --
+
+-- no metatable here .. better be sparse
+
+local function register_from_lists(collected,derived,pages,sections)
+ local derived_g = derived[""] -- global
+ local derived_p = nil
+ local derived_c = nil
+ local prefix = nil
+ local component = nil
+ local entry = nil
+ if not derived_g then
+ derived_g = { }
+ derived[""] = derived_g
+ end
+ local function action(s)
+ if trace_referencing then
+ report_references("list entry %a provides %a reference %a on realpage %a",i,kind,s,realpage)
+ end
+ if derived_p and not derived_p[s] then
+ derived_p[s] = entry
+ end
+ if derived_c and not derived_c[s] then
+ derived_c[s] = entry
+ end
+ if not derived_g[s] then
+ derived_g[s] = entry -- first wins
+ end
+ end
+ for i=1,#collected do
+ entry = collected[i]
+ local metadata = entry.metadata
+ if metadata then
+ local kind = metadata.kind -- why this check
+ if kind then
+ local references = entry.references
+ if references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local realpage = references.realpage
+ if realpage then
+ prefix = references.prefix
+ component = references.component
+ if prefix and prefix ~= "" then
+ derived_p = derived[prefix]
+ if not derived_p then
+ derived_p = { }
+ derived[prefix] = derived_p
+ end
+ end
+ if component and component ~= "" and component ~= prefix then
+ derived_c = derived[component]
+ if not derived_c then
+ derived_c = { }
+ derived[component] = derived_c
+ end
+ end
+ process_settings(reference,action)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+references.registerinitializer(function() register_from_lists(lists.collected,derived) end)
+
+-- tracing
+
+local function collectbypage(tracedpages)
+ -- lists
+ do
+ local collected = structures.lists.collected
+ local data = nil
+ local function action(reference)
+ local prefix = data.prefix
+ local component = data.component
+ local realpage = data.realpage
+ if realpage then
+ local pagelist = rawget(tracedpages,realpage)
+ local internal = data.internal or 0
+ local prefix = (prefix ~= "" and prefix) or (component ~= "" and component) or ""
+ local pagedata = { prefix, reference, internal }
+ if pagelist then
+ pagelist[#pagelist+1] = pagedata
+ else
+ tracedpages[realpage] = { pagedata }
+ end
+ if internal > 0 then
+ data.usedprefix = prefix
+ end
+ end
+ end
+ for i=1,#collected do
+ local entry = collected[i]
+ local metadata = entry.metadata
+ if metadata and metadata.kind then
+ data = entry.references
+ if data then
+ local reference = data.reference
+ if reference and reference ~= "" then
+ process_settings(reference,action)
+ end
+ end
+ end
+ end
+ end
+ -- references
+ do
+ for prefix, list in next, collected do
+ for reference, entry in next, list do
+ local data = entry.references
+ if data then
+ local realpage = data.realpage
+ local internal = data.internal or 0
+ local pagelist = rawget(tracedpages,realpage)
+ local pagedata = { prefix, reference, internal }
+ if pagelist then
+ pagelist[#pagelist+1] = pagedata
+ else
+ tracedpages[realpage] = { pagedata }
+ end
+ if internal > 0 then
+ data.usedprefix = prefix
+ end
+ end
+ end
+ end
+ end
+end
+
+references.tracedpages = table.setmetatableindex(allocate(),function(t,k)
+ if collectbypage then
+ collectbypage(t)
+ collectbypage = nil
+ end
+ return rawget(t,k)
+end)
+
+-- urls
+
+local urls = references.urls or { }
+references.urls = urls
+local urldata = urls.data or { }
+urls.data = urldata
+
+function urls.define(name,url,file,description)
+ if name and name ~= "" then
+ urldata[name] = { url or "", file or "", description or url or file or ""}
+ end
+end
+
+function urls.get(name)
+ local u = urldata[name]
+ if u then
+ local url, file = u[1], u[2]
+ if file and file ~= "" then
+ return formatters["%s/%s"](url,file)
+ else
+ return url
+ end
+ end
+end
+
+function urls.found(name)
+ return urldata[name]
+end
+
+local function geturl(name)
+ local url = urls.get(name)
+ if url and url ~= "" then
+ ctx_pushcatcodes(txtcatcodes)
+ context(url)
+ ctx_popcatcodes()
+ end
+end
+
+implement {
+ name = "doifelseurldefined",
+ actions = { urls.found, commands.doifelse },
+ arguments = "string"
+}
+
+implement {
+ name = "useurl",
+ actions = urls.define,
+ arguments = { "string", "string", "string", "string" }
+}
+
+implement {
+ name = "geturl",
+ actions = geturl,
+ arguments = "string",
+}
+
+-- files
+
+local files = references.files or { }
+references.files = files
+local filedata = files.data or { }
+files.data = filedata
+
+function files.define(name,file,description)
+ if name and name ~= "" then
+ filedata[name] = { file or "", description or file or "" }
+ end
+end
+
+function files.get(name,method,space) -- method: none, before, after, both, space: yes/no
+ local f = filedata[name]
+ if f then
+ context(f[1])
+ end
+end
+
+function files.found(name)
+ return filedata[name]
+end
+
+local function getfile(name)
+ local fil = files.get(name)
+ if fil and fil ~= "" then
+ ctx_pushcatcodes(txtcatcodes)
+ context(fil)
+ ctx_popcatcodes()
+ end
+end
+
+implement {
+ name = "doifelsefiledefined",
+ actions = { files.found, commands.doifelse },
+ arguments = "string"
+}
+
+implement {
+ name = "usefile",
+ actions = files.define,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "getfile",
+ actions = getfile,
+ arguments = "string"
+}
+
+-- helpers
+
+function references.checkedfile(whatever) -- return whatever if not resolved
+ if whatever then
+ local w = filedata[whatever]
+ if w then
+ return w[1]
+ else
+ return whatever
+ end
+ end
+end
+
+function references.checkedurl(whatever) -- return whatever if not resolved
+ if whatever then
+ local w = urldata[whatever]
+ if w then
+ local u, f = w[1], w[2]
+ if f and f ~= "" then
+ return u .. "/" .. f
+ else
+ return u
+ end
+ else
+ return whatever
+ end
+ end
+end
+
+function references.checkedfileorurl(whatever,default) -- return nil, nil if not resolved
+ if whatever then
+ local w = filedata[whatever]
+ if w then
+ return w[1], nil
+ else
+ local w = urldata[whatever]
+ if w then
+ local u, f = w[1], w[2]
+ if f and f ~= "" then
+ return nil, u .. "/" .. f
+ else
+ return nil, u
+ end
+ end
+ end
+ end
+ return default
+end
+
+-- programs
+
+local programs = references.programs or { }
+references.programs = programs
+local programdata = programs.data or { }
+programs.data = programdata
+
+function programs.define(name,file,description)
+ if name and name ~= "" then
+ programdata[name] = { file or "", description or file or ""}
+ end
+end
+
+function programs.get(name)
+ local f = programdata[name]
+ return f and f[1]
+end
+
+function references.checkedprogram(whatever) -- return whatever if not resolved
+ if whatever then
+ local w = programdata[whatever]
+ if w then
+ return w[1]
+ else
+ return whatever
+ end
+ end
+end
+
+implement {
+ name = "defineprogram",
+ actions = programs.define,
+ arguments = { "string", "string", "string" }
+}
+
+local function getprogram(name)
+ local p = programdata[name]
+ if p then
+ context(p[1])
+ end
+end
+
+implement {
+ name = "getprogram",
+ actions = getprogram,
+ arguments = "string"
+}
+
+-- shared by urls and files
+
+-- function references.whatfrom(name)
+-- context((urldata[name] and v_url) or (filedata[name] and v_file) or v_unknown)
+-- end
+
+function references.from(name)
+ local u = urldata[name]
+ if u then
+ local url, file, description = u[1], u[2], u[3]
+ if description ~= "" then
+ return description
+ -- ok
+ elseif file and file ~= "" then
+ return url .. "/" .. file
+ else
+ return url
+ end
+ else
+ local f = filedata[name]
+ if f then
+ local file, description = f[1], f[2]
+ if description ~= "" then
+ return description
+ else
+ return file
+ end
+ end
+ end
+end
+
+local function from(name)
+ local u = urldata[name]
+ if u then
+ local url, file, description = u[1], u[2], u[3]
+ if description ~= "" then
+ ctx_dofromurldescription(description)
+ -- ok
+ elseif file and file ~= "" then
+ ctx_dofromurlliteral(url .. "/" .. file)
+ else
+ ctx_dofromurlliteral(url)
+ end
+ else
+ local f = filedata[name]
+ if f then
+ local file, description = f[1], f[2]
+ if description ~= "" then
+ ctx_dofromfiledescription(description)
+ else
+ ctx_dofromfileliteral(file)
+ end
+ end
+ end
+end
+
+implement {
+ name = "from",
+ actions = from,
+ arguments = "string"
+}
+
+function references.define(prefix,reference,list)
+ local d = defined[prefix] if not d then d = { } defined[prefix] = d end
+ d[reference] = list
+end
+
+function references.reset(prefix,reference)
+ local d = defined[prefix]
+ if d then
+ d[reference] = nil
+ end
+end
+
+implement {
+ name = "definereference",
+ actions = references.define,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "resetreference",
+ actions = references.reset,
+ arguments = { "string", "string" }
+}
+
+setmetatableindex(defined,"table")
+
+local function resolve(prefix,reference,args,set) -- we start with prefix,reference
+ if reference and reference ~= "" then
+ if not set then
+ set = { prefix = prefix, reference = reference }
+ else
+ if not set.reference then set.reference = reference end
+ if not set.prefix then set.prefix = prefix end
+ end
+ local r = settings_to_array(reference)
+ for i=1,#r do
+ local ri = r[i]
+ local d = defined[prefix][ri] or defined[""][ri]
+ if d then
+ resolve(prefix,d,nil,set)
+ else
+ local var = splitreference(ri)
+ if var then
+ var.reference = ri
+ local vo, vi = var.outer, var.inner
+ if not vo and vi then
+ -- to be checked
+ d = defined[prefix][vi] or defined[""][vi]
+ --
+ if d then
+ resolve(prefix,d,var.arguments,set) -- args can be nil
+ else
+ if args then var.arguments = args end
+ set[#set+1] = var
+ end
+ else
+ if args then var.arguments = args end
+ set[#set+1] = var
+ end
+ if var.has_tex then
+ set.has_tex = true
+ end
+ else
+ -- report_references("funny pattern %a",ri)
+ end
+ end
+ end
+ return set
+ else
+ return { }
+ end
+end
+
+-- prefix == "" is valid prefix which saves multistep lookup
+
+references.currentset = nil
+
+local function setreferenceoperation(k,v)
+ references.currentset[k].operation = v
+end
+
+local function setreferencearguments(k,v)
+ references.currentset[k].arguments = v
+end
+
+function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex
+ local currentset = references.currentset
+ if currentset and currentset.has_tex then
+ for i=1,#currentset do
+ local ci = currentset[i]
+ local operation = ci.operation
+ if operation and find(operation,"\\",1,true) then -- if o_has_tex then
+ ctx_expandreferenceoperation(i,operation)
+ end
+ local arguments = ci.arguments
+ if arguments and find(arguments,"\\",1,true) then -- if a_has_tex then
+ ctx_expandreferencearguments(i,arguments)
+ end
+ end
+ end
+end
+
+implement {
+ name = "expandcurrentreference",
+ actions = references.expandcurrent
+}
+
+implement {
+ name = "setreferenceoperation",
+ actions = setreferenceoperation,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "setreferencearguments",
+ actions = setreferencearguments,
+ arguments = { "integer", "string" }
+}
+
+local externals = { }
+
+-- we have prefixes but also components:
+--
+-- : prefix
+-- :: always external
+-- ::: internal (for products) or external (for components)
+
+local function loadexternalreferences(name,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local external = struc.references.collected -- direct references
+ local lists = struc.lists.collected -- indirect references (derived)
+ local pages = struc.pages.collected -- pagenumber data
+ -- a bit weird one, as we don't have the externals in the collected
+ for prefix, set in next, external do
+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",
+ "external","regular",name,prefix,reference)
+ end
+ local section = reference.section
+ local realpage = reference.realpage
+ if section then
+ reference.sectiondata = lists[section]
+ end
+ if realpage then
+ reference.pagedata = pages[realpage]
+ end
+ end
+ end
+ for i=1,#lists do
+ local entry = lists[i]
+ local metadata = entry.metadata
+ local references = entry.references
+ if metadata and references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local kind = metadata.kind
+ local realpage = references.realpage
+ if kind and realpage then
+ references.pagedata = pages[realpage]
+ local prefix = references.prefix or ""
+if prefix == "" then
+ prefix = name -- this can clash!
+end
+ local target = external[prefix]
+ if not target then
+ target = { }
+ external[prefix] = target
+ end
+ -- for s in gmatch(reference,"%s*([^,]+)") do
+ -- if trace_importing then
+ -- report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a",
+ -- "external",kind,name,prefix,s)
+ -- end
+ -- target[s] = target[s] or entry
+ -- end
+ local function action(s)
+ if trace_importing then
+ report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a",
+ "external",kind,name,prefix,s)
+ end
+ target[s] = target[s] or entry
+ end
+ process_settings(reference,action)
+ end
+ end
+ end
+ end
+ externals[name] = external
+ return external
+ end
+end
+
+local externalfiles = { }
+
+setmetatableindex(externalfiles, function(t,k)
+ local v = filedata[k]
+ if not v then
+ v = { k, k }
+ end
+ externalfiles[k] = v
+ return v
+end)
+
+setmetatableindex(externals, function(t,k) -- either or not automatically
+ local filename = externalfiles[k][1] -- filename
+ local fullname = file.replacesuffix(filename,"tuc")
+ if lfs.isfile(fullname) then -- todo: use other locator
+ local utilitydata = job.loadother(fullname)
+ if utilitydata then
+ local external = loadexternalreferences(k,utilitydata)
+ t[k] = external or false
+ return external
+ end
+ end
+ t[k] = false
+ return false
+end)
+
+local productdata = allocate {
+ productreferences = { },
+ componentreferences = { },
+ components = { },
+}
+
+references.productdata = productdata
+
+local function loadproductreferences(productname,componentname,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local productreferences = struc.references.collected -- direct references
+ local lists = struc.lists.collected -- indirect references (derived)
+ local pages = struc.pages.collected -- pagenumber data
+ -- we use indirect tables to save room but as they are eventually
+ -- just references we resolve them to data here (the mechanisms
+ -- that use this data check for indirectness)
+ for prefix, set in next, productreferences do
+ for reference, data in next, set do
+ if trace_importing then
+ report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a",
+ "product","regular",productname,prefix,reference)
+ end
+ local section = reference.section
+ local realpage = reference.realpage
+ if section then
+ reference.sectiondata = lists[section]
+ end
+ if realpage then
+ reference.pagedata = pages[realpage]
+ end
+ end
+ end
+ --
+ local componentreferences = { }
+ for i=1,#lists do
+ local entry = lists[i]
+ local metadata = entry.metadata
+ local references = entry.references
+ if metadata and references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local kind = metadata.kind
+ local realpage = references.realpage
+ if kind and realpage then
+ references.pagedata = pages[realpage]
+ local prefix = references.prefix or ""
+ local component = references.component
+ local ctarget, ptarget
+ if not component or component == componentname then
+ -- skip
+ else
+ -- one level up
+ local external = componentreferences[component]
+ if not external then
+ external = { }
+ componentreferences[component] = external
+ end
+ if component == prefix then
+ prefix = ""
+ end
+ ctarget = external[prefix]
+ if not ctarget then
+ ctarget = { }
+ external[prefix] = ctarget
+ end
+ end
+ ptarget = productreferences[prefix]
+ if not ptarget then
+ ptarget = { }
+ productreferences[prefix] = ptarget
+ end
+ local function action(s)
+ if ptarget then
+ if trace_importing then
+ report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a",
+ "product",kind,productname,prefix,s)
+ end
+ ptarget[s] = ptarget[s] or entry
+ end
+ if ctarget then
+ if trace_importing then
+ report_importing("registering %s reference, kind %a, name %a, prefix %a, referenc %a",
+ "component",kind,productname,prefix,s)
+ end
+ ctarget[s] = ctarget[s] or entry
+ end
+ end
+ process_settings(reference,action)
+ end
+ end
+ end
+ end
+ productdata.productreferences = productreferences -- not yet used
+ productdata.componentreferences = componentreferences
+ end
+end
+
+local function loadproductvariables(product,component,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local lists = struc.lists and struc.lists.collected
+ if lists then
+ local pages = struc.pages and struc.pages.collected
+ for i=1,#lists do
+ local li = lists[i]
+ if li.metadata.kind == "section" and li.references.component == component then
+ local firstsection = li
+ if firstsection.numberdata then
+ local numbers = firstsection.numberdata.numbers
+ if numbers then
+ if trace_importing then
+ report_importing("initializing section number to %:t",numbers)
+ end
+ productdata.firstsection = firstsection
+ structures.documents.preset(numbers)
+ end
+ end
+ if pages and firstsection.references then
+ local firstpage = pages[firstsection.references.realpage]
+ local number = firstpage and firstpage.number
+ if number then
+ if trace_importing then
+ report_importing("initializing page number to %a",number)
+ end
+ productdata.firstpage = firstpage
+ counters.set("userpage",1,number)
+ end
+ end
+ break
+ end
+ end
+ end
+ end
+end
+
+local function componentlist(tree,target)
+ local branches = tree and tree.branches
+ if branches then
+ for i=1,#branches do
+ local branch = branches[i]
+ local type = branch.type
+ if type == "component" then
+ if target then
+ target[#target+1] = branch.name
+ else
+ target = { branch.name }
+ end
+ elseif type == "product" or type == "component" then
+ target = componentlist(branch,target)
+ end
+ end
+ end
+ return target
+end
+
+local function loadproductcomponents(product,component,utilitydata)
+ local job = utilitydata.job
+ productdata.components = componentlist(job and job.structure and job.structure.collected) or { }
+end
+
+references.registerinitializer(function(tobesaved,collected)
+ -- not that much related to tobesaved or collected
+ productdata.components = componentlist(job.structure.collected) or { }
+end)
+
+function references.loadpresets(product,component) -- we can consider a special components hash
+ if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename
+ productdata.product = product
+ productdata.component = component
+ local fullname = file.replacesuffix(product,"tuc")
+ if lfs.isfile(fullname) then -- todo: use other locator
+ local utilitydata = job.loadother(fullname)
+ if utilitydata then
+ if trace_importing then
+ report_importing("loading references for component %a of product %a from %a",component,product,fullname)
+ end
+ loadproductvariables (product,component,utilitydata)
+ loadproductreferences(product,component,utilitydata)
+ loadproductcomponents(product,component,utilitydata)
+ end
+ end
+ end
+end
+
+references.productdata = productdata
+
+local useproduct = commands.useproduct
+
+if useproduct then
+
+ local function newuseproduct(product)
+ useproduct(product)
+ if texconditionals.autocrossfilereferences then
+ local component = justacomponent()
+ if component then
+ if trace_referencing or trace_importing then
+ report_references("loading presets for component %a of product %a",component,product)
+ end
+ references.loadpresets(product,component)
+ end
+ end
+ end
+
+ implement {
+ name = "useproduct",
+ actions = newuseproduct,
+ arguments = "string",
+ overload = true,
+ }
+
+end
+
+-- productdata.firstsection.numberdata.numbers
+-- productdata.firstpage.number
+
+local function report_identify_special(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local special = var.special
+ local error = var.error
+ local kind = var.kind
+ if error then
+ report_identifying("type %a, reference %a, index %a, prefix %a, special %a, error %a",type,reference,i,prefix,special,error)
+ else
+ report_identifying("type %a, reference %a, index %a, prefix %a, special %a, kind %a",type,reference,i,prefix,special,kind)
+ end
+end
+
+local function report_identify_arguments(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local arguments = var.arguments
+ local error = var.error
+ local kind = var.kind
+ if error then
+ report_identifying("type %a, reference %a, index %a, prefix %a, arguments %a, error %a",type,reference,i,prefix,arguments,error)
+ else
+ report_identifying("type %a, reference %a, index %a, prefix %a, arguments %a, kind %a",type,reference,i,prefix,arguments,kind)
+ end
+end
+
+local function report_identify_outer(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local outer = var.outer
+ local error = var.error
+ local kind = var.kind
+ if outer then
+ if error then
+ report_identifying("type %a, reference %a, index %a, prefix %a, outer %a, error %a",type,reference,i,prefix,outer,error)
+ else
+ report_identifying("type %a, reference %a, index %a, prefix %a, outer %a, kind %a",type,reference,i,prefix,outer,kind)
+ end
+ else
+ if error then
+ report_identifying("type %a, reference %a, index %a, prefix %a, error %a",type,reference,i,prefix,error)
+ else
+ report_identifying("type %a, reference %a, index %a, prefix %a, kind %a",type,reference,i,prefix,kind)
+ end
+ end
+end
+
+local function identify_special(set,var,i)
+ local special = var.special
+ local s = specials[special]
+ if s then
+ local outer = var.outer
+ local operation = var.operation
+ local arguments = var.arguments
+ if outer then
+ if operation then
+ -- special(outer::operation)
+ var.kind = "special outer with operation"
+ else
+ -- special()
+ var.kind = "special outer"
+ end
+ var.f = outer
+ elseif operation then
+ if arguments then
+ -- special(operation{argument,argument})
+ var.kind = "special operation with arguments"
+ else
+ -- special(operation)
+ var.kind = "special operation"
+ end
+ else
+ -- special()
+ var.kind = "special"
+ end
+ if trace_identifying then
+ report_identify_special(set,var,i,"1a")
+ end
+ else
+ var.error = "unknown special"
+ end
+ return var
+end
+
+local function identify_arguments(set,var,i)
+ local s = specials[var.inner]
+ if s then
+ -- inner{argument}
+ var.kind = "special operation with arguments"
+ else
+ var.error = "unknown inner or special"
+ end
+ if trace_identifying then
+ report_identify_arguments(set,var,i,"3a")
+ end
+ return var
+end
+
+-- needs checking: if we don't do too much (redundant) checking now
+-- inner ... we could move the prefix logic into the parser so that we have 'm for each entry
+-- foo:bar -> foo == prefix (first we try the global one)
+-- -:bar -> ignore prefix
+
+local function finish_inner(var,p,i)
+ var.kind = "inner"
+ var.i = i
+ var.p = p
+ var.r = (i.references and i.references.realpage) or (i.pagedata and i.pagedata.realpage) or 1
+ return var
+end
+
+local function identify_inner(set,var,prefix,collected,derived)
+ local inner = var.inner
+ -- the next test is a safeguard when references are auto loaded from outer
+ if not inner or inner == "" then
+ return false
+ end
+ local splitprefix, splitinner = lpegmatch(prefixsplitter,inner)
+ if splitprefix and splitinner then
+ -- we check for a prefix:reference instance in the regular set of collected
+ -- references; a special case is -: which forces a lookup in the global list
+ if splitprefix == "-" then
+ local i = collected[""]
+ if i then
+ i = i[splitinner]
+ if i then
+ return finish_inner(var,"",i)
+ end
+ end
+ end
+ local i = collected[splitprefix]
+ if i then
+ i = i[splitinner]
+ if i then
+ return finish_inner(var,splitprefix,i)
+ end
+ end
+ if derived then
+ -- next we look for a reference in the regular set of collected references
+ -- using the prefix that is active at this moment (so we overload the given
+ -- these are taken from other data structures (like lists)
+ if splitprefix == "-" then
+ local i = derived[""]
+ if i then
+ i = i[splitinner]
+ if i then
+ return finish_inner(var,"",i)
+ end
+ end
+ end
+ local i = derived[splitprefix]
+ if i then
+ i = i[splitinner]
+ if i then
+ return finish_inner(var,splitprefix,i)
+ end
+ end
+ end
+ end
+ -- we now ignore the split prefix and treat the whole inner as a potential
+ -- referenice into the global list
+ local i = collected[prefix]
+ if i then
+ i = i[inner]
+ if i then
+ return finish_inner(var,prefix,i)
+ end
+ end
+ if not i and derived then
+ -- and if not found we look in the derived references
+ local i = derived[prefix]
+ if i then
+ i = i[inner]
+ if i then
+ return finish_inner(var,prefix,i)
+ end
+ end
+ end
+ return false
+end
+
+local function unprefixed_inner(set,var,prefix,collected,derived,tobesaved)
+ local inner = var.inner
+ local s = specials[inner]
+ if s then
+ var.kind = "special"
+ else
+ local i = (collected and collected[""] and collected[""][inner]) or
+ (derived and derived [""] and derived [""][inner]) or
+ (tobesaved and tobesaved[""] and tobesaved[""][inner])
+ if i then
+ var.kind = "inner"
+ var.p = ""
+ var.i = i
+ var.r = (i.references and i.references.realpage) or (i.pagedata and i.pagedata.realpage) or 1
+ else
+ var.error = "unknown inner or special"
+ end
+ end
+ return var
+end
+
+local function identify_outer(set,var,i)
+ local outer = var.outer
+ local inner = var.inner
+ local external = externals[outer]
+ if external then
+ local v = identify_inner(set,var,nil,external)
+ if v then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2a")
+ end
+ return v
+ end
+ 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,"2b")
+ end
+ return v
+ end
+ end
+ local external = productdata.componentreferences[outer]
+ if external then
+ local v = identify_inner(set,var,nil,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
+ end
+ local external = productdata.productreferences[outer]
+ if external then
+ local vi = external[inner]
+ if vi then
+ var.kind = "outer with inner"
+ var.i = vi
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2d")
+ end
+ return var
+ end
+ end
+ -- the rest
+ local special = var.special
+ local arguments = var.arguments
+ local operation = var.operation
+ if inner then
+ -- tricky: in this case we can only use views when we're sure that all inners
+ -- are flushed in the outer document so that should become an option
+ if arguments then
+ -- outer::inner{argument}
+ var.kind = "outer with inner with arguments"
+ else
+ -- outer::inner
+ var.kind = "outer with inner"
+ end
+ var.i = inner
+ var.f = outer
+ var.r = (inner.references and inner.references.realpage) or (inner.pagedata and inner.pagedata.realpage) or 1
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2e")
+ end
+ elseif special then
+ local s = specials[special]
+ if s then
+ if operation then
+ if arguments then
+ -- outer::special(operation{argument,argument})
+ var.kind = "outer with special and operation and arguments"
+ else
+ -- outer::special(operation)
+ var.kind = "outer with special and operation"
+ end
+ else
+ -- outer::special()
+ var.kind = "outer with special"
+ end
+ var.f = outer
+ else
+ var.error = "unknown outer with special"
+ end
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2f")
+ end
+ else
+ -- outer::
+ var.kind = "outer"
+ var.f = outer
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2g")
+ end
+ end
+ return var
+end
+
+-- todo: avoid copy
+
+local function identify_inner_or_outer(set,var,i)
+ -- here we fall back on product data
+ local inner = var.inner
+ if inner and inner ~= "" then
+
+ -- first we look up in collected and derived using the current prefix
+
+ local prefix = set.prefix
+
+ local v = identify_inner(set,var,set.prefix,collected,derived)
+ if v then
+ if trace_identifying then
+ report_identify_outer(set,v,i,"4a")
+ end
+ return v
+ end
+
+ -- nest we look at each component (but we can omit the already consulted one
+
+ local jobstructure = job.structure
+ local components = jobstructure and jobstructure.components
+ if components then
+ for c=1,#components do
+ local component = components[c]
+ if component ~= prefix then
+ local v = identify_inner(set,var,component,collected,derived)
+ if v then
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4b")
+ end
+ return v
+ end
+ end
+ end
+ end
+
+ -- as a last resort we will consult the global lists
+
+ local v = unprefixed_inner(set,var,"",collected,derived,tobesaved)
+ if v then
+ if trace_identifying then
+ report_identify_outer(set,v,i,"4c")
+ end
+ return v
+ end
+
+ -- not it gets bad ... we need to look in external files ... keep in mind that
+ -- we can best use explicit references for this ... we might issue a warning
+
+ local componentreferences = productdata.componentreferences
+ local productreferences = productdata.productreferences
+ local components = productdata.components
+ if components and componentreferences then
+ for c=1,#components do
+ local component = components[c]
+ local data = componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4d")
+ end
+ return var
+ end
+ end
+ end
+ end
+ local component, inner = lpegmatch(componentsplitter,inner)
+ if component then
+ local data = componentreferences and componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4e")
+ end
+ return var
+ end
+ end
+ local data = productreferences and productreferences[component]
+ if data then
+ local vi = data[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4f")
+ end
+ return var
+ end
+ end
+ end
+ var.error = "unknown inner"
+ else
+ var.error = "no inner"
+ end
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4g")
+ end
+ return var
+end
+
+local function identify_inner_component(set,var,i)
+ -- we're in a product (maybe ignore when same as component)
+ local component = var.component
+ local v = identify_inner(set,var,component,collected,derived)
+ if not v then
+ var.error = "unknown inner in component"
+ end
+ if trace_identifying then
+ report_identify_outer(set,var,i,"5a")
+ end
+ return var
+end
+
+local function identify_outer_component(set,var,i)
+ local component = var.component
+ local inner = var.inner
+ local data = productdata.componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6a")
+ end
+ return var
+ end
+ end
+ local data = productdata.productreferences[component]
+ if data then
+ local vi = data[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6b")
+ end
+ return var
+ end
+ end
+ var.error = "unknown component"
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6c")
+ end
+ return var
+end
+
+local nofidentified = 0
+
+local function identify(prefix,reference)
+ if not reference then
+ prefix = ""
+ reference = prefix
+ end
+ local set = resolve(prefix,reference)
+ local bug = false
+ texsetcount("referencehastexstate",set.has_tex and 1 or 0)
+ nofidentified = nofidentified + 1
+ set.n = nofidentified
+ for i=1,#set do
+ local var = set[i]
+ local spe = var.special
+ local fnc = functions[spe]
+ if fnc then
+ var = fnc(var) or { error = "invalid special function" }
+ elseif spe then
+ var = identify_special(set,var,i)
+ elseif var.outer then
+ var = identify_outer(set,var,i)
+ elseif var.arguments then
+ var = identify_arguments(set,var,i)
+ elseif not var.component then
+ var = identify_inner_or_outer(set,var,i)
+ elseif productcomponent() then
+ var = identify_inner_component(set,var,i)
+ else
+ var = identify_outer_component(set,var,i)
+ end
+ set[i] = var
+ bug = bug or var.error
+ end
+ references.currentset = mark(set) -- mark, else in api doc
+ if trace_analyzing then
+ report_references(table.serialize(set,reference))
+ end
+ return set, bug
+end
+
+references.identify = identify
+
+local unknowns, nofunknowns, f_valid = { }, 0, formatters["[%s][%s]"]
+
+function references.valid(prefix,reference,specification)
+ local set, bug = identify(prefix,reference)
+ local unknown = bug or #set == 0
+ if unknown then
+ currentreference = nil -- will go away
+ local str = f_valid(prefix,reference)
+ local u = unknowns[str]
+ if not u then
+ interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal
+ unknowns[str] = 1
+ nofunknowns = nofunknowns + 1
+ else
+ unknowns[str] = u + 1
+ end
+ else
+ set.highlight = specification.highlight
+ set.newwindow = specification.newwindow
+ set.layer = specification.layer
+ currentreference = set[1]
+ end
+ -- we can do the expansion here which saves a call
+ return not unknown
+end
+
+implement {
+ name = "doifelsereference",
+ actions = { references.valid, commands.doifelse },
+ arguments = {
+ "string",
+ "string",
+ {
+ { "highlight", "boolean" },
+ { "newwindow", "boolean" },
+ { "layer" },
+ }
+ }
+}
+
+function references.reportproblems() -- might become local
+ if nofunknowns > 0 then
+ statistics.register("cross referencing", function()
+ return format("%s identified, %s unknown",nofidentified,nofunknowns)
+ end)
+ logspushtarget("logfile")
+ logsnewline()
+ report_references("start problematic references")
+ logsnewline()
+ for k, v in table.sortedpairs(unknowns) do
+ report_unknown("%4i: %s",v,k)
+ end
+ logsnewline()
+ report_references("stop problematic references")
+ logsnewline()
+ logspoptarget()
+ end
+end
+
+luatex.registerstopactions(references.reportproblems)
+
+-- The auto method will try to avoid named internals in a clever way which
+-- can make files smaller without sacrificing external references. Some of
+-- the housekeeping happens the backend side.
+
+local innermethod = v_auto -- only page|auto now
+local defaultinnermethod = defaultinnermethod
+references.innermethod = innermethod -- don't mess with this one directly
+
+function references.setinnermethod(m)
+ if toboolean(m) or m == v_page or m == v_yes then
+ innermethod = v_page
+ elseif m == v_name then
+ innermethod = v_name
+ else
+ innermethod = v_auto
+ end
+ references.innermethod = innermethod
+ function references.setinnermethod()
+ report_references("inner method is already set and frozen to %a",innermethod)
+ end
+end
+
+implement {
+ name = "setinnerreferencemethod",
+ actions = references.setinnermethod,
+ arguments = "string",
+ -- onlyonce = true
+}
+
+function references.getinnermethod()
+ return innermethod or defaultinnermethod
+end
+
+directives.register("references.linkmethod", function(v) -- page auto
+ references.setinnermethod(v)
+end)
+
+-- we can call setinternalreference with an already known internal or with
+-- a reference/prefix specification
+
+local destinationattributes = { }
+
+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 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 function action(ref)
+ tn = tn + 1
+ t[tn] = prefix .. ref
+ end
+ process_settings(reference,action)
+ else
+ local function action(ref)
+ tn = tn + 1
+ t[tn] = ref
+ end
+ process_settings(reference,action)
+ end
+ end
+ -- 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
+ -- we don't want too many #1 #2 #3 etc
+ tn = tn + 1
+ t[tn] = internal -- when number it's internal
+ end
+ if not view then
+ local i = references.internals[internal]
+ if i then
+ view = i.references.view
+ end
+ end
+ end
+ destination = references.mark(t,nil,nil,view) -- returns an attribute
+ end
+ if internal then -- new
+ destinationattributes[internal] = destination
+ end
+ texsetcount("lastdestinationattribute",destination)
+ return destination
+end
+
+local function getinternalreference(internal)
+ return destinationattributes[internal] or 0
+end
+
+references.setinternalreference = setinternalreference
+references.getinternalreference = getinternalreference
+
+implement {
+ name = "setinternalreference",
+ actions = setinternalreference,
+ arguments = {
+ {
+ { "prefix" },
+ { "reference" },
+ { "internal", "integer" },
+ { "view" }
+ }
+ }
+}
+
+-- implement {
+-- name = "getinternalreference",
+-- actions = { getinternalreference, context },
+-- arguments = "integer",
+-- }
+
+function references.setandgetattribute(data) -- maybe do internal automatically here
+ local attr = unsetvalue
+ local mdat = data.metadata
+ local rdat = data.references
+ if mdat and rdat then
+ if not rdat.section then
+ rdat.section = structures.sections.currentid()
+ end
+ local ndat = data.numberdata
+ if ndat then
+ local numbers = ndat.numbers
+ if type(numbers) == "string" then
+ ndat.numbers = counters.compact(numbers,nil,true)
+ end
+ data.numberdata = helpers.simplify(ndat)
+ end
+ local pdat = data.prefixdata
+ if pdat then
+ data.prefixdata = helpers.simplify(pdat)
+ end
+ local udat = data.userdata
+ if type(udat) == "string" then
+ data.userdata = helpers.touserdata(udat)
+ end
+ if not rdat.block then
+ rdat.block = structures.sections.currentblock()
+ end
+ local done = references.set(data) -- we had kind i.e .item -> full
+ if done then
+ attr = setinternalreference {
+ prefix = prefix,
+ reference = rdat.reference,
+ internal = rdat.internal,
+ view = rdat.view
+ } or unsetvalue
+ end
+ end
+ texsetcount("lastdestinationattribute",attr)
+ return attr
+end
+
+implement {
+ name = "setdestinationattribute",
+ actions = references.setandgetattribute,
+ arguments = {
+ {
+ {
+ "references", {
+ { "internal", "integer" },
+ { "block" },
+ { "view" },
+ { "prefix" },
+ { "reference" },
+ },
+ },
+ {
+ "metadata", {
+ { "kind" },
+ { "xmlroot" },
+ { "catcodes", "integer" },
+ },
+ },
+ {
+ "prefixdata", { "*" }
+ },
+ {
+ "numberdata", { "*" }
+ },
+ {
+ "entries", { "*" }
+ },
+ {
+ "userdata"
+ }
+ }
+ }
+}
+
+function references.getinternallistreference(n) -- n points into list (todo: registers)
+ local l = lists.collected[n]
+ local i = l and l.references.internal
+ return i and destinationattributes[i] or 0
+end
+
+function references.getinternalcachedlistreference(n) -- n points into list (todo: registers)
+ local l = lists.cached[n]
+ local i = l and l.references.internal
+ return i and destinationattributes[i] or 0
+end
+
+implement {
+ name = "getinternallistreference",
+ actions = { references.getinternallistreference, context },
+ arguments = "integer"
+}
+
+implement {
+ name = "getinternalcachedlistreference",
+ actions = { references.getinternalcachedlistreference, context },
+ arguments = "integer"
+}
+
+
+--
+
+function references.getcurrentmetadata(tag)
+ local data = currentreference and currentreference.i
+ return data and data.metadata and data.metadata[tag]
+end
+
+implement {
+ name = "getcurrentreferencemetadata",
+ actions = { references.getcurrentmetadata, context },
+ arguments = "string",
+}
+
+local function currentmetadata(tag)
+ local data = currentreference and currentreference.i
+ return data and data.metadata and data.metadata[tag]
+end
+
+references.currentmetadata = currentmetadata
+
+local function getcurrentprefixspec(default)
+ local data = currentreference and currentreference.i
+ local metadata = data and data.metadata
+ return
+ metadata and metadata.kind or "?",
+ metadata and metadata.name or "?",
+ default or "?"
+end
+
+references.getcurrentprefixspec = getcurrentprefixspec
+
+-- implement {
+-- name = "getcurrentprefixspec",
+-- actions = { getcurrentprefixspec, context }, -- returns 3 arguments
+-- arguments = "string",
+-- }
+
+implement {
+ name = "getcurrentprefixspec",
+ actions = function(tag)
+ context("{%s}{%s}{%s}",getcurrentprefixspec(tag))
+ end,
+ arguments = "string",
+}
+
+local genericfilters = { }
+local userfilters = { }
+local textfilters = { }
+local fullfilters = { }
+local sectionfilters = { }
+
+filters.generic = genericfilters
+filters.user = userfilters
+filters.text = textfilters
+filters.full = fullfilters
+filters.section = sectionfilters
+
+local function filterreference(name,prefixspec,numberspec) -- number page title ...
+ local data = currentreference and currentreference.i -- maybe we should take realpage from here
+ if data then
+ if name == "realpage" then
+ local cs = references.analyze() -- normally already analyzed but also sets state
+ context(tonumber(cs.realpage) or 0)
+ else -- assumes data is table
+ local kind = type(data) == "table" and data.metadata and data.metadata.kind
+ if kind then
+ local filter = filters[kind] or genericfilters
+ filter = filter and (filter[name] or filter.unknown or genericfilters[name] or genericfilters.unknown)
+ if filter then
+ if trace_referencing then
+ report_references("name %a, kind %a, using dedicated filter",name,kind)
+ end
+ filter(data,name,prefixspec,numberspec)
+ elseif trace_referencing then
+ report_references("name %a, kind %a, using generic filter",name,kind)
+ end
+ elseif trace_referencing then
+ report_references("name %a, unknown kind",name)
+ end
+ end
+ elseif name == "realpage" then
+ context(0)
+ elseif trace_referencing then
+ report_references("name %a, no reference",name)
+ end
+end
+
+local function filterreferencedefault()
+ return filterreference("default",getcurrentprefixspec("default"))
+end
+
+references.filter = filterreference
+references.filterdefault = filterreferencedefault
+
+implement {
+ name = "filterreference",
+ actions = filterreference,
+ arguments = "string",
+}
+
+implement {
+ name = "filterdefaultreference",
+ actions = filterreference,
+ arguments = {
+ "string", -- 'default'
+ { { "*" } }, -- prefixspec
+ { { "*" } }, -- numberspec
+ }
+}
+
+function genericfilters.title(data)
+ if data then
+ local titledata = data.titledata or data.useddata
+ if titledata then
+ helpers.title(titledata.title or "?",data.metadata)
+ end
+ end
+end
+
+function genericfilters.text(data)
+ if data then
+ local entries = data.entries or data.useddata
+ if entries then
+ helpers.title(entries.text or "?",data.metadata)
+ end
+ end
+end
+
+function genericfilters.number(data,what,prefixspec,numberspec)
+ if data then
+ numberdata = lists.reordered(data) -- data.numberdata
+ if numberdata then
+ helpers.prefix(data,prefixspec)
+ sections.typesetnumber(numberdata,"number",numberspec,numberdata)
+ else
+ local useddata = data.useddata
+ if useddata and useddata.number then
+ context(useddata.number)
+ end
+ end
+ end
+end
+
+genericfilters.default = genericfilters.text
+
+function genericfilters.page(data,prefixspec,pagespec)
+ local pagedata = data.pagedata
+ if pagedata then
+ local number, conversion = pagedata.number, pagedata.conversion
+ if not number then
+ -- error
+ elseif conversion then
+ ctx_convertnumber(conversion,number)
+ else
+ context(number)
+ end
+ else
+ helpers.prefixpage(data,prefixspec,pagespec)
+ end
+end
+
+function userfilters.unknown(data,name)
+ if data then
+ local userdata = data.userdata
+ local userkind = userdata and userdata.kind
+ if userkind then
+ local filter = filters[userkind] or genericfilters
+ filter = filter and (filter[name] or filter.unknown)
+ if filter then
+ filter(data,name)
+ return
+ end
+ end
+ local namedata = userdata and userdata[name]
+ if namedata then
+ context(namedata)
+ end
+ end
+end
+
+function textfilters.title(data)
+ helpers.title(data.entries.text or "?",data.metadata)
+end
+
+-- no longer considered useful:
+--
+-- function filters.text.number(data)
+-- helpers.title(data.entries.text or "?",data.metadata)
+-- end
+
+function textfilters.page(data,prefixspec,pagespec)
+ helpers.prefixpage(data,prefixspec,pagespec)
+end
+
+fullfilters.title = textfilters.title
+fullfilters.page = textfilters.page
+
+function sectionfilters.number(data,what,prefixspec)
+ if data then
+ local numberdata = data.numberdata
+ if not numberdata then
+ local useddata = data.useddata
+ if useddata and useddata.number then
+ context(useddata.number)
+ end
+ elseif numberdata.hidenumber then
+ local references = data.references
+ if trace_empty then
+ report_empty("reference %a has a hidden number",references.reference)
+ ctx_emptyreference() -- maybe an option
+ end
+ else
+ sections.typesetnumber(numberdata,"number",prefixspec,numberdata)
+ end
+ end
+end
+
+sectionfilters.title = genericfilters.title
+sectionfilters.page = genericfilters.page
+sectionfilters.default = sectionfilters.number
+
+-- filters.note = { default = genericfilters.number }
+-- filters.formula = { default = genericfilters.number }
+-- filters.float = { default = genericfilters.number }
+-- filters.description = { default = genericfilters.number }
+-- filters.item = { default = genericfilters.number }
+
+setmetatableindex(filters, function(t,k) -- beware, test with rawget
+ local v = { default = genericfilters.number } -- not copy as it might be extended differently
+ t[k] = v
+ return v
+end)
+
+-- function references.sectiontitle(n)
+-- helpers.sectiontitle(lists.collected[tonumber(n) or 0])
+-- end
+
+-- function references.sectionnumber(n)
+-- helpers.sectionnumber(lists.collected[tonumber(n) or 0])
+-- end
+
+-- function references.sectionpage(n,prefixspec,pagespec)
+-- helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec)
+-- end
+
+-- analyze
+
+references.testrunners = references.testrunners or { }
+references.testspecials = references.testspecials or { }
+
+local runners = references.testrunners
+local specials = references.testspecials
+
+-- We need to prevent ending up in the 'relative location' analyzer as it is
+-- pretty slow (progressively). In the pagebody one can best check the reference
+-- real page to determine if we need contrastlocation as that is more lightweight.
+
+local function checkedpagestate(n,page,actions,position,spread)
+ local p = tonumber(page)
+ if not p then
+ return 0
+ end
+ if position and #actions > 0 then
+ local i = actions[1].i -- brrr
+ if i then
+ local a = i.references
+ if a then
+ local x = a.x
+ local y = a.y
+ if x and y then
+ local jp = jobpositions.collected[position]
+ if jp then
+ local px = jp.x
+ local py = jp.y
+ local pp = jp.p
+ if p == pp then
+ -- same page
+ if py > y then
+ return 5 -- above
+ elseif py < y then
+ return 4 -- below
+ elseif px > x then
+ return 4 -- below
+ elseif px < x then
+ return 5 -- above
+ else
+ return 1 -- same
+ end
+ elseif spread then
+ if pp % 2 == 0 then
+ -- left page
+ if pp > p then
+ return 2 -- before
+ elseif pp + 1 == p then
+-- return 4 -- below (on right page)
+ return 5 -- above (on left page)
+ else
+ return 3 -- after
+ end
+ else
+ -- right page
+ if pp < p then
+ return 3 -- after
+ elseif pp - 1 == p then
+-- return 5 -- above (on left page)
+ return 4 -- below (on right page)
+ else
+ return 2 -- before
+ end
+ end
+ elseif pp > p then
+ return 2 -- before
+ else
+ return 3 -- after
+ end
+ end
+ end
+ end
+ end
+ end
+ local r = referredpage(n) -- sort of obsolete
+ if p > r then
+ return 3 -- after
+ elseif p < r then
+ return 2 -- before
+ else
+ return 1 -- same
+ end
+end
+
+local function setreferencerealpage(actions)
+ if not actions then
+ actions = references.currentset
+ end
+ if not actions then
+ return 0
+ else
+ local realpage = actions.realpage
+ if realpage then
+ return realpage
+ end
+ local nofactions = #actions
+ if nofactions > 0 then
+ for i=1,nofactions do
+ local a = actions[i]
+ local what = runners[a.kind]
+ if what then
+ what = what(a,actions) -- needs documentation
+ end
+ end
+ realpage = actions.realpage
+ if realpage then
+ return realpage
+ end
+ end
+ actions.realpage = 0
+ return 0
+ end
+end
+
+references.setreferencerealpage = setreferencerealpage
+
+-- we store some analysis data alongside the indexed array
+-- at this moment only the real reference page is analyzed
+-- normally such an analysis happens in the backend code
+
+function references.analyze(actions,position,spread)
+ if not actions then
+ actions = references.currentset
+ end
+ if not actions then
+ actions = { realpage = 0, pagestate = 0 }
+ elseif actions.pagestate then
+ -- already done
+ else
+ local realpage = actions.realpage or setreferencerealpage(actions)
+ if realpage == 0 then
+ actions.pagestate = 0
+ elseif actions.external then
+ actions.pagestate = 0
+ else
+ actions.pagestate = checkedpagestate(actions.n,realpage,actions,position,spread)
+ end
+ end
+ return actions
+end
+
+local function referencepagestate(position,detail,spread)
+ local actions = references.currentset
+ if not actions then
+ return 0
+ else
+ if not actions.pagestate then
+ references.analyze(actions,position,spread) -- delayed unless explicitly asked for
+ end
+ local pagestate = actions.pagestate
+ if detail then
+ return pagestate
+ elseif pagestate == 4 then
+ return 2 -- compatible
+ elseif pagestate == 5 then
+ return 3 -- compatible
+ else
+ return pagestate
+ end
+ end
+end
+
+implement {
+ name = "referencepagestate",
+ actions = { referencepagestate, context },
+ arguments = "string"
+}
+
+implement {
+ name = "referencepagedetail",
+ actions = { referencepagestate, context },
+ arguments = { "string", "boolean", "boolean" }
+}
+
+local function referencerealpage(actions)
+ actions = actions or references.currentset
+ return not actions and 0 or actions.realpage or setreferencerealpage(actions)
+end
+
+implement {
+ name = "referencerealpage",
+ actions = { referencerealpage, context },
+ arguments = "string"
+}
+
+local plist, nofrealpages
+
+local function realpageofpage(p) -- the last one counts !
+ if not plist then
+ local pages = structures.pages.collected
+ nofrealpages = #pages
+ plist = { }
+ for rp=1,nofrealpages do
+ local page = pages[rp]
+ if page then
+ plist[page.number] = rp
+ end
+ end
+ references.nofrealpages = nofrealpages
+ end
+ return plist[p]
+end
+
+references.realpageofpage = realpageofpage
+
+function references.checkedrealpage(r)
+ if not plist then
+ realpageofpage(r) -- just initialize
+ end
+ if not r then
+ return texgetcount("realpageno")
+ elseif r < 1 then
+ return 1
+ elseif r > nofrealpages then
+ return nofrealpages
+ else
+ return r
+ end
+end
+
+-- use local ?
+
+local pages = allocate {
+ [variables.firstpage] = function() return counters.record("realpage")["first"] end,
+ [variables.previouspage] = function() return counters.record("realpage")["previous"] end,
+ [variables.nextpage] = function() return counters.record("realpage")["next"] end,
+ [variables.lastpage] = function() return counters.record("realpage")["last"] end,
+
+ [variables.firstsubpage] = function() return counters.record("subpage" )["first"] end,
+ [variables.previoussubpage] = function() return counters.record("subpage" )["previous"] end,
+ [variables.nextsubpage] = function() return counters.record("subpage" )["next"] end,
+ [variables.lastsubpage] = function() return counters.record("subpage" )["last"] end,
+
+ [variables.forward] = function() return counters.record("realpage")["forward"] end,
+ [variables.backward] = function() return counters.record("realpage")["backward"] end,
+}
+
+references.pages = pages
+
+-- maybe some day i will merge this in the backend code with a testmode (so each
+-- runner then implements a branch)
+
+runners["inner"] = function(var,actions)
+ local r = var.r
+ if r then
+ actions.realpage = r
+ end
+end
+
+runners["special"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["special operation"] = runners["special"]
+runners["special operation with arguments"] = runners["special"]
+
+function specials.internal(var,actions)
+ local v = internals[tonumber(var.operation)]
+ local r = v and v.references
+ if r then
+ local p = r.realpage
+ if p then
+-- setmetatableindex(actions,r)
+ actions.realpage = p
+ actions.view = r.view
+ end
+ end
+end
+
+specials.i = specials.internal
+
+function specials.page(var,actions)
+ local o = var.operation
+ local p = pages[o]
+ if type(p) == "function" then
+ p = p()
+ else
+ p = tonumber(realpageofpage(tonumber(o)))
+ end
+ if p then
+ var.r = p
+ actions.realpage = actions.realpage or p -- first wins
+ end
+end
+
+function specials.realpage(var,actions)
+ local p = tonumber(var.operation)
+ if p then
+ var.r = p
+ actions.realpage = actions.realpage or p -- first wins
+ end
+end
+
+function specials.userpage(var,actions)
+ local p = tonumber(realpageofpage(var.operation))
+ if p then
+ var.r = p
+ actions.realpage = actions.realpage or p -- first wins
+ end
+end
+
+function specials.deltapage(var,actions)
+ local p = tonumber(var.operation)
+ if p then
+ p = references.checkedrealpage(p + texgetcount("realpageno"))
+ var.r = p
+ actions.realpage = actions.realpage or p -- first wins
+ end
+end
+
+function specials.section(var,actions)
+ local sectionname = var.arguments
+ local destination = var.operation
+ local internal = structures.sections.internalreference(sectionname,destination)
+ if internal then
+ var.special = "internal"
+ var.operation = internal
+ var.arguments = nil
+ specials.internal(var,actions)
+ end
+end
+
+-- experimental:
+
+local p_splitter = lpeg.splitat(":")
+local p_lower = lpeg.patterns.utf8lower
+
+-- We can cache lowercased titles which saves a lot of time, but then
+-- we can better have a global cache with weak keys.
+
+-- local lowercache = table.setmetatableindex(function(t,k)
+-- local v = lpegmatch(p_lower,k)
+-- t[k] = v
+-- return v
+-- end)
+
+local lowercache = false
+
+local function locate(list,askedkind,askedname,pattern)
+ local kinds = lists.kinds
+ local names = lists.names
+ if askedkind and not kinds[askedkind] then
+ return false
+ end
+ if askedname and not names[askedname] then
+ return false
+ end
+ for i=1,#list do
+ local entry = list[i]
+ local metadata = entry.metadata
+ if metadata then
+ local found = false
+ if askedname then
+ local name = metadata.name
+ if name then
+ found = name == askedname
+ end
+ elseif askedkind then
+ local kind = metadata.kind
+ if kind then
+ found = kind == askedkind
+ end
+ end
+ if found then
+ local titledata = entry.titledata
+ if titledata then
+ local title = titledata.title
+ if title then
+ if lowercache then
+ found = lpegmatch(pattern,lowercache[title])
+ else
+ found = lpegmatch(pattern,lpegmatch(p_lower,title))
+ end
+ if found then
+ return {
+ inner = pattern,
+ kind = "inner",
+ reference = pattern,
+ i = entry,
+ p = "",
+ r = entry.references.realpage,
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function functions.match(var,actions)
+ if not var.outer then
+ local operation = var.operation
+ if operation and operation ~= "" then
+ local operation = lpegmatch(p_lower,operation)
+ local list = lists.collected
+ local names = false
+ local kinds = false
+ local where, what = lpegmatch(p_splitter,operation)
+ if where and what then
+ local pattern = lpeg.finder(what)
+ return
+ locate(list,false,where,pattern)
+ or locate(list,where,false,pattern)
+ or { error = "no match" }
+ else
+ local pattern = lpeg.finder(operation)
+ -- todo: don't look at section and float in last pass
+ return
+ locate(list,"section",false,pattern)
+ or locate(list,"float",false,pattern)
+ or locate(list,false,false,pattern)
+ or { error = "no match" }
+ end
+ end
+ end
+end
+
+-- needs a better split ^^^
+
+-- done differently now:
+
+function references.export(usedname) end
+function references.import(usedname) end
+function references.load (usedname) end
+
+implement { name = "exportreferences", actions =references.export }
+
+-- better done here .... we don't insert/remove, just use a pointer
+
+local prefixstack = { "" }
+local prefixlevel = 1
+
+local function pushreferenceprefix(prefix)
+ prefixlevel = prefixlevel + 1
+ prefixstack[prefixlevel] = prefix
+ return prefix
+end
+
+local function popreferenceprefix()
+ prefixlevel = prefixlevel - 1
+ if prefixlevel > 0 then
+ return prefixstack[prefixlevel]
+ else
+ report_references("unable to pop referenceprefix")
+ return ""
+ end
+end
+
+implement {
+ name = "pushreferenceprefix",
+ actions = { pushreferenceprefix, context }, -- we can use setmacro
+ arguments = "string",
+}
+
+implement {
+ name = "popreferenceprefix",
+ actions = { popreferenceprefix, context }, -- we can use setmacro
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi
new file mode 100644
index 00000000000..177abd835b7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi
@@ -0,0 +1,2296 @@
+%D \module
+%D [ file=strc-ref,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Cross Referencing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: (1) configure references, (2) rendering => with presets
+%
+% \defineconversionset[default][Character,number,Romannumerals,Character][number]
+% \defineseparatorset [default][.,.,--][.]
+% \setuphead[subsection][sectionstopper=),sectionsegments=4:4]
+% \setupreferencestructureprefix[default][prefixsegments=2:4]
+% \setupreferencestructureprefix[figure][default][prefixsegments=3:4]
+% \chapter {One}
+% \section {One}
+% \subsection[sec:test]{Two}
+% See \in[sec:test] and \in[fig:xx] and \in[fig:yy]
+% \placefigure[here][fig:xx]{}{}
+% \placefigure[here][fig:yy]{}{}
+
+\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing}
+
+\registerctxluafile{strc-rsc}{1.001}
+\registerctxluafile{strc-ref}{1.001}
+\registerctxluafile{node-ref}{1.001}
+
+\unprotect
+
+%D This module is a (partial) rewrite of core-ref.tex for \MKIV. As
+%D such it will be a moving target for a while.
+
+%D Later we will do a further cleanup and move much of the code to
+%D \LUA\ (i.e.\ better backend integration).
+
+\let\mainreference\gobblefivearguments
+
+% this will go when we got rid of the tuo file
+
+\let\currentfolioreference \!!zerocount % only used in xml-fo
+\let\resetreferences \relax
+\let\setreferences \relax
+\let\showcurrentreference \relax
+\let\setexecutecommandcheck\gobbletwoarguments
+
+% todo : unknown/illegal reference no arg
+% todo : +n pages check on 'samepage' (contrastcolor)
+% todo : multiple text in reference
+
+% Makes more sense to build action data first, especially now
+% openaction etc are supported.
+%
+% \definespecial\doexecuteactionchain w h
+% \definespecial\dosetgotolocation
+% \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
+%D Before we start implementing functionality we provide a way to set
+%D up this 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.
+
+\let\referenceprefix\empty
+
+\installcorenamespace{referencing}
+
+\installdirectcommandhandler \??referencing {referencing} % \??referencing
+
+\newif\ifreferencing \referencingtrue
+
+\appendtoks
+ \edef\p_state{\referencingparameter\c!state}%
+ \ifx\p_state\v!start
+ \referencingtrue
+ \else
+ \referencingfalse
+ \fi
+\to \everysetupreferencing
+
+%D In paper documents, referencing comes down to cross referencing, but in
+%D their interactive counterparts, is also involves navigation. Many features
+%D implemented here are therefore closely related to navigation.
+%D
+%D Many \CONTEXT\ commands can optionally be fed with a reference. Such a
+%D reference, when called upon, returns the number of a figure, table, chapter
+%D etc, a piece of text, or a pagenumber.
+%D
+%D There are three ways of defining a reference:
+%D
+%D \starttyping
+%D \pagereference[here]
+%D \textreference[here]{some text}
+%D \stoptyping
+%D
+%D the third alternative combines them in:
+%D
+%D \starttyping
+%D \reference[here]{some text}
+%D \stoptyping
+
+\unexpanded\def\textreference {\dosingleargument\strc_references_text_reference} % no need for \dosingle
+\unexpanded\def\pagereference {\dosingleargument\strc_references_page_reference} % as they're mandate and
+\unexpanded\def\reference {\dosingleargument\strc_references_full_reference} % never forgotten
+\unexpanded\def\setreference {\dodoubleargument\strc_references_set_reference } %
+
+% maybe: \let\reference\textreference
+
+\unexpanded\def\showreferences
+ {\enabletrackers[nodes.references.show,nodes.destinations.show]}
+
+%D These are implemented in a low level form as:
+
+\unexpanded\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}}
+\unexpanded\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}}
+\unexpanded\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}}
+\unexpanded\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}}
+
+\unexpanded\def\dosetdirectpagereference#1{\strc_references_set_named_reference\s!page{#1}{}{}} % low level, maybe use _
+
+\unexpanded\def\usereferenceparameter#1% faster local variant
+ {\edef\m_strc_references_asked{#1\c!reference}%
+ \ifx\m_strc_references_asked\empty\else
+ \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:
+
+\newcount\lastreferenceattribute
+\newcount\lastdestinationattribute
+
+\def\strc_references_finish#prefix#reference#internal%
+ {\normalexpanded{\ctxlatecommand{enhancereference("#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.
+
+% 0 = nothing
+% 1 = bind to following word
+
+\setnewconstant\c_strc_references_bind_state\plusone
+
+\def\strc_references_inject_before
+ {}
+
+\def\strc_references_inject_after
+ {\ifcase\c_strc_references_bind_state
+ % nothing
+ \or
+ \prewordbreak % to be tested: \removeunwantedspaces\permithyphenation
+ \fi}
+
+
+\unexpanded\def\strc_references_set_named_reference
+ {\ifreferencing
+ \expandafter\strc_references_set_named_reference_indeed
+ \else
+ \expandafter\gobblefourarguments
+ \fi}
+
+\newbox\b_strc_destination_nodes
+
+\unexpanded\def\strc_references_flush_destination_nodes
+ {\ifvoid\b_strc_destination_nodes \else
+ \unhbox\b_strc_destination_nodes
+ \fi}
+
+\unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay
+ {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute
+
+\unexpanded\def\strc_references_stop_destination_nodes
+ {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}}
+
+\unexpanded\def\strc_references_set_named_reference_indeed#kind#labels#userdata#text% labels userdata text -> todo: userdata
+ {\ifreferencing
+ % we could have a more efficient one for page references but for the moment
+ % we don't care too much
+ \edef\currentreferencekind {#kind}%
+ \edef\currentreferencelabels {#labels}%
+ \edef\currentreferenceuserdata {#userdata}%
+ \edef\currentreferenceexpansion{\referencingparameter\c!expansion}% {\referenceparameter\c!expansion}
+ \ifx\currentreferencelabels\empty
+ \lastdestinationattribute\attributeunsetvalue
+ \else
+ \ifx\currentreferenceexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentreferencedata{#text}% data, no text else conflict
+ \xmlstopraw
+ \globallet\currentreferencecoding\s!xml
+ \else
+ \ifx\currentreferenceexpansion\v!yes
+ \xdef\currentreferencedata{#text}%
+ \else
+ \xdef\currentreferencedata{\detokenize{#text}}%
+ \fi
+ \globallet\currentreferencecoding\s!tex
+ \fi
+ % beware, the structures.references.set writes a
+ \setnextinternalreference
+ \strc_references_start_destination_nodes
+ \clf_setdestinationattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ \ifx\referenceprefix\empty\else
+ prefix {\referenceprefix}%
+ \fi
+ reference {\currentreferencelabels}%
+ }%
+ metadata {%
+ kind {\currentreferencekind}%
+ \ifx\currentreferencekind\s!page\else
+ \ifx\currentreferencecoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ catcodes \catcodetable
+ \fi
+ }%
+ \ifx\currentreferencedata\empty\else
+ entries {%
+ text {\currentreferencedata}%
+ }%
+ \fi
+ \ifx\currentreferenceuserdata\empty\else
+ userdata {\detokenize{#userdata}}%
+ \fi
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi
+ % will become obsolete:
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \strc_references_inject_before % new
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \strc_references_inject_after % new
+ \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
+ \fi\fi}
+
+\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable
+ {\ifreferencing
+ \edef\currentreferencelabels{#labels}%
+ \ifx\currentreferencelabels\empty
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \else
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \clf_setdestinationattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ \ifx\referenceprefix\empty\else
+ prefix {\referenceprefix}%
+ \fi
+ reference {\currentreferencelabels}%
+ }%
+ metadata {%
+ kind {page}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi}
+
+\unexpanded\def\strc_references_direct_full_user#user#labels#text%
+ {\ifreferencing
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \edef\m_strc_references_user{#user}%
+ \edef\m_strc_references_text{#text}%
+ \clf_setdestinationattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ \ifx\referenceprefix\empty\else
+ prefix {\referenceprefix}%
+ \fi
+ reference {#labels}%
+ }%
+ metadata {%
+ kind {\s!full}%
+ }%
+ \ifx\m_strc_references_text\empty \else
+ entries {%
+ text {\m_strc_references_text}%
+ }%
+ \fi
+ \ifx\m_strc_references_user\empty \else
+ userdata {\m_strc_references_user}% \detokenize\expandafter{\normalexpanded{...}}
+ \fi
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi
+ % will become obsolete:
+ \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
+ \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
+ \fi\fi}
+
+\unexpanded\def\strc_references_direct_full
+ {\strc_references_direct_full_user\empty}
+
+\let\dodirectfullreference\strc_references_direct_full % for at lua end (no longer)
+
+\def\strc_references_set_page_only_destination_box_attribute#cs#labels%
+ {\strc_references_set_page_only_destination_attribute{#labels}%
+ \ifnum\lastdestinationattribute>\zerocount
+ \edef#cs{attr \destinationattribute\number\lastdestinationattribute}%
+ \else
+ \let#cs\empty
+ \fi}
+
+%D It's about time to clean up references .. stable enough now.
+
+\unexpanded\def\boxreference[#1]%
+ {\begingroup
+ \dowithnextbox
+ {\strc_references_set_page_only_destination_attribute{#1}%
+ \hbox
+ \ifnum\lastdestinationattribute=\attributeunsetvalue\else attr \destinationattribute \lastdestinationattribute \fi
+ {\box\b_strc_destination_nodes\box\nextbox}%
+ \endgroup}}
+
+\unexpanded\def\hboxreference[#1]{\boxreference[#1]\hbox}
+\unexpanded\def\vboxreference[#1]{\boxreference[#1]\vbox}
+
+% \ifx\currentdestinationattribute\empty
+% \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo
+% \fi
+
+\def\defaultreferencepage#text{[[[#text]]]}
+\def\defaultreferencetext#text{[[[#text]]]}
+
+%D For internal usage:
+
+\def\strc_references_set_simple_reference#label%
+ {\iflocation
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \clf_setdestinationattribute
+ {%
+ references {%
+ view {\interactionparameter\c!focus}%
+ \ifx\referenceprefix\empty\else
+ prefix {\referenceprefix}%
+ \fi
+ reference {#label}%
+ internal \nextinternalreference
+ }%
+ metadata {%
+ kind {\s!page}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
+ \fi}
+
+\def\strc_references_set_simple_internal_reference#label% no prefix
+ {\iflocation
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \clf_setdestinationattribute
+ {%
+ references {%
+ view {\interactionparameter\c!focus}%
+ reference {#label}%
+ internal \nextinternalreference
+ }%
+ metadata {%
+ kind {\s!page}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
+ \fi}
+
+\def\strc_references_get_simple_reference#label%
+ {\iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \ht\strutbox
+ depth \dp\strutbox
+ \extrareferencearguments
+ }%
+ \relax
+ \xdef\currentreferenceattribute{\number\lastreferenceattribute}%
+ \else
+ \xdef\currentreferenceattribute{\number\attributeunsetvalue}%
+ \fi}
+
+%D \macros
+%D {contentreference}
+%D
+%D \starttyping
+%D \setupinteraction
+%D [state=start,
+%D focus=standard]
+%D
+%D \setupheader
+%D [state=stop]
+%D
+%D See page \goto{page 2}[page2] \page
+%D
+%D \contentreference
+%D [page2]
+%D [offset=1cm,toffset=2cm,frame=on]
+%D {\externalfigure[cow.pdf][factor=fit]}
+%D
+%D \stoptyping
+
+\unexpanded\def\contentreference
+ {\hbox\bgroup
+ \dodoubleempty\strc_references_content_pickup}
+
+\def\strc_references_content_pickup
+ {\ifsecondargument
+ \expandafter\strc_references_content_pickup_yes
+ \else
+ \expandafter\strc_references_content_pickup_nop
+ \fi}
+
+\def\strc_references_content_pickup_yes[#1][#2]%
+ {\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_pickup_nop[#1][#2]%
+ {\dowithnextbox{\strc_references_content_nop_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_yes_finish#1#2%
+ {\scratchwidth \wd\nextbox
+ \scratchheight\ht\nextbox
+ \scratchdepth \dp\nextbox
+ \setbox\nextbox\hbox
+ {\framed[\c!frame=\v!off,#2]{\box\nextbox}}%
+ \strc_references_set_simple_reference{#1}%
+ \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \setbox\nextbox\hbox{\box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+\def\strc_references_content_nop_finish#1#2%
+ {\strc_references_set_simple_reference{#1}%
+ \hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \egroup}
+
+%D \macros
+%D {everyreference}
+%D
+%D For rather tricky purposes, one can assign sanitizing
+%D macros to \type{\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.
+
+\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.
+
+\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
+%D \starttabulate[||||]
+%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR
+%D \NC $\star$ \NC \NC \NC\NR
+%D \NC $\star$ \NC $\star$ \NC $\star$ \NC\NR
+%D \NC \NC $\star$ \NC \NC\NR
+%D \stoptabulate
+
+\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
+%D \starttyping
+%D \goto{go back}[PreviousJump]
+%D \goto{colofon}[colofon page]
+%D \stoptyping
+%D
+%D Here \type{PreviousJump} is handled by the viewer, while the
+%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
+%D We also use the odd/even characteristic to determine the
+%D page state.
+
+\let\currentrealreference \empty
+\let\currentpagereference \empty
+\let\currenttextreference \empty
+\let\currentreferenceorder \empty
+\let\currentsubtextreference \empty
+\let\currentsubsubtextreference\empty
+
+\newcount\referencehastexstate % set in backend
+
+% referencepagestate:
+%
+% 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
+%D \starttyping
+%D \goto[reference]
+%D \goto[outer reference::]
+%D \goto[outer reference::inner reference]
+%D \goto[operation(argument)]
+%D \goto[operation(action{argument,argument})]
+%D \goto[action]
+%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
+%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
+%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
+%D \starttyping
+%D \pagereference[important]
+%D \pagereference[unimportant]
+%D \setupreferencing[prefix=sidetrack]
+%D \pagereference[important]
+%D \stoptyping
+%D
+%D results in saving (writing) the references
+%D
+%D \starttyping
+%D ...{}{important}
+%D ...{}{unimportant}
+%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
+%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
+%D \starttyping
+%D \goto{do}[JS(My_Script{"test",123}),titlepage]
+%D \stoptyping
+%D
+%D This can also be achieved by:
+%D
+%D \starttyping
+%D \definereference[startup][JS(My_Script{"test",123}),titlepage]
+%D \goto{do}[startup]
+%D \stoptyping
+%D
+%D Now is this is a handy feature or not?
+%D
+%D \showsetup{definereference}
+%D
+%D We can trace references by setting the next switch to
+%D true.
+
+\unexpanded\def\definereference
+ {\dodoubleempty\strc_references_define_reference}
+
+\def\strc_references_define_reference[#name][#specification]%
+ {\clf_definereference{\referenceprefix}{#name}{\detokenize{#specification}}}
+
+\unexpanded\def\resetreference[#name]%
+ {\clf_resetreference{\referenceprefix}{#name}}
+
+\def\setpagereference#name#specification% hm,. low level ?
+ {\clf_definereference{}{#name}{\v!page(\detokenize{#specification}}} % is detokenize needed here?
+
+%D Chained references are defined as:
+%D
+%D \starttyping
+%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 \macros
+%D {highlighthyperlinks}
+%D
+%D The next switch can be used to make user hyperlinks are
+%D not highlighted when 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 opened.
+
+\newconditional\gotonewwindow \setfalse\gotonewwindow
+
+\def\expandtexincurrentreference % will happen in lua some time
+ {\ifcase\referencehastexstate\else\clf_expandcurrentreference\fi}
+
+\def\expandreferenceoperation#tag#content{\clf_setreferenceoperation#tag{#content}}
+\def\expandreferencearguments#tag#content{\clf_setreferencearguments#tag{#content}}
+
+\def\doifelsereferencefound#label#yes#nop%
+ {\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ #yes}%
+ {#nop}}
+
+\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 inner case is simple. Only two cases have to be taken
+%D care of:
+%D
+%D \starttyping
+%D \goto{some text}[reference]
+%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
+%D \starttyping
+%D \useexternaldocument[somefile][filename][a nice description]
+%D
+%D \goto{checked reference}[somefile::reference]
+%D \goto{unchecked reference}[somefile::]
+%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.
+
+\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).
+
+\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
+%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.
+
+\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
+%D \starttyping
+%D \thisissomeinternal{tag}{identifier}
+%D \gotosomeinternal {tag}{identifier}{pagenumber}{text}
+%D \stoptyping
+
+%D We could do this in lua ...
+
+\newif \iflocation
+\newcount\locationcount
+\newcount\locationorder
+\newbox \locationbox
+
+\def\nextinternalreference {\the\locationcount}
+\def\nextinternalorderreference{\the\locationorder}
+
+\def\setnextinternalreference
+ {\global\advance\locationcount\plusone}
+
+\def\setnextinternalreferences#kind#name% plural
+ {\clf_setnextinternalreference{#kind}{#name}}
+
+\def\getinternalorderreference#kind#name%
+ {\clf_currentreferenceorder{#kind}{#name}}
+
+\def\thisissomeinternal#kind#name% only for old time sake, will go away
+ {\begingroup
+ \clf_setinternalreference
+ reference {#kind:#name}% no view
+ \relax
+ \hbox attr \destinationattribute\lastdestinationattribute{}%
+ \endgroup}
+
+\installcorenamespace{savedinternalreference}
+
+\letvalue{\??savedinternalreference\s!default}\!!zerocount
+
+\unexpanded\def\storeinternalreference#1#2%
+ {\setxvalue{\??savedinternalreference\currentstructurename}{#2}}
+
+\newconditional\preferpagereferences
+
+\def\gotosomeinternal#kind#name#target#text%
+ {\ifconditional\preferpagereferences
+ \directgoto{#text}[page(#target)]%
+ \else
+ \directgoto{#text}[#kind:#name]%
+ \fi}
+
+\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
+%D An example of an action is:
+%D
+%D \starttyping
+%D \goto{some action}[PreviousJump]
+%D \stoptyping
+%D
+%D as well as:
+%D
+%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.
+
+\newcount\prefixcounter
+
+\newconditional\autocrossfilereferences
+
+\appendtoks
+ \edef\p_autofile{\referencingparameter\c!autofile}%
+ \ifx\p_autofile\v!yes
+ \settrue \autocrossfilereferences
+ \else
+ \setfalse\autocrossfilereferences
+ \fi
+\to \everysetupreferencing
+
+\appendtoks
+ \edef\p_export{\referencingparameter\c!export}%
+ \ifx\p_export\v!yes
+ \clf_exportreferences
+ \fi
+\to \everygoodbye
+
+\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}}}
+
+\unexpanded\def\globalpopreferenceprefix
+ {\xdef\referenceprefix{\clf_popreferenceprefix}}
+
+\unexpanded\def\pushreferenceprefix#prefix%
+ {\edef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
+
+\unexpanded\def\popreferenceprefix
+ {\edef\referenceprefix{\clf_popreferenceprefix}}
+
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\unexpanded\def\setupreferenceprefix[#prefix]%
+ {\edef\p_prefix{#prefix}%
+ \ifx\p_prefix\empty
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\m_strc_references_prefix_yes
+ \letreferencingparameter\c!prefix\s!unknown
+ \global\advance\prefixcounter\plusone
+ \edef\referenceprefix{\the\prefixcounter}%
+ \else\ifx\p_prefix\m_strc_references_prefix_nop
+ \letreferencingparameter\c!prefix\s!unknown
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\s!unknown
+ % forget about it
+ \else
+ \let\referenceprefix\p_prefix
+ \fi\fi\fi\fi}
+
+\appendtoks
+ \setupreferenceprefix[\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
+%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
+%D \placefigure
+%D [here][three calls]
+%D {Three alternatives reference calls.}
+%D {\startcombination[1*3]
+%D {\framed{\type{ \in }}} {a}
+%D {\framed{\type{ \at }}} {b}
+%D {\framed{\type{\goto}}} {c}
+%D \stopcombination}
+%D
+%D \startbuffer
+%D \in figure[fig:three calls]
+%D \in{figure}[fig:three calls]
+%D \in figure a[fig:three calls]
+%D \in{figure}{a}[fig:three calls]
+%D figure~\in[fig:three calls]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This turns up as:
+%D
+%D \startlines
+%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
+
+\appendtoks
+ \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi
+ \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \strc_references_at } \else \let\at \strc_references_at \fi
+ \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi
+ \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from \fi
+ \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi
+\to \everydump
+
+ \def\filterreference #key{\clf_filterreference{#key}} % no checking, expanded
+\unexpanded\def\getreferenceentry#key{\clf_filterreference{#key}} % no checking, unexpanded
+
+\def\currentreferencenumber {\clf_filterreference{number}}
+\def\currentreferencepage {\clf_filterreference{page}}
+\def\currentreferencetitle {\clf_filterreference{title}}
+\def\currentreferencetext {\clf_filterreference{text}}
+\def\currentreferencedefault {\clf_filterreference{default}}
+\def\currentreferencerealpage{\clf_filterreference{realpage}}
+
+%D The most straightforward way of retrieving references is
+%D using \type{\ref}.
+
+\unexpanded\def\getreference % checking, unexpanded
+ {\dodoubleargument\strc_references_get_reference}
+
+\def\strc_references_get_reference[#key][#label]% #key = number page title text default realpage ...
+ {\ifsecondargument
+ \doifelsereferencefound{#label}{\clf_filterreference{#key}}\dummyreference
+ \else
+ \dummyreference
+ \fi}
+
+\let\ref\getreference
+
+%D Special cases:
+
+\unexpanded\def\strc_references_about[#label]%
+ {\dontleavehmode
+ \begingroup
+ \let\crlf\space
+ \let\\\space
+ \postponenotes % might go
+ \referencingparameter\c!left
+ \doifelsereferencefound{#label}
+ {\goto{\limitatetext\currentreferencetitle{\referencingparameter\c!width}\unknown}[#label]}% not so efficient (dup lookup)
+ {}% todo
+ \flushnotes % might go
+ \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
+%D \starttyping
+%D ... \somewhere{backward text}{forward text}[someref] ...
+%D ... \atpage[someref] ...
+%D \stoptyping
+
+% standard detail
+%
+% 0 = unknown unknown
+% 1 = same on same page
+% 2 = before preceding page
+% 3 = after following page
+%
+% 4 = above above on same page
+% 5 = below below on same page
+
+% todo: optimize for use in pagebody
+% todo: maybe make it optional
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupreferencing [doublesided=no] % yes is default
+%
+% \somewhere{backward}{foreward}[label]
+% \someplace{preceding}{backward}{current}{foreward}{following}[label]
+% \atpage[#label]
+% \doifcheckedpagestate{label}{preceding}{backward}{current}{foreward}{following}{otherwise}
+%
+% \dorecurse {20} {
+% \placefigure[here][fig:#1]{}{\externalfigure[dummy]}
+% \dorecurse {20} {
+% ##1: \atpage[fig:##1] /
+% \doifcheckedpagestate
+% {fig:##1}
+% {preceding}{backward}{current}{foreward}{following}
+% {otherwise}
+% }
+% }
+
+\newcount \nofreferencestates
+\newconditional\pagestatespread
+
+\appendtoks
+ \doifelse{\referencingparameter\c!doublesided}\v!yes\settrue\setfalse\pagestatespread
+\to \everysetupreferencing
+
+\setupreferencing
+ [\c!doublesided=\v!yes]
+
+\def\referencepagestate
+ {\numexpr\clf_referencepagestate
+ {rst::\number\nofreferencestates}%
+ \relax}
+
+\def\referencepagedetail
+ {\numexpr\clf_referencepagestate
+ {rst::\number\nofreferencestates}%
+ true %
+ \ifconditional\pagestatespread false\ifdoublesided true\else false\fi\fi
+ \relax}
+
+\def\referencerealpage
+ {\clf_referencerealpage}
+
+\unexpanded\def\tracedpagestate
+ {{\blue\tttf(\ifcase\referencepagedetail unknown\or same\or previous\or next\or above\or below\else unknown\fi)}}
+
+\unexpanded\def\markreferencepage
+ {\dontleavehmode\begingroup
+ \iftrialtypesetting
+ % issue warning that not stable
+ \else
+ % needs checking ... but probably never in trialmode
+ \global\advance\nofreferencestates\plusone
+ \xypos{rst::\number\nofreferencestates}%
+ % \tracedpagestate
+ \fi
+ \endgroup}
+
+\unexpanded\def\doifcheckedpagestate#label% #preceding#backward#current#foreward#following#otherwise%
+ {\doifelsereferencefound{#label}\strc_references_handle_page_state_yes\strc_references_handle_page_state_nop}
+
+\let\strc_references_handle_page_state_nop\sixthofsixarguments
+
+\def\strc_references_handle_page_state_yes
+ {\markreferencepage
+ \ifcase\referencepagedetail
+ \expandafter\sixthofsixarguments \or
+ \expandafter\thirdofsixarguments \or
+ \expandafter\firstofsixarguments \or
+ \expandafter\fifthofsixarguments \or
+ \expandafter\secondofsixarguments\or
+ \expandafter\fourthofsixarguments\else
+ \expandafter\sixthofsixarguments \fi}
+
+\unexpanded\def\referencesymbol
+ {\hbox\bgroup
+ \strut
+ \markreferencepage
+ \high
+ {\setupsymbolset[\interactionparameter\c!symbolset]%
+ \symbol[\ifcase\referencepagedetail\v!somewhere\or\v!nowhere\or\v!previous\or\v!next\or\v!previous\or\v!next\else\v!somewhere\fi]}%
+ \egroup}
+
+%D Hereafter the \type {\ignorespaces} binds the state node to next character (more likely
+%D than a preceding one) and one can always add an explicit space.
+
+\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifcheckedpagestate{#label}%
+ {\goto{#backward}[#label]}%
+ {\goto{#backward}[#label]}%
+ {\ignorespaces}%
+ {\goto{#foreward}[#label]}%
+ {\goto{#foreward}[#label]}%
+ {#label}}%
+
+\unexpanded\def\someplace#preceding#backward#current#foreward#following#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifcheckedpagestate{#label}%
+ {\doifelsenothing{#preceding}{\goto{#preceding}[#label]}\ignorespaces}%
+ {\doifelsenothing {#backward}{\goto {#backward}[#label]}\ignorespaces}%
+ {\doifelsenothing {#current}{\goto {#current}[#label]}\ignorespaces}%
+ {\doifelsenothing {#foreward}{\goto {#foreward}[#label]}\ignorespaces}%
+ {\doifelsenothing{#following}{\goto{#following}[#label]}\ignorespaces}%
+ {#label}}
+
+\unexpanded\def\atpage[#label]% todo
+ {\doifcheckedpagestate{#label}%
+ {\goto{\labeltext \v!precedingpage }[#label]}%
+ {\goto{\labeltext \v!hencefore }[#label]}%
+ {\ignorespaces}%
+ {\goto{\labeltext \v!hereafter }[#label]}%
+ {\goto{\labeltext \v!followingpage }[#label]}%
+ {\goto{\labeltexts\v!page\dummyreference}[#label]}}
+
+% Someone requested this but in retrospect didn't need it so we keep it as example.
+% Beware: a node is injected which is why we add ignorespaces!
+%
+% \unexpanded\def\strc_references_conditional#action#text[#condition]#dummy[#label]%
+% {\doifcheckedpagestate{#label}%
+% {\doifelse{#condition}\v!precedingpage{#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!hencefore {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!current {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!hereafter {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!followingpage{#action{#text}[#label]}\ignorespaces}%
+% {#label}}
+%
+% \unexpanded\def\conditionalat {\strc_references_conditional\at}
+% \unexpanded\def\conditionalin {\strc_references_conditional\in}
+% \unexpanded\def\conditionalabout{\strc_references_conditional\about}
+
+%D The other alternatives just conform their names: only the label, only the text, or the
+%D label and the text.
+
+% \dounknownreference -> \dummyreference
+
+\def\symbolreference[#label]% for old times sake
+ {\goto{\referencesymbol}[#label]}
+
+% \referencecontentmode 0=all 1=label 2=text 3=symbol
+
+\newtoks\leftreferencetoks
+\newtoks\rightreferencetoks
+\newtoks\defaultleftreferencetoks
+\newtoks\defaultrightreferencetoks
+
+\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this
+\let\rightofreferencecontent \empty
+\let\leftofreference \empty
+\let\rightofreference \empty
+
+\installcorenamespace{referencinginteraction}
+
+\def\strc_references_interaction_all
+ {\the\leftreferencetoks
+ \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing
+ \leftofreference
+ \currentreferencecontent
+ \rightofreference
+ \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing
+ \the\rightreferencetoks}
+
+\letvalue{\??referencinginteraction\v!all}\strc_references_interaction_all
+
+\setvalue{\??referencinginteraction\v!label}%
+ {\leftofreference
+ \the\leftreferencetoks
+ \the\rightreferencetoks
+ \rightofreference}
+
+\setvalue{\??referencinginteraction\v!text}%
+ {\leftofreference
+ \currentreferencecontent
+ \rightofreference}
+
+\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
+ \else
+ \expandafter\strc_references_interaction_all
+ \fi}
+
+\newtoks\everyresetinatreference
+
+\appendtoks
+ \glet\leftofreference \relax
+ \glet\rightofreference\relax
+\to \everyresetinatreference
+
+\def\strc_references_start_goto
+ {\dontleavehmode
+ \begingroup}
+
+\def\strc_references_stop_goto
+ {\the\everyresetinatreference
+ \endgroup}
+
+\def\strc_references_pickup_goto
+ {\dodoublegroupempty\strc_references_pickup_goto_indeed}
+
+\def\strc_references_pickup_goto_indeed#left#right#dummy[#label]% #dummy gobbles spaces (really needed)
+ {\leftreferencetoks
+ \iffirstargument
+ {#left}%
+ \else
+ \defaultleftreferencetoks
+ \let\leftofreferencecontent\empty
+ \fi
+ \rightreferencetoks
+ \ifsecondargument
+ {#right}%
+ \else
+ \defaultrightreferencetoks
+ \let\rightofreferencecontent\empty
+ \fi
+ % inefficient: double resolve
+ \doifelsereferencefound{#label} % we need to resolve the text
+ {\goto{\referencesequence}[#label]}
+ {\let\currentreferencecontent\dummyreference
+ \goto{\referencesequence}[#label]}%
+ \strc_references_stop_goto}
+
+\unexpanded\def\strc_references_in
+ {\strc_references_start_goto
+ \let\currentreferencecontent\currentreferencedefault
+ \strc_references_pickup_goto}
+
+\unexpanded\def\strc_references_at
+ {\strc_references_start_goto
+ \let\currentreferencecontent\currentreferencepage
+ \strc_references_pickup_goto}
+
+%D \macros
+%D {definereferenceformat}
+%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
+%D \starttyping
+%D \definereferenceformat[informula] [left=(,right=),text=formula]
+%D \definereferenceformat[informulas] [left=(,right=),text=formulas]
+%D \definereferenceformat[andformula] [left=(,right=),text=and]
+%D \definereferenceformat[andformulas][left=(,right=),text=and]
+%D
+%D \informula [b] and \informula [for:c]
+%D the \informula {formulas}[b] \informula {and} [for:c]
+%D the \informulas {formulas}[b] \informula {and} [for:c]
+%D the \informulas [b] \informula {en} [for:c]
+%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
+%D Watch out: the second argument is somewhat special and mostly
+%D meant for a suffix to a number:
+%D
+%D \startbuffer
+%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~]
+%D \definereferenceformat [intestb] [left=(,right=),label=figure]
+%D
+%D \placeformula[x]\startformula a \stopformula
+%D
+%D \starttabulate[|||||]
+%D \NC \in [x] \NC \in {left}[x] \NC \in {}{right}[x] \NC \in {left}{right}[x] \NC \NR
+%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR
+%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% to be done: interfaced
+
+\installcorenamespace{referenceformat}
+
+\installcommandhandler \??referenceformat {referenceformat} \??referenceformat
+
+\appendtoks
+ \setuevalue\currentreferenceformat{\strc_references_apply_format{\currentreferenceformat}}%
+\to \everydefinereferenceformat
+
+\setupreferenceformat
+ [\c!left=,
+ \c!right=,
+ \c!text=,
+ \c!label=,
+ \c!autocase=\v!no,
+ \c!style=,
+ \c!type=default, % to be done: interfaced
+ \c!setups=,
+ \c!color=]
+
+\unexpanded\def\strc_references_apply_format#name%
+ {\strc_references_start_goto
+ \edef\currentreferenceformat{#name}%
+ \gdef\leftofreference {\referenceformatparameter\c!left }%
+ \gdef\rightofreference {\referenceformatparameter\c!right }%
+ \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }%
+ \edef\currentreferenceformattype {\referenceformatparameter\c!type }%
+ \edef\currentreferenceformatsetups {\referenceformatparameter\c!setups }%
+ \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}%
+ \usereferenceformatstyleandcolor\c!style\c!color
+ \ifx\currentstyleparameter\empty \else
+ \resetinteractionparameter\c!style
+ \fi
+ \ifx\currentcolorparameter\empty \else
+ \resetinteractionparameter\c!contrastcolor
+ \resetinteractionparameter\c!color
+ \fi
+ \ifx\currentreferenceformatlabel\autoreferencelabeltextflag
+ \edef\currentreferenceformatlabel{\autoreferencelabeltext}%
+ \fi
+ \ifx\currentreferenceformatautocase\v!yes
+ \setcharactercleaning[1]%
+ \fi
+ \ifx\currentreferenceformatlabel\empty
+ \defaultleftreferencetoks {\referenceformatparameter\c!text}%
+ \defaultrightreferencetoks\emptytoks
+ \else
+ \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}%
+ \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}%
+ \fi
+ \ifx\currentreferenceformattype\empty
+ \def\currentreferenceformattype{default}%
+ \fi
+ %
+ \ifx\currentreferenceformatsetups\empty
+ \def\currentreferencecontent{\filterreference\currentreferenceformattype}%
+ \else
+ \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}%
+ \fi
+ %
+ \let\leftofreferencecontent \empty
+ \let\rightofreferencecontent\empty
+ \strc_references_pickup_goto}
+
+\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
+
+\unexpanded\def\autoreferencelabeltext
+ {\clf_getcurrentreferencemetadata{name}}
+
+% \starttext
+% \definereferenceformat[inxx] [left=(,right=),text=txt]
+% \setupinteraction[state=start]
+% \chapter[one]{xx}
+% [\goto{state}[file(mk-last-state)]]
+% [\goto{state} [file(mk-last-state)]]
+% [\at{page} [one]]
+% [\at{page}[one]]
+% [\at{page}{okay}[one]]
+% [\inxx{a}{b}[one]]
+% \stoptext
+
+% \startsetups referenceformat:numberplustext
+% \filterreference{number}, \filterreference{title}
+% \stopsetups
+%
+% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
+
+%D In interactive documents going to a specific location is not
+%D bound to cross references. The \type{\goto} commands can be
+%D used to let users access another part of the document. In
+%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
+%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.
+
+% \starttext
+% \setupinteraction[state=start]
+% [\goto{state}[file(mk-last-state)]]
+% [\goto{state} [file(mk-last-state)]]
+% \stoptext
+
+\newconditional\uselocationstrut \settrue\uselocationstrut
+
+\def\extrareferencearguments
+ {highlight \luaconditional\highlighthyperlinks\space
+ newwindow \luaconditional\gotonewwindow\space
+ layer {\currentviewerlayer}}
+
+\unexpanded\def\directgoto
+ {\ifconditional\uselocationstrut
+ \expandafter\strc_references_direct_goto
+ \else
+ \expandafter\strc_references_direct_goto_htdp
+ \fi}
+
+\unexpanded\def\goto
+ {\ifconditional\uselocationstrut
+ \expandafter\strc_references_goto
+ \else
+ \expandafter\strc_references_goto_htdp
+ \fi}
+
+% The unbox trick is needed in order to permit \par inside a reference. Otherwise
+% the reference attribute migrates to the outer boxes.
+
+\newcount\lastsavedreferenceattribute
+
+\newbox\referencebox
+
+\def\revivesavedreferenceattribute % sometimes handy as no test etc needed
+ {\attribute\referenceattribute\lastsavedreferenceattribute}
+
+\def\strc_references_direct_goto#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \attribute\referenceattribute\attributeunsetvalue
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \ht\strutbox
+ depth \dp\strutbox
+ \extrareferencearguments
+ }%
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty % not here
+ #content%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\def\strc_references_direct_goto_htdp#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \dimexpr\interactionparameter\c!height\relax
+ depth \dimexpr\interactionparameter\c!depth \relax
+ \extrareferencearguments
+ }%
+ \relax
+ \setlocationattributes
+ \attribute\referenceattribute\lastreferenceattribute
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\def\strc_references_goto#content#dummy[#label]% #dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \ht\strutbox
+ \dp\strutbox
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ %\egroup\unhbox\referencebox}
+ \endgroup}
+
+\def\strc_references_goto_internal#content#dummy[#internal]% #dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \setstrut % can be option
+ \strc_references_get_simple_reference{internal(#internal)}%
+ \global\lastsavedreferenceattribute\currentreferenceattribute
+ \attribute\referenceattribute\currentreferenceattribute
+ \setlocationattributes
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\startgoto[#label]%
+ {\dontleavehmode
+ \begingroup
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandafter\strc_references_start_goto_yes}%
+ {\expandafter\strc_references_start_goto_nop}%
+ \else
+ \expandafter\strc_references_start_goto_nop
+ \fi}
+
+\unexpanded\def\strc_references_start_goto_nop
+ {\let\stopgoto\strc_references_stop_goto_nop}
+
+\unexpanded\def\strc_references_stop_goto_nop
+ {\endgroup}
+
+\unexpanded\def\strc_references_start_goto_yes
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \ht\strutbox
+ \dp\strutbox
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \let\stopgoto\strc_references_stop_goto_yes}
+
+\unexpanded\def\strc_references_stop_goto_yes
+ {\dostoptagged
+ \endgroup}
+
+\def\strc_references_goto_htdp#content#dummy[#label]% dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \dimexpr\interactionparameter\c!height\relax
+ \dimexpr\interactionparameter\c!depth \relax
+ \relax
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotobox#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \setlocationcolorspec{#resolver}% no consequence for strut
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\gotobox#content[#label]%
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreference
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox#width%
+ \ht\scratchbox#height%
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\clf_injectcurrentreference
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \hbox 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
+%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
+%D \showsetup{useexternaldocument}
+%D
+%D For example:
+%D
+%D \starttyping
+%D \useexternaldocument
+%D [dictionary][engldict]
+%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
+%D The \URL\ alternative takes four arguments:
+%D
+%D \showsetup{useURL}
+%D
+%D like:
+%D
+%D \starttyping
+%D \useURL
+%D [dictionary][http://www.publisher.com/public][engldict]
+%D [The Famous English Dictionary]
+%D \stoptyping
+%D
+%D Several specifications are possible:
+%D
+%D \starttyping
+%D \useURL [id] [url] [file] [description]
+%D \useURL [id] [url] [file]
+%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.
+
+\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments
+\unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments
+
+\let\useURL \useurl
+\let\useexternaldocument\usefile
+
+\def\strc_references_use_url[#label][#url][#file][#description]%
+ {\clf_useurl{#label}{\detokenize{#url}}{\detokenize{#file}}{\detokenize{#description}}}
+
+\def\strc_references_use_file[#label][#file][#description]%
+ {\clf_usefile{#label}{\detokenize{#file}}{\detokenize{#description}}}
+
+\def\doifelseurldefined #label{\clf_doifelseurldefined {#label}}
+\def\doifelsefiledefined#label{\clf_doifelsefiledefined{#label}}
+
+\let\doifurldefinedelse \doifelseurldefined
+\let\doiffiledefinedelse\doifelsefiledefined
+
+%D \macros
+%D {url,setupurl}
+%D
+%D We also have: \type{\url} for directly calling the
+%D description. So we can say:
+%D
+%D \starttyping
+%D \useURL [one] [http://www.test.nl]
+%D \useURL [two] [http://www.test.nl] [] [Some Site]
+%D
+%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)]
+%D \stoptyping
+%D
+%D An \URL\ can be set up with
+%D
+%D \showsetup{setupurl}
+
+\installcorenamespace{url}
+
+\installdirectcommandhandler \??url {url}
+
+\setupurl
+ [\c!style=\v!type,
+ \c!color=]
+
+\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
+ {\dontleavehmode
+ \begingroup
+ \useurlstyleandcolor\c!style\c!color
+ \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
+%D \startbuffer
+%D \useURL
+%D [test]
+%D [sentence_sentence~sentence//sentence:sentence.sentence]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Such an \URL\ is, depending on the settings, hyphenated as:
+%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
+%D \showsetup{from}
+%D
+%D We keep this for compatibility reasons, hence the hackery.
+
+\unexpanded\def\strc_references_from
+ {\dosingleempty\strc_references_do_special_from}
+
+\def\strc_references_do_special_from[#label]%
+ {\dontleavehmode
+ \goto{\clf_from{#label}}[fileorurl(#label)]}
+
+\def\dofromurldescription#content% called at the lua end
+ {#content}
+
+\def\dofromurlliteral#content% called at the lua end
+ {\useurlstyleandcolor\c!style\c!color
+ \hyphenatedurl{#content}}
+
+\let\dofromfiledescription\dofromurldescription
+\let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url
+
+%D We also support:
+%D
+%D \starttyping
+%D \goto{some text}[file(identifier{location}]
+%D \stoptyping
+%D
+%D which is completely equivalent with
+%D
+%D \starttyping
+%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
+%D \showsetup{setupprograms}
+%D \showsetup{defineprogram}
+%D \showsetup{program} % changed functionality !
+%D
+%D The latter gives access to the description of the program,
+%D being the last argument to the definition command.
+
+% also lua, like urls and files
+
+\installcorenamespace{programs}
+
+\installdirectcommandhandler \??programs {programs}
+
+\unexpanded\def\defineprogram
+ {\dotripleargument\strc_references_define_program}
+
+\def\strc_references_define_program[#name][#program][#description]%
+ {\clf_defineprogram{#name}{#program}{#description}}
+
+\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
+%D \starttyping
+%D \goto{some text}[program(name{args})]
+%D \stoptyping
+%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
+%D \starttyping
+%D \gotopage{some text}[location]
+%D \gotopage{some text}[number]
+%D \gotopage{some text}[file::number]
+%D \stoptyping
+%D
+%D as well as:
+%D
+%D \starttyping
+%D \goto{some text}[page(location)]
+%D \goto{some text}[page(number)]
+%D \goto{some text}[file::page(number)]
+%D \stoptyping
+%D
+%D Here location is a keyword like \type{nextpage}.
+%D
+%D \showsetup{gotopage}
+
+\unexpanded\def\definepage
+ {\dodoubleargument\strc_references_define_page}
+
+\def\strc_references_define_page[#name][#target]%
+ {\definereference[#name][page(#target)]}
+
+\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 We can cross link documents by using:
+%D
+%D \showsetup{coupledocument}
+%D
+%D like:
+%D
+%D \starttyping
+%D \coupledocument[print][somefile][chapter,section]
+%D \stoptyping
+%D
+%D After which when applicable, we have available the
+%D 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.
+
+\def\coupledocument
+ {\doquadrupleempty\strc_references_couple_document}
+
+\def\strc_references_couple_document[#name][#file][#sections][#description]%
+ {\ifthirdargument
+ % this will be done differently (when it's needed)
+ \fi}
+
+%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
+%D \starttyping
+%D \dotextprefix{text}
+%D \stoptyping
+%D
+%D Only when \type {text} is not empty, a space is inserted.
+
+\unexpanded\def\dotextprefix#text%
+ {\begingroup
+ \setbox\scratchbox\hbox{#text}% to be solved some day
+ \ifdim\wd\scratchbox>\zeropoint
+ \unhbox\scratchbox
+ \edef\p_separator{\referencingparameter\c!separator}%
+ \ifx\p_separator\empty \else
+ \removeunwantedspaces % remove is new
+ \p_separator
+ \fi
+ \else
+ \unhbox\scratchbox
+ \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.
+
+\setupreferencing
+ [\c!state=\v!start,
+ \c!autofile=\v!no,
+ \v!part\c!number=\v!yes,
+ \v!chapter\c!number=\v!no,
+ \c!interaction=\v!all,
+ \c!convertfile=\v!no,
+ %\c!strut=\v!no, % some day an option
+ \c!prefix=,
+ \c!width=.75\makeupwidth,
+ \c!left=\quotation\bgroup,
+ \c!right=\egroup,
+ \c!global=\v!no,
+ \c!expansion=\v!no,
+ \c!separator=\nonbreakablespace,
+ \c!export=\v!no]
+
+\setupprograms
+ [\c!directory=,
+ \c!style=\v!type,
+ \c!color=]
+
+\definereference [\v!CloseDocument ] [action(close)]
+\definereference [\v!ExitViewer ] [action(exit)]
+\definereference [\v!FirstPage ] [action(first)]
+\definereference [\v!LastPage ] [action(last)]
+\definereference [\v!NextJump ] [action(forward)]
+\definereference [\v!NextPage ] [action(next)]
+\definereference [\v!PauseMovie ] [action(pausemovie)]
+\definereference [\v!PauseSound ] [action(pausesound)]
+\definereference [\v!PauseRendering ] [action(pauserendering)]
+\definereference [\v!PreviousJump ] [action(backward)]
+\definereference [\v!PreviousPage ] [action(previous)]
+\definereference [\v!PrintDocument ] [action(print)]
+\definereference [\v!SaveForm ] [action(exportform)]
+\definereference [\v!LoadForm ] [action(importform)]
+\definereference [\v!ResetForm ] [action(resetform)]
+\definereference [\v!ResumeMovie ] [action(resumemovie)]
+\definereference [\v!ResumeSound ] [action(resumesound)]
+\definereference [\v!ResumeRendering ] [action(resumerendering)]
+\definereference [\v!SaveDocument ] [action(save)]
+\definereference [\v!SaveNamedDocument] [action(savenamed)]
+\definereference [\v!OpenNamedDocument] [action(opennamed)]
+\definereference [\v!SearchDocument ] [action(search)]
+\definereference [\v!SearchAgain ] [action(searchagain)]
+\definereference [\v!StartMovie ] [action(startmovie)]
+\definereference [\v!StartSound ] [action(startsound)]
+\definereference [\v!StartRendering ] [action(startrendering)]
+\definereference [\v!StopMovie ] [action(stopmovie)]
+\definereference [\v!StopSound ] [action(stopsound)]
+\definereference [\v!StopRendering ] [action(stoprendering)]
+\definereference [\v!SubmitForm ] [action(submitform)]
+\definereference [\v!ToggleViewer ] [action(toggle)]
+\definereference [\v!ViewerHelp ] [action(help)]
+\definereference [\v!HideField ] [action(hide)]
+\definereference [\v!ShowField ] [action(show)]
+\definereference [\v!GotoPage ] [action(gotopage)]
+\definereference [\v!Query ] [action(query)]
+\definereference [\v!QueryAgain ] [action(queryagain)]
+\definereference [\v!FitWidth ] [action(fitwidth)]
+\definereference [\v!FitHeight ] [action(fitheight)]
+\definereference [\v!ShowThumbs ] [action(thumbnails)]
+\definereference [\v!ShowBookmarks ] [action(bookmarks)]
+
+\definereference [\v!HideLayer ] [action(hidelayer)]
+\definereference [\v!VideLayer ] [action(videlayer)]
+\definereference [\v!ToggleLayer ] [action(togglelayer)]
+
+\definereference [\v!firstpage] [page(firstpage)]
+\definereference [\v!previouspage] [page(previouspage)]
+\definereference [\v!nextpage] [page(nextpage)]
+\definereference [\v!lastpage] [page(lastpage)]
+\definereference [\v!forward] [page(forward)]
+\definereference [\v!backward] [page(backward)]
+\definereference [\v!firstsubpage] [page(firstsubpage)]
+\definereference [\v!previoussubpage] [page(previoussubpage)]
+\definereference [\v!nextsubpage] [page(nextsubpage)]
+\definereference [\v!lastsubpage] [page(lastsubpage)]
+
+% we can do this but only when later in resolve (else problems with \chapter[first]{...}
+%
+% \definereference [\v!first] [page(firstpage)]
+% \definereference [\v!previous] [page(prevpage)]
+% \definereference [\v!next] [page(nextpage)]
+% \definereference [\v!last] [page(lastpage)]
+% \definereference [\v!first\v!sub] [page(firstsubpage)]
+% \definereference [\v!previous\v!sub] [page(prevsubpage)]
+% \definereference [\v!next\v!sub] [page(nextsubpage)]
+% \definereference [\v!last\v!sub] [page(lastsubpage)]
+
+%D We cannot set up buttons (not yet, this one calls a menu macro):
+
+%D New (and experimental):
+
+% \starttext
+% \chapter{test}
+% \placefigure[here][xx:1]{}{\framed{one}} \placefigure[here][xx:2]{}{\framed{three}}
+% \placetable [here][xx:3]{}{\framed{two}} \placetable [here][xx:4]{}{\framed{four}}
+% \start
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[float][default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[figure][default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank
+% \stoptext
+
+% todo: parameterhandler
+
+\installcorenamespace{referencingprefix}
+
+\def\getreferencestructureprefix#kind#name#category% name will change
+ {{%
+ prefix {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix}%
+ separatorset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset}%
+ conversion {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion}%
+ conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset}%
+ starter {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstarter}%
+ stopper {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstopper}%
+ set {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset}%
+ segments {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments}%
+ connector {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector}%
+ }%
+ {%
+ separatorset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberseparatorset}%
+ conversion {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversion}%
+ conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversionset}%
+ starter {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstarter}%
+ stopper {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstopper}%
+ segments {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numbersegments}%
+ }}
+
+\unexpanded\def\setupreferencestructureprefix
+ {\dotripleempty\strc_references_setup_reference_structure_prefix}
+
+\def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]%
+ {\ifthirdargument
+ \getparameters[\??referencingprefix#kind:#category][#settings]%
+ \else\ifsecondargument
+ \getparameters[\??referencingprefix:#kind][#category]%
+ \fi\fi}
+
+\def\referencestructureprefixparameter#kind#name#category#parameter%
+ {\ifcsname\??referencingprefix#name:#category#parameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\??referencingprefix:#category#parameter\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\def\currentreferencedefault % for some reason we need to explicitly expand
+ {\normalexpanded{\noexpand\clf_filterdefaultreference
+ {\s!default}%
+ \noexpand\getreferencestructureprefix\clf_getcurrentprefixspec{\s!default}% returns #kind#name#category
+ \relax}}
+
+%D Not all support is visible by looking at the \TEX\ code; here is one of those:^
+%D
+%D \starttyping
+%D \startinteractionmenu[right]
+%D \startbut [section(first {chapter})] first chapter \stopbut
+%D \startbut [section(previous{chapter})] previous chapter \stopbut
+%D \startbut [section(next {chapter})] next chapter \stopbut
+%D \startbut [section(last {chapter})] last chapter \stopbut
+%D \blank[2*big]
+%D \startbut [section(first {section})] first section \stopbut
+%D \startbut [section(previous{section})] previous section \stopbut
+%D \startbut [section(next {section})] next section \stopbut
+%D \startbut [section(last {section})] last section \stopbut
+%D \stopinteractionmenu
+%D \stoptyping
+
+%D Relatively new:
+%D
+%D \starttyping
+%D \chapter{The never ending story}
+%D
+%D \section{An ending story}
+%D
+%D \in{chapter}[match(complex bibliographies)]
+%D \in{chapter}[match(never ending)]
+%D \in{chapter}[match(ending)]
+%D \in{chapter}[match(chapter:never ending)]
+%D \in{chapter}[match(chapter:ending)]
+%D \in{section}[match(section:ending)]
+%D \in{figure}[match(float:mess)]
+%D \in{figure}[match(figure:mess)]
+%D \in{figure (not found)}[match(section:mess)]
+%D \in{figure (not found)}[match(section:xxxx)]
+%D \in{figure}[match(mess)]
+%D
+%D \placefigure{What a mess}{}
+%D
+%D \chapter{About complex bibliographies}
+%D
+%D \in{chapter}[match(complex bibliographies)]
+%D \in{chapter}[match(never ending)]
+%D \in{figure}[match(mess)]
+%D \stoptyping
+
+%D Tracing:
+
+\unexpanded\def\strc_references_tracer#1#2% \csleft csright
+ {\hbox to \zeropoint \bgroup
+ \hss
+ \infofont
+ \darkblue
+ \ifx#1\empty\else
+ \raise\strutht \hbox \s!to \zeropoint \bgroup
+ \hss#1\hskip.2\emwidth
+ \egroup
+ \fi
+ \vrule \s!height 1.5\strutht \s!depth \strutdp \s!width .1\emwidth
+ \ifx#2\empty\else
+ \raise\strutht \hbox \s!to \zeropoint \bgroup
+ \hskip.2\emwidth#2\hss
+ \egroup
+ \fi
+ \hss
+ \egroup}%
+
+\protect \endinput
+
+% tricky:
+%
+% \enabletrackers[nodes.references]
+% \setupinteraction[state=start]
+% \def\KnuthTest{\input knuth }
+% \def\KnuthTest{\input tufte }
+% \def\TufteTest{\input tufte }
+% \defineoverlay[xxx][\overlaybutton{page(3)}]
+% \setupbackgrounds[text][background=xxx]
+% \starttext
+% test {\red \KnuthTest} test \par
+% \button{test}[page(1)] \par
+% \goto{page 2 \TeX}[page(2)] \goto{page 2 \TeX}[page(2)] \goto{\TufteTest}[page(2)] test \page
+% test \goto{page 3}[page(3)] \goto{\TufteTest\space\par\TufteTest}[page(4)] test \page
+% \goto{page 1}[page(1)] \goto{\TufteTest\space test}[page(1)] \page
+% \goto{page 1}[page(1)] \goto{\KnuthTest\space test}[page(1)] \page
+% test \goto{page 1}[page(1)] {\goto{\KnuthTest\space test}[page(1)]} test
+% \goto{page 1}[page(1)] \goto{\TufteTest}[page(1)] test \page
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua
new file mode 100644
index 00000000000..4efbe038b3d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua
@@ -0,0 +1,1354 @@
+if not modules then modules = { } end modules ['strc-reg'] = {
+ version = 1.001,
+ comment = "companion to strc-reg.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+local format, gmatch = string.format, string.gmatch
+local equal, concat, remove = table.are_equal, table.concat, table.remove
+local utfchar = utf.char
+local lpegmatch = lpeg.match
+local allocate = utilities.storage.allocate
+
+local trace_registers = false trackers.register("structures.registers", function(v) trace_registers = v end)
+
+local report_registers = logs.reporter("structure","registers")
+
+local structures = structures
+local registers = structures.registers
+local helpers = structures.helpers
+local sections = structures.sections
+local documents = structures.documents
+local pages = structures.pages
+local references = structures.references
+
+local usedinternals = references.usedinternals
+
+local mappings = sorters.mappings
+local entries = sorters.entries
+local replacements = sorters.replacements
+
+local processors = typesetters.processors
+local splitprocessor = processors.split
+
+local texgetcount = tex.getcount
+
+local variables = interfaces.variables
+local v_forward = variables.forward
+local v_all = variables.all
+local v_yes = variables.yes
+local v_current = variables.current
+local v_previous = variables.previous
+local v_text = variables.text
+
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local matchingtilldepth = sections.matchingtilldepth
+local numberatdepth = sections.numberatdepth
+local currentlevel = sections.currentlevel
+local currentid = sections.currentid
+
+local touserdata = helpers.touserdata
+
+local internalreferences = references.internals
+local setinternalreference = references.setinternalreference
+
+local setmetatableindex = table.setmetatableindex
+local texsetattribute = tex.setattribute
+
+local a_destination = attributes.private('destination')
+
+local absmaxlevel = 5 -- \c_strc_registers_maxlevel
+
+local h_prefixpage = helpers.prefixpage
+local h_prefixlastpage = helpers.prefixlastpage
+local h_title = helpers.title
+
+local ctx_startregisteroutput = context.startregisteroutput
+local ctx_stopregisteroutput = context.stopregisteroutput
+local ctx_startregistersection = context.startregistersection
+local ctx_stopregistersection = context.stopregistersection
+local ctx_startregisterentries = context.startregisterentries
+local ctx_stopregisterentries = context.stopregisterentries
+local ctx_startregisterentry = context.startregisterentry
+local ctx_stopregisterentry = context.stopregisterentry
+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
+
+-- possible export, but ugly code (overloads)
+--
+-- local output, section, entries, nofentries, pages, words, rawtext
+--
+-- h_title = function(a,b) rawtext = a end
+--
+-- local function ctx_startregisteroutput()
+-- output = { }
+-- section = nil
+-- entries = nil
+-- nofentries = nil
+-- pages = nil
+-- words = nil
+-- rawtext = nil
+-- end
+-- local function ctx_stopregisteroutput()
+-- inspect(output)
+-- output = nil
+-- section = nil
+-- entries = nil
+-- nofentries = nil
+-- pages = nil
+-- words = nil
+-- rawtext = nil
+-- end
+-- local function ctx_startregistersection(tag)
+-- section = { }
+-- output[#output+1] = {
+-- section = section,
+-- tag = tag,
+-- }
+-- end
+-- local function ctx_stopregistersection()
+-- end
+-- local function ctx_startregisterentries(n)
+-- entries = { }
+-- nofentries = 0
+-- section[#section+1] = entries
+-- end
+-- local function ctx_stopregisterentries()
+-- end
+-- local function ctx_startregisterentry(n) -- or subentries (nested?)
+-- nofentries = nofentries + 1
+-- entry = { }
+-- entries[nofentries] = entry
+-- end
+-- local function ctx_stopregisterentry()
+-- nofentries = nofentries - 1
+-- entry = entries[nofentries]
+-- end
+-- local function ctx_startregisterpages()
+-- pages = { }
+-- entry.pages = pages
+-- end
+-- local function ctx_stopregisterpages()
+-- end
+-- local function ctx_startregisterseewords()
+-- words = { }
+-- entry.words = words
+-- end
+-- local function ctx_stopregisterseewords()
+-- end
+-- local function ctx_registerentry(processor,internal,seeparent,text)
+-- text()
+-- entry.text = {
+-- processor = processor,
+-- internal = internal,
+-- seeparent = seeparent,
+-- text = rawtext,
+-- }
+-- end
+-- local function ctx_registerseeword(i,n,processor,internal,seeindex,seetext)
+-- seetext()
+-- entry.words[i] = {
+-- processor = processor,
+-- internal = internal,
+-- seeparent = seeparent,
+-- seetext = rawtext,
+-- }
+-- end
+-- local function ctx_registerpagerange(fprocessor,finternal,frealpage,lprocessor,linternal,lrealpage)
+-- pages[#pages+1] = {
+-- first = {
+-- processor = fprocessor,
+-- internal = finternal,
+-- realpage = frealpage,
+-- },
+-- last = {
+-- processor = lprocessor,
+-- internal = linternal,
+-- realpage = lrealpage,
+-- },
+-- }
+-- end
+-- local function ctx_registeronepage(processor,internal,realpage)
+-- pages[#pages+1] = {
+-- processor = processor,
+-- internal = internal,
+-- realpage = realpage,
+-- }
+-- end
+
+-- some day we will share registers and lists (although there are some conceptual
+-- differences in the application of keywords)
+
+local function filtercollected(names,criterium,number,collected,prevmode)
+ if not criterium or criterium == "" then
+ criterium = v_all
+ end
+ local data = documents.data
+ local numbers = data.numbers
+ local depth = data.depth
+ local hash = { }
+ local result = { }
+ local nofresult = 0
+ local all = not names or names == "" or names == v_all
+ local detail = nil
+ if not all then
+ for s in gmatch(names,"[^, ]+") do
+ hash[s] = true
+ end
+ end
+ if criterium == v_all or criterium == v_text then
+ for i=1,#collected do
+ local v = collected[i]
+ if all then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ else
+ local vmn = v.metadata and v.metadata.name
+ if hash[vmn] then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ elseif criterium == v_current then
+ local collectedsections = sections.collected
+ for i=1,#collected do
+ local v = collected[i]
+ local sectionnumber = collectedsections[v.references.section]
+ if sectionnumber then
+ local cnumbers = sectionnumber.numbers
+ if prevmode then
+ if (all or hash[v.metadata.name]) and #cnumbers >= depth then -- is the = ok for lists as well?
+ local ok = true
+ for d=1,depth do
+ if not (cnumbers[d] == numbers[d]) then -- no zero test
+ ok = false
+ break
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ else
+ if (all or hash[v.metadata.name]) and #cnumbers > depth then
+ local ok = true
+ for d=1,depth do
+ local cnd = cnumbers[d]
+ if not (cnd == 0 or cnd == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ elseif criterium == v_previous then
+ local collectedsections = sections.collected
+ for i=1,#collected do
+ local v = collected[i]
+ local sectionnumber = collectedsections[v.references.section]
+ if sectionnumber then
+ local cnumbers = sectionnumber.numbers
+ if (all or hash[v.metadata.name]) and #cnumbers >= depth then
+ local ok = true
+ if prevmode then
+ for d=1,depth do
+ if not (cnumbers[d] == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ else
+ for d=1,depth do
+ local cnd = cnumbers[d]
+ if not (cnd == 0 or cnd == numbers[d]) then
+ ok = false
+ break
+ end
+ end
+ end
+ if ok then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ elseif criterium == variables["local"] then
+ if sections.autodepth(data.numbers) == 0 then
+ return filtercollected(names,v_all,number,collected,prevmode)
+ else
+ return filtercollected(names,v_current,number,collected,prevmode)
+ end
+ else -- sectionname, number
+ -- beware, this works ok for registers
+ -- to be redone with reference instead
+ local depth = sections.getlevel(criterium)
+ local number = tonumber(number) or numberatdepth(depth) or 0
+ if trace_registers then
+ detail = format("depth: %s, number: %s, numbers: %s, startset: %s",depth,number,concat(sections.numbers(),".",1,depth),#collected)
+ end
+ if number > 0 then
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ if r then
+ local sectionnumber = sections.collected[r.section]
+ if sectionnumber then
+ local metadata = v.metadata
+ local cnumbers = sectionnumber.numbers
+ if cnumbers then
+ if (all or hash[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers) then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if trace_registers then
+ if detail then
+ report_registers("criterium %a, detail %a, found %a",criterium,detail,#result)
+ else
+ report_registers("criterium %a, detail %a, found %a",criterium,nil,#result)
+ end
+ end
+ return result
+end
+
+local tobesaved = allocate()
+local collected = allocate()
+
+registers.collected = collected
+registers.tobesaved = tobesaved
+registers.filtercollected = filtercollected
+
+-- we follow a different strategy than by lists, where we have a global
+-- result table; we might do that here as well but since sorting code is
+-- older we delay that decision
+
+-- maybe store the specification in the format (although we predefine only
+-- saved registers)
+
+local function checker(t,k)
+ local v = {
+ metadata = {
+ language = 'en',
+ sorted = false,
+ class = class,
+ },
+ entries = { },
+ }
+ t[k] = v
+ return v
+end
+
+local function initializer()
+ tobesaved = registers.tobesaved
+ collected = registers.collected
+ setmetatableindex(tobesaved,checker)
+ setmetatableindex(collected,checker)
+ local usedinternals = references.usedinternals
+ for name, list in next, collected do
+ local entries = list.entries
+ if not list.metadata.notsaved then
+ for e=1,#entries do
+ local entry = entries[e]
+ local r = entry.references
+ if r then
+ local internal = r and r.internal
+ if internal then
+ internalreferences[internal] = entry
+ usedinternals[internal] = r.used
+ end
+ end
+ end
+ end
+ end
+end
+
+local function finalizer()
+ local flaginternals = references.flaginternals
+ local usedviews = references.usedviews
+ for k, v in next, tobesaved do
+ local entries = v.entries
+ if entries then
+ for i=1,#entries do
+ local r = entries[i].references
+ if r then
+ local i = r.internal
+ local f = flaginternals[i]
+ if f then
+ r.used = usedviews[i] or true
+ end
+ end
+ end
+ end
+ end
+end
+
+job.register('structures.registers.collected', tobesaved, initializer, finalizer)
+
+setmetatableindex(tobesaved,checker)
+setmetatableindex(collected,checker)
+
+local function defineregister(class,method)
+ local d = tobesaved[class]
+ if method == v_forward then
+ d.metadata.notsaved = true
+ end
+end
+
+registers.define = defineregister -- 4 times is somewhat over the top but we want consistency
+registers.setmethod = defineregister -- and we might have a difference some day
+
+implement {
+ name = "defineregister",
+ actions = defineregister,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "setregistermethod",
+ actions = defineregister, -- duplicate use
+ arguments = { "string", "string" }
+}
+
+local entrysplitter = lpeg.tsplitat('+') -- & obsolete in mkiv
+
+local tagged = { }
+
+-- this whole splitting is an inheritance of mkii
+
+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
+ local entryproc = processors and processors.entry
+ local pageproc = processors and processors.page
+ if entryproc == "" then
+ entryproc = nil
+ end
+ if pageproc == "" then
+ pageproc = nil
+ end
+ if not et then
+ local p, e = splitprocessor(entries.entry or "")
+ if p then
+ entryproc = p
+ end
+ et = lpegmatch(entrysplitter,e)
+ end
+ if not kt then
+ local p, k = splitprocessor(entries.key or "")
+ if p then
+ pageproc = p
+ end
+ kt = lpegmatch(entrysplitter,k)
+ end
+ --
+ entries = { }
+ local ok = false
+ for k=#et,1,-1 do
+ local etk = et[k]
+ local ktk = kt[k]
+ if not ok and etk == "" then
+ entries[k] = nil
+ else
+ entries[k] = { etk or "", ktk ~= "" and ktk or nil }
+ ok = true
+ end
+ end
+ rawdata.list = entries
+ if pageproc or entryproc then
+ rawdata.processors = { entryproc, pageproc } -- old way: indexed .. will be keys
+ end
+ rawdata.entries = nil
+ end
+ local seeword = rawdata.seeword
+ if seeword then
+ seeword.processor, seeword.text = splitprocessor(seeword.text or "")
+ end
+end
+
+local function storeregister(rawdata) -- metadata, references, entries
+ local references = rawdata.references
+ local metadata = rawdata.metadata
+ -- checking
+ if not metadata then
+ metadata = { }
+ rawdata.metadata = metadata
+ end
+ --
+ if not metadata.kind then
+ metadata.kind = "entry"
+ end
+ --
+ if not metadata.catcodes then
+ metadata.catcodes = tex.catcodetable -- get
+ end
+ --
+ local name = metadata.name
+ local notsaved = tobesaved[name].metadata.notsaved
+ --
+ if not references then
+ references = { }
+ rawdata.references = references
+ end
+ --
+ local internal = references.internal
+ if not internal then
+ internal = texgetcount("locationcount") -- we assume that it has been set
+ references.internal = internal
+ end
+ --
+ if notsaved then
+ usedinternals[internal] = references.used -- todo view (we assume that forward references index entries are used)
+ end
+ --
+ if not references.realpage then
+ references.realpage = 0 -- just to be sure as it can be refered to
+ end
+ --
+ local userdata = rawdata.userdata
+ if userdata then
+ rawdata.userdata = touserdata(userdata)
+ end
+ --
+ references.section = currentid()
+ metadata.level = currentlevel()
+ --
+ local data = notsaved and collected[name] or tobesaved[name]
+ local entries = data.entries
+ internalreferences[internal] = rawdata
+ preprocessentries(rawdata)
+ entries[#entries+1] = rawdata
+ local label = references.label
+ if label and label ~= "" then
+ tagged[label] = #entries
+ else
+ references.label = nil
+ end
+ return #entries
+end
+
+registers.store = storeregister
+
+function registers.enhance(name,n)
+ local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name]
+ 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
+ if type(tag) == "string" then
+ tag = tagged[tag]
+ end
+ if tag then
+ local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name]
+ local entry = data.entries[tag]
+ if entry then
+ local references = entry.references
+ references.lastrealpage = texgetcount("realpageno")
+ references.lastsection = currentid()
+ if rawdata then
+ local userdata = rawdata.userdata
+ if userdata then
+ rawdata.userdata = touserdata(userdata)
+ end
+ if rawdata.entries then
+ preprocessentries(rawdata)
+ end
+ local metadata = rawdata.metadata
+ if metadata and not metadata.catcodes then
+ metadata.catcodes = tex.catcodetable -- get
+ end
+ for k, v in next, rawdata do
+ local rk = references[k]
+ if not rk then
+ references[k] = v
+ else
+ for kk, vv in next, v do
+ if type(vv) == "table" then
+ if next(vv) then
+ rk[kk] = vv
+ end
+ elseif vv ~= "" then
+ rk[kk] = vv
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function registers.get(tag,n)
+ local list = tobesaved[tag]
+ return list and list.entries[n]
+end
+
+implement {
+ name = "enhanceregister",
+ actions = registers.enhance,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "extendregister",
+ actions = registers.extend,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "storeregister",
+ -- actions = function(rawdata)
+ -- local nofentries = storeregister(rawdata)
+ -- setinternalreference { internal = rawdata.references.internal }
+ -- context(nofentries)
+ -- end,
+ actions = { storeregister, context },
+ arguments = {
+ {
+ { "metadata", {
+ { "kind" },
+ { "name" },
+ { "coding" },
+ { "level", "integer" },
+ { "catcodes", "integer" },
+ { "own" },
+ { "xmlroot" },
+ { "xmlsetup" }
+ }
+ },
+ { "entries", {
+ { "entries", "list" },
+ { "keys", "list" },
+ { "entry" },
+ { "key" }
+ }
+ },
+ { "references", {
+ { "internal", "integer" },
+ { "section", "integer" },
+ { "view" },
+ { "label" }
+ }
+ },
+ { "seeword", {
+ { "text" }
+ }
+ },
+ { "processors", {
+ { "entry" },
+ { "key" },
+ { "page" }
+ }
+ },
+ { "userdata" },
+ }
+ }
+}
+
+-- sorting and rendering
+
+local compare = sorters.comparers.basic
+
+function registers.compare(a,b)
+ local result = compare(a,b)
+ if result ~= 0 then
+ return result
+ else
+ 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
+ if not page_a or not page_b then
+ return 0
+ elseif page_a < page_b then
+ return -1
+ elseif page_a > page_b then
+ return 1
+ end
+ elseif ka == "see" then
+ return 1
+ elseif kb == "see" then
+ return -1
+ end
+ end
+ return 0
+end
+
+function registers.filter(data,options)
+ data.result = registers.filtercollected(nil,options.criterium,options.number,data.entries,true)
+end
+
+local seeindex = 0
+
+-- meerdere loops, seewords, dan words, anders seewords
+
+local function crosslinkseewords(result) -- all words
+ -- collect all seewords
+ local seewords = { }
+ for i=1,#result do
+ local data = result[i]
+ local seeword = data.seeword
+ if seeword then
+ local seetext = seeword.text
+ if seetext and not seewords[seetext] then
+ seeindex = seeindex + 1
+ seewords[seetext] = seeindex
+ if trace_registers then
+ report_registers("see word %03i: %s",seeindex,seetext)
+ end
+ end
+ end
+ end
+ -- mark seeparents
+ local seeparents = { }
+ for i=1,#result do
+ local data = result[i]
+ local word = data.list[1]
+ word = word and word[1]
+ if word then
+ local seeindex = seewords[word]
+ if seeindex then
+ seeparents[word] = data
+ data.references.seeparent = seeindex
+ if trace_registers then
+ report_registers("see parent %03i: %s",seeindex,word)
+ end
+ end
+ end
+ end
+ -- mark seewords and extend sort list
+ for i=1,#result do
+ local data = result[i]
+ local seeword = data.seeword
+ if seeword then
+ local text = seeword.text
+ if text then
+ 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
+ end
+ end
+ end
+ end
+end
+
+local function removeemptyentries(result)
+ local i, n, m = 1, #result, 0
+ while i <= n do
+ local entry = result[i]
+ if #entry.list == 0 or #entry.split == 0 then
+ remove(result,i)
+ n = n - 1
+ m = m + 1
+ else
+ i = i + 1
+ end
+ end
+ if m > 0 then
+ report_registers("%s empty entries removed in register",m)
+ end
+end
+
+function registers.prepare(data)
+ -- data has 'list' table
+ local strip = sorters.strip
+ local splitter = sorters.splitters.utf
+ local result = data.result
+ if result then
+ for i=1, #result do
+ local entry = result[i]
+ local split = { }
+ local list = entry.list
+ if list then
+ for l=1,#list do
+ local ll = list[l]
+ local word = ll[1]
+ local key = ll[2]
+ if not key or key == "" then
+ key = word
+ end
+ split[l] = splitter(strip(key))
+ end
+ end
+ entry.split = split
+ end
+ removeemptyentries(result)
+ crosslinkseewords(result)
+ end
+end
+
+function registers.sort(data,options)
+ -- if options.pagenumber == false then
+ -- sorters.sort(data.result,compare)
+ -- else
+ sorters.sort(data.result,registers.compare)
+ -- end
+end
+
+function registers.unique(data,options)
+ local result, nofresult, prev = { }, 0, nil
+ local dataresult = data.result
+ for k=1,#dataresult do
+ local v = dataresult[k]
+ if prev then
+ local vr = v.references
+ local pr = prev.references
+ if not equal(prev.list,v.list) then
+ -- ok
+ elseif pr.realpage ~= vr.realpage then
+ -- ok
+ else
+ local pl, vl = pr.lastrealpage, vr.lastrealpage
+ if pl or vl then
+ if not vl then
+ -- ok
+ elseif not pl then
+ -- ok
+ elseif pl ~= vl then
+ -- ok
+ else
+ v = nil
+ end
+ else
+ v = nil
+ end
+ end
+ end
+ if v then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ prev = v
+ end
+ end
+ data.result = result
+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 firstofsplit = sorters.firstofsplit
+ for k=1,#result do
+ local v = result[k]
+ local entry, tag = firstofsplit(v)
+ if tag ~= lasttag then
+ if trace_registers then
+ report_registers("splitting at %a",tag)
+ end
+ done = { }
+ nofdone = 0
+ nofsplit = nofsplit + 1
+ lasttag = tag
+ split[nofsplit] = { tag = tag, data = done }
+ end
+ nofdone = nofdone + 1
+ done[nofdone] = v
+ end
+ 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
+
+registers.analyze = analyzeregister
+
+implement {
+ name = "analyzeregister",
+ actions = { analyzeregister, context },
+ arguments = {
+ "string",
+ {
+ { "language" },
+ { "method" },
+ { "numberorder" },
+ { "compress" },
+ { "criterium" },
+ { "pagenumber", "boolean" },
+ }
+ }
+}
+
+-- todo take conversion from index
+
+function registers.userdata(index,name)
+ local data = references.internals[tonumber(index)]
+ return data and data.userdata and data.userdata[name] or nil
+end
+
+implement {
+ name = "registeruserdata",
+ actions = { registers.userdata, context },
+ arguments = { "integer", "string" }
+}
+
+-- todo: ownnumber
+
+local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec)
+ local fer, ter = f_entry.references, t_entry.references
+ ctx_registerpagerange(
+ f_entry.processors and f_entry.processors[2] or "",
+ fer.internal or 0,
+ fer.realpage or 0,
+ function()
+ h_prefixpage(f_entry,prefixspec,pagespec)
+ end,
+ ter.internal or 0,
+ ter.lastrealpage or ter.realpage or 0,
+ function()
+ if is_last then
+ h_prefixlastpage(t_entry,prefixspec,pagespec) -- swaps page and realpage keys
+ else
+ h_prefixpage (t_entry,prefixspec,pagespec)
+ end
+ end
+ )
+end
+
+local function pagenumber(entry,prefixspec,pagespec)
+ local er = entry.references
+ ctx_registeronepage(
+ entry.processors and entry.processors[2] or "",
+ er.internal or 0,
+ er.realpage or 0,
+ function() h_prefixpage(entry,prefixspec,pagespec) end
+ )
+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_last_pn = first_last .references.realpage
+ local second_first_pn = second_first.references.realpage
+ local second_last_pn = second_last .references.realpage
+ local first_last_last = first_last .references.lastrealpage
+ local second_first_last = second_first.references.lastrealpage
+ if first_last_last then
+ first_last_pn = first_last_last
+ if second_first == second_last and second_first_pn <= first_last_pn then
+ -- 2=8, 5 -> 12=8
+ remove(pages,i)
+ return true
+ elseif second_first == second_last and second_first_pn > first_last_pn then
+ -- 2=8, 9 -> 2-9
+ pages[i-1] = { first_first, second_last }
+ remove(pages,i)
+ return true
+ elseif second_last_pn < first_last_pn then
+ -- 2=8, 3-4 -> 2=8
+ remove(pages,i)
+ return true
+ elseif first_last_pn < second_last_pn then
+ -- 2=8, 3-9 -> 2-9
+ pages[i-1] = { first_first, second_last }
+ remove(pages,i)
+ return true
+ elseif first_last_pn + 1 == second_first_pn and second_last_pn > first_last_pn then
+ -- 2=8, 9-11 -> 2-11
+ pages[i-1] = { first_first, second_last }
+ remove(pages,i)
+ return true
+ elseif second_first.references.lastrealpage then
+ -- 2=8, 9=11 -> 2-11
+ pages[i-1] = { first_first, second_last }
+ remove(pages,i)
+ return true
+ end
+ elseif second_first_last then
+ second_first_pn = second_first_last
+ if first_last_pn == second_first_pn then
+ -- 2-4, 5=9 -> 2-9
+ pages[i-1] = { first_first, second_last }
+ remove(pages,i)
+ return true
+ end
+ elseif first_last_pn == second_first_pn then
+ -- 2-3, 3-4 -> 2-4
+ pages[i-1] = { first_last, second_last }
+ remove(pages,i)
+ return true
+ end
+ end
+ return false
+end
+
+local function collapsepages(pages)
+ while collapsedpage(pages) do end
+ return #pages
+end
+
+function registers.flush(data,options,prefixspec,pagespec)
+ local collapse_singles = options.compress == v_yes
+ local collapse_ranges = options.compress == v_all
+ local show_page_number = options.pagenumber ~= false -- true or false
+ local result = data.result
+ local maxlevel = 0
+ --
+ for i=1,#result do
+ local data = result[i].data
+ for d=1,#data do
+ local m = #data[d].list
+ if m > maxlevel then
+ maxlevel = m
+ end
+ end
+ end
+ if maxlevel > absmaxlevel then
+ maxlevel = absmaxlevel
+ report_registers("limiting level to %a",maxlevel)
+ end
+ --
+ ctx_startregisteroutput()
+ local done = { }
+ local started = false
+ for i=1,#result do
+ -- ranges need checking !
+ local sublist = result[i]
+ -- local done = { false, false, false, false }
+ for i=1,maxlevel do
+ done[i] = false
+ end
+ local data = sublist.data
+ local d, n = 0, 0
+ ctx_startregistersection(sublist.tag)
+ for d=1,#data do
+ local entry = data[d]
+ if entry.metadata.kind == "see" then
+ local list = entry.list
+ if #list > 1 then
+ list[#list] = nil
+ else
+ -- we have an \seeindex{Foo}{Bar} without Foo being defined anywhere .. somehow this message is wrong
+ -- report_registers("invalid see entry in register %a, reference %a",entry.metadata.name,list[1][1])
+ end
+ end
+ 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]
+ local metadata = entry.metadata
+ local kind = metadata.kind
+ local list = entry.list
+ local e = { false, false, false }
+ for i=3,maxlevel do
+ e[i] = false
+ end
+ for i=1,maxlevel do
+ if list[i] then
+ e[i] = list[i][1]
+ end
+ if e[i] == done[i] then
+ -- skip
+ elseif not e[i] then
+ -- see ends up here
+ -- can't happen any more
+ done[i] = false
+ for j=i+1,maxlevel do
+ done[j] = false
+ end
+ elseif e[i] == "" then
+ done[i] = false
+ for j=i+1,maxlevel do
+ done[j] = false
+ end
+ else
+ done[i] = e[i]
+ for j=i+1,maxlevel do
+ done[j] = false
+ end
+ if started then
+ ctx_stopregisterentry()
+ started = false
+ end
+ if n == i then
+-- ctx_stopregisterentries()
+-- ctx_startregisterentries(n)
+ else
+ while n > i do
+ n = n - 1
+ ctx_stopregisterentries()
+ end
+ while n < i do
+ n = n + 1
+ ctx_startregisterentries(n)
+ end
+ end
+ local references = entry.references
+ local processors = entry.processors
+ local internal = references.internal or 0
+ local seeparent = references.seeparent or ""
+ local processor = processors and processors[1] or ""
+ -- so, we need to keep e as is (local), or we need local title = e[i] ... which might be
+ -- more of a problem
+ ctx_startregisterentry(0) -- will become a counter
+ started = true
+ if metadata then
+ ctx_registerentry(processor,internal,seeparent,function() h_title(e[i],metadata) end)
+ else
+ -- can this happen?
+ 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
+ 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 last.references.lastrealpage then
+ pagerange(first,last,true,prefixspec,pagespec)
+ else
+ pagerange(first,last,false,prefixspec,pagespec)
+ end
+ end
+ elseif entry.references.lastrealpage then
+ pagerange(entry,entry,true,prefixspec,pagespec)
+ else
+ pagenumber(entry,prefixspec,pagespec)
+ end
+ 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
+ end
+ end
+ ctx_stopregisterpages()
+ end
+ elseif kind == 'see' then
+ local t, nt = { }, 0
+ while true do
+ nt = nt + 1
+ t[nt] = 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
+ ctx_startregisterseewords()
+ for i=1,nt do
+ 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)
+ end
+ ctx_stopregisterseewords()
+ end
+ end
+ if started then
+ ctx_stopregisterentry()
+ started = false
+ end
+ while n > 0 do
+ ctx_stopregisterentries()
+ n = n - 1
+ end
+ ctx_stopregistersection()
+ end
+ ctx_stopregisteroutput()
+ -- for now, maybe at some point we will do a multipass or so
+ data.result = nil
+ data.metadata.sorted = false
+ -- temp hack for luajittex :
+ local entries = data.entries
+ for i=1,#entries do
+ entries[i].split = nil
+ end
+ -- collectgarbage("collect")
+end
+
+function registers.process(class,...)
+ if analyzeregister(class,...) > 0 then
+ local data = collected[class]
+ registers.flush(data,...)
+ end
+end
+
+implement {
+ name = "processregister",
+ actions = registers.process,
+ arguments = {
+ "string",
+ {
+ { "language" },
+ { "method" },
+ { "numberorder" },
+ { "compress" },
+ { "criterium" },
+ { "pagenumber", "boolean" },
+ },
+ {
+ { "separatorset" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ { "set" },
+ { "segments" },
+ { "connector" },
+ },
+ {
+ { "prefix" },
+ { "separatorset" },
+ { "conversionset" },
+ { "starter" },
+ { "stopper" },
+ { "segments" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv
new file mode 100644
index 00000000000..1d28db8dfed
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv
@@ -0,0 +1,1043 @@
+%D \module
+%D [ file=strc-reg,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Registers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Registers}
+
+\registerctxluafile{strc-reg}{1.001}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+% todo: tag:: becomes rendering
+% todo: language, character, linked, location
+% todo: fonts etc at sublevels (already defined)
+
+% \starttext
+% \placeregister[index]
+% \chapter{a} \index{93} \index{456} \index{***} \index{*} \index{@}
+% test \index{aa} test \startregister[index][x]{bb} test \page test \page test \page test \stopregister[index][x]
+% test \index{aa} test \setregisterentry[index][label=x,entries=bb] test \page test \page test \page test \finishregisterentry[index][label=x]
+% test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy]
+% \stoptext
+
+% \index {entry}
+% \index[key] {entry}
+% \index[pageclass::] {entry}
+% \index[pageclass::key]{entry}
+% \index {textclass::entry}
+% \index[key] {textclass::entry}
+% \index[pageclass::] {textclass::entry}
+% \index[pageclass::key]{textclass::entry}
+
+% tzt variant with n entries, parameters and userdata (altnum)
+
+\installcorenamespace{register}
+
+\installcommandhandler\??register {register} \??register
+
+\let\strc_registers_setup_saved\setupregister
+
+\unexpanded\def\setupregister % maybe we should drop the plural form
+ {\dotripleempty\strc_registers_setup}
+
+\def\strc_registers_setup[#1][#2][#3]%
+ {\ifthirdargument
+ \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}%
+ \processcommalist[#2]\strc_registers_setup_step
+ \else\ifsecondargument
+ \strc_registers_setup_saved[#1][#2]%
+ \else
+ \strc_registers_setup_saved[#1]%
+ \fi\fi}
+
+\unexpanded\def\setupregisters
+ {\dosingleempty\strc_registers_setup_root}
+
+\def\strc_registers_setup_root[#1]%
+ {\strc_registers_setup_saved[#1]\relax}
+
+\setupregister
+ [\c!n=2,
+ \c!balance=\v!yes, % \v!no komt niet zo vaak voor
+ \c!align=\v!flushleft,
+ \c!tolerance=\v!stretch,
+ \c!before=\blank,
+ %\c!after=,
+ %\c!symbol=,
+ \c!compress=\v!no,
+ \c!interaction=\v!pagenumber,
+ \c!alternative=\v!a,
+ \c!distance=\emwidth,
+ \c!style=\v!bold,
+ \c!pagestyle=\v!slanted,
+ \c!indicator=\v!yes,
+ \c!criterium=\v!all,
+ %\c!command=,
+ \c!referencing=\v!on,
+ \c!location=\v!middle,
+ %\c!maxwidth=,
+ \c!number=\v!no,
+ \c!unknownreference=\v!empty,
+ \c!prefix=\v!both,
+ %\c!expansion=,
+ %\c!xmlsetup=,
+ \c!pagenumber=\v!yes,
+ \c!pageprefixconnector=\endash,
+ \c!pagesegments=2:2,
+ \c!file=\jobname,
+ %\c!deeptextcommand=, % undefined by default !
+ \c!method=, % no default as we have them in the module, maybe some day in lang-*
+ \c!numberorder=\v!numbers, % \v!characters
+ \s!language=\currentmainlanguage]%
+
+% yes or no shared ?
+
+\setupregister
+ [\c!label=,
+ \c!entries=,
+ \c!alternative=]
+
+\definemixedcolumns
+ [\v!register]
+ [\c!n=\registerparameter\c!n,
+ \c!balance=\registerparameter\c!balance,
+ \c!align=\registerparameter\c!align,
+ \c!tolerance=\registerparameter\c!tolerance]
+
+%D \starttyping
+%D \setupregister[index][1][textcolor=darkred]
+%D \setupregister[index][2][textcolor=darkgreen,textstyle=bold]
+%D
+%D \placeregister[index][n=1] \blank[3*big]
+%D
+%D test \index{test+one} test \index{test+two} more \index{more}
+%D \stoptyping
+
+\newconditional\c_strc_registers_defining
+\setnewconstant\c_strc_registers_maxlevel \plusfive
+
+\ifdefined\Word \else \unexpanded\def\Word#1{#1} \fi
+
+\appendtoks
+ \ifconditional\c_strc_registers_defining \else % todo: dosingle ...
+ \settrue\c_strc_registers_defining
+ \definemixedcolumns[\currentregister][\v!register]% first as otherwise it overloads start/stop
+ \clf_defineregister{\currentregister}{\registerparameter\c!referencemethod}%
+ \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}%
+ \setuevalue{\currentregister}{\dodoubleempty\strc_registers_insert_entry[\currentregister]}%
+ \setuevalue{\e!see\currentregister}{\dodoubleempty\strc_registers_insert_see[\currentregister]}%
+ %setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}%
+ % historic ballast
+ \setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}%
+ \setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}%
+ \setuevalue{\e!setup\currentregister\e!endsetup}{\setupregister[\currentregister]}%
+ \dorecurse\c_strc_registers_maxlevel{% weird, expanded should not be needed
+ \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}%
+ %\defineregister[\currentregister:\recurselevel][\currentregister]%
+ \letregisterparameter{\c!entries:\recurselevel}\empty % needed as we use detokenize (ok, we can
+ \letregisterparameter{\c!keys :\recurselevel}\empty % avoid it, but it's faster too)
+ }%
+ %
+ \setfalse\c_strc_registers_defining
+ \fi
+\to \everydefineregister
+
+\appendtoks
+ \clf_setregistermethod{\currentregister}{\registerparameter\c!referencemethod}%
+\to \everysetupregister
+
+%D Registering:
+
+\def\strc_registers_register_page_entry
+ {\iftrialtypesetting
+ \expandafter\gobblethreearguments
+ \else
+ \expandafter\strc_registers_register_page_entry_indeed
+ \fi}
+
+\def\strc_registers_register_page_expand_xml_entries
+ {\xmlstartraw
+ \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
+ \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
+ \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
+ \xmlstopraw
+ \globallet\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}
+
+\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}
+
+\def\strc_registers_register_page_expand_xml
+ {\xmlstartraw
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml}
+
+\def\strc_registers_register_page_expand_yes
+ {\xdef\currentregisterentries{\registerparameter\c!entries}%
+ \globallet\currentregistercoding\s!tex}
+
+\def\strc_registers_register_page_expand_nop
+ {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
+ \globallet\currentregistercoding\s!tex}
+
+\def\strc_registers_register_page_expand_xml_keys
+ {\xmlstartraw
+ \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
+ \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
+ \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}%
+ \xmlstopraw}
+
+\def\strc_registers_register_page_expand_yes_keys
+ {\xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
+ \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
+ \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}}
+
+\def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
+ {\begingroup
+ \edef\currentregister{#1}%
+ %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
+ \setupcurrentregister[#2]%
+ \edef\currentregisterlabel {\registerparameter\c!label}%
+ \edef\currentregisterexpansion{\registerparameter\c!expansion}%
+ \edef\currentregisterownnumber{\registerparameter\c!ownnumber}%
+ \xdef\currentregisterkeys {\registerparameter\c!keys}%
+ \xdef\currentregisterentries {\registerparameter\c!entries}%
+ \xdef\currentregisterxmlsetup {\registerparameter\c!xmlsetup}%
+ \ifx\currentregisterentries\empty
+ \ifx\currentregisterexpansion\s!xml
+ \strc_registers_register_page_expand_xml_entries
+ \else\ifx\currentregisterexpansion\v!yes
+ \strc_registers_register_page_expand_yes_entries
+ \else
+ \strc_registers_register_page_expand_nop_entries
+ \fi\fi
+ \else
+ \ifx\currentregisterexpansion\s!xml
+ \strc_registers_register_page_expand_xml
+ \else\ifx\currentregisterexpansion\v!yes
+ \strc_registers_register_page_expand_yes
+ \else
+ \strc_registers_register_page_expand_nop
+ \fi\fi
+ \fi
+ \ifx\currentregisterkeys\empty
+ \ifx\currentregistercoding\s!xml
+ \strc_registers_register_page_expand_xml_keys
+ \else
+ \strc_registers_register_page_expand_yes_keys
+ \fi
+ \fi
+ \setnextinternalreference
+ % we could consider storing register entries in a list which we
+ % could then sort
+ \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
+ metadata {%
+ name {\currentregister}%
+ coding {\currentregistercoding}%
+ \ifx\currentregisterownnumber\v!yes
+ own {\registerparameter\c!alternative}% can be used instead of pagenumber
+ \fi
+ \ifx\currentreferencecoding\s!xml
+ xmlroot {\xmldocument} % only useful when text
+ \fi
+ \ifx\currentregisterxmlsetup\empty \else
+ xmlsetup {\currentregisterxmlsetup}%
+ \fi
+ }%
+ references {%
+ \ifx\currentregisterlabel\empty \else
+ label {\currentregisterlabel}%
+ \fi
+% view {\interactionparameter\c!focus}%
+ }%
+ entries {%
+ % we need a special one for xml, this is just a single one
+ \ifx\currentregisterentries\empty
+ entries {
+ {\currentregisterentriesa}%
+ {\currentregisterentriesb}%
+ {\currentregisterentriesc}%
+ }
+ \else
+ entry {\currentregisterentries}%
+ \fi
+ \ifx\currentregisterkeys\empty
+ keys {
+ {\currentregisterkeysa}%
+ {\currentregisterkeysb}%
+ {\currentregisterkeysc}%
+ }
+ \else
+ key {\currentregisterkeys}%
+ \fi
+ }%
+ userdata {\detokenize\expandafter{\normalexpanded{#3}}}
+ }%
+ \clf_setinternalreference
+ internal \nextinternalreference
+ view {\interactionparameter\c!focus}%
+ \relax % this will change
+ \ifx\currentregisterownnumber\v!yes
+ \glet\currentregistersynchronize\relax
+ \else
+ \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}%
+ \fi
+ \currentregistersynchronize % here?
+ % needs thinking ... bla\index{bla}. will break before the . but adding a
+ % penalty is also no solution
+ \dostarttagged\t!registerlocation\currentregister
+ \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
+ \dotagregisterlocation
+ \dostoptagged
+ \endgroup}
+
+\unexpanded\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor
+ {\begingroup
+ \edef\currentregister{#1}%
+ \setnextinternalreference
+ \xdef\currentregisternumber{\clf_storeregister
+ {%
+ metadata {%
+ name {\currentregister}%
+ }
+ entries {%
+ entry {#2}%
+ key {#3}%
+ }%
+ processors {%
+ entry {#4}%
+ page {#5}%
+ }%
+ }%
+ }%
+ % overlap with the above
+ % \clf_setinternalreference
+ % internal \nextinternalreference
+ % view {\interactionparameter\c!focus}%
+ \relax % this will change
+ \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}%
+ \currentregistersynchronize % here?
+ \dostarttagged\t!registerlocation\currentregister
+ \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
+ \dotagregisterlocation
+ \dostoptagged
+ \endgroup}
+
+\let\dotagregisterlocation\relax % experiment
+
+\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}}
+
+\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}}{}}}
+
+\unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry}
+\unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry}
+
+% a synonym, so that we can nest with overlap without syntax check problems
+
+\let\openregisterrange \startregister
+\let\closeregisterrange\stopregister
+
+\def\strc_registers_start_entry[#1][#2][#3][#4]#5%
+ {\iffourthargument
+ % #1=register #2=tag #3=own #4=sortkey #5=entry
+ \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
+ \else
+ % #1=register #2=tag #3=sortkey #5=entry
+ \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
+ \fi}
+
+\def\strc_registers_stop_entry[#1][#2]%
+ {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}}
+
+\def\setregisterentry {\dotripleempty\strc_registers_set_entry}
+\def\finishregisterentry{\dotripleempty\strc_registers_finish_entry}
+
+% not yet document, not sure if this will stay:
+
+\def\strc_registers_set_entry [#1][#2][#3]{\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
+\def\strc_registers_finish_entry[#1][#2][#3]{\strc_registers_finish_entry_indeed{#1}{#2}{#3}}
+
+\def\strc_registers_finish_entry_indeed#1#2#3% register data userdata
+ {\begingroup
+ \edef\currentregister{#1}%
+ \setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% todo: fast setter
+ \edef\currentregisterlabel {\registerparameter\c!label}%
+ \edef\currentregisterexpansion{\registerparameter\c!expansion}%
+ \edef\currentregisterownnumber{\registerparameter\c!ownnumber}%
+ \xdef\currentregisterkeys {\registerparameter\c!keys}%
+ \ifx\currentregisterexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml
+ \else
+ \ifx\currentregisterexpansion\v!yes
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \else
+ \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
+ \fi
+ \globallet\currentregistercoding\s!tex
+ \fi
+ % I hate this kind of mess ... but it's a user request.
+ \ifx\currentregisterentries\empty
+ \normalexpanded{\ctxcommand{extendregister("\currentregister","\currentregisterlabel", {
+ metadata = {
+ \ifx\currentregisterownnumber\v!yes
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ \fi
+ },
+ userdata = \!!bs\detokenize{#3}\!!es
+ })%
+ }}%
+ \else
+ \normalexpanded{\ctxcommand{extendregister("\currentregister","\currentregisterlabel", {
+ metadata = {
+ % catcodes = \the\catcodetable,
+ coding = "\currentregistercoding",
+ \ifx\currentregisterownnumber\v!yes
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ \fi
+ },
+ entries = {
+ % we need a special one for xml, this is just a single one
+ \!!bs\currentregisterentries\!!es,
+ \!!bs\currentregisterkeys\!!es
+ },
+ userdata = \!!bs\detokenize{#3}\!!es
+ })
+ }}%
+ \fi
+ \endgroup}
+
+% The following variants are meant for (for instance xml). There is some
+% overlap with previously defined macros.
+%
+% \starttext
+% \setstructurepageregister[index][entries=alpha]a
+% \setstructurepageregister[index][entries=gamma]g
+% \setstructurepageregister[index][entries=beta]b
+% \setstructurepageregister[index][entries:1=alpha,keys:1=z]a
+% \setstructurepageregister[index][entries:1=gamma,keys:1=x]g
+% \setstructurepageregister[index][entries:1=beta, keys:1=y]b
+% \index{alpha}a
+% \index{gamma}g
+% \index{beta}b
+% \placeregister[index][n=1]
+% \stoptext
+
+% some overlap with previous
+
+\unexpanded\def\setstructurepageregister
+ {\dotripleempty\strc_registers_set}
+
+\def\strc_registers_set[#1][#2][#3]% [register][settings][userdata]
+ {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
+
+\unexpanded\def\startstructurepageregister{\doquadrupleempty\strc_registers_start}
+\unexpanded\def\stopstructurepageregister {\dodoubleargument\strc_registers_stop}
+
+\let\openstructurepageregisterrange \startstructurepageregister
+\let\closestructurepageregisterrange\stopstructurepageregister
+
+\def\strc_registers_start[#1][#2][#3][#4]% [register][tag][settings][userdata]
+ {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}}
+
+\def\strc_registers_stop[#1][#2]%
+ {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}}
+
+% So far.
+
+\unexpanded\def\strc_registers_insert_see[#1][#2]#3#4%
+ {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}}
+
+\def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword
+ {\begingroup
+ \edef\currentregister{#1}%
+ \edef\currentregisterexpansion{\registerparameter\c!expansion}%
+ \ifx\currentregisterexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
+ \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml
+ \else
+ \ifx\currentregisterexpansion\v!yes
+ \xdef\currentregisterentries{#3}% not ok yet
+ \xdef\currentregisterseeword{#4}% not ok yet
+ \else
+ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
+ \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
+ \fi
+ \globallet\currentregistercoding\s!tex
+ \fi
+ \setnextinternalreference
+ % we could consider storing register entries in list
+ \edef\temp{\clf_storeregister{% \temp grabs the nofentries
+ metadata {%
+ kind {see}%
+ name {\currentregister}%
+ }%
+ references {%
+% view {\interactionparameter\c!focus}%
+ }%
+ entries {%
+ % we need a special one for xml, this is just a single one
+ entry {\currentregisterentries}%
+ key {#2}%
+ }%
+ seeword {%
+ text {\currentregisterseeword}%
+ }%
+ }}%
+ \clf_setinternalreference
+ internal \nextinternalreference
+ view {\interactionparameter\c!focus}%
+ \relax % this will change
+ \dostarttagged\t!registerlocation\currentregister
+ \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
+ \dotagregisterlocation
+ \dostoptagged
+ \endgroup}
+
+%D Rendering:
+
+% todo: c!language ipv s!language
+
+\let\utilityregisterlength\!!zerocount
+
+\def\determineregistercharacteristics
+ {\dodoubleempty\strc_registers_determine_characteristics}
+
+\def\strc_registers_determine_characteristics[#1][#2]%
+ {\begingroup
+ \edef\currentregister{#1}%
+ \setupregister[\currentregister][#2]%
+ \normalexpanded{\endgroup\noexpand\xdef\noexpand\utilityregisterlength{\clf_analyzeregister
+ {\currentregister}%
+ {%
+ language {\registerparameter\s!language}%
+ method {\registerparameter\c!method}%
+ numberorder {\registerparameter\c!numberorder}%
+ compress {\registerparameter\c!compress}%
+ criterium {\registerparameter\c!criterium}%
+ pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi
+ }%
+ }}%
+ \ifcase\utilityregisterlength\relax
+ \resetsystemmode\v!register
+ \else
+ \setsystemmode \v!register
+ \fi}
+
+\newtoks\everyplaceregister
+
+\appendtoks
+ \dontcomplain
+\to \everyplaceregister
+
+\unexpanded\def\placeregister
+ {\dodoubleempty\strc_registers_place}
+
+\def\strc_registers_place[#1][#2]%
+ {\iffirstargument
+ \begingroup
+ %\forgetall
+ \edef\currentregister{#1}%
+ \setupregister[\currentregister][#2]%
+ \the\everyplaceregister
+ \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone
+ \startmixedcolumns[\currentregister]
+ \strc_registers_place_indeed
+ \stopmixedcolumns
+ \else
+ \strc_registers_place_indeed
+ \fi
+ \endgroup
+ \fi}
+
+\newconditional\c_strc_registers_text_interaction
+
+\def\strc_registers_place_indeed
+ {\doifelse{\registerparameter\c!interaction}\v!text
+ \settrue\setfalse\c_strc_registers_text_interaction
+ \clf_processregister
+ {\currentregister}%
+ {%
+ language {\registerparameter\s!language}%
+ method {\registerparameter\c!method}%
+ numberorder {\registerparameter\c!numberorder}%
+ compress {\registerparameter\c!compress}%
+ criterium {\registerparameter\c!criterium}%
+ pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi
+ }{%
+ separatorset {\registerparameter\c!pageprefixseparatorset}%
+ conversionset {\registerparameter\c!pageprefixconversionset}%
+ starter {\registerparameter\c!pageprefixstarter}%
+ stopper {\registerparameter\c!pageprefixstopper}%
+ set {\registerparameter\c!pageprefixset}%
+ segments {\registerparameter\c!pageprefixsegments}%
+ connector {\registerparameter\c!pageprefixconnector}%
+ }{%
+ prefix {\registerparameter\c!pageprefix}%
+ separatorset {\registerparameter\c!pageseparatorset}%
+ conversionset {\registerparameter\c!pageconversionset}%
+ starter {\registerparameter\c!pagestarter}%
+ stopper {\registerparameter\c!pagestopper}%
+ segments {\registerparameter\c!pagesegments}%
+ }%
+ \relax}
+
+\def\strc_registers_limited_entry#1%
+ {\limitatetext{#1}\currentregistermaxwidth\unknown}%
+
+\appendtoks
+ \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
+ \ifx\currentregistermaxwidth\empty
+ \let\limitedregisterentry\firstofoneargument
+ \else
+ \let\limitedregisterentry\strc_registers_limited_entry
+ \fi
+\to \everyplaceregister
+
+\unexpanded\def\completeregister
+ {\dodoubleempty\strc_registers_complete}
+
+\def\strc_registers_complete[#1][#2]%
+ {\iffirstargument
+ \begingroup
+ \edef\currentregister{#1}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
+ \placeregister[\currentregister][#2]%
+ \page[\v!yes]%
+ \stopnamedsection
+ \endgroup
+ \fi}
+
+% test case for collapsing (experimental, for Steffen Wolfrum)
+%
+% \starttext
+% \placeregister[index][compress=no] \blank[2*big]
+% \placeregister[index][compress=yes] \blank[2*big]
+% \placeregister[index][compress=all] \page
+% \dorecurse{10}{test 1:!\index{test} test \page}
+% \dorecurse{5} {test 2:\recurselevel \page}
+% \dorecurse{10}{test 3:!\index{test} test \page}
+% \dorecurse{5} {test 4:\recurselevel \page}
+% \dorecurse{1} {test 5:!\index{test} test \page}
+% \dorecurse{5} {test 6:\recurselevel \page}
+% \dorecurse{10}{test 7:!\index{test} test \page}
+% \dorecurse{5} {test 8:\recurselevel \page}
+% oeps \index{oeps}
+% xxxx \index{xxxx}
+% todo \index{todo}
+% \stoptext
+
+%D Character rendering (sections):
+
+\installcorenamespace{registerindicator}
+
+\def\defaultregistercharacter#1%
+ {\edef\currentregistercharacter{#1}%
+ \ifx\currentregistercharacter\empty
+ % skip
+ \else\ifx\currentregistercharacter\s!unknown
+ % skip
+ \else
+ \edef\p_indicator{\registerparameter\c!indicator}%
+ \ifx\p_indicator\v!yes
+ \strc_registers_place_character_yes
+ \else
+ \strc_registers_place_character_nop
+ \fi
+ \fi\fi}
+
+\def\strc_registers_place_character_yes
+ {\expandnamespaceparameter\??registerindicator\registerparameter\c!alternative\v!a{\currentregistercharacter}}
+
+\def\strc_registers_place_character_nop
+ {\registerparameter\c!before
+ \goodbreak}
+
+% a = <before> <goodbreak> <character> <par> <after> <nobreak>
+
+\def\strc_registers_indicator_a#1#2%
+ {\registerparameter\c!before
+ % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
+ \typo_injectors_check_register
+ \begingroup
+ \useregisterstyleandcolor\c!style\c!color
+ \dontleavehmode
+ \typo_injectors_mark_register
+ \strut
+ \iflocation
+ \dosetdirectpagereference{\currentregister:\v!section:#1}%
+ \fi
+ \registerparameter\c!command{#2}%
+ \endgroup
+ \blank[\v!samepage]%
+ \registerparameter\c!after
+ \par
+ \nobreak}
+
+% b = <goodbreak> <before> <character> <after> <nobreak>
+
+\def\strc_registers_indicator_b#1#2%
+ {\registerparameter\c!before
+ \typo_injectors_check_register
+ \begingroup
+ \useregisterstyleandcolor\c!style\c!color
+ \dontleavehmode
+ \typo_injectors_mark_register
+ \strut
+ \iflocation
+ \dosetdirectpagereference{\currentregister:\v!section:#1}%
+ \fi
+ \registerparameter\c!command{#2}%
+ \endgroup
+ \registerparameter\c!after
+ \nobreak}
+
+\setvalue{\??registerindicator a}#1{\strc_registers_indicator_a{#1}{#1}}
+\setvalue{\??registerindicator A}#1{\strc_registers_indicator_a{#1}{\WORD{#1}}}
+\setvalue{\??registerindicator b}#1{\strc_registers_indicator_b{#1}{#1}}
+\setvalue{\??registerindicator B}#1{\strc_registers_indicator_b{#1}{\WORD{#1}}}
+
+%D The following macros are the interface to the rendering. These are
+%D generated by \LUA. This might change.
+
+% \showinjector
+% \setinjector[register][2][\column]
+%
+% \starttext
+% first \index{first}
+% second \index{second}
+% third \index{third}
+% fourth \index{fourth}
+% \placeregister[index]
+% \stoptext
+
+\doinstallinjector\s!register
+
+%D Beware, we get funny side effects when a dangling \index precedes an
+%D placeindex as then flushing takes place inside the index. Took me hours
+%D to notice that.
+
+\newconstant \c_strc_registers_page_state % 0=nothing 1=page 2=see
+\newdimen \d_strc_registers_distance
+
+\unexpanded\def\startregisteroutput
+ {\endgraf
+ \begingroup
+ \d_strc_registers_distance\registerparameter\c!distance\relax
+ \dostarttaggedchained\t!register\currentregister\??register
+ \forgeteverypar
+ \forgetparindent
+ \forgetparskip}
+
+\unexpanded\def\stopregisteroutput
+ {\endgraf
+ \dostoptagged
+ \endgroup}
+
+\newdimen\d_strc_registers_hangindent
+\newcount\c_strc_registers_hangafter
+
+\unexpanded\def\startregisterentries#1% depth
+ {\endgraf
+ \begingroup
+ \scratchcounter\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
+ \dostarttagged\t!registerentries\empty
+ \let\savedcurrentregister\currentregister
+ \edef\currentregister{\currentregister:\number\scratchcounter}%
+ \useregisterstyleandcolor\c!textstyle\c!textcolor
+ \ifnum\scratchcounter>\plusone
+ \advance\leftskip\d_strc_registers_distance\relax
+ \fi
+ \d_strc_registers_hangindent\registerparameter\c!distance\relax
+ \c_strc_registers_hangafter \plusone
+ \blank[\v!samepage]%
+ \let\currentregister\savedcurrentregister}
+
+\unexpanded\def\stopregisterentries
+ {\endgraf
+ \dostoptagged
+ \endgroup}
+
+\unexpanded\def\startregisterentry#1% todo: level
+ {\typo_injectors_check_register
+ \begingroup
+ \dostarttagged\t!registerentry\empty
+ \global\setconstant\c_strc_registers_page_state\zerocount
+ \hangindent\d_strc_registers_hangindent
+ \hangafter \c_strc_registers_hangafter
+ \typo_injectors_mark_register}
+
+\unexpanded\def\stopregisterentry
+ {\endgraf
+ \global\setconstant\c_strc_registers_page_state\zerocount
+ \dostoptagged
+ \endgroup}
+
+\unexpanded\def\startregistersection#1% title
+ {\dostarttagged\t!registersection\empty
+ \dostarttagged\t!registertag\empty
+ \registercharacter{#1}\endgraf
+ \dostoptagged}
+
+\unexpanded\def\stopregistersection
+ {\dostoptagged
+ \endgraf}
+
+\unexpanded\def\startregisterpages
+ {\begingroup
+ \dostarttagged\t!registerpages\empty
+ \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
+
+\unexpanded\def\stopregisterpages
+ {\dostoptagged
+ \endgroup}
+
+\unexpanded\def\startregisterseewords
+ {%\par % \ifhmode\crlf\fi % otherwise wrong level
+ \begingroup
+ \dostarttagged\t!registerpage\empty
+ \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
+
+\unexpanded\def\stopregisterseewords
+ {\dostoptagged
+ \endgroup}
+
+\unexpanded\def\registerpageseparator % todo: , configurable
+ {\ifcase\c_strc_registers_page_state
+ \hskip\d_strc_registers_distance\relax
+ \or
+ \dostarttagged\t!registerseparator\empty
+ \registerpageseparatorsymbol % page
+ \dostoptagged
+ \or
+ \dostarttagged\t!registerseparator\empty
+ \registerpageseparatorsymbol % see
+ \dostoptagged
+ \fi}
+
+\unexpanded\def\registeronepagerangeseparator
+ {|\endash|} % todo use \prewordbreak
+
+% \unexpanded\def\withregisterpagecommand#1#2#3#4%
+% {\def\currentregisterpageindex{#2}%
+% \iflocation
+% \goto{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
+% \else
+% \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+% \fi}
+
+\unexpanded\def\withregisterpagecommand#1#2#3#4%
+ {\def\currentregisterpageindex{#2}%
+ \iflocation
+ \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[#2]%
+ \else
+ \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+ \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\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word
+% {\def\currentregisterpageindex{#2}%
+% \iflocation
+% \def\currentregisterseeindex{#3}%
+% \doifelse{\registerparameter\c!interaction}\v!text
+% {\directgoto{\setlocationcolor\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]}
+% {\doapplyregisterentrycommand{#1}{#4}}%
+% \else
+% \let\currentregisterseeindex\empty
+% \doapplyregisterentrycommand{#1}{#4}%
+% \fi}
+
+\unexpanded\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word
+ {\def\currentregisterpageindex{#2}%
+ \iflocation
+ \def\currentregisterseeindex{#3}%
+ \ifconditional\c_strc_registers_text_interaction
+ \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]%
+ \else
+ \doapplyregisterentrycommand{#1}{#4}%
+ \fi
+ \else
+ \let\currentregisterseeindex\empty
+ \doapplyregisterentrycommand{#1}{#4}%
+ \fi}
+
+\unexpanded\def\doapplyregisterentrycommand#1#2% processor text
+ {\dostarttagged\t!registercontent\empty
+ \ifx\currentregisterseeindex\empty \else
+ \dontleavehmode
+ \dosetdirectpagereference{seeindex:\currentregisterseeindex}% maybe some day we will support an area
+ \fi
+ \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}%
+ \dostoptagged}
+
+% \unexpanded\def\doapplyregisterseecommand#1#2%
+% {\ifx\currentregisterseeindex\empty
+% % \dontleavehmode
+% \applyprocessor{#1}{#2}%
+% \else
+% \goto{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
+% \fi}
+
+\unexpanded\def\doapplyregisterseecommand#1#2%
+ {\ifx\currentregisterseeindex\empty
+ \applyprocessor{#1}{#2}%
+ \else\iflocation
+ \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
+ \else
+ \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
+ \global\setconstant\c_strc_registers_page_state\plustwo
+ \def\currentregisterpageindex{#4}%
+ \dostarttagged\t!registersee\empty
+ \settrue\c_strc_registers_page_done
+ \iflocation
+ \def\currentregisterseeindex{#5}%
+ \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}}%
+ \else
+ ,\space\doapplyregisterseecommand{#3}{#6}%
+ \fi\fi
+ \dostoptagged}
+
+\let\registerseeword \defaultregisterseeword
+\let\registerentry \defaultregisterentry
+\let\registercharacter\defaultregistercharacter
+
+%D A few specific rendering variants:
+
+% \def\doregisterpagelocation#1#2%
+% {\nextregisterpage
+% \hbox to 1em{\hss\doregisterpagehowto{#1}{#2}\hss}}
+
+% todo: \installregisterpagehandler
+
+% \def\MyRegisterPageCommand#1%
+% {#1\currentregisterpageuserdata{whatever}}
+%
+% \starttext
+% \setregisterentry[index][entries=aaa][whatever=f.] test \index{bbb} test
+% \placeregister[index][n=1,pagecommand=\MyRegisterPageCommand]
+% \stoptext
+
+\def\registerpageuserdata #1#2{\clf_registeruserdata#1{#2}}
+\def\currentregisterpageuserdata {\registerpageuserdata\currentregisterpageindex} % {#1}
+
+% not yet ok : new internal handler names
+
+\unexpanded\def\registerpagebuttonsymbol
+ {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}
+
+\installcorenamespace{registersymbol}
+
+\setvalue{\??registersymbol n}%
+ {\def\registerpageseparatorsymbol{,\space}}
+
+\setvalue{\??registersymbol a}%
+ {\def\registerpageseparatorsymbol{,\space}} % now done via conversion
+
+\setvalue{\??registersymbol\v!none}%
+ {\let\registerpageseparatorsymbol\empty
+ \let\registeronepage \gobblefourarguments
+ \let\registerpagerange \gobblesevenarguments}
+
+\setvalue{\??registersymbol 1}%
+ {\let\registerpageseparatorsymbol\space
+ \def\registeronepage {\symbol[1]\gobblefourarguments}%
+ \def\registerpagerange{\symbol[1]\gobblesevenarguments}}
+
+\setvalue{\??registersymbol 2}%
+ {\let\registerpageseparatorsymbol\space
+ \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}%
+ \def\registerpagerange{\registerpagebuttonsymbol\gobblesevenarguments}}
+
+\unexpanded\def\setregisterpagerendering
+ {\doifelse{\registerparameter\c!pagenumber}\v!no
+ {\let \currentregisterpagesymbol\v!none}
+ {\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}%
+ \ifx\currentregisterpagesymbol\empty
+ \csname\??registersymbol n\endcsname
+ \else\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname
+ \csname\??registersymbol\currentregisterpagesymbol\endcsname
+ \else
+ \let\registerpageseparatorsymbol\space
+ \def\registeronepage{\registerparameter\c!symbol\gobblefourarguments}%
+ \def\registerpagerange{\registerparameter\c!symbol\gobblesevenarguments}%
+ \fi\fi}
+
+\appendtoks
+ \setregisterpagerendering
+\to \everyplaceregister
+
+%D The linked register code will be reimplemented (not that hard) when it's needed
+%D again and/or when I'm bored.
+
+%D Default index:
+
+\defineregister
+ [\v!index]
+% [\v!indices]
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv
new file mode 100644
index 00000000000..6bdd05de96f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv
@@ -0,0 +1,789 @@
+%D \module
+%D [ file=strc-ren,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Section Rendering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Section Rendering}
+
+\unprotect
+
+\newbox\b_strc_rendering_head
+
+\newdimen\d_strc_rendering_local_leftoffset
+\newdimen\d_strc_rendering_local_rightoffset
+
+% Martin Kolarik's problem:
+%
+% \setuphead[section][command=\doTitle]
+% \def\doTitle#1#2{\ruledvbox{\forgetall \hsize=4cm \ruledhbox{\ruledvtop{#1}\ruledvtop{#2}}}}
+% \section{test test test test test test test test test test test test test test test test test}
+
+% \newtoks\everyheadstart % not used currently
+
+\unexpanded\def\strc_rendering_initialize_style_and_color
+ {\ifconditional\headisdisplay
+ \expandafter\strc_rendering_initialize_style_and_color_display
+ \else
+ \expandafter\strc_rendering_initialize_style_and_color_inline
+ \fi}
+
+\unexpanded\def\strc_rendering_initialize_style_and_color_display#1#2%
+ {\dontconvertfont
+ \edef\p_strc_rendering_interlinespace{\headparameter\c!interlinespace}%
+ \ifx\p_strc_rendering_interlinespace\empty
+ % here the interline space is only set when style sets no space
+ \setfalse\fontattributeisset % use the currentfontparameter state instead
+ \setfalse\interlinespaceisset
+ \useheadstyleandcolor\c!style\c!color\relax
+ \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
+ \setupinterlinespace
+ \fi \fi
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor#1#2\relax
+ \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
+ \setupinterlinespace
+ \fi \fi
+ \else
+ % here the set interline space overloads any other set space in the style
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor\c!style\c!color\relax
+ \ifconditional\fontattributeisset
+ \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace
+ \fi
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor#1#2\relax
+ \ifconditional\fontattributeisset
+ \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace
+ \fi
+ \fi}
+
+\unexpanded\def\strc_rendering_initialize_style_and_color_inline#1#2%
+ {\dontconvertfont
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor\c!style\c!color\relax
+ \ifconditional\fontattributeisset
+ \updateraggedskips % \setupspacing
+ \fi
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor#1#2\relax
+ \ifconditional\fontattributeisset
+ \updateraggedskips % \setupspacing
+ \fi}
+
+\let\currentstructurereferenceattribute\attributeunsetvalue
+
+\def\headreferenceattributes
+ {\iflocation
+ % \ctxlua{structures.lists.taglocation(\nextinternalreference)}% maybe ... tags entry as used
+ attr \destinationattribute \currentstructureattribute
+ attr \referenceattribute \currentstructurereferenceattribute
+ % attr \internalattribute \nextinternalreference
+ \fi}
+
+\def\setinlineheadreferenceattributes
+ {\ifconditional\headisdisplay \else \iflocation
+ \attribute\destinationattribute\currentstructureattribute
+ \attribute\referenceattribute \currentstructurereferenceattribute
+ % \attribute\internalattribute \nextinternalreference
+ \fi \fi}
+
+\def\docheckheadreference
+ {\edef\currentheadinteraction{\headparameter\c!interaction}%
+ \ifx\currentheadinteraction\v!list
+ % setuphead[<section>][interaction=list,...]
+ \strc_references_get_simple_reference{*\nextinternalreference}%
+ \let\currentstructurereferenceattribute\currentreferenceattribute
+ \else\ifx\currentheadinteraction\v!reference
+ % setuphead[<section>][interaction=reference,...] start<section>[backreference=abc,...]
+ \edef\currentheadbackreference{\structurevariable\c!backreference}% weird, was references.backreference
+ \ifx\currentheadbackreference\empty \else
+ \strc_references_get_simple_reference\currentheadbackreference
+ \let\currentstructurereferenceattribute\currentreferenceattribute
+ \fi
+ \else
+ % maybe auto: backreference when given, else list
+ \fi\fi}
+
+% a bit messy ... empty in place instead of self .. might change (or use special
+% whatsig (invisible user one)
+
+\unexpanded\def\strc_rendering_place_head_text
+ {\strc_rendering_start_placement
+ \setheadmarking
+ \doresetstructureheadnumbercontent
+ \ifconditional\c_strc_sectioning_empty
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
+ \else
+ \docheckheadreference
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes
+ {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
+ \doresetstructureheadnumbercontent
+ \useheadstyleparameter\c!style
+ \setinlineheadreferenceattributes
+ \strc_rendering_inject_text}%
+ \fi
+ \strc_rendering_stop_placement}
+
+\unexpanded\def\strc_rendering_place_head_number_and_text
+ {\strc_rendering_start_placement
+ \setheadmarking
+ \doifelsetext\getheadnumber
+ \dosetstructureheadnumbercontent
+ \doresetstructureheadnumbercontent
+ \ifconditional\c_strc_sectioning_empty
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
+ \else % = needed
+ \docheckheadreference
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes
+ {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
+ \useheadstyleparameter\c!style
+ \setinlineheadreferenceattributes
+ \strc_rendering_inject_number_and_text}%
+ \fi
+ \strc_rendering_stop_placement}
+
+\unexpanded\def\strc_rendering_place_head_empty
+ {\hbox \headreferenceattributes {\getheadsyncs}}
+
+%D \starttyping
+%D \def\StretchedBox#1%
+%D {\framed
+%D [frame=off,offset=.5em,align=middle,width=broad]
+%D {\sc\def\stretchedspaceamount{.3em}\stretchednormalcase{#1}}}
+%D
+%D \definehead[MySubject][subject]
+%D \setuphead [MySubject][deeptextcommand=\StretchedBox]
+%D
+%D \MySubject{feeling stretched feeling stretched feeling stretched feeling stretched}
+%D \stoptyping
+
+% helpers
+
+% \defineinmargin [ChapterInMargin] [outer] [normal] [distance=0.3em]
+%
+% \defineheadplacement[MyTest][horizontal]#1#2%
+% {\startlocalheadsetup
+% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay
+% \ChapterInMargin{\strut#2}% zero destination, ref okay
+% \stoplocalheadsetup}
+%
+% \setuphead
+% [chapter]
+% [alternative=MyTest]
+
+\unexpanded\def\headhbox{\hbox\headreferenceattributes}
+\unexpanded\def\headvbox{\vbox\headreferenceattributes}
+
+\unexpanded\def\startlocalheadsetup{\bgroup\strc_rendering_initialize_spacing}
+\unexpanded\def\stoplocalheadsetup {\egroup}
+
+\unexpanded\def\strc_rendering_initialize_spacing
+ {\forgetall % local !
+ \edef\p_align{\headparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\headparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_strut{\headparameter\c!strut}%
+ \ifx\p_strut\v!no
+ \setnostrut
+ \fi
+ \let\\\strc_rendering_shortcut_backslash}
+
+\unexpanded\def\strc_rendering_shortcut_backslash
+ {\crlf
+ \strut
+ \ignorespaces}
+
+\def\strc_rendering_start_placement
+ {\bgroup
+ \setsystemmode\currenthead
+ %
+ \strc_rendering_initialize_alternatives
+ \strc_rendering_initialize_dimensions
+ %
+ \strc_rendering_initialize_line_state
+ \reseteverypar % needed indeed
+ \noindent % ipv \whitespace elders, na \forgetall !
+ \bgroup
+ \edef\p_aligntitle{\headparameter\c!aligntitle}%
+ \ifx\p_aligntitle\v!yes
+ \strc_rendering_initialize_hsize_local
+ \else\ifx\p_aligntitle\v!float
+ \strc_rendering_initialize_hsize_local
+ \else
+ \strc_rendering_initialize_hsize_global
+ \fi\fi
+ \setfalse\inhibitmargindata % brrrr is set in forgetall
+ \dontcomplain
+ \postponenotes
+ \strc_rendering_initialize_interaction
+ % delayed
+ \let\localheadsetup \strc_rendering_initialize_spacing % historic name
+ \let\headsetupspacing\strc_rendering_initialize_spacing}
+
+\def\strc_rendering_initialize_hsize_local
+ {\global\d_strc_rendering_local_leftoffset \leftskip
+ \global\d_strc_rendering_local_rightoffset\rightskip
+ % \forgetall
+ % \leftskip \d_strc_rendering_local_leftoffset % no stretch
+ % \rightskip\d_strc_rendering_local_rightoffset % no stretch
+ % \setlocalhsize
+ % \hsize\localhsize
+ % \forgetbothskips}
+ \scratchwidth\availablehsize
+ \forgetall
+ \hsize\scratchwidth}
+
+\def\strc_rendering_initialize_hsize_global
+ {\global\d_strc_rendering_local_leftoffset \zeropoint
+ \global\d_strc_rendering_local_rightoffset\zeropoint
+ \forgetall}
+
+\def\strc_rendering_initialize_interaction
+ {\resetinteractionparameter\c!style
+ \resetinteractionparameter\c!color
+ \resetinteractionparameter\c!contrastcolor}
+
+% \setuphead[chapter] [style=\bfd,after=,hang=line] % fit broad 2
+% \setuphead[section] [style=\bfc,after=,hang=line]
+% \setuphead[subsection] [style=\bfb,after=,hang=line]
+% \setuphead[subsubsection] [style=\bfa,after=,hang=line]
+% \setuphead[subsubsubsection][style=\bf ,after=,hang=line]
+%
+% \chapter {Test} \input tufte \page
+% \section {Test} \input tufte \page
+% \subsection {Test} \input tufte \page
+% \subsubsection {Test} \input tufte \page
+% \subsubsubsection{Test} \input tufte \page
+%
+% \chapter {Test\\Test} \input tufte \page
+% \section {Test\\Test} \input tufte \page
+% \subsection {Test\\Test} \input tufte \page
+% \subsubsection {Test\\Test} \input tufte \page
+% \subsubsubsection{Test\\Test} \input tufte \page
+
+\newdimen\d_strc_rendering_hang_height
+\newcount\n_strc_rendering_hang_lines
+
+\newdimen\d_strc_rendering_local_height
+\newdimen\d_strc_rendering_local_depth
+\newdimen\d_strc_rendering_local_lineheight
+
+\def\strc_rendering_initialize_line_state
+ {\global\d_strc_rendering_local_height\strutht
+ \global\d_strc_rendering_local_depth\strutdp
+ \global\d_strc_rendering_local_lineheight\lineheight}
+
+\def\strc_rendering_check_hang
+ {\begingroup
+ \openlineheight\d_strc_rendering_local_lineheight
+ \d_strc_rendering_hang_height\htdp\b_strc_rendering_head
+ \getnoflines\d_strc_rendering_hang_height
+ \normalexpanded{\endgroup\n_strc_rendering_hang_lines\the\numexpr\noflines-\plusone\relax}% brrr
+ \setbox\b_strc_rendering_head\hbox{\lower\n_strc_rendering_hang_lines\d_strc_rendering_hang_height\box\b_strc_rendering_head}%
+ \d_strc_rendering_hang_height\dimexpr\htdp\b_strc_rendering_head-\d_strc_rendering_local_height+\strutdp\relax
+ \ht\b_strc_rendering_head\strutht
+ \dp\b_strc_rendering_head\strutdp
+ \d_strc_rendering_local_depth\strutdp}
+
+\installcorenamespace{headplacementcheckhang}
+
+\setvalue{\??headplacementcheckhang\v!line }{\strc_rendering_check_hang
+ \n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang\v!broad }{\strc_rendering_check_hang
+ \getnoflines\d_strc_rendering_hang_height}
+\setvalue{\??headplacementcheckhang\v!fit }{\strc_rendering_check_hang
+ \getrawnoflines\d_strc_rendering_hang_height}
+\setvalue{\??headplacementcheckhang\v!none }{\n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang }{\n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang\s!unknown}{\strc_rendering_check_hang
+ \n_strc_rendering_hang_lines\numexpr\headparameter\c!hang-\plusone\relax}
+
+\def\strc_rendering_initialize_line_hang
+ {\ifconditional\headisdisplay
+ \expandnamespaceparameter\??headplacementcheckhang\headparameter\c!hang\s!unknown
+ \relax
+ \else
+ \n_strc_rendering_hang_lines \zerocount
+ \d_strc_rendering_hang_height\zeropoint
+ \fi}
+
+\def\strc_rendering_stop_placement
+ {\n_strc_rendering_hang_lines\zerocount
+ \ifconditional\headisdisplay
+ \strc_rendering_initialize_line_hang
+ % kind of special, we want to snap heads also according to local specs local
+ \ifgridsnapping
+ \hbox\bgroup % extra hbox will trigger global snapper on top of local
+ \edef\p_grid{\headparameter\c!grid}%
+ \ifconditional\headisdisplay
+ \ifx\p_grid\empty\else
+ \useheadstyleandcolor\c!style\c!color
+ \setupinterlinespace
+ \useheadstyleandcolor\c!textstyle\c!textcolor
+ \setupinterlinespace
+ \fi
+ \fi
+ \snaptogrid[\p_grid]\hbox
+ {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}%
+ \egroup
+ \else
+ \hbox
+ {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}%
+ \fi
+ \flushnotes % new, not really needed
+ \endgraf
+ \ifvmode
+ \ifnum\n_strc_rendering_hang_lines>\zerocount
+ \dorecurse\n_strc_rendering_hang_lines{\nointerlineskip\dosomebreak\nobreak\strut\endgraf}% to be checked
+ \fi
+ \nointerlineskip
+ \dosomebreak\nobreak
+ \fi
+ \getheadsyncs
+ \else
+ \strut
+ \flushnotes % new, here since we're in par mode
+ \unhbox\b_strc_rendering_head
+ \getheadsyncs
+ \hskip\headnumberdistance\s!plus\headnumberdistance\s!minus.25\dimexpr\headnumberdistance\relax
+ \strc_sectioning_inject_continuous_signal
+ \fi
+ \ifconditional\headisdisplay
+ \ifvmode
+ \ifgridsnapping % important, font related depth, see comment
+ \prevdepth\strutdp
+ \else
+ \prevdepth\d_strc_rendering_local_depth
+ \fi
+ \fi
+ \fi
+ \egroup
+ \egroup
+ \ifconditional\headisdisplay
+ \useindentnextparameter\headparameter
+ \else
+ \nonoindentation % recently added, was a bug
+ \fi}
+
+% nice testcase
+%
+% \setupheads[aligntitle=yes]
+%
+% \startnarrower
+% \subject{\dorecurse{100}{x }}
+% \section{\dorecurse{100}{x }}
+% \input tufte \par
+% \setupheads[alternative=inmargin]
+% \subject{\dorecurse{100}{x }}
+% \section{\dorecurse{100}{x }}
+% \input tufte \par
+% \stopnarrower
+
+% \dodefineheadplacement[sectiona][vertical]{#1->#2}
+% \dodefineheadplacement[sectionb][vertical]#1#2{#1->#2}
+%
+% \setuphead[section][alternative=sectiona]
+% \setuphead[subsection][alternative=sectionb]
+
+% \startsetups[\??headrenderings:\v!vertical:\v!sectiona]
+% ... there will be a more public namespace
+% \stopsetups
+
+\installcorenamespace{headplacementalternative}
+\installcorenamespace{headrenderings}
+\installcorenamespace{headalternative}
+
+\installcommandhandler \??headalternative {headalternative} \??headalternative % or just \??head
+
+\setupheadalternative
+ [%\c!width=\headparameter\c!width,
+ %\c!distance=\headparameter\c!distance,
+ \c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\currentheadalternative]
+
+\let\currentheadalternative \v!normal
+\let\currentheadrenderingsetup \empty
+\let\currentheadrenderingalternative\v!vertical
+
+\unexpanded\def\defineheadplacement % old mechanism
+ {\dodoubleargument\strc_rendering_define_placement}
+
+\def\strc_rendering_define_placement[#1][#2]%
+ {\doifelsenextbgroup
+ {\strc_rendering_define_placement_yes[#1][#2]}%
+ {\strc_rendering_define_placement_nop[#1][#2]}}
+
+\def\strc_rendering_define_placement_yes[#1][#2]%
+ {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]%
+ \setuvalue{\??headplacementalternative#1}##1##2}
+
+\def\strc_rendering_define_placement_nop[#1][#2]%
+ {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]%
+ \setuvalue{\??headplacementalternative#1}}
+
+% these can be used in setups:
+%
+% \headnumbercontent
+% \headtextcontent
+%
+% \headwidth
+% \headtextwidth
+% \headnumberdistance
+% \headnumberwidth
+% \headsetupspacing
+%
+% \headshownumber
+% \headisdisplay
+
+\let\headnumbercontent\empty
+\let\headtextcontent \empty
+
+\newdimen\headwidth
+\newdimen\headtextwidth
+\newdimen\headnumberdistance
+\newdimen\headnumberwidth
+
+% \newconditional\headshownumber % defined already
+% \newconditional\headisdisplay % defined already
+
+\unexpanded\def\strc_rendering_initialize_alternatives
+ {\edef\currentheadalternative{\headparameter\c!alternative}%
+ \ifcsname\currentheadalternativehash\s!parent\endcsname \else
+ \let\currentheadalternative\v!normal % cf. mkii
+ \fi
+ \edef\currentheadrenderingsetup{\headalternativeparameter\c!renderingsetup}%
+ \edef\currentheadrenderingalternative{\headalternativeparameter\c!alternative}%
+ \ifx\currentheadrenderingalternative\empty
+ \let\currentheadrenderingalternative\v!vertical
+ \fi
+ \ifx\currentheadrenderingalternative\v!horizontal
+ \global\setfalse\headisdisplay % global
+ \else
+ \global\settrue\headisdisplay % global
+ \fi}
+
+\unexpanded\def\strc_rendering_initialize_dimensions
+ {\headwidth \headparameter\c!width \relax % \zeropoint == unset
+ \headnumberwidth \headparameter\c!numberwidth\relax % \zeropoint == unset
+ \headnumberdistance\headparameter\c!distance \relax
+ \headtextwidth \headparameter\c!textwidth \relax} % \zeropoint == unset
+
+\unexpanded\def\headtextcontent
+ {\begingroup
+ \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
+ \headparameter\c!commandbefore\relax
+ \ifcsname\currentheadhash\c!deeptextcommand\endcsname
+ %\expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
+ \expandafter\let\expandafter\deepstructuretitlecommand\lastnamedcs
+ \fi
+ \ifconditional\headisdisplay
+ % struts can be nilled with \setnostrut
+ \headparameter\c!textcommand{\setstrut\begstrut\getheadtitle\endstrut}%
+ \global\d_strc_rendering_local_height\strutht
+ \global\d_strc_rendering_local_depth\strutdp
+ \global\d_strc_rendering_local_lineheight\lineheight
+ \headparameter\c!commandafter\relax
+ \endgraf
+ \else
+ \headparameter\c!textcommand{\getheadtitle}%
+ \headparameter\c!commandafter\relax
+ \fi
+ \endgroup}
+
+\unexpanded\def\headnumbercontent
+ {\begingroup
+ \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
+ \ifcsname\currentheadhash\c!deepnumbercommand\endcsname
+ %\expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
+ \expandafter\let\expandafter\deepstructurenumbercommand\lastnamedcs
+ \fi
+ \ifconditional\headisdisplay
+ % can be nilled with \setnostrut
+ \headparameter\c!numbercommand{\setstrut\begstrut\getheadnumber\endstrut}%
+ \else
+ \headparameter\c!numbercommand{\getheadnumber}%
+ \fi
+ \endgroup}
+
+\def\fakedheadnumber{\vphantom{0}} % needed for mathplus
+
+\unexpanded\def\fakeheadnumbercontent
+ {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}}
+
+\unexpanded\def\strc_rendering_inject_number_and_text
+ {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition
+ \ifx\p_command\empty
+ \directsetup\currentheadrenderingsetup
+ \else
+ \p_command\headnumbercontent\headtextcontent
+ \fi}
+
+\unexpanded\def\strc_rendering_inject_text
+ {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition
+ \ifx\p_command\empty
+ \directsetup\currentheadrenderingsetup
+ \else
+ \p_command\empty\headtextcontent
+ \fi}
+
+\startsetups[\??headrenderings:\v!command]
+ \csname\??headplacementalternative\currentheadalternative\endcsname \headnumbercontent \headtextcontent
+\stopsetups
+
+% obsolete
+%
+% \def\normalplacehead % hooks into \c!command
+% {\csname\??headplacementalternative\ifcsname\??headplacementalternative\currentheadalternative\endcsname\currentheadalternative\else\v!normal\fi\endcsname}
+
+\defineheadalternative
+ [\v!paragraph]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!paragraph]
+
+\startsetups[\??headrenderings:\v!paragraph]
+ \vbox {
+ \headsetupspacing
+ \begstrut
+ \ifconditional\headshownumber % \ifheadnumbercontent
+ \headnumbercontent
+ \hskip\headnumberdistance
+ \fi
+ \headtextcontent
+ }
+\stopsetups
+
+% \setuphead
+% [chapter]
+% [numberwidth=2cm,hang=line,after={\blank[3*line]}]
+%
+% \chapter{Oeps oeps oeps} \input tufte \section{Oeps}
+% \chapter{Oeps oeps oeps} \section{Oeps} \input tufte
+
+\defineheadalternative
+ [\v!normal]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!normal]
+
+\startsetups[\??headrenderings:\v!normal]
+ \vbox {
+ \headsetupspacing
+ \ifconditional\headshownumber
+ \ifdim\headwidth=\zeropoint \else
+ \ifdim\headnumberwidth=\zeropoint
+ \ifdim\headtextwidth=\zeropoint \else
+ \headnumberwidth\dimexpr\headwidth-\headtextwidth\relax
+ \fi
+ \else
+ \ifdim\headtextwidth=\zeropoint
+ \headtextwidth\dimexpr\headwidth-\headnumberwidth\relax
+ \fi
+ \fi
+ \hsize\headwidth
+ \fi
+ \ifdim\headnumberwidth=\zeropoint\else
+ \headnumberdistance\zeropoint
+ \fi
+ \setbox\scratchbox\hbox \ifdim\headnumberwidth=\zeropoint\else to \headnumberwidth\fi{\headnumbercontent}
+ \scratchdimen\dimexpr\wd\scratchbox+\headnumberdistance\relax
+ \ifdim\headtextwidth=\zeropoint\else
+ \hsize\dimexpr\scratchdimen+\headtextwidth\relax
+ \fi
+ \hangindent\scratchdimen
+ \hangafter \plusone
+ \noindent
+ \box\scratchbox
+ \hskip\headnumberdistance
+ \else
+ \ifdim\headtextwidth=\zeropoint
+ \ifdim\headwidth=\zeropoint \else
+ \hsize\headwidth
+ \fi
+ \else
+ \hsize\headtextwidth
+ \fi
+ \noindent
+ \fakeheadnumbercontent % will also be done in the other ones (force consistency with numbered)
+ \fi
+ \headtextcontent
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!inmargin]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!inmargin]
+
+\startsetups[\??headrenderings:\v!inmargin]
+ \vbox {
+ \headsetupspacing
+ \begstrut % use one \strut here!
+ \dontleavehmode % in case there is no strut, else side effects with llap
+ \ifconditional\headshownumber
+ \llap {
+ \signalrightpage
+ \hbox {
+ \hfill
+ \headnumbercontent
+ \doifelserightpage{
+ \scratchdistance\leftmargindistance
+ } {
+ \scratchdistance\rightmargindistance
+ }
+ \hskip\dimexpr\d_strc_rendering_local_leftoffset+\scratchdistance\relax
+ }
+ }
+ \else
+ \fakeheadnumbercontent % will also be done in the other ones (force consistency with numbered)
+ \fi
+ \headtextcontent
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!margin]
+ [\v!inmargin]
+
+% \startsetups[\??headrenderings:\v!vertical:\v!margin]
+% \directsetup{\??headrenderings:\v!vertical:\v!inmargin}
+% \stopsetups
+
+%D This one is for head based numbering usage: foo 1.2 and so:
+
+\defineheadalternative
+ [\v!reverse]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!reverse]
+
+\startsetups[\??headrenderings:\v!reverse]
+ \vbox {
+ \headsetupspacing
+ \noindent
+ \begstrut
+ \setfalse\headisdisplay % so a kind of mix
+ \headtextcontent
+ \ifconditional\headshownumber
+ \kern\headnumberdistance
+ \headnumbercontent
+ \else
+ \fakeheadnumbercontent
+ \fi
+ \endstrut
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!middle]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!middle]
+
+\startsetups[\??headrenderings:\v!middle]
+ \vbox {
+ \headsetupspacing
+ \veryraggedcenter
+ \let\\\endgraf
+ \let\crlf\endgraf
+ \ifconditional\headshownumber
+ \strut
+ \headnumbercontent
+ \par
+ \else
+ \fakeheadnumbercontent
+ \fi
+ \begstrut
+ \headtextcontent
+ \endstrut
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!text]
+ [\c!alternative=\v!horizontal,
+ \c!renderingsetup=\??headrenderings:\v!text]
+
+\startsetups[\??headrenderings:\v!text]
+ \begingroup
+ \headsetupspacing % no stretch in distance
+ \ifconditional\headshownumber
+ \headnumbercontent
+ \kern\headnumberdistance
+ \fi
+ \begstrut
+ \headtextcontent
+ \endstrut
+ \endgroup
+\stopsetups
+
+% onder/boven lijnt het nummer op de onderste/bovenste regel uit van een meerregelige kop
+
+\defineheadalternative
+ [\v!bottom]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!bottom]
+
+\startsetups[\??headrenderings:\v!bottom]
+ \ifconditional\headshownumber
+ \setbox0\hbox {
+ \headnumbercontent
+ }
+ \setbox2\vbox {
+ \headsetupspacing
+ \advance\hsize-\wd0\relax
+ \headtextcontent
+ }
+ \hbox {
+ \box0
+ \hskip\headnumberdistance
+ \box2
+ }
+ \else
+ \vbox {
+ \headsetupspacing
+ \noindent
+ \headtextcontent
+ }
+ \fi
+\stopsetups
+
+\defineheadalternative
+ [\v!top]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!top]
+
+\startsetups[\??headrenderings:\v!top]
+ \ifconditional\headshownumber
+ \setbox0\hbox {
+ \headnumbercontent
+ }
+ \setbox2\vtop {
+ \headsetupspacing
+ \advance\hsize-\wd0\relax
+ \headtextcontent
+ }
+ \hbox {
+ \box0
+ \hskip\headnumberdistance
+ \box2
+ }
+ \else
+ \vtop{
+ \headsetupspacing
+ \noindent
+ \headtextcontent
+ }
+ \fi
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-rsc.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-rsc.lua
new file mode 100644
index 00000000000..627e443b2ce
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-rsc.lua
@@ -0,0 +1,185 @@
+if not modules then modules = { } end modules ['strc-rsc'] = {
+ version = 1.001,
+ comment = "companion to strc-ref.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The scanner is in a separate module so that we can test without too
+-- many dependencies.
+
+-- The scanner accepts nested outer, but we don't care too much, maybe
+-- some day we will have both but currently the innermost wins.
+
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg
+local find = string.find
+
+local spaces = lpegP(" ")^0
+local lparent = lpegP("(")
+local rparent = lpegP(")")
+local lbrace = lpegP("{")
+local rbrace = lpegP("}")
+local tcolon = lpegP(":::") -- component or outer
+local dcolon = lpegP("::") -- outer
+local scolon = lpegP(":") -- prefix
+local backslash = lpegP("\\")
+
+ lparent = spaces * lparent * spaces
+ rparent = spaces * rparent * spaces
+ lbrace = spaces * lbrace * spaces
+ rbrace = spaces * rbrace * spaces
+ tcolon = spaces * tcolon * spaces
+ dcolon = spaces * dcolon * spaces
+
+local endofall = spaces * lpegP(-1)
+
+----- o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient
+----- a_token = 1 - rbrace
+local s_token = 1 - lparent - lbrace
+local i_token = 1 - lparent - lbrace - endofall
+local f_token = 1 - lparent - lbrace - dcolon
+local c_token = 1 - lparent - lbrace - tcolon
+
+-- experimental
+
+local o_token = lpegpatterns.nestedparents
+ + (1 - rparent - lbrace)
+local a_token = lpegpatterns.nestedbraces
+ + (1 - rbrace)
+local q_token = lpegpatterns.unsingle
+ + lpegpatterns.undouble
+
+local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work
+local component = lpegCg(lpegCc("component") * lpegCs(c_token^1))
+local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1))
+----- operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1))
+local operation = lpegCg(lpegCc("operation") * lpegCs(q_token + o_token^1))
+local arguments = lpegCg(lpegCc("arguments") * lpegCs(q_token + a_token^0))
+local special = lpegCg(lpegCc("special") * lpegCs(s_token^1))
+local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1))
+
+ arguments = (lbrace * arguments * rbrace)^-1
+ component = component * tcolon
+ outer = outer * dcolon
+ operation = outer^-1 * operation -- special case: page(file::1) and file::page(1)
+ inner = inner * arguments
+ special = special * lparent * (operation * arguments)^-1 * rparent
+
+local referencesplitter = spaces
+ * lpegCf (lpegCt("") * (component + outer)^-1 * (special + inner)^-1 * endofall, rawset)
+
+local prefixsplitter = lpegCs(lpegP((1-scolon)^1 * scolon))
+ * #-scolon
+ * lpegCs(lpegP(1)^1)
+
+local componentsplitter = lpegCs(lpegP((1-scolon)^1))
+ * scolon * #-scolon
+ * lpegCs(lpegP(1)^1)
+
+prefixsplitter = componentsplitter
+
+local function splitreference(str)
+ if str and str ~= "" then
+ local t = lpegmatch(referencesplitter,str)
+ if t then
+ local a = t.arguments
+ if a and find(a,"\\",1,true) then
+ t.has_tex = true
+ else
+ local o = t.arguments
+ if o and find(o,"\\",1,true) then
+ t.has_tex = true
+ end
+ end
+ return t
+ end
+ end
+end
+
+local function splitprefix(str)
+ return lpegmatch(prefixsplitter,str)
+end
+
+local function splitcomponent(str)
+ return lpegmatch(componentsplitter,str)
+end
+
+-- register in the right namespace
+
+structures = structures or { }
+structures.references = structures.references or { }
+local references = structures.references
+
+references.referencesplitter = referencesplitter
+references.splitreference = splitreference
+references.prefixsplitter = prefixsplitter
+references.splitprefix = splitprefix
+references.componentsplitter = componentsplitter
+references.splitcomponent = splitcomponent
+
+-- test code:
+
+-- inspect(splitreference([[component:::inner]]))
+-- inspect(splitprefix([[component:::inner]]))
+-- inspect(splitprefix([[component:inner]]))
+
+-- inspect(splitreference([[ ]]))
+-- inspect(splitreference([[ inner ]]))
+-- inspect(splitreference([[ special ( operation { argument, argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { argument, \argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { \argument } ) ]]))
+-- inspect(splitreference([[ special ( operation ) ]]))
+-- inspect(splitreference([[ special ( \operation ) ]]))
+-- inspect(splitreference([[ special ( o\peration ) ]]))
+-- inspect(splitreference([[ special ( ) ]]))
+-- inspect(splitreference([[ inner { argument } ]]))
+-- inspect(splitreference([[ inner { \argument } ]]))
+-- inspect(splitreference([[ inner { ar\gument } ]]))
+-- inspect(splitreference([[inner{a\rgument}]]))
+-- inspect(splitreference([[ inner { argument, argument } ]]))
+-- inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg?
+-- inspect(splitreference([[ inner { \argument, \argument } ]]))
+-- inspect(splitreference([[ outer :: ]]))
+-- inspect(splitreference([[ outer :: inner]]))
+-- inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]]))
+-- inspect(splitreference([[ outer :: special (operation { } )]]))
+-- inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]]))
+-- inspect(splitreference([[ outer :: special ( operation ) ]]))
+-- inspect(splitreference([[ outer :: special ( \operation ) ]]))
+-- inspect(splitreference([[ outer :: special ( ) ]]))
+-- inspect(splitreference([[ outer :: inner { argument } ]]))
+-- inspect(splitreference([[ special ( outer :: operation ) ]]))
+
+-- inspect(splitreference([[inner(foo,bar)]]))
+
+-- inspect(splitreference([[]]))
+-- inspect(splitreference([[inner]]))
+-- inspect(splitreference([[special(operation{argument,argument})]]))
+-- inspect(splitreference([[special(operation)]]))
+-- inspect(splitreference([[special(\operation)]]))
+-- inspect(splitreference([[special()]]))
+-- inspect(splitreference([[inner{argument}]]))
+-- inspect(splitreference([[inner{\argument}]]))
+-- inspect(splitreference([[outer::]]))
+-- inspect(splitreference([[outer::inner]]))
+-- inspect(splitreference([[outer::special(operation{argument,argument})]]))
+-- inspect(splitreference([[outer::special(operation{argument,\argument})]]))
+-- inspect(splitreference([[outer::special(operation)]]))
+-- inspect(splitreference([[outer::special(\operation)]]))
+-- inspect(splitreference([[outer::special()]]))
+-- inspect(splitreference([[outer::inner{argument}]]))
+-- inspect(splitreference([[special(outer::operation)]]))
+
+-- inspect(splitreference([[special(operation)]]))
+-- inspect(splitreference([[special(operation(whatever))]]))
+-- inspect(splitreference([[special(operation{argument,argument{whatever}})]]))
+-- inspect(splitreference([[special(operation{argument{whatever}})]]))
+
+-- inspect(splitreference([[special("operation(")]]))
+-- inspect(splitreference([[special("operation(whatever")]]))
+-- inspect(splitreference([[special(operation{"argument,argument{whatever"})]]))
+-- inspect(splitreference([[special(operation{"argument{whatever"})]]))
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv
new file mode 100644
index 00000000000..9f1d214cfda
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv
@@ -0,0 +1,148 @@
+%D \module
+%D [ file=strc-sbe,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Section Block Environments,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Section Block Environments}
+
+\unprotect
+
+% \def\ChapterEntry#1#2#3%
+% {chapter : \hbox to \hsize{\strut\bf#2\hss#3}\endgraf\placelist[section]}
+%
+% \startfrontmatter % optional
+% \placelist[chapter][alternative=command,command=\ChapterEntry,criterium=text] \page
+% \stopfrontmatter % optional
+%
+% \startbodymatter % optional
+% \chapter{first} \section{one} test \section{two} test \page
+% \chapter{second} \section{alpha} test \section{beta} test \page
+% \stopbodymatter % optional
+
+\installcorenamespace{sectionblock}
+
+\installcommandhandler \??sectionblock {sectionblock} \??sectionblock
+
+\setupsectionblock
+ [\c!number=\v!yes,
+ \c!page=\v!right] % otherwise marks are reset too soon
+
+\newtoks\everybeforesectionblock
+\newtoks\everyaftersectionblock
+
+\let\strc_sectionblock_define_normal\definesectionblock
+
+\unexpanded\def\definesectionblock
+ {\dotripleargument\strc_sectionblock_define}
+
+\def\strc_sectionblock_define[#1][#2][#3]% singular plural settings
+ {\strc_sectionblock_define_normal[#1][#3]%
+ \expandafter\newif\csname if#2\endcsname % obsolete
+ \strc_sectionblock_set_environment{#1}\empty
+ \setuvalue{\e!start#2}{\startsectionblock[#1]}%
+ \setuvalue{\e!stop #2}{\stopsectionblock}}
+
+\ifdefined \resetallstructuremarks \else
+ \let\resetallstructuremarks\relax
+\fi
+
+\def\strc_sectionblock_handle_page
+ {\edef\p_strc_sectionblock_page{\sectionblockparameter\c!page}%
+ \ifx\p_strc_sectionblock_page\empty \else
+ \page[\p_strc_sectionblock_page]%
+ \fi}
+
+\appendtoks
+ \strc_sectionblock_handle_page
+ \resetallstructuremarks
+ \strc_sectionblock_get_environment\currentsectionblock
+ \sectionblockparameter\c!before % don't move
+ \dostarttagged\t!division\currentsectionblock % no parents
+\to \everybeforesectionblock
+
+\appendtoks
+ \sectionblockparameter\c!after % don't move
+ \strc_sectionblock_handle_page
+ \dostoptagged
+ \resetallstructuremarks
+\to \everyaftersectionblock
+
+\unexpanded\def\setsectionblock
+ {\dodoubleempty\strc_sectionblock_set}
+
+\def\strc_sectionblock_set[#1][#2]% used to set the default
+ {\edef\currentsectionblock{#1}% from now on we assume a value
+ \setupcurrentsectionblock[#2]%
+ \clf_setsectionblock{#1}
+ bookmark {\sectionblockparameter\c!bookmark}%
+ \relax}
+
+\let\currentsectionblock\empty % was \s!unknown
+
+\unexpanded\def\startsectionblock
+ {\dodoubleempty\strc_sectionblock_start}
+
+\unexpanded\def\strc_sectionblock_start[#1][#2]%
+ {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push)
+ \begingroup
+ \edef\currentsectionblock{#1}% from now on we assume a value
+ \setupcurrentsectionblock[#2]%
+ \clf_pushsectionblock{#1}
+ bookmark {\sectionblockparameter\c!bookmark}%
+ \relax
+ \csname #1true\endcsname % obsolete
+ \setsystemmode\currentsectionblock
+ \the\everybeforesectionblock\relax
+ \showmessage\m!structures1\currentsectionblock}
+
+\unexpanded\def\stopsectionblock
+ {\showmessage\m!structures2\currentsectionblock
+ \the\everyaftersectionblock\relax
+ \clf_popsectionblock
+ \endgroup}
+
+%D \starttyping
+%D \startsectionblockenvironment[frontpart]
+%D \setupnumber[userpage][numberconversion=romannumerals,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \startsectionblockenvironment[bodypart]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \startsectionblockenvironment[backpart]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \starttext
+%D \startfrontmatter \chapter{test} \stopfrontmatter
+%D \startbodymatter \chapter{test} \stopbodymatter
+%D \startappendices \chapter{test} \stopappendices
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{sectionblockenvironment}
+
+\unexpanded\def\strc_sectionblock_set_environment#1#2%
+ {\setvalue{\??sectionblockenvironment#1}{#2}}
+
+\unexpanded\def\strc_sectionblock_get_environment#1%
+ {\csname\??sectionblockenvironment#1\endcsname}
+
+\unexpanded\setvalue{\e!start\v!sectionblockenvironment}%
+ {\dosingleargument\strc_sectionblock_environment_start}
+
+\letvalue{\e!stop\v!sectionblockenvironment}\relax
+
+\def\strc_sectionblock_environment_start[#1]% evt \pushendofline \popendofline
+ {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv
new file mode 100644
index 00000000000..c78cffbffaf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv
@@ -0,0 +1,1208 @@
+%D \module
+%D [ file=strc-sec,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Sectioning,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Sectioning}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+\installcorenamespace{structure}
+
+\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters
+
+\setupstructure % not a user command so we might need to change the name
+ [\c!number=,
+ \c!level=,
+ \c!name=,
+ \c!title=,
+ \c!bookmark=,
+ \c!marking=,
+ \c!list=,
+ \c!label=,
+ \c!coupling=,
+ \c!ownnumber=,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionconversionset=\s!default,
+ \c!sectionstopper=,
+ \c!sectionstarter=,
+ \c!sectionsegments=,
+ \c!sectionresetset=,
+ \c!reference=,
+ \c!backreference=,
+ \c!expansion=\v!no,
+ \c!xmlsetup=,
+ \s!catcodes=,
+ \c!saveinlist=\v!yes]
+
+% maybe flags for list, bm, mark
+
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\def\strc_sectioning_set_reference_prefix
+ {\ifx\currentstructurereferenceprefix\empty
+ % nothing
+ \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes
+ \global\advance\prefixcounter \plusone % temp here
+ \setupglobalreferenceprefix[\the\prefixcounter]%
+ \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop
+ \setupglobalreferenceprefix[]%
+ \else
+ \setupglobalreferenceprefix[\currentstructurereferenceprefix]%
+ \fi\fi\fi
+ \let\currentstructurereferenceprefix\referenceprefix}
+
+% why xdef ?
+
+\setupstructure
+ [\c!label={\headparameter{\currentsectionblock\c!label}},
+ \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed
+ \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi,
+ \c!level=\currentheadlevel,
+ \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
+ \c!expansion=\headparameter\c!expansion,
+ \c!xmlsetup=\headparameter\c!xmlsetup,
+ \s!catcodes=\headparameter\s!catcodes,
+ \c!sectionresetset=\headparameter\c!sectionresetset,
+ \c!sectionseparatorset=\headparameter\c!sectionseparatorset,
+ \c!sectionconversionset=\headparameter\c!sectionconversionset,
+ \c!sectionconversion=\headparameter\c!conversion, % just for compatibility
+ \c!sectionstarter=\headparameter\c!sectionstarter,
+ \c!sectionstopper=\headparameter\c!sectionstopper,
+ \c!sectionset=\headparameter\c!sectionset,
+ \c!sectionsegments=\headparameter\c!sectionsegments,
+ \c!reference=\headparameter\c!reference,
+ \c!referenceprefix=\headparameter\c!referenceprefix]
+
+% see lists/neat-001.tex for usage of:
+
+\def\namedstructureheadlocation#1% expandable, maybe [#1]
+ {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname}
+
+% The next directive only makes sense when we have sort of garanteed outcome (math is not so
+% nice for instance).
+%
+% \enabledirectives[references.bookmarks.preroll]
+
+\newconditional\c_strc_bookmarks_preroll
+
+\installtexdirective
+ {references.bookmarks.preroll}
+ {\settrue \c_strc_bookmarks_preroll}
+ {\setfalse\c_strc_bookmarks_preroll}
+
+\def\strc_sectioning_autobookmark#1%
+ {\begingroup
+ \the\everypreroll
+ \nodestostring\tempstring{#1}%
+ \globallet\currentstructurebookmark\tempstring
+ \endgroup}
+
+% so it's an experiment
+
+\unexpanded\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported)
+ {\begingroup
+ \setupstructure[\c!name={#1},#2]%
+ \xdef\currentstructurename {\structureparameter\c!name}%
+ \xdef\currentstructurecoupling {\structureparameter\c!coupling}%
+ \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number
+ \xdef\currentstructurelevel {\structureparameter\c!level}%
+ \edef\currentstructureexpansion {\structureparameter\c!expansion}%
+ \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}%
+ \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}%
+ \xdef\currentstructurelabel {\structureparameter\c!label}%
+ \xdef\currentstructurereference {\structureparameter\c!reference}%
+ \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}%
+ \xdef\currentstructurebackreference {\structureparameter\c!backreference}%
+ \xdef\currentstructureshownumber {\structureparameter\c!number}%
+ \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}%
+ \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
+ \ifx\currentstructureexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \xmlstopraw
+ \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark\currentstructuretitle
+ \fi \fi \fi
+ \ifx\currentstructurelist\empty
+ \globallet\currentstructurelist\currentstructuretitle
+ \fi
+ \globallet\currentstructurecoding\s!xml
+ \else
+ \ifx\currentstructureexpansion\v!yes
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark\currentstructuretitle
+ \fi \fi \fi
+ \else
+ \xdef\currentstructuretitle {\detokenizedstructureparameter\c!title}%
+ \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}%
+ \xdef\currentstructurelist {\detokenizedstructureparameter\c!list}%
+ \iflocation \ifx\currentstructurebookmark\empty
+ \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark{\structureparameter\c!title}%
+ \else
+ \begingroup
+ \simplifycommands
+ \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}%
+ \endgroup
+ \fi
+ \fi \fi
+ \fi
+ \ifx\currentstructurelist\empty
+ \globallet\currentstructurelist\currentstructuretitle
+ \fi
+ \globallet\currentstructurecoding\s!tex
+ \fi
+ \setnextinternalreference
+ \storeinternalreference\currentstructurename\nextinternalreference %
+ \strc_sectioning_set_reference_prefix
+ \clf_setsectionentry
+ references {
+ internal \nextinternalreference\space
+ % block {\currentsectionblock}
+ prefix {\currentstructurereferenceprefix}
+ reference {\currentstructurereference}
+ backreference {\currentstructurebackreference}
+ }
+ directives {
+ resetset {\structureparameter\c!sectionresetset}
+ }
+ metadata {
+ kind {section}
+ name {\currentstructurename}
+ catcodes \ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space
+ coding {\currentstructurecoding}
+ \ifx\currentstructurecoding\s!xml
+ xmlroot {\xmldocument}
+ \fi
+ \ifx\currentstructurexmlsetup\empty \else
+ xmlsetup {\currentstructurexmlsetup}
+ \fi
+ \ifx\currentstructuresaveinlist\v!no
+ nolist \space true\space
+ \fi
+ \ifx\currentstructureincrementnumber\v!yes
+ increment {\currentstructureincrementnumber}
+ \fi
+ }
+ titledata {
+ label {\detokenize\expandafter{\currentstructurelabel}}
+ title {\detokenize\expandafter{\currentstructuretitle}}
+ \ifx\currentstructurebookmark\currentstructuretitle \else
+ bookmark {\detokenize\expandafter{\currentstructurebookmark}}
+ \fi
+ \ifx\currentstructuremarking\currentstructuretitle \else
+ marking {\detokenize\expandafter{\currentstructuremarking}}
+ \fi
+ \ifx\currentstructuresaveinlist\v!no \else
+ \ifx\currentstructurelist\currentstructuretitle \else
+ list {\detokenize\expandafter{\currentstructurelist}}
+ \fi
+ \fi
+ }
+ numberdata {
+ % block {\currentsectionblock}
+ \ifx\currentstructureshownumber\v!no
+ hidenumber \space true\space
+ \fi
+ separatorset {\structureparameter\c!sectionseparatorset}
+ conversionset {\structureparameter\c!sectionconversionset}
+ conversion {\structureparameter\c!sectionconversion}
+ starter {\structureparameter\c!sectionstarter}
+ stopper {\structureparameter\c!sectionstopper}
+ set {\structureparameter\c!sectionset}
+ segments {\structureparameter\c!sectionsegments}
+ ownnumber {\currentstructureownnumber}
+ language {\currentlanguage}% for the moment, needed for bookmarks conversion
+ }
+ userdata {\detokenize{#3}}% will be converted to table at the lua end
+ \relax
+ \xdef\currentstructurelistnumber{\clf_currentsectiontolist}%
+ % \currentstructuresynchronize has to be called someplace, since it introduces a node
+ \setstructuresynchronization\currentstructurelistnumber
+ \endgroup}
+
+\let\currentsectioncountervalue \!!zerocount % redefined later
+\let\previoussectioncountervalue\!!zerocount % redefined later
+
+% We can access the (stored) data with the following macros.
+%
+% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}}
+% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2}
+%
+% \setuphead[chapter][command=\MyHeadCommand]
+% \setuplist[chapter][alternative=command,command=\MyListCommand]
+%
+% \starttext
+% \setupheadertexts[chapter]
+% \setupinteraction[state=start]
+% \placebookmarks[chapter]
+% \placelist[chapter]
+% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps]
+% \stopchapter
+% \stoptext
+
+% todo: #1 => "#1" ... adapt lua code for name and number
+
+\def\structurenumber {\clf_structurenumber}
+\def\structuretitle {\clf_structuretitle}
+\def\structurevariable #1{\clf_structurevariable {#1}}
+\def\structureuservariable #1{\clf_structureuservariable {#1}}
+\def\structurecatcodedget #1{\clf_structurecatcodedget {#1}} % bad name
+\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name
+\def\structureautocatcodedget #1#2{\clf_structureautocatcodedget {#1}{#2}}
+\def\namedstructurevariable #1#2{\clf_namedstructurevariable {#1}{#2}}
+\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}}
+
+% compatibility issue:
+%
+% \def\setfullsectionnumber #1{}
+% \def\preparefullnumber #1{}
+% \def\fullsectionnumber {1--1--1}
+% \def\makesectionnumber [#1]{}
+% \def\makesectionformat {}
+% \def\sectionformat {1--1-1-1-1-1-1}
+% \def\composedsectionnumber{}
+% \def\@@kolist{}
+
+% \setuphead[section] [separator=\separatorlist{?,!,*}]
+% \setuphead[subsection][separator=\separatorlist{??,!!,**}]
+%
+% \let\spr\separatorlist % this will enable this feature
+%
+% \setuphead[section] [separator={?,!,*}]
+% \setuphead[subsection][separator={??,!!,**}]
+%
+% \setupheads[separator={A,B,C,D,E,F}]
+% \chapter{test}
+% \section{test} \subsection{test} \subsection{test}
+% \section{test} \subsection{test} \subsection{test}
+
+% lua interface / names and interface might change
+
+% \newconditional\c_strc_rendering_continuous % not used (mkii ?)
+
+\def\setstructurelevel #1#2{\clf_setstructurelevel {#1}{#2}} % name, level|parent
+\def\getstructurelevel #1{\clf_getstructurelevel {#1}} % name
+\def\setstructurenumber #1#2{\clf_setstructurenumber #1{#2}} % level, number (+/-)
+\def\getstructurenumber #1{\clf_getstructurenumber \numexpr#1\relax} % level
+\def\getsomestructurenumber #1#2{\clf_getsomestructurenumber #1{#2}} % level, what
+\def\getfullstructurenumber #1{\clf_getfullstructurenumber \numexpr#1\relax} % level
+\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}} % level, what
+\def\getspecificstructuretitle #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}}
+
+% structure heads (like \startchapter)
+
+% \c!deeptextcommand, \c!deepnumbercommand: undefined !
+% \c!before \c!after \c!distance
+% \c!page \c!header \c!text \c!footer=,
+% \c!numbercommand \c!textcommand \c!ownnumber \c!number
+% \c!file \c!grid \c!margintext
+% \c!expansion \c!xmlsetup \s!catcode
+
+\installcorenamespace{head}
+\installcorenamespace{headlevel}
+\installcorenamespace{headincrement}
+\installcorenamespace{headplace}
+\installcorenamespace{headmarkyes}
+\installcorenamespace{headmarknop}
+
+\installcommandhandler \??head {head} \??head
+
+\setuphead [%
+ %\c!after=,
+ %\c!align=,
+ %\c!aligntitle=,
+ \c!alternative=\v!normal,
+ %\c!before=,
+ %\c!color=,
+ %\c!command=,
+ \c!continue=\v!yes,
+ %\c!coupling=,
+ %\c!deepnumbercommand=,
+ %\c!deeptextcommand=,
+ %\c!default=,
+ \c!distance=\zeropoint,
+ \c!textwidth=\zeropoint, % signal too
+ \c!numberwidth=\zeropoint, % signal too
+ \c!width=\zeropoint, % signal too
+ \c!expansion=\v!no,
+ %\c!file=,
+ %\c!footer=,
+ %\c!grid=,
+ \c!hang=\v!none,
+ %\c!header=,
+ \c!incrementnumber=\v!yes,
+ \c!indentnext=\v!no,
+ %\c!label=,
+ %\c!limittext=\languageparameter\c!limittext,
+ \c!margin=\zeropoint,
+ %\c!margintext=,
+ \c!number=\v!yes,
+ \c!numbercolor=\headparameter\c!color,
+ \c!textcolor=\headparameter\c!color,
+ \c!numberstyle=\headparameter\c!style,
+ \c!textstyle=\headparameter\c!style,
+ %\c!numbercommand=,
+ %\c!textcommand=,
+ \c!ownnumber=\v!no,
+ %\c!page=,
+ \c!placehead=\v!yes,
+ \c!sectionconversionset=\s!default,
+ \c!sectionnumber=\v!yes,
+ %\c!sectionsegments=,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionset=\v!all,
+ \c!interlinespace=,
+ %\c!sectionstopper=,
+ %\c!sectionstarter=,
+ %\c!strut=,
+ %\c!style=,
+ %\c!text=,
+ %\c!tolerance=,
+ %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace
+ %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace
+ %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace
+ ]
+
+\let\setupheads\setuphead % will go
+
+\appendtoks
+ \ifx\currentheadparent\empty
+ \edef\currentheaddefault{\headparameter\c!default}%
+ \edef\currentheadsection{\headparameter\c!section}%
+ \ifx\currenthead\currentheaddefault
+ \let\currentheadparent\currentheadsection
+ \else\ifx\currentheaddefault\empty
+ \let\currentheadparent\currentheadsection
+ \else
+ \let\currentheadparent\currentheaddefault
+ \fi\fi
+ \normalexpanded {%
+ \setheadparameter{\c!label}{\currenthead}%
+ \setheadparameter{\c!coupling}{\currenthead}%
+ \setheadparameter{\s!parent}{\??head\currentheadparent}%
+ \definemarking[\currenthead] [\currentheadsection]%
+ \definemarking[\currenthead\v!number][\currentheadsection]%
+ \setupmarking [\currenthead] [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]%
+ \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]%
+ }%
+ \doifelselist\currenthead\donothing
+ {\definelist[\currenthead][\c!prefix=\v!no]}%
+ \else
+ \normalexpanded {%
+ \setheadparameter{\c!label}{\currenthead}%
+ \setheadparameter{\c!coupling}{\currentheadparent}%
+ \definemarking[\currenthead] [\currentheadparent]%
+ \definemarking[\currenthead\v!number][\currentheadparent\c!number]%
+ }%
+ \doifelselist\currenthead\donothing
+ {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}%
+ \fi
+ \presetlabeltext[\currenthead=]%
+ \the\everysetuphead
+\to \everydefinehead
+
+\newtoks\everyredefinehead
+
+\appendtoks
+ \the\everyredefinehead
+\to \everydefinehead
+
+\appendtoks
+ \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}%
+\to \everyredefinehead
+
+\appendtoks
+ % beware, this is a global register
+ \begingroup
+ \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}%
+ \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}%
+ \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}%
+ \clf_registersection {\currenthead} {
+ coupling {\currentsectionheadcoupling}
+ section {\currentsectionheadsection}
+ level \currentsectionlevel
+ parent {\currentheadparent}
+ }%
+ \endgroup
+\to \everyredefinehead
+
+\appendtoks
+ % \setevalue{\e!next \currenthead}{\donexthead [\currenthead]}%
+ \setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}%
+ \setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}%
+\to \everydefinehead
+
+% so \subject as well as \section will need two commands when ownnumber
+% is used (one can disable it anyway for subject) .. this is not downward
+% compatible but better
+
+\appendtoks
+ \doifelse{\headparameter\c!ownnumber}\v!yes
+ {\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}}
+ {\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}%
+\to \everysetuphead
+
+\unexpanded\def\doredefinehead#1#2% called at lua end
+ {\pushmacro\currenthead
+ \pushmacro\currentheadparent
+ \edef\currenthead{#1}%
+ \edef\currentheadparent{#2}%
+ \the\everyredefinehead\relax
+ \popmacro\currentheadparent
+ \popmacro\currenthead}
+
+\let\currentnamedsection\empty
+
+\unexpanded\def\startnamedsection
+ {\dotripleempty\strc_sectioning_start_named_section}
+
+% todo: add grouping but where: before/after trickery .. probably inside because one can always add
+% grouping to the before/after settings
+
+\unexpanded\def\strc_sectioning_start_named_section[#1]% [#2][#3]
+ {\pushmacro\currentnamedsection
+ \edef\currentnamedsection{#1}%
+ \normalexpanded{\strc_sectioning_start_named_section_indeed[\currentnamedsection]}} % [#2][#3]
+
+\unexpanded\def\stopnamedsection
+ {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}%
+ \popmacro\currentnamedsection}
+
+% structure sections (the parents of chapter etc)
+
+\let\firstsectionname\empty
+\let\lastsectionname \empty
+
+\let\resetallstructuremarks \relax
+\let\resetcurrentstructuremarks \relax
+\let\resetcurrentstructuremarkswithpage\relax
+
+\def\resetallstructuremarks {\resetmarking[\firstsectionname]} % will become option (was \v!section-1)
+\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option
+%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option
+
+% We could use a commandhandler here but sections are somewhat special in the
+% sense that we have two ways of chaining: the main section (levels) as well
+% as rendering (head).
+
+% -2 = text
+% -1 = manual
+% 0 = block
+% +1 = structurelevel 1 .. n
+
+\newcount\maxstructuredepth
+
+\def\sectionlevel#1%
+ {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname}
+
+\def\namedsectionlevel#1#2% direct indirect
+ {\csname\??headlevel
+ \ifcsname\??headlevel#1\endcsname
+ #1%
+ \else\ifcsname\??headlevel#2\endcsname
+ #2%
+ \else
+ \v!none
+ \fi\fi
+ \endcsname}
+
+\def\xthenamedheadlevel#1%
+ {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
+\setvalue{\??headlevel\v!block}{0}
+\setvalue{\??headlevel\v!none }{-1}
+\setvalue{\??headlevel\v!text }{-2}
+\setvalue{\??headlevel\v!head }{-3}
+
+\newtoks\everydefinesection
+
+\unexpanded\def\definesection[#1]%
+ {\ifcsname\??headlevel#1\endcsname \else
+ \edef\currentsection{#1}% not used, will go
+ \edef\currenthead{#1}%
+ \global\advance\maxstructuredepth\plusone
+ \setevalue{\??headlevel#1}{\the\maxstructuredepth}%
+ \setstructurelevel{#1}{\sectionlevel{#1}}%
+ \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER
+ \the\everydefinesection
+ % so far for these default inheritances
+ \definemarking[#1]%
+ \ifnum\maxstructuredepth>\plusone
+ \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
+ \fi
+ \xdef\lastsectionname{#1}%
+ \ifx\firstsectionname\empty
+ \glet\firstsectionname\lastsectionname
+ \fi
+ \fi}
+
+\unexpanded\def\setupsection
+ {\dotripleempty\strc_sectioning_setup}
+
+\def\strc_sectioning_setup[#1][#2][#3]%
+ {\ifcsname\??headlevel#1\endcsname
+ \strc_sectioning_setup_indeed[#1][#2][#3]%
+ \else
+ \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]%
+ \fi}
+
+\def\strc_sectioning_setup_indeed[#1][#2][#3]%
+ {\pushmacro\currenthead
+ \ifthirdargument
+ \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now)
+ \setupcurrenthead[#3]%
+ \else
+ \edef\currenthead{#1}%
+ \setupcurrenthead[#2]%
+ \fi
+ \popmacro\currenthead}
+
+% we share the parameters as sections are roots of heads so eventually we can
+% consider \definesection -> \definehead with one argument
+
+\appendtoks
+ % This is a rather practical default that we don't want to
+ % be part of the parent chain lookup mechanism; it's also
+ % mkii compatible. Somewhat weird that it's part of the
+ % top level structure but it will be flattened anyway.
+ \let\currenthead\currentsection %
+ \setheadparameter\c!textstyle {\strictheadparameter\c!style}%
+ \setheadparameter\c!textcolor {\strictheadparameter\c!color}%
+ \setheadparameter\c!numberstyle{\strictheadparameter\c!style}%
+ \setheadparameter\c!numbercolor{\strictheadparameter\c!color}%
+\to \everydefinesection
+
+% head -> head
+
+\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}}
+\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}}
+
+\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling}
+\def\sectionheadsection #1{\namedheadparameter{#1}\c!section}
+
+% head construction
+
+\unexpanded\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed} % [ref] {nr} {title}
+\unexpanded\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed} % [ref] {title}
+\unexpanded\def\strc_sectioning_start {\dotripleempty\strc_sectioning_start_named_section_indeed} % [settings] [userdata] !!! also used at lua end
+
+\newconditional\currentstructureown
+
+\newtoks\everybeforehead % hook, todo: before/after keys
+\newtoks\everyafterhead % hook, todo: before/after keys
+
+\unexpanded\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4%
+ {\settrue\currentstructureown
+ \triggerautostructurelevel
+ \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
+
+\unexpanded\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant
+ {\setfalse\currentstructureown
+ \triggerautostructurelevel
+ \doifelseassignment{#2}\strc_sectioning_handle_nop_indeed_yes\strc_sectioning_handle_nop_indeed_nop{#1}{#2}}
+
+\unexpanded\def\strc_sectioning_handle_nop_indeed_yes#1#2%
+ {\strc_sectioning_handle{#1}{#2}{}}
+
+\unexpanded\def\strc_sectioning_handle_nop_indeed_nop#1#2#3%
+ {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
+
+\unexpanded\def\strc_sectioning_start_named_section_indeed[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
+ {\setfalse\currentstructureown
+ %\globalpushmacro\currenthead % this does not work out well
+ \xdef\currenthead{#1}%
+ \setsystemmode\currenthead % new, also here now
+ \headparameter\c!beforesection % beware, no users vars set yet
+ \the\everybeforehead
+ \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
+ % potential: \bgroup (can be optional: grouped = yes)
+ \headparameter\c!insidesection}
+
+\unexpanded\def\strc_sectioning_stop[#1]% !!! also used at lua end
+ {\dostoptagged
+ \dostoptagged
+ % potential: \egroup
+ %\globalpopmacro\currenthead % so we do a hard recover
+ \xdef\currenthead{#1}% recover
+ \headparameter\c!aftersection
+ \the\everyafterhead
+ \resetsystemmode\currenthead} % new, also here now
+
+\let\dostarthead\strc_sectioning_start % used at lua end
+\let\dostophead \strc_sectioning_stop % used at lua end
+
+% \newconditional\structurereversesectionnumbers % todo: key/val
+
+\newconditional\c_strc_sectioning_to_list
+\newconditional\c_strc_sectioning_increment
+\newconditional\c_strc_sectioning_place
+\newconditional\c_strc_sectioning_empty
+\newconditional\c_strc_sectioning_hidden
+
+\newconditional\headshownumber % public
+\newconditional\headisdisplay % public
+
+\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+
+\unexpanded\def\strc_sectioning_initialize_increment
+ {\edef\currentheadincrement{\headparameter\c!incrementnumber}%
+ \ifcsname\??headincrement\currentheadincrement\endcsname
+ \lastnamedcs
+ \else
+ \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list
+ % \filterheadnumber
+ \fi}
+
+\def\filterheadnumber
+ {\settrue\c_strc_sectioning_increment
+ \settrue\c_strc_sectioning_to_list
+ \ifx\currentproduct\empty
+ % todo : filter from other toc (number, file, title)
+ % use : \currentheadincrement as spec
+ \fi}
+
+\setvalue{\??headplace\v!yes}%
+ {\setfalse\c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
+
+\setvalue{\??headplace\v!empty}%
+ {\settrue \c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
+
+\setvalue{\??headplace\v!no}%
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
+
+\setvalue{\??headplace\v!hidden}%
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \settrue \c_strc_sectioning_hidden}
+
+\unexpanded\def\strc_sectioning_initialize_placement
+ {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes}
+
+\newmode\v!sectionnumber
+
+\def\dosetstructureheadnumbercontent
+ {\setsystemmode\v!sectionnumber
+ \settrue\headshownumber} % why ?
+
+\def\doresetstructureheadnumbercontent
+ {\resetsystemmode\v!sectionnumber
+ \setfalse\headshownumber} % why ?
+
+\unexpanded\def\strc_sectioning_initialize_number
+ {\edef\p_number{\sectionblockparameter\c!number}%
+ \ifx\p_number\v!yes
+ \edef\p_number{\headparameter\c!number}%
+ \ifx\p_number\v!yes
+ \settrue\headshownumber
+ \else
+ \setfalse\headshownumber
+ \fi
+ \else
+ \setfalse\headshownumber
+ \fi}
+
+\newtoks\everyheadsynchronization
+
+\appendtoks
+ \currentstructuresynchronize
+\to \everyheadsynchronization
+
+\unexpanded\def\theheadsynchonization
+ {\the\everyheadsynchronization
+ \currentstructuresynchronize}
+
+% BEWARE: \marking[section]{my text} does not work as we use list indices instead
+% so we need a 'keep track of raw set option' (or maybe a funny internal prefix)
+
+\unexpanded\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this}
+ {\normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}}
+
+\let\deepstructurenumbercommand\relax
+\let\deepstructuretitlecommand \relax
+
+\unexpanded\def\fullheadnumber
+ {\edef\currentheadlabeltag{\currentsectionblock\c!label}%
+ \dostarttagged\t!sectionnumber\empty
+ \labeltexts
+ {\headparameter\currentheadlabeltag}
+ {\ifx\deepstructurenumbercommand\relax
+ \structurenumber
+ \else
+ \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}%
+ \fi}%
+ \dostoptagged}
+
+\unexpanded\def\fullheadtitle
+ {\dostarttagged\t!sectiontitle\empty
+ \ifx\deepstructuretitlecommand\relax
+ \structuretitle
+ \else
+ \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}%
+ \fi
+ \dostoptagged}
+
+\let\currenthead \empty
+\let\currentheadcoupling\empty
+\let\currentheadsection \empty
+\let\currentheadlevel \!!zerocount
+\let\currentheadcounter \!!zerocount
+
+\unexpanded\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care
+\unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care
+
+\unexpanded\def\strc_sectioning_report{\clf_reportstructure}
+
+\ifdefined\strc_rendering_initialize_style_and_color \else
+
+ \unexpanded\def\strc_rendering_initialize_style_and_color#1#2%
+ {\dontconvertfont
+ \useheadstyleandcolor\c!style\c!color
+ \useheadstyleandcolor#1#2%
+ \setupinterlinespace}
+
+\fi
+
+\def\strc_sectioning_place_head_text[#1]%
+ {\dontleavehmode
+ \begingroup
+ \unexpanded\def\\{\space}% messy here, but the default (and needs to be grouped)
+ \settrue\headisdisplay % triggers interlinespace checking
+ \edef\currenthead{#1}%
+ \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
+ \relax
+ \getspecificstructuretitle{\thenamedheadlevel{#1}}%
+ \endgraf
+ \endgroup}
+
+\def\strc_sectioning_place_head_number[#1]%
+ {\dontleavehmode
+ \begingroup
+ \settrue\headisdisplay % triggers interlinespace checking
+ \edef\currenthead{#1}%
+ \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
+ \relax
+ \getfullstructurenumber{\thenamedheadlevel{#1}}%
+ \endgraf
+ \endgroup}
+
+\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi
+
+\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller)
+ {\xdef\currenthead {#1}%
+ \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}%
+ \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}%
+ \xdef\currentheadlevel {\sectionlevel \currentheadsection}%
+ %
+ %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}%
+ %
+ \strc_sectioning_initialize_autolevel
+ \strc_sectioning_initialize_increment
+ \strc_sectioning_initialize_placement
+ \strc_sectioning_initialize_number
+ %
+ \flushingcolumnfloatsfalse
+ %
+ % todo: also mark (for header)
+ %
+ % we might remove the lower level
+ %
+ % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}%
+ %
+% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call
+ %
+ % \currentstructuresynchronize % will move
+ %
+ \let\getheadnumber\empty
+ \let\getheadtitle \empty
+ \let\getheadsyncs \empty
+ \ifconditional\c_strc_sectioning_increment
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \ifconditional\headshownumber
+ \let\getheadnumber\fullheadnumber
+ \strc_rendering_place_head_number_and_text
+ \else
+ \strc_rendering_place_head_text
+ \fi
+ \strc_sectioning_after_yes
+ \else\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_hidden % only something when tracing
+ \else
+ \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_empty % just flush 'm
+ \strc_sectioning_after_nop
+ \fi\fi
+ \else
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \strc_rendering_place_head_text
+ \strc_sectioning_after_yes
+ \else\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_hidden % only something when tracing
+ \else
+ % do nothing / should be vbox to 0pt
+ \strc_sectioning_before_nop
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_empty % just flush 'm
+ \strc_sectioning_after_nop
+ \fi\fi
+ \fi
+ \flushingcolumnfloatstrue
+ \setfalse\c_strc_sectioning_ignore_page
+ % ignorespaces prevents spaces creeping in when after=\dontleavehmode
+ \dostarttagged\t!sectioncontent\empty
+ \ifconditional\headisdisplay
+ \ignorespaces
+ \else
+ \expandafter\GotoPar
+ \fi}
+
+% typesetting (the getters are public)
+
+\unexpanded\def\strc_rendering_place_head_number_and_text
+ {\setheadmarking
+ \getheadnumber/\getheadtitle
+ \getheadsyncs}
+
+\unexpanded\def\strc_rendering_place_head_text
+ {\setheadmarking
+ \getheadtitle
+ \getheadsyncs}
+
+\unexpanded\def\strc_rendering_place_head_empty
+ {\setheadmarking
+ \getheadsyncs}
+
+\installcorenamespace{hiddenheadattr}
+\installcorenamespace{hiddenheadsync}
+
+% todo: when in the page builder we need to resolve the marking immediately
+% because otherwise we have an async
+
+\unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check
+ {\setxvalue{\??hiddenheadattr\currenthead}%
+ {\headreferenceattributes}% can be used when making a box
+ \setxvalue{\??hiddenheadsync\currenthead}%
+ {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax
+ \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
+ \hbox\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference
+ \currentstructuresynchronize}} % and it's a node anyway
+
+\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname}
+\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname}
+
+\unexpanded\def\placerawheaddata [#1]{\synchronizehead{#1}}
+\unexpanded\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}}
+\unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}}
+
+% \setuphead[chapter][placehead=hidden]
+% \chapter {test}
+%
+% %(\synchronizehead{chapter}) % \getheadsyncs
+% %(\getfullstructurenumber{\thenamedheadlevel{chapter}})
+% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}})
+%
+% (\placerawheaddata [chapter])
+% (\placerawheadnumber[chapter])
+% (\placerawheadtext [chapter])
+
+% pagebreaks
+
+\letvalue{\??headmarknop\v!page }\donothing
+\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarknop\s!unknown}\donothing
+
+\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks}
+\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarkyes\s!unknown}\donothing
+
+\def\strc_sectioning_check_layout
+ {\edef\p_page{\headparameter\c!page}%
+ \ifx\p_page\empty
+ \strc_sectioning_check_layout_nop
+ \else
+ \strc_sectioning_check_layout_yes
+ \fi}
+
+\def\strc_sectioning_check_layout_nop
+ {\expandnamespaceparameter\??headmarknop\headparameter\c!marking\s!unknown}
+
+\def\strc_sectioning_check_layout_yes
+ {\page[\p_page]%
+ \expandnamespaceparameter\??headmarkyes\headparameter\c!marking\s!unknown
+ \edef\p_header{\headparameter\c!header}%
+ \ifx\p_header\empty \else
+ \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing
+ \fi
+ \edef\p_text{\headparameter\c!text}%
+ \ifx\p_text\empty \else
+ \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing
+ \fi
+ \edef\p_footer{\headparameter\c!footer}%
+ \ifx\p_footer\empty \else
+ \doifelselayouttextline\v!footer{\normalexpanded{\setuplayouttext[\v!footer][\c!state=\p_footer]}}\donothing
+ \fi}
+
+\newcount \c_strc_sectioning_preceding_level \c_strc_sectioning_preceding_level\plusone
+\newconditional\c_strc_sectioning_auto_break \settrue\c_strc_sectioning_auto_break
+\newconditional\c_strc_sectioning_ignore_page
+\newsignal \s_strc_sectioning_continuous_signal
+
+\unexpanded\def\strc_sectioning_inject_continuous_signal
+ {\ifhmode
+ \hskip\s_strc_sectioning_continuous_signal\relax
+ \fi}
+
+% \let\dotagsectionlevel\relax
+
+\def\strc_sectioning_before_yes
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_yes
+ \headparameter\c!inbetween
+ \dostarttaggedchained\t!section\currenthead\??head
+% \dotagsectionlevel
+ }
+
+\def\strc_sectioning_before_nop
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_nop
+ \headparameter\c!inbetween
+ \dostarttagged\currenthead\empty} % this is a weird one .. needs checking
+
+\def\strc_sectioning_empty_correction
+ {\ifconditional\c_strc_sectioning_empty
+ % this needs checking
+ \penalty\plustenthousand
+ \vskip-\lineheight
+ \kern\zeropoint
+ \prevdepth\strutdepth
+ \fi}
+
+\def\strc_sectioning_after_yes
+ {\ifconditional\headisdisplay
+ \ifconditional\c_strc_sectioning_auto_break
+ % \vspacing[\v!samepage-\currentheadlevel]%
+\vspacing[\v!samepage]%
+ \fi
+ \strc_sectioning_empty_correction
+ \headparameter\c!after
+ \fi}
+
+\def\strc_sectioning_after_nop
+ {}
+
+\def\strc_sectioning_check_before#1%
+ {\ifhmode
+ \scratchcounter\lastpenalty
+ \unpenalty % no beauty in this
+ \ifdim\lastskip=\s_strc_sectioning_continuous_signal
+ % no page break
+ \ifconditional\c_strc_sectioning_ignore_page
+ \setfalse\c_strc_sectioning_ignore_page
+ \else
+ \global\c_strc_sectioning_preceding_level\currentheadlevel
+ \nobreak
+ \fi
+ % \global\settrue\c_strc_rendering_continuous
+ \else
+ \penalty\scratchcounter
+ % \global\setfalse\c_strc_rendering_continuous
+ #1%
+ \fi
+ \else
+ % \global\setfalse\c_strc_rendering_continuous
+ #1%
+ \fi}
+
+\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
+\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
+
+% \def\strc_sectioning_handle_page_nop
+% {\edef\p_continue{\headparameter\c!continue}%
+% \ifx\p_continue\v!yes
+% \ifnum\previoussectioncountervalue=\zerocount
+% \strc_sectioning_check_layout
+% \else\ifnum\currentsectioncountervalue>\zerocount
+% \strc_sectioning_check_layout
+% \fi\fi
+% \else
+% \strc_sectioning_check_layout
+% \fi}
+
+\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
+%def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
+\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax}
+
+\let\previoushead\empty
+
+\def\strc_sectioning_handle_page_nop
+ {\edef\p_continue{\headparameter\c!continue}%
+ \ifx\p_continue\v!yes
+ \ifx\currenthead\previoushead % not really needed
+ \strc_sectioning_check_layout
+ \else\ifnum\previoussectioncountervalue=\zerocount
+ \strc_sectioning_check_layout
+ \else\ifnum\currentsectioncountervalue>\zerocount
+ \strc_sectioning_check_layout
+ \fi\fi\fi
+ \else
+ \strc_sectioning_check_layout
+ \fi
+ \globallet\previoushead\currenthead}
+
+\def\strc_sectioning_handle_page_yes
+ {\ifconditional\c_strc_sectioning_ignore_page
+ \setfalse\c_strc_sectioning_ignore_page
+ \else
+ % beware, these numbers are not yet know here
+ \strc_sectioning_handle_page_nop
+ \edef\p_aligntitle{\headparameter\c!aligntitle}%
+ \ifx\p_aligntitle\v!float
+ \ifconditional\c_strc_sectioning_auto_break
+ \vspacing[\v!samepage-\currentheadlevel]%
+ \fi
+ \headparameter\c!before\relax
+ \indent
+ \else
+ \page_otr_command_flush_side_floats
+ \ifconditional\c_strc_sectioning_auto_break
+ \vspacing[\v!samepage-\currentheadlevel]%
+ \fi
+ \headparameter\c!before\relax
+ \fi
+ \global\c_strc_sectioning_preceding_level\currentheadlevel
+ \fi
+ \globallet\previoushead\currenthead}
+
+\unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con
+ {\ifconditional\c_strc_sectioning_auto_break
+ \vspacing[\v!samepage-\the\numexpr\currentheadlevel+\ifx#1\empty\plusone\else#1\fi\relax]%
+ \fi}
+
+% We do support negative numbers but it can have side effects that we won't catch:
+%
+% \chapter{some} \setupheadnumber[chapter][3] \chapter{more}
+% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d}
+
+\def\thenamedheadlevel#1%
+ {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
+\unexpanded\def\setupheadnumber
+ {\dodoubleargument\strc_sectioning_setup_number}
+
+\def\strc_sectioning_setup_number[#1][#2]% todo: reset if at other level
+ {\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}}
+
+\def\currentheadnumber{0} % ==> \currentheadnumber
+
+\unexpanded\def\determineheadnumber[#1]%
+ {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}}
+
+% The previous macro is been replaced by the expandable:
+
+\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}}
+\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}}
+
+\unexpanded\def\headnumber
+ {\dodoubleempty\strc_sectioning_number}
+
+\def\strc_sectioning_number[#1][#2]% simple case is just a number
+ {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}}
+
+\unexpanded\def\someheadnumber
+ {\dodoubleempty\strc_sectioning_number_some}
+
+\def\strc_sectioning_number_some[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \edef\currenthead{#1}%
+ \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}%
+ \endgroup}
+
+\let\sectioncountervalue\structurevalue
+
+\def\currentheadtext{obsolete,\space use marks}
+
+% list references, will be redone in lua when we need it
+
+\let\startlistreferences\relax
+\let\stoplistreferences \relax
+
+% experimental
+
+\newconditional\c_strc_sectioning_auto_levels
+
+\appendtoks
+ \settrue\c_strc_sectioning_auto_levels
+\to \everyenableelements
+
+\unexpanded\def\strc_sectioning_initialize_autolevel
+ {\ifconditional\c_strc_sectioning_auto_levels
+ \clf_autonextstructurelevel\currentheadlevel\relax
+ \global\setfalse\c_strc_sectioning_auto_levels
+ \fi}
+
+\unexpanded\def\triggerautostructurelevel
+ {\global\settrue\c_strc_sectioning_auto_levels}
+
+\unexpanded\def\finalizeautostructurelevels
+ {\clf_autofinishstructurelevels}
+
+\unexpanded\def\finalizeautostructurelevel
+ {\dostoptagged
+ \dostoptagged}
+
+\appendtoks
+ \finalizeautostructurelevels
+\to \everystoptext
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-syn.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.lua
new file mode 100644
index 00000000000..5f3557a6958
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.lua
@@ -0,0 +1,318 @@
+if not modules then modules = { } end modules ['strc-syn'] = {
+ version = 1.001,
+ comment = "companion to str-syn.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+
+local context = context
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+
+local sorters = sorters
+
+local structures = structures
+local synonyms = structures.synonyms
+local tags = structures.tags
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local firstofsplit = sorters.firstofsplit
+local strip = sorters.strip
+local splitter = sorters.splitters.utf
+
+synonyms.collected = collected
+synonyms.tobesaved = tobesaved
+
+local function initializer()
+ collected = synonyms.collected
+ tobesaved = synonyms.tobesaved
+end
+
+local function finalizer()
+ for entry, data in next, tobesaved do
+ data.hash = nil
+ end
+end
+
+job.register('structures.synonyms.collected', tobesaved, initializer, finalizer)
+
+-- todo: allocate becomes metatable
+
+table.setmetatableindex(tobesaved,function(t,k)
+ local v = {
+ metadata = {
+ language = 'en',
+ sorted = false,
+ class = v
+ },
+ entries = {
+ },
+ hash = {
+ }
+ }
+ t[k] = v
+ return v
+end)
+
+function synonyms.define(class,kind)
+ local data = tobesaved[class]
+ data.metadata.kind = kind
+end
+
+function synonyms.register(class,kind,spec)
+ local data = tobesaved[class]
+ local hash = data.hash
+ local definition = spec.definition
+ local tag = definition.tag or ""
+ data.metadata.kind = kind -- runtime, not saved in format (yet)
+ if not hash[tag] then
+ if definition.used == nil then
+ definition.used = false
+ end
+ if definition.shown == nil then
+ definition.shown = false
+ end
+ local entries = data.entries
+ entries[#entries+1] = spec
+ hash[tag] = spec
+ end
+end
+
+function synonyms.registerused(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.used = true
+ definition.list = true
+ end
+end
+
+function synonyms.registershown(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.shown = true
+ definition.list = true
+ end
+end
+
+function synonyms.isused(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ return okay and okay.definition.used
+end
+
+function synonyms.isshown(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ return okay and okay.definition.shown
+end
+
+function synonyms.resetused(class)
+ for tag, data in next, tobesaved[class].hash do
+ data.definition.used = false
+ end
+end
+
+function synonyms.resetshown(class)
+ for tag, data in next, tobesaved[class].hash do
+ data.definition.shown = false
+ end
+end
+
+function synonyms.synonym(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.used = true
+ definition.list = true
+ context(definition.synonym)
+ end
+end
+
+function synonyms.meaning(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.shown = true
+ definition.list = true
+ context(definition.meaning)
+ end
+end
+
+synonyms.compare = sorters.comparers.basic -- (a,b)
+
+function synonyms.filter(data,options)
+ local result = { }
+ local entries = data.entries
+ local all = options and options.criterium == interfaces.variables.all
+ if all then
+ for i=1,#entries do
+ result[i] = entries[i]
+ end
+ else
+ for i=1,#entries do
+ local entry = entries[i]
+ local definition = entry.definition
+ if definition.list then
+ result[#result+1] = entry
+ end
+ end
+ end
+ data.result = result
+end
+
+function synonyms.prepare(data)
+ local result = data.result
+ if result then
+ for i=1, #result do
+ local entry = result[i]
+ local definition = entry.definition
+ if definition then
+ local tag = definition.tag
+ local key = tag ~= "" and tag or definition.synonym
+ entry.split = splitter(strip(key))
+ end
+ end
+ end
+end
+
+function synonyms.sort(data,options)
+ sorters.sort(data.result,synonyms.compare)
+ data.metadata.sorted = true
+end
+
+function synonyms.finalize(data,options) -- mostly the same as registers so we will generalize it: sorters.split
+ local result = data.result
+ local split = { }
+ local nofsplit = 0
+ local lasttag = nil
+ local lasttag = nil
+ local nofdone = 0
+ for k=1,#result do
+ local entry = result[k]
+ local first, tag = firstofsplit(entry)
+ if tag ~= lasttag then
+ -- if trace_registers then
+ -- report_registers("splitting at %a",tag)
+ -- end
+ done = { }
+ nofdone = 0
+ nofsplit = nofsplit + 1
+ lasttag = tag
+ split[nofsplit] = { tag = tag, data = done }
+ end
+ nofdone = nofdone + 1
+ done[nofdone] = entry
+ end
+ data.result = split
+end
+
+-- for now, maybe at some point we will do a multipass or so
+-- maybe pass the settings differently
+
+local ctx_synonymentry = context.synonymentry
+
+function synonyms.flush(data,options)
+ local result = data.result
+ for i=1,#result do
+ local sublist = result[i]
+ local letter = sublist.tag
+ local data = sublist.data
+ for d=1,#data do
+ local entry = data[d].definition
+ ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "")
+ end
+ end
+ data.result = nil
+ data.metadata.sorted = false
+end
+
+function synonyms.analyzed(class,options)
+ local data = collected[class]
+ if data and data.entries then
+ options = options or { }
+ sorters.setlanguage(options.language,options.method)
+ synonyms.filter(data,options) -- filters entries to result
+ synonyms.prepare(data,options) -- adds split table parallel to list table
+ synonyms.sort(data,options) -- sorts entries in result
+ synonyms.finalize(data,options) -- do things with data.entries
+ data.metadata.sorted = true
+ end
+ return data and data.metadata.sorted and data.result and next(data.result)
+end
+
+function synonyms.process(class,options)
+ if synonyms.analyzed(class,options) then
+ synonyms.flush(collected[class],options)
+ end
+end
+
+-- todo: local higher up
+
+implement { name = "registerusedsynonym", actions = synonyms.registerused, arguments = { "string", "string" } }
+implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = { "string", "string" } }
+implement { name = "synonymmeaning", actions = synonyms.meaning, arguments = { "string", "string" } }
+implement { name = "synonymname", actions = synonyms.synonym, arguments = { "string", "string" } }
+implement { name = "resetusedsynonyms", actions = synonyms.resetused, arguments = "string" }
+implement { name = "resetshownsynonyms", actions = synonyms.resetshown, arguments = "string" }
+
+implement {
+ name = "doifelsesynonymused",
+ actions = { synonyms.isused, commands.doifelse },
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "doifelsesynonymshown",
+ actions = { synonyms.isshown, commands.doifelse },
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "registersynonym",
+ actions = synonyms.register,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "metadata", {
+ { "catcodes", "integer" },
+ { "coding" },
+ { "xmlroot" }
+ }
+ },
+ {
+ "definition", {
+ { "tag" },
+ { "synonym" },
+ { "meaning" },
+ { "used", "boolean" }
+ }
+ }
+ }
+ }
+}
+
+implement {
+ name = "processsynonyms",
+ actions = synonyms.process,
+ arguments = {
+ "string",
+ {
+ { "criterium" },
+ { "language" },
+ { "method" }
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv
new file mode 100644
index 00000000000..72c94d069df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv
@@ -0,0 +1,666 @@
+%D \module
+%D [ file=strc-syn,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Synonyms and Sorting,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting}
+
+\registerctxluafile{strc-syn}{1.001}
+
+%D Although we could nowadays build this on top of regular lists we keep this
+%D more efficient variant around. Eventually we can add some options to lists
+%D that also provide such functionality but at the cost of much more overhead.
+%D
+%D We show a usage of both synonyms and sorts, which are deep down variants of
+%D so called simple lists. A definition looks like this:
+%D
+%D \startbuffer
+%D \definesynonyms
+%D [myabbreviation]
+%D
+%D \setupsynonyms
+%D [myabbreviation]
+%D [headstyle=bold,
+%D headcolor=darkred,
+%D synonymstyle=boldslanted,
+%D synonymcolor=darkblue,
+%D textstyle=slanted,
+%D textcolor=darkgreen,
+%D style=normal,
+%D color=darkyellow]
+%D
+%D \definesorting
+%D [mylogo]
+%D
+%D \setupsorting
+%D [mylogo]
+%D [style=bold,
+%D color=darkmagenta]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D More complex definitions involves commands to call up meanings and such. The
+%D use of the defined commands is as follows: \
+%D
+%D \startbuffer
+%D \myabbreviation [FIRST] {TheFirst} {The First Words}
+%D \myabbreviation [SECOND] {TheSecond} {The Second Words}
+%D \myabbreviation [THIRD] {TheThird} {The Third Words}
+%D
+%D \mylogo [FOURTH] {TheFourth}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D By default a synonym is just typeset and flagges as being used, so that in
+%D a list it wil be shows with its meaning. You can however also expand the
+%D meaning automatically at first use:
+%D
+%D \startbuffer
+%D \setupsynonyms[myabbreviation][alternative=first]
+%D
+%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH.
+%D
+%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D We can change the order, as demonstrated in:
+%D
+%D \startbuffer
+%D \resetshownsynonyms[myabbreviation]
+%D
+%D \setupsynonyms[myabbreviation][alternative=last]
+%D
+%D We have \FIRST\ and \THIRD\ or \FOURTH.
+%D
+%D We have \FIRST\ and \THIRD\ or \FOURTH.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D A list is called up with:
+%D
+%D \startbuffer
+%D \placelistofsynonyms[myabbreviation]
+%D
+%D \placelistofsorts[mylogo]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The lists are constructions (like descriptions are) and can be set up
+%D likewise.
+
+% todo: add 'define only' option to descriptions, then add sorting (also based on key)
+% and call to definition -> replaces this module
+
+\unprotect
+
+% split but common in lua
+
+\def\preprocessexpansion#1#2#3#4% do this at the lua end if still needed
+ {\ifx#1\s!xml
+ \xmlstartraw
+ \xdef#2{#4}%
+ \xmlstopraw
+ \globallet#3\s!xml
+ \else
+ \ifx#1\v!yes
+ \xdef#2{#4}%
+ \else
+ \xdef#2{\detokenize{#4}}%
+ \fi
+ \globallet#3\s!tex
+ \fi}
+
+%D We now use a simple list variant:
+
+\installcorenamespace {simplelist}
+
+\installcommandhandler \??simplelist {simplelist} \??simplelist
+
+\let\setupsimplelists\setupsimplelist
+
+\setupsimplelists[%
+ %c!title=,
+ %c!text=,
+ %
+ %c!style=,
+ %c!color=,
+ %c!command=,
+ %c!align=,
+ %
+ %c!headstyle=,
+ %c!headcolor=,
+ %c!headalign=,
+ %
+ %c!titlestyle=,
+ %c!titlecolor=,
+ %c!titlecommand=,
+ %c!titleleft=,
+ %c!titleright=,
+ %
+ %c!closesymbol=,
+ %c!closecommand=,
+ %
+ \c!alternative=\v!left,
+ \c!display=\v!yes,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %c!hang=,
+ %c!sample=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %c!indentnext=,
+ %c!indenting=,
+ %
+ \c!expansion=\v!no,
+ %c!xmlsetup=,
+ %s!catcodes=,
+ \s!language=\currentmainlanguage,
+]
+
+\appendtoks
+ \setfalse\c_strc_constructions_define_commands
+ \ifx\currentsimplelistparent\empty
+ \defineconstruction[\currentsimplelist][\s!handler=\v!simplelist,\c!level=1]%
+ \else
+ \defineconstruction[\currentsimplelist][\currentsimplelistparent][\s!handler=\v!simplelist,\c!level=1]%
+ \fi
+ \settrue\c_strc_constructions_define_commands
+\to \everydefinesimplelist
+
+\setuvalue{\??constructioninitializer\v!simplelist}%
+ {\let\currentsimplelist \currentconstruction
+ \let\constructionparameter \simplelistparameter
+ \let\constructionnamespace \??simplelist
+ \let\detokenizedconstructionparameter\detokenizedsimplelistparameter
+ \let\letconstructionparameter \letsimplelistparameter
+ \let\useconstructionstyleandcolor \usesimpleliststyleandcolor
+ \let\setupcurrentconstruction \setupcurrentsimplelist}
+
+\setuvalue{\??constructionfinalizer\v!simplelist}%
+ {}
+
+\setuvalue{\??constructiontexthandler\v!simplelist}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \the\everyconstruction
+ \constructionparameter\c!headcommand
+ {\strut
+ \currentsimplelistentry}%
+ \endgroup}
+
+% And we build on top of this.
+
+\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi
+\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi
+
+\definesimplelist
+ [\v!synonym]
+ [\c!state=\v!start,
+ %\c!synonymstyle=,
+ %\c!textstyle=,
+ %\c!headstyle=,
+ %\c!headcolor=,
+ %\c!criterium=,
+ \c!location=\v!left,
+ \c!width=5\emwidth,
+ \c!distance=\zeropoint,
+ %\c!sample=,
+ %\c!hang=,
+ %\c!align=,
+ %\c!before=,
+ %\c!inbetween=,
+ %\c!after=,
+ \c!indentnext=\v!no,
+ %\c!expansion=,
+ \c!method=]
+
+\let\setupsynonyms\setupsimplelist
+
+\unexpanded\def\definesynonyms
+ {\doquadrupleempty\strc_synonyms_define}
+
+\def\strc_synonyms_define[#1][#2][#3][#4]% name plural \meaning \use
+ {\edef\currentsynonym{#1}%
+ \iffourthargument
+ \unexpanded\def#4##1{\strc_synonyms_insert{#1}{##1}}% name tag
+ \ifthirdargument
+ \unexpanded\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning
+ \fi
+ \setuvalue{#1}{\definesynonym[\v!no][#1]}% \name
+ \else
+ \ifthirdargument
+ \unexpanded\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning
+ \fi
+ \setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name
+ \fi
+ %
+% \checksynonymparent
+% \setupcurrentsynonym[\s!single={#1},\s!multi={#2}]%
+ \setfalse\c_strc_constructions_define_commands
+ \definesimplelist
+ [\currentsynonym]%
+ [\v!sorting]
+ [\s!single={#1},%
+ \s!multi={#2}]%
+ \settrue\c_strc_constructions_define_commands
+ %
+ \presetheadtext[#2=\Word{#2}]% changes the \if...argument
+ %
+ \setvalue{\e!setup #2\e!endsetup}{\setupsynonyms[#1]}% obsolete definition
+ \setvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument
+ \setvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}}
+
+\unexpanded\def\definesynonym
+ {\dotripleempty\strc_synonyms_define_entry}
+
+\def\strc_synonyms_define_entry[#1][#2][#3]#4#5%
+ {\begingroup
+ \edef\currentsynonym{#2}%
+ \edef\currentsynonymtag{#3}%
+ \let\currentsimplelist\currentsynonym
+ \ifx\currentsynonymtag\empty
+ \edef\currentsynonymtag{#4}%
+ \fi
+ \ifx\currentsynonymtag\empty
+ % todo: error message
+ \else
+ % this is not that efficient, esp when we load a big list
+ \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}%
+ \preprocessexpansion\currentsynonymexpansion\m_synonyms_text \currentsynonymcoding{#4}%
+ \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#5}%
+ %
+ \clf_registersynonym
+ {\currentsynonym}%
+ {synonym}%
+ {%
+ metadata {%
+ catcodes \catcodetable
+ coding {\currentsynonymcoding}%
+ \ifx\currentsynonymcoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ }%
+ definition {%
+ tag {\currentsynonymtag}%
+ synonym {\m_synonyms_text}%
+ meaning {\m_synonyms_meaning}%
+ % used false
+ }%
+ }%
+ \relax
+ \doif{#1}\v!yes{\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}}%
+ \fi
+ \endgroup}
+
+\unexpanded\def\registersynonym
+ {\dodoubleargument\strc_synonyms_register}
+
+\def\strc_synonyms_register[#1][#2]%
+ {\clf_registerusedsynonym{#1}{#2}}
+
+\unexpanded\def\currentsynonymname {\clf_synonymname {\currentsimplelist}{\currentsynonymtag}}
+\unexpanded\def\currentsynonymmeaning {\clf_synonymmeaning {\currentsimplelist}{\currentsynonymtag}}
+\unexpanded\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsynonymtag}}
+\unexpanded\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}}
+\unexpanded\def\resetusedsynonyms [#1]{\clf_resetusedsynonyms {#1}}
+\unexpanded\def\resetshownsynonyms [#1]{\clf_resetshownsynonyms {#1}}
+
+\let\rawsynonymname \clf_synonymname
+\let\rawsynonymmeaning\clf_synonymmeaning
+
+\installcorenamespace{simplelistalternative} % specific ways of rendering a list
+\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local)
+
+\installcommandhandler \??simplelistalternative {simplelistalternative} \??simplelistalternative
+
+\setupsimplelist
+ [\v!synonym]
+ [\c!alternative=\v!normal]
+
+\unexpanded\def\strc_synonyms_insert_meaning#1#2% name tag
+ {\begingroup
+ \def\currentsimplelist{#1}%
+ \def\currentsynonymtag{#2}%
+ \fastsetup{\??simplelistrenderings::\v!text}%
+ \endgroup}
+
+\unexpanded\def\strc_synonyms_insert#1#2% name tag
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \let \currentsynonym\currentsimplelist % for a while
+ \def \currentsynonymtag{#2}%
+ \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}%
+ \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative
+ {\let\currentsimplelistalternative\v!normal}%
+ \fastsetup{\??simplelistrenderings:\v!synonym:\currentsimplelistalternative}%
+ \normalexpanded{\endgroup\simplelistparameter\c!next}}
+
+% \setupsimplelistalternative
+% [\c!command=\strictsimplelistparameter\c!command]
+
+\definesimplelistalternative
+ [\v!normal]
+ [\c!inbetween=\space,
+ \c!left=(,
+ \c!right=)]
+
+\definesimplelistalternative
+ [\v!first]
+ [\v!normal]
+
+\definesimplelistalternative
+ [\v!last]
+ [\v!normal]
+
+\startsetups[\??simplelistrenderings::\v!synonym]
+ \begingroup
+ \dostarttaggedchained\t!synonym\currentsynonym\??simplelist
+ \dotagsynonym
+ \usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor
+ \simplelistparameter\c!synonymcommand{\currentsynonymname}%
+ \dostoptagged
+ \endgroup
+\stopsetups
+
+\startsetups[\??simplelistrenderings::\v!text]
+ \begingroup
+ \usesimpleliststyleandcolor\c!textstyle\c!textcolor
+ \simplelistparameter\c!textcommand{\currentsynonymmeaning}%
+ \endgroup
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!normal]
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!first]
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ \doifelsecurrentsynonymshown \donothing {
+ \simplelistalternativeparameter\c!inbetween
+ \simplelistalternativeparameter\c!left
+ \fastsetup{\??simplelistrenderings::\v!text}
+ \simplelistalternativeparameter\c!right
+ }
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!last]
+ \doifelsecurrentsynonymshown {
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ } {
+ \fastsetup{\??simplelistrenderings::\v!text}
+ \simplelistalternativeparameter\c!inbetween
+ \simplelistalternativeparameter\c!left
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ \simplelistalternativeparameter\c!right
+ }
+\stopsetups
+
+\unexpanded\def\placelistofsynonyms
+ {\dodoubleempty\strc_synonyms_place_list}
+
+\def\strc_synonyms_place_list[#1][#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \doifelsecommandhandler\??simplelist\currentsimplelist
+ {\strc_constructions_initialize{#1}%
+ \setupcurrentsimplelist[#2]%
+ \let\synonymentry\strc_synonym_normal
+ \startpacked
+ \clf_processsynonyms
+ {#1}%
+ {%
+ criterium {\simplelistparameter\c!criterium}%
+ language {\simplelistparameter\s!language}%
+ method {\simplelistparameter\c!method}%
+ }%
+ \relax
+ \stoppacked}%
+ {}% todo: message that invalid
+ \endgroup}
+
+\def\completelistofsynonyms
+ {\dodoubleempty\strc_synonyms_complete_list}
+
+\def\strc_synonyms_complete_list[#1][#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \doifelsecommandhandler\??simplelist\currentsimplelist
+ {\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}%
+ \strc_synonyms_place_list[#1][#2]%
+ \page
+ \stopnamedsection}%
+ {}% todo: message that invalid
+ \endgroup}
+
+\unexpanded\def\strc_synonym_normal#1#2#3#4%
+ {\begingroup
+ \def\currentsimplelistentry{#3}%
+ \csname\??constructionstarthandler\v!construction\endcsname
+ #4%
+ \csname\??constructionstophandler\v!construction\endcsname
+ \endgroup}
+
+%D Sorting (a simplified version of synonym).
+
+\definesimplelist
+ [\v!sorting]
+ [\c!state=\v!start,
+ %\c!command=, % we test for defined !
+ %\c!criterium=,
+ %\c!style=,
+ %\c!before=,
+ \c!after=\endgraf,
+ %\c!expansion=,
+ \c!method=]
+
+\let\setupsorting\setupsimplelist
+
+\unexpanded\def\definesorting
+ {\dotripleempty\strc_sorting_define}
+
+% if #3=\relax or \v!none, then no command but still protected
+
+\def\strc_sorting_define[#1][#2][#3]%
+ {\edef\currentsorting{#1}%
+ \ifthirdargument
+ \doifnot{#3}\v!none
+ {\ifx#3\relax \else
+ \unexpanded\def#3##1{\strc_sorting_insert{#1}{##1}}%
+ \fi}%
+ \setuvalue{#1}{\definesort[\v!no][#1]}%
+ \else
+ \setuvalue{#1}{\definesort[\v!yes][#1]}%
+ \fi
+ \setfalse\c_strc_constructions_define_commands
+ \definesimplelist
+ [\currentsorting]%
+ [\v!sorting]
+ [\s!single={#1},%
+ \s!multi={#2}]%
+ \settrue\c_strc_constructions_define_commands
+ %
+ \presetheadtext[#2=\Word{#2}]% after \ifthirdargument -)
+ %
+ \setvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition
+ \setvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}%
+ \setvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}}
+
+\unexpanded\def\definesort
+ {\dotripleempty\strc_sorting_define_entry}
+
+\def\strc_sorting_define_entry[#1][#2][#3]#4%
+ {\begingroup
+ \edef\currentsorting{#2}%
+ \edef\currentsortingtag{#3}%
+ \let\currentsimplelist\currentsimplelist
+ \ifx\currentsortingtag\empty
+ \edef\currentsortingtag{#4}%
+ \fi
+ \ifx\currentsortingtag\empty
+ % todo: error message
+ \else
+ \edef\currentsortingexpansion{\simplelistparameter\c!expansion}%
+ \preprocessexpansion\currentsortingexpansion\currentsortingtext\currentsortingcoding{#4}%
+ \clf_registersynonym
+ {\currentsorting}%
+ {sorting}%
+ {%
+ metadata {%
+ catcodes \catcodetable
+ coding {\currentsortingcoding}%
+ \ifx\currentsortingcoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ }%
+ definition {%
+ tag {\currentsortingtag}%
+ synonym {\currentsortingtext}%
+ % used false
+ }%
+ }%
+ \relax
+ \doif{#1}\v!yes{\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}}%
+ \fi
+ \endgroup}
+
+\unexpanded\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}}
+\unexpanded\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}}
+\unexpanded\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}}
+
+\setupsimplelist
+ [\v!sorting]
+ [\c!alternative=\v!normal]
+
+\unexpanded\def\strc_sorting_insert#1#2% name tag
+ {\begingroup
+ % no kap currently, of .. we need to map cap onto WORD
+ \edef\currentsorting{#1}%
+ \def \currentsortingtag{#2}%
+ \let \currentsimplelist\currentsorting
+ \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}%
+ \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative
+ {\let\currentsimplelistalternative\v!normal}%
+ \fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}%
+ \normalexpanded{\endgroup\simplelistparameter\c!next}}
+
+% or:
+%
+% \doifelsesetups{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}
+% {\fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}}
+% {\fastsetup{\??simplelistrenderings:\v!sorting:\v!normal}}
+
+\startsetups [\??simplelistrenderings:\v!sorting:\v!normal]
+ \fastsetup{\??simplelistrenderings::\v!sorting}%
+\stopsetups
+
+\startsetups [\??simplelistrenderings::\v!sorting]
+ \begingroup
+ \dostarttaggedchained\t!sorting\currentsorting\??simplelist
+ \dotagsorting
+ \usesimpleliststyleandcolor\c!style\c!color
+ \currentsortingname
+ \dostoptagged
+ \endgroup
+\stopsetups
+
+\unexpanded\def\registersort
+ {\dodoubleargument\strc_sorting_register}
+
+\def\strc_sorting_register[#1][#2]%
+ {\clf_registerusedsynonym{#1}{#2}}
+
+% before after
+%
+% maybe just 'commandset' and then combine
+
+\unexpanded\def\placelistofsorts
+ {\dodoubleempty\strc_sorting_place_list}
+
+\def\strc_sorting_place_list[#1][#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \strc_constructions_initialize{#1}%
+ \setupcurrentsimplelist[#2]%
+ \edef\p_simplelist_command{\simplelistparameter\c!command}%
+ \ifx\p_simplelist_command\empty
+ \let\synonymentry\strc_sorting_normal
+ \else
+ \let\synonymentry\strc_sorting_command
+ \fi
+ \startpacked
+ \clf_processsynonyms
+ {#1}%
+ {%
+ criterium {\simplelistparameter\c!criterium}%
+ language {\simplelistparameter\s!language}%
+ method {\simplelistparameter\c!method}%
+ }%
+ \relax
+ \stoppacked
+ \endgroup}
+
+\unexpanded\def\completelistofsorts
+ {\dodoubleempty\strc_sorting_complete_list}
+
+\def\strc_sorting_complete_list[#1][#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}%
+ \strc_sorting_place_list[#1][#2]%
+ \page
+ \stopnamedsection
+ \endgroup}
+
+\def\strc_sorting_command#1#2#3#4% #4 is meaning but empty here
+ {\p_simplelist_command{#1}{#2}{#3}}
+
+\def\strc_sorting_normal#1#2#3#4% #4 is meaning but empty here
+ {\begingroup
+ \usesimpleliststyleandcolor\c!style\c!color
+ #3%
+ \endgroup
+ \par}
+
+%D Presets.
+
+% To be considered:
+%
+% \setupsimplelist
+% [\v!sorting]
+% [\c!headstyle=\simplelistparameter\c!synonymstyle,
+% \c!headcolor=\simplelistparameter\c!synonymcolor,
+% \c!style=\simplelistparameter\c!textstyle,
+% \c!color=\simplelistparameter\c!textcolor]
+
+\definesynonyms
+ [\v!abbreviation]
+ [\v!abbreviations]
+ [\infull]
+
+\setupsynonyms
+ [\v!abbreviation]
+ [\c!textstyle=\v!capital]
+
+\definesorting
+ [\v!logo]
+ [\v!logos]
+% [\logogram] % no
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua
new file mode 100644
index 00000000000..8f2e1897810
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua
@@ -0,0 +1,516 @@
+if not modules then modules = { } end modules ['strc-tag'] = {
+ version = 1.001,
+ comment = "companion to strc-tag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is rather experimental code. Tagging happens on the fly and there are two analysers
+-- involved: the pdf backend tagger and the exporter. They share data but there are subtle
+-- differences. Each tag carries a specification and these can be accessed by attribute (the
+-- end of the chain tag) or by so called fullname which is a tagname combined with a number.
+
+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
+
+local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end)
+
+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
+
+-- Tags are internally stored as:
+--
+-- tag>number tag>number tag>number
+
+local p_splitter = C((1-S(">"))^1) * P(">") * C(P(1)^1)
+tagpatterns.splitter = p_splitter
+
+local properties = allocate {
+
+ document = { pdf = "Div", nature = "display" },
+
+ division = { pdf = "Div", nature = "display" },
+ paragraph = { pdf = "P", nature = "mixed" },
+ p = { pdf = "P", nature = "mixed" },
+ construct = { pdf = "Span", nature = "inline" },
+ highlight = { pdf = "Span", nature = "inline" },
+
+ section = { pdf = "Sect", nature = "display" },
+ sectiontitle = { pdf = "H", nature = "mixed" },
+ sectionnumber = { pdf = "H", nature = "mixed" },
+ sectioncontent = { pdf = "Div", nature = "display" },
+
+ itemgroup = { pdf = "L", nature = "display" },
+ item = { pdf = "LI", nature = "display" },
+ itemtag = { pdf = "Lbl", nature = "mixed" },
+ itemcontent = { pdf = "LBody", nature = "mixed" },
+ itemhead = { pdf = "Div", nature = "display" },
+ itembody = { pdf = "Div", nature = "display" },
+
+ description = { pdf = "Div", nature = "display" },
+ descriptiontag = { pdf = "Div", nature = "mixed" },
+ descriptioncontent = { pdf = "Div", nature = "mixed" },
+ descriptionsymbol = { pdf = "Span", nature = "inline" }, -- note reference
+
+ verbatimblock = { pdf = "Code", nature = "display" },
+ verbatimlines = { pdf = "Code", nature = "display" },
+ verbatimline = { pdf = "Code", nature = "mixed" },
+ verbatim = { pdf = "Code", nature = "inline" },
+
+ lines = { pdf = "Code", nature = "display" },
+ line = { pdf = "Code", nature = "mixed" },
+
+ synonym = { pdf = "Span", nature = "inline" },
+ sorting = { pdf = "Span", nature = "inline" },
+
+ register = { pdf = "Div", nature = "display" },
+ registerlocation = { pdf = "Span", nature = "inline" },
+ registersection = { pdf = "Div", nature = "display" },
+ registertag = { pdf = "Span", nature = "mixed" },
+ registerentries = { pdf = "Div", nature = "display" },
+ registerentry = { pdf = "Div", nature = "display" },
+ registercontent = { pdf = "Span", nature = "mixed" },
+ registersee = { pdf = "Span", nature = "mixed" },
+ registerpages = { pdf = "Span", nature = "mixed" },
+ registerpage = { pdf = "Span", nature = "mixed" },
+ registerseparator = { pdf = "Span", nature = "inline" },
+ registerpagerange = { pdf = "Span", nature = "mixed" },
+
+ table = { pdf = "Table", nature = "display" },
+ tablerow = { pdf = "TR", nature = "display" },
+ tablecell = { pdf = "TD", nature = "mixed" },
+
+ tabulate = { pdf = "Table", nature = "display" },
+ tabulaterow = { pdf = "TR", nature = "display" },
+ tabulatecell = { pdf = "TD", nature = "mixed" },
+
+ list = { pdf = "TOC", nature = "display" },
+ listitem = { pdf = "TOCI", nature = "display" },
+ listtag = { pdf = "Lbl", nature = "mixed" },
+ listcontent = { pdf = "P", nature = "mixed" },
+ listdata = { pdf = "P", nature = "mixed" },
+ listpage = { pdf = "Reference", nature = "mixed" },
+
+ delimitedblock = { pdf = "BlockQuote", nature = "display" },
+ delimited = { pdf = "Quote", nature = "inline" },
+ delimitedcontent = { pdf = "Span", nature = "inline" },
+ delimitedsymbol = { pdf = "Span", nature = "inline" },
+ subsentence = { pdf = "Span", nature = "inline" },
+ subsentencecontent = { pdf = "Span", nature = "inline" },
+ subsentencesymbol = { pdf = "Span", nature = "inline" },
+
+ label = { pdf = "Span", nature = "mixed" },
+ number = { pdf = "Span", nature = "mixed" },
+
+ float = { pdf = "Div", nature = "display" }, -- Figure
+ floatcaption = { pdf = "Caption", nature = "mixed" },
+ floatlabel = { pdf = "Span", nature = "inline" },
+ floatnumber = { pdf = "Span", nature = "inline" },
+ floattext = { pdf = "Span", nature = "mixed" },
+ floatcontent = { pdf = "P", nature = "mixed" },
+
+ image = { pdf = "P", nature = "mixed" },
+ mpgraphic = { pdf = "P", nature = "mixed" },
+
+ formulaset = { pdf = "Div", nature = "display" },
+ formula = { pdf = "Div", nature = "display" }, -- Formula
+ formulacaption = { pdf = "Span", nature = "mixed" },
+ formulalabel = { pdf = "Span", nature = "mixed" },
+ formulanumber = { pdf = "Span", nature = "mixed" },
+ formulacontent = { pdf = "P", nature = "display" },
+ subformula = { pdf = "Div", nature = "display" },
+
+ link = { pdf = "Link", nature = "inline" },
+
+ margintextblock = { pdf = "Span", nature = "inline" },
+ margintext = { pdf = "Span", nature = "inline" },
+
+ math = { pdf = "Div", nature = "inline" }, -- no display
+ mn = { pdf = "Span", nature = "mixed" },
+ mi = { pdf = "Span", nature = "mixed" },
+ mo = { pdf = "Span", nature = "mixed" },
+ ms = { pdf = "Span", nature = "mixed" },
+ mrow = { pdf = "Span", nature = "display" },
+ msubsup = { pdf = "Span", nature = "display" },
+ msub = { pdf = "Span", nature = "display" },
+ msup = { pdf = "Span", nature = "display" },
+ merror = { pdf = "Span", nature = "mixed" },
+ munderover = { pdf = "Span", nature = "display" },
+ munder = { pdf = "Span", nature = "display" },
+ mover = { pdf = "Span", nature = "display" },
+ mtext = { pdf = "Span", nature = "mixed" },
+ mfrac = { pdf = "Span", nature = "display" },
+ mroot = { pdf = "Span", nature = "display" },
+ msqrt = { pdf = "Span", nature = "display" },
+ mfenced = { pdf = "Span", nature = "display" },
+ maction = { pdf = "Span", nature = "display" },
+
+ mstacker = { pdf = "Span", nature = "display" }, -- these are only internally used
+ mstackertop = { pdf = "Span", nature = "display" }, -- these are only internally used
+ mstackerbot = { pdf = "Span", nature = "display" }, -- these are only internally used
+ mstackermid = { pdf = "Span", nature = "display" }, -- these are only internally used
+
+ mtable = { pdf = "Table", nature = "display" }, -- might change
+ mtr = { pdf = "TR", nature = "display" }, -- might change
+ mtd = { pdf = "TD", nature = "display" }, -- might change
+
+ ignore = { pdf = "Span", nature = "mixed" }, -- used internally
+ private = { pdf = "Span", nature = "mixed" }, -- for users (like LS) when they need it
+ metadata = { pdf = "Div", nature = "display" },
+ metavariable = { pdf = "Span", nature = "mixed" },
+
+ mid = { pdf = "Span", nature = "inline" },
+ sub = { pdf = "Span", nature = "inline" },
+ sup = { pdf = "Span", nature = "inline" },
+ subsup = { pdf = "Span", nature = "inline" },
+
+ combination = { pdf = "Span", nature = "display" },
+ combinationpair = { pdf = "Span", nature = "display" },
+ combinationcontent = { pdf = "Span", nature = "mixed" },
+ combinationcaption = { pdf = "Span", nature = "mixed" },
+}
+
+tags.properties = properties
+
+local patterns = setmetatableindex(function(t,tag)
+ local v = topattern("^" .. tag .. ">")
+ t[tag] = v
+ return v
+end)
+
+function tags.locatedtag(tag)
+ local attribute = texattribute[a_tagged]
+ if attribute >= 0 then
+ local specification = taglist[attribute]
+ if specification then
+ local taglist = specification.taglist
+ local pattern = patterns[tag]
+ for i=#taglist,1,-1 do
+ local t = taglist[i]
+ if find(t,pattern) then
+ return t
+ end
+ end
+ end
+ else
+ -- enabled but not auto
+ end
+ return false -- handy as bogus index
+end
+
+function structures.atlocation(str)
+ local specification = taglist[texattribute[a_tagged]]
+ if specification then
+ if list then
+ local taglist = specification.taglist
+ local pattern = patterns[str]
+ for i=#list,1,-1 do
+ if find(list[i],pattern) then
+ return true
+ end
+ end
+ end
+ end
+end
+
+function tags.setproperty(tag,key,value)
+ local p = properties[tag]
+ if p then
+ p[key] = value
+ else
+ properties[tag] = { [key] = value }
+ end
+end
+
+function tags.setaspect(key,value)
+ local tag = chain[stacksize]
+ if tag then
+ local p = properties[tag]
+ if p then
+ p[key] = value
+ else
+ properties[tag] = { [key] = value }
+ end
+ end
+end
+
+function tags.registermetadata(data)
+ local d = settings_to_hash(data)
+ if #chain > 1 then
+ if metadata then
+ merge(metadata,d)
+ else
+ metadata = d
+ end
+ else
+ merge(documentdata,d)
+ end
+end
+
+function tags.start(tag,specification)
+ if not enabled then
+ codeinjections.enabletags()
+ enabled = true
+ end
+ --
+ labels[tag] = tag -- can go away
+ --
+ local attribute = #taglist + 1
+ local tagindex = (ids[tag] or 0) + 1
+ --
+ local completetag = tag .. ">" .. tagindex
+ --
+ ids[tag] = tagindex
+ lasttags[tag] = tagindex
+ stacksize = stacksize + 1
+ --
+ chain[stacksize] = completetag
+ stack[stacksize] = attribute
+ tagcontext[tag] = completetag
+ --
+ local tagnesting = { unpack(chain,1,stacksize) } -- a copy so we can add actualtext
+ --
+ if specification then
+ specification.attribute = attribute
+ specification.tagindex = tagindex
+ specification.taglist = tagnesting
+ specification.tagname = tag
+ if metadata then
+ specification.metadata = metadata
+ metadata = nil
+ end
+ local userdata = specification.userdata
+ if user ~= "" and type(userdata) == "string" then
+ specification.userdata = settings_to_hash(userdata)
+ end
+ local detail = specification.detail
+ if detail == "" then
+ specification.detail = nil
+ end
+ local parents = specification.parents
+ if parents == "" then
+ specification.parents = nil
+ end
+ else
+ specification = {
+ attribute = attribute,
+ tagindex = tagindex,
+ taglist = tagnesting,
+ tagname = tag,
+ metadata = metadata,
+ }
+ metadata = nil
+ end
+ --
+ taglist[attribute] = specification
+ specifications[completetag] = specification
+ --
+ if completetag == "document>1" then
+ specification.metadata = documentdata
+ end
+ --
+ texattribute[a_tagged] = attribute
+ return attribute
+end
+
+function tags.restart(attribute)
+ stacksize = stacksize + 1
+ if type(attribute) == "number" then
+ local taglist = taglist[attribute].taglist
+ chain[stacksize] = taglist[#taglist]
+ else
+ chain[stacksize] = attribute -- a string
+ attribute = #taglist + 1
+ taglist[attribute] = { taglist = { unpack(chain,1,stacksize) } }
+ end
+ stack[stacksize] = attribute
+ texattribute[a_tagged] = attribute
+ return attribute
+end
+
+function tags.stop()
+ if stacksize > 0 then
+ stacksize = stacksize - 1
+ end
+ local t = stack[stacksize]
+ if not t then
+ -- if trace_tags then
+ report_tags("ignoring end tag, previous chain: %s",stacksize > 0 and concat(chain," ",1,stacksize) or "none")
+ -- end
+ t = unsetvalue
+ end
+ texattribute[a_tagged] = t
+ return t
+end
+
+function tags.getid(tag,detail)
+ return ids[tag] or "?"
+end
+
+function tags.last(tag)
+ return lasttags[tag] -- or false
+end
+
+function tags.lastinchain(tag)
+ if tag and tag ~= "" then
+ return tagcontext[tag]
+ else
+ return chain[stacksize]
+ end
+end
+
+local strip = C((1-S(">"))^1)
+
+function tags.elementtag()
+ local fulltag = chain[stacksize]
+ if fulltag then
+ return lpegmatch(strip,fulltag)
+ end
+end
+
+function tags.strip(fulltag)
+ return lpegmatch(strip,fulltag)
+end
+
+function tags.setuserproperties(tag,list)
+ if not list or list == "" then
+ tag, list = chain[stacksize], tag
+ else
+ tag = tagcontext[tag]
+ end
+ if tag then -- an attribute now
+ local l = settings_to_hash(list)
+ local s = specifications[tag]
+ if s then
+ local u = s.userdata
+ if u then
+ for k, v in next, l do
+ u[k] = v
+ end
+ else
+ s.userdata = l
+ end
+ else
+ -- error
+ end
+ end
+end
+
+function tags.handler(head) -- we need a dummy
+ return head, false
+end
+
+statistics.register("structure elements", function()
+ if enabled then
+ if stacksize > 0 then
+ return format("%s element chains identified, open chain: %s ",#taglist,concat(chain," => ",1,stacksize))
+ else
+ return format("%s element chains identified",#taglist)
+ end
+ end
+end)
+
+directives.register("backend.addtags", function(v)
+ if not enabled then
+ codeinjections.enabletags()
+ enabled = true
+ end
+end)
+
+-- interface
+
+local starttag = tags.start
+
+implement {
+ name = "starttag",
+ actions = starttag,
+ arguments = { "string" }
+}
+
+implement {
+ name = "stoptag",
+ actions = tags.stop,
+}
+
+implement {
+ name = "starttag_u",
+ scope = "private",
+ actions = function(tag,userdata) starttag(tag,{ userdata = userdata }) end,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "starttag_d",
+ scope = "private",
+ actions = function(tag,detail) starttag(tag,{ detail = detail }) end,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "starttag_c",
+ scope = "private",
+ actions = function(tag,detail,parents) starttag(tag,{ detail = detail, parents = parents }) end,
+ arguments = { "string", "string", "string" }
+}
+
+implement { name = "settagaspect", actions = tags.setaspect, arguments = { "string", "string" } }
+
+implement { name = "settagproperty", actions = tags.setproperty, arguments = { "string", "string", "string" } }
+implement { name = "settagproperty_b", actions = tags.setproperty, arguments = { "string", "'backend'", "string" }, scope = "private" }
+implement { name = "settagproperty_n", actions = tags.setproperty, arguments = { "string", "'nature'", "string" }, scope = "private" }
+
+implement { name = "getelementtag", actions = { tags.elementtag, context } }
+
+implement {
+ name = "setelementuserproperties",
+ scope = "private",
+ actions = tags.setuserproperties,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "doifelseinelement",
+ actions = { structures.atlocation, commands.testcase },
+ arguments = "string",
+}
+
+implement {
+ name = "settaggedmetadata",
+ actions = tags.registermetadata,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv
new file mode 100644
index 00000000000..c9132bf0493
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv
@@ -0,0 +1,523 @@
+%D \module
+%D [ file=strc-tag,
+%D version=2010.07.16,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Tags,
+%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.
+
+% labels: no language needed
+% key/values and other names might change (and probably will)
+
+\writestatus{loading}{ConTeXt Structure Macros / Tags}
+
+\registerctxluafile{strc-tag}{1.001}
+
+\unprotect
+
+%D Eventually these labels will either move to the modules
+%D where they're used, or they will en dup in mult-tag.
+
+\def\t!document {document} % Div
+
+\def\t!division {division} % Div
+\def\t!paragraph {paragraph} % P
+\def\t!p {p} % P
+\def\t!construct {construct} % Span
+\def\t!highlight {highlight} % Span
+
+\def\t!section {section} % Sect
+\def\t!sectiontitle {sectiontitle} % H
+\def\t!sectionnumber {sectionnumber} % H
+\def\t!sectioncontent {sectioncontent} % Div
+
+\def\t!itemgroup {itemgroup} % L
+\def\t!item {item} % Li
+\def\t!itemtag {itemtag} % Lbl
+\def\t!itemcontent {itemcontent} % LBody
+\def\t!itemhead {itemhead} % Div
+\def\t!itembody {itembody} % Div
+
+\def\t!description {description} % Li
+\def\t!descriptiontag {descriptiontag} % Lbl
+\def\t!descriptioncontent {descriptioncontent} % LBody
+\def\t!descriptionsymbol {descriptionsymbol} % Span
+
+\let\t!construction \t!description
+\let\t!constructiontag \t!descriptiontag
+\let\t!constructioncontent \t!descriptioncontent
+\let\t!constructionsymbol \t!descriptionsymbol
+
+\def\t!verbatimblock {verbatimblock} % Code
+\def\t!verbatimlines {verbatimlines} % Code
+\def\t!verbatimline {verbatimline} % Code
+\def\t!verbatim {verbatim} % Code
+
+\def\t!lines {lines} % Code
+\def\t!line {line} % Code
+
+\def\t!sorting {sorting} % Span
+\def\t!synonym {synonym} % Span
+
+\def\t!register {register} % Div
+\def\t!registerlocation {registerlocation} % Span
+\def\t!registersection {registersection} % Div
+\def\t!registertag {registertag} % Span
+\def\t!registerentries {registerentries} % Div
+\def\t!registerentry {registerentry} % Span
+\def\t!registercontent {registercontent} % Span
+\def\t!registersee {registersee} % Span
+\def\t!registerpages {registerpages} % Span
+\def\t!registerpage {registerpage} % Span
+\def\t!registerpagerange {registerpagerange} % Span
+\def\t!registerfrompage {registerfrompage} % Span
+\def\t!registertopage {registertopage} % Span
+\def\t!registerseparator {registerseparator} % Span
+
+\def\t!table {table} % Table
+\def\t!tablerow {tablerow} % TR
+\def\t!tablecell {tablecell} % TD
+\def\t!tabulate {tabulate} % Table
+\def\t!tabulaterow {tabulaterow} % TR
+\def\t!tabulatecell {tabulatecell} % TD
+
+\def\t!math {math} % math
+\def\t!mathtable {mtable} % Table
+\def\t!mathtablerow {mtr} % TR
+\def\t!mathtablecell {mtd} % TD
+\def\t!mathaction {maction} %
+\def\t!mathstacker {mstacker}
+\def\t!mathstackertop {mstackertop}
+\def\t!mathstackermid {mstackermid}
+\def\t!mathstackerbot {mstackerbot}
+
+\def\t!munderover {munderover} % special cases
+\def\t!munder {munder} % special cases
+\def\t!mover {mover} % special cases
+
+\def\t!list {list} % TOC
+\def\t!listitem {listitem} % TOCI
+\def\t!listtag {listtag} % Lbl
+\def\t!listcontent {listcontent} % P
+\def\t!listdata {listdata} % P
+\def\t!listpage {listpage} % Reference
+
+\def\t!delimitedblock {delimited} % BlockQuote
+\def\t!delimited {delimited} % Quote
+\def\t!delimitedsymbol {delimitedsymbol} % Span
+\def\t!delimitedcontent {delimitedcontent} % Span
+\def\t!subsentence {subsentence} % Span
+\def\t!subsentencecontent {subsentencecontent} % Span
+\def\t!subsentencesymbol {subsentencesymbol} % Span
+
+\def\t!float {float} % Div
+\def\t!floatcaption {floatcaption} % Caption
+\def\t!floatlabel {floatlabel} % Span
+\def\t!floattext {floattext} % Span
+\def\t!floatnumber {floatnumber} % Span
+\def\t!floatcontent {floatcontent} % P
+
+\def\t!image {image} % P
+
+\def\t!mpgraphic {mpgraphic} % P
+
+\def\t!formulaset {formulaset} % Div
+\def\t!formula {formula} % Div
+\def\t!formulacaption {formulacaption} % Span
+\def\t!formulalabel {formulalabel} % Span
+\def\t!formulanumber {formulanumber} % P
+\def\t!formulacontent {formulacontent} % P
+\def\t!subformula {subformula} % Div
+
+\def\t!link {link} % Link
+
+\def\t!margintext {margintext} % Span
+\def\t!margintextblock {margintextblock} % Div
+
+% we might opt for verbose variants so this is experimental:
+
+\def\t!label {label} % Span
+\def\t!number {number} % Span
+
+\def\t!ignore {ignore} % Span
+\def\t!private {private} % Span
+
+\def\t!mid {mid} % Span
+\def\t!sub {sub} % Span
+\def\t!sup {sup} % Span
+\def\t!subsup {subsup} % Span
+
+\def\t!unit {unit} % Span
+\def\t!quantity {quantity} % Span
+\def\t!number {number} % Span
+
+\def\t!combination {combination} % Span
+\def\t!combinationpair {combinationpair} % Span
+\def\t!combinationcontent {combinationcontent} % Span
+\def\t!combinationcaption {combinationcaption} % Span
+
+% \setuptaglabeltext
+% [en]
+% [\t!document=document]
+
+% the real code
+
+\definesystemattribute[tagged][public]
+\definesystemattribute[image] [public]
+
+\unexpanded\def\setelementbackendtag{\dodoubleargument\strc_tags_set_backend}
+\unexpanded\def\setelementnature {\dodoubleargument\strc_tags_set_nature}
+
+\def\strc_tags_set_backend[#1][#2]{\clf_settagproperty_b{#1}{#2}} % todo: ignore when no export
+\def\strc_tags_set_nature [#1][#2]{\clf_settagproperty_n{#1}{#2}} % todo: ignore when no export
+
+\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
+
+\installcorenamespace{tagging}
+
+\installsetuponlycommandhandler \??tagging {tagging}
+
+\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
+ \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_yes[#1][#2]%
+ {\clf_starttag_u{#1}{#2}}
+
+\unexpanded\def\strc_tags_element_stop_yes
+ {\clf_stoptag}
+
+\unexpanded\def\strc_tags_element_start_nop_indeed[#1][#2]%
+ {}
+
+\unexpanded\def\strc_tags_element_stop_nop
+ {}
+
+\unexpanded\def\strc_tags_enable_elements
+ {\setuplanguage[\s!default][\s!righthyphenchar="AD]% for the moment here
+ \let\startelement\strc_tags_element_start_yes
+ \let\stopelement \strc_tags_element_stop_yes
+ \let\dosettagproperty\strc_tags_set_aspect_yes}
+
+\unexpanded\def\strc_tags_disable_elements
+ {\let\startelement\strc_tags_element_start_nop
+ \let\stopelement \strc_tags_element_stop_nop
+ \let\dosettagproperty\strc_tags_set_aspect_nop}
+
+% beware: making these unexpanded spoils tables (noalign problem)
+
+\def\strc_tags_enabled_start_no_detail
+ {\iftrialtypesetting
+ \expandafter\strc_tags_start_nop_no_detail
+ \else
+ \expandafter\strc_tags_start_yes_no_detail
+ \fi}
+
+\def\strc_tags_enabled_start_detail
+ {\iftrialtypesetting
+ \expandafter\strc_tags_start_nop_detail
+ \else
+ \expandafter\strc_tags_start_yes_detail
+ \fi}
+
+\def\strc_tags_enabled_start_chained
+ {\iftrialtypesetting
+ \expandafter\strc_tags_start_nop_chained
+ \else
+ \expandafter\strc_tags_start_yes_chained
+ \fi}
+
+\def\strc_tags_enabled_stop
+ {\iftrialtypesetting
+ \expandafter\strc_tags_stop_nop
+ \else
+ \expandafter\strc_tags_stop_yes
+ \fi}
+
+\def\strc_tags_start_yes_no_detail #1{\clf_starttag{#1}}
+\def\strc_tags_start_yes_detail #1#2{\clf_starttag_d{#1}{#2}}
+\def\strc_tags_start_yes_chained #1#2#3{\clf_starttag_c{#1}{#2}{\getcurrentparentchain#3{#2}}}
+\def\strc_tags_stop_yes {\clf_stoptag}
+
+\let\strc_tags_start_nop_no_detail\gobbleoneargument
+\let\strc_tags_start_nop_detail \gobbletwoarguments
+\let\strc_tags_start_nop_chained \gobblethreearguments
+\let\strc_tags_stop_nop \donothing
+
+\def\strc_tags_start_yes_ignore{\clf_starttag{\t!ignore}}
+\let\strc_tags_stop_yes_ignore \strc_tags_stop_yes
+\let\strc_tags_start_nop_ignore\donothing
+\let\strc_tags_stop_nop_ignore \donothing
+
+% more efficient:
+
+% \dostarttagged % {tag} {detail}
+% \dostarttaggedchained % {tag} {detail} \??hash
+% \dostarttaggednodetail % {tag}
+
+% \unexpanded\def\strc_tags_enable
+% {\let\dostarttagged\strc_tags_start_yes
+% \let\dostoptagged \strc_tags_stop_yes}
+
+\unexpanded\def\strc_tags_enable
+ {\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
+ \let\dostartignoretagging \strc_tags_start_yes_ignore
+ \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}
+
+% for luigi (beware: fully expandable):
+
+\def\strc_tags_get_element_tag_yes{\clf_getelementtag}
+\let\strc_tags_get_element_tag_nop\donothing
+
+\unexpanded\def\strc_tags_setup_element_user_properties_yes
+ {\dodoubleempty\strc_tags_setup_element_user_properties_indeed}
+
+\unexpanded\def\strc_tags_setup_element_user_properties_nop
+ {\dodoubleempty\strc_tags_setup_element_user_properties_indeed_nop}
+
+\def\strc_tags_setup_element_user_properties_indeed
+ {\iftrialtypesetting
+ \expandafter\strc_tags_setup_element_user_properties_indeed_nop
+ \else
+ \expandafter\strc_tags_setup_element_user_properties_indeed_yes
+ \fi}
+
+\def\strc_tags_setup_element_user_properties_indeed_nop[#1][#2]{}
+\def\strc_tags_setup_element_user_properties_indeed_yes[#1][#2]{\clf_setelementuserproperties{#1}{#2}}
+
+\unexpanded\def\strc_tags_enable_properties
+ {\let\getelementtag \strc_tags_get_element_tag_yes
+ \let\setupelementuserproperties\strc_tags_setup_element_user_properties_yes}
+
+\unexpanded\def\strc_tags_disable_properties
+ {\let\getelementtag \strc_tags_get_element_tag_nop
+ \let\setupelementuserproperties\strc_tags_setup_element_user_properties_nop}
+
+%D The triggers:
+
+\newtoks\everyenableelements
+\newtoks\everydisableelements
+
+\appendtoks
+ \strc_tags_enable_elements
+ \strc_tags_enable_properties
+ \doifelse{\taggingparameter\c!method}\v!auto\strc_tags_enable\strc_tags_disable
+\to \everyenableelements
+
+\appendtoks
+ \strc_tags_disable_elements
+ \strc_tags_disable_properties
+ \strc_tags_disable
+\to \everydisableelements
+
+\appendtoks
+ \doifelse{\taggingparameter\c!state}\v!start{\the\everyenableelements}{\the\everydisableelements}%
+\to \everysetuptagging
+
+\setuptagging
+ [\c!state=\v!stop,
+ \c!method=\v!auto]
+
+% \unexpanded\def\startparagraph
+% {\dostarttagged\t!paragraph\empty}
+%
+% \unexpanded\def\stopparagraph
+% {% \removeunwantedspaces % yes or no
+% \dostoptagged
+% \par}
+
+% Cf suggestion by Wolfgang we now have named paragraphs. Watch out, the content
+% is grouped but only when we have an instance.
+%
+% \defineparagraph[red] [color=red]
+% \defineparagraph[bold][style=bold]
+%
+% \startparagraph \input ward \stopparagraph
+% \startparagraph[red] \input ward \stopparagraph
+% \startparagraph[bold] \input ward \stopparagraph
+
+\installcorenamespace {paragraph}
+\installcommandhandler \??paragraph {paragraph} \??paragraph
+
+\setupparagraph % someday maybe also strut (beg/end) and align
+ [\c!color=,
+ \c!style=]
+
+\unexpanded\def\startparagraph
+ {\dodoubleempty\paragraph_start}
+
+\def\paragraph_start
+ {\endgraf % we end before the group
+ \begingroup
+ \iffirstargument
+ \ifsecondargument
+ \doubleexpandafter\paragraph_start_two
+ \else
+ \doubleexpandafter\paragraph_start_one
+ \fi
+ \else
+ \expandafter\paragraph_start_zero
+ \fi}
+
+\def\paragraph_start_two[#1][#2]%
+ {\edef\currentparagraph{#1}%
+ \setupcurrentparagraph[#2]%
+ \paragraph_start_indeed}
+
+\def\paragraph_start_one[#1][#2]%
+ {\doifelseassignment{#1}
+ {\let\currentparagraph\empty
+ \setupcurrentparagraph[#1]}
+ {\edef\currentparagraph{#1}}%
+ \paragraph_start_indeed}
+
+\def\paragraph_start_zero[#1][#2]%
+ {\let\currentparagraph\empty
+ \paragraph_start_indeed}
+
+\def\paragraph_start_indeed
+ {\useparagraphstyleandcolor\c!style\c!color
+ \usealignparameter\paragraphparameter
+ \usesetupsparameter\paragraphparameter
+ \dostarttagged\t!paragraph\currentparagraph}
+
+\unexpanded\def\stopparagraph
+ {\dostoptagged
+ \endgraf % we end inside the group
+ \endgroup}
+
+\let\startpar\startparagraph
+\let\stoppar \stopparagraph
+
+\def\strc_tags_document_start_indeed
+ {\glet\strc_tags_document_start_indeed\relax
+ \dostarttagged\t!document\empty}
+
+\def\strc_tags_document_stop_indeed
+ {\glet\strc_tags_document_stop_indeed\relax
+ \dostoptagged}
+
+\appendtoks
+ \strc_tags_document_start_indeed % here because otherwise products don't get a root (starttext before env)
+\to \everyenableelements
+
+% \appendtoks
+% \strc_tags_document_start_indeed
+% \to \everystarttext
+
+\appendtoks
+ \strc_tags_document_stop_indeed
+\to \everystoptext
+
+\appendtoks
+ \strc_tags_disable_elements
+ \strc_tags_disable
+\to \everybeforepagebody
+
+%D This will only work well with sane use.
+
+\appendtoks
+ \dostartignoretagging
+\to \everybeforepagebody
+
+\appendtoks
+ \dostopignoretagging
+\to \everyafterpagebody
+
+% \doifelseinelement{structure:section} {yes} {no}
+% \doifelseinelement{structure:chapter} {yes} {no}
+% \doifelseinelement{division:*-structure:chapter} {yes} {no}
+
+\unexpanded\def\doifelseinelement#1%
+ {\clf_doifelseinelement{#1}}
+
+\let\doifinelementelse\doifelseinelement
+
+\unexpanded\def\taggedlabeltexts#1#2#3% experimental: label, numberdetail, numbercontent
+ {\begingroup
+ \dostarttagged\t!label{#1}%
+ \labeltexts{#1}%
+ {\dostoptagged
+ \dostarttagged\t!number{#2}%
+ #3%
+ \dostoptagged
+ \dostarttagged\t!label{#1}}%
+ \dostoptagged
+ \endgroup}
+
+\unexpanded\def\namedtaggedlabeltexts#1#2#3#4#5% experimental: labeltag label numbertag numberdetail numbercontent
+ {\begingroup
+ \dostarttagged{#1}{#2}%
+ \labeltexts{#2}%
+ {\dostoptagged
+ \dostarttagged{#3}{#4}%
+ #5%
+ \dostoptagged
+ \dostarttagged{#1}{#2}}%
+ \dostoptagged
+ \endgroup}
+
+%D Metadata is added after the following structure element so
+%D here we get some as child of the document root and some as child
+%D of the chapter element.
+%D
+%D \settaggedmetadata[title=Hello World!,author=Hans Hagen]
+%D
+%D \starttyping
+%D \starttext
+%D \startelement[ignore]
+%D \input tufte
+%D \stopelement
+%D \par \input ward \par
+%D \settaggedmetadata[whatever=Again and Again]
+%D \startchapter[title=test]
+%D \input ward
+%D \stopchapter
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\settaggedmetadata[#1]%
+ {\clf_settaggedmetadata{#1}}
+
+%D An overload:
+
+\let\strc_tagged_saved_bpar\bpar
+\let\strc_tagged_saved_epar\epar
+
+\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar}
+\unexpanded\def\epar{\strc_tagged_saved_epar\dostoptagged}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-xml.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-xml.mkiv
new file mode 100644
index 00000000000..3f9b4ef811d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-xml.mkiv
@@ -0,0 +1,146 @@
+%D \module
+%D [ file=strc-xml,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=XML Processing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / XML Processing}
+
+% This might disappear.
+
+\unprotect
+
+\startxmlsetups xml:ctx:internal:setup
+ \xmlsetsetup{#1}{ctx:genericentry} {xml:ctx:genericentry}
+ \xmlsetsetup{#1}{ctx:sectionentry} {xml:ctx:sectionentry}
+ \xmlsetsetup{#1}{ctx:registerentry}{xml:ctx:registerentry}
+\stopxmlsetups
+
+\xmlregistersetup{xml:ctx:internal:setup}
+
+\startxmlsetups xml:ctx:genericentry
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:ctx:sectionentry
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:ctx:registerentry
+ \xmlflush{#1}
+\stopxmlsetups
+
+\protect \endinput
+
+% test.xml
+
+<?xml version='1.0' standalone='yes?>
+
+<document>
+ <section>
+ <title>Some <b>bold</b> title <b>bold <i>bold</i> oeps</b> and more</title>
+ <content>
+ <p>a paragraph of text</p>
+ <p>another paragraph of text</p>
+ </content>
+ </section>
+ <section>
+ <title>Another <b>bold</b> title <b>bold <i>bold</i> oeps</b> and more</title>
+ <content>
+ <p>a paragraph of text</p>
+ <p>another paragraph of text</p>
+ </content>
+ </section>
+</document>
+
+% test.tex
+
+\setuphead[chapter][expansion=xml]
+
+\startxmlsetups xml:demo:define:base
+ \xmlsetsetup{demo}{document|section|p|b|i}{xml:demo:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{demo}{xml:demo:define:base}
+
+\startxmlsetups xml:demo:document
+ \title{Contents}
+ \placelist[chapter]
+ \page
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:demo:section
+ \chapter{\xmltext{#1}{/title}}
+ \xmlfirst{#1}{/content}
+\stopxmlsetups
+
+\startxmlsetups xml:demo:p
+ \xmlflush{#1}\endgraf
+\stopxmlsetups
+
+\startxmlsetups xml:demo:b
+ \bgroup\bf\xmlflush{#1}\egroup
+\stopxmlsetups
+
+\startxmlsetups xml:demo:i
+ \bgroup\it\xmlflush{#1}\egroup
+\stopxmlsetups
+
+\starttext
+ \xmlprocessfile{demo}{oeps.xml}{}
+\stoptext
+
+% example by thomas:
+
+\startbuffer[test]
+<auth>
+ <section>
+ <title><emph>MyTitle</emph></title>
+ <content>
+ Hello world
+ </content>
+ </section>
+</auth>
+\stopbuffer
+
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{\xmldocument}{auth|section|title|content|emph}{xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:mysetups}
+
+\startxmlsetups xml:auth
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:section
+ \xmlflush{#1}\par \midaligned{\hl[5]}
+\stopxmlsetups
+
+\startxmlsetups xml:title
+ \section{\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups xml:content
+ \xmlflush{#1}\par
+\stopxmlsetups
+
+\startxmlsetups xml:emph
+ {\bgroup\em \xmlflush{#1}\egroup}
+\stopxmlsetups
+
+\setuphead
+ [section]
+ [style=normal,number=no,expansion=yes,page=yes]
+
+\starttext
+ \xmlprocessbuffer{main}{test}{}
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua
new file mode 100644
index 00000000000..d3a4f57e54b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua
@@ -0,0 +1,420 @@
+if not modules then modules = { } end modules ['supp-box'] = {
+ version = 1.001,
+ comment = "companion to supp-box.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this is preliminary code, use insert_before etc
+
+local lpegmatch = lpeg.match
+
+local report_hyphenation = logs.reporter("languages","hyphenation")
+
+local tex = tex
+local context = context
+local nodes = nodes
+
+local implement = interfaces.implement
+
+local splitstring = string.split
+
+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 kern_code = nodecodes.kern
+local glyph_code = nodecodes.glyph
+
+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 getdisc = nuts.getdisc
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattribute = nuts.getattribute
+local getbox = nuts.getbox
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setboth = nuts.setboth
+local setnext = nuts.setnext
+local setbox = nuts.setbox
+local setlist = nuts.setlist
+
+local free_node = nuts.free
+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 link_nodes = nuts.linked
+local dimensions = nuts.dimensions
+
+local listtoutf = nodes.listtoutf
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_hlist = nodepool.hlist
+local new_glue = nodepool.glue
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+
+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)
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ local prev = getprev(current)
+ if id == disc_code then
+ local pre, post, replace = getdisc(current)
+ if pre then
+ setfield(current,"pre",nil)
+ end
+ if post then
+ setfield(current,"post",nil)
+ end
+ if not usecolor then
+ -- nothing fancy done
+ elseif pre and post then
+ setlistcolor(pre,"darkmagenta")
+ setlistcolor(post,"darkcyan")
+ elseif pre then
+ setlistcolor(pre,"darkyellow")
+ elseif post then
+ setlistcolor(post,"darkyellow")
+ end
+ if replace then
+ flush_list(replace)
+ setfield(current,"replace",nil)
+ end
+ -- setfield(current,"replace",new_rule(65536)) -- new_kern(65536*2))
+ setboth(current)
+ local list = link_nodes (
+ pre and new_penalty(10000),
+ pre,
+ current,
+ post,
+ post and new_penalty(10000)
+ )
+ local tail = find_tail(list)
+ if prev then
+ setlink(prev,list)
+ end
+ if next then
+ setlink(tail,next)
+ end
+ -- free_node(current)
+ elseif id == vlist_code or id == hlist_code then
+ hyphenatedlist(getlist(current))
+ end
+ current = next
+ end
+end
+
+implement {
+ name = "hyphenatedlist",
+ arguments = { "integer", "boolean" },
+ actions = function(n,color)
+ local b = texgetbox(n)
+ if b then
+ hyphenatedlist(b.list,color)
+ end
+ end
+}
+
+-- local function hyphenatedhack(head,pre)
+-- pre = tonut(pre)
+-- for n in traverse_id(disc_code,tonut(head)) do
+-- local hyphen = getfield(n,"pre")
+-- if hyphen then
+-- flush_list(hyphen)
+-- end
+-- setfield(n,"pre",copy_list(pre))
+-- end
+-- end
+--
+-- commands.hyphenatedhack = hyphenatedhack
+
+local function checkedlist(list)
+ if type(list) == "number" then
+ return getlist(getbox(tonut(list)))
+ else
+ return tonut(list)
+ end
+end
+
+implement {
+ name = "showhyphenatedinlist",
+ arguments = "integer",
+ actions = function(box)
+ report_hyphenation("show: %s",listtoutf(checkedlist(n),false,true))
+ end
+}
+
+local function applytochars(current,doaction,noaction,nested)
+ while current do
+ local id = getid(current)
+ if nested and (id == hlist_code or id == vlist_code) then
+ context.beginhbox()
+ applytochars(getlist(current),doaction,noaction,nested)
+ context.endhbox()
+ elseif id ~= glyph_code then
+ noaction(tonode(copy_node(current)))
+ else
+ doaction(tonode(copy_node(current)))
+ end
+ current = getnext(current)
+ end
+end
+
+local function applytowords(current,doaction,noaction,nested)
+ local start
+ while current do
+ local id = getid(current)
+ if id == glue_code then
+ if start then
+ doaction(tonode(copy_list(start,current)))
+ start = nil
+ end
+ noaction(tonode(copy_node(current)))
+ elseif nested and (id == hlist_code or id == vlist_code) then
+ context.beginhbox()
+ applytowords(getlist(current),doaction,noaction,nested)
+ context.egroup()
+ elseif not start then
+ start = current
+ end
+ current = getnext(current)
+ end
+ if start then
+ doaction(tonode(copy_list(start)))
+ end
+end
+
+local methods = {
+ char = applytochars,
+ characters = applytochars,
+ word = applytowords,
+ words = applytowords,
+}
+
+implement {
+ name = "applytobox",
+ arguments = {
+ {
+ { "box", "integer" },
+ { "command" },
+ { "method" },
+ { "nested", "boolean" },
+ }
+ },
+ actions = function(specification)
+ local list = checkedlist(specification.box)
+ local action = methods[specification.method or "char"]
+ if list and action then
+ action(list,context[specification.command or "ruledhbox"],context,specification.nested)
+ end
+ end
+}
+
+local split_char = lpeg.Ct(lpeg.C(1)^0)
+local split_word = lpeg.tsplitat(lpeg.patterns.space)
+local split_line = lpeg.tsplitat(lpeg.patterns.eol)
+
+local function processsplit(specification)
+ local str = specification.data or ""
+ local command = specification.command or "ruledhbox"
+ local method = specification.method or "word"
+ local spaced = specification.spaced
+ if method == "char" or method == "character" then
+ local words = lpegmatch(split_char,str)
+ for i=1,#words do
+ local word = words[i]
+ if word == " " then
+ if spaced then
+ context.space()
+ end
+ elseif command then
+ context[command](word)
+ else
+ context(word)
+ end
+ end
+ elseif method == "word" then
+ local words = lpegmatch(split_word,str)
+ for i=1,#words do
+ local word = words[i]
+ if spaced and i > 1 then
+ context.space()
+ end
+ if command then
+ context[command](word)
+ else
+ context(word)
+ end
+ end
+ elseif method == "line" then
+ local words = lpegmatch(split_line,str)
+ for i=1,#words do
+ local word = words[i]
+ if spaced and i > 1 then
+ context.par()
+ end
+ if command then
+ context[command](word)
+ else
+ context(word)
+ end
+ end
+ else
+ context(str)
+ end
+end
+
+implement {
+ name = "processsplit",
+ actions = processsplit,
+ arguments = {
+ {
+ { "data" },
+ { "command" },
+ { "method" },
+ { "spaced", "boolean" },
+ }
+ }
+}
+
+local a_vboxtohboxseparator = attributes.private("vboxtohboxseparator")
+
+implement {
+ name = "vboxlisttohbox",
+ arguments = { "integer", "integer", "dimen" },
+ actions = function(original,target,inbetween)
+ local current = getlist(getbox(original))
+ local head = nil
+ local tail = nil
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ if id == hlist_code then
+ local list = getlist(current)
+ if head then
+ if inbetween > 0 then
+ local n = new_glue(0,0,inbetween)
+ setlink(tail,n)
+ tail = n
+ end
+ setlink(tail,list)
+ else
+ head = list
+ end
+ tail = find_tail(list)
+ -- remove last separator
+ if getid(tail) == hlist_code and getattribute(tail,a_vboxtohboxseparator) == 1 then
+ local temp = tail
+ local prev = getprev(tail)
+ if next then
+ local list = getlist(tail)
+ setlink(prev,list)
+ setlist(tail)
+ tail = find_tail(list)
+ else
+ tail = prev
+ end
+ free_node(temp)
+ end
+ -- done
+ setnext(tail)
+ setlist(current)
+ end
+ current = next
+ end
+ local result = new_hlist()
+ setlist(result,head)
+ setbox(target,result)
+ end
+}
+
+implement {
+ name = "hboxtovbox",
+ arguments = "integer",
+ actions = function(n)
+ local b = getbox(n)
+ local factor = texget("baselineskip").width / texget("hsize")
+ setfield(b,"depth",0)
+ setfield(b,"height",getfield(b,"width") * factor)
+ end
+}
+
+implement {
+ name = "boxtostring",
+ arguments = "integer",
+ actions = function(n)
+ context.puretext(nodes.toutf(texgetbox(n).list)) -- helper is defined later
+ end
+}
+
+local function getnaturaldimensions(n)
+ local w, h, d = 0, 0, 0
+ local l = getlist(getbox(n))
+ if l then
+ w, h, d = dimensions(l)
+ end
+ texsetdimen("lastnaturalboxwd",w)
+ texsetdimen("lastnaturalboxht",h)
+ texsetdimen("lastnaturalboxdp",d)
+ return w, h, d
+end
+
+interfaces.implement {
+ name = "getnaturaldimensions",
+ arguments = "integer",
+ actions = getnaturaldimensions
+}
+
+interfaces.implement {
+ name = "naturalwd",
+ arguments = "integer",
+ actions = function(n)
+ getnaturaldimensions(n)
+ context.lastnaturalboxwd(false)
+ end
+}
+
+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 getfield(h,"dir")
+ end
+ end
+ end
+end
+
+nodes.firstdirinbox = firstdirinbox
+
+local doifelse = commands.doifelse
+
+interfaces.implement {
+ name = "doifelserighttoleftinbox",
+ arguments = "integer",
+ actions = function(n)
+ doifelse(firstdirinbox(n) == "TRT")
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv
new file mode 100644
index 00000000000..a302076f204
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv
@@ -0,0 +1,2945 @@
+%D \module
+%D [ file=supp-box,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Support Macros / Boxes}
+
+\unprotect
+
+\registerctxluafile{supp-box}{1.001}
+
+% This file is partially cleaned up.
+
+% handy to have
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.2\hsize
+% \vsize=2\hsize
+% \ruledvbox to \vsize{\input tufte \par}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern0pt}\hss
+% \ruledvbox to \vsize{\input tufte \par\vfill}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth\vfill}}
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.18\hsize
+% \vsize=2.5\hsize
+% \setbox0=\vbox{\input tufte\relax}%
+% \ruledvbox to \vsize{\unvcopy0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern0pt}\hss
+% \ruledvbox to \vsize{\unvcopy0\vfill}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0\vfill}}
+
+%D \macros
+%D {dontcomplain}
+%D
+%D The next macro suppresses over- and underfull messages which
+%D often makes sense when we deal with boxes.
+
+\unexpanded\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+%D This module implements some box manipulation macros. Some
+%D are quite simple, some are more advanced and when understood
+%D well, all can be of use.
+%D
+%D \macros
+%D {strutdp,strutht,strutwd}
+%D
+%D The next shortcuts save memory and keying. The width is
+%D normally zero points (if not, you're in trouble). These
+%D shortcuts can be used like a dimension, opposite to the
+%D core macros \type {\strutdepth} and alike, which are
+%D values.
+
+\def\strutdp {\dp\strutbox}
+\def\strutht {\ht\strutbox}
+\def\strutwd {\wd\strutbox}
+\def\struthtdp{\dimexpr\ht\strutbox+\dp\strutbox\relax}
+
+%D \macros
+%D {voidbox,nextbox}
+%D
+%D Let's start with an easy one. The next macro hides the
+%D ugly \type {@} in \type {\voidb@x}.
+
+\ifdefined\voidbox \else \newbox\voidbox \fi
+\ifdefined\nextbox \else \newbox\nextbox \fi
+
+%D \macros
+%D {nextdepth}
+%D
+%D Let's start with a rather simple declaration. Sometimes we
+%D need to save the \TEX\ \DIMENSION\ \type{\prevdepth} and
+%D append it later on. The name \type{\nextdepth} suits
+%D this purpose well.
+
+\newdimen\nextdepth
+
+%D \macros
+%D {smashbox, smashedbox}
+%D
+%D Smashing is introduced in \PLAIN\ \TEX, and stands for
+%D reducing the dimensions of a box to zero. The most resolute
+%D one is presented first.
+
+\unexpanded\def\smashbox#1%
+ {\wd#1\zeropoint
+ \ht#1\zeropoint
+ \dp#1\zeropoint}
+
+\unexpanded\def\smashboxed#1%
+ {\wd#1\zeropoint
+ \ht#1\zeropoint
+ \dp#1\zeropoint
+ \box#1\relax}
+
+%D \macros
+%D {hsmashbox,vsmashbox}
+%D
+%D Smashing can be used for overlaying boxes. Depending on
+%D the mode, horizontal or vertical, one can use:
+
+\unexpanded\def\hsmashbox#1%
+ {\wd#1\zeropoint}
+
+\unexpanded\def\vsmashbox#1%
+ {\ht#1\zeropoint
+ \dp#1\zeropoint}
+
+%D The next implementation is less sensitive for spurious
+%D spaces.
+
+\newcount\c_boxes_register
+
+\unexpanded\def\smashbox
+ {\afterassignment\syst_boxes_smash_boxes_register\c_boxes_register}
+
+\def\syst_boxes_smash_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
+
+\unexpanded\def\hsmashbox
+ {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register}
+
+\def\syst_boxes_hsmashed_boxes_register
+ {\wd\c_boxes_register\zeropoint}
+
+\unexpanded\def\vsmashbox
+ {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register}
+
+\def\syst_boxes_vsmashed_boxes_register
+ {\ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
+
+\unexpanded\def\smashedbox
+ {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register}
+
+\unexpanded\def\syst_boxes_smashed_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint
+ \box\c_boxes_register}
+
+%D \macros
+%D {hsmash,vsmash,
+%D hsmashed,vsmashed}
+%D
+%D While the previous macros expected a \BOX, the next act on a
+%D content. They are some subtle differences betreen the smash
+%D and smashed alternatives. The later ones reduce all
+%D dimensions to zero.
+
+\unexpanded\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
+\unexpanded\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
+\unexpanded\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox}
+\unexpanded\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox}
+
+\unexpanded\def\syst_boxes_hsmashed_nextbox
+ {\wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\unexpanded\def\syst_boxes_vsmashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\unexpanded\def\syst_boxes_smashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {smashedhbox,smashedvbox}
+%D
+%D Also handy (all dimensions zeroed):
+%D
+%D \starttyping
+%D \smashedhbox to ... {...}
+%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}
+
+%D First we define a helper. We use a \LUATEX\ feature in order to avoid
+%D mathpalettes.
+
+\newcount\c_boxes_math_style
+
+\unexpanded\def\syst_boxes_math_set_nextbox#1%
+ {\c_boxes_math_style\mathstyle
+ \setbox\nextbox\hbox{\normalstartimath\mathsurround\zeropoint\triggermathstyle\c_boxes_math_style{#1}\normalstopimath}}
+
+%D \macros
+%D {smash}
+%D
+%D This smash alternative takes an optional arg [whdtb] as
+%D well as is potentially catcode safer. It is needed by the
+%D math module (although the \type {\leavevmode} is not added
+%D here).
+
+\unexpanded\def\smash
+ {\begingroup
+ \futurelet\nexttoken\syst_boxes_smash}
+
+\def\syst_boxes_smash
+ {\ifx\nexttoken[%
+ \expandafter\syst_boxes_smash_yes
+ \else
+ \expandafter\syst_boxes_smash_nop
+ \fi}
+
+\def\syst_boxes_smash_nop
+ {\edef\m_boxes_smash_options{hd}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
+
+\def\syst_boxes_smash_yes[#1]%
+ {\edef\m_boxes_smash_options{#1}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
+
+\def\syst_boxes_smash_indeed
+ {\ifmmode
+ \expandafter\syst_boxes_smash_math
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_smash_hbox
+ \else
+ \doubleexpandafter\syst_boxes_smash_text
+ \fi\fi}
+
+\def\syst_boxes_smash_math#1%
+ {\syst_boxes_math_set_nextbox{#1}%
+ \syst_boxes_smash_process}
+
+\def\syst_boxes_smash_hbox
+ {\dowithnextboxcs\syst_boxes_smash_process\hbox}
+
+\def\syst_boxes_smash_text#1%
+ {\setbox\nextbox\hbox{#1}%
+ \syst_boxes_smash_process}
+
+\def\syst_boxes_smash_process
+ {\expandafter\syst_boxes_smash_process_option\m_boxes_smash_options\relax
+ \box\nextbox
+ \endgroup}
+
+\installcorenamespace {smashoptions}
+
+\setvalue{\??smashoptions w}{\wd\nextbox\zeropoint}
+\setvalue{\??smashoptions h}{\ht\nextbox\zeropoint}
+\setvalue{\??smashoptions d}{\dp\nextbox\zeropoint}
+\setvalue{\??smashoptions t}{\ht\nextbox\zeropoint}
+\setvalue{\??smashoptions b}{\dp\nextbox\zeropoint}
+
+\def\syst_boxes_smash_process_option#1%
+ {\ifx#1\relax\else
+ \begincsname\??smashoptions#1\endcsname
+ \expandafter\syst_boxes_smash_process_option
+ \fi}
+
+%D \starttabulate[|l|l|]
+%D \NC w \NC \ruledhbox{\smash [w]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC h \NC \ruledhbox{\smash [h]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC d \NC \ruledhbox{\smash [d]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC tb \NC \ruledhbox{\smash [tb]{This is some great smashing, isn't it?}} \NC \NR
+%D \NC whd \NC \ruledhbox{\smash[whd]{This is some great smashing, isn't it?}} \NC \NR
+%D \stoptabulate
+
+%D \macros
+%D {phantom, hphantom, vphantom, mathstrut}
+%D
+%D The next implementation of \type {\phantom} cum suis does
+%D not grab an argument in the non||math case, which is better.
+%D
+%D Due to a complicated call to \type {\mathpallete} and
+%D thereby \type {\mathchoice}, the next macro looks ugly.
+%D We also take care of non||braced arguments.
+
+\unexpanded\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
+\unexpanded\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
+\unexpanded\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h}
+
+\def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make }
+\def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v}
+\def\syst_boxes_phantom_math_h#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_h}
+
+\def\syst_boxes_phantom_hbox {\dowithnextboxcs\syst_boxes_phantom_make \hbox} % always hbox
+\def\syst_boxes_phantom_hbox_v{\dowithnextboxcs\syst_boxes_phantom_make_v\hbox} % always hbox
+\def\syst_boxes_phantom_hbox_h{\dowithnextboxcs\syst_boxes_phantom_make_h\hbox} % always hbox
+
+\def\syst_boxes_phantom_text #1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make } % always hbox
+\def\syst_boxes_phantom_text_v#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_v} % always hbox
+\def\syst_boxes_phantom_text_h#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_h} % always hbox
+
+\def\syst_boxes_phantom_indeed
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text
+ \fi\fi}
+
+\def\syst_boxes_phantom_indeed_v
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_v
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox_v
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text_v
+ \fi\fi}
+
+\def\syst_boxes_phantom_indeed_h
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_h
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox_h
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text_h
+ \fi\fi}
+
+\def\syst_boxes_phantom_make
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
+
+\def\syst_boxes_phantom_make_v
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \box\scratchbox
+ \endgroup}
+
+\def\syst_boxes_phantom_make_h
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
+
+%D We also define plain's \type {\mathstrut}.
+
+\unexpanded\def\mathstrut{\vphantom(} % can be made faster by inlining
+
+%D \macros
+%D {getboxheight}
+%D
+%D Although often needed, \TEX\ does not support arithmics
+%D like:
+%D
+%D \starttyping
+%D \dimen0 = \ht0 + \dp0
+%D \stoptyping
+%D
+%D so we implemented:
+%D
+%D \starttyping
+%D \getboxheight ... \of \box...
+%D \stoptyping
+%D
+%D For instance,
+%D
+%D \starttyping
+%D \getboxheight \dimen0 \of \box0
+%D \getboxheight \someheight \of \box \tempbox
+%D \stoptyping
+%D
+%D The implementation is rather stupid:
+%D
+%D \starttyping
+%D \def\getboxheight#1\of#2\box#3%
+%D {#1\ht#3\advance#1\dp#3\relax}
+%D \stoptyping
+%D
+%D The next alternative is slightly more clever, since
+%D it accepts \type {{12}} as well as \type {12} as box
+%D number.
+
+\unexpanded\def\getboxheight#1\of#2\box#3%
+ {\def\next{#1\dimexpr\ht\c_boxes_register+\dp\c_boxes_register\relax}%
+ \afterassignment\next\c_boxes_register=#3}
+
+%D For a long time the following three macros were part of
+%D the grid snapping core module, but it makes more sense to
+%D have them here so that users can see them.
+%D
+%D \macros
+%D {getnoflines, getroundednoflines, getrawnoflines}
+%D
+%D Het commando \type{\getnoflines} converteert een hoogte
+%D (dimensie) in een aantal regels en kent dit toe aan
+%D \type{\noflines}.
+%D
+%D \starttyping
+%D \getnoflines{dimensie}
+%D \stoptyping
+%D
+%D Er wordt gedeeld door \type{\openlineheight} en een hoogte
+%D van~0pt komt overeen met 0~regels. The raw alternative
+%D does not round.
+
+%D For a long time we had:
+%D
+%D \starttyping
+%D \newcount\noflines
+%D \newdimen\noflinesheight
+%D
+%D \def\dogetnoflines#1#2%
+%D {\noflinesheight#2\relax
+%D \ifzeropt\noflinesheight % \ifdim\noflinesheight=\zeropoint
+%D \noflines\zerocount
+%D \else
+%D \divide\noflinesheight \openlineheight
+%D \noflines\noflinesheight
+%D #1\ifdim\noflines\openlineheight=#2\relax \else
+%D \advance\noflines\ifdim#2>\zeropoint\plusone\else\minusone\fi
+%D \fi\fi
+%D \fi}
+%D
+%D \def\getnoflines {\dogetnoflines\iftrue } % compensated
+%D \def\getrawnoflines{\dogetnoflines\iffalse} % no compensation
+%D \stoptyping
+%D
+%D A more recent variant is:
+
+\ifx\roundingeps\undefined \newdimen\roundingeps \roundingeps=10sp \fi
+
+\newcount\noflines
+\newdimen\noflinesheight
+
+\unexpanded\def\getnoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \else\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight-\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \advance\noflines\plusone
+ \else
+ \advance\noflinesheight\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \advance\noflines\minusone
+ \fi\fi}
+
+\unexpanded\def\getroundednoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \else\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \else
+ \advance\noflinesheight-\roundingeps
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \fi\fi}
+
+\unexpanded\def\getrawnoflines#1%
+ {\noflinesheight#1\relax
+ \ifzeropt\noflinesheight
+ \noflines\zerocount
+ \else\ifdim\noflinesheight>\zeropoint
+ \advance\noflinesheight\roundingeps
+ \advance\noflinesheight.5\openlineheight
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \else
+ \advance\noflinesheight-\roundingeps
+ \advance\noflinesheight-.5\openlineheight
+ \divide\noflinesheight\openlineheight
+ \noflines\noflinesheight
+ \fi\fi}
+
+%D Let's proof that it works:
+%D
+%D \startbuffer
+%D \scratchdimen\dimexpr(3pt) \getnoflines\scratchdimen 1=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.1\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.5\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.9\lineheight) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3pt) \getnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3sp) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight-3sp) \getnoflines\scratchdimen 10=\the\noflines \endgraf
+%D
+%D \scratchdimen\dimexpr(3pt) \getrawnoflines\scratchdimen 0=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.1\lineheight) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.5\lineheight) \getrawnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10.9\lineheight) \getrawnoflines\scratchdimen 11=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3pt) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight+3sp) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \scratchdimen\dimexpr(10\lineheight-3sp) \getrawnoflines\scratchdimen 10=\the\noflines \endgraf
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {determinenoflines}
+%D
+%D The next macro determines the number of lines and
+%D returns it it \type {\noflines}. The macro works
+%D reasonable well as long as the content can be unboxed.
+%D
+%D \starttyping
+%D \determinenoflines{test\\test}
+%D \determinenoflines{\bfd test\\test}
+%D \determinenoflines{\definedfont[Sans at 40pt]test\\test}
+%D \stoptyping
+
+\def\dodeterminenoflines % can be mkiv'd
+ {\beginofshapebox
+ \unvbox\nextbox
+ \endofshapebox
+ % \global\count1\zerocount
+ % \reshapebox{\global\advance\count1\plusone}%
+ % \egroup\noflines\count1 }%
+ \scratchcounter\zerocount
+ \reshapebox{\global\advance\scratchcounter\plusone}%
+ \expandafter\egroup\expandafter\noflines\the\scratchcounter\relax}
+
+\unexpanded\def\determinenoflines
+ {\bgroup
+ \forgetall
+ \let\crlf\endgraf
+ \let\\\endgraf
+ \dowithnextboxcs\dodeterminenoflines\vbox}
+
+%D \macros
+%D {doiftextelse, doiftext}
+%D
+%D When \type {\doifelse} cum suis hopelessly fail, for
+%D instance because we pass data, we can fall back on the next
+%D macro:
+%D
+%D \starttyping
+%D \doiftextelse {data} {then branch} {else branch}
+%D \doiftext {data} {then branch}
+%D \stoptyping
+
+\unexpanded\def\doifelsetext#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\settrialtypesetting
+ \ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox
+ \endgroup\expandafter\secondoftwoarguments
+ \else
+ \endgroup\expandafter\firstoftwoarguments
+ \fi}
+
+\let\doiftextelse\doifelsetext
+
+\unexpanded\def\doiftext#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\settrialtypesetting
+ \ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox
+ \endgroup\expandafter\gobbleoneargument
+ \else
+ \endgroup\expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {dowithnextbox,nextbox}
+%D
+%D Sometimes we want a macro to grab a box and do something
+%D on the content. One could pass an argument to a box, but
+%D this can violate the specific \CATCODES\ of its content and
+%D leads to unexpected results. The next macro treats the
+%D following braced text as the content of a box and
+%D manipulates it afterwards in a predefined way.
+%D
+%D The first argument specifies what to do with the content.
+%D This content is available in \type{\nextbox}. The second
+%D argument is one of \type{\hbox}, \type{\vbox} or
+%D \type{\vtop}. The third argument must be grouped with
+%D \type{\bgroup} and \type{\egroup}, \type{{...}} or can be
+%D a \type{\box} specification.
+%D
+%D In \CONTEXT\ this macro is used for picking up a box and
+%D treating it according to earlier specifications. We use for
+%D instance something like:
+%D
+%D \starttyping
+%D \def\getfloat%
+%D {\def\handlefloat{...\box\nextbox...}
+%D \dowithnextboxcs\handlefloat\vbox}
+%D \stoptyping
+%D
+%D instead of:
+%D
+%D \starttyping
+%D \def\getfloat#1%
+%D {...#1...}
+%D \stoptyping
+%D
+%D In this implementation the \type{\aftergroup} construction
+%D is needed because \type{\afterassignment} is executed inside
+%D the box.
+
+\unexpanded\def\dowithnextbox#1%
+ {\def\syst_boxes_with_next_box{#1}%
+ \afterassignment\syst_boxes_with_next_box_indeed
+ \setbox\nextbox}
+
+\def\syst_boxes_with_next_box_indeed
+ {\aftergroup\syst_boxes_with_next_box}
+
+\unexpanded\def\dowithnextboxcs#1%
+ {\let\syst_boxes_with_next_box#1%
+ \afterassignment\syst_boxes_with_next_box_indeed
+ \setbox\nextbox}
+
+%D So in fact we get:
+%D
+%D \starttyping
+%D \setbox\nextbox { \aftergroup\syst_boxes_with_next_box ... }
+%D \stoptyping
+%D
+%D or
+%D
+%D \starttyping
+%D \setbox\nextbox { ... } \syst_boxes_with_next_box
+%D \stoptyping
+%D
+%D A slower but more versatile implementation is:
+%D
+%D \starttyping
+%D \unexpanded\def\dowithnextbox#1#2%
+%D {\def\syst_boxes_with_next_box{#1}%
+%D \ifx#2\hbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\vbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\normalvtop
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\normalvcenter
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else
+%D \afterassignment\syst_boxes_with_next_box
+%D \fi\fi\fi\fi
+%D \setbox\nextbox#2}
+%D \stoptyping
+%D
+%D This alternative also accepts \type{\box0} and alike, but
+%D we don't really need this functionality now.
+
+%D \macros
+%D {nextboxht,nextboxwd,nextboxdp,flushnextbox}
+%D
+%D The next couple of shortcuts saves us memory as well as
+%D \type {{}}'s in passing parameters.
+
+\def\nextboxht {\ht\nextbox}
+\def\nextboxwd {\wd\nextbox}
+\def\nextboxdp {\dp\nextbox}
+\def\nextboxhtdp {\dimexpr\ht\nextbox+\dp\nextbox\relax}
+
+\unexpanded\def\flushnextbox{\box\nextbox}
+
+%D \macros
+%D {dowithnextboxcontent}
+%D
+%D But, occasionally we do need to pass some local settings
+%D without wanting to use additional grouping. Therefore we
+%D provide:
+%D
+%D \starttyping
+%D \dowithnextboxcontent{inside}{after}{box content}
+%D \stoptyping
+%D
+%D {\em todo: Search source for potential usage!}
+
+\unexpanded\def\dowithnextboxcontent#1#2% inside, after
+ {\def\syst_boxes_with_next_box_one{#2}%
+ \def\syst_boxes_with_next_box_two{#1}%
+ \afterassignment\syst_boxes_with_next_box_content_indeed
+ \setbox\nextbox}
+
+\unexpanded\def\dowithnextboxcontentcs#1#2% inside, after
+ {\let\syst_boxes_with_next_box_one#2%
+ \let\syst_boxes_with_next_box_two#1%
+ \afterassignment\syst_boxes_with_next_box_content_indeed
+ \setbox\nextbox}
+
+\def\syst_boxes_with_next_box_content_indeed
+ {\syst_boxes_with_next_box_two\aftergroup\syst_boxes_with_next_box_one}
+
+%D \macros
+%D {llap, rlap, tlap, blap, clap}
+%D
+%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\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox}
+\def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox}
+\def\doclap{\begingroup\dowithnextboxcs\dodoclap\hbox}
+
+\def\domathclap{\mathpalette\dodomathclap} \def\dodomathclap#1#2{\doclap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\domathllap{\mathpalette\dodomathllap} \def\dodomathllap#1#2{\dollap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\domathrlap{\mathpalette\dodomathrlap} \def\dodomathrlap#1#2{\dorlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+
+\unexpanded\def\rlap{\mathortext\domathrlap\dorlap}
+\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}
+
+\unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
+\unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
+
+%D \macros
+%D {beginofshapebox,
+%D reshapebox, doreshapebox,
+%D flushshapebox,
+%D innerflushshapebox,
+%D shapebox,
+%D ifreshapingbox}
+%D
+%D The next utility macro originates from some linenumbering
+%D mechanism. Due to \TEX's advanced way of typesetting
+%D paragraphs, it's not easy to do things on a line||by||line
+%D basis. This macro is able to reprocess a given box and can
+%D act upon its vertical boxed components, such as lines. The
+%D unwinding sequence in this macro is inspired by a \NTG\
+%D workshop of David Salomon in June 1992.
+%D
+%D First we have to grab the piece of text we want to act
+%D upon. This is done by means of the duo macros:
+%D
+%D \starttyping
+%D \beginofshapebox
+%D a piece of text
+%D \endofshapebox
+%D \stoptyping
+%D
+%D When all texts is collected, we can call \type{\reshapebox}
+%D and do something with it's vertical components. We can make
+%D as much passes as needed. When we're done, the box can be
+%D unloaded with \type{\flushshapebox}. The only condition in
+%D this scheme is that \type{\reshapebox} must somehow unload
+%D the \BOX\ \type{\shapebox}.
+%D
+%D An important aspect is that the content is unrolled
+%D bottom||up. The next example illustrates this maybe
+%D unexpected characteristic.
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \em \input tufte
+%D \endofshapebox
+%D
+%D \newcounter\LineNumber
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D As we can see, when some kind of numbering is done, we have
+%D to add a second pass.
+%D
+%D \startbuffer
+%D \newcounter\LineNumber
+%D \newcounter\NumberOfLines
+%D
+%D \reshapebox
+%D {\doglobal\increment\NumberOfLines
+%D \box\shapebox}
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox
+%D {\llap{\LineNumber\ (\NumberOfLines)\hskip2em}%
+%D \box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D This example shows that the content of the box is still
+%D available after flushing. Another feature is that only the
+%D last reshaping counts. Multiple reshaping can be done by:
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \flushshapebox
+%D \endofshapebox
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{$\star$\hskip1em}\box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D The macros are surprisingly easy to follow and in fact
+%D introduce no new concepts. Nearly all books on \TEX\ show
+%D similar solutions for unwinding \BOXES.
+%D
+%D Some macros, like footnote ones, can be sensitive for
+%D reshaping, which can result in an endless loop. We
+%D therefore offer:
+%D
+%D \starttyping
+%D \ifreshapingbox
+%D \stoptyping
+%D
+%D Some \CONTEXT\ commands are protected this way. Anyhow,
+%D reshaping is aborted after 100 dead cycles.
+%D
+%D By the way, changing the height and depth of \BOX\
+%D \type{\shapebox} results in bad spacing. This means that
+%D for instance linenumbers etc. should be given zero height
+%D and depth before being lapped into the margin. The
+%D previous examples ignore this side effect, but beware!
+
+\newif \ifsomeshapeleft
+\newif \ifreshapingbox
+
+\newbox \shapebox
+\newcount \shapepenalty
+\newdimen \shapekern
+\newskip \shapeskip
+
+\newbox \newshapebox
+\newbox \oldshapebox
+
+\newcount \shapecounter
+
+\newevery \everyshapebox \relax
+
+\def\shapesignal{.12345678pt} % or 12345sp
+
+\unexpanded\def\reshapebox#1%
+ {\doreshapebox
+ {#1}%
+ {\penalty\shapepenalty}%
+ {\kern \shapekern }%
+ {\vskip \shapeskip }}
+
+\newbox\tmpshapebox
+
+\newif\ifreshapingfailed % may save redundant runs
+
+\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+ {\global\reshapingfailedfalse
+ \ifzeropt\ht\oldshapebox % \ifdim\ht\oldshapebox=\zeropoint
+ \setbox\newshapebox\emptyvbox
+ \else
+ \setbox\newshapebox\vbox
+ {\unvcopy\oldshapebox
+ \setbox\newshapebox\emptybox
+ \shapecounter\zerocount
+ \doloop{\dodoreshapebox{#1}{#2}{#3}{#4}}}%
+ \setbox\newshapebox\box\tmpshapebox
+ \fi}
+
+\ifx\originalshapebox\undefined \let\originalshapebox\oldshapebox \fi
+
+% We will turn this into a \MKIV\ variant.
+
+\unexpanded\def\insertshapesignal
+ {\hpack to \shapesignal{\strut\hss}% plus \strut
+ \prevdepth\strutdp} % never \nointerlineskip
+
+\unexpanded\def\restoreshapebox % compensates for the signal
+ {\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}}
+
+\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+ {\ifnum\lastnodetype=\gluenodecode
+ \shapeskip\lastskip
+ \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}%
+ \unskip
+ \else\ifnum\lastnodetype=\kernnodecode
+ \shapekern\lastkern
+ \global\setbox\tmpshapebox\vbox{#3\unvbox\tmpshapebox}%
+ \unkern
+ \else\ifnum\lastnodetype=\penaltynodecode
+ \shapepenalty\lastpenalty
+ \global\setbox\tmpshapebox\vbox{#2\unvbox\tmpshapebox}%
+ \unpenalty
+ \else\ifnum\lastnodetype<\zeropoint
+ \exitloop
+ \else
+ \setbox\shapebox\lastbox
+ \ifvoid\shapebox
+ \else\ifdim\wd\shapebox=\shapesignal\relax
+ \exitloop
+ \else
+ \shapecounter\zerocount
+ \global\setbox\tmpshapebox\vbox{#1\unvbox\tmpshapebox}%
+ \fi\fi
+ \fi\fi\fi\fi
+ \ifnum\shapecounter>100 % can be less
+ \global\reshapingfailedtrue
+ \message{!!forced exit from shapebox \the\lastnodetype !!}%
+ \restoreshapebox
+ \exitloop
+ \else
+ \advance\shapecounter \plusone
+ \fi}
+
+\unexpanded\def\beginofshapebox
+ {\setbox\oldshapebox\vbox
+ \bgroup
+ \reshapingboxtrue
+ \the\everyshapebox
+ \insertshapesignal}
+
+\unexpanded\def\endofshapebox
+ {\endgraf
+ \egroup}
+
+\let\beginshapebox\beginofshapebox
+\let\endshapebox \endofshapebox
+
+\unexpanded\def\flushshapebox
+ {\bgroup
+ \ifzeropt\ht\newshapebox % \ifdim\ht\newshapebox=\zeropoint
+ \else
+ % make \prevdepth legal
+ % \par before the next \vskip gives far worse results
+ \ifdim\parskip>\zeropoint\vskip\parskip\else\par\fi
+ % and take a look
+ \ifdim\prevdepth=-\thousandpoint
+ \prevdepth\zeropoint
+ \fi
+ \ifdim\prevdepth<\zeropoint\relax
+ % something like a line or a signal or ...
+ \donetrue
+ \else\ifinner
+ % not watertight and not ok
+ \donefalse
+ \else\ifdim\pagegoal=\maxdimen
+ \donetrue
+ \else
+ % give the previous line a normal depth
+ \donetrue
+ {\forgeteverypar\verticalstrut}\nobreak
+ \kern-\struttotal % geen \vskip
+ \kern-\parskip
+ % \vskip-\strutdp
+ \fi\fi\fi
+ \scratchdimen\dp\newshapebox
+ \unvbox\newshapebox
+ % \prevdepth=0pt and \dp\newshapebox depend on last line
+ \kern-\scratchdimen % ??
+ % now \prevdepth=0pt
+ \ifdone
+ \kern\strutdp
+ \prevdepth\strutdp
+ \fi
+ \fi
+ \egroup}
+
+%D In real inner situations we can use:
+%D
+%D \starttyping
+%D \flushinnershapebox
+%D \stoptyping
+%D
+%D This one is used in \type{\framed}.
+
+% The kern fails on for instance:
+%
+% \omlijnd[offset=0pt,hoogte=8mm,uitlijnen={rechts,laho}]{\bfa test}
+
+\unexpanded\def\innerflushshapebox
+ {\ifzeropt\ht\newshapebox \else
+ \unvcopy\newshapebox\relax % unvcopy ! else spacing problem
+ % \kern-\dp\newshapebox\relax
+ \fi}
+
+%D For absolute control, one can use \type{\doreshapebox}
+%D directly. This macro takes four arguments, that take care
+%D of:
+%D
+%D \startitemize[n,packed]
+%D \item \type{\shapebox}
+%D \item \type{\shapepenalty}
+%D \item \type{\shapekern}
+%D \item \type{\shapeskip}
+%D \stopitemize
+
+%D \macros
+%D {shapedhbox}
+%D
+%D When constructing a new box, using the content of \type
+%D {\shapebox}, one can best use \type {\shapedhbox} instead
+%D of \type {\hbox}, since it manages the height and depth of
+%D the line.
+
+\unexpanded\def\shapedhbox % lines with non strutted dimensions have
+ {\expanded{\dowithnextbox % interlineskip so if we want the original
+ {\dp\nextbox\the\ht\shapebox % spacing, we need to preserve the original
+ \dp\nextbox\the\dp\shapebox % height and depth which is definitely
+ \box\nextbox}} % needed if we apply struts to the 'new'
+ \hbox} % box or do something that changed ist size
+
+%D \macros
+%D {hyphenatedword,
+%D hyphenatedpar,
+%D hyphenatedfile,
+%D dohyphenateword}
+%D
+%D We no longer use the pure \TEX\ variant. In due time we will
+%D report some more advanced statistics.
+%D
+%D \starttyping
+%D \showhyphens{dohyphenatedword}
+%D \stoptyping
+
+\unexpanded\def\doshowhyphenatednextbox
+ {\clf_showhyphenatedinlist\nextbox}
+
+\unexpanded\def\showhyphens
+ {\dowithnextboxcs\doshowhyphenatednextbox\hbox}
+
+%D The following macros are seldom used but handy for tracing.
+%D
+%D \starttyping
+%D \hyphenatedword{dohyphenatedword}
+%D \hyphenatedpar {\dorecurse{10}{dohyphenatedword }}
+%D \hyphenatedfile{tufte}
+%D \stoptyping
+
+\unexpanded\def\dohyphenatednextbox
+ {\clf_hyphenatedlist\nextbox false\relax
+ \unhbox\nextbox}
+
+\unexpanded\def\hyphenatedword {\dowithnextboxcs\dohyphenatednextbox\hbox}
+\unexpanded\def\hyphenatedpar {\dowithnextboxcs\dohyphenatednextbox\hbox}
+\unexpanded\def\hyphenatedfile#1{\dowithnextboxcs\dohyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}}
+
+\unexpanded\def\dohyphenatednextboxcolor
+ {\clf_hyphenatedlist\nextbox true\relax
+ \unhbox\nextbox}
+
+\unexpanded\def\hyphenatedcoloredword{\dowithnextboxcs\dohyphenatednextboxcolor\hbox}
+
+%D \macros
+%D {processtokens}
+%D
+%D We fully agree with (most) typographers that inter||letter
+%D spacing is only permitted in fancy titles, we provide a
+%D macro that can be used to do so. Because this is
+%D (definitely and fortunately) no feature of \TEX, we have to
+%D step through the token list ourselves.
+%D
+%D \starttyping
+%D \processtokens {before} {between} {after} {space} {tokens}
+%D \stoptyping
+%D
+%D An example of a call is:
+%D
+%D \startbuffer
+%D \processtokens {[} {+} {]} {\space} {hello world}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This results in:
+%D
+%D \getbuffer
+%D
+%D The list of tokens may contain spaces, while \type{\\},
+%D \type{{}} and \type{\ } are handled as space too.
+
+\unexpanded\def\processtokens#1#2#3#4#5%
+ {\begingroup
+ \def\lastcharacter{\lastcharacter}%
+ \def\space{ }%
+ \let\\=\space
+ \def\before {#1}%
+ \def\between{#2}%
+ \def\after {#3}%
+ \def\white {#4}%
+ \let\savedbefore\before
+ \doprocesstokens#5\lastcharacter
+ \endgroup}
+
+\def\doprocesstokens% the space after = is essential
+ {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= }
+
+\def\dodoprocesstokens
+ {\ifx\nextprocessedtoken\lastcharacter
+ \after
+ \let\nextprocessedtoken\relax
+ \else\ifx\nextprocessedtoken\bgroup
+ \def\nextprocessedtoken
+ {\dowithnextbox
+ {\before{\copy\nextbox}% \before can use nextbox several times
+ \let\before\between
+ \doprocesstokens}
+ \hbox\bgroup}%
+ \else
+ \expandafter\if\space\nextprocessedtoken
+ \after\white
+ \let\before\savedbefore
+ \else
+ \before\nextprocessedtoken
+ \let\before\between
+ \fi
+ \let\nextprocessedtoken\doprocesstokens
+ \fi\fi
+ \nextprocessedtoken}
+
+%D \macros
+%D {doboundtext}
+%D
+%D Sometimes there is not enough room to show the complete
+%D (line of) text. In such a situation we can strip of some
+%D characters by using \type{\doboundtext}. When the text is
+%D wider than the given width, it's split and the third
+%D argument is appended. When the text to be checked is packed
+%D in a command, we'll have to use \type{\expandafter}.
+%D
+%D \starttyping
+%D \doboundtext{a very, probably to long, text}{3cm}{...}
+%D \stoptyping
+%D
+%D When calculating the room needed, we take the width of the
+%D third argument into account, which leads to a bit more
+%D complex macro than needed at first sight.
+
+\def\dodoboundtext#1%
+ {\setbox0\hbox{#1}%
+ \advance\scratchdimen -\wd0
+ \ifdim\scratchdimen>\zeropoint\relax#1\fi}%
+
+\def\doboundtext#1#2#3% still used?
+ {\hbox
+ {\setbox\scratchbox\hbox{#1}%
+ \scratchdimen#2\relax
+ \ifdim\wd\scratchbox>\scratchdimen
+ \setbox\scratchbox\hbox{#3}%
+ \advance\scratchdimen -\wd\scratchbox
+ \handletokens#1\with\dodoboundtext
+ \fi
+ \box\scratchbox}}
+
+%D \macros
+%D {limitatetext}
+%D
+%D A bit more beautiful alternative for the previous command is
+%D the next one. This command is more robust because we let
+%D \TEX\ do most of the job. The previous command works better
+%D on text that cannot be hyphenated.
+%D
+%D \starttyping
+%D \limitatetext {text} {width} {sentinel}
+%D \limitatetext {text} {-width} {prelude}
+%D \stoptyping
+%D
+%D When no width is given, the whole text comes available. The
+%D sentinel is optional. This is about the third version.
+
+\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi
+\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi
+
+\unexpanded\def\limitatetext
+ {\bgroup % evt \setstrut
+ \forgetall % otherwise indentation and so
+ \let\limitatetext\firstofthreearguments
+ \fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! !
+ \dowithnextboxcs\syst_boxes_limitate_text\hbox}
+
+\def\syst_boxes_limitate_text#1% #2
+ {\doifelsenothing{#1}\syst_boxes_limitate_text_nop\syst_boxes_limitate_text_yes{#1}} % {#2}
+
+\def\syst_boxes_limitate_text_nop#1#2%
+ {\unhbox\nextbox
+ \egroup}
+
+\def\syst_boxes_limitate_text_yes#1#2%
+ {\nopenalties
+ \scratchdimen#1\relax
+ \ifdim\scratchdimen<\zeropoint\relax % we'll take the last line
+ \donefalse
+ \scratchdimen-\scratchdimen
+ \else
+ \donetrue
+ \fi
+ \ifdim\wd\nextbox>\scratchdimen
+ \setbox\scratchbox\hbox{\ifdone\space#2\else#2\space\fi}%
+ \advance\scratchdimen -\wd\scratchbox
+ \setbox0\box\nextbox
+ \setbox\nextbox\vbox
+ {\hsize\scratchdimen
+ \hfuzz\maxdimen
+ \veryraggedright
+ \strut
+ \ifdone \else
+ \parfillskip\zeropoint
+ \rightskip\zeropoint
+ \hskip\zeropoint \s!plus 1\s!fill % \hsize
+ \fi
+ \unhcopy0}%
+ \ifdim\ht\nextbox>\strutht
+ \setbox\nextbox\vbox % if omitted: missing brace reported
+ {\splittopskip\openstrutheight
+ \ifdone
+ \setbox\nextbox\vsplit\nextbox to \strutht
+ \else
+ \doloop
+ {\setbox0\vsplit\nextbox to \strutht
+ \ifdim\ht\nextbox>\strutht \else \exitloop \fi}%
+ \fi
+ \unvbox\nextbox
+ \setbox\nextbox\lastbox
+ \global\setbox1\hpack
+ {\ifdone
+ \unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox
+ \else
+ \box\scratchbox\unhbox\nextbox
+ \fi
+ \unskip}}%
+ \unhbox1
+ \else
+ \unhbox0
+ \fi
+ \else
+ \unhbox\nextbox
+ \fi
+ \egroup}
+
+%D We can also limit a text with more control:
+%D
+%D \startbuffer
+%D \limitatetext {\input tufte } {2cm,5mm} {\unknown}
+%D \limitatetext {ton en hans} {2cm,5mm} {\unknown}
+%D \limitatetext {ton en hans zijn eikels} {2cm,5mm} {\unknown}
+%D \limitatetext {ton} {2cm,5mm} {\unknown}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D We build this feature on top of the previous macro.
+
+% we could move the text argument to the end
+
+\let\normallimitatetext\limitatetext
+
+\def\speciallimitatetext#1#2#3#4% text left right placeholder
+ {%\dontleavehmode
+ \bgroup
+ \let\speciallimitatetext\firstoffourarguments
+ \setbox0\hbox
+ {\nohyphens
+ \normallimitatetext{#1}{+#2}{}#4%
+ \normallimitatetext{#1}{-#3}{}}%
+ \setbox2\hbox
+ {#1}%
+ \ifdim\wd2<\wd0 #1\else\unhbox0\fi
+ \egroup}
+
+\unexpanded\def\limitatetext#1#2#3% \expanded added 2003/01/16
+ {\expanded{\beforesplitstring#2}\at,\to\leftlimit
+ \expanded{\aftersplitstring #2}\at,\to\rightlimit
+ \ifx\rightlimit\empty
+ \normallimitatetext {#1}\leftlimit {#3}%
+ \else
+ \speciallimitatetext{#1}\leftlimit\rightlimit{#3}%
+ \fi}
+
+%D Undocumented bonus (see wiki):
+%D
+%D \starttyping
+%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown}
+%D \stoptyping
+
+\unexpanded\def\limitatefirstline#1#2#3%
+ {\hbox\bgroup\strut
+ \setbox\scratchbox\hbox{\begstrut#1\endstrut}%
+ \ifdim\wd\scratchbox>#2\relax
+ \setbox\scratchbox\hbox{#3}%
+ \hsize#2\relax
+ \advance\hsize-\wd\scratchbox
+ \setbox\scratchbox\vbox{\forgetall\veryraggedright#1}%
+ \setbox\scratchbox\vsplit\scratchbox to \lineheight
+ \vbox
+ {\unvbox\scratchbox
+ \global\setbox\plusone\lastbox
+ \global\setbox\plusone\hbox{\strut\unhbox\plusone}%
+ \hbox % to #2
+ {\ifx\clip\undefined
+ \box\plusone
+ \else\ifdim\wd\plusone>\hsize
+ \lower\strutdepth\hpack{\clip[\c!width=\hsize,\c!height=\lineheight]{\hpack{\raise\strutdepth\box\plusone}}}%
+ \else
+ \box\plusone
+ \fi\fi
+ \removeunwantedspaces#3}}% \removeunwantedspaces\hss#3}}%
+ \else
+ #1%
+ \fi
+ \egroup}
+
+%D \macros
+%D {processisolatedwords,processisolatedchars}
+%D
+%D \startbuffer
+%D \processisolatedchars{some more words} \ruledhbox \par
+%D \processisolatedchars{and some $x + y = z$ math} \ruledhbox \par
+%D \processisolatedchars{and a \hbox{$x + y = z$}} \ruledhbox \par
+%D \processisolatedwords{some more words} \ruledhbox \par
+%D \processisolatedwords{and some $x + y = z$ math} \ruledhbox \par
+%D \processisolatedwords{and a \hbox{$x + y = z$}} \ruledhbox \par
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+% todo: provide variant with #1 picked up as box
+
+\unexpanded\def\processisolatedchars#1#2%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
+ \clf_applytobox
+ method {char}%
+ box \scratchbox
+ command {\csstring#2}%
+ nested true%
+ \relax
+ \endgroup}
+
+\unexpanded\def\processisolatedwords#1#2%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
+ \clf_applytobox
+ method {word}%
+ box \scratchbox
+ command {\csstring#2}%
+ nested true%
+ \relax
+ \endgroup}
+
+%D A variant:
+
+\unexpanded\def\applytocharacters#1%
+ {\dontleavehmode
+ \dowithnextbox{\clf_applytobox
+ method {char}%
+ box \nextbox
+ command {\csstring#1}%
+ nested true%
+ \relax}%
+ \hbox}
+
+\unexpanded\def\applytowords#1%
+ {\dontleavehmode
+ \dowithnextbox{\clf_applytobox
+ method {word}%
+ box \nextbox
+ command {\csstring#1}%
+ nested true%
+ \relax}%
+ \hbox}
+
+%D The old call:
+
+\unexpanded\def\processwords#1%
+ {\processisolatedwords{#1}\processword}
+
+\let\processword\relax
+
+\unexpanded\def\applytosplitstringchar#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {char}%
+ \relax}
+
+\unexpanded\def\applytosplitstringword#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {word}%
+ \relax}
+
+\unexpanded\def\applytosplitstringline#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {line}%
+ \relax}
+
+\unexpanded\def\applytosplitstringcharspaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {char}%
+ spaced true%
+ \relax}
+
+\unexpanded\def\applytosplitstringwordspaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {word}%
+ spaced true%
+ \relax}
+
+\unexpanded\def\applytosplitstringlinespaced#1#2%
+ {\dontleavehmode\clf_processsplit
+ data {#2}%
+ command {\csstring#1}%
+ method {line}%
+ spaced true%
+ \relax}
+
+%D \macros
+%D {sbox}
+%D
+%D This is a rather strange command. It grabs some box content
+%D and and limits the size to the height and depth of a
+%D \type{\strut}. The resulting bottom||alligned box can be used
+%D aside other ones, without disturbing the normal baseline
+%D distance.
+%D
+%D \startbuffer
+%D \ruledhbox to .5\hsize{\sbox{eerste\par tweede \par derde}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Shows up as:
+%D
+%D \startexample
+%D \vskip3\baselineskip
+%D \getbuffer
+%D \stopexample
+%D
+%D Before displaying the result we added some skip, otherwise
+%D the first two lines would have ended up in the text. This
+%D macro can be useful when building complicated menus, headers
+%D and footers and|/|or margin material.
+
+\unexpanded\def\sbox
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_sbox_finish\vbox}
+
+\unexpanded\def\syst_boxes_sbox_finish
+ {\setbox\nextbox\hpack
+ {\strut
+ \dp\nextbox\zeropoint
+ \lower\strutdp\box\nextbox}%
+ \dp\nextbox\strutdp
+ \ht\nextbox\strutht
+ \box\nextbox
+ \egroup}
+
+%D A variant on this:
+
+\unexpanded\def\inlinedbox
+ {\bgroup
+ \dowithnextbox
+ {\setbox\nextbox\hpack
+ {\lower
+ \dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax
+ \box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}%
+ \hbox}
+
+%D \macros
+%D {struttedbox}
+%D
+%D This boxing macro limits the height and depth to those of
+%D a strut.
+
+\unexpanded\def\struttedbox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_struttedbox_finish\hbox}
+
+\def\syst_boxes_struttedbox_finish
+ {\dp\nextbox\strutdepth
+ \ht\nextbox\strutheight
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {topskippedbox}
+%D
+%D This macro compensates the difference between the topskip
+%D and strutheight. Watch how we preserve the depth when it
+%D equals strutdepth.
+
+\unexpanded\def\topskippedbox
+ {\hbox\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
+
+\def\syst_boxes_topskippedbox_finish
+ {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}%
+ \lower\topskip\hpack{\raise\strutheight\box\nextbox}%
+ \m_boxes_tmp
+ \egroup}
+
+%D \macros
+%D {centeredbox, centerednextbox}
+%D
+%D Here is another strange one. This one offers a sort of overlay
+%D with positive or negative offsets. This command can be used
+%D in well defined areas where no offset options are available.
+%D We first used it when building a button inside the margin
+%D footer, where the button should have a horizontal offset and
+%D should be centered with respect to the surrounding box. The
+%D last of the three examples we show below says:
+%D
+%D \starttyping
+%D \vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height .5cm width -1cm
+%D {\vrule width \hsize height \vsize}}}
+%D \stoptyping
+%D
+%D Here the \type{\ruledvbox} just shows the surrounding box
+%D and \type{\vrule} is used to show the centered box.
+%D
+%D \def\AnExample#1#2%
+%D {\vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height #1 width #2
+%D {\color[green]{\vrule width \hsize height \vsize}}}}
+%D
+%D \startlinecorrection
+%D \startcombination[3*1]
+%D {\AnExample {-1cm} {.5cm}} {}
+%D {\AnExample {.5cm} {-1cm}} {}
+%D {\AnExample {-1cm} {-.5cm}} {}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D This command takes two optional arguments: \type{width} and
+%D \type{height}. Observing readers can see that we use \TEX's
+%D own scanner for grabbing these arguments: \type{#1#} reads
+%D everyting till the next brace and passes it to both rules.
+%D The setting of the box dimensions at the end is needed for
+%D special cases. The dimensions of the surrounding box are kept
+%D intact. This commands handles positive and negative
+%D dimensions (which is why we need two boxes with rules).
+
+\unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen
+ {\bgroup
+ \setbox0\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
+ \vpack to \vsize
+ \bgroup
+ \vskip-\ht2
+ \vss
+ \hpack to \hsize
+ \bgroup
+ \dowithnextbox
+ {\hskip-\wd0
+ \hss
+ \box\nextbox
+ \hss
+ \egroup
+ \vss
+ \egroup
+ \egroup
+ \wd0\hsize
+ \ht0\vsize
+ \box0
+ \egroup}
+ \hbox}
+
+%D For those who don't want to deal with \type {\hsize}
+%D and \type {\vsize}, we have:
+%D
+%D \starttyping
+%D \centerednextbox width 2bp height 2bp
+%D {\framed[width=100bp,height=100bp]{}}
+%D \stoptyping
+%D
+%D Do you see what we call this one \type {next}?
+
+\unexpanded\def\centerednextbox#1#%
+ {\bgroup
+ \dowithnextbox
+ {\hsize\wd\nextbox
+ \vsize\ht\nextbox
+ \centeredbox#1{\box\nextbox}%
+ \egroup}
+ \hbox}
+
+%D \macros
+%D {centerbox}
+%D
+%D Centering on the available space is done by:
+%D
+%D \starttyping
+%D \centerbox <optional specs> {content}
+%D \stoptyping
+%D
+%D When omitted, the current \type {\hsize} and \type
+%D {\vsize} are used. Local dimensions are supported.
+
+\unexpanded\def\centerbox#1#% optional height +/-dimen width +/-dimen
+ {\bgroup
+ \dowithnextbox
+ {\setlocalhsize
+ \setbox\scratchbox\hbox{\vrule\s!width \zeropoint#1}%
+ \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
+ \setbox\scratchbox\vbox{\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}%
+ \hbox}
+
+%D \macros
+%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines}
+%D
+%D These macros are copied from the \TEX book, page~397, and
+%D extended by a macro that sets the \type{\hsize}.
+%D
+%D \starttyping
+%D \setrigidcolumnhsize {total width} {distance} {n}
+%D \rigidcolumnbalance {box}
+%D \stoptyping
+%D
+%D Both these macros are for instance used in typesetting
+%D footnotes.
+%D
+%D Men kan het proces van breken enigzins beinvloeden met de
+%D volgende twee switches:
+
+\newif\ifalignrigidcolumns
+\newif\ifstretchrigidcolumns
+\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections
+
+%D De eerste switch bepaald het uitlijnen, de tweede rekt de
+%D individuele kolommen op naar \type{\vsize}.
+
+\unexpanded\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
+ {\xdef\savedrigidhsize{\the\hsize}%
+ \hsize#1\relax
+ \global\chardef\rigidcolumns#3\relax
+ \scratchdimen -#2\relax
+ \multiply\scratchdimen #3\relax
+ \advance\scratchdimen #2\relax
+ \advance\hsize \scratchdimen
+ \divide\hsize #3\relax}
+
+% ==
+%
+% \def\setrigidcolumnhsize#1#2#3%
+% {\xdef\savedrigidhsize{\the\hsize}%
+% \global\chardef\rigidcolumns#3\relax
+% \hsize=\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax}
+
+\newbox\rigidcolumnbox
+
+\let\rigidcolumnlines\!!zerocount
+
+\unexpanded\def\rigidcolumnbalance#1%
+ {\ifnum\rigidcolumns=1 % tzt ook h/d correctie
+ \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax
+ \else
+ \vbox
+ {\forgetall
+ \nopenalties
+ \dontcomplain
+ \setbox\rigidcolumnbox\vbox
+ {\line{}\goodbreak\unvbox#1\removebottomthings}%
+ \splittopskip\openstrutheight
+ \setbox\scratchbox\vsplit\rigidcolumnbox to \zeropoint
+ \ifcase\rigidcolumnlines\relax
+ % \iffalse
+ % % maybe some day an option
+ % \scratchskip\ht\rigidcolumnbox
+ % \advance\scratchskip\dp\rigidcolumnbox
+ % \getnoflines\scratchskip
+ % \ifodd\noflines
+ % \advance\noflines\plusone
+ % \fi
+ % \divide\noflines\rigidcolumns
+ %\else
+ \scratchdimen\ht\rigidcolumnbox
+ \divide\scratchdimen \rigidcolumns
+ \getnoflines\scratchdimen
+ %\fi
+ \else
+ \noflines\rigidcolumnlines % to be sure
+ \fi
+ \scratchdimen\noflines\lineheight
+ % new: we now loop so that we don't loose content
+ % since in practice we also use this macro for
+ % funny lineheights and border cases
+ \setbox0=\box\rigidcolumnbox
+ \doloop
+ {\setbox\rigidcolumnbox=\copy0
+ \setbox\scratchbox\hpack to \savedrigidhsize
+ {\dorecurse\rigidcolumns
+ {\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen
+ \dp\scratchbox\openstrutdepth
+ \setbox\scratchbox\normalvtop
+ \ifalignrigidcolumns to
+ \ifstretchrigidcolumns\vsize\else\scratchdimen\fi
+ \fi
+ {\unvbox\scratchbox}%
+ \wd\scratchbox\hsize
+ \box\scratchbox
+ \hfill}%
+ \hfillneg}%
+ \ifvoid\rigidcolumnbox\exitloop\else\advance\scratchdimen\lineheight\fi}%
+ \iftightrigidcolumns
+ \setbox\scratchbox\hpack{\raise\dp\scratchbox\box\scratchbox}%
+ \else
+ \advance\scratchdimen -\openstrutdepth
+ \setbox\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}%
+ \dp\scratchbox\openstrutdepth
+ \ht\scratchbox\scratchdimen
+ \fi
+ \box\scratchbox}%
+ \fi}
+
+%D \macros
+%D {startvboxtohbox,stopvboxtohbox,convertvboxtohbox}
+%D
+%D Here is another of Knuth's dirty tricks, as presented on
+%D pages 398 and 399 of the \TEX book. These macros can be used
+%D like:
+%D
+%D \starttyping
+%D \vbox
+%D \bgroup
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \egroup
+%D
+%D \vbox
+%D \bgroup
+%D \convertvboxtohbox
+%D \egroup
+%D \stoptyping
+%D
+%D These macros are used in reformatting footnotes, so they do
+%D what they're meant for.
+
+\newdimen\vboxtohboxslack
+\newdimen\hboxestohboxslack
+
+% Create line and fake height of paragraph by messign with heights:
+% a nice hack by DEK himself.
+
+%\unexpanded\def\setvboxtohbox
+% {\bgroup
+% \ifdim\baselineskip<16pt \relax
+% \scratchdimen\baselineskip
+% \multiply\scratchdimen 1024
+% \else
+% \message{cropping \baselineskip to 16pt}%
+% \scratchdimen\maxdimen
+% \fi
+% \divide\scratchdimen \hsize
+% \multiply\scratchdimen 64
+% \xdef\vboxtohboxfactor{\withoutpt\the\scratchdimen}%
+% \egroup}
+%
+% \unexpanded\def\startvboxtohbox
+% {\bgroup
+% \setvboxtohbox
+% \setbox\scratchbox\hbox\bgroup}
+%
+% \unexpanded\def\stopvboxtohbox
+% {\ifcase\vboxtohboxslack\else\hskip\zeropoint\!!minus\vboxtohboxslack\fi
+% \egroup
+% \dp\scratchbox\zeropoint
+% \ht\scratchbox\vboxtohboxfactor\wd\scratchbox
+% \box\scratchbox
+% \egroup}
+
+% More modern:
+
+% \definesystemattribute[vboxtohboxseparator][public]
+
+%newbox\d_syst_boxes_vboxtohbox
+\newbox\d_syst_boxes_separator
+
+\unexpanded\def\startvboxtohboxseparator
+ {\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup}
+
+\unexpanded\def\stopvboxtohboxseparator
+ {\egroup}
+
+\unexpanded\def\startvboxtohbox
+ {\begingroup
+ \setbox\scratchbox\hbox\bgroup}
+
+\unexpanded\def\stopvboxtohbox
+ {\ifvoid\d_syst_boxes_separator
+ \hskip\zeropoint\ifcase\vboxtohboxslack\else\s!minus\vboxtohboxslack\fi % we really need a skip
+ \else
+ \box\d_syst_boxes_separator
+ \fi
+ \egroup
+ \clf_hboxtovbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+% A possible reconstruction:
+
+\unexpanded\def\convertvboxtohbox
+ {\makehboxofhboxes
+ \setbox0\hbox{\unhbox0 \removehboxes}%
+ \noindent\unhbox0\par}
+
+\unexpanded\def\makehboxofhboxes
+ {\setbox0\emptyhbox
+ \loop % \doloop { .. \exitloop .. }
+ \setbox2\lastbox
+ \ifhbox2
+ \setbox0\hbox{\box2\unhbox0}%
+ \repeat}
+
+\unexpanded\def\removehboxes
+ {\setbox0\lastbox
+ \ifhbox0
+ {\removehboxes}\unhbox0
+ \fi}
+
+% And one special for notes:
+
+% \unexpanded\def\starthboxestohbox
+% {\bgroup
+% \beginofshapebox}
+%
+% \unexpanded\def\stophboxestohbox
+% {\endofshapebox
+% \doreshapebox
+% {\hbox\bgroup
+% \unhbox\shapebox
+% \ifcase\hboxestohboxslack\else\hskip\zeropoint\!!minus\hboxestohboxslack\fi
+% \egroup}%
+% \donothing
+% \donothing
+% \donothing % get rid of penalties etc
+% \innerflushshapebox
+% \convertvboxtohbox
+% \par
+% \egroup}
+
+% More modern:
+
+\unexpanded\def\starthboxestohbox
+ {\bgroup
+ \setbox\scratchbox\vbox\bgroup}
+
+\unexpanded\def\stophboxestohbox
+ {\egroup
+ \clf_vboxlisttohbox\scratchbox\nextbox\dimexpr\hboxestohboxslack\relax
+ \dontleavehmode
+ \unhbox\nextbox
+ \removeunwantedspaces
+ \par
+ \egroup}
+
+%D \macros
+%D {unhhbox}
+%D
+%D The next macro is used in typesetting inline headings.
+%D Let's first look at the macro and then show an example.
+
+\newbox \unhhedbox
+\newbox \hhbox
+\newdimen \lasthhboxwidth
+\newskip \hhboxindent
+
+\unexpanded\def\unhhbox#1\with#2%
+ {\bgroup
+ \nopenalties
+ \dontcomplain
+ \forgetall
+ \setbox\unhhedbox\vbox{\hskip\hhboxindent\strut\unhbox#1}% => \hsize
+ \doloop
+ {\setbox\hhbox\vsplit\unhhedbox to \lineheight
+ \ifvoid\unhhedbox
+ \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}%
+ \fi
+ \ht\hhbox\strutht
+ \dp\hhbox\strutdp
+ \ifzeropt\hhboxindent\else % \ifdim\hhboxindent=\zeropoint\else
+ \setbox\hhbox\hpack{\kern-\hhboxindent\box\hhbox}%
+ \hhboxindent\zeropoint
+ \fi
+ \global\lasthhboxwidth\wd\hhbox
+ #2\relax
+ \ifvoid\unhhedbox
+ \exitloop
+ \else
+ \hskip\zeropoint \s!plus \zeropoint
+ \fi}%
+ \egroup}
+
+\def\dohboxofvbox
+ {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}%
+ \unhbox1
+ \egroup}
+
+\unexpanded\def\hboxofvbox
+ {\bgroup
+ \afterassignment\dohboxofvbox
+ \scratchcounter=}
+
+%D This macro can be used to break a paragraph apart and treat
+%D each line seperately, for instance, making it clickable. The
+%D main complication is that we want to be able to continue the
+%D paragraph, something that's needed in the in line section
+%D headers.
+%D
+%D \startbuffer
+%D \setbox0=\hbox{\input tufte \relax}
+%D \setbox2=\hbox{\input knuth \relax}
+%D \unhhbox0\with{\ruledhbox{\box\hhbox}}
+%D \hskip1em plus 1em minus 1em
+%D \hhboxindent=\lasthhboxwidth
+%D \advance\hhboxindent by \lastskip
+%D \unhhbox2\with{\ruledhbox{\box\hhbox}}
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D This piece of text was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D Not that nice a definition, but effective. Note the stretch
+%D we've build in the line that connects the two paragraphs.
+
+%D \macros
+%D {doifcontent}
+%D
+%D When processing depends on the availability of content, one
+%D can give the next macro a try.
+%D
+%D \starttyping
+%D \doifcontent{pre content}{post content}{no content}\somebox
+%D \stoptyping
+%D
+%D Where \type{\somebox} is either a \type{\hbox} or
+%D \type{\vbox}. If the dimension of this box suggest some
+%D content, the resulting box is unboxed and surrounded by the
+%D first two arguments, else the third arguments is executed.
+
+\unexpanded\def\doifcontent#1#2#3%
+ {\dowithnextbox
+ {\ifhbox\nextbox
+ \ifdim\wd\nextbox>\zeropoint
+ #1\unhbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \else
+ \ifdim\ht\nextbox>\zeropoint
+ #1\unvbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \fi}}
+
+%D So when we say:
+%D
+%D \startbuffer
+%D \doifcontent{[}{]}{}\hbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{\page}{}\vbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{}{\message{Didn't you forget something?}}\hbox{}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \getbuffer
+%D
+%D Where the last call of course does not show up in this
+%D document, but definitely generates a confusing message.
+
+%D \macros
+%D {processboxes}
+%D
+%D The next macro gobble boxes and is for instance used for
+%D overlays. First we show the general handler.
+
+% we cannot use \futurelet here as we want to skip spaces between
+% boxes (see startoverlay for an example usage)
+
+% \newbox\processbox % public : this is the one where \nextbox's end up in
+%
+% \unexpanded\def\processboxes#1%
+% {\bgroup
+% \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
+% \setbox\processbox\emptybox
+% \afterassignment\syst_boxes_process
+% \let\nexttoken}
+%
+% \def\syst_boxes_process
+% {\ifx\nexttoken\bgroup
+% \expandafter\syst_boxes_process_yes
+% \else
+% \expandafter\syst_boxes_process_nop
+% \fi}
+%
+% \def\syst_boxes_process_yes
+% {\dowithnextboxcs\syst_boxes_process_content\hbox\bgroup}
+%
+% \def\syst_boxes_process_content
+% {\removeunwantedspaces
+% \syst_boxes_process_indeed % takes \nextbox makes \processbox
+% \afterassignment\syst_boxes_process
+% \let\nexttoken}
+%
+% \unexpanded\def\syst_boxes_process_nop
+% {\removeunwantedspaces
+% \box\processbox
+% \nexttoken % messy as we are still in the group
+% \egroup}
+
+\newbox\processbox % public : this is the one where \nextbox's end up in
+
+\unexpanded\def\processboxes#1%
+ {\bgroup
+ \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
+ \setbox\processbox\emptybox
+ \doifelsenextbgroup\syst_boxes_process_yes\syst_boxes_process_nop}
+
+\def\syst_boxes_process_yes
+ {\dowithnextboxcs\syst_boxes_process_content\hbox}
+
+\def\syst_boxes_process_content
+ {\removeunwantedspaces
+ \syst_boxes_process_indeed % takes \nextbox makes \processbox
+ \doifelsenextbgroup\syst_boxes_process_yes\syst_boxes_process_nop}
+
+\unexpanded\def\syst_boxes_process_nop
+ {\removeunwantedspaces
+ \box\processbox
+ \egroup}
+
+%D \macros
+%D {startoverlay}
+%D
+%D We can overlay boxes by saying:
+%D
+%D \startbuffer
+%D \startoverlay
+%D {\framed{hans}}
+%D {\framed[width=3cm]{ton}}
+%D {\framed[height=2cm]{oeps}}
+%D \stopoverlay
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows up as:
+%D
+%D \leavevmode\getbuffer
+
+\def\syst_boxes_overlay_process
+ {%\removeunwantedspaces % already done
+ \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi
+ \ifdim\ht\nextbox>\ht\processbox
+ \setbox\processbox\vpack to \ht\nextbox {\dp\processbox\zeropoint\vss\box\processbox\vss}%
+ \else
+ \setbox\nextbox \vpack to \ht\processbox{\dp\nextbox \zeropoint\vss\box\nextbox \vss}%
+ \fi
+ \dp\nextbox \scratchdepth
+ \dp\processbox\scratchdepth
+ \scratchwidth\wd\ifdim\wd\nextbox>\wd\processbox\nextbox\else\processbox\fi
+ \setbox\processbox\hpack to \scratchwidth
+ {\hpack to \scratchwidth{\hss\box\processbox\hss}%
+ \kern-\scratchwidth
+ \hpack to \scratchwidth{\hss\box\nextbox \hss}}}
+
+\unexpanded\def\startoverlay
+ {\bgroup
+ \let\stopoverlay\egroup
+ \processboxes\syst_boxes_overlay_process}
+
+\let\stopoverlay\relax
+
+%D \macros
+%D {fakebox}
+%D
+%D The next macro is a rather silly one, but saves space.
+%D
+%D \starttyping
+%D \hbox{\fakebox0}
+%D \stoptyping
+%D
+%D returns an empty box with the dimensions of the box
+%D specified, here being zero.
+
+\unexpanded\def\fakebox
+ {\bgroup
+ \afterassignment\syst_boxes_fakebox_finish\scratchcounter}
+
+\def\syst_boxes_fakebox_finish
+ {\setbox\scratchbox\ifhbox\scratchcounter\emptyhbox\else\emptyvbox\fi
+ \wd\scratchbox\wd\scratchcounter
+ \ht\scratchbox\ht\scratchcounter
+ \dp\scratchbox\dp\scratchcounter
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {lbox,rbox,cbox,tbox,bbox}
+%D
+%D Here are some convenient alternative box types:
+%D
+%D \starttyping
+%D \lbox{text ...}
+%D \cbox{text ...}
+%D \rbox{text ...}
+%D \stoptyping
+%D
+%D Are similar to \type {\vbox}, which means that they also
+%D accept something like \type{to 3cm}, but align to the left,
+%D middle and right. These box types can be used to typeset
+%D paragraphs.
+
+\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next}
+
+\unexpanded\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
+
+\unexpanded\def\ltop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\ctop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rtop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedright }
+
+%D The alternatives \type {\tbox} and \type {\bbox} can be used
+%D to properly align boxes, like in:
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \starttable[|||]
+%D \HL
+%D \VL \tbox{\externalfigure[cow][height=3cm,frame=on]} \VL top aligned \VL\SR
+%D \HL
+%D \VL \bbox{\externalfigure[cow][height=3cm,frame=on]} \VL bottom aligned \VL\SR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D The positioning depends on the strut settings:
+%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}
+
+\def\syst_boxes_tbox_finish
+ {\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+\def\syst_boxes_bbox_finish
+ {\scratchheight\dimexpr\ht\nextbox+\dp\nextbox-\dp\strutbox\relax
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {lhbox,mhbox,rhbox}
+%D
+%D A few more boxes.
+
+\def\dodolhbox{\hpack to \hsize{\box\nextbox\hss }}
+\def\dodomhbox{\hpack to \hsize{\hss\box\nextbox\hss}}
+\def\dodorhbox{\hpack to \hsize{\hss\box\nextbox }}
+
+\unexpanded\def\lhbox{\dowithnextboxcs\dodolhbox\hbox}
+\unexpanded\def\mhbox{\dowithnextboxcs\dodomhbox\hbox}
+\unexpanded\def\rhbox{\dowithnextboxcs\dodorhbox\hbox}
+
+\let\lefthbox \lhbox
+\let\midhbox \mhbox
+\let\righthbox\rhbox
+
+%D \macros
+%D {boxofsize}
+%D
+%D Sometimes we need to construct a box with a height or
+%D width made up of several dimensions. Instead of cumbersome
+%D additions, we can use:
+%D
+%D \starttyping
+%D \boxofsize \vbox 10cm 3cm -5cm {the text to be typeset}
+%D \stoptyping
+%D
+%D This example demonstrates that one can use positive and
+%D negative values. Dimension registers are also accepted.
+
+\newdimen\sizeofbox
+
+\unexpanded\def\boxofsize#1%
+ {\bgroup
+ \sizeofbox\zeropoint
+ \scratchdimen\zeropoint
+ \def\docommand
+ {\advance\sizeofbox\scratchdimen
+ \futurelet\next\dodocommand}%
+ \def\dodocommand
+ {\ifx\next\bgroup
+ \expanded{\egroup#1 to \the\sizeofbox}%
+ \else
+ \@EA\afterassignment\@EA\docommand\@EA\scratchdimen
+ \fi}%
+ \docommand}
+
+%D Some new, still undocumented features:
+
+% limitatetext -> beter {text} als laatste !!
+%
+% \limitvbox
+% \limithbox
+
+\unexpanded\def\limitatelines#1#2% size sentinel
+ {\dowithnextbox
+ {\dimen0=#1\hsize
+ \ifdim\wd\nextbox>\dimen0
+ \setbox\nextbox\hbox
+ {\advance\dimen0 -.1\hsize
+ \limitatetext{\unhbox\nextbox}{\dimen0}{\nobreak#2}}%
+ \fi
+ \unhbox\nextbox}
+ \hbox}
+
+\unexpanded\def\fittoptobaselinegrid % weg hier
+ {\dowithnextbox
+ {\bgroup
+ \par
+ \dimen0\ht\nextbox
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \hpack{\box\nextbox}
+ \prevdepth\strutdp
+ \doloop
+ {\advance\dimen0 -\lineheight
+ \ifdim\dimen0<\zeropoint
+ \exitloop
+ \else
+ \nobreak
+ \hpack{\strut}
+ \fi}
+ \egroup}
+ \vbox}
+
+%D Some more undocumented macros (used in m-chart).
+
+\newif\iftraceboxplacement % \traceboxplacementtrue
+
+\newbox\fakedboxcursor
+
+\setbox\fakedboxcursor\hbox
+ {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
+
+\unexpanded\def\boxcursor % overloaded in core-vis
+ {\iftraceboxplacement
+ \bgroup
+ \scratchdimen2\onepoint
+ \setbox\scratchbox\hpack to \zeropoint
+ {\hss
+ \vrule
+ \s!width \scratchdimen
+ \s!height\scratchdimen
+ \s!depth \scratchdimen
+ \hss}%
+ \smashedbox\scratchbox
+ \egroup
+ \else
+ \copy\fakedboxcursor
+ \fi}
+
+\unexpanded\def\placedbox
+ {\iftraceboxplacement\ruledhbox\else\hbox\fi}
+
+\newdimen\boxoffset
+\newdimen\boxhdisplacement
+\newdimen\boxvdisplacement
+
+\unexpanded\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox}
+\unexpanded\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox}
+\unexpanded\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox}
+\unexpanded\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox}
+\unexpanded\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox}
+\unexpanded\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox}
+\unexpanded\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
+\unexpanded\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
+
+\let\topleftbox \lefttopbox
+\let\toprightbox \righttopbox
+\let\bottomleftbox \leftbottombox
+\let\bottomrightbox\rightbottombox
+
+\def\syst_boxes_rightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_topbox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_bottombox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_lefttopbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_righttopbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbottombox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_rightbottombox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\unexpanded\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox}
+\unexpanded\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
+\unexpanded\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox}
+\unexpanded\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
+
+\def\syst_boxes_middlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinemiddlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselineleftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinerightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\kern\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+%D \macros
+%D {obox}
+%D
+%D Experimental, not yet frozen:
+
+\unexpanded\def\lrtbbox#1#2#3#4% l r t b
+ {\bgroup
+ \dowithnextboxcontent
+ {\advance\hsize-#1\advance\hsize-#2\relax
+ \advance\vsize-#3\advance\vsize-#4\relax}
+ {\forgetall\vpack to \vsize{\vskip#3\hpack to \hsize{\hskip#1\box\nextbox\hss}\vss}\egroup}
+ \vbox}
+
+%D \macros
+%D {toplinebox}
+%D
+%D See core-tbl.tex for an example of its usage:
+
+\unexpanded\def\toplinebox
+ {\dowithnextboxcs\syst_boxes_toplinebox_finish\tbox}
+
+\def\syst_boxes_toplinebox_finish
+ {\ifdim\dp\nextbox>\strutdepth
+ \scratchdimen\dp\nextbox
+ \advance\scratchdimen-\strutdepth
+ \getnoflines\scratchdimen
+ \struttedbox{\box\nextbox}%
+ \dorecurse\noflines\verticalstrut
+ \else
+ \box\nextbox
+ \fi}
+
+%D \macros
+%D {initializeboxstack,savebox,foundbox}
+%D
+%D At the cost of some memory, but saving box registers, we
+%D have implemented a box repository.
+%D
+%D \starttyping
+%D \initializeboxstack{one}
+%D
+%D \savebox{one}{a}{test a}
+%D \savebox{one}{p}{test p}
+%D \savebox{one}{q}{test q}
+%D
+%D \hbox{a:\foundbox{one}{a}} \par
+%D \hbox{q:\foundbox{one}{q}} \par
+%D \hbox{p:\foundbox{one}{p}} \par
+%D \hbox{x:\foundbox{one}{x}} \par
+%D \hbox{y:\foundbox{two}{a}} \par
+%D \stoptyping
+
+%D Kind of obsolete:
+
+\installcorenamespace {stackbox}
+\installcorenamespace {stacklst}
+
+\unexpanded\def\setstackbox#1#2%
+ {\ifcsname\??stackbox#1:#2\endcsname\else
+ \expandafter\newbox\csname\??stackbox#1:#2\endcsname
+ \fi
+ \global\setbox\csname\??stackbox#1:#2\endcsname\vbox}
+
+\unexpanded\def\initializeboxstack#1%
+ {\def\docommand##1{\setstackbox{#1}{##1}{}}%
+ \ifcsname\??stacklst#1\endcsname
+ \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand
+ \fi
+ \letgvalueempty{\??stacklst#1}}
+
+\unexpanded\def\savebox#1#2% stack name
+ {% beware, \setxvalue defines the cs beforehand so we cannot use the
+ % test inside the { }
+ \ifcsname\??stacklst#1\endcsname
+ %\setxvalue{\??stacklst#1}{\csname\??stacklst#1\endcsname,#2}%
+ \expandafter\xdef\csname\??stacklst#1\expandafter\endcsname\expandafter{\lastnamedcs,#2}%
+ \else
+ \expandafter\xdef\csname\??stacklst#1\endcsname{#2}%
+ \fi
+ \setstackbox{#1}{#2}}
+
+\unexpanded\def\restorebox#1#2% unwrapped
+ {\ifcsname\??stackbox#1:#2\endcsname
+ %\copy\csname\??stackbox#1:#2\endcsname
+ \copy\lastnamedcs
+ \else
+ \emptybox
+ \fi}
+
+\unexpanded\def\foundbox#1#2% wrapped
+ {\vpack
+ {\ifcsname\??stackbox#1:#2\endcsname
+ %\copy\csname\??stackbox#1:#2\endcsname
+ \copy\lastnamedcs
+ \fi}}
+
+\unexpanded\def\doifelsebox#1#2#3#4%
+ {\ifcsname\??stackbox#1:#2\endcsname
+ %\ifvoid\csname\??stackbox#1:#2\endcsname#4\else#3\fi
+ \ifvoid\lastnamedcs#4\else#3\fi
+ \else
+ #4%
+ \fi}
+
+\let\doifboxelse\doifelsebox
+
+%D This one is cheaper (the above is no longer used that much):
+
+\installcorenamespace {boxstack}
+
+\newcount\c_syst_boxes_stack
+\let \b_syst_boxes_stack\relax
+
+\unexpanded\def\syst_boxes_stack_allocate
+ {\newbox\b_syst_boxes_stack
+ \expandafter\let\csname\??boxstack\number\c_syst_boxes_stack\endcsname\b_syst_boxes_stack}
+
+\unexpanded\def\syst_boxes_push#1#2%
+ {\global\advance\c_syst_boxes_stack\plusone
+ \expandafter\let\expandafter\b_syst_boxes_stack\csname\??boxstack\number\c_syst_boxes_stack\endcsname
+ \ifx\b_syst_boxes_stack\relax % cheaper then csname check as in most cases it's defined
+ \syst_boxes_stack_allocate
+ \fi
+ #1\setbox\b_syst_boxes_stack\box#2\relax}
+
+\unexpanded\def\syst_boxes_pop#1#2%
+ {#1\setbox#2\box\csname\??boxstack\number\c_syst_boxes_stack\endcsname
+ \global\advance\c_syst_boxes_stack\minusone}
+
+\unexpanded\def\localpushbox {\syst_boxes_push\relax}
+\unexpanded\def\localpopbox {\syst_boxes_pop \relax}
+
+\unexpanded\def\globalpushbox{\syst_boxes_push\global}
+\unexpanded\def\globalpopbox {\syst_boxes_pop \global}
+
+%D \macros
+%D {removedepth, obeydepth}
+%D
+%D While \type {\removedepth} removes the preceding depth,
+%D \type {\obeydepth} makes sure we have depth. Both macros
+%D leave the \type {\prevdepth} untouched.
+
+\unexpanded\def\removedepth
+ {\ifvmode
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \fi}
+
+\unexpanded\def\obeydepth
+ {\par
+ \ifvmode
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \kern\strutdp
+ \fi}
+
+\unexpanded\def\undepthed
+ {\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\hbox}
+
+%D \macros
+%D {removebottomthings, removelastskip}
+%D
+%D A funny (but rather stupid) one, plus a redefinition.
+
+\unexpanded\def\removebottomthings
+ {\dorecurse5{\unskip\unkern\unpenalty}}
+
+\unexpanded\def\removelastskip % \ifvmode the plain tex one \fi
+ {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+
+%D \macros
+%D {makestrutofbox}
+%D
+%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete
+%D so it will go away.
+
+\unexpanded\def\makestrutofbox % not used
+ {\afterassignment\syst_boxes_makestrutofbox\c_boxes_register}
+
+\def\syst_boxes_makestrutofbox
+ {\ht\c_boxes_register\strutht
+ \dp\c_boxes_register\strutdp
+ \wd\c_boxes_register\zeropoint}
+
+%D \macros
+%D {raisebox,lowerbox}
+%D
+%D Some more box stuff, related to positioning (under
+%D construction). Nice stuff for a tips and tricks maps
+%D article.
+%D
+%D \starttyping
+%D \raisebox{100pt}\hbox{test}
+%D \hsmash{\raisebox{100pt}\hbox{test}}
+%D \stoptyping
+
+\unexpanded\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+\unexpanded\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+
+\def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish}
+\def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish}
+
+\def\syst_boxes_raise_finish
+ {\setbox\nextbox\hpack{\raise\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
+
+\def\syst_boxes_lower_finish
+ {\setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
+
+% vcenter in text, we kunnen vcenter overloaden
+
+\unexpanded\def\halfwaybox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox}
+
+\def\syst_boxes_halfwaybox_finish
+ {\dp\nextbox\zeropoint
+ \lower.5\ht\nextbox\box\nextbox
+ \egroup}
+
+\unexpanded\def\depthonlybox
+ {\vtop\bgroup
+ \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox}
+
+\def\syst_boxes_depthonlybox_finish
+ {\hsize\wd\nextbox
+ \kern\zeropoint\box\nextbox
+ \egroup}
+
+%D New:
+
+\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi}
+\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi}
+
+%D And even rawer:
+
+\let\naturalhbox \hbox
+\let\naturalvbox \vbox
+\let\naturalvtop \normalvtop
+\let\naturalvcenter\normalvtop
+
+\ifdefined\textdir
+
+ \unexpanded\def\naturalhbox {\hbox dir TLT}
+ \unexpanded\def\naturalvbox {\vbox dir TLT}
+ \unexpanded\def\naturalhpack{\hpack dir TLT}
+ \unexpanded\def\naturalvpack{\vpack dir TLT}
+
+\fi
+
+%D \macros
+%D {vcenter}
+%D
+%D Also new: tex mode \type {\vcenter}.
+
+\unexpanded\def\vcenter
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_vcenter_finish\vbox}
+
+\def\syst_boxes_vcenter_finish
+ {\hpack{\normalstartimath\normalvcenter{\box\nextbox}\normalstopimath}%
+ \egroup}
+
+% could be \everymathematics
+
+\prependtoks \let\vcenter\normalvcenter \to \everymath
+\prependtoks \let\vcenter\normalvcenter \to \everydisplay
+
+% \appendtoks \let\vcenter\normalvcenter \to \everymathematics
+
+%D \macros
+%D {frozenhbox}
+%D
+%D A not so well unhboxable box can be made with:
+
+\unexpanded\def\frozenhbox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
+
+\def\syst_boxes_frozenhbox_finish
+ {\hpack{\hpack{\box\nextbox}}%
+ \egroup}
+
+%D \macros
+%D {setboxllx,setboxlly,gsetboxllx,gsetboxlly,getboxllx,getboxlly}
+%D
+%D A prelude to an extended \TEX\ feature:
+
+\installcorenamespace {box_x}
+\installcorenamespace {box_y}
+
+\unexpanded\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+
+\unexpanded\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+
+%def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi}
+%def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi}
+\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+
+\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence
+\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence
+
+%D \macros
+%D {shownextbox}
+%D
+%D Handy for tracing
+%D
+%D \starttyping
+%D \shownextbox\vbox{test}
+%D \shownextbox\vbox{test\endgraf}
+%D \shownextbox\vbox{test\endgraf\strut\endgraf}
+%D \shownextbox\vbox{test\endgraf\thinrule}
+%D \shownextbox\vbox{\setupwhitespace[big]test\endgraf\thinrule}
+%D \stoptyping
+
+\unexpanded\def\shownextbox % seldom used
+ {\dowithnextbox
+ {\bgroup
+ \showboxbreadth\maxdimen
+ \showboxdepth \maxdimen
+ \scratchcounter\interactionmode
+ \batchmode
+ \showbox\nextbox
+ \box\nextbox
+ \interactionmode\scratchcounter
+ \egroup}}
+
+\unexpanded\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
+ {\bgroup
+ \ifhbox#1\relax
+ \setbox2\emptybox
+ \unhbox#1%
+ \doloop
+ {\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip
+ \setbox0\lastbox
+ \ifvoid0
+ \exitloop
+ \else
+ \setbox2\hbox
+ {\ifhbox0 \spreadhbox0\else\box0\fi
+ \ifvoid2 \else\hss\unhbox2\fi}%
+ \fi}%
+ \ifvoid2\else\unhbox2\fi
+ \else
+ \box#1%
+ \fi
+ \egroup}
+
+% makes sense but too much log for overfull boxes:
+%
+% \showboxbreadth\maxdimen
+% \showboxdepth \maxdimen
+
+%D Moved from cont-new:
+%D
+%D \starttyping
+%D \minimalhbox 100pt {test}
+%D \stoptyping
+
+\unexpanded\def\minimalhbox#1#%
+ {\dowithnextbox
+ {\bgroup
+ \setbox\scratchbox\hpack#1{\hss}%
+ \ifdim\wd\nextbox<\wd\scratchbox\wd\nextbox\wd\scratchbox\fi
+ \box\nextbox
+ \egroup}
+ \hbox}
+
+%D A bit dirty:
+
+% \unexpanded\def\nodestostring#1% \cs {content}
+% {\dowithnextbox{\edef#1{\syst_boxes_nodestostring}}\hbox}
+%
+% \def\syst_boxes_nodestostring
+% {\clf_boxtostring\nextbox}
+
+\unexpanded\def\nodestostring#1#2% more tolerant for #2=\cs
+ {\begingroup
+ \setbox\nextbox\hbox{#2}%
+ \normalexpanded{\endgroup\edef\noexpand#1{\clf_boxtostring\nextbox}}}
+
+%D Even more dirty:
+
+\let\hyphenatedhbox\hbox
+
+%D We can do this:
+%D
+%D \starttyping
+%D \setbox0\hbox to 10cm{foo} \setbox2\hbox{\unhbox0} \the\wd2
+%D \stoptyping
+%D
+%D But this saves a copy (and hpack pass):
+%D
+%D \starttyping
+%D \setbox0\hbox to 10cm{foo} \the\naturalwd0
+%D \stoptyping
+
+\newdimen\lastnaturalboxwd
+\newdimen\lastnaturalboxht
+\newdimen\lastnaturalboxdp
+
+\let\getnaturaldimensions\clf_getnaturaldimensions % sets three dimensions
+\let\naturalwd \clf_naturalwd % calculates and returns wd
+
+\unexpanded\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox}
+
+\let\doifrighttoleftinboxelse\doifelserighttoleftinbox
+
+\protect \endinput
+
+% a bit of test code:
+
+% \hbox \bgroup
+% \ruledvbox {\hbox{\strut gans}}
+% \ruledvbox to \lineheight {\hbox{\strut gans}}
+% \ruledvbox to \lineheight {\hbox {gans}}
+% \ruledvbox to \strutheight{\hbox {gans}}
+% \ruledvbox to \strutheight{\hbox{\strut gans}}
+% \ruledvbox to \strutheight{\vss\hbox{gans}}
+% \egroup
+
+% to be considered
+
+% \startluacode
+%
+% local spacer = lpeg.patterns.spacer
+%
+% function commands.withwords(command,str)
+% if str then
+% command = command or "ruledhbox"
+% local done = false
+% local function apply(s)
+% if done then
+% context.space()
+% done = true
+% else
+% context.dontleavehmode()
+% end
+% context[command](s)
+% end
+% lpeg.match(lpeg.splitter(spacer,apply),str)
+% end
+%
+% end
+%
+% \stopluacode
+%
+% \unprotect
+%
+% \unexpanded\def\withwordsinstring#1#2% command str
+% {\ctxcommand{withwords(\!!bs#1\!!es,\!!bs#2\!!es)}}
+%
+% \unexpanded\def\withwordsinfile#1#2% command name
+% {\ctxcommand{withwords(\!!bs#1\!!es,io.loaddata(resolvers.findfile("#2")))}}
+%
+% \protect
+%
+% \starttext
+%
+% \defineframed[colored][foregroundcolor=red,foregroundstyle=\bfc\underbar,location=low]
+%
+% \withwordsinstring{colored}{bla bla}
+% \withwordsinfile{colored}{ward.tex}
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv
new file mode 100644
index 00000000000..6251012b6a1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=supp-dir,
+%D version=2004.11.11,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Directional Things,
+%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 no longer have the \ETEX\ direction primitives.
+
+\unprotect
+
+% \expanded{\defineactivecharacter \number"2000E} {\textdir TRT\relax}
+% \expanded{\defineactivecharacter \number"2000F} {\textdir TLT\relax}
+
+%D As we have less directions now we can use something
+
+% \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\def\showdirsinmargin
+ {\doifelse{\the\pardir}\!!TLT
+ {\inleft{\normalexpanded{\noexpand\hbox dir TLT{\ttxx[\the\pardir,\the\textdir]}}}}
+ {\inleft{\normalexpanded{\noexpand\hbox dir TLT{\ttxx[\the\pardir,\the\textdir]}}}}}
+
+\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
+
+\def\istlttextdir{\expandafter\istltdir\the\textdir}
+\def\istrttextdir{\expandafter\istrtdir\the\textdir}
+
+\def\istltpardir {\expandafter\istltdir\the\pardir }
+\def\istrtpardir {\expandafter\istrtdir\the\pardir }
+
+% \ifcase\istlttextdir Y\else N\fi
+% \ifcase\istltpardir Y\else N\fi
+% \ifcase\istltdir TRT\relax Y\else N\fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv
new file mode 100644
index 00000000000..b265a7c5a1d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv
@@ -0,0 +1,317 @@
+%D \module
+%D [ file=supp-mat,
+%D version=1998.09.10,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Math,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D For practical reasons, I decided to move some math things to
+%D a support module. There is nothing spectacular here. It may move
+%D back to math-ini.
+
+\writestatus{loading}{ConTeXt Support Macros / Math}
+
+\unprotect
+
+%D \macros
+%D {mathematics, math, nomathematics, startmathmode}
+%D
+%D The \type{$} can be both an begin and end math character.
+%D This can lead to confusing and errorprone situations when
+%D macros insert \type{$}. When for instance we have defined:
+%D
+%D \starttyping
+%D \def\MyPlus{$\,+\,$}
+%D \stoptyping
+%D
+%D the sequence \type{$x^2 \MyPlus y^2 = r^2$} will expand to:
+%D
+%D \starttyping
+%D $x^2 $\,+\,$ y^2 = r^2$
+%D \stoptyping
+%D
+%D Here the \type{\,} are given outside math mode and \TEX\ will
+%D definitely complain about this. A more save definition would
+%D have been:
+%D
+%D \starttyping
+%D \def\MyPlus{\mathematics{\,+\,}}
+%D \stoptyping
+%D
+%D Which is implemented (in \type{syst-ini.mkiv}) as:
+
+% \let\normalsuperscript\Usuperscript
+% \let\normalsubscript \Usubscript
+% \let\normalstartimath \Ustartmath
+% \let\normalstopimath \Ustopmath
+% \let\normalstartdmath \Ustartdisplaymath
+% \let\normalstopdmath \Ustopdisplaymath
+
+% \unexpanded\def\Ustartdisplaymath
+% {\ifinner
+% \ifhmode
+% \normalUstartmath
+% \let\Ustopdisplaymath\normalUstopmath
+% \else
+% \normalUstartdisplaymath
+% \let\Ustopdisplaymath\normalUstopdisplaymath
+% \fi
+% \else
+% \normalUstartdisplaymath
+% \let\Ustopdisplaymath\normalUstopdisplaymath
+% \fi}
+
+\unexpanded\def\Ucheckedstartdisplaymath
+ {\ifinner
+ \ifhmode
+ \normalUstartmath
+ \let\Ucheckedstopdisplaymath\normalUstopmath
+ \else
+ \normalUstartdisplaymath
+ \let\Ucheckedstopdisplaymath\normalUstopdisplaymath
+ \fi
+ \else
+ \normalUstartdisplaymath
+ \let\Ucheckedstopdisplaymath\normalUstopdisplaymath
+ \fi}
+
+\let\Ucheckedstopdisplaymath\relax
+
+\def\normalmathaligntab{&} % \let\normalmathaligntab\aligntab does to work well in a let to & (a def works ok)
+
+\let\normalsuper \Usuperscript % obsolete
+\let\normalsuber \Usubscript % obsolete
+
+\let\startimath \Ustartmath
+\let\stopimath \Ustopmath
+\let\startdmath \Ustartdisplaymath % \Ucheckedstartdisplaymath
+\let\stopdmath \Ustopdisplaymath % \Ucheckedstopdisplaymath
+
+\unexpanded\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
+\unexpanded\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi}
+\unexpanded\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
+\unexpanded\def\textmath #1{\dontleavehmode\ifmmode#1\else\begingroup\everymath\emptytoks\normalstartimath#1\normalstopimath\endgroup\fi} % \mathsurround\zeropoint
+
+\let\m\mathematics
+
+\let\stopmathmode\relax
+
+\unexpanded\def\startmathmode % nested variant
+ {\relax\ifmmode
+ \begingroup
+ \let\stopmathmode\endgroup
+ \else
+ \normalstartimath
+ \let\stopmathmode\normalstopimath
+ \fi}
+
+\unexpanded\def\nomathematics#1%
+ {\relax\ifmmode\hbox{#1}\else#1\fi}
+
+\let\math\mathematics
+
+%D \macros
+%D {displaymathematics,inlinemathematics,automathematics}
+%D
+%D An example of usage of the following can be found in the MathML module:
+
+\ifdefined\strc_formulas_start_formula \else
+ \def\strc_formulas_start_formula{\normalstartdmath}
+ \def\strc_formulas_stop_formula {\normalstopdmath }
+\fi
+
+\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\strc_formulas_start_formula{}#1\strc_formulas_stop_formula\fi}
+\unexpanded\def\inlinemathematics {\dontleavehmode\mathematics}
+\unexpanded\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi}
+
+% better, esp when used in bTABLE ... eTABLE
+
+\unexpanded\def\automathematics
+ {\relax
+ \ifhmode
+ \expandafter\inlinemathematics
+ \else\ifintable
+ \doubleexpandafter\inlinemathematics
+ \else
+ \doubleexpandafter\displaymathematics
+ \fi\fi}
+
+%D \macros
+%D {dimension, nodimension}
+%D
+%D The next few macros are used for typesetting dimensions in
+%D such a way that spacing is acceptable. I won't spend much
+%D words on these macros, because they will be overloaded in
+%D the units module.
+%D
+%D REPLACED (keep commented):
+
+\newsignal\dimensionsignal
+
+\def\dimensiontypeface {\tf}
+\def\dimensionhalfspace {\,}
+
+\unexpanded\def\dimension#1%
+ {\pushmacro\dodimensionsignal
+ \gdef\dodimensionsignal{\kern\dimensionsignal}%
+ \ifdim\lastskip=\zeropoint\relax
+ \ifdim\lastkern=\zeropoint\relax
+ \ifmmode
+ \mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}%
+ \else
+ \mathematics{\dimensiontypeface#1}%
+ \fi
+ \else\ifdim\lastkern=\dimensionsignal
+ \mathematics{\dimensionhalfspace\dimensiontypeface#1}%
+ \else
+ \unkern\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}%
+ \fi\fi
+ \else
+ \unskip\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}%
+ \fi
+ \dodimensionsignal
+ \popmacro\dodimensionsignal}
+
+\unexpanded\def\nodimension#1%
+ {\unskip#1\global\let\dodimensionsignal\relax}
+
+%D \macros
+%D {cramped}
+%D
+%D Cramped math:
+%D
+%D \startbuffer
+%D \ruledhbox{$\left\{{x^2\over y^2}\right\}$}
+%D \ruledhbox{$\cramped{\left\{ {x^2\over y^2}\right\}}$}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\cramped
+ {\mathpalette\math_cramped}
+
+%D We force a cramped style by issuing a non||existing radical (box).
+%D After that we make sure the height is correct. (Comment taken from
+%D Morten Høgholm's mathtools package.) Macro suggested by AM and
+%D cleaned up a bit by HH.
+
+% original
+%
+% \def\docramped#1#2%
+% {\setbox\scratchbox\hbox
+% {\nulldelimiterspace\zeropoint
+% $\mathsurround\zeropoint#1\radical\zerocount{#2}$}%
+% \ifx#1\displaystyle
+% \scratchdimen\fontdimen8\textfont3
+% \advance\scratchdimen .25\fontdimen5\textfont2
+% \else
+% \scratchdimen1.25\fontdimen8
+% \ifx#1\textstyle\textfont
+% \else
+% \ifx#1\scriptstyle\scriptfont\else\scriptscriptfont\fi
+% \fi
+% 3
+% \fi
+% \advance\scratchdimen-\ht\scratchbox
+% \ht\scratchbox-\scratchdimen
+% \box\scratchbox}
+
+% mkii:
+%
+% \def\math_cramped#1#2%
+% {\begingroup % added HH, made even more cramped
+% \setbox\scratchbox\hbox
+% {\nulldelimiterspace\zeropoint
+% \normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}%
+% \ht\scratchbox-\dimexpr
+% \ifx#1\displaystyle
+% \fontdimen\pluseight\textfont\plusthree
+% +.25\fontdimen\plusfive\textfont\plustwo
+% \else
+% 1.25\fontdimen\pluseight
+% \ifx#1\textstyle
+% \textfont
+% \else\ifx#1\scriptstyle
+% \scriptfont
+% \else
+% \scriptscriptfont
+% \fi \fi
+% \plusthree
+% \fi
+% -\ht\scratchbox
+% \relax
+% \box\scratchbox
+% \endgroup}
+
+\def\math_cramped#1#2% we have all in one family
+ {\begingroup % added HH, made even more cramped
+ \setbox\scratchbox\hbox
+ {\nulldelimiterspace\zeropoint
+ \normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}%
+ \ht\scratchbox-\dimexpr
+ \ifx#1\displaystyle
+ \fontdimen\pluseight\textfont\plusone
+ + .25\fontdimen\plusfive \textfont\plusone
+ \else
+ 1.25\fontdimen\pluseight
+ \ifx#1\textstyle \textfont \else
+ \ifx#1\scriptstyle\scriptfont \else
+ \scriptscriptfont\fi\fi \plusone
+ \fi
+ -\ht\scratchbox
+ \relax
+ \box\scratchbox
+ \endgroup}
+
+%D \macros
+%D {cramedllap, crampedrlap, crampedclap}
+%D
+%D In many cases, one wants to use the \tex {clap} macro in
+%D math mode while using subscripts. Normally, subscripts are
+%D in cramped mode, and these macros allow you to go to
+%D cramped mode. For example:
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{a^2 < b^2 < c^2} \quad
+%D \sum_{\clap{a^2 < b^2 < c^2}} \quad
+%D \sum_{\crampedclap{a^2 < b^2 < c^2}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \start
+%D \typebuffer
+%D \switchtobodyfont[24pt]
+%D \getbuffer
+%D \stop
+%D
+%D Notice that \type {\clap{\cramped ... }} would also work,
+%D but it requires \TEX\ to typeset it arguments 16 times.
+
+\unexpanded\def\crampedllap{\mathpalette\math_cramped_llap}
+\unexpanded\def\crampedrlap{\mathpalette\math_cramped_rlap}
+\unexpanded\def\crampedclap{\mathpalette\math_cramped_clap}
+
+\def\math_cramped_llap#1#2{{}\dollap{\math_cramped #1{#2}}}
+\def\math_cramped_rlap#1#2{{}\dorlap{\math_cramped #1{#2}}}
+\def\math_cramped_clap#1#2{{}\doclap{\math_cramped #1{#2}}}
+
+% experiment, not yet to be used
+
+% \unexpanded\def\displaybreak
+% {\ifhmode
+% \removeunwantedspaces
+% \ifcase\raggedstatus\hfill\fi
+% \strut\penalty-9999 % \break fails on case (3)
+% \fi}
+%
+% \def\startdisplay{\displaybreak\ignorespaces\startpacked}
+% \def\stopdisplay {\stoppacked\displaybreak\ignorespaces}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-ran.lua b/Master/texmf-dist/tex/context/base/mkiv/supp-ran.lua
new file mode 100644
index 00000000000..4968e8cfc1d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-ran.lua
@@ -0,0 +1,107 @@
+if not modules then modules = { } end modules ['supp-ran'] = {
+ version = 1.001,
+ comment = "companion to supp-ran.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We cannot ask for the current seed, so we need some messy hack here.
+
+local report_system = logs.reporter("system","randomizer")
+
+local trace_random = false trackers.register("system.randomizer", function(v) trace_random = v end)
+local trace_random_mp = false trackers.register("system.randomizer.mp",function(v) trace_random_mp = v end)
+
+local insert, remove = table.insert, table.remove
+
+local math = math
+local context = context
+local implement = interfaces.implement
+
+local random = math.random
+local randomseed = math.randomseed
+local round = math.round
+local stack = { }
+local last = 1
+local maxcount = 2^30-1 -- 1073741823
+
+local function setrandomseedi(n)
+ if n <= 1 then
+ n = n * maxcount
+ elseif n < 1000 then
+ n = n * 1000
+ end
+ n = round(n)
+ if trace_random then
+ report_system("setting seed to %s",n)
+ end
+ randomseed(n)
+ last = random(0,maxcount) -- we need an initial value
+end
+
+math.setrandomseedi = setrandomseedi
+
+local function getrandomnumber(min,max)
+ last = random(min,max)
+ return last
+end
+
+local function setrandomseed(n)
+ last = n
+ setrandomseedi(n)
+end
+
+local function getrandomseed()
+ return last
+end
+
+local function getmprandomnumber()
+ last = random(0,4095)
+ if trace_random_mp then
+ report_system("using mp seed %s",last)
+ end
+ return last
+end
+
+-- maybe stack
+
+local function pushrandomseed()
+ insert(stack,last)
+ if trace_random then
+ report_system("pushing seed %s",last)
+ end
+end
+
+local function reuserandomseed(n)
+ local seed = stack[#stack]
+ if seed then
+ if trace_random then
+ report_system("reusing seed %s",last)
+ end
+ randomseed(seed)
+ end
+end
+
+local function poprandomseed()
+ local seed = remove(stack)
+ if seed then
+ if trace_random then
+ report_system("popping seed %s",seed)
+ end
+ randomseed(seed)
+ end
+end
+
+-- todo: also open up in utilities.randomizer.*
+
+implement { name = "getrandomnumber", actions = { getrandomnumber, context }, arguments = { "integer", "integer" } }
+implement { name = "getrandomdimen", actions = { getrandomnumber, context }, arguments = { "dimen", "dimen" } }
+implement { name = "getrandomfloat", actions = { getrandomnumber, context }, arguments = { "number", "number" } }
+implement { name = "getmprandomnumber", actions = { getmprandomnumber, context } }
+implement { name = "setrandomseed", actions = { setrandomseed }, arguments = { "integer" } }
+implement { name = "getrandomseed", actions = { getrandomseed, context } }
+implement { name = "pushrandomseed", actions = { pushrandomseed } }
+implement { name = "poprandomseed", actions = { poprandomseed } }
+implement { name = "reuserandomseed", actions = { reuserandomseed } }
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-ran.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-ran.mkiv
new file mode 100644
index 00000000000..f7cfd6e7334
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-ran.mkiv
@@ -0,0 +1,39 @@
+%D \module
+%D [ file=supp-ran,
+%D version=2008-10-31,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Random Number 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.
+
+\writestatus{loading}{ConTeXt Support Macros / Random Number Generation}
+
+%D This module is downward compatible in the sense that we've kept
+%D the user interface (which uses intermediate variables).
+
+\registerctxluafile{supp-ran}{1.001}
+
+\unprotect
+
+\unexpanded\def\getrandomcount #1#2#3{#1=\clf_getrandomnumber#2 #3\relax}
+\unexpanded\def\getrandomdimen #1#2#3{#1=\clf_getrandomdimen#2 #3 \scaledpoint\relax}
+\unexpanded\def\getrandomnumber#1#2#3{\edef#1{\clf_getrandomnumber#2 #3}}
+\unexpanded\def\getrandomfloat #1#2#3{\edef#1{\clf_getrandomfloat#2 #3}}
+\unexpanded\def\setrandomseed #1{\clf_setrandomseed#1\relax}
+\unexpanded\def\getrandomseed #1{\edef#1{\clf_getrandomseed}}
+\unexpanded\def\pushrandomseed {\clf_pushrandomseed}
+\unexpanded\def\poprandomseed {\clf_poprandomseed}
+\unexpanded\def\reuserandomseed {\clf_reuserandomseed} % within push/pop
+
+\let\freezerandomseed \pushrandomseed
+\let\defrostrandomseed\poprandomseed
+
+\def\randomnumber #1#2{\clf_getrandomnumber\numexpr#1\relax\numexpr#2\relax}
+\let\mprandomnumber \clf_getmprandomnumber
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-vis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-vis.mkiv
new file mode 100644
index 00000000000..8b94201620a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/supp-vis.mkiv
@@ -0,0 +1,1873 @@
+%D \module
+%D [ file=supp-vis,
+%D version=1996.10.21,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Visualization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is no longer generic \unknown\ but who cares. Maybe
+%D the code will be moved out of the core (apart from ruled boxes).
+
+%D \gdef\ShowBufferedExample% private typeseting macro
+%D {\startlinecorrection
+%D \bgroup
+%D \setuptyping[margin=0pt,option=color]
+%D \showmakeup
+%D \centeredvcuetrue
+%D \dontinterfere
+%D \baselinerulefalse
+%D \normalvbox
+%D {\normalhbox to \hsize
+%D {$\hsize=.5\hsize
+%D \advance\hsize by -.5em
+%D \normalvcenter{\vbox{\getbuffer}}\normalhss
+%D \normalvcenter{\vbox{\dontshowcomposition\typebuffer}}$}}
+%D \egroup
+%D \stoplinecorrection}
+%D
+%D \gdef\ShowBufferedExampleBox% private typeseting macro
+%D {\startlinecorrection
+%D \bgroup
+%D \setuptyping[margin=0pt,option=color]
+%D \showmakeup
+%D \centeredvcuetrue
+%D \dontinterfere
+%D \baselinerulefalse
+%D \normalvbox
+%D {\normalhbox to \hsize
+%D {$\hsize=.5\hsize
+%D \advance\hsize by -.5em
+%D \normalvcenter{\baselineruletrue\vbox{\getbuffer}}\normalhss
+%D \normalvcenter{\vbox{\dontshowcomposition\typebuffer}}$}}
+%D \egroup
+%D \stoplinecorrection}
+
+%D Depending on my personal needs and those of whoever uses it,
+%D the macros will be improved in terms of visualization,
+%D efficiency and compatibility. These rather low level
+%D visualization macros are supplemented by ones that can
+%D visualize baselines, the page layout and whatever deserves
+%D attention. Most of those macros can be found in \type
+%D {core-vis} and other core modules. Their integration in
+%D \CONTEXT\ prohibits generic applications.
+%D
+%D We no longer assume usage outside context so we no longer
+%D load support modules.
+%D
+%D One of the strong points of \TEX\ is abstraction of textual
+%D input. When macros are defined well and do what we
+%D want them to do, we will seldom need the tools present in
+%D What You See Is What You Get systems. For instance, when
+%D entering text we don't need rulers, because no manual
+%D shifting and/or alignment of text is needed. On the other
+%D hand, when we are designing macros or specifying layout
+%D elements, some insight in \TEX's advanced spacing, kerning,
+%D filling, boxing and punishment abilities will be handy.
+%D That's why we've implemented a mechanism that shows some of
+%D the inner secrets of \TEX.
+
+\writestatus{loading}{ConTeXt Support Macros / Visualization}
+
+%D In this module we are going to redefine some \TEX\
+%D primitives and \PLAIN\ macro's. Their original meaning is
+%D saved in macros with corresponding names, preceded by
+%D \type{normal}. These original macros are (1)~used to
+%D temporary restore the old values when needed and
+%D (2)~used to prevent recursive calls in the macros that
+%D replace them.
+
+\unprotect
+
+\let\visualvrule\vrule
+\let\visualhrule\hrule
+
+%D \macros
+%D {dontinterfere}
+%D
+%D Indentation, left and/or right skips, redefinition of
+%D \type{\par} and assignments to \type{\everypar} can lead to
+%D unwanted results. We can therefore turn all those things
+%D off with \type{\dontinterfere}.
+
+\unexpanded\def\dontinterfere % or maybe just forgetall
+ {\reseteverypar
+ \parindent\zeropoint
+ \parskip \zeropoint
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+%D \macros
+%D {dontcomplain}
+%D
+%D In this module we do a lot of box manipulations. Because we
+%D don't want to be confronted with to many over- and underfull
+%D messages we introduce \type{\dontcomplain}.
+
+\ifdefined\dontcomplain \else
+
+ \unexpanded\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+\fi
+
+%D \macros
+%D {normaloffinterlineskip}
+%D
+%D The next hack is needed because in \CONTEXT\ we redefine
+%D \type{\offinterlineskip}.
+
+\ifdefined\normaloffinterlineskip \else
+ \let\normaloffinterlineskip\offinterlineskip
+\fi
+
+%D \macros
+%D {normalhbox,
+%D normalvbox,normalvtop}
+%D
+%D There are three types of boxes, one horizontal and two
+%D vertical in nature. As we will see later on, all three types
+%D are to be handled according to their orientation and
+%D baseline behavior. Especially \type{\vtop}'s need our
+%D special attention.
+
+%D \macros
+%D {normalhskip,
+%D normalvskip}
+%D
+%D Next come the flexible skips, which come in two flavors
+%D too. Like boxes these are handled with \TEX\ primitives.
+
+%D \macros
+%D {normalpenalty,
+%D normalkern}
+%D
+%D Both penalties and kerns are taken care of by mode sensitive
+%D primitives. This means that when making them visible, we
+%D have to take the current mode into account.
+
+%D \macros
+%D {normalhglue,
+%D normalvglue}
+%D
+%D Glues on the other hand are macro's defined in \PLAIN\ \TEX.
+%D As we will see, their definitions make the implementation of
+%D their visible counterparts a bit more \TeX{}nical.
+
+\let\normalhglue\hglue
+\let\normalvglue\vglue
+
+%D \macros
+%D {normalmkern,
+%D normalmskip}
+%D
+%D Math mode has its own spacing primitives, preceded by
+%D \type{m}. Due to the relation with the current font and the
+%D way math is typeset, their unit \type{mu} is not compatible
+%D with other dimensions. As a result, the visual appearance
+%D of these primitives is kept primitive too.
+
+%D \macros
+%D {hfilneg,
+%D vfilneg}
+%D
+%D Fills can be made visible quite easy. We only need some
+%D additional negation macros. Because \PLAIN\ \TEX\ only
+%D offers \type{\hfilneg} and \type{\vfilneg}, we define our
+%D own alternative double \type{ll}'ed ones.
+
+\def\hfilneg {\normalhskip\zeropoint\s!plus-1\s!fil\relax}
+\def\vfilneg {\normalvskip\zeropoint\s!plus-1\s!fil\relax}
+\def\hfillneg {\normalhskip\zeropoint\s!plus-1\s!fill\relax}
+\def\vfillneg {\normalvskip\zeropoint\s!plus-1\s!fill\relax}
+\def\hfilllneg{\normalhskip\zeropoint\s!plus-1\s!filll\relax}
+\def\vfilllneg{\normalvskip\zeropoint\s!plus-1\s!filll\relax}
+
+%D \macros
+%D {normalhss,normalhfil,normalhfill,
+%D normalvss,normalvfil,normalvfill}
+%D
+%D The positive stretch primitives are used independant and in
+%D combination with \type{\leaders}.
+
+% already saved
+
+%D \macros
+%D {normalhfilneg,normalhfillneg,
+%D normalvfilneg,normalvfillneg}
+%D
+%D Keep in mind that both \type{\hfillneg} and \type{\vfillneg}
+%D are not part of \PLAIN\ \TEX\ and therefore not documented
+%D in standard \TEX\ documentation. They can nevertheless be
+%D used at will.
+
+\let\normalhfillneg\hfillneg
+\let\normalvfillneg\vfillneg
+
+%D Visualization is not always wanted. Instead of turning this
+%D option off in those (unpredictable) situations, we just
+%D redefine a few \PLAIN\ macros.
+
+% \ifx\tlap\undefined
+%
+% \def\rlap#1{\normalhbox to \zeropoint{#1\normalhss}}
+% \def\llap#1{\normalhbox to \zeropoint{\normalhss#1}}
+% \def\blap#1{\normalvbox to \zeropoint{#1\normalvss}}
+% \def\tlap#1{\normalvbox to \zeropoint{\normalvss#1}}
+%
+% \fi
+
+%D \macros
+%D {makeruledbox}
+%D
+%D Ruled boxes can be typeset is many ways. Here we present
+%D just one alternative. This implementation may be a little
+%D complicated, but it supports all three kind of boxes. The
+%D next command expects a \BOX\ specification, like:
+%D
+%D \starttyping
+%D \makeruledbox0
+%D \stoptyping
+
+%D \macros
+%D {baselinerule,baselinefill}
+%D
+%D We can make the baseline of a box visible, both dashed and
+%D as a rule. The line is drawn on top of the baseline. All
+%D we have to say is:
+%D
+%D \starttyping
+%D \baselineruletrue
+%D \baselinefilltrue
+%D \stoptyping
+%D
+%D At the cost of some overhead these alternatives are
+%D implemented using \type{\if}'s:
+
+\newif\ifbaselinerule\baselineruletrue
+\newif\ifbaselinefill\baselinefillfalse
+
+%D \macros
+%D {iftoprule,ifbottomrule,ifleftrule,ifrightrule}
+%D
+%D Rules can be turned on and off, but by default we have:
+%D
+%D \starttyping
+%D \topruletrue
+%D \bottomruletrue
+%D \leftruletrue
+%D \rightruletrue
+%D \stoptyping
+%D
+%D As we see below:
+
+\newif\iftoprule \topruletrue
+\newif\ifbottomrule\bottomruletrue
+\newif\ifleftrule \leftruletrue
+\newif\ifrightrule \rightruletrue
+
+%D \macros
+%D {boxrulewidth}
+%D
+%D The width in the surrounding rules can be specified by
+%D assigning an apropriate value to the dimension used. This
+%D module defaults the width to:
+%D
+%D \starttyping
+%D \boxrulewidth=.2pt
+%D \stoptyping
+
+\newdimen \boxrulewidth \boxrulewidth=.2pt
+
+\newdimen \boxruleht
+\newdimen \boxruledp
+\newdimen \boxrulewd
+
+\newbox \boxrulescratchbox
+
+%D The core macro \type{\makeruledbox} looks a bit hefty. The
+%D manipulation at the end is needed because we want to
+%D preserve both the mode and the baseline. This means that
+%D \type{\vtop}'s and \type{\vbox}'es behave the way we expect
+%D them to do.
+%D
+%D \startlinecorrection
+%D \hbox
+%D {\ruledhbox to 5em{\strut test\normalhss}\hskip1em
+%D \ruledvbox{\hsize 5em\strut test \par test\strut}\hskip1em
+%D \ruledvtop{\hsize 5em\strut test \par test\strut}}
+%D \stoplinecorrection
+%D
+%D The \type{\cleaders} part of the macro is responsible for
+%D the visual baseline. The \type{\normalhfill} belongs to this
+%D primitive too. By storing and restoring the height and depth
+%D of box \type{#1}, we preserve the mode.
+
+\let\dowithruledbox\relax % hook
+
+\unexpanded\def\makeruledbox#1%
+ {\boxruleht\ht#1%
+ \boxruledp\dp#1%
+ \boxrulewd\wd#1%
+ \setbox\boxrulescratchbox\normalvbox
+ {\dontcomplain
+ \normaloffinterlineskip
+ \visualhrule
+ \s!height\boxrulewidth
+ \iftoprule\else\s!width\zeropoint\fi
+ \normalvskip-\boxrulewidth
+ \normalhbox to \boxrulewd
+ {\visualvrule
+ \s!height\boxruleht
+ \s!depth \boxruledp
+ \s!width \ifleftrule\boxrulewidth\else\zeropoint\fi
+ \ifdim\boxruleht>\zeropoint \else \baselinerulefalse \fi
+ \ifdim\boxruledp>\zeropoint \else \baselinerulefalse \fi
+ \ifbaselinerule
+ \ifdim\boxrulewd<20\boxrulewidth
+ \baselinefilltrue
+ \fi
+ \cleaders
+ \ifbaselinefill
+ \visualhrule
+ \s!height\boxrulewidth
+ \else
+ \normalhbox
+ {\normalhskip2.5\boxrulewidth
+ \visualvrule
+ \s!height\boxrulewidth
+ \s!width5\boxrulewidth
+ \normalhskip2.5\boxrulewidth}%
+ \fi
+ \fi
+ \normalhfill
+ \visualvrule
+ \s!width\ifrightrule\boxrulewidth\else\zeropoint\fi}%
+ \normalvskip-\boxrulewidth
+ \visualhrule
+ \s!height\boxrulewidth
+ \ifbottomrule\else\s!width\zeropoint\fi}%
+ \wd#1\zeropoint
+ \setbox#1=\ifhbox#1\normalhbox\else\normalvbox\fi
+ {\normalhbox
+ {\box#1%
+ \lower\boxruledp\normalhbox{\dowithruledbox{\box\boxrulescratchbox}}}}%
+ \ht#1\boxruleht
+ \wd#1\boxrulewd
+ \dp#1\boxruledp}
+
+%D Just in case one didn't notice: the rules are in fact layed
+%D over the box. This way the contents of a box cannot
+%D visually interfere with the rules around (upon) it. A more
+%D advanced version of ruled boxes can be found in one of the
+%D core modules of \CONTEXT. There we take offsets, color,
+%D rounded corners, backgrounds and alignment into account too.
+
+%D \macros
+%D {ruledhbox,
+%D ruledvbox,ruledvtop,
+%D ruledvcenter}
+%D
+%D These macro's can be used instead of \type{\hbox},
+%D \type{\vbox}, \type{\vtop} and, when in math mode,
+%D \type{\vcenter}. They just do what their names state. Using
+%D an auxiliary macro would save us a few words of memory, but
+%D it would make their appearance even more obscure.
+%D
+%D \startbuffer
+%D \hbox
+%D {\strut
+%D one
+%D two
+%D \hbox{three}
+%D four
+%D five}
+%D \stopbuffer
+%D
+%D \ShowBufferedExampleBox
+
+\unexpanded\def\ruledhbox
+ {\normalhbox\bgroup
+ \dowithnextboxcs\supp_visualizers_hbox_finish\normalhbox}
+
+\def\supp_visualizers_hbox_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
+
+%D \startbuffer
+%D \vbox
+%D {\strut
+%D first line \par
+%D second line \par
+%D third line \par
+%D fourth line \par
+%D fifth line
+%D \strut }
+%D \stopbuffer
+%D
+%D \ShowBufferedExampleBox
+
+\unexpanded\def\ruledvbox
+ {\normalvbox\bgroup
+ \dowithnextboxcs\supp_visualizers_vbox_finish\normalvbox}
+
+\def\supp_visualizers_vbox_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
+
+%D \startbuffer
+%D \vtop
+%D {\strut
+%D first line \par
+%D second line \par
+%D third line \par
+%D fourth line \par
+%D fifth line
+%D \strut }
+%D \stopbuffer
+%D
+%D \ShowBufferedExampleBox
+
+\unexpanded\def\ruledvtop
+ {\normalvtop\bgroup
+ \dowithnextboxcs\supp_visualizers_vtop_finish\normalvtop}
+
+\def\supp_visualizers_vtop_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
+
+%D \startbuffer
+%D \hbox
+%D {$\vcenter{\hsize.2\hsize
+%D alfa \par beta}$
+%D $\vcenter to 3cm{\hsize.2\hsize
+%D alfa \par beta \par gamma}$
+%D $\vcenter{\hsize.2\hsize
+%D alfa \par beta}$}
+%D \stopbuffer
+%D
+%D \ShowBufferedExampleBox
+
+\unexpanded\def\ruledvcenter
+ {\normalvbox\bgroup
+ \dontinterfere
+ \dowithnextboxcs\supp_visualizers_vcenter_finish\normalvbox}
+
+\def\supp_visualizers_vcenter_finish
+ {\scratchdimen.5\dimexpr\ht\nextbox+\dp\nextbox\relax
+ \ht\nextbox\scratchdimen
+ \dp\nextbox\scratchdimen
+ %\ruledhbox{\box\nextbox}%
+ \makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {ruledbox,
+%D setruledbox}
+%D
+%D Of the next two macros the first can be used to precede a
+%D box of ones own choice. One can for instance prefix boxes
+%D with \type{\ruledbox} and afterwards --- when the macro
+%D satisfy the needs --- let it to \type{\relax}.
+%D
+%D \starttyping
+%D \ruledbox\hbox{What rules do you mean?}
+%D \stoptyping
+%D
+%D The macro \type{\setruledbox} can be used to directly
+%D rule a box.
+%D
+%D \starttyping
+%D \setruledbox12=\hbox{Who's talking about rules here?}
+%D \stoptyping
+%D
+%D At the cost of some extra macros we can implement a
+%D variant that does not need the~\type{=}, but we stick to:
+
+\unexpanded\def\ruledbox
+ {\dowithnextboxcs\supp_visualizers_box_finish}
+
+\def\supp_visualizers_box_finish
+ {\makeruledbox\nextbox\box\nextbox}
+
+% \def\setruledbox#1=%
+% {\dowithnextbox{\makeruledbox\nextbox\setbox#1\nextbox}}
+
+\def\setruledbox#1=% not nice, better
+ {\afterassignment\supp_visualizers_setruledbox_indeed\scratchcounter}
+
+\def\supp_visualizers_setruledbox_indeed
+ {\dowithnextboxcs\supp_visualizers_setruledbox_finish}
+
+\def\supp_visualizers_setruledbox_finish
+ {\makeruledbox\nextbox
+ \setbox\scratchcounter\nextbox}
+
+%D \macros
+%D {investigateskip,
+%D investigatecount,
+%D investigatemuskip}
+%D
+%D Before we meet the visualizing macro's, we first implement
+%D ourselves some handy utility ones. Just for the sake of
+%D efficiency and readability, we introduce some status
+%D variables, that tell us a bit more about the registers we
+%D use:
+%D
+%D \starttyping
+%D \ifflexible
+%D \ifzero
+%D \ifnegative
+%D \ifpositive
+%D \stoptyping
+%D
+%D These status variables are set when we call for one of the
+%D investigation macros, e.g.
+%D
+%D \starttyping
+%D \investigateskip\scratchskip
+%D \stoptyping
+%D
+%D We use some dirty trick to check stretchability of \SKIPS.
+%D Users of these macros are invited to study their exact
+%D behavior first. The positive and negative states both
+%D include zero and are in fact non-negative ($\geq0$) and
+%D non-positive ($\leq0$). Well, no dirty trick is needed
+%D any longer as we have \ETEX\ functionality.
+
+\newif\ifflexible
+\newif\ifzero
+\newif\ifnegative
+\newif\ifpositive
+
+\def\investigateskip#1%
+ {\relax
+ \ifdim#1=\zeropoint
+ \ifdim\gluestretch#1=\zeropoint
+ \ifdim\glueshrink#1=\zeropoint
+ \flexiblefalse
+ \else
+ \flexibletrue
+ \fi
+ \else
+ \flexibletrue
+ \fi
+ \else
+ \flexibletrue
+ \fi
+ \ifdim#1=\zeropoint\relax
+ \zerotrue \else
+ \zerofalse \fi
+ \ifdim#1<\zeropoint\relax
+ \positivefalse \else
+ \positivetrue \fi
+ \ifdim#1>\zeropoint\relax
+ \negativefalse \else
+ \negativetrue \fi}
+
+\def\investigatecount#1%
+ {\relax
+ \flexiblefalse
+ \ifnum#1=\zerocount
+ \zerotrue \else
+ \zerofalse \fi
+ \ifnum#1<\zerocount
+ \positivefalse \else
+ \positivetrue \fi
+ \ifnum#1>\zerocount
+ \negativefalse \else
+ \negativetrue \fi}
+
+\def\investigatemuskip#1% etex ?
+ {\relax
+ \edef\!!stringa{\the#1}%
+ \edef\!!stringb{0mu}%
+ \def\!!stringc##1##2\\{##1}%
+ \expandafter\edef\expandafter\!!stringc\expandafter
+ {\expandafter\!!stringc\!!stringa\\}%
+ \edef\!!stringd{-}%
+ \flexiblefalse
+ \ifx\!!stringa\!!stringb
+ \zerotrue
+ \negativefalse
+ \positivefalse
+ \else
+ \zerofalse
+ \ifx\!!stringc\!!stringd
+ \positivefalse
+ \negativetrue
+ \else
+ \positivetrue
+ \negativefalse
+ \fi
+ \fi}
+
+%D Now the neccessary utility macros are defined, we can make a
+%D start with the visualizing ones. The implementation of these
+%D macros is a compromise between readability, efficiency of
+%D coding and processing speed. Sometimes we do in steps what
+%D could have been done in combination, sometimes we use a few
+%D boxes more or less then actually needed, and more than once
+%D one can find the same piece of rule drawing code twice.
+
+%D \macros
+%D {ifcenteredvcue,normalvcue}
+%D
+%D Depending on the context, one can force visual vertical cues
+%D being centered along \type{\hsize} or being put at the
+%D current position. Although centering often looks better,
+%D we've chosen the second alternative as default. The main
+%D reason for doing so is that often when we don't set the
+%D \type{\hsize} ourselves, \TEX\ takes the value of the
+%D surrounding box. As a result the visual cues can migrate
+%D outside the current context.
+%D
+%D This behavior is accomplished by a small but effective
+%D auxiliary macro, which behavior can be influenced by the
+%D boolean \type{\centeredvcue}. By saying
+%D
+%D \starttyping
+%D \centeredvcuetrue
+%D \stoptyping
+%D
+%D one turns centering on. As said, we turn it off.
+
+\newif\ifcenteredvcue \centeredvcuefalse
+
+\def\normalvcue#1%
+ {\normalhbox \ifcenteredvcue to \hsize \fi {\normalhss#1\normalhss}}
+
+%D We could have used the more robust version
+%D
+%D \starttyping
+%D \def\normalvcue%
+%D {\normalhbox \ifcenteredvcue to \hsize \fi
+%D \bgroup\bgroup\normalhss
+%D \aftergroup\normalhss\aftergroup\egroup
+%D \let\next=}
+%D \stoptyping
+%D
+%D or the probably best one:
+%D
+%D \starttyping
+%D \def\normalvcue%
+%D {\hbox \ifcenteredvcue to \hsize
+%D \bgroup\bgroup\normalhss
+%D \aftergroup\normalhss\aftergroup\egroup
+%D \else
+%D \bgroup
+%D \fi
+%D \let\next=}
+%D \stoptyping
+%D
+%D Because we don't have to preserve \CATCODES\ and only use
+%D small arguments, we stick to the first alternative.
+
+%D \macros
+%D {testrulewidth}
+%D
+%D We build our visual cues out of rules. At the cost of a much
+%D bigger \DVI\ file, this is to be prefered over using
+%D characters (1)~because we cannot be sure of their
+%D availability and (2)~because their dimensions are fixed.
+%D
+%D As with ruled boxes, we use a \DIMENSION\ to specify the
+%D width of the ruled elements. This dimension defaults to:
+%D
+%D \starttyping
+%D \testrulewidth=\boxrulewidth
+%D \stoptyping
+%D
+%D Because we prefer whole numbers for specifying the
+%D dimensions, we often use even multiples of
+%D \type{\testrulewidth}.
+
+%D \macros
+%D {visiblestretch}
+%D
+%D A second variable is introduced because of the stretch
+%D components of \SKIPS. At the cost of some accuracy we can
+%D make this stretch visible.
+%D
+%D \starttyping
+%D \visiblestretchtrue
+%D \stoptyping
+
+\newdimen\testrulewidth \testrulewidth=\boxrulewidth
+\newif\ifvisiblestretch \visiblestretchfalse
+
+%D \macros
+%D {ruledhss,
+%D ruledhfil,ruledhfilneg,
+%D ruledhfill,ruledhfillneg}
+%D
+%D We start with the easiest part, the fills. The scheme we
+%D follow is {\em visual filling -- going back -- normal
+%D filling}. Visualizing is implemented using \type{\cleaders}.
+%D Because the \BOX\ that follows this command is constructed
+%D only once, the \type{\copy} is not really a prerequisite. We
+%D prefer using a \type{\normalhbox} here instead of a
+%D \type{\hbox}.
+
+\def\setvisiblehfilbox#1\to#2#3#4%
+ {\setbox#1\normalhbox
+ {\visualvrule
+ \s!width #2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth}%
+ \smashbox#1}
+
+\def\doruledhfiller#1#2#3#4%
+ {#1#2%
+ \bgroup
+ \dontinterfere
+ \dontcomplain
+ \setvisiblehfilbox0\to{4}{#3}{#4}%
+ \setvisiblehfilbox2\to422%
+ \copy0\copy2
+ \bgroup
+ \setvisiblehfilbox0\to422%
+ \cleaders
+ \normalhbox to 12\testrulewidth
+ {\normalhss\copy0\normalhss}%
+ #1%
+ \egroup
+ \setbox0\normalhbox
+ {\normalhskip-4\testrulewidth\copy0\copy2}%
+ \smashbox0%
+ \box0
+ \egroup}
+
+%D The horizontal fillers differ in their boundary
+%D visualization. Watch the small dots. Fillers can be
+%D combined within reasonable margins.
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\type{\hss}\ruledhss test}
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\type{\hfil}\ruledhfil test}
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\type{\hfill}\ruledhfill test}
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut
+%D \type{\hfil}\type{\hfil}\ruledhfil\ruledhfil
+%D test%
+%D \ruledhfil\type{\hfil}}
+%D \stoplinecorrection
+%D
+%D The negative counterparts are visualizes, but seldom
+%D become visible, apart from their boundaries.
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\type{\hfilneg}\ruledhfilneg test}
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\type{\hfillneg}\ruledhfillneg test}
+%D \stoplinecorrection
+%D
+%D Although leaders are used for visualizing, they are
+%D visualized themselves correctly as the next example shows.
+%D
+%D \startlinecorrection
+%D \baselinerulefalse
+%D \ruledhbox to \hsize
+%D {\strut\cleaders\normalhbox to 2em{\normalhss$\circ$\normalhss}\ruledhfill}
+%D \stoplinecorrection
+%D
+%D All five substitutions use the same auxiliary macro. Watch
+%D the positive first -- negative next approach.
+
+\unexpanded\def\ruledhss {\doruledhfiller\normalhss \normalhfilneg {0}{0}}
+\unexpanded\def\ruledhfil {\doruledhfiller\normalhfil \normalhfilneg {10}{-6}}
+\unexpanded\def\ruledhfill {\doruledhfiller\normalhfill \normalhfillneg{18}{-14}}
+\unexpanded\def\ruledhfilneg {\doruledhfiller\normalhfilneg \normalhfil {-6}{10}}
+\unexpanded\def\ruledhfillneg{\doruledhfiller\normalhfillneg\normalhfill {-14}{18}}
+
+%D \macros
+%D {ruledvss,
+%D ruledvfil,ruledvfilneg,
+%D ruledvfill,ruledvfillneg}
+%D
+%D The vertical mode commands adopt the same visualization
+%D scheme, but are implemented in a slightly different way.
+
+\def\setvisiblevfilbox#1\to#2#3#4%
+ {\setbox#1\normalhbox
+ {\visualvrule
+ \s!width #2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth}%
+ \smashbox#1}%
+
+\def\doruledvfiller#1#2#3%
+ {#1#2%
+ \bgroup
+ \dontinterfere
+ \dontcomplain
+ \normaloffinterlineskip
+ \setvisiblevfilbox0\to422%
+ \setbox2\normalvcue
+ {\normalhskip -#3\testrulewidth\copy0}%
+ \smashbox2%
+ \copy2
+ \bgroup
+ \setbox2\normalvcue
+ {\normalhskip -2\testrulewidth\copy0}%
+ \smashbox2%
+ \copy2
+ \cleaders
+ \normalvbox to 12\testrulewidth
+ {\normalvss\copy2\normalvss}%
+ #1%
+ \setbox2\normalvbox
+ {\normalvskip-2\testrulewidth\copy2}%
+ \smashbox2%
+ \box2
+ \egroup
+ \box2
+ \egroup}
+
+%D Because they act the same as their horizontal counterparts
+%D we only show a few examples.
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\dontinterfere
+%D \baselinerulefalse
+%D \centeredvcuetrue
+%D \ruledvbox to 10ex
+%D {\hsize.18\hsize
+%D \type{\vss}\ruledvss last line}\normalhss
+%D \ruledvbox to 10ex
+%D {\hsize.18\hsize
+%D \type{\vfil}\ruledvfil last line}\normalhss
+%D \ruledvbox to 10ex
+%D {\hsize.18\hsize
+%D \type{\vfill}\ruledvfill last line}\normalhss
+%D \ruledvbox to 10ex
+%D {\hsize.18\hsize
+%D \type{\vfilneg}\ruledvfilneg last line}\normalhss
+%D \ruledvbox to 10ex
+%D {\hsize.18\hsize
+%D \type{\vfillneg}\ruledvfillneg last line}}
+%D \stoplinecorrection
+%D
+%D Keep in mind that \type{\vfillneg} is not part of \PLAIN\
+%D \TEX, but are mimmicked by a macro.
+
+\unexpanded\def\ruledvss {\doruledvfiller\normalvss \normalvfilneg {2}}
+\unexpanded\def\ruledvfil {\doruledvfiller\normalvfil \normalvfilneg {-4}}
+\unexpanded\def\ruledvfill {\doruledvfiller\normalvfill \normalvfillneg{-12}}
+\unexpanded\def\ruledvfilneg {\doruledvfiller\normalvfilneg \normalvfil {8}}
+\unexpanded\def\ruledvfillneg{\doruledvfiller\normalvfillneg\normalvfill {16}}
+
+%D \macros
+%D {ruledhskip}
+%D
+%D Skips differ from kerns in two important aspects:
+%D
+%D \startitemize[packed]
+%D \item line and pagebreaks are allowed at a skip
+%D \item skips can have a positive and/or negative
+%D stretchcomponent
+%D \stopitemize
+%D
+%D Stated a bit different: kerns are fixed skips at which no
+%D line or pagebreak can occur. Because skips have a more open
+%D character, they are visualized in a open way.
+%D
+%D \startbuffer
+%D one
+%D \hskip +30pt plus 5pt
+%D two
+%D \hskip +30pt
+%D \hskip -10pt plus 5pt
+%D three
+%D \hskip 0pt
+%D four
+%D \hskip +30pt
+%D five
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+%D
+%D When skips have a stretch component, this is visualized by
+%D means of a dashed line. Positive skips are on top of the
+%D baseline, negative ones are below it. This way we can show
+%D the combined results. An alternative visualization of
+%D stretch could be drawing the mid line over a length of the
+%D stretch, in positive or negative direction.
+
+\def\supp_visualizers_hskip_indeed
+ {\relax
+ \dontinterfere
+ \dontcomplain
+ \investigateskip\scratchskip
+ \ifzero
+ \setbox0\normalhbox
+ {\normalhskip-\testrulewidth
+ \visualvrule
+ \s!width4\testrulewidth
+ \s!height16\testrulewidth
+ \s!depth16\testrulewidth}%
+ \else
+ \setbox0\normalhbox to \ifnegative-\fi\scratchskip
+ {\visualvrule
+ \s!width2\testrulewidth
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth
+ \cleaders
+ \visualhrule
+ \ifnegative
+ \s!depth2\testrulewidth
+ \s!height\zeropoint
+ \else
+ \s!height2\testrulewidth
+ \s!depth\zeropoint
+ \fi
+ \normalhfill
+ \ifflexible
+ \normalhskip\ifnegative\else-\fi\scratchskip
+ \normalhskip2\testrulewidth
+ \cleaders
+ \normalhbox
+ {\normalhskip 2\testrulewidth
+ \visualvrule
+ \s!width2\testrulewidth
+ \s!height\ifnegative-7\else9\fi\testrulewidth
+ \s!depth\ifnegative9\else-7\fi\testrulewidth
+ \normalhskip 2\testrulewidth}%
+ \normalhfill
+ \fi
+ \visualvrule
+ \s!width2\testrulewidth
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth}%
+ \setbox0\normalhbox
+ {\ifnegative\else\normalhskip-\scratchskip\fi
+ \box0}%
+ \fi
+ \smashbox0%
+ \ifvisiblestretch \else
+ \flexiblefalse
+ \fi
+ \ifflexible
+ % breaks ok but small displacements can occur
+ \skip2\scratchskip
+ \advance\skip2 -1\scratchskip
+ \divide\skip2 2
+ \advance\scratchskip -\skip2
+ \normalhskip\scratchskip
+ \normalpenalty\plustenthousand
+ \box0
+ \normalhskip\skip2
+ \else
+ \normalhskip\scratchskip
+ \box0
+ \fi
+ \egroup}
+
+\unexpanded\def\ruledhskip
+ {\bgroup
+ \afterassignment\supp_visualizers_hskip_indeed
+ \scratchskip=}
+
+%D The visual skip is located at a feasible point. Normally
+%D this does not interfere with the normaltypesetting process.
+%D The next examples show (1)~the default behavior, (2)~the
+%D (not entirely correct) distributed stretch and (3)~the way
+%D the text is typeset without cues.
+%D
+%D \startbuffer
+%D \dorecurse
+%D {15}
+%D {test\hskip1em plus .5em minus .5em
+%D test\hskip2em
+%D test}
+%D \stopbuffer
+%D
+%D \startlinecorrection
+%D \showmakeup
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \showmakeup
+%D \visiblestretchtrue
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+
+%D \macros
+%D {ruledvskip}
+%D
+%D We are less fortunate when implementing the vertical skips.
+%D This is a direct result of interference between the boxes that
+%D visualize the skip and skip removal at a pagebreak. Normally
+%D skips disappear at the top of a page, but not of course when
+%D visualized in a \type{\vbox}. A quite perfect simulation
+%D could have been built if we would have had available two
+%D more primitives: \type{\hnop} and \type{\vnop}. These new
+%D primitives could stand for boxes that are visible but are
+%D not taken into account in any way. They are there for us,
+%D but not for \TEX.
+%D
+%D \startbuffer
+%D first line
+%D \vskip +30pt plus 5pt
+%D second line
+%D \vskip +30pt
+%D \vskip -10pt plus 5pt
+%D third line
+%D \par
+%D fourth line
+%D \vskip +30pt
+%D fifth line
+%D \vskip 0pt
+%D sixth line
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+%D
+%D We have to postpone \type{\prevdepth}. Although this
+%D precaution probably is not completely waterproof, it works
+%D quite well.
+
+\def\dodoruledvskip
+ {\nextdepth\prevdepth
+ \dontinterfere
+ \dontcomplain
+ \normaloffinterlineskip
+ \investigateskip\scratchskip
+ \ifzero
+ \setbox0\normalvcue
+ {\visualvrule
+ \s!width32\testrulewidth
+ \s!height2\testrulewidth
+ \s!depth2\testrulewidth}%
+ \else
+ \setbox0\normalvbox to \ifnegative-\fi\scratchskip
+ {\visualhrule
+ \s!width16\testrulewidth
+ \s!height2\testrulewidth
+ \ifflexible
+ \cleaders
+ \normalhbox to 16\testrulewidth
+ {\normalhss
+ \normalvbox
+ {\normalvskip 2\testrulewidth
+ \visualhrule
+ \s!width2\testrulewidth
+ \s!height2\testrulewidth
+ \normalvskip 2\testrulewidth}%
+ \normalhss}%
+ \normalvfill
+ \else
+ \normalvfill
+ \fi
+ \visualhrule
+ \s!width16\testrulewidth
+ \s!height2\testrulewidth}%
+ \setbox2\normalvbox to \ht0
+ {\visualhrule
+ \s!width2\testrulewidth
+ \s!height\ht0}%
+ \ifnegative
+ \ht0\zeropoint
+ \setbox0\normalhbox
+ {\normalhskip2\testrulewidth % will be improved
+ \normalhskip-\wd0\box0}%
+ \fi
+ \smashbox0%
+ \smashbox2%
+ \setbox0\normalvcue
+ {\box2\box0}%
+ \setbox0\normalvbox
+ {\ifnegative\normalvskip\scratchskip\fi\box0}%
+ \smashbox0%
+ \fi
+ \ifvisiblestretch
+ \ifflexible
+ \skip2\scratchskip
+ \advance\skip2 -1\scratchskip
+ \divide\skip2 2
+ \advance\scratchskip -\skip2
+ \normalvskip\skip2
+ \fi
+ \fi
+ \normalpenalty\plustenthousand
+ \box0
+ \prevdepth\nextdepth % not \dp0=\nextdepth
+ \normalvskip\scratchskip}
+
+%D We try to avoid interfering at the top of a page. Of course
+%D we only do so when we are in the main vertical list.
+
+\def\doruledvskip
+ {\endgraf % \par
+ \ifdim\pagegoal=\maxdimen
+ \ifinner
+ \dodoruledvskip
+ \fi
+ \else
+ \dodoruledvskip
+ \fi
+ \egroup}
+
+\unexpanded\def\ruledvskip
+ {\bgroup
+ \afterassignment\doruledvskip
+ \scratchskip=}
+
+%D \macros
+%D {ruledkern}
+%D
+%D The macros that implement the kerns are a bit more
+%D complicated than needed, because they also serve the
+%D visualization of glue, our \PLAIN\ defined kerns with
+%D stretch or shrink. We've implemented both horizontal and
+%D vertical kerns as ruled boxes.
+%D
+%D \startbuffer
+%D one
+%D \kern +30pt
+%D two
+%D \kern +30pt
+%D \kern -10pt
+%D three
+%D \kern 0pt
+%D four
+%D \kern +30pt
+%D five
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+%D
+%D Positive and negative kerns are placed on top or below the
+%D baseline, so we are able to track their added result. We
+%D didn't mention spacings of 0~pt yet. Zero values are
+%D visualized a bit different, because we want to see them
+%D anyhow.
+
+\def\supp_visualizers_hkern_indeed
+ {\dontinterfere
+ \dontcomplain
+ \baselinerulefalse
+ \investigateskip\scratchskip
+ \boxrulewidth2\testrulewidth
+ \ifzero
+ \setbox0\ruledhbox to 8\testrulewidth
+ {\visualvrule
+ \s!width\zeropoint
+ \s!height16\testrulewidth
+ \s!depth16\testrulewidth}%
+ \setbox0\normalhbox
+ {\normalhskip-4\testrulewidth\box0}%
+ \else
+ \setbox0\ruledhbox to \ifnegative-\fi\scratchskip
+ {\visualvrule
+ \s!width\zeropoint
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth
+ \ifflexible
+ \normalhskip2\testrulewidth
+ \cleaders
+ \normalhbox
+ {\normalhskip 2\testrulewidth
+ \visualvrule
+ \s!width2\testrulewidth
+ \s!height\ifnegative-7\else9\fi\testrulewidth
+ \s!depth\ifnegative9\else-7\fi\testrulewidth
+ \normalhskip 2\testrulewidth}%
+ \normalhfill
+ \else
+ \normalhfill
+ \fi}%
+ \testrulewidth2\testrulewidth
+ \setbox0\ruledhbox{\box0}% \make...
+ \fi
+ \smashbox0%
+ \normalpenalty\plustenthousand
+ \normalhbox to \zeropoint
+ {\ifnegative\normalhskip1\scratchskip\fi
+ \box0}%
+ \afterwards\scratchskip
+ \egroup}
+
+\unexpanded\def\ruledhkern#1%
+ {\bgroup
+ \let\afterwards#1%
+ \afterassignment\supp_visualizers_hkern_indeed
+ \scratchskip=}
+
+%D After having seen the horizontal ones, the vertical kerns
+%D will not surprise us. In this example we use \type{\par} to
+%D switch to vertical mode.
+%D
+%D \startbuffer
+%D first line
+%D \par \kern +30pt
+%D second line
+%D \par \kern +30pt
+%D \par \kern -10pt
+%D third line
+%D \par
+%D fourth line
+%D \par \kern +30pt
+%D fifth line
+%D \par \kern 0pt
+%D sixth line
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+%D
+%D Like before, we have to postpone \type{\prevdepth}. If we
+%D leave out this trick, we got ourselves some wrong spacing.
+
+\def\supp_visualizers_vkern_finish
+ {\nextdepth\prevdepth
+ \dontinterfere
+ \dontcomplain
+ \baselinerulefalse
+ \normaloffinterlineskip
+ \investigateskip\scratchskip
+ \boxrulewidth2\testrulewidth
+ \ifzero
+ \setbox0\ruledhbox to 32\testrulewidth
+ {\visualvrule
+ \s!width\zeropoint
+ \s!height4\testrulewidth
+ \s!depth4\testrulewidth}%
+ \else
+ \setbox0\ruledvbox to \ifnegative-\fi\scratchskip
+ {\hsize16\testrulewidth
+ \ifflexible
+ \cleaders
+ \normalhbox to 16\testrulewidth
+ {\normalhss
+ \normalvbox
+ {\normalvskip 2\testrulewidth
+ \visualhrule
+ \s!width2\testrulewidth
+ \s!height2\testrulewidth
+ \normalvskip 2\testrulewidth}%
+ \normalhss}%
+ \normalvfill
+ \else
+ \visualvrule
+ \s!width\zeropoint
+ \s!height\ifnegative-\fi\scratchskip
+ \normalhfill
+ \fi}
+ \fi
+ \testrulewidth2\testrulewidth
+ \setbox0\ruledvbox{\box0}% \make...
+ \smashbox0%
+ \setbox0\normalvbox
+ {\ifnegative\normalvskip\scratchskip\fi
+ \normalvcue
+ {\ifnegative\normalhskip-16\testrulewidth\fi\box0}}%
+ \smashbox0%
+ \normalpenalty\plustenthousand
+ \box0
+ \prevdepth\nextdepth} % not \dp0=\nextdepth
+
+\def\supp_visualizers_vkern_indeed
+ {\ifdim\pagegoal=\maxdimen
+ \ifinner
+ \supp_visualizers_vkern_finish
+ \fi
+ \else
+ \supp_visualizers_vkern_finish
+ \fi
+ \afterwards\scratchskip
+ \egroup}
+
+\unexpanded\def\ruledvkern#1%
+ {\bgroup
+ \let\afterwards#1\relax
+ \afterassignment\supp_visualizers_vkern_indeed
+ \scratchskip=}
+
+\unexpanded\def\ruledkern
+ {\ifvmode
+ \expandafter\ruledvkern
+ \else
+ \expandafter\ruledhkern
+ \fi
+ \normalkern}
+
+%D A a bit more \TEX nice solution is:
+%D
+%D \starttyping
+%D \unexpanded\def\ruledkern%
+%D {\csname ruled\ifvmode v\else h\fi kern\endcsname\normalkern}
+%D \stoptyping
+
+%D \macros
+%D {ruledhglue,ruledvglue}
+%D
+%D The non-primitive glue commands are treated as kerns with
+%D stretch. This stretch is presented as a dashed line. I
+%D have to admit that until now, I've never used these glue
+%D commands.
+%D
+%D \startbuffer
+%D one
+%D \hglue +30pt plus 5pt
+%D two
+%D \hglue +30pt
+%D \hglue -10pt plus 5pt
+%D three
+%D \hglue 0pt
+%D four
+%D \hglue +30pt
+%D five
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+
+\def\supp_visualizers_hglue_indeed
+ {\leavevmode
+ \scratchcounter\spacefactor
+ \visualvrule\s!width\zeropoint
+ \normalpenalty\plustenthousand
+ \ruledhkern\normalhskip\scratchskip
+ \spacefactor\scratchcounter
+ \egroup}
+
+\unexpanded\def\ruledhglue
+ {\bgroup
+ \afterassignment\supp_visualizers_hglue_indeed\scratchskip=}
+
+%D \startbuffer
+%D first line
+%D \vglue +30pt plus 5pt
+%D second line
+%D \vglue +30pt
+%D \vglue -10pt plus 5pt
+%D third line
+%D \par
+%D fourth line
+%D \vglue +30pt
+%D fifth line
+%D \vglue 0pt
+%D sixth line
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+
+\def\supp_visualizers_vglue_indeed
+ {\endgraf % \par
+ \nextdepth\prevdepth
+ \visualhrule\s!height\zeropoint
+ \normalpenalty\plustenthousand
+ \ruledvkern\normalvskip\scratchskip
+ \prevdepth\nextdepth
+ \egroup}
+
+\unexpanded\def\ruledvglue
+ {\bgroup
+ \afterassignment\supp_visualizers_vglue_indeed\scratchskip=}
+
+%D \macros
+%D {ruledmkern,ruledmskip}
+%D
+%D Mathematical kerns and skips are specified in mu. This
+%D font related unit is incompatible with those of \DIMENSIONS\
+%D and \SKIPS. Because in math mode spacing is often a very
+%D subtle matter, we've used a very simple, not overloaded way
+%D to show them.
+
+\def\supp_visualizers_mkern_finish#1%
+ {\dontinterfere
+ \dontcomplain
+ \setbox\boxrulescratchbox\normalhbox
+ {\normalstartimath
+ \normalmkern\ifnegative-\fi\scratchskip
+ \normalstopimath}%
+ \setbox\boxrulescratchbox\normalhbox to \wd\boxrulescratchbox
+ {\visualvrule
+ \s!height16\testrulewidth
+ \s!depth 16\testrulewidth
+ \s!width \testrulewidth
+ \leaders
+ \visualhrule
+ \s!height\ifpositive 16\else-14\fi\testrulewidth
+ \s!depth \ifpositive-14\else 16\fi\testrulewidth
+ \normalhfill
+ \ifflexible
+ \normalhskip-\wd\boxrulescratchbox
+ \leaders
+ \visualhrule
+ \s!height\testrulewidth
+ \s!depth \testrulewidth
+ \normalhfill
+ \fi
+ \visualvrule
+ \s!height16\testrulewidth
+ \s!depth 16\testrulewidth
+ \s!width \testrulewidth}%
+ \smashbox0%
+ \ifnegative
+ #1\scratchskip
+ \box\boxrulescratchbox
+ \else
+ \box\boxrulescratchbox
+ #1\scratchskip
+ \fi
+ \egroup}
+
+%D \startbuffer
+%D $a \mkern3mu = \mkern3mu
+%D b \quad
+%D \mkern-2mu + \mkern-2mu
+%D \quad c$
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+
+\unexpanded\def\ruledmkern
+ {\bgroup
+ \afterassignment\supp_visualizers_mkern_indeed
+ \scratchmuskip=}
+
+\def\supp_visualizers_mkern_indeed
+ {\investigatemuskip\scratchmuskip
+ \flexiblefalse
+ \supp_visualizers_mkern_finish\normalmkern}
+
+%D \startbuffer
+%D $a \mskip3mu = \mskip3mu
+%D b \quad
+%D \mskip-2mu + \mskip-2mu
+%D \quad c$
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+
+\def\supp_visualizers_mskip_indeed
+ {\investigatemuskip\scratchmuskip
+ \flexibletrue
+ \supp_visualizers_mkern_finish\normalmskip}
+
+\unexpanded\def\ruledmskip
+ {\bgroup
+ \afterassignment\supp_visualizers_mskip_indeed
+ \scratchmuskip=}
+
+%D \macros
+%D {penalty}
+%D
+%D After presenting fills, skip, kerns and glue we've come to
+%D see penalties. In the first implementation --- most of the
+%D time needed to develop this set of macros went into testing
+%D different types of visualization --- penalties were mere
+%D small blocks with one black half, depending on the sign.
+%D This most recent version also gives an indication of the
+%D amount of penalty. Penalties can go from less than $-10000$
+%D to over $+10000$, and their behavior is somewhat
+%D non-lineair, with some values having special meanings. We
+%D therefore decided not to use its value for a lineair
+%D indicator.
+%D
+%D \startbuffer
+%D one
+%D \penalty +100
+%D two
+%D \penalty +100
+%D \penalty -100
+%D three
+%D \penalty 0
+%D four
+%D \penalty +100
+%D five
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+%D
+%D The small sticks at the side of the penalty indicate it
+%D size. The next example shows the positive and negative
+%D penalties of 0, 1, 10, 100, 1000 and 10000.
+%D
+%D \startlinecorrection
+%D \hbox
+%D {test \ruledhpenalty0
+%D test \ruledhpenalty1
+%D test \ruledhpenalty10
+%D test \ruledhpenalty100
+%D test \ruledhpenalty1000
+%D test \ruledhpenalty10000
+%D test}
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \hbox
+%D {test \ruledhpenalty0
+%D test \ruledhpenalty-1
+%D test \ruledhpenalty-10
+%D test \ruledhpenalty-100
+%D test \ruledhpenalty-1000
+%D test \ruledhpenalty-10000
+%D test}
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D This way stacked penalties of different severance can be
+%D shown in combination.
+%D
+%D test \ruledhpenalty10 \ruledhpenalty100
+%D test
+%D test \ruledhpenalty1000 \ruledhpenalty-1000
+%D test
+
+\def\supp_visualizers_penalty_box#1#2#3#4#5#6%
+ {\setbox#1\normalhbox
+ {\ifnum#2=\zerocount \else
+ \edef\sign{\ifnum#2>\zerocount +\else-\fi}%
+ \scratchdimen
+ \ifnum\sign#2>9999 28\else
+ \ifnum\sign#2>999 22\else
+ \ifnum\sign#2>99 16\else
+ \ifnum\sign#2>9 10\else
+ 4\fi\fi\fi\fi \testrulewidth
+ \ifnum#2<\zerocount
+ \normalhskip-\scratchdimen
+ \normalhskip-2\testrulewidth
+ \visualvrule
+ \s!width 2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth
+ \fi
+ \visualvrule
+ \s!width \scratchdimen
+ \s!height#5\testrulewidth
+ \s!depth #6\testrulewidth
+ \ifnum#2>\zerocount
+ \visualvrule
+ \s!width 2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth
+ \fi
+ \fi}%
+ \smashbox#1}
+
+\unexpanded\def\ruledhpenalty
+ {\bgroup
+ \afterassignment\supp_visualizers_hpenalty_indeed
+ \scratchcounter=}
+
+\def\supp_visualizers_hpenalty_indeed
+ {\dontinterfere
+ \dontcomplain
+ \investigatecount\scratchcounter
+ \testrulewidth2\testrulewidth
+ \boxrulewidth\testrulewidth
+ \setbox0\ruledhbox to 8\testrulewidth
+ {\ifnegative\else\normalhss\fi
+ \visualvrule
+ \s!depth8\testrulewidth
+ \s!width\ifzero\zeropoint\else4\testrulewidth\fi
+ \ifpositive\else\normalhss\fi}%
+ \supp_visualizers_penalty_box{2}{\scratchcounter}{0}{8}{-3.5}{4.5}%
+ \normalpenalty\plustenthousand
+ \setbox0\normalhbox
+ {\normalhskip-4\testrulewidth
+ \ifnegative
+ \box2\box0
+ \else
+ \box0\box2
+ \fi}%
+ \smashbox0%
+ \box0
+ \normalpenalty\scratchcounter
+ \egroup}
+
+%D The size of a vertical penalty is also shown on the
+%D horizontal axis. This way there is less interference with
+%D the often preceding or following skips and kerns.
+%D
+%D \startbuffer
+%D first line
+%D \par \penalty +100
+%D second line
+%D \par \penalty +100
+%D \par \penalty -100
+%D third line
+%D \par \penalty 0
+%D fourth line
+%D \par \penalty +100
+%D fifth line
+%D \stopbuffer
+%D
+%D \ShowBufferedExample
+
+\unexpanded\def\ruledvpenalty
+ {\bgroup
+ \afterassignment\supp_visualizers_vpenalty_indeed
+ \scratchcounter=}
+
+\def\supp_visualizers_vpenalty_indeed
+ {\ifdim\pagegoal=\maxdimen \else
+ \nextdepth\prevdepth
+ \dontinterfere
+ \dontcomplain
+ \investigatecount\scratchcounter
+ \testrulewidth2\testrulewidth
+ \boxrulewidth\testrulewidth
+ \setbox0\ruledhbox
+ {\visualvrule
+ \s!height4\testrulewidth
+ \s!depth 4\testrulewidth
+ \s!width \zeropoint
+ \visualvrule
+ \s!height\ifnegative.5\else4\fi\testrulewidth
+ \!!dept \ifpositive.5\else4\fi\testrulewidth
+ \s!width 8\testrulewidth}%
+ \supp_visualizers_penalty_box{2}{\scratchcounter}{4}{4}{.5}{.5}%
+ \setbox0\normalhbox
+ {\normalhskip-4\testrulewidth
+ \ifnegative
+ \box2\box0
+ \else
+ \box0\box2
+ \fi
+ \normalhss}%
+ \smashbox0%
+ \normalpenalty\plustenthousand
+ \nointerlineskip
+ \dp0\nextdepth % not \prevdepth=\nextdepth
+ \normalvbox
+ {\normalvcue{\box0}}%
+ \fi
+ \normalpenalty\scratchcounter
+ \egroup}
+
+%D This comes together in:
+
+\unexpanded\def\ruledpenalty
+ {\ifvmode
+ \expandafter\ruledvpenalty
+ \else
+ \expandafter\ruledhpenalty
+ \fi}
+
+%D \macros
+%D {showfils,dontshowfils,
+%D showboxes,dontshowboxes,
+%D showskips,dontshowskips,
+%D showpenalties,dontshowpenalties}
+%D
+%D For those who want to manipulate the visual cues in detail,
+%D we have grouped them.
+
+\newif\ifshowingcomposition % see later why we need this
+
+\unexpanded\def\showfils
+ {\showingcompositiontrue
+ \let\hss \ruledhss
+ \let\hfil \ruledhfil
+ \let\hfill \ruledhfill
+ \let\hfilneg \ruledhfilneg
+ \let\hfillneg \ruledhfillneg
+ \let\vss \ruledvss
+ \let\vfil \ruledvfil
+ \let\vfill \ruledvfill
+ \let\vfilneg \ruledvfilneg
+ \let\vfillneg \ruledvfillneg}
+
+\unexpanded\def\dontshowfils
+ {\let\hss \normalhss
+ \let\hfil \normalhfil
+ \let\hfill \normalhfill
+ \let\hfilneg \normalhfilneg
+ \let\hfillneg \normalhfillneg
+ \let\vss \normalvss
+ \let\vfil \normalvfil
+ \let\vfill \normalvfill
+ \let\vfilneg \normalvfilneg
+ \let\vfillneg \normalvfillneg}
+
+\unexpanded\def\showboxes
+ {\showingcompositiontrue
+ \baselineruletrue
+ \let\hbox \ruledhbox
+ \let\vbox \ruledvbox
+ \let\vtop \ruledvtop
+ \let\vcenter \ruledvcenter}
+
+\unexpanded\def\dontshowboxes
+ {\let\hbox \normalhbox
+ \let\vbox \normalvbox
+ \let\vtop \normalvtop
+ \let\vcenter \normalvcenter}
+
+\unexpanded\def\showskips
+ {\showingcompositiontrue
+ \let\hskip \ruledhskip
+ \let\vskip \ruledvskip
+ \let\kern \ruledkern
+ \let\mskip \ruledmskip
+ \let\mkern \ruledmkern
+ \let\hglue \ruledhglue
+ \let\vglue \ruledvglue}
+
+\unexpanded\def\dontshowskips
+ {\let\hskip \normalhskip
+ \let\vskip \normalvskip
+ \let\kern \normalkern
+ \let\mskip \normalmskip
+ \let\mkern \normalmkern
+ \let\hglue \normalhglue
+ \let\vglue \normalvglue}
+
+\unexpanded\def\showpenalties
+ {\showingcompositiontrue
+ \let\penalty \ruledpenalty}
+
+\unexpanded\def\dontshowpenalties
+ {\let\penalty \normalpenalty}
+
+%D \macros
+%D {showcomposition,dontshowcomposition,
+%D showingcomposition}
+%D
+%D All these nice options come together in three macros. One
+%D for turning the options on, one for turning them off, and a
+%D boolean for enabling the mechanism outside the scope of the
+%D user. The first two macros only do their job when we are
+%D actually showing the composition.
+%D
+%D \starttyping
+%D \showingcompositiontrue
+%D \showcomposition
+%D \stoptyping
+%D
+%D Because the output routine can do tricky things, like
+%D multiple column typesetting and manipulation of the
+%D pagebody, shifting things around and so on, the macro
+%D \type{\dontshowcomposition} best can be called when we enter
+%D this routine. Too much visual cues just don't make sense. In
+%D \CONTEXT\ this has been taken care of.
+
+\newif\ifshowingcomposition
+
+\unexpanded\def\showcomposition
+ {\ifshowingcomposition
+ \showfils
+ \showboxes
+ \showskips
+ \showpenalties
+ \fi}
+
+\unexpanded\def\dontshowcomposition
+ {\ifshowingcomposition
+ \dontshowfils
+ \dontshowboxes
+ \dontshowskips
+ \dontshowpenalties
+ \fi}
+
+%D \macros
+%D {showmakeup,
+%D defaulttestrulewidth}
+%D
+%D Just to make things even more easy, we have defined:
+%D
+%D \starttyping
+%D \showmakeup
+%D \stoptyping
+%D
+%D For the sake of those who don't (yet) use \CONTEXT\ we
+%D preset \type{\defaulttestrulewidth} to the already set
+%D value. Otherwise we default to a bodyfontsize related value.
+%D
+%D \starttyping
+%D \def\defaulttestrulewidth{.2pt}
+%D \stoptyping
+%D
+%D Beware, it's a macro not a \DIMENSION.
+
+\ifx\bodyfontsize\undefined
+ \edef\defaulttestrulewidth{\the\testrulewidth}
+\else
+ \def\defaulttestrulewidth{.02\bodyfontsize}
+\fi
+
+\unexpanded\def\showmakeup
+ {\testrulewidth\defaulttestrulewidth
+ \showingcompositiontrue
+ \showcomposition}
+
+\protect
+
+%D Lets end with some more advanced examples.
+%D Definitions and enumerations come in many flavors. The
+%D next one for instance is defined as:
+%D
+%D \starttyping
+%D \definedescription[test][place=left,hang=3,width=6em]
+%D \stoptyping
+%D
+%D When applied to some text, this would look like:
+%D
+%D \bgroup
+%D \showmakeup
+%D \definedescription[test][location=left,hang=3,width=6em]
+%D
+%D \test{visual\\debugger} I would be very pleased if \TEX\
+%D had two more primitives: \type{\vnop} and \type{\hnop}. Both
+%D should act and show up as normal boxes, but stay invisible
+%D for \TEX\ when it's doing calculations. The \type{\vnop}
+%D for instance should not interact with the internal mechanism
+%D responsible for the disappearing skips, kerns and penalties
+%D at a pagebreak. As long as we don't have these two boxtypes,
+%D visual debugging will never be perfect.
+%D
+%D \egroup
+%D
+%D The index to this section looks like:
+%D
+%D {\setupreferencing[prefixprefix=dummy]\showmakeup\placeindex[criterium=local]}
+%D
+%D Although not impressive examples or typesetting, both
+%D show us how and where things happen. When somehow the last
+%D lines in this two column index don't allign, then this is
+%D due to some still unknown interference.
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cc.mkiv
new file mode 100644
index 00000000000..e753d695f8c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cc.mkiv
@@ -0,0 +1,88 @@
+%D \module
+%D [ file=symb-imp-cc,
+%D version=2013.03.22,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Creative Commons,
+%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 LS/HH: This font has changed over time so there might be diffences
+%D in rendering. The otf, ttf and type1 version can differ too.
+
+\doifelsefontpresent{ccicons.otf} { % redone ctan version
+ \definefontfeature
+ [creativecommons]
+ [mode=base,
+ goodies=ccicons,
+ unicoding=yes]
+ \definefontsynonym
+ [creativecommons]
+ [ccicons*creativecommons]
+} { % official version
+ \definefontfeature
+ [creativecommons]
+ [mode=base,
+ goodies=cc-icons,
+ unicoding=yes]
+ \definefontsynonym
+ [creativecommons]
+ [cc-icons*creativecommons]
+}
+
+\startsymbolset[cc]
+
+ \definesymbol [sa] [\getnamedglyphdirect{creativecommons}{sa}]
+ \definesymbol [by] [\getnamedglyphdirect{creativecommons}{by}]
+ \definesymbol [cc] [\getnamedglyphdirect{creativecommons}{cc}]
+ \definesymbol [nd] [\getnamedglyphdirect{creativecommons}{nd}]
+ \definesymbol [nc] [\getnamedglyphdirect{creativecommons}{nc}]
+ \definesymbol [ncus] [\getnamedglyphdirect{creativecommons}{nc}]
+ \definesymbol [nceu] [\getnamedglyphdirect{creativecommons}{nceu}]
+ \definesymbol [ncjp] [\getnamedglyphdirect{creativecommons}{ncjp}]
+ \definesymbol [pd] [\getnamedglyphdirect{creativecommons}{pd}]
+ \definesymbol [sampling] [\getnamedglyphdirect{creativecommons}{sampling}]
+ \definesymbol [share] [\getnamedglyphdirect{creativecommons}{share}]
+ \definesymbol [remix] [\getnamedglyphdirect{creativecommons}{remix}]
+ \definesymbol [zero] [\getnamedglyphdirect{creativecommons}{zero}]
+ \definesymbol [logo] [\getnamedglyphdirect{creativecommons}{logo}]
+
+ % \definesymbol [cc-by-sa-nc] [\dontleavehmode\lower.15ex\hbox\bgroup
+ % \getnamedglyphdirect{creativecommons}{cc}\enspace
+ % \getnamedglyphdirect{creativecommons}{by}\enspace
+ % \getnamedglyphdirect{creativecommons}{sa}\enspace
+ % \getnamedglyphdirect{creativecommons}{nc}%
+ % \egroup]
+ %
+ % % more efficient:
+ %
+ % \definesymbol [cc-by-sa-nc] [\dontleavehmode\lower.15ex\hbox\bgroup
+ % \directsymbol{cc}{cc}\enspace\directsymbol{cc}{by}\enspace
+ % \directsymbol{cc}{sa}\enspace\directsymbol{cc}{nc}%
+ % \egroup]
+ %
+ % % more fun:
+
+ \unexpanded\def\creativecommons#1%
+ {\dontleavehmode\lower.15\exheight\hbox\bgroup
+ \let\inbetween\relax
+ \processseparatedlist[#1][-]{\inbetween\let\inbetween\enspace\directsymbol{cc}}%
+ \egroup}
+
+ \definesymbol [cc-by-sa-nc] [\creativecommons{cc-by-sa-nc}]
+
+\stopsymbolset
+
+\continueifinputfile{symb-imp-cc.mkiv}
+
+\starttext
+
+ \showsymbolset[cc]
+
+ \symbol[cc][cc-by-sa-nc]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cow.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cow.mkiv
new file mode 100644
index 00000000000..59eabae28ca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-cow.mkiv
@@ -0,0 +1,130 @@
+%D \module
+%D [ file=symb-cow,
+%D version=2006.06.23,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Cow Symbols,
+%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.
+
+\definefontsynonym [Cows] [koeielett]
+\definefontsynonym [CowsContour] [koeielett-contour]
+\definefontsynonym [CowsLogo] [koeielogos]
+\definefontsynonym [CowsLogoContour] [koeielogos-contour]
+
+\definecolor [lsky] [r=.6,g=.6,b=1]
+\definecolor [dsky] [r=.1,g=.1,b=1]
+\definecolor [lground] [r=.3,g=.9,b=.3]
+\definecolor [dground] [r=0,g=.5,b=0]
+\definecolor [cspots] [r=.33,g=.1,b=0]
+
+\definecolor [tlsky] [t=.5,a=1,r=.6,g=.6,b=1]
+\definecolor [tdsky] [t=.5,a=1,r=.1,g=.1,b=1]
+\definecolor [tlground] [t=.5,a=1,r=.3,g=.9,b=.3]
+\definecolor [tdground] [t=.5,a=1,r=0,g=.5,b=0]
+\definecolor [tcspots] [t=.5,a=1,r=.33,g=.1,b=0]
+
+\definepalet
+ [cow]
+ [normal=lground,
+ contour=dground,
+ sky=lsky]
+
+\def\CowNormal#1%
+ {\dontleavehmode\hbox{\color[cow:normal]{\getnamedglyphdirect{Cows}{#1}}}}
+
+\def\ScaledCowNormal#1#2%
+ {\dontleavehmode\hbox{\color[cow:normal]{\definedfont[Cows sa #1]#2}}}
+
+\def\ScaledCowOverlay#1#2%
+ {\dontleavehmode\hbox
+ {\color[cow:contour]{\hsmash{\definedfont[CowsContour sa #1]#2}}%
+ \color[cow:normal] {\definedfont[Cows sa #1]#2}}}
+
+\def\CowOverlay#1%
+ {\dontleavehmode\hbox
+ {\color[cow:contour]{\hsmash{\getnamedglyphdirect{CowsContour}{#1}}}%
+ \color[cow:normal] {\getnamedglyphdirect{Cows} {#1}}}}
+
+\def\CowContour#1%
+ {\dontleavehmode\hbox
+ {\color[cow:contour]{\hsmash{\getnamedglyphdirect{CowsLogoContour}{#1}}}%
+ \color[cow:normal] {\getnamedglyphdirect{CowsLogo} {#1}}}}
+
+\def\CowLogo {\getnamedglyphdirect{CowsLogo}} % #1
+\def\CowContourLogo{\getnamedglyphdirect{CowsLogoContour}} % #1
+
+\chardef\CowPragmaNormal= 1
+\chardef\CowPragmaShaded=20
+
+\startsymbolset[cownormal]
+
+ \definesymbol[CowPragmaADE] [\CowLogo{P_r_a_g_m_a_A_d_e}]
+ \definesymbol[CowPragma] [\CowLogo{p_r_a_g_m_a_a_d_e}]
+ \definesymbol[CowConTeXt] [\CowLogo{c_o_n_t_e_x_t}]
+ \definesymbol[CowConTeXtComplete] [\CowLogo{contextlogo}]
+ \definesymbol[CowConTeXtShadow] [\CowLogo{contextlogo.shadow}]
+ \definesymbol[CowConTeXtContour] [\CowLogo{contextlogo.contour}]
+ \definesymbol[CowConTeXtOutline] [\CowLogo{contextlogo.skeleton}]
+ \definesymbol[CowConTeXtDots] [\CowLogo{contextlogo.dots}]
+ \definesymbol[CowMP] [\CowLogo{M_P}]
+ \definesymbol[CowMPComplete] [\CowLogo{mplogo}]
+ \definesymbol[CowTeX] [\CowLogo{T_e_X}]
+ \definesymbol[CowTeXComplete] [\CowLogo{texlogo.alt}]
+ \definesymbol[CowBoo] [\CowLogo{boo}]
+ \definesymbol[CowCow] [\CowLogo{cow}]
+ \definesymbol[CowExampleComplete] [\CowLogo{E_x_a_m_p_l_e}]
+ \definesymbol[CowFoxetComplete] [\CowLogo{F_o_X_e_t}]
+ \definesymbol[CowMetafun] [\CowLogo{m_e_t_a_f_u_n}]
+ \definesymbol[CowMetafunComplete] [\CowLogo{metafunlogo}]
+ \definesymbol[CowTEXComplete] [\CowLogo{texlogo}]
+ \definesymbol[CowWikiComplete] [\CowLogo{wikilogo}]
+ \definesymbol[CowPragmaADEComplete][\CowLogo{PragmaADElogo}]
+ \definesymbol[CowPragmaComplete] [\CowLogo{pragmaadelogo}]
+ \definesymbol[CowExample] [\CowLogo{examplelogo}]
+ \definesymbol[CowFoxet] [\CowLogo{foxetlogo}]
+ \definesymbol[CowTEX] [\CowLogo{T_E_X}]
+ \definesymbol[CowWiki] [\CowLogo{W_i_k_i}]
+ \definesymbol[CowCowTeXtComplete] [\CowLogo{cowtextlogo}]
+ \definesymbol[CowCowTeXt] [\CowLogo{C_o_w_t_e_x_t}]
+
+\stopsymbolset
+
+\startsymbolset[cowcontour]
+
+ \definesymbol[CowPragmaADE] [\CowLogo{P_r_a_g_m_a_A_d_e}]
+ \definesymbol[CowPragma] [\CowLogo{p_r_a_g_m_a_a_d_e}]
+ \definesymbol[CowConTeXt] [\CowLogo{c_o_n_t_e_x_t}]
+ \definesymbol[CowConTeXtComplete] [\CowLogo{contextlogo}]
+ \definesymbol[CowConTeXtShadow] [\CowLogo{contextlogo.shadow}]
+ \definesymbol[CowConTeXtContour] [\CowLogo{contextlogo.contour}]
+ \definesymbol[CowConTeXtOutline] [\CowLogo{contextlogo.skeleton}]
+ \definesymbol[CowConTeXtDots] [\CowLogo{contextlogo.dots}]
+ \definesymbol[CowMP] [\CowLogo{M_P}]
+ \definesymbol[CowMPComplete] [\CowLogo{mplogo}]
+ \definesymbol[CowTeX] [\CowLogo{T_e_X}]
+ \definesymbol[CowTeXComplete] [\CowLogo{texlogo.alt}]
+ \definesymbol[CowBoo] [\CowLogo{boo}]
+ \definesymbol[CowCow] [\CowLogo{cow}]
+ \definesymbol[CowExampleComplete] [\CowLogo{E_x_a_m_p_l_e}]
+ \definesymbol[CowFoxetComplete] [\CowLogo{F_o_X_e_t}]
+ \definesymbol[CowMetafun] [\CowLogo{m_e_t_a_f_u_n}]
+ \definesymbol[CowMetafunComplete] [\CowLogo{metafunlogo}]
+ \definesymbol[CowTEXComplete] [\CowLogo{texlogo}]
+ \definesymbol[CowWikiComplete] [\CowLogo{wikilogo}]
+ \definesymbol[CowPragmaADEComplete][\CowLogo{PragmaADElogo}]
+ \definesymbol[CowPragmaComplete] [\CowLogo{pragmaadelogo}]
+ \definesymbol[CowExample] [\CowLogo{examplelogo}]
+ \definesymbol[CowFoxet] [\CowLogo{foxetlogo}]
+ \definesymbol[CowTEX] [\CowLogo{T_E_X}]
+ \definesymbol[CowWiki] [\CowLogo{W_i_k_i}]
+ \definesymbol[CowCowTeXtComplete] [\CowLogo{cowtextlogo}]
+ \definesymbol[CowCowTeXt] [\CowLogo{C_o_w_t_e_x_t}]
+
+\stopsymbolset
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-eur.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-eur.mkiv
new file mode 100644
index 00000000000..19a88c8fa86
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-eur.mkiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=symb-eur,
+%D version=2000.06.22,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Adobe Euro Symbols,
+%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.
+
+\definefontsynonym [EuroSerif] [eurose]
+\definefontsynonym [EuroSerifBold] [euroseb]
+\definefontsynonym [EuroSerifItalic] [eurosei]
+\definefontsynonym [EuroSerifSlanted] [eurosei]
+\definefontsynonym [EuroSerifBoldItalic] [eurosebi]
+\definefontsynonym [EuroSerifBoldSlanted] [eurosebi]
+
+\definefontsynonym [EuroSans] [eurosa]
+\definefontsynonym [EuroSansBold] [eurosab]
+\definefontsynonym [EuroSansItalic] [eurosai]
+\definefontsynonym [EuroSansSlanted] [eurosai]
+\definefontsynonym [EuroSansBoldItalic] [eurosabi]
+\definefontsynonym [EuroSansBoldSlanted] [eurosabi]
+
+\definefontsynonym [EuroMono] [euromo]
+\definefontsynonym [EuroMonoBold] [euromob]
+\definefontsynonym [EuroMonoSlanted] [euromoi]
+\definefontsynonym [EuroMonoItalic] [euromoi]
+\definefontsynonym [EuroMonoBoldItalic] [euromobi]
+\definefontsynonym [EuroMonoBoldSlanted] [euromobi]
+
+\definesymbol [euro] [\getglyph{Euro}{\fontchar{Euro.127}}]
+
+% \unexpanded\def\euro{\doiftextelse\texteuro\texteuro{\symbol[euro]}}
+
+%D The next table shows the complete set of symbols:
+%D
+%D \starttabulate[|l|c|c|c|c|c|c|]
+%D \NC \NC \tex{tf} \NC \tex{bf} \NC \tex{sl}
+%D \NC \tex{it} \NC \tex{bs} \NC \tex{bi} \NC\NR
+%D \NC \rm Serif \NC \rm\tf\euro \NC \rm\bf\euro \NC \rm\sl\euro
+%D \NC \rm\it\euro \NC \rm\bs\euro \NC \rm\bi\euro \NC\NR
+%D \NC \ss Sans \NC \ss\tf\euro \NC \ss\bf\euro \NC \ss\sl\euro
+%D \NC \ss\it\euro \NC \ss\bs\euro \NC \ss\bi\euro \NC\NR
+%D \NC \tt Mono \NC \tt\tf\euro \NC \tt\bf\euro \NC \tt\sl\euro
+%D \NC \tt\it\euro \NC \tt\bs\euro \NC \tt\bi\euro \NC\NR
+%D \stoptabulate
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-jmn.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-jmn.mkiv
new file mode 100644
index 00000000000..d66e0a33257
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-jmn.mkiv
@@ -0,0 +1,196 @@
+%D \module
+%D [ file=symb-jmn,
+%D version=2004.08.02,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Special Navigational Symbols,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file defines a few navigational symbol vectors. The font used
+%D here is designed by Janusz M.~Nowacki, one of the Polish Font
+%D Gurus who made this font specially for me, hence the name. If you
+%D you want to meet its designer, come to Bachotek! In case you're
+%D not familiar with his work, take a look at the Antikwa, Iwona and
+%D Kurier fonts!
+%D
+%D \usesymbols[jmn]
+%D
+%D \showsymbolset[navigation 1]
+%D \showsymbolset[navigation 3]
+%D \showsymbolset[navigation 2]
+%D \showsymbolset[navigation 4]
+%D
+%D \page
+%D \showfont[NavigationNormal]
+%D \page
+%D \showfont[NavigationShadowed]
+%D \page
+
+% needed:
+%
+% - inverted crossed
+% - curved diamond
+% - begin/end bars
+
+\unprotect
+
+\definefontsynonym[NavigationNormal] [hans]
+\definefontsynonym[NavigationShadowed] [hans-sh]
+
+\definefontsynonym[NavigationFont] [NavigationNormal]
+%definefontsynonym[NavigationFont] [NavigationShadowed]
+
+\def\NavigationGlyph{\getnamedglyphdirect{NavigationFont}} % #1
+
+\unprotect
+
+% lowercase up/down
+
+\startsymbolset [navigation 1]
+
+ \definesymbol [\v!PreviousJump] [\NavigationGlyph{CC}]
+ \definesymbol [\v!NextJump] [\NavigationGlyph{DD}]
+ \definesymbol [\v!CloseDocument] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!firstpage] [\NavigationGlyph{CCC}]
+ \definesymbol [\v!previouspage] [\NavigationGlyph{C}]
+ \definesymbol [\v!nextpage] [\NavigationGlyph{D}]
+ \definesymbol [\v!lastpage] [\NavigationGlyph{DDD}]
+
+ \definesymbol [\v!firstsubpage] [\NavigationGlyph{ccc}]
+ \definesymbol [\v!previoussubpage] [\NavigationGlyph{c}]
+ \definesymbol [\v!nextsubpage] [\NavigationGlyph{d}]
+ \definesymbol [\v!lastsubpage] [\NavigationGlyph{ddd}]
+
+ \definesymbol [\v!StartSound] [\NavigationGlyph{D}]
+ \definesymbol [\v!PauseSound] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopSound] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!StartMovie] [\NavigationGlyph{D}]
+ \definesymbol [\v!PauseMovie] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopMovie] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!StartRendering] [\NavigationGlyph{D}]
+ \definesymbol [\v!PauseRendering] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopRendering] [\NavigationGlyph{M}]
+ \definesymbol [\v!ResumeRendering] [\NavigationGlyph{D}]
+
+\stopsymbolset
+
+\startsymbolset [navigation 2]
+
+ \definesymbol [\v!PreviousJump] [\NavigationGlyph{AA}]
+ \definesymbol [\v!NextJump] [\NavigationGlyph{BB}]
+ \definesymbol [\v!CloseDocument] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!firstpage] [\NavigationGlyph{AAA}]
+ \definesymbol [\v!previouspage] [\NavigationGlyph{A}]
+ \definesymbol [\v!nextpage] [\NavigationGlyph{B}]
+ \definesymbol [\v!lastpage] [\NavigationGlyph{BBB}]
+
+ \definesymbol [\v!firstsubpage] [\NavigationGlyph{aaa}]
+ \definesymbol [\v!previoussubpage] [\NavigationGlyph{a}]
+ \definesymbol [\v!nextsubpage] [\NavigationGlyph{b}]
+ \definesymbol [\v!lastsubpage] [\NavigationGlyph{bbb}]
+
+ \definesymbol [\v!StartSound] [\NavigationGlyph{B}]
+ \definesymbol [\v!PauseSound] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopSound] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!StartMovie] [\NavigationGlyph{B}]
+ \definesymbol [\v!PauseMovie] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopMovie] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!StartRendering] [\NavigationGlyph{B}]
+ \definesymbol [\v!PauseRendering] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopRendering] [\NavigationGlyph{N}]
+ \definesymbol [\v!ResumeRendering] [\NavigationGlyph{B}]
+
+\stopsymbolset
+
+\startsymbolset [navigation 3]
+
+ \definesymbol [\v!PreviousJump] [\NavigationGlyph{KK}]
+ \definesymbol [\v!NextJump] [\NavigationGlyph{LL}]
+ \definesymbol [\v!CloseDocument] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!firstpage] [\NavigationGlyph{KKK}]
+ \definesymbol [\v!previouspage] [\NavigationGlyph{K}]
+ \definesymbol [\v!nextpage] [\NavigationGlyph{L}]
+ \definesymbol [\v!lastpage] [\NavigationGlyph{LLL}]
+
+ \definesymbol [\v!firstsubpage] [\NavigationGlyph{kkk}]
+ \definesymbol [\v!previoussubpage] [\NavigationGlyph{k}]
+ \definesymbol [\v!nextsubpage] [\NavigationGlyph{l}]
+ \definesymbol [\v!lastsubpage] [\NavigationGlyph{lll}]
+
+ \definesymbol [\v!StartSound] [\NavigationGlyph{L}]
+ \definesymbol [\v!PauseSound] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopSound] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!StartMovie] [\NavigationGlyph{L}]
+ \definesymbol [\v!PauseMovie] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopMovie] [\NavigationGlyph{M}]
+
+ \definesymbol [\v!StartRendering] [\NavigationGlyph{L}]
+ \definesymbol [\v!PauseRendering] [\NavigationGlyph{YY}]
+ \definesymbol [\v!StopRendering] [\NavigationGlyph{M}]
+ \definesymbol [\v!ResumeRendering] [\NavigationGlyph{L}]
+
+\stopsymbolset
+
+\startsymbolset [navigation 4]
+
+ \definesymbol [\v!PreviousJump] [\NavigationGlyph{II}]
+ \definesymbol [\v!NextJump] [\NavigationGlyph{JJ}]
+ \definesymbol [\v!CloseDocument] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!firstpage] [\NavigationGlyph{III}]
+ \definesymbol [\v!previouspage] [\NavigationGlyph{I}]
+ \definesymbol [\v!nextpage] [\NavigationGlyph{J}]
+ \definesymbol [\v!lastpage] [\NavigationGlyph{JJJ}]
+
+ \definesymbol [\v!firstsubpage] [\NavigationGlyph{iii}]
+ \definesymbol [\v!previoussubpage] [\NavigationGlyph{i}]
+ \definesymbol [\v!nextsubpage] [\NavigationGlyph{j}]
+ \definesymbol [\v!lastsubpage] [\NavigationGlyph{jjj}]
+
+ \definesymbol [\v!StartSound] [\NavigationGlyph{J}]
+ \definesymbol [\v!PauseSound] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopSound] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!StartMovie] [\NavigationGlyph{J}]
+ \definesymbol [\v!PauseMovie] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopMovie] [\NavigationGlyph{N}]
+
+ \definesymbol [\v!StartRendering] [\NavigationGlyph{J}]
+ \definesymbol [\v!PauseRendering] [\NavigationGlyph{XX}]
+ \definesymbol [\v!StopRendering] [\NavigationGlyph{N}]
+ \definesymbol [\v!ResumeRendering] [\NavigationGlyph{J}]
+
+\stopsymbolset
+
+% 1 left : 065 067 073 075
+% 2 left : 128 132 144 148
+% 3 left : 129 133 145 149
+
+% 1 right : 066 068 074 076
+% 2 right : 130 134 146 150
+% 3 right : 131 135 147 151
+
+% crossed : 160 160 160 160
+% opened : 152 152 156 156
+% closed : 154 154 158 158
+
+% larrow : 208 210 212 214
+% rarrow : 209 211 213 215
+% barrow : 178 178 178 178
+% ocircle : 168 168 168 168
+% ccircle : 170 170 170 170
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv
new file mode 100644
index 00000000000..d2657512f3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv
@@ -0,0 +1,77 @@
+%D \module
+%D [ file=symb-mis,
+%D version=2002.05.07,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Miscelaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+%D We predefine some common symbols and conversions that will
+%D be understood by many commands. The \type {\mathematics}
+%D is no longer needed, although only math fonts might have
+%D these symbols. The \type {\textmath} macro is twice as
+%D efficient.
+
+\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]
+
+% 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]
+
+ \definesymbol [bullet] [\textormathchar{"2022}] % • \bullet
+ \definesymbol [dash] [\textormathchar{"2013}] % –
+ \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 [blacktriangle] [\textormathchar{"25B6}] % ▶
+ \definesymbol [blacksquare] [\textormathchar{"25A0}] % ■
+ \definesymbol [blackdiamond] [\textormathchar{"25C6}] % ◆
+
+\stopsymbolset
+
+\definesymbol [smallcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptscriptstyle\bigcirc}}}]
+\definesymbol [medcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptstyle \bigcirc}}}]
+\definesymbol [bigcircle] [\textmath{\bigcirc}]
+
+\definesymbol [1] [\symbol{bullet}]
+\definesymbol [2] [\symbol{dash}]
+\definesymbol [3] [\symbol{star}]
+\definesymbol [4] [\symbol{triangle}]
+\definesymbol [5] [\symbol{circle}]
+\definesymbol [6] [\symbol{medcircle}]
+\definesymbol [7] [\symbol{bigcircle}]
+\definesymbol [8] [\symbol{square}]
+
+\definesymbol [S] [\sectionmark]
+\definesymbol [P] [\paragraphmark]
+\definesymbol [Numero] [\textnumero]
+\definesymbol [numero] [\textnumero]
+\definesymbol [euro] [\texteuro]
+
+\let\euro\texteuro
+
+\def\Numero{\symbol[Numero]} % obsolete
+\def\numero{\symbol[numero]} % obsolete
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv
new file mode 100644
index 00000000000..9902fc9e8a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv
@@ -0,0 +1,263 @@
+%D \module
+%D [ file=symb-mvs,
+%D version=2010.12.08, % 2000.03.30,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Martin Vogels Symbole,
+%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.
+
+\definefontsynonym [MartinVogel] [marvosym.ttf]
+
+\def\MartinVogelSymbol{\getnamedglyphdirect{MartinVogel}} % #1
+
+\startsymbolset [astronomic]
+
+ \definesymbol [Sun] [\MartinVogelSymbol{Sun}]
+ \definesymbol [Moon] [\MartinVogelSymbol{Moon}]
+ \definesymbol [Mercury] [\MartinVogelSymbol{Mercury}]
+ \definesymbol [Venus] [\MartinVogelSymbol{Venus}]
+ \definesymbol [Mars] [\MartinVogelSymbol{Mars}]
+ \definesymbol [Jupiter] [\MartinVogelSymbol{Jupiter}]
+ \definesymbol [Saturn] [\MartinVogelSymbol{Saturn}]
+ \definesymbol [Uranus] [\MartinVogelSymbol{Uranus}]
+ \definesymbol [Neptune] [\MartinVogelSymbol{Neptune}]
+ \definesymbol [Pluto] [\MartinVogelSymbol{Pluto}]
+
+\stopsymbolset
+
+\startsymbolset [zodiac]
+
+ \definesymbol [Aries] [\MartinVogelSymbol{Aries}]
+ \definesymbol [Taurus] [\MartinVogelSymbol{Taurus}]
+ \definesymbol [Gemini] [\MartinVogelSymbol{Gemini}]
+ \definesymbol [Cancer] [\MartinVogelSymbol{Cancer}]
+ \definesymbol [Leo] [\MartinVogelSymbol{Leo}]
+ \definesymbol [Virgo] [\MartinVogelSymbol{Virgo}]
+ \definesymbol [Libra] [\MartinVogelSymbol{Libra}]
+ \definesymbol [Scorpio] [\MartinVogelSymbol{Scorpio}]
+ \definesymbol [Sagittarius] [\MartinVogelSymbol{Sagittarius}]
+ \definesymbol [Capricorn] [\MartinVogelSymbol{Capricorn}]
+ \definesymbol [Aquarius] [\MartinVogelSymbol{Aquarius}]
+ \definesymbol [Pisces] [\MartinVogelSymbol{Pisces}]
+
+\stopsymbolset
+
+\startsymbolset [europe]
+
+ \definesymbol [EUR] [\MartinVogelSymbol{EUR}]
+ \definesymbol [EURhv] [\MartinVogelSymbol{EurHv}]
+ \definesymbol [EURcr] [\MartinVogelSymbol{EurCr}]
+ \definesymbol [EURtm] [\MartinVogelSymbol{EurTm}]
+ \definesymbol [EURdig] [\MartinVogelSymbol{EurDig}]
+ \definesymbol [CEsign] [\MartinVogelSymbol{CESign}]
+
+\stopsymbolset
+
+\startsymbolset [martinvogel 1]
+
+ \definesymbol [MVZero] [\MartinVogelSymbol{MVZero}]
+ \definesymbol [MVOne] [\MartinVogelSymbol{MVOne}]
+ \definesymbol [MVTwo] [\MartinVogelSymbol{MVTwo}]
+ \definesymbol [MVThree] [\MartinVogelSymbol{MVThree}]
+ \definesymbol [MVFour] [\MartinVogelSymbol{MVFour}]
+ \definesymbol [MVFive] [\MartinVogelSymbol{MVFive}]
+ \definesymbol [MVSix] [\MartinVogelSymbol{MVSix}]
+ \definesymbol [MVSeven] [\MartinVogelSymbol{MVSeven}]
+ \definesymbol [MVEight] [\MartinVogelSymbol{MVEight}]
+ \definesymbol [MVNine] [\MartinVogelSymbol{MVNine}]
+
+ \definesymbol [MVAt] [\MartinVogelSymbol{MVAt}]
+ \definesymbol [MVArrowDown] [\MartinVogelSymbol{MVArrowDown}]
+ \definesymbol [MVComma] [\MartinVogelSymbol{MVComma}]
+ \definesymbol [MVDivision] [\MartinVogelSymbol{MVDivision}]
+ \definesymbol [MVLeftBracket] [\MartinVogelSymbol{MVLeftBracket}]
+ \definesymbol [MVMinus] [\MartinVogelSymbol{MVMinus}]
+ \definesymbol [MVMultiplication] [\MartinVogelSymbol{MVMultiplication}]
+ \definesymbol [MVPeriod] [\MartinVogelSymbol{MVPeriod}]
+ \definesymbol [MVPlus] [\MartinVogelSymbol{MVPlus}]
+ \definesymbol [MVRightArrow] [\MartinVogelSymbol{MVRightArrow}]
+ \definesymbol [MVRightBracket] [\MartinVogelSymbol{MVRightBracket}]
+ \definesymbol [MVspace] [\MartinVogelSymbol{MVspace}]
+
+\stopsymbolset
+
+% Office signs, crosses, circles, arrows (names as in file)
+
+\startsymbolset [martinvogel 2]
+
+ \definesymbol [AngleSign] [\MartinVogelSymbol{AngleSign}]
+ \definesymbol [Ankh] [\MartinVogelSymbol{Ankh}]
+ \definesymbol [ArrowOver] [\MartinVogelSymbol{ArrowOver}]
+ \definesymbol [AtForty] [\MartinVogelSymbol{AtForty}]
+ \definesymbol [AtNinetyFive] [\MartinVogelSymbol{AtNinetyFive}]
+ \definesymbol [AtSixty] [\MartinVogelSymbol{AtSixty}]
+ %definesymbol [BOLogo] [\MartinVogelSymbol{BOLogo}]
+ %definesymbol [BOLogoL] [\MartinVogelSymbol{BOLogoL}]
+ %definesymbol [BOLogoP] [\MartinVogelSymbol{BOLogoP}]
+ \definesymbol [BSEFree] [\MartinVogelSymbol{BSEFree}]
+ \definesymbol [BarOver] [\MartinVogelSymbol{BarOver}]
+ \definesymbol [Bat] [\MartinVogelSymbol{Bat}]
+ \definesymbol [Beam] [\MartinVogelSymbol{Beam}]
+ \definesymbol [Bearing] [\MartinVogelSymbol{Bearing}]
+ \definesymbol [Bicycle] [\MartinVogelSymbol{Bicycle}]
+ \definesymbol [Biohazard] [\MartinVogelSymbol{Biohazard}]
+ \definesymbol [Bleech] [\MartinVogelSymbol{Bleech}]
+ \definesymbol [Bouquet] [\MartinVogelSymbol{Bouquet}]
+ \definesymbol [CeltCross] [\MartinVogelSymbol{CeltCross}]
+ \definesymbol [CheckedBox] [\MartinVogelSymbol{CheckedBox}]
+ \definesymbol [CircPipe] [\MartinVogelSymbol{CircPipe}]
+ \definesymbol [CircSteel] [\MartinVogelSymbol{CircSteel}]
+ \definesymbol [CircledA] [\MartinVogelSymbol{CircledA}]
+ \definesymbol [CleaningA] [\MartinVogelSymbol{CleaningA}]
+ \definesymbol [CleaningF] [\MartinVogelSymbol{CleaningF}]
+ \definesymbol [CleaningFF] [\MartinVogelSymbol{CleaningFF}]
+ \definesymbol [CleaningP] [\MartinVogelSymbol{CleaningP}]
+ \definesymbol [CleaningPP] [\MartinVogelSymbol{CleaningPP}]
+ \definesymbol [ClockLogo] [\MartinVogelSymbol{ClockLogo}]
+ \definesymbol [Coffeecup] [\MartinVogelSymbol{Coffeecup}]
+ \definesymbol [ComputerMouse] [\MartinVogelSymbol{ComputerMouse}]
+ \definesymbol [Conclusion] [\MartinVogelSymbol{Conclusion}]
+ \definesymbol [Congruent] [\MartinVogelSymbol{Congruent}]
+ \definesymbol [Corresponds] [\MartinVogelSymbol{Corresponds}]
+ \definesymbol [Cross] [\MartinVogelSymbol{Cross}]
+ \definesymbol [CrossedBox] [\MartinVogelSymbol{CrossedBox}]
+ \definesymbol [CutLeft] [\MartinVogelSymbol{CutLeft}]
+ \definesymbol [CutLine] [\MartinVogelSymbol{CutLine}]
+ \definesymbol [CutRight] [\MartinVogelSymbol{CutRight}]
+ \definesymbol [CuttingLine] [\MartinVogelSymbol{CuttingLine}]
+ \definesymbol [Deleatur] [\MartinVogelSymbol{Deleatur}]
+ \definesymbol [Divides] [\MartinVogelSymbol{Divides}]
+ \definesymbol [DividesNot] [\MartinVogelSymbol{DividesNot}]
+ \definesymbol [EMail] [\MartinVogelSymbol{EMail}]
+ \definesymbol [Earth] [\MartinVogelSymbol{Earth}]
+ \definesymbol [EmailCT] [\MartinVogelSymbol{EmailCT}]
+ \definesymbol [Equivalence] [\MartinVogelSymbol{Equivalence}]
+ \definesymbol [Estatically] [\MartinVogelSymbol{Estatically}]
+ \definesymbol [EstimatedSign] [\MartinVogelSymbol{EstimatedSign}]
+ \definesymbol [Explosionsafe] [\MartinVogelSymbol{Explosionsafe}]
+ \definesymbol [EyesDollar] [\MartinVogelSymbol{EyesDollar}]
+ \definesymbol [FAX] [\MartinVogelSymbol{FAX}]
+ \definesymbol [FEMALE] [\MartinVogelSymbol{FEMALE}]
+ \definesymbol [Fax] [\MartinVogelSymbol{Fax}]
+ \definesymbol [Female] [\MartinVogelSymbol{Female}]
+ \definesymbol [FemaleFemale] [\MartinVogelSymbol{FemaleFemale}]
+ \definesymbol [FemaleMale] [\MartinVogelSymbol{FemaleMale}]
+ \definesymbol [FixedBearing] [\MartinVogelSymbol{FixedBearing}]
+ \definesymbol [FlatSteel] [\MartinVogelSymbol{FlatSteel}]
+ \definesymbol [Florin] [\MartinVogelSymbol{Florin}]
+ \definesymbol [Football] [\MartinVogelSymbol{Football}]
+ \definesymbol [Forward] [\MartinVogelSymbol{Forward}]
+ \definesymbol [ForwardToEnd] [\MartinVogelSymbol{ForwardToEnd}]
+ \definesymbol [ForwardToIndex] [\MartinVogelSymbol{ForwardToIndex}]
+ \definesymbol [Frowny] [\MartinVogelSymbol{Frowny}]
+ \definesymbol [Gentsroom] [\MartinVogelSymbol{Gentsroom}]
+ \definesymbol [HERMAPHRODITE] [\MartinVogelSymbol{HERMAPHRODITE}]
+ \definesymbol [HandWash] [\MartinVogelSymbol{HandWash}]
+ \definesymbol [Heart] [\MartinVogelSymbol{Heart}]
+ \definesymbol [Hermaphrodite] [\MartinVogelSymbol{Hermaphrodite}]
+ \definesymbol [HexaSteel] [\MartinVogelSymbol{HexaSteel}]
+ \definesymbol [HollowBox] [\MartinVogelSymbol{HollowBox}]
+ \definesymbol [IRONING] [\MartinVogelSymbol{IRONING}]
+ \definesymbol [Industry] [\MartinVogelSymbol{Industry}]
+ \definesymbol [Info] [\MartinVogelSymbol{Info}]
+ \definesymbol [Ironing] [\MartinVogelSymbol{Ironing}]
+ \definesymbol [Keyboard] [\MartinVogelSymbol{Keyboard}]
+ \definesymbol [LSteel] [\MartinVogelSymbol{LSteel}]
+ \definesymbol [Ladiesroom] [\MartinVogelSymbol{Ladiesroom}]
+ \definesymbol [LargerOrEqual] [\MartinVogelSymbol{LargerOrEqual}]
+ \definesymbol [Laserbeam] [\MartinVogelSymbol{Laserbeam}]
+ \definesymbol [LeftScissors] [\MartinVogelSymbol{LeftScissors}]
+ \definesymbol [LeftTorque] [\MartinVogelSymbol{LeftTorque}]
+ \definesymbol [LessOrEqual] [\MartinVogelSymbol{LessOrEqual}]
+ \definesymbol [Letter] [\MartinVogelSymbol{Letter}]
+ \definesymbol [Lightning] [\MartinVogelSymbol{Lightning}]
+ \definesymbol [Lineload] [\MartinVogelSymbol{Lineload}]
+ \definesymbol [LooseBearing] [\MartinVogelSymbol{LooseBearing}]
+ \definesymbol [MALE] [\MartinVogelSymbol{MALE}]
+ \definesymbol [Male] [\MartinVogelSymbol{Male}]
+ \definesymbol [MaleMale] [\MartinVogelSymbol{MaleMale}]
+ \definesymbol [ManFace] [\MartinVogelSymbol{ManFace}]
+ \definesymbol [MineSign] [\MartinVogelSymbol{MineSign}]
+ \definesymbol [Mobilefone] [\MartinVogelSymbol{Mobilefone}]
+ \definesymbol [MoveDown] [\MartinVogelSymbol{MoveDown}]
+ \definesymbol [MoveUp] [\MartinVogelSymbol{MoveUp}]
+ \definesymbol [MultiplicationDot] [\MartinVogelSymbol{MultiplicationDot}]
+ \definesymbol [Mundus] [\MartinVogelSymbol{Mundus}]
+ \definesymbol [Neutral] [\MartinVogelSymbol{Neutral}]
+ \definesymbol [NoBleech] [\MartinVogelSymbol{NoBleech}]
+ \definesymbol [NoBreakSpace] [\MartinVogelSymbol{NoBreakSpace}]
+ \definesymbol [NoChemicalCleaning] [\MartinVogelSymbol{NoChemicalCleaning}]
+ \definesymbol [NoIroning] [\MartinVogelSymbol{NoIroning}]
+ \definesymbol [NoTumbler] [\MartinVogelSymbol{NoTumbler}]
+ \definesymbol [NoWash] [\MartinVogelSymbol{NoWash}]
+ \definesymbol [NotCongruent] [\MartinVogelSymbol{NotCongruent}]
+ \definesymbol [OktoSteel] [\MartinVogelSymbol{OktoSteel}]
+ \definesymbol [PackingWaste] [\MartinVogelSymbol{PackingWaste}]
+ \definesymbol [ParallelPort] [\MartinVogelSymbol{ParallelPort}]
+ \definesymbol [PeaceDove] [\MartinVogelSymbol{PeaceDove}]
+ \definesymbol [Pfund] [\MartinVogelSymbol{Pfund}]
+ \definesymbol [Pickup] [\MartinVogelSymbol{Pickup}]
+ \definesymbol [PointingHand] [\MartinVogelSymbol{PointingHand}]
+ \definesymbol [Printer] [\MartinVogelSymbol{Printer}]
+ \definesymbol [Radioactivity] [\MartinVogelSymbol{Radioactivity}]
+ \definesymbol [RectPipe] [\MartinVogelSymbol{RectPipe}]
+ \definesymbol [RectSteel] [\MartinVogelSymbol{RectSteel}]
+ \definesymbol [Recycling] [\MartinVogelSymbol{Recycling}]
+ \definesymbol [Rewind] [\MartinVogelSymbol{Rewind}]
+ \definesymbol [RewindToIndex] [\MartinVogelSymbol{RewindToIndex}]
+ \definesymbol [RewindToStart] [\MartinVogelSymbol{RewindToStart}]
+ \definesymbol [RightScissors] [\MartinVogelSymbol{RightScissors}]
+ \definesymbol [RightTorque] [\MartinVogelSymbol{RightTorque}]
+ \definesymbol [RoundedLSteel] [\MartinVogelSymbol{RoundedLSteel}]
+ \definesymbol [RoundedTSteel] [\MartinVogelSymbol{RoundedTSteel}]
+ \definesymbol [RoundedTTSteel] [\MartinVogelSymbol{RoundedTTSteel}]
+ \definesymbol [SerialInterface] [\MartinVogelSymbol{SerialInterface}]
+ \definesymbol [SerialPort] [\MartinVogelSymbol{SerialPort}]
+ \definesymbol [Shilling] [\MartinVogelSymbol{Shilling}]
+ \definesymbol [ShortFifty] [\MartinVogelSymbol{ShortFifty}]
+ \definesymbol [ShortForty] [\MartinVogelSymbol{ShortForty}]
+ \definesymbol [ShortNinetyfive] [\MartinVogelSymbol{ShortNinetyfive}]
+ \definesymbol [ShortSixty] [\MartinVogelSymbol{ShortSixty}]
+ \definesymbol [ShortThirty] [\MartinVogelSymbol{ShortThirty}]
+ \definesymbol [Smiley] [\MartinVogelSymbol{Smiley}]
+ \definesymbol [SoftHyphen] [\MartinVogelSymbol{SoftHyphen}]
+ \definesymbol [SpecialForty] [\MartinVogelSymbol{SpecialForty}]
+ \definesymbol [SquarePipe] [\MartinVogelSymbol{SquarePipe}]
+ \definesymbol [SquareSteel] [\MartinVogelSymbol{SquareSteel}]
+ \definesymbol [Stopsign] [\MartinVogelSymbol{Stopsign}]
+ \definesymbol [StrikingThrough] [\MartinVogelSymbol{StrikingThrough}]
+ \definesymbol [TSteel] [\MartinVogelSymbol{TSteel}]
+ \definesymbol [TTSteel] [\MartinVogelSymbol{TTSteel}]
+ \definesymbol [Telephone] [\MartinVogelSymbol{Telefon}]
+ \definesymbol [ToBottom] [\MartinVogelSymbol{ToBottom}]
+ \definesymbol [ToTop] [\MartinVogelSymbol{ToTop}]
+ \definesymbol [Tumbler] [\MartinVogelSymbol{Tumbler}]
+ \definesymbol [Valve] [\MartinVogelSymbol{Valve}]
+ \definesymbol [WashCotton] [\MartinVogelSymbol{WashCotton}]
+ \definesymbol [WashSynthetics] [\MartinVogelSymbol{WashSynthetics}]
+ \definesymbol [WashWool] [\MartinVogelSymbol{WashWool}]
+ \definesymbol [Wheelchair] [\MartinVogelSymbol{Wheelchair}]
+ \definesymbol [WomanFace] [\MartinVogelSymbol{WomanFace}]
+ \definesymbol [WritingHand] [\MartinVogelSymbol{WritingHand}]
+ \definesymbol [YinYang] [\MartinVogelSymbol{YinYang}]
+ \definesymbol [arrowOver] [\MartinVogelSymbol{arrowOver}]
+ \definesymbol [barOver] [\MartinVogelSymbol{barOver}]
+ \definesymbol [fax] [\MartinVogelSymbol{fax}]
+ %definesymbol [hyphen] [\MartinVogelSymbol{hyphen}]
+ \definesymbol [ironing] [\MartinVogelSymbol{ironing}]
+ %definesymbol [nonmarkingreturn] [\MartinVogelSymbol{nonmarkingreturn}]
+
+\stopsymbolset
+
+%D \showsymbolset[astronomic]
+%D \showsymbolset[zodiac]
+%D \showsymbolset[europe]
+%D \showsymbolset[martinvogel 1]
+%D \showsymbolset[martinvogel 2]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-nav.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-nav.mkiv
new file mode 100644
index 00000000000..6e2f2c1f034
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-nav.mkiv
@@ -0,0 +1,129 @@
+%D \module
+%D [ file=symb-nav,
+%D version=1998.07.20,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Navigational Symbols,
+%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
+
+\definesymbol [\v!first] [\symbol{\v!firstpage}]
+\definesymbol [\v!previous] [\symbol{\v!previouspage}]
+\definesymbol [\v!next] [\symbol{\v!nextpage}]
+\definesymbol [\v!last] [\symbol{\v!lastpage}]
+\definesymbol [\v!backward] [\symbol{\v!previouspage}]
+\definesymbol [\v!forward] [\symbol{\v!nextpage}]
+\definesymbol [\v!nowhere] [\symbol{bullet}]
+\definesymbol [\v!somewhere] [\startoverlay{\symbol\v!previouspage}{\symbol\v!nextpage}\stopoverlay]
+
+\definefontsynonym [ContextNavigation] [contnav]
+
+\def\ContextNavigationGlyph{\getnamedglyphdirect{ContextNavigation}} % #1
+
+\startsymbolset [navigation 1]
+
+ \definesymbol [\v!firstpage] [\ContextNavigationGlyph{char03}]
+ \definesymbol [\v!previouspage] [\ContextNavigationGlyph{char01}]
+ \definesymbol [\v!nextpage] [\ContextNavigationGlyph{char02}]
+ \definesymbol [\v!lastpage] [\ContextNavigationGlyph{char04}]
+
+ \definesymbol [\v!PreviousJump] [\ContextNavigationGlyph{char05}]
+ \definesymbol [\v!NextJump] [\ContextNavigationGlyph{char06}]
+
+ \definesymbol [\v!CloseDocument] [\ContextNavigationGlyph{char07}]
+
+ \definesymbol [\v!firstsubpage] [\ContextNavigationGlyph{char03}]
+ \definesymbol [\v!previoussubpage] [\ContextNavigationGlyph{char01}]
+ \definesymbol [\v!nextsubpage] [\ContextNavigationGlyph{char02}]
+ \definesymbol [\v!lastsubpage] [\ContextNavigationGlyph{char04}]
+
+ \definesymbol [\v!StartSound] [\ContextNavigationGlyph{char02}]
+ \definesymbol [\v!PauseSound] [\ContextNavigationGlyph{char08}]
+ \definesymbol [\v!StopSound] [\ContextNavigationGlyph{char07}]
+
+ \definesymbol [\v!StartMovie] [\ContextNavigationGlyph{char02}]
+ \definesymbol [\v!PauseMovie] [\ContextNavigationGlyph{char08}]
+ \definesymbol [\v!StopMovie] [\ContextNavigationGlyph{char07}]
+
+ \definesymbol [\v!StartRendering] [\ContextNavigationGlyph{char02}]
+ \definesymbol [\v!PauseRendering] [\ContextNavigationGlyph{char08}]
+ \definesymbol [\v!StopRendering] [\ContextNavigationGlyph{char07}]
+ \definesymbol [\v!ResumeRendering] [\ContextNavigationGlyph{char02}]
+
+\stopsymbolset
+
+\startsymbolset [navigation 2]
+
+ \definesymbol [\v!firstpage] [\ContextNavigationGlyph{char67}]
+ \definesymbol [\v!previouspage] [\ContextNavigationGlyph{char65}]
+ \definesymbol [\v!nextpage] [\ContextNavigationGlyph{char66}]
+ \definesymbol [\v!lastpage] [\ContextNavigationGlyph{char68}]
+
+ \definesymbol [\v!PreviousJump] [\ContextNavigationGlyph{char69}]
+ \definesymbol [\v!NextJump] [\ContextNavigationGlyph{char6a}]
+
+ \definesymbol [\v!CloseDocument] [\ContextNavigationGlyph{char6b}]
+
+ \definesymbol [\v!firstsubpage] [\ContextNavigationGlyph{char67}]
+ \definesymbol [\v!previoussubpage] [\ContextNavigationGlyph{char65}]
+ \definesymbol [\v!nextsubpage] [\ContextNavigationGlyph{char66}]
+ \definesymbol [\v!lastsubpage] [\ContextNavigationGlyph{char68}]
+
+ \definesymbol [\v!StartSound] [\ContextNavigationGlyph{char66}]
+ \definesymbol [\v!PauseSound] [\ContextNavigationGlyph{char6c}]
+ \definesymbol [\v!StopSound] [\ContextNavigationGlyph{char6b}]
+
+ \definesymbol [\v!StartMovie] [\ContextNavigationGlyph{char66}]
+ \definesymbol [\v!PauseMovie] [\ContextNavigationGlyph{char6c}]
+ \definesymbol [\v!StopMovie] [\ContextNavigationGlyph{char6b}]
+
+ \definesymbol [\v!StartRendering] [\ContextNavigationGlyph{char66}]
+ \definesymbol [\v!PauseRendering] [\ContextNavigationGlyph{char6c}]
+ \definesymbol [\v!StopRendering] [\ContextNavigationGlyph{char6b}]
+ \definesymbol [\v!ResumeRendering] [\ContextNavigationGlyph{char66}]
+
+\stopsymbolset
+
+\startsymbolset [navigation 3]
+
+ \definesymbol [\v!firstpage] [\ContextNavigationGlyph{charcb}]
+ \definesymbol [\v!previouspage] [\ContextNavigationGlyph{charc9}]
+ \definesymbol [\v!nextpage] [\ContextNavigationGlyph{charca}]
+ \definesymbol [\v!lastpage] [\ContextNavigationGlyph{charcc}]
+
+ \definesymbol [\v!PreviousJump] [\ContextNavigationGlyph{charcd}]
+ \definesymbol [\v!NextJump] [\ContextNavigationGlyph{charce}]
+
+ \definesymbol [\v!CloseDocument] [\ContextNavigationGlyph{charcf}]
+
+ \definesymbol [\v!firstsubpage] [\ContextNavigationGlyph{charcb}]
+ \definesymbol [\v!previoussubpage] [\ContextNavigationGlyph{charc9}]
+ \definesymbol [\v!nextsubpage] [\ContextNavigationGlyph{charca}]
+ \definesymbol [\v!lastsubpage] [\ContextNavigationGlyph{charcc}]
+
+ \definesymbol [\v!StartSound] [\ContextNavigationGlyph{charca}]
+ \definesymbol [\v!PauseSound] [\ContextNavigationGlyph{chard0}]
+ \definesymbol [\v!StopSound] [\ContextNavigationGlyph{charcf}]
+
+ \definesymbol [\v!StartMovie] [\ContextNavigationGlyph{charca}]
+ \definesymbol [\v!PauseMovie] [\ContextNavigationGlyph{chard0}]
+ \definesymbol [\v!StopMovie] [\ContextNavigationGlyph{charcf}]
+
+ \definesymbol [\v!StartRendering] [\ContextNavigationGlyph{charca}]
+ \definesymbol [\v!PauseRendering] [\ContextNavigationGlyph{chard0}]
+ \definesymbol [\v!StopRendering] [\ContextNavigationGlyph{charcf}]
+ \definesymbol [\v!ResumeRendering] [\ContextNavigationGlyph{charca}]
+
+\stopsymbolset
+
+%D \showsymbolset[navigation 1]
+%D \showsymbolset[navigation 2]
+%D \showsymbolset[navigation 3]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.lua
new file mode 100644
index 00000000000..6a4a1882529
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.lua
@@ -0,0 +1,62 @@
+if not modules then modules = { } end modules ['symb-ini'] = {
+ version = 1.001,
+ comment = "companion to symb-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local context = context
+local variables = interfaces.variables
+
+fonts = fonts or { } -- brrrr
+
+local symbols = fonts.symbols or { }
+fonts.symbols = symbols
+
+local listitem = utilities.parsers.listitem
+local uselibrary = resolvers.uselibrary
+
+local report_symbols = logs.reporter ("fonts","symbols")
+local status_symbols = logs.messenger("fonts","symbols")
+
+local patterns = {
+ "symb-imp-%s.mkiv",
+ "symb-imp-%s.tex",
+ -- obsolete:
+ "symb-%s.mkiv",
+ "symb-%s.tex"
+}
+
+local function action(name,foundname)
+ -- context.startnointerference()
+ context.startreadingfile()
+ context.input(foundname)
+ status_symbols("library %a loaded",name)
+ context.stopreadingfile()
+ -- context.stopnointerference()
+end
+
+local function failure(name)
+ report_symbols("library %a is unknown",name)
+end
+
+function symbols.uselibrary(name)
+ if name ~= variables.reset then
+ for name in listitem(name) do
+ uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+ end
+ end
+end
+
+interfaces.implement {
+ name = "usesymbols",
+ actions = symbols.uselibrary,
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv
new file mode 100644
index 00000000000..23879b43a28
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv
@@ -0,0 +1,318 @@
+%D \module
+%D [ file=symb-ini,
+%D version=1998.07.20,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Basic Symbols Commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The macros described here used to be part of the \type
+%D {core-con} module. I decided to move them here when
+%D symbolsets saw the light. Let their light shine.
+
+\writestatus{loading}{ConTeXt Symbol Libraries / Initialization}
+
+\registerctxluafile{symb-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {definesymbol, symbol}
+%D
+%D Converting numbers or levels into a character, romannumeral,
+%D symbol or something else, is supported by many \CONTEXT\
+%D commands. Therefore we need a mechanism for linking such
+%D numbers to their counterparts.
+%D
+%D First we take care of symbols. These are for instance used
+%D in enumerations and itemizations. We have:
+%D
+%D \showsetup{definesymbol}
+%D \showsetup{symbol}
+%D
+%D Symbols are simply linked to a tag. Such tags can be numbers
+%D or strings.
+%D
+%D \starttyping
+%D \definesymbol [1] [$\bullet$]
+%D \definesymbol [level 5] [$\star$]
+%D \stoptyping
+
+\installcorenamespace{symbol}
+\installcorenamespace{symbolset}
+
+\let\currentsymbol \empty
+\let\currentsymbolset\empty
+
+\newtoks\t_symb_setups
+
+\let\m_symb_current_set\empty
+
+\newconditional\c_symb_found
+
+\newtoks\everysymbol
+
+%D We don't use the commandhandler as symbols have their own
+%D subsystem for resolving values.
+
+\unexpanded\def\definesymbol
+ {\dotripleempty\symb_define}
+
+\def\symb_define[#1][#2][#3]% class name meaning
+ {\ifthirdargument
+ \setvalue{\??symbol#1:#2}{#3}%
+ \doifsomething{#1}{\addvalue{\??symbolset#1}{#2}}%
+ \else
+ \setvalue{\??symbol\m_symb_current_set:#1}{#2}%
+ \addvalue{\??symbolset\m_symb_current_set}{#1}%
+ \fi}
+
+\unexpanded\def\doifelseinsymbolset#1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\unexpanded\def\doifinsymbolset #1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\unexpanded\def\doifelsesymbolset #1{\ifcsname\??symbolset#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+
+\let\doifinsymbolsetelse\doifelseinsymbolset
+\let\doifsymbolsetelse \doifelsesymbolset
+
+\letvalue{\??symbolset}\empty
+
+%def\symbolset#1{\csname\??symbolset\ifcsname\??symbolset#1\endcsname#1\fi\endcsname} % no [#1], to be used in commalists etc
+
+\def\symbolset#1{\begincsname\??symbolset#1\endcsname} % no [#1], to be used in commalists etc
+
+%D Since symbols are used frequently in interactive
+%D documents, we speed up this one. Well, that was history,
+%D since now we simplified things a bit, because the low
+%D level macros have been sped up every now and then.
+
+% We support both:
+%
+% 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!
+
+\def\symb_place % so we also handle \symbol{name}
+ {\iffirstargument % which is nicer with following spaces
+ \expandafter\symb_place_normal
+ \else
+ \expandafter\symb_place_special
+ \fi}
+
+\def\symb_place_normal
+ {\ifsecondargument
+ \expandafter\symb_place_normal_a
+ \else
+ \expandafter\symb_place_normal_b
+ \fi}
+
+\def\symb_place_normal_a[#1][#2]%
+ {\edef\currentsymbol{#2}%
+ \ifcsname\??symbol#1:#2\endcsname
+ \symb_place_indeed{#1:#2}%
+ \else
+ \symb_place_normal_c
+ \fi}
+
+\def\symb_place_normal_b[#1][#2]%
+ {\edef\currentsymbol{#1}%
+ \ifcsname\??symbol\currentsymbolset:#1\endcsname
+ \symb_place_indeed{\currentsymbolset:#1}%
+ \else
+ \symb_place_normal_c
+ \fi}
+
+\def\symb_place_normal_c
+ {\setfalse\c_symb_found
+ \the\t_symb_setups
+ \ifconditional\c_symb_found \else
+ \symb_place_retry\currentsymbol % hm, isn't this redundant?
+ \fi}
+
+\def\symb_place_special[#1][#2]#3%
+ {\firstargumenttrue
+ \secondargumentfalse
+ \symb_place_normal[#3][]}
+
+\def\symb_place_indeed#1% \relax's prevent lookahead problems
+ {\settrue\c_symb_found
+ \begingroup
+ \the\everysymbol
+ \csname\??symbol#1\endcsname\relax
+ \endgroup}
+
+\letvalue{\??symbol}\firstofoneargument
+
+\def\directsymbol#1#2% no \relax, there can be an argument, see lists
+ %{\csname\??symbol\ifcsname\??symbol#1:#2\endcsname#1:#2\fi\endcsname}
+ {\begincsname\??symbol#1:#2\endcsname}
+
+\unexpanded\def\symb_fetch
+ {\ifconditional\c_symb_found
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\symb_fetch_indeed
+ \fi}
+
+\def\symb_fetch_indeed#1%
+ {\ifcsname\??symbol#1:\currentsymbol\endcsname
+ \symb_place_indeed{#1:\currentsymbol}%
+ \fi}
+
+\def\symb_place_retry#1%
+ {\ifcsname\??symbol:#1\endcsname
+ \symb_place_indeed{:#1}%
+ \else
+ #1%
+ \fi}
+
+%D \macros
+%D {definefiguresymbol}
+%D
+%D To simplify defining figure symbols, we offer:
+%D
+%D \showsetup{definefiguresymbol}
+%D
+%D By default, such symbols scale along the current bodyfont
+%D size or running font size (which is better).
+
+\def\defaultsymbolfactor{10}
+\def\defaultsymbolheight{1.25ex}
+
+\unexpanded\def\figuresymbol
+ {\dodoubleempty\symb_figure}
+
+\ifdefined\externalfigure \else \def\externalfigure[#1][#2]{#1} \fi
+\ifdefined\resetexternalfigures \else \let\resetexternalfigures\relax \fi
+
+\def\symb_figure[#1][% #2]%
+ {\externalfigure[#1][\c!reset=\v!yes,\c!symbol=\v!yes,\c!height=\defaultsymbolheight,}% #2]}
+
+\appendtoks \resetexternalfigures \to \everysymbol
+
+\unexpanded\def\definefiguresymbol
+ {\dotripleempty\symb_figure_define}
+
+\def\symb_figure_define[#1][#2][#3]%
+ {\ifsecondargument
+ \definesymbol[#1][{\symb_figure[#2][#3]}]%
+ \fi}
+
+%D \macros
+%D {doifsymboldefinedelse}
+%D
+%D A handy private one:
+
+\def\symb_fetch_first
+ {\ifconditional\c_symb_found
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\symb_fetch_first_indeed
+ \fi}
+
+\def\symb_fetch_first_indeed#1%
+ {\doifinsymbolset{#1}\currentsymbol{\settrue\c_symb_found}}
+
+\def\symb_fetch_second#1%
+ {\doifinsymbolset\empty\currentsymbol{\settrue\c_symb_found}}
+
+\unexpanded\def\doifelsesymboldefined#1%
+ {\begingroup
+ \edef\currentsymbol{#1}%
+ \let\symb_fetch\symb_fetch_first
+ \setfalse\c_symb_found
+ \the\t_symb_setups
+ \ifconditional\c_symb_found
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \symb_fetch_second\currentsymbol
+ \ifconditional\c_symb_found
+ \endgroup\doubleexpandafter\firstoftwoarguments
+ \else
+ \endgroup\doubleexpandafter\secondoftwoarguments
+ \fi
+ \fi}
+
+\let\doifsymboldefinedelse\doifelsesymboldefined
+
+%D \macros
+%D {setupsymbolset,startsymbolset}
+%D
+%D From these macro definitions one can deduce that symbols can
+%D be grouped in symbol sets:
+%D
+%D \starttyping
+%D \startsymbolset [navigation 1]
+%D \definefiguresymbol [Next] [mp-symb.1]
+%D \definefiguresymbol [Prev] [mp-symb.2]
+%D \stopsymbolset
+%D \stoptyping
+%D
+%D Such a symbol can be typeset with:
+%D
+%D \starttyping
+%D \setupsymbolset[navigation 1]\symbol[Next]
+%D \stoptyping
+%D
+%D or simply:
+%D
+%D \starttyping
+%D \symbol[navigation 1][Next]
+%D \stoptyping
+%D
+%D Formally:
+%D
+%D \showsetup{setupsymbolset}
+%D \showsetup{startsymbolset}
+
+\installcorenamespace{symbolsets}
+
+\unexpanded\def\startsymbolset[#1]%
+ {\pushmacro\m_symb_current_set
+ \def\m_symb_current_set{#1}}
+
+\unexpanded\def\stopsymbolset
+ {\popmacro\m_symb_current_set}
+
+\unexpanded\def\setupsymbolset[#1]%
+ {\edef\currentsymbolset{#1}%
+ \ifcsname\??symbolsets\currentsymbolset\endcsname \else
+ \symb_setup_symbol_set
+ \fi}
+
+\def\symb_setup_symbol_set
+ {\normalexpanded{\t_symb_setups{\symb_fetch{\currentsymbolset}\the\t_symb_setups}}%
+ \letvalue{\??symbolsets\currentsymbolset}\empty} % speedup
+
+\unexpanded\def\resetsymbolset
+ {\t_symb_setups\emptytoks}
+
+\unexpanded\def\forcesymbolset[#1]%
+ {\t_symb_setups{\symb_fetch{#1}}}
+
+%D \macros
+%D {showsymbolset}
+%D
+%D \showsetup{showsymbolset}
+
+\fetchruntimecommand \showsymbolset {\f!symbolprefix\s!run}
+
+%D \macros
+%D {usesymbols}
+%D
+%D \showsetup{usesymbols}
+
+\unexpanded\def\usesymbols[#1]{\clf_usesymbols{#1}}
+
+%D As longs as symbols are linked to levels or numbers, we can
+%D also use the conversion mechanism, but in for instance the
+%D itemization macros, we prefer symbols because they can more
+%D easier be (partially) redefined.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv
new file mode 100644
index 00000000000..ed4d90861ec
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=symb-run,
+%D version=2010.12.08, % 1998.07.20,
+%D title=\CONTEXT\ Symbol Libraries,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startluacode
+ function commands.showsymbolset(collection,symbols)
+ if type(symbols) == "string" then
+ symbols = utilities.parsers.settings_to_array(symbols)
+ end
+ 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.NC()
+ context(symbol)
+ context.NC()
+ context.symbol(symbol)
+ context.NC()
+ context.framed(options,context.nested.symbol(symbol))
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+ context.stop()
+ end
+\stopluacode
+
+\unprotect
+
+\unexpanded\gdef\showsymbolset
+ {\dosingleargument\symb_show_set}
+
+\gdef\symb_show_set[#1]%
+ {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}}
+
+\protect
+
+\continueifinputfile{symb-run.mkiv}
+
+\usesymbols[cc]
+
+\starttext
+
+ \showsymbolset[cc]
+
+ \symbol[cc][cc-by-sa-nc]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua
new file mode 100644
index 00000000000..98b92cef3b3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua
@@ -0,0 +1,514 @@
+if not modules then modules = { } end modules ['syst-aux'] = {
+ version = 1.001,
+ comment = "companion to syst-aux.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- slower than lpeg:
+--
+-- utfmatch(str,"(.?)(.*)$")
+-- utf.sub(str,1,1)
+
+local tonumber = tonumber
+local utfsub = utf.sub
+local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match
+local next = next
+local find = string.find
+
+local context = context
+local implement = interfaces.implement
+local formatters = string.formatters
+local setcatcode = tex.setcatcode
+local utf8character = lpeg.patterns.utf8character
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_set = utilities.parsers.settings_to_set
+local setmacro = interfaces.setmacro
+
+local pattern = C(utf8character^-1) * C(P(1)^0)
+
+implement {
+ name = "getfirstcharacter",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ setmacro("firstcharacter",first)
+ setmacro("remainingcharacters",rest)
+ end
+}
+
+implement {
+ name = "thefirstcharacter",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ context(first)
+ end
+}
+
+implement {
+ name = "theremainingcharacters",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ context(rest)
+ end
+}
+
+local pattern = C(utf8character^-1)
+local ctx_doifelse = commands.doifelse
+
+implement {
+ name = "doifelsefirstchar",
+ arguments = { "string", "string" },
+ actions = function(str,chr)
+ ctx_doifelse(lpegmatch(pattern,str) == chr)
+ end
+}
+
+implement {
+ name = "getsubstring",
+ arguments = { "string", "string", "string" },
+ actions = function(str,first,last)
+ context(utfsub(str,tonumber(first),tonumber(last)))
+ end
+}
+
+-- function commands.addtocommalist(list,item)
+-- if list == "" then
+-- context(item)
+-- else
+-- context("%s,%s",list,item) -- using tex.print is some 10% faster
+-- end
+-- end
+--
+-- function commands.removefromcommalist(list,item)
+-- if list == "" then
+-- context(item)
+-- else
+-- -- okay, using a proper lpeg is probably faster
+-- -- we could also check for #l = 1
+-- local l = settings_to_array(list)
+-- local t, n = { }
+-- for i=1,#l do
+-- if l[i] ~= item then
+-- n = n + 1
+-- t[n] = item
+-- end
+-- end
+-- if n == 0 then
+-- context(item)
+-- else
+-- context(concat(list,","))
+-- end
+-- end
+-- end
+
+local pattern = (C((1-P("%"))^1) * Carg(1)) / function(n,d)
+ return formatters["%.0fsp"](d * tonumber(n)/100) end * P("%") * P(-1) -- .0 ?
+
+-- percentageof("10%",65536*10)
+
+implement {
+ name = "percentageof",
+ arguments = { "string", "dimen" },
+ actions = function(str,dim)
+ context(lpegmatch(pattern,str,1,dim) or str)
+ end
+}
+
+-- \gdef\setpercentdimen#1#2%
+-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
+
+local spaces = P(" ")^0 / ""
+local nohash = 1 - P("#")
+local digit = R("09")
+local double = P("##") / "#"
+local single = P("#")
+local sentinel = spaces * (nohash^1 / "\\%0")
+local sargument = (single * digit)^1
+local dargument = (double * digit)^1
+
+local usespaces = nil
+local texpreamble = nil
+
+local pattern = Cs( -- ^-1
+ ( P("spaces") / function() usespaces = true return "" end )^0
+ * spaces
+ * ( P("nospaces") / function() usespaces = false return "" end )^0
+ * spaces
+ * ( P("global") / "\\global" )^0
+ * spaces
+ * ( P("unexpanded") / "\\unexpanded" )^0
+ * spaces
+ * Cc("\\expandafter\\")
+ * spaces
+ * ( P("expanded") / "e" )^0
+ * spaces
+ * ( P((1-S(" #"))^1) / "def\\csname %0\\endcsname" )
+ * spaces
+ * (
+ -- (double * digit)^1 * sentinel^-1 * double^-1
+ -- + (single * digit)^1 * sentinel^-1 * single^-1
+ ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1
+ + ( P("[") * sargument * P("]") + sargument)^1 * sentinel^-1 * single^-1
+ + sentinel^-1 * (double+single)^-1
+ )
+)
+
+local ctx_dostarttexdefinition = context.dostarttexdefinition
+
+local function texdefinition_one(str)
+ usespaces = nil
+ texpreamble = lpegmatch(pattern,str)
+ if usespaces == true then
+ setcatcode(32,10) -- space
+ setcatcode(13, 5) -- endofline
+ elseif usespaces == false then
+ setcatcode(32, 9) -- ignore
+ setcatcode(13, 9) -- ignore
+ else
+ -- this is default
+ -- setcatcode(32,10) -- space
+ -- setcatcode(13, 9) -- ignore
+ end
+ ctx_dostarttexdefinition()
+end
+
+local function texdefinition_two()
+ context(texpreamble)
+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
+
+implement {
+ name = "converteddimen",
+ arguments = { "dimen", "string" },
+ actions = function(dimen,unit)
+ context(number.todimen(dimen,unit or "pt","%0.5f")) -- no unit appended (%F)
+ end
+}
+
+-- where, not really the best spot for this:
+
+implement {
+ name = "immediatemessage",
+ arguments = { "'message'", "string" },
+ actions = logs.status
+}
+
+implement {
+ name = "resettimer",
+ actions = function()
+ statistics.resettiming("whatever")
+ statistics.starttiming("whatever")
+ end
+}
+
+implement {
+ name = "elapsedtime",
+ actions = function()
+ statistics.stoptiming("whatever")
+ context(statistics.elapsedtime("whatever"))
+ end
+}
+
+local accuracy = table.setmetatableindex(function(t,k)
+ local v = formatters["%0." ..k .. "f"]
+ t[k] = v
+ return v
+end)
+
+implement {
+ name = "rounded",
+ arguments = "integer",
+ actions = function(n,m) context(accuracy[n](m)) end
+}
+
+-- not faster but just less tracing:
+
+local firstoftwoarguments = context.firstoftwoarguments
+local secondoftwoarguments = context.secondoftwoarguments
+local firstofoneargument = context.firstofoneargument
+local gobbleoneargument = context.gobbleoneargument
+
+local hash = utilities.parsers.hashes.settings_to_set
+
+local function doifelsecommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ secondoftwoarguments()
+ else
+ firstoftwoarguments()
+ end
+ return
+ end
+ local ba = find(a,",")
+ local bb = find(b,",")
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ firstoftwoarguments()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ firstoftwoarguments()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ firstoftwoarguments()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ secondoftwoarguments()
+end
+
+local function doifcommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ gobbleoneargument()
+ else
+ firstofoneargument()
+ end
+ return
+ end
+ local ba = find(a,",")
+ local bb = find(b,",")
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ firstofoneargument()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ firstofoneargument()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ firstofoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ gobbleoneargument()
+end
+
+local function doifnotcommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ firstofoneargument()
+ else
+ gobbleoneargument()
+ end
+ return
+ end
+ local ba = find(a,",")
+ local bb = find(b,",")
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ gobbleoneargument()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ gobbleoneargument()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ gobbleoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ firstofoneargument()
+end
+
+local function doifelseinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ secondoftwoarguments()
+ else
+ firstoftwoarguments()
+ end
+ return
+ end
+ local bb = find(b,",")
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ firstoftwoarguments()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ secondoftwoarguments()
+end
+
+local function doifinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ gobbleoneargument()
+ else
+ firstofoneargument()
+ end
+ return
+ end
+ local bb = find(b,",")
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ firstofoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ gobbleoneargument()
+end
+
+local function doifnotinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ firstofoneargument()
+ else
+ gobbleoneargument()
+ end
+ return
+ end
+ local bb = find(b,",")
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ gobbleoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ firstofoneargument()
+end
+
+implement {
+ name = "doifelsecommon",
+ actions = doifelsecommon,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "doifcommon",
+ actions = doifcommon,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "doifnotcommon",
+ actions = doifnotcommon,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "doifelseinset",
+ actions = doifelseinset,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "doifinset",
+ actions = doifinset,
+ arguments = { "string", "string" },
+}
+
+implement {
+ name = "doifnotinset",
+ actions = doifnotinset,
+ arguments = { "string", "string" },
+}
+
+-- implement {
+-- name = "stringcompare",
+-- arguments = { "string", "string" },
+-- actions = function(a,b)
+-- context((a == b and 0) or (a > b and 1) or -1)
+-- end
+-- }
+--
+-- implement {
+-- name = "doifelsestringafter",
+-- arguments = { "string", "string" },
+-- actions = function(a,b)
+-- ctx_doifelse((a == b and 0) or (a > b and 1) or -1)
+-- end
+-- }
+--
+-- implement {
+-- name = "doifelsestringbefore",
+-- arguments = { "string", "string" },
+-- actions = function(a,b)
+-- ctx_doifelse((a == b and 0) or (a < b and -1) or 1)
+-- end
+-- }
+
+-- implement { -- not faster than addtocommalist
+-- name = "additemtolist", -- unique
+-- arguments = { "string", "string" },
+-- actions = function(l,s)
+-- if l == "" or s == l then
+-- -- s = s
+-- elseif find("," .. l .. ",","," .. s .. ",") then
+-- s = l
+-- else
+-- s = l .. "," .. s
+-- end
+-- context(s)
+-- end
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv
new file mode 100644
index 00000000000..825d1863641
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv
@@ -0,0 +1,7462 @@
+%D \module
+%D [ file=syst-aux, % merge of syst-gen cum suis
+%D version=1996.03.20,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=General,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D There are some references to \LUA\ variants here but these concern (often old)
+%D experiments, moved from local test modules to here, cleaned up, but not really
+%D used. After all it's not that urgent and replacing helpers is a delicate process.
+%D Don't depend on it.
+
+\registerctxluafile{syst-aux}{1.001}
+
+% A dedicated primitive \ifvoidmacro\cs == \ifx\cs\empty is some 10% faster but
+% probably not that noticeable in practice. An \ifvoidtoks might make sense but we
+% don't test that often for it (and it's more work to implement in the engine).
+
+%D This is a stripped down combination of:
+%D
+%D \startitemize
+%D \item \type {syst-gen.tex}
+%D \item \type {syst-ext.tex}
+%D \item \type {syst-new.tex}
+%D \stopitemize
+%D
+%D We keep them around (for \MKII) so you can find comments, experiences,
+%D intermediate versions and cleaner variants there (and also non-\ETEX\ variants).
+%D
+%D Contrary to the older files, we now assume that this one is used in \CONTEXT\ and
+%D therefore we might also assume that some basic functionality is available.
+%D
+%D The original files contain previous implementations and notes about performance.
+%D This file will be stripped down in due time.
+%D
+%D Some of the macros here were only used in the bibliography module. They have been
+%D be moved to a separate syst module since the bib module is no longer using them.
+%D Some more will go away.
+
+\unprotect
+
+%D \macros
+%D {unexpanded}
+%D
+%D Because we use this module only in \MKIV, we have removed the old protection
+%D code.
+%D
+%D \starttyping
+%D \unexpanded\def\somecommand{... ... ...}
+%D \stoptyping
+%D
+%D This overloads the \ETEX\ primitive but as we already had an \MKII\ solution we
+%D keep the same name for a similar mechanism.
+
+\let\unexpanded\normalprotected
+
+% %D \macros
+% %D {expunded}
+% %D
+% %D \unexpanded\edef\TestA{zzz}
+% %D \edef\TestB{zzz}
+% %D
+% %D \doifelse {\TestA} {\TestB} {WRONG} {OKAY} \par
+% %D \doifelse {\TestA} {\expunded\TestB} {WRONG} {OKAY} \par
+% %D \doifelse {\expunded\TestA} {\TestB} {OKAY} {WRONG} \par
+% %D \doifelse {\expunded\TestA} {\expunded\TestB} {OKAY} {WRONG} \par
+
+% %def\expunded#1{\normalexpanded\expandafter{#1}}
+% \def\expunded#1{\expandafter\empty#1} % used within an edef anyway
+
+%D As we don't have namespace definers yet, we use a special one:
+
+\ifdefined\c_syst_helpers_n_of_namespaces
+
+ % lets plug in a better error message
+
+\else
+
+ \newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
+
+ \def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
+ %def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
+
+\fi
+
+\unexpanded\def\installsystemnamespace#1% maybe move this to syst-ini
+ {\ifcsname ??#1\endcsname
+ \writestatus\m!system{duplicate system namespace '#1'}\wait
+ \else
+ \global\advance\c_syst_helpers_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \fi}
+
+%D \macros
+%D {normalspace}
+%D
+%D There is already \type{\space} but just to be sure we also provide:
+
+\def\normalspace{ }
+
+%D \macros
+%D {!!count, !!toks, !!dimen, !!box,
+%D !!width, !!height, !!depth, !!string, !!done}
+%D
+%D We define some more \COUNTERS\ and \DIMENSIONS. We also define some shortcuts to
+%D the local scatchregisters~0, 2, 4, 6 and~8.
+
+\newcount\!!counta \newtoks\!!toksa \newdimen\!!dimena \newbox\!!boxa
+\newcount\!!countb \newtoks\!!toksb \newdimen\!!dimenb \newbox\!!boxb
+\newcount\!!countc \newtoks\!!toksc \newdimen\!!dimenc \newbox\!!boxc
+\newcount\!!countd \newtoks\!!toksd \newdimen\!!dimend \newbox\!!boxd
+\newcount\!!counte \newtoks\!!tokse \newdimen\!!dimene \newbox\!!boxe
+\newcount\!!countf \newtoks\!!toksf \newdimen\!!dimenf \newbox\!!boxf
+ \newdimen\!!dimeng
+ \newdimen\!!dimenh
+ \newdimen\!!dimeni
+ \newdimen\!!dimenj
+ \newdimen\!!dimenk
+
+\let\!!stringa\empty \let\!!stringb\empty \let\!!stringc\empty
+\let\!!stringd\empty \let\!!stringe\empty \let\!!stringf\empty
+
+\newdimen\!!widtha \newdimen\!!heighta \newdimen\!!deptha
+\newdimen\!!widthb \newdimen\!!heightb \newdimen\!!depthb
+\newdimen\!!widthc \newdimen\!!heightc \newdimen\!!depthc
+\newdimen\!!widthd \newdimen\!!heightd \newdimen\!!depthd
+
+\newif\if!!donea \newif\if!!doneb \newif\if!!donec
+\newif\if!!doned \newif\if!!donee \newif\if!!donef
+
+\def\!!zerocount {0} % alongside \zerocount
+\def\!!minusone {-1} % ...
+\def\!!plusone {1} % ...
+\def\!!plustwo {2} % ...
+\def\!!plusthree {3} % ...
+\def\!!plusfour {4} % ...
+\def\!!plusfive {5} % ...
+\def\!!plussix {6} % ...
+\def\!!plusseven {7} % ...
+\def\!!pluseight {8} % ...
+\def\!!plusnine {9} % alongside \plusnine
+
+\setnewconstant \uprotationangle 0
+\setnewconstant\rightrotationangle 90
+\setnewconstant \downrotationangle 180
+\setnewconstant \leftrotationangle 270
+
+\ifdefined\data \else \let\data \relax \fi % dep checker
+
+%D \macros
+%D {s!,c!,e!,p!,v!,@@,??}
+%D
+%D To save memory, we use constants (sometimes called variables). Redefining these
+%D constants can have disastrous results.
+
+\def\v!prefix! {v!}
+\def\c!prefix! {c!}
+\def\s!prefix! {s!}
+
+\def\s!next {next}
+\def\s!default {default}
+\def\s!dummy {dummy}
+\def\s!unknown {unknown}
+
+\def\s!do {do}
+\def\s!dodo {dodo}
+
+\def\s!complex {complex}
+\def\s!start {start}
+\def\s!simple {simple}
+\def\s!stop {stop}
+
+\def\s!empty {empty}
+
+%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
+
+%D Sometimes we pass macros as arguments to commands that don't expand them
+%D before interpretation. Such commands can be enclosed with \type {\expanded},
+%D like:
+%D
+%D \starttyping
+%D \expanded{\setupsomething[\alfa]}
+%D \stoptyping
+%D
+%D Such situations occur for instance when \type{\alfa} is a commalist or when data
+%D stored in macros is fed to index of list commands. If needed, one should use
+%D \type{\noexpand} inside the argument. Later on we will meet some more clever
+%D alternatives to this command. Beware, only the simple one has \type {\noexpand}
+%D before its argument.
+
+\let\m_syst_helpers_expanded\empty
+
+\unexpanded\def\expanded#1%
+ {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded}
+
+\unexpanded\def\startexpanded#1\stopexpanded
+ {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded}
+
+\let\stopexpanded\relax
+
+%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when
+%D possible. After all, we can make not expandable macros now.
+
+% We cannot use the next variant as first we need to adapt \type {##}'s
+% in callers:
+%
+% \def\expanded#1%
+% {\normalexpanded{\noexpand#1}}
+%
+% \def\startexpanded#1\stopexpanded
+% {\normalexpanded{#1}}
+
+%D \macros
+%D {gobbleoneargument,gobble...arguments}
+%D
+%D The next set of macros just do nothing, except that they get rid of a number of
+%D arguments.
+
+\def\gobbleoneargument #1{}
+\def\gobbletwoarguments #1#2{}
+\def\gobblethreearguments#1#2#3{}
+\def\gobblefourarguments #1#2#3#4{}
+\def\gobblefivearguments #1#2#3#4#5{}
+\def\gobblesixarguments #1#2#3#4#5#6{}
+\def\gobblesevenarguments#1#2#3#4#5#6#7{}
+\def\gobbleeightarguments#1#2#3#4#5#6#7#8{}
+\def\gobbleninearguments #1#2#3#4#5#6#7#8#9{}
+\def\gobbletenarguments #1{\gobbleninearguments}
+
+\def\gobbleoneoptional [#1]{}
+\def\gobbletwooptionals [#1][#2]{}
+\def\gobblethreeoptionals[#1][#2][#3]{}
+\def\gobblefouroptionals [#1][#2][#3][#4]{}
+\def\gobblefiveoptionals [#1][#2][#3][#4][#5]{}
+
+%D Reserved macros for tests:
+
+\let\donothing\empty
+
+\let\m_syst_string_one \empty
+\let\m_syst_string_two \empty
+\let\m_syst_string_three\empty
+\let\m_syst_string_four \empty
+
+\let\m_syst_action_yes \empty
+\let\m_syst_action_nop \empty
+
+%D \macros
+%D {doifnextcharelse}
+%D
+%D When we started using \TEX\ in the late eighties, our first experiences with
+%D programming concerned a simple shell around \LATEX. The commands probably use
+%D most at \PRAGMA, are the itemizing ones. One of those few shell commands took
+%D care of an optional argument, that enabled us to specify what kind of item symbol
+%D we wanted. Without understanding anything we were able to locate a \LATEX\ macro
+%D that could be used to inspect the next character.
+%D
+%D It's this macro that the ancester of the next one presented here. It executes one
+%D of two actions, dependant of the next character. Disturbing spaces and line
+%D endings, which are normally interpreted as spaces too, are skipped.
+%D
+%D \starttyping
+%D \doifnextcharelse {karakter} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This macro differs from the original in the use of \type
+%D {\localnext} because we don't want clashes with \type
+%D {\next}.
+
+\unexpanded\def\doifelsenextchar#1#2#3% #1 should not be {} !
+ {\let\charactertoken=#1% = needed here
+ \def\m_syst_action_yes{#2}%
+ \def\m_syst_action_nop{#3}%
+ \futurelet\nexttoken\syst_helpers_inspect_next_character}
+
+\let\doifnextcharelse\doifelsenextchar
+
+\def\syst_helpers_inspect_next_character
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_reinspect_next_character
+ \else
+ \expandafter\syst_helpers_inspect_next_character_indeed
+ \fi}
+
+\def\syst_helpers_inspect_next_character_indeed
+ {\ifx\nexttoken\charactertoken
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+%D Because we will mostly use this macro for testing if the next character is \type
+%D {[}, we also make a slightly faster variant as it is not uncommon to have tens of
+%D thousands of calls to this test in a run. Of course it also is more convenient to
+%D read a trace then.
+
+% We could make variants without the \if_next_blank_space_token but the overhead is
+% only .1 sec on 3.5 for 10^6 tests and often that branch is not entered anyway. The
+% fast variants with less checking do make a difference however:
+
+% \testfeature{1000000}{\doifnextoptionalelse \gobbleoneargument\gobbleoneargument[} % 2.902s
+% \testfeature{1000000}{\doifnextoptionalcselse \gobbleoneargument\gobbleoneargument[} % 2.590s
+% \testfeature{1000000}{\doiffastoptionalcheckelse \gobbleoneargument\gobbleoneargument[} % 2.387s
+% \testfeature{1000000}{\doiffastoptionalcheckcselse\gobbleoneargument\gobbleoneargument[} % 2.168s
+
+\newif\if_next_blank_space_token
+
+\let\syst_helpers_next_optional_character_token=[
+
+\unexpanded\def\doifelsenextoptional#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\unexpanded\def\doifelsenextoptionalcs#1#2% \cs \cs (upto 10% faster)
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\let\doifnextoptionalelse \doifelsenextoptional
+\let\doifnextoptionalcselse\doifelsenextoptionalcs
+
+\def\syst_helpers_inspect_next_optional_character
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_reinspect_next_optional_character
+ \else
+ \expandafter\syst_helpers_inspect_next_optional_character_indeed
+ \fi}
+
+\def\syst_helpers_inspect_next_optional_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_optional_character_token
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+\let\syst_helpers_next_bgroup_character_token\bgroup
+
+\unexpanded\def\doifelsenextbgroup#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+
+\unexpanded\def\doifelsenextbgroupcs#1#2%
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+
+\let\doifnextbgroupelse \doifelsenextbgroup
+\let\doifnextbgroupcselse\doifelsenextbgroupcs
+
+\def\syst_helpers_inspect_next_bgroup_character
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_reinspect_next_bgroup_character
+ \else
+ \expandafter\syst_helpers_inspect_next_bgroup_character_indeed
+ \fi}
+
+\def\syst_helpers_inspect_next_bgroup_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_bgroup_character_token
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+\let\syst_helpers_next_parenthesis_character_token(
+
+\unexpanded\def\doifelsenextparenthesis#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
+
+\let\doifnextparenthesiselse\doifelsenextparenthesis
+
+\def\syst_helpers_inspect_next_parenthesis_character
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_reinspect_next_parenthesis_character
+ \else
+ \expandafter\syst_helpers_inspect_next_parenthesis_character_indeed
+ \fi}
+
+\def\syst_helpers_inspect_next_parenthesis_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_parenthesis_character_token
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+%D The next one is handy in predictable situations:
+
+\unexpanded\def\doifelsefastoptionalcheck#1#2%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
+
+\unexpanded\def\doifelsefastoptionalcheckcs#1#2% \cs \cs
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
+
+\let\doiffastoptionalcheckelse \doifelsefastoptionalcheck
+\let\doiffastoptionalcheckcselse\doifelsefastoptionalcheckcs
+
+\def\syst_helpers_do_if_fast_optional_check_else
+ {\ifx\nexttoken\syst_helpers_next_optional_character_token
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+%D Here's one for skipping spaces and pars, handy for:
+%D
+%D \starttyping
+%D \hbox
+%D
+%D {a few lines later}
+%D \stoptyping
+
+% \unexpanded\def\assumelongusagecs#1%
+% {\let\m_syst_action#1%
+% \futurelet\nexttoken\syst_helpers_ignore_par_character}
+%
+% \def\syst_helpers_ignore_par_character
+% {\ifx\nexttoken\blankspace
+% \expandafter\syst_helpers_ignore_par_character_blankspace
+% \else
+% \expandafter\syst_helpers_ignore_par_character_followup
+% \fi}
+%
+% \def\syst_helpers_ignore_par_character_followup
+% {\ifx\nexttoken\par
+% \expandafter\syst_helpers_ignore_par_partoken
+% \else
+% \expandafter\m_syst_action
+% \fi}
+%
+% \def\syst_helpers_ignore_par_partoken
+% {\afterassignment\m_syst_action\let\nexttoken}
+
+\unexpanded\def\assumelongusagecs#1% can be relaxed when we have long support in \hbox etc
+ {\let\m_syst_action#1%
+ \futurelet\nexttoken\syst_helpers_ignore_spacing}
+
+\def\syst_helpers_ignore_spacing
+ {\ifx\nexttoken\blankspace
+ \singleexpandafter\syst_helpers_ignore_spacing_blankspace
+ \else\ifx\nexttoken\par
+ \doubleexpandafter\syst_helpers_ignore_spacing_partoken
+ \else
+ \doubleexpandafter\m_syst_action
+ \fi\fi}
+
+\def\syst_helpers_ignore_spacing_partoken\par
+ {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
+%D These macros use some auxiliary macros. Although we were able to program quite
+%D complicated things, I only understood these after rereading the \TEX book. The
+%D trick is in using a command with a one character name. Such commands differ from
+%D the longer ones in the fact that trailing spaces are {\em not} skipped. This
+%D enables us to indirectly define a long named macro that gobbles a space. In the
+%D first line we define \type {\blankspace}. Next we make \type {\:} equivalent to
+%D \type {\reinspect...}. This one||character command is expanded before the next
+%D \type {\def} comes into action. This way the space after \type {\:} becomes a
+%D delimiter of the longer named \type {\reinspectnextcharacter}.
+
+% try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...}
+
+\let\next\:
+
+\def\:{\let\blankspace= } \:
+
+\def\:{\syst_helpers_reinspect_next_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_character}
+
+\def\:{\syst_helpers_reinspect_next_optional_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\:{\syst_helpers_reinspect_next_bgroup_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+
+\def\:{\syst_helpers_reinspect_next_parenthesis_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
+
+\def\:{\syst_helpers_ignore_spacing_blankspace}
+\expandafter\def\: {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
+\let\:\next
+
+%D \macros
+%D {setvalue,setgvalue,setevalue,setxvalue,
+%D letvalue,letgvalue,getvalue,resetvalue,
+%D undefinevalue,ignorevalue}
+%D
+%D \TEX's primitive \type {\csname} can be used to construct all kind of commands
+%D that cannot be defined with \type {\def} and \type {\let}. Every macro programmer
+%D sooner or later wants macros like these.
+%D
+%D \starttyping
+%D \setvalue {name}{...} = \def\name{...}
+%D \setgvalue {name}{...} = \gdef\name{...}
+%D \setevalue {name}{...} = \edef\name{...}
+%D \setxvalue {name}{...} = \xdef\name{...}
+%D \letvalue {name}=\... = \let\name=\...
+%D \letgvalue {name}=\... = \global\let\name=\...
+%D \getvalue {name} = \name
+%D \resetvalue {name} = \def\name{}
+%D \stoptyping
+%D
+%D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to
+%D its object oriented and parameter driven character.
+
+\def\setvalue #1{\expandafter \def\csname#1\endcsname}
+\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
+\def\setevalue #1{\expandafter\edef\csname#1\endcsname}
+\def\setxvalue #1{\expandafter\xdef\csname#1\endcsname}
+\def\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\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname}
+\def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname}
+\def\setugvalue #1{\normalprotected\expandafter\gdef\csname#1\endcsname}
+\def\setuxvalue #1{\normalprotected\expandafter\xdef\csname#1\endcsname}
+
+\unexpanded\def\getuvalue#1{\csname#1\endcsname}
+
+%D \macros
+%D {globallet,glet}
+%D
+%D In \CONTEXT\ of May 2000 using \type {\globallet} instead of the two
+%D tokens will save us some $300\times4=1200$ bytes of format file on a 32~bit
+%D system. Not that it matters much today. This shortcut is already defined:
+
+\unexpanded\def\glet{\global\let} \let\globallet\glet
+
+%D \macros
+%D {doifundefined,doifdefined,
+%D doifundefinedelse,doifdefinedelse,
+%D doifalldefinedelse}
+%D
+%D The standard way of testing if a macro is defined is comparing its meaning with
+%D another undefined one, usually \type{\undefined}. To garantee correct working of
+%D the next set of macros, \type{\undefined} may never be defined!
+%D
+%D \starttyping
+%D \doifundefined {string} {...}
+%D \doifdefined {string} {...}
+%D \doifundefinedelse {string} {then ...} {else ...}
+%D \doifdefinedelse {string} {then ...} {else ...}
+%D \doifalldefinedelse {commalist} {then ...} {else ...}
+%D \stoptyping
+%D
+%D Every macroname that \TEX\ builds gets an entry in the hash table, which is of
+%D limited size. It is expected that \ETEX\ will offer a less memory||consuming
+%D alternative.
+
+%D Although it will probably never be a big problem, it is good to be aware of the
+%D difference between testing on a macro name to be build by using \type{\csname} and
+%D \type{\endcsname} and testing the \type{\name} directly.
+%D
+%D \starttyping
+%D \expandafter\ifx\csname NameA\endcsname\relax ... \else ... \fi
+%D
+%D \ifundefined\NameB ... \else ... \fi
+%D \stoptyping
+
+% \suppressifcsnameerror\plusone % already set
+
+\def\doifelseundefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifelsedefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifundefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\gobbleoneargument\else\expandafter\firstofoneargument
+ \fi}
+
+\def\doifdefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstofoneargument\else\expandafter\gobbleoneargument
+ \fi}
+
+\let\doifundefinedelse\doifelseundefined
+\let\doifdefinedelse \doifelsedefined
+
+%D \macros
+%D {letbeundefined}
+%D
+%D Testing for being undefined comes down to testing on \type {\relax} when we use
+%D \type {\csname}, but when using \type {\ifx}, we test on being \type
+%D {\undefined}! In \ETEX\ we have \type {\ifcsname} and that way of testing on
+%D existance is not the same as the one described here. Therefore we introduce:
+
+\def\letbeundefined#1% potential stack buildup when used \global
+ {\expandafter\let\csname#1\endcsname\undefined} % or use \undefinevalue to match \setvalue
+
+\def\localundefine#1% conditional
+ {\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}
+
+%D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined!
+%D
+%D When we were developing the scientific units module, we encountered different
+%D behavior in text and math mode, which was due to this grouping subtilities. We
+%D therefore decided to use \type{\begingroup} instead of \type{\bgroup}.
+
+\unexpanded\def\doifelsealldefined#1%
+ {\begingroup
+ \donetrue % we could use a reserved one and avoid the group
+ \processcommalist[#1]\syst_helpers_do_if_all_defined_else
+ \ifdone
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifalldefinedelse\doifelsealldefined
+
+\def\syst_helpers_do_if_all_defined_else#1%
+ {\ifcsname#1\endcsname\else
+ \donefalse
+ \expandafter\quitcommalist % added
+ \fi}
+
+%D \macros
+%D {doif,doifelse,doifnot}
+%D
+%D Programming in \TEX\ differs from programming in procedural languages like
+%D \MODULA. This means that one --- well, let me speek for myself --- tries to do
+%D the things in the well known way. Therefore the next set of \type{\ifthenelse}
+%D commands were between the first ones we needed. A few years later, the opposite
+%D became true: when programming in \MODULA, I sometimes miss handy things like
+%D grouping, runtime redefinition, expansion etc. While \MODULA\ taught me to
+%D structure, \TEX\ taught me to think recursive.
+%D
+%D \starttyping
+%D \doif {string1} {string2} {...}
+%D \doifnot {string1} {string2} {...}
+%D \doifelse {string1} {string2} {then ...}{else ...}
+%D \stoptyping
+
+\unexpanded\def\doif#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnot#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelse#1#2%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+%D \macros
+%D {doifempty,doifemptyelse,doifnotempty}
+%D
+%D We complete our set of conditionals with:
+%D
+%D \starttyping
+%D \doifempty {string} {...}
+%D \doifnotempty {string} {...}
+%D \doifemptyelse {string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This time, the string is not expanded.
+
+\unexpanded\def\doifelseempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifemptyelse\doifelseempty
+
+\unexpanded\def\doifempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotempty#1%
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {doifinset,doifnotinset,doifinsetelse}
+%D
+%D We can check if a string is present in a comma separated set of strings.
+%D Depending on the result, some action is taken.
+%D
+%D \starttyping
+%D \doifinset {string} {string,...} {...}
+%D \doifnotinset {string} {string,...} {...}
+%D \doifinsetelse {string} {string,...} {then ...} {else ...}
+%D \stoptyping
+
+% !0nop=\doifinsetelse{ccc}{,}{yes}{nop}
+% !0nop=\doifinsetelse{ccc}{,,}{yes}{nop}
+% !0nop=\doifinsetelse{ccc}{,,,}{yes}{nop}
+
+% !1nop=\doifinsetelse{}{}{yes}{nop}
+% !2yes=\doifinsetelse{aaa}{bbb,ccc,ddd,aaa,eee}{yes}{nop}
+% !3nop=\doifinsetelse{aaa}{bbb}{yes}{nop}
+% !4yes=\doifinsetelse{aaa}{aaa}{yes}{nop}
+% !5nop=\doifinsetelse{aaaa}{bbb,ccc,ddd,aaa,eee}{yes}{nop}
+% !6nop=\doifinsetelse{}{}{yes}{nop}
+% !7nop=\doifinsetelse{}{aaa}{yes}{nop}
+% !8nop=\doifinsetelse{aaa}{}{yes}{nop}
+
+% !1=\doifinset{}{}{yes}
+% !2yes=\doifinset{aaa}{bbb,ccc,ddd,aaa,eee}{yes}
+% !3=\doifinset{aaa}{bbb}{yes}
+% !4yes=\doifinset{aaa}{aaa}{yes}
+% !5=\doifinset{}{}{yes}
+% !6=\doifinset{aaa}{}{yes}
+
+% !1yes=\doifnotinset{}{}{yes}
+% !2=\doifnotinset{aaa}{bbb,ccc,ddd,aaa,eee}{yes}
+% !3yes=\doifnotinset{aaa}{bbb}{yes}
+% !4=\doifnotinset{aaa}{aaa}{yes}
+% !5yes=\doifnotinset{}{}{yes}
+% !6yes=\doifnotinset{aaa}{}{yes}
+
+% \def\v_syst_helpers_right_optional_bracket{]}
+%
+% \def\syst_helpers_do_quit_if_item_in_set_else#1],\relax{\firstoftwoarguments}
+% \def\syst_helpers_do_quit_if_item_in_set #1],\relax{\firstofoneargument}
+% \def\syst_helpers_do_quit_if_item_not_in_set #1],\relax{\gobbleoneargument}
+%
+% \def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\m_syst_string_two,],\relax}
+% \def\syst_helpers_re_do_if_in_set {\expandafter\syst_helpers_do_check_if_item_in_set \m_syst_string_two,],\relax}
+% \def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \m_syst_string_two,],\relax}
+%
+% \unexpanded\def\doifelseinset#1% make this two step too
+% {\edef\m_syst_string_one{#1}%
+% \ifx\m_syst_string_one\empty
+% \expandafter\thirdofthreearguments
+% \else
+% \expandafter\syst_helpers_do_if_in_set_else
+% \fi}
+%
+% \let\doifinsetelse\doifelseinset
+%
+% \def\syst_helpers_do_if_in_set_else#1%
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\secondoftwoarguments
+% \else
+% \expandafter\syst_helpers_re_do_if_in_set_else
+% \fi}
+%
+% \unexpanded\def\doifinset#1%
+% {\edef\m_syst_string_one{#1}%
+% \ifx\m_syst_string_one\empty
+% \expandafter\gobbletwoarguments
+% \else
+% \expandafter\syst_helpers_do_if_in_set
+% \fi}
+%
+% \def\syst_helpers_do_if_in_set#1%
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\gobbleoneargument
+% \else
+% \expandafter\syst_helpers_re_do_if_in_set
+% \fi}
+%
+% \unexpanded\def\doifnotinset#1%
+% {\edef\m_syst_string_one{#1}%
+% \ifx\m_syst_string_one\empty
+% \expandafter\secondoftwoarguments
+% \else
+% \expandafter\syst_helpers_do_if_not_in_set
+% \fi}
+%
+% \def\syst_helpers_do_if_not_in_set#1%
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\syst_helpers_re_do_if_not_in_set % ...]{true}
+% \fi}
+%
+% \def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\syst_helpers_do_check_if_item_in_set_else
+% \else
+% \expandafter\syst_helpers_do_do_check_if_item_in_set_else
+% \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_in_set_else
+% {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+% \expandafter\thirdofthreearguments
+% \else
+% \expandafter\syst_helpers_do_do_do_check_if_item_in_set_else
+% \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_in_set_else
+% {\ifx\m_syst_string_one\m_syst_string_two
+% \expandafter\syst_helpers_do_quit_if_item_in_set_else
+% \else
+% \expandafter\syst_helpers_do_check_if_item_in_set_else
+% \fi}
+%
+% \def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\syst_helpers_do_check_if_item_in_set
+% \else
+% \expandafter\syst_helpers_do_do_check_if_item_in_set
+% \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_in_set
+% {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+% \expandafter\gobbletwoarguments
+% \else
+% \expandafter\syst_helpers_do_do_do_check_if_item_in_set
+% \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_in_set
+% {\ifx\m_syst_string_one\m_syst_string_two
+% \expandafter\syst_helpers_do_quit_if_item_in_set
+% \else
+% \expandafter\syst_helpers_do_check_if_item_in_set
+% \fi}
+%
+% \def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space
+% {\edef\m_syst_string_two{#1}%
+% \ifx\m_syst_string_two\empty
+% \expandafter\syst_helpers_do_check_if_item_not_in_set
+% \else
+% \expandafter\syst_helpers_do_do_check_if_item_not_in_set
+% \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_not_in_set
+% {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+% \expandafter\secondoftwoarguments
+% \else
+% \expandafter\syst_helpers_do_do_do_check_if_item_not_in_set
+% \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_not_in_set
+% {\ifx\m_syst_string_one\m_syst_string_two
+% \expandafter\syst_helpers_do_quit_if_item_not_in_set
+% \else
+% \expandafter\syst_helpers_do_check_if_item_not_in_set
+% \fi}
+
+\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\doifinsetelse\doifelseinset
+
+%D \macros
+%D {doifcommon,doifnotcommon,doifcommonelse}
+%D
+%D Probably the most time consuming tests are those that test for overlap in sets
+%D of strings.
+%D
+%D \starttyping
+%D \doifcommon {string,...} {string,...} {...}
+%D \doifnotcommon {string,...} {string,...} {...}
+%D \doifcommonelse {string,...} {string,...} {then ...} {else ...}
+%D \stoptyping
+
+% !1yes=\doifcommonelse{aaa,bbb,ccc}{aaa,bbb,ccc}{yes}{nop}
+% !2nop=\doifcommonelse{aaa,bbb,ccc}{ddd,eee,fff}{yes}{nop}
+% !3nop=\doifcommonelse{aaa}{ddd,eee,fff}{yes}{nop}
+% !4yes=\doifcommonelse{aaa}{aaa}{yes}{nop}
+% !5nop=\doifcommonelse{bbb}{aaa}{yes}{nop}
+% !6nop=\doifcommonelse{}{aaa,bbb,ccc}{yes}{nop}
+% !7nop=\doifcommonelse{aaa,bbb,ccc}{}{yes}{nop}
+% !8nop=\doifcommonelse{}{}{yes}{nop}
+
+% !9nop=\doifcommonelse{,,}{,,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,,a,}{,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,a,}{,,,a,}{yes}{nop}
+% !9yes=\doifcommonelse{,,a,}{,,,a,}{yes}{nop}
+
+% \let\m_syst_common_a\empty
+% \let\m_syst_common_b\empty
+% \let\m_syst_common_c\empty
+%
+% \def\syst_helpers_do_quit_if_common_else#1],\relax#2],\relax{\firstoftwoarguments}
+%
+% \def\syst_helpers_do_check_if_common_else_one#1,#2% hm, why #2 here and passed at end
+% {\edef\m_syst_common_c{#1}%
+% \ifx\m_syst_common_c\v_syst_helpers_right_optional_bracket
+% \expandafter\thirdofthreearguments
+% \else
+% \expandafter\syst_helpers_do_common_check
+% \fi#2}
+%
+% \def\syst_helpers_do_check_if_common_else_two#1,#2% we can do an empty #1 check too
+% {\edef\commalistelement{#1}%
+% \ifx\commalistelement\v_syst_helpers_right_optional_bracket
+% \expandafter\syst_helpers_re_do_check_if_common_else_one
+% \else
+% \expandafter\syst_helpers_do_do_check_if_common_else_two
+% \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_common_else_two
+% {\ifx\commalistelement\empty
+% \expandafter\syst_helpers_do_check_if_common_else_two
+% \else
+% \expandafter\syst_helpers_do_do_do_check_if_common_else_two
+% \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_common_else_two
+% {\ifx\m_syst_common_c\commalistelement
+% \expandafter\syst_helpers_do_quit_if_common_else
+% \else
+% \expandafter\syst_helpers_do_check_if_common_else_two
+% \fi}
+%
+% \def\syst_helpers_re_do_check_if_common_else_one#1{\syst_helpers_do_check_if_common_else_one}
+%
+% \def\syst_helpers_do_common_check
+% {\expandafter\syst_helpers_do_check_if_common_else_two\m_syst_common_b,],\relax}%
+%
+% \def\syst_helpers_do_do_do_if_common_else
+% {\expandafter\syst_helpers_do_check_if_common_else_one\m_syst_common_a,],\relax}
+%
+% \def\syst_helpers_do_do_if_common_else#1#2#3#4%
+% {\edef\m_syst_common_a{#3}%
+% \edef\m_syst_common_b{#4}%
+% \ifx\m_syst_common_a\empty
+% \expandafter\secondoftwoarguments
+% \else\ifx\m_syst_common_b\empty
+% \expandafter\expandafter\expandafter\secondoftwoarguments
+% \else
+% \expandafter\expandafter\expandafter\syst_helpers_do_do_do_if_common_else
+% \fi\fi
+% #1#2}
+
+% \unexpanded\def\doifelsecommon{\syst_helpers_do_do_if_common_else\firstoftwoarguments\secondoftwoarguments}
+% \unexpanded\def\doifcommon {\syst_helpers_do_do_if_common_else\firstofoneargument \gobbleoneargument }
+% \unexpanded\def\doifnotcommon {\syst_helpers_do_do_if_common_else\gobbleoneargument \firstofoneargument }
+%
+% \let\doifcommonelse\doifelsecommon
+
+\unexpanded\def\doifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
+\unexpanded\def\doifcommon #1#2{\clf_doifcommon {#1}{#2}}
+\unexpanded\def\doifnotcommon #1#2{\clf_doifnotcommon {#1}{#2}}
+
+\let\doifcommonelse\doifelsecommon
+
+%D \macros
+%D {processcommalist,processcommacommand,quitcommalist,
+%D processcommalistwithparameters}
+%D
+%D We've already seen some macros that take care of comma separated lists. Such
+%D list can be processed with
+%D
+%D \starttyping
+%D \processcommalist[string,string,...]\commando
+%D \stoptyping
+%D
+%D The user supplied command \type{\commando} receives one argument: the string.
+%D This command permits nesting and spaces after commas are skipped. Empty sets
+%D are no problem.
+%D
+%D \startbuffer
+%D \def\dosomething#1{(#1)}
+%D
+%D 1: \processcommalist [\hbox{$a,b,c,d,e,f$}] \dosomething \par
+%D 2: \processcommalist [{a,b,c,d,e,f}] \dosomething \par
+%D 3: \processcommalist [{a,b,c},d,e,f] \dosomething \par
+%D 4: \processcommalist [a,b,{c,d,e},f] \dosomething \par
+%D 5: \processcommalist [a{b,c},d,e,f] \dosomething \par
+%D 6: \processcommalist [{a,b}c,d,e,f] \dosomething \par
+%D 7: \processcommalist [] \dosomething \par
+%D 8: \processcommalist [{[}] \dosomething \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Before we show the result, we present the macro's:
+
+\newcount\commalevel
+
+\installsystemnamespace{nextcommalevel}
+
+\def\syst_helpers_do_do_do_process_comma_item
+ {\csname\??nextcommalevel\the\commalevel\endcsname}
+
+\def\syst_helpers_do_do_process_comma_item
+ {\ifx\nexttoken\blankspace
+ \expandafter\syst_helpers_re_do_process_comma_item
+ \else
+ \expandafter\syst_helpers_do_do_process_comma_item_indeed
+ \fi}
+
+\def\syst_helpers_do_do_process_comma_item_indeed
+ {\ifx\nexttoken]%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\syst_helpers_do_do_do_process_comma_item
+ \fi}
+
+\def\syst_helpers_do_process_comma_item
+ {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
+
+%D Empty arguments are not processed. Empty items (\type {,,}) however are
+%D treated. We have to check for the special case \type {[{a,b,c}]}.
+
+\unexpanded\def\processcommalist[%
+ {\futurelet\nexttoken\syst_helpers_do_check_comma_item}
+
+\def\syst_helpers_do_check_comma_item
+ {\ifx\nexttoken]%
+ \expandafter\gobblethreearguments
+ \else
+ \expandafter\syst_helpers_do_process_comma_list
+ \fi
+ \relax} % this one preserved the next {}
+
+\def\syst_helpers_do_process_comma_list#1]#2%
+ {\global\advance\commalevel \plusone
+ \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,%
+ {#2{##1}\syst_helpers_do_process_comma_item}%
+ \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument#1,]\relax
+ \global\advance\commalevel \minusone }
+
+%D One way of quitting a commalist halfway is:
+
+\unexpanded\def\quitcommalist
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
+
+\def\syst_helpers_do_quit_comma_list#1]%
+ {\endgroup}
+
+\unexpanded\def\quitprevcommalist
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_prev_comma_list}
+
+\def\syst_helpers_do_quit_prev_comma_list#1]%
+ {\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
+
+%D The hack we used for checking the next character \type {\doifnextcharelse}
+%D is also used here.
+
+\let\next\:
+
+\def\:{\syst_helpers_re_do_process_comma_item} % \:not saved ?
+
+\expandafter\def\: {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
+
+\let\:\next
+
+%D The previous examples lead to:
+%D
+%D \getbuffer
+
+%D When a list is saved in a macro, we can use a construction like:
+%D
+%D \starttyping
+%D \expandafter\processcommalist\expandafter[\list]\command
+%D \stoptyping
+%D
+%D Such solutions suit most situations, but we wanted a bit more.
+%D
+%D \starttyping
+%D \processcommacommand[string,\stringset,string]\commando
+%D \stoptyping
+%D
+%D where \type{\stringset} is a predefined set, like:
+%D
+%D \starttyping
+%D \def\first{aap,noot,mies}
+%D \def\second{laatste}
+%D
+%D \processcommacommand[\first]\message
+%D \processcommacommand[\first,second,third]\message
+%D \processcommacommand[\first,between,\second]\message
+%D \stoptyping
+%D
+%D Commands that are part of the list are expanded, so the use of
+%D this macro has its limits.
+
+\unexpanded\def\processcommacommand[#1]%
+ {\normalexpanded{\processcommalist[#1]}}
+
+%D The argument to \type{\command} is not delimited. Because we often
+%D use \type{[]} as delimiters, we also have:
+%D
+%D \starttyping
+%D \processcommalistwithparameters[string,string,...]\command
+%D \stoptyping
+%D
+%D where \type{\command} looks like:
+%D
+%D \starttyping
+%D \def\command[#1]{... #1 ...}
+%D \stoptyping
+
+\unexpanded\def\processcommalistwithparameters[#1]#2%
+ {\def\syst_helpers_do_process_comma_list_with_parameters##1{#2[##1]}%
+ \processcommalist[#1]\syst_helpers_do_process_comma_list_with_parameters}
+
+%D \macros
+%D {startprocesscommalist,startprocesscommacommand}
+%D
+%D Two more:
+
+\let\syst_helpers_comma_list_step\relax
+
+\unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \processcommalist[#1]\syst_helpers_comma_list_step}
+
+\unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step}
+
+\let\stopprocesscommalist \relax
+\let\stopprocesscommacommand\relax
+
+%D \macros
+%D {processaction,
+%D processfirstactioninset,
+%D processallactionsinset}
+%D
+%D \CONTEXT\ makes extensive use of a sort of case or switch
+%D command. Depending of the presence of one or more provided
+%D items, some actions is taken. These macros can be nested
+%D without problems.
+%D
+%D \starttyping
+%D \processaction [x] [a=>\a,b=>\b,c=>\c]
+%D \processfirstactioninset [x,y,z] [a=>\a,b=>\b,c=>\c]
+%D \processallactionsinset [x,y,z] [a=>\a,b=>\b,c=>\c]
+%D \stoptyping
+%D
+%D We can supply both a \type{default} action and an action
+%D to be undertaken when an \type{unknown} value is met:
+%D
+%D \starttyping
+%D \processallactionsinset
+%D [x,y,z]
+%D [ a=>\a,
+%D b=>\b,
+%D c=>\c,
+%D default=>\default,
+%D unknown=>\unknown{... \commalistelement ...}]
+%D \stoptyping
+%D
+%D When \type{#1} is empty, this macro scans list \type{#2} for
+%D the keyword \type{default} and executed the related action
+%D if present. When \type{#1} is non empty and not in the list,
+%D the action related to \type{unknown} is executed. Both
+%D keywords must be at the end of list \type{#2}. Afterwards,
+%D the actually found keyword is available in
+%D \type{\commalistelement}. An advanced example of the use of
+%D this macro can be found in \PPCHTEX, where we completely
+%D rely on \TEX\ for interpreting user supplied keywords like
+%D \type{SB}, \type{SB1..6}, \type{SB125} etc.
+
+\newcount\processlevel
+
+% obsolete: \def\expandactions{\let\expandedaction\edef} \expandactions (see mkii)
+
+\unexpanded\def\syst_helpers_do_compare_process_action_a[#1=>#2][#3]%
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\s!default
+ \let\commalistelement\empty
+ #2%
+ \fi}
+
+% met \quitcommalist tot meer dan 25\% sneller
+
+\unexpanded\def\syst_helpers_do_compare_process_action_b[#1=>#2][#3]%
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitcommalist
+ \else\ifx\m_syst_string_two\s!unknown
+ \def\commalistelement{#3}% beware of loops
+ #2%
+ \fi\fi}
+
+\unexpanded\def\processaction[#1]#2[%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_a
+ \else
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b
+ \fi
+ \edef\syst_helpers_do_process_action##1{\syst_helpers_do_compare_process_action[##1][#1]}% expands #1
+ \processnextcommalist\relax\relax\syst_helpers_do_process_action[}
+
+\unexpanded\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitprevcommalist
+ \else
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
+ \def\commalistelement{#3}%
+ #2%
+ \fi
+ \fi}
+
+\unexpanded\def\processfirstactioninset[#1]%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\processaction
+ \else
+ \expandafter\syst_helpers_process_first_action_in_set_indeed
+ \fi
+ [#1]}
+
+\unexpanded\def\syst_helpers_process_first_action_in_set_indeed[#1]#2[#3]%
+ {\def\syst_helpers_do_process_action##1%
+ {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}%
+ \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action}
+
+\unexpanded\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \def\commalistelement{#3}%
+ #2%
+ \expandafter\quitcommalist
+ \else
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
+ \def\commalistelement{#3}%
+ #2%
+ \fi
+ \fi}
+
+\installsystemnamespace{nextactionlevel}
+
+\unexpanded\def\syst_helpers_do_process_all_actions_in_set
+ {\csname\??nextactionlevel\the\processlevel\endcsname}
+
+\unexpanded\def\processallactionsinset[#1]%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\processaction
+ \else
+ \expandafter\syst_helpers_process_all_actions_in_set_indeed
+ \fi
+ [#1]}
+
+\unexpanded\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]%
+ {\advance\processlevel \plusone
+ \expandafter\def\csname\??nextactionlevel\the\processlevel\endcsname##1%
+ {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_d[####1][##1]}%
+ \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_all_actions_in_set
+ \advance\processlevel\minusone}
+
+%D These macros use:
+
+\unexpanded\def\processnextcommalist#1#2#3[#4#5]%
+ {#1%
+ \let\nexttoken#4%
+ \global\advance\commalevel \plusone
+ \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,%
+ {#3{##1}\syst_helpers_do_process_comma_item}%
+ \syst_helpers_do_do_process_comma_item#4#5,]\relax
+ \global\advance\commalevel\minusone
+ #2}
+
+%D \macros
+%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter}
+%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
+%D \starttyping
+%D \getfirstcharacter {string}
+%D \stoptyping
+%D
+%D A two step expansion is used to prevent problems with
+%D complicated arguments, for instance arguments that
+%D consist of two or more expandable tokens.
+
+\let\firstcharacter \empty
+\let\remainingcharacters\empty
+
+\unexpanded\def\getfirstcharacter #1{\clf_getfirstcharacter{#1}}
+\unexpanded\def\doifelsefirstchar #1#2{\clf_doifelsefirstchar{#1}{#2}}
+\unexpanded\def\thefirstcharacter #1{\clf_thefirstcharacter{#1}}
+\unexpanded\def\theremainingcharacters#1{\clf_theremainingcharacters{#1}}
+
+\let\doiffirstcharelse\doifelsefirstchar
+
+%D \macros
+%D {doifinstringelse, doifincsnameelse}
+%D
+%D We can check for the presence of a substring in a given
+%D sequence of characters.
+%D
+%D \starttyping
+%D \doifinsetelse {substring} {string} {then ...} {else ...}
+%D \stoptyping
+
+\let\m_syst_sub_string\empty
+
+\unexpanded\def\doifelseinstring#1%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\thirdofthreearguments
+ \else
+ \expandafter\syst_helpers_do_if_in_string_else_indeed
+ \fi}
+
+\let\doifinstringelse\doifelseinstring
+
+\unexpanded\def\syst_helpers_do_if_in_string_else_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifinstring#1%%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_do_if_in_string_indeed
+ \fi}
+
+\unexpanded\def\syst_helpers_do_if_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotinstring#1%%
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_do_if_not_in_string_indeed
+ \fi}
+
+\unexpanded\def\syst_helpers_do_if_not_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+% replaces prev
+
+\unexpanded\def\syst_helpers_do_if_in_string_else#1#2% ##2 can be {abc}
+ {\expandafter\def\expandafter\syst_helpers_do_do_if_in_string_else
+ \expandafter##\expandafter1#1##2##3\_e_o_s_{\unless\if##2@}% expand #1 here
+ \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@\_e_o_s_} % expand #2 here
+
+%D The next alternative proved to be upto twice as fast on
+%D tasks like checking reserved words in pretty verbatim
+%D typesetting! This is mainly due to the fact that passing
+%D (expanded) strings is much slower that passing a macro.
+%D
+%D \starttyping
+%D \doifincsnameelse {substring} {\string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D Where \type{\doifinstringelse} does as much expansion as
+%D possible, the latter alternative does minimal (one level)
+%D expansion.
+
+\unexpanded\def\syst_helpers_do_if_in_csname_else#1#2%
+ {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3\_e_o_s_
+ {\unless\if##2@}%
+ \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\_e_o_s_}
+
+\unexpanded\def\doifelseincsname#1#2%
+ {\normalexpanded{\syst_helpers_do_if_in_csname_else{#1}}{#2}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifincsnameelse\doifelseincsname
+
+%D \macros
+%D {doifnumberelse,doifnumber,doifnotnumber}
+%D
+%D The next macro executes a command depending of the outcome of a test on
+%D numerals. This is probably one of the fastest test possible, exept from
+%D a less robust 10||step \type {\if}||ladder or some tricky \type {\lcode}
+%D checking.
+%D
+%D \starttyping
+%D \doifnumberelse {string} {then ...} {else ...}
+%D \stoptyping
+%D
+%D The macro accepts \type {123}, \type {abc}, \type {{}}, \type {\getal} and
+%D \type {\the\count...}. This macro is a rather dirty one.
+
+\def\doifelsenumber#1% does not accept counters (fully expandable)
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifnumberelse\doifelsenumber
+
+\def\doifnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {setpercentdimen}
+%D
+%D \starttyping
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent}
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt}
+%D \scratchdimen \percentdimen \hsize {10\letterpercent}
+%D \stoptyping
+
+\def\percentdimen#1#2% dimen percentage (with %)
+ {\dimexpr\clf_percentageof{#2}\dimexpr#1\relax}
+
+\unexpanded\def\setpercentdimen#1#2% dimen percentage (with %)
+ {#1=\clf_percentageof{#2}\dimexpr#1\relax}
+
+%D \macros
+%D {makerawcommalist,
+%D rawdoinsetelse,
+%D rawprocesscommalist,
+%D rawprocessaction}
+%D
+%D Some of the commands mentioned earlier are effective but
+%D slow. When one is desperately in need of faster alternatives
+%D and when the conditions are predictable safe, the \type{\raw}
+%D alternatives come into focus. A major drawback is that
+%D they do not take \type{\c!constants} into account, simply
+%D because no expansion is done. This is no problem with
+%D \type{\rawprocesscommalist}, because this macro does not
+%D compare anything. Expandable macros are permitted as search
+%D string.
+%D
+%D \starttyping
+%D \makerawcommalist[string,string,...]\stringlist
+%D \rawdoifelseinset{string}{string,...}{...}{...}
+%D \rawprocesscommalist[string,string,...]\commando
+%D \rawprocessaction[x][a=>\a,b=>\b,c=>\c]
+%D \stoptyping
+%D
+%D Spaces embedded in the list, for instance after commas,
+%D spoil the search process. The gain in speed depends on the
+%D length of the argument (the longer the argument, the less
+%D we gain).
+
+\unexpanded\def\makerawcommalist[#1]#2% use \processnext ... here
+ {\def\syst_helpers_do_make_raw_comma_list##1% we don't expand ##1
+ {\ifx#2\empty
+ \def#2{##1}%
+ \else
+ \expandafter\def\expandafter#2\expandafter{#2,##1}%
+ \fi}%
+ \let#2\empty
+ \processcommalist[#1]\syst_helpers_do_make_raw_comma_list}
+
+\def\syst_helpers_raw_process_comma_item#1,#2% #2 eats up preceding space
+ {\if]#1\else
+ \csname\??nextcommalevel\the\commalevel\endcsname{#1}%
+ \expandafter\syst_helpers_raw_process_comma_item
+ \fi#2}
+
+\unexpanded\def\rawprocesscommalist[#1]#2% accepteert ook [\cs]
+ {\global\advance\commalevel \plusone
+ \expandafter\let\csname\??nextcommalevel\the\commalevel\endcsname#2%
+ \expandafter\syst_helpers_raw_process_comma_item#1,],% \relax
+ \global\advance\commalevel \minusone }
+
+\unexpanded\def\rawprocesscommacommand[#1]% not really needed
+ {\normalexpanded{\rawprocesscommalist[#1]}}
+
+% \def\rawdoifelseinset#1#2{\doifinstringelse{,#1,}{,#2,}}
+% \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}}
+
+\def\m_syst_two_commas{,,}
+
+\unexpanded\def\rawdoifelseinset#1%
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
+ \expandafter\thirdofthreearguments
+ \else
+ \expandafter\syst_helpers_raw_do_if_in_set_else
+ \fi}
+
+\let\rawdoifinsetelse\rawdoifinsetelse
+
+\unexpanded\def\syst_helpers_raw_do_if_in_set_else#1%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\rawdoifinset#1%
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\syst_helpers_raw_do_if_in_set
+ \fi}
+
+\unexpanded\def\syst_helpers_raw_do_if_in_set#1%%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D Some more raw material:
+
+\def\syst_helpers_do_raw_process_action[#1][#2]%
+ {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\_e_o_s_
+ {\if##3@\else
+ \def\m_syst_helpers_process_action{##2}%
+ \fi}%
+ \syst_helpers_do_do_raw_process_action,#2,#1=>,@\_e_o_s_}
+
+\unexpanded\def\rawprocessaction[#1]#2[#3]%
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{undefined}% better \!!undefined
+ \let\m_syst_helpers_process_action\m_syst_string_two
+ \ifx\m_syst_string_one\empty
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!default][#3]%
+ \else
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\m_syst_string_one][#3]%
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!unknown][#3]%
+ \fi
+ \fi
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
+ \else
+ \m_syst_helpers_process_action
+ \fi}
+
+%D When we process the list \type{a,b,c,d,e}, the raw routine takes over 30\% less
+%D time, when we feed $20+$ character strings we gain about 20\%. Alternatives which
+%D use \type{\futurelet} perform worse. Part of the speedup is due to the
+%D \type{\let} and \type{\expandafter} in the test.
+
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,docopyvalue,doresetvalue,
+%D dogetvalue}
+%D
+%D When we are going to do assignments, we have to take multi||linguality into account.
+%D For the moment we keep things simple and single||lingual.
+%D
+%D \starttyping
+%D \dosetvalue {label} {variable} {value}
+%D \dosetevalue {label} {variable} {value}
+%D \dosetgvalue {label} {variable} {value}
+%D \docopyvalue {to label} {from label} {variable}
+%D \doresetvalue {label} {variable}
+%D \stoptyping
+%D
+%D These macros are in fact auxiliary ones and are not meant for use outside the
+%D assignment macros.
+
+\def\dosetvalue#1#2% #3
+ {\expandafter\def\csname#1#2\endcsname} % {#3}}
+
+\def\dosetevalue#1#2% #3
+ {\expandafter\edef\csname#1#2\endcsname} % {#3}}
+
+\def\dosetgvalue#1#2% #3
+ {\expandafter\gdef\csname#1#2\endcsname} % {#3}}
+
+\def\doresetvalue#1#2%
+ {\expandafter\let\csname#1#2\endcsname\empty}
+
+\def\doignorevalue#1#2#3%
+ {\expandafter\let\csname#1#2\endcsname\empty}
+
+\def\docopyvalue#1#2#3%
+ {\expandafter\def\csname#1#3\endcsname{\csname#2#3\endcsname}}
+
+%D \macros
+%D {doassign,undoassign,doassignempty}
+%D
+%D Assignments are the backbone of \CONTEXT. Abhorred by the concept of style file
+%D hacking, we took a considerable effort in building a parameterized system.
+%D Unfortunately there is a price to pay in terms of speed. Compared to other
+%D packages and taking the functionality of \CONTEXT\ into account, the total size
+%D of the format file is still very acceptable. Now how are these assignments done.
+%D
+%D Assignments can be realized with:
+%D
+%D \starttyping
+%D \doassign[label][variable=value]
+%D \undoassign[label][variable=value]
+%D \stoptyping
+%D
+%D and:
+%D
+%D \starttyping
+%D \doassignempty[label][variable=value]
+%D \stoptyping
+%D
+%D Assignments like \type{\doassign} are compatible with:
+%D
+%D \starttyping
+%D \def\labelvariable{value}
+%D \stoptyping
+%D
+%D We do check for the presence of an \type{=} and loudly complain of it's missed. We
+%D will redefine this macro later on, when a more advanced message mechanism is
+%D implemented.
+
+\newif\iferrorisfatal
+
+\unexpanded\def\waitonfatalerror
+ {\iferrorisfatal\wait\fi}
+
+\unexpanded\def\showassignerror#1#2%
+ {\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}%
+ \waitonfatalerror}
+
+\unexpanded\def\doassignempty[#1][#2=#3]%
+ {\ifcsname#1#2\endcsname\else\dosetvalue{#1}{#2}{#3}\fi}
+
+%D \macros
+%D {getparameters,geteparameters,getgparameters,
+%D forgetparameters}
+%D
+%D Using the assignment commands directly is not our ideal of user friendly interfacing,
+%D so we take some further steps.
+%D
+%D \starttyping
+%D \getparameters [label] [...=...,...=...]
+%D \forgetparameters [label] [...=...,...=...]
+%D \stoptyping
+%D
+%D Again, the label identifies the category a variable belongs to. The second argument
+%D can be a comma separated list of assignments.
+%D
+%D \starttyping
+%D \getparameters
+%D [demo]
+%D [alfa=1,
+%D beta=2]
+%D \stoptyping
+%D
+%D is equivalent to
+%D
+%D \starttyping
+%D \def\demoalfa{1}
+%D \def\demobeta{2}
+%D \stoptyping
+%D
+%D
+%D In the pre||multi||lingual stadium \CONTEXT\ took the next approach. With
+%D
+%D \starttyping
+%D \def\??demo {@@demo}
+%D \def\!!alfa {alfa}
+%D \def\!!beta {beta}
+%D \stoptyping
+%D
+%D calling
+%D
+%D \starttyping
+%D \getparameters
+%D [\??demo]
+%D [\!!alfa=1,
+%D \!!beta=2]
+%D \stoptyping
+%D
+%D lead to:
+%D
+%D \starttyping
+%D \def\@@demoalfa{1}
+%D \def\@@demobeta{2}
+%D \stoptyping
+%D
+%D Because we want to be able to distinguish the \type{!!} pre||tagged user supplied
+%D variables from internal counterparts, we will introduce a slightly different tag
+%D in the multi||lingual modules. There we will use \type{c!} or \type{v!},
+%D depending on the context.
+%D
+%D By calling \type{doassign} directly, we save ourselves some argument passing
+%D and gain some speed. Whatever optimizations we do, this command will always be
+%D one of the bigger bottlenecks. The alternative \type{\geteparameters} --- it's
+%D funny to see that this alternative saw the light so lately --- can be used to do
+%D expanded assigments.
+
+\let\currentvalue\empty
+
+\unexpanded\def\getparameters {\dogetparameters\dosetvalue}
+\unexpanded\def\geteparameters {\dogetparameters\dosetevalue}
+\unexpanded\def\getgparameters {\dogetparameters\dosetgvalue}
+\unexpanded\def\getxparameters {\dogetparameters\dosetxvalue}
+\unexpanded\def\forgetparameters{\dogetparameters\doignorevalue}
+
+\let\getexpandedparameters\geteparameters
+
+\unexpanded\def\dogetparameters#1[#2]#3[#4%
+ {\if\noexpand#4]%
+ \expandafter\gobbleoneargument
+ \else
+ \let\setsomevalue#1%
+ \def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#2}%
+ \expandafter\syst_helpers_get_parameters
+ \fi#4}
+
+\def\syst_helpers_get_parameters#1]%
+ {\xprocesscommaitem#1,],\_e_o_p_}
+
+\def\syst_helpers_process_comma_item#1,#2% #2 takes space before ,
+ {\if,#1,% dirty trick for testing #1=empty
+ \expandafter\syst_helpers_process_comma_item
+ \else\if]#1%
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \syst_helpers_get_parameters_assign\_e_o_p_#1==\empty\_e_o_p_
+ \doubleexpandafter\syst_helpers_process_comma_item
+ \fi\fi#2}
+
+\def\syst_helpers_assign_error#1#2#3%
+ {\showassignerror{#2}{\the\inputlineno\space(#1)}}
+
+\def\syst_helpers_get_parameters_assign_normal#1\_e_o_p_#2=#3=#4#5\_e_o_p_
+ {\ifx\empty#2\empty
+ \expandafter\syst_helpers_assign_error
+ \else\ifx#4\empty
+ \doubleexpandafter\syst_helpers_assign_error
+ \else
+ \doubleexpandafter\setsomevalue
+ \fi\fi
+ {#1}{#2}{#3}}
+
+\def\syst_helpers_get_parameters_assign_error#1\_e_o_p_#2=#3=#4#5\_e_o_p_
+ {\ifx\empty#2\empty
+ \expandafter\syst_helpers_assign_error
+ \else\ifx#4\empty
+ \doubleexpandafter\syst_helpers_assign_error
+ \else
+ \ifcsname#1#2\endcsname
+ \expandafter\let\expandafter\currentvalue\csname#1#2\endcsname
+ \else
+ \let\currentvalue\empty
+ \fi
+ \doubleexpandafter\setsomevalue
+ \fi\fi
+ {#1}{#2}{#3}}
+
+\let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
+
+\unexpanded\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
+\unexpanded\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
+\unexpanded\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
+
+%D \macros
+%D {processassignmentlist,processassignmentcommand,
+%D startprocessassignmentlist,startprocessassignmentcommand}
+%D
+%D For Wolfgang:
+%D
+%D \starttyping
+%D \def\showpair#1#2{key:#1, value:#2\par}
+%D \processassignmentlist[a=1,b=2]\showpair
+%D \stoptyping
+%D
+%D We can optimize this one if needed but it's not a core macro so hardly
+%D worth the trouble and tokens.
+
+\unexpanded\def\processassignmentlist[#1]#2% #2 == \command{key}{value]
+ {\def\syst_helpers_process_assignment_entry##1{#2}% {##2}{##3} % namespace is ignored
+ \dogetparameters\syst_helpers_process_assignment_entry[][#1]}
+
+\unexpanded\def\processassignmentcommand[#1]%
+ {\normalexpanded{\processassignmentlist[#1]}}
+
+\unexpanded\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+ \processassignmentlist[#1]\currentassignmentlistcommand}
+
+\unexpanded\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+ \normalexpanded{\processassignmentlist[#1]}\currentassignmentlistcommand}
+
+%D \macros{currentvalue}
+%D
+%D Just in case a \type{\getparameter} argument itself ends up inside a \type
+%D {\write} or other expandable location, our new macro needs a default value.
+%D
+%D \starttyping
+%D \getparameters[xxx][aaa=bbb]\par
+%D \getparameters[xxx][=bbb]\par
+%D \getparameters[xxx][aaa=]\par
+%D \getparameters[xxx][=]\par
+%D \getparameters[xxx][aaa]\par
+%D \stoptyping
+
+%D \macros
+%D {expandparameters}
+%D
+%D Example usage:
+%D
+%D \startbuffer
+%D \getparameters[taco][name=taco]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \expandparameters \getparameters[taco][name=\currentvalue\space hoekwater]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \getparameters[taco][name=\currentvalue\space hoekwater]
+%D \convertcommand\taconame\to\ascii \ascii
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D Here we hook in the code (beware, this is the optimized get **):
+
+\def\syst_helpers_get_parameters_normal#1]%
+ {\syst_helpers_process_comma_item#1,],\_e_o_p_}
+
+\def\syst_helpers_get_parameters_expanded#1]%
+ {\let\dosetnvalue\setsomevalue
+ \let\setsomevalue\dosetevalue
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_error
+ \let\setsomevalue\dosetevalue
+ \syst_helpers_process_comma_item#1,],\_e_o_p_
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
+ \let\setsomevalue\dosetnvalue
+ \let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal
+ \let\currentvalue\empty}
+
+\let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal % **
+
+\unexpanded\def\expandparameters
+ {\let\syst_helpers_get_parameters\syst_helpers_get_parameters_expanded}
+
+%D \macros
+%D {getemptyparameters}
+%D
+%D Sometimes we explicitly want variables to default to an
+%D empty string, so we welcome:
+%D
+%D \starttyping
+%D \getemptyparameters [label] [...=...,...=...]
+%D \stoptyping
+
+\unexpanded\def\getemptyparameters[#1]#2[#3]%
+ {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}%
+ \processcommalist[#3]\syst_helpers_get_empty_parameters}
+
+%D \macros
+%D {copyparameters}
+%D
+%D Some \CONTEXT\ commands take their default setups from
+%D others. All commands that are able to provide backgounds
+%D or rules around some content, for instance default to the
+%D standard command for ruled boxes. Is situations like this
+%D we can use:
+%D
+%D \starttyping
+%D \copyparameters [to-label] [from-label] [name1,name2,...]
+%D \stoptyping
+%D
+%D For instance
+%D
+%D \starttyping
+%D \copyparameters
+%D [internal][external]
+%D [alfa,beta]
+%D \stoptyping
+%D
+%D Leads to:
+%D
+%D \starttyping
+%D \def\internalalfa {\externalalfa}
+%D \def\internalbeta {\externalbeta}
+%D \stoptyping
+%D
+%D By using \type{\docopyvalue} we've prepared this command
+%D for use in a multi||lingual environment.
+
+\unexpanded\def\copyparameters[#1]#2[#3]#4[#5]%
+ {\doifnot{#1}{#3}
+ {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#3}}% ##1
+ \processcommalist[#5]\syst_helpers_copy_parameter}}
+
+%D \macros
+%D {ifparameters,checkparameters}
+%D
+%D A slightly different one is \type{\checkparameters}, which
+%D also checks on the presence of a~\type{=}.
+%D
+%D The boolean \type{\ifparameters} can be used afterwards.
+%D Combining both in one \type{\if}||macro would lead to
+%D problems with nested \type{\if}'s.
+%D
+%D \starttyping
+%D \checkparameters[argument]
+%D \stoptyping
+
+\newif\ifparameters
+
+\def\syst_helpers_check_parameters#1=#2#3\_e_o_s_
+ {\if#2@\parametersfalse\else\parameterstrue\fi}
+
+\unexpanded\def\checkparameters[#1]%
+ {\syst_helpers_check_parameters#1=@@\_e_o_s_}
+
+%D \macros
+%D {getfromcommalist,getfromcommacommand,
+%D commalistelement,
+%D getcommalistsize,getcommacommandsize}
+%D
+%D It's possible to get an element from a commalist or a command representing
+%D a commalist.
+%D
+%D \starttyping
+%D \getfromcommalist [string] [n]
+%D \getfromcommacommand [string,\strings,string,...] [n]
+%D \stoptyping
+%D
+%D The difference betwee the two of them is the same as the difference between
+%D \type {\processcomma...}. The found string is stored in \type
+%D {\commalistelement}.
+%D
+%D We can calculate the size of a comma separated list by using:
+%D
+%D \starttyping
+%D \getcommalistsize [string,string,...]
+%D \getcommacommandsize [string,\strings,string,...]
+%D \stoptyping
+%D
+%D Afterwards, the length is available in the macro \type {\commalistsize}
+%D (not a \COUNTER).
+
+\newcount\commalistcounter
+
+\def\commalistsize{0}
+
+\def\syst_helpers_get_comma_list_size#1%
+ {\advance\commalistcounter\plusone}
+
+\unexpanded\def\getcommalistsize#1]% don't loose [{#1}]
+ {\commalistcounter\zerocount
+ \processcommalist#1]\syst_helpers_get_comma_list_size % was [{#1}]
+ \edef\commalistsize{\the\commalistcounter}}
+
+% \def\getcommacommandsize[#1]%
+% {\edef\commacommand{#1}%
+% \scratchtoks\expandafter{\expandafter[\commacommand]}%
+% \expandafter\getcommalistsize\the\scratchtoks }
+
+\unexpanded\def\getcommacommandsize[#1]%
+ {\normalexpanded{\getcommalistsize[#1]}}
+
+\def\syst_helpers_get_from_comma_list#1%
+ {\advance\commalistcounter \minusone
+ \ifcase\commalistcounter
+ \def\commalistelement{#1}%
+ \expandafter\quitcommalist
+ \fi}
+
+\unexpanded\def\getfromcommalist[#1]#2[#3]%
+ {\let\commalistelement\empty
+ \commalistcounter#3\relax
+ \processcommalist[#1]\syst_helpers_get_from_comma_list}
+
+\unexpanded\def\getfromcommacommand[#1]%
+ {\normalexpanded{\getfromcommalist[#1]}}
+
+%D Watertight (and efficient) solutions are hard to find, due
+%D to the handling of braces during parameters passing and
+%D scanning. Nevertheless:
+%D
+%D \startbuffer
+%D \def\dosomething#1{(#1=\commalistsize) }
+%D
+%D \getcommalistsize [\hbox{$a,b,c,d,e,f$}] \dosomething 1
+%D \getcommalistsize [{a,b,c,d,e,f}] \dosomething 1
+%D \getcommalistsize [{a,b,c},d,e,f] \dosomething 4
+%D \getcommalistsize [a,b,{c,d,e},f] \dosomething 4
+%D \getcommalistsize [a{b,c},d,e,f] \dosomething 4
+%D \getcommalistsize [{a,b}c,d,e,f] \dosomething 4
+%D \getcommalistsize [] \dosomething 0
+%D \getcommalistsize [{[}] \dosomething 1
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D reports:
+%D
+%D \getbuffer
+
+%D \macros
+%D {dogetcommalistelement,dogetcommacommandelement}
+%D
+%D For low level (fast) purposes, we can also use the next
+%D alternative, which can handle 8~elements at most.
+%D
+%D \starttyping
+%D \dogetcommalistelement1\from a,b,c\to\commalistelement
+%D \stoptyping
+
+\def\syst_helpers_get_comma_list_element#1\from#2,#3,#4,#5,#6,#7,#8\to#9%
+ {\edef#9{\ifcase#1\relax\or#2\or#3\or#4\or#5\or#6\or#7\or#8\fi}}
+
+\def\dogetcommacommandelement#1\from#2\to%
+ {\expandafter\syst_helpers_get_comma_list_element\expandafter#1\expandafter\from#2,,,,,,\to}
+
+%D \macros
+%D {dosingleargument,dodoubleargument,dotripleargument,
+%D doquadrupleargument,doquintupleargument,dosixtupleargument,
+%D doseventupleargument}
+%D
+%D When working with delimited arguments, spaces and
+%D lineendings can interfere. The next set of macros uses
+%D \TEX' internal scanner for grabbing everything between
+%D arguments. Forgive me the funny names.
+%D
+%D \starttyping
+%D \dosingleargument\commando = \commando[#1]
+%D \dodoubleargument\commando = \commando[#1][#2]
+%D \dotripleargument\commando = \commando[#1][#2][#3]
+%D \doquadrupleargument\commando = \commando[#1][#2][#3][#4]
+%D \doquintupleargument\commando = \commando[#1][#2][#3][#4][#5]
+%D \dosixtupleargument\commando = \commando[#1][#2][#3][#4][#5][#6]
+%D \doseventupleargument\command = \commando[#1][#2][#3][#4][#5][#6][#7]
+%D \stoptyping
+%D
+%D These macros are used in the following way:
+%D
+%D \starttyping
+%D \def\dosetupsomething[#1][#2]%
+%D {... #1 ... #2 ...}
+%D
+%D \unexpanded\def\setupsomething
+%D {\dodoubleargument\dosetupsomething}
+%D \stoptyping
+%D
+%D The implementation can be surprisingly simple and needs no
+%D further explanation, like:
+%D
+%D \starttyping
+%D \def\dosingleargument#1[#2]%
+%D {#1[#2]}
+%D \def\dotripleargument#1[#2]#3[#4]#5[#6]%
+%D {#1[#2][#4][#6]}
+%D \def\doquintupleargument#1%
+%D {\def\dodoquintupleargument[##1]##2[##3]##4[##5]##6[##7]##8[##9]%
+%D {#1[##1][##3][##5][##7][##9]}%
+%D \dodoquintupleargument}
+%D \stoptyping
+%D
+%D Because \TEX\ accepts 9~arguments at most, we have to use
+%D two||step solution when getting five or more arguments.
+%D
+%D When developing more and more of the real \CONTEXT, we
+%D started using some alternatives that provided empty
+%D arguments (in fact optional ones) whenever the user failed
+%D to supply them. Because this more complicated macros enable
+%D us to do some checking, we reimplemented the non||empty
+%D ones.
+
+% no longer a mesage:
+%
+% \unexpanded\def\dosingleargument {\let\expectedarguments\plusone \dosingleempty }
+% \unexpanded\def\dodoubleargument {\let\expectedarguments\plustwo \dodoubleempty }
+% \unexpanded\def\dotripleargument {\let\expectedarguments\plusthree \dotripleempty }
+% \unexpanded\def\doquadrupleargument {\let\expectedarguments\plusfour \doquadrupleempty }
+% \unexpanded\def\doquintupleargument {\let\expectedarguments\plusfive \doquintupleempty }
+% \unexpanded\def\dosixtupleargument {\let\expectedarguments\plussix \dosixtupleempty }
+% \unexpanded\def\doseventupleargument{\let\expectedarguments\plusseven \doseventupleempty}
+
+%D \macros
+%D {iffirstagument,ifsecondargument,ifthirdargument,
+%D iffourthargument,iffifthargument,ifsixthargument,
+%D ifseventhargument}
+%D
+%D We use some signals for telling the calling macros if all
+%D wanted arguments are indeed supplied by the user.
+
+\newif\iffirstargument
+\newif\ifsecondargument
+\newif\ifthirdargument
+\newif\iffourthargument
+\newif\iffifthargument
+\newif\ifsixthargument
+\newif\ifseventhargument
+
+%D \macros
+%D {dosingleempty,dodoubleempty,dotripleempty,
+%D doquadrupleempty,doquintupleempty,dosixtupeempty,
+%D doseventupleempty}
+%D
+%D The empty argument supplying macros mentioned before, look like:
+%D
+%D \starttyping
+%D \dosingleempty \command
+%D \dodoubleempty \command
+%D \dotripleempty \command
+%D \doquadrupleempty \command
+%D \doquintupleempty \command
+%D \dosixtuple_empty \command
+%D \doseventupleempty\command
+%D \stoptyping
+%D
+%D So \type{\dodoubleempty} leads to:
+%D
+%D \starttyping
+%D \command[#1][#2]
+%D \command[#1][]
+%D \command[][]
+%D \stoptyping
+%D
+%D Depending of the generousity of the user. Afterwards one can
+%D use the \type{\if...argument} boolean. For novice: watch
+%D the stepwise doubling of \type{#}'s
+
+\setnewconstant\noexpectedarguments\zerocount
+\setnewconstant\expectedarguments \zerocount
+
+\unexpanded\def\showargumenterror#1#2%
+ {\writestatus{system}{\number#1 argument(s) expected in line #2}}
+
+\unexpanded\def\syst_helpers_argument_error
+ {\ifnum\expectedarguments>\noexpectedarguments
+ \showargumenterror{\number\expectedarguments}{\number\inputlineno}%
+ \fi
+ \syst_helpers_argument_reset}
+
+\unexpanded\def\syst_helpers_argument_reset
+ {\let\expectedarguments\noexpectedarguments}
+
+% \def\test[#1]{(#1)}
+%
+% \dosingleempty\test[] xxx\par
+% \dosingleempty\test xxx\par
+%
+% \def\test[#1][#2]{(#1,#2)}
+%
+% \dodoubleempty\test[][] xxx\par
+% \dodoubleempty\test[] xxx\par
+% \dodoubleempty\test xxx\par
+%
+% \def\test[#1][#2][#3]{(#1,#2,#3)}
+%
+% \dotripleempty\test[][][] xxx\par
+% \dotripleempty\test[][] xxx\par
+% \dotripleempty\test[] xxx\par
+% \dotripleempty\test xxx\par
+
+%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[]}
+
+%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}][]}
+
+% 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}][]}
+
+%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}][]}
+
+%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}][]}
+
+%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}][]}
+
+%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}][]}
+
+\let\dosingleargument \dosingleempty
+\let\dodoubleargument \dodoubleempty
+\let\dotripleargument \dotripleempty
+\let\doquadrupleargument \doquadrupleempty
+\let\doquintupleargument \doquintupleempty
+\let\dosixtupleargument \dosixtupleempty
+\let\doseventupleargument\doseventupleempty
+
+%D \macros
+%D {strippedcsname}
+%D
+%D The next macro can be very useful when using \type{\csname}
+%D like in:
+%D
+%D \starttyping
+%D \csname if\strippedcsname\something\endcsname
+%D \stoptyping
+%D
+%D This expands to \type{\ifsomething}.
+
+% \def\strippedcsname
+% {\expandafter\gobbleoneargument\string}
+
+\let\strippedcsname\csstring
+
+%D \macros
+%D {complexorsimple,complexorsimpleempty}
+%D
+%D Setups can be optional. A command expecting a setup is
+%D prefixed by \type{\complex}, a command without one gets the
+%D prefix \type{\simple}. Commands like this can be defined by:
+%D
+%D \starttyping
+%D \complexorsimple\command
+%D \stoptyping
+%D
+%D When \type{\command} is followed by a \type{[setup]}, then
+%D
+%D \starttyping
+%D \complexcommand [setup]
+%D \stoptyping
+%D
+%D executes, else we get
+%D
+%D \starttyping
+%D \simplecommand
+%D \stoptyping
+%D
+%D An alternative for \type{\complexorsimple} is:
+%D
+%D \starttyping
+%D \complexorsimpleempty {command}
+%D \stoptyping
+%D
+%D Depending on the presence of \type{[setup]}, this one
+%D leads to one of:
+%D
+%D \starttyping
+%D \complexcommando [setup]
+%D \complexcommando []
+%D \stoptyping
+%D
+%D Many \CONTEXT\ commands started as complex or simple ones,
+%D but changed into more versatile (more object oriented) ones
+%D using the \type{\get..argument} commands.
+
+\unexpanded\def\complexorsimple#1%
+ {% \relax % prevents lookahead, brrr
+ \doifelsenextoptional
+ {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+ {\firstargumentfalse\csname\s!simple \csstring#1\endcsname}}
+
+\unexpanded\def\complexorsimpleempty#1%
+ {% \relax % prevents lookahead, brrr
+ \doifelsenextoptional
+ {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+ {\firstargumentfalse\csname\s!complex\csstring#1\endcsname[]}}
+
+%D \macros
+%D {definecomplexorsimple,definecomplexorsimpleempty}
+%D
+%D The previous commands are used that often that we found it
+%D worthwile to offer two more alternatives. Watch the build
+%D in protection.
+
+\unexpanded\def\syst_helpers_complex_or_simple#1#2%
+ {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#2}}
+
+\unexpanded\def\syst_helpers_complex_or_simple_empty#1%
+ {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#1[]}}
+
+\unexpanded\def\definecomplexorsimple#1%
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple
+ \expandafter\noexpand\csname\s!complex\csstring#1\endcsname
+ \expandafter\noexpand\csname\s!simple \csstring#1\endcsname}}
+
+\unexpanded\def\definecomplexorsimpleempty#1%
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple_empty
+ \expandafter\noexpand\csname\s!complex\csstring#1\endcsname}}
+
+%D These commands are called as:
+%D
+%D \starttyping
+%D \definecomplexorsimple\command
+%D \stoptyping
+%D
+%D Of course, we must have available
+%D
+%D \starttyping
+%D \def\complexcommand[#1]{...}
+%D \def\simplecommand {...}
+%D \stoptyping
+%D
+%D Using this construction saves a few string now and then.
+
+%D \macros
+%D {dosinglegroupempty,dodoublegroupempty,dotriplegroupempty,
+%D doquadruplegroupempty, doquintuplegroupempty}
+%D
+%D We've already seen some commands that take care of
+%D optional arguments between \type{[]}. The next two commands
+%D handle the ones with \type{{}}. They are called as:
+%D
+%D \starttyping
+%D \dosinglegroupempty \ineedONEargument
+%D \dodoublegroupempty \ineedTWOarguments
+%D \dotriplegroupempty \ineedTHREEarguments
+%D \doquadruplegroupempty \ineedFOURarguments
+%D \doquintuplegroupempty \ineedFIVEarguments
+%D \stoptyping
+
+%D We can add additional definitions later when we have defined
+%D \type {\appendtoks}.
+
+\newconditional\c_syst_helpers_permit_spaces_between_groups
+
+\unexpanded\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups}
+\unexpanded\def\dontpermitspacesbetweengroups{\setfalse\c_syst_helpers_permit_spaces_between_groups}
+
+\dontpermitspacesbetweengroups
+
+%D We can avoid the nasty if handling in \type {syst-gen} by splitting
+%D the lot in pieces so that we have no nested \type {\nextarguments}
+%D potentially being an \type {conditional} token. Okay, these macros
+%D are not called that often but it saves crap when tracing.
+
+\unexpanded\def\syst_helpers_get_grouped_argument#1#2%
+ {\let\syst_helpers_get_grouped_argument_yes#1%
+ \let\syst_helpers_get_grouped_argument_nop#2%
+ \futurelet\nextargument\syst_helpers_get_grouped_argument_indeed}
+
+\def\syst_helpers_get_grouped_argument_indeed
+ {\ifx\nextargument\bgroup
+ \expandafter\syst_helpers_get_grouped_argument_a
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_b
+ \fi}
+
+\def\syst_helpers_get_grouped_argument_a
+ {\syst_helpers_argument_reset
+ \syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nested}
+
+\def\syst_helpers_get_grouped_argument_b
+ {\ifconditional\c_syst_helpers_permit_spaces_between_groups
+ \expandafter\syst_helpers_get_grouped_argument_f
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_d
+ \fi}
+
+\def\syst_helpers_get_grouped_argument_d
+ {\syst_helpers_argument_error
+ \syst_helpers_get_grouped_argument_nop\syst_helpers_get_grouped_argument_nested{}}
+
+\begingroup
+ \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop}
+ \global\let\syst_helpers_get_grouped_argument_e\\
+\endgroup
+
+\def\syst_helpers_get_grouped_argument_f
+ {\ifx\nextargument\blankspace
+ \expandafter\syst_helpers_get_grouped_argument_e % g
+ \else
+ \expandafter\syst_helpers_get_grouped_argument_d % h
+ \fi}
+
+\def\dosinglegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\def\dodoublegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\def\dotriplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\def\doquadruplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}{########1}}%
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+\def\doquintuplegroupempty#1%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested################1%
+ {\def\syst_helpers_get_grouped_argument_nested
+ {\dontpermitspacesbetweengroups
+ #1{##1}{####1}{########1}{################1}}%
+ \syst_helpers_get_grouped_argument\fifthargumenttrue\fifthargumentfalse}%
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
+
+%D These macros can explictly take care of spaces, which means
+%D that the next definition and calls are valid:
+%D
+%D \starttyping
+%D \def\test#1#2#3{[#1#2#3]}
+%D
+%D \dotriplegroupempty\test {a}{b}{c}
+%D \dotriplegroupempty\test {a}{b}
+%D \dotriplegroupempty\test {a}
+%D \dotriplegroupempty\test
+%D \dotriplegroupempty\test {a} {b} {c}
+%D \dotriplegroupempty\test {a} {b}
+%D \dotriplegroupempty\test
+%D {a}
+%D {b}
+%D \stoptyping
+%D
+%D And alike.
+
+%D \macros
+%D {firstofoneargument, firstoftwoarguments, firstofthreearguments
+%D secondoftwoarguments, secondofthreearguments,
+%D thirdofthreearguments}
+%D
+%D The next six macros (dedicated to Taco) can conveniently
+%D used to select arguments. Their names explain their
+%D functionality.
+
+\def\firstofoneargument #1{#1}
+
+\def\firstoftwoarguments #1#2{#1}
+\def\secondoftwoarguments #1#2{#2}
+
+\def\firstofthreearguments #1#2#3{#1}
+\def\secondofthreearguments #1#2#3{#2}
+\def\thirdofthreearguments #1#2#3{#3}
+
+\def\firstoffourarguments #1#2#3#4{#1}
+\def\secondoffourarguments #1#2#3#4{#2}
+\def\thirdoffourarguments #1#2#3#4{#3}
+\def\fourthoffourarguments #1#2#3#4{#4}
+
+\def\firstoffivearguments #1#2#3#4#5{#1}
+\def\secondoffivearguments #1#2#3#4#5{#2}
+\def\thirdoffivearguments #1#2#3#4#5{#3}
+\def\fourthoffivearguments #1#2#3#4#5{#4}
+\def\fifthoffivearguments #1#2#3#4#5{#5}
+
+\def\firstofsixarguments #1#2#3#4#5#6{#1}
+\def\secondofsixarguments#1#2#3#4#5#6{#2}
+\def\thirdofsixarguments #1#2#3#4#5#6{#3}
+\def\fourthofsixarguments#1#2#3#4#5#6{#4}
+\def\fifthofsixarguments #1#2#3#4#5#6{#5}
+\def\sixthofsixarguments #1#2#3#4#5#6{#6}
+
+\unexpanded\def\firstofoneunexpanded #1{#1}
+
+\unexpanded\def\firstoftwounexpanded #1#2{#1}
+\unexpanded\def\secondoftwounexpanded #1#2{#2}
+
+\unexpanded\def\firstofthreeunexpanded #1#2#3{#1}
+\unexpanded\def\secondofthreeunexpanded#1#2#3{#2}
+\unexpanded\def\thirdofthreeunexpanded #1#2#3{#3}
+
+%D \macros
+%D {globalletempty,letempty,
+%D letvalueempty,letgvalueempty,
+%D letvaluerelax,letgvaluerelax}
+%D
+%D Trivial:
+
+\unexpanded\def\letempty #1{\let#1\empty}
+\unexpanded\def\globalletempty#1{\global\let#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\relaxvalueifundefined#1%
+ {\ifcsname#1\endcsname \else
+ \expandafter\let\csname#1\endcsname\relax
+ \fi}
+
+%D \macros
+%D {wait}
+%D
+%D The next macro hardly needs explanation. Because no
+%D nesting is to be expected, we can reuse \type{\wait} within
+%D \type{\wait} itself.
+
+\unexpanded\def\wait
+ {\begingroup
+ \read16 to \wait
+ \endgroup}
+
+%D \macros
+%D {writestring,writeline,writebanner,
+%D writestatus,statuswidth,normalwritestatus}
+%D
+%D Maybe one didn't notice, but we've already introduced a
+%D macro for showing messages. In the multi||lingual modules,
+%D we will also introduce a mechanism for message passing. For
+%D the moment we stick to the core macros:
+%D
+%D \starttyping
+%D \writestring {string}
+%D \writeline
+%D \writestatus {category} {message}
+%D \stoptyping
+%D
+%D Messages are formatted. One can provide the maximum with
+%D of the identification string with the macro \type
+%D {\statuswidth}.
+
+\setnewconstant\statuswidth 15
+\setnewconstant\statuswrite 128 % \pluscxxviii
+
+\ifdefined\writestring \else
+
+ \newtoks\everywritestring
+
+ \def\writedirect {\immediate\write\statuswrite}
+ \def\writeline {\writedirect{}}
+ \unexpanded\def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup}
+
+\fi
+
+\unexpanded\def\normalwritestatus#1#2%
+ {\writestring{\expandafter\syst_helpers_split_status_yes\expandafter\statuswidth#1%
+ \space\space\space\space\space\space\space
+ \space\space\space\space\space\space\space
+ \space\space\space\space\space\space\end
+ \space:\space#2}}
+
+\def\syst_helpers_split_status_yes#1#2%
+ {\ifcase#1 \expandafter\syst_helpers_split_status_nop\fi#2%
+ \expandafter\syst_helpers_split_status_yes\expandafter{\the\numexpr#1+\minusone\relax}}
+
+\def\syst_helpers_split_status_nop#1\end
+ {}
+
+%D \macros
+%D {immediatemessage}
+%D
+%D A fully expandable message:
+
+\let\immediatemessage\clf_immediatemessage % {} mandate
+
+%D \macros
+%D {debuggerinfo}
+%D
+%D For debugging purposes we can enhance macros with the
+%D next alternative. Here \type{debuggerinfo} stands for both
+%D a macro accepting two arguments and a boolean (in fact a
+%D few macro's too).
+
+\newif\ifdebuggerinfo
+
+\unexpanded\def\debuggerinfo#1#2%
+ {\ifdebuggerinfo
+ \writestatus{debugger}{#1:: #2}%
+ \fi}
+
+\ifdefined\writestatus \else \let\writestatus\normalwritestatus \fi
+\ifdefined\writebanner \else \unexpanded\def\writebanner{\writestring} \fi
+
+% % % % % % % % % % % % % % % % % % % % % % % %
+
+%D \macros
+%D {rawgetparameters}
+%D
+%D A raw and dirty alternative for \type {\getparameters}; no
+%D checking is done!
+
+\unexpanded\def\rawsetparameter#1=#2,%
+ {\if]#1\else
+ \expandafter\def\csname\rawparameterprefix#1\endcsname{#2}%
+ \expandafter\rawsetparameter
+ \fi}
+
+\unexpanded\def\rawgetparameters[#1][#2% some 5-10% faster
+ {\ifx#2]% test is needed, else bomb on [#1][]
+ \expandafter\gobbleoneargument
+ \else
+ \def\rawparameterprefix{#1}%
+ \expandafter\dorawgetparameters
+ \fi#2}
+
+\def\dorawgetparameters#1]%
+ {\expandafter\rawsetparameter#1,]=,}
+
+%D \macros
+%D {doglobal,
+%D redoglobal,dodoglobal,resetglobal}
+%D
+%D The two macros \type {\redoglobal} and \type{\dodoglobal} are
+%D used in this and some other modules to enforce a user
+%D specified \type {\doglobal} action. The last and often only
+%D global assignment in a macro is done with
+%D \type {\dodoglobal}, but all preceding ones with
+%D \type {\redoglobal}. When using only alternatives, one can
+%D reset this mechanism with \type {\resetglobal}.
+
+\unexpanded\def\resetglobal
+ {\let\redoglobal\relax
+ \let\dodoglobal\relax}
+
+\resetglobal
+
+\unexpanded\def\doglobal
+ {\ifx\redoglobal\relax
+ \let\redoglobal\global
+ \let\dodoglobal\syst_helpers_dodo_global
+ \fi}
+
+\def\syst_helpers_dodo_global
+ {\resetglobal\global}
+
+\def\saveglobal
+ {\let\syst_helpers_dodo_global\dodoglobal
+ \let\syst_helpers_redo_global\redoglobal}
+
+\def\restoreglobal
+ {\let\redoglobal\syst_helpers_redo_global
+ \let\dodoglobal\syst_helpers_dodo_global}
+
+%D A very useful application of this macro is \type {\newif},
+%D \TEX's fake boolean type. Not being a primitive,
+%D \type {\global} hopelessly fails here. But a slight
+%D adaption of Knuth's original macro permits:
+%D
+%D \starttyping
+%D \doglobal\newif\iftest
+%D \stoptyping
+%D
+%D Of course one can still say:
+%D
+%D \starttyping
+%D \global\testtrue
+%D \global\testfalse
+%D \stoptyping
+%D
+%D Apart from the prefixes, a few more \type{\expandafters}
+%D are needed:
+
+\unexpanded\def\newif#1%
+ {\scratchcounter\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\scratchcounter}
+
+%D Also new:
+
+\unexpanded\def\define#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is already defined]}%
+ \unexpanded\expandafter\def\expandafter\gobbleddefinition
+ \else
+ \unexpanded\expandafter\def
+ \fi#1}
+
+\unexpanded\def\redefine#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is redefined]}%
+ \fi
+ \unexpanded\def#1}
+
+\unexpanded\def\definemacro#1%
+ {\ifdefined#1%
+ \message{[\noexpand#1is already defined]}%
+ \unexpanded\expandafter\def\expandafter\gobbleddefinition
+ \else
+ \unexpanded\expandafter\def
+ \fi#1}
+
+% \define\hans{hans}
+% \redefine\hans{hans}
+% \define\hans#1[]#2#3{hans}
+
+%D The next variant fits nicely in the setups syntax:
+%D
+%D \starttyping
+%D \starttexdefinition bagger [#1] #2
+%D oeps
+%D #1
+%D oeps
+%D \stoptexdefinition
+%D
+%D \bagger [a] {b}
+%D \stoptyping
+
+% \starttexdefinition test
+% oeps
+% \stoptexdefinition
+%
+% [\test]
+
+\def\s!unexpanded{unexpanded}
+
+% \bgroup \obeylines
+%
+% \global\let\stoptexdefinition\relax
+%
+% \unexpanded\gdef\starttexdefinition%
+% {\bgroup%
+% \obeylines%
+% \syst_helpers_start_tex_definition}
+%
+% \gdef\syst_helpers_start_tex_definition #1
+% {\catcode\endoflineasciicode\ignorecatcode%
+% \doifinstringelse\letterhash{\detokenize{#1}}\syst_helpers_start_tex_definition_yes\syst_helpers_start_tex_definition_nop#1
+% }
+%
+% \gdef\syst_helpers_start_tex_definition_yes#1 #2
+% {\edef\texdefinitionname{#1}%
+% \ifx\texdefinitionname\s!unexpanded%
+% \expandafter\syst_helpers_start_tex_definition_yes_unexpanded%
+% \else%
+% \expandafter\syst_helpers_start_tex_definition_yes_normal%
+% \fi%
+% {#1}#2
+% }
+%
+% \gdef\syst_helpers_start_tex_definition_yes_unexpanded#1#2 #3
+% #4\stoptexdefinition%
+% {\egroup% #1=unexpanded
+% \unexpanded\expandafter\def\csname#2\endcsname#3{#4}}
+%
+% \gdef\syst_helpers_start_tex_definition_yes_normal#1#2
+% #3\stoptexdefinition%
+% {\egroup%
+% \expandafter\def\csname#1\endcsname#2{#3}}
+%
+% \gdef\syst_helpers_start_tex_definition_nop#1
+% {\syst_helpers_start_tex_definition_nop_indeed{#1}{}}
+%
+% \gdef\syst_helpers_start_tex_definition_nop_indeed#1#2#3\stoptexdefinition%
+% {\egroup%
+% \expandafter\def\csname#1\endcsname{#3}}
+%
+% \egroup
+
+% \starttexdefinition unexpanded test #1
+% [here #1]
+% \stoptexdefinition
+%
+% \starttexdefinition global unexpanded test
+% [here test]
+% \stoptexdefinition
+%
+% \scratchcounter=123
+%
+% \starttexdefinition global unexpanded expanded test #oeps
+% [here #oeps: \the\scratchcounter]
+% \stoptexdefinition
+
+% \bgroup \obeylines
+%
+% \global\let\stoptexdefinition\relax
+%
+% \unexpanded\gdef\starttexdefinition%
+% {\bgroup%
+% \obeylines%
+% \syst_helpers_start_tex_definition_one}
+%
+% \gdef\syst_helpers_start_tex_definition_one#1
+% {\catcode\endoflineasciicode\ignorecatcode%
+% \syst_helpers_start_tex_definition_two{#1}}
+%
+% \gdef\syst_helpers_start_tex_definition_two#1#2\stoptexdefinition%
+% {\egroup%
+% \ctxcommand{thetexdefinition("#1")}{#2}}
+%
+% \egroup
+
+\bgroup \obeylines
+
+\global\let\stoptexdefinition\relax
+
+\unexpanded\gdef\starttexdefinition%
+ {\bgroup%
+ \obeylines%
+ \syst_helpers_start_tex_definition}
+
+\gdef\syst_helpers_start_tex_definition#1
+ {\catcode\endoflineasciicode\ignorecatcode%
+ \clf_texdefinition_one{#1}}
+
+\gdef\dostarttexdefinition#1\stoptexdefinition%
+ {\egroup%
+ \clf_texdefinition_two{#1}}
+
+\egroup
+
+% \unexpanded\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace
+
+\unexpanded\def\texdefinition#1{\begincsname#1\endcsname}
+
+% This is a first variant, more might be added:
+
+\unexpanded\def\starttexcode{\unprotect}
+\unexpanded\def\stoptexcode {\protect}
+
+%D \macros
+%D {newcounter,
+%D increment,decrement}
+%D
+%D Unfortunately the number of \COUNTERS\ in \TEX\ is limited,
+%D but fortunately we can store numbers in a macro. We can
+%D increment such pseudo \COUNTERS\ with \type{\increment}.
+%D
+%D \starttyping
+%D \increment(\counter,20)
+%D \increment(\counter,-4)
+%D \increment(\counter)
+%D \increment\counter
+%D \stoptyping
+%D
+%D After this sequence of commands, the value of
+%D \type{\counter} is 20, 16, 17 and~18. Of course there is
+%D also the complementary command \type{\decrement}.
+%D
+%D Global assignments are possible too, using \type{\doglobal}:
+%D
+%D \starttyping
+%D \doglobal\increment\counter
+%D \stoptyping
+%D
+%D When \type{\counter} is undefined, it's value is initialized
+%D at~0. It is nevertheless better to define a \COUNTER\
+%D explicitly. One reason could be that the \COUNTER\ can be
+%D part of a test with \type{\ifnum} and this conditional does
+%D not accept undefined macro's. The \COUNTER\ in our example
+%D can for instance be defined with:
+%D
+%D \starttyping
+%D \newcounter\counter
+%D \stoptyping
+%D
+%D The command \type{\newcounter} must not be confused with
+%D \type{\newcount}! Of course this mechanism is much slower
+%D than using \TEX's \COUNTERS\ directly. In practice
+%D \COUNTERS\ (and therefore our pseudo counters too) are
+%D seldom the bottleneck in the processing of a text. Apart
+%D from some other incompatilities we want to mention a pitfal
+%D when using \type{\ifnum}.
+%D
+%D \starttyping
+%D \ifnum\normalcounter=\pseudocounter \doif \else \doelse \fi
+%D \ifnum\pseudocounter=\normalcounter \doif \else \doelse \fi
+%D \stoptyping
+%D
+%D In the first test, \TEX\ continues it's search for the
+%D second number after reading \type{\pseudocounter}, while
+%D in the second test, it stops reading after having
+%D encountered a real one. Tests like the first one therefore
+%D can give unexpected results, for instance execution
+%D of \type{\doif} even if both numbers are unequal.
+
+\def\zerocountervalue{0}
+
+\unexpanded\def\newcounter#1%
+ {\dodoglobal\let#1\zerocountervalue}
+
+%D Nowadays we don't mind a few more tokens if we can gain a
+%D bit of speed.
+
+\def\syst_helpers_do_increment#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\plusone \relax}}
+\def\syst_helpers_do_decrement#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\minusone\relax}}
+
+\def\syst_helpers_do_do_do_increment#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+#2\relax}}
+\def\syst_helpers_do_do_do_decrement#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi-#2\relax}}
+
+\def\syst_helpers_do_do_increment(#1{\doifelsenextchar,{\syst_helpers_do_do_do_increment#1}{\syst_helpers_do_do_do_increment#1,\plusone}}
+\def\syst_helpers_do_do_decrement(#1{\doifelsenextchar,{\syst_helpers_do_do_do_decrement#1}{\syst_helpers_do_do_do_decrement#1,\plusone}}
+
+\unexpanded\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}}
+\unexpanded\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}}
+
+\unexpanded\def\increment{\doifelsenextchar(\syst_helpers_do_do_increment\syst_helpers_do_increment}
+\unexpanded\def\decrement{\doifelsenextchar(\syst_helpers_do_do_decrement\syst_helpers_do_decrement}
+
+\unexpanded\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname}
+\unexpanded\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname}
+
+%D \macros
+%D {newsignal}
+%D
+%D When writing advanced macros, we cannot do without
+%D signaling. A signal is a small (invisible) kern or penalty
+%D that signals the next macro that something just happened.
+%D This macro can take any action depending on the previous
+%D signal. Signals must be unique and the next macro takes care
+%D of that.
+%D
+%D \starttyping
+%D \newsignal\somesignal
+%D \stoptyping
+%D
+%D Signals old dimensions and can be used in skips, kerns and
+%D tests like \type{\ifdim}.
+
+\newdimen\maximumsignal % step is about 0.00025pt
+
+\unexpanded\def\newsignal#1%
+ {\ifdefined#1\else
+ \advance\maximumsignal 2\scaledpoint % to be save in rounding
+ \edef#1{\the\maximumsignal}%
+ \fi}
+
+%D \macros
+%D {strippedcsname}
+%D
+%D The next macro can be very useful when using \type{\csname}
+%D like in:
+%D
+%D \starttyping
+%D \csname if\strippedcsname\something\endcsname
+%D \stoptyping
+
+% \def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
+% {\expandafter\syst_helpers_checked_stripped_csname\string#1}
+%
+% \def\syst_helpers_checked_stripped_csname#1%
+% %{\ifx#1\letterbackslash\else#1\fi}
+% {\if\noexpand#1\letterbackslash\else#1\fi}
+
+\let\checkedstrippedcsname\csstring
+
+%D \macros
+%D {savenormalmeaning}
+%D
+%D We will use this one in:
+
+\unexpanded\def\savenormalmeaning#1%
+ {\ifcsname normal\csstring#1\endcsname \else
+ \expandafter\let\csname normal\csstring#1\endcsname#1%
+ \fi}
+
+%D \macros
+%D {dorecurse,recurselevel,recursedepth,
+%D dostepwiserecurse}
+%D
+%D \TEX\ does not offer us powerfull for||loop mechanisms. On
+%D the other hand its recursion engine is quite unique. We
+%D therefore identify the for||looping macros by this method.
+%D The most simple alternative is the one that only needs a
+%D number.
+%D
+%D \starttyping
+%D \dorecurse {n} {whatever we want}
+%D \stoptyping
+%D
+%D This macro can be nested without problems and therefore be
+%D used in situations where \PLAIN\ \TEX's \type{\loop} macro
+%D ungracefully fails. The current value of the counter is
+%D available in \type{\recurselevel}, before as well as after
+%D the \typ{whatever we wat} stuff.
+%D
+%D \starttyping
+%D \dorecurse % inner loop
+%D {10}
+%D {\recurselevel: % outer value
+%D \dorecurse % inner loop
+%D {\recurselevel} % outer value
+%D {\recurselevel} % inner value
+%D \dorecurse % inner loop
+%D {\recurselevel} % outer value
+%D {\recurselevel} % inner value
+%D \endgraf}
+%D \stoptyping
+%D
+%D In this example the first, second and fourth
+%D \type{\recurselevel} concern the outer loop, while the third
+%D and fifth one concern the inner loop. The depth of the
+%D nesting is available for inspection in \type{\recursedepth}.
+%D
+%D Both \type{\recurselevel} and \type{\recursedepth} are
+%D macros. The real \COUNTERS\ are hidden from the user because
+%D we don't want any interference.
+
+\newcount\outerrecurse
+\newcount\innerrecurse
+
+\def\recursedepth{\the\outerrecurse}
+\def\recurselevel{0}
+
+\let\syst_helpers_stepwise_next\relax
+
+\installsystemnamespace{recurseindex}
+\installsystemnamespace{recurseaction}
+
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+ {\global\advance\outerrecurse \plusone
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname{#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\syst_helpers_stepwise_recurse#1#2#3% from to step
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_stepwise_recurse_nop
+ \else
+ \def\recurselevel{#1}%
+ \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
+ \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
+
+\unexpanded\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\recursedepth\endcsname}
+
+\unexpanded\def\syst_helpers_stepwise_recurse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_recurse}
+
+\unexpanded\def\syst_helpers_stepwise_reverse#1#2#3% from to step
+ {\ifnum#1<#2\relax
+ \expandafter\syst_helpers_stepwise_recurse_nop
+ \else
+ \def\recurselevel{#1}%
+ \innerrecurse#1\relax
+ \advance\innerrecurse#3\relax
+ \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter
+ \fi\expandafter{\the\innerrecurse}{#2}{#3}}
+
+\unexpanded\def\syst_helpers_stepwise_reverse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_reverse}
+
+\unexpanded\def\syst_helpers_stepwise_exit
+ {\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
+ \global\advance\outerrecurse\minusone}
+
+% \unexpanded\def\nonostepwiserecurse#1#2#3%
+% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+% \global\advance\outerrecurse\minusone}
+
+\unexpanded\def\dorecurse#1%
+ {\dostepwiserecurse\plusone{#1}\plusone}
+
+\def\doexpandedrecurse#1#2% user macro (also was \doxprecurse)
+ {\ifnum#1>\zerocount
+ #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-\plusone\relax}{#2}%
+ \fi}
+
+%D As we can see here, the simple command \type{\dorecurse} is
+%D a special case of the more general:
+%D
+%D \starttyping
+%D \dostepwiserecurse {from} {to} {step} {action}
+%D \stoptyping
+%D
+%D This commands accepts positive and negative steps. Illegal
+%D values are handles as good as possible and the macro accepts
+%D numbers and \COUNTERS.
+%D
+%D \starttyping
+%D \dostepwiserecurse {1} {10} {2} {...}
+%D \dostepwiserecurse {10} {1} {-2} {...}
+%D \stoptyping
+%D
+%D Because the simple case is used often, we implement it
+%D more efficiently:
+
+\unexpanded\def\dorecurse#1%
+ {\ifcase#1\relax
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\syst_helpers_recurse_y
+ \else
+ \expandafter\syst_helpers_recurse_x
+ \fi{#1}}
+
+\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\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
+ \let\recurselevel\!!plusone
+ #2%
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \global\advance\outerrecurse \minusone}
+
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_recurse_indeed_nop
+ \else
+ \def\recurselevel{#1}%
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
+ \fi\expandafter{\the\numexpr\recurselevel+\plusone\relax}{#2}}
+
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
+ {\ifnum#1>#2\relax
+ \expandafter\syst_helpers_recurse_indeed_nop
+ \else
+ \def\recurselevel{#1}%
+ \innerrecurse#1\advance\innerrecurse\plusone
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
+ \fi\expandafter{\the\innerrecurse}{#2}}
+
+\unexpanded\def\syst_helpers_recurse_indeed_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_recurse_indeed}
+
+\unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3%
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \global\advance\outerrecurse \minusone }
+
+%D \macros
+%D {dowith}
+%D
+%D Here's a loop over whatever is in a list:
+%D
+%D \starttyping
+%D \dowith{a,b,c}{[#1]}
+%D \stoptyping
+
+\unexpanded\def\dowith#1#2%
+ {\def\syst_helpers_with##1{#2}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_with}
+
+%D \macros
+%D {doloop,exitloop}
+%D
+%D Sometimes loops are not determined by counters, but by
+%D (a combinations of) conditions. We therefore implement a
+%D straightforward loop, which can only be left when we
+%D explictly exit it. Nesting is supported. First we present
+%D a more extensive alternative.
+%D
+%D \starttyping
+%D \doloop
+%D {Some kind of typesetting punishment \par
+%D \ifnum\pageno>100 \exitloop \fi}
+%D \stoptyping
+%D
+%D When needed, one can call for \type{\looplevel} and
+%D \type{\loopdepth}.
+
+\let\endofloop\donothing % maybe \syst_helpers_loop_end
+
+\unexpanded\def\doloop#1%
+ {\global\advance\outerrecurse \plusone
+ \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#1}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
+
+\unexpanded\def\syst_helpers_loop#1%
+ {\def\recurselevel{#1}%
+ \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}}
+
+\unexpanded\def\syst_helpers_loop_yes
+ {\syst_helpers_recurse_content
+ \endofloop}
+
+\unexpanded\def\syst_helpers_loop_nop#1%
+ {\let\endofloop\syst_helpers_loop % new, permits nested \doloop's
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \global\advance\outerrecurse\minusone}
+
+\unexpanded\def\exitloop % \exitloop quits at end
+ {\let\endofloop\syst_helpers_loop_nop}
+
+\unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly
+ {\syst_helpers_loop_nop}
+
+%D The loop is executed at least once, so beware of situations
+%D like:
+%D
+%D \starttyping
+%D \doloop {\exitloop some commands}
+%D \stoptyping
+%D
+%D It's just a matter of putting the text into the \type{\if}
+%D statement that should be there anyway, like in:
+%D
+%D \starttyping
+%D \doloop {\ifwhatever \exitloop \else some commands\fi}
+%D \stoptyping
+%D
+%D You can also quit a loop immediately, by using \type
+%D {\exitloopnow} instead. Beware, this is more sensitive
+%D for conditional errors.
+
+%D Krzysztof Leszczynski suggested to provide access to the level by
+%D means of a \type {#1}. I decided to pass the more frequently used
+%D level as \type {#1} and the less favoured depth as \type {#2}. The
+%D intended usage is:
+%D
+%D \starttyping
+%D \dorecurse{3}{\definesymbol[test-#1][xx-#1]}
+%D
+%D \def\test{\dorecurse{3}{\definesymbol[test-##1][xx-##1]}} \test
+%D
+%D \symbol[test-1]\quad\symbol[test-2]\quad\symbol[test-3]
+%D \stoptyping
+%D
+%D Since the hashed arguments are expanded, we don't need tricky
+%D expansion here.
+%D
+%D \starttyping
+%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}}
+%D \stoptyping
+
+\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\recursedepth\expandafter\expandafter\expandafter\endcsname
+ \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}}
+
+\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\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
+ \let\recurselevel\!!plusone
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}%
+ \syst_helpers_recurse_content
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \global\advance\outerrecurse \minusone}
+
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+ {\global\advance\outerrecurse \plusone
+ \global\expandafter\def\csname\??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
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
+
+% faster
+
+% \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% {\global\advance\outerrecurse \plusone
+% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+% \csname @swr%
+% \ifnum#3>\zerocount
+% \ifnum#2<#1\else d\fi
+% \else\ifnum#3<\zerocount
+% \ifnum#1<#2\else r\fi
+% \fi\fi
+% \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}}
+
+% \let\@swr \syst_helpers_stepwise_exit
+% \let\@swrd\syst_helpers_stepwise_recurse
+% \let\@swrr\syst_helpers_stepwise_reverse
+
+\installsystemnamespace{recursestepwise}
+
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+ {\global\advance\outerrecurse \plusone
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \csname\??recursestepwise
+ \ifnum#3>\zerocount
+ \ifnum#2<#1\else d\fi
+ \else\ifnum#3<\zerocount
+ \ifnum#1<#2\else r\fi
+ \fi\fi
+ \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}}
+ % \expandafter\endcsname\expandafter{\number#1\expandafter}\expandafter{\number#2\expandafter}\expandafter{\number#3}}
+
+\letvalue{\??recursestepwise }\syst_helpers_stepwise_exit
+\letvalue{\??recursestepwise d}\syst_helpers_stepwise_recurse
+\letvalue{\??recursestepwise r}\syst_helpers_stepwise_reverse
+
+% quite okay too, but untested
+%
+% \def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% {\global\advance\outerrecurse \plusone
+% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+% \normalexpanded
+% {\ifnum#3>\zerocount
+% \ifnum#2<#1
+% \syst_helpers_stepwise_exit
+% \else
+% \syst_helpers_stepwise_recurse
+% \fi
+% \else
+% \ifnum#3<\zerocount
+% \ifnum#1<#2
+% \syst_helpers_stepwise_exit
+% \else
+% \syst_helpers_stepwise_reverse
+% \fi
+% \else
+% \syst_helpers_stepwise_exit
+% \fi
+% \fi{\number#1}{\number#2}{\number#3}}}
+
+%D For special purposes:
+
+\newcount\fastloopindex
+\newcount\fastloopfinal
+
+\let\m_syst_helpers_fast_loop_cs\relax
+
+\unexpanded\def\dofastloopcs#1#2%
+ {\let\m_syst_helpers_fast_loop_cs#2%
+ \fastloopindex\plusone
+ \fastloopfinal#1\relax
+ \syst_helpers_fast_loop_cs}
+
+\unexpanded\def\syst_helpers_fast_loop_cs
+ {\ifnum\fastloopindex>\fastloopfinal
+ \let\m_syst_helpers_fast_loop_cs\relax
+ \else
+ \m_syst_helpers_fast_loop_cs
+ \advance\fastloopindex\plusone
+ \expandafter\syst_helpers_fast_loop_cs
+ \fi}
+
+% Helper:
+
+\unexpanded\def\resetrecurselevel{\let\recurselevel\!!zerocount}
+
+\let\recurselevel\!!zerocount
+
+% \appendtoks \resetrecurselevel \to \everydump
+
+%D \macros
+%D {doloopoverlist}
+%D
+%D \starttyping
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[\recursestring]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=\recursestring,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
+%D \stoptyping
+%D
+%D or:
+%D
+%D \starttyping
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[#1]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=##1,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
+%D \stoptyping
+
+\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
+ \global\advance\outerrecurse\minusone}
+
+%D \macros
+%D {newevery,everyline,EveryLine,EveryPar}
+%D
+%D Lets skip to something quite different. It's common use to use \type {\everypar}
+%D for special purposes. In \CONTEXT\ we use this primitive for locating sidefloats.
+%D This means that when user assignments to \type {\everypar} can interfere with
+%D those of the package. We therefore introduce \type {\EveryPar}.
+%D
+%D The same goes for \type {\EveryLine}. Because \TEX\ offers no \type {\everyline}
+%D primitive, we have to call for \type {\everyline} when we are working on a line
+%D by line basis. Just by calling \type {\EveryPar{}} and \type {\EveryLine{}} we
+%D restore the old situation.
+
+% \dorecurse{2}{
+% \expanded{\everypar{before \recurselevel\space}}
+% \EveryPar{x } [before \recurselevel\space x] \par
+% \EveryPar{y } [before \recurselevel\space y] \par
+% \EveryPar{} [before \recurselevel] \par
+% \EveryPar{x } \EveryPar{y } \EveryPar{} [before \recurselevel] \par
+% \EveryPar{y } \everypar{before } [before] \par
+% }
+
+\installsystemnamespace{extraevery}
+
+% \unexpanded\def\newevery#1#2%
+% {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
+% \ifx#2\relax\else\ifdefined#2\else
+% \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname
+% \def#2{\syst_helpers_every#1}%
+% \fi\fi}
+%
+% \unexpanded\def\syst_helpers_every#1%
+% {\expandafter\removetoks\expandafter\the\csname\??extraevery\csstring#1\endcsname\from#1%
+% \expandafter\appendtoks\expandafter\the\csname\??extraevery\csstring#1\endcsname\to #1%
+% \csname\??extraevery\csstring#1\endcsname}
+
+\unexpanded\def\newevery#1#2%
+ {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
+ \ifx#2\relax\else\ifdefined#2\else
+ \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname
+ \edef#2{\syst_helpers_every#1\csname\??extraevery\csstring#1\endcsname}%
+ \fi\fi}
+
+\unexpanded\def\syst_helpers_every#1#2%
+ {\removetoks\the#2\from#1%
+ \appendtoks\the#2\to #1%
+ #2}
+
+%D This one permits definitions like:
+
+\newevery \everypar \EveryPar % we get a warning which is ok
+\newevery \everyline \EveryLine
+
+%D and how about:
+
+% \newtoks \neverypar
+% \newtoks \neveryendpar
+%
+% \normalprotected\def\syst_helpers_forgotten_endpar
+% {\the\neveryendpar\normalpar}
+%
+% \unexpanded\def\forgeteverypar
+% {\everypar{\the\neverypar}%
+% \let\endpar\syst_helpers_forgotten_endpar}
+%
+% \unexpanded\def\finishpar
+% {\ifvmode\else\par\fi}
+
+\newtoks \neverypar
+
+\unexpanded\def\forgeteverypar
+ {\everypar{\the\neverypar}}
+
+%D Which we're going to use indeed! When the second argument
+%D equals \type {\relax}, the first token list is created
+%D unless it is already defined.
+
+%D Technically spoken we could have used the method we are
+%D going to present in the visual debugger. First we save
+%D the primitive \type{\everypar}:
+%D
+%D \starttyping
+%D \let\normaleverypar=\everypar
+%D \stoptyping
+%D
+%D Next we allocate a \TOKENLIST\ named \type{\everypar},
+%D which means that \type{\everypar} is no longer a primitive
+%D but something like \type{\toks44}.
+%D
+%D \starttyping
+%D \newtoks\everypar
+%D \stoptyping
+%D
+%D Because \TEX\ now executes \type{\normaleverypar} instead
+%D of \type{\everypar}, we are ready to assign some tokens to
+%D this internally known and used \TOKENLIST.
+%D
+%D \starttyping
+%D \normaleverypar={all the things the system wants to do \the\everypar}
+%D \stoptyping
+%D
+%D Where the user can provide his own tokens to be expanded
+%D every time he expects them to expand.
+%D
+%D \starttyping
+%D \everypar={something the user wants to do}
+%D \stoptyping
+%D
+%D We don't use this method because it undoubtly leads to
+%D confusing situations, especially when other packages are
+%D used, but it's this kind of tricks that make \TEX\ so
+%D powerful.
+
+%D \macros
+%D {convertargument,convertcommand,convertvalue}
+%D
+%D Some persistent experimenting led us to the next macro. This
+%D macro converts a parameter or an expanded macro to it's
+%D textual meaning.
+%D
+%D \starttyping
+%D \convertargument ... \to \command
+%D \stoptyping
+%D
+%D For example,
+%D
+%D \starttyping
+%D \convertargument{one \two \three{four}}\to\ascii
+%D \stoptyping
+%D
+%D The resulting macro \type{\ascii} can be written to a file
+%D or the terminal without problems. In \CONTEXT\ we use this
+%D macro for generating registers and tables of contents.
+%D
+%D The second conversion alternative accepts a command:
+%D
+%D \starttyping
+%D \convertcommand\command\to\ascii
+%D \stoptyping
+%D
+%D Both commands accept the prefix \type{\doglobal} for global
+%D assignments.
+
+\unexpanded\def\convertvalue#1\to
+ {\expandafter\convertcommand\csname#1\endcsname\to}
+
+\unexpanded\def\defconvertedvalue#1#2% less sensitive for \to
+ {\expandafter\defconvertedcommand\expandafter#1\csname#2\endcsname}
+
+%D \macros
+%D {doifassignmentelse}
+%D
+%D A lot of \CONTEXT\ commands take optional arguments, for
+%D instance:
+%D
+%D \starttyping
+%D \dothisorthat[alfa,beta]
+%D \dothisorthat[first=foo,second=bar]
+%D \dothisorthat[alfa,beta][first=foo,second=bar]
+%D \stoptyping
+%D
+%D Although a combined solution is possible, we prefer a
+%D seperation. The next command takes care of propper
+%D handling of such multi||faced commands.
+%D
+%D \starttyping
+%D \doifassignmentelse {...} {then ...} {else ...}
+%D \stoptyping
+
+\def\syst_helpers_check_if_assignment_else#1=#2#3\_e_o_p_{\if#2@}%
+
+\unexpanded\def\doifelseassignment#1% expandable
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifassignmentelse\doifelseassignment
+
+\newif\ifassignment
+
+\unexpanded\def\docheckassignment#1%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
+ \assignmentfalse
+ \else
+ \assignmenttrue
+ \fi}
+
+%D In \ETEX\ we can use \type {\detokenize} and gain some
+%D speed, but in general far less that 1\% for \type
+%D {\convertargument} and nil for \type {\convertcommand}.
+%D This macro is more robust than the pure \TEX\ one,
+%D something I found out when primitives like \type
+%D {\jobname} were fed (or something undefined).
+
+\unexpanded\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
+\unexpanded\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok
+
+\unexpanded\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}}
+\unexpanded\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}}
+\unexpanded\def\edefconvertedargument#1#2{\edef#1{#2}%
+ \edef#1{\detokenize\expandafter{#1}}}
+\unexpanded\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}}
+\unexpanded\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}}
+\unexpanded\def\xdefconvertedargument#1#2{\xdef#1{#2}%
+ \xdef#1{\detokenize\expandafter{#1}}}
+
+%D When you try to convert a primitive command, you'll find
+%D out that the \ETEX\ method fails on for instance \type
+%D {\jobname} in the sense that it returns the filename
+%D instead of just \type {\jobname}. So far this does not
+%D give real problems.
+
+%D This is typically a macro that one comes to after reading
+%D the \TEX book carefully. Even then, the definite solution
+%D was found after rereading the \TEX book. The first
+%D implementation was:
+%D
+%D \starttyping
+%D \def\doconvertargument#1->#2\\\\{#2}
+%D \stoptyping
+%D
+%D The \type{-}, the delimiter \type{\\\\} and the the second
+%D argument are completely redundant.
+
+%D \macros
+%D {showvalue}
+%D
+%D Ahandy macro, for testing purposes only:
+
+\unexpanded\def\showvalue#1%
+ {\ifcsname#1\endcsname
+ \expandafter\show\csname#1\endcsname
+ \else
+ \show\undefined
+ \fi}
+
+%D \macros
+%D {doifmeaningelse}
+%D
+%D We can use both commands in testing, but alas, not all
+%D meanings expand to something \type {->}. This is no problem
+%D in the \ETEX\ implementation, but since we want
+%D compatibility, we need:
+%D
+%D \starttyping
+%D \doifmeaningelse {\next} {\something} {true} {false}
+%D \stoptyping
+%D
+%D Watch the one level expansion of the second argument.
+
+\unexpanded\def\doifelsemeaning#1#2%
+ {\edef\m_syst_string_one{\meaning#1}%
+ \def \m_syst_string_two{#2}%
+ \edef\m_syst_string_two{\meaning\m_syst_string_two}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifmeaningelse\doifelsemeaning
+
+%D \macros
+%D {doifsamestringselse,doifsamestring,doifnotsamestring}
+%D
+%D The next comparison macro converts the arguments into
+%D expanded strings. This command can be used to compare for
+%D instance \type {\jobname} with a name stored in a macro.
+%D
+%D \starttyping
+%D \doifelse {\jobname}{oeps}{YES}{NO}
+%D \doifsamestringelse{\jobname}{oeps}{YES}{NO}
+%D \stoptyping
+
+\def\syst_helpers_if_samestring_else#1#2#3#4%
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#3}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#4}}}%
+ \ifx\m_syst_string_one\m_syst_string_two\expandafter#1\else\expandafter#2\fi}
+
+\unexpanded\def\doifelsesamestring{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument }
+\unexpanded\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument }
+
+\let\doifsamestringelse\doifelsesamestring
+
+%D \macros
+%D {ConvertToConstant,ConvertConstantAfter}
+%D
+%D When comparing arguments with a constant, we can get into
+%D trouble when this argument consists of tricky expandable
+%D commands. One solution for this is converting the
+%D argument to a string of unexpandable characters. To make
+%D comparison possible, we have to convert the constant too
+%D
+%D \starttyping
+%D \ConvertToConstant\doifelse {...} {...} {then ...} {else ...}
+%D \stoptyping
+%D
+%D This construction is only needed when the first argument
+%D can give troubles. Misuse can slow down processing.
+%D
+%D \starttyping
+%D \ConvertToConstant\doifelse{\c!alfa} {\c!alfa}{...}{...}
+%D \ConvertToConstant\doifelse{alfa} {\c!alfa}{...}{...}
+%D \ConvertToConstant\doifelse{alfa} {alfa} {...}{...}
+%D \ConvertToConstant\doifelse{alfa \alfa test}{\c!alfa}{...}{...}
+%D \stoptyping
+%D
+%D In examples~2 and~3 both arguments equal, in~1 and~4
+%D they differ.
+
+\unexpanded\def\ConvertToConstant#1#2#3%
+ {\edef\m_syst_string_one{\expandafter\detokenize\expandafter{#2}}%
+ \edef\m_syst_string_two{\expandafter\detokenize\expandafter{#3}}%
+ #1{\m_syst_string_one}{\m_syst_string_two}}
+
+%D When the argument \type{#1} consists of commands, we had
+%D better use
+%D
+%D \starttyping
+%D \ConvertConstantAfter\processaction[#1][...]
+%D \ConvertConstantAfter\doifelse{#1}{\v!something}{}{}
+%D \stoptyping
+%D
+%D This commands accepts things like:
+%D
+%D \starttyping
+%D \v!constant
+%D constant
+%D \hbox to \hsize{\rubish}
+%D \stoptyping
+%D
+%D As we will see in the core modules, this macro permits
+%D constructions like:
+%D
+%D \starttyping
+%D \setupfootertexts[...][...]
+%D \setupfootertexts[margin][...][...]
+%D \setupfootertexts[\v!margin][...][...]
+%D \stoptyping
+%D
+%D where \type{...} can be anything legally \TEX.
+
+\unexpanded\def\CheckConstantAfter#1#2%
+ {\expandafter\convertargument\v!prefix!\to\ascii
+ \convertargument#1\to#2\relax
+ \doifelseinstring\ascii{#2}
+ {\expandafter\convertargument#1\to#2}
+ {}}
+
+\unexpanded\def\ConvertConstantAfter#1#2#3%
+ {\CheckConstantAfter{#2}\asciia
+ \CheckConstantAfter{#3}\asciib
+ #1{\asciia}{\asciib}}
+
+%D \macros
+%D {assignifempty}
+%D
+%D We can assign a default value to an empty macro using:
+%D
+%D \starttyping
+%D \assignifempty \macros {default value}
+%D \stoptyping
+%D
+%D We don't explicitly test if the macro is defined.
+
+\unexpanded\def\assignifempty#1#2% can be sped up
+ {\doifsomething{#1}{\def#1{#2}}} % {\doifnot{#1}{}{\def#1{#2}}}
+
+%D \macros
+%D {gobbleuntil,grabuntil,gobbleuntilrelax,
+%D processbetween,processuntil}
+%D
+%D In \TEX\ gobbling usually stand for skipping arguments, so
+%D here are our gobbling macros.
+%D
+%D In \CONTEXT\ we use a lot of \type{\start}||\type{\stop}
+%D like constructions. Sometimes, the \type{\stop} is used as a
+%D hard coded delimiter like in:
+%D
+%D \starttyping
+%D \unexpanded\def\startcommand#1\stopcommand%
+%D {... #1 ...}
+%D \stoptyping
+%D
+%D In many cases the \type{\start}||\type{\stop} pair is
+%D defined at format generation time or during a job. This
+%D means that we cannot hardcode the \type{\stop} criterium.
+%D Only after completely understanding \type{\csname} and
+%D \type{\expandafter} I was able to to implement a solution,
+%D starting with:
+%D
+%D \starttyping
+%D \grabuntil{stop}\command
+%D \stoptyping
+%D
+%D This commands executes, after having encountered
+%D \type {\stop} the command \type {\command}. This command
+%D receives as argument the text preceding the \type {\stop}.
+%D This means that:
+%D
+%D \starttyping
+%D \unexpanded\def\starthello%
+%D {\grabuntil{stophello}\message}
+%D
+%D \starthello Hello world!\stophello
+%D \stoptyping
+%D
+%D results in: \type{\message{Hello world!}}.
+
+\let\syst_helpers_grab_indeed\relax
+
+\unexpanded\def\syst_helpers_grab#1#2%
+ {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed}
+
+\unexpanded\def\grabuntil#1%
+ {\expandafter\syst_helpers_grab\expandafter{\csname#1\endcsname}}
+
+%D The next command build on this mechanism:
+%D
+%D \starttyping
+%D \processbetween{string}\command
+%D \stoptyping
+%D
+%D Here:
+%D
+%D \starttyping
+%D \processbetween{hello}\message
+%D \starthello Hello again!\stophello
+%D \stoptyping
+%D
+%D leads to: \type{\message{Hello again!}}. The command
+%D
+%D \starttyping
+%D \gobbleuntil{sequence}
+%D \stoptyping
+%D
+%D is related to these commands. This one simply throws away
+%D everything preceding \type{\command}.
+
+\let\syst_helpers_gobble_indeed\relax
+
+\unexpanded\def\processbetween#1#2%
+ {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}}
+
+\unexpanded\def\gobbleuntil#1%
+ {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed}
+
+\unexpanded\def\gobbleuntilrelax#1\relax
+ {}
+
+%D The next one simply expands the pickup up tokens.
+%D
+%D \starttyping
+%D \processuntil{sequence}
+%D \stoptyping
+
+\let\syst_helpers_until_indeed\relax
+
+\unexpanded\def\processuntil#1%
+ {\def\syst_helpers_until_indeed##1#1{##1}\syst_helpers_until_indeed}
+
+%D \macros
+%D {groupedcommand}
+%D
+%D Commands often manipulate argument as in:
+%D
+%D \starttyping
+%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 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
+%D The next macro offers a solution for both unwanted
+%D situations:
+%D
+%D \starttyping
+%D \groupedcommand {before} {after}
+%D \stoptyping
+%D
+%D Which can be used like:
+%D
+%D \starttyping
+%D \def\cite%
+%D {\groupedcommand{\rightquote\rightquote}{\leftquote\leftquote}}
+%D \stoptyping
+%D
+%D This command is equivalent to, but more 'robust' than:
+%D
+%D \starttyping
+%D \def\cite#1%
+%D {\rightquote\rightquote#1\leftquote\leftquote}
+%D \stoptyping
+%D
+%D \starttyping
+%D \def\rightword%
+%D {\groupedcommand{\hfill\hbox}{\parfillskip\zeropoint}}
+%D
+%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
+%D \starttyping
+%D to be \bold{bold} or not, that's the question
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D to be {\bold bold} or not, that's the question
+%D \stoptyping
+%D
+%D This alternative checks for a \type {\bgroup} token first. The internal
+%D alternative does not accept the box handling mentioned before, but further
+%D nesting works all right. The extra \type {\bgroup}||\type {\egroup} is needed to
+%D keep \type {\m_syst_helpers_handle_group_after} both into sight and local.
+
+\let\m_syst_helpers_handle_group_after \relax
+\let\m_syst_helpers_handle_group_before\relax
+
+% keep:
+%
+% \unexpanded\def\syst_helpers_handle_group_normal#1#2%
+% {\bgroup
+% \def\m_syst_helpers_handle_group_before{\bgroup#1\bgroup\aftergroup\m_syst_helpers_handle_group_after}% can't we remove the second \bgroup
+% \def\m_syst_helpers_handle_group_after {#2\egroup\egroup}% and one \egroup here?
+% \afterassignment\m_syst_helpers_handle_group_before
+% \let\next=}
+
+\unexpanded\def\syst_helpers_handle_group_normal#1#2%
+ {\bgroup
+ \def\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}
+
+% keep:
+%
+% \unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference)
+% {\bgroup
+% %def\m_syst_helpers_handle_group_before{\bgroup#1\aftergroup\m_syst_helpers_handle_group_after}% interferes
+% \def\m_syst_helpers_handle_group_before{\bgroup\aftergroup\m_syst_helpers_handle_group_after#1}%
+% \def\m_syst_helpers_handle_group_after {#2\egroup}%
+% \afterassignment\m_syst_helpers_handle_group_before
+% \let\next=}
+
+\unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference)
+ {\bgroup
+ \def\m_syst_helpers_handle_group_before{#1}%
+ \def\m_syst_helpers_handle_group_after {#2}%
+ \afterassignment\m_syst_helpers_handle_group_simple_before
+ \let\next=}
+
+\def\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}
+
+%D I considered it a nuisance that
+%D
+%D \starttyping
+%D \color[green]
+%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:
+
+\unexpanded\def\groupedcommand#1#2%
+ {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+
+\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}}}
+
+%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:
+%D
+%D \starttyping
+%D \def\BoldRaggedCenter%
+%D {\groupedcommand{\raggedcenter\bf}{\par}}
+%D \stoptyping
+
+%D \macros
+%D {checkdefined}
+%D
+%D The bigger the system, the greater the change that
+%D user defined commands collide with those that are part of
+%D the system. The next macro gives a warning when a command is
+%D already defined. We considered blocking the definition, but
+%D this is not always what we want.
+%D
+%D \starttyping
+%D \checkdefined {category} {class} {command}
+%D \stoptyping
+%D
+%D The user is warned with the suggestion to use
+%D \type{CAPITALS}. This suggestion is feasible, because
+%D \CONTEXT only defines lowcased macros.
+
+\unexpanded\def\showdefinederror#1#2%
+ {\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}}
+
+\unexpanded\def\checkdefined#1#2#3%
+ {\doifdefined{#3}{\showdefinederror{#2}{#3}}}
+
+%D \macros
+%D {GotoPar,GetPar}
+%D
+%D Typesetting a paragraph in a special way can be done by
+%D first grabbing the contents of the paragraph and processing
+%D this contents grouped. The next macro for instance typesets
+%D a paragraph in boldface.
+%D
+%D \starttyping
+%D \def\remark#1\par%
+%D {\bgroup\bf#1\egroup}
+%D \stoptyping
+%D
+%D This macro has to be called like
+%D
+%D \starttyping
+%D \remark some text ... ending with \par
+%D \stoptyping
+%D
+%D Instead of \type{\par} we can of course use an empty line.
+%D When we started typesetting with \TEX, we already had
+%D produced lots of text in plain \ASCII. In producing such
+%D simple formatted texts, we adopted an open layout, and when
+%D switching to \TEX, we continued this open habit. Although
+%D \TEX\ permits a cramped and badly formatted source, it adds
+%D to confusion and sometimes introduces errors. So we prefer:
+%D
+%D \starttyping
+%D \remark
+%D
+%D some text ... ending with an empty line
+%D \stoptyping
+%D
+%D We are going to implement a mechanism that allows such open
+%D specifications. The definition of the macro handling
+%D \type{\remark} becomes:
+%D
+%D \starttyping
+%D \def\remark%
+%D {\BeforePar{\bgroup\bf}%
+%D \AfterPar{\egroup}%
+%D \GetPar}
+%D \stoptyping
+%D
+%D A macro like \type{\GetPar} can be defined in several
+%D ways. The recent version, the fourth one in a row,
+%D originally was far more complicated, but some functionality
+%D has been moved to other macros.
+%D
+%D We start with the more simple but in some cases more
+%D appropriate alternative is \type{\GotoPar}. This one leaves
+%D \type{\par} unchanged and is therefore more robust. On the
+%D other hand, \type{\AfterPar} is not supported.
+
+\newtoks\BeforePar
+\newtoks\AfterPar
+
+\def\redowithpar\par
+ {\doifelsenextchar\par\redowithpar\dodowithpar}%
+
+\def\dowithpar#1#2%
+ {\def\dodowithpar##1\par{#1##1#2}%
+ \redowithpar\par}
+
+\def\redogotopar\par
+ {\doifelsenextchar\par\redogotopar\dodogotopar}%
+
+\def\dogotopar#1%
+ {\def\dodogotopar{#1}%
+ \redogotopar\par}
+
+\def\dogotoparcs#1%
+ {\let\dodogotopar#1%
+ \redogotopar\par}
+
+\unexpanded\def\GetPar
+ {\expanded
+ {\dowithpar
+ {\the\BeforePar
+ \BeforePar\emptytoks}
+ {\the\AfterPar
+ \BeforePar\emptytoks
+ \AfterPar\emptytoks}}}
+
+\unexpanded\def\GotoPar
+ {\expanded
+ {\dogotopar
+ {\the\BeforePar
+ \BeforePar\emptytoks}}}
+
+%D \macros
+%D {dowithpargument,dowithwargument}
+%D
+%D The next macros are a variation on \type{\GetPar}. When
+%D macros expect an argument, it interprets a grouped sequence
+%D of characters a one token. While this adds to robustness and
+%D less ambiguous situations, we sometimes want to be a bit
+%D more flexible, or at least want to be a bit more tolerant
+%D to user input.
+%D
+%D We start with a commands that acts on paragraphs. This
+%D command is called as:
+%D
+%D \starttyping
+%D \dowithpargument\command
+%D \dowithpargument{\command ... }
+%D \stoptyping
+%D
+%D In \CONTEXT\ we use this one to read in the titles of
+%D chapters, sections etc. The commands responsible for these
+%D activities accept several alternative ways of argument
+%D passing. In these examples, the \type{\par} can be omitted
+%D when an empty line is present.
+%D
+%D \starttyping
+%D \command{...}
+%D \command ... \par
+%D \command
+%D {...}
+%D \command
+%D ... \par
+%D \stoptyping
+
+\let\syst_helpers_next_par\relax
+\let\syst_helpers_next_arg\relax
+
+\unexpanded\def\dowithpargument#1%
+ {\def\syst_helpers_next_par##1 \par{#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifelsenextbgroup\syst_helpers_next_arg{\doifelsenextchar\par{#1{}}\syst_helpers_next_par}}
+
+%D The \type{p} in the previous command stands for paragraph.
+%D When we want to act upon words we can use the \type{w}
+%D alternative.
+%D
+%D \starttyping
+%D \dowithwargument\command
+%D \dowithwargument{... \command ...}
+%D \stoptyping
+%D
+%D The main difference bwteen two alternatives is in the
+%D handling of \type{\par}'s. This time the space token acts
+%D as a delimiter.
+%D
+%D \starttyping
+%D \command{...}
+%D \command ...
+%D \command
+%D {...}
+%D \command
+%D ...
+%D \stoptyping
+
+\let\syst_helpers_next_war\relax
+\let\syst_helpers_next_arg\relax
+
+\unexpanded\def\dowithwargument#1%
+ {\def\syst_helpers_next_war##1 {#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifelsenextbgroup\syst_helpers_next_arg\syst_helpers_next_war}
+
+%D \macros
+%D {dorepeat,dorepeatwithcommand}
+%D
+%D When doing repetitive tasks, we stromgly advice to use
+%D \type{\dorecurse}. The next alternative however, suits
+%D better some of the \CONTEXT\ interface commands.
+%D
+%D \starttyping
+%D \dorepeat[n*\command]
+%D \stoptyping
+%D
+%D The value of the used \COUNTER\ can be called within
+%D \type{\command} by \type{\repeater}.
+%D
+%D A slightly different alternative is:
+%D
+%D \starttyping
+%D \dorepeatwithcommand[n*{...}]\command
+%D \stoptyping
+%D
+%D When we call for something like:
+%D
+%D \starttyping
+%D \dorepeatwithcommand[3*{Hello}]\message
+%D \stoptyping
+%D
+%D we get ourselves three \type{\message{Hello}} messages in
+%D a row. In both commands, the \type{n*} is optional. When this
+%D specification is missing, the command executes once.
+
+\unexpanded\def\dorepeatwithcommand[#1]%
+ {\syst_helpers_repeat_with_command#1*\empty*\relax}
+
+\def\syst_helpers_repeat_with_command#1*#2#3*#4\relax#5%
+ {\ifx#2\empty\syst_helpers_repeat_with_command_again[#1]#5\else\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5\fi}
+
+\def\syst_helpers_repeat_with_command_indeed#1#2#3#4%
+ {\ifx#2\empty % redundant but gives cleaner extensions
+ #4{#1}%
+ \else\ifnum#1<\zerocount
+ %\normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}%
+ \dorecurse{-#1}{#4{-#2#3}}%
+ \else\ifx#2+%
+ \dorecurse{#1}{#4{#3}}%
+ \else
+ \dorecurse{#1}{#4{#2#3}}%
+ \fi\fi\fi}
+
+\def\syst_helpers_repeat_with_command_again[#1]#2%
+ {#2{#1}}
+
+%D The extension hook permits something like:
+%D
+%D \starttyping
+%D \bgroup
+%D
+%D \catcode`\*=\superscriptcatcode
+%D
+%D \gdef\syst_helpers_repeat_with_command_again[#1]%
+%D {\redodorepeatwithcommand#1*\empty*\relax}
+%D
+%D \gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
+%D {\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5}
+%D
+%D \egroup
+%D \stoptyping
+%D
+%D although one may wonder if changing the catcode of \type {*} is wise.
+
+%D \macros
+%D {doifstringinstringelse}
+%D
+%D The next macro is meant for situations where both strings
+%D are macros. This save some unneeded expansion.
+%D
+%D \starttyping
+%D \def\doifstringinstringelse#1#2%
+%D {\syst_helpers_do_if_in_string_else#1#2%
+%D \expandafter\firstoftwoarguments
+%D \else
+%D \expandafter\secondoftwoarguments
+%D \fi}
+%D \stoptyping
+%D
+%D A bit faster is:
+
+\def\syst_helpers_if_instring_else_indeed#1%
+ {\if#1@%
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifelsestringinstring#1#2%
+ {\expandafter\def\expandafter\syst_helpers_if_instring_else\expandafter##\expandafter1#1##2##3\_e_o_s_
+ {\syst_helpers_if_instring_else_indeed##2}%
+ \expandafter\expandafter\expandafter\syst_helpers_if_instring_else\expandafter#2#1@@\_e_o_s_}
+
+\let\doifstringinstringelse\doifelsestringinstring
+
+%D \macros
+%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce,
+%D doifintokselse,flushtoks,dotoks}
+%D
+%D We use \TOKENLISTS\ sparsely within \CONTEXT, because the
+%D comma separated lists are more suitable for the user
+%D interface. Nevertheless we have:
+%D
+%D \starttyping
+%D (\doglobal) \appendtoks ... \to\tokenlist
+%D (\doglobal) \prependtoks ... \to\tokenlist
+%D (\doglobal) \flushtoks\tokenlist
+%D \dotoks\tokenlist
+%D \stoptyping
+%D
+%D These macros are clones of the ones implemented in page~378 of
+%D Knuth's \TeX book.
+
+\newtoks\t_syst_helpers_scratch
+\let \m_syst_helpers_scratch\empty
+
+% no longer \def but \let to target toks .. the space gobbling \relax will go
+
+% \unexpanded\def\appendtoks {\syst_helpers_append_toks \relax}
+% \unexpanded\def\prependtoks {\syst_helpers_prepend_toks \relax}
+% \unexpanded\def\appendtoksonce {\syst_helpers_append_toks_once \relax}
+% \unexpanded\def\prependtoksonce{\syst_helpers_prepend_toks_once\relax}
+%
+% \def\syst_helpers_append_toks_indeed
+% {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\m_syst_helpers_scratch\the\t_syst_helpers_scratch}}
+%
+% \def\syst_helpers_prepend_toks_indeed
+% {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\t_syst_helpers_scratch\the\m_syst_helpers_scratch}}
+%
+% \def\syst_helpers_append_toks#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+% \syst_helpers_append_toks_indeed}
+%
+% \def\syst_helpers_prepend_toks#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+% \syst_helpers_prepend_toks_indeed}
+%
+% \def\syst_helpers_append_toks_once#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+% \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+% \donothing
+% \syst_helpers_append_toks_indeed}
+%
+% \def\syst_helpers_prepend_toks_once#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+% \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+% \donothing
+% \syst_helpers_prepend_toks_indeed}
+
+\unexpanded\def\appendtoks#1\to#2%
+ {\toksapp#2{#1}%
+ \ifx\dodoglobal\relax\else
+ \global#2#2%
+ \fi}
+
+\unexpanded\def\prependtoks#1\to#2%
+ {\tokspre#2{#1}%
+ \ifx\dodoglobal\relax\else
+ \global#2#2%
+ \fi}
+
+\def\syst_helpers_append_toks_indeed
+ {\toksapp\m_syst_helpers_scratch\t_syst_helpers_scratch
+ \ifx\dodoglobal\relax\else
+ \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+ \fi}
+
+\def\syst_helpers_prepend_toks_indeed
+ {\tokspre\m_syst_helpers_scratch\t_syst_helpers_scratch
+ \ifx\dodoglobal\relax\else
+ \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+ \fi}
+
+\unexpanded\def\appendtoksonce#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch{#1}%
+ \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+ \donothing
+ \syst_helpers_append_toks_indeed}
+
+\unexpanded\def\prependtoksonce#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch{#1}%
+ \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+ \donothing
+ \syst_helpers_prepend_toks_indeed}
+
+%D The test macro:
+
+\unexpanded\def\doifelseintoks#1#2% #1 en #2 zijn toks
+ {\edef\asciia{\detokenize\expandafter{\the#1}}%
+ \edef\asciib{\detokenize\expandafter{\the#2}}%
+ \doifelsestringinstring\asciia\asciib}
+
+\let\doifintokselse\doifelseintoks
+
+%D Moved from \type{lxml-ini.tex} to here. This one is for generators that
+%D collect stuff piecewise, which is sometimes hard on mechanisms that
+%D grab content using delimiters:
+%D
+%D \starttyping
+%D \startcollecting
+%D \startcollect \bTABLE \stopcollect
+%D \startcollect \bTR \stopcollect
+%D \startcollect \bTD \stopcollect
+%D \startcollect foo\stopcollect
+%D \startcollect \eTD \stopcollect
+%D \startcollect \bTD \stopcollect
+%D \startcollect bar\stopcollect
+%D \startcollect \eTD \stopcollect
+%D \startcollect \eTR \stopcollect
+%D \startcollect \eTABLE \stopcollect
+%D \stopcollecting
+%D \stoptyping
+
+\newtoks \collectingtoks
+
+\unexpanded\def\startcollect #1\stopcollect {\toksapp \collectingtoks{#1}}
+\unexpanded\def\startexpandedcollect#1\stopexpandedcollect{\etoksapp\collectingtoks{#1}}
+
+\unexpanded\def\startcollecting{\collectingtoks\emptytoks}
+\unexpanded\def\stopcollecting {\the\collectingtoks}
+
+\unexpanded\def\collect {\toksapp \collectingtoks}
+\unexpanded\def\collectexpanded{\etoksapp\collectingtoks}
+
+%D A nice one too:
+
+% {\scratchtoks{abc} \removetoks b\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{abc} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{xaa} \removetoks x\from\scratchtoks [\the\scratchtoks]}
+% {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]}
+
+\unexpanded\def\removetoks#1\from#2%
+ {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3\_e_o_t_
+ {\def\m_syst_string_one{##3}%
+ \ifx\m_syst_string_one\empty#2{##1}\else#2{##1##2}\fi}%
+ \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty\_e_o_t_}
+
+%D Also:
+
+% \unexpanded\def\appendetoks #1\to{\normalexpanded{\appendtoks #1}\to}
+% \unexpanded\def\prependetoks#1\to{\normalexpanded{\prependtoks#1}\to}
+
+\unexpanded\def\appendetoks#1\to#2%
+ {\etoksapp#2{#1}%
+ \ifx\dodoglobal\relax\else
+ \global#2#2%
+ \fi}
+
+\unexpanded\def\prependetoks#1\to#2%
+ {\etokspre#2{#1}%
+ \ifx\dodoglobal\relax\else
+ \global#2#2%
+ \fi}
+
+%D Hm.
+
+\unexpanded\def\flushtoks#1% nb: can reassign to #1 again, hence the indirectness
+ {\t_syst_helpers_scratch#1\relax
+ \dodoglobal#1\emptytoks
+ \the\t_syst_helpers_scratch\relax}
+
+% better: \def\flushtoks#1{\normalexpanded{\noexpand\dodoglobal#1\emptytoks\the#\relax}}
+
+\let\dotoks\the
+
+%D \macros
+%D {beforesplitstring,aftersplitstring}
+%D
+%D These both commands split a string at a given point in two
+%D parts, so \type{x.y} becomes \type{x} or \type{y}.
+%D
+%D \starttyping
+%D \beforesplitstring test.tex\at.\to\filename
+%D \aftersplitstring test.tex\at.\to\extension
+%D \stoptyping
+%D
+%D The first routine looks (and is indeed) a bit simpler than
+%D the second one. The alternative looking more or less like
+%D the first one did not always give the results we needed.
+%D Both implementations show some insight in the manipulation
+%D of arguments.
+
+\let\syst_helpers_split_string\relax
+
+\unexpanded\def\beforesplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3\\%
+ {\def#3{##1}}%
+ \expandafter\syst_helpers_split_string#1#2#2\\}
+
+\unexpanded\def\aftersplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2@@@##3\\%
+ {\def#3{##2}}%
+ \expandafter\syst_helpers_split_string#1@@@#2@@@\\}
+
+%D \macros
+%D {splitstring,greedysplitstring}
+%D
+%D A bonus macro.
+
+\unexpanded\def\splitstring#1\at#2\to#3\and#4%
+ {\def\syst_helpers_split_string##1#2##2\empty\empty\empty##3\\%
+ {\def#3{##1}%
+ \def\syst_helpers_split_string{##3}%
+ \ifx\syst_helpers_split_string\empty
+ \let#4\empty
+ \else
+ \def#4{##2}%
+ \fi}%
+ \expandafter\syst_helpers_split_string#1\empty\empty\empty#2\empty\empty\empty\\}
+
+\unexpanded\def\greedysplitstring#1\at#2\to#3\and#4%
+ {\edef\asciib{#1}%
+ \let\asciic\asciib
+ \let#3\empty
+ \let#4\empty
+ \doloop
+ {\expandafter\splitstring\asciib\at#2\to\asciia\and\asciib
+ \ifx\asciib\empty
+ \exitloop
+ \else
+ % not \edef#3{\ifx#3\empty\else#3#2\fi\asciia} else
+ % /root/path fails because then #3==empty
+ \edef#3{\ifcase\recurselevel\or\else#3#2\fi\asciia}%
+ \let#4\asciib
+ \fi}%
+ \ifx#3\empty\let#3\asciic\fi}
+
+%D \macros
+%D {beforetestandsplitstring,
+%D aftertestandsplitstring,
+%D testandsplitstring}
+
+\unexpanded\def\beforetestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
+ {\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
+
+\unexpanded\def\aftertestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string ##1#2##2@@@##3##4\\%
+ {\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
+ \expandafter\syst_helpers_split_string #1@@@#2@@@\empty\\}
+
+\def\testandsplitstring#1\at#2\to#3\and#4%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
+ {\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}%
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
+
+%D \macros
+%D {removesubstring}
+%D
+%D A first application of the two routines defined above is:
+%D
+%D \starttyping
+%D \removesubstring-\from first-last\to\nothyphenated
+%D \stoptyping
+%D
+%D Which in terms of \TEX\ looks like:
+
+\unexpanded\def\removesubstring#1\from#2\to#3%
+ {\splitstring#2\to\m_syst_string_one\and\m_syst_string_two
+ \dodoglobal#3{\m_syst_string_one\m_syst_string_two}}
+
+%D \macros
+%D {appendtocommalist,prependtocommalist,
+%D addtocommalist,removefromcommalist}
+%D
+%D When working with comma separated lists, one sooner or
+%D later want the tools to append or remove items from such a
+%D list. When we add an item, we first check if it's already
+%D there. This means that every item in the list is unique.
+%D
+%D \starttyping
+%D \addtocommalist {alfa} \name
+%D \addtocommalist {beta} \name
+%D \addtocommalist {gamma} \name
+%D \removefromcommalist {beta} \name
+%D \stoptyping
+%D
+%D These commands can be prefixed with \type{\doglobal}. The
+%D implementation of the second command is more complecated,
+%D because we have to take leading spaces into account. Keep in
+%D mind that users may provide lists with spaces after the
+%D commas. When one item is left, we also have to get rid of
+%D trailing spaces.
+%D
+%D \starttyping
+%D \def\words{alfa, beta, gamma, delta}
+%D \def\words{alfa,beta,gamma,delta}
+%D \stoptyping
+%D
+%D Removing an item takes more time than adding one.
+%D
+%D A fast appending alternative, without any testing, is
+%D also provided:
+%D
+%D \starttyping
+%D \appendtocommalist {something} \name
+%D \prependtocommalist {something} \name
+%D \stoptyping
+%D
+%D This can be implemented as follows:
+%D
+%D \starttyping
+%D \def\appendtocommalist#1#2%
+%D {\ifx#2\empty
+%D \dodoglobal\edef#2{#1}%
+%D \else % no test on empty
+%D \dodoglobal\edef#2{#2,#1}%
+%D \fi}
+%D
+%D \def\prependtocommalist#1#2%
+%D {\ifx#2\empty
+%D \dodoglobal\edef#2{#1}%
+%D \else % no test on empty
+%D \dodoglobal\edef#2{#1,#2}%
+%D \fi}
+%D \stoptyping
+%D
+%D The faster alternatives are:
+
+\unexpanded\def\appendtocommalist#1#2%
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}
+
+\unexpanded\def\prependtocommalist#1#2%
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}
+
+\unexpanded\def\addtocommalist#1#2% {item} \cs
+ {\rawdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+\unexpanded\def\pretocommalist#1#2% {item} \cs
+ {\rawdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
+
+\unexpanded\def\robustdoifelseinset#1#2%
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#1}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#2}}}%
+ \rawdoifelseinset\m_syst_string_one\m_syst_string_two}
+
+\let\robustdoifinsetelse\robustdoifelseinset
+
+\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
+ {\robustdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+\unexpanded\def\robustpretocommalist#1#2% {item} \cs
+ {\robustdoifelseinset{#1}#2\resetglobal
+ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
+
+\unexpanded\def\xsplitstring#1#2% \cs {str}
+ {\def\syst_helpers_split_string##1,#2,##2,#2,##3\\%
+ {\edef\m_syst_string_one{\bcleanedupcommalist##1\empty\empty\relax}%
+ \edef\m_syst_string_two{\acleanedupcommalist##2,,\relax}}%
+ \expandafter\syst_helpers_split_string\expandafter,#1,,#2,,#2,\\}
+
+\def\bcleanedupcommalist#1#2#3\relax{\if#1,\else#1\fi\if#2,\else#2\fi#3}
+\def\bcleanedupcommalist#1#2\relax{\if#1,\else#1\fi#2}
+\def\acleanedupcommalist#1,,#2\relax{#1}
+
+\unexpanded\def\removefromcommalist#1#2% to be sped up
+ {\rawdoifelseinset{#1}#2%
+ {\normalexpanded{\xsplitstring\noexpand#2{#1}}%
+ \dodoglobal\edef#2%
+ {\ifx\m_syst_string_one\empty
+ \m_syst_string_two
+ \else
+ \m_syst_string_one\ifx\m_syst_string_two\empty\else,\m_syst_string_two\fi
+ \fi}}
+ \resetglobal}
+
+% \unexpanded\def\addtocommalist#1#2% upto 3 times slower
+% {\dodoglobal\edef#2{\ctxcommand{addtocommalist(\!!bs#1\!!es,\!!bs#2\!!es)}}}
+%
+% \unexpanded\def\removefromcommalist#1#2% faster and more robust
+% {\dodoglobal\edef#2{\ctxcommand{addtocommalist(\!!bs#1\!!es,\!!bs#2\!!es)}}}
+
+%D \macros
+%D {substituteincommalist}
+%D
+%D Slow but seldom used, so for the moment we stick to this
+%D implementation.
+%D
+%D \starttyping
+%D \substituteincommalist{old}{new}{list}
+%D \stoptyping
+
+\def\syst_helpers_substitute_in_comma_list_step#1%
+ {\edef\m_syst_string_three{#1}%
+ \ifx\m_syst_string_one\m_syst_string_three
+ \ifx\m_syst_string_two\empty \else
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi\m_syst_string_two}%
+ \fi
+ \else
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi#1}%
+ \fi}
+
+\unexpanded\def\substituteincommalist#1#2#3% old, new, list (slooow)
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \let\m_syst_string_four\empty
+ \normalexpanded{\rawprocesscommacommand[#3]}\syst_helpers_substitute_in_comma_list_step
+ \let#3\m_syst_string_four}
+
+%D \macros
+%D {replaceincommalist}
+%D
+%D The next macro can be used to replace an indexed element in a commalist:
+%D
+%D \starttyping
+%D \replaceincommalist\MyList{2}
+%D \stoptyping
+%D
+%D Element~2 will be replaced by the current meaning of the macro \type
+%D {\newcommalistelement}. The old meaning is saved in \type {\commalistelement}.
+%D The replacement honors grouped items, like in:
+%D
+%D \starttyping
+%D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,{b,c},d,e,f} \replaceincommalist\MyList{3}
+%D \def\MyList{a,b,c,{d,e,f}} \replaceincommalist\MyList{3}
+%D \stoptyping
+%D
+%D This macro was used in the bibtex code (and is probably no longer needed).
+
+\newcount\c_syst_helpers_comma_list_index
+\let \m_syst_helpers_comma_list_target\empty
+
+\let\newcommalistelement\empty
+
+\def\syst_helpers_replace_in_comma_list_step#1%
+ {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax
+ \ifx\newcommalistelement\empty\else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \let\m_syst_helpers_comma_list_target\newcommalistelement
+ \else
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
+ \m_syst_helpers_comma_list_target\expandafter\expandafter\expandafter
+ {\expandafter\m_syst_helpers_comma_list_target\expandafter,\newcommalistelement}%
+ \fi
+ \fi
+ \def\commalistelement{#1}%
+ \else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \ifx\nexttoken\bgroup % is known -)
+ \def\m_syst_helpers_comma_list_target{{#1}}%
+ \else
+ \def\m_syst_helpers_comma_list_target{#1}%
+ \fi
+ \else
+ \ifx\nexttoken\bgroup % is known -)
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,{#1}}%
+ \else
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,#1}%
+ \fi
+ \fi
+ \fi
+ \advance\commalistcounter\plusone}
+
+\unexpanded\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1
+ {\c_syst_helpers_comma_list_index#2\relax
+ \let\m_syst_helpers_comma_list_target\empty
+ \let\commalistelement\empty
+ \commalistcounter\plusone
+ \expandafter\processcommalist\expandafter[#1]\syst_helpers_replace_in_comma_list_step
+ \dodoglobal\let#1\m_syst_helpers_comma_list_target}
+
+%D \macros
+%D {globalprocesscommalist}
+%D
+%D The commalist processing commands are characterized by the
+%D fact that the way they handle expansion as well as the fact
+%D that they can be nested. This makes them kind of useless for
+%D handling comma lists in alignments. In these situations the
+%D next macro can be of use.
+
+\let\m_syst_helpers_comma_list_command_global\empty
+
+\def\syst_helpers_comma_list_command_global_step#1,%
+ {\if]#1\else
+ \m_syst_helpers_comma_list_command_global{#1}%
+ \expandafter\syst_helpers_comma_list_command_global_step
+ \fi}
+
+\unexpanded\def\globalprocesscommalist[#1]#2%
+ {\global\let\m_syst_helpers_comma_list_command_global#2%
+ \expandafter\syst_helpers_comma_list_command_global_step#1,],}
+
+%D \macros
+%D {withoutpt,PtToCm,
+%D numberofpoints,dimensiontocount}
+%D
+%D We can convert point into centimeters with:
+%D
+%D \starttyping
+%D \PtToCm{dimension}
+%D \stoptyping
+
+{\catcode`\.=\othercatcode
+ \catcode`\p=\othercatcode
+ \catcode`\t=\othercatcode
+ \gdef\WITHOUTPT#1pt{#1}}
+
+\def\withoutpt#1%
+ {\expandafter\WITHOUTPT#1}
+
+%D The capitals are needed because \type{p} and \type{t} have
+%D \CATCODE~12, while macronames only permit tokens with the
+%D \CATCODE~11. As a result we cannot use the \type{.group}
+%D primitives. Those who want to know more about this kind of
+%D manipulations, we advice to study the \TEX book in detail.
+%D Because this macro does not do any assignment, we can use it
+%D in the following way too.
+
+\def\PtToCm#1%
+ {\withoutpt\the\dimexpr0.0351459804\dimexpr#1\relax\relax cm}
+
+%D We also support:
+%D
+%D \starttyping
+%D \numberofpoints {dimension}
+%D \dimensiontocount {dimension} {\count}
+%D \stoptyping
+%D
+%D Both macros return a rounded number.
+
+% \dimensiontocount{10.49pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.49pt}
+% \dimensiontocount{10.51pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.51pt}
+
+\def\dimensiontocount#1#2{#2\numexpr\dimexpr#1\relax/\maxcard\relax}
+\def\numberofpoints #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax}
+
+%D \macros
+%D {swapdimens,swapcounts,swapmacros,
+%D globalswapdimens,globalswapcounts,globalswapmacros}
+%D
+%D Simple but effective are the next two macros. There name
+%D exactly states their purpose.
+
+\newdimen\d_syst_helpers_swapped
+\newcount\c_syst_helpers_swapped
+\let \m_syst_helpers_swapped\relax
+
+\unexpanded\def\swapdimens#1#2{\d_syst_helpers_swapped #1\relax#1#2\relax#2\d_syst_helpers_swapped}
+\unexpanded\def\swapcounts#1#2{\c_syst_helpers_swapped #1\relax#1#2\relax#2\c_syst_helpers_swapped}
+\unexpanded\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let #1#2\let #2\m_syst_helpers_swapped}
+
+\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global #1#2\global #2\d_syst_helpers_swapped}
+\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global #1#2\global #2\c_syst_helpers_swapped}
+\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\global\let#1#2\global\let#2\m_syst_helpers_swapped}
+
+%D \macros
+%D {pushmacro,popmacro}
+%D
+%D Premature and a bit of beta, we offer:
+%D
+%D \starttyping
+%D \pushmacro\macro
+%D \popmacro\macro
+%D \stoptyping
+%D
+%D Beware: global!
+
+\installsystemnamespace{localpushedmacro}
+\installsystemnamespace{globalpushedmacro}
+
+% \let\m_syst_helpers_push_macro\empty
+%
+% \unexpanded\def\globalpushmacro#1%
+% {\xdef\m_syst_helpers_push_macro{\string#1}%
+% \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \else
+% \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+% \fi
+% \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
+% \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
+%
+% \unexpanded\def\globalpopmacro#1%
+% {\xdef\m_syst_helpers_push_macro{\string#1}%
+% \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+% \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone}
+%
+% \unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
+% {\xdef\m_syst_helpers_push_macro{\string#1}%
+% \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \else
+% \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+% \fi
+% \global\advance\csname\??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}
+%
+% \unexpanded\def\localpopmacro#1%
+% {\xdef\m_syst_helpers_push_macro{\string#1}%
+% \expandafter\let\expandafter#1\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+% \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \minusone }
+%
+% \let\pushmacro\localpushmacro
+% \let\popmacro \localpopmacro
+%
+% slightly faster but more important: less tracing
+
+\let\m_syst_helpers_push_macro\empty
+
+\newcount\c_syst_helpers_pop_count
+
+\def\syst_helpers_push_macro_new_global
+ {\expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
+\def\syst_helpers_push_macro_new_local
+ {\expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
+\unexpanded\def\globalpushmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs\plusone
+ \else
+ \syst_helpers_push_macro_new_global
+ \fi
+ \global\expandafter\let\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}%
+ \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs\plusone
+ \else
+ \syst_helpers_push_macro_new_local
+ \fi
+ \global\expandafter\let\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
+ \expandafter\let\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}%
+ \c_syst_helpers_pop_count\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+ \global\advance\lastnamedcs \minusone
+ \expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
+
+\let\pushmacro\localpushmacro
+\let\popmacro \localpopmacro
+
+%D \macros
+%D {setlocalhsize,distributedhsize}
+%D
+%D Sometimes we need to work with the \type{\hsize} that is
+%D corrected for indentation and left and right skips. The
+%D corrected value is available in \type{\localhsize}, which
+%D needs to be calculated with \type{\setlocalhsize} first.
+%D
+%D \starttyping
+%D \setlocalhsize \hbox to \localhsize{...}
+%D \setlocalhsize[-1em] \hbox to \localhsize{...}
+%D \setlocalhsize[.5ex] \hbox to \localhsize{...}
+%D \stoptyping
+%D
+%D These examples show us that an optional can be used. The
+%D value provided is added to \type{\localhsize}.
+
+\newdimen\localhsize
+
+\unexpanded\def\setlocalhsize % don't change !
+ {\doifelsenextoptional
+ \syst_helpers_set_local_hsize_yes
+ \syst_helpers_set_local_hsize_nop}
+
+\def\syst_helpers_set_local_hsize_nop
+ {\localhsize\availablehsize}
+
+\def\syst_helpers_set_local_hsize_yes[#1]%
+ {\syst_helpers_set_local_hsize_nop
+ \advance\localhsize#1\relax}
+
+\def\availablehsize
+ {\dimexpr
+ \hsize-\leftskip-\rightskip
+ \ifnum\hangafter<\zerocount
+ \ifdim\hangindent>\zeropoint-\else+\fi\hangindent
+ \fi
+ \relax}
+
+\def\distributedhsize#1#2#3%
+ {\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax}
+
+\def\hsizefraction#1#2%
+ {\dimexpr#1/#2\relax}
+
+%D \macros
+%D {doifvalue,doifnotvalue,doifelsevalue,
+%D doifnothing,doifsomething,doifelsenothing,
+%D doifvaluenothing,doifvaluesomething,doifelsevaluenothing}
+%D
+%D These long named \type{\if} commands can be used to access
+%D macros (or variables) that are normally accessed by using
+%D \type{\getvalue}. Using these alternatives safes us three
+%D tokens per call. Anyone familiar with the not||values
+%D ones, can derive their meaning from the definitions.
+
+\unexpanded\def\doifvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsevalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifnothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifsomething#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsenothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifelsesomething#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\unexpanded\def\doifvaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifvaluesomething#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifelsevaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifvalueelse \doifelsevalue
+\let\doifnothingelse \doifelsenothing
+\let\doifsomethingelse \doifelsesomething
+\let\doifvaluenothingelse\doifelsevaluenothing
+
+%D \macros
+%D {doifemptyelsevalue, doifemptyvalue, doifnotemptyvalue}
+%D
+%D Also handy:
+
+\def\doifelseemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifemptyvalueelse\doifelseemptyvalue
+
+\def\doifemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotemptyvalue#1%
+ {\expandafter\ifx\csname#1\endcsname\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {doifallcommonelse}
+%D
+%D A complete match of two sets can be tested with
+%D \type {\doifallcommonelse}, where the first two
+%D arguments are sets.
+
+\def\syst_helpers_do_if_all_common_else#1#2#3#4% slow
+ {\def\syst_helpers_do_common_check_all##1%
+ {\doifnotinset{##1}{#4}\donefalse
+ \ifdone\else\expandafter\quitcommalist\fi}%
+ \donetrue
+ \processcommalist[#3]\syst_helpers_do_common_check_all
+ \ifdone\expandafter#1\else\expandafter#2\fi}
+
+\unexpanded\def\doifelseallcommon{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument }
+\unexpanded\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments }
+
+\let\doifallcommonelse\doifelseallcommon
+
+%D \macros
+%D {DOIF,DOIFELSE,DOIFNOT}
+%D
+%D \TEX\ is case sensitive. When comparing arguments, this
+%D feature sometimes is less desirable, for instance when we
+%D compare filenames. The next three alternatives upcase their
+%D arguments before comparing them.
+%D
+%D \starttyping
+%D \DOIF {string1} {string2} {...}
+%D \DOIFNOT {string1} {string2} {...}
+%D \DOIFELSE {string1} {string2} {then ...}{else ...}
+%D \stoptyping
+%D
+%D We have to use a two||step implementation, because the
+%D expansion has to take place outside \type{\uppercase}.
+%D
+%D These might end up as \LUA based helpers (i.e. consider these
+%D obsolete:
+
+\unexpanded\def\syst_helpers_do_IF#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_NOT#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_ELSE#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\syst_helpers_do_IF_INSTRING_ELSE#1#2%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}}% will become obsolete
+
+%D \macros
+%D {dosingleargumentwithset,
+%D dodoubleargumentwithset,dodoubleemptywithset,
+%D dotripleargumentwithset,dotripleemptywithset}
+%D
+%D These maybe too mysterious macros enable us to handle more
+%D than one setup at once.
+%D
+%D \starttyping
+%D \dosingleargumentwithset \command[#1]
+%D \dodoubleargumentwithset \command[#1][#2]
+%D \dotripleargumentwithset \command[#1][#2][#3]
+%D \dodoubleemptywithset \command[#1][#2]
+%D \dotripleemptywithset \command[#1][#2][#3]
+%D \stoptyping
+%D
+%D The first macro calls \type{\command[##1]} for each string
+%D in the set~\type{#1}. The second one calls for
+%D \type{\commando[##1][#2]} and the third, well one may guess.
+%D These commands support constructions like:
+%D
+%D \starttyping
+%D \def\dodefinesomething[#1][#2]%
+%D {\getparameters[\??xx#1][#2]}
+%D
+%D \unexpanded\def\definesomething%
+%D {\dodoubleargumentwithset\dodefinesomething}
+%D \stoptyping
+%D
+%D Which accepts calls like:
+%D
+%D \starttyping
+%D \definesomething[alfa,beta,...][variable=...,...]
+%D \stoptyping
+
+\let\m_syst_helpers_with_set_command\empty
+\let\syst_helpers_with_set_step \relax
+
+\def\syst_helpers_with_set_double[#1][#2]%
+ {\doifsomething{#1}
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
+
+\def\syst_helpers_with_set_triple[#1][#2][#3]%
+ {\doifsomething{#1}
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
+
+\def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command
+\def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command
+
+\def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command
+\def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command
+
+%D \macros
+%D {stripcharacters,stripspaces}
+%D
+%D The next command was needed first when we implemented
+%D the \CONTEXT\ interactivity macros. When we use labeled
+%D destinations, we often cannot use all the characters we
+%D want. We therefore strip some of the troublemakers, like
+%D spaces, from the labels before we write them to the
+%D \DVI||file, which passes them to for instance a PostScript
+%D file.
+%D
+%D \starttyping
+%D \stripspaces\from\one\to\two
+%D \stoptyping
+%D
+%D Both the old string \type{\one} and the new one \type{\two}
+%D are expanded. This command is a special case of:
+%D
+%D \starttyping
+%D \stripcharacter\char\from\one\to\two
+%D \stoptyping
+%D
+%D As we can see below, spaces following a control sequence are
+%D to enclosed in \type{{}}.
+
+\let\m_syst_helpers_strip_character\empty
+
+\unexpanded\def\stripcharacter#1\from#2\to#3%
+ {\def\syst_helpers_strip_character##1#1##2\end
+ {\edef\m_syst_helpers_strip_character{\m_syst_helpers_strip_character##1}%
+ \doifnotempty{##2}{\syst_helpers_strip_character##2\end}}%
+ \let\m_syst_helpers_strip_character\empty
+ \edef\m_syst_string_one{#2}%
+ \expandafter\syst_helpers_strip_character\m_syst_string_one#1\end
+ \dodoglobal\let#3\m_syst_helpers_strip_character}
+
+\unexpanded\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
+ {\stripcharacter{ }\from#1\to#2}
+
+%D \macros
+%D {unspacestring}
+%D
+%D The next macro does the same but is more compatible with other macros,
+%D like \type {\convert...}.
+
+\unexpanded\def\unspacestring#1\to#2%
+ {\stripcharacter{ }\from#1\to#2}
+
+%D \macros
+%D {executeifdefined}
+%D
+%D \CONTEXT\ uses one auxiliary file for all data concerning
+%D tables of contents, references, two||pass optimizations,
+%D sorted lists etc. This file is loaded as many times as
+%D needed. During such a pass we skip the commands thate are of
+%D no use at that moment. Because we don't want to come into
+%D trouble with undefined auxiliary commands, we call the
+%D macros in a way similar to \type{\getvalue}. The next macro
+%D take care of such executions and when not defined, gobbles
+%D the unwanted arguments.
+%D
+%D \starttyping
+%D \executeifdefined{name}\gobbleoneargument
+%D \stoptyping
+%D
+%D We can of course gobble more arguments using the
+%D appropriate gobbling command.
+
+\def\executeifdefined#1% #2 / never change this one again
+ {\ifcsname#1\endcsname
+ % \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D This one also has the advantage that it is fully
+%D expandable and that it can be used after an assignment.
+
+%D \macros
+%D {doifsomespaceelse}
+%D
+%D The next command checks a string on the presence of a space
+%D and executed a command accordingly.
+%D
+%D \starttyping
+%D \doifsomespaceelse {tekst} {then ...} {else ...}
+%D \stoptyping
+%D
+%D We use this command in \CONTEXT\ for determing if an
+%D argument must be broken into words when made interactive.
+%D Watch the use of \type{\noexpand}.
+
+%D Is this one still needed?
+
+\def\syst_helpers_if_some_space_else#1 #2#3\_e_o_s_{\if\noexpand#2@}
+
+\def\doifelsesomespace#1% % #2#3%
+ {\syst_helpers_if_some_space_else#1 @ @\_e_o_s_ % #3\else#2\fi}
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifsomespaceelse\doifelsesomespace
+
+%D \macros
+%D {processseparatedlist}
+%D
+%D Maybe a bit late, but here is a more general version of the
+%D \type{\processcommalist} command. This time we don't handle
+%D nesting but accept arbitrary seperators.
+%D
+%D \starttyping
+%D \processseparatedlist[list][separator]\command
+%D \stoptyping
+%D
+%D One can think of things like:
+%D
+%D \starttyping
+%D \processseparatedlist[alfa+beta+gamma][+]\message
+%D \stoptyping
+%D
+%D We want to handle all situations, like:
+%D
+%D \startbuffer
+%D \processseparatedlist[{aap noot}] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[{aap} {noot}][ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[aap {noot}] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \processseparatedlist[aap noot] [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Therefore we smuggle a \type {\relax} in front of the
+%D argument, which we remove afterwards.
+
+\let\syst_helpers_process_separated_list_step\relax
+
+\def\syst_helpers_process_separated_list#1]#2[#3]#4%
+ {\def\syst_helpers_process_separated_list_step##1##2#3%
+ {\def\m_syst_string_one{##2}% suggested by VZ
+ \if]##1%
+ \let\syst_helpers_process_separated_list_step\relax
+ \else\ifx\blankspace\m_syst_string_one
+ #4{##1}%
+ \else\if]##2%
+ \let\syst_helpers_process_separated_list_step\relax
+ \else
+ #4{##1##2}%
+ \fi\fi\fi
+ \syst_helpers_process_separated_list_step}%
+ \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3}
+
+\unexpanded\def\processseparatedlist[%
+ {\syst_helpers_process_separated_list\relax}
+
+%D \macros
+%D {processlist}
+%D
+%D An even more general list processing macro is the following one:
+%D
+%D \starttyping
+%D \processlist{beginsym}{endsym}{separator}\docommand list
+%D \stoptyping
+%D
+%D This one supports arbitrary open and close symbols as well as user
+%D defined separators.
+%D
+%D \starttyping
+%D \processlist(){=>}\docommand(a=>b=>c=>d)
+%D \stoptyping
+
+\let\syst_helpers_process_any_list \relax
+\let\syst_helpers_process_any_list_indeed\relax
+\let\syst_helpers_process_any_list_step \relax
+
+\unexpanded\def\processlist#1#2#3#4% no blank skipping !
+ {\def\syst_helpers_process_any_list_indeed##1#2%
+ {\def\syst_helpers_process_any_list_step####1####2#3%
+ {\ifx#2####1%
+ \let\syst_helpers_process_any_list_step\relax
+ \else\ifx#2####2%
+ \let\syst_helpers_process_any_list_step\relax
+ \else
+ #4{####1####2}%
+ \fi\fi
+ \syst_helpers_process_any_list_step}%
+ \expandafter\syst_helpers_process_any_list_step\gobbleoneargument##1#3#2#3}%
+ \def\syst_helpers_process_any_list#1%
+ {\syst_helpers_process_any_list_indeed\relax}%
+ \syst_helpers_process_any_list}
+
+%D \macros
+%D {processassignlist}
+%D
+%D Is possible to combine an assignment list with one
+%D containing keywords. Assignments are treated accordingly,
+%D keywords are treated by \type{\command}.
+%D
+%D \starttyping
+%D \processassignlist[...=...,...=...,...]\commando
+%D \stoptyping
+%D
+%D This command can be integrated in \type{\getparameters}, but
+%D we decided best not to do so.
+
+\unexpanded\def\processassignlist#1[#2]#3%
+ {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]%
+ {\doifnot{##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}
+
+%D \macros
+%D {untextargument
+%D untexcommand}
+%D
+%D When manipulating data(bases) and for instance generating
+%D index entries, the next three macros can be of help:
+%D
+%D \starttyping
+%D \untextargument{...}\to\name
+%D \untexcommand {...}\to\name
+%D \stoptyping
+%D
+%D They remove braces and backslashes and give us something to
+%D sort.
+
+\let\m_syst_helpers_untexed\empty
+
+\unexpanded\def\untexsomething
+ {\begingroup
+ \catcode\leftbraceasciicode \ignorecatcode
+ \catcode\rightbraceasciicode\ignorecatcode
+ \escapechar\minusone
+ \syst_helpers_untex_something}
+
+\def\syst_helpers_untex_something#1#2\to#3%
+ {\doglobal#1#2\to\m_syst_helpers_untexed
+ \endgroup
+ \let#3\m_syst_helpers_untexed}
+
+\unexpanded\def\untexargument{\untexsomething\convertargument}
+\unexpanded\def\untexcommand {\untexsomething\convertcommand}
+
+%D \macros
+%D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints}
+%D
+%D One characteristic of \POSTSCRIPT\ and \PDF\ is that both
+%D used big points (\TEX's bp). The next macros convert points
+%D and scaled points into big points.
+%D
+%D \starttyping
+%D \ScaledPointsToBigPoints {number} \target
+%D \ScaledPointsToWholeBigPoints {number} \target
+%D \stoptyping
+%D
+%D The magic factor $72/72.27$ can be found in most \TEX\
+%D related books.
+
+% \PointsToBigPoints{10.53940pt}\test \test
+% \PointsToBigPoints{10.53941pt}\test \test
+% \PointsToBigPoints{10.53942pt}\test \test
+
+% \PointsToWholeBigPoints{10.53940pt}\test \test
+% \PointsToWholeBigPoints{10.53941pt}\test \test
+% \PointsToWholeBigPoints{10.53942pt}\test \test
+
+\unexpanded\def\PointsToBigPoints#1#2%
+ {\edef#2{\withoutpt\the\dimexpr.996264\dimexpr#1\relax\relax}}
+
+\unexpanded\def\PointsToWholeBigPoints#1#2%
+ {\edef#2{\the\numexpr\dimexpr.996264\dimexpr#1\relax\relax/\maxcard\relax}}
+
+\unexpanded\def\ScaledPointsToBigPoints #1{\PointsToBigPoints {\number#1\scaledpoint}}
+\unexpanded\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}}
+
+%D \macros
+%D {PointsToReal}
+%D
+%D Points can be stripped from their suffix by using
+%D \type{\withoutpt}. The next macro enveloppes this macro.
+%D
+%D \starttyping
+%D \PointsToReal {dimension} \target
+%D \stoptyping
+
+\unexpanded\def\PointsToReal#1#2%
+ {\edef#2{\withoutpt\the\dimexpr#1}}
+
+%D \macros
+%D {dontleavehmode}
+%D
+%D Sometimes when we enter a paragraph with some command, the
+%D first token gets the whole first line. We can prevent this
+%D by saying:
+%D
+%D \starttyping
+%D \dontleavehmode
+%D \stoptyping
+%D
+%D This command is used in for instance the language module
+%D \type{lang-ini}. The first version was:
+%D
+%D \starttyping
+%D \def\dontleavehmode{\ifhmode\else\ifmmode\else$ $\fi\fi}
+%D \stoptyping
+%D
+%D Next, Taco came with a better alternative (using mathsurround):
+%D
+%D \starttyping
+%D \def\dontleavehmode
+%D {\ifhmode\else \ifmmode\else
+%D {\mathsurround\zeropoint\everymath\emptytoks$ $}%
+%D \fi \fi}
+%D \stoptyping
+%D
+%D And finaly we got the following alternative, one that avoids
+%D interfering grouping at the cost of a box.
+%D
+%D \starttyping
+%D \newbox\b_syst_helpers_dlh
+%D
+%D \unexpanded\def\dontleavehmode
+%D {\ifhmode\else \ifmmode\else
+%D \setbox\b_syst_helpers_dlh\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\b_syst_helpers_dlh
+%D \fi \fi}
+%D \stoptyping
+%D
+%D But, as we run a recent version of \TEX, we can use the new primitive:
+
+\ifdefined\normalquitvmode \let\dontleavehmode\normalquitvmode \fi
+
+%D \macros
+%D {utfupper, utflower, uppercasestring, lowercasestring}
+%D
+%D The names tell what they do:
+%D
+%D \starttyping
+%D \uppercasestring somestring\to\somestring
+%D \lowercasestring somestring\to\somestring
+%D \stoptyping
+%D
+%D The first argument may be a \type{\macro}.
+
+% \unexpanded\def\uppercasestring#1\to#2%
+% {\uppercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
+%
+% \unexpanded\def\lowercasestring#1\to#2%
+% {\lowercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
+
+%D These macros are sort of obsolete as we never use uppercase this
+%D way. But nevertheless we provide them:
+
+\def\utfupper#1{\clf_upper{#1}} % expandable
+\def\utflower#1{\clf_lower{#1}} % expandable
+
+\unexpanded\def\uppercasestring#1\to#2{\dodoglobal\edef#2{\clf_upper{#1}}}
+\unexpanded\def\lowercasestring#1\to#2{\dodoglobal\edef#2{\clf_lower{#1}}}
+
+%D \macros
+%D {handletokens}
+%D
+%D With the next macro we enter a critical area of macro
+%D expansion. What we want is a macro that looks like:
+%D
+%D \starttyping
+%D \handletokens some tokens\with \somemacro
+%D \stoptyping
+%D
+%D A bonus example:
+%D
+%D \starttyping
+%D \hbox{\handletokens tekst en meer tekst\with\ruledhbox}
+%D
+%D \def\weetikveel#1{\if#1\blankspace\space\else\ruledhbox{#1}\fi}
+%D
+%D \hbox{\handletokens tekst en meer tekst\with\weetikveel}
+%D \stoptyping
+
+%D \macros
+%D {counttoken,counttokens}
+%D
+%D For the few occasions that we want to know the number of
+%D specific tokens in a string, we can use:
+%D
+%D \starttyping
+%D \counttoken token\in string\to \somecount
+%D \counttokens string\to \somecount
+%D \stoptyping
+%D
+%D This macro, that for instance is used in \type{cont-tab},
+%D takes a real counter. The macro can be preceded by \type
+%D {\doglobal}.
+
+\def\syst_helpers_count_token#1% obeys {}
+ {\def\m_syst_string_three{#1}%
+ \ifx\m_syst_string_two\m_syst_string_three \else
+ \ifx\m_syst_string_one\m_syst_string_three
+ \advance\scratchcounter\plusone
+ \fi
+ \expandafter\syst_helpers_count_token
+ \fi}
+
+\unexpanded\def\counttoken#1\in#2\to#3%
+ {\scratchcounter\zerocount
+ \def\m_syst_string_one{#1}%
+ \def\m_syst_string_two{\end}%
+ \syst_helpers_count_token#2\end
+ \dodoglobal#3\scratchcounter}
+
+\unexpanded\def\counttokens#1\to#2%
+ {\scratchcounter\zerocount
+ \def\syst_helpers_count_token##1{\advance\scratchcounter\plusone}%
+ \handletokens#1\with\syst_helpers_count_token
+ \dodoglobal#2\scratchcounter}
+
+%D \macros
+%D {splitofftokens}
+%D
+%D Running this one not always gives the expected results.
+%D Consider for instance the macro for which I originally
+%D wrote this token handler.
+
+\unexpanded\def\splitofftokens#1\from#2\to#3% slow but hardly used
+ {\ifnum#1>\zerocount
+ \scratchcounter#1\relax
+ \def\syst_helpers_split_off_tokens##1%
+ {\ifnum\scratchcounter>\zerocount
+ \advance\scratchcounter \minusone
+ \edef#3{#3##1}%
+ \fi}%
+ % \let#3\empty % #3 can be #2, so:
+ \expandafter\let\expandafter#3\expandafter\empty
+ \expandafter\handletokens#2\with\syst_helpers_split_off_tokens
+ \else
+ \edef#3{#2}%
+ \fi}
+
+%D This macro can be called like:
+%D
+%D \startbuffer[example]
+%D \splitofftokens10\from01234567 890123456789\to\test [\test]
+%D \stopbuffer
+%D
+%D However, the characters that we expect to find in
+%D \type{\test} just don't show up there. The reason for this
+%D is not that logical but follows from \TEX's sometimes
+%D mysterious way of expanding. Look at this:
+%D
+%D \startbuffer[next]
+%D \def\next{a} \edef\test{\next} [\test]
+%D \let\next=b \edef\test{\test\next} [\test]
+%D \let\next=c \edef\test{\next} [\test]
+%D \let\next=d \edef\test{\test\next} [\test]
+%D \let\next=e \expandafter\edef\expandafter\test\expandafter{\test\next} [\test]
+%D \stopbuffer
+%D
+%D \typebuffer[next]
+%D
+%D Careful reading shows that inside an \type{\edef} macro's
+%D that are \type{\let} are not expanded!
+%D
+%D \unprotect\getbuffer[next]\protect
+%D
+%D That's why we finally end up with a macro that looks
+%D ahead by using an assignment, this time by using \type
+%D {\futurelet}, and grabbing an argument as well. That
+%D way we can handle the sentinal, a blank space and grouped
+%D tokens.
+
+\unexpanded\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface
+ {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed}
+
+\def\handletokens#1\with#2%
+ {\gdef\syst_helpers_handle_tokens_command{#2}% permits more complex #2's
+ \syst_helpers_handle_tokens#1\end}
+
+\def\syst_helpers_handle_tokens_indeed
+ {\ifx\nexthandledtoken\blankspace
+ \expandafter\syst_helpers_handle_tokens_indeed_one
+ \else\ifx\nexthandledtoken\end
+ \expandafter\expandafter\expandafter\gobbletwoarguments % also gobble the \end
+ \else
+ \expandafter\expandafter\expandafter\syst_helpers_handle_tokens_indeed_two
+ \fi\fi *}
+
+\def\syst_helpers_handle_tokens_indeed_one * %
+ {\syst_helpers_handle_tokens_command{ }\syst_helpers_handle_tokens}
+
+\def\syst_helpers_handle_tokens_indeed_two *#1%
+ {\syst_helpers_handle_tokens_command{#1}\syst_helpers_handle_tokens}
+
+%D This macro is tested on:
+%D
+%D \def\xxx#1{[#1]}
+%D
+%D \startlines
+%D \handletokens abc\with\xxx
+%D \handletokens a b c\with\xxx
+%D \handletokens a b c\with\xxx
+%D \handletokens a{bc}d\with\xxx
+%D \handletokens a\space bc \with\xxx
+%D \stoplines
+%D
+%D And our previous example shows up as:
+%D
+%D \getbuffer[example]
+
+%D \macros
+%D {iftrialtypesetting, ifvisible}
+%D
+%D The next boolean is at first sight a strange one. Sometimes
+%D one does a trial typesetting run, for instance to determine
+%D dimensions. Some mechanisms, like object inclusion, can fail
+%D on such trials. Temporary setting the next boolean to true,
+%D helps a lot. The second boolena can be used to inhibit
+%D processing completely.
+
+\newif\ifvisible \visibletrue
+
+\newtoks\everysettrialtypesetting
+\newtoks\everyresettrialtypesetting
+
+\unexpanded\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so
+\unexpanded\def\resettrialtypesetting{\the\everyresettrialtypesetting} % this one is seldom needed
+
+\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv !
+
+\appendtoks \let\iftrialtypesetting\iftrue \to \everysettrialtypesetting
+\appendtoks \let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting
+
+%D \macros
+%D {twodigitrounding}
+%D
+%D When using \type {\special}s or \type {\pdfliteral}s, it
+%D sometimes makes sense to limit the precission. The next
+%D macro rounds a real number to two digits. It takes one
+%D argument and only works in \ETEX.
+
+% \def\dointegerrounding #1.#2\relax {#1}
+% \def\doonedigitrounding #1.#2#3\relax {\ifx#2*#1\else#1.#2\fi}
+% \def\dotwodigitrounding #1.#2#3#4\relax {\ifx#2*#1\else#1.#2#3\fi}
+% \def\dothreedigitrounding#1.#2#3#4#5\relax{\ifx#2*#1\else#1.#2#3#4\fi}
+%
+% \def\integerrounding#1%
+% {\expandafter\expandafter\expandafter\dointegerrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.5\points \relax .\relax}
+% \def\onedigitrounding#1%
+% {\expandafter\expandafter\expandafter\doonedigitrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.05\points \relax 00.*0\relax}
+% \def\twodigitrounding#1%
+% {\expandafter\expandafter\expandafter\dotwodigitrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.005\points \relax 000.*00\relax}
+% \def\threedigitrounding#1%
+% {\expandafter\expandafter\expandafter\dothreedigitrounding\expandafter\WITHOUTPT\the\dimexpr#1\points+.0005\points\relax0000.*00\relax}
+
+\def\integerrounding #1{\clf_rounded\zerocount\numexpr#1\relax}
+\def\onedigitrounding #1{\clf_rounded\plusone \numexpr#1\relax}
+\def\twodigitrounding #1{\clf_rounded\plustwo \numexpr#1\relax}
+\def\threedigitrounding#1{\clf_rounded\plusthree\numexpr#1\relax}
+
+%D \macros
+%D {processcontent}
+%D
+%D This macro is first used in the tabulation macros.
+%D
+%D \starttyping
+%D \unexpanded\def\starthans%
+%D {\processcontent{stophans}\test{\message{\test}\wait}}
+%D \stoptyping
+
+\unexpanded\def\processcontent#1%
+ {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname}
+
+\unexpanded\def\syst_helpers_process_content#1#2#3%
+ {\unexpanded\def\syst_helpers_process_content##1#1%
+ {\endgroup\def#2{##1}#3}%
+ \syst_helpers_process_content}
+
+%D \macros
+%D {dogobblesingleempty, dogobbledoubleempty}
+%D
+%D These two macros savely grab and dispose two arguments.
+
+\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty}
+\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty}
+
+\def\syst_helpers_gobble_single_empty [#1]{}
+\def\syst_helpers_gobble_double_empty[#1][#2]{}
+
+\let\gobblesingleempty\dogobblesingleempty % also used
+\let\gobbledoubleempty\dogobbledoubleempty % also used
+
+%D \macros
+%D {@True, @False, @Not, @And}
+%D
+%D Some predicate logic functions, used in for instance the
+%D math module.
+
+% These have rather ugly names ... will change:
+
+\def\@True {00}
+\def\@False {01}
+\def\@Not #1{0\ifcase#11 \or\expandafter 1\else \expandafter 0\fi}
+\def\@And #1#2{0\ifcase#1#2 \expandafter 0\else \expandafter 1\fi}
+
+%D \macros
+%D {setdimensionwithunit, freezedimensionwithunit}
+%D
+%D The next assignments are all valid:
+%D
+%D \starttyping
+%D \setdimensionwithunit\scratchdimen{10} {cm}
+%D \setdimensionwithunit\scratchdimen{10cm}{cm}
+%D \setdimensionwithunit\scratchdimen{10cm}{}
+%D \freezedimensionwithunit\SomeWidth{\textwidth}
+%D \freezedimensionwithunit\SomeDepth{\dp\strutbox}
+%D \stoptyping
+%D
+%D As an alternative for the next macro we can use a global
+%D assignment inside a box. The \type{\empty}'s permits
+%D gobbling while preventing spurious \type{\relax}'s.
+
+\unexpanded\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick
+ {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty}
+
+\unexpanded\def\freezedimensionwithunit#1#2%
+ {\setdimensionwithunit\scratchdimen#1{#2}\edef#1{\the\scratchdimen}}
+
+%D \macros
+%D {doifsometokselse, doifsometoks}
+%D
+%D Not that fast I guess, but here's a way to test for token
+%D registers being empty.
+
+\unexpanded\def\doifelsesometoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\let\doifsometokselse\doifelsesometoks
+
+\unexpanded\def\doifsometoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doifemptytoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D \macros
+%D {startstrictinspectnextcharacter}
+%D
+%D This one if for Taco's bibliography module:
+
+\let\syst_helpers_normal_inspect_next_character\syst_helpers_inspect_next_character
+
+\def\syst_helpers_strict_inspect_next_character% no user macro !
+ {\ifx\nexttoken\charactertoken
+ \expandafter\m_syst_action_yes
+ \else
+ \expandafter\m_syst_action_nop
+ \fi}
+
+% better: push/pop
+
+\unexpanded\def\startstrictinspectnextcharacter
+ {\let\syst_helpers_inspect_next_character\syst_helpers_strict_inspect_next_character}
+
+\unexpanded\def\stopstrictinspectnextcharacter
+ {\let\syst_helpers_inspect_next_character\syst_helpers_normal_inspect_next_character}
+
+\unexpanded\def\strictdoifelsenextoptional#1#2%
+ {\startstrictinspectnextcharacter
+ \doifelsenextchar[{\stopstrictinspectnextcharacter#1}{\stopstrictinspectnextcharacter#2}}
+
+\let\strictdoifnextoptionalelse\strictdoifelsenextoptional
+
+%D \macros
+%D {gobblespacetokens}
+%D
+%D This macro needs a speed-up!
+
+%\def\gobblespacetokens
+% {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do !
+
+\def\gobblespacetokens
+ {\afterassignment\nexttoken\let\nexttoken=}
+
+%D \macros
+%D {verbatimargument}
+%D
+%D As the name says, this macro converts its argument to a
+%D (rather safe) string.
+
+\let\verbatimstring\detokenize
+
+%D These are needed in ordinal number conversions:
+
+\def\lastdigit#1%
+ {\expandafter\thelastdigit\number#1\relax}
+
+\def\thelastdigit#1#2%
+ {\ifx#2\relax#1\else\expandafter\thelastdigit\expandafter#2\fi}
+
+\def\lasttwodigits#1%
+ {\expandafter\thelasttwodigits\expandafter0\number#1\relax}
+
+\def\thelasttwodigits#1#2#3% 0 dig ... \relax
+ {\ifx#3\relax#1#2\else\expandafter\thelasttwodigits\expandafter#2\expandafter#3\fi}
+
+%D \macros
+%D {serializecommalist}
+%D
+%D Concatenate commalists:
+
+\let\syst_helpers_serialize_comma_list_step\relax
+
+\def\syst_helpers_serialize_comma_list_step#1%
+ {\edef\serializedcommalist{\serializedcommalist#1}}
+
+\unexpanded\def\serializecommalist[#1]%
+ {\let\serializedcommalist\empty
+ \processcommacommand[#1]\syst_helpers_serialize_comma_list_step}
+
+%D \macros
+%D {purenumber}
+%D
+%D Sometimes we need control over when \TEX\ stops reading a
+%D number, especially in full expandable macros where using
+%D \type {\relax} would lead to disasters.
+%D
+%D \starttyping
+%D \ifodd\purenumber{...}\space ... \else ... \fi
+%D \stoptyping
+%D
+%D Here we use a space as number delimiter in combination
+%D with a space- and relax-less \type {\purenumber}. This
+%D macro works ok with \type {\the}, \type {\number} as well
+%D as \ETEX's \type {\numexpr}.
+
+\def\purenumber#1{\expandafter\firstofoneargument\expandafter{\number#1}}
+
+%D \macros
+%D {filterfromvalue}
+%D
+%D \starttyping
+%D \setvalue{xx}{{A}{B}{C}}
+%D
+%D \filterfromvalue{xx}{3}{3}
+%D \filterfromvalue{xx}{3}{2}
+%D \filterfromvalue{xx}{3}{1}
+%D \stoptyping
+%D
+%D An alternative is to store 'max' in the list, say:
+%D
+%D \starttyping
+%D \setvalue{xx}{3{A}{B}{C}}
+%D
+%D \filterfromvalues{3}{xx}{3}
+%D \filterfromvalues{3}{xx}{2}
+%D \filterfromvalues{3}{xx}{1}
+%D \stoptyping
+%D
+%D I'll implement this when I'm in \quotation {writing dirty
+%D macros mood}.
+
+\def\dofilterfromstr#1#2% max n % no need to be fast
+ {\expandafter \expandafter \expandafter \csstring
+ \ifcase#1\or \ifcase#2\or
+ \firstofoneargument \else
+ \gobbleoneargument \fi
+ \or \ifcase#2\or
+ \firstoftwoarguments \or
+ \secondoftwoarguments \else
+ \gobbletwoarguments \fi
+ \or \ifcase#2\or
+ \firstofthreearguments \or
+ \secondofthreearguments \or
+ \thirdofthreearguments \else
+ \gobblethreearguments \fi
+ \or \ifcase#2\or
+ \firstoffourarguments \or
+ \secondoffourarguments \or
+ \thirdoffourarguments \or
+ \fourthoffourarguments \else
+ \gobblefourarguments \fi
+ \or \ifcase#2\or
+ \firstoffivearguments \or
+ \secondoffivearguments \or
+ \thirdoffivearguments \or
+ \fourthoffivearguments \or
+ \fifthoffivearguments \else
+ \gobblefivearguments \fi
+ \fi}
+
+\def\filterfromvalue#1#2#3% value max n
+ {\expandafter\doubleexpandafter\csname % we use the fact that an
+ \expandafter\ifx\csname#1\endcsname\relax % undefined cs has become \relax
+ \csstring\gobbleoneargument % which we then gobble here
+ \else
+ \dofilterfromstr{#2}{#3}%
+ \fi
+ \endcsname\csname#1\endcsname}
+
+\def\filterfromnext#1#2% max n {..}{..}{..}{..}
+ {\csname\dofilterfromstr{#1}{#2}\endcsname}
+
+%D \macros
+%D {definemeasure}
+%D
+%D \starttyping
+%D \definemeasure[mywidth][\dimexpr(\textwidth-1cm)]
+%D
+%D ... \measure{mywidth} ...
+%D \stoptyping
+
+\installsystemnamespace{measure}
+
+\unexpanded\def\definemeasure
+ {\dodoubleargument\syst_helpers_define_measure}
+
+\def\syst_helpers_define_measure[#1][#2]%
+ {\expandafter\def\csname\??measure#1\endcsname{#2}}
+
+\unexpanded\def\freezemeasure
+ {\dodoubleargument\syst_helpers_freeze_measure}
+
+\def\syst_helpers_freeze_measure[#1][#2]%
+ {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}}
+
+\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+
+\def\measure
+ {\the\measured}
+
+\def\measured#1%
+ %{\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax}
+ {\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+
+% #2 could be omitted, but we want to support spaces
+%
+% \setmeasure {x} {1cm}
+% \setmeasure {xx} {1cm}
+% \setmeasure {xxx}{1cm}
+
+%D \macros
+%D {dividedsize}
+%D
+%D This one can be used inside a measure (used in m4all):
+%D
+%D \starttyping
+%D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}]
+%D \stoptyping
+
+\def\dividedsize#1#2#3% size gap n
+ {\dimexpr
+ \ifnum\dimexpr#1\relax>\plusone
+ (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1%
+ \fi
+ \relax}
+
+%D \macros
+%D {doifdimensionelse}
+%D
+%D This is a dirty one: we simply append a unit and discard it when needed.
+
+\def\doifelsedimension#1%
+ {\afterassignment\syst_helpers_if_dimension_else\scratchdimen#1pt\relax}
+
+\let\doifdimensionelse\doifelsedimension
+
+\def\syst_helpers_if_dimension_else#1%
+ {\ifx#1\relax
+ \expandafter\secondoftwoarguments
+ \else % #1=p ... t\relax
+ \expandafter\thirdoffourarguments
+ \fi}
+
+%D Ok, here's another one, slower but seldom used. This one scans the text.
+%D
+%D \starttabulate[|Tc|Tc|]
+%D \NC pt \NC \doifdimenstringelse {pt}{yes}{no} \NC \NR
+%D \NC 12pt \NC \doifdimenstringelse {-12pt}{yes}{no} \NC \NR
+%D \NC 1pt \NC \doifdimenstringelse {1pt}{yes}{no} \NC \NR
+%D \NC 12pt \NC \doifdimenstringelse {12pt}{yes}{no} \NC \NR
+%D \NC 12.0pt \NC \doifdimenstringelse {12.0pt}{yes}{no} \NC \NR
+%D \NC -.12pt \NC \doifdimenstringelse {-.12pt}{yes}{no} \NC \NR
+%D \NC .12pt \NC \doifdimenstringelse {.12pt}{yes}{no} \NC \NR
+%D \NC -12pt \NC \doifdimenstringelse {-12pt}{yes}{no} \NC \NR
+%D \NC -12.0pt \NC \doifdimenstringelse{-12.0pt}{yes}{no} \NC \NR
+%D \NC big \NC \doifdimenstringelse {big}{yes}{no} \NC \NR
+%D \NC 10 \NC \doifdimenstringelse {10}{yes}{no} \NC \NR
+%D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR
+%D \stoptabulate
+
+\installsystemnamespace{dimenchecka}
+\installsystemnamespace{dimencheckb}
+\installsystemnamespace{dimencheckc}
+
+\def\doifelsedimenstring#1{\normalexpanded{\noexpand\dodimenteststageone#1}\empty\empty]}
+
+\let\doifdimenstringelse\doifelsedimenstring
+
+\def\dodimenteststageone #1#2{\csname \??dimenchecka\ifcsname \??dimenchecka#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagetwo #1#2{\csname \??dimencheckb\ifcsname \??dimencheckb#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagethree #1]{\csname \??dimencheckc\ifcsname \??dimencheckc#1\endcsname#1\else x\fi\endcsname}
+
+\expandafter\let\csname \??dimenchecka x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckb x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckc x\endcsname\secondoftwoarguments
+
+\expandafter\let\csname \??dimenchecka.\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka,\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka1\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka2\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka3\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka4\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka5\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka6\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka7\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka8\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka9\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka0\endcsname\dodimenteststageone
+
+\expandafter\let\csname \??dimencheckb1\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb2\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb3\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb4\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb5\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb6\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb7\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb8\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb9\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb0\endcsname\dodimenteststagetwo
+
+\expandafter\let\csname \??dimencheckc pt\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc pc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc in\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc bp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc mm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc dd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc sp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc ex\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc em\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nc\endcsname\firstoftwoarguments
+
+%D \macros
+%D {comparedimension,comparedimensioneps}
+%D
+%D This is a dirty one: we simply append a unit and discard it when needed.
+
+\newdimen \roundingeps \roundingeps=10sp
+\newconstant\compresult
+
+\def\comparedimension#1#2%
+ {\compresult
+ \ifdim#1<#2%
+ \zerocount
+ \else\ifdim#1<#2%
+ \plusone
+ \else
+ \plustwo
+ \fi\fi}
+
+\def\comparedimensioneps#1#2% todo: use eps feature
+ {\compresult
+ \ifdim\dimexpr#1-#2\relax<\roudingeps
+ \zerocount
+ \else\ifdim\dimexpr#2-#1\relax<\roudingeps
+ \zerocount
+ \else\ifdim#1<#2%
+ \plusone
+ \else
+ \plustwo
+ \fi\fi\fi}
+
+% % % % % % % % % % % % % % % % % % % % % %
+
+% pretty ugly but fast
+
+% \copycsname xxx\endcsname\csname ..\endcsname
+
+\unexpanded\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
+
+% \letcscsname \crap \csname ..\endcsname
+% \letcsnamecs \csname ..\endcsname\crap
+% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname
+
+\unexpanded\def\letcscsname {\expandafter\let\expandafter}
+\unexpanded\def\letcsnamecs {\expandafter\let}
+\unexpanded\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
+
+% another one, add an item to a commalist
+
+\unexpanded\def\addvalue#1#2% cs item
+ {\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi
+ \normalexpanded{\noexpand\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}}
+
+\def\unspaced#1%
+ {\syst_helpers_unspaced#1\end}
+
+\def\syst_helpers_unspaced#1%
+ {\ifx#1\end
+ \expandafter\gobbleoneargument
+ \else
+ \ifx#1\blankspace\else#1\fi
+ \fi
+ \syst_helpers_unspaced}
+
+\unexpanded\def\unspaceargument#1\to#2%
+ {\scratchcounter\catcode\spaceasciicode
+ \catcode\spaceasciicode\ignorecatcode
+ \scantextokens{\edef#2{#1}}%
+ \catcode\spaceasciicode\scratchcounter}
+
+\unexpanded\def\unspaceafter#1#2%
+ {\unspaceargument#2\to\ascii
+ \expandafter#1\expandafter{\ascii}}
+
+% sometimes handy:
+
+\unexpanded\def\doifelsehasspace#1%
+ {\edef\m_syst_string_one{#1}%
+ \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax}
+
+\let\doifhasspaceelse\doifelsehasspace
+
+\unexpanded\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax
+ {\ifx\m_syst_string_one\space
+ \expandafter\firstoftwoarguments
+ \else\ifx#2\empty
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi\fi}
+
+% this will replace loadfile once and alike !!! todo
+
+\installsystemnamespace{flag}
+
+\unexpanded\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\zerocount}
+\unexpanded\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\plusone}
+
+\def\flag#1{\csname\??flag#1\endcsname}
+
+\def\doifelseflagged#1%
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
+ \expandafter\secondoftwoarguments
+ \else\ifcase\csname\??flag#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\let\doifflaggedelse\doifelseflagged
+
+\def\doifnotflagged#1%
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
+ \expandafter\firstofoneargument
+ \else\ifcase\csname\??flag#1\endcsname
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\firstofoneargument
+ \fi\fi}
+
+\unexpanded\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter{\csname#1#5\endcsname}}
+
+\def\syst_helpers_if_non_zero_positive_else#1#2\end % #3#4%
+ {\ifx#1\relax
+ \ifcase\scratchcounter
+ \endgroup
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \endgroup
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \endgroup
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifelsenonzeropositive#1%
+ {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\scratchcounter=0#1\relax\empty\end}
+
+\let\doifnonzeropositiveelse\doifelsenonzeropositive
+
+% here ?
+
+\unexpanded\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}}
+
+\unexpanded\def\getrawparameters {\dogetparameters\dosetrawvalue }
+\unexpanded\def\getraweparameters {\dogetparameters\dosetrawevalue}
+\unexpanded\def\getrawgparameters {\dogetparameters\dosetrawgvalue}
+\unexpanded\def\getrawxparameters {\dogetparameters\dosetrawxvalue}
+
+\unexpanded\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete
+
+%D Sort of obsolete:
+
+\newcount\c_syst_helpers_mod
+
+\unexpanded\def\dosetmodulo#1#2#3%
+ {\c_syst_helpers_mod#1\divide\c_syst_helpers_mod#2\multiply\c_syst_helpers_mod#2%
+ #3#1\advance#3-\c_syst_helpers_mod}
+
+\unexpanded\def\dosetdivision#1#2#3%
+ {#3#1\divide#3 #2\relax}
+
+\unexpanded\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}}
+\unexpanded\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}}
+
+\def\syst_helpers_unprotected#1\par
+ {#1\protect}
+
+\unexpanded\def\unprotected
+ {\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
+
+\newcount\c_syst_helpers_test_feature_n
+\chardef \c_syst_helpers_test_feature_m\zerocount
+
+\def\currentfeaturetest{\number\c_syst_helpers_test_feature_n}
+
+\unexpanded\def\testfeature#1#2%
+ {\chardef\c_syst_helpers_test_feature_m#1\relax
+ \def\syst_helpers_test_feature_step
+ {\advance\c_syst_helpers_test_feature_n\plusone
+ \ifnum\c_syst_helpers_test_feature_n>\c_syst_helpers_test_feature_m\else
+ #2\expandafter\syst_helpers_test_feature_step
+ \fi}%
+ \retestfeature}
+
+\unexpanded\def\retestfeature % timer support is new per 10/5/2005
+ {\bgroup
+ \ifcase\interactionmode\let\wait\relax\fi
+ \writestatus\m!system{starting feature test}\wait
+ \resettimer
+ \c_syst_helpers_test_feature_n\zerocount
+ \syst_helpers_test_feature_step
+ \writestatus\m!system{\number\c_syst_helpers_test_feature_m\space feature tests done (\elapsedseconds s)}%
+ \wait
+ \egroup}
+
+\unexpanded\def\showtimer#1%
+ {\writestatus{runtime}{\elapsedseconds\space s / #1}}
+
+\unexpanded\def\testfeatureonce#1#2%
+ {\begingroup
+ \let\wait\relax
+ \testfeature{#1}{#2}%
+ \endgroup}
+
+%D \macros
+%D {freezedimenmacro}
+%D
+%D This macro is use as:
+%D
+%D \starttyping
+%D \freezedimenmacro\leftmargindistance
+%D \stoptyping
+
+\unexpanded\def\freezedimenmacro#1%
+ {\edef#1{\the\dimexpr#1}}
+
+%D The next macro negates a macro (dimension or number, or actually, whatever.
+%D It's a typical example of \type {\if} usage:
+%D
+%D \starttyping
+%D \if-\whatever \else-\whatever\fi => else => -whatever
+%D \if--\whatever\else-\whatever\fi => then => whatever
+%D \stoptyping
+
+\def\negated#1{\if-#1\else-#1\fi} % does only work in macros or text
+
+\def\gobbleassigndimen#1\\{}
+
+\def\assigndimen#1#2%
+ {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\}
+
+\unexpanded\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}}
+\unexpanded\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname}
+
+\unexpanded\def\prepended#1#2#3%
+ {\t_syst_helpers_scratch{#3}%
+ \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter#2\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_syst_helpers_scratch#2}}
+
+\unexpanded\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname}
+
+%D \macros
+%D {dowithrange}
+%D
+%D This one is for Mojca Miklavec, who made me aware of the fact that
+%D \type {page-imp.tex} was not the best place to hide it.
+%D
+%D \startbuffer
+%D \def\DoSomething#1{ [item #1] }
+%D
+%D \processranges[1,4:5]\DoSomething \par
+%D \dowithrange {1,4:5}\DoSomething \par
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\def\syst_helpers_with_range#1%
+ {\splitstring#1\at:\to\m_syst_helpers_range_from\and\m_syst_helpers_range_to
+ \ifx\m_syst_helpers_range_to\empty\let\m_syst_helpers_range_to\m_syst_helpers_range_from\fi
+ \dostepwiserecurse\m_syst_helpers_range_from\m_syst_helpers_range_to\plusone{\m_helpers_range_action{##1}}}%
+
+\unexpanded\def\processranges[#1]#2% #1= n:m,p,q:r
+ {\def\m_helpers_range_action{#2}%
+ \processcommacommand[#1]\syst_helpers_with_range}
+
+\unexpanded\def\dowithrange#1#2%
+ {\def\m_helpers_range_action{#2}%
+ \processcommacommand[#1]\syst_helpers_with_range}
+
+% \def\DoSomething#1{ [item #1] }
+% \dowithrange[1,4:5]\DoSomething
+
+%D \macros
+%D {ignoreimplicitspaces}
+%D
+%D \startbuffer
+%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignorespaces}
+%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
+%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignoreimplicitspaces}
+%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\ignoreimplicitspaces
+ {\doifelsenextchar\relax\relax\relax}
+
+%D \macros
+%D {processwords}
+%D
+%D Not that sophisticated but sometimes users (like in metafun).
+
+\def\syst_helpers_process_word#1 #2\_e_o_w_
+ {\doifsomething{#1}{\processword{#1} \syst_helpers_process_word#2 \_e_o_w_}}
+
+\def\processwords#1%
+ {\syst_helpers_process_word#1 \_e_o_w_}% no \unskip
+
+\let\processword\relax
+
+%D \macros
+%D {startnointerference}
+%D
+%D \starttyping
+%D \startnointerference
+%D all kind of code
+%D \stopnointerference
+%D \stoptyping
+
+\newbox\b_syst_helpers_no_interference
+
+\unexpanded\def\startnointerference % not even grouped !
+ {\setbox\b_syst_helpers_no_interference\vbox
+ \bgroup}
+
+\unexpanded\def\stopnointerference
+ {\egroup
+ \setbox\b_syst_helpers_no_interference\emptybox}
+
+%D A variant for \type {\executeifdefined}:
+
+\def\expandcheckedcsname#1#2% #2 is often a \xxxparameter so let's expand it once
+ {\normalexpanded{\noexpand\syst_helpers_expand_checked_csname{#1}{#2}}}
+
+\def\syst_helpers_expand_checked_csname#1#2#3%
+ {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
+
+%D Signal. Some fonts have a char0 rendering so we need to make sure that it
+%D is not set in the font! (THis will be overloaded)
+
+\unexpanded\def\signalcharacter{\char\zerocount} % \zwj
+
+%D A few secial variants of commands defined here. Some more will be moved here (e.g.
+%D from table modules.
+
+\def\dodirectdoubleempty#1#2% used in math (lookahead issues)
+ {\ifx#2[%
+ \expandafter\syst_helpers_direct_double_empty_one_yes
+ \else
+ \expandafter\syst_helpers_direct_double_empty_one_nop
+ \fi#1#2}
+
+\def\syst_helpers_direct_double_empty_one_yes#1[#2]#3%
+ {\ifx#3[\else\expandafter\syst_helpers_direct_double_empty_two_nop\fi#1[#2]#3}
+
+\def\syst_helpers_direct_double_empty_one_nop#1{#1[][]}
+\def\syst_helpers_direct_double_empty_two_nop#1[#2]{#1[#2][]}
+
+%D Used in math definitions (in an \type {\edef}):
+
+%D \startbuffer
+%D [\docheckedpair{}]
+%D [\docheckedpair{a}]
+%D [\docheckedpair{a,b}]
+%D [\docheckedpair{a,b,c}]
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+\def\docheckedpair#1%
+ {\syst_helpers_checked_pair#1,,\_o_e_p_}
+
+\def\syst_helpers_checked_pair#1,#2,#3\_o_e_p_
+ {#1,#2}
+
+%D Here are some nasty helpers. They can be used to fill often expanded token
+%D lists efficiently (see tabulate for an example).
+
+\def\constantnumber#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else \number#1\relax\fi}
+
+\def\constantnumberargument#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else {\number#1}\fi}
+
+\def\constantdimen#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ \the#1\relax
+ \fi}
+
+\def\constantdimenargument#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ {\the#1}%
+ \fi}
+
+\def\constantemptyargument#1%
+ {\ifx#1\empty
+ \noexpand\empty
+ \else
+ {#1}%
+ \fi}
+
+% %D Maybe some day (moved from cont-new):
+% %D
+% %D \starttyping
+% %D \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \stoptyping
+%
+% \def\syst_helpers_choice_finish#1\empty{}
+%
+% \def\syst_helpers_choice_dim#1#2#3%
+% {\ifdim#1#2%
+% #3\expandafter\syst_helpers_choice_finish
+% \else
+% \expandafter\syst_helpers_choice_dim
+% \fi{#1}}
+%
+% \def\syst_helpers_choice_num#1#2#3%
+% {\ifnum#1#2%
+% #3\expandafter\syst_helpers_choice_finish
+% \else
+% \expandafter\syst_helpers_choice_num
+% \fi{#1}}
+%
+% \def\dimchoice#1#2{\syst_helpers_choice_dim{#1}#2{=#1}{#1}\empty}
+% \def\numchoice#1#2{\syst_helpers_choice_num{#1}#2{=#1}{#1}\empty}
+
+%D \macros
+%D {getsubstring}
+%D \startbuffer
+%D
+%D \getsubstring{4}{}{Who Wants This}
+%D \getsubstring{4}{9}{Who Wants This}
+%D \getsubstring{9}{-2}{Who Wants This}
+%D \getsubstring{1}{5}{Who Wants This}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+% expandable:
+
+\def\getsubstring#1#2#3{\clf_getsubstring{#3}{#1}{#2}}
+
+%D Other dimensions than pt (used in mb-mp)
+
+\def\converteddimen#1#2{\clf_converteddimen\dimexpr#1\relax{#2}}
+
+%D Maybe (looks ugly):
+%D
+%D \starttyping
+%D \doifcase {foo}
+%D {bar} {BAR}
+%D {foo} {FOO}
+%D {default} {DEFAULT}
+%D
+%D \doifcase {foo}
+%D {bar} {BAR}
+%D {foo} {\doifcase {bar}
+%D {bar} {BAR}
+%D {foo} {FOO}
+%D {default} {DEFAULT}
+%D }
+%D {default} {DEFAULT}
+%D \stoptyping
+
+% \doifcase {\btxfoundname{author}}
+% {author} {\btxflush{author}}
+% {editor} {\texdefinition{btx:apa:editor-or-editors}}
+% {title} {\texdefinition{btx:apa:title-subtitle-type}}
+% {default} {\btxflush{author}}
+
+% \unexpanded\def\doifcase#1%
+% {\edef\m_case_asked{#1}%
+% \syst_aux_case}
+%
+% \def\syst_aux_case#1%
+% {\edef\m_case_temp{#1}%
+% \ifx\m_case_temp\m_case_asked
+% \expandafter\syst_aux_case_yes
+% \else\ifx\m_case_temp\s!default
+% \doubleexpandafter\firstofoneargument
+% \else
+% \doubleexpandafter\syst_aux_case_nop
+% \fi\fi}
+%
+% \def\syst_aux_skip#1#2%
+% {\edef\m_case_temp{#1}%
+% \ifx\m_case_temp\s!default
+% \expandafter\syst_aux_done
+% \else
+% \expandafter\syst_aux_skip
+% \fi}
+%
+% \def\syst_aux_case_yes#1%
+% {\def\syst_aux_done{#1}%
+% \syst_aux_skip}
+%
+% \def\syst_aux_case_nop#1%
+% {\syst_aux_case}
+
+%D \macros
+%D {ntimes}
+%D
+%D some repetition:
+%D
+%D \startbuffer
+%D \ntimes{*}{20}
+%D \stopbuffer
+%D
+%D \typebuffer \blank gives: \getbuffer \blank
+%D
+%D This is not real fast but quite okay:
+
+%def\ntimes#1#2{\ifnum#2>\zerocount#1\ntimes{#1}{\numexpr#2-\plusone\relax}\fi} % 1.72
+\def\ntimes#1#2{\clf_ntimes{#1}\numexpr#2\relax} % 0.33
+
+%D Not that useful:
+
+% \unexpanded\def\doifelsestringbefore{\clf_doifelsestringbefore}
+% \unexpanded\def\doifelsestringafter {\clf_doifelsestringafter}
+
+% Could have been useful but not faster that addtocommalist and also expansion mess:
+%
+% \def\additemtolist#1#2{\normalexpanded{\noexpand\clf_additemtolist{#1}{#2}}}
+
+\protect \endinput
+
+% \edef\choicetokenyes{+}
+% \edef\choicetokennop{-}
+%
+% \unexpanded\def\startchoice#1%
+% {\pushmacro\currentchoicevalue
+% \edef\currentchoicevalue{#1}%
+% \checkchoicetoken}
+%
+% \unexpanded\def\checkchoicetoken#1%
+% {\edef\choicetoken{#1}%
+% \ifx\choicetoken\choicetokenyes
+% \singleexpandafter\checkchoiceyes
+% \else\ifx\choicetoken\choicetokennop
+% \doubleexpandafter\checkchoicenop
+% \else
+% \doubleexpandafter\choicequit
+% \fi\fi}
+%
+% \def\checkchoiceyes#1%
+% {\edef\choicevalue{#1}%
+% \ifx\currentchoicevalue\choicevalue
+% \expandafter\choiceindeed
+% \else
+% \expandafter\choiceignore
+% \fi}
+%
+% \def\checkchoicenop
+% {\choiceindeed}
+%
+% \def\choiceabort#1\stopchoice
+% {\popmacro\currentchoicevalue}
+%
+% \def\choicequit
+% {\popmacro\currentchoicevalue}
+%
+% \def\choiceindeed#1#2\stopchoice
+% {\popmacro\currentchoicevalue
+% #1}
+%
+% \def\choiceignore#1%
+% {\checkchoicetoken}
+%
+% \let\stopchoice\relax
+%
+% \def\xxx{3}
+% \def\xxx{x}
+%
+% \startchoice {\xxx}
+% + {1} {
+% first
+% } + {2} {
+% second
+% } + {3} {
+% third
+% } - {
+% nothing
+% }
+% \stopchoice
+
+% \def\appendtovaluelist#1#2%
+% {\ifcsname#1\endcsname
+% \expandafter\ifx\csname#1\endcsname\empty
+% \expandafter\def\csname#1\endcsname{#2}%
+% \else
+% \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname
+% \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}%
+% \fi
+% \else
+% \expandafter\def\csname#1\endcsname{#2}%
+% \fi}
+%
+% or
+%
+% \def\appendtovaluelist#1%
+% {\ifcsname#1\endcsname
+% \expandafter\ifx\csname#1\endcsname\empty
+% \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
+% \else
+% \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
+% \fi
+% \else
+% \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname
+% \fi}
+%
+% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}}
+% \def\noappendtovaluelist#1#2{\def#1{#2}}
+%
+% \appendtovaluelist{mylist}{aap}
+% \appendtovaluelist{mylist}{noot}
+% \appendtovaluelist{mylist}{mies}
+%
+% \showvalue{mylist}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-con.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-con.lua
new file mode 100644
index 00000000000..0fa685b2dab
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-con.lua
@@ -0,0 +1,68 @@
+if not modules then modules = { } end modules ['syst-con'] = {
+ version = 1.001,
+ comment = "companion to syst-con.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+local math = math
+local utfchar = utf.char
+local gsub = string.gsub
+
+converters = converters or { }
+local converters = converters
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local formatters = string.formatters
+
+--[[ldx--
+<p>For raw 8 bit characters, the offset is 0x110000 (bottom of plane 18) at
+the top of <l n='luatex'/>'s char range but outside the unicode range.</p>
+--ldx]]--
+
+function converters.hexstringtonumber(n) tonumber(n,16) end
+function converters.octstringtonumber(n) tonumber(n, 8) end
+
+function converters.rawcharacter (n) utfchar(0x110000+n) end
+
+local lchexnumber = formatters["%x"]
+local uchexnumber = formatters["%X"]
+local lchexnumbers = formatters["%02x"]
+local uchexnumbers = formatters["%02X"]
+local octnumber = formatters["%03o"]
+local nicenumber = formatters["%0.6F"]
+
+converters.lchexnumber = lchexnumber
+converters.uchexnumber = uchexnumber
+converters.lchexnumbers = lchexnumbers
+converters.uchexnumbers = uchexnumbers
+converters.octnumber = octnumber
+converters.nicenumber = nicenumber
+
+implement { name = "hexstringtonumber", actions = { tonumber, context }, arguments = { "integer", 16 } }
+implement { name = "octstringtonumber", actions = { tonumber, context }, arguments = { "integer", 8 } }
+
+implement { name = "rawcharacter", actions = function(n) context(utfchar(0x110000+n)) end, arguments = "integer" }
+
+implement { name = "lchexnumber", actions = { lchexnumber, context }, arguments = "integer" }
+implement { name = "uchexnumber", actions = { uchexnumber, context }, arguments = "integer" }
+implement { name = "lchexnumbers", actions = { lchexnumbers, context }, arguments = "integer" }
+implement { name = "uchexnumbers", actions = { uchexnumbers, context }, arguments = "integer" }
+implement { name = "octnumber", actions = { octnumber, context }, arguments = "integer" }
+
+implement { name = "sin", actions = { math.sin, nicenumber, context }, arguments = "number" }
+implement { name = "cos", actions = { math.cos, nicenumber, context }, arguments = "number" }
+implement { name = "tan", actions = { math.tan, nicenumber, context }, arguments = "number" }
+
+implement { name = "sind", actions = { math.sind, nicenumber, context }, arguments = "number" }
+implement { name = "cosd", actions = { math.cosd, nicenumber, context }, arguments = "number" }
+implement { name = "tand", actions = { math.tand, nicenumber, context }, arguments = "number" }
+
+-- only as commands
+
+function commands.format(fmt,...) context((gsub(fmt,"@","%%")),...) end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-con.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-con.mkiv
new file mode 100644
index 00000000000..17c40781977
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-con.mkiv
@@ -0,0 +1,137 @@
+%D \module
+%D [ file=syst-con,
+%D version=2006.09.16, % real old stuff ... 2000.12.10
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Conversions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{syst-con}{1.001}
+
+\unprotect
+
+%D When the number of conversions grew, it did no longer make
+%D sense to spread them over multiple files. So, instead of
+%D defining these in \type {font-ini}, we now have a dedicated
+%D module.
+
+%D \macros
+%D {lchexnumber,uchexnumber,lchexnumbers,uchexnumbers}
+%D
+%D In addition to the uppercase hex conversion, as needed in
+%D math families, we occasionally need a lowercase one, for
+%D instance when we want to compose gbsong fontnames.
+%D
+%D The ugly indirectness is needed to get rid of \TEX\
+%D induced spaces and \type {\relax}'s.
+%D
+%D \starttyping
+%D [\uchexnumber{0}]
+%D [\uchexnumber\scratchcounter]
+%D [\uchexnumber\zerocount]
+%D [\uchexnumber{\number0}]
+%D [\uchexnumber{\number\scratchcounter}]
+%D [\uchexnumber{\number\zerocount}]
+%D [\uchexnumber{\the\scratchcounter}]
+%D [\uchexnumber{\the\zerocount}]
+%D [\expandafter\uchexnumber\expandafter{\number0}]
+%D [\expandafter\uchexnumber\expandafter{\number\scratchcounter}]
+%D [\expandafter\uchexnumber\expandafter{\number\zerocount}]
+%D [\expandafter\uchexnumber\expandafter{\the\scratchcounter}]
+%D [\expandafter\uchexnumber\expandafter{\the\zerocount}]
+%D \stoptyping
+
+\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax}
+\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax}
+\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax}
+\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax}
+
+\let\hexnumber\uchexnumber
+
+%D \macros
+%D {octnumber}
+%D
+%D For unicode remapping purposes, we need octal numbers.
+
+\def\octnumber#1{\clf_octnumber\numexpr#1\relax}
+
+%D \macros
+%D {hexstringtonumber,octstringtonumber}
+%D
+%D This macro converts a two character hexadecimal number into
+%D a decimal number, thereby taking care of lowercase characters
+%D as well.
+
+\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax}
+\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax}
+
+%D \macros
+%D {rawcharacter}
+%D
+%D This macro can be used to produce proper 8 bit characters
+%D that we sometimes need in backends and round||trips.
+
+\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax}
+
+%D \macros
+%D {twodigits, threedigits}
+%D
+%D These macros provides two or three digits always:
+
+\def\twodigits #1{\ifnum #1<10 0\fi\number#1}
+\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1}
+
+%D \macros{modulonumber}
+%D
+%D In the conversion macros described in \type {core-con} we
+%D need a wrap||around method. The following solution is
+%D provided by Taco.
+%D
+%D The \type {modulonumber} macro expands to the mathematical
+%D modulo of a positive integer. It is crucial for it's
+%D application that this macro is fully exandable.
+%D
+%D The expression inside the \type {\numexpr} itself is
+%D somewhat bizarre because \ETEX\ uses a rounding
+%D division instead of truncation. If \ETEX's division
+%D would have behaved like \TEX's normal\type{\divide}, then
+%D the expression could have been somewhat simpler, like
+%D \type {#2-(#2/#1)*#1}. This works just as well, but a bit
+%D more complex.
+
+\def\modulonumber#1#2%
+ {\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
+
+%D \macros{modulatednumber}
+%D
+%D Modulo numbers run from zero to one less than the limit,
+%D but for conversion sets, we need a value between 1 and the
+%D limit. The \type{\modulatednumber} arranges that. This
+%D macro also needs to be fully expandable, resulting in
+%D two \type{\numexpr}s.
+
+\def\modulatednumber#1#2%
+ {\ifnum\the\numexpr\modulonumber{#1}{#2}\relax=0 #1%
+ \else \the\numexpr\modulonumber{#1}{#2}\relax \fi}
+
+%D \macros
+%D {realnumber} % used?
+
+\def\realnumber#1{\withoutpt\the\dimexpr#1\s!pt\relax} % brrr
+
+%D \macros
+%D {setcalculatedsin,setcalculatedcos,setcalculatedtan}
+
+\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}}
+\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}}
+\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}}
+
+ \def\formatted#1{\ctxcommand{format(#1)}} % not clf
+\unexpanded\def\format #1{\ctxcommand{format(#1)}} % not clf
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-fnt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-fnt.mkiv
new file mode 100644
index 00000000000..cacc5f51740
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-fnt.mkiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=syst-fnt,
+%D version=2006.08.11,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Font Things,
+%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.
+
+% formal names cf the tb \& tbt
+
+\unprotect
+
+\def\fontslantperpoint {\fontdimen\plusone }
+\def\fontinterwordspace {\fontdimen\plustwo }
+\def\fontinterwordstretch{\fontdimen\plusthree}
+\def\fontinterwordshrink {\fontdimen\plusfour }
+\def\fontexheight {\fontdimen\plusfive }
+\def\fontemwidth {\fontdimen\plussix }
+\def\fontextraspace {\fontdimen\plusseven}
+
+\def\slantperpoint {\fontdimen\plusone \font}
+\def\interwordspace {\fontdimen\plustwo \font}
+\def\interwordstretch {\fontdimen\plusthree\font}
+\def\interwordshrink {\fontdimen\plusfour \font}
+\def\exheight {\fontdimen\plusfive \font}
+\def\emwidth {\fontdimen\plussix \font}
+\def\extraspace {\fontdimen\plusseven\font}
+
+\def\mathsupdisplay {\fontdimen13 } % to be remapped
+\def\mathsupnormal {\fontdimen14 } % to be remapped
+\def\mathsupcramped {\fontdimen15 } % to be remapped
+\def\mathsubnormal {\fontdimen16 } % to be remapped
+\def\mathsubcombined {\fontdimen17 } % to be remapped
+\def\mathaxisheight {\fontdimen22 } % to be remapped
+
+\def\currentspaceskip {\interwordspace\s!plus\interwordstretch\s!minus\interwordshrink\relax}
+
+\def\currentspacevalue {\the\interwordspace
+ \ifzeropt\interwordstretch\else{ plus }\the\interwordstretch\fi
+ \ifzeropt\interwordshrink \else{ minus }\the\interwordshrink \fi}
+
+\def\usedspacevalue {\ifzeropt\spaceskip\the\spaceskip\else\currentspacevalue\fi}
+
+\def\mathstacktotal {\dimexpr\Umathstacknumup\scriptstyle+\Umathstackdenomdown\scriptstyle\relax}
+\def\mathstackvgap {\Umathstackvgap\scriptstyle}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv
new file mode 100644
index 00000000000..dc8300e7f07
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv
@@ -0,0 +1,1159 @@
+%D \module
+%D [ file=syst-ini,
+%D version=2008.11.04, % 2001.11.16, % 1999.03.17, % an oldie: 1995.10.10
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Bootstrapping \TEX,
+%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 used to load plain \TEX\ in a special way, but redefining a couple of
+%D primitives so that for instance font loading was ignored. For those interested,
+%D this loader is found in \type {syst-tex.tex}. Some of the comment's are Don
+%D Knuths and more of it can be found in the plain \TEX\ format.
+%D
+%D Characters can have special states, that can be triggered by setting their
+%D category coded. Some are preset, others are to be set as soon as possible,
+%D otherwise we cannot define any useful macros.
+
+%catcode`\^^@ = 9 % ascii null is ignored
+%catcode`\\ = 0 % backslash is TeX escape character
+
+\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 Initialization of primitives.
+
+\directlua 0 { % this info is stored in the format
+ lua.name[0] = "main ctx instance"
+
+ local coreprimitives = tex.extraprimitives("core")
+ local texprimitives = tex.extraprimitives("tex")
+ local etexprimitives = tex.extraprimitives("etex")
+ local luatexprimitives = tex.extraprimitives("luatex")
+
+ tex.enableprimitives("",etexprimitives)
+ tex.enableprimitives("",luatexprimitives)
+
+ tex.enableprimitives("normal",coreprimitives)
+ tex.enableprimitives("normal",texprimitives)
+ tex.enableprimitives("normal",etexprimitives)
+ tex.enableprimitives("normal",luatexprimitives)
+}
+
+%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\gobbleoneargument#1{} % will be defined later on anyway
+
+\mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax
+
+%D First we define a simplified version of the \CONTEXT\ 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
+ \let\protect\relax}%
+ \catcode`@=11
+ \catcode`?=11
+ \catcode`!=11
+ \catcode`_=11 }
+
+\let\protect\relax
+
+\unprotect
+
+%D Some pretty important definitions:
+
+\let\bgroup={
+\let\egroup=}
+
+%D \macros
+%D {normalbgroup,normalgroup}
+%D
+%D No comment.
+
+%D Allocation of registers is done slightly different than in plain \TEX. First of
+%D all we use different reserved counters. We also don't implement a family handler
+%D because users are not supposed to implement their own math. We reserve the lowest
+%D 31 registers for scratch purposes. Keep in mind that in the core engine some
+%D registers are reserved: counters 0 upto 9, and counter 255.
+%D
+%D As with plain \TEX\ we recommend that macro designers always use \type {\global}
+%D assignments with respect to registers numbered 1, 3, 5 \unknown\ 31, and always
+%D non||\type {\global} assignments with respect to registers 0, 2, 4, \unknown\ 30.
+%D This will prevent \quote {save stack buildup} that might otherwise occur.
+%D
+%D We reserve some registers for special (management) purposes:
+
+% 0 - 20 : scratch
+% 21 - 127 : internal
+% 128 - 254 : inserts
+% 255 : page
+% 256 - : user
+
+\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change
+\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 32767
+\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = -1
+\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_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_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read
+\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write
+\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register
+\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context
+\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert
+\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context
+\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context
+
+\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end
+\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end
+
+\countdef \zerocount = 120 \zerocount = 0
+\countdef \plusone = 121 \plusone = 1
+\countdef \minusone = 122 \minusone = -1
+
+\countdef \normalpagebox = 127 \normalpagebox = 255 % hardcoded in pdftex/xetex
+
+% A few traditional allocations (these might go):
+
+\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there
+\dimendef \dimen@ = 0
+\dimendef \dimen@i = 1 % global only
+\dimendef \dimen@ii = 2
+
+%D So, effectively we start allocating from 256 and upwards. The inserts sit in the
+%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is
+%D 255. Users can use the scratch registers upto 31 without problem but all others
+%D are reserved.
+
+\let\wlog\gobbleoneargument % Let's get rid of this one.
+
+%D The allocators share a common helper macro.
+
+\normalprotected\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register}
+\normalprotected\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register}
+\normalprotected\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register}
+\normalprotected\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register}
+\normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register}
+\normalprotected\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \chardef \c_syst_max_allocated_read}
+\normalprotected\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \chardef \c_syst_max_allocated_write}
+\normalprotected\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert}
+
+%D We don't need these in \CONTEXT:
+
+\normalprotected\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\chardef \c_syst_max_allocated_language}
+\normalprotected\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \chardef \c_syst_max_allocated_family}
+
+\let\newfam\newfamily
+
+\firstvalidlanguage\plusone
+
+% Watch out, for the moment we disable the check for already being defined
+% later we will revert this but first all chardefs must be replaced.
+
+\normalprotected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
+\normalprotected\def\setnewconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
+\normalprotected\def\setconstant {} % dummy, no checking, so it warns
+\normalprotected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax}
+
+% maybe setconstant with check
+
+% %D The next definitions are really needed (in \CONTEXT):
+
+%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
+\newlinechar=10 \edef\outputnewlinechar{^^J}
+
+%D One reason to start high with allocation is that it permits us to allocate
+%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a
+%D continuous range of boxes. It also permits us to do a proper upward allocation
+%D for inserts. The current code evolved from code that dealt with older engines but
+%D as all engines now provide many registers we removed all traces.
+
+\ifdefined\writestatus \else
+ \normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}}
+\fi
+
+\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name
+ {\ifnum#1<#4\relax
+ \global\advance#1\plusone
+ \global#3#5=#1\relax
+ \else
+ \writestatus{warning}{no room for \string#2\space \string#5\space (max: \number#4)}%
+ \fi}
+
+\def\syst_basics_allocate_nop#1#2#3#4#5% last class method max name
+ {\writestatus{warning}{\string#2 \string#5 is already defined (\string\relax\space it first)}}
+
+\def\syst_basics_allocate#1#2#3#4#5% last class method max name
+ {\ifx#5\undefined
+ \expandafter\syst_basics_allocate_yes
+ \else\ifx#5\relax
+ \expandafter\expandafter\expandafter\syst_basics_allocate_yes
+ \else
+ \expandafter\expandafter\expandafter\syst_basics_allocate_nop
+ \fi\fi
+ #1#2#3#4#5}
+
+%D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of
+%D the more limited \type {\mathchardef}.
+
+\normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register}
+\normalprotected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register}
+
+%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use
+%D the attributes directly but always allocate then first. For instance attribute~0
+%D is reserved for special purposes (this might change). Attributes in the range
+%D 128-1023 are private and should not be touched.
+
+\let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
+\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
+%D strings instead of tokens that take more memory. It's a trick to trick to force
+%D strings. This macro is never used in \CONTEXT.
+
+%normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
+\normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}}
+
+%D \macros
+%D {scratchcounter,
+%D scratchdimen,scratchskip,scratchmuskip,
+%D scratchbox,
+%D scratchtoks}
+%D
+%D We now define a few scratch registers, so that successive loads at least have
+%D some available.
+
+\newcount \scratchcounter \newcount \globalscratchcounter
+\newdimen \scratchdimen \newdimen \globalscratchdimen
+\newskip \scratchskip \newskip \globalscratchskip
+\newmuskip\scratchmuskip \newmuskip\globalscratchmuskip
+\newtoks \scratchtoks \newtoks \globalscratchtoks
+\newbox \scratchbox \newbox \globalscratchbox
+
+\newcount\scratchcounterone \newcount\scratchcountertwo \newcount\scratchcounterthree
+\newdimen \scratchdimenone \newdimen \scratchdimentwo \newdimen \scratchdimenthree
+\newskip \scratchskipone \newskip \scratchskiptwo \newskip \scratchskipthree
+\newmuskip\scratchmuskipone \newmuskip\scratchmuskiptwo \newmuskip\scratchmuskipthree
+\newtoks \scratchtoksone \newtoks \scratchtokstwo \newtoks \scratchtoksthree
+\newbox \scratchboxone \newbox \scratchboxtwo \newbox \scratchboxthree
+
+\newcount\scratchcounterfour \newcount\scratchcounterfive \newcount\scratchcountersix
+\newdimen \scratchdimenfour \newdimen \scratchdimenfive \newdimen \scratchdimensix
+\newskip \scratchskipfour \newskip \scratchskipfive \newskip \scratchskipsix
+\newmuskip\scratchmuskipfour \newmuskip\scratchmuskipfive \newmuskip\scratchmuskipsix
+\newtoks \scratchtoksfour \newtoks \scratchtoksfive \newtoks \scratchtokssix
+\newbox \scratchboxfour \newbox \scratchboxfive \newbox \scratchboxsix
+
+%D \macros
+%D {scratchwidth, scratchheight, scratchdepth, scratchoffset, scratchdistance}
+%D
+%D A few more scratch dimensions:
+
+\newdimen\scratchwidth
+\newdimen\scratchheight
+\newdimen\scratchdepth
+
+\newdimen\scratchoffset
+\newdimen\scratchleftoffset
+\newdimen\scratchrightoffset
+\newdimen\scratchtopoffset
+\newdimen\scratchbottomoffset
+
+\newdimen\scratchdistance
+
+\newdimen\scratchhsize
+\newdimen\scratchvsize
+
+\newdimen\scratchxoffset
+\newdimen\scratchyoffset
+\newdimen\scratchhoffset
+\newdimen\scratchvoffset
+
+\newdimen\scratchxposition
+\newdimen\scratchyposition
+
+\newcount\scratchnx
+\newcount\scratchny
+
+\newcount\scratchmx
+\newcount\scratchmy
+
+\newcount\scratchmin
+\newcount\scratchmax
+
+\newcount\scratchunicode
+
+\newdimen\scratchleftskip
+\newdimen\scratchrightskip
+\newdimen\scratchtopskip
+\newdimen\scratchbottomskip
+
+%D More allocations:
+
+\newskip \zeroskip \zeroskip = 0pt plus 0pt minus 0pt
+\newdimen \zeropoint \zeropoint = 0pt
+\newdimen \onepoint \onepoint = 1pt
+\newdimen \halfapoint \halfapoint = 0.5pt
+\newdimen \maxdimen \maxdimen = 16383.99999pt
+\newdimen \onebasepoint \onebasepoint = 1bp
+\newdimen \scaledpoint \scaledpoint = 1sp
+\newdimen \thousandpoint \thousandpoint = 1000pt
+\newmuskip\zeromuskip \zeromuskip = 0mu
+\newmuskip\onemuskip \onemuskip = 1mu
+
+\newmuskip\muquad \muquad = 18mu
+
+\let\points \onepoint
+\let\halfpoint\halfapoint
+
+\newtoks \emptytoks
+
+%D And even more: (todo: countdefs 60+)
+
+%newcount \minusone \minusone = -1
+\newcount \minustwo \minustwo = -2
+%chardef \zerocount = 0
+%chardef \plusone = 1
+\chardef \plustwo = 2
+\chardef \plusthree = 3
+\chardef \plusfour = 4
+\chardef \plusfive = 5
+\chardef \plussix = 6
+\chardef \plusseven = 7
+\chardef \pluseight = 8
+\chardef \plusnine = 9
+\chardef \plusten = 10
+\chardef \plussixteen = 16
+\chardef \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
+
+%D \macros
+%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded}
+%D
+%D A few handy shortcuts
+
+\let\singleexpandafter \expandafter
+\def\doubleexpandafter{\expandafter\expandafter\expandafter}
+\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter}
+
+%D We prefer the more readable variant than in plain \TEX. User should only
+%D use \type {\emptybox}:
+
+\newbox\voidbox % public
+
+\let\normalhbox\hbox
+\let\normalvbox\vbox
+
+\def\unvoidbox{\unhbox\voidbox}
+\def\emptybox {\box \voidbox} % used in initializations so no attributes
+\def\emptyvbox{\normalvbox{}} % no copy as we need to set attributes
+\def\emptyhbox{\normalhbox{}} % no copy as we need to set attributes
+
+\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode
+
+%D \macros
+%D {dontcomplain}
+%D
+%D We need this one soon:
+
+\normalprotected\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+%D Some expected plain variants follow. We don't reuse registers because we
+%D don't want clashes.
+
+\let \p@ \onepoint
+\let \m@ne \minusone
+\let \z@ \zeropoint
+\let \@ne \plusone
+\let \tw@ \plustwo
+\let \thr@@ \plusthree
+\let \sixt@@n \plussixteen
+\let \@cclv \pluscclv
+\let \@cclvi \pluscclvi
+\let \voidb@x \voidbox
+\newtoks \toks@ % \scratchtoks
+
+%D We define \type {\newif} a la plain \TEX, but will redefine it later. As
+%D Knuth says:
+%D
+%D \startnarrower
+%D And here's a different sort of allocation: for example,
+%D
+%D \starttyping
+%D \newif\iffoo
+%D \stoptyping
+%D
+%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}
+
+\bgroup % `if' is required
+
+ \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+
+\egroup
+
+%D Let's test this one:
+
+\newif\ifdone
+\newif\iffound
+
+%D Potential primitive in \LUATEX:
+
+\ifdefined\htdp \else \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi
+
+%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.
+
+\let\active\activecatcode
+
+%D Constants to be used with \type {\currentgrouptype}.
+
+\chardef\bottomlevelgroupcode = 0
+\chardef\simplegroupcode = 1
+\chardef\hboxgroupcode = 2
+\chardef\adjustedhboxgroupcode = 3
+\chardef\vboxgroupcode = 4
+\chardef\vtopgroupcode = 5
+\chardef\aligngroupcode = 6
+\chardef\noaligngroupcode = 7
+\chardef\outputgroupcode = 8
+\chardef\mathgroupcode = 9
+\chardef\discretionarygroupcode = 10
+\chardef\insertgroupcode = 11
+\chardef\vcentergroupcode = 12
+\chardef\mathchoicegroupcode = 13
+\chardef\semisimplegroupcode = 14
+\chardef\mathshiftgroupcode = 15
+\chardef\mathleftgroupcode = 16
+\chardef\vadjustgroupcode = \insertgroupcode
+
+%D Constants to be used with \type {\interactionmode}.
+
+\chardef\batchmodecode = 0
+\chardef\nonstopmodecode = 1
+\chardef\scrollmodecode = 2
+\chardef\errorstopmodecode = 3
+
+%D Constants to be used with \type {\lastnodetype}. The \type {\lastnodetype}
+%D primitive is \ETEX\ compliant. The valid range is still -1 .. 15 and glyph nodes
+%D have number 0 (used to be char node) and ligature nodes are mapped to 7. That way
+%D macro packages can use the same symbolic names as in traditional \ETEX. Keep in
+%D mind that the internal node numbers are different and that there are more node
+%D types that 15.
+
+\chardef\charnodecode = 0
+\chardef\hlistnodecode = 1
+\chardef\vlistnodecode = 2
+\chardef\rulenodecode = 3
+\chardef\insertnodecode = 4
+\chardef\marknodecode = 5
+\chardef\adjustnodecode = 6
+\chardef\ligaturenodecode = 7
+\chardef\discretionarynodecode = 8
+\chardef\whatsitnodecode = 9
+\chardef\mathnodecode = 10
+\chardef\gluenodecode = 11
+\chardef\kernnodecode = 12
+\chardef\penaltynodecode = 13
+\chardef\unsetnodecode = 14
+\chardef\mathsnodecode = 15
+
+%D Constants to be used with \type {\currentiftype}. I wonder if we will ever
+%D use these in \CONTEXT.
+
+\chardef\charifcode = 1
+\chardef\catifcode = 2
+\chardef\numifcode = 3
+\chardef\dimifcode = 4
+\chardef\oddifcode = 5
+\chardef\vmodeifcode = 6
+\chardef\hmodeifcode = 7
+\chardef\mmodeifcode = 8
+\chardef\innerifcode = 9
+\chardef\voidifcode = 10
+\chardef\hboxifcode = 11
+\chardef\vboxifcode = 12
+\chardef\xifcode = 13
+\chardef\eofifcode = 14
+\chardef\trueifcode = 15
+\chardef\falseifcode = 16
+\chardef\caseifcode = 17
+\chardef\definedifcode = 18
+\chardef\csnameifcode = 19
+\chardef\fontcharifcode = 20
+
+%D Of course we want even bigger log files, so we copied this from the \ETEX\
+%D source files.
+%D
+%D When watching such logs, beware of nasty side effects of \type {\scantokens},
+%D as in:
+%D
+%D \starttyping
+%D \bgroup
+%D \lccode`a=12\lowercase{\xdef\whatever{a}}\egroup
+%D \def\whatever{test \whatever test}
+%D \scantokens\expandafter{\whatever}
+%D \egroup
+%D \stoptyping
+%D
+%D In \LUATEX\ we have ways around this.
+
+% no longer \errorstopmode cf. plain tex 3.141592653
+
+\normalprotected\def\tracingall
+ {\tracingonline \plusone
+ \tracingcommands \plusthree
+ \tracingstats \plustwo
+ \tracingpages \plusone
+ \tracingoutput \plusone
+ \tracinglostchars \plustwo
+ \tracingmacros \plustwo
+ \tracingparagraphs\plusone
+ \tracingrestores \plusone
+ \showboxbreadth \maxdimen
+ \showboxdepth \maxdimen
+ \tracinggroups \plusone
+ \tracingifs \plusone
+ \tracingscantokens\plusone
+ \tracingnesting \plusone
+ \tracingassigns \plustwo}
+
+\normalprotected\def\loggingall
+ {\tracingall
+ \tracingonline \zerocount}
+
+\normalprotected\def\tracingnone
+ {\tracingassigns \zerocount
+ \tracingnesting \zerocount
+ \tracingscantokens\zerocount
+ \tracingifs \zerocount
+ \tracinggroups \zerocount
+ \showboxdepth \plusthree
+ \showboxbreadth \plusfive
+ \tracingrestores \zerocount
+ \tracingparagraphs\zerocount
+ \tracingmacros \zerocount
+ \tracinglostchars \plusone
+ \tracingoutput \zerocount
+ \tracingpages \zerocount
+ \tracingstats \zerocount
+ \tracingcommands \zerocount
+ \tracingonline \zerocount}
+
+%D Just for tracing purposes we set:
+
+\tracingstats\plusone
+
+%D Here we also save \type {\input}, more will be saved later.
+
+\ifdefined\normalinput \else \let\normalinput\input \fi
+
+%D We don't like outer commands, and we always want access to the original
+%D \type {\input} primitive.
+
+\let\normalouter\outer \def\outer{} % no longer \relax
+
+%D To circumvent dependencies, we can postpone certain initializations to
+%D dumping time, by appending them to the \type {\everydump} token register.
+
+\ifdefined\normaldump \else \let\normaldump\dump \fi
+
+\newtoks\everydump
+
+\def\dump{\the\everydump\normaldump}
+
+%D The same applies for the startup actions.
+
+\ifdefined\normaleveryjob \else \let\normaleveryjob\everyjob \fi
+
+\let\everyjob\relax \newtoks\everyjob
+
+\normaleveryjob{\the\everyjob}
+
+%D \macros
+%D {newconditional,
+%D settrue, setfalse,
+%D ifconditional,then}
+%D
+%D \TEX's lacks boolean variables, although the \PLAIN\ format implements \type
+%D {\newif}. The main disadvantage of this scheme is that it takes three hash table
+%D entries. A more memory saving alternative is presented here. A conditional is
+%D defined by:
+%D
+%D \starttyping
+%D \newconditional\doublesided
+%D \setfalse
+%D \stoptyping
+%D Setting a conditional is done by \type{\settrue} and
+%D \type{\setfalse}:
+%D
+%D \starttyping
+%D \settrue\doublesided
+%D \setfalse
+%D \stoptyping
+%D while testing is accomplished by:
+%D
+%D \starttyping
+%D \ifconditional\doublesided ... \else ... \fi
+%D \setfalse
+%D \stoptyping
+%D We cannot use the simple scheme:
+%D
+%D \starttyping
+%D \def\settrue #1{\let#1=\iftrue}
+%D \def\setfalse#1{\let#1=\iffalse}
+%D \stoptyping
+%D
+%D Such an implementation gives problems with nested conditionals. The next
+%D implementation is about as fast and just as straightforward:
+
+\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef
+\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef
+
+\normalprotected\def\settrue #1{\let#1\conditionaltrue }
+\normalprotected\def\setfalse#1{\let#1\conditionalfalse}
+
+\normalprotected\def\settruevalue #1{\expandafter\let\csname#1\endcsname\conditionaltrue }
+\normalprotected\def\setfalsevalue#1{\expandafter\let\csname#1\endcsname\conditionalfalse}
+
+\let\newconditional\setfalse
+\let\ifconditional \ifcase
+
+\let\then\relax % so that we can say: \ifnum1>2\then -)
+
+%D \macros
+%D {newmacro,setnewmacro,newfraction}
+%D
+%D Let's be complete and also introduce some definers. These are not mandate
+%D but handy for grepping.
+
+\normalprotected\def\newmacro #1{\let#1\empty}
+\normalprotected\def\setnewmacro#1{\let#1}
+
+\def\!!plusone{1}
+
+\normalprotected\def\newfraction#1{\let#1\!!plusone}
+
+%D It would be handy to have a primitive \type {\unless\ifcase} because then we
+%D could use nicer values. Anyhow, this conditional code used to be in the \type
+%D {syst-aux} module but is now promoted to here.
+
+%D \macros
+%D {ifzeropt}
+%D
+%D The next macro is both cosmetic and byte saving. It is pretty \type
+%D {\if}||safe too. It can be used in cases like:
+%D
+%D \starttyping
+%D \ifzeropt \somedimen ... \else ... \fi
+%D \stoptyping
+
+\let\ifzeropt\ifcase
+
+% these token list helpers might move to syst-aux.mkiv
+%
+% we assume a \cs. not toks0 or so
+%
+% \normalprotected\def\appendtotoks #1#{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=}
+% \normalprotected\def\prependtotoks#1#{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=}
+
+\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp
+
+\normalprotected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=}
+\normalprotected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=}
+
+% \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}}
+% \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}}
+
+\normalprotected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=}
+\normalprotected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=}
+
+\def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}}
+\def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}}
+
+\def\syst_toks_append_g {\global\syst_toks_append_l }
+\def\syst_toks_prepend_g{\global\syst_toks_prepend_l}
+
+\normalprotected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next}
+\normalprotected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next}
+
+\def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp}
+\def\syst_toks_add_g{\global\syst_toks_add_l}
+
+\normalprotected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes
+\normalprotected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes
+
+%D \macros
+%D {begcsname}
+%D
+%D Handy for \ETEX-only usage (avoids making \type {\relax}'s:
+
+% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
+
+\let\begcsname\begincsname
+
+%D Now come a few macros that might be needed in successive loading. We redefine the
+%D \type {\par} primitive pretty soon so that we get the equivalents right.
+
+% too tricky: \par is use more often than a par starts so we have too much change
+% that we get assymetrical behaviour
+%
+% \newtoks\everyendpar
+%
+% \normalprotected\def\endpar{\the\everyendpar\normalpar}
+% \normalprotected\def\par {\endpar}
+%
+% \normalprotected\def\reseteverypar
+% {\everypar \emptytoks
+% \everyendpar\emptytoks}
+
+\normalprotected\def\reseteverypar
+ {\everypar\emptytoks}
+
+\let\endgraf\par
+\let\endline\cr
+
+\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
+
+%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
+%D get. Beware: this macro does not support nested loops. We use a namespace
+%D prefix \type {@@pln}.
+
+\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go
+
+%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type
+%D {\repeat} skippable (clever trick):
+
+\let\repeat\fi % so both \loop and \repeat are reserved words!
+
+%D The original (no \type {@@pln} there):
+%D
+%D \starttyping
+%D \def\@@plniterate{\@@plnbody\let\next\@@plniterate\else\let\next\relax\fi\next}
+%D \stoptyping
+%D
+%D A more efficient alternative:
+%D
+%D \starttyping
+%D \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\expandafter\relax\fi}
+%D \stoptyping
+%D
+%D An even more efficient one:
+
+\def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\fi}
+
+%D We don't define a real output routine yet but at least get rid of pages:
+
+\output{\shipout\box\normalpagebox}
+
+%D Although we don't add pagenumbers yet we alias the default register used
+%D for counting pages:
+
+\countdef\pageno\zerocount \pageno\plusone % first page is number 1
+
+%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides
+%D the value.
+
+\def\folio{\the\pageno} % kind of expected and therefore reserved
+
+%D The following registers are kind of standard and (for the moment) we define
+%D them here. This might change.
+
+\newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt
+\newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt
+\newskip \smallskipamount \smallskipamount = 3pt plus 1pt minus 1pt
+
+\baselineskip = 12pt
+\lineskip = 1pt
+\lineskiplimit = 0pt
+
+%D Again a few kind-of-extensions the core. These come from plain \TEX\ but
+%D are probably not used in \CONTEXT.
+
+\newskip \hideskip \hideskip = -1000pt plus 1fill
+\newskip \centering \centering = 0pt plus 1000pt minus 1000pt
+
+\def\hidewidth % for alignment entries that can stick out
+ {\hskip\hideskip}
+
+\def\ialign % initialized \halign
+ {\everycr\emptytoks
+ \tabskip\zeroskip
+ \halign}
+
+\newcount \mscount
+
+\def\spanomit{\span\omit} % bypass error message
+
+\def\multispan#1%
+ {\omit
+ \mscount#1\relax
+ \loop
+ \ifnum\mscount>\plusone
+ \spanomit \advance\mscount\minusone
+ \repeat}
+
+%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}
+\def\pdftexrevision {\pdffeedback revision}
+\def\pdflastlink {\numexpr\pdffeedback lastlink}
+\def\pdfretval {\numexpr\pdffeedback retval}
+\def\pdflastobj {\numexpr\pdffeedback lastobj}
+\def\pdflastannot {\numexpr\pdffeedback lastannot}
+\def\pdfxformname {\numexpr\pdffeedback xformname}
+\def\pdfcreationdate {\pdffeedback creationdate}
+\def\pdffontname {\numexpr\pdffeedback fontname}
+\def\pdffontobjnum {\numexpr\pdffeedback fontobjnum}
+\def\pdffontsize {\dimexpr\pdffeedback fontsize}
+\def\pdfpageref {\numexpr\pdffeedback pageref}
+\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\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
+
+%D Basic status stuff.
+
+\newif\ifproductionrun
+
+%D For those who expect this \unknown
+
+\ifx\fmtname \undefined \def\fmtname {ConTeXt Initial TeX} \fi
+\ifx\fmtversion\undefined \def\fmtversion{3.1415926} \fi
+
+%D A few bonus macros:
+
+\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
+\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
+
+\def \texenginename {LuaTeX}
+\edef\texengineversion{\dividenumber{100}\luatexversion.\modulonumber{100}\luatexversion.\luatexrevision}
+
+%D We have no reason not to enable this:
+
+\savingvdiscards\plusone
+
+%D We only can set this one via directives (system.synctex).
+
+\let\synctex\undefined \newcount\synctex
+
+%D We get rid of the funny \TEX\ offset defaults of one 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
+
+%D Handy.
+
+\suppresslongerror \plusone % \let\suppresslongerror \relax
+\suppressoutererror \plusone % \let\suppressoutererror \relax
+\suppressmathparerror \plusone % \let\suppressmathparerror \relax
+\suppressifcsnameerror\plusone % \let\suppressifcsnameerror\relax
+
+\matheqnogapstep \zerocount % fr now
+
+%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.
+
+%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.
+
+\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
+
+\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
+%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
+
+\normalprotected\def\installsystemnamespace#1%
+ {\ifcsname ??#1\endcsname
+ \immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}%
+ \expandafter\normalend
+ \else
+ \global\advance\c_syst_helpers_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \fi}
+
+%D It makes more sense to have these here:
+
+\let\normalsuperscript\Usuperscript
+\let\normalsubscript \Usubscript
+\let\normalstartimath \Ustartmath
+\let\normalstopimath \Ustopmath
+\let\normalstartdmath \Ustartdisplaymath
+\let\normalstopdmath \Ustopdisplaymath
+
+%D For now:
+
+\ifdefined\protrusionboundary \else \let\protrusionboundary\boundary \fi
+\ifdefined\wordboundary \else \let\wordboundary \noboundary \fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua
new file mode 100644
index 00000000000..422f57a0092
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua
@@ -0,0 +1,180 @@
+if not modules then modules = { } end modules ['syst-lua'] = {
+ version = 1.001,
+ comment = "companion to syst-lua.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find, match = string.find, string.match
+local tonumber = tonumber
+local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat
+
+
+commands = commands or { }
+local commands = commands
+
+local implement = interfaces.implement
+
+local two_strings = interfaces.strings[2]
+
+local context = context
+local csprint = context.sprint
+
+local prtcatcodes = tex.prtcatcodes
+
+implement { -- will b eoverloaded later
+ name = "writestatus",
+ arguments = two_strings,
+ actions = logs.status,
+}
+
+local ctx_firstoftwoarguments = context.firstoftwoarguments -- context.constructcsonly("firstoftwoarguments" )
+local ctx_secondoftwoarguments = context.secondoftwoarguments -- context.constructcsonly("secondoftwoarguments")
+local ctx_firstofoneargument = context.firstofoneargument -- context.constructcsonly("firstofoneargument" )
+local ctx_gobbleoneargument = context.gobbleoneargument -- context.constructcsonly("gobbleoneargument" )
+
+-- contextsprint(prtcatcodes,[[\ui_fo]]) -- ctx_firstofonearguments
+-- contextsprint(prtcatcodes,[[\ui_go]]) -- ctx_gobbleonearguments
+-- contextsprint(prtcatcodes,[[\ui_ft]]) -- ctx_firstoftwoarguments
+-- contextsprint(prtcatcodes,[[\ui_st]]) -- ctx_secondoftwoarguments
+
+function commands.doifelse(b)
+ if b then
+ ctx_firstoftwoarguments()
+-- csprint(prtcatcodes,[[\ui_ft]]) -- ctx_firstoftwoarguments
+ else
+ ctx_secondoftwoarguments()
+-- csprint(prtcatcodes,[[\ui_st]]) -- ctx_secondoftwoarguments
+ end
+end
+
+function commands.doifelsesomething(b)
+ if b and b ~= "" then
+ ctx_firstoftwoarguments()
+-- csprint(prtcatcodes,[[\ui_ft]]) -- ctx_firstoftwoarguments
+ else
+ ctx_secondoftwoarguments()
+-- csprint(prtcatcodes,[[\ui_st]]) -- ctx_secondoftwoarguments
+ end
+end
+
+function commands.doif(b)
+ if b then
+ ctx_firstofoneargument()
+-- context.__flushdirect(prtcatcodes,[[\ui_fo]]) -- ctx_firstofonearguments
+ else
+ ctx_gobbleoneargument()
+-- context.__flushdirect(prtcatcodes,[[\ui_go]]) -- ctx_gobbleonearguments
+ end
+end
+
+function commands.doifsomething(b)
+ if b and b ~= "" then
+ ctx_firstofoneargument()
+-- context.__flushdirect(prtcatcodes,[[\ui_fo]]) -- ctx_firstofonearguments
+ else
+ ctx_gobbleoneargument()
+-- context.__flushdirect(prtcatcodes,[[\ui_go]]) -- ctx_gobbleonearguments
+ end
+end
+
+function commands.doifnot(b)
+ if b then
+ ctx_gobbleoneargument()
+-- csprint(prtcatcodes,[[\ui_go]]) -- ctx_gobbleonearguments
+ else
+ ctx_firstofoneargument()
+-- csprint(prtcatcodes,[[\ui_fo]]) -- ctx_firstofonearguments
+ end
+end
+
+function commands.doifnotthing(b)
+ if b and b ~= "" then
+ ctx_gobbleoneargument()
+-- csprint(prtcatcodes,[[\ui_go]]) -- ctx_gobbleonearguments
+ else
+ ctx_firstofoneargument()
+-- csprint(prtcatcodes,[[\ui_fo]]) -- ctx_firstofonearguments
+ end
+end
+
+commands.testcase = commands.doifelse -- obsolete
+
+function commands.boolcase(b)
+ context(b and 1 or 0)
+end
+
+function commands.doifelsespaces(str)
+ if find(str,"^ +$") then
+ ctx_firstoftwoarguments()
+ else
+ ctx_secondoftwoarguments()
+ end
+end
+
+local pattern = lpeg.patterns.validdimen
+
+function commands.doifelsedimenstring(str)
+ if lpegmatch(pattern,str) then
+ ctx_firstoftwoarguments()
+ else
+ ctx_secondoftwoarguments()
+ end
+end
+
+local p_first = C((1-P(",")-P(-1))^0)
+
+implement {
+ name = "firstinset",
+ arguments = "string",
+ actions = function(str) context(lpegmatch(p_first,str or "")) end
+}
+
+implement {
+ name = "ntimes",
+ arguments = { "string", "integer" },
+ actions = { string.rep, context }
+}
+
+implement {
+ name = "execute",
+ arguments = "string",
+ actions = os.execute -- wrapped in sandbox
+}
+
+implement {
+ name = "doifelsesame",
+ arguments = two_strings,
+ actions = function(a,b)
+ if a == b then
+ ctx_firstoftwoarguments()
+ else
+ ctx_secondoftwoarguments()
+ end
+ end
+}
+
+implement {
+ name = "doifsame",
+ arguments = two_strings,
+ actions = function(a,b)
+ if a == b then
+ ctx_firstofoneargument()
+ else
+ ctx_gobbleoneargument()
+ end
+ end
+}
+
+implement {
+ name = "doifnotsame",
+ arguments = two_strings,
+ actions = function(a,b)
+ if a == b then
+ ctx_gobbleoneargument()
+ else
+ ctx_firstofoneargument()
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv
new file mode 100644
index 00000000000..b5001ab6253
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=syst-lua,
+%D version=2008.01.25,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Helper macros based on \LUA,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{syst-lua}{1.001}
+
+\unprotect
+
+\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}}
+\def\expdoif #1#2{\clf_doifsame {#1}{#2}}
+\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}}
+
+% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3
+% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5
+
+\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
+\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}}
+
+\def\expdoifcommonelse\expdoifelsecommon
+\def\expdoifinsetelse \expdoifelseinset
+
+% we define these here, just in case ...
+
+\def\luastringsep{===} % this permits \typefile{self} otherwise nested b/e sep problems
+
+\edef\!!bs{[\luastringsep[}
+\edef\!!es{]\luastringsep]}
+
+\unexpanded\def\writestatus#1#2{\clf_writestatus{#1}{#2}}
+
+% A handy helper:
+
+% \def\luaexpr#1{\ctxlua{context(tostring(#1))}} % more efficient:
+
+% We can omit the tex.ctxcatcodes here as nowadays we seldom
+% change the regime at the \TEX\ end:
+
+\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled
+
+% helpers:
+
+\def\ui_fo #1{#1}
+\def\ui_go #1{}
+\def\ui_ft#1#2{#1}
+\def\ui_st#1#2{#2}
+
+
+%D But as we only use write 16 we could as well do all in \LUA\
+%D and ignore the rest. Okay, we still can do writes here but only
+%D when not blocked.
+
+\let\syst_write_execute\clf_execute % always {...}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-mes.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-mes.mkiv
new file mode 100644
index 00000000000..4cd36e24bdf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-mes.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=syst-mes,
+%D version=2010.06.03,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Messages,
+%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.
+
+\newtoks\everywritestring
+
+\def\writedirect {\immediate\write\statuswrite}
+\def\writeline {\writedirect{}}
+\def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup}
+\let\writebanner \writestring
+\let\message \normalmessage
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-pln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-pln.mkiv
new file mode 100644
index 00000000000..2481131209f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/syst-pln.mkiv
@@ -0,0 +1,120 @@
+%D \module
+%D [ file=syst-pln,
+%D version=2001.11.16, % 1999.03.17, % an oldie: 1995.10.10
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Efficient \PLAIN\ \TEX\ loading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+%D This module set a couple of variables to the plain \TEX\
+%D values. Later they might be overloaded. There is not much
+%D difference between \MKII\ and \MKIV\ but at some point they
+%D might diverge.
+
+%D Build||in numeric variables.
+
+\adjdemerits = 10000
+\binoppenalty = 700
+\brokenpenalty = 100
+\clubpenalty = 150
+%day = 0
+\defaulthyphenchar = `\-
+\defaultskewchar = -1
+\delimiterfactor = 901
+\displaywidowpenalty = 50
+\doublehyphendemerits = 10000
+%endlinechar = `\^^M
+\errorcontextlines = 5
+%escapechar = `\\
+\exhyphenpenalty = 50
+%fam = 0
+\finalhyphendemerits = 5000
+%floatingpenalty = 0
+%globaldefs = 0
+\hangafter = 1 % automatically set to 1 (no zero assignment)
+\hbadness = 1000
+%holdinginserts = 0
+\hyphenpenalty = 50
+%interlinepenalty = 0
+%language = 0
+\lefthyphenmin = 2
+\linepenalty = 10
+%looseness = 0
+%mag = 1000
+%maxdeadcycles = 25
+%month = 0
+%newlinechar = -1 % commented i.e. no plain value
+%outputpenalty = 0
+%pausing = 0
+%postdisplaypenalty = 0
+\predisplaypenalty = 10000
+\pretolerance = 100
+\relpenalty = 500
+\righthyphenmin = 3
+\showboxbreadth = 5
+\showboxdepth = 3
+%time = 0
+\tolerance = 200
+%tracingcommands = 0
+\tracinglostchars = 1
+%tracingmacros = 0
+%tracingonline = 0
+%tracingoutput = 0
+%tracingpages = 0
+%tracingparagraphs = 0
+%tracingrestores = 0
+%tracingstats = 0
+\uchyph = 1
+\vbadness = 1000
+\widowpenalty = 150
+%year = 0
+
+%D Build in dimension variables.
+
+\abovedisplayshortskip = 0pt plus 3pt
+\abovedisplayskip = 12pt plus 3pt minus 9pt
+%baselineskip = 0pt
+\belowdisplayshortskip = 7pt plus 3pt minus 4pt
+\belowdisplayskip = 12pt plus 3pt minus 9pt
+\boxmaxdepth = \maxdimen
+\delimitershortfall = 5pt
+%displayindent = 0pt
+%displaywidth = 0pt
+%hangindent = 0pt
+\hfuzz = 0.1pt
+%hoffset = 0pt
+\hsize = 6.5in
+%leftskip = 0pt
+%lineskip = 0pt
+%lineskiplimit = 0pt
+%mathsurround = 0pt
+\maxdepth = 4pt
+\medmuskip = 4mu plus 2mu minus 4mu
+\nulldelimiterspace = 1.2pt
+\overfullrule = 5pt
+\parfillskip = 0pt plus 1fil
+\parindent = 20pt
+\parskip = 0pt plus 1pt
+%predisplaysize = 0pt
+%rightskip = 0pt
+\scriptspace = 0.5pt
+%spaceskip = 0pt
+\splitmaxdepth = \maxdimen
+\splittopskip = 10pt
+%tabskip = 0pt
+\thickmuskip = 5mu plus 5mu
+\thinmuskip = 3mu
+\topskip = 10pt
+\vfuzz = 0.1pt
+%voffset = 0pt
+\vsize = 8.9in
+%xspaceskip = 0pt
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv
new file mode 100644
index 00000000000..e9008636886
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=tabl-com,
+%D version=2009.08.22,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Common Code,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Common Code}
+
+\unprotect
+
+\let\VL\relax
+
+\let\NC\relax
+\let\RC\relax
+\let\HC\relax
+\let\EQ\relax
+
+\let\RQ\relax
+\let\HQ\relax
+
+\let\NG\relax
+\let\NN\relax
+\let\ND\relax
+\let\NR\relax
+\let\NB\relax
+
+\let\CC\relax
+\let\CL\relax
+\let\CM\relax
+\let\CR\relax
+
+\let\SR\relax
+\let\FR\relax
+\let\MR\relax
+\let\LR\relax
+\let\AR\relax
+
+\let\FL\relax
+\let\ML\relax
+\let\LL\relax
+\let\TL\relax
+\let\BL\relax
+\let\HL\relax
+\let\HR\relax
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv
new file mode 100644
index 00000000000..b0e3f52e439
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv
@@ -0,0 +1,780 @@
+%D \module
+%D [ file=tabl-ltb,
+%D version=2002.10.31, % updated 2016.01.08
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Line Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module was made for some special project where we needed to typeset tables
+%D spanning spanning many pages horizontally and vertically, with repeated header
+%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a
+%D table, which is why the table can go into a buffer or file. As said, tables can
+%D be real huge but performance is still quite okay (there is room for some speed
+%D up). The code has been adapted to \MKIV\ but the functionality is the same as in
+%D \MKII.
+
+% \BH \BC .. \EC \BC .. \EC \EH % append
+% \BR \BC .. \EC \BC .. \EC \ER
+%
+% or
+%
+% \NC .. \NC .. \NC \NR (todo: optional last \NC)
+
+% alternative:
+%
+% (1) direct run, save content in macro, but only if needed
+%
+% todo
+%
+% (2) buffered table content
+%
+% \startbuffer
+% \startlinetablehead
+% \stoplinetablehead
+% \startlinetablebody
+% \stoplinetablebody
+% \stopbuffer
+%
+% \processlinetablebuffer[buffer]
+%
+% in buffer : head and body
+%
+% (3) unbuffered run, multipass
+%
+% - run with starting width zero / prev run
+% - clip on prev run
+% - flush real widths
+
+\writestatus{loading}{ConTeXt Table Macros / Line Tables}
+
+\unprotect
+
+\installcorenamespace{linetable}
+\installcorenamespace{linetablepart}
+\installcorenamespace{linetablewidth}
+\installcorenamespace{linetableheight}
+\installcorenamespace{linetabledepth}
+
+\newconditional \c_tabl_lines_preroll
+\newconditional \c_tabl_lines_in_table
+
+\newdimen \d_tabl_lines_width
+\newdimen \d_tabl_lines_height
+%newdimen \d_tabl_lines_depth
+
+\newbox \b_tabl_lines_cell
+
+\newcount \c_tabl_lines_n_of_columns
+\newcount \c_tabl_lines_n_of_rows
+\newcount \c_tabl_lines_n_of_lines
+\newcount \c_tabl_lines_n_of_parts
+\newcount \c_tabl_lines_part \c_tabl_lines_part\plusone
+\newcount \c_tabl_lines_step \c_tabl_lines_step\plusone
+\newcount \c_tabl_lines_line
+\newcount \c_tabl_lines_row
+\newcount \c_tabl_lines_rows
+\newcount \c_tabl_lines_column
+\newcount \c_tabl_lines_subcol
+
+\newconstant \c_tabl_lines_hmode
+\newconstant \c_tabl_lines_page
+\newconstant \c_tabl_lines_repeat
+\newconstant \c_tabl_lines_split_state
+\newconstant \c_tabl_lines_head_state
+\newconstant \c_tabl_lines_mode
+
+\newtoks \t_tabl_lines_head
+
+\newconditional \linetableautoheight \settrue\linetableautoheight
+
+\initializetablebox\zerocount % holds repeater
+
+\unexpanded\def\setuplinetable
+ {\dotripleempty\tabl_lines_setup}
+
+\def\tabl_lines_setup[#1][#2][#3]%
+ {\ifthirdargument
+ \getparameters[\??linetable#1:#2][#3]%
+ \else\ifsecondargument
+ \getparameters[\??linetable#1:][#2]%
+ \else
+ \getparameters[\??linetable][#1]%
+ \fi\fi}
+
+\setuplinetable
+ [\c!n=\maxcard,
+ \c!lines=\maxcard,
+ \c!nx=\plusone,
+ \c!nleft=\zerocount,
+ \c!repeat=\v!yes, % when nleft > 0, repeat on both pages
+ \c!before=,
+ \c!after=,
+ \c!inbetween=\page,
+ \c!distance=\zeropoint,
+ \c!stretch=\v!no,
+ \c!align=\c!right,
+ \c!leftoffset=.25\exheight,
+ \c!rightoffset=\linetableparameter\c!leftoffset,
+ \c!maxwidth=\zeropoint,
+ \c!width=5\emwidth,
+ \c!height=\v!fit, % \v!line = faster
+ \c!background=,
+ \c!backgroundcolor=]
+
+\def\linetableparameter#1%
+ {\begincsname\??linetable#1\endcsname}
+
+\unexpanded\def\doifelselinetablecparameter#1%
+ {\ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??linetable c:#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\let\doiflinetablecparameterelse\doifelselinetablecparameter
+
+\def\linetablecparameter#1%
+ {\begincsname
+ \??linetable
+ \ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname
+ c:\number\c_tabl_lines_column
+ \else\ifcsname\??linetable c:#1\endcsname
+ c:%
+ \fi\fi
+ #1%
+ \endcsname}
+
+\def\linetablerparameter#1% faster, leaner and meaner
+ {\begincsname
+ \??linetable
+ \ifnum\c_tabl_lines_row=\zerocount % geen ifcase
+ \ifcsname\??linetable r:\v!header#1\endcsname
+ r:\v!header
+ \else\ifcsname\??linetable r:0#1\endcsname
+ r:0%
+ \fi\fi
+ \else
+ \ifcsname\??linetable r:\number\c_tabl_lines_row#1\endcsname
+ r:\number\c_tabl_lines_row
+ \else\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname
+ r:\v!oddeven\c_tabl_lines_row
+ \fi\fi
+ \fi
+ #1%
+ \endcsname}
+
+\unexpanded\def\tabl_lines_set
+ {\edef\p_lines{\linetableparameter\c!lines}%
+ \ifx\p_lines\v!fit
+ \tabl_lines_set_indeed
+ \else
+ \global\c_tabl_lines_n_of_lines\p_lines
+ \fi}
+
+\unexpanded\def\tabl_lines_set_indeed
+ {% whitespace already added by vertical strut
+ %\triggerpagebuilder
+ \scratchdimen
+ \ifdim\pagegoal<\maxdimen
+ \dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \textheight
+ \fi
+ \getrawnoflines\scratchdimen
+ \global\c_tabl_lines_n_of_lines\noflines
+ \ifconditional\c_tabl_lines_preroll \else \ifnum\c_tabl_lines_n_of_lines<\plustwo
+ \page
+ \tabl_lines_set
+ \fi \fi}
+
+\unexpanded\def\startlinetablecell
+ {\dosingleempty\tabl_lines_start_cell}
+
+\def\tabl_lines_step_cell
+ {\advance\scratchdimen\linetablecparameter\c!width
+ \global\advance \c_tabl_lines_column\plusone
+ \advance\scratchskip \linetablecparameter\c!distance}
+
+\def\tabl_lines_start_cell[#1]%
+ {\global\setbox\b_tabl_lines_cell\hbox\bgroup
+ \iffirstargument
+ \getparameters[\??linetable c:\number\c_tabl_lines_column][#1]%
+ \fi
+ \global\c_tabl_lines_step\linetablecparameter\c!nx\relax
+ \ifcase\c_tabl_lines_step\or
+ \scratchdimen\linetablecparameter\c!width
+ \scratchskip \linetablecparameter\c!distance
+ \else
+ \scratchdimen \zeropoint
+ \scratchskip \zeropoint
+ \scratchcounter\c_tabl_lines_column
+ \dorecurse\c_tabl_lines_step\tabl_lines_step_cell
+ \global\c_tabl_lines_column\scratchcounter
+ \fi
+ \c_tabl_lines_mode
+ \ifconditional\c_tabl_lines_preroll
+ \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi
+ \else
+ \zerocount
+ \fi
+ \ifcase\c_tabl_lines_mode
+ \ifcase\c_tabl_lines_hmode
+ % nothing
+ \or
+ % fit, keep it simple
+ \or
+ \c_tabl_lines_mode\plusone % line
+ \else
+ % some already calculated height
+ \fi
+ \fi
+ \setbox\scratchbox\hbox
+ \bgroup
+ \dontcomplain
+ \hskip\linetablecparameter\c!leftoffset\relax
+ % 0 = width, unknown height
+ % 1 = width, fixed height
+ % 2 = no width, auto hsize
+ \ifnum\c_tabl_lines_mode<\plustwo
+ \advance\scratchdimen-\linetablecparameter\c!leftoffset
+ \advance\scratchdimen-\linetablecparameter\c!rightoffset
+ \fi
+ \ifcase\c_tabl_lines_mode
+ \dosetraggedcommand{\linetablecparameter\c!align}%
+ \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup
+ \hsize\scratchdimen
+ \raggedcommand
+ \else
+ \setalignmentswitch{\linetablecparameter\c!align}%
+ \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup
+ \ifcase\alignmentswitch\hss\or\hss\fi
+ \fi
+ \dousestyleparameter{\linetablecparameter\c!style}%
+ \dousecolorparameter{\linetablecparameter\c!color}%
+ \begstrut \ignorespaces}
+
+\unexpanded\def\stoplinetablecell
+ {\unskip \endstrut
+ \ifcase\c_tabl_lines_mode
+ \endgraf
+ \else
+ \ifcase\alignmentswitch\else\hss\fi
+ \fi
+ \egroup
+ \hskip\linetablecparameter\c!rightoffset
+ \egroup
+ \ifconditional\c_tabl_lines_preroll
+ \box\scratchbox
+ \else
+ \tabl_lines_wrap_up
+ \fi
+ \egroup}
+
+\def\tabl_lines_wrap_up
+ {\edef\p_background{\linetablecparameter\c!background}%
+ \ifx\p_background\v!color
+ \ifconditional\linetableautoheight
+ \tabl_lines_wrap_up_auto
+ \else
+ \tabl_lines_wrap_up_line
+ \fi
+ \else
+ \box\scratchbox
+ \fi}
+
+\def\tabl_lines_wrap_up_auto
+ {\edef\p_height{\linetablerparameter{x\c!height}}%
+ \edef\p_depth {\linetablerparameter{x\c!depth }}%
+ \hbox
+ {\blackrule
+ [ \c!color=\linetablecparameter\c!backgroundcolor,
+ \c!height=\ifx\p_height\empty\ht\scratchbox\else\p_height\fi,
+ \c!depth=\ifx\p_depth \empty\dp\scratchbox\else\p_depth \fi,
+ \c!width=\wd\scratchbox]%
+ \hskip-\wd\scratchbox\box\scratchbox}}
+
+\def\tabl_lines_wrap_up_line
+ {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}}
+
+\def\tabl_lines_save_part
+ {\global\setbox\tablebox\c_tabl_lines_part
+ \ifnum\c_tabl_lines_part=\zerocount
+ \box\scratchbox % just storing
+ \else
+ \vbox
+ {\ifvoid\tablebox\c_tabl_lines_part\else\unvbox\tablebox\c_tabl_lines_part\fi
+ \doif{\linetablerparameter\c!background}\v!color
+ {\backgroundline[\linetablerparameter\c!backgroundcolor]}%
+ {\box\scratchbox}% is also arg to \backgroundline
+ \endgraf
+ \linetablerparameter\c!after}%
+ \fi}
+
+\def\tabl_lines_flush_parts
+ {\global\advance\c_tabl_lines_line\plusone
+ \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines
+ % keep collecting
+ \else
+ \ifconditional\c_tabl_lines_preroll
+ % forget about them
+ \else
+ \dorecurse\c_tabl_lines_n_of_parts
+ {\c_tabl_lines_part\recurselevel
+ \dp\tablebox\c_tabl_lines_part\strutdepth
+ % noindent en endgraf needed else whitespace mess-up!
+ \whitespace % here not after verticalstrut
+ \ifdim\topskipgap=\zeropoint\else
+ \verticalstrut
+ \nobreak
+ \kern-\struttotal
+ \kern-\parskip
+ \nobreak
+ \nointerlineskip % fix topskip
+ \fi
+ \noindent\strut
+ \hbox to \hsize{\box\tablebox\c_tabl_lines_part\hss}%
+ \endgraf
+ \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax
+ \linetableparameter\c!inbetween
+ \fi}%
+ \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows
+ \linetableparameter\c!inbetween
+ \else
+ % after, later
+ \fi
+ \c_tabl_lines_head_state\plusthree
+ \global\setbox\tablebox\zerocount\emptybox % here
+ \fi
+ % reset \c_tabl_lines_row will be an option, currently
+ % starts at zero after split
+ \global\c_tabl_lines_row\zerocount
+ \global\c_tabl_lines_line\zerocount
+ \global\c_tabl_lines_page\zerocount
+ \global\d_tabl_lines_width\zeropoint
+ \tabl_lines_set
+ \fi}
+
+\def\tabl_lines_start_part
+ {\global\c_tabl_lines_subcol\zerocount
+ \setbox\scratchbox\hbox\bgroup
+ \dousestyleparameter{\linetablerparameter\c!style}%
+ \dousecolorparameter{\linetablerparameter\c!color}%
+ \ignorespaces}
+
+\def\tabl_lines_stop_part
+ {\ifnum\c_tabl_lines_part>\zerocount
+ \unskip \unskip % remove last intercolumn skip (distance+fill)
+ \fi
+ \egroup
+ \ifconditional\c_tabl_lines_preroll \else
+ \ifcase\c_tabl_lines_part
+ % we're collecting the repeater
+ \else
+ \ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch\else
+ \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}%
+ \fi
+ \fi
+ \fi}
+
+\def\tabl_lines_check_part
+ {\global\advance\d_tabl_lines_width\wd\b_tabl_lines_cell
+ \global\advance\c_tabl_lines_column\c_tabl_lines_step
+ \global\advance\c_tabl_lines_subcol\c_tabl_lines_step
+ \relax
+ %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait
+ % from now on the column counter is already incremented
+ \ifcase\c_tabl_lines_split_state
+ \ifconditional\c_tabl_lines_preroll \else
+ \box\b_tabl_lines_cell
+ % the columncounter is one ahead !
+ \hskip\scratchskip
+ \fi
+ %%%
+ \donefalse
+ \ifcase\c_tabl_lines_repeat\else
+ % calculate ahead
+ \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax
+ \donetrue % collecting repeater
+ \fi
+ \fi
+ %%%%
+ \ifdone
+ % collecting repeater
+ \else
+ \ifnum\c_tabl_lines_column>\csname\??linetablepart\number\c_tabl_lines_part\endcsname\relax
+ \donetrue
+ \fi
+ \fi
+ \ifdone
+ \tabl_lines_stop_part
+ \ifconditional\c_tabl_lines_preroll \else
+ \tabl_lines_save_part
+ \fi
+ \ifcase\c_tabl_lines_page \or
+ \global\c_tabl_lines_page \plustwo
+ \else
+ \global\c_tabl_lines_page \plusone
+ \fi
+ \global\advance\c_tabl_lines_part\plusone
+ \global\d_tabl_lines_width\wd\tablebox\zerocount
+ \tabl_lines_start_part
+ \fi
+ \else
+ \donefalse
+ \!!doneafalse
+ \ifcase\c_tabl_lines_repeat\else
+ % calculate ahead
+ \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax
+ \donetrue % collecting repeater
+ \fi
+ \fi
+ \ifdone
+ \!!doneatrue
+ % collecting repeater
+ \else\ifdim\d_tabl_lines_width>\hsize
+ \donetrue
+ \else
+ \global\advance\d_tabl_lines_width\scratchskip
+ \ifdim\d_tabl_lines_width>\hsize % ?
+ \donetrue
+ \fi
+ \fi\fi
+ \ifdone
+ \tabl_lines_stop_part
+ \tabl_lines_save_part
+ \ifcase\c_tabl_lines_page \or
+ \global\c_tabl_lines_page \plustwo
+ \else
+ \global\c_tabl_lines_page \plusone
+ \fi
+ \global\advance\c_tabl_lines_part\plusone
+ \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts
+ \global\c_tabl_lines_n_of_parts\c_tabl_lines_part
+ \initializetablebox\c_tabl_lines_part
+ \fi
+ \global\d_tabl_lines_width\wd\b_tabl_lines_cell
+ \tabl_lines_start_part
+ \if!!doneb \else \ifcase\c_tabl_lines_repeat \else
+ % check for left/right page
+ \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi\ifdone
+ % insert repeater
+ \global\advance\d_tabl_lines_width\wd\tablebox\zerocount
+ \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\tablebox\zerocount
+ \fi
+ \fi \fi
+ \fi
+ \ifconditional\c_tabl_lines_preroll \else
+ \box\b_tabl_lines_cell
+ % the columncounter is one ahead !
+ \dorecurse\c_tabl_lines_step{\strut\hfil}%
+ \hskip\scratchskip
+ \fi
+ \fi}
+
+\unexpanded\def\startlinetablerun % to do: quit when nested
+ {\bgroup
+ \settrue\c_tabl_lines_in_table
+ % autowidth
+ \doif{\linetableparameter\c!maxwidth}\v!fit
+ {\setuplinetable[\c!maxwidth=\zeropoint]}%
+ \processaction
+ [\linetableparameter\c!stretch]
+ [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch
+ \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch
+ \c_tabl_lines_repeat\linetableparameter\c!nleft
+ \c_tabl_lines_split_state % =
+ \ifdim\linetableparameter\c!maxwidth>\zeropoint
+ \zerocount \else \plusone
+ \fi
+ % optional prevdepth correction
+ \ifconditional\c_tabl_lines_preroll
+ \global\c_tabl_lines_n_of_rows\zerocount
+ \else
+ \linetableparameter\c!before
+ \fi
+ \global\c_tabl_lines_rows\zerocount
+ \global\c_tabl_lines_n_of_columns\zerocount
+ \global\c_tabl_lines_n_of_parts\zerocount
+ \scratchcounter\zerocount
+ \def\docommand##1%
+ {\global\advance\c_tabl_lines_n_of_parts\plusone
+ \advance\scratchcounter##1%
+ \setxvalue{\??linetablepart\number\c_tabl_lines_n_of_parts}{\the\scratchcounter}}%
+ \processcommacommand[\linetableparameter\c!n]\docommand
+ \initializetableboxes\c_tabl_lines_n_of_parts
+ \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater
+ \global\c_tabl_lines_step\plusone
+ \global\c_tabl_lines_line\zerocount
+ \global\c_tabl_lines_row \zerocount
+ \global\c_tabl_lines_column\zerocount
+ \global\c_tabl_lines_subcol\zerocount
+ \global\d_tabl_lines_width\zeropoint
+ \ifconditional\c_tabl_lines_preroll \else \ifdim\pagetotal>\zeropoint
+ \verticalstrut\kern-\struttotal
+ \fi \fi
+ \tabl_lines_set
+ \tabl_lines_check_page
+ \let\BR\tabl_lines_BR
+ \let\ER\tabl_lines_ER
+ \let\BH\tabl_lines_BR
+ \let\EH\tabl_lines_ER
+ \let\BC\tabl_lines_BC
+ \let\EC\tabl_lines_EC
+ \let\NC\tabl_lines_NC
+ \let\NR\tabl_lines_NR
+ \tabl_lines_flush_head}
+
+\unexpanded\def\stoplinetablerun
+ {\global\c_tabl_lines_line\maxcard
+ \c_tabl_lines_head_state\zerocount % blocked
+ \tabl_lines_flush_parts
+ \ifconditional\c_tabl_lines_preroll \else
+ \linetableparameter\c!after
+ \fi
+ \global\c_tabl_lines_part\zerocount
+ \global\c_tabl_lines_n_of_parts\zerocount
+ \egroup}
+
+\def\checklinecolumndimension#1#2#3%
+ {\expandafter\xdef\csname#1\number#3\endcsname
+ {\expandafter\ifx\csname#1\number#3\endcsname\relax
+ \the#2\b_tabl_lines_cell
+ \else\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell
+ \the#2\b_tabl_lines_cell
+ \else
+ \csname#1\number#3\endcsname
+ \fi\fi}}
+
+\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column}
+\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row}
+\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row}
+
+\unexpanded\def\tabl_lines_BR
+ {\dosingleempty\tabl_lines_BR_indeed}
+
+\def\tabl_lines_BR_indeed[#1]% #1 not yet implemented
+ {\ifnum\c_tabl_lines_head_state=1\else
+ \global\advance\c_tabl_lines_row\plusone
+ \global\advance\c_tabl_lines_rows\plusone
+ \fi
+ \global\c_tabl_lines_column\plusone
+ \global\c_tabl_lines_subcol\plusone
+ \d_tabl_lines_height\zeropoint
+ \edef\p_height{\linetablerparameter\c!height}%
+ \ifx\p_height\empty
+ \c_tabl_lines_hmode \zerocount
+ \else\ifx\p_height\v!fit
+ \c_tabl_lines_hmode \plusone
+ \else\ifx\p_height\v!line
+ \c_tabl_lines_hmode \plustwo
+ \else
+ \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax
+ \fi\fi\fi
+ \tabl_lines_start_part}
+
+\unexpanded\def\tabl_lines_BC
+ {\startlinetablecell}
+
+\unexpanded\def\tabl_lines_EC
+ {\stoplinetablecell
+ \ifconditional\c_tabl_lines_preroll
+ \tabl_lines_check_width
+ \tabl_lines_check_height
+ \tabl_lines_check_depth
+ \fi
+ \tabl_lines_check_part}
+
+\unexpanded\def\tabl_lines_ER
+ {% \stoplinetablecell
+ % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR
+ \tabl_lines_stop_part
+ \tabl_lines_save_part
+ \advance\c_tabl_lines_column \minusone
+ \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns
+ \global\c_tabl_lines_n_of_columns\c_tabl_lines_column
+ \fi
+ \tabl_lines_flush_parts
+ \global\c_tabl_lines_column\zerocount
+ \global\d_tabl_lines_width \zeropoint
+ \ifcase\c_tabl_lines_repeat
+ \global\c_tabl_lines_part\plusone
+ \else
+ \global\c_tabl_lines_part\zerocount % repeater
+ \fi
+ \tabl_lines_check_page
+ \tabl_lines_flush_head}
+
+\def\tabl_lines_check_page
+ {\global\c_tabl_lines_page\zerocount
+ \ifcase\c_tabl_lines_repeat \else \ifcase\c_tabl_lines_page
+ \doif{\linetableparameter\c!repeat}\v!no
+ {\global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo}%
+ \fi \fi}
+
+\def\tabl_lines_flush_head
+ {\ifcase\c_tabl_lines_head_state
+ % 0 blocked
+ \or
+ % 1 doing head
+ \or
+ % 2 head done
+ \or
+ % 3 trigger flush
+ \c_tabl_lines_head_state\plusone
+ \the\t_tabl_lines_head\relax
+ \c_tabl_lines_head_state\plustwo
+ \fi}
+
+\unexpanded\def\tabl_lines_NC % first time special treatment
+ {\relax
+ \ifcase\c_tabl_lines_column
+ \tabl_lines_BR
+ \else
+ \tabl_lines_EC
+ \fi
+ \tabl_lines_BC} % beware, this will result in BR BC EC BC NR
+
+\unexpanded\def\tabl_lines_NR
+ {\stoplinetablecell % dummy
+ \tabl_lines_ER}
+
+\unexpanded\def\startlinetable
+ {\startlinetablerun}
+
+\unexpanded\def\stoplinetable
+ {\stoplinetablerun}
+
+\unexpanded\def\startlinetableanalysis
+ {\bgroup
+ \settrue\c_tabl_lines_preroll
+ \settrialtypesetting
+ \startlinetablerun}
+
+% \unexpanded\def\stoplinetableanalysis
+% {\stoplinetablerun
+% \egroup
+% \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
+% \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
+% {\setevalue{\??linetable r:\recurselevel x\c!height}{\getvalue{\??linetableheight\recurselevel}}%
+% \setevalue{\??linetable r:\recurselevel x\c!depth }{\getvalue{\??linetabledepth \recurselevel}}%
+% \letgvalue{\??linetableheight\recurselevel}\!!zeropoint
+% \letgvalue{\??linetabledepth \recurselevel}\!!zeropoint}
+% \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
+% {\setevalue{\??linetable c:\recurselevel\c!width}{\getvalue{\??linetablewidth\recurselevel}}%
+% \letgvalue{\??linetablewidth\recurselevel}\!!zeropoint}} % init next table
+
+\unexpanded\def\stoplinetableanalysis
+ {\stoplinetablerun
+ \egroup
+ \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
+ \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
+ {\setevalue{\??linetable r:##1x\c!height}{\csname\??linetableheight##1\endcsname}%
+ \setevalue{\??linetable r:##1x\c!depth }{\csname\??linetabledepth ##1\endcsname}%
+ \letgvalue{\??linetableheight##1}\zeropoint
+ \letgvalue{\??linetabledepth ##1}\zeropoint}
+ \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
+ {\setevalue{\??linetable c:##1\c!width}{\csname\??linetablewidth##1\endcsname}%
+ \letgvalue{\??linetablewidth##1}\zeropoint}} % init next table
+
+% todo: store in box instead of macro
+
+\let\stoplinetablehead\relax
+
+\unexpanded\def\startlinetablehead#1\stoplinetablehead
+ {\ifconditional\c_tabl_lines_in_table
+ \t_tabl_lines_head\emptytoks
+ \fi
+ \c_tabl_lines_head_state\plusthree % full
+ \t_tabl_lines_head{#1}%
+ \ifconditional\c_tabl_lines_in_table
+ \tabl_lines_flush_head
+ \fi}
+
+\unexpanded\def\tabl_lines_BH
+ {\ifx\EC\relax
+ % signal, grabbing lines
+ \else
+ \t_tabl_lines_head\emptytoks
+ \fi
+ \pushmacro\BC
+ \pushmacro\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
+ \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead}
+
+\let\startlinetablebody\relax
+\let\stoplinetablebody \relax
+
+\unexpanded\def\processlinetablebuffer
+ {\dosingleempty\tabl_lines_process_buffer}
+
+\def\tabl_lines_process_buffer[#1]%
+ {\bgroup
+ \let\startlinetable\relax
+ \let\stoplinetable \relax
+ \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis
+ \startlinetablerun \getbuffer[#1]\stoplinetablerun
+ \egroup}
+
+\unexpanded\def\processlinetablefile
+ {\dosingleempty\tabl_lines_process_file}
+
+\def\tabl_lines_process_file#1% maybe accept #1 as well as [#1]
+ {\bgroup
+ \let\startlinetable\relax
+ \let\stoplinetable \relax
+ \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis
+ \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun
+ \egroup}
+
+\protect
+
+\continueifinputfile{tabl-ltb.mkiv}
+
+\setuplinetable[n=6,m={2,2,2},lines=25] % m ?
+
+\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red]
+\setuplinetable[c][4] [width=3cm,background=color,backgroundcolor=yellow]
+\setuplinetable[c][6] [width=3cm,background=color,backgroundcolor=magenta]
+\setuplinetable[r][odd] [background=color,backgroundcolor=gray]
+\setuplinetable[r][even][background=color,backgroundcolor=green]
+
+\starttext
+
+\showframe \showstruts
+
+\setupcolors[state=start]
+
+\setuppagenumbering[alternative=doublesided]\page[left]
+
+\startlinetable
+\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR
+\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
+\stoplinetable
+
+\startlinetable
+\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx
+ \NC yy \NC ddddd \NC eeee \NC ff \NC \NR
+\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
+\stoplinetable
+
+% \startbuffer[lt]
+% \NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC ee \NC ff \NC \NR
+% \NC aaa\crlf aaa \NC b \NC cc \NC ddd \NC eeee \NC f \NC \NR
+% \stopbuffer
+%
+% \processlinetablebuffer[lt]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-mis.mkiv
new file mode 100644
index 00000000000..8db31b31d7a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-mis.mkiv
@@ -0,0 +1,289 @@
+%D \module
+%D [ file=tabl-mis,
+%D version=2012.06.28,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Miscellaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Miscellaneous}
+
+\unprotect
+
+%D \macros
+%D {somekindoftab,kindoftabposition}
+%D
+%D This macro can be used to create tabs:
+%D
+%D \starttyping
+%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\kindoftabposition}}}]
+%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\kindoftabposition}}}]
+%D
+%D \starttext
+%D \showframe \dorecurse{10}{test\page}
+%D \stoptext
+%D \stoptyping
+%D
+%D (This rather old but updated code used to be in \type {core-mis.mkiv}.)
+
+\let\kindoftabposition\!!zerocount
+
+\unexpanded\def\somekindoftab
+ {\dosingleempty\typo_kindoftab}
+
+\def\typo_kindoftab[#1]%
+ {\bgroup
+ \getdummyparameters
+ [\c!alternative=\v!vertical,
+ \c!width=\textwidth,\c!height=\textheight,
+ \c!n=\lastpage,\c!m=\realpageno,
+ #1]%
+ \doifelse{\directdummyparameter\c!alternative}\v!vertical
+ {\typo_kindoftab_indeed\vbox\vskip\c!height}
+ {\typo_kindoftab_indeed\hbox\hskip\c!width }}
+
+\def\typo_kindoftab_indeed#1#2#3#4%
+ {#1 to \directdummyparameter#3 \bgroup
+ \forgetall
+ \scratchnx\directdummyparameter\c!n\relax
+ \scratchmx\directdummyparameter\c!m\relax
+ \edef\kindoftabposition{\the\scratchmx}%
+ \ifnum\scratchmx>\plusone
+ #2\zeropoint \s!plus \the\numexpr\scratchmx-\plusone \relax\s!fill\relax
+ \fi
+ #4% can use \kindoftabposition
+ \ifnum\scratchmx<\scratchnx\relax
+ #2\zeropoint \s!plus \the\numexpr\scratchnx-\scratchmx\relax\s!fill\relax
+ \fi
+ \egroup
+ \egroup}
+
+%D The following paragraphs mechanism is probably one of the oldest of
+%D \CONTEXT\ and mostly served as a table mechanism capable of dealing
+%D with paragraphs. Nowadays one can also use tabulate or natural tables.
+%D
+%D \startbuffer
+%D \defineparagraphs[sample][n=2,rule=on]
+%D
+%D \startsample
+%D first \nextsample
+%D second \nextsample
+%D third
+%D \stopsample
+%D
+%D \startsample
+%D \input tufte \nextsample
+%D \input ward \nextsample
+%D \input davis \nextsample
+%D \input zapf
+%D \stopsample
+%D
+%D \startparagraphs[sample]
+%D first \nextsample
+%D second \nextsample
+%D third
+%D \stopparagraphs
+%D
+%D \startparagraphs[sample]
+%D \startparagraphscell
+%D first
+%D \stopparagraphscell
+%D \startparagraphscell
+%D second
+%D \stopparagraphscell
+%D \startparagraphscell
+%D third
+%D \stopparagraphscell
+%D \stopparagraphs
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{paragraphs}
+
+\installcommandhandler \??paragraphs {paragraphs} \??paragraphs
+
+\setupparagraphs
+ [\c!n=3,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=\emwidth,
+ \c!height=\v!fit,
+ \c!width=\availablehsize,
+ \c!rule=\v!off,
+ \c!command=,
+ \c!align=,
+ \c!tolerance=\v!tolerant, % obsolete
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!style=,
+ \c!color=,
+ \c!top=\vss,
+ \c!bottom=\vfill]
+
+\let\typo_paragraphs_setup_saved\setupparagraphs
+
+\unexpanded\def\setupparagraphs
+ {\dotripleempty\typo_paragraphs_setup}
+
+\def\typo_paragraphs_setup[#1][#2][#3]% we are downward compatible with [each] and [1,3]
+ {\ifthirdargument
+ \doifelse{#2}\v!each
+ {\dorecurse{\namedparagraphsparameter{#1}\c!n}%
+ {\normalexpanded{\typo_paragraphs_setup_saved[#1:\recurselevel]}[#3]}}%
+ {\def\typo_paragraphs_setup_step##1{\typo_paragraphs_setup_saved[#1:##1][#3]}%
+ \processcommalist[#2]\typo_paragraphs_setup_step}%
+ \else\ifsecondargument
+ \typo_paragraphs_setup_saved[#1][#2]%
+ \else\iffirstargument
+ \typo_paragraphs_setup_saved[#1]%
+ \fi\fi\fi}
+
+\appendtoks
+ \letvalue{\e!next \currentparagraphs}\nextparagraphs
+ \letvalue\currentparagraphs\nextparagraphs
+ \setuevalue{\e!start\currentparagraphs}{\startparagraphs[\currentparagraphs]}%
+ \letvalue{\e!stop \currentparagraphs}\stopparagraphs
+ %setuevalue{\e!setup\currentparagraph\e!endsetup}{\typo_paragraphs_setup_saved[\currentparagraphs]}%
+ \dorecurse{\paragraphsparameter\c!n}
+ {\normalexpanded{\typo_paragraphs_setup_saved[\currentparagraphs:\recurselevel][\c!width=,\s!parent=\??paragraphs\currentparagraphs]}}%
+ \typo_paragraphs_setup_saved[\currentparagraphs:1][\c!distance=\zeropoint]%
+\to \everydefineparagraphs
+
+\newcount\c_typo_paragraphs_n
+\newcount\c_typo_paragraphs_max
+\newdimen\d_typo_paragraphs_width
+\newdimen\d_typo_paragraphs_auto
+
+\unexpanded\def\startparagraphs[#1]% quite slow
+ {\bgroup % (1)
+ \edef\currentparagraphs{#1}%
+ \paragraphsparameter\c!before
+ \edef\p_width{\paragraphsparameter\c!width}%
+ \ifx\p_width\empty
+ \d_typo_paragraphs_width\availablehsize
+ \else
+ \d_typo_paragraphs_width\p_width\relax
+ \fi
+ \c_typo_paragraphs_max\paragraphsparameter\c!n\relax
+ \d_typo_paragraphs_auto\d_typo_paragraphs_width\relax
+ \scratchcounter\zerocount
+ \dorecurse\c_typo_paragraphs_max
+ {\edef\p_width{\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!width}%
+ \ifx\p_width\empty
+ \advance\scratchcounter\plusone
+ \else
+ \advance\d_typo_paragraphs_auto-\p_width\relax
+ \fi
+ \ifnum\recurselevel>\plusone
+ \advance\d_typo_paragraphs_auto-\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!distance\relax
+ \fi}%
+ \ifnum\scratchcounter>\zerocount
+ \divide\d_typo_paragraphs_auto\scratchcounter
+ \else
+ \d_typo_paragraphs_auto\zeropoint
+ \fi
+ \parindent\zeropoint
+ \c_typo_paragraphs_n\zerocount
+ \let\\=\typo_paragraphs_next % downward compatible
+ \dontleavehmode\hbox
+ \bgroup % (2)
+ \forgetall
+ \let\typo_paragraphs_start_cell\typo_paragraphs_start_cell_indeed
+ \let\typo_paragraphs_stop_cell \typo_paragraphs_stop_cell_indeed
+ \typo_paragraphs_start_cell_indeed}
+
+\unexpanded\def\stopparagraphs
+ {\stopparagraphscell
+ \egroup % (2)
+ \paragraphsparameter\c!after
+ \egroup} % (1)
+
+\unexpanded\def\nextparagraphs
+ {\stopparagraphscell
+ \startparagraphscell}
+
+\unexpanded\def\startparagraphscell
+ {\typo_paragraphs_start_cell}
+
+\def\typo_paragraphs_start_cell_indeed
+ {\removeunwantedspaces
+ \advance\c_typo_paragraphs_n\plusone
+ \ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max
+ \expandafter\typo_paragraphs_start_cell_nop
+ \else
+ \expandafter\typo_paragraphs_start_cell_yes
+ \fi}
+
+\def\typo_paragraphs_start_cell_nop
+ {\begingroup
+ % message: too many cells in paragraphs
+ \let\typo_paragraphs_start_cell\relax
+ \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed
+ \setbox\scratchbox\vbox\bgroup}
+
+\def\typo_paragraphs_start_cell_yes
+ {\begingroup
+ \let\typo_paragraphs_start_cell\relax
+ \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed
+ \edef\currentparagraphs{\currentparagraphs:\the\c_typo_paragraphs_n}%
+ \ifnum\c_typo_paragraphs_n>\plusone
+ \typo_paragraphs_separator
+ \fi
+ \edef\p_height{\paragraphsparameter\c!height}%
+ \edef\p_width {\paragraphsparameter\c!width }%
+ \useparagraphsstyleandcolor\c!style\c!color
+ \setbox\scratchbox\vtop \ifx\p_height\empty \else\ifx\p_height\v!fit \else to \p_height \fi\fi
+ \bgroup % (2)
+ \blank[\v!disable]%
+ \paragraphsparameter\c!top
+ \hsize\ifx\p_width\empty \d_typo_paragraphs_auto \else \p_width \fi \relax
+ \usealignparameter\paragraphsparameter
+ \paragraphsparameter\c!inner
+ \everypar{\begstrut\everypar\emptytoks}%
+ \ignorespaces
+ \paragraphsparameter\c!command}
+
+\unexpanded\def\stopparagraphscell
+ {\typo_paragraphs_stop_cell
+ \let\typo_paragraphs_stop_cell\relax}
+
+\def\typo_paragraphs_stop_cell_indeed
+ {\ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max
+ \expandafter\typo_paragraphs_stop_cell_nop
+ \else
+ \expandafter\typo_paragraphs_stop_cell_yes
+ \fi}
+
+\def\typo_paragraphs_stop_cell_nop
+ {\egroup
+ \endgroup}
+
+\def\typo_paragraphs_stop_cell_yes
+ {\ifvmode
+ \removelastskip
+ \else
+ \removeunwantedspaces
+ \endstrut
+ \endgraf
+ \fi
+ \paragraphsparameter\c!bottom
+ \egroup % (2)
+ \dontleavehmode\hpack{\raise\strutheight\box\scratchbox}%
+ \endgroup}
+
+\def\typo_paragraphs_separator
+ {\scratchdistance\paragraphsparameter\c!distance
+ \doif{\paragraphsparameter\c!rule}\v!on
+ {\scratchwidth\paragraphsparameter\c!rulethickness
+ \scratchdistance\dimexpr(\scratchdistance-\scratchwidth)/2\relax
+ \hskip\scratchdistance
+ \color[\paragraphsparameter\c!rulecolor]{\vrule\s!width\scratchwidth}}%
+ \hskip\scratchdistance}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv
new file mode 100644
index 00000000000..78e867546b4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv
@@ -0,0 +1,2118 @@
+%D \module
+%D [ file=tabl-ntb,
+%D version=2000.04.18,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module has a more modern variant in xtables but as we follow a bit
+%D different approach with settings there, this mechanism will stay. In fact
+%D each of them has its advantages. This module could be sped up a bit and made
+%D more efficient by delegating some housekeeping to \LUA\ but it's not worth
+%D the effort. The code could me made more readable but again, there is no
+%D real purpose in it. If needed I can squeeze out a few more percentages
+%D runtime.
+
+% columndistance 'optimized' ... needs checking
+%
+% we don't need the alignment mechanism .. we can just pack the row in a box
+
+\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
+
+% sometimes this helps (with nc going wild): \setupTABLE[maxwidth=100cm]
+%
+% bug: width 3cm is not honored and column becomes too wide
+% as given width is added to distributed width
+%
+% \bTABLE
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD[width=3cm] \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \eTABLE
+
+% \unexpanded\def\startrow {\bTR}
+% \unexpanded\def\stoprow {\eTR}
+% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD}
+% \let\stopcell \relax
+% \let\startcelltable \bTABLE
+% \let\stopcelltable \eTABLE
+
+% \starttext
+% \startcelltable
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \stopcelltable
+% \stoptext
+
+%D As always, this is the n\high{th} version. Much time went in
+%D trying to speed up the many cell calculations, some
+%D optimizations were rejected in order not to complicate this
+%D module too much (and in order to prevail extensibility). In the
+%D meantime we've sacrified some speed for readability.
+
+\unprotect
+
+%D The next alternative also takes care of preceding and following
+%D white space.
+%D
+%D \startbuffer
+%D \bTABLE[left={(},right={)},top=\startnarrower,bottom=\stopnarrower]
+%D \bTR \bTD something \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi % todo: namespace
+\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi % todo: namespace
+
+\let\tabl_ntb_next_level\relax
+
+\newtoks\t_tabl_ntb_cell_start
+\newtoks\t_tabl_ntb_cell_stop
+
+\appendtoks
+ \naturaltablelocalparameter\c!left
+ \delayedbegstrut
+\to \t_tabl_ntb_cell_start
+
+\appendtoks
+ \delayedendstrut
+ \naturaltablelocalparameter\c!right
+\to \t_tabl_ntb_cell_stop
+
+\appendtoks
+ \flushpostponednodedata
+ % maybe: \the\neverypar
+\to \t_tabl_ntb_cell_start
+
+\unexpanded\def\tabl_ntb_cell_start
+ {% \inhibitblank
+ \dotagTABLEcell
+ %\tabl_ntb_next_level
+ \usenaturaltablelocalstyleandcolor\c!style\c!color
+ \everypar\t_tabl_ntb_cell_start}
+
+\unexpanded\def\tabl_ntb_cell_stop
+ {\ifhmode
+ \the\t_tabl_ntb_cell_stop
+ \par % added 13/4/2006
+ \else
+ % not sure yet:\naturaltablelocalparameter\c!right
+ \par
+ \ifdim\prevdepth<\zeropoint % =-1000pt ?
+ \vskip-\strutdp
+ \else
+ \removebottomthings
+ \fi
+ \fi}
+
+\newcount\c_tabl_ntb_row
+\newcount\c_tabl_ntb_col
+\newcount\c_tabl_ntb_spn
+
+\newcount\c_tabl_ntb_nx
+\newcount\c_tabl_ntb_ny
+
+\setnewconstant\c_tabl_ntb_cell \plusone
+\setnewconstant\c_tabl_ntb_none \plustwo
+
+\newcount\c_tabl_ntb_current_row
+\newcount\c_tabl_ntb_current_col
+\newcount\c_tabl_ntb_current_row_one
+\newcount\c_tabl_ntb_current_col_one
+\newcount\c_tabl_ntb_current_row_two
+\newcount\c_tabl_ntb_current_col_two
+\newcount\c_tabl_ntb_current_row_three
+\newcount\c_tabl_ntb_current_col_three
+\newcount\c_tabl_ntb_current_row_four
+\newcount\c_tabl_ntb_current_col_four
+
+\newcount\c_tabl_ntb_running_col
+\newcount\c_tabl_ntb_maximum_row
+\newcount\c_tabl_ntb_maximum_col
+\newcount\c_tabl_ntb_maximum_row_span
+\newcount\c_tabl_ntb_maximum_col_span
+
+\newcount\c_tabl_ntb_encountered_col
+\newcount\c_tabl_ntb_encountered_max
+
+\newtoks\t_tabl_ntb
+\newtoks\t_tabl_ntb_row
+
+\newconstant\c_tabl_tbl_pass
+
+\newtoks\t_tabl_ntb_head
+\newtoks\t_tabl_ntb_next
+\newtoks\t_tabl_ntb_body
+\newtoks\t_tabl_ntb_foot
+
+\newcount\c_tabl_ntb_n_of_head_lines
+\newcount\c_tabl_ntb_n_of_next_lines
+\newcount\c_tabl_ntb_n_of_hdnx_lines
+
+\newdimen\d_tabl_ntb_height
+\newdimen\d_tabl_ntb_width
+
+\newdimen\d_tabl_ntb_leftmargindistance
+\newdimen\d_tabl_ntb_rightmargindistance
+\newdimen\d_tabl_ntb_columndistance
+\newdimen\d_tabl_ntb_maxwidth
+
+\newtoks\everyTABLEpass % public
+
+\newcount\tablecellrows % public (needs checking)
+\newcount\tablecellcolumns % public (needs checking)
+
+\newbox\b_tabl_ntb_final
+
+%D We have already prepared the previous macros for nesting,
+%D so we only have to pop in the right ones:
+
+\newcount\c_tabl_level
+
+\unexpanded\def\tabl_ntb_table_push
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \tabl_ntb_parameters_reset
+ % we need a proper count push/pop
+ \xdef\m_tabl_ntb_saved_row{\the\c_tabl_ntb_row}\globalpushmacro\m_tabl_ntb_saved_row
+ \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\globalpushmacro\m_tabl_ntb_saved_col
+ \else
+ \global\intabletrue
+ \fi}
+
+\unexpanded\def\tabl_ntb_table_pop
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \globalpopmacro\m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row
+ \globalpopmacro\m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col
+ \else
+ \global\intablefalse
+ \fi}
+
+\unexpanded\def\tabl_ntb_next_level
+ {\advance\c_tabl_level\plusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\unexpanded\def\tabl_ntb_prev_level
+ {\advance\c_tabl_level\minusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\tabl_ntb_next_level % go to level 1
+
+\installcorenamespace{naturaltable} % was tbl
+\installcorenamespace{naturaltablelocal} % was tbltbl
+
+\installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable
+\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal
+
+\installcorenamespace{naturaltabletal}
+\installcorenamespace{naturaltablegal}
+\installcorenamespace{naturaltablenob}
+\installcorenamespace{naturaltabletag}
+\installcorenamespace{naturaltablecol}
+\installcorenamespace{naturaltablerow}
+\installcorenamespace{naturaltablewd}
+\installcorenamespace{naturaltableht}
+\installcorenamespace{naturaltabledp}
+\installcorenamespace{naturaltablewid}
+\installcorenamespace{naturaltablehei}
+\installcorenamespace{naturaltabledis}
+\installcorenamespace{naturaltableaut}
+%installcorenamespace{naturaltablefwd} % forcedwidth
+\installcorenamespace{naturaltabletxt}
+\installcorenamespace{naturaltablespn}
+\installcorenamespace{naturaltableref}
+\installcorenamespace{naturaltableset}
+\installcorenamespace{naturaltablecell}
+\installcorenamespace{naturaltablesqueeze}
+\installcorenamespace{naturaltabletok}
+
+\letvalue{\??naturaltablesqueeze }\donefalse
+\letvalue{\??naturaltablesqueeze\v!fit }\donetrue
+\letvalue{\??naturaltablesqueeze\v!fixed}\donetrue
+\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_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_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}
+\def\tabl_ntb_get_nob#1{\ifcsname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone\else\zerocount\fi}
+
+\def\tabl_ntb_set_tag#1#2{\expandafter\edef\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_col#1#2{\expandafter\edef\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_row#1#2{\expandafter\edef\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_let_tag#1#2{\expandafter\let\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_col#1#2{\expandafter\let\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_row#1#2{\expandafter\let\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_wd#1#2{\expandafter\xdef\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_set_ht#1#2{\expandafter\xdef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+\def\tabl_ntb_let_wd#1#2{\global\expandafter\let\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_let_ht#1#2{\global\expandafter\let\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+\def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_wid#1{\expandafter\xdef\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_hei#1{\expandafter\xdef\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_dis#1{\expandafter\xdef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_aut#1{\expandafter\xdef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_let_wid#1{\global\expandafter\let\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_hei#1{\global\expandafter\let\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_dis#1{\global\expandafter\let\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_aut#1{\global\expandafter\let\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_aut#1{\csname \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname}
+
+\def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2}
+
+\def\tabl_ntb_tag_doif #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+\def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\def\tabl_ntb_row_doif #1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doif #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+
+% not used
+%
+% \def\tabl_ntb_tag_state#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_row_state#1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_col_state#1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+
+%def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
+%def\tabl_ntb_spn_doifelse#1{\doifelse {\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname}\!!plusone}
+
+%def\tabl_ntb_set_spn #1{\setvalue {\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
+%def\tabl_ntb_spn_doifelse#1{\doifelsevalue{\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
+
+\def\tabl_ntb_let_ref #1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_ref #1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+%def\tabl_ntb_get_ref #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
+\def\tabl_ntb_get_ref #1#2{\begincsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
+\def\tabl_ntb_spn_doifelse#1{\ifcase0\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname\relax % could be inlined
+ \expandafter\secondoftwoarguments % unset
+ \else
+ \expandafter\firstoftwoarguments % a span
+ \fi}
+
+% keep for a while:
+%
+% \unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level
+% {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\expandafter\endcsname\expandafter
+% {\expandafter\def\expandafter\m_tabl_tbl_level\expandafter{\m_tabl_tbl_level}\tabl_ntb_cell_process{#3}{#4}[#5]{#6}}}
+
+\unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
+ {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname
+ {\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_ntb_next_level#6\tabl_ntb_prev_level}}}
+
+\def\tabl_ntb_get_txt#1#2%
+ {\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+% to be changed:
+
+\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells
+\newif\ifautosqueezeTBLspan \autosqueezeTBLspantrue % unless explicit widths are given
+\newif\ifautoTBLspread \autoTBLspreadfalse
+\newif\ifautoTBLhsize \autoTBLhsizetrue
+\newif\ifautoTBLrowspan \autoTBLrowspantrue
+\newif\ifautoTBLemptycell \autoTBLemptycelltrue
+\newif\ifautoTBLcheckwidth \autoTBLcheckwidthtrue
+\newif\ifappendTBLsetups \appendTBLsetupstrue
+\newif\ifenableTBLbreak \enableTBLbreakfalse
+\newif\ifmultipleTBLheads \multipleTBLheadsfalse
+\newif\iftightTBLrowspan \tightTBLrowspantrue
+\newif\iftightTBLcolspan \tightTBLcolspanfalse
+
+\newif\iftraceTABLE \traceTABLEfalse
+
+% so far
+
+\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{}
+
+\unexpanded\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax
+\unexpanded\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax
+\unexpanded\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax
+
+\unexpanded\def\setupTABLE
+ {\dotripleempty\tabl_ntb_setup}
+
+\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+
+\def\tabl_ntb_setup
+ {\ifthirdargument
+ \expandafter\tabl_ntb_setup_three
+ \else\ifsecondargument
+ \doubleexpandafter\tabl_ntb_setup_two
+ \else
+ \doubleexpandafter\tabl_ntb_setup_one
+ \fi\fi}
+
+\def\tabl_ntb_setup_one[#1][#2][#3]%
+ {\setupcurrentnaturaltablelocal[#1]}
+
+\def\tabl_ntb_setup_xy[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[#1##1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_un[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1%
+ {\def\tabl_ntb_setup_step_step####1{\tabl_ntb_parameters_set[\c!x##1\c!y####1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step_step}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_each[#1][#2][#3]% ignores #3
+ {\tabl_ntb_parameters_set[#1\v!each][#2]}
+
+\def\tabl_ntb_setup_ux[#1][#2][#3]% ignores #3
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[\c!x##1][#2]}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\installcorenamespace{naturaltablesetupthree}
+\installcorenamespace{naturaltablesetuptwo}
+
+%def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+%def\tabl_ntb_setup_two [#1]{\csname\??naturaltablesetuptwo \ifcsname\??naturaltablesetuptwo #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+
+\def\tabl_ntb_setup_three[#1]{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi[#1]}
+\def\tabl_ntb_setup_two [#1]{\ifcsname\??naturaltablesetuptwo #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi[#1]}
+
+\setvalue{\??naturaltablesetupthree \v!row}[#1]{\tabl_ntb_setup_xy [\c!y]}
+\setvalue{\??naturaltablesetupthree \v!column}[#1]{\tabl_ntb_setup_xy [\c!x]}
+\setvalue{\??naturaltablesetupthree \v!start}[#1]{\tabl_ntb_setup_xy [\v!start]}
+\setvalue{\??naturaltablesetupthree \v!header}[#1]{\tabl_ntb_setup_xy [\v!header]}
+
+\setvalue{\??naturaltablesetuptwo \v!row}[#1]{\tabl_ntb_setup_each[\c!y]}
+\setvalue{\??naturaltablesetuptwo \v!column}[#1]{\tabl_ntb_setup_each[\c!x]}
+\setvalue{\??naturaltablesetuptwo \v!start}[#1]{\tabl_ntb_setup_each[\v!start]}
+\setvalue{\??naturaltablesetuptwo \v!header}[#1]{\tabl_ntb_setup_each[\v!header]}
+
+\letvalue{\??naturaltablesetupthree\s!unknown}\tabl_ntb_setup_un
+\letvalue{\??naturaltablesetuptwo \s!unknown}\tabl_ntb_setup_ux
+
+\letcsnamecsname\csname\??naturaltablesetupthree r\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree c\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree y\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree x\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+
+\letcsnamecsname\csname\??naturaltablesetuptwo r\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo c\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo y\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo x\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+
+\def\tabl_ntb_parameters_set[#1][#2]%
+ {\ifappendTBLsetups
+ \ifcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
+ \def\tabl_ntb_parameters_get[##1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}%
+ \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
+ \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+ \else
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi
+ \else
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi}
+
+% % \setupTABLE [y] [first][background=color,backgroundcolor=blue,frame=off,bottomframe=on,topframe=on,framecolor=white]
+% \setupTABLE [first][first][backgroundcorner=2,corner=10,frame=on]
+% \setupTABLE [last] [first][backgroundcorner=4,corner=12,frame=on]
+%
+% \setupTABLE [row] [each] [background=color,backgroundcolor=blue,frame=on,framecolor=white]
+% \setupTABLE [first][2] [corner=8]
+% \setupTABLE [last] [2] [corner=5]
+% \setupTABLE [first][last] [corner=7]
+% \setupTABLE [last] [last] [corner=6]
+%
+% \startTEXpage
+% \bTABLE[frame=off,align=middle]
+% \bTR \bTD one \eTD \bTD two \eTD \bTD three \eTD \eTR
+% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
+% \bTR \bTD alpha \eTD \bTD beta \eTD \bTD gamma \eTD \eTR
+% \eTABLE
+% \stopTEXpage
+%
+% \setupTABLE [first] [two][corner=2] % special case
+% \setupTABLE [last] [two][corner=4] % special case
+%
+% % % \setupTABLE [one] [first] ... special case of span
+%
+% \startTEXpage
+% \bTABLE[frame=off,align=middle]
+% \bTR \bTD one \eTD \bTD two \eTD \bTD three \eTD \eTR
+% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
+% \eTABLE
+% \stopTEXpage
+
+%D By default rowspans are tight but you can change that:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR[height=20pt] \bTH 1. col \eTH \bTH 2. col \eTH \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \bTD[nr=2] 2 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 1. col\eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=3] 3 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \eTABLE
+%D
+%D \bTABLE
+%D \bTR[height=20pt] \bTH 2. col \eTH \bTH 1. col \eTH \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 2. col \eTD \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 1. col\eTD \eTR
+%D \bTR[height=20pt] \bTD[nr=3] 3 rows in 2. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \bTR[height=20pt] \bTD 1 row in 1. col \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D With \type {\tightTBLrowspanfalse} we get:
+%D
+%D \start \tightTBLrowspanfalse \getbuffer \stop
+
+\let\tabl_ntb_setup_section\relax
+
+\unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
+ {\tabl_ntb_setup_section % already forgotten
+ \edef\m_tabl_ntb_positive_row{\number#1}%
+ \edef\m_tabl_ntb_positive_col{\number#2}%
+ \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}%
+ \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}%
+ % saves tokens (no speed gain)
+ \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}%
+ % each each
+ \begincsname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!y\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!each\endcsname
+ % odd even
+ \begincsname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+ % row/col number combinations
+ \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+ % first/last combinations
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!y\v!first\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \begincsname\m_tabl_ntb_prefix\c!y\v!last\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
+ \fi\fi
+ % special case: two rows and last row : two&first and two&last (round corners)
+ \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
+ \fi\fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
+ \fi\fi
+ \fi
+ \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
+ \fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
+ \fi
+ \fi
+ % header things
+ \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
+ \begincsname\m_tabl_ntb_prefix\v!header\v!each\endcsname
+ \begincsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname
+ \fi
+ % explicit cells
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname
+ \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname
+ % local
+ \begincsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname
+ % done
+ \relax}
+
+% we cannot use +n (checking on number/last/first would slow down too much)
+%
+% \setupTABLE[r] [2][color=red]
+% \setupTABLE[r] [-2][color=red]
+% \setupTABLE[c] [2][color=green]
+% \setupTABLE[c] [-2][color=green]
+% \setupTABLE[4] [4][color=blue]
+% \setupTABLE[-4][-4][color=blue]
+%
+% \bTABLE
+% \dorecurse{10}{\bTR \dorecurse{6}{\bTD xxx \eTD} \eTR}
+% \eTABLE
+
+\let\m_tabl_ntb_before_split\empty
+\let\m_tabl_ntb_after_split \empty
+\let\m_tabl_ntb_same_page \empty
+
+% split + page:
+%
+% \bTABLE[split=yes]
+% \bTR \bTD left \eTD\bTD right \eTD\eTR
+% \bTR[after=\page] \bTD left \eTD\bTD right \eTD\eTR
+% \bTR \bTD left \eTD\bTD right \eTD\eTR
+% \eTABLE
+
+\unexpanded\def\tabl_ntb_tr
+ {\c_tabl_ntb_running_col\zerocount
+ \c_tabl_ntb_encountered_col\zerocount
+ \advance\c_tabl_ntb_maximum_row\plusone
+ \iffirstargument
+ \expandafter\tabl_ntb_tr_yes
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
+
+\def\tabl_ntb_tr_yes[#1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_maximum_row}{\setupcurrentnaturaltablelocal[#1]}}
+
+\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr}
+\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc}
+
+\unexpanded\def\tabl_ntb_td
+ {\advance\c_tabl_ntb_encountered_col\plusone
+ \iffirstargument
+ \expandafter\tabl_ntb_td_yes
+ \else
+ \expandafter\tabl_ntb_td_nop
+ \fi}
+
+\def\tabl_ntb_td_yes[#1]#2\eTD
+ {\letnaturaltableparameter\c!ny \m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx \m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc \plusone
+ \letnaturaltableparameter\c!nr \plusone
+ \letnaturaltableparameter\c!n \c_tabl_ntb_running_col
+ \letnaturaltableparameter\c!m \empty
+ \letnaturaltableparameter\c!action\empty % not that important
+ \setupcurrentnaturaltable[#1]%
+ %
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ % goto first cell n/m=cellnumber
+ \edef\m_tabl_ntb_n{\naturaltableparameter\c!n}%
+ \edef\m_tabl_ntb_m{\naturaltableparameter\c!m}%
+ %
+ \ifx\m_tabl_ntb_n\empty
+ \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax
+ \else\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_n{#1}%
+ \fi\fi
+ \ifx\m_tabl_ntb_m\empty \else
+ \ifnum\m_tabl_ntb_m=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_m{#1}%
+ \fi
+ \fi
+ \doloop % skip over columns that result from earlier span
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
+ % fill r*c cells and set span
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ \ifnum\c_tabl_ntb_nx=\plusone
+ \ifnum\c_tabl_ntb_ny=\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
+ \fi
+ \else
+ \tabl_ntb_cell_preset
+ \fi
+ \else
+ \tabl_ntb_cell_preset
+ \fi
+ % set values
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
+ % the action key will change!
+ \tabl_ntb_set_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\naturaltableparameter\c!action}%
+ % save text
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}%
+ \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
+ \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
+ \fi}
+
+\def\tabl_ntb_td_nop[#1]#2\eTD
+ {\global\advance\c_tabl_ntb_spn\plusone\relax
+ \doloop
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
+ \c_tabl_ntb_nx\plusone
+ \c_tabl_ntb_ny\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
+ \fi
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
+ \tabl_ntb_let_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\empty
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}%
+ \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
+ \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
+ \fi}
+
+\def\tabl_ntb_td_pass_n#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \ifnum\scratchcounter>\zerocount
+ \normalexpanded{\tabl_ntb_td[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD
+ \fi
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_td_pass_m#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \dorecurse\scratchcounter{\normalexpanded{\tabl_ntb_td[\c!n=,\c!m=]}\eTD}%
+ % can be sped up
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_cell_preset
+ {\c_tabl_ntb_current_row\c_tabl_ntb_maximum_row
+ \c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \dorecurse\c_tabl_ntb_ny\tabl_ntb_cell_preset_rows
+ % check max column
+ \advance\c_tabl_ntb_current_col\minusone
+ \ifnum\c_tabl_ntb_current_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_current_col
+ \fi}
+
+\def\tabl_ntb_cell_preset_rows
+ {\c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_nx}%
+ \ifnum\c_tabl_ntb_nx>\c_tabl_ntb_maximum_row_span\relax
+ \c_tabl_ntb_maximum_row_span\c_tabl_ntb_nx
+ \fi
+ \dorecurse\c_tabl_ntb_nx\tabl_ntb_cell_preset_cells
+ \advance\c_tabl_ntb_current_row\plusone}
+
+\def\tabl_ntb_cell_preset_cells
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col\plusone}
+
+%D The usage of n and m:
+%D
+%D \startbuffer
+%D \bTABLE[width=3em]
+%D \bTR\bTD d1 \eTD\bTD[n=2] d2 \eTD\bTD[n=5] d5 \eTD\bTD[n=7] d7 \eTD\eTR
+%D \bTR\bTD f1 \eTD\bTD[n=4] f4 \eTD\bTD[n=5] f5 \eTD\bTD[n=7] f7 \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \bTABLE[width=3em]
+%D \bTR\bTD d1 \eTD\bTD[m=2] d2 \eTD\bTD[m=5] d5 \eTD\bTD[m=7] d7 \eTD\eTR
+%D \bTR\bTD f1 \eTD\bTD[m=4] f4 \eTD\bTD[m=5] f5 \eTD\bTD[m=7] f7 \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \bTABLE[frame=on]
+%D \bTR \bTH[nc=3] One \eTH \bTH[m=4] Four \eTH\eTR
+%D \bTR \bTD a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \eTABLE
+%D
+%D \bTABLE[frame=on]
+%D \bTR \bTH[nr=2] One \eTH \bTH[m=3] Three \eTH\eTR
+%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\tabl_ntb_th[#1]#2\eTH
+ {\tabl_ntb_td[#1,\c!color=\naturaltablelocalparameter\c!headcolor,\c!style=\naturaltablelocalparameter\c!headstyle,\c!aligncharacter=\v!no]#2\eTD}
+
+\def\tabl_ntb_tn[#1]#2\eTN
+ {\tabl_ntb_td[#1]\digits#2\relax\eTD}
+
+%D Vit Zyka needed the option to create a distance between columns, so I
+%D added support for individual column distances.
+%D
+%D \startbuffer
+%D % \setupTABLE[c][each][distance=2em]
+%D \setupTABLE[c][1][distance=2em]
+%D \setupTABLE[c][2][distance=3em]
+%D
+%D \bTABLE
+%D \bTR \bTD test \eTD \bTD test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD[nx=2] test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD test \eTD \bTD[nx=2] test \eTD \eTR
+%D \eTABLE
+%D
+%D \bTABLE[option=stretch]
+%D \bTR \bTD test \eTD \bTD test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD[nx=2] test \eTD \bTD test \eTD \eTR
+%D \bTR \bTD test \eTD \bTD[nx=2] test \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+%D
+%D and he provided patches for the global left and right margin distances
+%D as well as the columndistance (although i changed the names -). Here
+%D is his testcase:
+%D
+%D \startbuffer
+%D \framed[offset=overlay]\bgroup
+%D \setupTABLE[column][2][align=left]%
+%D \setupTABLE[column][3][align=right]%
+%D \bTABLE[columndistance=2cm,leftmargindistance=.3cm,rightmargindistance=.5cm]
+%D \bTR \bTH[nc=3] Table head\eTH \eTR
+%D \bTR \bTD[nc=2] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD[nc=2,align=left] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD[nc=2,align=middle] AB\eTD \bTD C\eTD \eTR
+%D \bTR \bTD A\eTD \bTD B\eTD \bTD C\eTD \eTR
+%D \bTR \bTD Aa\eTD \bTD Bb\eTD \bTD Cccc\eTD \eTR
+%D \bTR \bTD[nc=3,align=middle] ABC\eTD \eTR
+%D \eTABLE
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+% to be done: head <raw> foot, dus state var
+
+\unexpanded\def\bTABLEhead{\dosingleempty\tabl_ntb_head} \let\eTABLEhead\relax
+\unexpanded\def\bTABLEnext{\dosingleempty\tabl_ntb_next} \let\eTABLEnext\relax
+\unexpanded\def\bTABLEbody{\dosingleempty\tabl_ntb_body} \let\eTABLEbody\relax
+\unexpanded\def\bTABLEfoot{\dosingleempty\tabl_ntb_foot} \let\eTABLEfoot\relax
+
+\def\tabl_ntb_head[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\def\tabl_ntb_next[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\def\tabl_ntb_body[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\def\tabl_ntb_foot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
+
+\def\tabl_ntb_section[#1]#2% also used in tabl-nte
+ {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
+ #2%
+ \let\tabl_ntb_setup_section\relax}
+
+\def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
+ {\begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+ \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
+ \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname}
+
+\unexpanded\def\bTABLE
+ {\dosingleempty\tabl_ntb_table}
+
+\def\tabl_ntb_table[#1]%
+ {\tabl_ntb_table_push
+ % box not here
+ \bgroup
+ \pushpostponednodedata
+ \t_tabl_ntb_head\emptytoks
+ \t_tabl_ntb_next\emptytoks
+ \t_tabl_ntb_body\emptytoks
+ \t_tabl_ntb_foot\emptytoks
+ \ifhmode\kern\zeropoint\fi % blocks \removeunwantedspaces: check this on icare handelingsschema
+ \resetcharacteralign % new
+ \setupcurrentnaturaltablelocal[\c!align={\v!right,\v!broad,\v!high},#1]%
+ %
+ \d_tabl_ntb_leftmargindistance \naturaltablelocalparameter\c!leftmargindistance\relax
+ \d_tabl_ntb_rightmargindistance\naturaltablelocalparameter\c!rightmargindistance\relax
+ \d_tabl_ntb_columndistance \naturaltablelocalparameter\c!columndistance\relax
+ \d_tabl_ntb_maxwidth \naturaltablelocalparameter\c!maxwidth\relax
+ %
+ \usesetupsparameter\naturaltablelocalparameter
+ \doifelse{\naturaltablelocalparameter\c!textwidth}\v!local
+ {\hsize\availablehsize}
+ {\hsize\naturaltablelocalparameter\c!textwidth}%
+ \enableTBLbreakfalse
+ \multipleTBLheadsfalse
+ \autoTBLspreadfalse
+ \tightTBLcolspanfalse
+ \processaction
+ [\naturaltablelocalparameter\c!split]
+ [ \v!yes=>\enableTBLbreaktrue,
+ \v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue,
+ \v!auto=>\ifinsidesplitfloat\enableTBLbreaktrue\fi]
+ \processaction
+ [\naturaltablelocalparameter\c!header]
+ [\v!repeat=>\multipleTBLheadstrue]%
+ \tabl_ntb_preset_parameters
+ \processallactionsinset
+ [\naturaltablelocalparameter\c!option]
+ [\v!stretch=>\autoTBLspreadtrue,%
+ \v!tight=>\tightTBLcolspantrue]%
+ \linewidth\naturaltablelocalparameter\c!rulethickness % needs to be frozen
+ \dontcomplain
+ \c_tabl_ntb_running_col \zerocount
+ \c_tabl_ntb_maximum_col \zerocount
+ \c_tabl_ntb_maximum_row \zerocount
+ \c_tabl_ntb_maximum_row_span\plusone
+ \let\currentTABLErow \tabl_ntb_current_row
+ \let\currentTABLEcolumn\tabl_ntb_current_column
+ \let\nofTABLErows \tabl_ntb_n_of_rows
+ \let\nofTABLEcolumns \tabl_ntb_n_of_columns
+ \let\bTR\dobTR
+ \let\bTD\dobTD
+ \let\bTH\dobTH
+ \let\bTN\dobTN}
+
+\def\tabl_ntb_current_row {\m_tabl_ntb_positive_row}
+\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col}
+\def\tabl_ntb_n_of_rows {\number\c_tabl_ntb_maximum_row}
+\def\tabl_ntb_n_of_columns {\number\c_tabl_ntb_maximum_col}
+
+\let\currentTABLErow \!!zerocount
+\let\currentTABLEcolumn\!!zerocount
+\let\nofTABLErows \!!zerocount
+\let\nofTABLEcolumns \!!zerocount
+
+\unexpanded\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte
+\unexpanded\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte
+\unexpanded\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte
+\unexpanded\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte
+
+% permits \expanded{\bTD ... \eTD}
+
+\let\bTR\relax \unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows
+\let\bTD\relax \unexpanded\def\eTD{\ignorespaces}
+\let\bTH\relax \unexpanded\def\eTH{\ignorespaces}
+\let\bTN\relax \unexpanded\def\eTN{\ignorespaces}
+
+\unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
+ {% tricky and dirty order -)
+ \doifelsesometoks\t_tabl_ntb_head % slow, better a flag
+ {\the\t_tabl_ntb_head
+ \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax
+ \doifelsesometoks\t_tabl_ntb_next
+ {\the\t_tabl_ntb_next
+ \c_tabl_ntb_n_of_next_lines\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines\relax}%
+ {\c_tabl_ntb_n_of_next_lines\zerocount}% was 1
+ \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row}
+ {\c_tabl_ntb_n_of_head_lines\zerocount % was 1
+ \c_tabl_ntb_n_of_next_lines\zerocount
+ \c_tabl_ntb_n_of_hdnx_lines\zerocount}%
+ \the\t_tabl_ntb_body
+ \the\t_tabl_ntb_foot
+ \removeunwantedspaces % only if hmode
+ % finish cells
+ \tabl_ntb_loop_one
+ % to be sure
+ \tabl_ntb_loop_two
+ % check and do
+ \ifcase\c_tabl_ntb_maximum_col\else
+ \startTBLprocessing
+ \tabl_ntb_table_start
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_row_start
+ \c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \normalexpanded{\tabl_ntb_cell{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}}%
+ \tabl_ntb_row_stop}%
+ \removeunwantedspaces % only if hmode
+ \tabl_ntb_table_stop
+ \stopTBLprocessing
+ % wrong ! ! ! better to have an auto-offset-overlay
+ % \ifnum\m_tabl_tbl_level>1
+ % \vskip-\strutdp
+ % \fi
+ \fi
+ % tracing
+ % \iftrue
+ % \blank \tttf
+ % \dorecurse\c_tabl_ntb_maximum_row
+ % {\c_tabl_ntb_current_row\recurselevel\relax
+ % \dorecurse\c_tabl_ntb_maximum_col
+ % {\c_tabl_ntb_current_col\recurselevel\relax
+ % [r=\the\c_tabl_ntb_current_row,c=\the\c_tabl_ntb_current_col,h=\the\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col,w=\the\dimexpr\tabl_ntb_get_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col]}%
+ % \par}%
+ % \blank
+ % \fi
+ \poppostponednodedata
+ \egroup
+ \tabl_ntb_table_pop}
+
+\def\tabl_ntb_loop_one
+ {\dorecurse\c_tabl_ntb_maximum_row{\tabl_ntb_loop_one_rows}}
+
+\def\tabl_ntb_loop_one_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_one_cells}
+
+\def\tabl_ntb_loop_one_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_loop_one_cells_indeed
+ \fi}
+
+\def\tabl_ntb_loop_one_cells_indeed
+ {\c_tabl_ntb_current_col_two\c_tabl_ntb_current_col
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \doloop
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \doloop
+ {\ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
+ \else
+ \advance\c_tabl_ntb_current_col_one\plusone
+ \ifnum\c_tabl_ntb_current_col_one>\c_tabl_ntb_maximum_col\relax
+ \exitloop
+ \fi
+ \fi}%
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
+ \else
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row_one
+ \c_tabl_ntb_current_col_two\c_tabl_ntb_current_col_one
+ \advance\c_tabl_ntb_current_row_one\plusone
+ \ifnum\c_tabl_ntb_current_row_one>\c_tabl_ntb_maximum_row
+ \exitloop
+ \fi
+ \fi}%
+ \ifnum\c_tabl_ntb_current_row_two>\c_tabl_ntb_maximum_row\c_tabl_ntb_current_row_two\c_tabl_ntb_maximum_row\fi
+ \ifnum\c_tabl_ntb_current_col_two>\c_tabl_ntb_maximum_col\c_tabl_ntb_current_col_two\c_tabl_ntb_maximum_col\fi
+ \c_tabl_ntb_current_row_two\numexpr\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone\relax
+ \c_tabl_ntb_current_col_two\numexpr\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone\relax
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \dorecurse\c_tabl_ntb_current_row_two
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one{\the\c_tabl_ntb_current_col_two}%
+ \dorecurse\c_tabl_ntb_current_col_two
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col_one\plusone}%
+ \advance\c_tabl_ntb_current_row_one\plusone}%
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_col_two}%
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row_two}%
+ \ifautoTBLemptycell
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}%
+ {\c!option=\v!tight}{\strut\kern\scaledpoint}% the kern forces the tight
+ \fi}
+
+\def\tabl_ntb_loop_two
+ {\dorecurse\c_tabl_ntb_maximum_row\tabl_ntb_loop_two_rows}
+
+\def\tabl_ntb_loop_two_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_two_cells}
+
+\def\tabl_ntb_loop_two_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname
+ \scratchcounter\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone\relax
+ \ifnum\tabl_ntb_get_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col>\scratchcounter
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\scratchcounter}%
+ \fi
+ \fi
+ \tabl_ntb_let_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ \tabl_ntb_let_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ \ifcsname\tabl_ntb_col_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zerocount
+ \fi
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \fi}
+
+\let\startTBLprocessing\relax % public
+\let\stopTBLprocessing \relax % public
+
+\newcount\c_tabl_prelocated_rows % \prelocateTBLrows{1000} may speed up large tables
+
+% \def\tabl_ntb_row_start{\t_tabl_ntb_row\emptytoks}
+% \def\tabl_ntb_row_stop {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\t_tabl_ntb_row\tabl_ntb_row_align_stop}}}
+
+\def\tabl_ntb_row_start
+ {\t_tabl_ntb_row\emptytoks}
+
+\def\tabl_ntb_row_stop
+ {\ifenableTBLbreak
+ \tabl_ntb_row_stop_split
+ \else
+ \tabl_ntb_row_stop_boxed
+ \fi}
+
+\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}}}
+
+\def\tabl_ntb_row_stop_split
+ {\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
+ \tabl_ntb_row_stop_split_yes
+ \else
+ \tabl_ntb_row_stop_split_nop
+ \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}}}
+
+\def\tabl_ntb_row_stop_split_yes
+ {\begingroup
+ \csname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
+ \xdef\m_tabl_ntb_before_split{\naturaltablelocalparameter\c!before}% to be checked
+ \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}}}
+
+\unexpanded\def\tabl_ntb_row_align_set#1#2#3%
+ {\xdef\m_tabl_ntb_before_split{#1}%
+ \xdef\m_tabl_ntb_after_split {#2}%
+ \xdef\m_tabl_ntb_same_page {#3}}
+
+\unexpanded\def\tabl_ntb_row_align_reset
+ {\global\let\m_tabl_ntb_before_split\empty
+ \global\let\m_tabl_ntb_after_split \empty
+ \global\let\m_tabl_ntb_same_page \empty}
+
+\def\tabl_ntb_prelocate_error
+ {\writestatus\m!system{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}}
+
+% \prelocateTBLrows{1000} % may speed up large tables
+
+\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
+ {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone
+ {\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}%
+ \def\tabl_ntb_row_start
+ {\ifnum\c_tabl_ntb_row<\c_tabl_prelocated_rows\relax
+ \tabl_ntb_prelocate_okay
+ \else
+ \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}}}%
+ \global\c_tabl_prelocated_rows#1\relax}
+
+\def\tabl_ntb_prelocate_okay
+ {\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks}
+
+% We use aligments to handle the empty (skipped) columns, so
+% that we don't have to (re|)|calculate these.
+
+\let\m_tabl_ntb_saved_row\!!zerocount
+\let\m_tabl_ntb_saved_col\!!zerocount
+
+\unexpanded\def\tabl_ntb_row_align_start
+ {\global\advance\c_tabl_ntb_row\plusone
+ \global\c_tabl_ntb_col\plusone
+ \global\c_tabl_ntb_spn\zerocount
+ \tabl_ntb_row_align_start_inject
+ \dostarttagged\t!tablerow\empty
+ \hbox\bgroup
+ \kern\dimexpr\d_tabl_ntb_leftmargindistance\relax}
+
+\unexpanded\def\tabl_ntb_row_align_stop
+ {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax
+ \egroup
+ \dostoptagged
+ \tabl_ntb_row_align_stop_inject}
+
+\unexpanded\def\tabl_ntb_before_page
+ {\ifx\m_tabl_ntb_same_page\v!before
+ % \blank[\v!samepage,\v!strong]%
+ \unpenalty
+ \nobreak
+ \else\ifx\m_tabl_ntb_same_page\v!both
+ % \blank[\v!samepage,\v!strong]%
+ \unpenalty
+ \nobreak
+ \fi\fi}
+
+\unexpanded\def\tabl_ntb_after_page
+ {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines
+ \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount
+ \unpenalty
+ \ifx\m_tabl_ntb_same_page\v!after
+ % \blank[\v!samepage,\v!strong]%
+ \nobreak
+ \else\ifx\m_tabl_ntb_same_page\v!both
+ % \blank[\v!samepage,\v!strong]%
+ \nobreak
+ \else
+ % \blank[\v!preference,\v!weak]%
+ \allowbreak
+ \fi\fi
+ \fi
+ \else
+ % \blank[\v!preference,\v!weak]%
+ \allowbreak % else no proper head split off
+ \fi}
+
+\unexpanded\def\tabl_ntb_inbetween
+ {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax
+ \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax
+ \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty\else
+ \blank[\p_spaceinbetween]%
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_ntb_row_align_start_inject
+ {\bgroup % protect local vars
+ \m_tabl_ntb_before_split
+ \egroup
+ \ifenableTBLbreak
+ \tabl_ntb_before_page
+ \fi}
+
+\unexpanded\def\tabl_ntb_row_align_stop_inject
+ {\par
+ \nointerlineskip
+ \ifenableTBLbreak
+ \tabl_ntb_after_page
+ \fi
+ \bgroup % protect local vars
+ \m_tabl_ntb_after_split
+ \egroup
+ \bgroup % protect local vars
+ \tabl_ntb_inbetween
+ \egroup}
+
+\def\tabl_ntb_flush_content
+ {\the\everyTABLEpass
+ \global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\advance\c_tabl_ntb_row\minusone
+ \dostarttaggedchained\t!table\empty\??naturaltable
+ %\registerparoptions % (*) triggers max hsize
+ \the\t_tabl_ntb
+ \dostoptagged}
+
+\unexpanded\def\tabl_ntb_span#1%
+ {\dorecurse{#1}
+ {\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \global\advance\c_tabl_ntb_col\plusone}}
+
+\unexpanded\def\tabl_ntb_skip#1%
+ {\global\advance\c_tabl_ntb_col#1\relax}
+
+\unexpanded\def\tabl_ntb_plus
+ {\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}}}%
+ \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
+ \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}}%
+ \fi}
+
+\unexpanded\def\tabl_ntb_cell#1#2%
+ {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}}
+
+\unexpanded\def\tabl_ntb_table_start
+ {\global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \c_tabl_tbl_pass\zerocount
+ \t_tabl_ntb\emptytoks}
+
+\def\tabl_ntb_pass_one#1 #2 %
+ {\tabl_ntb_get_txt{#1}{#2}}%
+
+\def\tabl_ntb_pass_two#1 #2 % meer in cellD
+ {\d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
+ \!!counta\tabl_ntb_get_col{#1}{#2}\relax
+ \ifcase\!!counta\or
+ \advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \relax
+ \advance\scratchcounter\plusone
+ \else
+ \dorecurse\!!counta
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \ifnum\recurselevel<\!!counta
+ +\d_tabl_ntb_columndistance
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
+ \advance\scratchcounter\plusone}%
+ \fi
+ \setbox\scratchbox\hbox{\tabl_ntb_get_txt{#1}{#2}}%
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
+ \ifdim\ht\scratchbox>\tabl_ntb_get_hei{#1}\relax
+ \tabl_ntb_set_hei{#1}{\the\ht\scratchbox}%
+ \fi}%
+
+\def\tabl_ntb_pass_three#1 #2 %
+ {% height
+ \dostarttagged\t!tablecell\empty
+ \!!counta \tabl_ntb_get_col{#1}{#2}\relax
+ \!!countb \tabl_ntb_get_row{#1}{#2}\relax
+ \!!heighta\tabl_ntb_get_ht {#1}{#2}\relax
+ \tablecellcolumns\!!counta % used later so don't adapt these
+ \tablecellrows \!!countb % used later so don't adapt these
+ \d_tabl_ntb_height\zeropoint
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
+ % case: nc=maxcolumns
+ \else
+ \scratchcounter#1\relax
+ \dorecurse\!!countb
+ {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter
+ \advance\scratchcounter\plusone}%
+ \ifdim\d_tabl_ntb_height<\!!heighta\relax
+ \d_tabl_ntb_height\!!heighta
+ \fi
+ \fi
+ % width
+ \d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
+ \ifcase\!!counta\or
+ \advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \relax
+ \advance\scratchcounter\plusone
+ \else
+ \dorecurse\!!counta
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ \ifnum\recurselevel<\!!counta
+ +\d_tabl_ntb_columndistance
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
+ \advance\scratchcounter\plusone}%
+ \fi
+ % cell
+ \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute \bgroup
+ \dotagTABLEsignal % maybe we need to add some packaging in this case
+ \tabl_ntb_get_txt{#1}{#2}%
+ \egroup
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
+ % case: nc=maxcolumns
+ \else
+ \scratchdimen\tabl_ntb_get_hei{#1}%
+ \setbox\scratchbox\hbox
+ {\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}%
+ \ht\scratchbox\scratchdimen
+ \fi
+ \dp\scratchbox\zeropoint
+ \edef\!!stringa{\tabl_ntb_get_ref{#1}{#2}}%
+ \ifx\!!stringa\empty
+ \box\scratchbox
+ \else
+ \normalexpanded{\noexpand\directgotobox{\box\scratchbox}[\!!stringa]}% to be checked
+ \fi
+ \dostoptagged} % right spot
+
+% \def\tabl_ntb_cell_finalize
+% {\doifnotinset\localwidth{\v!fit,\v!broad}% user set
+% {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+% \ifdim\localwidth>\scratchdimen
+% \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
+% \fi}}
+
+\def\tabl_ntb_cell_finalize
+ {\ifx\localwidth\v!fit
+ % nothing
+ \else\ifx\localwidth\v!broad
+ % nothing
+ \else\ifx\localwidth\empty
+ % nothing (safeguard)
+ \else
+ \tabl_ntb_cell_finalize_indeed
+ \fi\fi\fi}
+
+\def\tabl_ntb_cell_finalize_indeed
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+ \ifdim\localwidth>\scratchdimen
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
+ \fi}
+
+\let\tabl_ntb_preroll\relax
+
+\def\tabl_ntb_table_stop
+ {\forgetall % new, here see narrower-004.tex
+ %\setbox\scratchbox\hbox
+ % {\letnaturaltablelocalparameter\c!frame\v!off
+ % \letnaturaltablelocalparameter\c!background\empty
+ % \letnaturaltablelocalparameter\c!align\v!no
+ % \inheritednaturaltablelocalframed{\strut}}%
+ %\edef\minimalcellheight{\the\ht\scratchbox}% not used
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_let_aut\recurselevel\zeropoint
+ % new
+ \c_tabl_ntb_current_col_one\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_let_wd\recurselevel\c_tabl_ntb_current_col_one\zeropoint
+ \tabl_ntb_let_ht\recurselevel\c_tabl_ntb_current_col_one\zeropoint}%
+ % till here
+ \tabl_ntb_let_tal\recurselevel\zerocount
+ \tabl_ntb_let_wid\recurselevel\zeropoint
+ \tabl_ntb_let_dis\recurselevel\zeropoint}%
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_let_hei\recurselevel\maxdimen}%
+ \tabl_ntb_let_gal\zerocount
+\tabl_ntb_preroll\relax
+ \c_tabl_tbl_pass\plusone
+ \let\tabl_ntb_pass\tabl_ntb_pass_one
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \ifcase\tabl_ntb_get_gal\or
+ % \c_tabl_tbl_pass\plusone
+ % \let\tabl_ntb_pass\tabl_ntb_pass_one
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a_extra
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi
+ \tabl_ntb_let_dis\c_tabl_ntb_maximum_col\zeropoint
+ \ifautoTBLspread
+ % experimental, stretch non fixed cells to \hsize
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \tabl_ntb_stretch_widths
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \else\ifdim\wd\scratchbox>\hsize
+ \ifautoTBLhsize
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi
+ \else\ifautoTBLrowspan\ifnum\c_tabl_ntb_maximum_row_span>\plusone % max ?
+ % added jan 2002 because nx=* did no longer work
+ \ifnum\c_tabl_ntb_encountered_max<\c_tabl_ntb_maximum_col
+ % added jun 2014 because someone had less columns than nx .. sigh / see *nx*
+ \writestatus\m!TABLE{missing\space\number\numexpr\c_tabl_ntb_maximum_col-\c_tabl_ntb_encountered_max\relax\space column(s), guessing widths}%
+ \fi
+ \edef\savedhsize{\the\hsize}%
+ \hsize\wd\scratchbox\relax % new per 17/04/2006
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \hsize\savedhsize
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_c
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \fi\fi\fi\fi
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_d
+ \c_tabl_tbl_pass\plustwo
+ \let\tabl_ntb_pass\tabl_ntb_pass_two
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \tabl_ntb_check_heights_one
+ \tabl_ntb_check_heights_two
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_e
+ \c_tabl_tbl_pass\plusthree
+ \let\tabl_ntb_pass\tabl_ntb_pass_three
+ \ifnum\m_tabl_tbl_level>\plusone
+ \tabl_tbl_split_nop
+ \else\ifenableTBLbreak
+ \tabl_tbl_split_yes
+ \else
+ \tabl_tbl_split_nop
+ \fi\fi}
+
+\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend
+ {\ifcase\c_tabl_ntb_maximum_col\else % else division by zero
+ \!!dimend\zeropoint
+ \!!dimene\dimexpr
+ \hsize
+ -\d_tabl_ntb_leftmargindistance
+ -\d_tabl_ntb_rightmargindistance
+ +\d_tabl_ntb_columndistance
+ \relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\advance\!!dimend\dimexpr
+ \tabl_ntb_get_wid\recurselevel
+ \relax
+ \advance\!!dimene\dimexpr
+ -\tabl_ntb_get_dis\recurselevel
+ -\d_tabl_ntb_columndistance
+ \relax}%
+ \relax
+ % distribute width (stretch)
+ \ifdim\!!dimend<\!!dimene
+ \advance\!!dimend-\!!dimene
+ \divide\!!dimend\c_tabl_ntb_maximum_col
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel-\!!dimend\relax}}%
+ \fi
+ \fi}
+
+\def\tabl_tbl_split_nop
+ {\setbox\b_tabl_ntb_final\vbox{\tabl_ntb_flush_content}%
+ \postprocessTABLEbox\b_tabl_ntb_final
+ \beforeTABLEbox
+ % packaging prevents max hsized box
+ % \hbox{\registerparoptions\box\b_tabl_ntb_final}% (*) better here
+ % better :
+ \ifinsidefloat
+ % nothing, else we get a \hsized box
+ \else
+ \registerparoptions % (*) better here
+ \fi
+ \box\b_tabl_ntb_final
+ \afterTABLEbox}
+
+\def\tabl_tbl_split_yes
+ {\ifinsidesplitfloat
+ \donetrue
+ \else\ifinsidefloat
+ \donefalse
+ \else
+ \donetrue
+ \fi\fi
+ \ifdone
+ \expandafter\tabl_ntb_split_box
+ \else
+ \expandafter\tabl_tbl_split_nop
+ \fi}
+
+\newbox\TABLEsplitbox % public, don't change
+
+\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox
+
+\def\tabl_ntb_split_box
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax}%
+ \def\tsplitbeforeresult {\beforeTABLEsplitbox}%
+ \def\tsplitafterresult {\afterTABLEsplitbox}%
+ \def\tsplitafter {\m_tabl_ntb_after_split}%
+ \def\tsplitbefore {\m_tabl_ntb_before_split}% supported ?
+ \setbox\tsplitcontent\vbox{\tabl_ntb_flush_content}%
+ \ifmultipleTBLheads
+ \dorecurse\c_tabl_ntb_n_of_head_lines
+ {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvcopy\tsplithead\unvcopy\scratchbox}}%
+ \dorecurse\c_tabl_ntb_n_of_next_lines
+ {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplitnext\vbox{\unvcopy\tsplitnext\unvcopy\scratchbox}}%
+ \fi
+ \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty\else
+ \blank[\p_spaceinbetween]%
+ \fi
+ \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\tsplitresult}}%
+ \handletsplit}
+
+% ! ! ! ! TODO: naast \postprocessTABLEsplitbox ook evt \postprocessTABLEbox voor niet split
+
+\let\postprocessTABLEsplitbox\gobbleoneargument
+\let\postprocessTABLEbox \gobbleoneargument
+
+\let\beforeTABLEsplitbox\relax
+\let\afterTABLEsplitbox \relax
+\let\beforeTABLEbox \relax
+\let\afterTABLEbox \relax
+
+\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed0} % 0 = trial run
+\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed1} % 1 = real run
+
+\def\tabl_ntb_check_widths_indeed#1%
+ {\iftraceTABLE\tabl_ntb_show_widths{B#1}\fi
+ \!!counta\zerocount
+ \!!dimena\dimexpr
+ \hsize
+ -\d_tabl_ntb_leftmargindistance
+ -\d_tabl_ntb_rightmargindistance
+ -\d_tabl_ntb_columndistance
+ \relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_aut\recurselevel\relax
+ \advance\!!dimena\dimexpr
+ -\tabl_ntb_get_dis\recurselevel
+ -\d_tabl_ntb_columndistance
+ \relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \advance\!!dimena -\scratchdimen
+ \else
+ \scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ \ifdim\scratchdimen>\d_tabl_ntb_maxwidth\relax
+ \ifcase#1\else\tabl_ntb_let_wid\recurselevel\zeropoint\fi
+ \advance\!!counta \plusone
+ \else
+ \ifdim\scratchdimen>\zeropoint\relax
+ \advance\!!dimena -\scratchdimen
+ \else
+ % eigenlijk moet dit alleen als de kolom wordt overspannen door een
+ % vorige, maw extra dubbele loop en status var
+ \ifnum\c_tabl_ntb_encountered_max=\c_tabl_ntb_maximum_col % *nx* bah
+ \advance\!!counta \plusone % setting maxwidth to a large value also works
+ \fi
+ \fi
+ \fi
+ \fi}%
+ \ifcase\!!counta \else \divide\!!dimena \!!counta \fi
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ \ifcase#1\relax
+ \ifdim\scratchdimen<\!!dimena % take natural width
+ \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}%
+ \fi
+ \else
+ \ifdim\scratchdimen=\zeropoint % auto set width
+ \tabl_ntb_set_wid\recurselevel{\the\!!dimena}%
+ \fi
+ \fi}%
+ \iftraceTABLE\tabl_ntb_show_widths{E#1}\fi}
+
+\def\tabl_ntb_check_heights_one_indeed
+ {\!!countb\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax
+ % check row span
+ \ifnum\!!countb>\plusone
+ % current height in row
+ \dimen0=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three
+ % find nearest height in row
+ \dimen2=\zeropoint
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\recurselevel\endcsname
+ \!!countc=\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifnum\!!countc=\plusone
+ \dimen4=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifdim\dimen2<\dimen4
+ \dimen2=\dimen4
+ \fi
+ \fi
+ \fi
+ \fi}%
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
+ % calculate cummulative height
+ \dimen4=\dimen2
+ \!!countc\c_tabl_ntb_current_row_three
+ \advance\!!countc\minusone
+ \dorecurse\!!countb
+ {\ifnum\c_tabl_ntb_current_row_four=\c_tabl_ntb_current_row_three\else
+ \advance\dimen4 \tabl_ntb_get_hei\c_tabl_ntb_current_row_four
+ \fi
+ \ifnum\recurselevel=\!!countb\else
+ \tabl_ntb_set_nob\!!countc
+ \advance\!!countc\plusone
+ \fi
+ \advance\c_tabl_ntb_current_row_four\plusone}%
+ % distribute overshoot equally
+ \ifdim\dimen2>\zeropoint % new: test on natural-003
+ \ifdim\dimen4<\dimen0
+ \advance\dimen0 -\dimen4
+ \divide\dimen0 \!!countb
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
+ \dorecurse\!!countb
+ {\dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \scratchdimen\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\recurselevel+\dimen0\relax
+ \tabl_ntb_set_ht\c_tabl_ntb_current_row_four\recurselevel{\the\scratchdimen}%
+ \ifdim\tabl_ntb_get_hei\c_tabl_ntb_current_row_four<\scratchdimen
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_four{\the\scratchdimen}%
+ \fi
+ \fi}%
+ \advance\c_tabl_ntb_current_row_four\plusone}%
+ \else\ifdim\dimen4>\dimen0
+ \iftightTBLrowspan
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
+ \fi
+ \fi\fi
+ \fi
+ \fi}
+
+\def\tabl_ntb_check_heights_one
+ {\dorecurse\c_tabl_ntb_maximum_row
+ {\c_tabl_ntb_current_row_three\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col_three\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\endcsname
+ \tabl_ntb_check_heights_one_indeed
+ \fi}}}
+
+\def\tabl_ntb_check_heights_two
+ {}
+
+\def\tabl_ntb_show_widths#1%
+ {\vbox
+ {\forgetall
+ \tttf[#1]%
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ [\recurselevel:\the\scratchdimen]}}}
+
+% \def\tabl_ntb_char_align
+% {\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes
+% \tabl_ntb_char_align_indeed\gobbletwoarguments}
+
+% \def\tabl_ntb_char_align_indeed#1#2#3% row column data
+% {\edef\alignmentclass{#2}%
+% \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}%
+% \ifcase\c_tabl_tbl_pass\or
+% \setfirstpasscharacteralign\checkalignment{#3}% {\strut#2\unskip}%
+% \fi % force hsize, so always a second
+% \setsecondpasscharacteralign \checkalignment{#3}% {\strut#2\unskip}%
+% \ignorespaces}
+
+\def\tabl_ntb_char_align % called often
+ {\edef\p_characteralign{\naturaltablelocalparameter\c!aligncharacter}%
+ \ifx\p_characteralign\v!yes
+ \ifcase\c_tabl_tbl_pass\or
+ \tabl_ntb_let_tal\currentTABLEcolumn\plusone
+ \tabl_ntb_let_gal\plusone
+ \fi
+ \expandafter\tabl_ntb_char_align_indeed
+ \else
+ \expandafter\gobbletwoarguments
+ \fi}
+
+\def\tabl_ntb_char_align_indeed#1#2% row column
+ {\ifcase\c_tabl_tbl_pass \or
+ \setcharacteralign{#2}{\naturaltablelocalparameter\c!alignmentcharacter}% we could store the character in tal
+ \fi
+ \typo_charalign_adapt_font
+ \signalcharacteralign{#2}{#1}}
+
+\unexpanded\def\tabl_ntb_cell_process_a_extra#1#2%
+ {\ifcase\tabl_ntb_get_tal{#2}\relax
+ \expandafter\tabl_ntb_cell_process_x
+ \else
+ \expandafter\tabl_ntb_cell_process_a
+ \fi{#1}{#2}}
+
+\unexpanded\def\tabl_ntb_cell_process_x#1#2[#3]#4%
+ {}
+
+% problem: when span doesn't break we can have a span that is the sum of
+% cells but still to small .. chicken egg problem ... for that we should
+% also have a smallest width run
+%
+% nilling the background makes a run upto 25% faster
+
+% \def\tabl_ntb_cell_process_a_check_span_one
+% {\ifautosqueezeTBLspan
+% \edef\p_width{\naturaltablelocalparameter\c!width}%
+% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
+% \else
+% \donetrue
+% \fi
+% \ifdone % brr, 0
+% \ifnum\scratchcounter>\plusone
+% \tabl_ntb_set_spn\c_tabl_ntb_col
+% \fi
+% \fi}
+
+\def\tabl_ntb_cell_process_a_check_span_one
+ {\ifautosqueezeTBLspan
+ \edef\p_width{\naturaltablelocalparameter\c!width}%
+ \ifcsname\??naturaltablesqueeze\p_width\endcsname\lastnamedcs\else\donefalse\fi
+ \else
+ \donetrue
+ \fi
+ \ifdone % brr, 0
+ \ifnum\scratchcounter>\plusone
+ \tabl_ntb_set_spn\c_tabl_ntb_col
+ \fi
+ \fi}
+
+% \def\tabl_ntb_cell_process_a_check_span_two_yes
+% {\iftightTBLcolspan
+% \donefalse
+% \else
+% \ifnum\scratchcounter>\plusone
+% \begingroup
+% \edef\p_width{\naturaltablelocalparameter\c!width}%
+% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
+% \ifdone
+% \endgroup
+% \edef\p_option{\naturaltablelocalparameter\c!option}%
+% \ifx\p_option\v!tight\donefalse\else\donetrue\fi
+% \else
+% % a dimension
+% \endgroup
+% \donefalse
+% \fi
+% \else
+% \edef\p_option{\naturaltablelocalparameter\c!option}%
+% \ifx\p_option\v!tight\donefalse\else\donetrue\fi
+% \fi
+% \fi
+% \ifdone
+% \ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
+% \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
+% \fi
+% \fi}
+
+% \def\tabl_ntb_cell_process_a_check_span_two_nop
+% {\ifnum\scratchcounter>\plusone
+% \edef\p_width{\naturaltablelocalparameter\c!width}%
+% \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
+% \else
+% \donetrue
+% \fi
+% \ifdone
+% \ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
+% \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
+% \fi
+% \fi}
+
+\let\tabl_ntb_cell_process_a_check_span_two_yes\relax
+
+\def\tabl_ntb_cell_process_a_check_span_two_nop
+ {\ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
+ \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
+ \fi}
+
+\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
+ {\bgroup
+ \letnaturaltablelocalparameter\c!option\empty
+ \tabl_ntb_setup_cell{#1}{#2}%
+ \setupcurrentnaturaltablelocal[#3]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
+ \setbox\scratchbox\hbox
+ {\scratchdimen\naturaltablelocalparameter\c!distance\relax
+ \ifdim\scratchdimen>\tabl_ntb_get_dis{#2}\relax
+ \tabl_ntb_set_dis{#2}{\the\scratchdimen}%
+ \fi
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}}%
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \ifdim\wd\scratchbox>\scratchdimen
+ \ifsqueezeTBLspan
+ \tabl_ntb_cell_process_a_check_span_one
+ \fi
+ \tabl_ntb_spn_doifelse\c_tabl_ntb_col
+ \tabl_ntb_cell_process_a_check_span_two_yes
+ \tabl_ntb_cell_process_a_check_span_two_nop
+ \fi
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
+ \ifdim\ht\scratchbox<\scratchdimen
+ \tabl_ntb_set_hei\scratchcounter{\the\ht\scratchbox}% auto set
+ \fi
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
+ \ifautoTBLcheckwidth
+ \ifdim\wd\scratchbox<.75\hsize % fuzzy guess
+ \ifdim\ht\scratchbox>2\openlineheight % honor width since this
+ \scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax % can be a figure or so
+ \ifdim\scratchdimen=\zeropoint
+ % side effect: when width is set to 0pt,
+ % we can force a span that fits the sum of spans widths
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\scratchdimen}%
+ \else\ifdim\wd\scratchbox>\scratchdimen
+ % unless span
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\wd\scratchbox}%
+ % to be translated
+ \writestatus\m!TABLE{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
+ \fi\fi
+ \fi
+ \fi
+ \fi
+ \setbox2\emptyhbox
+ \wd2\wd\scratchbox
+ \ht2\ht\scratchbox
+ \dp2\dp\scratchbox
+ \box2
+ \egroup}
+
+\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5%
+ {\setbox\scratchbox\hbox
+ {\tabl_ntb_setup_cell{#2}{#3}%
+ \setupcurrentnaturaltablelocal[#4,#1]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start#5\tabl_ntb_cell_stop}}%
+ \setbox2\emptyhbox
+ \wd2\wd\scratchbox
+ \ht2\ht\scratchbox
+ \dp2\dp\scratchbox
+ \ifautoTBLrowspan
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifcsname\tabl_ntb_row_pattern\scratchcounter\c_tabl_ntb_col\endcsname
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
+ \ifnum\tabl_ntb_get_row\scratchcounter\c_tabl_ntb_col>\plusone
+ \ifdim\ht\scratchbox>\scratchdimen
+ \ht2\dimexpr-\scratchdimen-\ht\scratchbox\relax
+ \fi
+ \fi
+ \fi
+ \fi
+ \box2 }
+
+\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4%
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \else
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
+ \ifdim\scratchdimen>\zeropoint\relax
+ \ifnum\tabl_ntb_get_col{#1}{#2}=\c_tabl_ntb_maximum_col\relax
+ \scratchdimen\hsize
+ \fi
+ \fi
+ \fi
+ \normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
+ {#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}}
+
+\unexpanded\def\tabl_ntb_cell_process_c
+ {\tabl_ntb_cell_process_b_c{}}
+
+\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
+ \bgroup
+ \setupcurrentnaturaltablelocal[#3]%
+ \letnaturaltablelocalparameter\c!background\empty
+ \letnaturaltablelocalparameter\c!frame\v!off
+ \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}%
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
+ \egroup}
+
+\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
+ \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we
+ \color % handle color here prevents interference due to whatsit nodes
+ [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence
+ {\letnaturaltablelocalparameter\c!color\empty
+ \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}%
+ \ifdim\d_tabl_ntb_height=\zeropoint\relax % case: nc=maxcolumns
+ \else
+ \setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}%
+ \fi
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}%
+ \hskip\tabl_ntb_get_dis{#2}}
+
+\setupTABLE
+ [\c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ % \c!framecolor=\s!black,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!autowidth=\v!yes,
+ \c!rulethickness=\linewidth,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!no,
+ %
+ \c!color=,
+ \c!style=,
+ \c!headstyle=\v!bold,
+ \c!headcolor=,
+ \c!aligncharacter=\v!no,
+ \c!alignmentcharacter={,},
+ \c!option=, % \v!stretch
+ \c!header=,
+ \c!spaceinbetween=,
+ \c!maxwidth=8\emwidth,
+ \c!textwidth=\v!local, % was \hsize
+ \c!split=\v!auto,
+ \c!splitoffset=\zeropoint,
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+ \c!left=,
+ \c!right=,
+ \c!setups=]
+
+% \bgroup
+% \setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
+% \bTABLE
+% \bTR \bTD 1,2 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,2 \eTD \bTD
+% {\setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
+% \bTABLE
+% \bTR \bTD 1,2 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,22 \eTD \bTD 2 \eTD \eTR
+% \bTR \bTD 11,2 \eTD \bTD 2 \eTD \eTR \eTABLE} \eTD \eTR
+% \bTR \bTD 11,22 \eTD \bTD 2 \eTD \eTR
+% \eTABLE
+% \egroup
+
+\newconditional\resetTABLEmode \settrue\resetTABLEmode
+
+\def\tabl_ntb_parameters_reset % we can use setters instead
+ {\ifnum\m_tabl_tbl_level>\plusone % in ieder geval
+ \ifconditional\resetTABLEmode
+ % not ok yet
+ \setupTABLE
+ [\c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ % \c!framecolor=\s!black,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!autowidth=\v!yes,
+ % \c!rulethickness=\linewidth,
+ \c!strut=\v!no,
+ \c!strut=\v!yes, % needed for mathml, but ... maybe we need another resetTABLEmode
+ \c!autostrut=\v!no,
+ \c!color=,
+ \c!style=,
+ \c!headstyle=,
+ \c!headcolor=,
+ \c!aligncharacter=\v!no,
+ \c!alignmentcharacter={,},
+ \c!maxwidth=8\emwidth]%
+ \else
+ \setupTABLE
+ [\c!width=\v!fit,
+ \c!height=\v!fit]%
+ \fi
+ \fi}
+
+% new (for Olivier Turlier)
+%
+% \defineTABLEsetup [xx] [foregroundcolor=red]
+%
+% \bTABLE
+% \bTR \bTD oeps \eTD \bTD oeps \eTD \eTR
+% \bTR \bTDs[xx] oeps \eTDs \bTD oeps \eTD \eTR
+% \bTRs[xx] \bTD oeps \eTD \bTD oeps \eTD \eTRs
+% \eTABLE
+
+\installcorenamespace{naturaltablesetup}
+
+\unexpanded\def\defineTABLEsetup
+ {\dodoubleargument\tabl_ntb_define_setup}
+
+\def\tabl_ntb_define_setup[#1][#2]%
+ {\setvalue{\??naturaltablesetup#1}{#2}}
+
+\let\eTDs\relax
+\let\eTRs\relax
+
+% \unexpanded\def\bTDs[#1]#2\eTDs
+% {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD}
+%
+% \unexpanded\def\bTRs[#1]#2\eTRs
+% {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR}
+
+\unexpanded\def\bTDs[#1]#2\eTDs
+ {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}
+
+\unexpanded\def\bTRs[#1]#2\eTRs
+ {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}
+
+\protect \endinput
+
+% todo: mode: first|next (of niets)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-nte.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-nte.mkiv
new file mode 100644
index 00000000000..af74a2abe9b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-nte.mkiv
@@ -0,0 +1,110 @@
+%D \module
+%D [ file=core-nte,
+%D version=2009.03.08,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural Tables Extensions,
+%D author=Hans Hagen \& Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Module / Natural Tables Extensions}
+
+\unprotect
+
+%D This module is suggested by Wolfgang Schuster who also prototyped
+%D it and came up with the rationale:
+%D
+%D This module provides an easy way to use natural in a similiar
+%D way as the older table module (based on the \TABLE\ macros) and
+%D the newer tabulate module.
+%D
+%D You can see the advantage in the following table, once created
+%D with the new macros and once with the normal macros provided
+%D with the natural table module.
+%D
+%D Let us start with the original macros:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR
+%D \bTD Text 1 \eTD
+%D \bTD Text 2 \eTD
+%D \eTR
+%D \bTR
+%D \bTD Text 3 \eTD
+%D \bTD Text 4 \eTD
+%D \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Watch how the new macros use less code:
+%D
+%D \startbuffer
+%D \startTABLE
+%D \NC Text 1 \NC Text 2 \NC\NR
+%D \NC Text 3 \NC Text 4 \NC\NR
+%D \stopTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The actual code differs from the prototype that it does not need
+%D to collect whole rows and parse them but looks ahead instead.
+
+\newconditional\c_tabl_nte_in_nc
+
+\unexpanded\def\startTABLE
+ {\dosingleempty\tabl_nte_start}
+
+\def\tabl_nte_start[#1]%
+ {\bgroup
+ \bTABLE[#1]%
+ \let\NC\tabl_nte_start_nc
+ \let\NR\tabl_nte_start_nr
+ \let\bTR\relax
+ \let\bTD\relax
+ \let\bTH\relax
+ \let\bTN\relax}
+
+\unexpanded\def\stopTABLE
+ {\eTABLE
+ \egroup}
+
+\unexpanded\def\tabl_nte_start_nr
+ {\eTR
+ \setfalse\c_tabl_nte_in_nc}
+
+\unexpanded\def\tabl_nte_start_nc
+ {\futurelet\next\tabl_nte_start_nc_indeed}
+
+\def\tabl_nte_start_nc_indeed
+ {\ifx\next\tabl_nte_start_nr \else
+ \expandafter\tabl_nte_start_nc_finish
+ \fi}
+
+\def\tabl_nte_start_nc_finish#1\NC
+ {\ifconditional\c_tabl_nte_in_nc \else
+ \settrue\c_tabl_nte_in_nc
+ \dobTR[]%
+ \fi
+ \dobTD#1\eTD\NC}
+
+%D The related structure commands are also available:
+
+\unexpanded\def\startTABLEhead{\dosingleempty\tabl_nte_start_head} \let\stopTABLEhead\relax
+\unexpanded\def\startTABLEnext{\dosingleempty\tabl_nte_start_next} \let\stopTABLEnext\relax
+\unexpanded\def\startTABLEbody{\dosingleempty\tabl_nte_start_body} \let\stopTABLEbody\relax
+\unexpanded\def\startTABLEfoot{\dosingleempty\tabl_nte_start_foot} \let\stopTABLEfoot\relax
+
+\def\tabl_nte_start_head[#1]#2\stopTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\def\tabl_nte_start_next[#1]#2\stopTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\def\tabl_nte_start_body[#1]#2\stopTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\def\tabl_nte_start_foot[#1]#2\stopTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-pln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-pln.mkiv
new file mode 100644
index 00000000000..3638006c79a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-pln.mkiv
@@ -0,0 +1,132 @@
+%D The following bunch of macros come from plain \TEX\ by
+%D Don Knuth and deal with basic alignment. We just include
+%D them here so that they can be used if needed. Normally,
+%D \CONTEXT\ users will fall back on one of the three table
+%D environments.
+%D
+%D The hidden names are somewhat adapted and we use other
+%D local variables.
+
+\writestatus{loading}{ConTeXt Table Macros / Plain Tabular}
+
+%D This code might become a module.
+
+\unprotect
+
+\newconditional \c_tabl_plain_cr
+\newconditional \c_tabl_plain_use_tab
+\newbox \b_tabl_plain_tabs
+\newbox \b_tabl_plain_tabs_yet
+\newbox \b_tabl_plain_tabs_done
+\newdimen \d_tabl_plain_tab
+
+\let\m_tabl_plain_next\relax
+
+\def\cleartabs % visible
+ {\global\setbox\b_tabl_plain_tabs_yet\emptyhbox
+ \setbox\b_tabl_plain_tabs\emptyhbox}
+
+\def\settabs % visible
+ {\setbox\b_tabl_plain_tabs\emptyhbox
+ \futurelet\m_tabl_plain_next\tabl_plain_set_tabs}
+
+\def\tabalign % visible
+ {\settrue\c_tabl_plain_use_tab
+ \tabl_plain_make_tab_box}
+
+\ifdefined\+ \else
+ \let\+\tabalign % no outer here (can be overloaded)
+\fi
+
+\def\tabl_plain_set_tabs
+ {\ifx\m_tabl_plain_next\+%
+ \let\tabl_plain_nxt\tabl_plain_align
+ \else\ifx\m_tabl_plain_next\tabalign % added hh
+ \let\tabl_plain_nxt\tabl_plain_align
+ \else
+ \let\tabl_plain_nxt\tabl_plain_set_cols
+ \fi\fi
+ \let\m_tabl_plain_next\relax
+ \tabl_plain_nxt}
+
+\def\tabl_plain_align
+ {\afterassignment\tabl_plain_set_tab
+ \let\tabl_plain_nxt}
+
+\def\tabl_plain_set_tab
+ {\let\tabl_plain_nxt\relax
+ \setfalse\c_tabl_plain_use_tab
+ \tabl_plain_make_tab_box}
+
+\def\tabl_plain_set_cols#1\columns
+ {\scratchcounter#1\relax
+ \d_tabl_plain_tab\hsize
+ \loop
+ \ifnum\scratchcounter>\zerocount
+ \tabl_plain_other
+ \repeat}
+
+\def\tabl_plain_other
+ {\scratchdimen\d_tabl_plain_tab
+ \divide\scratchdimen\scratchcounter
+ \setbox\b_tabl_plain_tabs\hbox
+ {\hbox to\scratchdimen{}%
+ \unhbox\b_tabl_plain_tabs}%
+ \advance\d_tabl_plain_tab-\scratchdimen
+ \advance\scratchcounter\minusone}
+
+\def\tabl_plain_make_tab_box
+ {\begingroup
+ \let\+\tabalign % added hh
+ \global\setbox\b_tabl_plain_tabs_yet\copy\b_tabl_plain_tabs
+ \global\setbox\b_tabl_plain_tabs_done\emptyhbox
+ \let\cr\tabl_plain_cr
+ \setbox\scratchbox\vbox\bgroup
+ \setfalse\c_tabl_plain_cr
+ \ialign\bgroup
+ \aligntab
+ \tabl_plain_begin_tab_box
+ \alignmark\alignmark
+ \tabl_plain_end_tab_box
+ \crcr}
+
+\def\tabl_plain_cr
+ {\settrue\c_tabl_plain_cr
+ \crcr
+ \egroup
+ \egroup
+ \ifconditional\c_tabl_plain_use_tab
+ \unvbox\scratchbox
+ \lastbox % okay?
+ \fi
+ \endgroup
+ \setbox\b_tabl_plain_tabs\hbox
+ {\unhbox\b_tabl_plain_tabs_yet
+ \unhbox\b_tabl_plain_tabs_done}}
+
+\def\tabl_plain_begin_tab_box
+ {\setbox\scratchbox\hbox\bgroup}
+
+\def\tabl_plain_end_tab_box
+ {\ifconditional\c_tabl_plain_cr
+ \egroup % now \box\scratchbox holds the column
+ \else
+ \hss
+ \egroup
+ \global\setbox\b_tabl_plain_tabs_yet\hbox
+ {\unhbox\b_tabl_plain_tabs_yet
+ \global\setbox\globalscratchbox\lastbox}% now \box\globalscratchbox holds its size
+ \ifvoid\globalscratchbox
+ \global\setbox\globalscratchbox\hbox to \wd\scratchbox
+ {}%
+ \else
+ \setbox\scratchbox\hbox to \wd\globalscratchbox
+ {\unhbox\scratchbox}%
+ \fi
+ \global\setbox\b_tabl_plain_tabs_done\hbox
+ {\box\globalscratchbox
+ \unhbox\b_tabl_plain_tabs_done}%
+ \fi
+ \box\scratchbox}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv
new file mode 100644
index 00000000000..e238447b952
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv
@@ -0,0 +1,2273 @@
+%D \module
+%D [ file=core-tab,
+%D version=1997.10.10,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=\TABLE\ Embedding,
+%D author=Hans Hagen with copied and patched code from MJ Wichura,
+%D date=\currentdate]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / TaBlE Embedding}
+
+% Todo: a bitmore namespace protection ... although we want to keep some of the
+% original flavour.
+%
+% In \MKIV\ the old table macros are sort of obsolete. The color extensions have
+% been removed and some code is stripped. For practical reasons the \TABLE\ macros
+% that are used are embedded in this file.
+%
+% The following code is based on TABLE 1.0 by Michael J. Wichura (August 1988. We
+% used a patched version with many overloads and extensions. The documented (and
+% larger) source can be found in \type {thrd-tab.tex}.
+%
+% Some code has been stripped. Some color has been added. Some macros have been
+% renamed. Registers have been replaces. And probably much more can be cleaned up.
+% We also need to use \tabl_tab_ prefixes here.
+
+\unprotect
+
+\newconditional\c_tabl_table_spacing_left
+\newconditional\c_tabl_table_spacing_right
+
+\newdimen \d_tabl_table_line_thickness_unit
+\newdimen \d_tabl_table_strut_unit
+\newskip \s_tabl_table_inter_column_space_unit
+\newdimen \d_tabl_table_column_width_unit
+\newdimen \d_tabl_table_kern_unit
+
+\def\tablestrutheightfactor {8}
+\def\tablestrutdepthfactor {3}
+\def\tableintercolumnspacefactor {3}
+\def\tablecolumnwidthfactor {10}
+\def\tablevspacefactor {2}
+\def\tablekernfactor {1}
+\def\tablelinethicknessfactor {4}
+
+\newtoks\everytable
+\newtoks\everytableparbox
+
+\unexpanded\def\tabl_table_begin_par_box#1%
+ {\setbox\scratchbox\vtop\bgroup % \setbox added
+ \hsize#1\relax
+ \dontcomplain
+ \tabl_table_restore_lineskips
+ \normalbaselines
+ \let~\fixedspace
+ \inhibitblank % \blank[\v!disable]% % added
+ \the\everytableparbox}
+
+\unexpanded\def\tabl_table_end_par_box
+ {\removelastskip % itemize or so
+ \endgraf
+ \ifnum\prevgraf>\zerocount % we want at least
+ \verticalstrut \nowhitespace \vskip-\struttotal % one line of text
+ \egroup
+ \ifdim\dp\scratchbox>\lineheight % see (*) for an
+ \getnoflines{\dp\scratchbox}% % example of where
+ \dp\scratchbox\zeropoint % saving can go
+ \setbox\scratchbox % terrible wrong
+ \vtop to \noflines\lineheight{\box\scratchbox}%
+ \fi % esp between rows
+ \else % of paragraphs
+ \egroup
+ \fi
+ \box\scratchbox}
+
+\appendtoks
+ \parindent\zeropoint
+ \raggedright
+ \rightskip\zeropoint \s!plus 4em \relax
+\to \everytableparbox
+
+\newskip \tablelefttabskip
+\newskip \tablerighttabskip
+
+\newcount\!taColumnNumber
+\newcount\!taRecursionLevel % (Initially 0)
+
+\newdimen\!taDimenA % used by \Enlarge
+\newdimen\!taDimenB % used by \Enlarge
+\newdimen\!taDimenC % used by numeric.tex
+\newdimen\!taMinimumColumnWidth
+
+\newtoks \!taTableSpread
+\newtoks \!taPreamble
+\newtoks \!taDataColumnTemplate
+\newtoks \!taRuleColumnTemplate
+\newtoks \!taOldRuleColumnTemplate
+\newtoks \!taLeftGlue
+\newtoks \!taRightGlue
+
+\newskip \!taLastRegularTabskip
+
+\newif \if!taBeginFormat
+\newif \if!taOnceOnlyTabskip
+
+\def\!thToksEdef#1#2%
+ {\edef\tempstring{#2}%
+ #1\expandafter{\tempstring}%
+ \ignorespaces}
+
+\def\!thLoop#1\repeat
+ {\def\!thIterate{#1\expandafter \!thIterate\fi}%
+ \!thIterate
+ \let\!thIterate\relax}
+
+\def\tabl_table_begin_format
+ {\!taPreamble\emptytoks
+ \!taColumnNumber\zerocount
+ \scratchskip\s_tabl_table_inter_column_space_unit
+ \multiply\scratchskip\tableintercolumnspacefactor
+ \divide\scratchskip\plustwo
+ \!taRuleColumnTemplate\expandafter{\expandafter\tabskip\the\scratchskip}%
+ \!taLastRegularTabskip\scratchskip
+ \!taOnceOnlyTabskipfalse
+ \!taBeginFormattrue
+ \let\!tfRowOfWidths\empty
+ \doreadtableformatkeys}
+
+\def\!tfSetWidth
+ {\ifx\!tfRowOfWidths\empty % true if no prior "w" keys
+ \ifnum\!taColumnNumber>\zerocount % true if "w" key is to right of first "|"
+ \begingroup % RowOfWidths={\aligntab\omit || n copies of \aligntab\omit\aligntab#\omit}, where n = number of column to the left of this one
+ \scratchcounter\plusone
+ \aftergroup\edef
+ \aftergroup\!tfRowOfWidths
+ \aftergroup{%
+ \aftergroup\aligntab
+ \aftergroup\omit
+ \!thLoop
+ \ifnum \scratchcounter<\!taColumnNumber
+ \advance\scratchcounter\plusone
+ \aftergroup\!tfAOAO
+ \repeat
+ \aftergroup}%
+ \endgroup
+ \fi
+ \fi
+ \ifx[\tempstring % \!tgGetValue sets \tempstring = token after w
+ \expandafter\!tfSetWidthText
+ \else
+ \expandafter\!tfSetWidthValue
+ \fi}
+
+\def\!tfAOAO{\aligntab\omit\aligntab\omit}
+
+\def\!tfSetWidthText[#1]%
+ {\def\!tfWidthText{#1}%
+ \doreadtableformatkeys}
+
+\def\!tfSetWidthValue
+ {\!taMinimumColumnWidth=
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty \tablecolumnwidthfactor \else \!tgValue \fi \d_tabl_table_column_width_unit
+ \else
+ \!tgValue
+ \fi
+ \let\!tfWidthText\empty % Override possible prior `w[sample entry]'
+ \doreadtableformatkeys}
+
+\def\!tfSetTabskip
+ {\ifnum\!tgCode=\plusone
+ \scratchskip\s_tabl_table_inter_column_space_unit
+ \multiply\scratchskip \ifx\!tgValue\empty\tableintercolumnspacefactor\else\!tgValue\fi
+ \else
+ \scratchskip\!tgValue
+ \fi
+ \divide\scratchskip\plustwo
+ \ifnum\!taColumnNumber=\zerocount
+ %\!thToksEdef\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}%
+ \normalexpanded{\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}}%
+ \else
+ %\!thToksEdef\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}%
+ \normalexpanded{\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}}%
+ \fi
+ \if!taOnceOnlyTabskip\else
+ \!taLastRegularTabskip\scratchskip % Remember this Tabskip, for possible
+ \fi % restoration after a subsequent"OnceOnly"
+ \doreadtableformatkeys}
+
+\def\!tfSetVrule
+ {\!thToksEdef\!taRuleColumnTemplate
+ {\hfil
+ \vrule
+ \noexpand\s!width
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \c_tabl_table_vrule_thickness_factor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue
+ \fi
+ \alignmark\alignmark\alignmark\alignmark
+ \hfil
+ \the\!taRuleColumnTemplate}%
+ \!tfAdjoinPriorColumn}
+
+\def\!tfSetAlternateVrule
+ {\afterassignment\!tfSetAlternateA
+ \scratchtoks}
+
+\def\!tfSetAlternateA
+ {\!thToksEdef\!taRuleColumnTemplate{\the\scratchtoks\the\!taRuleColumnTemplate}%
+ \!tfAdjoinPriorColumn}
+
+\def\!tfAdjoinPriorColumn
+ {\ifnum \!taColumnNumber=0
+ \!taPreamble=\!taRuleColumnTemplate % New \tabskip may have been added
+ \else
+ \ifx\!tfRowOfWidths\empty % no "w" keys specified yet, not even this col
+ \else
+ \!tfUpdateRowOfWidths
+ \fi
+ \!thToksEdef\!taDataColumnTemplate{\the\!taLeftGlue\the\!taDataColumnTemplate\the\!taRightGlue}%
+ \!thToksEdef\!taPreamble{\the\!taPreamble\aligntab\the\!taDataColumnTemplate\aligntab\the\!taRuleColumnTemplate}%
+ \fi
+ \advance \!taColumnNumber \plusone
+ \if!taOnceOnlyTabskip
+ \!thToksEdef\!taDataColumnTemplate{\alignmark\alignmark\alignmark\alignmark\tabskip\the\!taLastRegularTabskip}%
+ \else
+ \!taDataColumnTemplate{\alignmark\alignmark}%
+ \fi
+ \!taRuleColumnTemplate\emptytoks
+ \!taLeftGlue{\hfil}%
+ \!taRightGlue{\hfil}%
+ \!taMinimumColumnWidth\zeropoint
+ \let\!tfWidthText\empty
+ \!taOnceOnlyTabskipfalse
+ \doreadtableformatkeys}
+
+\def\!tfUpdateRowOfWidths
+ {\ifx\!tfWidthText\empty \else
+ \!tfComputeMinColWidth
+ \fi
+ \edef\!tfRowOfWidths
+ {\!tfRowOfWidths
+ \aligntab
+ \omit
+ \ifdim \!taMinimumColumnWidth>\zeropoint
+ \hskip \the\!taMinimumColumnWidth
+ \fi
+ \aligntab
+ \omit}}
+
+\def\!tfComputeMinColWidth
+ {\setbox0\vbox
+ {\ialign{% Plain's initialized \halign; \tabskip=0pt \everycr={}
+ \span\the\!taDataColumnTemplate\cr
+ \!tfWidthText\cr}}%
+ \!taMinimumColumnWidth=\wd0 }
+
+\def\!tfFinishFormat
+ {\!thToksEdef\!taPreamble{%
+ \alignmark\alignmark\alignmark\alignmark\tabskip\tablelefttabskip
+ \aligntab
+ \the\!taPreamble\tabskip\tablerighttabskip
+ \aligntab
+ \alignmark\alignmark\alignmark\alignmark\tabskip\zeropoint\cr}
+ \!taBeginFormatfalse
+ \!ttDoHalign}
+
+\def\tabl_table_reformat[#1]% will become local
+ {\omit
+ \!taDataColumnTemplate{\alignmark\alignmark}%
+ \!taLeftGlue\emptytoks
+ \!taRightGlue\emptytoks
+ \begingroup
+ \tabl_table_use_bar
+ \expanded{\endgroup\noexpand\doreadtableformatkeys#1]}}% appear in a \tabl_table_reformat cmd; this is here as a safeguard.
+
+\appendtoks
+ \let\ReFormat\tabl_table_reformat
+\to \everytable
+
+\def\!tfEndReFormat
+ {\!tfReFormat}
+
+\appendtoks \tabl_table_paralignment \to \everytableparbox
+
+\def\!tfReFormat#1%
+ {\the \!taLeftGlue
+ \vbox{\forgetall\ialign{\span\the\!taDataColumnTemplate\cr#1\cr}}%
+ \the \!taRightGlue
+ \kern\zeropoint} % prevents \unskip / really needed
+
+\def\!tgGetValue#1%
+ {\def\!tgReturn{#1}%
+ \futurelet\tempstring\!tgCheckForParen}
+
+\def\!tgCheckForParen%
+ {\ifx\tempstring (%
+ \expandafter \!tgDoParen
+ \else
+ \expandafter \!tgCheckForSpace
+ \fi}
+
+\def\!tgDoParen(#1)%
+ {\def\!tgCode{2}% will be expanded
+ \def\!tgValue{#1}%
+ \!tgReturn}
+
+\def\!tgCheckForSpace
+ {\def\!tgCode{1}%
+ \let\!tgValue\empty
+ \ifx\tempstring\!thSpaceToken
+ \expandafter \!tgReturn
+ \else
+ \expandafter \!tgCheckForDigit
+ \fi}
+
+% \def\!tgCheckForDigit
+% {\donefalse
+% \ifx 0\tempstring \donetrue
+% \else\ifx 1\tempstring \donetrue
+% \else\ifx 2\tempstring \donetrue
+% \else\ifx 3\tempstring \donetrue
+% \else\ifx 4\tempstring \donetrue
+% \else\ifx 5\tempstring \donetrue
+% \else\ifx 6\tempstring \donetrue
+% \else\ifx 7\tempstring \donetrue
+% \else\ifx 8\tempstring \donetrue
+% \else\ifx 9\tempstring \donetrue
+% \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+% \ifdone
+% \expandafter \!tgGetNumber
+% \else
+% \expandafter \!tgReturn
+% \fi}
+
+\def\!tgCheckForDigit % less tokens: (could be an ifcsname)
+ {\donetrue
+ \ifx 0\tempstring \else \ifx 1\tempstring \else
+ \ifx 2\tempstring \else \ifx 3\tempstring \else
+ \ifx 4\tempstring \else \ifx 5\tempstring \else
+ \ifx 6\tempstring \else \ifx 7\tempstring \else
+ \ifx 8\tempstring \else \ifx 9\tempstring \else
+ \donefalse
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \ifdone
+ \expandafter \!tgGetNumber
+ \else
+ \expandafter \!tgReturn
+ \fi}
+
+% \def\!tgCheckForDigit % does not work
+% {\relax\doifnumberelse\tempstring\!tgGetNumber\!tgReturn}
+
+\def\!tgGetNumber {\afterassignment\!tgGetNumberA\scratchcounter=}
+\def\!tgGetNumberA{\edef\!tgValue{\the\scratchcounter}\!tgReturn}
+
+\def\!tgSetUpParBox
+ {\normalexpanded
+ {\noexpand \doreadtableformatkeys
+ b{\tabl_table_begin_par_box
+ {\ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \tablecolumnwidthfactor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_column_width_unit
+ \else
+ \!tgValue
+ \fi}}%
+ a{\tabl_table_end_par_box}}}
+
+\def\!tgInsertKern
+ {\edef\tempstring
+ {\kern
+ \ifnum \!tgCode=\plusone
+ \ifx \!tgValue\empty
+ \tablekernfactor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_kern_unit
+ \else
+ \!tgValue
+ \fi}%
+ \edef\tempstring
+ {\noexpand\doreadtableformatkeys
+ \ifconditional\c_tabl_table_spacing_left
+ b{\tempstring}
+ \fi
+ \ifconditional\c_tabl_table_spacing_right
+ a{\tempstring}
+ \fi}%
+ \tempstring}
+
+\def\newtableformatkey #1{\setvalue{!tk<\string#1>}}
+\def\doreadtableformatkeys#1{\getvalue{!tk<\string#1>}}
+
+% Key "b": b{TOKENS} adds TOKENS to the left of (before) the template
+
+\newtableformatkey b#1%
+ {\expandafter\!tkJoin\expandafter{\the\!taDataColumnTemplate}{#1}%
+ \doreadtableformatkeys}
+
+\def\!tkJoin#1#2%
+ {\!taDataColumnTemplate{#2#1}}%
+
+% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template
+
+\newtableformatkey a#1%
+ {\!taDataColumnTemplate\expandafter{\the\!taDataColumnTemplate #1}%
+ \doreadtableformatkeys}
+
+% Key "\{": Enclose template in braces.
+
+\newtableformatkey \{%
+ {\!taDataColumnTemplate=\expandafter{\expandafter{\the\!taDataColumnTemplate}}%
+ \doreadtableformatkeys}
+
+% Key "*": "*{N}{KEY LETTERS}" is equivalent to specifying
+% <KEY LETTERS> N times.
+% KEY LETTERS may contain further * specifications
+
+\newtableformatkey *#1#2%
+ {\scratchcounter=#1\relax
+ \scratchtoks\emptytoks
+ \!thLoop
+ \ifnum\scratchcounter>\zerocount
+ \scratchtoks\expandafter{\the\scratchtoks#2}%
+ \advance\scratchcounter\minusone
+ \repeat
+ \expandafter\doreadtableformatkeys\the\scratchtoks}
+
+% Key "\LeftGlue": Specifies the glue (usually \hfil, or nothing) to be
+% added to extreme left of the template to position a column
+
+\newtableformatkey \LeftGlue#1%
+ {\!taLeftGlue{#1}%
+ \doreadtableformatkeys}
+
+\newtableformatkey \RightGlue#1%
+ {\!taRightGlue{#1}%
+ \doreadtableformatkeys}
+
+\newtableformatkey c%
+ {\prependtoks\raggedcenter\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\hfil}
+
+\newtableformatkey l%
+ {\prependtoks\raggedright\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\empty \RightGlue\hfil}
+
+\newtableformatkey r%
+ {\prependtoks\raggedleft\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty}
+
+\newtableformatkey x%
+ {\prependtoks\notragged\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty}
+
+% Key "k": Adds kerns to left and right of "#" This key and the two below use Plain
+% TeX's \if@h as if it were \if@left, and \if@v as if it were \if@right. Table
+% making goes on in a group, so even in the unlikely circumstance that a \phantom
+% is currently under construction, there's no problem.
+
+\newtableformatkey k%
+ {\settrue\c_tabl_table_spacing_left
+ \settrue\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "i": Adds a kern to the left of "#"
+
+\newtableformatkey i%
+ {\settrue\c_tabl_table_spacing_left
+ \setfalse\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "j": Adds a kern to the right of "#"
+
+\newtableformatkey j%
+ {\setfalse\c_tabl_table_spacing_left
+ \settrue\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "n": numeric item , non-math mode.
+
+\newtableformatkey n%
+ {\def\!tnStyle{}%
+ \futurelet\!tnext\!tnTestForBracket}
+
+% Key "N": numeric item, math mode.
+
+\newtableformatkey N%
+ {\def\!tnStyle{$}%
+ \futurelet\!tnext\!tnTestForBracket}
+
+% Key "m": Math mode.
+
+\newtableformatkey m%
+ {\doreadtableformatkeys b{\normalstartimath} a{\normalstopimath}}
+
+% Key "M": Displaymath mode.
+
+\newtableformatkey M%
+ {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}}
+
+% Key "\m": Template ${}#\hfil$
+
+\newtableformatkey \m%
+ {\doreadtableformatkeys l b{{}} m}
+
+% Key "\M": Template $\displaystyle{{}#\hfil}$
+
+\newtableformatkey \M%
+ {\doreadtableformatkeys l b{{}} M}
+
+% Key "f": Set font (E.g., f\it sets up italic font (assuming \it
+% has its usual meaning)
+
+\newtableformatkey f#1%
+ {\doreadtableformatkeys b{#1}}
+
+\newtableformatkey B{\doreadtableformatkeys f\bf} % Key "B": abbreviation for f\bf
+\newtableformatkey I{\doreadtableformatkeys f\it} % Key "I": abbreviation for f\it
+\newtableformatkey S{\doreadtableformatkeys f\sl} % Key "S": abbreviation for f\sl
+\newtableformatkey R{\doreadtableformatkeys f\rm} % Key "R": abbreviation for f\rm
+\newtableformatkey T{\doreadtableformatkeys f\tt} % Key "T": abbreviation for f\tt
+
+% Key "p": ParBox
+
+\newtableformatkey p%
+ {\!tgGetValue{\!tgSetUpParBox}}
+
+% Key "w": minimum column width
+
+\newtableformatkey w%
+ {\!tkTestForBeginFormat w{\!tgGetValue{\!tfSetWidth}}}
+
+% Key "s": Set tabskip for the inter-column space to the right of the current
+% column, and all subsequent spaces, until overriden by a new "s" or "o" key.
+
+\newtableformatkey s%
+ {\!taOnceOnlyTabskipfalse % in case same column has a prior "o" key
+ \!tkTestForBeginFormat t{\!tgGetValue{\!tfSetTabskip}}}
+
+% Key "o": Apply the \tabskip stated for this column ONLY to the inter-column space
+% just to the right of this column; restore the the previous \tabskip for
+% subsequent columns.
+
+\newtableformatkey o%
+ {\!taOnceOnlyTabskiptrue
+ \!tkTestForBeginFormat o{\!tgGetValue{\!tfSetTabskip}}}
+
+% Key "|": Standard rule column designator
+
+\newtableformatkey |%
+ {\!tkTestForBeginFormat |{\!tgGetValue{\!tfSetVrule}}}
+
+% Key "\|": Non-standard rule column designator
+
+\newtableformatkey \|%
+ {\!tkTestForBeginFormat \|{\!tfSetAlternateVrule}}
+
+% Key ".": PERIOD -- end of \tabl_table_begin_format section.
+
+\newtableformatkey .%
+ {\!tkTestForBeginFormat.{\!tfFinishFormat}}
+
+% Key "\doendtableformat": Equivalent to "."
+
+\newtableformatkey \doendtableformat
+ {\!tkTestForBeginFormat\doendtableformat{\!tfFinishFormat}}
+
+% Key "]": End of \tabl_table_reformat section
+
+\newtableformatkey ]%
+ {\!tkTestForReFormat ] \!tfEndReFormat}
+
+% TEST FOR BEGIN FORMAT{<Key>}{Intended Action}: This test is run on keys that can
+% only be used by \tabl_table_begin_format --- "s", "o", "|", "\|", "w", ".", and
+% "\doendtableformat".
+
+\def\!tkTestForBeginFormat#1#2%
+ {\if!taBeginFormat
+ \def\tempstring{#2}%
+ \expandafter\tempstring
+ \else
+ \toks0={#1}%
+ \toks2=\expandafter{\string\tabl_table_reformat}%
+ \expandafter\!tkImproperUse
+ \fi}
+
+% TEST FOR RE FORMAT{<Key>}{Intended Action}: This test is run on the key "]",
+% which can only be used by \tabl_table_reformat.
+
+\def\!tkTestForReFormat#1#2%
+ {\if!taBeginFormat
+ \toks0={#1}%
+ \toks2=\expandafter{\string\tabl_table_begin_format}%
+ \expandafter\!tkImproperUse
+ \else
+ \def\tempstring{#2}%
+ \expandafter\tempstring
+ \fi}
+
+% NOTE: THE SPACE BETWEEN A NUMERIC ENTRY AND THE FOLLOWING '|', '"', OR '\|' IS
+% MANDATORY. EMPTY NUMERIC ENTRIES ARE NOT ALLOWED: USE '{}' OR '\omit' INSTEAD.
+
+\def\!tnTestForBracket
+ {\ifx[\!tnext
+ \expandafter\!tnGetArgument
+ \else
+ \expandafter\!tnGetCode
+ \fi}
+
+% GET CODE: E.g. "4", or "4.0", "0.4", or "10.2"
+
+\def\!tnGetCode#1 %
+ {\!tnConvertCode #1..!}
+
+% CONVERT CODE: E.g. converts above to [0000], [0000.], [.0000], [0000000000.00]
+
+\def\!tnConvertCode #1.#2.#3!%
+ {\begingroup
+ \aftergroup\edef \aftergroup\tempstring \aftergroup{%
+ \aftergroup[%
+ \scratchcounter#1\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \def\tempstring{#3}%
+ \ifx\tempstring \empty
+ \else
+ \aftergroup.
+ \scratchcounter#2\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \fi
+ \aftergroup]\aftergroup}%
+ \endgroup\relax
+ \expandafter\!tnGetArgument\tempstring}
+
+% GET ARGUMENT: [<sample left field> <optional .<sample right field>>
+
+\def\!tnGetArgument[#1]%
+ {\!tnMakeNumericTemplate\!tnStyle#1..!}
+
+% MAKE NUMERIC TEMPLATE
+
+\def\!tnMakeNumericTemplate#1#2.#3.#4!% #1=<empty> or $
+ {\def\tempstring{#4}%
+ \ifx\tempstring\empty
+ \!taDimenC\zeropoint
+ \else
+ \setbox\scratchbox=\hbox{\mathsurround\zeropoint #1.#3#1}%
+ \!taDimenC\wd\scratchbox
+ \fi
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}%
+ \!thToksEdef\!taDataColumnTemplate
+ {\noexpand\!tnSetNumericItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}%
+ \the\!taDataColumnTemplate}% Might have tabskip glue in here
+ \doreadtableformatkeys}
+
+% SET NUMERIC ITEM
+
+\def\!tnSetNumericItem #1#2#3#4 %
+ {\!tnSetNumericItemA {#1}{#2}{#3}#4..!}
+
+\def\!tnSetNumericItemA #1#2#3#4.#5.#6!%
+ {\def\tempstring{#6}%
+ \hbox to #1{\hss \mathsurround\zeropoint #3#4#3}%
+ \hbox to #2{\ifx\tempstring\empty\else\mathsurround\zeropoint #3.#5#3\fi\hss}}
+
+% extensions
+
+\newtableformatkey q%
+ {\letempty\!tqStyle
+ \futurelet\!tnext\!tqTestForBracket}
+
+\newtableformatkey Q%
+ {\def\!tqStyle{$}%
+ \futurelet\!tnext\!tqTestForBracket}
+
+\def\!tqTestForBracket
+ {\ifx[\!tnext
+ \!thx\!tqGetArgument
+ \else
+ \!thx\!tqGetCode
+ \fi}
+
+\def\!tqGetCode#1 % note the blank
+ {\!tqConvertCode #1,,!}
+
+\def\!tqConvertCode #1,#2,#3!%
+ {\begingroup
+ \aftergroup\edef
+ \aftergroup\tempstring
+ \aftergroup{%
+ \aftergroup[%
+ \scratchcounter#1\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \def\tempstring{#3}%
+ \ifx\tempstring\empty
+ \else
+ \aftergroup,
+ \scratchcounter#2\relax
+ \!thLoop
+ \ifnum\scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \fi
+ \aftergroup]\aftergroup}%
+ \endgroup\relax
+ \!thx\!tqGetArgument\tempstring}
+
+\def\!tqGetArgument[#1]%
+ {\!tqMakeQuantityTemplate\!tqStyle#1,,!}
+
+\def\!tqMakeQuantityTemplate#1#2,#3,#4!% #1=<empty> or $
+ {\def\tempstring{#4}%
+ \ifx\tempstring\empty
+ \!taDimenC\zeropoint
+ \else
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1,#3#1}%
+ \!taDimenC\wd\scratchbox
+ \fi
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}%
+ \!thToksEdef\!taDataColumnTemplate
+ {\noexpand\!tqSetQuantityItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}%
+ \the\!taDataColumnTemplate}%
+ \doreadtableformatkeys}
+
+\def\!tqSetQuantityItem #1#2#3#4 %
+ {\!tqSetQuantityItemA{#1}{#2}{#3}#4,,!}
+
+\def\!tqSetQuantityItemA #1#2#3#4,#5,#6!%
+ {\def\tempstring{#6}%
+ \hbox to #1{\hss\mathsurround\zeropoint#3#4#3}%
+ \hbox to #2{\ifx\tempstring\empty\else\mathsurround\zeropoint#3,#5#3\fi\hss}}
+
+% \Enlarge<extra height><extra depth><original>
+% \enlarge<multiple for extra height><multiple for extra depth><original>
+
+\def\tabl_table_Enlarge#1#2%
+ {% 3rd argument is picked up later
+ % #1=extra height
+ % #2=extra depth
+ \!taDimenA=#1\relax
+ \!taDimenB=#2\relax
+ \let\!TsSpaceFactor\empty
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!TsEnlargeMath
+ \else
+ \expandafter\!TsEnlargeOther
+ \fi}
+
+\def\!TsEnlargeOther#1%
+ {\ifhmode
+ \setbox\scratchbox\hbox{#1\xdef\!TsSpaceFactor{\spacefactor\the\spacefactor}}%
+ \else
+ \setbox\scratchbox\hbox{#1}%
+ \fi
+ \!TsFinishEnlarge}
+
+\def\!TsEnlargeMath#1#2%
+ {\setbox\scratchbox\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}%
+ \!TsFinishEnlarge}
+
+\def\!TsFinishEnlarge
+ {\ht\scratchbox\dimexpr\ht\scratchbox+\!taDimenA\relax
+ \dp\scratchbox\dimexpr\dp\scratchbox+\!taDimenB\relax
+ \box\scratchbox
+ \!TsSpaceFactor\relax}
+
+\def\tabl_table_enlarge#1#2% 3rd argument is picked up later
+ {\tabl_table_Enlarge{#1\d_tabl_table_strut_unit}{#2\d_tabl_table_strut_unit}}
+
+\appendtoks
+ \let\enlarge\tabl_table_enlarge
+ \let\Enlarge\tabl_table_Enlarge
+\to \everytable
+
+% BEGIN TABLE
+
+\let\tabl_table_standard_end\relax
+
+\def\tabl_table_standard_begin[#1]% \!ttBeginTable (always argument)
+ {\if#1u% unboxed table
+ \ifmmode
+ \let\tabl_table_standard_end\relax % user had better be in display math mode and have only one table at the outer level
+ \else % user had better be in vertical mode
+ \bgroup
+ \let\tabl_table_standard_end\egroup
+ \fi
+ \else
+ \hbox\bgroup
+ \def\tabl_table_standard_end{\egroup\egroup}%
+ \if#1t%
+ \vtop
+ \else\if#1b%
+ \vbox
+ \else
+ \def\tabl_table_standard_end{\egroup\normalstopimath\egroup}%
+ \scratchtoks\everymath
+ \everymath\emptytoks
+ \normalstartimath
+ \everymath\scratchtoks
+ \vcenter
+ \fi\fi
+ \bgroup % for the \vtop, \vbox, or \vcenter
+ \fi
+ \advance\!taRecursionLevel\plusone
+ \let\!ttRightGlue\relax
+ \everycr\emptytoks
+ \ifnum\!taRecursionLevel=\plusone
+ \the\everytable
+ \fi}
+
+\bgroup \catcode\tildeasciicode\activecatcode
+
+ \appendtoks
+ \catcode\barasciicode\activecatcode
+ \def~{\kern.5em}%
+ \def\\{\ifhmode\space\else\par\fi}%
+ \to \everytable
+
+\egroup
+
+\let\!ttRightGlue\relax % This may be changed, in a group, by \JustCenter, etc
+
+% DO HALIGN: Invoked by END FORMAT (or the key ".")
+
+\let\tabl_table_restore_lineskips\relax
+
+\def\!ttDoHalign
+ {\edef\tabl_table_restore_lineskips
+ {\baselineskip \the\baselineskip
+ \lineskiplimit\the\lineskiplimit
+ \lineskip \the\lineskip
+ \tabskip \the\tabskip
+ \relax}%
+ \baselineskip \zeropoint
+ \lineskiplimit\zeropoint
+ \lineskip \zeropoint
+ \tabskip \zeropoint
+ \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}%
+ \halign \ifx\p_tabl_table_textwidth\empty \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi
+% \the\!taTableSpread
+ \bgroup
+ \span
+ \the\!taPreamble
+ \ifx\!tfRowOfWidths\empty\else
+ \!tfRowOfWidths\cr
+ \fi}
+
+% END TABLE
+
+\def\tabl_table_normal_end
+ {\egroup % finishes the \halign
+ \tabl_table_standard_end} % closes off the table envirnoment set up by \tablestandardbegin
+
+\def\tabl_table_normal_line_ending
+ {\cr}
+
+\def\tabl_table_normal_line_format#1#2%
+ {\vrule
+ \s!width \zeropoint
+ \s!height\dimexpr\tablestrutheightfactor\d_tabl_table_strut_unit+#1\d_tabl_table_strut_unit\relax
+ \s!depth \dimexpr\tablestrutdepthfactor \d_tabl_table_strut_unit+#2\d_tabl_table_strut_unit\relax
+ \relax
+ \cr}
+
+% INSERT VRULE
+
+\newcount\c_tabl_table_n_of_vrules \c_tabl_table_n_of_vrules\plusone
+
+\let\m_tabl_table_vrule_color\empty
+\let\m_tabl_table_hrule_color\empty
+
+\def\do!ttInsertVrule
+ {\vrule\s!width
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \c_tabl_table_vrule_thickness_factor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue
+ \fi
+ \hskip.125\emwidth\relax}
+
+\def\tabl_table_normal_line_simple_bar
+ {\unskip\!ttRightGlue\aligntab\aligntab}
+
+\def\tabl_table_normal_line_complex_bar
+ {\unskip\!ttRightGlue\aligntab\omit
+ \hfil
+ \ifx\m_tabl_table_vrule_color\empty\else
+ \switchtocolor[\m_tabl_table_vrule_color]%
+ \fi
+ \ifcase\c_tabl_table_n_of_vrules\or
+ \do!ttInsertVrule
+ \unskip
+ \else
+ \dorecurse\c_tabl_table_n_of_vrules\do!ttInsertVrule
+ \global\c_tabl_table_n_of_vrules\plusone
+ \unskip
+ \fi
+ \global\let\m_tabl_table_vrule_color\empty
+ \hfil
+ \aligntab}
+
+\def\tabl_table_normal_no_bar
+ {\unskip\!ttRightGlue\aligntab\omit\aligntab}
+
+\def\tabl_table_normal_single_rule
+ {\aligntab\tabl_table_normal_long_rule\aligntab}
+
+\def\tabl_table_normal_multi_rule
+ {\aligntab\tabl_table_use\c_tabl_table_drule_span\tabl_table_normal_long_rule\aligntab}
+
+% USE
+
+\def\tabl_table_use#1%
+ {\ifnum#1>\plusone
+ \omit
+ \global\setfalse\c_tabl_table_is_division % added
+ \scratchcounter\currenttablecolumn % added
+ \advance\scratchcounter #1% % added
+ \advance\scratchcounter \minusone % added
+ \def\next % added
+ {\global\advance\currenttablecolumn #1% % added
+ \global\advance\currenttablecolumn \minusone % added
+ \scratchcounter#1%
+ \advance\scratchcounter \minusone
+ \advance\scratchcounter \scratchcounter
+ \!thLoop
+ \ifnum\scratchcounter>\plusone
+ \spanomit \advance\scratchcounter\minusone
+ \repeat
+ \span}%
+ \else % added
+ \def\next % conflicts with possible next \omit % added
+ {\global\advance\currenttablecolumn \plusone}%% added
+ \fi
+ \next} % added
+
+\def\tabl_table_Use#1[%
+ {\tabl_table_use{#1}%
+ \tabl_table_reformat[}
+
+\appendtoks
+ \let\use\tabl_table_use
+ \let\Use\tabl_table_Use
+\to \everytable
+
+% rules
+
+\def\tabl_table_normal_full_rule
+ {\starttablenoalign
+ \!ttGetHalfRuleThickness
+ \hrule\s!height\scratchdimen\s!depth\scratchdimen
+ \stoptablenoalign}
+
+\def\tabl_table_normal_short_rule % was: \!ttShortHrule
+ {\omit
+ \!ttGetHalfRuleThickness
+ \ifx\m_tabl_table_hrule_color\empty\else
+ \switchtocolor[\m_tabl_table_hrule_color]% see *DL*
+ \fi
+ \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill
+ \emptyhbox
+ \ignorespaces}
+
+\def\tabl_table_normal_long_rule % was: \!ttLongHrule
+ {\omit\span
+ \omit\span
+ \tabl_table_normal_short_rule}
+
+\def\!ttGetHalfRuleThickness
+ {\scratchdimen\dimexpr
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \c_tabl_table_hrule_thickness_factor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue % user-specified dimension
+ \fi
+ \divide\scratchdimen\plustwo}
+
+% \emptyhbox prevents \unskip
+
+\def\tabl_table_Left #1{#1\hfill\emptyhbox}
+\def\tabl_table_Center#1{\hfill#1\hfill\emptyhbox}
+\def\tabl_table_Right #1{\hfill#1}
+
+\def\tabl_table_OpenUp#1#2%
+ {\edef\tablestrutheightfactor{\withoutpt\the\dimexpr\tablestrutheightfactor\points+#1\points}%
+ \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr\tablestrutdepthfactor \points+#2\points}}
+
+% SetTableToWidth -> textwidth=dimension [to dimension]
+% Expand -> textwidth=max [to \hsize]
+% WidenTableBy -> [spread #1]
+% \tablelefttabskip\zeropoint\s!plus1\s!fill
+% \tablerighttabskip\tablelefttabskip
+% LongLines -> [spread \hsize]
+
+\def\tabl_table_JustLeft {\omit\let\!ttRightGlue\hfill}
+\def\tabl_table_JustCenter{\omit\hfill\emptyhbox\let\!ttRightGlue\hfill}
+\def\tabl_table_JustRight {\omit\hfill\emptyhbox}
+
+\def\tabl_table_Smash
+ {\relax
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!thDoMathVCS
+ \else
+ \expandafter\!thDoVCS
+ \fi}
+
+\def\!thDoVCS#1%
+ {\setbox\zerocount\hbox{#1}%
+ \!thFinishVCS}
+
+\def\!thDoMathVCS#1#2%
+ {\setbox\zerocount\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}%
+ \!thFinishVCS}
+
+\def\!thFinishVCS
+ {\vpack to\zeropoint{\vss\box\zerocount\vss}}
+
+\def\tabl_table_Raise
+ {\def\!thSign{+}%
+ \!tgGetValue\!thSetDimen}
+
+\def\tabl_table_Lower
+ {\def\!thSign{-}%
+ \!tgGetValue\!thSetDimen}
+
+\def\!thSetDimen
+ {\ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \!taDimenA\tablestrutheightfactor\d_tabl_table_strut_unit
+ \advance\!taDimenA\tablestrutdepthfactor\d_tabl_table_strut_unit
+ \divide\!taDimenA\plustwo
+ \else
+ \!taDimenA\!tgValue\d_tabl_table_strut_unit
+ \fi
+ \else
+ \!taDimenA\!tgValue
+ \fi
+ \!taDimenA\!thSign\!taDimenA\relax
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!thDoMathRaise
+ \else
+ \expandafter\!thDoSimpleRaise
+ \fi}
+
+\def\!thDoSimpleRaise#1%
+ {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{#1}}%
+ \!thFinishRaise} % From Plain TeX: \ht0=0pt \dp0=0pt \box0
+
+\def\!thDoMathRaise#1#2%
+ {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}}%
+ \!thFinishRaise}
+
+\def\!thFinishRaise
+ {\ht\zerocount\zeropoint
+ \dp\zerocount\zeropoint
+ \box\zerocount}
+
+\def\tabl_table_BackSpace
+ {\!tgGetValue\!thKernBack}
+
+\def\!thKernBack
+ {\kern -
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \tablekernfactor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_kern_unit
+ \else
+ \!tgValue % user-specified dimension
+ \fi
+ \ignorespaces}
+
+\def\tabl_table_Vspace
+ {\noalign
+ \bgroup
+ \!tgGetValue\!thVspace}
+
+\def\!thVspace
+ {\vskip
+ \ifnum\!tgCode=\plusone
+ \ifx\!tgValue\empty
+ \tablevspacefactor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_strut_unit
+ \else
+ \!tgValue % user-specified skip
+ \fi
+ \egroup} % Ends the \noalign
+
+\appendtoks
+ \let\JustLeft \tabl_table_JustLeft
+ \let\JustCenter \tabl_table_JustCenter
+ \let\JustRight \tabl_table_JustRight
+ \let\Smash \tabl_table_Smash
+ \let\Raise \tabl_table_Raise
+ \let\Lower \tabl_table_Lower
+ \let\BackSpace \tabl_table_BackSpace
+ \let\Vspace \tabl_table_Vspace
+ \let\OpenUp \tabl_table_OpenUp
+ \let\TableLeft \tabl_table_Left
+ \let\TableCenter \tabl_table_Center
+ \let\TableRight \tabl_table_Right
+\to \everytable
+
+%D \macros
+%D {inintable, ifsplittables}
+%D
+%D First we declare some variables. These show a bit what we are dealing with. First
+%D we introdoce some booleans that enable us, inside as well as outside this module,
+%D to determine in what mode we are.
+
+\newif\ifintable
+\newif\ifsplittables
+
+%D We show this feature in an example that also shows some of the basic table
+%D typesetting commands.
+%D
+%D \startbuffer
+%D \starttable[|||]
+%D \HL
+%D \VL first \VL second \VL\AR
+%D \HL
+%D \VL alfa \VL 1 \VL\AR
+%D \VL beta \VL 2 \VL\AR
+%D \VL gamma \VL 3 \VL\AR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D This table is specified as:
+%D
+%D \typebuffer
+%D
+%D This examples shows about the minimum of commands needed to typeset such a table.
+%D In this table, the \type {\AR} is automatically translated into the more
+%D primitive (but more verbose) commands \type {\SR}, \type {\FR}, \type {\MR} and
+%D \type {\LR} commands.
+%D
+%D \startbuffer
+%D \starttables[|||]
+%D \HL
+%D \VL first \VL second \VL\AR
+%D \HL
+%D \VL alfa \VL 1 \VL\AR
+%D \VL beta \VL 2 \VL\AR
+%D \VL gamma \VL 3 \VL\AR
+%D \HL
+%D \stoptables
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D Some simple color support is provided:
+%D
+%D \startbuffer
+%D \starttable[|c|c|]
+%D \HL
+%D \VL test \VL test \VL \SR
+%D \HL[green,5]
+%D \VL[red] test \VL test \VL \FR
+%D \VL test \VL[10,red] test \VL \MR
+%D \VL test \VL test \VL[10] \LR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{tabletemplate}
+
+\def\m!TABLE{TABLE}
+
+%D We already saw that the table macros report errors and provide automatic spacing.
+%D These features can only be implemented by keeping track of the state, often the
+%D last command on a row.
+
+\newconstant\tableforcestate
+\newconstant\tableactionstate
+
+\setnewconstant\tableunknownstate 0
+
+\setnewconstant\tableseparaterowstate 1
+\setnewconstant\tablefirstrowstate 2
+\setnewconstant\tablemidrowstate 3
+\setnewconstant\tablelastrowstate 4
+\setnewconstant\tablerulestate 5
+%setnewconstant\tableskipstate 6
+%setnewconstant\tableautorowstate 7
+
+\setnewconstant\tableforcefirstrowstate 1
+\setnewconstant\tableforcelastrowstate 2
+
+\newconstant\tablerowfactor
+\newconstant\TABLEendofrowdepth
+\newconstant\TABLEendofrowheight
+\newconstant\TABLEcr
+\newconstant\tablerowzero
+\newconstant\TABLEn
+
+%D We store these states using \type {constants}'s and like most variables, these
+%D are global ones. When needed, especially when we flush the backgrounds, we can
+%D temporary disable the assignment.
+
+\newconditional\tableactionstatepermitted
+
+\def\tabl_table_set_action#1{\ifconditional\tableactionstatepermitted\global\tableactionstate#1\fi}
+\def\tabl_table_set_force #1{\ifconditional\tableactionstatepermitted\global\tableforcestate #1\fi}
+
+%D To give an impression of what the (well documented) source of \TABLE\ looks like,
+%D we first implement an alternative for the numeric keys. The quantity keys
+%D (\type{q} and \type{Q}) support the more european way of writing numbers:
+%D
+%D \startnarrower
+%D 100.000.000,00 instead of 100,000,000.00
+%D \stopnarrower
+%D
+%D The next table shows how to use these keys. We use braces instead of brackets because
+%D we need brackets to specify the format.
+%D
+%D \starttyping
+%D \starttable{|q[00,000]|Q[00,00]|}
+%D \HL
+%D \VL -1,2 \VL 12,35 \VL\FR
+%D \VL 11,203 \VL 2,4 \VL\LR
+%D \HL
+%D \stoptable
+%D \stoptyping
+%D
+%D Although a more efficient implementation is possible |<|we can for instance share
+%D common macros|>| we just adapt a copy of the numeric ones. To permit double
+%D loading of this module, we check for the existence of one of the macros.
+%D
+%D To be compatible with the tabulate environment, we also support the \type {l},
+%D \type {c} and \type {r} keys for paragraph entries.
+%D
+%D All commands that are executed between rows are to be put in \type {\noalign}. We
+%D can however not verify if we (that is \TABLE) does or did not enter this mode. A
+%D moderate dirty but useful trick is using our own alternative:\footnote{Once one
+%D has entered the stage of redefining \TEX\ primitives, such hacks become a second
+%D nature. However, redefining \type {\omit} and \type{\span} is not that easy.}
+
+\def\tablenoalign
+ {\noalign
+ \bgroup
+ \let\noalign\relax
+ \let\tablenoalign\relax
+ \let\next=}
+
+\def\starttablenoalign
+ {\tablenoalign\bgroup}
+
+\let\stoptablenoalign\egroup
+
+%D \macros
+%D {starttable}
+%D
+%D The rest of this module is not easy to comprehend, mainly because we have to take
+%D care of:
+%D
+%D \startitemize[packed]
+%D \item \type{\startitemize[template]}
+%D \item \type{\startitemize{template}}
+%D \item \type{\startitemize[predefined]}
+%D \stopitemize
+%D
+%D as well as:
+%D
+%D \startitemize[continue]
+%D \item restart after table break
+%D \stopitemize
+%D
+%D The official specification of the start command is:
+%D
+%D \showsetup{starttable}
+
+\newconditional\c_tabl_table_repeat_head
+\newconditional\c_tabl_table_repeat_tail
+
+\unexpanded\def\starttable
+ {\bgroup
+ \dodoubleempty\table_table_start}
+
+\unexpanded\def\table_table_start[#1][#2]% preamble optional-settings
+ {\ifsecondargument
+ \setupcurrenttables[#2]%
+ \fi
+ \let\stoptable\table_table_stop
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \edef\p_tabl_table_frame{\directtablesparameter\c!frame}%
+ \ifx\p_tabl_table_split\v!auto
+ \ifinsidesplitfloat
+ \let\p_tabl_table_split\v!yes
+ \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode
+ \fi
+ \fi
+ \ifx\p_tabl_table_split\v!yes
+ \def\stoptable{\table_table_stop_s\egroup}% not \unexpanded as we look ahead
+ \expandafter\starttables
+ \else\ifx\p_tabl_table_split\v!repeat
+ \def\stoptable{\table_table_stop_s\egroup}% not \unexpanded as we look ahead
+ \doubleexpandafter\starttables
+ \else
+ \ifx\p_tabl_table_frame\empty
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \else
+ \startframedcontent[\p_tabl_table_frame]%
+ \fi
+ \postponenotes
+ \doubleexpandafter\tabl_table_first_stage
+ \fi\fi
+ [#1]}
+
+% We cannot define the stopper as \type {\unexpanded} because lookahead in
+% alignments fail then, so we relax it and define it locally.
+
+\let\stoptable\relax
+
+\def\table_table_stop
+ {\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
+ \stoptablenoalign
+ \tabl_table_finish
+ \ifx\p_tabl_table_frame\empty
+ \ifinsidefloat\else
+ \stopbaselinecorrection
+ \goodbreak % compensates all the nobreaks
+ \fi
+ \else
+ \stopframedcontent
+ \fi
+ \egroup}
+
+%D Before we can grab the argument, we have to make sure that the \CATCODES\ are
+%D set. The first stage takes care of that.
+
+\def\tabl_table_first_stage
+ {\bgroup
+ \global\intabletrue
+ \tabl_table_second_stage}
+
+%D \macros
+%D {definetabletemplate}
+%D
+%D The complex (and main) start macro first takes care of the predefined case. Such
+%D a predefined setup looks like:
+%D
+%D \starttyping
+%D \definetabletemplate[test][|||]
+%D
+%D \starttable[test]
+%D \VL test \VL test \VL\AR
+%D \VL test \VL test \VL\AR
+%D \VL test \VL test \VL\AR
+%D \stoptable
+%D \stoptyping
+%D
+%D The implementation of the definition macro is not that complicated:
+
+\installcorenamespace{tablehead}
+\installcorenamespace{tabletail}
+
+\unexpanded\def\definetabletemplate % to be redone
+ {\bgroup
+ \catcode\barasciicode\othercatcode
+ \doquadrupleempty\tabl_table_define_template}
+
+\def\tabl_table_define_template[#1][#2][#3][#4]%
+ {\ifsecondargument
+ \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}%
+ \fi
+ \egroup}
+
+\def\tabl_table_use_template#1#2#3%
+ {\gdef\tabl_table_head{\begincsname\??tablehead#2\endcsname}%
+ \gdef\tabl_table_tail{\begincsname\??tabletail#3\endcsname}%
+ \tabl_table_second_stage[#1]}
+
+%D The optional third and fourth arguments define which table head and tail to use.
+%D
+%D \starttyping
+%D \definetabletemplate[test][|||][before][after]
+%D \stoptyping
+%D
+%D This also means that one can define table heads and tails by name!
+%D
+%D \starttyping
+%D \starttablehead[before]
+%D \HL \VL first \VL second \VL \SR \HL
+%D \stoptablehead
+%D \stoptyping
+%D
+%D Templates defined this way get protected names, that cannot conflict with
+%D existing commands.
+%D
+%D \showsetup{definetabletemplate}
+%D
+%D The second half of the next macro prepares table
+%D splitting.
+
+\def\tabl_table_insert_head
+ {\starttablenoalign
+ \global\settrue\preventtablebreak
+ \global\setfalse\hassometablehead
+ \stoptablenoalign
+ \tabl_table_head
+ \starttablenoalign
+ \global\setfalse\preventtablebreak
+ \stoptablenoalign}
+
+\def\tabl_table_insert_tail
+ {\starttablenoalign
+ \global\settrue\preventtablebreak
+ \global\setfalse\hassometabletail
+ \stoptablenoalign
+ \tabl_table_tail
+ \starttablenoalign
+ \global\setfalse\preventtablebreak
+ \stoptablenoalign}
+
+% \def\doverysimpletableHL % todo
+% {\starttablenoalign
+% \normalexpanded{\noexpand\tabl_table_normal_full_rule\m_tabl_table_HLheight}%
+% \stoptablenoalign}
+
+\def\tabl_table_restart_indeed#1%
+ {\gdef\tabl_table_restart{#1}%
+ \tabl_table_restart
+% \starttablenoalign
+% \globalpushmacro\simpletableHL
+% \global\let\simpletableHL\doverysimpletableHL
+% \stoptablenoalign
+ \tabl_table_insert_head
+ \ifsplittables \ifconditional \c_tabl_table_repeat_tail
+ \tablenoalign{\goodbreak}%
+ \tabl_table_insert_tail
+ \tablenoalign{\goodbreak}%
+ \fi \fi
+% \starttablenoalign
+% \globalpopmacro\simpletableHL
+% \stoptablenoalign
+ }
+
+\bgroup \catcode\barasciicode\othercatcode
+
+\gdef\tabl_table_second_stage[#1]% brr nested mess
+ {\bgroup
+ \tabl_table_use_bar
+ \global\setfalse\tableactionstatepermitted
+ \global\setfalse\hassometablehead
+ \global\setfalse\hassometabletail
+ \expanded{\doifelseinstring{|}{#1}}
+ {\xdef\tabl_table_restart{\noexpand\tabl_table_restart_indeed{\noexpand\tabl_table_third_stage{#1}}}}
+ {\doifelsedefined{\??tabletemplate#1}
+ {\gdef\tabl_table_restart{\getvalue{\??tabletemplate#1}}}
+ {\gdef\tabl_table_restart{\tabl_table_restart_indeed{\getvalue{#1}}}}}%
+ \egroup
+ \tabl_table_restart}
+
+\egroup
+
+%D The third stage involves a lot of (re)sets, which we will explain later.
+
+\appendtoks
+ \fixedspaces
+ \let\_\normalunderscore
+\to \everytable
+
+%D Now we can start the table.
+
+\newtoks\localtabledefinitions
+
+\def\tabl_table_third_stage#1%
+ {\global\settrue\tableactionstatepermitted
+ \tabl_table_set_action\tableunknownstate
+ \tabl_table_set_force\tableunknownstate
+ \tabl_table_resetVLvalues
+ \appendtoks\tabl_table_local_setups\to\everytable
+ \tabl_table_standard_begin[\ifsplittables u\else b\fi]%
+ \the\localtabledefinitions
+ \forgetall % added
+ \edef\currenttableformat{#1}%
+ \doifsomething\currenttableformat
+ {\dogettablenofcolumns\currenttableformat
+ % more modern is to use catcode tables
+ \expandafter\tabl_table_begin_format\currenttableformat\doendtableformat}}
+
+\def\tabl_table_finish
+ {\tabl_tables_chuck_auto_row
+ \unskip\crcr
+ \tabl_table_normal_end
+ \global\intablefalse
+ \egroup}
+
+%D \macros
+%D {starttables}
+%D
+%D Split tables are specified using the plural form of the start and stop commands.
+%D
+%D \showsetup{starttables}
+%D
+%D For example:
+%D
+%D \starttyping
+%D \starttables[|||]
+%D \HL
+%D \VL element \VL atom weight \VL\AR
+%D \HL
+%D \VL ....... \VL ........... \VL\AR
+%D \VL ....... \VL ........... \VL\AR
+%D \HL
+%D \stoptables
+%D \stoptyping
+
+\newbox\tablecontentbox
+
+\unexpanded\def\starttables
+ {\bgroup
+ \let\stoptables\table_table_stop_s
+ \splittablestrue
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \ifx\p_tabl_table_split\v!repeat
+ \settrue\c_tabl_table_repeat_head
+ \settrue\c_tabl_table_repeat_tail
+ \else
+ \setfalse\c_tabl_table_repeat_head
+ \setfalse\c_tabl_table_repeat_tail
+ \fi
+ \flushnotes
+ \setbox\tablecontentbox\vbox\bgroup
+ \forgetall
+ \tabl_table_first_stage}
+
+\let\stoptables\relax % needed for \noalign
+
+\def\table_table_stop_s % not \unexpanded as we need the lookahead (brrr)
+ {\tabl_tables_chuck_auto_row % AM: before the tail, else noalign problem
+ \ifconditional\c_tabl_table_repeat_tail\else\tabl_table_insert_tail\fi
+ \tabl_table_finish
+ \egroup
+ \dontcomplain
+ \tabl_table_split_box\tablecontentbox
+ \global\let\tabl_table_head\empty % new here
+ \global\let\tabl_table_tail\empty % new here
+ \flushnotes
+ \egroup}
+
+\def\tabl_table_split_box#1%
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{\zeropoint}%
+ \setbox\tsplitcontent\box#1%
+ \ifconditional\c_tabl_table_repeat_head \ifconditional\hassometablehead
+ \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvbox\tsplithead}%
+ \fi \fi
+ \ifconditional\c_tabl_table_repeat_tail \ifconditional\hassometabletail
+ \setbox\tsplittail\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplittail\vbox{\unvbox\tsplittail}%
+ \fi \fi
+ \ifinsidefloat\else
+ \def\tsplitbeforeresult{\startbaselinecorrection}%
+ \def\tsplitafterresult {\stopbaselinecorrection}%
+ \fi
+ \handletsplit}
+
+%D When the table in the previous example is split across pages, only the first gets
+%D a head. We could have said something like:
+%D
+%D \starttyping
+%D \starttablehead
+%D \HL
+%D \VL element \VL atom weight \VL\AR
+%D \HL
+%D \stoptablehead
+%D
+%D \starttabletail
+%D \HL
+%D \stoptabletail
+%D
+%D \starttables[|||]
+%D \VL ....... \VL ........... \VL\AR
+%D \VL ....... \VL ........... \VL\AR
+%D \stoptables
+%D \stoptyping
+%D
+%D This time each split table gets a head line and ends with a rule. Keep in mind
+%D that such heads also apply to the unbroken ones and should be defined local
+%D (grouped) if needed. The rather complicated definition below is due to the fact
+%D that the stopcondition is interface language dependant.
+
+\let\tabl_table_head\empty % needs checking
+\let\tabl_table_tail\empty % needs checking
+
+\letvalue{\e!start\v!tablehead}\relax
+\letvalue{\e!stop \v!tablehead}\relax
+\letvalue{\e!start\v!tabletail}\relax
+\letvalue{\e!stop \v!tabletail}\relax
+
+%D The second argument is a dummy one, by scanning for it, we get rid of
+%D interfering spaces.
+
+\newconditional\preventtablebreak
+\newconditional\hassometablehead
+\newconditional\hassometabletail
+
+\unexpanded\def\settablehead{\dodoubleempty\tabl_table_set_head}
+\unexpanded\def\settabletail{\dodoubleempty\tabl_table_set_tail}
+
+% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\tablenoalign{\global\settrue\hassometablehead}#3}}
+% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\tablenoalign{\global\settrue\hassometabletail}#3}}
+
+\def\tabl_table_set_head[#1][#2]#3\end
+ {\gdef\tabl_table_head{\begincsname\??tablehead#1\endcsname}% new
+ \setvalue{\??tablehead#1}{\tablenoalign{\global\settrue\hassometablehead}#3}}
+
+\def\tabl_table_set_tail[#1][#2]#3\end
+ {\gdef\tabl_table_tail{\begincsname\??tabletail#1\endcsname}% new
+ \setvalue{\??tabletail#1}{\tablenoalign{\global\settrue\hassometabletail}#3}}
+
+\normalexpanded
+ {\def\csname\e!start\v!tablehead\endcsname#1\csname\e!stop\v!tablehead\endcsname%
+ {\settablehead#1\noexpand\end}}
+
+\normalexpanded
+ {\def\csname\e!start\v!tabletail\endcsname#1\csname\e!stop\v!tabletail\endcsname%
+ {\settabletail#1\noexpand\end}}
+
+%D Redundant \type{\HL}'s are removed automatically, so mid||lines can be used
+%D without problems.
+%D
+%D The order of the next macros is more or less random. First we implement error
+%D recovery. Errors are reported to the screen and log file as well as visualized in
+%D the table in teletype.
+
+\def\tabl_table_finish_row
+ {\crcr
+ \starttablenoalign
+ \nobreak
+ \tabl_table_set_action\tableunknownstate
+ \globalletempty\tabl_tables_check_auto_row
+ \globalletempty\tabl_tables_chuck_auto_row
+ \global\currenttablecolumn\zerocount
+ \stoptablenoalign}
+
+%D Next we enter the more complicated area of column and row switching. I won't go
+%D into much detail from now on, but just mention the general principles.
+%D
+%D \startitemize[3*ruim]
+%D \sym{\type{\SR}} end a separate row (between rules)
+%D \sym{\type{\FR}} end a first row (after a rule)
+%D \sym{\type{\MR}} end a mid row (between text lines)
+%D \sym{\type{\LR}} end a last row (before a rule)
+%D \stopitemize
+%D
+%D and best of all:
+%D
+%D \startitemize[continue]
+%D \sym{\type{\AR}} end a row with automatic spacing
+%D \stopitemize
+%D
+%D As far as possible, we report confusing situations. In most cases one can use
+%D \type{\AR}, which transfigurates itself into one of the other types.
+%D
+%D \starttyping
+%D \starttable[||]
+%D \HL
+%D \VL a separate row \VL\SR
+%D \HL
+%D \VL a first row \VL\FR
+%D \VL a mid row \VL\MR
+%D \VL a last row \VL\LR
+%D \HL
+%D \stoptable
+%D \stoptyping
+%D
+%D In this example we could have used \type{\AR} without problems.
+%D
+%D Color or gray scale backgrounds precede the content. They are passed over
+%D horizontal (division) lines when needed. Errors in the color template are traced
+%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\
+%D handles alignments, we cannot automate spacing for colored rows and columns.
+
+\setnewconstant\tablerowzero\zerocount
+
+\appendtoks
+ \let\SR\tabl_table_SR
+ \let\FR\tabl_table_FR
+ \let\MR\tabl_table_MR
+ \let\LR\tabl_table_LR
+ \let\AR\tabl_table_AR
+\to \localtabledefinitions
+
+\unexpanded\def\tabl_table_SR
+ {\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \else\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \else\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \fi\fi\fi
+ \tabl_table_end_row_indeed\tableseparaterowstate\tablerowfactor\tablerowfactor}
+
+\unexpanded\def\tabl_table_FR
+ {\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}%
+ \else\ifnum\tableactionstate=\tablelastrowstate
+ \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}%
+ \fi\fi
+ \tabl_table_end_row_indeed\tablefirstrowstate\tablerowfactor\tablerowzero}
+
+\unexpanded\def\tabl_table_MR
+ {\ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{change \string\MR\space into \string\FR/\string\SR}%
+ \else\ifnum\tableactionstate=\tablelastrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\FR}%
+ \fi\fi
+ \tabl_table_end_row_indeed\tablemidrowstate00}
+
+\unexpanded\def\tabl_table_LR
+ {\ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{change \string\LR\space into \string\FR/\string\SR}%
+ \fi
+ \tabl_table_end_row_indeed\tablelastrowstate\tablerowzero\tablerowfactor}
+
+%D \macros
+%D {ifcheckTABLEcolums}
+%D
+%D The next macros handle the actual row ending. This macro also take care of space
+%D corrections due to table splitting when \type{\MR} and collegues are used. When
+%D tracing is enabled, the corrections as well as the values used to determine the
+%D available space are shown (in color). By default checking is off.
+
+\def\tabl_table_end_row_indeed#1#2#3%
+ {\tabl_table_set_action#1%
+ \ifcase#1\relax
+ % unknown
+ \or
+ \tabl_tables_end_line\SR\SR\tablerowfactor\tablerowfactor
+ \or
+ \tabl_tables_end_line\FR\FR\tablerowfactor\tablerowzero
+ \or\ifnum\tableforcestate=\tableforcelastrowstate
+ \tabl_tables_end_line\MR\LR\tablerowzero\tablerowfactor
+ \else\ifnum\tableforcestate=\tableforcefirstrowstate
+ \tabl_tables_end_line\MR\FR\tablerowfactor\tablerowzero
+ \else
+ \tabl_tables_end_line\MR\MR\tablerowzero\tablerowzero
+ \fi\fi\or
+ \tabl_tables_end_line\LR\LR\tablerowzero\tablerowfactor
+ \fi
+ \starttablenoalign
+ \tabl_table_set_force\tableunknownstate
+ \global\currenttablecolumn\zerocount
+ \ifconditional\preventtablebreak
+ \nobreak
+ \else
+ \goodbreak
+ \fi
+ \stoptablenoalign}
+
+%D Handling \type{\AR} is postponed till the next row. The check takes care of
+%D the first and mid rows, the chuck macro |<|how about that name|>| handles
+%D the last row.
+
+\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}
+
+\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
+ \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
+ \ifnum\tableactionstate=\tablerulestate \SR\else
+ \ifnum\tableactionstate=\tableunknownstate\SR\else
+ \LR\fi\fi}
+
+%D When a table is split, we also add a tail and when present we repeat the table
+%D head. If a gets split indeed, the spacing before and after a horizontal rule is
+%D corrected according to what we expect.
+
+\def\tabl_tables_end_line#1#2#3#4%
+ {\ifx#1#2\else
+ \writestatus\m!TABLE{\string#1\space changed into \string#2}%
+ \fi
+ \expandafter\tabl_table_normal_line_format#3#4\crcr % \crcr nodig ?
+ \tablenoalign{\nobreak\global\settrue\tableactionstatepermitted}}
+
+%D In order to prevent (as good as possible) alignment overflow and therefore \TEX\
+%D error messages, we check the maximum number of columns. We keep track of the
+%D current column and maximum column by means of two \COUNTERS. Keep in mind that
+%D the number of \type{|}'s and \type{\VL}'s or alike is always one more than the
+%D number of columns.
+
+\newcount\currenttablecolumn
+
+% DWhile defining this macro we change the \CATCODE\ of \type{|}. When counting the
+% Dbars, we use a non active representation of the bar, simply because we cannot be
+% Dsure if the bar is active or not.\footnote{Normally it is, but \TABLE\ changes
+% Dthe catcode when needed.}
+
+\bgroup
+ \catcode\barasciicode\othercatcode \gdef\tabl_table_bar {|}
+ \catcode\barasciicode\activecatcode \gdef\tabl_table_use_bar{\let|\tabl_table_bar}
+\egroup
+
+\bgroup \catcode\barasciicode\othercatcode
+
+\gdef\dogettablenofcolumns#1% todo: also divert this to lua as with tabulate
+ {\bgroup
+ \cleanupfeatures % needed !
+ \tabl_table_use_bar
+ \egroup}
+
+\egroup
+
+%D \startitemize[3*ruim]
+%D \sym{\type{\VL}} a vertical line
+%D \sym{\type{\VC}} a vertical colored line
+%D \sym{\type{\HL}} a horizontal line
+%D \sym{\type{\HC}} a horizontal colored line
+%D \stopitemize
+
+\newcount\c_tabl_table_vrule_thickness_factor
+\newcount\c_tabl_table_hrule_thickness_factor
+\newcount\c_tabl_table_drule_span
+
+\let\m_tabl_table_vrule_color\empty
+\let\m_tabl_table_hrule_color\empty
+
+\appendtoks
+ \let\VL\tabl_table_VL
+ \let\VC\tabl_table_VC
+ \let\HL\tabl_table_HL
+ \let\HC\tabl_table_HC
+ \let\VS\tabl_table_VS
+ \let\VD\tabl_table_VD
+ \let\VT\tabl_table_VT
+ \let\VN\tabl_table_VN
+\to \localtabledefinitions
+
+\def\tabl_table_resetVLvalues
+ {\global\currenttablecolumn\zerocount}
+
+\def\tabl_table_vrulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\global\c_tabl_table_vrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax}
+ {\xdef\m_tabl_table_vrule_color{#1}}}
+
+\unexpanded\def\tabl_table_VL
+ {\tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn\plusone
+ \dosingleempty\table_tabl_VL_indeed}
+
+\def\table_tabl_VL_indeed[#1]%
+ {\global\let\m_tabl_table_vrule_color\empty
+ \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax
+ \iffirstargument
+ \rawprocesscommalist[#1]\tabl_table_vrulecommand
+ \fi
+ \tabl_table_normal_line_complex_bar}% \relax breaks \use
+
+\let\tabl_table_VC\tabl_table_VL % for mojca
+
+% \starttable[|||]
+% \HL
+% \VL test \VS test \VL \FR
+% \VL test \VD test \VL \MR
+% \VL test \VT test \VL \LR
+% \HL
+% \stoptable
+
+\unexpanded\def\tabl_table_VS {\VN1}
+\unexpanded\def\tabl_table_VD {\VN2}
+\unexpanded\def\tabl_table_VT {\VN3}
+\unexpanded\def\tabl_table_VN#1{\global\c_tabl_table_n_of_vrules#1\relax\VL}
+
+\def\tabl_table_hrulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\global\c_tabl_table_hrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax}
+ {\xdef\m_tabl_table_hrule_color{#1}}}
+
+\unexpanded\def\tabl_table_HL
+ {\tabl_tables_chuck_auto_row
+ \tabl_table_finish_row
+ \starttablenoalign
+ \dosingleempty\table_tabl_HL_indeed}
+
+\def\table_tabl_HL_indeed[#1]%
+ {\nobreak
+ \ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{skipping \string\HL}% \statusmessage
+ \else
+ \ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}%
+ \else\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\SR}%
+ \fi\fi
+ \bgroup
+ \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
+ \iffirstargument
+ \global\let\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]%
+ \fi
+ \fi
+ \tabl_table_normal_full_rule
+ \egroup
+ \tabl_table_account_width
+ \fi
+ \tabl_table_set_action\tablerulestate
+ \nobreak
+ \stoptablenoalign}
+
+\let\tabl_table_HC\tabl_table_HL % for mojca
+
+%D \startitemize[3*ruim]
+%D \sym{\type{\NL}} a vertical skip
+%D \sym{\type{\NR}} goto the next row
+%D \sym{\type{\NC}} goto the next column
+%D \sym{\type{\FC}} a first column
+%D \sym{\type{\MC}} a mid column
+%D \sym{\type{\LC}} a last column
+%D \stopitemize
+
+% \starttable[|||]
+% \VL text \VL text \VL \AR
+% \TB[small]
+% \VL text \VL text \VL \AR
+% \TB[4*big]
+% \VL text \VL text \VL \AR
+% \stoptable
+
+% n+1 uitleggen
+
+\appendtoks
+ \let\TB\tabl_table_TB
+ \let\NL\tabl_table_NL % old
+ \let\NR\tabl_table_NR
+ \let\NC\tabl_table_NC
+ \let\FC\tabl_table_NC
+ \let\MC\tabl_table_NC
+ \let\LC\tabl_table_NC
+\to \localtabledefinitions
+
+\unexpanded\def\tabl_table_TB
+ {\tabl_tables_chuck_auto_row
+ \tabl_table_finish_row
+ \starttablenoalign
+ \dosingleempty\table_tabl_TB_indeed}
+
+\def\table_tabl_TB_indeed[#1]%
+ {\blank[\iffirstargument#1\else\directtablesparameter\c!NL\fi]%
+ \nobreak
+ \stoptablenoalign}
+
+\let\tabl_table_NL\tabl_table_TB
+
+\unexpanded\def\tabl_table_NR
+ {\global\currenttablecolumn\zerocount
+ \tabl_table_normal_line_ending
+ \starttablenoalign
+ \nobreak
+ \tabl_table_set_action\tableunknownstate
+ \stoptablenoalign}
+
+\unexpanded\def\tabl_table_NC
+ {\tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_no_bar}
+
+%D \startitemize[3*broad]
+%D \sym{\type{\DL}}
+%D \sym{\type{\DV}} (\type{\VD})
+%D \sym{\type{\DC}}
+%D \sym{\type{\DR}}
+%D \stopitemize
+
+\newconditional\c_tabl_table_is_division
+
+\appendtoks
+ \global\setfalse\c_tabl_table_is_division
+ \let\DL\tabl_table_DL
+ \let\DC\tabl_table_DC
+ \let\DV\tabl_table_DV
+ \let\DR\tabl_table_DR
+\to \localtabledefinitions
+
+\def\tabl_table_check_division
+ {\ifconditional\c_tabl_table_is_division\else
+ \tabl_tables_chuck_auto_row
+ \global\currenttablecolumn\zerocount
+ \global\settrue\c_tabl_table_is_division
+ \fi}
+
+\def\tabl_table_drulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\ifcase\c_tabl_table_drule_span
+ \global\c_tabl_table_drule_span#1\relax
+ \else
+ \global\c_tabl_table_hrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_VLwidth\relax
+ \fi}
+ {\xdef\m_tabl_table_hrule_color{#1}}}
+
+\unexpanded\def\tabl_table_DL
+ {\tabl_table_check_division
+ \dosingleempty\table_tabl_DL_indeed}
+
+\def\table_tabl_DL_indeed[#1]%
+ {\ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{skipping \string\DL}%
+ \else
+ \ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}%
+ \else\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\SR}%
+ \fi\fi
+ \tabl_table_set_action\tableunknownstate
+ \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
+ \global\c_tabl_table_drule_span\zerocount
+ \iffirstargument
+ \global\let\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*
+ % \fi
+ \fi
+ \ifcase\c_tabl_table_drule_span
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_single_rule
+ \or
+ \global\advance\currenttablecolumn \plustwo
+ \tabl_table_normal_single_rule
+ \else
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_multi_rule
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_table_DV
+ {\tabl_table_DCV\tabl_table_normal_line_simple_bar}
+
+\unexpanded\def\tabl_table_DC
+ {\tabl_table_DCV\tabl_table_normal_no_bar}
+
+\unexpanded\def\tabl_table_DCV#1%
+ {\tabl_table_check_division
+ \tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn \plusone
+ #1}
+
+\unexpanded\def\tabl_table_DR
+ {\global\currenttablecolumn\zerocount % nog check
+ \tabl_table_normal_line_ending
+ \starttablenoalign
+ \nobreak
+ \global\setfalse\c_tabl_table_is_division
+ \tabl_table_account_width % temporary solution
+ \tabl_table_set_action\tablerulestate
+ \stoptablenoalign}
+
+\def\tabl_table_account_width
+ {\scratchdimen\d_tabl_table_line_thickness_unit}
+
+\def\tabl_table_TWO {\use\plustwo}
+\def\tabl_table_THREE {\use\plusthree}
+\def\tabl_table_FOUR {\use\plusfour}
+\def\tabl_table_FIVE {\use\plusfive}
+\def\tabl_table_SIX {\use\plussix}
+
+\appendtoks
+ \let\TWO \tabl_table_TWO
+ \let\THREE\tabl_table_THREE
+ \let\FOUR \tabl_table_FOUR
+ \let\FIVE \tabl_table_FIVE
+ \let\SIX \tabl_table_SIX
+ \let\SPAN \use
+ \let\REF \tabl_table_reformat
+\to \localtabledefinitions
+
+\installcorenamespace{tables}
+\installcorenamespace{tabledistance}
+\installcorenamespace{tablealign}
+
+\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables
+
+\setvalue{\??tabledistance\v!none }{\tabl_table_OpenUp00\def\LOW{\Lower6 }}
+\setvalue{\??tabledistance\v!small }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} % == baseline
+\setvalue{\??tabledistance\v!medium}{\tabl_table_OpenUp11\def\LOW{\Lower7 }}
+\setvalue{\??tabledistance\v!big }{\tabl_table_OpenUp22\def\LOW{\Lower8 }}
+
+\appendtoks
+ \expandnamespaceparameter\??tabledistance\directtablesparameter\c!distance\v!medium
+\to \localtabledefinitions
+
+\setvalue{\??tablealign\v!right }{\def\tabl_table_paralignment{\raggedright}}
+\setvalue{\??tablealign\v!left }{\def\tabl_table_paralignment{\raggedleft}}
+\setvalue{\??tablealign\v!middle }{\def\tabl_table_paralignment{\raggedcenter}}
+\setvalue{\??tablealign\s!unknown}{\def\tabl_table_paralignment{\notragged}}
+
+\appendtoks
+ \doifelse{\directtablesparameter\c!distance}\v!none
+ {\tablerowfactor\zerocount}
+ {\tablerowfactor\plustwo }%
+\to \localtabledefinitions
+
+\def\dohandlebar % here ?
+ {\ifmmode
+ \expandafter\domathmodebar
+ \else\ifintable
+ \doubleexpandafter\domathmodebar
+ \else
+ \doubleexpandafter\dotextmodebar
+ \fi\fi}
+
+\appendtoks
+ \expandnamespaceparameter\??tablealign\directtablesparameter\c!align\s!unknown
+ \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246%
+ \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246%
+\to \everysetuptables
+
+\def\tabl_table_local_setups
+ {\directtablesparameter\c!commands\relax
+ \usebodyfontparameter\directtablesparameter
+ \d_tabl_table_line_thickness_unit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax
+ \edef\p_tabl_table_height{\directtablesparameter\c!height}%
+ \edef\p_tabl_table_depth{\directtablesparameter\c!depth}%
+ \ifx\p_tabl_table_height\v!strut
+ \let\tablestrutheightfactor\tablestrutheightfactor
+ \else
+ \let\tablestrutheightfactor\p_tabl_table_height
+ \fi
+ \ifx\p_tabl_table_depth\v!strut
+ \let\tablestrutdepthfactor\tablestrutdepthfactor
+ \else
+ \let\tablestrutdepthfactor\p_tabl_table_depth
+ \fi
+ \edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}%
+ \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}%
+ \d_tabl_table_strut_unit \dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont
+ \d_tabl_table_kern_unit .5em\relax
+ \s_tabl_table_inter_column_space_unit.5em plus 1fil minus .25em\relax
+ \d_tabl_table_column_width_unit \d_tabl_table_kern_unit
+ \d_tabl_table_kern_unit \d_tabl_table_kern_unit}
+
+%D As one can see, we didn't only add color, but also more control over spacing.
+%D
+%D \startbuffer[a]
+%D \starttable[|c|]
+%D \HL
+%D \VL \strut test \VL \FR
+%D \VL \strut test \VL \MR
+%D \VL \strut test \VL \MR
+%D \VL \strut test \VL \LR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \starttabulate[|c|]
+%D \HL
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D In the next example, the first table is defined as:
+%D
+%D \typebuffer[a]
+%D
+%D and the second one as:
+%D
+%D \typebuffer[b]
+%D
+%D The first table is typeset using the default height and depth factors .8 and .4.
+%D The second table has both factors set to \type {strut}, and the third table shows
+%D what happens when we set the values to zero. The rightmost table is typeset using
+%D the tabulate environment.
+%D
+%D \startcombination[4*1]
+%D {$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=.8 d=.4}}
+%D {\setuptables[height=strut,depth=strut]$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=d=\type{strut}}}
+%D {\setuptables[height=0,depth=0]$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=d=0}}
+%D {$\vcenter{\getbuffer[b]}$}
+%D {\hbox{tabulate}}
+%D \stopcombination
+
+\setuptables
+ [\c!HL=\v!medium,
+ \c!VL=\v!medium,
+ \c!NL=\v!small,
+ \c!frame=,
+ \c!align=\v!right,
+ \c!depth=.40, % \v!strut
+ \c!height=.80, % \v!strut
+ \c!textwidth=,
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!distance=\v!medium,
+ \c!bodyfont=,
+ \c!commands=,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!split=\v!auto]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.lua b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.lua
new file mode 100644
index 00000000000..13d899de647
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.lua
@@ -0,0 +1,52 @@
+if not modules then modules = { } end modules ['tabl-tbl'] = {
+ version = 1.001,
+ comment = "companion to tabl-tbl.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A couple of hacks ... easier to do in Lua than in regular TeX. More will
+-- follow.
+
+local tonumber = tonumber
+local gsub, rep, sub, find = string.gsub, string.rep, string.sub, string.find
+local P, C, Cc, Ct, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.match
+
+local context = context
+local commands = commands
+
+local texsetcount = tex.setcount
+
+local separator = P("|")
+local nested = lpeg.patterns.nested
+local pattern = Ct((separator * (C(nested) + Cc("")) * C((1-separator)^0))^0)
+
+local ctx_settabulatelastentry = context.settabulatelastentry
+local ctx_settabulateentry = context.settabulateentry
+
+local function presettabulate(preamble)
+ preamble = gsub(preamble,"~","d") -- let's get rid of ~ mess here
+ if find(preamble,"*",1,true) then
+ -- todo: lpeg but not now
+ preamble = gsub(preamble, "%*(%b{})(%b{})", function(n,p)
+ return rep(sub(p,2,-2),tonumber(sub(n,2,-2)) or 1)
+ end)
+ end
+ local t = lpegmatch(pattern,preamble)
+ local m = #t - 2
+ texsetcount("global","c_tabl_tabulate_nofcolumns", m/2)
+ texsetcount("global","c_tabl_tabulate_has_rule_spec_first", t[1] == "" and 0 or 1)
+ texsetcount("global","c_tabl_tabulate_has_rule_spec_last", t[m+1] == "" and 0 or 1)
+ for i=1,m,2 do
+ ctx_settabulateentry(t[i],t[i+1])
+ end
+ ctx_settabulatelastentry(t[m+1])
+end
+
+interfaces.implement {
+ name = "presettabulate",
+ actions = presettabulate,
+ arguments = "string",
+ scope = "private",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv
new file mode 100644
index 00000000000..c8d7d5aae6d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv
@@ -0,0 +1,2484 @@
+%D \module
+%D [ file=core-tbl,
+%D version=1998.11.03,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Text Flow Tabulation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Tabulation}
+
+\unprotect
+
+\registerctxluafile{tabl-tbl.lua}{1.001} % experiment
+
+%D I can probably reimplement this using a \LUATEX\ combination
+%D but it does not pay of in development time. If I need something
+%D else I will write it from scratch anyway. This module looks
+%D a bit complex which is a consequence of it dealing with paragraphs
+%D being split over pages and that there are several passes over the
+%D data set. We can probably do some cleanup (combine/split).
+%D
+%D Caching the preamble does not save much (compared to other
+%D bits and pieces of \CONTEXT). There are not that many ways to
+%D deal with preambles and this is just one of them. The keys are
+%D somewhat similar to those of the \TABLE\ package.
+
+% |p2|p3| 2:3 -> spanning (maybe)
+%
+% In-text tabbing environment
+%
+% \starttabulate[| separated template] % eg [|l|p|] or [|l|p|p|]
+% \NC ... \NC ... \NC\NR
+% \stoptabulate
+%
+% with: two pass auto width calculation when no p-width
+% specified, even with multiple p's, see examples.
+%
+% TaBlE compatible specifications:
+%
+% l align column/paragraph left
+% r align column/paragraph right
+% c align column/paragraph center
+% p p(dimen) of automatisch als alleen p
+% w column width
+% f font#1
+% A {alignmentoptions}
+% B bold
+% I italic
+% S slanted
+% T type
+% R roman
+% m math
+% M display math
+% h hook (inner level or par lines)
+% b before (may be command#1)
+% a after
+% i i<n> skip left of column
+% j i<n> skip right of column
+% k i<n> skip around column
+% d digits (~)
+%
+% C [LMRT] {color} % T is text color
+%
+% | {color,n}
+%
+% s setups
+%
+% g g{char} align at char
+% . align at .
+% , align at ,
+%
+% Still to be done
+%
+% N math numbers (best hook into existing digits mechanism)
+% n numbers (best hook into existing digits mechanism)
+% Q math numbers (best hook into existing digits mechanism)
+% q numbers (best hook into existing digits mechanism)
+% ~ \hskip.5em
+% | check
+%
+% nesting
+%
+% 10 evt auto stack; dan wel andere signal dan void nodig
+%
+% present but not yet 100% ok
+%
+% \TL [width,color] bottom hrule
+% \FL [width,color] first hrule
+% \ML [width,color] mid hrule (with auto split)
+% \LL [width,color] bottom hrule
+% \BL [width,color] last hrule
+%
+% \HL [width,color] top rule
+% \VL [width,color]
+%
+% \CC \CL \CM \CR color
+%
+% \EQ \RQ \HQ equal (raw, hook)
+% \NC \RC \HC normal (raw, hook)
+%
+% \NR checked break
+% \NB no break
+%
+% \HR : rule with lineheight
+%
+% \autotabulaterule : with lineheight, not first/last
+% \autotabulateline : spaced, not first/last
+% \tabulaterule : with lineheight
+% \tabulateline : spaced
+%
+% tricky: align scans ahead, over # and expands ones before
+% while doing
+%
+% new:
+%
+% \starttabulate[|cg{.}|cg{,}|cg{,}|]
+% \NC period \NC comma \NC comma \NC\NR
+% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
+% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \stoptabulate
+%
+% \starttabulate[|c.|c,|c,|]
+% \NC period \NC comma \NC comma \NC\NR
+% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
+% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \stoptabulate
+
+% nice demo (for BG)
+%
+% \starttabulate[|r|b{$\star$}|ra{\percent}|b{=}|r|]
+% \NC 500 \NC \NC 60 \NC \NC 300 \NC \NR
+% \NC 500 \NC \NC 55 \NC \NC 275 \NC \NR
+% \NC 500 \NC \NC 50 \NC \NC 250 \NC \NR
+% \NC 500 \NC \NC 45 \NC \NC 225 \NC \NR
+% \NC 500 \NC \NC 40 \NC \NC 200 \NC \NR
+% \NC 500 \NC \NC 35 \NC \NC 175 \NC \NR
+% \NC 500 \NC \NC 30 \NC \NC 150 \NC \NR
+% \NC 500 \NC \NC 25 \NC \NC 125 \NC \NR
+% \NC 500 \NC \NC 20 \NC \NC 100 \NC \NR
+% \stoptabulate
+
+\newtoks \t_tabl_tabulate_preamble
+\newtoks \t_tabl_tabulate_before
+\newtoks \t_tabl_tabulate_after
+\newtoks \t_tabl_tabulate_bmath
+\newtoks \t_tabl_tabulate_emath
+\newtoks \t_tabl_tabulate_font
+\newtoks \t_tabl_tabulate_settings
+\newtoks \t_tabl_tabulate_dummy
+\newtoks \t_tabl_tabulate_every_row
+\newtoks \t_tabl_tabulate_every_after_row
+
+\newtoks \t_tabl_tabulate_initializers_first
+\newtoks \t_tabl_tabulate_initializers_second
+
+\newcount \c_tabl_tabulate_nofauto
+\newcount \c_tabl_tabulate_columns
+\newcount \c_tabl_tabulate_column
+\newcount \c_tabl_tabulate_plines_min
+\newcount \c_tabl_tabulate_plines_max
+\newcount \c_tabl_tabulate_max_colorcolumn
+\newcount \c_tabl_tabulate_repeathead
+\newcount \c_tabl_tabulate_noflines
+\newcount \c_tabl_tabulate_totalnoflines
+\newcount \c_tabl_tabulate_minusnoflines
+\newcount \c_tabl_tabulate_align
+
+\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser
+\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count)
+\newcount \c_tabl_tabulate_has_rule_spec_last % set at the lua end by parser (for the moment a count)
+
+\newconditional \c_tabl_tabulate_nopbreak
+\newconditional \c_tabl_tabulate_firstflushed
+\newconditional \c_tabl_tabulate_equal
+\newconditional \c_tabl_tabulate_split \settrue\c_tabl_tabulate_split
+\newconditional \c_tabl_tabulate_automode
+\newconditional \c_tabl_tabulate_handlepbreak \settrue\c_tabl_tabulate_handlepbreak
+\newconditional \c_tabl_tabulate_autorulespacing \settrue\c_tabl_tabulate_autorulespacing
+\newconditional \c_tabl_tabulate_someamble
+\newconditional \c_tabl_tabulate_tolerant_break
+\newconditional \c_tabl_tabulate_splitoff_whitespace
+\newconditional \c_tabl_tabulate_pwidth_set
+\newconditional \c_tabl_tabulate_reshape
+
+\newdimen \d_tabl_tabulate_width_p
+\newdimen \d_tabl_tabulate_width_w
+\newdimen \d_tabl_tabulate_width
+\newdimen \d_tabl_tabulate_unit
+\newdimen \d_tabl_tabulate_height_p_max
+\newdimen \d_tabl_tabulate_vrulethickness_default
+\newdimen \d_tabl_tabulate_hrulethickness_default
+\newdimen \d_tabl_tabulate_vrulethickness
+\newdimen \d_tabl_tabulate_hrulethickness % not used
+\newdimen \d_tabl_tabulate_vrulethickness_local
+\newdimen \d_tabl_tabulate_hrulethickness_local
+\newdimen \d_tabl_tabulate_indent
+\newdimen \d_tabl_tabulate_splitoff_betweenskip
+\newdimen \d_tabl_tabulate_margin
+
+\newskip \s_tabl_tabulate_pre
+\newskip \s_tabl_tabulate_post
+\newskip \s_tabl_tabulate_first
+\newskip \s_tabl_tabulate_last
+\newskip \s_tabl_tabulate_separator
+
+\newbox \b_tabl_tabulate
+
+\newconstant \c_tabl_tabulate_pass
+\newconstant \c_tabl_tabulate_type
+\newconstant \c_tabl_tabulate_splitlinemode \c_tabl_tabulate_splitlinemode\plusone
+\newconstant \c_tabl_tabulate_colorspan
+\newconstant \c_tabl_tabulate_localcolorspan
+\newconstant \c_tabl_tabulate_modus
+
+\let\tabulatesplitlinemode\c_tabl_tabulate_splitlinemode % temp hack, we need an interface
+
+\let \m_tabl_tabulate_separator_factor \empty % fraction
+
+\newif \iftracetabulate % will become a tracker
+\newtoks \everytabulatepar % where used ?
+\newtoks \everytabulate % public ?
+
+\unexpanded\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
+\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
+
+\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
+
+\installcorenamespace{tabulatebox}
+\installcorenamespace{tabulatesetup}
+\installcorenamespace{tabulatehook}
+\installcorenamespace{tabulatesplit}
+\installcorenamespace{tabulateseparator}
+\installcorenamespace{tabulatecolor}
+\installcorenamespace{tabulateheader}
+\installcorenamespace{tabulatealigning}
+\installcorenamespace{tabulatepreamble}
+
+\installcorenamespace{tabulatehead}
+\installcorenamespace{tabulatefoot}
+\installcorenamespace{tabulatenext}
+
+\def\b_tabl_tabulate_current#1%
+ {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym
+
+\def\tabl_tabulate_initialize_boxes#1%
+ {\scratchcounter#1\relax
+ \tabl_tabulate_initialize_boxes_step}
+
+\def\tabl_tabulate_initialize_boxes_step
+ {\ifnum\scratchcounter>\zerocount
+ \tabl_tabulate_initialize_box\scratchcounter
+ \advance\scratchcounter\minusone
+ \expandafter\tabl_tabulate_initialize_boxes_step
+ \fi}
+
+% \def\tabl_tabulate_initialize_box#1% also used elsewhere
+% {\ifcsname\??tabulatebox\number#1\endcsname
+% \tabl_tabulate_initialize_box_yes#1%
+% \else
+% \tabl_tabulate_initialize_box_nop#1%
+% \fi}
+\def\tabl_tabulate_initialize_box#1% also used elsewhere
+ {\ifcsname\??tabulatebox\number#1\endcsname
+ \tabl_tabulate_initialize_box_yes
+ \else
+ \tabl_tabulate_initialize_box_nop#1%
+ \fi}
+
+%def\tabl_tabulate_initialize_box_yes#1{\global \setbox\csname\??tabulatebox\number#1\endcsname\emptybox}
+\def\tabl_tabulate_initialize_box_yes {\global \setbox\lastnamedcs\emptybox}
+\def\tabl_tabulate_initialize_box_nop#1{\expandafter\newbox\csname\??tabulatebox\number#1\endcsname}
+
+\tabl_tabulate_initialize_boxes{16} % not really needed
+
+\let\initializetablebox \tabl_tabulate_initialize_box % used elsewhere, will change
+\let\initializetableboxes\tabl_tabulate_initialize_boxes % used elsewhere, will change
+\let\tablebox \b_tabl_tabulate_current
+
+% 0 = NC column next EQ equal column
+% 1 = RC column raw RQ equal column raw
+% 2 = HC column hook HQ equal column hook
+
+% handy helper
+
+\def\tabulatenoalign % public ?
+ {\noalign
+ \bgroup
+ \let\noalign\relax
+ \let\tabulatenoalign\relax
+ \let\next=}
+
+\def\starttabulatenoalign % public ?
+ {\tabulatenoalign\bgroup}
+
+\let\stoptabulatenoalign\egroup
+
+% [|lg{.}|] => \NG 12.34 \NC
+
+\def\tabl_tabulate_nobreak_inject_tracer
+ {\red % maybe use the fast color switcher here
+ \hrule\s!height.5\linewidth\s!depth.5\linewidth
+ \par
+ \kern-\linewidth
+ \tabl_tabulate_break_no}
+
+\def\tabl_tabulate_nobreak_inject_indeed
+ {\tabl_tabulate_break_no
+ \iftracetabulate
+ \tabl_tabulate_nobreak_inject_tracer
+ \fi}
+
+\def\tabl_tabulate_nobreak_inject
+ {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}}
+
+\unexpanded\def\tabl_tabulate_hook_check
+ {\ifnum\c_tabl_tabulate_type<\plustwo
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
+ \else
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \fi}
+
+\unexpanded\def\tabl_tabulate_setups_check
+ {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname}
+
+\unexpanded\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook}
+\unexpanded\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi}
+
+\unexpanded\def\tabl_tabulate_shaped_par_begin
+ {\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup}
+
+\def\tabl_tabulate_shaped_par_finish
+ {\clf_doreshapeframedbox\nextbox\relax
+ \ifvmode\unvbox\else\box\fi\nextbox}
+
+\let\tabl_tabulate_shaped_par_end\egroup
+
+\ifdefined\dotagtabulatecell \else \let\dotagtabulatecell \relax \fi
+\ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi
+
+\unexpanded\def\tabl_tabulate_check_local_color_first#1#2%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_color_second#1#2%
+ {\relax
+ \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
+ \fi
+ \ifcase\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_colorspan#2\relax
+ \else
+ \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_localcolorspan\zerocount
+ \fi}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1%
+ {\relax
+ \ifcase\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness#1\relax
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness_local\zeropoint
+ \fi}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1%
+ {\relax
+ \ifx\m_tabl_tabulate_vrule_color_local\empty
+ \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
+ \fi}
+
+\let\tabl_tabulate_check_local_color \gobbletwoarguments
+\let\tabl_tabulate_check_local_vrule_color\gobbleoneargument
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_first
+ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_second
+ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_second
+\to \t_tabl_tabulate_initializers_second
+
+% \unexpanded % we can expand this one
+\def\tabl_tabulate_inject_pre_skip#1%
+ {\ifdim#1>\zeropoint
+ \kern#1\relax % was \hskip
+ \else\ifnum\c_tabl_tabulate_column=\zerocount
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_first\else
+ \kern\s_tabl_tabulate_first\relax % was \hskip
+ \fi
+ \fi
+ \fi\fi}
+
+% \unexpanded % we can expand this one
+\def\tabl_tabulate_inject_post_skip#1%
+ {\ifdim#1>\zeropoint
+ \kern#1\relax % was \hskip
+ \else\ifnum\c_tabl_tabulate_columns=\c_tabl_tabulate_nofcolumns
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_last\else
+ \kern\s_tabl_tabulate_last\relax % was \hskip
+ \fi
+ \fi
+ \fi\fi}
+
+\let\tabl_tabulate_hook_b\donothing
+\let\tabl_tabulate_hook_e\donothing
+
+\let\tabl_tabulate_hook_g\donothing
+
+\def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
+ {\etoksapp\t_tabl_tabulate_preamble{%
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
+ \tabl_tabulate_color_side_right
+ \aligntab
+ \tabl_tabulate_column_vrule_inject
+ \tabl_tabulate_color_side_left
+ \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus
+ \alignmark\alignmark
+ \aligntab
+ \tabl_tabulate_color_side_both
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
+ \tabl_tabulate_hook_g
+ \tabl_tabulate_setups_check % unexpandable
+ \tabl_tabulate_hook_check % unexpandable
+ \ifzeropt\d_tabl_tabulate_width
+ \ifcase\c_tabl_tabulate_modus\else
+ \settrue\c_tabl_tabulate_automode
+ \fi
+ \else
+ \ifcase\c_tabl_tabulate_modus
+ \hbox to
+ \else
+ \hsize
+ \fi
+ \the\d_tabl_tabulate_width
+ \fi
+ \bgroup
+ \tabl_tabulate_bbskip
+ \bgroup % we cannot combine the if because a cell may have only one ##
+ \tabl_tabulate_hook_b
+ \c_tabl_tabulate_align\constantnumber\c_tabl_tabulate_align % needed in tag passing
+ \ifx\m_tabl_tabulate_alignment\empty \else
+ \spac_align_use_now{\m_tabl_tabulate_alignment}%
+ \fi
+ \noexpand\dostarttagged\noexpand\t!tabulatecell\noexpand\empty
+ \noexpand\dotagtabulatecell
+ \noexpand#1%
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_begin
+ \fi
+ \dotagtabulatesignal % empty cells .. todo (can be removed as soon as build)
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_bmath % maybe later? can interfere with char 0
+ \the\t_tabl_tabulate_font
+ \the\t_tabl_tabulate_settings
+ \the\t_tabl_tabulate_before
+ \ifx\m_tabl_tabulate_text_color\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\dofastcoloractivation
+ \fi\m_tabl_tabulate_text_color
+ \noexpand\fi
+ % grouping needs to be outside macros (or expandable), nice test
+ % example \NC \string \aligntab \NC which will fail otherwise (mk)
+ \bgroup
+ \tabl_tabulate_entry_before
+ \alignmark\alignmark
+ \tabl_tabulate_entry_after
+ \egroup
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_after
+ \the\t_tabl_tabulate_emath
+ \noexpand\fi
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_end
+ \fi
+ \noexpand#2%
+ \tabl_tabulate_hook_e
+ \egroup
+ \egroup
+ \aligntab
+ \noexpand\dostoptagged
+ \tabl_tabulate_inject_post_skip{\the\dimexpr\s_tabl_tabulate_post}% get rid of plus
+ \alignmark\alignmark
+ }%
+ \toksapp\t_tabl_tabulate_dummy{\NC}%
+ \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
+ \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
+ \s_tabl_tabulate_post\s_tabl_tabulate_pre
+ \else
+ \s_tabl_tabulate_post\zeropoint
+ \fi
+ %\let\gettabulateexit\dogettabulateexit % still needed ?
+ \d_tabl_tabulate_width\zeropoint}
+
+\unexpanded\def\installtabulatepreambleoption#1#2%
+ {\setvalue{\??tabulatepreamble\string#1}{#2}}%
+
+\installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount
+ \tabl_tabulate_set_preamble} % internal
+\installtabulatepreambleoption{l}{\c_tabl_tabulate_align\plusone
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{r}{\c_tabl_tabulate_align\plustwo
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{c}{\c_tabl_tabulate_align\plusthree
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{p}{\tabl_tabulate_set_paragraph}
+\installtabulatepreambleoption{s}{\tabl_tabulate_set_setups}
+\installtabulatepreambleoption{w}{\tabl_tabulate_set_width}
+\installtabulatepreambleoption{f}{\tabl_tabulate_set_font}
+\installtabulatepreambleoption{B}{\t_tabl_tabulate_font{\bf}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{I}{\t_tabl_tabulate_font{\it}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{S}{\t_tabl_tabulate_font{\sl}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{T}{\t_tabl_tabulate_font{\tt}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{R}{\t_tabl_tabulate_font{\rm}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{m}{\t_tabl_tabulate_bmath{\normalstartimath}%
+ \t_tabl_tabulate_emath{\normalstopimath}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{\normalstartimath\displaystyle}%
+ \t_tabl_tabulate_emath{\normalstopimath}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{h}{\tabl_tabulate_set_hook}
+\installtabulatepreambleoption{b}{\tabl_tabulate_set_before}
+\installtabulatepreambleoption{a}{\tabl_tabulate_set_after}
+\installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip}
+\installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip}
+\installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip}
+\installtabulatepreambleoption{e}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\global\settrue\c_tabl_tabulate_equal}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{g}{\tabl_tabulate_set_align}
+\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.}
+\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,}
+\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span}
+\installtabulatepreambleoption{d}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\fixedspaces}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment}
+
+% We no longer deal with '~' here but map it onto 'd' instead. Of course
+% we could prefix a key with \type {\meaning} instead, which works ok (and
+% is needed in order to pseudo expand \type {\next}, but is ugly at the
+% same time. The 'd' stands for digitspace.
+%
+% \installtabulatepreambleoption{~}{...} % see 'd'
+%
+% Also, as there is always a key, we no longer do some after assigment or
+% future let but just pick up the key.
+
+% \installtabulatepreambleoption \s!unknown %
+% {\writestatus{tabulate}{unknown preamble key [\meaning\next]}%
+% \tabl_tabulate_set_preamble}
+%
+% \def\tabl_tabulate_set_preamble
+% {\afterassignment\dosettabulatepreamble\let\next=}
+%
+% \def\dosettabulatepreamble
+% {\ifx\next\relax \else
+% \csname\??tabulatepreamble
+% \ifcsname\??tabulatepreamble\next\endcsname\next\else\s!unknown\fi
+% \expandafter\endcsname
+% \fi}
+
+\installtabulatepreambleoption\relax
+ {} % finished
+
+\def\tabl_tabulate_set_preamble#1%
+ {\ifcsname\??tabulatepreamble\string#1\endcsname
+ %\expandafter\tabl_tabulate_set_preamble_yes
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\tabl_tabulate_set_preamble_nop
+ \fi{#1}}
+
+\def\tabl_tabulate_set_preamble_yes#1%
+ {\csname\??tabulatepreamble\string#1\expandafter\endcsname}
+
+\def\tabl_tabulate_set_preamble_nop#1%
+ {\writestatus{tabulate}{unknown preamble key: #1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_preskip#1%
+ {\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 }
+ {\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 }
+ {\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%
+ {\setvalue{\??tabulatesetup\the\c_tabl_tabulate_columns}{\setups[#1]}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_hook#1%
+ {\setvalue{\??tabulatehook\the\c_tabl_tabulate_columns}{#1}%
+ \tabl_tabulate_set_preamble}
+
+% begin of character align plugin
+
+\newconditional\c_tabl_auto_align_mode % reset later
+
+\def\tabl_tabulate_hook_g % partly expanded
+ {\ifconditional\c_tabl_auto_align_mode
+ \signalcharacteralign\c_tabl_tabulate_column{\c_tabl_tabulate_noflines+\plusone}%
+ \typo_charalign_adapt_font
+ \fi}
+
+\def\tabl_tabulate_set_align#1%
+ {\global\settrue\c_tabl_auto_align_mode
+ \setcharacteralign\c_tabl_tabulate_columns{#1}%
+ \tabl_tabulate_set_preamble}
+
+% end of character align plugin
+
+\def\tabl_tabulate_set_before#1%
+ {\t_tabl_tabulate_before{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_after#1%
+ {\t_tabl_tabulate_after{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_font#1%
+ {\t_tabl_tabulate_font{#1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_pickup_width
+ {\doifelsenextparenthesis\tabl_tabulate_set_width_indeed\tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_width
+ {\setfalse\c_tabl_tabulate_pwidth_set
+ \c_tabl_tabulate_modus\zerocount
+ \tabl_tabulate_pickup_width}
+
+\def\tabl_tabulate_set_alignment#1%
+ {\edef\m_tabl_tabulate_alignment{#1}%
+ \spac_align_use_later\m_tabl_tabulate_alignment
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_paragraph
+ {\doifelsenextparenthesis
+ {\c_tabl_tabulate_modus\plusone
+ \settrue\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_pickup_width}
+ {\c_tabl_tabulate_modus\plustwo
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_set_preamble}}
+
+% \startbuffer
+% \toplinebox{\framed[width=3cm,height=2cm]{tufte}}
+% \stopbuffer
+% \starttabulate[|p(fixed)|p|]
+% \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
+% \stoptabulate
+% \starttabulate[|p(fit)|p|]
+% \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
+% \stoptabulate
+
+\def\tabl_tabulate_set_width_indeed(#1)%
+ {\processallactionsinset % can be made faster
+ [#1]%
+ [ \v!fit=>\c_tabl_tabulate_modus\plusthree,
+ \v!fixed=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_nopbreak,
+ \v!auto=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_reshape,
+ \s!unknown=>\d_tabl_tabulate_width#1\relax]%
+ \ifconditional\c_tabl_tabulate_pwidth_set
+ \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
+ \fi
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi}
+\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi}
+\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi}
+\def\tabl_tabulate_set_notragged {\ifnum\c_tabl_tabulate_type=\plusone \else\notragged \fi}
+\def\tabl_tabulate_set_hss {\ifnum\c_tabl_tabulate_type=\plusone \else\hss \fi} % never change this to a fill
+
+\def\tabl_tabulate_bskip_raggedright {\tabl_tabulate_bskip\tabl_tabulate_set_raggedright }
+\def\tabl_tabulate_bskip_raggedleft {\tabl_tabulate_bskip\tabl_tabulate_set_raggedleft }
+\def\tabl_tabulate_bskip_raggedcenter{\tabl_tabulate_bskip\tabl_tabulate_set_raggedcenter}
+
+\def\tabl_tabulate_set_width_normal
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\empty \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\tabl_tabulate_set_hss \fi}
+
+\def\tabl_tabulate_set_width_fixed
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_auto
+ {\global\advance\c_tabl_tabulate_nofauto\plusone
+ \ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_simple
+ {\tabl_tabulate_set_preamble_step\tabl_tabulate_xbskip\tabl_tabulate_xeskip}
+
+% \def\tabl_tabulate_set_color_span#1#2%
+% {\xdef\m_tabl_tabulate_color{#2}%
+% \global\c_tabl_tabulate_colorspan\if#1L\plusone\else\if#1M\plustwo\else\if#1R\plusthree\else\zerocount\fi\fi\fi\relax
+% \tabl_tabulate_set_preamble}
+
+\installcorenamespace{tabulatecolorspec}
+
+\setvalue{\??tabulatecolorspec C}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\zerocount}
+\setvalue{\??tabulatecolorspec L}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plusone }
+\setvalue{\??tabulatecolorspec M}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plustwo }
+\setvalue{\??tabulatecolorspec R}#1{\xdef\m_tabl_tabulate_color {#1}\global\c_tabl_tabulate_colorspan\plusthree}
+\setvalue{\??tabulatecolorspec T}#1{\xdef\m_tabl_tabulate_text_color{#1}}
+
+\def\tabl_tabulate_set_color_span#1#2%
+ {\csname\??tabulatecolorspec#1\endcsname{#2}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_vrule_command#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color{#1}}}
+
+\def\tabl_tabulate_set_entry#1#2% rulespec template
+ {\c_tabl_tabulate_align\v_tabl_tabulate_align
+ \c_tabl_tabulate_modus\zerocount
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \setfalse\c_tabl_tabulate_reshape
+ \t_tabl_tabulate_before\emptytoks
+ \t_tabl_tabulate_after\emptytoks
+ \t_tabl_tabulate_bmath\emptytoks
+ \t_tabl_tabulate_emath\emptytoks
+ \t_tabl_tabulate_font\emptytoks
+ \t_tabl_tabulate_settings\emptytoks
+ \global\let\m_tabl_tabulate_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
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\setfalse\c_tabl_auto_align_mode
+ \global\advance\c_tabl_tabulate_columns\plusone
+ \expandafter\let\csname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ?
+ \edef\currenttabulationtrulespec{#1}%
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+ \fi
+ \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
+ \ifcase\c_tabl_tabulate_modus\relax
+ \tabl_tabulate_set_width_normal
+ \or % fixed width
+ \tabl_tabulate_set_width_fixed
+ \or % auto width
+ \tabl_tabulate_set_width_auto
+ \or % simple
+ \tabl_tabulate_set_width_simple
+ \fi}
+
+\def\tabl_tabulate_set_last_entry#1% rulespec
+ {\global\let\m_tabl_tabulate_color\empty
+ \global\let\m_tabl_tabulate_vrule_color\empty
+ \edef\currenttabulationtrulespec{#1}%
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
+ \else
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+ \fi
+ \etoksapp\t_tabl_tabulate_preamble{%
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_column_vrule_inject}}
+
+\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end
+\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
+
+\def\tabl_tabulate_normalize_splitline
+ {\ifcase\c_tabl_tabulate_splitlinemode
+ % nothing
+ \or
+ \ht\b_tabl_tabulate\strutht
+ \dp\b_tabl_tabulate\strutdp
+ \or
+ \ifdim\ht\b_tabl_tabulate<\strutht
+ \ht\b_tabl_tabulate\strutht
+ \fi
+ \ifdim\dp\b_tabl_tabulate<\strutdp
+ \dp\b_tabl_tabulate\strutdp
+ \fi
+ \fi}
+
+\def\tabl_tabulate_whitespace
+ {\ifdim\d_tabl_tabulate_splitoff_betweenskip>\zeropoint
+ \vskip\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\zeropoint
+ \fi}
+
+\def\tabl_tabulate_check_whitespace
+ {\setbox\scratchbox\vpack
+ {\splitdiscards
+ \unskip
+ \ifdim\lastskip>\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\lastskip
+ \fi}}
+
+\installtexdirective
+ {tabulate.linenumbers}
+ {\def\tabl_tabulate_check_linenumbers{\page_postprocessors_linenumbers_deepbox\b_tabl_tabulate}}
+ {\let\tabl_tabulate_check_linenumbers\relax}
+
+\let\tabl_tabulate_check_linenumbers\relax
+
+\def\tabl_tabulate_splitoff_box
+ {\dontcomplain
+ \global\setbox\b_tabl_tabulate\vsplit\b_tabl_tabulate_current\c_tabl_tabulate_column to \lineheight % % % global ? % % %
+ \setbox\b_tabl_tabulate\vbox
+ {\unvbox\b_tabl_tabulate}%
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_check_whitespace
+ \fi
+ \tabl_tabulate_color_repeat % needs to end up in a cell
+ \setbox\b_tabl_tabulate\hpack to \wd\b_tabl_tabulate
+ {\hss\tabl_tabulate_hook_yes{\box\b_tabl_tabulate}\hss}%
+ \tabl_tabulate_normalize_splitline
+ \tabl_tabulate_check_linenumbers
+ \box\b_tabl_tabulate}
+
+\unexpanded\def\tabl_tabulate_hook_nop
+ {}
+
+\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
+
+\def\tabl_tabulate_hook_yes{\csname\??tabulatehook\the\c_tabl_tabulate_column\endcsname}
+
+\def\tabl_tabulate_pheight_reset
+ {\global\c_tabl_tabulate_plines_min\plusone
+ \ifdim\d_tabl_tabulate_height_p_max>\zeropoint
+ \getnoflines\d_tabl_tabulate_height_p_max
+ \global\c_tabl_tabulate_plines_max\noflines
+ \else
+ \global\c_tabl_tabulate_plines_max\zerocount
+ \fi
+ \global\d_tabl_tabulate_height_p_max\zeropoint}
+
+\def\tabl_tabulate_pheight_set
+ {\scratchdimen\ht\b_tabl_tabulate_current\c_tabl_tabulate_column\relax
+ \ifdim\scratchdimen>\d_tabl_tabulate_height_p_max
+ \global\d_tabl_tabulate_height_p_max\scratchdimen
+ \fi}
+
+\def\tabl_tabulate_pbreak_inject
+ {\ifconditional\c_tabl_tabulate_handlepbreak
+ \ifconditional\c_tabl_tabulate_nopbreak
+ \tabl_tabulate_nobreak_inject
+ \else\ifnum\c_tabl_tabulate_plines_max>\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\plusone
+ \tabl_tabulate_nobreak_inject
+ \fi
+ \global\advance\c_tabl_tabulate_plines_min\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\c_tabl_tabulate_plines_max\relax
+ \tabl_tabulate_nobreak_inject
+ \fi
+ \fi \fi
+ \fi}
+
+\def\tabl_tabulate_pbreak_check
+ {\starttabulatenoalign
+ \tabl_tabulate_pbreak_inject
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_whitespace
+ \fi
+ \stoptabulatenoalign}
+
+%D \startbuffer
+%D \starttabulate[|c|p|p|]
+%D \NC \bf Alpha \NC \bf Beta \NC \bf Gamma \NC\NR
+%D \NC 1 \NC right indeed \NC definitely wrong \NC\NR
+%D \NC 2 \NC \thinrules[n=3] \NC \thinrules[n=3] \NC\NR
+%D \NC 3 \NC oh yes \NC simply no \NC\NR
+%D \NC 4 \NC very true \NC as false as can be \NC\NR
+%D \NC 5 \NC \thinrules[n=5] \NC \thinrules[n=5] \NC\NR
+%D \NC 6 \NC \thinrules[n=3] \NC \thinrules[n=4] \NC\NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer {\tracetabulatetrue\getbuffer}
+%D
+%D \startbuffer
+%D \starttabulate[|c|p|p|]
+%D \NC \bf Alpha \NC \bf Beta \NC \bf Gamma \NC\NR
+%D \NC 1 \NC right indeed \NC definitely wrong \NC\NR
+%D \NC 2 \NC oh yes \NC simply no \NC\NR
+%D \NC 3 \NC very true \NC as false as can be \NC\NR
+%D \NC 4 \NC the whole truth \NC but the truth \NC\NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer {\tracetabulatetrue\getbuffer}
+
+%D As we want to be compatible we use an indirect way to
+%D implement the definers. The next examples demonstrate
+%D the difference:
+%D
+%D \starttyping
+%D \definetabulate[test][|l|c|r|]
+%D \definetabulate[test][two][|r|c|l|]
+%D
+%D \definetabulation[more][format={|l|c|r|}]
+%D \definetabulation[more:two][format={|r|c|l|}]
+%D
+%D \starttest
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D
+%D \starttest[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D \startmore
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D
+%D \startmore[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D \stoptyping
+
+\installcorenamespace {tabulation}
+
+\installcommandhandler \??tabulation {tabulation} \??tabulation
+
+\setuptabulation
+ [\c!unit=1em,
+ EQ={:},
+ \c!format={|l|p|},
+ \c!frame=\v!off,
+ %\c!bodyfont=,
+ \c!rule=\v!normal,
+ %\c!rulecolor=,
+ \c!rulethickness=\linewidth,
+ %\c!inner=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance={\v!depth,\v!medium},
+ \c!align=\v!normal,
+ \c!margin=\!!zeropoint,
+ \c!split=\v!auto,
+ \c!header=\v!yes,
+ %\c!title=,
+ \c!indenting=\v!no]
+
+\unexpanded\def\definetabulate
+ {\dotripleempty\tabl_tabulate_define}
+
+\def\tabl_tabulate_define[#1][#2][#3]%
+ {\ifthirdargument
+ % [tag] [sub] [template]
+ \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else
+ \definetabulation[#1][\c!format={#3},\s!check=]%
+ \fi
+ \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]%
+ \else\ifsecondargument
+ % [tag] [template]
+ \definetabulation[#1][\c!format={#2},\s!check=]%
+ \else
+ % [tag]
+ \definetabulation[#1][\c!format={|l|p|},\s!check=]%
+ \fi\fi}
+
+\unexpanded\def\setuptabulate
+ {\dotripleempty\tabl_tabulate_setup}
+
+\def\tabl_tabulate_setup[#1][#2][#3]%
+ {\ifthirdargument
+ % [tag] [sub] [settings]
+ \setuptabulation[#1:#2][#3]%
+ \else\ifsecondargument
+ % [tag] [settings]
+ \setuptabulation[#1][#2]%
+ \else
+ % [tag]
+ \setuptabulation[#1]%
+ \fi\fi}
+
+\appendtoks
+ \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}%
+ \letvalue{\??tabulatehead\currenttabulation}\empty
+ \letvalue{\??tabulatefoot\currenttabulation}\empty
+\to \everydefinetabulation
+
+\let\tabulateparameter\tabulationparameter % will stay for a while
+\def\currenttabulate {\currenttabulation} % will stay for a while
+
+% Here begins the implementation.
+
+\let\tabl_tabulate_insert_head\empty
+\let\tabl_tabulate_insert_body\empty
+\let\tabl_tabulate_insert_foot\empty
+
+\def\tabl_tabulate_insert_head_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \csname\??tabulatehead\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_insert_foot_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \csname\??tabulatefoot\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
+ {\ifcsname\??tabulatehead\currenttabulation\endcsname
+ %\expandafter\ifx\csname\??tabulatehead\currenttabulation\endcsname\empty
+ \expandafter\ifx\lastnamedcs\empty
+ \let\tabl_tabulate_insert_head\empty
+ \else
+ \let\tabl_tabulate_insert_head\tabl_tabulate_insert_head_content
+ \fi
+ \else
+ \let\tabl_tabulate_insert_head\empty
+ \fi
+ \ifcsname\??tabulatefoot\currenttabulation\endcsname
+ \expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty
+ %\expandafter\ifx\lastnamedcs\empty
+ \let\tabl_tabulate_insert_foot\empty
+ \else
+ \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_head_content
+ \fi
+ \else
+ \let\tabl_tabulate_insert_foot\empty
+ \fi}
+
+\def\tabl_tabulate_insert_content
+ {\tabl_tabulate_insert_head
+ \ifcase\c_tabl_tabulate_repeathead \else
+ \tabulatenoalign{\penalty\zerocount}% added 7/5/2014 WS mail
+ \fi
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_insert_foot
+ \tabl_tabulate_remove_funny_line}
+
+\def\tabl_tabulate_remove_funny_line
+ {\ifhmode
+ \strut\crcr
+ \tabulatenoalign{\kern-\lineheight}%
+ \fi}
+
+% todo: make footer synonym to tail
+
+\setuvalue{\e!start\v!tabulatehead}{\doifelsenextoptionalcs\tabl_tabulate_start_head_yes\tabl_tabulate_start_head_nop}
+\setuvalue{\e!start\v!tabulatetail}{\doifelsenextoptionalcs\tabl_tabulate_start_foot_yes\tabl_tabulate_start_foot_nop}
+
+\let\m_tabl_tabulate_data\empty
+
+\def\tabl_tabulate_start_head_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatehead}\m_tabl_tabulate_data{\letvalue{\??tabulatehead#1}\m_tabl_tabulate_data}}
+
+\def\tabl_tabulate_start_foot_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatetail}\m_tabl_tabulate_data{\letvalue{\??tabulatefoot#1}\m_tabl_tabulate_data}}
+
+\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[\v!tabulate]}
+\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[\v!tabulate]}
+
+% \def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[]}
+% \def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[]}
+
+% \unexpanded\def\tabl_start_defined[#1]%
+% {\bgroup
+% \edef\currenttabulationparent{#1}%
+% \let\currenttabulation\currenttabulationparent
+% \dodoubleargument\tabl_start_defined_indeed}
+
+\unexpanded\def\tabl_start_defined[#1]%
+ {\bgroup
+ \edef\currenttabulationparent{#1}%
+ \let\currenttabulation\currenttabulationparent
+ \edef\p_format{\tabulationparameter\c!format}%
+ \ifx\p_format\v!none
+ % this is special case: we need to define the generic english
+ % \starttabulate in other interfaces as well
+ \expandafter\dodoubleempty \expandafter\tabl_start_regular
+ \else
+ \expandafter\dodoubleargument\expandafter\tabl_start_defined_indeed
+ \fi}
+
+\def\tabl_start_defined_indeed
+ {\iffirstargument
+ \ifsecondargument
+ \doubleexpandafter\tabl_start_defined_two
+ \else
+ \doubleexpandafter\tabl_start_defined_one
+ \fi
+ \else
+ \singleexpandafter\tabl_start_defined_zero
+ \fi}
+
+\def\tabl_start_defined_one[#1][#2]%
+ {\doifelseassignment{#1}
+ {\setuptabulation[\currenttabulation][#1]}%
+ {\edef\currenttabulation{\currenttabulation:#1}}%
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_defined_two[#1][#2]%
+ {\edef\currenttabulation{\currenttabulation:#1}%
+ \setuptabulation[\currenttabulation][#2]%
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_defined_zero[#1][#2]%
+ {\tabl_tabulate_start_building}
+
+% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
+
+\unexpanded\setuvalue{\e!start\v!tabulate}%
+ {\bgroup % whole thing
+ \let\currenttabulationparent\empty
+ \dodoubleempty\tabl_start_regular}
+
+\def\tabl_start_regular
+ {\let\currenttabulation\currenttabulationparent
+ \ifsecondargument
+ \expandafter\tabl_start_regular_two
+ \else
+ \expandafter\tabl_start_regular_one
+ \fi}
+
+\def\tabl_start_regular_one[#1][#2]%
+ {\doifelseassignment{#1}
+ {\setupcurrenttabulation[\c!format={|l|p|},#1]}
+ {\def\p_format{#1}%
+ \ifx\p_format\empty
+ \def\p_format{|l|p|}%
+ \fi
+ \lettabulationparameter\c!format\p_format}%
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_regular_two[#1][#2]%
+ {\def\p_format{#1}%
+ \ifx\p_format\empty
+ \def\p_format{|l|p|}%
+ \fi
+ \lettabulationparameter\c!format\p_format
+ \setupcurrenttabulation[#2]%
+ \tabl_tabulate_start_building}
+
+\letvalue{\e!stop\v!tabulate }\relax
+\letvalue{\e!stop\v!tabulatehead}\relax
+\letvalue{\e!stop\v!tabulatetail}\relax
+
+\unexpanded\def\tabl_tabulate_start_ignore
+ {\em Nested tabulate is not (yet) supported.\relax
+ \expandafter\gobbleuntil\csname\e!stop\v!tabulate\endcsname}
+
+\appendtoks
+ \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
+\to \everytabulate
+
+\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!repeat}{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!no }{\setfalse\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!auto }{\ifinsidefloat\ifinsidesplitfloat\else\setfalse\c_tabl_tabulate_split\fi\fi}
+
+% todo: spacing around tabulate when bodyfont is set
+
+\unexpanded\def\tabl_tabulate_start_building
+ {\ifinsidefloat \else
+ \whitespace
+ \tabulationparameter\c!before
+ \fi
+ \bgroup % settings
+ %
+ \t_tabl_tabulate_preamble\emptytoks
+ \t_tabl_tabulate_dummy \emptytoks
+ %
+ \resetcharacteralign
+ %
+ \edef\p_distance {\tabulationparameter\c!distance}%
+ \edef\p_align {\tabulationparameter\c!align}%
+ \edef\p_line {\tabulationparameter\c!rule}%
+ \edef\p_rulecolor {\tabulationparameter\c!rulecolor}%
+ \edef\p_rulethickness{\tabulationparameter\c!rulethickness}%
+ \edef\p_bodyfont {\tabulationparameter\c!bodyfont}
+ \edef\p_indenting {\tabulationparameter\c!indenting}%
+ %
+ \settrue\c_tabl_tabulate_split
+ \csname\??tabulatesplit\tabulationparameter\c!split\endcsname
+ %
+ \d_tabl_tabulate_unit\tabulationparameter\c!unit
+ \d_tabl_tabulate_margin\tabulationparameter\c!margin
+ \let\m_tabl_tabulate_vrule_color_default\p_rulecolor
+ \let\m_tabl_tabulate_hrule_color_default\p_rulecolor
+ \d_tabl_tabulate_vrulethickness_default\p_rulethickness
+ \d_tabl_tabulate_hrulethickness_default\p_rulethickness
+ \ifx\p_bodyfont\empty\else
+ \switchtobodyfont[\p_bodyfont]%
+ \fi
+ \postponenotes % new, to be tested / will be configurable
+ \widowpenalty\zerocount % otherwise lines are not broken
+ \clubpenalty \zerocount % but overlap in funny ways
+ \the\everytabulate
+ \tabulationparameter\c!inner
+ \d_tabl_tabulate_indent\dimexpr\leftskip+\hangindent\ifx\p_indenting\v!yes+\parindent\fi\relax
+ \global\c_tabl_tabulate_column\zerocount
+ \processcontent
+ {\e!stop\ifx\currenttabulationparent\empty\v!tabulate\else\currenttabulationparent\fi}
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_process}
+
+\def\tabulateEQ
+ {\ifconditional\c_tabl_tabulate_firstflushed\else\tabulationparameter{EQ}\fi
+ \global\setfalse\c_tabl_tabulate_equal}
+
+% The next ones will be token registers
+
+\let\tabulatenormalpos\relax % hooks, todo
+\let\tabulateequalpos \relax % hooks, todo
+
+% color columns
+
+\let\m_tabl_tabulate_color_previous \empty
+\let\m_tabl_tabulate_color \empty
+\let\m_tabl_tabulate_text_color \empty
+\let\m_tabl_tabulate_color_local \empty
+\let\m_tabl_tabulate_vrule_color \empty
+\let\m_tabl_tabulate_vrule_color_local \empty
+\let\m_tabl_tabulate_vrule_color_default\empty % used local
+\let\m_tabl_tabulate_hrule_color_default\empty % used local
+
+\appendtoks
+ \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
+ \global \d_tabl_tabulate_vrulethickness_local\zeropoint
+\to \t_tabl_tabulate_every_row
+
+\unexpanded\def\tabl_tabulate_color_side_right_second
+ {\ifx\m_tabl_tabulate_color_previous\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color_previous
+ \glet\m_tabl_tabulate_color_previous\empty
+ \fi}
+
+\unexpanded\def\tabl_tabulate_color_side_left_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \ifcase\c_tabl_tabulate_colorspan
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_color_side_both_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \ifcase\c_tabl_tabulate_colorspan
+ %\glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
+ \fi
+ \fi}
+
+\let\tabl_tabulate_color_side_right \relax
+\let\tabl_tabulate_color_side_left \relax
+\let\tabl_tabulate_color_side_both \relax
+
+\appendtoks
+ \let\tabl_tabulate_color_side_right\tabl_tabulate_color_side_right_second
+ \let\tabl_tabulate_color_side_left \tabl_tabulate_color_side_left_second
+ \let\tabl_tabulate_color_side_both \tabl_tabulate_color_side_both_second
+\to \t_tabl_tabulate_initializers_second
+
+\def\tabl_tabulate_set_color_column#1% overloaded
+ {\unskip
+ \doifelsefastoptionalcheck{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}}
+
+\def\tabl_tabulate_set_color_column_nop
+ {\tabl_tabulate_column_normal}
+
+\def\tabl_tabulate_set_color_column_yes#1[#2]%
+ {\xdef\m_tabl_tabulate_color_local{#2}%
+ \tabl_tabulate_column_normal#1}
+
+% normal columns:
+
+\def\tabl_tabulate_column_normal#1%
+ {\unskip
+ \aligntab
+ \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi
+ \aligntab
+ \global\c_tabl_tabulate_type#1%
+ \aligntab}
+
+% equal columns
+
+\def\tabl_tabulate_column_equal#1%
+ {\unskip
+ \aligntab
+ \tabulateequalpos
+ \aligntab\global\c_tabl_tabulate_type#1%
+ \aligntab}
+
+% ruled columns
+
+\def\tabl_tabulate_column_vruled#1%
+ {\unskip % 0-n
+% \ifnum\c_tabl_tabulate_column=\plusone
+% \global\c_tabl_tabulate_has_rule_spec_first\plusone
+% \else\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns
+% \global\c_tabl_tabulate_has_rule_spec_last\plusone
+% \fi\fi
+ \global\let\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
+ \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default
+ \doifelsefastoptionalcheck{\tabl_tabulate_column_vruled_yes#1}{\tabl_tabulate_column_vruled_nop#1}}
+
+\def\tabl_tabulate_column_vruled_nop
+ {\tabl_tabulate_column_normal}
+
+\def\tabl_tabulate_column_vruled_step#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_vrulethickness_local#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color_local{#1}}}
+
+\def\tabl_tabulate_column_vruled_yes#1[#2]%
+ {\rawprocesscommalist[#2]\tabl_tabulate_column_vruled_step
+ \tabl_tabulate_column_normal#1}
+
+\def\tabl_tabulate_column_vruled_normal
+ {\vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
+
+\def\tabl_tabulate_column_vruled_colored
+ {\dousecolorparameter\m_tabl_tabulate_vrule_color
+ \vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
+
+\unexpanded\def\tabl_tabulate_column_vrule_inject_first
+ {\ifcase\d_tabl_tabulate_vrulethickness\else
+ \tabl_tabulate_column_vruled_normal % could be a skip instead
+ \fi
+ \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
+
+\unexpanded\def\tabl_tabulate_column_vrule_inject_second
+ {\ifcase\d_tabl_tabulate_vrulethickness\else
+ \ifx\m_tabl_tabulate_vrule_color\empty
+ \tabl_tabulate_column_vruled_normal
+ \else
+ \tabl_tabulate_column_vruled_colored
+ \fi
+ \fi
+ \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
+
+\let\tabl_tabulate_column_vrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_second
+\to \t_tabl_tabulate_initializers_second
+
+% auto columns
+
+\def\tabl_tabulate_column_inject_auto
+ {\tabl_tabulate_column_normal\zerocount
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax
+ \expandafter\NR
+ \else
+ \expandafter\ignorespaces % interferes with the more tricky hooks
+ \fi}
+
+\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
+ {\let#1\tabl_tabulate_column_inject_auto
+ \let\\\tabl_tabulate_column_inject_auto} % brrr, will go
+
+\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
+\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
+\setvalue{\??tabulateseparator\v!small }{\def\m_tabl_tabulate_separator_factor{.25}}
+\setvalue{\??tabulateseparator\v!medium}{\def\m_tabl_tabulate_separator_factor{.5}}
+\setvalue{\??tabulateseparator\v!big }{}
+\setvalue{\??tabulateseparator\v!none }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+\setvalue{\??tabulateseparator\v!grid }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+
+\def\tabl_tabulate_column_rule_separator_step#1%
+ {\ifcsname\??tabulateseparator#1\endcsname
+ \lastnamedcs
+ \else
+ \s_tabl_tabulate_separator#1\relax
+ \fi}
+
+\def\tabl_tabulate_column_rule_separator_inject % can be sped up (will do when used frequently)
+ {\bgroup
+ \s_tabl_tabulate_separator\strutdp
+ \ifx\p_distance\empty\else
+ \let\m_tabl_tabulate_separator_factor\plusone
+ \processcommacommand[\p_distance]\tabl_tabulate_column_rule_separator_step
+ \s_tabl_tabulate_separator\m_tabl_tabulate_separator_factor\s_tabl_tabulate_separator
+ \fi
+ % someamble: footer or header: unfortunately a skip can trigger a page break (weird
+ % as we have lots of nobreaks)
+ % \ifconditional\c_tabl_tabulate_someamble\kern\else\vskip\fi\s_tabl_tabulate_separator % new
+ % \directvspacing{\the\s_tabl_tabulate_separator}% new
+ \directvskip\s_tabl_tabulate_separator
+ \egroup}
+
+\def\tabl_tabulate_hrule_spec_ignore#1%
+ {%\global\let\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
+ \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
+ \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
+
+\def\tabl_tabulate_hrule_preset_step#1%
+ {\doifelsenumber{#1}
+ {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
+ {\xdef\currenttabulationlocalhrulecolor{#1}}}
+
+\def\tabl_tabulate_hrule_preset#1[#2]%
+ {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
+ #1}
+
+\def\tabl_tabulate_hrule_inject_normal
+ {\hrule
+ \s!height.5\d_tabl_tabulate_hrulethickness_local
+ \s!depth .5\d_tabl_tabulate_hrulethickness_local
+ \relax}
+
+\def\tabl_tabulate_hrule_inject_colored
+ {\dousecolorparameter\currenttabulationlocalhrulecolor
+ \tabl_tabulate_hrule_inject_normal}
+
+\unexpanded\def\tabl_tabulate_hrule_inject_first
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \tabl_tabulate_hrule_inject_normal
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hrule_inject_second
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \ifx\currenttabulationlocalhrulecolor\empty
+ \tabl_tabulate_hrule_inject_normal
+ \else
+ \tabl_tabulate_hrule_inject_colored
+ \fi
+ \fi}
+
+\let\tabl_tabulate_hrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_second
+\to \t_tabl_tabulate_initializers_second
+
+%D Color:
+
+% \starttabulate[||p||]
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[green] \input tufte \CC[yellow] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \CC[blue] test \CC[red] test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \CC[gray] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \CC[blue] test \NC test \NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \NC test \CC[magenta] test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[cyan] \dorecurse{10}{\input ward }\NC test \NC \NR
+% \NC test \NC test \NC test \NC \NR
+% \NC test \CC[yellow] test \NC test \NC \NR
+% \stoptabulate
+
+\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
+ {\begingroup
+ \clf_enablebackgroundalign % was \node_backgrounds_align_initialize
+ \global\let\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
+ \setxvalue{\??tabulatecolor\the\c_tabl_tabulate_column}{#1}%
+ \hbox \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 ?
+ \fi
+ \endgroup}
+
+\let\tabl_tabulate_color_repeat\relax
+
+\appendtoks
+ \let\tabl_tabulate_color_repeat\relax
+\to \everytabulate
+
+\def\tabl_tabulate_color_reset
+ {\ifcase\c_tabl_tabulate_max_colorcolumn\else
+ \tabl_tabulate_color_reset_indeed
+ \fi}
+
+% \def\tabl_tabulate_color_reset_indeed
+% {\dorecurse\c_tabl_tabulate_max_colorcolumn{\letgvalue{\??tabulatecolor\recurselevel}\undefined}} % slow
+
+\def\tabl_tabulate_color_reset_indeed
+ {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
+
+\def\tabl_tabulate_color_reset_step % undefined or empty?
+ {\global\expandafter\let\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
+
+\appendtoks
+ \tabl_tabulate_color_reset
+\to \t_tabl_tabulate_every_after_row
+
+% \def\tabl_tabulate_register_par_options_indeed
+% {\iftrialtypesetting \else
+% \registerparoptions
+% \ifinsidefloat
+% % that is, an unbreakable one
+% \glet\tabl_tabulate_register_par_options\empty
+% \else
+% % unsafe in crossing pages, at each b...
+% % \glet\tabl_tabulate_register_par_options\empty
+% \fi
+% \fi}
+%
+% \appendtoks
+% \glet\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_indeed
+% \to \everytabulate
+
+\def\tabl_tabulate_register_par_options_first % maybe track here if needed
+ {}
+
+\def\tabl_tabulate_register_par_options_second
+ {\registerparoptions
+ \ifinsidefloat
+ % that is, an unbreakable one
+ \glet\tabl_tabulate_register_par_options\empty
+ \else
+ % unsafe in crossing pages, at each b...
+ % \glet\tabl_tabulate_register_par_options\empty
+ \fi}
+
+\let\tabl_tabulate_register_par_options\relax
+
+\appendtoks
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_second
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \tabl_tabulate_register_par_options
+\to \t_tabl_tabulate_every_row
+
+\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}%
+ \fi}
+
+\def\tabl_tabulate_digits{\digits}
+
+%D Beware, we cannot use \type {\unexpanded} on \type {\HL}
+%D cum suis, since \TEX's hard coded noalign lookahead fails
+%D on it! I mistakenly added this for a while.
+
+\setvalue{\??tabulatealigning\v!normal}{0}
+\setvalue{\??tabulatealigning\v!right }{1}
+\setvalue{\??tabulatealigning\v!left }{2}
+\setvalue{\??tabulatealigning\v!middle}{3}
+
+\setvalue{\??tabulateheader\v!repeat}{\plusone}
+\setvalue{\??tabulateheader\v!text }{\plustwo}
+
+\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+\unexpanded\def\tabl_tabulate_xbskip_first{\hbox\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+
+\let\tabl_tabulate_bbskip\relax
+\let\tabl_tabulate_eeskip\relax
+\let\tabl_tabulate_bskip \relax
+\let\tabl_tabulate_eskip \relax
+\let\tabl_tabulate_xbskip\relax
+\let\tabl_tabulate_xeskip\relax
+
+\appendtoks
+ \let\tabl_tabulate_bbskip\relax
+ %\let\tabl_tabulate_eeskip\relax % adapted by bskip
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_first
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_first
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_first
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_first
+\to \t_tabl_tabulate_initializers_first
+
+\def\tabl_tabulate_baselinecorrection % keep an eye on this one
+ {\def\dobaselinecorrection{\vskip\dimexpr-\prevdepth+\strutdp+\strutdp\relax}% todo: mkiv
+ \baselinecorrection}
+
+% some hack to prevent an allowbreak ... actually we could set up a system then
+% that is dealt with atthe lua end in the skip handler: turn penalties with attributes
+% values into other penalties that get removed
+
+\installcorenamespace{tabulatenobreak}
+
+% \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}
+%
+% \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
+% \fi}
+%
+% \def\tabl_tabulate_break_state_allowbreak
+% {\ifcsname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname
+% %\writestatus{TRUE}{\the\c_tabl_tabulate_noflines}%
+% \else
+% %\writestatus{FALSE}{\the\c_tabl_tabulate_noflines}%
+% \tabl_tabulate_break_allow % needed with pbreak prevention
+% \fi}
+%
+% \let\tabl_tabulate_break_allow\allowbreak
+% \let\tabl_tabulate_break_no \nobreak
+
+\def\tabl_tabulate_break_allow{\directvpenalty\zerocount}
+\def\tabl_tabulate_break_maybe{\directvpenalty\zerocount}
+\def\tabl_tabulate_break_no {\directvpenalty\plustenthousand} % ,order:2}}
+
+\let\tabl_tabulate_break_state_set \relax
+\let\tabl_tabulate_break_state_reset \relax
+\let\tabl_tabulate_break_state_allowbreak\tabl_tabulate_break_maybe
+
+% so far
+
+\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount}
+\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount}
+\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\plusone}
+\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\plustwo}
+\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \zerocount}
+\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \plusone}
+\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \plustwo}
+
+%unexpanded\def\tabl_tabulate_NG_first{\NC\tabl_tabulate_charalign}
+\unexpanded\def\tabl_tabulate_NG_first{\NC}
+\unexpanded\def\tabl_tabulate_NN_first{\NC\tabl_tabulate_digits} % new, undocumented, test first
+\unexpanded\def\tabl_tabulate_ND_first{\NC\tabl_tabulate_digits} % same, for old times sake
+
+\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
+\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
+
+\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
+\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
+
+\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount}
+\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
+
+\appendtoks
+ \let\VL\tabl_tabulate_VL_first
+ \let\NC\tabl_tabulate_NC_first
+ \let\RC\tabl_tabulate_RC_first
+ \let\HC\tabl_tabulate_HC_first
+ \let\EQ\tabl_tabulate_EQ_first
+ \let\RQ\tabl_tabulate_RQ_first
+ \let\HQ\tabl_tabulate_HQ_first
+ \let\NG\tabl_tabulate_NG_first
+ \let\NN\tabl_tabulate_NN_first
+ \let\ND\tabl_tabulate_ND_first
+ \let\NR\tabl_tabulate_NR_first
+ \let\NB\tabl_tabulate_NB_first
+ \let\CC\tabl_tabulate_CC_first
+ \let\CL\tabl_tabulate_CL_first
+ \let\CM\tabl_tabulate_CM_first
+ \let\CR\tabl_tabulate_CR_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\NR\tabl_tabulate_NR_second
+ \let\NB\tabl_tabulate_NB_second
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \let\SR\NR
+ \let\FR\NR
+ \let\MR\NR
+ \let\LR\NR
+ \let\AR\NR
+\to \t_tabl_tabulate_initializers_first
+
+\unexpanded\def\tabl_tabulate_NR_common#1#2%
+ {\global\advance\c_tabl_tabulate_noflines\plusone
+ \global\setfalse\c_tabl_tabulate_firstflushed
+ \global\setfalse\c_tabl_tabulate_equal
+ \global\c_tabl_tabulate_column\zerocount
+ \ifconditional#1\relax
+ \tabl_tabulate_break_state_reset
+ \fi
+ \tabl_tabulate_pheight_reset
+ \unskip\unskip\crcr\tabl_tabulate_flush_collected
+ % can we omit the next one in the first run? probably
+ \starttabulatenoalign
+ \the\t_tabl_tabulate_every_after_row
+ #2%
+ \stoptabulatenoalign}
+
+\def\tabl_tabulate_check_penalties
+ {\ifconditional\c_tabl_tabulate_tolerant_break\else
+ \ifnum\c_tabl_tabulate_totalnoflines=\plusone
+ % \tabl_tabulate_break_allow
+ \else
+ \ifconditional\c_tabl_tabulate_someamble \ifcase\c_tabl_tabulate_repeathead \else
+ \tabl_tabulate_break_allow
+ \fi \fi
+ \ifnum\c_tabl_tabulate_noflines=\plusone
+ \tabl_tabulate_nobreak_inject
+ \else \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_minusnoflines
+ \ifnum\c_tabl_tabulate_plines_max<\plustwo
+ \tabl_tabulate_nobreak_inject
+ \else
+ \tabl_tabulate_break_allow % needed with pbreak prevention
+ \fi
+ \else
+ \tabl_tabulate_break_state_allowbreak
+ \fi \fi
+ \fi
+ \fi
+ \global\setfalse\c_tabl_tabulate_firstflushed}
+
+\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ \ifx\tabl_tabulate_flush_collected_indeed\empty\else
+ \setbox0\hbox
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_eskip_second
+ {\par\egroup
+ \tabl_tabulate_pheight_set
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \tabl_tabulate_splitoff_box}
+
+\unexpanded\def\tabl_tabulate_bskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ % first line
+ \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
+ \bgroup
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
+ % \begstrut % interferes with pre-\pars
+ % evt: \appendtoks\begstrut\to\everypar
+ \ignorespaces
+ \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
+ \else
+ % successive lines
+ \let\tabl_tabulate_eskip\empty
+ \dontcomplain
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \expandafter\tabl_tabulate_splitoff_box
+ \fi}
+
+\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
+\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
+
+\unexpanded\def\tabl_tabulate_flush_second_indeed
+ {\glet\tabl_tabulate_flush_collected_indeed\empty
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pbreak_check
+ \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
+ \global\settrue\c_tabl_tabulate_firstflushed}
+
+\unexpanded\def\tabl_tabulate_flush_second_step
+ {\ifvoid\b_tabl_tabulate_current\fastloopindex\else
+ \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
+ \fi}
+
+\def\tabl_tabulate_flush_second
+ {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
+ \tabl_tabulate_flush_collected_indeed}
+
+\unexpanded\def\tabl_tabulate_bskip_second_split_nop
+ {\vtop\bgroup
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
+ % \begstrut % interferes with pre-\pars
+ % evt: \appendtoks\begstrut\to\everypar
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
+ {\par\verticalstrut
+ \vskip-\struttotal
+ \egroup}
+
+% \let\tabl_tabulate_eskip \relax % adapted by bskip
+% \let\tabl_tabulate_eeskip\relax % adapted by bskip
+
+\appendtoks
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
+ \ifconditional\c_tabl_tabulate_split
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
+ \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
+ \else
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
+ \fi
+\to \t_tabl_tabulate_initializers_second
+
+% see ***
+%
+% \enabletrackers[nodes.page_vspacing]
+% \starttext
+% \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
+% \stoptext
+
+\def\tabl_tabulate_XX_none
+ {\starttabulatenoalign
+ \tabl_tabulate_break_state_set
+ \tabl_tabulate_hrule_spec_ignore
+ \stoptabulatenoalign}
+
+\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
+\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
+\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
+\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
+\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
+
+\unexpanded\def\tabl_tabulate_FL_second_indeed
+ {\ifinsidefloat\else
+ \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
+ \fi
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \prevdepth\strutdp
+ \tabl_tabulate_nobreak_inject
+ \stoptabulatenoalign}
+
+% \unexpanded\def\tabl_tabulate_ML_second_indeed
+% {\tabl_tabulate_column_rule_separator_inject
+% \tabl_tabulate_hrule_inject
+% \vskip-\p_rulethickness\relax
+% \tabl_tabulate_hrule_inject
+% \tabl_tabulate_break_no
+% \tabl_tabulate_column_rule_separator_inject
+% \stoptabulatenoalign}
+
+\def\spac_vspacing_no_topskip % use grouped
+ {\attribute\skipcategoryattribute\plusten}
+
+\unexpanded\def\tabl_tabulate_ML_second_indeed
+ {\tabl_tabulate_break_no
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_break_no
+ \tabl_tabulate_hrule_inject
+ \vskip-\p_rulethickness\relax
+ \begingroup
+ \spac_vspacing_no_topskip
+ \tabl_tabulate_hrule_inject
+ \endgroup
+ \tabl_tabulate_break_no
+ \tabl_tabulate_column_rule_separator_inject
+ \stoptabulatenoalign}
+
+\unexpanded\def\tabl_tabulate_LL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
+ \ifinsidefloat\else
+ \doifempty{\tabulationparameter\c!after}
+ {\vskip\strutdp
+ \verticalstrut
+ \vskip-\struttotal}%
+ \fi
+ \stoptabulatenoalign}
+
+\unexpanded\def\tabl_tabulate_TL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ %\prevdepth\strutdp % todo, might differ between TL and BL
+ \tabl_tabulate_nobreak_inject
+ \stoptabulatenoalign}
+
+\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
+
+\def\tabl_tabulate_HL_second
+ {\csname
+ \ifnum\c_tabl_tabulate_noflines=\zerocount F\else
+ \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
+ M\fi\fi
+ L\endcsname}
+
+\appendtoks
+ \let\FL\tabl_tabulate_XX_none
+ \let\ML\tabl_tabulate_XX_none
+ \let\LL\tabl_tabulate_XX_none
+ \let\TL\tabl_tabulate_XX_none
+ \let\BL\tabl_tabulate_XX_none
+ \let\HL\tabl_tabulate_XX_none
+ \let\HR\tabl_tabulate_XX_none
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\FL\tabl_tabulate_FL_second
+ \let\ML\tabl_tabulate_ML_second
+ \let\LL\tabl_tabulate_LL_second
+ \let\TL\tabl_tabulate_TL_second
+ \let\BL\tabl_tabulate_BL_second
+ \let\HL\tabl_tabulate_HL_second
+ \let\HR\tabl_tabulate_HL_second
+\to \t_tabl_tabulate_initializers_second
+
+% \def\tabulatedoHRfive % horizontal rule line (break untested)
+% {\starttabulatenoalign
+% \globallet\dotabulateautoline\dotabulatelinerule
+% %\ifcase#1\or % todo: check what this does
+% \ifnum\noftabulatelines=\zerocount
+% \glet\dotabulateautoline\donothing
+% \else\ifnum\noftabulatelines=\totalnoftabulatelines
+% \glet\dotabulateautoline\donothing
+% \fi\fi
+% %\fi
+% \dotabulatenobreak
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \tabl_tabulate_break_no
+% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
+% \ifnum\noftabulatelines=\totalnoftabulatelines
+% \@EA\dotabulatenobreak
+% \else
+% \@EA\tabl_tabulate_break_allow
+% \fi
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \dotabulatenobreak
+% \stoptabulatenoalign}
+
+% \dorecurse{10}{
+% \starttabulate[|l|]
+% \FL
+% \NC first line, bound to next rule \NC \NR
+% \TL
+% \NC bound to previous rule \NC \NR
+% \NC some line \NC \NR
+% \NC some line \NC \NR
+% \NC some line \NC \NR
+% \NC bound to next rule \NC \NR
+% \ML
+% \NC bound to previous rule \NC \NR
+% \NC bound to next rule \NC \NR
+% \BL
+% \NC last line, bound to previous rule \NC \NR
+% \LL
+% \stoptabulate
+% }
+
+% This needs checking:
+
+\def\tabulaterule {\HR} % a rule with lineheight
+\def\tabulateline {\HL} % just a spaced rule
+\def\tabulateautorule{\HR}%
+\def\tabulateautoline{\HL} % no longer different (to be looked into)
+
+% When support for vertical rules we needed a way to pick up the
+% specification for the final rule and a \type {|{}} interface was
+% chosen. As a result parsing had to become more complex and I was
+% not in the mood for messing up the code too much. Therefore from
+% now on the preamble is split by \LUA. There are definitely more
+% places where we can use \LUA\ code (for instance in alignment of
+% numbers. The repeat parser is replace at the \LUA\ end as well.
+
+\let\tabl_tabulate_flush_collected \empty
+\let\tabl_tabulate_flush_collected_indeed\empty
+
+\let\v_tabl_tabulate_align\!!zerocount
+
+\def\tabl_tabulate_set_local_hsize
+ {\setlocalhsize
+ \hsize\localhsize}
+
+\def\tabl_tabulate_process
+ {\c_tabl_tabulate_pass\plusone
+ \tabl_tabulate_check_full_content
+ \edef\v_tabl_tabulate_align{\executeifdefined{\??tabulatealigning\p_align}0}%
+ \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
+ \s_tabl_tabulate_last\s_tabl_tabulate_first
+ \s_tabl_tabulate_pre\zeropoint
+ \s_tabl_tabulate_post\s_tabl_tabulate_first % was: \zeropoint
+ \global\c_tabl_tabulate_columns\zerocount
+ \global\c_tabl_tabulate_nofauto\zerocount
+ \global\c_tabl_tabulate_noflines\zerocount
+ \c_tabl_tabulate_totalnoflines\zerocount
+ \c_tabl_tabulate_minusnoflines\zerocount
+ \global\d_tabl_tabulate_width_p\zeropoint
+ \global\d_tabl_tabulate_width_w\zeropoint
+ \global\setfalse\c_tabl_tabulate_equal
+ \tabl_tabulate_pheight_reset
+ \tabskip\zeropoint
+ \ifinsidesplitfloat
+ \donetrue
+ \else\ifinsidefloat
+ \donefalse
+ \else
+ \donetrue
+ \fi\fi
+ \ifdone
+ \global\c_tabl_tabulate_repeathead\executeifdefined{\??tabulateheader\tabulationparameter\c!header}\zerocount
+ \else
+ \global\c_tabl_tabulate_repeathead\zerocount
+ \fi
+ %
+ \the\t_tabl_tabulate_initializers_first % collect more here
+ %
+ \glet\tabl_tabulate_flush_collected\empty
+ \ifdim\d_tabl_tabulate_margin>\zeropoint
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \tabskip\d_tabl_tabulate_margin
+ \strut
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
+ \else
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
+ \fi
+ \d_tabl_tabulate_width\zeropoint
+ % these counters are set at the lua end
+ \c_tabl_tabulate_nofcolumns \zerocount
+ \c_tabl_tabulate_has_rule_spec_first\zerocount
+ \c_tabl_tabulate_has_rule_spec_last \zerocount
+ \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
+ %
+ % \edef\totaltabulatecolumns{\the\numexpr3*\c_tabl_tabulate_columns+\plusfour}%
+ \d_tabl_tabulate_width\zeropoint
+ \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
+ \toksapp\t_tabl_tabulate_preamble{%
+ \aligntab\alignmark\alignmark
+ \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
+ }%
+ \toksapp\t_tabl_tabulate_dummy{%
+ \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
+ }%
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pheight_reset
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \ifx\p_indenting\v!no
+ \forgetparindent
+ \fi
+ \ifinsidefloat
+ \d_tabl_tabulate_indent\zeropoint
+ \else
+ \tabl_tabulate_set_local_hsize
+ \fi
+ \dontcomplain
+ \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
+ \everypar\everytabulatepar
+ \setbox0\vbox % outside \if because of line counting
+ {\notesenabledfalse
+ \d_tabl_tabulate_indent\zeropoint
+ \settrialtypesetting % very important
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ % so, even if the natural size is larger, in the final run, we force the calculated width
+ \d_tabl_tabulate_width\dimexpr\hsize-\wd0-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
+ \fi
+ \fi
+ \ifconditional\c_tabl_tabulate_split
+ \splittopskip\strutht
+ \glet\tabl_tabulate_flush_collected_indeed\empty
+ \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
+ \fi
+ \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
+ \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
+ \global\c_tabl_tabulate_noflines\zerocount
+ %
+ \c_tabl_tabulate_pass\plustwo % final pass
+ \the\t_tabl_tabulate_initializers_second % collect more here
+ %
+ \ifx\p_line\v!line
+ \let\HL\HR
+ \let\tabulateautoline\tabulateautorule
+ \let\tabulateline\tabulaterule
+ \fi
+ %
+ \ifcase\c_tabl_tabulate_repeathead
+ \ifinsidesplitfloat
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
+ \else
+ \startframedcontent[\tabulationparameter\c!frame]%
+ \fi
+ \else
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
+ \fi
+ %
+ \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}%
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
+ \dostoptagged
+ \dostoptagged
+ \ifhmode\par\prevdepth\strutdp\fi % nog eens beter, temporary hack
+ \ifx\p_distance\v!grid
+ \vskip-\strutdp % experimental tm-prikkels
+ \fi
+ %
+ \ifcase\c_tabl_tabulate_repeathead
+ \ifinsidesplitfloat
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
+ \else
+ \stopframedcontent
+ \egroup
+ \fi
+ \else
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
+ \fi
+ %
+ \ifinsidefloat \else
+ \tabulationparameter\c!after
+ \fi
+ \egroup} % whole thing
+
+% \egroup
+
+% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
+%
+% % \starttabulatehead
+% % \NC test \NC hans\NC \NR
+% % \stoptabulatehead
+%
+% \starttabulate
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input knuth \relax \NC \NR
+% \NC test \NC \input knuth \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \NC test \NC \input tufte \relax \NC \NR
+% \stoptabulate
+
+\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
+ {\ifinsidesplitfloat
+ \tabl_split_box_indeed#1%
+ \else\ifinsidefloat
+ \unvbox#1%
+ \else
+ \tabl_split_box_indeed#1%
+ \fi\fi}
+
+\def\tabl_split_box_indeed#1%
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{0pt}%
+ \setbox\tsplitcontent\box#1%
+ \ifcase\c_tabl_tabulate_repeathead\or
+ \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvbox\tsplithead}%
+ \or
+ \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
+ \fi
+ \handletsplit}
+
+%D \starttyping
+%D \setuptabulate[split=no,rule=line]
+%D
+%D \starttabulate
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
+%D \stoptabulate
+%D \stoptyping
+
+%D Spacing:
+%
+% \starttabulate
+% \NC text \NC text \NC \NR
+% \TB[small]
+% \NC text \NC text \NC \NR
+% \TB[4*big]
+% \NC text \NC text \NC \NR
+% \stoptabulate
+
+\def\tabl_tabulate_TB
+ {\starttabulatenoalign
+ \dosingleempty\tabl_tabulate_TB_indeed}
+
+\def\tabl_tabulate_TB_indeed[#1]%
+ {\iffirstargument
+ \blank[#1]
+ \else
+ \blank
+ \fi
+ \stoptabulatenoalign}
+
+% to be tested:
+%
+% \def\tabl_tabulate_TB
+% {\starttabulatenoalign
+% \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
+%
+% \def\tabl_tabulate_TB_yes[#1]%
+% {\blank[#1]
+% \stoptabulatenoalign}
+%
+% \def\tabl_tabulate_TB_nop[#1]%
+% {\blank
+% \stoptabulatenoalign}
+
+\appendtoks
+ \let\TB\tabl_tabulate_TB
+\to \everytabulate
+
+% %D Between alignment lines certain rules apply, and even a simple test can mess
+% %D up a table, which is why we have a special test facilityL
+% %D
+% %D \startbuffer
+% %D \starttabulate[|l|p|]
+% %D \NC 1test \NC test \NC \NR
+% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
+% %D \stoptabulate
+% %D \stopbuffer
+% %D
+% %D \typebuffer \getbuffer
+%
+% \def\tableifelse#1% should be tabulatenoalign then
+% {\tablenoalign
+% {#1%
+% {\aftergroup \firstoftwoarguments}%
+% {\aftergroup\secondoftwoarguments}}}
+%
+% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
+
+%D Some new trickery:
+%D
+%D \startbuffer
+%D \settrue\c_tabl_tabulate_splitoff_whitespace
+%D
+%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \par
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[line]
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \blank \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \NC \NR
+%D \NC test 1a
+%D \par
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \par
+%D test 2b \NC test 3a \NC \NR
+%D \NC test 1a
+%D \blank
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \blank
+%D test 2b \NC test 3a \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+
+% \starttabulatie[|mc|]
+% \NC \digits{100.000,00} \NC\NR
+% \NC \digits{@10.000,00} \NC\NR
+% \NC \digits{@@@.100,00} \NC\NR
+% \NC \digits{@@@.@10,@@} \NC\NR
+% \NC \digits{@@@.@@1,@@} \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|mc|]
+% \ND 100.000,00 \NC\NR
+% \ND @10.000,00 \NC\NR
+% \ND @@@.100,00 \NC\NR
+% \ND @@@.@10,@@ \NC\NR
+% \ND @@@.@@1,@@ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \ND $100.000,00$ \NC\NR
+% \ND $@10.000,00$ \NC\NR
+% \ND $@@@.100,00$ \NC\NR
+% \ND $@@@.@10,@@$ \NC\NR
+% \ND $@@@.@@1,@@$ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \NC $\digits 100.000,00 $ \NC\NR
+% \NC $\digits @10.000,00 $ \NC\NR
+% \NC $\digits @@@.100,00 $ \NC\NR
+% \NC $\digits @@@.@10,@@ $ \NC\NR
+% \NC $\digits @@@.@@1,@@ $ \NC\NR
+% \stoptabulatie
+%
+% \starttabulatie[|c|]
+% \NC \digits $100.000,00$ \NC\NR
+% \NC \digits $@10.000,00$ \NC\NR
+% \NC \digits $@@@.100,00$ \NC\NR
+% \NC \digits $@@@.@10,@@$ \NC\NR
+% \NC \digits $@@@.@@1,@@$ \NC\NR
+% \stoptabulatie
+
+%D Predefined categories (moved from core-mis):
+
+\definetabulate
+ [\v!legend]
+ [|emj1|i1|mR|]
+
+\setuptabulate
+ [\v!legend]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
+
+\definetabulate
+ [\v!legend][\v!two]
+ [|emj1|emk1|i1|mR|]
+
+\definetabulate
+ [\v!fact]
+ [|R|ecmj1|i1mR|]
+
+\setuptabulate
+ [\v!fact]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
+
+%D Another example:
+%D
+%D \starttyping
+%D \definetabulate
+%D [whatever]
+%D [|l|r|]
+%D
+%D \definetabulate
+%D [whatever][else]
+%D [|l|c|r|]
+%D
+%D \startwhatever
+%D \NC l \NC r \NC \NR
+%D \NC left \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else]
+%D \NC l \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else][format={|c|c|c|c|}]
+%D \NC l \NC m \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D \stoptyping
+
+%D This is needed because we soemtimes use the english command in
+%D tracing macros. In fact, most detailed tracing macros that
+%D are done with \LUA\ only work in the english interface anyway.
+
+\definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv
new file mode 100644
index 00000000000..e0c3b9b746b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv
@@ -0,0 +1,537 @@
+%D \module
+%D [ file=tabl-tsp,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Splitting,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Splitting}
+
+%D The code in this file is moved here from other places and needs
+%D a mkiv cleanup. As it mostly targets at tables the code lives in
+%D the tabl and page namespaces.
+
+% work in progress
+
+\unprotect
+
+%D Although the name resembles floats, and therefore this should be
+%D a page module, we decided to make it core functionality because the
+%D table code depends on it. Othrwise there would be too much
+%D overloading afterwards involved. Actually, the float part is rather
+%D generic and not that related to floats.
+
+% \splitfloat [settings] {\placetable[optional args]{test}} {content}
+
+%D When \type {inbetween} is made empty instead of the
+%D default \type {\page}, we will get delayed flushing
+%D and text may continue below the graphic.
+%D
+%D \starttyping
+%D \dorecurse{2}{\input tufte }
+%D
+%D \splitfloat[lines=auto,inbetween=]
+%D {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}}
+%D {\bTABLE[split=yes]
+%D \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 14 \eTD \bTD test \eTD \eTR
+%D \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 24 \eTD \bTD test \eTD \eTR
+%D \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 34 \eTD \bTD test \eTD \eTR
+%D \eTABLE}
+%D
+%D \dorecurse{10}{\input tufte }
+%D \stoptyping
+
+\installcorenamespace{floatsplitting}
+
+\installdirectcommandhandler \??floatsplitting {floatsplitting} % \??floatsplitting
+
+\setupfloatsplitting
+ [\c!conversion=\v!character, % \v!romannumerals
+ \c!lines=3,
+ \c!before=,
+ \c!inbetween=\page,
+ \c!after=]
+
+\newconditional\splitfloatfirstdone
+\newconditional\somenextsplitofffloat
+\newconditional\splitfloatdone
+\newconditional\onlyonesplitofffloat \settrue\onlyonesplitofffloat
+
+\newif \ifinsidesplitfloat % will become conditional
+
+\newcount \noffloatssplits
+\newtoks \everysplitfloatsetup
+
+\let \extrasplitfloatlines \!!zerocount
+\let \splitfloatfinalizer \relax
+\let \floatcaptionsuffix \empty
+
+\unexpanded\def\splitfloat
+ {\dosingleempty\page_split_float}
+
+\def\page_split_float[#1]#2% nog dubbele refs
+ {\bgroup
+ \global\setfalse\splitfloatdone
+ \aftergroup\page_split_float_check
+ \insidefloattrue
+ \insidesplitfloattrue
+ \setupcurrentfloatsplitting[#1]%
+ \global\noffloatssplits\zerocount
+ \let\floatcaptionsuffix\page_split_float_suffix
+ \edef\extrasplitfloatlines{\floatsplittingparameter\c!lines}%
+ \the\everysplitfloatsetup
+ \def\splitfloatcommand{#2}%
+ \global\settrue \onlyonesplitofffloat
+ \global\setfalse\somenextsplitofffloat
+ \page_floats_push_saved
+ \floatsplittingparameter\c!before
+ \let\next} % \bgroup
+
+\unexpanded\def\page_split_float_suffix
+ {\begingroup
+ \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix
+ \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits
+ \endgroup}
+
+\unexpanded\def\page_split_float_check
+ {\ifconditional\splitfloatdone
+ \splitfloatfinalizer % a weird place (could interfere with flushing)
+ \else
+ \blank
+ \begingroup
+ \tttf \dontleavehmode \getmessage\m!floatblocks{13}\empty
+ \endgroup
+ \blank
+ \showmessage\m!floatblocks{13}\empty
+ \fi}
+
+\def\page_split_float_process % nextbox
+ {\ifinsidesplitfloat
+ \expandafter\page_split_float_process_yes
+ \else
+ \expandafter\page_split_float_process_nop
+ \fi}
+
+\def\page_split_float_process_yes
+ {\dowithnextboxcs\page_split_float_process_finish\vbox}
+
+\def\page_split_float_process_finish
+ {\forgetall
+ \dontcomplain
+ \global\settrue\splitfloatdone
+ % \nodelocationmode\zerocount % bypass auto-renumbering
+ \global\advance\noffloatssplits\plusone
+ \ifcase\noffloatssplits\relax \or
+ \ifconditional\onlyonesplitofffloat
+ \let\floatcaptionsuffix\empty
+ \fi
+ \fi
+ \bgroup
+ \ifconditional\somenextsplitofffloat
+ \notesenabledfalse % best here, experimental, brrr; test with note in caption
+ \fi
+ \splitfloatcommand{\box\nextbox}%
+ \egroup
+ \ifconditional\somenextsplitofffloat
+ \edef\p_inbetween{\floatsplittingparameter\c!inbetween}%
+ \ifx\p_inbetween\empty
+ \ifconditional\splitfloatfirstdone\else\page\fi
+ \else
+ \p_inbetween
+ \fi
+ \else
+ \floatsplittingparameter\c!after
+ \page_floats_pop_saved
+ \page_floats_flush_saved
+ \fi
+ \global\settrue\splitfloatfirstdone}
+
+\def\page_split_float_process_nop
+ {\dowithnextboxcs\page_split_float_process_nop_finish\vbox}
+
+\def\page_split_float_process_nop_finish
+ {\forgetall
+ \dontcomplain
+ \box\nextbox % maybe an option to unvbox
+ \global\settrue\splitfloatfirstdone}
+
+\def\page_split_float_check_content#1% box
+ {\ifinsidesplitfloat
+ % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow
+ \ifcase\ht#1\relax
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \fi}
+
+\def\page_split_float_check_caption#1% depends on page-flt .. pretty messy
+ {\edef\extrasplitfloatlines{\extrasplitfloatlines}%
+ \ifx\extrasplitfloatlines\v!auto
+ \bgroup
+ \forcelocalfloats
+ \setuplocalfloats[\c!before=,\c!after=,\c!inbetween=]%
+ \splitfloatcommand{\hbox to #1{\strut}}% dummy line
+ \setbox\scratchbox\vbox{\flushlocalfloats}%
+ \getnoflines{\ht\scratchbox}%
+ \resetlocalfloats
+ \advance\noflines\minusone % compensate dummy line
+ \normalexpanded{\egroup\noexpand\edef\noexpand\extrasplitfloatlines{\the\noflines}}%
+ \global\settrue\usesamefloatnumber
+ \else
+ \doifelsenumber\extrasplitfloatlines\donothing{\def\extrasplitfloatlines{1}}%
+ \fi}
+
+\unexpanded\def\doifnotinsidesplitfloat
+ {\ifinsidesplitfloat
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D Table splitter, on top of previous code:
+
+% todo: keep tail to rest, so we need a lookahead
+
+\newbox\tsplitcontent
+\newbox\tsplitresult
+\newbox\tsplithead
+\newbox\tsplitnext
+\newbox\tsplittail
+
+\newtoks\everyresettsplit
+
+\appendtoks
+ \let \tsplitminimumfreelines\!!zerocount
+ \let \tsplitminimumfreespace\!!zeropoint
+ \setbox\tsplitcontent \emptyvbox
+ \setbox\tsplitresult \emptyvbox
+ \setbox\tsplithead \emptyvbox
+ \setbox\tsplitnext \emptyvbox
+ \setbox\tsplittail \emptyvbox
+ \let \tsplitbeforeresult \donothing
+ \let \tsplitafterresult \donothing
+ \let \tsplitinbetween \donothing
+ \let \tsplitbefore \donothing
+ \let \tsplitafter \donothing
+ \let \postprocesstsplit \donothing
+\to \everyresettsplit
+
+\unexpanded\def\resettsplit
+ {\the\everyresettsplit}
+
+\resettsplit
+
+\def\tsplitdirectwidth{\hsize}
+
+\newconditional\c_tabl_split_done
+\newconditional\c_tabl_split_head
+\newconditional\c_tabl_split_full
+
+\newdimen \d_tabl_split_available
+
+\unexpanded\def\handletsplit
+ {\page_split_float_check_caption{\wd\tsplitcontent}%
+ \global\setfalse\splitfloatfirstdone
+ \testpagesync % new, sync, but still tricky
+ [\tsplitminimumfreelines]
+ [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]%
+ \setbox\scratchbox\vbox{\tsplitinbetween}%
+ \edef\tsplitinbetweenheight{\the\htdp\scratchbox}% etex
+ \setfalse\c_tabl_split_done
+ \doloop\tabl_split_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+\newconditional\tabl_split_forced_page
+
+\def\tabl_split_loop_body
+ {\ifinsidecolumns
+ % brrr, assumes empty columns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else
+ \ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \setfalse\c_tabl_split_full
+ \else
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \fi\fi
+ \fi
+ \d_tabl_split_available \dimexpr
+ \d_tabl_split_available
+ -\tsplitinbetweenheight
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \ifdim\htdp\tsplittail>\zeropoint
+ \advance\d_tabl_split_available-\htdp\tsplittail
+ \fi
+ \setbox\tsplitresult\vbox
+ {\ifdim\ht\tsplithead>\zeropoint
+ \unvcopy\tsplithead
+ \tsplitinbetween
+ \fi}%
+ \ifconditional\c_tabl_split_done \else
+ \ifdim\ht\tsplitnext>\zeropoint
+ \setbox\tsplithead\box\tsplitnext
+ \fi
+ \fi
+ \settrue\c_tabl_split_done
+ \ifdim\ht\tsplitresult>\zeropoint
+ \settrue\c_tabl_split_head % table head
+ \else
+ \setfalse\c_tabl_split_head % no tablehead
+ \fi
+ \splittopskip\zeropoint
+ \doloop % inner loop
+ {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight
+ \setbox\scratchbox\vbox % \vpack
+ {\unvbox\scratchbox
+ \setbox\scratchbox\vbox
+ {\splitdiscards
+ \ifnum\lastpenalty>-\plustenthousand\else
+ % so that \bTR[before=\page] works
+ \global\settrue\tabl_split_forced_page
+ \fi}}%
+ \ifconditional\tabl_split_forced_page
+ \global\setfalse\tabl_split_forced_page
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvbox\scratchbox}%
+ \exitloop
+ \else\ifdim\dimexpr\d_tabl_split_available-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvbox\scratchbox}%
+ \ifvoid\tsplitcontent \exitloop \fi
+ \else\ifconditional\c_tabl_split_head
+ % we only have a tablehead so far
+ \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}%
+ \exitloop
+ \else\ifconditional\c_tabl_split_full
+ % we have text height available, but the (one) cell is too
+ % large to fit, so, in order to avoid loops/deadcycles we do:
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvbox\scratchbox}%
+ \exitloop
+ \else
+ \setbox\tsplitcontent\vbox
+ {\unvbox\scratchbox
+ \tsplitinbetween
+ \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}%
+ \exitloop
+ \fi\fi\fi\fi
+ \setfalse\c_tabl_split_head
+ \setfalse\c_tabl_split_full}%
+ \postprocesstsplit
+ \page_split_float_check_content\tsplitcontent
+ \ifvoid\tsplitcontent
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \exitloop
+ \else
+ % hack
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ % brrr
+ \ifdim\ht\tsplitresult>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \fi
+ \ifinsidecolumns
+ \goodbreak % was \doifnotinsidesplitfloat\goodbreak
+ \else
+ \page % was \doifnotinsidesplitfloat\page
+ \fi
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \fi}
+
+%D The next one assumes that the split takes place elsewhere. This is
+%D used in xtables.
+
+\let\resetdirecttsplit\resettsplit
+
+\unexpanded\def\handledirecttsplit
+ {\page_split_float_check_caption{\tsplitdirectwidth}%
+ \global\setfalse\splitfloatfirstdone
+ \testpagesync % new, sync, but still tricky
+ [\tsplitminimumfreelines]
+ [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]%
+ \doloop\tabl_split_direct_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+\def\tabl_split_direct_loop_body
+ {\ifinsidecolumns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \d_tabl_split_available\textheight
+ \fi\fi\fi
+ \d_tabl_split_available\dimexpr
+ \d_tabl_split_available
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \tsplitdirectsplitter\d_tabl_split_available % also sets state
+ \ifdim\ht\tsplitresult>\zeropoint
+ \ifconditional\somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \endgraf
+ \ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page
+ \fi
+ \fi
+ \global\settrue\splitfloatfirstdone
+ \else\ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page % no room
+ \fi
+ \else
+ \exitloop
+ \fi\fi}
+
+\protect \endinput
+
+% test cases
+
+% \setupTABLE[split=repeat]
+%
+% \input tufte \endgraf
+% \splitfloat[lines=11]
+% {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}}
+% {\bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE}
+% \input tufte \page
+%
+% \input tufte \endgraf
+% \splitfloat[lines=0]
+% {}
+% {\bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE}
+% \input tufte \endgraf \page
+%
+% \input tufte \endgraf
+% \bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE
+% \input tufte \page
+
+% \setuptabulate[split=yes]
+%
+% \input tufte \endgraf
+% \splitfloat[lines=11]
+% {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}}
+% {\starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate}
+% \input tufte \page
+%
+% \input tufte \endgraf
+% \splitfloat[lines=0]
+% {}
+% {\starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate}
+% \input tufte \page
+%
+% \input tufte \endgraf
+% \starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate
+% \input tufte \page
+
+% \setuptables[split=yes]
+%
+% \newtoks\TestToks
+%
+% \TestToks\emptytoks
+% \appendtoks\starttablehead\to\TestToks
+% \dorecurse{3}{\appendtoks\VL head \VL head \VL \SR\to\TestToks}
+% \appendtoks\stoptablehead\to\TestToks
+% \appendtoks\starttabletail\to\TestToks
+% \dorecurse{3}{\appendtoks\VL tail \VL tail \VL \SR\to\TestToks}
+% \appendtoks\stoptabletail\to\TestToks
+% \appendtoks\starttables[|c|c|]\to\TestToks
+% \dorecurse{100}{\appendtoks\VL test \VL test \VL \SR\to\TestToks}
+% \appendtoks\stoptables\to\TestToks
+%
+% \input tufte \endgraf
+% \splitfloat[lines=auto] % [lines=11]
+% {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}}
+% {\the\TestToks}
+% \input tufte \page
+%
+% \input tufte \endgraf
+% \splitfloat[lines=0]
+% {}
+% {\the\TestToks}
+% \input tufte \page
+%
+% \input tufte \endgraf
+% \the\TestToks
+% \input tufte \page
+%
+% multiple floats
+%
+% \starttext
+% \dorecurse{3}{\input tufte } \endgraf
+% \dorecurse{5}{\placefigure{}{\framed[height=.5\textheight]{}}}
+% \splitfloat[lines=auto,inbetween=]
+% {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}}
+% {\bTABLE[split=yes]
+% \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR
+% \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR
+% \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR
+% \bTR \bTD 14 \eTD \bTD test \eTD \eTR
+% \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR
+% \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR
+% \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR
+% \bTR \bTD 24 \eTD \bTD test \eTD \eTR
+% \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR
+% \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR
+% \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR
+% \bTR \bTD 34 \eTD \bTD test \eTD \eTR
+% \eTABLE}
+% \dorecurse{10}{\input tufte }
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-xnt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/tabl-xnt.mkvi
new file mode 100644
index 00000000000..fd2de5a13cd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-xnt.mkvi
@@ -0,0 +1,135 @@
+% macros=mkvi
+
+%D \module
+%D [ file=tabl-xtb,
+%D version=2011.10.28,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural to Xtreme Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Natural to Xtreme Tables}
+
+\unprotect
+
+%D Don't expect wonders but it might come in handy:
+%D
+%D \starttyping
+%D \mapTABLEtoxtable
+%D \restoreTABLEfromxtable
+%D \stoptyping
+%D
+%D We stick to a simple example:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR
+%D \bTD[width=1cm,background=color,backgroundcolor=red] one \eTD
+%D \bTD[width=2cm] two \eTD
+%D \eTR
+%D \bTR
+%D \bTD alpha \eTD
+%D \bTD beta \eTD
+%D \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startbuffer
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \mapTABLEtoxtable \getbuffer
+%D \stoplinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\let\tabl_x_normal_bTABLEhead\bTABLEhead
+\let\tabl_x_normal_eTABLEhead\eTABLEhead
+\let\tabl_x_normal_bTABLEnext\bTABLEnext
+\let\tabl_x_normal_eTABLEnext\eTABLEnext
+\let\tabl_x_normal_bTABLEfoot\bTABLEfoot
+\let\tabl_x_normal_eTABLEfoot\eTABLEfoot
+\let\tabl_x_normal_bTABLEbody\bTABLEbody
+\let\tabl_x_normal_eTABLEbody\eTABLEbody
+\let\tabl_x_normal_bTR \bTR
+\let\tabl_x_normal_eTR \eTR
+\let\tabl_x_normal_bTD \bTD
+\let\tabl_x_normal_eTD \eTD
+\let\tabl_x_normal_bTH \bTH
+\let\tabl_x_normal_eTH \eTH
+\let\tabl_x_normal_setupTABLE\setupTABLE
+\let\tabl_x_normal_bTABLE \bTABLE
+\let\tabl_x_normal_eTABLE \eTABLE
+
+\unexpanded\def\restoreTABLEfromxtable
+ {\let\bTABLEhead\tabl_x_normal_bTABLEhead
+ \let\eTABLEhead\tabl_x_normal_eTABLEhead
+ \let\bTABLEnext\tabl_x_normal_bTABLEnext
+ \let\eTABLEnext\tabl_x_normal_eTABLEnext
+ \let\bTABLEfoot\tabl_x_normal_bTABLEfoot
+ \let\eTABLEfoot\tabl_x_normal_eTABLEfoot
+ \let\bTABLEbody\tabl_x_normal_bTABLEbody
+ \let\eTABLEbody\tabl_x_normal_eTABLEbody
+ \let\bTR \tabl_x_normal_bTR
+ \let\eTR \tabl_x_normal_eTR
+ \let\bTD \tabl_x_normal_bTD
+ \let\eTD \tabl_x_normal_eTD
+ \let\bTH \tabl_x_normal_bTH
+ \let\eTH \tabl_x_normal_eTH
+ \let\setupTABLE\tabl_x_normal_setupTABLE
+ \let\bTABLE \tabl_x_normal_bTABLE
+ \let\eTABLE \tabl_x_normal_eTABLE}
+
+\unexpanded\def\mapTABLEtoxtable
+ {\let\bTABLEhead\startxtablehead
+ \let\eTABLEhead\stopxtablehead
+ \let\bTABLEnext\startxtablefoot
+ \let\eTABLEnext\stopxtablefoot
+ \let\bTABLEfoot\startxtablefoot
+ \let\eTABLEfoot\stopxtablefoot
+ \let\bTABLEbody\startxtablebody
+ \let\eTABLEbody\stopxtablebody
+ \let\bTR \startxrow
+ \let\eTR \stopxrow
+ \let\bTD \startxcell
+ \let\eTD \stopxcell
+ \let\bTH \tabl_x_TABLE_TH_start_cell
+ \let\eTH \tabl_x_TABLE_TH_stop_cell
+ \let\setupTABLE\tabl_x_TABLE_setup
+ \let\bTABLE \tabl_x_TABLE_start
+ \let\eTABLE \tabl_x_TABLE_stop}
+
+\unexpanded\def\tabl_x_TABLE_setup{\dosingleempty\tabl_x_TABLE_setup_indeed}
+\unexpanded\def\tabl_x_TABLE_start{\dosingleempty\tabl_x_TABLE_start_indeed}
+\unexpanded\def\tabl_x_TABLE_stop {\stopxtable}
+
+\unexpanded\def\tabl_x_TABLE_TH_start_cell
+ {\startxcellgroup[\c!foregroundstyle=\v!bold]%
+ \startxcell}
+
+\unexpanded\def\tabl_x_TABLE_TH_stop_cell
+ {\stopxcell
+ \stopxcellgroup}
+
+\unexpanded\def\tabl_x_TABLE_setup_indeed[#settings]%
+ {\iffirstargument
+ \setupxtable[#settings]%
+ \fi}
+
+\unexpanded\def\tabl_x_TABLE_start_indeed[#settings]%
+ {\bgroup
+ \tabl_x_prepare{#settings}%
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process\zerocount}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua
new file mode 100644
index 00000000000..87d5fa12150
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua
@@ -0,0 +1,1273 @@
+if not modules then modules = { } end modules ['tabl-xtb'] = {
+ version = 1.001,
+ comment = "companion to tabl-xtb.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+
+This table mechanism is a combination between TeX and Lua. We do process
+cells at the TeX end and inspect them at the Lua end. After some analysis
+we have a second pass using the calculated widths, and if needed cells
+will go through a third pass to get the heights right. This last pass is
+avoided when possible which is why some code below looks a bit more
+complex than needed. The reason for such optimizations is that each cells
+is actually a framed instance and because tables like this can be hundreds
+of pages we want to keep processing time reasonable.
+
+To a large extend the behaviour is comparable with the way bTABLE/eTABLE
+works and there is a module that maps that one onto this one. Eventually
+this mechamism will be improved so that it can replace its older cousin.
+
+]]--
+
+-- todo: use linked list instead of r/c array
+-- todo: we can use the sum of previously forced widths for column spans
+
+local tonumber, next = tonumber, next
+
+local commands = commands
+local context = context
+local tex = tex
+
+local implement = interfaces.implement
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+local texgetdimen = tex.getdimen
+local texsetdimen = tex.setdimen
+local texget = tex.get
+
+local format = string.format
+local concat = table.concat
+local points = number.points
+
+local todimen = string.todimen
+
+local context_beginvbox = context.beginvbox
+local context_endvbox = context.endvbox
+local context_blank = context.blank
+local context_nointerlineskip = context.nointerlineskip
+local context_dummyxcell = context.dummyxcell
+
+local variables = interfaces.variables
+
+local setmetatableindex = table.setmetatableindex
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local nuts = nodes.nuts -- here nuts gain hardly nothing
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getlist = nuts.getlist
+local getfield = nuts.getfield
+local getbox = nuts.getbox
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+
+local copy_node_list = nuts.copy_list
+local hpack_node_list = nuts.hpack
+local flush_node_list = nuts.flush_list
+local takebox = nuts.takebox
+
+local nodepool = nuts.pool
+
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_penalty = nodepool.penalty
+local new_hlist = nodepool.hlist
+
+local v_stretch = variables.stretch
+local v_normal = variables.normal
+local v_width = variables.width
+local v_height = variables.height
+local v_repeat = variables["repeat"]
+local v_max = variables.max
+local v_fixed = variables.fixed
+local v_auto = variables.auto
+local v_before = variables.before
+local v_after = variables.after
+local v_both = variables.both
+local v_samepage = variables.samepage
+local v_tight = variables.tight
+
+local xtables = { }
+typesetters.xtables = xtables
+
+local trace_xtable = false
+local report_xtable = logs.reporter("xtable")
+
+trackers.register("xtable.construct", function(v) trace_xtable = v end)
+
+local null_mode = 0
+local head_mode = 1
+local foot_mode = 2
+local more_mode = 3
+local body_mode = 4
+
+local namedmodes = { [0] =
+ "null",
+ "head",
+ "foot",
+ "next",
+ "body",
+}
+
+local stack, data = { }, nil
+
+function xtables.create(settings)
+ table.insert(stack,data)
+ local rows = { }
+ local widths = { }
+ local heights = { }
+ local depths = { }
+ local spans = { }
+ local distances = { }
+ local autowidths = { }
+ local modes = { }
+ local fixedrows = { }
+ local fixedcolumns = { }
+ -- local fixedcspans = { }
+ local frozencolumns = { }
+ local options = { }
+ local rowproperties = { }
+ data = {
+ rows = rows,
+ widths = widths,
+ heights = heights,
+ depths = depths,
+ spans = spans,
+ distances = distances,
+ modes = modes,
+ autowidths = autowidths,
+ fixedrows = fixedrows,
+ fixedcolumns = fixedcolumns,
+ -- fixedcspans = fixedcspans,
+ frozencolumns = frozencolumns,
+ options = options,
+ nofrows = 0,
+ nofcolumns = 0,
+ currentrow = 0,
+ currentcolumn = 0,
+ settings = settings or { },
+ rowproperties = rowproperties,
+ }
+ local function add_zero(t,k)
+ t[k] = 0
+ return 0
+ end
+ local function add_table(t,k)
+ local v = { }
+ t[k] = v
+ return v
+ end
+ local function add_cell(row,c)
+ local cell = {
+ nx = 0,
+ ny = 0,
+ list = false,
+ wd = 0,
+ ht = 0,
+ dp = 0,
+ }
+ row[c] = cell
+ if c > data.nofcolumns then
+ data.nofcolumns = c
+ end
+ return cell
+ end
+ local function add_row(rows,r)
+ local row = { }
+ setmetatableindex(row,add_cell)
+ rows[r] = row
+ if r > data.nofrows then
+ data.nofrows = r
+ end
+ return row
+ end
+ setmetatableindex(rows,add_row)
+ setmetatableindex(widths,add_zero)
+ setmetatableindex(heights,add_zero)
+ setmetatableindex(depths,add_zero)
+ setmetatableindex(distances,add_zero)
+ setmetatableindex(modes,add_zero)
+ setmetatableindex(fixedrows,add_zero)
+ setmetatableindex(fixedcolumns,add_zero)
+ setmetatableindex(options,add_table)
+ -- setmetatableindex(fixedcspans,add_table)
+ --
+ local globaloptions = settings_to_hash(settings.option)
+ --
+ settings.columndistance = tonumber(settings.columndistance) or 0
+ settings.rowdistance = tonumber(settings.rowdistance) or 0
+ settings.leftmargindistance = tonumber(settings.leftmargindistance) or 0
+ settings.rightmargindistance = tonumber(settings.rightmargindistance) or 0
+ settings.options = globaloptions
+ settings.textwidth = tonumber(settings.textwidth) or texget("hsize")
+ settings.lineheight = tonumber(settings.lineheight) or texgetdimen("lineheight")
+ settings.maxwidth = tonumber(settings.maxwidth) or settings.textwidth/8
+ -- if #stack > 0 then
+ -- settings.textwidth = texget("hsize")
+ -- end
+ data.criterium_v = 2 * data.settings.lineheight
+ data.criterium_h = .75 * data.settings.textwidth
+ --
+ data.tight = globaloptions[v_tight] and true or false
+end
+
+function xtables.initialize_reflow_width(option,width)
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local drc = data.rows[r][c]
+ drc.nx = texgetcount("c_tabl_x_nx")
+ drc.ny = texgetcount("c_tabl_x_ny")
+ local distances = data.distances
+ local distance = texgetdimen("d_tabl_x_distance")
+ if distance > distances[c] then
+ distances[c] = distance
+ end
+ if option and option ~= "" then
+ local options = settings_to_hash(option)
+ data.options[r][c] = options
+ if options[v_fixed] then
+ data.frozencolumns[c] = true
+ end
+ end
+ data.currentcolumn = c
+end
+
+-- todo: we can better set the cell values in one go
+
+function xtables.set_reflow_width()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ local tb = getbox("b_tabl_x")
+ local drc = row[c]
+ --
+ drc.list = true -- we don't need to keep the content around as we're in trial mode (no: copy_node_list(tb))
+ --
+ local width = getfield(tb,"width")
+ local height = getfield(tb,"height")
+ local depth = getfield(tb,"depth")
+ --
+ local widths = data.widths
+ local heights = data.heights
+ local depths = data.depths
+ local cspan = drc.nx
+ if cspan < 2 then
+ if width > widths[c] then
+ widths[c] = width
+ end
+ else
+ local options = data.options[r][c]
+ if data.tight then
+ -- no check
+ elseif not options then
+ if width > widths[c] then
+ widths[c] = width
+ end
+ elseif not options[v_tight] then
+ if width > widths[c] then
+ widths[c] = width
+ end
+ end
+ end
+ -- if cspan > 1 then
+ -- local f = data.fixedcspans[c]
+ -- local w = f[cspan] or 0
+ -- if width > w then
+ -- f[cspan] = width -- maybe some day a solution for autospanmax and so
+ -- end
+ -- end
+ if drc.ny < 2 then
+ if height > heights[r] then
+ heights[r] = height
+ end
+ if depth > depths[r] then
+ depths[r] = depth
+ end
+ end
+ --
+ drc.wd = width
+ drc.ht = height
+ drc.dp = depth
+ --
+ local dimensionstate = texgetcount("frameddimensionstate")
+ local fixedcolumns = data.fixedcolumns
+ local fixedrows = data.fixedrows
+ if dimensionstate == 1 then
+ if cspan > 1 then
+ -- ignore width
+ elseif width > fixedcolumns[c] then -- how about a span here?
+ fixedcolumns[c] = width
+ end
+ elseif dimensionstate == 2 then
+ fixedrows[r] = height
+ elseif dimensionstate == 3 then
+ fixedrows[r] = height -- width
+ fixedcolumns[c] = width -- height
+ elseif width <= data.criterium_h and height >= data.criterium_v then
+ -- somewhat tricky branch
+ if width > fixedcolumns[c] then -- how about a span here?
+ -- maybe an image, so let's fix
+ fixedcolumns[c] = width
+ end
+ end
+--
+-- -- this fails so not good enough predictor
+--
+-- -- \startxtable
+-- -- \startxrow
+-- -- \startxcell knuth \stopxcell
+-- -- \startxcell \input knuth \stopxcell
+-- -- \stopxrow
+--
+-- else
+-- local o = data.options[r][c]
+-- if o and o[v_auto] then -- new per 5/5/2014 - removed per 15/07/2014
+-- data.autowidths[c] = true
+-- else
+-- -- no dimensions are set in the cell
+-- if width <= data.criterium_h and height >= data.criterium_v then
+-- -- somewhat tricky branch
+-- if width > fixedcolumns[c] then -- how about a span here?
+-- -- maybe an image, so let's fix
+-- fixedcolumns[c] = width
+-- end
+-- else
+-- -- safeguard as it could be text that can be recalculated
+-- -- and the previous branch could have happened in a previous
+-- -- row and then forces a wrong one-liner in a multiliner
+-- if width > fixedcolumns[c] then
+-- data.autowidths[c] = true -- new per 5/5/2014 - removed per 15/07/2014
+-- end
+-- end
+-- end
+-- end
+--
+ --
+ drc.dimensionstate = dimensionstate
+ --
+ local nx, ny = drc.nx, drc.ny
+ if nx > 1 or ny > 1 then
+ local spans = data.spans
+ local self = true
+ for y=1,ny do
+ for x=1,nx do
+ if self then
+ self = false
+ else
+ local ry = r + y - 1
+ local cx = c + x - 1
+ if y > 1 then
+ spans[ry] = true
+ end
+ rows[ry][cx].span = true
+ end
+ end
+ end
+ c = c + nx - 1
+ end
+ if c > data.nofcolumns then
+ data.nofcolumns = c
+ end
+ data.currentcolumn = c
+end
+
+function xtables.initialize_reflow_height()
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ data.currentcolumn = c
+ local widths = data.widths
+ local w = widths[c]
+ local drc = row[c]
+ for x=1,drc.nx-1 do
+ w = w + widths[c+x]
+ end
+ texsetdimen("d_tabl_x_width",w)
+ local dimensionstate = drc.dimensionstate or 0
+ if dimensionstate == 1 or dimensionstate == 3 then
+ -- width was fixed so height is known
+ texsetcount("c_tabl_x_skip_mode",1)
+ elseif dimensionstate == 2 then
+ -- height is enforced
+ texsetcount("c_tabl_x_skip_mode",1)
+ elseif data.autowidths[c] then
+ -- width has changed so we need to recalculate the height
+ texsetcount("c_tabl_x_skip_mode",0)
+ elseif data.fixedcolumns[c] then
+ texsetcount("c_tabl_x_skip_mode",0) -- new
+ else
+ texsetcount("c_tabl_x_skip_mode",1)
+ end
+end
+
+function xtables.set_reflow_height()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+ -- while row[c].span do -- we could adapt drc.nx instead
+ -- c = c + 1
+ -- end
+ local tb = getbox("b_tabl_x")
+ local drc = row[c]
+ --
+ local width = getfield(tb,"width")
+ local height = getfield(tb,"height")
+ local depth = getfield(tb,"depth")
+ --
+ if drc.ny < 2 then
+ if data.fixedrows[r] == 0 then -- and drc.dimensionstate < 2
+ local heights = data.heights
+ local depths = data.depths
+ if height > heights[r] then
+ heights[r] = height
+ end
+ if depth > depths[r] then
+ depths[r] = depth
+ end
+ end
+ end
+ --
+ drc.wd = width
+ drc.ht = height
+ drc.dp = depth
+ --
+ -- c = c + drc.nx - 1
+ -- data.currentcolumn = c
+end
+
+function xtables.initialize_construct()
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ data.currentcolumn = c
+ local widths = data.widths
+ local heights = data.heights
+ local depths = data.depths
+ --
+ local drc = row[c]
+ local wd = drc.wd
+ local ht = drc.ht
+ local dp = drc.dp
+ --
+ local width = widths[c]
+ local height = heights[r]
+ local depth = depths[r]
+ --
+ for x=1,drc.nx-1 do
+ width = width + widths[c+x]
+ end
+ --
+ local total = height + depth
+ local ny = drc.ny
+ if ny > 1 then
+ for y=1,ny-1 do
+ local nxt = r + y
+ total = total + heights[nxt] + depths[nxt]
+ end
+ end
+ --
+ texsetdimen("d_tabl_x_width",width)
+ texsetdimen("d_tabl_x_height",total)
+ texsetdimen("d_tabl_x_depth",0) -- for now
+end
+
+function xtables.set_construct()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+ -- while row[c].span do -- can also be previous row ones
+ -- c = c + 1
+ -- end
+ local drc = row[c]
+ -- this will change as soon as in luatex we can reset a box list without freeing
+ drc.list = takebox("b_tabl_x")
+ -- c = c + drc.nx - 1
+ -- data.currentcolumn = c
+end
+
+local function showwidths(where,widths,autowidths)
+ local result = { }
+ for i=1,#widths do
+ result[#result+1] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ")
+ end
+ return report_xtable("%s widths: %s",where,concat(result," "))
+end
+
+function xtables.reflow_width()
+ local nofrows = data.nofrows
+ local nofcolumns = data.nofcolumns
+ local rows = data.rows
+ for r=1,nofrows do
+ local row = rows[r]
+ for c=1,nofcolumns do
+ local drc = row[c]
+ if drc.list then
+ -- flush_node_list(drc.list)
+ drc.list = false
+ end
+ end
+ end
+ -- spread
+ local settings = data.settings
+ local options = settings.options
+ local maxwidth = settings.maxwidth
+ -- calculate width
+ local widths = data.widths
+ local heights = data.heights
+ local depths = data.depths
+ local distances = data.distances
+ local autowidths = data.autowidths
+ local fixedcolumns = data.fixedcolumns
+ local frozencolumns = data.frozencolumns
+ local width = 0
+ local distance = 0
+ local nofwide = 0
+ local widetotal = 0
+ local available = settings.textwidth - settings.leftmargindistance - settings.rightmargindistance
+ if trace_xtable then
+ showwidths("stage 1",widths,autowidths)
+ end
+ local noffrozen = 0
+ -- inspect(data.fixedcspans)
+ if options[v_max] then
+ for c=1,nofcolumns do
+ width = width + widths[c]
+ if width > maxwidth then
+ autowidths[c] = true
+ nofwide = nofwide + 1
+ widetotal = widetotal + widths[c]
+ end
+ if c < nofcolumns then
+ distance = distance + distances[c]
+ end
+ if frozencolumns[c] then
+ noffrozen = noffrozen + 1 -- brr, should be nx or so
+ end
+ end
+ else
+ for c=1,nofcolumns do -- also keep track of forced
+ local fixedwidth = fixedcolumns[c]
+ if fixedwidth > 0 then
+ widths[c] = fixedwidth
+ width = width + fixedwidth
+ else
+ local wc = widths[c]
+ width = width + wc
+ -- if width > maxwidth then
+ if wc > maxwidth then -- per 2015-08-09
+ autowidths[c] = true
+ nofwide = nofwide + 1
+ widetotal = widetotal + wc
+ end
+ end
+ if c < nofcolumns then
+ distance = distance + distances[c]
+ end
+ if frozencolumns[c] then
+ noffrozen = noffrozen + 1 -- brr, should be nx or so
+ end
+ end
+ end
+ if trace_xtable then
+ showwidths("stage 2",widths,autowidths)
+ end
+ local delta = available - width - distance - (nofcolumns-1) * settings.columndistance
+ if delta == 0 then
+ -- nothing to be done
+ if trace_xtable then
+ report_xtable("perfect fit")
+ end
+ elseif delta > 0 then
+ -- we can distribute some
+ if not options[v_stretch] then
+ -- not needed
+ if trace_xtable then
+ report_xtable("too wide but no stretch, delta %p",delta)
+ end
+ elseif options[v_width] then
+ local factor = delta / width
+ if trace_xtable then
+ report_xtable("proportional stretch, delta %p, width %p, factor %a",delta,width,factor)
+ end
+ for c=1,nofcolumns do
+ widths[c] = widths[c] + factor * widths[c]
+ end
+ else
+ -- frozen -> a column with option=fixed will not stretch
+ local extra = delta / (nofcolumns - noffrozen)
+ if trace_xtable then
+ report_xtable("normal stretch, delta %p, extra %p",delta,extra)
+ end
+ for c=1,nofcolumns do
+ if not frozencolumns[c] then
+ widths[c] = widths[c] + extra
+ end
+ end
+ end
+ elseif nofwide > 0 then
+ while true do
+ done = false
+ local available = (widetotal + delta) / nofwide
+ if trace_xtable then
+ report_xtable("shrink check, total %p, delta %p, columns %s, fixed %p",widetotal,delta,nofwide,available)
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] and available >= widths[c] then
+ autowidths[c] = nil
+ nofwide = nofwide - 1
+ widetotal = widetotal - widths[c]
+ done = true
+ end
+ end
+ if not done then
+ break
+ end
+ end
+ -- maybe also options[v_width] here but tricky as width does not say
+ -- much about amount
+ if options[v_width] then -- not that much (we could have a clever vpack loop balancing .. no fun)
+ local factor = (widetotal + delta) / width
+ if trace_xtable then
+ report_xtable("proportional shrink used, total %p, delta %p, columns %s, factor %s",widetotal,delta,nofwide,factor)
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] then
+ widths[c] = factor * widths[c]
+ end
+ end
+ else
+ local available = (widetotal + delta) / nofwide
+ if trace_xtable then
+ report_xtable("normal shrink used, total %p, delta %p, columns %s, fixed %p",widetotal,delta,nofwide,available)
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] then
+ widths[c] = available
+ end
+ end
+ end
+ end
+ if trace_xtable then
+ showwidths("stage 3",widths,autowidths)
+ end
+ --
+ data.currentrow = 0
+ data.currentcolumn = 0
+ --
+-- inspect(data)
+end
+
+function xtables.reflow_height()
+ data.currentrow = 0
+ data.currentcolumn = 0
+ local settings = data.settings
+ --
+ -- analyze ny
+ --
+ local nofrows = data.nofrows
+ local nofcolumns = data.nofcolumns
+ local widths = data.widths
+ local heights = data.heights
+ local depths = data.depths
+ --
+ for r=1,nofrows do
+ for c=1,nofcolumns do
+ local drc = data.rows[r][c]
+ if drc then
+ local ny = drc.ny
+ if ny > 1 then
+ local height = heights[r]
+ local depth = depths[r]
+ local total = height + depth
+ local htdp = drc.ht + drc.dp
+ for y=1,ny-1 do
+ local nxt = r + y
+ total = total + heights[nxt] + depths[nxt]
+ end
+ local delta = htdp - total
+ if delta > 0 then
+ delta = delta / ny
+ for y=0,ny-1 do
+ local nxt = r + y
+ heights[nxt] = heights[nxt] + delta
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ if settings.options[v_height] then
+ local totalheight = 0
+ local totaldepth = 0
+ for i=1,nofrows do
+ totalheight = totalheight + heights[i]
+ totalheight = totalheight + depths [i]
+ end
+ local total = totalheight + totaldepth
+ local leftover = settings.textheight - total
+ if leftover > 0 then
+ local leftheight = (totalheight / total) * leftover / #heights
+ local leftdepth = (totaldepth / total) * leftover / #depths
+ for i=1,nofrows do
+ heights[i] = heights[i] + leftheight
+ depths [i] = depths [i] + leftdepth
+ end
+ end
+ end
+ --
+-- inspect(data)
+end
+
+local function showspans(data)
+ local rows = data.rows
+ local modes = data.modes
+ local nofcolumns = data.nofcolumns
+ local nofrows = data.nofrows
+ for r=1,nofrows do
+ local line = { }
+ local row = rows[r]
+ for c=1,nofcolumns do
+ local cell =row[c]
+ if cell.list then
+ line[#line+1] = "list"
+ elseif cell.span then
+ line[#line+1] = "span"
+ else
+ line[#line+1] = "none"
+ end
+ end
+ report_xtable("%3d : %s : % t",r,namedmodes[modes[r]] or "----",line)
+ end
+end
+
+function xtables.construct()
+ local rows = data.rows
+ local heights = data.heights
+ local depths = data.depths
+ local widths = data.widths
+ local spans = data.spans
+ local distances = data.distances
+ local modes = data.modes
+ local settings = data.settings
+ local nofcolumns = data.nofcolumns
+ local nofrows = data.nofrows
+ local columndistance = settings.columndistance
+ local rowdistance = settings.rowdistance
+ local leftmargindistance = settings.leftmargindistance
+ local rightmargindistance = settings.rightmargindistance
+ local rowproperties = data.rowproperties
+ -- ranges can be mixes so we collect
+
+ if trace_xtable then
+ showspans(data)
+ end
+
+ local ranges = {
+ [head_mode] = { },
+ [foot_mode] = { },
+ [more_mode] = { },
+ [body_mode] = { },
+ }
+ for r=1,nofrows do
+ local m = modes[r]
+ if m == 0 then
+ m = body_mode
+ end
+ local range = ranges[m]
+ range[#range+1] = r
+ end
+ -- todo: hook in the splitter ... the splitter can ask for a chunk of
+ -- a certain size ... no longer a split memory issue then and header
+ -- footer then has to happen here too .. target height
+ local function packaged_column(r)
+ local row = rows[r]
+ local start = nil
+ local stop = nil
+ if leftmargindistance > 0 then
+ start = new_kern(leftmargindistance)
+ stop = start
+ end
+ local hasspan = false
+ for c=1,nofcolumns do
+ local drc = row[c]
+ if not hasspan then
+ hasspan = drc.span
+ end
+ local list = drc.list
+ if list then
+ setfield(list,"shift",getfield(list,"height") + getfield(list,"depth"))
+ -- list = hpack_node_list(list) -- is somehow needed
+ -- setfield(list,"width",0)
+ -- setfield(list,"height",0)
+ -- setfield(list,"depth",0)
+ -- faster:
+ local h = new_hlist(list)
+ list = h
+ --
+ if start then
+ setlink(stop,list)
+ else
+ start = list
+ end
+ stop = list
+ end
+ local step = widths[c]
+ if c < nofcolumns then
+ step = step + columndistance + distances[c]
+ end
+ local kern = new_kern(step)
+ if stop then
+ setlink(stop,kern)
+ else -- can be first spanning next row (ny=...)
+ start = kern
+ end
+ stop = kern
+ end
+ if start then
+ if rightmargindistance > 0 then
+ local kern = new_kern(rightmargindistance)
+ setlink(stop,kern)
+ -- stop = kern
+ end
+ return start, heights[r] + depths[r], hasspan
+ end
+ end
+ local function collect_range(range)
+ local result, nofr = { }, 0
+ local nofrange = #range
+ for i=1,#range do
+ local r = range[i]
+ -- local row = rows[r]
+ local list, size, hasspan = packaged_column(r)
+ if list then
+ if hasspan and nofr > 0 then
+ result[nofr][4] = true
+ end
+ nofr = nofr + 1
+ local rp = rowproperties[r]
+ -- 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)
+ setfield(hbox,"dir","TLT")
+ result[nofr] = {
+ hbox,
+ size,
+ i < nofrange and rowdistance > 0 and rowdistance or false, -- might move
+ false,
+ rp and rp.samepage or false,
+ }
+ end
+ end
+ if nofr > 0 then
+ -- the [5] slot gets the after break
+ result[1] [5] = false
+ result[nofr][5] = false
+ for i=2,nofr-1 do
+ local r = result[i]
+ if r == v_both or r == v_before then
+ result[i-1][5] = true
+ elseif r == v_after then
+ result[i][5] = true
+ end
+ end
+ end
+ return result
+ end
+ local body = collect_range(ranges[body_mode])
+ data.results = {
+ [head_mode] = collect_range(ranges[head_mode]),
+ [foot_mode] = collect_range(ranges[foot_mode]),
+ [more_mode] = collect_range(ranges[more_mode]),
+ [body_mode] = body,
+ }
+ if #body == 0 then
+ texsetcount("global","c_tabl_x_state",0)
+ texsetdimen("global","d_tabl_x_final_width",0)
+ else
+ texsetcount("global","c_tabl_x_state",1)
+ texsetdimen("global","d_tabl_x_final_width",getfield(body[1][1],"width"))
+ end
+end
+
+-- todo: join as that is as efficient as fushing multiple
+
+local function inject(row,copy,package)
+ local list = row[1]
+ if copy then
+ row[1] = copy_node_list(list)
+ end
+ if package then
+ context_beginvbox()
+ context(tonode(list))
+ context(tonode(new_kern(row[2])))
+ context_endvbox()
+ context_nointerlineskip() -- figure out a better way
+ if row[4] then
+ -- nothing as we have a span
+ elseif row[5] then
+ if row[3] then
+ context_blank { v_samepage, row[3] .. "sp" }
+ else
+ context_blank { v_samepage }
+ end
+ elseif row[3] then
+ context_blank { row[3] .. "sp" } -- why blank ?
+ else
+ context(tonode(new_glue(0)))
+ end
+ else
+ context(tonode(list))
+ context(tonode(new_kern(row[2])))
+ if row[3] then
+ context(tonode(new_glue(row[3])))
+ end
+ end
+end
+
+local function total(row,distance)
+ local n = #row > 0 and rowdistance or 0
+ for i=1,#row do
+ local ri = row[i]
+ n = n + ri[2] + (ri[3] or 0)
+ end
+ return n
+end
+
+-- local function append(list,what)
+-- for i=1,#what do
+-- local l = what[i]
+-- list[#list+1] = l[1]
+-- local k = l[2] + (l[3] or 0)
+-- if k ~= 0 then
+-- list[#list+1] = new_kern(k)
+-- end
+-- end
+-- end
+
+local function spanheight(body,i)
+ local height, n = 0, 1
+ while true do
+ local bi = body[i]
+ if bi then
+ height = height + bi[2] + (bi[3] or 0)
+ if bi[4] then
+ n = n + 1
+ i = i + 1
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ return height, n
+end
+
+function xtables.flush(directives) -- todo split by size / no inbetween then .. glue list kern blank
+ local height = directives.height
+ local method = directives.method or v_normal
+ local settings = data.settings
+ local results = data.results
+ local rowdistance = settings.rowdistance
+ local head = results[head_mode]
+ local foot = results[foot_mode]
+ local more = results[more_mode]
+ local body = results[body_mode]
+ local repeatheader = settings.header == v_repeat
+ local repeatfooter = settings.footer == v_repeat
+ if height and height > 0 then
+ context_beginvbox()
+ local bodystart = data.bodystart or 1
+ local bodystop = data.bodystop or #body
+ if bodystart > 0 and bodystart <= bodystop then
+ local bodysize = height
+ local footsize = total(foot,rowdistance)
+ local headsize = total(head,rowdistance)
+ local moresize = total(more,rowdistance)
+ local firstsize, firstspans = spanheight(body,bodystart)
+ if bodystart == 1 then -- first chunk gets head
+ bodysize = bodysize - headsize - footsize
+ if headsize > 0 and bodysize >= firstsize then
+ for i=1,#head do
+ inject(head[i],repeatheader)
+ end
+ if rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ if not repeatheader then
+ results[head_mode] = { }
+ end
+ end
+ elseif moresize > 0 then -- following chunk gets next
+ bodysize = bodysize - footsize - moresize
+ if bodysize >= firstsize then
+ for i=1,#more do
+ inject(more[i],true)
+ end
+ if rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ end
+ elseif headsize > 0 and repeatheader then -- following chunk gets head
+ bodysize = bodysize - footsize - headsize
+ if bodysize >= firstsize then
+ for i=1,#head do
+ inject(head[i],true)
+ end
+ if rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ end
+ else -- following chunk gets nothing
+ bodysize = bodysize - footsize
+ end
+ if bodysize >= firstsize then
+ local i = bodystart
+ while i <= bodystop do -- room for improvement
+ local total, spans = spanheight(body,i)
+ local bs = bodysize - total
+ if bs > 0 then
+ bodysize = bs
+ for s=1,spans do
+ inject(body[i])
+ body[i] = nil
+ i = i + 1
+ end
+ bodystart = i
+ else
+ break
+ end
+ end
+ if bodystart > bodystop then
+ -- all is flushed and footer fits
+ if footsize > 0 then
+ if rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ for i=1,#foot do
+ inject(foot[i])
+ end
+ results[foot_mode] = { }
+ end
+ results[body_mode] = { }
+ texsetcount("global","c_tabl_x_state",0)
+ else
+ -- some is left so footer is delayed
+ -- todo: try to flush a few more lines
+ if repeatfooter and footsize > 0 then
+ if rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ for i=1,#foot do
+ inject(foot[i],true)
+ end
+ else
+ -- todo: try to fit more of body
+ end
+ texsetcount("global","c_tabl_x_state",2)
+ end
+ else
+ if firstsize > height then
+ -- get rid of the too large cell
+ for s=1,firstspans do
+ inject(body[bodystart])
+ body[bodystart] = nil
+ bodystart = bodystart + 1
+ end
+ end
+ texsetcount("global","c_tabl_x_state",2) -- 1
+ end
+ else
+ texsetcount("global","c_tabl_x_state",0)
+ end
+ data.bodystart = bodystart
+ data.bodystop = bodystop
+ context_endvbox()
+ else
+ if method == variables.split then
+ -- maybe also a non float mode with header/footer repeat although
+ -- we can also use a float without caption
+ for i=1,#head do
+ inject(head[i],false,true)
+ end
+ if #head > 0 and rowdistance > 0 then
+ context_blank { rowdistance .. "sp" }
+ end
+ for i=1,#body do
+ inject(body[i],false,true)
+ end
+ if #foot > 0 and rowdistance > 0 then
+ context_blank { rowdistance .. "sp" }
+ end
+ for i=1,#foot do
+ inject(foot[i],false,true)
+ end
+ else -- normal
+ context_beginvbox()
+ for i=1,#head do
+ inject(head[i])
+ end
+ if #head > 0 and rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ for i=1,#body do
+ inject(body[i])
+ end
+ if #foot > 0 and rowdistance > 0 then
+ context(tonode(new_glue(rowdistance)))
+ end
+ for i=1,#foot do
+ inject(foot[i])
+ end
+ context_endvbox()
+ end
+ results[head_mode] = { }
+ results[body_mode] = { }
+ results[foot_mode] = { }
+ texsetcount("global","c_tabl_x_state",0)
+ end
+end
+
+function xtables.cleanup()
+ for mode, result in next, data.results do
+ for _, r in next, result do
+ flush_node_list(r[1])
+ end
+ end
+
+ -- local rows = data.rows
+ -- for i=1,#rows do
+ -- local row = rows[i]
+ -- for i=1,#row do
+ -- local cell = row[i]
+ -- local list = cell.list
+ -- if list then
+ -- cell.width = getfield(list,"width")
+ -- cell.height = getfield(list,"height")
+ -- cell.depth = getfield(list,"depth")
+ -- cell.list = true
+ -- end
+ -- end
+ -- end
+ -- data.result = nil
+ -- inspect(data)
+
+ data = table.remove(stack)
+end
+
+function xtables.next_row(specification)
+ local r = data.currentrow + 1
+ data.modes[r] = texgetcount("c_tabl_x_mode")
+ data.currentrow = r
+ data.currentcolumn = 0
+ data.rowproperties[r] = specification
+end
+
+function xtables.finish_row()
+ local n = data.nofcolumns - data.currentcolumn
+ if n > 0 then
+ -- message
+ for i=1,n do
+ context_dummyxcell()
+ end
+ end
+end
+
+-- eventually we might only have commands
+
+implement {
+ name = "x_table_create",
+ actions = xtables.create,
+ arguments = {
+ {
+ { "option" },
+ { "textwidth", "dimen" },
+ { "textheight", "dimen" },
+ { "maxwidth", "dimen" },
+ { "lineheight", "dimen" },
+ { "columndistance", "dimen" },
+ { "leftmargindistance", "dimen" },
+ { "rightmargindistance", "dimen" },
+ { "rowdistance", "dimen" },
+ { "header" },
+ { "footer" },
+ }
+ }
+}
+
+implement {
+ name = "x_table_flush",
+ actions = xtables.flush,
+ arguments = {
+ {
+ { "method" },
+ { "height", "dimen" }
+ }
+ }
+}
+
+implement { name = "x_table_reflow_width", actions = xtables.reflow_width }
+implement { name = "x_table_reflow_height", actions = xtables.reflow_height }
+implement { name = "x_table_construct", actions = xtables.construct }
+implement { name = "x_table_cleanup", actions = xtables.cleanup }
+implement { name = "x_table_next_row", actions = xtables.next_row }
+implement { name = "x_table_next_row_option", actions = xtables.next_row, arguments = "string" }
+implement { name = "x_table_finish_row", actions = xtables.finish_row }
+implement { name = "x_table_init_reflow_width", actions = xtables.initialize_reflow_width }
+implement { name = "x_table_init_reflow_height", actions = xtables.initialize_reflow_height }
+implement { name = "x_table_init_reflow_width_option", actions = xtables.initialize_reflow_width, arguments = "string" }
+implement { name = "x_table_init_reflow_height_option", actions = xtables.initialize_reflow_height, arguments = "string" }
+implement { name = "x_table_init_construct", actions = xtables.initialize_construct }
+implement { name = "x_table_set_reflow_width", actions = xtables.set_reflow_width }
+implement { name = "x_table_set_reflow_height", actions = xtables.set_reflow_height }
+implement { name = "x_table_set_construct", actions = xtables.set_construct }
+implement { name = "x_table_r", actions = function() context(data.currentrow or 0) end }
+implement { name = "x_table_c", actions = function() context(data.currentcolumn or 0) end }
+
+-- experiment:
+
+do
+
+ local context = context
+
+ local startxtable = context.startxtable
+ local stopxtable = context.stopxtable
+
+ local startcollecting = context.startcollecting
+ local stopcollecting = context.stopcollecting
+
+ function context.startxtable(...)
+ startcollecting()
+ startxtable(...)
+ end
+
+ function context.stopxtable()
+ stopxtable()
+ stopcollecting()
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi
new file mode 100644
index 00000000000..851b6e80f84
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi
@@ -0,0 +1,810 @@
+% macros=mkvi
+
+%D \module
+%D [ file=tabl-xtb,
+%D version=2011.10.26,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Xtreme,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Xtreme}
+
+\registerctxluafile{tabl-xtb}{1.001}
+
+% todo:
+%
+% - yes or no: foregroundstyle/color <- style/color
+% - template alignment
+% - maybe split horizontal (a la linetables)
+% - before/after and wrapping (linecorrection)
+% - maybe also some before/after commands
+% - maybe correction when non float usage
+% - tagging needs to be checked
+% - maybe only tag the box
+% - scale to fit
+%
+% - buffers permit verbatim but are not always handy
+
+%D This module started as an afternoon experiment and surprisingly could be
+%D mostly finished the same evening. Of course it builds upon existing
+%D functionality. The main reason for writing it is that we occasionally
+%D run into pretty large tables that take tens of pages and need to be split
+%D into floats. Speed is one issue there, avoiding to use vsplit is another.
+%D
+%D \starttyping
+%D \definextable [tag] | [tag][parent]
+%D \setupxtable [settings] | [tag][settings]
+%D
+%D \startxtable[tag|settings]
+%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot
+%D \startxrowgroup[tag|settings]
+%D \startxrow[settings]
+%D \startxcellgroup[tag|settings]
+%D \startxcell[settings] ... \stopxcell
+%D \stopxcellgroup
+%D \stopxrow
+%D \startxrowgroup
+%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot
+%D \stopxtable
+%D \stoptyping
+%D
+%D See xtables-001.tex etc for some examples.
+
+% We can avoid some checking by using the fastoptionalcheckcs helpers
+% instead of dosingleempty but the speed gain is neglectable.
+
+\unprotect
+
+% option=stretch : equal distribution
+% option={stretch,width} : proportional distribution
+% option={max} : prefer max over forced width/height
+%
+% cells: option=fixed : nils autostretch (not yet complete)
+
+% \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute {...}
+%
+% \let\tsplitbeforeresult\donothing
+% \let\tsplitafterresult \donothing
+% \let\tsplitinbetween \donothing
+% \let\tsplitbefore \donothing
+% \let\tsplitafter \donothing
+% \let\postprocesstsplit \donothing
+
+\let\dotagxtablecell \relax % names will change
+\let\dotagxtablesignal\relax % names will change
+
+\appendtoks
+ \def\dotagxtablecell
+ {\clf_settagtablecell
+ \numexpr\tablecellrows\relax
+ \numexpr\tablecellcolumns\relax
+ \numexpr\raggedstatus\relax}%
+ \def\dotagxtablesignal
+ {\signalcharacter}% not used
+\to \everyenableelements
+
+\newdimen\d_tabl_x_width
+\newdimen\d_tabl_x_height
+\newdimen\d_tabl_x_depth % not used
+\newdimen\d_tabl_x_distance
+\newcount\c_tabl_x_nx
+\newcount\c_tabl_x_ny
+\newcount\c_tabl_x_mode
+\newbox \b_tabl_x
+\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft
+\newdimen\d_tabl_x_final_width
+\newcount\c_tabl_x_nesting
+\newcount\c_tabl_x_skip_mode % 1 = skip
+\newdimen\d_tabl_x_textwidth
+
+\let\currentxtablerow \clf_x_table_r
+\let\currentxtablecolumn\clf_x_table_c
+
+% \setupxtable[one][parent][a=b,c=d]
+% \setupxtable[one] [a=b,c=d]
+% \setupxtable [a=b,c=d]
+
+\installcorenamespace{xtable}
+\installcorenamespace{xtablecheck}
+
+\installframedautocommandhandler \??xtable {xtable} \??xtable
+
+\appendtoks
+ \checkxtableparent % so we can deal with undefined settings, not that it's efficient
+\to \everysetupxtable
+
+\setupxtable[%
+ \c!nr=\plusone,
+ \c!nc=\plusone,
+ \c!nx=\plusone, % slow
+ \c!ny=\plusone, % slow
+ \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE
+ \c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ % \c!framecolor=\s!black,
+ % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere
+ % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere
+ % \c!bodyfont=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!maxwidth=8\emwidth,
+ \c!autowidth=\v!yes, % controls framed
+ \c!rulethickness=\linewidth,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!no,
+ \c!split=\v!auto, % a number will take that many lines
+ \c!splitoffset=\zeropoint, % extra space taken
+ % \c!aligncharacter=\v!no,
+ % \c!alignmentcharacter={,},
+ % \c!option=, % \v!stretch {\v!stretch,\v!width}
+ % \c!footer=,
+ % \c!header=,
+ \c!spaceinbetween=,
+ \c!textwidth=\v!local, % was \hsize,
+ \c!textheight=\vsize, % used for vertical spread
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+]
+
+\unexpanded\def\startxtable
+ {\dosingleempty\tabl_x_start_table}
+
+\let\stopxtable\relax
+
+\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting}
+\let\tabl_x_current_buffer\empty
+
+\unexpanded\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings]
+ {\bgroup
+ \tabl_x_prepare{#settings}%
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process\zerocount}
+
+\unexpanded\def\processxtablebuffer
+ {\dosingleempty\tabl_x_process_buffer_directly}
+
+% These direct buffers can be somewhat faster but it's probably neglectable.
+% Anyway, no nesting is supported as we then need to catch (e.g.) rows and
+% keep track of nesting and have a more complex redefinition of nested
+% instanced \unknown\ it's not worth the trouble. Only use them when you
+% really need them and use the embeddedxtable command when nesting them.
+% Implementing nesting would be slower than not using direct buffers.
+
+\unexpanded\def\tabl_x_process_buffer_directly[#name]%
+ {\bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{#name}%
+ \tabl_x_get_buffer % settings
+ \tabl_x_process}
+
+\unexpanded\def\tabl_x_start_ignore[#settings]%
+ {}
+
+\unexpanded\def\tabl_x_process_buffer[#settings]%
+ {\tabl_x_prepare{#settings}%
+ \let\tabl_x_start_table\tabl_x_start_ignore
+ \gobbleuntil\stopxtable} % nested xtables are not supported,
+
+%D A bonus: you have to use the following construct inside a macro or
+%D direct buffer.
+
+\unexpanded\def\startembeddedxtable
+ {\dosingleempty\tabl_x_embedded_start}
+
+\unexpanded\def\tabl_x_embedded_start[#settings]#content\stopembeddedxtable
+ {\tabl_x_prepare{#settings}%
+ \clf_assignbuffer{embedded_x_table}{\detokenize{#content}}\catcodetable\relax
+ \bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{embedded_x_table}%
+ \tabl_x_process}
+
+\let\stopembeddedxtable\relax
+
+%D We can also define xtables.
+
+\appendtoks
+ \setuevalue{\e!start\currentxtable}{\tabl_x_start_named{\currentxtable}}%
+ \setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}%
+\to \everydefinextable
+
+\unexpanded\def\tabl_x_start_named#tag%
+ {\bgroup
+ \edef\currentxtable{#tag}%
+ \dosingleempty\tabl_x_start_named_indeed}
+
+\unexpanded\def\tabl_x_start_named_indeed[#settings]%
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttaggedchained\t!table\empty\??xtable
+ \iffirstargument
+ \setupcurrentxtable[#settings]%
+ \fi
+ \tabl_x_check_textwidth
+ %\forgetall % else whitespace mess
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process\zerocount}}
+
+\unexpanded\def\tabl_x_stop_named
+ {}
+
+%D Now we come to processing:
+
+\unexpanded\def\tabl_x_check_textwidth
+ {\edef\p_textwidth{\xtableparameter\c!textwidth}%
+ \ifx\p_textwidth\v!local
+ \d_tabl_x_textwidth\availablehsize
+ \else
+ \d_tabl_x_textwidth\p_textwidth
+ \fi}
+
+\unexpanded\def\tabl_x_prepare#settings% assumes \iffirstargument to be set
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttaggedchained\t!table\empty\??xtable
+ \iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi
+ \tabl_x_check_textwidth
+ }% else whitespace mess
+
+\def\tabl_x_get_buffer
+ {\clf_gettexbuffer{\tabl_x_current_buffer}}
+
+\let\tabl_x_start_row_yes \relax
+\let\tabl_x_start_row_nop \relax
+\let\tabl_x_stop_row \relax
+\let\tabl_x_start_cell_yes\relax
+\let\tabl_x_start_cell_nop\relax
+\let\tabl_x_stop_cell \relax
+
+\unexpanded\def\tabl_x_process
+ {\begingroup % *
+ \forgetall % moved here
+ \dontcomplain % for the moment here till we figure out where we get the overflow
+ \usebodyfontparameter\xtableparameter
+ \setbox\scratchbox\vbox
+ {\doifsomething{\xtableparameter\c!spaceinbetween}{\blank[\xtableparameter\c!spaceinbetween]}}%
+ \clf_x_table_create
+ option {\xtableparameter\c!option}%
+ textwidth \d_tabl_x_textwidth
+ textheight \dimexpr\xtableparameter\c!textheight\relax
+ maxwidth \dimexpr\xtableparameter\c!maxwidth\relax
+ lineheight \openlineheight
+ columndistance \dimexpr\xtableparameter\c!columndistance\relax
+ leftmargindistance \dimexpr\xtableparameter\c!leftmargindistance\relax
+ rightmargindistance \dimexpr\xtableparameter\c!rightmargindistance\relax
+ rowdistance \ht\scratchbox
+ header {\xtableparameter\c!header}%
+ footer {\xtableparameter\c!footer}%
+ \relax
+ %
+ \letxtableparameter\c!option\empty
+ % not so nice but needed as we use this in the setup
+ \linewidth\xtableparameter\c!rulethickness\relax
+ % so we freeze it
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width
+ \settrialtypesetting
+ \tabl_x_get_buffer
+ \clf_x_table_reflow_width
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height
+ \settrialtypesetting
+ \tabl_x_get_buffer
+ \clf_x_table_reflow_height
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_construct
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_construct
+ \tabl_x_get_buffer
+ \clf_x_table_construct
+ \endgroup
+ \endgroup % *
+ \ifinsidesplitfloat
+ \tabl_x_flush_float_split
+ \else\ifinsidefloat
+ \tabl_x_flush_float_normal
+ \else
+ \tabl_x_flush_text_checked
+ \fi\fi
+ \clf_x_table_cleanup
+ \dostoptagged
+ \resetbuffer[\tabl_x_current_buffer]%
+ \egroup}
+
+% text flow split modes
+
+\installcorenamespace{xtableflushsplit}
+
+\unexpanded\def\tabl_x_flush_text_checked
+ {\expandnamespaceparameter\??xtableflushsplit\xtableparameter\c!split\v!no}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!yes}%
+ {\clf_x_table_flush
+ method {\v!split}%
+ \relax}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!no}%
+ {% \noindent % gives extra line after table
+ % \noindentation % messes up the next indentation
+ % \dontleavehmode % no leftskip
+ \kern\zeropoint % yet another guess
+ \ignorespaces
+ \clf_x_table_flush
+ method {\v!normal}%
+ \relax
+ \removeunwantedspaces}
+
+% in text flow: headers and footers get repeated
+
+\setvalue{\??xtableflushsplit\v!repeat}%
+ {\doloop
+ {\clf_x_table_flush
+ method {\v!split}%
+ height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi
+ \relax
+ \ifcase\c_tabl_x_state
+ \exitloop
+ \else
+ \page
+ \fi}}
+
+% \setvalue{\??xtableflushsplit\v!setups}%
+% {\directsetup{xtable:split:user}}
+%
+% \startsetups[xtable:split:user]
+% \doloop {
+% \xtablesplitflush % uses \xtablesplitvsize (a macro)
+% \ifcase\xtablesplitstate
+% \exitloop
+% \else
+% \page
+% \fi
+% }
+% \stopsetups
+%
+% \unexpanded\def\xtablesplitflush
+% {\clf_x_table_flush
+% method {\v!split}%
+% height \dimexpr\xtablesplitvsize\relax
+% \relax}
+%
+% \def\xtablesplitvsize
+% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi}
+%
+% \let\xtablesplitstate\c_tabl_x_state
+
+\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it
+
+\unexpanded\def\tabl_x_flush_float_normal
+ {\clf_x_table_flush
+ method {\v!normal}%
+ \relax}
+
+\unexpanded\def\tabl_x_flush_float_split
+ {\resetdirecttsplit
+ \edef\extrasplitfloatlines {\xtableparameter\c!split}%
+ \edef\tsplitminimumfreespace{\the\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax}%
+ % \edef\tsplitminimumfreelines{2}% not needed here as we're precise enough
+ \let\tsplitdirectsplitter\tabl_x_split_splitter
+ \let\tsplitdirectwidth \d_tabl_x_final_width
+ \handledirecttsplit}
+
+\unexpanded\def\tabl_x_split_splitter#height%
+ {\setbox\tsplitresult\vbox
+ {\clf_x_table_flush
+ method {\v!split}%
+ height \dimexpr#height\relax
+ \relax}%
+ \ifcase\c_tabl_x_state
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \fi}
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\unexpanded\def\tabl_x_start_row_reflow_width_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \clf_x_table_next_row}
+
+\unexpanded\def\tabl_x_start_row_reflow_width_nop
+ {\clf_x_table_next_row}
+
+\unexpanded\def\tabl_x_stop_row_reflow_width
+ {}
+
+\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes
+\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop
+\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width
+
+\unexpanded\def\tabl_x_start_row_construct_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \dostarttagged\t!tablerow\empty
+ \clf_x_table_next_row_option{\xtableparameter\c!samepage}}
+
+\unexpanded\def\tabl_x_start_row_construct_nop
+ {\dostarttagged\t!tablerow\empty
+ \clf_x_table_next_row}
+
+\unexpanded\def\tabl_x_stop_row_construct
+ {\clf_x_table_finish_row
+ \dostoptagged}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\unexpanded\def\startxcell
+ {\doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\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}
+
+\unexpanded\def\tabl_x_begin_of_cell
+ {%\inhibitblank % already in framed
+ \everypar{\delayedbegstrut}}
+
+\unexpanded\def\tabl_x_end_of_cell
+ {\ifhmode
+ \delayedendstrut
+ \par
+ \else
+ \par
+ \ifdim\prevdepth<\zeropoint % =-1000pt ?
+ \vskip-\strutdp
+ \else
+ \removebottomthings
+ \fi
+ \fi}
+
+% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes
+% obsolete some day. The let as well as the direct speed things up a bit. We
+% could also consider a \defaultxtableparameter.
+%
+% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone}
+% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone}
+%
+% Although this becomes kind of messy. It saves already time that we only check
+% for it when we have settings.
+
+% \def\tabl_x_set_hsize
+% {\hsize.25\maxdimen} % let's be reasonable
+
+% \def\tabl_x_set_hsize
+% {\edef\p_width{\xtableparameter\c!width}%
+% \ifx\p_width\empty
+% \hsize.25\maxdimen % is this really needed
+% \fi}
+
+\let\tabl_x_set_hsize\relax
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ %
+ \letxtableparameter\c!nx\plusone
+ \letxtableparameter\c!ny\plusone
+ \letxtableparameter\c!nc\plusone
+ \letxtableparameter\c!nr\plusone
+ %
+ \setupcurrentxtable[#settings]%
+ %
+ \c_tabl_x_nx\directxtableparameter\c!nc\relax
+ \c_tabl_x_ny\directxtableparameter\c!nr\relax
+ \ifnum\c_tabl_x_nx=\plusone
+ \c_tabl_x_nx\directxtableparameter\c!nx\relax
+ \fi
+ \ifnum\c_tabl_x_ny=\plusone
+ \c_tabl_x_ny\directxtableparameter\c!ny\relax
+ \fi
+ %
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \clf_x_table_init_reflow_width_option{\xtableparameter\c!option}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_nop
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \c_tabl_x_nx\plusone
+ \c_tabl_x_ny\plusone
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \clf_x_table_init_reflow_width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_width
+ {\tabl_x_end_of_cell
+ \egroup
+ \egroup
+ \clf_x_table_set_reflow_width}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\bgroup
+ \clf_x_table_init_reflow_height
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \setupcurrentxtable[#settings]%
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_nop
+ {\setbox\b_tabl_x\hbox\bgroup
+ \clf_x_table_init_reflow_height
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_height
+ {\ifcase\c_tabl_x_skip_mode
+ \tabl_x_end_of_cell
+ \egroup
+ \fi
+ \egroup
+ \clf_x_table_set_reflow_height}
+
+\unexpanded\def\tabl_x_start_cell_construct_yes[#settings]%
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \setupcurrentxtable[#settings]%
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \clf_x_table_init_construct
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_start_cell_construct_nop
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height (commenting it ... nice option)
+ \clf_x_table_init_construct
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_stop_cell_construct
+ {\tabl_x_end_of_cell
+ \egroup
+ \dotagxtablesignal % harmless spot
+ \egroup
+ \clf_x_table_set_construct
+ \dostoptagged}
+
+\unexpanded\def\startxcellgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_cell_group}
+
+\unexpanded\def\stopxcellgroup
+ {\endgroup}
+
+\unexpanded\def\tabl_x_start_cell_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\startxrowgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_row_group}
+
+\unexpanded\def\stopxrowgroup
+ {\dostoptagged
+ \endgroup}
+
+\unexpanded\def\tabl_x_start_row_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+% \def\tabl_x_set_checked#settings
+% {\doifassignmentelse{#settings}
+% {\setupcurrentxtable[#settings]}
+% {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+% \edef\currentxtable{#settings}%
+% \fi}}
+
+\unexpanded\def\tabl_x_set_checked#settings%
+ {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+ \edef\currentxtable{#settings}%
+ \else
+ \setupcurrentxtable[#settings]%
+ \fi}
+
+\unexpanded\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \dosingleempty\tabl_x_start_partition}
+
+\unexpanded\def\tabl_x_start_partition[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\tabl_x_stop_partition
+ {\endgroup}
+
+\let\stopxtablehead\tabl_x_stop_partition
+\let\stopxtablefoot\tabl_x_stop_partition
+\let\stopxtablenext\tabl_x_stop_partition
+\let\stopxtablebody\tabl_x_stop_partition
+
+%D This is an experiment! Beware: you can create loops by using nested
+%D references to already chained settings.
+%D
+%D \startbuffer
+%D \setupxtable[suffix][align=middle,foregroundcolor=red]
+%D \setupxtable[blabla][foregroundstyle=slanted]
+%D \setupxtable[crap] [foregroundcolor=blue]
+%D \setupxtable[bold] [crap][foregroundstyle=bold]
+%D
+%D \startxtable[frame=off]
+%D \startxtablehead
+%D \startxrow[bold]
+%D \startxcell[suffix] a 0 \stopxcell
+%D \startxcell[blabla] a 1 \stopxcell
+%D \startxcell a 2 \stopxcell
+%D \stopxrow
+%D \stopxtablehead
+%D \startxtablebody
+%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow
+%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow
+%D \stopxtablebody
+%D \stopxtable
+%D \stopbuffer
+%D
+%D \typebuffer \placetable{}{\getbuffer}
+
+\appendtoks
+ \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent
+\to \everysetupxtable
+
+% \definefontfamily[newtimes][serif][TeX Gyre Termes]
+% \setupxtable[newtimes][foregroundstyle=\newtimes]
+% \startxcell[newtimes] ...\stopxcell
+% \startxcell[foregroundstyle=\newtimes] ...\stopxcell
+
+% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+% % \ifcsname\??xtablecheck#tag\endcsname
+% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords
+% \expandafter\whatever % but more tolerant for tricky key=value
+% \else
+% \expandafter\whatever
+% \fi[#tag]
+
+% groups
+
+\unexpanded\def\startxgroup
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_group_delayed_one\relax}
+
+\unexpanded\def\stopxgroup
+ {\endgroup}
+
+\unexpanded\def\tabl_x_start_group_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_group_delayed_two
+ \else
+ \expandafter\setupcurrentxtable
+ \fi[#tag]}
+
+\unexpanded\def\tabl_x_start_group_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\setupcurrentxtable\relax}
+
+\let\startxrowgroup \startxgroup
+\let\stopxrowgroup \stopxgroup
+\let\startxcellgroup\startxgroup
+\let\stopxcellgroup \stopxgroup
+
+% cells (maybe also check for 1 etc but it becomes messy)
+
+\unexpanded\def\startxcell
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop}
+
+\unexpanded\def\tabl_x_start_cell_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_cell_delayed_two
+ \else
+ \expandafter\tabl_x_start_cell_yes
+ \fi[#tag]}
+
+\unexpanded\def\tabl_x_start_cell_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\stopxcell
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% rows
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_row_delayed_one\tabl_x_start_row_nop}
+
+\unexpanded\def\tabl_x_start_row_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_row_delayed_two
+ \else
+ \expandafter\tabl_x_start_row_yes
+ \fi[#tag]}
+
+\unexpanded\def\tabl_x_start_row_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua
new file mode 100644
index 00000000000..eaf342234de
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua
@@ -0,0 +1,253 @@
+if not modules then modules = { } end modules ['task-ini'] = {
+ version = 1.001,
+ comment = "companion to task-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this is a temporary solution, we need to isolate some modules and then
+-- the load order can determine the trickery to be applied to node lists
+--
+-- we can disable more handlers and enable then when really used (*)
+--
+-- todo: two finalizers: real shipout (can be imposed page) and page shipout (individual page)
+--
+-- todo: consider moving the kernel kerning/ligaturing functions in the main font loop because
+-- there we know if they are needed; doesn't save time but; if we overload unh* commands to
+-- 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", "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
+
+appendaction("processors", "words", "languages.replacements.handler") -- disabled
+
+appendaction("processors", "words", "languages.hyphenators.handler") -- always on
+
+appendaction("processors", "words", "languages.words.check") -- disabled -- might move up, no disc check needed then
+
+appendaction("processors", "words", "typesetters.initials.handler") -- disabled -- might move up
+appendaction("processors", "words", "typesetters.firstlines.handler") -- disabled -- might move down
+
+appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split") -- experimental
+appendaction("processors", "fonts", "nodes.handlers.characters") -- maybe todo
+appendaction("processors", "fonts", "nodes.injections.handler") -- maybe todo
+appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nohead") -- maybe todo
+appendaction("processors", "fonts", "builders.kernel.ligaturing") -- always on (could be selective: if only node mode)
+appendaction("processors", "fonts", "builders.kernel.kerning") -- 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", "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", "lists", "typesetters.initials.handler") -- disabled
+
+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")
+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", "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") -- * 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.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("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")
+
+-- 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("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("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("math", "noads.handlers.showtree")
+disableaction("math", "noads.handlers.tags")
+disableaction("math", "noads.handlers.italics")
+disableaction("math", "noads.handlers.domains")
+disableaction("math", "noads.handlers.classes")
+disableaction("math", "noads.handlers.autofences")
+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")
+
+freezecallbacks("find_.*_file", "find file using resolver")
+freezecallbacks("read_.*_file", "read file at once")
+freezecallbacks("open_.*_file", "open file for reading")
+
+-- experimental:
+
+freezegroup("processors", "normalizers")
+freezegroup("processors", "characters")
+freezegroup("processors", "words")
+freezegroup("processors", "fonts")
+freezegroup("processors", "lists")
+
+freezegroup("finalizers", "normalizers")
+freezegroup("finalizers", "fonts")
+freezegroup("finalizers", "lists")
+
+freezegroup("shipouts", "normalizers")
+freezegroup("shipouts", "finishers")
+
+freezegroup("mvlbuilders", "normalizers")
+freezegroup("vboxbuilders", "normalizers")
+
+-----------("parbuilders", "lists")
+-----------("pagebuilders", "lists")
+
+freezegroup("math", "normalizers")
+freezegroup("math", "builders")
+
+-- new: disabled here
+
+disableaction("processors", "builders.kernel.ligaturing")
+disableaction("processors", "builders.kernel.kerning")
+
+directives.register("nodes.basepass", function(v)
+ if v then
+ enableaction("processors", "builders.kernel.ligaturing")
+ enableaction("processors", "builders.kernel.kerning")
+ else
+ disableaction("processors", "builders.kernel.ligaturing")
+ disableaction("processors", "builders.kernel.kerning")
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/task-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/task-ini.mkiv
new file mode 100644
index 00000000000..6cdbe739f15
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/task-ini.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=task-ini,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Task Handler,
+%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 Task Handler / initialization}
+
+\unprotect
+
+%D Maybe we will make things configureable (speed up and such).
+
+\registerctxluafile{task-ini}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua
new file mode 100644
index 00000000000..132605d385a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua
@@ -0,0 +1,281 @@
+if not modules then modules = { } end modules ['toks-ini'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+tokens = tokens or { }
+
+local tokens = tokens
+local token = token -- the built in one
+local tonumber = tonumber
+local tostring = tostring
+local utfchar = utf.char
+local char = string.char
+local printtable = table.print
+local concat = table.concat
+
+if setinspector then
+
+ local istoken = token.is_token
+ local simple = { letter = "letter", other_char = "other" }
+
+ 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.istoken = istoken
+ tokens.astable = astable
+
+ setinspector("token",function(v) if istoken(v) then printtable(astable(v),tostring(v)) return true end end)
+
+end
+
+local scan_toks = token.scan_toks
+local scan_string = token.scan_string
+local scan_int = token.scan_int
+local scan_code = token.scan_code
+local scan_dimen = token.scan_dimen
+local scan_glue = token.scan_glue
+local scan_keyword = token.scan_keyword
+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 get_next = token.get_next
+
+local set_macro = token.set_macro
+local get_cmdname = token.get_cmdname
+local create_token = token.create
+
+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
+
+local bits = {
+ escape = 2^ 0,
+ begingroup = 2^ 1,
+ endgroup = 2^ 2,
+ mathshift = 2^ 3,
+ alignment = 2^ 4,
+ endofline = 2^ 5,
+ parameter = 2^ 6,
+ superscript = 2^ 7,
+ subscript = 2^ 8,
+ ignore = 2^ 9,
+ space = 2^10, -- 1024
+ letter = 2^11,
+ other = 2^12,
+ active = 2^13,
+ comment = 2^14,
+ invalid = 2^15,
+ --
+ character = 2^11 + 2^12,
+ whitespace = 2^13 + 2^10, -- / needs more checking
+ --
+ open = 2^10 + 2^1, -- space + begingroup
+ close = 2^10 + 2^2, -- space + endgroup
+}
+
+-- for k, v in next, bits do bits[v] = k end
+
+tokens.bits = bits
+
+local space_bits = bits.space
+
+-- words are space or \relax terminated and the trailing space is gobbled; a word
+-- can contain any non-space letter/other
+
+local t = { } -- small optimization, a shared variable that is not reset
+
+if scan_word then
+
+ scan_number = function(base)
+ local s = scan_word()
+ if not s then
+ return nil
+ elseif base then
+ return tonumber(s,base)
+ else
+ return tonumber(s)
+ end
+ end
+
+else
+
+ scan_word = function()
+ local n = 0
+ while true do
+ local c = scan_code()
+ if c then
+ n = n + 1
+ t[n] = utfchar(c)
+ elseif scan_code(space_bits) then
+ if n > 0 then
+ break
+ end
+ elseif n > 0 then
+ break
+ else
+ return
+ end
+ end
+ return concat(t,"",1,n)
+ end
+
+ -- so we gobble the space (like scan_int) (number has to be space or non-char terminated
+ -- as we accept 0xabcd and such so there is no clear separator for a keyword
+
+ scan_number = function(base)
+ local n = 0
+ while true do
+ local c = scan_code()
+ if c then
+ n = n + 1
+ t[n] = char(c)
+ elseif scan_code(space_bits) then
+ if n > 0 then
+ break
+ end
+ elseif n > 0 then
+ break
+ else
+ return
+ end
+ end
+ local s = concat(t,"",1,n)
+ if base then
+ return tonumber(s,base)
+ else
+ return tonumber(s)
+ end
+ end
+
+end
+
+-- -- the next one cannot handle \iftrue true\else false\fi
+--
+-- local function scan_boolean()
+-- if scan_keyword("true") then
+-- return true
+-- elseif scan_keyword("false") then
+-- return false
+-- else
+-- return nil
+-- end
+-- end
+
+local function scan_boolean()
+ local kw = scan_word()
+ if kw == "true" then
+ return true
+ elseif kw == "false" then
+ return false
+ else
+ return nil
+ end
+end
+
+if not scan_csname then
+
+ scan_csname = function()
+ local t = get_next()
+ local n = t.csname
+ return n ~= "" and n or nil
+ end
+
+end
+
+tokens.scanners = { -- these expand
+ token = scan_token,
+ toks = scan_toks,
+ tokens = scan_toks,
+ dimen = scan_dimen,
+ dimension = scan_dimen,
+ glue = scan_glue,
+ skip = scan_glue,
+ integer = scan_int,
+ count = scan_int,
+ string = scan_string,
+ code = scan_code,
+ word = scan_word,
+ number = scan_number,
+ boolean = scan_boolean,
+ keyword = scan_keyword,
+ csname = scan_csname,
+}
+
+tokens.getters = { -- these don't expand
+ token = get_next,
+ count = tex.getcount,
+ dimen = tex.getdimen,
+ skip = tex.getglue,
+ glue = tex.getglue,
+ skip = tex.getmuglue,
+ glue = tex.getmuglue,
+ box = tex.getbox,
+}
+
+tokens.setters = {
+ macro = set_macro,
+ count = tex.setcount,
+ dimen = tex.setdimen,
+ skip = tex.setglue,
+ glue = tex.setglue,
+ skip = tex.setmuglue,
+ glue = tex.setmuglue,
+ box = tex.setbox,
+}
+
+-- static int run_scan_token(lua_State * L)
+-- {
+-- saved_tex_scanner texstate;
+-- save_tex_scanner(texstate);
+-- get_x_token();
+-- make_new_token(L, cur_cmd, cur_chr, cur_cs);
+-- unsave_tex_scanner(texstate);
+-- return 1;
+-- }
+--
+-- static int run_get_future(lua_State * L)
+-- {
+-- /* saved_tex_scanner texstate; */
+-- /* save_tex_scanner(texstate); */
+-- get_token();
+-- make_new_token(L, cur_cmd, cur_chr, cur_cs);
+-- back_input();
+-- /* unsave_tex_scanner(texstate); */
+-- return 1;
+-- }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv
new file mode 100644
index 00000000000..03ec997421a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv
@@ -0,0 +1,25 @@
+%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 / Initialization}
+
+\registerctxluafile{toks-ini}{1.001}
+\registerctxluafile{toks-scn}{1.001}
+\registerctxluafile{cldf-scn}{1.001}
+\registerctxluafile{cldf-stp}{1.001}
+
+\unprotect
+
+% nothing yet
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-map.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-map.lua
new file mode 100644
index 00000000000..9120c2084e6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-map.lua
@@ -0,0 +1,70 @@
+if not modules then modules = { } end modules ['toks-map'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Even more experimental ... this used to be part of toks-ini but as
+-- this kind of remapping has not much use it is not loaded in the
+-- core. We just keep it here for old times sake.
+
+-- local remapper = { } -- namespace
+-- collectors.remapper = remapper
+--
+-- local remapperdata = { } -- user mappings
+-- remapper.data = remapperdata
+--
+-- function remapper.store(tag,class,key)
+-- local s = remapperdata[class]
+-- if not s then
+-- s = { }
+-- remapperdata[class] = s
+-- end
+-- s[key] = collectordata[tag]
+-- collectordata[tag] = nil
+-- end
+--
+-- function remapper.convert(tag,toks)
+-- local data = remapperdata[tag]
+-- local leftbracket = utfbyte('[')
+-- local rightbracket = utfbyte(']')
+-- local skipping = 0
+-- -- todo: math
+-- if data then
+-- local t, n = { }, 0
+-- for s=1,#toks do
+-- local tok = toks[s]
+-- local one, two = tok[1], tok[2]
+-- if one == 11 or one == 12 then
+-- if two == leftbracket then
+-- skipping = skipping + 1
+-- n = n + 1 ; t[n] = tok
+-- elseif two == rightbracket then
+-- skipping = skipping - 1
+-- n = n + 1 ; t[n] = tok
+-- elseif skipping == 0 then
+-- local new = data[two]
+-- if new then
+-- if #new > 1 then
+-- for n=1,#new do
+-- n = n + 1 ; t[n] = new[n]
+-- end
+-- else
+-- n = n + 1 ; t[n] = new[1]
+-- end
+-- else
+-- n = n + 1 ; t[n] = tok
+-- end
+-- else
+-- n = n + 1 ; t[n] = tok
+-- end
+-- else
+-- n = n + 1 ; t[n] = tok
+-- end
+-- end
+-- return t
+-- else
+-- return toks
+-- end
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-map.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-map.mkiv
new file mode 100644
index 00000000000..f1b63a68b0a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-map.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=toks-map, % experimental moved from 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 / Remapping}
+%
+% \registerctxluafile{toks-map}{1.001}
+%
+% \unprotect
+%
+% %D Inspired by a prototype by Taco for Thomas cum suis.
+% %D
+% %D \starttyping
+% %D \defineremapper[babelgreek]
+% %D
+% %D \remapcharacter[babelgreek][`a]{\alpha}
+% %D \remapcharacter[babelgreek][`b]{\beta}
+% %D \remapcharacter[babelgreek][`c]{\gamma}
+% %D \remapcharacter[babelgreek][`d]{OEPS}
+% %D
+% %D \starttext
+% %D
+% %D [\startbabelgreek
+% %D a b c some stuff here \blank[big] oeps b d
+% %D \stopbabelgreek]
+% %D
+% %D [\babelgreek{some stuff here}]
+% %D
+% %D \stoptext
+% %D \stoptyping
+%
+% \unexpanded\def\defineremapper[#1]%
+% {\setuevalue{\e!start#1}{\toks_start_remapper{#1}}%
+% \setuevalue{\e!stop #1}{\toks_stop_remapper {#1}}%
+% \letvalue{#1}\relax
+% \normalexpanded{\expandafter\def\csname#1\endcsname##1{\csname\e!start#1\endcsname##1\csname\e!stop#1\endcsname}}}
+%
+% \unexpanded\def\toks_start_remapper#1%
+% {\ctxlua{tokens.collectors.install("#1", "\e!stop#1")}}
+%
+% \unexpanded\def\toks_stop_remapper#1%
+% {\ctxlua{tokens.collectors.handle("#1",function(str) return tokens.collectors.remapper.convert("#1",str) end, true)}}
+%
+% \unexpanded\def\remaptokens#1%
+% {\ctxlua{tokens.collectors.handle("#1",function(str) return tokens.collectors.remapper.convert("#1",str) end)}}
+%
+% \unexpanded\def\remapcharacter
+% {\dodoubleempty\toks_remap_character}
+%
+% \def\toks_remap_character[#1][#2]#3%
+% {\ctxlua{tokens.collectors.install("store", "ctxlua")}#3%
+% \ctxlua{tokens.collectors.remapper.store("store","#1",\number#2)}}
+%
+% \protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua
new file mode 100644
index 00000000000..5c8dee8f3d2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua
@@ -0,0 +1,447 @@
+if not modules then modules = { } end modules ['toks-scn'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Writing this kind of code (and completing the newtoken code base) is fun. I did
+-- so with the brilliant film music from The Girl with the Dragon Tattoo running in a
+-- loop in the background (three cd's by Trent Reznor and Atticus Ross). An alien
+-- feeling helps with alien code.
+
+-- todo: more \let's at the tex end
+
+local type, next, tostring, tonumber = type, next, tostring, tonumber
+
+local formatters = string.formatters
+local concat = table.concat
+
+local scanners = tokens.scanners
+local tokenbits = tokens.bits
+
+local scanstring = scanners.string
+local scaninteger = scanners.integer
+local scannumber = scanners.number
+local scankeyword = scanners.keyword
+local scanword = scanners.word
+local scancode = scanners.code
+local scanboolean = scanners.boolean
+local scandimen = scanners.dimen
+local scancsname = scanners.csname
+
+local todimen = number.todimen
+local toboolean = toboolean
+
+local lpegmatch = lpeg.match
+local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted)
+
+local trace_compile = false trackers.register("tokens.compile", function(v) trace_compile = v end)
+local report_compile = logs.reporter("tokens","compile")
+local report_scan = logs.reporter("tokens","scan")
+
+local open = tokenbits.open
+local close = tokenbits.close
+
+local function scanopen()
+ while true do
+ local c = scancode(open)
+ if c == 123 then
+ return true
+ -- elseif c ~= 32 then
+ elseif not c then
+ return
+ end
+ end
+end
+
+local function scanclose()
+ while true do
+ local c = scancode(close)
+ if c == 125 then
+ return true
+ -- elseif c ~= 32 then
+ elseif not c then
+ return
+ end
+ end
+end
+
+scanners.scanopen = scanopen
+scanners.scanclose = scanclose
+
+local function scanlist()
+ local wrapped = scanopen()
+ local list = { }
+ local size = 0
+ while true do
+ local entry = scanstring()
+ if entry then
+ size = size + 1
+ list[size] = entry
+ else
+ break
+ end
+ end
+ if wrapped then
+ scanclose()
+ end
+ return list
+end
+
+local function scanconditional()
+ local kw = scanword()
+ if kw == "true" then
+ return true
+ end
+ if kw == "false" then
+ return false
+ end
+ local c = scaninteger()
+ if c then
+ return c == 0 -- with a conditional 0=true
+ end
+ return nil
+end
+
+scanners.list = scanlist
+scanners.conditional = scanconditional
+
+local shortcuts = {
+ tokens = tokens,
+ bits = tokenbits,
+ open = open,
+ close = close,
+ scanners = scanners,
+ scanstring = scanstring,
+ scaninteger = scaninteger,
+ scannumber = scannumber,
+ scankeyword = scankeyword,
+ scanword = scanword,
+ scancode = scancode,
+ scanboolean = scanboolean,
+ scandimen = scandimen,
+ scandimension = scandimen,
+ scanconditional = scanconditional,
+ scanopen = scanopen,
+ scanclose = scanclose,
+ scanlist = scanlist,
+ scancsname = scancsname,
+ todimen = todimen,
+ tonumber = tonumber,
+ tostring = tostring,
+ toboolean = toboolean,
+ inspect = inspect,
+ report = report_scan,
+}
+
+tokens.shortcuts = shortcuts
+
+local load = load
+local dump = string.dump
+
+local function loadstripped(code)
+ return load(code,nil,nil,shortcuts)
+ -- return load(dump(load(code),true),nil,nil,shortcuts)
+end
+
+tokens.converters = {
+ tonumber = "tonumber",
+ tostring = "tostring",
+ toboolean = "toboolean",
+ todimen = "todimen",
+ toglue = "todimen",
+}
+
+local f_if = formatters[ " if scankeyword('%s') then data['%s'] = scan%s()"]
+local f_elseif = formatters[" elseif scankeyword('%s') then data['%s'] = scan%s()"]
+local f_local = formatters["local scan%s = scanners.%s"]
+local f_scan = formatters["scan%s()"]
+local f_shortcut = formatters["local %s = scanners.converters.%s"]
+
+local f_if_c = formatters[ " if scankeyword('%s') then data['%s'] = %s(scan%s())"]
+local f_elseif_c = formatters[" elseif scankeyword('%s') then data['%s'] = %s(scan%s())"]
+local f_scan_c = formatters["%s(scan%s())"]
+
+local f_any = formatters[" else local key = scanword() if key then data[key] = scan%s() else break end end"]
+local f_any_c = formatters[" else local key = scanword() if key then data[key] = %s(scan%s()) else break end end"]
+local s_done = " else break end"
+
+local f_any_all = formatters[" local key = scanword() if key then data[key] = scan%s() else break end"]
+local f_any_all_c= formatters[" local key = scanword() if key then data[key] = %s(scan%s()) else break end"]
+
+local f_table = formatters["%\nt\nreturn function()\n local data = { }\n%s\n return %s\nend\n"]
+local f_sequence = formatters["%\nt\n%\nt\n%\nt\nreturn function()\n return %s\nend\n"]
+local f_simple = formatters["%\nt\nreturn function()\n return %s\nend\n"]
+local f_string = formatters["%q"]
+local f_action_f = formatters["action%s(%s)"]
+local f_action_s = formatters["local action%s = tokens._action[%s]"]
+local f_nested = formatters["local function scan%s()\n local data = { }\n%s\n return data\nend\n"]
+
+-- local f_check = formatters[ [[
+-- local wrapped = false
+-- while true do
+-- local c = scancode(open)
+-- if c == 123 then
+-- wrapped = true
+-- break
+-- elseif c ~= 32 then
+-- break
+-- end
+-- end
+-- while true do
+-- ]] .. "%\nt\n" .. [[
+-- %s
+-- end
+-- if wrapped then
+-- while true do
+-- local c = scancode(close)
+-- if c == 125 then
+-- break
+-- elseif c ~= 32 then
+-- break
+-- end
+-- end
+-- end
+-- ]] ]
+
+local f_check = formatters[ [[
+ local wrapped = scanopen()
+ while true do
+ ]] .. "%\nt\n" .. [[
+ %s
+ end
+ if wrapped then
+ scanclose()
+ end
+]] ]
+
+function tokens.compile(specification)
+ local f = { }
+ local n = 0
+ local c = { }
+ local t = specification.arguments or specification
+ local a = specification.actions or nil
+ if type(a) == "function" then
+ a = { a }
+ end
+ local code
+ local function compile(t,nested)
+ local done = s_done
+ local r = { }
+ local m = 0
+ for i=1,#t do
+ local ti = t[i]
+ if ti == "*" and i == 1 then
+ done = f_any_all("string")
+ else
+ local t1 = ti[1]
+ local t2 = ti[2] or "string"
+ if type(t2) == "table" then
+ n = n + 1
+ f[n] = compile(t2,n)
+ t2 = n
+ end
+ local t3 = ti[3]
+ if type(t3) == "function" then
+ -- todo: also create shortcut
+ elseif t3 then
+ c[t3] = f_shortcut(t3,t3)
+ if t1 == "*" then
+ if i == 1 then
+ done = f_any_all_c(t3,t2)
+ break
+ else
+ done = f_any_c(t3,t2)
+ end
+ else
+ m = m + 1
+ r[m] = (m > 1 and f_elseif_c or f_if_c)(t1,t1,t3,t2)
+ end
+ else
+ if t1 == "*" then
+ if i == 1 then
+ done = f_any_all(t2)
+ break
+ else
+ done = f_any(t2)
+ end
+ else
+ m = m + 1
+ r[m] = (m > 1 and f_elseif or f_if )(t1,t1,t2)
+ end
+ end
+ end
+ end
+ local c = f_check(r,done)
+ if nested then
+ return f_nested(nested,c)
+ else
+ return c
+ end
+ end
+ local tt = type(t)
+ if tt == "string" then
+ if a then
+ local s = lpegmatch(p_unquoted,t)
+ if s and t ~= s then
+ code = t
+ else
+ code = f_scan(t)
+ end
+ tokens._action = a
+ for i=1,#a do
+ code = f_action_f(i,code)
+ f[#f+1] = f_action_s(i,i)
+ end
+ code = f_simple(f,code)
+ else
+ return scanners[t]
+ end
+ elseif tt ~= "table" then
+ return
+ elseif #t == 1 then
+ local ti = t[1]
+ if type(ti) == "table" then
+ ti = compile(ti)
+ code = "data"
+ if a then
+ tokens._action = a
+ for i=1,#a do
+ code = f_action_f(i,code)
+ f[#f+1] = f_action_s(i,i)
+ end
+ end
+ code = f_table(f,ti,code)
+ elseif a then
+ code = f_scan(ti)
+ tokens._action = a
+ for i=1,#a do
+ code = f_action_f(i,code)
+ f[#f+1] = f_action_s(i,i)
+ end
+ code = f_simple(f,code)
+ else
+ return scanners[ti]
+ end
+ else
+ local r = { }
+ local p = { }
+ local m = 0
+ for i=1,#t do
+ local ti = t[i]
+ local tt = type(ti)
+ if tt == "table" then
+ if ti[1] == "_constant_" then
+ local v = ti[2]
+ if type(v) == "string" then
+ r[i] = f_string(v)
+ else
+ r[i] = tostring(v)
+ end
+ else
+ m = m + 1
+ p[m] = compile(ti,100+m)
+ r[i] = f_scan(100+m)
+ end
+ elseif tt == "number" then
+ r[i] = tostring(ti)
+ elseif tt == "boolean" then
+ r[i] = tostring(ti)
+ else
+ local s = lpegmatch(p_unquoted,ti)
+ if s and ti ~= s then
+ r[i] = ti -- a string, given as "'foo'" or '"foo"'
+ elseif scanners[ti] then
+ r[i] = f_scan(ti)
+ else
+ report_compile("unknown scanner %a",ti)
+ r[i] = ti
+ end
+ end
+ end
+ code = concat(r,",")
+ if a then
+ tokens._action = a
+ for i=1,#a do
+ code = f_action_f(i,code)
+ f[#f+1] = f_action_s(i,i)
+ end
+ end
+ code = f_sequence(c,f,p,code)
+ end
+ if not code then
+ return
+ end
+ if trace_compile then
+ report_compile("code: %s",code)
+ end
+ local code, message = loadstripped(code)
+ if code then
+ code = code() -- sets action
+ else
+ report_compile("error in code: %s",code)
+ report_compile("error message: %s",message)
+ end
+ if a then
+ tokens._action = nil
+ end
+ if code then
+ return code
+ end
+end
+
+-- local fetch = tokens.compile {
+-- "string",
+-- "string",
+-- {
+-- { "data", "string" },
+-- { "tab", "string" },
+-- { "method", "string" },
+-- { "foo", {
+-- { "method", "integer" },
+-- { "compact", "number" },
+-- { "nature" },
+-- { "*" }, -- any key
+-- } },
+-- { "compact", "string", "tonumber" },
+-- { "nature", "boolean" },
+-- { "escape", "string" },
+-- { "escape" },
+-- }
+-- "boolean",
+-- }
+--
+-- 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/Master/texmf-dist/tex/context/base/mkiv/toks-tra.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-tra.lua
new file mode 100644
index 00000000000..a1408b0b85a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-tra.lua
@@ -0,0 +1,292 @@
+if not modules then modules = { } end modules ['toks-ini'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+local utfbyte, utfchar, utfvalues = utf.byte, utf.char, utf.values
+local format, gsub = string.format, string.gsub
+local tostring = tostring
+
+local tokens = tokens
+local token = token -- the built in one
+local tex = tex
+local context = context
+local commands = commands
+
+tokens.collectors = tokens.collectors or { }
+local collectors = tokens.collectors
+
+collectors.data = collectors.data or { }
+local collectordata = collectors.data
+
+collectors.registered = collectors.registered or { }
+local registered = collectors.registered
+
+local report = logs.reporter("tokens","collectors")
+
+-- todo:
+--
+-- register : macros that will be expanded (only for demo-ing)
+-- flush : print back to tex
+-- test : fancy stuff
+
+local get_next = token.get_next
+local create_token = token.create
+
+function collectors.install(tag,end_cs)
+ local data, d = { }, 0
+ collectordata[tag] = data
+ end_cs = gsub(end_cs,"^\\","")
+ while true do
+ local t = get_next()
+ if t.csname == end_cs then
+ context[end_cs]()
+ return
+ else
+ d = d + 1
+ data[d] = t
+ end
+ end
+end
+
+local simple = { letter = "letter", other_char = "other" }
+
+function collectors.show(data)
+ -- We no longer have methods as we only used (in demos) method a
+ -- so there is no need to burden the core with this. We have a
+ -- different table anyway.
+ if type(data) == "string" then
+ data = collectordata[data]
+ end
+ if not data then
+ return
+ end
+ local ctx_NC = context.NC
+ local ctx_NR = context.NR
+ local ctx_bold = context.bold
+ local ctx_verbatim = context.verbatim
+ context.starttabulate { "|Tl|Tc|Tl|" }
+ ctx_NC() ctx_bold("cmd")
+ ctx_NC() ctx_bold("meaning")
+ ctx_NC() ctx_bold("properties")
+ ctx_NC() ctx_NR()
+ context.HL()
+ for i=1,#data do
+ local token = data[i]
+ local cmdname = token.cmdname
+ local simple = simple[cmdname]
+ ctx_NC()
+ ctx_verbatim(simple or cmdname)
+ ctx_NC()
+ ctx_verbatim(simple and utfchar(token.mode) or token.csname)
+ ctx_NC()
+ if token.active then context("active ") end
+ if token.expandable then context("expandable ") end
+ if token.protected then context("protected ") end
+ ctx_NC()
+ ctx_NR()
+ end
+ context.stoptabulate()
+end
+
+local function printlist(data)
+ if data and #data > 0 then
+ report("not supported (yet): printing back to tex")
+ end
+end
+
+tokens.printlist = printlist -- will change to another namespace
+
+function collectors.flush(tag)
+ printlist(collectordata[tag])
+end
+
+function collectors.test(tag,handle)
+ report("not supported (yet): testing")
+end
+
+function collectors.register(name)
+ report("not supported (yet): registering")
+end
+
+-- -- old token code
+--
+-- -- 1 = command, 2 = modifier (char), 3 = controlsequence id
+--
+-- local create = token.create
+-- local csname_id = token.csname_id
+-- local command_id = token.command_id
+-- local command_name = token.command_name
+-- local get_next = token.get_next
+-- local expand = token.expand
+-- local csname_name = token.csname_name
+--
+-- local function printlist(data)
+-- if data and #data > 0 then
+-- callbacks.push('token_filter', function ()
+-- callbacks.pop('token_filter') -- tricky but the nil assignment helps
+-- return data
+-- end)
+-- end
+-- end
+--
+-- tokens.printlist = printlist -- will change to another namespace
+--
+-- function collectors.flush(tag)
+-- printlist(collectordata[tag])
+-- end
+--
+-- function collectors.register(name)
+-- registered[csname_id(name)] = name
+-- end
+--
+-- local call = command_id("call")
+-- local letter = command_id("letter")
+-- local other = command_id("other_char")
+--
+-- function collectors.install(tag,end_cs)
+-- local data, d = { }, 0
+-- collectordata[tag] = data
+-- end_cs = gsub(end_cs,"^\\","")
+-- local endcs = csname_id(end_cs)
+-- while true do
+-- local t = get_next()
+-- local a, b = t[1], t[3]
+-- if b == endcs then
+-- context[end_cs]()
+-- return
+-- elseif a == call and registered[b] then
+-- expand()
+-- else
+-- d = d + 1
+-- data[d] = t
+-- end
+-- end
+-- end
+--
+-- function collectors.show(data)
+-- -- We no longer have methods as we only used (in demos) method a
+-- -- so there is no need to burden the core with this.
+-- if type(data) == "string" then
+-- data = collectordata[data]
+-- end
+-- if not data then
+-- return
+-- end
+-- local ctx_NC = context.NC
+-- local ctx_NR = context.NR
+-- local ctx_bold = context.bold
+-- local ctx_verbatim = context.verbatim
+-- context.starttabulate { "|T|Tr|cT|Tr|T|" }
+-- ctx_NC() ctx_bold("cmd")
+-- ctx_NC() ctx_bold("chr")
+-- ctx_NC()
+-- ctx_NC() ctx_bold("id")
+-- ctx_NC() ctx_bold("name")
+-- ctx_NC() ctx_NR()
+-- context.HL()
+-- for i=1,#data do
+-- local token = data[i]
+-- local cmd = token[1]
+-- local chr = token[2]
+-- local id = token[3]
+-- local name = command_name(token)
+-- ctx_NC()
+-- ctx_verbatim(name)
+-- ctx_NC()
+-- if tonumber(chr) >= 0 then
+-- ctx_verbatim(chr)
+-- end
+-- ctx_NC()
+-- if cmd == letter or cmd == other then
+-- ctx_verbatim(utfchar(chr))
+-- end
+-- ctx_NC()
+-- if id > 0 then
+-- ctx_verbatim(id)
+-- end
+-- ctx_NC()
+-- if id > 0 then
+-- ctx_verbatim(csname_name(token) or "")
+-- end
+-- ctx_NC() ctx_NR()
+-- end
+-- context.stoptabulate()
+-- end
+--
+-- function collectors.test(tag,handle)
+-- local t, w, tn, wn = { }, { }, 0, 0
+-- handle = handle or collectors.defaultwords
+-- local tagdata = collectordata[tag]
+-- for k=1,#tagdata do
+-- local v = tagdata[k]
+-- if v[1] == letter then
+-- wn = wn + 1
+-- w[wn] = v[2]
+-- else
+-- if wn > 0 then
+-- handle(t,w)
+-- wn = 0
+-- end
+-- tn = tn + 1
+-- t[tn] = v
+-- end
+-- end
+-- if wn > 0 then
+-- handle(t,w)
+-- end
+-- collectordata[tag] = t
+-- end
+
+-- Interfacing:
+
+commands.collecttokens = collectors.install
+commands.showtokens = collectors.show
+commands.flushtokens = collectors.flush
+commands.testtokens = collectors.test
+commands.registertoken = collectors.register
+
+-- Redundant:
+
+-- function collectors.test(tag)
+-- printlist(collectordata[tag])
+-- end
+
+-- For old times sake:
+
+collectors.dowithwords = collectors.test
+
+-- This is only used in old articles ... will move to a module:
+
+tokens.vbox = create_token("vbox")
+tokens.hbox = create_token("hbox")
+tokens.vtop = create_token("vtop")
+tokens.bgroup = create_token(utfbyte("{"),1)
+tokens.egroup = create_token(utfbyte("}"),2)
+
+tokens.letter = function(chr) return create_token(utfbyte(chr),11) end
+tokens.other = function(chr) return create_token(utfbyte(chr),12) end
+
+tokens.letters = function(str)
+ local t, n = { }, 0
+ for chr in utfvalues(str) do
+ n = n + 1
+ t[n] = create_token(chr, 11)
+ end
+ return t
+end
+
+function collectors.defaultwords(t,str)
+ if t then
+ local n = #t
+ n = n + 1 ; t[n] = tokens.bgroup
+ n = n + 1 ; t[n] = create_token("red")
+ for i=1,#str do
+ n = n + 1 ; t[n] = tokens.other('*')
+ end
+ n = n + 1 ; t[n] = tokens.egroup
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-tra.mkiv
new file mode 100644
index 00000000000..a3e27eaf89f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-tra.mkiv
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=toks-tra, % was 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 / Tracing}
+
+\registerctxluafile{toks-tra}{1.001}
+
+\unprotect
+
+%D Handy for manuals \unknown\ but not really used in practice, so it might
+%D become a runtime loaded module instead.
+
+\unexpanded\def\starttokens [#1]{\ctxcommand{collecttokens("#1","stoptokens")}}
+ \let\stoptokens \relax
+ \def\flushtokens [#1]{\ctxcommand{flushtokens("#1")}}
+ \def\showtokens [#1]{\ctxcommand{showtokens("#1")}}
+ \def\testtokens [#1]{\ctxcommand{testtokens("#1")}}
+ \def\registertoken #1{\ctxcommand{registertoken("#1")}}
+
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.lua
new file mode 100644
index 00000000000..493ce793686
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.lua
@@ -0,0 +1,70 @@
+if not modules then modules = { } end modules ['trac-ctx'] = {
+ version = 1.001,
+ comment = "companion to trac-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local context = context
+local implement = interfaces.implement
+local register = trackers.register
+
+local textrackers = tex.trackers or { }
+local texdirectives = tex.directives or { }
+
+tex.trackers = textrackers
+tex.directives = texdirectives
+
+storage.register("tex/trackers", textrackers, "tex.trackers")
+storage.register("tex/directives",texdirectives,"tex.directives")
+
+local function doit(category,tag,v)
+ local tt = category[tag]
+ if tt then
+ context.unprotect()
+ context(v and tt[1] or tt[2]) -- could be one call
+ context.protect()
+ end
+end
+
+local function initialize(category,register)
+ for tag, commands in next, category do
+ register(tag, function(v) doit(category,tag,v) end) -- todo: v,tag in caller
+ end
+end
+
+local function install(category,register,tag,enable,disable)
+ category[tag] = { enable, disable }
+ register(tag, function(v) doit(category,tag,v) end) -- todo: v,tag in caller
+end
+
+implement {
+ name = "initializetextrackers",
+ actions = function()
+ initialize(textrackers,trackers.register)
+ end
+}
+
+implement {
+ name = "initializetexdirectives",
+ actions = function()
+ initialize(texdirectives,directives.register)
+ end
+}
+
+implement {
+ name = "installtextracker",
+ actions = function(tag,enable,disable)
+ install(textrackers,trackers.register,tag,enable,disable)
+ end,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "installtexdirective",
+ actions = function(tag,enable,disable)
+ install(texdirectives,directives.register,tag,enable,disable)
+ end,
+ arguments = { "string", "string", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.mkiv
new file mode 100644
index 00000000000..4240281a6fb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-ctx.mkiv
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=trac-ctx,
+%D version=2012.07.13,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=TeX Trackers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Tracing Macros / TeX Trackers}
+
+\registerctxluafile{trac-ctx}{1.001}
+
+\unprotect
+
+\unexpanded\def\installtextracker#1#2#3%
+ {\clf_installtextracker{#1}{\detokenize{#2}}{\detokenize{#3}}}
+
+\unexpanded\def\installtexdirective#1#2#3%
+ {\clf_installtexdirective{#1}{\detokenize{#2}}{\detokenize{#3}}}
+
+\appendtoks
+ \clf_initializetextrackers
+ \clf_initializetexdirectives
+\to \everyjob
+
+\protect \endinput
+
+% this is one option:
+%
+% \newconditional\c_math_virtual_tx
+% \newconditional\c_math_virtual_px
+% \newconditional\c_math_virtual_lm
+%
+% \installtexdirective {fonts.math.virtual.tx} {\settrue \c_math_virtual_tx} {\setfalse\c_math_virtual_tx}
+% \installtexdirective {fonts.math.virtual.px} {\settrue \c_math_virtual_px} {\setfalse\c_math_virtual_px}
+% \installtexdirective {fonts.math.virtual.lm} {\settrue \c_math_virtual_lm} {\setfalse\c_math_virtual_lm}
+%
+% but as it makes the typescript look ugly we wil use:
+%
+% \installtexdirective {fonts.math.virtual.tx} {\enablemode[fonts.math.virtual.tx]} {\disablemode[fonts.math.virtual.tx]}
+% \installtexdirective {fonts.math.virtual.px} {\enablemode[fonts.math.virtual.px]} {\disablemode[fonts.math.virtual.px]}
+% \installtexdirective {fonts.math.virtual.lm} {\enablemode[fonts.math.virtual.lm]} {\disablemode[fonts.math.virtual.lm]}
+%
+% which could be:
+%
+% \def\mode_f_m_v_tx{fonts.math.virtual.tx}
+% \def\mode_f_m_v_px{fonts.math.virtual.px}
+% \def\mode_f_m_v_lm{fonts.math.virtual.lm}
+%
+% \installtexdirective \mode_f_m_v_tx {\enablemode[\mode_f_m_v_tx]} {\disablemode[\mode_f_m_v_tx]}
+% \installtexdirective \mode_f_m_v_px {\enablemode[\mode_f_m_v_px]} {\disablemode[\mode_f_m_v_px]}
+% \installtexdirective \mode_f_m_v_lm {\enablemode[\mode_f_m_v_lm]} {\disablemode[\mode_f_m_v_lm]}
+%
+% alas .. we don't want to define this in the core
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua
new file mode 100644
index 00000000000..792ad9b567d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua
@@ -0,0 +1,352 @@
+if not modules then modules = { } end modules ['trac-deb'] = {
+ version = 1.001,
+ comment = "companion to trac-deb.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpeg, status = lpeg, status
+
+local lpegmatch = lpeg.match
+local format, concat, match, find, gsub = string.format, table.concat, string.match, string.find, string.gsub
+local tonumber, tostring = tonumber, tostring
+
+-- maybe tracers -> tracers.tex (and tracers.lua for current debugger)
+
+----- report_tex = logs.reporter("tex error")
+----- report_lua = logs.reporter("lua error")
+local report_nl = logs.newline
+local report_str = logs.writer
+
+tracers = tracers or { }
+local tracers = tracers
+
+tracers.lists = { }
+local lists = tracers.lists
+
+tracers.strings = { }
+local strings = tracers.strings
+
+local texgetdimen = tex.getdimen
+local texgettoks = tex.gettoks
+local texgetcount = tex.getcount
+
+local implement = interfaces.implement
+
+strings.undefined = "undefined"
+
+lists.scratch = {
+ 0, 2, 4, 6, 8
+}
+
+lists.internals = {
+ 'p:hsize', 'p:parindent', 'p:leftskip','p:rightskip',
+ 'p:vsize', 'p:parskip', 'p:baselineskip', 'p:lineskip', 'p:topskip'
+}
+
+lists.context = {
+ 'd:lineheight',
+ 'c:realpageno', 'c:userpageno', 'c:pageno', 'c:subpageno'
+}
+
+local types = {
+ ['d'] = tracers.dimen,
+ ['c'] = tracers.count,
+ ['t'] = tracers.toks,
+ ['p'] = tracers.primitive
+}
+
+local splitboth = lpeg.splitat(":")
+local splittype = lpeg.firstofsplit(":")
+local splitname = lpeg.secondofsplit(":")
+
+function tracers.type(csname)
+ return lpegmatch(splittype,csname)
+end
+
+function tracers.name(csname)
+ return lpegmatch(splitname,csname) or csname
+end
+
+function tracers.cs(csname)
+ local tag, name = lpegmatch(splitboth,csname)
+ if name and types[tag] then
+ return types[tag](name)
+ else
+ return tracers.primitive(csname)
+ end
+end
+
+function tracers.dimen(name)
+ local d = texgetdimen(name)
+ return d and number.topoints(d) or strings.undefined
+end
+
+function tracers.count(name)
+ return texgetcount(name) or strings.undefined
+end
+
+function tracers.toks(name,limit)
+ local t = texgettoks(name)
+ return t and string.limit(t,tonumber(limit) or 40) or strings.undefined
+end
+
+function tracers.primitive(name)
+ return tex[name] or strings.undefined
+end
+
+function tracers.knownlist(name)
+ local l = lists[name]
+ return l and #l > 0
+end
+
+local savedluaerror = nil
+
+local function errorreporter(luaerror)
+ local category = luaerror and "lua error" or "tex error"
+ local report = logs.reporter(category)
+ logs.enable(category)
+ return report
+end
+
+function tracers.showlines(filename,linenumber,offset,luaerrorline)
+ local data = io.loaddata(filename)
+ if not data or data == "" then
+ local hash = url.hashed(filename)
+ if not hash.noscheme then
+ local ok, d, n = resolvers.loaders.byscheme(hash.scheme,filename)
+ if ok and n > 0 then
+ data = d
+ end
+ end
+ end
+ local lines = data and string.splitlines(data)
+ if lines and #lines > 0 then
+ if luaerrorline and luaerrorline > 0 then
+ -- lua error: linenumber points to last line
+ local start = "\\startluacode"
+ local stop = "\\stopluacode"
+ local n = linenumber
+ for i=n,1,-1 do
+ local line = lines[i]
+ if not line then
+ break
+ elseif find(line,start) then
+ n = i + luaerrorline - 1
+ if n <= linenumber then
+ linenumber = n
+ end
+ break
+ end
+ end
+ end
+ offset = tonumber(offset) or 10
+ linenumber = tonumber(linenumber) or 10
+ local start = math.max(linenumber - offset,1)
+ local stop = math.min(linenumber + offset,#lines)
+ if stop > #lines then
+ return "<linenumber past end of file>"
+ else
+ local result, fmt = { }, "%" .. #tostring(stop) .. "d %s %s"
+ for n=start,stop do
+ result[#result+1] = format(fmt,n,n == linenumber and ">>" or " ",lines[n])
+ end
+ return concat(result,"\n")
+ end
+ else
+ return "<empty file>"
+ end
+end
+
+-- this will work ok in >=0.79
+
+-- todo: last tex error has ! prepended
+-- todo: some nested errors have two line numbers
+-- todo: collect errorcontext in string (after code cleanup)
+-- todo: have a separate status.lualinenumber
+
+-- todo: \starttext bla \blank[foo] bla \stoptext
+
+local nop = function() end
+local resetmessages = status.resetmessages() or nop
+
+local function processerror(offset)
+ -- print("[[ last tex error: " .. tostring(status.lasterrorstring or "<unset>") .. " ]]")
+ -- print("[[ last lua error: " .. tostring(status.lastluaerrorstring or "<unset>") .. " ]]")
+ -- print("[[ last warning : " .. tostring(status.lastwarningstring or "<unset>") .. " ]]")
+ -- print("[[ last location : " .. tostring(status.lastwarninglocation or "<unset>") .. " ]]")
+ -- print("[[ last context : " .. tostring(status.lasterrorcontext or "<unset>") .. " ]]")
+
+ local inputstack = resolvers.inputstack
+ local filename = inputstack[#inputstack] or status.filename
+ local linenumber = tonumber(status.linenumber) or 0
+ local lastcontext = status.lasterrorcontext
+ local lasttexerror = status.lasterrorstring or "?"
+ local lastluaerror = status.lastluaerrorstring or lasttexerror
+ local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0)
+ resetmessages()
+ lastluaerror = gsub(lastluaerror,"%[\\directlua%]","[ctxlua]")
+ tracers.printerror {
+ filename = filename,
+ linenumber = linenumber,
+ offset = tonumber(offset) or 10,
+ lasttexerror = lasttexerror,
+ lastluaerror = lastluaerror,
+ luaerrorline = luaerrorline,
+ lastcontext = lastcontext,
+ }
+end
+
+-- so one can overload the printer if (really) needed
+
+function tracers.printerror(specification)
+ local filename = specification.filename
+ local linenumber = specification.linenumber
+ local lasttexerror = specification.lasttexerror
+ local lastluaerror = specification.lastluaerror
+ local lastcontext = specification.lasterrorcontext
+ local luaerrorline = specification.luaerrorline
+ local offset = specification.offset
+ local report = errorreporter(luaerrorline)
+ if not filename then
+ report("error not related to input file: %s ...",lasttexerror)
+ elseif type(filename) == "number" then
+ report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror)
+ else
+ report_nl()
+ if luaerrorline then
+ report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ -- report("error on line %s in file %s:\n\n%s",linenumber,filename,lasttexerror)
+ else
+ report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror)
+ if lastcontext then
+ report_nl()
+ report_str(lastcontext)
+ report_nl()
+ elseif tex.show_context then
+ report_nl()
+ tex.show_context()
+ end
+ end
+ report_nl()
+ report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline)))
+ report_nl()
+ end
+end
+
+local function processwarning(offset)
+ -- local inputstack = resolvers.inputstack
+ -- local filename = inputstack[#inputstack] or status.filename
+ -- local linenumber = tonumber(status.linenumber) or 0
+ local lastwarning = status.lastwarningstring or "?"
+ local lastlocation = status.lastwarningtag or "?"
+ resetmessages()
+ tracers.printwarning {
+ -- filename = filename,
+ -- linenumber = linenumber,
+ -- offset = tonumber(offset) or 10,
+ lastwarning = lastwarning ,
+ lastlocation = lastlocation,
+ }
+end
+
+function tracers.printwarning(specification)
+ logs.report("luatex warning","%s: %s",specification.lastlocation,specification.lastwarning)
+end
+
+directives.register("system.errorcontext", function(v)
+ local register = callback.register
+ if v then
+ register('show_error_message', nop)
+ register('show_warning_message',function() processwarning(v) end)
+ register('show_error_hook', function() processerror(v) end)
+ register('show_lua_error_hook', nop)
+ else
+ register('show_error_message', nil)
+ register('show_error_hook', nil)
+ register('show_warning_message',nil)
+ register('show_lua_error_hook', nil)
+ end
+end)
+
+-- this might move
+
+lmx = lmx or { }
+
+lmx.htmfile = function(name) return environment.jobname .. "-status.html" end
+lmx.lmxfile = function(name) return resolvers.findfile(name,'tex') end
+
+function lmx.showdebuginfo(lmxname)
+ local variables = {
+ ['title'] = 'ConTeXt Debug Information',
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ }
+ if lmxname == false then
+ return variables
+ else
+ lmx.show(lmxname or 'context-debug.lmx',variables)
+ end
+end
+
+function lmx.showerror(lmxname)
+ local filename, linenumber, errorcontext = status.filename, tonumber(status.linenumber) or 0, ""
+ if not filename then
+ filename, errorcontext = 'unknown', 'error in filename'
+ elseif type(filename) == "number" then
+ filename, errorcontext = format("<read %s>",filename), 'unknown error'
+ else
+ errorcontext = tracers.showlines(filename,linenumber,offset)
+ end
+ local variables = {
+ ['title'] = 'ConTeXt Error Information',
+ ['errormessage'] = status.lasterrorstring,
+ ['linenumber'] = linenumber,
+ ['color-background-one'] = lmx.get('color-background-yellow'),
+ ['color-background-two'] = lmx.get('color-background-purple'),
+ ['filename'] = filename,
+ ['errorcontext'] = errorcontext,
+ }
+ if lmxname == false then
+ return variables
+ else
+ lmx.show(lmxname or 'context-error.lmx',variables)
+ end
+end
+
+function lmx.overloaderror()
+ callback.register('show_error_hook', function() lmx.showerror() end) -- prevents arguments being passed
+end
+
+directives.register("system.showerror", lmx.overloaderror)
+
+local debugger = utilities.debugger
+
+local function trace_calls(n)
+ debugger.enable()
+ luatex.registerstopactions(function()
+ debugger.disable()
+ debugger.savestats(tex.jobname .. "-luacalls.log",tonumber(n))
+ end)
+ trace_calls = function() end
+end
+
+directives.register("system.tracecalls", function(n) trace_calls(n) end) -- indirect is needed for nilling
+
+implement { name = "showtrackers", actions = trackers.show }
+implement { name = "enabletrackers", actions = trackers.enable, arguments = "string" }
+implement { name = "disabletrackers", actions = trackers.disable, arguments = "string" }
+implement { name = "resettrackers", actions = trackers.reset }
+
+implement { name = "showdirectives", actions = directives.show }
+implement { name = "enabledirectives", actions = directives.enable, arguments = "string" }
+implement { name = "disabledirectives", actions = directives.disable, arguments = "string" }
+
+implement { name = "showexperiments", actions = experiments.show }
+implement { name = "enableexperiments", actions = experiments.enable, arguments = "string" }
+implement { name = "disableexperiments", actions = experiments.disable, arguments = "string" }
+
+implement { name = "showdebuginfo", actions = lmx.showdebuginfo }
+implement { name = "overloaderror", actions = lmx.overloaderror }
+implement { name = "showlogcategories", actions = logs.show }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-deb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.mkiv
new file mode 100644
index 00000000000..1e61a351261
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.mkiv
@@ -0,0 +1,43 @@
+%D \module
+%D [ file=trac-deb,
+%D version=2005.11.06,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=Debugger,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Tracing Macros / Debugger}
+
+\unprotect
+
+%registerctxluafile{trac-lmx}{1.001}
+\registerctxluafile{trac-deb}{1.001}
+
+\unexpanded\def\breakpoint {\showdebuginfo\wait}
+
+\unexpanded\def\showtrackers {\clf_showtrackers}
+\unexpanded\def\enabletrackers [#1]{\clf_enabletrackers{#1}}
+\unexpanded\def\disabletrackers [#1]{\clf_disabletrackers{#1}}
+\unexpanded\def\resettrackers {\clf_resettrackers}
+
+\unexpanded\def\showdirectives {\clf_showdirectives}
+\unexpanded\def\enabledirectives [#1]{\clf_enabledirectives{#1}}
+\unexpanded\def\disabledirectives [#1]{\clf_disabledirectives{#1}}
+
+\unexpanded\def\showexperiments {\clf_showexperiments}
+\unexpanded\def\enableexperiments [#1]{\clf_enableexperiments{#1}}
+\unexpanded\def\disableexperiments[#1]{\clf_disableexperiments{#1}}
+
+\unexpanded\def\showdebuginfo {\clf_showdebuginfo}
+\unexpanded\def\overloaderror {\clf_overloaderror}
+
+\unexpanded\def\showlogcategories {\clf_showlogcategories}
+
+% \enabledirectives[system.showerror]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-exp.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-exp.lua
new file mode 100644
index 00000000000..5879f1b7bad
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-exp.lua
@@ -0,0 +1,229 @@
+if not modules then modules = { } end modules ['trac-exp'] = {
+ version = 1.001,
+ comment = "companion to trac-log.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local formatters = string.formatters
+local reporters = logs.reporters
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmltext = xml.text
+local xmlfirst = xml.first
+local xmlfilter = xml.filter
+
+-- there is no need for a newhandlers { name = "help", parent = "string" }
+
+local function flagdata(flag)
+ local name = flag.at.name or ""
+ local value = flag.at.value or ""
+ -- local short = xmlfirst(s,"/short")
+ -- local short = xmlserialize(short,xs)
+ local short = xmltext(xmlfirst(flag,"/short")) or ""
+ return name, value, short
+end
+
+local function exampledata(example)
+ local command = xmltext(xmlfirst(example,"/command")) or ""
+ local comment = xmltext(xmlfirst(example,"/comment")) or ""
+ return command, comment
+end
+
+local function categorytitle(category)
+ return xmltext(xmlfirst(category,"/title")) or ""
+end
+
+local exporters = logs.exporters
+
+function exporters.man(specification,...)
+ local root = xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs = xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref", function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories = select("#",...) == 0 and true or table.tohash { ... }
+ local nofcategories = xml.count(root,"/application/flags/category")
+ local name = xmlfilter(root,"/application/metadata/entry[@name='name']/text()")
+ local detail = xmlfilter(root,"/application/metadata/entry[@name='detail']/text()") or name
+ local version = xmlfilter(root,"/application/metadata/entry[@name='version']/text()") or "0.00"
+ local banner = specification.banner or detail or name
+ --
+ local result = { }
+ --
+ -- .TH "context" "1" "some date" "version" "ConTeXt" -- we use a fake date as I don't want to polute the git repos
+ --
+ local runner = string.match(name,"^mtx%-(.*)")
+ if runner then
+ runner = formatters["mtxrun --script %s"](runner)
+ else
+ runner = name
+ end
+ --
+ result[#result+1] = formatters['.TH "%s" "1" "%s" "version %s" "%s"'](name,os.date("01-01-%Y"),version,detail)
+ result[#result+1] = formatters[".SH NAME\n.B %s"](name)
+ result[#result+1] = formatters[".SH SYNOPSIS\n.B %s [\n.I OPTIONS ...\n.B ] [\n.I FILENAMES\n.B ]"](runner)
+ result[#result+1] = formatters[".SH DESCRIPTION\n.B %s"](detail)
+ --
+ for category in xmlcollected(root,"/application/flags/category") do
+ if nofcategories > 1 then
+ result[#result+1] = formatters['.SH OPTIONS: %s'](string.upper(category.at.name or "all"))
+ else
+ result[#result+1] = ".SH OPTIONS"
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for flag in xmlcollected(subcategory,"/flag") do
+ local name, value, short = flagdata(flag)
+ if value == "" then
+ result[#result+1] = formatters[".TP\n.B --%s\n%s"](name,short)
+ else
+ result[#result+1] = formatters[".TP\n.B --%s=%s\n%s"](name,value,short)
+ end
+ end
+ end
+ end
+ local moreinfo = specification.moreinfo
+ if moreinfo and moreinfo ~= "" then
+ moreinfo = string.gsub(moreinfo,"[\n\r]([%a]+)%s*:%s*",'\n\n.B "%1:"\n')
+ result[#result+1] = formatters[".SH AUTHOR\n%s"](moreinfo)
+ end
+ return table.concat(result,"\n")
+end
+
+local craptemplate = [[
+<?xml version="1.0"?>
+<application>
+<metadata>
+<entry name="banner">%s</entry>
+</metadata>
+<verbose>
+%s
+</verbose>
+]]
+
+function exporters.xml(specification,...)
+ local helpinfo = specification.helpinfo
+ if type(helpinfo) == "string" then
+ if string.find(helpinfo,"^<%?xml") then
+ return helpinfo
+ end
+ elseif type(helpinfo) == "table" then
+ helpinfo = table.concat(helpinfo,"\n\n")
+ else
+ helpinfo = "no help"
+ end
+ return formatters[craptemplate](specification.banner or "?",helpinfo)
+end
+
+-- the following template is optimized a bit for space
+
+-- local bodytemplate = [[
+-- <h1>Command line options</h1>
+-- <table>
+-- <tr>
+-- <th style="width: 10em">flag</th>
+-- <th style="width: 8em">value</th>
+-- <th>description</th>
+-- </tr>
+-- <?lua
+-- for category in xml.collected(variables.root,"/application/flags/category") do
+-- if variables.nofcategories > 1 then
+-- ?><tr>
+-- <th colspan="3"><?lua inject(category.at.name) ?></th>
+-- </tr><?lua
+-- end
+-- for subcategory in xml.collected(category,"/subcategory") do
+-- ?><tr><th/><td/><td/></tr><?lua
+-- for flag in xml.collected(subcategory,"/flag") do
+-- local name, value, short = variables.flagdata(flag)
+-- ?><tr>
+-- <th>--<?lua inject(name) ?></th>
+-- <td><?lua inject(value) ?></td>
+-- <td><?lua inject(short) ?></td>
+-- </tr><?lua
+-- end
+-- end
+-- end
+-- ?>
+-- </table>
+-- <br/>
+-- <?lua
+-- for category in xml.collected(variables.root,"/application/examples/category") do
+-- local title = variables.categorytitle(category)
+-- if title ~= "" then
+-- ?><h1><?lua inject(title) ?></h1><?lua
+-- end
+-- for subcategory in xml.collected(category,"/subcategory") do
+-- for example in xml.collected(subcategory,"/example") do
+-- local command, comment = variables.exampledata(example)
+-- ?><tt><?lua inject(command) ?></tt><br/><?lua
+-- end
+-- ?><br/><?lua
+-- end
+-- end
+-- for comment in xml.collected(root,"/application/comments/comment") do
+-- ?><br/><?lua inject(xml.text(comment)) ?><br/><?lua
+-- end
+-- ?>
+-- ]]
+
+local bodytemplate = [[
+<h1>Command line options</h1>
+<table>
+ <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+ <?lua for category in xml.collected(variables.root,"/application/flags/category") do if variables.nofcategories > 1 then ?>
+ <tr><th colspan="3"><?lua inject(category.at.name) ?></th></tr>
+ <?lua end for subcategory in xml.collected(category,"/subcategory") do ?>
+ <tr><th/><td/><td/></tr>
+ <?lua for flag in xml.collected(subcategory,"/flag") do local name, value, short = variables.flagdata(flag) ?>
+ <tr><th>--<?lua inject(name) ?></th><td><?lua inject(value) ?></td><td><?lua inject(short) ?></td></tr>
+ <?lua end end end ?>
+</table>
+<br/>
+<?lua for category in xml.collected(variables.root,"/application/examples/category") do local title = variables.categorytitle(category) if title ~= "" then ?>
+<h1><?lua inject(title) ?></h1>
+<?lua end for subcategory in xml.collected(category,"/subcategory") do for example in xml.collected(subcategory,"/example") do local command, comment = variables.exampledata(example) ?>
+<tt><?lua inject(command) ?></tt>
+<br/><?lua end ?><br/><?lua end end for comment in xml.collected(root,"/application/comments/comment") do ?>
+<br/><?lua inject(xml.text(comment)) ?><br/><?lua end ?>
+]]
+
+function exporters.html(specification,...)
+ local root = xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs = xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref", function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories = select("#",...) == 0 and true or table.tohash { ... }
+ local nofcategories = xml.count(root,"/application/flags/category")
+ local name = xmlfilter(root,"/application/metadata/entry[@name='name']/text()")
+ local detail = xmlfilter(root,"/application/metadata/entry[@name='detail']/text()") or name
+ local version = xmlfilter(root,"/application/metadata/entry[@name='version']/text()") or "0.00"
+ local banner = specification.banner or detail or name
+ --
+ dofile(resolvers.findfile("trac-lmx.lua","tex"))
+ --
+ local htmltemplate = io.loaddata(resolvers.findfile("context-base.lmx","tex")) or "no template"
+ --
+ local body = lmx.convertstring(bodytemplate, {
+ nofcategories = nofcategories,
+ wantedcategories = wantedcategories,
+ root = root,
+ -- moreinfo = specification.moreinfo,
+ flagdata = flagdata,
+ exampledata = exampledata,
+ categorytitle = categorytitle,
+ })
+ local html = lmx.convertstring(htmltemplate, {
+ maintext = body,
+ title = banner,
+ bottomtext = "wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl",
+ })
+ --
+ return html
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-fil.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-fil.lua
new file mode 100644
index 00000000000..8cc903e2a62
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-fil.lua
@@ -0,0 +1,181 @@
+if not modules then modules = { } end modules ['trac-fil'] = {
+ version = 1.001,
+ comment = "for the moment for myself",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local rawset, tonumber, type, pcall = rawset, tonumber, type, pcall
+local format, concat = string.format, table.concat
+local openfile = io.open
+local date = os.date
+local sortedpairs = table.sortedpairs
+
+local P, C, Cc, Cg, Cf, Ct, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local lpegmatch = lpeg.match
+
+local patterns = lpeg.patterns
+local cardinal = patterns.cardinal
+local whitespace = patterns.whitespace^0
+
+local timestamp = Cf(Ct("") * (
+ Cg (Cc("year") * (cardinal/tonumber)) * P("-")
+ * Cg (Cc("month") * (cardinal/tonumber)) * P("-")
+ * Cg (Cc("day") * (cardinal/tonumber)) * P(" ")
+ * Cg (Cc("hour") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("minute") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("second") * (cardinal/tonumber)) * P("+")
+ * Cg (Cc("thour") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("tminute") * (cardinal/tonumber))
+)^0, rawset)
+
+local keysvalues = Cf(Ct("") * (
+ Cg(C(patterns.letter^0) * whitespace * "=" * whitespace * Cs(patterns.unquoted) * whitespace)
+)^0, rawset)
+
+local statusline = Cf(Ct("") * (
+ whitespace * P("[") * Cg(Cc("timestamp") * timestamp ) * P("]")
+ * whitespace * Cg(Cc("status" ) * keysvalues)
+),rawset)
+
+patterns.keysvalues = keysvalues
+patterns.statusline = statusline
+patterns.timestamp = timestamp
+
+loggers = loggers or { }
+
+local timeformat = format("[%%s%s]",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function loggers.makeline(t)
+ local result = { } -- minimize time that file is open
+ result[#result+1] = format(timeformat,date(dateformat))
+ for k, v in sortedpairs(t) do
+ local tv = type(v)
+ if tv == "string" then
+ if v ~= "password" then
+ result[#result+1] = format(" %s=%q",k,v)
+ end
+ elseif tv == "number" or tv == "boolean" then
+ result[#result+1] = format(" %s=%q",k,tostring(v))
+ end
+ end
+ return concat(result," ")
+end
+
+local function append(filename,...)
+ local f = openfile(filename,"a+")
+ if not f then
+ dir.mkdirs(file.dirname(filename))
+ f = openfile(filename,"a+")
+ end
+ if f then
+ f:write(...)
+ f:close()
+ return true
+ else
+ return false
+ end
+end
+
+function loggers.store(filename,data) -- a log service is nicer
+ if type(data) == "table"then
+ data = loggers.makeline(data)
+ end
+ pcall(append,filename,data,"\n")
+end
+
+function loggers.collect(filename,result)
+ if lfs.isfile(filename) then
+ local r = lpegmatch(Ct(statusline^0),io.loaddata(filename))
+ if result then -- append
+ local nofresult = #result
+ for i=1,#r do
+ nofresult = nofresult + 1
+ result[nofresult] = r[i]
+ end
+ return result
+ else
+ return r
+ end
+ else
+ return result or { }
+ end
+end
+
+function loggers.fields(results) -- returns hash of fields with counts so that we can decide on importance
+ local fields = { }
+ if results then
+ for i=1,#results do
+ local r = results[i]
+ for k, v in next, r do
+ local f = fields[k]
+ if not f then
+ fields[k] = 1
+ else
+ fields[k] = f + 1
+ end
+ end
+ end
+ end
+ return fields
+end
+
+local template = [[<!-- log entries: begin --!>
+<table>
+<tr>%s</tr>
+%s
+</table>
+<!-- log entries: end --!>
+]]
+
+function loggers.tohtml(entries,fields)
+ if not fields or #fields == 0 then
+ return ""
+ end
+ if type(entries) == "string" then
+ entries = loggers.collect(entries)
+ end
+ local scratch, lines = { }, { }
+ for i=1,#entries do
+ local entry = entries[i]
+ local status = entry.status
+ for i=1,#fields do
+ local field = fields[i]
+ local v = status[field.name]
+ if v ~= nil then
+ v = tostring(v)
+ local f = field.format
+ if f then
+ v = format(f,v)
+ end
+ scratch[i] = format("<td nowrap='nowrap' align='%s'>%s</td>",field.align or "left",v)
+ else
+ scratch[i] = "<td/>"
+ end
+ end
+ lines[i] = format("<tr>%s</tr>",concat(scratch))
+ end
+ for i=1,#fields do
+ local field = fields[i]
+ scratch[i] = format("<th nowrap='nowrap' align='left'>%s</th>", field.label or field.name)
+ end
+ local result = format(template,concat(scratch),concat(lines,"\n"))
+ return result, entries
+end
+
+-- loggers.store("test.log", { name = "whatever", more = math.random(1,100) })
+
+-- local fields = {
+-- { name = "name", align = "left" },
+-- { name = "more", align = "right" },
+-- }
+
+-- local entries = loggers.collect("test.log")
+-- local html = loggers.tohtml(entries,fields)
+
+-- inspect(entries)
+-- inspect(fields)
+-- inspect(html)
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua
new file mode 100644
index 00000000000..401fd01e7d9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua
@@ -0,0 +1,209 @@
+if not modules then modules = { } end modules ['trac-inf'] = {
+ version = 1.001,
+ comment = "companion to trac-inf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- As we want to protect the global tables, we no longer store the timing
+-- in the tables themselves but in a hidden timers table so that we don't
+-- get warnings about assignments. This is more efficient than using rawset
+-- and rawget.
+
+local type, tonumber, select = type, tonumber, select
+local format, lower, find = string.format, string.lower, string.find
+local concat = table.concat
+local clock = os.gettimeofday or os.clock -- should go in environment
+
+local setmetatableindex = table.setmetatableindex
+local serialize = table.serialize
+local formatters = string.formatters
+
+statistics = statistics or { }
+local statistics = statistics
+
+statistics.enable = true
+statistics.threshold = 0.01
+
+local statusinfo, n, registered, timers = { }, 0, { }, { }
+
+setmetatableindex(timers,function(t,k)
+ local v = { timing = 0, loadtime = 0 }
+ t[k] = v
+ return v
+end)
+
+local function hastiming(instance)
+ return instance and timers[instance]
+end
+
+local function resettiming(instance)
+ timers[instance or "notimer"] = { timing = 0, loadtime = 0 }
+end
+
+local function starttiming(instance)
+ local timer = timers[instance or "notimer"]
+ local it = timer.timing or 0
+ if it == 0 then
+ timer.starttime = clock()
+ if not timer.loadtime then
+ timer.loadtime = 0
+ end
+ end
+ timer.timing = it + 1
+end
+
+local function stoptiming(instance)
+ local timer = timers[instance or "notimer"]
+ local it = timer.timing
+ if it > 1 then
+ timer.timing = it - 1
+ else
+ local starttime = timer.starttime
+ if starttime then
+ local stoptime = clock()
+ local loadtime = stoptime - starttime
+ timer.stoptime = stoptime
+ timer.loadtime = timer.loadtime + loadtime
+ timer.timing = 0
+ return loadtime
+ end
+ end
+ return 0
+end
+
+local function elapsed(instance)
+ if type(instance) == "number" then
+ return instance or 0
+ else
+ local timer = timers[instance or "notimer"]
+ return timer and timer.loadtime or 0
+ end
+end
+
+local function elapsedtime(instance)
+ return format("%0.3f",elapsed(instance))
+end
+
+local function elapsedindeed(instance)
+ return elapsed(instance) > statistics.threshold
+end
+
+local function elapsedseconds(instance,rest) -- returns nil if 0 seconds
+ if elapsedindeed(instance) then
+ return format("%0.3f seconds %s", elapsed(instance),rest or "")
+ end
+end
+
+statistics.hastiming = hastiming
+statistics.resettiming = resettiming
+statistics.starttiming = starttiming
+statistics.stoptiming = stoptiming
+statistics.elapsed = elapsed
+statistics.elapsedtime = elapsedtime
+statistics.elapsedindeed = elapsedindeed
+statistics.elapsedseconds = elapsedseconds
+
+-- general function .. we might split this module
+
+function statistics.register(tag,fnc)
+ if statistics.enable and type(fnc) == "function" then
+ local rt = registered[tag] or (#statusinfo + 1)
+ statusinfo[rt] = { tag, fnc }
+ registered[tag] = rt
+ if #tag > n then n = #tag end
+ end
+end
+
+local report = logs.reporter("mkiv lua stats")
+
+function statistics.show()
+ if statistics.enable then
+ -- this code will move
+ local register = statistics.register
+ register("used platform", function()
+ return format("%s, type: %s, binary subtree: %s",
+ os.platform or "unknown",os.type or "unknown", environment.texos or "unknown")
+ end)
+ register("luatex banner", function()
+ return lower(status.banner)
+ end)
+ register("control sequences", function()
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
+ end)
+ register("callbacks", function()
+ local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
+ return format("%s direct, %s indirect, %s total", total-indirect, indirect, total)
+ end)
+ if jit then
+ local jitstatus = { jit.status() }
+ if jitstatus[1] then
+ register("luajit options", concat(jitstatus," ",2))
+ end
+ end
+ -- so far
+ -- collectgarbage("collect")
+ register("lua properties",function()
+ local hashchar = tonumber(status.luatex_hashchars)
+ local hashtype = status.luatex_hashtype
+ local mask = lua.mask or "ascii"
+ return format("engine: %s, used memory: %s, hash type: %s, hash chars: min(%s,40), symbol mask: %s (%s)",
+ jit and "luajit" or "lua",
+ statistics.memused(),
+ hashtype or "default",
+ hashchar and 2^hashchar or "unknown",
+ mask,
+ mask == "utf" and "τεχ" or "tex")
+ end)
+ register("runtime",statistics.runtime)
+ logs.newline() -- initial newline
+ for i=1,#statusinfo do
+ local s = statusinfo[i]
+ local r = s[2]()
+ if r then
+ report("%s: %s",s[1],r)
+ end
+ end
+ -- logs.newline() -- final newline
+ statistics.enable = false
+ end
+end
+
+function statistics.memused() -- no math.round yet -)
+ local round = math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000))
+end
+
+starttiming(statistics)
+
+function statistics.formatruntime(runtime) -- indirect so it can be overloaded and
+ return format("%s seconds", runtime) -- indeed that happens in cure-uti.lua
+end
+
+function statistics.runtime()
+ stoptiming(statistics)
+ return statistics.formatruntime(elapsedtime(statistics))
+end
+
+local report = logs.reporter("system")
+
+function statistics.timed(action)
+ starttiming("run")
+ action()
+ stoptiming("run")
+ report("total runtime: %s seconds",elapsedtime("run"))
+end
+
+-- goodie
+
+function statistics.tracefunction(base,tag,...)
+ for i=1,select("#",...) do
+ local name = select(i,...)
+ local stat = { }
+ local func = base[name]
+ setmetatableindex(stat,function(t,k) t[k] = 0 return 0 end)
+ base[name] = function(n,k,v) stat[k] = stat[k] + 1 return func(n,k,v) end
+ statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua
new file mode 100644
index 00000000000..ad1a098e27f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua
@@ -0,0 +1,115 @@
+if not modules then modules = { } end modules ['trac-jus'] = {
+ version = 1.001,
+ comment = "companion to trac-jus.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local checkers = typesetters.checkers or { }
+typesetters.checkers = checkers
+
+----- report_justification = logs.reporter("visualize","justification")
+
+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 setfield = nuts.setfield
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local setlist = nuts.setlist
+
+local traverse_id = nuts.traverse_id
+local get_list_dimensions = nuts.dimensions
+local linked_nodes = nuts.linked
+local copy_node = nuts.copy
+
+local tracedrule = nodes.tracers.pool.nuts.rule
+
+local nodepool = nuts.pool
+
+local new_rule = nodepool.rule
+local new_hlist = nodepool.hlist
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+
+local hlist_code = nodes.nodecodes.hlist
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local min_threshold = 0
+local max_threshold = 0
+
+local function set(n)
+ nodes.tasks.enableaction("mvlbuilders", "typesetters.checkers.handler")
+ nodes.tasks.enableaction("vboxbuilders","typesetters.checkers.handler")
+ texsetattribute(a_justification,n or 1)
+ function typesetters.checkers.set(n)
+ texsetattribute(a_justification,n or 1)
+ end
+end
+
+local function reset()
+ texsetattribute(a_justification,unsetvalue)
+end
+
+checkers.set = set
+checkers.reset = reset
+
+interfaces.implement {
+ name = "showjustification",
+ actions = set
+}
+
+trackers.register("visualizers.justification", function(v)
+ if v then
+ set(1)
+ else
+ reset()
+ end
+end)
+
+function checkers.handler(head)
+ for current in traverse_id(hlist_code,tonut(head)) do
+ if getattr(current,a_justification) == 1 then
+ setattr(current,a_justification,0) -- kind of reset
+ local width = getfield(current,"width")
+ if width > 0 then
+ local list = getlist(current)
+ if list then
+ local naturalwidth, naturalheight, naturaldepth = get_list_dimensions(list)
+ local delta = naturalwidth - width
+ if naturalwidth == 0 or delta == 0 then
+ -- special box
+ elseif delta >= max_threshold then
+ local rule = tracedrule(delta,naturalheight,naturaldepth,getfield(list,"glue_set") == 1 and "trace:dr" or "trace:db")
+ setlist(current,linked_nodes(list,new_hlist(rule)))
+ elseif delta <= min_threshold then
+ local alignstate = getattr(list,a_alignstate)
+ if alignstate == 1 then
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dc")
+ setlist(current,linked_nodes(new_hlist(rule),list))
+ elseif alignstate == 2 then
+ local lrule = tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy")
+ local rrule = copy_node(lrule)
+ setlist(current,linked_nodes(new_hlist(lrule),list,new_kern(delta/2),new_hlist(rrule)))
+ elseif alignstate == 3 then
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dm")
+ setlist(current,linked_nodes(list,new_kern(delta),new_hlist(rule)))
+ else
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dg")
+ setlist(current,linked_nodes(list,new_kern(delta),new_hlist(rule)))
+ end
+ end
+ end
+ end
+ end
+ end
+ return head
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-jus.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.mkiv
new file mode 100644
index 00000000000..71d88b00e42
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=trac-jus,
+%D version=2012.11.27,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=Justification,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Tracing Macros / Justification}
+
+\registerctxluafile{trac-jus}{1.001}
+
+\unprotect
+
+\definesystemattribute[justification] [public]
+
+\unexpanded\def\showjustification
+ {\clf_showjustification} % currently no argument (default 1)
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-lmx.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-lmx.lua
new file mode 100644
index 00000000000..4f4ea62c489
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-lmx.lua
@@ -0,0 +1,732 @@
+if not modules then modules = { } end modules ['trac-lmx'] = {
+ version = 1.002,
+ comment = "companion to trac-lmx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this one will be adpated to the latest helpers
+
+local type, tostring, rawget, loadstring, pcall = type, tostring, rawget, loadstring, pcall
+local format, sub, gsub = string.format, string.sub, string.gsub
+local concat = table.concat
+local collapsespaces = string.collapsespaces
+local P, Cc, Cs, C, Carg, lpegmatch = lpeg.P, lpeg.Cc, lpeg.Cs, lpeg.C, lpeg.Carg, lpeg.match
+local joinpath, replacesuffix, pathpart, filesuffix = file.join, file.replacesuffix, file.pathpart, file.suffix
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+----- trace_templates = false trackers .register("lmx.templates", function(v) trace_templates = v end)
+local trace_variables = false trackers .register("lmx.variables", function(v) trace_variables = v end)
+
+local cache_templates = true directives.register("lmx.cache.templates",function(v) cache_templates = v end)
+local cache_files = true directives.register("lmx.cache.files", function(v) cache_files = v end)
+
+local report_lmx = logs.reporter("lmx")
+local report_error = logs.reporter("lmx","error")
+
+lmx = lmx or { }
+local lmx = lmx
+
+-- This will change: we will just pass the global defaults as argument, but then we need
+-- to rewrite some older code or come up with an ugly trick.
+
+local lmxvariables = {
+ ['title-default'] = 'ConTeXt LMX File',
+ ['color-background-green'] = '#4F6F6F',
+ ['color-background-blue'] = '#6F6F8F',
+ ['color-background-yellow'] = '#8F8F6F',
+ ['color-background-purple'] = '#8F6F8F',
+ ['color-background-body'] = '#808080',
+ ['color-background-main'] = '#3F3F3F',
+}
+
+local lmxinherited = {
+ ['title'] = 'title-default',
+ ['color-background-one'] = 'color-background-green',
+ ['color-background-two'] = 'color-background-blue',
+ ['color-background-three'] = 'color-background-one',
+ ['color-background-four'] = 'color-background-two',
+}
+
+lmx.variables = lmxvariables
+lmx.inherited = lmxinherited
+
+setmetatableindex(lmxvariables,function(t,k)
+ k = lmxinherited[k]
+ while k do
+ local v = rawget(lmxvariables,k)
+ if v then
+ return v
+ end
+ k = lmxinherited[k]
+ end
+end)
+
+function lmx.set(key,value)
+ lmxvariables[key] = value
+end
+
+function lmx.get(key)
+ return lmxvariables[key] or ""
+end
+
+lmx.report = report_lmx
+
+-- helpers
+
+-- the variables table is an empty one that gets linked to a defaults table
+-- that gets passed with a creation (first time only) and that itself links
+-- to one that gets passed to the converter
+
+local variables = { } -- we assume no nesting
+local result = { } -- we assume no nesting
+
+local function do_print(one,two,...)
+ if two then
+ result[#result+1] = concat { one, two, ... }
+ else
+ result[#result+1] = one
+ end
+end
+
+-- Although it does not make much sense for most elements, we provide a mechanism
+-- to print wrapped content, something that is more efficient when we are constructing
+-- tables.
+
+local html = { }
+lmx.html = html
+
+function html.td(str)
+ if type(str) == "table" then
+ for i=1,#str do -- spoils t !
+ str[i] = format("<td>%s</td>",str[i] or "")
+ end
+ result[#result+1] = concat(str)
+ else
+ result[#result+1] = format("<td>%s</td>",str or "")
+ end
+end
+
+function html.th(str)
+ if type(str) == "table" then
+ for i=1,#str do -- spoils t !
+ str[i] = format("<th>%s</th>",str[i])
+ end
+ result[#result+1] = concat(str)
+ else
+ result[#result+1] = format("<th>%s</th>",str or "")
+ end
+end
+
+function html.a(text,url)
+ result[#result+1] = format("<a href=%q>%s</a>",url,text)
+end
+
+setmetatableindex(html,function(t,k)
+ local f = format("<%s>%%s</%s>",k,k)
+ local v = function(str) result[#result+1] = format(f,str or "") end
+ t[k] = v
+ return v
+end)
+
+-- Loading templates:
+
+local function loadedfile(name)
+ name = resolvers and resolvers.findfile and resolvers.findfile(name) or name
+ local data = io.loaddata(name)
+ if not data or data == "" then
+ report_lmx("file %a is empty",name)
+ end
+ return data
+end
+
+local function loadedsubfile(name)
+ return io.loaddata(resolvers and resolvers.findfile and resolvers.findfile(name) or name)
+end
+
+lmx.loadedfile = loadedfile
+
+-- A few helpers (the next one could end up in l-lpeg):
+
+local usedpaths = { }
+local givenpath = nil
+
+local do_nested_include = nil
+
+local pattern = lpeg.replacer {
+ ["&"] = "&amp;",
+ [">"] = "&gt;",
+ ["<"] = "&lt;",
+ ['"'] = "&quot;",
+}
+
+local function do_escape(str)
+ return lpegmatch(pattern,str) or str
+end
+
+local function do_variable(str)
+ local value = variables[str]
+ if not trace_variables then
+ -- nothing
+ elseif type(value) == "string" then
+ if #value > 80 then
+ report_lmx("variable %a is set to: %s ...",str,collapsespaces(sub(value,1,80)))
+ else
+ report_lmx("variable %a is set to: %s",str,collapsespaces(value))
+ end
+ elseif type(value) == "nil" then
+ report_lmx("variable %a is set to: %s",str,"<!-- unset -->")
+ else
+ report_lmx("variable %a is set to: %S",str,value)
+ end
+ if type(value) == "function" then -- obsolete ... will go away
+ return value(str)
+ else
+ return value
+ end
+end
+
+local function do_type(str)
+ if str and str ~= "" then
+ result[#result+1] = format("<tt>%s</tt>",do_escape(str))
+ end
+end
+
+local function do_fprint(str,...)
+ if str and str ~= "" then
+ result[#result+1] = format(str,...)
+ end
+end
+
+local function do_eprint(str,...)
+ if str and str ~= "" then
+ result[#result+1] = lpegmatch(pattern,format(str,...))
+ end
+end
+
+local function do_print_variable(str)
+ local str = do_variable(str) -- variables[str]
+ if str and str ~= "" then
+ result[#result+1] = str
+ end
+end
+
+local function do_type_variable(str)
+ local str = do_variable(str) -- variables[str]
+ if str and str ~= "" then
+ result[#result+1] = format("<tt>%s</tt>",do_escape(str))
+ end
+end
+
+local function do_include(filename,option)
+ local data = loadedsubfile(filename)
+ if (not data or data == "") and givenpath then
+ data = loadedsubfile(joinpath(givenpath,filename))
+ end
+ if (not data or data == "") and type(usedpaths) == "table" then
+ for i=1,#usedpaths do
+ data = loadedsubfile(joinpath(usedpaths[i],filename))
+ if data and data ~= "" then
+ break
+ end
+ end
+ end
+ if not data or data == "" then
+ data = format("<!-- unknown lmx include file: %s -->",filename)
+ report_lmx("include file %a is empty",filename)
+ else
+ -- report_lmx("included file: %s",filename)
+ data = do_nested_include(data)
+ end
+ if filesuffix(filename,"css") and option == "strip" then -- new
+ data = lmx.stripcss(data)
+ end
+ return data
+end
+
+-- Flushers:
+
+lmx.print = do_print
+lmx.type = do_type
+lmx.eprint = do_eprint
+lmx.fprint = do_fprint
+
+lmx.escape = do_escape
+lmx.urlescape = url.escape
+lmx.variable = do_variable
+lmx.include = do_include
+
+lmx.inject = do_print
+lmx.finject = do_fprint
+lmx.einject = do_eprint
+
+lmx.pv = do_print_variable
+lmx.tv = do_type_variable
+
+-- The next functions set up the closure.
+
+function lmx.initialize(d,v)
+ if not v then
+ setmetatableindex(d,lmxvariables)
+ if variables ~= d then
+ setmetatableindex(variables,d)
+ if trace_variables then
+ report_lmx("using chain: variables => given defaults => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("using chain: variables == given defaults => lmx variables")
+ end
+ elseif d ~= v then
+ setmetatableindex(v,d)
+ if d ~= lmxvariables then
+ setmetatableindex(d,lmxvariables)
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("using chain: variables => given variables => given defaults => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("using chain: variables == given variables => given defaults => lmx variables")
+ end
+ else
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("using chain: variabes => given variables => given defaults")
+ end
+ elseif trace_variables then
+ report_lmx("using chain: variables == given variables => given defaults")
+ end
+ end
+ else
+ setmetatableindex(v,lmxvariables)
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("using chain: variables => given variables => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("using chain: variables == given variables => lmx variables")
+ end
+ end
+ result = { }
+end
+
+function lmx.finalized()
+ local collapsed = concat(result)
+ result = { } -- free memory
+ return collapsed
+end
+
+function lmx.getvariables()
+ return variables
+end
+
+function lmx.reset()
+ -- obsolete
+end
+
+-- Creation: (todo: strip <!-- -->)
+
+-- local template = [[
+-- return function(defaults,variables)
+--
+-- -- initialize
+--
+-- lmx.initialize(defaults,variables)
+--
+-- -- interface
+--
+-- local definitions = { }
+-- local variables = lmx.getvariables()
+-- local html = lmx.html
+-- local inject = lmx.print
+-- local finject = lmx.fprint
+-- local einject = lmx.eprint
+-- local escape = lmx.escape
+-- local verbose = lmx.type
+--
+-- -- shortcuts (sort of obsolete as there is no gain)
+--
+-- local p = lmx.print
+-- local f = lmx.fprint
+-- local v = lmx.variable
+-- local e = lmx.escape
+-- local t = lmx.type
+-- local pv = lmx.pv
+-- local tv = lmx.tv
+--
+-- -- generator
+--
+-- %s
+--
+-- -- finalize
+--
+-- return lmx.finalized()
+--
+-- end
+-- ]]
+
+local template = [[
+-- interface
+
+local html = lmx.html
+local inject = lmx.print
+local finject = lmx.fprint -- better use the following
+local einject = lmx.eprint -- better use the following
+local injectf = lmx.fprint
+local injecte = lmx.eprint
+local injectfmt = lmx.fprint
+local injectesc = lmx.eprint
+local escape = lmx.escape
+local verbose = lmx.type
+
+local i_n_j_e_c_t = lmx.print
+
+-- shortcuts (sort of obsolete as there is no gain)
+
+local p = lmx.print
+local f = lmx.fprint
+local v = lmx.variable
+local e = lmx.escape
+local t = lmx.type
+local pv = lmx.pv
+local tv = lmx.tv
+
+local lmx_initialize = lmx.initialize
+local lmx_finalized = lmx.finalized
+local lmx_getvariables = lmx.getvariables
+
+-- generator
+
+return function(defaults,variables)
+
+ lmx_initialize(defaults,variables)
+
+ local definitions = { }
+ local variables = lmx_getvariables()
+
+ %s -- the action: appends to result
+
+ return lmx_finalized()
+
+end
+]]
+
+local function savedefinition(definitions,tag,content)
+ definitions[tag] = content
+ return ""
+end
+
+local function getdefinition(definitions,tag)
+ return definitions[tag] or ""
+end
+
+local whitespace = lpeg.patterns.whitespace
+local optionalspaces = whitespace^0
+
+local dquote = P('"')
+
+local begincomment = P("<!--") -- only makes sense when we in intercept pre|script|style
+local endcomment = P("-->")
+
+local beginembedxml = P("<?")
+local endembedxml = P("?>")
+
+local beginembedcss = P("/*")
+local endembedcss = P("*/")
+
+local gobbledendxml = (optionalspaces * endembedxml) / ""
+----- argumentxml = (1-gobbledendxml)^0
+local argumentxml = (whitespace^1 + dquote * C((1-dquote)^1) * dquote + C((1-gobbledendxml-whitespace)^1))^0
+
+local gobbledendcss = (optionalspaces * endembedcss) / ""
+----- argumentcss = (1-gobbledendcss)^0
+local argumentcss = (whitespace^1 + dquote * C((1-dquote)^1) * dquote + C((1-gobbledendcss-whitespace)^1))^0
+
+local commentxml = (begincomment * (1-endcomment)^0 * endcomment) / ""
+
+local beginluaxml = (beginembedxml * P("lua")) / ""
+local endluaxml = endembedxml / ""
+
+local luacodexml = beginluaxml
+ * (1-endluaxml)^1
+ * endluaxml
+
+local beginluacss = (beginembedcss * P("lua")) / ""
+local endluacss = endembedcss / ""
+
+local luacodecss = beginluacss
+ * (1-endluacss)^1
+ * endluacss
+
+local othercode = (1-beginluaxml-beginluacss)^1 / " i_n_j_e_c_t[==[%0]==] "
+
+local includexml = ((beginembedxml * P("lmx-include") * optionalspaces) / "")
+ * (argumentxml / do_include)
+ * gobbledendxml
+
+local includecss = ((beginembedcss * P("lmx-include") * optionalspaces) / "")
+ * (argumentcss / do_include)
+ * gobbledendcss
+
+local definexml_b = ((beginembedxml * P("lmx-define-begin") * optionalspaces) / "")
+ * argumentxml
+ * gobbledendxml
+
+local definexml_e = ((beginembedxml * P("lmx-define-end") * optionalspaces) / "")
+ * argumentxml
+ * gobbledendxml
+
+local definexml_c = C((1-definexml_e)^0)
+
+local definexml = (Carg(1) * C(definexml_b) * definexml_c * definexml_e) / savedefinition
+
+local resolvexml = ((beginembedxml * P("lmx-resolve") * optionalspaces) / "")
+ * ((Carg(1) * C(argumentxml)) / getdefinition)
+ * gobbledendxml
+
+local definecss_b = ((beginembedcss * P("lmx-define-begin") * optionalspaces) / "")
+ * argumentcss
+ * gobbledendcss
+
+local definecss_e = ((beginembedcss * P("lmx-define-end") * optionalspaces) / "")
+ * argumentcss
+ * gobbledendcss
+
+local definecss_c = C((1-definecss_e)^0)
+
+local definecss = (Carg(1) * C(definecss_b) * definecss_c * definecss_e) / savedefinition
+
+local resolvecss = ((beginembedcss * P("lmx-resolve") * optionalspaces) / "")
+ * ((Carg(1) * C(argumentcss)) / getdefinition)
+ * gobbledendcss
+
+----- pattern_1 = Cs((commentxml + includexml + includecss + P(1))^0) -- get rid of xml comments asap .. not good enough: embedded css and script is in <!-- .. also <pre>
+local pattern_1 = Cs((includexml + includecss + P(1))^0)
+local pattern_2 = Cs((definexml + resolvexml + definecss + resolvecss + P(1))^0)
+local pattern_3 = Cs((luacodexml + luacodecss + othercode)^0)
+
+local cache = { }
+
+local function lmxerror(str)
+ report_error(str)
+ return html.tt(str)
+end
+
+local function wrapper(converter,defaults,variables)
+ local outcome, message = pcall(converter,defaults,variables)
+ if not outcome then
+ return lmxerror(format("error in conversion: %s",message))
+ else
+ return message
+ end
+end
+
+do_nested_include = function(data) -- also used in include
+ return lpegmatch(pattern_1,data)
+end
+
+local function lmxnew(data,defaults,nocache,path) -- todo: use defaults in calling routines
+ data = data or ""
+ local known = cache[data]
+ if not known then
+ givenpath = path
+ usedpaths = lmxvariables.includepath or { }
+ if type(usedpaths) == "string" then
+ usedpaths = { usedpaths }
+ end
+ data = lpegmatch(pattern_1,data)
+ data = lpegmatch(pattern_2,data,1,{})
+ data = lpegmatch(pattern_3,data)
+ local converted = loadstring(format(template,data))
+ if converted then
+ converted = converted()
+ end
+ defaults = defaults or { }
+ local converter
+ if converted then
+ converter = function(variables)
+ return wrapper(converted,defaults,variables)
+ end
+ else
+ report_error("error in:\n%s\n:",data)
+ converter = function() lmxerror("error in template") end
+ end
+ known = {
+ data = defaults.trace and data or "",
+ variables = defaults,
+ converter = converter,
+ }
+ if cache_templates and nocache ~= false then
+ cache[data] = known
+ end
+ elseif variables then
+ known.variables = variables
+ end
+ return known, known.variables
+end
+
+local function lmxresult(self,variables)
+ if self then
+ local converter = self.converter
+ if converter then
+ local converted = converter(variables)
+ if trace_variables then -- will become templates
+ report_lmx("converted size: %s",#converted)
+ end
+ return converted or lmxerror("no result from converter")
+ else
+ return lmxerror("invalid converter")
+ end
+ else
+ return lmxerror("invalid specification")
+ end
+end
+
+lmx.new = lmxnew
+lmx.result = lmxresult
+
+local loadedfiles = { }
+
+function lmx.convertstring(templatestring,variables,nocache,path)
+ return lmxresult(lmxnew(templatestring,nil,nocache,path),variables)
+end
+
+function lmx.convertfile(templatefile,variables,nocache)
+ if trace_variables then -- will become templates
+ report_lmx("converting file %a",templatefile)
+ end
+ local converter = loadedfiles[templatefile]
+ if not converter then
+ converter = lmxnew(loadedfile(templatefile),nil,nocache,pathpart(templatefile))
+ loadedfiles[templatefile] = converter
+ end
+ return lmxresult(converter,variables)
+end
+
+local function lmxconvert(templatefile,resultfile,variables,nocache) -- or (templatefile,variables)
+ if trace_variables then -- will become templates
+ report_lmx("converting file %a",templatefile)
+ end
+ if not variables and type(resultfile) == "table" then
+ variables = resultfile
+ end
+ local converter = loadedfiles[templatefile]
+ if not converter then
+ converter = lmxnew(loadedfile(templatefile),nil,nocache,pathpart(templatefile))
+ if cache_files then
+ loadedfiles[templatefile] = converter
+ end
+ end
+ local result = lmxresult(converter,variables)
+ if resultfile then
+ io.savedata(resultfile,result)
+ else
+ return result
+ end
+end
+
+lmx.convert = lmxconvert
+
+-- helpers
+
+local nocomment = (beginembedcss * (1 - endembedcss)^1 * endembedcss) / ""
+local nowhitespace = whitespace^1 / " " -- ""
+local semistripped = whitespace^1 / "" * P(";")
+local stripper = Cs((nocomment + semistripped + nowhitespace + 1)^1)
+
+function lmx.stripcss(str)
+ return lpegmatch(stripper,str)
+end
+
+function lmx.color(r,g,b,a)
+ if r > 1 then
+ r = 1
+ end
+ if g > 1 then
+ g = 1
+ end
+ if b > 1 then
+ b = 1
+ end
+ if not a then
+ a= 0
+ elseif a > 1 then
+ a = 1
+ end
+ if a > 0 then
+ return format("rgba(%s%%,%s%%,%s%%,%s)",r*100,g*100,b*100,a)
+ else
+ return format("rgb(%s%%,%s%%,%s%%)",r*100,g*100,b*100)
+ end
+end
+
+-- these can be overloaded
+
+lmx.lmxfile = string.itself
+lmx.htmfile = string.itself
+lmx.popupfile = os.launch
+
+local function lmxmake(name,variables)
+ local lmxfile = lmx.lmxfile(name)
+ local htmfile = lmx.htmfile(name)
+ if lmxfile == htmfile then
+ htmfile = replacesuffix(lmxfile,"html")
+ end
+ lmxconvert(lmxfile,htmfile,variables)
+ return htmfile
+end
+
+lmx.make = lmxmake
+
+function lmx.show(name,variables)
+ local htmfile = lmxmake(name,variables)
+ lmx.popupfile(htmfile)
+ return htmfile
+end
+
+-- Command line (will become mtx-lmx):
+
+if arg then
+ if arg[1] == "--show" then if arg[2] then lmx.show (arg[2]) end
+ elseif arg[1] == "--convert" then if arg[2] then lmx.convert(arg[2], arg[3] or "temp.html") end
+ end
+end
+
+-- Test 1:
+
+-- inspect(lmx.result(lmx.new(io.loaddata("t:/sources/context-timing.lmx"))))
+
+-- Test 2:
+
+-- local str = [[
+-- <?lmx-include context.css strip ?>
+-- <test>
+-- <?lmx-define-begin whatever?>some content a<?lmx-define-end ?>
+-- <?lmx-define-begin somemore?>some content b<?lmx-define-end ?>
+-- <more>
+-- <?lmx-resolve whatever ?>
+-- <?lua
+-- for i=1,10 do end
+-- ?>
+-- <?lmx-resolve somemore ?>
+-- </more>
+-- <td><?lua p(100) ?></td>
+-- <td><?lua p(variables.a) ?></td>
+-- <td><?lua p(variables.b) ?></td>
+-- <td><?lua p(variables.c) ?></td>
+-- <td><?lua pv('title-default') ?></td>
+-- </test>
+-- ]]
+
+-- local defaults = { trace = true, a = 3, b = 3 }
+-- local result = lmx.new(str,defaults)
+-- inspect(result.data)
+-- inspect(result.converter(defaults))
+-- inspect(result.converter { a = 1 })
+-- inspect(lmx.result(result, { b = 2 }))
+-- inspect(lmx.result(result, { a = 20000, b = 40000 }))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua
new file mode 100644
index 00000000000..86557ef0927
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua
@@ -0,0 +1,1031 @@
+if not modules then modules = { } end modules ['trac-log'] = {
+ version = 1.001,
+ comment = "companion to trac-log.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- In fact all writes could go through lua and we could write the console and
+-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go.
+
+local next, type, select, print = next, type, select, print
+local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
+local format, gmatch, find = string.format, string.gmatch, string.find
+local concat, insert, remove = table.concat, table.insert, table.remove
+local topattern = string.topattern
+local utfchar = utf.char
+local datetime = os.date
+local openfile = io.open
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local texgetcount = tex and tex.getcount
+
+-- variant is set now
+
+local variant = "default"
+-- local variant = "ansi"
+
+-- todo: less categories, more subcategories (e.g. nodes)
+-- todo: split into basics and ctx specific
+
+--[[ldx--
+<p>This is a prelude to a more extensive logging module. We no longer
+provide <l n='xml'/> based logging as parsing is relatively easy anyway.</p>
+--ldx]]--
+
+logs = logs or { }
+local logs = logs
+
+local moreinfo = [[
+More information about ConTeXt and the tools that come with it can be found at:
+]] .. "\n" .. [[
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
+-- -- we extend the formatters:
+--
+-- function utilities.strings.unichr(s) return "U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")" end
+-- function utilities.strings.chruni(s) return utfchar(s) .. " (U+" .. format("%05X",s) .. ")" end
+--
+-- utilities.strings.formatters.add (
+-- string.formatters, "unichr",
+-- [[unichr(%s)]],
+-- [[local unichr = utilities.strings.unichr]]
+-- )
+--
+-- utilities.strings.formatters.add (
+-- string.formatters, "chruni",
+-- [[chruni(%s)]],
+-- [[local chruni = utilities.strings.chruni]]
+-- )
+
+formatters.add (
+ formatters, "unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+
+formatters.add (
+ formatters, "chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+
+-- function utilities.strings.unichk(s) return s <= 0xFFFF and ("U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")") or ("U+" .. format("%05X",s)) end
+-- function utilities.strings.chkuni(s) return s <= 0xFFFF and (utfchar(s) .. " (U+" .. format("%05X",s) .. ")") or ("U+" .. format("%05X",s)) end
+--
+-- utilities.strings.formatters.add (
+-- string.formatters, "unichk",
+-- [[unichk(%s)]],
+-- [[local unichk = utilities.strings.unichk]]
+-- )
+--
+-- utilities.strings.formatters.add (
+-- string.formatters, "chkuni",
+-- [[chkuni(%s)]],
+-- [[local chkuni = utilities.strings.chkuni]]
+-- )
+--
+-- print(formatters["Missing character %!chruni! in font."](234))
+-- print(formatters["Missing character %!unichr! in font."](234))
+-- print(formatters["Missing character %!chkuni! in font."](234))
+-- print(formatters["Missing character %!unichk! in font."](234))
+
+-- basic loggers
+
+local function ignore() end
+
+setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
+
+local report, subreport, status, settarget, setformats, settranslations
+
+local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline
+
+-- we use formatters but best check for % then because for simple messages but
+-- we don't want this overhead for single messages (not that there are that
+-- many; we could have a special weak table)
+
+if tex and (tex.jobname or tex.formatname) then
+
+ if texio.setescape then
+ texio.setescape(0) -- or (false)
+ end
+
+ local function useluawrites()
+
+ -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2)
+ -- still needed for luajittex .. luatex should not have that ^^ mess
+
+ local texio_write_nl = texio.write_nl
+ local texio_write = texio.write
+ local io_write = io.write
+
+ write_nl = function(target,...)
+ if not io_write then
+ io_write = io.write
+ end
+ if target == "term and log" then
+ texio_write_nl("log",...)
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target == "log" then
+ texio_write_nl("log",...)
+ elseif target == "term" then
+ texio_write_nl("term","")
+ io_write(...)
+ elseif type(target) == "number" then
+ texio_write_nl(target,...) -- a tex output channel
+ elseif target ~= "none" then
+ texio_write_nl("log",target,...)
+ texio_write_nl("term","")
+ io_write(target,...)
+ end
+ end
+
+ write = function(target,...)
+ if not io_write then
+ io_write = io.write
+ end
+ if target == "term and log" then
+ texio_write("log",...)
+ io_write(...)
+ elseif target == "log" then
+ texio_write("log",...)
+ elseif target == "term" then
+ io_write(...)
+ elseif type(target) == "number" then
+ texio_write(target,...) -- a tex output channel
+ elseif target ~= "none" then
+ texio_write("log",target,...)
+ io_write(target,...)
+ end
+ end
+
+ texio.write = write
+ texio.write_nl = write_nl
+
+ useluawrites = ignore
+
+ end
+
+ -- local format = string.formatter
+
+ local whereto = "both"
+ local target = nil
+ local targets = nil
+
+ local formats = table.setmetatableindex("self")
+ local translations = table.setmetatableindex("self")
+
+ local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes
+ local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop
+
+ local variants = {
+ default = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = {
+ logfile = "log",
+ log = "log",
+ file = "log",
+ console = "term",
+ terminal = "term",
+ both = "term and log",
+ },
+ },
+ ansi = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = {
+ logfile = "none",
+ log = "none",
+ file = "none",
+ console = "term",
+ terminal = "term",
+ both = "term",
+ },
+ }
+ }
+
+ logs.flush = io.flush
+
+ writer = function(...)
+ write_nl(target,...)
+ end
+
+ newline = function()
+ write_nl(target,"\n")
+ end
+
+ report = function(a,b,c,...)
+ if c ~= nil then
+ write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,report_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,report_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ direct = function(a,b,c,...)
+ if c ~= nil then
+ return direct_yes(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return direct_yes(translations[a],formats[b])
+ elseif a then
+ return direct_nop(translations[a])
+ else
+ return ""
+ end
+ end
+
+ subreport = function(a,s,b,c,...)
+ if c ~= nil then
+ write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,subreport_nop(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ subdirect = function(a,s,b,c,...)
+ if c ~= nil then
+ return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return subdirect_yes(translations[a],translations[s],formats[b])
+ elseif a then
+ return subdirect_nop(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+
+ status = function(a,b,c,...)
+ if c ~= nil then
+ write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,status_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,status_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ settarget = function(askedwhereto)
+ whereto = askedwhereto or whereto or "both"
+ target = targets[whereto]
+ if not target then
+ whereto = "both"
+ target = targets[whereto]
+ end
+ if target == "term" or target == "term and log" then
+ logs.flush = io.flush
+ else
+ logs.flush = ignore
+ end
+ end
+
+ local stack = { }
+
+ pushtarget = function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+
+ poptarget = function()
+ if #stack > 0 then
+ settarget(remove(stack))
+ end
+ end
+
+ setformats = function(f)
+ formats = f
+ end
+
+ settranslations = function(t)
+ translations = t
+ end
+
+ setprocessor = function(f)
+ local writeline = write_nl
+ write_nl = function(target,...)
+ writeline(target,f(...))
+ end
+ end
+
+ setformatters = function(specification)
+ local t = nil
+ local f = nil
+ local d = variants.default
+ if not specification then
+ --
+ elseif type(specification) == "table" then
+ t = specification.targets
+ f = specification.formats or specification
+ else
+ local v = variants[specification]
+ if v then
+ t = v.targets
+ f = v.formats
+ variant = specification
+ end
+ end
+ targets = t or d.targets
+ target = targets[whereto] or target
+ if f then
+ d = d.formats
+ else
+ f = d.formats
+ d = f
+ end
+ setmetatableindex(f,d)
+ report_yes = f.report_yes
+ report_nop = f.report_nop
+ subreport_yes = f.subreport_yes
+ subreport_nop = f.subreport_nop
+ direct_yes = f.direct_yes
+ direct_nop = f.direct_nop
+ subdirect_yes = f.subdirect_yes
+ subdirect_nop = f.subdirect_nop
+ status_yes = f.status_yes
+ status_nop = f.status_nop
+ if variant == "ansi" then
+ useluawrites() -- because tex escapes ^^
+ end
+ settarget(whereto)
+ end
+
+ setformatters(variant)
+
+ setlogfile = ignore
+ settimedlog = ignore
+
+else
+
+ local report_yes, subreport_yes, status_yes
+ local report_nop, subreport_nop, status_nop
+
+ local variants = {
+ default = {
+ formats = {
+ report_yes = formatters["%-15s | %s"],
+ report_nop = formatters["%-15s |"],
+ subreport_yes = formatters["%-15s | %s | %s"],
+ subreport_nop = formatters["%-15s | %s |"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ },
+ ansi = {
+ formats = {
+ report_yes = formatters["%-15s | %s"],
+ report_nop = formatters["%-15s |"],
+ subreport_yes = formatters["%-15s | %s | %s"],
+ subreport_nop = formatters["%-15s | %s |"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ },
+ }
+
+ logs.flush = ignore
+
+ writer = function(s)
+ write_nl(s)
+ end
+
+ newline = function()
+ write_nl("\n")
+ end
+
+ report = function(a,b,c,...)
+ if c then
+ write_nl(report_yes(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(report_yes(a,b))
+ elseif a then
+ write_nl(report_nop(a))
+ else
+ write_nl("")
+ end
+ end
+
+ subreport = function(a,sub,b,c,...)
+ if c then
+ write_nl(subreport_yes(a,sub,formatters[b](c,...)))
+ elseif b then
+ write_nl(subreport_yes(a,sub,b))
+ elseif a then
+ write_nl(subreport_nop(a,sub))
+ else
+ write_nl("")
+ end
+ end
+
+ status = function(a,b,c,...) -- not to be used in lua anyway
+ if c then
+ write_nl(status_yes(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(status_yes(a,b)) -- b can have %'s
+ elseif a then
+ write_nl(status_nop(a))
+ else
+ write_nl("\n")
+ end
+ end
+
+ direct = ignore
+ subdirect = ignore
+
+ settarget = ignore
+ pushtarget = ignore
+ poptarget = ignore
+ setformats = ignore
+ settranslations = ignore
+
+ setprocessor = function(f)
+ local writeline = write_nl
+ write_nl = function(s)
+ writeline(f(s))
+ end
+ end
+
+ setformatters = function(specification)
+ local f = nil
+ local d = variants.default
+ if specification then
+ if type(specification) == "table" then
+ f = specification.formats or specification
+ else
+ local v = variants[specification]
+ if v then
+ f = v.formats
+ end
+ end
+ end
+ if f then
+ d = d.formats
+ else
+ f = d.formats
+ d = f
+ end
+ setmetatableindex(f,d)
+ report_yes = f.report_yes
+ report_nop = f.report_nop
+ subreport_yes = f.subreport_yes
+ subreport_nop = f.subreport_nop
+ status_yes = f.status_yes
+ status_nop = f.status_nop
+ end
+
+ setformatters(variant)
+
+ setlogfile = function(name,keepopen)
+ if name and name ~= "" then
+ local localtime = os.localtime
+ local writeline = write_nl
+ if keepopen then
+ local f = io.open(name,"ab")
+ write_nl = function(s)
+ writeline(s)
+ f:write(localtime()," | ",s,"\n")
+ end
+ else
+ write_nl = function(s)
+ writeline(s)
+ local f = io.open(name,"ab")
+ f:write(localtime()," | ",s,"\n")
+ f:close()
+ end
+ end
+ end
+ setlogfile = ignore
+ end
+
+ settimedlog = function()
+ local localtime = os.localtime
+ local writeline = write_nl
+ write_nl = function(s)
+ writeline(localtime() .. " | " .. s)
+ end
+ settimedlog = ignore
+ end
+
+end
+
+logs.report = report
+logs.subreport = subreport
+logs.status = status
+logs.settarget = settarget
+logs.pushtarget = pushtarget
+logs.poptarget = poptarget
+logs.setformats = setformats
+logs.settranslations = settranslations
+
+logs.setlogfile = setlogfile
+logs.settimedlog = settimedlog
+logs.setprocessor = setprocessor
+logs.setformatters = setformatters
+
+logs.direct = direct
+logs.subdirect = subdirect
+logs.writer = writer
+logs.newline = newline
+
+-- installer
+
+-- todo: renew (un) locks when a new one is added and wildcard
+
+local data, states = { }, nil
+
+function logs.reporter(category,subcategory)
+ local logger = data[category]
+ if not logger then
+ local state = false
+ if states == true then
+ state = true
+ elseif type(states) == "table" then
+ for c, _ in next, states do
+ if find(category,c) then
+ state = true
+ break
+ end
+ end
+ end
+ logger = {
+ reporters = { },
+ state = state,
+ }
+ data[category] = logger
+ end
+ local reporter = logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter = function(...)
+ if not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory] = reporter
+ else
+ local tag = category
+ reporter = function(...)
+ if not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default = reporter
+ end
+ end
+ return reporter
+end
+
+logs.new = logs.reporter -- for old times sake
+
+-- context specicific: this ends up in the macro stream
+
+local ctxreport = logs.writer
+
+function logs.setmessenger(m)
+ ctxreport = m
+end
+
+function logs.messenger(category,subcategory)
+ -- we need to avoid catcode mess (todo: fast context)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
+end
+
+-- so far
+
+local function setblocked(category,value) -- v.state == value == true : disable
+ if category == true then
+ -- lock all
+ category, value = "*", true
+ elseif category == false then
+ -- unlock all
+ category, value = "*", false
+ elseif value == nil then
+ -- lock selective
+ value = true
+ end
+ if category == "*" then
+ states = value
+ for k, v in next, data do
+ v.state = value
+ end
+ else
+ states = utilities.parsers.settings_to_hash(category,type(states)=="table" and states or nil)
+ for c in next, states do
+ local v = data[c]
+ if v then
+ v.state = value
+ else
+ c = topattern(c,true,true)
+ for k, v in next, data do
+ if find(k,c) then
+ v.state = value
+ end
+ end
+ end
+ end
+ end
+end
+
+function logs.disable(category,value)
+ setblocked(category,value == nil and true or value)
+end
+
+function logs.enable(category)
+ setblocked(category,false)
+end
+
+function logs.categories()
+ return table.sortedkeys(data)
+end
+
+function logs.show()
+ local n, c, s, max = 0, 0, 0, 0
+ for category, v in table.sortedpairs(data) do
+ n = n + 1
+ local state = v.state
+ local reporters = v.reporters
+ local nc = #category
+ if nc > c then
+ c = nc
+ end
+ for subcategory, _ in next, reporters do
+ local ns = #subcategory
+ if ns > c then
+ s = ns
+ end
+ local m = nc + ns
+ if m > max then
+ max = m
+ end
+ end
+ local subcategories = concat(table.sortedkeys(reporters),", ")
+ if state == true then
+ state = "disabled"
+ elseif state == false then
+ state = "enabled"
+ else
+ state = "unknown"
+ end
+ -- no new here
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
+end
+
+local delayed_reporters = { }
+
+setmetatableindex(delayed_reporters,function(t,k)
+ local v = logs.reporter(k.name)
+ t[k] = v
+ return v
+end)
+
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
+end
+
+directives.register("logs.blocked", function(v)
+ setblocked(v,true)
+end)
+
+directives.register("logs.target", function(v)
+ settarget(v)
+end)
+
+-- tex specific loggers (might move elsewhere)
+
+local report_pages = logs.reporter("pages") -- not needed but saves checking when we grep for it
+
+local real, user, sub
+
+function logs.start_page_number()
+ real = texgetcount("realpageno")
+ user = texgetcount("userpageno")
+ sub = texgetcount("subpageno")
+end
+
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real <= 0 then
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
+ elseif user <= 0 then
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
+ elseif sub <= 0 then
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ end
+ else
+ if real <= 0 then
+ report_pages("flushing page")
+ elseif user <= 0 then
+ report_pages("flushing realpage %s",real)
+ elseif sub <= 0 then
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ end
+ end
+ logs.flush()
+end
+
+-- we don't have show_open and show_close callbacks yet
+
+local report_files = logs.reporter("files")
+local nesting = 0
+local verbose = false
+local hasscheme = url.hasscheme
+
+function logs.show_open(name)
+ -- if hasscheme(name) ~= "virtual" then
+ -- if verbose then
+ -- nesting = nesting + 1
+ -- report_files("level %s, opening %s",nesting,name)
+ -- else
+ -- write(formatters["(%s"](name)) -- tex adds a space
+ -- end
+ -- end
+end
+
+function logs.show_close(name)
+ -- if hasscheme(name) ~= "virtual" then
+ -- if verbose then
+ -- report_files("level %s, closing %s",nesting,name)
+ -- nesting = nesting - 1
+ -- else
+ -- write(")") -- tex adds a space
+ -- end
+ -- end
+end
+
+function logs.show_load(name)
+ -- if hasscheme(name) ~= "virtual" then
+ -- if verbose then
+ -- report_files("level %s, loading %s",nesting+1,name)
+ -- else
+ -- write(formatters["(%s)"](name))
+ -- end
+ -- end
+end
+
+-- there may be scripts out there using this:
+
+local simple = logs.reporter("comment")
+
+logs.simple = simple
+logs.simpleline = simple
+
+-- obsolete
+
+logs.setprogram = ignore -- obsolete
+logs.extendbanner = ignore -- obsolete
+logs.reportlines = ignore -- obsolete
+logs.reportbanner = ignore -- obsolete
+logs.reportline = ignore -- obsolete
+logs.simplelines = ignore -- obsolete
+logs.help = ignore -- obsolete
+
+-- applications
+
+-- local function reportlines(t,str)
+-- if str then
+-- for line in gmatch(str,"([^\n\r]*)[\n\r]") do
+-- t.report(line)
+-- end
+-- end
+-- end
+
+local Carg, C, lpegmatch = lpeg.Carg, lpeg.C, lpeg.match
+local p_newline = lpeg.patterns.newline
+
+local linewise = (
+ Carg(1) * C((1-p_newline)^1) / function(t,s) t.report(s) end
+ + Carg(1) * p_newline^2 / function(t) t.report() end
+ + p_newline
+)^1
+
+local function reportlines(t,str)
+ if str then
+ lpegmatch(linewise,str,1,t)
+ end
+end
+
+local function reportbanner(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ t.report()
+ end
+end
+
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
+local function reporthelp(t,...)
+ local helpinfo = t.helpinfo
+ if type(helpinfo) == "string" then
+ reportlines(t,helpinfo)
+ elseif type(helpinfo) == "table" then
+ for i=1,select("#",...) do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i < n then
+ t.report()
+ end
+ end
+ end
+end
+
+local function reportinfo(t)
+ t.report()
+ reportlines(t,t.moreinfo)
+end
+
+local function reportexport(t,method)
+ report(t.helpinfo)
+end
+
+local reporters = {
+ lines = reportlines, -- not to be overloaded
+ banner = reportbanner,
+ version = reportversion,
+ help = reporthelp,
+ info = reportinfo,
+ export = reportexport,
+}
+
+local exporters = {
+ -- empty
+}
+
+logs.reporters = reporters
+logs.exporters = exporters
+
+function logs.application(t)
+ t.name = t.name or "unknown"
+ t.banner = t.banner
+ t.moreinfo = moreinfo
+ t.report = logs.reporter(t.name)
+ t.help = function(...)
+ reporters.banner(t)
+ reporters.help(t,...)
+ reporters.info(t)
+ end
+ t.export = function(...)
+ reporters.export(t,...)
+ end
+ t.identify = function()
+ reporters.banner(t)
+ end
+ t.version = function()
+ reporters.version(t)
+ end
+ return t
+end
+
+-- somewhat special .. will be redone (already a better solution in place in lmx)
+
+-- logging to a file
+
+-- local syslogname = "oeps.xxx"
+--
+-- for i=1,10 do
+-- logs.system(syslogname,"context","test","fonts","font %s recached due to newer version (%s)","blabla","123")
+-- end
+
+local f_syslog = formatters["%s %s => %s => %s => %s\r"]
+
+function logs.system(whereto,process,jobname,category,fmt,arg,...)
+ local message = f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg == nil and fmt or format(fmt,arg,...))
+ for i=1,10 do
+ local f = openfile(whereto,"a") -- we can consider keeping the file open
+ if f then
+ f:write(message)
+ f:close()
+ break
+ else
+ sleep(0.1)
+ end
+ end
+end
+
+local report_system = logs.reporter("system","logs")
+
+function logs.obsolete(old,new)
+ local o = loadstring("return " .. new)()
+ if type(o) == "function" then
+ return function(...)
+ report_system("function %a is obsolete, use %a",old,new)
+ loadstring(old .. "=" .. new .. " return ".. old)()(...)
+ end
+ elseif type(o) == "table" then
+ local t, m = { }, { }
+ m.__index = function(t,k)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index, m.__newindex = o, o
+ return o[k]
+ end
+ m.__newindex = function(t,k,v)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index, m.__newindex = o, o
+ o[k] = v
+ end
+ if libraries then
+ libraries.obsolete[old] = t -- true
+ end
+ setmetatable(t,m)
+ return t
+ end
+end
+
+if utilities then
+ utilities.report = report_system
+end
+
+if tex and tex.error then
+ function logs.texerrormessage(...) -- for the moment we put this function here
+ tex.error(format(...), { })
+ end
+else
+ function logs.texerrormessage(...)
+ print(format(...))
+ end
+end
+
+-- this is somewhat slower but prevents out-of-order messages when print is mixed
+-- with texio.write
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
+-- windows: > nul 2>&1
+-- unix : > null 2>&1
+
+if package.helpers.report then
+ package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua
new file mode 100644
index 00000000000..fc3be5b6c55
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua
@@ -0,0 +1,144 @@
+if not modules then modules = { } end modules ['trac-par'] = {
+ version = 1.001,
+ comment = "companion to node-par.mkiv",
+ author = "Hans Hagen",
+ copyright = "ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "a translation of the built in parbuilder, initial convertsin by Taco Hoekwater",
+}
+
+-- todo: kern
+
+local utfchar = utf.char
+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 nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local setnodecolor = nodes.tracers.colors.set
+local parameters = fonts.hashes.parameters
+local basepoints = number.basepoints
+
+-- definecolor[hz:positive] [r=0.6]
+-- definecolor[hz:negative] [g=0.6]
+-- definecolor[hz:zero] [b=0.6]
+
+-- scale = multiplier + ef/multiplier
+
+local trace_both = false trackers.register("builders.paragraphs.expansion.both", function(v) trace_verbose = false trace_both = v end)
+local trace_verbose = false trackers.register("builders.paragraphs.expansion.verbose", function(v) trace_verbose = v trace_color = v end)
+
+local report_verbose = logs.reporter("fonts","expansion")
+
+local function colorize(n)
+ local size, font, ef, width, list, flush, length
+ if trace_verbose then
+ width = 0
+ length = 0
+ list = { }
+ flush = function()
+ if length > 0 then
+ report_verbose("%0.3f : %10s %10s %s",ef/1000,basepoints(width),basepoints(width*ef/1000000),concat(list,"",1,length))
+ width = 0
+ length = 0
+ end
+ end
+ else
+ length = 0
+ end
+ -- 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")
+ if ne == 0 then
+ if length > 0 then flush() end
+ setnodecolor(n,"hz:zero")
+ else
+ local f = getfont(n)
+ if f ~= font then
+ if length > 0 then
+ flush()
+ end
+ local pf = parameters[f]
+ local ex = pf.expansion
+ if ex and ex.auto then
+ size = pf.size
+ font = f -- save lookups
+ else
+ size = false
+ end
+ end
+ if size then
+ if ne ~= ef then
+ if length > 0 then
+ flush()
+ end
+ ef = ne
+ end
+ if ef > 1 then
+ setnodecolor(n,"hz:plus")
+ elseif ef < 1 then
+ setnodecolor(n,"hz:minus")
+ else
+ setnodecolor(n,"hz:zero")
+ end
+ if trace_verbose then
+ length = length + 1
+ list[length] = utfchar(getchar(n))
+ width = width + getfield(n,"width") -- no kerning yet
+ end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if length > 0 then
+ flush()
+ end
+ colorize(getlist(n),flush)
+ else -- nothing to show on kerns
+ if length > 0 then
+ flush()
+ end
+ end
+ n = getnext(n)
+ end
+ if length > 0 then
+ flush()
+ end
+end
+
+builders.paragraphs.expansion = builders.paragraphs.expansion or { }
+
+function builders.paragraphs.expansion.trace(head)
+ colorize(tonut(head),true)
+ return head
+end
+
+local tasks = nodes.tasks
+
+-- tasks.prependaction("shipouts","normalizers","builders.paragraphs.expansion.trace")
+-- tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
+
+local function set(v)
+ if v then
+ tasks.enableaction("shipouts","builders.paragraphs.expansion.trace")
+ else
+ tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
+ end
+end
+
+trackers.register("builders.paragraphs.expansion.verbose",set)
+trackers.register("builders.paragraphs.expansion.both",set)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-pro.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-pro.lua
new file mode 100644
index 00000000000..897b6a15c11
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-pro.lua
@@ -0,0 +1,210 @@
+if not modules then modules = { } end modules ['trac-pro'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local getmetatable, setmetatable, rawset, type = getmetatable, setmetatable, rawset, type
+
+-- The protection implemented here is probably not that tight but good enough to catch
+-- problems due to naive usage.
+--
+-- There's a more extensive version (trac-xxx.lua) that supports nesting.
+--
+-- This will change when we have _ENV in lua 5.2+
+
+local trace_namespaces = false trackers.register("system.namespaces", function(v) trace_namespaces = v end)
+
+local report_system = logs.reporter("system","protection")
+
+namespaces = namespaces or { }
+local namespaces = namespaces
+
+local registered = { }
+
+local function report_index(k,name)
+ if trace_namespaces then
+ report_system("reference to %a in protected namespace %a: %s",k,name)
+ debugger.showtraceback(report_system)
+ else
+ report_system("reference to %a in protected namespace %a",k,name)
+ end
+end
+
+local function report_newindex(k,name)
+ if trace_namespaces then
+ report_system("assignment to %a in protected namespace %a: %s",k,name)
+ debugger.showtraceback(report_system)
+ else
+ report_system("assignment to %a in protected namespace %a",k,name)
+ end
+end
+
+local function register(name)
+ local data = name == "global" and _G or _G[name]
+ if not data then
+ return -- error
+ end
+ registered[name] = data
+ local m = getmetatable(data)
+ if not m then
+ m = { }
+ setmetatable(data,m)
+ end
+ local index, newindex = { }, { }
+ m.__saved__index = m.__index
+ m.__no__index = function(t,k)
+ if not index[k] then
+ index[k] = true
+ report_index(k,name)
+ end
+ return nil
+ end
+ m.__saved__newindex = m.__newindex
+ m.__no__newindex = function(t,k,v)
+ if not newindex[k] then
+ newindex[k] = true
+ report_newindex(k,name)
+ end
+ rawset(t,k,v)
+ end
+ m.__protection__depth = 0
+end
+
+local function private(name) -- maybe save name
+ local data = registered[name]
+ if not data then
+ data = _G[name]
+ if not data then
+ data = { }
+ _G[name] = data
+ end
+ register(name)
+ end
+ return data
+end
+
+local function protect(name)
+ local data = registered[name]
+ if not data then
+ return
+ end
+ local m = getmetatable(data)
+ local pd = m.__protection__depth
+ if pd > 0 then
+ m.__protection__depth = pd + 1
+ else
+ m.__save_d_index, m.__saved__newindex = m.__index, m.__newindex
+ m.__index, m.__newindex = m.__no__index, m.__no__newindex
+ m.__protection__depth = 1
+ end
+end
+
+local function unprotect(name)
+ local data = registered[name]
+ if not data then
+ return
+ end
+ local m = getmetatable(data)
+ local pd = m.__protection__depth
+ if pd > 1 then
+ m.__protection__depth = pd - 1
+ else
+ m.__index, m.__newindex = m.__saved__index, m.__saved__newindex
+ m.__protection__depth = 0
+ end
+end
+
+local function protectall()
+ for name, _ in next, registered do
+ if name ~= "global" then
+ protect(name)
+ end
+ end
+end
+
+local function unprotectall()
+ for name, _ in next, registered do
+ if name ~= "global" then
+ unprotect(name)
+ end
+ end
+end
+
+namespaces.register = register -- register when defined
+namespaces.private = private -- allocate and register if needed
+namespaces.protect = protect
+namespaces.unprotect = unprotect
+namespaces.protectall = protectall
+namespaces.unprotectall = unprotectall
+
+namespaces.private("namespaces") registered = { } register("global") -- unreachable
+
+directives.register("system.protect", function(v)
+ if v then
+ protectall()
+ else
+ unprotectall()
+ end
+end)
+
+directives.register("system.checkglobals", function(v)
+ if v then
+ report_system("enabling global namespace guard")
+ protect("global")
+ else
+ report_system("disabling global namespace guard")
+ unprotect("global")
+ end
+end)
+
+-- dummy section (will go to luat-dum.lua)
+
+--~ if not namespaces.private then
+--~ -- somewhat protected
+--~ local registered = { }
+--~ function namespaces.private(name)
+--~ local data = registered[name]
+--~ if data then
+--~ return data
+--~ end
+--~ local data = _G[name]
+--~ if not data then
+--~ data = { }
+--~ _G[name] = data
+--~ end
+--~ registered[name] = data
+--~ return data
+--~ end
+--~ function namespaces.protectall(list)
+--~ for name, data in next, list or registered do
+--~ setmetatable(data, { __newindex = function() print(string.format("table %s is protected",name)) end })
+--~ end
+--~ end
+--~ namespaces.protectall { namespaces = namespaces }
+--~ end
+
+--~ directives.enable("system.checkglobals")
+
+--~ namespaces.register("resolvers","trackers")
+--~ namespaces.protect("resolvers")
+--~ namespaces.protect("resolvers")
+--~ namespaces.protect("resolvers")
+--~ namespaces.unprotect("resolvers")
+--~ namespaces.unprotect("resolvers")
+--~ namespaces.unprotect("resolvers")
+--~ namespaces.protect("trackers")
+
+--~ resolvers.x = true
+--~ resolvers.y = true
+--~ trackers.a = ""
+--~ resolvers.z = true
+--~ oeps = { }
+
+--~ resolvers = namespaces.private("resolvers")
+--~ fonts = namespaces.private("fonts")
+--~ directives.enable("system.protect")
+--~ namespaces.protectall()
+--~ resolvers.xx = { }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua
new file mode 100644
index 00000000000..9e2bf87589a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua
@@ -0,0 +1,380 @@
+if not modules then modules = { } end modules ['trac-set'] = { -- might become util-set.lua
+ 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"
+}
+
+-- maybe this should be util-set.lua
+
+local type, next, tostring = type, next, tostring
+local concat = table.concat
+local format, find, lower, gsub, topattern = string.format, string.find, string.lower, string.gsub, string.topattern
+local is_boolean = string.is_boolean
+local settings_to_hash = utilities.parsers.settings_to_hash
+local allocate = utilities.storage.allocate
+
+utilities = utilities or { }
+local utilities = utilities
+
+local setters = utilities.setters or { }
+utilities.setters = setters
+
+local data = { }
+
+-- We can initialize from the cnf file. This is sort of tricky as
+-- later defined setters also need to be initialized then. If set
+-- this way, we need to ensure that they are not reset later on.
+
+local trace_initialize = false -- only for testing during development
+
+function setters.initialize(filename,name,values) -- filename only for diagnostics
+ local setter = data[name]
+ if setter then
+ frozen = true -- don't permitoverload
+ -- trace_initialize = true
+ local data = setter.data
+ if data then
+ for key, newvalue in next, values do
+ local newvalue = is_boolean(newvalue,newvalue,true) -- strict
+ local functions = data[key]
+ if functions then
+ local oldvalue = functions.value
+ if functions.frozen then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
+ end
+ elseif #functions > 0 and not oldvalue then
+-- elseif #functions > 0 and oldvalue == nil then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
+ end
+ for i=1,#functions do
+ functions[i](newvalue)
+ end
+ functions.value = newvalue
+ functions.frozen = functions.frozen or frozen
+ else
+ if trace_initialize then
+ setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
+ end
+ end
+ else
+ -- we do a simple preregistration i.e. not in the
+ -- list as it might be an obsolete entry
+ functions = { default = newvalue, frozen = frozen }
+ data[key] = functions
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
+ end
+ end
+ end
+ return true
+ end
+ end
+end
+
+-- user interface code
+
+local function set(t,what,newvalue)
+ local data = t.data
+ if not data.frozen then
+ local done = t.done
+ if type(what) == "string" then
+ what = settings_to_hash(what) -- inefficient but ok
+ end
+ if type(what) ~= "table" then
+ return
+ end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
+ for w, value in next, what do
+ if value == "" then
+ value = newvalue
+ elseif not value then
+ value = false -- catch nil
+ else
+ value = is_boolean(value,value,true) -- strict
+ end
+ w = topattern(w,true,true)
+ for name, functions in next, data do
+ if done[name] then
+ -- prevent recursion due to wildcards
+ elseif find(name,w) then
+ done[name] = true
+ for i=1,#functions do
+ functions[i](value)
+ end
+ functions.value = value
+ end
+ end
+ end
+ end
+end
+
+local function reset(t)
+ local data = t.data
+ if not data.frozen then
+ for name, functions in next, data do
+ for i=1,#functions do
+ functions[i](false)
+ end
+ functions.value = false
+ end
+ end
+end
+
+local function enable(t,what)
+ set(t,what,true)
+end
+
+local function disable(t,what)
+ local data = t.data
+ if not what or what == "" then
+ t.done = { }
+ reset(t)
+ else
+ set(t,what,false)
+ end
+end
+
+function setters.register(t,what,...)
+ local data = t.data
+ what = lower(what)
+ local functions = data[what]
+ if not functions then
+ functions = { }
+ data[what] = functions
+ if trace_initialize then
+ t.report("defining %a",what)
+ end
+ end
+ local default = functions.default -- can be set from cnf file
+ for i=1,select("#",...) do
+ local fnc = select(i,...)
+ local typ = type(fnc)
+ if typ == "string" then
+ if trace_initialize then
+ t.report("coupling %a to %a",what,fnc)
+ end
+ local s = fnc -- else wrong reference
+ fnc = function(value) set(t,s,value) end
+ elseif typ ~= "function" then
+ fnc = nil
+ end
+ if fnc then
+ functions[#functions+1] = fnc
+ -- default: set at command line or in cnf file
+ -- value : set in tex run (needed when loading runtime)
+ local value = functions.value or default
+ if value ~= nil then
+ fnc(value)
+ functions.value = value
+ end
+ end
+ end
+ return false -- so we can use it in an assignment
+end
+
+function setters.enable(t,what)
+ local e = t.enable
+ t.enable, t.done = enable, { }
+ enable(t,what)
+ t.enable, t.done = e, { }
+end
+
+function setters.disable(t,what)
+ local e = t.disable
+ t.disable, t.done = disable, { }
+ disable(t,what)
+ t.disable, t.done = e, { }
+end
+
+function setters.reset(t)
+ t.done = { }
+ reset(t)
+end
+
+function setters.list(t) -- pattern
+ local list = table.sortedkeys(t.data)
+ local user, system = { }, { }
+ for l=1,#list do
+ local what = list[l]
+ if find(what,"^%*") then
+ system[#system+1] = what
+ else
+ user[#user+1] = what
+ end
+ end
+ return user, system
+end
+
+function setters.show(t)
+ local category = t.name
+ local list = setters.list(t)
+ t.report()
+ for k=1,#list do
+ local name = list[k]
+ local functions = t.data[name]
+ if functions then
+ local value, default, modules = functions.value, functions.default, #functions
+ value = value == nil and "unset" or tostring(value)
+ default = default == nil and "unset" or tostring(default)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
+ end
+ end
+ t.report()
+end
+
+-- we could have used a bit of oo and the trackers:enable syntax but
+-- there is already a lot of code around using the singular tracker
+
+-- we could make this into a module but we also want the rest avaliable
+
+local enable, disable, register, list, show = setters.enable, setters.disable, setters.register, setters.list, setters.show
+
+function setters.report(setter,...)
+ print(format("%-15s : %s\n",setter.name,format(...)))
+end
+
+local function default(setter,name)
+ local d = setter.data[name]
+ return d and d.default
+end
+
+local function value(setter,name)
+ local d = setter.data[name]
+ return d and (d.value or d.default)
+end
+
+function setters.new(name) -- we could use foo:bar syntax (but not used that often)
+ local setter -- we need to access it in setter itself
+ setter = {
+ data = allocate(), -- indexed, but also default and value fields
+ name = name,
+ report = function(...) setters.report (setter,...) end,
+ enable = function(...) enable (setter,...) end,
+ disable = function(...) disable (setter,...) end,
+ reset = function(...) reset (setter,...) end, -- can be dangerous
+ register = function(...) register(setter,...) end,
+ list = function(...) list (setter,...) end,
+ show = function(...) show (setter,...) end,
+ default = function(...) return default (setter,...) end,
+ value = function(...) return value (setter,...) end,
+ }
+ data[name] = setter
+ return setter
+end
+
+trackers = setters.new("trackers")
+directives = setters.new("directives")
+experiments = setters.new("experiments")
+
+local t_enable, t_disable = trackers .enable, trackers .disable
+local d_enable, d_disable = directives .enable, directives .disable
+local e_enable, e_disable = experiments.enable, experiments.disable
+
+-- nice trick: we overload two of the directives related functions with variants that
+-- do tracing (itself using a tracker) .. proof of concept
+
+local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
+local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
+
+function directives.enable(...)
+ if trace_directives then
+ directives.report("enabling: % t",{...})
+ end
+ d_enable(...)
+end
+
+function directives.disable(...)
+ if trace_directives then
+ directives.report("disabling: % t",{...})
+ end
+ d_disable(...)
+end
+
+function experiments.enable(...)
+ if trace_experiments then
+ experiments.report("enabling: % t",{...})
+ end
+ e_enable(...)
+end
+
+function experiments.disable(...)
+ if trace_experiments then
+ experiments.report("disabling: % t",{...})
+ end
+ e_disable(...)
+end
+
+-- a useful example
+
+directives.register("system.nostatistics", function(v)
+ if statistics then
+ statistics.enable = not v
+ else
+ -- forget about it
+ end
+end)
+
+directives.register("system.nolibraries", function(v)
+ if libraries then
+ libraries = nil -- we discard this tracing for security
+ else
+ -- no libraries defined
+ end
+end)
+
+-- experiment
+
+if environment then
+
+ -- The engineflags are known earlier than environment.arguments but maybe we
+ -- need to handle them both as the later are parsed differently. The c: prefix
+ -- is used by mtx-context to isolate the flags from those that concern luatex.
+
+ local engineflags = environment.engineflags
+
+ if engineflags then
+ local list = engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list) == "string" then
+ setters.initialize("commandline flags","trackers",settings_to_hash(list))
+ -- t_enable(list)
+ end
+ local list = engineflags["c:directives"] or engineflags["directives"]
+ if type(list) == "string" then
+ setters.initialize("commandline flags","directives", settings_to_hash(list))
+ -- d_enable(list)
+ end
+ end
+
+end
+
+-- here
+
+if texconfig then
+
+ -- this happens too late in ini mode but that is no problem
+
+ local function set(k,v)
+ v = tonumber(v)
+ if v then
+ texconfig[k] = v
+ end
+ end
+
+ directives.register("luatex.expanddepth", function(v) set("expand_depth",v) end)
+ directives.register("luatex.hashextra", function(v) set("hash_extra",v) end)
+ directives.register("luatex.nestsize", function(v) set("nest_size",v) end)
+ directives.register("luatex.maxinopen", function(v) set("max_in_open",v) end)
+ directives.register("luatex.maxprintline", function(v) set("max_print_line",v) end)
+ directives.register("luatex.maxstrings", function(v) set("max_strings",v) end)
+ directives.register("luatex.paramsize", function(v) set("param_size",v) end)
+ directives.register("luatex.savesize", function(v) set("save_size",v) end)
+ directives.register("luatex.stacksize", function(v) set("stack_size",v) end)
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-tex.lua
new file mode 100644
index 00000000000..86f3b539f30
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-tex.lua
@@ -0,0 +1,118 @@
+if not modules then modules = { } end modules ['trac-tex'] = {
+ version = 1.001,
+ comment = "companion to trac-deb.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- moved from trac-deb.lua
+
+local next = next
+
+local texhashtokens = tex.hashtokens
+
+local trackers = trackers
+local token = token
+local saved = { }
+
+function trackers.savehash()
+ saved = texhashtokens()
+end
+
+function trackers.dumphashtofile(filename,delta)
+ local list = { }
+ local hash = tex.hashtokens()
+ local create = token.create
+ for name, token in next, hash do
+ if not delta or not saved[name] then
+ if token[2] ~= 0 then -- still old interface
+ local token = create(name)
+ -- inspect(token)
+ local category = token.cmdname
+ local dk = list[category]
+ if not dk then
+ dk = {
+ names = { },
+ found = 0,
+ -- code = token[1],
+ }
+ list[category] = dk
+ end
+ if token.protected then
+ if token.expandable then
+ dk.names[name] = "ep"
+ else
+ dk.names[name] = "-p"
+ end
+ else
+ if token.expandable then
+ dk.names[name] = "ep"
+ else
+ dk.names[name] = "--"
+ end
+ end
+ dk.found = dk.found + 1
+ end
+ end
+ end
+ table.save(filename or tex.jobname .. "-hash.log",list)
+end
+
+-- -- old token code
+--
+-- function trackers.dumphashtofile(filename,delta)
+-- local list = { }
+-- local hash = texhashtokens()
+-- local getname = token.command_name
+-- for name, token in next, hash do
+-- if not delta or not saved[name] then
+-- -- token: cmd, chr, csid -- combination cmd,chr determines name
+-- local category = getname(token)
+-- local dk = list[category]
+-- if not dk then
+-- -- a bit funny names but this sorts better (easier to study)
+-- dk = { names = { }, found = 0, code = token[1] }
+-- list[category] = dk
+-- end
+-- dk.names[name] = { token[2], token[3] }
+-- dk.found = dk.found + 1
+-- end
+-- end
+-- table.save(filename or tex.jobname .. "-hash.log",list)
+-- end
+
+local delta = nil
+
+local function dump_hash(wanteddelta)
+ if delta == nil then
+ saved = saved or texhashtokens() -- no need for trackers.dump_hash
+ luatex.registerstopactions(1,function() dump_hash(nil,wanteddelta) end) -- at front
+ end
+ delta = wanteddelta
+end
+
+directives.register("system.dumphash", function() dump_hash(false) end)
+directives.register("system.dumpdelta", function() dump_hash(true ) end)
+
+local report_dump = logs.reporter("resolvers","dump")
+
+local function saveusedfilesintrees(format)
+ local data = {
+ jobname = environment.jobname or "?",
+ version = environment.version or "?",
+ kind = environment.kind or "?",
+ files = resolvers.instance.foundintrees
+ }
+ local filename = file.replacesuffix(environment.jobname or "context-job",'jlg')
+ if format == "lua" then
+ io.savedata(filename,table.serialize(data,true))
+ else
+ io.savedata(filename,table.toxml(data,"job"))
+ end
+end
+
+directives.register("system.dumpfiles", function(v)
+ luatex.registerstopactions(function() saveusedfilesintrees(v) end)
+end)
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-tex.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-tex.mkiv
new file mode 100644
index 00000000000..53c95ab01d7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-tex.mkiv
@@ -0,0 +1,42 @@
+%D \module
+%D [ file=trac-tex,
+%D version=2009.07.20,
+%D title=\CONTEXT\ Tracking Macros,
+%D subtitle=\TEX,
+%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 Tracking Macros / TeX}
+
+\registerctxluafile{trac-tex}{1.001}
+
+%D All tracing flags at the \TEX\ end will be redone this way so
+%D that we have a similar mechanism for \TEX\ and \LUA. Also, the
+%D currently used if's might become conditionals.
+
+\unprotect
+
+% \def\enabletextracerwhatever {...}
+% \def\disabletextracerwhatever{...}
+
+\let\alltextracers\empty % so that we can report available tracers
+
+\unexpanded\def\installtextracer#1%
+ {\addtocommalist{#1}\alltextracers}
+
+\unexpanded\def\enabletextracers [#1]{\processcommalist[#1]\syst_textracers_enable }
+\unexpanded\def\disabletextracers[#1]{\processcommalist[#1]\syst_textracers_disable}
+
+\def\syst_textracers_enable #1{\csname enabletracer#1\endcsname}
+\def\syst_textracers_disable#1{\csname disabletracer#1\endcsname}
+
+% The next one is for Taco, although we can use directives as well:
+
+\unexpanded\def\nomkivstatistics{\enabledirectives[system.nostatistics]}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-tim.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-tim.lua
new file mode 100644
index 00000000000..b4744291ce0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-tim.lua
@@ -0,0 +1,138 @@
+if not modules then modules = { } end modules ['trac-tim'] = {
+ version = 1.001,
+ comment = "companion to m-timing.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, gsub = string.format, string.gsub
+local concat, sort = table.concat, table.sort
+local next, tonumber = next, tonumber
+
+moduledata = moduledata or { }
+local progress = moduledata.progress or { }
+moduledata.progress = progress
+
+local report_timing = logs.reporter("timing")
+
+if not nodes then nodes = { } end -- when loaded in mtxrun
+
+progress.parameters = nodes and nodes.snapshots.getparameters
+progress.defaultfilename = ((tex and tex.jobname) or "whatever") .. "-luatex-progress"
+
+-- storage
+
+function progress.store()
+ nodes.snapshots.takesample()
+end
+
+function progress.save(name)
+ local filename = (name or progress.defaultfilename) .. ".lut"
+ report_timing("saving data in %a",filename)
+ table.save(filename,nodes.snapshots.getsamples())
+ nodes.snapshots.resetsamples()
+end
+
+-- conversion
+
+local processed = { }
+local parameters = progress.parameters()
+
+local function convert(name)
+ name = name ~= "" and name or progress.defaultfilename
+ if not processed[name] then
+ local names, top, bot, pages, paths, keys = { }, { }, { }, 0, { }, { }
+ local data = table.load(name .. ".lut")
+ if data then
+ pages = #data
+ if pages > 1 then
+ local factor = 100
+ for k=1,#data do
+ for k, v in next, data[k].node_memory do
+ keys[k] = true
+ end
+ end
+ for k=1,#data do
+ local m = data[k].node_memory
+ for k, v in next, keys do
+ if not m[k] then m[k] = 0 end
+ end
+ end
+ local function path(tag,subtag)
+ local b, t, s = nil, nil, { }
+ for k=1,#data do
+ local v = data[k][tag]
+ v = v and (subtag and v[subtag]) or v
+ if v then
+ v = tonumber(v)
+ if b then
+ if v > t then t = v end
+ if v < b then b = v end
+ else
+ t = v
+ b = v
+ end
+ s[k] = v
+ else
+ s[k] = 0
+ end
+ end
+ local tagname = subtag or tag
+ top[tagname] = gsub(format("%.3f",t),"%.000$","")
+ bot[tagname] = gsub(format("%.3f",b),"%.000$","")
+ local delta = t-b
+ if delta == 0 then
+ delta = 1
+ else
+ delta = factor/delta
+ end
+ for k=1,#s do
+ s[k] = format("(%.3f,%.3f)",k,(s[k]-b)*delta)
+ end
+ paths[tagname] = concat(s,"--")
+ end
+ for i=1,#parameters do
+ path(parameters[i])
+ end
+ for tag, _ in next, keys do
+ path("node_memory",tag)
+ names[#names+1] = tag
+ end
+ pages = pages - 1
+ end
+ end
+ sort(names)
+ processed[name] = {
+ names = names,
+ top = top,
+ bot = bot,
+ pages = pages,
+ paths = paths,
+ }
+ end
+ return processed[name]
+end
+
+progress.convert = convert
+
+function progress.bot(name,tag)
+ return convert(name).bot[tag] or 0
+end
+
+function progress.top(name,tag)
+ return convert(name).top[tag] or 0
+end
+
+function progress.pages(name,tag)
+ return convert(name).pages or 0
+end
+
+function progress.path(name,tag)
+ return convert(name).paths[tag] or "origin"
+end
+
+function progress.nodes(name)
+ return convert(name).names or { }
+end
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua
new file mode 100644
index 00000000000..061cef8ba5c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua
@@ -0,0 +1,1107 @@
+if not modules then modules = { } end modules ['trac-vis'] = {
+ version = 1.001,
+ comment = "companion to trac-vis.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string, number, table = string, number, table
+local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex
+local type = type
+local format = string.format
+local formatters = string.formatters
+
+-- This module started out in the early days of mkiv and luatex with
+-- visualizing kerns related to fonts. In the process of cleaning up the
+-- visual debugger code it made sense to integrate some other code that
+-- I had laying around and replace the old supp-vis debugging code. As
+-- only a subset of the old visual debugger makes sense it has become a
+-- different implementation. Soms of the m-visual functionality will also
+-- be ported. The code is rather trivial. The caching is not really needed
+-- but saves upto 50% of the time needed to add visualization. Of course
+-- the overall runtime is larger because of color and layer processing in
+-- the backend (can be times as much) so the runtime is somewhat larger
+-- with full visualization enabled. In practice this will never happen
+-- unless one is demoing.
+
+-- We could use pdf literals and re stream codes but it's not worth the
+-- trouble because we would end up in color etc mess. Maybe one day I'll
+-- make a nodeinjection variant.
+
+-- todo: global switch (so no attributes)
+-- todo: maybe also xoffset, yoffset of glyph
+-- todo: inline concat (more efficient)
+-- todo: tags can also be numbers (just add to hash)
+
+-- todo: dir and localpar nodes
+
+local nodecodes = nodes.nodecodes
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local whatsit_code = nodecodes.whatsit
+local user_code = nodecodes.user
+local math_code = nodecodes.math
+local gluespec_code = nodecodes.gluespec
+
+local kerncodes = nodes.kerncodes
+local font_kern_code = kerncodes.fontkern
+local user_kern_code = kerncodes.userkern
+
+local gluecodes = nodes.gluecodes
+local cleaders_code = gluecodes.cleaders
+local userskip_code = gluecodes.userskip
+local space_code = gluecodes.space
+local xspace_code = gluecodes.xspace
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+
+local whatsitcodes = nodes.whatsitcodes
+local mathcodes = nodes.mathcodes
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local setfield = nuts.setfield
+local setboth = nuts.setboth
+local setlink = nuts.setlink
+local setdisc = nuts.setdisc
+local setlist = nuts.setlist
+local setleader = nuts.setleader
+local setsubtype = nuts.setsubtype
+local setattr = nuts.setattr
+
+local 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
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getdisc = nuts.getdisc
+
+local hpack_nodes = nuts.hpack
+local vpack_nodes = nuts.vpack
+local copy_node = nuts.copy
+local copy_list = nuts.copy_list
+local free_node = nuts.free
+local free_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 linked_nodes = nuts.linked
+
+local effectiveglue = nuts.effective_glue
+
+local hpack_string = nuts.typesetters.tohpack
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local fonthashes = fonts.hashes
+local chardata = fonthashes.characters
+local exheights = fonthashes.exheights
+local emwidths = fonthashes.emwidths
+local pt_factor = number.dimenfactors.pt
+
+local nodepool = nuts.pool
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+local new_penalty = nodepool.penalty
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+
+local tracers = nodes.tracers
+local visualizers = nodes.visualizers
+
+local setcolor = tracers.colors.set
+local setlistcolor = tracers.colors.setlist
+local settransparency = tracers.transparencies.set
+local setlisttransparency = tracers.transparencies.setlist
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local a_visual = attributes.private("visual")
+local a_fontkern = attributes.private("fontkern")
+local a_layer = attributes.private("viewerlayer")
+
+local hasbit = number.hasbit
+local bit = number.bit
+local setbit = number.setbit
+local clearbit = number.clearbit
+
+local trace_hbox
+local trace_vbox
+local trace_vtop
+local trace_kern
+local trace_glue
+local trace_penalty
+local trace_fontkern
+local trace_strut
+local trace_whatsit
+local trace_user
+local trace_math
+local trace_italic
+
+local report_visualize = logs.reporter("visualize")
+
+local modes = {
+ hbox = 1,
+ vbox = 2,
+ vtop = 4,
+ kern = 8,
+ glue = 16,
+ penalty = 32,
+ fontkern = 64,
+ strut = 128,
+ whatsit = 256,
+ glyph = 512,
+ simple = 1024,
+ simplehbox = 1024 + 1,
+ simplevbox = 1024 + 2,
+ simplevtop = 1024 + 4,
+ user = 2048,
+ math = 4096,
+ italic = 8192,
+ origin = 16384,
+}
+
+local usedfont, exheight, emwidth
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin
+
+local enabled = false
+local layers = { }
+
+local preset_boxes = modes.hbox + modes.vbox + modes.origin
+local preset_makeup = preset_boxes
+ + modes.kern + modes.glue + modes.penalty
+local preset_all = preset_makeup
+ + modes.fontkern + modes.whatsit + modes.glyph + modes.user + modes.math
+
+function visualizers.setfont(id)
+ usedfont = id or current_font()
+ exheight = exheights[usedfont]
+ emwidth = emwidths[usedfont]
+end
+
+-- we can preset a bunch of bits
+
+local function enable()
+ if not usedfont then
+ -- we use a narrow monospaced font -- infofont ?
+ visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") })
+ end
+ for mode, value in next, modes do
+ local tag = formatters["v_%s"](mode)
+ attributes.viewerlayers.define {
+ tag = tag,
+ title = formatters["visualizer %s"](mode),
+ visible = "start",
+ editable = "yes",
+ printable = "yes"
+ }
+ layers[mode] = attributes.viewerlayers.register(tag,true)
+ end
+ l_hbox = layers.hbox
+ l_vbox = layers.vbox
+ l_vtop = layers.vtop
+ l_glue = layers.glue
+ l_kern = layers.kern
+ l_penalty = layers.penalty
+ l_fontkern = layers.fontkern
+ l_strut = layers.strut
+ l_whatsit = layers.whatsit
+ l_glyph = layers.glyph
+ l_user = layers.user
+ l_math = layers.math
+ l_italic = layers.italic
+ l_origin = layers.origin
+ nodes.tasks.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) -- this will become more efficient when we have the bit lib linked in
+ if not n or n == "reset" then
+ return unsetvalue
+ elseif n == "makeup" then
+ if not a or a == 0 or a == unsetvalue then
+ a = preset_makeup
+ else
+ a = setbit(a,preset_makeup)
+ end
+ elseif n == "boxes" then
+ if not a or a == 0 or a == unsetvalue then
+ a = preset_boxes
+ else
+ a = setbit(a,preset_boxes)
+ end
+ elseif n == "all" then
+ if what == false then
+ return unsetvalue
+ elseif not a or a == 0 or a == unsetvalue then
+ a = preset_all
+ else
+ a = setbit(a,preset_all)
+ end
+ else
+ local m = modes[n]
+ if not m then
+ -- go on
+ elseif a == unsetvalue then
+ if what == false then
+ return unsetvalue
+ else
+ -- a = setbit(0,m)
+ a = m
+ end
+ elseif what == false then
+ a = clearbit(a,m)
+ elseif not a or a == 0 then
+ a = m
+ else
+ a = setbit(a,m)
+ end
+ end
+ if not a or a == 0 or a == unsetvalue then
+ return unsetvalue
+ elseif not enabled then -- must happen at runtime (as we don't store layers yet)
+ enable()
+ end
+ return a
+end
+
+function nuts.setvisual(n,mode)
+ setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true))
+end
+
+function nuts.copyvisual(n,m)
+ setattr(n,a_visual,getattr(m,a_visual))
+end
+
+function visualizers.setvisual(n)
+ texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual)))
+end
+
+function visualizers.setlayer(n)
+ texsetattribute(a_layer,layers[n] or unsetvalue)
+end
+
+local function set(mode,v)
+ texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v))
+end
+
+for mode, value in next, modes do
+ trackers.register(formatters["visualizers.%s"](mode), function(v) set(mode,v) end)
+end
+
+local raisepenalties = false
+
+directives.register("visualizers.raisepenalties",function(v) raisepenalties = v end)
+
+local fraction = 10
+
+trackers .register("visualizers.reset", function(v) set("reset", v) end)
+trackers .register("visualizers.all", function(v) set("all", v) end)
+trackers .register("visualizers.makeup", function(v) set("makeup",v) end)
+trackers .register("visualizers.boxes", function(v) set("boxes", v) end)
+directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end)
+
+local c_positive = "trace:b"
+local c_negative = "trace:r"
+local c_zero = "trace:g"
+local c_text = "trace:s"
+local c_space = "trace:y"
+local c_skip_a = "trace:c"
+local c_skip_b = "trace:m"
+local c_glyph = "trace:o"
+local c_ligature = "trace:s"
+local c_white = "trace:w"
+local c_math = "trace:r"
+local c_origin = "trace:o"
+
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+local c_zero_d = "trace:dg"
+local c_text_d = "trace:ds"
+local c_space_d = "trace:dy"
+local c_skip_a_d = "trace:dc"
+local c_skip_b_d = "trace:dm"
+local c_glyph_d = "trace:do"
+local c_ligature_d = "trace:ds"
+local c_white_d = "trace:dw"
+local c_math_d = "trace:dr"
+local c_origin_d = "trace:do"
+
+local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
+ local text = hpack_string(str,usedfont)
+ local size = getfield(text,"width")
+ local rule = new_rule(size,2*exheight,exheight/2)
+ local kern = new_kern(-size)
+ if color then
+ setcolor(rule,color)
+ end
+ if textcolor then
+ setlistcolor(getlist(text),textcolor)
+ end
+ local info = linked_nodes(rule,kern,text)
+ setlisttransparency(info,c_zero)
+ info = new_hlist(info)
+ local width = getfield(info,"width")
+ if lap then
+ info = new_hlist(linked_nodes(new_kern(-width),info))
+ end
+ if layer then
+ setattr(info,a_layer,layer)
+ end
+ return info, width
+end
+
+local f_cache = { }
+
+local function fontkern(head,current)
+ local kern = getfield(current,"kern") + getfield(current,"expansion_factor")
+ local info = f_cache[kern]
+ if info then
+ -- print("hit fontkern")
+ else
+ local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
+ local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
+ local list = getlist(text)
+ if kern > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif kern < 0 then
+ setlistcolor(list,c_negative_d)
+ else
+ setlistcolor(list,c_zero_d)
+ end
+ setlisttransparency(list,c_text_d)
+ settransparency(rule,c_text_d)
+ setfield(text,"shift",-5 * exheight)
+ info = new_hlist(linked_nodes(rule,text))
+ setattr(info,a_layer,l_fontkern)
+ f_cache[kern] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+end
+
+local w_cache = { }
+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",
+}
+
+local function whatsit(head,current)
+ local what = getsubtype(current)
+ local info = w_cache[what]
+ if info then
+ -- print("hit whatsit")
+ else
+ local tag = whatsitcodes[what]
+ -- maybe different text colors per tag
+ info = sometext(formatters["W:%s"](tag and tags[tag] or what),usedfont,nil,c_white)
+ setattr(info,a_layer,l_whatsit)
+ w_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+end
+
+local u_cache = { }
+
+local function user(head,current)
+ local what = getsubtype(current)
+ local info = u_cache[what]
+ if info then
+ -- print("hit user")
+ else
+ info = sometext(formatters["U:%s"](what),usedfont)
+ setattr(info,a_layer,l_user)
+ u_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+end
+
+local m_cache = { }
+local tags = {
+ beginmath = "B",
+ endmath = "E",
+}
+
+local function math(head,current)
+ local what = getsubtype(current)
+ local info = m_cache[what]
+ if info then
+ -- print("hit math")
+ else
+ local tag = mathcodes[what]
+ info = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
+ setattr(info,a_layer,l_math)
+ m_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+end
+
+local b_cache = { }
+
+local o_cache = table.setmetatableindex(function(t,size)
+ local rule = new_rule(2*size,size,size)
+ origin = hpack_nodes(rule)
+ setcolor(rule,c_origin_d)
+ settransparency(rule,c_origin_d)
+ setattr(rule,a_layer,l_origin)
+ t[size] = origin
+ return origin
+end)
+
+local function ruledbox(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
+ local wd = getfield(current,"width")
+ if wd ~= 0 then
+ local ht = getfield(current,"height")
+ local dp = getfield(current,"depth")
+ local shift = getfield(current,"shift")
+ 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
+ baseline = b_cache.baseline
+ if not baseline then
+ -- due to an optimized leader color/transparency we need to set the glue node in order
+ -- to trigger this mechanism
+ local leader = linked_nodes(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
+ leader = hpack_nodes(leader)
+ baseline = new_glue(0)
+ setleader(baseline,leader)
+ setsubtype(baseline,cleaders_code)
+ setfield(baseline,"stretch",65536)
+ setfield(baseline,"stretch_order",2)
+ setlisttransparency(baseline,c_text)
+ b_cache.baseline = baseline
+ end
+ baseline = copy_list(baseline)
+ baseline = hpack_nodes(baseline,wd-size)
+ -- or new_hlist, set head and also:
+ -- baseline.width = wd
+ -- baseline.glue_set = wd/65536
+ -- baseline.glue_order = 2
+ -- baseline.glue_sign = 1
+ baseskip = new_kern(-wd+linewidth)
+ else
+ baseline = new_rule(wd-size,linewidth,0)
+ baseskip = new_kern(-wd+size)
+ end
+ end
+ local this
+ if not simple then
+ this = b_cache[what]
+ if not this then
+ local text = hpack_string(what,usedfont)
+ this = linked_nodes(new_kern(-getfield(text,"width")),text)
+ setlisttransparency(this,c_text)
+ this = new_hlist(this)
+ b_cache[what] = this
+ end
+ end
+ -- we need to trigger the right mode (else sometimes no whatits)
+ local info = linked_nodes(
+ 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)
+ )
+ if baseskip then
+ info = linked_nodes(info,baseskip,baseline) -- could be in previous linked
+ end
+ setlisttransparency(info,c_text)
+ info = new_hlist(info)
+ --
+ setattr(info,a_layer,layer)
+ if vertical then
+ if shift == 0 then
+ info = linked_nodes(current,info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ setfield(origin,"shift",-shift)
+ info = linked_nodes(current,new_kern(-size),origin,new_kern(-size),info)
+ else
+ -- todo .. i need an example
+ info = linked_nodes(current,info)
+ end
+ setfield(current,"shift",0)
+ else
+ info = linked_nodes(current,info)
+ setfield(current,"shift",0)
+ end
+ info = new_vlist(info,wd,ht,dp,shift)
+ else
+ if shift == 0 then
+ info = linked_nodes(current,new_kern(-wd),info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ info = linked_nodes(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ else
+ setfield(origin,"shift",-shift)
+ info = linked_nodes(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ end
+ setfield(current,"shift",0)
+ else
+ info = linked_nodes(current,new_kern(-wd),info)
+ setfield(current,"shift",0)
+ end
+ info = new_hlist(info,wd,ht,dp,shift)
+ end
+
+-- how about dir, so maybe just copy the node
+--
+-- local l = getlist(current)
+-- setlist(current,nil)
+-- local c = copy_node(current)
+-- setlist(current,l)
+-- setlist(c,info)
+-- info = c
+
+ if next then
+ setlink(info,next)
+ end
+ if prev then
+ if getid(prev) == gluespec_code then
+ report_visualize("ignoring invalid prev")
+ -- weird, how can this happen, an inline glue-spec, probably math
+ else
+ setlink(prev,info)
+ end
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+end
+
+local bpfactor = number.dimenfactors.bp
+
+-- callback.register("process_rule",function(n,h,v)
+-- local p = string.formatters["0 0 %0.6F %0.6F re f"](h*bpfactor,v*bpfactor)
+-- pdf.print("direct",p)
+-- end)
+
+local function ruledglyph(head,current,previous)
+ local wd = getfield(current,"width")
+ -- local wd = chardata[getfont(current)][getchar(current)].width
+ if wd ~= 0 then
+ local ht = getfield(current,"height")
+ local dp = getfield(current,"depth")
+ local next = getnext(current)
+ local prev = previous
+ setboth(current)
+ local linewidth = emwidth/(2*fraction)
+ local baseline
+ -- if dp ~= 0 and ht ~= 0 then
+ 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)
+ local info = linked_nodes(
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-doublelinewidth,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-doublelinewidth,ht,-ht+linewidth),
+ new_kern(-wd+doublelinewidth),
+ baseline
+ )
+ local char = chardata[getfont(current)][getchar(current)]
+ if char and type(char.unicode) == "table" then -- hackery test
+ setlistcolor(info,c_ligature)
+ setlisttransparency(info,c_ligature_d)
+ else
+ setlistcolor(info,c_glyph)
+ setlisttransparency(info,c_glyph_d)
+ end
+ info = new_hlist(info)
+ setattr(info,a_layer,l_glyph)
+ local info = linked_nodes(current,new_kern(-wd),info)
+ info = hpack_nodes(info)
+ setfield(info,"width",wd)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
+ setlink(prev,info)
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+end
+
+local g_cache_v = { }
+local g_cache_h = { }
+
+local tags = {
+ -- userskip = "US",
+ lineskip = "LS",
+ baselineskip = "BS",
+ parskip = "PS",
+ abovedisplayskip = "DA",
+ belowdisplayskip = "DB",
+ abovedisplayshortskip = "SA",
+ belowdisplayshortskip = "SB",
+ leftskip = "LS",
+ rightskip = "RS",
+ topskip = "TS",
+ splittopskip = "ST",
+ tabskip = "AS",
+ spaceskip = "SS",
+ xspaceskip = "XS",
+ parfillskip = "PF",
+ thinmuskip = "MS",
+ medmuskip = "MM",
+ thickmuskip = "ML",
+ leaders = "NL",
+ cleaders = "CL",
+ xleaders = "XL",
+ gleaders = "GL",
+ -- true = "VS",
+ -- false = "HS",
+}
+
+-- we sometimes pass previous as we can have issues in math (not watertight for all)
+
+local function ruledglue(head,current,vertical,parent)
+ local subtype = getsubtype(current)
+ local width = effectiveglue(current,parent)
+ local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
+ local info = (vertical and g_cache_v or g_cache_h)[amount]
+ if info then
+ -- print("glue hit")
+ else
+ if subtype == space_code or subtype == xspace_code then -- not yet all space
+ info = sometext(amount,l_glue,c_space)
+ elseif subtype == leftskip_code or subtype == rightskip_code then
+ info = sometext(amount,l_glue,c_skip_a)
+ elseif subtype == userskip_code then
+ if width > 0 then
+ info = sometext(amount,l_glue,c_positive)
+ elseif width < 0 then
+ info = sometext(amount,l_glue,c_negative)
+ else
+ info = sometext(amount,l_glue,c_zero)
+ end
+ else
+ info = sometext(amount,l_glue,c_skip_b)
+ end
+ (vertical and g_cache_v or g_cache_h)[amount] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+end
+
+local k_cache_v = { }
+local k_cache_h = { }
+
+local function ruledkern(head,current,vertical)
+ local kern = getfield(current,"kern")
+ local info = (vertical and k_cache_v or k_cache_h)[kern]
+ if info then
+ -- print("kern hit")
+ else
+ local amount = formatters["%s:%0.3f"](vertical and "VK" or "HK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ (vertical and k_cache_v or k_cache_h)[kern] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+end
+
+local i_cache = { }
+
+local function ruleditalic(head,current)
+ local kern = getfield(current,"kern")
+ local info = i_cache[kern]
+ if info then
+ -- print("kern hit")
+ else
+ local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ i_cache[kern] = info
+ end
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+end
+
+local p_cache_v = { }
+local p_cache_h = { }
+
+local function ruledpenalty(head,current,vertical)
+ local penalty = getfield(current,"penalty")
+ local info = (vertical and p_cache_v or p_cache_h)[penalty]
+ if info then
+ -- print("penalty hit")
+ else
+ local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
+ if penalty > 0 then
+ info = sometext(amount,l_penalty,c_positive)
+ elseif penalty < 0 then
+ info = sometext(amount,l_penalty,c_negative)
+ else
+ info = sometext(amount,l_penalty,c_zero)
+ end
+ (vertical and p_cache_v or p_cache_h)[penalty] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ elseif raisepenalties then
+ setfield(info,"shift",-65536*4)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+end
+
+local function visualize(head,vertical,forced,parent)
+ local trace_hbox = false
+ local trace_vbox = false
+ local trace_vtop = false
+ local trace_kern = false
+ local trace_glue = false
+ local trace_penalty = false
+ local trace_fontkern = false
+ local trace_strut = false
+ local trace_whatsit = false
+ local trace_glyph = false
+ local trace_simple = false
+ local trace_user = false
+ local trace_math = false
+ local trace_italic = false
+ local trace_origin = false
+ local current = head
+ local previous = nil
+ local attr = unsetvalue
+ local prev_trace_fontkern = nil
+ while current do
+ local id = getid(current)
+ local a = forced or getattr(current,a_visual) or unsetvalue
+ if a ~= attr then
+ prev_trace_fontkern = trace_fontkern
+ if a == unsetvalue then
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ trace_math = false
+ trace_italic = false
+ trace_origin = false
+ else -- dead slow:
+ trace_hbox = hasbit(a, 1)
+ trace_vbox = hasbit(a, 2)
+ trace_vtop = hasbit(a, 4)
+ trace_kern = hasbit(a, 8)
+ trace_glue = hasbit(a, 16)
+ trace_penalty = hasbit(a, 32)
+ trace_fontkern = hasbit(a, 64)
+ trace_strut = hasbit(a, 128)
+ trace_whatsit = hasbit(a, 256)
+ trace_glyph = hasbit(a, 512)
+ trace_simple = hasbit(a, 1024)
+ trace_user = hasbit(a, 2048)
+ trace_math = hasbit(a, 4096)
+ trace_italic = hasbit(a, 8192)
+ trace_origin = hasbit(a,16384)
+ end
+ attr = a
+ end
+ if trace_strut then
+ setattr(current,a_layer,l_strut)
+ elseif id == glyph_code then
+ if trace_glyph then
+ head, current = ruledglyph(head,current,previous)
+ end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(current)
+ if pre then
+ pre = visualize(pre,false,a,parent)
+ end
+ if post then
+ post = visualize(post,false,a,parent)
+ end
+ if replace then
+ replace = visualize(replace,false,a,parent)
+ end
+ setdisc(current,pre,post,replace)
+ elseif id == kern_code then
+ local subtype = getsubtype(current)
+ -- tricky ... we don't copy the trace attribute in node-inj (yet)
+ if subtype == font_kern_code or getattr(current,a_fontkern) then
+ if trace_fontkern or prev_trace_fontkern then
+ head, current = fontkern(head,current)
+ end
+ else -- if subtype == user_kern_code then
+ if trace_italic then
+ head, current = ruleditalic(head,current)
+ elseif trace_kern then
+ head, current = ruledkern(head,current,vertical)
+ end
+ end
+ elseif id == glue_code then
+ local content = getleader(current)
+ if content then
+ setleader(current,visualize(content,false,nil,parent))
+ elseif trace_glue then
+ head, current = ruledglue(head,current,vertical,parent)
+ end
+ elseif id == penalty_code then
+ if trace_penalty then
+ head, current = ruledpenalty(head,current,vertical)
+ end
+ elseif id == hlist_code then
+ local content = getlist(current)
+ if content then
+ setlist(current,visualize(content,false,nil,current))
+ end
+ if trace_hbox then
+ head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
+ end
+ elseif id == vlist_code then
+ local content = getlist(current)
+ if content then
+ setlist(current,visualize(content,true,nil,current))
+ end
+ if trace_vtop then
+ head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous,trace_origin,parent)
+ elseif trace_vbox then
+ head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous,trace_origin,parent)
+ end
+ elseif id == whatsit_code then
+ if trace_whatsit then
+ head, current = whatsit(head,current)
+ end
+ elseif id == user_code then
+ if trace_user then
+ head, current = user(head,current)
+ end
+ elseif id == math_code then
+ if trace_math then
+ head, current = math(head,current)
+ end
+ end
+ previous = current
+ current = getnext(current)
+ end
+ return head
+end
+
+do
+
+ local function freed(cache)
+ local n = 0
+ for k, v in next, cache do
+ free_node_list(v)
+ n = n + 1
+ end
+ if n == 0 then
+ return 0, cache
+ else
+ return n, { }
+ end
+ end
+
+ local function cleanup()
+ local hf, nw, nb, ng_v, ng_h, np_v, np_h, nk_v, nk_h
+ nf, f_cache = freed(f_cache)
+ nw, w_cache = freed(w_cache)
+ nb, b_cache = freed(b_cache)
+ no, o_cache = freed(o_cache)
+ ng_v, g_cache_v = freed(g_cache_v)
+ ng_h, g_cache_h = freed(g_cache_h)
+ np_v, p_cache_v = freed(p_cache_v)
+ np_h, p_cache_h = freed(p_cache_h)
+ nk_v, k_cache_v = freed(k_cache_v)
+ nk_h, k_cache_h = freed(k_cache_h)
+ -- report_visualize("cache cleanup: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes, %s origins",
+ -- nf,ng_v+ng_h,np_v+np_h,nk_v+nk_h,nw,nb,no)
+ end
+
+ local function handler(head)
+ if usedfont then
+ starttiming(visualizers)
+ -- local l = texgetattribute(a_layer)
+ -- local v = texgetattribute(a_visual)
+ -- texsetattribute(a_layer,unsetvalue)
+ -- texsetattribute(a_visual,unsetvalue)
+ head = visualize(tonut(head),true)
+ -- texsetattribute(a_layer,l)
+ -- texsetattribute(a_visual,v)
+ -- -- cleanup()
+ stoptiming(visualizers)
+ return tonode(head), true
+ else
+ return head, false
+ end
+ end
+
+ visualizers.handler = handler
+
+ luatex.registerstopactions(cleanup)
+
+end
+
+function visualizers.box(n)
+ if usedfont then
+ starttiming(visualizers)
+ local box = getbox(n)
+ if box then
+ setlist(box,visualize(getlist(box),getid(box) == vlist_code))
+ end
+ stoptiming(visualizers)
+ return head, true
+ else
+ return head, false
+ end
+end
+
+do
+
+ local last = nil
+ local used = nil
+
+ local mark = {
+ "trace:1", "trace:2", "trace:3",
+ "trace:4", "trace:5", "trace:6",
+ "trace:7",
+ }
+
+ local function markfonts(list)
+ for n in traverse_nodes(list) do
+ local id = getid(n)
+ if id == glyph_code then
+ local font = getfont(n)
+ local okay = used[font]
+ if not okay then
+ last = last + 1
+ okay = mark[last]
+ used[font] = okay
+ end
+ setcolor(n,okay)
+ elseif id == hlist_code or id == vlist_code then
+ markfonts(getlist(n))
+ end
+ end
+ end
+
+ function visualizers.markfonts(list)
+ last, used = 0, { }
+ markfonts(type(n) == "number" and getlist(getbox(n)) or n)
+ end
+
+end
+
+statistics.register("visualization time",function()
+ if enabled then
+ -- cleanup() -- in case we don't don't do it each time
+ return format("%s seconds",statistics.elapsedtime(visualizers))
+ end
+end)
+
+-- interface
+
+local implement = interfaces.implement
+
+implement { name = "setvisual", arguments = "string", actions = visualizers.setvisual }
+implement { name = "getvisual", arguments = "string", actions = { setvisual, context } }
+implement { name = "setvisuallayer", arguments = "string", actions = visualizers.setlayer }
+implement { name = "markvisualfonts", arguments = "integer", actions = visualizers.markfonts }
+implement { name = "setvisualfont", arguments = "integer", actions = visualizers.setfont }
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv
new file mode 100644
index 00000000000..a503981f5d9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv
@@ -0,0 +1,240 @@
+%D \module
+%D [ file=trac-vis, % replaces supp-vis plus some s-* modules
+%D version=2112.06.23, % 1996.10.21,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=Visualization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The old visual debugger dates from 1996 and started out as joke. In practice
+%D it's not used that often although the \type {\ruledhbox} cum suis macros come
+%D in handy when writing code. In the process of luafication some additional
+%D tracing options were tested, for instance showing font kerns. As part of the
+%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider
+%D all these features. The old code is gone and the new code will get extended
+%D when needed. We still provide placeholders for some old visualization commands
+%D but they might go away.
+%D
+%D Control over what gets visualized happens with the tracker command:
+%D
+%D \enabletrackers[visualizers.*]
+%D
+%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type
+%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type
+%D {makeup}, \type {whatsit}, \type{glyph}.
+%D
+%D In due time some special visualzation of math will move here as well.
+
+\writestatus{loading}{ConTeXt Tracing Macros / Visualization}
+
+\registerctxluafile{trac-vis}{1.001}
+
+\unprotect
+
+\newconstant\c_syst_visualizers_state
+\newtoks \t_syst_visualizers_optimize
+
+\definesystemattribute[visual][public,global] % global ?
+
+% no, but can become an option:
+%
+% \appendtoks
+% \attribute\visualattribute\attributeunsetvalue
+% \to \everybeforepagebody
+
+%D We only provide box visualizers as they can come in handy for testing
+%D macros. In due time we will move some of the m-visual code here too.
+
+\let\syst_visualizers_hbox\hbox
+\let\syst_visualizers_vbox\vbox
+\let\syst_visualizers_vtop\vtop
+
+\let\syst_visualizers_hpack\hpack
+\let\syst_visualizers_vpack\vpack
+\let\syst_visualizers_tpack\tpack
+
+\unexpanded\def\ruledhbox{\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} }
+\unexpanded\def\ruledvbox{\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} }
+\unexpanded\def\ruledvtop{\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} } % special case
+\unexpanded\def\ruledtopv{\syst_visualizers_vtop attr \visualattribute \clf_getvisual{vtop} }
+
+\unexpanded\def\ruledhpack{\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} }
+\unexpanded\def\ruledvpack{\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} }
+\unexpanded\def\ruledtpack{\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} } % special case
+
+\unexpanded\def\ruledmbox#1{\ruledhbox{\startimath#1\stopimath}}
+
+\appendtoks
+ \ifcase\c_syst_visualizers_state\else
+ \syst_visualizers_speedup
+ \fi
+\to \everyshipout
+
+\appendtoks
+ \global\let\syst_visualizers_speedup\relax
+\to \t_syst_visualizers_optimize
+
+\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize}
+
+\appendtoks
+ \normalexpanded {%
+ \unexpanded\xdef\ruledhbox\expandafter{\ruledhbox}%
+ \unexpanded\xdef\ruledvbox\expandafter{\ruledvbox}%
+ \unexpanded\xdef\ruledvtop\expandafter{\ruledvtop}%
+ \unexpanded\xdef\ruledtopv\expandafter{\ruledtopv}%
+ }%
+\to \t_syst_visualizers_optimize
+
+\unexpanded\def\showmakeup
+ {\dosingleempty\syst_visualizers_makeup}
+
+\unexpanded\def\syst_visualizers_makeup[#1]%
+ {\iffirstargument
+ \clf_setvisual{#1}%
+ \else
+ \clf_setvisual{makeup}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv
+ \fi}
+
+\unexpanded\def\showallmakeup
+ {\clf_setvisual{all}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv
+ \showstruts}
+
+\unexpanded\def\showboxes
+ {\clf_setvisual{boxes}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv}
+
+\unexpanded\def\showglyphs
+ {\clf_setvisual{glyph}}
+
+\unexpanded\def\showfontkerns
+ {\clf_setvisual{fontkern}}
+
+\unexpanded\def\setvisualizerfont
+ {\dosingleempty\syst_visualizers_setfont}
+
+\def\syst_visualizers_setfont[#1]% somename at 4pt
+ {\begingroup
+ \doifelsenothing{#1}{\definedfont[Mono at 4pt]}{\definedfont[#1]}%
+ \clf_setvisualfont\fontid\font
+ \endgroup}
+
+\unexpanded\def\resetvisualizers
+ {\attribute\visualattribute\attributeunsetvalue}
+
+%D New (these might also be a visualizers):
+
+% \definecolor[f:r:t][a=1,t=.25,r=1]
+% \definecolor[f:g:t][a=1,t=.25,g=1]
+% \definecolor[f:b:t][a=1,t=.25,b=1]
+% \definecolor[f:c:t][a=1,t=.25,c=1]
+% \definecolor[f:m:t][a=1,t=.25,m=1]
+% \definecolor[f:y:t][a=1,t=.25,y=1]
+% \definecolor[f:k:t][a=1,t=.25,s=0]
+
+\unexpanded\def\filledhboxr{\node_backgrounds_boxes_add\hbox[f:r:t]}
+\unexpanded\def\filledhboxg{\node_backgrounds_boxes_add\hbox[f:g:t]}
+\unexpanded\def\filledhboxb{\node_backgrounds_boxes_add\hbox[f:b:t]}
+\unexpanded\def\filledhboxc{\node_backgrounds_boxes_add\hbox[f:c:t]}
+\unexpanded\def\filledhboxm{\node_backgrounds_boxes_add\hbox[f:m:t]}
+\unexpanded\def\filledhboxy{\node_backgrounds_boxes_add\hbox[f:y:t]}
+\unexpanded\def\filledhboxk{\node_backgrounds_boxes_add\hbox[f:k:t]}
+
+%D Overload:
+
+% \def\spac_struts_vide_hbox
+% {\hbox attr \visualattribute \clf_getvisual{strut} }
+%
+% \def\spac_struts_vide_hbox
+% {\xdef\spac_struts_vide_hbox{\hbox attr \visualattribute \clf_getvisual{strut} }%
+% \spac_struts_vide_hbox}
+
+\unexpanded\def\spac_struts_vide_hbox
+ {\hbox attr \visualattribute \clf_getvisual{strut} }
+
+\appendtoks
+ \normalexpanded{\unexpanded\xdef\spac_struts_vide_hbox\expandafter{\spac_struts_vide_hbox}}%
+\to \t_syst_visualizers_optimize
+
+%D For manuals:
+
+\unexpanded\def\markfonts#1%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\getbuffer}%
+ \clf_markvisualfonts\scratchbox
+ \unhbox\scratchbox
+ \endgroup}
+
+% As demo:
+%
+% \startbuffer
+% \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}}
+% \blank
+% \moveleft1cm\hbox{left}
+% \blank
+% \hbox{normal}
+% \blank
+% \moveright1cm\hbox{right}
+% \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+%
+% \startbuffer
+% \moveleft1cm\vbox{left}
+% \blank
+% \vbox{normal}
+% \blank
+% \moveright1cm\vbox{right}
+% \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+
+%D We keep this one:
+
+\unexpanded\def\dontinterfere
+ {\reseteverypar
+ \parindent\zeropoint
+ \parskip \zeropoint
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+%D We keep these for a while:
+
+\let\ruledvcenter \vcenter
+\let\ruledhss \hss
+\let\ruledhfil \hfil
+\let\ruledhfill \hfill
+\let\ruledhfilll \hfilll
+\let\ruledhfilneg \hfilneg
+\let\ruledhfillneg \hfillneg
+\let\ruledhfilllneg \hfilllneg
+\let\ruledvss \vss
+\let\ruledvfil \vfil
+\let\ruledvfill \vfill
+\let\ruledvfilll \vfilll
+\let\ruledvfilneg \vfilneg
+\let\ruledvfillneg \vfillneg
+\let\ruledvfilllneg \vfilllneg
+\let\ruledhskip \hskip
+\let\ruledvskip \vskip
+\let\ruledkern \kern
+\let\ruledhglue \hglue
+\let\ruledvglue \vglue
+\let\ruledmkern \mkern
+\let\ruledmskip \mskip
+\let\ruledpenalty \penalty
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-xml.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-xml.lua
new file mode 100644
index 00000000000..cd8b8c0a5f5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/trac-xml.lua
@@ -0,0 +1,183 @@
+if not modules then modules = { } end modules ['trac-xml'] = {
+ version = 1.001,
+ comment = "companion to trac-log.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Application helpinfo can be defined in several ways:
+--
+-- helpinfo = "big blob of help"
+--
+-- helpinfo = { basic = "blob of basic help", extra = "blob of extra help" }
+--
+-- helpinfo = "<?xml version=1.0?><application>...</application/>"
+--
+-- helpinfo = "somefile.xml"
+--
+-- In the case of an xml file, the file should be either present on the same path
+-- as the script, or we should be be able to locate it using the resolver.
+
+local formatters = string.formatters
+local reporters = logs.reporters
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmltext = xml.text
+local xmlfirst = xml.first
+
+-- there is no need for a newhandlers { name = "help", parent = "string" }
+
+local function showhelp(specification,...)
+ local root = xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs = xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref", function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories = select("#",...) == 0 and true or table.tohash { ... }
+ local nofcategories = xml.count(root,"/application/flags/category")
+ local report = specification.report
+ for category in xmlcollected(root,"/application/flags/category") do
+ local categoryname = category.at.name or ""
+ if wantedcategories == true or wantedcategories[categoryname] then
+ if nofcategories > 1 then
+ report("%s options:",categoryname)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for flag in xmlcollected(subcategory,"/flag") do
+ local name = flag.at.name
+ local value = flag.at.value
+ -- local short = xmlfirst(s,"/short")
+ -- local short = xmlserialize(short,xs)
+ local short = xmltext(xmlfirst(flag,"/short"))
+ if value then
+ report("--%-20s %s",formatters["%s=%s"](name,value),short)
+ else
+ report("--%-20s %s",name,short)
+ end
+ end
+ report()
+ end
+ end
+ end
+ for category in xmlcollected(root,"/application/examples/category") do
+ local title = xmltext(xmlfirst(category,"/title"))
+ if title and title ~= "" then
+ report()
+ report(title)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for example in xmlcollected(subcategory,"/example") do
+ local command = xmltext(xmlfirst(example,"/command"))
+ local comment = xmltext(xmlfirst(example,"/comment"))
+ report(command)
+ end
+ report()
+ end
+ end
+ for comment in xmlcollected(root,"/application/comments/comment") do
+ local comment = xmltext(comment)
+ report()
+ report(comment)
+ report()
+ end
+end
+
+local reporthelp = reporters.help
+local exporthelp = reporters.export
+
+local function xmlfound(t)
+ local helpinfo = t.helpinfo
+ if type(helpinfo) == "table" then
+ return false
+ end
+ if type(helpinfo) ~= "string" then
+ helpinfo = "Warning: no helpinfo found."
+ t.helpinfo = helpinfo
+ return false
+ end
+ if string.find(helpinfo,".xml$") then
+ local ownscript = environment.ownscript
+ local helpdata = false
+ if ownscript then
+ local helpfile = file.join(file.pathpart(ownscript),helpinfo)
+ helpdata = io.loaddata(helpfile)
+ if helpdata == "" then
+ helpdata = false
+ end
+ end
+ if not helpdata then
+ local helpfile = resolvers.findfile(helpinfo,"tex")
+ helpdata = helpfile and io.loaddata(helpfile)
+ end
+ if helpdata and helpdata ~= "" then
+ helpinfo = helpdata
+ else
+ helpinfo = formatters["Warning: help file %a is not found."](helpinfo)
+ end
+ end
+ t.helpinfo = helpinfo
+ return string.find(t.helpinfo,"^<%?xml") and true or false
+end
+
+function reporters.help(t,...)
+ if xmlfound(t) then
+ showhelp(t,...)
+ else
+ reporthelp(t,...)
+ end
+end
+
+function reporters.export(t,methods,filename)
+ if not xmlfound(t) then
+ return exporthelp(t)
+ end
+ if not methods or methods == "" then
+ methods = environment.arguments["exporthelp"]
+ end
+ if not filename or filename == "" then
+ filename = environment.files[1]
+ end
+ dofile(resolvers.findfile("trac-exp.lua","tex"))
+ local exporters = logs.exporters
+ if not exporters or not methods then
+ return exporthelp(t)
+ end
+ if methods == "all" then
+ methods = table.keys(exporters)
+ elseif type(methods) == "string" then
+ methods = utilities.parsers.settings_to_array(methods)
+ else
+ return exporthelp(t)
+ end
+ if type(filename) ~= "string" or filename == "" then
+ filename = false
+ elseif file.pathpart(filename) == "" then
+ t.report("export file %a will not be saved on the current path (safeguard)",filename)
+ return
+ end
+ for i=1,#methods do
+ local method = methods[i]
+ local exporter = exporters[method]
+ if exporter then
+ local result = exporter(t,method)
+ if result and result ~= "" then
+ if filename then
+ local fullname = file.replacesuffix(filename,method)
+ t.report("saving export in %a",fullname)
+ io.savedata(fullname,result)
+ else
+ reporters.lines(t,result)
+ end
+ else
+ t.report("no output from exporter %a",method)
+ end
+ else
+ t.report("unknown exporter %a",method)
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-def.mkiv
new file mode 100644
index 00000000000..a80b4f7bdf3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-def.mkiv
@@ -0,0 +1,48 @@
+%D \module
+%D [ file=type-def,
+%D version=2005.02.04,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Default Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\starttypescriptcollection[simplification]
+
+\starttypescript [\s!serif] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Serif] [\s!Simple]
+ \definefontsynonym [\s!SerifBold] [\s!Serif]
+ \definefontsynonym [\s!SerifItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifCaps] [\s!Serif]
+\stoptypescript
+
+\starttypescript [\s!sans] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Sans] [\s!Simple]
+ \definefontsynonym [\s!SansBold] [\s!Sans]
+ \definefontsynonym [\s!SansItalic] [\s!Sans]
+ \definefontsynonym [\s!SansSlanted] [\s!Sans]
+ \definefontsynonym [\s!SansBoldItalic] [\s!Sans]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!Sans]
+ \definefontsynonym [\s!SansCaps] [\s!Sans]
+\stoptypescript
+
+\starttypescript [\s!mono] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Mono] [\s!Simple]
+ \definefontsynonym [\s!MonoBold] [\s!Mono]
+ \definefontsynonym [\s!MonoItalic] [\s!Mono]
+ \definefontsynonym [\s!MonoSlanted] [\s!Mono]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!Mono]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!Mono]
+ \definefontsynonym [\s!MonoCaps] [\s!Mono]
+\stoptypescript
+
+\stoptypescriptcollection
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-fbk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-fbk.mkiv
new file mode 100644
index 00000000000..4ac38178754
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-fbk.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=type-sfbk,
+%D version=2005.02.04, % moved from ini/def/set
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Fallbacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\definetypescriptprefix [\s!serif] [\s!Serif]
+\definetypescriptprefix [\s!sans] [\s!Sans]
+\definetypescriptprefix [\s!mono] [\s!Mono]
+
+\definefontsynonym [\s!DefaultFont] [\s!file:lmmonoproplt10-regular]
+
+\startsetups [\s!font:\s!fallback:\s!serif]
+ \definefontsynonym[\s!Serif] [\s!DefaultFont]
+ \definefontsynonym[\s!SerifBold] [\s!Serif]
+ \definefontsynonym[\s!SerifItalic] [\s!Serif]
+ \definefontsynonym[\s!SerifSlanted] [\s!SerifItalic]
+ \definefontsynonym[\s!SerifBoldItalic] [\s!Serif]
+ \definefontsynonym[\s!SerifBoldSlanted][\s!SerifBoldItalic]
+ \definefontsynonym[\s!SerifCaps] [\s!Serif] [\s!features=\s!smallcaps]
+\stopsetups
+
+\startsetups [\s!font:\s!fallback:\s!sans]
+ \definefontsynonym[\s!Sans] [\s!DefaultFont]
+ \definefontsynonym[\s!SansBold] [\s!Sans]
+ \definefontsynonym[\s!SansItalic] [\s!Sans]
+ \definefontsynonym[\s!SansSlanted] [\s!SansItalic]
+ \definefontsynonym[\s!SansBoldItalic] [\s!Sans]
+ \definefontsynonym[\s!SansBoldSlanted][\s!SansBoldItalic]
+ \definefontsynonym[\s!SansCaps] [\s!Sans] [\s!features=\s!smallcaps]
+\stopsetups
+
+\startsetups [\s!font:\s!fallback:\s!mono]
+ \definefontsynonym[\s!Mono] [\s!DefaultFont]
+ \definefontsynonym[\s!MonoBold] [\s!Mono]
+ \definefontsynonym[\s!MonoItalic] [\s!Mono]
+ \definefontsynonym[\s!MonoSlanted] [\s!MonoItalic]
+ \definefontsynonym[\s!MonoBoldItalic] [\s!Mono]
+ \definefontsynonym[\s!MonoBoldSlanted][\s!MonoBoldItalic]
+ \definefontsynonym[\s!MonoCaps] [\s!Mono] [\s!features=\s!smallcaps]
+\stopsetups
+
+\starttypescript [\s!serif,\s!sans,\s!mono] [\s!fallback]
+ \setups[\s!font:\s!fallback:\typescriptone]
+\stoptypescript
+
+\startsetups [\s!font:allbold:\s!serif]
+ \definefontsynonym[\s!Serif] [\s!SerifBold]
+ \definefontsynonym[\s!SerifItalic] [\s!SerifBoldItalic]
+ \definefontsynonym[\s!SerifSlanted][\s!SerifBoldSlanted]
+ %definefontsynonym[\s!SerifCaps] [\s!SerifBold]
+\stopsetups
+
+\startsetups [\s!font:allbold:\s!sans]
+ \definefontsynonym[\s!Sans] [\s!SansBold]
+ \definefontsynonym[\s!SansItalic] [\s!SansBoldItalic]
+ \definefontsynonym[\s!SansSlanted][\s!SansBoldSlanted]
+ %definefontsynonym[\s!SansCaps] [\s!SansBold]
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/type-ini.lua
new file mode 100644
index 00000000000..cd5b32d3e6c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-ini.lua
@@ -0,0 +1,117 @@
+if not modules then modules = { } end modules ['type-ini'] = {
+ version = 1.001,
+ comment = "companion to type-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gsub = string.gsub
+local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
+
+-- more code will move here
+
+local commands = commands
+local context = context
+local implement = interfaces.implement
+
+local uselibrary = resolvers.uselibrary
+
+local name_one = nil
+local name_two = nil
+
+local p_strip = Cs((P("type-") * (P("imp-")^0))^0/"" * P(1)^0)
+
+local report = logs.reporter("fonts","typescripts")
+
+local function action(name,foundname)
+ -- context.startreadingfile()
+ -- context.unprotect()
+ -- context.pushendofline()
+ -- context.input(foundname)
+ -- context.popendofline()
+ -- context.protect()
+ -- context.stopreadingfile()
+ context.loadfoundtypescriptfile(foundname)
+end
+
+local patterns = {
+ "type-imp-%s.mkiv",
+ "type-imp-%s.tex"
+}
+
+local function failure(name)
+ if name == "loc" then
+ -- ignore
+ else
+ report("unknown library %a",name)
+ end
+end
+
+implement {
+ name = "loadtypescriptfile",
+ arguments = "string",
+ actions = function(name) -- a more specific name
+ uselibrary {
+ name = lpegmatch(p_strip,name) or name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = false, -- will become true
+ }
+ end
+}
+
+local patterns = {
+ "type-imp-%s.mkiv",
+ "type-imp-%s.tex",
+ -- obsolete
+ "type-%s.mkiv",
+ "type-%s.tex"
+}
+
+-- local function failure_two(name)
+-- report("unknown library %a or %a",name_one,name_two)
+-- end
+--
+-- local function failure_one(name)
+-- name_two = gsub(name,"%-.*$","")
+-- if name == "loc" then
+-- -- ignore
+-- elseif name_two == name then
+-- report("unknown library %a",name_one)
+-- else
+-- commands.uselibrary {
+-- name = name_two,
+-- patterns = patterns,
+-- action = action,
+-- failure = failure_two,
+-- onlyonce = false, -- will become true
+-- }
+-- end
+-- end
+--
+-- function commands.doprocesstypescriptfile(name)
+-- name_one = lpegmatch(p_strip,name) or name
+-- uselibrary {
+-- name = name_one,
+-- patterns = patterns,
+-- action = action,
+-- failure = failure_one,
+-- onlyonce = false, -- will become true
+-- }
+-- end
+
+implement {
+ name = "doprocesstypescriptfile",
+ arguments = "string",
+ actions = function(name)
+ uselibrary {
+ name = lpegmatch(p_strip,name) or name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = false, -- will become true
+ }
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi
new file mode 100644
index 00000000000..3969a5b95e6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi
@@ -0,0 +1,642 @@
+%D \module
+%D [ file=type-ini,
+%D version=2001.03.05,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typescript Macros / Initialization}
+
+\registerctxluafile{type-ini}{1.001}
+
+%D The default fontclass is empty. We could demand always using fontclasses,
+%D and then make the calling macros simplier (always assume fontclass) but
+%D apart from downward compatibility issues, it would make global, class
+%D spanning definitions a pain. Some day we will introduce a default class.
+%D
+%D The \type {type-ini} and \type {font-ini} modules come as a pair and have
+%D mutual dependencies.
+%D
+%D At some point we will only store in memory so some code can go away.
+
+\unprotect
+
+\definesystemvariable {ts} % TypeScript / for the moment we keep this one
+
+\newcount \c_font_typescripts_n_of_preloaded
+\newconditional\c_font_typescripts_quit
+\newtoks \c_font_typescripts_document
+\newconditional\c_font_typescripts_preload
+\newconditional\c_font_typescripts_first_pass \settrue\c_font_typescripts_first_pass
+
+\newif \iftypescriptfound % will become a mode
+\newif \iftracetypescripts
+
+\newtoks \everybeforedefinetypeface
+\newtoks \everyafterdefinetypeface
+
+\let\typescriptfiles \empty
+\let\currenttypescripts\empty
+\let\currenttypefile \empty
+
+\let\typescriptone \empty % public, used in typescripts
+\let\typescripttwo \empty % public, used in typescripts
+\let\typescriptthree\empty % public, used in typescripts
+
+\let\fontclassstyle \empty
+
+\let\m_font_typescripts_one \empty
+\let\m_font_typescripts_two \empty
+\let\m_font_typescripts_three\empty
+\let\m_font_typescripts_check\empty
+\let\m_font_typescripts_match\empty
+
+\let\t_font_typescripts\relax % uses as synonym
+
+\installcorenamespace{typescriptcache}
+\installcorenamespace{typescriptfiles}
+\installcorenamespace{typescriptonce}
+\installcorenamespace{typescriptsynonyms}
+\installcorenamespace{typescriptprefix}
+\installcorenamespace{typescriptinheritances}
+\installcorenamespace{typescriptdefaultstyles}
+\installcorenamespace{typescriptrelatives}
+
+\definesystemvariable{ts} % TypeScript
+
+% tricky ... here we push/pop ... so \let
+
+\let\typescriptmethod\plusone % 1: empty==all==true 2: empty==false
+\let\typescriptstate \plustwo % 1: process 2: store
+
+\unexpanded\def\starttypescriptcollection
+ {\dosingleempty\font_typescripts_collection_start}
+
+\def\font_typescripts_collection_start[#tag]%
+ {}
+
+\let\stoptypescriptcollection\relax
+
+\unexpanded\def\usetypescriptfile[#filename]%
+ {\doifelse{#filename}\v!reset
+ {\let\typescriptfiles\empty}
+ {\splitfilename{#filename}%
+ \addtocommalist\splitoffbase\typescriptfiles}}
+
+\unexpanded\def\usetypescript {\dotripleempty\font_typescripts_use_one}
+\unexpanded\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two}
+
+\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use}
+\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use}
+
+\unexpanded\def\font_typescripts_use[#one][#two][#three]%
+ {\pushmacro\m_font_typescripts_one
+ \pushmacro\m_font_typescripts_two
+ \pushmacro\m_font_typescripts_three
+ \edef\m_font_typescripts_one {\truetypescript{#one}}%
+ \edef\m_font_typescripts_two {\truetypescript{#two}}%
+ \edef\m_font_typescripts_three{\truetypescript{#three}}%
+ \pushmacro\typescriptone
+ \pushmacro\typescripttwo
+ \pushmacro\typescriptthree
+ \pushmacro\typescriptmethod
+ \pushmacro\typescriptstate
+ \pushmacro\stoptypescript
+ \typescriptfoundfalse
+ \let\typescriptstate\plusone % why
+ \iftracetypescripts
+ \writestatus\m!fonts{request: [\m_font_typescripts_one] [\m_font_typescripts_two] [\m_font_typescripts_three]}%
+ \fi
+ \ifhmode
+ \font_typescripts_use_inline
+ \else
+ \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}
+
+\def\font_typescripts_use_display
+ {\processcommacommand[\typescriptfiles]\font_typescripts_load_file
+ \the\c_font_typescripts_document}
+
+\let\font_typescripts_use_inline\font_typescripts_use_display
+
+% % not yet:
+%
+% \newsignal\d_font_typescripts_signal
+%
+% \def\font_typescripts_use_inline
+% {\ifhmode
+% \kern\d_font_typescripts_signal
+% \fi
+% \font_typescripts_use_display
+% \ifhmode
+% \ifdim\lastkern=\d_font_typescripts_signal
+% \unkern
+% \else
+% \removeunwantedspaces
+% \ifdim\lastkern=\d_font_typescripts_signal
+% \unkern
+% \else
+% % messy typescript 2
+% \fi
+% \fi
+% \else
+% % messy typescript 1
+% \fi}
+
+\unexpanded\def\preloadtypescripts
+ {\ifproductionrun\settrue\c_font_typescripts_preload\fi}
+
+\prependtoks
+ \preloadtypescripts
+\to \everyjob
+
+% The next will change .. we can load a file inside a typescript but as the state is
+% 1 then, it doesn't get stored without doing that explicitly
+
+\unexpanded\def\loadtypescriptfile[#1]%
+ {\pushmacro\typescriptstate
+ \let\typescriptstate\plustwo % assumes 2 at the outer level
+ \clf_loadtypescriptfile{#1}%
+ \popmacro\typescriptstate}
+
+\unexpanded\def\loadfoundtypescriptfile#1%
+ {\startreadingfile
+ \unprotect
+ \pushendofline
+ \input{#1}%
+ \popendofline
+ \protect
+ \stopreadingfile}
+
+\unexpanded\def\quittypescriptscanning
+ {\settrue\c_font_typescripts_quit} % public
+
+\def\font_typescripts_start_store#definitions\stoptypescript
+ {\global\advance\c_font_typescripts_n_of_preloaded\plusone
+ \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
+ {\starttypescript#definitions\stoptypescript}%
+ %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
+ \global\t_font_typescripts\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_font_typescripts
+ \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection
+ {\global\advance\c_font_typescripts_n_of_preloaded\plusone
+ \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
+ {\starttypescriptcollection#definitions\stoptypescriptcollection}%
+ %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
+ \global\t_font_typescripts\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_font_typescripts
+ \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\def\font_typescripts_load_file#filename%
+ {\setfalse\c_font_typescripts_quit
+ \pushmacro\currenttypefile
+ \def\currenttypefile{#filename}%
+ \ifconditional\c_font_typescripts_preload
+ \font_typescript_process_typescript_file_and_store
+ \else
+ \font_typescript_process_typescript_file
+ \fi
+ \popmacro\currenttypefile
+ \ifconditional\c_font_typescripts_quit
+ \quitcommalist
+ \setfalse\c_font_typescripts_quit
+ \fi}
+
+\def\font_typescript_process_typescript_file_and_store
+ {\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname
+ \ifx\t_font_typescripts\relax
+ \font_typescript_process_typescript_store_indeed
+ \fi
+ \the\t_font_typescripts}
+
+\def\font_typescript_process_typescript_store_indeed
+ {\newtoks\t_font_typescripts % is \relaxed elsewhere
+ \begingroup
+ \let\starttypescript \font_typescripts_start_store
+ \let\starttypescriptcollection\font_typescripts_collection_start_store
+ \font_typescript_process_typescript_file
+ \endgroup
+ \expandafter\let\csname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts}
+
+\def\font_typescript_process_typescript_file
+ {\clf_doprocesstypescriptfile{\currenttypefile}}
+
+\unexpanded\def\usetypescriptonce
+ {\dotripleempty\font_typescripts_use_once}
+
+\def\font_typescripts_use_once[#one][#two][#three]%
+ {\ifcsname\??typescriptonce#one:#two:#three\endcsname
+ \writestatus\m!fonts{once (#one) (#two) (#three)}%
+ \else
+ \expandafter\let\csname\??typescriptonce#one:#two:#three\endcsname\relax
+ \font_typescripts_use[#one][#two][#three]%
+ \fi}
+
+% \definetypescriptsynonym[lbr][cmr]
+
+\unexpanded\def\definetypescriptsynonym
+ {\dodoubleempty\font_typescripts_synonym_define}
+
+\def\font_typescripts_synonym_define[#name][#synonym]%
+ {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi}
+
+\def\truetypescript#name% recursove so no \lastnamedcs
+ {\ifcsname\??typescriptsynonyms#name\endcsname
+ %\expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname
+ \expandafter\truetypescript\lastnamedcs
+ \else
+ #name%
+ \fi}
+
+% script [serif] [default] [size]
+% script [serif] [computer-modern] [size]
+% script [serif] [computer-modern] [ec]
+% script [serif] [computer-modern] [name]
+% script [serif] [computer-modern] [special]
+
+\prependtoks
+ \settrue\c_font_typescripts_first_pass
+\to \everyjob
+
+\unexpanded\def\starttypescript
+ {\ifcase\typescriptstate
+ % 0 = skip
+ \expandafter\font_typescripts_start_gobble
+ \or
+ % 1 = process
+ \expandafter\font_typescripts_start_process
+ \or
+ % 2 = store
+ \expandafter\font_typescripts_start_document
+ \else
+ % ? = skip
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_gobble#definitions\stoptypescript{}
+
+\def\font_typescripts_start_document#definitions\stoptypescript
+ %{\appendtoks\starttypescript#definitions\stoptypescript\to\c_font_typescripts_document}
+ {\c_font_typescripts_document\expandafter{\the\c_font_typescripts_document\starttypescript#definitions\stoptypescript}}
+
+\def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed
+ {\let\typescriptone \m_font_typescripts_one
+ \let\typescripttwo \m_font_typescripts_two
+ \let\typescriptthree\m_font_typescripts_three
+ \let\m_font_typescripts_match\empty
+ \doifelsenextoptionalcs\font_typescripts_start_process_one\font_typescripts_start_process_all}
+
+\def\font_typescripts_start_process_all % could be a \let
+ {\ifconditional\c_font_typescripts_first_pass
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ % skip this since it may do unwanted resets, like
+ % setting symbolic font names to unknown, especially
+ % in run time user type scripts
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_show_match
+ {\writestatus\m!fonts{match:\ifx\currenttypefile\relax\space *\fi \m_font_typescripts_match}}
+
+\def\font_typescripts_start_process_yes
+ {\ifdone
+ \typescriptfoundtrue
+ \iftracetypescripts\font_typescripts_show_match\fi
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_process_one
+ {\font_typescripts_check\m_font_typescripts_one\typescriptone\font_typescripts_start_process_again_one}
+
+\def\font_typescripts_start_process_two
+ {\font_typescripts_check\m_font_typescripts_two\typescripttwo\font_typescripts_start_process_again_two}
+
+\def\font_typescripts_start_process_three
+ {\font_typescripts_check\m_font_typescripts_three\typescriptthree\font_typescripts_start_process_again_three}
+
+\def\font_typescripts_start_process_again_one
+ {\doifelsenextoptionalcs\font_typescripts_start_process_two\font_typescripts_start_process_yes}
+
+\def\font_typescripts_start_process_again_two
+ {\doifelsenextoptionalcs\font_typescripts_start_process_three\font_typescripts_start_process_yes}
+
+\let\font_typescripts_start_process_again_three\font_typescripts_start_process_yes
+
+\def\font_typescripts_start_process_indeed
+ {\pushmacro\fontclass}
+
+\unexpanded\def\stoptypescript
+ {\popmacro\fontclass}
+
+\def\font_typescripts_check#asked#target#followup[#value]% script use value next
+ {\donefalse
+ \edef\m_font_typescripts_check{#value}%
+ \ifx\m_font_typescripts_check\empty % no longer needed / met
+ \ifcase\typescriptmethod\or\donetrue\fi
+ \else\ifx#asked\s!all
+ \donetrue
+ \else\ifx\m_font_typescripts_check\s!all
+ \donetrue
+ \else\ifx#asked\m_font_typescripts_check % saves 10% trace so probably faster too
+ \donetrue
+ \let#target\m_font_typescripts_check
+ \else
+ \doifelsecommon\m_font_typescripts_check#asked\donetrue\donefalse
+ \ifdone
+ \let#target\commalistelement
+ \fi
+ \fi\fi\fi\fi
+ \ifdone
+ \iftracetypescripts\extendtypescriptmatch\fi
+ \expandafter#followup%
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\extendtypescriptmatch
+ {\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}}
+
+%D Map files will go away in \LUATEX, but till that happens we
+%D use stripped down support for loading them.
+
+\unexpanded\def\loadmapfile{\dosingleempty\font_map_load_file}
+\unexpanded\def\loadmapline{\dodoubleempty\font_map_load_line}
+
+\def\font_map_load_file[#filename]%
+ {\clf_loadmapfile{#filename}}
+
+\def\font_map_load_line[#kind][#data]%
+ {\clf_loadmapline{#kind}{#data}}
+
+\unexpanded\def\forgetmapfiles
+ {\clf_resetmapfiles}
+
+% \prependtoks
+% \loadmapfile[mkiv-base.map]% can't we preload this one?
+% \to \everystarttext
+
+%D A handy shortcut:
+
+% \definetypescriptprefix[serif][Serif]
+% \definetypescriptprefix[sans] [Sans]
+% \definetypescriptprefix[mono] [Mono]
+%
+%\starttypescript [serif,sans,mono] [handling,hanging,hz] [pure,normal,hz,quality]
+% \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree]
+% \stoptypescript
+
+\unexpanded\def\definetypescriptprefix
+ {\dodoubleargument\font_typescripts_define_prefix}
+
+\def\font_typescripts_define_prefix[#name][#prefix]%
+ {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global
+
+% without testing:
+%
+% \def\typescriptprefix#name%
+% {\csname\??typescriptprefix#name\endcsname}
+%
+% with testing:
+
+\def\typescriptprefix#name%
+ %{\ifcsname\??typescriptprefix#name\endcsname\csname\??typescriptprefix#name\endcsname\else#name\fi}
+ {\ifcsname\??typescriptprefix#name\endcsname\lastnamedcs\else#name\fi}
+
+% defining typefaces:
+%
+% \definetypeface [joke] [rm]
+% \definetypeface [joke] [rm] [settings]
+% \definetypeface [joke] [rm] [serif] [lucida]
+% \definetypeface [joke] [rm] [serif] [lucida] [size]
+% \definetypeface [joke] [rm] [serif] [lucida] [size] [settings]
+% \definetypeface [joke] [specification]
+
+\unexpanded\def\definetypeface
+ {\dosixtupleargument\font_typefaces_define}
+
+\appendtoks
+ \font_helpers_reset_fontclass_math_families\fontclass
+\to \everybeforedefinetypeface
+
+%D This hooks into the font switcher:
+
+\settrue\autotypescripts
+
+\unexpanded\def\trycurrentfontclass#typeface%
+ {\ifconditional\autotypescripts
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ \iftracetypescripts\writestatus\m!fonts{auto load typescript file 1: [#typeface]}\fi
+ \usetypescriptfile[#typeface]%
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi
+ \fi
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi}
+
+%D Now we define:
+
+\def\font_typefaces_define
+ {\iffifthargument
+ \singleexpandafter\font_typefaces_define_a
+ \else\iffourthargument
+ \doubleexpandafter\font_typefaces_define_b
+ \else\ifthirdargument
+ \tripleexpandafter\font_typefaces_define_c
+ \else
+ \tripleexpandafter\font_typefaces_define_d
+ \fi\fi\fi}
+
+\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+ {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi
+ \font_typefaces_define_indeed[#name][#style]%
+ \font_typefaces_defining_start{#name}{#style}{#settings}%
+ \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+ \iftypescriptfound
+ % we're okay
+ \else
+ \ifconditional\autotypescripts
+ \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi
+ \usetypescriptfile[#fontname]%
+ \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+ \fi
+ \fi
+ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
+ \font_typefaces_defining_stop}
+
+\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#dummya][#dummyb]%
+ {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#dummyb]}
+
+\def\font_typefaces_define_c[#name][#style][#dummya][#dummyb][#dummyc][#dummyd]%
+ {\font_typefaces_define_indeed[#name][#style]}
+
+\def\font_typefaces_define_d[#name][#specification][#dummya][#dummyb][#dummyc][#dummyd]% use definitions in lfg file
+ {\clf_definetypeface{#name}{#specification}}
+
+\def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition
+ {\doifsomething{#name}
+ {\ifcsname\??typescriptdefaultstyles#name\endcsname \else
+ \registerfontclass{#name}%
+ \setxvalue{\??typescriptdefaultstyles#name}{#style}%
+ \fi
+ \ifcsname#name\endcsname \else
+ \setugvalue{#name}{\switchtotypeface[#name][#style]}%
+ \fi}}
+
+\def\font_typefaces_defining_start#name#style#settings%
+ {\let\@@tsrscale \!!plusone % as we push/pop
+ \let\@@tsfeatures \empty
+ \let\@@tsfallbacks \empty
+ \let\@@tsgoodies \empty
+ \let\@@tsdirection \empty
+ \let\@@tsdesignsize\empty
+ \geteparameters[\??ts][#settings]% todo raw
+ \pushmacro\fontclass
+ \pushmacro\fontclassstyle
+ \setcurrentfontclass{#name}%
+ \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection
+ \the\everybeforedefinetypeface}
+
+\def\tsvar#key#default% undocumented and unofficial
+ {\expandafter\ifx\csname\??ts#key\endcsname\empty
+ #default%
+ \else
+ \csname\??ts#key\endcsname
+ \fi}
+
+\def\font_typefaces_defining_stop
+ {\the\everyafterdefinetypeface
+ \popmacro\fontclassstyle
+ \popmacro\fontclass}
+
+\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d)
+ {\font_typefaces_define_indeed[#name][#style]%
+ \font_typefaces_defining_start{#name}{#style}{#settings}%
+ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
+ \font_typefaces_defining_stop}
+
+\unexpanded\def\setuptypeface% [class] [settings]
+ {\dodoubleempty\font_typefaces_setup}
+
+\unexpanded\def\switchtotypeface% [class] [settings]
+ {\dodoubleempty\font_typefaces_switch}
+
+\def\font_typefaces_setup[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\fontclass
+ \ifsecondargument
+ \setupbodyfont[#settings]%
+ \else\ifx\fontclass\empty
+ \setupbodyfont[\s!rm]%
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
+ \else
+ \setupbodyfont[\s!rm]%
+ \fi \fi \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+\def\font_typefaces_switch[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\globalfontclass
+ \ifsecondargument
+ \switchtobodyfont[#settings]%
+ \else\ifx\fontclass\empty
+ \switchtobodyfont[\s!rm]%
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
+ \else
+ \switchtobodyfont[\s!rm]%
+ \fi \fi \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+%D For Taco:
+%D
+%D \starttyping
+%D \inherittypeface[palatino][rm][postscript]
+%D \inherittypeface[palatino][rm][\fontclass]
+%D \inherittypeface[palatino][rm] % == \fontclass
+%D \inherittypeface[palatino] % == [rm,ss,tt,mm]
+%D \stoptyping
+
+\unexpanded\def\inherittypeface
+ {\dotripleempty\font_typescripts_inherit_indeed}
+
+\def\font_typescripts_inherit_indeed[#name][#styles][#parentclass]%
+ {\doifelsenothing{#styles}
+ {\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]}
+ {\doifnot{#name}{#parentclass}
+ {\global\let\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
+ \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}%
+ \processcommalist[#styles]\font_typescripts_inherit_check_step}}}
+
+\let\font_typescripts_inherit_check_step\relax
+
+%D This hooks into the font mechanism with:
+
+\def\font_typescripts_inherit_check_indeed#name% called often
+ {\ifcsname\??typescriptinheritances\fontclass:#name\endcsname
+ %\expandafter\let\expandafter\fontclass\csname\??typescriptinheritances\fontclass:#name\endcsname
+ \expandafter\let\expandafter\fontclass\lastnamedcs
+ \fi}
+
+\let\font_typescripts_inherit_check\gobbleoneargument
+
+% not yet:
+%
+% \def\font_helpers_check_relative_font_id
+% {\ifcsname\??typescriptrelatives\fontclass\endcsname
+% \expandafter\let\expandafter\relativefontid\csname\??typescriptrelatives\fontclass\endcsname
+% \else
+% \expandafter\normalxdef\csname\??typescriptrelatives\fontclass\endcsname{\the\lastfontid}%
+% \let\relativefontid\minusone
+% \fi}
+
+\def\v_font_string_d % default fontstyle (expands to \s!Serif in font-ini)
+ {\expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!rm \s!Serif \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!ss \s!Sans \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\unexpanded\def\font_helpers_set_fontstyle_of_fontclass
+ {\ifx\fontclass\empty
+ \let\fontstyle\s!rm
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ %\edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}%
+ \edef\fontstyle{\lastnamedcs}%
+ \else
+ \let\fontstyle\s!rm
+ \fi\fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-lua.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-lua.mkiv
new file mode 100644
index 00000000000..fac6c3867a8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-lua.mkiv
@@ -0,0 +1,86 @@
+%D \module
+%D [ file=type-lua,
+%D version=2009.11.27,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=\MKIV\ goodies,
+%D author=Hans Hagen \& Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\starttypescriptcollection [luatex]
+
+\starttypescript [specserif] [\s!all] [\s!name]
+ \definefontsynonym [\s!Serif] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifCaps] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\stoptypescript
+
+\starttypescript [specsans] [\s!all] [\s!name]
+ \definefontsynonym [\s!Sans] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansCaps] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\stoptypescript
+
+\starttypescript [specmono] [\s!all] [\s!name]
+ \definefontsynonym [\s!Mono] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoItalic] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBold] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoCaps] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\stoptypescript
+
+% we could combine these in the normal serif settings
+
+\starttypescript [specserif] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!rm] [\s!default]
+\stoptypescript
+
+\starttypescript [specsans] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!ss] [\s!default]
+\stoptypescript
+
+\starttypescript [specmono] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!tt] [\s!default]
+\stoptypescript
+
+\starttypescript [specserif] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!rm] [\s!default]
+\stoptypescript
+
+\starttypescript [specsans] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!ss] [\s!default]
+\stoptypescript
+
+\starttypescript [specmono] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!tt] [\s!default]
+\stoptypescript
+
+\stoptypescriptcollection
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-one.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-one.mkiv
new file mode 100644
index 00000000000..12b9e14add2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-one.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=type-one,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Type One Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% We use open type fonts in \MKIV. However we can still use type
+% one fonts but there are not that many useful left that only
+% come in type one.
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-otf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-otf.mkiv
new file mode 100644
index 00000000000..1f1564ef571
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-otf.mkiv
@@ -0,0 +1,27 @@
+%D \module
+%D [ file=type-otf,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Opentype Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D When a fontname equals the filename, then use
+%D
+%D \starttyping
+%D \setupfontsynonym [LMRoman10-DemiOblique] [features=default]
+%D \definefontsynonym [LMRoman10-DemiOblique] [\s!name:LMRoman10-DemiOblique] [features=default]
+%D \definefontsynonym [LMRoman10-DemiOblique] [lmroman10-demioblique] [features=default]
+%D \stoptyping
+%D
+%D This file is no longer used. When going from \MKII\ to \MKIV\ quite some typescripts
+%D were collected here but now they are nicely distributed over files and a semi-automatic
+%D loaded takes care of finding the right ones. This also benefits for instance alternative
+%D loaders (like simplefonts).
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv
new file mode 100644
index 00000000000..e2d7071d461
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv
@@ -0,0 +1,124 @@
+%D \module
+%D [ file=type-set,
+%D version=2005.02.04, % moved from ini/def
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Default Settings,
+%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
+
+\ifnum\typescriptstate=\plustwo
+
+ % we store some typescripts in the format
+
+ % \loadmarkfile{type-def}
+ % \loadmarkfile{type-lua}
+ % \loadmarkfile{type-siz}
+ % \loadmarkfile{type-fbk}
+ % \loadmarkfile{type-imp-latinmodern}
+
+ % but ... let's make sure that newlines are gone
+
+ \loadfoundtypescriptfile{type-def.mkiv}
+ \loadfoundtypescriptfile{type-lua.mkiv}
+ \loadfoundtypescriptfile{type-siz.mkiv}
+ \loadfoundtypescriptfile{type-fbk.mkiv}
+ \loadfoundtypescriptfile{type-imp-latinmodern.mkiv}
+
+ % and not:
+
+ % \loadtypescriptfile[def] % meant for local usage only
+ % \loadtypescriptfile[fbk] % meant for local usage only
+ % \loadtypescriptfile[lua] % meant for local usage only
+ % \loadtypescriptfile[siz] % meant for local usage only
+ % \usetypescriptfile[latinmodern]
+
+ \usetypescriptfile[loc]
+
+ % We want these names preset but they conflict with later loads so from now on
+ % one has to define a proper typeface if they are needed.
+ %
+ % \usetypescript[serif,sans,mono,math] [latin-modern]
+
+\else
+
+ \usetypescriptfile[def]
+ \usetypescriptfile[fbk]
+ \usetypescriptfile[lua]
+ \usetypescriptfile[siz]
+ \usetypescriptfile[latinmodern]
+ \usetypescriptfile[loc]
+
+\fi
+
+\definefilesynonym [type-imp-lucida.mkiv] [type-imp-lucida-typeone.mkiv]
+\definefilesynonym [type-imp-lucidaot.mkiv] [type-imp-lucida-opentype.mkiv]
+\definefilesynonym [type-imp-lucidadk.mkiv] [type-imp-lucida-opentype.mkiv]
+
+\definefilesynonym [type-imp-dejavu-condensed.mkiv] [type-imp-dejavu.mkiv]
+
+\definefilesynonym [type-imp-palatino.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-courier.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-avantgarde.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-helvetica.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-chancery.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-bookman.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-schoolbook.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-times.mkiv] [type-imp-texgyre.mkiv]
+
+\definefilesynonym [type-imp-cursor.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-adventor.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-heros.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-chorus.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-bonum.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-schola.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-pagella.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-termes.mkiv] [type-imp-texgyre.mkiv]
+
+\definefilesynonym [type-imp-mscoretimes.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscorearial.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscorecourier.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscoreverdana.mkiv] [type-imp-mscore.mkiv]
+
+\definefilesynonym [type-imp-candara.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-consolas.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-constantia.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-corbel.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-calibri.mkiv] [type-imp-cleartype.mkiv]
+
+\definefilesynonym [type-imp-antykwa-poltawskiego.mkiv] [type-imp-antykwapoltawskiego.mkiv]
+
+%definefilesynonym [type-imp-mac.mkiv] [type-imp-osx.mkiv]
+%definefilesynonym [type-imp-win.mkiv] [type-imp-mscore.mkiv]
+
+\definefilesynonym [type-imp-eulernovum.mkiv] [type-imp-euler.mkiv]
+\definefilesynonym [type-imp-eulernova.mkiv] [type-imp-euler.mkiv]
+
+\definefilesynonym [type-imp-euler-with-pagella.mkiv] [type-imp-euler.mkiv]
+\definefilesynonym [type-imp-pagella-with-euler.mkiv] [type-imp-euler.mkiv]
+
+\definefilesynonym [type-imp-mdbch.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mdugm.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mdput.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mdici.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mdpgd.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mdpus.mkiv] [type-imp-mathdesign.mkiv]
+
+\definefilesynonym [type-imp-mathdesignch.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesigngm.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesignut.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesignci.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesigngd.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesignus.mkiv] [type-imp-mathdesign.mkiv]
+
+\definefilesynonym [type-imp-mathdesigncharter.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesigngaramond.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-mathdesignutopia.mkiv] [type-imp-mathdesign.mkiv]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-siz.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-siz.mkiv
new file mode 100644
index 00000000000..d4c90b18229
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-siz.mkiv
@@ -0,0 +1,169 @@
+%D \module
+%D [ file=type-siz,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Sizing scripts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+% beware: no \s! before keys as these are interpreted
+
+\starttypescriptcollection[\s!size]
+
+\starttypescript [\s!serif] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!rm] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!sans] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!ss] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!mono] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!tt] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!math] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!mm] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!handwriting] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!hw] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!calligraphy] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!cg] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!casual] [\s!default] [\s!size]
+ \definebodyfont
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!rm] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!all] [\s!dtp] [\s!size]
+
+ \definebodyfontenvironment
+ [4pt]
+ [\s!text=4pt,\s!script=4pt,\s!scriptscript=4pt,
+ \s!x=4pt,\s!xx=4pt,\v!big=6pt,\v!small=4pt]
+
+ \definebodyfontenvironment
+ [5pt]
+ [\s!text=5pt,\s!script=5pt,\s!scriptscript=5pt,
+ \s!x=5pt,\s!xx=5pt,\v!big=7pt,\v!small=5pt]
+
+ \definebodyfontenvironment
+ [6pt]
+ [\s!text=6pt,\s!script=5pt,\s!scriptscript=5pt,
+ \s!x=5pt,\s!xx=5pt,\v!big=8pt,\v!small=5pt]
+
+ \definebodyfontenvironment
+ [7pt]
+ [\s!text=7pt,\s!script=6pt,\s!scriptscript=5pt,
+ \s!x=6pt,\s!xx=5pt,\v!big=9pt,\v!small=5pt]
+
+ \definebodyfontenvironment
+ [8pt]
+ [\s!text=8pt,\s!script=6pt,\s!scriptscript=5pt,
+ \s!x=6pt,\s!xx=5pt,\v!big=10pt,\v!small=6pt]
+
+ \definebodyfontenvironment
+ [9pt]
+ [\s!text=9pt,\s!script=7pt,\s!scriptscript=5pt,
+ \s!x=7pt,\s!xx=5pt,\v!big=11pt,\v!small=7pt]
+
+ \definebodyfontenvironment
+ [10pt]
+ [\s!text=10pt,\s!script=7pt,\s!scriptscript=5pt,
+ \s!x=8pt,\s!xx=6pt,\v!big=12pt,\v!small=8pt]
+
+ \definebodyfontenvironment
+ [11pt]
+ [\s!text=11pt,\s!script=8pt,\s!scriptscript=6pt,
+ \s!x=9pt,\s!xx=7pt,\v!big=13pt,\v!small=9pt]
+
+ \definebodyfontenvironment
+ [12pt]
+ [\s!text=12pt,\s!script=9pt,\s!scriptscript=7pt,
+ \s!x=10pt,\s!xx=8pt,\v!big=14pt,\v!small=10pt]
+
+ \definebodyfontenvironment
+ [13pt]
+ [\s!text=13pt,\s!script=10pt,\s!scriptscript=8pt,
+ \s!x=11pt,\s!xx=9pt,\v!big=16pt,\v!small=11pt]
+
+ \definebodyfontenvironment
+ [14pt]
+ [\s!text=14pt,\s!script=10pt,\s!scriptscript=7pt,
+ \s!x=12pt,\s!xx=10pt,\v!big=16pt,\v!small=12pt]
+
+ \definebodyfontenvironment
+ [16pt]
+ [\s!text=16pt,\s!script=12pt,\s!scriptscript=9pt,
+ \s!x=13pt,\s!xx=11pt,\v!big=18pt,\v!small=14pt]
+
+ % suboptimal math sizes
+
+ \definebodyfontenvironment
+ [18pt]
+ [\s!text=18pt,\s!script=16pt,\s!scriptscript=14pt,
+ \s!x=16pt,\s!xx=14pt,\v!big=22pt,\v!small=16pt]
+
+ \definebodyfontenvironment
+ [22pt]
+ [\s!text=22pt,\s!script=22pt,\s!scriptscript=18pt,
+ \s!x=18pt,\s!xx=16pt,\v!big=28pt,\v!small=18pt]
+
+ \definebodyfontenvironment
+ [28pt]
+ [\s!text=28pt,\s!script=22pt,\s!scriptscript=18pt,
+ \s!x=22pt,\s!xx=18pt,\v!big=28pt,\v!small=22pt]
+
+\stoptypescript
+
+\starttypescript [\s!serif] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!rm] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!sans] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!ss] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!mono] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!tt] [\s!default]
+\stoptypescript
+
+\starttypescript [\s!math] [\s!dtp] [\s!size]
+ \definebodyfont
+ [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
+ [\s!mm] [\s!default]
+\stoptypescript
+
+\stoptypescriptcollection
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-tmf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-tmf.mkiv
new file mode 100644
index 00000000000..829b6baec99
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/type-tmf.mkiv
@@ -0,0 +1,14 @@
+%D \module
+%D [ file=type-tmf,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Core \TEX\ Fonts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua
new file mode 100644
index 00000000000..ce6a65baf37
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua
@@ -0,0 +1,385 @@
+if modules then modules = { } end modules ['typo-bld'] = { -- was node-par
+ version = 1.001,
+ comment = "companion to typo-bld.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- no need for nuts in the one-line demo (that might move anyway)
+
+local insert, remove = table.insert, table.remove
+
+builders = builders or { }
+local builders = builders
+
+builders.paragraphs = builders.paragraphs or { }
+local parbuilders = builders.paragraphs
+
+parbuilders.constructors = parbuilders.constructors or { }
+local constructors = parbuilders.constructors
+
+constructors.names = constructors.names or { }
+local names = constructors.names
+
+constructors.numbers = constructors.numbers or { }
+local numbers = constructors.numbers
+
+constructors.methods = constructors.methods or { }
+local methods = constructors.methods
+
+local a_parbuilder = attributes.numbers['parbuilder'] or 999 -- why 999
+constructors.attribute = a_parbuilder
+
+local unsetvalue = attributes.unsetvalue
+local texsetattribute = tex.setattribute
+local texnest = tex.nest
+local texlists = tex.lists
+
+local nodes = nodes
+local nodepool = nodes.pool
+local new_baselineskip = nodepool.baselineskip
+local new_lineskip = nodepool.lineskip
+local insert_node_before = nodes.insert_before
+local hpack_node = nodes.hpack
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+storage.register("builders/paragraphs/constructors/names", names, "builders.paragraphs.constructors.names")
+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_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 mainconstructor = nil -- not stored in format
+local nofconstructors = 0
+local stack = { }
+
+function constructors.define(name)
+ nofconstructors = nofconstructors + 1
+ names[nofconstructors] = name
+ numbers[name] = nofconstructors
+end
+
+function constructors.set(name) --- will go
+ if name then
+ mainconstructor = numbers[name] or unsetvalue
+ else
+ mainconstructor = stack[#stack] or unsetvalue
+ end
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor ~= unsetvalue then
+ constructors.enable()
+ end
+end
+
+function constructors.start(name)
+ local number = numbers[name]
+ insert(stack,number)
+ mainconstructor = number or unsetvalue
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor ~= unsetvalue then
+ constructors.enable()
+ end
+ -- report_par_builder("start %a",name)
+end
+
+function constructors.stop()
+ remove(stack)
+ mainconstructor = stack[#stack] or unsetvalue
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor == unsetvalue then
+ constructors.disable()
+ end
+ -- report_par_builder("stop")
+end
+
+-- return values:
+--
+-- true : tex will break itself
+-- false : idem but dangerous
+-- head : list of valid vmode nodes with last being hlist
+
+function constructors.handler(head,followed_by_display)
+ if type(head) == "boolean" then
+ return head
+ else
+ local attribute = head[a_parbuilder] -- or mainconstructor
+ if attribute then
+ local method = names[attribute]
+ if method then
+ local handler = methods[method]
+ if handler then
+ return handler(head,followed_by_display)
+ else
+ report_par_builder("contructor method %a is not defined",tostring(method))
+ return true -- let tex break
+ end
+ end
+ end
+ return true -- let tex break
+ end
+end
+
+-- just for testing
+
+function constructors.methods.default(head,followed_by_display)
+ return true -- let tex break
+end
+
+-- also for testing (now also surrounding spacing done)
+
+function builders.paragraphs.constructors.methods.oneline(head,followed_by_display)
+ -- when needed we will turn this into a helper
+ local t = texnest[texnest.ptr]
+ local h = hpack_node(head)
+ local d = tex.baselineskip.width - t.prevdepth - h.height
+ t.prevdepth = h.depth
+ t.prevgraf = 1
+ if d < tex.lineskiplimit then
+ return insert_node_before(h,h,new_lineskip(tex.lineskip))
+ else
+ return insert_node_before(h,h,new_baselineskip(d))
+ end
+end
+
+-- It makes no sense to have a sequence here as we already have
+-- pre and post hooks and only one parbuilder makes sense, so no:
+--
+-- local actions = nodes.tasks.actions("parbuilders")
+--
+-- yet ... maybe some day.
+
+local actions = constructors.handler
+local enabled = false
+
+local function processor(head,followed_by_display)
+ -- todo: not again in otr so we need to flag
+ if enabled then
+ starttiming(parbuilders)
+ local head = actions(head,followed_by_display)
+ stoptiming(parbuilders)
+ return head
+ else
+ return true -- let tex do the work
+ end
+end
+
+function constructors.enable () enabled = true end
+function constructors.disable() enabled = false end
+
+callbacks.register('linebreak_filter', processor, "breaking paragraps into lines")
+
+statistics.register("linebreak processing time", function()
+ return statistics.elapsedseconds(parbuilders)
+end)
+
+-- todo: move from nodes.builders to builders
+
+nodes.builders = nodes.builder or { }
+local builders = nodes.builders
+
+local normalize = typesetters.paragraphs.normalize
+
+local vboxactions = nodes.tasks.actions("vboxbuilders")
+
+function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
+ local done = false
+ if head then
+ starttiming(builders)
+ if trace_vpacking then
+ local before = nodes.count(head)
+ head, done = vboxactions(head,groupcode,size,packtype,maxdepth,direction)
+ local after = nodes.count(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
+ else
+ head, done = vboxactions(head,groupcode)
+ end
+ stoptiming(builders)
+ end
+ return head, done
+end
+
+-- This one is special in the sense that it has no head and we operate on the mlv. Also,
+-- we need to do the vspacing last as it removes items from the mvl.
+
+local pageactions = nodes.tasks.actions("mvlbuilders")
+----- lineactions = nodes.tasks.actions("linebuilders")
+
+local function report(groupcode,head)
+ report_page_builder("trigger: %s",groupcode)
+ report_page_builder(" vsize : %p",tex.vsize)
+ report_page_builder(" pagegoal : %p",tex.pagegoal)
+ report_page_builder(" pagetotal: %p",tex.pagetotal)
+ report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>")
+end
+
+-- use tex.[sg]etlist
+
+-- check why box is called before after_linebreak .. maybe make categories and
+-- call 'm less
+
+
+-- this will be split into contribute_filter for these 4 so at some point
+-- thecheck can go away
+
+function builders.buildpage_filter(groupcode)
+ -- the next check saves 1% runtime on 1000 tufte pages
+ local head = texlists.contrib_head
+ local done = false
+ if head then
+ -- called quite often ... maybe time to remove timing
+ starttiming(builders)
+ if trace_page_builder then
+ report(groupcode,head)
+ end
+ head, done = pageactions(head,groupcode)
+ stoptiming(builders)
+ -- -- doesn't work here (not passed on?)
+ -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom
+ texlists.contrib_head = head or nil -- needs checking
+ -- tex.setlist("contrib_head",head,head and nodes.tail(head))
+ return done and head or true -- no return value needed
+ else
+ -- happens quite often
+ if trace_page_builder then
+ report(groupcode)
+ end
+ return nil, false -- no return value needed
+ end
+end
+
+callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc")
+callbacks.register('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
+---------.register('contribute_filter', builders.contribute_filter, "adding content to lists")
+
+statistics.register("v-node processing time", function()
+ return statistics.elapsedseconds(builders)
+end)
+
+local implement = interfaces.implement
+
+implement { name = "defineparbuilder", actions = constructors.define, arguments = "string" }
+implement { name = "setparbuilder", actions = constructors.set, arguments = "string" }
+implement { name = "startparbuilder", actions = constructors.start, arguments = "string" }
+implement { name = "stopparbuilder", actions = constructors.stop }
+implement { name = "enableparbuilder", actions = constructors.enable }
+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 setcolor = nodes.tracers.colors.set
+local listtoutf = nodes.listtoutf
+
+local report_hpack = logs.reporter("hpack routine")
+local report_vpack = logs.reporter("vpack routine")
+
+-- overflow|badness w h d dir
+
+local function vpack_quality(how,n,detail,first,last)
+ if last <= 0 then
+ report_vpack("%s vbox",how)
+ elseif first > 0 and first < last then
+ report_vpack("%s vbox at line %i - %i",how,first,last)
+ else
+ report_vpack("%s vbox at line %i",how,last)
+ end
+end
+
+trackers.register("builders.vpack.quality",function(v)
+ callback.register("vpack_quality",v and report_vpack_quality or nil)
+end)
+
+local report, show = false, false
+
+local function hpack_quality(how,detail,n,first,last)
+ if report then
+ local str = listtoutf(n.head,"",true,nil,true)
+ if last <= 0 then
+ report_hpack("%s hbox: %s",how,str)
+ elseif first > 0 and first < last then
+ report_hpack("%s hbox at line %i - %i: %s",how,first,last,str)
+ else
+ report_hpack("%s hbox at line %i: %s",how,last,str)
+ end
+ end
+ if show then
+ local width = 2*65536
+ local height = n.height
+ local depth = n.depth
+ local dir = n.dir
+ if height < 4*65526 then
+ height = 4*65526
+ end
+ if depth < 2*65526 then
+ depth = 2*65526
+ end
+ local rule = new_rule(width,height,depth)
+ rule.dir = dir
+ if how == "overfull" then
+ setcolor(rule,"red")
+ local kern = new_kern(-detail)
+ kern.next = rule
+ rule.prev = kern
+ rule = kern
+ elseif how == "underfull" then
+ setcolor(rule,"blue")
+ elseif how == "loose" then
+ setcolor(rule,"magenta")
+ elseif how == "tight" then
+ setcolor(rule,"cyan")
+ end
+ rule = hpack(rule)
+ rule.width = 0
+ rule.dir = dir
+ return rule
+ end
+end
+
+trackers.register("builders.hpack.quality",function(v)
+ report = v
+ callback.register("hpack_quality",(report or show) and hpack_quality or nil)
+end)
+
+trackers.register("builders.hpack.overflow",function(v)
+ show = v
+ callback.register("hpack_quality",(report or show) and hpack_quality or nil)
+end)
+
+-- local ignoredepth = - 65536000
+--
+-- callback.register("append_to_vlist_filter", function(box,location,prevdepth,mirrored)
+-- if prevdepth > ignoredepth then
+-- local b = tex.baselineskip
+-- local d = b.width - prevdepth
+-- local g = nil
+-- if mirrored then
+-- d = d - box.depth
+-- else
+-- d = d - box.height
+-- end
+-- if d < tex.lineskiplimit then
+-- g = nodes.pool.glue()
+-- g.spec = tex.lineskip
+-- else
+-- g = nodes.pool.baselineskip(d)
+-- end
+-- g.next = box
+-- box.prev = g
+-- return g, mirrored and box.height or box.depth
+-- else
+-- return box, mirrored and box.height or box.depth
+-- end
+-- end)
+--
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-bld.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.mkiv
new file mode 100644
index 00000000000..621d81c524f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.mkiv
@@ -0,0 +1,68 @@
+%D \module
+%D [ file=typo-bld, % was node-par,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Paragraph Building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Paragraph Building}
+
+%D This is very experimental, undocumented, subjected to changes, etc. just as
+%D the underlying interfaces. But at least it's cleaned as part of the status-mkiv
+%D cleanup.
+
+% \enabletrackers[builders.hpack.overflow]
+% \enabletrackers[builders.hpack.quality]
+% \enabletrackers[builders.vpack.quality]
+
+% \startparbuilder[default]
+% \input tufte \par
+% \startparbuilder[oneline]
+% \input tufte \par
+% \stopparbuilder
+% \input tufte \par
+% \stopparbuilder
+%
+% \startparbuilder[oneline]
+% \dorecurse{100}{\input ward \par}
+% \stopparbuilder
+
+\unprotect
+
+\registerctxluafile{typo-bld}{1.001}
+
+\definesystemattribute[parbuilder][public]
+
+\installcorenamespace {parbuilder}
+
+\unexpanded\def\defineparbuilder[#1]%
+ {\clf_defineparbuilder{#1}}
+
+\unexpanded\def\startparbuilder[#1]%
+ {\ifhmode\par\fi
+ \clf_startparbuilder{#1}}
+
+\unexpanded\def\stopparbuilder
+ {\ifhmode\par\fi
+ \clf_stopparbuilder}
+
+\unexpanded\def\setmainparbuilder[#1]%
+ {\clf_setparbuilder{#1}}
+
+% no high level interface, after all implementing a linebreaker is not something that
+% the average user will do
+
+\defineparbuilder[default] % just for testing
+\defineparbuilder[oneline] % just for testing
+\defineparbuilder[basic] % just for testing
+
+\unexpanded\def\enableparbuilders {\clf_enableparbuilder } % hooks in otr so we need to pickup
+\unexpanded\def\disableparbuilders{\clf_disableparbuilder} % hooks in otr so we need to pickup
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua
new file mode 100644
index 00000000000..106bb49546b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua
@@ -0,0 +1,500 @@
+if not modules then modules = { } end modules ['typo-brk'] = {
+ version = 1.001,
+ comment = "companion to typo-brk.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this code dates from the beginning and is kind of experimental; it
+-- will be optimized and improved soon
+
+local next, type, tonumber = next, type, tonumber
+local utfbyte, utfchar = utf.byte, utf.char
+local format = string.format
+
+local trace_breakpoints = false trackers.register("typesetters.breakpoints", function(v) trace_breakpoints = v end)
+
+local report_breakpoints = logs.reporter("typesetting","breakpoints")
+
+local nodes, node = nodes, node
+
+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
+local getboth = nuts.getboth
+local getsubtype = nuts.getsubtype
+local getfont = nuts.getfont
+local getid = nuts.getid
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setchar = nuts.setchar
+local setdisc = nuts.setdisc
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setboth = nuts.setboth
+local setsubtype = nuts.setsubtype
+
+local copy_node = nuts.copy
+local copy_nodelist = nuts.copy_list
+local free_node = nuts.free
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+local end_of_math = nuts.end_of_math
+
+local tonodes = nuts.tonodes
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local nodepool = nuts.pool
+local tasks = nodes.tasks
+
+local v_reset = interfaces.variables.reset
+local v_yes = interfaces.variables.yes
+
+local implement = interfaces.implement
+
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+local new_disc = nodepool.disc
+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
+local userkern_code = kerncodes.userkern
+local italickern_code = kerncodes.italiccorrection
+
+local typesetters = typesetters
+
+typesetters.breakpoints = typesetters.breakpoints or {}
+local breakpoints = typesetters.breakpoints
+
+breakpoints.mapping = breakpoints.mapping or { }
+breakpoints.numbers = breakpoints.numbers or { }
+
+breakpoints.methods = breakpoints.methods or { }
+local methods = breakpoints.methods
+
+local a_breakpoints = attributes.private("breakpoint")
+
+storage.register("typesetters/breakpoints/mapping", breakpoints.mapping, "typesetters.breakpoints.mapping")
+
+local mapping = breakpoints.mapping
+local numbers = breakpoints.mapping
+
+for i=1,#mapping do
+ local m = mapping[i]
+ numbers[m.name] = m
+end
+
+-- this needs a cleanup ... maybe make all of them disc nodes
+
+-- todo: use boundaries
+
+local function withattribute(n,a)
+ setfield(n,"attr",a)
+ return n
+end
+
+local function insert_break(head,start,stop,before,after,kern)
+ local a = getfield(start,"attr")
+ if not kern then
+ insert_node_before(head,start,withattribute(new_penalty(before),a))
+ insert_node_before(head,start,withattribute(new_glue(0),a))
+ end
+ insert_node_after(head,stop,withattribute(new_glue(0),a))
+ insert_node_after(head,stop,withattribute(new_penalty(after),a))
+end
+
+methods[1] = function(head,start,stop,settings,kern)
+ local p, n = getboth(stop)
+ if p and n then
+ insert_break(head,start,stop,10000,0,kern)
+ end
+ return head, stop
+end
+
+methods[6] = function(head,start,stop,settings,kern)
+ local p = getprev(start)
+ local n = getnext(stop)
+ if p and n then
+ if kern then
+ insert_break(head,start,stop,10000,0,kern)
+ else
+ local l = new_wordboundary()
+ local d = new_disc()
+ local r = new_wordboundary()
+ local a = getfield(start,"attr")
+ -- setfield(l,"attr",a)
+ setfield(d,"attr",a) -- otherwise basemode is forces and we crash
+ -- setfield(r,"attr",a)
+ setlink(p,l)
+ setlink(l,d)
+ setlink(d,r)
+ setlink(r,n)
+ if start == stop then
+ setboth(start)
+ setdisc(d,start,nil,copy_node(start))
+ else
+ setprev(start)
+ setnext(stop)
+ setdisc(d,start,nil,copy_nodelist(start))
+ end
+ stop = r
+ end
+ end
+ return head, stop
+end
+
+methods[2] = function(head,start) -- ( => (-
+ local p, n = getboth(start)
+ if p and n then
+ local tmp
+ head, start, tmp = remove_node(head,start)
+ head, start = insert_node_before(head,start,new_disc())
+ -- setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) -- just a copy will do
+ setfield(start,"attr",getfield(tmp,"attr"))
+ setfield(start,"replace",tmp)
+ local tmp = copy_node(tmp)
+ local hyphen = copy_node(tmp)
+ setchar(hyphen,languages.prehyphenchar(getfield(tmp,"lang")))
+ setlink(tmp,hyphen)
+ setfield(start,"post",tmp)
+ insert_break(head,start,start,10000,10000)
+ end
+ return head, start
+end
+
+methods[3] = function(head,start) -- ) => -)
+ local p, n = getboth(start)
+ if p and n then
+ local tmp
+ head, start, tmp = remove_node(head,start)
+ head, start = insert_node_before(head,start,new_disc())
+ -- setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) -- just a copy will do
+ setfield(start,"attr",getfield(tmp,"attr"))
+ setfield(start,"replace",tmp)
+ local tmp = copy_node(tmp)
+ local hyphen = copy_node(tmp)
+ setchar(hyphen,languages.prehyphenchar(getfield(tmp,"lang")))
+ setlink(hyphen,tmp)
+ setfield(start,"pre",hyphen)
+ insert_break(head,start,start,10000,10000)
+ end
+ return head, start
+end
+
+methods[4] = function(head,start) -- - => - - -
+ local p, n = getboth(start)
+ if p and n then
+ local tmp
+ head, start, tmp = remove_node(head,start)
+ head, start = insert_node_before(head,start,new_disc())
+ -- setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) -- just a copy will do
+ setfield(start,"attr",getfield(tmp,"attr"))
+ setdisc(start,copy_node(tmp),copy_node(tmp),tmp)
+ insert_break(head,start,start,10000,10000)
+ end
+ return head, start
+end
+
+methods[5] = function(head,start,stop,settings) -- x => p q r
+ local p, n = getboth(start)
+ if p and n then
+ local tmp
+ head, start, tmp = remove_node(head,start)
+ head, start = insert_node_before(head,start,new_disc())
+ local attr = getfield(tmp,"attr")
+ local font = getfont(tmp)
+ local left = settings.left
+ local right = settings.right
+ local middle = settings.middle
+ if left then
+ left = tonodes(tostring(left),font,attr)
+ end
+ if right then
+ right = tonodes(tostring(right),font,attr)
+ end
+ if middle then
+ middle = tonodes(tostring(middle),font,attr)
+ end
+ setdisc(start,left,right,middle)
+ -- setfield(start,"attr",copy_nodelist(attr)) -- todo: critical only -- just a copy will do
+ setfield(start,"attr",attr) -- todo: critical only -- just a copy will do
+ free_node(tmp)
+ insert_break(head,start,start,10000,10000)
+ end
+ return head, start
+end
+
+-- we know we have a limited set
+-- what if characters are replaced by the font handler
+-- do we need to go into disc nodes (or do it as first step but then we need a pre/post font handler)
+
+function breakpoints.handler(head)
+ local done = false
+ local nead = tonut(head)
+ local attr = nil
+ local map = nil
+ local current = nead
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local a = getattr(current,a_breakpoints)
+ if a and a > 0 then
+ if a ~= attr then
+ local data = mapping[a]
+ if data then
+ map = data.characters
+ else
+ map = nil
+ end
+ attr = a
+ end
+ if map then
+ local cmap = map[char]
+ if cmap then
+ -- for now we collect but when found ok we can move the handler here
+ -- although it saves nothing in terms of performance
+ local lang = getfield(current,"lang")
+ local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
+ if smap then
+ local skip = smap.skip
+ local start = current
+ local stop = current
+ current = getnext(current)
+ if skip then
+ while current do
+ local c = isglyph(current)
+ if c == char then
+ stop = current
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ end
+ local d = { start, stop, cmap, smap, char }
+ if done then
+ done[#done+1] = d
+ else
+ done = { d }
+ end
+ else
+ current = getnext(current)
+ end
+ setattr(start,a_breakpoints,unsetvalue) -- should not be needed
+ else
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ elseif id == math_code then
+ attr = nil
+ current = end_of_math(current)
+ if current then
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ if not done then
+ return head, false
+ end
+ -- we have hits
+ local numbers = languages.numbers
+ for i=1,#done do
+ local data = done[i]
+ local start = data[1]
+ local stop = data[2]
+ local cmap = data[3]
+ local smap = data[4]
+-- local lang = getfield(start,"lang")
+-- -- we do a sanity check for language
+-- 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
+ while prev and nleft ~= cleft do
+ local id = getid(prev)
+ if id == glyph_code then
+ cleft = cleft + 1
+ prev = getprev(prev)
+ elseif id == kern_code then
+ local s = getsubtype(prev)
+ if s == fontkern_code or s == italickern_code then
+ if cleft == 0 then
+ kern = prev
+ prev = getprev(prev)
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if nleft == cleft then
+ local nright = smap.nright
+ local cright = 0
+ local next = getnext(stop) -- getnext(start)
+ while next and nright ~= cright do
+ local char, id = isglyph(next)
+ if char then
+ if cright == 1 and cmap[char] then
+ -- let's not make it too messy
+ break
+ end
+ cright = cright + 1
+ next = getnext(next)
+ elseif id == kern_code then
+ local s = getsubtype(next)
+ if s == fontkern_code or s == italickern_code then
+ if cleft == 0 then
+ next = getnext(next)
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if nright == cright then
+ local method = methods[smap.type]
+ if method then
+ nead, start = method(nead,start,stop,smap,kern)
+ end
+ end
+-- end
+ end
+ end
+ return tonode(nead), true
+end
+
+local enabled = false
+
+function breakpoints.define(name)
+ local data = numbers[name]
+ if data then
+ -- error
+ else
+ local number = #mapping + 1
+ local data = {
+ name = name,
+ number = number,
+ characters = { },
+ }
+ mapping[number] = data
+ numbers[name] = data
+ end
+end
+
+function breakpoints.setreplacement(name,char,language,settings)
+ char = utfbyte(char)
+ local data = numbers[name]
+ if data then
+ local characters = data.characters
+ local cmap = characters[char]
+ if not cmap then
+ cmap = { }
+ characters[char] = cmap
+ end
+ local left, right, middle = settings.left, settings.right, settings.middle
+ cmap[language or ""] = {
+ type = tonumber(settings.type) or 1,
+ nleft = tonumber(settings.nleft) or 1,
+ nright = tonumber(settings.nright) or 1,
+ left = left ~= "" and left or nil,
+ right = right ~= "" and right or nil,
+ middle = middle ~= "" and middle or nil,
+ skip = settings.range == v_yes,
+ } -- was { type or 1, before or 1, after or 1 }
+ end
+end
+
+function breakpoints.set(n)
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = mapping[n]
+ if not n then
+ n = unsetvalue
+ else
+ if not enabled then
+ if trace_breakpoints then
+ report_breakpoints("enabling breakpoints handler")
+ end
+ tasks.enableaction("processors","typesetters.breakpoints.handler")
+ end
+ n = n.number
+ end
+ end
+ texsetattribute(a_breakpoints,n)
+end
+
+-- function breakpoints.enable()
+-- tasks.enableaction("processors","typesetters.breakpoints.handler")
+-- end
+
+-- interface
+
+implement {
+ name = "definebreakpoints",
+ actions = breakpoints.define,
+ arguments = "string"
+}
+
+implement {
+ name = "definebreakpoint",
+ actions = breakpoints.setreplacement,
+ arguments = {
+ "string",
+ "string",
+ "string",
+ {
+ { "type", "integer" },
+ { "nleft", "integer" },
+ { "nright", "integer" },
+ { "right" },
+ { "left" },
+ { "middle" },
+ { "range" },
+ }
+ }
+}
+
+implement {
+ name = "setbreakpoints",
+ actions = breakpoints.set,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-brk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.mkiv
new file mode 100644
index 00000000000..3f9ce6f3a49
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.mkiv
@@ -0,0 +1,99 @@
+%D \module
+%D [ file=typo-brk,
+%D version=2009.03.27, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Breakpoints,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Breakpoints}
+
+\unprotect
+
+% hm, we cannot prebuild lists, font dependent
+%
+% -- type nleft nright language left right middle
+%
+% -- we might eventually stick to only method 5
+
+\registerctxluafile{typo-brk}{1.001}
+
+\definesystemattribute[breakpoint][public,global]
+
+% see below: \exhyphenchar \minusone % we use a different order tha n base tex, so we really need this
+
+\unexpanded\def\definebreakpoints
+ {\dosingleargument\typo_breakpoints_define}
+
+\def\typo_breakpoints_define[#1]%
+ {\clf_definebreakpoints{#1}}
+
+\def\definebreakpoint
+ {\dotripleempty\typo_breakpoints_define_character}
+
+\def\typo_breakpoints_define_character[#1][#2][#3]% name char settings
+ {\begingroup
+ \getdummyparameters
+ [\c!type=\plusone,\c!nleft=\plusthree,\c!nright=\plusthree,%
+ \s!language=,\c!left=,\c!right=,\c!middle=,\c!range=\v!no,%
+ #3]%
+ \clf_definebreakpoint
+ {#1}%
+ {#2}%
+ {\reallanguagetag{\directdummyparameter\s!language}}%
+ {% maybe deal with #3 at the lua end
+ type \directdummyparameter\c!type
+ nleft \directdummyparameter\c!nleft
+ nright \directdummyparameter\c!nright
+ right {\directdummyparameter\c!right}%
+ left {\directdummyparameter\c!left}%
+ middle {\directdummyparameter\c!middle}%
+ range {\directdummyparameter\c!range}%
+ }%
+ \relax
+ \endgroup}
+
+\unexpanded\def\setbreakpoints[#1]%
+ {\exhyphenchar\minusone % we use a different order tha n base tex, so we really need this
+ \clf_setbreakpoints{#1}}
+
+\unexpanded\def\resetbreakpoints
+ {\attribute\breakpointattribute\attributeunsetvalue}
+
+\definebreakpoints[compound]
+
+% 1: simple break
+% 6: simple break but skip same
+
+\definebreakpoint [compound] [+] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
+%definebreakpoint [compound] [-] [\c!nleft=3,\c!nright=3,\c!type=1,\c!range=\v!yes] % middle=+,left=,right=
+\definebreakpoint [compound] [-] [\c!nleft=3,\c!nright=3,\c!type=6,\c!range=\v!yes] % middle=+,left=,right=
+\definebreakpoint [compound] [/] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
+\definebreakpoint [compound] [(] [\c!nleft=3,\c!nright=3,\c!type=2] % type=5,middle=(,left=(-,right=
+\definebreakpoint [compound] [)] [\c!nleft=3,\c!nright=3,\c!type=3] % type=5,middle=),left=,right=-)
+
+\let\installbreakpoint\definebreakpoint % for a while
+
+% \start \hsize 1.5cm \setbreakpoints[compound]
+% \definebreakpoint [compound] [-] [nleft=3,nright=3,type=5,left=,right={-},middle={-}]
+% \definebreakpoint [compound] [(] [nleft=3,nright=3,type=5,left=,right={(-},middle={(}]
+% \definebreakpoint [compound] [)] [nleft=3,nright=3,type=5,left={-)},right=,middle={)}]
+% composed-word\par composed(word)\par
+% \stop
+
+% \mainlanguage[czech]
+% \definebreakpoint [compound] [\number`-] [language=cs,nleft=3,nright=3,type=4]
+% \setbreakpoints[compound]
+% \start \hsize 1mm test-test \par \stop
+
+%D Maybe some day default:
+%
+% \setbreakpoints[compound]
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua
new file mode 100644
index 00000000000..62b90b8ab36
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua
@@ -0,0 +1,487 @@
+if not modules then modules = { } end modules ['typo-cap'] = {
+ version = 1.001,
+ comment = "companion to typo-cap.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+ }
+
+local next, type = next, type
+local format, insert = string.format, table.insert
+local div, randomnumber = math.div, math.random
+
+local trace_casing = false trackers .register("typesetters.casing", function(v) trace_casing = v end)
+local check_kerns = true directives.register("typesetters.casing.checkkerns", function(v) check_kerns = v end)
+
+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 getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getdisc = nuts.getdisc
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setchar = nuts.setchar
+
+local copy_node = nuts.copy
+local end_of_math = nuts.end_of_math
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+local insert_after = nuts.insert_after
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+
+local kerning_code = kerncodes.kerning
+
+local tasks = nodes.tasks
+
+local newkern = nuts.pool.kern
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontchar = fonthashes.characters
+
+local variables = interfaces.variables
+local v_reset = variables.reset
+
+local chardata = characters.data
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.cases = typesetters.cases or { }
+local cases = typesetters.cases
+
+cases.actions = { }
+local actions = cases.actions
+local a_cases = attributes.private("case")
+
+local extract = bit32.extract
+local run = 0 -- a trick to make neighbouring ranges work
+
+local blocked = { }
+
+local function set(tag,font)
+ if run == 2^6 then
+ run = 1
+ else
+ run = run + 1
+ end
+ local a = font * 0x10000 + tag * 0x100 + run
+ blocked[a] = false
+ return a
+end
+
+local function get(a)
+ local font = extract(a,16,12) -- 4000
+ local tag = extract(a, 8, 8) -- 250
+ local run = extract(a, 0, 8) -- 50
+ return tag, font, 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
+--
+-- we could do the whole glyph run here (till no more attributes match) but then we end up
+-- with more code .. maybe i will clean this up anyway as the lastfont hack is somewhat ugly
+-- ... on the other hand, we need to deal with cases like:
+--
+-- \WORD {far too \Word{many \WORD{more \word{pushed} in between} useless} words}
+
+local uccodes = characters.uccodes
+local lccodes = characters.lccodes
+local categories = characters.categories
+
+-- true false true == mixed
+
+local function replacer(start,codes)
+ local char = getchar(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
+ if not ifc[dc[i]] then
+ return start, false
+ end
+ end
+ for i=#dc,1,-1 do
+ local chr = dc[i]
+ if i == 1 then
+ setchar(start,chr)
+ else
+ local g = copy_node(start)
+ setchar(g,chr)
+ insert_after(start,start,g)
+ end
+ end
+ return start, true
+ elseif ifc[dc] then
+ setchar(start,dc)
+ return start, true
+ end
+ end
+ return start, false
+end
+
+local registered, n = { }, 0
+
+local function register(name,f)
+ if type(f) == "function" then
+ n = n + 1
+ actions[n] = f
+ registered[name] = n
+ return n
+ else
+ local n = registered[f]
+ registered[name] = n
+ return n
+ end
+end
+
+cases.register = register
+
+local function WORD(start,attr,lastfont,n,count,where,first)
+ lastfont[n] = false
+ return replacer(first or start,uccodes)
+end
+
+local function word(start,attr,lastfont,n,count,where,first)
+ lastfont[n] = false
+ return replacer(first or start,lccodes)
+end
+
+local function Words(start,attr,lastfont,n,count,where,first) -- looks quite complex
+ if where == "post" then
+ return
+ end
+ if count == 1 and where ~= "post" then
+ replacer(first or start,uccodes)
+ return start, true, true
+ else
+ return start, false, true
+ end
+end
+
+local function Word(start,attr,lastfont,n,count,where,first)
+ blocked[attr] = true
+ return Words(start,attr,lastfont,n,count,where,first)
+end
+
+local function camel(start,attr,lastfont,n,count,where,first)
+ 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
+end
+
+-- local function mixed(start,attr,lastfont,n,count,where,first)
+-- if where == "post" then
+-- return
+-- end
+-- local used = first or start
+-- local char = getchar(first)
+-- local dc = uccodes[char]
+-- if not dc then
+-- return start, false, true
+-- elseif dc == char then
+-- local lfa = lastfont[n]
+-- if lfa then
+-- setfield(first,"font",lfa)
+-- return start, true, true
+-- else
+-- return start, false, true
+-- end
+-- else
+-- replacer(first or start,uccodes)
+-- return start, true, true
+-- end
+-- end
+
+local function mixed(start,attr,lastfont,n,count,where,first)
+ if where == "post" then
+ return
+ end
+ local used = first or start
+ local char = getchar(used)
+ local dc = uccodes[char]
+ if not dc then
+ return start, false, true
+ elseif dc == char then
+ local lfa = lastfont[n]
+ if lfa then
+ setfield(used,"font",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
+ end
+ else
+ replacer(used,uccodes)
+ end
+ else
+ replacer(used,uccodes)
+ end
+ return start, true, true
+ end
+end
+
+local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3
+ local used = first or start
+ if count == 1 and where ~= "post" then
+ local lfa = lastfont[n]
+ if lfa then
+ local dc = uccodes[getchar(used)]
+ if dc then
+ setfield(used,"font",lfa)
+ end
+ end
+ end
+ local s, d, c = replacer(first or start,uccodes)
+ if once then
+ lastfont[n] = false -- here
+ end
+ return start, d, c
+end
+
+local function capital(start,attr,lastfont,n,where,count,first,count) -- 4
+ return Capital(start,attr,lastfont,n,where,count,first,true)
+end
+
+local function none(start,attr,lastfont,n,count,where,first)
+ return start, false, true
+end
+
+local function random(start,attr,lastfont,n,count,where,first)
+ local used = first or start
+ local char = getchar(used)
+ local font = getfont(used)
+ local tfm = fontchar[font]
+ lastfont[n] = false
+ local kind = categories[char]
+ if kind == "lu" then
+ while true do
+ local n = randomnumber(0x41,0x5A)
+ if tfm[n] then -- this also intercepts tables
+ setchar(used,n)
+ return start, true
+ end
+ end
+ elseif kind == "ll" then
+ while true do
+ local n = randomnumber(0x61,0x7A)
+ if tfm[n] then -- this also intercepts tables
+ setchar(used,n)
+ return start, true
+ end
+ end
+ end
+ return start, false
+end
+
+register(variables.WORD, WORD) -- 1
+register(variables.word, word) -- 2
+register(variables.Word, Word) -- 3
+register(variables.Words, Words) -- 4
+register(variables.capital,capital) -- 5
+register(variables.Capital,Capital) -- 6
+register(variables.none, none) -- 7 (dummy)
+register(variables.random, random) -- 8
+register(variables.mixed, mixed) -- 9
+register(variables.camel, camel) -- 10
+
+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 lastfont = { }
+ local lastattr = nil
+ local done = false
+ local start = tonut(head)
+ local count = 0
+ local previd = nil
+ local prev = nil
+ while start do -- while because start can jump ahead
+ local id = getid(start)
+ if id == glyph_code then
+ local attr = getattr(start,a_cases)
+ if attr and attr > 0 and not blocked[attr] then
+ if attr ~= lastattr then
+ lastattr = attr
+ count = 1
+ else
+ count = count + 1
+ end
+ setattr(start,a_cases,unsetvalue)
+ local n, id, m = get(attr)
+ if lastfont[n] == nil then
+ lastfont[n] = id
+ end
+ local action = actions[n] -- map back to low number
+ if action then
+ start, ok = action(start,attr,lastfont,n,count)
+ if ok then
+ done = true
+ end
+ if trace_casing then
+ report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok)
+ end
+ elseif trace_casing then
+ report_casing("unknown case trigger %a",n)
+ end
+ end
+ elseif id == disc_code then
+ local attr = getattr(start,a_cases)
+ if attr and attr > 0 and not blocked[attr] then
+ if attr ~= lastattr then
+ lastattr = attr
+ count = 0
+ end
+ setattr(start,a_cases,unsetvalue)
+ local n, id, m = get(attr)
+ if lastfont[n] == nil then
+ lastfont[n] = id
+ end
+ local action = actions[n] -- map back to low number
+ if action then
+ local pre, post, replace = getdisc(start)
+ if replace then
+ local cnt = count
+ for g in traverse_id(glyph_code,replace) do
+ cnt = cnt + 1
+ -- setattr(g,a_cases,unsetvalue)
+ local _, _, 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
+ cnt = cnt + 1
+ -- setattr(g,a_cases,unsetvalue)
+ local _, _, 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
+ cnt = cnt + 1
+ -- setattr(g,a_cases,unsetvalue)
+ local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g)
+ if quit then break end
+ end
+ end
+ end
+ count = count + 1
+ end
+ elseif id == math_code then
+ start = end_of_math(start)
+ count = 0
+ elseif prev_id == kern_code and getsubtype(prev) == kerning_code then
+ -- still inside a word ...nomally kerns are added later
+ else
+ count = 0
+ end
+ if start then
+ prev = start
+ previd = id
+ start = getnext(start)
+ end
+ end
+ return head, done
+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
+-- 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
+-- end
+-- end
+-- return head, done
+-- end
+
+local enabled = false
+
+function cases.set(n,id)
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = registered[n] or tonumber(n)
+ if n then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.cases.handler")
+ if trace_casing then
+ report_casing("enabling case handler")
+ end
+ enabled = true
+ end
+ n = set(n,id)
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_cases,n)
+ -- return n -- bonus
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setcharactercasing",
+ actions = cases.set,
+ arguments = { "string", "integer" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv
new file mode 100644
index 00000000000..114532e4e47
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv
@@ -0,0 +1,292 @@
+%D \module
+%D [ file=typo-cap,
+%D version=2009.03.27, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Capping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Caps}
+
+\unprotect
+
+%D Maybe we need a more clever system: either command or style mode etc. so
+%D that we can avoid the grouped mess in a simple style switch.
+
+\registerctxluafile{typo-cap}{1.001}
+
+\definesystemattribute[case][public]
+
+%D \macros
+%D {setupcapitals}
+%D
+%D By default we use pseudo small caps in titles. This can be
+%D set up with:
+%D
+%D \showsetup{setupcapitals}
+
+\installcorenamespace{capitals}
+
+\installcommandhandler \??capitals {capitals} \??capitals
+
+%D Beware, these are not really defines (yet).
+
+\definecapitals[\v!WORD] % all upper
+\definecapitals[\v!capital] % one upper + font
+\definecapitals[\v!Capital] % some upper + font
+\definecapitals[\v!mixed] % UpperCase
+\definecapitals[\v!WORD] % all lower
+\definecapitals[\v!Word] % one upper + font
+\definecapitals[\v!Words] % some upper
+\definecapitals[\v!camel] % lowers first
+\definecapitals[\v!word][\c!style=] % nothing
+
+%D \macros
+%D {Word, Words, WORD, WORDS}
+%D
+%D This is probably not the right place to present the next set
+%D of macros.
+%D
+%D \starttyping
+%D \Word {far too many words}
+%D \Words{far too many words}
+%D \WORD {far too many words}
+%D \WORDS{far too many words}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D This calls result in:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D \showsetup{Word}
+%D \showsetup{Words}
+%D \showsetup{WORD}
+%D \showsetup{WORDS}
+
+% test \WORD{test TEST \TeX} test
+% test \word{test TEST \TeX} test
+% test \Word{test TEST \TeX} test
+
+\unexpanded\def\setcharactercasing[#1]%
+ {\clf_setcharactercasing{#1}\fontid\font}
+
+% 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)
+
+\let\WORDS\WORD
+\let\words\word
+
+%D \macros
+%D {kap,KAP,Kap,Kaps,nokap,userealcaps,usepseudocaps}
+%D
+%D We already introduced \type{\cap} as way to capitalize
+%D words. This command comes in several versions:
+%D
+%D \startbuffer
+%D \cap {let's put on a \cap{cap}}
+%D \cap {let's put on a \nocap{cap}}
+%D \CAP {let's put on a \\{cap}}
+%D \Cap {let's put on a \\{cap}}
+%D \Caps{let's put on a cap}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Note the use of \type{\nocap}, \type{\\} and the nested
+%D \type{\cap}.
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D These macros show te main reason why we introduced the
+%D smaller \type{\tx} and \type{\txx}.
+%D
+%D \starttyping
+%D \cap\romannumerals{1995}
+%D \stoptyping
+%D
+%D This at first sight unusual capitilization is completely
+%D legal.
+%D
+%D \showsetup{smallcapped}
+%D \showsetup{notsmallcapped}
+%D \showsetup{CAPPED}
+%D \showsetup{SmallCapped}
+%D \showsetup{SmallCaps}
+%D
+%D The difference between pseudo and real caps is demonstrated
+%D below:
+%D
+%D \startbuffer
+%D \usepseudocaps \cap{Hans Hagen}
+%D \userealcaps \cap{Hans Hagen}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D The \type {\bgroup} trickery below is needed because of
+%D \type {\groupedcommand}.
+
+\let\disablepseudocaps\relax % maybe used elsewhere
+
+\newconditional\c_typo_capitals_pseudo
+
+\unexpanded\def\usepseudocaps{\settrue \c_typo_capitals_pseudo}
+\unexpanded\def\userealcaps {\setfalse\c_typo_capitals_pseudo}
+
+\usepseudocaps
+
+% we use char0 as placeholder for the larger font
+%
+% here we keep the \groupedcommand
+
+\def\typo_capitals_set_fake#1%
+ {\edef\currentcapitals{#1}%
+ \clf_setcharactercasing{\currentcapitals}\fontid\font
+ \usecapitalsstyleparameter\c!style}
+
+\def\typo_capitals_set_real#1%
+ {\edef\currentcapitals{#1}%
+ \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\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\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
+\unexpanded\def\font_style_pseudoSmallCapped{\typo_capitals_set_fake\v!Capital} % some upper + font
+\unexpanded\def\font_style_pseudoMixedCapped{\typo_capitals_set_fake\v!mixed }
+
+\unexpanded\def\font_style_realsmallcapped {\typo_capitals_set_real\v!WORD } % all lower
+\unexpanded\def\font_style_realSmallcapped {\typo_capitals_set_real\v!Word } % one upper + font
+\unexpanded\def\font_style_realSmallCapped {\typo_capitals_set_real\v!Words } % some upper
+
+\unexpanded\def\font_style_notsmallcapped {\typo_capitals_set_fake\v!word }
+
+\unexpanded\def\typo_capitals_smallcaps
+ {\ifconditional\c_typo_capitals_pseudo
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\smallcapped{\typo_capitals_smallcaps\pseudosmallcapped\realsmallcapped}
+\unexpanded\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped}
+\unexpanded\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped}
+
+\unexpanded\def\font_style_smallcapped{\typo_capitals_smallcaps\font_style_pseudosmallcapped\font_style_realsmallcapped}
+\unexpanded\def\font_style_Smallcapped{\typo_capitals_smallcaps\font_style_pseudoSmallcapped\font_style_realSmallcapped}
+\unexpanded\def\font_style_SmallCapped{\typo_capitals_smallcaps\font_style_pseudoSmallCapped\font_style_realSmallCapped}
+
+\unexpanded\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi}
+
+\appendtoks
+ \let\normalcap\cap % mathmode cap
+ \let\cap\autocap
+\to \everydump
+
+\let\kap\cap % for old times sake
+\let\Caps\SmallCapped % for old times sake
+
+\let\mixedcaps\pseudoMixedCapped
+
+\let\normalsmallcapped\smallcapped
+\let\normalWORD \WORD
+\let\normalword \word
+
+\let\font_style_normalsmallcapped\font_style_smallcapped
+\let\font_style_normalWORD \WORD
+\let\font_style_normalword \word
+
+%D Further tweaks
+
+\let\normalsmallcapped\smallcapped
+
+\appendtoks
+ \ifx\currentcapitals\empty
+ \doifelse{\directcapitalsparameter\c!title}\v!yes
+ {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalsmallcapped]%
+ \definealternativestyle[\v!smallcaps][\setsmallcaps][\setsmallcaps]}
+ {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalWORD]%
+ \definealternativestyle[\v!smallcaps][\setsmallcaps][\font_style_normalWORD]}%
+ \doifelse{\directcapitalsparameter\s!sc}\v!yes
+ \userealcaps
+ \usepseudocaps
+ \fi
+\to \everysetupcapitals
+
+\let\uppercased\normalWORD
+\let\lowercased\normalword
+
+\setupcapitals
+ [\c!title=\v!yes,
+ \c!style=\tx,
+ \s!sc=\v!no] % no \c!sc any longer
+
+% \definefont
+% [MixedCaps]
+% [\v_font_string_a\v_font_string_c*default cp \the\exheight]
+%
+% \definefont
+% [MixedCaps]
+% [MixedCaps*default cp \the\exheight]
+
+% \definefontfeature
+% [mixeddefault]
+% [default]
+% [extend=1.2]
+
+\definefont
+ [MixedCaps]
+ [CurrentFont*default cp 1.2\exheight]
+
+\setupcapitals
+ [\v!mixed]
+ [\c!style=MixedCaps]
+
+% \definestartstop is not yet in available at core-spa time
+%
+% \startrandomized \input tufte \stoprandomized
+%
+% \definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
+
+\unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}}
+
+\definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua
new file mode 100644
index 00000000000..041a73e1b23
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua
@@ -0,0 +1,251 @@
+if not modules then modules = { } end modules ['typo-chr'] = {
+ version = 1.001,
+ comment = "companion to typo-bld.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- local nodecodes = nodes.nodecodes
+-- local whatsitcodes = nodes.whatsitcodes
+-- local glyph_code = nodecodes.glyph
+-- local whatsit_code = nodecodes.whatsit
+-- local user_code = whatsitcodes.userdefined
+--
+-- local stringusernode = nodes.pool.userstring
+--
+-- local nuts = nodes.nuts
+-- local pool = nuts.pool
+--
+-- 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 remove_node = nuts.remove
+-- local traverse_by_id = nuts.traverse_id
+--
+-- 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
+-- end
+-- end
+-- return head
+-- end
+-- }
+--
+-- -- we can also use properties .. todo (saves pass)
+--
+-- 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")]
+-- if action then
+-- h = action(h,n)
+-- end
+-- h = remove_node(h,n,true)
+-- done = true
+-- end
+-- end
+-- if done then
+-- return tonode(h), true
+-- else
+-- return head
+-- end
+-- end
+--
+-- local enabled = false
+--
+-- local function signal(what)
+-- if not enabled then
+-- nodes.tasks.prependaction("processors","normalizers", "typesetters.signals.handler")
+-- enabled = true
+-- end
+-- context(stringusernode(signal,what))
+-- end
+--
+-- interfaces.implement {
+-- name = "signal",
+-- actions = signal,
+-- arguments = "string",
+-- }
+
+local insert, remove = table.insert, table.remove
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local whatsit_code = nodecodes.whatsit
+local localpar_code = nodecodes.localpar
+
+local texnest = tex.nest
+local free_node = node.free
+local flush_list = node.flush_list
+
+local settexattribute = tex.setattribute
+local punctuation = characters.is_punctuation
+
+local variables = interfaces.variables
+local v_all = variables.all
+local v_reset = variables.reset
+
+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]
+ if list then
+ local tail = list.tail
+ if tail and tail.id == glyph_code and punctuation[tail.char] then
+ local prev = tail.prev
+ list.tail = prev
+ if prev then
+ prev.next = nil
+ end
+ list.tail = prev
+ tail.prev = nil
+ return tail
+ end
+ end
+end
+
+local actions = {
+ remove = function(specification)
+ local n = pickup()
+ if n then
+ free_node(n)
+ end
+ end,
+ push = function(specification)
+ local n = pickup()
+ if n then
+ insert(stack,n or false)
+ end
+ end,
+ pop = function(specification)
+ local n = remove(stack)
+ if n then
+ context(n)
+ end
+ end,
+}
+
+local function pickuppunctuation(specification)
+ local action = actions[specification.action or "remove"]
+ if action then
+ action(specification)
+ end
+end
+
+-- I played with nested marked content but it makes no sense and gives
+-- complex code. Also, it's never needed so why bother.
+
+local function pickup(head,tail,str)
+ local attr = marked[str]
+ local last = tail
+ if last[a_marked] == attr then
+ local first = last
+ while true do
+ local prev = first.prev
+ if prev and prev[a_marked] == attr then
+ local id = prev.id
+ if id == localpar_code then
+ break
+ else
+ first = prev
+ end
+ else
+ break
+ end
+ end
+ return first, last
+ end
+end
+
+local actions = {
+ remove = function(specification)
+ local list = texnest[texnest.ptr]
+ if list then
+ local head = list.head
+ local tail = list.tail
+ local first, last = pickup(head,tail,specification.mark)
+ if first then
+ if first == head then
+ list.head = nil
+ list.tail = nil
+ else
+ local prev = first.prev
+ list.tail = prev
+ prev.next = nil
+ end
+ flush_list(first)
+ end
+ end
+ end,
+}
+
+local function pickupmarkedcontent(specification)
+ local action = actions[specification.action or "remove"]
+ if action then
+ action(specification)
+ end
+end
+
+local function markcontent(str)
+ local currentmarked = marked[str or v_all]
+ if not currentmarked then
+ lastmarked = lastmarked + 1
+ currentmarked = lastmarked
+ marked[str] = currentmarked
+ end
+ settexattribute(a_marked,currentmarked)
+end
+
+interfaces.implement {
+ name = "pickuppunctuation",
+ actions = pickuppunctuation,
+ arguments = {
+ {
+ { "action" }
+ }
+ }
+}
+
+interfaces.implement {
+ name = "pickupmarkedcontent",
+ actions = pickupmarkedcontent,
+ arguments = {
+ {
+ { "action" },
+ { "mark" }
+ }
+ }
+}
+
+interfaces.implement {
+ name = "markcontent",
+ actions = markcontent,
+ arguments = "string",
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv
new file mode 100644
index 00000000000..dc0c6866408
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv
@@ -0,0 +1,82 @@
+
+%D \module
+%D [ file=typo-chr,
+%D version=2015.01.01, % or about that time
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Cleaning Up Mess,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Characters}
+
+\unprotect
+
+%D This is a very experimental feature, mostly for Alan and me to play with in
+%D publication hell.
+%D
+%D \startbuffer
+%D before, after\par
+%D before,\removepunctuation after\par
+%D before\markcontent[gone]{\darkred gone}\removemarkedcontent[gone]after\par
+%D before\markcontent[kept]{\darkgreen kept}\removemarkedcontent[gone]after\par
+%D \markcontent[gone]{\darkred gone}\removemarkedcontent[gone]after\par
+%D \markcontent[kept]{\darkgreen kept}\removemarkedcontent[gone]after\par
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer\blank
+%D
+%D This feature is paragraph based and is only to be used for small snippets of text,
+%D for instance when combining bit and pieces where keeping a state is complex compared
+%D to cleaning up unwanted stuff.
+
+\registerctxluafile{typo-chr}{1.001}
+
+\definesystemattribute[marked][public]
+
+\unexpanded\def\removepunctuation
+ {\clf_pickuppunctuation action{remove}\relax} % the first experiment
+
+\unexpanded\def\pushpunctuation
+ {\clf_pickuppunctuation action{push}\relax} % the first experiment
+
+\unexpanded\def\poppunctuation
+ {\clf_pickuppunctuation action{pop}\relax} % the first experiment
+
+\unexpanded\def\markcontent
+ {\dosingleempty\typo_marked_mark}
+
+\def\typo_marked_mark[#1]#2%
+ {\dontleavehmode
+ \bgroup
+ \clf_markcontent{#1}%
+ \bgroup
+ #2% double grouping makes aftergroups work ok
+ \egroup
+ \egroup}
+
+\unexpanded\def\startmarkedcontent
+ {\dontleavehmode
+ \bgroup
+ \dosingleempty\typo_marked_start}
+
+\def\typo_marked_start[#1]%
+ {\clf_markcontent{#1}%
+ % double grouping makes aftergroups work ok
+ \bgroup}
+
+\unexpanded\def\stopmarkedcontent
+ {\egroup
+ \egroup}
+
+\unexpanded\def\removemarkedcontent
+ {\dosingleempty\typo_marked_remove}
+
+\def\typo_marked_remove[#1]%
+ {\clf_pickupmarkedcontent action{remove}mark{#1}\relax}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua
new file mode 100644
index 00000000000..bc11f944c94
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua
@@ -0,0 +1,110 @@
+if not modules then modules = { } end modules ['typo-cln'] = {
+ version = 1.001,
+ comment = "companion to typo-cln.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This quick and dirty hack took less time than listening to a CD (In
+-- this case Dream Theaters' Octavium). Of course extensions will take
+-- more time.
+
+local utfbyte = utf.byte
+
+local trace_cleaners = false trackers.register("typesetters.cleaners", function(v) trace_cleaners = v end)
+local trace_autocase = false trackers.register("typesetters.cleaners.autocase",function(v) trace_autocase = v end)
+
+local report_cleaners = logs.reporter("nodes","cleaners")
+local report_autocase = logs.reporter("nodes","autocase")
+
+typesetters.cleaners = typesetters.cleaners or { }
+local cleaners = typesetters.cleaners
+
+local variables = interfaces.variables
+
+local nodecodes = nodes.nodecodes
+local tasks = nodes.tasks
+
+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 setfield = nuts.setfield
+local setchar = nuts.setchar
+
+local traverse_id = nuts.traverse_id
+
+local unsetvalue = attributes.unsetvalue
+
+local glyph_code = nodecodes.glyph
+local uccodes = characters.uccodes
+
+local a_cleaner = attributes.private("cleaner")
+
+local resetter = { -- this will become an entry in char-def
+ [utfbyte(".")] = true
+}
+
+-- Contrary to the casing code we need to keep track of a state.
+-- We could extend the casing code with a status tracker but on
+-- the other hand we might want to apply casing afterwards. So,
+-- 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)
+ if resetter[char] then
+ inline = false
+ elseif not inline then
+ local a = getattr(n,a_cleaner)
+ if a == 1 then -- currently only one cleaner so no need to be fancy
+ local upper = uccodes[char]
+ if type(upper) == "table" then
+ -- some day, not much change that \SS ends up here
+ else
+ setchar(n,upper)
+ done = true
+ if trace_autocase then
+ report_autocase("")
+ end
+ end
+ end
+ inline = true
+ end
+ end
+ return head, done
+end
+
+-- see typo-cap for a more advanced settings handler .. not needed now
+
+local enabled = false
+
+function cleaners.set(n)
+ if n == variables.reset or not tonumber(n) or n == 0 then
+ texsetattribute(a_cleaner,unsetvalue)
+ else
+ if not enabled then
+ tasks.enableaction("processors","typesetters.cleaners.handler")
+ if trace_cleaners then
+ report_cleaners("enabling cleaners")
+ end
+ enabled = true
+ end
+ texsetattribute(a_cleaner,tonumber(n))
+ end
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setcharactercleaning",
+ actions = cleaners.set,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.mkiv
new file mode 100644
index 00000000000..193198dc556
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.mkiv
@@ -0,0 +1,33 @@
+%D \module
+%D [ file=typo-cln,
+%D version=2011.02.11,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Cleaning,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Cleaning}
+
+\unprotect
+
+\registerctxluafile{typo-cln}{1.001}
+
+\definesystemattribute[cleaner][public]
+
+%D Currently there is no interface.
+%D
+%D 1: Autocap first character of a line
+
+\unexpanded\def\setcharactercleaning[#1]% This name might change!
+ {\clf_setcharactercleaning{#1}} % also accepts "reset"
+
+% \appendtoks
+% \attribute\cleanerattribute\attributeunsetvalue
+% \to \everyforgetall
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv
new file mode 100644
index 00000000000..eb51a06e107
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv
@@ -0,0 +1,778 @@
+%D \module
+%D [ file=typo-del, % moved from core-mis,
+%D version=20110112,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Delimited Content,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% todo: textstyle|color for inline \quotation etc
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Delimited Content}
+
+\unprotect
+
+\ifdefined\dotagsetdelimitedsymbol \else \let\dotagsetdelimitedsymbol \gobbleoneargument \fi
+\ifdefined\dotagsetsubsentencesymbol \else \let\dotagsetsubsentencesymbol\gobbleoneargument \fi
+
+% THIS IS OBSOLETE:
+
+\installcorenamespace{hyphenmarksign} % let's not waste a setuphandler (yet)
+
+\unexpanded\def\setuphyphenmark[#1]% sign=normal|wide
+ {\getdummyparameters[#1]%
+ \expandnamespaceparameter\??hyphenmarksign\dummyparameter\c!sign\v!normal}
+
+\setvalue{\??hyphenmarksign\v!normal}%
+ {\let\textmodehyphen\normalhyphen
+ \let\textmodehyphendiscretionary\normalhyphendiscretionary}
+
+\setvalue{\??hyphenmarksign\v!wide}%
+ {\let\textmodehyphen\composedhyphen
+ \let\textmodehyphendiscretionary\composedhyphendiscretionary}
+
+\setuphyphenmark[\c!sign=\v!wide]
+
+\definesymbol[\c!lefthyphen] [\languageparameter\c!lefthyphen]
+\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
+\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
+
+\unexpanded\def\normalhyphen
+ {\hbox{\directsymbol\empty\c!hyphen}}
+
+\unexpanded\def\composedhyphen
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}
+
+\unexpanded\def\normalhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!righthyphen}}
+ {\hbox{\directsymbol\empty\c!lefthyphen}}
+ {\hbox{\directsymbol\empty\c!hyphen}}}
+
+\unexpanded\def\composedhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}}
+
+\let\textmodehyphen \composedhyphen
+\let\textmodehyphendiscretionary\composedhyphendiscretionary
+
+\definesymbol[\c!leftcompoundhyphen] [\languageparameter\c!leftcompoundhyphen]
+\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
+\definesymbol[\c!compoundhyphen] [\languageparameter\c!compoundhyphen]
+
+% TILL HERE
+
+\setnewconstant\boundarycharactermode\plusone
+
+\unexpanded\def\midboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ %\nobreak
+ \hskip\hspaceamount\currentusedlanguage{#2}%
+ \usedlanguageparameter#1%
+ %\nobreak
+ \hskip\hspaceamount\currentusedlanguage{#2}%
+ \or
+ \usedlanguageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\unexpanded\def\leftboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \usedlanguageparameter#1%
+ \nobreak
+ \hskip\hspaceamount\currentusedlanguage{#2}%
+ \or
+ \usedlanguageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\unexpanded\def\rightboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \prewordbreak %\nobreak
+ \hskip\hspaceamount\currentusedlanguage{#2}%
+ \usedlanguageparameter#1%
+ \or
+ \usedlanguageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\definehspace [sentence] [\zeropoint]
+\definehspace [intersentence] [.250\emwidth]
+
+\definesymbol
+ [\c!midsentence]
+ [\midboundarycharacter\c!midsentence{sentence}]
+
+\definesymbol
+ [\c!leftsentence]
+ [\leftboundarycharacter\c!leftsentence{sentence}]
+
+\definesymbol
+ [\c!rightsentence]
+ [\rightboundarycharacter\c!rightsentence{sentence}]
+
+\definesymbol
+ [\c!leftsubsentence]
+ [\leftboundarycharacter\c!leftsubsentence{sentence}]
+
+\definesymbol
+ [\c!rightsubsentence]
+ [\rightboundarycharacter\c!rightsubsentence{sentence}]
+
+\newsignal \d_typo_subsentence_signal
+\newcount \c_typo_subsentence_nesting
+
+\let\beforesubsentence\donothing
+\let\aftersubsentence \donothing
+
+% todo: make this language option
+%
+% \def\beforesubsentence{\removeunwantedspaces}
+% \def\aftersubsentence {\ignorespaces}
+
+\unexpanded\def\midsentence
+ {\dostarttagged\t!subsentencesymbol\empty
+ \dotagsetsubsentencesymbol\s!middle
+ \symbol[\c!midsentence]%
+ \dostoptagged}
+
+\unexpanded\def\beginofsubsentence
+ {\beforesubsentence
+ \ifdim\lastkern=\d_typo_subsentence_signal
+ \unskip
+ \kern\hspaceamount\currentusedlanguage{intersentence}%
+ \fi
+ \global\advance\c_typo_subsentence_nesting\plusone
+ \ifnum\c_typo_subsentence_nesting=\plusone
+ \dontleavehmode % was \leaveoutervmode
+ \fi
+ \dostarttagged\t!subsentence\empty % no chain
+ \dostarttagged\t!subsentencesymbol\empty
+ \dotagsetsubsentencesymbol\s!left
+ \symbol[\ifodd\c_typo_subsentence_nesting\c!leftsentence\else\c!leftsubsentence\fi]%
+ \dostoptagged
+ \dostarttagged\t!subsentencecontent\empty
+ }% \ignorespaces}
+
+\unexpanded\def\endofsubsentence % relax prevents space gobbling
+ {\dostoptagged
+ \dostarttagged\t!subsentencesymbol\empty
+ \dotagsetsubsentencesymbol\s!right
+ \symbol[\ifodd\c_typo_subsentence_nesting\c!rightsentence\else\c!rightsubsentence\fi]%
+ \dostoptagged
+ \dostoptagged
+ \global\advance\c_typo_subsentence_nesting\minusone
+ \unskip
+ \kern\d_typo_subsentence_signal\relax
+ \aftersubsentence}
+
+\unexpanded\def\beginofsubsentencespacing % relax prevents space gobbling
+ {\kern\d_typo_subsentence_signal\relax}% \ignorespaces}
+
+\unexpanded\def\endofsubsentencespacing
+ {\ifdim\lastkern=\d_typo_subsentence_signal
+ \unskip
+ \hskip\hspaceamount\currentusedlanguage{intersentence}%
+ % no good, actually language dependent:
+% \ignorespaces
+ \else
+ \unskip
+ \fi}
+
+%D \startbuffer
+%D test |<|test |<|test|>| test|>| test \par
+%D test|<|test|<|test|>|test|>|test \par
+%D test |<||<|test|>||>| test \par
+%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\unexpanded\def\startsubsentence{\beginofsubsentence \prewordbreak\beginofsubsentencespacing}
+\unexpanded\def\stopsubsentence {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+\unexpanded\def\subsentence {\groupedcommand\startsubsentence\stopsubsentence}
+
+\definehspace [quotation] [\zeropoint]
+\definehspace [interquotation] [.125em]
+
+%definehspace [quote] [\zeropoint]
+%definehspace [speech] [\zeropoint]
+
+\definehspace [quote] [\hspaceamount\currentusedlanguage{quotation}]
+\definehspace [speech] [\hspaceamount\currentusedlanguage{quotation}]
+
+\definesymbol
+ [\c!leftquotation]
+ [\leftboundarycharacter\c!leftquotation{quotation}]
+
+\definesymbol
+ [\c!rightquotation]
+ [\rightboundarycharacter\c!rightquotation{quotation}]
+
+\definesymbol
+ [\c!nextleftquotation]
+ [\rightboundarycharacter\c!leftquotation{quotation}]
+
+\definesymbol
+ [\c!nextrightquotation]
+ [\leftboundarycharacter\c!rightquotation{quotation}]
+
+\definesymbol
+ [\c!leftquote]
+ [\leftboundarycharacter\c!leftquote{quote}]
+
+\definesymbol
+ [\c!rightquote]
+ [\rightboundarycharacter\c!rightquote{quote}]
+
+\definesymbol
+ [\c!leftspeech]
+ [\leftboundarycharacter\c!leftspeech{speech}]
+
+\definesymbol
+ [\c!rightspeech]
+ [\rightboundarycharacter\c!rightspeech{speech}]
+
+\definesymbol
+ [\c!middlespeech]
+ [\leftboundarycharacter\c!middlespeech{speech}]
+
+\appendtoks
+ \def\quotation#1{"#1"}%
+ \def\quote #1{'#1'}%
+\to \everysimplifycommands
+
+%D The next features was so desperately needed by Giuseppe Bilotta that he made a
+%D module for it. Since this is a typical example of core functionality, I decided
+%D to extend the low level quotation macros in such a way that a speech feature
+%D could be build on top of it. The speech opening and closing symbols are defined
+%D per language. Italian is an example of a language that has them set.
+
+\newsignal\d_typo_delimited_signal
+
+\let\currentdelimitedtext\s!unknown
+
+\let\delimitedtextlevel\!!zerocount
+
+\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname}
+
+\def\typo_delimited_push#1%
+ {\globalpushmacro\currentdelimitedtext
+ \def\currentdelimitedtext{#1}%
+ \setlanguageparameter\delimitedtextparameter
+ \let\currentparentdelimitedtext\currentdelimitedtext
+ \global\advance\c_typo_delimited_nesting\plusone
+ \edef\delimitedtextlevel{\number\c_typo_delimited_nesting}%
+ \normalexpanded{\chaintocurrentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}%
+ \edef\currentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}
+
+\def\typo_delimited_pop
+ {\global\advance\c_typo_delimited_nesting\minusone
+ \globalpopmacro\currentdelimitedtext}
+
+\installcorenamespace{delimitedtext}
+\installcorenamespace{delimitedtextlevel}
+
+\installcommandhandler \??delimitedtext {delimitedtext} \??delimitedtext
+
+\appendtoks
+ \expandafter\newcount\csname\??delimitedtextlevel\currentdelimitedtext\endcsname
+ \setuevalue{\currentdelimitedtext }{\delimitedtext[\currentdelimitedtext]}%
+ \setuevalue{\e!start\currentdelimitedtext}{\startdelimitedtext[\currentdelimitedtext]}%
+ \setuevalue{\e!stop \currentdelimitedtext}{\stopdelimitedtext}%
+\to \everydefinedelimitedtext
+
+\setupdelimitedtext
+ [\c!location=\v!margin, % \v!text \v!paragraph
+ \c!spacebefore=,
+ \c!spaceafter=\delimitedtextparameter\c!spacebefore,
+ \c!style=,
+ \c!color=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\delimitedtextparameter\c!leftmargin,
+ \c!indentnext=\v!yes,
+ \c!before=,
+ \c!after=,
+ \c!left=,
+ \c!right=,
+ %\c!level=0,
+ \c!method=,
+ \c!repeat=\v!no]
+
+\def\typo_delimited_repeat_ideed
+ {\relax\ifcase\delimitedtextlevel\else
+ \typo_delimited_handle_middle\c!middle
+ \fi}
+
+\let\typo_delimited_repeat\relax
+
+\unexpanded\def\startdelimitedtext[#1]%
+ {\begingroup
+ \typo_delimited_push{#1}%
+ \dostarttaggedchained\t!delimitedblock\currentdelimitedtext\??delimitedtext
+ \edef\p_delimited_method{\delimitedtextparameter\c!method}%
+ \ifx\p_delimited_method\s!font
+ \expandafter\typo_delimited_start_font
+ \else
+ \expandafter\typo_delimited_start_other
+ \fi}
+
+\let\typo_delimited_stop\relax % hooks into \everypar
+
+\def\typo_delimited_start_font
+ {\let\typo_delimited_stop\typo_delimitedtexts_finish_font
+ \dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!left
+ \delimitedtextparameter\c!left
+ \dostoptagged
+ \ignorespaces}
+
+\def\typo_delimited_start_other
+ {\edef\p_delimited_repeat{\delimitedtextparameter\c!repeat}%
+ \ifx\p_delimited_repeat\v!yes
+ \let\typo_delimited_repeat\typo_delimited_repeat_indeed
+ \else
+ \let\typo_delimited_repeat\relax
+ \fi
+ \edef\p_delimited_location{\delimitedtextparameter\c!location}%
+ \ifx\p_delimited_location\v!paragraph
+ \singleexpandafter\typo_delimited_start_par
+ \else\ifx\p_delimited_location\v!margin
+ \doubleexpandafter\typo_delimited_start_par
+ \else
+ \doubleexpandafter\typo_delimited_start_txt
+ \fi\fi}
+
+\def\typo_delimitedtexts_finish_font
+ {\removeunwantedspaces
+ \dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!right
+ \delimitedtextparameter\c!right
+ \dostoptagged}
+
+\def\typo_delimited_start_par
+ {\dosingleempty\typo_delimited_start_par_indeed}
+
+\let\typo_delimited_stop_par_indeed\endgraf
+
+\def\typo_delimited_start_par_indeed[#1]%
+ {\let\typo_delimited_stop\typo_delimited_stop_par
+ \edef\p_delimited_spacebefore{\delimitedtextparameter\c!spacebefore}%
+ \ifx\p_delimited_spacebefore\empty \else
+ \blank[\p_delimited_spacebefore]%
+ \fi
+ \delimitedtextparameter\c!before
+ \edef\m_typo_delimited_narrower{#1}%
+ \ifx\m_typo_delimited_narrower\empty
+ \endgraf
+ \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ \let\typo_delimited_stop_par_indeed\endgraf
+ \else % backward compatible direct directive
+ \startnarrower[#1]%
+ \let\typo_delimited_stop_par_indeed\stopnarrower
+ \fi
+ % so far
+ \pushmacro\checkindentation
+ \useindentingparameter\delimitedtextparameter
+ %
+ \begingroup
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ %
+ \edef\p_delimited_left {\delimitedtextparameter{\c!left}}%
+ \edef\p_delimited_right {\delimitedtextparameter{\c!right}}%
+ \edef\p_delimited_nextleft {\delimitedtextparameter{\c!nextleft}}%
+ \edef\p_delimited_nextright{\delimitedtextparameter{\c!nextright}}%
+ %
+ \leftdelimitedtextmark
+ %
+ \setnextleftdelimitedtextmark
+ \setnextrightdelimitedtextmark
+ %
+ \ignorespaces
+ \dostarttagged\t!delimitedcontent\empty}
+
+\def\typo_delimited_stop_par
+ {\removeunwantedspaces
+ \removelastskip
+ \dostoptagged
+ \rightdelimitedtextmark
+ \carryoverpar\endgroup % new per 2013-01-21 ... please left floats
+ \popmacro\checkindentation
+ \typo_delimited_stop_par_indeed
+ \delimitedtextparameter\c!after
+ \edef\p_delimited_spaceafter{\delimitedtextparameter\c!spaceafter}%
+ \ifx\p_delimited_spaceafter\empty \else
+ \blank[\p_delimited_spaceafter]%
+ \fi
+ \useindentnextparameter\delimitedtextparameter
+ \aftergroup\dorechecknextindentation}% AM: This was missing!
+
+\def\typo_delimited_start_txt
+ {\let\typo_delimited_stop\typo_delimited_stop_txt
+ \begingroup
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \typo_delimited_handle_left\c!left
+ \ignorespaces
+ \dostarttagged\t!delimitedcontent\empty}
+
+\def\typo_delimited_stop_txt
+ {\removeunwantedspaces
+ \dostoptagged
+ \typo_delimited_handle_right\c!right
+ \endgroup}
+
+\unexpanded\def\stopdelimitedtext
+ {\typo_delimited_stop
+ \dostoptagged
+ \typo_delimited_pop
+ \endgroup}
+
+\unexpanded\def\delimitedtext[#1]%
+ {\dontleavehmode % following ones can be omited
+ \typo_delimited_push{#1}%
+ \edef\p_delimited_method{\delimitedtextparameter\c!method}%
+ \ifx\p_delimited_method\s!font
+ \expandafter\typo_delimited_fontdriven
+ \else
+ \expandafter\typo_delimited_other
+ \fi}
+
+\def\typo_delimited_other
+ {\edef\p_delimited_location{\delimitedtextparameter\c!location}%
+ \ifx\p_delimited_location\v!paragraph
+ \singleexpandafter\typo_delimited_par
+ \else\ifx\p_delimited_location\v!margin
+ \doubleexpandafter\typo_delimited_par
+ \else
+ \doubleexpandafter\typo_delimited_txt
+ \fi\fi}
+
+% shortcuts
+
+\unexpanded\def\startdelimited{\startdelimitedtext}
+\unexpanded\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned
+ \def\delimited {\delimitedtext}
+
+% todo: \dostarttagged\t!nothing\empty % for left/right boxes
+
+%D We have 4 different location and symbol handlers (two pairs):
+%D
+%D \starttyping
+%D \input tufte \startquotation \input tufte \stopquotation
+%D
+%D \setupdelimitedtext
+%D [quotation]
+%D [nextleft=right,
+%D nextright=left]
+%D
+%D \input tufte \startquotation \input tufte \stopquotation
+%D
+%D \setupdelimitedtext
+%D [quotation]
+%D [nextleft={\symbol[nextleftquotation]},
+%D nextright={\symbol[nextrightquotation]}]
+%D
+%D \input tufte \startquotation \input tufte \stopquotation
+%D \stoptyping
+
+\unexpanded\def\setnextleftdelimitedtextmark
+ {\ifx\p_delimited_nextleft\empty
+ % nothing
+ \else\ifx\p_delimited_nextleft\v!left
+ \typo_delimited_nextleft_symbol\p_delimited_left
+ \else\ifx\p_delimited_nextleft\v!right
+ \typo_delimited_nextleft_symbol\p_delimited_right
+ \else
+ \typo_delimited_nextleft_symbol\p_delimited_nextleft
+ \fi\fi\fi}
+
+\unexpanded\def\setnextrightdelimitedtextmark
+ {\ifx\p_delimited_nextright\empty
+ % nothing
+ \else\ifx\p_delimited_nextright\v!right
+ \typo_delimited_nextright_symbol\p_delimited_right
+ \else\ifx\p_delimited_nextright\v!left
+ \typo_delimited_nextright_symbol\p_delimited_left
+ \else
+ \typo_delimited_nextright_symbol\p_delimited_nextright
+ \fi\fi\fi}
+
+\unexpanded\def\leftdelimitedtextmark
+ {\ifx\p_delimited_left\empty
+ % nothing
+ \else
+ \typo_delimited_left_symbol\p_delimited_left
+ \fi}
+
+\unexpanded\def\rightdelimitedtextmark
+ {\ifx\p_delimited_right\empty
+ % nothing
+ \else
+ \typo_delimited_right_symbol\p_delimited_right
+ \fi}
+
+\def\typo_delimited_left_symbol#1%
+ {\dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!left
+ \setbox\scratchbox\hbox{\usedelimitedtextstyleandcolor\c!symstyle\c!symcolor#1}%
+ \dontleavehmode
+ \edef\p_delimited_margin{\delimitedtextparameter\c!location}%
+ \ifx\p_delimited_margin\v!margin
+ \hskip-\wd\scratchbox
+ \fi
+ \box\scratchbox
+ \dostoptagged}
+
+\def\typo_delimited_right_symbol#1%
+ {\dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!right
+ \hsmash{\usedelimitedtextstyleandcolor\c!symstyle\c!symcolor#1}%
+ \dostoptagged}
+
+\def\typo_delimited_nextleft_symbol#1%
+ {\localleftbox\bgroup
+ \swapmacros\leftboundarycharacter\rightboundarycharacter
+ \boundarycharactermode\plusone
+ \typo_delimited_left_symbol#1%
+ \egroup}
+
+\def\typo_delimited_nextright_symbol#1%
+ {\localrightbox\bgroup
+ \swapmacros\leftboundarycharacter\rightboundarycharacter
+ \boundarycharactermode\plusone
+ \typo_delimited_right_symbol#1%
+ \egroup}
+
+% \starttext
+% \hyphenatedword{groepsvrijstellingsverordeningen}\par
+% \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
+% \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
+% \page \setuppapersize[A5][A4]
+% \quotation {overly beautiful pusillanimous sesquipedalian
+% longwinded} test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test
+% \stoptext
+
+\def\typo_delimited_handle_middle#1%
+ {\dostoptagged
+ \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}%
+ \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
+ \dostarttagged\t!delimitedcontent\empty}
+
+\def\typo_delimited_handle_left#1%
+ {\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\ifdim\lastskip=\d_typo_delimited_signal
+ \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
+ \dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!left
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \dostoptagged
+ \penalty\plustenthousand % new per 2013-03-09 WS mailing list
+ \hskip\d_typo_delimited_signal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\typo_delimited_handle_right#1%
+ {\begingroup
+ \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\d_typo_delimited_signal
+ \unkern
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentusedlanguage{interquotation}%
+ \else\ifdim\lastskip=\d_typo_delimited_signal
+ \unskip
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentusedlanguage{interquotation}%
+ \fi\fi
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!right
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \dostoptagged
+ \kern\d_typo_delimited_signal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\unexpanded\def\typo_delimited_par
+ {\groupedcommand
+ {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext % block?
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \typo_delimited_handle_left\c!left
+ \dostarttagged\t!delimitedcontent\empty}
+ {\dostoptagged
+ \typo_delimited_handle_right\c!right
+ \removelastskip
+ \dostoptagged
+ \typo_delimited_pop}}
+
+\unexpanded\def\typo_delimited_txt
+ {\edef\p_left_right{\delimitedtextparameter\c!left\delimitedtextparameter\c!right}%
+ \ifx\p_left_right\empty
+ \expandafter\typo_delimited_attributed
+ \else
+ \expandafter\typo_delimited_quoted
+ \fi}
+
+\def\typo_delimited_quoted_b
+ {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext
+ \typo_delimited_handle_left\c!left
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \dostarttagged\t!delimitedcontent\empty}
+
+\def\typo_delimited_quoted_e
+ {\dostoptagged
+ \typo_delimited_handle_right\c!right
+ \removelastskip % ?
+ \dostoptagged
+ \typo_delimited_pop}
+
+\def\typo_delimited_attributed_b
+ {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \dostarttagged\t!delimitedcontent\empty
+ \ignorespaces}
+
+\def\typo_delimited_attributed_e
+ {\dostoptagged
+ \dostoptagged
+ \typo_delimited_pop}
+
+\def\typo_delimited_fontdriven_b
+ {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext
+ \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \dostarttagged\t!delimitedcontent\empty}
+
+\def\typo_delimited_fontdriven_e
+ {\dostoptagged
+ \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext
+ \dostoptagged
+ \typo_delimited_pop}
+
+% We now assume proper argument usage (so no longer grouped
+% command).
+
+% \def\typo_delimited_quoted {\groupedcommand \typo_delimited_quoted_b \typo_delimited_quoted_e }
+% \def\typo_delimited_attributed{\groupedcommand \typo_delimited_attributed_b\typo_delimited_attributed_e}
+% \def\typo_delimited_fontdriven{\simplegroupedcommand\typo_delimited_fontdriven_b\typo_delimited_fontdriven_e}
+
+\def\typo_delimited_quoted {\bgroup\typo_delimited_quoted_b \aftergroup\typo_delimited_quoted_e \let\next=}
+\def\typo_delimited_attributed{\bgroup\typo_delimited_attributed_b\aftergroup\typo_delimited_attributed_e\let\next=}
+\def\typo_delimited_fontdriven{\bgroup\typo_delimited_fontdriven_b\aftergroup\typo_delimited_fontdriven_e\let\next=}
+
+% testcase for nesting:
+%
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+% \setupdelimitedtext[quotation][1][left=(,right=)]
+% \setupdelimitedtext[quotation][2][left={[},right={]}]
+% \setupdelimitedtext[quotation][3][left=\{,right=\}]
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+
+\definedelimitedtext
+ [\v!quotation]
+ [\c!left={\symbol[\c!leftquotation]},
+ \c!right={\symbol[\c!rightquotation]},
+ \c!leftmargin=\v!standard]
+
+\definedelimitedtext
+ [\v!quote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!quote]
+ [\c!location=\v!text,
+ \c!left={\symbol[\c!leftquote]},
+ \c!right={\symbol[\c!rightquote]}]
+
+\definedelimitedtext
+ [\v!blockquote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!blockquote]
+ [\c!left=,
+ \c!right=]
+
+\definedelimitedtext
+ [\v!speech][\v!quotation]
+
+\setupdelimitedtext
+ [\v!speech]
+ [\c!repeat=\v!yes,
+ \c!left={\symbol[\c!leftspeech]},
+ \c!middle={\symbol[\c!middlespeech]},
+ \c!right={\symbol[\c!rightspeech]}]
+
+\definedelimitedtext
+ [\v!aside]
+ [\c!left={\symbol[\c!leftsentence]},
+ \c!right={\symbol[\c!rightsentence]}]
+
+% how do we call an tight quote
+%
+% \definedelimitedtext
+% [\v!quotation][\v!quotation]
+%
+% \setupdelimitedtext
+% [\v!quotation]
+% [\c!indentnext=\v!no,
+% \c!spacebefore=\v!nowhite]
+
+\unexpanded\def\setupquotation{\setupdelimitedtext[\v!quotation]}
+\unexpanded\def\setupquote {\setupdelimitedtext[\v!quote]}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua
new file mode 100644
index 00000000000..25e92bd2841
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua
@@ -0,0 +1,458 @@
+if not modules then modules = { } end modules ['typo-dha'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Some analysis by Idris:
+--
+-- 1. Assuming the reading- vs word-order distinction (bidi-char types) is governing;
+-- 2. Assuming that 'ARAB' represents an actual arabic string in raw input order, not word-order;
+-- 3. Assuming that 'BARA' represent the correct RL word order;
+--
+-- Then we have, with input: LATIN ARAB
+--
+-- \textdir TLT LATIN ARAB => LATIN BARA
+-- \textdir TRT LATIN ARAB => LATIN BARA
+-- \textdir TRT LRO LATIN ARAB => LATIN ARAB
+-- \textdir TLT LRO LATIN ARAB => LATIN ARAB
+-- \textdir TLT RLO LATIN ARAB => NITAL ARAB
+-- \textdir TRT RLO LATIN ARAB => NITAL ARAB
+
+-- elseif d == "es" then -- European Number Separator
+-- elseif d == "et" then -- European Number Terminator
+-- elseif d == "cs" then -- Common Number Separator
+-- elseif d == "nsm" then -- Non-Spacing Mark
+-- elseif d == "bn" then -- Boundary Neutral
+-- elseif d == "b" then -- Paragraph Separator
+-- elseif d == "s" then -- Segment Separator
+-- elseif d == "ws" then -- Whitespace
+-- elseif d == "on" then -- Other Neutrals
+
+-- todo : use new dir functions
+-- todo : make faster
+-- todo : move dir info into nodes
+-- todo : swappable tables and floats i.e. start-end overloads (probably loop in builders)
+
+-- I removed the original tracing code and now use the colorful one. If I ever want to change
+-- something I will just inject prints for tracing.
+
+local nodes, node = nodes, node
+
+local trace_directions = false trackers.register("typesetters.directions.default", 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 nutstring = nuts.tostring
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getchar = nuts.getchar
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local getprop = nuts.getprop
+local isglyph = nuts.isglyph -- or ischar
+
+local setfield = nuts.setfield
+local setprop = nuts.setprop
+local setchar = nuts.setchar
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+local end_of_math = nuts.end_of_math
+
+local nodepool = nuts.pool
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local glyph_code = nodecodes.glyph
+local math_code = nodecodes.math
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+
+local parfillskip_code = skipcodes.parfillskip
+
+local new_textdir = nodepool.textdir
+
+local hasbit = number.hasbit
+local formatters = string.formatters
+local insert = table.insert
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontchar = fonthashes.characters
+
+local chardirections = characters.directions
+local charmirrors = characters.mirrors
+local charclasses = characters.textclasses
+
+local directions = typesetters.directions
+local setcolor = directions.setcolor
+local getglobal = directions.getglobal
+
+local a_state = attributes.private('state')
+local a_directions = attributes.private('directions')
+
+local strip = false
+
+local s_isol = fonts.analyzers.states.isol
+
+local function stopdir(finish)
+ local n = new_textdir(finish == "TRT" and "-TRT" or "-TLT")
+ setprop(n,"direction",true)
+ return n
+end
+
+local function startdir(finish)
+ local n = new_textdir(finish == "TRT" and "+TRT" or "+TLT")
+ setprop(n,"direction",true)
+ return n
+end
+
+local function nextisright(current)
+ current = getnext(current)
+ local character, id = isglyph(current)
+ if character then
+ local direction = chardirections[character]
+ return direction == "r" or direction == "al" or direction == "an"
+ end
+end
+
+local function previsright(current)
+ current = getprev(current)
+ local character, id = isglyph(current)
+ if character then
+ local direction = chardirections[character]
+ return direction == "r" or direction == "al" or direction == "an"
+ end
+end
+
+local function process(start)
+
+ local head = tonut(start) -- we have a global head
+ local current = head
+ local autodir = 0
+ local embedded = 0
+ local override = 0
+ local pardir = 0
+ local textdir = 0
+ local done = false
+ local stack = { }
+ local top = 0
+ local obsolete = { }
+ local rlo = false
+ local lro = false
+ local prevattr = false
+ local fences = { }
+
+ while current do
+ -- no isglyph here as we test for skips first
+ local id = getid(current)
+ local next = getnext(current)
+ if id == math_code then
+ current = getnext(end_of_math(next))
+ elseif getprop(current,"direction") then
+ -- this handles unhbox etc
+ current = next
+ else
+ local attr = getattr(current,a_directions)
+ if attr and attr > 0 then
+ if attr ~= prevattr then
+ if not getglobal(a) then
+ lro = false
+ rlo = false
+ end
+ prevattr = attr
+ end
+ end
+ if id == glyph_code then
+ if attr and attr > 0 then
+ local character, font = isglyph(current)
+ if character == 0 then
+ -- skip signals
+ setprop(current,"direction",true)
+ else
+ local direction = chardirections[character]
+ local reversed = false
+ if rlo or override > 0 then
+ if direction == "l" then
+ direction = "r"
+ reversed = true
+ end
+ elseif lro or override < 0 then
+ if direction == "r" or direction == "al" then
+ setprop(current,a_state,s_isol) -- hm
+ direction = "l"
+ reversed = true
+ end
+ end
+ if direction == "on" then
+ local mirror = charmirrors[character]
+ if mirror and fontchar[font][mirror] then
+ local class = charclasses[character]
+ if class == "open" then
+ if nextisright(current) then
+ setchar(current,mirror)
+ setprop(current,"direction","r")
+ elseif autodir < 0 then
+ setchar(current,mirror)
+ setprop(current,"direction","r")
+ else
+ mirror = false
+ setprop(current,"direction","l")
+ end
+ local fencedir = autodir == 0 and textdir or autodir
+ fences[#fences+1] = fencedir
+ elseif class == "close" and #fences > 0 then
+ local fencedir = fences[#fences]
+ fences[#fences] = nil
+ if fencedir < 0 then
+ setchar(current,mirror)
+ setprop(current,"direction","r")
+ else
+ setprop(current,"direction","l")
+ mirror = false
+ end
+ elseif autodir < 0 then
+ setchar(current,mirror)
+ setprop(current,"direction","r")
+ else
+ setprop(current,"direction","l")
+ mirror = false
+ end
+ else
+ setprop(current,"direction",true)
+ end
+ if trace_directions then
+ setcolor(current,direction,false,mirror)
+ end
+ elseif direction == "l" then
+ if trace_directions then
+ setcolor(current,"l",reversed)
+ end
+ setprop(current,"direction","l")
+ elseif direction == "r" then
+ if trace_directions then
+ setcolor(current,"r",reversed)
+ end
+ setprop(current,"direction","r")
+ elseif direction == "en" then -- european number
+ if trace_directions then
+ setcolor(current,"l")
+ end
+ setprop(current,"direction","l")
+ elseif direction == "al" then -- arabic letter
+ if trace_directions then
+ setcolor(current,"r")
+ end
+ setprop(current,"direction","r")
+ elseif direction == "an" then -- arabic number
+ -- needs a better scanner as it can be a float
+ if trace_directions then
+ setcolor(current,"l") -- was r
+ end
+ setprop(current,"direction","n") -- was r
+ elseif direction == "lro" then -- Left-to-Right Override -> right becomes left
+ top = top + 1
+ stack[top] = { override, embedded }
+ override = -1
+ obsolete[#obsolete+1] = current
+ elseif direction == "rlo" then -- Right-to-Left Override -> left becomes right
+ top = top + 1
+ stack[top] = { override, embedded }
+ override = 1
+ obsolete[#obsolete+1] = current
+ elseif direction == "lre" then -- Left-to-Right Embedding -> TLT
+ top = top + 1
+ stack[top] = { override, embedded }
+ embedded = 1
+ obsolete[#obsolete+1] = current
+ elseif direction == "rle" then -- Right-to-Left Embedding -> TRT
+ top = top + 1
+ stack[top] = { override, embedded }
+ embedded = -1
+ obsolete[#obsolete+1] = current
+ elseif direction == "pdf" then -- Pop Directional Format
+ if top > 0 then
+ local s = stack[top]
+ override = s[1]
+ embedded = s[2]
+ top = top - 1
+ else
+ override = 0
+ embedded = 0
+ end
+ obsolete[#obsolete+1] = current
+ elseif trace_directions then
+ setcolor(current)
+ setprop(current,"direction",true)
+ else
+ setprop(current,"direction",true)
+ end
+ end
+ else
+ setprop(current,"direction",true)
+ end
+ elseif id == glue_code then
+ if getsubtype(current) == parfillskip_code then
+ setprop(current,"direction",'!')
+ else
+ setprop(current,"direction",'g')
+ end
+ elseif id == kern_code then
+ setprop(current,"direction",'k')
+ elseif id == dir_code then
+ local dir = getfield(current,"dir")
+ 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
+ autodir = embedded
+ else
+ autodir = 0
+ end
+ else
+ -- message
+ end
+ textdir = autodir
+ setprop(current,"direction",true)
+ elseif id == localpar_code then
+ local dir = getfield(current,"dir")
+ if dir == 'TRT' then
+ autodir = -1
+ elseif dir == 'TLT' then
+ autodir = 1
+ end
+ pardir = autodir
+ textdir = pardir
+ setprop(current,"direction",true)
+ else
+ setprop(current,"direction",true)
+ end
+ current = next
+ end
+ end
+
+ -- todo: track if really needed
+ -- todo: maybe we need to set the property (as it can be a copied list)
+
+ if done and strip then
+ local n = #obsolete
+ if n > 0 then
+ for i=1,n do
+ remove_node(head,obsolete[i],true)
+ end
+ if trace_directions then
+ report_directions("%s character nodes removed",n)
+ end
+ end
+ end
+
+ local state = false
+ local last = false
+ local collapse = true
+ current = head
+
+ -- todo: textdir
+ -- todo: inject before parfillskip
+
+ while current do
+ local id = getid(current)
+ if id == math_code then
+ -- todo: this might be tricky nesting
+ current = getnext(end_of_math(getnext(current)))
+ else
+ local cp = getprop(current,"direction")
+ if cp == "n" then
+ local swap = state == "r"
+ if swap then
+ head = insert_node_before(head,current,startdir("TLT"))
+ end
+ setprop(current,"direction",true)
+ while true do
+ local n = getnext(current)
+ if n and getprop(n,"direction") == "n" then
+ current = n
+ setprop(current,"direction",true)
+ else
+ break
+ end
+ end
+ if swap then
+ head, current = insert_node_after(head,current,stopdir("TLT"))
+ end
+ elseif cp == "l" then
+ if state ~= "l" then
+ if state == "r" then
+ head = insert_node_before(head,last or current,stopdir("TRT"))
+ end
+ head = insert_node_before(head,current,startdir("TLT"))
+ state = "l"
+ done = true
+ end
+ last = false
+ elseif cp == "r" then
+ if state ~= "r" then
+ if state == "l" then
+ head = insert_node_before(head,last or current,stopdir("TLT"))
+ end
+ head = insert_node_before(head,current,startdir("TRT"))
+ state = "r"
+ done = true
+ end
+ last = false
+ elseif collapse then
+ if cp == "k" or cp == "g" then
+ last = last or current
+ else
+ last = false
+ end
+ else
+ if state == "r" then
+ head = insert_node_before(head,current,stopdir("TRT"))
+ elseif state == "l" then
+ head = insert_node_before(head,current,stopdir("TLT"))
+ end
+ state = false
+ last = false
+ end
+ setprop(current,"direction",true)
+ end
+ local next = getnext(current)
+ if next then
+ current = next
+ else
+ local sd = (state == "r" and stopdir("TRT")) or (state == "l" and stopdir("TLT"))
+ if sd then
+ if id == glue_code and getsubtype(current) == parfillskip_code then
+ head = insert_node_before(head,current,sd)
+ else
+ head = insert_node_after(head,current,sd)
+ end
+ end
+ break
+ end
+ end
+
+ return tonode(head), done
+
+end
+
+directions.installhandler(interfaces.variables.default,process)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua
new file mode 100644
index 00000000000..09c2f64eeb7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua
@@ -0,0 +1,181 @@
+if not modules then modules = { } end modules ['typo-dig'] = {
+ version = 1.001,
+ comment = "companion to typo-dig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we might consider doing this after the otf pass because now osf do not work
+-- out well in node mode.
+
+local next, type = next, type
+local format, insert = string.format, table.insert
+local round, div = math.round, math.div
+
+local trace_digits = false trackers.register("typesetters.digits", function(v) trace_digits = v end)
+
+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 getfield = nuts.getfield
+local getattr = nuts.getattr
+
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setattr = nuts.setattr
+
+local hpack_node = nuts.hpack
+local traverse_id = nuts.traverse_id
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local nodepool = nuts.pool
+local tasks = nodes.tasks
+
+local new_glue = nodepool.glue
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
+
+local v_reset = interfaces.variables.reset
+
+local charbase = characters.data
+local getdigitwidth = fonts.helpers.getdigitwidth
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.digits = typesetters.digits or { }
+local digits = typesetters.digits
+
+digits.actions = { }
+local actions = digits.actions
+
+local a_digits = attributes.private("digits")
+
+-- at some point we can manipulate the glyph node so then i need
+-- to rewrite this then
+
+function nodes.aligned(head,start,stop,width,how)
+ if how == "flushright" or how == "middle" then
+ head, start = insert_node_before(head,start,new_glue(0,65536,65536))
+ end
+ if how == "flushleft" or how == "middle" then
+ head, stop = insert_node_after(head,stop,new_glue(0,65536,65536))
+ end
+ local prv = getprev(start)
+ local nxt = getnext(stop)
+ setprev(start)
+ setnext(stop)
+ local packed = hpack_node(start,width,"exactly") -- no directional mess here, just lr
+ if prv then
+ setlink(prv,packed)
+ end
+ if nxt then
+ setlink(packed,nxt)
+ end
+ if getprev(packed) then
+ return head, packed
+ else
+ return packed, packed
+ end
+end
+
+actions[1] = function(head,start,attr)
+ local font = getfont(start)
+ local char = getchar(start)
+ local unic = chardata[font][char].unicode or char
+ if charbase[unic].category == "nd" then -- ignore unic tables
+ local oldwidth = getfield(start,"width")
+ local newwidth = getdigitwidth(font)
+ if newwidth ~= oldwidth then
+ if trace_digits then
+ report_digits("digit trigger %a, instance %a, char %C, unicode %U, delta %s",
+ attr%100,div(attr,100),char,unic,newwidth-oldwidth)
+ end
+ head, start = nodes.aligned(head,start,start,newwidth,"middle")
+ return head, start, true
+ end
+ end
+ return head, start, false
+end
+
+function digits.handler(head)
+ head = tonut(head)
+ local done, current, ok = false, head, false
+ while current do
+ if getid(current) == glyph_code then
+ local attr = getattr(current,a_digits)
+ if attr and attr > 0 then
+ setattr(current,a_digits,unsetvalue)
+ local action = actions[attr%100] -- map back to low number
+ if action then
+ head, current, ok = action(head,current,attr)
+ done = done and ok
+ elseif trace_digits then
+ report_digits("unknown digit trigger %a",attr)
+ end
+ end
+ end
+ if current then
+ current = getnext(current)
+ end
+ end
+ return tonode(head), done
+end
+
+local m, enabled = 0, false -- a trick to make neighbouring ranges work
+
+function digits.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.digits.handler")
+ if trace_digits then
+ report_digits("enabling digit handler")
+ end
+ enabled = true
+ end
+ if m == 100 then
+ m = 1
+ else
+ m = m + 1
+ end
+ n = m * 100 + n
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_digits,n)
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setdigitsmanipulation",
+ actions = digits.set,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dig.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.mkiv
new file mode 100644
index 00000000000..aa610b3c943
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.mkiv
@@ -0,0 +1,58 @@
+%D \module
+%D [ file=typo-dig,
+%D version=2010.01.18,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Digits,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Digits}
+
+\unprotect
+
+\registerctxluafile{typo-dig}{1.001}
+
+\definesystemattribute[digits][public]
+
+%D This could as well be a dynamic font feature but why bother.
+%D
+%D \macros
+%D {\equaldigits}
+%D
+%D \startbuffer
+%D test test \ruledhbox{123} test test\par
+%D test test \ruledhbox{\equaldigits{123}} test test\par
+%D test test \equaldigits{123} test test\par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This calls result in:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\unexpanded\def\setdigitsmanipulation[#1]%
+ {\clf_setdigitsmanipulation{#1}}
+
+\unexpanded\def\resetdigitsmanipulation
+ {\attribute\digitsattribute\attributeunsetvalue}
+
+\appendtoks
+ \resetdigitsmanipulation
+\to \everyresettypesetting
+
+\unexpanded\def\equaldigits{\groupedcommand{\setdigitsmanipulation[\number\plusone]}{}}
+\unexpanded\def\dummydigit {\hphantom {\setdigitsmanipulation[\number\plusone]0}}
+
+\appendtoks
+ \resetdigitsmanipulation
+\to \everyinitializeverbatim
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua
new file mode 100644
index 00000000000..482b7114d63
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua
@@ -0,0 +1,207 @@
+if not modules then modules = { } end modules ['typo-dir'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- When we started with this, there were some issues in luatex so we needed to take care of
+-- intereferences. Some has been improved but we stil might end up with each node having a
+-- dir property. Now, the biggest problem is that there is an official bidi algorithm but
+-- some searching on the web shows that there are many confusing aspects and therefore
+-- proposals circulate about (sometimes imcompatible ?) improvements. In the end it all boils
+-- down to the lack of willingness to tag an input source. Of course tagging of each number
+-- and fenced strip is somewhat over the top, but now it has to be captured in logic. Texies
+-- normally have no problem with tagging but we need to handle any input. So, what we have
+-- done here (over the years) is starting from what we expect to see happen, especially with
+-- respect to punctation, numbers and fences. Eventually alternative algorithms will be provides
+-- so that users can choose (the reason why suggestion sfor improvements circulate on the web
+-- is that it is non trivial to predict the expected behaviour so one hopes that the ditor
+-- and the rest of the machinery match somehow. Anyway, the fun of tex is that it has no hard
+-- coded behavior. And ... we also want to have more debugging and extras and ... so we want
+-- a flexible approach. In the end we will have:
+--
+-- = full tagging (mechanism turned off)
+-- = half tagging (the current implementation)
+-- = unicode version x interpretation (several depending on the evolution)
+
+local next, type = next, type
+local format, insert, sub, find, match = string.format, table.insert, string.sub, string.find, string.match
+local utfchar = utf.char
+local formatters = string.formatters
+
+local nodes, node = nodes, node
+
+local trace_textdirections = false trackers.register("typesetters.directions.text", function(v) trace_textdirections = v end)
+local trace_mathdirections = false trackers.register("typesetters.directions.math", function(v) trace_mathdirections = v end)
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_textdirections = v trace_mathdirections = v end)
+
+local report_textdirections = logs.reporter("typesetting","text directions")
+local report_mathdirections = logs.reporter("typesetting","math directions")
+
+local hasbit = number.hasbit
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local tasks = nodes.tasks
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local resetcolor = tracers.colors.reset
+
+local implement = interfaces.implement
+
+local directions = typesetters.directions or { }
+typesetters.directions = directions
+
+local a_directions = attributes.private('directions')
+
+local variables = interfaces.variables
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_on = variables.on
+local v_yes = variables.yes
+
+local m_enabled = 2^6 -- 64
+local m_global = 2^7
+local m_fences = 2^8
+
+local handlers = { }
+local methods = { }
+local lastmethod = 0
+
+local function installhandler(name,handler)
+ local method = methods[name]
+ if not method then
+ lastmethod = lastmethod + 1
+ method = lastmethod
+ methods[name] = method
+ end
+ handlers[method] = handler
+ return method
+end
+
+directions.handlers = handlers
+directions.installhandler = installhandler
+
+local function tomode(specification)
+ local scope = specification.scope
+ local mode
+ if scope == v_global or scope == v_on then
+ mode = m_enabled + m_global
+ elseif scope == v_local then
+ mode = m_enabled
+ else
+ return 0
+ end
+ local method = methods[specification.method]
+ if method then
+ mode = mode + method
+ else
+ return 0
+ end
+ if specification.fences == v_yes then
+ mode = mode + m_fences
+ end
+ return mode
+end
+
+local function getglobal(a)
+ return a and a > 0 and hasbit(a,m_global)
+end
+
+local function getfences(a)
+ return a and a > 0 and hasbit(a,m_fences)
+end
+
+local function getmethod(a)
+ return a and a > 0 and a % m_enabled or 0
+end
+
+directions.tomode = tomode
+directions.getglobal = getglobal
+directions.getfences = getfences
+directions.getmethod = getmethod
+directions.installhandler = installhandler
+
+-- beware: in dha we have character properties and in dua|b we have direction properties
+
+function directions.setcolor(current,direction,reversed,mirror)
+ if mirror then
+ setcolor(current,"bidi:mirrored")
+ elseif direction == "l" then
+ setcolor(current,reversed and "bidi:left:reversed" or "bidi:left:original")
+ elseif direction == "r" then
+ setcolor(current,reversed and "bidi:right:reversed" or "bidi:right:original")
+ else
+ resetcolor(current)
+ end
+end
+
+implement {
+ name = "getbidimode",
+ actions = { tomode, context },
+ arguments = {
+ {
+ { "scope" },
+ { "method" },
+ { "fences" },
+ }
+ }
+}
+
+local enabled = false
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+function directions.handler(head) -- ,_,_,_,direction) -- nodes not nuts | 5th arg is direction
+ if not head.next then
+ return head, false
+ end
+ local attr = head[a_directions]
+ if not attr or attr == 0 then
+ return head, false
+ end
+ local method = getmethod(attr)
+ local handler = handlers[method]
+ if not handler then
+ return head, false
+ end
+ starttiming(directions)
+ local head, done = handler(head)
+ stoptiming(directions)
+ return head, done
+end
+
+statistics.register("text directions", function()
+ if enabled then
+ return statistics.elapsedseconds(directions)
+ end
+end)
+
+-- function directions.enable()
+-- tasks.enableaction("processors","directions.handler")
+-- end
+
+function directions.set(n) -- todo: names and numbers
+ if not enabled then
+ if trace_textdirections then
+ report_textdirections("enabling directions handler")
+ end
+ tasks.enableaction("processors","typesetters.directions.handler")
+ enabled = true
+ end
+ if not n or n == 0 then
+ n = unsetvalue
+ -- maybe tracing
+ end
+ texsetattribute(a_directions,n)
+end
+
+implement {
+ name = "setdirection",
+ arguments = "integer",
+ actions = directions.set
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv
new file mode 100644
index 00000000000..c5fd6fa4184
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv
@@ -0,0 +1,195 @@
+%D \module
+%D [ file=typo-dir,
+%D version=2009.03.27, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Directions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Directions}
+
+%D At some point we might default to method 'two' but first I need to make it more
+%D efficient (and provide some options). I also want to have some basic tracing.
+
+\unprotect
+
+\registerctxluafile{typo-dir}{1.001}
+\registerctxluafile{typo-dha}{1.001}
+\registerctxluafile{typo-dua}{1.001}
+\registerctxluafile{typo-dub}{1.001}
+\registerctxluafile{typo-duc}{1.001}
+
+\definesystemattribute[directions][public]
+
+\installcorenamespace{directions}
+\installcorenamespace{directionsbidimode}
+
+% plural as we can have a combination but maybe better singular
+
+\installsimplecommandhandler \??directions {directions} \??directions % no \define... yet
+
+\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark
+\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark
+
+\unexpanded\def\setdirection[#1]% todo: symbolic names
+ {\clf_setdirection#1\relax}
+
+% \unexpanded\def\resetdirection
+% {\clf_setdirection\zerocount}
+%
+% is in fact:
+
+\unexpanded\def\resetdirection
+ {\attribute\directionsattribute\attributeunsetvalue}
+
+\newconstant\directionsbidimode % this one might become pivate
+
+% \setupdirections[bidi=global,method=default]
+% \setupdirections[bidi=global,method=one]
+% \setupdirections[bidi=global,method=two]
+% \setupdirections[bidi=global,method=two,fences=no]
+
+% maybe use chardefs
+
+\def\typo_dir_get_mode
+ {\def\currentbidimode{\clf_getbidimode
+ scope {\directionsparameter\c!bidi}%
+ method {\directionsparameter\c!method}%
+ fences {\directionsparameter\c!fences}%
+ }%
+ \expandafter\glet\csname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode}
+
+\appendtoks
+ \edef\currentbidistamp
+ {\directionsparameter\c!bidi
+ :\directionsparameter\c!method
+ :\directionsparameter\c!fences}%
+ \expandafter\let\expandafter\currentbidimode\csname\??directionsbidimode\currentbidistamp\endcsname
+ \ifx\currentbidimode\relax
+ \typo_dir_get_mode
+ \fi
+ \directionsbidimode\currentbidimode\relax
+ \ifcase\directionsbidimode
+ \resetdirection
+ \else
+ \setdirection[\number\directionsbidimode]%
+ \fi
+\to \everysetupdirections
+
+% bidi: local=obey grouping, global=ignore grouping (unicode has no grouping)
+
+\setupdirections % maybe start/stop
+ [\c!bidi=\v!off,
+ \c!method=\v!default,
+ \c!fences=\v!yes]
+
+\unexpanded\edef\bidilre{\normalUchar"202A} % maybe \edef's
+\unexpanded\edef\bidirle{\normalUchar"202B}
+\unexpanded\edef\bidipop{\normalUchar"202C}
+\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\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi}
+\unexpanded\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi}
+
+% for the moment: \setdirection[\plusone]
+
+\definecolor[bidi:left:original] [r=.6]
+\definecolor[bidi:left:reversed] [g=.6]
+\definecolor[bidi:right:original][b=.6]
+\definecolor[bidi:right:reversed][r=.6,g=.6]
+\definecolor[bidi:mirrored] [r=.6,b=.6]
+
+\protect \endinput
+
+% 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
+
+\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
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua
new file mode 100644
index 00000000000..bddcc008e01
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua
@@ -0,0 +1,384 @@
+if not modules then modules = { } end modules ['typo-drp'] = {
+ version = 1.001,
+ comment = "companion to typo-drp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This ons is sensitive for order (e.g. when combined with first line
+-- processing.
+
+-- todo: use isglyph
+
+local tonumber, type, next = tonumber, type, next
+local ceil = math.ceil
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end)
+local report_initials = logs.reporter("nodes","initials")
+
+local initials = typesetters.paragraphs or { }
+typesetters.initials = initials or { }
+
+local nodes = nodes
+local tasks = nodes.tasks
+
+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 getfield = nuts.getfield
+local getattr = nuts.getattr
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setprev = nuts.setprev
+local setnext = nuts.setnext
+local setchar = nuts.setchar
+
+local hpack_nodes = nuts.hpack
+
+local nodecodes = nodes.nodecodes
+
+local nodepool = nuts.pool
+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 free_node = nuts.free
+
+local variables = interfaces.variables
+local v_default = variables.default
+local v_margin = variables.margin
+local v_auto = variables.auto
+local v_first = variables.first
+local v_last = variables.last
+
+local texget = tex.get
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local localpar_code = nodecodes.localpar
+
+local actions = { }
+initials.actions = actions
+
+local a_initial = attributes.private("initial")
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local category = characters.category
+
+local settings = nil
+
+function initials.set(specification)
+ settings = specification or { }
+ settings.enabled = true
+ tasks.enableaction("processors","typesetters.initials.handler")
+ if trace_initials then
+ report_initials("enabling initials")
+ end
+ texsetattribute(a_initial,1)
+end
+
+interfaces.implement {
+ name = "setinitial",
+ actions = initials.set,
+ arguments = {
+ {
+ { "location" },
+ { "enabled", "boolean" },
+ { "method" },
+ { "distance" ,"dimen" },
+ { "hoffset" ,"dimen" },
+ { "voffset" ,"dimen" },
+ { "font", "integer" },
+ { "dynamic", "integer" },
+ { "ca", "integer" },
+ { "ma", "integer" },
+ { "ta", "integer" },
+ { "n", "integer" },
+ { "m", "integer" },
+ }
+ }
+}
+
+-- dropped caps experiment (will be done properly when luatex
+-- stores the state in the local par node) .. btw, search still
+-- works with dropped caps, as does an export
+
+-- we need a 'par' attribute and in fact for dropped caps we don't need
+-- need an attribute ... dropit will become s state counter (or end up
+-- in the localpar user data
+
+-- for the moment, each paragraph gets a number as id (attribute) ..problem
+-- with nesting .. or anyhow, needed for tagging anyway
+
+-- todo: prevent linebreak .. but normally a initial ends up at the top of
+-- 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
+ -- begin of par
+ local first = getnext(head)
+ local indent = false
+ -- parbox .. needs to be set at 0
+ if first and getid(first) == hlist_code then
+ first = getnext(first)
+ indent = true
+ end
+ -- we need to skip over kerns and glues (signals)
+ while first and getid(first) ~= glyph_code do
+ first = getnext(first)
+ end
+ if first and getid(first) == glyph_code then
+ local ma = setting.ma or 0
+ local ca = setting.ca
+ local ta = setting.ta
+ local last = first
+ local distance = setting.distance or 0
+ local voffset = setting.voffset or 0
+ local hoffset = setting.hoffset or 0
+ local parindent = tex.parindent
+ local baseline = texget("baselineskip").width
+ local lines = tonumber(setting.n) or 0
+ local dynamic = setting.dynamic
+ local font = setting.font
+ local method = settings_to_hash(setting.method)
+ local length = tonumber(setting.m) or 1
+ --
+ -- 1 char | n chars | skip first quote | ignore punct | keep punct
+ --
+ if getattr(first,a_initial) then
+ for current in traverse(getnext(first)) do
+ if getattr(current,a_initial) then
+ last = current
+ else
+ break
+ end
+ end
+ elseif method[v_auto] then
+ local char = getchar(first)
+ local kind = category(char)
+ if kind == "po" or kind == "pi" then
+ if method[v_first] then
+ -- remove quote etc before initial
+ local next = getnext(first)
+ if not next then
+ -- don't start with a quote or so
+ return head, false
+ end
+ last = nil
+ for current in traverse_id(glyph_code,next) do
+ head, first = remove_node(head,first,true)
+ first = current
+ last = first
+ break
+ end
+ if not last then
+ -- no following glyph or so
+ return head, false
+ 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
+ end
+ for current in traverse_id(glyph_code,next) do
+ last = current
+ break
+ end
+ if last == first then
+ return head, false
+ end
+ end
+ elseif kind == "pf" then
+ -- error: final quote
+ else
+ -- okay
+ end
+ -- 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)
+ local kind = category(char)
+ if kind == "po" then
+ if method[v_last] then
+ -- remove period etc after initial
+ remove_node(head,current,true)
+ else
+ -- keep period etc with initial
+ last = current
+ end
+ end
+ break
+ end
+ end
+ else
+ for current in traverse_id(glyph_code,first) do
+ last = current
+ if length <= 1 then
+ break
+ else
+ length = length - 1
+ end
+ end
+ end
+ local current = first
+ while true do
+ local id = getid(current)
+ if id == kern_code then
+ setfield(current,"kern",0)
+ elseif id == glyph_code then
+ local next = getnext(current)
+ if font then
+ setfield(current,"font",font)
+ end
+ if dynamic > 0 then
+ setattr(current,0,dynamic)
+ end
+-- apply font
+
+-- local g = nodes.copy(tonode(current))
+-- g.subtype = 0
+-- nodes.handlers.characters(g)
+-- nodes.handlers.protectglyphs(g)
+-- setchar(current,g.char)
+-- nodes.free(g)
+
+ -- can be a helper
+ if ca and ca > 0 then
+ setattr(current,a_colorspace,ma == 0 and 1 or ma)
+ setattr(current,a_color,ca)
+ end
+ if ta and ta > 0 then
+ setattr(current,a_transparency,ta)
+ end
+ --
+ end
+ if current == last then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ -- We pack so that successive handling cannot touch the dropped cap. Packaging
+ -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not
+ -- yet stored in with localpar).
+ local prev = getprev(first)
+ local next = getnext(last)
+ --
+ setprev(first)
+ setnext(last)
+ local dropper = hpack_nodes(first)
+ local width = getfield(dropper,"width")
+ local height = getfield(dropper,"height")
+ local depth = getfield(dropper,"depth")
+ setfield(dropper,"width",0)
+ setfield(dropper,"height",0)
+ setfield(dropper,"depth",0)
+ --
+ setlink(prev,dropper)
+ setlink(dropper,next)
+ --
+ if next then
+ local current = next
+ while current do
+ local id = getid(current)
+ if id == glue_code or id == kern_code then
+ local next = getnext(current)
+ -- remove_node(current,current,true) -- created an invalid next link and dangling remains
+ remove_node(head,current,true)
+ current = next
+ else
+ break
+ end
+ end
+ end
+ --
+ local hoffset = width + hoffset + distance + (indent and parindent or 0)
+ for current in traverse_id(glyph_code,first) do
+ setfield(current,"xoffset",- hoffset )
+ setfield(current,"yoffset",- voffset) -- no longer - height here
+ if current == last then
+ break
+ end
+ end
+ --
+ first = dropper
+ --
+ if setting.location == v_margin then
+ -- okay
+ else
+ if lines == 0 then -- safeguard, not too precise
+ lines = ceil((height+voffset) / baseline)
+ end
+ -- We cannot set parshape yet ... when we can I'll add a slope
+ -- option (positive and negative, in emwidth).
+ local hangafter = - lines
+ local hangindent = width + distance
+ if trace_initials then
+ report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent)
+ end
+ tex.hangafter = hangafter
+ tex.hangindent = hangindent
+ end
+ if indent then
+ insert_after(first,first,new_kern(-parindent))
+ end
+ done = true
+ end
+ end
+ return head, done
+end
+
+function initials.handler(head)
+ head = tonut(head)
+ local start = head
+ local attr = nil
+ while start do
+ attr = getattr(start,a_initial)
+ if attr then
+ break
+ elseif getid(start) == glyph then
+ break
+ else
+ start = getnext(start)
+ end
+ end
+ if attr then
+ -- here as we can process nested boxes first so we need to keep state
+ tasks.disableaction("processors","typesetters.initials.handler")
+ -- texsetattribute(attribute,unsetvalue)
+ local alternative = settings.alternative or v_default
+ local action = actions[alternative] or actions[v_default]
+ if action then
+ if trace_initials then
+ report_initials("processing initials, alternative %a",alternative)
+ end
+ local head, done = action(head,settings)
+ return tonode(head), done
+ end
+ end
+ return tonode(head), false
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv
new file mode 100644
index 00000000000..2520c3bfdef
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv
@@ -0,0 +1,140 @@
+%D \module
+%D [ file=typo-drp, % was typo-par
+%D version=2011.10.27,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Initials,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Initials}
+
+%D This will change ... par specific attribute set and such.
+
+\unprotect
+
+\registerctxluafile{typo-drp}{1.001}
+
+\definesystemattribute[initial][public]
+
+\appendtoks
+ \attribute\initialattribute\attributeunsetvalue
+\to \everyforgetall
+
+%D For the moment here: dropped caps redone. In addition to the
+%D parameters shown in the example you can use the \type {style} and
+%D more low level \type {font} keys to set up the font where
+%D the first one wins. If you don't like the behaviour you can always
+%D roll out your own command.
+%D
+%D \starttyping
+%D \placeinitial \input ward \par \input ward \par \placeinitial \input tufte
+%D
+%D \setupinitial
+%D [location=text,
+%D n=2,
+%D color=darkred,
+%D distance=-1em,
+%D hoffset=1em,
+%D voffset=-3ex,
+%D before=\blank]
+%D
+%D \placeinitial \input ward \par \input ward \placeinitial \input tufte
+%D \stoptyping
+
+% todo: angle (once we can set parshape at the Lua end)
+
+\installcorenamespace{initial}
+
+\installcommandhandler \??initial {initial} \??initial
+
+\definemeasure[initial:n][\lineheight*\initialparameter\c!n - \strutdp]
+
+\setupinitial
+ [\c!location=\v!text,
+ \c!n=3,
+ \c!m=1,
+ \c!method=\v!none,
+ % \s!font=Bold sa 4,
+ % \s!font=Bold ht \measure{initial:n},
+ \s!font=Bold cp \measure{initial:n},
+ \c!distance=.125\emwidth,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\v!line, % \dimexp\lineheight*\initialparameter\c!n-\lineheight\relax]
+ \c!style=,
+ \c!color=,
+ \c!before=\blank]
+
+\unexpanded\def\placeinitial % we cannot group so no settings
+ {\dosingleempty\typo_initials_place}
+
+\def\typo_initials_place[#1]% old command
+ {\par
+ \namedinitialparameter{#1}\c!before
+ \setinitial[#1]\relax}
+
+\unexpanded\def\setinitial
+ {\dodoubleempty\typo_initials_set}
+
+\unexpanded\def\typo_initials_set[#1][#2]%
+ {\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{#2}}}
+
+\unexpanded\def\typo_initial_handle_indeed#1#2%
+ {\dontleavehmode
+ \begingroup
+ \edef\currentinitial{#1}%
+ \setupcurrentinitial[#2]%
+ \scratchcounter \initialparameter\c!n\relax
+ \scratchdistance\initialparameter\c!distance\relax
+ \scratchhoffset \initialparameter\c!hoffset \relax
+ \edef\p_voffset{\initialparameter\c!voffset}%
+ \scratchvoffset\dimexpr\ifx\p_voffset\v!line\scratchcounter\lineheight-\lineheight\else\p_voffset\fi\relax
+ \resetfontfeature % might be needed in more places
+ \doifelsenothing{\initialparameter\c!style}
+ {\definedfont[\initialparameter\s!font]}
+ {\useinitialstyleparameter\c!style}%
+ \useinitialcolorparameter\c!color
+ \edef\p_text{\initialparameter\c!text}% optional
+ \clf_setinitial
+ location {\initialparameter\c!location}%
+ enabled true\space
+ n \scratchcounter
+ m \numexpr\initialparameter\c!m\relax
+ method {\initialparameter\c!method}%
+ distance \scratchdistance
+ hoffset \scratchhoffset
+ voffset \scratchvoffset
+ ma \attribute\colormodelattribute
+ ca \attribute\colorattribute
+ ta \attribute\transparencyattribute
+ font \fontid\font
+ dynamic \attribute\zerocount % it's a bit over the top to support this here
+ \relax
+ \stopluacode
+ \kern\zeropoint % we need a node
+ \p_text
+ \endgroup
+ \globallet\typo_initial_handle\relax}
+
+\let\typo_initial_handle\relax
+
+% \setupbodyfont[dejavu,9pt]
+%
+% \startbuffer
+% \setinitial[two] D. E. Knuth \ignorespaces\input knuth \par
+% \setinitial[two] Knuth \ignorespaces\input knuth \par
+% \setinitial[two] \quotation{D. E. Knuth} \ignorespaces\input knuth \par
+% \setinitial[two] \quotation {Knuth} \ignorespaces\input knuth \par
+% \setinitial[two] [text={D.E. Knuth}] \ignorespaces\input knuth \par
+% \setinitial[two] [m=4] D. E. Knuth \ignorespaces\input knuth \par
+% \stopbuffer
+%
+% \type{m=2} \start \defineinitial[two][m=2,method=none] \getbuffer \page \stop
+% \type{m=1,method=auto} \start \defineinitial[two][m=1,method=auto] \getbuffer \page \stop
+% \type{m=1,method={auto,first,last}} \start \defineinitial[two][m=1,method={first,auto,last}] \getbuffer \page \stop
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua
new file mode 100644
index 00000000000..f697ac5620a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua
@@ -0,0 +1,829 @@
+if not modules then modules = { } end modules ['typo-dua'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team / See below",
+ license = "see context related readme files / whatever applies",
+ comment = "Unicode bidi (sort of) variant a",
+ derived = "derived from t-bidi by Khaled Hosny who derived from minibidi.c by Arabeyes",
+}
+
+-- Comment by Khaled Hosny:
+--
+-- This code started as a line for line translation of Arabeyes' minibidi.c from C to Lua,
+-- excluding parts that of no use to us like shaping. The C code is Copyright (c) 2004
+-- Ahmad Khalifa, and is distributed under the MIT Licence. The full license text can be
+-- found at: http://svn.arabeyes.org/viewvc/projects/adawat/minibidi/LICENCE.
+--
+-- Comment by Hans Hagen:
+--
+-- The initial conversion to Lua has been done by Khaled Hosny. As a first step I optimized the
+-- code (to suit todays context mkiv). Next I fixed the foreign object handling, for instance,
+-- we can skip over math but we need to inject before the open math node and after the close node,
+-- so we need to keep track of the endpoint. After I fixed that bit I realized that it was possible
+-- to generalize the object skipper if only because it saves memory (and processing time). The
+-- current implementation is about three times as fast (roughly measured) and I can probably squeeze
+-- out some more, only to sacrifice soem when I start adding features. A next stage will be to have
+-- more granularity in foreign objects. Of course all errors are mine. I'll also added the usual bit
+-- of context tracing and reshuffled some code. A memory optimization is on the agenda (already sort
+-- of prepared). It is no longer line by line.
+--
+-- The first implementation of bidi in context started out from examples of mixed usage (including
+-- more than text) with an at that point bugged r2l support. It has some alternatives for letting
+-- the tex markup having a bit higher priority. I will probably add some local (style driven)
+-- overrides to the following code as well. It also means that we can selectively enable and disable
+-- the parser (because a document wide appliance migh tnot be what we want). This will bring a
+-- slow down but not that much. (I need to check with Idris why we have things like isol there.)
+--
+-- We'll probably keep multiple methods around (this is just a side track of improving the already
+-- available scanner). I need to look into the changed unicode recomendations anyway as a first
+-- impression is that some fuzzyness has been removed. I finally need to spend time on those specs. So,
+-- there will be a third variant (written from scratch) so some point. The fun about TeX is that we
+-- can provide alternative solutions (given that it doesn't bloat the engine!)
+--
+-- A test with some hebrew, mixed with hboxes with latin/hebrew and simple math. In fact this triggered
+-- playing with bidi again:
+--
+-- 0.11 : nothing
+-- 0.14 : 0.03 node list only, one pass
+-- 0.23 : 0.12 close to unicode bidi, multipass
+-- 0.44 : 0.33 original previous
+--
+-- todo: check for introduced errors
+-- todo: reuse list, we have size, so we can just change values (and auto allocate when not there)
+-- todo: reuse the stack
+-- todo: no need for a max check
+-- todo: collapse bound similar ranges (not ok yet)
+-- tood: combine some sweeps
+--
+-- This one wil get frozen (or if needed in sync with basic t-bidi) and I will explore more options
+-- in typo-dub.lua. There I might also be able to improve performance a bit.
+
+local insert, remove, unpack, concat = table.insert, table.remove, table.unpack, table.concat
+local utfchar = utf.char
+local formatters = string.formatters
+
+local directiondata = characters.directions
+local mirrordata = characters.mirrors
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local nutstring = nuts.tostring
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getchar = nuts.getchar
+local getfield = nuts.getfield
+local getprop = nuts.getprop
+
+local setfield = nuts.setfield
+local setprop = nuts.setprop
+local setchar = nuts.setchar
+
+local remove_node = nuts.remove
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+
+local nodepool = nuts.pool
+local new_textdir = nodepool.textdir
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+local parfillskip_code = skipcodes.parfillskip
+
+----- object_replacement = 0xFFFC -- object replacement character
+local maximum_stack = 60 -- probably spec but not needed
+
+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 whitespace = {
+ lre = true,
+ rle = true,
+ lro = true,
+ rlo = true,
+ pdf = true,
+ bn = true,
+ ws = true,
+}
+
+local b_s_ws_on = {
+ b = true,
+ s = true,
+ ws = true,
+ on = true
+}
+
+-- tracing
+
+local function show_list(list,size,what)
+ local what = what or "direction"
+ local joiner = utfchar(0x200C)
+ local result = { }
+ for i=1,size do
+ local entry = list[i]
+ local character = entry.char
+ local direction = entry[what]
+ if character == 0xFFFC then
+ local first = entry.id
+ local last = entry.last
+ local skip = entry.skip
+ if last then
+ result[i] = formatters["%-3s:%s %s..%s (%i)"](direction,joiner,nodecodes[first],nodecodes[last],skip or 0)
+ else
+ result[i] = formatters["%-3s:%s %s (%i)"](direction,joiner,nodecodes[first],skip or 0)
+ end
+ elseif character >= 0x202A and character <= 0x202C then
+ result[i] = formatters["%-3s:%s %U"](direction,joiner,character)
+ else
+ result[i] = formatters["%-3s:%s %c %U"](direction,joiner,character,character)
+ end
+ end
+ return concat(result,joiner .. " | " .. joiner)
+end
+
+-- preparation
+
+local function show_done(list,size)
+ local joiner = utfchar(0x200C)
+ local result = { }
+ 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)
+ end
+ if entry.remove then
+ -- continue
+ elseif character == 0xFFFC then
+ result[#result+1] = formatters["<%s>"]("?")
+ elseif character == 0x0020 then
+ result[#result+1] = formatters["<%s>"](" ")
+ elseif character >= 0x202A and character <= 0x202C then
+ result[#result+1] = formatters["<%s>"](entry.original)
+ else
+ result[#result+1] = utfchar(character)
+ end
+ if enddir then
+ result[#result+1] = formatters["<%s>"](enddir)
+ end
+ end
+ return concat(result,joiner)
+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
+
+local function build_list(head) -- todo: store node pointer ... saves loop
+ -- P1
+ local current = head
+ local list = { }
+ local size = 0
+ while current do
+ size = size + 1
+ local id = getid(current)
+ if getprop(current,"directions") then
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while current do
+ local id = getid(current)
+ if getprop(current,"directions") then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if id == last then -- the start id
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id, last = last }
+ end
+ elseif id == glyph_code then
+ local chr = getchar(current)
+ local dir = directiondata[chr]
+ list[size] = { char = chr, direction = dir, original = dir, level = 0 }
+ current = getnext(current)
+ elseif id == glue_code then -- and how about kern
+ list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
+ current = getnext(current)
+ elseif id == dir_code then
+ local dir = getfield(current,"dir")
+ 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 }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character
+ end
+ current = getnext(current)
+ elseif id == math_code then
+ local skip = 0
+ current = getnext(current)
+ while getid(current) ~= math_code do
+ skip = skip + 1
+ current = getnext(current)
+ end
+ skip = skip + 1
+ current = getnext(current)
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while n do
+ local id = getid(current)
+ if id ~= glyph_code and id ~= glue_code and id ~= dir_code then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if id == last then -- the start id
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id, last = last }
+ end
+ end
+ end
+ return list, size
+end
+
+-- the action
+
+-- local function find_run_limit_et(list,run_start,limit)
+-- local run_limit = run_start
+-- local i = run_start
+-- while i <= limit and list[i].direction == "et" do
+-- run_limit = i
+-- i = i + 1
+-- end
+-- return run_limit
+-- end
+
+local function find_run_limit_et(list,start,limit) -- returns last match
+ for i=start,limit do
+ if list[i].direction == "et" then
+ start = i
+ else
+ return start
+ end
+ end
+ return start
+end
+
+-- local function find_run_limit_b_s_ws_on(list,run_start,limit)
+-- local run_limit = run_start
+-- local i = run_start
+-- while i <= limit and b_s_ws_on[list[i].direction] do
+-- run_limit = i
+-- i = i + 1
+-- end
+-- return run_limit
+-- end
+
+local function find_run_limit_b_s_ws_on(list,start,limit)
+ for i=start,limit do
+ if b_s_ws_on[list[i].direction] then
+ start = i
+ else
+ return start
+ end
+ end
+ 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 getfield(head,"dir") == "TRT" then
+ return 1, "TRT", true
+ else
+ return 0, "TLT", 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
+ return 0, "TLT", false
+ end
+end
+
+local function resolve_explicit(list,size,baselevel)
+ -- X1
+ local level = baselevel
+ local override = "on"
+ local stack = { }
+ local nofstack = 0
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ -- X2
+ if direction == "rle" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "on"
+ 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)
+ end
+ -- X3
+ elseif direction == "lre" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "on"
+ 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)
+ end
+ -- X4
+ elseif direction == "rlo" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "r"
+ 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)
+ end
+ -- X5
+ elseif direction == "lro" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "l"
+ 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)
+ end
+ -- X7
+ elseif direction == "pdf" then
+ if nofstack < maximum_stack then
+ local stacktop = stack[nofstack]
+ nofstack = nofstack - 1
+ level = stacktop[1]
+ override = stacktop[2]
+ 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)
+ end
+ -- X6
+ else
+ entry.level = level
+ if override ~= "on" then
+ entry.direction = override
+ end
+ end
+ end
+ -- X8 (reset states and overrides after paragraph)
+end
+
+local function resolve_weak(list,size,start,limit,sor,eor)
+ -- W1
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "nsm" then
+ if i == start then
+ entry.direction = sor
+ else
+ entry.direction = list[i-1].direction
+ end
+ end
+ end
+ -- W2
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ for j=i-1,start,-1 do
+ local prev = list[j]
+ local direction = prev.direction
+ if direction == "al" then
+ entry.direction = "an"
+ break
+ elseif direction == "r" or direction == "l" then
+ break
+ end
+ end
+ end
+ end
+ -- W3
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "al" then
+ entry.direction = "r"
+ end
+ end
+ -- W4
+ for i=start+1,limit-1 do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" then
+ if list[i-1].direction == "en" and list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif direction == "cs" then
+ local prevdirection = list[i-1].direction
+ if prevdirection == "en" then
+ if list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif prevdirection == "an" and list[i+1].direction == "an" then
+ entry.direction = "an"
+ end
+ end
+ end
+ -- W5
+ local i = start
+ while i <= limit do
+ if list[i].direction == "et" then
+ local runstart = i
+ local runlimit = find_run_limit_et(list,runstart,limit) -- when moved inline we can probably collapse a lot
+ local rundirection = runstart == start and sor or list[runstart-1].direction
+ if rundirection ~= "en" then
+ rundirection = runlimit == limit and eor or list[runlimit+1].direction
+ end
+ if rundirection == "en" then
+ for j=runstart,runlimit do
+ list[j].direction = "en"
+ end
+ end
+ i = runlimit
+ end
+ i = i + 1
+ end
+ -- W6
+ for i=start,limit do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" or direction == "et" or direction == "cs" then
+ entry.direction = "on"
+ end
+ end
+ -- W7
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ local prev_strong = sor
+ for j=i-1,start,-1 do
+ local direction = list[j].direction
+ if direction == "l" or direction == "r" then
+ prev_strong = direction
+ break
+ end
+ end
+ if prev_strong == "l" then
+ entry.direction = "l"
+ end
+ end
+ end
+end
+
+local function resolve_neutral(list,size,start,limit,sor,eor)
+ -- N1, N2
+ for i=start,limit do
+ local entry = list[i]
+ if b_s_ws_on[entry.direction] then
+ local leading_direction, trailing_direction, resolved_direction
+ local runstart = i
+ local runlimit = find_run_limit_b_s_ws_on(list,runstart,limit)
+ if runstart == start then
+ leading_direction = sor
+ else
+ leading_direction = list[runstart-1].direction
+ if leading_direction == "en" or leading_direction == "an" then
+ leading_direction = "r"
+ end
+ end
+ if runlimit == limit then
+ trailing_direction = eor
+ else
+ trailing_direction = list[runlimit+1].direction
+ if trailing_direction == "en" or trailing_direction == "an" then
+ trailing_direction = "r"
+ end
+ end
+ if leading_direction == trailing_direction then
+ -- N1
+ resolved_direction = leading_direction
+ else
+ -- N2 / does the weird period
+ resolved_direction = entry.level % 2 == 1 and "r" or "l" -- direction_of_level(entry.level)
+ end
+ for j=runstart,runlimit do
+ list[j].direction = resolved_direction
+ end
+ i = runlimit
+ end
+ i = i + 1
+ end
+end
+
+-- local function resolve_implicit(list,size,start,limit,sor,eor)
+-- -- 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,sor,eor)
+ for i=start,limit do
+ local entry = list[i]
+ local level = entry.level
+ local direction = entry.direction
+ if level % 2 ~= 1 then -- even
+ -- I1
+ if direction == "r" then
+ entry.level = level + 1
+ elseif direction == "an" or direction == "en" then
+ entry.level = level + 2
+ end
+ else
+ -- I2
+ if direction == "l" or direction == "en" or direction == "an" then
+ entry.level = level + 1
+ end
+ end
+ end
+end
+
+local function resolve_levels(list,size,baselevel)
+ -- X10
+ local start = 1
+ while start < size do
+ local level = list[start].level
+ local limit = start + 1
+ while limit < size and list[limit].level == level do
+ limit = limit + 1
+ end
+ local prev_level = start == 1 and baselevel or list[start-1].level
+ local next_level = limit == size and baselevel or list[limit+1].level
+ local sor = (level > prev_level and level or prev_level) % 2 == 1 and "r" or "l" -- direction_of_level(max(level,prev_level))
+ local eor = (level > next_level and level or next_level) % 2 == 1 and "r" or "l" -- direction_of_level(max(level,next_level))
+ -- W1 .. W7
+ resolve_weak(list,size,start,limit,sor,eor)
+ -- N1 .. N2
+ resolve_neutral(list,size,start,limit,sor,eor)
+ -- I1 .. I2
+ resolve_implicit(list,size,start,limit,sor,eor)
+ start = limit
+ end
+ -- L1
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.original
+ -- (1)
+ if direction == "s" or direction == "b" then
+ entry.level = baselevel
+ -- (2)
+ for j=i-1,1,-1 do
+ local entry = list[j]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ end
+ end
+ -- (3)
+ for i=size,1,-1 do
+ local entry = list[i]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ -- L4
+ for i=1,size do
+ local entry = list[i]
+ if entry.level % 2 == 1 then -- odd(entry.level)
+ local mirror = mirrordata[entry.char]
+ if mirror then
+ entry.mirror = mirror
+ end
+ end
+ 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 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")
+ break
+ end
+ local id = getid(current)
+ local entry = list[index]
+ local begindir = entry.begindir
+ local enddir = entry.enddir
+ setprop(current,"directions",true)
+ if id == glyph_code then
+ local mirror = entry.mirror
+ if mirror then
+ setchar(current,mirror)
+ end
+ if trace_directions then
+ local direction = entry.direction
+ setcolor(current,direction,false,mirror)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ setfield(current,"dir",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)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ enddir = false
+ done = true
+ end
+ elseif begindir then
+ if id == localpar_code then
+ -- localpar should always be the 1st node
+ local d = new_textdir(begindir)
+ setprop(d,"directions",true)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ 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)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ done = true
+ end
+ local skip = entry.skip
+ if skip and skip > 0 then
+ for i=1,skip do
+ current = getnext(current)
+ setprop(current,"directions",true)
+ end
+ end
+ if enddir then
+ local d = new_textdir(enddir)
+ setprop(d,"directions",true)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ 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
+end
+
+local function process(head)
+ head = tonut(head)
+ local list, size = build_list(head)
+ local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context
+ if not dirfound and trace_details then
+ report_directions("no initial direction found, gambling")
+ end
+ if trace_details then
+ report_directions("before : %s",show_list(list,size,"original"))
+ end
+ resolve_explicit(list,size,baselevel)
+ resolve_levels(list,size,baselevel)
+ insert_dir_points(list,size)
+ if trace_details then
+ report_directions("after : %s",show_list(list,size,"direction"))
+ report_directions("result : %s",show_done(list,size))
+ end
+ head, done = apply_to_list(list,size,head,pardir)
+ return tonode(head), done
+end
+
+directions.installhandler(interfaces.variables.one,process)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
new file mode 100644
index 00000000000..7ac33979935
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
@@ -0,0 +1,990 @@
+if not modules then modules = { } end modules ['typo-dub'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "Unicode bidi (sort of) variant b",
+}
+
+-- This is a follow up on typo-uba 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
+-- added. As a consequence this module is somewhat slower than its precursor which itself is
+-- slower than the one-pass bidi handler. This is also a playground and I might add some plugin
+-- support.
+
+-- todo (cf html):
+--
+-- normal The element does not offer a additional level of embedding with respect to the bidirectional algorithm. For inline elements implicit reordering works across element boundaries.
+-- embed If the element is inline, this value opens an additional level of embedding with respect to the bidirectional algorithm. The direction of this embedding level is given by the direction property.
+-- bidi-override For inline elements this creates an override. For block container elements this creates an override for inline-level descendants not within another block container element. This means that inside the element, reordering is strictly in sequence according to the direction property; the implicit part of the bidirectional algorithm is ignored.
+-- isolate This keyword indicates that the element's container directionality should be calculated without considering the content of this element. The element is therefore isolated from its siblings. When applying its bidirectional-resolution algorithm, its container element treats it as one or several U+FFFC Object Replacement Character, i.e. like an image.
+-- isolate-override This keyword applies the isolation behavior of the isolate keyword to the surrounding content and the override behavior o f the bidi-override keyword to the inner content.
+-- plaintext This keyword makes the elements directionality calculated without considering its parent bidirectional state or the value of the direction property. The directionality is calculated using the P2 and P3 rules of the Unicode Bidirectional Algorithm.
+-- This value allows to display data which has already formatted using a tool following the Unicode Bidirectional Algorithm.
+--
+-- todo: check for introduced errors
+-- todo: reuse list, we have size, so we can just change values (and auto allocate when not there)
+-- todo: reuse the stack
+-- todo: no need for a max check
+-- todo: collapse bound similar ranges (not ok yet)
+-- todo: combine some sweeps
+-- todo: removing is not needed when we inject at the same spot (only chnage the dir property)
+-- todo: isolated runs (isolating runs are similar to bidi=local in the basic analyzer)
+
+-- todo: check unicode addenda (from the draft):
+--
+-- Added support for canonical equivalents in BD16.
+-- Changed logic in N0 to not check forwards for context in the case of enclosed text opposite the embedding direction.
+-- Major extension of the algorithm to allow for the implementation of directional isolates and the introduction of new isolate-related values to the Bidi_Class property.
+-- Adds BD8, BD9, BD10, BD11, BD12, BD13, BD14, BD15, and BD16, Sections 2.4 and 2.5, and Rules X5a, X5b, X5c and X6a.
+-- Extensively revises Section 3.3.2, Explicit Levels and Directions and its existing X rules to formalize the algorithm for matching a PDF with the embedding or override initiator whose scope it terminates.
+-- Moves Rules X9 and X10 into a separate new Section 3.3.3, Preparations for Implicit Processing.
+-- Modifies Rule X10 to make the isolating run sequence the unit to which subsequent rules are applied.
+-- Modifies Rule W1 to change an NSM preceded by an isolate initiator or PDI into ON.
+-- Adds Rule N0 and makes other changes to Section 3.3.5, Resolving Neutral and Isolate Formatting Types to resolve bracket pairs to the same level.
+
+local insert, remove, unpack, concat = table.insert, table.remove, table.unpack, table.concat
+local utfchar = utf.char
+local setmetatable = setmetatable
+local formatters = string.formatters
+
+local directiondata = characters.directions
+local mirrordata = characters.mirrors
+local textclassdata = characters.textclasses
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local nutstring = nuts.tostring
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getchar = nuts.getchar
+local getattr = nuts.getattr
+local getfield = nuts.getfield
+local getprop = nuts.getprop
+
+local setfield = nuts.setfield
+local setprop = nuts.setprop
+local setchar = nuts.setchar
+
+local remove_node = nuts.remove
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+
+local nodepool = nuts.pool
+local new_textdir = nodepool.textdir
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+local parfillskip_code = skipcodes.parfillskip
+
+local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much
+
+local directions = typesetters.directions
+local setcolor = directions.setcolor
+local getfences = directions.getfences
+
+local a_directions = attributes.private('directions')
+local a_textbidi = attributes.private('textbidi')
+----- a_state = attributes.private('state')
+
+----- s_isol = fonts.analyzers.states.isol
+
+----- current[a_state] = s_isol -- maybe better have a special bidi attr value -> override (9) -> todo
+
+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 two")
+
+-- strong (old):
+--
+-- l : left to right
+-- r : right to left
+-- lro : left to right override
+-- rlo : left to left override
+-- lre : left to right embedding
+-- rle : left to left embedding
+-- al : right to legt arabic (esp punctuation issues)
+
+-- weak:
+--
+-- en : english number
+-- es : english number separator
+-- et : english number terminator
+-- an : arabic number
+-- 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
+-- rlo : left to left override
+-- lre : left to right embedding
+-- rle : left to left embedding
+-- pdf : pop dir format
+-- lri : left to right isolate
+-- rli : left to left isolate
+-- fsi : first string isolate
+-- pdi : pop directional isolate
+
+local whitespace = {
+ lre = true,
+ rle = true,
+ lro = true,
+ rlo = true,
+ pdf = true,
+ bn = true,
+ ws = true,
+}
+
+local b_s_ws_on = {
+ b = true,
+ s = true,
+ ws = true,
+ on = true
+}
+
+-- tracing
+
+local function show_list(list,size,what)
+ local what = what or "direction"
+ local joiner = utfchar(0x200C)
+ local result = { }
+ for i=1,size do
+ local entry = list[i]
+ local character = entry.char
+ local direction = entry[what]
+ if character == 0xFFFC then
+ local first = entry.id
+ local last = entry.last
+ local skip = entry.skip
+ if last then
+ result[i] = formatters["%-3s:%s %s..%s (%i)"](direction,joiner,nodecodes[first],nodecodes[last],skip or 0)
+ else
+ result[i] = formatters["%-3s:%s %s (%i)"](direction,joiner,nodecodes[first],skip or 0)
+ end
+ elseif character >= 0x202A and character <= 0x202C then
+ result[i] = formatters["%-3s:%s %U"](direction,joiner,character)
+ else
+ result[i] = formatters["%-3s:%s %c %U"](direction,joiner,character,character)
+ end
+ end
+ return concat(result,joiner .. " | " .. joiner)
+end
+
+-- preparation
+
+local function show_done(list,size)
+ local joiner = utfchar(0x200C)
+ local result = { }
+ 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)
+ end
+ if entry.remove then
+ -- continue
+ elseif character == 0xFFFC then
+ result[#result+1] = formatters["<%s>"]("?")
+ elseif character == 0x0020 then
+ result[#result+1] = formatters["<%s>"](" ")
+ elseif character >= 0x202A and character <= 0x202C then
+ result[#result+1] = formatters["<%s>"](entry.original)
+ else
+ result[#result+1] = utfchar(character)
+ end
+ if enddir then
+ result[#result+1] = formatters["<%s>"](enddir)
+ end
+ end
+ return concat(result,joiner)
+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
+
+-- 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 lre = { 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
+ -- P1
+ local current = head
+ local list = { }
+ local size = 0
+ while current do
+ size = size + 1
+ local id = getid(current)
+ if getprop(current,"directions") then
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while current do
+ local id = getid(current)
+ if getprop(current,"directions") then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if id == last then -- the start id
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id, last = last }
+ end
+ elseif id == glyph_code then
+ local chr = getchar(current)
+ local dir = directiondata[chr]
+ list[size] = { char = chr, direction = dir, original = dir, level = 0 }
+ current = getnext(current)
+ elseif id == glue_code then -- and how about kern
+ list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
+ current = getnext(current)
+ elseif id == dir_code then
+ local dir = getfield(current,"dir")
+ 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 }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character
+ end
+ current = getnext(current)
+ elseif id == math_code then
+ local skip = 0
+ current = getnext(current)
+ while getid(current) ~= math_code do
+ skip = skip + 1
+ current = getnext(current)
+ end
+ skip = skip + 1
+ current = getnext(current)
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while n do
+ local id = getid(current)
+ if id ~= glyph_code and id ~= glue_code and id ~= dir_code then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if id == last then -- the start id
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id }
+ else
+ list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id, last = last }
+ end
+ end
+ end
+ return list, size
+end
+
+-- new
+
+-- we could support ( ] and [ ) and such ...
+
+-- ש ) ל ( א 0-0
+-- ש ( ל ] א 0-0
+-- ש ( ל ) א 2-4
+-- ש ( ל [ א ) כ ] 2-6
+-- ש ( ל ] א ) כ 2-6
+-- ש ( ל ) א ) כ 2-4
+-- ש ( ל ( א ) כ 4-6
+-- ש ( ל ( א ) כ ) 2-8,4-6
+-- ש ( ל [ א ] כ ) 2-8,4-6
+
+local function resolve_fences(list,size,start,limit)
+ -- N0: funny effects, not always better, so it's an option
+ local stack = { }
+ local top = 0
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "on" then
+ local char = entry.char
+ local mirror = mirrordata[char]
+ if mirror then
+ local class = textclassdata[char]
+ entry.mirror = mirror
+ entry.class = class
+ if class == "open" then
+ top = top + 1
+ stack[top] = { mirror, i, false }
+ elseif top == 0 then
+ -- skip
+ elseif class == "close" then
+ while top > 0 do
+ local s = stack[top]
+ if s[1] == char then
+ local open = s[2]
+ local close = i
+ list[open ].paired = close
+ list[close].paired = open
+ break
+ else
+ -- do we mirror or not
+ end
+ top = top - 1
+ end
+ end
+ end
+ end
+ end
+end
+
+-- local function test_fences(str)
+-- local list = { }
+-- for s in string.gmatch(str,".") do
+-- local b = utf.byte(s)
+-- list[#list+1] = { c = s, char = b, direction = directiondata[b] }
+-- end
+-- resolve_fences(list,#list,1,#size)
+-- inspect(list)
+-- end
+--
+-- test_fences("a(b)c(d)e(f(g)h)i")
+-- test_fences("a(b[c)d]")
+
+-- 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 getfield(head,"dir") == "TRT" then
+ return 1, "TRT", true
+ else
+ return 0, "TLT", 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
+ return 0, "TLT", false
+ end
+end
+
+local function resolve_explicit(list,size,baselevel)
+ -- X1
+ local level = baselevel
+ local override = "on"
+ local stack = { }
+ local nofstack = 0
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ -- X2
+ if direction == "rle" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "on"
+ 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)
+ end
+ -- X3
+ elseif direction == "lre" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "on"
+ 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)
+ end
+ -- X4
+ elseif direction == "rlo" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "r"
+ 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)
+ end
+ -- X5
+ elseif direction == "lro" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "l"
+ 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)
+ end
+ -- X7
+ elseif direction == "pdf" then
+ if nofstack < maximum_stack then
+ local stacktop = stack[nofstack]
+ nofstack = nofstack - 1
+ level = stacktop[1]
+ override = stacktop[2]
+ 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)
+ end
+ -- X6
+ else
+ entry.level = level
+ if override ~= "on" then
+ entry.direction = override
+ end
+ end
+ end
+ -- X8 (reset states and overrides after paragraph)
+end
+
+local function resolve_weak(list,size,start,limit,orderbefore,orderafter)
+ -- W1: non spacing marks get the direction of the previous character
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "nsm" then
+ if i == start then
+ entry.direction = orderbefore
+ else
+ entry.direction = list[i-1].direction
+ end
+ end
+ end
+ -- W2: mess with numbers and arabic
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ for j=i-1,start,-1 do
+ local prev = list[j]
+ local direction = prev.direction
+ if direction == "al" then
+ entry.direction = "an"
+ break
+ elseif direction == "r" or direction == "l" then
+ break
+ end
+ end
+ end
+ end
+ -- W3
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "al" then
+ entry.direction = "r"
+ end
+ end
+ -- W4: make separators number
+ if true then
+ for i=start+1,limit-1 do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" then
+ if list[i-1].direction == "en" and list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif direction == "cs" then
+ local prevdirection = list[i-1].direction
+ if prevdirection == "en" then
+ if list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif prevdirection == "an" and list[i+1].direction == "an" then
+ entry.direction = "an"
+ end
+ end
+ end
+ else -- probably more efficient
+ local runner = start + 2
+ local before = list[start]
+ local entry = list[start + 1]
+ local after = list[runner]
+ while after do
+ local direction = entry.direction
+ if direction == "es" then
+ if before.direction == "en" and after.direction == "en" then
+ entry.direction = "en"
+ end
+ elseif direction == "cs" then
+ local prevdirection = before.direction
+ if prevdirection == "en" then
+ if after.direction == "en" then
+ entry.direction = "en"
+ end
+ elseif prevdirection == "an" and after.direction == "an" then
+ entry.direction = "an"
+ end
+ end
+ before = current
+ current = after
+ after = list[runner]
+ end
+ end
+ -- W5
+ local i = start
+ while i <= limit do
+ if list[i].direction == "et" then
+ local runstart = i
+ local runlimit = runstart
+ for i=runstart,limit do
+ if list[i].direction == "et" then
+ runlimit = i
+ else
+ break
+ end
+ end
+ local rundirection = runstart == start and sor or list[runstart-1].direction
+ if rundirection ~= "en" then
+ rundirection = runlimit == limit and orderafter or list[runlimit+1].direction
+ end
+ if rundirection == "en" then
+ for j=runstart,runlimit do
+ list[j].direction = "en"
+ end
+ end
+ i = runlimit
+ end
+ i = i + 1
+ end
+ -- W6
+ for i=start,limit do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" or direction == "et" or direction == "cs" then
+ entry.direction = "on"
+ end
+ end
+ -- W7
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ local prev_strong = orderbefore
+ for j=i-1,start,-1 do
+ local direction = list[j].direction
+ if direction == "l" or direction == "r" then
+ prev_strong = direction
+ break
+ end
+ end
+ if prev_strong == "l" then
+ entry.direction = "l"
+ end
+ end
+ end
+end
+
+local function resolve_neutral(list,size,start,limit,orderbefore,orderafter)
+ -- N1, N2
+ for i=start,limit do
+ local entry = list[i]
+ if b_s_ws_on[entry.direction] then
+ -- this needs checking
+ local leading_direction, trailing_direction, resolved_direction
+ local runstart = i
+ local runlimit = runstart
+-- for j=runstart,limit do
+ for j=runstart+1,limit do
+ if b_s_ws_on[list[j].direction] then
+-- runstart = j
+ runlimit = j
+ else
+ break
+ end
+ end
+ if runstart == start then
+ leading_direction = orderbefore
+ else
+ leading_direction = list[runstart-1].direction
+ if leading_direction == "en" or leading_direction == "an" then
+ leading_direction = "r"
+ end
+ end
+ if runlimit == limit then
+ trailing_direction = orderafter
+ else
+ trailing_direction = list[runlimit+1].direction
+ if trailing_direction == "en" or trailing_direction == "an" then
+ trailing_direction = "r"
+ end
+ end
+ if leading_direction == trailing_direction then
+ -- N1
+ resolved_direction = leading_direction
+ else
+ -- N2 / does the weird period
+ resolved_direction = entry.level % 2 == 1 and "r" or "l"
+ end
+ for j=runstart,runlimit do
+ list[j].direction = resolved_direction
+ end
+ i = runlimit
+ end
+ i = i + 1
+ 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]
+ local level = entry.level
+ local direction = entry.direction
+ if level % 2 ~= 1 then -- even
+ -- I1
+ if direction == "r" then
+ entry.level = level + 1
+ elseif direction == "an" or direction == "en" then
+ entry.level = level + 2
+ end
+ else
+ -- I2
+ if direction == "l" or direction == "en" or direction == "an" then
+ entry.level = level + 1
+ end
+ end
+ end
+end
+
+local function resolve_levels(list,size,baselevel,analyze_fences)
+ -- X10
+ local start = 1
+ while start < size do
+ local level = list[start].level
+ local limit = start + 1
+ while limit < size and list[limit].level == level do
+ limit = limit + 1
+ end
+ local prev_level = start == 1 and baselevel or list[start-1].level
+ local next_level = limit == size and baselevel or list[limit+1].level
+ local orderbefore = (level > prev_level and level or prev_level) % 2 == 1 and "r" or "l"
+ local orderafter = (level > next_level and level or next_level) % 2 == 1 and "r" or "l"
+ -- W1 .. W7
+ resolve_weak(list,size,start,limit,orderbefore,orderafter)
+ -- N0
+ if analyze_fences then
+ resolve_fences(list,size,start,limit)
+ end
+ -- N1 .. N2
+ resolve_neutral(list,size,start,limit,orderbefore,orderafter)
+ -- I1 .. I2
+ resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel)
+ start = limit
+ end
+ -- L1
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.original
+ -- (1)
+ if direction == "s" or direction == "b" then
+ entry.level = baselevel
+ -- (2)
+ for j=i-1,1,-1 do
+ local entry = list[j]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ end
+ end
+ -- (3)
+ for i=size,1,-1 do
+ local entry = list[i]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ -- L4
+ if analyze_fences then
+ for i=1,size do
+ local entry = list[i]
+ if entry.level % 2 == 1 then -- odd(entry.level)
+ if entry.mirror and not entry.paired then
+ entry.mirror = false
+ end
+ -- okay
+ elseif entry.mirror then
+ entry.mirror = false
+ end
+ end
+ else
+ for i=1,size do
+ local entry = list[i]
+ if entry.level % 2 == 1 then -- odd(entry.level)
+ local mirror = mirrordata[entry.char]
+ if mirror then
+ entry.mirror = mirror
+ end
+ end
+ end
+ 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 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
+ while current do
+ if index > size then
+ report_directions("fatal error, size mismatch")
+ break
+ end
+ local id = getid(current)
+ local entry = list[index]
+ local begindir = entry.begindir
+ local enddir = entry.enddir
+ setprop(current,"directions",true)
+ if id == glyph_code then
+ local mirror = entry.mirror
+ if mirror then
+ setchar(current,mirror)
+ end
+ if trace_directions then
+ local direction = entry.direction
+ if trace_list then
+ local original = entry.original
+ local char = entry.char
+ local level = entry.level
+ if direction == original then
+ report_directions("%2i : %C : %s",level,char,direction)
+ else
+ report_directions("%2i : %C : %s -> %s",level,char,original,direction)
+ end
+ end
+ setcolor(current,direction,false,mirror)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ setfield(current,"dir",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)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ enddir = false
+ done = true
+ end
+ elseif begindir then
+ if id == localpar_code then
+ -- localpar should always be the 1st node
+ local d = new_textdir(begindir)
+ setprop(d,"directions",true)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head, current = insert_node_after(head,current,d)
+ begindir = nil
+ done = true
+ end
+ else
+ end
+ if begindir then
+ local d = new_textdir(begindir)
+ setprop(d,"directions",true)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ done = true
+ end
+ local skip = entry.skip
+ if skip and skip > 0 then
+ for i=1,skip do
+ current = getnext(current)
+ setprop(current,"directions",true)
+ end
+ end
+ if enddir then
+ local d = new_textdir(enddir)
+ setprop(d,"directions",true)
+ -- setfield(d,"attr",getfield(current,"attr"))
+ 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
+ if trace_list then
+ report_directions("stop run")
+ end
+ return head, done
+end
+
+local function process(head)
+ head = tonut(head)
+ -- 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
+ if not dirfound and trace_details then
+ report_directions("no initial direction found, gambling")
+ end
+ if trace_details then
+ report_directions("before : %s",show_list(list,size,"original"))
+ end
+ resolve_explicit(list,size,baselevel)
+ resolve_levels(list,size,baselevel,analyze_fences)
+ insert_dir_points(list,size)
+ if trace_details then
+ report_directions("after : %s",show_list(list,size,"direction"))
+ report_directions("result : %s",show_done(list,size))
+ end
+ head, done = apply_to_list(list,size,head,pardir)
+ return tonode(head), done
+end
+
+directions.installhandler(interfaces.variables.two,process)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua
new file mode 100644
index 00000000000..fce40932fcb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua
@@ -0,0 +1,1025 @@
+if not modules then modules = { } end modules ['typo-duc'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "Unicode bidi (sort of) variant b",
+}
+
+-- This is a follow up on typo-uba 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
+-- added. As a consequence this module is somewhat slower than its precursor which itself is
+-- slower than the one-pass bidi handler. This is also a playground and I might add some plugin
+-- support. However, in the meantime performance got a bit better and this third variant is again
+-- some 10% faster than the two variant.
+
+-- todo (cf html):
+--
+-- normal The element does not offer a additional level of embedding with respect to the bidirectional algorithm. For inline elements implicit reordering works across element boundaries.
+-- embed If the element is inline, this value opens an additional level of embedding with respect to the bidirectional algorithm. The direction of this embedding level is given by the direction property.
+-- bidi-override For inline elements this creates an override. For block container elements this creates an override for inline-level descendants not within another block container element. This means that inside the element, reordering is strictly in sequence according to the direction property; the implicit part of the bidirectional algorithm is ignored.
+-- isolate This keyword indicates that the element's container directionality should be calculated without considering the content of this element. The element is therefore isolated from its siblings. When applying its bidirectional-resolution algorithm, its container element treats it as one or several U+FFFC Object Replacement Character, i.e. like an image.
+-- isolate-override This keyword applies the isolation behavior of the isolate keyword to the surrounding content and the override behavior o f the bidi-override keyword to the inner content.
+-- plaintext This keyword makes the elements directionality calculated without considering its parent bidirectional state or the value of the direction property. The directionality is calculated using the P2 and P3 rules of the Unicode Bidirectional Algorithm.
+-- This value allows to display data which has already formatted using a tool following the Unicode Bidirectional Algorithm.
+--
+-- todo: check for introduced errors
+-- todo: reuse list, we have size, so we can just change values (and auto allocate when not there)
+-- todo: reuse the stack
+-- todo: no need for a max check
+-- todo: collapse bound similar ranges (not ok yet)
+-- todo: combine some sweeps
+-- todo: removing is not needed when we inject at the same spot (only chnage the dir property)
+-- todo: isolated runs (isolating runs are similar to bidi=local in the basic analyzer)
+
+-- todo: check unicode addenda (from the draft):
+--
+-- Added support for canonical equivalents in BD16.
+-- Changed logic in N0 to not check forwards for context in the case of enclosed text opposite the embedding direction.
+-- Major extension of the algorithm to allow for the implementation of directional isolates and the introduction of new isolate-related values to the Bidi_Class property.
+-- Adds BD8, BD9, BD10, BD11, BD12, BD13, BD14, BD15, and BD16, Sections 2.4 and 2.5, and Rules X5a, X5b, X5c and X6a.
+-- Extensively revises Section 3.3.2, Explicit Levels and Directions and its existing X rules to formalize the algorithm for matching a PDF with the embedding or override initiator whose scope it terminates.
+-- Moves Rules X9 and X10 into a separate new Section 3.3.3, Preparations for Implicit Processing.
+-- Modifies Rule X10 to make the isolating run sequence the unit to which subsequent rules are applied.
+-- Modifies Rule W1 to change an NSM preceded by an isolate initiator or PDI into ON.
+-- Adds Rule N0 and makes other changes to Section 3.3.5, Resolving Neutral and Isolate Formatting Types to resolve bracket pairs to the same level.
+
+local insert, remove, unpack, concat = table.insert, table.remove, table.unpack, table.concat
+local utfchar = utf.char
+local setmetatable = setmetatable
+local formatters = string.formatters
+
+local directiondata = characters.directions
+local mirrordata = characters.mirrors
+local textclassdata = characters.textclasses
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local nutstring = nuts.tostring
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getfield = nuts.getfield
+local getprop = nuts.getprop
+
+local setfield = nuts.setfield
+local setprop = nuts.setprop
+local setchar = nuts.setchar
+
+local properties = nodes.properties
+
+local remove_node = nuts.remove
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+
+local nodepool = nuts.pool
+local new_textdir = nodepool.textdir
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+local parfillskip_code = skipcodes.parfillskip
+
+local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much
+
+local directions = typesetters.directions
+local setcolor = directions.setcolor
+local getfences = directions.getfences
+
+local a_directions = attributes.private('directions')
+local a_textbidi = attributes.private('textbidi')
+----- a_state = attributes.private('state')
+
+----- s_isol = fonts.analyzers.states.isol
+
+----- current[a_state] = s_isol -- maybe better have a special bidi attr value -> override (9) -> todo
+
+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 two")
+
+-- strong (old):
+--
+-- l : left to right
+-- r : right to left
+-- lro : left to right override
+-- rlo : left to left override
+-- lre : left to right embedding
+-- rle : left to left embedding
+-- al : right to legt arabic (esp punctuation issues)
+
+-- weak:
+--
+-- en : english number
+-- es : english number separator
+-- et : english number terminator
+-- an : arabic number
+-- 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
+-- rlo : left to left override
+-- lre : left to right embedding
+-- rle : left to left embedding
+-- pdf : pop dir format
+-- lri : left to right isolate
+-- rli : left to left isolate
+-- fsi : first string isolate
+-- pdi : pop directional isolate
+
+local whitespace = {
+ lre = true,
+ rle = true,
+ lro = true,
+ rlo = true,
+ pdf = true,
+ bn = true,
+ ws = true,
+}
+
+local b_s_ws_on = {
+ b = true,
+ s = true,
+ ws = true,
+ on = true
+}
+
+-- tracing
+
+local function show_list(list,size,what)
+ local what = what or "direction"
+ local joiner = utfchar(0x200C)
+ local result = { }
+ for i=1,size do
+ local entry = list[i]
+ local character = entry.char
+ local direction = entry[what]
+ if character == 0xFFFC then
+ local first = entry.id
+ local last = entry.last
+ local skip = entry.skip
+ if last then
+ result[i] = formatters["%-3s:%s %s..%s (%i)"](direction,joiner,nodecodes[first],nodecodes[last],skip or 0)
+ else
+ result[i] = formatters["%-3s:%s %s (%i)"](direction,joiner,nodecodes[first],skip or 0)
+ end
+ elseif character >= 0x202A and character <= 0x202C then
+ result[i] = formatters["%-3s:%s %U"](direction,joiner,character)
+ else
+ result[i] = formatters["%-3s:%s %c %U"](direction,joiner,character,character)
+ end
+ end
+ return concat(result,joiner .. " | " .. joiner)
+end
+
+-- preparation
+
+local function show_done(list,size)
+ local joiner = utfchar(0x200C)
+ local result = { }
+ 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)
+ end
+ if entry.remove then
+ -- continue
+ elseif character == 0xFFFC then
+ result[#result+1] = formatters["<%s>"]("?")
+ elseif character == 0x0020 then
+ result[#result+1] = formatters["<%s>"](" ")
+ elseif character >= 0x202A and character <= 0x202C then
+ result[#result+1] = formatters["<%s>"](entry.original)
+ else
+ result[#result+1] = utfchar(character)
+ end
+ if enddir then
+ result[#result+1] = formatters["<%s>"](enddir)
+ end
+ end
+ return concat(result,joiner)
+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_lre = { __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 function build_list(head) -- todo: store node pointer ... saves loop
+ -- P1
+ local current = head
+ local list = { }
+ local size = 0
+ while current do
+ size = size + 1
+ local id = getid(current)
+ local p = properties[current]
+ local t
+ if p and p.directions then
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while current do
+ local id = getid(current)
+ if p and p.directions then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if id == last then -- the start id
+ t = { skip = skip, id = id }
+ else
+ t = { skip = skip, id = id, last = last }
+ end
+ setmetatable(t,mt_object)
+ elseif id == glyph_code then
+ local chr = getchar(current)
+ local dir = directiondata[chr]
+ t = { 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
+ elseif id == glue_code then -- and how about kern
+ t = { }
+ setmetatable(t,mt_space)
+ current = getnext(current)
+ elseif id == dir_code then
+ local dir = getfield(current,"dir")
+ if dir == "+TLT" then
+ t = { }
+ setmetatable(t,mt_lre)
+ elseif dir == "+TRT" then
+ t = { }
+ setmetatable(t,mt_rle)
+ elseif dir == "-TLT" or dir == "-TRT" then
+ t = { }
+ setmetatable(t,mt_pdf)
+ else
+ t = { id = id }
+ setmetatable(t,mt_object)
+ end
+ current = getnext(current)
+ elseif id == math_code then
+ local skip = 0
+ current = getnext(current)
+ while getid(current) ~= math_code do
+ skip = skip + 1
+ current = getnext(current)
+ end
+ skip = skip + 1
+ current = getnext(current)
+ t = { id = id, skip = skip }
+ setmetatable(t,mt_object)
+ else
+ local skip = 0
+ local last = id
+ current = getnext(current)
+ while n do
+ local id = getid(current)
+ if id ~= glyph_code and id ~= glue_code and id ~= dir_code then
+ skip = skip + 1
+ last = id
+ current = getnext(current)
+ else
+ break
+ end
+ end
+ if skip == 0 then
+ t = { id = id }
+ elseif id == last then -- the start id
+ t = { id = id, skip = skip }
+ else
+ t = { id = id, skip = skip, last = last }
+ end
+ setmetatable(t,mt_object)
+ end
+ list[size] = t
+ end
+ return list, size
+end
+
+-- new
+
+-- we could support ( ] and [ ) and such ...
+
+-- ש ) ל ( א 0-0
+-- ש ( ל ] א 0-0
+-- ש ( ל ) א 2-4
+-- ש ( ל [ א ) כ ] 2-6
+-- ש ( ל ] א ) כ 2-6
+-- ש ( ל ) א ) כ 2-4
+-- ש ( ל ( א ) כ 4-6
+-- ש ( ל ( א ) כ ) 2-8,4-6
+-- ש ( ל [ א ] כ ) 2-8,4-6
+
+local function resolve_fences(list,size,start,limit)
+ -- N0: funny effects, not always better, so it's an option
+ local stack = { }
+ local top = 0
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "on" then
+ local char = entry.char
+ local mirror = mirrordata[char]
+ if mirror then
+ local class = textclassdata[char]
+ entry.mirror = mirror
+ entry.class = class
+ if class == "open" then
+ top = top + 1
+ stack[top] = { mirror, i, false }
+ elseif top == 0 then
+ -- skip
+ elseif class == "close" then
+ while top > 0 do
+ local s = stack[top]
+ if s[1] == char then
+ local open = s[2]
+ local close = i
+ list[open ].paired = close
+ list[close].paired = open
+ break
+ else
+ -- do we mirror or not
+ end
+ top = top - 1
+ end
+ end
+ end
+ end
+ end
+end
+
+-- local function test_fences(str)
+-- local list = { }
+-- for s in string.gmatch(str,".") do
+-- local b = utf.byte(s)
+-- list[#list+1] = { c = s, char = b, direction = directiondata[b] }
+-- end
+-- resolve_fences(list,#list,1,#size)
+-- inspect(list)
+-- end
+--
+-- test_fences("a(b)c(d)e(f(g)h)i")
+-- test_fences("a(b[c)d]")
+
+-- 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 getfield(head,"dir") == "TRT" then
+ return 1, "TRT", true
+ else
+ return 0, "TLT", 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
+ return 0, "TLT", false
+ end
+end
+
+local function resolve_explicit(list,size,baselevel)
+-- if list.rle or list.lre or list.rlo or list.lro then
+ -- X1
+ local level = baselevel
+ local override = "on"
+ local stack = { }
+ local nofstack = 0
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ -- X2
+ if direction == "rle" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "on"
+ 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)
+ end
+ -- X3
+ elseif direction == "lre" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "on"
+ 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)
+ end
+ -- X4
+ elseif direction == "rlo" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 2 or 1) -- least_greater_odd(level)
+ override = "r"
+ 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)
+ end
+ -- X5
+ elseif direction == "lro" then
+ if nofstack < maximum_stack then
+ nofstack = nofstack + 1
+ stack[nofstack] = { level, override }
+ level = level + (level % 2 == 1 and 1 or 2) -- least_greater_even(level)
+ override = "l"
+ 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)
+ end
+ -- X7
+ elseif direction == "pdf" then
+ if nofstack < maximum_stack then
+ local stacktop = stack[nofstack]
+ nofstack = nofstack - 1
+ level = stacktop[1]
+ override = stacktop[2]
+ 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)
+ end
+ -- X6
+ else
+ entry.level = level
+ if override ~= "on" then
+ entry.direction = override
+ end
+ end
+ end
+-- else
+-- for i=1,size do
+-- list[i].level = baselevel
+-- end
+-- end
+ -- X8 (reset states and overrides after paragraph)
+end
+
+local function resolve_weak(list,size,start,limit,orderbefore,orderafter)
+ -- W1: non spacing marks get the direction of the previous character
+-- if list.nsm then
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "nsm" then
+ if i == start then
+ entry.direction = orderbefore
+ else
+ entry.direction = list[i-1].direction
+ end
+ end
+ end
+-- end
+ -- W2: mess with numbers and arabic
+-- if list.en then
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ for j=i-1,start,-1 do
+ local prev = list[j]
+ local direction = prev.direction
+ if direction == "al" then
+ entry.direction = "an"
+ break
+ elseif direction == "r" or direction == "l" then
+ break
+ end
+ end
+ end
+ end
+-- end
+ -- W3
+-- if list.al then
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "al" then
+ entry.direction = "r"
+ end
+ end
+-- end
+ -- W4: make separators number
+-- if list.es or list.cs then
+ -- skip
+ if false then
+ for i=start+1,limit-1 do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" then
+ if list[i-1].direction == "en" and list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif direction == "cs" then
+ local prevdirection = list[i-1].direction
+ if prevdirection == "en" then
+ if list[i+1].direction == "en" then
+ entry.direction = "en"
+ end
+ elseif prevdirection == "an" and list[i+1].direction == "an" then
+ entry.direction = "an"
+ end
+ end
+ end
+ else -- only more efficient when we have es/cs
+ local runner = start + 2
+ local before = list[start]
+ local entry = list[start + 1]
+ local after = list[runner]
+ while after do
+ local direction = entry.direction
+ if direction == "es" then
+ if before.direction == "en" and after.direction == "en" then
+ entry.direction = "en"
+ end
+ elseif direction == "cs" then
+ local prevdirection = before.direction
+ if prevdirection == "en" then
+ if after.direction == "en" then
+ entry.direction = "en"
+ end
+ elseif prevdirection == "an" and after.direction == "an" then
+ entry.direction = "an"
+ end
+ end
+ before = current
+ current = after
+ after = list[runner]
+ runner = runner + 1
+ end
+ end
+-- end
+ -- W5
+-- if list.et then
+ local i = start
+ while i <= limit do
+ if list[i].direction == "et" then
+ local runstart = i
+ local runlimit = runstart
+ for i=runstart,limit do
+ if list[i].direction == "et" then
+ runlimit = i
+ else
+ break
+ end
+ end
+ local rundirection = runstart == start and sor or list[runstart-1].direction
+ if rundirection ~= "en" then
+ rundirection = runlimit == limit and orderafter or list[runlimit+1].direction
+ end
+ if rundirection == "en" then
+ for j=runstart,runlimit do
+ list[j].direction = "en"
+ end
+ end
+ i = runlimit
+ end
+ i = i + 1
+ end
+-- end
+ -- W6
+-- if list.es or list.cs or list.et then
+ for i=start,limit do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "es" or direction == "et" or direction == "cs" then
+ entry.direction = "on"
+ end
+ end
+-- end
+ -- W7
+ for i=start,limit do
+ local entry = list[i]
+ if entry.direction == "en" then
+ local prev_strong = orderbefore
+ for j=i-1,start,-1 do
+ local direction = list[j].direction
+ if direction == "l" or direction == "r" then
+ prev_strong = direction
+ break
+ end
+ end
+ if prev_strong == "l" then
+ entry.direction = "l"
+ end
+ end
+ end
+end
+
+local function resolve_neutral(list,size,start,limit,orderbefore,orderafter)
+ -- N1, N2
+ for i=start,limit do
+ local entry = list[i]
+ if b_s_ws_on[entry.direction] then
+ -- this needs checking
+ local leading_direction, trailing_direction, resolved_direction
+ local runstart = i
+ local runlimit = runstart
+-- for j=runstart,limit do
+ for j=runstart+1,limit do
+ if b_s_ws_on[list[j].direction] then
+-- runstart = j
+ runlimit = j
+ else
+ break
+ end
+ end
+ if runstart == start then
+ leading_direction = orderbefore
+ else
+ leading_direction = list[runstart-1].direction
+ if leading_direction == "en" or leading_direction == "an" then
+ leading_direction = "r"
+ end
+ end
+ if runlimit == limit then
+ trailing_direction = orderafter
+ else
+ trailing_direction = list[runlimit+1].direction
+ if trailing_direction == "en" or trailing_direction == "an" then
+ trailing_direction = "r"
+ end
+ end
+ if leading_direction == trailing_direction then
+ -- N1
+ resolved_direction = leading_direction
+ else
+ -- N2 / does the weird period
+ resolved_direction = entry.level % 2 == 1 and "r" or "l"
+ end
+ for j=runstart,runlimit do
+ list[j].direction = resolved_direction
+ end
+ i = runlimit
+ end
+ i = i + 1
+ 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]
+ local level = entry.level
+ local direction = entry.direction
+ if level % 2 ~= 1 then -- even
+ -- I1
+ if direction == "r" then
+ entry.level = level + 1
+ elseif direction == "an" or direction == "en" then
+ entry.level = level + 2
+ end
+ else
+ -- I2
+ if direction == "l" or direction == "en" or direction == "an" then
+ entry.level = level + 1
+ end
+ end
+ end
+end
+
+local function resolve_levels(list,size,baselevel,analyze_fences)
+ -- X10
+ local start = 1
+ while start < size do
+ local level = list[start].level
+ local limit = start + 1
+ while limit < size and list[limit].level == level do
+ limit = limit + 1
+ end
+ local prev_level = start == 1 and baselevel or list[start-1].level
+ local next_level = limit == size and baselevel or list[limit+1].level
+ local orderbefore = (level > prev_level and level or prev_level) % 2 == 1 and "r" or "l"
+ local orderafter = (level > next_level and level or next_level) % 2 == 1 and "r" or "l"
+ -- W1 .. W7
+ resolve_weak(list,size,start,limit,orderbefore,orderafter)
+ -- N0
+ if analyze_fences then
+ resolve_fences(list,size,start,limit)
+ end
+ -- N1 .. N2
+ resolve_neutral(list,size,start,limit,orderbefore,orderafter)
+ -- I1 .. I2
+ resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel)
+ start = limit
+ end
+ -- L1
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.original
+ -- (1)
+ if direction == "s" or direction == "b" then
+ entry.level = baselevel
+ -- (2)
+ for j=i-1,1,-1 do
+ local entry = list[j]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ end
+ end
+ -- (3)
+ for i=size,1,-1 do
+ local entry = list[i]
+ if whitespace[entry.original] then
+ entry.level = baselevel
+ else
+ break
+ end
+ end
+ -- L4
+ if analyze_fences then
+ for i=1,size do
+ local entry = list[i]
+ if entry.level % 2 == 1 then -- odd(entry.level)
+ if entry.mirror and not entry.paired then
+ entry.mirror = false
+ end
+ -- okay
+ elseif entry.mirror then
+ entry.mirror = false
+ end
+ end
+ else
+ for i=1,size do
+ local entry = list[i]
+ if entry.level % 2 == 1 then -- odd(entry.level)
+ local mirror = mirrordata[entry.char]
+ if mirror then
+ entry.mirror = mirror
+ end
+ end
+ end
+ 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 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
+ while current do
+ if index > size then
+ report_directions("fatal error, size mismatch")
+ break
+ end
+ local id = getid(current)
+ 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
+ if id == glyph_code then
+ local mirror = entry.mirror
+ if mirror then
+ setchar(current,mirror)
+ end
+ if trace_directions then
+ local direction = entry.direction
+ if trace_list then
+ local original = entry.original
+ local char = entry.char
+ local level = entry.level
+ if direction == original then
+ report_directions("%2i : %C : %s",level,char,direction)
+ else
+ report_directions("%2i : %C : %s -> %s",level,char,original,direction)
+ end
+ end
+ setcolor(current,direction,false,mirror)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ setfield(current,"dir",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
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ enddir = false
+ done = true
+ end
+ elseif begindir then
+ if id == localpar_code 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
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head, current = insert_node_after(head,current,d)
+ 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
+ -- setfield(d,"attr",getfield(current,"attr"))
+ head = insert_node_before(head,current,d)
+ done = true
+ 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
+ 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
+ -- setfield(d,"attr",getfield(current,"attr"))
+ 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
+ if trace_list then
+ report_directions("stop run")
+ end
+ return head, done
+end
+
+local function process(head)
+ head = tonut(head)
+ -- 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
+ if not dirfound and trace_details then
+ report_directions("no initial direction found, gambling")
+ end
+ if trace_details then
+ report_directions("before : %s",show_list(list,size,"original"))
+ end
+ resolve_explicit(list,size,baselevel)
+ resolve_levels(list,size,baselevel,analyze_fences)
+ insert_dir_points(list,size)
+ if trace_details then
+ report_directions("after : %s",show_list(list,size,"direction"))
+ report_directions("result : %s",show_done(list,size))
+ end
+ head, done = apply_to_list(list,size,head,pardir)
+ return tonode(head), done
+end
+
+directions.installhandler(interfaces.variables.three,process)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua
new file mode 100644
index 00000000000..1e1a2c44a69
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua
@@ -0,0 +1,309 @@
+if not modules then modules = { } end modules ['typo-fln'] = {
+ version = 1.001,
+ comment = "companion to typo-fln.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- When I ran into the following experimental code again, I figured that it dated
+-- from the early days of mkiv, so I updates it a bit to fit into todays context.
+-- In the process I might have messed up things. For instance we had a diffent
+-- wrapper then using head and tail.
+
+-- todo: only letters (no punctuation)
+-- todo: nuts
+
+local trace_firstlines = false trackers.register("typesetters.firstlines", function(v) trace_firstlines = v end)
+local report_firstlines = logs.reporter("nodes","firstlines")
+
+typesetters.firstlines = typesetters.firstlines or { }
+local firstlines = typesetters.firstlines
+
+local nodes = nodes
+local tasks = nodes.tasks
+
+local context = context
+local implement = interfaces.implement
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getbox = nuts.getbox
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+
+local traverse_id = nuts.traverse_id
+local free_node_list = nuts.flush_list
+local free_node = nuts.flush_node
+local copy_node_list = nuts.copy_list
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+local hpack_node_list = nuts.hpack
+local remove_node = nuts.remove
+
+local nodepool = nuts.pool
+local newpenalty = nodepool.penalty
+local newkern = nodepool.kern
+local tracerrule = nodes.tracers.pool.nuts.rule
+
+local actions = { }
+firstlines.actions = actions
+
+local a_firstline = attributes.private('firstline')
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local variables = interfaces.variables
+local v_default = variables.default
+local v_line = variables.line
+local v_word = variables.word
+
+----- is_letter = characters.is_letter
+----- categories = characters.categories
+
+local settings = nil
+
+function firstlines.set(specification)
+ settings = specification or { }
+ tasks.enableaction("processors","typesetters.firstlines.handler")
+ if trace_firstlines then
+ report_firstlines("enabling firstlines")
+ end
+ texsetattribute(a_firstline,1)
+end
+
+implement {
+ name = "setfirstline",
+ actions = firstlines.set,
+ arguments = {
+ {
+ { "alternative" },
+ { "font", "integer" },
+ { "dynamic", "integer" },
+ { "ma", "integer" },
+ { "ca", "integer" },
+ { "ta", "integer" },
+ { "n", "integer" },
+ }
+ }
+}
+
+actions[v_line] = function(head,setting)
+ -- local attribute = fonts.specifiers.contextnumber(setting.feature) -- was experimental
+ local dynamic = setting.dynamic
+ local font = setting.font
+ local noflines = setting.n or 1
+ local ma = setting.ma or 0
+ local ca = setting.ca
+ local ta = setting.ta
+ local hangafter = tex.hangafter
+ local hangindent = tex.hangindent
+ local parindent = tex.parindent
+ local nofchars = 0
+ local n = 0
+ local temp = copy_node_list(head)
+ local linebreaks = { }
+ for g in traverse_id(glyph_code,temp) do
+ if dynamic > 0 then
+ setattr(g,0,dynamic)
+ end
+ setfield(g,"font",font)
+ end
+ local start = temp
+ local list = temp
+ local prev = temp
+ for i=1,noflines do
+ local hsize = tex.hsize - tex.leftskip.width - tex.rightskip.width
+ if i == 1 then
+ hsize = hsize - parindent
+ end
+ if i <= - hangafter then
+ hsize = hsize - hangindent
+ end
+ while start do
+ local id = getid(start)
+ if id == glyph_code then
+ n = n + 1
+ elseif id == disc_code then
+ -- this could be an option
+ elseif id == kern_code then -- todo: fontkern
+ -- this could be an option
+ elseif n > 0 then
+ local pack = hpack_node_list(copy_node_list(list,start))
+ if getfield(pack,"width") > hsize then
+ free_node_list(pack)
+ list = prev
+ break
+ else
+ linebreaks[i] = n
+ prev = start
+ free_node_list(pack)
+ nofchars = n
+ end
+ end
+ start = getnext(start)
+ end
+ if not linebreaks[i] then
+ linebreaks[i] = n
+ end
+ end
+ local start = head
+ local n = 0
+ for i=1,noflines do
+ local linebreak = linebreaks[i]
+ while start and n < nofchars do
+ local id = getid(start)
+ if id == glyph_code then -- or id == disc_code then
+ if dynamic > 0 then
+ setattr(start,0,dynamic)
+ end
+ setfield(start,"font",font)
+ if ca and ca > 0 then
+ setattr(start,a_colorspace,ma == 0 and 1 or ma)
+ setattr(start,a_color,ca)
+ end
+ if ta and ta > 0 then
+ setattr(start,a_transparency,ta)
+ end
+ n = n + 1
+ end
+ 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"))
+ end
+ head, start = insert_node_after(head,start,newpenalty(-10000)) -- break
+ break
+ end
+ start = getnext(start)
+ end
+ end
+ free_node_list(temp)
+ return head, true
+end
+
+actions[v_word] = function(head,setting)
+ -- local attribute = fonts.specifiers.contextnumber(setting.feature) -- was experimental
+ local dynamic = setting.dynamic
+ local font = setting.font
+ local words = 0
+ local nofwords = setting.n or 1
+ local start = head
+ local ok = false
+ local ma = setting.ma or 0
+ local ca = setting.ca
+ local ta = setting.ta
+ while start do
+ local id = getid(start)
+ -- todo: delete disc nodes
+ if id == glyph_code then
+ if not ok then
+ words = words + 1
+ ok = true
+ end
+ if ca and ca > 0 then
+ setattr(start,a_colorspace,ma == 0 and 1 or ma)
+ setattr(start,a_color,ca)
+ end
+ if ta and ta > 0 then
+ setattr(start,a_transparency,ta)
+ end
+ if dynamic > 0 then
+ setattr(start,0,dynamic)
+ end
+ setfield(start,"font",font)
+ elseif id == disc_code then
+ -- continue
+ elseif id == kern_code then -- todo: fontkern
+ -- continue
+ else
+ ok = false
+ if words == nofwords then
+ break
+ end
+ end
+ start = getnext(start)
+ end
+ return head, true
+end
+
+actions[v_default] = actions[v_line]
+
+function firstlines.handler(head)
+ head = tonut(head)
+ local start = head
+ local attr = nil
+ while start do
+ attr = getattr(start,a_firstline)
+ if attr then
+ break
+ elseif getid(start) == glyph_code then
+ break
+ else
+ start = getnext(start)
+ end
+ end
+ if attr then
+ -- here as we can process nested boxes first so we need to keep state
+ tasks.disableaction("processors","typesetters.firstlines.handler")
+ -- texsetattribute(attribute,unsetvalue)
+ local alternative = settings.alternative or v_default
+ local action = actions[alternative] or actions[v_default]
+ if action then
+ if trace_firstlines then
+ report_firstlines("processing firstlines, alternative %a",alternative)
+ end
+ local head, done = action(head,settings)
+ return tonode(head), done
+ end
+ end
+ return tonode(head), false
+end
+
+-- goodie
+
+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
+ list = remove_node(list,n)
+ done = n
+ break
+ end
+ if done then
+ setlist(tbox,list)
+ local kind = type(what)
+ if kind == "string" then
+ context[what](tonode(done))
+ elseif kind == "function" then
+ what(done)
+ else
+ -- error
+ end
+ end
+end
+
+implement {
+ name = "applytofirstcharacter",
+ actions = applytofirstcharacter,
+ arguments = { "integer", "string" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv
new file mode 100644
index 00000000000..e883c57d2a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv
@@ -0,0 +1,112 @@
+%D \module
+%D [ file=typo-fln,
+%D version=2013.08.22, % comes from the few years older m-newstuff
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=First Lines,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / First Lines}
+
+%D I had this code laying around for a while \unknown\ probably as a side effect
+%D of cleaning up the supp-fun modules. There is probably room for improvement
+%D and more features.
+
+% \setupbodyfont[pagella]
+%
+% \starttext
+%
+% \setupindenting[medium,yes]
+%
+% \definefirstline
+% [smallcaps]
+% [alternative=line,
+% color=darkred,
+% style=\setfontfeature{smallcaps}]
+%
+% \setfirstline[smallcaps] \input tufte \par
+% \setfirstline[smallcaps] \input ward \par
+% \setfirstline[smallcaps] \input knuth \par
+% \setfirstline[smallcaps] \input bryson \par
+%
+% \definefirstline
+% [smallcaps]
+% [alternative=word,
+% color=darkblue,
+% style=bold,
+% n=2]
+%
+% \setfirstline[smallcaps] \input tufte \par
+% \setfirstline[smallcaps] \input ward \par
+% \setfirstline[smallcaps] \input knuth \par
+% \setfirstline[smallcaps] \input bryson \par
+%
+% \stoptext
+
+\unprotect
+
+\registerctxluafile{typo-fln}{1.001}
+
+\definesystemattribute[firstline][public]
+
+\appendtoks
+ \attribute\firstlineattribute\attributeunsetvalue
+\to \everyforgetall
+
+\installcorenamespace {firstline}
+
+\installcommandhandler \??firstline {firstline} \??firstline
+
+\setupfirstline
+ [\c!alternative=\v!line,
+ %\c!style=,
+ %\c!color=,
+ \c!n=1]
+
+\unexpanded\def\setfirstline
+ {\dosingleempty\typo_firstline_set}
+
+\unexpanded\def\typo_firstline_set[#1]%
+ {\edef\typo_firstline_handle{\typo_firstline_handle_indeed{#1}}}
+
+\unexpanded\def\typo_firstline_handle_indeed#1%
+ {\dontleavehmode
+ \begingroup
+ \edef\currentfirstline{#1}%
+ \usefirstlinestyleandcolor\c!style\c!color
+ \clf_setfirstline
+ alternative {\firstlineparameter\c!alternative}%
+ ma \attribute\colormodelattribute
+ ca \attribute\colorattribute
+ ta \attribute\transparencyattribute
+ n \numexpr\firstlineparameter\c!n\relax
+ font \fontid\font
+ dynamic \attribute\zerocount
+ \relax
+ \kern\zeropoint % we need a node
+% \hskip\zeropoint\s!plus\emwidth\relax % can be an option
+ \endgroup
+ \globallet\typo_firstline_handle\relax}
+
+\let\typo_firstline_handle\relax
+
+% goodie, question on list
+%
+% \defineframed[ChapterFramed][location=low,background=color,backgroundcolor=red,frame=off]
+%
+% \setuphead[chapter][deeptextcommand=\applytofirstcharacter\ChapterFramed]
+
+\unexpanded\def\applytofirstcharacter#1%
+ {\begingroup
+ \dowithnextbox
+ {\clf_applytofirstcharacter\nextbox{\csstring#1}%
+ \unhbox\nextbox
+ \endgroup}%
+ \hbox}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-ini.lua
new file mode 100644
index 00000000000..c45d2966436
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-ini.lua
@@ -0,0 +1,11 @@
+if not modules then modules = { } end modules ['typo-ini'] = {
+ version = 1.001,
+ comment = "companion to typo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- nothing yet
+
+typesetters = typesetters or { }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-ini.mkiv
new file mode 100644
index 00000000000..1c2d6617a53
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-ini.mkiv
@@ -0,0 +1,49 @@
+%D \module
+%D [ file=typo-ini,
+%D version=2000.16.09,
+%D title=\CONTEXT\ Typographic Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Since \CONTEXT\ is dealing with typographics, isn't
+%D September 2000 a bit late to start writing this module? It
+%D may seem so, but since more and more languages are
+%D supported, we think it is time to isolate language specific
+%D typographic extensions in modules. The first language that
+%D demands this is Chinese, and more will follow.
+
+\writestatus{loading}{ConTeXt Typographic Macros / Initialization}
+
+\registerctxluafile{typo-ini}{1.001}
+
+\unprotect
+
+% This will be done differently:
+%
+% %D \macros
+% %D {ifvertical}
+% %D
+% %D The following switch can be used to signal macros that they
+% %D should adapt their behaviour.
+%
+% \newif\ifvertical % maybe also ifreverse
+%
+% %D \macros
+% %D {vhbox}
+% %D
+% %D A stupid but useful macro.
+%
+% \def\vhbox{\ifvertical\vbox\else\hbox\fi}
+
+%D \macros
+%D {everyresettypesetting}
+
+\newtoks\everyresettypesetting
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-inj.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-inj.lua
new file mode 100644
index 00000000000..786c3c2875a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-inj.lua
@@ -0,0 +1,98 @@
+if not modules then modules = { } end modules ['typo-inj'] = { -- was node-par
+ version = 1.001,
+ comment = "companion to typo-inj.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+
+local context = context
+local implement = interfaces.implement
+
+local injectors = { }
+typesetters.injectors = injectors
+local list = { }
+injectors.list = list
+local showall = false
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local variables = interfaces.variables
+local v_next = variables.next
+local v_previous = variables.previous
+
+local ctx_domarkinjector = context.domarkinjector
+local ctx_doactivateinjector = context.doactivateinjector
+
+table.setmetatableindex(list,function(t,k)
+ local v = {
+ counter = 0,
+ actions = { },
+ show = false,
+ active = false,
+ }
+ t[k] = v
+ return v
+end)
+
+function injectors.reset(name)
+ list[name] = nil
+end
+
+function injectors.set(name,numbers,command)
+ local injector = list[name]
+ local actions = injector.actions
+ local places = settings_to_array(numbers)
+ for i=1,#places do
+ actions[tonumber(places[i])] = command
+ end
+ if not injector.active then
+ ctx_doactivateinjector(name)
+ injector.active = true
+ end
+end
+
+function injectors.show(name)
+ if not name or name == "" then
+ showall = true
+ else
+ local list = settings_to_array(name)
+ for i=1,#list do
+ list[list[i]].show = true
+ end
+ end
+end
+
+function injectors.mark(name,show)
+ local injector = list[name]
+ local n = injector.counter + 1
+ injector.counter = n
+ if showall or injector.show then
+ ctx_domarkinjector(injector.actions[n] and 1 or 0,n)
+ end
+end
+
+function injectors.check(name,n) -- we could also accent n = number : +/- 2
+ local injector = list[name]
+ if not n or n == "" or n == v_next then
+ n = injector.counter + 1
+ elseif n == v_previous then
+ n = injector.counter
+ else
+ n = tonumber(n) or 0
+ end
+ local action = injector.actions[n]
+ if action then
+ context(action)
+ end
+end
+
+implement { name = "resetinjector", actions = injectors.reset, arguments = "string" }
+implement { name = "showinjector", actions = injectors.show, arguments = "string" }
+implement { name = "setinjector", actions = injectors.set, arguments = { "string", "string", "string" } }
+implement { name = "markinjector", actions = injectors.mark, arguments = "string" }
+implement { name = "checkinjector", actions = injectors.check, arguments = { "string", "string" } }
+--------- { name = "checkpreviousinjector", actions = injectors.check, arguments = { "string", tokens.constant(v_previous) } }
+--------- { name = "checknextinjector", actions = injectors.check, arguments = { "string", tokens.constant(v_next) } }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-inj.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-inj.mkiv
new file mode 100644
index 00000000000..59f35378fca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-inj.mkiv
@@ -0,0 +1,80 @@
+%D \module
+%D [ file=typo-inj,
+%D version=2014.10.13,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Triggering Actions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Triggering Actions}
+
+%D This is a sort of escape from too automatic typesetting of lists. I have
+%D been thinking fo a more generic injector for instance based on tags (as we
+%D already index each element) but thi sis sort of fuzzy because the number of a
+%D tag is not always incremented before we check for it. Also, registers and lists
+%D are among the few candidates that cannot be controlled directly by putting
+%D something in the input. So,m for the moment I stick to this mechanism but
+%D future versions of \CONTEXT\ might do it differently. Compatibility is not much
+%D of an issue here as this mechanism is only to be used in final production runs.
+
+\unprotect
+
+\registerctxluafile{typo-inj}{1.001}
+
+% todo: no need in trialmode
+
+%D \showinjector
+%D
+%D \setinjector[register][3][\column]
+%D \setinjector[list] [2][{\blank[3*big]}]
+%D
+%D \starttext
+%D \placelist[section][criterium=text]
+%D \blank[3*big]
+%D \placeregister[index][criterium=text]
+%D \page
+%D \startsection[title=Alpha] first \index{first} \stopsection
+%D \startsection[title=Beta] second \index{second} \stopsection
+%D \startsection[title=Gamma] third \index{third} \stopsection
+%D \startsection[title=Delta] fourth \index{fourth} \stopsection
+%D \stoptext
+
+\unexpanded\def\resetinjector [#1]{\clf_resetinjector{#1}}
+\unexpanded\def\markinjector [#1]{\dontleavehmode\clf_markinjector{#1}}
+\unexpanded\def\docheckinjector [#1][#2]{\clf_checkinjector{#1}{#2}}
+\unexpanded\def\checknextinjector [#1]{\clf_checkinjector{#1}{\v!next}}
+\unexpanded\def\checkpreviousinjector [#1]{\clf_checkinjector{#1}{\v!previous}}
+%unexpanded\def\checknextinjector [#1]{\clf_checknextinjector{#1}}
+%unexpanded\def\checkpreviousinjector [#1]{\clf_checkpreviousinjector{#1}}
+\unexpanded\def\dosetinjector [#1][#2][#3]{\clf_setinjector{#1}{#2}{#3}}
+\unexpanded\def\doshowinjector [#1]{\clf_showinjector{#1}}
+
+\unexpanded\def\checkinjector{\dodoubleempty \docheckinjector}
+\unexpanded\def\setinjector {\dotripleargument\dosetinjector}
+\unexpanded\def\showinjector {\dosingleempty \doshowinjector}
+
+\unexpanded\def\domarkinjector#1#2% called at the lua end
+ {\dontleavehmode\llap{\infofont\ifcase#1\else\red\fi<#2>\quad}}
+
+% low level definers .. we could have \injectors_mark and \injectors_check and then
+% use \v!list instead of \s!list
+
+\unexpanded\def\doinstallinjector#1%
+ {\letvalue{typo_injectors_mark_#1}\donothing
+ \letvalue{typo_injectors_check_#1}\donothing}
+
+\unexpanded\def\doactivateinjector#1% used at lua end
+ {\setuxvalue{typo_injectors_mark_#1}{\dontleavehmode\noexpand\clf_markinjector{#1}}%
+ \setuxvalue{typo_injectors_check_#1}{\noexpand\clf_checkinjector{#1}}}
+
+\unexpanded\def\dotestinjector#1% only for testing outside unprotect
+ {\csname typo_injectors_check_#1\endcsname
+ \csname typo_injectors_mark_#1\endcsname}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua
new file mode 100644
index 00000000000..cf54187d737
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua
@@ -0,0 +1,590 @@
+if not modules then modules = { } end modules ['typo-itc'] = {
+ version = 1.001,
+ comment = "companion to typo-itc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfchar = utf.char
+
+local trace_italics = false trackers.register("typesetters.italics", function(v) trace_italics = v end)
+local report_italics = logs.reporter("nodes","italics")
+
+local threshold = 0.5 trackers.register("typesetters.threshold", function(v) threshold = v == true and 0.5 or tonumber(v) end)
+
+typesetters.italics = typesetters.italics or { }
+local italics = typesetters.italics
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+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
+local setattr = nuts.setattr
+local setfield = nuts.setfield
+local setdisc = nuts.setdisc
+local isglyph = nuts.isglyph
+
+local insert_node_after = nuts.insert_after
+local delete_node = nuts.delete
+local end_of_math = nuts.end_of_math
+local find_tail = nuts.tail
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+local a_italics = attributes.private("italics")
+local a_mathitalics = attributes.private("mathitalics")
+
+local unsetvalue = attributes.unsetvalue
+
+local new_correction_kern = nodepool.italickern
+local new_correction_glue = nodepool.glue
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local italicsdata = fonthashes.italics
+local exheights = fonthashes.exheights
+
+local is_punctuation = characters.is_punctuation
+
+local implement = interfaces.implement
+
+local forcedvariant = false
+
+function typesetters.italics.forcevariant(variant)
+ forcedvariant = variant
+end
+
+-- We use the same key as the tex font handler. So, if a valua has already be set, we
+-- use that one.
+
+local function setitalicinfont(font,char)
+ local tfmdata = fontdata[font]
+ local character = tfmdata.characters[char]
+ if character then
+ local italic = character.italic
+ if not italic then
+ local autoitalicamount = tfmdata.properties.autoitalicamount or 0
+ if autoitalicamount ~= 0 then
+ local description = tfmdata.descriptions[char]
+ if description then
+ italic = description.italic
+ if not italic then
+ local boundingbox = description.boundingbox
+ italic = boundingbox[3] - description.width + autoitalicamount
+ if italic < 0 then -- < 0 indicates no overshoot or a very small auto italic
+ italic = 0
+ end
+ end
+ if italic ~= 0 then
+ italic = italic * tfmdata.parameters.hfactor
+ end
+ end
+ end
+ if trace_italics then
+ report_italics("setting italic correction of %C of font %a to %p",char,font,italic)
+ end
+ if not italic then
+ italic = 0
+ end
+ character.italic = italic
+ end
+ return italic
+ else
+ return 0
+ end
+end
+
+-- todo: clear attribute
+
+local function okay(data,current,font,prevchar,previtalic,char,what)
+ if not data then
+ if trace_italics then
+ report_italics("ignoring %p between %s italic %C and italic %C",previtalic,what,prevchar,char)
+ end
+ return false
+ end
+ if threshold then
+ local ht = getfield(current,"height")
+ 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
+ end
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and regular %C",previtalic,what,prevchar,char)
+ end
+ return true
+end
+
+-- maybe: with_attributes(current,n) :
+--
+-- local function correction_kern(kern,n)
+-- return with_attributes(new_correction_kern(kern),n)
+-- end
+
+local function correction_kern(kern,n)
+ local k = new_correction_kern(kern)
+ if n then
+ local a = getfield(n,"attr")
+ if a then -- maybe not
+ setfield(k,"attr",a) -- can be a marked content (border case)
+ end
+ end
+ return k
+end
+
+local function correction_glue(glue,n)
+ local g = new_correction_glue(glue)
+ if n then
+ local a = getfield(n,"attr")
+ if a then -- maybe not
+ setfield(g,"attr",a) -- can be a marked content (border case)
+ end
+ end
+ return g
+end
+
+function italics.handler(head)
+
+ local prev = nil
+ local prevchar = nil
+ local prevhead = tonut(head)
+ local previtalic = 0
+ local previnserted = nil
+
+ local pre = nil
+ local pretail = nil
+
+ local post = nil
+ local posttail = nil
+ local postchar = nil
+ local posthead = nil
+ local postitalic = 0
+ local postinserted = nil
+
+ local replace = nil
+ local replacetail = nil
+ local replacechar = nil
+ local replacehead = nil
+ local replaceitalic = 0
+ 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 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
+ report_italics("deleting last correction before %s %C",char,"glyph")
+ end
+ delete_node(prevhead,previnserted)
+ else
+ --
+ 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
+ if trace_italics then
+ report_italics("deleting last correction before %s %C","replace",char)
+ end
+ delete_node(replacehead,replaceinserted)
+ end
+ --
+ 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
+ if trace_italics then
+ report_italics("deleting last correction before %s %C","post",char)
+ end
+ delete_node(posthead,postinserted)
+ end
+ end
+ --
+ lastfont = font
+ end
+ if data then
+ local attr = forcedvariant or getattr(current,a_italics)
+ if attr and attr > 0 then
+ local cd = data[char]
+ if not cd then
+ -- this really can happen
+ previtalic = 0
+ else
+ previtalic = cd.italic
+ if not previtalic then
+ previtalic = setitalicinfont(font,char) -- calculated once
+ -- previtalic = 0
+ end
+ if previtalic ~= 0 then
+ lastfont = font
+ lastattr = attr
+ prev = current
+ -- prevhead = head
+ prevchar = char
+ end
+ end
+ else
+ previtalic = 0
+ end
+ else
+ previtalic = 0
+ end
+ previnserted = nil
+ replaceinserted = nil
+ postinserted = nil
+ elseif id == disc_code then
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ updated = false
+ pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
+ if replace then
+ local current = replacetail
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local font = getfont(current)
+ local data = italicsdata[font]
+ if data then
+ local attr = forcedvariant or getattr(current,a_italics)
+ if attr and attr > 0 then
+ local cd = data[char]
+ if not cd then
+ -- this really can happen
+ replaceitalic = 0
+ else
+ replaceitalic = cd.italic
+ if not replaceitalic then
+ replaceitalic = setitalicinfont(font,char) -- calculated once
+ -- replaceitalic = 0
+ end
+ if replaceitalic ~= 0 then
+ lastfont = font
+ lastattr = attr
+ replacechar = char
+ replacehead = replace
+ replace = current
+ updated = true
+ end
+ end
+ end
+ end
+ break
+ else
+ current = getprev(current)
+ end
+ end
+ end
+ if post then
+ local current = posttail
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local font = getfont(current)
+ local data = italicsdata[font]
+ if data then
+ local attr = forcedvariant or getattr(current,a_italics)
+ if attr and attr > 0 then
+ local cd = data[char]
+ if not cd then
+ -- this really can happen
+ -- postitalic = 0
+ else
+ postitalic = cd.italic
+ if not postitalic then
+ postitalic = setitalicinfont(font,char) -- calculated once
+ -- postitalic = 0
+ end
+ if postitalic ~= 0 then
+ lastfont = font
+ lastattr = attr
+ postchar = char
+ posthead = post
+ post = current
+ updated = true
+ end
+ end
+ end
+ end
+ break
+ else
+ current = getprev(current)
+ end
+ end
+ end
+ if updated then
+ setdisc(current,pre,post,replace)
+ end
+ elseif id == kern_code then -- how about fontkern ?
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ elseif id == glue_code then
+ if previtalic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and glue",previtalic,"glyph",prevchar)
+ 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
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and glue",replaceitalic,"replace",replacechar)
+ 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
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and glue",postitalic,"post",postchar)
+ end
+ postinserted = correction_kern(postitalic,current) -- needs to be a kern
+ postitalic = 0
+ done = true
+ insert_node_after(posthead,post,postinserted)
+ end
+ end
+ elseif id == math_code then
+ current = end_of_math(current)
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ local next = getnext(current)
+ if next then
+ local char, id = isglyph(next)
+ if char and is_punctuation[char] then
+ local kern = getprev(current)
+ if kern and getid(kern) == kern_code then
+ local glyph = getprev(kern)
+ if glyph and getid(glyph) == glyph_code then
+ local a = getattr(glyph,a_mathitalics)
+ if a == 101 then
+ local font = getfont(next)
+ local ex = exheights[font]
+ -- we need an extrat punctuation checker: . ; etc
+ if getfield(next,"height") < 1.25*ex then
+ if trace_italics then
+ report_italics("removing italic between math %C and punctuation %C",getchar(glyph),char)
+ end
+ setfield(kern,"kern",0) -- or maybe a small value or half the ic
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ if previtalic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and whatever",previtalic,"glyph",prevchar)
+ end
+ insert_node_after(prevhead,prev,correction_kern(previtalic,current))
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ done = true
+ else
+ if replaceitalic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and whatever",replaceritalic,"replace",replacechar)
+ end
+ insert_node_after(replacehead,replace,correction_kern(replaceitalic,current))
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ done = true
+ end
+ if postitalic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %p between %s italic %C and whatever",postitalic,"post",postchar)
+ end
+ insert_node_after(posthead,post,correction_kern(postitalic,current))
+ previnserted = nil
+ previtalic = 0
+ replaceinserted = nil
+ replaceitalic = 0
+ postinserted = nil
+ postitalic = 0
+ done = true
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ if lastattr and lastattr > 1 then -- more control is needed here
+ if previtalic ~= 0 then
+ if trace_italics then
+ 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
+end
+
+local enable
+
+enable = function()
+ tasks.enableaction("processors","typesetters.italics.handler")
+ if trace_italics then
+ report_italics("enabling text italics")
+ end
+ enable = false
+end
+
+function italics.set(n)
+ if enable then
+ enable()
+ end
+ if n == variables.reset then
+ texsetattribute(a_italics,unsetvalue)
+ else
+ texsetattribute(a_italics,tonumber(n) or unsetvalue)
+ end
+end
+
+function italics.reset()
+ texsetattribute(a_italics,unsetvalue)
+end
+
+implement {
+ name = "setitaliccorrection",
+ actions = italics.set,
+ arguments = "string"
+}
+
+implement {
+ name = "resetitaliccorrection",
+ actions = italics.reset,
+}
+
+local variables = interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local function setupitaliccorrection(option) -- no grouping !
+ if enable then
+ enable()
+ end
+ local options = settings_to_hash(option)
+ local variant = unsetvalue
+ if options[variables.text] then
+ variant = 1
+ elseif options[variables.always] then
+ variant = 2
+ end
+ -- maybe also keywords for threshold
+ if options[variables.global] then
+ forcedvariant = variant
+ texsetattribute(a_italics,unsetvalue)
+ else
+ forcedvariant = false
+ texsetattribute(a_italics,variant)
+ end
+ if trace_italics then
+ report_italics("forcing %a, variant %a",forcedvariant or "-",variant ~= unsetvalue and variant)
+ end
+end
+
+implement {
+ name = "setupitaliccorrection",
+ actions = setupitaliccorrection,
+ arguments = "string"
+}
+
+-- for manuals:
+
+local stack = { }
+
+implement {
+ name = "pushitaliccorrection",
+ actions = function()
+ table.insert(stack,{forcedvariant, texgetattribute(a_italics) })
+ end
+}
+
+implement {
+ name = "popitaliccorrection",
+ actions = function()
+ local top = table.remove(stack)
+ forcedvariant = top[1]
+ texsetattribute(a_italics,top[2])
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-itc.mkvi b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.mkvi
new file mode 100644
index 00000000000..b0d2673cd48
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.mkvi
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=typo-itc,
+%D version=2011.10.08,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Italic Correction,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Italics Corrections}
+
+\unprotect
+
+%D The brave might try:
+%D
+%D \starttyping
+%D \definefontfeature[default][default][itlc=yes,textitalics=yes]
+%D \setupitaliccorrection[global,always]
+%D \stoptyping
+
+\registerctxluafile{typo-itc}{1.001}
+
+\definesystemattribute[italics] [public]
+\definesystemattribute[mathitalics][public]
+
+% \let\/=/
+% \let\emphasiscorrection\donothing
+
+\ifdefined \normalitaliccorrection \else
+ \let\normalitaliccorrection\italiccorrection
+\fi
+
+\unexpanded\def\italiccorrection
+ {\ifnum\attribute\italicsattribute<\plusone\normalitaliccorrection\fi}
+
+\let\/\italiccorrection
+
+% 1 = end of word
+% 2 = end of word and end of a list
+
+\unexpanded\def\setitaliccorrection[#code]% rather low level (might go away)
+ {\clf_setitaliccorrection#code\relax}
+
+\unexpanded\def\resetitaliccorrection% rather low level (might go away)
+ {\clf_resetitaliccorrection}
+
+% global : no attributes, just always (faster and less memory)
+% text : only text
+% always : text and boxes
+% none : -
+
+\unexpanded\def\setupitaliccorrection[#settings]%
+ {\clf_setupitaliccorrection{#settings}}
+
+\appendtoks
+ \attribute\italicsattribute\attributeunsetvalue
+\to \everymathematics
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-itm.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-itm.mkiv
new file mode 100644
index 00000000000..0bb8170c721
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-itm.mkiv
@@ -0,0 +1,273 @@
+%D \module
+%D [ file=typo-itm, % comes from core-mis
+%D version=2012.06.28,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Item Lists,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Macros / Item Lists}
+
+\unprotect
+
+%D This is a real old mechanism that we once used for questionaries. As it is documented
+%D we keep it around. A more modern implementation would probably use another approach
+%D but I don't want to spend too much time on it now. There are a couple of changes:
+%D
+%D \startitemize
+%D \startitem textwidth sets the combined width \stopitem
+%D \startitem width sets the symbolwidth \stopitem
+%D \startitem alternative is used instead of location \stopitem
+%D \stopitemize
+%D
+%D \startbuffer
+%D \items[alternative=left]{a,b,c}
+%D \items[alternative=left,align=middle,textalign=flushright,distance=1em]{a,b,c}
+%D \items[alternative=right]{a,b,c}
+%D \items[alternative=inmargin]{a,b,c}
+%D \items[alternative=top]{a,b,c}
+%D \items[alternative=bottom]{a,b,c}
+%D \items[alternative=bottom,align=flushleft,textstyle=bold,color=red,textcolor=green]{a,b,c}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This renders as:
+%D
+%D \getbuffer
+
+\installcorenamespace{items}
+\installcorenamespace{itemsalternatives}
+\installcorenamespace{itemshorizontal}
+\installcorenamespace{itemsvertical}
+
+\installcommandhandler \??items {items} \??items
+
+\setupitems
+ [\c!alternative=\v!left,
+ \c!symbol=5,
+ \c!textwidth=\availablehsize,
+ \c!align=\v!middle,
+ \c!textalign=\v!flushleft,
+ \c!distance=\zeropoint,
+ %\c!n=,
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=\blank]
+
+\unexpanded\def\items
+ {\dosingleempty\typo_items_process}
+
+\newcount\c_typo_items_n
+\newcount\c_typo_items_m
+\newdimen\d_typo_items_text_width
+\newdimen\d_typo_items_symbol_width
+\newdimen\d_typo_items_distance
+\newbox \b_typo_items_symbols
+\newbox \b_typo_items_texts
+
+\def\typo_items_process[#1]#2%
+ {\bgroup
+ \setupitems[#1]%
+ \edef\p_typo_items_alternative{\itemsparameter\c!alternative}%
+ \ifcsname\??itemsalternatives\p_typo_items_alternative\endcsname \else
+ \let\p_typo_items_alternative\v!left
+ \fi
+ \let\currentitems\p_typo_items_alternative
+ \setupcurrentitems[#1]%
+ %
+ \edef\p_typo_items_textwidth{\itemsparameter\c!textwidth}%
+ \ifx\p_typo_items_textwidth\empty
+ \d_typo_items_text_width\availablehsize
+ \else
+ \d_typo_items_text_width\p_typo_items_textwidth\relax
+ \fi
+ %
+ \edef\p_typo_items_width{\itemsparameter\c!width}%
+ \ifx\p_typo_items_width\empty
+ \d_typo_items_symbol_width1.5\emwidth
+ \else
+ \d_typo_items_symbol_width\p_typo_items_width\relax
+ \fi
+ %
+ \edef\p_typo_items_distance{\itemsparameter\c!distance}%
+ \ifx\p_typo_items_distance\empty
+ \d_typo_items_distance\zeropoint
+ \else
+ \d_typo_items_distance\p_typo_items_distance\relax
+ \fi
+ %
+ \edef\p_typo_items_symbol{\itemsparameter\c!symbol}%
+ \ifx\p_typo_items_symbol\empty
+ \let\m_typo_items_symbol\firstofoneargument
+ \else\ifx\p_typo_items_symbol\v!none
+ \let\p_typo_items_symbol\empty
+ \let\m_typo_items_symbol\firstofoneargument
+ \else
+ \doifelseconversiondefined\p_typo_items_symbol
+ {\def\m_typo_items_symbol{\convertnumber\p_typo_items_symbol}}
+ {\doifelsesymboldefined\p_typo_items_symbol
+ {\def\m_typo_items_symbol{\symbol[\p_typo_items_symbol]\gobbleoneargument}}
+ {\let\m_typo_items_symbol\firstofoneargument}}%
+ \fi\fi
+ %
+ \edef\p_typo_items_align{\itemsparameter\c!align}%
+ \edef\p_typo_items_textalign{\itemsparameter\c!textalign}%
+ %
+ \edef\p_typo_items_n{\itemsparameter\c!n}%
+ \ifx\p_typo_items_n\empty
+ \getcommalistsize[#2]%
+ \c_typo_items_n\commalistsize\relax
+ \else
+ \c_typo_items_n\p_typo_items_n\relax
+ \fi
+ %
+ \parindent\zeropoint
+ \dontcomplain
+ %
+ \itemsparameter\c!before
+ \csname\??itemsalternatives\p_typo_items_alternative\endcsname{#2}%
+ \itemsparameter\c!after
+ \egroup}
+
+% rendering
+
+\setvalue{\??itemshorizontal\v!margin}#1%
+ {\ifnum\c_typo_items_m=\plusone\hss\else\hfill\fi
+ \strut#1%
+ \ifnum\c_typo_items_m=\c_typo_items_n\hss\else\hfill\fi}
+
+\setvalue{\??itemshorizontal\s!unknown}%
+ {\simplealignedbox\scratchwidth\m_typo_items_align}
+
+\def\typo_items_item_horizontal
+ {\advance\c_typo_items_m\plusone
+ \csname\??itemshorizontal
+ \ifcsname\??itemshorizontal\p_typo_items_align\endcsname
+ \p_typo_items_align
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\setvalue{\??itemsvertical\s!unknown}%
+ {\simplealignedbox\scratchwidth\m_typo_items_align}
+
+\def\typo_items_item_vertical
+ {\advance\c_typo_items_m\plusone
+ \csname\??itemsvertical
+ \ifcsname\??itemsvertical\p_typo_items_align\endcsname
+ \p_typo_items_align
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\def\typo_items_make_horizontal#1%
+ {\divide\scratchwidth\c_typo_items_n
+ \hbox{#1}}
+
+\def\typo_items_make_vertical#1%
+ {\vbox{#1}}
+
+\def\typo_items_construct_items_boxes#1%
+ {\setbox\b_typo_items_texts\hbox
+ {\c_typo_items_m\zerocount
+ \let\m_typo_items_align\p_typo_items_textalign
+ \scratchwidth\d_typo_items_text_width
+ \useitemsstyleandcolor\c!textstyle\c!textcolor
+ \typo_items_make{\processcommalist[#1]\typo_items_item}}%
+ \ifx\p_typo_items_symbol\empty
+ \setbox\b_typo_items_symbols\emptyhbox
+ \else
+ \setbox\b_typo_items_symbols\hbox
+ {\c_typo_items_m\zerocount
+ \let\m_typo_items_align\p_typo_items_align
+ \scratchwidth\d_typo_items_symbol_width
+ \useitemsstyleandcolor\c!style\c!color
+ \typo_items_make{\dorecurse\c_typo_items_n{\typo_items_item{\strut\m_typo_items_symbol\recurselevel}}}}%
+ \fi}
+
+% alternatives:
+
+\defineitems[\v!top][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align]
+
+\setvalue{\??itemsalternatives\v!top}#1%
+ {\let\typo_items_make\typo_items_make_horizontal
+ \let\typo_items_item\typo_items_item_horizontal
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\vbox\bgroup
+ \forgetall
+ \ifvoid\b_typo_items_symbols \else
+ \box\b_typo_items_symbols
+ \itemsparameter\c!inbetween
+ \nointerlineskip
+ \fi
+ \box\b_typo_items_texts\
+ \egroup}
+
+\defineitems[\v!bottom][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align]
+
+\setvalue{\??itemsalternatives\v!bottom}#1%
+ {\let\typo_items_make\typo_items_make_horizontal
+ \let\typo_items_item\typo_items_item_horizontal
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\vbox\bgroup
+ \forgetall
+ \box\b_typo_items_texts
+ \ifvoid\b_typo_items_symbols \else
+ \itemsparameter\c!inbetween
+ \nointerlineskip
+ \box\b_typo_items_symbols
+ \fi
+ \egroup}
+
+\defineitems[\v!inmargin][\c!width=1.5\emwidth,\c!align=\v!flushright,\c!distance=\leftmargindistance]
+
+\setvalue{\??itemsalternatives\v!inmargin}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \ifvoid\b_typo_items_symbols \else
+ \llap{\box\b_typo_items_symbols\hskip\d_typo_items_distance}%
+ \fi
+ \box\b_typo_items_texts
+ \egroup}
+
+\defineitems[\v!left][\c!width=1.5\emwidth,\c!align=\v!flushleft]
+
+\setvalue{\??itemsalternatives\v!left}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \ifvoid\b_typo_items_symbols \else
+ \box\b_typo_items_symbols
+ \kern\d_typo_items_distance
+ \fi
+ \box\b_typo_items_texts
+ \egroup}
+
+\defineitems[\v!right][\c!width=1.5\emwidth,\c!align=\v!flushright]
+
+\setvalue{\??itemsalternatives\v!right}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \box\b_typo_items_texts
+ \ifvoid\b_typo_items_symbols \else
+ \kern\d_typo_items_distance
+ \box\b_typo_items_symbols
+ \fi
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua
new file mode 100644
index 00000000000..7607fc5f509
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua
@@ -0,0 +1,638 @@
+if not modules then modules = { } end modules ['typo-krn'] = {
+ version = 1.001,
+ comment = "companion to typo-krn.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- glue is still somewhat suboptimal
+-- components: better split on tounicode
+
+local next, type, tonumber = next, type, tonumber
+local utfchar = utf.char
+
+local nodes = nodes
+local fonts = fonts
+
+local tasks = nodes.tasks
+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
+local free_node = nuts.free
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local end_of_math = nuts.end_of_math
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getid = nuts.getid
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getdisc = nuts.getdisc
+local isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setsubtype = nuts.setsubtype
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local setglue = nuts.setglue -- todo
+
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+local skipcodes = nodes.skipcodes
+local disccodes = nodes.disccodes
+local listcodes = nodes.listcodes
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+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 discretionary_code = disccodes.discretionary
+local automatic_code = disccodes.automatic
+
+local kerning_code = kerncodes.kerning
+local userkern_code = kerncodes.userkern
+local userskip_code = skipcodes.userskip
+local spaceskip_code = skipcodes.spaceskip
+local xspaceskip_code = skipcodes.xspaceskip
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
+local markdata = fonthashes.marks
+local fontproperties = fonthashes.properties
+local fontdescriptions = fonthashes.descriptions
+local fontfeatures = fonthashes.features
+
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local resetcolor = tracers.colors.reset
+
+local v_max = interfaces.variables.max
+local v_auto = interfaces.variables.auto
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.kerns = typesetters.kerns or { }
+local kerns = typesetters.kerns
+
+local report = logs.reporter("kerns")
+local trace_ligatures = false trackers.register("typesetters.kerns.ligatures",function(v) trace_ligatures = v end)
+
+-- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous
+
+local use_advance = false directives.register("typesetters.kerns.advance", function(v) use_advance = v end)
+
+kerns.mapping = kerns.mapping or { }
+kerns.factors = kerns.factors or { }
+local a_kerns = attributes.private("kern")
+local a_fontkern = attributes.private('fontkern')
+
+local contextsetups = fonts.specifiers.contextsetups
+
+storage.register("typesetters/kerns/mapping", kerns.mapping, "typesetters.kerns.mapping")
+storage.register("typesetters/kerns/factors", kerns.factors, "typesetters.kerns.factors")
+
+local mapping = kerns.mapping
+local factors = kerns.factors
+
+-- one must use liga=no and mode=base and kern=yes
+-- use more helpers
+-- make sure it runs after all others
+-- there will be a width adaptor field in nodes so this will change
+-- todo: interchar kerns / disc nodes / can be made faster
+-- todo: use insert_before etc
+
+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
+
+function kerns.keepligature(n) -- might become default
+ local f = getfont(n)
+ local a = getattr(n,0) or 0
+ if trace_ligatures then
+ local c = getchar(n)
+ local d = fontdescriptions[f][c].name
+ if a > 0 and contextsetups[a].keepligatures == v_auto then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"kept","dynamic","keepligatures")
+ setcolor(n,"darkred")
+ return true
+ end
+ local k = fontfeatures[f].keepligatures
+ if k == v_auto then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"kept","static","keepligatures")
+ setcolor(n,"darkgreen")
+ return true
+ end
+ if not k then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"split","static","keepligatures")
+ resetcolor(n)
+ return false
+ end
+ local k = fontproperties[f].keptligatures
+ if not k then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"split","no")
+ resetcolor(n)
+ return false
+ end
+ if k and k[c] then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"kept","by")
+ setcolor(n,"darkblue")
+ return true
+ else
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"split","by")
+ resetcolor(n)
+ return false
+ end
+ else
+ if a > 0 and contextsetups[a].keepligatures == v_auto then
+ return true
+ end
+ local k = fontfeatures[f].keepligatures
+ if k == v_auto then
+ return true
+ end
+ if not k then
+ return false
+ end
+ local k = fontproperties[f].keptligatures
+ if not k then
+ return false
+ end
+ if k and k[c] then
+ return true
+ end
+ end
+end
+
+-- can be optimized .. the prev thing .. but hardly worth the effort
+
+local function kern_injector(fillup,kern)
+ if fillup then
+ local g = new_glue(kern)
+ setfield(g,"stretch",kern)
+ setfield(g,"stretch_order",1)
+ return g
+ else
+ return new_kern(kern)
+ end
+end
+
+-- a simple list injector, no components and such .. just disable ligatures in
+-- kern mode .. maybe not even hyphenate ... anyway, the next one is for simple
+-- sublists .. beware: we can have char -1
+
+local function inject_begin(boundary,prev,keeptogether,krn,ok) -- prev is a glyph
+ local char, id = isglyph(boundary)
+ if id == kern_code then
+ if getsubtype(boundary) == kerning_code or getattr(boundary,a_fontkern) then
+ local inject = true
+ if keeptogether then
+ local next = getnext(boundary)
+ if not next or (getid(next) == glyph_code and keeptogether(prev,next)) then
+ inject = false
+ end
+ end
+ if inject then
+ -- not yet ok, as injected kerns can be overlays (from node-inj.lua)
+ setsubtype(boundary,userkern_code)
+ setfield(boundary,"kern",getfield(boundary,"kern") + quaddata[getfont(prev)]*krn)
+ return boundary, true
+ end
+ end
+ elseif char then
+ if keeptogether and keeptogether(boundary,prev) then
+ -- keep 'm
+ else
+ local prevchar = isglyph(prev)
+ if prevchar and prevchar > 0 then
+ local font = getfont(boundary)
+ local data = chardata[font][prevchar]
+ local kerns = data and data.kerns
+ local kern = new_kern((kerns and kerns[char] or 0) + quaddata[font]*krn)
+ setlink(kern,boundary)
+ return kern, true
+ end
+ end
+ end
+ return boundary, ok
+end
+
+local function inject_end(boundary,next,keeptogether,krn,ok)
+ local tail = find_node_tail(boundary)
+ local char, id = getid(tail)
+ if id == kern_code then
+ if getsubtype(tail) == kerning_code or getattr(tail,a_fontkern) then
+ local inject = true
+ if keeptogether then
+ local prev = getprev(tail)
+ if getid(prev) == glyph_code and keeptogether(prev,two) then
+ inject = false
+ end
+ end
+ if inject then
+ -- not yet ok, as injected kerns can be overlays (from node-inj.lua)
+ setsubtype(tail,userkern_code)
+ setfield(tail,"kern",getfield(tail,"kern") + quaddata[getfont(next)]*krn)
+ return boundary, true
+ end
+ end
+ elseif char then
+ if keeptogether and keeptogether(tail,two) then
+ -- keep 'm
+ else
+ local nextchar = isglyph(tail)
+ if nextchar and nextchar > 0 then
+ local font = getfont(tail)
+ local data = chardata[font][nextchar]
+ local kerns = data and data.kerns
+ local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn
+ insert_node_after(boundary,tail,new_kern(kern))
+ return boundary, true
+ end
+ end
+ end
+ return boundary, ok
+end
+
+local function process_list(head,keeptogether,krn,font,okay)
+ local start = head
+ local prev = nil
+ local pid = nil
+ local kern = 0
+ local mark = font and markdata[font]
+ while start do
+ local char, id = isglyph(start)
+ if char then
+ if not font then
+ font = getfont(start)
+ mark = markdata[font]
+ kern = quaddata[font]*krn
+ end
+ if prev then
+ if mark[char] then
+ -- skip
+ elseif pid == kern_code then
+ if getsubtype(prev) == kerning_code or getattr(prev,a_fontkern) then
+ local inject = true
+ if keeptogether then
+ local prevprev = getprev(prev)
+ if getid(prevprev) == glyph_code and keeptogether(prevprev,start) then
+ inject = false
+ end
+ end
+ if inject then
+ -- not yet ok, as injected kerns can be overlays (from node-inj.lua)
+ setsubtype(prev,userkern_code)
+ setfield(prev,"kern",getfield(prev,"kern") + kern)
+ okay = true
+ end
+ end
+ elseif pid == glyph_code then
+ if keeptogether and keeptogether(prev,start) then
+ -- keep 'm
+ else
+ local prevchar = getchar(prev)
+ local data = chardata[font][prevchar]
+ local kerns = data and data.kerns
+ -- if kerns then
+ -- print("it happens indeed, basemode kerns not yet injected")
+ -- end
+ insert_node_before(head,start,new_kern((kerns and kerns[char] or 0) + kern))
+ okay = true
+ end
+ end
+ end
+ end
+ if start then
+ prev = start
+ pid = id
+ start = getnext(start)
+ end
+ end
+ return head, okay, prev
+end
+
+local function closest_bound(b,get)
+ b = get(b)
+ if b and getid(b) ~= glue_code then
+ 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)
+ end
+ end
+ end
+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
+ 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 = getattr(start,a_kerns)
+ if attr and attr > 0 then
+ setattr(start,a_kerns,0) -- unsetvalue)
+ 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 -- we could use the subtype ligature
+ local c = getfield(start,"components")
+ if not c then
+ -- fine
+ elseif keepligature and keepligature(start) then
+ -- keep 'm
+ c = nil
+ else
+ while c do
+ local s = start
+ local t = find_node_tail(c)
+ local p, n = getboth(s)
+ if p then
+ setlink(p,c)
+ else
+ head = c
+ end
+ if n then
+ setlink(t,n)
+ end
+ start = c
+ setfield(s,"components",nil)
+ free_node(s)
+ c = getfield(start,"components")
+ end
+ end
+ local char = getchar(start)
+ local font = getfont(start)
+ local mark = markdata[font]
+ if not bound then
+ -- yet
+ elseif mark[char] then
+ -- skip
+ elseif previd == kern_code then
+ if getsubtype(prev) == kerning_code or getattr(prev,a_fontkern) 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)
+ setsubtype(prev,userkern_code)
+ setfield(prev,"kern",getfield(prev,"kern") + quaddata[font]*krn)
+ done = true
+ 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
+ if not fillup and use_advance then
+ setfield(prev,"xadvance",getfield(prev,"xadvance") + kern)
+ else
+ insert_node_before(head,start,kern_injector(fillup,kern))
+ end
+ 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
+ bound = true
+ elseif id == disc_code then
+ local prev, next, pglyph, nglyph -- delayed till needed
+ local subtype = getsubtype(start)
+ if subtype == automatic_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
+ prev = getprev(start)
+ pglyph = prev and getid(prev) == glyph_code
+ languages.expand(start,pglyph and prev)
+ end
+ local pre, post, replace = getdisc(start)
+ -- we really need to reasign the fields as luatex keeps track of
+ -- the tail in a temp preceding head .. kind of messy so we might
+ -- want to come up with a better solution some day like a real
+ -- pretail etc fields in a disc node
+ --
+ -- maybe i'll merge the now split functions
+ if pre then
+ local okay = false
+ if not prev then
+ prev = prev or 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
+ setfield(start,"pre",pre)
+ done = 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
+ setfield(start,"post",post)
+ done = true
+ end
+ end
+ if replace then
+ local okay = false
+ if not prev then
+ prev = prev or 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
+ setfield(start,"replace",replace)
+ done = true
+ end
+ elseif prevfont then
+ setfield(start,"replace",new_kern(quaddata[prevfont]*krn))
+ done = true
+ end
+ bound = false
+ elseif id == kern_code then
+ bound = getsubtype(start) == kerning_code or getattr(start,a_fontkern)
+ 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 w = getfield(start,"width")
+ if w > 0 then
+ local width = w + gluefactor * w * krn
+ local stretch = getfield(start,"stretch") * width / w
+ local shrink = getfield(start,"shrink") * width / w
+ if fillup then
+ stretch = 2 * stretch
+ shrink = 2 * shrink
+ setfield(start,"stretch_order",1)
+ -- shrink_order ?
+ end
+ setfield(start,"width",width)
+ setfield(start,"stretch",stretch)
+ setfield(start,"shrink", shrink)
+ --
+ 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
+ -- 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
+ 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) == kerning_code or getattr(start,a_fontkern)
+ prev = start
+ previd = id
+ start = getnext(start)
+ else
+ bound = false
+ start = getnext(start)
+ end
+ end
+ return tonode(head), done
+end
+
+local enabled = false
+
+function kerns.set(factor)
+ if factor ~= v_max then
+ factor = tonumber(factor) or 0
+ end
+ if factor == v_max or factor ~= 0 then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.kerns.handler")
+ enabled = true
+ end
+ local a = factors[factor]
+ if not a then
+ a = #mapping + 1
+ factors[factors], mapping[a] = a, factor
+ end
+ factor = a
+ else
+ factor = unsetvalue
+ end
+ texsetattribute(a_kerns,factor)
+ return factor
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setcharacterkerning",
+ actions = kerns.set,
+ arguments = "string"
+}
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-krn.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.mkiv
new file mode 100644
index 00000000000..6d6126542bf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.mkiv
@@ -0,0 +1,166 @@
+%D \module
+%D [ file=typo-krn,
+%D version=2009.03.27, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Spacing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Kerning}
+
+\unprotect
+
+\registerctxluafile{typo-krn}{1.001}
+
+\definesystemattribute[kern][public]
+
+% more
+%
+% {\setcharacterkerning[extrakerning]\input davis\relax}
+
+\installcorenamespace{characterkerning}
+
+\installcommandhandler \??characterkerning {characterkerning} \??characterkerning
+
+\unexpanded\def\setcharacterkerning[#1]%
+ {\edef\currentcharacterkerning{#1}%
+ \ifx\currentcharacterkerning\s!reset
+ \resetcharacterkerning
+ \else
+ \typo_kerning_set
+ \fi}
+
+\def\typo_kerning_set
+ {\usecharacterkerningstyleandcolor\c!style\c!color % goodie, maybe also strut
+ \useaddfontfeatureparameter\characterkerningparameter
+ \clf_setcharacterkerning{\characterkerningparameter\c!factor}}
+
+\unexpanded\def\resetcharacterkerning % fast one
+ {\attribute\kernattribute\attributeunsetvalue}
+
+\appendtoks
+ \resetcharacterkerning
+\to \everyresettypesetting
+
+\definecharacterkerning [extrakerning] [\c!factor=.125] % used in manuals
+
+%D Added after discussion on list (posted by WS, adapted abit by HH)
+%D \unknown\ this needs to be interfaced (\type {\v!kerncharacters}).
+%D
+%D \starttyping
+%D \setuphead[section][style=\sca,textstyle={\kerncharacters[.5]}] \section{Section}
+%D \stoptyping
+%D
+%D We could combine this with the previous definition command but
+%D then we always would get a command defined which is not beforehand
+%D a good idea.
+
+% Here we need to keep the groupedcommand solution as it is
+% used as modifier.
+
+% \definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
+% \definecharacterkerning [\v!letterspacing ] [\v!kerncharacters] [\c!features=letterspacing]
+%
+% \unexpanded\def\kerncharacters
+% {\doifnextoptionalcselse\typo_kerning_apply_yes\typo_kerning_apply_nop}
+%
+% \def\typo_kerning_apply_yes[#1]%
+% {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}}\donothing}
+%
+% \def\typo_kerning_apply_nop
+% {\groupedcommand\typo_kerning_apply_nop_indeed\donothing}
+%
+% \def\typo_kerning_apply_yes_indeed#1%
+% {\let\currentcharacterkerning\v!kerncharacters
+% \setupcurrentcharacterkerning[\c!factor=#1]%
+% \typo_kerning_set}
+%
+% \def\typo_kerning_apply_nop_indeed
+% {\let\currentcharacterkerning\v!kerncharacters
+% \typo_kerning_set}
+
+\appendtoks
+ \setuevalue{\currentcharacterkerning}%
+ {\doifelsenextoptional
+ {\typo_kerning_apply_yes{\currentcharacterkerning}}%
+ {\typo_kerning_apply_nop{\currentcharacterkerning}}}%
+\to \everydefinecharacterkerning
+
+\unexpanded\def\typo_kerning_apply_yes#1[#2]%
+ {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}{#2}}\donothing}
+
+\unexpanded\def\typo_kerning_apply_nop#1%
+ {\groupedcommand{\typo_kerning_apply_nop_indeed{#1}}\donothing}
+
+\def\typo_kerning_apply_yes_indeed#1#2%
+ {\edef\currentcharacterkerning{#1}%
+ \setupcurrentcharacterkerning[\c!factor=#2]%
+ \typo_kerning_set}
+
+\def\typo_kerning_apply_nop_indeed#1%
+ {\edef\currentcharacterkerning{#1}%
+ \typo_kerning_set}
+
+\definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
+\definecharacterkerning [\v!letterspacing ] [\v!kerncharacters] [\c!features=letterspacing]
+
+%D \macros
+%D {stretched}
+%D
+%D Stretching characters in a word is a sort of typographical
+%D murder. Nevertheless we support this manipulation for use in
+%D for instance titles.
+%D
+%D \starttyping
+%D \hbox to 5cm{\stretched{to the limit}}
+%D \stretched{to the limit}
+%D \stretched[width=10cm]{to the limit}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D \showsetup{stretched}
+%D
+%D This command replaces the old \MKII\ variant.
+
+\definecharacterkerning
+ [\v!stretched]
+ [\c!factor=\v!max,
+ \c!width=\availablehsize]
+
+\unexpanded\def\setupstretched
+ {\setupcharacterkerning[\v!stretched]}
+
+\unexpanded\def\stretched
+ {\dosingleempty\typo_kerning_stretched}
+
+\unexpanded\def\typo_kerning_stretched[#1]#2%
+ {\begingroup
+ \let\currentcharacterkerning\v!stretched
+ \iffirstargument
+ \setupcurrentcharacterkerning[#1]%
+ \fi
+ \edef\p_width{\characterkerningparameter\c!width}%
+ \ifx\p_width\empty \else
+ \hbox to \p_width
+ \fi
+ \bgroup
+ \usecharacterkerningstyleandcolor\c!style\c!color
+ \useaddfontfeatureparameter\characterkerningparameter
+ \typo_kerning_set
+ #2%
+ \egroup
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lan.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-lan.lua
new file mode 100644
index 00000000000..c42d2119eb6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lan.lua
@@ -0,0 +1,74 @@
+if not modules then modules = { } end modules ['typo-lan'] = {
+ version = 1.001,
+ comment = "companion to typo-lan.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next = type, next
+
+local currentfont = font.current
+local setmetatableindex = table.setmetatableindex
+local utfbyte = utf.byte
+
+local hashes = fonts.hashes
+local fontdata = hashes.characters
+local emwidths = hashes.emwidths
+
+local frequencies = languages.frequencies or { }
+languages.frequencies = frequencies
+
+local frequencydata = { }
+local frequencyfile = string.formatters["lang-frq-%s.lua"]
+local frequencycache = { }
+
+setmetatableindex(frequencydata, function(t,language)
+ local fullname = resolvers.findfile(frequencyfile(language))
+ local v = fullname ~= "" and dofile(fullname)
+ if not v or not v.frequencies then
+ v = t.en
+ end
+ t[language] = v
+ return v
+end)
+
+setmetatableindex(frequencycache, function(t,language)
+ local dataset = frequencydata[language]
+ local frequencies = dataset.frequencies
+ if not frequencies then
+ return t.en
+ end
+ local v = { }
+ setmetatableindex(v, function(t,font)
+ local average = emwidths[font] / 2
+ if frequencies then
+ local characters = fontdata[font]
+ local sum, tot = 0, 0
+ for k, v in next, frequencies do
+ local character = characters[k] -- characters[type(k) == "number" and k or utfbyte(k)]
+ tot = tot + v
+ sum = sum + v * (character and character.width or average)
+ end
+ average = sum / tot -- widths
+ end
+ t[font] = average
+ return average
+ end)
+ t[language] = v
+ return v
+end)
+
+function frequencies.getdata(language)
+ return frequencydata[language]
+end
+
+function frequencies.averagecharwidth(language,font)
+ return frequencycache[language or "en"][font or currentfont()]
+end
+
+interfaces.implement {
+ name = "averagecharwidth",
+ actions = { frequencies.averagecharwidth, context },
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lan.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-lan.mkiv
new file mode 100644
index 00000000000..6bc052b9989
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lan.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=typo-lan,
+%D version=2013.03.22,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Language Goodies,
+%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 Typography Macros / Languages}
+
+\unprotect
+
+\registerctxluafile{typo-lan}{1.001}
+
+%D \macros
+%D {averagecharwidth, charwidthlanguage}
+%D
+%D This is a more \MKIV-ish variant of lang-frq.mkiv. The methods are
+%D gone as one doesn't need the tables for them. The main macro is
+%D \type {\averagecharwidth} which behaves like a dimension register.
+%D
+%D I finally decided to reimplement this as I needed it for a manual
+%D (which is often a reason for such a rewrite). With some inspiring
+%D Porcupine Tree in the background it's not the worst thing to do.
+
+\def\charwidthlanguage{\currentmainlanguage}
+
+\def\averagecharwidth {\dimexpr\clf_averagecharwidth{\charwidthlanguage}\scaledpoint\relax}
+\def\languagecharwidth#1{\dimexpr\clf_averagecharwidth{#1}\scaledpoint\relax}
+
+\protect
+
+\continueifinputfile{typo-lan.mkiv}
+
+\setuplayout[backspace=4cm]
+
+\showframe
+
+\starttext
+
+\startbuffer
+
+\mainlanguage[en] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par
+\mainlanguage[de] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par
+\mainlanguage[nl] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par
+
+\stopbuffer
+
+\getbuffer \blank
+
+\switchtobodyfont[pagella]
+
+\getbuffer \blank
+
+\switchtobodyfont[tt,8pt]
+
+\getbuffer
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lig.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-lig.mkiv
new file mode 100644
index 00000000000..6171441d6d3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lig.mkiv
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=typo-lig,
+%D version=2014.12.01,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Ligatures,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Ligatures}
+
+%D This macro is mostly used for testing an attribute that blocks ligatures
+%D in the nodemode handler. It is not really used in practice, and mostly
+%D there as a plug in the generic font handler.
+
+\unprotect
+
+\definesystemattribute[noligature][public]
+
+\unexpanded\def\noligature#1%
+ {\dontleavehmode
+ \begingroup
+ \attribute\noligatureattribute\plusone
+ #1%
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua
new file mode 100644
index 00000000000..40a27dd3949
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua
@@ -0,0 +1,471 @@
+if not modules then modules = { } end modules ['typo-lin'] = {
+ version = 1.001,
+ comment = "companion to typo-lin.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code. The idea is to create an anchor point in a line but there are
+-- some considerations:
+--
+-- * if we normalize in order to have more easy access later on, we need to normalize all
+-- lines and we cannot catch all without losing efficiency
+--
+-- * if we normalize too soon, we might have issues with changed properties later on
+--
+-- * if we normalize too late, we have no knowledge of the current hsize
+--
+-- * if we always create an anchor we also create unwanted overhead if it is not used later
+-- on (more nodes)
+--
+-- The question is: do we mind of at the first access an anchor is created? As we cannot know
+-- that now, I choose some middle ground but this might change. if we don't assume direct
+-- access but only helpers, we can decide later.
+--
+-- Because of right2left mess it makes sense to use helpers so that we only need to deal with
+-- this mess once, in helpers. The more abstraction there the better. And so, after a week of
+-- experimenting, yet another abstraction was introduced.
+--
+-- The danger of adding the anchor later is that we adapt the head and so the caller needs to
+-- check that ... real messy. On the other hand, we soldom traverse the line. And other
+-- mechanisms can push stuff in front too. Actually that alone can mess up analysis when we
+-- delay too much. So in the end we need to accept the slow down.
+--
+-- We only need to normalize the left side because when we mess around we keep the page stream
+-- order (and adding content to the right of the line is a no-go for tagged etc. For the same
+-- reason we don't use two left anchors (each side fo leftskip) because there can be stretch.
+-- But, maybe there are good reasons for having just that anchor (mostly for educational purposes
+-- I guess.)
+--
+-- At this stage the localpar node is no longer of any use so we remove it (each line has the
+-- direction attached). We might at some point also strip the disc nodes as they no longer serve
+-- a purpose but that can better be a helper. Anchoring left has advantage of keeping page
+-- stream.
+--
+-- This looks a bit messy but we want to keep the box as it is so \showboxes still visualizes as
+-- expected. Normally left and rightskips end up in the line while hangindents become shifts and
+-- hsize corrections. We could normalize this to a line with
+
+-- indent : hlist type 3
+-- hangindent : shift and width
+
+local type = type
+
+local trace_anchors = false trackers.register("paragraphs.anchors", function(v) trace_anchors = v end)
+
+local report = logs.reporter("anchors")
+
+local nuts = nodes.nuts
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+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 localpar_code = nodecodes.localpar
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+local parfillskip_code = gluecodes.parfillskip
+
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local traverse_id = nuts.traverse_id
+local insert_before = nuts.insert_before
+local insert_after = nuts.insert_after
+local find_tail = nuts.tail
+----- remove_node = nuts.remove
+
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+
+local setprop = nuts.setprop
+local getprop = nuts.rawprop -- getprop
+
+local effectiveglue = nuts.effective_glue
+
+local nodepool = nuts.pool
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_leftskip = nodepool.leftskip
+local new_rightskip = nodepool.rightskip
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_rule = nodepool.rule
+local new_latelua = nodepool.latelua
+
+local texgetcount = tex.getcount
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local jobpositions = job.positions
+local getposition = jobpositions.get
+local getreserved = jobpositions.getreserved
+
+local paragraphs = { }
+typesetters.paragraphs = paragraphs
+
+local addskips = false
+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 = getfield(line,"shift") -- dangerous as it can be vertical as well
+ local reverse = getfield(line,"dir") == "TRT" or false
+ local pack = new_hlist()
+ local head = getlist(line)
+ local delta = 0
+ if reverse then
+ delta = - shift + (hsize - width)
+ else
+ delta = shift
+ end
+ local kern1 = new_kern(delta)
+ local kern2 = new_kern(-delta)
+ head = insert_before(head,head,kern1)
+ head = insert_before(head,head,pack)
+ head = insert_before(head,head,kern2)
+ setlist(line,head)
+ local where = {
+ pack = pack,
+ head = nil,
+ tail = nil,
+ }
+ prop.where = where
+ prop.reverse = reverse
+ prop.shift = shift
+ setmetatableindex(prop,nil)
+ return prop[key]
+end
+
+local function normalize(line,islocal) -- assumes prestine lines, nothing pre/appended
+ local oldhead = getlist(line)
+ local head = oldhead
+ local leftskip = nil
+ local rightskip = nil
+ local width = getfield(line,"width")
+ local hsize = islocal and width or tex.hsize
+ local lskip = 0
+ local rskip = 0
+ local pskip = 0
+ local current = head
+ local id = getid(current)
+ if id == glue_code then
+ local subtype = getsubtype(head)
+ if subtype == leftskip_code then
+ leftskip = head
+ lskip = getfield(head,"width") or 0
+ end
+ current = getnext(head)
+ id = getid(current)
+ end
+ -- no:
+ -- if id == localpar_code then
+ -- head = remove_node(head,head,true)
+ -- end
+ local tail = find_tail(head)
+ local current = tail
+ local id = getid(current)
+ if id == glue_code then
+ if getsubtype(current) == rightskip_code then
+ rightskip = tail
+ rskip = getfield(current,"width") or 0
+ current = getprev(tail)
+ id = getid(current)
+ end
+ if id == glue_code then
+ if getsubtype(current) == parfillskip_code then
+ pskip = effectiveglue(current,line)
+ end
+ end
+ end
+ if addskips then
+ if rightskip and not leftskip then
+ leftskip = new_leftskip(lskip)
+ head = insert_before(head,head,leftskip)
+ end
+ if leftskip and not rightskip then
+ rightskip = new_rightskip(0)
+ head, tail = insert_after(head,tail,rightskip)
+ end
+ end
+ if head ~= oldhead then
+ setlist(line,head)
+ end
+ noflines = noflines + 1
+ local prop = {
+ width = width,
+ hsize = hsize,
+ leftskip = lskip,
+ rightskip = rskip,
+ parfillskip = pskip,
+ line = line,
+ number = noflines,
+ }
+ setprop(line,"line",prop)
+ setmetatableindex(prop,finalize)
+ return prop
+end
+
+function paragraphs.checkline(n)
+ return getprop(n,"line") or normalize(n,true)
+end
+
+function paragraphs.normalize(head,islocal)
+ if texgetcount("pagebodymode") > 0 then
+ -- can be an option, maybe we need a proper state in lua itself ... is this check still needed?
+ return head, false
+ end
+ for line in traverse_id(hlist_code,tonut(head)) do
+ if getsubtype(line) == line_code and not getprop(line,"line") then
+ normalize(line)
+ end
+ end
+ return head, true
+end
+
+-- print(nodes.idstostring(head))
+
+-- We do only basic positioning and leave compensation for directions and distances
+-- to the caller as that one knows the circumstances better.
+
+-- todo: only in mvl or explicitly, e.g. framed or so, not in all lines
+
+local function addtoline(n,list,option)
+ local line = getprop(n,"line")
+ if not line then
+ line = normalize(n,true)
+ end
+ if line then
+ if trace_anchors and not line.traced then
+ line.traced = true
+ local rule = new_rule(2*65536,2*65536,1*65536)
+ local list = insert_before(rule,rule,new_kern(-1*65536))
+ addtoline(n,list)
+ local rule = new_rule(2*65536,6*65536,-3*65536)
+ local list = insert_before(rule,rule,new_kern(-1*65536))
+ addtoline(n,list,"internal")
+ else
+ line.traced = true
+ end
+ local list = tonut(list)
+ local where = line.where
+ local head = where.head
+ local tail = where.tail
+ local blob = new_hlist(list)
+ local delta = 0
+ if option == "internal" then
+ if line.reverse then
+ delta = line.shift - line.leftskip - (line.hsize - line.width)
+ else
+ delta = line.shift + line.leftskip
+ end
+ end
+ -- always kerns, also when 0 so that we can adapt but we can optimize if needed
+ -- by keeping a hash as long as we use the shiftinline helper .. no need to
+ -- optimize now .. we can also decide to put each blob in a hlist
+ local kern = new_kern(delta)
+ if tail then
+ head, tail = insert_after(head,tail,kern)
+ else
+ head, tail = kern, kern
+ setlist(where.pack,head)
+ end
+ head, tail = insert_after(head,tail,blob)
+ local kern = new_kern(-delta)
+ head, tail = insert_after(head,tail,kern)
+ --
+ where.head = head
+ where.tail = tail
+ return line, blob
+ else
+ -- report("unknown anchor")
+ end
+end
+
+local function addanchortoline(n,anchor)
+ local line = type(n) ~= "table" and getprop(n,"line") or n
+ if not line then
+ line = normalize(n,true)
+ end
+ if line then
+ local anchor = tonut(anchor)
+ local where = line.where
+ if trace_anchors then
+ local rule1 = new_rule(65536/2,4*65536,4*65536)
+ local rule2 = new_rule(8*65536,65536/4,65536/4)
+ local kern1 = new_kern(-65536/4)
+ local kern2 = new_kern(-65536/4-4*65536)
+ anchor = new_hlist(nuts.link { anchor, kern1, rule1, kern2, rule2 })
+ setfield(anchor,"width",0)
+ end
+ if where.tail then
+ local head = where.head
+ insert_before(head,head,anchor)
+ else
+ where.tail = anchor
+ end
+ setlist(where.pack,anchor)
+ where.head = anchor
+ return line
+ end
+end
+
+paragraphs.addtoline = addtoline
+paragraphs.addanchortoline = addanchortoline
+
+function paragraphs.moveinline(n,blob,dx,dy)
+ if not blob then
+ return
+ end
+ if not dx then
+ dx = 0
+ end
+ if not dy then
+ dy = 0
+ end
+ if dx ~= 0 or dy ~= 0 then
+ local line = type(n) ~= "table" and getprop(n,"line") or n
+ if line then
+ if dx ~= 0 then
+ local prev, next = getboth(blob)
+ if prev and getid(prev) == kern_code then
+ setfield(prev,"kern",getfield(prev,"kern") + dx)
+ end
+ if next and getid(next) == kern_code then
+ setfield(next,"kern",getfield(next,"kern") - dx)
+ end
+ end
+ if dy ~= 0 then
+ if getid(blob) == hlist_code then
+ setfield(blob,"shift",getfield(blob,"shift") + dy)
+ end
+ end
+ else
+-- report("no line")
+ end
+ end
+end
+
+local f_anchor = formatters["_plib_.set('md:h',%i,{x=true,c=true})"]
+local s_anchor = 'md:h'
+
+local function setanchor(h_anchor)
+ return new_latelua(f_anchor(h_anchor))
+end
+
+-- local t_anchor = { x = true, c = true }
+--
+-- local function setanchor(h_anchor)
+-- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end)
+-- end
+
+function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area)
+ local line = type(n) ~= "table" and getprop(n,"line") or n
+ if not line then
+ line = normalize(n,true)
+ end
+ local hmove = 0
+ if line then
+ local reverse = line.reverse
+ -- basic hsize based anchoring
+ if atleft then
+ if reverse then
+ -- delta = delta
+ else
+ delta = - delta - width
+ end
+ else
+ if reverse then
+ delta = - delta - width - line.hsize
+ else
+ delta = delta + line.hsize
+ end
+ end
+ if islocal then
+ -- relative to hsize with leftskip / rightskip compensation
+ if atleft then
+ if reverse then
+ delta = delta - line.leftskip
+ else
+ delta = delta + line.leftskip
+ end
+ else
+ if reverse then
+ delta = delta + line.rightskip
+ else
+ delta = delta - line.rightskip
+ end
+ end
+ if followshape then
+ -- shape compensation
+ if atleft then
+ if reverse then
+ delta = delta + line.shift - line.hsize + line.width
+ else
+ delta = delta + line.shift
+ end
+ else
+ if reverse then
+ delta = delta + line.shift + line.parfillskip
+ else
+ delta = delta + line.shift - line.hsize + line.width - line.parfillskip
+ end
+ end
+ end
+ end
+ if area then
+ local number = line.number
+ if not line.hanchor then
+ addanchortoline(line,setanchor(number))
+ line.hanchor = true
+ end
+ local blob = getposition(s_anchor,number)
+ if blob then
+ local reference = getreserved(area,blob.c)
+ if reference then
+ hmove = (reference.x or 0) - (blob.x or 0)
+ if atleft then
+ if reverse then
+ hmove = hmove + (reference.w or 0)
+ else
+ -- hmove = hmove
+ end
+ else
+ if reverse then
+ hmove = hmove + line.hsize
+ else
+ hmove = hmove + (reference.w or 0) - line.hsize
+ end
+ end
+ end
+ end
+ end
+ end
+ return delta, hmove
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lin.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.mkiv
new file mode 100644
index 00000000000..eba08b4c8ba
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=typo-lin,
+%D version=2015.08.01,
+%D title=\CONTEXT\ Typographic Macros,
+%D subtitle=Line Normalization,
+%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 Typographic Macros / Normalization}
+
+%D Beware: the mvl callback is also called when a line is added to a vbox.
+
+\registerctxluafile{typo-lin}{1.001}
+
+\unprotect
+
+% nothing yet / experimental
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-man.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-man.lua
new file mode 100644
index 00000000000..6c6d7926f37
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-man.lua
@@ -0,0 +1,113 @@
+if not modules then modules = { } end modules ['typo-man'] = {
+ version = 1.001,
+ comment = "companion to typo-prc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not characters then
+ -- for testing stand-alone
+ require("char-def")
+ require("char-ini")
+end
+
+local lpegmatch = lpeg.match
+local P, R, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local global = global or _G
+
+local methods = {
+ uppercase = characters.upper,
+ lowercase = characters.lower,
+ Word = converters.Word,
+ Words = converters.Words,
+}
+
+local function nothing(s) return s end -- we already have that one somewhere
+
+-- table.setmetatableindex(methods,function(t,k)
+-- t[k] = nothing
+-- return nothing
+-- end)
+
+local splitter = lpeg.tsplitat(".")
+
+table.setmetatableindex(methods,function(t,k)
+ local s = lpegmatch(splitter,k)
+ local v = global
+ for i=1,#s do
+ v = v[s[i]]
+ if not v then
+ break
+ end
+ end
+ if not v or v == global then
+ v = nothing
+ end
+ t[k] = v
+ return v
+end)
+
+local whitespace = lpeg.patterns.whitespace^0
+local separator = whitespace * P("->") * whitespace
+local pair = C((1-separator)^1) * separator * C(P(1)^0)
+local list = Ct((C((1-separator)^1) * separator)^1) * C(P(1)^0)
+
+local pattern = Carg(1) * pair / function(methods,operation,str)
+ return methods[operation](str) or str
+end
+
+local function apply(str,m)
+ return lpegmatch(pattern,str,1,m or methods) or str
+end
+
+local function splitspecification(field,m)
+ local m, f = lpegmatch(list,field,1,m or methods)
+ if m then
+ return m, f or field
+ else
+ return nil, field
+ end
+end
+
+local function applyspecification(actions,str)
+ if actions then
+ for i=1,#actions do
+ local action = methods[actions[i]]
+ if action then
+ str = action(str) or str
+ end
+ end
+ end
+ return str
+end
+
+if not typesetters then typesetters = { } end
+
+typesetters.manipulators = {
+ methods = methods,
+ apply = apply,
+ patterns = {
+ pair = pair,
+ list = list,
+ },
+ splitspecification = splitspecification,
+ applyspecification = applyspecification,
+}
+
+local pattern = Cs((1 - P(1) * P(-1))^0 * (P(".")/"" + P(1)))
+
+methods.stripperiod = function(str) return lpegmatch(pattern,str) end
+
+-- print(apply("hans"))
+-- print(apply("uppercase->hans"))
+-- print(apply("string.reverse -> hans"))
+-- print(apply("uppercase->hans",{ uppercase = string.reverse } ))
+
+-- print(applyspecification(splitspecification("hans")))
+-- print(applyspecification(splitspecification("lowercase->uppercase->hans")))
+-- print(applyspecification(splitspecification("uppercase->stripperiod->hans.")))
+
+function commands.manipulated(str)
+ context(apply(str))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua
new file mode 100644
index 00000000000..cdb4d544cee
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua
@@ -0,0 +1,999 @@
+if not modules then modules = { } end modules ['typo-mar'] = {
+ version = 1.001,
+ comment = "companion to typo-mar.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo:
+--
+-- * autoleft/right depending on available space (or distance to margin)
+-- * stack across paragraphs, but that is messy and one should reconsider
+-- using margin data then as also vertical spacing kicks in
+-- * floating margin data, with close-to-call anchoring
+
+-- -- experiment (does not work, too much interference)
+--
+-- local pdfprint = pdf.print
+-- local format = string.format
+--
+-- anchors = anchors or { }
+--
+-- local whatever = { }
+-- local factor = (7200/7227)/65536
+--
+-- function anchors.set(tag)
+-- whatever[tag] = { pdf.h, pdf.v }
+-- end
+--
+-- function anchors.reset(tag)
+-- whatever[tag] = nil
+-- end
+--
+-- function anchors.startmove(tag,how) -- save/restore nodes but they don't support moves
+-- local w = whatever[tag]
+-- if not w then
+-- -- error
+-- elseif how == "horizontal" or how == "h" then
+-- pdfprint("page",format(" q 1 0 0 1 %f 0 cm ", (w[1] - pdf.h) * factor))
+-- elseif how == "vertical" or how == "v" then
+-- pdfprint("page",format(" q 1 0 0 1 0 %f cm ", (w[2] - pdf.v) * factor))
+-- else
+-- pdfprint("page",format(" q 1 0 0 1 %f %f cm ", (w[1] - pdf.h) * factor, (w[2] - pdf.v) * factor))
+-- end
+-- end
+--
+-- function anchors.stopmove(tag)
+-- local w = whatever[tag]
+-- if not w then
+-- -- error
+-- else
+-- pdfprint("page"," Q ")
+-- end
+-- end
+--
+-- local latelua = nodes.pool.latelua
+--
+-- function anchors.node_set(tag)
+-- return latelua(formatters["anchors.set(%q)"](tag))
+-- end
+--
+-- function anchors.node_reset(tag)
+-- return latelua(formatters["anchors.reset(%q)"](tag))
+-- end
+--
+-- function anchors.node_start_move(tag,how)
+-- return latelua(formatters["anchors.startmove(%q,%q)](tag,how))
+-- end
+--
+-- function anchors.node_stop_move(tag)
+-- return latelua(formatters["anchors.stopmove(%q)"](tag))
+-- end
+
+-- so far
+
+local format, validstring = string.format, string.valid
+local insert, remove = table.insert, table.remove
+local setmetatable, next = setmetatable, next
+local formatters = string.formatters
+local toboolean = toboolean
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local attributes, nodes, node, variables = attributes, nodes, node, variables
+
+local trace_margindata = false trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
+local trace_marginstack = false trackers.register("typesetters.margindata.stack", function(v) trace_marginstack = v end)
+local trace_margingroup = false trackers.register("typesetters.margindata.group", function(v) trace_margingroup = v end)
+
+local report_margindata = logs.reporter("typesetters","margindata")
+
+local tasks = nodes.tasks
+local prependaction = tasks.prependaction
+local disableaction = tasks.disableaction
+local enableaction = tasks.enableaction
+
+local variables = interfaces.variables
+
+local conditionals = tex.conditionals
+local systemmodes = tex.systemmodes
+
+local v_top = variables.top
+local v_depth = variables.depth
+local v_local = variables["local"]
+local v_global = variables["global"]
+local v_left = variables.left
+local v_right = variables.right
+local v_flushleft = variables.flushleft
+local v_flushright = variables.flushright
+local v_inner = variables.inner
+local v_outer = variables.outer
+local v_margin = variables.margin
+local v_edge = variables.edge
+local v_default = variables.default
+local v_normal = variables.normal
+local v_yes = variables.yes
+local v_continue = variables.continue
+local v_first = variables.first
+local v_text = variables.text
+local v_paragraph = variables.paragraph
+local v_column = variables.column
+local v_line = variables.line
+local v_hanging = variables.hanging
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local copy_node_list = nuts.copy_list
+local hpack_nodes = nuts.hpack
+local traverse_id = nuts.traverse_id
+local free_node_list = nuts.flush_list
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+local linked_nodes = nuts.linked
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
+local gluecodes = nodes.gluecodes
+local whatsitcodes = nodes.whatsitcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+local whatsit_code = nodecodes.whatsit
+local line_code = listcodes.line
+local cell_code = listcodes.cell
+local alignment_code = listcodes.alignment
+local userdefined_code = whatsitcodes.userdefined
+
+local nodepool = nuts.pool
+
+local new_kern = nodepool.kern
+local new_usernumber = nodepool.usernumber
+local new_latelua = nodepool.latelua
+
+local lateluafunction = nodepool.lateluafunction
+
+local texgetcount = tex.getcount
+local texgetdimen = tex.getdimen
+local texget = tex.get
+
+local isleftpage = layouts.status.isleftpage
+local registertogether = builders.paragraphs.registertogether -- tonode
+
+local paragraphs = typesetters.paragraphs
+local addtoline = paragraphs.addtoline
+local moveinline = paragraphs.moveinline
+local calculatedelta = paragraphs.calculatedelta
+
+local a_margindata = attributes.private("margindata")
+local a_specialcontent = attributes.private("specialcontent")
+local a_linenumber = attributes.private('linenumber')
+
+local inline_mark = nodepool.userids["margins.inline"]
+
+local jobpositions = job.positions
+local getposition = jobpositions.get
+local setposition = jobpositions.set
+local getreserved = jobpositions.getreserved
+
+local margins = { }
+typesetters.margins = margins
+
+local locations = { v_left, v_right, v_inner, v_outer } -- order might change
+local categories = { }
+local displaystore = { } -- [category][location][scope]
+local inlinestore = { } -- [number]
+local nofsaved = 0
+local nofstored = 0
+local nofinlined = 0
+local nofdelayed = 0
+local h_anchors = 0
+local v_anchors = 0
+
+local mt1 = {
+ __index = function(t,location)
+ local v = { [v_local] = { }, [v_global] = { } }
+ t[location] = v
+ return v
+ end
+}
+
+local mt2 = {
+ __index = function(stores,category)
+ categories[#categories+1] = category
+ local v = { }
+ setmetatable(v,mt1)
+ stores[category] = v
+ return v
+ end
+}
+
+setmetatable(displaystore,mt2)
+
+local defaults = {
+ __index = {
+ location = v_left,
+ align = v_normal,
+ method = "",
+ name = "",
+ threshold = 0, -- .25ex
+ margin = v_normal,
+ scope = v_global,
+ distance = 0,
+ hoffset = 0,
+ voffset = 0,
+ category = v_default,
+ line = 0,
+ vstack = 0,
+ dy = 0,
+ baseline = false,
+ inline = false,
+ leftskip = 0,
+ rightskip = 0,
+ option = { }
+ }
+}
+
+local enablelocal, enableglobal -- forward reference (delayed initialization)
+
+local function showstore(store,banner,location)
+ if next(store) then
+ for i, si in table.sortedpairs(store) do
+ local si =store[i]
+ report_margindata("%s: stored in %a at %s: %a => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(getlist(si.box)))
+ end
+ else
+ report_margindata("%s: nothing stored in location %a",banner,location)
+ end
+end
+
+function margins.save(t)
+ setmetatable(t,defaults)
+ local content = getbox(t.number)
+setattr(content,a_specialcontent,1) -- todo: a property
+ local location = t.location
+ local category = t.category
+ local inline = t.inline
+ local scope = t.scope
+ local name = t.name
+ local option = t.option
+ if option then
+ option = settings_to_hash(option)
+ t.option = option
+ end
+ if not content then
+ report_margindata("ignoring empty margin data %a",location or "unknown")
+ return
+ end
+ local store
+ if inline then
+ store = inlinestore
+ else
+ store = displaystore[category][location]
+ if not store then
+ report_margindata("invalid location %a",location)
+ return
+ end
+ store = store[scope]
+ end
+ if not store then
+ report_margindata("invalid scope %a",scope)
+ return
+ end
+ if enablelocal and scope == v_local then
+ enablelocal()
+ if enableglobal then
+ enableglobal() -- is the fallback
+ end
+ elseif enableglobal and scope == v_global then
+ enableglobal()
+ end
+ nofsaved = nofsaved + 1
+ nofstored = nofstored + 1
+ if trace_marginstack then
+ showstore(store,"before",location)
+ end
+ if name and name ~= "" then
+ if inlinestore then -- todo: inline store has to be done differently (not sparse)
+ local t = table.sortedkeys(store) for j=#t,1,-1 do local i = t[j]
+ local si = store[i]
+ if si.name == name then
+ local s = remove(store,i)
+ free_node_list(s.box)
+ end
+ end
+ else
+ for i=#store,1,-1 do
+ local si = store[i]
+ if si.name == name then
+ local s = remove(store,i)
+ free_node_list(s.box)
+ end
+ end
+ end
+ if trace_marginstack then
+ showstore(store,"between",location)
+ end
+ end
+ if t.number then
+ local leftmargindistance = texgetdimen("naturalleftmargindistance")
+ local rightmargindistance = texgetdimen("naturalrightmargindistance")
+ local strutbox = getbox("strutbox")
+ -- better make a new table and make t entry in t
+ t.box = copy_node_list(content)
+ t.n = nofsaved
+ -- used later (we will clean up this natural mess later)
+ -- nice is to make a special status table mechanism
+ t.strutdepth = getfield(strutbox,"depth")
+ t.strutheight = getfield(strutbox,"height")
+ -- beware: can be different from the applied one
+ t.leftskip = getfield(texget("leftskip"),"width") -- we're not in forgetall
+ t.rightskip = getfield(texget("rightskip"),"width") -- we're not in forgetall
+ --
+ t.leftmargindistance = leftmargindistance -- todo:layoutstatus table
+ t.rightmargindistance = rightmargindistance
+ t.leftedgedistance = texgetdimen("naturalleftedgedistance")
+ + texgetdimen("leftmarginwidth")
+ + leftmargindistance
+ t.rightedgedistance = texgetdimen("naturalrightedgedistance")
+ + texgetdimen("rightmarginwidth")
+ + rightmargindistance
+ t.lineheight = texgetdimen("lineheight")
+ --
+ -- t.realpageno = texgetcount("realpageno")
+ if inline then
+ context(tonode(new_usernumber(inline_mark,nofsaved))) -- or use a normal node
+ store[nofsaved] = t -- no insert
+ nofinlined = nofinlined + 1
+ else
+ insert(store,t)
+ end
+ end
+ if trace_marginstack then
+ showstore(store,"after",location)
+ end
+ if trace_margindata then
+ report_margindata("saved %a, location %a, scope %a, inline %a",nofsaved,location,scope,inline)
+ end
+end
+
+-- Actually it's an advantage to have them all anchored left (tags and such)
+-- we could keep them in store and flush in stage two but we might want to
+-- do more before that so we need the content to be there unless we can be
+-- sure that we flush this first which might not be the case in the future.
+--
+-- When the prototype inner/outer code that was part of this proved to be
+-- okay it was moved elsewhere.
+
+local status, nofstatus = { }, 0
+
+-- local f_anchor = formatters["_plib_.set('md:h',%i,{x=true,c=true})"]
+-- local s_anchor = 'md:h'
+--
+-- local function setanchor(h_anchor)
+-- return new_latelua(f_anchor(h_anchor))
+-- end
+
+-- local t_anchor = { x = true, c = true }
+--
+-- local function setanchor(h_anchor)
+-- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end)
+-- end
+
+local function realign(current,candidate)
+ local location = candidate.location
+ local margin = candidate.margin
+ local hoffset = candidate.hoffset
+ local distance = candidate.distance
+ local hsize = candidate.hsize
+ local width = candidate.width
+ local align = candidate.align
+ local inline = candidate.inline
+ local anchor = candidate.anchor
+ local hook = candidate.hook
+ local scope = candidate.scope
+ local option = candidate.option
+ local reverse = hook.reverse
+ local atleft = true
+ local hmove = 0
+ local delta = 0
+ -- local realpageno = candidate.realpageno
+ local leftpage = isleftpage(false,true)
+ local leftdelta = 0
+ local rightdelta = 0
+ local leftdistance = distance
+ local rightdistance = distance
+ --
+ if not anchor or anchor == "" then
+ anchor = v_text -- this has to become more clever: region:0|column:n|column
+ end
+ if margin == v_normal then
+ --
+ elseif margin == v_local then
+ leftdelta = - candidate.leftskip
+ rightdelta = candidate.rightskip
+ elseif margin == v_margin then
+ leftdistance = candidate.leftmargindistance
+ rightdistance = candidate.rightmargindistance
+ elseif margin == v_edge then
+ leftdistance = candidate.leftedgedistance
+ rightdistance = candidate.rightedgedistance
+ end
+ if leftpage then
+ leftdistance, rightdistance = rightdistance, leftdistance
+ end
+ if location == v_right then
+ atleft = false
+ elseif location == v_inner then
+ if leftpage then
+ atleft = false
+ end
+ elseif location == v_outer then
+ if not leftpage then
+ atleft = false
+ end
+ end
+
+ local islocal = scope == v_local
+ local area = (not islocal or option[v_text]) and anchor or nil
+
+ if atleft then
+ delta = hoffset + leftdelta + leftdistance
+ else
+ delta = hoffset + rightdelta + rightdistance
+ end
+
+ local delta, hmove = calculatedelta (
+ hook, -- the line
+ width, -- width of object
+ delta, -- offset
+ atleft,
+ islocal, -- islocal
+ option[v_paragraph], -- followshape
+ area -- relative to area
+ )
+
+ if hmove ~= 0 then
+ delta = delta + hmove
+ if trace_margindata then
+ report_margindata("realigned %a, location %a, margin %a, move %p",candidate.n,location,margin,hmove)
+ end
+ else
+ if trace_margindata then
+ report_margindata("realigned %a, location %a, margin %a",candidate.n,location,margin)
+ end
+ end
+ moveinline(hook,candidate.node,delta)
+end
+
+local function realigned(current,a)
+ local candidate = status[a]
+ realign(current,candidate)
+ nofdelayed = nofdelayed - 1
+ status[a] = nil
+ return true
+end
+
+-- Stacking is done in two ways: the v_yes option stacks per paragraph (or line,
+-- depending on what gets by) and mostly concerns margin data dat got set at more or
+-- less the same time. The v_continue option uses position tracking and works on
+-- larger range. However, crossing pages is not part of it. Anyway, when you have
+-- such messed up margin data you'd better think twice.
+--
+-- The stacked table keeps track (per location) of the offsets (the v_yes case). This
+-- table gets saved when the v_continue case is active. We use a special variant
+-- of position tracking, after all we only need the page number and vertical position.
+
+local stacked = { } -- left/right keys depending on location
+local cache = { }
+
+local function resetstacked()
+ stacked = { }
+end
+
+-- resetstacked()
+
+local function ha(tag) -- maybe l/r keys ipv left/right keys
+ local p = cache[tag]
+ p.p = true
+ p.y = true
+ setposition('md:v',tag,p)
+ cache[tag] = nil
+end
+
+margins.ha = ha
+
+local f_anchor = formatters["typesetters.margins.ha(%s)"]
+
+local function setanchor(v_anchor)
+ return new_latelua(f_anchor(v_anchor))
+end
+
+-- local function setanchor(v_anchor) -- freezes the global here
+-- return lateluafunction(function() ha(v_anchor) end)
+-- end
+
+local function markovershoot(current) -- todo: alleen als offset > line
+ v_anchors = v_anchors + 1
+ cache[v_anchors] = stacked
+ local anchor = setanchor(v_anchors)
+ -- local list = hpack_nodes(linked_nodes(anchor,getlist(current))) -- not ok, we need to retain width
+ local list = hpack_nodes(linked_nodes(anchor,getlist(current)),getfield(current,"width"),"exactly")--
+ -- why not:
+ -- local list = linked_nodes(anchor,getlist(current))
+ setlist(current,list)
+end
+
+local function getovershoot(location)
+ local p = getposition("md:v",v_anchors)
+ local c = getposition("md:v",v_anchors+1)
+ if p and c and p.p and p.p == c.p then
+ local distance = p.y - c.y
+ local offset = p[location] or 0
+ local overshoot = offset - distance
+ if trace_marginstack then
+ report_margindata("location %a, distance %p, offset %p, overshoot %p",location,distance,offset,overshoot)
+ end
+ if overshoot > 0 then
+ return overshoot
+ end
+ end
+ return 0
+end
+
+local function inject(parent,head,candidate)
+ local box = candidate.box
+ if not box then
+ return head, nil, false -- we can have empty texts
+ end
+ local width = getfield(box,"width")
+ local height = getfield(box,"height")
+ local depth = getfield(box,"depth")
+ local shift = getfield(box,"shift")
+ local stack = candidate.stack
+ local location = candidate.location
+ local method = candidate.method
+ local voffset = candidate.voffset
+ local line = candidate.line
+ local baseline = candidate.baseline
+ local strutheight = candidate.strutheight
+ local strutdepth = candidate.strutdepth
+ local psubtype = getsubtype(parent)
+ local offset = stacked[location]
+ local firstonstack = offset == false or offset == nil
+ nofstatus = nofstatus + 1
+ nofdelayed = nofdelayed + 1
+ status[nofstatus] = candidate
+ -- yet untested
+ baseline = tonumber(baseline)
+ if not baseline then
+ baseline = toboolean(baseline)
+ end
+ --
+ if baseline == true then
+ baseline = false
+ else
+ baseline = tonumber(baseline)
+ if not baseline or baseline <= 0 then
+ -- in case we have a box of width 0 that is not analyzed
+ baseline = false -- strutheight -- actually a hack
+ end
+ end
+ candidate.width = width
+ candidate.hsize = getfield(parent,"width") -- we can also pass textwidth
+ candidate.psubtype = psubtype
+ if trace_margindata then
+ report_margindata("processing, index %s, height %p, depth %p, parent %s",candidate.n,height,depth,listcodes[psubtype])
+ end
+ if firstonstack then
+ offset = 0
+ else
+ -- offset = offset + height
+ end
+ if stack == v_yes then
+ offset = offset + candidate.dy -- always
+ shift = shift + offset
+ elseif stack == v_continue then
+ offset = offset + candidate.dy -- always
+ if firstonstack then
+ offset = offset + getovershoot(location)
+ end
+ shift = shift + offset
+ end
+ -- -- --
+ -- Maybe we also need to patch offset when we apply methods, but how ...
+ -- This needs a bit of playing as it depends on the stack setting of the
+ -- following which we don't know yet ... so, consider stacking partially
+ -- experimental.
+ -- -- --
+ if method == v_top then
+ local delta = height - getfield(parent,"height")
+ if trace_margindata then
+ report_margindata("top aligned by %p",delta)
+ end
+ if delta < candidate.threshold then -- often we need a negative threshold here
+ shift = shift + voffset + delta
+ end
+ elseif method == v_line then
+ if getfield(parent,"depth") == 0 then
+ local delta = height - getfield(parent,"height")
+ if trace_margindata then
+ report_margindata("top aligned by %p (no depth)",delta)
+ end
+ if delta < candidate.threshold then -- often we need a negative threshold here
+ shift = shift + voffset + delta
+ end
+ end
+ elseif method == v_first then
+ if baseline then
+ shift = shift + voffset + height - baseline -- option
+ else
+ shift = shift + voffset -- normal
+ end
+ if trace_margindata then
+ report_margindata("first aligned")
+ end
+ elseif method == v_depth then
+ local delta = strutdepth
+ if trace_margindata then
+ report_margindata("depth aligned by %p",delta)
+ end
+ shift = shift + voffset + delta
+ elseif method == v_height then
+ local delta = - strutheight
+ if trace_margindata then
+ report_margindata("height aligned by %p",delta)
+ end
+ shift = shift + voffset + delta
+ elseif voffset ~= 0 then
+ if trace_margindata then
+ report_margindata("voffset %p applied",voffset)
+ end
+ shift = shift + voffset
+ end
+ -- -- --
+ if line ~= 0 then
+ local delta = line * candidate.lineheight
+ if trace_margindata then
+ report_margindata("offset %p applied to line %s",delta,line)
+ end
+ shift = shift + delta
+ offset = offset + delta
+ end
+ setfield(box,"shift",shift)
+ setfield(box,"width",0)
+ --
+ candidate.hook, candidate.node = addtoline(parent,box)
+ --
+ setattr(box,a_margindata,nofstatus)
+ if trace_margindata then
+ report_margindata("injected, location %a, shift %p",location,shift)
+ end
+ -- we need to add line etc to offset as well
+ offset = offset + depth
+ local room = {
+ height = height,
+ depth = offset,
+ slack = candidate.bottomspace, -- todo: 'depth' => strutdepth
+ lineheight = candidate.lineheight, -- only for tracing
+ }
+ offset = offset + height
+ stacked[location] = offset -- weird, no table ?
+ -- todo: if no real depth then zero
+ if trace_margindata then
+ report_margindata("status, offset %s",offset)
+ end
+ return getlist(parent), room, stack == v_continue
+end
+
+local function flushinline(parent,head)
+ local current = head
+ local done = false
+ local continue = false
+ local room, don, con, list
+ 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")
+ local candidate = inlinestore[n]
+ if candidate then -- no vpack, as we want to realign
+ inlinestore[n] = nil
+ nofinlined = nofinlined - 1
+ head, room, con = inject(parent,head,candidate) -- maybe return applied offset
+ continue = continue or con
+ done = true
+ nofstored = nofstored - 1
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ -- optional (but sometimes needed)
+ list, don, con = flushinline(current,getlist(current))
+ setlist(current,list)
+ continue = continue or con
+ done = done or don
+ end
+ current = getnext(current)
+ end
+ return head, done, continue
+end
+
+local function flushed(scope,parent) -- current is hlist
+ local head = getlist(parent)
+ local done = false
+ local continue = false
+ local room, con, don
+ for c=1,#categories do
+ local category = categories[c]
+ for l=1,#locations do
+ local location = locations[l]
+ local store = displaystore[category][location][scope]
+ if store then
+ while true do
+ local candidate = remove(store,1) -- brr, local stores are sparse
+ if candidate then -- no vpack, as we want to realign
+ head, room, con = inject(parent,head,candidate)
+ done = true
+ continue = continue or con
+ nofstored = nofstored - 1
+ if room then
+ registertogether(tonode(parent),room) -- !! tonode
+ end
+ else
+ break
+ end
+ end
+ else
+ -- report_margindata("fatal error: invalid category %a",category or "?")
+ end
+ end
+ end
+ if nofinlined > 0 then
+ if done then
+ setlist(parent,head)
+ end
+ head, don, con = flushinline(parent,head)
+ continue = continue or con
+ done = done or don
+ end
+ if done then
+ local a = getattr(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism
+ if false then
+ local l = hpack_nodes(head,getfield(parent,"width"),"exactly")
+ setlist(parent,l)
+ if a then
+ setattr(l,a_linenumber,a)
+ end
+ else
+ -- because packing messes up profiling
+ setlist(parent,head)
+ if a then
+ setattr(parent,a_linenumber,a)
+ end
+ end
+ -- resetstacked()
+ end
+ return done, continue
+end
+
+-- only when group : vbox|vmode_par
+-- only when subtype : line, box (no indent alignment cell)
+
+local function handler(scope,head,group)
+ if nofstored > 0 then
+ if trace_margindata then
+ report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group)
+ end
+ head = tonut(head)
+ local current = head
+ local done = false
+ while current do
+ local id = getid(current)
+ if (id == vlist_code or id == hlist_code) and not getattr(current,a_margindata) then
+ local don, continue = flushed(scope,current)
+ if don then
+ done = true
+ setattr(current,a_margindata,0) -- signal to prevent duplicate processing
+ if continue then
+ markovershoot(current)
+ end
+ if nofstored <= 0 then
+ break
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ if trace_margindata then
+ if done then
+ report_margindata("flushing stage one, done, %s left",nofstored)
+ else
+ report_margindata("flushing stage one, nothing done, %s left",nofstored)
+ end
+ end
+ -- if done then
+ resetstacked() -- why doesn't done work ok here?
+ -- end
+ return tonode(head), done
+ else
+ return head, false
+ end
+end
+
+local trialtypesetting = context.trialtypesetting
+
+function margins.localhandler(head,group) -- sometimes group is "" which is weird
+
+if trialtypesetting() then
+ return head, false
+end
+
+ local inhibit = conditionals.inhibitmargindata
+ if inhibit then
+ 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 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
+end
+
+function margins.globalhandler(head,group) -- check group
+
+if trialtypesetting() then
+ return head, false
+end
+
+ local inhibit = conditionals.inhibitmargindata
+ if inhibit or nofstored == 0 then
+ if trace_margingroup then
+ report_margindata("ignored 1, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
+ end
+ return head, false
+ elseif group == "hmode_par" then
+ return handler(v_global,head,group)
+ elseif group == "vmode_par" then -- experiment (for alignments)
+ return handler(v_global,head,group)
+ -- this needs checking as we then get quite some one liners to process and
+ -- we cannot look ahead then:
+ elseif group == "box" then -- experiment (for alignments)
+ return handler(v_global,head,group)
+ elseif group == "alignment" then -- experiment (for alignments)
+ return handler(v_global,head,group)
+ else
+ if trace_margingroup then
+ report_margindata("ignored 2, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
+ end
+ return head, false
+ end
+end
+
+local function finalhandler(head)
+ if nofdelayed > 0 then
+ local current = head
+ local done = false
+ while current and nofdelayed > 0 do
+ local id = getid(current)
+ if id == hlist_code then -- only lines?
+ local a = getattr(current,a_margindata)
+ if not a or a == 0 then
+ finalhandler(getlist(current))
+ elseif realigned(current,a) then
+ done = true
+ if nofdelayed == 0 then
+ return head, true
+ end
+ end
+ elseif id == vlist_code then
+ finalhandler(getlist(current))
+ end
+ current = getnext(current)
+ end
+ return head, done
+ else
+ return head, false
+ end
+end
+
+function margins.finalhandler(head)
+ if nofdelayed > 0 then
+ -- if trace_margindata then
+ -- report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed)
+ -- end
+ head = tonut(head)
+ local head, done = finalhandler(head)
+ head = tonode(head)
+ return head, done
+ else
+ return head, false
+ end
+end
+
+-- Somehow the vbox builder (in combinations) gets pretty confused and decides to
+-- go horizontal. So this needs more testing.
+
+prependaction("finalizers", "lists", "typesetters.margins.localhandler")
+-- ("vboxbuilders", "normalizers", "typesetters.margins.localhandler")
+prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler")
+prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler")
+
+disableaction("finalizers", "typesetters.margins.localhandler")
+-- ("vboxbuilders", "typesetters.margins.localhandler")
+disableaction("mvlbuilders", "typesetters.margins.globalhandler")
+disableaction("shipouts", "typesetters.margins.finalhandler")
+
+enablelocal = function()
+ enableaction("finalizers", "typesetters.margins.localhandler")
+ -- enableaction("vboxbuilders", "typesetters.margins.localhandler")
+ enableaction("shipouts", "typesetters.margins.finalhandler")
+ enablelocal = nil
+end
+
+enableglobal = function()
+ enableaction("mvlbuilders", "typesetters.margins.globalhandler")
+ enableaction("shipouts", "typesetters.margins.finalhandler")
+ enableglobal = nil
+end
+
+statistics.register("margin data", function()
+ if nofsaved > 0 then
+ return format("%s entries, %s pending",nofsaved,nofdelayed)
+ else
+ return nil
+ end
+end)
+
+interfaces.implement {
+ name = "savemargindata",
+ actions = margins.save,
+ arguments = {
+ {
+ { "location" },
+ { "method" },
+ { "category" },
+ { "name" },
+ { "scope" },
+ { "number", "integer" },
+ { "margin" },
+ { "distance", "dimen" },
+ { "hoffset", "dimen" },
+ { "voffset", "dimen" },
+ { "dy", "dimen" },
+ { "bottomspace", "dimen" },
+ { "baseline"}, -- dimen or string or
+ { "threshold", "dimen" },
+ { "inline", "boolean" },
+ { "anchor" },
+ -- { "leftskip", "dimen" },
+ -- { "rightskip", "dimen" },
+ { "align" },
+ { "option" },
+ { "line", "integer" },
+ { "stack" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv
new file mode 100644
index 00000000000..90ccd46e2f0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv
@@ -0,0 +1,438 @@
+% macros=mkvi
+
+%D \module
+%D [ file=typo-mar,
+%D version=2010.02.15, % was experimental code
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Margindata,
+%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.
+
+% maybe dontleavehmode when scope is local
+
+% todo: tags
+% todo: force inline with option (saves pos)
+% todo: margintitle (also less position then)
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Margindata}
+
+\unprotect
+
+%D This module has been on the agenda for a while. Actually, it is
+%D one of the things that I really need myself, for instance when
+%D rendering rather unpredictable (educational) tests encoded in
+%D XML. This module permits anchoring for instance item numbers and
+%D also overload them when they have subnumbers. In the future it
+%D might replace the current maginal note mechanism (that then
+%D will be just an instance).
+%D
+%D In spite of what might be expected, the more advanced \LUA\ based
+%D variant is upto twice as fast on simple entries. Also, we no longer
+%D need an extra pass to get inner and outer alignments in sync with
+%D the pagebuilder.
+
+\registerctxluafile{typo-mar}{1.001}
+
+%definesystemattribute[margindata] % only at the lua end
+
+%D In \MKII\ we have three categories and their historically meaning
+%D is as follows:
+%D
+%D marginlines: These are flushed relative to the start of a line and
+%D need to be invoked there.
+%D
+%D marginwords: These can be issued in the text flow and will migrate
+%D sidewards; in spite of the name, it can be a paragraph of text as
+%D well, but normally it's words.
+%D
+%D margintexts: These can be set beforehand and are flushed at the
+%D next paragraph of text (of header).
+%D
+%D In \MKIV\ we have further integrated the mechanism and we now have:
+%D
+%D margindata: This can be anything that needs to go into the margin.
+%D It can be anchored in the text or given beforehand in which case
+%D it gets flushed at the first occasion.
+%D
+%D margintext: This runs on top of margindata and the only difference
+%D is that it uses the framed mechanism for packaging.
+%D
+%D Stacking is done differently as is inner and outer alignment (in
+%D most cases more efficient). The functionality is mostly the same
+%D as in \MKII, but there are a few additions, like names entries,
+%D where later ones overload preceding not yet flushed ones. Data can
+%D get catagorized and is then treated as a group (e.g. when stacking
+%D is needed).
+%D
+%D The amount of \TEX\ code is less than in \MKII\ because we do all
+%D trickery in at the \LUA\ end. At the end of this file we define
+%D several commands, like \type {\inleftmargin} and \type {\inleft}.
+%D You can configure them individually or as a group. There is an
+%D inheritance model in place.
+%D
+%D The following notes will be stacked:
+%D
+%D \starttyping
+%D \ininner[line=2]{IM A}
+%D \ininner[stack=yes]{IM B}
+%D \ininner[stack=yes]{IM C}
+%D \stoptyping
+%D
+%D The distance between them is determined by \type {dy}:
+%D
+%D \starttyping
+%D \ininner[stack=yes,dy=2ex][frame=on] {IM A}
+%D \ininner[stack=yes,dy=2ex][frame=on] {IM B}
+%D \stoptyping
+%D
+%D There are several methods of vertical alignment.
+%D
+%D \starttyping
+%D \inmargin [method=first] [frame=on] {first\\second} \input ward \par
+%D \inmargin [method=first] [frame=on,offset=3pt] {first\\second} \input ward \par
+%D \inmargin [method=first,voffset=-3pt][frame=on,offset=3pt,rulethickness=3pt] {first\\second} \input ward \par
+%D \inmargin [method=first,voffset=-6pt][frame=on,offset=3pt,rulethickness=3pt] {first\\second} \input ward \par
+%D \stoptyping
+%D
+%D You sometimes need to combine \type {voffset} with \type {offset}. The first
+%D argument concerns the data, the second the framed. Not sharing the setup is
+%D on purpose: location, offset, alignment and other parameters might clash.
+
+\installcorenamespace{margindata}
+\installcorenamespace{marginframed}
+
+\installcommandhandler \??margindata {margindata} \??margindata
+\installframedcommandhandler \??marginframed {marginframed} \??marginframed
+
+\setupmargindata
+ [\c!location=\v!left,
+ % \c!align=,
+ % \c!method=,
+ \c!style=\v!bold,
+ \c!color=, % maybe \maintextcolor
+ % \c!name=,
+ % \c!category=,
+ \c!threshold=.25\exheight,
+ \c!margin=\v!normal,
+ \c!scope=\v!global,
+ \c!width=,
+ % \c!stack=,
+ % \c!option=, % \v!paragraph (follow shape)
+ \c!line=0,
+ \c!anchor=\v!text,
+ \c!bottomspace=\strutdepth, % slack used for keeptogether
+ \c!dy=\zeropoint,
+ \c!distance=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint]
+
+\setupmarginframed % so, align should be set with the data command
+ [\c!strut=\v!yes,
+ \c!offset=\v!overlay,
+ \c!fr!analyze=\v!yes,
+ \c!frame=\v!off,
+ \c!width=\margindataparameter\c!width,
+ \c!align=\margindataparameter\c!align]
+
+\appendtoks
+ \setuevalue\currentmargindata{\margindata[\currentmargindata]}%
+\to \everydefinemargindata
+
+\newconditional\inhibitmargindata % This one is used at the Lua end!
+\newtoks \everymargindatacontent % Later on we will set this one.
+
+\appendtoks
+ \settrue\inhibitmargindata
+\to \everyforgetall
+
+\appendtoks
+ \forgetall
+ \tf
+ \resetallattributes % \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor
+\to \everymargindatacontent
+
+% trialtypesetting: no need for margin stuff while trialing as
+% is has no dimensions
+
+\definesystemconstant{margintext}
+
+\newcount\nofmargintexts
+
+\definepagestate[\s!margintext]
+
+\unexpanded\def\typo_margins_data_synchronize
+ {\doforcedtrackpagestate\s!margintext\nofmargintexts % includes increment
+ \docheckpagestate\s!margintext\nofmargintexts
+ %\doifelserightpagestate\s!margintext\nofmargintexts\relax\relax
+ \realpageno\realpagestateno
+ \swapmargins}
+
+\unexpanded\def\margindata
+ {\iftrialtypesetting
+ \expandafter\typo_margins_data_nop
+ \else
+ \expandafter\typo_margins_data_yes
+ \fi}
+
+\def\typo_margins_data_nop[#name]%
+ {\dodoubleempty\typo_margins_data_nop_indeed}
+
+\def\typo_margins_data_yes[#name]%
+ {\setfalse\inhibitmargindata % flushing afterwards
+ \begingroup
+ %\settrue\inhibitmargindata % no flushing in here
+ \def\currentmargindata{#name}%
+ \let\currentmarginframed\currentmargindata
+ \dodoubleempty\typo_margins_data_yes_indeed}
+
+\unexpanded\def\typo_margins_data_nop_indeed[#dataparameters][#textparameters]#content%
+ {}
+
+% todo: naturalhbox
+
+\let\margindatahbox\naturalhbox % \hbox
+
+\unexpanded\def\typo_margins_data_yes_indeed[#dataparameters][#textparameters]#content%
+ {\iffirstargument
+ \setupcurrentmargindata[#dataparameters]%
+ \fi
+ \doifelsenothing{#content}\donefalse\donetrue
+ \ifdone
+ \edef\currentmarginreference{\margindataparameter\c!reference}%
+ \ifx\currentmarginreference\empty \else
+ \strc_references_set_page_only_destination_box_attribute\currentmarginreference\currentmarginreference
+ \fi
+ \edef\currentmargindatastrut{\margindataparameter\c!strut}%
+ \dostarttaggedchained\t!margintext\currentmargindata\??margindata
+ \ifcsname\currentmarginframedhash\s!parent\endcsname
+ \setbox\nextbox\margindatahbox \currentmarginreference \bgroup
+ \the\everymargindatacontent
+ \usemargindatastyleandcolor\c!style\c!color
+ \setupcurrentmarginframed[\c!location=\v!normal,#textparameters]%
+ \typo_margins_data_synchronize
+ \inheritedmarginframedframed\bgroup
+ \ifx\currentmargindatastrut\empty \else
+ \synchronizestrut\currentmargindatastrut
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
+ \egroup
+ \edef\currentmarginfirstheight{\number\dimexpr\framedfirstheight}%
+ \else
+ \edef\currentmargindatawidth{\margindataparameter\c!width}%
+ \ifx\currentmargindatawidth\empty
+ \setbox\nextbox\margindatahbox \currentmarginreference \bgroup
+ \typo_margins_data_synchronize
+ \the\everymargindatacontent
+ \usemargindatastyleandcolor\c!style\c!color
+ \ifx\currentmargindatastrut\empty \else
+ \synchronizestrut\currentmargindatastrut
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
+ \let\currentmarginfirstheight\empty
+ \else
+ \setbox\nextbox\margindatahbox \currentmarginreference \bgroup
+ \typo_margins_data_synchronize
+ \dosetraggedcommand{\margindataparameter\c!align}%
+ \vtop \bgroup
+ \the\everymargindatacontent
+ \usemargindatastyleandcolor\c!style\c!color
+ \hsize\currentmargindatawidth
+ \raggedcommand
+ \ifx\currentmargindatastrut\empty \else
+ \synchronizestrut\currentmargindatastrut
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
+ \egroup
+ \edef\currentmarginfirstheight{true}%
+ \fi
+ \fi
+ \dostoptagged
+ \fi
+ \ifdone
+ \edef\p_anchor{\margindataparameter\c!anchor}%
+ \anch_positions_initialize % we use positions at the lua end
+ \clf_savemargindata
+ location {\margindataparameter\c!location}%
+ method {\margindataparameter\c!method}%
+ category {\margindataparameter\c!category}%
+ name {\margindataparameter\c!name}%
+ scope {\margindataparameter\c!scope}%
+ option {\margindataparameter\c!option}%
+ number \nextbox
+ margin {\margindataparameter\c!margin}% local normal margin edge
+ distance \dimexpr\margindataparameter\c!distance\relax
+ hoffset \dimexpr\margindataparameter\c!hoffset\relax
+ voffset \dimexpr\margindataparameter\c!voffset\relax
+ dy \dimexpr\margindataparameter\c!dy\relax
+ bottomspace \dimexpr\margindataparameter\c!bottomspace\relax
+ \ifx\currentmarginfirstheight\empty \else
+ baseline {\currentmarginfirstheight}%
+ \fi
+ threshold \dimexpr\margindataparameter\c!threshold\relax % overlap related, will change
+ \ifhmode
+ inline true %
+ \fi
+ anchor {\p_anchor\ifx\p_anchor\v!region:0\fi}% kind of a hack to force column anchoring (for now)
+ %
+ % we're not in forgetall
+ %
+ % \ifzeropt\leftskip \else
+ % leftskip \dimexpr\leftskip\relax
+ % \fi
+ % \ifzeropt\leftskip \else
+ % rightskip \dimexpr\rightskip\relax
+ % \fi
+ align {\margindataparameter\c!align}%
+ line \numexpr\margindataparameter\c!line\relax
+ stack {\margindataparameter\c!stack}%
+ \relax
+ \else
+ \clf_savemargindata
+ location {\margindataparameter\c!location}%
+ method {\margindataparameter\c!method}%
+ category {\margindataparameter\c!category}%
+ name {\margindataparameter\c!name}%
+ scope {\margindataparameter\c!scope}%
+ number \nextbox
+ \relax
+ \fi
+ \endgroup}
+
+%D Downward compatible hack:
+
+\unexpanded\def\spaceorpar
+ {\endgraf\ifhmode\space\fi}
+
+\appendtoks
+ \let\\\spaceorpar
+\to \everymargindatacontent
+
+%D Another one:
+
+% \installcorenamespace{oppositemargin}
+%
+% \letvalue{\??oppositemargin\v!left }\v!right
+% \letvalue{\??oppositemargin\v!right }\v!left
+% \letvalue{\??oppositemargin\v!inner }\v!outer
+% \letvalue{\??oppositemargin\v!outer }\v!inner
+% \letvalue{\??oppositemargin\v!normal}\v!normal
+%
+% \def\oppositemargin#1%
+% {\csname\??oppositemargin\ifcsname\??oppositemargin#1\endcsname#1\else\v!normal\fi\endcsname}
+
+%D Definitions:
+
+% common to lines and text
+
+\setupmargindata [\v!left ] [\c!method=\v!first,\c!location=\v!left ,\c!margin=\v!margin,\c!align=\v!flushright,\s!parent=\??margindata] % we could autoparent when no define yet
+\setupmargindata [\v!right] [\c!method=\v!first,\c!location=\v!right,\c!margin=\v!margin,\c!align=\v!flushleft, \s!parent=\??margindata]
+\setupmargindata [\v!outer] [\c!method=\v!first,\c!location=\v!outer,\c!margin=\v!margin,\c!align=\v!inner, \s!parent=\??margindata]
+\setupmargindata [\v!inner] [\c!method=\v!first,\c!location=\v!inner,\c!margin=\v!margin,\c!align=\v!outer, \s!parent=\??margindata]
+
+% lines
+
+\definemargindata [\v!inleftmargin] [\v!left ] [\c!margin=\v!margin,\c!width=\leftmarginwidth ,\c!style=,\c!color=]
+\definemargindata [\v!inrightmargin] [\v!right] [\c!margin=\v!margin,\c!width=\rightmarginwidth,\c!style=,\c!color=]
+\definemargindata [\v!inoutermargin] [\v!outer] [\c!margin=\v!margin,\c!width=\outermarginwidth,\c!style=,\c!color=]
+\definemargindata [\v!ininnermargin] [\v!inner] [\c!margin=\v!margin,\c!width=\innermarginwidth,\c!style=,\c!color=]
+
+\definemargindata [\v!inleftedge] [\v!left ] [\c!margin=\v!edge ,\c!width=\leftedgewidth ,\c!style=,\c!color=,\c!category=\v!edge]
+\definemargindata [\v!inrightedge] [\v!right] [\c!margin=\v!edge ,\c!width=\rightedgewidth ,\c!style=,\c!color=,\c!category=\v!edge]
+\definemargindata [\v!inouteredge] [\v!outer] [\c!margin=\v!edge ,\c!width=\outeredgewidth ,\c!style=,\c!color=,\c!category=\v!edge]
+\definemargindata [\v!ininneredge] [\v!inner] [\c!margin=\v!edge ,\c!width=\inneredgewidth ,\c!style=,\c!color=,\c!category=\v!edge]
+
+\definemargindata [\v!atleftmargin] [\v!left ] [\c!margin=\v!normal,\c!width=\leftmarginwidth ,\c!style=,\c!color=]
+\definemargindata [\v!atrightmargin] [\v!right] [\c!margin=\v!normal,\c!width=\rightmarginwidth,\c!style=,\c!color=]
+
+% text: \v!added
+
+\definemargindata [\v!inleft] [\v!left ] [\c!margin=\v!margin,\c!width=\leftmarginwidth ,\c!align=\v!flushright]
+\definemargindata [\v!inright] [\v!right] [\c!margin=\v!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
+\definemargindata [\v!inouter] [\v!outer] [\c!margin=\v!margin,\c!width=\outermarginwidth,\c!align=\v!inner]
+\definemargindata [\v!ininner] [\v!inner] [\c!margin=\v!margin,\c!width=\innermarginwidth,\c!align=\v!outer]
+
+% no longer auto auto-other
+
+\definemargindata [\v!inmargin] [\v!left] [\c!margin=\v!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright]
+\definemargindata [\v!inother] [\v!right] [\c!margin=\v!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
+
+\definemargindata [\v!margintext] [\v!left] [\c!margin=\v!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright,\c!stack=\v!yes]
+
+\setupmarginframed [\v!left ] [\c!method=\v!first,\c!align=\v!flushright,\s!parent=\??marginframed] % we could autoparent when no define yet
+\setupmarginframed [\v!right] [\c!method=\v!first,\c!align=\v!flushleft, \s!parent=\??marginframed]
+\setupmarginframed [\v!outer] [\c!method=\v!first,\c!align=\v!inner, \s!parent=\??marginframed]
+\setupmarginframed [\v!inner] [\c!method=\v!first,\c!align=\v!outer, \s!parent=\??marginframed]
+
+\definemarginframed [\v!inleft] [\v!left ]
+\definemarginframed [\v!inright] [\v!right]
+\definemarginframed [\v!inouter] [\v!outer]
+\definemarginframed [\v!ininner] [\v!inner]
+\definemarginframed [\v!inmargin] [\v!inleft]
+\definemarginframed [\v!inother] [\v!inright]
+
+\let\marginword \margintext
+\let\margintitle \margintext
+\let\inothermargin\inother % for old times sake
+
+%definemargindata [inouterextra] [\v!outer] [\c!margin=\v!edge,\c!location=\v!outer,\c!width=\outeredgewidth,\c!align=\v!outer,\c!category=\v!edge]
+%definemargindata [ininnerextra] [\v!inner] [\c!margin=\v!edge,\c!location=\v!inner,\c!width=\inneredgewidth,\c!align=\v!inner,\c!category=\v!edge]
+%
+%definemarginframed [inouterextra] [\v!outer]
+%definemarginframed [ininnerextra] [\v!inner]
+
+%D As we have more control we are not backward compatible although in
+%D practice it won't hurt that much. So, from now on use:
+%D
+%D \starttyping
+%D \definemargindata
+%D \setupmargindata
+%D \definemarginframed
+%D \setupmarginframed
+%D \stoptyping
+
+% The following sort of works okay but is to be avoided:
+
+\let\definemarginline\definemargindata
+
+\unexpanded\def\defineinmargin
+ {\doquadrupleempty\typo_inmargin_define}
+
+\def\typo_inmargin_define[#name][#location][#align][#settings]% not completely compatible
+ {\definemargindata[#name][\c!location=#location,\c!align=#align,#settings]%
+ \definemarginframed[#name][#location][\c!align=#align,#settings]}
+
+\let\setupinmargin\setupmargindata % only partial (no framed)
+
+% begin of experimental code (will move)
+%
+% \dosetanchor{x}test \dostarthanchoring{x}\llap{crap}\dostophanchoring{x}test test test
+% test \dostarthanchoring{text}\llap{crap}\dostophanchoring{text}test test test
+
+% \def\dosetanchor #1{\dontleavehmode\latelua{anchors.set("#1")}}
+% \def\doresetanchor #1{\dontleavehmode\latelua{anchors.reset("#1")}}
+% \def\doresetanchornow #1{\directlua{anchors.reset("#1")}}
+% \def\dostartanchoring #1{\dontleavehmode\latelua{anchors.startmove("#1")}}
+% \def\dostopanchoring #1{\dontleavehmode\latelua{anchors.stopmove("#1")}}
+% \def\dostarthanchoring#1{\dontleavehmode\latelua{anchors.startmove("#1","h")}}
+% \def\dostartvanchoring#1{\dontleavehmode\latelua{anchors.startmove("#1","v")}}
+% \let\dostophanchoring \dostopanchoring
+% \let\dostopvanchoring \dostopanchoring
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua
new file mode 100644
index 00000000000..355becff667
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua
@@ -0,0 +1,198 @@
+if not modules then modules = { } end modules ['typo-pag'] = {
+ version = 1.001,
+ comment = "companion to typo-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+builders = builders or { }
+local builders = builders
+
+builders.paragraphs = builders.paragraphs or { }
+local parbuilders = builders.paragraphs
+
+local nodes = nodes
+local nodecodes = nodes.nodecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+
+local unsetvalue = attributes.unsetvalue
+local a_keeptogether = attributes.private("keeptogether")
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+
+local insert_node_after = nuts.insert_after
+local new_penalty = nuts.pool.penalty
+
+local trace_keeptogether = false
+local report_keeptogether = logs.reporter("parbuilders","keeptogether")
+
+local cache = { }
+local last = 0
+local enabled = false
+
+trackers.register("parbuilders.keeptogether", function(v) trace_keeptogether = v end)
+
+-- todo: also support lines = 3 etc (e.g. dropped caps) but how to set that
+-- when no hlists are there ?
+
+function parbuilders.registertogether(line,specification) -- might change
+ if not specification then
+ return
+ end
+ if not enabled then
+ nodes.tasks.enableaction("finalizers","builders.paragraphs.keeptogether")
+ end
+ local a = getattr(line,a_keeptogether)
+ local c = a and cache[a]
+ if c then
+ local height = specification.height
+ local depth = specification.depth
+ local slack = specification.slack
+ if height and height > c.height then
+ c.height = height
+ end
+ if depth and depth > c.depth then
+ c.depth = depth
+ end
+ if slack and slack > c.slack then
+ c.slack = slack
+ end
+ else
+ last = last + 1
+ cache[last] = specification
+ if not specification.height then
+ specification.height = 0
+ end
+ if not specification.depth then
+ specification.depth = 0
+ end
+ if not specification.slack then
+ specification.slack = 0
+ end
+ setattr(line,a_keeptogether,last)
+ end
+ if trace_keeptogether then
+ local a = a or last
+ local c = cache[a]
+ local noflines = specification.lineheight
+ local height = c.height
+ local depth = c.depth
+ local slack = c.slack
+ if not noflines or noflines == 0 then
+ noflines = "unknown"
+ else
+ noflines = math.round((height + depth - slack) / noflines)
+ end
+ report_keeptogether("registered, index %s, height %p, depth %p, slack %p, noflines %a",a,height,depth,slack,noflines)
+ end
+end
+
+local function keeptogether(start,a)
+ if start then
+ local specification = cache[a]
+ if a then
+ local current = getnext(start)
+ local previous = start
+ local total = getfield(previous,"depth")
+ local slack = specification.slack
+ local threshold = specification.depth - slack
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %p, threshold %p, slack %p","list",a,total,threshold,slack)
+ end
+ while current do
+ local id = getid(current)
+ if id == vlist_code or id == hlist_code then
+ total = total + getfield(current,"height") + getfield(current,"depth")
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %p, threshold %p","list",a,total,threshold)
+ end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setfield(previous,"penalty",10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == glue_code then
+ -- hm, breakpoint, maybe turn this into kern
+ total = total + getfield(current,"width")
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold)
+ end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setfield(previous,"penalty",10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == kern_code then
+ total = total + getfield(current,"kern")
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %s, threshold %s","kern",a,total,threshold)
+ end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setfield(previous,"penalty",10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == penalty_code then
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setfield(previous,"penalty",10000)
+ end
+ setfield(current,"penalty",10000)
+ else
+ break
+ end
+ end
+ previous = current
+ current = getnext(current)
+ end
+ end
+ end
+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)
+ while current do
+ if getid(current) == hlist_code then
+ local a = getattr(current,a_keeptogether)
+ if a and a > 0 then
+ keeptogether(current,a)
+ setattr(current,a_keeptogether,unsetvalue)
+ cache[a] = nil
+ done = true
+ end
+ end
+ current = getnext(current)
+ end
+ return head, done
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.mkiv
new file mode 100644
index 00000000000..30d2b51b73d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=typo-pag,
+%D version=2011.11.02,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Pages,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Pages}
+
+\unprotect
+
+\registerctxluafile{typo-pag}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv
new file mode 100644
index 00000000000..8572f31b83b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=typo-par,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Paragraph Building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Node Macros / Paragraph Building}
+
+%D This is very experimental, undocumented, subjected to changes, etc. just as
+%D the underlying interfaces. But at least it's cleaned as part of the status-mkiv
+%D cleanup.
+
+% \startparbuilder[basic]
+% \input tufte \par
+% \stopparbuilder
+
+\unprotect
+
+\registerctxluafile{node-ltp}{1.001}
+\registerctxluafile{trac-par}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua
new file mode 100644
index 00000000000..cde66df0087
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua
@@ -0,0 +1,129 @@
+if not modules then modules = { } end modules ['typo-prc'] = {
+ version = 1.001,
+ comment = "companion to typo-prc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch, patterns, P, C, Cs = lpeg.match, lpeg.patterns, lpeg.P, lpeg.C, lpeg.Cs
+
+-- processors: syntax: processor->data ... not ok yet
+
+local context = context
+local implement = interfaces.implement
+
+local formatters = string.formatters
+
+typesetters.processors = typesetters.processors or { }
+local processors = typesetters.processors
+
+local trace_processors = false
+local report_processors = logs.reporter("processors")
+local registered = { }
+
+local ctx_applyprocessor = context.applyprocessor
+local ctx_firstofoneargument = context.firstofoneargument
+
+trackers.register("typesetters.processors", function(v) trace_processors = v end)
+
+function processors.register(p)
+ registered[p] = true
+end
+
+function processors.reset(p)
+ registered[p] = nil
+end
+
+--~ local splitter = lpeg.splitat("->",true) -- also support =>
+
+local becomes = P('->')
+local processor = (1-becomes)^1
+local splitter = C(processor) * becomes * Cs(patterns.argument + patterns.content)
+
+function processors.split(str)
+ local p, s = lpegmatch(splitter,str)
+ if registered[p] then
+ return p, s
+ else
+ return false, str
+ end
+end
+
+function processors.apply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("applying %s processor %a, argument: %s","known",p,s)
+ end
+ ctx_applyprocessor(p,s)
+ elseif s then
+ if trace_processors then
+ report_processors("applying %s processor %a, argument: %s","unknown",p,s)
+ end
+ context(s)
+ elseif str then
+ if trace_processors then
+ report_processors("applying %s processor, data: %s","ignored",str)
+ end
+ context(str)
+ end
+end
+
+function processors.startapply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("start applying %s processor %a","known",p)
+ end
+ ctx_applyprocessor(p)
+ context("{")
+ return s
+ elseif p then
+ if trace_processors then
+ report_processors("start applying %s processor %a","unknown",p)
+ end
+ ctx_firstofoneargument()
+ context("{")
+ return s
+ else
+ if trace_processors then
+ report_processors("start applying %s processor","ignored")
+ end
+ ctx_firstofoneargument()
+ context("{")
+ return str
+ end
+end
+
+function processors.stopapply()
+ context("}")
+ if trace_processors then
+ report_processors("stop applying processor")
+ end
+end
+
+function processors.tostring(str)
+ local p, s = lpegmatch(splitter,str)
+ if registered[p] then
+ return formatters["\\applyprocessor{%s}{%s}"](p,s)
+ else
+ return str
+ end
+end
+
+function processors.stripped(str)
+ local p, s = lpegmatch(splitter,str)
+ return s or str
+end
+
+-- interface
+
+implement { name = "registerstructureprocessor", actions = processors.register, arguments = "string" }
+implement { name = "resetstructureprocessor", actions = processors.reset, arguments = "string" }
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-prc.mkvi b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.mkvi
new file mode 100644
index 00000000000..49a16569647
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.mkvi
@@ -0,0 +1,99 @@
+%D \module
+%D [ file=typo-prc,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Processors,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Processors}
+
+%D For the moment manipulators are loaded here too, as they're in the same
+%D category as processors. This might change. (They are used in publications.)
+
+\registerctxluafile{typo-prc}{1.001}
+\registerctxluafile{typo-man}{1.001}
+
+\unprotect
+
+%D Processors are used when we cannot easily associate typesetting directives
+%D with (for instance) structural elements. Instead of ending up with numerous
+%D additional definitions we can group treatments in so called processors.
+%D
+%D An example of where processors can be used is in separator sets (these are
+%D related to typesetting numbers using structure).
+%D
+%D \starttyping
+%D \defineprocessor[demo][style=\bfb,color=red]
+%D \stoptyping
+%D
+%D This defines a processor named \type {demo}. Such a name ends up as prefix in
+%D for instance:
+%D
+%D \starttyping
+%D \defineseparatorset [demosep] [demo->!,demo->?,demo->!,demo->?] [demo->@]
+%D \stoptyping
+%D
+%D Here the \type {!} and \type {?} are just the seperator characters that end
+%D up between part, chapter, section, etc.\ numbers. The third argument defines the
+%D default. When a separator is inserted, the \type{demo} processor will be applied.
+%D Here the number will be separated by red slightly bigger than normal bold
+%D exclamation marks and questionmarks
+%D
+%D Valid keys for defining a processor are \type {style}, \type {color}, \type {left},
+%D \type {right}, and \type {command} (the given command takes one argument).
+
+\installcorenamespace{processor}
+\installcorenamespace{processorcheck}
+
+\installcommandhandler \??processor {processor} \??processor
+
+\appendtoks
+ \letvalue{\??processorcheck\currentprocessor}\relax
+ \clf_registerstructureprocessor{\currentprocessor}% global, but it permits using processor that are yet undefined
+\to \everydefineprocessor
+
+%D The following command can be used by users but normally it will be
+%D invoked behind the screens. After all, processor prefixes need to
+%D be split off first. At the \LUA\ end we do check for a processor
+%D being registered anyway.
+
+\unexpanded\def\applyprocessor#tag%
+ {\def\currentprocessor{#tag}%
+ \ifcsname\??processorcheck\currentprocessor\endcsname
+ \expandafter\typo_processor_apply
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\typo_processor_apply
+ {\edef\p_state{\processorparameter\c!state}%
+ \ifx\p_state\v!stop
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\typo_processor_apply_indeed
+ \fi}
+
+\def\typo_processor_apply_indeed#content%
+ {\begingroup
+ \useprocessorstyleandcolor\c!style\c!color
+ \processorparameter\c!left
+ \processorparameter\c!command{#content}%
+ \processorparameter\c!right
+ \endgroup}
+
+%D \startbuffer
+%D \defineprocessor[first] [style=bold]
+%D \defineprocessor[last] [first] [color=red]
+%D
+%D \applyprocessor{first}{hans} \applyprocessor{last}{hagen}
+%D \stopbuffer
+%D
+%D \typebuffer \start \blank \getbuffer \blank \stop
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua
new file mode 100644
index 00000000000..a8925a2ceab
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua
@@ -0,0 +1,145 @@
+if not modules then modules = { } end modules ['typo-rep'] = {
+ 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"
+}
+
+-- This was rather boring to program (more of the same) but I could
+-- endure it by listening to a couple cd's by The Scene and The Lau
+-- on the squeezebox on my desk.
+
+local next, type, tonumber = next, type, tonumber
+
+local trace_stripping = false trackers.register("nodes.stripping", function(v) trace_stripping = v end)
+ trackers.register("fonts.stripping", function(v) trace_stripping = v end)
+
+local report_stripping = logs.reporter("fonts","stripping")
+
+local nodes = nodes
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getchar = nuts.getchar
+local isglyph = nuts.isglyph
+
+local getattr = nuts.getattr
+
+local delete_node = nuts.delete
+local replace_node = nuts.replace
+local copy_node = nuts.copy
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local chardata = characters.data
+local collected = false
+local fontdata = fonts.hashes.identifiers
+
+local a_stripping = attributes.private("stripping")
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+-- todo: other namespace -> typesetters
+
+nodes.stripping = nodes.stripping or { } local stripping = nodes.stripping
+stripping.glyphs = stripping.glyphs or { } local glyphs = stripping.glyphs
+
+local function initialize()
+ for k,v in next, chardata do
+ if v.category == "cf" and v.visible ~= "yes" then
+ if not glyphs[k] then
+ glyphs[k] = true
+ end
+ end
+ end
+ initialize = nil
+end
+
+local function process(what,head,current,char)
+ if what == true then
+ if trace_stripping then
+ report_stripping("deleting %C from text",char)
+ end
+ head, current = delete_node(head,current)
+ elseif type(what) == "function" then
+ head, current = what(head,current)
+ current = getnext(current)
+ if trace_stripping then
+ report_stripping("processing %C in text",char)
+ end
+ elseif what then -- assume node
+ head, current = replace_node(head,current,copy_node(what))
+ current = getnext(current)
+ if trace_stripping then
+ report_stripping("replacing %C in text",char)
+ end
+ end
+ return head, current
+end
+
+function nodes.handlers.stripping(head)
+ head = tonut(head)
+ local current, done = head, false
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ -- it's more efficient to keep track of what needs to be kept
+ local todo = getattr(current,a_stripping)
+ if todo == 1 then
+ 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
+ else
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ return tonode(head), done
+end
+
+local enabled = false
+
+function stripping.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ if initialize then initialize() end
+ tasks.enableaction("processors","nodes.handlers.stripping")
+ enabled = true
+ end
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_stripping,n)
+end
+
+-- why not in task-ini?
+
+tasks.appendaction("processors","fonts","nodes.handlers.stripping",nil,"nodes.handlers.characters")
+tasks.disableaction("processors","nodes.handlers.stripping")
+
+-- interface
+
+interfaces.implement {
+ name = "setcharacterstripping",
+ actions = stripping.set,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-rep.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.mkiv
new file mode 100644
index 00000000000..c1146997e33
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.mkiv
@@ -0,0 +1,51 @@
+%D \module
+%D [ file=typo-rep,
+%D version=2010.05.23,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Stripping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Stripping}
+
+% experimental stripping
+
+%D For a while we had stripping of special chars built into the analyzer
+%D but Khaled suggested to generalize this so I changed the code into a
+%D manipulator there.
+%D
+%D \starttyping
+%D \definefontfeature[default][default][mode=node,formatters=strip]
+%D \stoptyping
+%D
+%D However, in \MKIV\ it makes more sense to also provide it as a more
+%D general feature. Here we implement this as experiment. I might
+%D cook up a few more variants in both variants.
+%D
+%D \starttyping
+%D \setcharacterstripping[1]
+%D \stoptyping
+
+\unprotect
+
+\registerctxluafile{typo-rep}{1.001}
+
+\definesystemattribute[stripping][public]
+
+\unexpanded\def\setcharacterstripping[#1]%
+ {\clf_setcharacterstripping{#1}}
+
+\unexpanded\def\resetcharacterstripping
+ {\attribute\strippingattribute\attributeunsetvalue}
+
+% maybe .. this might disappear, but is handy for testing
+
+\unexpanded\def\forcecharacterstripping % secret command
+ {\ctxlua{fonts.handlers.otf.features.register("formatters",true)}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv
new file mode 100644
index 00000000000..6249c390a93
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv
@@ -0,0 +1,268 @@
+%D \module
+%D [ file=typo-scr,
+%D version=2012.01.23, % very old ... 1995.10.10 .. moved from core-mis
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Scripts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Scripts}
+
+\unprotect
+
+%D I addition to the commands implemented here, we have alternative commands
+%D \type {shiftup} and \type {shiftdown} that can work across paragraphs.
+
+%D \macros
+%D {low, high, definelow, definehigh, setuplow, setuphigh}
+%D
+%D Although \TEX\ is pretty well aware of super- and subscripts, its mechanism
+%D is mainly tuned for math mode. The next few commands take care of script
+%D texts both modes.
+%D
+%D \startbuffer
+%D The higher\high{one goes} the lower\low{one drops}, or\lohi{yes}{no}?
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+%D
+%D Note the different placement of \type {\lohi}, where we need a bit more
+%D space. The implementation looks a bit fuzzy, since some \type {\fontdimen}'s
+%D are involved to determine the optimal placement.
+
+\installcorenamespace {low}
+\installcorenamespace {high}
+
+\installcommandhandler \??low {low} \??low
+\installcommandhandler \??high {high} \??high
+
+\setuplow [\c!style=\tx,\c!distance=\zeropoint,\c!down=.48\exheight] % historical
+\setuphigh[\c!style=\tx,\c!distance=\zeropoint,\c!up =.86\exheight] % values
+
+\appendtoks \setuevalue\currentlow {\typo_scripts_low {\currentlow }}\to \everydefinelow
+\appendtoks \setuevalue\currenthigh{\typo_scripts_high{\currenthigh}}\to \everydefinehigh
+
+\unexpanded\def\typo_scripts_low#1#2%
+ {\dontleavehmode
+ \begingroup
+ \edef\currentlow{#1}%
+ \kern\lowparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ \lower\lowparameter\c!down\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \uselowstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \uselowstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged\t!sub\currentlow
+ #2%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\typo_scripts_high#1#2%
+ {\dontleavehmode
+ \begingroup
+ \edef\currenthigh{#1}%
+ \kern\highparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ \raise\highparameter\c!up\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \usehighstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \usehighstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged\t!sup\currenthigh
+ #2%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\low {\typo_scripts_low \empty}
+\unexpanded\def\high{\typo_scripts_high\empty}
+
+%D \macros
+%D {lohi, hilo, definelohi, setuplohi}
+%D
+%D You can provide an optional keyword \type {left}, in which case the super and
+%D subscripts will be aligned in a way that permits placement at the left of a word
+%D (which means that it will be right aligned).
+%D
+%D \startbuffer
+%D \lohi {aha} {ah} test \lohi {aha} {ah} test
+%D \lohi [left] {aha} {ah} test \lohi [left] {aha} {ah} test
+%D \lohi {aha} {ah} test \lohi {aha} {ah} test
+%D \lohi [left] {aha} {ah}test \lohi [left] {aha} {ah} test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\installcorenamespace {lowhigh}
+
+\installcommandhandler \??lowhigh {lowhigh} \??lowhigh
+
+\setuplowhigh
+ [\c!style=\tx,
+ \c!distance=.1\exheight, % these are
+ \c!up=.96\exheight, % historical
+ \c!down=.58\exheight] % values
+
+\appendtoks
+ \setuevalue\currentlowhigh{\typo_scripts_lowhigh{\currentlowhigh}\typo_scripts_lowhigh_indeed}%
+\to \everydefinelowhigh
+
+\unexpanded\def\typo_scripts_lowhigh#1% #2
+ {\dontleavehmode
+ \hbox\bgroup
+ \edef\currentlowhigh{#1}%
+ \dosingleempty} % #2
+
+\unexpanded\def\typo_scripts_lowhigh_indeed[#1]#2#3% todo: align .. [#1] is compatible hack
+ {\dostarttagged\t!subsup\currentlowhigh
+ \setbox\plusfour\hbox{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}%
+ \setbox\plussix \hbox{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}%
+ \doif{#1}{\v!left}
+ {\ifdim\wd\plusfour<\wd\plussix
+ \setbox\plusfour\hbox to \wd\plussix {\hss\box\plusfour}%
+ \else
+ \setbox\plussix \hbox to \wd\plusfour{\hss\box\plussix }%
+ \fi}%
+ \ifdim\wd\plusfour<\wd\plussix
+ \wd\plusfour\zeropoint
+ \box\plusfour
+ \box\plussix
+ \else
+ \wd\plussix\zeropoint
+ \box\plussix
+ \box\plusfour
+ \fi
+ \dostoptagged
+ \egroup}
+
+\def\typo_scripts_lowhigh_low_high#1#2#3#4%
+ {\dontleavehmode
+ \begingroup
+ \kern\lowhighparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ #1\lowhighparameter#2\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \uselowhighstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \uselowhighstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged#3\empty
+ #4%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\typo_scripts_highlow_indeed[#1]#2#3%
+ {\typo_scripts_lowhigh_indeed[#1]{#3}{#2}}
+
+\unexpanded\def\lohi{\typo_scripts_lowhigh\empty\typo_scripts_lowhigh_indeed}
+\unexpanded\def\hilo{\typo_scripts_lowhigh\empty\typo_scripts_highlow_indeed}
+
+%D \macros
+%D {lowmidhigh, definelowmidhigh, setuplowmidhigh}
+%D
+%D The previous command originally didn't have definers. These were introduced when
+%D the next showed up:
+%D
+%D \startbuffer
+%D \definelow [MyLow] [style=\txx]
+%D \definehigh [MyHigh] [style=\txx]
+%D \definelowhigh [MyLoHi] [style=\txx]
+%D \definelowmidhigh[MyLoMiHi][style=\txx]
+%D
+%D We have
+%D \ruledhbox{\low {L}} and \ruledhbox{\MyLow {L}} and
+%D \ruledhbox{\high {H}} and \ruledhbox{\MyHigh {H}} and
+%D \ruledhbox{\lohi {L}{H}} and \ruledhbox{\MyLoHi {L}{H}} and
+%D \ruledhbox{\lomihi{L}{M}{H}} and \ruledhbox{\MyLoMiHi{L}{M}{H}}.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace {lowmidhigh}
+
+\installcommandhandler \??lowmidhigh {lowmidhigh} \??lowmidhigh
+
+\setuplowmidhigh
+ [\c!style=\tx,
+ \c!up=.8\struthtdp,
+ \c!down=.8\struthtdp]
+
+\appendtoks
+ \setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh{\currentlowmidhigh}}%
+\to \everydefinelowmidhigh
+
+\unexpanded\def\typo_scripts_lowmidhigh#1#2#3#4%
+ {\dontleavehmode \hbox \bgroup
+ \edef\currentlowmidhigh{#1}%
+ \dostarttagged\t!subsup\currentlowmidhigh
+ \uselowmidhighstyleandcolor\c!style\c!color
+ \setstrut
+ \setbox\plustwo \hbox{\strut\dostarttagged\t!sub\empty#2\dostoptagged}%
+ \setbox\plusfour\hbox{\strut\dostarttagged\t!mid\empty#3\dostoptagged}% inefficient
+ \setbox\plussix \hbox{\strut\dostarttagged\t!sup\empty#4\dostoptagged}%
+ \scratchdimen \wd
+ \ifdim\wd\plustwo>\wd\plusfour
+ \ifdim\wd\plustwo>\wd\plussix
+ \plustwo
+ \else
+ \plussix
+ \fi
+ \else
+ \ifdim\wd\plusfour>\wd\plussix
+ \plusfour
+ \else
+ \plussix
+ \fi
+ \fi
+ \relax
+ \setbox\plustwo \hbox to \scratchdimen{\hss\lower\lowmidhighparameter\c!down\box\plustwo \hss}%
+ \setbox\plusfour\hbox to \scratchdimen{\hss \box\plusfour\hss}%
+ \setbox\plussix \hbox to \scratchdimen{\hss\raise\lowmidhighparameter\c!up \box\plussix \hss}%
+ \wd\plustwo \zeropoint
+ \wd\plusfour\zeropoint
+ \box\plusfour
+ \box\plustwo
+ \box\plussix
+ \dostoptagged
+ \egroup}
+
+\unexpanded\def\lomihi {\typo_scripts_lowmidhigh\empty}
+\unexpanded\def\himilo#1#2#3{\typo_scripts_lowmidhigh\empty{#3}{#2}{#1}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua
new file mode 100644
index 00000000000..f00e3ae6b39
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua
@@ -0,0 +1,257 @@
+if not modules then modules = { } end modules ['typo-spa'] = {
+ version = 1.001,
+ comment = "companion to typo-spa.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+local utfchar = utf.char
+
+local trace_spacing = false trackers.register("typesetters.spacing", function(v) trace_spacing = v end)
+
+local report_spacing = logs.reporter("typesetting","spacing")
+
+local nodes, fonts, node = nodes, fonts, node
+
+local tasks = nodes.tasks
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local quaddata = fonthashes.quads
+
+local texsetattribute = tex.setattribute
+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 getattr = nuts.getattr
+local setattr = nuts.setattr
+local isglyph = nuts.isglyph
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+local end_of_math = nuts.end_of_math
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local math_code = nodecodes.math
+
+local somespace = nodes.somespace
+local somepenalty = nodes.somepenalty
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.spacings = typesetters.spacings or { }
+local spacings = typesetters.spacings
+
+spacings.mapping = spacings.mapping or { }
+spacings.numbers = spacings.numbers or { }
+
+local a_spacings = attributes.private("spacing")
+
+storage.register("typesetters/spacings/mapping", spacings.mapping, "typesetters.spacings.mapping")
+
+local mapping = spacings.mapping
+local numbers = spacings.numbers
+
+for i=1,#mapping do
+ local m = mapping[i]
+ numbers[m.name] = m
+end
+
+-- todo cache lastattr
+
+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
+ while start do
+ local char, id = isglyph(start)
+ if char then
+ local attr = getattr(start,a_spacings)
+ if attr and attr > 0 then
+ local data = mapping[attr]
+ if data then
+ local map = data.characters[char]
+ setattr(start,a_spacings,unsetvalue) -- needed?
+ if map then
+ local left = map.left
+ local right = map.right
+ local alternative = map.alternative
+ local quad = quaddata[getfont(start)]
+ local prev = getprev(start)
+ if left and left ~= 0 and prev then
+ local ok = false
+ local prevprev = getprev(prev)
+ if alternative == 1 then
+ local somespace = somespace(prev,true)
+ if somespace then
+ local somepenalty = somepenalty(prevprev,10000)
+ if somepenalty then
+ if trace_spacing then
+ report_spacing("removing penalty and space before %C (left)",char)
+ end
+ head = remove_node(head,prev,true)
+ head = remove_node(head,prevprev,true)
+ else
+ if trace_spacing then
+ report_spacing("removing space before %C (left)",char)
+ end
+ head = remove_node(head,prev,true)
+ end
+ end
+ ok = true
+ else
+ ok = not (somespace(prev,true) and somepenalty(prevprev,true)) or somespace(prev,true)
+ end
+ if ok then
+ if trace_spacing then
+ report_spacing("inserting penalty and space before %C (left)",char)
+ 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)
+ if right and right ~= 0 and next then
+ local ok = false
+ local nextnext = getnext(next)
+ if alternative == 1 then
+ local somepenalty = somepenalty(next,10000)
+ if somepenalty then
+ local somespace = somespace(nextnext,true)
+ if somespace then
+ if trace_spacing then
+ report_spacing("removing penalty and space after %C right",char)
+ end
+ head = remove_node(head,next,true)
+ head = remove_node(head,nextnext,true)
+ end
+ else
+ local somespace = somespace(next,true)
+ if somespace then
+ if trace_spacing then
+ report_spacing("removing space after %C (right)", char)
+ end
+ head = remove_node(head,next,true)
+ end
+ end
+ ok = true
+ else
+ ok = not (somepenalty(next,10000) and somespace(nextnext,true)) or somespace(next,true)
+ end
+ if ok then
+ if trace_spacing then
+ report_spacing("inserting penalty and space after %C (right)",char)
+ end
+ insert_node_after(head,start,new_glue(right*quad))
+ insert_node_after(head,start,new_penalty(10000))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ elseif id == math_code then
+ start = end_of_math(start) -- weird, can return nil .. no math end?
+ end
+ if start then
+ start = getnext(start)
+ end
+ end
+ return tonode(head), done
+end
+
+local enabled = false
+
+function spacings.define(name)
+ local data = numbers[name]
+ if data then
+ -- error
+ else
+ local number = #mapping + 1
+ local data = {
+ name = name,
+ number = number,
+ characters = { },
+ }
+ mapping[number] = data
+ numbers[name] = data
+ end
+end
+
+function spacings.setup(name,char,settings)
+ local data = numbers[name]
+ if not data then
+ -- error
+ else
+ data.characters[char] = settings
+ end
+end
+
+function spacings.set(name)
+ local n = unsetvalue
+ if name ~= v_reset then
+ local data = numbers[name]
+ if data then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.spacings.handler")
+ enabled = true
+ end
+ n = data.number or unsetvalue
+ end
+ end
+ texsetattribute(a_spacings,n)
+end
+
+function spacings.reset()
+ texsetattribute(a_spacings,unsetvalue)
+end
+
+-- interface
+
+local implement = interfaces.implement
+
+implement {
+ name = "definecharacterspacing",
+ actions = spacings.define,
+ arguments = "string"
+}
+
+implement {
+ name = "setupcharacterspacing",
+ actions = spacings.setup,
+ arguments = {
+ "string",
+ "integer",
+ {
+ { "left", "number" },
+ { "right", "number" },
+ { "alternative", "integer" },
+ }
+ }
+}
+
+implement {
+ name = "setcharacterspacing",
+ actions = spacings.set,
+ arguments = "string"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-spa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.mkiv
new file mode 100644
index 00000000000..2e3e71bf3b3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.mkiv
@@ -0,0 +1,81 @@
+%D \module
+%D [ file=typo-spa,
+%D version=2009.03.27, % code moved from cors-spa.mkiv
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Spacing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Spacing}
+
+\unprotect
+
+\registerctxluafile{typo-spa}{1.001}
+
+\definesystemattribute[spacing][public]
+
+% experimental spacing
+%
+% test: oeps {\setcharacterspacing[frenchpunctuation]x: xx \bfd x: xx} oeps: test
+%
+% todo: page | text => pagebody or text only
+
+\installcorenamespace{characterspacing}
+
+\installsetuponlycommandhandler \??characterspacing {_p_characterspacing} % private
+
+\setup_p_characterspacing
+ [\c!left=0,
+ \c!right=0,
+ \c!alternative=0]
+
+\unexpanded\def\definecharacterspacing[#1]%
+ {\clf_definecharacterspacing{#1}}
+
+\unexpanded\def\setupcharacterspacing
+ {\dotripleargument\typo_characterspacing_setup}
+
+\def\typo_characterspacing_setup[#1][#2][#3]% todo: #2 list
+ {\begingroup
+ \setupcurrent_p_characterspacing[#3]%
+ \clf_setupcharacterspacing
+ {#1}%
+ \numexpr#2\relax
+ {%
+ left \direct_p_characterspacingparameter\c!left\space
+ right \direct_p_characterspacingparameter\c!right\space
+ alternative \direct_p_characterspacingparameter\c!alternative
+ }%
+ \relax
+ \endgroup}
+
+\unexpanded\def\setcharacterspacing[#1]% we can store the attribute if we want speed
+ {\clf_setcharacterspacing{#1}}
+
+\unexpanded\def\resetcharacterspacing % fast one
+ {\attribute\spacingattribute\attributeunsetvalue}
+
+\appendtoks
+ \resetcharacterspacing
+\to \everyresettypesetting
+
+% \setcharacterspacing[frenchpunctuation]
+% «\type{bla}»\crlf « \type{bla}»\crlf
+% «bla »\crlf « bla»\crlf « bla »\crlf
+% bla: bla\crlf bla : bla
+
+\definecharacterspacing [frenchpunctuation] % name may change / unit is em
+
+\setupcharacterspacing [frenchpunctuation] ["003A] [\c!left =.25,\c!alternative=1] % : % strip preceding space(char)
+\setupcharacterspacing [frenchpunctuation] ["003B] [\c!left =.25,\c!alternative=1] % ; % strip preceding space(char)
+\setupcharacterspacing [frenchpunctuation] ["003F] [\c!left =.25,\c!alternative=1] % ? % strip preceding space(char)
+\setupcharacterspacing [frenchpunctuation] ["0021] [\c!left =.25,\c!alternative=1] % ! % strip preceding space(char)
+\setupcharacterspacing [frenchpunctuation] ["00AB] [\c!right=.25,\c!alternative=1] % guillemotleft/leftguillemot % strip following space(char)
+\setupcharacterspacing [frenchpunctuation] ["00BB] [\c!left =.25,\c!alternative=1] % guillemotright/rightguillemot % strip preceding space(char)
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua
new file mode 100644
index 00000000000..ce193333050
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua
@@ -0,0 +1,311 @@
+if not modules then modules = { } end modules ['typo-sus'] = {
+ version = 1.001,
+ comment = "companion to typo-sus.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local punctuation = {
+ po = true,
+}
+
+local openquote = {
+ ps = true,
+ pi = true,
+}
+
+local closequote = {
+ pe = true,
+ pf = true,
+}
+
+local weird = {
+ lm = true,
+ no = true,
+}
+
+local categories = characters.categories
+
+local nodecodes = nodes.nodecodes
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+local glue_code = nodecodes.glue
+local math_code = nodecodes.math
+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
+local getnext = nuts.getnext
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local getfont = nuts.getfont
+local getlist = nuts.getlist
+local isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlist = nuts.setlist
+
+local setcolor = nodes.tracers.colors.set
+local insert_before = nuts.insert_before
+local insert_after = nuts.insert_after
+local end_of_math = nuts.end_of_math
+
+local nodepool = nuts.pool
+
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_hlist = nodepool.hlist
+----- new_penalty = nodepool.penalty
+
+local a_characters = attributes.private("characters")
+local a_suspecting = attributes.private('suspecting')
+local a_suspect = attributes.private('suspect')
+local texsetattribute = tex.setattribute
+local enabled = false
+
+local threshold = 65536 / 4
+
+local function special(n)
+ if n then
+ local id = getid(n)
+ if id == kern_code then
+ local kern = getfield(n,"kern")
+ return kern < threshold
+ elseif id == penalty_code then
+ return true
+ elseif id == glue_code then
+ local width = getfield(n,"width")
+ return width < threshold
+ elseif id == hlist_code then
+ local width = getfield(n,"width")
+ return width < threshold
+ end
+ else
+ return false
+ end
+end
+
+local function goback(current)
+ local prev = getprev(current)
+ while prev and special(prev) do
+ prev = getprev(prev)
+ end
+ if prev then
+ return prev, getid(prev)
+ end
+end
+
+local function goforward(current)
+ local next = getnext(current)
+ while next and special(next) do
+ next = getnext(next)
+ end
+ if next then
+ return next, getid(next)
+ end
+end
+
+local function mark(head,current,id,color)
+ if id == glue_code then
+ -- the glue can have stretch and/or shrink so the rule can overlap with the
+ -- following glyph .. no big deal as that one then sits on top of the rule
+ local width = getfield(current,"width")
+ local rule = new_rule(width)
+ local kern = new_kern(-width)
+ head = insert_before(head,current,rule)
+ head = insert_before(head,current,kern)
+ setcolor(rule,color)
+ -- elseif id == kern_code then
+ -- local width = getfield(current,"kern")
+ -- local rule = new_rule(width)
+ -- local kern = new_kern(-width)
+ -- head = insert_before(head,current,rule)
+ -- head = insert_before(head,current,kern)
+ -- setcolor(rule,color)
+ else
+ local width = getfield(current,"width")
+ local extra = fonts.hashes.xheights[getfont(current)] / 2
+ local rule = new_rule(width,getfield(current,"height")+extra,getfield(current,"depth")+extra)
+ local hlist = new_hlist(rule)
+ head = insert_before(head,current,hlist)
+ setcolor(rule,color)
+ setcolor(current,"white")
+ end
+ return head, current
+end
+
+-- we can cache the font and skip ahead to next but it doesn't
+-- save enough time and it makes the code looks bad too ... after
+-- all, we seldom use this
+
+local colors = {
+ "darkred",
+ "darkgreen",
+ "darkblue",
+ "darkcyan",
+ "darkmagenta",
+ "darkyellow",
+ "darkgray",
+ "orange",
+}
+
+local found = 0
+
+function typesetters.marksuspects(head)
+ local head = tonut(head)
+ local current = head
+ local lastdone = nil
+ while current do
+ if getattr(current,a_suspecting) then
+ local char, id = isglyph(current)
+ if char then
+ local code = categories[char]
+ local done = false
+ if punctuation[code] then
+ local prev, pid = goback(current)
+ if prev and pid == glue_code then
+ done = 3 -- darkblue
+ elseif prev and pid == math_code then
+ done = 3 -- darkblue
+ else
+ local next, nid = goforward(current)
+ if next and nid ~= glue_code then
+ done = 3 -- darkblue
+ end
+ end
+ elseif openquote[code] then
+ local next, nid = goforward(current)
+ if next and nid == glue_code then
+ done = 1 -- darkred
+ end
+ elseif closequote[code] then
+ local prev, pid = goback(current)
+ if prev and pid == glue_code then
+ done = 1 -- darkred
+ end
+ elseif weird[code] then
+ done = 2 -- darkgreen
+ else
+ local prev, pid = goback(current)
+ if prev then
+ if pid == math_code then
+ done = 7-- darkgray
+ elseif pid == glyph_code and getfont(current) ~= getfont(prev) then
+ if lastdone ~= prev then
+ done = 2 -- darkgreen
+ end
+ end
+ end
+ if not done then
+ local next, nid = goforward(current)
+ if next then
+ if nid == math_code then
+ done = 7 -- darkgray
+ elseif nid == glyph_code and getfont(current) ~= getfont(next) then
+ if lastdone ~= prev then
+ done = 2 -- darkgreen
+ end
+ end
+ end
+ end
+ end
+ if done then
+ setattr(current,a_suspect,done)
+ lastdone = current
+ found = found + 1
+ end
+ current = getnext(current)
+ elseif id == math_code then
+ current = getnext(end_of_math(current))
+ elseif id == glue_code then
+ local a = getattr(current,a_characters)
+ if a then
+ local prev = getprev(current)
+ local prid = prev and getid(prev)
+ local done = false
+ if prid == penalty_code and getfield(prev,"penalty") == 10000 then
+ done = 8 -- orange
+ else
+ done = 5 -- darkmagenta
+ end
+ if done then
+ setattr(current,a_suspect,done)
+ -- lastdone = current
+ found = found + 1
+ end
+ end
+ current = getnext(current)
+ else
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ return tonode(head), found > 0
+end
+
+local function showsuspects(head)
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ local a = getattr(current,a_suspect)
+ if a then
+ head, current = mark(head,current,id,colors[a])
+ end
+ elseif id == glue_code then
+ local a = getattr(current,a_suspect)
+ if a then
+ head, current = mark(head,current,id,colors[a])
+ end
+ elseif id == math_code then
+ current = end_of_math(current)
+ elseif id == hlist_code or id == vlist_code then
+ local list = getlist(current)
+ if list then
+ local l = showsuspects(list)
+ if l ~= list then
+ setlist(current,l)
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ return head
+end
+
+function typesetters.showsuspects(head)
+ if found > 0 then
+ return tonode(showsuspects(tonut(head))), true
+ else
+ return head, false
+ end
+end
+
+nodes.tasks.appendaction ("processors","after", "typesetters.marksuspects")
+nodes.tasks.prependaction("shipouts", "normalizers","typesetters.showsuspects")
+
+nodes.tasks.disableaction("processors","typesetters.marksuspects")
+nodes.tasks.disableaction("shipouts", "typesetters.showsuspects")
+
+-- or maybe a directive
+
+trackers.register("typesetters.suspects",function(v)
+ texsetattribute(a_suspecting,v and 1 or unsetvalue)
+ if v and not enabled then
+ nodes.tasks.enableaction("processors","typesetters.marksuspects")
+ nodes.tasks.enableaction("shipouts", "typesetters.showsuspects")
+ enabled = true
+ end
+end)
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-sus.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.mkiv
new file mode 100644
index 00000000000..fe44e63277b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.mkiv
@@ -0,0 +1,51 @@
+%D \module
+%D [ file=typo-sus,
+%D version=2014.11.06,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Checking Suspects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Checking Suspects}
+
+%D This is a rather special module, mostly needed by ourselves for
+%D projects where copy||editing is not that precise.
+
+\registerctxluafile{typo-sus}{1.001}
+
+\unexpanded\def\showsuspects{\enabletrackers[typesetters.suspects]}
+
+%D The suspicious spacing will be colored in the text. There can be false
+%D positives but this features is mostly used when proofreading. So, we
+%D don't worry too much about interference (and efficiency).
+%D
+%D \unexpanded\def\showsample#1%
+%D {\NC \type{#1}%
+%D \NC \enabletrackers[typesetters.suspects]#1\disabletrackers[typesetters.spacing]%
+%D \NC \NR}
+%D
+%D \starttabulate[|||][before=,after=]
+%D \showsample{foo$x$}
+%D \showsample{$x$bar}
+%D \showsample{foo$x$bar}
+%D \showsample{$f+o+o$:}
+%D \showsample{;$f+o+o$}
+%D \showsample{; bar}
+%D \showsample{foo:bar}
+%D \showsample{\quote{ foo }}
+%D \showsample{\quote{bar }}
+%D \showsample{\quote{ bar}}
+%D \showsample{(foo )}
+%D \showsample{\{foo \}}
+%D \showsample{foo{\bf gnu}bar}
+%D \showsample{foo$x^2$bar}
+%D \showsample{foo\nobreakspace bar}
+%D \stoptabulate
+
+\endinput
+
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua
new file mode 100644
index 00000000000..a67cd0a4b47
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua
@@ -0,0 +1,390 @@
+if not modules then modules = { } end modules ['typo-tal'] = {
+ version = 1.001,
+ comment = "companion to typo-tal.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- I'll make it a bit more efficient and provide named instances too which is needed for
+-- nested tables.
+--
+-- Currently we have two methods: text and number with some downward compatible
+-- defaulting.
+
+-- We can speed up by saving the current fontcharacters[font] + lastfont.
+
+local next, type = next, type
+local div = math.div
+local utfbyte = utf.byte
+
+local splitmethod = utilities.parsers.splitmethod
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+
+local fontcharacters = fonts.hashes.characters
+----- unicodes = fonts.hashes.unicodes
+local categories = characters.categories -- nd
+
+local variables = interfaces.variables
+local v_text = variables.text
+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
+local getid = nuts.getid
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local isglyph = nuts.isglyph
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+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 dimensions_of_list = nuts.dimensions
+local first_glyph = nuts.first_glyph
+
+local setglue = nuts.setglue
+
+local nodepool = nuts.pool
+local new_kern = nodepool.kern
+
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local tracedrule = tracers.pool.nuts.rule
+
+local characteralign = { }
+typesetters.characteralign = characteralign
+
+local trace_split = false trackers.register("typesetters.characteralign", function(v) trace_split = true end)
+local report = logs.reporter("aligning")
+
+local a_characteralign = attributes.private("characteralign")
+local a_character = attributes.private("characters")
+
+local enabled = false
+
+local datasets = false
+
+local implement = interfaces.implement
+
+local comma = 0x002C
+local period = 0x002E
+local punctuationspace = 0x2008
+
+local validseparators = {
+ [comma] = true,
+ [period] = true,
+ [punctuationspace] = true,
+}
+
+local validsigns = {
+ [0x002B] = 0x002B, -- plus
+ [0x002D] = 0x2212, -- hyphen
+ [0x00B1] = 0x00B1, -- plusminus
+ [0x2212] = 0x2212, -- minus
+ [0x2213] = 0x2213, -- minusplus
+}
+
+-- If needed we can have more modes which then also means a faster simple handler
+-- for non numbers.
+
+local function setcharacteralign(column,separator)
+ if not enabled then
+ nodes.tasks.enableaction("processors","typesetters.characteralign.handler")
+ enabled = true
+ end
+ if not datasets then
+ datasets = { }
+ end
+ local dataset = datasets[column] -- we can use a metatable
+ if not dataset then
+ local method, token
+ if separator then
+ method, token = splitmethod(separator)
+ if method and token then
+ separator = utfbyte(token) or comma
+ else
+ separator = utfbyte(separator) or comma
+ method = validseparators[separator] and v_number or v_text
+ end
+ else
+ separator = comma
+ method = v_number
+ end
+ dataset = {
+ separator = separator,
+ list = { },
+ maxafter = 0,
+ maxbefore = 0,
+ collected = false,
+ method = method,
+ separators = validseparators,
+ signs = validsigns,
+ }
+ datasets[column] = dataset
+ used = true
+ end
+ return dataset
+end
+
+local function resetcharacteralign()
+ datasets = false
+end
+
+characteralign.setcharacteralign = setcharacteralign
+characteralign.resetcharacteralign = resetcharacteralign
+
+implement {
+ name = "setcharacteralign",
+ actions = setcharacteralign,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "resetcharacteralign",
+ actions = resetcharacteralign
+}
+
+local function traced_kern(w)
+ return tracedrule(w,nil,nil,"darkgray")
+end
+
+function characteralign.handler(originalhead,where)
+ if not datasets then
+ return originalhead, false
+ 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
+ first = n
+ break
+ end
+ if not first then
+ return originalhead, false
+ end
+ local a = getattr(first,a_characteralign)
+ if not a or a == 0 then
+ return originalhead, false
+ end
+ local column = div(a,0xFFFF)
+ local row = a % 0xFFFF
+ local dataset = datasets and datasets[column] or setcharacteralign(column)
+ local separator = dataset.separator
+ local list = dataset.list
+ local b_start = nil
+ local b_stop = nil
+ local a_start = nil
+ local a_stop = nil
+ local c = nil
+ local current = first
+ local sign = nil
+ --
+ local validseparators = dataset.separators
+ local validsigns = dataset.signs
+ local method = dataset.method
+ -- we can think of constraints
+ if method == v_number then
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local font = getfont(current)
+ -- local unicode = unicodes[font][char]
+ local unicode = fontcharacters[font][char].unicode or char -- ignore tables
+ if not unicode then
+ -- no unicode so forget about it
+ elseif unicode == separator then
+ c = current
+ if trace_split then
+ setcolor(current,"darkred")
+ end
+ dataset.hasseparator = true
+ elseif categories[unicode] == "nd" or validseparators[unicode] then
+ if c then
+ if not a_start then
+ a_start = current
+ end
+ a_stop = current
+ if trace_split then
+ setcolor(current,validseparators[unicode] and "darkcyan" or "darkblue")
+ end
+ else
+ 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
+ if trace_split then
+ setcolor(sign,"darkyellow")
+ end
+ else
+ setchar(sign,new)
+ if trace_split then
+ setcolor(sign,"darkmagenta")
+ end
+ end
+ sign = nil
+ b_stop = current
+ else
+ b_start = current
+ b_stop = current
+ end
+ else
+ b_stop = current
+ end
+ if trace_split and current ~= sign then
+ setcolor(current,validseparators[unicode] and "darkcyan" or "darkblue")
+ end
+ end
+ elseif not b_start then
+ sign = validsigns[unicode] and current
+ -- if trace_split then
+ -- setcolor(current,"darkgreen")
+ -- end
+ end
+ elseif (b_start or a_start) and id == glue_code then
+ -- maybe only in number mode
+ -- somewhat inefficient
+ local next = getnext(current)
+ local prev = getprev(current)
+ if next and prev and getid(next) == glyph_code and getid(prev) == glyph_code then -- too much checking
+ local width = fontcharacters[getfont(b_start)][separator or period].width
+ setglue(current,width)
+ setattr(current,a_character,punctuationspace)
+ if a_start then
+ a_stop = current
+ elseif b_start then
+ b_stop = current
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ else
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local font = getfont(current)
+ -- local unicode = unicodes[font][char]
+ local unicode = fontcharacters[font][char].unicode or char -- ignore tables
+ if not unicode then
+ -- no unicode so forget about it
+ elseif unicode == separator then
+ c = current
+ if trace_split then
+ setcolor(current,"darkred")
+ end
+ dataset.hasseparator = true
+ else
+ if c then
+ if not a_start then
+ a_start = current
+ end
+ a_stop = current
+ if trace_split then
+ setcolor(current,"darkgreen")
+ end
+ else
+ if not b_start then
+ b_start = current
+ end
+ b_stop = current
+ if trace_split then
+ setcolor(current,"darkblue")
+ end
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ end
+ local entry = list[row]
+ if entry then
+ if not dataset.collected then
+ -- print("[maxbefore] [maxafter]")
+ local maxbefore = 0
+ local maxafter = 0
+ for k, v in next, list do
+ local before = v.before
+ local after = v.after
+ if before and before > maxbefore then
+ maxbefore = before
+ end
+ if after and after > maxafter then
+ maxafter = after
+ end
+ end
+ dataset.maxbefore = maxbefore
+ dataset.maxafter = maxafter
+ dataset.collected = true
+ end
+ local maxbefore = dataset.maxbefore
+ local maxafter = dataset.maxafter
+ local before = entry.before or 0
+ local after = entry.after or 0
+ local new_kern = trace_split and traced_kern or new_kern
+ if b_start then
+ if before < maxbefore then
+ head = insert_node_before(head,b_start,new_kern(maxbefore-before))
+ end
+ if not c then
+ -- print("[before]")
+ if dataset.hasseparator then
+ local width = fontcharacters[getfont(b_stop)][separator].width
+ insert_node_after(head,b_stop,new_kern(maxafter+width))
+ end
+ elseif a_start then
+ -- print("[before] [separator] [after]")
+ if after < maxafter then
+ insert_node_after(head,a_stop,new_kern(maxafter-after))
+ end
+ else
+ -- print("[before] [separator]")
+ if maxafter > 0 then
+ insert_node_after(head,c,new_kern(maxafter))
+ end
+ end
+ elseif a_start then
+ if c then
+ -- print("[separator] [after]")
+ if maxbefore > 0 then
+ head = insert_node_before(head,c,new_kern(maxbefore))
+ end
+ else
+ -- print("[after]")
+ local width = fontcharacters[getfont(b_stop)][separator].width
+ head = insert_node_before(head,a_start,new_kern(maxbefore+width))
+ end
+ if after < maxafter then
+ insert_node_after(head,a_stop,new_kern(maxafter-after))
+ end
+ elseif c then
+ -- print("[separator]")
+ if maxbefore > 0 then
+ head = insert_node_before(head,c,new_kern(maxbefore))
+ end
+ if maxafter > 0 then
+ insert_node_after(head,c,new_kern(maxafter))
+ end
+ end
+ else
+ entry = {
+ before = b_start and dimensions_of_list(b_start,getnext(b_stop)) or 0,
+ after = a_start and dimensions_of_list(a_start,getnext(a_stop)) or 0,
+ }
+ list[row] = entry
+ end
+ return tonode(head), true
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.mkiv
new file mode 100644
index 00000000000..570f1a1f56e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.mkiv
@@ -0,0 +1,177 @@
+%D \module
+%D [ file=typo-tal, % spac-cha (2012.06.08) supp-ali (2000.04.17)
+%D version=2013.10.04,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Character Alignment,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Character Alignment}
+
+%D This module replaces the \MKII\ character alignment code which hooked into
+%D table mechanisms but used parsing. In fact, this might be one of these cases
+%D where a \TEX\ based solution is faster, but a \LUA\ one a bit more robust.
+%D Anyway, as I had to fix something (to fit the newer table mechanisms) I
+%D decided to go the mixed route, a rather easy going effort in the aftermath of
+%D the 2013 \CONTEXT\ meeting.
+
+\unprotect
+
+\registerctxluafile{typo-tal}{1.001}
+
+\definesystemattribute[characteralign][public]
+
+%D This mechanism is mostly meant for tables:
+%D
+%D \startbuffer
+%D \starttabulate[|l|g{,}|r|]
+%D \NC test \NC 1.234.456,99 \NC \NC test \NR
+%D \NC test \NC 234.456,9 \NC \NC test \NR
+%D \NC test \NC 234.456 \NC \NC test \NR
+%D \NC test \NC 456 \NC \NC test \NR
+%D \NC test \NC \bf whatever \NC \NC test \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+% D \startbuffer
+% D \bTABLE
+% D \bTR \bTD[aligncharacter=yes] € 1,1 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 11,11 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 12\punctuationspace111,11 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 12 111,11 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 1.234.451,22222 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 234.451,2 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 234.451 \eTD \eTR
+% D \bTR \bTD[aligncharacter=yes] € 451 \eTD \eTR
+% D \bTR \bTD \bf some text \eTD \eTR
+% D \eTABLE
+% D \stopbuffer
+% D
+% D \typebuffer \blank \getbuffer \blank
+
+\unexpanded\def\signalcharacteralign#1#2{\attribute\characteralignattribute\numexpr#1*\maxcardminusone+#2\relax} % 0xFFFF
+\unexpanded\def\setcharacteralign #1#2{\clf_setcharacteralign#1{#2}}
+\unexpanded\def\resetcharacteralign {\clf_resetcharacteralign}
+\unexpanded\def\nocharacteralign {\attribute\characteralignattribute\attributeunsetvalue}
+
+%D Mostly downward compatible:
+%D
+%D \startbuffer
+%D \startcharacteralign
+%D \checkcharacteralign{123.456,78}
+%D \checkcharacteralign{456}
+%D \checkcharacteralign{23.456}
+%D \checkcharacteralign{78,9}
+%D \stopcharacteralign
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+%D We have (currently) two modes: \type {text} and \type {number}. The handler tries
+%D to determine the mode automatically. When using periods and commas as separators
+%D the \type {number} mode is chosen. If you use for instance a \type {-} as
+%D separator, \type {text} is chosen, but you can enforce \type {number} with \type
+%D {number->-} (as with other mechanisms, the arrow indicates a methot to apply).
+%D
+%D One can use \type {\nocharacteralign} to disable this mechanism, for instance in
+%D a table cell.
+
+\def\alignmentcharacter{,}
+
+\unexpanded\def\typo_charalign_pass_one
+ {\advance\scratchcounter\plusone
+ \setbox\scratchbox\typo_charalign_pass}
+
+\unexpanded\def\typo_charalign_pass_two
+ {\advance\scratchcounter\plusone
+ \typo_charalign_pass}
+
+\def\typo_charalign_pass
+ {\hbox\bgroup\signalcharacteralign\plusone\scratchcounter\let\next}
+
+\unexpanded\def\startcharacteralign
+ {\dosingleempty\typo_charalign_start}
+
+\def\typo_charalign_start[#1]#2\stopcharacteralign
+ {\bgroup
+ \edef\m_temp{#1}%
+ \ifx\m_temp\empty \else
+ \let\alignmentcharacter\m_temp
+ \fi
+ \setcharacteralign\plusone\alignmentcharacter
+ \begingroup
+ \scratchcounter\zerocount
+ \let\checkcharacteralign\typo_charalign_pass_one
+ \settrialtypesetting
+ #2\relax
+ \endgroup
+ \begingroup
+ \scratchcounter\zerocount
+ \let\checkcharacteralign\typo_charalign_pass_two
+ #2\relax
+ \endgroup
+ \resetcharacteralign
+ \egroup}
+
+\let\stopcharacteralign \relax
+\let\checkcharacteralign\gobbleoneargument
+
+\def\setfirstpasscharacteralign {\let\checkcharacteralign\gobbleoneargument}
+\def\setsecondpasscharacteralign{\let\checkcharacteralign\firstofoneargument}
+
+%D We need fonts to provide tabular digits that is, the digits need to have the same
+%D width.
+%D
+%D \startbuffer
+%D \startbuffer[demo]
+%D \switchtobodyfont[pagella]
+%D \setupTABLE[column][1][alignmentcharacter=.,aligncharacter=yes]
+%D \bTABLE
+%D \bTR \bTD 11.111 \eTD \bTD 11.111 \eTD \eTR
+%D \bTR \bTD 2.2 \eTD \bTD 2.2 \eTD \eTR
+%D \bTR \bTD 444.444 \eTD \bTD 444.444 \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \start inlinenumbers: \crlf \addfeature[inlinenumbers] \getbuffer \stop
+%D \start tabularnumbers: \crlf \addfeature[tabularnumbers] \getbuffer \stop
+%D \start oldstylenumbers:\crlf \addfeature[oldstylenumbers] \getbuffer \stop
+%D \stopbuffer
+%D
+%D \enabledirectives[typesetters.characteralign.autofont]
+%D \typebuffer \blank \getbuffer \blank
+%D \disabledirectives[typesetters.characteralign.autofont]
+%D \typebuffer \blank \getbuffer \blank
+%D \enabledirectives[typesetters.characteralign.autofont]
+
+\definefontfeature
+ [system:tabnum]
+ [tnum=yes,
+ lnum=no]
+
+\newconditional\c_tabl_ntb_char_align_auto_font \settrue\c_tabl_ntb_char_align_auto_font
+
+\installtexdirective % yes or no ?
+ {typesetters.characteralign.autofont}
+ {\settrue \c_tabl_ntb_char_align_auto_font}
+ {\setfalse\c_tabl_ntb_char_align_auto_font}
+
+\def\m_font_feature_auto_tabnum{system:tabnum}
+
+\unexpanded\def\typo_charalign_adapt_font_indeed
+ {\let\m_font_feature_asked\m_font_feature_auto_tabnum
+ \font_feature_reset_add_indeed}
+
+\def\typo_charalign_adapt_font % slow but seldom used (expanded in preamble)
+ {\ifconditional\c_tabl_ntb_char_align_auto_font
+ \typo_charalign_adapt_font_indeed
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-txt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/typo-txt.mkvi
new file mode 100644
index 00000000000..7562fe70cd0
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-txt.mkvi
@@ -0,0 +1,244 @@
+%D \module
+%D [ file=typo-txt,
+%D version=2011.10.27,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Text Hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module replaces the by now rather old supp-fun module.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Text Hacks}
+
+\unprotect
+
+% registerctxluafile{typo-txt}{1.001}
+
+%D \macros
+%D {normalizefontheight,normalizefontwidth,normalizedfontsize}
+%D
+%D Next we introduce some font manipulation macros. When we
+%D want to typeset some text spread in a well defined area, it
+%D can be considered bad practice to manipulate character and
+%D word spacing. In such situations the next few macros can be
+%D of help:
+%D
+%D \starttyping
+%D \normalizefontheight \name {sample text} {height} {font}
+%D \normalizefontwidth \name {sample text} {width} {font}
+%D \stoptyping
+%D
+%D Consider for instance:
+%D
+%D \startbuffer[a]
+%D \normalizefontheight \TempFont {X} {2\baselineskip} {Serif}
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \ruledhbox{\TempFont To Be Or Not To Be}
+%D \stopbuffer
+%D
+%D \typebuffer[a,b] \getbuffer[a]
+%D
+%D This shows up as:
+%D
+%D \startlinecorrection
+%D \ruledhbox{\getbuffer[b]}
+%D \stoplinecorrection
+%D
+%D The horizontal counterpart is:
+%D
+%D \startbuffer[a]
+%D \normalizefontwidth \TempFont {This Line Fits} {\hsize} {Serif}
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \ruledhbox{\TempFont This Line Fits}
+%D \stopbuffer
+%D
+%D \typebuffer[a,b] \getbuffer[a]
+%D
+%D This gives:
+%D
+%D \startlinecorrection
+%D \ruledhbox{\getbuffer[b]}
+%D \stoplinecorrection
+%D
+%D The calculated font scale is avaliable in \type {\normalizedfontsize}.
+
+\newbox\b_typo_normalizers
+
+\def\typo_normalizers_size#axis#size%
+ {\dimexpr\ifdim#1\b_typo_normalizers=\zeropoint
+ \bodyfontsize
+ \else
+ \luaexpr{\number\dimexpr10pt\relax*\number\dimexpr#size\relax/\number#axis\b_typo_normalizers}\scaledpoint
+ \fi\relax}
+
+\def\typo_normalizers_font_at_size#axis#cs#text#size#font% avoid overflow by using lua
+ {\begingroup
+ \setbox\b_typo_normalizers\hbox{\definedfont[#font at 10pt]\settrialtypesetting#text}%
+ \normalexpanded{\endgroup\edef\noexpand\normalizedfontsize{\the\typo_normalizers_size{#axis}{#size}}}%
+ \definefont[\strippedcsname#cs][#font at \normalizedfontsize]}
+
+\unexpanded\def\typo_normalizers_text_at_size#axis#font#size#text%
+ {\dontleavehmode
+ \begingroup
+ \setbox\b_typo_normalizers\hbox{\definedfont[#font at 10pt]\settrialtypesetting#text}%
+ \definedfont[#font at \the\typo_normalizers_size{#axis}{#size}]#text%
+ \endgroup}
+
+\def\normalizedfontsize{\bodyfontsize}
+
+\unexpanded\def\normalizetextwidth {\typo_normalizers_text_at_size\wd}
+\unexpanded\def\normalizetextheight{\typo_normalizers_text_at_size\ht}
+\unexpanded\def\normalizetextdepth {\typo_normalizers_text_at_size\dp}
+\unexpanded\def\normalizetextline {\typo_normalizers_text_at_size\htdp}
+
+\unexpanded\def\normalizefontwidth {\typo_normalizers_font_at_size\wd}
+\unexpanded\def\normalizefontheight{\typo_normalizers_font_at_size\ht}
+\unexpanded\def\normalizefontdepth {\typo_normalizers_font_at_size\dp}
+\unexpanded\def\normalizefontline {\typo_normalizers_font_at_size\htdp}
+
+\unexpanded\def\widthspanningtext #text#size#specification{\hbox{\normalizefontwidth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\heightspanningtext#text#size#specification{\hbox{\normalizefontheight\temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\depthspanningtext #text#size#specification{\hbox{\normalizefontdepth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\linespanningtext #text#size#specification{\hbox{\normalizefontline \temp{#text}{#size}{#specification}\temp#text}}
+
+%D Traditionally we use UpperCasedNames for this kind of functionality.
+
+\let\NormalizeFontHeight \normalizefontheight
+\let\NormalizeFontWidth \normalizefontwidth
+\let\NormalizeTextHeight \normalizetextheight
+\let\NormalizeTextWidth \normalizetextwidth
+
+\let\WidthSpanningText \widthspanningtext
+
+\def\TheNormalizedFontSize{\normalizedfontsize}
+
+%D \macros
+%D {vulgarfraction}
+%D
+%D This code is moved from \type {cor-mis.mkiv}. We show three versions. First
+%D the simple one using \type {\low} and \type {high}:
+%D
+%D \startbuffer
+%D \def\vfrac#1#2%
+%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}}
+%D
+%D test \vfrac{1}{2} test \vfrac{123}{456} test
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D A better way to handle the kerning is the following, here we kind of assume
+%D that tye slash is symmetrical and has nearly zero width.
+%D
+%D \startbuffer
+%D \def\vfract#1#2%
+%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D The third and best alternative is the following:
+%D
+%D {\showmakeup\getbuffer}\crlf\getbuffer
+%D
+%D This time we measure the height of the \type {/} and shift over the maximum
+%D height and depths of this character and the fractional digits (we use 57 as
+%D sample). Here we combine all methods in one macros.
+
+\setnewconstant\vulgarfractionmethod\plusthree
+
+\definehspace[\v!vulgarfraction][.25em] % [.15em]
+\definesymbol[\v!vulgarfraction][/] % [\raise.2ex\hbox{/}]
+
+\unexpanded\def\vulgarfraction#1#2%
+ {\dontleavehmode
+ \hbox
+ {\def\vulgarfraction{vulgarfraction}%
+ \ifcase\vulgarfractionmethod
+ #1\symbol[\v!vulgarfraction]#2%
+ \or
+ \high{\tx#1\kern-\hspaceamount\empty\v!vulgarfraction}%
+ \symbol[\vulgarfraction]%
+ \low {\kern-\hspaceamount\empty\v!vulgarfraction\tx#2}%
+ \or
+ \high{\tx#1}%
+ \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}%
+ \low{\tx#2}%
+ \or
+ \setbox0\hbox{\symbol[\vulgarfraction]}%
+ \setbox2\hbox{\txx57}%
+ \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}%
+ \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}%
+ \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
+ \fi}}
+
+\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi
+
+%D \starttabulate[|l|l|]
+%D \HL
+%D \NC \bf method \NC \bf visualization \NC\NR
+%D \HL
+%D \NC 0 \NC \vulgarfractionmethod0 \vulgarfraction{1}{2} \NC\NR
+%D \NC 1 \NC \vulgarfractionmethod1 \vulgarfraction{1}{2} \NC\NR
+%D \NC 2 \NC \vulgarfractionmethod2 \vulgarfraction{1}{2} \NC\NR
+%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR
+%D \HL
+%D \stoptabulate
+
+%D This is used in the beginners manual. One needs to set the font size to an
+%D acceptable value for this to work.
+
+\unexpanded\def\startnicelyfilledbox
+ {\vbox\bgroup
+ \forgetall
+ \dosingleempty\dostartnicelyfilledbox}
+
+\def\dostartnicelyfilledbox[#1]%
+ {\letdummyparameter\c!width \hsize
+ \letdummyparameter\c!height\vsize
+ \letdummyparameter\c!offset\exheight % we obey to the outer exheight
+ \letdummyparameter\c!strut \v!yes % we obey to the inner strut !
+ \getdummyparameters[#1]%
+ \scratchoffset\dummyparameter\c!offset\relax
+ \setbox\scratchbox\vbox to \dummyparameter\c!height \bgroup
+ \hsize\dummyparameter\c!width\relax
+ \emergencystretch10\scratchoffset
+ \parfillskip\zeropoint
+ \baselineskip\zeropoint plus \onepoint minus \onepoint
+ \beginofshapebox
+ \leftskip \scratchoffset
+ \rightskip\scratchoffset}
+
+\unexpanded\def\stopnicelyfilledbox
+ {\doifelse{\dummyparameter\c!strut}\v!yes
+ {\xdef\doflushnicelyfilledbox
+ {\ht\shapebox\the\strutht
+ \dp\shapebox\the\strutdp
+ \box\shapebox}}%
+ {\gdef\doflushnicelyfilledbox
+ {\box\shapebox}}%
+ \endofshapebox
+ \doreshapebox
+ {\doflushnicelyfilledbox}
+ {\penalty\shapepenalty}
+ {\kern\shapekern}
+ {\vfil}%
+ \kern\scratchoffset
+ \vfilneg
+ \flushshapebox
+ \vfilneg
+ \kern\scratchoffset
+ \egroup
+ \box\scratchbox
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua
new file mode 100644
index 00000000000..394e15090db
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua
@@ -0,0 +1,76 @@
+if not modules then modules = { } end modules ['typo-wrp'] = {
+ version = 1.001,
+ comment = "companion to typo-wrp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- begin/end par wrapping stuff ... more to come
+
+local nodecodes = nodes.nodecodes
+
+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 nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local find_node_tail = nuts.tail
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getfield = nuts.getfield
+local remove = nuts.remove
+
+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
+
+local function remove_dangling_crlf(head,tail)
+ if tail and getid(tail) == glue_code and getsubtype(tail) == parfill_skip_code then
+ tail = getprev(tail)
+ if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getfield(tail,"penalty") == 10000 then
+ tail = getprev(tail)
+ if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getfield(tail,"penalty") == -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)
+ end
+ remove(head,tail,true)
+ return head, tail, true
+ end
+ end
+ end
+ end
+ return head, tail, false
+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
+ end
+ return head, true
+end
+
+interfaces.implement {
+ name = "enablecrlf",
+ onlyonce = true,
+ actions = function()
+ nodes.tasks.enableaction("processors","typesetters.wrappers.handler")
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv
new file mode 100644
index 00000000000..4b18785bd33
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=typo-wrp,
+%D version=2014.11.09,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Wrappers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Wrapping}
+
+\unprotect
+
+\registerctxluafile{typo-wrp}{1.001}
+
+%D This definition has moved from page-lin.tex to spac-hor.tex (due to
+%D visualization added in august 2003) and now to here (november 2014)
+%D due to cacthing border cases in dirty and messy \XML\ sources).
+
+% \unexpanded\def\crlf
+% {\ifhmode
+% \unskip
+% \prewordbreak\crlfplaceholder
+% \ifcase\raggedstatus\hfil\or\or\or\hfil\fi
+% \break
+% \else
+% \crlfplaceholder
+% \endgraf
+% \fi}
+
+\unexpanded\def\crlf
+ {\ifhmode
+ \expandafter\spac_crlf
+ \fi}
+
+\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
+ \break
+ \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}}
+
+\unexpanded\def\settestcrlf
+ {\let\spac_crlf_placeholder\spac_crlf_placeholder_show}
+
+\unexpanded\def\crlfplaceholder % for old times sake
+ {\spac_crlf_placeholder}
+
+\appendtoks
+ \let\spac_crlf_placeholder\empty
+\to \everysetnostrut
+
+\appendtoks
+ \let\spac_crlf\space
+\to \everysimplifycommands
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/unic-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/unic-ini.lua
new file mode 100644
index 00000000000..132c92efaab
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/unic-ini.lua
@@ -0,0 +1,23 @@
+if not modules then modules = { } end modules ['unic-ini'] = {
+ version = 1.001,
+ comment = "companion to unic-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfchar = utf.char
+
+-- Beware, initializing unicodechar happens at first usage and takes
+-- 0.05 -- 0.1 second (lots of function calls).
+
+interfaces.implement {
+ name = "unicodechar",
+ arguments = "string",
+ actions = function(asked)
+ local n = characters.unicodechar(asked)
+ if n then
+ context(utfchar(n))
+ end
+ end
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/unic-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/unic-ini.mkiv
new file mode 100644
index 00000000000..13ad4bdb98f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/unic-ini.mkiv
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=unic-ini,
+%D version=2002.12.03,
+%D title=\CONTEXT\ \UNICODE\ Support,
+%D subtitle=\UNICODE\ \& UTF-8 support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Unicode Support / Initialization}
+
+\registerctxluafile{unic-ini}{1.001}
+
+\unprotect
+
+\def\unicodenumber #1{\the \numexpr#1\relax} % no lookahead
+\def\unicodehexnumber#1{\cldcontext{number.toevenhex(\number#1))}}
+
+%D \startbuffer
+%D \unicodechar{left square bracket}okay\unicodechar{right square bracket}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\unicodechar#1{\clf_unicodechar{#1}}
+
+\unexpanded\def\unknownchar
+ {\dontleavehmode\hbox{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}}
+
+\ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua b/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua
new file mode 100644
index 00000000000..ee732b3b54c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua
@@ -0,0 +1,132 @@
+if not modules then modules = { } end modules ['util-deb'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- the <anonymous> tag is kind of generic and used for functions that are not
+-- 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 = debug.getinfo
+local type, next, tostring = type, next, tostring
+local format, find = string.format, string.find
+local is_boolean = string.is_boolean
+
+utilities = utilities or { }
+local debugger = utilities.debugger or { }
+utilities.debugger = debugger
+
+local counters = { }
+local names = { }
+
+local report = logs.reporter("debugger")
+
+-- one
+
+local function hook()
+ local f = getinfo(2) -- "nS"
+ if f then
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
+ else
+ -- source short_src linedefined what name namewhat nups func
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
+ end
+ counters[n] = (counters[n] or 0) + 1
+ end
+end
+
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
+ printer = printer or report
+ threshold = threshold or 0
+ local total, grandtotal, functions = 0, 0, 0
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
+ end
+ grandtotal = grandtotal + count
+ functions = functions + 1
+ end
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
+end
+
+function debugger.savestats(filename,threshold)
+ local f = io.open(filename,'w')
+ if f then
+ debugger.showstats(function(str) f:write(str) end,threshold)
+ f:close()
+ end
+end
+
+function debugger.enable()
+ debug.sethook(hook,"c")
+end
+
+function debugger.disable()
+ debug.sethook()
+ -- counters[debug.getinfo(2,"f").func] = nil
+end
+
+-- debugger.enable()
+--
+-- print(math.sin(1*.5))
+-- print(math.sin(1*.5))
+-- print(math.sin(1*.5))
+-- print(math.sin(1*.5))
+-- print(math.sin(1*.5))
+--
+-- debugger.disable()
+--
+-- print("")
+-- debugger.showstats()
+-- print("")
+-- debugger.showstats(print,3)
+--
+-- 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)
+ end
+ level = level + 1
+ end
+end
+
+debugger.showtraceback = showtraceback
+-- debug.showtraceback = showtraceback
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-dim.lua b/Master/texmf-dist/tex/context/base/mkiv/util-dim.lua
new file mode 100644
index 00000000000..2bdb870e7a4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-dim.lua
@@ -0,0 +1,452 @@
+if not modules then modules = { } end modules ['util-dim'] = {
+ version = 1.001,
+ comment = "support for dimensions",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>Internally <l n='luatex'/> work with scaled point, which are
+represented by integers. However, in practice, at east at the
+<l n='tex'/> end we work with more generic units like points (pt). Going
+from scaled points (numbers) to one of those units can be
+done by using the conversion factors collected in the following
+table.</p>
+--ldx]]--
+
+local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable
+local P, S, R, Cc, C, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.C, lpeg.match
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local texget = tex and tex.get or function() return 65536*10*100 end
+
+local p_stripzeros = lpeg.patterns.stripzeros
+
+--this might become another namespace
+
+number = number or { }
+local number = number
+
+number.tonumberf = function(n) return lpegmatch(p_stripzeros,format("%.20f",n)) end
+number.tonumberg = function(n) return format("%.20g",n) end
+
+local dimenfactors = allocate {
+ ["pt"] = 1/65536,
+ ["in"] = ( 100/ 7227)/65536,
+ ["cm"] = ( 254/ 7227)/65536,
+ ["mm"] = ( 2540/ 7227)/65536,
+ ["sp"] = 1, -- 65536 sp in 1pt
+ ["bp"] = ( 7200/ 7227)/65536,
+ ["pc"] = ( 1/ 12)/65536,
+ ["dd"] = ( 1157/ 1238)/65536,
+ ["cc"] = ( 1157/14856)/65536,
+ ["nd"] = (20320/21681)/65536,
+ ["nc"] = ( 5080/65043)/65536
+}
+
+-- print(table.serialize(dimenfactors))
+--
+-- %.99g:
+--
+-- t={
+-- ["bp"]=1.5201782378580324e-005,
+-- ["cc"]=1.1883696112892098e-006,
+-- ["cm"]=5.3628510057769479e-007,
+-- ["dd"]=1.4260435335470516e-005,
+-- ["em"]=0.000152587890625,
+-- ["ex"]=6.103515625e-005,
+-- ["in"]=2.1113586636917117e-007,
+-- ["mm"]=5.3628510057769473e-008,
+-- ["nc"]=1.1917446679504327e-006,
+-- ["nd"]=1.4300936015405194e-005,
+-- ["pc"]=1.2715657552083333e-006,
+-- ["pt"]=1.52587890625e-005,
+-- ["sp"]=1,
+-- }
+--
+-- patched %s and tonumber
+--
+-- t={
+-- ["bp"]=0.00001520178238,
+-- ["cc"]=0.00000118836961,
+-- ["cm"]=0.0000005362851,
+-- ["dd"]=0.00001426043534,
+-- ["em"]=0.00015258789063,
+-- ["ex"]=0.00006103515625,
+-- ["in"]=0.00000021113587,
+-- ["mm"]=0.00000005362851,
+-- ["nc"]=0.00000119174467,
+-- ["nd"]=0.00001430093602,
+-- ["pc"]=0.00000127156576,
+-- ["pt"]=0.00001525878906,
+-- ["sp"]=1,
+-- }
+
+--[[ldx--
+<p>A conversion function that takes a number, unit (string) and optional
+format (string) is implemented using this table.</p>
+--ldx]]--
+
+local f_none = formatters["%s%s"]
+local f_true = formatters["%0.5F%s"]
+
+local function numbertodimen(n,unit,fmt) -- will be redefined later !
+ if type(n) == 'string' then
+ return n
+ else
+ unit = unit or 'pt'
+ n = n * dimenfactors[unit]
+ if not fmt then
+ fmt = f_none(n,unit)
+ elseif fmt == true then
+ fmt = f_true(n,unit)
+ else
+ return formatters[fmt](n,unit)
+ end
+ end
+end
+
+--[[ldx--
+<p>We collect a bunch of converters in the <type>number</type> namespace.</p>
+--ldx]]--
+
+number.maxdimen = 1073741823
+number.todimen = numbertodimen
+number.dimenfactors = dimenfactors
+
+function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end
+function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end
+function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
+function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
+function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
+function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
+function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
+function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
+function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
+function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
+
+--[[ldx--
+<p>More interesting it to implement a (sort of) dimen datatype, one
+that permits calculations too. First we define a function that
+converts a string to scaledpoints. We use <l n='lpeg'/>. We capture
+a number and optionally a unit. When no unit is given a constant
+capture takes place.</p>
+--ldx]]--
+
+local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0")
+local unit = R("az")^1 + P("%")
+
+local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new
+
+lpeg.patterns.dimenpair = dimenpair
+
+local splitter = amount/tonumber * C(unit^1)
+
+function number.splitdimen(str)
+ return lpegmatch(splitter,str)
+end
+
+--[[ldx--
+<p>We use a metatable to intercept errors. When no key is found in
+the table with factors, the metatable will be consulted for an
+alternative index function.</p>
+--ldx]]--
+
+setmetatableindex(dimenfactors, function(t,s)
+ -- error("wrong dimension: " .. (s or "?")) -- better a message
+ return false
+end)
+
+--[[ldx--
+<p>We redefine the following function later on, so we comment it
+here (which saves us bytecodes.</p>
+--ldx]]--
+
+-- function string.todimen(str)
+-- if type(str) == "number" then
+-- return str
+-- else
+-- local value, unit = lpegmatch(dimenpair,str)
+-- return value/unit
+-- end
+-- end
+--
+-- local stringtodimen = string.todimen
+
+local stringtodimen -- assigned later (commenting saves bytecode)
+
+local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0
+local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") +
+ P("pc") + P("dd") + P("cc") + P("nd") + P("nc")
+
+local validdimen = amount * unit
+
+lpeg.patterns.validdimen = validdimen
+
+--[[ldx--
+<p>This converter accepts calls like:</p>
+
+<typing>
+string.todimen("10")
+string.todimen(".10")
+string.todimen("10.0")
+string.todimen("10.0pt")
+string.todimen("10pt")
+string.todimen("10.0pt")
+</typing>
+
+<p>With this in place, we can now implement a proper datatype for dimensions, one
+that permits us to do this:</p>
+
+<typing>
+s = dimen "10pt" + dimen "20pt" + dimen "200pt"
+ - dimen "100sp" / 10 + "20pt" + "0pt"
+</typing>
+
+<p>We create a local metatable for this new type:</p>
+--ldx]]--
+
+local dimensions = { }
+
+--[[ldx--
+<p>The main (and globally) visible representation of a dimen is defined next: it is
+a one-element table. The unit that is returned from the match is normally a number
+(one of the previously defined factors) but we also accept functions. Later we will
+see why. This function is redefined later.</p>
+--ldx]]--
+
+-- function dimen(a)
+-- if a then
+-- local ta= type(a)
+-- if ta == "string" then
+-- local value, unit = lpegmatch(pattern,a)
+-- if type(unit) == "function" then
+-- k = value/unit()
+-- else
+-- k = value/unit
+-- end
+-- a = k
+-- elseif ta == "table" then
+-- a = a[1]
+-- end
+-- return setmetatable({ a }, dimensions)
+-- else
+-- return setmetatable({ 0 }, dimensions)
+-- end
+-- end
+
+--[[ldx--
+<p>This function return a small hash with a metatable attached. It is
+through this metatable that we can do the calculations. We could have
+shared some of the code but for reasons of speed we don't.</p>
+--ldx]]--
+
+function dimensions.__add(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end
+ return setmetatable({ a + b }, dimensions)
+end
+
+function dimensions.__sub(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end
+ return setmetatable({ a - b }, dimensions)
+end
+
+function dimensions.__mul(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end
+ return setmetatable({ a * b }, dimensions)
+end
+
+function dimensions.__div(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end
+ return setmetatable({ a / b }, dimensions)
+end
+
+function dimensions.__unm(a)
+ local ta = type(a)
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
+ return setmetatable({ - a }, dimensions)
+end
+
+--[[ldx--
+<p>It makes no sense to implement the power and modulo function but
+the next two do make sense because they permits is code like:</p>
+
+<typing>
+local a, b = dimen "10pt", dimen "11pt"
+...
+if a > b then
+ ...
+end
+</typing>
+--ldx]]--
+
+-- makes no sense: dimensions.__pow and dimensions.__mod
+
+function dimensions.__lt(a, b)
+ return a[1] < b[1]
+end
+
+function dimensions.__eq(a, b)
+ return a[1] == b[1]
+end
+
+--[[ldx--
+<p>We also need to provide a function for conversion to string (so that
+we can print dimensions). We print them as points, just like <l n='tex'/>.</p>
+--ldx]]--
+
+function dimensions.__tostring(a)
+ return a[1]/65536 .. "pt" -- instead of todimen(a[1])
+end
+
+--[[ldx--
+<p>Since it does not take much code, we also provide a way to access
+a few accessors</p>
+
+<typing>
+print(dimen().pt)
+print(dimen().sp)
+</typing>
+--ldx]]--
+
+function dimensions.__index(tab,key)
+ local d = dimenfactors[key]
+ if not d then
+ error("illegal property of dimen: " .. key)
+ d = 1
+ end
+ return 1/d
+end
+
+--[[ldx--
+<p>In the converter from string to dimension we support functions as
+factors. This is because in <l n='tex'/> we have a few more units:
+<type>ex</type> and <type>em</type>. These are not constant factors but
+depend on the current font. They are not defined by default, but need
+an explicit function call. This is because at the moment that this code
+is loaded, the relevant tables that hold the functions needed may not
+yet be available.</p>
+--ldx]]--
+
+ dimenfactors["ex"] = 4 * 1/65536 -- 4pt
+ dimenfactors["em"] = 10 * 1/65536 -- 10pt
+-- dimenfactors["%"] = 4 * 1/65536 -- 400pt/100
+
+--[[ldx--
+<p>The previous code is rather efficient (also thanks to <l n='lpeg'/>) but we
+can speed it up by caching converted dimensions. On my machine (2008) the following
+loop takes about 25.5 seconds.</p>
+
+<typing>
+for i=1,1000000 do
+ local s = dimen "10pt" + dimen "20pt" + dimen "200pt"
+ - dimen "100sp" / 10 + "20pt" + "0pt"
+end
+</typing>
+
+<p>When we cache converted strings this becomes 16.3 seconds. In order not
+to waste too much memory on it, we tag the values of the cache as being
+week which mean that the garbage collector will collect them in a next
+sweep. This means that in most cases the speed up is mostly affecting the
+current couple of calculations and as such the speed penalty is small.</p>
+
+<p>We redefine two previous defined functions that can benefit from
+this:</p>
+--ldx]]--
+
+local known = { } setmetatable(known, { __mode = "v" })
+
+function dimen(a)
+ if a then
+ local ta= type(a)
+ if ta == "string" then
+ local k = known[a]
+ if k then
+ a = k
+ else
+ local value, unit = lpegmatch(dimenpair,a)
+ if value and unit then
+ k = value/unit -- to be considered: round
+ else
+ k = 0
+ end
+ known[a] = k
+ a = k
+ end
+ elseif ta == "table" then
+ a = a[1]
+ end
+ return setmetatable({ a }, dimensions)
+ else
+ return setmetatable({ 0 }, dimensions)
+ end
+end
+
+function string.todimen(str) -- maybe use tex.sp when available
+ if type(str) == "number" then
+ return str
+ else
+ local k = known[str]
+ if not k then
+ local value, unit = lpegmatch(dimenpair,str)
+ if value and unit then
+ k = value/unit -- to be considered: round
+ else
+ k = 0
+ end
+ -- print(str,value,unit)
+ known[str] = k
+ end
+ return k
+ end
+end
+
+-- local known = { }
+--
+-- function string.todimen(str) -- maybe use tex.sp
+-- local k = known[str]
+-- if not k then
+-- k = tex.sp(str)
+-- known[str] = k
+-- end
+-- return k
+-- end
+
+stringtodimen = string.todimen -- local variable defined earlier
+
+function number.toscaled(d)
+ return format("%0.5f",d/2^16)
+end
+
+--[[ldx--
+<p>In a similar fashion we can define a glue datatype. In that case we
+probably use a hash instead of a one-element table.</p>
+--ldx]]--
+
+--[[ldx--
+<p>Goodie:s</p>
+--ldx]]--
+
+function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out
+ d = d or texget("hsize")
+ if type(d) == "string" then
+ d = stringtodimen(d)
+ end
+ return (n/100) * d
+end
+
+number["%"] = number.percent
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-env.lua b/Master/texmf-dist/tex/context/base/mkiv/util-env.lua
new file mode 100644
index 00000000000..b72226900a9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-env.lua
@@ -0,0 +1,262 @@
+if not modules then modules = { } end modules ['util-env'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+
+local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
+local unquoted, quoted, optionalquoted = string.unquoted, string.quoted, string.optionalquoted
+local concat, insert, remove = table.concat, table.insert, table.remove
+
+environment = environment or { }
+local environment = environment
+
+-- precautions
+
+os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
+
+function os.setlocale()
+ -- no way you can mess with it
+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,
+}
+
+local basicengines = allocate {
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex",
+ ["texluac"] = "luatex",
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex",
+ -- ["texlua.exe"] = "luatex",
+ -- ["texluajit.exe"] = "luajittex",
+}
+
+local luaengines = allocate {
+ ["lua"] = true,
+ ["luajit"] = true,
+}
+
+environment.validengines = validengines
+environment.basicengines = basicengines
+
+-- [-1] = binary
+-- [ 0] = self
+-- [ 1] = argument 1 ...
+
+-- instead we could set ranges
+
+if not arg then
+ environment.used_as_library = true
+ -- used as library
+elseif luaengines[file.removesuffix(arg[-1])] then
+-- arg[-1] = arg[0]
+-- arg[ 0] = arg[1]
+-- for k=2,#arg do
+-- arg[k-1] = arg[k]
+-- end
+-- remove(arg) -- last
+--
+-- environment.used_as_library = true
+elseif validengines[file.removesuffix(arg[0])] then
+ if arg[1] == "--luaonly" then
+ arg[-1] = arg[0]
+ arg[ 0] = arg[2]
+ for k=3,#arg do
+ arg[k-2] = arg[k]
+ end
+ remove(arg) -- last
+ remove(arg) -- pre-last
+ else
+ -- tex run
+ end
+
+ -- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
+ --
+ -- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
+ --
+ -- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
+ -- but it's unlikely that there will be more of this
+
+ local originalzero = file.basename(arg[0])
+ local specialmapping = { luatools == "base" }
+
+ if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then
+ arg[0] = specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+
+end
+
+-- environment
+
+environment.arguments = allocate()
+environment.files = allocate()
+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
+ for index=1,#arg do
+ local argument = arg[index]
+ if index > 0 then
+ local flag, value = match(argument,"^%-+(.-)=(.-)$")
+ if flag then
+ flag = gsub(flag,"^c:","")
+ arguments[flag] = unquoted(value or "")
+ else
+ flag = match(argument,"^%-+(.+)")
+ if flag then
+ flag = gsub(flag,"^c:","")
+ arguments[flag] = true
+ else
+ files[#files+1] = argument
+ end
+ end
+ end
+ end
+ environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
+end
+
+function environment.setargument(name,value)
+ environment.arguments[name] = value
+end
+
+-- todo: defaults, better checks e.g on type (boolean versus string)
+--
+-- tricky: too many hits when we support partials unless we add
+-- a registration of arguments so from now on we have 'partial'
+
+function environment.getargument(name,partial)
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags = allocate(table.sortedkeys(arguments))
+ for k=1,#sortedflags do
+ sortedflags[k] = "^" .. sortedflags[k]
+ end
+ environment.sortedflags = sortedflags
+ end
+ -- example of potential clash: ^mode ^modefile
+ for k=1,#sortedflags do
+ local v = sortedflags[k]
+ if find(name,v) then
+ return arguments[sub(v,2,#v)]
+ end
+ end
+ end
+ return nil
+end
+
+environment.argument = environment.getargument
+
+function environment.splitarguments(separator) -- rather special, cut-off before separator
+ local done, before, after = false, { }, { }
+ local originalarguments = environment.originalarguments
+ for k=1,#originalarguments do
+ local v = originalarguments[k]
+ if not done and v == separator then
+ done = true
+ elseif done then
+ after[#after+1] = v
+ else
+ before[#before+1] = v
+ end
+ end
+ return before, after
+end
+
+function environment.reconstructcommandline(arg,noquote)
+ local resolveprefix = resolvers.resolve -- something rather special
+ arg = arg or environment.originalarguments
+ if noquote and #arg == 1 then
+ return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
+ elseif #arg > 0 then
+ local result = { }
+ for i=1,#arg do
+ result[i] = optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
+ end
+ return concat(result," ")
+ else
+ return ""
+ end
+end
+
+-- handy in e.g. package.addluapath(environment.relativepath("scripts"))
+
+function environment.relativepath(path,root)
+ if not path then
+ path = ""
+ end
+ if not file.is_rootbased_path(path) then
+ if not root then
+ root = file.pathpart(environment.ownscript or environment.ownname or ".")
+ end
+ if root == "" then
+ root = "."
+ end
+ path = root .. "/" .. path
+ end
+ return file.collapsepath(path,true)
+end
+
+-- -- when script lives on e:/tmp we get this:
+--
+-- print(environment.relativepath("x/y/z","c:/w")) -- c:/w/x/y/z
+-- print(environment.relativepath("x")) -- e:/tmp/x
+-- print(environment.relativepath("../x")) -- e:/x
+-- print(environment.relativepath("./x")) -- e:/tmp/x
+-- print(environment.relativepath("/x")) -- /x
+-- print(environment.relativepath("c:/x")) -- c:/x
+-- print(environment.relativepath("//x")) -- //x
+-- print(environment.relativepath()) -- e:/tmp
+
+if arg then
+
+ -- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
+
+ local newarg, instring = { }, false
+
+ for index=1,#arg do
+ local argument = arg[index]
+ if find(argument,"^\"") then
+ newarg[#newarg+1] = gsub(argument,"^\"","")
+ if not find(argument,"\"$") then
+ instring = true
+ end
+ elseif find(argument,"\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initializearguments(newarg)
+
+ environment.originalarguments = mark(newarg)
+ environment.rawarguments = mark(arg)
+
+ arg = { } -- prevent duplicate handling
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua b/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua
new file mode 100644
index 00000000000..28c92c7c3c3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua
@@ -0,0 +1,167 @@
+if not modules then modules = { } end modules ['util-fil'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte = string.byte
+local extract = bit32.extract
+
+-- Here are a few helpers (the starting point were old ones I used for parsing
+-- flac files). In Lua 5.3 we can probably do this better. Some code will move
+-- here.
+
+utilities = utilities or { }
+local files = { }
+utilities.files = files
+
+local zerobased = { }
+
+function files.open(filename,zb)
+ local f = io.open(filename,"rb")
+ if f then
+ zerobased[f] = zb or false
+ end
+ return f
+end
+
+function files.close(f)
+ zerobased[f] = nil
+ f:close()
+end
+
+function files.size(f)
+ return f:seek("end")
+end
+
+function files.setposition(f,n)
+ if zerobased[f] then
+ f:seek("set",n)
+ else
+ f:seek("set",n - 1)
+ end
+end
+
+function files.getposition(f)
+ if zerobased[f] then
+ return f:seek()
+ else
+ return f:seek() + 1
+ end
+end
+
+function files.look(f,n,chars)
+ local p = f:seek()
+ local s = f:read(n)
+ f:seek("set",p)
+ if chars then
+ return s
+ else
+ return byte(s,1,#s)
+ end
+end
+
+function files.skip(f,n)
+ if n == 1 then
+ f:read(n)
+ else
+ f:seek("set",f:seek()+n)
+ end
+end
+
+function files.readbyte(f)
+ return byte(f:read(1))
+end
+
+function files.readbytes(f,n)
+ return byte(f:read(n),1,n)
+end
+
+function files.readchar(f)
+ return f:read(1)
+end
+
+function files.readstring(f,n)
+ return f:read(n or 1)
+end
+
+function files.readinteger1(f) -- one byte
+ local n = byte(f:read(1))
+ if n >= 0x80 then
+ return n - 0xFF - 1
+ else
+ return n
+ end
+end
+
+files.readcardinal1 = files.readbyte -- one byte
+files.readcardinal = files.readcardinal1
+files.readinteger = files.readinteger1
+
+function files.readcardinal2(f)
+ local a, b = byte(f:read(2),1,2)
+ return 0x100 * a + b
+end
+
+function files.readinteger2(f)
+ local a, b = byte(f:read(2),1,2)
+ local n = 0x100 * a + b
+ if n >= 0x8000 then
+ return n - 0xFFFF - 1
+ else
+ return n
+ end
+end
+
+function files.readcardinal3(f)
+ local a, b, c = byte(f:read(3),1,3)
+ return 0x10000 * a + 0x100 * b + c
+end
+
+function files.readcardinal4(f)
+ local a, b, c, d = byte(f:read(4),1,4)
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+end
+
+function files.readinteger4(f)
+ local a, b, c, d = byte(f:read(4),1,4)
+ local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+ if n >= 0x8000000 then
+ return n - 0xFFFFFFFF - 1
+ else
+ return n
+ end
+end
+
+function files.readfixed4(f)
+ local a, b, c, d = byte(f:read(4),1,4)
+ local n = 0x100 * a + b
+ if n >= 0x8000 then
+ return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF
+ else
+ return n + (0x100 * c + d)/0xFFFF
+ end
+end
+
+function files.read2dot14(f)
+ local a, b = byte(f:read(2),1,2)
+ local n = 0x100 * a + b
+ local m = extract(n,0,30)
+ if n > 0x7FFF then
+ n = extract(n,30,2)
+ return m/0x4000 - 4
+ else
+ n = extract(n,30,2)
+ return n + m/0x4000
+ end
+end
+
+function files.skipshort(f,n)
+ f:read(2*(n or 1))
+end
+
+function files.skiplong(f,n)
+ f:read(4*(n or 1))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua
new file mode 100644
index 00000000000..371a5dfcece
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua
@@ -0,0 +1,76 @@
+if not modules then modules = { } end modules ['util-fmt'] = {
+ 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"
+}
+
+utilities = utilities or { }
+utilities.formatters = utilities.formatters or { }
+local formatters = utilities.formatters
+
+local concat, format = table.concat, string.format
+local tostring, type = tostring, type
+local strip = string.strip
+
+local lpegmatch = lpeg.match
+local stripper = lpeg.patterns.stripzeros
+
+function formatters.stripzeros(str)
+ return lpegmatch(stripper,str)
+end
+
+function formatters.formatcolumns(result,between)
+ if result and #result > 0 then
+ between = between or " "
+ local widths, numbers = { }, { }
+ local first = result[1]
+ local n = #first
+ for i=1,n do
+ widths[i] = 0
+ end
+ for i=1,#result do
+ local r = result[i]
+ 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
+ local w = #rj
+ if w > widths[j] then
+ widths[j] = w
+ end
+ end
+ end
+ for i=1,n do
+ local w = widths[i]
+ if numbers[i] then
+ if w > 80 then
+ widths[i] = "%s" .. between
+ else
+ widths[i] = "%0" .. w .. "i" .. between
+ end
+ else
+ if w > 80 then
+ widths[i] = "%s" .. between
+ elseif w > 0 then
+ widths[i] = "%-" .. w .. "s" .. between
+ else
+ widths[i] = "%s"
+ end
+ end
+ end
+ local template = strip(concat(widths))
+ for i=1,#result do
+ local str = format(template,unpack(result[i]))
+ result[i] = strip(str)
+ end
+ end
+ return result
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua b/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua
new file mode 100644
index 00000000000..bbe25d89df8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua
@@ -0,0 +1,158 @@
+if not modules then modules = { } end modules ['util-jsn'] = {
+ version = 1.001,
+ comment = "companion to m-json.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Of course we could make a nice complete parser with proper error messages but
+-- as json is generated programmatically errors are systematic and we can assume
+-- a correct stream. If not, we have some fatal error anyway. So, we can just rely
+-- on strings being strings (apart from the unicode escape which is not in 5.1) and
+-- as we first catch known types we just assume that anything else is a number.
+--
+-- Reminder for me: check usage in framework and extend when needed. Also document
+-- it in the cld lib documentation.
+
+local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg
+local lpegmatch = lpeg.match
+local format = string.format
+local utfchar = utf.char
+local concat = table.concat
+
+local tonumber, tostring, rawset, type = tonumber, tostring, rawset, type
+
+local json = utilities.json or { }
+utilities.json = json
+
+-- moduledata = moduledata or { }
+-- moduledata.json = json
+
+-- \\ \/ \b \f \n \r \t \uHHHH
+
+local lbrace = P("{")
+local rbrace = P("}")
+local lparent = P("[")
+local rparent = P("]")
+local comma = P(",")
+local colon = P(":")
+local dquote = P('"')
+
+local whitespace = lpeg.patterns.whitespace
+local optionalws = whitespace^0
+
+local escapes = {
+ -- ["\\"] = "\\", -- lua will escape these
+ -- ["/"] = "/", -- no need to escape this one
+ ["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
+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
+local jtrue = P("true") * Cc(true)
+local jfalse = P("false") * Cc(false)
+local jnull = P("null") * Cc(nil)
+local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber
+
+local key = jstring
+
+local jsonconverter = { "value",
+ object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace,
+ pair = Cg(optionalws * key * optionalws * colon * V("value")),
+ array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent),
+ value = optionalws * (jstring + V("object") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws,
+}
+
+-- local jsonconverter = { "value",
+-- object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace,
+-- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")),
+-- array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent),
+-- string = jstring,
+-- value = optionalws * (V("string") + V("object") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
+-- }
+
+-- lpeg.print(jsonconverter) -- size 181
+
+function json.tolua(str)
+ return lpegmatch(jsonconverter,str)
+end
+
+local function tojson(value,t) -- we could optimize #t
+ local kind = type(value)
+ if kind == "table" then
+ local done = false
+ local size = #value
+ if size == 0 then
+ for k, v in next, value do
+ if done then
+ t[#t+1] = ","
+ else
+ t[#t+1] = "{"
+ done = true
+ end
+ t[#t+1] = format("%q:",k)
+ tojson(v,t)
+ end
+ if done then
+ t[#t+1] = "}"
+ else
+ t[#t+1] = "{}"
+ end
+ elseif size == 1 then
+ -- we can optimize for non tables
+ t[#t+1] = "["
+ tojson(value[1],t)
+ t[#t+1] = "]"
+ else
+ for i=1,size do
+ if done then
+ t[#t+1] = ","
+ else
+ t[#t+1] = "["
+ done = true
+ end
+ tojson(value[i],t)
+ end
+ t[#t+1] = "]"
+ end
+ elseif kind == "string" then
+ t[#t+1] = format("%q",value)
+ elseif kind == "number" then
+ t[#t+1] = value
+ elseif kind == "boolean" then
+ t[#t+1] = tostring(value)
+ end
+ return t
+end
+
+function json.tostring(value)
+ -- todo optimize for non table
+ local kind = type(value)
+ if kind == "table" then
+ return concat(tojson(value,{}),"")
+ elseif kind == "string" or kind == "number" then
+ return value
+ else
+ return tostring(value)
+ end
+end
+
+-- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
+
+-- tmp = json.tolua(tmp)
+-- inspect(tmp)
+-- tmp = json.tostring(tmp)
+-- inspect(tmp)
+-- tmp = json.tolua(tmp)
+-- inspect(tmp)
+-- tmp = json.tostring(tmp)
+-- inspect(tmp)
+
+-- inspect(json.tostring(true))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gm.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gm.lua
new file mode 100644
index 00000000000..4c5254721df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gm.lua
@@ -0,0 +1,69 @@
+if not modules then modules = { } end modules ['util-lib-imp-gm'] = {
+ version = 1.001,
+ comment = "a mkiv swiglib module",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local graphicmagick = utilities.graphicmagick or { }
+utilities.graphicmagick = graphicmagick
+
+local report_gm = logs.reporter("swiglib gm")
+
+local gm = swiglib("gmwand.core")
+
+if gm then
+ report_gm("library loaded")
+ -- inspect(table.sortedkeys(gm))
+else
+ return
+end
+
+local nofruns = 0
+
+function graphicmagick.convert(specification)
+ --
+ nofruns = nofruns + 1
+ statistics.starttiming(graphicmagick)
+ --
+ local inputname = specification.inputname
+ if not inputname or inputname == "" then
+ report_gm("invalid run %s, no inputname specified",nofruns)
+ statistics.stoptiming(graphicmagick)
+ return false
+ end
+ local outputname = specification.outputname
+ if not outputname or outputname == "" then
+ outputname = file.replacesuffix(inputname,"pdf")
+ end
+ --
+ if not lfs.isfile(inputname) then
+ report_gm("invalid run %s, input file %a is not found",nofruns,inputname)
+ statistics.stoptiming(graphicmagick)
+ return false
+ end
+ --
+ report_gm("run %s, input file %a, outputfile %a",nofruns,inputname,outputname)
+ local magick_wand = gm.NewMagickWand()
+ gm.MagickReadImage(magick_wand,inputname)
+ gm.MagickWriteImage(magick_wand,outputname)
+ gm.DestroyMagickWand(magick_wand)
+ --
+ statistics.stoptiming(graphicmagick)
+end
+
+function graphicmagick.statistics(report)
+ local runtime = statistics.elapsedtime(graphicmagick)
+ if report then
+ report_gm("nofruns %s, runtime %s",nofruns,runtime)
+ else
+ return {
+ runtime = runtime,
+ nofruns = nofruns,
+ }
+ end
+end
+
+-- graphicmagick.convert { inputname = "t:/sources/hacker.jpg", outputname = "e:/tmp/hacker.png" }
+-- graphicmagick.statistics(true)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gs.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gs.lua
new file mode 100644
index 00000000000..8fd2dd45826
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-lib-imp-gs.lua
@@ -0,0 +1,212 @@
+if not modules then modules = { } end modules ['util-lib-imp-gs'] = {
+ version = 1.001,
+ comment = "a mkiv swiglib module",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local insert = table.insert
+local formatters = string.formatters
+
+local ghostscript = utilities.ghostscript or { }
+utilities.ghostscript = ghostscript
+
+local report_gs = logs.reporter("swiglib gs")
+
+local gs = swiglib("gs.core")
+local helpers = swiglib("helpers.core")
+
+if gs then
+ report_gs("library loaded")
+ -- inspect(table.sortedkeys(gs))
+else
+ return
+end
+
+-- these could be generic helpers
+
+local function luatable_to_c_array(t)
+ local gsargv = helpers.new_char_p_array(#t)
+ for i=1,#t do
+ helpers.char_p_array_setitem(gsargv,i-1,t[i])
+ end
+ return gsargv
+end
+
+-- the more abstract interface
+
+local interface = { }
+ghostscript.interface = interface
+
+function interface.new()
+
+ local instance = helpers.new_void_p_p()
+ local result = gs.gsapi_new_instance(instance,nil)
+ local buffer = nil
+ local object = { }
+
+ local function reader(instance,str,len)
+ return 0
+ end
+
+ local function writer(instance,str,len)
+ if buffer then
+ str = buffer .. str
+ buffer = nil
+ end
+ if not string.find(str,"[\n\r]$") then
+ str, buffer = string.match(str,"(.-)([^\n\r]+)$")
+ end
+ local log = object.log
+ for s in string.gmatch(str,"[^\n\r]+") do
+ insert(log,s)
+ report_gs(s)
+ end
+ return len
+ end
+
+ if result < 0 then
+ return nil
+ else
+ local job = helpers.void_p_p_value(instance)
+ gs.gsapi_set_stdio_callback(job,reader,writer,writer) -- could be option
+ object.instance = instance
+ object.job = job
+ object.result = 0
+ object.log = { }
+ return object
+ end
+end
+
+function interface.dispose(run)
+ if run.job then
+ gs.gsapi_delete_instance(run.job)
+ run.job = nil
+ end
+ if run.instance then
+ helpers.delete_void_p_p(run.instance)
+ run.instance = nil
+ end
+end
+
+function interface.init(run,options)
+ if run.job then
+ if not options then
+ options = { "ps2pdf" }
+ else
+ insert(options,1,"ps2pdf") -- a dummy
+ end
+ run.log = { }
+ local ct = luatable_to_c_array(options)
+ local result = gs.gsapi_init_with_args(run.job,#options,ct)
+ helpers.delete_char_p_array(ct)
+ run.initresult = result
+ return result >= 0
+ end
+end
+
+function interface.exit(run)
+ if run.job then
+ local result = gs.gsapi_exit(run.job)
+ if run.initresult == 0 or run.initresult == gs.e_Quit then
+ run.result = result
+ end
+ run.exitresult = result
+ return run.result >= 0
+ end
+end
+
+function interface.process(run,options)
+ interface.init(run,options)
+ return interface.exit(run)
+end
+
+-- end of more abstract interface
+
+local nofruns = 0
+
+function ghostscript.convert(specification)
+ --
+ nofruns = nofruns + 1
+ statistics.starttiming(ghostscript)
+ --
+ local inputname = specification.inputname
+ if not inputname or inputname == "" then
+ report_gs("invalid run %s, no inputname specified",nofruns)
+ statistics.stoptiming(ghostscript)
+ return false
+ end
+ local outputname = specification.outputname
+ if not outputname or outputname == "" then
+ outputname = file.replacesuffix(inputname,"pdf")
+ end
+ --
+ if not lfs.isfile(inputname) then
+ report_gs("invalid run %s, input file %a is not found",nofruns,inputname)
+ statistics.stoptiming(ghostscript)
+ return false
+ end
+ --
+ local device = specification.device
+ if not device or device == "" then
+ device = "pdfwrite"
+ end
+ --
+ local code = specification.code
+ if not code or code == "" then
+ code = ".setpdfwrite"
+ end
+ --
+ local run = interface.new()
+ if gsinstance then
+ report_gs("invalid run %s, initialization error",nofruns)
+ statistics.stoptiming(ghostscript)
+ return false
+ end
+ --
+ local options = specification.options or { }
+ --
+ insert(options,"-dNOPAUSE")
+ insert(options,"-dBATCH")
+ insert(options,"-dSAFER")
+ insert(options,formatters["-sDEVICE=%s"](device))
+ insert(options,formatters["-sOutputFile=%s"](outputname))
+ insert(options,"-c")
+ insert(options,code)
+ insert(options,"-f")
+ insert(options,inputname)
+ --
+ report_gs("run %s, input file %a, outputfile %a",nofruns,inputname,outputname)
+ report_gs("")
+ local okay = interface.process(run,options)
+ report_gs("")
+ --
+ interface.dispose(run)
+ --
+ statistics.stoptiming(ghostscript)
+ if okay then
+ return outputname
+ else
+ report_gs("run %s quit with errors",nofruns)
+ return false
+ end
+end
+
+function ghostscript.statistics(report)
+ local runtime = statistics.elapsedtime(ghostscript)
+ if report then
+ report_gs("nofruns %s, runtime %s",nofruns,runtime)
+ else
+ return {
+ runtime = runtime,
+ nofruns = nofruns,
+ }
+ end
+end
+
+-- for i=1,100 do
+-- ghostscript.convert { inputname = "temp.eps" }
+-- ghostscript.convert { inputname = "t:/escrito/tiger.eps" }
+-- end
+-- ghostscript.statistics(true)
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua
new file mode 100644
index 00000000000..2601b2e5781
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua
@@ -0,0 +1,297 @@
+if not modules then modules = { } end modules ['util-lib'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This is experimental code for Hans and Luigi. Don't depend on it! There
+-- will be a plain variant.
+
+--[[
+
+The problem with library bindings is manyfold. They are of course platform
+dependent and while a binary with its directly related libraries are often
+easy to maintain and load, additional libraries can each have their demands.
+
+One important aspect is that loading additional libraries from within the
+loaded one is also operating system dependent. There can be shared libraries
+elsewhere on the system and as there can be multiple libraries with the same
+name but different usage and versioning there can be clashes. So there has to
+be some logic in where to look for these sublibraries.
+
+We found out that for instance on windows libraries are by default sought on
+the parents path and then on the binary paths and these of course can be in
+an out of our control, thereby enlarging the changes on a clash. A rather
+safe solution for that to load the library on the path where it sits.
+
+Another aspect is initialization. When you ask for a library t.e.x it will
+try to initialize luaopen_t_e_x no matter if such an inializer is present.
+However, because loading is configurable and in the case of luatex is already
+partly under out control, this is easy to deal with. We only have to make
+sure that we inform the loader that the library has been loaded so that
+it won't load it twice.
+
+In swiglib we have chosen for a clear organization and although one can use
+variants normally in the tex directory structure predictability is more or
+less the standard. For instance:
+
+.../tex/texmf-mswin/bin/lib/luatex/lua/swiglib/mysql/core.dll
+.../tex/texmf-mswin/bin/lib/luajittex/lua/swiglib/mysql/core.dll
+.../tex/texmf-mswin/bin/lib/luatex/context/lua/swiglib/mysql/core.dll
+.../tex/texmf-mswin/bin/lib/swiglib/lua/mysql/core.dll
+.../tex/texmf-mswin/bin/lib/swiglib/lua/mysql/5.6/core.dll
+
+The lookups are determined via an entry in texmfcnf.lua:
+
+CLUAINPUTS = ".;$SELFAUTOLOC/lib/{$engine,luatex}/lua//",
+
+A request for t.e.x is converted to t/e/x.dll or t/e/x.so depending on the
+platform. Then we use the regular finder to locate the file in the tex
+directory structure. Once located we goto the path where it sits, load the
+file and return to the original path. We register as t.e.x in order to
+prevent reloading and also because the base name is seldom unique.
+
+The main function is a big one and evolved out of experiments that Luigi
+Scarso and I conducted when playing with variants of SwigLib. The function
+locates the library using the context mkiv resolver that operates on the
+tds tree and if that doesn't work out well, the normal clib path is used.
+
+The lookups is somewhat clever in the sense that it can deal with (optional)
+versions and can fall back on non versioned alternatives if needed, either
+or not using a wildcard lookup.
+
+This code is experimental and by providing a special abstract loader (called
+swiglib) we can start using the libraries.
+
+A complication is that we might end up with a luajittex path matching before a
+luatex path due to the path spec. One solution is to first check with the engine
+prefixed. This could be prevented by a more strict lib pattern but that is not
+always under our control. So, we first check for paths with engine in their name
+and then without.
+
+]]--
+
+-- seems to be clua in recent texlive
+
+local gsub, find = string.gsub, string.find
+local pathpart, nameonly, joinfile = file.pathpart, file.nameonly, file.join
+local findfile, findfiles = resolvers and resolvers.findfile, resolvers and resolvers.findfiles
+
+local loaded = package.loaded
+
+local report_swiglib = logs.reporter("swiglib")
+local trace_swiglib = false trackers.register("resolvers.swiglib", function(v) trace_swiglib = v end)
+
+-- We can check if there are more that one component, and if not, we can
+-- append 'core'.
+
+local done = false
+
+local function requireswiglib(required,version)
+ local trace_swiglib = trace_swiglib or package.helpers.trace
+ local library = loaded[required]
+ if library == nil then
+ if trace_swiglib then
+ report_swiglib("requiring library %a with version %a",required,version or "any")
+ end
+ -- initialize a few variables
+ local required_full = gsub(required,"%.","/") -- package.helpers.lualibfile
+ local required_path = pathpart(required_full)
+ local required_base = nameonly(required_full)
+ local required_name = required_base .. "." .. os.libsuffix
+ local version = type(version) == "string" and version ~= "" and version or false
+ local engine = environment.ownmain or false
+ --
+ if trace_swiglib and not done then
+ local list = resolvers.expandedpathlistfromvariable("lib") -- fresh, no reuse
+ for i=1,#list do
+ report_swiglib("tds path %i: %s",i,list[i])
+ end
+ end
+ -- helpers
+ local function found(locate,asked_library,how,...)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a",how,asked_library)
+ end
+ return locate(asked_library,...)
+ end
+ local function check(locate,...)
+ local found = nil
+ if version then
+ local asked_library = joinfile(required_path,version,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","with version",asked_library)
+ end
+ found = locate(asked_library,...)
+ end
+ if not found or found == "" then
+ local asked_library = joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","with version",asked_library)
+ end
+ found = locate(asked_library,...)
+ end
+ return found and found ~= "" and found or false
+ end
+ -- Alternatively we could first collect the locations and then do the two attempts
+ -- on this list but in practice this is not more efficient as we might have a fast
+ -- match anyway.
+ local function attempt(checkpattern)
+ -- check cnf spec using name and version
+ if trace_swiglib then
+ report_swiglib("checking tds lib paths strictly")
+ end
+ local found = findfile and check(findfile,"lib")
+ if found and (not checkpattern or find(found,checkpattern)) then
+ return found
+ end
+ -- check cnf spec using wildcard
+ if trace_swiglib then
+ report_swiglib("checking tds lib paths with wildcard")
+ end
+ local asked_library = joinfile(required_path,".*",required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","latest version",asked_library)
+ end
+ local list = findfiles(asked_library,"lib",true)
+ if list and #list > 0 then
+ table.sort(list)
+ local found = list[#list]
+ if found and (not checkpattern or find(found,checkpattern)) then
+ return found
+ end
+ end
+ -- Check lib paths using name and version.
+ if trace_swiglib then
+ report_swiglib("checking lib paths")
+ end
+ package.extralibpath(environment.ownpath)
+ local paths = package.libpaths()
+ for i=1,#paths do
+ local found = check(lfs.isfile)
+ if found and (not checkpattern or find(found,checkpattern)) then
+ return found
+ end
+ end
+ return false
+ end
+ local found_library = nil
+ if engine then
+ if trace_swiglib then
+ report_swiglib("attemp 1, engine %a",engine)
+ end
+ found_library = attempt("/"..engine.."/")
+ if not found_library then
+ if trace_swiglib then
+ report_swiglib("attemp 2, no engine",asked_library)
+ end
+ found_library = attempt()
+ end
+ else
+ found_library = attempt()
+ end
+ -- load and initialize when found
+ if not found_library then
+ if trace_swiglib then
+ report_swiglib("not found: %a",required)
+ end
+ library = false
+ else
+ local path = pathpart(found_library)
+ local base = nameonly(found_library)
+ dir.push(path)
+ if trace_swiglib then
+ report_swiglib("found: %a",found_library)
+ end
+ local message = nil
+ local opener = "luaopen_" .. required_base
+ library, message = package.loadlib(found_library,opener)
+ local libtype = type(library)
+ if libtype == "function" then
+ library = library()
+ else
+ report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library")
+ library = false
+ end
+ dir.pop()
+ end
+ -- cache result
+ if not library then
+ report_swiglib("unknown: %a",required)
+ elseif trace_swiglib then
+ report_swiglib("stored: %a",required)
+ end
+ loaded[required] = library
+ else
+ report_swiglib("reused: %a",required)
+ end
+ return library
+end
+
+--[[
+
+For convenience we make the require loader function swiglib aware. Alternatively
+we could put the specific loader in the global namespace.
+
+]]--
+
+local savedrequire = require
+
+function require(name,version)
+ if find(name,"^swiglib%.") then
+ return requireswiglib(name,version)
+ else
+ return savedrequire(name)
+ end
+end
+
+--[[
+
+At the cost of some overhead we provide a specific loader so that we can keep
+track of swiglib usage which is handy for development. In context this is the
+recommended loader.
+
+]]--
+
+local swiglibs = { }
+local initializer = "core"
+
+function swiglib(name,version)
+ local library = swiglibs[name]
+ if not library then
+ statistics.starttiming(swiglibs)
+ if trace_swiglib then
+ report_swiglib("loading %a",name)
+ end
+ if not find(name,"%." .. initializer .. "$") then
+ fullname = "swiglib." .. name .. "." .. initializer
+ else
+ fullname = "swiglib." .. name
+ end
+ library = requireswiglib(fullname,version)
+ swiglibs[name] = library
+ statistics.stoptiming(swiglibs)
+ end
+ return library
+end
+
+statistics.register("used swiglibs", function()
+ if next(swiglibs) then
+ return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+ end
+end)
+
+--[[
+
+So, we now have:
+
+local gm = require("swiglib.gmwand.core")
+local gm = swiglib("gmwand.core")
+local sq = swiglib("mysql.core")
+local sq = swiglib("mysql.core","5.6")
+
+Watch out, the last one is less explicit and lacks the swiglib prefix.
+
+]]--
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua
new file mode 100644
index 00000000000..e1dcdc94d57
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua
@@ -0,0 +1,160 @@
+if not modules then modules = { } end modules ['util-lua'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment = "the strip code is written by Peter Cawley",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we will remove the 5.1 code some day soon
+
+local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
+local load, loadfile, type = load, loadfile, type
+
+utilities = utilities or {}
+utilities.lua = utilities.lua or { }
+local luautilities = utilities.lua
+
+local report_lua = logs.reporter("system","lua")
+
+local tracestripping = false
+local forcestupidcompile = true -- use internal bytecode compiler
+luautilities.stripcode = true -- support stripping when asked for
+luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12)
+luautilities.nofstrippedchunks = 0
+luautilities.nofstrippedbytes = 0
+local strippedchunks = { } -- allocate()
+luautilities.strippedchunks = strippedchunks
+
+luautilities.suffixes = {
+ tma = "tma",
+ tmc = jit and "tmb" or "tmc",
+ lua = "lua",
+ luc = jit and "lub" or "luc",
+ lui = "lui",
+ luv = "luv",
+ luj = "luj",
+ tua = "tua",
+ tuc = "tuc",
+}
+
+-- environment.loadpreprocessedfile can be set to a preprocessor
+
+local function register(name)
+ if tracestripping then
+ report_lua("stripped bytecode from %a",name or "unknown")
+ end
+ strippedchunks[#strippedchunks+1] = name
+ luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
+end
+
+local function stupidcompile(luafile,lucfile,strip)
+ local code = io.loaddata(luafile)
+ if code and code ~= "" then
+ code = load(code)
+ if code then
+ code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
+ if code and code ~= "" then
+ register(name)
+ io.savedata(lucfile,code)
+ return true, 0
+ end
+ else
+ report_lua("fatal error %a in file %a",1,luafile)
+ end
+ else
+ report_lua("fatal error %a in file %a",2,luafile)
+ end
+ return false, 0
+end
+
+-- quite subtle ... doing this wrong incidentally can give more bytes
+
+function luautilities.loadedluacode(fullname,forcestrip,name)
+ -- quite subtle ... doing this wrong incidentally can give more bytes
+ name = name or fullname
+ local code, message
+ if environment.loadpreprocessedfile then
+ code, message = environment.loadpreprocessedfile(fullname)
+ else
+ code, message = loadfile(fullname)
+ end
+ if code then
+ code()
+ else
+ report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip) == "function" then
+ forcestrip = forcestrip(fullname)
+ end
+ if forcestrip or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)), 0
+ else
+ return code, 0
+ end
+ elseif luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)), 0
+ else
+ return code, 0
+ end
+end
+
+function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local code, message = load(code)
+ if not code then
+ report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
+ end
+ if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)), 0 -- not yet executes
+ else
+ return code, 0
+ end
+end
+
+function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done = stupidcompile(luafile,lucfile,strip ~= false)
+ if done then
+ report_lua("dumping %a into %a stripped",luafile,lucfile)
+ if cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ end
+ return done
+end
+
+function luautilities.loadstripped(...)
+ local l = load(...)
+ if l then
+ return load(dump(l,true))
+ end
+end
+
+-- local getmetatable, type = getmetatable, type
+--
+-- local types = { }
+--
+-- function luautilities.registerdatatype(d,name)
+-- types[getmetatable(d)] = name
+-- end
+--
+-- function luautilities.datatype(d)
+-- local t = type(d)
+-- if t == "userdata" then
+-- local m = getmetatable(d)
+-- return m and types[m] or "userdata"
+-- else
+-- return t
+-- end
+-- end
+--
+-- luautilities.registerdatatype(lpeg.P("!"),"lpeg")
+--
+-- print(luautilities.datatype(lpeg.P("oeps")))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua b/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua
new file mode 100644
index 00000000000..690188ef879
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua
@@ -0,0 +1,228 @@
+if not modules then modules = { } end modules ['util-mrg'] = {
+ 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"
+}
+
+-- hm, quite unreadable
+
+local gsub, format = string.gsub, string.format
+local concat = table.concat
+local type, next = type, next
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt, Cb, Cg = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt, lpeg.Cb, lpeg.Cg
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+
+utilities = utilities or { }
+local merger = utilities.merger or { }
+utilities.merger = merger
+merger.strip_comment = true
+
+local report = logs.reporter("system","merge")
+utilities.report = report
+
+local m_begin_merge = "begin library merge"
+local m_end_merge = "end library merge"
+local m_begin_closure = "do -- create closure to overcome 200 locals limit"
+local m_end_closure = "end -- of closure"
+
+local m_pattern =
+ "%c+" ..
+ "%-%-%s+" .. m_begin_merge ..
+ "%c+(.-)%c+" ..
+ "%-%-%s+" .. m_end_merge ..
+ "%c+"
+
+local m_format =
+ "\n\n-- " .. m_begin_merge ..
+ "\n%s\n" ..
+ "-- " .. m_end_merge .. "\n\n"
+
+local m_faked =
+ "-- " .. "created merged file" .. "\n\n" ..
+ "-- " .. m_begin_merge .. "\n\n" ..
+ "-- " .. m_end_merge .. "\n\n"
+
+local m_report = [[
+-- used libraries : %s
+-- skipped libraries : %s
+-- original bytes : %s
+-- stripped bytes : %s
+]]
+
+local m_preloaded = [[package.loaded[%q] = package.loaded[%q] or true]]
+
+local function self_fake()
+ return m_faked
+end
+
+local function self_nothing()
+ return ""
+end
+
+local function self_load(name)
+ local data = io.loaddata(name) or ""
+ if data == "" then
+ report("unknown file %a",name)
+ else
+ report("inserting file %a",name)
+ end
+ return data or ""
+end
+
+-- -- saves some 20K .. scite comments
+-- data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
+-- -- saves some 20K .. ldx comments
+-- data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","")
+
+local space = patterns.space
+local eol = patterns.newline
+local equals = P("=")^0
+local open = P("[") * Cg(equals,"init") * P("[") * P("\n")^-1
+local close = P("]") * C(equals) * P("]")
+local closeeq = Cmt(close * Cb("init"), function(s,i,a,b) return a == b end)
+local longstring = open * (1 - closeeq)^0 * close
+
+local quoted = patterns.quoted
+local digit = patterns.digit
+local emptyline = space^0 * eol
+local operator1 = P("<=") + P(">=") + P("~=") + P("..") + S("/^<>=*+%%")
+local operator2 = S("*+/")
+local operator3 = S("-")
+local operator4 = P("..")
+local separator = S(",;")
+
+local ignore = (P("]") * space^1 * P("=") * space^1 * P("]")) / "]=[" +
+ (P("=") * space^1 * P("{")) / "={" +
+ (P("(") * space^1) / "(" +
+ (P("{") * (space+eol)^1 * P("}")) / "{}"
+local strings = quoted -- / function (s) print("<<"..s..">>") return s end
+local longcmt = (emptyline^0 * P("--") * longstring * emptyline^0) / ""
+local longstr = longstring
+local comment = emptyline^0 * P("--") * P("-")^0 * (1-eol)^0 * emptyline^1 / "\n"
+local optionalspaces = space^0 / ""
+local mandatespaces = space^1 / ""
+local optionalspacing = (eol+space)^0 / ""
+local mandatespacing = (eol+space)^1 / ""
+local pack = digit * space^1 * operator4 * optionalspacing +
+ optionalspacing * operator1 * optionalspacing +
+ optionalspacing * operator2 * optionalspaces +
+ mandatespacing * operator3 * mandatespaces +
+ optionalspaces * separator * optionalspaces
+local lines = emptyline^2 / "\n"
+local spaces = (space * space) / " "
+----- spaces = ((space+eol)^1 ) / " "
+
+local compact = Cs ( (
+ ignore +
+ strings +
+ longcmt +
+ longstr +
+ comment +
+ pack +
+ lines +
+ spaces +
+ 1
+)^1 )
+
+local strip = Cs((emptyline^2/"\n" + 1)^0)
+local stripreturn = Cs((1-P("return") * space^1 * P(1-space-eol)^1 * (space+eol)^0 * P(-1))^1)
+
+function merger.compact(data)
+ return lpegmatch(strip,lpegmatch(compact,data))
+end
+
+local function self_compact(data)
+ local delta = 0
+ if merger.strip_comment then
+ local before = #data
+ data = lpegmatch(compact,data)
+ data = lpegmatch(strip,data) -- also strips in longstrings ... alas
+ -- data = string.strip(data)
+ local after = #data
+ delta = before - after
+ report("original size %s, compacted to %s, stripped %s",before,after,delta)
+ data = format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
+ end
+ return lpegmatch(stripreturn,data) or data, delta
+end
+
+local function self_save(name, data)
+ if data ~= "" then
+ io.savedata(name,data)
+ report("saving %s with size %s",name,#data)
+ end
+end
+
+local function self_swap(data,code)
+ return data ~= "" and (gsub(data,m_pattern, function() return format(m_format,code) end, 1)) or ""
+end
+
+local function self_libs(libs,list)
+ local result, f, frozen, foundpath = { }, nil, false, nil
+ result[#result+1] = "\n"
+ if type(libs) == 'string' then libs = { libs } end
+ if type(list) == 'string' then list = { list } end
+ for i=1,#libs do
+ local lib = libs[i]
+ for j=1,#list do
+ local pth = gsub(list[j],"\\","/") -- file.clean_path
+ report("checking library path %a",pth)
+ local name = pth .. "/" .. lib
+ if lfs.isfile(name) then
+ foundpath = pth
+ end
+ end
+ if foundpath then break end
+ end
+ if foundpath then
+ report("using library path %a",foundpath)
+ local right, wrong, original, stripped = { }, { }, 0, 0
+ for i=1,#libs do
+ local lib = libs[i]
+ local fullname = foundpath .. "/" .. lib
+ if lfs.isfile(fullname) then
+ report("using library %a",fullname)
+ local preloaded = file.nameonly(lib)
+ local data = io.loaddata(fullname,true)
+ original = original + #data
+ local data, delta = self_compact(data)
+ right[#right+1] = lib
+ result[#result+1] = m_begin_closure
+ result[#result+1] = format(m_preloaded,preloaded,preloaded)
+ result[#result+1] = data
+ result[#result+1] = m_end_closure
+ stripped = stripped + delta
+ else
+ report("skipping library %a",fullname)
+ wrong[#wrong+1] = lib
+ end
+ end
+ right = #right > 0 and concat(right," ") or "-"
+ wrong = #wrong > 0 and concat(wrong," ") or "-"
+ report("used libraries: %a",right)
+ report("skipped libraries: %a",wrong)
+ report("original bytes: %a",original)
+ report("stripped bytes: %a",stripped)
+ result[#result+1] = format(m_report,right,wrong,original,stripped)
+ else
+ report("no valid library path found")
+ end
+ return concat(result, "\n\n")
+end
+
+function merger.selfcreate(libs,list,target)
+ if target then
+ self_save(target,self_swap(self_fake(),self_libs(libs,list)))
+ end
+end
+
+function merger.selfmerge(name,libs,list,target)
+ self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
+end
+
+function merger.selfclean(name)
+ self_save(name,self_swap(self_load(name),self_nothing()))
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-pck.lua b/Master/texmf-dist/tex/context/base/mkiv/util-pck.lua
new file mode 100644
index 00000000000..83b85cd9486
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-pck.lua
@@ -0,0 +1,146 @@
+if not modules then modules = { } end modules ['util-pck'] = {
+ 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"
+}
+
+-- moved from core-uti
+
+local next, tostring, type = next, tostring, type
+local sort, concat = table.sort, table.concat
+local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash
+
+utilities = utilities or { }
+utilities.packers = utilities.packers or { }
+local packers = utilities.packers
+packers.version = 1.01
+
+local function hashed(t)
+ local s, ns = { }, 0
+ for k, v in next, t do
+ ns = ns + 1
+ if type(v) == "table" then
+ s[ns] = k .. "={" .. hashed(v) .. "}"
+ else
+ s[ns] = k .. "=" .. tostring(v)
+ end
+ end
+ sort(s)
+ return concat(s,",")
+end
+
+local function simplehashed(t)
+ local s, ns = { }, 0
+ for k, v in next, t do
+ ns = ns + 1
+ s[ns] = k .. "=" .. v
+ end
+ sort(s)
+ return concat(s,",")
+end
+
+packers.hashed = hashed
+packers.simplehashed = simplehashed
+
+-- In luatex < 0.74 (lua 5.1) a next chain was the same for each run so no sort was needed,
+-- but in the latest greatest versions (lua 5.2) we really need to sort the keys in order
+-- not to get endless runs due to a difference in tuc files.
+
+local function pack(t,keys,skip,hash,index)
+ if t then
+ local sk = #t > 0 and sortedkeys(t) or sortedhashkeys(t)
+ for i=1,#sk do
+ local k = sk[i]
+ if not skip or not skip[k] then
+ local v = t[k]
+ --
+ if type(v) == "table" then
+ pack(v,keys,skip,hash,index)
+ if keys[k] then
+ local h = hashed(v)
+ local i = hash[h]
+ if not i then
+ i = #index + 1
+ index[i] = v
+ hash[h] = i
+ end
+ t[k] = i
+ end
+ end
+ end
+ end
+ end
+end
+
+local function unpack(t,keys,skip,index)
+ if t then
+ for k, v in next, t do
+ if keys[k] and type(v) == "number" then
+ local iv = index[v]
+ if iv then
+ v = iv
+ t[k] = v
+ end
+ end
+ if type(v) == "table" and (not skip or not skip[k]) then
+ unpack(v,keys,skip,index)
+ end
+ end
+ end
+end
+
+function packers.new(keys,version,skip)
+ return {
+ version = version or packers.version,
+ keys = tohash(keys),
+ skip = tohash(skip),
+ hash = { },
+ index = { },
+ }
+end
+
+function packers.pack(t,p,shared)
+ if shared then
+ pack(t,p.keys,p.skip,p.hash,p.index)
+ elseif not t.packer then
+ pack(t,p.keys,p.skip,p.hash,p.index)
+ if #p.index > 0 then
+ t.packer = {
+ version = p.version or packers.version,
+ keys = p.keys,
+ skip = p.skip,
+ index = p.index,
+ }
+ end
+ p.hash = { }
+ p.index = { }
+ end
+end
+
+function packers.unpack(t,p,shared)
+ if shared then
+ if p then
+ unpack(t,p.keys,p.skip,p.index)
+ end
+ else
+ local tp = t.packer
+ if tp then
+ if tp.version == (p and p.version or packers.version) then
+ unpack(t,tp.keys,tp.skip,tp.index)
+ else
+ return false
+ end
+ t.packer = nil
+ end
+ end
+ return true
+end
+
+function packers.strip(p)
+ p.hash = nil
+end
+
+-- We could have a packer.serialize where we first flush the shared table
+-- and then use inline a reference . This saves an unpack.
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua b/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua
new file mode 100644
index 00000000000..01138f1bbb3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua
@@ -0,0 +1,725 @@
+if not modules then modules = { } end modules ['util-prs'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpeg, table, string = lpeg, table, string
+local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local concat, gmatch, find = table.concat, string.gmatch, string.find
+local tostring, type, next, rawset = tostring, type, next, rawset
+local mod, div = math.mod, math.div
+
+utilities = utilities or {}
+local parsers = utilities.parsers or { }
+utilities.parsers = parsers
+local patterns = parsers.patterns or { }
+parsers.patterns = patterns
+
+local setmetatableindex = table.setmetatableindex
+local sortedhash = table.sortedhash
+local sortedkeys = table.sortedkeys
+local tohash = table.tohash
+
+local hashes = { }
+utilities.parsers.hashes = hashes
+-- we share some patterns
+
+local digit = R("09")
+local space = P(' ')
+local equal = P("=")
+local comma = P(",")
+local lbrace = P("{")
+local rbrace = P("}")
+local lparent = P("(")
+local rparent = P(")")
+local period = S(".")
+local punctuation = S(".,:;")
+local spacer = lpegpatterns.spacer
+local whitespace = lpegpatterns.whitespace
+local newline = lpegpatterns.newline
+local anything = lpegpatterns.anything
+local endofstring = lpegpatterns.endofstring
+
+local nobrace = 1 - (lbrace + rbrace )
+local noparent = 1 - (lparent + rparent)
+
+-- we could use a Cf Cg construct
+
+local escape, left, right = P("\\"), P('{'), P('}')
+
+lpegpatterns.balanced = P {
+ [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
+ [2] = left * V(1) * right
+}
+
+local nestedbraces = P { lbrace * (nobrace + V(1))^0 * rbrace }
+local nestedparents = P { lparent * (noparent + V(1))^0 * rparent }
+local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nestedbraces)^0) * (rbrace/""))
+local content = (1-endofstring)^0
+
+lpegpatterns.nestedbraces = nestedbraces -- no capture
+lpegpatterns.nestedparents = nestedparents -- no capture
+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 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 key = C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+-- todo: rewrite to fold etc
+--
+-- parse = lpeg.Cf(lpeg.Carg(1) * lpeg.Cg(key * equal * value) * separator^0,rawset)^0 -- lpeg.match(parse,"...",1,hash)
+
+local hash = { }
+
+local function set(key,value)
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+patterns.settings_to_hash_a = pattern_a_s
+patterns.settings_to_hash_b = pattern_b_s
+patterns.settings_to_hash_c = pattern_c_s
+
+function parsers.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function parsers.settings_to_hash(str,existing)
+ if not str or str == "" then
+ return { }
+ elseif type(str) == "table" then
+ if existing then
+ for k, v in next, str do
+ existing[k] = v
+ end
+ return exiting
+ else
+ return str
+ end
+ else
+ hash = existing or { }
+ lpegmatch(pattern_a_s,str)
+ return hash
+ end
+end
+
+function parsers.settings_to_hash_tolerant(str,existing)
+ if not str or str == "" then
+ return { }
+ elseif type(str) == "table" then
+ if existing then
+ for k, v in next, str do
+ existing[k] = v
+ end
+ return exiting
+ else
+ return str
+ end
+ else
+ hash = existing or { }
+ lpegmatch(pattern_b_s,str)
+ return hash
+ end
+end
+
+function parsers.settings_to_hash_strict(str,existing)
+ if not str or str == "" then
+ return nil
+ elseif type(str) == "table" then
+ if existing then
+ for k, v in next, str do
+ existing[k] = v
+ end
+ return exiting
+ else
+ return str
+ end
+ elseif str and str ~= "" then
+ hash = existing or { }
+ lpegmatch(pattern_c_s,str)
+ return next(hash) and hash
+ end
+end
+
+local separator = comma * space^0
+local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+ + C((nestedbraces + (1-comma))^0)
+local pattern = spaces * Ct(value*(separator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removed, leading spaces ignored
+
+patterns.settings_to_array = pattern
+
+-- we could use a weak table as cache
+
+function parsers.settings_to_array(str,strict)
+ if not str or str == "" then
+ return { }
+ elseif type(str) == "table" then
+ return str
+ elseif strict then
+ if find(str,"{",1,true) then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
+ elseif find(str,",",1,true) then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
+end
+
+-- this one also strips end spaces before separators
+--
+-- "{123} , 456 " -> "123" "456"
+
+-- local separator = space^0 * comma * space^0
+-- local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+-- + C((nestedbraces + (1-(space^0*(comma+P(-1)))))^0)
+-- local withvalue = Carg(1) * value / function(f,s) return f(s) end
+-- local pattern_a = spaces * Ct(value*(separator*value)^0)
+-- local pattern_b = spaces * withvalue * (separator*withvalue)^0
+
+local cache_a = { }
+local cache_b = { }
+
+function parsers.groupedsplitat(symbol,withaction)
+ if not symbol then
+ symbol = ","
+ end
+ local pattern = (withaction and cache_b or cache_a)[symbol]
+ if not pattern then
+ local symbols = S(symbol)
+ local separator = space^0 * symbols * space^0
+ local value = P(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
+ pattern = spaces * withvalue * (separator*withvalue)^0
+ cache_b[symbol] = pattern
+ else
+ pattern = spaces * Ct(value*(separator*value)^0)
+ cache_a[symbol] = pattern
+ end
+ end
+ return pattern
+end
+
+local pattern_a = parsers.groupedsplitat(",",false)
+local pattern_b = parsers.groupedsplitat(",",true)
+
+function parsers.stripped_settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return lpegmatch(pattern_a,str)
+ end
+end
+
+function parsers.process_stripped_settings(str,action)
+ if not str or str == "" then
+ return { }
+ else
+ return lpegmatch(pattern_b,str,1,action)
+ end
+end
+
+-- parsers.process_stripped_settings("{123} , 456 ",function(s) print("["..s.."]") end)
+-- parsers.process_stripped_settings("123 , 456 ",function(s) print("["..s.."]") end)
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = P(Carg(1)*value) / set
+local pattern = value*(separator*value)^0 * Carg(1)
+
+function parsers.add_settings_to_array(t,str)
+ return lpegmatch(pattern,str,nil,t)
+end
+
+function parsers.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, tn, s = { }, 0, sortedkeys(h)
+ omit = omit and tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ tn = tn + 1
+ t[tn] = key .. '=' .. yes
+ elseif not strict then
+ tn = tn + 1
+ t[tn] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ tn = tn + 1
+ t[tn] = key .. '=' .. tostring(value)
+ end
+ else
+ tn = tn + 1
+ t[tn] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function parsers.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+-- function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate anyway
+-- if str then
+-- t = t or { }
+-- for s in gmatch(str,"[^, ]+") do -- space added
+-- t[s] = true
+-- end
+-- return t
+-- else
+-- return { }
+-- end
+-- end
+
+local pattern = Cf(Ct("") * Cg(C((1-S(", "))^1) * S(", ")^0 * Cc(true))^1,rawset)
+
+function utilities.parsers.settings_to_set(str)
+ return str and lpegmatch(pattern,str) or { }
+end
+
+hashes.settings_to_set = table.setmetatableindex(function(t,k) -- experiment, not public
+ local v = k and lpegmatch(pattern,k) or { }
+ t[k] = v
+ return v
+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
+ for k, v in sortedhash(h) do
+ if v then
+ tn = tn + 1
+ t[tn] = k
+ end
+ end
+ return concat(t,separator or ",")
+end
+
+-- for mtx-context etc: aaaa bbbb cccc=dddd eeee=ffff
+
+local str = Cs(lpegpatterns.unquoted) + C((1-whitespace-equal)^1)
+local setting = Cf( Carg(1) * (whitespace^0 * Cg(str * whitespace^0 * (equal * whitespace^0 * str + Cc(""))))^1,rawset)
+local splitter = setting^1
+
+function utilities.parsers.options_to_hash(str,target)
+ return str and lpegmatch(splitter,str,1,target or { }) or { }
+end
+
+local splitter = lpeg.tsplitat(" ")
+
+function utilities.parsers.options_to_array(str)
+ return str and lpegmatch(splitter,str) or { }
+end
+
+-- for chem (currently one level)
+
+local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+ + C(digit^1 * lparent * (noparent + nestedparents)^1 * rparent)
+ + C((nestedbraces + (1-comma))^1)
+local pattern_a = spaces * Ct(value*(separator*value)^0)
+
+local function repeater(n,str)
+ if not n then
+ return str
+ else
+ local s = lpegmatch(pattern_a,str)
+ if n == 1 then
+ return unpack(s)
+ else
+ local t, tn = { }, 0
+ for i=1,n do
+ for j=1,#s do
+ tn = tn + 1
+ t[tn] = s[j]
+ end
+ end
+ return unpack(t)
+ end
+ end
+end
+
+local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+ + (C(digit^1)/tonumber * lparent * Cs((noparent + nestedparents)^1) * rparent) / repeater
+ + C((nestedbraces + (1-comma))^1)
+local pattern_b = spaces * Ct(value*(separator*value)^0)
+
+function parsers.settings_to_array_with_repeat(str,expand) -- beware: "" => { }
+ if expand then
+ return lpegmatch(pattern_b,str) or { }
+ else
+ return lpegmatch(pattern_a,str) or { }
+ end
+end
+
+--
+
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+local pattern = Ct((space + value)^0)
+
+function parsers.arguments_to_table(str)
+ return lpegmatch(pattern,str)
+end
+
+-- temporary here (unoptimized)
+
+function parsers.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = { }
+ self[class] = sc
+ if parentclass then
+ local sp = self[parentclass]
+ if not sp then
+ sp = { }
+ self[parentclass] = sp
+ end
+ setmetatableindex(sc,sp)
+ end
+ end
+ parsers.settings_to_hash(settings,sc)
+end
+
+function parsers.listitem(str)
+ return gmatch(str,"[^, ]+")
+end
+
+--
+
+local pattern = Cs { "start",
+ start = V("one") + V("two") + V("three"),
+ rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0,
+ thousand = digit * digit * digit,
+ one = digit * V("rest"),
+ two = digit * digit * V("rest"),
+ three = V("thousand") * V("rest"),
+}
+
+lpegpatterns.splitthousands = pattern -- maybe better in the parsers namespace ?
+
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+
+-- print(parsers.splitthousands("11111111111.11"))
+
+local optionalwhitespace = whitespace^0
+
+lpegpatterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1)
+lpegpatterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1)
+lpegpatterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1)
+
+-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n "
+-- inspect(lpegmatch(lpegpatterns.paragraphs,str))
+-- inspect(lpegmatch(lpegpatterns.sentences,str))
+-- inspect(lpegmatch(lpegpatterns.words,str))
+
+-- handy for k="v" [, ] k="v"
+
+local dquote = P('"')
+local equal = P('=')
+local escape = P('\\')
+local separator = S(' ,')
+
+local key = C((1-equal)^1)
+local value = dquote * C((1-dquote-escape*dquote)^0) * dquote
+
+----- pattern = Cf(Ct("") * Cg(key * equal * value) * separator^0,rawset)^0 * P(-1) -- was wrong
+local pattern = Cf(Ct("") * (Cg(key * equal * value) * separator^0)^1,rawset)^0 * P(-1)
+
+function parsers.keq_to_hash(str)
+ if str and str ~= "" then
+ return lpegmatch(pattern,str)
+ else
+ return { }
+ end
+end
+
+-- inspect(lpeg.match(pattern,[[key="value" foo="bar"]]))
+
+local defaultspecification = { separator = ",", quote = '"' }
+
+-- this version accepts multiple separators and quotes as used in the
+-- database module
+
+function parsers.csvsplitter(specification)
+ specification = specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator = specification.separator
+ local quotechar = specification.quote
+ local separator = S(separator ~= "" and separator or ",")
+ local whatever = C((1 - separator - newline)^0)
+ if quotechar and quotechar ~= "" then
+ local quotedata = nil
+ for chr in gmatch(quotechar,".") do
+ local quotechar = P(chr)
+ local quoteword = quotechar * C((1 - quotechar)^0) * quotechar
+ if quotedata then
+ quotedata = quotedata + quoteword
+ else
+ quotedata = quoteword
+ end
+ end
+ whatever = quotedata + whatever
+ end
+ local parser = Ct((Ct(whatever * (separator * whatever)^0) * S("\n\r")^1)^0 )
+ return function(data)
+ return lpegmatch(parser,data)
+ end
+end
+
+-- and this is a slightly patched version of a version posted by Philipp Gesang
+
+-- local mycsvsplitter = utilities.parsers.rfc4180splitter()
+
+-- local crap = [[
+-- first,second,third,fourth
+-- "1","2","3","4"
+-- "a","b","c","d"
+-- "foo","bar""baz","boogie","xyzzy"
+-- ]]
+
+-- local list, names = mycsvsplitter(crap,true) inspect(list) inspect(names)
+-- local list, names = mycsvsplitter(crap) inspect(list) inspect(names)
+
+function parsers.rfc4180splitter(specification)
+ specification = specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator = specification.separator --> rfc: COMMA
+ local quotechar = P(specification.quote) --> DQUOTE
+ local dquotechar = quotechar * quotechar --> 2DQUOTE
+ / specification.quote
+ local separator = S(separator ~= "" and separator or ",")
+ local escaped = quotechar
+ * Cs((dquotechar + (1 - quotechar))^0)
+ * quotechar
+ local non_escaped = C((1 - quotechar - newline - separator)^1)
+ local field = escaped + non_escaped + Cc("")
+ local record = Ct(field * (separator * field)^1)
+ local headerline = record * Cp()
+ local wholeblob = Ct((newline^(specification.strict and -1 or 1) * record)^0)
+ return function(data,getheader)
+ if getheader then
+ local header, position = lpegmatch(headerline,data)
+ local data = lpegmatch(wholeblob,data,position)
+ return data, header
+ else
+ return lpegmatch(wholeblob,data)
+ end
+ end
+end
+
+-- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- utilities.parsers.stepper("1-3,7,8,9")
+-- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- utilities.parsers.stepper(" 1 : 3, ,7 ")
+-- utilities.parsers.stepper("1:4,9:13,24:*",30)
+
+local function ranger(first,last,n,action)
+ if not first then
+ -- forget about it
+ elseif last == true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+
+local cardinal = lpegpatterns.cardinal / tonumber
+local spacers = lpegpatterns.spacer^0
+local endofstring = lpegpatterns.endofstring
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring)
+
+function parsers.stepper(str,n,action)
+ if type(n) == "function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
+
+--
+
+local pattern_math = Cs((P("%")/"\\percent " + P("^") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0)
+local pattern_text = Cs((P("%")/"\\percent " + (P("^")/"\\high") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0)
+
+patterns.unittotex = pattern
+
+function parsers.unittotex(str,textmode)
+ return lpegmatch(textmode and pattern_text or pattern_math,str)
+end
+
+local pattern = Cs((P("^") / "<sup>" * lpegpatterns.integer * Cc("</sup>") + anything)^0)
+
+function parsers.unittoxml(str)
+ return lpegmatch(pattern,str)
+end
+
+-- print(utilities.parsers.unittotex("10^-32 %"),utilities.parsers.unittoxml("10^32 %"))
+
+local cache = { }
+local spaces = lpegpatterns.space^0
+local dummy = function() end
+
+setmetatableindex(cache,function(t,k)
+ local separator = P(k)
+ local value = (1-separator)^0
+ local pattern = spaces * C(value) * separator^0 * Cp()
+ t[k] = pattern
+ return pattern
+end)
+
+local commalistiterator = cache[","]
+
+function utilities.parsers.iterator(str,separator)
+ local n = #str
+ if n == 0 then
+ return dummy
+ else
+ local pattern = separator and cache[separator] or commalistiterator
+ local p = 1
+ return function()
+ if p <= n then
+ local s, e = lpegmatch(pattern,str,p)
+ if e then
+ p = e
+ return s
+ end
+ end
+ end
+ end
+end
+
+-- for s in utilities.parsers.iterator("a b c,b,c") do
+-- print(s)
+-- end
+
+local function initialize(t,name)
+ local source = t[name]
+ if source then
+ local result = { }
+ for k, v in next, t[name] do
+ result[k] = v
+ end
+ return result
+ else
+ return { }
+ end
+end
+
+local function fetch(t,name)
+ return t[name] or { }
+end
+
+local function process(result,more)
+ for k, v in next, more do
+ result[k] = v
+ end
+ return result
+end
+
+local name = C((1-S(", "))^1)
+local parser = (Carg(1) * name / initialize) * (S(", ")^1 * (Carg(1) * name / fetch))^0
+local merge = Cf(parser,process)
+
+function utilities.parsers.mergehashes(hash,list)
+ return lpegmatch(merge,list,1,hash)
+end
+
+-- local t = {
+-- aa = { alpha = 1, beta = 2, gamma = 3, },
+-- bb = { alpha = 4, beta = 5, delta = 6, },
+-- cc = { epsilon = 3 },
+-- }
+--
+-- inspect(utilities.parsers.mergehashes(t,"aa, bb, cc"))
+
+function utilities.parsers.runtime(time)
+ if not time then
+ time = os.runtime()
+ end
+ local days = div(time,24*60*60)
+ time = mod(time,24*60*60)
+ local hours = div(time,60*60)
+ time = mod(time,60*60)
+ local minutes = div(time,60)
+ local seconds = mod(time,60)
+ return days, hours, minutes, seconds
+end
+
+--
+
+local spacing = whitespace^0
+local apply = P("->")
+local method = C((1-apply)^1)
+local token = lbrace * C((1-rbrace)^1) * rbrace + C(anything^1)
+
+local pattern = spacing * (method * spacing * apply + Carg(1)) * spacing * token
+
+function utilities.parsers.splitmethod(str,default)
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false, ""
+ end
+end
+
+-- print(utilities.parsers.splitmethod(" foo -> {bar} "))
+-- print(utilities.parsers.splitmethod("foo->{bar}"))
+-- print(utilities.parsers.splitmethod("foo->bar"))
+-- print(utilities.parsers.splitmethod("foo"))
+-- print(utilities.parsers.splitmethod("{foo}"))
+-- print(utilities.parsers.splitmethod())
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-ran.lua b/Master/texmf-dist/tex/context/base/mkiv/util-ran.lua
new file mode 100644
index 00000000000..50d0a7082ac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-ran.lua
@@ -0,0 +1,107 @@
+if not modules then modules = { } end modules ['util-ran'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local random = math.random
+local concat = table.concat
+local sub, upper = string.sub, string.upper
+
+local randomizers = utilities.randomizers or { }
+utilities.randomizers = randomizers
+
+local l_one = "bcdfghjklmnpqrstvwxz"
+local l_two = "aeiouy"
+
+local u_one = upper(l_one)
+local u_two = upper(l_two)
+
+local n_one = #l_one
+local n_two = #l_two
+
+function randomizers.word(min,max,separator)
+ local t = { }
+ for i=1,random(min,max) do
+ if i % 2 == 0 then
+ local r = random(1,n_one)
+ t[i] = sub(l_one,r,r)
+ else
+ local r = random(1,n_two)
+ t[i] = sub(l_two,r,r)
+ end
+ end
+ return concat(t,separator)
+end
+
+function randomizers.initials(min,max)
+ if not min then
+ if not max then
+ min, max = 1, 3
+ else
+ min, max = 1, min
+ end
+ elseif not max then
+ max = min
+ end
+ local t = { }
+ local n = random(min or 1,max or 3)
+ local m = 0
+ for i=1,n do
+ m = m + 1
+ if i % 2 == 0 then
+ local r = random(1,n_one)
+ t[m] = sub(u_one,r,r)
+ else
+ local r = random(1,n_two)
+ t[m] = sub(u_two,r,r)
+ end
+ m = m + 1
+ t[m] = "."
+ end
+ return concat(t)
+end
+
+function randomizers.firstname(min,max)
+ if not min then
+ if not max then
+ min, max = 3, 10
+ else
+ min, max = 1, min
+ end
+ elseif not max then
+ max = min
+ end
+ local t = { }
+ local n = random(min,max)
+ local b = true
+ if n % 2 == 0 then
+ local r = random(1,n_two)
+ t[1] = sub(u_two,r,r)
+ b = true
+ else
+ local r = random(1,n_one)
+ t[1] = sub(u_one,r,r)
+ b = false
+ end
+ for i=2,n do
+ if b then
+ local r = random(1,n_one)
+ t[i] = sub(l_one,r,r)
+ b = false
+ else
+ local r = random(1,n_two)
+ t[i] = sub(l_two,r,r)
+ b = true
+ end
+ end
+ return concat(t,separator)
+end
+
+randomizers.surname = randomizers.firstname
+
+-- for i=1,10 do
+-- print(randomizers.initials(1,3),randomizers.firstname(5,10),randomizers.surname(5,15))
+-- end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua
new file mode 100644
index 00000000000..8a12e7cf06e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua
@@ -0,0 +1,202 @@
+if not modules then modules = { } end modules ['util-sac'] = {
+ 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"
+}
+
+-- experimental string access (some 3 times faster than file access when messing
+-- with bytes)
+
+local byte, sub = string.byte, string.sub
+local extract = bit32.extract
+
+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 }
+end
+
+function streams.close()
+ -- dummy
+end
+
+function streams.size(f)
+ return f and f[3] or 0
+end
+
+function streams.setposition(f,i)
+ if f[4] then
+ -- zerobased
+ if i <= 0 then
+ f[2] = 1
+ else
+ f[2] = i + 1
+ end
+ else
+ if i <= 1 then
+ f[2] = 1
+ else
+ f[2] = i
+ end
+ end
+end
+
+function streams.getposition(f)
+ if f[4] then
+ -- zerobased
+ return f[2] - 1
+ else
+ return f[2]
+ end
+end
+
+function streams.look(f,n,chars)
+ local b = f[2]
+ local e = b + n - 1
+ if chars then
+ return sub(f[1],b,e)
+ else
+ return byte(f[1],b,e)
+ end
+end
+
+function streams.skip(f,n)
+ f[2] = f[2] + n
+end
+
+function streams.readbyte(f)
+ local i = f[2]
+ f[2] = i + 1
+ return byte(f[1],i)
+end
+
+function streams.readbytes(f,n)
+ local i = f[2]
+ local j = i + n
+ f[2] = j
+ return byte(f[1],i,j-1)
+end
+
+function streams.skipbytes(f,n)
+ f[2] = f[2] + n
+end
+
+function streams.readchar(f)
+ local i = f[2]
+ f[2] = i + 1
+ return sub(f[1],i,i)
+end
+
+function streams.readstring(f,n)
+ local i = f[2]
+ local j = i + n
+ f[2] = j
+ return sub(f[1],i,j-1)
+end
+
+function streams.readinteger1(f) -- one byte
+ local i = f[2]
+ f[2] = i + 1
+ local n = byte(f[1],i)
+ if n >= 0x80 then
+ return n - 0xFF - 1
+ else
+ return n
+ end
+end
+
+streams.readcardinal1 = streams.readbyte -- one byte
+streams.readcardinal = streams.readcardinal1
+streams.readinteger = streams.readinteger1
+
+function streams.readcardinal2(f)
+ local i = f[2]
+ local j = i + 1
+ f[2] = j + 1
+ local a, b = byte(f[1],i,j)
+ return 0x100 * a + b
+end
+
+function streams.readinteger2(f)
+ local i = f[2]
+ local j = i + 1
+ f[2] = j + 1
+ local a, b = byte(f[1],i,j)
+ local n = 0x100 * a + b
+ if n >= 0x8000 then
+ return n - 0xFFFF - 1
+ else
+ return n
+ end
+end
+
+function streams.readcardinal3(f)
+ local i = f[2]
+ local j = i + 2
+ f[2] = j + 1
+ local a, b, c = byte(f[1],i,j)
+ return 0x10000 * a + 0x100 * b + c
+end
+
+function streams.readcardinal4(f)
+ local i = f[2]
+ local j = i + 3
+ f[2] = j + 1
+ local a, b, c, d = byte(f[1],i,j)
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+end
+
+function streams.readinteger4(f)
+ local i = f[2]
+ local j = i + 3
+ f[2] = j + 1
+ local a, b, c, d = byte(f[1],i,j)
+ local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+ if n >= 0x8000000 then
+ return n - 0xFFFFFFFF - 1
+ else
+ return n
+ end
+end
+
+function streams.readfixed4(f)
+ local i = f[2]
+ local j = i + 3
+ f[2] = j + 1
+ local a, b, c, d = byte(f[1],i,j)
+ local n = 0x100 * a + b
+ if n >= 0x8000 then
+ return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF
+ else
+ return n + (0x100 * c + d)/0xFFFF
+ end
+end
+
+function streams.read2dot14(f)
+ local i = f[2]
+ local j = i + 1
+ f[2] = j + 1
+ local a, b = byte(f[1],i,j)
+ local n = 0x100 * a + b
+ local m = extract(n,0,30)
+ if n > 0x7FFF then
+ n = extract(n,30,2)
+ return m/0x4000 - 4
+ else
+ n = extract(n,30,2)
+ return n + m/0x4000
+ end
+end
+
+function streams.skipshort(f,n)
+ f[2] = f[2] + 2*(n or 1)
+end
+
+function streams.skiplong(f,n)
+ f[2] = f[2] + 4*(n or 1)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sbx.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sbx.lua
new file mode 100644
index 00000000000..260e8b3b5a7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sbx.lua
@@ -0,0 +1,415 @@
+if not modules then modules = { } end modules ['util-sbx'] = {
+ 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"
+}
+
+-- Note: we use expandname and collapsepath and these use chdir
+-- which is overloaded so we need to use originals there. Just
+-- something to keep in mind.
+
+if not sandbox then require("l-sandbox") end -- for testing
+
+local next, type = next, type
+
+local replace = utilities.templates.replace
+local collapsepath = file.collapsepath
+local expandname = dir.expandname
+local sortedhash = table.sortedhash
+local lpegmatch = lpeg.match
+local platform = os.type
+local P, S, C = lpeg.P, lpeg.S, lpeg.C
+local gsub = string.gsub
+local lower = string.lower
+local unquoted = string.unquoted
+local optionalquoted = string.optionalquoted
+
+local sandbox = sandbox
+local validroots = { }
+local validrunners = { }
+local validbinaries = { }
+local validators = { }
+local p_validroot = nil
+local finalized = nil
+local norunners = false
+local trace = false
+local p_split = lpeg.tsplitat(" ") -- more spaces?
+
+local report = logs.reporter("sandbox")
+
+trackers.register("sandbox",function(v) trace = v end) -- often too late anyway
+
+sandbox.setreporter(report)
+
+sandbox.finalizer(function()
+ finalized = true
+end)
+
+local function registerroot(root,what) -- what == read|write
+ if finalized then
+ report("roots are already finalized")
+ else
+ root = collapsepath(expandname(root))
+ if platform == "windows" then
+ root = lower(root) -- we assume ascii names
+ end
+ -- true: read & write | false: read
+ validroots[root] = what == "write" or false
+ end
+end
+
+sandbox.finalizer(function() -- initializers can set the path
+ if p_validroot then
+ report("roots are already initialized")
+ else
+ sandbox.registerroot(".","write") -- always ok
+ -- also register texmf as read
+ for name in sortedhash(validroots) do
+ if p_validroot then
+ p_validroot = P(name) + p_validroot
+ else
+ p_validroot = P(name)
+ end
+ end
+ p_validroot = p_validroot / validroots
+ end
+end)
+
+local function registerrunner(specification)
+ if finalized then
+ report("runners are already finalized")
+ else
+ local name = specification.name
+ if not name then
+ report("no runner name specified")
+ return
+ end
+ local program = specification.program
+ if type(program) == "string" then
+ -- common for all platforms
+ elseif type(program) == "table" then
+ program = program[platform]
+ end
+ if type(program) ~= "string" or program == "" then
+ report("invalid runner %a specified for platform %a",name,platform)
+ return
+ end
+ specification.program = program
+ validrunners[name] = specification
+ end
+end
+
+local function registerbinary(name)
+ if finalized then
+ report("binaries are already finalized")
+ elseif type(name) == "string" and name ~= "" then
+ validbinaries[name] = true
+ end
+end
+
+-- begin of validators
+
+local p_write = S("wa") p_write = (1 - p_write)^0 * p_write
+local p_path = S("\\/~$%:") p_path = (1 - p_path )^0 * p_path -- be easy on other arguments
+
+local function normalized(name) -- only used in executers
+ if platform == "windows" then
+ name = gsub(name,"/","\\")
+ end
+ return name
+end
+
+function sandbox.possiblepath(name)
+ return lpegmatch(p_path,name) and true or false
+end
+
+local filenamelogger = false
+
+function sandbox.setfilenamelogger(l)
+ filenamelogger = type(l) == "function" and l or false
+end
+
+local function validfilename(name,what)
+ if p_validroot and type(name) == "string" and lpegmatch(p_path,name) then
+ local asked = collapsepath(expandname(name))
+ if platform == "windows" then
+ asked = lower(asked) -- we assume ascii names
+ end
+ local okay = lpegmatch(p_validroot,asked)
+ if okay == true then
+ -- read and write access
+ if filenamelogger then
+ filenamelogger(name,"w",asked,true)
+ end
+ return name
+ elseif okay == false then
+ -- read only access
+ if not what then
+ -- no further argument to io.open so a readonly case
+ if filenamelogger then
+ filenamelogger(name,"r",asked,true)
+ end
+ return name
+ elseif lpegmatch(p_write,what) then
+ if filenamelogger then
+ filenamelogger(name,"w",asked,false)
+ end
+ return -- we want write access
+ else
+ if filenamelogger then
+ filenamelogger(name,"r",asked,true)
+ end
+ return name
+ end
+ else
+ if filenamelogger then
+ filenamelogger(name,"*",name,false)
+ end
+ end
+ else
+ return name
+ end
+end
+
+local function readable(name)
+ if platform == "windows" then
+ name = lower(name) -- we assume ascii names
+ end
+ local valid = validfilename(name,"r")
+ if valid then
+ return normalized(valid)
+ end
+end
+
+local function writeable(name)
+ if platform == "windows" then
+ name = lower(name) -- we assume ascii names
+ end
+ local valid = validfilename(name,"w")
+ if valid then
+ return normalized(valid)
+ end
+end
+
+validators.readable = readable
+validators.writeable = writeable
+validators.filename = readable
+
+table.setmetatableindex(validators,function(t,k)
+ if k then
+ t[k] = readable
+ end
+ return readable
+end)
+
+function validators.string(s)
+ return s -- can be used to prevent filename checking
+end
+
+-- end of validators
+
+sandbox.registerroot = registerroot
+sandbox.registerrunner = registerrunner
+sandbox.registerbinary = registerbinary
+sandbox.validfilename = validfilename
+
+local function filehandlerone(action,one,...)
+ local checkedone = validfilename(one)
+ if checkedone then
+ return action(one,...)
+ else
+-- report("file %a is unreachable",one)
+ end
+end
+
+local function filehandlertwo(action,one,two,...)
+ local checkedone = validfilename(one)
+ if checkedone then
+ local checkedtwo = validfilename(two)
+ if checkedtwo then
+ return action(one,two,...)
+ else
+-- report("file %a is unreachable",two)
+ end
+ else
+-- report("file %a is unreachable",one)
+ end
+end
+
+local function iohandler(action,one,...)
+ if type(one) == "string" then
+ local checkedone = validfilename(one)
+ if checkedone then
+ return action(one,...)
+ end
+ elseif one then
+ return action(one,...)
+ else
+ return action()
+ end
+end
+
+-- runners can be strings or tables
+--
+-- os.execute : string
+-- os.exec : table with program in [0|1]
+-- os.spawn : table with program in [0|1]
+--
+-- our execute: registered program with specification
+
+local function runhandler(action,name,specification)
+ local kind = type(name)
+ if kind ~= "string" then
+ return
+ end
+ if norunners then
+ report("no runners permitted, ignoring command: %s",name)
+ return
+ end
+ local spec = validrunners[name]
+ if not spec then
+ report("unknown runner: %s",name)
+ return
+ end
+ -- specs are already checked
+ local program = spec.program
+ local variables = { }
+ local checkers = spec.checkers or { }
+ if specification then
+ -- we only handle runners that are defined before the sandbox is
+ -- closed so in principle we cannot have user runs with no files
+ -- while for context runners we assume a robust specification
+ for k, v in next, specification do
+ local checker = validators[checkers[k]]
+ local value = checker(unquoted(v)) -- todo: write checkers
+ if value then
+ variables[k] = optionalquoted(value)
+ else
+ report("suspicious argument found, run blocked: %s",v)
+ return
+ end
+ end
+ end
+ local command = replace(program,variables)
+ if trace then
+ report("executing runner: %s",command)
+ end
+ return action(command)
+end
+
+-- only registered (from list) -- no checking on writable so let's assume harmless
+-- runs
+
+local function binaryhandler(action,name)
+ local kind = type(name)
+ local list = name
+ if kind == "string" then
+ list = lpegmatch(p_split,name)
+ end
+ local program = name[0] or name[1]
+ if type(program) ~= "string" or program == "" then
+ return --silently ignore
+ end
+ if norunners then
+ report("no binaries permitted, ignoring command: %s",program)
+ return
+ end
+ if not validbinaries[program] then
+ report("binary is not permitted: %s",program)
+ return
+ end
+ for i=0,#list do
+ local n = list[i]
+ if n then
+ local v = readable(unquoted(n))
+ if v then
+ list[i] = optionalquoted(v)
+ else
+ report("suspicious argument found, run blocked: %s",n)
+ return
+ end
+ end
+ end
+ return action(name)
+end
+
+sandbox.filehandlerone = filehandlerone
+sandbox.filehandlertwo = filehandlertwo
+sandbox.iohandler = iohandler
+sandbox.runhandler = runhandler
+sandbox.binaryhandler = binaryhandler
+
+function sandbox.disablerunners()
+ norunners = true
+end
+
+local execute = sandbox.original(os.execute)
+
+function sandbox.run(name,specification)
+ return runhandler(execute,name,specification)
+end
+
+-------------------
+
+local overload = sandbox.overload
+local register = sandbox.register
+
+ overload(loadfile, filehandlerone,"loadfile") -- todo
+
+if io then
+ overload(io.open, filehandlerone,"io.open")
+ overload(io.popen, filehandlerone,"io.popen")
+ overload(io.input, iohandler, "io.input")
+ overload(io.output, iohandler, "io.output")
+ overload(io.lines, filehandlerone,"io.lines")
+end
+
+if os then
+ overload(os.execute, binaryhandler, "os.execute")
+ overload(os.spawn, binaryhandler, "os.spawn")
+ overload(os.exec, binaryhandler, "os.exec")
+ overload(os.rename, filehandlertwo,"os.rename")
+ overload(os.remove, filehandlerone,"os.remove")
+end
+
+if lfs then
+ overload(lfs.chdir, filehandlerone,"lfs.chdir")
+ overload(lfs.mkdir, filehandlerone,"lfs.mkdir")
+ overload(lfs.rmdir, filehandlerone,"lfs.rmdir")
+ overload(lfs.isfile, filehandlerone,"lfs.isfile")
+ overload(lfs.isdir, filehandlerone,"lfs.isdir")
+ overload(lfs.attributes, filehandlerone,"lfs.attributes")
+ overload(lfs.dir, filehandlerone,"lfs.dir")
+ overload(lfs.lock_dir, filehandlerone,"lfs.lock_dir")
+ overload(lfs.touch, filehandlerone,"lfs.touch")
+ overload(lfs.link, filehandlertwo,"lfs.link")
+ overload(lfs.setmode, filehandlerone,"lfs.setmode")
+ overload(lfs.readlink, filehandlerone,"lfs.readlink")
+ overload(lfs.shortname, filehandlerone,"lfs.shortname")
+ overload(lfs.symlinkattributes,filehandlerone,"lfs.symlinkattributes")
+end
+
+-- these are used later on
+
+if zip then
+ zip.open = register(zip.open, filehandlerone,"zip.open")
+end
+
+if fontloader then
+ fontloader.open = register(fontloader.open,filehandlerone,"fontloader.open")
+ fontloader.info = register(fontloader.info,filehandlerone,"fontloader.info")
+end
+
+if epdf then
+ epdf.open = register(epdf.open, filehandlerone,"epdf.open")
+end
+
+-- not used in a normal mkiv run : os.spawn = os.execute
+-- not used in a normal mkiv run : os.exec = os.exec
+
+-- print(io.open("test.log"))
+-- sandbox.enable()
+-- print(io.open("test.log"))
+-- print(io.open("t:/test.log"))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sci.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sci.lua
new file mode 100644
index 00000000000..43d873b6377
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sci.lua
@@ -0,0 +1,288 @@
+if not modules then modules = { } end modules ['util-sci'] = {
+ version = 1.001,
+ comment = "companion to m-scite.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gsub, sub, find = string.gsub, string.sub, string.find
+local concat = table.concat
+local formatters = string.formatters
+local lpegmatch = lpeg.match
+local setmetatableindex = table.setmetatableindex
+
+local scite = scite or { }
+utilities.scite = scite
+
+local report = logs.reporter("scite")
+
+local lexerroot = file.dirname(resolvers.find_file("scite-context-lexer.lua"))
+
+local knownlexers = {
+ tex = "tex", mkiv = "tex", mkvi = "tex", mkxi = "tex", mkix = "tex", mkii = "tex", cld = "tex",
+ lua = "lua", lfg = "lua", lus = "lua",
+ w = "web", ww = "web",
+ c = "cpp", h = "cpp", cpp = "cpp", hpp = "cpp", cxx = "cpp", hxx = "cpp",
+ xml = "xml", lmx = "xml", ctx = "xml", xsl = "xml", xsd = "xml", rlx = "xml", css = "xml", dtd = "xml",
+ bib = "bibtex",
+ rme = "txt",
+ -- todo: pat/hyp ori
+}
+
+lexer = nil -- main lexer, global (for the moment needed for themes)
+
+local function loadscitelexer()
+ if not lexer then
+ dir.push(lexerroot)
+ lexer = dofile("scite-context-lexer.lua")
+ dofile("themes/scite-context-theme.lua")
+ dir.pop()
+ end
+ return lexer
+end
+
+local loadedlexers = setmetatableindex(function(t,k)
+ local l = knownlexers[k] or k
+ dir.push(lexerroot)
+ loadscitelexer()
+ local v = lexer.load(formatters["scite-context-lexer-%s"](l))
+ dir.pop()
+ t[l] = v
+ t[k] = v
+ return v
+end)
+
+scite.loadedlexers = loadedlexers
+scite.knownlexers = knownlexers
+scite.loadscitelexer = loadscitelexer
+
+local f_fore_bold = formatters['.%s { display: inline ; font-weight: bold ; color: #%s%s%s ; }']
+local f_fore_none = formatters['.%s { display: inline ; font-weight: normal ; color: #%s%s%s ; }']
+local f_none_bold = formatters['.%s { display: inline ; font-weight: bold ; }']
+local f_none_none = formatters['.%s { display: inline ; font-weight: normal ; }']
+local f_div_class = formatters['<div class="%s">%s</div>']
+local f_linenumber = formatters['<div class="linenumber">%s</div>\n']
+local f_div_number = formatters['.linenumber { display: inline-block ; font-weight: normal ; width: %sem ; margin-right: 2em ; padding-right: .25em ; text-align: right ; background-color: #C7C7C7 ; }']
+
+local replacer_regular = lpeg.replacer {
+ ["<"] = "&lt;",
+ [">"] = "&gt;",
+ ["&"] = "&amp;",
+}
+
+local linenumber = 0
+local linenumbers = { }
+
+local replacer_numbered = lpeg.replacer {
+ ["<"] = "&lt;",
+ [">"] = "&gt;",
+ ["&"] = "&amp;",
+ [lpeg.patterns.newline] = function()
+ linenumber = linenumber + 1
+ linenumbers[linenumber] = f_linenumber(linenumber)
+ return "\n"
+ end,
+}
+
+local css = nil
+
+local function exportcsslexing()
+ if not css then
+ loadscitelexer()
+ local function black(f)
+ return (f[1] == f[2]) and (f[2] == f[3]) and (f[3] == '00')
+ end
+ local result, r = { }, 0
+ for k, v in table.sortedhash(lexer.context.styles) do
+ local bold = v.bold
+ local fore = v.fore
+ r = r + 1
+ if fore and not black(fore) then
+ if bold then
+ result[r] = f_fore_bold(k,fore[1],fore[2],fore[3])
+ else
+ result[r] = f_fore_none(k,fore[1],fore[2],fore[3])
+ end
+ else
+ if bold then
+ result[r] = f_none_bold(k)
+ else
+ result[r] = f_none_none(k)
+ end
+ end
+ end
+ css = concat(result,"\n")
+ end
+ return css
+end
+
+local function exportwhites()
+ return setmetatableindex(function(t,k)
+ local v = find(k,"white") and true or false
+ t[k] = v
+ return v
+ end)
+end
+
+local function exportstyled(lexer,text,numbered)
+ local result = lexer.lex(lexer,text,0)
+ local start = 1
+ local whites = exportwhites()
+ local buffer = { }
+ local b = 0
+ linenumber = 0
+ linenumbers = { }
+ local replacer = numbered and replacer_numbered or replacer_regular
+ local n = #result
+ for i=1,n,2 do
+ local ii = i + 1
+ local style = result[i]
+ local position = result[ii]
+ local txt = sub(text,start,position-1)
+ txt = lpegmatch(replacer,txt)
+ b = b + 1
+ if whites[style] then
+ buffer[b] = txt
+ else
+ buffer[b] = f_div_class(style,txt)
+ end
+ start = position
+ end
+ buffer = concat(buffer)
+ return buffer, concat(linenumbers)
+end
+
+local function exportcsslinenumber()
+ return f_div_number(#tostring(linenumber)/2+1)
+end
+
+local htmlfile = utilities.templates.replacer([[
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <title>%title%</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+ <style type="text/css"><!--
+%lexingstyles%
+%numberstyles%
+ --></style>
+ <body>
+ <table style="padding:0; margin:0;">
+ <tr>
+ <td><pre>%linenumbers%</pre></td>
+ <td><pre>%lexedcontent%</pre></td>
+ </tr>
+ </table>
+ </body>
+</html>
+]])
+
+function scite.tohtml(data,lexname,numbered,title)
+ local source, lines = exportstyled(loadedlexers[lexname],data or "",numbered)
+ return htmlfile {
+ lexedcontent = source, -- before numberstyles
+ lexingstyles = exportcsslexing(),
+ numberstyles = exportcsslinenumber(),
+ title = title or "context source file",
+ linenumbers = lines,
+ }
+end
+
+local function maketargetname(name)
+ if name then
+ return file.removesuffix(name) .. "-" .. file.suffix(name) .. ".html"
+ else
+ return "util-sci.html"
+ end
+end
+
+function scite.filetohtml(filename,lexname,targetname,numbered,title)
+ io.savedata(targetname or "util-sci.html",scite.tohtml(io.loaddata(filename),lexname or file.suffix(filename),numbered,title or filename))
+end
+
+function scite.css()
+ return exportcsslexing() .. "\n" .. exportcsslinenumber()
+end
+
+function scite.html(data,lexname,numbered)
+ return exportstyled(loadedlexers[lexname],data or "",numbered)
+end
+
+local f_tree_entry = formatters['<a href="%s" class="dir-entry">%s</a>']
+
+local htmlfile = utilities.templates.replacer([[
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <title>%title%</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+ <style type="text/css"><!--
+%styles%
+ --></style>
+ <body>
+ <pre>
+%dirlist%
+ </pre>
+ </body>
+</html>
+]])
+
+function scite.converttree(sourceroot,targetroot,numbered)
+ if lfs.isdir(sourceroot) then
+ statistics.starttiming()
+ local skipped = { }
+ local noffiles = 0
+ dir.makedirs(targetroot)
+ local function scan(sourceroot,targetroot,subpath)
+ local tree = { }
+ for name in lfs.dir(sourceroot) do
+ if name ~= "." and name ~= ".." then
+ local sourcename = file.join(sourceroot,name)
+ local targetname = file.join(targetroot,name)
+ local mode = lfs.attributes(sourcename,'mode')
+ local path = subpath and file.join(subpath,name) or name
+ if mode == 'file' then
+ local filetype = file.suffix(sourcename)
+ local basename = file.basename(name)
+ local targetname = maketargetname(targetname)
+ local fullname = file.join(path,name)
+ if knownlexers[filetype] then
+ report("converting file %a to %a",sourcename,targetname)
+ scite.filetohtml(sourcename,nil,targetname,numbered,fullname)
+ noffiles = noffiles + 1
+ tree[#tree+1] = f_tree_entry(file.basename(targetname),basename)
+ else
+ skipped[filetype] = true
+ report("no lexer for %a",sourcename)
+ end
+ else
+ dir.makedirs(targetname)
+ scan(sourcename,targetname,path)
+ tree[#tree+1] = f_tree_entry(file.join(name,"files.html"),name)
+ end
+ end
+ end
+ report("saving tree in %a",targetroot)
+ local htmldata = htmlfile {
+ dirlist = concat(tree,"\n"),
+ styles = "",
+ title = path or "context dir listing",
+ }
+ io.savedata(file.join(targetroot,"files.html"),htmldata)
+ end
+ scan(sourceroot,targetroot)
+ if next(skipped) then
+ report("skipped filetypes: %a",table.concat(table.sortedkeys(skipped)," "))
+ end
+ statistics.stoptiming()
+ report("conversion time for %s files: %s",noffiles,statistics.elapsedtime())
+ end
+end
+
+-- scite.filetohtml("strc-sec.mkiv",nil,"e:/tmp/util-sci.html",true)
+-- scite.filetohtml("syst-aux.mkiv",nil,"e:/tmp/util-sci.html",true)
+
+-- scite.converttree("t:/texmf/tex/context","e:/tmp/html/context",true)
+
+return scite
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
new file mode 100644
index 00000000000..32fe5909624
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
@@ -0,0 +1,352 @@
+if not modules then modules = { } end modules ['util-seq'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Here we implement a mechanism for chaining the special functions
+that we use in <l n="context"> to deal with mode list processing. We
+assume that namespaces for the functions are used, but for speed we
+use locals to refer to them when compiling the chain.</p>
+--ldx]]--
+
+-- todo: delayed: i.e. we register them in the right order already but delay usage
+
+-- todo: protect groups (as in tasks)
+
+local gsub, concat, gmatch = string.gsub, table.concat, string.gmatch
+local type, load = type, load
+
+utilities = utilities or { }
+local tables = utilities.tables
+local allocate = utilities.storage.allocate
+
+local formatters = string.formatters
+
+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 function validaction(action)
+ if type(action) == "string" then
+ local g = _G
+ for str in gmatch(action,"[^%.]+") do
+ g = g[str]
+ if not g then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+local compile
+
+local known = { } -- just a convenience, in case we want public access (only to a few methods)
+
+function sequencers.new(t) -- was reset
+ local s = {
+ list = { },
+ order = { },
+ kind = { },
+ askip = { },
+ gskip = { },
+ dirty = true,
+ runner = nil,
+ }
+ if t then
+ s.arguments = t.arguments
+ s.returnvalues = t.returnvalues
+ s.results = t.results
+ local name = t.name
+ if name and name ~= "" then
+ s.name = name
+ known[name] = s
+ end
+ end
+ table.setmetatableindex(s,function(t,k)
+ -- this will automake a dirty runner
+ if k == "runner" then
+ local v = compile(t,t.compiler)
+ return v
+ end
+ end)
+ known[s] = s -- saves test for string later on
+ return s
+end
+
+function sequencers.prependgroup(t,group,where)
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertbeforevalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.appendgroup(t,group,where)
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertaftervalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.prependaction(t,group,action,where,kind,force)
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertbeforevalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
+ end
+end
+
+function sequencers.appendaction(t,group,action,where,kind,force)
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertaftervalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
+ end
+end
+
+function sequencers.enableaction(t,action)
+ t = known[t]
+ if t then
+ t.askip[action] = false
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.disableaction(t,action)
+ t = known[t]
+ if t then
+ t.askip[action] = true
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.enablegroup(t,group)
+ t = known[t]
+ if t then
+ t.gskip[action] = false
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.disablegroup(t,group)
+ t = known[t]
+ if t then
+ t.gskip[action] = true
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.setkind(t,action,kind)
+ t = known[t]
+ if t then
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
+end
+
+function sequencers.removeaction(t,group,action,force)
+ t = known[t]
+ local g = t and t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ t.dirty = true
+ t.runner = nil
+ 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
+ end
+ end
+end
+
+local function localize(str)
+ return (gsub(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
+ for i=1,#order do
+ local group = order[i]
+ if not gskip[group] then
+ local actions = list[group]
+ for i=1,#actions do
+ local action = actions[i]
+ if not askip[action] then
+ local localized
+ if type(action) == "function" then
+ local name = localize(tostring(action))
+ functions[name] = action
+ action = formatters["utilities.sequencers.functions.%s"](name)
+ localized = localize(name) -- shorter than action
+ else
+ localized = localize(action)
+ end
+ n = n + 1
+ variables[n] = formatters["local %s = %s"](localized,action)
+ if not returnvalues then
+ calls[n] = formatters["%s(%s)"](localized,arguments)
+ elseif n == 1 then
+ calls[n] = formatters["local %s = %s(%s)"](returnvalues,localized,arguments)
+ else
+ calls[n] = formatters["%s = %s(%s)"](returnvalues,localized,arguments)
+ end
+ end
+ end
+ end
+ end
+ t.dirty = false
+ if n == 0 then
+ t.compiled = ""
+ else
+ variables = concat(variables,"\n")
+ calls = concat(calls,"\n")
+ if results then
+ t.compiled = formatters["%s\nreturn function(%s)\n%s\nreturn %s\nend"](variables,arguments,calls,results)
+ else
+ 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
+ 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)
+ t.compiled = compiled
+ else
+ compiled = construct(t,n)
+ 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
+ return runner
+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 = [[
+%s
+return function(head%s)
+ local ok, done = false, false
+%s
+ return head, done
+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 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 = ",..."
+ end
+ for i=1,#order do
+ local group = order[i]
+ if not gskip[group] then
+ local actions = list[group]
+ 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 kind[action] == "nohead" then
+ calls[n] = formatters[" ok = %s(head%s) done = done or ok"](localized,args)
+ else
+ calls[n] = formatters[" head, ok = %s(head%s) done = done or ok"](localized,args)
+ end
+-- local s = " print('" .. tostring(group) .. " " .. tostring(action) .. " : ' .. tostring(head)) "
+-- calls[n] = s .. calls[n] .. s
+ end
+ end
+ end
+ end
+ local processor = #calls > 0 and formatters[template_yes](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
+-- print(processor)
+ return processor
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua
new file mode 100644
index 00000000000..3a52ee86de3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua
@@ -0,0 +1,97 @@
+if not modules then modules = { } end modules ['util-soc'] = {
+ version = 1.001,
+ comment = "support for sockets / protocols",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local smtp = require("socket.smtp")
+local ltn12 = require("ltn12")
+local mime = require("mime")
+
+local mail = utilities.mail or { }
+utilities.mail = mail
+
+local report_mail = logs.reporter("mail")
+
+function mail.send(specification)
+ local presets = specification.presets
+ if presets then
+ table.setmetatableindex(specification,presets)
+ end
+ local server = specification.server or ""
+ if not server then
+ report_mail("no server specified")
+ return false, "invalid server"
+ end
+ local to = specification.to or specification.recepient or ""
+ if to == "" then
+ report_mail("no recipient specified")
+ return false, "invalid recipient"
+ end
+ local from = specification.from or specification.sender or ""
+ if from == "" then
+ report_mail("no sender specified")
+ return false, "invalid sender"
+ end
+ local message = { }
+ local body = specification.body
+ if body then
+ message[#message+1] = {
+ body = body
+ }
+ end
+ local files = specification.files
+ if files then
+ for i=1,#files do
+ local filename = files[i]
+ local handle = io.open(filename, "rb")
+ if handle then
+ report_mail("attaching file %a",filename)
+ message[#message+1] = {
+ headers = {
+ ["content-type"] = format('application/pdf; name="%s"',filename),
+ ["content-disposition"] = format('attachment; filename="%s"',filename),
+ ["content-description"] = format('file: %s',filename),
+ ["content-transfer-encoding"] = "BASE64"
+ },
+ body = ltn12.source.chain(
+ ltn12.source.file(handle),
+ ltn12.filter.chain(mime.encode("base64"),mime.wrap())
+ )
+ }
+ else
+ report_mail("file %a not found",filename)
+ end
+ end
+ end
+ local user = specification.user
+ local password = specification.password
+ local result, detail = smtp.send {
+ server = specification.server,
+ port = specification.port,
+ user = user ~= "" and user or nil,
+ password = password ~= "" and password or nil,
+ from = from,
+ rcpt = to,
+ source = smtp.message {
+ headers = {
+ to = to,
+ from = from,
+ cc = specification.cc,
+ subject = specification.subject or "no subject",
+ },
+ body = message
+ },
+ }
+ if detail then
+ report_mail("error: %s",detail)
+ return false, detail
+ else
+ report_mail("message sent")
+ return true
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua
new file mode 100644
index 00000000000..9a0fbc29983
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua
@@ -0,0 +1,284 @@
+if not modules then modules = { } end modules ['util-sql-client'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: make a converter
+
+local rawset, setmetatable = rawset, setmetatable
+local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","client")
+
+local sql = utilities.sql
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local preparetemplate = helpers.preparetemplate
+local splitdata = helpers.splitdata
+local replacetemplate = utilities.templates.replace
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+local getserver = sql.getserver
+
+-- Experiments with an p/action demonstrated that there is not much gain. We could do a runtime
+-- capture but creating all the small tables is not faster and it doesn't work well anyway.
+
+local separator = P("\t")
+local newline = patterns.newline
+local empty = Cc("")
+
+local entry = C((1-separator-newline)^0) -- C 10% faster than Cs
+
+local unescaped = P("\\n") / "\n"
+ + P("\\t") / "\t"
+ + P("\\0") / "\000"
+ + P("\\\\") / "\\"
+
+local entry = Cs((unescaped + (1-separator-newline))^0) -- C 10% faster than Cs but Cs needed due to nesting
+
+local getfirst = Ct( entry * (separator * (entry+empty))^0) + newline
+local skipfirst = (1-newline)^1 * newline
+local skipdashes = (P("-")+separator)^1 * newline
+local getfirstline = C((1-newline)^0)
+
+local cache = { }
+
+local function splitdata(data) -- todo: hash on first line ... maybe move to client module
+ if data == "" then
+ if trace_sql then
+ report_state("no data")
+ end
+ return { }, { }
+ end
+ local first = lpegmatch(getfirstline,data)
+ if not first then
+ if trace_sql then
+ report_state("no data")
+ end
+ return { }, { }
+ end
+ local p = cache[first]
+ if p then
+ -- report_state("reusing: %s",first)
+ local entries = lpegmatch(p.parser,data)
+ return entries or { }, p.keys
+ elseif p == false then
+ return { }, { }
+ elseif p == nil then
+ local keys = lpegmatch(getfirst,first) or { }
+ if #keys == 0 then
+ if trace_sql then
+ report_state("no banner")
+ end
+ cache[first] = false
+ return { }, { }
+ end
+ -- quite generic, could be a helper
+ local n = #keys
+ if n == 0 then
+ report_state("no fields")
+ cache[first] = false
+ return { }, { }
+ end
+ if n == 1 then
+ local key = keys[1]
+ if trace_sql then
+ report_state("one field with name %a",key)
+ end
+ p = Cg(Cc(key) * entry)
+ else
+ for i=1,n do
+ local key = keys[i]
+ if trace_sql then
+ report_state("field %s has name %a",i,key)
+ end
+ local s = Cg(Cc(key) * entry)
+ if p then
+ p = p * separator * s
+ else
+ p = s
+ end
+ end
+ end
+ p = Cf(Ct("") * p,rawset) * newline^1
+if getserver() == "mssql" then
+ p = skipfirst * skipdashes * Ct(p^0)
+else
+ p = skipfirst * Ct(p^0)
+end
+ cache[first] = { parser = p, keys = keys }
+ local entries = lpegmatch(p,data)
+ return entries or { }, keys
+ end
+end
+
+local splitter = skipfirst * Ct((Ct(entry * (separator * entry)^0) * newline^1)^0)
+
+local function getdata(data)
+ return lpegmatch(splitter,data)
+end
+
+helpers.splitdata = splitdata
+helpers.getdata = getdata
+
+local t_runner = {
+ mysql = [[mysql --batch --user="%username%" --password="%password%" --host="%host%" --port=%port% --database="%database%" --default-character-set=utf8 < "%queryfile%" > "%resultfile%"]],
+ mssql = [[sqlcmd -S %host% %?U: -U "%username%" ?% %?P: -P "%password%" ?% -I -W -w 65535 -s"]] .. "\t" .. [[" -m 1 -i "%queryfile%" -o "%resultfile%"]],
+}
+
+local t_preamble = {
+ mysql = [[
+SET GLOBAL SQL_MODE=ANSI_QUOTES;
+ ]],
+ mssql = [[
+:setvar SQLCMDERRORLEVEL 1
+SET QUOTED_IDENTIFIER ON;
+SET NOCOUNT ON;
+%?database: USE %database%; ?%
+ ]],
+}
+
+local function dataprepared(specification,client)
+ local query = preparetemplate(specification)
+ if query then
+ local preamble = t_preamble[getserver()] or t_preamble.mysql
+ if preamble then
+ preamble = replacetemplate(preamble,specification.variables,'sql')
+ query = preamble .. "\n" .. query
+ end
+ io.savedata(specification.queryfile,query)
+ os.remove(specification.resultfile)
+ if trace_queries then
+ report_state("query: %s",query)
+ end
+ return true
+ else
+ -- maybe push an error
+ os.remove(specification.queryfile)
+ os.remove(specification.resultfile)
+ end
+end
+
+local function datafetched(specification,client)
+ local runner = t_runner[getserver()] or t_runner.mysql
+ local command = replacetemplate(runner,specification)
+ if trace_sql then
+ local t = osclock()
+ report_state("command: %s",command)
+ local okay = os.execute(command)
+ report_state("fetchtime: %.3f sec",osclock()-t) -- not okay under linux
+ return okay == 0
+ else
+ return os.execute(command) == 0
+ end
+end
+
+local function dataloaded(specification)
+ if trace_sql then
+ local t = osclock()
+ local data = io.loaddata(specification.resultfile) or ""
+ report_state("datasize: %.3f MB",#data/1024/1024)
+ report_state("loadtime: %.3f sec",osclock()-t)
+ return data
+ else
+ return io.loaddata(specification.resultfile) or ""
+ end
+end
+
+local function dataconverted(data,converter)
+ if converter then
+ local data = getdata(data)
+ if data then
+ data = converter.client(data)
+ end
+ return data
+ elseif trace_sql then
+ local t = osclock()
+ local data, keys = splitdata(data,target)
+ report_state("converttime: %.3f",osclock()-t)
+ report_state("keys: %s ",#keys)
+ report_state("entries: %s ",#data)
+ return data, keys
+ else
+ return splitdata(data)
+ end
+end
+
+-- todo: new, etc
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing client")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ if not dataprepared(specification,methods.client) then
+ report_state("error in preparation")
+ return
+ end
+ if not datafetched(specification,methods.client) then
+ report_state("error in fetching, query: %s",string.collapsespaces(io.loaddata(specification.queryfile)))
+ return
+ end
+ local data = dataloaded(specification)
+ if not data then
+ report_state("error in loading")
+ return
+ end
+ local data, keys = dataconverted(data,specification.converter)
+ if not data then
+ report_state("error in converting or no data")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+-- The following is not that (memory) efficient but normally we will use
+-- the lib anyway. Of course we could make a dedicated converter and/or
+-- hook into the splitter code but ... it makes not much sense because then
+-- we can as well move the builder to the library modules.
+--
+-- Here we reuse data as the indexes are the same, unless we hash.
+
+local wraptemplate = [[
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(data)
+ local target = %s -- data or { }
+ for i=1,#data do
+ local cells = data[i]
+ target[%s] = {
+ %s
+ }
+ end
+ return target
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.client = {
+ execute = execute,
+ usesfiles = true,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua
new file mode 100644
index 00000000000..15754e26ab1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua
@@ -0,0 +1,289 @@
+if not modules then modules = { } end modules ['util-sql-library'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- local function pcall(f,...) return true, f(...) end
+
+-- For some reason the sql lib partially fails in luatex when creating hashed row. So far
+-- we couldn't figure it out (some issue with adapting the table that is passes as first
+-- argument in the fetch routine. Apart from this it looks like the mysql binding has some
+-- efficiency issues (like creating a keys and types table for each row) but that could be
+-- optimized. Anyhow, fecthing results can be done as follows:
+
+-- local function collect_1(r)
+-- local t = { }
+-- for i=1,r:numrows() do
+-- t[#t+1] = r:fetch({},"a")
+-- end
+-- return t
+-- end
+--
+-- local function collect_2(r)
+-- local keys = r:getcolnames()
+-- local n = #keys
+-- local t = { }
+-- for i=1,r:numrows() do
+-- local v = { r:fetch() }
+-- local r = { }
+-- for i=1,n do
+-- r[keys[i]] = v[i]
+-- end
+-- t[#t+1] = r
+-- end
+-- return t
+-- end
+--
+-- local function collect_3(r)
+-- local keys = r:getcolnames()
+-- local n = #keys
+-- local t = { }
+-- for i=1,r:numrows() do
+-- local v = r:fetch({},"n")
+-- local r = { }
+-- for i=1,n do
+-- r[keys[i]] = v[i]
+-- end
+-- t[#t+1] = r
+-- end
+-- return t
+-- end
+--
+-- On a large table with some 8 columns (mixed text and numbers) we get the following
+-- timings (the 'a' alternative is already using the more efficient variant in the
+-- binding).
+--
+-- collect_1 : 1.31
+-- collect_2 : 1.39
+-- collect_3 : 1.75
+--
+-- Some, as a workaround for this 'bug' the second alternative can be used.
+
+local format = string.format
+local lpegmatch = lpeg.match
+local setmetatable, type = setmetatable, type
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","library")
+
+local sql = utilities.sql
+local mysql = require("luasql.mysql")
+local cache = { }
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local querysplitter = helpers.querysplitter
+local dataprepared = helpers.preparetemplate
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+local formatters = string.formatters
+
+local initialize = mysql.mysql
+
+local function connect(session,specification)
+ return session:connect(
+ specification.database or "",
+ specification.username or "",
+ specification.password or "",
+ specification.host or "",
+ specification.port
+ )
+end
+
+local function fetched(specification,query,converter)
+ if not query or query == "" then
+ report_state("no valid query")
+ return false
+ end
+ local id = specification.id
+ local session, connection
+ if id then
+ local c = cache[id]
+ if c then
+ session = c.session
+ connection = c.connection
+ end
+ if not connection then
+ session = initialize()
+ if not session then
+ return formatters["no session for %a"](id)
+ end
+ connection = connect(session,specification)
+ if not connection then
+ return formatters["no connection for %a"](id)
+ end
+ cache[id] = { session = session, connection = connection }
+ end
+ else
+ session = initialize()
+ if not session then
+ return "no session"
+ end
+ connection = connect(session,specification)
+ if not connection then
+ return "no connection"
+ end
+ end
+ if not connection then
+ report_state("error in connection: %s@%s to %s:%s",
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+ return "no connection"
+ end
+ 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))
+ if m then
+ report_state("message: %s",m)
+ end
+ end
+ local t = type(r)
+ if t == "userdata" then
+ result = r
+ okay = true
+ elseif t == "number" then
+ okay = true
+ end
+ end
+ if not okay then -- can go
+ if session then
+ session:close()
+ end
+ if connection then
+ connection:close()
+ end
+ if id then
+ cache[id] = nil
+ end
+ return "execution error"
+ end
+ local data, keys
+ if result then
+ if converter then
+ data = converter.library(result)
+ else
+ keys = result:getcolnames()
+ if keys then
+ data = { }
+ local n = result:numrows() or 0
+ if n > 0 then
+ local k = #keys
+ for i=1,n do
+ local v = { result:fetch() }
+ local d = { }
+ for i=1,k do
+ d[keys[i]] = v[i]
+ end
+ data[#data+1] = d
+ end
+ end
+ end
+ end
+ result:close()
+ end
+ if not id then
+ if connection then
+ connection:close()
+ end
+ if session then
+ session:close()
+ end
+ end
+ return false, data, keys
+end
+
+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 function execute(specification)
+ if trace_sql then
+ report_state("executing library")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ local query = dataprepared(specification)
+ if not query then
+ report_state("error in preparation")
+ return
+ end
+ local data, keys = datafetched(specification,query,specification.converter)
+ if not data then
+ report_state("error in fetching")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+-- Here we build the dataset stepwise so we don't use the data hack that
+-- is used in the client variant.
+
+local wraptemplate = [[
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(result)
+ if not result then
+ return { }
+ end
+ local nofrows = result:numrows() or 0
+ if nofrows == 0 then
+ return { }
+ end
+ local target = { } -- no %s needed here
+ for i=1,nofrows do
+ local cells = { result:fetch() }
+ target[%s] = {
+ %s
+ }
+ end
+ return target
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.library = {
+ runner = function() end, -- never called
+ execute = execute,
+ initialize = initialize, -- returns session
+ usesfiles = false,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-swiglib.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-swiglib.lua
new file mode 100644
index 00000000000..af7012392b6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-swiglib.lua
@@ -0,0 +1,546 @@
+if not modules then modules = { } end modules ['util-sql-swiglib'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- As the regular library is flawed (i.e. there are crashes in the table
+-- construction code) and also not that efficient, Luigi Scarso looked into
+-- a swig binding. This is a bit more low level approach but as we stay
+-- closer to the original library it's also less dependant.
+
+local concat = table.concat
+local format, byte = string.format, string.byte
+local lpegmatch = lpeg.match
+local setmetatable, type = setmetatable, type
+local sleep = os.sleep
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","swiglib")
+
+local helpers = require("swiglib.helpers.core")
+local sql = utilities.sql
+local mysql = require("swiglib.mysql.core") -- "5.6.14"
+----- mysql = swiglib("mysql.core") -- "5.6.14"
+
+local new_u_char_array = helpers.new_u_char_array or helpers.new_ucharArray
+local ucharArray_setitem = helpers.u_char_array_setitem or helpers.ucharArray_setitem
+local int_p_assign = helpers.int_p_assign
+local ulongArray_getitem = helpers.u_long_array_getitem or helpers.ulongArray_getitem
+
+-- inspect(table.sortedkeys(mysql))
+
+local nofretries = 5
+local retrydelay = 1
+
+local cache = { }
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local querysplitter = helpers.querysplitter
+local dataprepared = helpers.preparetemplate
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+
+local mysql_initialize = mysql.mysql_init
+
+local mysql_open_connection = mysql.mysql_real_connect
+local mysql_execute_query = mysql.mysql_real_query
+local mysql_close_connection = mysql.mysql_close
+
+local mysql_field_seek = mysql.mysql_field_seek
+local mysql_num_fields = mysql.mysql_num_fields
+local mysql_fetch_field = mysql.mysql_fetch_field
+local mysql_num_rows = mysql.mysql_num_rows
+local mysql_fetch_row = mysql.mysql_fetch_row
+local mysql_fetch_lengths = mysql.mysql_fetch_lengths
+local mysql_init = mysql.mysql_init
+local mysql_store_result = mysql.mysql_store_result
+local mysql_free_result = mysql.mysql_free_result
+local mysql_use_result = mysql.mysql_use_result
+
+local mysql_error_message = mysql.mysql_error
+----- mysql_options_argument = mysql.mysql_options_argument
+
+local instance = mysql.MYSQL()
+
+local mysql_constant_false = false
+local mysql_constant_true = true
+
+----- util_getbytearray = mysql.util_getbytearray
+
+-- if mysql_options_argument then
+--
+-- mysql_constant_false = mysql_options_argument(false) -- 0 "\0"
+-- mysql_constant_true = mysql_options_argument(true) -- 1 "\1"
+--
+-- -- print(swig_type(mysql_constant_false))
+-- -- print(swig_type(mysql_constant_true))
+--
+-- mysql.mysql_options(instance,mysql.MYSQL_OPT_RECONNECT,mysql_constant_true);
+--
+-- else
+--
+-- print("")
+-- print("incomplete swiglib.mysql interface")
+-- print("")
+--
+-- end
+
+-- some helpers:
+
+function mysql.options_argument(arg)
+ local targ = type(arg)
+ if targ == "boolean" then
+ local o = new_u_char_array(1)
+ ucharArray_setitem(o,0,arg == true and 64 or 0)
+ return o
+ elseif targ == "string" then
+ local o = new_u_char_array(#arg)
+ ucharArray_setitem(o,0,0)
+ for i=1,#arg do
+ ucharArray_setitem(o,i-1,byte(arg,i))
+ end
+ return o
+ elseif targ == "number" then
+ local o = core.new_int_p()
+ int_p_assign(o, arg)
+ return o
+ else
+ return nil
+ end
+end
+
+-- function mysql.util_unpackbytearray(row,noffields,len)
+-- if row == nil then
+-- return { }
+-- elseif noffields < 1 then
+-- return { }
+-- else
+-- local t = { }
+-- for i=0,noffields-1 do
+-- local l = ulongArray_getitem(len,i) -- zero based ... element from len array
+-- local r = util_getbytearray(row,i,l) -- zero based ... element from len array
+-- t[#t+1]= r
+-- end
+-- return t
+-- end
+-- end
+
+--
+
+local typemap = mysql.MYSQL_TYPE_VAR_STRING and {
+ [mysql.MYSQL_TYPE_VAR_STRING ] = "string",
+ [mysql.MYSQL_TYPE_STRING ] = "string",
+ [mysql.MYSQL_TYPE_DECIMAL ] = "number",
+ [mysql.MYSQL_TYPE_SHORT ] = "number",
+ [mysql.MYSQL_TYPE_LONG ] = "number",
+ [mysql.MYSQL_TYPE_FLOAT ] = "number",
+ [mysql.MYSQL_TYPE_DOUBLE ] = "number",
+ [mysql.MYSQL_TYPE_LONGLONG ] = "number",
+ [mysql.MYSQL_TYPE_INT24 ] = "number",
+ [mysql.MYSQL_TYPE_YEAR ] = "number",
+ [mysql.MYSQL_TYPE_TINY ] = "number",
+ [mysql.MYSQL_TYPE_TINY_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_MEDIUM_BLOB] = "binary",
+ [mysql.MYSQL_TYPE_LONG_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_DATE ] = "date",
+ [mysql.MYSQL_TYPE_NEWDATE ] = "date",
+ [mysql.MYSQL_TYPE_DATETIME ] = "datetime",
+ [mysql.MYSQL_TYPE_TIME ] = "time",
+ [mysql.MYSQL_TYPE_TIMESTAMP ] = "time",
+ [mysql.MYSQL_TYPE_ENUM ] = "set",
+ [mysql.MYSQL_TYPE_SET ] = "set",
+ [mysql.MYSQL_TYPE_NULL ] = "null",
+}
+
+-- real_escape_string
+
+local function finish(t)
+ local r = t._result_
+ if r then
+ mysql_free_result(r)
+ end
+end
+
+-- will become metatable magic
+
+-- local function analyze(result)
+-- mysql_field_seek(result,0)
+-- local nofrows = mysql_num_rows(result) or 0
+-- local noffields = mysql_num_fields(result)
+-- local names = { }
+-- local types = { }
+-- for i=1,noffields do
+-- local field = mysql_fetch_field(result)
+-- names[i] = field.name
+-- types[i] = field.type
+-- end
+-- return names, types, noffields, nofrows
+-- end
+
+local function getcolnames(t)
+ return t.names
+end
+
+local function getcoltypes(t)
+ return t.types
+end
+
+local function numrows(t)
+ return t.nofrows
+end
+
+local fetch_fields_from_current_row = mysql.util_mysql_fetch_fields_from_current_row
+local fetch_all_rows = mysql.util_mysql_fetch_all_rows
+
+-- swig_type
+
+-- local function list(t)
+-- local result = t._result_
+-- local row = mysql_fetch_row(result)
+-- local len = mysql_fetch_lengths(result)
+-- local result = { }
+-- for i=1,t.noffields do
+-- local r = i - 1 -- zero offset
+-- result[i] = util_getbytearray(row,r,ulongArray_getitem(len,r))
+-- end
+-- return result
+-- end
+
+-- local function hash(t)
+-- local list = fetch_fields_from_current_row(t._result_)
+-- local result = t._result_
+-- local fields = t.names
+-- local row = mysql_fetch_row(result)
+-- local len = mysql_fetch_lengths(result)
+-- local result = { }
+-- for i=1,t.noffields do
+-- local r = i - 1 -- zero offset
+-- result[fields[i]] = util_getbytearray(row,r,ulongArray_getitem(len,r))
+-- end
+-- return result
+-- end
+
+local function list(t)
+ return fetch_fields_from_current_row(t._result_)
+end
+
+local function hash(t)
+ local list = fetch_fields_from_current_row(t._result_)
+ local fields = t.names
+ local data = { }
+ for i=1,t.noffields do
+ data[fields[i]] = list[i]
+ end
+ return data
+end
+
+local function wholelist(t)
+ return 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 nt = setmetatable({},mt)
+
+-- session
+
+local function close(t)
+ mysql_close_connection(t._connection_)
+end
+
+local function execute(t,query)
+ if query and query ~= "" then
+ local connection = t._connection_
+ local result = mysql_execute_query(connection,query,#query)
+ if result == 0 then
+ local result = mysql_store_result(connection)
+ if result then
+ mysql_field_seek(result,0)
+ local nofrows = mysql_num_rows(result) or 0
+ local noffields = mysql_num_fields(result)
+ local names = { }
+ local types = { }
+ for i=1,noffields do
+ local field = mysql_fetch_field(result)
+ names[i] = field.name
+ types[i] = field.type
+ end
+ local t = {
+ _result_ = result,
+ names = names,
+ types = types,
+ noffields = noffields,
+ nofrows = nofrows,
+ }
+ return setmetatable(t,mt)
+ else
+ return nt
+ end
+ end
+ end
+ return false
+end
+
+local mt = { __index = {
+ close = close,
+ execute = execute,
+ }
+}
+
+local function open(t,database,username,password,host,port)
+ local connection = mysql_open_connection(t._session_,host or "localhost",username or "",password or "",database or "",port or 0,0,0)
+ if connection then
+ local t = {
+ _connection_ = connection,
+ }
+ return setmetatable(t,mt)
+ end
+end
+
+local function message(t)
+ return mysql_error_message(t._session_)
+end
+
+local function close(t)
+ -- dummy, as we have a global session
+end
+
+local mt = {
+ __index = {
+ connect = open,
+ close = close,
+ message = message,
+ }
+}
+
+local function initialize()
+ local session = {
+ _session_ = mysql_initialize(instance) -- maybe share, single thread anyway
+ }
+ return setmetatable(session,mt)
+end
+
+-- -- -- --
+
+local function connect(session,specification)
+ return session:connect(
+ specification.database or "",
+ specification.username or "",
+ specification.password or "",
+ specification.host or "",
+ specification.port
+ )
+end
+
+local function error_in_connection(specification,action)
+ report_state("error in connection: [%s] %s@%s to %s:%s",
+ action or "unknown",
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+end
+
+local function datafetched(specification,query,converter)
+ if not query or query == "" then
+ report_state("no valid query")
+ return { }, { }
+ end
+ local id = specification.id
+ local session, connection
+ if id then
+ local c = cache[id]
+ if c then
+ session = c.session
+ connection = c.connection
+ end
+ if not connection then
+ session = initialize()
+ connection = connect(session,specification)
+ 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
+ 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
+ end
+ end
+ end
+ end
+ if not connection then
+ report_state("error in connection: %s@%s to %s:%s",
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+ return { }, { }
+ end
+ query = lpegmatch(querysplitter,query)
+ local result, message, okay
+ for i=1,#query do
+ local q = query[i]
+ local r, m = connection:execute(q)
+ if m then
+ report_state("error in query, stage: %s",string.collapsespaces(q))
+ message = message and format("%s\n%s",message,m) or m
+ end
+ if type(r) == "table" then
+ result = r
+ okay = true
+ elseif not m then
+ okay = true
+ end
+ end
+ local data, keys
+ if result then
+ if converter then
+ data = converter.swiglib(result)
+ else
+ keys = result.names
+ data = { }
+ for i=1,result.nofrows do
+ data[i] = result:hash()
+ end
+ end
+ result:finish() -- result:close()
+ elseif message then
+ report_state("message %s",message)
+ end
+ if not keys then
+ keys = { }
+ end
+ if not data then
+ data = { }
+ end
+ if not id then
+ connection:close()
+ session:close()
+ end
+ return data, keys
+end
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing library")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ local query = dataprepared(specification)
+ if not query then
+ report_state("error in preparation")
+ return
+ end
+ local data, keys = datafetched(specification,query,specification.converter)
+ if not data then
+ report_state("error in fetching")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+local wraptemplate = [[
+local mysql = require("swiglib.mysql.core") -- will be stored in method
+
+local fetch_fields = mysql.util_mysql_fetch_fields_from_current_row
+
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(result)
+ if not result then
+ return { }
+ end
+ local nofrows = result.nofrows or 0
+ if nofrows == 0 then
+ return { }
+ end
+ local noffields = result.noffields or 0
+ local target = { } -- no %s needed here
+ result = result._result_
+ for i=1,nofrows do
+ local cells = fetch_fields(result)
+ target[%s] = {
+ %s
+ }
+ end
+ return target
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.swiglib = {
+ runner = function() end, -- never called
+ execute = execute,
+ initialize = initialize, -- returns session
+ usesfiles = false,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-loggers.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-loggers.lua
new file mode 100644
index 00000000000..ceb1ff75cfa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-loggers.lua
@@ -0,0 +1,277 @@
+if not modules then modules = { } end modules ['util-sql-loggers'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+local tonumber = tonumber
+local format = string.format
+local concat = table.concat
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+
+local sql = utilities.sql
+local loggers = { }
+sql.loggers = loggers
+
+local trace_sql = false trackers.register("sql.loggers.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","loggers")
+
+loggers.newtoken = sql.tokens.new
+local makeconverter = sql.makeconverter
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "loggers")
+end
+
+loggers.usedb = checkeddb
+
+local totype = {
+ ["error"] = 1, [1] = 1, ["1"] = 1,
+ ["warning"] = 2, [2] = 2, ["2"] = 2,
+ ["debug"] = 3, [3] = 3, ["3"] = 3,
+ ["info"] = 4, [4] = 4, ["4"] = 4,
+}
+
+local fromtype = {
+ ["error"] = "error", [1] = "error", ["1"] = "error",
+ ["warning"] = "warning", [2] = "warning", ["2"] = "warning",
+ ["debug"] = "debug", [3] = "debug", ["3"] = "debug",
+ ["info"] = "info", [4] = "info", ["4"] = "info",
+}
+
+table.setmetatableindex(totype, function() return 4 end)
+table.setmetatableindex(fromtype,function() return "info" end)
+
+loggers.totype = totype
+loggers.fromtype = fromtype
+
+local template = [[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `time` int(11) NOT NULL,
+ `type` int(11) NOT NULL,
+ `action` varchar(15) NOT NULL,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `id_unique_key` (`id`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function loggers.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a created in %a",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function loggers.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a removed in %a",db.name,db.base)
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ ) VALUES (
+ %time%,
+ %type%,
+ '%action%',
+ '%[data]%'
+ ) ;
+]]
+
+function loggers.save(db,data) -- beware, we pass type and action in the data (saves a table)
+
+ if data then
+
+ local time = ostime()
+ local kind = totype[data.type]
+ local action = data.action or "unknown"
+
+ data.type = nil
+ data.action = nil
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ time = ostime(),
+ type = kind,
+ action = action,
+ data = data and db.serialize(data,"return") or "",
+ },
+ }
+
+ end
+
+end
+
+-- local template =[[
+-- REMOVE FROM
+-- %basename%
+-- WHERE
+-- `token` = '%token%' ;
+-- ]]
+--
+-- function loggers.remove(db,token)
+--
+-- db.execute {
+-- template = template,
+-- variables = {
+-- basename = db.basename,
+-- token = token,
+-- },
+-- }
+--
+-- if trace_sql then
+-- report("removed: %s",token)
+-- end
+--
+-- end
+
+local template_nop =[[
+ SELECT
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ FROM
+ %basename%
+ ORDER BY
+ `time`, `type`, `action`
+ DESC LIMIT
+ %limit% ;
+]]
+
+local template_yes =[[
+ SELECT
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ FROM
+ %basename%
+ %WHERE%
+ ORDER BY
+ `time`, `type`, `action`
+ DESC LIMIT
+ %limit% ;
+]]
+
+local converter = makeconverter {
+ -- { name = "time", type = os.localtime },
+ { name = "time", type = "number" },
+ { name = "type", type = fromtype },
+ { name = "action", type = "string" },
+ { name = "data", type = "deserialize" },
+}
+
+function loggers.collect(db,specification)
+
+ specification = specification or { }
+
+ local start = specification.start
+ local stop = specification.stop
+ local limit = specification.limit or 100
+ local kind = specification.type
+ local action = specification.action
+
+ local filtered = start or stop
+
+ local where = { }
+
+ if filtered then
+ local today = os.date("*t")
+
+ if type(start) ~= "table" then
+ start = { }
+ end
+ start = os.time {
+ day = start.day or today.day,
+ month = start.month or today.month,
+ year = start.year or today.year,
+ hour = start.hour or 0,
+ minute = start.minute or 0,
+ second = start.second or 0,
+ isdst = true,
+ }
+
+ if type(stop) ~= "table" then
+ stop = { }
+ end
+ stop = os.time {
+ day = stop.day or today.day,
+ month = stop.month or today.month,
+ year = stop.year or today.year,
+ hour = stop.hour or 24,
+ minute = stop.minute or 0,
+ second = stop.second or 0,
+ isdst = true,
+ }
+
+ -- report("filter: %s => %s",start,stop)
+
+ where[#where+1] = format("`time` BETWEEN %s AND %s",start,stop)
+
+ end
+
+ if kind then
+ where[#where+1] = format("`type` = %s",totype[kind])
+ end
+
+ if action then
+ where[#where+1] = format("`action` = '%s'",action)
+ end
+
+ local records = db.execute {
+ template = filtered and template_yes or template_nop,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ limit = limit,
+ WHERE = #where > 0 and format("WHERE\n%s",concat(where," AND ")) or "",
+ },
+ }
+
+ if trace_sql then
+ report("collected: %s loggers",#records)
+ end
+
+ return records, keys
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-sessions.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-sessions.lua
new file mode 100644
index 00000000000..76bb91962fa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-sessions.lua
@@ -0,0 +1,349 @@
+if not modules then modules = { } end modules ['util-sql-sessions'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+-- maybe store threshold in session (in seconds)
+
+local tonumber = tonumber
+local format = string.format
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+
+-- In older frameworks we kept a session table in memory. This time we
+-- follow a route where we store session data in a sql table. Each session
+-- has a token (similar to what we do on q2p and pod services), a data
+-- blob which is just a serialized lua table (we could consider a dump instead)
+-- and two times: the creation and last accessed time. The first one is handy
+-- for statistics and the second one for cleanup. Both are just numbers so that
+-- we don't have to waste code on conversions. Anyhow, we provide variants so that
+-- we can always choose what is best.
+
+local sql = utilities.sql
+local sessions = { }
+sql.sessions = sessions
+
+local trace_sql = false trackers.register("sql.sessions.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","sessions")
+
+sessions.newtoken = sql.tokens.new
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "sessions")
+end
+
+sessions.usedb = checkeddb
+
+local template =[[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `token` varchar(50) NOT NULL,
+ `data` longtext NOT NULL,
+ `created` int(11) NOT NULL,
+ `accessed` int(11) NOT NULL,
+ UNIQUE KEY `token_unique_key` (`token`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function sessions.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a created in %a",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function sessions.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a removed in %a",db.name,db.base)
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `token`,
+ `created`,
+ `accessed`,
+ `data`
+ ) VALUES (
+ '%token%',
+ %time%,
+ %time%,
+ '%[data]%'
+ ) ;
+]]
+
+function sessions.create(db,data)
+
+ local token = sessions.newtoken()
+ local time = ostime()
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = time,
+ data = db.serialize(data or { },"return")
+ },
+ }
+
+ if trace_sql then
+ report("created: %s at %s",token,osfulltime(time))
+ end
+
+ return {
+ token = token,
+ created = time,
+ accessed = time,
+ data = data,
+ }
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `data` = '%[data]%',
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.save(db,session)
+
+ local time = ostime()
+ local data = db.serialize(session.data or { },"return")
+ local token = session.token
+
+ session.accessed = time
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ data = data,
+ },
+ }
+
+ if trace_sql then
+ report("saved: %s at %s",token,osfulltime(time))
+ end
+
+ return session
+end
+
+local template = [[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.touch(db,token)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ },
+ }
+
+end
+
+local template = [[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.restore(db,token)
+
+ local records, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ },
+ }
+
+ local record = records and records[1]
+
+ if record then
+ if trace_sql then
+ report("restored: %s",token)
+ end
+ record.data = db.deserialize(record.data or "")
+ return record, keys
+ elseif trace_sql then
+ report("unknown: %s",token)
+ end
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.remove(db,token)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ if trace_sql then
+ report("removed: %s",token)
+ end
+
+end
+
+local template_collect_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+local template_collect_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+function sessions.collect(db,nodata)
+
+ local records, keys = db.execute {
+ template = nodata and template_collect_nop or template_collect_yes,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("collected: %s sessions",#records)
+ end
+
+ return records, keys
+
+end
+
+local template_cleanup_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% ;
+]]
+
+local template_cleanup_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% ;
+]]
+
+function sessions.cleanupdb(db,delta,nodata)
+
+ local time = ostime()
+
+ local records, keys = db.execute {
+ template = nodata and template_cleanup_nop or template_cleanup_yes,
+ variables = {
+ basename = db.basename,
+ time = time - delta
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("cleaned: %s seconds before %s",delta,osfulltime(time))
+ end
+
+ return records, keys
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-tickets.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-tickets.lua
new file mode 100644
index 00000000000..5e958299deb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-tickets.lua
@@ -0,0 +1,772 @@
+if not modules then modules = { } end modules ['util-sql-tickets'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- TODO: MAKE SOME INTO STORED PROCUDURES
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to distribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+local tonumber = tonumber
+local format = string.format
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+local concat = table.concat
+
+local sql = utilities.sql
+local tickets = { }
+sql.tickets = tickets
+
+local trace_sql = false trackers.register("sql.tickets.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","tickets")
+
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+local execute = sql.execute
+
+tickets.newtoken = sql.tokens.new
+
+-- Beware as an index can be a string or a number, we will create
+-- a combination of hash and index.
+
+local statustags = { [0] =
+ "unknown",
+ "pending",
+ "busy",
+ "finished",
+ "dependent", -- same token but different subtoken (so we only need to find the first)
+ "reserved-1",
+ "reserved-2",
+ "error",
+ "deleted",
+}
+
+local status = table.swapped(statustags)
+tickets.status = status
+tickets.statustags = statustags
+
+local s_unknown = status.unknown
+local s_pending = status.pending
+local s_busy = status.busy
+local s_finished = status.finished
+local s_dependent = status.dependent
+local s_error = status.error
+local s_deleted = status.deleted
+
+local s_rubish = s_error -- and higher
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "tickets")
+end
+
+tickets.usedb = checkeddb
+
+local template =[[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `token` varchar(50) NOT NULL,
+ `subtoken` INT(11) NOT NULL,
+ `created` int(11) NOT NULL,
+ `accessed` int(11) NOT NULL,
+ `category` int(11) NOT NULL,
+ `status` int(11) NOT NULL,
+ `usertoken` varchar(50) NOT NULL,
+ `data` longtext NOT NULL,
+ `comment` longtext NOT NULL,
+
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `id_unique_index` (`id` ASC),
+ KEY `token_unique_key` (`token`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function tickets.createdb(presets,datatable)
+ local db = checkeddb(presets,datatable)
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a created in %a",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function tickets.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a removed in %a",db.name,db.base)
+
+end
+
+local template_push =[[
+ INSERT INTO %basename% (
+ `token`,
+ `subtoken`,
+ `created`,
+ `accessed`,
+ `status`,
+ `category`,
+ `usertoken`,
+ `data`,
+ `comment`
+ ) VALUES (
+ '%token%',
+ %subtoken%,
+ %time%,
+ %time%,
+ %status%,
+ %category%,
+ '%usertoken%',
+ '%[data]%',
+ '%[comment]%'
+ ) ;
+]]
+
+local template_fetch =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%'
+ AND
+ `subtoken` = '%subtoken%'
+ ;
+]]
+
+function tickets.create(db,ticket)
+
+ -- We assume a unique token .. if not we're toast anyway. We used to lock and
+ -- get the last id etc etc but there is no real need for that.
+
+ -- we could check for dependent here but we don't want the lookup
+
+ local token = ticket.token or tickets.newtoken()
+ local time = ostime()
+ local status = ticket.status
+ local category = ticket.category or 0
+ local subtoken = ticket.subtoken or 0
+ local usertoken = ticket.usertoken or ""
+ local comment = ticket.comment or ""
+
+ status = not status and subtoken > 1 and s_dependent or s_pending
+
+ local result, message = db.execute {
+ template = template_push,
+ variables = {
+ basename = db.basename,
+ token = token,
+ subtoken = subtoken,
+ time = time,
+ status = status,
+ category = category,
+ usertoken = usertoken,
+ data = db.serialize(ticket.data or { },"return"),
+ comment = comment,
+ },
+ }
+
+ -- We could stick to only fetching the id and make the table here
+ -- but we're not pushing that many tickets so we can as well follow
+ -- the lazy approach and fetch the whole.
+
+ local result, message = db.execute {
+ template = template_fetch,
+ variables = {
+ basename = db.basename,
+ token = token,
+ subtoken = subtoken,
+ },
+ }
+
+ if result and #result > 0 then
+ if trace_sql then
+ report("created: %s at %s",token,osfulltime(time))
+ end
+ return result[1]
+ else
+ report("failed: %s at %s",token,osfulltime(time))
+ end
+
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `data` = '%[data]%',
+ `status` = %status%,
+ `accessed` = %time%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.save(db,ticket)
+
+ local time = ostime()
+ local data = db.serialize(ticket.data or { },"return")
+ local status = ticket.status or s_error
+
+-- print("SETTING")
+-- inspect(data)
+
+ ticket.status = status
+ ticket.accessed = time
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = ticket.id,
+ time = ostime(),
+ status = status,
+ data = data,
+ },
+ }
+
+ if trace_sql then
+ report("saved: id %s, time %s",id,osfulltime(time))
+ end
+
+ return ticket
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.restore(db,id)
+
+ local record, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ time = ostime(),
+ },
+ }
+
+ local record = record and record[1]
+
+ if record then
+ if trace_sql then
+ report("restored: id %s",id)
+ end
+ record.data = db.deserialize(record.data or "")
+ return record
+ elseif trace_sql then
+ report("unknown: id %s",id)
+ end
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.remove(db,id)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ },
+ }
+
+ if trace_sql then
+ report("removed: id %s",id)
+ end
+
+end
+
+local template_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ ORDER BY
+ `id` ;
+]]
+
+local template_nop =[[
+ SELECT
+ `created`,
+ `usertoken`,
+ `accessed`,
+ `status`
+ FROM
+ %basename%
+ ORDER BY
+ `id` ;
+]]
+
+function tickets.collect(db,nodata)
+
+ local records, keys = db.execute {
+ template = nodata and template_nop or template_yes,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("collected: %s tickets",#records)
+ end
+
+ return records, keys
+
+end
+
+-- We aleays keep the last select in the execute so one can have
+-- an update afterwards.
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% OR `status` >= %rubish% ;
+]]
+
+local template_cleanup_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `id` ;
+]] .. template
+
+local template_cleanup_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ `usertoken`
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `id` ;
+]] .. template
+
+function tickets.cleanupdb(db,delta,nodata) -- maybe delta in db
+
+ local time = delta and (ostime() - delta) or 0
+
+ local records, keys = db.execute {
+ template = nodata and template_cleanup_nop or template_cleanup_yes,
+ variables = {
+ basename = db.basename,
+ time = time,
+ rubish = s_rubish,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("cleaned: %s seconds before %s",delta,osfulltime(time))
+ end
+
+ return records, keys
+
+end
+
+-- status related functions
+
+local template =[[
+ SELECT
+ `status`
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%'
+ ORDER BY
+ `id`
+ ;
+]]
+
+function tickets.getstatus(db,token)
+
+ local record, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ local record = record and record[1]
+
+ return record and record.status or s_unknown
+
+end
+
+local template =[[
+ SELECT
+ `status`
+ FROM
+ %basename%
+ WHERE
+ `status` >= %rubish% OR `accessed` < %time%
+ ORDER BY
+ `id`
+ ;
+]]
+
+function tickets.getobsolete(db,delta)
+
+ local time = delta and (ostime() - delta) or 0
+
+ local records = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ time = time,
+ rubish = s_rubish,
+ },
+ }
+
+ db.unpackdata(records)
+
+ return records
+
+end
+
+local template =[[
+ SELECT
+ `id`
+ FROM
+ %basename%
+ WHERE
+ `status` = %status%
+ LIMIT
+ 1 ;
+]]
+
+function tickets.hasstatus(db,status)
+
+ local records = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ status = status or s_unknown,
+ },
+ }
+
+ return records and #records > 0 or false
+
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `status` = %status%,
+ `accessed` = %time%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.setstatus(db,id,status)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ time = ostime(),
+ status = status or s_error,
+ },
+ }
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `status` IN (%status%) ;
+]]
+
+function tickets.prunedb(db,status)
+
+ if type(status) == "table" then
+ status = concat(status,",")
+ end
+
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ status = status or s_unknown,
+ },
+ }
+
+ if trace_sql then
+ report("pruned: status %s removed",status)
+ end
+
+end
+
+-- START TRANSACTION ; ... COMMIT ;
+-- LOCK TABLES %basename% WRITE ; ... UNLOCK TABLES ;
+
+local template_a = [[
+ SET
+ @last_ticket_token = '' ;
+ UPDATE
+ %basename%
+ SET
+ `token` = (@last_ticket_token := `token`),
+ `status` = %newstatus%,
+ `accessed` = %time%
+ WHERE
+ `status` = %status%
+ ORDER BY
+ `id`
+ LIMIT
+ 1
+ ;
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = @last_ticket_token
+ ORDER BY
+ `id`
+ ;
+]]
+
+local template_b = [[
+ SELECT
+ *
+ FROM
+ tickets
+ WHERE
+ `status` = %status%
+ ORDER BY
+ `id`
+ LIMIT
+ 1
+ ;
+]]
+
+function tickets.getfirstwithstatus(db,status,newstatus)
+
+ local records
+
+ if type(newstatus) == "number" then -- todo: also accept string
+
+ records = db.execute {
+ template = template_a,
+ variables = {
+ basename = db.basename,
+ status = status or s_pending,
+ newstatus = newstatus,
+ time = ostime(),
+ },
+ }
+
+
+ else
+
+ records = db.execute {
+ template = template_b,
+ variables = {
+ basename = db.basename,
+ status = status or s_pending,
+ },
+ }
+
+ end
+
+ if type(records) == "table" and #records > 0 then
+
+ for i=1,#records do
+ local record = records[i]
+ record.data = db.deserialize(record.data or "")
+ record.status = newstatus or s_busy
+ end
+
+ return records
+
+ end
+end
+
+-- The next getter assumes that we have a sheduler running so that there is
+-- one process in charge of changing the status.
+
+local template = [[
+ SET
+ @last_ticket_token = '' ;
+ UPDATE
+ %basename%
+ SET
+ `token` = (@last_ticket_token := `token`),
+ `status` = %newstatus%,
+ `accessed` = %time%
+ WHERE
+ `status` = %status%
+ ORDER BY
+ `id`
+ LIMIT
+ 1
+ ;
+ SELECT
+ @last_ticket_token AS `token`
+ ;
+]]
+
+function tickets.getfirstinqueue(db,status,newstatus)
+
+ local records = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ status = status or s_pending,
+ newstatus = newstatus or s_busy,
+ time = ostime(),
+ },
+ }
+
+ local token = type(records) == "table" and #records > 0 and records[1].token
+
+ return token ~= "" and token
+
+end
+
+local template =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%'
+ ORDER BY
+ `id` ;
+]]
+
+function tickets.getticketsbytoken(db,token)
+
+ local records, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ db.unpackdata(records)
+
+ return records
+
+end
+
+local template =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `usertoken` = '%usertoken%' AND `status` < %rubish%
+ ORDER BY
+ `id` ;
+]]
+
+function tickets.getusertickets(db,usertoken)
+
+ -- todo: update accessed
+ -- todo: get less fields
+ -- maybe only data for status changed (hard to check)
+
+ local records, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ usertoken = usertoken,
+ rubish = s_rubish,
+ },
+ }
+
+ db.unpackdata(records)
+
+ return records
+
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `status` = %deleted%
+ WHERE
+ `usertoken` = '%usertoken%' ;
+]]
+
+function tickets.removeusertickets(db,usertoken)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ usertoken = usertoken,
+ deleted = s_deleted,
+ },
+ }
+
+ if trace_sql then
+ report("removed: usertoken %s",usertoken)
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-tracers.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-tracers.lua
new file mode 100644
index 00000000000..44e32d256c6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-tracers.lua
@@ -0,0 +1,71 @@
+if not modules then modules = { } end modules ['util-sql-tracers'] = {
+ version = 1.001,
+ comment = "companion to m-sql.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local sql = utilities.sql
+local tracers = { }
+sql.tracers = tracers
+
+sql.setmethod("swiglib")
+
+local gsub, lower = string.gsub, string.lower
+
+local t_names = {
+ mysql = [[SHOW TABLES FROM `%database%`]],
+ mssql = [[SELECT table_name FROM %database%.information_schema.tables;]],
+ mssql = [[SELECT "name" FROM "%database%"."sys"."databases" ORDER BY "name";]],
+ mssql = [[SELECT name FROM "%database%"."sys"."objects" WHERE "type" IN ('P', 'U', 'V', 'TR', 'FN', 'TF');]],
+}
+
+local t_fields = {
+ mysql = [[SHOW FIELDS FROM `%database%`.`%table%` ]],
+ mssql = [[SELECT column_name "field", data_type "type", column_default "default", is_nullable "null" FROM %database%.information_schema.columns WHERE table_name='%table%']],
+}
+
+function sql.tracers.gettables(presets)
+ local servertype = sql.getserver()
+
+ local results, keys = sql.execute {
+ presets = presets,
+ template = t_names[servertype],
+ variables = {
+ database = presets.database,
+ },
+ }
+
+ local key = keys and keys[1]
+ local tables = { }
+
+ if keys then
+ for i=1,#results do
+ local name = results[i][key]
+ local results, keys = sql.execute {
+ presets = presets,
+ template = t_fields[servertype],
+ variables = {
+ database = presets.database,
+ table = name
+ },
+ }
+ if #results > 0 then
+ for i=1,#results do
+ local result = table.loweredkeys(results[i])
+ -- ms cleanup
+ result.default = gsub(result.default,"^[%(']+(.-)[%)']+$","%1")
+ result.null = lower(result.null)
+ --
+ results[i] = result
+ end
+ tables[name] = results
+ else
+ -- a view
+ end
+ end
+ end
+
+ return tables
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua
new file mode 100644
index 00000000000..a1f4339461c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua
@@ -0,0 +1,410 @@
+if not modules then modules = { } end modules ['util-sql-users'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+-- local sql = sql or (utilities and utilities.sql) or require("util-sql")
+-- local md5 = md5 or require("md5")
+
+local sql = utilities.sql
+
+local format, upper, find, gsub, topattern = string.format, string.upper, string.find, string.gsub, string.topattern
+local sumhexa = md5.sumhexa
+local toboolean = string.toboolean
+
+local sql = utilities.sql
+local users = { }
+sql.users = users
+
+local trace_sql = false trackers.register("sql.users.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","users")
+
+local function encryptpassword(str)
+ if not str or str == "" then
+ return ""
+ elseif find(str,"^MD5:") then
+ return str
+ else
+ return upper(format("MD5:%s",sumhexa(str)))
+ end
+end
+
+local function cleanuppassword(str)
+ return (gsub(str,"^MD5:",""))
+end
+
+local function samepasswords(one,two)
+ if not one or not two then
+ return false
+ end
+ if not find(one,"^MD5:") then
+ one = encryptpassword(one)
+ end
+ if not find(two,"^MD5:") then
+ two = encryptpassword(two)
+ end
+ return one == two
+end
+
+local function validaddress(address,addresses)
+ if address and addresses and address ~= "" and addresses ~= "" then
+ if find(address,topattern(addresses,true,true)) then
+ return true, "valid remote address"
+ end
+ return false, "invalid remote address"
+ else
+ return true, "no remote address check"
+ end
+end
+
+
+users.encryptpassword = encryptpassword
+users.cleanuppassword = cleanuppassword
+users.samepasswords = samepasswords
+users.validaddress = validaddress
+
+-- print(users.encryptpassword("test")) -- MD5:098F6BCD4621D373CADE4E832627B4F6
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "users")
+end
+
+users.usedb = checkeddb
+
+local groupnames = { }
+local groupnumbers = { }
+
+local function registergroup(name)
+ local n = #groupnames + 1
+ groupnames [n] = name
+ groupnames [tostring(n)] = name
+ groupnames [name] = name
+ groupnumbers[n] = n
+ groupnumbers[tostring(n)] = n
+ groupnumbers[name] = n
+ return n
+end
+
+registergroup("superuser")
+registergroup("administrator")
+registergroup("user")
+registergroup("guest")
+
+users.groupnames = groupnames
+users.groupnumbers = groupnumbers
+
+-- password 'test':
+--
+-- INSERT insert into users (`name`,`password`,`group`,`enabled`) values ('...','MD5:098F6BCD4621D373CADE4E832627B4F6',1,1) ;
+
+local template =[[
+ CREATE TABLE `users` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(80) NOT NULL,
+ `fullname` varchar(80) NOT NULL,
+ `password` varchar(50) DEFAULT NULL,
+ `group` int(11) NOT NULL,
+ `enabled` int(11) DEFAULT '1',
+ `email` varchar(80) DEFAULT NULL,
+ `address` varchar(256) DEFAULT NULL,
+ `theme` varchar(50) DEFAULT NULL,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name_unique` (`name`)
+ ) DEFAULT CHARSET = utf8 ;
+]]
+
+local converter, fields = sql.makeconverter {
+ { name = "id", type = "number" },
+ { name = "name", type = "string" },
+ { name = "fullname", type = "string" },
+ { name = "password", type = "string" },
+ { name = "group", type = groupnames },
+ { name = "enabled", type = "boolean" },
+ { name = "email", type = "string" },
+ { name = "address", type = "string" },
+ { name = "theme", type = "string" },
+ { name = "data", type = "deserialize" },
+}
+
+function users.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %a created in %a",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%[name]%'
+ AND
+ `password` = '%[password]%'
+ ;
+]]
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%[name]%'
+ ;
+]]
+
+function users.valid(db,username,password,address)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ name = username,
+ },
+ }
+
+ local data = data and data[1]
+
+ if not data then
+ return false, "unknown user"
+ elseif not data.enabled then
+ return false, "disabled user"
+ elseif data.password ~= encryptpassword(password) then
+ return false, "wrong password"
+ elseif not validaddress(address,data.address) then
+ return false, "invalid address"
+ else
+ data.password = nil
+ return data, "okay"
+ end
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `name`,
+ `fullname`,
+ `password`,
+ `group`,
+ `enabled`,
+ `email`,
+ `address`,
+ `theme`,
+ `data`
+ ) VALUES (
+ '%[name]%',
+ '%[fullname]%',
+ '%[password]%',
+ '%[group]%',
+ '%[enabled]%',
+ '%[email]%',
+ '%[address]%',
+ '%[theme]%',
+ '%[data]%'
+ ) ;
+]]
+
+function users.add(db,specification)
+
+ local name = specification.username or specification.name
+
+ if not name or name == "" then
+ return
+ end
+
+ local data = specification.data
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ name = name,
+ fullname = name or fullname,
+ password = encryptpassword(specification.password or ""),
+ group = groupnumbers[specification.group] or groupnumbers.guest,
+ enabled = toboolean(specification.enabled) and "1" or "0",
+ email = specification.email,
+ address = specification.address,
+ theme = specification.theme,
+ data = type(data) == "table" and db.serialize(data,"return") or "",
+ },
+ }
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%[name]%' ;
+]]
+
+function users.getbyname(db,name)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ name = name,
+ },
+ }
+
+ return data and data[1] or nil
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `id` = '%id%' ;
+]]
+
+local function getbyid(db,id)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ id = id,
+ },
+ }
+
+ return data and data[1] or nil
+
+end
+
+users.getbyid = getbyid
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `fullname` = '%[fullname]%',
+ `password` = '%[password]%',
+ `group` = '%[group]%',
+ `enabled` = '%[enabled]%',
+ `email` = '%[email]%',
+ `address` = '%[address]%',
+ `theme` = '%[theme]%',
+ `data` = '%[data]%'
+ WHERE
+ `id` = '%id%'
+ ;
+]]
+
+function users.save(db,id,specification)
+
+ id = tonumber(id)
+
+ if not id then
+ return
+ end
+
+ local user = getbyid(db,id)
+
+ if tonumber(user.id) ~= id then
+ return
+ end
+
+ local fullname = specification.fullname == nil and user.fulname or specification.fullname
+ local password = specification.password == nil and user.password or specification.password
+ local group = specification.group == nil and user.group or specification.group
+ local enabled = specification.enabled == nil and user.enabled or specification.enabled
+ local email = specification.email == nil and user.email or specification.email
+ local address = specification.address == nil and user.address or specification.address
+ local theme = specification.theme == nil and user.theme or specification.theme
+ local data = specification.data == nil and user.data or specification.data
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ fullname = fullname,
+ password = encryptpassword(password),
+ group = groupnumbers[group],
+ enabled = toboolean(enabled) and "1" or "0",
+ email = email,
+ address = address,
+ theme = theme,
+ data = type(data) == "table" and db.serialize(data,"return") or "",
+ },
+ }
+
+ return getbyid(db,id)
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `id` = '%id%' ;
+]]
+
+function users.remove(db,id)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ },
+ }
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ ORDER BY
+ `name` ;
+]]
+
+function users.collect(db) -- maybe also an id/name only variant
+
+ local records, keys = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ },
+ }
+
+ return records, keys
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua
new file mode 100644
index 00000000000..84cbb1692bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua
@@ -0,0 +1,457 @@
+if not modules then modules = { } end modules ['util-sql'] = {
+ version = 1.001,
+ comment = "companion to m-sql.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: templates as table (saves splitting)
+
+-- Of course we could use a library but we don't want another depedency and there is
+-- a bit of flux in these libraries. Also, we want the data back in a way that we
+-- like.
+--
+-- This is the first of set of sql related modules that are providing functionality
+-- for a web based framework that we use for typesetting (related) services. We're
+-- talking of session management, job ticket processing, storage, (xml) file processing
+-- and dealing with data from databases (often ambitiously called database publishing).
+--
+-- There is no generic solution for such services, but from our perspective, as we use
+-- context in a regular tds tree (the standard distribution) it makes sense to put shared
+-- code in the context distribution. That way we don't need to reinvent wheels every time.
+
+-- We use the template mechanism from util-tpl which inturn is just using the dos cq
+-- windows convention of %whatever% variables that I've used for ages.
+
+-- util-sql-imp-client.lua
+-- util-sql-imp-library.lua
+-- util-sql-imp-swiglib.lua
+-- util-sql-imp-lmxsql.lua
+
+-- local sql = require("util-sql")
+--
+-- local converter = sql.makeconverter {
+-- { name = "id", type = "number" },
+-- { name = "data",type = "string" },
+-- }
+--
+-- local execute = sql.methods.swiglib.execute
+-- -- local execute = sql.methods.library.execute
+-- -- local execute = sql.methods.client.execute
+-- -- local execute = sql.methods.lmxsql.execute
+--
+-- result = execute {
+-- presets = {
+-- host = "localhost",
+-- username = "root",
+-- password = "test",
+-- database = "test",
+-- id = "test", -- forces persistent session
+-- },
+-- template = "select * from `test` where `id` > %criterium% ;",
+-- variables = {
+-- criterium = 2,
+-- },
+-- converter = converter
+-- }
+--
+-- inspect(result)
+
+local format, match = string.format, string.match
+local random = math.random
+local rawset, setmetatable, getmetatable, load, type = rawset, setmetatable, getmetatable, load, type
+local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
+local concat = table.concat
+
+local osuuid = os.uuid
+local osclock = os.clock or os.time
+local ostime = os.time
+local setmetatableindex = table.setmetatableindex
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql")
+
+-- trace_sql = true
+-- trace_queries = true
+
+utilities.sql = utilities.sql or { }
+local sql = utilities.sql
+
+local replacetemplate = utilities.templates.replace
+local loadtemplate = utilities.templates.load
+
+local methods = { }
+sql.methods = methods
+
+local helpers = { }
+sql.helpers = helpers
+
+local serialize = table.fastserialize
+local deserialize = table.deserialize
+
+sql.serialize = serialize
+sql.deserialize = deserialize
+
+helpers.serialize = serialize -- bonus
+helpers.deserialize = deserialize -- bonus
+
+local defaults = { __index =
+ {
+ resultfile = "result.dat",
+ templatefile = "template.sql",
+ queryfile = "query.sql",
+ variables = { },
+ username = "default",
+ password = "default",
+ host = "localhost",
+ port = 3306,
+ database = "default",
+ },
+}
+
+setmetatableindex(sql.methods,function(t,k)
+ report_state("start loading method %a",k)
+ require("util-sql-imp-"..k)
+ report_state("loading method %a done",k)
+ return rawget(t,k)
+end)
+
+-- converters
+
+local converters = { }
+sql.converters = converters
+
+local function makeconverter(entries,celltemplate,wraptemplate)
+ local shortcuts = { }
+ local assignments = { }
+ local key = false
+ for i=1,#entries do
+ local entry = entries[i]
+ local name = entry.name
+ local kind = entry.type or entry.kind
+ local value = format(celltemplate,i,i)
+ if kind == "boolean" then
+ assignments[#assignments+1] = format("[%q] = booleanstring(%s),",name,value)
+ elseif kind == "number" then
+ assignments[#assignments+1] = format("[%q] = tonumber(%s),",name,value)
+ elseif type(kind) == "function" then
+ local c = #converters + 1
+ converters[c] = kind
+ shortcuts[#shortcuts+1] = format("local fun_%s = converters[%s]",c,c)
+ assignments[#assignments+1] = format("[%q] = fun_%s(%s),",name,c,value)
+ elseif type(kind) == "table" then
+ local c = #converters + 1
+ converters[c] = kind
+ shortcuts[#shortcuts+1] = format("local tab_%s = converters[%s]",c,c)
+ assignments[#assignments+1] = format("[%q] = tab_%s[%s],",name,#converters,value)
+ elseif kind == "deserialize" then
+ assignments[#assignments+1] = format("[%q] = deserialize(%s),",name,value)
+ elseif kind == "key" then
+ -- hashed instead of indexed
+ key = value
+ elseif kind == "entry" then
+ -- so we can (efficiently) extend the hashed table
+ local default = entry.default or ""
+ if type(default) == "string" then
+ assignments[#assignments+1] = format("[%q] = %q,",name,default)
+ else
+ assignments[#assignments+1] = format("[%q] = %s,",name,tostring(default))
+ end
+ else
+ assignments[#assignments+1] = format("[%q] = %s,",name,value)
+ end
+ end
+ local code = format(wraptemplate,concat(shortcuts,"\n"),key and "{ }" or "data",key or "i",concat(assignments,"\n "))
+ -- print(code)
+ local func = load(code)
+ return func and func()
+end
+
+function sql.makeconverter(entries)
+ local fields = { }
+ for i=1,#entries do
+ fields[i] = format("`%s`",entries[i].name)
+ end
+ fields = concat(fields, ", ")
+ local converter = {
+ fields = fields
+ }
+ setmetatableindex(converter, function(t,k)
+ local sqlmethod = methods[k]
+ local v = makeconverter(entries,sqlmethod.celltemplate,sqlmethod.wraptemplate)
+ t[k] = v
+ return v
+ end)
+ return converter, fields
+end
+
+-- helper for libraries:
+
+local function validspecification(specification)
+ local presets = specification.presets
+ if type(presets) == "string" then
+ presets = dofile(presets)
+ end
+ if type(presets) == "table" then
+ setmetatable(presets,defaults)
+ setmetatable(specification,{ __index = presets })
+ else
+ setmetatable(specification,defaults)
+ end
+ return true
+end
+
+helpers.validspecification = validspecification
+
+local whitespace = patterns.whitespace^0
+local eol = patterns.eol
+local separator = P(";")
+local escaped = patterns.escaped
+local dquote = patterns.dquote
+local squote = patterns.squote
+local dsquote = squote * squote
+---- quoted = patterns.quoted
+local quoted = dquote * (escaped + (1-dquote))^0 * dquote
+ + squote * (escaped + dsquote + (1-squote))^0 * squote
+local comment = P("--") * (1-eol) / ""
+local query = whitespace
+ * Cs((quoted + comment + 1 - separator)^1 * Cc(";"))
+ * whitespace
+local splitter = Ct(query * (separator * query)^0)
+
+helpers.querysplitter = splitter
+
+-- I will add a bit more checking.
+
+local function validspecification(specification)
+ local presets = specification.presets
+ if type(presets) == "string" then
+ presets = dofile(presets)
+ end
+ if type(presets) == "table" then
+ local m = getmetatable(presets)
+ if m then
+ setmetatable(m,defaults)
+ else
+ setmetatable(presets,defaults)
+ end
+ setmetatable(specification,{ __index = presets })
+ else
+ setmetatable(specification,defaults)
+ end
+ local templatefile = specification.templatefile or "query"
+ local queryfile = specification.queryfile or presets.queryfile or file.nameonly(templatefile) .. "-temp.sql"
+ local resultfile = specification.resultfile or presets.resultfile or file.nameonly(templatefile) .. "-temp.dat"
+ specification.queryfile = queryfile
+ specification.resultfile = resultfile
+ if trace_sql then
+ report_state("template file: %s",templatefile or "<none>")
+ report_state("query file: %s",queryfile)
+ report_state("result file: %s",resultfile)
+ end
+ return true
+end
+
+local function preparetemplate(specification)
+ local template = specification.template
+ if template then
+ local query = replacetemplate(template,specification.variables,'sql')
+ if not query then
+ report_state("error in template: %s",template)
+ elseif trace_queries then
+ report_state("query from template: %s",query)
+ end
+ return query
+ end
+ local templatefile = specification.templatefile
+ if templatefile then
+ local query = loadtemplate(templatefile,specification.variables,'sql')
+ if not query then
+ report_state("error in template file %a",templatefile)
+ elseif trace_queries then
+ report_state("query from template file %a: %s",templatefile,query)
+ end
+ return query
+ end
+ report_state("no query template or templatefile")
+end
+
+helpers.preparetemplate = preparetemplate
+
+-- -- -- we delay setting this -- -- --
+
+local currentmethod
+local currentserver
+
+local function firstexecute(...)
+ local execute = methods[currentmethod].execute
+ sql.execute = execute
+ return execute(...)
+end
+
+function sql.setmethod(method)
+ currentmethod = method
+ sql.execute = firstexecute
+end
+
+function sql.setserver(server)
+ currentserver = server
+end
+
+function sql.getmethod()
+ return currentmethod
+end
+
+function sql.getserver()
+ return currentserver
+end
+
+sql.setmethod("library")
+sql.setserver("mysql")
+
+-- helper:
+
+function sql.usedatabase(presets,datatable)
+ local name = datatable or presets.datatable
+ if name then
+ local method = presets.method and sql.methods[presets.method] or sql.methods.client
+ local base = presets.database or "test"
+ local basename = format("`%s`.`%s`",base,name)
+ local execute = nil
+ local m_execute = method.execute
+ if method.usesfiles then
+ local queryfile = presets.queryfile or format("%s-temp.sql",name)
+ local resultfile = presets.resultfile or format("%s-temp.dat",name)
+ execute = function(specification) -- variables template
+ if not specification.presets then specification.presets = presets end
+ if not specification.queryfile then specification.queryfile = queryfile end
+ if not specification.resultfile then specification.resultfile = queryfile end
+ return m_execute(specification)
+ end
+ else
+ execute = function(specification) -- variables template
+ if not specification.presets then specification.presets = presets end
+ return m_execute(specification)
+ end
+ end
+ local function unpackdata(records,name)
+ if records then
+ name = name or "data"
+ for i=1,#records do
+ local record = records[i]
+ local data = record[name]
+ if data then
+ record[name] = deserialize(data)
+ end
+ end
+ end
+ end
+ return {
+ presets = preset,
+ base = base,
+ name = name,
+ basename = basename,
+ execute = execute,
+ serialize = serialize,
+ deserialize = deserialize,
+ unpackdata = unpackdata,
+ }
+ else
+ report_state("missing name in usedatabase specification")
+ end
+end
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- host = "...",
+-- username = "...",
+-- password = "...",
+-- database = "...",
+-- }
+
+-- local presets = {
+-- host = "...",
+-- username = "...",
+-- password = "...",
+-- database = "...",
+-- }
+--
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = presets,
+-- }
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = dofile(...),
+-- }
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = "...",
+-- }
+
+-- for i=1,10 do
+-- local dummy = uuid() -- else same every time, don't ask
+-- end
+
+sql.tokens = {
+ length = 42, -- but in practice we will reserve some 50 characters
+ new = function()
+ return format("%s-%x06",osuuid(),random(0xFFFFF)) -- 36 + 1 + 6 = 42
+ end,
+}
+
+-- -- --
+
+-- local func, code = sql.makeconverter {
+-- { name = "a", type = "number" },
+-- { name = "b", type = "string" },
+-- { name = "c", type = "boolean" },
+-- { name = "d", type = { x = "1" } },
+-- { name = "e", type = os.fulltime },
+-- }
+--
+-- print(code)
+
+-- -- --
+
+if tex and tex.systemmodes then
+
+ local droptable = table.drop
+ local threshold = 16 * 1024 -- use slower but less memory hungry variant
+
+ function sql.prepare(specification,tag)
+ -- could go into tuc if needed
+ -- todo: serialize per column
+ local tag = tag or specification.tag or "last"
+ local filename = format("%s-sql-result-%s.tuc",tex.jobname,tag)
+ if tex.systemmodes["first"] then
+ local data, keys = sql.execute(specification)
+ if not data then
+ data = { }
+ end
+ if not keys then
+ keys = { }
+ end
+ io.savedata(filename,droptable({ data = data, keys = keys },#keys*#data>threshold))
+ return data, keys
+ else
+ local result = table.load(filename)
+ return result.data, result.keys
+ end
+ end
+
+else
+
+ sql.prepare = sql.execute
+
+end
+
+return sql
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua
new file mode 100644
index 00000000000..27ab5a624b6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua
@@ -0,0 +1,352 @@
+if not modules then modules = { } end modules ['util-sta'] = {
+ version = 1.001,
+ comment = "companion to util-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local format = string.format
+local select, tostring = select, tostring
+
+local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end)
+
+local stacker = stacker or { }
+
+utilities.stacker = stacker
+
+local function start(s,t,first,last)
+ if s.mode == "switch" then
+ local n = tostring(t[last])
+ if trace_stacker then
+ s.report("start: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=first,last do
+ r[#r+1] = tostring(t[i])
+ end
+ local n = concat(r," ")
+ if trace_stacker then
+ s.report("start: %s",n)
+ end
+ return n
+ end
+end
+
+local function stop(s,t,first,last)
+ if s.mode == "switch" then
+ local n = tostring(false)
+ if trace_stacker then
+ s.report("stop: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=last,first,-1 do
+ r[#r+1] = tostring(false)
+ end
+ local n = concat(r," ")
+ if trace_stacker then
+ s.report("stop: %s",n)
+ end
+ return n
+ end
+end
+
+local function change(s,t1,first1,last1,t2,first2,last2)
+ if s.mode == "switch" then
+ local n = tostring(t2[last2])
+ if trace_stacker then
+ s.report("change: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=last1,first1,-1 do
+ r[#r+1] = tostring(false)
+ end
+ local n = concat(r," ")
+ for i=first2,last2 do
+ r[#r+1] = tostring(t2[i])
+ end
+ if trace_stacker then
+ s.report("change: %s",n)
+ end
+ return n
+ end
+end
+
+function stacker.new(name)
+
+ local report = logs.reporter("stacker",name or nil)
+
+ local s
+
+ local stack = { }
+ local list = { }
+ local ids = { }
+ local hash = { }
+
+ local hashing = true
+
+ local function push(...)
+ for i=1,select("#",...) do
+ insert(stack,(select(i,...))) -- watch the ()
+ end
+ if hashing then
+ local c = concat(stack,"|")
+ local n = hash[c]
+ if not n then
+ n = #list+1
+ hash[c] = n
+ list[n] = fastcopy(stack)
+ end
+ insert(ids,n)
+ return n
+ else
+ local n = #list+1
+ list[n] = fastcopy(stack)
+ insert(ids,n)
+ return n
+ end
+ end
+
+ local function pop()
+ remove(stack)
+ remove(ids)
+ return ids[#ids] or s.unset or -1
+ end
+
+ local function clean()
+ if #stack == 0 then
+ if trace_stacker then
+ s.report("%s list entries, %s stack entries",#list,#stack)
+ end
+ end
+ end
+
+ local tops = { }
+ local top = nil
+ local switch = nil
+
+ local function resolve_reset(mode)
+ if #tops > 0 then
+ report("resetting %s left-over states of %a",#tops,name)
+ end
+ tops = { }
+ top = nil
+ switch = nil
+ end
+
+ local function resolve_begin(mode)
+ if mode then
+ switch = mode == "switch"
+ else
+ switch = s.mode == "switch"
+ end
+ top = { switch = switch }
+ insert(tops,top)
+ end
+
+ local function resolve_step(ti) -- keep track of changes outside function !
+ -- todo: optimize for n=1 etc
+ local result = nil
+ local noftop = #top
+ if ti > 0 then
+ local current = list[ti]
+ if current then
+ local noflist = #current
+ local nofsame = 0
+ if noflist > noftop then
+ for i=1,noflist do
+ if current[i] == top[i] then
+ nofsame = i
+ else
+ break
+ end
+ end
+ else
+ for i=1,noflist do
+ if current[i] == top[i] then
+ nofsame = i
+ else
+ break
+ end
+ end
+ end
+ local plus = nofsame + 1
+ if plus <= noftop then
+ if plus <= noflist then
+ if switch then
+ result = s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result = s.change(s,top,plus,noftop,current,plus,noflist)
+ end
+ else
+ if switch then
+ result = s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result = s.stop(s,top,plus,noftop)
+ end
+ end
+ elseif plus <= noflist then
+ if switch then
+ result = s.start(s,current,nofsame,noflist)
+ else
+ result = s.start(s,current,plus,noflist)
+ end
+ end
+ top = current
+ else
+ if 1 <= noftop then
+ result = s.stop(s,top,1,noftop)
+ end
+ top = { }
+ end
+ return result
+ else
+ if 1 <= noftop then
+ result = s.stop(s,top,1,noftop)
+ end
+ top = { }
+ return result
+ end
+ end
+
+ local function resolve_end()
+ -- resolve_step(s.unset)
+ if #tops > 0 then -- was #top brrr
+ local result = s.stop(s,top,1,#top)
+ remove(tops)
+ top = tops[#tops]
+ switch = top and top.switch
+ return result
+ end
+ end
+
+ local function resolve(t)
+ resolve_begin()
+ for i=1,#t do
+ resolve_step(t[i])
+ end
+ resolve_end()
+ end
+
+ s = {
+ name = name or "unknown",
+ unset = -1,
+ report = report,
+ start = start,
+ stop = stop,
+ change = change,
+ push = push,
+ pop = pop,
+ clean = clean,
+ resolve = resolve,
+ resolve_begin = resolve_begin,
+ resolve_step = resolve_step,
+ resolve_end = resolve_end,
+ resolve_reset = resolve_reset,
+ }
+
+ return s -- we can overload functions
+
+end
+
+-- local s = utilities.stacker.new("demo")
+--
+-- local unset = s.unset
+-- local push = s.push
+-- local pop = s.pop
+--
+-- local t = {
+-- unset,
+-- unset,
+-- push("a"), -- a
+-- push("b","c"), -- a b c
+-- pop(), -- a b
+-- push("d"), -- a b d
+-- pop(), -- a b
+-- unset,
+-- pop(), -- a
+-- pop(), -- b
+-- unset,
+-- unset,
+-- }
+--
+-- s.resolve(t)
+
+-- demostacker = utilities.stacker.new("demos")
+--
+-- local whatever = {
+-- one = "1 0 0 RG 1 0 0 rg",
+-- two = "1 1 0 RG 1 1 0 rg",
+-- [false] = "0 G 0 g",
+-- }
+--
+-- local concat = table.concat
+--
+-- local pdfliteral = nodes.pool.pdfliteral
+--
+-- function demostacker.start(s,t,first,last)
+-- local n = whatever[t[last]]
+-- -- s.report("start: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.stop(s,t,first,last)
+-- local n = whatever[false]
+-- -- s.report("stop: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
+-- local n = whatever[t2[last2]]
+-- -- s.report("change: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- demostacker.mode = "switch"
+--
+-- local whatever = {
+-- one = "/OC /test1 BDC",
+-- two = "/OC /test2 BDC",
+-- [false] = "EMC",
+-- }
+--
+-- demostacker = utilities.stacker.new("demos")
+--
+-- function demostacker.start(s,t,first,last)
+-- local r = { }
+-- for i=first,last do
+-- r[#r+1] = whatever[t[i]]
+-- end
+-- -- s.report("start: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- function demostacker.stop(s,t,first,last)
+-- local r = { }
+-- for i=last,first,-1 do
+-- r[#r+1] = whatever[false]
+-- end
+-- -- s.report("stop: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
+-- local r = { }
+-- for i=last1,first1,-1 do
+-- r[#r+1] = whatever[false]
+-- end
+-- for i=first2,last2 do
+-- r[#r+1] = whatever[t2[i]]
+-- end
+-- -- s.report("change: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- demostacker.mode = "stack"
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua
new file mode 100644
index 00000000000..d21267d7a8c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua
@@ -0,0 +1,174 @@
+if not modules then modules = { } end modules ['util-sto'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, getmetatable, type = setmetatable, getmetatable, type
+
+utilities = utilities or { }
+utilities.storage = utilities.storage or { }
+local storage = utilities.storage
+
+function storage.mark(t)
+ if not t then
+ print("\nfatal error: storage cannot be marked\n")
+ os.exit()
+ return
+ end
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.allocate(t)
+ t = t or { }
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.marked(t)
+ local m = getmetatable(t)
+ return m and m.__storage__
+end
+
+function storage.checked(t)
+ if not t then
+ report("\nfatal error: storage has not been allocated\n")
+ os.exit()
+ return
+ end
+ return t
+end
+
+-- function utilities.storage.delay(parent,name,filename)
+-- local m = getmetatable(parent)
+-- m.__list[name] = filename
+-- end
+--
+-- function utilities.storage.predefine(parent)
+-- local list = { }
+-- local m = getmetatable(parent) or {
+-- __list = list,
+-- __index = function(t,k)
+-- local l = require(list[k])
+-- t[k] = l
+-- return l
+-- end
+-- }
+-- setmetatable(parent,m)
+-- end
+--
+-- bla = { }
+-- utilities.storage.predefine(bla)
+-- utilities.storage.delay(bla,"test","oepsoeps")
+-- local t = bla.test
+-- table.print(t)
+-- print(t.a)
+
+function storage.setinitializer(data,initialize)
+ local m = getmetatable(data) or { }
+ m.__index = function(data,k)
+ m.__index = nil -- so that we can access the entries during initializing
+ initialize()
+ return data[k]
+ end
+ setmetatable(data, m)
+end
+
+local keyisvalue = { __index = function(t,k)
+ t[k] = k
+ return k
+end }
+
+function storage.sparse(t)
+ t = t or { }
+ setmetatable(t,keyisvalue)
+ return t
+end
+
+-- table namespace ?
+
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_table (t,k) local v = { } t[k] = v return v end
+local function f_number(t,k) t[k] = 0 return 0 end -- t,k,v
+local function f_ignore() end -- t,k,v
+
+local f_index = {
+ ["empty"] = f_empty,
+ ["self"] = f_self,
+ ["table"] = f_table,
+ ["number"] = f_number,
+}
+
+function table.setmetatableindex(t,f)
+ if type(t) ~= "table" then
+ f, t = t, { }
+ end
+ local m = getmetatable(t)
+ local i = f_index[f] or f
+ if m then
+ m.__index = i
+ else
+ setmetatable(t,{ __index = i })
+ end
+ return t
+end
+
+local f_index = {
+ ["ignore"] = f_ignore,
+}
+
+function table.setmetatablenewindex(t,f)
+ if type(t) ~= "table" then
+ f, t = t, { }
+ end
+ local m = getmetatable(t)
+ local i = f_index[f] or f
+ if m then
+ m.__newindex = i
+ else
+ setmetatable(t,{ __newindex = i })
+ end
+ return t
+end
+
+function table.setmetatablecall(t,f)
+ if type(t) ~= "table" then
+ f, t = t, { }
+ end
+ local m = getmetatable(t)
+ if m then
+ m.__call = f
+ else
+ setmetatable(t,{ __call = f })
+ end
+ return t
+end
+
+function table.setmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m[key] = value
+ return t
+end
+
+function table.getmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ return m and m[key]
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-str.lua b/Master/texmf-dist/tex/context/base/mkiv/util-str.lua
new file mode 100644
index 00000000000..28b75dbc599
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-str.lua
@@ -0,0 +1,1136 @@
+if not modules then modules = { } end modules ['util-str'] = {
+ 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"
+}
+
+utilities = utilities or { }
+utilities.strings = utilities.strings or { }
+local strings = utilities.strings
+
+local format, gsub, rep, sub = string.format, string.gsub, string.rep, string.sub
+local load, dump = load, string.dump
+local tonumber, type, tostring = tonumber, type, tostring
+local unpack, concat = table.unpack, table.concat
+local P, V, C, S, R, Ct, Cs, Cp, Carg, Cc = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg, lpeg.Cc
+local patterns, lpegmatch = lpeg.patterns, lpeg.match
+local utfchar, utfbyte = utf.char, utf.byte
+----- loadstripped = utilities.lua.loadstripped
+----- setmetatableindex = table.setmetatableindex
+
+local loadstripped = nil
+
+if _LUAVERSION < 5.2 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
+ 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 newline = patterns.newline
+local endofstring = patterns.endofstring
+local whitespace = patterns.whitespace
+local spacer = patterns.spacer
+local spaceortab = patterns.spaceortab
+
+local function points(n)
+ n = tonumber(n)
+ return (not n or n == 0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+end
+
+local function basepoints(n)
+ n = tonumber(n)
+ return (not n or n == 0) and "0bp" or lpegmatch(stripper,format("%.5fbp", n*(7200/7227)/65536))
+end
+
+number.points = points
+number.basepoints = basepoints
+
+-- str = " \n \ntest \n test\ntest "
+-- print("["..string.gsub(string.collapsecrlf(str),"\n","+").."]")
+
+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) / ""
+local redundant = rubish^3 / "\n"
+
+local pattern = Cs(leading * (trailing + redundant + stripped + anything)^0)
+
+function strings.collapsecrlf(str)
+ return lpegmatch(pattern,str)
+end
+
+-- The following functions might end up in another namespace.
+
+local repeaters = { } -- watch how we also moved the -1 in depth-1 to the creator
+
+function strings.newrepeater(str,offset)
+ offset = offset or 0
+ local s = repeaters[str]
+ if not s then
+ s = { }
+ repeaters[str] = s
+ end
+ local t = s[offset]
+ if t then
+ return t
+ end
+ t = { }
+ setmetatable(t, { __index = function(t,k)
+ if not k then
+ return ""
+ end
+ local n = k + offset
+ local s = n > 0 and rep(str,n) or ""
+ t[k] = s
+ return s
+ end })
+ s[offset] = t
+ return t
+end
+
+-- local dashes = strings.newrepeater("--",-1)
+-- print(dashes[2],dashes[3],dashes[1])
+
+local extra, tab, start = 0, 0, 4, 0
+
+local nspaces = strings.newrepeater(" ")
+
+string.nspaces = nspaces
+
+local pattern =
+ Carg(1) / function(t)
+ extra, tab, start = 0, t or 7, 1
+ end
+ * Cs((
+ Cp() * patterns.tab / function(position)
+ local current = (position - start + 1) + extra
+ local spaces = tab-(current-1) % tab
+ if spaces > 0 then
+ extra = extra + spaces - 1
+ return nspaces[spaces] -- rep(" ",spaces)
+ else
+ return ""
+ end
+ end
+ + newline * Cp() / function(position)
+ extra, start = 0, position
+ end
+ + patterns.anything
+ )^1)
+
+function strings.tabtospace(str,tab)
+ return lpegmatch(pattern,str,1,tab or 7)
+end
+
+-- local t = {
+-- "1234567123456712345671234567",
+-- "\tb\tc",
+-- "a\tb\tc",
+-- "aa\tbb\tcc",
+-- "aaa\tbbb\tccc",
+-- "aaaa\tbbbb\tcccc",
+-- "aaaaa\tbbbbb\tccccc",
+-- "aaaaaa\tbbbbbb\tcccccc\n aaaaaa\tbbbbbb\tcccccc",
+-- "one\n two\nxxx three\nxx four\nx five\nsix",
+-- }
+-- for k=1,#t do
+-- print(strings.tabtospace(t[k]))
+-- end
+
+-- todo: lpeg
+
+-- function strings.striplong(str) -- strips all leading spaces
+-- str = gsub(str,"^%s*","")
+-- str = gsub(str,"[\n\r]+ *","\n")
+-- return str
+-- end
+
+local space = spacer^0
+local nospace = space/""
+local endofline = nospace * newline
+
+local stripend = (whitespace^1 * endofstring)/""
+
+local normalline = (nospace * ((1-space*(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 stripstart = stripempty^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_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
+-- if noempty then
+-- return lpegmatch(p_prune_noempty,str) or str
+-- elseif collapse then
+-- return lpegmatch(p_prune_collapse,str) or str
+-- else
+-- return lpegmatch(p_prune_normal,str) or str
+-- end
+-- else
+-- if noempty then
+-- return lpegmatch(p_retain_noempty,str) or str
+-- elseif collapse then
+-- return lpegmatch(p_retain_collapse,str) or str
+-- else
+-- return lpegmatch(p_retain_normal,str) or str
+-- end
+-- end
+-- end
+
+local striplinepatterns = {
+ ["prune"] = p_prune_normal,
+ ["prune and collapse"] = p_prune_collapse, -- default
+ ["prune and no empty"] = p_prune_noempty,
+ ["retain"] = p_retain_normal,
+ ["retain and collapse"] = p_retain_collapse,
+ ["retain and no empty"] = p_retain_noempty,
+ ["collapse"] = patterns.collapser, -- how about: stripper fullstripper
+}
+
+setmetatable(striplinepatterns,{ __index = function(t,k) return p_prune_collapse end })
+
+strings.striplinepatterns = striplinepatterns
+
+function strings.striplines(str,how)
+ return str and lpegmatch(striplinepatterns[how],str) or str
+end
+
+-- also see: string.collapsespaces
+
+strings.striplong = strings.striplines -- for old times sake
+
+-- local str = table.concat( {
+-- " ",
+-- " aap",
+-- " noot mies",
+-- " ",
+-- " ",
+-- " zus wim jet",
+-- "zus wim jet",
+-- " 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
+
+-- inspect(strings.striplong([[
+-- aaaa
+-- bb
+-- cccccc
+-- ]]))
+
+function strings.nice(str)
+ str = gsub(str,"[:%-+_]+"," ") -- maybe more
+ return str
+end
+
+-- Work in progress. Interesting is that compared to the built-in this is faster in
+-- luatex than in luajittex where we have a comparable speed. It only makes sense
+-- to use the formatter when a (somewhat) complex format is used a lot. Each formatter
+-- is a function so there is some overhead and not all formatted output is worth that
+-- overhead. Keep in mind that there is an extra function call involved. In principle
+-- we end up with a string concatination so one could inline such a sequence but often
+-- at the cost of less readabinity. So, it's a sort of (visual) compromise. Of course
+-- there is the benefit of more variants. (Concerning the speed: a simple format like
+-- %05fpt is better off with format than with a formatter, but as soon as you put
+-- something in front formatters become faster. Passing the pt as extra argument makes
+-- formatters behave better. Of course this is rather implementation dependent. Also,
+-- when a specific format is only used a few times the overhead in creating it is not
+-- compensated by speed.)
+--
+-- More info can be found in cld-mkiv.pdf so here I stick to a simple list.
+--
+-- integer %...i number
+-- integer %...d number
+-- unsigned %...u number
+-- character %...c number
+-- hexadecimal %...x number
+-- HEXADECIMAL %...X number
+-- octal %...o number
+-- string %...s string number
+-- float %...f number
+-- checked float %...F number
+-- exponential %...e number
+-- exponential %...E number
+-- autofloat %...g number
+-- autofloat %...G number
+-- utf character %...c number
+-- force tostring %...S any
+-- force tostring %Q any
+-- force tonumber %N number (strip leading zeros)
+-- signed number %I number
+-- rounded number %r number
+-- 0xhexadecimal %...h character number
+-- 0xHEXADECIMAL %...H character number
+-- U+hexadecimal %...u character number
+-- U+HEXADECIMAL %...U character number
+-- points %p number (scaled points)
+-- basepoints %b number (scaled points)
+-- table concat %...t table
+-- table concat %{.}t table
+-- serialize %...T sequenced (no nested tables)
+-- serialize %{.}T sequenced (no nested tables)
+-- boolean (logic) %l boolean
+-- BOOLEAN %L boolean
+-- whitespace %...w
+-- automatic %...a 'whatever' (string, table, ...)
+-- automatic %...A "whatever" (string, table, ...)
+
+local n = 0
+
+-- we are somewhat sloppy in parsing prefixes as it's not that critical
+
+-- hard to avoid but we can collect them in a private namespace if needed
+
+-- inline the next two makes no sense as we only use this in logging
+
+local sequenced = table.sequenced
+
+function string.autodouble(s,sep)
+ if s == nil then
+ return '""'
+ end
+ local t = type(s)
+ if t == "number" then
+ return tostring(s) -- tostring not really needed
+ end
+ if t == "table" then
+ return ('"' .. sequenced(s,sep or ",") .. '"')
+ end
+ return ('"' .. tostring(s) .. '"')
+end
+
+function string.autosingle(s,sep)
+ if s == nil then
+ return "''"
+ end
+ local t = type(s)
+ if t == "number" then
+ return tostring(s) -- tostring not really needed
+ end
+ if t == "table" then
+ return ("'" .. sequenced(s,sep or ",") .. "'")
+ end
+ return ("'" .. tostring(s) .. "'")
+end
+
+local tracedchars = { [0] =
+ -- the regular bunch
+ "[null]", "[soh]", "[stx]", "[etx]", "[eot]", "[enq]", "[ack]", "[bel]",
+ "[bs]", "[ht]", "[lf]", "[vt]", "[ff]", "[cr]", "[so]", "[si]",
+ "[dle]", "[dc1]", "[dc2]", "[dc3]", "[dc4]", "[nak]", "[syn]", "[etb]",
+ "[can]", "[em]", "[sub]", "[esc]", "[fs]", "[gs]", "[rs]", "[us]",
+ -- plus space
+ "[space]", -- 0x20
+}
+
+string.tracedchars = tracedchars
+strings.tracers = tracedchars
+
+function string.tracedchar(b)
+ -- todo: table
+ if type(b) == "number" then
+ return tracedchars[b] or (utfchar(b) .. " (U+" .. format("%05X",b) .. ")")
+ else
+ local c = utfbyte(b)
+ return tracedchars[c] or (b .. " (U+" .. (c and format("%05X",c) or "?????") .. ")")
+ end
+end
+
+function number.signed(i)
+ if i > 0 then
+ return "+", i
+ else
+ return "-", -i
+ end
+end
+
+local zero = P("0")^1 / ""
+local plus = P("+") / ""
+local minus = P("-")
+local separator = S(".")
+local digit = R("09")
+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 pattern_a = Cs(minus^0 * digit^1 * (separator/"" * trailing + separator * (trailing + digit)^0) * exponent)
+local pattern_b = Cs((exponent + P(1))^0)
+
+function number.sparseexponent(f,n)
+ if not n then
+ n = f
+ f = "%e"
+ end
+ local tn = type(n)
+ if tn == "string" then -- cast to number
+ local m = tonumber(n)
+ if m then
+ return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,m))
+ end
+ elseif tn == "number" then
+ return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,n))
+ end
+ return tostring(n)
+end
+
+local template = [[
+%s
+%s
+return function(%s) return %s end
+]]
+
+local preamble, environment = "", { }
+
+if _LUAVERSION < 5.2 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 tracedchar=string.tracedchar
+local autosingle=string.autosingle
+local autodouble=string.autodouble
+local sequenced=table.sequenced
+local formattednumber=number.formatted
+local sparseexponent=number.sparseexponent
+ ]]
+
+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,
+ tracedchar = string.tracedchar,
+ autosingle = string.autosingle,
+ autodouble = string.autodouble,
+ sequenced = table.sequenced,
+ formattednumber = number.formatted,
+ sparseexponent = number.sparseexponent,
+ }
+
+end
+
+-- -- --
+
+local arguments = { "a1" } -- faster than previously used (select(n,...))
+
+setmetatable(arguments, { __index =
+ function(t,k)
+ local v = t[k-1] .. ",a" .. k
+ t[k] = v
+ return v
+ end
+})
+
+local prefix_any = C((S("+- .") + R("09"))^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)
+
+-- todo: replace outer formats in next by ..
+
+local format_s = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("format('%%%ss',a%s)",f,n)
+ else -- best no tostring in order to stay compatible (.. does a selective tostring too)
+ return format("(a%s or '')",n) -- goodie: nil check
+ end
+end
+
+local format_S = function(f) -- can be optimized
+ n = n + 1
+ if f and f ~= "" then
+ return format("format('%%%ss',tostring(a%s))",f,n)
+ else
+ return format("tostring(a%s)",n)
+ end
+end
+
+local format_q = function()
+ n = n + 1
+ return format("(a%s and format('%%q',a%s) or '')",n,n) -- goodie: nil check (maybe separate lpeg, not faster)
+end
+
+local format_Q = function() -- can be optimized
+ n = n + 1
+ return format("format('%%q',tostring(a%s))",n)
+end
+
+local format_i = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("format('%%%si',a%s)",f,n)
+ else
+ return format("format('%%i',a%s)",n) -- why not just tostring()
+ end
+end
+
+local format_d = format_i
+
+local format_I = function(f)
+ n = n + 1
+ return format("format('%%s%%%si',signed(a%s))",f,n)
+end
+
+local format_f = function(f)
+ n = n + 1
+ return format("format('%%%sf',a%s)",f,n)
+end
+
+-- The next one formats an integer as integer and very small values as zero. This is needed
+-- for pdf backend code.
+--
+-- 1.23 % 1 : 0.23
+-- - 1.23 % 1 : 0.77
+--
+-- We could probably use just %s with integers but who knows what Lua 5.3 will do? So let's
+-- for the moment use %i.
+
+local 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 %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
+ else
+ return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
+ end
+end
+
+local format_g = function(f)
+ n = n + 1
+ return format("format('%%%sg',a%s)",f,n)
+end
+
+local format_G = function(f)
+ n = n + 1
+ return format("format('%%%sG',a%s)",f,n)
+end
+
+local format_e = function(f)
+ n = n + 1
+ return format("format('%%%se',a%s)",f,n)
+end
+
+local format_E = function(f)
+ n = n + 1
+ return format("format('%%%sE',a%s)",f,n)
+end
+
+local format_j = function(f)
+ n = n + 1
+ return format("sparseexponent('%%%se',a%s)",f,n)
+end
+
+local format_J = function(f)
+ n = n + 1
+ return format("sparseexponent('%%%sE',a%s)",f,n)
+end
+
+local format_x = function(f)
+ n = n + 1
+ return format("format('%%%sx',a%s)",f,n)
+end
+
+local format_X = function(f)
+ n = n + 1
+ return format("format('%%%sX',a%s)",f,n)
+end
+
+local format_o = function(f)
+ n = n + 1
+ return format("format('%%%so',a%s)",f,n)
+end
+
+local format_c = function()
+ n = n + 1
+ return format("utfchar(a%s)",n)
+end
+
+local format_C = function()
+ n = n + 1
+ return format("tracedchar(a%s)",n)
+end
+
+local format_r = function(f)
+ n = n + 1
+ return format("format('%%%s.0f',a%s)",f,n)
+end
+
+local format_h = function(f)
+ n = n + 1
+ if f == "-" then
+ f = sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ end
+end
+
+local format_H = function(f)
+ n = n + 1
+ if f == "-" then
+ f = sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ end
+end
+
+local format_u = function(f)
+ n = n + 1
+ if f == "-" then
+ f = sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ else
+ return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ end
+end
+
+local format_U = function(f)
+ n = n + 1
+ if f == "-" then
+ f = sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ else
+ return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n)
+ end
+end
+
+local format_p = function()
+ n = n + 1
+ return format("points(a%s)",n)
+end
+
+local format_b = function()
+ n = n + 1
+ return format("basepoints(a%s)",n)
+end
+
+local format_t = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("concat(a%s,%q)",n,f)
+ else
+ return format("concat(a%s)",n)
+ end
+end
+
+local format_T = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("sequenced(a%s,%q)",n,f)
+ else
+ return format("sequenced(a%s)",n)
+ end
+end
+
+local format_l = function()
+ n = n + 1
+ return format("(a%s and 'true' or 'false')",n)
+end
+
+local format_L = function()
+ n = n + 1
+ return format("(a%s and 'TRUE' or 'FALSE')",n)
+end
+
+local format_N = function() -- strips leading zeros
+ n = n + 1
+ return format("tostring(tonumber(a%s) or a%s)",n,n)
+end
+
+local format_a = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("autosingle(a%s,%q)",n,f)
+ else
+ return format("autosingle(a%s)",n)
+ end
+end
+
+local format_A = function(f)
+ n = n + 1
+ if f and f ~= "" then
+ return format("autodouble(a%s,%q)",n,f)
+ else
+ return format("autodouble(a%s)",n)
+ end
+end
+
+local format_w = function(f) -- handy when doing depth related indent
+ n = n + 1
+ f = tonumber(f)
+ if f then -- not that useful
+ return format("nspaces[%s+a%s]",f,n) -- no real need for tonumber
+ else
+ return format("nspaces[a%s]",n) -- no real need for tonumber
+ end
+end
+
+local format_W = function(f) -- handy when doing depth related indent
+ return format("nspaces[%s]",tonumber(f) or 0)
+end
+
+-- maybe to util-num
+
+local digit = patterns.digit
+local period = patterns.period
+local three = digit * digit * digit
+
+local splitter = Cs (
+ (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1))
+ * (P(1)/"" * Carg(2)) * C(2)
+)
+
+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 ".")
+ else
+ return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
+ end
+end
+
+-- print(number.formatted(1))
+-- print(number.formatted(12))
+-- print(number.formatted(123))
+-- print(number.formatted(1234))
+-- print(number.formatted(12345))
+-- print(number.formatted(123456))
+-- print(number.formatted(1234567))
+-- print(number.formatted(12345678))
+-- print(number.formatted(12345678,true))
+-- print(number.formatted(1234.56,"!","?"))
+
+local format_m = function(f)
+ n = n + 1
+ if not f or f == "" then
+ f = ","
+ end
+ return format([[formattednumber(a%s,%q,".")]],n,f)
+end
+
+local format_M = function(f)
+ n = n + 1
+ if not f or f == "" then
+ f = "."
+ end
+ return format([[formattednumber(a%s,%q,",")]],n,f)
+end
+
+--
+
+local format_z = function(f)
+ n = n + (tonumber(f) or 1)
+ return "''" -- okay, not that efficient to append '' but a special case anyway
+end
+
+--
+
+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
+ if f == 0 then
+ return extension
+ elseif f == 1 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
+ local t = { }
+ for i=1,f do
+ n = n + 1
+ t[#t+1] = "a" .. n
+ end
+ return format(extension,unpack(t))
+ end
+end
+
+-- aA b cC d eE f gG hH iI jJ lL mM N o p qQ r sS tT uU wW xX z
+
+-- extensions : %!tag!
+
+local builder = Cs { "start",
+ start = (
+ (
+ P("%") / ""
+ * (
+ V("!") -- new
+ + V("s") + V("q")
+ + V("i") + V("d")
+ + V("f") + V("F") + V("g") + V("G") + V("e") + V("E")
+ + V("x") + V("X") + V("o")
+ --
+ + V("c")
+ + V("C")
+ + V("S") -- new
+ + V("Q") -- new
+ + V("N") -- new
+ --
+ + V("r")
+ + V("h") + V("H") + V("u") + V("U")
+ + V("p") + V("b")
+ + V("t") + V("T")
+ + V("l") + V("L")
+ + V("I")
+ + V("w") -- new
+ + V("W") -- new
+ + V("a") -- new
+ + V("A") -- new
+ + V("j") + V("J") -- stripped e E
+ + V("m") + V("M") -- new
+ + V("z") -- new
+ --
+ -- + V("?") -- ignores probably messed up %
+ )
+ + V("*")
+ )
+ * (P(-1) + Carg(1))
+ )^0,
+ --
+ ["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string)
+ ["q"] = (prefix_any * P("q")) / format_q, -- %q => regular %q (quoted string)
+ ["i"] = (prefix_any * P("i")) / format_i, -- %i => regular %i (integer)
+ ["d"] = (prefix_any * P("d")) / format_d, -- %d => regular %d (integer)
+ ["f"] = (prefix_any * P("f")) / format_f, -- %f => regular %f (float)
+ ["F"] = (prefix_any * P("F")) / format_F, -- %F => regular %f (float) but 0/1 check
+ ["g"] = (prefix_any * P("g")) / format_g, -- %g => regular %g (float)
+ ["G"] = (prefix_any * P("G")) / format_G, -- %G => regular %G (float)
+ ["e"] = (prefix_any * P("e")) / format_e, -- %e => regular %e (float)
+ ["E"] = (prefix_any * P("E")) / format_E, -- %E => regular %E (float)
+ ["x"] = (prefix_any * P("x")) / format_x, -- %x => regular %x (hexadecimal)
+ ["X"] = (prefix_any * P("X")) / format_X, -- %X => regular %X (HEXADECIMAL)
+ ["o"] = (prefix_any * P("o")) / format_o, -- %o => regular %o (octal)
+ --
+ ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring)
+ ["Q"] = (prefix_any * P("Q")) / format_S, -- %Q => %q (tostring)
+ ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros)
+ ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular)
+ ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character
+ --
+ ["r"] = (prefix_any * P("r")) / format_r, -- %r => round
+ ["h"] = (prefix_any * P("h")) / format_h, -- %h => 0x0a1b2 (when - no 0x) was v
+ ["H"] = (prefix_any * P("H")) / format_H, -- %H => 0x0A1B2 (when - no 0x) was V
+ ["u"] = (prefix_any * P("u")) / format_u, -- %u => u+0a1b2 (when - no u+)
+ ["U"] = (prefix_any * P("U")) / format_U, -- %U => U+0A1B2 (when - no U+)
+ ["p"] = (prefix_any * P("p")) / format_p, -- %p => 12.345pt / maybe: P (and more units)
+ ["b"] = (prefix_any * P("b")) / format_b, -- %b => 12.342bp / maybe: B (and more units)
+ ["t"] = (prefix_tab * P("t")) / format_t, -- %t => concat
+ ["T"] = (prefix_tab * P("T")) / format_T, -- %t => sequenced
+ ["l"] = (prefix_any * P("l")) / format_l, -- %l => boolean
+ ["L"] = (prefix_any * P("L")) / format_L, -- %L => BOOLEAN
+ ["I"] = (prefix_any * P("I")) / format_I, -- %I => signed integer
+ --
+ ["w"] = (prefix_any * P("w")) / format_w, -- %w => n spaces (optional prefix is added)
+ ["W"] = (prefix_any * P("W")) / format_W, -- %W => mandate prefix, no specifier
+ --
+ ["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 ,)
+ --
+ ["z"] = (prefix_any * P("z")) / format_z, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,)
+ --
+ ["a"] = (prefix_any * P("a")) / format_a, -- %a => '...' (forces tostring)
+ ["A"] = (prefix_any * P("A")) / format_A, -- %A => "..." (forces tostring)
+ --
+ ["*"] = Cs(((1-P("%"))^1 + P("%%")/"%%")^1) / format_rest, -- rest (including %%)
+ ["?"] = Cs(((1-P("%"))^1 )^1) / format_rest, -- rest (including %%)
+ --
+ ["!"] = Carg(2) * prefix_any * P("!") * C((1-P("!"))^1) * P("!") / format_extension,
+}
+
+-- we can be clever and only alias what is needed
+
+-- local direct = Cs (
+-- P("%")/""
+-- * Cc([[local format = string.format return function(str) return format("%]])
+-- * (S("+- .") + R("09"))^0
+-- * S("sqidfgGeExXo")
+-- * Cc([[",str) end]])
+-- * P(-1)
+-- )
+
+local direct = Cs (
+ P("%")
+ * (S("+- .") + R("09"))^0
+ * S("sqidfgGeExXo")
+ * P(-1) / [[local format = string.format return function(str) return format("%0",str) end]]
+)
+
+local function make(t,str)
+ local f
+ local p
+ local p = lpegmatch(direct,str)
+ if p then
+ -- f = loadstripped(p)()
+ -- print("builder 1 >",p)
+ f = loadstripped(p)()
+ else
+ n = 0
+ -- p = lpegmatch(builder,str,1,"..",t._extensions_) -- after this we know n
+ p = lpegmatch(builder,str,1,t._connector_,t._extensions_) -- after this we know n
+ if n > 0 then
+ p = format(template,preamble,t._preamble_,arguments[n],p)
+ -- print("builder 2 >",p)
+ f = loadstripped(p,t._environment_)() -- t._environment is not populated (was experiment)
+ else
+ f = function() return str end
+ end
+ end
+ t[str] = f
+ return f
+end
+
+-- -- collect periodically
+--
+-- local threshold = 1000 -- max nof cached formats
+--
+-- local function make(t,str)
+-- local f = rawget(t,str)
+-- if f then
+-- return f
+-- end
+-- local parent = t._t_
+-- if parent._n_ > threshold then
+-- local m = { _t_ = parent }
+-- getmetatable(parent).__index = m
+-- setmetatable(m, { __index = make })
+-- else
+-- parent._n_ = parent._n_ + 1
+-- end
+-- local f
+-- local p = lpegmatch(direct,str)
+-- if p then
+-- f = loadstripped(p)()
+-- else
+-- n = 0
+-- p = lpegmatch(builder,str,1,"..",parent._extensions_) -- after this we know n
+-- if n > 0 then
+-- p = format(template,preamble,parent._preamble_,arguments[n],p)
+-- -- print("builder>",p)
+-- f = loadstripped(p)()
+-- else
+-- f = function() return str end
+-- end
+-- end
+-- t[str] = f
+-- return f
+-- end
+
+local function use(t,fmt,...)
+ return t[fmt](...)
+end
+
+strings.formatters = { }
+
+-- we cannot make these tables weak, unless we start using an indirect
+-- table (metatable) in which case we could better keep a count and
+-- clear that table when a threshold is reached
+
+-- _connector_ is an experiment
+
+if _LUAVERSION < 5.2 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
+ 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
+
+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
+string.formatter = function(str,...) return formatters[str](...) end -- sometimes nicer name
+
+local function add(t,name,template,preamble)
+ if type(t) == "table" and t._type_ == "formatter" then
+ t._extensions_[name] = template or "%s"
+ if type(preamble) == "string" then
+ t._preamble_ = preamble .. "\n" .. t._preamble_ -- so no overload !
+ elseif type(preamble) == "table" then
+ for k, v in next, preamble do
+ t._environment_[k] = v
+ end
+ end
+ end
+end
+
+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.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)
+
+-- 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]])
+
+if _LUAVERSION < 5.2 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
+
+-- -- yes or no:
+--
+-- local function make(t,str)
+-- local f
+-- local p = lpegmatch(direct,str)
+-- if p then
+-- f = loadstripped(p)()
+-- else
+-- n = 0
+-- p = lpegmatch(builder,str,1,",") -- after this we know n
+-- if n > 0 then
+-- p = format(template,template_shortcuts,arguments[n],p)
+-- f = loadstripped(p)()
+-- else
+-- f = function() return str end
+-- end
+-- end
+-- t[str] = f
+-- return f
+-- end
+--
+-- local formatteds = string.formatteds or { }
+-- string.formatteds = formatteds
+--
+-- setmetatable(formatteds, { __index = make, __call = use })
+
+-- This is a somewhat silly one used in commandline reconstruction but the older
+-- method, using a combination of fine, gsub, quoted and unquoted was not that
+-- reliable.
+--
+-- '"foo"bar \"and " whatever"' => "foo\"bar \"and \" whatever"
+-- 'foo"bar \"and " whatever' => "foo\"bar \"and \" whatever"
+
+local dquote = patterns.dquote -- P('"')
+local equote = patterns.escaped + dquote / '\\"' + 1
+local space = patterns.space
+local cquote = Cc('"')
+
+local pattern =
+ Cs(dquote * (equote - P(-2))^0 * dquote) -- we keep the outer but escape unescaped ones
+ + Cs(cquote * (equote - space)^0 * space * equote^0 * cquote) -- we escape unescaped ones
+
+function string.optionalquoted(str)
+ return lpegmatch(pattern,str) or str
+end
+
+local pattern = Cs((newline / (os.newline or "\r") + 1)^0)
+
+function string.replacenewlines(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua b/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua
new file mode 100644
index 00000000000..a6239adf409
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua
@@ -0,0 +1,837 @@
+if not modules then modules = { } end modules ['util-tab'] = {
+ 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"
+}
+
+utilities = utilities or {}
+utilities.tables = utilities.tables or { }
+local tables = utilities.tables
+
+local format, gmatch, gsub, sub = string.format, string.gmatch, string.gsub, string.sub
+local concat, insert, remove, sort = table.concat, table.insert, table.remove, table.sort
+local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select
+local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc
+local sortedkeys, sortedpairs = table.sortedkeys, table.sortedpairs
+local formatters = string.formatters
+local utftoeight = utf.toeight
+
+local splitter = lpeg.tsplitat(".")
+
+function utilities.tables.definetable(target,nofirst,nolast) -- defines undefined tables
+ local composed, t = nil, { }
+ local snippets = lpegmatch(splitter,target)
+ for i=1,#snippets - (nolast and 1 or 0) do
+ local name = snippets[i]
+ if composed then
+ composed = composed .. "." .. name
+ t[#t+1] = formatters["if not %s then %s = { } end"](composed,composed)
+ else
+ composed = name
+ if not nofirst then
+ t[#t+1] = formatters["%s = %s or { }"](composed,composed)
+ end
+ end
+ end
+ if composed then
+ if nolast then
+ composed = composed .. "." .. snippets[#snippets]
+ end
+ return concat(t,"\n"), composed -- could be shortcut
+ else
+ return "", target
+ end
+end
+
+-- local t = tables.definedtable("a","b","c","d")
+
+function tables.definedtable(...)
+ local t = _G
+ for i=1,select("#",...) do
+ local li = select(i,...)
+ local tl = t[li]
+ if not tl then
+ tl = { }
+ t[li] = tl
+ end
+ t = tl
+ end
+ return t
+end
+
+function tables.accesstable(target,root)
+ local t = root or _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ return t
+end
+
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = lpegmatch(splitter,target)
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
+function tables.removevalue(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
+end
+
+function tables.replacevalue(t,oldvalue,newvalue)
+ if oldvalue and newvalue then
+ for i=1,#t do
+ if t[i] == oldvalue then
+ t[i] = newvalue
+ -- replace all, so no: return
+ end
+ end
+ end
+end
+
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+
+-- experimental
+
+local escape = Cs(Cc('"') * ((P('"')/'""' + P(1))^0) * Cc('"'))
+
+function table.tocsv(t,specification)
+ if t and #t > 0 then
+ local result = { }
+ local r = { }
+ specification = specification or { }
+ local fields = specification.fields
+ if type(fields) ~= "string" then
+ fields = sortedkeys(t[1])
+ end
+ local separator = specification.separator or ","
+ if specification.preamble == true then
+ for f=1,#fields do
+ r[f] = lpegmatch(escape,tostring(fields[f]))
+ end
+ result[1] = concat(r,separator)
+ end
+ for i=1,#t do
+ local ti = t[i]
+ for f=1,#fields do
+ local field = ti[fields[f]]
+ if type(field) == "string" then
+ r[f] = lpegmatch(escape,field)
+ else
+ r[f] = tostring(field)
+ end
+ end
+ result[#result+1] = concat(r,separator)
+ end
+ return concat(result,"\n")
+ else
+ return ""
+ end
+end
+
+-- local nspaces = utilities.strings.newrepeater(" ")
+-- local escape = Cs((P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;" + P(1))^0)
+--
+-- local function toxml(t,d,result,step)
+-- for k, v in sortedpairs(t) do
+-- local s = nspaces[d]
+-- local tk = type(k)
+-- local tv = type(v)
+-- if tv == "table" then
+-- if tk == "number" then
+-- result[#result+1] = format("%s<entry n='%s'>",s,k)
+-- toxml(v,d+step,result,step)
+-- result[#result+1] = format("%s</entry>",s,k)
+-- else
+-- result[#result+1] = format("%s<%s>",s,k)
+-- toxml(v,d+step,result,step)
+-- result[#result+1] = format("%s</%s>",s,k)
+-- end
+-- elseif tv == "string" then
+-- if tk == "number" then
+-- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,lpegmatch(escape,v),k)
+-- else
+-- result[#result+1] = format("%s<%s>%s</%s>",s,k,lpegmatch(escape,v),k)
+-- end
+-- elseif tk == "number" then
+-- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,tostring(v),k)
+-- else
+-- result[#result+1] = format("%s<%s>%s</%s>",s,k,tostring(v),k)
+-- end
+-- end
+-- end
+--
+-- much faster
+
+local nspaces = utilities.strings.newrepeater(" ")
+
+local function toxml(t,d,result,step)
+ for k, v in sortedpairs(t) do
+ local s = nspaces[d] -- inlining this is somewhat faster but gives more formatters
+ local tk = type(k)
+ local tv = type(v)
+ if tv == "table" then
+ if tk == "number" then
+ result[#result+1] = formatters["%s<entry n='%s'>"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1] = formatters["%s</entry>"](s,k)
+ else
+ result[#result+1] = formatters["%s<%s>"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1] = formatters["%s</%s>"](s,k)
+ end
+ elseif tv == "string" then
+ if tk == "number" then
+ result[#result+1] = formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k)
+ else
+ result[#result+1] = formatters["%s<%s>%!xml!</%s>"](s,k,v,k)
+ end
+ elseif tk == "number" then
+ result[#result+1] = formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k)
+ else
+ result[#result+1] = formatters["%s<%s>%S</%s>"](s,k,v,k)
+ end
+ end
+end
+
+-- function table.toxml(t,name,nobanner,indent,spaces)
+-- local noroot = name == false
+-- local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+-- local indent = rep(" ",indent or 0)
+-- local spaces = rep(" ",spaces or 1)
+-- if noroot then
+-- toxml( t, inndent, result, spaces)
+-- else
+-- toxml( { [name or "root"] = t }, indent, result, spaces)
+-- end
+-- return concat(result,"\n")
+-- end
+
+function table.toxml(t,specification)
+ specification = specification or { }
+ local name = specification.name
+ local noroot = name == false
+ local result = (specification.nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = specification.indent or 0
+ local spaces = specification.spaces or 1
+ if noroot then
+ toxml( t, indent, result, spaces)
+ else
+ toxml( { [name or "data"] = t }, indent, result, spaces)
+ end
+ return concat(result,"\n")
+end
+
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
+-- best keep [%q] keys (as we have some in older applications i.e. saving user data
+
+local f_hashed_string = formatters["[%q]=%q,"]
+local f_hashed_number = formatters["[%q]=%s,"]
+local f_hashed_boolean = formatters["[%q]=%l,"]
+local f_hashed_table = formatters["[%q]="]
+
+local f_indexed_string = formatters["[%s]=%q,"]
+local f_indexed_number = formatters["[%s]=%s,"]
+local f_indexed_boolean = formatters["[%s]=%l,"]
+local f_indexed_table = formatters["[%s]="]
+
+local f_ordered_string = formatters["%q,"]
+local f_ordered_number = formatters["%s,"]
+local f_ordered_boolean = formatters["%l,"]
+
+function table.fastserialize(t,prefix)
+
+ -- prefix should contain the =
+ -- not sorted
+ -- only number and string indices (currently)
+
+ local r = { type(prefix) == "string" and prefix or "return" }
+ local m = 1
+
+ local function fastserialize(t,outer) -- no mixes
+ local n = #t
+ m = m + 1
+ r[m] = "{"
+ if n > 0 then
+ for i=0,n do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "string" then
+ m = m + 1 r[m] = f_ordered_string(v)
+ elseif tv == "number" then
+ m = m + 1 r[m] = f_ordered_number(v)
+ elseif tv == "table" then
+ fastserialize(v)
+ elseif tv == "boolean" then
+ m = m + 1 r[m] = f_ordered_boolean(v)
+ end
+ end
+ end
+ for k, v in next, t do
+ local tk = type(k)
+ if tk == "number" then
+ if k > n or k < 0 then
+ local tv = type(v)
+ if tv == "string" then
+ m = m + 1 r[m] = f_indexed_string(k,v)
+ elseif tv == "number" then
+ m = m + 1 r[m] = f_indexed_number(k,v)
+ elseif tv == "table" then
+ m = m + 1 r[m] = f_indexed_table(k)
+ fastserialize(v)
+ elseif tv == "boolean" then
+ m = m + 1 r[m] = f_indexed_boolean(k,v)
+ end
+ end
+ else
+ local tv = type(v)
+ if tv == "string" then
+ m = m + 1 r[m] = f_hashed_string(k,v)
+ elseif tv == "number" then
+ m = m + 1 r[m] = f_hashed_number(k,v)
+ elseif tv == "table" then
+ m = m + 1 r[m] = f_hashed_table(k)
+ fastserialize(v)
+ elseif tv == "boolean" then
+ m = m + 1 r[m] = f_hashed_boolean(k,v)
+ end
+ end
+ end
+ m = m + 1
+ if outer then
+ r[m] = "}"
+ else
+ r[m] = "},"
+ end
+ return r
+ end
+ return concat(fastserialize(t,true))
+end
+
+function table.deserialize(str)
+ if not str or str == "" then
+ return
+ end
+ local code = load(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
+end
+
+-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+
+function table.load(filename,loader)
+ if filename then
+ local t = (loader or io.loaddata)(filename)
+ if t and t ~= "" then
+ local t = utftoeight(t)
+ t = load(t)
+ if type(t) == "function" then
+ t = t()
+ if type(t) == "table" then
+ return t
+ end
+ end
+ end
+ end
+end
+
+function table.save(filename,t,n,...)
+ io.savedata(filename,table.serialize(t,n == nil and true or n,...)) -- no frozen table.serialize
+end
+
+local f_key_value = formatters["%s=%q"]
+local f_add_table = formatters[" {%t},\n"]
+local f_return_table = formatters["return {\n%t}"]
+
+local function slowdrop(t) -- maybe less memory (intermediate concat)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = f_key_value(k,v)
+ end
+ r[i] = f_add_table(l)
+ end
+ return f_return_table(r)
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ local m = 1
+ for i=1,#t do
+ local ti = t[i]
+ m = m + 1 r[m] = " {"
+ for k, v in next, ti do
+ m = m + 1 r[m] = f_key_value(k,v)
+ end
+ m = m + 1 r[m] = "},\n"
+ end
+ m = m + 1
+ r[m] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow) -- only { { a=2 }, {a=3} } -- for special cases
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
+-- inspect(table.drop({ { a=2 }, {a=3} }))
+-- inspect(table.drop({ { a=2 }, {a=3} },true))
+
+function table.autokey(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end
+
+local selfmapper = { __index = function(t,k) t[k] = k return k end }
+
+function table.twowaymapper(t)
+ if not t then
+ t = { }
+ else
+ for i=0,#t do
+ local ti = t[i] -- t[1] = "one"
+ if ti then
+ local i = tostring(i)
+ t[i] = ti -- t["1"] = "one"
+ t[ti] = i -- t["one"] = "1"
+ end
+ end
+ t[""] = t[0] or ""
+ end
+ -- setmetatableindex(t,"key")
+ setmetatable(t,selfmapper)
+ return t
+end
+
+-- The next version is somewhat faster, although in practice one will seldom
+-- serialize a lot using this one. Often the above variants are more efficient.
+-- If we would really need this a lot, we could hash q keys, or just not used
+-- indented code.
+
+-- char-def.lua : 0.53 -> 0.38
+-- husayni.tma : 0.28 -> 0.19
+
+local f_start_key_idx = formatters["%w{"]
+local f_start_key_num = formatters["%w[%s]={"]
+local f_start_key_str = formatters["%w[%q]={"]
+local f_start_key_boo = formatters["%w[%l]={"]
+local f_start_key_nop = formatters["%w{"]
+
+local f_stop = formatters["%w},"]
+
+local f_key_num_value_num = formatters["%w[%s]=%s,"]
+local f_key_str_value_num = formatters["%w[%q]=%s,"]
+local f_key_boo_value_num = formatters["%w[%l]=%s,"]
+
+local f_key_num_value_str = formatters["%w[%s]=%q,"]
+local f_key_str_value_str = formatters["%w[%q]=%q,"]
+local f_key_boo_value_str = formatters["%w[%l]=%q,"]
+
+local f_key_num_value_boo = formatters["%w[%s]=%l,"]
+local f_key_str_value_boo = formatters["%w[%q]=%l,"]
+local f_key_boo_value_boo = formatters["%w[%l]=%l,"]
+
+local f_key_num_value_not = formatters["%w[%s]={},"]
+local f_key_str_value_not = formatters["%w[%q]={},"]
+local f_key_boo_value_not = formatters["%w[%l]={},"]
+
+local f_key_num_value_seq = formatters["%w[%s]={ %, t },"]
+local f_key_str_value_seq = formatters["%w[%q]={ %, t },"]
+local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"]
+
+local f_val_num = formatters["%w%s,"]
+local f_val_str = formatters["%w%q,"]
+local f_val_boo = formatters["%w%l,"]
+local f_val_not = formatters["%w{},"]
+local f_val_seq = formatters["%w{ %, t },"]
+local f_fin_seq = formatters[" %, t }"]
+
+local f_table_return = formatters["return {"]
+local f_table_name = formatters["%s={"]
+local f_table_direct = formatters["{"]
+local f_table_entry = formatters["[%q]={"]
+local f_table_finish = formatters["}"]
+
+----- f_string = formatters["%q"]
+
+local spaces = utilities.strings.newrepeater(" ")
+
+local original_serialize = table.serialize -- the extensive one, the one we started with
+
+-- there is still room for optimization: index run, key run, but i need to check with the
+-- latest lua for the value of #n (with holes) .. anyway for tracing purposes we want
+-- indices / keys being sorted, so it will never be real fast
+
+local function serialize(root,name,specification)
+
+ if type(specification) == "table" then
+ return original_serialize(root,name,specification) -- the original one
+ end
+
+ local t -- = { }
+ local n = 1
+ local unknown = false
+
+-- local function simple_table(t)
+-- local ts = #t
+-- if ts > 0 then
+-- local n = 0
+-- for _, v in next, t do
+-- n = n + 1
+-- if type(v) == "table" then
+-- return nil
+-- end
+-- end
+-- if n == ts then
+-- local tt = { }
+-- local nt = 0
+-- for i=1,ts do
+-- local v = t[i]
+-- local tv = type(v)
+-- nt = nt + 1
+-- if tv == "number" then
+-- tt[nt] = v
+-- elseif tv == "string" then
+-- tt[nt] = format("%q",v) -- f_string(v)
+-- elseif tv == "boolean" then
+-- tt[nt] = v and "true" or "false"
+-- else
+-- return nil
+-- end
+-- end
+-- return tt
+-- end
+-- end
+-- return nil
+-- end
+
+ local function simple_table(t)
+ local nt = #t
+ if nt > 0 then
+ local n = 0
+ for _, v in next, t do
+ n = n + 1
+ if type(v) == "table" then
+ return nil
+ end
+ end
+ local haszero = t[0]
+ if n == nt then
+ local tt = { }
+ for i=1,nt do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ tt[i] = v -- not needed tostring(v)
+ elseif tv == "string" then
+ tt[i] = format("%q",v) -- f_string(v)
+ elseif tv == "boolean" then
+ tt[i] = v and "true" or "false"
+ else
+ return nil
+ end
+ end
+ return tt
+ elseif haszero and (n == nt + 1) then
+ local tt = { }
+ for i=0,nt do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ tt[i+1] = v -- not needed tostring(v)
+ elseif tv == "string" then
+ tt[i+1] = format("%q",v) -- f_string(v)
+ elseif tv == "boolean" then
+ tt[i+1] = v and "true" or "false"
+ else
+ return nil
+ end
+ end
+ tt[1] = "[0] = " .. tt[1]
+ return tt
+ end
+ end
+ return nil
+ end
+
+ local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ n = n + 1
+ if indexed then
+ t[n] = f_start_key_idx(depth)
+ else
+ local tn = type(name)
+ if tn == "number" then
+ t[n] = f_start_key_num(depth,name)
+ elseif tn == "string" then
+ t[n] = f_start_key_str(depth,name)
+ elseif tn == "boolean" then
+ t[n] = f_start_key_boo(depth,name)
+ else
+ t[n] = f_start_key_nop(depth)
+ end
+ end
+ depth = depth + 1
+ end
+ -- we could check for k (index) being number (cardinal)
+ if root and next(root) ~= nil then
+ local first = nil
+ local last = 0
+ last = #root
+ for k=1,last do
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
+ end
+ local sk = sortedkeys(root) -- inline fast version?\
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ local tv = type(v)
+ local tk = type(k)
+ if first and tk == "number" and k <= last and k >= first then
+ if tv == "number" then
+ n = n + 1 t[n] = f_val_num(depth,v)
+ elseif tv == "string" then
+ n = n + 1 t[n] = f_val_str(depth,v)
+ elseif tv == "table" then
+ if next(v) == nil then -- tricky as next is unpredictable in a hash
+ n = n + 1 t[n] = f_val_not(depth)
+ else
+ local st = simple_table(v)
+ if st then
+ n = n + 1 t[n] = f_val_seq(depth,st)
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ end
+ elseif tv == "boolean" then
+ n = n + 1 t[n] = f_val_boo(depth,v)
+ elseif unknown then
+ n = n + 1 t[n] = f_val_str(depth,tostring(v))
+ end
+ elseif tv == "number" then
+ if tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_num(depth,k,v)
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_num(depth,k,v)
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_num(depth,k,v)
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_num(depth,tostring(k),v)
+ end
+ elseif tv == "string" then
+ if tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_str(depth,k,v)
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_str(depth,k,v)
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_str(depth,k,v)
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_str(depth,tostring(k),v)
+ end
+ elseif tv == "table" then
+ if next(v) == nil then
+ if tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_not(depth,k)
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_not(depth,k)
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_not(depth,k)
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_not(depth,tostring(k))
+ end
+ else
+ local st = simple_table(v)
+ if not st then
+ do_serialize(v,k,depth,level+1)
+ elseif tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_seq(depth,k,st)
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_seq(depth,k,st)
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_seq(depth,k,st)
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_seq(depth,tostring(k),st)
+ end
+ end
+ elseif tv == "boolean" then
+ if tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_boo(depth,k,v)
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_boo(depth,k,v)
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_boo(depth,k,v)
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_boo(depth,tostring(k),v)
+ end
+ else
+ if tk == "number" then
+ n = n + 1 t[n] = f_key_num_value_str(depth,k,tostring(v))
+ elseif tk == "string" then
+ n = n + 1 t[n] = f_key_str_value_str(depth,k,tostring(v))
+ elseif tk == "boolean" then
+ n = n + 1 t[n] = f_key_boo_value_str(depth,k,tostring(v))
+ elseif unknown then
+ n = n + 1 t[n] = f_key_str_value_str(depth,tostring(k),tostring(v))
+ end
+ end
+ end
+ end
+ if level > 0 then
+ n = n + 1 t[n] = f_stop(depth-1)
+ end
+ end
+
+ local tname = type(name)
+
+ if tname == "string" then
+ if name == "return" then
+ t = { f_table_return() }
+ else
+ t = { f_table_name(name) }
+ end
+ elseif tname == "number" then
+ t = { f_table_entry(name) }
+ elseif tname == "boolean" then
+ if name then
+ t = { f_table_return() }
+ else
+ t = { f_table_direct() }
+ end
+ else
+ t = { f_table_name("t") }
+ end
+
+ if root then
+ -- The dummy access will initialize a table that has a delayed initialization
+ -- using a metatable. (maybe explicitly test for metatable)
+ if getmetatable(root) then -- todo: make this an option, maybe even per subtable
+ local dummy = root._w_h_a_t_e_v_e_r_
+ root._w_h_a_t_e_v_e_r_ = nil
+ end
+ -- Let's forget about empty tables.
+ if next(root) ~= nil then
+ local st = simple_table(root)
+ if st then
+ return t[1] .. f_fin_seq(st) -- todo: move up and in one go
+ else
+ do_serialize(root,name,1,0)
+ end
+ end
+ end
+ n = n + 1
+ t[n] = f_table_finish()
+ return concat(t,"\n")
+end
+
+table.serialize = serialize
+
+if setinspector then
+ setinspector("table",function(v) if type(v) == "table" then print(serialize(v,"table",{})) return true end end)
+end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-tpl.lua b/Master/texmf-dist/tex/context/base/mkiv/util-tpl.lua
new file mode 100644
index 00000000000..468dd429c98
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-tpl.lua
@@ -0,0 +1,213 @@
+if not modules then modules = { } end modules ['util-tpl'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code. Coming from dos and windows, I've always used %whatever%
+-- as template variables so let's stick to it. After all, it's easy to parse and stands
+-- out well. A double %% is turned into a regular %.
+
+utilities.templates = utilities.templates or { }
+local templates = utilities.templates
+
+local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end)
+local report_template = logs.reporter("template")
+
+local tostring = tostring
+local format, sub, byte = string.format, string.sub, string.byte
+local P, C, R, Cs, Cc, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match, lpeg.patterns
+
+-- todo: make installable template.new
+
+local replacer
+
+local function replacekey(k,t,how,recursive)
+ local v = t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %a",k)
+ end
+ return ""
+ else
+ v = tostring(v)
+ if trace_template then
+ report_template("setting key %a to value %a",k,v)
+ end
+ if recursive then
+ return lpegmatch(replacer,v,1,t,how,recursive)
+ else
+ return v
+ end
+ end
+end
+
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local sqlquoted = Cs(Cc("'") * sqlescape * Cc("'"))
+
+lpegpatterns.sqlescape = sqlescape
+lpegpatterns.sqlquoted = sqlquoted
+
+-- escapeset : \0\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\"\\\127
+-- test string: [[1\0\31test23"\\]] .. string.char(19) .. "23"
+--
+-- slow:
+--
+-- local luaescape = lpeg.replacer {
+-- { '"', [[\"]] },
+-- { '\\', [[\\]] },
+-- { R("\0\9") * #R("09"), function(s) return "\\00" .. byte(s) end },
+-- { R("\10\31") * #R("09"), function(s) return "\\0" .. byte(s) end },
+-- { R("\0\31") , function(s) return "\\" .. byte(s) end },
+-- }
+--
+-- slightly faster:
+
+-- local luaescape = Cs ((
+-- P('"' ) / [[\"]] +
+-- P('\\') / [[\\]] +
+-- Cc("\\00") * (R("\0\9") / byte) * #R("09") +
+-- Cc("\\0") * (R("\10\31") / byte) * #R("09") +
+-- Cc("\\") * (R("\0\31") / byte) +
+-- P(1)
+-- )^0)
+
+----- xmlescape = lpegpatterns.xmlescape
+----- texescape = lpegpatterns.texescape
+local luaescape = lpegpatterns.luaescape
+----- sqlquoted = lpegpatterns.sqlquoted
+----- luaquoted = lpegpatterns.luaquoted
+
+local escapers = {
+ lua = function(s)
+ -- return sub(format("%q",s),2,-2)
+ return lpegmatch(luaescape,s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local quotedescapers = {
+ lua = function(s)
+ -- return lpegmatch(luaquoted,s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlquoted,s)
+ end,
+}
+
+local luaescaper = escapers.lua
+local quotedluaescaper = quotedescapers.lua
+
+local function replacekeyunquoted(s,t,how,recurse) -- ".. \" "
+ if how == false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper = how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
+end
+
+local function replacekeyquoted(s,t,how,recurse) -- ".. \" "
+ if how == false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper = how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
+end
+
+local function replaceoptional(l,m,r,t,how,recurse)
+ local v = t[l]
+ return v and v ~= "" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
+end
+
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s
+local rquoted = P("]%") --
+local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s
+local rquotedq = P(")%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+local nolquotedq = lquotedq / ''
+local norquotedq = rquotedq / ''
+
+local noloptional = P("%?") / ''
+local noroptional = P("?%") / ''
+local nomoptional = P(":") / ''
+
+
+local args = Carg(1) * Carg(2) * Carg(3)
+local key = nosingle * ((C((1-nosingle )^1) * args) / replacekey ) * nosingle
+local quoted = nolquotedq * ((C((1-norquotedq )^1) * args) / replacekeyquoted ) * norquotedq
+local unquoted = nolquoted * ((C((1-norquoted )^1) * args) / replacekeyunquoted) * norquoted
+local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional
+local any = P(1)
+
+ replacer = Cs((unquoted + quoted + escape + optional + key + any)^0)
+
+local function replace(str,mapping,how,recurse)
+ if mapping and str then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = true }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]], y = "oeps" },'sql'))
+-- print(replace("test '%[x]%' test",{ x = [[a '%y%'  a]], y = "oeps" },'sql',true))
+-- print(replace([[test %[x]% test]],{ x = [[a "x"  a]]}))
+-- print(replace([[test %(x)% test]],{ x = [[a "x"  a]]}))
+-- print(replace([[convert %?x: -x "%x%" ?% %?y: -y "%y%" ?%]],{ x = "yes" }))
+
+templates.replace = replace
+
+function templates.replacer(str,how,recurse) -- reads nicer
+ return function(mapping)
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ end
+end
+
+-- local cmd = templates.replacer([[foo %bar%]]) print(cmd { bar = "foo" })
+
+function templates.load(filename,mapping,how,recurse)
+ local data = io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping = t
+ end
+ for k, v in next, t do
+ t[k] = replace(v,mapping,how,recurse)
+ end
+ return t
+end
+
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" }))
+-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" }))
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" },false,true))
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" },false))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-you.lua b/Master/texmf-dist/tex/context/base/mkiv/util-you.lua
new file mode 100644
index 00000000000..79a0e83e781
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-you.lua
@@ -0,0 +1,256 @@
+if not modules then modules = { } end modules ['util-you'] = {
+ version = 1.002,
+ comment = "library for fetching data from youless kwh meter polling device",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE",
+ license = "see context related readme files"
+}
+
+-- See mtx-youless.lua and s-youless.mkiv for examples of usage.
+--
+-- todo: already calculate min, max and average per hour and discard
+-- older data, or maybe a condense option
+--
+-- maybe just a special parser but who cares about speed here
+--
+-- curl -c pw.txt http://192.168.2.50/L?w=pwd
+-- curl -b pw.txt http://192.168.2.50/V?...
+--
+-- the socket library barks on an (indeed) invalid header ... unfortunately we cannot
+-- pass a password with each request ... although the youless is a rather nice gadget,
+-- the weak part is in the http polling
+
+require("util-jsn")
+
+-- the library variant:
+
+utilities = utilities or { }
+local youless = { }
+utilities.youless = youless
+
+local lpegmatch = lpeg.match
+local formatters = string.formatters
+
+-- dofile("http.lua")
+
+local http = socket.http
+
+local f_normal = formatters["http://%s/V?%s=%i&f=j"]
+local f_password = formatters["http://%s/L?w=%s"]
+
+local function fetch(url,password,what,i)
+ local url = f_normal(url,what,i)
+ local data, h = http.request(url)
+ local result = data and utilities.json.tolua(data)
+ return result
+end
+
+-- "123" " 1,234"
+
+local tovalue = lpeg.Cs((lpeg.R("09") + lpeg.P(1)/"")^1) / tonumber
+
+-- "2013-11-12T06:40:00"
+
+local totime = (lpeg.C(4) / tonumber) * lpeg.P("-")
+ * (lpeg.C(2) / tonumber) * lpeg.P("-")
+ * (lpeg.C(2) / tonumber) * lpeg.P("T")
+ * (lpeg.C(2) / tonumber) * lpeg.P(":")
+ * (lpeg.C(2) / tonumber) * lpeg.P(":")
+ * (lpeg.C(2) / tonumber)
+
+local function get(url,password,what,i,data,average,variant)
+ if not data then
+ data = { }
+ end
+ while true do
+ local d = fetch(url,password,what,i)
+ if d and next(d) then
+ local c_year, c_month, c_day, c_hour, c_minute, c_seconds = lpegmatch(totime,d.tm)
+ if c_year and c_seconds then
+ local delta = tonumber(d.dt)
+ local tnum = os.time { year = c_year, month = c_month, day = c_day, hour = c_hour, minute = c_minute }
+ local v = d.val
+ for i=1,#v do
+ local newvalue = lpegmatch(tovalue,v[i])
+ if newvalue then
+ local t = tnum + (i-1)*delta
+ local current = os.date("%Y-%m-%dT%H:%M:%S",t)
+ local c_year, c_month, c_day, c_hour, c_minute, c_seconds = lpegmatch(totime,current)
+ if c_year and c_seconds then
+ local years = data.years if not years then years = { } data.years = years end
+ local d_year = years[c_year] if not d_year then d_year = { } years[c_year] = d_year end
+ local months = d_year.months if not months then months = { } d_year.months = months end
+ local d_month = months[c_month] if not d_month then d_month = { } months[c_month] = d_month end
+ local days = d_month.days if not days then days = { } d_month.days = days end
+ local d_day = days[c_day] if not d_day then d_day = { } days[c_day] = d_day end
+ if average then
+ d_day.average = newvalue
+ else
+ local hours = d_day.hours if not hours then hours = { } d_day.hours = hours end
+ local d_hour = hours[c_hour] if not d_hour then d_hour = { } hours[c_hour] = d_hour end
+ d_hour[c_minute] = newvalue
+ end
+ end
+ end
+ end
+ end
+ else
+ return data
+ end
+ i = i + 1
+ end
+ return data
+end
+
+-- day of month (kwh)
+-- url = http://192.168.1.14/V?m=2
+-- m = the number of month (jan = 1, feb = 2, ..., dec = 12)
+
+-- hour of day (watt)
+-- url = http://192.168.1.14/V?d=1
+-- d = the number of days ago (today = 0, yesterday = 1, etc.)
+
+-- 10 minutes (watt)
+-- url = http://192.168.1.14/V?w=1
+-- w = 1 for the interval now till 8 hours ago.
+-- w = 2 for the interval 8 till 16 hours ago.
+-- w = 3 for the interval 16 till 24 hours ago.
+
+-- 1 minute (watt)
+-- url = http://192.168.1.14/V?h=1
+-- h = 1 for the interval now till 30 minutes ago.
+-- h = 2 for the interval 30 till 60 minutes ago
+
+function youless.collect(specification)
+ if type(specification) ~= "table" then
+ return
+ end
+ local host = specification.host or ""
+ local data = specification.data or { }
+ local filename = specification.filename or ""
+ local variant = specification.variant or "kwh"
+ local detail = specification.detail or false
+ local nobackup = specification.nobackup or false
+ local password = specification.password or ""
+ if host == "" then
+ return
+ end
+ if filename == "" then
+ return
+ else
+ data = table.load(filename) or data
+ end
+ if variant == "kwh" then
+ get(host,password,"m",1,data,true)
+ elseif variant == "watt" then
+ get(host,password,"d",0,data,true)
+ get(host,password,"w",1,data)
+ if detail then
+ get(host,password,"h",1,data) -- todo: get this for calculating the precise max
+ end
+ else
+ return
+ end
+ local path = file.dirname(filename)
+ local base = file.basename(filename)
+ data.variant = variant
+ data.host = host
+ data.updated = os.now()
+ if nobackup then
+ -- saved but with checking
+ local tempname = file.join(path,"youless.tmp")
+ table.save(tempname,data)
+ local check = table.load(tempname)
+ if type(check) == "table" then
+ local keepname = file.replacesuffix(filename,"old")
+ os.remove(keepname)
+ if not lfs.isfile(keepname) then
+ os.rename(filename,keepname)
+ os.rename(tempname,filename)
+ end
+ end
+ else
+ local keepname = file.join(path,formatters["%s-%s"](os.date("%Y-%m-%d-%H-%M-%S",os.time()),base))
+ os.rename(filename,keepname)
+ if not lfs.isfile(filename) then
+ table.save(filename,data)
+ end
+ end
+ return data
+end
+
+-- local data = youless.collect {
+-- host = "192.168.2.50",
+-- variant = "watt",
+-- filename = "youless-watt.lua"
+-- }
+
+-- inspect(data)
+
+-- local data = youless.collect {
+-- host = "192.168.2.50",
+-- variant = "kwh",
+-- filename = "youless-kwh.lua"
+-- }
+
+-- inspect(data)
+
+function youless.analyze(data)
+ if data and data.variant == "watt" and data.years then
+ for y, year in next, data.years do
+ local a_year, n_year, m_year = 0, 0, 0
+ if year.months then
+ for m, month in next, year.months do
+ local a_month, n_month = 0, 0
+ if month.days then
+ for d, day in next, month.days do
+ local a_day, n_day = 0, 0
+ if day.hours then
+ for h, hour in next, day.hours do
+ local a_hour, n_hour, m_hour = 0, 0, 0
+ for k, v in next, hour do
+ if type(k) == "number" then
+ a_hour = a_hour + v
+ n_hour = n_hour + 1
+ if v > m_hour then
+ m_hour = v
+ end
+ end
+ end
+ n_day = n_day + n_hour
+ a_day = a_day + a_hour
+ hour.maxwatt = m_hour
+ hour.watt = a_hour / n_hour
+ if m_hour > m_year then
+ m_year = m_hour
+ end
+ end
+ end
+ if n_day > 0 then
+ a_month = a_month + a_day
+ n_month = n_month + n_day
+ day.watt = a_day / n_day
+ else
+ day.watt = 0
+ end
+ end
+ end
+ if n_month > 0 then
+ a_year = a_year + a_month
+ n_year = n_year + n_month
+ month.watt = a_month / n_month
+ else
+ month.watt = 0
+ end
+ end
+ end
+ if n_year > 0 then
+ year.watt = a_year / n_year
+ year.maxwatt = m_year
+ else
+ year.watt = 0
+ year.maxwatt = 0
+ end
+ end
+ end
+end